v0.0.85 - Skip llm_config republish on startup when config was recalled from Nostr

This commit is contained in:
Your Name
2026-03-18 17:34:11 -04:00
parent 9d06f18769
commit 650df7bc41
4 changed files with 57 additions and 23 deletions
+2 -2
View File
@@ -55,11 +55,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.0.84
## Current Status — v0.0.85
**Active build — this project is barely working. Experiment at your own risk.**
> Last release update: v0.0.84Remove duplicated read-only tool payload fields and make slash output prefer content
> Last release update: v0.0.85Skip llm_config republish on startup when config was recalled from Nostr
- Connects to configured relays with auto-reconnect and relay state transition logging
- Publishes configured startup events per relay as each relay becomes connected
+29 -19
View File
@@ -813,24 +813,29 @@ static int publish_encrypted_self_config(const didactyl_config_t* cfg, const cha
return rc;
}
static int persist_runtime_config_to_nostr(const didactyl_config_t* cfg) {
static int persist_runtime_config_to_nostr(const didactyl_config_t* cfg, int persist_llm_config) {
if (!cfg) return -1;
cJSON* llm = cJSON_CreateObject();
if (!llm) return -1;
cJSON_AddStringToObject(llm, "provider", cfg->llm.provider);
cJSON_AddStringToObject(llm, "api_key", cfg->llm.api_key);
cJSON_AddStringToObject(llm, "model", cfg->llm.model);
cJSON_AddStringToObject(llm, "base_url", cfg->llm.base_url);
cJSON_AddNumberToObject(llm, "max_tokens", cfg->llm.max_tokens);
cJSON_AddNumberToObject(llm, "temperature", cfg->llm.temperature);
int llm_rc = 0;
if (persist_llm_config) {
cJSON* llm = cJSON_CreateObject();
if (!llm) return -1;
cJSON_AddStringToObject(llm, "provider", cfg->llm.provider);
cJSON_AddStringToObject(llm, "api_key", cfg->llm.api_key);
cJSON_AddStringToObject(llm, "model", cfg->llm.model);
cJSON_AddStringToObject(llm, "base_url", cfg->llm.base_url);
cJSON_AddNumberToObject(llm, "max_tokens", cfg->llm.max_tokens);
cJSON_AddNumberToObject(llm, "temperature", cfg->llm.temperature);
char* llm_json = cJSON_PrintUnformatted(llm);
cJSON_Delete(llm);
if (!llm_json) return -1;
char* llm_json = cJSON_PrintUnformatted(llm);
cJSON_Delete(llm);
if (!llm_json) return -1;
int llm_rc = publish_encrypted_self_config(cfg, "llm_config", llm_json);
free(llm_json);
llm_rc = publish_encrypted_self_config(cfg, "llm_config", llm_json);
free(llm_json);
} else {
DEBUG_INFO("[didactyl] startup phase: skipping llm_config publish because it was recalled from Nostr");
}
cJSON* agent = cJSON_CreateObject();
if (!agent) return llm_rc;
@@ -846,15 +851,18 @@ static int persist_runtime_config_to_nostr(const didactyl_config_t* cfg) {
return (llm_rc == 0 && agent_rc == 0) ? 0 : -1;
}
static void recover_missing_runtime_config_from_nostr(didactyl_config_t* cfg) {
static int recover_missing_runtime_config_from_nostr(didactyl_config_t* cfg) {
if (!cfg) {
return;
return 0;
}
int llm_recalled_from_nostr = 0;
if (!llm_config_is_complete(&cfg->llm)) {
char* llm_plaintext = NULL;
if (fetch_self_config_plaintext(cfg, "llm_config", &llm_plaintext) == 0 && llm_plaintext) {
if (apply_recalled_llm_config(cfg, llm_plaintext) == 0) {
llm_recalled_from_nostr = 1;
DEBUG_INFO("[didactyl] startup phase: recovered llm_config from Nostr");
} else {
DEBUG_WARN("[didactyl] startup phase: failed to apply recalled llm_config");
@@ -885,6 +893,8 @@ static void recover_missing_runtime_config_from_nostr(didactyl_config_t* cfg) {
DEBUG_WARN("[didactyl] startup phase: agent_config recall unavailable");
}
free(agent_plaintext);
return llm_recalled_from_nostr;
}
int main(int argc, char** argv) {
@@ -1129,8 +1139,8 @@ int main(int argc, char** argv) {
}
startup_step_begin(2, "Recover runtime config from Nostr");
recover_missing_runtime_config_from_nostr(&cfg);
startup_step_ok(2, "Recover runtime config from Nostr", NULL);
int llm_recalled_from_nostr = recover_missing_runtime_config_from_nostr(&cfg);
startup_step_ok(2, "Recover runtime config from Nostr", llm_recalled_from_nostr ? "llm_config recalled" : NULL);
startup_step_begin(3, "Validate LLM config");
if (!llm_config_is_complete(&cfg.llm)) {
@@ -1184,7 +1194,7 @@ int main(int argc, char** argv) {
}
}
if (persist_runtime_config_to_nostr(&cfg) != 0) {
if (persist_runtime_config_to_nostr(&cfg, llm_recalled_from_nostr ? 0 : 1) != 0) {
DEBUG_WARN("[didactyl] startup phase: failed to persist encrypted runtime config to Nostr");
} else {
DEBUG_INFO("[didactyl] startup phase: persisted encrypted runtime config to Nostr");
+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 84
#define DIDACTYL_VERSION "v0.0.84"
#define DIDACTYL_VERSION_PATCH 85
#define DIDACTYL_VERSION "v0.0.85"
// Agent metadata
#define DIDACTYL_NAME "Didactyl"
+24
View File
@@ -108,6 +108,25 @@ static int assign_string_field(cJSON* item, char* dst, size_t dst_size, int* cha
return 0;
}
static void mask_api_key_local(const char* api_key, char* out, size_t out_size) {
if (!out || out_size == 0) return;
out[0] = '\0';
if (!api_key || api_key[0] == '\0') {
return;
}
size_t api_len = strlen(api_key);
if (api_len >= 8U) {
snprintf(out,
out_size,
"%.4s...%s",
api_key,
api_key + api_len - 4U);
} else {
snprintf(out, out_size, "%s", "(set)");
}
}
char* execute_model_get(const char* args_json) {
cJSON* args = parse_args_local(args_json);
if (!args) return json_error_local("invalid arguments JSON");
@@ -120,10 +139,15 @@ char* execute_model_get(const char* args_json) {
cJSON* out = cJSON_CreateObject();
if (!out) return NULL;
char api_key_masked[64] = {0};
mask_api_key_local(cfg.api_key, api_key_masked, sizeof(api_key_masked));
cJSON_AddBoolToObject(out, "success", 1);
cJSON_AddStringToObject(out, "provider", cfg.provider);
cJSON_AddStringToObject(out, "model", cfg.model);
cJSON_AddStringToObject(out, "base_url", cfg.base_url);
cJSON_AddStringToObject(out, "api_key_masked", api_key_masked);
cJSON_AddNumberToObject(out, "max_tokens", cfg.max_tokens);
cJSON_AddNumberToObject(out, "temperature", cfg.temperature);