v0.0.56 - Load triggers deterministically from startup events before EOSE

This commit is contained in:
Your Name
2026-03-09 16:29:17 -04:00
parent 1b9ecb782c
commit ffed72c9fd
5 changed files with 82 additions and 4 deletions
+2 -2
View File
@@ -53,11 +53,11 @@ Skills support context modes (`inject`, `full`, `override`) and per-skill LLM fa
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.0.55
## Current Status — v0.0.56
**Active build — this project is barely working. Experiment at your own risk.**
> Last release update: v0.0.55Defer trigger loading until self-skill EOSE and add trigger subscription debug instrumentation
> Last release update: v0.0.56Load triggers deterministically from startup events before EOSE
- Connects to configured relays with auto-reconnect and relay state transition logging
- Publishes configured startup events per relay as each relay becomes connected
+6
View File
@@ -271,6 +271,12 @@ int main(int argc, char** argv) {
DEBUG_INFO("[didactyl] startup phase: deferred trigger load will run after self-skill EOSE");
DEBUG_INFO("[didactyl] startup phase: startup-config trigger load begin");
if (trigger_manager_load_from_startup_events(&trigger_manager) != 0) {
DEBUG_WARN("[didactyl] startup phase: startup-config trigger load failed (continuing)");
}
DEBUG_INFO("[didactyl] startup phase: startup-config trigger load end");
DEBUG_INFO("[didactyl] startup phase: subscribe admin context begin");
if (nostr_handler_subscribe_admin_context() != 0) {
DEBUG_WARN("[didactyl] startup phase: subscribe admin context failed (continuing)");
+2 -2
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 0
#define DIDACTYL_VERSION_PATCH 55
#define DIDACTYL_VERSION "v0.0.55"
#define DIDACTYL_VERSION_PATCH 56
#define DIDACTYL_VERSION "v0.0.56"
// Agent metadata
#define DIDACTYL_NAME "Didactyl"
+71
View File
@@ -495,6 +495,77 @@ int trigger_manager_load_from_skills(trigger_manager_t* mgr) {
return 0;
}
int trigger_manager_load_from_startup_events(trigger_manager_t* mgr) {
if (!mgr || !mgr->cfg) {
return -1;
}
int loaded = 0;
int considered = 0;
for (int i = 0; i < mgr->cfg->startup_event_count; i++) {
startup_event_t* ev = &mgr->cfg->startup_events[i];
if (!ev) {
continue;
}
if (ev->kind != 31123 && ev->kind != 31124) {
continue;
}
considered++;
if (!ev->content || ev->content[0] == '\0' || !ev->tags_json || ev->tags_json[0] == '\0') {
continue;
}
cJSON* tags = cJSON_Parse(ev->tags_json);
if (!tags || !cJSON_IsArray(tags)) {
cJSON_Delete(tags);
DEBUG_WARN("[didactyl] startup trigger skip: invalid tags_json for startup event index=%d", i);
continue;
}
cJSON* d = find_tag_value_string(tags, "d");
cJSON* trigger = find_tag_value_string(tags, "trigger");
cJSON* filter = find_tag_value_string(tags, "filter");
cJSON* action = find_tag_value_string(tags, "action");
cJSON* enabled = find_tag_value_string(tags, "enabled");
const char* slug = (d && cJSON_IsString(d) && d->valuestring) ? d->valuestring : NULL;
const char* trigger_s = (trigger && cJSON_IsString(trigger) && trigger->valuestring) ? trigger->valuestring : NULL;
const char* filter_s = (filter && cJSON_IsString(filter) && filter->valuestring) ? filter->valuestring : NULL;
const char* action_s = (action && cJSON_IsString(action) && action->valuestring) ? action->valuestring : "llm";
const char* enabled_s = (enabled && cJSON_IsString(enabled) && enabled->valuestring) ? enabled->valuestring : "true";
if (!slug || slug[0] == '\0') {
cJSON_Delete(tags);
DEBUG_WARN("[didactyl] startup trigger skip: missing d tag for startup event index=%d", i);
continue;
}
if (!trigger_s || strcmp(trigger_s, "nostr-subscription") != 0 || !filter_s || filter_s[0] == '\0') {
cJSON_Delete(tags);
continue;
}
trigger_action_type_t at = (strcmp(action_s, "template") == 0) ? TRIGGER_ACTION_TEMPLATE : TRIGGER_ACTION_LLM;
int is_enabled = (strcmp(enabled_s, "false") == 0 || strcmp(enabled_s, "0") == 0) ? 0 : 1;
if (trigger_manager_add(mgr, slug, ev->content, filter_s, at, is_enabled) == 0) {
loaded++;
DEBUG_INFO("[didactyl] startup trigger registered slug=%s action=%s enabled=%d", slug, at == TRIGGER_ACTION_TEMPLATE ? "template" : "llm", is_enabled);
} else {
DEBUG_WARN("[didactyl] startup trigger failed slug=%s", slug);
}
cJSON_Delete(tags);
}
DEBUG_INFO("[didactyl] trigger manager loaded %d trigger(s) from startup config (considered=%d)", loaded, considered);
return 0;
}
int trigger_manager_add(trigger_manager_t* mgr,
const char* skill_slug,
const char* content,
+1
View File
@@ -40,6 +40,7 @@ typedef struct trigger_manager {
int trigger_manager_init(trigger_manager_t* mgr, didactyl_config_t* cfg);
int trigger_manager_load_from_skills(trigger_manager_t* mgr);
int trigger_manager_load_from_startup_events(trigger_manager_t* mgr);
int trigger_manager_add(trigger_manager_t* mgr,
const char* skill_slug,
const char* content,