Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c877ca646e | ||
|
|
b5b479e9a8 | ||
|
|
52f1cd3b30 | ||
|
|
09d45febdd |
@@ -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.40
|
||||
## Current Status — v0.2.44
|
||||
|
||||
**Active build — this project is barely working. Experiment at your own risk.**
|
||||
|
||||
> Last release update: v0.2.40 — Fix adoption list freshness by selecting newest kind 10123 event and temporarily disable periodic relay-backed trigger reconciliation for validation
|
||||
> Last release update: v0.2.44 — Fix adoption list selection to self-authored latest event in agent and skill tool
|
||||
|
||||
- Connects to configured relays with auto-reconnect and relay state transition logging
|
||||
- Publishes configured startup events per relay as each relay becomes connected
|
||||
|
||||
40
src/agent.c
40
src/agent.c
@@ -681,7 +681,21 @@ static char* build_slash_help_all_json(void) {
|
||||
|
||||
int adopted_count = 0;
|
||||
if (adoption_events && cJSON_IsArray(adoption_events) && cJSON_GetArraySize(adoption_events) > 0) {
|
||||
cJSON* ev0 = cJSON_GetArrayItem(adoption_events, 0);
|
||||
cJSON* ev0 = NULL;
|
||||
double best_created = -1.0;
|
||||
int an = cJSON_GetArraySize(adoption_events);
|
||||
for (int ai = 0; ai < an; ai++) {
|
||||
cJSON* ev = cJSON_GetArrayItem(adoption_events, ai);
|
||||
if (!ev || !cJSON_IsObject(ev)) {
|
||||
continue;
|
||||
}
|
||||
cJSON* created_at = cJSON_GetObjectItemCaseSensitive(ev, "created_at");
|
||||
double created = (created_at && cJSON_IsNumber(created_at)) ? created_at->valuedouble : 0.0;
|
||||
if (!ev0 || created > best_created) {
|
||||
ev0 = ev;
|
||||
best_created = created;
|
||||
}
|
||||
}
|
||||
cJSON* tags = ev0 ? cJSON_GetObjectItemCaseSensitive(ev0, "tags") : NULL;
|
||||
if (tags && cJSON_IsArray(tags)) {
|
||||
int tn = cJSON_GetArraySize(tags);
|
||||
@@ -1449,7 +1463,29 @@ static int refresh_adopted_skills_cache_if_needed(void) {
|
||||
free(adoption_json);
|
||||
|
||||
if (adoption_events && cJSON_IsArray(adoption_events) && cJSON_GetArraySize(adoption_events) > 0) {
|
||||
cJSON* list_event = cJSON_GetArrayItem(adoption_events, 0);
|
||||
cJSON* list_event = NULL;
|
||||
double list_event_created_at = -1.0;
|
||||
int adoption_n = cJSON_GetArraySize(adoption_events);
|
||||
for (int ai = 0; ai < adoption_n; ai++) {
|
||||
cJSON* ev = cJSON_GetArrayItem(adoption_events, ai);
|
||||
if (!ev || !cJSON_IsObject(ev)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
cJSON* ev_pubkey = cJSON_GetObjectItemCaseSensitive(ev, "pubkey");
|
||||
if (!ev_pubkey || !cJSON_IsString(ev_pubkey) || !ev_pubkey->valuestring ||
|
||||
strcmp(ev_pubkey->valuestring, g_cfg->keys.public_key_hex) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
cJSON* created_at = cJSON_GetObjectItemCaseSensitive(ev, "created_at");
|
||||
double created = (created_at && cJSON_IsNumber(created_at)) ? created_at->valuedouble : 0.0;
|
||||
if (!list_event || created > list_event_created_at) {
|
||||
list_event = ev;
|
||||
list_event_created_at = created;
|
||||
}
|
||||
}
|
||||
|
||||
cJSON* list_tags = list_event ? cJSON_GetObjectItemCaseSensitive(list_event, "tags") : NULL;
|
||||
|
||||
if (list_tags && cJSON_IsArray(list_tags)) {
|
||||
|
||||
@@ -815,7 +815,21 @@ static char* build_slash_help_all_json_local(void) {
|
||||
|
||||
int adopted_count = 0;
|
||||
if (adoption_events && cJSON_IsArray(adoption_events) && cJSON_GetArraySize(adoption_events) > 0) {
|
||||
cJSON* ev0 = cJSON_GetArrayItem(adoption_events, 0);
|
||||
cJSON* ev0 = NULL;
|
||||
double best_created = -1.0;
|
||||
int an = cJSON_GetArraySize(adoption_events);
|
||||
for (int ai = 0; ai < an; ai++) {
|
||||
cJSON* ev = cJSON_GetArrayItem(adoption_events, ai);
|
||||
if (!ev || !cJSON_IsObject(ev)) {
|
||||
continue;
|
||||
}
|
||||
cJSON* created_at = cJSON_GetObjectItemCaseSensitive(ev, "created_at");
|
||||
double created = (created_at && cJSON_IsNumber(created_at)) ? created_at->valuedouble : 0.0;
|
||||
if (!ev0 || created > best_created) {
|
||||
ev0 = ev;
|
||||
best_created = created;
|
||||
}
|
||||
}
|
||||
cJSON* tags = ev0 ? cJSON_GetObjectItemCaseSensitive(ev0, "tags") : NULL;
|
||||
if (tags && cJSON_IsArray(tags)) {
|
||||
int tn = cJSON_GetArraySize(tags);
|
||||
|
||||
@@ -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 40
|
||||
#define DIDACTYL_VERSION "v0.2.40"
|
||||
#define DIDACTYL_VERSION_PATCH 44
|
||||
#define DIDACTYL_VERSION "v0.2.44"
|
||||
|
||||
// Agent metadata
|
||||
#define DIDACTYL_NAME "Didactyl"
|
||||
|
||||
@@ -3694,6 +3694,75 @@ char* nostr_handler_get_self_skill_events_json(void) {
|
||||
return json ? json : strdup("[]");
|
||||
}
|
||||
|
||||
int nostr_handler_refresh_self_skill_cache_from_relays(int timeout_ms) {
|
||||
if (!g_cfg || !g_pool) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int effective_timeout_ms = timeout_ms > 0 ? timeout_ms : 5000;
|
||||
|
||||
cJSON* filter = cJSON_CreateObject();
|
||||
cJSON* kinds = cJSON_CreateArray();
|
||||
cJSON* authors = cJSON_CreateArray();
|
||||
if (!filter || !kinds || !authors) {
|
||||
cJSON_Delete(filter);
|
||||
cJSON_Delete(kinds);
|
||||
cJSON_Delete(authors);
|
||||
return -1;
|
||||
}
|
||||
|
||||
cJSON_AddItemToArray(kinds, cJSON_CreateNumber(31123));
|
||||
cJSON_AddItemToArray(kinds, cJSON_CreateNumber(31124));
|
||||
cJSON_AddItemToArray(kinds, cJSON_CreateNumber(10123));
|
||||
cJSON_AddItemToObject(filter, "kinds", kinds);
|
||||
|
||||
cJSON_AddItemToArray(authors, cJSON_CreateString(g_cfg->keys.public_key_hex));
|
||||
if (g_cfg->admin.pubkey[0] != '\0' && strcmp(g_cfg->admin.pubkey, g_cfg->keys.public_key_hex) != 0) {
|
||||
cJSON_AddItemToArray(authors, cJSON_CreateString(g_cfg->admin.pubkey));
|
||||
}
|
||||
cJSON_AddItemToObject(filter, "authors", authors);
|
||||
cJSON_AddNumberToObject(filter, "limit", 500);
|
||||
|
||||
char* events_json = nostr_handler_query_json(filter, effective_timeout_ms);
|
||||
cJSON_Delete(filter);
|
||||
if (!events_json) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
cJSON* events = cJSON_Parse(events_json);
|
||||
free(events_json);
|
||||
if (!events || !cJSON_IsArray(events)) {
|
||||
cJSON_Delete(events);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int merged = 0;
|
||||
pthread_mutex_lock(&g_self_skill_mutex);
|
||||
int n = cJSON_GetArraySize(events);
|
||||
for (int i = 0; i < n; i++) {
|
||||
cJSON* ev = cJSON_GetArrayItem(events, i);
|
||||
if (!ev || !cJSON_IsObject(ev)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
cJSON* kind = cJSON_GetObjectItemCaseSensitive(ev, "kind");
|
||||
int kind_val = (kind && cJSON_IsNumber(kind)) ? (int)kind->valuedouble : -1;
|
||||
if (kind_val == 31124) {
|
||||
(void)normalize_private_skill_event_local(ev);
|
||||
}
|
||||
|
||||
self_skill_cache_upsert_event_locked(ev);
|
||||
merged++;
|
||||
}
|
||||
pthread_mutex_unlock(&g_self_skill_mutex);
|
||||
|
||||
cJSON_Delete(events);
|
||||
|
||||
agent_invalidate_adopted_skills_cache();
|
||||
DEBUG_INFO("[didactyl] skill_refresh relay reload merged %d self-skill/adoption events", merged);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nostr_handler_is_event_in_self_cache(const char* event_id_hex) {
|
||||
if (!event_id_hex || strlen(event_id_hex) != 64U) {
|
||||
return 0;
|
||||
|
||||
@@ -77,6 +77,7 @@ int nostr_handler_validate_self_skill_cache(int* out_skill_count, int* out_adopt
|
||||
void nostr_handler_refresh_relay_statuses(void);
|
||||
int nostr_handler_sync_relays_from_config(void);
|
||||
char* nostr_handler_get_self_skill_events_json(void);
|
||||
int nostr_handler_refresh_self_skill_cache_from_relays(int timeout_ms);
|
||||
int nostr_handler_is_event_in_self_cache(const char* event_id_hex);
|
||||
const char* nostr_handler_get_startup_display_name(void);
|
||||
int nostr_handler_connected_relay_count(void);
|
||||
|
||||
@@ -342,6 +342,12 @@ static int fetch_adoption_list_tags_local(tools_context_t* ctx, cJSON** out_tags
|
||||
continue;
|
||||
}
|
||||
|
||||
cJSON* ev_pubkey = cJSON_GetObjectItemCaseSensitive(ev, "pubkey");
|
||||
if (!ev_pubkey || !cJSON_IsString(ev_pubkey) || !ev_pubkey->valuestring ||
|
||||
strcmp(ev_pubkey->valuestring, ctx->cfg->keys.public_key_hex) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
cJSON* created_at = cJSON_GetObjectItemCaseSensitive(ev, "created_at");
|
||||
double created = (created_at && cJSON_IsNumber(created_at)) ? created_at->valuedouble : 0.0;
|
||||
if (!best || created > best_created) {
|
||||
@@ -2474,12 +2480,17 @@ char* execute_skill_refresh(tools_context_t* ctx, const char* args_json) {
|
||||
(void)args_json;
|
||||
if (!ctx || !ctx->cfg) return json_error_local("tool context unavailable");
|
||||
|
||||
int rc = nostr_handler_refresh_self_skill_cache_from_relays(5000);
|
||||
if (rc != 0) {
|
||||
return json_error_local("skill_refresh failed to reload self-skill cache from relays");
|
||||
}
|
||||
|
||||
agent_invalidate_adopted_skills_cache();
|
||||
|
||||
cJSON* out = cJSON_CreateObject();
|
||||
if (!out) return NULL;
|
||||
cJSON_AddBoolToObject(out, "success", 1);
|
||||
cJSON_AddStringToObject(out, "message", "adopted skills cache invalidated; next context build will reload skills");
|
||||
cJSON_AddStringToObject(out, "message", "self-skill cache refreshed from relays; adopted skills cache invalidated; next context build will use latest relay data");
|
||||
char* json = cJSON_PrintUnformatted(out);
|
||||
cJSON_Delete(out);
|
||||
return json;
|
||||
|
||||
Reference in New Issue
Block a user