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.
## Current Status — v0.0.25
## Current Status — v0.0.26
**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
- Publishes configured startup events per relay as each relay becomes connected
+46 -22
View File
@@ -44,43 +44,67 @@ sequenceDiagram
### Tool Categories
#### Nostr Core Tools
#### Nostr Event & Messaging Tools
| Tool | Description |
|---|---|
| `nostr_post` | Publish any kind event to relays |
| `nostr_query` | Query relays with filters, return matching events |
| `nostr_dm` | Send a DM via NIP-04 |
| `nostr_dm_nip17` | Send a DM via NIP-17 gift wrap |
| `nostr_profile` | Update the agent's kind 0 metadata |
| `nostr_list_manage` | Add/remove items from replaceable list events |
| `nostr_relay_status` | Get connection status of all relays |
| `nostr_relay_info` | Get NIP-11 relay information document |
| `nostr_post` | Publish a Nostr event to connected relays |
| `nostr_delete` | Request deletion of one or more previously published events (NIP-09 kind 5) |
| `nostr_react` | React to a Nostr event with like/dislike/emoji (NIP-25 kind 7) |
| `nostr_query` | Query events from relays using a Nostr filter |
| `nostr_dm_send` | Send a NIP-04 encrypted DM |
| `nostr_dm_send_nip17` | Send a private DM using NIP-17 gift wrap protocol |
#### Identity Tools
#### Nostr Identity & Utility Tools
| Tool | Description |
|---|---|
| `nostr_resolve_identifier` | Resolve NIP-05, npub, nprofile, or note identifiers |
| `nostr_verify_nip05` | Verify a NIP-05 identifier |
| `nostr_profile_get` | Look up a Nostr profile (kind 0 metadata) by pubkey |
| `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 |
|---|---|
| `skill_create` | Create or update a skill definition |
| `skill_list` | List the agent's published skills |
| `skill_adopt` | Add a skill to the adoption list |
| `skill_remove` | Remove a skill from the adoption list |
| `skill_search` | Search for skills across the Web of Trust |
| `skill_create` | Create or update a skill definition as kind `31123`/`31124` and optionally auto-adopt it |
| `skill_list` | List this agent's published skills, optionally filtered by scope |
| `skill_adopt` | Adopt a skill by adding its address to kind `10123` adoption list |
| `skill_remove` | Remove a skill address from kind `10123` adoption list |
| `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 |
|---|---|
| `shell_exec` | Execute a shell command with sandboxing |
| `http_request` | Make an HTTP request |
| `get_time` | Get the current UTC time |
| `model_get` | Get current active LLM runtime configuration (excluding API key) |
| `model_set` | Update active LLM configuration and persist it to `config.json` |
| `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
+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 25
#define DIDACTYL_VERSION "v0.0.25"
#define DIDACTYL_VERSION_PATCH 26
#define DIDACTYL_VERSION "v0.0.26"
// Agent metadata
#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_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);
cJSON_Delete(tools);
return out;
@@ -3900,6 +3960,47 @@ static char* execute_nostr_query(const char* args_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) {
cJSON* args = parse_tool_args_json(args_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) {
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) {
return execute_http_fetch(ctx, args_json);
}