@kr78/pi-coding-agent 17.2.10
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 +14861 -0
- package/README.md +35 -0
- package/dist/CHANGELOG-chtdxh1z.md +14861 -0
- package/dist/cli.js +20483 -0
- package/dist/template-c2hyaytt.js +1653 -0
- package/dist/template-f8wx9vfn.css +1355 -0
- package/dist/template-qat058wr.html +55 -0
- package/dist/tool-views.generated-jdfmzwmn.js +35 -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 +78 -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 +169 -0
- package/package.json +587 -0
- package/scripts/bench-guard.ts +71 -0
- package/scripts/bench-title-models.ts +332 -0
- package/scripts/build-binary.ts +117 -0
- package/scripts/bundle-dist.ts +123 -0
- package/scripts/compile-binary.ts +69 -0
- package/scripts/embed-mupdf-wasm.ts +67 -0
- package/scripts/format-prompts.ts +68 -0
- package/scripts/generate-aria-snapshot.ts +134 -0
- package/scripts/generate-docs-index.ts +58 -0
- package/scripts/generate-share-viewer.ts +34 -0
- package/scripts/legacy-pi-virtual-module.ts +205 -0
- package/scripts/measure-prompt-tokens.ts +63 -0
- package/scripts/omp +51 -0
- package/scripts/omp.ts +19 -0
- package/scripts/security-compare.ts +40 -0
- package/src/advisor/advise-tool.ts +234 -0
- package/src/advisor/config.ts +341 -0
- package/src/advisor/emission-guard.ts +172 -0
- package/src/advisor/index.ts +6 -0
- package/src/advisor/runtime.ts +1412 -0
- package/src/advisor/transcript-recorder.ts +215 -0
- package/src/advisor/watchdog.ts +135 -0
- package/src/async/index.ts +1 -0
- package/src/async/job-manager.ts +847 -0
- package/src/auto-thinking/classifier.ts +220 -0
- package/src/autolearn/controller.ts +152 -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 +331 -0
- package/src/autoresearch/helpers.ts +218 -0
- package/src/autoresearch/index.ts +541 -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 +268 -0
- package/src/autoresearch/tools/log-experiment.ts +520 -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 +467 -0
- package/src/capability/instruction.ts +37 -0
- package/src/capability/mcp.ts +115 -0
- package/src/capability/prompt.ts +35 -0
- package/src/capability/rule-buckets.ts +66 -0
- package/src/capability/rule.ts +298 -0
- package/src/capability/settings.ts +34 -0
- package/src/capability/skill.ts +69 -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 +187 -0
- package/src/cleanse/agent.ts +226 -0
- package/src/cleanse/balance.ts +79 -0
- package/src/cleanse/checkers.ts +996 -0
- package/src/cleanse/index.ts +190 -0
- package/src/cleanse/loop.ts +51 -0
- package/src/cleanse/parsers.ts +726 -0
- package/src/cleanse/progress.ts +50 -0
- package/src/cleanse/prompts/assignment.md +47 -0
- package/src/cleanse/types.ts +72 -0
- package/src/cli/agents-cli.ts +138 -0
- package/src/cli/args.ts +368 -0
- package/src/cli/auth-broker-cli.ts +940 -0
- package/src/cli/auth-gateway-cli.ts +674 -0
- package/src/cli/bench-cli.ts +990 -0
- package/src/cli/browser-relay-cli.ts +119 -0
- package/src/cli/classify-install-target.ts +76 -0
- package/src/cli/claude-trace-cli.ts +795 -0
- package/src/cli/command-help.ts +107 -0
- package/src/cli/commands/init-xdg.ts +27 -0
- package/src/cli/completion-gen.ts +550 -0
- package/src/cli/config-cli.ts +459 -0
- package/src/cli/dry-balance-cli.ts +864 -0
- package/src/cli/extension-flags.ts +48 -0
- package/src/cli/file-processor.ts +132 -0
- package/src/cli/flag-tables.ts +367 -0
- package/src/cli/gallery-cli.ts +272 -0
- package/src/cli/gallery-fixtures/agentic.ts +420 -0
- package/src/cli/gallery-fixtures/codeintel.ts +187 -0
- package/src/cli/gallery-fixtures/edit.ts +254 -0
- package/src/cli/gallery-fixtures/fs.ts +245 -0
- package/src/cli/gallery-fixtures/index.ts +40 -0
- package/src/cli/gallery-fixtures/interaction.ts +46 -0
- package/src/cli/gallery-fixtures/memory.ts +81 -0
- package/src/cli/gallery-fixtures/misc.ts +177 -0
- package/src/cli/gallery-fixtures/search.ts +135 -0
- package/src/cli/gallery-fixtures/shell.ts +241 -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/gc-cli.ts +1566 -0
- package/src/cli/grep-cli.ts +161 -0
- package/src/cli/grievances-cli.ts +256 -0
- package/src/cli/help-extra.ts +89 -0
- package/src/cli/initial-message.ts +58 -0
- package/src/cli/models-cli.ts +385 -0
- package/src/cli/plugin-cli.ts +996 -0
- package/src/cli/profile-alias.ts +369 -0
- package/src/cli/profile-bootstrap.ts +233 -0
- package/src/cli/read-cli.ts +99 -0
- package/src/cli/session-picker.ts +110 -0
- package/src/cli/setup-cli.ts +312 -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/thinking-levels.ts +7 -0
- package/src/cli/tiny-models-cli.ts +153 -0
- package/src/cli/ttsr-cli.ts +1013 -0
- package/src/cli/update-cli.ts +1184 -0
- package/src/cli/usage-cli.ts +1084 -0
- package/src/cli/usage-error.ts +7 -0
- package/src/cli/web-search-cli.ts +144 -0
- package/src/cli/worktree-cli.ts +311 -0
- package/src/cli-commands.ts +308 -0
- package/src/cli.ts +428 -0
- package/src/collab/crypto.ts +63 -0
- package/src/collab/display-name.ts +13 -0
- package/src/collab/guest.ts +764 -0
- package/src/collab/host.ts +692 -0
- package/src/collab/protocol.ts +296 -0
- package/src/collab/relay-client.ts +282 -0
- package/src/collab/replication-shrink.ts +111 -0
- package/src/commands/acp.ts +35 -0
- package/src/commands/agents.ts +58 -0
- package/src/commands/auth-broker.ts +100 -0
- package/src/commands/auth-gateway.ts +70 -0
- package/src/commands/bench.ts +64 -0
- package/src/commands/browser-relay.ts +53 -0
- package/src/commands/cleanse.ts +45 -0
- package/src/commands/commit.ts +47 -0
- package/src/commands/complete.ts +67 -0
- package/src/commands/completions.ts +61 -0
- package/src/commands/config.ts +52 -0
- package/src/commands/dry-balance.ts +43 -0
- package/src/commands/gallery.ts +61 -0
- package/src/commands/gc.ts +47 -0
- package/src/commands/grep.ts +49 -0
- package/src/commands/grievances.ts +52 -0
- package/src/commands/install.ts +107 -0
- package/src/commands/join.ts +40 -0
- package/src/commands/launch-help.ts +116 -0
- package/src/commands/launch.ts +34 -0
- package/src/commands/models.ts +61 -0
- package/src/commands/plugin.ts +79 -0
- package/src/commands/read.ts +39 -0
- package/src/commands/say.ts +146 -0
- package/src/commands/setup.ts +68 -0
- package/src/commands/share.ts +71 -0
- package/src/commands/shell.ts +30 -0
- package/src/commands/ssh.ts +61 -0
- package/src/commands/stats.ts +30 -0
- package/src/commands/tiny-models.ts +36 -0
- package/src/commands/token.ts +164 -0
- package/src/commands/ttsr.ts +125 -0
- package/src/commands/update.ts +34 -0
- package/src/commands/usage.ts +55 -0
- package/src/commands/web-search.ts +43 -0
- package/src/commands/worktree.ts +63 -0
- package/src/commit/agentic/agent.ts +322 -0
- package/src/commit/agentic/fallback.ts +96 -0
- package/src/commit/agentic/index.ts +383 -0
- package/src/commit/agentic/lock-files.ts +107 -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 +148 -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 +62 -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 +95 -0
- package/src/commit/pipeline.ts +244 -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 +81 -0
- package/src/config/append-only-context-mode.ts +76 -0
- package/src/config/config-file.ts +347 -0
- package/src/config/inline-tool-descriptors-mode.ts +26 -0
- package/src/config/keybindings.ts +703 -0
- package/src/config/mcp-schema.json +252 -0
- package/src/config/model-discovery.ts +1077 -0
- package/src/config/model-registry.ts +2822 -0
- package/src/config/model-resolver.ts +2115 -0
- package/src/config/model-roles.ts +113 -0
- package/src/config/models-config-schema-bundle.ts +315 -0
- package/src/config/models-config-schema.ts +14 -0
- package/src/config/models-config.ts +130 -0
- package/src/config/prompt-templates.ts +205 -0
- package/src/config/provider-globals.ts +25 -0
- package/src/config/resolve-config-value.ts +95 -0
- package/src/config/service-tier.ts +146 -0
- package/src/config/settings-schema.ts +5887 -0
- package/src/config/settings.ts +2394 -0
- package/src/config.ts +242 -0
- package/src/cursor-bridge-tools.ts +81 -0
- package/src/cursor.ts +960 -0
- package/src/dap/client.ts +1043 -0
- package/src/dap/config.ts +480 -0
- package/src/dap/defaults.json +212 -0
- package/src/dap/index.ts +4 -0
- package/src/dap/session.ts +1841 -0
- package/src/dap/types.ts +611 -0
- package/src/debug/index.ts +584 -0
- package/src/debug/log-formatting.ts +58 -0
- package/src/debug/log-viewer.ts +966 -0
- package/src/debug/profiler.ts +168 -0
- package/src/debug/protocol-probe.ts +267 -0
- package/src/debug/raw-sse-buffer.ts +421 -0
- package/src/debug/raw-sse.ts +312 -0
- package/src/debug/remote-debugger.ts +151 -0
- package/src/debug/report-bundle.ts +411 -0
- package/src/debug/system-info.ts +111 -0
- package/src/debug/terminal-info.ts +124 -0
- package/src/discovery/agent-plugin-format.ts +551 -0
- package/src/discovery/agent-plugins.ts +341 -0
- package/src/discovery/agents-md.ts +67 -0
- package/src/discovery/agents.ts +300 -0
- package/src/discovery/at-imports.ts +273 -0
- package/src/discovery/builtin-defaults.ts +39 -0
- package/src/discovery/builtin-rules/go-add-cleanup.md +33 -0
- package/src/discovery/builtin-rules/go-bench-loop.md +36 -0
- package/src/discovery/builtin-rules/go-exp-promoted.md +40 -0
- package/src/discovery/builtin-rules/go-ioutil.md +37 -0
- package/src/discovery/builtin-rules/go-join-hostport.md +30 -0
- package/src/discovery/builtin-rules/go-new-expr.md +44 -0
- package/src/discovery/builtin-rules/go-rand-v2.md +41 -0
- package/src/discovery/builtin-rules/go-range-int.md +45 -0
- package/src/discovery/builtin-rules/index.ts +74 -0
- package/src/discovery/builtin-rules/rs-box-leak.md +49 -0
- package/src/discovery/builtin-rules/rs-future-prelude.md +24 -0
- package/src/discovery/builtin-rules/rs-lazylock.md +52 -0
- package/src/discovery/builtin-rules/rs-match-ergonomics.md +68 -0
- package/src/discovery/builtin-rules/rs-parking-lot.md +45 -0
- package/src/discovery/builtin-rules/rs-result-type.md +20 -0
- package/src/discovery/builtin-rules/ts-bare-catch.md +39 -0
- package/src/discovery/builtin-rules/ts-import-type.md +43 -0
- package/src/discovery/builtin-rules/ts-no-any.md +66 -0
- package/src/discovery/builtin-rules/ts-no-deprecated-leftovers.md +45 -0
- package/src/discovery/builtin-rules/ts-no-dynamic-import.md +40 -0
- package/src/discovery/builtin-rules/ts-no-inline-cast-access.md +56 -0
- package/src/discovery/builtin-rules/ts-no-local-is-record.md +48 -0
- package/src/discovery/builtin-rules/ts-no-return-type.md +45 -0
- package/src/discovery/builtin-rules/ts-no-test-timers.md +55 -0
- package/src/discovery/builtin-rules/ts-no-tiny-functions.md +51 -0
- package/src/discovery/builtin-rules/ts-promise-with-resolvers.md +66 -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 +945 -0
- package/src/discovery/claude-plugins.ts +640 -0
- package/src/discovery/claude.ts +591 -0
- package/src/discovery/cline.ts +83 -0
- package/src/discovery/codex.ts +553 -0
- package/src/discovery/contained-path.ts +78 -0
- package/src/discovery/cursor.ts +223 -0
- package/src/discovery/gemini.ts +386 -0
- package/src/discovery/github.ts +337 -0
- package/src/discovery/helpers.ts +1183 -0
- package/src/discovery/index.ts +82 -0
- package/src/discovery/mcp-json.ts +182 -0
- package/src/discovery/omp-extension-roots.ts +272 -0
- package/src/discovery/omp-plugins.ts +409 -0
- package/src/discovery/opencode.ts +441 -0
- package/src/discovery/plugin-dir-roots.ts +28 -0
- package/src/discovery/ssh.ts +153 -0
- package/src/discovery/substitute-plugin-root.ts +77 -0
- package/src/discovery/vscode.ts +106 -0
- package/src/discovery/windsurf.ts +149 -0
- package/src/edit/apply-patch/index.ts +87 -0
- package/src/edit/apply-patch/parser.ts +174 -0
- package/src/edit/diff.ts +1008 -0
- package/src/edit/edit-clipboard.ts +23 -0
- package/src/edit/file-snapshot-store.ts +148 -0
- package/src/edit/hashline/block-resolver.ts +33 -0
- package/src/edit/hashline/diff.ts +402 -0
- package/src/edit/hashline/execute.ts +313 -0
- package/src/edit/hashline/filesystem.ts +247 -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 +12 -0
- package/src/edit/index.ts +699 -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 +1958 -0
- package/src/edit/modes/replace.ts +1191 -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 +998 -0
- package/src/edit/snapshot-details.ts +77 -0
- package/src/edit/streaming.ts +710 -0
- package/src/eval/agent-bridge.ts +224 -0
- package/src/eval/backend-helpers.ts +48 -0
- package/src/eval/backend.ts +71 -0
- package/src/eval/bridge-timeout.ts +65 -0
- package/src/eval/budget-bridge.ts +48 -0
- package/src/eval/completion-bridge.ts +212 -0
- package/src/eval/concurrency-bridge.ts +34 -0
- package/src/eval/executor-base.ts +562 -0
- package/src/eval/idle-timeout.ts +91 -0
- package/src/eval/index.ts +6 -0
- package/src/eval/jl/executor.ts +551 -0
- package/src/eval/jl/index.ts +54 -0
- package/src/eval/jl/kernel.ts +236 -0
- package/src/eval/jl/prelude.jl +736 -0
- package/src/eval/jl/prelude.ts +3 -0
- package/src/eval/jl/runner.jl +666 -0
- package/src/eval/jl/runtime.ts +118 -0
- package/src/eval/js/context-manager.ts +872 -0
- package/src/eval/js/executor.ts +178 -0
- package/src/eval/js/index.ts +41 -0
- package/src/eval/js/process-entry.ts +31 -0
- package/src/eval/js/shared/helpers.ts +170 -0
- package/src/eval/js/shared/indirect-eval.ts +30 -0
- package/src/eval/js/shared/local-module-loader.ts +364 -0
- package/src/eval/js/shared/prelude.ts +2 -0
- package/src/eval/js/shared/prelude.txt +294 -0
- package/src/eval/js/shared/rewrite-imports.ts +550 -0
- package/src/eval/js/shared/runtime.ts +590 -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 +380 -0
- package/src/eval/js/worker-entry.ts +37 -0
- package/src/eval/js/worker-protocol.ts +47 -0
- package/src/eval/kernel-base.ts +569 -0
- package/src/eval/py/display.ts +71 -0
- package/src/eval/py/executor.ts +643 -0
- package/src/eval/py/index.ts +57 -0
- package/src/eval/py/kernel.ts +235 -0
- package/src/eval/py/prelude.py +673 -0
- package/src/eval/py/prelude.ts +3 -0
- package/src/eval/py/runner.py +1425 -0
- package/src/eval/py/runtime.ts +276 -0
- package/src/eval/py/spawn-options.ts +134 -0
- package/src/eval/py/tool-bridge.ts +201 -0
- package/src/eval/rb/executor.ts +511 -0
- package/src/eval/rb/index.ts +54 -0
- package/src/eval/rb/kernel.ts +231 -0
- package/src/eval/rb/prelude.rb +551 -0
- package/src/eval/rb/prelude.ts +3 -0
- package/src/eval/rb/runner.rb +581 -0
- package/src/eval/rb/runtime.ts +132 -0
- package/src/eval/runtime-env.ts +104 -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 +627 -0
- package/src/exec/direnv.ts +145 -0
- package/src/exec/exec.ts +53 -0
- package/src/exec/non-interactive-env.ts +118 -0
- package/src/export/custom-share.ts +65 -0
- package/src/export/html/args.ts +20 -0
- package/src/export/html/index.ts +320 -0
- package/src/export/html/share-loader.js +102 -0
- package/src/export/html/template.css +1355 -0
- package/src/export/html/template.html +55 -0
- package/src/export/html/template.js +1653 -0
- package/src/export/html/tool-views.generated.js +35 -0
- package/src/export/html/vendor/highlight.min.js +1213 -0
- package/src/export/html/vendor/marked.min.js +6 -0
- package/src/export/html/web-palette.ts +126 -0
- package/src/export/share.ts +686 -0
- package/src/export/ttsr.ts +590 -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 +301 -0
- package/src/extensibility/custom-tools/types.ts +287 -0
- package/src/extensibility/custom-tools/wrapper.ts +50 -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/load-errors.ts +13 -0
- package/src/extensibility/extensions/loader.ts +663 -0
- package/src/extensibility/extensions/managed-timers.ts +83 -0
- package/src/extensibility/extensions/model-api.ts +39 -0
- package/src/extensibility/extensions/runner.ts +1396 -0
- package/src/extensibility/extensions/types.ts +1603 -0
- package/src/extensibility/extensions/wrapper.ts +395 -0
- package/src/extensibility/hooks/index.ts +6 -0
- package/src/extensibility/hooks/loader.ts +243 -0
- package/src/extensibility/hooks/runner.ts +425 -0
- package/src/extensibility/hooks/tool-wrapper.ts +124 -0
- package/src/extensibility/hooks/types.ts +612 -0
- package/src/extensibility/legacy-pi-ai-shim.ts +161 -0
- package/src/extensibility/legacy-pi-coding-agent-shim.ts +1460 -0
- package/src/extensibility/legacy-pi-tui-shim.ts +43 -0
- package/src/extensibility/legacy-typebox.ts +101 -0
- package/src/extensibility/plugins/bun-git-cache.ts +91 -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 +201 -0
- package/src/extensibility/plugins/legacy-pi-compat.ts +2643 -0
- package/src/extensibility/plugins/legacy-pi-virtual-modules.d.ts +4 -0
- package/src/extensibility/plugins/loader.ts +535 -0
- package/src/extensibility/plugins/manager.ts +1142 -0
- package/src/extensibility/plugins/marketplace/cache.ts +136 -0
- package/src/extensibility/plugins/marketplace/fetcher.ts +316 -0
- package/src/extensibility/plugins/marketplace/index.ts +6 -0
- package/src/extensibility/plugins/marketplace/manager.ts +927 -0
- package/src/extensibility/plugins/marketplace/registry.ts +192 -0
- package/src/extensibility/plugins/marketplace/source-resolver.ts +147 -0
- package/src/extensibility/plugins/marketplace/types.ts +192 -0
- package/src/extensibility/plugins/marketplace-auto-update.ts +49 -0
- package/src/extensibility/plugins/parser.ts +107 -0
- package/src/extensibility/plugins/runtime-config.ts +9 -0
- package/src/extensibility/plugins/types.ts +194 -0
- package/src/extensibility/session-handler-types.ts +21 -0
- package/src/extensibility/shared-events.ts +401 -0
- package/src/extensibility/skills.ts +531 -0
- package/src/extensibility/slash-commands.ts +131 -0
- package/src/extensibility/tool-event-input.ts +80 -0
- package/src/extensibility/tool-proxy.ts +28 -0
- package/src/extensibility/utils.ts +192 -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 +680 -0
- package/src/hindsight/config.ts +193 -0
- package/src/hindsight/content.ts +266 -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 +530 -0
- package/src/hindsight/transcript.ts +71 -0
- package/src/index.ts +66 -0
- package/src/internal-urls/agent-protocol.ts +180 -0
- package/src/internal-urls/artifact-protocol.ts +151 -0
- package/src/internal-urls/docs-index.ts +102 -0
- package/src/internal-urls/filesystem-resource.ts +34 -0
- package/src/internal-urls/history-protocol.ts +198 -0
- package/src/internal-urls/index.ts +28 -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 +471 -0
- package/src/internal-urls/mcp-protocol.ts +168 -0
- package/src/internal-urls/memory-protocol.ts +380 -0
- package/src/internal-urls/omp-protocol.ts +94 -0
- package/src/internal-urls/parse.ts +103 -0
- package/src/internal-urls/registry-helpers.ts +132 -0
- package/src/internal-urls/router.ts +153 -0
- package/src/internal-urls/rule-protocol.ts +45 -0
- package/src/internal-urls/security-protocol.ts +261 -0
- package/src/internal-urls/skill-protocol.ts +131 -0
- package/src/internal-urls/ssh-protocol.ts +368 -0
- package/src/internal-urls/types.ts +196 -0
- package/src/internal-urls/vault-protocol.ts +940 -0
- package/src/internal-urls/xd-protocol.ts +46 -0
- package/src/irc/bus.ts +380 -0
- package/src/jsonrpc/message-framing.ts +142 -0
- package/src/launch/broker.ts +1368 -0
- package/src/launch/client.ts +521 -0
- package/src/launch/ensure.ts +73 -0
- package/src/launch/paths.ts +14 -0
- package/src/launch/presence.ts +82 -0
- package/src/launch/protocol.ts +448 -0
- package/src/launch/spawn-options.ts +17 -0
- package/src/launch/terminal-output-worker-client.ts +53 -0
- package/src/launch/terminal-output-worker-protocol.ts +11 -0
- package/src/launch/terminal-output-worker.ts +23 -0
- package/src/launch/terminal-output.ts +46 -0
- package/src/lib/xai-http.ts +150 -0
- package/src/live/attestation.ts +91 -0
- package/src/live/controller.ts +517 -0
- package/src/live/prompts/agent-final-message.md +3 -0
- package/src/live/prompts/live-instructions.md +23 -0
- package/src/live/protocol.ts +233 -0
- package/src/live/transport.ts +422 -0
- package/src/live/visualizer.ts +221 -0
- package/src/live/voices.ts +18 -0
- package/src/lsp/client.ts +1465 -0
- package/src/lsp/clients/biome-client.ts +263 -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 +549 -0
- package/src/lsp/defaults.json +499 -0
- package/src/lsp/deferred-diagnostics.ts +66 -0
- package/src/lsp/diagnostics-ledger.ts +51 -0
- package/src/lsp/edits.ts +288 -0
- package/src/lsp/format-options.ts +119 -0
- package/src/lsp/index.ts +2821 -0
- package/src/lsp/lspmux.ts +233 -0
- package/src/lsp/mux/daemon.ts +348 -0
- package/src/lsp/mux/protocol.ts +96 -0
- package/src/lsp/mux/server.ts +797 -0
- package/src/lsp/render.ts +668 -0
- package/src/lsp/startup-events.ts +13 -0
- package/src/lsp/types.ts +479 -0
- package/src/lsp/utils.ts +747 -0
- package/src/main.ts +1799 -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/pdf/columns.ts +103 -0
- package/src/markit/converters/pdf/extract.ts +598 -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 +511 -0
- package/src/mcp/config-writer.ts +377 -0
- package/src/mcp/config.ts +385 -0
- package/src/mcp/index.ts +29 -0
- package/src/mcp/json-rpc.ts +122 -0
- package/src/mcp/loader.ts +125 -0
- package/src/mcp/manager.ts +1524 -0
- package/src/mcp/oauth-credentials.ts +104 -0
- package/src/mcp/oauth-discovery.ts +587 -0
- package/src/mcp/oauth-flow.ts +830 -0
- package/src/mcp/render.ts +214 -0
- package/src/mcp/request-id.ts +24 -0
- package/src/mcp/smithery-auth.ts +108 -0
- package/src/mcp/smithery-connect.ts +154 -0
- package/src/mcp/smithery-registry.ts +500 -0
- package/src/mcp/startup-events.ts +116 -0
- package/src/mcp/timeout.ts +59 -0
- package/src/mcp/tool-bridge.ts +691 -0
- package/src/mcp/tool-cache.ts +117 -0
- package/src/mcp/transports/header-policy.ts +95 -0
- package/src/mcp/transports/http.ts +508 -0
- package/src/mcp/transports/index.ts +7 -0
- package/src/mcp/transports/sse.ts +372 -0
- package/src/mcp/transports/stdio.ts +905 -0
- package/src/mcp/types.ts +467 -0
- package/src/memories/index.ts +1434 -0
- package/src/memories/storage.ts +578 -0
- package/src/memory-backend/index.ts +19 -0
- package/src/memory-backend/local-backend.ts +47 -0
- package/src/memory-backend/messages.ts +19 -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/tool-names.ts +2 -0
- package/src/memory-backend/types.ts +166 -0
- package/src/mnemopi/backend.ts +629 -0
- package/src/mnemopi/config.ts +267 -0
- package/src/mnemopi/embed-client.ts +293 -0
- package/src/mnemopi/embed-protocol.ts +35 -0
- package/src/mnemopi/embed-worker.ts +114 -0
- package/src/mnemopi/index.ts +3 -0
- package/src/mnemopi/state.ts +940 -0
- package/src/modes/acp/acp-agent.ts +2595 -0
- package/src/modes/acp/acp-client-bridge.ts +154 -0
- package/src/modes/acp/acp-event-mapper.ts +1084 -0
- package/src/modes/acp/acp-mode.ts +48 -0
- package/src/modes/acp/index.ts +2 -0
- package/src/modes/acp/terminal-auth.ts +37 -0
- package/src/modes/components/advisor-config.ts +635 -0
- package/src/modes/components/advisor-message.ts +109 -0
- package/src/modes/components/agent-dashboard.ts +1252 -0
- package/src/modes/components/agent-hub-projection.ts +248 -0
- package/src/modes/components/agent-hub-renderer.ts +194 -0
- package/src/modes/components/agent-hub.ts +1126 -0
- package/src/modes/components/agent-transcript-viewer.ts +647 -0
- package/src/modes/components/ask-dialog.ts +1017 -0
- package/src/modes/components/assistant-message.ts +978 -0
- package/src/modes/components/background-tan-message.ts +36 -0
- package/src/modes/components/bash-execution.ts +233 -0
- package/src/modes/components/bordered-loader.ts +41 -0
- package/src/modes/components/btw-panel.ts +161 -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 +518 -0
- package/src/modes/components/codex-reset-fireworks.ts +369 -0
- package/src/modes/components/collab-prompt-message.ts +32 -0
- package/src/modes/components/compaction-summary-message.ts +221 -0
- package/src/modes/components/copy-selector.ts +218 -0
- package/src/modes/components/countdown-timer.ts +75 -0
- package/src/modes/components/custom-editor.ts +1036 -0
- package/src/modes/components/custom-message.ts +70 -0
- package/src/modes/components/diff.ts +254 -0
- package/src/modes/components/dynamic-border.ts +37 -0
- package/src/modes/components/error-banner.ts +33 -0
- package/src/modes/components/eval-execution.ts +169 -0
- package/src/modes/components/execution-shared.ts +101 -0
- package/src/modes/components/extensions/extension-dashboard.ts +492 -0
- package/src/modes/components/extensions/extension-list.ts +507 -0
- package/src/modes/components/extensions/index.ts +9 -0
- package/src/modes/components/extensions/inspector-panel.ts +326 -0
- package/src/modes/components/extensions/state-manager.ts +648 -0
- package/src/modes/components/extensions/types.ts +186 -0
- package/src/modes/components/footer.ts +274 -0
- package/src/modes/components/history-search.ts +268 -0
- package/src/modes/components/hook-editor.ts +213 -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 +691 -0
- package/src/modes/components/index.ts +42 -0
- package/src/modes/components/keybinding-hints.ts +56 -0
- package/src/modes/components/late-diagnostics-message.ts +60 -0
- package/src/modes/components/login-dialog.ts +197 -0
- package/src/modes/components/logout-account-selector.ts +130 -0
- package/src/modes/components/mcp-add-wizard.ts +1413 -0
- package/src/modes/components/message-frame.ts +98 -0
- package/src/modes/components/model-browser.ts +888 -0
- package/src/modes/components/model-hub.ts +2014 -0
- package/src/modes/components/model-picker.ts +237 -0
- package/src/modes/components/move-overlay.ts +293 -0
- package/src/modes/components/oauth-selector.ts +474 -0
- package/src/modes/components/omfg-panel.ts +141 -0
- package/src/modes/components/overlay-box.ts +109 -0
- package/src/modes/components/pause-screen.ts +208 -0
- package/src/modes/components/plan-review-overlay.ts +1226 -0
- package/src/modes/components/plan-toc.ts +138 -0
- package/src/modes/components/plugin-selector.ts +100 -0
- package/src/modes/components/plugin-settings.ts +745 -0
- package/src/modes/components/queue-mode-selector.ts +61 -0
- package/src/modes/components/read-tool-group.ts +856 -0
- package/src/modes/components/reset-usage-selector.ts +161 -0
- package/src/modes/components/segment-track.ts +89 -0
- package/src/modes/components/select-list-mouse-routing.ts +35 -0
- package/src/modes/components/selector-helpers.ts +129 -0
- package/src/modes/components/session-account-selector.ts +62 -0
- package/src/modes/components/session-selector.ts +1035 -0
- package/src/modes/components/settings-defs.ts +267 -0
- package/src/modes/components/settings-selector.ts +1445 -0
- package/src/modes/components/show-images-selector.ts +50 -0
- package/src/modes/components/skill-message.ts +110 -0
- package/src/modes/components/snapcompact-shape-preview-doc.md +14 -0
- package/src/modes/components/snapcompact-shape-preview.ts +192 -0
- package/src/modes/components/status-line/component.ts +1843 -0
- package/src/modes/components/status-line/context-thresholds.ts +86 -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 +710 -0
- package/src/modes/components/status-line/separators.ts +55 -0
- package/src/modes/components/status-line/types.ts +159 -0
- package/src/modes/components/stripped-tool-calls-placeholder.ts +35 -0
- package/src/modes/components/theme-selector.ts +68 -0
- package/src/modes/components/thinking-selector.ts +57 -0
- package/src/modes/components/tiny-title-download-progress.ts +90 -0
- package/src/modes/components/tips.txt +26 -0
- package/src/modes/components/todo-reminder.ts +43 -0
- package/src/modes/components/tool-execution.ts +1467 -0
- package/src/modes/components/transcript-container.ts +527 -0
- package/src/modes/components/tree-selector.ts +1006 -0
- package/src/modes/components/ttsr-notification.ts +123 -0
- package/src/modes/components/usage-row.ts +52 -0
- package/src/modes/components/user-message-selector.ts +227 -0
- package/src/modes/components/user-message.ts +167 -0
- package/src/modes/components/visual-truncate.ts +63 -0
- package/src/modes/components/welcome.ts +578 -0
- package/src/modes/controllers/btw-controller.ts +246 -0
- package/src/modes/controllers/command-controller-shared.ts +109 -0
- package/src/modes/controllers/command-controller.ts +2024 -0
- package/src/modes/controllers/event-controller.ts +2173 -0
- package/src/modes/controllers/extension-ui-controller.ts +1243 -0
- package/src/modes/controllers/input-controller.ts +2037 -0
- package/src/modes/controllers/live-command-controller.ts +261 -0
- package/src/modes/controllers/mcp-command-controller.ts +2552 -0
- package/src/modes/controllers/omfg-controller.ts +287 -0
- package/src/modes/controllers/omfg-rule.ts +647 -0
- package/src/modes/controllers/selector-controller.ts +2058 -0
- package/src/modes/controllers/session-focus-controller.ts +117 -0
- package/src/modes/controllers/ssh-command-controller.ts +385 -0
- package/src/modes/controllers/streaming-reveal.ts +399 -0
- package/src/modes/controllers/tan-command-controller.ts +243 -0
- package/src/modes/controllers/todo-command-controller.ts +487 -0
- package/src/modes/controllers/tool-args-reveal.ts +591 -0
- package/src/modes/data/emojis.json +1 -0
- package/src/modes/emoji-autocomplete.ts +285 -0
- package/src/modes/github-ref-autocomplete.ts +75 -0
- package/src/modes/gradient-highlight.ts +99 -0
- package/src/modes/image-references.ts +137 -0
- package/src/modes/index.ts +10 -0
- package/src/modes/interactive-mode.ts +5055 -0
- package/src/modes/internal-url-autocomplete.ts +158 -0
- package/src/modes/loop-limit.ts +192 -0
- package/src/modes/magic-keyword-boundary.ts +23 -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 +43 -0
- package/src/modes/print-mode.ts +282 -0
- package/src/modes/prompt-action-autocomplete.ts +322 -0
- package/src/modes/queue-input.ts +132 -0
- package/src/modes/rpc/host-tools.ts +204 -0
- package/src/modes/rpc/host-uris.ts +241 -0
- package/src/modes/rpc/rpc-client.ts +1213 -0
- package/src/modes/rpc/rpc-frame.ts +316 -0
- package/src/modes/rpc/rpc-input.ts +38 -0
- package/src/modes/rpc/rpc-messages.ts +127 -0
- package/src/modes/rpc/rpc-mode.ts +1519 -0
- package/src/modes/rpc/rpc-subagents.ts +265 -0
- package/src/modes/rpc/rpc-types.ts +544 -0
- package/src/modes/running-subagent-badge.ts +13 -0
- package/src/modes/runtime-init.ts +144 -0
- package/src/modes/session-observer-registry.ts +223 -0
- package/src/modes/session-teardown.ts +82 -0
- package/src/modes/setup-version.ts +11 -0
- package/src/modes/setup-wizard/index.ts +103 -0
- package/src/modes/setup-wizard/lazy.ts +16 -0
- package/src/modes/setup-wizard/scenes/glyph.ts +103 -0
- package/src/modes/setup-wizard/scenes/model.ts +132 -0
- package/src/modes/setup-wizard/scenes/outro.ts +35 -0
- package/src/modes/setup-wizard/scenes/providers.ts +105 -0
- package/src/modes/setup-wizard/scenes/sign-in.ts +312 -0
- package/src/modes/setup-wizard/scenes/splash.ts +201 -0
- package/src/modes/setup-wizard/scenes/theme.ts +330 -0
- package/src/modes/setup-wizard/scenes/types.ts +65 -0
- package/src/modes/setup-wizard/scenes/web-search.ts +153 -0
- package/src/modes/setup-wizard/startup-splash.ts +107 -0
- package/src/modes/setup-wizard/wizard-overlay.ts +335 -0
- package/src/modes/shared.ts +49 -0
- package/src/modes/skill-command.ts +91 -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 +143 -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 +143 -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 +305 -0
- package/src/modes/theme/theme-schema.json +463 -0
- package/src/modes/theme/theme.ts +3171 -0
- package/src/modes/turn-budget.ts +31 -0
- package/src/modes/types.ts +494 -0
- package/src/modes/ultrathink.ts +42 -0
- package/src/modes/utils/context-usage.ts +518 -0
- package/src/modes/utils/copy-targets.ts +378 -0
- package/src/modes/utils/hotkeys-markdown.ts +65 -0
- package/src/modes/utils/interactive-context-helpers.ts +31 -0
- package/src/modes/utils/keybinding-matchers.ts +86 -0
- package/src/modes/utils/tools-markdown.ts +31 -0
- package/src/modes/utils/transcript-render-helpers.ts +253 -0
- package/src/modes/utils/ui-helpers.ts +976 -0
- package/src/modes/warp-events.ts +232 -0
- package/src/modes/workflow.ts +55 -0
- package/src/plan-mode/approved-plan.ts +194 -0
- package/src/plan-mode/model-transition.ts +51 -0
- package/src/plan-mode/plan-files.ts +40 -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 +60 -0
- package/src/prompts/advisor/active-repo-watchdog.md +6 -0
- package/src/prompts/advisor/advise-tool.md +3 -0
- package/src/prompts/advisor/context-files.md +8 -0
- package/src/prompts/advisor/system.md +98 -0
- package/src/prompts/agents/designer.md +74 -0
- package/src/prompts/agents/frontmatter.md +12 -0
- package/src/prompts/agents/init.md +33 -0
- package/src/prompts/agents/librarian.md +119 -0
- package/src/prompts/agents/reviewer.md +139 -0
- package/src/prompts/agents/scout.md +58 -0
- package/src/prompts/agents/security-reviewer.md +75 -0
- package/src/prompts/agents/task.md +17 -0
- package/src/prompts/bench/cache-prefix-chunk.md +1 -0
- package/src/prompts/bench/cache-prefix.md +3 -0
- package/src/prompts/bench/cache-suffix.md +1 -0
- package/src/prompts/bench.md +6 -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/goal-mode-context.md +4 -0
- package/src/prompts/goals/goal-todo-context.md +12 -0
- package/src/prompts/goals/guided-goal-interview.md +43 -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 +21 -0
- package/src/prompts/review-headless-request.md +16 -0
- package/src/prompts/review-request.md +68 -0
- package/src/prompts/security/scan-coordinator.md +7 -0
- package/src/prompts/security/scan-request.md +21 -0
- package/src/prompts/security/validate-request.md +8 -0
- package/src/prompts/session/launch-completion.md +1 -0
- package/src/prompts/skills/autoload.md +8 -0
- package/src/prompts/skills/user-invocation.md +11 -0
- package/src/prompts/steering/parent-irc.md +5 -0
- package/src/prompts/steering/user-interjection.md +6 -0
- package/src/prompts/system/active-repo-context.md +4 -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 +14 -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-autocontinue.md +5 -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/computer-safety.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/gemini-tool-call-reminder.md +9 -0
- package/src/prompts/system/interrupted-thinking.md +7 -0
- package/src/prompts/system/irc-autoreply.md +6 -0
- package/src/prompts/system/irc-incoming.md +9 -0
- package/src/prompts/system/manual-continue.md +7 -0
- package/src/prompts/system/mcp-xdev-guidance.md +11 -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/mid-run-todo-nudge.md +3 -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 +125 -0
- package/src/prompts/system/plan-mode-approved.md +22 -0
- package/src/prompts/system/plan-mode-compact-instructions.md +17 -0
- package/src/prompts/system/plan-mode-reference.md +10 -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/plan-yolo-handoff.md +5 -0
- package/src/prompts/system/prewalk-checklist.md +7 -0
- package/src/prompts/system/prewalk-continue.md +1 -0
- package/src/prompts/system/prewalk-plan.md +13 -0
- package/src/prompts/system/project-prompt.md +61 -0
- package/src/prompts/system/recap-user.md +9 -0
- package/src/prompts/system/resolve-device-reminder.md +3 -0
- package/src/prompts/system/rewind-report.md +6 -0
- package/src/prompts/system/side-channel-no-tools.md +3 -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/speech-rewrite.md +15 -0
- package/src/prompts/system/subagent-async-pending.md +6 -0
- package/src/prompts/system/subagent-system-prompt.md +73 -0
- package/src/prompts/system/subagent-user-prompt.md +3 -0
- package/src/prompts/system/subagent-yield-reminder.md +23 -0
- package/src/prompts/system/system-prompt.md +263 -0
- package/src/prompts/system/tan-context-switch.md +17 -0
- package/src/prompts/system/task-label.md +23 -0
- package/src/prompts/system/thinking-loop-redirect.md +10 -0
- package/src/prompts/system/title-marker-instruction.md +1 -0
- package/src/prompts/system/title-system.md +16 -0
- package/src/prompts/system/tool-call-loop-redirect.md +8 -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/vibe-mode-active.md +26 -0
- package/src/prompts/system/web-search.md +25 -0
- package/src/prompts/system/workflow-notice.md +112 -0
- package/src/prompts/system/xdev-mount-notice.md +20 -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 +11 -0
- package/src/prompts/tools/ast-grep.md +19 -0
- package/src/prompts/tools/async-result.md +8 -0
- package/src/prompts/tools/bash.md +23 -0
- package/src/prompts/tools/browser.md +29 -0
- package/src/prompts/tools/checkpoint.md +15 -0
- package/src/prompts/tools/computer.md +26 -0
- package/src/prompts/tools/debug.md +3 -0
- package/src/prompts/tools/eval.md +45 -0
- package/src/prompts/tools/github.md +22 -0
- package/src/prompts/tools/glob.md +16 -0
- package/src/prompts/tools/goal.md +11 -0
- package/src/prompts/tools/grep.md +13 -0
- package/src/prompts/tools/hub.md +34 -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/learn.md +7 -0
- package/src/prompts/tools/lsp-late-diagnostic.md +8 -0
- package/src/prompts/tools/lsp.md +19 -0
- package/src/prompts/tools/manage-skill.md +9 -0
- package/src/prompts/tools/memory-edit.md +12 -0
- package/src/prompts/tools/patch.md +57 -0
- package/src/prompts/tools/read.md +27 -0
- package/src/prompts/tools/recall.md +7 -0
- package/src/prompts/tools/reflect.md +5 -0
- package/src/prompts/tools/replace.md +30 -0
- package/src/prompts/tools/retain.md +6 -0
- package/src/prompts/tools/rewind.md +14 -0
- package/src/prompts/tools/security-publish.md +1 -0
- package/src/prompts/tools/security-scan.md +1 -0
- package/src/prompts/tools/task-async-contract.md +1 -0
- package/src/prompts/tools/task-summary.md +20 -0
- package/src/prompts/tools/task.md +83 -0
- package/src/prompts/tools/todo.md +42 -0
- package/src/prompts/tools/vibe-kill.md +3 -0
- package/src/prompts/tools/vibe-list.md +3 -0
- package/src/prompts/tools/vibe-send.md +9 -0
- package/src/prompts/tools/vibe-spawn.md +10 -0
- package/src/prompts/tools/vibe-turn-result.md +19 -0
- package/src/prompts/tools/vibe-wait.md +8 -0
- package/src/prompts/tools/web-search.md +8 -0
- package/src/prompts/tools/write.md +14 -0
- package/src/registry/agent-lifecycle.ts +505 -0
- package/src/registry/agent-registry.ts +287 -0
- package/src/registry/persisted-agents.ts +423 -0
- package/src/sdk.ts +3820 -0
- package/src/secrets/index.ts +375 -0
- package/src/secrets/obfuscator.ts +2629 -0
- package/src/secrets/regex.ts +21 -0
- package/src/security/auth.ts +98 -0
- package/src/security/cloud.ts +686 -0
- package/src/security/comparison.ts +255 -0
- package/src/security/contracts/ids.ts +111 -0
- package/src/security/contracts/index.ts +4 -0
- package/src/security/contracts/schemas.ts +219 -0
- package/src/security/contracts/types.ts +254 -0
- package/src/security/contracts/validation.ts +69 -0
- package/src/security/coordinator.ts +708 -0
- package/src/security/importers/codex-security.ts +387 -0
- package/src/security/importers/index.ts +2 -0
- package/src/security/importers/sarif.ts +357 -0
- package/src/security/index.ts +13 -0
- package/src/security/preflight.ts +405 -0
- package/src/security/provenance.ts +106 -0
- package/src/security/publication.ts +326 -0
- package/src/security/remediation.ts +93 -0
- package/src/security/resource-output.ts +50 -0
- package/src/security/sarif.ts +78 -0
- package/src/security/store.ts +430 -0
- package/src/session/acp-permission-gate.ts +165 -0
- package/src/session/agent-session-events.ts +67 -0
- package/src/session/agent-session-types.ts +407 -0
- package/src/session/agent-session.ts +9000 -0
- package/src/session/agent-storage.ts +807 -0
- package/src/session/artifacts.ts +154 -0
- package/src/session/async-job-delivery.ts +82 -0
- package/src/session/auth-broker-config.ts +92 -0
- package/src/session/auth-storage.ts +25 -0
- package/src/session/bash-runner.ts +326 -0
- package/src/session/blob-store.ts +295 -0
- package/src/session/checkpoint-entries.ts +81 -0
- package/src/session/claude-session-store.ts +426 -0
- package/src/session/client-bridge.ts +85 -0
- package/src/session/codex-auto-reset.ts +673 -0
- package/src/session/codex-session-store.ts +673 -0
- package/src/session/compact-modes.ts +105 -0
- package/src/session/credential-pin.ts +93 -0
- package/src/session/eval-runner.ts +219 -0
- package/src/session/exit-diagnostics.ts +310 -0
- package/src/session/foreign-session-import.ts +52 -0
- package/src/session/foreign-session-jsonl.ts +29 -0
- package/src/session/foreign-session-store.ts +26 -0
- package/src/session/history-storage.ts +329 -0
- package/src/session/indexed-session-storage.ts +553 -0
- package/src/session/irc-bridge.ts +203 -0
- package/src/session/launch-completion.ts +37 -0
- package/src/session/messages.ts +1304 -0
- package/src/session/model-controls.ts +757 -0
- package/src/session/prewalk.ts +279 -0
- package/src/session/provider-image-budget.ts +86 -0
- package/src/session/queued-messages.ts +99 -0
- package/src/session/redis-session-storage.ts +257 -0
- package/src/session/retry-fallback-chains.ts +455 -0
- package/src/session/role-models.ts +85 -0
- package/src/session/session-advisors.ts +1896 -0
- package/src/session/session-context.ts +584 -0
- package/src/session/session-dump-format.ts +216 -0
- package/src/session/session-entries.ts +306 -0
- package/src/session/session-handoff.ts +325 -0
- package/src/session/session-history-format.ts +459 -0
- package/src/session/session-listing.ts +715 -0
- package/src/session/session-loader.ts +362 -0
- package/src/session/session-maintenance.ts +3115 -0
- package/src/session/session-manager.ts +2747 -0
- package/src/session/session-memory.ts +222 -0
- package/src/session/session-metadata.ts +53 -0
- package/src/session/session-migrations.ts +78 -0
- package/src/session/session-paths.ts +280 -0
- package/src/session/session-persistence.ts +293 -0
- package/src/session/session-provider-boundary.ts +306 -0
- package/src/session/session-stats.ts +349 -0
- package/src/session/session-storage.ts +774 -0
- package/src/session/session-title-slot.ts +141 -0
- package/src/session/session-tools.ts +1385 -0
- package/src/session/session-workspace.ts +53 -0
- package/src/session/settings-stream-fn.ts +79 -0
- package/src/session/shake-types.ts +43 -0
- package/src/session/snapcompact-inline.ts +545 -0
- package/src/session/snapcompact-savings-journal.ts +113 -0
- package/src/session/sql-session-storage.ts +374 -0
- package/src/session/stream-guards.ts +417 -0
- package/src/session/streaming-output.ts +1459 -0
- package/src/session/todo-tracker.ts +380 -0
- package/src/session/tool-choice-queue.ts +305 -0
- package/src/session/ttsr-coordinator.ts +496 -0
- package/src/session/turn-persistence.ts +142 -0
- package/src/session/turn-recovery.ts +2005 -0
- package/src/session/unexpected-stop-classifier.ts +141 -0
- package/src/session/yield-queue.ts +288 -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 +3149 -0
- package/src/slash-commands/helpers/active-oauth-account.ts +80 -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 +108 -0
- package/src/slash-commands/helpers/marketplace-manager.ts +25 -0
- package/src/slash-commands/helpers/mcp.ts +533 -0
- package/src/slash-commands/helpers/parse.ts +85 -0
- package/src/slash-commands/helpers/reset-usage.ts +68 -0
- package/src/slash-commands/helpers/security.ts +451 -0
- package/src/slash-commands/helpers/session-pin.ts +44 -0
- package/src/slash-commands/helpers/ssh.ts +196 -0
- package/src/slash-commands/helpers/stats-dashboard.ts +86 -0
- package/src/slash-commands/helpers/todo.ts +285 -0
- package/src/slash-commands/helpers/usage-report.ts +198 -0
- package/src/slash-commands/marketplace-install-parser.ts +99 -0
- package/src/slash-commands/types.ts +139 -0
- package/src/ssh/config-writer.ts +183 -0
- package/src/ssh/connection-manager.ts +667 -0
- package/src/ssh/file-transfer.ts +214 -0
- package/src/ssh/sshfs-mount.ts +163 -0
- package/src/ssh/utils.ts +51 -0
- package/src/startup-splash.ts +19 -0
- package/src/stt/asr-client.ts +401 -0
- package/src/stt/asr-protocol.ts +65 -0
- package/src/stt/asr-worker.ts +603 -0
- package/src/stt/downloader.ts +142 -0
- package/src/stt/endpointer.ts +259 -0
- package/src/stt/index.ts +6 -0
- package/src/stt/models.ts +150 -0
- package/src/stt/sherpa-runtime.ts +71 -0
- package/src/stt/stt-controller.ts +320 -0
- package/src/stt/submit-trigger.ts +74 -0
- package/src/subprocess/worker-client.ts +463 -0
- package/src/subprocess/worker-runtime.ts +494 -0
- package/src/system-prompt.ts +921 -0
- package/src/task/agents.ts +170 -0
- package/src/task/commands.ts +132 -0
- package/src/task/discovery.ts +145 -0
- package/src/task/executor.ts +3431 -0
- package/src/task/index.ts +1515 -0
- package/src/task/isolation-ownership.ts +106 -0
- package/src/task/isolation-runner.ts +444 -0
- package/src/task/label.ts +40 -0
- package/src/task/name-generator.ts +1577 -0
- package/src/task/omp-command.ts +26 -0
- package/src/task/output-manager.ts +115 -0
- package/src/task/parallel.ts +221 -0
- package/src/task/persisted-revive.ts +173 -0
- package/src/task/prewalk.ts +6 -0
- package/src/task/prompt-policy.ts +8 -0
- package/src/task/provider-concurrency.ts +100 -0
- package/src/task/read-only-policy.ts +27 -0
- package/src/task/render.ts +1830 -0
- package/src/task/renderer.ts +14 -0
- package/src/task/repair-args.ts +118 -0
- package/src/task/spawn-policy.ts +72 -0
- package/src/task/structured-subagent.ts +676 -0
- package/src/task/subprocess-tool-registry.ts +88 -0
- package/src/task/types.ts +555 -0
- package/src/task/worktree.ts +967 -0
- package/src/task/yield-assembly.ts +198 -0
- package/src/telemetry-export.ts +504 -0
- package/src/thinking.ts +377 -0
- package/src/tiny/device.ts +111 -0
- package/src/tiny/dtype.ts +101 -0
- package/src/tiny/message-preproc.ts +155 -0
- package/src/tiny/models.ts +268 -0
- package/src/tiny/text.ts +290 -0
- package/src/tiny/title-client.ts +460 -0
- package/src/tiny/title-protocol.ts +56 -0
- package/src/tiny/worker.ts +354 -0
- package/src/tools/acp-bridge.ts +125 -0
- package/src/tools/approval.ts +245 -0
- package/src/tools/ask.ts +1459 -0
- package/src/tools/ast-edit.ts +718 -0
- package/src/tools/ast-grep.ts +526 -0
- package/src/tools/auto-generated-guard.ts +335 -0
- package/src/tools/bash-interactive.ts +435 -0
- package/src/tools/bash-interceptor.ts +148 -0
- package/src/tools/bash-pty-selection.ts +14 -0
- package/src/tools/bash-skill-urls.ts +350 -0
- package/src/tools/bash.ts +1826 -0
- package/src/tools/browser/aria/aria-snapshot.bundle.txt +7 -0
- package/src/tools/browser/aria/aria-snapshot.ts +131 -0
- package/src/tools/browser/attach.ts +219 -0
- package/src/tools/browser/cmux/cmux-tab.ts +1531 -0
- package/src/tools/browser/cmux/rpc.ts +200 -0
- package/src/tools/browser/cmux/socket-client.ts +445 -0
- package/src/tools/browser/launch.ts +939 -0
- package/src/tools/browser/readable.ts +112 -0
- package/src/tools/browser/registry.ts +447 -0
- package/src/tools/browser/relay/bridge.ts +945 -0
- package/src/tools/browser/relay/daemon.ts +117 -0
- package/src/tools/browser/relay/extension-assets/background.js.txt +242 -0
- package/src/tools/browser/relay/extension-assets/manifest.json.txt +14 -0
- package/src/tools/browser/relay/extension-assets/options.html.txt +53 -0
- package/src/tools/browser/relay/extension-assets/options.js.txt +23 -0
- package/src/tools/browser/relay/kind.ts +41 -0
- package/src/tools/browser/relay/protocol.ts +54 -0
- package/src/tools/browser/relay/server.ts +141 -0
- package/src/tools/browser/render.ts +229 -0
- package/src/tools/browser/run-output.ts +76 -0
- package/src/tools/browser/shared-daemon.ts +139 -0
- package/src/tools/browser/tab-protocol.ts +123 -0
- package/src/tools/browser/tab-supervisor.ts +1077 -0
- package/src/tools/browser/tab-worker-entry.ts +29 -0
- package/src/tools/browser/tab-worker.ts +1982 -0
- package/src/tools/browser.ts +487 -0
- package/src/tools/builtin-names.ts +67 -0
- package/src/tools/checkpoint.ts +137 -0
- package/src/tools/computer/exposure.ts +14 -0
- package/src/tools/computer/protocol.ts +69 -0
- package/src/tools/computer/supervisor.ts +409 -0
- package/src/tools/computer/worker-entry.ts +39 -0
- package/src/tools/computer/worker.ts +745 -0
- package/src/tools/computer-renderer.ts +147 -0
- package/src/tools/computer.ts +222 -0
- package/src/tools/conflict-detect.ts +815 -0
- package/src/tools/context.ts +49 -0
- package/src/tools/debug.ts +1121 -0
- package/src/tools/default-renderer.ts +154 -0
- package/src/tools/essential-tools.ts +46 -0
- package/src/tools/eval-backends.ts +34 -0
- package/src/tools/eval-format/index.ts +24 -0
- package/src/tools/eval-format/javascript.ts +952 -0
- package/src/tools/eval-format/julia.ts +446 -0
- package/src/tools/eval-format/python.ts +544 -0
- package/src/tools/eval-format/ruby.ts +380 -0
- package/src/tools/eval-render.ts +784 -0
- package/src/tools/eval.ts +774 -0
- package/src/tools/fetch.ts +1889 -0
- package/src/tools/file-recorder.ts +35 -0
- package/src/tools/fs-cache-invalidation.ts +28 -0
- package/src/tools/gh-cache-invalidation.ts +175 -0
- package/src/tools/gh-format.ts +12 -0
- package/src/tools/gh-renderer.ts +484 -0
- package/src/tools/gh.ts +3958 -0
- package/src/tools/github-cache.ts +663 -0
- package/src/tools/glob.ts +691 -0
- package/src/tools/grep.ts +1920 -0
- package/src/tools/grouped-file-output.ts +210 -0
- package/src/tools/hub/index.ts +579 -0
- package/src/tools/hub/jobs.ts +714 -0
- package/src/tools/hub/launch.ts +690 -0
- package/src/tools/hub/messaging.ts +735 -0
- package/src/tools/hub/types.ts +117 -0
- package/src/tools/image-gen.ts +1689 -0
- package/src/tools/image-providers.ts +50 -0
- package/src/tools/index.ts +736 -0
- package/src/tools/inspect-image-renderer.ts +133 -0
- package/src/tools/inspect-image.ts +316 -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 +102 -0
- package/src/tools/match-line-format.ts +20 -0
- package/src/tools/memory-edit.ts +61 -0
- package/src/tools/memory-recall.ts +102 -0
- package/src/tools/memory-reflect.ts +88 -0
- package/src/tools/memory-render.ts +211 -0
- package/src/tools/memory-retain.ts +89 -0
- package/src/tools/output-meta.ts +860 -0
- package/src/tools/output-schema-validator.ts +307 -0
- package/src/tools/path-utils.ts +1489 -0
- package/src/tools/plan-mode-guard.ts +155 -0
- package/src/tools/puppeteer/00_stealth_tampering.txt +44 -0
- package/src/tools/puppeteer/01_stealth_activity.txt +80 -0
- package/src/tools/puppeteer/02_stealth_hairline.txt +57 -0
- package/src/tools/puppeteer/03_stealth_botd.txt +380 -0
- package/src/tools/puppeteer/04_stealth_iframe.txt +174 -0
- package/src/tools/puppeteer/05_stealth_webgl.txt +233 -0
- package/src/tools/puppeteer/06_stealth_screen.txt +260 -0
- package/src/tools/puppeteer/07_stealth_fonts.txt +99 -0
- package/src/tools/puppeteer/08_stealth_audio.txt +63 -0
- package/src/tools/puppeteer/09_stealth_locale.txt +51 -0
- package/src/tools/puppeteer/10_stealth_plugins.txt +212 -0
- package/src/tools/puppeteer/11_stealth_hardware.txt +59 -0
- package/src/tools/puppeteer/12_stealth_codecs.txt +42 -0
- package/src/tools/puppeteer/13_stealth_worker.txt +235 -0
- package/src/tools/read.ts +3762 -0
- package/src/tools/render-utils.ts +926 -0
- package/src/tools/renderers.ts +133 -0
- package/src/tools/report-tool-issue.ts +568 -0
- package/src/tools/resolve.ts +423 -0
- package/src/tools/review.ts +103 -0
- package/src/tools/run-scope.ts +417 -0
- package/src/tools/security-scan.ts +287 -0
- package/src/tools/shell-tokenize.ts +213 -0
- package/src/tools/sqlite-reader.ts +884 -0
- package/src/tools/terminal-output.ts +141 -0
- package/src/tools/todo.ts +1226 -0
- package/src/tools/tool-errors.ts +62 -0
- package/src/tools/tool-result.ts +102 -0
- package/src/tools/tool-timeouts.ts +38 -0
- package/src/tools/tts.ts +266 -0
- package/src/tools/vibe.ts +608 -0
- package/src/tools/write.ts +1646 -0
- package/src/tools/xdev.ts +560 -0
- package/src/tools/yield.ts +486 -0
- package/src/tts/downloader.ts +64 -0
- package/src/tts/index.ts +10 -0
- package/src/tts/models.ts +137 -0
- package/src/tts/runtime.ts +21 -0
- package/src/tts/speakable.ts +392 -0
- package/src/tts/speech-enhancer.ts +206 -0
- package/src/tts/streaming-player.ts +120 -0
- package/src/tts/tts-client.ts +475 -0
- package/src/tts/tts-protocol.ts +69 -0
- package/src/tts/tts-worker.ts +434 -0
- package/src/tts/vocalizer.ts +419 -0
- package/src/tts/wav.ts +58 -0
- package/src/tui/code-cell.ts +268 -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 +268 -0
- package/src/tui/status-line.ts +54 -0
- package/src/tui/tree-list.ts +172 -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/active-repo-context.ts +143 -0
- package/src/utils/block-context.ts +312 -0
- package/src/utils/changelog.ts +373 -0
- package/src/utils/clipboard.ts +361 -0
- package/src/utils/command-args.ts +74 -0
- package/src/utils/commit-message-generator.ts +148 -0
- package/src/utils/cpuprofile.ts +235 -0
- package/src/utils/edit-mode.ts +61 -0
- package/src/utils/enhanced-paste.ts +230 -0
- package/src/utils/event-bus.ts +33 -0
- package/src/utils/external-editor.ts +80 -0
- package/src/utils/fetch-timeout.ts +10 -0
- package/src/utils/file-display-mode.ts +44 -0
- package/src/utils/file-mentions.ts +293 -0
- package/src/utils/git.ts +2472 -0
- package/src/utils/image-loading.ts +236 -0
- package/src/utils/image-resize.ts +420 -0
- package/src/utils/image-vision-fallback.ts +196 -0
- package/src/utils/inspect-image-mode.ts +39 -0
- package/src/utils/ipc.ts +38 -0
- package/src/utils/jj.ts +422 -0
- package/src/utils/lang-from-path.ts +251 -0
- package/src/utils/late-cleanup.ts +17 -0
- package/src/utils/local-date.ts +7 -0
- package/src/utils/mac-file-urls.applescript +37 -0
- package/src/utils/markit-cache.ts +166 -0
- package/src/utils/markit.ts +223 -0
- package/src/utils/mupdf-wasm-embed.ts +12 -0
- package/src/utils/open.ts +126 -0
- package/src/utils/profile-tree.ts +111 -0
- package/src/utils/prompt-path.ts +3 -0
- package/src/utils/qrcode.ts +535 -0
- package/src/utils/sample-profile.ts +437 -0
- package/src/utils/session-color.ts +142 -0
- package/src/utils/shell-snapshot-fn-env.sh +63 -0
- package/src/utils/shell-snapshot.ts +326 -0
- package/src/utils/sixel.ts +69 -0
- package/src/utils/thinking-display.ts +163 -0
- package/src/utils/title-generator.ts +597 -0
- package/src/utils/token-rate.ts +72 -0
- package/src/utils/tool-choice.ts +50 -0
- package/src/utils/tools-manager.ts +411 -0
- package/src/utils/turndown.ts +82 -0
- package/src/utils/zip.ts +1106 -0
- package/src/vibe/runtime.ts +1684 -0
- package/src/vibe/state.ts +4 -0
- package/src/web/kagi.ts +305 -0
- package/src/web/parallel.ts +354 -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 +663 -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 +129 -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 +121 -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 +393 -0
- package/src/web/search/provider.ts +272 -0
- package/src/web/search/providers/anthropic.ts +406 -0
- package/src/web/search/providers/base.ts +112 -0
- package/src/web/search/providers/brave.ts +181 -0
- package/src/web/search/providers/browser-headers.ts +82 -0
- package/src/web/search/providers/browser-page.ts +125 -0
- package/src/web/search/providers/codex.ts +788 -0
- package/src/web/search/providers/duckduckgo.ts +382 -0
- package/src/web/search/providers/ecosia.ts +183 -0
- package/src/web/search/providers/exa.ts +513 -0
- package/src/web/search/providers/firecrawl.ts +213 -0
- package/src/web/search/providers/gemini.ts +634 -0
- package/src/web/search/providers/google.ts +195 -0
- package/src/web/search/providers/jina.ts +144 -0
- package/src/web/search/providers/kagi.ts +98 -0
- package/src/web/search/providers/kimi.ts +221 -0
- package/src/web/search/providers/mojeek.ts +220 -0
- package/src/web/search/providers/parallel.ts +186 -0
- package/src/web/search/providers/perplexity-auth.ts +142 -0
- package/src/web/search/providers/perplexity.ts +997 -0
- package/src/web/search/providers/public.ts +199 -0
- package/src/web/search/providers/searxng.ts +467 -0
- package/src/web/search/providers/startpage.ts +225 -0
- package/src/web/search/providers/synthetic.ts +126 -0
- package/src/web/search/providers/tavily.ts +244 -0
- package/src/web/search/providers/tinyfish.ts +166 -0
- package/src/web/search/providers/utils.ts +130 -0
- package/src/web/search/providers/xai.ts +372 -0
- package/src/web/search/providers/zai.ts +452 -0
- package/src/web/search/query.ts +850 -0
- package/src/web/search/render.ts +262 -0
- package/src/web/search/types.ts +518 -0
- package/src/web/search/utils.ts +17 -0
- package/src/workspace-tree.ts +326 -0
|
@@ -0,0 +1,2058 @@
|
|
|
1
|
+
import { type AgentToolResult, ThinkingLevel } from "@oh-my-pi/pi-agent-core";
|
|
2
|
+
import type { CompactionOutcome } from "@oh-my-pi/pi-agent-core/compaction";
|
|
3
|
+
import { PASTE_CODE_LOGIN_PROVIDERS } from "@oh-my-pi/pi-ai";
|
|
4
|
+
import { getOAuthProviders } from "@oh-my-pi/pi-ai/oauth";
|
|
5
|
+
import type { OAuthProvider } from "@oh-my-pi/pi-ai/oauth/types";
|
|
6
|
+
import type { Component, OverlayHandle } from "@oh-my-pi/pi-tui";
|
|
7
|
+
import { Loader, Spacer, setTuiTight, Text } from "@oh-my-pi/pi-tui";
|
|
8
|
+
import { getAgentDbPath, getAgentDir, getProjectDir, normalizePathForComparison } from "@oh-my-pi/pi-utils";
|
|
9
|
+
import {
|
|
10
|
+
type AdvisorConfigScope,
|
|
11
|
+
discoverAdvisorConfigs,
|
|
12
|
+
loadWatchdogConfigFile,
|
|
13
|
+
resolveAdvisorConfigEditPath,
|
|
14
|
+
saveWatchdogConfigFile,
|
|
15
|
+
} from "../../advisor";
|
|
16
|
+
import { reset as resetCapabilities } from "../../capability";
|
|
17
|
+
import {
|
|
18
|
+
formatModelSelectorValue,
|
|
19
|
+
resolveAdvisorRoleSelection,
|
|
20
|
+
resolveModelRoleValue,
|
|
21
|
+
} from "../../config/model-resolver";
|
|
22
|
+
import { getRoleInfo } from "../../config/model-roles";
|
|
23
|
+
import { settings } from "../../config/settings";
|
|
24
|
+
import { disableProvider, enableProvider } from "../../discovery";
|
|
25
|
+
import { clearPluginRootsAndCaches, resolveActiveProjectRegistryPath } from "../../discovery/helpers";
|
|
26
|
+
import {
|
|
27
|
+
getInstalledPluginsRegistryPath,
|
|
28
|
+
getMarketplacesCacheDir,
|
|
29
|
+
getMarketplacesRegistryPath,
|
|
30
|
+
getPluginsCacheDir,
|
|
31
|
+
MarketplaceManager,
|
|
32
|
+
} from "../../extensibility/plugins/marketplace";
|
|
33
|
+
import {
|
|
34
|
+
getAvailableThemes,
|
|
35
|
+
getSymbolTheme,
|
|
36
|
+
previewTheme,
|
|
37
|
+
setColorBlindMode,
|
|
38
|
+
setMarkdownMermaidRendering,
|
|
39
|
+
setSymbolPreset,
|
|
40
|
+
setTheme,
|
|
41
|
+
theme,
|
|
42
|
+
} from "../../modes/theme/theme";
|
|
43
|
+
import type { InteractiveModeContext } from "../../modes/types";
|
|
44
|
+
import type { SessionOAuthAccountList } from "../../session/agent-session-types";
|
|
45
|
+
import type { ResetCreditAccountStatus, ResetCreditRedeemOutcome } from "../../session/auth-storage";
|
|
46
|
+
import {
|
|
47
|
+
createForeignSessionStore,
|
|
48
|
+
foreignSessionInfoToSessionInfo,
|
|
49
|
+
foreignSessionSourceName,
|
|
50
|
+
persistForeignSession,
|
|
51
|
+
} from "../../session/foreign-session-import";
|
|
52
|
+
import type { ForeignSessionInfo, ForeignSessionSource } from "../../session/foreign-session-store";
|
|
53
|
+
import type { SessionInfo } from "../../session/session-listing";
|
|
54
|
+
import { SessionManager } from "../../session/session-manager";
|
|
55
|
+
import { FileSessionStorage } from "../../session/session-storage";
|
|
56
|
+
import { type LogoutAccount, toLogoutAccounts } from "../../slash-commands/helpers/logout";
|
|
57
|
+
import {
|
|
58
|
+
describeRedeemOutcome,
|
|
59
|
+
type ResetUsageAccount,
|
|
60
|
+
toResetUsageAccounts,
|
|
61
|
+
} from "../../slash-commands/helpers/reset-usage";
|
|
62
|
+
import { toSessionPinAccounts } from "../../slash-commands/helpers/session-pin";
|
|
63
|
+
import {
|
|
64
|
+
AUTO_THINKING,
|
|
65
|
+
type ConfiguredThinkingLevel,
|
|
66
|
+
concreteThinkingLevel,
|
|
67
|
+
parseConfiguredThinkingLevel,
|
|
68
|
+
} from "../../thinking";
|
|
69
|
+
import {
|
|
70
|
+
isSearchProviderId,
|
|
71
|
+
setExcludedSearchProviders,
|
|
72
|
+
setImageProviderOrder,
|
|
73
|
+
setSearchProviderOrder,
|
|
74
|
+
type ToolSession,
|
|
75
|
+
} from "../../tools";
|
|
76
|
+
import { AskTool, type AskToolDetails, type AskToolInput } from "../../tools/ask";
|
|
77
|
+
import { shortenPath } from "../../tools/render-utils";
|
|
78
|
+
import { ToolAbortError } from "../../tools/tool-errors";
|
|
79
|
+
import { copyToClipboard } from "../../utils/clipboard";
|
|
80
|
+
import { repo } from "../../utils/git";
|
|
81
|
+
import { setSessionTerminalTitle } from "../../utils/title-generator";
|
|
82
|
+
import { type AdvisorConfigDeps, AdvisorConfigOverlayComponent } from "../components/advisor-config";
|
|
83
|
+
import { AgentDashboard } from "../components/agent-dashboard";
|
|
84
|
+
import { AgentHubOverlayComponent } from "../components/agent-hub";
|
|
85
|
+
import { AssistantMessageComponent } from "../components/assistant-message";
|
|
86
|
+
import { CopySelectorComponent } from "../components/copy-selector";
|
|
87
|
+
import { ExtensionDashboard } from "../components/extensions";
|
|
88
|
+
import { HistorySearchComponent } from "../components/history-search";
|
|
89
|
+
import { LoginDialogComponent } from "../components/login-dialog";
|
|
90
|
+
import { LogoutAccountSelectorComponent } from "../components/logout-account-selector";
|
|
91
|
+
import { ModelHubComponent, type ModelRoleSelectionScope } from "../components/model-hub";
|
|
92
|
+
import { ModelPickerComponent } from "../components/model-picker";
|
|
93
|
+
import { OAuthSelectorComponent } from "../components/oauth-selector";
|
|
94
|
+
import { PluginSelectorComponent } from "../components/plugin-selector";
|
|
95
|
+
import { ReadToolGroupComponent } from "../components/read-tool-group";
|
|
96
|
+
import { ResetUsageSelectorComponent } from "../components/reset-usage-selector";
|
|
97
|
+
import { renderSegmentTrack } from "../components/segment-track";
|
|
98
|
+
import { SessionAccountSelectorComponent } from "../components/session-account-selector";
|
|
99
|
+
import { SessionSelectorComponent, type SessionSelectorOptions } from "../components/session-selector";
|
|
100
|
+
import { SettingsSelectorComponent } from "../components/settings-selector";
|
|
101
|
+
import { StrippedToolCallsPlaceholder } from "../components/stripped-tool-calls-placeholder";
|
|
102
|
+
import { ToolExecutionComponent } from "../components/tool-execution";
|
|
103
|
+
import { TranscriptBlock } from "../components/transcript-container";
|
|
104
|
+
import { TreeSelectorComponent } from "../components/tree-selector";
|
|
105
|
+
import { UserMessageSelectorComponent } from "../components/user-message-selector";
|
|
106
|
+
import type { SessionObserverRegistry } from "../session-observer-registry";
|
|
107
|
+
import { buildCopyTargets } from "../utils/copy-targets";
|
|
108
|
+
|
|
109
|
+
const MANUAL_LOGIN_PROMPT = "Paste the authorization code (or full redirect URL), then press Enter:";
|
|
110
|
+
|
|
111
|
+
export class SelectorController {
|
|
112
|
+
constructor(private ctx: InteractiveModeContext) {}
|
|
113
|
+
/**
|
|
114
|
+
* Mount a primary fullscreen menu through the one polished modal path shared
|
|
115
|
+
* by Settings, Model Hub, and Agent Hub.
|
|
116
|
+
*/
|
|
117
|
+
#showFullscreenMenu(component: Component): OverlayHandle {
|
|
118
|
+
const handle = this.ctx.ui.showOverlay(component, {
|
|
119
|
+
anchor: "bottom-center",
|
|
120
|
+
width: "100%",
|
|
121
|
+
maxHeight: "100%",
|
|
122
|
+
margin: 0,
|
|
123
|
+
fullscreen: true,
|
|
124
|
+
});
|
|
125
|
+
this.ctx.ui.setFocus(component);
|
|
126
|
+
this.ctx.ui.requestRender();
|
|
127
|
+
return handle;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
#defaultRoleMutationTail = Promise.resolve();
|
|
131
|
+
|
|
132
|
+
async #acquireDefaultRoleMutation(): Promise<() => void> {
|
|
133
|
+
const previous = this.#defaultRoleMutationTail;
|
|
134
|
+
const { promise, resolve } = Promise.withResolvers<void>();
|
|
135
|
+
this.#defaultRoleMutationTail = previous.then(() => promise);
|
|
136
|
+
await previous;
|
|
137
|
+
return resolve;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
async #refreshOAuthProviderAuthState(): Promise<void> {
|
|
141
|
+
const oauthProviders = getOAuthProviders();
|
|
142
|
+
await Promise.all(
|
|
143
|
+
oauthProviders.map(provider =>
|
|
144
|
+
this.ctx.session.modelRegistry
|
|
145
|
+
.getApiKeyForProvider(provider.id, this.ctx.session.sessionId)
|
|
146
|
+
.catch(() => undefined),
|
|
147
|
+
),
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Restore keyboard focus to whatever currently owns the editor slot. The
|
|
153
|
+
* slot can hold the editor itself or a hook selector/input/editor pushed
|
|
154
|
+
* in by `ExtensionUiController` — e.g. an approval prompt that fired while
|
|
155
|
+
* a fullscreen overlay was up. `overlayHandle.hide()` restores focus to
|
|
156
|
+
* the component focused when the overlay opened, which is stale in that
|
|
157
|
+
* case (the editor was swapped out): keys land on a hidden editor and the
|
|
158
|
+
* visible prompt receives nothing (issue #3349). Call this after the
|
|
159
|
+
* overlay hides to re-target focus at the visible slot owner.
|
|
160
|
+
*/
|
|
161
|
+
focusActiveEditorArea(): void {
|
|
162
|
+
const visible = this.ctx.editorContainer.children[0] ?? this.ctx.editor;
|
|
163
|
+
this.ctx.ui.setFocus(visible);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Shows a selector component in place of the editor.
|
|
168
|
+
* @param create Factory that receives a `done` callback and returns the component and focus target
|
|
169
|
+
*/
|
|
170
|
+
showSelector(create: (done: () => void) => { component: Component; focus: Component }): void {
|
|
171
|
+
const done = () => {
|
|
172
|
+
this.ctx.editorContainer.clear();
|
|
173
|
+
this.ctx.editorContainer.addChild(this.ctx.editor);
|
|
174
|
+
this.ctx.ui.setFocus(this.ctx.editor);
|
|
175
|
+
};
|
|
176
|
+
const { component, focus } = create(done);
|
|
177
|
+
this.ctx.editorContainer.clear();
|
|
178
|
+
this.ctx.editorContainer.addChild(component);
|
|
179
|
+
this.ctx.ui.setFocus(focus);
|
|
180
|
+
this.ctx.ui.requestRender();
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
showSettingsSelector(): void {
|
|
184
|
+
getAvailableThemes().then(availableThemes => {
|
|
185
|
+
// Fullscreen settings editor on the alternate screen: the overlay
|
|
186
|
+
// enables mouse tracking (click/hover/wheel) for its lifetime and
|
|
187
|
+
// the transcript stays untouched underneath.
|
|
188
|
+
let overlayHandle: OverlayHandle | undefined;
|
|
189
|
+
const done = () => {
|
|
190
|
+
overlayHandle?.hide();
|
|
191
|
+
this.focusActiveEditorArea();
|
|
192
|
+
this.ctx.ui.requestRender();
|
|
193
|
+
};
|
|
194
|
+
const selector = new SettingsSelectorComponent(
|
|
195
|
+
{
|
|
196
|
+
availableThinkingLevels: [...this.ctx.session.getAvailableThinkingLevels()],
|
|
197
|
+
thinkingLevel: this.ctx.session.thinkingLevel,
|
|
198
|
+
availableThemes,
|
|
199
|
+
providers: [...new Set(this.ctx.session.getAvailableModels().map(model => model.provider))].sort(
|
|
200
|
+
(a, b) => a.localeCompare(b),
|
|
201
|
+
),
|
|
202
|
+
cwd: getProjectDir(),
|
|
203
|
+
model: this.ctx.session.model,
|
|
204
|
+
imageBudget: this.ctx.ui.imageBudget,
|
|
205
|
+
requestRender: () => this.ctx.ui.requestRender(),
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
onChange: (id, value) => this.handleSettingChange(id, value),
|
|
209
|
+
onThemePreview: async themeName => {
|
|
210
|
+
const result = await previewTheme(themeName);
|
|
211
|
+
if (result.success) {
|
|
212
|
+
this.ctx.statusLine.invalidate();
|
|
213
|
+
this.ctx.ui.invalidate();
|
|
214
|
+
this.ctx.ui.requestRender();
|
|
215
|
+
}
|
|
216
|
+
},
|
|
217
|
+
onStatusLinePreview: previewSettings => {
|
|
218
|
+
// Update status line with preview settings
|
|
219
|
+
this.ctx.statusLine.updateSettings({
|
|
220
|
+
preset: settings.get("statusLine.preset"),
|
|
221
|
+
leftSegments: settings.get("statusLine.leftSegments"),
|
|
222
|
+
rightSegments: settings.get("statusLine.rightSegments"),
|
|
223
|
+
separator: settings.get("statusLine.separator"),
|
|
224
|
+
showHookStatus: settings.get("statusLine.showHookStatus"),
|
|
225
|
+
sessionAccent: settings.get("statusLine.sessionAccent"),
|
|
226
|
+
transparent: settings.get("statusLine.transparent"),
|
|
227
|
+
compactThinkingLevel: settings.get("statusLine.compactThinkingLevel"),
|
|
228
|
+
...previewSettings,
|
|
229
|
+
});
|
|
230
|
+
this.ctx.ui.requestRender();
|
|
231
|
+
},
|
|
232
|
+
getStatusLinePreview: () => {
|
|
233
|
+
// Return the rendered status line for inline preview
|
|
234
|
+
const availableWidth = this.ctx.editor.getTopBorderAvailableWidth(this.ctx.ui.terminal.columns);
|
|
235
|
+
return this.ctx.statusLine.getTopBorder(availableWidth).content;
|
|
236
|
+
},
|
|
237
|
+
onPluginsChanged: async () => {
|
|
238
|
+
const projectPath = await resolveActiveProjectRegistryPath(this.ctx.sessionManager.getCwd());
|
|
239
|
+
clearPluginRootsAndCaches(projectPath ? [projectPath] : undefined);
|
|
240
|
+
await this.ctx.refreshSkillState();
|
|
241
|
+
await this.ctx.refreshSlashCommandState();
|
|
242
|
+
resetCapabilities();
|
|
243
|
+
this.ctx.ui.requestRender();
|
|
244
|
+
},
|
|
245
|
+
onCancel: () => {
|
|
246
|
+
done();
|
|
247
|
+
// Restore status line to saved settings
|
|
248
|
+
this.ctx.statusLine.updateSettings({
|
|
249
|
+
preset: settings.get("statusLine.preset"),
|
|
250
|
+
leftSegments: settings.get("statusLine.leftSegments"),
|
|
251
|
+
rightSegments: settings.get("statusLine.rightSegments"),
|
|
252
|
+
separator: settings.get("statusLine.separator"),
|
|
253
|
+
showHookStatus: settings.get("statusLine.showHookStatus"),
|
|
254
|
+
sessionAccent: settings.get("statusLine.sessionAccent"),
|
|
255
|
+
transparent: settings.get("statusLine.transparent"),
|
|
256
|
+
compactThinkingLevel: settings.get("statusLine.compactThinkingLevel"),
|
|
257
|
+
});
|
|
258
|
+
this.ctx.ui.requestRender();
|
|
259
|
+
},
|
|
260
|
+
},
|
|
261
|
+
);
|
|
262
|
+
overlayHandle = this.#showFullscreenMenu(selector);
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
showAdvisorConfigure(): void {
|
|
267
|
+
const cwd = this.ctx.sessionManager.getCwd();
|
|
268
|
+
const agentDir = getAgentDir() ?? getProjectDir();
|
|
269
|
+
const initialScope: AdvisorConfigScope = "project";
|
|
270
|
+
void (async () => {
|
|
271
|
+
// "Project" scope edits the repo-root WATCHDOG.yml (the project-level file
|
|
272
|
+
// discovery walks), not the launch subdir — `getProjectDir()` is only cwd.
|
|
273
|
+
let projectDir = cwd;
|
|
274
|
+
try {
|
|
275
|
+
projectDir = (await repo.root(cwd)) ?? cwd;
|
|
276
|
+
} catch {
|
|
277
|
+
projectDir = cwd;
|
|
278
|
+
}
|
|
279
|
+
const dirs = { projectDir, agentDir };
|
|
280
|
+
const initialDoc = await loadWatchdogConfigFile(await resolveAdvisorConfigEditPath(initialScope, dirs));
|
|
281
|
+
// Fullscreen editor on the alternate screen (the /settings idiom): the
|
|
282
|
+
// overlay holds the alt buffer + mouse tracking; the transcript stays put.
|
|
283
|
+
let overlayHandle: OverlayHandle | undefined;
|
|
284
|
+
const done = () => {
|
|
285
|
+
overlayHandle?.hide();
|
|
286
|
+
this.focusActiveEditorArea();
|
|
287
|
+
this.ctx.ui.requestRender();
|
|
288
|
+
};
|
|
289
|
+
// Label the seeded implicit-default row with the actual advisor-role model
|
|
290
|
+
// (NOT the first live advisor, which may be a named advisor from another scope).
|
|
291
|
+
const advisorRoleSel = resolveAdvisorRoleSelection(
|
|
292
|
+
this.ctx.settings,
|
|
293
|
+
this.ctx.session.modelRegistry.getAvailable(),
|
|
294
|
+
);
|
|
295
|
+
const defaultAdvisorModel = advisorRoleSel?.model;
|
|
296
|
+
const deps: AdvisorConfigDeps = {
|
|
297
|
+
modelRegistry: this.ctx.session.modelRegistry,
|
|
298
|
+
settings: this.ctx.settings,
|
|
299
|
+
scopedModels: this.ctx.session.scopedModels,
|
|
300
|
+
availableToolNames: this.ctx.session.getAdvisorAvailableToolNames(),
|
|
301
|
+
defaultModelLabel: defaultAdvisorModel
|
|
302
|
+
? `${defaultAdvisorModel.provider}/${defaultAdvisorModel.id}`
|
|
303
|
+
: undefined,
|
|
304
|
+
};
|
|
305
|
+
const overlay = new AdvisorConfigOverlayComponent(this.ctx.ui, deps, initialScope, initialDoc, {
|
|
306
|
+
loadDoc: async scope => loadWatchdogConfigFile(await resolveAdvisorConfigEditPath(scope, dirs)),
|
|
307
|
+
save: async (scope, doc) => {
|
|
308
|
+
await saveWatchdogConfigFile(await resolveAdvisorConfigEditPath(scope, dirs), doc);
|
|
309
|
+
// Re-discover the merged roster (project + user) so the live advisors
|
|
310
|
+
// reflect cross-level precedence, not just the edited file.
|
|
311
|
+
const discovered = await discoverAdvisorConfigs(cwd, agentDir);
|
|
312
|
+
const count = this.ctx.session.applyAdvisorConfigs(discovered.advisors, discovered.sharedInstructions);
|
|
313
|
+
this.ctx.statusLine.invalidate();
|
|
314
|
+
this.ctx.showStatus(
|
|
315
|
+
count > 0
|
|
316
|
+
? `Saved ${scope} WATCHDOG.yml — ${count} advisor${count === 1 ? "" : "s"} active.`
|
|
317
|
+
: `Saved ${scope} WATCHDOG.yml. Run /advisor on to activate the configured advisors.`,
|
|
318
|
+
);
|
|
319
|
+
this.ctx.ui.requestRender();
|
|
320
|
+
},
|
|
321
|
+
close: done,
|
|
322
|
+
requestRender: () => this.ctx.ui.requestRender(),
|
|
323
|
+
notify: message => this.ctx.showStatus(message),
|
|
324
|
+
getAdvisorStats: () => this.ctx.session.getAdvisorStats().advisors,
|
|
325
|
+
getUsageReports: async () => this.ctx.session.fetchUsageReports?.() ?? null,
|
|
326
|
+
resolveActiveAccount: (provider, sessionId) =>
|
|
327
|
+
this.ctx.session.modelRegistry.authStorage.getOAuthAccountIdentity(
|
|
328
|
+
provider,
|
|
329
|
+
sessionId ?? this.ctx.session.sessionId,
|
|
330
|
+
),
|
|
331
|
+
});
|
|
332
|
+
overlayHandle = this.ctx.ui.showOverlay(overlay, {
|
|
333
|
+
anchor: "bottom-center",
|
|
334
|
+
width: "100%",
|
|
335
|
+
maxHeight: "100%",
|
|
336
|
+
margin: 0,
|
|
337
|
+
fullscreen: true,
|
|
338
|
+
});
|
|
339
|
+
this.ctx.ui.setFocus(overlay);
|
|
340
|
+
this.ctx.ui.requestRender();
|
|
341
|
+
})();
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
showHistorySearch(): void {
|
|
345
|
+
const historyStorage = this.ctx.historyStorage;
|
|
346
|
+
if (!historyStorage) return;
|
|
347
|
+
|
|
348
|
+
this.showSelector(done => {
|
|
349
|
+
const component = new HistorySearchComponent(
|
|
350
|
+
historyStorage,
|
|
351
|
+
prompt => {
|
|
352
|
+
done();
|
|
353
|
+
this.ctx.editor.setText(prompt);
|
|
354
|
+
this.ctx.ui.requestRender();
|
|
355
|
+
},
|
|
356
|
+
() => {
|
|
357
|
+
done();
|
|
358
|
+
this.ctx.ui.requestRender();
|
|
359
|
+
},
|
|
360
|
+
);
|
|
361
|
+
return { component, focus: component };
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
/**
|
|
366
|
+
* Show the Extension Control Center dashboard.
|
|
367
|
+
* Replaces /status with a unified view of all providers and extensions.
|
|
368
|
+
*/
|
|
369
|
+
async showExtensionsDashboard(): Promise<void> {
|
|
370
|
+
const dashboard = await ExtensionDashboard.create(getProjectDir(), this.ctx.settings, this.ctx.ui.terminal.rows);
|
|
371
|
+
// Fullscreen dashboard on the alternate screen (the /settings idiom): the
|
|
372
|
+
// overlay borrows the terminal's alt buffer and enables mouse tracking for
|
|
373
|
+
// its lifetime, leaving the transcript untouched underneath.
|
|
374
|
+
const overlay = this.ctx.ui.showOverlay(dashboard, {
|
|
375
|
+
width: "100%",
|
|
376
|
+
maxHeight: "100%",
|
|
377
|
+
anchor: "top-left",
|
|
378
|
+
margin: 0,
|
|
379
|
+
fullscreen: true,
|
|
380
|
+
});
|
|
381
|
+
dashboard.onClose = () => {
|
|
382
|
+
overlay.hide();
|
|
383
|
+
this.focusActiveEditorArea();
|
|
384
|
+
this.ctx.ui.requestRender();
|
|
385
|
+
};
|
|
386
|
+
dashboard.onRequestRender = () => {
|
|
387
|
+
this.ctx.ui.requestRender();
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
/**
|
|
392
|
+
* Show the Agent Control Center dashboard.
|
|
393
|
+
*/
|
|
394
|
+
async showAgentsDashboard(): Promise<void> {
|
|
395
|
+
const activeModel = this.ctx.session.model;
|
|
396
|
+
const activeModelPattern = activeModel ? `${activeModel.provider}/${activeModel.id}` : undefined;
|
|
397
|
+
const defaultModelPattern = this.ctx.settings.getModelRole("default");
|
|
398
|
+
const dashboard = await AgentDashboard.create(getProjectDir(), this.ctx.settings, this.ctx.ui.terminal.rows, {
|
|
399
|
+
modelRegistry: this.ctx.session.modelRegistry,
|
|
400
|
+
activeModelPattern,
|
|
401
|
+
defaultModelPattern,
|
|
402
|
+
});
|
|
403
|
+
const overlay = this.ctx.ui.showOverlay(dashboard, {
|
|
404
|
+
width: "100%",
|
|
405
|
+
maxHeight: "100%",
|
|
406
|
+
anchor: "top-left",
|
|
407
|
+
margin: 0,
|
|
408
|
+
});
|
|
409
|
+
dashboard.onClose = () => {
|
|
410
|
+
overlay.hide();
|
|
411
|
+
this.focusActiveEditorArea();
|
|
412
|
+
this.ctx.ui.requestRender();
|
|
413
|
+
};
|
|
414
|
+
dashboard.onRequestRender = () => {
|
|
415
|
+
this.ctx.ui.requestRender();
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
/**
|
|
420
|
+
* Handle setting changes from the settings selector.
|
|
421
|
+
* Most settings are saved directly via SettingsManager in the definitions.
|
|
422
|
+
* This handles side effects and session-specific settings.
|
|
423
|
+
*/
|
|
424
|
+
handleSettingChange(id: string, value: unknown): void {
|
|
425
|
+
// Discovery provider toggles
|
|
426
|
+
if (id.startsWith("discovery.")) {
|
|
427
|
+
const providerId = id.replace("discovery.", "");
|
|
428
|
+
if (value) {
|
|
429
|
+
enableProvider(providerId);
|
|
430
|
+
} else {
|
|
431
|
+
disableProvider(providerId);
|
|
432
|
+
}
|
|
433
|
+
return;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
switch (id) {
|
|
437
|
+
// Session-managed settings (not in SettingsManager)
|
|
438
|
+
case "autoCompact":
|
|
439
|
+
this.ctx.session.setAutoCompactionEnabled(value as boolean);
|
|
440
|
+
this.ctx.statusLine.setAutoCompactEnabled(value as boolean);
|
|
441
|
+
break;
|
|
442
|
+
case "advisor.enabled":
|
|
443
|
+
this.ctx.session.setAdvisorEnabled(value as boolean);
|
|
444
|
+
this.ctx.statusLine.invalidate();
|
|
445
|
+
this.ctx.ui.requestRender();
|
|
446
|
+
break;
|
|
447
|
+
case "steeringMode":
|
|
448
|
+
this.ctx.session.setSteeringMode(value as "all" | "one-at-a-time");
|
|
449
|
+
break;
|
|
450
|
+
case "followUpMode":
|
|
451
|
+
this.ctx.session.setFollowUpMode(value as "all" | "one-at-a-time");
|
|
452
|
+
break;
|
|
453
|
+
case "interruptMode":
|
|
454
|
+
this.ctx.session.setInterruptMode(value as "immediate" | "wait");
|
|
455
|
+
break;
|
|
456
|
+
case "thinkingLevel":
|
|
457
|
+
case "defaultThinkingLevel":
|
|
458
|
+
this.ctx.session.setThinkingLevel(value as ConfiguredThinkingLevel, true);
|
|
459
|
+
this.ctx.statusLine.invalidate();
|
|
460
|
+
this.ctx.updateEditorBorderColor();
|
|
461
|
+
break;
|
|
462
|
+
case "personality":
|
|
463
|
+
void this.ctx.session.refreshBaseSystemPrompt().catch(err => {
|
|
464
|
+
this.ctx.showError(`Failed to apply personality: ${err}`);
|
|
465
|
+
});
|
|
466
|
+
break;
|
|
467
|
+
case "tools.xdevDocs":
|
|
468
|
+
void this.ctx.session.refreshBaseSystemPrompt().catch(err => {
|
|
469
|
+
this.ctx.showError(`Failed to apply xd:// prompt docs setting: ${err}`);
|
|
470
|
+
});
|
|
471
|
+
break;
|
|
472
|
+
case "memory.backend":
|
|
473
|
+
void this.ctx.session.applyMemoryBackend().catch(err => {
|
|
474
|
+
this.ctx.showError(`Failed to apply memory backend: ${err}`);
|
|
475
|
+
});
|
|
476
|
+
break;
|
|
477
|
+
case "inspect_image.mode":
|
|
478
|
+
void this.ctx.session.applyInspectImageModeChange().catch(err => {
|
|
479
|
+
this.ctx.showError(`Failed to apply vision mode: ${err}`);
|
|
480
|
+
});
|
|
481
|
+
break;
|
|
482
|
+
|
|
483
|
+
case "autocompleteMaxVisible":
|
|
484
|
+
this.ctx.editor.setAutocompleteMaxVisible(typeof value === "number" ? value : Number(value));
|
|
485
|
+
break;
|
|
486
|
+
|
|
487
|
+
// Settings with UI side effects
|
|
488
|
+
case "display.hideToolActivity": {
|
|
489
|
+
const hidden = value as boolean;
|
|
490
|
+
this.ctx.hideToolActivity = hidden;
|
|
491
|
+
if (!hidden) this.ctx.toolOutputExpanded = false;
|
|
492
|
+
for (const child of this.ctx.chatContainer.children) {
|
|
493
|
+
if (child instanceof ToolExecutionComponent || child instanceof ReadToolGroupComponent) {
|
|
494
|
+
if (!hidden) child.setExpanded(false);
|
|
495
|
+
child.setToolActivityVisible(!hidden);
|
|
496
|
+
} else if (child instanceof AssistantMessageComponent) {
|
|
497
|
+
child.setToolResultImagesVisible(!hidden);
|
|
498
|
+
} else if (child instanceof StrippedToolCallsPlaceholder) {
|
|
499
|
+
child.setToolActivityVisible(!hidden);
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
if (hidden) this.ctx.ui.clearInlineImages();
|
|
503
|
+
this.ctx.ui.resetDisplay();
|
|
504
|
+
break;
|
|
505
|
+
}
|
|
506
|
+
case "terminal.showImages":
|
|
507
|
+
case "showImages": {
|
|
508
|
+
const visible = value as boolean;
|
|
509
|
+
for (const child of this.ctx.chatContainer.children) {
|
|
510
|
+
if (child instanceof ToolExecutionComponent) {
|
|
511
|
+
child.setShowImages(visible);
|
|
512
|
+
} else if (child instanceof AssistantMessageComponent) {
|
|
513
|
+
child.setImagesVisible(visible);
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
if (!visible) this.ctx.ui.clearInlineImages();
|
|
517
|
+
this.ctx.ui.resetDisplay();
|
|
518
|
+
break;
|
|
519
|
+
}
|
|
520
|
+
case "hideThinkingBlock":
|
|
521
|
+
this.ctx.hideThinkingBlock = value as boolean;
|
|
522
|
+
for (const child of this.ctx.chatContainer.children) {
|
|
523
|
+
if (child instanceof AssistantMessageComponent) {
|
|
524
|
+
child.setHideThinkingBlock(this.ctx.effectiveHideThinkingBlock);
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
// Full clear + replay so blocks frozen in committed scrollback on
|
|
528
|
+
// ED3-risk terminals retire their stale snapshots too (see
|
|
529
|
+
// InputController.toggleThinkingBlockVisibility).
|
|
530
|
+
this.ctx.ui.resetDisplay();
|
|
531
|
+
break;
|
|
532
|
+
case "proseOnlyThinking":
|
|
533
|
+
this.ctx.proseOnlyThinking = value as boolean;
|
|
534
|
+
for (const child of this.ctx.chatContainer.children) {
|
|
535
|
+
if (child instanceof AssistantMessageComponent) {
|
|
536
|
+
child.setProseOnlyThinking(value as boolean);
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
this.ctx.ui.resetDisplay();
|
|
540
|
+
break;
|
|
541
|
+
case "omitThinking":
|
|
542
|
+
this.ctx.session.agent.hideThinkingSummary = value as boolean;
|
|
543
|
+
break;
|
|
544
|
+
case "display.cacheMissMarker":
|
|
545
|
+
// Rebuild re-runs the usage-based detection under the new setting so
|
|
546
|
+
// markers appear/disappear; full reset retires any already committed
|
|
547
|
+
// to native scrollback (mirrors hideThinking).
|
|
548
|
+
this.ctx.rebuildChatFromMessages();
|
|
549
|
+
this.ctx.ui.resetDisplay();
|
|
550
|
+
break;
|
|
551
|
+
case "display.collapseCompacted":
|
|
552
|
+
// Rebuild swaps between the collapsed tail and the full inline
|
|
553
|
+
// history; full reset retires blocks already committed to native
|
|
554
|
+
// scrollback (mirrors cacheMissMarker).
|
|
555
|
+
this.ctx.rebuildChatFromMessages();
|
|
556
|
+
this.ctx.ui.resetDisplay();
|
|
557
|
+
break;
|
|
558
|
+
case "tui.tight":
|
|
559
|
+
setTuiTight(value as boolean);
|
|
560
|
+
this.ctx.ui.invalidate();
|
|
561
|
+
this.ctx.ui.requestRender();
|
|
562
|
+
break;
|
|
563
|
+
|
|
564
|
+
case "tui.scrollbackRebuild":
|
|
565
|
+
this.ctx.ui.setScrollbackRebuild(value as boolean);
|
|
566
|
+
break;
|
|
567
|
+
|
|
568
|
+
case "tui.renderMermaid":
|
|
569
|
+
setMarkdownMermaidRendering(value as boolean);
|
|
570
|
+
this.ctx.session.refreshBaseSystemPrompt().catch(err => {
|
|
571
|
+
this.ctx.showError(`Failed to apply Mermaid rendering setting: ${err}`);
|
|
572
|
+
});
|
|
573
|
+
this.ctx.rebuildChatFromMessages();
|
|
574
|
+
this.ctx.ui.resetDisplay();
|
|
575
|
+
break;
|
|
576
|
+
|
|
577
|
+
case "theme": {
|
|
578
|
+
setTheme(value as string, true).then(result => {
|
|
579
|
+
this.ctx.statusLine.invalidate();
|
|
580
|
+
this.ctx.ui.requestRender();
|
|
581
|
+
this.ctx.ui.invalidate();
|
|
582
|
+
if (!result.success) {
|
|
583
|
+
this.ctx.showError(`Failed to load theme "${value}": ${result.error}\nFell back to dark theme.`);
|
|
584
|
+
}
|
|
585
|
+
});
|
|
586
|
+
break;
|
|
587
|
+
}
|
|
588
|
+
case "symbolPreset": {
|
|
589
|
+
setSymbolPreset(value as "unicode" | "nerd" | "ascii").then(() => {
|
|
590
|
+
this.ctx.statusLine.invalidate();
|
|
591
|
+
this.ctx.ui.requestRender();
|
|
592
|
+
this.ctx.ui.invalidate();
|
|
593
|
+
});
|
|
594
|
+
break;
|
|
595
|
+
}
|
|
596
|
+
case "colorBlindMode": {
|
|
597
|
+
setColorBlindMode(value === "true" || value === true).then(() => {
|
|
598
|
+
this.ctx.ui.invalidate();
|
|
599
|
+
});
|
|
600
|
+
break;
|
|
601
|
+
}
|
|
602
|
+
case "temperature": {
|
|
603
|
+
const temp = typeof value === "number" ? value : Number(value);
|
|
604
|
+
this.ctx.session.agent.temperature = temp >= 0 ? temp : undefined;
|
|
605
|
+
break;
|
|
606
|
+
}
|
|
607
|
+
case "topP": {
|
|
608
|
+
const topP = typeof value === "number" ? value : Number(value);
|
|
609
|
+
this.ctx.session.agent.topP = topP >= 0 ? topP : undefined;
|
|
610
|
+
break;
|
|
611
|
+
}
|
|
612
|
+
case "topK": {
|
|
613
|
+
const topK = typeof value === "number" ? value : Number(value);
|
|
614
|
+
this.ctx.session.agent.topK = topK >= 0 ? topK : undefined;
|
|
615
|
+
break;
|
|
616
|
+
}
|
|
617
|
+
case "minP": {
|
|
618
|
+
const minP = typeof value === "number" ? value : Number(value);
|
|
619
|
+
this.ctx.session.agent.minP = minP >= 0 ? minP : undefined;
|
|
620
|
+
break;
|
|
621
|
+
}
|
|
622
|
+
case "presencePenalty": {
|
|
623
|
+
const presencePenalty = typeof value === "number" ? value : Number(value);
|
|
624
|
+
this.ctx.session.agent.presencePenalty = presencePenalty >= 0 ? presencePenalty : undefined;
|
|
625
|
+
break;
|
|
626
|
+
}
|
|
627
|
+
case "repetitionPenalty": {
|
|
628
|
+
const repetitionPenalty = typeof value === "number" ? value : Number(value);
|
|
629
|
+
this.ctx.session.agent.repetitionPenalty = repetitionPenalty >= 0 ? repetitionPenalty : undefined;
|
|
630
|
+
break;
|
|
631
|
+
}
|
|
632
|
+
case "git.enabled":
|
|
633
|
+
case "statusLinePreset":
|
|
634
|
+
case "statusLine.preset":
|
|
635
|
+
case "statusLineSeparator":
|
|
636
|
+
case "statusLine.separator":
|
|
637
|
+
case "statusLineShowHooks":
|
|
638
|
+
case "statusLine.showHookStatus":
|
|
639
|
+
case "statusLine.sessionAccent":
|
|
640
|
+
case "statusLine.transparent":
|
|
641
|
+
case "statusLine.compactThinkingLevel":
|
|
642
|
+
case "statusLineSegments":
|
|
643
|
+
case "statusLineModelThinking":
|
|
644
|
+
case "statusLinePathAbbreviate":
|
|
645
|
+
case "statusLinePathMaxLength":
|
|
646
|
+
case "statusLinePathStripWorkPrefix":
|
|
647
|
+
case "statusLineGitShowBranch":
|
|
648
|
+
case "statusLineGitShowStaged":
|
|
649
|
+
case "statusLineGitShowUnstaged":
|
|
650
|
+
case "statusLineGitShowUntracked":
|
|
651
|
+
case "statusLineTimeFormat":
|
|
652
|
+
case "statusLineTimeShowSeconds": {
|
|
653
|
+
const statusLineSettings = {
|
|
654
|
+
preset: settings.get("statusLine.preset"),
|
|
655
|
+
leftSegments: settings.get("statusLine.leftSegments"),
|
|
656
|
+
rightSegments: settings.get("statusLine.rightSegments"),
|
|
657
|
+
separator: settings.get("statusLine.separator"),
|
|
658
|
+
showHookStatus: settings.get("statusLine.showHookStatus"),
|
|
659
|
+
sessionAccent: settings.get("statusLine.sessionAccent"),
|
|
660
|
+
transparent: settings.get("statusLine.transparent"),
|
|
661
|
+
segmentOptions: settings.get("statusLine.segmentOptions"),
|
|
662
|
+
compactThinkingLevel: settings.get("statusLine.compactThinkingLevel"),
|
|
663
|
+
};
|
|
664
|
+
this.ctx.statusLine.updateSettings(statusLineSettings);
|
|
665
|
+
this.ctx.ui.requestRender();
|
|
666
|
+
break;
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
// Provider settings - update runtime preferences
|
|
670
|
+
case "providers.webSearchOrder":
|
|
671
|
+
if (Array.isArray(value)) {
|
|
672
|
+
setSearchProviderOrder(value.filter(isSearchProviderId));
|
|
673
|
+
}
|
|
674
|
+
break;
|
|
675
|
+
case "providers.webSearchExclude":
|
|
676
|
+
if (Array.isArray(value)) {
|
|
677
|
+
setExcludedSearchProviders(value.filter(isSearchProviderId));
|
|
678
|
+
}
|
|
679
|
+
break;
|
|
680
|
+
case "providers.imageOrder":
|
|
681
|
+
if (Array.isArray(value)) {
|
|
682
|
+
setImageProviderOrder(value.filter((entry): entry is string => typeof entry === "string"));
|
|
683
|
+
}
|
|
684
|
+
break;
|
|
685
|
+
|
|
686
|
+
// MCP update injection - live subscribe/unsubscribe
|
|
687
|
+
case "mcp.notifications":
|
|
688
|
+
this.ctx.mcpManager?.setNotificationsEnabled(value as boolean);
|
|
689
|
+
break;
|
|
690
|
+
|
|
691
|
+
// All other settings are handled by the definitions (get/set on SettingsManager)
|
|
692
|
+
// No additional side effects needed
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
showModelSelector(options?: { temporaryOnly?: boolean }): void {
|
|
697
|
+
if (options?.temporaryOnly) {
|
|
698
|
+
this.#showModelPicker();
|
|
699
|
+
return;
|
|
700
|
+
}
|
|
701
|
+
this.#showModelHub({});
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
/**
|
|
705
|
+
* Compact session-only model picker (alt+p / `/switch`): a floating
|
|
706
|
+
* bottom-anchored overlay over the transcript. The current model is
|
|
707
|
+
* highlighted and preselected; a leading `@` searches ctrl+p quick roles.
|
|
708
|
+
*/
|
|
709
|
+
#showModelPicker(): void {
|
|
710
|
+
const currentContextTokens = this.ctx.session.getContextUsage()?.tokens ?? 0;
|
|
711
|
+
const current = this.ctx.session.model;
|
|
712
|
+
const quickRoleOrder = this.ctx.settings.get("cycleOrder");
|
|
713
|
+
const quickRoleCycle = this.ctx.session.getRoleModelCycle(quickRoleOrder);
|
|
714
|
+
let overlayHandle: OverlayHandle | undefined;
|
|
715
|
+
let closed = false;
|
|
716
|
+
const done = () => {
|
|
717
|
+
if (closed) return;
|
|
718
|
+
closed = true;
|
|
719
|
+
overlayHandle?.hide();
|
|
720
|
+
this.focusActiveEditorArea();
|
|
721
|
+
this.ctx.ui.requestRender();
|
|
722
|
+
};
|
|
723
|
+
const picker = new ModelPickerComponent(
|
|
724
|
+
this.ctx.ui,
|
|
725
|
+
this.ctx.settings,
|
|
726
|
+
this.ctx.session.modelRegistry,
|
|
727
|
+
this.ctx.session.scopedModels,
|
|
728
|
+
{
|
|
729
|
+
onPick: async (model, selector, { overContext }) => {
|
|
730
|
+
// Session-only: update agent state but don't persist the model to settings.
|
|
731
|
+
const applySessionModel = async () => {
|
|
732
|
+
const roleThinkingLevel = this.ctx.session.resolveTemporaryModelThinkingLevel(model);
|
|
733
|
+
await this.ctx.session.setModelTemporary(model, roleThinkingLevel);
|
|
734
|
+
this.ctx.statusLine.invalidate();
|
|
735
|
+
this.ctx.updateEditorBorderColor();
|
|
736
|
+
const roleSelectorHint = this.ctx.keybindings.getKeys("app.model.select")[0] ?? "Alt+M";
|
|
737
|
+
this.ctx.showStatus(`Session-only model: ${selector}. Use ${roleSelectorHint} or /model for roles.`);
|
|
738
|
+
};
|
|
739
|
+
try {
|
|
740
|
+
if (overContext) {
|
|
741
|
+
// Over-context pick: close the picker so the compaction loader is
|
|
742
|
+
// visible, compact with the current model, then switch. The switch
|
|
743
|
+
// runs in the before-flush hook so any prompt queued during
|
|
744
|
+
// compaction executes on the target model, not the old one; the
|
|
745
|
+
// early "nothing to compact" return skips the hook, so the
|
|
746
|
+
// idempotent post-return call covers it. A cancelled or failed
|
|
747
|
+
// compaction keeps the current model — the target still cannot
|
|
748
|
+
// fit the transcript.
|
|
749
|
+
done();
|
|
750
|
+
let switched = false;
|
|
751
|
+
const switchAfterCompaction = async (outcome: CompactionOutcome) => {
|
|
752
|
+
if (switched || outcome !== "ok") return;
|
|
753
|
+
switched = true;
|
|
754
|
+
await applySessionModel();
|
|
755
|
+
};
|
|
756
|
+
const outcome = await this.ctx.handleCompactCommand(undefined, undefined, switchAfterCompaction);
|
|
757
|
+
await switchAfterCompaction(outcome);
|
|
758
|
+
return;
|
|
759
|
+
}
|
|
760
|
+
await applySessionModel();
|
|
761
|
+
done();
|
|
762
|
+
} catch (error) {
|
|
763
|
+
this.ctx.showError(error instanceof Error ? error.message : String(error));
|
|
764
|
+
}
|
|
765
|
+
},
|
|
766
|
+
onPickRole: async entry => {
|
|
767
|
+
try {
|
|
768
|
+
await this.ctx.session.applyRoleModel(entry);
|
|
769
|
+
this.ctx.statusLine.invalidate();
|
|
770
|
+
this.ctx.updateEditorBorderColor();
|
|
771
|
+
this.ctx.showModelCycleTrack(
|
|
772
|
+
renderSegmentTrack(
|
|
773
|
+
quickRoleOrder.map(role => ({ label: role })),
|
|
774
|
+
quickRoleOrder.indexOf(entry.role),
|
|
775
|
+
),
|
|
776
|
+
);
|
|
777
|
+
done();
|
|
778
|
+
} catch (error) {
|
|
779
|
+
this.ctx.showError(error instanceof Error ? error.message : String(error));
|
|
780
|
+
}
|
|
781
|
+
},
|
|
782
|
+
onCancel: done,
|
|
783
|
+
},
|
|
784
|
+
{
|
|
785
|
+
currentContextTokens,
|
|
786
|
+
currentSelector: current ? `${current.provider}/${current.id}` : undefined,
|
|
787
|
+
quickRoles: quickRoleCycle?.models,
|
|
788
|
+
quickRoleOrder,
|
|
789
|
+
currentQuickRole: quickRoleCycle?.models[quickRoleCycle.currentIndex]?.role,
|
|
790
|
+
},
|
|
791
|
+
);
|
|
792
|
+
overlayHandle = this.ctx.ui.showOverlay(picker, {
|
|
793
|
+
anchor: "bottom-center",
|
|
794
|
+
width: "100%",
|
|
795
|
+
maxHeight: "100%",
|
|
796
|
+
margin: 0,
|
|
797
|
+
});
|
|
798
|
+
this.ctx.ui.setFocus(picker);
|
|
799
|
+
this.ctx.ui.requestRender();
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
/**
|
|
803
|
+
* Fullscreen model hub on the alternate screen (the /settings idiom): the
|
|
804
|
+
* overlay enables mouse tracking for its lifetime and the transcript stays
|
|
805
|
+
* untouched underneath. `initialProviderId` preselects a provider's sidebar
|
|
806
|
+
* entry — used when reopening the hub after a /login round-trip.
|
|
807
|
+
*/
|
|
808
|
+
#showModelHub(hubOptions: { initialProviderId?: string }): void {
|
|
809
|
+
let overlayHandle: OverlayHandle | undefined;
|
|
810
|
+
let hub: ModelHubComponent | undefined;
|
|
811
|
+
let closed = false;
|
|
812
|
+
const done = () => {
|
|
813
|
+
// Re-entrant guard: cancel paths (Esc, login forward) may race;
|
|
814
|
+
// the overlay must hide exactly once.
|
|
815
|
+
if (closed) return;
|
|
816
|
+
closed = true;
|
|
817
|
+
hub?.dispose();
|
|
818
|
+
overlayHandle?.hide();
|
|
819
|
+
this.focusActiveEditorArea();
|
|
820
|
+
this.ctx.ui.requestRender();
|
|
821
|
+
};
|
|
822
|
+
hub = new ModelHubComponent(
|
|
823
|
+
this.ctx.ui,
|
|
824
|
+
this.ctx.settings,
|
|
825
|
+
this.ctx.session.modelRegistry,
|
|
826
|
+
this.ctx.session.scopedModels,
|
|
827
|
+
{
|
|
828
|
+
onAssign: async (model, role, thinkingLevel, selector, scope?: ModelRoleSelectionScope) => {
|
|
829
|
+
const releaseDefaultMutation = role === "default" ? await this.#acquireDefaultRoleMutation() : undefined;
|
|
830
|
+
const configuredStorage = this.ctx.settings.get("modelRoleStorage");
|
|
831
|
+
const targetScope = configuredStorage === "project" ? (scope ?? "project") : "global";
|
|
832
|
+
// `auto` is session-global: never baked into a per-role model value
|
|
833
|
+
// (it can't round-trip through `model:<level>`). Apply it to the session
|
|
834
|
+
// separately and persist via `defaultThinkingLevel`.
|
|
835
|
+
const isAuto = thinkingLevel === AUTO_THINKING;
|
|
836
|
+
const concreteThinking = isAuto || thinkingLevel === undefined ? undefined : thinkingLevel;
|
|
837
|
+
const selectorValue = selector ?? `${model.provider}/${model.id}`;
|
|
838
|
+
const scopeLabel =
|
|
839
|
+
configuredStorage === "project" ? `${targetScope === "project" ? "Project" : "Global"} ` : "";
|
|
840
|
+
const defaultStatusLabel = configuredStorage === "project" ? `${scopeLabel}default` : "Default";
|
|
841
|
+
try {
|
|
842
|
+
if (role === "default") {
|
|
843
|
+
const effectiveProvenance = this.ctx.settings.getModelRoleProvenance("default");
|
|
844
|
+
const shadowedGlobal =
|
|
845
|
+
configuredStorage === "project" &&
|
|
846
|
+
targetScope === "global" &&
|
|
847
|
+
(effectiveProvenance === "project" ||
|
|
848
|
+
effectiveProvenance === "overlay" ||
|
|
849
|
+
(effectiveProvenance === "runtime" &&
|
|
850
|
+
this.ctx.settings.isProjectModelRoleRuntimeOverrideActive("default")));
|
|
851
|
+
const shadowedProject =
|
|
852
|
+
configuredStorage === "project" &&
|
|
853
|
+
targetScope === "project" &&
|
|
854
|
+
effectiveProvenance === "overlay";
|
|
855
|
+
if (shadowedGlobal) {
|
|
856
|
+
this.ctx.settings.setModelRole(
|
|
857
|
+
"default",
|
|
858
|
+
formatModelSelectorValue(selectorValue, concreteThinking),
|
|
859
|
+
);
|
|
860
|
+
if (isAuto) {
|
|
861
|
+
this.ctx.settings.set("defaultThinkingLevel", AUTO_THINKING);
|
|
862
|
+
}
|
|
863
|
+
} else if (shadowedProject) {
|
|
864
|
+
this.ctx.settings.setProjectModelRole(
|
|
865
|
+
"default",
|
|
866
|
+
formatModelSelectorValue(selectorValue, concreteThinking),
|
|
867
|
+
);
|
|
868
|
+
if (isAuto) {
|
|
869
|
+
this.ctx.settings.set("defaultThinkingLevel", AUTO_THINKING);
|
|
870
|
+
}
|
|
871
|
+
} else {
|
|
872
|
+
const { switched } = await this.ctx.session.setModel(model, role, {
|
|
873
|
+
selector,
|
|
874
|
+
thinkingLevel: isAuto ? ThinkingLevel.Inherit : concreteThinking,
|
|
875
|
+
persist: targetScope === "global",
|
|
876
|
+
});
|
|
877
|
+
if (!switched) return;
|
|
878
|
+
if (targetScope === "project") {
|
|
879
|
+
this.ctx.settings.setProjectModelRole(
|
|
880
|
+
"default",
|
|
881
|
+
formatModelSelectorValue(selectorValue, concreteThinking),
|
|
882
|
+
);
|
|
883
|
+
}
|
|
884
|
+
if (isAuto) {
|
|
885
|
+
this.ctx.session.setThinkingLevel(AUTO_THINKING, true);
|
|
886
|
+
} else if (concreteThinking && concreteThinking !== ThinkingLevel.Inherit) {
|
|
887
|
+
this.ctx.session.setThinkingLevel(concreteThinking);
|
|
888
|
+
}
|
|
889
|
+
this.ctx.statusLine.invalidate();
|
|
890
|
+
this.ctx.updateEditorBorderColor();
|
|
891
|
+
}
|
|
892
|
+
this.ctx.showStatus(`${defaultStatusLabel} model: ${selector ?? model.id}`);
|
|
893
|
+
} else {
|
|
894
|
+
// Other roles (smol, slow, custom): update settings, not the current model.
|
|
895
|
+
const modelRoleValue = formatModelSelectorValue(selectorValue, concreteThinking);
|
|
896
|
+
if (targetScope === "project") {
|
|
897
|
+
this.ctx.settings.setProjectModelRole(role, modelRoleValue);
|
|
898
|
+
} else {
|
|
899
|
+
this.ctx.settings.setModelRole(role, modelRoleValue);
|
|
900
|
+
}
|
|
901
|
+
if (isAuto) {
|
|
902
|
+
this.ctx.session.setThinkingLevel(AUTO_THINKING, true);
|
|
903
|
+
}
|
|
904
|
+
const roleInfo = getRoleInfo(role, settings);
|
|
905
|
+
this.ctx.showStatus(
|
|
906
|
+
`${scopeLabel}${roleInfo?.tag ?? roleInfo?.name ?? role} model: ${selector ?? model.id}`,
|
|
907
|
+
);
|
|
908
|
+
}
|
|
909
|
+
} catch (error) {
|
|
910
|
+
this.ctx.showError(error instanceof Error ? error.message : String(error));
|
|
911
|
+
} finally {
|
|
912
|
+
releaseDefaultMutation?.();
|
|
913
|
+
hub?.refreshAfterExternalMutation();
|
|
914
|
+
}
|
|
915
|
+
},
|
|
916
|
+
onUnassign: async (role, scope?: ModelRoleSelectionScope) => {
|
|
917
|
+
const releaseDefaultMutation = role === "default" ? await this.#acquireDefaultRoleMutation() : undefined;
|
|
918
|
+
const configuredStorage = this.ctx.settings.get("modelRoleStorage");
|
|
919
|
+
const targetScope = configuredStorage === "project" ? (scope ?? "project") : "global";
|
|
920
|
+
const scopeLabel =
|
|
921
|
+
configuredStorage === "project" ? `${targetScope === "project" ? "Project" : "Global"} ` : "";
|
|
922
|
+
try {
|
|
923
|
+
const previousEffectiveRoleValue =
|
|
924
|
+
role === "default" ? this.ctx.settings.getModelRole("default") : undefined;
|
|
925
|
+
if (targetScope === "project") {
|
|
926
|
+
this.ctx.settings.clearProjectModelRole(role);
|
|
927
|
+
} else {
|
|
928
|
+
this.ctx.settings.setModelRole(role, undefined);
|
|
929
|
+
}
|
|
930
|
+
const roleInfo = getRoleInfo(role, settings);
|
|
931
|
+
this.ctx.showStatus(
|
|
932
|
+
`${scopeLabel}${roleInfo?.tag ?? roleInfo?.name ?? role} role cleared — auto-selection applies`,
|
|
933
|
+
);
|
|
934
|
+
// Clearing either persisted scope can also remove a captured
|
|
935
|
+
// runtime override. When that changes the effective default,
|
|
936
|
+
// resolve the newly exposed persisted layer and switch the live
|
|
937
|
+
// session without writing it back to global settings. Overlay
|
|
938
|
+
// and runtime provenance remain authoritative and session-neutral.
|
|
939
|
+
if (role === "default") {
|
|
940
|
+
const fallbackRoleValue = this.ctx.settings.getModelRole("default");
|
|
941
|
+
const fallbackProvenance = this.ctx.settings.getModelRoleProvenance("default");
|
|
942
|
+
const exposesPersistedFallback =
|
|
943
|
+
fallbackProvenance === "project" || fallbackProvenance === "global";
|
|
944
|
+
if (
|
|
945
|
+
fallbackRoleValue &&
|
|
946
|
+
fallbackRoleValue !== previousEffectiveRoleValue &&
|
|
947
|
+
exposesPersistedFallback
|
|
948
|
+
) {
|
|
949
|
+
const scopedModels = this.ctx.session.scopedModels.map(sm => sm.model);
|
|
950
|
+
const availableModels =
|
|
951
|
+
scopedModels.length > 0 ? scopedModels : this.ctx.session.getAvailableModels();
|
|
952
|
+
const resolved = resolveModelRoleValue(fallbackRoleValue, availableModels, {
|
|
953
|
+
settings: this.ctx.settings,
|
|
954
|
+
});
|
|
955
|
+
if (resolved.model) {
|
|
956
|
+
const fallbackModel = resolved.model;
|
|
957
|
+
const isAuto = resolved.thinkingLevel === AUTO_THINKING;
|
|
958
|
+
let concreteThinking = concreteThinkingLevel(resolved.thinkingLevel);
|
|
959
|
+
let isAutoFromDefault = false;
|
|
960
|
+
if (!resolved.explicitThinkingLevel && !concreteThinking) {
|
|
961
|
+
const defaultLevel = parseConfiguredThinkingLevel(
|
|
962
|
+
this.ctx.settings.get("defaultThinkingLevel"),
|
|
963
|
+
);
|
|
964
|
+
if (defaultLevel === AUTO_THINKING) {
|
|
965
|
+
isAutoFromDefault = true;
|
|
966
|
+
} else if (defaultLevel) {
|
|
967
|
+
concreteThinking = defaultLevel;
|
|
968
|
+
}
|
|
969
|
+
}
|
|
970
|
+
const effectiveIsAuto = isAuto || isAutoFromDefault;
|
|
971
|
+
const { switched } = await this.ctx.session.setModel(fallbackModel, "default", {
|
|
972
|
+
persist: false,
|
|
973
|
+
thinkingLevel: effectiveIsAuto
|
|
974
|
+
? ThinkingLevel.Inherit
|
|
975
|
+
: (concreteThinking ?? ThinkingLevel.Inherit),
|
|
976
|
+
});
|
|
977
|
+
if (!switched) return;
|
|
978
|
+
if (effectiveIsAuto) {
|
|
979
|
+
this.ctx.session.setThinkingLevel(AUTO_THINKING, true);
|
|
980
|
+
} else if (concreteThinking && concreteThinking !== ThinkingLevel.Inherit) {
|
|
981
|
+
this.ctx.session.setThinkingLevel(concreteThinking);
|
|
982
|
+
}
|
|
983
|
+
this.ctx.statusLine.invalidate();
|
|
984
|
+
this.ctx.updateEditorBorderColor();
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
}
|
|
988
|
+
} catch (error) {
|
|
989
|
+
this.ctx.showError(error instanceof Error ? error.message : String(error));
|
|
990
|
+
} finally {
|
|
991
|
+
releaseDefaultMutation?.();
|
|
992
|
+
hub?.refreshAfterExternalMutation();
|
|
993
|
+
}
|
|
994
|
+
},
|
|
995
|
+
onFallbackChainChange: (role, chain) => {
|
|
996
|
+
try {
|
|
997
|
+
const chains = { ...this.ctx.settings.get("retry.fallbackChains") };
|
|
998
|
+
if (chain.length === 0) {
|
|
999
|
+
delete chains[role];
|
|
1000
|
+
} else {
|
|
1001
|
+
chains[role] = chain;
|
|
1002
|
+
}
|
|
1003
|
+
this.ctx.settings.set("retry.fallbackChains", chains);
|
|
1004
|
+
const roleInfo = getRoleInfo(role, settings);
|
|
1005
|
+
this.ctx.showStatus(
|
|
1006
|
+
chain.length > 0
|
|
1007
|
+
? `${roleInfo?.tag ?? roleInfo?.name ?? role} fallbacks: ${chain.join(" → ")}`
|
|
1008
|
+
: `${roleInfo?.tag ?? roleInfo?.name ?? role} fallbacks cleared`,
|
|
1009
|
+
);
|
|
1010
|
+
} catch (error) {
|
|
1011
|
+
this.ctx.showError(error instanceof Error ? error.message : String(error));
|
|
1012
|
+
}
|
|
1013
|
+
},
|
|
1014
|
+
|
|
1015
|
+
onLoginRequest: providerId => {
|
|
1016
|
+
done();
|
|
1017
|
+
void this.#loginThenReopenModelHub(providerId);
|
|
1018
|
+
},
|
|
1019
|
+
onCycleOrderChange: order => {
|
|
1020
|
+
try {
|
|
1021
|
+
this.ctx.settings.set("cycleOrder", order);
|
|
1022
|
+
this.ctx.showStatus(
|
|
1023
|
+
order.length > 0 ? `Quick-switch cycle: ${order.join(" → ")}` : "Quick-switch cycle cleared",
|
|
1024
|
+
);
|
|
1025
|
+
} catch (error) {
|
|
1026
|
+
this.ctx.showError(error instanceof Error ? error.message : String(error));
|
|
1027
|
+
}
|
|
1028
|
+
},
|
|
1029
|
+
onCancel: () => done(),
|
|
1030
|
+
},
|
|
1031
|
+
{
|
|
1032
|
+
initialProviderId: hubOptions.initialProviderId,
|
|
1033
|
+
},
|
|
1034
|
+
);
|
|
1035
|
+
overlayHandle = this.#showFullscreenMenu(hub);
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
/** /login round-trip for a locked provider; reopen the hub on that provider only after a successful login. */
|
|
1039
|
+
async #loginThenReopenModelHub(providerId: string): Promise<void> {
|
|
1040
|
+
const succeeded = await this.#handleOAuthLogin(providerId);
|
|
1041
|
+
if (succeeded) {
|
|
1042
|
+
this.#showModelHub({ initialProviderId: providerId });
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
async showPluginSelector(mode: "install" | "uninstall" = "install"): Promise<void> {
|
|
1047
|
+
const mgr = new MarketplaceManager({
|
|
1048
|
+
marketplacesRegistryPath: getMarketplacesRegistryPath(),
|
|
1049
|
+
installedRegistryPath: getInstalledPluginsRegistryPath(),
|
|
1050
|
+
projectInstalledRegistryPath: (await resolveActiveProjectRegistryPath(getProjectDir())) ?? undefined,
|
|
1051
|
+
marketplacesCacheDir: getMarketplacesCacheDir(),
|
|
1052
|
+
pluginsCacheDir: getPluginsCacheDir(),
|
|
1053
|
+
clearPluginRootsCache: clearPluginRootsAndCaches,
|
|
1054
|
+
});
|
|
1055
|
+
|
|
1056
|
+
const [marketplaces, installed] = await Promise.all([mgr.listMarketplaces(), mgr.listInstalledPlugins()]);
|
|
1057
|
+
const installedIds = new Set(installed.map(p => p.id));
|
|
1058
|
+
|
|
1059
|
+
if (mode === "uninstall") {
|
|
1060
|
+
// Show only installed plugins for uninstall
|
|
1061
|
+
const items = installed.map(p => {
|
|
1062
|
+
const entry = p.entries[0];
|
|
1063
|
+
const atIdx = p.id.lastIndexOf("@");
|
|
1064
|
+
const pluginName = atIdx > 0 ? p.id.slice(0, atIdx) : p.id;
|
|
1065
|
+
const mkt = atIdx > 0 ? p.id.slice(atIdx + 1) : "unknown";
|
|
1066
|
+
return {
|
|
1067
|
+
plugin: { name: pluginName, version: entry?.version, description: undefined as string | undefined },
|
|
1068
|
+
marketplace: mkt,
|
|
1069
|
+
scope: p.scope,
|
|
1070
|
+
};
|
|
1071
|
+
});
|
|
1072
|
+
this.showSelector(done => {
|
|
1073
|
+
const selector = new PluginSelectorComponent(marketplaces.length, items, new Set(), {
|
|
1074
|
+
onSelect: async (name, marketplace, scope) => {
|
|
1075
|
+
done();
|
|
1076
|
+
const pluginId = `${name}@${marketplace}`;
|
|
1077
|
+
this.ctx.showStatus(`Uninstalling ${pluginId}...`);
|
|
1078
|
+
this.ctx.ui.requestRender();
|
|
1079
|
+
try {
|
|
1080
|
+
await mgr.uninstallPlugin(pluginId, scope);
|
|
1081
|
+
this.ctx.showStatus(`Uninstalled ${pluginId}`);
|
|
1082
|
+
} catch (err) {
|
|
1083
|
+
this.ctx.showStatus(`Uninstall failed: ${err}`);
|
|
1084
|
+
}
|
|
1085
|
+
this.ctx.ui.requestRender();
|
|
1086
|
+
},
|
|
1087
|
+
onCancel: () => {
|
|
1088
|
+
done();
|
|
1089
|
+
this.ctx.ui.requestRender();
|
|
1090
|
+
},
|
|
1091
|
+
});
|
|
1092
|
+
return { component: selector, focus: selector.getSelectList() };
|
|
1093
|
+
});
|
|
1094
|
+
return;
|
|
1095
|
+
}
|
|
1096
|
+
|
|
1097
|
+
// Install mode: show all available plugins from all marketplaces
|
|
1098
|
+
const allPlugins: Array<{
|
|
1099
|
+
plugin: { name: string; version?: string; description?: string };
|
|
1100
|
+
marketplace: string;
|
|
1101
|
+
}> = [];
|
|
1102
|
+
for (const mkt of marketplaces) {
|
|
1103
|
+
const plugins = await mgr.listAvailablePlugins(mkt.name);
|
|
1104
|
+
for (const plugin of plugins) {
|
|
1105
|
+
allPlugins.push({ plugin, marketplace: mkt.name });
|
|
1106
|
+
}
|
|
1107
|
+
}
|
|
1108
|
+
|
|
1109
|
+
this.showSelector(done => {
|
|
1110
|
+
const selector = new PluginSelectorComponent(marketplaces.length, allPlugins, installedIds, {
|
|
1111
|
+
onSelect: async (name, marketplace) => {
|
|
1112
|
+
done();
|
|
1113
|
+
this.ctx.showStatus(`Installing ${name} from ${marketplace}...`);
|
|
1114
|
+
this.ctx.ui.requestRender();
|
|
1115
|
+
try {
|
|
1116
|
+
const force = installedIds.has(`${name}@${marketplace}`);
|
|
1117
|
+
await mgr.installPlugin(name, marketplace, { force });
|
|
1118
|
+
this.ctx.showStatus(`Installed ${name} from ${marketplace}`);
|
|
1119
|
+
} catch (err) {
|
|
1120
|
+
this.ctx.showStatus(`Install failed: ${err}`);
|
|
1121
|
+
}
|
|
1122
|
+
this.ctx.ui.requestRender();
|
|
1123
|
+
},
|
|
1124
|
+
onCancel: () => {
|
|
1125
|
+
done();
|
|
1126
|
+
this.ctx.ui.requestRender();
|
|
1127
|
+
},
|
|
1128
|
+
});
|
|
1129
|
+
return { component: selector, focus: selector.getSelectList() };
|
|
1130
|
+
});
|
|
1131
|
+
}
|
|
1132
|
+
|
|
1133
|
+
showUserMessageSelector(): void {
|
|
1134
|
+
const userMessages = this.ctx.session.getUserMessagesForBranching();
|
|
1135
|
+
|
|
1136
|
+
if (userMessages.length === 0) {
|
|
1137
|
+
this.ctx.showStatus("No messages to branch from");
|
|
1138
|
+
return;
|
|
1139
|
+
}
|
|
1140
|
+
|
|
1141
|
+
this.showSelector(done => {
|
|
1142
|
+
const selector = new UserMessageSelectorComponent(
|
|
1143
|
+
userMessages.map(m => ({ id: m.entryId, text: m.text })),
|
|
1144
|
+
async entryId => {
|
|
1145
|
+
const result = await this.ctx.session.branch(entryId);
|
|
1146
|
+
if (result.cancelled) {
|
|
1147
|
+
// Hook cancelled the branch
|
|
1148
|
+
done();
|
|
1149
|
+
this.ctx.ui.requestRender();
|
|
1150
|
+
return;
|
|
1151
|
+
}
|
|
1152
|
+
|
|
1153
|
+
this.ctx.renderInitialMessages({ clearTerminalHistory: true });
|
|
1154
|
+
this.ctx.editor.setDraft(result.selectedText, result.selectedImages);
|
|
1155
|
+
done();
|
|
1156
|
+
this.ctx.showStatus("Branched to new session");
|
|
1157
|
+
},
|
|
1158
|
+
() => {
|
|
1159
|
+
done();
|
|
1160
|
+
this.ctx.ui.requestRender();
|
|
1161
|
+
},
|
|
1162
|
+
);
|
|
1163
|
+
return { component: selector, focus: selector.getMessageList() };
|
|
1164
|
+
});
|
|
1165
|
+
}
|
|
1166
|
+
|
|
1167
|
+
showCopySelector(): void {
|
|
1168
|
+
const targets = buildCopyTargets(this.ctx.session);
|
|
1169
|
+
if (targets.length === 0) {
|
|
1170
|
+
this.ctx.showStatus("Nothing to copy yet.");
|
|
1171
|
+
return;
|
|
1172
|
+
}
|
|
1173
|
+
|
|
1174
|
+
let overlayHandle: OverlayHandle | undefined;
|
|
1175
|
+
const done = () => {
|
|
1176
|
+
overlayHandle?.hide();
|
|
1177
|
+
this.ctx.ui.requestRender();
|
|
1178
|
+
};
|
|
1179
|
+
const selector = new CopySelectorComponent(targets, {
|
|
1180
|
+
onPick: target => {
|
|
1181
|
+
done();
|
|
1182
|
+
if (target.content === undefined) return;
|
|
1183
|
+
void copyToClipboard(target.content);
|
|
1184
|
+
this.ctx.showStatus(target.copyMessage ?? "Copied to clipboard");
|
|
1185
|
+
},
|
|
1186
|
+
onCancel: done,
|
|
1187
|
+
});
|
|
1188
|
+
|
|
1189
|
+
overlayHandle = this.ctx.ui.showOverlay(selector, {
|
|
1190
|
+
anchor: "bottom-center",
|
|
1191
|
+
width: "100%",
|
|
1192
|
+
maxHeight: "100%",
|
|
1193
|
+
margin: 0,
|
|
1194
|
+
});
|
|
1195
|
+
this.ctx.ui.setFocus(selector);
|
|
1196
|
+
this.ctx.ui.requestRender();
|
|
1197
|
+
}
|
|
1198
|
+
|
|
1199
|
+
showTreeSelector(): void {
|
|
1200
|
+
const tree = this.ctx.sessionManager.getTree();
|
|
1201
|
+
const realLeafId = this.ctx.sessionManager.getLeafId();
|
|
1202
|
+
|
|
1203
|
+
if (tree.length === 0) {
|
|
1204
|
+
this.ctx.showStatus("No entries in session");
|
|
1205
|
+
return;
|
|
1206
|
+
}
|
|
1207
|
+
|
|
1208
|
+
this.showSelector(done => {
|
|
1209
|
+
const selector = new TreeSelectorComponent(
|
|
1210
|
+
tree,
|
|
1211
|
+
realLeafId,
|
|
1212
|
+
this.ctx.ui.terminal.rows,
|
|
1213
|
+
async (entryId, options) => {
|
|
1214
|
+
// Selecting the current leaf is normally a no-op (already there) —
|
|
1215
|
+
// unless it's an `ask` toolResult, in which case the re-answer flow
|
|
1216
|
+
// must still be allowed to reopen the picker even though the leaf
|
|
1217
|
+
// doesn't move (chatgpt-codex review on #5895).
|
|
1218
|
+
if (entryId === realLeafId) {
|
|
1219
|
+
const currentEntry = this.ctx.sessionManager.getEntry(entryId);
|
|
1220
|
+
const currentIsAskResult =
|
|
1221
|
+
currentEntry?.type === "message" &&
|
|
1222
|
+
currentEntry.message.role === "toolResult" &&
|
|
1223
|
+
currentEntry.message.toolName === "ask";
|
|
1224
|
+
if (!currentIsAskResult) {
|
|
1225
|
+
done();
|
|
1226
|
+
this.ctx.showStatus("Already at this point");
|
|
1227
|
+
return;
|
|
1228
|
+
}
|
|
1229
|
+
}
|
|
1230
|
+
|
|
1231
|
+
// Ask about summarization
|
|
1232
|
+
done(); // Close selector first
|
|
1233
|
+
|
|
1234
|
+
// Loop until user makes a complete choice or cancels to tree.
|
|
1235
|
+
// Shift+Enter in the tree selector pre-answers "Summarize" and
|
|
1236
|
+
// skips the prompt entirely.
|
|
1237
|
+
let wantsSummary = options.summarize;
|
|
1238
|
+
let customInstructions: string | undefined;
|
|
1239
|
+
|
|
1240
|
+
const branchSummariesEnabled = settings.get("branchSummary.enabled");
|
|
1241
|
+
|
|
1242
|
+
while (!wantsSummary && branchSummariesEnabled) {
|
|
1243
|
+
const summaryChoice = await this.ctx.showHookSelector("Summarize branch?", [
|
|
1244
|
+
"No summary",
|
|
1245
|
+
"Summarize",
|
|
1246
|
+
"Summarize with custom prompt",
|
|
1247
|
+
]);
|
|
1248
|
+
|
|
1249
|
+
if (summaryChoice === undefined) {
|
|
1250
|
+
// User pressed escape - re-show tree selector
|
|
1251
|
+
this.showTreeSelector();
|
|
1252
|
+
return;
|
|
1253
|
+
}
|
|
1254
|
+
|
|
1255
|
+
wantsSummary = summaryChoice !== "No summary";
|
|
1256
|
+
|
|
1257
|
+
if (summaryChoice === "Summarize with custom prompt") {
|
|
1258
|
+
customInstructions = await this.ctx.showHookEditor("Custom summarization instructions");
|
|
1259
|
+
if (customInstructions === undefined) {
|
|
1260
|
+
// User cancelled - loop back to summary selector
|
|
1261
|
+
continue;
|
|
1262
|
+
}
|
|
1263
|
+
}
|
|
1264
|
+
|
|
1265
|
+
// User made a complete choice
|
|
1266
|
+
break;
|
|
1267
|
+
}
|
|
1268
|
+
|
|
1269
|
+
// Set up escape handler and loader if summarizing
|
|
1270
|
+
let summaryLoader: Loader | undefined;
|
|
1271
|
+
const originalOnEscape = this.ctx.editor.onEscape;
|
|
1272
|
+
|
|
1273
|
+
if (wantsSummary) {
|
|
1274
|
+
this.ctx.editor.onEscape = () => {
|
|
1275
|
+
this.ctx.session.abortBranchSummary();
|
|
1276
|
+
};
|
|
1277
|
+
this.ctx.chatContainer.addChild(new Spacer(1));
|
|
1278
|
+
summaryLoader = new Loader(
|
|
1279
|
+
this.ctx.ui,
|
|
1280
|
+
spinner => theme.fg("accent", spinner),
|
|
1281
|
+
text => theme.fg("muted", text),
|
|
1282
|
+
"Summarizing branch... (esc to cancel)",
|
|
1283
|
+
getSymbolTheme().spinnerFrames,
|
|
1284
|
+
);
|
|
1285
|
+
this.ctx.statusContainer.addChild(summaryLoader);
|
|
1286
|
+
this.ctx.ui.requestRender();
|
|
1287
|
+
}
|
|
1288
|
+
|
|
1289
|
+
try {
|
|
1290
|
+
let result = await this.ctx.session.navigateTree(entryId, {
|
|
1291
|
+
summarize: wantsSummary,
|
|
1292
|
+
customInstructions,
|
|
1293
|
+
allowAskReopen: true,
|
|
1294
|
+
});
|
|
1295
|
+
|
|
1296
|
+
// Selecting an `ask` toolResult doesn't land the leaf directly —
|
|
1297
|
+
// re-open the picker with the original questions first, then
|
|
1298
|
+
// complete the navigation as a new sibling branch (issue #5642).
|
|
1299
|
+
if (result.reopenAsk) {
|
|
1300
|
+
const reanswer = await this.#reanswerAsk(result.reopenAsk.questions);
|
|
1301
|
+
if (!reanswer) {
|
|
1302
|
+
this.ctx.showStatus("Re-answer cancelled");
|
|
1303
|
+
return;
|
|
1304
|
+
}
|
|
1305
|
+
result = await this.ctx.session.navigateTree(entryId, {
|
|
1306
|
+
summarize: wantsSummary,
|
|
1307
|
+
customInstructions,
|
|
1308
|
+
allowAskReopen: true,
|
|
1309
|
+
reanswerAskResult: reanswer,
|
|
1310
|
+
});
|
|
1311
|
+
}
|
|
1312
|
+
|
|
1313
|
+
if (result.aborted) {
|
|
1314
|
+
// Summarization aborted - re-show tree selector
|
|
1315
|
+
this.ctx.showStatus("Branch summarization cancelled");
|
|
1316
|
+
this.showTreeSelector();
|
|
1317
|
+
return;
|
|
1318
|
+
}
|
|
1319
|
+
if (result.cancelled) {
|
|
1320
|
+
this.ctx.showStatus("Navigation cancelled");
|
|
1321
|
+
return;
|
|
1322
|
+
}
|
|
1323
|
+
|
|
1324
|
+
// Update UI — rebuild the display transcript for the new leaf (the
|
|
1325
|
+
// context from navigateTree is the LLM context, not the transcript).
|
|
1326
|
+
this.ctx.renderInitialMessages({ clearTerminalHistory: true });
|
|
1327
|
+
await this.ctx.reloadTodos();
|
|
1328
|
+
if (result.editorText && !this.ctx.editor.getText().trim()) {
|
|
1329
|
+
this.ctx.editor.setDraft(result.editorText, result.editorImages);
|
|
1330
|
+
}
|
|
1331
|
+
this.ctx.showStatus("Navigated to selected point");
|
|
1332
|
+
|
|
1333
|
+
// Re-answering a past `ask` commits a new sibling answer but,
|
|
1334
|
+
// unlike a live `ask`, leaves the agent idle. Resume it now —
|
|
1335
|
+
// after the transcript rebuild above — so the model consumes the
|
|
1336
|
+
// new answer without the resumed turn rendering against the stale
|
|
1337
|
+
// pre-rebuild UI (issue #6483).
|
|
1338
|
+
if (result.askReanswerCommitted) {
|
|
1339
|
+
this.ctx.session.resumeAfterAskReanswer();
|
|
1340
|
+
}
|
|
1341
|
+
} catch (error) {
|
|
1342
|
+
this.ctx.showError(error instanceof Error ? error.message : String(error));
|
|
1343
|
+
} finally {
|
|
1344
|
+
if (summaryLoader) {
|
|
1345
|
+
summaryLoader.stop();
|
|
1346
|
+
this.ctx.statusContainer.disposeChildren();
|
|
1347
|
+
}
|
|
1348
|
+
this.ctx.editor.onEscape = originalOnEscape;
|
|
1349
|
+
}
|
|
1350
|
+
},
|
|
1351
|
+
() => {
|
|
1352
|
+
done();
|
|
1353
|
+
this.ctx.ui.requestRender();
|
|
1354
|
+
},
|
|
1355
|
+
(entryId, label) => {
|
|
1356
|
+
this.ctx.sessionManager.appendLabelChange(entryId, label);
|
|
1357
|
+
this.ctx.ui.requestRender();
|
|
1358
|
+
},
|
|
1359
|
+
settings.get("treeFilterMode"),
|
|
1360
|
+
);
|
|
1361
|
+
return { component: selector, focus: selector };
|
|
1362
|
+
});
|
|
1363
|
+
}
|
|
1364
|
+
|
|
1365
|
+
/**
|
|
1366
|
+
* Re-open the `ask` picker with the original `questions` (issue #5642):
|
|
1367
|
+
* runs a standalone `AskTool.execute()` outside a normal agent turn,
|
|
1368
|
+
* reusing the same picker/dialog primitives a live `ask` tool call gets.
|
|
1369
|
+
* Returns `undefined` when the user cancels — mirrors `navigateTree`'s
|
|
1370
|
+
* cancellation contract instead of throwing.
|
|
1371
|
+
*/
|
|
1372
|
+
async #reanswerAsk(questions: AskToolInput["questions"]): Promise<AgentToolResult<AskToolDetails> | undefined> {
|
|
1373
|
+
const uiContext = this.ctx.getToolUIContext();
|
|
1374
|
+
if (!uiContext) {
|
|
1375
|
+
this.ctx.showError("Ask tool UI is not ready");
|
|
1376
|
+
return undefined;
|
|
1377
|
+
}
|
|
1378
|
+
const toolSession: ToolSession = {
|
|
1379
|
+
cwd: this.ctx.sessionManager.getCwd(),
|
|
1380
|
+
hasUI: true,
|
|
1381
|
+
settings: this.ctx.settings,
|
|
1382
|
+
getSessionFile: () => this.ctx.sessionManager.getSessionFile() ?? null,
|
|
1383
|
+
getSessionSpawns: () => null,
|
|
1384
|
+
getPlanModeState: () => this.ctx.session.getPlanModeState(),
|
|
1385
|
+
};
|
|
1386
|
+
const askTool = new AskTool(toolSession);
|
|
1387
|
+
const context = this.ctx.session.buildAskReanswerContext(uiContext);
|
|
1388
|
+
let result: AgentToolResult<AskToolDetails>;
|
|
1389
|
+
try {
|
|
1390
|
+
result = await askTool.execute("tree-reanswer", { questions }, undefined, undefined, context);
|
|
1391
|
+
} catch (error) {
|
|
1392
|
+
if (error instanceof ToolAbortError) return undefined;
|
|
1393
|
+
throw error;
|
|
1394
|
+
}
|
|
1395
|
+
// The rich ask dialog can race a collab guest choosing "Chat about this"
|
|
1396
|
+
// (`AskTool`'s `chatRedirect` result); that's meaningful inside a live
|
|
1397
|
+
// agent turn, where the model sees the redirect and starts a
|
|
1398
|
+
// conversation, but this standalone re-answer has no turn to hand it
|
|
1399
|
+
// to — completing the navigation with it would silently drop the
|
|
1400
|
+
// user's intent to chat (roboomp review on #5895).
|
|
1401
|
+
if (result.details?.chatRedirect) {
|
|
1402
|
+
this.ctx.showError(
|
|
1403
|
+
"Chat about this isn't available when re-answering from the tree — pick an option or type a custom answer instead.",
|
|
1404
|
+
);
|
|
1405
|
+
return undefined;
|
|
1406
|
+
}
|
|
1407
|
+
return result;
|
|
1408
|
+
}
|
|
1409
|
+
|
|
1410
|
+
async showSessionSelector(source?: ForeignSessionSource): Promise<void> {
|
|
1411
|
+
let sessions: SessionInfo[];
|
|
1412
|
+
let onSelectSession: (session: SessionInfo) => Promise<boolean>;
|
|
1413
|
+
let selectorOptions: SessionSelectorOptions;
|
|
1414
|
+
|
|
1415
|
+
if (source) {
|
|
1416
|
+
const sourceName = foreignSessionSourceName(source);
|
|
1417
|
+
const store = createForeignSessionStore(source);
|
|
1418
|
+
let foreignSessions: ForeignSessionInfo[];
|
|
1419
|
+
try {
|
|
1420
|
+
foreignSessions = await store.list();
|
|
1421
|
+
} catch (error) {
|
|
1422
|
+
this.ctx.showError(
|
|
1423
|
+
`Failed to list ${sourceName} sessions: ${error instanceof Error ? error.message : String(error)}`,
|
|
1424
|
+
);
|
|
1425
|
+
return;
|
|
1426
|
+
}
|
|
1427
|
+
if (foreignSessions.length === 0) {
|
|
1428
|
+
this.ctx.showWarning(`No ${sourceName} sessions found`);
|
|
1429
|
+
return;
|
|
1430
|
+
}
|
|
1431
|
+
const foreignByPath = new Map(foreignSessions.map(session => [session.path, session]));
|
|
1432
|
+
sessions = foreignSessions.map(foreignSessionInfoToSessionInfo);
|
|
1433
|
+
onSelectSession = async session => {
|
|
1434
|
+
try {
|
|
1435
|
+
await this.ctx.settings.flush();
|
|
1436
|
+
} catch (error) {
|
|
1437
|
+
this.ctx.showError(
|
|
1438
|
+
`Failed to save pending settings: ${error instanceof Error ? error.message : String(error)}`,
|
|
1439
|
+
);
|
|
1440
|
+
return false;
|
|
1441
|
+
}
|
|
1442
|
+
const foreignSession = foreignByPath.get(session.path);
|
|
1443
|
+
if (!foreignSession) throw new Error(`Selected ${sourceName} session is no longer available`);
|
|
1444
|
+
const imported = await persistForeignSession(store, foreignSession, {
|
|
1445
|
+
fallbackCwd: this.ctx.sessionManager.getCwd(),
|
|
1446
|
+
suppressBreadcrumb: true,
|
|
1447
|
+
});
|
|
1448
|
+
const sessionFile = imported.getSessionFile();
|
|
1449
|
+
if (!sessionFile) throw new Error(`Failed to persist ${sourceName} session`);
|
|
1450
|
+
await imported.close();
|
|
1451
|
+
return await this.handleResumeSession(sessionFile, { settingsFlushed: true });
|
|
1452
|
+
};
|
|
1453
|
+
selectorOptions = {
|
|
1454
|
+
title: `Import ${sourceName} Session`,
|
|
1455
|
+
scopeLabel: false,
|
|
1456
|
+
showCwd: true,
|
|
1457
|
+
};
|
|
1458
|
+
} else {
|
|
1459
|
+
sessions = await SessionManager.list(
|
|
1460
|
+
this.ctx.sessionManager.getCwd(),
|
|
1461
|
+
this.ctx.sessionManager.getSessionDir(),
|
|
1462
|
+
);
|
|
1463
|
+
const historyStorage = this.ctx.historyStorage;
|
|
1464
|
+
const historyMatcher = historyStorage
|
|
1465
|
+
? (query: string) => historyStorage.matchingSessionIds(query)
|
|
1466
|
+
: undefined;
|
|
1467
|
+
onSelectSession = session => this.handleResumeSession(session.path);
|
|
1468
|
+
selectorOptions = {
|
|
1469
|
+
onDelete: async (session: SessionInfo) => {
|
|
1470
|
+
if (!(await this.#detachActiveSessionBeforeDeletion(session.path))) {
|
|
1471
|
+
return false;
|
|
1472
|
+
}
|
|
1473
|
+
const storage = new FileSessionStorage();
|
|
1474
|
+
try {
|
|
1475
|
+
await storage.deleteSessionWithArtifacts(session.path);
|
|
1476
|
+
return true;
|
|
1477
|
+
} catch (error) {
|
|
1478
|
+
throw new Error(
|
|
1479
|
+
`Failed to delete session: ${error instanceof Error ? error.message : String(error)}`,
|
|
1480
|
+
{ cause: error },
|
|
1481
|
+
);
|
|
1482
|
+
}
|
|
1483
|
+
},
|
|
1484
|
+
historyMatcher,
|
|
1485
|
+
loadAllSessions: () => SessionManager.listAll(),
|
|
1486
|
+
};
|
|
1487
|
+
}
|
|
1488
|
+
|
|
1489
|
+
// Keep the fullscreen picker on the alternate buffer while a selected
|
|
1490
|
+
// session is loaded and its transcript is rebuilt.
|
|
1491
|
+
let overlayHandle: OverlayHandle | undefined;
|
|
1492
|
+
const done = () => {
|
|
1493
|
+
overlayHandle?.hide();
|
|
1494
|
+
this.focusActiveEditorArea();
|
|
1495
|
+
this.ctx.ui.requestRender();
|
|
1496
|
+
};
|
|
1497
|
+
const selector = new SessionSelectorComponent(
|
|
1498
|
+
sessions,
|
|
1499
|
+
async (session: SessionInfo) => {
|
|
1500
|
+
selector.lockInput();
|
|
1501
|
+
let keepOpen = false;
|
|
1502
|
+
try {
|
|
1503
|
+
const success = await onSelectSession(session);
|
|
1504
|
+
if (!success) {
|
|
1505
|
+
keepOpen = true;
|
|
1506
|
+
selector.unlockInput();
|
|
1507
|
+
this.ctx.ui.requestRender();
|
|
1508
|
+
}
|
|
1509
|
+
} catch (error) {
|
|
1510
|
+
this.ctx.showError(error instanceof Error ? error.message : String(error));
|
|
1511
|
+
} finally {
|
|
1512
|
+
if (!keepOpen) done();
|
|
1513
|
+
}
|
|
1514
|
+
},
|
|
1515
|
+
done,
|
|
1516
|
+
() => {
|
|
1517
|
+
// Release the alt buffer before teardown: shutdown() awaits flush/save/
|
|
1518
|
+
// dispose/drain before stop() leaves the alt screen.
|
|
1519
|
+
done();
|
|
1520
|
+
void this.ctx.shutdown();
|
|
1521
|
+
},
|
|
1522
|
+
{
|
|
1523
|
+
...selectorOptions,
|
|
1524
|
+
getTerminalRows: () => this.ctx.ui.terminal.rows,
|
|
1525
|
+
fillHeight: true,
|
|
1526
|
+
},
|
|
1527
|
+
);
|
|
1528
|
+
selector.setOnRequestRender(() => this.ctx.ui.requestRender());
|
|
1529
|
+
overlayHandle = this.ctx.ui.showOverlay(selector, {
|
|
1530
|
+
anchor: "top-left",
|
|
1531
|
+
width: "100%",
|
|
1532
|
+
maxHeight: "100%",
|
|
1533
|
+
margin: 0,
|
|
1534
|
+
fullscreen: true,
|
|
1535
|
+
});
|
|
1536
|
+
this.ctx.ui.setFocus(selector);
|
|
1537
|
+
this.ctx.ui.requestRender();
|
|
1538
|
+
}
|
|
1539
|
+
|
|
1540
|
+
#refreshSessionTerminalTitle(): void {
|
|
1541
|
+
const sessionManager = this.ctx.sessionManager as {
|
|
1542
|
+
getSessionName?: () => string | undefined;
|
|
1543
|
+
getCwd: () => string;
|
|
1544
|
+
titleSource?: "auto" | "user" | undefined;
|
|
1545
|
+
};
|
|
1546
|
+
setSessionTerminalTitle(sessionManager.getSessionName?.(), sessionManager.getCwd());
|
|
1547
|
+
}
|
|
1548
|
+
|
|
1549
|
+
async #detachActiveSessionBeforeDeletion(sessionPath: string): Promise<boolean> {
|
|
1550
|
+
const currentSessionFile = this.ctx.sessionManager.getSessionFile();
|
|
1551
|
+
if (currentSessionFile !== sessionPath) {
|
|
1552
|
+
return true;
|
|
1553
|
+
}
|
|
1554
|
+
|
|
1555
|
+
const detached = await this.ctx.session.newSession();
|
|
1556
|
+
if (!detached) {
|
|
1557
|
+
return false;
|
|
1558
|
+
}
|
|
1559
|
+
this.#refreshSessionTerminalTitle();
|
|
1560
|
+
|
|
1561
|
+
this.ctx.clearTransientSessionUi();
|
|
1562
|
+
this.ctx.statusLine.invalidate();
|
|
1563
|
+
this.ctx.statusLine.resetActiveTime();
|
|
1564
|
+
this.ctx.ui.requestRender();
|
|
1565
|
+
this.ctx.updateEditorBorderColor();
|
|
1566
|
+
this.ctx.renderInitialMessages({ clearTerminalHistory: true });
|
|
1567
|
+
await this.ctx.reloadTodos();
|
|
1568
|
+
this.ctx.ui.requestRender(true, { clearScrollback: true });
|
|
1569
|
+
return true;
|
|
1570
|
+
}
|
|
1571
|
+
|
|
1572
|
+
async handleResumeSession(sessionPath: string, options?: { settingsFlushed?: boolean }): Promise<boolean> {
|
|
1573
|
+
const previousCwd = this.ctx.sessionManager.getCwd();
|
|
1574
|
+
// Flush pending settings writes before switching sessions so a save
|
|
1575
|
+
// failure leaves the session, process project dir, and Settings in the
|
|
1576
|
+
// source scope — the switch below mutates the SessionManager cwd.
|
|
1577
|
+
if (!options?.settingsFlushed) {
|
|
1578
|
+
try {
|
|
1579
|
+
await this.ctx.settings.flush();
|
|
1580
|
+
} catch (err) {
|
|
1581
|
+
this.ctx.showError(`Failed to save pending settings: ${err instanceof Error ? err.message : String(err)}`);
|
|
1582
|
+
return false;
|
|
1583
|
+
}
|
|
1584
|
+
}
|
|
1585
|
+
// Switch session via AgentSession (emits hook and tool session events). The
|
|
1586
|
+
// SessionManager adopts the resumed session's own cwd when it differs.
|
|
1587
|
+
await this.ctx.session.switchSession(sessionPath);
|
|
1588
|
+
this.ctx.clearTransientSessionUi();
|
|
1589
|
+
const newCwd = this.ctx.sessionManager.getCwd();
|
|
1590
|
+
const movedProject = normalizePathForComparison(newCwd) !== normalizePathForComparison(previousCwd);
|
|
1591
|
+
if (movedProject) {
|
|
1592
|
+
// Resumed a session from another project: re-point the process and every
|
|
1593
|
+
// cwd-derived cache at it before rendering.
|
|
1594
|
+
await this.ctx.applyCwdChange(newCwd);
|
|
1595
|
+
}
|
|
1596
|
+
this.#refreshSessionTerminalTitle();
|
|
1597
|
+
this.ctx.updateEditorBorderColor();
|
|
1598
|
+
|
|
1599
|
+
// Clear and re-render the chat
|
|
1600
|
+
this.ctx.renderInitialMessages({ clearTerminalHistory: true });
|
|
1601
|
+
await this.ctx.reloadTodos();
|
|
1602
|
+
this.ctx.showStatus(movedProject ? `Resumed session in ${shortenPath(newCwd)}` : "Resumed session");
|
|
1603
|
+
return true;
|
|
1604
|
+
}
|
|
1605
|
+
|
|
1606
|
+
async handleSessionDeleteCommand(): Promise<void> {
|
|
1607
|
+
const sessionFile = this.ctx.sessionManager.getSessionFile();
|
|
1608
|
+
if (!sessionFile) {
|
|
1609
|
+
this.ctx.showError("No session file to delete (in-memory session)");
|
|
1610
|
+
return;
|
|
1611
|
+
}
|
|
1612
|
+
|
|
1613
|
+
// Check if session file exists (may not exist for brand new sessions)
|
|
1614
|
+
const storage = new FileSessionStorage();
|
|
1615
|
+
const fileExists = await storage.exists(sessionFile);
|
|
1616
|
+
if (!fileExists) {
|
|
1617
|
+
this.ctx.showError("Session has not been saved yet");
|
|
1618
|
+
return;
|
|
1619
|
+
}
|
|
1620
|
+
|
|
1621
|
+
const confirmed = await this.ctx.showHookConfirm(
|
|
1622
|
+
"Delete Session",
|
|
1623
|
+
"This will permanently delete the current session.\nYou will be returned to the session selector.",
|
|
1624
|
+
);
|
|
1625
|
+
|
|
1626
|
+
if (!confirmed) {
|
|
1627
|
+
this.ctx.showStatus("Delete cancelled");
|
|
1628
|
+
return;
|
|
1629
|
+
}
|
|
1630
|
+
|
|
1631
|
+
if (!(await this.#detachActiveSessionBeforeDeletion(sessionFile))) {
|
|
1632
|
+
this.ctx.showStatus("Delete cancelled");
|
|
1633
|
+
return;
|
|
1634
|
+
}
|
|
1635
|
+
|
|
1636
|
+
// Delete the session file and artifacts directory
|
|
1637
|
+
await storage.deleteSessionWithArtifacts(sessionFile);
|
|
1638
|
+
|
|
1639
|
+
// Show session selector
|
|
1640
|
+
this.ctx.showStatus("Session deleted");
|
|
1641
|
+
await this.showSessionSelector();
|
|
1642
|
+
}
|
|
1643
|
+
|
|
1644
|
+
/**
|
|
1645
|
+
* Run the OAuth login flow for `providerId` inside a cancellable
|
|
1646
|
+
* {@link LoginDialogComponent} that replaces the editor slot. Esc aborts:
|
|
1647
|
+
* the dialog's abort signal reaches the provider flow, any pending prompt
|
|
1648
|
+
* rejects, and the editor is restored immediately. Returns true when
|
|
1649
|
+
* credentials were stored.
|
|
1650
|
+
*/
|
|
1651
|
+
async #handleOAuthLogin(providerId: string): Promise<boolean> {
|
|
1652
|
+
this.ctx.showStatus(`Logging in to ${providerId}…`);
|
|
1653
|
+
const useManualInput = PASTE_CODE_LOGIN_PROVIDERS.has(providerId);
|
|
1654
|
+
let restored = false;
|
|
1655
|
+
const restoreEditor = () => {
|
|
1656
|
+
if (restored) return;
|
|
1657
|
+
restored = true;
|
|
1658
|
+
this.ctx.editorContainer.clear();
|
|
1659
|
+
this.ctx.editorContainer.addChild(this.ctx.editor);
|
|
1660
|
+
this.ctx.ui.setFocus(this.ctx.editor);
|
|
1661
|
+
this.ctx.ui.requestRender();
|
|
1662
|
+
};
|
|
1663
|
+
const dialog = new LoginDialogComponent(this.ctx.ui, providerId, (_success, message) => {
|
|
1664
|
+
// Fires on Esc: unblock the editor immediately; the aborted flow's
|
|
1665
|
+
// rejection settles the awaited login below.
|
|
1666
|
+
restoreEditor();
|
|
1667
|
+
if (message) this.ctx.showStatus(message);
|
|
1668
|
+
});
|
|
1669
|
+
this.ctx.editorContainer.clear();
|
|
1670
|
+
this.ctx.editorContainer.addChild(dialog);
|
|
1671
|
+
this.ctx.ui.setFocus(dialog);
|
|
1672
|
+
this.ctx.ui.requestRender();
|
|
1673
|
+
try {
|
|
1674
|
+
const identity = await this.ctx.session.modelRegistry.authStorage.login(providerId as OAuthProvider, {
|
|
1675
|
+
signal: dialog.signal,
|
|
1676
|
+
onAuth: (info: { url: string; launchUrl?: string; instructions?: string }) => {
|
|
1677
|
+
// The dialog renders the full URL (SSH-safe copy target) and
|
|
1678
|
+
// opens the browser best-effort.
|
|
1679
|
+
dialog.showAuth(info.url, info.instructions, info.launchUrl);
|
|
1680
|
+
},
|
|
1681
|
+
onPrompt: (prompt: { message: string; placeholder?: string }) =>
|
|
1682
|
+
dialog.showPrompt(prompt.message, prompt.placeholder),
|
|
1683
|
+
onProgress: (message: string) => {
|
|
1684
|
+
dialog.showProgress(message);
|
|
1685
|
+
},
|
|
1686
|
+
// Paste-code providers (e.g. Codex) may need the user to paste the
|
|
1687
|
+
// fallback redirect URL when the loopback callback can't complete
|
|
1688
|
+
// (headless/remote/Windows). Mount a focused input in the dialog so
|
|
1689
|
+
// the paste lands somewhere the OAuth flow consumes — the hidden
|
|
1690
|
+
// editor's `/login <url>` path is unreachable while the dialog holds
|
|
1691
|
+
// focus (#5339).
|
|
1692
|
+
onManualCodeInput: useManualInput ? () => dialog.showManualInput(MANUAL_LOGIN_PROMPT) : undefined,
|
|
1693
|
+
});
|
|
1694
|
+
// Scope the post-login refresh to the just-authenticated provider with an
|
|
1695
|
+
// `online` strategy: the default all-provider `online-if-uncached` reuses
|
|
1696
|
+
// a fresh authoritative cache row (e.g. an empty result fetched before
|
|
1697
|
+
// login), so newly persisted credentials would never re-run discovery and
|
|
1698
|
+
// models would stay unavailable in-session (#5780). Unrelated providers
|
|
1699
|
+
// are left untouched. `refreshProvider` swallows discovery failures, so
|
|
1700
|
+
// awaiting cannot reject the login.
|
|
1701
|
+
await this.ctx.session.modelRegistry.refreshProvider(providerId, "online");
|
|
1702
|
+
const block = new TranscriptBlock();
|
|
1703
|
+
// Name the account (and Anthropic organization) that was stored so a
|
|
1704
|
+
// login that lands on an unintended account/subscription is visible
|
|
1705
|
+
// immediately instead of silently replacing an existing registration.
|
|
1706
|
+
const whoBase = identity?.type === "oauth" ? (identity.email ?? identity.accountId) : undefined;
|
|
1707
|
+
const whoOrg = identity?.type === "oauth" ? (identity.orgName ?? identity.orgId) : undefined;
|
|
1708
|
+
const who = whoBase ? ` as ${whoBase}${whoOrg ? ` (${whoOrg})` : ""}` : whoOrg ? ` as ${whoOrg}` : "";
|
|
1709
|
+
block.addChild(
|
|
1710
|
+
new Text(
|
|
1711
|
+
theme.fg("success", `${theme.status.success} Successfully logged in to ${providerId}${who}`),
|
|
1712
|
+
1,
|
|
1713
|
+
0,
|
|
1714
|
+
),
|
|
1715
|
+
);
|
|
1716
|
+
block.addChild(new Text(theme.fg("dim", `Credentials saved to ${getAgentDbPath()}`), 1, 0));
|
|
1717
|
+
this.ctx.present(block);
|
|
1718
|
+
return true;
|
|
1719
|
+
} catch (error: unknown) {
|
|
1720
|
+
if (dialog.signal.aborted) {
|
|
1721
|
+
// User-cancelled: the dialog already restored the editor and
|
|
1722
|
+
// surfaced "Login cancelled".
|
|
1723
|
+
return false;
|
|
1724
|
+
}
|
|
1725
|
+
this.ctx.showError(`Login failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
1726
|
+
return false;
|
|
1727
|
+
} finally {
|
|
1728
|
+
restoreEditor();
|
|
1729
|
+
}
|
|
1730
|
+
}
|
|
1731
|
+
|
|
1732
|
+
async #handleCredentialLogout(providerId: string, account: LogoutAccount): Promise<void> {
|
|
1733
|
+
try {
|
|
1734
|
+
const authStorage = this.ctx.session.modelRegistry.authStorage;
|
|
1735
|
+
const removed = await authStorage.removeCredential(providerId, account.credentialId);
|
|
1736
|
+
if (!removed) {
|
|
1737
|
+
this.ctx.showError(`Logout skipped: ${account.label} is no longer stored for ${providerId}.`);
|
|
1738
|
+
return;
|
|
1739
|
+
}
|
|
1740
|
+
|
|
1741
|
+
// Provider-scoped online refresh so the removed credential's stale
|
|
1742
|
+
// endpoint/deployment models are invalidated deterministically; the
|
|
1743
|
+
// default all-provider `online-if-uncached` would reuse the fresh
|
|
1744
|
+
// authoritative cache row and keep showing models the credential
|
|
1745
|
+
// unlocked (#5780). Other providers are left untouched.
|
|
1746
|
+
await this.ctx.session.modelRegistry.refreshProvider(providerId, "online");
|
|
1747
|
+
const block = new TranscriptBlock();
|
|
1748
|
+
block.addChild(
|
|
1749
|
+
new Text(
|
|
1750
|
+
theme.fg(
|
|
1751
|
+
"success",
|
|
1752
|
+
`${theme.status.success} Successfully logged out ${account.label} from ${providerId}`,
|
|
1753
|
+
),
|
|
1754
|
+
1,
|
|
1755
|
+
0,
|
|
1756
|
+
),
|
|
1757
|
+
);
|
|
1758
|
+
block.addChild(new Text(theme.fg("dim", `Credential removed from ${getAgentDbPath()}`), 1, 0));
|
|
1759
|
+
const remainingSource = authStorage.describeCredentialSource(providerId, this.ctx.session.sessionId);
|
|
1760
|
+
if (remainingSource) {
|
|
1761
|
+
block.addChild(
|
|
1762
|
+
new Text(theme.fg("warning", `${providerId} is still authenticated via ${remainingSource}`), 1, 0),
|
|
1763
|
+
);
|
|
1764
|
+
}
|
|
1765
|
+
this.ctx.present(block);
|
|
1766
|
+
} catch (error: unknown) {
|
|
1767
|
+
this.ctx.showError(`Logout failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
1768
|
+
}
|
|
1769
|
+
}
|
|
1770
|
+
|
|
1771
|
+
async #showOAuthLogoutAccountSelector(providerId: string): Promise<void> {
|
|
1772
|
+
const authStorage = this.ctx.session.modelRegistry.authStorage;
|
|
1773
|
+
try {
|
|
1774
|
+
await authStorage.reload();
|
|
1775
|
+
} catch (error: unknown) {
|
|
1776
|
+
this.ctx.showError(
|
|
1777
|
+
`Could not load stored credentials: ${error instanceof Error ? error.message : String(error)}`,
|
|
1778
|
+
);
|
|
1779
|
+
return;
|
|
1780
|
+
}
|
|
1781
|
+
const provider = getOAuthProviders().find(candidate => candidate.id === providerId);
|
|
1782
|
+
const accounts = toLogoutAccounts(providerId, authStorage.listStoredCredentials(providerId), {
|
|
1783
|
+
activeIdentity: authStorage.getOAuthAccountIdentity(providerId, this.ctx.session.sessionId),
|
|
1784
|
+
activeApiKey: authStorage.getCredentialOrigin(providerId)?.kind === "api_key",
|
|
1785
|
+
});
|
|
1786
|
+
if (accounts.length === 0) {
|
|
1787
|
+
const source = authStorage.describeCredentialSource(providerId, this.ctx.session.sessionId);
|
|
1788
|
+
const suffix = source ? ` Current auth comes from ${source}; remove that source to log out.` : "";
|
|
1789
|
+
this.ctx.showError(`Logout skipped: no stored credentials for ${providerId}.${suffix}`);
|
|
1790
|
+
return;
|
|
1791
|
+
}
|
|
1792
|
+
|
|
1793
|
+
this.showSelector(done => {
|
|
1794
|
+
const selector = new LogoutAccountSelectorComponent(
|
|
1795
|
+
provider?.name ?? providerId,
|
|
1796
|
+
accounts,
|
|
1797
|
+
account => {
|
|
1798
|
+
done();
|
|
1799
|
+
void this.#handleCredentialLogout(providerId, account);
|
|
1800
|
+
},
|
|
1801
|
+
() => {
|
|
1802
|
+
done();
|
|
1803
|
+
this.ctx.ui.requestRender();
|
|
1804
|
+
},
|
|
1805
|
+
);
|
|
1806
|
+
return { component: selector, focus: selector };
|
|
1807
|
+
});
|
|
1808
|
+
}
|
|
1809
|
+
|
|
1810
|
+
async showOAuthSelector(mode: "login" | "logout", providerId?: string): Promise<void> {
|
|
1811
|
+
if (providerId) {
|
|
1812
|
+
if (mode === "login") {
|
|
1813
|
+
await this.#handleOAuthLogin(providerId);
|
|
1814
|
+
} else {
|
|
1815
|
+
await this.#showOAuthLogoutAccountSelector(providerId);
|
|
1816
|
+
}
|
|
1817
|
+
return;
|
|
1818
|
+
}
|
|
1819
|
+
|
|
1820
|
+
if (mode === "logout") {
|
|
1821
|
+
await this.#refreshOAuthProviderAuthState();
|
|
1822
|
+
const oauthProviders = getOAuthProviders();
|
|
1823
|
+
const loggedInProviders = oauthProviders.filter(provider =>
|
|
1824
|
+
this.ctx.session.modelRegistry.authStorage.has(provider.id),
|
|
1825
|
+
);
|
|
1826
|
+
if (loggedInProviders.length === 0) {
|
|
1827
|
+
this.ctx.showStatus("No stored provider credentials to log out. Remove env or config auth at its source.");
|
|
1828
|
+
return;
|
|
1829
|
+
}
|
|
1830
|
+
}
|
|
1831
|
+
|
|
1832
|
+
this.showSelector(done => {
|
|
1833
|
+
let selector: OAuthSelectorComponent;
|
|
1834
|
+
selector = new OAuthSelectorComponent(
|
|
1835
|
+
mode,
|
|
1836
|
+
this.ctx.session.modelRegistry.authStorage,
|
|
1837
|
+
async (selectedProviderId: string) => {
|
|
1838
|
+
selector.stopValidation();
|
|
1839
|
+
done();
|
|
1840
|
+
if (mode === "login") {
|
|
1841
|
+
await this.#handleOAuthLogin(selectedProviderId);
|
|
1842
|
+
} else {
|
|
1843
|
+
await this.#showOAuthLogoutAccountSelector(selectedProviderId);
|
|
1844
|
+
}
|
|
1845
|
+
},
|
|
1846
|
+
() => {
|
|
1847
|
+
selector.stopValidation();
|
|
1848
|
+
done();
|
|
1849
|
+
this.ctx.ui.requestRender();
|
|
1850
|
+
},
|
|
1851
|
+
{
|
|
1852
|
+
validateAuth: async (selectedProviderId: string) => {
|
|
1853
|
+
const apiKey = await this.ctx.session.modelRegistry.getApiKeyForProvider(
|
|
1854
|
+
selectedProviderId,
|
|
1855
|
+
this.ctx.session.sessionId,
|
|
1856
|
+
);
|
|
1857
|
+
return !!apiKey;
|
|
1858
|
+
},
|
|
1859
|
+
requestRender: () => {
|
|
1860
|
+
this.ctx.ui.requestRender();
|
|
1861
|
+
},
|
|
1862
|
+
},
|
|
1863
|
+
);
|
|
1864
|
+
return { component: selector, focus: selector };
|
|
1865
|
+
});
|
|
1866
|
+
}
|
|
1867
|
+
|
|
1868
|
+
async showSessionPinSelector(): Promise<void> {
|
|
1869
|
+
const session = this.ctx.session;
|
|
1870
|
+
if (session.isStreaming) {
|
|
1871
|
+
this.ctx.showStatus("Cannot pin an account while the session is streaming.");
|
|
1872
|
+
return;
|
|
1873
|
+
}
|
|
1874
|
+
this.ctx.showStatus("Loading provider accounts…", { dim: true });
|
|
1875
|
+
let accountList: SessionOAuthAccountList | undefined;
|
|
1876
|
+
try {
|
|
1877
|
+
accountList = await session.listCurrentProviderOAuthAccounts();
|
|
1878
|
+
} catch (error) {
|
|
1879
|
+
this.ctx.showError(
|
|
1880
|
+
`Could not load provider accounts: ${error instanceof Error ? error.message : String(error)}`,
|
|
1881
|
+
);
|
|
1882
|
+
return;
|
|
1883
|
+
}
|
|
1884
|
+
if (!accountList) {
|
|
1885
|
+
this.ctx.showStatus("Select a model before pinning a provider account.");
|
|
1886
|
+
return;
|
|
1887
|
+
}
|
|
1888
|
+
const provider = getOAuthProviders().find(candidate => candidate.id === accountList.provider);
|
|
1889
|
+
const providerName = provider?.name ?? accountList.provider;
|
|
1890
|
+
const accounts = toSessionPinAccounts(accountList.accounts);
|
|
1891
|
+
if (accounts.length === 0) {
|
|
1892
|
+
const source = session.modelRegistry.authStorage.describeCredentialSource(
|
|
1893
|
+
accountList.provider,
|
|
1894
|
+
session.sessionId,
|
|
1895
|
+
);
|
|
1896
|
+
this.ctx.showStatus(
|
|
1897
|
+
source
|
|
1898
|
+
? `No stored OAuth accounts for ${providerName}. Current auth comes from ${source}.`
|
|
1899
|
+
: `No stored OAuth accounts for ${providerName}. Use /login to add one.`,
|
|
1900
|
+
);
|
|
1901
|
+
return;
|
|
1902
|
+
}
|
|
1903
|
+
|
|
1904
|
+
this.showSelector(done => {
|
|
1905
|
+
const selector = new SessionAccountSelectorComponent(
|
|
1906
|
+
providerName,
|
|
1907
|
+
accounts,
|
|
1908
|
+
account => {
|
|
1909
|
+
done();
|
|
1910
|
+
if (!session.pinCurrentProviderOAuthAccount(account.credentialId)) {
|
|
1911
|
+
this.ctx.showWarning(`${account.label} is no longer available to pin.`);
|
|
1912
|
+
return;
|
|
1913
|
+
}
|
|
1914
|
+
this.ctx.showStatus(`Pinned ${account.label} to this session for ${providerName}.`);
|
|
1915
|
+
this.ctx.statusLine.invalidate();
|
|
1916
|
+
this.ctx.ui.requestRender();
|
|
1917
|
+
},
|
|
1918
|
+
() => {
|
|
1919
|
+
done();
|
|
1920
|
+
this.ctx.ui.requestRender();
|
|
1921
|
+
},
|
|
1922
|
+
);
|
|
1923
|
+
return { component: selector, focus: selector };
|
|
1924
|
+
});
|
|
1925
|
+
}
|
|
1926
|
+
|
|
1927
|
+
async showResetUsageSelector(): Promise<void> {
|
|
1928
|
+
const session = this.ctx.session;
|
|
1929
|
+
this.ctx.showStatus("Checking saved rate-limit resets…", { dim: true });
|
|
1930
|
+
let statuses: ResetCreditAccountStatus[];
|
|
1931
|
+
try {
|
|
1932
|
+
statuses = await session.listResetCredits();
|
|
1933
|
+
} catch (error) {
|
|
1934
|
+
this.ctx.showError(`Could not load saved resets: ${error instanceof Error ? error.message : String(error)}`);
|
|
1935
|
+
return;
|
|
1936
|
+
}
|
|
1937
|
+
const accounts = toResetUsageAccounts(statuses);
|
|
1938
|
+
if (accounts.length === 0) {
|
|
1939
|
+
this.ctx.showStatus("No Codex accounts found. Use /login to add one.");
|
|
1940
|
+
return;
|
|
1941
|
+
}
|
|
1942
|
+
if (!accounts.some(account => account.availableCount > 0)) {
|
|
1943
|
+
this.ctx.showStatus(
|
|
1944
|
+
accounts.some(account => account.error)
|
|
1945
|
+
? "No saved resets available — some accounts couldn't be reached (try /login)."
|
|
1946
|
+
: "No saved rate-limit resets available to spend right now.",
|
|
1947
|
+
);
|
|
1948
|
+
return;
|
|
1949
|
+
}
|
|
1950
|
+
this.showSelector(done => {
|
|
1951
|
+
const selector = new ResetUsageSelectorComponent(
|
|
1952
|
+
accounts,
|
|
1953
|
+
account => {
|
|
1954
|
+
done();
|
|
1955
|
+
void this.#redeemReset(account);
|
|
1956
|
+
},
|
|
1957
|
+
() => {
|
|
1958
|
+
done();
|
|
1959
|
+
this.ctx.ui.requestRender();
|
|
1960
|
+
},
|
|
1961
|
+
);
|
|
1962
|
+
return { component: selector, focus: selector };
|
|
1963
|
+
});
|
|
1964
|
+
}
|
|
1965
|
+
|
|
1966
|
+
async #redeemReset(account: ResetUsageAccount): Promise<void> {
|
|
1967
|
+
this.ctx.showStatus(`Spending 1 saved reset for ${account.label}…`, { dim: true });
|
|
1968
|
+
let outcome: ResetCreditRedeemOutcome;
|
|
1969
|
+
try {
|
|
1970
|
+
outcome = await this.ctx.session.redeemResetCredit(account.target);
|
|
1971
|
+
} catch (error) {
|
|
1972
|
+
this.ctx.showError(
|
|
1973
|
+
`Reset failed for ${account.label}: ${error instanceof Error ? error.message : String(error)}`,
|
|
1974
|
+
);
|
|
1975
|
+
return;
|
|
1976
|
+
}
|
|
1977
|
+
const message = describeRedeemOutcome(outcome, account.label);
|
|
1978
|
+
if (outcome.ok) {
|
|
1979
|
+
this.ctx.showStatus(message);
|
|
1980
|
+
// Refresh the status-line usage so the freshly-reset window shows.
|
|
1981
|
+
this.ctx.statusLine.invalidate();
|
|
1982
|
+
this.ctx.ui.requestRender();
|
|
1983
|
+
} else {
|
|
1984
|
+
this.ctx.showWarning(message);
|
|
1985
|
+
}
|
|
1986
|
+
}
|
|
1987
|
+
|
|
1988
|
+
async showDebugSelector(): Promise<void> {
|
|
1989
|
+
const { DebugSelectorComponent } = await import("../../debug");
|
|
1990
|
+
this.showSelector(done => {
|
|
1991
|
+
const selector = new DebugSelectorComponent(this.ctx, done);
|
|
1992
|
+
return { component: selector, focus: selector };
|
|
1993
|
+
});
|
|
1994
|
+
}
|
|
1995
|
+
|
|
1996
|
+
showAgentHub(
|
|
1997
|
+
observers: SessionObserverRegistry,
|
|
1998
|
+
options?: { requireContent?: boolean; armCloseTap?: boolean },
|
|
1999
|
+
): void {
|
|
2000
|
+
const hubKeys = [
|
|
2001
|
+
...this.ctx.keybindings.getKeys("app.agents.hub"),
|
|
2002
|
+
...this.ctx.keybindings.getKeys("app.session.observe"),
|
|
2003
|
+
];
|
|
2004
|
+
let overlayHandle: OverlayHandle | undefined;
|
|
2005
|
+
let closed = false;
|
|
2006
|
+
|
|
2007
|
+
const done = () => {
|
|
2008
|
+
if (closed) return;
|
|
2009
|
+
closed = true;
|
|
2010
|
+
hub.dispose();
|
|
2011
|
+
overlayHandle?.hide();
|
|
2012
|
+
// A gated empty Hub may never have been mounted. Restoring editor
|
|
2013
|
+
// focus in that case would steal focus from a menu opened meanwhile.
|
|
2014
|
+
if (overlayHandle) this.focusActiveEditorArea();
|
|
2015
|
+
this.ctx.ui.requestRender();
|
|
2016
|
+
};
|
|
2017
|
+
|
|
2018
|
+
const hub = new AgentHubOverlayComponent({
|
|
2019
|
+
observers,
|
|
2020
|
+
settings: this.ctx.settings,
|
|
2021
|
+
hubKeys,
|
|
2022
|
+
expandKeys: this.ctx.keybindings.getKeys("app.tools.expand"),
|
|
2023
|
+
onDone: done,
|
|
2024
|
+
requestRender: () => this.ctx.ui.requestRender(),
|
|
2025
|
+
registry: this.ctx.collabGuest?.agentRegistry,
|
|
2026
|
+
remote: this.ctx.collabGuest?.hubRemote,
|
|
2027
|
+
ui: this.ctx.ui,
|
|
2028
|
+
getTool: name => this.ctx.session.getToolByName(name),
|
|
2029
|
+
getMessageRenderer: type => this.ctx.session.extensionRunner?.getMessageRenderer(type),
|
|
2030
|
+
cwd: this.ctx.sessionManager.getCwd(),
|
|
2031
|
+
hideThinkingBlock: () => this.ctx.effectiveHideThinkingBlock,
|
|
2032
|
+
proseOnlyThinking: () => this.ctx.proseOnlyThinking,
|
|
2033
|
+
focusAgent: id => this.ctx.focusAgentSession(id),
|
|
2034
|
+
sessionFile: this.ctx.sessionManager.getSessionFile() ?? null,
|
|
2035
|
+
});
|
|
2036
|
+
|
|
2037
|
+
const showReadyHub = () => {
|
|
2038
|
+
if (closed) return;
|
|
2039
|
+
// The double-← gesture stays inert when neither live nor persisted
|
|
2040
|
+
// subagents are available, so wait for discovery before making the gate.
|
|
2041
|
+
if (options?.requireContent && hub.isEmpty) {
|
|
2042
|
+
done();
|
|
2043
|
+
return;
|
|
2044
|
+
}
|
|
2045
|
+
|
|
2046
|
+
// Prime the detector before the first frame when the editor's double-←
|
|
2047
|
+
// gesture opened the hub, so the next single ← dismisses it.
|
|
2048
|
+
if (options?.armCloseTap) hub.armCloseTap();
|
|
2049
|
+
overlayHandle = this.#showFullscreenMenu(hub);
|
|
2050
|
+
};
|
|
2051
|
+
|
|
2052
|
+
if (options?.requireContent && hub.isEmpty) {
|
|
2053
|
+
void hub.persistedSubagentsReady.then(showReadyHub);
|
|
2054
|
+
} else {
|
|
2055
|
+
showReadyHub();
|
|
2056
|
+
}
|
|
2057
|
+
}
|
|
2058
|
+
}
|