v0.0.26 - Add nostr_pubkey/nostr_npub tools with my_pubkey/my_npub aliases for agent key output

This commit is contained in:
Your Name
2026-03-02 07:32:05 -04:00
parent 4a400f1582
commit b1609317c1
4 changed files with 163 additions and 26 deletions
+2 -2
View File
@@ -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. 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.25 ## Current Status — v0.0.26
**Active build — this project is barely working. Experiment at your own risk.** **Active build — this project is barely working. Experiment at your own risk.**
> Last release update: v0.0.25 — Add model_get/model_set/model_list tools with persisted LLM config updates and model discovery > Last release update: v0.0.26 — Add nostr_pubkey/nostr_npub tools with my_pubkey/my_npub aliases for agent key output
- Connects to configured relays with auto-reconnect and relay state transition logging - Connects to configured relays with auto-reconnect and relay state transition logging
- Publishes configured startup events per relay as each relay becomes connected - Publishes configured startup events per relay as each relay becomes connected
+46 -22
View File
@@ -44,43 +44,67 @@ sequenceDiagram
### Tool Categories ### Tool Categories
#### Nostr Core Tools #### Nostr Event & Messaging Tools
| Tool | Description | | Tool | Description |
|---|---| |---|---|
| `nostr_post` | Publish any kind event to relays | | `nostr_post` | Publish a Nostr event to connected relays |
| `nostr_query` | Query relays with filters, return matching events | | `nostr_delete` | Request deletion of one or more previously published events (NIP-09 kind 5) |
| `nostr_dm` | Send a DM via NIP-04 | | `nostr_react` | React to a Nostr event with like/dislike/emoji (NIP-25 kind 7) |
| `nostr_dm_nip17` | Send a DM via NIP-17 gift wrap | | `nostr_query` | Query events from relays using a Nostr filter |
| `nostr_profile` | Update the agent's kind 0 metadata | | `nostr_dm_send` | Send a NIP-04 encrypted DM |
| `nostr_list_manage` | Add/remove items from replaceable list events | | `nostr_dm_send_nip17` | Send a private DM using NIP-17 gift wrap protocol |
| `nostr_relay_status` | Get connection status of all relays |
| `nostr_relay_info` | Get NIP-11 relay information document |
#### Identity Tools #### Nostr Identity & Utility Tools
| Tool | Description | | Tool | Description |
|---|---| |---|---|
| `nostr_resolve_identifier` | Resolve NIP-05, npub, nprofile, or note identifiers | | `nostr_profile_get` | Look up a Nostr profile (kind 0 metadata) by pubkey |
| `nostr_verify_nip05` | Verify a NIP-05 identifier | | `nostr_nip05_lookup` | Look up or verify a NIP-05 identifier (`user@domain`) |
| `nostr_encode` | Encode a Nostr entity into `nostr:` URI (`npub`, `note`, `nprofile`, `nevent`, `naddr`) |
| `nostr_decode` | Decode a Nostr bech32/`nostr:` URI into components |
| `nostr_relay_status` | Get connection status and statistics for all relays |
| `nostr_relay_info` | Fetch NIP-11 relay information document |
| `nostr_encrypt` | Encrypt plaintext using NIP-44 for a recipient |
| `nostr_decrypt` | Decrypt NIP-44 ciphertext from a sender |
| `nostr_list_manage` | Add/remove tag tuples in replaceable list events (NIP-51 style) |
#### Skill Management Tools #### Skills & Trigger Tools
| Tool | Description | | Tool | Description |
|---|---| |---|---|
| `skill_create` | Create or update a skill definition | | `skill_create` | Create or update a skill definition as kind `31123`/`31124` and optionally auto-adopt it |
| `skill_list` | List the agent's published skills | | `skill_list` | List this agent's published skills, optionally filtered by scope |
| `skill_adopt` | Add a skill to the adoption list | | `skill_adopt` | Adopt a skill by adding its address to kind `10123` adoption list |
| `skill_remove` | Remove a skill from the adoption list | | `skill_remove` | Remove a skill address from kind `10123` adoption list |
| `skill_search` | Search for skills across the Web of Trust | | `skill_search` | Search public skills by query/author and optionally rank by adoption popularity |
| `trigger_list` | List active triggered skills and their runtime status |
#### System Tools #### LLM / Model Management Tools
| Tool | Description | | Tool | Description |
|---|---| |---|---|
| `shell_exec` | Execute a shell command with sandboxing | | `model_get` | Get current active LLM runtime configuration (excluding API key) |
| `http_request` | Make an HTTP request | | `model_set` | Update active LLM configuration and persist it to `config.json` |
| `get_time` | Get the current UTC time | | `model_list` | List available model IDs using provider OpenAI-compatible `/models` endpoint |
#### System & Runtime Tools
| Tool | Description |
|---|---|
| `my_version` | Return current Didactyl version and metadata from build macros |
| `http_fetch` | Fetch HTTP(S) resources with optional method, headers, timeout, and body |
| `shell_exec` | Execute a shell command and return stdout/stderr |
| `file_read` | Read a local file as text from the configured working directory |
| `file_write` | Write text content to a local file in the configured working directory |
| `tool_list` | List available tools with name, description, and JSON parameter schema |
#### Content Publishing Conveniences
| Tool | Description |
|---|---|
| `nostr_post_readme` | Publish `README.md` as kind `30023` with deterministic d-tag `readme.md` |
| `nostr_file_md_to_longform_post` | Read a markdown file and publish it as kind `30023` longform post (defaults d-tag to lowercase filename) |
### Security Model ### Security Model
+2 -2
View File
@@ -12,8 +12,8 @@
// Using DIDACTYL_ prefix to avoid conflicts with nostr_core_lib VERSION macros // Using DIDACTYL_ prefix to avoid conflicts with nostr_core_lib VERSION macros
#define DIDACTYL_VERSION_MAJOR 0 #define DIDACTYL_VERSION_MAJOR 0
#define DIDACTYL_VERSION_MINOR 0 #define DIDACTYL_VERSION_MINOR 0
#define DIDACTYL_VERSION_PATCH 25 #define DIDACTYL_VERSION_PATCH 26
#define DIDACTYL_VERSION "v0.0.25" #define DIDACTYL_VERSION "v0.0.26"
// Agent metadata // Agent metadata
#define DIDACTYL_NAME "Didactyl" #define DIDACTYL_NAME "Didactyl"
+113
View File
@@ -1781,6 +1781,66 @@ char* tools_build_openai_schema_json(const tools_context_t* ctx) {
cJSON_AddItemToObject(t32, "function", t32_fn); cJSON_AddItemToObject(t32, "function", t32_fn);
cJSON_AddItemToArray(tools, t32); cJSON_AddItemToArray(tools, t32);
cJSON* t33 = cJSON_CreateObject();
cJSON* t33_fn = cJSON_CreateObject();
cJSON* t33_params = cJSON_CreateObject();
cJSON* t33_props = cJSON_CreateObject();
cJSON_AddStringToObject(t33, "type", "function");
cJSON_AddStringToObject(t33_fn, "name", "nostr_pubkey");
cJSON_AddStringToObject(t33_fn, "description", "Return this agent's pubkey in hex format");
cJSON_AddStringToObject(t33_params, "type", "object");
cJSON_AddItemToObject(t33_params, "properties", t33_props);
cJSON_AddItemToObject(t33_fn, "parameters", t33_params);
cJSON_AddItemToObject(t33, "function", t33_fn);
cJSON_AddItemToArray(tools, t33);
cJSON* t34 = cJSON_CreateObject();
cJSON* t34_fn = cJSON_CreateObject();
cJSON* t34_params = cJSON_CreateObject();
cJSON* t34_props = cJSON_CreateObject();
cJSON_AddStringToObject(t34, "type", "function");
cJSON_AddStringToObject(t34_fn, "name", "nostr_npub");
cJSON_AddStringToObject(t34_fn, "description", "Return this agent's pubkey encoded as npub bech32");
cJSON_AddStringToObject(t34_params, "type", "object");
cJSON_AddItemToObject(t34_params, "properties", t34_props);
cJSON_AddItemToObject(t34_fn, "parameters", t34_params);
cJSON_AddItemToObject(t34, "function", t34_fn);
cJSON_AddItemToArray(tools, t34);
cJSON* t35 = cJSON_CreateObject();
cJSON* t35_fn = cJSON_CreateObject();
cJSON* t35_params = cJSON_CreateObject();
cJSON* t35_props = cJSON_CreateObject();
cJSON_AddStringToObject(t35, "type", "function");
cJSON_AddStringToObject(t35_fn, "name", "my_pubkey");
cJSON_AddStringToObject(t35_fn, "description", "Alias for nostr_pubkey: return this agent's pubkey in hex format");
cJSON_AddStringToObject(t35_params, "type", "object");
cJSON_AddItemToObject(t35_params, "properties", t35_props);
cJSON_AddItemToObject(t35_fn, "parameters", t35_params);
cJSON_AddItemToObject(t35, "function", t35_fn);
cJSON_AddItemToArray(tools, t35);
cJSON* t36 = cJSON_CreateObject();
cJSON* t36_fn = cJSON_CreateObject();
cJSON* t36_params = cJSON_CreateObject();
cJSON* t36_props = cJSON_CreateObject();
cJSON_AddStringToObject(t36, "type", "function");
cJSON_AddStringToObject(t36_fn, "name", "my_npub");
cJSON_AddStringToObject(t36_fn, "description", "Alias for nostr_npub: return this agent's pubkey encoded as npub bech32");
cJSON_AddStringToObject(t36_params, "type", "object");
cJSON_AddItemToObject(t36_params, "properties", t36_props);
cJSON_AddItemToObject(t36_fn, "parameters", t36_params);
cJSON_AddItemToObject(t36, "function", t36_fn);
cJSON_AddItemToArray(tools, t36);
char* out = cJSON_PrintUnformatted(tools); char* out = cJSON_PrintUnformatted(tools);
cJSON_Delete(tools); cJSON_Delete(tools);
return out; return out;
@@ -3900,6 +3960,47 @@ static char* execute_nostr_query(const char* args_json) {
return json; return json;
} }
static char* execute_nostr_pubkey(tools_context_t* ctx, const char* args_json) {
if (!ctx || !ctx->cfg) return json_error("tool context unavailable");
cJSON* args = parse_tool_args_json(args_json);
if (!args) return json_error("invalid arguments JSON");
cJSON_Delete(args);
cJSON* out = cJSON_CreateObject();
if (!out) return NULL;
cJSON_AddBoolToObject(out, "success", 1);
cJSON_AddStringToObject(out, "pubkey", ctx->cfg->keys.public_key_hex);
char* json = cJSON_PrintUnformatted(out);
cJSON_Delete(out);
return json;
}
static char* execute_nostr_npub(tools_context_t* ctx, const char* args_json) {
if (!ctx || !ctx->cfg) return json_error("tool context unavailable");
cJSON* args = parse_tool_args_json(args_json);
if (!args) return json_error("invalid arguments JSON");
cJSON_Delete(args);
char npub[256] = {0};
if (nostr_key_to_bech32(ctx->cfg->keys.public_key, "npub", npub) != NOSTR_SUCCESS) {
return json_error("failed to encode npub");
}
cJSON* out = cJSON_CreateObject();
if (!out) return NULL;
cJSON_AddBoolToObject(out, "success", 1);
cJSON_AddStringToObject(out, "npub", npub);
char* json = cJSON_PrintUnformatted(out);
cJSON_Delete(out);
return json;
}
static char* execute_my_version(const char* args_json) { static char* execute_my_version(const char* args_json) {
cJSON* args = parse_tool_args_json(args_json); cJSON* args = parse_tool_args_json(args_json);
if (!args) return json_error("invalid arguments JSON"); if (!args) return json_error("invalid arguments JSON");
@@ -4653,6 +4754,18 @@ char* tools_execute(tools_context_t* ctx, const char* tool_name, const char* arg
if (strcmp(tool_name, "my_version") == 0) { if (strcmp(tool_name, "my_version") == 0) {
return execute_my_version(args_json); return execute_my_version(args_json);
} }
if (strcmp(tool_name, "nostr_pubkey") == 0) {
return execute_nostr_pubkey(ctx, args_json);
}
if (strcmp(tool_name, "nostr_npub") == 0) {
return execute_nostr_npub(ctx, args_json);
}
if (strcmp(tool_name, "my_pubkey") == 0) {
return execute_nostr_pubkey(ctx, args_json);
}
if (strcmp(tool_name, "my_npub") == 0) {
return execute_nostr_npub(ctx, args_json);
}
if (strcmp(tool_name, "http_fetch") == 0) { if (strcmp(tool_name, "http_fetch") == 0) {
return execute_http_fetch(ctx, args_json); return execute_http_fetch(ctx, args_json);
} }