From 7e69819be550e7b1e41f0df1e45df9f31d7768cb Mon Sep 17 00:00:00 2001 From: Your Name Date: Thu, 5 Mar 2026 09:58:06 -0400 Subject: [PATCH] v0.0.36 - Remove inline NIP-17 poll+retry window to prevent post-reply hang while keeping send-path debug logging --- README.md | 4 +- context.log.md | 180 ++++++++++++++++++++++++++++++++++++++++++++ src/main.h | 4 +- src/nostr_handler.c | 73 +----------------- 4 files changed, 187 insertions(+), 74 deletions(-) diff --git a/README.md b/README.md index ddc6d81..521e362 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.35 +## Current Status — v0.0.36 **Active build — this project is barely working. Experiment at your own risk.** -> Last release update: v0.0.35 — Improve NIP-17 send reliability with re-entrancy guard, auth handshake retry window, and send-path debug logs +> Last release update: v0.0.36 — Remove inline NIP-17 poll+retry window to prevent post-reply hang while keeping send-path debug logging - 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/context.log.md b/context.log.md index 831f3c2..525222c 100644 --- a/context.log.md +++ b/context.log.md @@ -1,3 +1,183 @@ +```text +Context Log - not seen by model +timestamp=2026-03-05 09:54:29 +phase=llm_chat_with_tools_messages +sender=8ff74724ed641b3c28e5a86d7c5cbc49c37638ace8c6c38935860e7a5eedde0e +model=claude-haiku-4.5 +context_bytes=10457 +approx_tokens=2614 +``` + +Sections: 19 + +# system_prompt | role=system + +## Didactyl Agent + +You are Didactyl, a sovereign AI agent living on Nostr. + +### Communication Rules +- You communicate through encrypted Nostr direct messages. +- Keep responses concise and clear. + +### Behavior +- Be helpful and technically accurate. +- If unsure, state uncertainty directly. +- Prefer actionable, practical advice. +- Use the person's name when messaging them if you know it. +- For the administrator, use their name from the administrator kind 0 profile metadata when available. + +### Tool Use Policy +- You have tools available and should use them when a request requires taking action. +- For requests involving local inspection or command execution, call `shell_exec` instead of refusing. +- For posting to Nostr, call `nostr_post` with explicit `kind` and `content`. +- For relay/event lookup tasks, call `nostr_query` with an appropriate filter. +- After a tool call, base your answer on the actual tool result. +- Never claim a tool was run if no tool was executed. + +### Task Management +- Maintain and use your internal task list as short-term working memory. +- Break long or complex actions into clear tasks before executing them. +- Update task status as you complete steps so your plan stays accurate. + +### Safety +- Do not claim to have executed actions you did not execute. +- You may share your public key (npub) with anyone. +- Never reveal your private key (nsec) under any circumstance. + +# admin_identity | role=system + +### Administrator Identity (source: config.admin.pubkey) + +This is your administrator! Admin pubkey (hex): 8ff74724ed641b3c28e5a86d7c5cbc49c37638ace8c6c38935860e7a5eedde0e + +# admin_profile | role=system + +### Administrator Kind 0 Profile (source: nostr kind 0) + +Administrator kind 0 profile content (JSON): {"name":"William S Burroughs","display_name":"WSB","about":"I like to write, and I like crank. They are good. Sometimes I'm not so sure.","banner":"https://www.grunge.com/img/gallery/paul-mccartney-and-william-s-burroughs-relationship-explained/who-was-william-s-burroughs-1672155531.jpg","website":"https://addicted.com","picture":"https://hips.hearstapps.com/hmg-prod/images/william-s-burroughs.jpg?resize=1200:*","lud16":"","nip05":""} + +# admin_relay_list | role=system + +### Administrator Relay List (source: nostr kind 10002) + +Administrator kind 10002 relay-list content (JSON): ["wss://relay.laantungir.net/","wss://relay.damus.io/","wss://nos.lol/","wss://relay.nostr.band/","wss://purplepag.es/","ws://127.0.0.1:7777/","wss://nostr.mom/"] + +# startup_events | role=system + +### Startup Events Memory (source: config.startup_events) + +Startup events memory (kinds/content/tags): [{"kind":0,"content":"{\"name\":\"Didactyl Agent\",\"display_name\":\"Didactyl\",\"about\":\"A sovereign AI agent on Nostr\",\"picture\":\"https://laantungir.github.io/img_repo/daf95a99f3797fa4ac39f3791f377ad79bcb7b8a6868f75fe66d2ab4af4bd1f5.png\",\"banner\":\"https://laantungir.github.io/img_repo/d21c4060632ab3d9d37a6062eeecbdbfbd67f03cb20dbd64838b1ba0d9cd8922.jpg\"}","tags":[]},{"kind":10002,"content":"","tags":[["r","wss://relay.damus.io"],["r","wss://nos.lol"],["r","wss://relay.primal.net"],["r","ws://127.0.0.1:7777"],["r","wss://relay.laantungir.net"]]},{"kind":10050,"content":"","tags":[["relay","wss://relay.damus.io"],["relay","wss://nos.lol"],["relay","wss://relay.primal.net"],["relay","ws://127.0.0.1:7777"],["relay","wss://relay.laantungir.net"]]},{"kind":1,"content":"Hello world from Didactyl startup","tags":[["t","didactyl"],["t","startup"]]},{"kind":3,"content":"","tags":[]},{"kind":31123,"content":"{\"name\":\"long_form_note\",\"description\":\"How to publish a NIP-23 long-form article (kind 30023)\",\"nip\":\"NIP-23\",\"event_kind\":30023,\"format\":\"The content field must be markdown text; avoid arbitrary hard line-breaks in paragraphs and do not include HTML.\",\"required_tags\":{\"d\":\"Addressable identifier slug for the article. Reusing the same d tag replaces prior versions.\",\"title\":\"Human-readable article title.\",\"published_at\":\"Unix timestamp as a string for first publication time; keep stable on edits.\"},\"optional_tags\":{\"summary\":\"Short 1-2 sentence summary.\",\"image\":\"URL for article preview image.\",\"t\":\"Topic hashtags using repeated t tags, usually 3-6 lowercase terms.\"},\"behavior\":\"If required values are missing or unclear, ask the administrator before publishing instead of guessing.\",\"procedure\":[\"Determine title and d tag from admin input or source material.\",\"Draft markdown body content.\",\"Set published_at as unix seconds string.\",\"Add optional summary/image/t tags when known.\",\"Publish with nostr_post kind 30023 including tags array.\"]}","tags":[["d","long_form_note"],["app","didactyl"],["scope","public"],["slug","long_form_note"]]},{"kind":31123,"content":"{\"name\":\"post_readme_to_nostr\",\"description\":\"Publish README.md using the dedicated nostr_post_readme tool\",\"uses_skill\":\"long_form_note\",\"event_kind\":30023,\"procedure\":[\"Call nostr_post_readme with empty arguments {}.\",\"Return the tool response including event_id, d_tag, and naddr_uri.\",\"If the tool returns success=false, report the tool error verbatim.\"],\"required_values\":{\"d\":\"readme.md\",\"tool\":\"nostr_post_readme\"}}","tags":[["d","post_readme_to_nostr"],["app","didactyl"],["scope","public"],["slug","post_readme_to_nostr"]]},{"kind":31124,"content":"{\"name\":\"admin_ops\",\"description\":\"Private operational procedures\"}","tags":[["d","admin_ops"],["app","didactyl"],["scope","private"],["slug","admin_ops"]]},{"kind":10123,"content":"","tags":[["a","31123:55993e3db0ed7bf07395fd44c2d695c224d195553a1aff7320a18e41679d9c7c:long_form_note"],["a","31123:55993e3db0ed7bf07395fd44c2d695c224d195553a1aff7320a18e41679d9c7c:post_readme_to_nostr"],["app","didactyl"],["scope","public"]]}] + +# adopted_skills | role=system + +### Adopted Skills Memory (source: adoption list + startup fallback) + +Adopted skills memory (always-on behavioral instructions): follow these skill instructions when relevant and never violate explicit constraints. + + +--- + +#### Skill +Skill slug: long_form_note +Skill address: 31123:52a3e82f7b3743852fbe804cfcbf4db3448115887895247c001f2b50e790acb8:long_form_note + +Instructions: +Name: long_form_note +Description: How to publish a NIP-23 long-form article (kind 30023) +Event kind: 30023 +Procedure: + 1. Determine title and d tag from admin input or source material. + 2. Draft markdown body content. + 3. Set published_at as unix seconds string. + 4. Add optional summary/image/t tags when known. + 5. Publish with nostr_post kind 30023 including tags array. + + + +--- + +#### Skill +Skill slug: post_readme_to_nostr +Skill address: 31123:52a3e82f7b3743852fbe804cfcbf4db3448115887895247c001f2b50e790acb8:post_readme_to_nostr + +Instructions: +Name: post_readme_to_nostr +Description: Publish README.md using the dedicated nostr_post_readme tool +Event kind: 30023 +Procedure: + 1. Call nostr_post_readme with empty arguments {}. + 2. Return the tool response including event_id, d_tag, and naddr_uri. + 3. If the tool returns success=false, report the tool error verbatim. + + + +--- + +#### Skill +Skill slug: admin_ops +Skill address: 31124:52a3e82f7b3743852fbe804cfcbf4db3448115887895247c001f2b50e790acb8:admin_ops + +Instructions: +Name: admin_ops +Description: Private operational procedures + + + +# agent_tasks | role=system + +#### Current Tasks + +Your active task list - short-term working memory for tracking plan steps. + +- [ ] 5. Tweet 3: Gets Smarter Over Time - "Didactyl starts as an AI that explores and learns. Over time, the best workflows get locked in as reliable, fast processes. It evolves from experimental to hardened—from thinking to doing. An agent that improves itself. #nostr #agents" + + +# admin_notes | role=system + +### Administrator Recent Notes (source: nostr kind 1) + +Recent posts: +- GM +- Getting longer +- Long day. +- This is a test. +- test +- Post 11 +- Post 10 +- This is +Post +9 +- Eight +- Seven + + +# dm_history | role=chat + +09:47 WSB /model_list +11:31 Agent Didactyl has started up and is online (version v0.0.29, connected relays: 4/4). +11:31 WSB Good afternoon. +11:31 Agent Good afternoon, WSB! How's it going? What can I help you with today? +11:32 WSB What is left on your tasks? +11:32 Agent Looking at my active task list, I have 2 items remaining: + +- [ ] 4. Tweet 2: Borrow Skills from Friends - "Imagine if you could test out a friend's workflow without fully committing to it. Didactyl lets you try skills others have built, safely and temporarily. No installation. No lock-in. Just try it, see if it works for you. That's how tools should work. #nostr" + +- [ ] 5. Tweet 3: Gets Smarter Over Time - "Didactyl starts as an AI that explores and learns. Over time, the best workflows get locked in as reliable, fast processes. It evolves from experimental to hardened—from thinking to doing. An agent that improves itself. #nostr #agents" + +Both are promotional posts about Didactyl skills. Want me to post these? +11:32 WSB delete tweet 2. We finished that. +11:42 Agent Done. Tweet 2 is removed. You now have 1 remaining task: + +- [ ] 5. Tweet 3: Gets Smarter Over Time - "Didactyl starts as an AI that explores and learns. Over time, the best workflows get locked in as reliable, fast processes. It evolves from experimental to hardened—from thinking to doing. An agent that improves itself. #nostr #agents" +06:23 Agent Didactyl has started up and is online (version v0.0.30, connected relays: 4/4). +07:39 WSB /help +09:54 WSB good morning + + + +--- + ```text Context Log - not seen by model timestamp=2026-03-05 09:44:11 diff --git a/src/main.h b/src/main.h index 34e70a7..bd34727 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 35 -#define DIDACTYL_VERSION "v0.0.35" +#define DIDACTYL_VERSION_PATCH 36 +#define DIDACTYL_VERSION "v0.0.36" // Agent metadata #define DIDACTYL_NAME "Didactyl" diff --git a/src/nostr_handler.c b/src/nostr_handler.c index e13744a..ff24bb2 100644 --- a/src/nostr_handler.c +++ b/src/nostr_handler.c @@ -1872,8 +1872,6 @@ char* nostr_handler_relay_info_json(const char* relay_url) { } int nostr_handler_send_dm_nip17(const char* recipient_pubkey_hex, const char* message, const char* subject) { - static int g_nip17_send_in_progress = 0; - if (!g_cfg || !g_pool || !recipient_pubkey_hex || !message || recipient_pubkey_hex[0] == '\0' || message[0] == '\0') { return -1; } @@ -1928,8 +1926,6 @@ int nostr_handler_send_dm_nip17(const char* recipient_pubkey_hex, const char* me int any_sent = 0; int sent_count = 0; - g_nip17_send_in_progress++; - for (int i = 0; i < gift_count; i++) { if (!gift_wraps[i]) { continue; @@ -1953,72 +1949,9 @@ int nostr_handler_send_dm_nip17(const char* recipient_pubkey_hex, const char* me cJSON_Delete(gift_wraps[i]); } - if (g_nip17_send_in_progress == 1) { - for (int i = 0; i < 5; i++) { - (void)nostr_relay_pool_poll(g_pool, 100); - } - - for (int i = 0; i < gift_count; i++) { - if (!gift_wraps[i]) { - continue; - } - } - - int resend_total = 0; - for (int i = 0; i < gift_count; i++) { - (void)i; - } - - // Recreate and resend once after auth handshake drain. - cJSON* retry_chat_event = nostr_nip17_create_chat_event( - message, - recipients, - 1, - (subject && subject[0] != '\0') ? subject : NULL, - NULL, - NULL, - g_cfg->keys.public_key_hex); - if (retry_chat_event) { - cJSON* retry_gift_wraps[NIP17_MAX_GIFT_WRAPS] = {0}; - int retry_count = nostr_nip17_send_dm(retry_chat_event, - recipients, - 1, - g_cfg->keys.private_key, - retry_gift_wraps, - NIP17_MAX_GIFT_WRAPS, - 0); - cJSON_Delete(retry_chat_event); - - if (retry_count > 0) { - for (int i = 0; i < retry_count; i++) { - if (!retry_gift_wraps[i]) { - continue; - } - int resent = nostr_relay_pool_publish_async(g_pool, - target_relays, - target_count, - retry_gift_wraps[i], - NULL, - NULL); - if (resent > 0) { - any_sent = 1; - resend_total += resent; - } - cJSON_Delete(retry_gift_wraps[i]); - } - } - } - - DEBUG_TRACE("[didactyl] NIP-17 send retry window complete: recipient=%.16s... initial_sent=%d retry_sent=%d", - recipient_pubkey_hex, - sent_count, - resend_total); - } else { - DEBUG_TRACE("[didactyl] NIP-17 send in nested context (depth=%d), skipping poll+retry window", - g_nip17_send_in_progress); - } - - g_nip17_send_in_progress--; + DEBUG_TRACE("[didactyl] NIP-17 send complete: recipient=%.16s... sent_count=%d", + recipient_pubkey_hex, + sent_count); if (!any_sent) { DEBUG_WARN("[didactyl] NIP-17 send failed: no relay accepted publish for recipient %.16s...",