oma-coding-agent 1.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12164 -0
- package/README.md +35 -0
- package/dist/cli.js +18266 -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 +573 -0
- package/scripts/bench-guard.ts +71 -0
- package/scripts/build-binary.ts +108 -0
- package/scripts/bundle-dist.ts +110 -0
- package/scripts/embed-mupdf-wasm.ts +67 -0
- package/scripts/format-prompts.ts +68 -0
- package/scripts/generate-docs-index.ts +56 -0
- package/scripts/generate-share-viewer.ts +34 -0
- package/scripts/measure-prompt-tokens.ts +63 -0
- package/scripts/omp +42 -0
- package/scripts/omp.ts +19 -0
- package/src/advisor/__tests__/advisor.test.ts +915 -0
- package/src/advisor/advise-tool.ts +165 -0
- package/src/advisor/index.ts +4 -0
- package/src/advisor/runtime.ts +270 -0
- package/src/advisor/transcript-recorder.ts +136 -0
- package/src/advisor/watchdog.ts +83 -0
- package/src/async/index.ts +1 -0
- package/src/async/job-manager.ts +674 -0
- package/src/auto-thinking/classifier.ts +190 -0
- package/src/autolearn/controller.ts +139 -0
- package/src/autolearn/managed-skills.ts +255 -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 +700 -0
- package/src/autoresearch/tools/init-experiment.ts +269 -0
- package/src/autoresearch/tools/log-experiment.ts +521 -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/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 +76 -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 +361 -0
- package/src/cli/auth-broker-cli.ts +893 -0
- package/src/cli/auth-gateway-cli.ts +608 -0
- package/src/cli/bench-cli.ts +552 -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 +858 -0
- package/src/cli/extension-flags.ts +48 -0
- package/src/cli/file-processor.ts +133 -0
- package/src/cli/flag-tables.ts +280 -0
- package/src/cli/gallery-cli.ts +231 -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/models-cli.ts +427 -0
- package/src/cli/plugin-cli.ts +996 -0
- package/src/cli/profile-alias.ts +338 -0
- package/src/cli/profile-bootstrap.ts +243 -0
- package/src/cli/read-cli.ts +57 -0
- package/src/cli/session-picker.ts +80 -0
- package/src/cli/setup-cli.ts +332 -0
- package/src/cli/setup-model-picker.ts +43 -0
- package/src/cli/shell-cli.ts +176 -0
- package/src/cli/ssh-cli.ts +179 -0
- package/src/cli/startup-cwd.ts +58 -0
- package/src/cli/stats-cli.ts +229 -0
- package/src/cli/tiny-models-cli.ts +127 -0
- package/src/cli/ttsr-cli.ts +995 -0
- package/src/cli/update-cli.ts +671 -0
- package/src/cli/usage-cli.ts +774 -0
- package/src/cli/web-search-cli.ts +132 -0
- package/src/cli/worktree-cli.ts +291 -0
- package/src/cli-commands.ts +85 -0
- package/src/cli.ts +326 -0
- package/src/collab/crypto.ts +63 -0
- package/src/collab/guest.ts +450 -0
- package/src/collab/host.ts +577 -0
- package/src/collab/protocol.ts +274 -0
- package/src/collab/relay-client.ts +216 -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/bench.ts +42 -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/join.ts +39 -0
- package/src/commands/launch.ts +182 -0
- package/src/commands/models.ts +61 -0
- package/src/commands/plugin.ts +78 -0
- package/src/commands/read.ts +38 -0
- package/src/commands/say.ts +102 -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/token.ts +108 -0
- package/src/commands/ttsr.ts +125 -0
- package/src/commands/update.ts +21 -0
- package/src/commands/usage.ts +43 -0
- package/src/commands/web-search.ts +42 -0
- package/src/commands/worktree.ts +56 -0
- package/src/commit/agentic/agent.ts +318 -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 +149 -0
- package/src/commit/agentic/tools/git-file-diff.ts +191 -0
- package/src/commit/agentic/tools/git-hunk.ts +52 -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 +147 -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 +11 -0
- package/src/commit/agentic/tools/split-commit.ts +241 -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 +107 -0
- package/src/commit/analysis/validation.ts +66 -0
- package/src/commit/changelog/detect.ts +40 -0
- package/src/commit/changelog/generate.ts +101 -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 +89 -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 +70 -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 +67 -0
- package/src/config/append-only-context-mode.ts +76 -0
- package/src/config/config-file.ts +315 -0
- package/src/config/file-lock.ts +164 -0
- package/src/config/keybindings.ts +634 -0
- package/src/config/mcp-schema.json +238 -0
- package/src/config/model-discovery.ts +589 -0
- package/src/config/model-registry.ts +2260 -0
- package/src/config/model-resolver.ts +1819 -0
- package/src/config/model-roles.ts +99 -0
- package/src/config/models-config-schema.ts +266 -0
- package/src/config/models-config.ts +131 -0
- package/src/config/prompt-templates.ts +185 -0
- package/src/config/resolve-config-value.ts +94 -0
- package/src/config/settings-schema.ts +4740 -0
- package/src/config/settings.ts +1243 -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 +559 -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 +294 -0
- package/src/debug/raw-sse.ts +292 -0
- package/src/debug/remote-debugger.ts +151 -0
- package/src/debug/report-bundle.ts +375 -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 +63 -0
- package/src/discovery/builtin-rules/low-end/no-hallucinated-apis.md +14 -0
- package/src/discovery/builtin-rules/low-end/no-hallucinated-paths.md +14 -0
- package/src/discovery/builtin-rules/low-end/no-premature-completion.md +14 -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 +65 -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-inline-cast-access.md +55 -0
- package/src/discovery/builtin-rules/ts-no-return-type.md +44 -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 +934 -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 +337 -0
- package/src/discovery/helpers.ts +1092 -0
- package/src/discovery/index.ts +81 -0
- package/src/discovery/mcp-json.ts +172 -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 +143 -0
- package/src/edit/hashline/block-resolver.ts +33 -0
- package/src/edit/hashline/diff.ts +290 -0
- package/src/edit/hashline/execute.ts +237 -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 +19 -0
- package/src/edit/index.ts +620 -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 +1888 -0
- package/src/edit/modes/replace.ts +1133 -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 +823 -0
- package/src/edit/streaming.ts +517 -0
- package/src/eval/__tests__/agent-bridge.test.ts +769 -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 +291 -0
- package/src/eval/__tests__/kernel-spawn.test.ts +103 -0
- package/src/eval/__tests__/prelude-agent.test.ts +73 -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 +211 -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 +621 -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 +307 -0
- package/src/eval/js/shared/rewrite-imports.ts +532 -0
- package/src/eval/js/shared/runtime.ts +580 -0
- package/src/eval/js/shared/types.ts +18 -0
- package/src/eval/js/tool-bridge.ts +163 -0
- package/src/eval/js/worker-core.ts +151 -0
- package/src/eval/js/worker-entry.ts +37 -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 +683 -0
- package/src/eval/py/prelude.ts +3 -0
- package/src/eval/py/runner.py +1177 -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 +434 -0
- package/src/exec/exec.ts +53 -0
- package/src/exec/non-interactive-env.ts +119 -0
- package/src/export/custom-share.ts +65 -0
- package/src/export/html/index.ts +266 -0
- package/src/export/html/share-loader.js +102 -0
- package/src/export/html/template.css +1337 -0
- package/src/export/html/template.html +49 -0
- package/src/export/html/template.js +1626 -0
- package/src/export/html/tool-views.generated.js +37 -0
- package/src/export/html/vendor/highlight.min.js +1213 -0
- package/src/export/html/vendor/marked.min.js +6 -0
- package/src/export/share.ts +268 -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 +698 -0
- package/src/extensibility/custom-commands/index.ts +2 -0
- package/src/extensibility/custom-commands/loader.ts +242 -0
- package/src/extensibility/custom-commands/types.ts +119 -0
- package/src/extensibility/custom-tools/index.ts +7 -0
- package/src/extensibility/custom-tools/loader.ts +268 -0
- package/src/extensibility/custom-tools/types.ts +277 -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 +587 -0
- package/src/extensibility/extensions/model-api.ts +41 -0
- package/src/extensibility/extensions/runner.ts +989 -0
- package/src/extensibility/extensions/types.ts +1394 -0
- package/src/extensibility/extensions/wrapper.ts +259 -0
- package/src/extensibility/hooks/index.ts +6 -0
- package/src/extensibility/hooks/loader.ts +262 -0
- package/src/extensibility/hooks/runner.ts +425 -0
- package/src/extensibility/hooks/tool-wrapper.ts +107 -0
- package/src/extensibility/hooks/types.ts +613 -0
- package/src/extensibility/legacy-pi-ai-shim.ts +61 -0
- package/src/extensibility/legacy-pi-coding-agent-shim.ts +128 -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 +712 -0
- package/src/extensibility/plugins/loader.ts +458 -0
- package/src/extensibility/plugins/manager.ts +1026 -0
- package/src/extensibility/plugins/marketplace/cache.ts +136 -0
- package/src/extensibility/plugins/marketplace/fetcher.ts +315 -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/runtime-config.ts +9 -0
- package/src/extensibility/plugins/types.ts +194 -0
- package/src/extensibility/shared-events.ts +367 -0
- package/src/extensibility/skills.ts +408 -0
- package/src/extensibility/slash-commands.ts +131 -0
- package/src/extensibility/tool-proxy.ts +28 -0
- package/src/extensibility/typebox.ts +945 -0
- package/src/extensibility/utils.ts +44 -0
- package/src/goals/guided-setup.ts +142 -0
- package/src/goals/index.ts +3 -0
- package/src/goals/runtime.ts +521 -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 +623 -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 +492 -0
- package/src/hindsight/transcript.ts +71 -0
- package/src/index.ts +66 -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.txt +2 -0
- package/src/internal-urls/docs-index.ts +102 -0
- package/src/internal-urls/history-protocol.ts +118 -0
- package/src/internal-urls/index.ts +25 -0
- package/src/internal-urls/issue-pr-protocol.ts +594 -0
- package/src/internal-urls/json-query.ts +126 -0
- package/src/internal-urls/local-protocol.ts +309 -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 +94 -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 +311 -0
- package/src/lib/xai-http.ts +124 -0
- package/src/lsp/client.ts +1217 -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 +85 -0
- package/src/lsp/clients/swiftlint-client.ts +120 -0
- package/src/lsp/config.ts +502 -0
- package/src/lsp/defaults.json +499 -0
- package/src/lsp/diagnostics-ledger.ts +51 -0
- package/src/lsp/edits.ts +267 -0
- package/src/lsp/format-options.ts +119 -0
- package/src/lsp/index.ts +2480 -0
- package/src/lsp/lspmux.ts +233 -0
- package/src/lsp/render.ts +668 -0
- package/src/lsp/startup-events.ts +13 -0
- package/src/lsp/types.ts +444 -0
- package/src/lsp/utils.ts +718 -0
- package/src/main.ts +1421 -0
- package/src/markit/NOTICE +32 -0
- package/src/markit/converters/docx.ts +56 -0
- package/src/markit/converters/epub.ts +136 -0
- package/src/markit/converters/mammoth.d.ts +24 -0
- package/src/markit/converters/pdf/columns.ts +103 -0
- package/src/markit/converters/pdf/extract.ts +574 -0
- package/src/markit/converters/pdf/grid.ts +780 -0
- package/src/markit/converters/pdf/headers.ts +106 -0
- package/src/markit/converters/pdf/index.ts +146 -0
- package/src/markit/converters/pdf/render.ts +501 -0
- package/src/markit/converters/pdf/types.ts +84 -0
- package/src/markit/converters/pptx.ts +325 -0
- package/src/markit/converters/xlsx.ts +173 -0
- package/src/markit/index.ts +2 -0
- package/src/markit/registry.ts +59 -0
- package/src/markit/types.ts +35 -0
- package/src/mcp/client.ts +509 -0
- package/src/mcp/config-writer.ts +229 -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 +1326 -0
- package/src/mcp/oauth-credentials.ts +104 -0
- package/src/mcp/oauth-discovery.ts +467 -0
- package/src/mcp/oauth-flow.ts +555 -0
- package/src/mcp/render.ts +155 -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/startup-events.ts +21 -0
- package/src/mcp/timeout.ts +59 -0
- package/src/mcp/tool-bridge.ts +429 -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 +606 -0
- package/src/mcp/types.ts +427 -0
- package/src/memories/index.ts +1281 -0
- package/src/memories/storage.ts +578 -0
- package/src/memory-backend/index.ts +18 -0
- package/src/memory-backend/local-backend.ts +45 -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 +612 -0
- package/src/mnemopi/config.ts +265 -0
- package/src/mnemopi/embed-client.ts +401 -0
- package/src/mnemopi/embed-protocol.ts +35 -0
- package/src/mnemopi/embed-worker.ts +113 -0
- package/src/mnemopi/index.ts +3 -0
- package/src/mnemopi/state.ts +657 -0
- package/src/modes/acp/acp-agent.ts +2362 -0
- package/src/modes/acp/acp-client-bridge.ts +154 -0
- package/src/modes/acp/acp-event-mapper.ts +933 -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/__tests__/skill-message.test.ts +92 -0
- package/src/modes/components/advisor-message.ts +99 -0
- package/src/modes/components/agent-dashboard.ts +1206 -0
- package/src/modes/components/agent-hub.ts +566 -0
- package/src/modes/components/agent-transcript-viewer.ts +461 -0
- package/src/modes/components/assistant-message.ts +612 -0
- package/src/modes/components/background-tan-message.ts +36 -0
- package/src/modes/components/bash-execution.ts +220 -0
- package/src/modes/components/bordered-loader.ts +41 -0
- package/src/modes/components/btw-panel.ts +112 -0
- package/src/modes/components/cache-invalidation-marker.ts +110 -0
- package/src/modes/components/chat-block.ts +111 -0
- package/src/modes/components/chat-transcript-builder.ts +476 -0
- package/src/modes/components/collab-prompt-message.ts +32 -0
- package/src/modes/components/compaction-summary-message.ts +215 -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.test.ts +142 -0
- package/src/modes/components/custom-editor.ts +620 -0
- package/src/modes/components/custom-message.ts +67 -0
- package/src/modes/components/diff.ts +254 -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 +321 -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 +275 -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 +67 -0
- package/src/modes/components/hook-selector.ts +659 -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/logout-account-selector.ts +130 -0
- package/src/modes/components/mcp-add-wizard.ts +1360 -0
- package/src/modes/components/message-frame.ts +92 -0
- package/src/modes/components/model-selector.ts +1315 -0
- package/src/modes/components/oauth-selector.ts +457 -0
- package/src/modes/components/omfg-panel.ts +141 -0
- package/src/modes/components/overlay-box.ts +109 -0
- package/src/modes/components/plan-review-overlay.ts +847 -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 +739 -0
- package/src/modes/components/queue-mode-selector.ts +56 -0
- package/src/modes/components/read-tool-group.ts +676 -0
- package/src/modes/components/reset-usage-selector.ts +161 -0
- package/src/modes/components/segment-track.ts +89 -0
- package/src/modes/components/session-selector.ts +631 -0
- package/src/modes/components/settings-defs.ts +225 -0
- package/src/modes/components/settings-selector.ts +1095 -0
- package/src/modes/components/show-images-selector.ts +45 -0
- package/src/modes/components/skill-message.ts +110 -0
- package/src/modes/components/snapcompact-shape-preview-doc.md +18 -0
- package/src/modes/components/snapcompact-shape-preview.ts +192 -0
- package/src/modes/components/status-line/component.ts +1001 -0
- package/src/modes/components/status-line/context-thresholds.ts +78 -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 +616 -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 +124 -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 +24 -0
- package/src/modes/components/todo-reminder.ts +39 -0
- package/src/modes/components/tool-execution.ts +1165 -0
- package/src/modes/components/transcript-container.ts +806 -0
- package/src/modes/components/tree-selector.ts +994 -0
- package/src/modes/components/ttsr-notification.ts +123 -0
- package/src/modes/components/usage-row.ts +18 -0
- package/src/modes/components/user-message-selector.ts +227 -0
- package/src/modes/components/user-message.ts +68 -0
- package/src/modes/components/visual-truncate.ts +63 -0
- package/src/modes/components/welcome.ts +581 -0
- package/src/modes/controllers/btw-controller.ts +173 -0
- package/src/modes/controllers/command-controller-shared.ts +109 -0
- package/src/modes/controllers/command-controller.ts +1653 -0
- package/src/modes/controllers/event-controller.ts +1153 -0
- package/src/modes/controllers/extension-ui-controller.ts +893 -0
- package/src/modes/controllers/input-controller.ts +1627 -0
- package/src/modes/controllers/mcp-command-controller.ts +2162 -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 +1285 -0
- package/src/modes/controllers/session-focus-controller.ts +112 -0
- package/src/modes/controllers/ssh-command-controller.ts +384 -0
- package/src/modes/controllers/streaming-reveal.ts +295 -0
- package/src/modes/controllers/tan-command-controller.ts +190 -0
- package/src/modes/controllers/todo-command-controller.ts +485 -0
- package/src/modes/controllers/tool-args-reveal.ts +174 -0
- package/src/modes/data/emojis.json +1 -0
- package/src/modes/emoji-autocomplete.ts +285 -0
- package/src/modes/gradient-highlight.ts +99 -0
- package/src/modes/image-references.ts +137 -0
- package/src/modes/index.ts +17 -0
- package/src/modes/interactive-mode.ts +3940 -0
- package/src/modes/internal-url-autocomplete.ts +143 -0
- package/src/modes/loop-limit.ts +192 -0
- package/src/modes/magic-keywords.ts +42 -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 +130 -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 +995 -0
- package/src/modes/rpc/rpc-mode.ts +1156 -0
- package/src/modes/rpc/rpc-subagents.ts +265 -0
- package/src/modes/rpc/rpc-types.ts +487 -0
- package/src/modes/runtime-init.ts +142 -0
- package/src/modes/session-observer-registry.ts +215 -0
- package/src/modes/setup-version.ts +11 -0
- package/src/modes/setup-wizard/index.ts +101 -0
- package/src/modes/setup-wizard/lazy.ts +16 -0
- package/src/modes/setup-wizard/scenes/glyph.ts +114 -0
- package/src/modes/setup-wizard/scenes/outro.ts +35 -0
- package/src/modes/setup-wizard/scenes/providers.ts +103 -0
- package/src/modes/setup-wizard/scenes/sign-in.ts +286 -0
- package/src/modes/setup-wizard/scenes/splash.ts +201 -0
- package/src/modes/setup-wizard/scenes/theme.ts +326 -0
- package/src/modes/setup-wizard/scenes/types.ts +57 -0
- package/src/modes/setup-wizard/scenes/web-search.ts +145 -0
- package/src/modes/setup-wizard/startup-splash.ts +107 -0
- package/src/modes/setup-wizard/wizard-overlay.ts +334 -0
- package/src/modes/shared.ts +49 -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 +92 -0
- package/src/modes/theme/shimmer.ts +235 -0
- package/src/modes/theme/theme-schema.json +459 -0
- package/src/modes/theme/theme.ts +2915 -0
- package/src/modes/turn-budget.ts +31 -0
- package/src/modes/types.ts +406 -0
- package/src/modes/ultrathink.ts +41 -0
- package/src/modes/utils/context-usage.ts +432 -0
- package/src/modes/utils/copy-targets.ts +360 -0
- package/src/modes/utils/hotkeys-markdown.ts +62 -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 +886 -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 +45 -0
- package/src/prompts/advisor/advise-tool.md +3 -0
- package/src/prompts/advisor/system.md +113 -0
- package/src/prompts/agents/designer.md +74 -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 +54 -0
- package/src/prompts/agents/plan.md +48 -0
- package/src/prompts/agents/reviewer.md +139 -0
- package/src/prompts/agents/task.md +17 -0
- package/src/prompts/bench.md +12 -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/goals/guided-goal-interview.md +8 -0
- package/src/prompts/goals/guided-goal-system.md +12 -0
- package/src/prompts/low-end/system.md +47 -0
- package/src/prompts/memories/consolidation.md +30 -0
- package/src/prompts/memories/consolidation_system.md +4 -0
- package/src/prompts/memories/read-path.md +17 -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 +9 -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/autolearn-guidance-learn.md +1 -0
- package/src/prompts/system/autolearn-guidance.md +7 -0
- package/src/prompts/system/autolearn-nudge.md +3 -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-task.md +7 -0
- package/src/prompts/system/eager-todo.md +18 -0
- package/src/prompts/system/empty-stop-retry.md +4 -0
- package/src/prompts/system/irc-autoreply.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/personalities/default.md +18 -0
- package/src/prompts/system/personalities/friendly.md +17 -0
- package/src/prompts/system/personalities/pragmatic.md +15 -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/snapcompact-context-frames-note.md +1 -0
- package/src/prompts/system/snapcompact-context-stub.md +1 -0
- package/src/prompts/system/snapcompact-system-frames-note.md +1 -0
- package/src/prompts/system/snapcompact-system-stub.md +1 -0
- package/src/prompts/system/snapcompact-toolresult-note.md +1 -0
- package/src/prompts/system/subagent-system-prompt.md +71 -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 +251 -0
- package/src/prompts/system/tiny-title-system.md +8 -0
- package/src/prompts/system/title-marker-instruction.md +1 -0
- package/src/prompts/system/title-system-marker.md +16 -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/unexpected-stop-classifier.md +17 -0
- package/src/prompts/system/unexpected-stop-retry.md +4 -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 +22 -0
- package/src/prompts/tools/ast-edit.md +22 -0
- package/src/prompts/tools/ast-grep.md +25 -0
- package/src/prompts/tools/async-result.md +8 -0
- package/src/prompts/tools/bash.md +45 -0
- package/src/prompts/tools/browser.md +42 -0
- package/src/prompts/tools/checkpoint.md +15 -0
- package/src/prompts/tools/debug.md +17 -0
- package/src/prompts/tools/eval.md +70 -0
- package/src/prompts/tools/find.md +19 -0
- package/src/prompts/tools/github.md +17 -0
- package/src/prompts/tools/goal.md +11 -0
- package/src/prompts/tools/image-attachment-describe-system.md +8 -0
- package/src/prompts/tools/image-attachment-describe.md +10 -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 +22 -0
- package/src/prompts/tools/irc.md +33 -0
- package/src/prompts/tools/job.md +17 -0
- package/src/prompts/tools/learn.md +7 -0
- package/src/prompts/tools/lsp-late-diagnostic.md +8 -0
- package/src/prompts/tools/lsp.md +39 -0
- package/src/prompts/tools/manage-skill.md +9 -0
- package/src/prompts/tools/memory-edit.md +8 -0
- package/src/prompts/tools/patch.md +57 -0
- package/src/prompts/tools/read.md +76 -0
- package/src/prompts/tools/recall.md +5 -0
- package/src/prompts/tools/reflect.md +5 -0
- package/src/prompts/tools/replace.md +29 -0
- package/src/prompts/tools/resolve.md +4 -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 +22 -0
- package/src/prompts/tools/ssh.md +22 -0
- package/src/prompts/tools/task-summary.md +17 -0
- package/src/prompts/tools/task.md +91 -0
- package/src/prompts/tools/todo.md +39 -0
- package/src/prompts/tools/web-search.md +6 -0
- package/src/prompts/tools/write.md +14 -0
- package/src/registry/agent-lifecycle.ts +270 -0
- package/src/registry/agent-registry.ts +190 -0
- package/src/sdk.ts +2919 -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 +12539 -0
- package/src/session/agent-storage.ts +478 -0
- package/src/session/artifacts.ts +153 -0
- package/src/session/auth-broker-config.ts +92 -0
- package/src/session/auth-storage.ts +24 -0
- package/src/session/blob-store.ts +255 -0
- package/src/session/client-bridge.ts +85 -0
- package/src/session/codex-auto-reset.ts +202 -0
- package/src/session/compact-modes.ts +105 -0
- package/src/session/history-storage.ts +361 -0
- package/src/session/indexed-session-storage.ts +427 -0
- package/src/session/messages.ts +546 -0
- package/src/session/redis-session-storage.ts +170 -0
- package/src/session/session-context.ts +399 -0
- package/src/session/session-dump-format.ts +216 -0
- package/src/session/session-entries.ts +198 -0
- package/src/session/session-history-format.ts +308 -0
- package/src/session/session-listing.ts +588 -0
- package/src/session/session-loader.ts +93 -0
- package/src/session/session-manager.ts +1748 -0
- package/src/session/session-migrations.ts +78 -0
- package/src/session/session-paths.ts +193 -0
- package/src/session/session-persistence.ts +147 -0
- package/src/session/session-storage.ts +590 -0
- package/src/session/shake-types.ts +43 -0
- package/src/session/snapcompact-inline.ts +542 -0
- package/src/session/snapcompact-savings-journal.ts +113 -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 +290 -0
- package/src/session/unexpected-stop-classifier.ts +129 -0
- package/src/session/yield-queue.ts +183 -0
- package/src/slash-commands/acp-builtins.ts +70 -0
- package/src/slash-commands/available-commands.ts +105 -0
- package/src/slash-commands/builtin-registry.ts +2332 -0
- package/src/slash-commands/helpers/active-oauth-account.ts +44 -0
- package/src/slash-commands/helpers/collab-qrcode.ts +28 -0
- package/src/slash-commands/helpers/context-report.ts +66 -0
- package/src/slash-commands/helpers/format.ts +46 -0
- package/src/slash-commands/helpers/logout.ts +88 -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/reset-usage.ts +66 -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 +128 -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 +510 -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/startup-splash.ts +19 -0
- package/src/stt/asr-client.ts +521 -0
- package/src/stt/asr-protocol.ts +65 -0
- package/src/stt/asr-worker.ts +790 -0
- package/src/stt/downloader.ts +138 -0
- package/src/stt/endpointer.ts +259 -0
- package/src/stt/index.ts +7 -0
- package/src/stt/models.ts +150 -0
- package/src/stt/recorder.ts +538 -0
- package/src/stt/stt-controller.ts +380 -0
- package/src/stt/transcriber.ts +60 -0
- package/src/stt/wav.ts +173 -0
- package/src/system-prompt.ts +709 -0
- package/src/task/agents.ts +166 -0
- package/src/task/commands.ts +132 -0
- package/src/task/discovery.ts +122 -0
- package/src/task/executor.ts +2356 -0
- package/src/task/index.ts +1580 -0
- package/src/task/name-generator.ts +1577 -0
- package/src/task/omp-command.ts +26 -0
- package/src/task/output-manager.ts +93 -0
- package/src/task/parallel.ts +116 -0
- package/src/task/persisted-revive.ts +128 -0
- package/src/task/render.ts +1558 -0
- package/src/task/repair-args.ts +129 -0
- package/src/task/subprocess-tool-registry.ts +88 -0
- package/src/task/types.ts +401 -0
- package/src/task/worktree.ts +514 -0
- package/src/telemetry-export.ts +144 -0
- package/src/thinking.ts +187 -0
- package/src/tiny/device.ts +111 -0
- package/src/tiny/dtype.ts +101 -0
- package/src/tiny/models.ts +252 -0
- package/src/tiny/text.ts +169 -0
- package/src/tiny/title-client.ts +538 -0
- package/src/tiny/title-protocol.ts +56 -0
- package/src/tiny/worker.ts +491 -0
- package/src/tool-discovery/mode.ts +24 -0
- package/src/tool-discovery/tool-index.ts +271 -0
- package/src/tools/__tests__/json-tree.test.ts +35 -0
- package/src/tools/approval.ts +189 -0
- package/src/tools/ask.ts +977 -0
- package/src/tools/ast-edit.ts +700 -0
- package/src/tools/ast-grep.ts +483 -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 +1405 -0
- package/src/tools/browser/attach.ts +194 -0
- package/src/tools/browser/cmux/cmux-tab.ts +1264 -0
- package/src/tools/browser/cmux/rpc.ts +156 -0
- package/src/tools/browser/cmux/socket-client.ts +309 -0
- package/src/tools/browser/launch.ts +673 -0
- package/src/tools/browser/readable.ts +112 -0
- package/src/tools/browser/registry.ts +241 -0
- package/src/tools/browser/render.ts +221 -0
- package/src/tools/browser/tab-protocol.ts +107 -0
- package/src/tools/browser/tab-supervisor.ts +799 -0
- package/src/tools/browser/tab-worker-entry.ts +29 -0
- package/src/tools/browser/tab-worker.ts +1226 -0
- package/src/tools/browser.ts +403 -0
- package/src/tools/builtin-names.ts +34 -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 +1087 -0
- package/src/tools/eval-backends.ts +27 -0
- package/src/tools/eval-render.ts +762 -0
- package/src/tools/eval.ts +600 -0
- package/src/tools/fetch.ts +1902 -0
- package/src/tools/file-recorder.ts +35 -0
- package/src/tools/find.ts +629 -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 +3752 -0
- package/src/tools/github-cache.ts +663 -0
- package/src/tools/grouped-file-output.ts +210 -0
- package/src/tools/image-gen.ts +1586 -0
- package/src/tools/index.ts +649 -0
- package/src/tools/inspect-image-renderer.ts +132 -0
- package/src/tools/inspect-image.ts +260 -0
- package/src/tools/irc.ts +788 -0
- package/src/tools/job.ts +612 -0
- package/src/tools/json-tree.ts +260 -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/learn.ts +141 -0
- package/src/tools/list-limit.ts +40 -0
- package/src/tools/manage-skill.ts +100 -0
- package/src/tools/match-line-format.ts +20 -0
- package/src/tools/memory-edit.ts +59 -0
- package/src/tools/memory-recall.ts +102 -0
- package/src/tools/memory-reflect.ts +88 -0
- package/src/tools/memory-render.ts +202 -0
- package/src/tools/memory-retain.ts +89 -0
- package/src/tools/output-meta.ts +768 -0
- package/src/tools/output-schema-validator.ts +132 -0
- package/src/tools/path-utils.ts +1116 -0
- package/src/tools/plan-mode-guard.ts +142 -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 +208 -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 +3124 -0
- package/src/tools/render-utils.ts +895 -0
- package/src/tools/renderers.ts +86 -0
- package/src/tools/report-tool-issue.ts +530 -0
- package/src/tools/resolve.ts +302 -0
- package/src/tools/review.ts +251 -0
- package/src/tools/search-tool-bm25.ts +351 -0
- package/src/tools/search.ts +1583 -0
- package/src/tools/sqlite-reader.ts +828 -0
- package/src/tools/ssh.ts +369 -0
- package/src/tools/todo.ts +938 -0
- package/src/tools/tool-errors.ts +62 -0
- package/src/tools/tool-result.ts +102 -0
- package/src/tools/tool-timeouts.ts +30 -0
- package/src/tools/tts.ts +265 -0
- package/src/tools/write.ts +1182 -0
- package/src/tools/yield.ts +269 -0
- package/src/tts/downloader.ts +64 -0
- package/src/tts/index.ts +8 -0
- package/src/tts/models.ts +137 -0
- package/src/tts/player.ts +137 -0
- package/src/tts/runtime.ts +21 -0
- package/src/tts/streaming-player.ts +266 -0
- package/src/tts/tts-client.ts +642 -0
- package/src/tts/tts-protocol.ts +60 -0
- package/src/tts/tts-worker.ts +505 -0
- package/src/tts/vocalizer.ts +162 -0
- package/src/tts/wav.ts +58 -0
- package/src/tui/code-cell.ts +257 -0
- package/src/tui/file-list.ts +55 -0
- package/src/tui/hyperlink.ts +178 -0
- package/src/tui/index.ts +13 -0
- package/src/tui/output-block.ts +240 -0
- package/src/tui/status-line.ts +54 -0
- package/src/tui/tree-list.ts +133 -0
- package/src/tui/types.ts +15 -0
- package/src/tui/utils.ts +103 -0
- package/src/tui/width-aware-text.ts +58 -0
- package/src/utils/block-context.ts +312 -0
- package/src/utils/changelog.ts +132 -0
- package/src/utils/clipboard.ts +262 -0
- package/src/utils/command-args.ts +76 -0
- package/src/utils/commit-message-generator.ts +147 -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 +78 -0
- package/src/utils/file-display-mode.ts +45 -0
- package/src/utils/file-mentions.ts +284 -0
- package/src/utils/git.ts +1838 -0
- package/src/utils/image-loading.ts +231 -0
- package/src/utils/image-resize.ts +309 -0
- package/src/utils/image-vision-fallback.ts +197 -0
- package/src/utils/ipc.ts +38 -0
- package/src/utils/jj.ts +248 -0
- package/src/utils/lang-from-path.ts +244 -0
- package/src/utils/markit.ts +143 -0
- package/src/utils/mupdf-wasm-embed.ts +12 -0
- package/src/utils/open.ts +55 -0
- package/src/utils/qrcode.ts +535 -0
- package/src/utils/session-color.ts +142 -0
- package/src/utils/shell-snapshot.ts +187 -0
- package/src/utils/sixel.ts +69 -0
- package/src/utils/thinking-display.ts +11 -0
- package/src/utils/title-generator.ts +416 -0
- package/src/utils/tool-choice.ts +49 -0
- package/src/utils/tools-manager.ts +372 -0
- package/src/utils/turndown.ts +83 -0
- package/src/utils/zip.ts +1091 -0
- package/src/web/kagi.ts +304 -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 +652 -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 +800 -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 +354 -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 +317 -0
- package/src/web/search/provider.ts +169 -0
- package/src/web/search/providers/anthropic.ts +343 -0
- package/src/web/search/providers/base.ts +90 -0
- package/src/web/search/providers/brave.ts +152 -0
- package/src/web/search/providers/codex.ts +593 -0
- package/src/web/search/providers/exa.ts +400 -0
- package/src/web/search/providers/gemini.ts +518 -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-auth.ts +133 -0
- package/src/web/search/providers/perplexity.ts +866 -0
- package/src/web/search/providers/searxng.ts +325 -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 +462 -0
- package/src/web/search/utils.ts +17 -0
- package/src/workspace-tree.ts +326 -0
|
@@ -0,0 +1,2332 @@
|
|
|
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 { setNextRequestDebugPath } from "@oh-my-pi/pi-ai/utils/request-debug";
|
|
6
|
+
import { type AutocompleteItem, Spacer } from "@oh-my-pi/pi-tui";
|
|
7
|
+
import { APP_NAME, setProjectDir } from "@oh-my-pi/pi-utils";
|
|
8
|
+
import { COLLAB_GUEST_ALLOWED_COMMANDS, CollabGuestLink } from "../collab/guest";
|
|
9
|
+
import { CollabHost } from "../collab/host";
|
|
10
|
+
import type { SettingPath, SettingValue } from "../config/settings";
|
|
11
|
+
import { settings } from "../config/settings";
|
|
12
|
+
import {
|
|
13
|
+
clearPluginRootsAndCaches,
|
|
14
|
+
resolveActiveProjectRegistryPath,
|
|
15
|
+
resolveOrDefaultProjectRegistryPath,
|
|
16
|
+
} from "../discovery/helpers.js";
|
|
17
|
+
import { shareSession } from "../export/share";
|
|
18
|
+
import { PluginManager } from "../extensibility/plugins";
|
|
19
|
+
import {
|
|
20
|
+
getInstalledPluginsRegistryPath,
|
|
21
|
+
getMarketplacesCacheDir,
|
|
22
|
+
getMarketplacesRegistryPath,
|
|
23
|
+
getPluginsCacheDir,
|
|
24
|
+
MarketplaceManager,
|
|
25
|
+
} from "../extensibility/plugins/marketplace";
|
|
26
|
+
import { resolveMemoryBackend } from "../memory-backend";
|
|
27
|
+
import { theme } from "../modes/theme/theme";
|
|
28
|
+
import type { InteractiveModeContext } from "../modes/types";
|
|
29
|
+
import type { AgentSession, FreshSessionResult } from "../session/agent-session";
|
|
30
|
+
import { COMPACT_MODES, parseCompactArgs } from "../session/compact-modes";
|
|
31
|
+
import { formatShakeSummary, type ShakeMode } from "../session/shake-types";
|
|
32
|
+
import { urlHyperlinkAlways } from "../tui";
|
|
33
|
+
import { getChangelogPath, parseChangelog } from "../utils/changelog";
|
|
34
|
+
import { CollabQrCodeComponent } from "./helpers/collab-qrcode";
|
|
35
|
+
import { buildContextReportText } from "./helpers/context-report";
|
|
36
|
+
import { formatDuration } from "./helpers/format";
|
|
37
|
+
import { createMarketplaceManager } from "./helpers/marketplace-manager";
|
|
38
|
+
import { handleMcpAcp } from "./helpers/mcp";
|
|
39
|
+
import { commandConsumed, errorMessage, parseSlashCommand, parseSubcommand, usage } from "./helpers/parse";
|
|
40
|
+
import { describeRedeemOutcome, type ResetUsageAccount, toResetUsageAccounts } from "./helpers/reset-usage";
|
|
41
|
+
import { handleSshAcp } from "./helpers/ssh";
|
|
42
|
+
import { launchStatsDashboard, parseStatsDashboardArgs } from "./helpers/stats-dashboard";
|
|
43
|
+
import { handleTodoAcp } from "./helpers/todo";
|
|
44
|
+
import { buildUsageReportText } from "./helpers/usage-report";
|
|
45
|
+
import { parseMarketplaceInstallArgs, parsePluginScopeArgs } from "./marketplace-install-parser";
|
|
46
|
+
import type {
|
|
47
|
+
BuiltinSlashCommand,
|
|
48
|
+
ParsedSlashCommand,
|
|
49
|
+
SlashCommandResult,
|
|
50
|
+
SlashCommandRuntime,
|
|
51
|
+
SlashCommandSpec,
|
|
52
|
+
SubcommandDef,
|
|
53
|
+
TuiSlashCommandRuntime,
|
|
54
|
+
} from "./types";
|
|
55
|
+
|
|
56
|
+
export type { BuiltinSlashCommand, SubcommandDef } from "./types";
|
|
57
|
+
|
|
58
|
+
/** TUI-specific runtime accepted by `executeBuiltinSlashCommand`. */
|
|
59
|
+
export type BuiltinSlashCommandRuntime = TuiSlashCommandRuntime;
|
|
60
|
+
|
|
61
|
+
function refreshStatusLine(ctx: InteractiveModeContext): void {
|
|
62
|
+
ctx.statusLine.invalidate();
|
|
63
|
+
ctx.updateEditorTopBorder();
|
|
64
|
+
ctx.ui.requestRender();
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** `/fast status` label: "off", "on", or scope-qualified "on (… only)". */
|
|
68
|
+
function formatFastModeStatus(session: AgentSession): string {
|
|
69
|
+
if (!session.isFastModeEnabled()) return "off";
|
|
70
|
+
switch (session.serviceTier) {
|
|
71
|
+
case "openai-only":
|
|
72
|
+
return "on (OpenAI only)";
|
|
73
|
+
case "claude-only":
|
|
74
|
+
return "on (Claude only)";
|
|
75
|
+
default:
|
|
76
|
+
return "on";
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** Scheme-less display form of a browser deep link: accent + underline, OSC-8 linked to the full URL. */
|
|
81
|
+
function collabWebLinkClickable(webLink: string): string {
|
|
82
|
+
const display = theme.fg("accent", `\x1b[4m${webLink.replace(/^https?:\/\//, "")}\x1b[24m`);
|
|
83
|
+
return urlHyperlinkAlways(webLink, display);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** Join hint printed by /collab: compact terminal link + clickable browser deep link. */
|
|
87
|
+
function collabLinkHint(host: CollabHost, heading: string, view = false): string {
|
|
88
|
+
const bullet = theme.fg("accent", theme.format.bullet);
|
|
89
|
+
const link = view ? host.viewLink : host.link;
|
|
90
|
+
const webLink = view ? host.webViewLink : host.webLink;
|
|
91
|
+
return [
|
|
92
|
+
theme.fg("success", heading),
|
|
93
|
+
` ${bullet} ${theme.fg("muted", view ? "Watch from another terminal:" : "Join from another terminal:")} ${APP_NAME} join "${link}"`,
|
|
94
|
+
` ${bullet} ${theme.fg("muted", "or any web browser:")} ${collabWebLinkClickable(webLink)}`,
|
|
95
|
+
theme.fg(
|
|
96
|
+
"dim",
|
|
97
|
+
view
|
|
98
|
+
? "Anyone with this link can watch the session but cannot prompt the agent."
|
|
99
|
+
: "Anyone with the link can read the session and prompt the agent. Read-only link: /collab view",
|
|
100
|
+
),
|
|
101
|
+
].join("\n");
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function showCollabQrCode(ctx: InteractiveModeContext, webLink: string): void {
|
|
105
|
+
try {
|
|
106
|
+
ctx.present([new Spacer(1), new CollabQrCodeComponent(webLink)]);
|
|
107
|
+
} catch (err) {
|
|
108
|
+
ctx.showError(`Failed to render collab QR code: ${errorMessage(err)}`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function showCollabLink(ctx: InteractiveModeContext, host: CollabHost, heading: string, view = false): void {
|
|
113
|
+
ctx.showStatus(collabLinkHint(host, heading, view), { dim: false });
|
|
114
|
+
showCollabQrCode(ctx, view ? host.webViewLink : host.webLink);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function formatFreshSessionResult(result: FreshSessionResult): string {
|
|
118
|
+
const stateLabel = result.closedProviderSessions === 1 ? "provider state" : "provider states";
|
|
119
|
+
return `Fresh provider session started (${result.closedProviderSessions} ${stateLabel} pruned).`;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const shutdownHandlerTui = (_command: ParsedSlashCommand, runtime: TuiSlashCommandRuntime): SlashCommandResult => {
|
|
123
|
+
runtime.ctx.editor.setText("");
|
|
124
|
+
void runtime.ctx.shutdown();
|
|
125
|
+
return commandConsumed();
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
async function handleUsageResetCommand(
|
|
129
|
+
arg: string,
|
|
130
|
+
session: AgentSession,
|
|
131
|
+
output: SlashCommandRuntime["output"],
|
|
132
|
+
): Promise<void> {
|
|
133
|
+
let accounts: ResetUsageAccount[];
|
|
134
|
+
try {
|
|
135
|
+
accounts = toResetUsageAccounts(await session.listResetCredits());
|
|
136
|
+
} catch (error) {
|
|
137
|
+
await output(`Could not load saved resets: ${errorMessage(error)}`);
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
if (accounts.length === 0) {
|
|
141
|
+
await output("No Codex accounts found. Use /login to add one.");
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
const targetArg = arg.trim();
|
|
145
|
+
if (!targetArg) {
|
|
146
|
+
const lines = ["Saved Codex rate-limit resets:"];
|
|
147
|
+
for (const account of accounts) {
|
|
148
|
+
const detail = account.error ? `unavailable (${account.error})` : `${account.availableCount} available`;
|
|
149
|
+
lines.push(`- ${account.label}: ${detail}${account.active ? " (active)" : ""}`);
|
|
150
|
+
}
|
|
151
|
+
lines.push("", "Spend one with `/usage reset <account email>` or `/usage reset active`.");
|
|
152
|
+
await output(lines.join("\n"));
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
const wanted = targetArg.toLowerCase();
|
|
156
|
+
const target =
|
|
157
|
+
wanted === "active"
|
|
158
|
+
? accounts.find(account => account.active)
|
|
159
|
+
: accounts.find(
|
|
160
|
+
account =>
|
|
161
|
+
account.label.toLowerCase() === wanted ||
|
|
162
|
+
account.target.email?.toLowerCase() === wanted ||
|
|
163
|
+
account.target.accountId?.toLowerCase() === wanted,
|
|
164
|
+
);
|
|
165
|
+
if (!target) {
|
|
166
|
+
await output(`No Codex account matches "${targetArg}".`);
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
if (target.availableCount <= 0) {
|
|
170
|
+
await output(`${target.label}: no saved resets to spend.`);
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
const outcome = await session.redeemResetCredit(target.target);
|
|
174
|
+
await output(describeRedeemOutcome(outcome, target.label));
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const DEBUG_DUMP_NEXT_REQUEST_USAGE = "Usage: /debug dump-next-request <path>";
|
|
178
|
+
|
|
179
|
+
function resolveDebugRequestDumpPath(target: string, cwd: string): string {
|
|
180
|
+
const expanded =
|
|
181
|
+
target === "~"
|
|
182
|
+
? os.homedir()
|
|
183
|
+
: target.startsWith("~/") || target.startsWith("~\\")
|
|
184
|
+
? path.join(os.homedir(), target.slice(2))
|
|
185
|
+
: target;
|
|
186
|
+
return path.resolve(cwd, expanded);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
async function handleDebugSubcommand(
|
|
190
|
+
args: string,
|
|
191
|
+
cwd: string,
|
|
192
|
+
output: (text: string) => Promise<void> | void,
|
|
193
|
+
): Promise<SlashCommandResult> {
|
|
194
|
+
const { verb, rest } = parseSubcommand(args);
|
|
195
|
+
switch (verb) {
|
|
196
|
+
case "":
|
|
197
|
+
await output(DEBUG_DUMP_NEXT_REQUEST_USAGE);
|
|
198
|
+
return commandConsumed();
|
|
199
|
+
case "dump-next-request":
|
|
200
|
+
case "dump-request":
|
|
201
|
+
case "next-request": {
|
|
202
|
+
if (!rest) {
|
|
203
|
+
await output(DEBUG_DUMP_NEXT_REQUEST_USAGE);
|
|
204
|
+
return commandConsumed();
|
|
205
|
+
}
|
|
206
|
+
const requestPath = resolveDebugRequestDumpPath(rest, cwd);
|
|
207
|
+
setNextRequestDebugPath(requestPath);
|
|
208
|
+
await output(`Next AI provider request will be dumped to ${requestPath}`);
|
|
209
|
+
return commandConsumed();
|
|
210
|
+
}
|
|
211
|
+
default:
|
|
212
|
+
await output(`Unknown /debug subcommand "${verb}". ${DEBUG_DUMP_NEXT_REQUEST_USAGE}`);
|
|
213
|
+
return commandConsumed();
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/** Parse the `/shake` subcommand into a {@link ShakeMode}; empty defaults to elide. */
|
|
218
|
+
function parseShakeMode(args: string): ShakeMode | { error: string } {
|
|
219
|
+
const verb = args.trim().toLowerCase();
|
|
220
|
+
if (verb === "" || verb === "elide") return "elide";
|
|
221
|
+
if (verb === "images") return "images";
|
|
222
|
+
return { error: `Unknown /shake mode "${verb}". Use elide or images.` };
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const BUILTIN_SLASH_COMMAND_REGISTRY: ReadonlyArray<SlashCommandSpec> = [
|
|
226
|
+
{
|
|
227
|
+
name: "settings",
|
|
228
|
+
description: "Open settings menu",
|
|
229
|
+
handleTui: (_command, runtime) => {
|
|
230
|
+
runtime.ctx.showSettingsSelector();
|
|
231
|
+
runtime.ctx.editor.setText("");
|
|
232
|
+
},
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
name: "setup",
|
|
236
|
+
aliases: ["providers"],
|
|
237
|
+
description: "Open provider setup",
|
|
238
|
+
allowArgs: true,
|
|
239
|
+
subcommands: [{ name: "providers", description: "Configure sign-in and web search providers" }],
|
|
240
|
+
handleTui: async (command, runtime) => {
|
|
241
|
+
const args = command.args.trim().toLowerCase();
|
|
242
|
+
const opensProviders = args === "" || args === "providers";
|
|
243
|
+
if (opensProviders) {
|
|
244
|
+
await runtime.ctx.showProviderSetup();
|
|
245
|
+
} else {
|
|
246
|
+
runtime.ctx.showWarning(`Usage: /${command.name} [providers]`);
|
|
247
|
+
}
|
|
248
|
+
runtime.ctx.editor.setText("");
|
|
249
|
+
},
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
name: "plan",
|
|
253
|
+
description: "Toggle plan mode (agent plans before executing)",
|
|
254
|
+
inlineHint: "[prompt]",
|
|
255
|
+
allowArgs: true,
|
|
256
|
+
handleTui: async (command, runtime) => {
|
|
257
|
+
const hadArgs = !!command.args;
|
|
258
|
+
await runtime.ctx.handlePlanModeCommand(command.args || undefined);
|
|
259
|
+
if (hadArgs) {
|
|
260
|
+
runtime.ctx.editor.addToHistory(command.text);
|
|
261
|
+
}
|
|
262
|
+
runtime.ctx.editor.setText("");
|
|
263
|
+
},
|
|
264
|
+
},
|
|
265
|
+
{
|
|
266
|
+
name: "plan-review",
|
|
267
|
+
description: "Re-open the plan review for the latest plan (plan mode only)",
|
|
268
|
+
handleTui: async (_command, runtime) => {
|
|
269
|
+
await runtime.ctx.openPlanReview();
|
|
270
|
+
runtime.ctx.editor.setText("");
|
|
271
|
+
},
|
|
272
|
+
},
|
|
273
|
+
{
|
|
274
|
+
name: "goal",
|
|
275
|
+
description: "Toggle goal mode (persistent autonomous objective for this session)",
|
|
276
|
+
subcommands: [
|
|
277
|
+
{ name: "set", description: "Set or replace the goal", usage: "<objective>" },
|
|
278
|
+
{ name: "show", description: "Show current goal details" },
|
|
279
|
+
{ name: "pause", description: "Pause the current goal" },
|
|
280
|
+
{ name: "resume", description: "Resume a paused goal" },
|
|
281
|
+
{ name: "drop", description: "Drop the current goal" },
|
|
282
|
+
{ name: "budget", description: "Adjust the token budget", usage: "<N|off>" },
|
|
283
|
+
],
|
|
284
|
+
inlineHint: "[objective]",
|
|
285
|
+
allowArgs: true,
|
|
286
|
+
handleTui: async (command, runtime) => {
|
|
287
|
+
const hadArgs = !!command.args;
|
|
288
|
+
await runtime.ctx.handleGoalModeCommand(command.args || undefined);
|
|
289
|
+
if (hadArgs) {
|
|
290
|
+
runtime.ctx.editor.addToHistory(command.text);
|
|
291
|
+
}
|
|
292
|
+
runtime.ctx.editor.setText("");
|
|
293
|
+
},
|
|
294
|
+
},
|
|
295
|
+
{
|
|
296
|
+
name: "guided-goal",
|
|
297
|
+
description: "Interview and refine a goal before enabling goal mode",
|
|
298
|
+
inlineHint: "[rough objective]",
|
|
299
|
+
allowArgs: true,
|
|
300
|
+
handleTui: async (command, runtime) => {
|
|
301
|
+
await runtime.ctx.handleGuidedGoalCommand(command.args || undefined);
|
|
302
|
+
runtime.ctx.editor.setText("");
|
|
303
|
+
},
|
|
304
|
+
},
|
|
305
|
+
{
|
|
306
|
+
name: "loop",
|
|
307
|
+
description:
|
|
308
|
+
"Toggle loop mode. While enabled, the next prompt you send re-submits after every yield. Esc cancels the current iteration; /loop again to disable.",
|
|
309
|
+
inlineHint: "[count|duration] [prompt]",
|
|
310
|
+
allowArgs: true,
|
|
311
|
+
handleTui: async (command, runtime) => {
|
|
312
|
+
const prompt = await runtime.ctx.handleLoopCommand(command.args);
|
|
313
|
+
runtime.ctx.editor.setText("");
|
|
314
|
+
// Surface any inline prompt so the dispatcher returns it and the normal
|
|
315
|
+
// submit flow runs the first loop iteration (recording it as the loop prompt).
|
|
316
|
+
if (prompt) return { prompt };
|
|
317
|
+
},
|
|
318
|
+
},
|
|
319
|
+
{
|
|
320
|
+
name: "model",
|
|
321
|
+
aliases: ["models"],
|
|
322
|
+
description: "Switch model for this session",
|
|
323
|
+
acpDescription: "Show current model selection",
|
|
324
|
+
handle: async (command, runtime) => {
|
|
325
|
+
if (command.args) {
|
|
326
|
+
const modelId = command.args.trim();
|
|
327
|
+
const availableModels = runtime.session.getAvailableModels?.() ?? [];
|
|
328
|
+
const match = availableModels.find(
|
|
329
|
+
model => model.id === modelId || `${model.provider}/${model.id}` === modelId,
|
|
330
|
+
);
|
|
331
|
+
if (!match) {
|
|
332
|
+
return usage(
|
|
333
|
+
`Unknown model: ${modelId}. Use ACP \`session/setModel\` for picker-driven selection or list available models with /model.`,
|
|
334
|
+
runtime,
|
|
335
|
+
);
|
|
336
|
+
}
|
|
337
|
+
try {
|
|
338
|
+
await runtime.session.setModel(match);
|
|
339
|
+
await runtime.output(`Model set to ${match.provider}/${match.id}.`);
|
|
340
|
+
await runtime.notifyTitleChanged?.();
|
|
341
|
+
await runtime.notifyConfigChanged?.();
|
|
342
|
+
return commandConsumed();
|
|
343
|
+
} catch (err) {
|
|
344
|
+
return usage(`Failed to set model: ${errorMessage(err)}`, runtime);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
const model = runtime.session.model;
|
|
349
|
+
await runtime.output(
|
|
350
|
+
model ? `Current model: ${model.provider}/${model.id}` : "No model is currently selected.",
|
|
351
|
+
);
|
|
352
|
+
return commandConsumed();
|
|
353
|
+
},
|
|
354
|
+
handleTui: (_command, runtime) => {
|
|
355
|
+
runtime.ctx.showModelSelector();
|
|
356
|
+
runtime.ctx.editor.setText("");
|
|
357
|
+
},
|
|
358
|
+
},
|
|
359
|
+
{
|
|
360
|
+
name: "switch",
|
|
361
|
+
description: "Switch model for this session (same as alt+p)",
|
|
362
|
+
handleTui: (_command, runtime) => {
|
|
363
|
+
runtime.ctx.showModelSelector({ temporaryOnly: true });
|
|
364
|
+
runtime.ctx.editor.setText("");
|
|
365
|
+
},
|
|
366
|
+
},
|
|
367
|
+
{
|
|
368
|
+
name: "fast",
|
|
369
|
+
description: "Toggle priority service tier (OpenAI service_tier=priority, Anthropic speed=fast)",
|
|
370
|
+
acpDescription: "Toggle fast mode",
|
|
371
|
+
acpInputHint: "[on|off|status]",
|
|
372
|
+
subcommands: [
|
|
373
|
+
{ name: "on", description: "Enable fast mode" },
|
|
374
|
+
{ name: "off", description: "Disable fast mode" },
|
|
375
|
+
{ name: "status", description: "Show fast mode status" },
|
|
376
|
+
],
|
|
377
|
+
allowArgs: true,
|
|
378
|
+
handle: async (command, runtime) => {
|
|
379
|
+
const arg = command.args.toLowerCase();
|
|
380
|
+
if (!arg || arg === "toggle") {
|
|
381
|
+
const enabled = runtime.session.toggleFastMode();
|
|
382
|
+
await runtime.output(`Fast mode ${enabled ? "enabled" : "disabled"}.`);
|
|
383
|
+
return commandConsumed();
|
|
384
|
+
}
|
|
385
|
+
if (arg === "on") {
|
|
386
|
+
runtime.session.setFastMode(true);
|
|
387
|
+
await runtime.output("Fast mode enabled.");
|
|
388
|
+
return commandConsumed();
|
|
389
|
+
}
|
|
390
|
+
if (arg === "off") {
|
|
391
|
+
runtime.session.setFastMode(false);
|
|
392
|
+
await runtime.output("Fast mode disabled.");
|
|
393
|
+
return commandConsumed();
|
|
394
|
+
}
|
|
395
|
+
if (arg === "status") {
|
|
396
|
+
await runtime.output(`Fast mode is ${formatFastModeStatus(runtime.session)}.`);
|
|
397
|
+
return commandConsumed();
|
|
398
|
+
}
|
|
399
|
+
return usage("Usage: /fast [on|off|status]", runtime);
|
|
400
|
+
},
|
|
401
|
+
handleTui: (command, runtime) => {
|
|
402
|
+
const arg = command.args.trim().toLowerCase();
|
|
403
|
+
if (!arg || arg === "toggle") {
|
|
404
|
+
const enabled = runtime.ctx.session.toggleFastMode();
|
|
405
|
+
refreshStatusLine(runtime.ctx);
|
|
406
|
+
runtime.ctx.showStatus(`Fast mode ${enabled ? "enabled" : "disabled"}.`);
|
|
407
|
+
runtime.ctx.editor.setText("");
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
410
|
+
if (arg === "on") {
|
|
411
|
+
runtime.ctx.session.setFastMode(true);
|
|
412
|
+
refreshStatusLine(runtime.ctx);
|
|
413
|
+
runtime.ctx.showStatus("Fast mode enabled.");
|
|
414
|
+
runtime.ctx.editor.setText("");
|
|
415
|
+
return;
|
|
416
|
+
}
|
|
417
|
+
if (arg === "off") {
|
|
418
|
+
runtime.ctx.session.setFastMode(false);
|
|
419
|
+
refreshStatusLine(runtime.ctx);
|
|
420
|
+
runtime.ctx.showStatus("Fast mode disabled.");
|
|
421
|
+
runtime.ctx.editor.setText("");
|
|
422
|
+
return;
|
|
423
|
+
}
|
|
424
|
+
if (arg === "status") {
|
|
425
|
+
runtime.ctx.showStatus(`Fast mode is ${formatFastModeStatus(runtime.ctx.session)}.`);
|
|
426
|
+
runtime.ctx.editor.setText("");
|
|
427
|
+
return;
|
|
428
|
+
}
|
|
429
|
+
runtime.ctx.showStatus("Usage: /fast [on|off|status]");
|
|
430
|
+
runtime.ctx.editor.setText("");
|
|
431
|
+
},
|
|
432
|
+
},
|
|
433
|
+
{
|
|
434
|
+
name: "advisor",
|
|
435
|
+
description: "Toggle the advisor (a second model that reviews each turn and injects notes)",
|
|
436
|
+
acpDescription: "Toggle advisor",
|
|
437
|
+
acpInputHint: "[on|off|status|dump [raw]]",
|
|
438
|
+
subcommands: [
|
|
439
|
+
{ name: "on", description: "Enable the advisor" },
|
|
440
|
+
{ name: "off", description: "Disable the advisor" },
|
|
441
|
+
{ name: "status", description: "Show advisor status" },
|
|
442
|
+
{ name: "dump", description: "Copy the advisor's transcript to clipboard", usage: "[raw]" },
|
|
443
|
+
],
|
|
444
|
+
allowArgs: true,
|
|
445
|
+
handle: async (command, runtime) => {
|
|
446
|
+
const { verb, rest } = parseSubcommand(command.args);
|
|
447
|
+
if (!verb || verb === "toggle") {
|
|
448
|
+
const active = runtime.session.toggleAdvisorEnabled();
|
|
449
|
+
const configured = runtime.session.isAdvisorEnabled();
|
|
450
|
+
if (active) {
|
|
451
|
+
await runtime.output("Advisor enabled.");
|
|
452
|
+
} else if (configured) {
|
|
453
|
+
await runtime.output("Advisor setting enabled, but no model is assigned to the 'advisor' role.");
|
|
454
|
+
} else {
|
|
455
|
+
await runtime.output("Advisor disabled.");
|
|
456
|
+
}
|
|
457
|
+
return commandConsumed();
|
|
458
|
+
}
|
|
459
|
+
if (verb === "on") {
|
|
460
|
+
const active = runtime.session.setAdvisorEnabled(true);
|
|
461
|
+
await runtime.output(
|
|
462
|
+
active ? "Advisor enabled." : "Advisor setting enabled, but no model is assigned to the 'advisor' role.",
|
|
463
|
+
);
|
|
464
|
+
return commandConsumed();
|
|
465
|
+
}
|
|
466
|
+
if (verb === "off") {
|
|
467
|
+
runtime.session.setAdvisorEnabled(false);
|
|
468
|
+
await runtime.output("Advisor disabled.");
|
|
469
|
+
return commandConsumed();
|
|
470
|
+
}
|
|
471
|
+
if (verb === "status") {
|
|
472
|
+
await runtime.output(runtime.session.formatAdvisorStatus());
|
|
473
|
+
return commandConsumed();
|
|
474
|
+
}
|
|
475
|
+
if (verb === "dump") {
|
|
476
|
+
const isRaw = rest.toLowerCase() === "raw";
|
|
477
|
+
const text = runtime.session.formatAdvisorHistoryAsText({ compact: !isRaw });
|
|
478
|
+
await runtime.output(text ?? "Advisor is not active for this session.");
|
|
479
|
+
return commandConsumed();
|
|
480
|
+
}
|
|
481
|
+
return usage("Usage: /advisor [on|off|status|dump [raw]]", runtime);
|
|
482
|
+
},
|
|
483
|
+
handleTui: async (command, runtime) => {
|
|
484
|
+
const { verb, rest } = parseSubcommand(command.args);
|
|
485
|
+
if (!verb || verb === "toggle") {
|
|
486
|
+
const active = runtime.ctx.session.toggleAdvisorEnabled();
|
|
487
|
+
const configured = runtime.ctx.session.isAdvisorEnabled();
|
|
488
|
+
if (active) {
|
|
489
|
+
runtime.ctx.showStatus("Advisor enabled.");
|
|
490
|
+
} else if (configured) {
|
|
491
|
+
runtime.ctx.showStatus("Advisor setting enabled, but no model is assigned to the 'advisor' role.");
|
|
492
|
+
} else {
|
|
493
|
+
runtime.ctx.showStatus("Advisor disabled.");
|
|
494
|
+
}
|
|
495
|
+
refreshStatusLine(runtime.ctx);
|
|
496
|
+
runtime.ctx.editor.setText("");
|
|
497
|
+
return;
|
|
498
|
+
}
|
|
499
|
+
if (verb === "on") {
|
|
500
|
+
const active = runtime.ctx.session.setAdvisorEnabled(true);
|
|
501
|
+
runtime.ctx.showStatus(
|
|
502
|
+
active ? "Advisor enabled." : "Advisor setting enabled, but no model is assigned to the 'advisor' role.",
|
|
503
|
+
);
|
|
504
|
+
refreshStatusLine(runtime.ctx);
|
|
505
|
+
runtime.ctx.editor.setText("");
|
|
506
|
+
return;
|
|
507
|
+
}
|
|
508
|
+
if (verb === "off") {
|
|
509
|
+
runtime.ctx.session.setAdvisorEnabled(false);
|
|
510
|
+
runtime.ctx.showStatus("Advisor disabled.");
|
|
511
|
+
refreshStatusLine(runtime.ctx);
|
|
512
|
+
runtime.ctx.editor.setText("");
|
|
513
|
+
return;
|
|
514
|
+
}
|
|
515
|
+
if (verb === "status") {
|
|
516
|
+
await runtime.ctx.handleAdvisorStatusCommand();
|
|
517
|
+
runtime.ctx.editor.setText("");
|
|
518
|
+
return;
|
|
519
|
+
}
|
|
520
|
+
if (verb === "dump") {
|
|
521
|
+
const isRaw = rest.toLowerCase() === "raw";
|
|
522
|
+
runtime.ctx.handleAdvisorDumpCommand(isRaw);
|
|
523
|
+
runtime.ctx.editor.setText("");
|
|
524
|
+
return;
|
|
525
|
+
}
|
|
526
|
+
runtime.ctx.showStatus("Usage: /advisor [on|off|status|dump [raw]]");
|
|
527
|
+
runtime.ctx.editor.setText("");
|
|
528
|
+
},
|
|
529
|
+
},
|
|
530
|
+
{
|
|
531
|
+
name: "export",
|
|
532
|
+
description: "Export session to HTML file",
|
|
533
|
+
inlineHint: "[path]",
|
|
534
|
+
allowArgs: true,
|
|
535
|
+
handle: async (command, runtime) => {
|
|
536
|
+
const arg = command.args.trim();
|
|
537
|
+
// Match the interactive `/export` behavior: clipboard aliases are not a
|
|
538
|
+
// valid export target. Without this, the literal value (`copy`,
|
|
539
|
+
// `--copy`, `clipboard`) is passed to `exportToHtml` and becomes the
|
|
540
|
+
// output filename.
|
|
541
|
+
if (arg === "--copy" || arg === "clipboard" || arg === "copy") {
|
|
542
|
+
return usage("Use /dump to copy the session to clipboard.", runtime);
|
|
543
|
+
}
|
|
544
|
+
try {
|
|
545
|
+
const filePath = await runtime.session.exportToHtml(arg || undefined);
|
|
546
|
+
await runtime.output(`Session exported to: ${filePath}`);
|
|
547
|
+
return commandConsumed();
|
|
548
|
+
} catch (err) {
|
|
549
|
+
return usage(`Failed to export session: ${errorMessage(err)}`, runtime);
|
|
550
|
+
}
|
|
551
|
+
},
|
|
552
|
+
handleTui: async (command, runtime) => {
|
|
553
|
+
await runtime.ctx.handleExportCommand(command.text);
|
|
554
|
+
runtime.ctx.editor.setText("");
|
|
555
|
+
},
|
|
556
|
+
},
|
|
557
|
+
{
|
|
558
|
+
name: "dump",
|
|
559
|
+
description: "Copy session transcript to clipboard",
|
|
560
|
+
acpDescription: "Return full transcript as plain text",
|
|
561
|
+
allowArgs: true,
|
|
562
|
+
handle: async (_command, runtime) => {
|
|
563
|
+
const text = runtime.session.formatSessionAsText();
|
|
564
|
+
await runtime.output(text || "No messages to dump yet.");
|
|
565
|
+
return commandConsumed();
|
|
566
|
+
},
|
|
567
|
+
handleTui: (_command, runtime) => {
|
|
568
|
+
runtime.ctx.handleDumpCommand();
|
|
569
|
+
runtime.ctx.editor.setText("");
|
|
570
|
+
},
|
|
571
|
+
},
|
|
572
|
+
{
|
|
573
|
+
name: "share",
|
|
574
|
+
description: "Share session via an encrypted link (secret gist or share server)",
|
|
575
|
+
handle: async (_command, runtime) => {
|
|
576
|
+
try {
|
|
577
|
+
const result = await shareSession(runtime.sessionManager, {
|
|
578
|
+
serverUrl: runtime.settings.get("share.serverUrl"),
|
|
579
|
+
state: runtime.session.state,
|
|
580
|
+
obfuscator: runtime.settings.get("share.redactSecrets") ? runtime.session.obfuscator : undefined,
|
|
581
|
+
});
|
|
582
|
+
const lines = [`Share URL: ${result.url}`];
|
|
583
|
+
if (result.gistUrl) lines.push(`Gist: ${result.gistUrl}`);
|
|
584
|
+
if (result.truncated) lines.push("Note: large content was trimmed to fit the share size limit.");
|
|
585
|
+
await runtime.output(lines.join("\n"));
|
|
586
|
+
return commandConsumed();
|
|
587
|
+
} catch (err) {
|
|
588
|
+
return usage(`Failed to share session: ${errorMessage(err)}`, runtime);
|
|
589
|
+
}
|
|
590
|
+
},
|
|
591
|
+
handleTui: async (_command, runtime) => {
|
|
592
|
+
await runtime.ctx.handleShareCommand();
|
|
593
|
+
runtime.ctx.editor.setText("");
|
|
594
|
+
},
|
|
595
|
+
},
|
|
596
|
+
{
|
|
597
|
+
name: "collab",
|
|
598
|
+
description: "Share this session live via a relay",
|
|
599
|
+
inlineHint: "[start|view|stop|status] [relayUrl]",
|
|
600
|
+
subcommands: [
|
|
601
|
+
{ name: "view", description: "Share a read-only link (guests can watch, not prompt)" },
|
|
602
|
+
{ name: "status", description: "Show link + participants" },
|
|
603
|
+
{ name: "stop", description: "Stop sharing" },
|
|
604
|
+
],
|
|
605
|
+
allowArgs: true,
|
|
606
|
+
handleTui: async (command, runtime) => {
|
|
607
|
+
const ctx = runtime.ctx;
|
|
608
|
+
ctx.editor.setText("");
|
|
609
|
+
const args = command.args.trim();
|
|
610
|
+
const { verb, rest } = parseSubcommand(args);
|
|
611
|
+
if (verb === "stop") {
|
|
612
|
+
if (!ctx.collabHost) {
|
|
613
|
+
ctx.showStatus("Not hosting a collab session");
|
|
614
|
+
return;
|
|
615
|
+
}
|
|
616
|
+
await ctx.collabHost.stop("host stopped");
|
|
617
|
+
ctx.showStatus("Collab stopped");
|
|
618
|
+
return;
|
|
619
|
+
}
|
|
620
|
+
if (verb === "status") {
|
|
621
|
+
if (ctx.collabHost) {
|
|
622
|
+
const names = ctx.collabHost.participants.map(p =>
|
|
623
|
+
p.role === "host" ? `${p.name} (host)` : p.readOnly ? `${p.name} (view-only)` : p.name,
|
|
624
|
+
);
|
|
625
|
+
ctx.showStatus(`Collab: ${names.join(", ")} — ${collabWebLinkClickable(ctx.collabHost.webLink)}`);
|
|
626
|
+
} else if (ctx.collabGuest) {
|
|
627
|
+
ctx.showStatus(
|
|
628
|
+
ctx.collabGuest.readOnly
|
|
629
|
+
? "In a collab session as a read-only guest (/leave to exit)"
|
|
630
|
+
: "In a collab session as a guest (/leave to exit)",
|
|
631
|
+
);
|
|
632
|
+
} else {
|
|
633
|
+
ctx.showStatus("Not in a collab session");
|
|
634
|
+
}
|
|
635
|
+
return;
|
|
636
|
+
}
|
|
637
|
+
if (ctx.collabGuest) {
|
|
638
|
+
ctx.showError("Already in a collab session as a guest (/leave first)");
|
|
639
|
+
return;
|
|
640
|
+
}
|
|
641
|
+
const knownStartVerb = verb === "start" || verb === "view";
|
|
642
|
+
const view = verb === "view";
|
|
643
|
+
if (ctx.collabHost) {
|
|
644
|
+
showCollabLink(
|
|
645
|
+
ctx,
|
|
646
|
+
ctx.collabHost,
|
|
647
|
+
view ? "Read-only collab session active" : "Collab session active",
|
|
648
|
+
view,
|
|
649
|
+
);
|
|
650
|
+
return;
|
|
651
|
+
}
|
|
652
|
+
const explicitUrl = knownStartVerb ? rest : args;
|
|
653
|
+
const relayInput = explicitUrl || ctx.settings.get("collab.relayUrl") || "";
|
|
654
|
+
if (!relayInput) {
|
|
655
|
+
ctx.showError(
|
|
656
|
+
"No relay configured. Set collab.relayUrl in /settings or pass one: /collab relay.example.com",
|
|
657
|
+
);
|
|
658
|
+
return;
|
|
659
|
+
}
|
|
660
|
+
// Scheme-less relay args default to wss (ws:// must be spelled out for localhost).
|
|
661
|
+
const relayUrl = relayInput.includes("://") ? relayInput : `wss://${relayInput}`;
|
|
662
|
+
const webUrl = ctx.settings.get("collab.webUrl") || "";
|
|
663
|
+
const host = new CollabHost(ctx);
|
|
664
|
+
try {
|
|
665
|
+
await host.start(relayUrl, webUrl);
|
|
666
|
+
} catch (err) {
|
|
667
|
+
ctx.showError(`Failed to start collab session: ${errorMessage(err)}`);
|
|
668
|
+
return;
|
|
669
|
+
}
|
|
670
|
+
ctx.collabHost = host;
|
|
671
|
+
showCollabLink(ctx, host, "Collab session started!", view);
|
|
672
|
+
},
|
|
673
|
+
},
|
|
674
|
+
{
|
|
675
|
+
name: "join",
|
|
676
|
+
description: "Join a shared collab session",
|
|
677
|
+
inlineHint: "<link>",
|
|
678
|
+
allowArgs: true,
|
|
679
|
+
handleTui: async (command, runtime) => {
|
|
680
|
+
const ctx = runtime.ctx;
|
|
681
|
+
ctx.editor.setText("");
|
|
682
|
+
const link = command.args.trim();
|
|
683
|
+
if (!link) {
|
|
684
|
+
ctx.showError("Usage: /join <link>");
|
|
685
|
+
return;
|
|
686
|
+
}
|
|
687
|
+
if (ctx.collabHost) {
|
|
688
|
+
ctx.showError("Stop hosting first (/collab stop)");
|
|
689
|
+
return;
|
|
690
|
+
}
|
|
691
|
+
if (ctx.collabGuest) {
|
|
692
|
+
ctx.showError("Already in a collab session (/leave first)");
|
|
693
|
+
return;
|
|
694
|
+
}
|
|
695
|
+
try {
|
|
696
|
+
await new CollabGuestLink(ctx).join(link);
|
|
697
|
+
} catch (err) {
|
|
698
|
+
ctx.showError(`Failed to join collab session: ${errorMessage(err)}`);
|
|
699
|
+
}
|
|
700
|
+
},
|
|
701
|
+
},
|
|
702
|
+
{
|
|
703
|
+
name: "leave",
|
|
704
|
+
description: "Leave the collab session",
|
|
705
|
+
handleTui: async (_command, runtime) => {
|
|
706
|
+
const ctx = runtime.ctx;
|
|
707
|
+
ctx.editor.setText("");
|
|
708
|
+
if (ctx.collabGuest) {
|
|
709
|
+
await ctx.collabGuest.leave("left");
|
|
710
|
+
return;
|
|
711
|
+
}
|
|
712
|
+
if (ctx.collabHost) {
|
|
713
|
+
await ctx.collabHost.stop("host stopped");
|
|
714
|
+
ctx.showStatus("Collab stopped");
|
|
715
|
+
return;
|
|
716
|
+
}
|
|
717
|
+
ctx.showStatus("Not in a collab session");
|
|
718
|
+
},
|
|
719
|
+
},
|
|
720
|
+
{
|
|
721
|
+
name: "browser",
|
|
722
|
+
description: "Toggle browser headless vs visible mode",
|
|
723
|
+
acpInputHint: "[headless|visible]",
|
|
724
|
+
subcommands: [
|
|
725
|
+
{ name: "headless", description: "Switch to headless mode" },
|
|
726
|
+
{ name: "visible", description: "Switch to visible mode" },
|
|
727
|
+
],
|
|
728
|
+
allowArgs: true,
|
|
729
|
+
handle: async (command, runtime) => {
|
|
730
|
+
const arg = command.args.toLowerCase();
|
|
731
|
+
const enabled = runtime.settings.get("browser.enabled" as SettingPath) as boolean;
|
|
732
|
+
if (!enabled) return usage("Browser tool is disabled (enable in settings).", runtime);
|
|
733
|
+
const current = runtime.settings.get("browser.headless" as SettingPath) as boolean;
|
|
734
|
+
let next = current;
|
|
735
|
+
if (!arg) next = !current;
|
|
736
|
+
else if (arg === "headless" || arg === "hidden") next = true;
|
|
737
|
+
else if (arg === "visible" || arg === "show" || arg === "headful") next = false;
|
|
738
|
+
else return usage("Usage: /browser [headless|visible]", runtime);
|
|
739
|
+
runtime.settings.set("browser.headless" as SettingPath, next as SettingValue<SettingPath>);
|
|
740
|
+
const tool = runtime.session.getToolByName("browser");
|
|
741
|
+
if (tool && "restartForModeChange" in tool) {
|
|
742
|
+
try {
|
|
743
|
+
await (tool as { restartForModeChange: () => Promise<void> }).restartForModeChange();
|
|
744
|
+
} catch (err) {
|
|
745
|
+
// Setting was already mutated; surface the restart failure so the
|
|
746
|
+
// user knows the browser is in an inconsistent state.
|
|
747
|
+
await runtime.output(
|
|
748
|
+
`Browser mode set to ${next ? "headless" : "visible"}, but restart failed: ${errorMessage(err)}`,
|
|
749
|
+
);
|
|
750
|
+
return commandConsumed();
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
await runtime.output(`Browser mode: ${next ? "headless" : "visible"}`);
|
|
754
|
+
return commandConsumed();
|
|
755
|
+
},
|
|
756
|
+
handleTui: async (command, runtime) => {
|
|
757
|
+
const arg = command.args.toLowerCase();
|
|
758
|
+
const current = settings.get("browser.headless" as SettingPath) as boolean;
|
|
759
|
+
let next = current;
|
|
760
|
+
if (!(settings.get("browser.enabled" as SettingPath) as boolean)) {
|
|
761
|
+
runtime.ctx.showWarning("Browser tool is disabled (enable in settings)");
|
|
762
|
+
runtime.ctx.editor.setText("");
|
|
763
|
+
return;
|
|
764
|
+
}
|
|
765
|
+
if (!arg) {
|
|
766
|
+
next = !current;
|
|
767
|
+
} else if (arg === "headless" || arg === "hidden") {
|
|
768
|
+
next = true;
|
|
769
|
+
} else if (arg === "visible" || arg === "show" || arg === "headful") {
|
|
770
|
+
next = false;
|
|
771
|
+
} else {
|
|
772
|
+
runtime.ctx.showStatus("Usage: /browser [headless|visible]");
|
|
773
|
+
runtime.ctx.editor.setText("");
|
|
774
|
+
return;
|
|
775
|
+
}
|
|
776
|
+
settings.set("browser.headless" as SettingPath, next as SettingValue<SettingPath>);
|
|
777
|
+
const tool = runtime.ctx.session.getToolByName("browser");
|
|
778
|
+
if (tool && "restartForModeChange" in tool) {
|
|
779
|
+
try {
|
|
780
|
+
await (tool as { restartForModeChange: () => Promise<void> }).restartForModeChange();
|
|
781
|
+
} catch (error) {
|
|
782
|
+
runtime.ctx.showWarning(`Failed to restart browser: ${errorMessage(error)}`);
|
|
783
|
+
runtime.ctx.editor.setText("");
|
|
784
|
+
return;
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
runtime.ctx.showStatus(`Browser mode: ${next ? "headless" : "visible"}`);
|
|
788
|
+
runtime.ctx.editor.setText("");
|
|
789
|
+
},
|
|
790
|
+
},
|
|
791
|
+
{
|
|
792
|
+
name: "copy",
|
|
793
|
+
description: "Pick text or code from the conversation to copy",
|
|
794
|
+
handleTui: (_command, runtime) => {
|
|
795
|
+
runtime.ctx.showCopySelector();
|
|
796
|
+
runtime.ctx.editor.setText("");
|
|
797
|
+
},
|
|
798
|
+
},
|
|
799
|
+
{
|
|
800
|
+
name: "todo",
|
|
801
|
+
description: "View or modify the agent's todo list",
|
|
802
|
+
acpDescription: "Manage todos",
|
|
803
|
+
acpInputHint: "<subcommand>",
|
|
804
|
+
subcommands: [
|
|
805
|
+
{ name: "edit", description: "Open todos in $EDITOR (Markdown round-trip)" },
|
|
806
|
+
{ name: "copy", description: "Copy todos as Markdown to clipboard" },
|
|
807
|
+
{ name: "export", description: "Write todos as Markdown to a file (default: TODO.md)", usage: "[<path>]" },
|
|
808
|
+
{ name: "import", description: "Replace todos from a Markdown file (default: TODO.md)", usage: "[<path>]" },
|
|
809
|
+
{
|
|
810
|
+
name: "append",
|
|
811
|
+
description: "Append a task; phase fuzzy-matched or auto-created",
|
|
812
|
+
usage: "[<phase>] <task...>",
|
|
813
|
+
},
|
|
814
|
+
{ name: "start", description: "Mark task in_progress (fuzzy-matched)", usage: "<task>" },
|
|
815
|
+
{ name: "done", description: "Mark task/phase/all completed (fuzzy-matched)", usage: "[<task|phase>]" },
|
|
816
|
+
{ name: "drop", description: "Mark task/phase/all abandoned (fuzzy-matched)", usage: "[<task|phase>]" },
|
|
817
|
+
{ name: "rm", description: "Remove task/phase/all (fuzzy-matched)", usage: "[<task|phase>]" },
|
|
818
|
+
],
|
|
819
|
+
allowArgs: true,
|
|
820
|
+
handle: handleTodoAcp,
|
|
821
|
+
handleTui: async (command, runtime) => {
|
|
822
|
+
await runtime.ctx.handleTodoCommand(command.args);
|
|
823
|
+
runtime.ctx.editor.setText("");
|
|
824
|
+
},
|
|
825
|
+
},
|
|
826
|
+
{
|
|
827
|
+
name: "session",
|
|
828
|
+
description: "Session management commands",
|
|
829
|
+
acpDescription: "Show session information",
|
|
830
|
+
acpInputHint: "info|delete",
|
|
831
|
+
subcommands: [
|
|
832
|
+
{ name: "info", description: "Show session info and stats" },
|
|
833
|
+
{ name: "delete", description: "Delete current session and return to selector" },
|
|
834
|
+
],
|
|
835
|
+
allowArgs: true,
|
|
836
|
+
handle: async (command, runtime) => {
|
|
837
|
+
if (!command.args || command.args === "info") {
|
|
838
|
+
await runtime.output(
|
|
839
|
+
[
|
|
840
|
+
`Session: ${runtime.session.sessionId}`,
|
|
841
|
+
`Title: ${runtime.session.sessionName}`,
|
|
842
|
+
`CWD: ${runtime.cwd}`,
|
|
843
|
+
].join("\n"),
|
|
844
|
+
);
|
|
845
|
+
return commandConsumed();
|
|
846
|
+
}
|
|
847
|
+
if (command.args === "delete") {
|
|
848
|
+
if (runtime.session.isStreaming) return usage("Cannot delete the session while streaming.", runtime);
|
|
849
|
+
const sessionFile = runtime.sessionManager.getSessionFile();
|
|
850
|
+
if (!sessionFile) return usage("No session file to delete (in-memory session).", runtime);
|
|
851
|
+
// Route through the active SessionManager so the persist writer is
|
|
852
|
+
// closed before the file is deleted. Constructing a fresh
|
|
853
|
+
// FileSessionStorage and calling deleteSessionWithArtifacts leaves
|
|
854
|
+
// the active writer attached to the now-deleted path, so the next
|
|
855
|
+
// prompt would silently resurrect or corrupt the "deleted" file.
|
|
856
|
+
try {
|
|
857
|
+
await runtime.sessionManager.dropSession(sessionFile);
|
|
858
|
+
} catch (err) {
|
|
859
|
+
return usage(`Failed to delete session: ${errorMessage(err)}`, runtime);
|
|
860
|
+
}
|
|
861
|
+
await runtime.output(
|
|
862
|
+
`Session deleted: ${sessionFile}. Use ACP \`session/load\` to switch to another session.`,
|
|
863
|
+
);
|
|
864
|
+
return commandConsumed();
|
|
865
|
+
}
|
|
866
|
+
return usage("Usage: /session [info|delete]", runtime);
|
|
867
|
+
},
|
|
868
|
+
handleTui: async (command, runtime) => {
|
|
869
|
+
const sub = command.args.trim().toLowerCase() || "info";
|
|
870
|
+
if (sub === "delete") {
|
|
871
|
+
runtime.ctx.editor.setText("");
|
|
872
|
+
await runtime.ctx.handleSessionDeleteCommand();
|
|
873
|
+
return;
|
|
874
|
+
}
|
|
875
|
+
// Default: show session info
|
|
876
|
+
await runtime.ctx.handleSessionCommand();
|
|
877
|
+
runtime.ctx.editor.setText("");
|
|
878
|
+
},
|
|
879
|
+
},
|
|
880
|
+
{
|
|
881
|
+
name: "jobs",
|
|
882
|
+
description: "Show async background jobs status",
|
|
883
|
+
acpDescription: "Show background jobs",
|
|
884
|
+
handle: async (_command, runtime) => {
|
|
885
|
+
const snapshot = runtime.session.getAsyncJobSnapshot({ recentLimit: 5 });
|
|
886
|
+
if (!snapshot || (snapshot.running.length === 0 && snapshot.recent.length === 0)) {
|
|
887
|
+
await runtime.output(
|
|
888
|
+
"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.)",
|
|
889
|
+
);
|
|
890
|
+
return commandConsumed();
|
|
891
|
+
}
|
|
892
|
+
const now = Date.now();
|
|
893
|
+
const lines: string[] = ["Background Jobs", `Running: ${snapshot.running.length}`];
|
|
894
|
+
if (snapshot.running.length > 0) {
|
|
895
|
+
lines.push("", "Running Jobs");
|
|
896
|
+
for (const job of snapshot.running) {
|
|
897
|
+
lines.push(` [${job.id}] ${job.type} (${job.status}) — ${formatDuration(now - job.startTime)}`);
|
|
898
|
+
lines.push(` ${job.label}`);
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
if (snapshot.recent.length > 0) {
|
|
902
|
+
lines.push("", "Recent Jobs");
|
|
903
|
+
for (const job of snapshot.recent) {
|
|
904
|
+
lines.push(` [${job.id}] ${job.type} (${job.status}) — ${formatDuration(now - job.startTime)}`);
|
|
905
|
+
lines.push(` ${job.label}`);
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
await runtime.output(lines.join("\n"));
|
|
909
|
+
return commandConsumed();
|
|
910
|
+
},
|
|
911
|
+
handleTui: async (_command, runtime) => {
|
|
912
|
+
await runtime.ctx.handleJobsCommand();
|
|
913
|
+
runtime.ctx.editor.setText("");
|
|
914
|
+
},
|
|
915
|
+
},
|
|
916
|
+
{
|
|
917
|
+
name: "usage",
|
|
918
|
+
description: "Show provider usage and limits",
|
|
919
|
+
acpDescription: "Show token usage",
|
|
920
|
+
acpInputHint: "[show|reset [account|active]]",
|
|
921
|
+
subcommands: [
|
|
922
|
+
{ name: "show", description: "Show provider usage and limits" },
|
|
923
|
+
{ name: "reset", description: "Spend a saved Codex rate-limit reset", usage: "[account|active]" },
|
|
924
|
+
],
|
|
925
|
+
allowArgs: true,
|
|
926
|
+
handle: async (command, runtime) => {
|
|
927
|
+
const { verb, rest } = parseSubcommand(command.args);
|
|
928
|
+
if (!verb || (verb === "show" && !rest)) {
|
|
929
|
+
await runtime.output(await buildUsageReportText(runtime));
|
|
930
|
+
return commandConsumed();
|
|
931
|
+
}
|
|
932
|
+
if (verb === "reset") {
|
|
933
|
+
await handleUsageResetCommand(rest, runtime.session, runtime.output);
|
|
934
|
+
return commandConsumed();
|
|
935
|
+
}
|
|
936
|
+
return usage("Usage: /usage [show|reset [account|active]]", runtime);
|
|
937
|
+
},
|
|
938
|
+
handleTui: async (command, runtime) => {
|
|
939
|
+
const { verb, rest } = parseSubcommand(command.args);
|
|
940
|
+
if (!verb || (verb === "show" && !rest)) {
|
|
941
|
+
await runtime.ctx.handleUsageCommand();
|
|
942
|
+
runtime.ctx.editor.setText("");
|
|
943
|
+
return;
|
|
944
|
+
}
|
|
945
|
+
if (verb === "reset") {
|
|
946
|
+
if (rest) {
|
|
947
|
+
await handleUsageResetCommand(rest, runtime.ctx.session, text => runtime.ctx.showStatus(text));
|
|
948
|
+
} else {
|
|
949
|
+
await runtime.ctx.showResetUsageSelector();
|
|
950
|
+
}
|
|
951
|
+
runtime.ctx.editor.setText("");
|
|
952
|
+
return;
|
|
953
|
+
}
|
|
954
|
+
runtime.ctx.showStatus("Usage: /usage [show|reset [account|active]]");
|
|
955
|
+
runtime.ctx.editor.setText("");
|
|
956
|
+
},
|
|
957
|
+
},
|
|
958
|
+
{
|
|
959
|
+
name: "stats",
|
|
960
|
+
description: "Launch the local stats dashboard",
|
|
961
|
+
inlineHint: "[--port <port>]",
|
|
962
|
+
allowArgs: true,
|
|
963
|
+
handle: async (command, runtime) => {
|
|
964
|
+
const parsed = parseStatsDashboardArgs(command.args);
|
|
965
|
+
if ("error" in parsed) return usage(parsed.error, runtime);
|
|
966
|
+
|
|
967
|
+
await runtime.output("Syncing session files...");
|
|
968
|
+
try {
|
|
969
|
+
const result = await launchStatsDashboard(parsed);
|
|
970
|
+
await runtime.output(result.message);
|
|
971
|
+
} catch (error) {
|
|
972
|
+
await runtime.output(`Stats dashboard failed: ${errorMessage(error)}`);
|
|
973
|
+
}
|
|
974
|
+
return commandConsumed();
|
|
975
|
+
},
|
|
976
|
+
},
|
|
977
|
+
{
|
|
978
|
+
name: "changelog",
|
|
979
|
+
description: "Show changelog entries",
|
|
980
|
+
acpDescription: "Show changelog",
|
|
981
|
+
acpInputHint: "[full]",
|
|
982
|
+
subcommands: [{ name: "full", description: "Show complete changelog" }],
|
|
983
|
+
allowArgs: true,
|
|
984
|
+
handle: async (command, runtime) => {
|
|
985
|
+
const changelogPath = getChangelogPath();
|
|
986
|
+
const allEntries = await parseChangelog(changelogPath);
|
|
987
|
+
const showFull = command.args.trim().toLowerCase() === "full";
|
|
988
|
+
const entriesToShow = showFull ? allEntries : allEntries.slice(0, 3);
|
|
989
|
+
if (entriesToShow.length === 0) {
|
|
990
|
+
await runtime.output("No changelog entries found.");
|
|
991
|
+
return commandConsumed();
|
|
992
|
+
}
|
|
993
|
+
await runtime.output(
|
|
994
|
+
[...entriesToShow]
|
|
995
|
+
.reverse()
|
|
996
|
+
.map(entry => entry.content)
|
|
997
|
+
.join("\n\n"),
|
|
998
|
+
);
|
|
999
|
+
return commandConsumed();
|
|
1000
|
+
},
|
|
1001
|
+
handleTui: async (command, runtime) => {
|
|
1002
|
+
const showFull = command.args.split(/\s+/).filter(Boolean).includes("full");
|
|
1003
|
+
await runtime.ctx.handleChangelogCommand(showFull);
|
|
1004
|
+
runtime.ctx.editor.setText("");
|
|
1005
|
+
},
|
|
1006
|
+
},
|
|
1007
|
+
{
|
|
1008
|
+
name: "hotkeys",
|
|
1009
|
+
description: "Show all keyboard shortcuts",
|
|
1010
|
+
handleTui: (_command, runtime) => {
|
|
1011
|
+
runtime.ctx.handleHotkeysCommand();
|
|
1012
|
+
runtime.ctx.editor.setText("");
|
|
1013
|
+
},
|
|
1014
|
+
},
|
|
1015
|
+
{
|
|
1016
|
+
name: "tools",
|
|
1017
|
+
description: "Show tools currently visible to the agent",
|
|
1018
|
+
acpDescription: "Show available tools",
|
|
1019
|
+
handle: async (_command, runtime) => {
|
|
1020
|
+
const active = runtime.session.getActiveToolNames();
|
|
1021
|
+
const all = runtime.session.getAllToolNames();
|
|
1022
|
+
if (all.length === 0) {
|
|
1023
|
+
await runtime.output("No tools are available.");
|
|
1024
|
+
return commandConsumed();
|
|
1025
|
+
}
|
|
1026
|
+
await runtime.output(all.map(name => `${active.includes(name) ? "*" : "-"} ${name}`).join("\n"));
|
|
1027
|
+
return commandConsumed();
|
|
1028
|
+
},
|
|
1029
|
+
handleTui: (_command, runtime) => {
|
|
1030
|
+
runtime.ctx.handleToolsCommand();
|
|
1031
|
+
runtime.ctx.editor.setText("");
|
|
1032
|
+
},
|
|
1033
|
+
},
|
|
1034
|
+
{
|
|
1035
|
+
name: "context",
|
|
1036
|
+
description: "Show estimated context usage breakdown",
|
|
1037
|
+
acpDescription: "Show context usage",
|
|
1038
|
+
handle: async (_command, runtime) => {
|
|
1039
|
+
await runtime.output(buildContextReportText(runtime));
|
|
1040
|
+
return commandConsumed();
|
|
1041
|
+
},
|
|
1042
|
+
handleTui: (_command, runtime) => {
|
|
1043
|
+
runtime.ctx.handleContextCommand();
|
|
1044
|
+
runtime.ctx.editor.setText("");
|
|
1045
|
+
},
|
|
1046
|
+
},
|
|
1047
|
+
{
|
|
1048
|
+
name: "extensions",
|
|
1049
|
+
aliases: ["status"],
|
|
1050
|
+
description: "Open Extension Control Center dashboard",
|
|
1051
|
+
handleTui: (_command, runtime) => {
|
|
1052
|
+
runtime.ctx.showExtensionsDashboard();
|
|
1053
|
+
runtime.ctx.editor.setText("");
|
|
1054
|
+
},
|
|
1055
|
+
},
|
|
1056
|
+
{
|
|
1057
|
+
name: "agents",
|
|
1058
|
+
description: "Open Agent Control Center dashboard",
|
|
1059
|
+
handleTui: (_command, runtime) => {
|
|
1060
|
+
runtime.ctx.showAgentsDashboard();
|
|
1061
|
+
runtime.ctx.editor.setText("");
|
|
1062
|
+
},
|
|
1063
|
+
},
|
|
1064
|
+
{
|
|
1065
|
+
name: "branch",
|
|
1066
|
+
description: "Create a new branch from a previous message",
|
|
1067
|
+
handleTui: (_command, runtime) => {
|
|
1068
|
+
if (settings.get("doubleEscapeAction") === "tree") {
|
|
1069
|
+
runtime.ctx.showTreeSelector();
|
|
1070
|
+
} else {
|
|
1071
|
+
runtime.ctx.showUserMessageSelector();
|
|
1072
|
+
}
|
|
1073
|
+
runtime.ctx.editor.setText("");
|
|
1074
|
+
},
|
|
1075
|
+
},
|
|
1076
|
+
{
|
|
1077
|
+
name: "fork",
|
|
1078
|
+
description: "Create a new fork from a previous message",
|
|
1079
|
+
handleTui: async (_command, runtime) => {
|
|
1080
|
+
runtime.ctx.editor.setText("");
|
|
1081
|
+
await runtime.ctx.handleForkCommand();
|
|
1082
|
+
},
|
|
1083
|
+
},
|
|
1084
|
+
{
|
|
1085
|
+
name: "tree",
|
|
1086
|
+
description: "Navigate session tree (switch branches)",
|
|
1087
|
+
handleTui: (_command, runtime) => {
|
|
1088
|
+
runtime.ctx.showTreeSelector();
|
|
1089
|
+
runtime.ctx.editor.setText("");
|
|
1090
|
+
},
|
|
1091
|
+
},
|
|
1092
|
+
{
|
|
1093
|
+
name: "login",
|
|
1094
|
+
description: "Login with OAuth provider",
|
|
1095
|
+
inlineHint: "[provider|redirect URL]",
|
|
1096
|
+
allowArgs: true,
|
|
1097
|
+
handleTui: (command, runtime) => {
|
|
1098
|
+
const manualInput = runtime.ctx.oauthManualInput;
|
|
1099
|
+
const args = command.args.trim();
|
|
1100
|
+
if (args.length > 0) {
|
|
1101
|
+
const matchedProvider = getOAuthProviders().find(provider => provider.id === args);
|
|
1102
|
+
if (matchedProvider) {
|
|
1103
|
+
if (manualInput.hasPending()) {
|
|
1104
|
+
const pendingProvider = manualInput.pendingProviderId;
|
|
1105
|
+
const message = pendingProvider
|
|
1106
|
+
? `OAuth login already in progress for ${pendingProvider}. Paste the redirect URL with /login <url>.`
|
|
1107
|
+
: "OAuth login already in progress. Paste the redirect URL with /login <url>.";
|
|
1108
|
+
runtime.ctx.showWarning(message);
|
|
1109
|
+
runtime.ctx.editor.setText("");
|
|
1110
|
+
return;
|
|
1111
|
+
}
|
|
1112
|
+
void runtime.ctx.showOAuthSelector("login", matchedProvider.id);
|
|
1113
|
+
runtime.ctx.editor.setText("");
|
|
1114
|
+
return;
|
|
1115
|
+
}
|
|
1116
|
+
const submitted = manualInput.submit(args);
|
|
1117
|
+
if (submitted) {
|
|
1118
|
+
runtime.ctx.showStatus("OAuth callback received; completing login…");
|
|
1119
|
+
} else {
|
|
1120
|
+
runtime.ctx.showWarning("No OAuth login is waiting for a manual callback.");
|
|
1121
|
+
}
|
|
1122
|
+
runtime.ctx.editor.setText("");
|
|
1123
|
+
return;
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1126
|
+
if (manualInput.hasPending()) {
|
|
1127
|
+
const provider = manualInput.pendingProviderId;
|
|
1128
|
+
const message = provider
|
|
1129
|
+
? `OAuth login already in progress for ${provider}. Paste the redirect URL with /login <url>.`
|
|
1130
|
+
: "OAuth login already in progress. Paste the redirect URL with /login <url>.";
|
|
1131
|
+
runtime.ctx.showWarning(message);
|
|
1132
|
+
runtime.ctx.editor.setText("");
|
|
1133
|
+
return;
|
|
1134
|
+
}
|
|
1135
|
+
|
|
1136
|
+
void runtime.ctx.showOAuthSelector("login");
|
|
1137
|
+
runtime.ctx.editor.setText("");
|
|
1138
|
+
},
|
|
1139
|
+
},
|
|
1140
|
+
{
|
|
1141
|
+
name: "logout",
|
|
1142
|
+
description: "Logout from OAuth provider",
|
|
1143
|
+
inlineHint: "[provider]",
|
|
1144
|
+
allowArgs: true,
|
|
1145
|
+
handleTui: (command, runtime) => {
|
|
1146
|
+
const providerId = command.args.trim();
|
|
1147
|
+
if (providerId) {
|
|
1148
|
+
const matchedProvider = getOAuthProviders().find(provider => provider.id === providerId);
|
|
1149
|
+
if (!matchedProvider) {
|
|
1150
|
+
runtime.ctx.showWarning(`Unknown OAuth provider: ${providerId}`);
|
|
1151
|
+
runtime.ctx.editor.setText("");
|
|
1152
|
+
return;
|
|
1153
|
+
}
|
|
1154
|
+
void runtime.ctx.showOAuthSelector("logout", matchedProvider.id);
|
|
1155
|
+
runtime.ctx.editor.setText("");
|
|
1156
|
+
return;
|
|
1157
|
+
}
|
|
1158
|
+
void runtime.ctx.showOAuthSelector("logout");
|
|
1159
|
+
runtime.ctx.editor.setText("");
|
|
1160
|
+
},
|
|
1161
|
+
},
|
|
1162
|
+
{
|
|
1163
|
+
name: "mcp",
|
|
1164
|
+
description: "Manage MCP servers (add, list, remove, test)",
|
|
1165
|
+
acpDescription: "Manage MCP servers",
|
|
1166
|
+
inlineHint: "<subcommand>",
|
|
1167
|
+
subcommands: [
|
|
1168
|
+
{
|
|
1169
|
+
name: "add",
|
|
1170
|
+
description: "Add a new MCP server",
|
|
1171
|
+
usage: "<name> [--scope project|user] [--url <url>] [-- <command...>]",
|
|
1172
|
+
},
|
|
1173
|
+
{ name: "list", description: "List all configured MCP servers" },
|
|
1174
|
+
{ name: "remove", description: "Remove an MCP server", usage: "<name> [--scope project|user]" },
|
|
1175
|
+
{ name: "test", description: "Test connection to a server", usage: "<name>" },
|
|
1176
|
+
{ name: "reauth", description: "Reauthorize OAuth for a server", usage: "<name>" },
|
|
1177
|
+
{ name: "unauth", description: "Remove OAuth auth from a server", usage: "<name>" },
|
|
1178
|
+
{ name: "enable", description: "Enable an MCP server", usage: "<name>" },
|
|
1179
|
+
{ name: "disable", description: "Disable an MCP server", usage: "<name>" },
|
|
1180
|
+
{
|
|
1181
|
+
name: "smithery-search",
|
|
1182
|
+
description: "Search Smithery registry and deploy an MCP server",
|
|
1183
|
+
usage: "<keyword> [--scope project|user] [--limit <1-100>] [--semantic]",
|
|
1184
|
+
},
|
|
1185
|
+
{ name: "smithery-login", description: "Login to Smithery and cache API key" },
|
|
1186
|
+
{ name: "smithery-logout", description: "Remove cached Smithery API key" },
|
|
1187
|
+
{ name: "reconnect", description: "Reconnect to a specific MCP server", usage: "<name>" },
|
|
1188
|
+
{ name: "reload", description: "Force reload MCP runtime tools" },
|
|
1189
|
+
{ name: "resources", description: "List available resources from connected servers" },
|
|
1190
|
+
{ name: "prompts", description: "List available prompts from connected servers" },
|
|
1191
|
+
{ name: "notifications", description: "Show notification capabilities and subscriptions" },
|
|
1192
|
+
{ name: "help", description: "Show help message" },
|
|
1193
|
+
],
|
|
1194
|
+
allowArgs: true,
|
|
1195
|
+
handle: handleMcpAcp,
|
|
1196
|
+
handleTui: async (command, runtime) => {
|
|
1197
|
+
runtime.ctx.editor.addToHistory(command.text);
|
|
1198
|
+
runtime.ctx.editor.setText("");
|
|
1199
|
+
await runtime.ctx.handleMCPCommand(command.text);
|
|
1200
|
+
},
|
|
1201
|
+
},
|
|
1202
|
+
{
|
|
1203
|
+
name: "ssh",
|
|
1204
|
+
description: "Manage SSH hosts (add, list, remove)",
|
|
1205
|
+
acpDescription: "Manage SSH connections",
|
|
1206
|
+
inlineHint: "<subcommand>",
|
|
1207
|
+
subcommands: [
|
|
1208
|
+
{
|
|
1209
|
+
name: "add",
|
|
1210
|
+
description: "Add an SSH host",
|
|
1211
|
+
usage: "<name> --host <host> [--user <user>] [--port <port>] [--key <keyPath>]",
|
|
1212
|
+
},
|
|
1213
|
+
{ name: "list", description: "List all configured SSH hosts" },
|
|
1214
|
+
{ name: "remove", description: "Remove an SSH host", usage: "<name> [--scope project|user]" },
|
|
1215
|
+
{ name: "help", description: "Show help message" },
|
|
1216
|
+
],
|
|
1217
|
+
allowArgs: true,
|
|
1218
|
+
handle: handleSshAcp,
|
|
1219
|
+
handleTui: async (command, runtime) => {
|
|
1220
|
+
runtime.ctx.editor.addToHistory(command.text);
|
|
1221
|
+
runtime.ctx.editor.setText("");
|
|
1222
|
+
await runtime.ctx.handleSSHCommand(command.text);
|
|
1223
|
+
},
|
|
1224
|
+
},
|
|
1225
|
+
{
|
|
1226
|
+
name: "new",
|
|
1227
|
+
description: "Start a new session",
|
|
1228
|
+
handleTui: async (_command, runtime) => {
|
|
1229
|
+
runtime.ctx.editor.setText("");
|
|
1230
|
+
await runtime.ctx.handleClearCommand();
|
|
1231
|
+
},
|
|
1232
|
+
},
|
|
1233
|
+
{
|
|
1234
|
+
name: "fresh",
|
|
1235
|
+
description: "Reset provider stream state without changing the local transcript",
|
|
1236
|
+
handle: async (_command, runtime) => {
|
|
1237
|
+
const result = runtime.session.freshSession();
|
|
1238
|
+
if (!result) {
|
|
1239
|
+
await runtime.output(
|
|
1240
|
+
"Wait for the current response to finish or abort it before refreshing provider state.",
|
|
1241
|
+
);
|
|
1242
|
+
return commandConsumed();
|
|
1243
|
+
}
|
|
1244
|
+
await runtime.output(formatFreshSessionResult(result));
|
|
1245
|
+
return commandConsumed();
|
|
1246
|
+
},
|
|
1247
|
+
handleTui: async (_command, runtime) => {
|
|
1248
|
+
runtime.ctx.editor.setText("");
|
|
1249
|
+
await runtime.ctx.handleFreshCommand();
|
|
1250
|
+
},
|
|
1251
|
+
},
|
|
1252
|
+
{
|
|
1253
|
+
name: "drop",
|
|
1254
|
+
description: "Delete the current session and start a new one",
|
|
1255
|
+
handleTui: async (_command, runtime) => {
|
|
1256
|
+
runtime.ctx.editor.setText("");
|
|
1257
|
+
await runtime.ctx.handleDropCommand();
|
|
1258
|
+
},
|
|
1259
|
+
},
|
|
1260
|
+
{
|
|
1261
|
+
name: "compact",
|
|
1262
|
+
description: "Manually compact the session context",
|
|
1263
|
+
acpDescription: "Compact the conversation",
|
|
1264
|
+
subcommands: COMPACT_MODES.map(mode => ({
|
|
1265
|
+
name: mode.name,
|
|
1266
|
+
description: mode.description,
|
|
1267
|
+
usage: mode.rejectsFocus ? undefined : "[focus]",
|
|
1268
|
+
})),
|
|
1269
|
+
acpInputHint: `[${COMPACT_MODES.map(mode => mode.name).join("|")}] [focus]`,
|
|
1270
|
+
allowArgs: true,
|
|
1271
|
+
handle: async (command, runtime) => {
|
|
1272
|
+
const parsed = parseCompactArgs(command.args);
|
|
1273
|
+
if ("error" in parsed) return usage(parsed.error, runtime);
|
|
1274
|
+
const before = runtime.session.getContextUsage?.();
|
|
1275
|
+
const beforeTokens = before?.tokens;
|
|
1276
|
+
try {
|
|
1277
|
+
await runtime.session.compact(parsed.instructions, parsed.mode ? { mode: parsed.mode } : undefined);
|
|
1278
|
+
} catch (err) {
|
|
1279
|
+
// Compaction precondition failures (no model, already compacted, too
|
|
1280
|
+
// small) and provider errors propagate as plain Errors; surface them
|
|
1281
|
+
// via runtime.output so they don't fail the ACP prompt turn.
|
|
1282
|
+
return usage(`Compaction failed: ${errorMessage(err)}`, runtime);
|
|
1283
|
+
}
|
|
1284
|
+
const after = runtime.session.getContextUsage?.();
|
|
1285
|
+
const afterTokens = after?.tokens;
|
|
1286
|
+
if (beforeTokens != null && afterTokens != null) {
|
|
1287
|
+
const saved = beforeTokens - afterTokens;
|
|
1288
|
+
await runtime.output(`Compaction complete. Tokens: ${beforeTokens} -> ${afterTokens} (saved ${saved}).`);
|
|
1289
|
+
} else {
|
|
1290
|
+
await runtime.output("Compaction complete.");
|
|
1291
|
+
}
|
|
1292
|
+
return commandConsumed();
|
|
1293
|
+
},
|
|
1294
|
+
handleTui: async (command, runtime) => {
|
|
1295
|
+
const parsed = parseCompactArgs(command.args);
|
|
1296
|
+
runtime.ctx.editor.setText("");
|
|
1297
|
+
if ("error" in parsed) {
|
|
1298
|
+
runtime.ctx.showWarning(parsed.error);
|
|
1299
|
+
return;
|
|
1300
|
+
}
|
|
1301
|
+
await runtime.ctx.handleCompactCommand(parsed.instructions, parsed.mode);
|
|
1302
|
+
},
|
|
1303
|
+
},
|
|
1304
|
+
{
|
|
1305
|
+
name: "shake",
|
|
1306
|
+
description: "Drop heavy content from context (tool results, large blocks)",
|
|
1307
|
+
acpDescription: "Shake heavy content out of the conversation context",
|
|
1308
|
+
subcommands: [
|
|
1309
|
+
{ name: "elide", description: "Strip tool results + large blocks (default)" },
|
|
1310
|
+
{ name: "images", description: "Strip image blocks" },
|
|
1311
|
+
],
|
|
1312
|
+
acpInputHint: "[elide|images]",
|
|
1313
|
+
allowArgs: true,
|
|
1314
|
+
handle: async (command, runtime) => {
|
|
1315
|
+
const mode = parseShakeMode(command.args);
|
|
1316
|
+
if (typeof mode !== "string") return usage(mode.error, runtime);
|
|
1317
|
+
const result = await runtime.session.shake(mode);
|
|
1318
|
+
await runtime.output(formatShakeSummary(result));
|
|
1319
|
+
return commandConsumed();
|
|
1320
|
+
},
|
|
1321
|
+
handleTui: async (command, runtime) => {
|
|
1322
|
+
runtime.ctx.editor.setText("");
|
|
1323
|
+
const mode = parseShakeMode(command.args);
|
|
1324
|
+
if (typeof mode !== "string") {
|
|
1325
|
+
runtime.ctx.showWarning(mode.error);
|
|
1326
|
+
return;
|
|
1327
|
+
}
|
|
1328
|
+
await runtime.ctx.handleShakeCommand(mode);
|
|
1329
|
+
},
|
|
1330
|
+
},
|
|
1331
|
+
{
|
|
1332
|
+
name: "handoff",
|
|
1333
|
+
description: "Hand off session context to a new session",
|
|
1334
|
+
inlineHint: "[focus instructions]",
|
|
1335
|
+
allowArgs: true,
|
|
1336
|
+
handleTui: async (command, runtime) => {
|
|
1337
|
+
const customInstructions = command.args || undefined;
|
|
1338
|
+
runtime.ctx.editor.setText("");
|
|
1339
|
+
await runtime.ctx.handleHandoffCommand(customInstructions);
|
|
1340
|
+
},
|
|
1341
|
+
},
|
|
1342
|
+
{
|
|
1343
|
+
name: "resume",
|
|
1344
|
+
description: "Resume a different session",
|
|
1345
|
+
handleTui: (_command, runtime) => {
|
|
1346
|
+
runtime.ctx.showSessionSelector();
|
|
1347
|
+
runtime.ctx.editor.setText("");
|
|
1348
|
+
},
|
|
1349
|
+
},
|
|
1350
|
+
{
|
|
1351
|
+
name: "btw",
|
|
1352
|
+
description: "Ask an ephemeral side question using the current session context",
|
|
1353
|
+
inlineHint: "<question>",
|
|
1354
|
+
allowArgs: true,
|
|
1355
|
+
handleTui: async (command, runtime) => {
|
|
1356
|
+
const question = command.text.slice(`/${command.name}`.length).trim();
|
|
1357
|
+
runtime.ctx.editor.setText("");
|
|
1358
|
+
await runtime.ctx.handleBtwCommand(question);
|
|
1359
|
+
},
|
|
1360
|
+
},
|
|
1361
|
+
{
|
|
1362
|
+
name: "tan",
|
|
1363
|
+
description: "Run a full background agent on tangential work",
|
|
1364
|
+
inlineHint: "<work>",
|
|
1365
|
+
allowArgs: true,
|
|
1366
|
+
handleTui: async (command, runtime) => {
|
|
1367
|
+
const work = command.text.slice(`/${command.name}`.length).trim();
|
|
1368
|
+
runtime.ctx.editor.setText("");
|
|
1369
|
+
await runtime.ctx.handleTanCommand(work);
|
|
1370
|
+
},
|
|
1371
|
+
},
|
|
1372
|
+
{
|
|
1373
|
+
name: "omfg",
|
|
1374
|
+
description: "Forge a TTSR rule from a complaint to stop a recurring behavior",
|
|
1375
|
+
inlineHint: "<complaint>",
|
|
1376
|
+
allowArgs: true,
|
|
1377
|
+
handleTui: async (command, runtime) => {
|
|
1378
|
+
const complaint = command.text.slice(`/${command.name}`.length).trim();
|
|
1379
|
+
runtime.ctx.editor.setText("");
|
|
1380
|
+
await runtime.ctx.handleOmfgCommand(complaint);
|
|
1381
|
+
},
|
|
1382
|
+
},
|
|
1383
|
+
{
|
|
1384
|
+
name: "retry",
|
|
1385
|
+
description: "Retry the last failed agent turn",
|
|
1386
|
+
handleTui: async (_command, runtime) => {
|
|
1387
|
+
const didRetry = await runtime.ctx.session.retry();
|
|
1388
|
+
if (!didRetry) {
|
|
1389
|
+
runtime.ctx.showStatus("Nothing to retry");
|
|
1390
|
+
}
|
|
1391
|
+
runtime.ctx.editor.setText("");
|
|
1392
|
+
},
|
|
1393
|
+
},
|
|
1394
|
+
{
|
|
1395
|
+
name: "debug",
|
|
1396
|
+
description: "Open debug tools selector",
|
|
1397
|
+
allowArgs: true,
|
|
1398
|
+
subcommands: [
|
|
1399
|
+
{
|
|
1400
|
+
name: "dump-next-request",
|
|
1401
|
+
description: "Dump the next AI provider HTTP request as JSON",
|
|
1402
|
+
usage: "<path>",
|
|
1403
|
+
},
|
|
1404
|
+
],
|
|
1405
|
+
handle: async (command, runtime) =>
|
|
1406
|
+
handleDebugSubcommand(command.args, runtime.cwd, text => runtime.output(text)),
|
|
1407
|
+
handleTui: async (command, runtime) => {
|
|
1408
|
+
const args = command.args.trim();
|
|
1409
|
+
if (args.length === 0) {
|
|
1410
|
+
runtime.ctx.showDebugSelector();
|
|
1411
|
+
} else {
|
|
1412
|
+
await handleDebugSubcommand(args, runtime.ctx.sessionManager.getCwd(), text =>
|
|
1413
|
+
runtime.ctx.showStatus(text),
|
|
1414
|
+
);
|
|
1415
|
+
}
|
|
1416
|
+
runtime.ctx.editor.setText("");
|
|
1417
|
+
},
|
|
1418
|
+
},
|
|
1419
|
+
{
|
|
1420
|
+
name: "memory",
|
|
1421
|
+
description: "Inspect and operate memory maintenance",
|
|
1422
|
+
acpDescription: "Manage memory",
|
|
1423
|
+
acpInputHint: "<subcommand>",
|
|
1424
|
+
subcommands: [
|
|
1425
|
+
{ name: "view", description: "Show current memory injection payload" },
|
|
1426
|
+
{ name: "stats", description: "Show memory backend statistics" },
|
|
1427
|
+
{ name: "diagnose", description: "Run memory backend diagnostics" },
|
|
1428
|
+
{ name: "clear", description: "Clear persisted memory data and artifacts" },
|
|
1429
|
+
{ name: "reset", description: "Alias for clear" },
|
|
1430
|
+
{ name: "enqueue", description: "Enqueue memory consolidation maintenance" },
|
|
1431
|
+
{ name: "rebuild", description: "Alias for enqueue" },
|
|
1432
|
+
{ name: "mm list", description: "List mental models on the active bank" },
|
|
1433
|
+
{ name: "mm show", description: "Show one mental model (id required)" },
|
|
1434
|
+
{
|
|
1435
|
+
name: "mm refresh",
|
|
1436
|
+
description: "Refresh auto-refresh models bank-wide, or one model by id",
|
|
1437
|
+
},
|
|
1438
|
+
{ name: "mm history", description: "Diff the change history of a mental model" },
|
|
1439
|
+
{ name: "mm seed", description: "Create any built-in mental models that are missing" },
|
|
1440
|
+
{ name: "mm delete", description: "Delete a mental model from the bank (id required)" },
|
|
1441
|
+
{ name: "mm reload", description: "Re-pull the cached <mental_models> block" },
|
|
1442
|
+
],
|
|
1443
|
+
allowArgs: true,
|
|
1444
|
+
handle: async (command, runtime) => {
|
|
1445
|
+
const verb = (command.args.trim().split(/\s+/)[0] ?? "").toLowerCase() || "view";
|
|
1446
|
+
const backend = await resolveMemoryBackend(runtime.settings);
|
|
1447
|
+
switch (verb) {
|
|
1448
|
+
case "view": {
|
|
1449
|
+
const payload = await backend.buildDeveloperInstructions(
|
|
1450
|
+
runtime.settings.getAgentDir(),
|
|
1451
|
+
runtime.settings,
|
|
1452
|
+
runtime.session,
|
|
1453
|
+
);
|
|
1454
|
+
await runtime.output(payload || "Memory payload is empty.");
|
|
1455
|
+
return commandConsumed();
|
|
1456
|
+
}
|
|
1457
|
+
case "clear":
|
|
1458
|
+
case "reset": {
|
|
1459
|
+
await backend.clear(runtime.settings.getAgentDir(), runtime.cwd, runtime.session);
|
|
1460
|
+
await runtime.session.refreshBaseSystemPrompt();
|
|
1461
|
+
await runtime.output("Memory cleared.");
|
|
1462
|
+
return commandConsumed();
|
|
1463
|
+
}
|
|
1464
|
+
case "enqueue":
|
|
1465
|
+
case "rebuild": {
|
|
1466
|
+
await backend.enqueue(runtime.settings.getAgentDir(), runtime.cwd, runtime.session);
|
|
1467
|
+
await runtime.output("Memory consolidation enqueued.");
|
|
1468
|
+
return commandConsumed();
|
|
1469
|
+
}
|
|
1470
|
+
case "stats":
|
|
1471
|
+
case "diagnose": {
|
|
1472
|
+
const hook = verb === "stats" ? backend.stats : backend.diagnose;
|
|
1473
|
+
const payload = await hook?.(runtime.settings.getAgentDir(), runtime.cwd, runtime.session);
|
|
1474
|
+
await runtime.output(payload ?? `Memory ${verb} is not available for the ${backend.id} backend.`);
|
|
1475
|
+
return commandConsumed();
|
|
1476
|
+
}
|
|
1477
|
+
case "mm":
|
|
1478
|
+
return usage(
|
|
1479
|
+
"Mental-model maintenance via /memory mm is unsupported in ACP mode; use the hindsight HTTP API directly.",
|
|
1480
|
+
runtime,
|
|
1481
|
+
);
|
|
1482
|
+
default:
|
|
1483
|
+
return usage("Usage: /memory <view|stats|diagnose|clear|reset|enqueue|rebuild>", runtime);
|
|
1484
|
+
}
|
|
1485
|
+
},
|
|
1486
|
+
handleTui: async (command, runtime) => {
|
|
1487
|
+
runtime.ctx.editor.setText("");
|
|
1488
|
+
await runtime.ctx.handleMemoryCommand(command.text);
|
|
1489
|
+
},
|
|
1490
|
+
},
|
|
1491
|
+
{
|
|
1492
|
+
name: "rename",
|
|
1493
|
+
description: "Rename the current session",
|
|
1494
|
+
inlineHint: "<title>",
|
|
1495
|
+
allowArgs: true,
|
|
1496
|
+
handle: async (command, runtime) => {
|
|
1497
|
+
if (!command.args) return usage("Usage: /rename <title>", runtime);
|
|
1498
|
+
const ok = await runtime.sessionManager.setSessionName(command.args, "user");
|
|
1499
|
+
if (!ok) {
|
|
1500
|
+
await runtime.output("Session name not changed (a user-set name takes precedence).");
|
|
1501
|
+
return commandConsumed();
|
|
1502
|
+
}
|
|
1503
|
+
await runtime.notifyTitleChanged?.();
|
|
1504
|
+
await runtime.output(`Session renamed to ${command.args}.`);
|
|
1505
|
+
return commandConsumed();
|
|
1506
|
+
},
|
|
1507
|
+
handleTui: async (command, runtime) => {
|
|
1508
|
+
const title = command.args.trim();
|
|
1509
|
+
if (!title) {
|
|
1510
|
+
runtime.ctx.showError("Usage: /rename <title>");
|
|
1511
|
+
runtime.ctx.editor.setText("");
|
|
1512
|
+
return;
|
|
1513
|
+
}
|
|
1514
|
+
runtime.ctx.editor.setText("");
|
|
1515
|
+
await runtime.ctx.handleRenameCommand(title);
|
|
1516
|
+
},
|
|
1517
|
+
},
|
|
1518
|
+
{
|
|
1519
|
+
name: "move",
|
|
1520
|
+
description: "Move session to a different working directory",
|
|
1521
|
+
acpDescription: "Move the current session file",
|
|
1522
|
+
inlineHint: "<path>",
|
|
1523
|
+
allowArgs: true,
|
|
1524
|
+
handle: async (command, runtime) => {
|
|
1525
|
+
if (runtime.session.isStreaming) return usage("Cannot move while streaming.", runtime);
|
|
1526
|
+
if (!command.args) return usage("Usage: /move <path>", runtime);
|
|
1527
|
+
const resolvedPath = path.resolve(runtime.cwd, command.args);
|
|
1528
|
+
let isDirectory: boolean;
|
|
1529
|
+
try {
|
|
1530
|
+
isDirectory = (await fs.stat(resolvedPath)).isDirectory();
|
|
1531
|
+
} catch {
|
|
1532
|
+
return usage(`Directory does not exist or is not a directory: ${resolvedPath}`, runtime);
|
|
1533
|
+
}
|
|
1534
|
+
if (!isDirectory) return usage(`Directory does not exist or is not a directory: ${resolvedPath}`, runtime);
|
|
1535
|
+
try {
|
|
1536
|
+
await runtime.sessionManager.flush();
|
|
1537
|
+
await runtime.sessionManager.moveTo(resolvedPath);
|
|
1538
|
+
} catch (err) {
|
|
1539
|
+
return usage(`Move failed: ${errorMessage(err)}`, runtime);
|
|
1540
|
+
}
|
|
1541
|
+
setProjectDir(resolvedPath);
|
|
1542
|
+
// Reload plugin/capability caches so the next prompt sees commands and
|
|
1543
|
+
// capabilities scoped to the new cwd.
|
|
1544
|
+
await runtime.reloadPlugins();
|
|
1545
|
+
await runtime.notifyTitleChanged?.();
|
|
1546
|
+
await runtime.output(`Session moved to ${runtime.sessionManager.getCwd()}.`);
|
|
1547
|
+
return commandConsumed();
|
|
1548
|
+
},
|
|
1549
|
+
handleTui: async (command, runtime) => {
|
|
1550
|
+
const targetPath = command.args;
|
|
1551
|
+
if (!targetPath) {
|
|
1552
|
+
runtime.ctx.showError("Usage: /move <path>");
|
|
1553
|
+
runtime.ctx.editor.setText("");
|
|
1554
|
+
return;
|
|
1555
|
+
}
|
|
1556
|
+
runtime.ctx.editor.setText("");
|
|
1557
|
+
await runtime.ctx.handleMoveCommand(targetPath);
|
|
1558
|
+
},
|
|
1559
|
+
},
|
|
1560
|
+
{
|
|
1561
|
+
name: "exit",
|
|
1562
|
+
description: "Exit the application",
|
|
1563
|
+
handleTui: shutdownHandlerTui,
|
|
1564
|
+
},
|
|
1565
|
+
{
|
|
1566
|
+
name: "marketplace",
|
|
1567
|
+
description: "Manage marketplace plugin sources and installed plugins",
|
|
1568
|
+
acpDescription: "Manage plugins from marketplaces",
|
|
1569
|
+
acpInputHint: "<subcommand>",
|
|
1570
|
+
subcommands: [
|
|
1571
|
+
{ name: "add", description: "Add a marketplace source", usage: "<source>" },
|
|
1572
|
+
{ name: "remove", description: "Remove a marketplace source", usage: "<name>" },
|
|
1573
|
+
{ name: "update", description: "Update marketplace catalog(s)", usage: "[name]" },
|
|
1574
|
+
{ name: "list", description: "List configured marketplaces" },
|
|
1575
|
+
{ name: "discover", description: "Browse available plugins", usage: "[marketplace]" },
|
|
1576
|
+
{
|
|
1577
|
+
name: "install",
|
|
1578
|
+
description: "Install a plugin (interactive browser if no args)",
|
|
1579
|
+
usage: "[--force] [name@marketplace]",
|
|
1580
|
+
},
|
|
1581
|
+
{ name: "uninstall", description: "Uninstall a plugin (selector if no args)", usage: "[name@marketplace]" },
|
|
1582
|
+
{ name: "installed", description: "List installed marketplace plugins" },
|
|
1583
|
+
{ name: "upgrade", description: "Upgrade outdated plugins", usage: "[name@marketplace]" },
|
|
1584
|
+
{ name: "help", description: "Show usage guide" },
|
|
1585
|
+
],
|
|
1586
|
+
allowArgs: true,
|
|
1587
|
+
handle: async (command, runtime) => {
|
|
1588
|
+
const { verb, rest } = parseSubcommand(command.args);
|
|
1589
|
+
if (!verb) {
|
|
1590
|
+
try {
|
|
1591
|
+
const manager = await createMarketplaceManager(runtime);
|
|
1592
|
+
const marketplaces = await manager.listMarketplaces();
|
|
1593
|
+
if (marketplaces.length === 0) {
|
|
1594
|
+
await runtime.output(
|
|
1595
|
+
"No marketplaces configured.\n\nGet started:\n /marketplace add anthropics/claude-plugins-official\n\nThen browse with /marketplace discover",
|
|
1596
|
+
);
|
|
1597
|
+
} else {
|
|
1598
|
+
const lines = marketplaces.map(m => ` ${m.name} ${m.sourceUri}`);
|
|
1599
|
+
await runtime.output(
|
|
1600
|
+
`Marketplaces:\n${lines.join("\n")}\n\nUse /marketplace discover to browse plugins, or /marketplace help for all commands`,
|
|
1601
|
+
);
|
|
1602
|
+
}
|
|
1603
|
+
return commandConsumed();
|
|
1604
|
+
} catch (err) {
|
|
1605
|
+
return usage(`Marketplace error: ${errorMessage(err)}`, runtime);
|
|
1606
|
+
}
|
|
1607
|
+
}
|
|
1608
|
+
if (verb === "help") {
|
|
1609
|
+
await runtime.output(
|
|
1610
|
+
[
|
|
1611
|
+
"Marketplace commands:",
|
|
1612
|
+
" /marketplace List configured marketplaces",
|
|
1613
|
+
" /marketplace add <source> Add a marketplace (e.g. owner/repo)",
|
|
1614
|
+
" /marketplace remove <name> Remove a marketplace",
|
|
1615
|
+
" /marketplace update [name] Re-fetch catalog(s)",
|
|
1616
|
+
" /marketplace list List configured marketplaces",
|
|
1617
|
+
" /marketplace discover [marketplace] Browse available plugins",
|
|
1618
|
+
" /marketplace install <name@marketplace> Install a plugin",
|
|
1619
|
+
" /marketplace uninstall <name@marketplace> Uninstall a plugin",
|
|
1620
|
+
" /marketplace installed List installed plugins",
|
|
1621
|
+
" /marketplace upgrade [name@marketplace] Upgrade plugin(s)",
|
|
1622
|
+
"",
|
|
1623
|
+
"Quick start:",
|
|
1624
|
+
" /marketplace add anthropics/claude-plugins-official",
|
|
1625
|
+
].join("\n"),
|
|
1626
|
+
);
|
|
1627
|
+
return commandConsumed();
|
|
1628
|
+
}
|
|
1629
|
+
if ((verb === "install" || verb === "uninstall") && !rest) {
|
|
1630
|
+
return usage(
|
|
1631
|
+
"Interactive plugin pickers are TUI-only. Pass an explicit name@marketplace argument.",
|
|
1632
|
+
runtime,
|
|
1633
|
+
);
|
|
1634
|
+
}
|
|
1635
|
+
try {
|
|
1636
|
+
const manager = await createMarketplaceManager(runtime);
|
|
1637
|
+
switch (verb) {
|
|
1638
|
+
case "add": {
|
|
1639
|
+
if (!rest) return usage("Usage: /marketplace add <source>", runtime);
|
|
1640
|
+
const entry = await manager.addMarketplace(rest);
|
|
1641
|
+
await runtime.output(`Added marketplace: ${entry.name}`);
|
|
1642
|
+
return commandConsumed();
|
|
1643
|
+
}
|
|
1644
|
+
case "remove":
|
|
1645
|
+
case "rm": {
|
|
1646
|
+
if (!rest) return usage("Usage: /marketplace remove <name>", runtime);
|
|
1647
|
+
await manager.removeMarketplace(rest);
|
|
1648
|
+
await runtime.output(`Removed marketplace: ${rest}`);
|
|
1649
|
+
return commandConsumed();
|
|
1650
|
+
}
|
|
1651
|
+
case "update": {
|
|
1652
|
+
if (rest) {
|
|
1653
|
+
await manager.updateMarketplace(rest);
|
|
1654
|
+
await runtime.output(`Updated marketplace: ${rest}`);
|
|
1655
|
+
} else {
|
|
1656
|
+
const results = await manager.updateAllMarketplaces();
|
|
1657
|
+
await runtime.output(`Updated ${results.length} marketplace(s)`);
|
|
1658
|
+
}
|
|
1659
|
+
return commandConsumed();
|
|
1660
|
+
}
|
|
1661
|
+
case "list": {
|
|
1662
|
+
const marketplaces = await manager.listMarketplaces();
|
|
1663
|
+
if (marketplaces.length === 0) {
|
|
1664
|
+
await runtime.output("No marketplaces configured.");
|
|
1665
|
+
} else {
|
|
1666
|
+
const lines = marketplaces.map(m => ` ${m.name} ${m.sourceUri}`);
|
|
1667
|
+
await runtime.output(`Marketplaces:\n${lines.join("\n")}`);
|
|
1668
|
+
}
|
|
1669
|
+
return commandConsumed();
|
|
1670
|
+
}
|
|
1671
|
+
case "discover": {
|
|
1672
|
+
const plugins = await manager.listAvailablePlugins(rest || undefined);
|
|
1673
|
+
if (plugins.length === 0) {
|
|
1674
|
+
const marketplaces = await manager.listMarketplaces();
|
|
1675
|
+
await runtime.output(
|
|
1676
|
+
marketplaces.length === 0
|
|
1677
|
+
? "No marketplaces configured. Try:\n /marketplace add anthropics/claude-plugins-official"
|
|
1678
|
+
: "No plugins available in configured marketplaces",
|
|
1679
|
+
);
|
|
1680
|
+
return commandConsumed();
|
|
1681
|
+
}
|
|
1682
|
+
const lines = ["Available plugins:"];
|
|
1683
|
+
for (const plugin of plugins) {
|
|
1684
|
+
lines.push(` - ${plugin.name}${plugin.version ? `@${plugin.version}` : ""}`);
|
|
1685
|
+
if (plugin.description) lines.push(` ${plugin.description}`);
|
|
1686
|
+
}
|
|
1687
|
+
await runtime.output(lines.join("\n"));
|
|
1688
|
+
return commandConsumed();
|
|
1689
|
+
}
|
|
1690
|
+
case "install": {
|
|
1691
|
+
const parsed = parseMarketplaceInstallArgs(rest);
|
|
1692
|
+
if ("error" in parsed) return usage(parsed.error, runtime);
|
|
1693
|
+
const atIndex = parsed.installSpec.lastIndexOf("@");
|
|
1694
|
+
const pluginName = parsed.installSpec.slice(0, atIndex);
|
|
1695
|
+
const marketplace = parsed.installSpec.slice(atIndex + 1);
|
|
1696
|
+
await manager.installPlugin(pluginName, marketplace, { force: parsed.force, scope: parsed.scope });
|
|
1697
|
+
await runtime.reloadPlugins();
|
|
1698
|
+
await runtime.output(`Installed ${pluginName} from ${marketplace}`);
|
|
1699
|
+
return commandConsumed();
|
|
1700
|
+
}
|
|
1701
|
+
case "uninstall": {
|
|
1702
|
+
const parsed = parsePluginScopeArgs(
|
|
1703
|
+
rest,
|
|
1704
|
+
"Usage: /marketplace uninstall [--scope user|project] <name@marketplace>",
|
|
1705
|
+
);
|
|
1706
|
+
if ("error" in parsed) return usage(parsed.error, runtime);
|
|
1707
|
+
await manager.uninstallPlugin(parsed.pluginId, parsed.scope);
|
|
1708
|
+
await runtime.reloadPlugins();
|
|
1709
|
+
await runtime.output(`Uninstalled ${parsed.pluginId}`);
|
|
1710
|
+
return commandConsumed();
|
|
1711
|
+
}
|
|
1712
|
+
case "installed": {
|
|
1713
|
+
const installed = await manager.listInstalledPlugins();
|
|
1714
|
+
if (installed.length === 0) {
|
|
1715
|
+
await runtime.output("No marketplace plugins installed");
|
|
1716
|
+
} else {
|
|
1717
|
+
const lines = installed.map(
|
|
1718
|
+
p => ` ${p.id} [${p.scope}]${p.shadowedBy ? " [shadowed]" : ""} (${p.entries.length} entry)`,
|
|
1719
|
+
);
|
|
1720
|
+
await runtime.output(`Installed plugins:\n${lines.join("\n")}`);
|
|
1721
|
+
}
|
|
1722
|
+
return commandConsumed();
|
|
1723
|
+
}
|
|
1724
|
+
case "upgrade": {
|
|
1725
|
+
if (rest) {
|
|
1726
|
+
const parsed = parsePluginScopeArgs(
|
|
1727
|
+
rest,
|
|
1728
|
+
"Usage: /marketplace upgrade [--scope user|project] <name@marketplace>",
|
|
1729
|
+
);
|
|
1730
|
+
if ("error" in parsed) return usage(parsed.error, runtime);
|
|
1731
|
+
const result = await manager.upgradePlugin(parsed.pluginId, parsed.scope);
|
|
1732
|
+
await runtime.reloadPlugins();
|
|
1733
|
+
await runtime.output(`Upgraded ${parsed.pluginId} to ${result.version}`);
|
|
1734
|
+
return commandConsumed();
|
|
1735
|
+
}
|
|
1736
|
+
const results = await manager.upgradeAllPlugins();
|
|
1737
|
+
if (results.length === 0) {
|
|
1738
|
+
await runtime.output("All marketplace plugins are up to date");
|
|
1739
|
+
} else {
|
|
1740
|
+
await runtime.reloadPlugins();
|
|
1741
|
+
const lines = results.map(r => ` ${r.pluginId}: ${r.from} -> ${r.to}`);
|
|
1742
|
+
await runtime.output(`Upgraded ${results.length} plugin(s):\n${lines.join("\n")}`);
|
|
1743
|
+
}
|
|
1744
|
+
return commandConsumed();
|
|
1745
|
+
}
|
|
1746
|
+
default:
|
|
1747
|
+
return usage(
|
|
1748
|
+
`Unknown /marketplace subcommand: ${verb}. Use /marketplace help for available commands.`,
|
|
1749
|
+
runtime,
|
|
1750
|
+
);
|
|
1751
|
+
}
|
|
1752
|
+
} catch (err) {
|
|
1753
|
+
return usage(`Marketplace error: ${errorMessage(err)}`, runtime);
|
|
1754
|
+
}
|
|
1755
|
+
},
|
|
1756
|
+
handleTui: async (command, runtime) => {
|
|
1757
|
+
runtime.ctx.editor.setText("");
|
|
1758
|
+
const args = command.args.trim().split(/\s+/);
|
|
1759
|
+
const sub = args[0] || "install";
|
|
1760
|
+
const rest = args.slice(1).join(" ").trim();
|
|
1761
|
+
|
|
1762
|
+
// /marketplace (no args) or /marketplace install (no args) → interactive browser
|
|
1763
|
+
if ((sub === "install" && !rest) || (!args[0] && !command.args.trim())) {
|
|
1764
|
+
try {
|
|
1765
|
+
runtime.ctx.showPluginSelector("install");
|
|
1766
|
+
} catch (err) {
|
|
1767
|
+
runtime.ctx.showStatus(`Marketplace error: ${err}`);
|
|
1768
|
+
}
|
|
1769
|
+
return;
|
|
1770
|
+
}
|
|
1771
|
+
|
|
1772
|
+
const mgr = new MarketplaceManager({
|
|
1773
|
+
marketplacesRegistryPath: getMarketplacesRegistryPath(),
|
|
1774
|
+
installedRegistryPath: getInstalledPluginsRegistryPath(),
|
|
1775
|
+
projectInstalledRegistryPath: await resolveOrDefaultProjectRegistryPath(
|
|
1776
|
+
runtime.ctx.sessionManager.getCwd(),
|
|
1777
|
+
),
|
|
1778
|
+
marketplacesCacheDir: getMarketplacesCacheDir(),
|
|
1779
|
+
pluginsCacheDir: getPluginsCacheDir(),
|
|
1780
|
+
clearPluginRootsCache: clearPluginRootsAndCaches,
|
|
1781
|
+
});
|
|
1782
|
+
|
|
1783
|
+
try {
|
|
1784
|
+
switch (sub) {
|
|
1785
|
+
case "add": {
|
|
1786
|
+
if (!rest) {
|
|
1787
|
+
runtime.ctx.showStatus("Usage: /marketplace add <source>");
|
|
1788
|
+
return;
|
|
1789
|
+
}
|
|
1790
|
+
const entry = await mgr.addMarketplace(rest);
|
|
1791
|
+
runtime.ctx.showStatus(`Added marketplace: ${entry.name}`);
|
|
1792
|
+
break;
|
|
1793
|
+
}
|
|
1794
|
+
case "remove":
|
|
1795
|
+
case "rm": {
|
|
1796
|
+
if (!rest) {
|
|
1797
|
+
runtime.ctx.showStatus("Usage: /marketplace remove <name>");
|
|
1798
|
+
return;
|
|
1799
|
+
}
|
|
1800
|
+
await mgr.removeMarketplace(rest);
|
|
1801
|
+
runtime.ctx.showStatus(`Removed marketplace: ${rest}`);
|
|
1802
|
+
break;
|
|
1803
|
+
}
|
|
1804
|
+
case "update": {
|
|
1805
|
+
if (rest) {
|
|
1806
|
+
await mgr.updateMarketplace(rest);
|
|
1807
|
+
runtime.ctx.showStatus(`Updated marketplace: ${rest}`);
|
|
1808
|
+
} else {
|
|
1809
|
+
const results = await mgr.updateAllMarketplaces();
|
|
1810
|
+
runtime.ctx.showStatus(`Updated ${results.length} marketplace(s)`);
|
|
1811
|
+
}
|
|
1812
|
+
break;
|
|
1813
|
+
}
|
|
1814
|
+
case "discover": {
|
|
1815
|
+
const plugins = await mgr.listAvailablePlugins(rest || undefined);
|
|
1816
|
+
if (plugins.length === 0) {
|
|
1817
|
+
const marketplaces = await mgr.listMarketplaces();
|
|
1818
|
+
if (marketplaces.length === 0) {
|
|
1819
|
+
runtime.ctx.showStatus(
|
|
1820
|
+
"No marketplaces configured. Try:\n /marketplace add anthropics/claude-plugins-official",
|
|
1821
|
+
);
|
|
1822
|
+
} else {
|
|
1823
|
+
runtime.ctx.showStatus("No plugins available in configured marketplaces");
|
|
1824
|
+
}
|
|
1825
|
+
} else {
|
|
1826
|
+
const lines = plugins.map(
|
|
1827
|
+
p =>
|
|
1828
|
+
` ${p.name}${p.version ? `@${p.version}` : ""}${p.description ? ` - ${p.description}` : ""}`,
|
|
1829
|
+
);
|
|
1830
|
+
runtime.ctx.showStatus(`Available plugins:\n${lines.join("\n")}`);
|
|
1831
|
+
}
|
|
1832
|
+
break;
|
|
1833
|
+
}
|
|
1834
|
+
case "install": {
|
|
1835
|
+
// Parse: /marketplace install [--force] [--scope user|project] name@marketplace
|
|
1836
|
+
const parsed = parseMarketplaceInstallArgs(rest);
|
|
1837
|
+
if ("error" in parsed) {
|
|
1838
|
+
runtime.ctx.showStatus(parsed.error);
|
|
1839
|
+
return;
|
|
1840
|
+
}
|
|
1841
|
+
const atIdx = parsed.installSpec.lastIndexOf("@");
|
|
1842
|
+
const name = parsed.installSpec.slice(0, atIdx);
|
|
1843
|
+
const marketplace = parsed.installSpec.slice(atIdx + 1);
|
|
1844
|
+
await mgr.installPlugin(name, marketplace, { force: parsed.force, scope: parsed.scope });
|
|
1845
|
+
runtime.ctx.showStatus(`Installed ${name} from ${marketplace}`);
|
|
1846
|
+
break;
|
|
1847
|
+
}
|
|
1848
|
+
case "uninstall": {
|
|
1849
|
+
if (!rest) {
|
|
1850
|
+
// No args → open interactive uninstall selector
|
|
1851
|
+
runtime.ctx.showPluginSelector("uninstall");
|
|
1852
|
+
return;
|
|
1853
|
+
}
|
|
1854
|
+
const uninstArgs = parsePluginScopeArgs(
|
|
1855
|
+
rest,
|
|
1856
|
+
"Usage: /marketplace uninstall [--scope user|project] <name@marketplace>",
|
|
1857
|
+
);
|
|
1858
|
+
if ("error" in uninstArgs) {
|
|
1859
|
+
runtime.ctx.showStatus(uninstArgs.error);
|
|
1860
|
+
return;
|
|
1861
|
+
}
|
|
1862
|
+
await mgr.uninstallPlugin(uninstArgs.pluginId, uninstArgs.scope);
|
|
1863
|
+
runtime.ctx.showStatus(`Uninstalled ${uninstArgs.pluginId}`);
|
|
1864
|
+
break;
|
|
1865
|
+
}
|
|
1866
|
+
case "installed": {
|
|
1867
|
+
const installed = await mgr.listInstalledPlugins();
|
|
1868
|
+
if (installed.length === 0) {
|
|
1869
|
+
runtime.ctx.showStatus("No marketplace plugins installed");
|
|
1870
|
+
} else {
|
|
1871
|
+
const lines = installed.map(
|
|
1872
|
+
p => ` ${p.id} [${p.scope}]${p.shadowedBy ? " [shadowed]" : ""} (${p.entries.length} entry)`,
|
|
1873
|
+
);
|
|
1874
|
+
runtime.ctx.showStatus(`Installed plugins:\n${lines.join("\n")}`);
|
|
1875
|
+
}
|
|
1876
|
+
break;
|
|
1877
|
+
}
|
|
1878
|
+
case "upgrade": {
|
|
1879
|
+
if (rest) {
|
|
1880
|
+
const upArgs = parsePluginScopeArgs(
|
|
1881
|
+
rest,
|
|
1882
|
+
"Usage: /marketplace upgrade [--scope user|project] <name@marketplace>",
|
|
1883
|
+
);
|
|
1884
|
+
if ("error" in upArgs) {
|
|
1885
|
+
runtime.ctx.showStatus(upArgs.error);
|
|
1886
|
+
return;
|
|
1887
|
+
}
|
|
1888
|
+
const result = await mgr.upgradePlugin(upArgs.pluginId, upArgs.scope);
|
|
1889
|
+
runtime.ctx.showStatus(`Upgraded ${upArgs.pluginId} to ${result.version}`);
|
|
1890
|
+
} else {
|
|
1891
|
+
const results = await mgr.upgradeAllPlugins();
|
|
1892
|
+
if (results.length === 0) {
|
|
1893
|
+
runtime.ctx.showStatus("All marketplace plugins are up to date");
|
|
1894
|
+
} else {
|
|
1895
|
+
const lines = results.map(r => ` ${r.pluginId}: ${r.from} -> ${r.to}`);
|
|
1896
|
+
runtime.ctx.showStatus(`Upgraded ${results.length} plugin(s):\n${lines.join("\n")}`);
|
|
1897
|
+
}
|
|
1898
|
+
}
|
|
1899
|
+
break;
|
|
1900
|
+
}
|
|
1901
|
+
case "help": {
|
|
1902
|
+
runtime.ctx.showStatus(
|
|
1903
|
+
[
|
|
1904
|
+
"Marketplace commands:",
|
|
1905
|
+
" /marketplace Browse and install plugins",
|
|
1906
|
+
" /marketplace add <source> Add a marketplace (e.g. owner/repo)",
|
|
1907
|
+
" /marketplace remove <name> Remove a marketplace",
|
|
1908
|
+
" /marketplace update [name] Re-fetch catalog(s)",
|
|
1909
|
+
" /marketplace list List configured marketplaces",
|
|
1910
|
+
" /marketplace discover [marketplace] Browse available plugins",
|
|
1911
|
+
" /marketplace install <name@marketplace> Install a plugin",
|
|
1912
|
+
" /marketplace uninstall <name@marketplace> Uninstall a plugin",
|
|
1913
|
+
" /marketplace installed List installed plugins",
|
|
1914
|
+
" /marketplace upgrade [name@marketplace] Upgrade plugin(s)",
|
|
1915
|
+
"",
|
|
1916
|
+
"Quick start:",
|
|
1917
|
+
" /marketplace add anthropics/claude-plugins-official",
|
|
1918
|
+
" /marketplace (opens interactive browser)",
|
|
1919
|
+
].join("\n"),
|
|
1920
|
+
);
|
|
1921
|
+
break;
|
|
1922
|
+
}
|
|
1923
|
+
default: {
|
|
1924
|
+
const marketplaces = await mgr.listMarketplaces();
|
|
1925
|
+
if (marketplaces.length === 0) {
|
|
1926
|
+
runtime.ctx.showStatus(
|
|
1927
|
+
"No marketplaces configured.\n\nGet started:\n /marketplace add anthropics/claude-plugins-official\n\nThen browse plugins with /marketplace or /marketplace discover",
|
|
1928
|
+
);
|
|
1929
|
+
} else {
|
|
1930
|
+
const lines = marketplaces.map(m => ` ${m.name} ${m.sourceUri}`);
|
|
1931
|
+
runtime.ctx.showStatus(
|
|
1932
|
+
`Marketplaces:\n${lines.join("\n")}\n\nUse /marketplace discover to browse plugins, or /marketplace help for all commands`,
|
|
1933
|
+
);
|
|
1934
|
+
}
|
|
1935
|
+
break;
|
|
1936
|
+
}
|
|
1937
|
+
}
|
|
1938
|
+
} catch (err) {
|
|
1939
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1940
|
+
runtime.ctx.showStatus(`Marketplace error: ${msg}`);
|
|
1941
|
+
}
|
|
1942
|
+
},
|
|
1943
|
+
},
|
|
1944
|
+
{
|
|
1945
|
+
name: "plugins",
|
|
1946
|
+
description: "View and manage installed plugins",
|
|
1947
|
+
acpDescription: "Manage plugins",
|
|
1948
|
+
acpInputHint: "[list|enable|disable]",
|
|
1949
|
+
subcommands: [
|
|
1950
|
+
{ name: "list", description: "List all installed plugins (npm + marketplace)" },
|
|
1951
|
+
{ name: "enable", description: "Enable a marketplace plugin", usage: "<name@marketplace>" },
|
|
1952
|
+
{ name: "disable", description: "Disable a marketplace plugin", usage: "<name@marketplace>" },
|
|
1953
|
+
],
|
|
1954
|
+
allowArgs: true,
|
|
1955
|
+
handle: async (command, runtime) => {
|
|
1956
|
+
const { verb, rest } = parseSubcommand(command.args);
|
|
1957
|
+
try {
|
|
1958
|
+
if (verb === "enable" || verb === "disable") {
|
|
1959
|
+
const parsed = parsePluginScopeArgs(
|
|
1960
|
+
rest,
|
|
1961
|
+
`Usage: /plugins ${verb} [--scope user|project] <name@marketplace>`,
|
|
1962
|
+
);
|
|
1963
|
+
if ("error" in parsed) return usage(parsed.error, runtime);
|
|
1964
|
+
const manager = await createMarketplaceManager(runtime);
|
|
1965
|
+
const isEnable = verb === "enable";
|
|
1966
|
+
await manager.setPluginEnabled(parsed.pluginId, isEnable, parsed.scope);
|
|
1967
|
+
await runtime.reloadPlugins();
|
|
1968
|
+
await runtime.output(`${isEnable ? "Enabled" : "Disabled"} ${parsed.pluginId}`);
|
|
1969
|
+
return commandConsumed();
|
|
1970
|
+
}
|
|
1971
|
+
// Default: list
|
|
1972
|
+
const lines: string[] = [];
|
|
1973
|
+
const npmManager = new PluginManager();
|
|
1974
|
+
const npmPlugins = await npmManager.list();
|
|
1975
|
+
if (npmPlugins.length > 0) {
|
|
1976
|
+
lines.push("npm plugins:");
|
|
1977
|
+
for (const plugin of npmPlugins) {
|
|
1978
|
+
const status = plugin.enabled === false ? " (disabled)" : "";
|
|
1979
|
+
lines.push(` ${plugin.name}@${plugin.version}${status}`);
|
|
1980
|
+
}
|
|
1981
|
+
}
|
|
1982
|
+
|
|
1983
|
+
const marketplaceManager = await createMarketplaceManager(runtime);
|
|
1984
|
+
const marketplacePlugins = await marketplaceManager.listInstalledPlugins();
|
|
1985
|
+
if (marketplacePlugins.length > 0) {
|
|
1986
|
+
if (lines.length > 0) lines.push("");
|
|
1987
|
+
lines.push("marketplace plugins:");
|
|
1988
|
+
for (const plugin of marketplacePlugins) {
|
|
1989
|
+
const entry = plugin.entries[0];
|
|
1990
|
+
const status = entry?.enabled === false ? " (disabled)" : "";
|
|
1991
|
+
const shadowed = plugin.shadowedBy ? " [shadowed]" : "";
|
|
1992
|
+
lines.push(` ${plugin.id} v${entry?.version ?? "?"}${status} [${plugin.scope}]${shadowed}`);
|
|
1993
|
+
}
|
|
1994
|
+
}
|
|
1995
|
+
|
|
1996
|
+
await runtime.output(lines.length === 0 ? "No plugins installed" : lines.join("\n"));
|
|
1997
|
+
return commandConsumed();
|
|
1998
|
+
} catch (err) {
|
|
1999
|
+
return usage(`Plugin error: ${errorMessage(err)}`, runtime);
|
|
2000
|
+
}
|
|
2001
|
+
},
|
|
2002
|
+
handleTui: async (command, runtime) => {
|
|
2003
|
+
runtime.ctx.editor.setText("");
|
|
2004
|
+
const args = command.args.trim().split(/\s+/);
|
|
2005
|
+
const sub = args[0] || "list";
|
|
2006
|
+
const rest = args.slice(1).join(" ").trim();
|
|
2007
|
+
|
|
2008
|
+
try {
|
|
2009
|
+
const mgr = new MarketplaceManager({
|
|
2010
|
+
marketplacesRegistryPath: getMarketplacesRegistryPath(),
|
|
2011
|
+
installedRegistryPath: getInstalledPluginsRegistryPath(),
|
|
2012
|
+
projectInstalledRegistryPath: await resolveOrDefaultProjectRegistryPath(
|
|
2013
|
+
runtime.ctx.sessionManager.getCwd(),
|
|
2014
|
+
),
|
|
2015
|
+
marketplacesCacheDir: getMarketplacesCacheDir(),
|
|
2016
|
+
pluginsCacheDir: getPluginsCacheDir(),
|
|
2017
|
+
clearPluginRootsCache: clearPluginRootsAndCaches,
|
|
2018
|
+
});
|
|
2019
|
+
|
|
2020
|
+
switch (sub) {
|
|
2021
|
+
case "enable":
|
|
2022
|
+
case "disable": {
|
|
2023
|
+
const parsed = parsePluginScopeArgs(
|
|
2024
|
+
rest ?? "",
|
|
2025
|
+
`Usage: /plugins ${sub} [--scope user|project] <name@marketplace>`,
|
|
2026
|
+
);
|
|
2027
|
+
if ("error" in parsed) {
|
|
2028
|
+
runtime.ctx.showStatus(parsed.error);
|
|
2029
|
+
return;
|
|
2030
|
+
}
|
|
2031
|
+
const isEnable = sub === "enable";
|
|
2032
|
+
await mgr.setPluginEnabled(parsed.pluginId, isEnable, parsed.scope);
|
|
2033
|
+
runtime.ctx.showStatus(`${isEnable ? "Enabled" : "Disabled"} ${parsed.pluginId}`);
|
|
2034
|
+
break;
|
|
2035
|
+
}
|
|
2036
|
+
default: {
|
|
2037
|
+
const lines: string[] = [];
|
|
2038
|
+
|
|
2039
|
+
const npm = new PluginManager();
|
|
2040
|
+
const npmPlugins = await npm.list();
|
|
2041
|
+
if (npmPlugins.length > 0) {
|
|
2042
|
+
lines.push("npm plugins:");
|
|
2043
|
+
for (const p of npmPlugins) {
|
|
2044
|
+
const status = p.enabled === false ? " (disabled)" : "";
|
|
2045
|
+
lines.push(` ${p.name}@${p.version}${status}`);
|
|
2046
|
+
}
|
|
2047
|
+
}
|
|
2048
|
+
|
|
2049
|
+
const mktPlugins = await mgr.listInstalledPlugins();
|
|
2050
|
+
if (mktPlugins.length > 0) {
|
|
2051
|
+
if (lines.length > 0) lines.push("");
|
|
2052
|
+
lines.push("marketplace plugins:");
|
|
2053
|
+
for (const p of mktPlugins) {
|
|
2054
|
+
const entry = p.entries[0];
|
|
2055
|
+
const status = entry?.enabled === false ? " (disabled)" : "";
|
|
2056
|
+
const shadowed = p.shadowedBy ? " [shadowed]" : "";
|
|
2057
|
+
lines.push(` ${p.id} v${entry?.version ?? "?"}${status} [${p.scope}]${shadowed}`);
|
|
2058
|
+
}
|
|
2059
|
+
}
|
|
2060
|
+
|
|
2061
|
+
if (lines.length === 0) {
|
|
2062
|
+
runtime.ctx.showStatus("No plugins installed");
|
|
2063
|
+
} else {
|
|
2064
|
+
runtime.ctx.showStatus(lines.join("\n"));
|
|
2065
|
+
}
|
|
2066
|
+
break;
|
|
2067
|
+
}
|
|
2068
|
+
}
|
|
2069
|
+
} catch (err) {
|
|
2070
|
+
runtime.ctx.showStatus(`Plugin error: ${err}`);
|
|
2071
|
+
}
|
|
2072
|
+
},
|
|
2073
|
+
},
|
|
2074
|
+
{
|
|
2075
|
+
name: "reload-plugins",
|
|
2076
|
+
description: "Reload all plugins (skills, commands, hooks, tools, agents, MCP)",
|
|
2077
|
+
acpDescription: "Reload all plugins",
|
|
2078
|
+
handle: async (_command, runtime) => {
|
|
2079
|
+
await runtime.reloadPlugins();
|
|
2080
|
+
await runtime.output("Plugins reloaded.");
|
|
2081
|
+
return commandConsumed();
|
|
2082
|
+
},
|
|
2083
|
+
handleTui: async (_command, runtime) => {
|
|
2084
|
+
// Invalidate registry fs caches and the plugin roots cache so
|
|
2085
|
+
// listClaudePluginRoots re-reads from disk on next access.
|
|
2086
|
+
const projectPath = await resolveActiveProjectRegistryPath(runtime.ctx.sessionManager.getCwd());
|
|
2087
|
+
clearPluginRootsAndCaches(projectPath ? [projectPath] : undefined);
|
|
2088
|
+
await runtime.ctx.refreshSlashCommandState();
|
|
2089
|
+
await runtime.ctx.session.refreshSshTool({ activateIfAvailable: true });
|
|
2090
|
+
runtime.ctx.showStatus("Plugins reloaded.");
|
|
2091
|
+
runtime.ctx.editor.setText("");
|
|
2092
|
+
},
|
|
2093
|
+
},
|
|
2094
|
+
{
|
|
2095
|
+
name: "force",
|
|
2096
|
+
description: "Force next turn to use a specific tool",
|
|
2097
|
+
aliases: ["force:"],
|
|
2098
|
+
inlineHint: "<tool-name> [prompt]",
|
|
2099
|
+
allowArgs: true,
|
|
2100
|
+
handle: async (command, runtime) => {
|
|
2101
|
+
const spaceIdx = command.args.indexOf(" ");
|
|
2102
|
+
const toolName = spaceIdx === -1 ? command.args : command.args.slice(0, spaceIdx);
|
|
2103
|
+
const prompt = spaceIdx === -1 ? "" : command.args.slice(spaceIdx + 1).trim();
|
|
2104
|
+
if (!toolName) return usage("Usage: /force:<tool-name> [prompt]", runtime);
|
|
2105
|
+
try {
|
|
2106
|
+
runtime.session.setForcedToolChoice(toolName);
|
|
2107
|
+
} catch (err) {
|
|
2108
|
+
return usage(errorMessage(err), runtime);
|
|
2109
|
+
}
|
|
2110
|
+
await runtime.output(`Next turn forced to use ${toolName}.`);
|
|
2111
|
+
return prompt ? { prompt } : commandConsumed();
|
|
2112
|
+
},
|
|
2113
|
+
handleTui: (command, runtime) => {
|
|
2114
|
+
const spaceIdx = command.args.indexOf(" ");
|
|
2115
|
+
const toolName = spaceIdx === -1 ? command.args : command.args.slice(0, spaceIdx);
|
|
2116
|
+
const prompt = spaceIdx === -1 ? "" : command.args.slice(spaceIdx + 1).trim();
|
|
2117
|
+
|
|
2118
|
+
if (!toolName) {
|
|
2119
|
+
runtime.ctx.showError("Usage: /force:<tool-name> [prompt]");
|
|
2120
|
+
runtime.ctx.editor.setText("");
|
|
2121
|
+
return;
|
|
2122
|
+
}
|
|
2123
|
+
|
|
2124
|
+
try {
|
|
2125
|
+
runtime.ctx.session.setForcedToolChoice(toolName);
|
|
2126
|
+
runtime.ctx.showStatus(`Next turn forced to use ${toolName}.`);
|
|
2127
|
+
} catch (error) {
|
|
2128
|
+
runtime.ctx.showError(errorMessage(error));
|
|
2129
|
+
runtime.ctx.editor.setText("");
|
|
2130
|
+
return;
|
|
2131
|
+
}
|
|
2132
|
+
|
|
2133
|
+
runtime.ctx.editor.setText("");
|
|
2134
|
+
|
|
2135
|
+
// If a prompt was provided, pass it through as input
|
|
2136
|
+
if (prompt) return { prompt };
|
|
2137
|
+
},
|
|
2138
|
+
},
|
|
2139
|
+
{
|
|
2140
|
+
name: "quit",
|
|
2141
|
+
description: "Quit the application",
|
|
2142
|
+
handleTui: shutdownHandlerTui,
|
|
2143
|
+
},
|
|
2144
|
+
];
|
|
2145
|
+
|
|
2146
|
+
const BUILTIN_SLASH_COMMAND_LOOKUP = new Map<string, SlashCommandSpec>();
|
|
2147
|
+
for (const command of BUILTIN_SLASH_COMMAND_REGISTRY) {
|
|
2148
|
+
BUILTIN_SLASH_COMMAND_LOOKUP.set(command.name, command);
|
|
2149
|
+
for (const alias of command.aliases ?? []) {
|
|
2150
|
+
BUILTIN_SLASH_COMMAND_LOOKUP.set(alias, command);
|
|
2151
|
+
}
|
|
2152
|
+
}
|
|
2153
|
+
|
|
2154
|
+
export const BUILTIN_SLASH_COMMAND_RESERVED_NAMES: ReadonlySet<string> = new Set(BUILTIN_SLASH_COMMAND_LOOKUP.keys());
|
|
2155
|
+
|
|
2156
|
+
/**
|
|
2157
|
+
* Build getArgumentCompletions from declarative subcommand definitions.
|
|
2158
|
+
* Returns subcommand names filtered by prefix in the dropdown.
|
|
2159
|
+
*/
|
|
2160
|
+
function buildArgumentCompletions(subcommands: SubcommandDef[]): (prefix: string) => AutocompleteItem[] | null {
|
|
2161
|
+
return (argumentPrefix: string) => {
|
|
2162
|
+
if (argumentPrefix.includes(" ")) return null; // past the subcommand
|
|
2163
|
+
const lower = argumentPrefix.toLowerCase();
|
|
2164
|
+
const matches = subcommands
|
|
2165
|
+
.filter(s => s.name.startsWith(lower))
|
|
2166
|
+
.map(s => ({
|
|
2167
|
+
value: `${s.name} `,
|
|
2168
|
+
label: s.name,
|
|
2169
|
+
description: s.description,
|
|
2170
|
+
hint: s.usage,
|
|
2171
|
+
}));
|
|
2172
|
+
return matches.length > 0 ? matches : null;
|
|
2173
|
+
};
|
|
2174
|
+
}
|
|
2175
|
+
|
|
2176
|
+
/**
|
|
2177
|
+
* Build getInlineHint from declarative subcommand definitions.
|
|
2178
|
+
* Shows remaining completion + usage as dim ghost text after cursor.
|
|
2179
|
+
*/
|
|
2180
|
+
function buildSubcommandInlineHint(subcommands: SubcommandDef[]): (argumentText: string) => string | null {
|
|
2181
|
+
return (argumentText: string) => {
|
|
2182
|
+
const trimmed = argumentText.trimStart();
|
|
2183
|
+
const spaceIndex = trimmed.indexOf(" ");
|
|
2184
|
+
|
|
2185
|
+
if (spaceIndex === -1) {
|
|
2186
|
+
// Still typing subcommand name — show remaining chars + usage
|
|
2187
|
+
const prefix = trimmed.toLowerCase();
|
|
2188
|
+
if (prefix.length === 0) return null;
|
|
2189
|
+
const match = subcommands.find(s => s.name.startsWith(prefix));
|
|
2190
|
+
if (!match) return null;
|
|
2191
|
+
const remaining = match.name.slice(prefix.length);
|
|
2192
|
+
return remaining + (match.usage ? ` ${match.usage}` : "");
|
|
2193
|
+
}
|
|
2194
|
+
|
|
2195
|
+
// Subcommand typed — show remaining usage params
|
|
2196
|
+
const subName = trimmed.slice(0, spaceIndex).toLowerCase();
|
|
2197
|
+
const afterSub = trimmed.slice(spaceIndex + 1);
|
|
2198
|
+
const sub = subcommands.find(s => s.name === subName);
|
|
2199
|
+
if (!sub?.usage) return null;
|
|
2200
|
+
|
|
2201
|
+
if (afterSub.length > 0) {
|
|
2202
|
+
const usageParts = sub.usage.split(" ");
|
|
2203
|
+
const inputParts = afterSub.trim().split(/\s+/);
|
|
2204
|
+
const remaining = usageParts.slice(inputParts.length);
|
|
2205
|
+
return remaining.length > 0 ? remaining.join(" ") : null;
|
|
2206
|
+
}
|
|
2207
|
+
|
|
2208
|
+
return sub.usage;
|
|
2209
|
+
};
|
|
2210
|
+
}
|
|
2211
|
+
|
|
2212
|
+
/**
|
|
2213
|
+
* Build getInlineHint for commands with a simple static hint string.
|
|
2214
|
+
* Shows the hint only when no arguments have been typed yet.
|
|
2215
|
+
*/
|
|
2216
|
+
function buildStaticInlineHint(hint: string): (argumentText: string) => string | null {
|
|
2217
|
+
return (argumentText: string) => (argumentText.trim().length === 0 ? hint : null);
|
|
2218
|
+
}
|
|
2219
|
+
|
|
2220
|
+
/** Builtin command metadata used for slash-command autocomplete and help text. */
|
|
2221
|
+
export const BUILTIN_SLASH_COMMAND_DEFS: ReadonlyArray<BuiltinSlashCommand> = BUILTIN_SLASH_COMMAND_REGISTRY.map(
|
|
2222
|
+
command => ({
|
|
2223
|
+
name: command.name,
|
|
2224
|
+
aliases: command.aliases,
|
|
2225
|
+
description: command.description,
|
|
2226
|
+
subcommands: command.subcommands,
|
|
2227
|
+
inlineHint: command.inlineHint,
|
|
2228
|
+
}),
|
|
2229
|
+
);
|
|
2230
|
+
|
|
2231
|
+
/**
|
|
2232
|
+
* Materialized builtin slash commands with completion functions derived from
|
|
2233
|
+
* declarative subcommand/hint definitions.
|
|
2234
|
+
*/
|
|
2235
|
+
export const BUILTIN_SLASH_COMMANDS: ReadonlyArray<
|
|
2236
|
+
BuiltinSlashCommand & {
|
|
2237
|
+
getArgumentCompletions?: (prefix: string) => AutocompleteItem[] | null;
|
|
2238
|
+
getInlineHint?: (argumentText: string) => string | null;
|
|
2239
|
+
}
|
|
2240
|
+
> = BUILTIN_SLASH_COMMAND_DEFS.map(cmd => {
|
|
2241
|
+
if (cmd.subcommands) {
|
|
2242
|
+
return {
|
|
2243
|
+
...cmd,
|
|
2244
|
+
getArgumentCompletions: buildArgumentCompletions(cmd.subcommands),
|
|
2245
|
+
getInlineHint: buildSubcommandInlineHint(cmd.subcommands),
|
|
2246
|
+
};
|
|
2247
|
+
}
|
|
2248
|
+
if (cmd.inlineHint) {
|
|
2249
|
+
return {
|
|
2250
|
+
...cmd,
|
|
2251
|
+
getInlineHint: buildStaticInlineHint(cmd.inlineHint),
|
|
2252
|
+
};
|
|
2253
|
+
}
|
|
2254
|
+
return cmd;
|
|
2255
|
+
});
|
|
2256
|
+
|
|
2257
|
+
/**
|
|
2258
|
+
* Unified registry exposed for cross-mode tooling. Each spec carries at least
|
|
2259
|
+
* one of `handle` / `handleTui`. The TUI dispatcher prefers `handleTui`; the
|
|
2260
|
+
* ACP dispatcher requires `handle` and skips TUI-only entries.
|
|
2261
|
+
*/
|
|
2262
|
+
export const BUILTIN_SLASH_COMMANDS_INTERNAL: ReadonlyArray<SlashCommandSpec> = BUILTIN_SLASH_COMMAND_REGISTRY;
|
|
2263
|
+
|
|
2264
|
+
/**
|
|
2265
|
+
* Execute a builtin slash command in the interactive TUI.
|
|
2266
|
+
*
|
|
2267
|
+
* Returns `false` when no builtin matched. Returns `true` when a command
|
|
2268
|
+
* consumed the input entirely. Returns a `string` when the command was handled
|
|
2269
|
+
* but remaining text should be sent as a prompt.
|
|
2270
|
+
*/
|
|
2271
|
+
export async function executeBuiltinSlashCommand(
|
|
2272
|
+
text: string,
|
|
2273
|
+
runtime: BuiltinSlashCommandRuntime,
|
|
2274
|
+
): Promise<string | boolean> {
|
|
2275
|
+
const parsed = parseSlashCommand(text);
|
|
2276
|
+
if (!parsed) return false;
|
|
2277
|
+
|
|
2278
|
+
const command = BUILTIN_SLASH_COMMAND_LOOKUP.get(parsed.name);
|
|
2279
|
+
if (!command) return false;
|
|
2280
|
+
if (parsed.args.length > 0 && !command.allowArgs) {
|
|
2281
|
+
return false;
|
|
2282
|
+
}
|
|
2283
|
+
// Collab guests run a read-mostly replica: session-mutating builtins are
|
|
2284
|
+
// host-only; the allowlist covers purely local/read-only commands.
|
|
2285
|
+
if (runtime.ctx.collabGuest && !COLLAB_GUEST_ALLOWED_COMMANDS[command.name]) {
|
|
2286
|
+
runtime.ctx.showStatus(`/${command.name} is host-only during a collab session`);
|
|
2287
|
+
runtime.ctx.editor.setText("");
|
|
2288
|
+
return true;
|
|
2289
|
+
}
|
|
2290
|
+
if (command.handleTui) {
|
|
2291
|
+
const result = await command.handleTui(parsed, runtime);
|
|
2292
|
+
if (result && typeof result === "object" && "prompt" in result) return result.prompt;
|
|
2293
|
+
return true;
|
|
2294
|
+
}
|
|
2295
|
+
if (command.handle) {
|
|
2296
|
+
// No TUI-specific override → adapt the ACP/text-mode `handle` to the
|
|
2297
|
+
// TUI by routing `runtime.output` through `ctx.showStatus`, clearing
|
|
2298
|
+
// the editor after the call, and reusing the active session's plugin
|
|
2299
|
+
// reload pipeline. Spec authors get a single body usable from either
|
|
2300
|
+
// dispatcher without forcing every TUI test to construct the full
|
|
2301
|
+
// `SlashCommandRuntime` shape.
|
|
2302
|
+
const ctx = runtime.ctx;
|
|
2303
|
+
const adapted: SlashCommandRuntime = {
|
|
2304
|
+
session: ctx.session,
|
|
2305
|
+
sessionManager: ctx.sessionManager,
|
|
2306
|
+
settings: ctx.settings,
|
|
2307
|
+
cwd: ctx.sessionManager.getCwd(),
|
|
2308
|
+
output: (text: string) => {
|
|
2309
|
+
ctx.showStatus(text);
|
|
2310
|
+
},
|
|
2311
|
+
refreshCommands: () => ctx.refreshSlashCommandState(),
|
|
2312
|
+
reloadPlugins: async () => {
|
|
2313
|
+
const projectPath = await resolveActiveProjectRegistryPath(ctx.sessionManager.getCwd());
|
|
2314
|
+
clearPluginRootsAndCaches(projectPath ? [projectPath] : undefined);
|
|
2315
|
+
await ctx.refreshSlashCommandState();
|
|
2316
|
+
await ctx.session.refreshSshTool({ activateIfAvailable: true });
|
|
2317
|
+
},
|
|
2318
|
+
};
|
|
2319
|
+
const result = await command.handle(parsed, adapted);
|
|
2320
|
+
ctx.editor.setText("");
|
|
2321
|
+
if (result && typeof result === "object" && "prompt" in result) return result.prompt;
|
|
2322
|
+
return true;
|
|
2323
|
+
}
|
|
2324
|
+
return false;
|
|
2325
|
+
}
|
|
2326
|
+
|
|
2327
|
+
/** Look up a unified spec by name or alias. Used by the ACP dispatcher. */
|
|
2328
|
+
export function lookupBuiltinSlashCommand(name: string): SlashCommandSpec | undefined {
|
|
2329
|
+
return BUILTIN_SLASH_COMMAND_LOOKUP.get(name);
|
|
2330
|
+
}
|
|
2331
|
+
|
|
2332
|
+
export type { ParsedSlashCommand, SlashCommandResult, SlashCommandRuntime, SlashCommandSpec, TuiSlashCommandRuntime };
|