@pingvinen/donna-assistant 0.6.0 → 0.8.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 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 CLI tools you already have installed. Register them with:
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
- Donna verifies the tool is installed and authenticated, learns its capabilities, and asks what scope to query (which repos, projects, namespaces). Any CLI tool can be added Donna uses the AI model's knowledge of well-known tools and parses `--help` output for everything else.
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 inspect it to learn its current capabilities. You can also re-learn tools at any time:
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,11 +135,13 @@ 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 tool |
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 |
144
+ | `/donna:focus` | Distill today's tasks into a short prioritized focus list |
128
145
 
129
146
  ## License
130
147
 
@@ -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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pingvinen/donna-assistant",
3
- "version": "0.6.0",
3
+ "version": "0.8.0",
4
4
  "description": "Donna - your AI powered personal assistant",
5
5
  "bin": {
6
6
  "donna-assistant": "./bin/donna-assistant"
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, focus) 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>
@@ -0,0 +1,16 @@
1
+ ---
2
+ name: donna:focus
3
+ description: Distill today's tasks into a short prioritized focus list
4
+ allowed-tools:
5
+ - Read
6
+ - Write
7
+ - Bash
8
+ ---
9
+
10
+ <objective>
11
+ Run the Donna focus workflow.
12
+ </objective>
13
+
14
+ <execution_context>
15
+ @~/.donna/workflows/focus.md
16
+ </execution_context>
@@ -1,7 +1,7 @@
1
1
  # Donna Add-Tool Workflow
2
2
 
3
3
  <objective>
4
- Declare an external CLI tool, verify its installation and authentication, learn its capabilities, and persist the result to tools.md in the storage repo.
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
- Resolve the CLI command — default to the tool name itself. If the tool name is in `<noted_tools>`, pre-fill any context from set-role notes. Use AskUserQuestion to confirm or override the CLI command:
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
- If the user presses enter without typing, use the default. Store the confirmed CLI command as `<command>`.
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 this format:
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>, ...