@draht/coding-agent 2026.3.3 → 2026.3.4

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 (139) hide show
  1. package/CHANGELOG.md +120 -0
  2. package/README.md +1 -0
  3. package/dist/cli/args.d.ts.map +1 -1
  4. package/dist/cli/args.js +1 -0
  5. package/dist/cli/args.js.map +1 -1
  6. package/dist/cli.d.ts.map +1 -1
  7. package/dist/cli.js +5 -0
  8. package/dist/cli.js.map +1 -1
  9. package/dist/config.d.ts +0 -7
  10. package/dist/config.d.ts.map +1 -1
  11. package/dist/config.js +0 -12
  12. package/dist/config.js.map +1 -1
  13. package/dist/core/agent-session.d.ts +14 -4
  14. package/dist/core/agent-session.d.ts.map +1 -1
  15. package/dist/core/agent-session.js +167 -49
  16. package/dist/core/agent-session.js.map +1 -1
  17. package/dist/core/auth-storage.d.ts +1 -1
  18. package/dist/core/auth-storage.d.ts.map +1 -1
  19. package/dist/core/auth-storage.js +2 -1
  20. package/dist/core/auth-storage.js.map +1 -1
  21. package/dist/core/builtins/subagent.d.ts +14 -0
  22. package/dist/core/builtins/subagent.d.ts.map +1 -0
  23. package/dist/core/builtins/subagent.js +492 -0
  24. package/dist/core/builtins/subagent.js.map +1 -0
  25. package/dist/core/compaction/compaction.d.ts.map +1 -1
  26. package/dist/core/compaction/compaction.js +4 -1
  27. package/dist/core/compaction/compaction.js.map +1 -1
  28. package/dist/core/export-html/tool-renderer.d.ts.map +1 -1
  29. package/dist/core/export-html/tool-renderer.js +6 -0
  30. package/dist/core/export-html/tool-renderer.js.map +1 -1
  31. package/dist/core/extensions/loader.d.ts.map +1 -1
  32. package/dist/core/extensions/loader.js +19 -8
  33. package/dist/core/extensions/loader.js.map +1 -1
  34. package/dist/core/extensions/runner.d.ts.map +1 -1
  35. package/dist/core/extensions/runner.js +1 -0
  36. package/dist/core/extensions/runner.js.map +1 -1
  37. package/dist/core/extensions/types.d.ts +8 -2
  38. package/dist/core/extensions/types.d.ts.map +1 -1
  39. package/dist/core/extensions/types.js.map +1 -1
  40. package/dist/core/model-registry.d.ts +1 -0
  41. package/dist/core/model-registry.d.ts.map +1 -1
  42. package/dist/core/model-registry.js +9 -6
  43. package/dist/core/model-registry.js.map +1 -1
  44. package/dist/core/model-resolver.d.ts.map +1 -1
  45. package/dist/core/model-resolver.js +35 -5
  46. package/dist/core/model-resolver.js.map +1 -1
  47. package/dist/core/package-manager.d.ts.map +1 -1
  48. package/dist/core/package-manager.js +1 -10
  49. package/dist/core/package-manager.js.map +1 -1
  50. package/dist/core/prompt-templates.js.map +1 -1
  51. package/dist/core/resource-loader.d.ts +2 -0
  52. package/dist/core/resource-loader.d.ts.map +1 -1
  53. package/dist/core/resource-loader.js +5 -1
  54. package/dist/core/resource-loader.js.map +1 -1
  55. package/dist/core/sdk.d.ts +1 -1
  56. package/dist/core/sdk.d.ts.map +1 -1
  57. package/dist/core/sdk.js.map +1 -1
  58. package/dist/core/session-manager.js.map +1 -1
  59. package/dist/core/settings-manager.d.ts +3 -0
  60. package/dist/core/settings-manager.d.ts.map +1 -1
  61. package/dist/core/settings-manager.js +4 -0
  62. package/dist/core/settings-manager.js.map +1 -1
  63. package/dist/core/system-prompt.d.ts +4 -0
  64. package/dist/core/system-prompt.d.ts.map +1 -1
  65. package/dist/core/system-prompt.js +34 -12
  66. package/dist/core/system-prompt.js.map +1 -1
  67. package/dist/core/tools/edit-diff.js.map +1 -1
  68. package/dist/core/tools/path-utils.js.map +1 -1
  69. package/dist/main.d.ts.map +1 -1
  70. package/dist/main.js +5 -5
  71. package/dist/main.js.map +1 -1
  72. package/dist/migrations.js.map +1 -1
  73. package/dist/modes/interactive/components/armin.js.map +1 -1
  74. package/dist/modes/interactive/components/config-selector.js.map +1 -1
  75. package/dist/modes/interactive/components/daxnuts.js.map +1 -1
  76. package/dist/modes/interactive/components/dynamic-border.js.map +1 -1
  77. package/dist/modes/interactive/components/extension-editor.d.ts +5 -2
  78. package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
  79. package/dist/modes/interactive/components/extension-editor.js +9 -1
  80. package/dist/modes/interactive/components/extension-editor.js.map +1 -1
  81. package/dist/modes/interactive/components/extension-selector.js.map +1 -1
  82. package/dist/modes/interactive/components/footer.js.map +1 -1
  83. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  84. package/dist/modes/interactive/components/login-dialog.js +1 -1
  85. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  86. package/dist/modes/interactive/components/model-selector.d.ts +1 -1
  87. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  88. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  89. package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
  90. package/dist/modes/interactive/components/oauth-selector.js +1 -1
  91. package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
  92. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
  93. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  94. package/dist/modes/interactive/components/session-selector.js +1 -1
  95. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  96. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  97. package/dist/modes/interactive/components/tool-execution.d.ts +2 -0
  98. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  99. package/dist/modes/interactive/components/tool-execution.js +28 -3
  100. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  101. package/dist/modes/interactive/components/tree-selector.js.map +1 -1
  102. package/dist/modes/interactive/components/user-message-selector.js.map +1 -1
  103. package/dist/modes/interactive/components/user-message.d.ts +1 -0
  104. package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  105. package/dist/modes/interactive/components/user-message.js +11 -0
  106. package/dist/modes/interactive/components/user-message.js.map +1 -1
  107. package/dist/modes/interactive/interactive-mode.d.ts +1 -1
  108. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  109. package/dist/modes/interactive/interactive-mode.js +27 -26
  110. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  111. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  112. package/dist/modes/interactive/theme/theme.js +5 -0
  113. package/dist/modes/interactive/theme/theme.js.map +1 -1
  114. package/dist/prompts/commands/fix.md +29 -0
  115. package/dist/prompts/commands/init-project.md +49 -0
  116. package/dist/prompts/commands/next-milestone.md +44 -0
  117. package/dist/prompts/commands/review.md +26 -0
  118. package/docs/custom-provider.md +10 -2
  119. package/docs/extensions.md +20 -1
  120. package/docs/providers.md +3 -1
  121. package/docs/settings.md +1 -0
  122. package/examples/extensions/README.md +1 -0
  123. package/examples/extensions/antigravity-image-gen.ts +3 -1
  124. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  125. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  126. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  127. package/examples/extensions/custom-provider-qwen-cli/package.json +1 -1
  128. package/examples/extensions/dynamic-tools.ts +74 -0
  129. package/examples/extensions/with-deps/package-lock.json +2 -2
  130. package/examples/extensions/with-deps/package.json +1 -1
  131. package/package.json +8 -7
  132. package/prompts/commands/fix.md +29 -0
  133. package/prompts/commands/init-project.md +49 -0
  134. package/prompts/commands/next-milestone.md +44 -0
  135. package/prompts/commands/review.md +26 -0
  136. package/dist/extensions/gsd-commands.ts +0 -403
  137. package/dist/extensions/subagent.ts +0 -515
  138. package/extensions/gsd-commands.ts +0 -403
  139. package/extensions/subagent.ts +0 -515
@@ -0,0 +1,49 @@
1
+ # /init-project
2
+
3
+ Initialize GSD planning framework for an existing project: codebase mapping → questioning → domain model → requirements → roadmap.
4
+
5
+ ## Usage
6
+ ```
7
+ /init-project [focus area or goal]
8
+ ```
9
+
10
+ Use this when you have an existing codebase and want to add GSD methodology.
11
+ For greenfield projects, use `/new-project` instead.
12
+
13
+ ## Steps
14
+ 1. Run `draht-tools init` to check preconditions (git repo, etc.)
15
+ 2. Run `draht-tools map-codebase` to build a structural map of the existing code
16
+ 3. Analyze the codebase map to understand architecture, tech stack, and conventions
17
+ 4. Deep questioning phase (3-7 rounds, 1-2 questions at a time):
18
+ - What is this project? Who uses it?
19
+ - What are the current pain points or goals?
20
+ - What is MVP vs aspirational scope?
21
+ - What constraints exist (infra, team size, deadlines)?
22
+ 5. Run `draht-tools create-project` with gathered info
23
+ 6. Run `draht-tools create-domain-model` to define bounded contexts, entities, and ubiquitous language
24
+ 7. Create `.planning/DOMAIN.md` with:
25
+ - `## Bounded Contexts` — each context with name, responsibility, and brief description
26
+ - `## Ubiquitous Language` — glossary of domain terms agreed with the user (term → definition)
27
+ - `## Context Map` — how bounded contexts relate to each other (upstream/downstream, shared kernel, ACL)
28
+ - `## Aggregates` — aggregates and their root entities per context
29
+ - `## Domain Events` — named events that cross context boundaries
30
+ 8. Create `.planning/TEST-STRATEGY.md` with:
31
+ - `## Test Framework` — chosen framework and rationale
32
+ - `## Directory Conventions` — where test files live relative to source
33
+ - `## Coverage Goals` — target coverage percentage and which paths are critical
34
+ - `## Testing Levels` — what is tested at unit level vs integration vs e2e, with examples
35
+ - `## Excluded` — what is explicitly not tested and why (config files, generated code, etc.)
36
+ 9. Optional research phase via `draht-tools research`
37
+ 10. Run `draht-tools create-requirements` with v1/v2/out-of-scope (map requirements to bounded contexts)
38
+ 11. Run `draht-tools create-roadmap` with phases
39
+ 12. Run `draht-tools init-state`
40
+ 13. Git commit via `draht-tools commit-docs "initialize GSD planning"`
41
+
42
+ ## Rules
43
+ - Ask 1-2 questions at a time, never dump 10 at once
44
+ - Follow threads based on answers
45
+ - Use examples ("Like Stripe Checkout, or custom?")
46
+ - Confirm, don't assume
47
+ - 3-7 follow-up rounds typical
48
+ - Respect what already exists — do not propose rewriting working code
49
+ - Stop when you have: current state, goals, MVP scope, constraints, success criteria
@@ -0,0 +1,44 @@
1
+ # /next-milestone
2
+
3
+ Plan the next milestone after the current one is complete.
4
+
5
+ ## Usage
6
+ ```
7
+ /next-milestone
8
+ ```
9
+
10
+ ## Prerequisites
11
+ - `.planning/ROADMAP.md` must exist
12
+ - Current milestone should be complete or nearly complete
13
+
14
+ ## Steps
15
+ 1. Load project context:
16
+ - Read `.planning/ROADMAP.md` — identify the completed milestone and its phases
17
+ - Read `.planning/STATE.md` — understand current status
18
+ - Read `.planning/REQUIREMENTS.md` — check which requirements are satisfied
19
+ - Read `.planning/DOMAIN.md` (if exists) — review domain model for evolution needs
20
+ 2. Review completed work:
21
+ - Scan `.planning/phases/` for all UAT reports (`*-UAT.md`) and summaries (`*-SUMMARY.md`)
22
+ - Note what was built, what worked well, what had issues
23
+ 3. Assess requirements:
24
+ - Which v1 requirements are now satisfied?
25
+ - Which v1 requirements remain?
26
+ - Should any v2 requirements be promoted based on what we learned?
27
+ - Are there new requirements discovered during implementation?
28
+ 4. Propose next milestone:
29
+ - Define 3-5 phases, each with a clear goal (outcome, not activity)
30
+ - Order phases by dependency
31
+ - Map each phase to specific requirements
32
+ - Estimate relative complexity
33
+ 5. Present the proposed milestone for user approval before writing files
34
+ 6. After approval:
35
+ - Update `ROADMAP.md` with the new milestone and phases
36
+ - Update `STATE.md` to reflect milestone transition
37
+ - Update `REQUIREMENTS.md` if requirements changed
38
+ - Update `DOMAIN.md` if domain model needs evolution
39
+ - Commit: `draht-tools commit-docs "plan next milestone"`
40
+
41
+ ## Rules
42
+ - Always review what was actually built, not just what was planned
43
+ - Be honest about requirements that slipped or changed scope
44
+ - Each phase goal must be testable — "user can X" not "implement Y"
@@ -0,0 +1,26 @@
1
+ # /review
2
+
3
+ Ad-hoc code review and security audit of recent changes or a specific scope.
4
+
5
+ ## Usage
6
+ ```
7
+ /review [scope]
8
+ ```
9
+
10
+ If no scope given, reviews all recent uncommitted changes.
11
+
12
+ ## Steps
13
+ 1. Identify the scope:
14
+ - If argument given: review those files/directories/description
15
+ - If no argument: run `git diff --stat` and `git diff --cached --stat` to find changes
16
+ 2. For each changed file, examine:
17
+ - Correctness: logic errors, off-by-one, null handling, error paths
18
+ - Type safety: any `as` casts, `any` types, missing null checks
19
+ - Conventions: naming, file organization, import style
20
+ - Security: injection risks, auth bypasses, secrets in code, unsafe deserialization
21
+ - Performance: unnecessary allocations, missing indexes, N+1 queries
22
+ 3. Produce a prioritized findings report:
23
+ - **Critical** — must fix before merge (security, data loss, crashes)
24
+ - **Important** — should fix (bugs, type issues, missing error handling)
25
+ - **Minor** — style, naming, or optional improvements
26
+ 4. For each finding: cite the exact file and line, explain the issue, suggest the fix
@@ -172,10 +172,17 @@ models: [{
172
172
  // ...
173
173
  compat: {
174
174
  supportsDeveloperRole: false, // use "system" instead of "developer"
175
- supportsReasoningEffort: false, // disable reasoning_effort param
175
+ supportsReasoningEffort: true,
176
+ reasoningEffortMap: { // map pi-ai levels to provider values
177
+ minimal: "default",
178
+ low: "default",
179
+ medium: "default",
180
+ high: "default",
181
+ xhigh: "default"
182
+ },
176
183
  maxTokensField: "max_tokens", // instead of "max_completion_tokens"
177
184
  requiresToolResultName: true, // tool results need name field
178
- requiresMistralToolIds: true // tool IDs must be 9 alphanumeric chars
185
+ requiresMistralToolIds: true,
179
186
  thinkingFormat: "qwen" // uses enable_thinking: true
180
187
  }
181
188
  }]
@@ -568,6 +575,7 @@ interface ProviderModelConfig {
568
575
  supportsStore?: boolean;
569
576
  supportsDeveloperRole?: boolean;
570
577
  supportsReasoningEffort?: boolean;
578
+ reasoningEffortMap?: Partial<Record<"minimal" | "low" | "medium" | "high" | "xhigh", string>>;
571
579
  supportsUsageInStreaming?: boolean;
572
580
  maxTokensField?: "max_completion_tokens" | "max_tokens";
573
581
  requiresToolResultName?: boolean;
@@ -880,6 +880,14 @@ Subscribe to events. See [Events](#events) for event types and return values.
880
880
 
881
881
  Register a custom tool callable by the LLM. See [Custom Tools](#custom-tools) for full details.
882
882
 
883
+ `pi.registerTool()` works both during extension load and after startup. You can call it inside `session_start`, command handlers, or other event handlers. New tools are refreshed immediately in the same session, so they appear in `pi.getAllTools()` and are callable by the LLM without `/reload`.
884
+
885
+ Use `pi.setActiveTools()` to enable or disable tools (including dynamically added tools) at runtime.
886
+
887
+ Use `promptSnippet` to customize that tool's one-line entry in `Available tools`, and `promptGuidelines` to append tool-specific bullets to the default `Guidelines` section when the tool is active.
888
+
889
+ See [dynamic-tools.ts](../examples/extensions/dynamic-tools.ts) for a full example.
890
+
883
891
  ```typescript
884
892
  import { Type } from "@sinclair/typebox";
885
893
  import { StringEnum } from "@draht/ai";
@@ -888,6 +896,8 @@ pi.registerTool({
888
896
  name: "my_tool",
889
897
  label: "My Tool",
890
898
  description: "What this tool does",
899
+ promptSnippet: "Summarize or transform text according to action",
900
+ promptGuidelines: ["Use this tool when the user asks to summarize previously generated text."],
891
901
  parameters: Type.Object({
892
902
  action: StringEnum(["list", "add"] as const),
893
903
  text: Type.Optional(Type.String()),
@@ -1116,7 +1126,7 @@ const result = await pi.exec("git", ["status"], { signal, timeout: 5000 });
1116
1126
 
1117
1127
  ### pi.getActiveTools() / pi.getAllTools() / pi.setActiveTools(names)
1118
1128
 
1119
- Manage active tools.
1129
+ Manage active tools. This works for both built-in tools and dynamically registered tools.
1120
1130
 
1121
1131
  ```typescript
1122
1132
  const active = pi.getActiveTools(); // ["read", "bash", "edit", "write"]
@@ -1276,6 +1286,10 @@ export default function (pi: ExtensionAPI) {
1276
1286
 
1277
1287
  Register tools the LLM can call via `pi.registerTool()`. Tools appear in the system prompt and can have custom rendering.
1278
1288
 
1289
+ Use `promptSnippet` for a short one-line entry in the `Available tools` section in the default system prompt. If omitted, pi falls back to `description`.
1290
+
1291
+ Use `promptGuidelines` to add tool-specific bullets to the default system prompt `Guidelines` section. These bullets are included only while the tool is active (for example, after `pi.setActiveTools([...])`).
1292
+
1279
1293
  Note: Some models are idiots and include the @ prefix in tool path arguments. Built-in tools strip a leading @ before resolving paths. If your custom tool accepts a path, normalize a leading @ as well.
1280
1294
 
1281
1295
  ### Tool Definition
@@ -1289,6 +1303,10 @@ pi.registerTool({
1289
1303
  name: "my_tool",
1290
1304
  label: "My Tool",
1291
1305
  description: "What this tool does (shown to LLM)",
1306
+ promptSnippet: "List or add items in the project todo list",
1307
+ promptGuidelines: [
1308
+ "Use this tool for todo planning instead of direct file edits when the user asks for a task list."
1309
+ ],
1292
1310
  parameters: Type.Object({
1293
1311
  action: StringEnum(["list", "add"] as const), // Use StringEnum for Google compatibility
1294
1312
  text: Type.Optional(Type.String()),
@@ -1886,6 +1904,7 @@ All examples in [examples/extensions/](../examples/extensions/).
1886
1904
  | `question.ts` | Tool with user interaction | `registerTool`, `ui.select` |
1887
1905
  | `questionnaire.ts` | Multi-step wizard tool | `registerTool`, `ui.custom` |
1888
1906
  | `todo.ts` | Stateful tool with persistence | `registerTool`, `appendEntry`, `renderResult`, session events |
1907
+ | `dynamic-tools.ts` | Register tools after startup and during commands | `registerTool`, `session_start`, `registerCommand` |
1889
1908
  | `truncated-tool.ts` | Output truncation example | `registerTool`, `truncateHead` |
1890
1909
  | `tool-override.ts` | Override built-in read tool | `registerTool` (same name as built-in) |
1891
1910
  | **Commands** |||
package/docs/providers.md CHANGED
@@ -65,6 +65,7 @@ pi
65
65
  | Vercel AI Gateway | `AI_GATEWAY_API_KEY` | `vercel-ai-gateway` |
66
66
  | ZAI | `ZAI_API_KEY` | `zai` |
67
67
  | OpenCode Zen | `OPENCODE_API_KEY` | `opencode` |
68
+ | OpenCode Go | `OPENCODE_API_KEY` | `opencode-go` |
68
69
  | Hugging Face | `HF_TOKEN` | `huggingface` |
69
70
  | Kimi For Coding | `KIMI_API_KEY` | `kimi-coding` |
70
71
  | MiniMax | `MINIMAX_API_KEY` | `minimax` |
@@ -81,7 +82,8 @@ Store credentials in `~/.pi/agent/auth.json`:
81
82
  "anthropic": { "type": "api_key", "key": "sk-ant-..." },
82
83
  "openai": { "type": "api_key", "key": "sk-..." },
83
84
  "google": { "type": "api_key", "key": "..." },
84
- "opencode": { "type": "api_key", "key": "..." }
85
+ "opencode": { "type": "api_key", "key": "..." },
86
+ "opencode-go": { "type": "api_key", "key": "..." }
85
87
  }
86
88
  ```
87
89
 
package/docs/settings.md CHANGED
@@ -69,6 +69,7 @@ Edit directly or use `/settings` for common options.
69
69
  | Setting | Type | Default | Description |
70
70
  |---------|------|---------|-------------|
71
71
  | `branchSummary.reserveTokens` | number | `16384` | Tokens reserved for branch summarization |
72
+ | `branchSummary.skipPrompt` | boolean | `false` | Skip "Summarize branch?" prompt on `/tree` navigation (defaults to no summary) |
72
73
 
73
74
  ### Retry
74
75
 
@@ -33,6 +33,7 @@ cp permission-gate.ts ~/.draht/agent/extensions/
33
33
  | `question.ts` | Demonstrates `ctx.ui.select()` for asking the user questions with custom UI |
34
34
  | `questionnaire.ts` | Multi-question input with tab bar navigation between questions |
35
35
  | `tool-override.ts` | Override built-in tools (e.g., add logging/access control to `read`) |
36
+ | `dynamic-tools.ts` | Register tools after startup (`session_start`) and at runtime via command, with prompt snippets and tool-specific prompt guidelines |
36
37
  | `built-in-tool-renderer.ts` | Custom compact rendering for built-in tools (read, bash, edit, write) while keeping original behavior |
37
38
  | `minimal-mode.ts` | Override built-in tool rendering for minimal display (only tool calls, no output in collapsed mode) |
38
39
  | `truncated-tool.ts` | Wraps ripgrep with proper output truncation (50KB/2000 lines) |
@@ -49,8 +49,10 @@ type SaveMode = (typeof SAVE_MODES)[number];
49
49
 
50
50
  const ANTIGRAVITY_ENDPOINT = "https://daily-cloudcode-pa.sandbox.googleapis.com";
51
51
 
52
+ const DEFAULT_ANTIGRAVITY_VERSION = "1.18.3";
53
+
52
54
  const ANTIGRAVITY_HEADERS = {
53
- "User-Agent": "antigravity/1.15.8 darwin/arm64",
55
+ "User-Agent": `antigravity/${process.env.PI_AI_ANTIGRAVITY_VERSION || DEFAULT_ANTIGRAVITY_VERSION} darwin/arm64`,
54
56
  "X-Goog-Api-Client": "google-cloud-sdk vscode_cloudshelleditor/0.1",
55
57
  "Client-Metadata": JSON.stringify({
56
58
  ideType: "IDE_UNSPECIFIED",
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "pi-extension-custom-provider",
3
- "version": "1.6.3",
3
+ "version": "1.7.0",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "pi-extension-custom-provider",
9
- "version": "1.6.3",
9
+ "version": "1.7.0",
10
10
  "dependencies": {
11
11
  "@anthropic-ai/sdk": "^0.52.0"
12
12
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pi-extension-custom-provider-anthropic",
3
3
  "private": true,
4
- "version": "1.6.3",
4
+ "version": "1.7.0",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pi-extension-custom-provider-gitlab-duo",
3
3
  "private": true,
4
- "version": "1.6.3",
4
+ "version": "1.7.0",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pi-extension-custom-provider-qwen-cli",
3
3
  "private": true,
4
- "version": "1.5.3",
4
+ "version": "1.6.0",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Dynamic Tools Extension
3
+ *
4
+ * Demonstrates registering tools after session initialization.
5
+ *
6
+ * - Registers one tool during session_start
7
+ * - Registers additional tools at runtime via /add-echo-tool <name>
8
+ */
9
+
10
+ import type { ExtensionAPI } from "@draht/coding-agent";
11
+ import { Type } from "@sinclair/typebox";
12
+
13
+ const ECHO_PARAMS = Type.Object({
14
+ message: Type.String({ description: "Message to echo" }),
15
+ });
16
+
17
+ function normalizeToolName(input: string): string | undefined {
18
+ const trimmed = input.trim().toLowerCase();
19
+ if (!trimmed) return undefined;
20
+ if (!/^[a-z0-9_]+$/.test(trimmed)) return undefined;
21
+ return trimmed;
22
+ }
23
+
24
+ export default function dynamicToolsExtension(pi: ExtensionAPI) {
25
+ const registeredToolNames = new Set<string>();
26
+
27
+ const registerEchoTool = (name: string, label: string, prefix: string): boolean => {
28
+ if (registeredToolNames.has(name)) {
29
+ return false;
30
+ }
31
+
32
+ registeredToolNames.add(name);
33
+ pi.registerTool({
34
+ name,
35
+ label,
36
+ description: `Echo a message with prefix: ${prefix}`,
37
+ promptSnippet: `Echo back user-provided text with ${prefix.trim()} prefix`,
38
+ promptGuidelines: ["Use this tool when the user asks for exact echo output."],
39
+ parameters: ECHO_PARAMS,
40
+ async execute(_toolCallId, params) {
41
+ return {
42
+ content: [{ type: "text", text: `${prefix}${params.message}` }],
43
+ details: { tool: name, prefix },
44
+ };
45
+ },
46
+ });
47
+
48
+ return true;
49
+ };
50
+
51
+ pi.on("session_start", (_event, ctx) => {
52
+ registerEchoTool("echo_session", "Echo Session", "[session] ");
53
+ ctx.ui.notify("Registered dynamic tool: echo_session", "info");
54
+ });
55
+
56
+ pi.registerCommand("add-echo-tool", {
57
+ description: "Register a new echo tool dynamically: /add-echo-tool <tool_name>",
58
+ handler: async (args, ctx) => {
59
+ const toolName = normalizeToolName(args);
60
+ if (!toolName) {
61
+ ctx.ui.notify("Usage: /add-echo-tool <tool_name> (lowercase, numbers, underscores)", "warning");
62
+ return;
63
+ }
64
+
65
+ const created = registerEchoTool(toolName, `Echo ${toolName}`, `[${toolName}] `);
66
+ if (!created) {
67
+ ctx.ui.notify(`Tool already registered: ${toolName}`, "warning");
68
+ return;
69
+ }
70
+
71
+ ctx.ui.notify(`Registered dynamic tool: ${toolName}`, "info");
72
+ },
73
+ });
74
+ }
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "pi-extension-with-deps",
3
- "version": "1.19.3",
3
+ "version": "1.20.0",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "pi-extension-with-deps",
9
- "version": "1.19.3",
9
+ "version": "1.20.0",
10
10
  "dependencies": {
11
11
  "ms": "^2.1.3"
12
12
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pi-extension-with-deps",
3
3
  "private": true,
4
- "version": "1.19.3",
4
+ "version": "1.20.0",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@draht/coding-agent",
3
- "version": "2026.3.3",
3
+ "version": "2026.3.4",
4
4
  "description": "Coding agent CLI with read, bash, edit, write tools and session management",
5
5
  "type": "module",
6
6
  "drahtConfig": {
@@ -30,7 +30,6 @@
30
30
  "examples",
31
31
  "prompts",
32
32
  "hooks",
33
- "extensions",
34
33
  "agents",
35
34
  "bin",
36
35
  "CHANGELOG.md"
@@ -40,16 +39,16 @@
40
39
  "dev": "tsgo -p tsconfig.build.json --watch --preserveWatchOutput",
41
40
  "build": "tsgo -p tsconfig.build.json && shx chmod +x dist/cli.js && bun run copy-assets",
42
41
  "build:binary": "bun run build && bun build --compile ./dist/cli.js --outfile dist/pi && bun run copy-binary-assets",
43
- "copy-assets": "shx mkdir -p dist/modes/interactive/theme && shx cp src/modes/interactive/theme/*.json dist/modes/interactive/theme/ && shx mkdir -p dist/core/export-html/vendor && shx cp src/core/export-html/template.html src/core/export-html/template.css src/core/export-html/template.js dist/core/export-html/ && shx cp src/core/export-html/vendor/*.js dist/core/export-html/vendor/ && shx rm -rf dist/prompts dist/hooks dist/extensions dist/agents && shx cp -r prompts dist/prompts && shx cp -r hooks dist/hooks && shx cp -r extensions dist/extensions && shx cp -r agents dist/agents",
44
- "copy-binary-assets": "shx cp package.json dist/ && shx cp README.md dist/ && shx cp CHANGELOG.md dist/ && shx mkdir -p dist/theme && shx cp src/modes/interactive/theme/*.json dist/theme/ && shx mkdir -p dist/export-html/vendor && shx cp src/core/export-html/template.html dist/export-html/ && shx cp src/core/export-html/vendor/*.js dist/export-html/vendor/ && shx cp -r docs dist/ && shx cp -r examples dist/ && shx cp -r prompts dist/ && shx cp -r hooks dist/ && shx cp -r extensions dist/ && shx cp -r agents dist/ && shx cp ../../node_modules/@silvia-odwyer/photon-node/photon_rs_bg.wasm dist/",
42
+ "copy-assets": "shx mkdir -p dist/modes/interactive/theme && shx cp src/modes/interactive/theme/*.json dist/modes/interactive/theme/ && shx mkdir -p dist/core/export-html/vendor && shx cp src/core/export-html/template.html src/core/export-html/template.css src/core/export-html/template.js dist/core/export-html/ && shx cp src/core/export-html/vendor/*.js dist/core/export-html/vendor/ && shx rm -rf dist/prompts dist/hooks dist/agents && shx cp -r prompts dist/prompts && shx cp -r hooks dist/hooks && shx cp -r agents dist/agents",
43
+ "copy-binary-assets": "shx cp package.json dist/ && shx cp README.md dist/ && shx cp CHANGELOG.md dist/ && shx mkdir -p dist/theme && shx cp src/modes/interactive/theme/*.json dist/theme/ && shx mkdir -p dist/export-html/vendor && shx cp src/core/export-html/template.html dist/export-html/ && shx cp src/core/export-html/vendor/*.js dist/export-html/vendor/ && shx cp -r docs dist/ && shx cp -r examples dist/ && shx cp -r prompts dist/ && shx cp -r hooks dist/ && shx cp -r agents dist/ && shx cp ../../node_modules/@silvia-odwyer/photon-node/photon_rs_bg.wasm dist/",
45
44
  "test": "vitest --run",
46
45
  "prepublishOnly": "bun run clean && bun run build"
47
46
  },
48
47
  "dependencies": {
49
48
  "@mariozechner/jiti": "^2.6.2",
50
- "@draht/agent-core": "2026.3.3",
51
- "@draht/ai": "2026.3.3",
52
- "@draht/tui": "2026.3.3",
49
+ "@draht/agent-core": "2026.3.4",
50
+ "@draht/ai": "2026.3.4",
51
+ "@draht/tui": "2026.3.4",
53
52
  "@silvia-odwyer/photon-node": "^0.3.4",
54
53
  "chalk": "^5.5.0",
55
54
  "cli-highlight": "^2.1.11",
@@ -62,6 +61,8 @@
62
61
  "marked": "^15.0.12",
63
62
  "minimatch": "^10.2.3",
64
63
  "proper-lockfile": "^4.1.2",
64
+ "strip-ansi": "^7.1.0",
65
+ "undici": "^7.19.1",
65
66
  "yaml": "^2.8.2"
66
67
  },
67
68
  "overrides": {
@@ -0,0 +1,29 @@
1
+ # /fix
2
+
3
+ Diagnose and fix a specific bug or failing task with TDD discipline.
4
+
5
+ ## Usage
6
+ ```
7
+ /fix [description of what's broken]
8
+ ```
9
+
10
+ ## Steps
11
+ 1. **Diagnose**: Read the relevant code and error output to identify the root cause
12
+ - If a test is failing, run it first to see the actual error
13
+ - If a runtime bug, reproduce it and capture the error
14
+ 2. **Write a reproducing test**: Before touching any implementation:
15
+ - Write a test that demonstrates the bug (it must fail)
16
+ - Commit: `draht-tools commit-docs "red: reproduce bug"`
17
+ 3. **Minimal fix**: Write the smallest change that makes the test pass
18
+ - Do not refactor or add features — just fix the bug
19
+ - Run the full test suite to check for regressions
20
+ - Commit: `draht-tools commit-docs "green: fix description"`
21
+ 4. **Refactor** (if needed): Clean up without changing behavior
22
+ - Tests must stay green after every change
23
+ - Commit: `draht-tools commit-docs "refactor: description"`
24
+ 5. **Update state**: `draht-tools update-state`
25
+
26
+ ## Rules
27
+ - Always reproduce before fixing — a fix without a test is a guess
28
+ - One bug, one fix, one commit. Do not bundle unrelated changes.
29
+ - If the root cause spans multiple files, explain the chain in the commit message
@@ -0,0 +1,49 @@
1
+ # /init-project
2
+
3
+ Initialize GSD planning framework for an existing project: codebase mapping → questioning → domain model → requirements → roadmap.
4
+
5
+ ## Usage
6
+ ```
7
+ /init-project [focus area or goal]
8
+ ```
9
+
10
+ Use this when you have an existing codebase and want to add GSD methodology.
11
+ For greenfield projects, use `/new-project` instead.
12
+
13
+ ## Steps
14
+ 1. Run `draht-tools init` to check preconditions (git repo, etc.)
15
+ 2. Run `draht-tools map-codebase` to build a structural map of the existing code
16
+ 3. Analyze the codebase map to understand architecture, tech stack, and conventions
17
+ 4. Deep questioning phase (3-7 rounds, 1-2 questions at a time):
18
+ - What is this project? Who uses it?
19
+ - What are the current pain points or goals?
20
+ - What is MVP vs aspirational scope?
21
+ - What constraints exist (infra, team size, deadlines)?
22
+ 5. Run `draht-tools create-project` with gathered info
23
+ 6. Run `draht-tools create-domain-model` to define bounded contexts, entities, and ubiquitous language
24
+ 7. Create `.planning/DOMAIN.md` with:
25
+ - `## Bounded Contexts` — each context with name, responsibility, and brief description
26
+ - `## Ubiquitous Language` — glossary of domain terms agreed with the user (term → definition)
27
+ - `## Context Map` — how bounded contexts relate to each other (upstream/downstream, shared kernel, ACL)
28
+ - `## Aggregates` — aggregates and their root entities per context
29
+ - `## Domain Events` — named events that cross context boundaries
30
+ 8. Create `.planning/TEST-STRATEGY.md` with:
31
+ - `## Test Framework` — chosen framework and rationale
32
+ - `## Directory Conventions` — where test files live relative to source
33
+ - `## Coverage Goals` — target coverage percentage and which paths are critical
34
+ - `## Testing Levels` — what is tested at unit level vs integration vs e2e, with examples
35
+ - `## Excluded` — what is explicitly not tested and why (config files, generated code, etc.)
36
+ 9. Optional research phase via `draht-tools research`
37
+ 10. Run `draht-tools create-requirements` with v1/v2/out-of-scope (map requirements to bounded contexts)
38
+ 11. Run `draht-tools create-roadmap` with phases
39
+ 12. Run `draht-tools init-state`
40
+ 13. Git commit via `draht-tools commit-docs "initialize GSD planning"`
41
+
42
+ ## Rules
43
+ - Ask 1-2 questions at a time, never dump 10 at once
44
+ - Follow threads based on answers
45
+ - Use examples ("Like Stripe Checkout, or custom?")
46
+ - Confirm, don't assume
47
+ - 3-7 follow-up rounds typical
48
+ - Respect what already exists — do not propose rewriting working code
49
+ - Stop when you have: current state, goals, MVP scope, constraints, success criteria
@@ -0,0 +1,44 @@
1
+ # /next-milestone
2
+
3
+ Plan the next milestone after the current one is complete.
4
+
5
+ ## Usage
6
+ ```
7
+ /next-milestone
8
+ ```
9
+
10
+ ## Prerequisites
11
+ - `.planning/ROADMAP.md` must exist
12
+ - Current milestone should be complete or nearly complete
13
+
14
+ ## Steps
15
+ 1. Load project context:
16
+ - Read `.planning/ROADMAP.md` — identify the completed milestone and its phases
17
+ - Read `.planning/STATE.md` — understand current status
18
+ - Read `.planning/REQUIREMENTS.md` — check which requirements are satisfied
19
+ - Read `.planning/DOMAIN.md` (if exists) — review domain model for evolution needs
20
+ 2. Review completed work:
21
+ - Scan `.planning/phases/` for all UAT reports (`*-UAT.md`) and summaries (`*-SUMMARY.md`)
22
+ - Note what was built, what worked well, what had issues
23
+ 3. Assess requirements:
24
+ - Which v1 requirements are now satisfied?
25
+ - Which v1 requirements remain?
26
+ - Should any v2 requirements be promoted based on what we learned?
27
+ - Are there new requirements discovered during implementation?
28
+ 4. Propose next milestone:
29
+ - Define 3-5 phases, each with a clear goal (outcome, not activity)
30
+ - Order phases by dependency
31
+ - Map each phase to specific requirements
32
+ - Estimate relative complexity
33
+ 5. Present the proposed milestone for user approval before writing files
34
+ 6. After approval:
35
+ - Update `ROADMAP.md` with the new milestone and phases
36
+ - Update `STATE.md` to reflect milestone transition
37
+ - Update `REQUIREMENTS.md` if requirements changed
38
+ - Update `DOMAIN.md` if domain model needs evolution
39
+ - Commit: `draht-tools commit-docs "plan next milestone"`
40
+
41
+ ## Rules
42
+ - Always review what was actually built, not just what was planned
43
+ - Be honest about requirements that slipped or changed scope
44
+ - Each phase goal must be testable — "user can X" not "implement Y"
@@ -0,0 +1,26 @@
1
+ # /review
2
+
3
+ Ad-hoc code review and security audit of recent changes or a specific scope.
4
+
5
+ ## Usage
6
+ ```
7
+ /review [scope]
8
+ ```
9
+
10
+ If no scope given, reviews all recent uncommitted changes.
11
+
12
+ ## Steps
13
+ 1. Identify the scope:
14
+ - If argument given: review those files/directories/description
15
+ - If no argument: run `git diff --stat` and `git diff --cached --stat` to find changes
16
+ 2. For each changed file, examine:
17
+ - Correctness: logic errors, off-by-one, null handling, error paths
18
+ - Type safety: any `as` casts, `any` types, missing null checks
19
+ - Conventions: naming, file organization, import style
20
+ - Security: injection risks, auth bypasses, secrets in code, unsafe deserialization
21
+ - Performance: unnecessary allocations, missing indexes, N+1 queries
22
+ 3. Produce a prioritized findings report:
23
+ - **Critical** — must fix before merge (security, data loss, crashes)
24
+ - **Important** — should fix (bugs, type issues, missing error handling)
25
+ - **Minor** — style, naming, or optional improvements
26
+ 4. For each finding: cite the exact file and line, explain the issue, suggest the fix