@pingvinen/donna-assistant 0.6.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.
- package/README.md +21 -5
- package/migrations/003-tool-type-backfill.cjs +36 -0
- package/package.json +1 -1
- package/src/installer.cjs +1 -1
- package/stubs/claude-code/donna/adjust-tool.md +17 -0
- package/workflows/add-tool.md +240 -4
- package/workflows/adjust-tool.md +250 -0
- package/workflows/begin-the-day.md +84 -3
- package/workflows/relearn-tools.md +122 -14
- package/workflows/run-tools.md +77 -2
package/README.md
CHANGED
|
@@ -73,7 +73,14 @@ Re-pulls data from all configured tools. New items appear, resolved items get cl
|
|
|
73
73
|
|
|
74
74
|
## External tools
|
|
75
75
|
|
|
76
|
-
Donna can pull tasks and status from
|
|
76
|
+
Donna can pull tasks and status from external tools you already use. She supports four tool types:
|
|
77
|
+
|
|
78
|
+
- **CLI tools** — shell commands like `gh`, `jira`, `kubectl`
|
|
79
|
+
- **REST APIs** — HTTP endpoints like GitHub API, Slack API
|
|
80
|
+
- **GraphQL APIs** — GraphQL endpoints like Linear, GitHub GraphQL
|
|
81
|
+
- **MCP servers** — Claude Code MCP tools like linear, postgres
|
|
82
|
+
|
|
83
|
+
Register a tool with:
|
|
77
84
|
|
|
78
85
|
```
|
|
79
86
|
/donna:add-tool gh
|
|
@@ -81,9 +88,17 @@ Donna can pull tasks and status from CLI tools you already have installed. Regis
|
|
|
81
88
|
|
|
82
89
|
Or call it without arguments — Donna will check your role and suggest tools typically associated with your job.
|
|
83
90
|
|
|
84
|
-
|
|
91
|
+
For CLI tools, Donna verifies installation and authentication, learns capabilities, and asks what scope to query. For REST and GraphQL APIs, Donna sets up secure secret management (via a gitignored `secrets.md` file) and validates API connectivity. MCP servers are configured through Claude Code settings.
|
|
92
|
+
|
|
93
|
+
When multiple tools are registered, Donna runs them in parallel — one agent per tool — so your morning brief stays fast regardless of how many tools you have.
|
|
94
|
+
|
|
95
|
+
Edit a tool's configuration (scope, capabilities, auth, command, type) at any time:
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
/donna:adjust-tool
|
|
99
|
+
```
|
|
85
100
|
|
|
86
|
-
If a tool version is newer than what the AI model knows, Donna will
|
|
101
|
+
If a CLI tool version is newer than what the AI model knows, Donna will re-learn its capabilities:
|
|
87
102
|
|
|
88
103
|
```
|
|
89
104
|
/donna:relearn-tools
|
|
@@ -120,9 +135,10 @@ Most commands are safe to run again. Want to update your role? Run `/donna:set-r
|
|
|
120
135
|
| `/donna:begin-the-day` | Morning brief with carry-forward, recurring tasks, tool data |
|
|
121
136
|
| `/donna:add-task` | Capture a task instantly |
|
|
122
137
|
| `/donna:done` | Mark a task complete |
|
|
123
|
-
| `/donna:add-tool` | Register an external CLI
|
|
138
|
+
| `/donna:add-tool` | Register an external tool (CLI, REST API, GraphQL API, MCP server) |
|
|
139
|
+
| `/donna:adjust-tool` | Edit a tool's configuration (scope, capabilities, auth, command, type) |
|
|
124
140
|
| `/donna:run-tools` | Refresh tool data mid-day |
|
|
125
|
-
| `/donna:relearn-tools` | Update tool knowledge after upgrades |
|
|
141
|
+
| `/donna:relearn-tools` | Update CLI tool knowledge after upgrades |
|
|
126
142
|
| `/donna:help` | Conversational troubleshooting for config, storage, or skill issues |
|
|
127
143
|
| `/donna:contribute-idea` | Submit a feature idea or bug report via GitHub Issues |
|
|
128
144
|
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
version: "0.7.0",
|
|
5
|
+
description: "Backfill type: cli on existing tool sections in tools.md",
|
|
6
|
+
up(ctx) {
|
|
7
|
+
// tools.md lives in the user's storage repo, which is not accessible
|
|
8
|
+
// from the migration context. We write a pending flag to state.md so that
|
|
9
|
+
// workflows can detect and execute the backfill on next skill run.
|
|
10
|
+
const statePath = ctx.path.join(ctx.donnaDir, "state.md");
|
|
11
|
+
|
|
12
|
+
if (ctx.fs.existsSync(statePath)) {
|
|
13
|
+
const content = ctx.fs.readFileSync(statePath, "utf8");
|
|
14
|
+
if (content.includes("backfill-tool-type")) {
|
|
15
|
+
// Already queued — idempotent, nothing to do
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (ctx.fs.existsSync(statePath)) {
|
|
21
|
+
// Append to existing pending_migrations list
|
|
22
|
+
const existing = ctx.fs.readFileSync(statePath, "utf8");
|
|
23
|
+
const updated = existing.replace(
|
|
24
|
+
/^(pending_migrations:\n(?:\s+-\s+.*\n)*)/m,
|
|
25
|
+
"$1 - backfill-tool-type\n",
|
|
26
|
+
);
|
|
27
|
+
if (updated !== existing) {
|
|
28
|
+
ctx.fs.writeFileSync(statePath, updated, "utf8");
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const pendingFlag = "---\npending_migrations:\n - backfill-tool-type\n---\n";
|
|
34
|
+
ctx.fs.writeFileSync(statePath, pendingFlag, "utf8");
|
|
35
|
+
},
|
|
36
|
+
};
|
package/package.json
CHANGED
package/src/installer.cjs
CHANGED
|
@@ -79,7 +79,7 @@ async function run(options = {}) {
|
|
|
79
79
|
for (const provider of detected) {
|
|
80
80
|
fs.cpSync(provider.stubSource, provider.stubTarget, { recursive: true });
|
|
81
81
|
output.success(
|
|
82
|
-
`Copied donna skills (setup, add-task, done, set-role, begin-the-day, add-tool, relearn-tools, run-tools, help, contribute-idea) to ${provider.stubTarget}`,
|
|
82
|
+
`Copied donna skills (setup, add-task, done, set-role, begin-the-day, add-tool, relearn-tools, run-tools, help, contribute-idea, adjust-tool) to ${provider.stubTarget}`,
|
|
83
83
|
);
|
|
84
84
|
}
|
|
85
85
|
} else {
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: donna:adjust-tool
|
|
3
|
+
description: Edit an existing tool's configuration — scope, capabilities, auth, or command
|
|
4
|
+
allowed-tools:
|
|
5
|
+
- Read
|
|
6
|
+
- Write
|
|
7
|
+
- Bash
|
|
8
|
+
- AskUserQuestion
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
<objective>
|
|
12
|
+
Run the Donna adjust-tool workflow. Edit an existing registered tool's configuration.
|
|
13
|
+
</objective>
|
|
14
|
+
|
|
15
|
+
<execution_context>
|
|
16
|
+
@~/.donna/workflows/adjust-tool.md
|
|
17
|
+
</execution_context>
|
package/workflows/add-tool.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Donna Add-Tool Workflow
|
|
2
2
|
|
|
3
3
|
<objective>
|
|
4
|
-
Declare an external CLI
|
|
4
|
+
Declare an external tool (CLI, REST API, GraphQL API, or MCP server), verify its connectivity, learn its capabilities, and persist the result to tools.md in the storage repo.
|
|
5
5
|
</objective>
|
|
6
6
|
|
|
7
7
|
<step name="read-config">
|
|
@@ -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
|
---
|
|
@@ -84,17 +104,43 @@ What tool would you like to add? (e.g. gh, jira, kubectl)
|
|
|
84
104
|
```
|
|
85
105
|
|
|
86
106
|
Store the answer as `<tool_name>`.
|
|
107
|
+
</step>
|
|
108
|
+
|
|
109
|
+
<step name="ask-tool-type">
|
|
110
|
+
Use AskUserQuestion:
|
|
111
|
+
```
|
|
112
|
+
What type of tool is <tool_name>?
|
|
113
|
+
|
|
114
|
+
1. CLI — runs shell commands (e.g., gh, jira, kubectl)
|
|
115
|
+
2. REST API — HTTP endpoints (e.g., GitHub API, Slack API)
|
|
116
|
+
3. GraphQL API — GraphQL endpoint (e.g., Linear, GitHub GraphQL)
|
|
117
|
+
4. MCP server — Claude Code MCP tool (e.g., linear, postgres)
|
|
118
|
+
```
|
|
87
119
|
|
|
88
|
-
|
|
120
|
+
Store the answer as `<tool_type>`: one of `cli`, `rest`, `graphql`, `mcp`.
|
|
89
121
|
|
|
122
|
+
**If type is `cli`:** Use AskUserQuestion to confirm or override the CLI command:
|
|
90
123
|
```
|
|
91
124
|
CLI command for <tool_name>? (default: <tool_name>)
|
|
92
125
|
```
|
|
126
|
+
If the tool name is in `<noted_tools>`, pre-fill any context from set-role notes. If the user presses enter without typing, use the default. Store the confirmed CLI command as `<command>`.
|
|
127
|
+
|
|
128
|
+
**If type is `rest` or `graphql`:**
|
|
93
129
|
|
|
94
|
-
|
|
130
|
+
The base URL is the root API endpoint (for example, https://api.github.com for GitHub REST or https://api.linear.app/graphql for Linear). Guide the user if they seem unsure, but do not include examples in the AskUserQuestion prompt text — inline examples render as picker options in Claude Code.
|
|
131
|
+
|
|
132
|
+
Use AskUserQuestion:
|
|
133
|
+
```
|
|
134
|
+
What is the base URL for <tool_name>?
|
|
135
|
+
```
|
|
136
|
+
Store as `<base_url>`. Set `<command>` to `<base_url>` (for display purposes).
|
|
137
|
+
|
|
138
|
+
**If type is `mcp`:** Skip the command question. Set `<command>` to `mcp`.
|
|
95
139
|
</step>
|
|
96
140
|
|
|
97
141
|
<step name="verify-installation">
|
|
142
|
+
If `<tool_type>` is not `cli`, skip this step.
|
|
143
|
+
|
|
98
144
|
Run via Bash:
|
|
99
145
|
```bash
|
|
100
146
|
which <command> && echo "INSTALLED=true" || echo "INSTALLED=false"
|
|
@@ -115,6 +161,8 @@ Store the output as `<version>`. If the command does not support `--version`, st
|
|
|
115
161
|
</step>
|
|
116
162
|
|
|
117
163
|
<step name="auth-test">
|
|
164
|
+
**If `<tool_type>` is `cli`:**
|
|
165
|
+
|
|
118
166
|
For well-known tools, run the appropriate auth test via Bash with a 10-second timeout:
|
|
119
167
|
|
|
120
168
|
- `gh`: `timeout 10 gh api user --jq '.login' 2>&1`
|
|
@@ -132,9 +180,66 @@ Fix instructions per tool:
|
|
|
132
180
|
- `kubectl` → check your kubeconfig
|
|
133
181
|
|
|
134
182
|
Continue (do not stop — user may want to save the tool despite auth issues).
|
|
183
|
+
|
|
184
|
+
**If `<tool_type>` is `rest` or `graphql`:**
|
|
185
|
+
|
|
186
|
+
Common auth headers include Authorization (for Bearer tokens) and X-API-Key. Do not include examples in the prompt text.
|
|
187
|
+
|
|
188
|
+
Use AskUserQuestion to ask for the auth header name:
|
|
189
|
+
```
|
|
190
|
+
What auth header does <tool_name> use? Default: Authorization
|
|
191
|
+
```
|
|
192
|
+
Store as `<auth_header>` (default: `Authorization` if blank).
|
|
193
|
+
|
|
194
|
+
The key name should match the service convention (e.g., GITHUB_TOKEN, SLACK_TOKEN, LINEAR_API_KEY). Guide the user if needed but keep examples out of the prompt.
|
|
195
|
+
|
|
196
|
+
Use AskUserQuestion to ask for the secret key name:
|
|
197
|
+
```
|
|
198
|
+
What should the secret key be called in secrets.md for <tool_name>?
|
|
199
|
+
```
|
|
200
|
+
Store as `<auth_secret>`.
|
|
201
|
+
|
|
202
|
+
**Set up secrets.md:**
|
|
203
|
+
Read `<storage_repo>/donna/secrets.md` with the Read tool. If the file does not exist, create it with:
|
|
204
|
+
```markdown
|
|
205
|
+
---
|
|
206
|
+
# secrets.md -- managed by user, never by donna
|
|
207
|
+
# Auto-added to .gitignore
|
|
208
|
+
---
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Check if `<auth_secret>` already appears in secrets.md. If not, append a placeholder line:
|
|
212
|
+
```
|
|
213
|
+
<auth_secret>: REPLACE_WITH_YOUR_SECRET
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
Write the updated secrets.md.
|
|
217
|
+
|
|
218
|
+
**Ensure secrets.md is gitignored:**
|
|
219
|
+
Read `<storage_repo>/.gitignore` with the Read tool. If the file does not exist or does not contain `donna/secrets.md`, append `donna/secrets.md` to `.gitignore` and write back. If `.gitignore` does not exist, create it with `donna/secrets.md` as its sole content.
|
|
220
|
+
|
|
221
|
+
**Validate API connectivity:**
|
|
222
|
+
Read `<storage_repo>/donna/secrets.md` to get the current value for `<auth_secret>`. If the value is `REPLACE_WITH_YOUR_SECRET` or the key is absent, print:
|
|
223
|
+
```
|
|
224
|
+
! No secret set for <auth_secret> — edit donna/secrets.md before testing connectivity.
|
|
225
|
+
```
|
|
226
|
+
Skip validation.
|
|
227
|
+
|
|
228
|
+
If a real secret value exists, run via Bash:
|
|
229
|
+
```bash
|
|
230
|
+
curl -s -o /dev/null -w "%{http_code}" -H "<auth_header>: <resolved_secret>" <base_url> 2>&1
|
|
231
|
+
```
|
|
232
|
+
- 200-299: print `✓ API reachable at <base_url>`
|
|
233
|
+
- 401/403: print `! Authentication failed — check <auth_secret> in donna/secrets.md`
|
|
234
|
+
- Other/timeout: print `! Could not reach <base_url>`
|
|
235
|
+
|
|
236
|
+
**If `<tool_type>` is `mcp`:**
|
|
237
|
+
Print `ℹ MCP server auth is managed in Claude Code settings. Skipping auth test.`
|
|
135
238
|
</step>
|
|
136
239
|
|
|
137
240
|
<step name="ask-scope">
|
|
241
|
+
**If `<tool_type>` is `cli`:**
|
|
242
|
+
|
|
138
243
|
Ask the user to define the scope/context for this tool. Different tools need different scope:
|
|
139
244
|
|
|
140
245
|
- **gh**: Which GitHub orgs or repos to pull from (e.g., `mycompany`, `mycompany/api mycompany/web`)
|
|
@@ -149,10 +254,28 @@ What scope should Donna use for <tool_name>?
|
|
|
149
254
|
Leave blank for no filtering.
|
|
150
255
|
```
|
|
151
256
|
|
|
257
|
+
**If `<tool_type>` is `rest` or `graphql`:**
|
|
258
|
+
|
|
259
|
+
Use AskUserQuestion:
|
|
260
|
+
```
|
|
261
|
+
What scope should Donna use for <tool_name>? (e.g., specific endpoints or resource filters to apply)
|
|
262
|
+
Leave blank for no filtering.
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
**If `<tool_type>` is `mcp`:**
|
|
266
|
+
|
|
267
|
+
Use AskUserQuestion:
|
|
268
|
+
```
|
|
269
|
+
What scope should Donna use for <tool_name>? (e.g., specific resources to monitor)
|
|
270
|
+
Leave blank for no filtering.
|
|
271
|
+
```
|
|
272
|
+
|
|
152
273
|
Store the answer as `<scope>`. If blank, set to empty string.
|
|
153
274
|
</step>
|
|
154
275
|
|
|
155
276
|
<step name="learn-capabilities">
|
|
277
|
+
**If `<tool_type>` is `cli`:**
|
|
278
|
+
|
|
156
279
|
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.
|
|
157
280
|
|
|
158
281
|
**gh (GitHub CLI) — training data baseline:**
|
|
@@ -179,6 +302,50 @@ If `<scope>` is set, replace `--all-namespaces` with `-n <namespace>` for each n
|
|
|
179
302
|
|
|
180
303
|
For **unknown tools**, run `<command> --help 2>&1 | head -80` via Bash and use Claude's understanding to identify 3–5 capabilities relevant to daily task management. If `<scope>` is set, incorporate the scope into the CLI invocations where appropriate. Format each as `name: <cli invocation>`.
|
|
181
304
|
|
|
305
|
+
**If `<tool_type>` is `rest`:**
|
|
306
|
+
|
|
307
|
+
Print to user:
|
|
308
|
+
```
|
|
309
|
+
Each capability is a name and HTTP method + path.
|
|
310
|
+
Format: <name>: <METHOD> /path?params
|
|
311
|
+
Example: list-issues: GET /repos/{owner}/{repo}/issues?state=open
|
|
312
|
+
Example: my-profile: GET /user
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
Use AskUserQuestion:
|
|
316
|
+
```
|
|
317
|
+
Enter capabilities for <tool_name> (one per line, blank line when done):
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
**If `<tool_type>` is `graphql`:**
|
|
321
|
+
|
|
322
|
+
Print to user:
|
|
323
|
+
```
|
|
324
|
+
Each capability is a name and a GraphQL query (single line).
|
|
325
|
+
Format: <name>: query { ... }
|
|
326
|
+
Example: my-issues: query { viewer { issues(first: 20, states: OPEN) { nodes { title url } } } }
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
Use AskUserQuestion:
|
|
330
|
+
```
|
|
331
|
+
Enter capabilities for <tool_name> (one per line, blank line when done):
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
**If `<tool_type>` is `mcp`:**
|
|
335
|
+
|
|
336
|
+
Print to user:
|
|
337
|
+
```
|
|
338
|
+
Each capability is a name and an MCP tool reference.
|
|
339
|
+
Format: <name>: mcp:<server_name>/<tool_name>
|
|
340
|
+
Example: list-issues: mcp:linear/list_issues
|
|
341
|
+
Example: search-docs: mcp:notion/search
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
Use AskUserQuestion:
|
|
345
|
+
```
|
|
346
|
+
Enter capabilities for <tool_name> (one per line, blank line when done):
|
|
347
|
+
```
|
|
348
|
+
|
|
182
349
|
Store the full list as `<available_capabilities>`.
|
|
183
350
|
</step>
|
|
184
351
|
|
|
@@ -202,11 +369,14 @@ Read `<storage_repo>/donna/tools.md` with the Read tool. If the file does not ex
|
|
|
202
369
|
---
|
|
203
370
|
```
|
|
204
371
|
|
|
205
|
-
Upsert (not overwrite) the tool's section. Each tool section has
|
|
372
|
+
Upsert (not overwrite) the tool's section. Each tool section has a type-specific format:
|
|
373
|
+
|
|
374
|
+
**CLI tools:**
|
|
206
375
|
```markdown
|
|
207
376
|
## <tool_name>
|
|
208
377
|
|
|
209
378
|
- command: <command>
|
|
379
|
+
- type: cli
|
|
210
380
|
- version: <version>
|
|
211
381
|
- learned: <today's date YYYY-MM-DD>
|
|
212
382
|
- auth_test: <auth_test_command or "none">
|
|
@@ -216,6 +386,47 @@ Upsert (not overwrite) the tool's section. Each tool section has this format:
|
|
|
216
386
|
- <capability_name>: <cli_invocation>
|
|
217
387
|
```
|
|
218
388
|
|
|
389
|
+
**REST API tools:**
|
|
390
|
+
```markdown
|
|
391
|
+
## <tool_name>
|
|
392
|
+
|
|
393
|
+
- type: rest
|
|
394
|
+
- base_url: <base_url>
|
|
395
|
+
- auth_header: <auth_header>
|
|
396
|
+
- auth_secret: <auth_secret>
|
|
397
|
+
- scope: <scope or "none">
|
|
398
|
+
- learned: <today's date YYYY-MM-DD>
|
|
399
|
+
|
|
400
|
+
### Capabilities
|
|
401
|
+
- <capability_name>: <METHOD> /path
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
**GraphQL API tools:**
|
|
405
|
+
```markdown
|
|
406
|
+
## <tool_name>
|
|
407
|
+
|
|
408
|
+
- type: graphql
|
|
409
|
+
- base_url: <base_url>
|
|
410
|
+
- auth_header: <auth_header>
|
|
411
|
+
- auth_secret: <auth_secret>
|
|
412
|
+
- scope: <scope or "none">
|
|
413
|
+
- learned: <today's date YYYY-MM-DD>
|
|
414
|
+
|
|
415
|
+
### Capabilities
|
|
416
|
+
- <capability_name>: <graphql_query>
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
**MCP server tools:**
|
|
420
|
+
```markdown
|
|
421
|
+
## <tool_name>
|
|
422
|
+
|
|
423
|
+
- type: mcp
|
|
424
|
+
- learned: <today's date YYYY-MM-DD>
|
|
425
|
+
|
|
426
|
+
### Capabilities
|
|
427
|
+
- <capability_name>: mcp:<server>/<tool>
|
|
428
|
+
```
|
|
429
|
+
|
|
219
430
|
If a section for this tool already exists in tools.md, replace it entirely. Write the full file back with the Write tool. Preserve all other tool sections unchanged.
|
|
220
431
|
</step>
|
|
221
432
|
|
|
@@ -244,6 +455,8 @@ git -C <storage_repo> push
|
|
|
244
455
|
</step>
|
|
245
456
|
|
|
246
457
|
<step name="confirm">
|
|
458
|
+
**If `<tool_type>` is `cli`:**
|
|
459
|
+
|
|
247
460
|
Print:
|
|
248
461
|
```
|
|
249
462
|
✓ Added <tool_name> to tools registry
|
|
@@ -254,6 +467,29 @@ Print:
|
|
|
254
467
|
Run /donna:begin-the-day to see tool data in your daily brief.
|
|
255
468
|
```
|
|
256
469
|
|
|
470
|
+
**If `<tool_type>` is `rest` or `graphql`:**
|
|
471
|
+
|
|
472
|
+
Print:
|
|
473
|
+
```
|
|
474
|
+
✓ Added <tool_name> to tools registry (type: <tool_type>)
|
|
475
|
+
Base URL: <base_url>
|
|
476
|
+
Capabilities: <count> configured
|
|
477
|
+
Secrets: Edit donna/secrets.md to set <auth_secret>
|
|
478
|
+
|
|
479
|
+
Run /donna:begin-the-day to see tool data in your daily brief.
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
**If `<tool_type>` is `mcp`:**
|
|
483
|
+
|
|
484
|
+
Print:
|
|
485
|
+
```
|
|
486
|
+
✓ Added <tool_name> to tools registry (type: mcp)
|
|
487
|
+
Capabilities: <count> configured
|
|
488
|
+
|
|
489
|
+
Ensure the MCP server is configured in Claude Code settings.
|
|
490
|
+
Run /donna:begin-the-day to see tool data in your daily brief.
|
|
491
|
+
```
|
|
492
|
+
|
|
257
493
|
If in batch mode, repeat steps ask-tool-name through confirm for each remaining tool in `<noted_tools>`, then print a final summary:
|
|
258
494
|
```
|
|
259
495
|
✓ Configured <N> tools: <tool_name_1>, <tool_name_2>, ...
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
# Donna Adjust-Tool Workflow
|
|
2
|
+
|
|
3
|
+
<objective>
|
|
4
|
+
Edit an existing registered tool's configuration — scope, capabilities, auth/secrets, command, or type.
|
|
5
|
+
</objective>
|
|
6
|
+
|
|
7
|
+
<step name="read-config">
|
|
8
|
+
Read `~/.config/donna/config.md`.
|
|
9
|
+
|
|
10
|
+
If the file does not exist, print:
|
|
11
|
+
```
|
|
12
|
+
✗ Donna is not configured. Run /donna:setup first.
|
|
13
|
+
```
|
|
14
|
+
Stop.
|
|
15
|
+
|
|
16
|
+
Extract the `storage_repo`, `daily_folder` (default: `daily`), and `auto_push` (default: false) fields from the YAML frontmatter.
|
|
17
|
+
|
|
18
|
+
**Obsidian sync:** Check if `<storage_repo>/.obsidian/daily-notes.json` exists.
|
|
19
|
+
- If it exists and has a `folder` field that differs from `<daily_folder>`: update `<daily_folder>` to match Obsidian's value, and update `~/.config/donna/config.md` with the new `daily_folder`. Print `✓ Synced daily folder with Obsidian: <daily_folder>`.
|
|
20
|
+
- If `<storage_repo>/.obsidian/` exists but `daily-notes.json` does not exist or has no `folder` field: write `<storage_repo>/.obsidian/daily-notes.json` with `{"folder":"<daily_folder>"}`. Print `✓ Configured Obsidian daily notes to use <daily_folder>/`.
|
|
21
|
+
- Otherwise: do nothing.
|
|
22
|
+
</step>
|
|
23
|
+
|
|
24
|
+
<step name="check-pending-migrations">
|
|
25
|
+
Read `~/.donna/state.md` with the Read tool. If the file does not exist or has no `pending_migrations` field in its YAML frontmatter, skip this step.
|
|
26
|
+
|
|
27
|
+
For each entry in `pending_migrations`:
|
|
28
|
+
|
|
29
|
+
**`move-standing-files`:** Move standing files from storage repo root to donna/ subfolder.
|
|
30
|
+
|
|
31
|
+
Run via Bash:
|
|
32
|
+
```bash
|
|
33
|
+
STORAGE_REPO="<storage_repo>"
|
|
34
|
+
DONNA_DIR="$STORAGE_REPO/donna"
|
|
35
|
+
MOVED=0
|
|
36
|
+
|
|
37
|
+
mkdir -p "$DONNA_DIR"
|
|
38
|
+
for FILE in role.md recurring.md role-research.md; do
|
|
39
|
+
if [ -f "$STORAGE_REPO/$FILE" ] && [ ! -f "$DONNA_DIR/$FILE" ]; then
|
|
40
|
+
mv "$STORAGE_REPO/$FILE" "$DONNA_DIR/$FILE"
|
|
41
|
+
echo "Moved $FILE to donna/$FILE"
|
|
42
|
+
MOVED=$((MOVED + 1))
|
|
43
|
+
fi
|
|
44
|
+
done
|
|
45
|
+
|
|
46
|
+
echo "MOVED=$MOVED"
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
If MOVED > 0, commit the move:
|
|
50
|
+
```bash
|
|
51
|
+
git -C <storage_repo> add -A
|
|
52
|
+
git -C <storage_repo> diff --cached --quiet || git -C <storage_repo> commit -m "donna(migrate): move standing files to donna/ subfolder"
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
If `auto_push` is true in config, also push.
|
|
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
|
+
|
|
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:
|
|
78
|
+
```markdown
|
|
79
|
+
---
|
|
80
|
+
pending_migrations: []
|
|
81
|
+
---
|
|
82
|
+
```
|
|
83
|
+
</step>
|
|
84
|
+
|
|
85
|
+
<step name="read-tools-md">
|
|
86
|
+
Read `<storage_repo>/donna/tools.md` with the Read tool. If the file does not exist or has no tool sections, print:
|
|
87
|
+
```
|
|
88
|
+
! No tools registered. Run /donna:add-tool first.
|
|
89
|
+
```
|
|
90
|
+
Stop.
|
|
91
|
+
|
|
92
|
+
Parse each tool section (starting with `## <tool_name>`). For each tool, extract the `type` field (if absent, treat as "cli"), `command`, `version`, `learned`, `auth_test`, `scope`, and capabilities list under `### Capabilities`.
|
|
93
|
+
|
|
94
|
+
Store as `<registered_tools>`.
|
|
95
|
+
</step>
|
|
96
|
+
|
|
97
|
+
<step name="select-tool">
|
|
98
|
+
If a tool name was provided as argument (e.g., `/donna:adjust-tool gh`), look it up in `<registered_tools>`. If not found, print `! Tool "<name>" not found in tools.md` and stop.
|
|
99
|
+
|
|
100
|
+
If no argument was provided, list all registered tools via AskUserQuestion:
|
|
101
|
+
```
|
|
102
|
+
Which tool would you like to adjust?
|
|
103
|
+
|
|
104
|
+
<numbered list of tool names from registered_tools>
|
|
105
|
+
```
|
|
106
|
+
Store the selected tool as `<selected_tool>`.
|
|
107
|
+
</step>
|
|
108
|
+
|
|
109
|
+
<step name="show-current-config">
|
|
110
|
+
Display the current configuration of `<selected_tool>`:
|
|
111
|
+
```
|
|
112
|
+
Current configuration for <tool_name>:
|
|
113
|
+
|
|
114
|
+
command: <command>
|
|
115
|
+
type: <type>
|
|
116
|
+
version: <version>
|
|
117
|
+
learned: <learned>
|
|
118
|
+
auth_test: <auth_test>
|
|
119
|
+
scope: <scope>
|
|
120
|
+
|
|
121
|
+
Capabilities:
|
|
122
|
+
- <name>: <invocation>
|
|
123
|
+
- ...
|
|
124
|
+
```
|
|
125
|
+
</step>
|
|
126
|
+
|
|
127
|
+
<step name="ask-what-to-change">
|
|
128
|
+
Use AskUserQuestion:
|
|
129
|
+
```
|
|
130
|
+
What would you like to change?
|
|
131
|
+
|
|
132
|
+
1. scope — filtering context (orgs, repos, projects, namespaces)
|
|
133
|
+
2. capabilities — add, remove, or modify capability commands
|
|
134
|
+
3. command — the CLI command or base URL
|
|
135
|
+
4. auth — auth test command or API secrets
|
|
136
|
+
5. type — tool type (cli, rest, graphql, mcp)
|
|
137
|
+
```
|
|
138
|
+
Store as `<change_choice>`.
|
|
139
|
+
</step>
|
|
140
|
+
|
|
141
|
+
<step name="apply-change">
|
|
142
|
+
Based on `<change_choice>`:
|
|
143
|
+
|
|
144
|
+
**1. scope:**
|
|
145
|
+
Show current scope. Use AskUserQuestion: `New scope for <tool_name>? (current: <scope>)`. Store new value.
|
|
146
|
+
Then ask via AskUserQuestion: `Scope changed. Re-learn capabilities with new scope? (yes/no)`.
|
|
147
|
+
If yes, run the same learn-capabilities logic as add-tool.md (well-known baselines for gh/jira/kubectl, `--help` parse for unknown tools), incorporating the new scope into CLI invocations.
|
|
148
|
+
|
|
149
|
+
**2. capabilities:**
|
|
150
|
+
Show current capabilities numbered. Use AskUserQuestion:
|
|
151
|
+
```
|
|
152
|
+
Current capabilities:
|
|
153
|
+
1. <name>: <invocation>
|
|
154
|
+
2. ...
|
|
155
|
+
|
|
156
|
+
Type "remove <number>" to remove, "add <name>: <command>" to add, or "edit <number> <new_command>" to modify.
|
|
157
|
+
```
|
|
158
|
+
Apply the change. Allow multiple edits — keep asking until user says "done".
|
|
159
|
+
|
|
160
|
+
**3. command:**
|
|
161
|
+
Use AskUserQuestion: `New command for <tool_name>? (current: <command>)`. Store new value.
|
|
162
|
+
Verify installation: `which <new_command>` via Bash. Print result.
|
|
163
|
+
|
|
164
|
+
**4. auth:**
|
|
165
|
+
For type=cli: Use AskUserQuestion to update auth_test command.
|
|
166
|
+
For type=rest|graphql: Print `Edit your secrets in <storage_repo>/donna/secrets.md directly. The auth_secret field references the key name in that file.` Use AskUserQuestion to update `auth_secret` field name if needed.
|
|
167
|
+
For type=mcp: Print `MCP server auth is managed in Claude Code settings, not in Donna.`
|
|
168
|
+
|
|
169
|
+
**5. type:**
|
|
170
|
+
Use AskUserQuestion:
|
|
171
|
+
```
|
|
172
|
+
What is the correct type for <tool_name>? (cli, rest, graphql, mcp) Current: <type>
|
|
173
|
+
```
|
|
174
|
+
Store new value as `<new_type>`.
|
|
175
|
+
|
|
176
|
+
If `<new_type>` differs from `<type>`, check for capability format mismatches:
|
|
177
|
+
|
|
178
|
+
**Detect format mismatches:**
|
|
179
|
+
For each capability line (`- <name>: <invocation>`), check if the invocation matches the expected format for `<new_type>`:
|
|
180
|
+
- `cli`: invocation should be a shell command (no `mcp:` prefix, no `GET /` or `POST /` pattern, no `query {` pattern)
|
|
181
|
+
- `rest`: invocation should match `<METHOD> /path` pattern (e.g., `GET /repos/...`)
|
|
182
|
+
- `graphql`: invocation should contain `query {` or `mutation {`
|
|
183
|
+
- `mcp`: invocation should match `mcp:<server>/<tool>` pattern
|
|
184
|
+
|
|
185
|
+
If ANY capability does not match the expected format for `<new_type>`, print:
|
|
186
|
+
|
|
187
|
+
```
|
|
188
|
+
⚠ Capability format mismatch detected. Current capabilities are in <type> format but type is changing to <new_type>.
|
|
189
|
+
|
|
190
|
+
Mismatched capabilities:
|
|
191
|
+
<list each mismatched capability with its current invocation>
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
Use AskUserQuestion:
|
|
195
|
+
```
|
|
196
|
+
How would you like to fix the capabilities?
|
|
197
|
+
```
|
|
198
|
+
Suggest these options:
|
|
199
|
+
1. Re-enter capabilities manually (interactive editor)
|
|
200
|
+
2. Clear all capabilities (start fresh with adjust-tool later)
|
|
201
|
+
3. Keep as-is (may cause runtime errors)
|
|
202
|
+
|
|
203
|
+
If option 1: Present the same interactive capabilities editing loop (show numbered list, accept "remove N", "add name: invocation", "edit N new_invocation", "done"). Pre-populate with existing capability NAMES but empty invocations so the user only needs to type the new format.
|
|
204
|
+
|
|
205
|
+
If option 2: Clear the capabilities section entirely. Print `✓ Capabilities cleared. Run /donna:adjust-tool <tool_name> to add new capabilities.`
|
|
206
|
+
|
|
207
|
+
If option 3: Print `⚠ Keeping mismatched capabilities — runtime errors may occur.`
|
|
208
|
+
|
|
209
|
+
**Update structural fields when type changes:**
|
|
210
|
+
- Changing TO rest/graphql: ensure `base_url`, `auth_header`, `auth_secret` fields exist. If missing, prompt for them (same prompts as add-tool).
|
|
211
|
+
- Changing TO mcp: remove `command`, `version`, `base_url`, `auth_header`, `auth_secret` fields if present.
|
|
212
|
+
- Changing TO cli: ensure `command`, `version` fields exist. If missing, prompt for command and run version check.
|
|
213
|
+
- Changing FROM rest/graphql: remove `base_url`, `auth_header`, `auth_secret` fields.
|
|
214
|
+
</step>
|
|
215
|
+
|
|
216
|
+
<step name="write-tools-md">
|
|
217
|
+
Read `<storage_repo>/donna/tools.md`. Update only the `<selected_tool>` section with the changed fields. Preserve all other tool sections unchanged. Write the full file back with the Write tool.
|
|
218
|
+
</step>
|
|
219
|
+
|
|
220
|
+
<step name="git-commit">
|
|
221
|
+
Run via Bash:
|
|
222
|
+
```bash
|
|
223
|
+
git -C <storage_repo> add -A
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
Check whether there is anything to commit:
|
|
227
|
+
```bash
|
|
228
|
+
git -C <storage_repo> status --porcelain
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
If the output is empty, skip the commit and continue.
|
|
232
|
+
|
|
233
|
+
Otherwise, run:
|
|
234
|
+
```bash
|
|
235
|
+
git -C <storage_repo> commit -m "donna(adjust-tool): updated <tool_name> (<change_description>)"
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
If `auto_push` is true in config, also run:
|
|
239
|
+
```bash
|
|
240
|
+
git -C <storage_repo> push
|
|
241
|
+
```
|
|
242
|
+
</step>
|
|
243
|
+
|
|
244
|
+
<step name="confirm">
|
|
245
|
+
Print:
|
|
246
|
+
```
|
|
247
|
+
! Updated <tool_name>:
|
|
248
|
+
<field>: <old_value> -> <new_value>
|
|
249
|
+
```
|
|
250
|
+
</step>
|
|
@@ -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
|
---
|
|
@@ -132,9 +152,33 @@ Read `<storage_repo>/donna/tools.md` with the Read tool.
|
|
|
132
152
|
|
|
133
153
|
If the file does not exist or has no tool sections (no `## ` headers after the frontmatter), set `<tool_tasks>` to an empty list and `<tool_warnings>` to an empty list. Continue to the next step. Do NOT print any error — tools are optional.
|
|
134
154
|
|
|
135
|
-
|
|
155
|
+
Parse each tool section (starting with `## <tool_name>`). For each tool, extract the `type` field (if absent, treat as "cli"), the `command` field (or `base_url` for rest/graphql), and the capabilities list under `### Capabilities`.
|
|
156
|
+
|
|
157
|
+
Store the parsed tools and their capabilities as `<registered_tools>`.
|
|
158
|
+
|
|
159
|
+
**If only one tool is registered**, run it directly (no Task spawning needed) using the type-aware execution logic below.
|
|
160
|
+
|
|
161
|
+
**If multiple tools are registered**, spawn one Task agent per tool. Each agent receives:
|
|
162
|
+
|
|
163
|
+
- The tool name, type, and its capabilities list
|
|
164
|
+
- For REST/GraphQL tools: the base_url, auth_header, and auth_secret fields
|
|
165
|
+
- For MCP tools: the capability names with mcp: prefix
|
|
166
|
+
- Instructions to execute all capabilities and return results as a structured list
|
|
167
|
+
- Instructions to NEVER write to any file or run git commands
|
|
168
|
+
|
|
169
|
+
**CRITICAL constraints for Task agents:**
|
|
170
|
+
- Agents return raw task lists and warnings ONLY
|
|
171
|
+
- Agents must NOT write to any file (no Write tool calls to daily file)
|
|
172
|
+
- Agents must NOT run git commands (SSH signing constraint from CLAUDE.md)
|
|
173
|
+
- All file writing happens in the main workflow after agents return
|
|
174
|
+
|
|
175
|
+
**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)`.
|
|
136
176
|
|
|
137
|
-
|
|
177
|
+
**Type-aware execution within each agent (or direct execution for single tool):**
|
|
178
|
+
|
|
179
|
+
For `type: cli` capabilities (format: `<name>: <cli_invocation>`):
|
|
180
|
+
|
|
181
|
+
Run via Bash with a 10-second timeout:
|
|
138
182
|
```bash
|
|
139
183
|
timeout 10 <cli_invocation> 2>&1
|
|
140
184
|
```
|
|
@@ -161,7 +205,44 @@ Determine the failure type from the exit code and output:
|
|
|
161
205
|
- Exit 127 or "not found" in output: `! <tool_name>: command not found — install <command> first`
|
|
162
206
|
- Other: `! <tool_name>: <first line of stderr>`
|
|
163
207
|
|
|
164
|
-
Add the warning to `<tool_warnings>`. Continue to next capability/tool. Never retry.
|
|
208
|
+
Add the warning to `<tool_warnings>`. Continue to next capability/tool. Never retry.
|
|
209
|
+
|
|
210
|
+
For `type: rest` capabilities (format: `<name>: <METHOD> /path`):
|
|
211
|
+
1. Read `<storage_repo>/donna/secrets.md` with the Read tool. Parse key-value pairs from under the frontmatter.
|
|
212
|
+
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.
|
|
213
|
+
3. For each capability, run via Bash with a 10-second timeout:
|
|
214
|
+
```bash
|
|
215
|
+
timeout 10 curl -s -H "<auth_header>: <resolved_secret>" "<base_url><path>" 2>&1
|
|
216
|
+
```
|
|
217
|
+
4. Parse the JSON response using Claude's understanding to extract task-like items. Format:
|
|
218
|
+
`- [ ] (<tool_name>) <description> [<identifier>](<url>)`
|
|
219
|
+
|
|
220
|
+
**On any failure** (non-zero exit, timeout, missing secret):
|
|
221
|
+
Add a warning: `! <tool_name>: <error_description>`
|
|
222
|
+
Continue. Never retry.
|
|
223
|
+
|
|
224
|
+
For `type: graphql` capabilities (format: `<name>: <graphql_query>`):
|
|
225
|
+
1. Same secrets resolution as REST.
|
|
226
|
+
2. For each capability, run via Bash with a 10-second timeout:
|
|
227
|
+
```bash
|
|
228
|
+
timeout 10 curl -s -X POST -H "<auth_header>: <resolved_secret>" -H "Content-Type: application/json" -d '{"query":"<graphql_query>"}' "<base_url>" 2>&1
|
|
229
|
+
```
|
|
230
|
+
3. Parse the JSON response to extract task-like items. Same format as REST.
|
|
231
|
+
|
|
232
|
+
**On any failure** (non-zero exit, timeout, missing secret):
|
|
233
|
+
Add a warning: `! <tool_name>: <error_description>`
|
|
234
|
+
Continue. Never retry.
|
|
235
|
+
|
|
236
|
+
For `type: mcp` capabilities (format: `<name>: mcp:<server>/<tool>`):
|
|
237
|
+
1. Invoke the MCP tool directly using Claude's native MCP tool invocation (NOT via Bash).
|
|
238
|
+
2. Parse the MCP tool's response using Claude's understanding of the tool to extract task-like items. Format:
|
|
239
|
+
`- [ ] (<tool_name>) <description> [<identifier>](<url>)`
|
|
240
|
+
|
|
241
|
+
**On any failure:**
|
|
242
|
+
Add a warning: `! <tool_name>: <error_description>`
|
|
243
|
+
Continue. Never retry.
|
|
244
|
+
|
|
245
|
+
Tool failures must never block manual tasks, carry-forward, or recurring task processing.
|
|
165
246
|
|
|
166
247
|
Collect all task entries as `<tool_tasks>`.
|
|
167
248
|
Collect all warning messages as `<tool_warnings>`.
|
|
@@ -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
|
-
- `
|
|
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
|
|
83
|
-
|
|
84
|
-
|
|
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
|
-
|
|
164
|
+
<step name="report-unchanged">
|
|
165
|
+
For each tool in `<unchanged_tools>`:
|
|
88
166
|
|
|
89
|
-
If `<
|
|
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
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
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
|
-
|
|
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.
|
package/workflows/run-tools.md
CHANGED
|
@@ -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
|
-
|
|
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>
|