@buehnenproduktionsgesellschaft/donna 0.1.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.
Files changed (154) hide show
  1. package/LICENSE +73 -0
  2. package/README.md +253 -0
  3. package/dist/agents/builtin/research/AGENT.md +53 -0
  4. package/dist/agents/builtin/review/AGENT.md +58 -0
  5. package/dist/agents/global.d.ts +19 -0
  6. package/dist/agents/global.js +54 -0
  7. package/dist/agents/loader.d.ts +9 -0
  8. package/dist/agents/loader.js +75 -0
  9. package/dist/agents/manager.d.ts +52 -0
  10. package/dist/agents/manager.js +221 -0
  11. package/dist/agents/pool.d.ts +29 -0
  12. package/dist/agents/pool.js +159 -0
  13. package/dist/agents/runner.d.ts +8 -0
  14. package/dist/agents/runner.js +239 -0
  15. package/dist/agents/types.d.ts +67 -0
  16. package/dist/agents/types.js +19 -0
  17. package/dist/api/account.d.ts +2 -0
  18. package/dist/api/account.js +32 -0
  19. package/dist/api/client.d.ts +46 -0
  20. package/dist/api/client.js +241 -0
  21. package/dist/api/redact.d.ts +11 -0
  22. package/dist/api/redact.js +47 -0
  23. package/dist/api/tools.d.ts +838 -0
  24. package/dist/api/tools.js +323 -0
  25. package/dist/api/types.d.ts +56 -0
  26. package/dist/api/types.js +1 -0
  27. package/dist/api/usage.d.ts +6 -0
  28. package/dist/api/usage.js +68 -0
  29. package/dist/app-raw.d.ts +6 -0
  30. package/dist/app-raw.js +1607 -0
  31. package/dist/artifacts.d.ts +16 -0
  32. package/dist/artifacts.js +70 -0
  33. package/dist/ask.d.ts +26 -0
  34. package/dist/ask.js +57 -0
  35. package/dist/auth.d.ts +17 -0
  36. package/dist/auth.js +37 -0
  37. package/dist/banner.d.ts +1 -0
  38. package/dist/banner.js +130 -0
  39. package/dist/checker.d.ts +44 -0
  40. package/dist/checker.js +583 -0
  41. package/dist/cli/args.d.ts +34 -0
  42. package/dist/cli/args.js +120 -0
  43. package/dist/cli/login.d.ts +3 -0
  44. package/dist/cli/login.js +51 -0
  45. package/dist/cli/logout.d.ts +3 -0
  46. package/dist/cli/logout.js +27 -0
  47. package/dist/cli/prompt.d.ts +15 -0
  48. package/dist/cli/prompt.js +47 -0
  49. package/dist/cli/subcommands.d.ts +7 -0
  50. package/dist/cli/subcommands.js +55 -0
  51. package/dist/commands.d.ts +20 -0
  52. package/dist/commands.js +115 -0
  53. package/dist/compaction.d.ts +8 -0
  54. package/dist/compaction.js +512 -0
  55. package/dist/config/memory.d.ts +25 -0
  56. package/dist/config/memory.js +131 -0
  57. package/dist/config/permissions.d.ts +14 -0
  58. package/dist/config/permissions.js +164 -0
  59. package/dist/config/schema.d.ts +29 -0
  60. package/dist/config/schema.js +15 -0
  61. package/dist/config/secure-fs.d.ts +27 -0
  62. package/dist/config/secure-fs.js +94 -0
  63. package/dist/config/store.d.ts +33 -0
  64. package/dist/config/store.js +187 -0
  65. package/dist/context.d.ts +6 -0
  66. package/dist/context.js +59 -0
  67. package/dist/conversation.d.ts +23 -0
  68. package/dist/conversation.js +338 -0
  69. package/dist/file-complete.d.ts +9 -0
  70. package/dist/file-complete.js +41 -0
  71. package/dist/index.d.ts +2 -0
  72. package/dist/index.js +1289 -0
  73. package/dist/init.d.ts +5 -0
  74. package/dist/init.js +145 -0
  75. package/dist/markdown.d.ts +23 -0
  76. package/dist/markdown.js +315 -0
  77. package/dist/mcp/client.d.ts +26 -0
  78. package/dist/mcp/client.js +206 -0
  79. package/dist/mcp/config.d.ts +2 -0
  80. package/dist/mcp/config.js +90 -0
  81. package/dist/mcp/manager.d.ts +57 -0
  82. package/dist/mcp/manager.js +176 -0
  83. package/dist/mcp/protocol.d.ts +23 -0
  84. package/dist/mcp/protocol.js +51 -0
  85. package/dist/mcp/state.d.ts +3 -0
  86. package/dist/mcp/state.js +32 -0
  87. package/dist/mcp/types.d.ts +66 -0
  88. package/dist/mcp/types.js +2 -0
  89. package/dist/pkg-info.d.ts +4 -0
  90. package/dist/pkg-info.js +23 -0
  91. package/dist/promotion.d.ts +2 -0
  92. package/dist/promotion.js +34 -0
  93. package/dist/shell-inline.d.ts +9 -0
  94. package/dist/shell-inline.js +63 -0
  95. package/dist/skills/builtin/api-design/SKILL.md +70 -0
  96. package/dist/skills/builtin/code-review/SKILL.md +65 -0
  97. package/dist/skills/builtin/database/SKILL.md +69 -0
  98. package/dist/skills/builtin/debugging/SKILL.md +53 -0
  99. package/dist/skills/builtin/deployment-safety/SKILL.md +57 -0
  100. package/dist/skills/builtin/documentation/SKILL.md +79 -0
  101. package/dist/skills/builtin/error-handling/SKILL.md +76 -0
  102. package/dist/skills/builtin/git-workflow/SKILL.md +65 -0
  103. package/dist/skills/builtin/performance/SKILL.md +57 -0
  104. package/dist/skills/builtin/planning/SKILL.md +58 -0
  105. package/dist/skills/builtin/refactoring/SKILL.md +55 -0
  106. package/dist/skills/builtin/security-review/SKILL.md +62 -0
  107. package/dist/skills/builtin/testing/SKILL.md +41 -0
  108. package/dist/skills/frontmatter.d.ts +10 -0
  109. package/dist/skills/frontmatter.js +37 -0
  110. package/dist/skills/loader.d.ts +2 -0
  111. package/dist/skills/loader.js +104 -0
  112. package/dist/skills/manager.d.ts +34 -0
  113. package/dist/skills/manager.js +107 -0
  114. package/dist/skills/state.d.ts +3 -0
  115. package/dist/skills/state.js +34 -0
  116. package/dist/skills/types.d.ts +30 -0
  117. package/dist/skills/types.js +2 -0
  118. package/dist/slash-commands.d.ts +34 -0
  119. package/dist/slash-commands.js +350 -0
  120. package/dist/snapshot.d.ts +21 -0
  121. package/dist/snapshot.js +144 -0
  122. package/dist/state.d.ts +153 -0
  123. package/dist/state.js +102 -0
  124. package/dist/theme.d.ts +10 -0
  125. package/dist/theme.js +10 -0
  126. package/dist/tools/bash.d.ts +1 -0
  127. package/dist/tools/bash.js +22 -0
  128. package/dist/tools/edit.d.ts +6 -0
  129. package/dist/tools/edit.js +69 -0
  130. package/dist/tools/file-state.d.ts +10 -0
  131. package/dist/tools/file-state.js +49 -0
  132. package/dist/tools/glob.d.ts +1 -0
  133. package/dist/tools/glob.js +98 -0
  134. package/dist/tools/grep.d.ts +1 -0
  135. package/dist/tools/grep.js +100 -0
  136. package/dist/tools/memory.d.ts +44 -0
  137. package/dist/tools/memory.js +56 -0
  138. package/dist/tools/path-policy.d.ts +37 -0
  139. package/dist/tools/path-policy.js +152 -0
  140. package/dist/tools/read.d.ts +1 -0
  141. package/dist/tools/read.js +63 -0
  142. package/dist/tools/runner.d.ts +46 -0
  143. package/dist/tools/runner.js +395 -0
  144. package/dist/tools/search.d.ts +9 -0
  145. package/dist/tools/search.js +61 -0
  146. package/dist/tools/todo.d.ts +44 -0
  147. package/dist/tools/todo.js +221 -0
  148. package/dist/tools/write.d.ts +6 -0
  149. package/dist/tools/write.js +48 -0
  150. package/dist/update-check.d.ts +6 -0
  151. package/dist/update-check.js +18 -0
  152. package/dist/utils.d.ts +8 -0
  153. package/dist/utils.js +25 -0
  154. package/package.json +69 -0
package/LICENSE ADDED
@@ -0,0 +1,73 @@
1
+ DONNA Code — Proprietary Software License
2
+
3
+ Copyright (c) 2026 dbpg deutsche Bühnenproduktionsgesellschaft mbH & Co. KG.
4
+ All rights reserved.
5
+
6
+ 1. Grant of Use
7
+
8
+ Subject to the terms of this License and to a valid, paid subscription or
9
+ account with dbpg where required, dbpg grants you a personal, non-exclusive,
10
+ non-transferable, revocable license to install and use the DONNA Code
11
+ software (the "Software") solely for the purpose of interacting with dbpg
12
+ services through the Software's intended interfaces.
13
+
14
+ 2. Restrictions
15
+
16
+ You may NOT, without prior written permission from dbpg:
17
+
18
+ (a) copy, modify, fork, redistribute, sublicense, sell, rent, lease, or
19
+ lend the Software or any portion thereof;
20
+ (b) reverse engineer, decompile, disassemble, or otherwise attempt to
21
+ derive the source code of the Software except to the extent such
22
+ activity is expressly permitted by applicable law;
23
+ (c) remove, alter, or obscure any proprietary notices in the Software;
24
+ (d) use the Software to build a competing product or service;
25
+ (e) circumvent any technical measures designed to control access to or
26
+ use of the Software or dbpg services;
27
+ (f) use the Software in any manner that violates applicable law.
28
+
29
+ 3. Ownership
30
+
31
+ The Software is licensed, not sold. dbpg retains all right, title, and
32
+ interest in and to the Software, including all intellectual property rights.
33
+ No rights are granted to you other than those expressly stated in this
34
+ License.
35
+
36
+ 4. Third-Party Components
37
+
38
+ The Software incorporates third-party open-source components governed by
39
+ their respective licenses. Such components remain subject to their original
40
+ license terms; nothing in this License modifies those terms.
41
+
42
+ 5. No Warranty
43
+
44
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
45
+ IMPLIED, INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, FITNESS
46
+ FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. dbpg DOES NOT WARRANT THAT
47
+ THE SOFTWARE WILL BE UNINTERRUPTED OR ERROR-FREE.
48
+
49
+ 6. Limitation of Liability
50
+
51
+ TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, IN NO EVENT SHALL dbpg
52
+ BE LIABLE FOR ANY INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL, OR PUNITIVE
53
+ DAMAGES, OR ANY LOSS OF PROFITS OR REVENUE, ARISING OUT OF OR RELATED TO
54
+ YOUR USE OF OR INABILITY TO USE THE SOFTWARE.
55
+
56
+ 7. Termination
57
+
58
+ This License terminates automatically if you fail to comply with any of its
59
+ terms. Upon termination, you must cease all use of the Software and remove
60
+ all copies from your systems.
61
+
62
+ 8. Governing Law
63
+
64
+ This License is governed by the laws of the Federal Republic of Germany,
65
+ without regard to its conflict-of-law principles. Exclusive jurisdiction
66
+ and venue lie with the competent courts at the registered seat of dbpg.
67
+
68
+ 9. Contact
69
+
70
+ For licensing inquiries, please contact:
71
+ support@buehnenproduktionsgesellschaft.de
72
+
73
+ dbpg deutsche Bühnenproduktionsgesellschaft mbH & Co. KG
package/README.md ADDED
@@ -0,0 +1,253 @@
1
+ # DONNA Code
2
+
3
+ A terminal-based AI coding assistant by [dbpg](https://dbpg.io).
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install -g @buehnenproduktionsgesellschaft/donna
9
+ ```
10
+
11
+ ## First-time setup
12
+
13
+ ```bash
14
+ donna login # paste your API key (validated against the gateway)
15
+ donna login --browser # also opens the portal page in your browser
16
+ ```
17
+
18
+ Generate keys at https://centra.dbpg.io/dashboard.
19
+
20
+ ## Usage
21
+
22
+ ```bash
23
+ # Start a new session
24
+ donna
25
+
26
+ # Start with a prompt
27
+ donna "fix the bug in auth.ts"
28
+ donna fix the bug # quotes optional
29
+
30
+ # Multi-line prompt from heredoc / pipe
31
+ donna -p - <<'EOF'
32
+ write a function that
33
+ sums two numbers
34
+ EOF
35
+ echo "long prompt..." | donna -p -
36
+
37
+ # Resume last session
38
+ donna resume
39
+
40
+ # Resume specific session
41
+ donna resume abc123
42
+
43
+ # Logout (remove API key from disk)
44
+ donna logout
45
+ ```
46
+
47
+ ### Subcommands
48
+
49
+ `login`, `logout`, and `resume` are reserved subcommand names. To use them as
50
+ prompt text, pass them via `-p`:
51
+
52
+ ```bash
53
+ donna -p login # chat prompt: "login"
54
+ ```
55
+
56
+ ## Commands
57
+
58
+ Type `/` in the TUI to see and filter all commands. `/help` lists them in-app.
59
+
60
+ **Session & navigation**
61
+
62
+ | Command | Description |
63
+ |---------|-------------|
64
+ | `/help` | Show all commands and shortcuts |
65
+ | `/clear` | Clear the chat |
66
+ | `/resume [id]` | Resume the last (or a specific) session |
67
+ | `/history` | Show past sessions |
68
+ | `/exit` | Exit donna |
69
+
70
+ **Conversation context**
71
+
72
+ | Command | Description |
73
+ |---------|-------------|
74
+ | `/context` | Show context window usage and breakdown |
75
+ | `/compact` | Compact the conversation into a summary |
76
+ | `/inspect` | Browse past tool calls and compactions |
77
+
78
+ **Workflows**
79
+
80
+ | Command | Description |
81
+ |---------|-------------|
82
+ | `/init` | Analyze the project and create `DONNA.md` |
83
+ | `/plan <goal>` | Create an implementation plan |
84
+ | `/explain <file>` | Explain a file or concept |
85
+ | `/review` | Review recent code changes |
86
+ | `/security` | Full security audit of the project |
87
+ | `/test [filter]` | Run tests and analyze failures |
88
+ | `/diff` | Show the current git diff |
89
+ | `/commit` | Generate a commit message and commit |
90
+ | `/undo` | Undo the last file edit |
91
+ | `/image <path>` | Analyze an image file |
92
+
93
+ **Memory**
94
+
95
+ | Command | Description |
96
+ |---------|-------------|
97
+ | `/memory` | Show or manage project memory |
98
+ | `/clear-memory` | Clear all project memory |
99
+
100
+ **Integrations**
101
+
102
+ | Command | Description |
103
+ |---------|-------------|
104
+ | `/agents` | Show agent status and queue |
105
+ | `/skills` | Enable / disable skills (Space toggles) |
106
+ | `/mcp` | Enable / disable MCP servers (Space toggles); `/mcp restart <name>` |
107
+
108
+ **Settings**
109
+
110
+ | Command | Description |
111
+ |---------|-------------|
112
+ | `/model` | Show the current model |
113
+ | `/thinking` | Set reasoning depth (none / low / medium / high) |
114
+ | `/config` | Show configuration |
115
+
116
+ **Account & permissions**
117
+
118
+ | Command | Description |
119
+ |---------|-------------|
120
+ | `/account` | Show account and credits |
121
+ | `/usage` | Show today's token usage |
122
+ | `/login` | Show login status / how to re-authenticate |
123
+ | `/logout` | Remove the API key from disk |
124
+ | `/permissions` | Show saved permissions |
125
+ | `/reset-permissions` | Reset all saved permissions |
126
+
127
+ ## Keyboard Shortcuts
128
+
129
+ | Key | Action |
130
+ |-----|--------|
131
+ | `Ctrl+O` | Expand/collapse tool outputs |
132
+ | `Esc Esc` | Jump to previous message (revert) |
133
+ | `Escape` | Clear input / cancel streaming / close modal |
134
+ | `Alt+Enter` | Newline in input (also in `ask_user` note / `request_input`). On terminals that send a distinct Shift+Enter, that works too |
135
+ | `Tab` | Accept suggestion / file path completion |
136
+ | `Ctrl+C` | Quit |
137
+
138
+ ## Shortcuts
139
+
140
+ | Prefix | Action |
141
+ |--------|--------|
142
+ | `!<cmd>` | Run `<cmd>` in your shell. Output is shown to you only — the model never sees it. Useful for quick lookups (`!ls`, `!git status`) without spending a model turn |
143
+
144
+ ## Tools
145
+
146
+ DONNA Code has built-in tools that the AI uses automatically:
147
+
148
+ - **read_file** — Read files with optional offset/limit
149
+ - **edit_file** — Diff-based file editing (targeted string replacement)
150
+ - **write_file** — Create new files
151
+ - **glob** — Find files by pattern
152
+ - **grep** — Search file contents by regex
153
+ - **run_bash** — Execute shell commands
154
+ - **web_search** — Search the web
155
+ - **web_fetch** — Fetch full content from URLs
156
+ - **todo_read / todo_write** — Mini-issue task list. Each task has a title, optional description (multi-line, survives compaction), optional priority (low/normal/high/urgent), optional size (XS/S/M/L/XL). `todo_read <id>` returns full detail so the assistant can pick a task up again after a context compaction
157
+ - **ask_user** — Open a structured multi-choice modal for the user to answer
158
+ - **request_input** — Prompt the user for free-text input (with optional masking for secrets)
159
+ - **run_agent** — Delegate a focused sub-task to a sub-agent that runs in parallel
160
+
161
+ ## Project Context
162
+
163
+ Create a `DONNA.md` in your project root (or run `/init`) to give the AI context about your project. This file is automatically loaded at the start of each session.
164
+
165
+ Plans in `.plans/*.md` are also loaded automatically.
166
+
167
+ ## MCP Servers (optional)
168
+
169
+ [MCP](https://modelcontextprotocol.io) lets you give DONNA extra tools beyond the
170
+ built-ins — GitHub, Linear, databases, custom internal services. Note: for
171
+ plain file access in the current project, the **built-in tools above are
172
+ already enough**. MCP is for paths outside cwd or non-file integrations.
173
+
174
+ Configure servers in either:
175
+ - `~/.config/donna/mcp.json` (global, trusted automatically)
176
+ - `.donna/mcp.json` (per-project, **requires explicit trust on first use**)
177
+
178
+ ```json
179
+ {
180
+ "mcpServers": {
181
+ "github": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-github"] }
182
+ }
183
+ }
184
+ ```
185
+
186
+ ### Workspace trust
187
+
188
+ When DONNA finds a `.donna/mcp.json` in your current directory it has not
189
+ seen before, you'll be prompted before any subprocess is started:
190
+
191
+ ```
192
+ .donna/mcp.json declares the following MCP servers:
193
+ - github
194
+ These run as subprocesses with full filesystem access.
195
+ Trust this configuration? [y/N]
196
+ ```
197
+
198
+ Answer `y` once and DONNA records the file's content hash in
199
+ `~/.donna/config.json`. Subsequent runs are silent until the file changes.
200
+ This protects you from a hostile cloned repository auto-running a
201
+ subprocess on the first `donna` you type in that directory — the same
202
+ threat model as VS Code's workspace trust.
203
+
204
+ To revoke trust: edit `~/.donna/config.json` and remove the entry from
205
+ `mcpTrust`, or delete the file entirely.
206
+
207
+ ## Configuration
208
+
209
+ Config is stored in `~/.donna/config.json`. The API key is set by
210
+ `donna login` — you generally don't edit this file by hand. Other fields:
211
+
212
+ ```json
213
+ {
214
+ "endpoint": "https://api.centra.dbpg.io/v1",
215
+ "model": "donna-coda",
216
+ "contextLimit": 180000,
217
+ "autoCompactThreshold": 0.8,
218
+ "reasoningEffort": "high"
219
+ }
220
+ ```
221
+
222
+ ## Reporting bugs
223
+
224
+ Email: **support@buehnenproduktionsgesellschaft.de**
225
+
226
+ For security issues please use the private channel in [SECURITY.md](SECURITY.md).
227
+
228
+ When reporting, include:
229
+ - Output of `donna --version`
230
+ - `node --version`
231
+ - Operating system
232
+
233
+ ## Platform support
234
+
235
+ Officially supported: **macOS** and **Linux**. Windows is not supported in
236
+ this release — `run_bash` uses `/bin/bash` and several path helpers assume
237
+ POSIX semantics, so `npm i -g` refuses to install on Windows (`"os"` field
238
+ in `package.json`). Windows support is tracked as issue #4 and planned for
239
+ a future release.
240
+
241
+ ## Development
242
+
243
+ ```bash
244
+ npm install
245
+ npm run build
246
+ node dist/index.js
247
+ ```
248
+
249
+ A complete history of changes is in [CHANGELOG.md](CHANGELOG.md).
250
+
251
+ ## License
252
+
253
+ Proprietary. Copyright (c) 2026 dbpg deutsche Bühnenproduktionsgesellschaft mbH & Co. KG. All rights reserved.
@@ -0,0 +1,53 @@
1
+ ---
2
+ name: research
3
+ description: Deep research agent - reads code and returns structured findings
4
+ allowedTools: [read_file, glob, grep, web_search, web_fetch]
5
+ maxTurns: 19
6
+ timeout: 180000
7
+ ---
8
+
9
+ You are a research agent running in an isolated context. You receive ONE task,
10
+ investigate using `read_file` / `glob` / `grep` / `web_search` / `web_fetch`,
11
+ and ALWAYS return a structured report.
12
+
13
+ ## Mandatory Contract
14
+ - Every run MUST end with a final response containing the report below.
15
+ - Empty content is a critical violation of the agent contract.
16
+ - If the task is impossible (file missing, ambiguous, blocked) you STILL respond — set `Status: failed` and explain why in `Summary`.
17
+ - Your final turn (the one with no tool calls) IS the report. Do not call tools in that turn.
18
+
19
+ ## Workflow
20
+ 1. Read the task carefully and extract any paths, symbols, or keywords.
21
+ 2. Use `glob`/`grep` to locate relevant files if not given explicitly.
22
+ 3. Use `read_file` to inspect them.
23
+ 4. Stop investigating after 1–3 evidence-gathering turns and produce the report.
24
+ 5. Be concise but specific — quote line numbers, function names, exact paths.
25
+ 6. Do NOT write files or execute commands. Read-only.
26
+
27
+ ## Required Output Format
28
+ Your final response MUST start with this exact structure:
29
+
30
+ ```
31
+ ## Status
32
+ success | partial | failed
33
+
34
+ ## Summary
35
+ <one sentence directly answering the task>
36
+
37
+ ## Findings
38
+ <structured detail; subsections allowed>
39
+
40
+ ## Key Files
41
+ - `path/to/file.ts:line` — what it does, why it matters
42
+ ```
43
+
44
+ `Key Files` may be empty if no files are central to the answer, but the heading must still be present.
45
+
46
+ ## Output Style (strict)
47
+ - Start the response directly with `## Status`. No preamble ("Sure", "I'll investigate", "Let me check"), no greeting.
48
+ - End after the last finding. No closing pleasantries ("Let me know if...", "Hope this helps").
49
+ - No emojis. No decorative characters.
50
+ - No bold/italic for emphasis — only inside section headers if needed.
51
+ - No prose paragraphs where bullets work. Terse over flowing.
52
+ - Quote exact identifiers: file paths, line numbers, function names, error strings. Never paraphrase them.
53
+ - No filler ("It looks like", "It appears that"). State facts directly.
@@ -0,0 +1,58 @@
1
+ ---
2
+ name: review
3
+ description: Code review agent - unbiased analysis of changes
4
+ allowedTools: [read_file, grep]
5
+ maxTurns: 19
6
+ timeout: 180000
7
+ ---
8
+
9
+ You are a code review agent running in an isolated context with no knowledge of
10
+ the surrounding conversation or the author's intent. You judge only what the
11
+ code does.
12
+
13
+ ## Mandatory Contract
14
+ - Every run MUST end with a final response containing the report below.
15
+ - Empty content is a critical violation of the agent contract.
16
+ - If you cannot review (file missing, unreadable, scope unclear) you STILL respond — set `Status: failed` and explain why in `Summary`.
17
+ - Your final turn (no tool calls) IS the report. Do not call tools in that turn.
18
+
19
+ ## Workflow
20
+ 1. Read the task to identify what to review (file, range, concern).
21
+ 2. Use `read_file` and `grep` to inspect the code.
22
+ 3. Look for: bugs, security issues, performance problems, readability concerns.
23
+ 4. After 1–3 evidence-gathering turns, produce the report.
24
+ 5. Be direct — name files, lines, severities. No hedging.
25
+
26
+ ## Severity Levels
27
+ - `CRITICAL` — bug, security flaw, data loss risk
28
+ - `WARNING` — likely bug, performance issue, smell
29
+ - `INFO` — style, minor improvement
30
+
31
+ ## Required Output Format
32
+ Your final response MUST start with this exact structure:
33
+
34
+ ```
35
+ ## Status
36
+ success | partial | failed
37
+
38
+ ## Summary
39
+ <one sentence: count by severity and overall verdict>
40
+
41
+ ## Findings
42
+ ### [SEVERITY] <Issue title>
43
+ - **Location**: `file.ts:line`
44
+ - **Problem**: <what's wrong>
45
+ - **Impact**: <why it matters>
46
+ - **Suggestion**: <how to fix, if applicable>
47
+
48
+ (repeat per finding; if none, write "No issues found.")
49
+ ```
50
+
51
+ ## Output Style (strict)
52
+ - Start the response directly with `## Status`. No preamble ("Sure", "I'll review", "Let me look"), no greeting.
53
+ - End after the last finding. No closing pleasantries ("Let me know if...", "Hope this helps").
54
+ - No emojis. No decorative characters.
55
+ - No bold/italic for emphasis — only the labels inside finding entries (Location/Problem/Impact/Suggestion) and section headers.
56
+ - No hedging ("might be", "could potentially"). If you flag an issue, state it as fact with severity.
57
+ - Quote exact identifiers: file paths, line numbers, function names. Never paraphrase them.
58
+ - No filler. One issue, one entry, no surrounding prose.
@@ -0,0 +1,19 @@
1
+ import { AgentManager } from './manager.js';
2
+ import type { AppState } from '../state.js';
3
+ import type { Session } from '../config/store.js';
4
+ export declare let globalAgentManager: AgentManager | null;
5
+ export declare function setGlobalAgentManager(manager: AgentManager): void;
6
+ export declare function getGlobalAgentManager(): AgentManager | null;
7
+ export declare let globalAppState: AppState | null;
8
+ export declare function setGlobalAppState(state: AppState): void;
9
+ export declare function getGlobalAppState(): AppState | null;
10
+ /**
11
+ * Drain pending async agent results into the session as a synthetic user
12
+ * turn so the next runConversation call sees them. Returns true if anything
13
+ * was drained.
14
+ *
15
+ * Shared by:
16
+ * - processAgentQueue (idle wake-up from listener)
17
+ * - runConversation end-of-turn check (drained while a turn was in flight)
18
+ */
19
+ export declare function drainAgentResults(state: AppState, session: Session): boolean;
@@ -0,0 +1,54 @@
1
+ import { markUserTurnStart } from '../state.js';
2
+ import { saveSession } from '../config/store.js';
3
+ export let globalAgentManager = null;
4
+ export function setGlobalAgentManager(manager) {
5
+ globalAgentManager = manager;
6
+ }
7
+ export function getGlobalAgentManager() {
8
+ return globalAgentManager;
9
+ }
10
+ export let globalAppState = null;
11
+ export function setGlobalAppState(state) {
12
+ globalAppState = state;
13
+ }
14
+ export function getGlobalAppState() {
15
+ return globalAppState;
16
+ }
17
+ /**
18
+ * Drain pending async agent results into the session as a synthetic user
19
+ * turn so the next runConversation call sees them. Returns true if anything
20
+ * was drained.
21
+ *
22
+ * Shared by:
23
+ * - processAgentQueue (idle wake-up from listener)
24
+ * - runConversation end-of-turn check (drained while a turn was in flight)
25
+ */
26
+ export function drainAgentResults(state, session) {
27
+ if (state.agentResultQueue.length === 0)
28
+ return false;
29
+ const results = [...state.agentResultQueue];
30
+ state.agentResultQueue = [];
31
+ const combinedContent = results
32
+ .map((r) => {
33
+ const tokens = `${(r.tokenUsage.prompt / 1000).toFixed(1)}k prompt, ${(r.tokenUsage.completion / 1000).toFixed(1)}k completion`;
34
+ return `## Result from **${r.agent}** agent (${r.turnsUsed} turns, ${tokens}, ${(r.elapsedMs / 1000).toFixed(1)}s)\n${r.task}\n\n${r.response}`;
35
+ })
36
+ .join('\n\n---\n\n');
37
+ state.items.push({
38
+ type: 'message',
39
+ role: 'assistant',
40
+ content: combinedContent,
41
+ });
42
+ // Treat the drained agent results as a real turn boundary: freeze prior
43
+ // display items and capture a git snapshot before the synthetic user
44
+ // message, so point-in-time revert works for agent-result-driven turns
45
+ // (consistent with queued prompts in conversation.ts).
46
+ markUserTurnStart(state, session);
47
+ const agentMsg = {
48
+ role: 'user',
49
+ content: `[Sub-agent results for ${results.length} task(s):\n\n${results.map((r) => `"${r.task}" (${r.agent})`).join('\n')}]\n\n${combinedContent}`,
50
+ };
51
+ session.messages.push(agentMsg);
52
+ saveSession(session);
53
+ return true;
54
+ }
@@ -0,0 +1,9 @@
1
+ import { AgentSpec } from './types.js';
2
+ export interface AgentsLoadResult {
3
+ agents: AgentSpec[];
4
+ errors: {
5
+ file: string;
6
+ message: string;
7
+ }[];
8
+ }
9
+ export declare function loadAgents(cwd: string): AgentsLoadResult;
@@ -0,0 +1,75 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import os from 'node:os';
4
+ import { AGENT_BLOCKED_TOOLS } from './types.js';
5
+ import { parseFrontmatter } from '../skills/frontmatter.js';
6
+ export function loadAgents(cwd) {
7
+ const agents = [];
8
+ const errors = [];
9
+ const dirs = [
10
+ path.join(cwd, '.donna/agents'),
11
+ path.join(os.homedir(), '.donna/agents'),
12
+ path.join(cwd, 'src/agents/builtin'), // Built-in agents from source
13
+ ];
14
+ for (const dir of dirs) {
15
+ if (!fs.existsSync(dir))
16
+ continue;
17
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
18
+ if (!entry.isDirectory())
19
+ continue;
20
+ const agentFile = path.join(dir, entry.name, 'AGENT.md');
21
+ if (!fs.existsSync(agentFile))
22
+ continue;
23
+ try {
24
+ const raw = fs.readFileSync(agentFile, 'utf-8');
25
+ const { frontmatter, body } = parseFrontmatter(raw);
26
+ // Validate frontmatter
27
+ const name = String(frontmatter.name || entry.name);
28
+ const description = String(frontmatter.description || '');
29
+ const maxTurns = Math.min(Number(frontmatter.maxTurns) || 10, 20); // Hard cap
30
+ const timeoutMs = Math.min(Number(frontmatter.timeout) || 120000, 300000); // Max 5min
31
+ // Sanitize allowed tools - block dangerous ones
32
+ // Parse allowed tools - handle both array syntax [a, b] and missing frontmatter
33
+ const safeToolsList = ['read_file', 'glob', 'grep', 'web_search', 'web_fetch', 'list_skills'];
34
+ const allowedToolsRaw = frontmatter.allowedTools;
35
+ let allowedTools;
36
+ if (allowedToolsRaw) {
37
+ // Parse YAML array format: [tool1, tool2]
38
+ const match = String(allowedToolsRaw).match(/^\[([^\]]*)\]$/);
39
+ if (match) {
40
+ allowedTools = match[1].split(',').map(s => s.trim().replace(/^["']|["']$/g, ''));
41
+ }
42
+ else {
43
+ allowedTools = [allowedToolsRaw];
44
+ }
45
+ // Filter to only safe tools
46
+ allowedTools = allowedTools.filter((t) => !AGENT_BLOCKED_TOOLS.has(t) && safeToolsList.includes(t));
47
+ // If nothing valid remains, fall back to safe defaults
48
+ if (allowedTools.length === 0) {
49
+ allowedTools = [...safeToolsList];
50
+ }
51
+ }
52
+ else {
53
+ // No explicit tools - use all safe defaults
54
+ allowedTools = [...safeToolsList];
55
+ }
56
+ agents.push({
57
+ name: sanitizeAgentName(name),
58
+ description,
59
+ allowedTools,
60
+ maxTurns,
61
+ timeoutMs,
62
+ filePath: agentFile,
63
+ systemPrompt: body.trim(),
64
+ });
65
+ }
66
+ catch (e) {
67
+ errors.push({ file: agentFile, message: e.message });
68
+ }
69
+ }
70
+ }
71
+ return { agents, errors };
72
+ }
73
+ function sanitizeAgentName(name) {
74
+ return name.toLowerCase().replace(/[^a-z0-9_-]/g, '_');
75
+ }
@@ -0,0 +1,52 @@
1
+ import { AgentSpec, AgentResult } from './types.js';
2
+ import { AgentPool } from './pool.js';
3
+ import { DonnaConfig } from '../config/schema.js';
4
+ export interface ToolDef {
5
+ type: 'function';
6
+ function: {
7
+ name: string;
8
+ description: string;
9
+ parameters: Record<string, unknown>;
10
+ };
11
+ }
12
+ export declare class AgentManager {
13
+ private cwd;
14
+ private agents;
15
+ private pool;
16
+ private config;
17
+ /** One AbortController per in-flight task, so abortAll() can actually
18
+ * cancel the running turn loop + its API call — not just the pool
19
+ * bookkeeping. */
20
+ private controllers;
21
+ /** Non-fatal errors collected during initial agent load. Exposed so the
22
+ * TUI can surface them via /agents or a status indicator instead of
23
+ * writing to stdout/stderr and corrupting the Ink render. */
24
+ readonly loadErrors: string[];
25
+ constructor(cwd: string, config: DonnaConfig);
26
+ private load;
27
+ getPool(): AgentPool;
28
+ getAgent(name: string): AgentSpec | undefined;
29
+ listAgents(): AgentSpec[];
30
+ /**
31
+ * Submit task and optionally wait for completion.
32
+ * @param options.wait - If true, blocks until completion. If false, returns immediately with task ID.
33
+ * @returns Task ID (async) or AgentResult (sync when wait=true)
34
+ */
35
+ submitTask(name: string, task: string, files?: string[], options?: {
36
+ wait?: boolean;
37
+ waitTimeoutMs?: number;
38
+ }): Promise<string | AgentResult>;
39
+ private executeWhenReady;
40
+ /** Resolve once the task reaches a terminal-or-running state, driven by
41
+ * pool notifications instead of polling. Also resolves on abort. */
42
+ private waitForRunning;
43
+ /** Get tool definition for API */
44
+ getToolDef(): ToolDef | null;
45
+ /** Wait for task completion and return result (blocking).
46
+ * Event-driven off pool notifications — no polling. */
47
+ waitForResult(taskId: string, timeoutMs?: number): Promise<AgentResult>;
48
+ /** Abort every in-flight and queued agent — cancels the running turn loop
49
+ * and its API call via the per-task AbortController, then clears pool
50
+ * bookkeeping. Call on app exit / Ctrl+C. */
51
+ abortAll(): void;
52
+ }