diff --git a/README.md b/README.md index 75b1bb8..fc7d0c9 100644 --- a/README.md +++ b/README.md @@ -54,11 +54,11 @@ Skills compose by adoption-list order (`10123`) and trigger tags carry runtime e 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.2.23 +## Current Status — v0.2.24 **Active build — this project is barely working. Experiment at your own risk.** -> Last release update: v0.2.23 — Improve skill authoring guidance and context viewing workflow: enrich skill_create/skill_edit schema descriptions for markdown content, role markers, template variables, and trigger/filter pairing; add external Anvil context.logs viewer assets (index.html + watch_context.sh) for Live Server markdown-to-HTML monitoring without Didactyl runtime changes +> Last release update: v0.2.24 — Improve skills editor trigger filters with per-trigger helper widgets and presets - 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/docs/CONTEXT.md b/docs/CONTEXT.md index 3cb8992..ad8c91a 100644 --- a/docs/CONTEXT.md +++ b/docs/CONTEXT.md @@ -92,8 +92,8 @@ Trigger event occurs (DM, cron, subscription, webhook, chain) │ ├─ Bump all skill headings down one level (# -> ##) │ └─ Concatenate skills with `---` separators │ - ├─ Split Roles - │ └─ Parse `system:` and `user:` markers to build API messages array + ├─ Build API roles + │ └─ Runtime constructs OpenAI-compatible `messages` (system + user + assistant/tool loop) │ ├─ Attach tool schemas (filtered by skill requires_tool tags) │ @@ -105,10 +105,9 @@ Trigger event occurs (DM, cron, subscription, webhook, chain) ### Visualization -The assembled context is a single, coherent markdown document before being split into API messages: +The assembled context starts as a single markdown document (skills + resolved variables), then the runtime maps it into API role messages. ```markdown -system: # Didactyl Agent - **npub**: `npub1...` @@ -123,11 +122,10 @@ You speak concisely and directly. Respond helpfully to the admin. Use tools as needed. - -user: -Who mentioned me today? ``` +For DM triggers, the runtime appends the incoming DM text as the `user` message. For non-DM triggers, it appends the trigger payload as the `user` message. + ### Why Order Matters - Earlier skills in the adoption list appear first in the context window. @@ -248,17 +246,13 @@ Output files are written to: ### Snapshot Formats -Initial snapshots (`*_init.md`) are the assembled markdown context document, including role markers and heading bump effects: +Initial snapshots (`*_init.md`) are the assembled markdown context document (with heading-bump effects). They reflect authored skill markdown before runtime message-role packaging: ```markdown # Didactyl Agent -system: ## Anvil Agent ... - -user: -Who was WSB historically? ``` Turn snapshots (`*_tNNN.md`) are human-readable markdown renderings of the OpenAI-compatible `messages` array used for that loop turn: diff --git a/docs/SKILLS.md b/docs/SKILLS.md index eb67c42..6bf3646 100644 --- a/docs/SKILLS.md +++ b/docs/SKILLS.md @@ -68,7 +68,7 @@ The `content` field of a skill event IS the template — markdown instructions t ```json { "kind": 31123, - "content": "system:\n## Spelling and Grammar Checker\n\nYou are a spelling and grammar checker.\n\n### Rules\n\n- Fix spelling errors\n- Fix grammar errors\n- Preserve original formatting\n- Return **ONLY** the corrected text, no explanations\n\nuser:\n{{message}}", + "content": "## Spelling and Grammar Checker\n\nYou are a spelling and grammar checker.\n\n### Rules\n\n- Fix spelling errors\n- Fix grammar errors\n- Preserve original formatting\n- Return **ONLY** the corrected text, no explanations\n\nInput text:\n{{message}}", "tags": [ ["d", "spellcheck"], ["description", "Check spelling and grammar"], @@ -80,8 +80,8 @@ The `content` field of a skill event IS the template — markdown instructions t } ``` -- **`content`** — the template in markdown. May include `{{...}}` template variables and `system:` / `user:` role markers. This is what goes into the context window. -- **Role Markers** — `system:`, `user:`, and `assistant:` are parsed only when they appear at the start of a line. Content without a marker defaults to `system:`. +- **`content`** — the template in markdown. May include `{{...}}` template variables. This is what goes into the context window. +- **Role ownership** — skill authors should write plain markdown instructions, not `system:` / `user:` / `assistant:` markers. The runtime owns role construction and appends trigger payloads (for DM triggers, raw message text) as the `user` message at execution time. - **Heading Levels** — The runtime owns the `#` (h1) heading for the document title. All headings in skill content are automatically bumped down one level (`#` becomes `##`, `##` becomes `###`) during context assembly. Skill authors should use `##` for their top-level sections. - **`["description", "..."]`** — human-readable description for discovery and UI display. - Each `["tag", "value"]` is a separate tag on the Nostr event. diff --git a/docs/TOOLS.md b/docs/TOOLS.md index 966902d..a373ddc 100644 --- a/docs/TOOLS.md +++ b/docs/TOOLS.md @@ -114,7 +114,7 @@ These tools manage skill and trigger lifecycle; skill semantics and trigger exec | Tool | Description | |---|---| -| `skill_create` | Create or update a skill definition as kind `31123`/`31124` and optionally auto-adopt it (content should be markdown with optional `system:`/`user:`/`assistant:` role markers) | +| `skill_create` | Create or update a skill definition as kind `31123`/`31124` and optionally auto-adopt it (content should be markdown instructions; runtime handles role packaging) | | `skill_edit` | Edit an existing self skill by d tag and republish it as kind `31123`/`31124` (content should remain markdown-first) | | `skill_list` | List available skills discovered online (agent + admin), with adoption status and optional filters | | `skill_adopt` | Adopt a skill by adding its address to kind `10123` adoption list | @@ -469,7 +469,7 @@ These examples show the JSON structure for tool calls. "name": "skill_create", "arguments": { "d": "weather-skill", - "content": "system:\n## Weather Assistant\n\nYou provide concise weather summaries.\n\nuser:\n{{message}}", + "content": "## Weather Assistant\n\nYou provide concise weather summaries.\n\nInput:\n{{message}}", "description": "Fetches weather data", "trigger": "dm", "filter": "{\"from\":\"admin\"}", diff --git a/plans/remove_role_markers_from_skills.md b/plans/remove_role_markers_from_skills.md new file mode 100644 index 0000000..75ea9f7 --- /dev/null +++ b/plans/remove_role_markers_from_skills.md @@ -0,0 +1,94 @@ +# Remove Role Markers from Skill Content + +## Summary + +Skill content should always be **system-role instructions** — pure markdown. The `system:`, `user:`, and `assistant:` role markers should not appear in skill content authored by users or the LLM agent. + +The runtime already handles `user:` injection internally (appending the DM message or trigger event as the user message). Skill authors writing `user:` in their content is either redundant or creates conflicts (double `user:` markers). + +## What Changes + +### Principle + +- **Skill content = system instructions.** Always. No role markers. +- **The runtime owns role assignment.** It injects `user:` before the actual input (DM, trigger event). +- **`context_roles_split()` stays** — the runtime still uses it internally to split the assembled markdown (which includes the runtime-injected `user:` marker) into API messages. + +### Files to Change + +#### Documentation + +| File | Change | +|------|--------| +| `docs/SKILLS.md` | Remove role markers from skill content spec and examples. Clarify that skill content is always system instructions. | +| `docs/CONTEXT.md` | Clarify that `user:` is injected by the runtime, not by skill authors. Update examples. | +| `docs/TOOLS.md` | Remove role marker references from `skill_create` and `skill_edit` descriptions. | + +#### Source Code + +| File | Change | +|------|--------| +| `src/tools/tools_schema.c` | Remove role marker references from `skill_create` and `skill_edit` tool descriptions and parameter descriptions. | +| `src/context_roles.c` | **No change** — still needed for runtime-level `user:` splitting. | +| `src/context_roles.h` | **No change**. | +| `src/agent.c` | **No change** — already injects `user:` correctly. | + +#### Web Pages + +| File | Change | +|------|--------| +| `~/lt/client-ndk/www/skills-edit.html` | Remove `system:`/`user:`/`assistant:` syntax highlighting from the editor overlay. Update placeholder text. | + +#### Plans (historical docs, lower priority) + +| File | Change | +|------|--------| +| `plans/skills_edit_page.md` | Remove role marker references from content description and highlighting spec. | +| `plans/markdown_context_window.md` | Update role marker section to clarify runtime-only usage. | +| `plans/example_context.md` | Update examples to show skill content without role markers. | +| `plans/example_context_v2.md` | Update examples to show skill content without role markers. | +| `plans/skills_demo_page.md` | Update template examples to remove `system:`/`user:` from skill templates. | + +### What Does NOT Change + +- **`context_roles_split()`** — The runtime still assembles a full markdown string with `user:` injected at the boundary, then splits it. This is an internal runtime mechanism, not a skill authoring concern. +- **skills-tv.html** — This is a separate client-side execution model that builds its own messages array. It can keep its `system:`/`user:` template format since it is not going through the Didactyl agent. However, it could be simplified later. +- **DM history** — Already uses proper role assignment in the messages array, not role markers. + +## Detailed Changes + +### docs/SKILLS.md + +**Before:** +```json +{ + "content": "system:\n## Spelling and Grammar Checker\n\nYou are a spelling and grammar checker.\n\n### Rules\n...\n\nuser:\n{{message}}" +} +``` + +**After:** +```json +{ + "content": "## Spelling and Grammar Checker\n\nYou are a spelling and grammar checker.\n\n### Rules\n..." +} +``` + +Remove the bullet points about role markers. Add a note: + +> Skill content is always system-role instructions. The runtime handles user message injection (DM content, trigger events) automatically. Do not include `system:`, `user:`, or `assistant:` markers in skill content. + +### src/tools/tools_schema.c + +**skill_create description** — Remove "use role markers (system:/user:/assistant:) at line start when needed; unmarked content defaults to system." + +Replace with: "Write content as markdown system instructions. The runtime handles user message injection. Prefer ## for top-level sections." + +**skill_create content param** — Remove "May include role markers at line start (system:/user:/assistant:)" + +Replace with: "Markdown system instructions for the skill. May include markdown headings/lists/code fences and template variables." + +Same pattern for **skill_edit**. + +### skills-edit.html + +Remove the `.hl-role` CSS class and the regex that highlights `system:`, `user:`, `assistant:` in the editor overlay. Update the textarea placeholder from `system:\nYou are...\n\nuser:\n{{message}}` to just `## My Skill\n\nYou are a helpful assistant.\n\nRespond to {{message}} with...`. diff --git a/plans/skills_edit_page.md b/plans/skills_edit_page.md new file mode 100644 index 0000000..eb38761 --- /dev/null +++ b/plans/skills_edit_page.md @@ -0,0 +1,307 @@ +# Skills Editor Page — `skills-edit.html` + +## Overview + +A standalone web page in `~/lt/client-ndk/www/` for editing Didactyl agent skills. Built on top of [`template.html`](../../client-ndk/www/template.html) — all existing template functionality (auth, sidenav, hamburger, relay status, footer, theme toggle, logout) remains intact. + +The logged-in user IS the agent. The page uses Nostr subscriptions via the NDK worker to fetch skills and the adoption list, and publishes events via `publishEvent()` to save/adopt/remove skills. + +--- + +## Data Model + +### Nostr Event Kinds + +| Kind | Purpose | Replaceable? | +|------|---------|-------------| +| `31123` | Public skill definition | Yes, by d-tag | +| `31124` | Private skill definition (NIP-44 encrypted content) | Yes, by d-tag | +| `10123` | Skill adoption list | Yes, single per pubkey | + +### Skill Event Structure + +``` +content: markdown template with {{variables}} (plain authored instructions; runtime handles role packaging) +tags: + [d, slug] + [description, human-readable description] + [trigger, dm|cron|nostr-subscription|webhook|chain] (optional) + [filter, type-specific filter JSON] (optional) + [llm, fallback chain string] (optional) + [temperature, number] (optional) + [max_tokens, number] (optional) + [seed, number] (optional) + [requires_tool, tool_name] (0..N) + [requires_skill, skill_d_tag] (0..N) + [optional_tool, tool_name] (0..N) +``` + +### Adoption List (kind 10123) + +```json +{ + "kind": 10123, + "tags": [ + ["a", "31123::skill-slug"], + ["a", "31124::private-skill-slug"] + ] +} +``` + +--- + +## Page Layout + +Three-column layout filling the body area between header and footer: + +``` +┌─────────────────────────────────────────────────────────────────────┐ +│ HEADER [hamburger] Skills Editor [avatar]│ +├──────────────┬──────────────────────────────────┬───────────────────┤ +│ │ │ │ +│ SKILLS │ SKILL EDITOR │ TOOLS │ +│ LIST │ │ │ +│ │ [slug] [description] │ nostr_post │ +│ ┌────────┐ │ [trigger] [filter] │ nostr_query │ +│ │ search │ │ [llm] [temp] [tokens] │ nostr_dm_send │ +│ └────────┘ │ │ local_shell_exec │ +│ │ ┌──────────────────────────────┐ │ memory_save │ +│ My|Pub|Adpt │ │ │ │ memory_recall │ +│ │ │ Large textarea with │ │ skill_create │ +│ skill-1 ★ │ │ syntax highlighting for │ │ ... │ +│ skill-2 │ │ {{variables}} and tool names │ │ │ +│ skill-3 ★ │ │ │ │ Double-click to │ +│ skill-4 │ │ │ │ add as │ +│ ... │ │ │ │ requires_tool │ +│ │ └──────────────────────────────┘ │ │ +│ ────────── │ │ │ +│ ADOPTED │ [Save] [Save Private] [New] │ │ +│ identity ↕ │ [Adopt] [Remove from adopted] │ │ +│ chat ↕ │ │ │ +│ monitor ↕ │ │ │ +│ │ │ │ +├──────────────┴──────────────────────────────────┴───────────────────┤ +│ FOOTER [relay status] [status] [info] │ +└─────────────────────────────────────────────────────────────────────┘ +``` + +### Left Column — Skills List (~20% width) + +- **Search input** at top to filter skills by slug/description +- **Filter tabs**: My | Public | Adopted + - **My**: skills authored by the current pubkey (kind 31123 + 31124) + - **Public**: public skills from anyone (kind 31123 only, no author filter) — for discovery and copying + - **Adopted**: skills currently in the kind 10123 adoption list +- **Scrollable skill list**: each item shows slug, description snippet, author name/short-pubkey, ★ if adopted +- Clicking a skill loads it into the editor +- **Copy/Fork button**: when viewing a public skill from another author, a "Copy to My Skills" button creates a new skill under the current pubkey with the same content (new d-tag to avoid collision) +- **Adopted Skills section** below the list: + - Shows current adoption list entries in order + - Drag-to-reorder support (or up/down buttons) + - Visual indicator of adoption order + +### Center Column — Skill Editor (~60% width) + +- **Metadata row**: slug (d-tag), description inputs +- **Trigger row**: trigger type dropdown, filter input +- **Execution params row**: llm input, temperature, max_tokens, seed +- **Requirements display**: shows current requires_tool, requires_skill, optional_tool tags as removable chips/badges +- **Large textarea** for skill content (markdown template) + - Syntax highlighting overlay for `{{variable_names}}` in accent color + - Tool name references highlighted when they match known tools +- **Action buttons**: + - Save (publish as kind 31123) + - Save Private (publish as kind 31124 with NIP-44 encryption) + - New Skill (clear editor) + - Adopt (add to kind 10123 list) + - Remove from Adopted (remove from kind 10123 list) + - Delete Skill (kind 5 deletion event) + +### Right Column — Tools List (~20% width) + +- **Hardcoded list** of all Didactyl tools from TOOLS.md +- Each tool shows name and brief description +- **Double-click** a tool to add it as a `requires_tool` tag on the current skill +- Visual indicator if tool is already required by current skill +- Search/filter input at top + +--- + +## Syntax Highlighting Approach + +Use a transparent overlay `
` positioned exactly over the `