@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,1798 @@
|
|
|
1
|
+
import * as fs from "node:fs/promises";
|
|
2
|
+
import * as os from "node:os";
|
|
3
|
+
import * as path from "node:path";
|
|
4
|
+
import { getOAuthProviders } from "@oh-my-pi/pi-ai/oauth";
|
|
5
|
+
import { Snowflake, setProjectDir } from "@oh-my-pi/pi-utils";
|
|
6
|
+
import { $ } from "bun";
|
|
7
|
+
import type { SettingPath, SettingValue } from "../config/settings";
|
|
8
|
+
import { settings } from "../config/settings";
|
|
9
|
+
import {
|
|
10
|
+
clearPluginRootsAndCaches,
|
|
11
|
+
resolveActiveProjectRegistryPath,
|
|
12
|
+
resolveOrDefaultProjectRegistryPath,
|
|
13
|
+
} from "../discovery/helpers.js";
|
|
14
|
+
import { PluginManager } from "../extensibility/plugins";
|
|
15
|
+
import {
|
|
16
|
+
getInstalledPluginsRegistryPath,
|
|
17
|
+
getMarketplacesCacheDir,
|
|
18
|
+
getMarketplacesRegistryPath,
|
|
19
|
+
getPluginsCacheDir,
|
|
20
|
+
MarketplaceManager,
|
|
21
|
+
} from "../extensibility/plugins/marketplace";
|
|
22
|
+
import { resolveMemoryBackend } from "../memory-backend";
|
|
23
|
+
import type { InteractiveModeContext } from "../modes/types";
|
|
24
|
+
import type { FreshSessionResult } from "../session/agent-session";
|
|
25
|
+
import { formatShakeSummary, type ShakeMode } from "../session/shake-types";
|
|
26
|
+
import { getChangelogPath, parseChangelog } from "../utils/changelog";
|
|
27
|
+
import { buildContextReportText } from "./helpers/context-report";
|
|
28
|
+
import { formatDuration } from "./helpers/format";
|
|
29
|
+
import { createMarketplaceManager } from "./helpers/marketplace-manager";
|
|
30
|
+
import { handleMcpAcp } from "./helpers/mcp";
|
|
31
|
+
import { commandConsumed, errorMessage, parseSlashCommand, parseSubcommand, usage } from "./helpers/parse";
|
|
32
|
+
import { handleSshAcp } from "./helpers/ssh";
|
|
33
|
+
import { launchStatsDashboard, parseStatsDashboardArgs } from "./helpers/stats-dashboard";
|
|
34
|
+
import { handleTodoAcp } from "./helpers/todo";
|
|
35
|
+
import { buildUsageReportText } from "./helpers/usage-report";
|
|
36
|
+
import { parseMarketplaceInstallArgs, parsePluginScopeArgs } from "./marketplace-install-parser";
|
|
37
|
+
import type {
|
|
38
|
+
BuiltinSlashCommand,
|
|
39
|
+
ParsedSlashCommand,
|
|
40
|
+
SlashCommandResult,
|
|
41
|
+
SlashCommandRuntime,
|
|
42
|
+
SlashCommandSpec,
|
|
43
|
+
TuiSlashCommandRuntime,
|
|
44
|
+
} from "./types";
|
|
45
|
+
|
|
46
|
+
export type { BuiltinSlashCommand, SubcommandDef } from "./types";
|
|
47
|
+
|
|
48
|
+
/** TUI-specific runtime accepted by `executeBuiltinSlashCommand`. */
|
|
49
|
+
export type BuiltinSlashCommandRuntime = TuiSlashCommandRuntime;
|
|
50
|
+
|
|
51
|
+
function refreshStatusLine(ctx: InteractiveModeContext): void {
|
|
52
|
+
ctx.statusLine.invalidate();
|
|
53
|
+
ctx.updateEditorTopBorder();
|
|
54
|
+
ctx.ui.requestRender();
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function formatFreshSessionResult(result: FreshSessionResult): string {
|
|
58
|
+
const stateLabel = result.closedProviderSessions === 1 ? "provider state" : "provider states";
|
|
59
|
+
return `Fresh provider session started (${result.closedProviderSessions} ${stateLabel} pruned).`;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const shutdownHandlerTui = (_command: ParsedSlashCommand, runtime: TuiSlashCommandRuntime): SlashCommandResult => {
|
|
63
|
+
runtime.ctx.editor.setText("");
|
|
64
|
+
void runtime.ctx.shutdown();
|
|
65
|
+
return commandConsumed();
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
/** Parse the `/shake` subcommand into a {@link ShakeMode}; empty defaults to elide. */
|
|
69
|
+
function parseShakeMode(args: string): ShakeMode | { error: string } {
|
|
70
|
+
const verb = args.trim().toLowerCase();
|
|
71
|
+
if (verb === "" || verb === "elide") return "elide";
|
|
72
|
+
if (verb === "images") return "images";
|
|
73
|
+
return { error: `Unknown /shake mode "${verb}". Use elide or images.` };
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const BUILTIN_SLASH_COMMAND_REGISTRY: ReadonlyArray<SlashCommandSpec> = [
|
|
77
|
+
{
|
|
78
|
+
name: "settings",
|
|
79
|
+
description: "Open settings menu",
|
|
80
|
+
handleTui: (_command, runtime) => {
|
|
81
|
+
runtime.ctx.showSettingsSelector();
|
|
82
|
+
runtime.ctx.editor.setText("");
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
name: "setup",
|
|
87
|
+
aliases: ["providers"],
|
|
88
|
+
description: "Open provider setup",
|
|
89
|
+
allowArgs: true,
|
|
90
|
+
subcommands: [{ name: "providers", description: "Configure sign-in and web search providers" }],
|
|
91
|
+
handleTui: async (command, runtime) => {
|
|
92
|
+
const args = command.args.trim().toLowerCase();
|
|
93
|
+
const opensProviders = args === "" || args === "providers";
|
|
94
|
+
if (opensProviders) {
|
|
95
|
+
await runtime.ctx.showProviderSetup();
|
|
96
|
+
} else {
|
|
97
|
+
runtime.ctx.showWarning(`Usage: /${command.name} [providers]`);
|
|
98
|
+
}
|
|
99
|
+
runtime.ctx.editor.setText("");
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
name: "plan",
|
|
104
|
+
description: "Toggle plan mode (agent plans before executing)",
|
|
105
|
+
inlineHint: "[prompt]",
|
|
106
|
+
allowArgs: true,
|
|
107
|
+
handleTui: async (command, runtime) => {
|
|
108
|
+
const hadArgs = !!command.args;
|
|
109
|
+
// Capture state BEFORE the call: when plan mode is already active,
|
|
110
|
+
// handlePlanModeCommand may exit it (on confirmed exit) or leave it on (on cancel
|
|
111
|
+
// or warning). In every "already active" case the typed args are NOT consumed,
|
|
112
|
+
// so preserve them in history regardless of the user's confirm/cancel choice.
|
|
113
|
+
const wasPlanModeEnabled = runtime.ctx.planModeEnabled;
|
|
114
|
+
await runtime.ctx.handlePlanModeCommand(command.args || undefined);
|
|
115
|
+
if (hadArgs && wasPlanModeEnabled) {
|
|
116
|
+
runtime.ctx.editor.addToHistory(command.text);
|
|
117
|
+
}
|
|
118
|
+
runtime.ctx.editor.setText("");
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
name: "plan-review",
|
|
123
|
+
description: "Re-open the plan review for the latest plan (plan mode only)",
|
|
124
|
+
handleTui: async (_command, runtime) => {
|
|
125
|
+
await runtime.ctx.openPlanReview();
|
|
126
|
+
runtime.ctx.editor.setText("");
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
name: "goal",
|
|
131
|
+
description: "Toggle goal mode (persistent autonomous objective for this session)",
|
|
132
|
+
subcommands: [
|
|
133
|
+
{ name: "set", description: "Set or replace the goal", usage: "<objective>" },
|
|
134
|
+
{ name: "show", description: "Show current goal details" },
|
|
135
|
+
{ name: "pause", description: "Pause the current goal" },
|
|
136
|
+
{ name: "resume", description: "Resume a paused goal" },
|
|
137
|
+
{ name: "drop", description: "Drop the current goal" },
|
|
138
|
+
{ name: "budget", description: "Adjust the token budget", usage: "<N|off>" },
|
|
139
|
+
],
|
|
140
|
+
inlineHint: "[objective]",
|
|
141
|
+
allowArgs: true,
|
|
142
|
+
handleTui: async (command, runtime) => {
|
|
143
|
+
const hadArgs = !!command.args;
|
|
144
|
+
// Capture state BEFORE the call (see /plan above for rationale).
|
|
145
|
+
const wasGoalModeEnabled = runtime.ctx.goalModeEnabled;
|
|
146
|
+
await runtime.ctx.handleGoalModeCommand(command.args || undefined);
|
|
147
|
+
if (hadArgs && wasGoalModeEnabled) {
|
|
148
|
+
runtime.ctx.editor.addToHistory(command.text);
|
|
149
|
+
}
|
|
150
|
+
runtime.ctx.editor.setText("");
|
|
151
|
+
},
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
name: "loop",
|
|
155
|
+
description:
|
|
156
|
+
"Toggle loop mode. While enabled, the next prompt you send re-submits after every yield. Esc cancels the current iteration; /loop again to disable.",
|
|
157
|
+
inlineHint: "[count|duration]",
|
|
158
|
+
allowArgs: true,
|
|
159
|
+
handleTui: async (command, runtime) => {
|
|
160
|
+
await runtime.ctx.handleLoopCommand(command.args);
|
|
161
|
+
runtime.ctx.editor.setText("");
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
name: "model",
|
|
166
|
+
aliases: ["models"],
|
|
167
|
+
description: "Select model (opens selector UI)",
|
|
168
|
+
acpDescription: "Show current model selection",
|
|
169
|
+
handle: async (command, runtime) => {
|
|
170
|
+
if (command.args) {
|
|
171
|
+
const modelId = command.args.trim();
|
|
172
|
+
const availableModels = runtime.session.getAvailableModels?.() ?? [];
|
|
173
|
+
const match = availableModels.find(
|
|
174
|
+
model => model.id === modelId || `${model.provider}/${model.id}` === modelId,
|
|
175
|
+
);
|
|
176
|
+
if (!match) {
|
|
177
|
+
return usage(
|
|
178
|
+
`Unknown model: ${modelId}. Use ACP \`session/setModel\` for picker-driven selection or list available models with /model.`,
|
|
179
|
+
runtime,
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
try {
|
|
183
|
+
await runtime.session.setModel(match);
|
|
184
|
+
await runtime.output(`Model set to ${match.provider}/${match.id}.`);
|
|
185
|
+
await runtime.notifyTitleChanged?.();
|
|
186
|
+
await runtime.notifyConfigChanged?.();
|
|
187
|
+
return commandConsumed();
|
|
188
|
+
} catch (err) {
|
|
189
|
+
return usage(`Failed to set model: ${errorMessage(err)}`, runtime);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const model = runtime.session.model;
|
|
194
|
+
await runtime.output(
|
|
195
|
+
model ? `Current model: ${model.provider}/${model.id}` : "No model is currently selected.",
|
|
196
|
+
);
|
|
197
|
+
return commandConsumed();
|
|
198
|
+
},
|
|
199
|
+
handleTui: (_command, runtime) => {
|
|
200
|
+
runtime.ctx.showModelSelector();
|
|
201
|
+
runtime.ctx.editor.setText("");
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
name: "switch",
|
|
206
|
+
description: "Switch model for this session (same as alt+p)",
|
|
207
|
+
handleTui: (_command, runtime) => {
|
|
208
|
+
runtime.ctx.showModelSelector({ temporaryOnly: true });
|
|
209
|
+
runtime.ctx.editor.setText("");
|
|
210
|
+
},
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
name: "fast",
|
|
214
|
+
description: "Toggle priority service tier (OpenAI service_tier=priority, Anthropic speed=fast)",
|
|
215
|
+
acpDescription: "Toggle fast mode",
|
|
216
|
+
acpInputHint: "[on|off|status]",
|
|
217
|
+
subcommands: [
|
|
218
|
+
{ name: "on", description: "Enable fast mode" },
|
|
219
|
+
{ name: "off", description: "Disable fast mode" },
|
|
220
|
+
{ name: "status", description: "Show fast mode status" },
|
|
221
|
+
],
|
|
222
|
+
allowArgs: true,
|
|
223
|
+
handle: async (command, runtime) => {
|
|
224
|
+
const arg = command.args.toLowerCase();
|
|
225
|
+
if (!arg || arg === "toggle") {
|
|
226
|
+
const enabled = runtime.session.toggleFastMode();
|
|
227
|
+
await runtime.output(`Fast mode ${enabled ? "enabled" : "disabled"}.`);
|
|
228
|
+
return commandConsumed();
|
|
229
|
+
}
|
|
230
|
+
if (arg === "on") {
|
|
231
|
+
runtime.session.setFastMode(true);
|
|
232
|
+
await runtime.output("Fast mode enabled.");
|
|
233
|
+
return commandConsumed();
|
|
234
|
+
}
|
|
235
|
+
if (arg === "off") {
|
|
236
|
+
runtime.session.setFastMode(false);
|
|
237
|
+
await runtime.output("Fast mode disabled.");
|
|
238
|
+
return commandConsumed();
|
|
239
|
+
}
|
|
240
|
+
if (arg === "status") {
|
|
241
|
+
await runtime.output(`Fast mode is ${runtime.session.isFastModeEnabled() ? "on" : "off"}.`);
|
|
242
|
+
return commandConsumed();
|
|
243
|
+
}
|
|
244
|
+
return usage("Usage: /fast [on|off|status]", runtime);
|
|
245
|
+
},
|
|
246
|
+
handleTui: (command, runtime) => {
|
|
247
|
+
const arg = command.args.trim().toLowerCase();
|
|
248
|
+
if (!arg || arg === "toggle") {
|
|
249
|
+
const enabled = runtime.ctx.session.toggleFastMode();
|
|
250
|
+
refreshStatusLine(runtime.ctx);
|
|
251
|
+
runtime.ctx.showStatus(`Fast mode ${enabled ? "enabled" : "disabled"}.`);
|
|
252
|
+
runtime.ctx.editor.setText("");
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
if (arg === "on") {
|
|
256
|
+
runtime.ctx.session.setFastMode(true);
|
|
257
|
+
refreshStatusLine(runtime.ctx);
|
|
258
|
+
runtime.ctx.showStatus("Fast mode enabled.");
|
|
259
|
+
runtime.ctx.editor.setText("");
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
if (arg === "off") {
|
|
263
|
+
runtime.ctx.session.setFastMode(false);
|
|
264
|
+
refreshStatusLine(runtime.ctx);
|
|
265
|
+
runtime.ctx.showStatus("Fast mode disabled.");
|
|
266
|
+
runtime.ctx.editor.setText("");
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
if (arg === "status") {
|
|
270
|
+
const enabled = runtime.ctx.session.isFastModeEnabled();
|
|
271
|
+
runtime.ctx.showStatus(`Fast mode is ${enabled ? "on" : "off"}.`);
|
|
272
|
+
runtime.ctx.editor.setText("");
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
runtime.ctx.showStatus("Usage: /fast [on|off|status]");
|
|
276
|
+
runtime.ctx.editor.setText("");
|
|
277
|
+
},
|
|
278
|
+
},
|
|
279
|
+
{
|
|
280
|
+
name: "export",
|
|
281
|
+
description: "Export session to HTML file",
|
|
282
|
+
inlineHint: "[path]",
|
|
283
|
+
allowArgs: true,
|
|
284
|
+
handle: async (command, runtime) => {
|
|
285
|
+
const arg = command.args.trim();
|
|
286
|
+
// Match the interactive `/export` behavior: clipboard aliases are not a
|
|
287
|
+
// valid export target. Without this, the literal value (`copy`,
|
|
288
|
+
// `--copy`, `clipboard`) is passed to `exportToHtml` and becomes the
|
|
289
|
+
// output filename.
|
|
290
|
+
if (arg === "--copy" || arg === "clipboard" || arg === "copy") {
|
|
291
|
+
return usage("Use /dump to copy the session to clipboard.", runtime);
|
|
292
|
+
}
|
|
293
|
+
try {
|
|
294
|
+
const filePath = await runtime.session.exportToHtml(arg || undefined);
|
|
295
|
+
await runtime.output(`Session exported to: ${filePath}`);
|
|
296
|
+
return commandConsumed();
|
|
297
|
+
} catch (err) {
|
|
298
|
+
return usage(`Failed to export session: ${errorMessage(err)}`, runtime);
|
|
299
|
+
}
|
|
300
|
+
},
|
|
301
|
+
handleTui: async (command, runtime) => {
|
|
302
|
+
await runtime.ctx.handleExportCommand(command.text);
|
|
303
|
+
runtime.ctx.editor.setText("");
|
|
304
|
+
},
|
|
305
|
+
},
|
|
306
|
+
{
|
|
307
|
+
name: "dump",
|
|
308
|
+
description: "Copy session transcript to clipboard",
|
|
309
|
+
acpDescription: "Return full transcript as plain text",
|
|
310
|
+
handle: async (_command, runtime) => {
|
|
311
|
+
const text = runtime.session.formatSessionAsText();
|
|
312
|
+
await runtime.output(text || "No messages to dump yet.");
|
|
313
|
+
return commandConsumed();
|
|
314
|
+
},
|
|
315
|
+
handleTui: async (_command, runtime) => {
|
|
316
|
+
await runtime.ctx.handleDumpCommand();
|
|
317
|
+
runtime.ctx.editor.setText("");
|
|
318
|
+
},
|
|
319
|
+
},
|
|
320
|
+
{
|
|
321
|
+
name: "share",
|
|
322
|
+
description: "Share session as a secret GitHub gist",
|
|
323
|
+
handle: async (_command, runtime) => {
|
|
324
|
+
const tmpFile = path.join(os.tmpdir(), `${Snowflake.next()}.html`);
|
|
325
|
+
try {
|
|
326
|
+
try {
|
|
327
|
+
await runtime.session.exportToHtml(tmpFile);
|
|
328
|
+
} catch (err) {
|
|
329
|
+
return usage(`Failed to export session: ${errorMessage(err)}`, runtime);
|
|
330
|
+
}
|
|
331
|
+
const result = await $`gh gist create --public=false ${tmpFile}`.quiet().nothrow();
|
|
332
|
+
if (result.exitCode !== 0) {
|
|
333
|
+
return usage(
|
|
334
|
+
`Failed to create gist: ${result.stderr.toString("utf-8").trim() || "unknown error"}`,
|
|
335
|
+
runtime,
|
|
336
|
+
);
|
|
337
|
+
}
|
|
338
|
+
const gistUrl = result.stdout.toString("utf-8").trim();
|
|
339
|
+
const gistId = gistUrl.split("/").pop();
|
|
340
|
+
if (!gistId) return usage("Failed to parse gist ID from gh output", runtime);
|
|
341
|
+
await runtime.output(`Share URL: https://gistpreview.github.io/?${gistId}\nGist: ${gistUrl}`);
|
|
342
|
+
return commandConsumed();
|
|
343
|
+
} catch {
|
|
344
|
+
return usage("GitHub CLI (gh) is required for /share. Install it from https://cli.github.com/.", runtime);
|
|
345
|
+
} finally {
|
|
346
|
+
await fs.rm(tmpFile, { force: true }).catch(() => {});
|
|
347
|
+
}
|
|
348
|
+
},
|
|
349
|
+
handleTui: async (_command, runtime) => {
|
|
350
|
+
await runtime.ctx.handleShareCommand();
|
|
351
|
+
runtime.ctx.editor.setText("");
|
|
352
|
+
},
|
|
353
|
+
},
|
|
354
|
+
{
|
|
355
|
+
name: "browser",
|
|
356
|
+
description: "Toggle browser headless vs visible mode",
|
|
357
|
+
acpInputHint: "[headless|visible]",
|
|
358
|
+
subcommands: [
|
|
359
|
+
{ name: "headless", description: "Switch to headless mode" },
|
|
360
|
+
{ name: "visible", description: "Switch to visible mode" },
|
|
361
|
+
],
|
|
362
|
+
allowArgs: true,
|
|
363
|
+
handle: async (command, runtime) => {
|
|
364
|
+
const arg = command.args.toLowerCase();
|
|
365
|
+
const enabled = runtime.settings.get("browser.enabled" as SettingPath) as boolean;
|
|
366
|
+
if (!enabled) return usage("Browser tool is disabled (enable in settings).", runtime);
|
|
367
|
+
const current = runtime.settings.get("browser.headless" as SettingPath) as boolean;
|
|
368
|
+
let next = current;
|
|
369
|
+
if (!arg) next = !current;
|
|
370
|
+
else if (arg === "headless" || arg === "hidden") next = true;
|
|
371
|
+
else if (arg === "visible" || arg === "show" || arg === "headful") next = false;
|
|
372
|
+
else return usage("Usage: /browser [headless|visible]", runtime);
|
|
373
|
+
runtime.settings.set("browser.headless" as SettingPath, next as SettingValue<SettingPath>);
|
|
374
|
+
const tool = runtime.session.getToolByName("browser");
|
|
375
|
+
if (tool && "restartForModeChange" in tool) {
|
|
376
|
+
try {
|
|
377
|
+
await (tool as { restartForModeChange: () => Promise<void> }).restartForModeChange();
|
|
378
|
+
} catch (err) {
|
|
379
|
+
// Setting was already mutated; surface the restart failure so the
|
|
380
|
+
// user knows the browser is in an inconsistent state.
|
|
381
|
+
await runtime.output(
|
|
382
|
+
`Browser mode set to ${next ? "headless" : "visible"}, but restart failed: ${errorMessage(err)}`,
|
|
383
|
+
);
|
|
384
|
+
return commandConsumed();
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
await runtime.output(`Browser mode: ${next ? "headless" : "visible"}`);
|
|
388
|
+
return commandConsumed();
|
|
389
|
+
},
|
|
390
|
+
handleTui: async (command, runtime) => {
|
|
391
|
+
const arg = command.args.toLowerCase();
|
|
392
|
+
const current = settings.get("browser.headless" as SettingPath) as boolean;
|
|
393
|
+
let next = current;
|
|
394
|
+
if (!(settings.get("browser.enabled" as SettingPath) as boolean)) {
|
|
395
|
+
runtime.ctx.showWarning("Browser tool is disabled (enable in settings)");
|
|
396
|
+
runtime.ctx.editor.setText("");
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
if (!arg) {
|
|
400
|
+
next = !current;
|
|
401
|
+
} else if (arg === "headless" || arg === "hidden") {
|
|
402
|
+
next = true;
|
|
403
|
+
} else if (arg === "visible" || arg === "show" || arg === "headful") {
|
|
404
|
+
next = false;
|
|
405
|
+
} else {
|
|
406
|
+
runtime.ctx.showStatus("Usage: /browser [headless|visible]");
|
|
407
|
+
runtime.ctx.editor.setText("");
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
410
|
+
settings.set("browser.headless" as SettingPath, next as SettingValue<SettingPath>);
|
|
411
|
+
const tool = runtime.ctx.session.getToolByName("browser");
|
|
412
|
+
if (tool && "restartForModeChange" in tool) {
|
|
413
|
+
try {
|
|
414
|
+
await (tool as { restartForModeChange: () => Promise<void> }).restartForModeChange();
|
|
415
|
+
} catch (error) {
|
|
416
|
+
runtime.ctx.showWarning(`Failed to restart browser: ${errorMessage(error)}`);
|
|
417
|
+
runtime.ctx.editor.setText("");
|
|
418
|
+
return;
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
runtime.ctx.showStatus(`Browser mode: ${next ? "headless" : "visible"}`);
|
|
422
|
+
runtime.ctx.editor.setText("");
|
|
423
|
+
},
|
|
424
|
+
},
|
|
425
|
+
{
|
|
426
|
+
name: "copy",
|
|
427
|
+
description: "Pick text or code from the conversation to copy",
|
|
428
|
+
handleTui: (_command, runtime) => {
|
|
429
|
+
runtime.ctx.showCopySelector();
|
|
430
|
+
runtime.ctx.editor.setText("");
|
|
431
|
+
},
|
|
432
|
+
},
|
|
433
|
+
{
|
|
434
|
+
name: "todo",
|
|
435
|
+
description: "View or modify the agent's todo list",
|
|
436
|
+
acpDescription: "Manage todos",
|
|
437
|
+
acpInputHint: "<subcommand>",
|
|
438
|
+
subcommands: [
|
|
439
|
+
{ name: "edit", description: "Open todos in $EDITOR (Markdown round-trip)" },
|
|
440
|
+
{ name: "copy", description: "Copy todos as Markdown to clipboard" },
|
|
441
|
+
{ name: "export", description: "Write todos as Markdown to a file (default: TODO.md)", usage: "[<path>]" },
|
|
442
|
+
{ name: "import", description: "Replace todos from a Markdown file (default: TODO.md)", usage: "[<path>]" },
|
|
443
|
+
{
|
|
444
|
+
name: "append",
|
|
445
|
+
description: "Append a task; phase fuzzy-matched or auto-created",
|
|
446
|
+
usage: "[<phase>] <task...>",
|
|
447
|
+
},
|
|
448
|
+
{ name: "start", description: "Mark task in_progress (fuzzy-matched)", usage: "<task>" },
|
|
449
|
+
{ name: "done", description: "Mark task/phase/all completed (fuzzy-matched)", usage: "[<task|phase>]" },
|
|
450
|
+
{ name: "drop", description: "Mark task/phase/all abandoned (fuzzy-matched)", usage: "[<task|phase>]" },
|
|
451
|
+
{ name: "rm", description: "Remove task/phase/all (fuzzy-matched)", usage: "[<task|phase>]" },
|
|
452
|
+
],
|
|
453
|
+
allowArgs: true,
|
|
454
|
+
handle: handleTodoAcp,
|
|
455
|
+
handleTui: async (command, runtime) => {
|
|
456
|
+
await runtime.ctx.handleTodoCommand(command.args);
|
|
457
|
+
runtime.ctx.editor.setText("");
|
|
458
|
+
},
|
|
459
|
+
},
|
|
460
|
+
{
|
|
461
|
+
name: "session",
|
|
462
|
+
description: "Session management commands",
|
|
463
|
+
acpDescription: "Show session information",
|
|
464
|
+
acpInputHint: "info|delete",
|
|
465
|
+
subcommands: [
|
|
466
|
+
{ name: "info", description: "Show session info and stats" },
|
|
467
|
+
{ name: "delete", description: "Delete current session and return to selector" },
|
|
468
|
+
],
|
|
469
|
+
allowArgs: true,
|
|
470
|
+
handle: async (command, runtime) => {
|
|
471
|
+
if (!command.args || command.args === "info") {
|
|
472
|
+
await runtime.output(
|
|
473
|
+
[
|
|
474
|
+
`Session: ${runtime.session.sessionId}`,
|
|
475
|
+
`Title: ${runtime.session.sessionName}`,
|
|
476
|
+
`CWD: ${runtime.cwd}`,
|
|
477
|
+
].join("\n"),
|
|
478
|
+
);
|
|
479
|
+
return commandConsumed();
|
|
480
|
+
}
|
|
481
|
+
if (command.args === "delete") {
|
|
482
|
+
if (runtime.session.isStreaming) return usage("Cannot delete the session while streaming.", runtime);
|
|
483
|
+
const sessionFile = runtime.sessionManager.getSessionFile();
|
|
484
|
+
if (!sessionFile) return usage("No session file to delete (in-memory session).", runtime);
|
|
485
|
+
// Route through the active SessionManager so the persist writer is
|
|
486
|
+
// closed before the file is deleted. Constructing a fresh
|
|
487
|
+
// FileSessionStorage and calling deleteSessionWithArtifacts leaves
|
|
488
|
+
// the active writer attached to the now-deleted path, so the next
|
|
489
|
+
// prompt would silently resurrect or corrupt the "deleted" file.
|
|
490
|
+
try {
|
|
491
|
+
await runtime.sessionManager.dropSession(sessionFile);
|
|
492
|
+
} catch (err) {
|
|
493
|
+
return usage(`Failed to delete session: ${errorMessage(err)}`, runtime);
|
|
494
|
+
}
|
|
495
|
+
await runtime.output(
|
|
496
|
+
`Session deleted: ${sessionFile}. Use ACP \`session/load\` to switch to another session.`,
|
|
497
|
+
);
|
|
498
|
+
return commandConsumed();
|
|
499
|
+
}
|
|
500
|
+
return usage("Usage: /session [info|delete]", runtime);
|
|
501
|
+
},
|
|
502
|
+
handleTui: async (command, runtime) => {
|
|
503
|
+
const sub = command.args.trim().toLowerCase() || "info";
|
|
504
|
+
if (sub === "delete") {
|
|
505
|
+
runtime.ctx.editor.setText("");
|
|
506
|
+
await runtime.ctx.handleSessionDeleteCommand();
|
|
507
|
+
return;
|
|
508
|
+
}
|
|
509
|
+
// Default: show session info
|
|
510
|
+
await runtime.ctx.handleSessionCommand();
|
|
511
|
+
runtime.ctx.editor.setText("");
|
|
512
|
+
},
|
|
513
|
+
},
|
|
514
|
+
{
|
|
515
|
+
name: "jobs",
|
|
516
|
+
description: "Show async background jobs status",
|
|
517
|
+
acpDescription: "Show background jobs",
|
|
518
|
+
handle: async (_command, runtime) => {
|
|
519
|
+
const snapshot = runtime.session.getAsyncJobSnapshot({ recentLimit: 5 });
|
|
520
|
+
if (!snapshot || (snapshot.running.length === 0 && snapshot.recent.length === 0)) {
|
|
521
|
+
await runtime.output(
|
|
522
|
+
"No background jobs running. (Background jobs run async tools — e.g. long-running bash, debug, or task subagents that would otherwise tie up a turn. They appear here while alive and for ~5 minutes after.)",
|
|
523
|
+
);
|
|
524
|
+
return commandConsumed();
|
|
525
|
+
}
|
|
526
|
+
const now = Date.now();
|
|
527
|
+
const lines: string[] = ["Background Jobs", `Running: ${snapshot.running.length}`];
|
|
528
|
+
if (snapshot.running.length > 0) {
|
|
529
|
+
lines.push("", "Running Jobs");
|
|
530
|
+
for (const job of snapshot.running) {
|
|
531
|
+
lines.push(` [${job.id}] ${job.type} (${job.status}) — ${formatDuration(now - job.startTime)}`);
|
|
532
|
+
lines.push(` ${job.label}`);
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
if (snapshot.recent.length > 0) {
|
|
536
|
+
lines.push("", "Recent Jobs");
|
|
537
|
+
for (const job of snapshot.recent) {
|
|
538
|
+
lines.push(` [${job.id}] ${job.type} (${job.status}) — ${formatDuration(now - job.startTime)}`);
|
|
539
|
+
lines.push(` ${job.label}`);
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
await runtime.output(lines.join("\n"));
|
|
543
|
+
return commandConsumed();
|
|
544
|
+
},
|
|
545
|
+
handleTui: async (_command, runtime) => {
|
|
546
|
+
await runtime.ctx.handleJobsCommand();
|
|
547
|
+
runtime.ctx.editor.setText("");
|
|
548
|
+
},
|
|
549
|
+
},
|
|
550
|
+
{
|
|
551
|
+
name: "usage",
|
|
552
|
+
description: "Show provider usage and limits",
|
|
553
|
+
acpDescription: "Show token usage",
|
|
554
|
+
handle: async (_command, runtime) => {
|
|
555
|
+
await runtime.output(await buildUsageReportText(runtime));
|
|
556
|
+
return commandConsumed();
|
|
557
|
+
},
|
|
558
|
+
handleTui: async (_command, runtime) => {
|
|
559
|
+
await runtime.ctx.handleUsageCommand();
|
|
560
|
+
runtime.ctx.editor.setText("");
|
|
561
|
+
},
|
|
562
|
+
},
|
|
563
|
+
{
|
|
564
|
+
name: "stats",
|
|
565
|
+
description: "Launch the local stats dashboard",
|
|
566
|
+
inlineHint: "[--port <port>]",
|
|
567
|
+
allowArgs: true,
|
|
568
|
+
handle: async (command, runtime) => {
|
|
569
|
+
const parsed = parseStatsDashboardArgs(command.args);
|
|
570
|
+
if ("error" in parsed) return usage(parsed.error, runtime);
|
|
571
|
+
|
|
572
|
+
await runtime.output("Syncing session files...");
|
|
573
|
+
try {
|
|
574
|
+
const result = await launchStatsDashboard(parsed);
|
|
575
|
+
await runtime.output(result.message);
|
|
576
|
+
} catch (error) {
|
|
577
|
+
await runtime.output(`Stats dashboard failed: ${errorMessage(error)}`);
|
|
578
|
+
}
|
|
579
|
+
return commandConsumed();
|
|
580
|
+
},
|
|
581
|
+
},
|
|
582
|
+
{
|
|
583
|
+
name: "changelog",
|
|
584
|
+
description: "Show changelog entries",
|
|
585
|
+
acpDescription: "Show changelog",
|
|
586
|
+
acpInputHint: "[full]",
|
|
587
|
+
subcommands: [{ name: "full", description: "Show complete changelog" }],
|
|
588
|
+
allowArgs: true,
|
|
589
|
+
handle: async (command, runtime) => {
|
|
590
|
+
const changelogPath = getChangelogPath();
|
|
591
|
+
const allEntries = await parseChangelog(changelogPath);
|
|
592
|
+
const showFull = command.args.trim().toLowerCase() === "full";
|
|
593
|
+
const entriesToShow = showFull ? allEntries : allEntries.slice(0, 3);
|
|
594
|
+
if (entriesToShow.length === 0) {
|
|
595
|
+
await runtime.output("No changelog entries found.");
|
|
596
|
+
return commandConsumed();
|
|
597
|
+
}
|
|
598
|
+
await runtime.output(
|
|
599
|
+
[...entriesToShow]
|
|
600
|
+
.reverse()
|
|
601
|
+
.map(entry => entry.content)
|
|
602
|
+
.join("\n\n"),
|
|
603
|
+
);
|
|
604
|
+
return commandConsumed();
|
|
605
|
+
},
|
|
606
|
+
handleTui: async (command, runtime) => {
|
|
607
|
+
const showFull = command.args.split(/\s+/).filter(Boolean).includes("full");
|
|
608
|
+
await runtime.ctx.handleChangelogCommand(showFull);
|
|
609
|
+
runtime.ctx.editor.setText("");
|
|
610
|
+
},
|
|
611
|
+
},
|
|
612
|
+
{
|
|
613
|
+
name: "hotkeys",
|
|
614
|
+
description: "Show all keyboard shortcuts",
|
|
615
|
+
handleTui: (_command, runtime) => {
|
|
616
|
+
runtime.ctx.handleHotkeysCommand();
|
|
617
|
+
runtime.ctx.editor.setText("");
|
|
618
|
+
},
|
|
619
|
+
},
|
|
620
|
+
{
|
|
621
|
+
name: "tools",
|
|
622
|
+
description: "Show tools currently visible to the agent",
|
|
623
|
+
acpDescription: "Show available tools",
|
|
624
|
+
handle: async (_command, runtime) => {
|
|
625
|
+
const active = runtime.session.getActiveToolNames();
|
|
626
|
+
const all = runtime.session.getAllToolNames();
|
|
627
|
+
if (all.length === 0) {
|
|
628
|
+
await runtime.output("No tools are available.");
|
|
629
|
+
return commandConsumed();
|
|
630
|
+
}
|
|
631
|
+
await runtime.output(all.map(name => `${active.includes(name) ? "*" : "-"} ${name}`).join("\n"));
|
|
632
|
+
return commandConsumed();
|
|
633
|
+
},
|
|
634
|
+
handleTui: (_command, runtime) => {
|
|
635
|
+
runtime.ctx.handleToolsCommand();
|
|
636
|
+
runtime.ctx.editor.setText("");
|
|
637
|
+
},
|
|
638
|
+
},
|
|
639
|
+
{
|
|
640
|
+
name: "context",
|
|
641
|
+
description: "Show estimated context usage breakdown",
|
|
642
|
+
acpDescription: "Show context usage",
|
|
643
|
+
handle: async (_command, runtime) => {
|
|
644
|
+
await runtime.output(buildContextReportText(runtime));
|
|
645
|
+
return commandConsumed();
|
|
646
|
+
},
|
|
647
|
+
handleTui: (_command, runtime) => {
|
|
648
|
+
runtime.ctx.handleContextCommand();
|
|
649
|
+
runtime.ctx.editor.setText("");
|
|
650
|
+
},
|
|
651
|
+
},
|
|
652
|
+
{
|
|
653
|
+
name: "extensions",
|
|
654
|
+
aliases: ["status"],
|
|
655
|
+
description: "Open Extension Control Center dashboard",
|
|
656
|
+
handleTui: (_command, runtime) => {
|
|
657
|
+
runtime.ctx.showExtensionsDashboard();
|
|
658
|
+
runtime.ctx.editor.setText("");
|
|
659
|
+
},
|
|
660
|
+
},
|
|
661
|
+
{
|
|
662
|
+
name: "agents",
|
|
663
|
+
description: "Open Agent Control Center dashboard",
|
|
664
|
+
handleTui: (_command, runtime) => {
|
|
665
|
+
runtime.ctx.showAgentsDashboard();
|
|
666
|
+
runtime.ctx.editor.setText("");
|
|
667
|
+
},
|
|
668
|
+
},
|
|
669
|
+
{
|
|
670
|
+
name: "branch",
|
|
671
|
+
description: "Create a new branch from a previous message",
|
|
672
|
+
handleTui: (_command, runtime) => {
|
|
673
|
+
if (settings.get("doubleEscapeAction") === "tree") {
|
|
674
|
+
runtime.ctx.showTreeSelector();
|
|
675
|
+
} else {
|
|
676
|
+
runtime.ctx.showUserMessageSelector();
|
|
677
|
+
}
|
|
678
|
+
runtime.ctx.editor.setText("");
|
|
679
|
+
},
|
|
680
|
+
},
|
|
681
|
+
{
|
|
682
|
+
name: "fork",
|
|
683
|
+
description: "Create a new fork from a previous message",
|
|
684
|
+
handleTui: async (_command, runtime) => {
|
|
685
|
+
runtime.ctx.editor.setText("");
|
|
686
|
+
await runtime.ctx.handleForkCommand();
|
|
687
|
+
},
|
|
688
|
+
},
|
|
689
|
+
{
|
|
690
|
+
name: "tree",
|
|
691
|
+
description: "Navigate session tree (switch branches)",
|
|
692
|
+
handleTui: (_command, runtime) => {
|
|
693
|
+
runtime.ctx.showTreeSelector();
|
|
694
|
+
runtime.ctx.editor.setText("");
|
|
695
|
+
},
|
|
696
|
+
},
|
|
697
|
+
{
|
|
698
|
+
name: "login",
|
|
699
|
+
description: "Login with OAuth provider",
|
|
700
|
+
inlineHint: "[provider|redirect URL]",
|
|
701
|
+
allowArgs: true,
|
|
702
|
+
handleTui: (command, runtime) => {
|
|
703
|
+
const manualInput = runtime.ctx.oauthManualInput;
|
|
704
|
+
const args = command.args.trim();
|
|
705
|
+
if (args.length > 0) {
|
|
706
|
+
const matchedProvider = getOAuthProviders().find(provider => provider.id === args);
|
|
707
|
+
if (matchedProvider) {
|
|
708
|
+
if (manualInput.hasPending()) {
|
|
709
|
+
const pendingProvider = manualInput.pendingProviderId;
|
|
710
|
+
const message = pendingProvider
|
|
711
|
+
? `OAuth login already in progress for ${pendingProvider}. Paste the redirect URL with /login <url>.`
|
|
712
|
+
: "OAuth login already in progress. Paste the redirect URL with /login <url>.";
|
|
713
|
+
runtime.ctx.showWarning(message);
|
|
714
|
+
runtime.ctx.editor.setText("");
|
|
715
|
+
return;
|
|
716
|
+
}
|
|
717
|
+
void runtime.ctx.showOAuthSelector("login", matchedProvider.id);
|
|
718
|
+
runtime.ctx.editor.setText("");
|
|
719
|
+
return;
|
|
720
|
+
}
|
|
721
|
+
const submitted = manualInput.submit(args);
|
|
722
|
+
if (submitted) {
|
|
723
|
+
runtime.ctx.showStatus("OAuth callback received; completing login…");
|
|
724
|
+
} else {
|
|
725
|
+
runtime.ctx.showWarning("No OAuth login is waiting for a manual callback.");
|
|
726
|
+
}
|
|
727
|
+
runtime.ctx.editor.setText("");
|
|
728
|
+
return;
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
if (manualInput.hasPending()) {
|
|
732
|
+
const provider = manualInput.pendingProviderId;
|
|
733
|
+
const message = provider
|
|
734
|
+
? `OAuth login already in progress for ${provider}. Paste the redirect URL with /login <url>.`
|
|
735
|
+
: "OAuth login already in progress. Paste the redirect URL with /login <url>.";
|
|
736
|
+
runtime.ctx.showWarning(message);
|
|
737
|
+
runtime.ctx.editor.setText("");
|
|
738
|
+
return;
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
void runtime.ctx.showOAuthSelector("login");
|
|
742
|
+
runtime.ctx.editor.setText("");
|
|
743
|
+
},
|
|
744
|
+
},
|
|
745
|
+
{
|
|
746
|
+
name: "logout",
|
|
747
|
+
description: "Logout from OAuth provider",
|
|
748
|
+
handleTui: (_command, runtime) => {
|
|
749
|
+
void runtime.ctx.showOAuthSelector("logout");
|
|
750
|
+
runtime.ctx.editor.setText("");
|
|
751
|
+
},
|
|
752
|
+
},
|
|
753
|
+
{
|
|
754
|
+
name: "mcp",
|
|
755
|
+
description: "Manage MCP servers (add, list, remove, test)",
|
|
756
|
+
acpDescription: "Manage MCP servers",
|
|
757
|
+
inlineHint: "<subcommand>",
|
|
758
|
+
subcommands: [
|
|
759
|
+
{
|
|
760
|
+
name: "add",
|
|
761
|
+
description: "Add a new MCP server",
|
|
762
|
+
usage: "<name> [--scope project|user] [--url <url>] [-- <command...>]",
|
|
763
|
+
},
|
|
764
|
+
{ name: "list", description: "List all configured MCP servers" },
|
|
765
|
+
{ name: "remove", description: "Remove an MCP server", usage: "<name> [--scope project|user]" },
|
|
766
|
+
{ name: "test", description: "Test connection to a server", usage: "<name>" },
|
|
767
|
+
{ name: "reauth", description: "Reauthorize OAuth for a server", usage: "<name>" },
|
|
768
|
+
{ name: "unauth", description: "Remove OAuth auth from a server", usage: "<name>" },
|
|
769
|
+
{ name: "enable", description: "Enable an MCP server", usage: "<name>" },
|
|
770
|
+
{ name: "disable", description: "Disable an MCP server", usage: "<name>" },
|
|
771
|
+
{
|
|
772
|
+
name: "smithery-search",
|
|
773
|
+
description: "Search Smithery registry and deploy an MCP server",
|
|
774
|
+
usage: "<keyword> [--scope project|user] [--limit <1-100>] [--semantic]",
|
|
775
|
+
},
|
|
776
|
+
{ name: "smithery-login", description: "Login to Smithery and cache API key" },
|
|
777
|
+
{ name: "smithery-logout", description: "Remove cached Smithery API key" },
|
|
778
|
+
{ name: "reconnect", description: "Reconnect to a specific MCP server", usage: "<name>" },
|
|
779
|
+
{ name: "reload", description: "Force reload MCP runtime tools" },
|
|
780
|
+
{ name: "resources", description: "List available resources from connected servers" },
|
|
781
|
+
{ name: "prompts", description: "List available prompts from connected servers" },
|
|
782
|
+
{ name: "notifications", description: "Show notification capabilities and subscriptions" },
|
|
783
|
+
{ name: "help", description: "Show help message" },
|
|
784
|
+
],
|
|
785
|
+
allowArgs: true,
|
|
786
|
+
handle: handleMcpAcp,
|
|
787
|
+
handleTui: async (command, runtime) => {
|
|
788
|
+
runtime.ctx.editor.addToHistory(command.text);
|
|
789
|
+
runtime.ctx.editor.setText("");
|
|
790
|
+
await runtime.ctx.handleMCPCommand(command.text);
|
|
791
|
+
},
|
|
792
|
+
},
|
|
793
|
+
{
|
|
794
|
+
name: "ssh",
|
|
795
|
+
description: "Manage SSH hosts (add, list, remove)",
|
|
796
|
+
acpDescription: "Manage SSH connections",
|
|
797
|
+
inlineHint: "<subcommand>",
|
|
798
|
+
subcommands: [
|
|
799
|
+
{
|
|
800
|
+
name: "add",
|
|
801
|
+
description: "Add an SSH host",
|
|
802
|
+
usage: "<name> --host <host> [--user <user>] [--port <port>] [--key <keyPath>]",
|
|
803
|
+
},
|
|
804
|
+
{ name: "list", description: "List all configured SSH hosts" },
|
|
805
|
+
{ name: "remove", description: "Remove an SSH host", usage: "<name> [--scope project|user]" },
|
|
806
|
+
{ name: "help", description: "Show help message" },
|
|
807
|
+
],
|
|
808
|
+
allowArgs: true,
|
|
809
|
+
handle: handleSshAcp,
|
|
810
|
+
handleTui: async (command, runtime) => {
|
|
811
|
+
runtime.ctx.editor.addToHistory(command.text);
|
|
812
|
+
runtime.ctx.editor.setText("");
|
|
813
|
+
await runtime.ctx.handleSSHCommand(command.text);
|
|
814
|
+
},
|
|
815
|
+
},
|
|
816
|
+
{
|
|
817
|
+
name: "new",
|
|
818
|
+
description: "Start a new session",
|
|
819
|
+
handleTui: async (_command, runtime) => {
|
|
820
|
+
runtime.ctx.editor.setText("");
|
|
821
|
+
await runtime.ctx.handleClearCommand();
|
|
822
|
+
},
|
|
823
|
+
},
|
|
824
|
+
{
|
|
825
|
+
name: "fresh",
|
|
826
|
+
description: "Reset provider stream state without changing the local transcript",
|
|
827
|
+
handle: async (_command, runtime) => {
|
|
828
|
+
const result = runtime.session.freshSession();
|
|
829
|
+
if (!result) {
|
|
830
|
+
await runtime.output(
|
|
831
|
+
"Wait for the current response to finish or abort it before refreshing provider state.",
|
|
832
|
+
);
|
|
833
|
+
return commandConsumed();
|
|
834
|
+
}
|
|
835
|
+
await runtime.output(formatFreshSessionResult(result));
|
|
836
|
+
return commandConsumed();
|
|
837
|
+
},
|
|
838
|
+
handleTui: async (_command, runtime) => {
|
|
839
|
+
runtime.ctx.editor.setText("");
|
|
840
|
+
await runtime.ctx.handleFreshCommand();
|
|
841
|
+
},
|
|
842
|
+
},
|
|
843
|
+
{
|
|
844
|
+
name: "drop",
|
|
845
|
+
description: "Delete the current session and start a new one",
|
|
846
|
+
handleTui: async (_command, runtime) => {
|
|
847
|
+
runtime.ctx.editor.setText("");
|
|
848
|
+
await runtime.ctx.handleDropCommand();
|
|
849
|
+
},
|
|
850
|
+
},
|
|
851
|
+
{
|
|
852
|
+
name: "compact",
|
|
853
|
+
description: "Manually compact the session context",
|
|
854
|
+
acpDescription: "Compact the conversation",
|
|
855
|
+
inlineHint: "[focus instructions]",
|
|
856
|
+
allowArgs: true,
|
|
857
|
+
handle: async (command, runtime) => {
|
|
858
|
+
const before = runtime.session.getContextUsage?.();
|
|
859
|
+
const beforeTokens = before?.tokens;
|
|
860
|
+
try {
|
|
861
|
+
await runtime.session.compact(command.args || undefined);
|
|
862
|
+
} catch (err) {
|
|
863
|
+
// Compaction precondition failures (no model, already compacted, too
|
|
864
|
+
// small) and provider errors propagate as plain Errors; surface them
|
|
865
|
+
// via runtime.output so they don't fail the ACP prompt turn.
|
|
866
|
+
return usage(`Compaction failed: ${errorMessage(err)}`, runtime);
|
|
867
|
+
}
|
|
868
|
+
const after = runtime.session.getContextUsage?.();
|
|
869
|
+
const afterTokens = after?.tokens;
|
|
870
|
+
if (beforeTokens != null && afterTokens != null) {
|
|
871
|
+
const saved = beforeTokens - afterTokens;
|
|
872
|
+
await runtime.output(`Compaction complete. Tokens: ${beforeTokens} -> ${afterTokens} (saved ${saved}).`);
|
|
873
|
+
} else {
|
|
874
|
+
await runtime.output("Compaction complete.");
|
|
875
|
+
}
|
|
876
|
+
return commandConsumed();
|
|
877
|
+
},
|
|
878
|
+
handleTui: async (command, runtime) => {
|
|
879
|
+
const customInstructions = command.args || undefined;
|
|
880
|
+
runtime.ctx.editor.setText("");
|
|
881
|
+
await runtime.ctx.handleCompactCommand(customInstructions);
|
|
882
|
+
},
|
|
883
|
+
},
|
|
884
|
+
{
|
|
885
|
+
name: "shake",
|
|
886
|
+
description: "Drop heavy content from context (tool results, large blocks)",
|
|
887
|
+
acpDescription: "Shake heavy content out of the conversation context",
|
|
888
|
+
subcommands: [
|
|
889
|
+
{ name: "elide", description: "Strip tool results + large blocks (default)" },
|
|
890
|
+
{ name: "images", description: "Strip image blocks" },
|
|
891
|
+
],
|
|
892
|
+
acpInputHint: "[elide|images]",
|
|
893
|
+
allowArgs: true,
|
|
894
|
+
handle: async (command, runtime) => {
|
|
895
|
+
const mode = parseShakeMode(command.args);
|
|
896
|
+
if (typeof mode !== "string") return usage(mode.error, runtime);
|
|
897
|
+
const result = await runtime.session.shake(mode);
|
|
898
|
+
await runtime.output(formatShakeSummary(result));
|
|
899
|
+
return commandConsumed();
|
|
900
|
+
},
|
|
901
|
+
handleTui: async (command, runtime) => {
|
|
902
|
+
runtime.ctx.editor.setText("");
|
|
903
|
+
const mode = parseShakeMode(command.args);
|
|
904
|
+
if (typeof mode !== "string") {
|
|
905
|
+
runtime.ctx.showWarning(mode.error);
|
|
906
|
+
return;
|
|
907
|
+
}
|
|
908
|
+
await runtime.ctx.handleShakeCommand(mode);
|
|
909
|
+
},
|
|
910
|
+
},
|
|
911
|
+
{
|
|
912
|
+
name: "handoff",
|
|
913
|
+
description: "Hand off session context to a new session",
|
|
914
|
+
inlineHint: "[focus instructions]",
|
|
915
|
+
allowArgs: true,
|
|
916
|
+
handleTui: async (command, runtime) => {
|
|
917
|
+
const customInstructions = command.args || undefined;
|
|
918
|
+
runtime.ctx.editor.setText("");
|
|
919
|
+
await runtime.ctx.handleHandoffCommand(customInstructions);
|
|
920
|
+
},
|
|
921
|
+
},
|
|
922
|
+
{
|
|
923
|
+
name: "resume",
|
|
924
|
+
description: "Resume a different session",
|
|
925
|
+
handleTui: (_command, runtime) => {
|
|
926
|
+
runtime.ctx.showSessionSelector();
|
|
927
|
+
runtime.ctx.editor.setText("");
|
|
928
|
+
},
|
|
929
|
+
},
|
|
930
|
+
{
|
|
931
|
+
name: "btw",
|
|
932
|
+
description: "Ask an ephemeral side question using the current session context",
|
|
933
|
+
inlineHint: "<question>",
|
|
934
|
+
allowArgs: true,
|
|
935
|
+
handleTui: async (command, runtime) => {
|
|
936
|
+
const question = command.text.slice(`/${command.name}`.length).trim();
|
|
937
|
+
runtime.ctx.editor.setText("");
|
|
938
|
+
await runtime.ctx.handleBtwCommand(question);
|
|
939
|
+
},
|
|
940
|
+
},
|
|
941
|
+
{
|
|
942
|
+
name: "tan",
|
|
943
|
+
description: "Run a full background agent on tangential work",
|
|
944
|
+
inlineHint: "<work>",
|
|
945
|
+
allowArgs: true,
|
|
946
|
+
handleTui: async (command, runtime) => {
|
|
947
|
+
const work = command.text.slice(`/${command.name}`.length).trim();
|
|
948
|
+
runtime.ctx.editor.setText("");
|
|
949
|
+
await runtime.ctx.handleTanCommand(work);
|
|
950
|
+
},
|
|
951
|
+
},
|
|
952
|
+
{
|
|
953
|
+
name: "omfg",
|
|
954
|
+
description: "Forge a TTSR rule from a complaint to stop a recurring behavior",
|
|
955
|
+
inlineHint: "<complaint>",
|
|
956
|
+
allowArgs: true,
|
|
957
|
+
handleTui: async (command, runtime) => {
|
|
958
|
+
const complaint = command.text.slice(`/${command.name}`.length).trim();
|
|
959
|
+
runtime.ctx.editor.setText("");
|
|
960
|
+
await runtime.ctx.handleOmfgCommand(complaint);
|
|
961
|
+
},
|
|
962
|
+
},
|
|
963
|
+
{
|
|
964
|
+
name: "retry",
|
|
965
|
+
description: "Retry the last failed agent turn",
|
|
966
|
+
handleTui: async (_command, runtime) => {
|
|
967
|
+
const didRetry = await runtime.ctx.session.retry();
|
|
968
|
+
if (!didRetry) {
|
|
969
|
+
runtime.ctx.showStatus("Nothing to retry");
|
|
970
|
+
}
|
|
971
|
+
runtime.ctx.editor.setText("");
|
|
972
|
+
},
|
|
973
|
+
},
|
|
974
|
+
{
|
|
975
|
+
name: "debug",
|
|
976
|
+
description: "Open debug tools selector",
|
|
977
|
+
handleTui: (_command, runtime) => {
|
|
978
|
+
runtime.ctx.showDebugSelector();
|
|
979
|
+
runtime.ctx.editor.setText("");
|
|
980
|
+
},
|
|
981
|
+
},
|
|
982
|
+
{
|
|
983
|
+
name: "memory",
|
|
984
|
+
description: "Inspect and operate memory maintenance",
|
|
985
|
+
acpDescription: "Manage memory",
|
|
986
|
+
acpInputHint: "<subcommand>",
|
|
987
|
+
subcommands: [
|
|
988
|
+
{ name: "view", description: "Show current memory injection payload" },
|
|
989
|
+
{ name: "stats", description: "Show memory backend statistics" },
|
|
990
|
+
{ name: "diagnose", description: "Run memory backend diagnostics" },
|
|
991
|
+
{ name: "clear", description: "Clear persisted memory data and artifacts" },
|
|
992
|
+
{ name: "reset", description: "Alias for clear" },
|
|
993
|
+
{ name: "enqueue", description: "Enqueue memory consolidation maintenance" },
|
|
994
|
+
{ name: "rebuild", description: "Alias for enqueue" },
|
|
995
|
+
{ name: "mm list", description: "List mental models on the active bank" },
|
|
996
|
+
{ name: "mm show", description: "Show one mental model (id required)" },
|
|
997
|
+
{
|
|
998
|
+
name: "mm refresh",
|
|
999
|
+
description: "Refresh auto-refresh models bank-wide, or one model by id",
|
|
1000
|
+
},
|
|
1001
|
+
{ name: "mm history", description: "Diff the change history of a mental model" },
|
|
1002
|
+
{ name: "mm seed", description: "Create any built-in mental models that are missing" },
|
|
1003
|
+
{ name: "mm delete", description: "Delete a mental model from the bank (id required)" },
|
|
1004
|
+
{ name: "mm reload", description: "Re-pull the cached <mental_models> block" },
|
|
1005
|
+
],
|
|
1006
|
+
allowArgs: true,
|
|
1007
|
+
handle: async (command, runtime) => {
|
|
1008
|
+
const verb = (command.args.trim().split(/\s+/)[0] ?? "").toLowerCase() || "view";
|
|
1009
|
+
const backend = await resolveMemoryBackend(runtime.settings);
|
|
1010
|
+
switch (verb) {
|
|
1011
|
+
case "view": {
|
|
1012
|
+
const payload = await backend.buildDeveloperInstructions(
|
|
1013
|
+
runtime.settings.getAgentDir(),
|
|
1014
|
+
runtime.settings,
|
|
1015
|
+
runtime.session,
|
|
1016
|
+
);
|
|
1017
|
+
await runtime.output(payload || "Memory payload is empty.");
|
|
1018
|
+
return commandConsumed();
|
|
1019
|
+
}
|
|
1020
|
+
case "clear":
|
|
1021
|
+
case "reset": {
|
|
1022
|
+
await backend.clear(runtime.settings.getAgentDir(), runtime.cwd, runtime.session);
|
|
1023
|
+
await runtime.session.refreshBaseSystemPrompt();
|
|
1024
|
+
await runtime.output("Memory cleared.");
|
|
1025
|
+
return commandConsumed();
|
|
1026
|
+
}
|
|
1027
|
+
case "enqueue":
|
|
1028
|
+
case "rebuild": {
|
|
1029
|
+
await backend.enqueue(runtime.settings.getAgentDir(), runtime.cwd, runtime.session);
|
|
1030
|
+
await runtime.output("Memory consolidation enqueued.");
|
|
1031
|
+
return commandConsumed();
|
|
1032
|
+
}
|
|
1033
|
+
case "stats":
|
|
1034
|
+
case "diagnose": {
|
|
1035
|
+
const hook = verb === "stats" ? backend.stats : backend.diagnose;
|
|
1036
|
+
const payload = await hook?.(runtime.settings.getAgentDir(), runtime.cwd, runtime.session);
|
|
1037
|
+
await runtime.output(payload ?? `Memory ${verb} is not available for the ${backend.id} backend.`);
|
|
1038
|
+
return commandConsumed();
|
|
1039
|
+
}
|
|
1040
|
+
case "mm":
|
|
1041
|
+
return usage(
|
|
1042
|
+
"Mental-model maintenance via /memory mm is unsupported in ACP mode; use the hindsight HTTP API directly.",
|
|
1043
|
+
runtime,
|
|
1044
|
+
);
|
|
1045
|
+
default:
|
|
1046
|
+
return usage("Usage: /memory <view|stats|diagnose|clear|reset|enqueue|rebuild>", runtime);
|
|
1047
|
+
}
|
|
1048
|
+
},
|
|
1049
|
+
handleTui: async (command, runtime) => {
|
|
1050
|
+
runtime.ctx.editor.setText("");
|
|
1051
|
+
await runtime.ctx.handleMemoryCommand(command.text);
|
|
1052
|
+
},
|
|
1053
|
+
},
|
|
1054
|
+
{
|
|
1055
|
+
name: "rename",
|
|
1056
|
+
description: "Rename the current session",
|
|
1057
|
+
inlineHint: "<title>",
|
|
1058
|
+
allowArgs: true,
|
|
1059
|
+
handle: async (command, runtime) => {
|
|
1060
|
+
if (!command.args) return usage("Usage: /rename <title>", runtime);
|
|
1061
|
+
const ok = await runtime.sessionManager.setSessionName(command.args, "user");
|
|
1062
|
+
if (!ok) {
|
|
1063
|
+
await runtime.output("Session name not changed (a user-set name takes precedence).");
|
|
1064
|
+
return commandConsumed();
|
|
1065
|
+
}
|
|
1066
|
+
await runtime.notifyTitleChanged?.();
|
|
1067
|
+
await runtime.output(`Session renamed to ${command.args}.`);
|
|
1068
|
+
return commandConsumed();
|
|
1069
|
+
},
|
|
1070
|
+
handleTui: async (command, runtime) => {
|
|
1071
|
+
const title = command.args.trim();
|
|
1072
|
+
if (!title) {
|
|
1073
|
+
runtime.ctx.showError("Usage: /rename <title>");
|
|
1074
|
+
runtime.ctx.editor.setText("");
|
|
1075
|
+
return;
|
|
1076
|
+
}
|
|
1077
|
+
runtime.ctx.editor.setText("");
|
|
1078
|
+
await runtime.ctx.handleRenameCommand(title);
|
|
1079
|
+
},
|
|
1080
|
+
},
|
|
1081
|
+
{
|
|
1082
|
+
name: "move",
|
|
1083
|
+
description: "Move session to a different working directory",
|
|
1084
|
+
acpDescription: "Move the current session file",
|
|
1085
|
+
inlineHint: "<path>",
|
|
1086
|
+
allowArgs: true,
|
|
1087
|
+
handle: async (command, runtime) => {
|
|
1088
|
+
if (runtime.session.isStreaming) return usage("Cannot move while streaming.", runtime);
|
|
1089
|
+
if (!command.args) return usage("Usage: /move <path>", runtime);
|
|
1090
|
+
const resolvedPath = path.resolve(runtime.cwd, command.args);
|
|
1091
|
+
let isDirectory: boolean;
|
|
1092
|
+
try {
|
|
1093
|
+
isDirectory = (await fs.stat(resolvedPath)).isDirectory();
|
|
1094
|
+
} catch {
|
|
1095
|
+
return usage(`Directory does not exist or is not a directory: ${resolvedPath}`, runtime);
|
|
1096
|
+
}
|
|
1097
|
+
if (!isDirectory) return usage(`Directory does not exist or is not a directory: ${resolvedPath}`, runtime);
|
|
1098
|
+
try {
|
|
1099
|
+
await runtime.sessionManager.flush();
|
|
1100
|
+
await runtime.sessionManager.moveTo(resolvedPath);
|
|
1101
|
+
} catch (err) {
|
|
1102
|
+
return usage(`Move failed: ${errorMessage(err)}`, runtime);
|
|
1103
|
+
}
|
|
1104
|
+
setProjectDir(resolvedPath);
|
|
1105
|
+
// Reload plugin/capability caches so the next prompt sees commands and
|
|
1106
|
+
// capabilities scoped to the new cwd.
|
|
1107
|
+
await runtime.reloadPlugins();
|
|
1108
|
+
await runtime.notifyTitleChanged?.();
|
|
1109
|
+
await runtime.output(`Session moved to ${runtime.sessionManager.getCwd()}.`);
|
|
1110
|
+
return commandConsumed();
|
|
1111
|
+
},
|
|
1112
|
+
handleTui: async (command, runtime) => {
|
|
1113
|
+
const targetPath = command.args;
|
|
1114
|
+
if (!targetPath) {
|
|
1115
|
+
runtime.ctx.showError("Usage: /move <path>");
|
|
1116
|
+
runtime.ctx.editor.setText("");
|
|
1117
|
+
return;
|
|
1118
|
+
}
|
|
1119
|
+
runtime.ctx.editor.setText("");
|
|
1120
|
+
await runtime.ctx.handleMoveCommand(targetPath);
|
|
1121
|
+
},
|
|
1122
|
+
},
|
|
1123
|
+
{
|
|
1124
|
+
name: "exit",
|
|
1125
|
+
description: "Exit the application",
|
|
1126
|
+
handleTui: shutdownHandlerTui,
|
|
1127
|
+
},
|
|
1128
|
+
{
|
|
1129
|
+
name: "marketplace",
|
|
1130
|
+
description: "Manage marketplace plugin sources and installed plugins",
|
|
1131
|
+
acpDescription: "Manage plugins from marketplaces",
|
|
1132
|
+
acpInputHint: "<subcommand>",
|
|
1133
|
+
subcommands: [
|
|
1134
|
+
{ name: "add", description: "Add a marketplace source", usage: "<source>" },
|
|
1135
|
+
{ name: "remove", description: "Remove a marketplace source", usage: "<name>" },
|
|
1136
|
+
{ name: "update", description: "Update marketplace catalog(s)", usage: "[name]" },
|
|
1137
|
+
{ name: "list", description: "List configured marketplaces" },
|
|
1138
|
+
{ name: "discover", description: "Browse available plugins", usage: "[marketplace]" },
|
|
1139
|
+
{
|
|
1140
|
+
name: "install",
|
|
1141
|
+
description: "Install a plugin (interactive browser if no args)",
|
|
1142
|
+
usage: "[--force] [name@marketplace]",
|
|
1143
|
+
},
|
|
1144
|
+
{ name: "uninstall", description: "Uninstall a plugin (selector if no args)", usage: "[name@marketplace]" },
|
|
1145
|
+
{ name: "installed", description: "List installed marketplace plugins" },
|
|
1146
|
+
{ name: "upgrade", description: "Upgrade outdated plugins", usage: "[name@marketplace]" },
|
|
1147
|
+
{ name: "help", description: "Show usage guide" },
|
|
1148
|
+
],
|
|
1149
|
+
allowArgs: true,
|
|
1150
|
+
handle: async (command, runtime) => {
|
|
1151
|
+
const { verb, rest } = parseSubcommand(command.args);
|
|
1152
|
+
if (!verb) {
|
|
1153
|
+
try {
|
|
1154
|
+
const manager = await createMarketplaceManager(runtime);
|
|
1155
|
+
const marketplaces = await manager.listMarketplaces();
|
|
1156
|
+
if (marketplaces.length === 0) {
|
|
1157
|
+
await runtime.output(
|
|
1158
|
+
"No marketplaces configured.\n\nGet started:\n /marketplace add anthropics/claude-plugins-official\n\nThen browse with /marketplace discover",
|
|
1159
|
+
);
|
|
1160
|
+
} else {
|
|
1161
|
+
const lines = marketplaces.map(m => ` ${m.name} ${m.sourceUri}`);
|
|
1162
|
+
await runtime.output(
|
|
1163
|
+
`Marketplaces:\n${lines.join("\n")}\n\nUse /marketplace discover to browse plugins, or /marketplace help for all commands`,
|
|
1164
|
+
);
|
|
1165
|
+
}
|
|
1166
|
+
return commandConsumed();
|
|
1167
|
+
} catch (err) {
|
|
1168
|
+
return usage(`Marketplace error: ${errorMessage(err)}`, runtime);
|
|
1169
|
+
}
|
|
1170
|
+
}
|
|
1171
|
+
if (verb === "help") {
|
|
1172
|
+
await runtime.output(
|
|
1173
|
+
[
|
|
1174
|
+
"Marketplace commands:",
|
|
1175
|
+
" /marketplace List configured marketplaces",
|
|
1176
|
+
" /marketplace add <source> Add a marketplace (e.g. owner/repo)",
|
|
1177
|
+
" /marketplace remove <name> Remove a marketplace",
|
|
1178
|
+
" /marketplace update [name] Re-fetch catalog(s)",
|
|
1179
|
+
" /marketplace list List configured marketplaces",
|
|
1180
|
+
" /marketplace discover [marketplace] Browse available plugins",
|
|
1181
|
+
" /marketplace install <name@marketplace> Install a plugin",
|
|
1182
|
+
" /marketplace uninstall <name@marketplace> Uninstall a plugin",
|
|
1183
|
+
" /marketplace installed List installed plugins",
|
|
1184
|
+
" /marketplace upgrade [name@marketplace] Upgrade plugin(s)",
|
|
1185
|
+
"",
|
|
1186
|
+
"Quick start:",
|
|
1187
|
+
" /marketplace add anthropics/claude-plugins-official",
|
|
1188
|
+
].join("\n"),
|
|
1189
|
+
);
|
|
1190
|
+
return commandConsumed();
|
|
1191
|
+
}
|
|
1192
|
+
if ((verb === "install" || verb === "uninstall") && !rest) {
|
|
1193
|
+
return usage(
|
|
1194
|
+
"Interactive plugin pickers are TUI-only. Pass an explicit name@marketplace argument.",
|
|
1195
|
+
runtime,
|
|
1196
|
+
);
|
|
1197
|
+
}
|
|
1198
|
+
try {
|
|
1199
|
+
const manager = await createMarketplaceManager(runtime);
|
|
1200
|
+
switch (verb) {
|
|
1201
|
+
case "add": {
|
|
1202
|
+
if (!rest) return usage("Usage: /marketplace add <source>", runtime);
|
|
1203
|
+
const entry = await manager.addMarketplace(rest);
|
|
1204
|
+
await runtime.output(`Added marketplace: ${entry.name}`);
|
|
1205
|
+
return commandConsumed();
|
|
1206
|
+
}
|
|
1207
|
+
case "remove":
|
|
1208
|
+
case "rm": {
|
|
1209
|
+
if (!rest) return usage("Usage: /marketplace remove <name>", runtime);
|
|
1210
|
+
await manager.removeMarketplace(rest);
|
|
1211
|
+
await runtime.output(`Removed marketplace: ${rest}`);
|
|
1212
|
+
return commandConsumed();
|
|
1213
|
+
}
|
|
1214
|
+
case "update": {
|
|
1215
|
+
if (rest) {
|
|
1216
|
+
await manager.updateMarketplace(rest);
|
|
1217
|
+
await runtime.output(`Updated marketplace: ${rest}`);
|
|
1218
|
+
} else {
|
|
1219
|
+
const results = await manager.updateAllMarketplaces();
|
|
1220
|
+
await runtime.output(`Updated ${results.length} marketplace(s)`);
|
|
1221
|
+
}
|
|
1222
|
+
return commandConsumed();
|
|
1223
|
+
}
|
|
1224
|
+
case "list": {
|
|
1225
|
+
const marketplaces = await manager.listMarketplaces();
|
|
1226
|
+
if (marketplaces.length === 0) {
|
|
1227
|
+
await runtime.output("No marketplaces configured.");
|
|
1228
|
+
} else {
|
|
1229
|
+
const lines = marketplaces.map(m => ` ${m.name} ${m.sourceUri}`);
|
|
1230
|
+
await runtime.output(`Marketplaces:\n${lines.join("\n")}`);
|
|
1231
|
+
}
|
|
1232
|
+
return commandConsumed();
|
|
1233
|
+
}
|
|
1234
|
+
case "discover": {
|
|
1235
|
+
const plugins = await manager.listAvailablePlugins(rest || undefined);
|
|
1236
|
+
if (plugins.length === 0) {
|
|
1237
|
+
const marketplaces = await manager.listMarketplaces();
|
|
1238
|
+
await runtime.output(
|
|
1239
|
+
marketplaces.length === 0
|
|
1240
|
+
? "No marketplaces configured. Try:\n /marketplace add anthropics/claude-plugins-official"
|
|
1241
|
+
: "No plugins available in configured marketplaces",
|
|
1242
|
+
);
|
|
1243
|
+
return commandConsumed();
|
|
1244
|
+
}
|
|
1245
|
+
const lines = ["Available plugins:"];
|
|
1246
|
+
for (const plugin of plugins) {
|
|
1247
|
+
lines.push(` - ${plugin.name}${plugin.version ? `@${plugin.version}` : ""}`);
|
|
1248
|
+
if (plugin.description) lines.push(` ${plugin.description}`);
|
|
1249
|
+
}
|
|
1250
|
+
await runtime.output(lines.join("\n"));
|
|
1251
|
+
return commandConsumed();
|
|
1252
|
+
}
|
|
1253
|
+
case "install": {
|
|
1254
|
+
const parsed = parseMarketplaceInstallArgs(rest);
|
|
1255
|
+
if ("error" in parsed) return usage(parsed.error, runtime);
|
|
1256
|
+
const atIndex = parsed.installSpec.lastIndexOf("@");
|
|
1257
|
+
const pluginName = parsed.installSpec.slice(0, atIndex);
|
|
1258
|
+
const marketplace = parsed.installSpec.slice(atIndex + 1);
|
|
1259
|
+
await manager.installPlugin(pluginName, marketplace, { force: parsed.force, scope: parsed.scope });
|
|
1260
|
+
await runtime.reloadPlugins();
|
|
1261
|
+
await runtime.output(`Installed ${pluginName} from ${marketplace}`);
|
|
1262
|
+
return commandConsumed();
|
|
1263
|
+
}
|
|
1264
|
+
case "uninstall": {
|
|
1265
|
+
const parsed = parsePluginScopeArgs(
|
|
1266
|
+
rest,
|
|
1267
|
+
"Usage: /marketplace uninstall [--scope user|project] <name@marketplace>",
|
|
1268
|
+
);
|
|
1269
|
+
if ("error" in parsed) return usage(parsed.error, runtime);
|
|
1270
|
+
await manager.uninstallPlugin(parsed.pluginId, parsed.scope);
|
|
1271
|
+
await runtime.reloadPlugins();
|
|
1272
|
+
await runtime.output(`Uninstalled ${parsed.pluginId}`);
|
|
1273
|
+
return commandConsumed();
|
|
1274
|
+
}
|
|
1275
|
+
case "installed": {
|
|
1276
|
+
const installed = await manager.listInstalledPlugins();
|
|
1277
|
+
if (installed.length === 0) {
|
|
1278
|
+
await runtime.output("No marketplace plugins installed");
|
|
1279
|
+
} else {
|
|
1280
|
+
const lines = installed.map(
|
|
1281
|
+
p => ` ${p.id} [${p.scope}]${p.shadowedBy ? " [shadowed]" : ""} (${p.entries.length} entry)`,
|
|
1282
|
+
);
|
|
1283
|
+
await runtime.output(`Installed plugins:\n${lines.join("\n")}`);
|
|
1284
|
+
}
|
|
1285
|
+
return commandConsumed();
|
|
1286
|
+
}
|
|
1287
|
+
case "upgrade": {
|
|
1288
|
+
if (rest) {
|
|
1289
|
+
const parsed = parsePluginScopeArgs(
|
|
1290
|
+
rest,
|
|
1291
|
+
"Usage: /marketplace upgrade [--scope user|project] <name@marketplace>",
|
|
1292
|
+
);
|
|
1293
|
+
if ("error" in parsed) return usage(parsed.error, runtime);
|
|
1294
|
+
const result = await manager.upgradePlugin(parsed.pluginId, parsed.scope);
|
|
1295
|
+
await runtime.reloadPlugins();
|
|
1296
|
+
await runtime.output(`Upgraded ${parsed.pluginId} to ${result.version}`);
|
|
1297
|
+
return commandConsumed();
|
|
1298
|
+
}
|
|
1299
|
+
const results = await manager.upgradeAllPlugins();
|
|
1300
|
+
if (results.length === 0) {
|
|
1301
|
+
await runtime.output("All marketplace plugins are up to date");
|
|
1302
|
+
} else {
|
|
1303
|
+
await runtime.reloadPlugins();
|
|
1304
|
+
const lines = results.map(r => ` ${r.pluginId}: ${r.from} -> ${r.to}`);
|
|
1305
|
+
await runtime.output(`Upgraded ${results.length} plugin(s):\n${lines.join("\n")}`);
|
|
1306
|
+
}
|
|
1307
|
+
return commandConsumed();
|
|
1308
|
+
}
|
|
1309
|
+
default:
|
|
1310
|
+
return usage(
|
|
1311
|
+
`Unknown /marketplace subcommand: ${verb}. Use /marketplace help for available commands.`,
|
|
1312
|
+
runtime,
|
|
1313
|
+
);
|
|
1314
|
+
}
|
|
1315
|
+
} catch (err) {
|
|
1316
|
+
return usage(`Marketplace error: ${errorMessage(err)}`, runtime);
|
|
1317
|
+
}
|
|
1318
|
+
},
|
|
1319
|
+
handleTui: async (command, runtime) => {
|
|
1320
|
+
runtime.ctx.editor.setText("");
|
|
1321
|
+
const args = command.args.trim().split(/\s+/);
|
|
1322
|
+
const sub = args[0] || "install";
|
|
1323
|
+
const rest = args.slice(1).join(" ").trim();
|
|
1324
|
+
|
|
1325
|
+
// /marketplace (no args) or /marketplace install (no args) → interactive browser
|
|
1326
|
+
if ((sub === "install" && !rest) || (!args[0] && !command.args.trim())) {
|
|
1327
|
+
try {
|
|
1328
|
+
runtime.ctx.showPluginSelector("install");
|
|
1329
|
+
} catch (err) {
|
|
1330
|
+
runtime.ctx.showStatus(`Marketplace error: ${err}`);
|
|
1331
|
+
}
|
|
1332
|
+
return;
|
|
1333
|
+
}
|
|
1334
|
+
|
|
1335
|
+
const mgr = new MarketplaceManager({
|
|
1336
|
+
marketplacesRegistryPath: getMarketplacesRegistryPath(),
|
|
1337
|
+
installedRegistryPath: getInstalledPluginsRegistryPath(),
|
|
1338
|
+
projectInstalledRegistryPath: await resolveOrDefaultProjectRegistryPath(
|
|
1339
|
+
runtime.ctx.sessionManager.getCwd(),
|
|
1340
|
+
),
|
|
1341
|
+
marketplacesCacheDir: getMarketplacesCacheDir(),
|
|
1342
|
+
pluginsCacheDir: getPluginsCacheDir(),
|
|
1343
|
+
clearPluginRootsCache: clearPluginRootsAndCaches,
|
|
1344
|
+
});
|
|
1345
|
+
|
|
1346
|
+
try {
|
|
1347
|
+
switch (sub) {
|
|
1348
|
+
case "add": {
|
|
1349
|
+
if (!rest) {
|
|
1350
|
+
runtime.ctx.showStatus("Usage: /marketplace add <source>");
|
|
1351
|
+
return;
|
|
1352
|
+
}
|
|
1353
|
+
const entry = await mgr.addMarketplace(rest);
|
|
1354
|
+
runtime.ctx.showStatus(`Added marketplace: ${entry.name}`);
|
|
1355
|
+
break;
|
|
1356
|
+
}
|
|
1357
|
+
case "remove":
|
|
1358
|
+
case "rm": {
|
|
1359
|
+
if (!rest) {
|
|
1360
|
+
runtime.ctx.showStatus("Usage: /marketplace remove <name>");
|
|
1361
|
+
return;
|
|
1362
|
+
}
|
|
1363
|
+
await mgr.removeMarketplace(rest);
|
|
1364
|
+
runtime.ctx.showStatus(`Removed marketplace: ${rest}`);
|
|
1365
|
+
break;
|
|
1366
|
+
}
|
|
1367
|
+
case "update": {
|
|
1368
|
+
if (rest) {
|
|
1369
|
+
await mgr.updateMarketplace(rest);
|
|
1370
|
+
runtime.ctx.showStatus(`Updated marketplace: ${rest}`);
|
|
1371
|
+
} else {
|
|
1372
|
+
const results = await mgr.updateAllMarketplaces();
|
|
1373
|
+
runtime.ctx.showStatus(`Updated ${results.length} marketplace(s)`);
|
|
1374
|
+
}
|
|
1375
|
+
break;
|
|
1376
|
+
}
|
|
1377
|
+
case "discover": {
|
|
1378
|
+
const plugins = await mgr.listAvailablePlugins(rest || undefined);
|
|
1379
|
+
if (plugins.length === 0) {
|
|
1380
|
+
const marketplaces = await mgr.listMarketplaces();
|
|
1381
|
+
if (marketplaces.length === 0) {
|
|
1382
|
+
runtime.ctx.showStatus(
|
|
1383
|
+
"No marketplaces configured. Try:\n /marketplace add anthropics/claude-plugins-official",
|
|
1384
|
+
);
|
|
1385
|
+
} else {
|
|
1386
|
+
runtime.ctx.showStatus("No plugins available in configured marketplaces");
|
|
1387
|
+
}
|
|
1388
|
+
} else {
|
|
1389
|
+
const lines = plugins.map(
|
|
1390
|
+
p =>
|
|
1391
|
+
` ${p.name}${p.version ? `@${p.version}` : ""}${p.description ? ` - ${p.description}` : ""}`,
|
|
1392
|
+
);
|
|
1393
|
+
runtime.ctx.showStatus(`Available plugins:\n${lines.join("\n")}`);
|
|
1394
|
+
}
|
|
1395
|
+
break;
|
|
1396
|
+
}
|
|
1397
|
+
case "install": {
|
|
1398
|
+
// Parse: /marketplace install [--force] [--scope user|project] name@marketplace
|
|
1399
|
+
const parsed = parseMarketplaceInstallArgs(rest);
|
|
1400
|
+
if ("error" in parsed) {
|
|
1401
|
+
runtime.ctx.showStatus(parsed.error);
|
|
1402
|
+
return;
|
|
1403
|
+
}
|
|
1404
|
+
const atIdx = parsed.installSpec.lastIndexOf("@");
|
|
1405
|
+
const name = parsed.installSpec.slice(0, atIdx);
|
|
1406
|
+
const marketplace = parsed.installSpec.slice(atIdx + 1);
|
|
1407
|
+
await mgr.installPlugin(name, marketplace, { force: parsed.force, scope: parsed.scope });
|
|
1408
|
+
runtime.ctx.showStatus(`Installed ${name} from ${marketplace}`);
|
|
1409
|
+
break;
|
|
1410
|
+
}
|
|
1411
|
+
case "uninstall": {
|
|
1412
|
+
if (!rest) {
|
|
1413
|
+
// No args → open interactive uninstall selector
|
|
1414
|
+
runtime.ctx.showPluginSelector("uninstall");
|
|
1415
|
+
return;
|
|
1416
|
+
}
|
|
1417
|
+
const uninstArgs = parsePluginScopeArgs(
|
|
1418
|
+
rest,
|
|
1419
|
+
"Usage: /marketplace uninstall [--scope user|project] <name@marketplace>",
|
|
1420
|
+
);
|
|
1421
|
+
if ("error" in uninstArgs) {
|
|
1422
|
+
runtime.ctx.showStatus(uninstArgs.error);
|
|
1423
|
+
return;
|
|
1424
|
+
}
|
|
1425
|
+
await mgr.uninstallPlugin(uninstArgs.pluginId, uninstArgs.scope);
|
|
1426
|
+
runtime.ctx.showStatus(`Uninstalled ${uninstArgs.pluginId}`);
|
|
1427
|
+
break;
|
|
1428
|
+
}
|
|
1429
|
+
case "installed": {
|
|
1430
|
+
const installed = await mgr.listInstalledPlugins();
|
|
1431
|
+
if (installed.length === 0) {
|
|
1432
|
+
runtime.ctx.showStatus("No marketplace plugins installed");
|
|
1433
|
+
} else {
|
|
1434
|
+
const lines = installed.map(
|
|
1435
|
+
p => ` ${p.id} [${p.scope}]${p.shadowedBy ? " [shadowed]" : ""} (${p.entries.length} entry)`,
|
|
1436
|
+
);
|
|
1437
|
+
runtime.ctx.showStatus(`Installed plugins:\n${lines.join("\n")}`);
|
|
1438
|
+
}
|
|
1439
|
+
break;
|
|
1440
|
+
}
|
|
1441
|
+
case "upgrade": {
|
|
1442
|
+
if (rest) {
|
|
1443
|
+
const upArgs = parsePluginScopeArgs(
|
|
1444
|
+
rest,
|
|
1445
|
+
"Usage: /marketplace upgrade [--scope user|project] <name@marketplace>",
|
|
1446
|
+
);
|
|
1447
|
+
if ("error" in upArgs) {
|
|
1448
|
+
runtime.ctx.showStatus(upArgs.error);
|
|
1449
|
+
return;
|
|
1450
|
+
}
|
|
1451
|
+
const result = await mgr.upgradePlugin(upArgs.pluginId, upArgs.scope);
|
|
1452
|
+
runtime.ctx.showStatus(`Upgraded ${upArgs.pluginId} to ${result.version}`);
|
|
1453
|
+
} else {
|
|
1454
|
+
const results = await mgr.upgradeAllPlugins();
|
|
1455
|
+
if (results.length === 0) {
|
|
1456
|
+
runtime.ctx.showStatus("All marketplace plugins are up to date");
|
|
1457
|
+
} else {
|
|
1458
|
+
const lines = results.map(r => ` ${r.pluginId}: ${r.from} -> ${r.to}`);
|
|
1459
|
+
runtime.ctx.showStatus(`Upgraded ${results.length} plugin(s):\n${lines.join("\n")}`);
|
|
1460
|
+
}
|
|
1461
|
+
}
|
|
1462
|
+
break;
|
|
1463
|
+
}
|
|
1464
|
+
case "help": {
|
|
1465
|
+
runtime.ctx.showStatus(
|
|
1466
|
+
[
|
|
1467
|
+
"Marketplace commands:",
|
|
1468
|
+
" /marketplace Browse and install plugins",
|
|
1469
|
+
" /marketplace add <source> Add a marketplace (e.g. owner/repo)",
|
|
1470
|
+
" /marketplace remove <name> Remove a marketplace",
|
|
1471
|
+
" /marketplace update [name] Re-fetch catalog(s)",
|
|
1472
|
+
" /marketplace list List configured marketplaces",
|
|
1473
|
+
" /marketplace discover [marketplace] Browse available plugins",
|
|
1474
|
+
" /marketplace install <name@marketplace> Install a plugin",
|
|
1475
|
+
" /marketplace uninstall <name@marketplace> Uninstall a plugin",
|
|
1476
|
+
" /marketplace installed List installed plugins",
|
|
1477
|
+
" /marketplace upgrade [name@marketplace] Upgrade plugin(s)",
|
|
1478
|
+
"",
|
|
1479
|
+
"Quick start:",
|
|
1480
|
+
" /marketplace add anthropics/claude-plugins-official",
|
|
1481
|
+
" /marketplace (opens interactive browser)",
|
|
1482
|
+
].join("\n"),
|
|
1483
|
+
);
|
|
1484
|
+
break;
|
|
1485
|
+
}
|
|
1486
|
+
default: {
|
|
1487
|
+
const marketplaces = await mgr.listMarketplaces();
|
|
1488
|
+
if (marketplaces.length === 0) {
|
|
1489
|
+
runtime.ctx.showStatus(
|
|
1490
|
+
"No marketplaces configured.\n\nGet started:\n /marketplace add anthropics/claude-plugins-official\n\nThen browse plugins with /marketplace or /marketplace discover",
|
|
1491
|
+
);
|
|
1492
|
+
} else {
|
|
1493
|
+
const lines = marketplaces.map(m => ` ${m.name} ${m.sourceUri}`);
|
|
1494
|
+
runtime.ctx.showStatus(
|
|
1495
|
+
`Marketplaces:\n${lines.join("\n")}\n\nUse /marketplace discover to browse plugins, or /marketplace help for all commands`,
|
|
1496
|
+
);
|
|
1497
|
+
}
|
|
1498
|
+
break;
|
|
1499
|
+
}
|
|
1500
|
+
}
|
|
1501
|
+
} catch (err) {
|
|
1502
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1503
|
+
runtime.ctx.showStatus(`Marketplace error: ${msg}`);
|
|
1504
|
+
}
|
|
1505
|
+
},
|
|
1506
|
+
},
|
|
1507
|
+
{
|
|
1508
|
+
name: "plugins",
|
|
1509
|
+
description: "View and manage installed plugins",
|
|
1510
|
+
acpDescription: "Manage plugins",
|
|
1511
|
+
acpInputHint: "[list|enable|disable]",
|
|
1512
|
+
subcommands: [
|
|
1513
|
+
{ name: "list", description: "List all installed plugins (npm + marketplace)" },
|
|
1514
|
+
{ name: "enable", description: "Enable a marketplace plugin", usage: "<name@marketplace>" },
|
|
1515
|
+
{ name: "disable", description: "Disable a marketplace plugin", usage: "<name@marketplace>" },
|
|
1516
|
+
],
|
|
1517
|
+
allowArgs: true,
|
|
1518
|
+
handle: async (command, runtime) => {
|
|
1519
|
+
const { verb, rest } = parseSubcommand(command.args);
|
|
1520
|
+
try {
|
|
1521
|
+
if (verb === "enable" || verb === "disable") {
|
|
1522
|
+
const parsed = parsePluginScopeArgs(
|
|
1523
|
+
rest,
|
|
1524
|
+
`Usage: /plugins ${verb} [--scope user|project] <name@marketplace>`,
|
|
1525
|
+
);
|
|
1526
|
+
if ("error" in parsed) return usage(parsed.error, runtime);
|
|
1527
|
+
const manager = await createMarketplaceManager(runtime);
|
|
1528
|
+
const isEnable = verb === "enable";
|
|
1529
|
+
await manager.setPluginEnabled(parsed.pluginId, isEnable, parsed.scope);
|
|
1530
|
+
await runtime.reloadPlugins();
|
|
1531
|
+
await runtime.output(`${isEnable ? "Enabled" : "Disabled"} ${parsed.pluginId}`);
|
|
1532
|
+
return commandConsumed();
|
|
1533
|
+
}
|
|
1534
|
+
// Default: list
|
|
1535
|
+
const lines: string[] = [];
|
|
1536
|
+
const npmManager = new PluginManager();
|
|
1537
|
+
const npmPlugins = await npmManager.list();
|
|
1538
|
+
if (npmPlugins.length > 0) {
|
|
1539
|
+
lines.push("npm plugins:");
|
|
1540
|
+
for (const plugin of npmPlugins) {
|
|
1541
|
+
const status = plugin.enabled === false ? " (disabled)" : "";
|
|
1542
|
+
lines.push(` ${plugin.name}@${plugin.version}${status}`);
|
|
1543
|
+
}
|
|
1544
|
+
}
|
|
1545
|
+
|
|
1546
|
+
const marketplaceManager = await createMarketplaceManager(runtime);
|
|
1547
|
+
const marketplacePlugins = await marketplaceManager.listInstalledPlugins();
|
|
1548
|
+
if (marketplacePlugins.length > 0) {
|
|
1549
|
+
if (lines.length > 0) lines.push("");
|
|
1550
|
+
lines.push("marketplace plugins:");
|
|
1551
|
+
for (const plugin of marketplacePlugins) {
|
|
1552
|
+
const entry = plugin.entries[0];
|
|
1553
|
+
const status = entry?.enabled === false ? " (disabled)" : "";
|
|
1554
|
+
const shadowed = plugin.shadowedBy ? " [shadowed]" : "";
|
|
1555
|
+
lines.push(` ${plugin.id} v${entry?.version ?? "?"}${status} [${plugin.scope}]${shadowed}`);
|
|
1556
|
+
}
|
|
1557
|
+
}
|
|
1558
|
+
|
|
1559
|
+
await runtime.output(lines.length === 0 ? "No plugins installed" : lines.join("\n"));
|
|
1560
|
+
return commandConsumed();
|
|
1561
|
+
} catch (err) {
|
|
1562
|
+
return usage(`Plugin error: ${errorMessage(err)}`, runtime);
|
|
1563
|
+
}
|
|
1564
|
+
},
|
|
1565
|
+
handleTui: async (command, runtime) => {
|
|
1566
|
+
runtime.ctx.editor.setText("");
|
|
1567
|
+
const args = command.args.trim().split(/\s+/);
|
|
1568
|
+
const sub = args[0] || "list";
|
|
1569
|
+
const rest = args.slice(1).join(" ").trim();
|
|
1570
|
+
|
|
1571
|
+
try {
|
|
1572
|
+
const mgr = new MarketplaceManager({
|
|
1573
|
+
marketplacesRegistryPath: getMarketplacesRegistryPath(),
|
|
1574
|
+
installedRegistryPath: getInstalledPluginsRegistryPath(),
|
|
1575
|
+
projectInstalledRegistryPath: await resolveOrDefaultProjectRegistryPath(
|
|
1576
|
+
runtime.ctx.sessionManager.getCwd(),
|
|
1577
|
+
),
|
|
1578
|
+
marketplacesCacheDir: getMarketplacesCacheDir(),
|
|
1579
|
+
pluginsCacheDir: getPluginsCacheDir(),
|
|
1580
|
+
clearPluginRootsCache: clearPluginRootsAndCaches,
|
|
1581
|
+
});
|
|
1582
|
+
|
|
1583
|
+
switch (sub) {
|
|
1584
|
+
case "enable":
|
|
1585
|
+
case "disable": {
|
|
1586
|
+
const parsed = parsePluginScopeArgs(
|
|
1587
|
+
rest ?? "",
|
|
1588
|
+
`Usage: /plugins ${sub} [--scope user|project] <name@marketplace>`,
|
|
1589
|
+
);
|
|
1590
|
+
if ("error" in parsed) {
|
|
1591
|
+
runtime.ctx.showStatus(parsed.error);
|
|
1592
|
+
return;
|
|
1593
|
+
}
|
|
1594
|
+
const isEnable = sub === "enable";
|
|
1595
|
+
await mgr.setPluginEnabled(parsed.pluginId, isEnable, parsed.scope);
|
|
1596
|
+
runtime.ctx.showStatus(`${isEnable ? "Enabled" : "Disabled"} ${parsed.pluginId}`);
|
|
1597
|
+
break;
|
|
1598
|
+
}
|
|
1599
|
+
default: {
|
|
1600
|
+
const lines: string[] = [];
|
|
1601
|
+
|
|
1602
|
+
const npm = new PluginManager();
|
|
1603
|
+
const npmPlugins = await npm.list();
|
|
1604
|
+
if (npmPlugins.length > 0) {
|
|
1605
|
+
lines.push("npm plugins:");
|
|
1606
|
+
for (const p of npmPlugins) {
|
|
1607
|
+
const status = p.enabled === false ? " (disabled)" : "";
|
|
1608
|
+
lines.push(` ${p.name}@${p.version}${status}`);
|
|
1609
|
+
}
|
|
1610
|
+
}
|
|
1611
|
+
|
|
1612
|
+
const mktPlugins = await mgr.listInstalledPlugins();
|
|
1613
|
+
if (mktPlugins.length > 0) {
|
|
1614
|
+
if (lines.length > 0) lines.push("");
|
|
1615
|
+
lines.push("marketplace plugins:");
|
|
1616
|
+
for (const p of mktPlugins) {
|
|
1617
|
+
const entry = p.entries[0];
|
|
1618
|
+
const status = entry?.enabled === false ? " (disabled)" : "";
|
|
1619
|
+
const shadowed = p.shadowedBy ? " [shadowed]" : "";
|
|
1620
|
+
lines.push(` ${p.id} v${entry?.version ?? "?"}${status} [${p.scope}]${shadowed}`);
|
|
1621
|
+
}
|
|
1622
|
+
}
|
|
1623
|
+
|
|
1624
|
+
if (lines.length === 0) {
|
|
1625
|
+
runtime.ctx.showStatus("No plugins installed");
|
|
1626
|
+
} else {
|
|
1627
|
+
runtime.ctx.showStatus(lines.join("\n"));
|
|
1628
|
+
}
|
|
1629
|
+
break;
|
|
1630
|
+
}
|
|
1631
|
+
}
|
|
1632
|
+
} catch (err) {
|
|
1633
|
+
runtime.ctx.showStatus(`Plugin error: ${err}`);
|
|
1634
|
+
}
|
|
1635
|
+
},
|
|
1636
|
+
},
|
|
1637
|
+
{
|
|
1638
|
+
name: "reload-plugins",
|
|
1639
|
+
description: "Reload all plugins (skills, commands, hooks, tools, agents, MCP)",
|
|
1640
|
+
acpDescription: "Reload all plugins",
|
|
1641
|
+
handle: async (_command, runtime) => {
|
|
1642
|
+
await runtime.reloadPlugins();
|
|
1643
|
+
await runtime.output("Plugins reloaded.");
|
|
1644
|
+
return commandConsumed();
|
|
1645
|
+
},
|
|
1646
|
+
handleTui: async (_command, runtime) => {
|
|
1647
|
+
// Invalidate registry fs caches and the plugin roots cache so
|
|
1648
|
+
// listClaudePluginRoots re-reads from disk on next access.
|
|
1649
|
+
const projectPath = await resolveActiveProjectRegistryPath(runtime.ctx.sessionManager.getCwd());
|
|
1650
|
+
clearPluginRootsAndCaches(projectPath ? [projectPath] : undefined);
|
|
1651
|
+
await runtime.ctx.refreshSlashCommandState();
|
|
1652
|
+
await runtime.ctx.session.refreshSshTool({ activateIfAvailable: true });
|
|
1653
|
+
runtime.ctx.showStatus("Plugins reloaded.");
|
|
1654
|
+
runtime.ctx.editor.setText("");
|
|
1655
|
+
},
|
|
1656
|
+
},
|
|
1657
|
+
{
|
|
1658
|
+
name: "force",
|
|
1659
|
+
description: "Force next turn to use a specific tool",
|
|
1660
|
+
aliases: ["force:"],
|
|
1661
|
+
inlineHint: "<tool-name> [prompt]",
|
|
1662
|
+
allowArgs: true,
|
|
1663
|
+
handle: async (command, runtime) => {
|
|
1664
|
+
const spaceIdx = command.args.indexOf(" ");
|
|
1665
|
+
const toolName = spaceIdx === -1 ? command.args : command.args.slice(0, spaceIdx);
|
|
1666
|
+
const prompt = spaceIdx === -1 ? "" : command.args.slice(spaceIdx + 1).trim();
|
|
1667
|
+
if (!toolName) return usage("Usage: /force:<tool-name> [prompt]", runtime);
|
|
1668
|
+
try {
|
|
1669
|
+
runtime.session.setForcedToolChoice(toolName);
|
|
1670
|
+
} catch (err) {
|
|
1671
|
+
return usage(errorMessage(err), runtime);
|
|
1672
|
+
}
|
|
1673
|
+
await runtime.output(`Next turn forced to use ${toolName}.`);
|
|
1674
|
+
return prompt ? { prompt } : commandConsumed();
|
|
1675
|
+
},
|
|
1676
|
+
handleTui: (command, runtime) => {
|
|
1677
|
+
const spaceIdx = command.args.indexOf(" ");
|
|
1678
|
+
const toolName = spaceIdx === -1 ? command.args : command.args.slice(0, spaceIdx);
|
|
1679
|
+
const prompt = spaceIdx === -1 ? "" : command.args.slice(spaceIdx + 1).trim();
|
|
1680
|
+
|
|
1681
|
+
if (!toolName) {
|
|
1682
|
+
runtime.ctx.showError("Usage: /force:<tool-name> [prompt]");
|
|
1683
|
+
runtime.ctx.editor.setText("");
|
|
1684
|
+
return;
|
|
1685
|
+
}
|
|
1686
|
+
|
|
1687
|
+
try {
|
|
1688
|
+
runtime.ctx.session.setForcedToolChoice(toolName);
|
|
1689
|
+
runtime.ctx.showStatus(`Next turn forced to use ${toolName}.`);
|
|
1690
|
+
} catch (error) {
|
|
1691
|
+
runtime.ctx.showError(errorMessage(error));
|
|
1692
|
+
runtime.ctx.editor.setText("");
|
|
1693
|
+
return;
|
|
1694
|
+
}
|
|
1695
|
+
|
|
1696
|
+
runtime.ctx.editor.setText("");
|
|
1697
|
+
|
|
1698
|
+
// If a prompt was provided, pass it through as input
|
|
1699
|
+
if (prompt) return { prompt };
|
|
1700
|
+
},
|
|
1701
|
+
},
|
|
1702
|
+
{
|
|
1703
|
+
name: "quit",
|
|
1704
|
+
description: "Quit the application",
|
|
1705
|
+
handleTui: shutdownHandlerTui,
|
|
1706
|
+
},
|
|
1707
|
+
];
|
|
1708
|
+
|
|
1709
|
+
const BUILTIN_SLASH_COMMAND_LOOKUP = new Map<string, SlashCommandSpec>();
|
|
1710
|
+
for (const command of BUILTIN_SLASH_COMMAND_REGISTRY) {
|
|
1711
|
+
BUILTIN_SLASH_COMMAND_LOOKUP.set(command.name, command);
|
|
1712
|
+
for (const alias of command.aliases ?? []) {
|
|
1713
|
+
BUILTIN_SLASH_COMMAND_LOOKUP.set(alias, command);
|
|
1714
|
+
}
|
|
1715
|
+
}
|
|
1716
|
+
|
|
1717
|
+
export const BUILTIN_SLASH_COMMAND_RESERVED_NAMES: ReadonlySet<string> = new Set(BUILTIN_SLASH_COMMAND_LOOKUP.keys());
|
|
1718
|
+
|
|
1719
|
+
/** Builtin command metadata used for slash-command autocomplete and help text. */
|
|
1720
|
+
export const BUILTIN_SLASH_COMMAND_DEFS: ReadonlyArray<BuiltinSlashCommand> = BUILTIN_SLASH_COMMAND_REGISTRY.map(
|
|
1721
|
+
command => ({
|
|
1722
|
+
name: command.name,
|
|
1723
|
+
aliases: command.aliases,
|
|
1724
|
+
description: command.description,
|
|
1725
|
+
subcommands: command.subcommands,
|
|
1726
|
+
inlineHint: command.inlineHint,
|
|
1727
|
+
}),
|
|
1728
|
+
);
|
|
1729
|
+
|
|
1730
|
+
/**
|
|
1731
|
+
* Unified registry exposed for cross-mode tooling. Each spec carries at least
|
|
1732
|
+
* one of `handle` / `handleTui`. The TUI dispatcher prefers `handleTui`; the
|
|
1733
|
+
* ACP dispatcher requires `handle` and skips TUI-only entries.
|
|
1734
|
+
*/
|
|
1735
|
+
export const BUILTIN_SLASH_COMMANDS_INTERNAL: ReadonlyArray<SlashCommandSpec> = BUILTIN_SLASH_COMMAND_REGISTRY;
|
|
1736
|
+
|
|
1737
|
+
/**
|
|
1738
|
+
* Execute a builtin slash command in the interactive TUI.
|
|
1739
|
+
*
|
|
1740
|
+
* Returns `false` when no builtin matched. Returns `true` when a command
|
|
1741
|
+
* consumed the input entirely. Returns a `string` when the command was handled
|
|
1742
|
+
* but remaining text should be sent as a prompt.
|
|
1743
|
+
*/
|
|
1744
|
+
export async function executeBuiltinSlashCommand(
|
|
1745
|
+
text: string,
|
|
1746
|
+
runtime: BuiltinSlashCommandRuntime,
|
|
1747
|
+
): Promise<string | boolean> {
|
|
1748
|
+
const parsed = parseSlashCommand(text);
|
|
1749
|
+
if (!parsed) return false;
|
|
1750
|
+
|
|
1751
|
+
const command = BUILTIN_SLASH_COMMAND_LOOKUP.get(parsed.name);
|
|
1752
|
+
if (!command) return false;
|
|
1753
|
+
if (parsed.args.length > 0 && !command.allowArgs) {
|
|
1754
|
+
return false;
|
|
1755
|
+
}
|
|
1756
|
+
if (command.handleTui) {
|
|
1757
|
+
const result = await command.handleTui(parsed, runtime);
|
|
1758
|
+
if (result && typeof result === "object" && "prompt" in result) return result.prompt;
|
|
1759
|
+
return true;
|
|
1760
|
+
}
|
|
1761
|
+
if (command.handle) {
|
|
1762
|
+
// No TUI-specific override → adapt the ACP/text-mode `handle` to the
|
|
1763
|
+
// TUI by routing `runtime.output` through `ctx.showStatus`, clearing
|
|
1764
|
+
// the editor after the call, and reusing the active session's plugin
|
|
1765
|
+
// reload pipeline. Spec authors get a single body usable from either
|
|
1766
|
+
// dispatcher without forcing every TUI test to construct the full
|
|
1767
|
+
// `SlashCommandRuntime` shape.
|
|
1768
|
+
const ctx = runtime.ctx;
|
|
1769
|
+
const adapted: SlashCommandRuntime = {
|
|
1770
|
+
session: ctx.session,
|
|
1771
|
+
sessionManager: ctx.sessionManager,
|
|
1772
|
+
settings: ctx.settings,
|
|
1773
|
+
cwd: ctx.sessionManager.getCwd(),
|
|
1774
|
+
output: (text: string) => {
|
|
1775
|
+
ctx.showStatus(text);
|
|
1776
|
+
},
|
|
1777
|
+
refreshCommands: () => ctx.refreshSlashCommandState(),
|
|
1778
|
+
reloadPlugins: async () => {
|
|
1779
|
+
const projectPath = await resolveActiveProjectRegistryPath(ctx.sessionManager.getCwd());
|
|
1780
|
+
clearPluginRootsAndCaches(projectPath ? [projectPath] : undefined);
|
|
1781
|
+
await ctx.refreshSlashCommandState();
|
|
1782
|
+
await ctx.session.refreshSshTool({ activateIfAvailable: true });
|
|
1783
|
+
},
|
|
1784
|
+
};
|
|
1785
|
+
const result = await command.handle(parsed, adapted);
|
|
1786
|
+
ctx.editor.setText("");
|
|
1787
|
+
if (result && typeof result === "object" && "prompt" in result) return result.prompt;
|
|
1788
|
+
return true;
|
|
1789
|
+
}
|
|
1790
|
+
return false;
|
|
1791
|
+
}
|
|
1792
|
+
|
|
1793
|
+
/** Look up a unified spec by name or alias. Used by the ACP dispatcher. */
|
|
1794
|
+
export function lookupBuiltinSlashCommand(name: string): SlashCommandSpec | undefined {
|
|
1795
|
+
return BUILTIN_SLASH_COMMAND_LOOKUP.get(name);
|
|
1796
|
+
}
|
|
1797
|
+
|
|
1798
|
+
export type { ParsedSlashCommand, SlashCommandResult, SlashCommandRuntime, SlashCommandSpec, TuiSlashCommandRuntime };
|