From 66b4ebee794c9a0d91b94cb07b9b1c6f2c965264 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sun, 1 Mar 2026 12:16:38 -0400 Subject: [PATCH] v0.0.18 - Harden tool argument JSON parsing and set fixed README publish image tag --- README.md | 4 +-- src/main.h | 4 +-- src/tools.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++------ 3 files changed, 78 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 4f38d0c..93d1f17 100644 --- a/README.md +++ b/README.md @@ -51,11 +51,11 @@ Agents learn capabilities through skills — Nostr events that any agent can di 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.17 +## Current Status — v0.0.18 **Active build — this project is barely working. Experiment at your own risk.** -> Last release update: v0.0.17 — Add -h/-v CLI flags and make post_readme_to_nostr skill call nostr_post_readme tool +> Last release update: v0.0.18 — Harden tool argument JSON parsing and set fixed README publish image tag - Connects to configured relays with auto-reconnect and relay state transition logging - Publishes configured startup events per relay as each relay becomes connected diff --git a/src/main.h b/src/main.h index a848dd2..a520898 100644 --- a/src/main.h +++ b/src/main.h @@ -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 17 -#define DIDACTYL_VERSION "v0.0.17" +#define DIDACTYL_VERSION_PATCH 18 +#define DIDACTYL_VERSION "v0.0.18" // Agent metadata #define DIDACTYL_NAME "Didactyl" diff --git a/src/tools.c b/src/tools.c index 3dbd433..c203ec9 100644 --- a/src/tools.c +++ b/src/tools.c @@ -674,16 +674,39 @@ char* tools_build_openai_schema_json(const tools_context_t* ctx) { } static char* execute_nostr_post(const char* args_json) { - cJSON* args = cJSON_Parse(args_json ? args_json : "{}"); + const char* raw_args_json = args_json ? args_json : "{}"; + raw_args_json = skip_ws(raw_args_json); + if (!raw_args_json || raw_args_json[0] == '\0') { + raw_args_json = "{}"; + } + + cJSON* args = cJSON_Parse(raw_args_json); char* repaired_args_json = NULL; - if (!args && args_json) { - repaired_args_json = sanitize_json_string_controls(args_json); - if (repaired_args_json) { - args = cJSON_Parse(repaired_args_json); + + if (args && cJSON_IsString(args) && args->valuestring) { + cJSON* nested = cJSON_Parse(args->valuestring); + if (nested) { + cJSON_Delete(args); + args = nested; } } - if (!args && args_json) { - args = parse_loose_nostr_post_args(args_json); + + if (!args && raw_args_json) { + repaired_args_json = sanitize_json_string_controls(raw_args_json); + if (repaired_args_json) { + args = cJSON_Parse(repaired_args_json); + if (args && cJSON_IsString(args) && args->valuestring) { + cJSON* nested = cJSON_Parse(args->valuestring); + if (nested) { + cJSON_Delete(args); + args = nested; + } + } + } + } + + if (!args && raw_args_json) { + args = parse_loose_nostr_post_args(raw_args_json); } if (!args) { free(repaired_args_json); @@ -807,9 +830,43 @@ static char* read_entire_file(const char* file_path, size_t* out_bytes) { static char* execute_nostr_post_readme(tools_context_t* ctx, const char* args_json) { if (!ctx || !ctx->cfg) return json_error("tool context unavailable"); - cJSON* args = cJSON_Parse(args_json ? args_json : "{}"); - if (!args) return json_error("invalid arguments JSON"); + const char* raw_args_json = args_json ? args_json : "{}"; + raw_args_json = skip_ws(raw_args_json); + if (!raw_args_json || raw_args_json[0] == '\0') { + raw_args_json = "{}"; + } + + cJSON* args = cJSON_Parse(raw_args_json); + char* repaired_args_json = NULL; + + if (args && cJSON_IsString(args) && args->valuestring) { + cJSON* nested = cJSON_Parse(args->valuestring); + if (nested) { + cJSON_Delete(args); + args = nested; + } + } + + if (!args) { + repaired_args_json = sanitize_json_string_controls(raw_args_json); + if (repaired_args_json) { + args = cJSON_Parse(repaired_args_json); + if (args && cJSON_IsString(args) && args->valuestring) { + cJSON* nested = cJSON_Parse(args->valuestring); + if (nested) { + cJSON_Delete(args); + args = nested; + } + } + } + } + + if (!args) { + free(repaired_args_json); + return json_error("invalid arguments JSON"); + } cJSON_Delete(args); + free(repaired_args_json); char readme_path[PATH_MAX]; if (build_tool_path(ctx, "README.md", readme_path, sizeof(readme_path)) != 0) { @@ -834,6 +891,14 @@ static char* execute_nostr_post_readme(tools_context_t* ctx, const char* args_js return json_error("failed to set d tag"); } + if (add_string_tag(tags, + "image", + "https://laantungir.github.io/img_repo/d21c4060632ab3d9d37a6062eeecbdbfbd67f03cb20dbd64838b1ba0d9cd8922.jpg") != 0) { + cJSON_Delete(tags); + free(content); + return json_error("failed to set image tag"); + } + ensure_nip23_metadata_tags(30023, content, &tags); nostr_publish_result_t publish_result;