v0.0.26 - Add nostr_pubkey/nostr_npub tools with my_pubkey/my_npub aliases for agent key output
This commit is contained in:
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user