@draht/coding-agent 2026.3.11-1 → 2026.3.25-1
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/CHANGELOG.md +45 -0
- package/README.md +45 -30
- package/bin/draht-tools.cjs +187 -32
- package/dist/bun/cli.d.ts +3 -0
- package/dist/bun/cli.d.ts.map +1 -0
- package/dist/bun/cli.js +7 -0
- package/dist/bun/cli.js.map +1 -0
- package/dist/bun/register-bedrock.d.ts +2 -0
- package/dist/bun/register-bedrock.d.ts.map +1 -0
- package/dist/bun/register-bedrock.js +4 -0
- package/dist/bun/register-bedrock.js.map +1 -0
- package/dist/cli/args.d.ts +1 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +11 -6
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/file-processor.d.ts.map +1 -1
- package/dist/cli/file-processor.js +4 -0
- package/dist/cli/file-processor.js.map +1 -1
- package/dist/cli/initial-message.d.ts +18 -0
- package/dist/cli/initial-message.d.ts.map +1 -0
- package/dist/cli/initial-message.js +22 -0
- package/dist/cli/initial-message.js.map +1 -0
- package/dist/cli/session-picker.d.ts.map +1 -1
- package/dist/cli/session-picker.js +2 -1
- package/dist/cli/session-picker.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +1 -3
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +2 -2
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session.d.ts +38 -5
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +201 -73
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/bash-executor.d.ts +6 -7
- package/dist/core/bash-executor.d.ts.map +1 -1
- package/dist/core/bash-executor.js +8 -107
- package/dist/core/bash-executor.js.map +1 -1
- package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
- package/dist/core/compaction/branch-summarization.js +1 -0
- package/dist/core/compaction/branch-summarization.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +2 -0
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/exec.d.ts.map +1 -1
- package/dist/core/exec.js +7 -3
- package/dist/core/exec.js.map +1 -1
- package/dist/core/export-html/index.d.ts +2 -2
- package/dist/core/export-html/index.d.ts.map +1 -1
- package/dist/core/export-html/index.js +7 -6
- package/dist/core/export-html/index.js.map +1 -1
- package/dist/core/export-html/template.css +43 -13
- package/dist/core/export-html/template.html +1 -0
- package/dist/core/export-html/template.js +107 -0
- package/dist/core/export-html/tool-renderer.d.ts +2 -2
- package/dist/core/export-html/tool-renderer.d.ts.map +1 -1
- package/dist/core/export-html/tool-renderer.js +41 -16
- package/dist/core/export-html/tool-renderer.js.map +1 -1
- package/dist/core/extensions/index.d.ts +4 -3
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +16 -6
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +9 -9
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +89 -71
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +49 -13
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/extensions/wrapper.d.ts +4 -11
- package/dist/core/extensions/wrapper.d.ts.map +1 -1
- package/dist/core/extensions/wrapper.js +6 -86
- package/dist/core/extensions/wrapper.js.map +1 -1
- package/dist/core/footer-data-provider.d.ts +13 -1
- package/dist/core/footer-data-provider.d.ts.map +1 -1
- package/dist/core/footer-data-provider.js +155 -37
- package/dist/core/footer-data-provider.js.map +1 -1
- package/dist/core/index.d.ts +2 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +2 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/keybindings.d.ts +270 -50
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +222 -134
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/model-registry.d.ts +1 -0
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +49 -23
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-resolver.d.ts +6 -0
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +41 -17
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/output-guard.d.ts +6 -0
- package/dist/core/output-guard.d.ts.map +1 -0
- package/dist/core/output-guard.js +59 -0
- package/dist/core/output-guard.js.map +1 -0
- package/dist/core/package-manager.d.ts +22 -1
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +374 -54
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/prompt-templates.d.ts +2 -1
- package/dist/core/prompt-templates.d.ts.map +1 -1
- package/dist/core/prompt-templates.js +39 -39
- package/dist/core/prompt-templates.js.map +1 -1
- package/dist/core/resolve-config-value.d.ts.map +1 -1
- package/dist/core/resolve-config-value.js +43 -8
- package/dist/core/resolve-config-value.js.map +1 -1
- package/dist/core/resource-loader.d.ts +6 -7
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +141 -118
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/sdk.d.ts +3 -3
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +4 -4
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager.d.ts +6 -0
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +9 -10
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +3 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +8 -0
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/skills.d.ts +5 -3
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js +54 -9
- package/dist/core/skills.js.map +1 -1
- package/dist/core/slash-commands.d.ts +2 -3
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +3 -2
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/source-info.d.ts +18 -0
- package/dist/core/source-info.d.ts.map +1 -0
- package/dist/core/source-info.js +19 -0
- package/dist/core/source-info.js.map +1 -0
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +17 -60
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tools/bash.d.ts +24 -6
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +210 -110
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/edit-diff.d.ts.map +1 -1
- package/dist/core/tools/edit-diff.js +1 -0
- package/dist/core/tools/edit-diff.js.map +1 -1
- package/dist/core/tools/edit.d.ts +14 -2
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +95 -23
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/file-mutation-queue.d.ts +6 -0
- package/dist/core/tools/file-mutation-queue.d.ts.map +1 -0
- package/dist/core/tools/file-mutation-queue.js +37 -0
- package/dist/core/tools/file-mutation-queue.js.map +1 -0
- package/dist/core/tools/find.d.ts +11 -4
- package/dist/core/tools/find.d.ts.map +1 -1
- package/dist/core/tools/find.js +82 -30
- package/dist/core/tools/find.js.map +1 -1
- package/dist/core/tools/grep.d.ts +15 -4
- package/dist/core/tools/grep.d.ts.map +1 -1
- package/dist/core/tools/grep.js +83 -29
- package/dist/core/tools/grep.js.map +1 -1
- package/dist/core/tools/index.d.ts +58 -19
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js +51 -26
- package/dist/core/tools/index.js.map +1 -1
- package/dist/core/tools/ls.d.ts +9 -3
- package/dist/core/tools/ls.d.ts.map +1 -1
- package/dist/core/tools/ls.js +67 -13
- package/dist/core/tools/ls.js.map +1 -1
- package/dist/core/tools/read.d.ts +10 -3
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +110 -51
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/render-utils.d.ts +21 -0
- package/dist/core/tools/render-utils.d.ts.map +1 -0
- package/dist/core/tools/render-utils.js +49 -0
- package/dist/core/tools/render-utils.js.map +1 -0
- package/dist/core/tools/tool-definition-wrapper.d.ts +14 -0
- package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -0
- package/dist/core/tools/tool-definition-wrapper.js +30 -0
- package/dist/core/tools/tool-definition-wrapper.js.map +1 -0
- package/dist/core/tools/write.d.ts +9 -3
- package/dist/core/tools/write.d.ts.map +1 -1
- package/dist/core/tools/write.js +168 -30
- package/dist/core/tools/write.js.map +1 -1
- package/dist/gsd/domain.d.ts +5 -1
- package/dist/gsd/domain.d.ts.map +1 -1
- package/dist/gsd/domain.js +71 -1
- package/dist/gsd/domain.js.map +1 -1
- package/dist/gsd/git.d.ts.map +1 -1
- package/dist/gsd/git.js +18 -0
- package/dist/gsd/git.js.map +1 -1
- package/dist/gsd/index.d.ts +1 -0
- package/dist/gsd/index.d.ts.map +1 -1
- package/dist/gsd/index.js.map +1 -1
- package/dist/index.d.ts +5 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -3
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +105 -226
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/bash-execution.d.ts +0 -1
- package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/bash-execution.js +22 -9
- package/dist/modes/interactive/components/bash-execution.js.map +1 -1
- package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -1
- package/dist/modes/interactive/components/bordered-loader.js +1 -1
- package/dist/modes/interactive/components/bordered-loader.js.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.js +2 -2
- package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.js +2 -2
- package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/config-selector.js +8 -8
- package/dist/modes/interactive/components/config-selector.js.map +1 -1
- package/dist/modes/interactive/components/custom-editor.d.ts +3 -3
- package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-editor.js +6 -6
- package/dist/modes/interactive/components/custom-editor.js.map +1 -1
- package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-editor.js +9 -9
- package/dist/modes/interactive/components/extension-editor.js.map +1 -1
- package/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-input.js +5 -5
- package/dist/modes/interactive/components/extension-input.js.map +1 -1
- package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-selector.js +8 -8
- package/dist/modes/interactive/components/extension-selector.js.map +1 -1
- package/dist/modes/interactive/components/index.d.ts +1 -1
- package/dist/modes/interactive/components/index.d.ts.map +1 -1
- package/dist/modes/interactive/components/index.js +1 -1
- package/dist/modes/interactive/components/index.js.map +1 -1
- package/dist/modes/interactive/components/keybinding-hints.d.ts +3 -36
- package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
- package/dist/modes/interactive/components/keybinding-hints.js +5 -44
- package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
- package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
- package/dist/modes/interactive/components/login-dialog.js +6 -6
- package/dist/modes/interactive/components/login-dialog.js.map +1 -1
- package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/model-selector.js +13 -9
- package/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.js +6 -6
- package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.js +4 -4
- package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
- package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector.js +32 -35
- package/dist/modes/interactive/components/session-selector.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +5 -1
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/show-images-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/show-images-selector.js +5 -1
- package/dist/modes/interactive/components/show-images-selector.js.map +1 -1
- package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/skill-invocation-message.js +2 -2
- package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
- package/dist/modes/interactive/components/theme-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/theme-selector.js +5 -1
- package/dist/modes/interactive/components/theme-selector.js.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.js +5 -1
- package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts +16 -34
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +128 -636
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/tree-selector.js +27 -16
- package/dist/modes/interactive/components/tree-selector.js.map +1 -1
- package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/user-message-selector.js +6 -6
- package/dist/modes/interactive/components/user-message-selector.js.map +1 -1
- package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/user-message.js +2 -1
- package/dist/modes/interactive/components/user-message.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +7 -11
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +353 -212
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/theme/theme.d.ts +3 -0
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +63 -37
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/modes/print-mode.d.ts.map +1 -1
- package/dist/modes/print-mode.js +5 -11
- package/dist/modes/print-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +27 -17
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +3 -4
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/dist/prompts/commands/execute-phase.md +2 -2
- package/dist/prompts/commands/fix.md +2 -2
- package/dist/prompts/commands/plan-phase.md +5 -1
- package/dist/prompts/commands/quick.md +5 -1
- package/dist/utils/changelog.d.ts +12 -0
- package/dist/utils/changelog.d.ts.map +1 -1
- package/dist/utils/changelog.js +25 -14
- package/dist/utils/changelog.js.map +1 -1
- package/dist/utils/child-process.d.ts +11 -0
- package/dist/utils/child-process.d.ts.map +1 -0
- package/dist/utils/child-process.js +78 -0
- package/dist/utils/child-process.js.map +1 -0
- package/dist/utils/clipboard-image.d.ts.map +1 -1
- package/dist/utils/clipboard-image.js +94 -11
- package/dist/utils/clipboard-image.js.map +1 -1
- package/dist/utils/clipboard-native.d.ts +1 -0
- package/dist/utils/clipboard-native.d.ts.map +1 -1
- package/dist/utils/clipboard-native.js.map +1 -1
- package/dist/utils/clipboard.d.ts +1 -1
- package/dist/utils/clipboard.d.ts.map +1 -1
- package/dist/utils/clipboard.js +27 -16
- package/dist/utils/clipboard.js.map +1 -1
- package/dist/utils/exif-orientation.d.ts +5 -0
- package/dist/utils/exif-orientation.d.ts.map +1 -0
- package/dist/utils/exif-orientation.js +158 -0
- package/dist/utils/exif-orientation.js.map +1 -0
- package/dist/utils/image-convert.d.ts.map +1 -1
- package/dist/utils/image-convert.js +5 -1
- package/dist/utils/image-convert.js.map +1 -1
- package/dist/utils/image-resize.d.ts +5 -5
- package/dist/utils/image-resize.d.ts.map +1 -1
- package/dist/utils/image-resize.js +51 -95
- package/dist/utils/image-resize.js.map +1 -1
- package/dist/utils/notify.d.ts +12 -0
- package/dist/utils/notify.d.ts.map +1 -0
- package/dist/utils/notify.js +41 -0
- package/dist/utils/notify.js.map +1 -0
- package/dist/utils/tools-manager.d.ts.map +1 -1
- package/dist/utils/tools-manager.js +5 -4
- package/dist/utils/tools-manager.js.map +1 -1
- package/docs/custom-provider.md +6 -2
- package/docs/extensions.md +108 -21
- package/docs/keybindings.md +103 -112
- package/docs/models.md +39 -1
- package/docs/packages.md +9 -0
- package/docs/providers.md +7 -0
- package/docs/rpc.md +15 -6
- package/docs/sdk.md +2 -2
- package/docs/settings.md +9 -0
- package/docs/terminal-setup.md +11 -0
- package/docs/tui.md +2 -2
- package/examples/extensions/README.md +2 -2
- package/examples/extensions/antigravity-image-gen.ts +9 -6
- package/examples/extensions/built-in-tool-renderer.ts +8 -8
- package/examples/extensions/commands.ts +3 -3
- package/examples/extensions/custom-provider-gitlab-duo/test.ts +2 -2
- package/examples/extensions/minimal-mode.ts +14 -14
- package/examples/extensions/notify.ts +9 -2
- package/examples/extensions/preset.ts +2 -3
- package/examples/extensions/question.ts +2 -2
- package/examples/extensions/questionnaire.ts +2 -2
- package/examples/extensions/sandbox/index.ts +2 -3
- package/examples/extensions/subagent/index.ts +30 -8
- package/examples/extensions/titlebar-spinner.ts +2 -2
- package/examples/extensions/todo.ts +2 -2
- package/examples/extensions/tool-override.ts +10 -9
- package/examples/extensions/truncated-tool.ts +8 -5
- package/examples/sdk/04-skills.ts +8 -2
- package/examples/sdk/08-prompt-templates.ts +8 -2
- package/examples/sdk/12-full-control.ts +0 -1
- package/examples/sdk/README.md +1 -1
- package/package.json +4 -4
- package/prompts/commands/execute-phase.md +2 -2
- package/prompts/commands/fix.md +2 -2
- package/prompts/commands/plan-phase.md +5 -1
- package/prompts/commands/quick.md +5 -1
|
@@ -60,10 +60,10 @@ export default function commandsExtension(pi: ExtensionAPI) {
|
|
|
60
60
|
if (selected && !selected.startsWith("---")) {
|
|
61
61
|
const cmdName = selected.split(" - ")[0].slice(1); // Remove leading /
|
|
62
62
|
const cmd = commands.find((c) => c.name === cmdName);
|
|
63
|
-
if (cmd?.path) {
|
|
64
|
-
const showPath = await ctx.ui.confirm(cmd.name, `View source path?\n${cmd.path}`);
|
|
63
|
+
if (cmd?.sourceInfo.path) {
|
|
64
|
+
const showPath = await ctx.ui.confirm(cmd.name, `View source path?\n${cmd.sourceInfo.path}`);
|
|
65
65
|
if (showPath) {
|
|
66
|
-
ctx.ui.notify(cmd.path, "info");
|
|
66
|
+
ctx.ui.notify(cmd.sourceInfo.path, "info");
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
69
|
}
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
import { type Api, type Context, type Model, registerApiProvider, streamSimple } from "@draht/ai";
|
|
12
12
|
import { readFileSync } from "fs";
|
|
13
|
-
import {
|
|
13
|
+
import { getAgentDir } from "packages/coding-agent/src/config.js";
|
|
14
14
|
import { join } from "path";
|
|
15
15
|
import { MODELS, streamGitLabDuo } from "./index.js";
|
|
16
16
|
|
|
@@ -28,7 +28,7 @@ async function main() {
|
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
// Read auth
|
|
31
|
-
const authPath = join(
|
|
31
|
+
const authPath = join(getAgentDir(), "extensions", "auth.json");
|
|
32
32
|
const authData = JSON.parse(readFileSync(authPath, "utf-8"));
|
|
33
33
|
const gitlabCred = authData["gitlab-duo"];
|
|
34
34
|
if (!gitlabCred?.access) {
|
|
@@ -80,7 +80,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
80
80
|
return tools.read.execute(toolCallId, params, signal, onUpdate);
|
|
81
81
|
},
|
|
82
82
|
|
|
83
|
-
renderCall(args, theme) {
|
|
83
|
+
renderCall(args, theme, _context) {
|
|
84
84
|
const path = shortenPath(args.path || "");
|
|
85
85
|
let pathDisplay = path ? theme.fg("accent", path) : theme.fg("toolOutput", "...");
|
|
86
86
|
|
|
@@ -94,7 +94,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
94
94
|
return new Text(`${theme.fg("toolTitle", theme.bold("read"))} ${pathDisplay}`, 0, 0);
|
|
95
95
|
},
|
|
96
96
|
|
|
97
|
-
renderResult(result, { expanded }, theme) {
|
|
97
|
+
renderResult(result, { expanded }, theme, _context) {
|
|
98
98
|
// Minimal mode: show nothing in collapsed state
|
|
99
99
|
if (!expanded) {
|
|
100
100
|
return new Text("", 0, 0);
|
|
@@ -127,7 +127,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
127
127
|
return tools.bash.execute(toolCallId, params, signal, onUpdate);
|
|
128
128
|
},
|
|
129
129
|
|
|
130
|
-
renderCall(args, theme) {
|
|
130
|
+
renderCall(args, theme, _context) {
|
|
131
131
|
const command = args.command || "...";
|
|
132
132
|
const timeout = args.timeout as number | undefined;
|
|
133
133
|
const timeoutSuffix = timeout ? theme.fg("muted", ` (timeout ${timeout}s)`) : "";
|
|
@@ -135,7 +135,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
135
135
|
return new Text(theme.fg("toolTitle", theme.bold(`$ ${command}`)) + timeoutSuffix, 0, 0);
|
|
136
136
|
},
|
|
137
137
|
|
|
138
|
-
renderResult(result, { expanded }, theme) {
|
|
138
|
+
renderResult(result, { expanded }, theme, _context) {
|
|
139
139
|
// Minimal mode: show nothing in collapsed state
|
|
140
140
|
if (!expanded) {
|
|
141
141
|
return new Text("", 0, 0);
|
|
@@ -176,7 +176,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
176
176
|
return tools.write.execute(toolCallId, params, signal, onUpdate);
|
|
177
177
|
},
|
|
178
178
|
|
|
179
|
-
renderCall(args, theme) {
|
|
179
|
+
renderCall(args, theme, _context) {
|
|
180
180
|
const path = shortenPath(args.path || "");
|
|
181
181
|
const pathDisplay = path ? theme.fg("accent", path) : theme.fg("toolOutput", "...");
|
|
182
182
|
const lineCount = args.content ? args.content.split("\n").length : 0;
|
|
@@ -185,7 +185,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
185
185
|
return new Text(`${theme.fg("toolTitle", theme.bold("write"))} ${pathDisplay}${lineInfo}`, 0, 0);
|
|
186
186
|
},
|
|
187
187
|
|
|
188
|
-
renderResult(result, { expanded }, theme) {
|
|
188
|
+
renderResult(result, { expanded }, theme, _context) {
|
|
189
189
|
// Minimal mode: show nothing (file was written)
|
|
190
190
|
if (!expanded) {
|
|
191
191
|
return new Text("", 0, 0);
|
|
@@ -218,14 +218,14 @@ export default function (pi: ExtensionAPI) {
|
|
|
218
218
|
return tools.edit.execute(toolCallId, params, signal, onUpdate);
|
|
219
219
|
},
|
|
220
220
|
|
|
221
|
-
renderCall(args, theme) {
|
|
221
|
+
renderCall(args, theme, _context) {
|
|
222
222
|
const path = shortenPath(args.path || "");
|
|
223
223
|
const pathDisplay = path ? theme.fg("accent", path) : theme.fg("toolOutput", "...");
|
|
224
224
|
|
|
225
225
|
return new Text(`${theme.fg("toolTitle", theme.bold("edit"))} ${pathDisplay}`, 0, 0);
|
|
226
226
|
},
|
|
227
227
|
|
|
228
|
-
renderResult(result, { expanded }, theme) {
|
|
228
|
+
renderResult(result, { expanded }, theme, _context) {
|
|
229
229
|
// Minimal mode: show nothing in collapsed state
|
|
230
230
|
if (!expanded) {
|
|
231
231
|
return new Text("", 0, 0);
|
|
@@ -263,7 +263,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
263
263
|
return tools.find.execute(toolCallId, params, signal, onUpdate);
|
|
264
264
|
},
|
|
265
265
|
|
|
266
|
-
renderCall(args, theme) {
|
|
266
|
+
renderCall(args, theme, _context) {
|
|
267
267
|
const pattern = args.pattern || "";
|
|
268
268
|
const path = shortenPath(args.path || ".");
|
|
269
269
|
const limit = args.limit;
|
|
@@ -277,7 +277,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
277
277
|
return new Text(text, 0, 0);
|
|
278
278
|
},
|
|
279
279
|
|
|
280
|
-
renderResult(result, { expanded }, theme) {
|
|
280
|
+
renderResult(result, { expanded }, theme, _context) {
|
|
281
281
|
if (!expanded) {
|
|
282
282
|
// Minimal: just show count
|
|
283
283
|
const textContent = result.content.find((c) => c.type === "text");
|
|
@@ -321,7 +321,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
321
321
|
return tools.grep.execute(toolCallId, params, signal, onUpdate);
|
|
322
322
|
},
|
|
323
323
|
|
|
324
|
-
renderCall(args, theme) {
|
|
324
|
+
renderCall(args, theme, _context) {
|
|
325
325
|
const pattern = args.pattern || "";
|
|
326
326
|
const path = shortenPath(args.path || ".");
|
|
327
327
|
const glob = args.glob;
|
|
@@ -339,7 +339,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
339
339
|
return new Text(text, 0, 0);
|
|
340
340
|
},
|
|
341
341
|
|
|
342
|
-
renderResult(result, { expanded }, theme) {
|
|
342
|
+
renderResult(result, { expanded }, theme, _context) {
|
|
343
343
|
if (!expanded) {
|
|
344
344
|
// Minimal: just show match count
|
|
345
345
|
const textContent = result.content.find((c) => c.type === "text");
|
|
@@ -383,7 +383,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
383
383
|
return tools.ls.execute(toolCallId, params, signal, onUpdate);
|
|
384
384
|
},
|
|
385
385
|
|
|
386
|
-
renderCall(args, theme) {
|
|
386
|
+
renderCall(args, theme, _context) {
|
|
387
387
|
const path = shortenPath(args.path || ".");
|
|
388
388
|
const limit = args.limit;
|
|
389
389
|
|
|
@@ -395,7 +395,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
395
395
|
return new Text(text, 0, 0);
|
|
396
396
|
},
|
|
397
397
|
|
|
398
|
-
renderResult(result, { expanded }, theme) {
|
|
398
|
+
renderResult(result, { expanded }, theme, _context) {
|
|
399
399
|
if (!expanded) {
|
|
400
400
|
// Minimal: just show entry count
|
|
401
401
|
const textContent = result.content.find((c) => c.type === "text");
|
|
@@ -3,12 +3,14 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Sends a native terminal notification when Pi agent is done and waiting for input.
|
|
5
5
|
* Supports multiple terminal protocols:
|
|
6
|
+
* - cmux: uses `cmux notify` CLI
|
|
6
7
|
* - OSC 777: Ghostty, iTerm2, WezTerm, rxvt-unicode
|
|
7
8
|
* - OSC 99: Kitty
|
|
8
9
|
* - Windows toast: Windows Terminal (WSL)
|
|
9
10
|
*/
|
|
10
11
|
|
|
11
12
|
import type { ExtensionAPI } from "@draht/coding-agent";
|
|
13
|
+
import { execFile } from "child_process";
|
|
12
14
|
|
|
13
15
|
function windowsToastScript(title: string, body: string): string {
|
|
14
16
|
const type = "Windows.UI.Notifications";
|
|
@@ -33,13 +35,18 @@ function notifyOSC99(title: string, body: string): void {
|
|
|
33
35
|
process.stdout.write(`\x1b]99;i=1:p=body;${body}\x1b\\`);
|
|
34
36
|
}
|
|
35
37
|
|
|
38
|
+
function notifyCmux(title: string, body: string): void {
|
|
39
|
+
execFile("cmux", ["notify", "--title", title, "--body", body]);
|
|
40
|
+
}
|
|
41
|
+
|
|
36
42
|
function notifyWindows(title: string, body: string): void {
|
|
37
|
-
const { execFile } = require("child_process");
|
|
38
43
|
execFile("powershell.exe", ["-NoProfile", "-Command", windowsToastScript(title, body)]);
|
|
39
44
|
}
|
|
40
45
|
|
|
41
46
|
function notify(title: string, body: string): void {
|
|
42
|
-
if (process.env.
|
|
47
|
+
if (process.env.CMUX_BUNDLE_ID) {
|
|
48
|
+
notifyCmux(title, body);
|
|
49
|
+
} else if (process.env.WT_SESSION) {
|
|
43
50
|
notifyWindows(title, body);
|
|
44
51
|
} else if (process.env.KITTY_WINDOW_ID) {
|
|
45
52
|
notifyOSC99(title, body);
|
|
@@ -39,10 +39,9 @@
|
|
|
39
39
|
*/
|
|
40
40
|
|
|
41
41
|
import { existsSync, readFileSync } from "node:fs";
|
|
42
|
-
import { homedir } from "node:os";
|
|
43
42
|
import { join } from "node:path";
|
|
44
43
|
import type { ExtensionAPI, ExtensionContext } from "@draht/coding-agent";
|
|
45
|
-
import { DynamicBorder } from "@draht/coding-agent";
|
|
44
|
+
import { DynamicBorder, getAgentDir } from "@draht/coding-agent";
|
|
46
45
|
import { Container, Key, type SelectItem, SelectList, Text } from "@draht/tui";
|
|
47
46
|
|
|
48
47
|
// Preset configuration
|
|
@@ -68,7 +67,7 @@ interface PresetsConfig {
|
|
|
68
67
|
* Project-local presets override global presets with the same name.
|
|
69
68
|
*/
|
|
70
69
|
function loadPresets(cwd: string): PresetsConfig {
|
|
71
|
-
const globalPath = join(
|
|
70
|
+
const globalPath = join(getAgentDir(), "presets.json");
|
|
72
71
|
const projectPath = join(cwd, ".pi", "presets.json");
|
|
73
72
|
|
|
74
73
|
let globalPresets: PresetsConfig = {};
|
|
@@ -227,7 +227,7 @@ export default function question(pi: ExtensionAPI) {
|
|
|
227
227
|
};
|
|
228
228
|
},
|
|
229
229
|
|
|
230
|
-
renderCall(args, theme) {
|
|
230
|
+
renderCall(args, theme, _context) {
|
|
231
231
|
let text = theme.fg("toolTitle", theme.bold("question ")) + theme.fg("muted", args.question);
|
|
232
232
|
const opts = Array.isArray(args.options) ? args.options : [];
|
|
233
233
|
if (opts.length) {
|
|
@@ -238,7 +238,7 @@ export default function question(pi: ExtensionAPI) {
|
|
|
238
238
|
return new Text(text, 0, 0);
|
|
239
239
|
},
|
|
240
240
|
|
|
241
|
-
renderResult(result, _options, theme) {
|
|
241
|
+
renderResult(result, _options, theme, _context) {
|
|
242
242
|
const details = result.details as QuestionDetails | undefined;
|
|
243
243
|
if (!details) {
|
|
244
244
|
const text = result.content[0];
|
|
@@ -393,7 +393,7 @@ export default function questionnaire(pi: ExtensionAPI) {
|
|
|
393
393
|
};
|
|
394
394
|
},
|
|
395
395
|
|
|
396
|
-
renderCall(args, theme) {
|
|
396
|
+
renderCall(args, theme, _context) {
|
|
397
397
|
const qs = (args.questions as Question[]) || [];
|
|
398
398
|
const count = qs.length;
|
|
399
399
|
const labels = qs.map((q) => q.label || q.id).join(", ");
|
|
@@ -405,7 +405,7 @@ export default function questionnaire(pi: ExtensionAPI) {
|
|
|
405
405
|
return new Text(text, 0, 0);
|
|
406
406
|
},
|
|
407
407
|
|
|
408
|
-
renderResult(result, _options, theme) {
|
|
408
|
+
renderResult(result, _options, theme, _context) {
|
|
409
409
|
const details = result.details as QuestionnaireResult | undefined;
|
|
410
410
|
if (!details) {
|
|
411
411
|
const text = result.content[0];
|
|
@@ -39,11 +39,10 @@
|
|
|
39
39
|
|
|
40
40
|
import { spawn } from "node:child_process";
|
|
41
41
|
import { existsSync, readFileSync } from "node:fs";
|
|
42
|
-
import { homedir } from "node:os";
|
|
43
42
|
import { join } from "node:path";
|
|
44
43
|
import { SandboxManager, type SandboxRuntimeConfig } from "@anthropic-ai/sandbox-runtime";
|
|
45
44
|
import type { ExtensionAPI } from "@draht/coding-agent";
|
|
46
|
-
import { type BashOperations, createBashTool } from "@draht/coding-agent";
|
|
45
|
+
import { type BashOperations, createBashTool, getAgentDir } from "@draht/coding-agent";
|
|
47
46
|
|
|
48
47
|
interface SandboxConfig extends SandboxRuntimeConfig {
|
|
49
48
|
enabled?: boolean;
|
|
@@ -75,7 +74,7 @@ const DEFAULT_CONFIG: SandboxConfig = {
|
|
|
75
74
|
|
|
76
75
|
function loadConfig(cwd: string): SandboxConfig {
|
|
77
76
|
const projectConfigPath = join(cwd, ".pi", "sandbox.json");
|
|
78
|
-
const globalConfigPath = join(
|
|
77
|
+
const globalConfigPath = join(getAgentDir(), "extensions", "sandbox.json");
|
|
79
78
|
|
|
80
79
|
let globalConfig: Partial<SandboxConfig> = {};
|
|
81
80
|
let projectConfig: Partial<SandboxConfig> = {};
|
|
@@ -19,7 +19,7 @@ import * as path from "node:path";
|
|
|
19
19
|
import type { AgentToolResult } from "@draht/agent-core";
|
|
20
20
|
import type { Message } from "@draht/ai";
|
|
21
21
|
import { StringEnum } from "@draht/ai";
|
|
22
|
-
import { type ExtensionAPI, getMarkdownTheme } from "@draht/coding-agent";
|
|
22
|
+
import { type ExtensionAPI, getMarkdownTheme, withFileMutationQueue } from "@draht/coding-agent";
|
|
23
23
|
import { Container, Markdown, Spacer, Text } from "@draht/tui";
|
|
24
24
|
import { Type } from "@sinclair/typebox";
|
|
25
25
|
import { type AgentConfig, type AgentScope, discoverAgents } from "./agents.js";
|
|
@@ -207,14 +207,31 @@ async function mapWithConcurrencyLimit<TIn, TOut>(
|
|
|
207
207
|
return results;
|
|
208
208
|
}
|
|
209
209
|
|
|
210
|
-
function writePromptToTempFile(agentName: string, prompt: string): { dir: string; filePath: string } {
|
|
211
|
-
const tmpDir = fs.
|
|
210
|
+
async function writePromptToTempFile(agentName: string, prompt: string): Promise<{ dir: string; filePath: string }> {
|
|
211
|
+
const tmpDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), "pi-subagent-"));
|
|
212
212
|
const safeName = agentName.replace(/[^\w.-]+/g, "_");
|
|
213
213
|
const filePath = path.join(tmpDir, `prompt-${safeName}.md`);
|
|
214
|
-
|
|
214
|
+
await withFileMutationQueue(filePath, async () => {
|
|
215
|
+
await fs.promises.writeFile(filePath, prompt, { encoding: "utf-8", mode: 0o600 });
|
|
216
|
+
});
|
|
215
217
|
return { dir: tmpDir, filePath };
|
|
216
218
|
}
|
|
217
219
|
|
|
220
|
+
function getPiInvocation(args: string[]): { command: string; args: string[] } {
|
|
221
|
+
const currentScript = process.argv[1];
|
|
222
|
+
if (currentScript && fs.existsSync(currentScript)) {
|
|
223
|
+
return { command: process.execPath, args: [currentScript, ...args] };
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
const execName = path.basename(process.execPath).toLowerCase();
|
|
227
|
+
const isGenericRuntime = /^(node|bun)(\.exe)?$/.test(execName);
|
|
228
|
+
if (!isGenericRuntime) {
|
|
229
|
+
return { command: process.execPath, args };
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
return { command: "pi", args };
|
|
233
|
+
}
|
|
234
|
+
|
|
218
235
|
type OnUpdateCallback = (partial: AgentToolResult<SubagentDetails>) => void;
|
|
219
236
|
|
|
220
237
|
async function runSingleAgent(
|
|
@@ -274,7 +291,7 @@ async function runSingleAgent(
|
|
|
274
291
|
|
|
275
292
|
try {
|
|
276
293
|
if (agent.systemPrompt.trim()) {
|
|
277
|
-
const tmp = writePromptToTempFile(agent.name, agent.systemPrompt);
|
|
294
|
+
const tmp = await writePromptToTempFile(agent.name, agent.systemPrompt);
|
|
278
295
|
tmpPromptDir = tmp.dir;
|
|
279
296
|
tmpPromptPath = tmp.filePath;
|
|
280
297
|
args.push("--append-system-prompt", tmpPromptPath);
|
|
@@ -284,7 +301,12 @@ async function runSingleAgent(
|
|
|
284
301
|
let wasAborted = false;
|
|
285
302
|
|
|
286
303
|
const exitCode = await new Promise<number>((resolve) => {
|
|
287
|
-
const
|
|
304
|
+
const invocation = getPiInvocation(args);
|
|
305
|
+
const proc = spawn(invocation.command, invocation.args, {
|
|
306
|
+
cwd: cwd ?? defaultCwd,
|
|
307
|
+
shell: false,
|
|
308
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
309
|
+
});
|
|
288
310
|
let buffer = "";
|
|
289
311
|
|
|
290
312
|
const processLine = (line: string) => {
|
|
@@ -646,7 +668,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
646
668
|
};
|
|
647
669
|
},
|
|
648
670
|
|
|
649
|
-
renderCall(args, theme) {
|
|
671
|
+
renderCall(args, theme, _context) {
|
|
650
672
|
const scope: AgentScope = args.agentScope ?? "user";
|
|
651
673
|
if (args.chain && args.chain.length > 0) {
|
|
652
674
|
let text =
|
|
@@ -690,7 +712,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
690
712
|
return new Text(text, 0, 0);
|
|
691
713
|
},
|
|
692
714
|
|
|
693
|
-
renderResult(result, { expanded }, theme) {
|
|
715
|
+
renderResult(result, { expanded }, theme, _context) {
|
|
694
716
|
const details = result.details as SubagentDetails | undefined;
|
|
695
717
|
if (!details || details.results.length === 0) {
|
|
696
718
|
const text = result.content[0];
|
|
@@ -16,7 +16,7 @@ const BRAILLE_FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧",
|
|
|
16
16
|
function getBaseTitle(pi: ExtensionAPI): string {
|
|
17
17
|
const cwd = path.basename(process.cwd());
|
|
18
18
|
const session = pi.getSessionName();
|
|
19
|
-
return session ?
|
|
19
|
+
return session ? `D - ${session} - ${cwd}` : `D - ${cwd}`;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
export default function (pi: ExtensionAPI) {
|
|
@@ -38,7 +38,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
38
38
|
const frame = BRAILLE_FRAMES[frameIndex % BRAILLE_FRAMES.length];
|
|
39
39
|
const cwd = path.basename(process.cwd());
|
|
40
40
|
const session = pi.getSessionName();
|
|
41
|
-
const title = session ? `${frame}
|
|
41
|
+
const title = session ? `${frame} D - ${session} - ${cwd}` : `${frame} D - ${cwd}`;
|
|
42
42
|
ctx.ui.setTitle(title);
|
|
43
43
|
frameIndex++;
|
|
44
44
|
}, 80);
|
|
@@ -220,14 +220,14 @@ export default function (pi: ExtensionAPI) {
|
|
|
220
220
|
}
|
|
221
221
|
},
|
|
222
222
|
|
|
223
|
-
renderCall(args, theme) {
|
|
223
|
+
renderCall(args, theme, _context) {
|
|
224
224
|
let text = theme.fg("toolTitle", theme.bold("todo ")) + theme.fg("muted", args.action);
|
|
225
225
|
if (args.text) text += ` ${theme.fg("dim", `"${args.text}"`)}`;
|
|
226
226
|
if (args.id !== undefined) text += ` ${theme.fg("accent", `#${args.id}`)}`;
|
|
227
227
|
return new Text(text, 0, 0);
|
|
228
228
|
},
|
|
229
229
|
|
|
230
|
-
renderResult(result, { expanded }, theme) {
|
|
230
|
+
renderResult(result, { expanded }, theme, _context) {
|
|
231
231
|
const details = result.details as TodoDetails | undefined;
|
|
232
232
|
if (!details) {
|
|
233
233
|
const text = result.content[0];
|
|
@@ -21,14 +21,13 @@
|
|
|
21
21
|
*/
|
|
22
22
|
|
|
23
23
|
import type { TextContent } from "@draht/ai";
|
|
24
|
-
import type
|
|
24
|
+
import { type ExtensionAPI, getAgentDir, withFileMutationQueue } from "@draht/coding-agent";
|
|
25
25
|
import { Type } from "@sinclair/typebox";
|
|
26
|
-
import {
|
|
27
|
-
import { access, readFile } from "fs/promises";
|
|
28
|
-
import { homedir } from "os";
|
|
26
|
+
import { constants, readFileSync } from "fs";
|
|
27
|
+
import { access, appendFile, readFile } from "fs/promises";
|
|
29
28
|
import { join, resolve } from "path";
|
|
30
29
|
|
|
31
|
-
const LOG_FILE = join(
|
|
30
|
+
const LOG_FILE = join(getAgentDir(), "read-access.log");
|
|
32
31
|
|
|
33
32
|
// Paths that are blocked from reading
|
|
34
33
|
const BLOCKED_PATTERNS = [
|
|
@@ -45,14 +44,16 @@ function isBlockedPath(path: string): boolean {
|
|
|
45
44
|
return BLOCKED_PATTERNS.some((pattern) => pattern.test(path));
|
|
46
45
|
}
|
|
47
46
|
|
|
48
|
-
function logAccess(path: string, allowed: boolean, reason?: string) {
|
|
47
|
+
async function logAccess(path: string, allowed: boolean, reason?: string) {
|
|
49
48
|
const timestamp = new Date().toISOString();
|
|
50
49
|
const status = allowed ? "ALLOWED" : "BLOCKED";
|
|
51
50
|
const msg = reason ? ` (${reason})` : "";
|
|
52
51
|
const line = `[${timestamp}] ${status}: ${path}${msg}\n`;
|
|
53
52
|
|
|
54
53
|
try {
|
|
55
|
-
|
|
54
|
+
await withFileMutationQueue(LOG_FILE, async () => {
|
|
55
|
+
await appendFile(LOG_FILE, line);
|
|
56
|
+
});
|
|
56
57
|
} catch {
|
|
57
58
|
// Ignore logging errors
|
|
58
59
|
}
|
|
@@ -78,7 +79,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
78
79
|
|
|
79
80
|
// Check if path is blocked
|
|
80
81
|
if (isBlockedPath(absolutePath)) {
|
|
81
|
-
logAccess(absolutePath, false, "matches blocked pattern");
|
|
82
|
+
await logAccess(absolutePath, false, "matches blocked pattern");
|
|
82
83
|
return {
|
|
83
84
|
content: [
|
|
84
85
|
{
|
|
@@ -91,7 +92,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
91
92
|
}
|
|
92
93
|
|
|
93
94
|
// Log allowed access
|
|
94
|
-
logAccess(absolutePath, true);
|
|
95
|
+
await logAccess(absolutePath, true);
|
|
95
96
|
|
|
96
97
|
// Perform the actual read (simplified implementation)
|
|
97
98
|
try {
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
* built-in `grep` tool in src/core/tools/grep.ts for a more complete implementation.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
+
import { mkdtemp, writeFile } from "node:fs/promises";
|
|
17
18
|
import type { ExtensionAPI } from "@draht/coding-agent";
|
|
18
19
|
import {
|
|
19
20
|
DEFAULT_MAX_BYTES,
|
|
@@ -21,11 +22,11 @@ import {
|
|
|
21
22
|
formatSize,
|
|
22
23
|
type TruncationResult,
|
|
23
24
|
truncateHead,
|
|
25
|
+
withFileMutationQueue,
|
|
24
26
|
} from "@draht/coding-agent";
|
|
25
27
|
import { Text } from "@draht/tui";
|
|
26
28
|
import { Type } from "@sinclair/typebox";
|
|
27
29
|
import { execSync } from "child_process";
|
|
28
|
-
import { mkdtempSync, writeFileSync } from "fs";
|
|
29
30
|
import { tmpdir } from "os";
|
|
30
31
|
import { join } from "path";
|
|
31
32
|
|
|
@@ -108,9 +109,11 @@ export default function (pi: ExtensionAPI) {
|
|
|
108
109
|
|
|
109
110
|
if (truncation.truncated) {
|
|
110
111
|
// Save full output to a temp file so LLM can access it if needed
|
|
111
|
-
const tempDir =
|
|
112
|
+
const tempDir = await mkdtemp(join(tmpdir(), "pi-rg-"));
|
|
112
113
|
const tempFile = join(tempDir, "output.txt");
|
|
113
|
-
|
|
114
|
+
await withFileMutationQueue(tempFile, async () => {
|
|
115
|
+
await writeFile(tempFile, output, "utf8");
|
|
116
|
+
});
|
|
114
117
|
|
|
115
118
|
details.truncation = truncation;
|
|
116
119
|
details.fullOutputPath = tempFile;
|
|
@@ -132,7 +135,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
132
135
|
},
|
|
133
136
|
|
|
134
137
|
// Custom rendering of the tool call (shown before/during execution)
|
|
135
|
-
renderCall(args, theme) {
|
|
138
|
+
renderCall(args, theme, _context) {
|
|
136
139
|
let text = theme.fg("toolTitle", theme.bold("rg "));
|
|
137
140
|
text += theme.fg("accent", `"${args.pattern}"`);
|
|
138
141
|
if (args.path) {
|
|
@@ -145,7 +148,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
145
148
|
},
|
|
146
149
|
|
|
147
150
|
// Custom rendering of the tool result
|
|
148
|
-
renderResult(result, { expanded, isPartial }, theme) {
|
|
151
|
+
renderResult(result, { expanded, isPartial }, theme, _context) {
|
|
149
152
|
const details = result.details as RgDetails | undefined;
|
|
150
153
|
|
|
151
154
|
// Handle streaming/partial results
|
|
@@ -5,7 +5,13 @@
|
|
|
5
5
|
* Discover, filter, merge, or replace them.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
createAgentSession,
|
|
10
|
+
createSyntheticSourceInfo,
|
|
11
|
+
DefaultResourceLoader,
|
|
12
|
+
SessionManager,
|
|
13
|
+
type Skill,
|
|
14
|
+
} from "@draht/coding-agent";
|
|
9
15
|
|
|
10
16
|
// Or define custom skills inline
|
|
11
17
|
const customSkill: Skill = {
|
|
@@ -13,7 +19,7 @@ const customSkill: Skill = {
|
|
|
13
19
|
description: "Custom project instructions",
|
|
14
20
|
filePath: "/virtual/SKILL.md",
|
|
15
21
|
baseDir: "/virtual",
|
|
16
|
-
source: "
|
|
22
|
+
sourceInfo: createSyntheticSourceInfo("/virtual/SKILL.md", { source: "sdk" }),
|
|
17
23
|
disableModelInvocation: false,
|
|
18
24
|
};
|
|
19
25
|
|
|
@@ -4,14 +4,20 @@
|
|
|
4
4
|
* File-based templates that inject content when invoked with /templatename.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
createAgentSession,
|
|
9
|
+
createSyntheticSourceInfo,
|
|
10
|
+
DefaultResourceLoader,
|
|
11
|
+
type PromptTemplate,
|
|
12
|
+
SessionManager,
|
|
13
|
+
} from "@draht/coding-agent";
|
|
8
14
|
|
|
9
15
|
// Define custom templates
|
|
10
16
|
const deployTemplate: PromptTemplate = {
|
|
11
17
|
name: "deploy",
|
|
12
18
|
description: "Deploy the application",
|
|
13
|
-
source: "path",
|
|
14
19
|
filePath: "/virtual/prompts/deploy.md",
|
|
20
|
+
sourceInfo: createSyntheticSourceInfo("/virtual/prompts/deploy.md", { source: "sdk" }),
|
|
15
21
|
content: `# Deploy Instructions
|
|
16
22
|
|
|
17
23
|
1. Build: npm run build
|
|
@@ -53,7 +53,6 @@ const resourceLoader: ResourceLoader = {
|
|
|
53
53
|
getSystemPrompt: () => `You are a minimal assistant.
|
|
54
54
|
Available: read, bash. Be concise.`,
|
|
55
55
|
getAppendSystemPrompt: () => [],
|
|
56
|
-
getPathMetadata: () => new Map(),
|
|
57
56
|
extendResources: () => {},
|
|
58
57
|
reload: async () => {},
|
|
59
58
|
};
|
package/examples/sdk/README.md
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@draht/coding-agent",
|
|
3
|
-
"version": "2026.3.
|
|
3
|
+
"version": "2026.3.25-1",
|
|
4
4
|
"description": "Coding agent CLI with read, bash, edit, write tools and session management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"drahtConfig": {
|
|
@@ -48,9 +48,9 @@
|
|
|
48
48
|
"@mariozechner/jiti": "^2.6.2",
|
|
49
49
|
"@sinclair/typebox": "^0.34.41",
|
|
50
50
|
"ajv": "^8.17.1",
|
|
51
|
-
"@draht/agent-core": "2026.3.
|
|
52
|
-
"@draht/ai": "2026.3.
|
|
53
|
-
"@draht/tui": "2026.3.
|
|
51
|
+
"@draht/agent-core": "2026.3.25-1",
|
|
52
|
+
"@draht/ai": "2026.3.25-1",
|
|
53
|
+
"@draht/tui": "2026.3.25-1",
|
|
54
54
|
"@silvia-odwyer/photon-node": "^0.3.4",
|
|
55
55
|
"chalk": "^5.5.0",
|
|
56
56
|
"cli-highlight": "^2.1.11",
|
|
@@ -41,8 +41,8 @@ Execute this plan. Here is the full plan content:
|
|
|
41
41
|
<paste full plan XML here>
|
|
42
42
|
|
|
43
43
|
For each <task> in the plan, follow this TDD cycle:
|
|
44
|
-
1. RED — Write failing tests from <test>. Run the test runner, confirm they FAIL. Commit with: git add <test-files> && git commit -m "
|
|
45
|
-
2. GREEN — Write minimal implementation from <action> to make tests pass. Run tests, confirm PASS. Commit with: git add <files> && git commit -m "
|
|
44
|
+
1. RED — Write failing tests from <test>. Run the test runner, confirm they FAIL. Commit with: git add <test-files> && git commit -m "test: <description>"
|
|
45
|
+
2. GREEN — Write minimal implementation from <action> to make tests pass. Run tests, confirm PASS. Commit with: git add <files> && git commit -m "feat: <task name>"
|
|
46
46
|
3. REFACTOR — Apply <refactor> improvements if any. Tests must stay green after each change. Commit with: git add <files> && git commit -m "refactor: <description>"
|
|
47
47
|
4. VERIFY — Run the <verify> step, confirm <done> criteria are met.
|
|
48
48
|
|
package/prompts/commands/fix.md
CHANGED
|
@@ -18,12 +18,12 @@ Issue: $ARGUMENTS
|
|
|
18
18
|
"Diagnose this issue: $ARGUMENTS. Reproduce the bug by running the relevant test or command. Trace the root cause by reading the code. Identify the exact files and lines involved. Do NOT fix it yet — only report the diagnosis with: root cause, affected files, and a recommended fix approach. Do NOT run draht, draht-tools, or pi commands."
|
|
19
19
|
|
|
20
20
|
2. **Write a reproducing test**: Based on the diagnosis, write a test that demonstrates the bug (it must fail)
|
|
21
|
-
- Commit: `draht-tools commit-docs "
|
|
21
|
+
- Commit: `draht-tools commit-docs "test: reproduce bug"`
|
|
22
22
|
|
|
23
23
|
3. **Minimal fix**: Write the smallest change that makes the test pass
|
|
24
24
|
- Do not refactor or add features — just fix the bug
|
|
25
25
|
- Run the full test suite to check for regressions
|
|
26
|
-
- Commit: `draht-tools commit-docs "
|
|
26
|
+
- Commit: `draht-tools commit-docs "fix: fix description"`
|
|
27
27
|
|
|
28
28
|
4. **Refactor** (if needed): Clean up without changing behavior
|
|
29
29
|
- Tests must stay green after every change
|
|
@@ -34,7 +34,11 @@ Phase: $1
|
|
|
34
34
|
- Instruction to output the plan as XML (you will save it via `draht-tools create-plan`)
|
|
35
35
|
|
|
36
36
|
6. Collect all plan outputs from subagents
|
|
37
|
-
7. Save
|
|
37
|
+
7. Save each plan by piping the subagent's output into `draht-tools create-plan`:
|
|
38
|
+
```
|
|
39
|
+
echo 'plan content from subagent' | draht-tools create-plan $1 P [title]
|
|
40
|
+
```
|
|
41
|
+
The content must contain real task details (files, actions, tests) — NOT placeholder brackets. If `create-plan` is called without stdin, it writes a useless template.
|
|
38
42
|
8. Validate: `draht-tools validate-plans $1`
|
|
39
43
|
9. Commit: `draht-tools commit-docs "create phase $1 plans"`
|
|
40
44
|
|
|
@@ -15,7 +15,11 @@ Task: $ARGUMENTS
|
|
|
15
15
|
|
|
16
16
|
## Steps
|
|
17
17
|
1. Run `draht-tools next-quick-number` to get task number
|
|
18
|
-
2.
|
|
18
|
+
2. Analyze the task and write a concrete plan with actual task details (files, actions, verification). Pipe it into `draht-tools create-quick-plan`:
|
|
19
|
+
```
|
|
20
|
+
echo 'plan content here' | draht-tools create-quick-plan NNN "$ARGUMENTS"
|
|
21
|
+
```
|
|
22
|
+
The plan content must include: a `# Quick Task NNN: title` heading, a `## Tasks` section with one or more `<task>` XML blocks containing real file paths, real actions, and real verification steps — NOT placeholders like `[files]`.
|
|
19
23
|
3. **Delegate execution to subagent**: Use the `subagent` tool in **single mode** with the `implementer` agent:
|
|
20
24
|
"Execute this task: $ARGUMENTS
|
|
21
25
|
|