v0.0.12 - Add nostr_post tags support plus NIP-23 long_form_note and post_readme_to_nostr skills
This commit is contained in:
@@ -12,11 +12,11 @@ Because all identity, communication, and memory live on Nostr, the agent is **po
|
||||
|
||||
**Skills are the new apps.** Agents learn capabilities through skills — public Nostr events that any agent can discover, adopt, and share. There is no app store, no gatekeeper, no approval process. If someone publishes a useful skill, your agent can find it through your web of trust and start using it. Popularity is measured by adoption, not by a rating algorithm. The best skills spread because agents actually use them.
|
||||
|
||||
## Current Status — v0.0.11
|
||||
## Current Status — v0.0.12
|
||||
|
||||
**Active build — relay-aware autonomous agent with tool-use and Nostr-native startup memory.**
|
||||
**Active build — this project is barely working. Experiment at your own risk.**
|
||||
|
||||
> Last release update: v0.0.11 — auto update readme.md
|
||||
> Last release update: v0.0.12 — Add nostr_post tags support plus NIP-23 long_form_note and post_readme_to_nostr skills
|
||||
|
||||
- Connects to configured relays with auto-reconnect and relay state transition logging
|
||||
- Publishes configured startup events per relay as each relay becomes connected
|
||||
|
||||
@@ -123,12 +123,27 @@
|
||||
"kind": 31123,
|
||||
"content_fields": {
|
||||
"name": "long_form_note",
|
||||
"description": "Procedure for creating and publishing long-form notes",
|
||||
"steps": [
|
||||
"Draft structure",
|
||||
"Write sections",
|
||||
"Review",
|
||||
"Publish"
|
||||
"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": [
|
||||
@@ -150,6 +165,47 @@
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"kind": 31123,
|
||||
"content_fields": {
|
||||
"name": "post_readme_to_nostr",
|
||||
"description": "Read README.md from the repo and publish it as a NIP-23 long-form note",
|
||||
"uses_skill": "long_form_note",
|
||||
"event_kind": 30023,
|
||||
"procedure": [
|
||||
"Read README.md using file_read with path README.md.",
|
||||
"Set d tag exactly to readme.md.",
|
||||
"Set title from the first markdown H1 heading in README.md.",
|
||||
"Set summary from the opening paragraph of README.md.",
|
||||
"Set image from project metadata when available (kind 0 picture/banner), otherwise omit image tag.",
|
||||
"Generate 3-6 lowercase t tags from README section topics.",
|
||||
"Set published_at to current unix timestamp as string.",
|
||||
"Publish with nostr_post kind 30023, full README markdown in content, and full NIP-23 tag set."
|
||||
],
|
||||
"required_values": {
|
||||
"d": "readme.md",
|
||||
"summary_source": "opening paragraph"
|
||||
}
|
||||
},
|
||||
"tags": [
|
||||
[
|
||||
"d",
|
||||
"post_readme_to_nostr"
|
||||
],
|
||||
[
|
||||
"app",
|
||||
"didactyl"
|
||||
],
|
||||
[
|
||||
"scope",
|
||||
"public"
|
||||
],
|
||||
[
|
||||
"slug",
|
||||
"post_readme_to_nostr"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"kind": 31124,
|
||||
"content_fields": {
|
||||
@@ -183,6 +239,10 @@
|
||||
"a",
|
||||
"31123:55993e3db0ed7bf07395fd44c2d695c224d195553a1aff7320a18e41679d9c7c:long_form_note"
|
||||
],
|
||||
[
|
||||
"a",
|
||||
"31123:55993e3db0ed7bf07395fd44c2d695c224d195553a1aff7320a18e41679d9c7c:post_readme_to_nostr"
|
||||
],
|
||||
[
|
||||
"app",
|
||||
"didactyl"
|
||||
|
||||
@@ -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 11
|
||||
#define DIDACTYL_VERSION "v0.0.11"
|
||||
#define DIDACTYL_VERSION_PATCH 12
|
||||
#define DIDACTYL_VERSION "v0.0.12"
|
||||
|
||||
// Agent metadata
|
||||
#define DIDACTYL_NAME "Didactyl"
|
||||
|
||||
24
src/tools.c
24
src/tools.c
@@ -94,6 +94,13 @@ char* tools_build_openai_schema_json(const tools_context_t* ctx) {
|
||||
cJSON* p_content = cJSON_CreateObject();
|
||||
cJSON_AddStringToObject(p_content, "type", "string");
|
||||
cJSON_AddItemToObject(t1_props, "content", p_content);
|
||||
cJSON* p_tags = cJSON_CreateObject();
|
||||
cJSON_AddStringToObject(p_tags, "type", "array");
|
||||
cJSON_AddStringToObject(p_tags, "description", "Optional Nostr tags array, e.g. [[\"d\",\"slug\"],[\"t\",\"nostr\"]]");
|
||||
cJSON* p_tags_items = cJSON_CreateObject();
|
||||
cJSON_AddStringToObject(p_tags_items, "type", "array");
|
||||
cJSON_AddItemToObject(p_tags, "items", p_tags_items);
|
||||
cJSON_AddItemToObject(t1_props, "tags", p_tags);
|
||||
cJSON_AddItemToArray(t1_required, cJSON_CreateString("kind"));
|
||||
cJSON_AddItemToArray(t1_required, cJSON_CreateString("content"));
|
||||
|
||||
@@ -213,12 +220,27 @@ static char* execute_nostr_post(const char* args_json) {
|
||||
|
||||
cJSON* kind = cJSON_GetObjectItemCaseSensitive(args, "kind");
|
||||
cJSON* content = cJSON_GetObjectItemCaseSensitive(args, "content");
|
||||
cJSON* tags = cJSON_GetObjectItemCaseSensitive(args, "tags");
|
||||
if (!kind || !cJSON_IsNumber(kind) || !content || !cJSON_IsString(content) || !content->valuestring) {
|
||||
cJSON_Delete(args);
|
||||
return json_error("nostr_post requires integer kind and string content");
|
||||
}
|
||||
if (tags && !cJSON_IsArray(tags)) {
|
||||
cJSON_Delete(args);
|
||||
return json_error("nostr_post tags must be an array when provided");
|
||||
}
|
||||
|
||||
int rc = nostr_handler_publish_kind_event((int)kind->valuedouble, content->valuestring, NULL);
|
||||
cJSON* tags_dup = NULL;
|
||||
if (tags) {
|
||||
tags_dup = cJSON_Duplicate(tags, 1);
|
||||
if (!tags_dup) {
|
||||
cJSON_Delete(args);
|
||||
return json_error("nostr_post failed to duplicate tags");
|
||||
}
|
||||
}
|
||||
|
||||
int rc = nostr_handler_publish_kind_event((int)kind->valuedouble, content->valuestring, tags_dup);
|
||||
cJSON_Delete(tags_dup);
|
||||
cJSON_Delete(args);
|
||||
if (rc != 0) return json_error("nostr_post failed");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user