@pingvinen/donna-assistant 0.5.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -54,6 +54,26 @@ git -C <storage_repo> diff --cached --quiet || git -C <storage_repo> commit -m "
54
54
 
55
55
  If `auto_push` is true in config, also push.
56
56
 
57
+ **`backfill-tool-type`:** Backfill `type` on existing tool sections in tools.md using heuristic detection.
58
+
59
+ Read `<storage_repo>/donna/tools.md` with the Read tool. If the file does not exist or has no tool sections, skip this handler.
60
+
61
+ For each tool section (starting with `## <tool_name>`), check if a `- type:` line already exists. If the `- type:` line is missing, detect the correct type:
62
+
63
+ 1. If the tool section contains a `- command:` line where the value starts with `mcp:` (e.g., `- command: mcp:linear`), insert `- type: mcp` immediately after the `- command:` line.
64
+ 2. Else, if the tool section contains a `- base_url:` line:
65
+ - If the capabilities section contains entries that look like GraphQL queries (contain `query {` or `mutation {`), insert `- type: graphql` immediately after `## <tool_name>` (REST/GraphQL tools have no `- command:` line).
66
+ - Otherwise, insert `- type: rest` immediately after `## <tool_name>`.
67
+ 3. Else (no `mcp:` prefix, no `base_url` field), insert `- type: cli` immediately after the `- command:` line.
68
+
69
+ Write the updated file back with the Write tool. If any changes were made, commit:
70
+ ```bash
71
+ git -C <storage_repo> add -A
72
+ git -C <storage_repo> diff --cached --quiet || git -C <storage_repo> commit -m "donna(migrate): backfill tool types on existing tools"
73
+ ```
74
+
75
+ If `auto_push` is true in config, also push.
76
+
57
77
  After processing all pending migrations, update `~/.donna/state.md` with the Write tool: remove the completed entries from `pending_migrations`. If no entries remain, write:
58
78
  ```markdown
59
79
  ---
@@ -70,31 +90,92 @@ Read `<storage_repo>/donna/tools.md` with the Read tool. If the file does not ex
70
90
  Stop.
71
91
 
72
92
  Parse each tool section (starting with `## <tool_name>`). For each tool, extract:
73
- - `command` — the CLI command to run
74
- - `version` — the stored version string
93
+ - `command` — the CLI command to run (CLI/MCP tools only)
94
+ - `type` — the tool type field (if absent, treat as "cli")
95
+ - `version` — the stored version string (CLI tools only)
75
96
  - `learned` — the date capabilities were last learned
97
+ - `base_url` — the API endpoint (REST/GraphQL tools only)
98
+ - `auth_header` — the auth header name, if present (REST/GraphQL tools only)
99
+ - `auth_secret` — the secret key name, if present (REST/GraphQL tools only)
76
100
  - capabilities list under `### Capabilities`
77
101
 
78
102
  Store the parsed tools as `<registered_tools>`.
79
103
  </step>
80
104
 
81
105
  <step name="check-versions">
82
- For each tool in `<registered_tools>`, run via Bash:
83
- ```bash
84
- <command> --version 2>/dev/null | head -1
85
- ```
106
+ For each tool in `<registered_tools>`:
107
+
108
+ If `<type>` is `rest` or `mcp`:
109
+ Add to `<unchanged_tools>` — version checking is not applicable for REST/MCP tools.
110
+ Continue to next tool.
111
+
112
+ If `<type>` is `graphql`:
113
+ Run a GraphQL introspection query to detect schema changes.
114
+
115
+ **IMPORTANT: Auth is OPTIONAL for GraphQL tools. Public APIs work without any secret. You MUST always attempt introspection regardless of whether auth is configured. NEVER skip a GraphQL tool just because it has no auth_secret.**
116
+
117
+ 1. Attempt to read `<storage_repo>/donna/secrets.md` with the Read tool. If the file exists and contains the `auth_secret` key with a value that is not a placeholder (does not contain "REPLACE_WITH"), set `<resolved_secret>` to that value. Otherwise, set `<resolved_secret>` to empty (no auth). **An empty resolved_secret is perfectly valid — proceed to step 2 regardless.**
118
+
119
+ 2. Run via Bash with a 15-second timeout. Include the auth header only when a real secret was resolved:
120
+ - If `<resolved_secret>` is non-empty:
121
+ ```bash
122
+ timeout 15 curl -s -X POST \
123
+ -H "<auth_header>: <resolved_secret>" \
124
+ -H "Content-Type: application/json" \
125
+ -d '{"query":"{ __schema { types { name fields { name type { name } } } } }"}' \
126
+ "<base_url>" 2>&1
127
+ ```
128
+ - If `<resolved_secret>` is empty (public API or no secret configured):
129
+ ```bash
130
+ timeout 15 curl -s -X POST \
131
+ -H "Content-Type: application/json" \
132
+ -d '{"query":"{ __schema { types { name fields { name type { name } } } } }"}' \
133
+ "<base_url>" 2>&1
134
+ ```
135
+
136
+ 3. If the request fails (non-zero exit, timeout, or error response), add to `<unchanged_tools>` with note "introspection failed — skipped" and continue.
137
+
138
+ 4. If successful, compare the returned schema against stored capabilities:
139
+ - Extract field names and types from the introspection response for the types/queries relevant to stored capabilities.
140
+ - Check if any stored capability references fields that no longer exist in the schema (removed fields).
141
+ - Check if the schema has new fields on types used by stored capabilities that might be useful.
142
+
143
+ 5. If no meaningful changes detected, add to `<unchanged_tools>`.
144
+
145
+ 6. If changes detected, add to `<changed_tools>` with a `<schema_changes>` annotation listing:
146
+ - Removed fields (fields in stored capabilities no longer in schema)
147
+ - New fields (fields in schema not referenced by any stored capability)
148
+
149
+ If `<type>` is `cli` (or absent; treat as `cli`):
150
+ Run via Bash:
151
+ ```bash
152
+ <command> --version 2>/dev/null | head -1
153
+ ```
154
+
155
+ Compare the output against the stored `version` field using simple string equality — "is it different?" is sufficient; no semver parsing required.
156
+
157
+ If `<command>` is not found (command fails), treat it as changed with a warning note.
158
+
159
+ Add to:
160
+ - `<changed_tools>` — installed version differs from stored version (or command not found)
161
+ - `<unchanged_tools>` — installed version matches stored version exactly
162
+ </step>
86
163
 
87
- Compare the output against the stored `version` field using simple string equality — "is it different?" is sufficient; no semver parsing required.
164
+ <step name="report-unchanged">
165
+ For each tool in `<unchanged_tools>`:
88
166
 
89
- If `<command>` is not found (command fails), treat it as changed with a warning note.
167
+ If `<type>` is `rest` or `mcp`, print:
168
+ ```
169
+ ⊘ <tool_name>: <type> tool — re-learning not applicable (capabilities are user-defined)
170
+ ```
90
171
 
91
- Collect tools into two lists:
92
- - `<changed_tools>` — installed version differs from stored version (or command not found)
93
- - `<unchanged_tools>` installed version matches stored version exactly
94
- </step>
172
+ If `<type>` is `graphql`, print using the skip reason from check-versions:
173
+ ```
174
+ <tool_name>: graphql tool <skip_reason>
175
+ ```
176
+ Where `<skip_reason>` is "no schema changes detected" or "introspection failed — skipped".
95
177
 
96
- <step name="report-unchanged">
97
- For each tool in `<unchanged_tools>`, print:
178
+ Otherwise (CLI tools), print:
98
179
  ```
99
180
  ⊘ <tool_name>: unchanged at <version> — skipped
100
181
  ```
@@ -106,7 +187,34 @@ If ALL tools are in `<unchanged_tools>` (no changes found), print:
106
187
  Stop.
107
188
  </step>
108
189
 
190
+ <step name="relearn-graphql">
191
+ For each graphql tool in `<changed_tools>`:
192
+
193
+ Print:
194
+ ```
195
+ ⚠ <tool_name>: schema changes detected
196
+ Removed fields: <list or "none">
197
+ New fields: <list or "none">
198
+ ```
199
+
200
+ Use AskUserQuestion:
201
+ ```
202
+ Update capabilities for <tool_name>?
203
+ ```
204
+ Suggest "yes" and "no" as options.
205
+
206
+ If yes:
207
+ Show the current capabilities and the detected changes side by side. Use AskUserQuestion to let the user update capabilities interactively (same editing loop as adjust-tool: "remove <number>", "add <name>: <query>", "edit <number> <new_query>", "done").
208
+
209
+ Store the updated capabilities. Update `learned` date to today.
210
+
211
+ If no:
212
+ Skip — keep existing capabilities unchanged. Update `learned` date to today (to avoid re-checking next run).
213
+ </step>
214
+
109
215
  <step name="relearn-changed">
216
+ Note: Re-learning is supported for CLI tools (version-based) and GraphQL tools (schema introspection). REST and MCP tool capabilities are user-defined and not auto-learned.
217
+
110
218
  For each tool in `<changed_tools>`, apply the same learn-capabilities logic as add-tool.md's learn-capabilities step.
111
219
 
112
220
  Determine if the tool is well-known (gh, jira, kubectl) or unknown. For well-known tools, synthesize capabilities from training data. Do NOT parse --help for well-known tools.
@@ -54,6 +54,26 @@ git -C <storage_repo> diff --cached --quiet || git -C <storage_repo> commit -m "
54
54
 
55
55
  If `auto_push` is true in config, also push.
56
56
 
57
+ **`backfill-tool-type`:** Backfill `type` on existing tool sections in tools.md using heuristic detection.
58
+
59
+ Read `<storage_repo>/donna/tools.md` with the Read tool. If the file does not exist or has no tool sections, skip this handler.
60
+
61
+ For each tool section (starting with `## <tool_name>`), check if a `- type:` line already exists. If the `- type:` line is missing, detect the correct type:
62
+
63
+ 1. If the tool section contains a `- command:` line where the value starts with `mcp:` (e.g., `- command: mcp:linear`), insert `- type: mcp` immediately after the `- command:` line.
64
+ 2. Else, if the tool section contains a `- base_url:` line:
65
+ - If the capabilities section contains entries that look like GraphQL queries (contain `query {` or `mutation {`), insert `- type: graphql` immediately after `## <tool_name>` (REST/GraphQL tools have no `- command:` line).
66
+ - Otherwise, insert `- type: rest` immediately after `## <tool_name>`.
67
+ 3. Else (no `mcp:` prefix, no `base_url` field), insert `- type: cli` immediately after the `- command:` line.
68
+
69
+ Write the updated file back with the Write tool. If any changes were made, commit:
70
+ ```bash
71
+ git -C <storage_repo> add -A
72
+ git -C <storage_repo> diff --cached --quiet || git -C <storage_repo> commit -m "donna(migrate): backfill tool types on existing tools"
73
+ ```
74
+
75
+ If `auto_push` is true in config, also push.
76
+
57
77
  After processing all pending migrations, update `~/.donna/state.md` with the Write tool: remove the completed entries from `pending_migrations`. If no entries remain, write:
58
78
  ```markdown
59
79
  ---
@@ -69,7 +89,7 @@ Read `<storage_repo>/donna/tools.md` with the Read tool. If the file does not ex
69
89
  ```
70
90
  Stop.
71
91
 
72
- Parse each tool section (starting with `## <tool_name>`). For each tool, extract the `command` field and the capabilities list under `### Capabilities`.
92
+ Parse each tool section (starting with `## <tool_name>`). For each tool, extract the `type` field (if absent, treat as "cli"), the `command` field, and the capabilities list under `### Capabilities`.
73
93
 
74
94
  Store the parsed tools and their capabilities as `<registered_tools>`.
75
95
  </step>
@@ -101,7 +121,27 @@ If the `## From Tools` section does not exist in today's file, set `<existing_to
101
121
  </step>
102
122
 
103
123
  <step name="pull-fresh-data">
104
- For each tool in `<registered_tools>`, for each capability:
124
+ **If only one tool is registered**, run it directly (no Task spawning needed) using the type-aware execution logic below.
125
+
126
+ **If multiple tools are registered**, spawn one Task agent per tool. Each agent receives:
127
+
128
+ - The tool name, type, and its capabilities list
129
+ - For REST/GraphQL tools: the base_url, auth_header, and auth_secret fields
130
+ - For MCP tools: the capability names with mcp: prefix
131
+ - Instructions to execute all capabilities and return results as a structured list
132
+ - Instructions to NEVER write to any file or run git commands
133
+
134
+ **CRITICAL constraints for Task agents:**
135
+ - Agents return raw task lists and warnings ONLY
136
+ - Agents must NOT write to any file (no Write tool calls to daily file)
137
+ - Agents must NOT run git commands (SSH signing constraint from CLAUDE.md)
138
+ - All file writing happens in the main workflow after agents return
139
+
140
+ **Global timeout:** Wait for all Task agents to complete, up to 2 minutes total. After 2 minutes, collect whatever results have been returned and treat non-responding tools as failed with warning: `! <tool_name>: timed out (2-minute batch limit)`.
141
+
142
+ **Type-aware execution within each agent (or direct execution for single tool):**
143
+
144
+ For `type: cli` capabilities (format: `<name>: <cli_invocation>`):
105
145
 
106
146
  Run the capability command via Bash with a 10-second timeout:
107
147
  ```bash
@@ -133,6 +173,41 @@ For other tools: use Claude's understanding to extract task-like items from the
133
173
  ```
134
174
  Continue to the next capability. Never retry.
135
175
 
176
+ For `type: rest` capabilities (format: `<name>: <METHOD> /path`):
177
+ 1. Read `<storage_repo>/donna/secrets.md` with the Read tool. Parse key-value pairs from under the frontmatter.
178
+ 2. Resolve the `auth_secret` key to get the actual secret value. If the key is not found in secrets.md or the value is `REPLACE_WITH_YOUR_SECRET`, add warning `! <tool_name>: missing secret <auth_secret> — edit donna/secrets.md` and skip this tool.
179
+ 3. For each capability, run via Bash with a 10-second timeout:
180
+ ```bash
181
+ timeout 10 curl -s -H "<auth_header>: <resolved_secret>" "<base_url><path>" 2>&1
182
+ ```
183
+ 4. Parse the JSON response using Claude's understanding to extract task-like items. Format:
184
+ `- [ ] (<tool_name>) <description> [<identifier>](<url>)`
185
+
186
+ **On any failure** (non-zero exit, timeout, missing secret):
187
+ Add a warning: `! <tool_name>: <error_description>`
188
+ Continue. Never retry.
189
+
190
+ For `type: graphql` capabilities (format: `<name>: <graphql_query>`):
191
+ 1. Same secrets resolution as REST.
192
+ 2. For each capability, run via Bash with a 10-second timeout:
193
+ ```bash
194
+ timeout 10 curl -s -X POST -H "<auth_header>: <resolved_secret>" -H "Content-Type: application/json" -d '{"query":"<graphql_query>"}' "<base_url>" 2>&1
195
+ ```
196
+ 3. Parse the JSON response to extract task-like items. Same format as REST.
197
+
198
+ **On any failure** (non-zero exit, timeout, missing secret):
199
+ Add a warning: `! <tool_name>: <error_description>`
200
+ Continue. Never retry.
201
+
202
+ For `type: mcp` capabilities (format: `<name>: mcp:<server>/<tool>`):
203
+ 1. Invoke the MCP tool directly using Claude's native MCP tool invocation (NOT via Bash).
204
+ 2. Parse the MCP tool's response using Claude's understanding of the tool to extract task-like items. Format:
205
+ `- [ ] (<tool_name>) <description> [<identifier>](<url>)`
206
+
207
+ **On any failure:**
208
+ Add a warning: `! <tool_name>: <error_description>`
209
+ Continue. Never retry.
210
+
136
211
  Store all fresh tasks as `<fresh_tool_tasks>`: a map of URL to task line.
137
212
  Collect all warning messages as `<tool_warnings>`.
138
213
  </step>