@wahack/pi-coding-agent 15.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10031 -0
- package/README.md +36 -0
- package/examples/README.md +21 -0
- package/examples/custom-tools/README.md +104 -0
- package/examples/custom-tools/hello/index.ts +20 -0
- package/examples/extensions/README.md +142 -0
- package/examples/extensions/api-demo.ts +79 -0
- package/examples/extensions/chalk-logger.ts +25 -0
- package/examples/extensions/hello.ts +31 -0
- package/examples/extensions/pirate.ts +43 -0
- package/examples/extensions/plan-mode.ts +549 -0
- package/examples/extensions/reload-runtime.ts +38 -0
- package/examples/extensions/thinking-note.ts +13 -0
- package/examples/extensions/tools.ts +145 -0
- package/examples/extensions/with-deps/index.ts +36 -0
- package/examples/extensions/with-deps/package-lock.json +31 -0
- package/examples/extensions/with-deps/package.json +17 -0
- package/examples/hooks/README.md +56 -0
- package/examples/hooks/auto-commit-on-exit.ts +48 -0
- package/examples/hooks/confirm-destructive.ts +58 -0
- package/examples/hooks/custom-compaction.ts +115 -0
- package/examples/hooks/dirty-repo-guard.ts +51 -0
- package/examples/hooks/file-trigger.ts +40 -0
- package/examples/hooks/git-checkpoint.ts +52 -0
- package/examples/hooks/handoff.ts +149 -0
- package/examples/hooks/permission-gate.ts +33 -0
- package/examples/hooks/protected-paths.ts +29 -0
- package/examples/hooks/qna.ts +118 -0
- package/examples/hooks/status-line.ts +39 -0
- package/examples/sdk/01-minimal.ts +21 -0
- package/examples/sdk/02-custom-model.ts +49 -0
- package/examples/sdk/03-custom-prompt.ts +46 -0
- package/examples/sdk/04-skills.ts +43 -0
- package/examples/sdk/06-extensions.ts +82 -0
- package/examples/sdk/06-hooks.ts +61 -0
- package/examples/sdk/07-context-files.ts +35 -0
- package/examples/sdk/08-prompt-templates.ts +41 -0
- package/examples/sdk/08-slash-commands.ts +46 -0
- package/examples/sdk/09-api-keys-and-oauth.ts +54 -0
- package/examples/sdk/11-sessions.ts +47 -0
- package/examples/sdk/12-redis-sessions.ts +54 -0
- package/examples/sdk/13-sql-sessions.ts +61 -0
- package/examples/sdk/README.md +172 -0
- package/package.json +554 -0
- package/scripts/build-binary.ts +100 -0
- package/scripts/bundle-dist.ts +90 -0
- package/scripts/format-prompts.ts +68 -0
- package/scripts/generate-docs-index.ts +40 -0
- package/scripts/generate-template.ts +33 -0
- package/scripts/omp +42 -0
- package/scripts/omp.ts +19 -0
- package/src/async/index.ts +1 -0
- package/src/async/job-manager.ts +625 -0
- package/src/auto-thinking/classifier.ts +185 -0
- package/src/autoresearch/command-resume.md +14 -0
- package/src/autoresearch/dashboard.ts +436 -0
- package/src/autoresearch/git.ts +319 -0
- package/src/autoresearch/helpers.ts +218 -0
- package/src/autoresearch/index.ts +536 -0
- package/src/autoresearch/prompt-setup.md +43 -0
- package/src/autoresearch/prompt.md +103 -0
- package/src/autoresearch/resume-message.md +10 -0
- package/src/autoresearch/state.ts +273 -0
- package/src/autoresearch/storage.ts +699 -0
- package/src/autoresearch/tools/init-experiment.ts +272 -0
- package/src/autoresearch/tools/log-experiment.ts +524 -0
- package/src/autoresearch/tools/run-experiment.ts +407 -0
- package/src/autoresearch/tools/update-notes.ts +109 -0
- package/src/autoresearch/types.ts +168 -0
- package/src/bun-imports.d.ts +28 -0
- package/src/capability/context-file.ts +44 -0
- package/src/capability/extension-module.ts +34 -0
- package/src/capability/extension.ts +47 -0
- package/src/capability/fs.ts +117 -0
- package/src/capability/hook.ts +40 -0
- package/src/capability/index.ts +436 -0
- package/src/capability/instruction.ts +37 -0
- package/src/capability/mcp.ts +74 -0
- package/src/capability/prompt.ts +35 -0
- package/src/capability/rule-buckets.ts +66 -0
- package/src/capability/rule.ts +261 -0
- package/src/capability/settings.ts +34 -0
- package/src/capability/skill.ts +63 -0
- package/src/capability/slash-command.ts +40 -0
- package/src/capability/ssh.ts +41 -0
- package/src/capability/system-prompt.ts +34 -0
- package/src/capability/tool.ts +38 -0
- package/src/capability/types.ts +168 -0
- package/src/cli/agents-cli.ts +138 -0
- package/src/cli/args.ts +340 -0
- package/src/cli/auth-broker-cli.ts +895 -0
- package/src/cli/auth-gateway-cli.ts +611 -0
- package/src/cli/classify-install-target.ts +76 -0
- package/src/cli/claude-trace-cli.ts +795 -0
- package/src/cli/commands/init-xdg.ts +27 -0
- package/src/cli/completion-gen.ts +550 -0
- package/src/cli/config-cli.ts +418 -0
- package/src/cli/dry-balance-cli.ts +856 -0
- package/src/cli/extension-flags.ts +48 -0
- package/src/cli/file-processor.ts +133 -0
- package/src/cli/gallery-cli.ts +230 -0
- package/src/cli/gallery-fixtures/agentic.ts +407 -0
- package/src/cli/gallery-fixtures/codeintel.ts +187 -0
- package/src/cli/gallery-fixtures/edit.ts +194 -0
- package/src/cli/gallery-fixtures/fs.ts +220 -0
- package/src/cli/gallery-fixtures/index.ts +40 -0
- package/src/cli/gallery-fixtures/interaction.ts +49 -0
- package/src/cli/gallery-fixtures/memory.ts +81 -0
- package/src/cli/gallery-fixtures/misc.ts +250 -0
- package/src/cli/gallery-fixtures/search.ts +213 -0
- package/src/cli/gallery-fixtures/shell.ts +167 -0
- package/src/cli/gallery-fixtures/types.ts +57 -0
- package/src/cli/gallery-fixtures/web.ts +158 -0
- package/src/cli/gallery-screenshot.ts +279 -0
- package/src/cli/grep-cli.ts +160 -0
- package/src/cli/grievances-cli.ts +256 -0
- package/src/cli/initial-message.ts +58 -0
- package/src/cli/list-models.ts +194 -0
- package/src/cli/plugin-cli.ts +996 -0
- package/src/cli/read-cli.ts +57 -0
- package/src/cli/session-picker.ts +79 -0
- package/src/cli/setup-cli.ts +231 -0
- package/src/cli/shell-cli.ts +176 -0
- package/src/cli/ssh-cli.ts +179 -0
- package/src/cli/startup-cwd.ts +68 -0
- package/src/cli/stats-cli.ts +238 -0
- package/src/cli/tiny-models-cli.ts +127 -0
- package/src/cli/update-cli.ts +611 -0
- package/src/cli/usage-cli.ts +603 -0
- package/src/cli/web-search-cli.ts +132 -0
- package/src/cli/worktree-cli.ts +291 -0
- package/src/cli-commands.ts +79 -0
- package/src/cli.ts +200 -0
- package/src/commands/acp.ts +24 -0
- package/src/commands/agents.ts +57 -0
- package/src/commands/auth-broker.ts +99 -0
- package/src/commands/auth-gateway.ts +69 -0
- package/src/commands/commit.ts +46 -0
- package/src/commands/complete.ts +66 -0
- package/src/commands/completions.ts +60 -0
- package/src/commands/config.ts +51 -0
- package/src/commands/dry-balance.ts +43 -0
- package/src/commands/gallery.ts +52 -0
- package/src/commands/grep.ts +48 -0
- package/src/commands/grievances.ts +51 -0
- package/src/commands/install.ts +107 -0
- package/src/commands/launch.ts +169 -0
- package/src/commands/plugin.ts +78 -0
- package/src/commands/read.ts +38 -0
- package/src/commands/setup.ts +67 -0
- package/src/commands/shell.ts +29 -0
- package/src/commands/ssh.ts +60 -0
- package/src/commands/stats.ts +29 -0
- package/src/commands/tiny-models.ts +36 -0
- package/src/commands/update.ts +21 -0
- package/src/commands/usage.ts +35 -0
- package/src/commands/web-search.ts +42 -0
- package/src/commands/worktree.ts +56 -0
- package/src/commit/agentic/agent.ts +317 -0
- package/src/commit/agentic/fallback.ts +96 -0
- package/src/commit/agentic/index.ts +355 -0
- package/src/commit/agentic/prompts/analyze-file.md +22 -0
- package/src/commit/agentic/prompts/session-user.md +25 -0
- package/src/commit/agentic/prompts/split-confirm.md +1 -0
- package/src/commit/agentic/prompts/system.md +38 -0
- package/src/commit/agentic/state.ts +60 -0
- package/src/commit/agentic/tools/analyze-file.ts +146 -0
- package/src/commit/agentic/tools/git-file-diff.ts +191 -0
- package/src/commit/agentic/tools/git-hunk.ts +50 -0
- package/src/commit/agentic/tools/git-overview.ts +81 -0
- package/src/commit/agentic/tools/index.ts +54 -0
- package/src/commit/agentic/tools/propose-changelog.ts +144 -0
- package/src/commit/agentic/tools/propose-commit.ts +109 -0
- package/src/commit/agentic/tools/recent-commits.ts +81 -0
- package/src/commit/agentic/tools/schemas.ts +23 -0
- package/src/commit/agentic/tools/split-commit.ts +245 -0
- package/src/commit/agentic/topo-sort.ts +44 -0
- package/src/commit/agentic/trivial.ts +51 -0
- package/src/commit/agentic/validation.ts +183 -0
- package/src/commit/analysis/conventional.ts +64 -0
- package/src/commit/analysis/index.ts +4 -0
- package/src/commit/analysis/scope.ts +242 -0
- package/src/commit/analysis/summary.ts +105 -0
- package/src/commit/analysis/validation.ts +66 -0
- package/src/commit/changelog/detect.ts +40 -0
- package/src/commit/changelog/generate.ts +97 -0
- package/src/commit/changelog/index.ts +234 -0
- package/src/commit/changelog/parse.ts +44 -0
- package/src/commit/cli.ts +85 -0
- package/src/commit/git/diff.ts +148 -0
- package/src/commit/index.ts +5 -0
- package/src/commit/map-reduce/index.ts +69 -0
- package/src/commit/map-reduce/map-phase.ts +193 -0
- package/src/commit/map-reduce/reduce-phase.ts +49 -0
- package/src/commit/map-reduce/utils.ts +9 -0
- package/src/commit/message.ts +11 -0
- package/src/commit/model-selection.ts +92 -0
- package/src/commit/pipeline.ts +243 -0
- package/src/commit/prompts/analysis-system.md +148 -0
- package/src/commit/prompts/analysis-user.md +38 -0
- package/src/commit/prompts/changelog-system.md +50 -0
- package/src/commit/prompts/changelog-user.md +18 -0
- package/src/commit/prompts/file-observer-system.md +24 -0
- package/src/commit/prompts/file-observer-user.md +8 -0
- package/src/commit/prompts/reduce-system.md +50 -0
- package/src/commit/prompts/reduce-user.md +17 -0
- package/src/commit/prompts/summary-retry.md +3 -0
- package/src/commit/prompts/summary-system.md +38 -0
- package/src/commit/prompts/summary-user.md +13 -0
- package/src/commit/prompts/types-description.md +2 -0
- package/src/commit/shared-llm.ts +77 -0
- package/src/commit/types.ts +118 -0
- package/src/commit/utils/exclusions.ts +42 -0
- package/src/commit/utils.ts +58 -0
- package/src/config/api-key-resolver.ts +60 -0
- package/src/config/append-only-context-mode.ts +31 -0
- package/src/config/config-file.ts +317 -0
- package/src/config/file-lock.ts +164 -0
- package/src/config/keybindings.ts +628 -0
- package/src/config/mcp-schema.json +230 -0
- package/src/config/model-discovery.ts +554 -0
- package/src/config/model-registry.ts +2090 -0
- package/src/config/model-resolver.ts +1502 -0
- package/src/config/model-roles.ts +74 -0
- package/src/config/models-config-schema.ts +226 -0
- package/src/config/models-config.ts +129 -0
- package/src/config/prompt-templates.ts +185 -0
- package/src/config/resolve-config-value.ts +94 -0
- package/src/config/settings-schema.ts +3530 -0
- package/src/config/settings.ts +1178 -0
- package/src/config.ts +242 -0
- package/src/cursor.ts +340 -0
- package/src/dap/client.ts +760 -0
- package/src/dap/config.ts +189 -0
- package/src/dap/defaults.json +212 -0
- package/src/dap/index.ts +4 -0
- package/src/dap/session.ts +1441 -0
- package/src/dap/types.ts +610 -0
- package/src/debug/index.ts +515 -0
- package/src/debug/log-formatting.ts +58 -0
- package/src/debug/log-viewer.ts +908 -0
- package/src/debug/profiler.ts +162 -0
- package/src/debug/protocol-probe.ts +267 -0
- package/src/debug/raw-sse-buffer.ts +273 -0
- package/src/debug/raw-sse.ts +292 -0
- package/src/debug/report-bundle.ts +374 -0
- package/src/debug/system-info.ts +111 -0
- package/src/debug/terminal-info.ts +124 -0
- package/src/discovery/agents-md.ts +67 -0
- package/src/discovery/agents.ts +230 -0
- package/src/discovery/at-imports.ts +273 -0
- package/src/discovery/builtin-defaults.ts +39 -0
- package/src/discovery/builtin-rules/index.ts +54 -0
- package/src/discovery/builtin-rules/rs-box-leak.md +48 -0
- package/src/discovery/builtin-rules/rs-future-prelude.md +23 -0
- package/src/discovery/builtin-rules/rs-lazylock.md +51 -0
- package/src/discovery/builtin-rules/rs-match-ergonomics.md +67 -0
- package/src/discovery/builtin-rules/rs-parking-lot.md +44 -0
- package/src/discovery/builtin-rules/rs-result-type.md +19 -0
- package/src/discovery/builtin-rules/ts-bare-catch.md +38 -0
- package/src/discovery/builtin-rules/ts-import-type.md +42 -0
- package/src/discovery/builtin-rules/ts-no-any.md +56 -0
- package/src/discovery/builtin-rules/ts-no-deprecated-leftovers.md +44 -0
- package/src/discovery/builtin-rules/ts-no-dynamic-import.md +39 -0
- package/src/discovery/builtin-rules/ts-no-return-type.md +45 -0
- package/src/discovery/builtin-rules/ts-no-test-timers.md +55 -0
- package/src/discovery/builtin-rules/ts-no-tiny-functions.md +51 -0
- package/src/discovery/builtin-rules/ts-promise-with-resolvers.md +65 -0
- package/src/discovery/builtin-rules/ts-redundant-clear-guard.md +75 -0
- package/src/discovery/builtin-rules/ts-set-map.md +28 -0
- package/src/discovery/builtin.ts +906 -0
- package/src/discovery/claude-plugins.ts +386 -0
- package/src/discovery/claude.ts +584 -0
- package/src/discovery/cline.ts +83 -0
- package/src/discovery/codex.ts +522 -0
- package/src/discovery/cursor.ts +220 -0
- package/src/discovery/gemini.ts +383 -0
- package/src/discovery/github.ts +154 -0
- package/src/discovery/helpers.ts +1016 -0
- package/src/discovery/index.ts +81 -0
- package/src/discovery/mcp-json.ts +171 -0
- package/src/discovery/omp-extension-roots.ts +190 -0
- package/src/discovery/omp-plugins.ts +383 -0
- package/src/discovery/opencode.ts +398 -0
- package/src/discovery/plugin-dir-roots.ts +28 -0
- package/src/discovery/ssh.ts +153 -0
- package/src/discovery/substitute-plugin-root.ts +29 -0
- package/src/discovery/vscode.ts +105 -0
- package/src/discovery/windsurf.ts +147 -0
- package/src/edit/apply-patch/index.ts +87 -0
- package/src/edit/apply-patch/parser.ts +174 -0
- package/src/edit/diff.ts +999 -0
- package/src/edit/file-snapshot-store.ts +91 -0
- package/src/edit/hashline/block-resolver.ts +33 -0
- package/src/edit/hashline/diff.ts +290 -0
- package/src/edit/hashline/execute.ts +242 -0
- package/src/edit/hashline/filesystem.ts +130 -0
- package/src/edit/hashline/index.ts +5 -0
- package/src/edit/hashline/noop-loop-guard.ts +99 -0
- package/src/edit/hashline/params.ts +18 -0
- package/src/edit/index.ts +571 -0
- package/src/edit/modes/apply-patch.lark +19 -0
- package/src/edit/modes/apply-patch.ts +53 -0
- package/src/edit/modes/patch.ts +1891 -0
- package/src/edit/modes/replace.ts +1137 -0
- package/src/edit/normalize.ts +345 -0
- package/src/edit/notebook.ts +242 -0
- package/src/edit/read-file.ts +25 -0
- package/src/edit/renderer.ts +769 -0
- package/src/edit/streaming.ts +517 -0
- package/src/eval/__tests__/agent-bridge.test.ts +708 -0
- package/src/eval/__tests__/bridge-timeout.test.ts +64 -0
- package/src/eval/__tests__/budget-bridge.test.ts +69 -0
- package/src/eval/__tests__/completion-bridge.test.ts +412 -0
- package/src/eval/__tests__/helpers-local-roots.test.ts +58 -0
- package/src/eval/__tests__/idle-timeout.test.ts +80 -0
- package/src/eval/__tests__/js-context-manager.test.ts +241 -0
- package/src/eval/__tests__/kernel-spawn.test.ts +103 -0
- package/src/eval/agent-bridge.ts +319 -0
- package/src/eval/backend.ts +71 -0
- package/src/eval/bridge-timeout.ts +44 -0
- package/src/eval/budget-bridge.ts +48 -0
- package/src/eval/completion-bridge.ts +207 -0
- package/src/eval/concurrency-bridge.ts +34 -0
- package/src/eval/idle-timeout.ts +91 -0
- package/src/eval/index.ts +4 -0
- package/src/eval/js/context-manager.ts +502 -0
- package/src/eval/js/executor.ts +173 -0
- package/src/eval/js/index.ts +51 -0
- package/src/eval/js/shared/helpers.ts +283 -0
- package/src/eval/js/shared/indirect-eval.ts +30 -0
- package/src/eval/js/shared/local-module-loader.ts +342 -0
- package/src/eval/js/shared/prelude.ts +2 -0
- package/src/eval/js/shared/prelude.txt +246 -0
- package/src/eval/js/shared/rewrite-imports.ts +532 -0
- package/src/eval/js/shared/runtime.ts +352 -0
- package/src/eval/js/shared/types.ts +18 -0
- package/src/eval/js/tool-bridge.ts +162 -0
- package/src/eval/js/worker-core.ts +132 -0
- package/src/eval/js/worker-entry.ts +30 -0
- package/src/eval/js/worker-protocol.ts +47 -0
- package/src/eval/py/__tests__/prelude.test.ts +19 -0
- package/src/eval/py/display.ts +71 -0
- package/src/eval/py/executor.ts +742 -0
- package/src/eval/py/index.ts +68 -0
- package/src/eval/py/kernel.ts +748 -0
- package/src/eval/py/prelude.py +658 -0
- package/src/eval/py/prelude.ts +3 -0
- package/src/eval/py/runner.py +1133 -0
- package/src/eval/py/runtime.ts +276 -0
- package/src/eval/py/spawn-options.ts +126 -0
- package/src/eval/py/tool-bridge.ts +182 -0
- package/src/eval/session-id.ts +8 -0
- package/src/eval/types.ts +48 -0
- package/src/exa/index.ts +2 -0
- package/src/exa/mcp-client.ts +370 -0
- package/src/exa/types.ts +69 -0
- package/src/exec/bash-executor.ts +419 -0
- package/src/exec/exec.ts +53 -0
- package/src/exec/non-interactive-env.ts +48 -0
- package/src/export/custom-share.ts +65 -0
- package/src/export/html/index.ts +164 -0
- package/src/export/html/template.css +1051 -0
- package/src/export/html/template.generated.ts +2 -0
- package/src/export/html/template.html +46 -0
- package/src/export/html/template.js +2271 -0
- package/src/export/html/template.macro.ts +25 -0
- package/src/export/html/vendor/highlight.min.js +1213 -0
- package/src/export/html/vendor/marked.min.js +6 -0
- package/src/export/ttsr.ts +583 -0
- package/src/extensibility/custom-commands/bundled/ci-green/index.ts +54 -0
- package/src/extensibility/custom-commands/bundled/review/index.ts +489 -0
- package/src/extensibility/custom-commands/index.ts +2 -0
- package/src/extensibility/custom-commands/loader.ts +238 -0
- package/src/extensibility/custom-commands/types.ts +113 -0
- package/src/extensibility/custom-tools/index.ts +7 -0
- package/src/extensibility/custom-tools/loader.ts +269 -0
- package/src/extensibility/custom-tools/types.ts +270 -0
- package/src/extensibility/custom-tools/wrapper.ts +47 -0
- package/src/extensibility/extensions/compact-handler.ts +40 -0
- package/src/extensibility/extensions/get-commands-handler.ts +78 -0
- package/src/extensibility/extensions/index.ts +16 -0
- package/src/extensibility/extensions/loader.ts +572 -0
- package/src/extensibility/extensions/runner.ts +922 -0
- package/src/extensibility/extensions/types.ts +1322 -0
- package/src/extensibility/extensions/wrapper.ts +223 -0
- package/src/extensibility/hooks/index.ts +5 -0
- package/src/extensibility/hooks/loader.ts +257 -0
- package/src/extensibility/hooks/runner.ts +425 -0
- package/src/extensibility/hooks/tool-wrapper.ts +107 -0
- package/src/extensibility/hooks/types.ts +606 -0
- package/src/extensibility/legacy-pi-ai-shim.ts +24 -0
- package/src/extensibility/legacy-pi-coding-agent-shim.ts +15 -0
- package/src/extensibility/plugins/doctor.ts +65 -0
- package/src/extensibility/plugins/git-url.ts +367 -0
- package/src/extensibility/plugins/index.ts +9 -0
- package/src/extensibility/plugins/installer.ts +192 -0
- package/src/extensibility/plugins/legacy-pi-compat.ts +682 -0
- package/src/extensibility/plugins/loader.ts +313 -0
- package/src/extensibility/plugins/manager.ts +827 -0
- package/src/extensibility/plugins/marketplace/cache.ts +136 -0
- package/src/extensibility/plugins/marketplace/fetcher.ts +317 -0
- package/src/extensibility/plugins/marketplace/index.ts +6 -0
- package/src/extensibility/plugins/marketplace/manager.ts +770 -0
- package/src/extensibility/plugins/marketplace/registry.ts +196 -0
- package/src/extensibility/plugins/marketplace/source-resolver.ts +147 -0
- package/src/extensibility/plugins/marketplace/types.ts +191 -0
- package/src/extensibility/plugins/marketplace-auto-update.ts +49 -0
- package/src/extensibility/plugins/parser.ts +105 -0
- package/src/extensibility/plugins/types.ts +194 -0
- package/src/extensibility/shared-events.ts +343 -0
- package/src/extensibility/skills.ts +312 -0
- package/src/extensibility/slash-commands.ts +227 -0
- package/src/extensibility/tool-proxy.ts +25 -0
- package/src/extensibility/typebox.ts +418 -0
- package/src/extensibility/utils.ts +44 -0
- package/src/goals/index.ts +3 -0
- package/src/goals/runtime.ts +528 -0
- package/src/goals/state.ts +37 -0
- package/src/goals/tools/goal-tool.ts +251 -0
- package/src/hindsight/backend.ts +354 -0
- package/src/hindsight/bank.ts +156 -0
- package/src/hindsight/client.ts +598 -0
- package/src/hindsight/config.ts +175 -0
- package/src/hindsight/content.ts +210 -0
- package/src/hindsight/index.ts +8 -0
- package/src/hindsight/mental-models.ts +429 -0
- package/src/hindsight/seeds.json +32 -0
- package/src/hindsight/state.ts +488 -0
- package/src/hindsight/transcript.ts +71 -0
- package/src/index.ts +59 -0
- package/src/internal-urls/agent-protocol.ts +146 -0
- package/src/internal-urls/artifact-protocol.ts +107 -0
- package/src/internal-urls/docs-index.generated.ts +106 -0
- package/src/internal-urls/history-protocol.ts +113 -0
- package/src/internal-urls/index.ts +25 -0
- package/src/internal-urls/issue-pr-protocol.ts +584 -0
- package/src/internal-urls/json-query.ts +126 -0
- package/src/internal-urls/local-protocol.ts +287 -0
- package/src/internal-urls/mcp-protocol.ts +151 -0
- package/src/internal-urls/memory-protocol.ts +169 -0
- package/src/internal-urls/omp-protocol.ts +93 -0
- package/src/internal-urls/parse.ts +72 -0
- package/src/internal-urls/registry-helpers.ts +25 -0
- package/src/internal-urls/router.ts +105 -0
- package/src/internal-urls/rule-protocol.ts +45 -0
- package/src/internal-urls/skill-protocol.ts +96 -0
- package/src/internal-urls/types.ts +152 -0
- package/src/internal-urls/vault-protocol.ts +936 -0
- package/src/irc/bus.ts +292 -0
- package/src/lib/xai-http.ts +124 -0
- package/src/lsp/client.ts +1193 -0
- package/src/lsp/clients/biome-client.ts +264 -0
- package/src/lsp/clients/index.ts +50 -0
- package/src/lsp/clients/lsp-linter-client.ts +93 -0
- package/src/lsp/clients/swiftlint-client.ts +120 -0
- package/src/lsp/config.ts +502 -0
- package/src/lsp/defaults.json +493 -0
- package/src/lsp/diagnostics-ledger.ts +51 -0
- package/src/lsp/edits.ts +267 -0
- package/src/lsp/index.ts +2477 -0
- package/src/lsp/lspmux.ts +233 -0
- package/src/lsp/render.ts +694 -0
- package/src/lsp/startup-events.ts +13 -0
- package/src/lsp/types.ts +455 -0
- package/src/lsp/utils.ts +718 -0
- package/src/main.ts +1325 -0
- package/src/mcp/client.ts +484 -0
- package/src/mcp/config-writer.ts +225 -0
- package/src/mcp/config.ts +365 -0
- package/src/mcp/index.ts +29 -0
- package/src/mcp/json-rpc.ts +122 -0
- package/src/mcp/loader.ts +124 -0
- package/src/mcp/manager.ts +1275 -0
- package/src/mcp/oauth-discovery.ts +442 -0
- package/src/mcp/oauth-flow.ts +442 -0
- package/src/mcp/render.ts +132 -0
- package/src/mcp/smithery-auth.ts +104 -0
- package/src/mcp/smithery-connect.ts +145 -0
- package/src/mcp/smithery-registry.ts +477 -0
- package/src/mcp/timeout.ts +59 -0
- package/src/mcp/tool-bridge.ts +426 -0
- package/src/mcp/tool-cache.ts +117 -0
- package/src/mcp/transports/http.ts +519 -0
- package/src/mcp/transports/index.ts +6 -0
- package/src/mcp/transports/stdio.ts +528 -0
- package/src/mcp/types.ts +423 -0
- package/src/memories/index.ts +1150 -0
- package/src/memories/storage.ts +577 -0
- package/src/memory-backend/index.ts +18 -0
- package/src/memory-backend/local-backend.ts +39 -0
- package/src/memory-backend/off-backend.ts +25 -0
- package/src/memory-backend/resolve.ts +25 -0
- package/src/memory-backend/runtime.ts +66 -0
- package/src/memory-backend/types.ts +166 -0
- package/src/mnemopi/backend.ts +547 -0
- package/src/mnemopi/config.ts +160 -0
- package/src/mnemopi/index.ts +3 -0
- package/src/mnemopi/state.ts +584 -0
- package/src/modes/acp/acp-agent.ts +2407 -0
- package/src/modes/acp/acp-client-bridge.ts +154 -0
- package/src/modes/acp/acp-event-mapper.ts +929 -0
- package/src/modes/acp/acp-mode.ts +23 -0
- package/src/modes/acp/index.ts +2 -0
- package/src/modes/acp/terminal-auth.ts +37 -0
- package/src/modes/components/agent-dashboard.ts +1206 -0
- package/src/modes/components/agent-hub.ts +1071 -0
- package/src/modes/components/assistant-message.ts +307 -0
- package/src/modes/components/bash-execution.ts +220 -0
- package/src/modes/components/bordered-loader.ts +41 -0
- package/src/modes/components/branch-summary-message.ts +45 -0
- package/src/modes/components/btw-panel.ts +104 -0
- package/src/modes/components/chat-block.ts +111 -0
- package/src/modes/components/compaction-summary-message.ts +87 -0
- package/src/modes/components/copy-selector.ts +206 -0
- package/src/modes/components/countdown-timer.ts +75 -0
- package/src/modes/components/custom-editor.ts +398 -0
- package/src/modes/components/custom-message.ts +63 -0
- package/src/modes/components/diff.ts +277 -0
- package/src/modes/components/dynamic-border.ts +34 -0
- package/src/modes/components/error-banner.ts +33 -0
- package/src/modes/components/eval-execution.ts +158 -0
- package/src/modes/components/execution-shared.ts +101 -0
- package/src/modes/components/extensions/extension-dashboard.ts +399 -0
- package/src/modes/components/extensions/extension-list.ts +502 -0
- package/src/modes/components/extensions/index.ts +9 -0
- package/src/modes/components/extensions/inspector-panel.ts +317 -0
- package/src/modes/components/extensions/state-manager.ts +627 -0
- package/src/modes/components/extensions/types.ts +186 -0
- package/src/modes/components/footer.ts +274 -0
- package/src/modes/components/history-search.ts +280 -0
- package/src/modes/components/hook-editor.ts +167 -0
- package/src/modes/components/hook-input.ts +87 -0
- package/src/modes/components/hook-message.ts +66 -0
- package/src/modes/components/hook-selector.ts +660 -0
- package/src/modes/components/index.ts +38 -0
- package/src/modes/components/keybinding-hints.ts +65 -0
- package/src/modes/components/late-diagnostics-message.ts +60 -0
- package/src/modes/components/login-dialog.ts +164 -0
- package/src/modes/components/mcp-add-wizard.ts +1340 -0
- package/src/modes/components/message-frame.ts +88 -0
- package/src/modes/components/model-selector.ts +1271 -0
- package/src/modes/components/oauth-selector.ts +368 -0
- package/src/modes/components/omfg-panel.ts +141 -0
- package/src/modes/components/overlay-box.ts +108 -0
- package/src/modes/components/plan-review-overlay.ts +820 -0
- package/src/modes/components/plan-toc.ts +138 -0
- package/src/modes/components/plugin-selector.ts +95 -0
- package/src/modes/components/plugin-settings.ts +722 -0
- package/src/modes/components/queue-mode-selector.ts +56 -0
- package/src/modes/components/read-tool-group.ts +670 -0
- package/src/modes/components/segment-track.ts +52 -0
- package/src/modes/components/session-selector.ts +625 -0
- package/src/modes/components/settings-defs.ts +189 -0
- package/src/modes/components/settings-selector.ts +651 -0
- package/src/modes/components/show-images-selector.ts +45 -0
- package/src/modes/components/skill-message.ts +89 -0
- package/src/modes/components/status-line/component.ts +869 -0
- package/src/modes/components/status-line/context-thresholds.ts +79 -0
- package/src/modes/components/status-line/git-utils.ts +42 -0
- package/src/modes/components/status-line/index.ts +5 -0
- package/src/modes/components/status-line/presets.ts +106 -0
- package/src/modes/components/status-line/segments.ts +584 -0
- package/src/modes/components/status-line/separators.ts +55 -0
- package/src/modes/components/status-line/token-rate.ts +66 -0
- package/src/modes/components/status-line/types.ts +108 -0
- package/src/modes/components/theme-selector.ts +63 -0
- package/src/modes/components/thinking-selector.ts +52 -0
- package/src/modes/components/tiny-title-download-progress.ts +90 -0
- package/src/modes/components/tips.txt +19 -0
- package/src/modes/components/todo-reminder.ts +38 -0
- package/src/modes/components/tool-execution.ts +1024 -0
- package/src/modes/components/transcript-container.ts +608 -0
- package/src/modes/components/tree-selector.ts +978 -0
- package/src/modes/components/ttsr-notification.ts +122 -0
- package/src/modes/components/user-message-selector.ts +227 -0
- package/src/modes/components/user-message.ts +66 -0
- package/src/modes/components/visual-truncate.ts +63 -0
- package/src/modes/components/welcome.ts +493 -0
- package/src/modes/controllers/btw-controller.ts +105 -0
- package/src/modes/controllers/command-controller-shared.ts +109 -0
- package/src/modes/controllers/command-controller.ts +1566 -0
- package/src/modes/controllers/event-controller.ts +1054 -0
- package/src/modes/controllers/extension-ui-controller.ts +886 -0
- package/src/modes/controllers/input-controller.ts +1073 -0
- package/src/modes/controllers/mcp-command-controller.ts +2017 -0
- package/src/modes/controllers/omfg-controller.ts +283 -0
- package/src/modes/controllers/omfg-rule.ts +647 -0
- package/src/modes/controllers/selector-controller.ts +1108 -0
- package/src/modes/controllers/ssh-command-controller.ts +384 -0
- package/src/modes/controllers/streaming-reveal.ts +279 -0
- package/src/modes/controllers/tan-command-controller.ts +173 -0
- package/src/modes/controllers/todo-command-controller.ts +485 -0
- package/src/modes/data/emojis.json +1 -0
- package/src/modes/emoji-autocomplete.ts +285 -0
- package/src/modes/gradient-highlight.ts +87 -0
- package/src/modes/image-references.ts +117 -0
- package/src/modes/index.ts +17 -0
- package/src/modes/interactive-mode.ts +3370 -0
- package/src/modes/internal-url-autocomplete.ts +143 -0
- package/src/modes/loop-limit.ts +140 -0
- package/src/modes/magic-keywords.ts +20 -0
- package/src/modes/markdown-prose.ts +247 -0
- package/src/modes/oauth-manual-input.ts +69 -0
- package/src/modes/orchestrate.ts +42 -0
- package/src/modes/print-mode.ts +126 -0
- package/src/modes/prompt-action-autocomplete.ts +260 -0
- package/src/modes/rpc/host-tools.ts +186 -0
- package/src/modes/rpc/host-uris.ts +235 -0
- package/src/modes/rpc/rpc-client.ts +963 -0
- package/src/modes/rpc/rpc-mode.ts +947 -0
- package/src/modes/rpc/rpc-subagents.ts +265 -0
- package/src/modes/rpc/rpc-types.ts +458 -0
- package/src/modes/runtime-init.ts +116 -0
- package/src/modes/session-observer-registry.ts +146 -0
- package/src/modes/setup-version.ts +11 -0
- package/src/modes/setup-wizard/index.ts +99 -0
- package/src/modes/setup-wizard/lazy.ts +16 -0
- package/src/modes/setup-wizard/scenes/glyph.ts +96 -0
- package/src/modes/setup-wizard/scenes/outro.ts +35 -0
- package/src/modes/setup-wizard/scenes/providers.ts +69 -0
- package/src/modes/setup-wizard/scenes/sign-in.ts +205 -0
- package/src/modes/setup-wizard/scenes/splash.ts +201 -0
- package/src/modes/setup-wizard/scenes/theme.ts +299 -0
- package/src/modes/setup-wizard/scenes/types.ts +48 -0
- package/src/modes/setup-wizard/scenes/web-search.ts +129 -0
- package/src/modes/setup-wizard/wizard-overlay.ts +275 -0
- package/src/modes/shared.ts +47 -0
- package/src/modes/theme/dark.json +95 -0
- package/src/modes/theme/defaults/alabaster.json +93 -0
- package/src/modes/theme/defaults/amethyst.json +96 -0
- package/src/modes/theme/defaults/anthracite.json +93 -0
- package/src/modes/theme/defaults/basalt.json +91 -0
- package/src/modes/theme/defaults/birch.json +95 -0
- package/src/modes/theme/defaults/dark-abyss.json +91 -0
- package/src/modes/theme/defaults/dark-arctic.json +104 -0
- package/src/modes/theme/defaults/dark-aurora.json +95 -0
- package/src/modes/theme/defaults/dark-catppuccin.json +107 -0
- package/src/modes/theme/defaults/dark-cavern.json +91 -0
- package/src/modes/theme/defaults/dark-copper.json +95 -0
- package/src/modes/theme/defaults/dark-cosmos.json +90 -0
- package/src/modes/theme/defaults/dark-cyberpunk.json +102 -0
- package/src/modes/theme/defaults/dark-dracula.json +98 -0
- package/src/modes/theme/defaults/dark-eclipse.json +91 -0
- package/src/modes/theme/defaults/dark-ember.json +95 -0
- package/src/modes/theme/defaults/dark-equinox.json +90 -0
- package/src/modes/theme/defaults/dark-forest.json +96 -0
- package/src/modes/theme/defaults/dark-github.json +105 -0
- package/src/modes/theme/defaults/dark-gruvbox.json +112 -0
- package/src/modes/theme/defaults/dark-lavender.json +95 -0
- package/src/modes/theme/defaults/dark-lunar.json +89 -0
- package/src/modes/theme/defaults/dark-midnight.json +95 -0
- package/src/modes/theme/defaults/dark-monochrome.json +94 -0
- package/src/modes/theme/defaults/dark-monokai.json +98 -0
- package/src/modes/theme/defaults/dark-nebula.json +90 -0
- package/src/modes/theme/defaults/dark-nord.json +97 -0
- package/src/modes/theme/defaults/dark-ocean.json +101 -0
- package/src/modes/theme/defaults/dark-one.json +100 -0
- package/src/modes/theme/defaults/dark-poimandres.json +142 -0
- package/src/modes/theme/defaults/dark-rainforest.json +91 -0
- package/src/modes/theme/defaults/dark-reef.json +91 -0
- package/src/modes/theme/defaults/dark-retro.json +92 -0
- package/src/modes/theme/defaults/dark-rose-pine.json +96 -0
- package/src/modes/theme/defaults/dark-sakura.json +95 -0
- package/src/modes/theme/defaults/dark-slate.json +95 -0
- package/src/modes/theme/defaults/dark-solarized.json +97 -0
- package/src/modes/theme/defaults/dark-solstice.json +90 -0
- package/src/modes/theme/defaults/dark-starfall.json +91 -0
- package/src/modes/theme/defaults/dark-sunset.json +99 -0
- package/src/modes/theme/defaults/dark-swamp.json +90 -0
- package/src/modes/theme/defaults/dark-synthwave.json +103 -0
- package/src/modes/theme/defaults/dark-taiga.json +91 -0
- package/src/modes/theme/defaults/dark-terminal.json +95 -0
- package/src/modes/theme/defaults/dark-tokyo-night.json +101 -0
- package/src/modes/theme/defaults/dark-tundra.json +91 -0
- package/src/modes/theme/defaults/dark-twilight.json +91 -0
- package/src/modes/theme/defaults/dark-volcanic.json +91 -0
- package/src/modes/theme/defaults/graphite.json +92 -0
- package/src/modes/theme/defaults/index.ts +199 -0
- package/src/modes/theme/defaults/light-arctic.json +107 -0
- package/src/modes/theme/defaults/light-aurora-day.json +91 -0
- package/src/modes/theme/defaults/light-canyon.json +91 -0
- package/src/modes/theme/defaults/light-catppuccin.json +106 -0
- package/src/modes/theme/defaults/light-cirrus.json +90 -0
- package/src/modes/theme/defaults/light-coral.json +95 -0
- package/src/modes/theme/defaults/light-cyberpunk.json +96 -0
- package/src/modes/theme/defaults/light-dawn.json +90 -0
- package/src/modes/theme/defaults/light-dunes.json +91 -0
- package/src/modes/theme/defaults/light-eucalyptus.json +95 -0
- package/src/modes/theme/defaults/light-forest.json +100 -0
- package/src/modes/theme/defaults/light-frost.json +95 -0
- package/src/modes/theme/defaults/light-github.json +115 -0
- package/src/modes/theme/defaults/light-glacier.json +91 -0
- package/src/modes/theme/defaults/light-gruvbox.json +108 -0
- package/src/modes/theme/defaults/light-haze.json +90 -0
- package/src/modes/theme/defaults/light-honeycomb.json +95 -0
- package/src/modes/theme/defaults/light-lagoon.json +91 -0
- package/src/modes/theme/defaults/light-lavender.json +95 -0
- package/src/modes/theme/defaults/light-meadow.json +91 -0
- package/src/modes/theme/defaults/light-mint.json +95 -0
- package/src/modes/theme/defaults/light-monochrome.json +101 -0
- package/src/modes/theme/defaults/light-ocean.json +99 -0
- package/src/modes/theme/defaults/light-one.json +99 -0
- package/src/modes/theme/defaults/light-opal.json +91 -0
- package/src/modes/theme/defaults/light-orchard.json +91 -0
- package/src/modes/theme/defaults/light-paper.json +95 -0
- package/src/modes/theme/defaults/light-poimandres.json +142 -0
- package/src/modes/theme/defaults/light-prism.json +90 -0
- package/src/modes/theme/defaults/light-retro.json +98 -0
- package/src/modes/theme/defaults/light-sand.json +95 -0
- package/src/modes/theme/defaults/light-savanna.json +91 -0
- package/src/modes/theme/defaults/light-solarized.json +102 -0
- package/src/modes/theme/defaults/light-soleil.json +90 -0
- package/src/modes/theme/defaults/light-sunset.json +99 -0
- package/src/modes/theme/defaults/light-synthwave.json +98 -0
- package/src/modes/theme/defaults/light-tokyo-night.json +111 -0
- package/src/modes/theme/defaults/light-wetland.json +91 -0
- package/src/modes/theme/defaults/light-zenith.json +89 -0
- package/src/modes/theme/defaults/limestone.json +94 -0
- package/src/modes/theme/defaults/mahogany.json +97 -0
- package/src/modes/theme/defaults/marble.json +93 -0
- package/src/modes/theme/defaults/obsidian.json +91 -0
- package/src/modes/theme/defaults/onyx.json +91 -0
- package/src/modes/theme/defaults/pearl.json +93 -0
- package/src/modes/theme/defaults/porcelain.json +91 -0
- package/src/modes/theme/defaults/quartz.json +96 -0
- package/src/modes/theme/defaults/sandstone.json +95 -0
- package/src/modes/theme/defaults/titanium.json +90 -0
- package/src/modes/theme/light.json +93 -0
- package/src/modes/theme/mermaid-cache.ts +29 -0
- package/src/modes/theme/shimmer.ts +235 -0
- package/src/modes/theme/theme-schema.json +459 -0
- package/src/modes/theme/theme.ts +2676 -0
- package/src/modes/turn-budget.ts +31 -0
- package/src/modes/types.ts +359 -0
- package/src/modes/ultrathink.ts +41 -0
- package/src/modes/utils/context-usage.ts +339 -0
- package/src/modes/utils/copy-targets.ts +360 -0
- package/src/modes/utils/hotkeys-markdown.ts +61 -0
- package/src/modes/utils/keybinding-matchers.ts +51 -0
- package/src/modes/utils/tools-markdown.ts +27 -0
- package/src/modes/utils/ui-helpers.ts +801 -0
- package/src/modes/workflow.ts +42 -0
- package/src/plan-mode/approved-plan.ts +186 -0
- package/src/plan-mode/plan-handoff.ts +37 -0
- package/src/plan-mode/plan-protection.ts +31 -0
- package/src/plan-mode/state.ts +6 -0
- package/src/priority.json +41 -0
- package/src/prompts/agents/designer.md +66 -0
- package/src/prompts/agents/explore.md +58 -0
- package/src/prompts/agents/frontmatter.md +11 -0
- package/src/prompts/agents/init.md +33 -0
- package/src/prompts/agents/librarian.md +119 -0
- package/src/prompts/agents/oracle.md +55 -0
- package/src/prompts/agents/plan.md +48 -0
- package/src/prompts/agents/reviewer.md +140 -0
- package/src/prompts/agents/task.md +16 -0
- package/src/prompts/ci-green-request.md +36 -0
- package/src/prompts/dry-balance-bench.md +8 -0
- package/src/prompts/goals/goal-budget-limit.md +16 -0
- package/src/prompts/goals/goal-continuation.md +28 -0
- package/src/prompts/goals/goal-mode-active.md +23 -0
- package/src/prompts/memories/consolidation.md +30 -0
- package/src/prompts/memories/read-path.md +11 -0
- package/src/prompts/memories/stage_one_input.md +6 -0
- package/src/prompts/memories/stage_one_system.md +21 -0
- package/src/prompts/review-custom-request.md +22 -0
- package/src/prompts/review-headless-request.md +16 -0
- package/src/prompts/review-request.md +69 -0
- package/src/prompts/steering/user-interjection.md +10 -0
- package/src/prompts/system/agent-creation-architect.md +50 -0
- package/src/prompts/system/agent-creation-user.md +6 -0
- package/src/prompts/system/auto-continue.md +1 -0
- package/src/prompts/system/auto-thinking-difficulty-local.md +14 -0
- package/src/prompts/system/auto-thinking-difficulty.md +12 -0
- package/src/prompts/system/background-tan-dispatch.md +8 -0
- package/src/prompts/system/btw-user.md +8 -0
- package/src/prompts/system/commit-message-system.md +14 -0
- package/src/prompts/system/custom-system-prompt.md +64 -0
- package/src/prompts/system/eager-todo.md +13 -0
- package/src/prompts/system/empty-stop-retry.md +6 -0
- package/src/prompts/system/irc-incoming.md +7 -0
- package/src/prompts/system/manual-continue.md +7 -0
- package/src/prompts/system/memory-consolidation-system.md +8 -0
- package/src/prompts/system/memory-extraction-system.md +26 -0
- package/src/prompts/system/omfg-user.md +50 -0
- package/src/prompts/system/orchestrate-notice.md +40 -0
- package/src/prompts/system/plan-mode-active.md +109 -0
- package/src/prompts/system/plan-mode-approved.md +25 -0
- package/src/prompts/system/plan-mode-compact-instructions.md +16 -0
- package/src/prompts/system/plan-mode-reference.md +11 -0
- package/src/prompts/system/plan-mode-subagent.md +33 -0
- package/src/prompts/system/plan-mode-tool-decision-reminder.md +9 -0
- package/src/prompts/system/project-prompt.md +52 -0
- package/src/prompts/system/subagent-system-prompt.md +64 -0
- package/src/prompts/system/subagent-user-prompt.md +3 -0
- package/src/prompts/system/subagent-yield-reminder.md +12 -0
- package/src/prompts/system/system-prompt.md +258 -0
- package/src/prompts/system/tiny-title-system.md +8 -0
- package/src/prompts/system/title-system.md +16 -0
- package/src/prompts/system/ttsr-interrupt.md +7 -0
- package/src/prompts/system/ttsr-tool-reminder.md +5 -0
- package/src/prompts/system/ultrathink-notice.md +3 -0
- package/src/prompts/system/web-search.md +25 -0
- package/src/prompts/system/workflow-notice.md +70 -0
- package/src/prompts/tools/apply-patch.md +65 -0
- package/src/prompts/tools/ask.md +30 -0
- package/src/prompts/tools/ast-edit.md +39 -0
- package/src/prompts/tools/ast-grep.md +42 -0
- package/src/prompts/tools/async-result.md +8 -0
- package/src/prompts/tools/bash.md +46 -0
- package/src/prompts/tools/browser.md +73 -0
- package/src/prompts/tools/checkpoint.md +16 -0
- package/src/prompts/tools/debug.md +34 -0
- package/src/prompts/tools/eval.md +92 -0
- package/src/prompts/tools/find.md +36 -0
- package/src/prompts/tools/github.md +21 -0
- package/src/prompts/tools/goal.md +18 -0
- package/src/prompts/tools/image-gen.md +7 -0
- package/src/prompts/tools/inspect-image-system.md +20 -0
- package/src/prompts/tools/inspect-image.md +32 -0
- package/src/prompts/tools/irc.md +59 -0
- package/src/prompts/tools/job.md +19 -0
- package/src/prompts/tools/lsp-late-diagnostic.md +8 -0
- package/src/prompts/tools/lsp.md +42 -0
- package/src/prompts/tools/memory-edit.md +8 -0
- package/src/prompts/tools/patch.md +70 -0
- package/src/prompts/tools/read.md +84 -0
- package/src/prompts/tools/recall.md +5 -0
- package/src/prompts/tools/reflect.md +5 -0
- package/src/prompts/tools/render-mermaid.md +9 -0
- package/src/prompts/tools/replace.md +30 -0
- package/src/prompts/tools/resolve.md +9 -0
- package/src/prompts/tools/retain.md +6 -0
- package/src/prompts/tools/rewind.md +13 -0
- package/src/prompts/tools/search-tool-bm25.md +32 -0
- package/src/prompts/tools/search.md +24 -0
- package/src/prompts/tools/ssh.md +31 -0
- package/src/prompts/tools/task-summary.md +17 -0
- package/src/prompts/tools/task.md +88 -0
- package/src/prompts/tools/todo.md +62 -0
- package/src/prompts/tools/web-search.md +10 -0
- package/src/prompts/tools/write.md +14 -0
- package/src/registry/agent-lifecycle.ts +218 -0
- package/src/registry/agent-registry.ts +151 -0
- package/src/sdk.ts +2558 -0
- package/src/secrets/index.ts +123 -0
- package/src/secrets/obfuscator.ts +298 -0
- package/src/secrets/regex.ts +21 -0
- package/src/session/agent-session.ts +10121 -0
- package/src/session/agent-storage.ts +455 -0
- package/src/session/artifacts.ts +135 -0
- package/src/session/auth-broker-config.ts +131 -0
- package/src/session/auth-storage.ts +29 -0
- package/src/session/blob-store.ts +255 -0
- package/src/session/client-bridge.ts +85 -0
- package/src/session/history-storage.ts +348 -0
- package/src/session/indexed-session-storage.ts +430 -0
- package/src/session/messages.ts +541 -0
- package/src/session/redis-session-storage.ts +170 -0
- package/src/session/session-dump-format.ts +209 -0
- package/src/session/session-history-format.ts +246 -0
- package/src/session/session-manager.ts +3676 -0
- package/src/session/session-storage.ts +529 -0
- package/src/session/shake-types.ts +43 -0
- package/src/session/sql-session-storage.ts +314 -0
- package/src/session/streaming-output.ts +1330 -0
- package/src/session/tool-choice-queue.ts +213 -0
- package/src/session/yield-queue.ts +173 -0
- package/src/slash-commands/acp-builtins.ts +70 -0
- package/src/slash-commands/builtin-registry.ts +1798 -0
- package/src/slash-commands/helpers/context-report.ts +39 -0
- package/src/slash-commands/helpers/format.ts +46 -0
- package/src/slash-commands/helpers/marketplace-manager.ts +25 -0
- package/src/slash-commands/helpers/mcp.ts +532 -0
- package/src/slash-commands/helpers/parse.ts +85 -0
- package/src/slash-commands/helpers/ssh.ts +195 -0
- package/src/slash-commands/helpers/stats-dashboard.ts +85 -0
- package/src/slash-commands/helpers/todo.ts +279 -0
- package/src/slash-commands/helpers/usage-report.ts +95 -0
- package/src/slash-commands/marketplace-install-parser.ts +99 -0
- package/src/slash-commands/types.ts +135 -0
- package/src/ssh/config-writer.ts +183 -0
- package/src/ssh/connection-manager.ts +509 -0
- package/src/ssh/ssh-executor.ts +189 -0
- package/src/ssh/sshfs-mount.ts +140 -0
- package/src/ssh/utils.ts +8 -0
- package/src/stt/downloader.ts +71 -0
- package/src/stt/index.ts +3 -0
- package/src/stt/recorder.ts +351 -0
- package/src/stt/setup.ts +52 -0
- package/src/stt/stt-controller.ts +160 -0
- package/src/stt/transcribe.py +70 -0
- package/src/stt/transcriber.ts +91 -0
- package/src/stubs/natives/index.ts +814 -0
- package/src/stubs/natives/package.json +7 -0
- package/src/stubs/tui/index.ts +282 -0
- package/src/stubs/tui/package.json +7 -0
- package/src/system-prompt.ts +611 -0
- package/src/task/agents.ts +167 -0
- package/src/task/commands.ts +132 -0
- package/src/task/discovery.ts +122 -0
- package/src/task/executor.ts +2133 -0
- package/src/task/index.ts +1419 -0
- package/src/task/name-generator.ts +1577 -0
- package/src/task/omp-command.ts +26 -0
- package/src/task/output-manager.ts +88 -0
- package/src/task/parallel.ts +116 -0
- package/src/task/render.ts +1381 -0
- package/src/task/repair-args.ts +129 -0
- package/src/task/subprocess-tool-registry.ts +88 -0
- package/src/task/types.ts +336 -0
- package/src/task/worktree.ts +514 -0
- package/src/telemetry-export.ts +144 -0
- package/src/thinking.ts +167 -0
- package/src/tiny/compiled-runtime.ts +179 -0
- package/src/tiny/device.ts +111 -0
- package/src/tiny/dtype.ts +101 -0
- package/src/tiny/models.ts +242 -0
- package/src/tiny/text.ts +165 -0
- package/src/tiny/title-client.ts +543 -0
- package/src/tiny/title-protocol.ts +56 -0
- package/src/tiny/worker.ts +568 -0
- package/src/tool-discovery/mode.ts +24 -0
- package/src/tool-discovery/tool-index.ts +256 -0
- package/src/tools/approval.ts +189 -0
- package/src/tools/archive-reader.ts +721 -0
- package/src/tools/ask.ts +928 -0
- package/src/tools/ast-edit.ts +642 -0
- package/src/tools/ast-grep.ts +452 -0
- package/src/tools/auto-generated-guard.ts +322 -0
- package/src/tools/bash-command-fixup.ts +37 -0
- package/src/tools/bash-interactive.ts +408 -0
- package/src/tools/bash-interceptor.ts +67 -0
- package/src/tools/bash-pty-selection.ts +14 -0
- package/src/tools/bash-skill-urls.ts +248 -0
- package/src/tools/bash.ts +1386 -0
- package/src/tools/browser/attach.ts +175 -0
- package/src/tools/browser/launch.ts +660 -0
- package/src/tools/browser/readable.ts +112 -0
- package/src/tools/browser/registry.ts +197 -0
- package/src/tools/browser/render.ts +216 -0
- package/src/tools/browser/tab-protocol.ts +105 -0
- package/src/tools/browser/tab-supervisor.ts +628 -0
- package/src/tools/browser/tab-worker-entry.ts +21 -0
- package/src/tools/browser/tab-worker.ts +1226 -0
- package/src/tools/browser.ts +343 -0
- package/src/tools/checkpoint.ts +136 -0
- package/src/tools/conflict-detect.ts +718 -0
- package/src/tools/context.ts +39 -0
- package/src/tools/debug.ts +1067 -0
- package/src/tools/eval-backends.ts +27 -0
- package/src/tools/eval-render.ts +752 -0
- package/src/tools/eval.ts +577 -0
- package/src/tools/fetch.ts +1926 -0
- package/src/tools/file-recorder.ts +35 -0
- package/src/tools/find.ts +609 -0
- package/src/tools/fs-cache-invalidation.ts +28 -0
- package/src/tools/gh-cache-invalidation.ts +255 -0
- package/src/tools/gh-format.ts +12 -0
- package/src/tools/gh-renderer.ts +481 -0
- package/src/tools/gh.ts +3720 -0
- package/src/tools/github-cache.ts +637 -0
- package/src/tools/grouped-file-output.ts +210 -0
- package/src/tools/image-gen.ts +1517 -0
- package/src/tools/index.ts +599 -0
- package/src/tools/inspect-image-renderer.ts +132 -0
- package/src/tools/inspect-image.ts +174 -0
- package/src/tools/irc.ts +723 -0
- package/src/tools/job.ts +557 -0
- package/src/tools/json-tree.ts +243 -0
- package/src/tools/jtd-to-json-schema.ts +219 -0
- package/src/tools/jtd-to-typescript.ts +136 -0
- package/src/tools/jtd-utils.ts +102 -0
- package/src/tools/list-limit.ts +40 -0
- package/src/tools/match-line-format.ts +20 -0
- package/src/tools/memory-edit.ts +59 -0
- package/src/tools/memory-recall.ts +100 -0
- package/src/tools/memory-reflect.ts +88 -0
- package/src/tools/memory-render.ts +202 -0
- package/src/tools/memory-retain.ts +91 -0
- package/src/tools/output-meta.ts +754 -0
- package/src/tools/output-schema-validator.ts +132 -0
- package/src/tools/path-utils.ts +1054 -0
- package/src/tools/plan-mode-guard.ts +108 -0
- package/src/tools/puppeteer/00_stealth_tampering.txt +63 -0
- package/src/tools/puppeteer/01_stealth_activity.txt +20 -0
- package/src/tools/puppeteer/02_stealth_hairline.txt +11 -0
- package/src/tools/puppeteer/03_stealth_botd.txt +384 -0
- package/src/tools/puppeteer/04_stealth_iframe.txt +81 -0
- package/src/tools/puppeteer/05_stealth_webgl.txt +75 -0
- package/src/tools/puppeteer/06_stealth_screen.txt +72 -0
- package/src/tools/puppeteer/07_stealth_fonts.txt +97 -0
- package/src/tools/puppeteer/08_stealth_audio.txt +51 -0
- package/src/tools/puppeteer/09_stealth_locale.txt +46 -0
- package/src/tools/puppeteer/10_stealth_plugins.txt +206 -0
- package/src/tools/puppeteer/11_stealth_hardware.txt +8 -0
- package/src/tools/puppeteer/12_stealth_codecs.txt +40 -0
- package/src/tools/puppeteer/13_stealth_worker.txt +74 -0
- package/src/tools/read.ts +2929 -0
- package/src/tools/render-mermaid.ts +69 -0
- package/src/tools/render-utils.ts +838 -0
- package/src/tools/renderers.ts +77 -0
- package/src/tools/report-tool-issue.ts +534 -0
- package/src/tools/resolve.ts +276 -0
- package/src/tools/review.ts +253 -0
- package/src/tools/search-tool-bm25.ts +351 -0
- package/src/tools/search.ts +1580 -0
- package/src/tools/sqlite-reader.ts +828 -0
- package/src/tools/ssh.ts +349 -0
- package/src/tools/todo.ts +982 -0
- package/src/tools/tool-errors.ts +62 -0
- package/src/tools/tool-result.ts +94 -0
- package/src/tools/tool-timeouts.ts +30 -0
- package/src/tools/tts.ts +133 -0
- package/src/tools/write.ts +1217 -0
- package/src/tools/yield.ts +269 -0
- package/src/tui/code-cell.ts +216 -0
- package/src/tui/file-list.ts +55 -0
- package/src/tui/hyperlink.ts +175 -0
- package/src/tui/index.ts +12 -0
- package/src/tui/output-block.ts +240 -0
- package/src/tui/status-line.ts +54 -0
- package/src/tui/tree-list.ts +84 -0
- package/src/tui/types.ts +15 -0
- package/src/tui/utils.ts +103 -0
- package/src/utils/block-context.ts +312 -0
- package/src/utils/changelog.ts +132 -0
- package/src/utils/clipboard.ts +193 -0
- package/src/utils/command-args.ts +76 -0
- package/src/utils/commit-message-generator.ts +151 -0
- package/src/utils/edit-mode.ts +41 -0
- package/src/utils/enhanced-paste.ts +230 -0
- package/src/utils/event-bus.ts +33 -0
- package/src/utils/external-editor.ts +65 -0
- package/src/utils/file-display-mode.ts +45 -0
- package/src/utils/file-mentions.ts +281 -0
- package/src/utils/git.ts +1833 -0
- package/src/utils/image-loading.ts +132 -0
- package/src/utils/image-resize.ts +309 -0
- package/src/utils/jj.ts +248 -0
- package/src/utils/lang-from-path.ts +239 -0
- package/src/utils/markit.ts +89 -0
- package/src/utils/open.ts +55 -0
- package/src/utils/session-color.ts +68 -0
- package/src/utils/shell-snapshot.ts +187 -0
- package/src/utils/sixel.ts +69 -0
- package/src/utils/title-generator.ts +373 -0
- package/src/utils/tool-choice.ts +33 -0
- package/src/utils/tools-manager.ts +363 -0
- package/src/web/kagi.ts +305 -0
- package/src/web/parallel.ts +353 -0
- package/src/web/scrapers/artifacthub.ts +207 -0
- package/src/web/scrapers/arxiv.ts +83 -0
- package/src/web/scrapers/aur.ts +162 -0
- package/src/web/scrapers/biorxiv.ts +133 -0
- package/src/web/scrapers/bluesky.ts +262 -0
- package/src/web/scrapers/brew.ts +172 -0
- package/src/web/scrapers/cheatsh.ts +68 -0
- package/src/web/scrapers/chocolatey.ts +196 -0
- package/src/web/scrapers/choosealicense.ts +95 -0
- package/src/web/scrapers/cisa-kev.ts +87 -0
- package/src/web/scrapers/clojars.ts +154 -0
- package/src/web/scrapers/coingecko.ts +177 -0
- package/src/web/scrapers/crates-io.ts +97 -0
- package/src/web/scrapers/crossref.ts +136 -0
- package/src/web/scrapers/devto.ts +147 -0
- package/src/web/scrapers/discogs.ts +306 -0
- package/src/web/scrapers/discourse.ts +197 -0
- package/src/web/scrapers/dockerhub.ts +138 -0
- package/src/web/scrapers/docs-rs.ts +653 -0
- package/src/web/scrapers/fdroid.ts +134 -0
- package/src/web/scrapers/firefox-addons.ts +191 -0
- package/src/web/scrapers/flathub.ts +223 -0
- package/src/web/scrapers/github-gist.ts +58 -0
- package/src/web/scrapers/github.ts +704 -0
- package/src/web/scrapers/gitlab.ts +401 -0
- package/src/web/scrapers/go-pkg.ts +266 -0
- package/src/web/scrapers/hackage.ts +140 -0
- package/src/web/scrapers/hackernews.ts +189 -0
- package/src/web/scrapers/hex.ts +105 -0
- package/src/web/scrapers/huggingface.ts +321 -0
- package/src/web/scrapers/iacr.ts +89 -0
- package/src/web/scrapers/index.ts +252 -0
- package/src/web/scrapers/jetbrains-marketplace.ts +159 -0
- package/src/web/scrapers/lemmy.ts +203 -0
- package/src/web/scrapers/lobsters.ts +175 -0
- package/src/web/scrapers/mastodon.ts +292 -0
- package/src/web/scrapers/maven.ts +138 -0
- package/src/web/scrapers/mdn.ts +173 -0
- package/src/web/scrapers/metacpan.ts +222 -0
- package/src/web/scrapers/musicbrainz.ts +250 -0
- package/src/web/scrapers/npm.ts +98 -0
- package/src/web/scrapers/nuget.ts +183 -0
- package/src/web/scrapers/nvd.ts +222 -0
- package/src/web/scrapers/ollama.ts +239 -0
- package/src/web/scrapers/open-vsx.ts +106 -0
- package/src/web/scrapers/opencorporates.ts +292 -0
- package/src/web/scrapers/openlibrary.ts +336 -0
- package/src/web/scrapers/orcid.ts +286 -0
- package/src/web/scrapers/osv.ts +176 -0
- package/src/web/scrapers/packagist.ts +160 -0
- package/src/web/scrapers/pub-dev.ts +143 -0
- package/src/web/scrapers/pubmed.ts +211 -0
- package/src/web/scrapers/pypi.ts +112 -0
- package/src/web/scrapers/rawg.ts +110 -0
- package/src/web/scrapers/readthedocs.ts +120 -0
- package/src/web/scrapers/reddit.ts +95 -0
- package/src/web/scrapers/repology.ts +251 -0
- package/src/web/scrapers/rfc.ts +201 -0
- package/src/web/scrapers/rubygems.ts +103 -0
- package/src/web/scrapers/searchcode.ts +189 -0
- package/src/web/scrapers/sec-edgar.ts +261 -0
- package/src/web/scrapers/semantic-scholar.ts +171 -0
- package/src/web/scrapers/snapcraft.ts +187 -0
- package/src/web/scrapers/sourcegraph.ts +336 -0
- package/src/web/scrapers/spdx.ts +108 -0
- package/src/web/scrapers/spotify.ts +198 -0
- package/src/web/scrapers/stackoverflow.ts +120 -0
- package/src/web/scrapers/terraform.ts +277 -0
- package/src/web/scrapers/tldr.ts +47 -0
- package/src/web/scrapers/twitter.ts +94 -0
- package/src/web/scrapers/types.ts +397 -0
- package/src/web/scrapers/utils.ts +109 -0
- package/src/web/scrapers/vimeo.ts +133 -0
- package/src/web/scrapers/vscode-marketplace.ts +187 -0
- package/src/web/scrapers/w3c.ts +156 -0
- package/src/web/scrapers/wikidata.ts +344 -0
- package/src/web/scrapers/wikipedia.ts +84 -0
- package/src/web/scrapers/youtube.ts +325 -0
- package/src/web/search/index.ts +292 -0
- package/src/web/search/provider.ts +157 -0
- package/src/web/search/providers/anthropic.ts +318 -0
- package/src/web/search/providers/base.ts +89 -0
- package/src/web/search/providers/brave.ts +152 -0
- package/src/web/search/providers/codex.ts +591 -0
- package/src/web/search/providers/exa.ts +400 -0
- package/src/web/search/providers/gemini.ts +460 -0
- package/src/web/search/providers/jina.ts +111 -0
- package/src/web/search/providers/kagi.ts +86 -0
- package/src/web/search/providers/kimi.ts +196 -0
- package/src/web/search/providers/parallel.ts +225 -0
- package/src/web/search/providers/perplexity.ts +730 -0
- package/src/web/search/providers/searxng.ts +313 -0
- package/src/web/search/providers/synthetic.ts +114 -0
- package/src/web/search/providers/tavily.ts +176 -0
- package/src/web/search/providers/utils.ts +128 -0
- package/src/web/search/providers/zai.ts +333 -0
- package/src/web/search/render.ts +262 -0
- package/src/web/search/types.ts +482 -0
- package/src/web/search/utils.ts +17 -0
- package/src/workspace-tree.ts +286 -0
|
@@ -0,0 +1,1024 @@
|
|
|
1
|
+
import type { SnapshotStore } from "@oh-my-pi/hashline";
|
|
2
|
+
import type { AgentTool } from "@oh-my-pi/pi-agent-core";
|
|
3
|
+
import {
|
|
4
|
+
Box,
|
|
5
|
+
type Component,
|
|
6
|
+
Container,
|
|
7
|
+
getImageDimensions,
|
|
8
|
+
Image,
|
|
9
|
+
ImageProtocol,
|
|
10
|
+
imageFallback,
|
|
11
|
+
Spacer,
|
|
12
|
+
TERMINAL,
|
|
13
|
+
Text,
|
|
14
|
+
type TUI,
|
|
15
|
+
} from './stubs/tui/index.ts';
|
|
16
|
+
import { getProjectDir, logger, sanitizeText } from "@oh-my-pi/pi-utils";
|
|
17
|
+
import { EDIT_MODE_STRATEGIES, type EditMode, type PerFileDiffPreview } from "../../edit";
|
|
18
|
+
import type { Theme } from "../../modes/theme/theme";
|
|
19
|
+
import { theme } from "../../modes/theme/theme";
|
|
20
|
+
import { BASH_DEFAULT_PREVIEW_LINES } from "../../tools/bash";
|
|
21
|
+
import { EVAL_DEFAULT_PREVIEW_LINES } from "../../tools/eval";
|
|
22
|
+
import { isWaitingPollDetails } from "../../tools/job";
|
|
23
|
+
import {
|
|
24
|
+
formatArgsInline,
|
|
25
|
+
JSON_TREE_MAX_DEPTH_COLLAPSED,
|
|
26
|
+
JSON_TREE_MAX_DEPTH_EXPANDED,
|
|
27
|
+
JSON_TREE_MAX_LINES_COLLAPSED,
|
|
28
|
+
JSON_TREE_MAX_LINES_EXPANDED,
|
|
29
|
+
JSON_TREE_SCALAR_LEN_COLLAPSED,
|
|
30
|
+
JSON_TREE_SCALAR_LEN_EXPANDED,
|
|
31
|
+
renderJsonTreeLines,
|
|
32
|
+
} from "../../tools/json-tree";
|
|
33
|
+
import { formatExpandHint, replaceTabs, resolveImageOptions, truncateToWidth } from "../../tools/render-utils";
|
|
34
|
+
import { toolRenderers } from "../../tools/renderers";
|
|
35
|
+
import { TODO_STRIKE_TOTAL_FRAMES } from "../../tools/todo";
|
|
36
|
+
import { isFramedBlockComponent, renderStatusLine } from "../../tui";
|
|
37
|
+
import { sanitizeWithOptionalSixelPassthrough } from "../../utils/sixel";
|
|
38
|
+
import { renderDiff } from "./diff";
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Drop trailing removal/hunk-header lines that appear in a streaming diff
|
|
42
|
+
* before the matching `+added` lines have arrived. Without this, a partial
|
|
43
|
+
* apply_patch / hashline preview shows `-old` first and then visibly grows
|
|
44
|
+
* the `+new` block beneath it — the "removals first, additions catching up"
|
|
45
|
+
* jitter. Once the next streaming tick brings the additions in, the trailing
|
|
46
|
+
* block reappears alongside them.
|
|
47
|
+
*/
|
|
48
|
+
function stripTrailingUnbalancedRemoval(diff: string | undefined): string | undefined {
|
|
49
|
+
if (!diff) return diff;
|
|
50
|
+
const lines = diff.split("\n");
|
|
51
|
+
let lastAddIdx = -1;
|
|
52
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
53
|
+
if (lines[i].startsWith("+")) {
|
|
54
|
+
lastAddIdx = i;
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
let hasTrailingUnbalanced = false;
|
|
59
|
+
for (let i = lastAddIdx + 1; i < lines.length; i++) {
|
|
60
|
+
const line = lines[i];
|
|
61
|
+
if (line.startsWith("-") || line.startsWith("@@")) {
|
|
62
|
+
hasTrailingUnbalanced = true;
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (!hasTrailingUnbalanced) return diff;
|
|
67
|
+
if (lastAddIdx === -1) return "";
|
|
68
|
+
return lines.slice(0, lastAddIdx + 1).join("\n");
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function stabilizeStreamingPreviews(previews: PerFileDiffPreview[]): PerFileDiffPreview[] {
|
|
72
|
+
let changed = false;
|
|
73
|
+
const next = previews.map(preview => {
|
|
74
|
+
if (!preview.diff) return preview;
|
|
75
|
+
const trimmed = stripTrailingUnbalancedRemoval(preview.diff);
|
|
76
|
+
if (trimmed === preview.diff) return preview;
|
|
77
|
+
changed = true;
|
|
78
|
+
return { ...preview, diff: trimmed ?? "" };
|
|
79
|
+
});
|
|
80
|
+
return changed ? next : previews;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function isEditLikeToolName(toolName: string): boolean {
|
|
84
|
+
return toolName === "edit" || toolName === "apply_patch";
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function resolveEditModeForTool(toolName: string, tool: AgentTool | undefined): EditMode | undefined {
|
|
88
|
+
if (toolName === "apply_patch") return "apply_patch";
|
|
89
|
+
if (toolName !== "edit") return undefined;
|
|
90
|
+
return (tool as { mode?: EditMode } | undefined)?.mode;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function rawTextInputFromPartialJson(partialJson: unknown): string | undefined {
|
|
94
|
+
if (typeof partialJson !== "string") return undefined;
|
|
95
|
+
if (partialJson.length === 0) return undefined;
|
|
96
|
+
const trimmed = partialJson.trimStart();
|
|
97
|
+
if (trimmed.length === 0) return undefined;
|
|
98
|
+
const first = trimmed[0];
|
|
99
|
+
// Function-tool arguments stream as JSON. Custom/free-form tools stream raw
|
|
100
|
+
// text in the same transport field; only the raw form is a valid fallback for
|
|
101
|
+
// the conventional `input` parameter.
|
|
102
|
+
if (first === "{" || first === '"') return undefined;
|
|
103
|
+
return partialJson;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function getArgsWithStreamedTextInput(args: unknown): unknown {
|
|
107
|
+
if (args == null || typeof args !== "object") return args;
|
|
108
|
+
const record = args as Record<string, unknown>;
|
|
109
|
+
if (typeof record.input === "string") return args;
|
|
110
|
+
const input = rawTextInputFromPartialJson(record.__partialJson);
|
|
111
|
+
return input === undefined ? args : { ...record, input };
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export interface ToolExecutionOptions {
|
|
115
|
+
snapshots?: SnapshotStore;
|
|
116
|
+
showImages?: boolean; // default: true (only used if terminal supports images)
|
|
117
|
+
editFuzzyThreshold?: number;
|
|
118
|
+
editAllowFuzzy?: boolean;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export interface ToolExecutionHandle {
|
|
122
|
+
updateArgs(args: any, toolCallId?: string): void;
|
|
123
|
+
updateResult(
|
|
124
|
+
result: {
|
|
125
|
+
content: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;
|
|
126
|
+
details?: any;
|
|
127
|
+
isError?: boolean;
|
|
128
|
+
},
|
|
129
|
+
isPartial?: boolean,
|
|
130
|
+
toolCallId?: string,
|
|
131
|
+
): void;
|
|
132
|
+
setArgsComplete(toolCallId?: string): void;
|
|
133
|
+
setExpanded(expanded: boolean): void;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/** Drive pending-tool redraws at 30fps so the running `task` row's shimmered
|
|
137
|
+
* subagent name stays smooth without spending twice the frame budget. The TUI
|
|
138
|
+
* throttles at the same cadence, and static frames diff to a no-op redraw at
|
|
139
|
+
* ~zero cost. */
|
|
140
|
+
const SPINNER_RENDER_INTERVAL_MS = 1000 / 30;
|
|
141
|
+
/** Advance the spinner glyph at its classic ~12.5fps step, decoupled from the
|
|
142
|
+
* render cadence (mirrors `Loader`). */
|
|
143
|
+
const SPINNER_GLYPH_ADVANCE_MS = 80;
|
|
144
|
+
|
|
145
|
+
// Stable per-instance counter so each tool execution's inline images get a
|
|
146
|
+
// graphics id that survives child re-creation (the image budget keys off it).
|
|
147
|
+
let toolExecutionInstanceSeq = 0;
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Component that renders a tool call with its result (updateable)
|
|
151
|
+
*/
|
|
152
|
+
export class ToolExecutionComponent extends Container {
|
|
153
|
+
#contentBox: Box; // Used for custom tools and bash visual truncation
|
|
154
|
+
#contentText: Text; // For built-in tools (with its own padding/bg)
|
|
155
|
+
#multiFileBoxes: (Box | Spacer)[] = []; // Extra boxes for multi-file edit results
|
|
156
|
+
#imageComponents: Image[] = [];
|
|
157
|
+
#imageSpacers: Spacer[] = [];
|
|
158
|
+
readonly #instanceId = ++toolExecutionInstanceSeq;
|
|
159
|
+
#toolName: string;
|
|
160
|
+
#toolLabel: string;
|
|
161
|
+
#args: any;
|
|
162
|
+
#expanded = false;
|
|
163
|
+
#showImages: boolean;
|
|
164
|
+
#editFuzzyThreshold: number | undefined;
|
|
165
|
+
#editAllowFuzzy: boolean | undefined;
|
|
166
|
+
#snapshots?: SnapshotStore;
|
|
167
|
+
#isPartial = true;
|
|
168
|
+
#tool?: AgentTool;
|
|
169
|
+
#ui: TUI;
|
|
170
|
+
#cwd: string;
|
|
171
|
+
#result?: {
|
|
172
|
+
content: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;
|
|
173
|
+
isError?: boolean;
|
|
174
|
+
details?: any;
|
|
175
|
+
};
|
|
176
|
+
// Edit preview state
|
|
177
|
+
#editMode?: EditMode;
|
|
178
|
+
#editDiffPreview?: PerFileDiffPreview[];
|
|
179
|
+
#editDiffAbort?: AbortController;
|
|
180
|
+
#editDiffLastArgsKey?: string;
|
|
181
|
+
// Latest in-flight streaming diff recompute, captured so it can be awaited.
|
|
182
|
+
#editDiffInFlight?: Promise<void>;
|
|
183
|
+
// Cached converted images for Kitty protocol (which requires PNG), keyed by index
|
|
184
|
+
#convertedImages: Map<number, { data: string; mimeType: string }> = new Map();
|
|
185
|
+
// Spinner animation for partial task results
|
|
186
|
+
#spinnerFrame?: number;
|
|
187
|
+
#spinnerInterval?: NodeJS.Timeout;
|
|
188
|
+
#lastSpinnerAdvanceAt = 0;
|
|
189
|
+
// Todo write completion strikethrough reveal animation
|
|
190
|
+
#todoStrikeInterval?: NodeJS.Timeout;
|
|
191
|
+
// Track if args are still being streamed (for edit/write spinner)
|
|
192
|
+
#argsComplete = false;
|
|
193
|
+
// Sealed once the tool reaches a terminal state (result delivered, or the
|
|
194
|
+
// turn abandoned it without one). Drives `isTranscriptBlockFinalized`: until
|
|
195
|
+
// sealed the block stays in the transcript's repaintable live region so a
|
|
196
|
+
// late result still repaints instead of stranding the streaming preview.
|
|
197
|
+
#sealed = false;
|
|
198
|
+
// A `job` poll result whose watched jobs are all still running. Such a
|
|
199
|
+
// block never finalizes (stays in the transcript live region) so a
|
|
200
|
+
// follow-up `job` call can displace it instead of stacking another
|
|
201
|
+
// "waiting on N jobs" frame. Cleared by `seal()`.
|
|
202
|
+
#displaceable = false;
|
|
203
|
+
#renderState: {
|
|
204
|
+
spinnerFrame?: number;
|
|
205
|
+
expanded: boolean;
|
|
206
|
+
isPartial: boolean;
|
|
207
|
+
renderContext?: Record<string, unknown>;
|
|
208
|
+
} = {
|
|
209
|
+
expanded: false,
|
|
210
|
+
isPartial: true,
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
constructor(
|
|
214
|
+
toolName: string,
|
|
215
|
+
args: any,
|
|
216
|
+
options: ToolExecutionOptions = {},
|
|
217
|
+
tool: AgentTool | undefined,
|
|
218
|
+
ui: TUI,
|
|
219
|
+
cwd: string = getProjectDir(),
|
|
220
|
+
_toolCallId?: string,
|
|
221
|
+
) {
|
|
222
|
+
super();
|
|
223
|
+
this.#toolName = toolName;
|
|
224
|
+
this.#toolLabel = tool?.label ?? toolName;
|
|
225
|
+
this.#showImages = options.showImages ?? true;
|
|
226
|
+
this.#editFuzzyThreshold = options.editFuzzyThreshold;
|
|
227
|
+
this.#editAllowFuzzy = options.editAllowFuzzy;
|
|
228
|
+
this.#snapshots = options.snapshots;
|
|
229
|
+
this.#tool = tool;
|
|
230
|
+
this.#ui = ui;
|
|
231
|
+
this.#cwd = cwd;
|
|
232
|
+
this.#args = args;
|
|
233
|
+
|
|
234
|
+
// Always create both - contentBox for custom tools/bash/tools with renderers, contentText for other built-ins.
|
|
235
|
+
// paddingY is 1 so background-tinted blocks (custom/extension tools and the
|
|
236
|
+
// generic fallback) get top/bottom breathing room. TranscriptContainer
|
|
237
|
+
// strips PLAIN-blank edges, so framed/minimal blocks (no bg set) drop these
|
|
238
|
+
// lines and keep their tight spacing — only tinted lines survive.
|
|
239
|
+
this.#contentBox = new Box(0, 1);
|
|
240
|
+
this.#contentText = new Text("", 1, 1);
|
|
241
|
+
|
|
242
|
+
// Use Box for custom tools or built-in tools that have renderers
|
|
243
|
+
const hasRenderer = toolName in toolRenderers;
|
|
244
|
+
const hasCustomRenderer = !!(tool?.renderCall || tool?.renderResult);
|
|
245
|
+
if (hasCustomRenderer || hasRenderer) {
|
|
246
|
+
this.addChild(this.#contentBox);
|
|
247
|
+
} else {
|
|
248
|
+
this.addChild(this.#contentText);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
this.#editMode = resolveEditModeForTool(toolName, tool);
|
|
252
|
+
|
|
253
|
+
this.#updateDisplay();
|
|
254
|
+
this.#editDiffInFlight = this.#runPreviewDiff();
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
updateArgs(args: any, _toolCallId?: string): void {
|
|
258
|
+
// Reference-equality short-circuit before any further work. Callers
|
|
259
|
+
// always allocate a new arg object on each streamed delta (see
|
|
260
|
+
// event-controller.ts and ui-helpers.ts), so a same-reference assignment
|
|
261
|
+
// signals "nothing meaningful changed" and the renderer can skip.
|
|
262
|
+
if (args === this.#args) return;
|
|
263
|
+
this.#args = args;
|
|
264
|
+
this.#updateSpinnerAnimation();
|
|
265
|
+
this.#editDiffInFlight = this.#runPreviewDiff();
|
|
266
|
+
this.#updateDisplay();
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Signal that args are complete (tool is about to execute).
|
|
271
|
+
* This triggers an immediate final diff computation for edit-like tools.
|
|
272
|
+
*/
|
|
273
|
+
setArgsComplete(_toolCallId?: string): void {
|
|
274
|
+
this.#argsComplete = true;
|
|
275
|
+
this.#updateSpinnerAnimation();
|
|
276
|
+
this.#editDiffInFlight = this.#runPreviewDiff();
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Await the streaming diff recompute kicked off by the most recent
|
|
281
|
+
* `updateArgs`/`setArgsComplete`. The recompute reads the file and re-runs the
|
|
282
|
+
* whole-file Myers diff off the render path, signalling completion only via a
|
|
283
|
+
* throttled `requestRender`. Tests await this to sample a *settled* preview
|
|
284
|
+
* deterministically instead of racing the spinner's render ticks.
|
|
285
|
+
*/
|
|
286
|
+
async whenPreviewSettled(): Promise<void> {
|
|
287
|
+
await this.#editDiffInFlight;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
async #runPreviewDiff(): Promise<void> {
|
|
291
|
+
const editMode = this.#editMode;
|
|
292
|
+
if (!editMode) return;
|
|
293
|
+
const strategy = EDIT_MODE_STRATEGIES[editMode];
|
|
294
|
+
if (!strategy) return;
|
|
295
|
+
|
|
296
|
+
const args = this.#args;
|
|
297
|
+
if (args == null || typeof args !== "object") return;
|
|
298
|
+
|
|
299
|
+
const previewArgs = getArgsWithStreamedTextInput(args);
|
|
300
|
+
const partialJson = (previewArgs as { __partialJson?: string }).__partialJson;
|
|
301
|
+
let effectiveArgs: unknown;
|
|
302
|
+
try {
|
|
303
|
+
effectiveArgs = strategy.extractCompleteEdits(previewArgs, partialJson);
|
|
304
|
+
} catch {
|
|
305
|
+
effectiveArgs = previewArgs;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// Coalesce duplicate computes for identical args. The key pairs the
|
|
309
|
+
// streaming flag with a content hash: the final (args-complete) pass
|
|
310
|
+
// computes an untrimmed diff and must run even when the payload is
|
|
311
|
+
// byte-identical to the last streamed chunk — only `isStreaming` differs,
|
|
312
|
+
// and it flips the trailing-line trim. Without the flag a single-line edit
|
|
313
|
+
// whose trailing payload line never gets a newline stays stuck on the
|
|
314
|
+
// trimmed "no changes" streaming preview and renders no diff. Hashing keeps
|
|
315
|
+
// the retained key tiny instead of holding the whole serialized blob.
|
|
316
|
+
const streamingState = this.#argsComplete ? "final" : "stream";
|
|
317
|
+
let argsKey: string;
|
|
318
|
+
try {
|
|
319
|
+
argsKey = `${streamingState}:${Bun.hash(JSON.stringify(effectiveArgs))}`;
|
|
320
|
+
} catch {
|
|
321
|
+
// effectiveArgs isn't JSON-serializable (exotic value in tool args).
|
|
322
|
+
// The raw streamed JSON is a plain string, so hash that instead of a
|
|
323
|
+
// timestamp — a deterministic key keeps the dedup cache working
|
|
324
|
+
// instead of recomputing (and re-reading the file) on every render.
|
|
325
|
+
argsKey = `${streamingState}:partial:${Bun.hash(partialJson ?? "")}`;
|
|
326
|
+
}
|
|
327
|
+
if (argsKey === this.#editDiffLastArgsKey) return;
|
|
328
|
+
this.#editDiffLastArgsKey = argsKey;
|
|
329
|
+
|
|
330
|
+
this.#editDiffAbort?.abort();
|
|
331
|
+
const controller = new AbortController();
|
|
332
|
+
this.#editDiffAbort = controller;
|
|
333
|
+
|
|
334
|
+
try {
|
|
335
|
+
const isStreaming = !this.#argsComplete;
|
|
336
|
+
if (editMode === "hashline" && !this.#snapshots) return;
|
|
337
|
+
const previews = await strategy.computeDiffPreview(effectiveArgs, {
|
|
338
|
+
cwd: this.#cwd,
|
|
339
|
+
signal: controller.signal,
|
|
340
|
+
snapshots: this.#snapshots!,
|
|
341
|
+
fuzzyThreshold: this.#editFuzzyThreshold,
|
|
342
|
+
allowFuzzy: this.#editAllowFuzzy,
|
|
343
|
+
isStreaming,
|
|
344
|
+
});
|
|
345
|
+
if (controller.signal.aborted) return;
|
|
346
|
+
if (previews) {
|
|
347
|
+
this.#editDiffPreview = isStreaming ? stabilizeStreamingPreviews(previews) : previews;
|
|
348
|
+
this.#updateDisplay();
|
|
349
|
+
this.#ui.requestRender();
|
|
350
|
+
}
|
|
351
|
+
} catch (err) {
|
|
352
|
+
if (controller.signal.aborted) return;
|
|
353
|
+
logger.warn("Edit preview diff failed", { tool: this.#toolName, error: String(err) });
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
updateResult(
|
|
358
|
+
result: {
|
|
359
|
+
content: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;
|
|
360
|
+
details?: any;
|
|
361
|
+
isError?: boolean;
|
|
362
|
+
},
|
|
363
|
+
isPartial = false,
|
|
364
|
+
_toolCallId?: string,
|
|
365
|
+
): void {
|
|
366
|
+
this.#result = result;
|
|
367
|
+
this.#isPartial = isPartial;
|
|
368
|
+
// A `job` poll that found every watched job still running is transient
|
|
369
|
+
// "still waiting" chrome; keep the block displaceable so the next `job`
|
|
370
|
+
// call replaces it instead of stacking another waiting frame (see the
|
|
371
|
+
// event controller's displaceable-poll bookkeeping).
|
|
372
|
+
this.#displaceable = this.#toolName === "job" && result.isError !== true && isWaitingPollDetails(result.details);
|
|
373
|
+
// When tool is complete, ensure args are marked complete so spinner stops
|
|
374
|
+
if (!isPartial) {
|
|
375
|
+
this.#argsComplete = true;
|
|
376
|
+
}
|
|
377
|
+
this.#updateSpinnerAnimation();
|
|
378
|
+
this.#updateTodoStrikeAnimation();
|
|
379
|
+
this.#updateDisplay();
|
|
380
|
+
// Convert non-PNG images to PNG for Kitty protocol (async)
|
|
381
|
+
this.#maybeConvertImagesForKitty();
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
/**
|
|
385
|
+
* Get all image blocks from result content and details.images.
|
|
386
|
+
* Some tools (like generate_image) store images in details to avoid bloating model context.
|
|
387
|
+
*/
|
|
388
|
+
#getAllImageBlocks(): Array<{ data?: string; mimeType?: string }> {
|
|
389
|
+
if (!this.#result) return [];
|
|
390
|
+
const contentImages = this.#result.content?.filter((c: any) => c.type === "image") || [];
|
|
391
|
+
const detailImages = this.#result.details?.images || [];
|
|
392
|
+
return [...contentImages, ...detailImages];
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/**
|
|
396
|
+
* Convert non-PNG images to PNG for Kitty graphics protocol.
|
|
397
|
+
* Kitty requires PNG format (f=100), so JPEG/GIF/WebP won't display.
|
|
398
|
+
*/
|
|
399
|
+
#maybeConvertImagesForKitty(): void {
|
|
400
|
+
// Only needed for Kitty protocol
|
|
401
|
+
if (TERMINAL.imageProtocol !== ImageProtocol.Kitty) return;
|
|
402
|
+
if (!this.#result) return;
|
|
403
|
+
|
|
404
|
+
const imageBlocks = this.#getAllImageBlocks();
|
|
405
|
+
|
|
406
|
+
for (let i = 0; i < imageBlocks.length; i++) {
|
|
407
|
+
const img = imageBlocks[i];
|
|
408
|
+
if (!img.data || !img.mimeType) continue;
|
|
409
|
+
// Skip if already PNG or already converted
|
|
410
|
+
if (img.mimeType === "image/png") continue;
|
|
411
|
+
if (this.#convertedImages.has(i)) continue;
|
|
412
|
+
|
|
413
|
+
// Convert async - catch errors from processing
|
|
414
|
+
const index = i;
|
|
415
|
+
new Bun.Image(Buffer.from(img.data, "base64"))
|
|
416
|
+
.png()
|
|
417
|
+
.toBase64()
|
|
418
|
+
.then(data => {
|
|
419
|
+
this.#convertedImages.set(index, { data, mimeType: "image/png" });
|
|
420
|
+
this.#updateDisplay();
|
|
421
|
+
this.#ui.requestRender();
|
|
422
|
+
})
|
|
423
|
+
.catch(() => {
|
|
424
|
+
// Ignore conversion failures - display will use original image format
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
/**
|
|
430
|
+
* Start or stop spinner animation based on whether this is a partial task result.
|
|
431
|
+
*/
|
|
432
|
+
#updateSpinnerAnimation(): void {
|
|
433
|
+
// Spinner for: task tool with partial result, or edit/write while args streaming
|
|
434
|
+
const isStreamingArgs = !this.#argsComplete && (isEditLikeToolName(this.#toolName) || this.#toolName === "write");
|
|
435
|
+
const isBackgroundAsyncRunning =
|
|
436
|
+
(this.#result?.details as { async?: { state?: string } } | undefined)?.async?.state === "running";
|
|
437
|
+
const isBackgroundAsyncTask = this.#toolName === "task" && isBackgroundAsyncRunning;
|
|
438
|
+
const isPartialTask = this.#isPartial && this.#toolName === "task" && !isBackgroundAsyncTask;
|
|
439
|
+
// A displaceable waiting poll keeps its spinner ticking: it reads as one
|
|
440
|
+
// persistent live poll, and the changing leading glyph keeps the
|
|
441
|
+
// transcript's stable-prefix ratchet from committing rows of a block
|
|
442
|
+
// that a follow-up `job` call may remove.
|
|
443
|
+
const needsSpinner = isStreamingArgs || isPartialTask || this.isDisplaceableBlock();
|
|
444
|
+
if (needsSpinner && !this.#spinnerInterval) {
|
|
445
|
+
const now = performance.now();
|
|
446
|
+
const frameCount = theme.spinnerFrames.length;
|
|
447
|
+
this.#lastSpinnerAdvanceAt = now;
|
|
448
|
+
if (frameCount > 0 && this.#spinnerFrame === undefined) {
|
|
449
|
+
this.#spinnerFrame = 0;
|
|
450
|
+
this.#renderState.spinnerFrame = 0;
|
|
451
|
+
}
|
|
452
|
+
this.#spinnerInterval = setInterval(() => {
|
|
453
|
+
const now = performance.now();
|
|
454
|
+
const frameCount = theme.spinnerFrames.length;
|
|
455
|
+
// Redraw at 30fps for a smooth `task` name shimmer, but keep the spinner
|
|
456
|
+
// glyph phase-locked to its classic ~12.5fps cadence. Advancing the
|
|
457
|
+
// anchor by elapsed frames instead of resetting to `now` avoids the
|
|
458
|
+
// 30fps timer quantizing the glyph down to one step every three ticks.
|
|
459
|
+
if (frameCount > 0) {
|
|
460
|
+
const elapsed = now - this.#lastSpinnerAdvanceAt;
|
|
461
|
+
if (elapsed >= SPINNER_GLYPH_ADVANCE_MS) {
|
|
462
|
+
const steps = Math.floor(elapsed / SPINNER_GLYPH_ADVANCE_MS);
|
|
463
|
+
this.#spinnerFrame = ((this.#spinnerFrame ?? 0) + steps) % frameCount;
|
|
464
|
+
this.#renderState.spinnerFrame = this.#spinnerFrame;
|
|
465
|
+
this.#lastSpinnerAdvanceAt += steps * SPINNER_GLYPH_ADVANCE_MS;
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
this.#ui.requestRender();
|
|
469
|
+
}, SPINNER_RENDER_INTERVAL_MS);
|
|
470
|
+
} else if (!needsSpinner && this.#spinnerInterval) {
|
|
471
|
+
clearInterval(this.#spinnerInterval);
|
|
472
|
+
this.#spinnerInterval = undefined;
|
|
473
|
+
// Clear the last drawn frame so a non-live renderCall (e.g. a write whose
|
|
474
|
+
// args just completed) stops showing a frozen spinner glyph. Skip when a
|
|
475
|
+
// todo strike owns the frame — it sets its own value right after this.
|
|
476
|
+
if (!this.#todoStrikeInterval) {
|
|
477
|
+
this.#spinnerFrame = undefined;
|
|
478
|
+
this.#renderState.spinnerFrame = undefined;
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
#updateTodoStrikeAnimation(): void {
|
|
484
|
+
if (this.#toolName !== "todo" || this.#isPartial || this.#result?.isError) {
|
|
485
|
+
this.#stopTodoStrikeAnimation();
|
|
486
|
+
return;
|
|
487
|
+
}
|
|
488
|
+
const completedTasks = (this.#result?.details as { completedTasks?: unknown[] } | undefined)?.completedTasks;
|
|
489
|
+
if (!completedTasks || completedTasks.length === 0) {
|
|
490
|
+
this.#stopTodoStrikeAnimation();
|
|
491
|
+
return;
|
|
492
|
+
}
|
|
493
|
+
if (this.#todoStrikeInterval) return;
|
|
494
|
+
|
|
495
|
+
this.#spinnerFrame = 0;
|
|
496
|
+
this.#renderState.spinnerFrame = 0;
|
|
497
|
+
this.#todoStrikeInterval = setInterval(() => {
|
|
498
|
+
const nextFrame = (this.#spinnerFrame ?? 0) + 1;
|
|
499
|
+
if (nextFrame > TODO_STRIKE_TOTAL_FRAMES) {
|
|
500
|
+
this.#stopTodoStrikeAnimation();
|
|
501
|
+
} else {
|
|
502
|
+
this.#spinnerFrame = nextFrame;
|
|
503
|
+
this.#renderState.spinnerFrame = nextFrame;
|
|
504
|
+
}
|
|
505
|
+
this.#ui.requestRender();
|
|
506
|
+
}, 65);
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
#stopTodoStrikeAnimation(): void {
|
|
510
|
+
if (this.#todoStrikeInterval) {
|
|
511
|
+
clearInterval(this.#todoStrikeInterval);
|
|
512
|
+
this.#todoStrikeInterval = undefined;
|
|
513
|
+
}
|
|
514
|
+
if (!this.#spinnerInterval) {
|
|
515
|
+
this.#spinnerFrame = undefined;
|
|
516
|
+
this.#renderState.spinnerFrame = undefined;
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
/**
|
|
521
|
+
* Whether this block has reached a terminal state for transcript freezing.
|
|
522
|
+
* Reports `false` while it can still visually change so the
|
|
523
|
+
* {@link TranscriptContainer} keeps it inside the repaintable live region:
|
|
524
|
+
* a foreground tool awaiting its result, or one streaming partial output.
|
|
525
|
+
* A final (non-partial) result, a background-async tool the agent has moved
|
|
526
|
+
* past, or an explicit {@link seal} flips it to `true`.
|
|
527
|
+
*/
|
|
528
|
+
isTranscriptBlockFinalized(): boolean {
|
|
529
|
+
if (this.#sealed) return true;
|
|
530
|
+
if (this.#result === undefined) return false;
|
|
531
|
+
// A displaceable waiting poll stays live: its rows are kept out of
|
|
532
|
+
// native scrollback so a follow-up `job` call can remove the block.
|
|
533
|
+
if (this.#displaceable) return false;
|
|
534
|
+
if (!this.#isPartial) return true;
|
|
535
|
+
// Partial result: a background async tool is accepted to freeze (the agent
|
|
536
|
+
// continues while it runs and would otherwise pin an unbounded live region);
|
|
537
|
+
// a foreground tool streaming partial output stays live until it finishes.
|
|
538
|
+
return (this.#result.details as { async?: { state?: string } } | undefined)?.async?.state === "running";
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
/**
|
|
542
|
+
* Mark the tool terminal even though no result arrived (the turn aborted or
|
|
543
|
+
* abandoned it) and stop animating, so it can freeze and stops pinning the
|
|
544
|
+
* transcript live region.
|
|
545
|
+
*/
|
|
546
|
+
seal(): void {
|
|
547
|
+
if (this.#sealed) return;
|
|
548
|
+
this.#sealed = true;
|
|
549
|
+
this.#displaceable = false;
|
|
550
|
+
this.stopAnimation();
|
|
551
|
+
this.#updateDisplay();
|
|
552
|
+
this.#ui.requestRender();
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
/**
|
|
556
|
+
* Whether this block is a waiting `job` poll (every watched job still
|
|
557
|
+
* running) that has not been sealed. Such a block never finalized, so none
|
|
558
|
+
* of its rows entered native scrollback (the ticking spinner keeps the
|
|
559
|
+
* stable-prefix ratchet at zero) and the whole block can be removed when a
|
|
560
|
+
* follow-up `job` call supersedes it.
|
|
561
|
+
*/
|
|
562
|
+
isDisplaceableBlock(): boolean {
|
|
563
|
+
return this.#displaceable && !this.#sealed;
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
/**
|
|
567
|
+
* Stop spinner animation and cleanup resources.
|
|
568
|
+
*/
|
|
569
|
+
stopAnimation(): void {
|
|
570
|
+
if (this.#spinnerInterval) {
|
|
571
|
+
clearInterval(this.#spinnerInterval);
|
|
572
|
+
this.#spinnerInterval = undefined;
|
|
573
|
+
this.#spinnerFrame = undefined;
|
|
574
|
+
this.#renderState.spinnerFrame = undefined;
|
|
575
|
+
}
|
|
576
|
+
this.#stopTodoStrikeAnimation();
|
|
577
|
+
this.#editDiffAbort?.abort();
|
|
578
|
+
this.#editDiffAbort = undefined;
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
setExpanded(expanded: boolean): void {
|
|
582
|
+
this.#expanded = expanded;
|
|
583
|
+
this.#updateDisplay();
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
setShowImages(show: boolean): void {
|
|
587
|
+
this.#showImages = show;
|
|
588
|
+
this.#updateDisplay();
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
override invalidate(): void {
|
|
592
|
+
super.invalidate();
|
|
593
|
+
this.#updateDisplay();
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
#updateDisplay(): void {
|
|
597
|
+
// Sync shared mutable render state for component closures
|
|
598
|
+
this.#renderState.expanded = this.#expanded;
|
|
599
|
+
this.#renderState.isPartial = this.#isPartial;
|
|
600
|
+
this.#renderState.spinnerFrame = this.#spinnerFrame;
|
|
601
|
+
|
|
602
|
+
// Non-self-framing tools (custom/extension renderers and the generic
|
|
603
|
+
// fallback) get a padded, state-tinted block — built-ins that draw their
|
|
604
|
+
// own frame opt out below via the framed-component mark.
|
|
605
|
+
const stateBgKey = this.#isPartial ? "toolPendingBg" : this.#result?.isError ? "toolErrorBg" : "toolSuccessBg";
|
|
606
|
+
const stateBgFn = (t: string) => theme.bg(stateBgKey, t);
|
|
607
|
+
|
|
608
|
+
// Check for custom tool rendering
|
|
609
|
+
if (this.#tool && (this.#tool.renderCall || this.#tool.renderResult)) {
|
|
610
|
+
const tool = this.#tool;
|
|
611
|
+
const mergeCallAndResult = Boolean((tool as { mergeCallAndResult?: boolean }).mergeCallAndResult);
|
|
612
|
+
// Custom tools use Box for flexible component rendering
|
|
613
|
+
this.#contentBox.setBgFn(undefined);
|
|
614
|
+
this.#contentBox.clear();
|
|
615
|
+
// Mirror the built-in renderer branch so custom renderers (notably the
|
|
616
|
+
// task tool, whose live instance routes through here) receive the same
|
|
617
|
+
// render context — e.g. the `hasResult` flag that suppresses the task
|
|
618
|
+
// call preview once result lines exist.
|
|
619
|
+
this.#renderState.renderContext = this.#buildRenderContext();
|
|
620
|
+
|
|
621
|
+
// Render call component. The fallback label only stands in for a
|
|
622
|
+
// missing `renderCall`; when the call is intentionally suppressed
|
|
623
|
+
// (mergeCallAndResult once a result exists) we render nothing here so
|
|
624
|
+
// the result component isn't preceded by a redundant tool-name line.
|
|
625
|
+
const shouldRenderCall = !this.#result || !mergeCallAndResult;
|
|
626
|
+
if (shouldRenderCall) {
|
|
627
|
+
if (tool.renderCall) {
|
|
628
|
+
try {
|
|
629
|
+
const callComponent = tool.renderCall(this.#getCallArgsForRender(), this.#renderState, theme);
|
|
630
|
+
if (callComponent) this.#contentBox.addChild(callComponent as Component);
|
|
631
|
+
} catch (err) {
|
|
632
|
+
logger.warn("Tool renderer failed", { tool: this.#toolName, error: String(err) });
|
|
633
|
+
// Fall back to default on error
|
|
634
|
+
this.#contentBox.addChild(new Text(theme.fg("toolTitle", theme.bold(this.#toolLabel)), 0, 0));
|
|
635
|
+
}
|
|
636
|
+
} else {
|
|
637
|
+
// No custom renderCall, show tool name
|
|
638
|
+
this.#contentBox.addChild(new Text(theme.fg("toolTitle", theme.bold(this.#toolLabel)), 0, 0));
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
// Render result component if we have a result
|
|
643
|
+
if (this.#result && tool.renderResult) {
|
|
644
|
+
try {
|
|
645
|
+
const renderResult = tool.renderResult as (
|
|
646
|
+
result: { content: Array<{ type: string; text?: string }>; details?: unknown; isError?: boolean },
|
|
647
|
+
options: { expanded: boolean; isPartial: boolean; spinnerFrame?: number },
|
|
648
|
+
theme: Theme,
|
|
649
|
+
args?: unknown,
|
|
650
|
+
) => Component;
|
|
651
|
+
const resultComponent = renderResult(
|
|
652
|
+
{
|
|
653
|
+
content: this.#result.content as any,
|
|
654
|
+
details: this.#result.details,
|
|
655
|
+
isError: this.#result.isError,
|
|
656
|
+
},
|
|
657
|
+
this.#renderState,
|
|
658
|
+
theme,
|
|
659
|
+
this.#args,
|
|
660
|
+
);
|
|
661
|
+
if (resultComponent) this.#contentBox.addChild(resultComponent);
|
|
662
|
+
} catch (err) {
|
|
663
|
+
logger.warn("Tool renderer failed", { tool: this.#toolName, error: String(err) });
|
|
664
|
+
// Fall back to showing raw output on error
|
|
665
|
+
const output = this.#getTextOutput();
|
|
666
|
+
if (output) {
|
|
667
|
+
this.#contentBox.addChild(new Text(theme.fg("toolOutput", replaceTabs(output)), 0, 0));
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
} else if (this.#result) {
|
|
671
|
+
// Has result but no custom renderResult
|
|
672
|
+
const output = this.#getTextOutput();
|
|
673
|
+
if (output) {
|
|
674
|
+
this.#contentBox.addChild(new Text(theme.fg("toolOutput", replaceTabs(output)), 0, 0));
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
// Custom tools that draw their own frame (task) render flush; plain
|
|
678
|
+
// extension renderers get the padded, state-tinted block back.
|
|
679
|
+
const customFramed = this.#contentBox.children.some(isFramedBlockComponent);
|
|
680
|
+
this.#contentBox.setPaddingX(customFramed ? 0 : 1);
|
|
681
|
+
this.#contentBox.setBgFn(customFramed ? undefined : stateBgFn);
|
|
682
|
+
} else if (this.#toolName in toolRenderers) {
|
|
683
|
+
// Built-in tools with renderers
|
|
684
|
+
const renderer = toolRenderers[this.#toolName];
|
|
685
|
+
|
|
686
|
+
// Clean up previous multi-file boxes
|
|
687
|
+
for (const box of this.#multiFileBoxes) {
|
|
688
|
+
this.removeChild(box);
|
|
689
|
+
}
|
|
690
|
+
this.#multiFileBoxes = [];
|
|
691
|
+
|
|
692
|
+
// Check for multi-file edit results
|
|
693
|
+
const perFileResults = this.#result?.details?.perFileResults as
|
|
694
|
+
| Array<{ path: string; isError?: boolean }>
|
|
695
|
+
| undefined;
|
|
696
|
+
if (perFileResults && perFileResults.length > 1) {
|
|
697
|
+
// Multi-file: render each file as its own Box (identical to separate tool calls)
|
|
698
|
+
this.#contentBox.setBgFn(undefined);
|
|
699
|
+
this.#contentBox.clear();
|
|
700
|
+
|
|
701
|
+
const renderContext = this.#buildRenderContext();
|
|
702
|
+
this.#renderState.renderContext = renderContext;
|
|
703
|
+
|
|
704
|
+
for (let i = 0; i < perFileResults.length; i++) {
|
|
705
|
+
const fileResult = perFileResults[i];
|
|
706
|
+
if (i > 0) {
|
|
707
|
+
const spacer = new Spacer(1);
|
|
708
|
+
this.#multiFileBoxes.push(spacer);
|
|
709
|
+
this.addChild(spacer);
|
|
710
|
+
}
|
|
711
|
+
const fileBox = new Box(0, 0);
|
|
712
|
+
try {
|
|
713
|
+
const resultComponent = renderer.renderResult(
|
|
714
|
+
{ content: [], details: fileResult, isError: fileResult.isError },
|
|
715
|
+
this.#renderState,
|
|
716
|
+
theme,
|
|
717
|
+
);
|
|
718
|
+
if (resultComponent) fileBox.addChild(resultComponent);
|
|
719
|
+
} catch (err) {
|
|
720
|
+
logger.warn("Tool renderer failed", { tool: this.#toolName, error: String(err) });
|
|
721
|
+
}
|
|
722
|
+
this.#multiFileBoxes.push(fileBox);
|
|
723
|
+
this.addChild(fileBox);
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
// Show pending indicator for remaining files
|
|
727
|
+
const totalFiles = this.#args?.edits
|
|
728
|
+
? new Set((this.#args.edits as any[]).map((e: any) => e?.path).filter(Boolean)).size
|
|
729
|
+
: 0;
|
|
730
|
+
const remaining = Math.max(0, totalFiles - perFileResults.length);
|
|
731
|
+
if (remaining > 0 && this.#isPartial) {
|
|
732
|
+
const pendingSpacer = new Spacer(1);
|
|
733
|
+
this.#multiFileBoxes.push(pendingSpacer);
|
|
734
|
+
this.addChild(pendingSpacer);
|
|
735
|
+
const pendingBox = new Box(0, 0);
|
|
736
|
+
const pendingText = renderStatusLine(
|
|
737
|
+
{
|
|
738
|
+
icon: "pending",
|
|
739
|
+
title: "Edit",
|
|
740
|
+
description: theme.fg("dim", `${remaining} more file${remaining > 1 ? "s" : ""} pending…`),
|
|
741
|
+
},
|
|
742
|
+
theme,
|
|
743
|
+
);
|
|
744
|
+
pendingBox.addChild(new Text(pendingText, 0, 0));
|
|
745
|
+
this.#multiFileBoxes.push(pendingBox);
|
|
746
|
+
this.addChild(pendingBox);
|
|
747
|
+
}
|
|
748
|
+
} else {
|
|
749
|
+
// Single-file or no result: standard rendering
|
|
750
|
+
// Inline renderers skip background styling
|
|
751
|
+
this.#contentBox.setBgFn(undefined);
|
|
752
|
+
this.#contentBox.clear();
|
|
753
|
+
|
|
754
|
+
const renderContext = this.#buildRenderContext();
|
|
755
|
+
this.#renderState.renderContext = renderContext;
|
|
756
|
+
|
|
757
|
+
const shouldRenderCall = !this.#result || !renderer.mergeCallAndResult;
|
|
758
|
+
if (shouldRenderCall) {
|
|
759
|
+
// Render call component
|
|
760
|
+
try {
|
|
761
|
+
const callComponent = renderer.renderCall(this.#getCallArgsForRender(), this.#renderState, theme);
|
|
762
|
+
if (callComponent) this.#contentBox.addChild(callComponent);
|
|
763
|
+
} catch (err) {
|
|
764
|
+
logger.warn("Tool renderer failed", { tool: this.#toolName, error: String(err) });
|
|
765
|
+
// Fall back to default on error
|
|
766
|
+
this.#contentBox.addChild(new Text(theme.fg("toolTitle", theme.bold(this.#toolLabel)), 0, 0));
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
// Render result component if we have a result
|
|
771
|
+
if (this.#result) {
|
|
772
|
+
try {
|
|
773
|
+
const resultComponent = renderer.renderResult(
|
|
774
|
+
{
|
|
775
|
+
content: this.#result.content as any,
|
|
776
|
+
details: this.#result.details,
|
|
777
|
+
isError: this.#result.isError,
|
|
778
|
+
},
|
|
779
|
+
this.#renderState,
|
|
780
|
+
theme,
|
|
781
|
+
this.#getCallArgsForRender(),
|
|
782
|
+
);
|
|
783
|
+
if (resultComponent) this.#contentBox.addChild(resultComponent);
|
|
784
|
+
} catch (err) {
|
|
785
|
+
logger.warn("Tool renderer failed", { tool: this.#toolName, error: String(err) });
|
|
786
|
+
// Fall back to showing raw output on error
|
|
787
|
+
const output = this.#getTextOutput();
|
|
788
|
+
if (output) {
|
|
789
|
+
this.#contentBox.addChild(new Text(theme.fg("toolOutput", replaceTabs(output)), 0, 0));
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
} else {
|
|
795
|
+
// Other built-in tools: use Text directly with caching
|
|
796
|
+
this.#contentText.setCustomBgFn(stateBgFn);
|
|
797
|
+
this.#contentText.setText(this.#formatToolExecution());
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
// Handle images (same for both custom and built-in)
|
|
801
|
+
for (const img of this.#imageComponents) {
|
|
802
|
+
this.removeChild(img);
|
|
803
|
+
}
|
|
804
|
+
this.#imageComponents = [];
|
|
805
|
+
for (const spacer of this.#imageSpacers) {
|
|
806
|
+
this.removeChild(spacer);
|
|
807
|
+
}
|
|
808
|
+
this.#imageSpacers = [];
|
|
809
|
+
|
|
810
|
+
if (this.#result) {
|
|
811
|
+
const imageBlocks = this.#getAllImageBlocks();
|
|
812
|
+
|
|
813
|
+
for (let i = 0; i < imageBlocks.length; i++) {
|
|
814
|
+
const img = imageBlocks[i];
|
|
815
|
+
if (TERMINAL.imageProtocol && this.#showImages && img.data && img.mimeType) {
|
|
816
|
+
// Use converted PNG for Kitty protocol if available
|
|
817
|
+
const converted = this.#convertedImages.get(i);
|
|
818
|
+
const imageData = converted?.data ?? img.data;
|
|
819
|
+
const imageMimeType = converted?.mimeType ?? img.mimeType;
|
|
820
|
+
|
|
821
|
+
// For Kitty, skip non-PNG images that haven't been converted yet
|
|
822
|
+
if (TERMINAL.imageProtocol === ImageProtocol.Kitty && imageMimeType !== "image/png") {
|
|
823
|
+
continue;
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
const spacer = new Spacer(1);
|
|
827
|
+
this.addChild(spacer);
|
|
828
|
+
this.#imageSpacers.push(spacer);
|
|
829
|
+
const imageComponent = new Image(
|
|
830
|
+
imageData,
|
|
831
|
+
imageMimeType,
|
|
832
|
+
{ fallbackColor: (s: string) => theme.fg("toolOutput", s) },
|
|
833
|
+
{ ...resolveImageOptions(), budget: this.#ui.imageBudget, imageKey: `te${this.#instanceId}:${i}` },
|
|
834
|
+
);
|
|
835
|
+
this.#imageComponents.push(imageComponent);
|
|
836
|
+
this.addChild(imageComponent);
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
#getCallArgsForRender(): any {
|
|
843
|
+
const renderArgs = getArgsWithStreamedTextInput(this.#args);
|
|
844
|
+
if (!isEditLikeToolName(this.#toolName)) {
|
|
845
|
+
return renderArgs;
|
|
846
|
+
}
|
|
847
|
+
const previews = this.#editDiffPreview;
|
|
848
|
+
if (!previews || previews.length === 0) {
|
|
849
|
+
return renderArgs;
|
|
850
|
+
}
|
|
851
|
+
// Single-file previews feed the existing `previewDiff` channel consumed
|
|
852
|
+
// by `formatStreamingDiff` in the renderer.
|
|
853
|
+
const first = previews[0];
|
|
854
|
+
if (!first?.diff) {
|
|
855
|
+
return renderArgs;
|
|
856
|
+
}
|
|
857
|
+
return { ...(renderArgs as Record<string, unknown>), previewDiff: first.diff };
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
/**
|
|
861
|
+
* Build render context for tools that need extra state (bash, python, edit)
|
|
862
|
+
*/
|
|
863
|
+
#buildRenderContext(): Record<string, unknown> {
|
|
864
|
+
const context: Record<string, unknown> = {};
|
|
865
|
+
const normalizeTimeoutSeconds = (value: unknown, maxSeconds: number): number | undefined => {
|
|
866
|
+
if (typeof value !== "number" || !Number.isFinite(value)) return undefined;
|
|
867
|
+
return Math.max(1, Math.min(maxSeconds, value));
|
|
868
|
+
};
|
|
869
|
+
|
|
870
|
+
if (this.#toolName === "bash") {
|
|
871
|
+
// Bash needs render context even before a result exists. The renderer uses the pending-call args
|
|
872
|
+
// plus this context to keep the inline command preview visible while tool-call JSON is still streaming.
|
|
873
|
+
if (this.#result) {
|
|
874
|
+
// Pass raw output and expanded state - renderer handles width-aware truncation
|
|
875
|
+
const output = this.#getTextOutput().trimEnd();
|
|
876
|
+
context.output = output;
|
|
877
|
+
}
|
|
878
|
+
context.expanded = this.#expanded;
|
|
879
|
+
context.previewLines = BASH_DEFAULT_PREVIEW_LINES;
|
|
880
|
+
context.timeout = normalizeTimeoutSeconds(this.#args?.timeout, 3600);
|
|
881
|
+
} else if (this.#toolName === "eval" && this.#result) {
|
|
882
|
+
const output = this.#getTextOutput().trimEnd();
|
|
883
|
+
context.output = output;
|
|
884
|
+
context.expanded = this.#expanded;
|
|
885
|
+
context.previewLines = EVAL_DEFAULT_PREVIEW_LINES;
|
|
886
|
+
} else if (this.#toolName === "task") {
|
|
887
|
+
// Once a result snapshot exists the task renderer's `renderResult`
|
|
888
|
+
// draws every dispatched agent as a progress/result line, so tell
|
|
889
|
+
// `renderCall` to drop its duplicate streaming preview list.
|
|
890
|
+
context.hasResult = Boolean(this.#result);
|
|
891
|
+
} else if (isEditLikeToolName(this.#toolName)) {
|
|
892
|
+
context.editMode = this.#editMode;
|
|
893
|
+
const previews = this.#editDiffPreview;
|
|
894
|
+
if (previews && previews.length > 0) {
|
|
895
|
+
const first = previews[0];
|
|
896
|
+
if (first?.diff || first?.error) {
|
|
897
|
+
context.editDiffPreview = first.error
|
|
898
|
+
? { error: first.error }
|
|
899
|
+
: { diff: first.diff ?? "", firstChangedLine: first.firstChangedLine };
|
|
900
|
+
}
|
|
901
|
+
if (previews.length > 1) {
|
|
902
|
+
context.perFileDiffPreview = previews;
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
if (!previews?.some(preview => preview.diff)) {
|
|
906
|
+
const editMode = this.#editMode;
|
|
907
|
+
const strategy = editMode ? EDIT_MODE_STRATEGIES[editMode] : undefined;
|
|
908
|
+
const fallback = strategy?.renderStreamingFallback(getArgsWithStreamedTextInput(this.#args), theme);
|
|
909
|
+
if (fallback) context.editStreamingFallback = fallback;
|
|
910
|
+
}
|
|
911
|
+
context.renderDiff = renderDiff;
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
return context;
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
#getTextOutput(): string {
|
|
918
|
+
if (!this.#result) return "";
|
|
919
|
+
|
|
920
|
+
const textBlocks = this.#result.content?.filter((c: any) => c.type === "text") || [];
|
|
921
|
+
const imageBlocks = this.#getAllImageBlocks();
|
|
922
|
+
|
|
923
|
+
let output = textBlocks
|
|
924
|
+
.map((c: any) => {
|
|
925
|
+
return sanitizeWithOptionalSixelPassthrough(c.text || "", sanitizeText);
|
|
926
|
+
})
|
|
927
|
+
.join("\n");
|
|
928
|
+
|
|
929
|
+
if (imageBlocks.length > 0 && (!TERMINAL.imageProtocol || !this.#showImages)) {
|
|
930
|
+
const imageIndicators = imageBlocks
|
|
931
|
+
.map((img: any) => {
|
|
932
|
+
const dims = img.data ? (getImageDimensions(img.data, img.mimeType) ?? undefined) : undefined;
|
|
933
|
+
return imageFallback(img.mimeType, dims);
|
|
934
|
+
})
|
|
935
|
+
.join("\n");
|
|
936
|
+
output = output ? `${output}\n${imageIndicators}` : imageIndicators;
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
return output;
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
/**
|
|
943
|
+
* Format a generic tool execution (fallback for tools without custom renderers)
|
|
944
|
+
*/
|
|
945
|
+
#formatToolExecution(): string {
|
|
946
|
+
const lines: string[] = [];
|
|
947
|
+
const icon = this.#isPartial ? "pending" : this.#result?.isError ? "error" : "done";
|
|
948
|
+
lines.push(renderStatusLine({ icon, title: this.#toolLabel }, theme));
|
|
949
|
+
|
|
950
|
+
const argsObject = this.#args && typeof this.#args === "object" ? (this.#args as Record<string, unknown>) : null;
|
|
951
|
+
if (!this.#expanded && argsObject && Object.keys(argsObject).length > 0) {
|
|
952
|
+
const preview = formatArgsInline(argsObject, 70);
|
|
953
|
+
if (preview) {
|
|
954
|
+
lines.push(` ${theme.fg("dim", theme.tree.last)} ${theme.fg("dim", preview)}`);
|
|
955
|
+
}
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
if (this.#expanded && this.#args !== undefined) {
|
|
959
|
+
lines.push("");
|
|
960
|
+
lines.push(theme.fg("dim", "Args"));
|
|
961
|
+
const tree = renderJsonTreeLines(
|
|
962
|
+
this.#args,
|
|
963
|
+
theme,
|
|
964
|
+
JSON_TREE_MAX_DEPTH_EXPANDED,
|
|
965
|
+
JSON_TREE_MAX_LINES_EXPANDED,
|
|
966
|
+
JSON_TREE_SCALAR_LEN_EXPANDED,
|
|
967
|
+
);
|
|
968
|
+
lines.push(...tree.lines);
|
|
969
|
+
if (tree.truncated) {
|
|
970
|
+
lines.push(theme.fg("dim", "…"));
|
|
971
|
+
}
|
|
972
|
+
lines.push("");
|
|
973
|
+
}
|
|
974
|
+
|
|
975
|
+
if (!this.#result) {
|
|
976
|
+
return lines.join("\n");
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
const textContent = this.#getTextOutput().trimEnd();
|
|
980
|
+
if (!textContent) {
|
|
981
|
+
lines.push(theme.fg("dim", "(no output)"));
|
|
982
|
+
return lines.join("\n");
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
if (textContent.startsWith("{") || textContent.startsWith("[")) {
|
|
986
|
+
try {
|
|
987
|
+
const parsed = JSON.parse(textContent);
|
|
988
|
+
const maxDepth = this.#expanded ? JSON_TREE_MAX_DEPTH_EXPANDED : JSON_TREE_MAX_DEPTH_COLLAPSED;
|
|
989
|
+
const maxLines = this.#expanded ? JSON_TREE_MAX_LINES_EXPANDED : JSON_TREE_MAX_LINES_COLLAPSED;
|
|
990
|
+
const maxScalarLen = this.#expanded ? JSON_TREE_SCALAR_LEN_EXPANDED : JSON_TREE_SCALAR_LEN_COLLAPSED;
|
|
991
|
+
const tree = renderJsonTreeLines(parsed, theme, maxDepth, maxLines, maxScalarLen);
|
|
992
|
+
|
|
993
|
+
if (tree.lines.length > 0) {
|
|
994
|
+
lines.push(...tree.lines);
|
|
995
|
+
if (!this.#expanded) {
|
|
996
|
+
lines.push(formatExpandHint(theme, this.#expanded, true));
|
|
997
|
+
} else if (tree.truncated) {
|
|
998
|
+
lines.push(theme.fg("dim", "…"));
|
|
999
|
+
}
|
|
1000
|
+
return lines.join("\n");
|
|
1001
|
+
}
|
|
1002
|
+
} catch {
|
|
1003
|
+
// Fall through to raw output
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
|
|
1007
|
+
const outputLines = textContent.split("\n");
|
|
1008
|
+
const maxOutputLines = this.#expanded ? 12 : 4;
|
|
1009
|
+
const displayLines = outputLines.slice(0, maxOutputLines);
|
|
1010
|
+
|
|
1011
|
+
for (const line of displayLines) {
|
|
1012
|
+
lines.push(theme.fg("toolOutput", truncateToWidth(replaceTabs(line), 80)));
|
|
1013
|
+
}
|
|
1014
|
+
|
|
1015
|
+
if (outputLines.length > maxOutputLines) {
|
|
1016
|
+
const remaining = outputLines.length - maxOutputLines;
|
|
1017
|
+
lines.push(`${theme.fg("dim", `… ${remaining} more lines`)} ${formatExpandHint(theme, this.#expanded, true)}`);
|
|
1018
|
+
} else if (!this.#expanded) {
|
|
1019
|
+
lines.push(formatExpandHint(theme, this.#expanded, true));
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
return lines.join("\n");
|
|
1023
|
+
}
|
|
1024
|
+
}
|