Compare commits

...

2 Commits

4 changed files with 79 additions and 21552 deletions

View File

@@ -54,11 +54,11 @@ Skills compose by adoption-list order (`10123`) and trigger tags carry runtime e
Didactyl will support local inference, which is very privacy preserving. Remote inference does however have it's advantages, and in those cases Didactyl supports using Bitcoin Lightning and eCash inference providers.
## Current Status — v0.2.5
## Current Status — v0.2.7
**Active build — this project is barely working. Experiment at your own risk.**
> Last release update: v0.2.5 — Fix increment_and_push upstream auto-setup and finalize SIGINT shutdown fix
> Last release update: v0.2.7 — Fix default_admin_dm inline variable resolution for my_kind0_profile and my_npub
- Connects to configured relays with auto-reconnect and relay state transition logging
- Publishes configured startup events per relay as each relay becomes connected

File diff suppressed because it is too large Load Diff

View File

@@ -15,6 +15,7 @@
#include "nostr_handler.h"
#include "trigger_manager.h"
#include "tools/tools.h"
#include "prompt_template.h"
#include "cjson/cJSON.h"
#include "debug.h"
#include "../../nostr_core_lib/nostr_core/nostr_core.h"
@@ -1450,114 +1451,7 @@ static const char* template_skill_lookup_callback(void* user_data, const char* d
}
static char* resolve_skill_references_local(const char* input) {
if (!input) {
return strdup("");
}
size_t cap = strlen(input) + 128U;
size_t used = 0U;
char* out = (char*)malloc(cap);
if (!out) return NULL;
out[0] = '\0';
const char* p = input;
while (*p) {
const char* open = strstr(p, "{{");
if (!open) {
size_t tail = strlen(p);
if (used + tail + 1U > cap) {
size_t next = cap;
while (used + tail + 1U > next) next *= 2U;
char* grown = (char*)realloc(out, next);
if (!grown) {
free(out);
return NULL;
}
out = grown;
cap = next;
}
memcpy(out + used, p, tail);
used += tail;
out[used] = '\0';
break;
}
size_t prefix_len = (size_t)(open - p);
if (used + prefix_len + 1U > cap) {
size_t next = cap;
while (used + prefix_len + 1U > next) next *= 2U;
char* grown = (char*)realloc(out, next);
if (!grown) {
free(out);
return NULL;
}
out = grown;
cap = next;
}
memcpy(out + used, p, prefix_len);
used += prefix_len;
out[used] = '\0';
const char* close = strstr(open + 2, "}}");
if (!close) {
size_t rem = strlen(open);
if (used + rem + 1U > cap) {
size_t next = cap;
while (used + rem + 1U > next) next *= 2U;
char* grown = (char*)realloc(out, next);
if (!grown) {
free(out);
return NULL;
}
out = grown;
cap = next;
}
memcpy(out + used, open, rem);
used += rem;
out[used] = '\0';
break;
}
size_t var_len = (size_t)(close - (open + 2));
char var[128];
if (var_len >= sizeof(var)) var_len = sizeof(var) - 1U;
memcpy(var, open + 2, var_len);
var[var_len] = '\0';
char* start = var;
while (*start && isspace((unsigned char)*start)) start++;
char* end = start + strlen(start);
while (end > start && isspace((unsigned char)end[-1])) {
end[-1] = '\0';
end--;
}
const char* repl = "";
pthread_mutex_lock(&g_adopted_skills_mutex);
const char* found = adopted_skill_content_lookup_by_d_tag_locked(start);
repl = found ? found : "";
pthread_mutex_unlock(&g_adopted_skills_mutex);
size_t repl_len = strlen(repl);
if (used + repl_len + 1U > cap) {
size_t next = cap;
while (used + repl_len + 1U > next) next *= 2U;
char* grown = (char*)realloc(out, next);
if (!grown) {
free(out);
return NULL;
}
out = grown;
cap = next;
}
memcpy(out + used, repl, repl_len);
used += repl_len;
out[used] = '\0';
p = close + 2;
}
return out;
return prompt_template_resolve_inline_variables(input ? input : "", &g_tools_ctx);
}
static char* build_context_from_triggers(trigger_type_t trigger_type,
@@ -1596,8 +1490,12 @@ static char* build_context_from_triggers(trigger_type_t trigger_type,
}
}
char* matched_skill_contents[AGENT_ADOPTED_SKILLS_MAX];
int matched_skill_count = 0;
memset(matched_skill_contents, 0, sizeof(matched_skill_contents));
pthread_mutex_lock(&g_adopted_skills_mutex);
for (int i = 0; i < g_adopted_skills_count; i++) {
for (int i = 0; i < g_adopted_skills_count && matched_skill_count < AGENT_ADOPTED_SKILLS_MAX; i++) {
const agent_adopted_skill_t* s = &g_adopted_skills[i];
if (!s->has_trigger || s->trigger_type != trigger_type) {
continue;
@@ -1606,8 +1504,16 @@ static char* build_context_from_triggers(trigger_type_t trigger_type,
continue;
}
char* expanded = resolve_skill_references_local(s->content ? s->content : "");
const char* skill_text = expanded ? expanded : (s->content ? s->content : "");
matched_skill_contents[matched_skill_count] = strdup(s->content ? s->content : "");
if (matched_skill_contents[matched_skill_count]) {
matched_skill_count++;
}
}
pthread_mutex_unlock(&g_adopted_skills_mutex);
for (int i = 0; i < matched_skill_count; i++) {
char* expanded = resolve_skill_references_local(matched_skill_contents[i] ? matched_skill_contents[i] : "");
const char* skill_text = expanded ? expanded : (matched_skill_contents[i] ? matched_skill_contents[i] : "");
size_t need = strlen("\n\n---\n\n") + strlen(skill_text) + 1U;
if (used + need >= cap) {
@@ -1616,7 +1522,9 @@ static char* build_context_from_triggers(trigger_type_t trigger_type,
char* grown = (char*)realloc(out, next);
if (!grown) {
free(expanded);
pthread_mutex_unlock(&g_adopted_skills_mutex);
for (int j = i; j < matched_skill_count; j++) {
free(matched_skill_contents[j]);
}
free(out);
return NULL;
}
@@ -1635,8 +1543,8 @@ static char* build_context_from_triggers(trigger_type_t trigger_type,
matched++;
free(expanded);
free(matched_skill_contents[i]);
}
pthread_mutex_unlock(&g_adopted_skills_mutex);
if (matched == 0) {
const char* fallback = "You are an AI agent. Respond to the message.";

View File

@@ -12,8 +12,8 @@
// Using DIDACTYL_ prefix to avoid conflicts with nostr_core_lib VERSION macros
#define DIDACTYL_VERSION_MAJOR 0
#define DIDACTYL_VERSION_MINOR 2
#define DIDACTYL_VERSION_PATCH 5
#define DIDACTYL_VERSION "v0.2.5"
#define DIDACTYL_VERSION_PATCH 7
#define DIDACTYL_VERSION "v0.2.7"
// Agent metadata
#define DIDACTYL_NAME "Didactyl"