@gajae-code/coding-agent 0.18.11 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +760 -0
- package/dist/types/async/job-manager.d.ts +7 -3
- package/dist/types/async/result-formatting.d.ts +2 -0
- package/dist/types/autoresearch/git.d.ts +1 -1
- package/dist/types/capability/fs.d.ts +2 -2
- package/dist/types/capability/rule.d.ts +7 -2
- package/dist/types/cli/accounts-cli.d.ts +2 -2
- package/dist/types/cli/append-system-prompt.d.ts +6 -0
- package/dist/types/cli/args.d.ts +7 -2
- package/dist/types/cli/customize-doctor-precedence.d.ts +16 -0
- package/dist/types/cli/customize-doctor.d.ts +4 -3
- package/dist/types/cli/doctor/install-repairs.d.ts +4 -1
- package/dist/types/cli/install-activation.d.ts +10 -4
- package/dist/types/cli/public-command-errors.d.ts +2 -0
- package/dist/types/cli/root-flags.d.ts +0 -12
- package/dist/types/cli/update-cli.d.ts +21 -3
- package/dist/types/cli-main.d.ts +0 -6
- package/dist/types/cli-ordinary.d.ts +2 -2
- package/dist/types/commands/accounts.d.ts +2 -1
- package/dist/types/commands/launch.d.ts +0 -6
- package/dist/types/commands/migrate.d.ts +1 -1
- package/dist/types/commands/sdk.d.ts +13 -0
- package/dist/types/commit/changelog/index.d.ts +1 -0
- package/dist/types/commit/map-reduce/index.d.ts +4 -4
- package/dist/types/config/autorouting-tier-map.d.ts +53 -1
- package/dist/types/config/config-hot-reload-trust.d.ts +12 -0
- package/dist/types/config/config-hot-reload.d.ts +44 -0
- package/dist/types/config/file-lock.d.ts +52 -3
- package/dist/types/config/model-discovery-manager.d.ts +2 -0
- package/dist/types/config/model-profile-activation.d.ts +79 -9
- package/dist/types/config/model-registry.d.ts +72 -8
- package/dist/types/config/model-resolver.d.ts +7 -4
- package/dist/types/config/models-config-schema.d.ts +10 -0
- package/dist/types/config/settings-schema.d.ts +57 -4
- package/dist/types/config/settings.d.ts +33 -1
- package/dist/types/coordinator-mcp/server.d.ts +4 -0
- package/dist/types/customization/import.d.ts +2 -0
- package/dist/types/customization/types.d.ts +1 -1
- package/dist/types/dap/config.d.ts +8 -4
- package/dist/types/dap/session.d.ts +11 -2
- package/dist/types/debug/system-info.d.ts +6 -1
- package/dist/types/discovery/helpers.d.ts +7 -2
- package/dist/types/discovery/mcp-compat.d.ts +3 -1
- package/dist/types/edit/index.d.ts +5 -0
- package/dist/types/edit/modes/patch.d.ts +14 -0
- package/dist/types/edit/modes/replace.d.ts +3 -0
- package/dist/types/eval/py/runtime.d.ts +9 -0
- package/dist/types/exec/bash-executor.d.ts +12 -0
- package/dist/types/export/ttsr.d.ts +19 -0
- package/dist/types/extensibility/extensions/types.d.ts +5 -1
- package/dist/types/extensibility/slash-commands.d.ts +1 -0
- package/dist/types/gjc-runtime/managed-owner-admission.d.ts +3 -0
- package/dist/types/gjc-runtime/ralplan-current-final.d.ts +54 -0
- package/dist/types/gjc-runtime/ralplan-runtime.d.ts +5 -0
- package/dist/types/gjc-runtime/session-state-lock.d.ts +2 -0
- package/dist/types/gjc-runtime/state-runtime.d.ts +0 -2
- package/dist/types/gjc-runtime/tmux-sessions.d.ts +24 -0
- package/dist/types/gjc-runtime/ultragoal-change-set.d.ts +6 -0
- package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +1 -0
- package/dist/types/harness-control-plane/receipt-spool.d.ts +4 -0
- package/dist/types/hindsight/content.d.ts +5 -6
- package/dist/types/internal-urls/types.d.ts +2 -0
- package/dist/types/lsp/clients/swiftlint-client.d.ts +0 -4
- package/dist/types/main.d.ts +23 -18
- package/dist/types/migrate/action-planner.d.ts +10 -1
- package/dist/types/migrate/adapters/codex.d.ts +2 -1
- package/dist/types/migrate/adapters/index.d.ts +42 -1
- package/dist/types/migrate/executor.d.ts +3 -1
- package/dist/types/migrate/hook-module.d.ts +23 -0
- package/dist/types/migrate/report.d.ts +2 -1
- package/dist/types/migrate/types.d.ts +82 -3
- package/dist/types/modes/components/agent-dashboard.d.ts +1 -1
- package/dist/types/modes/components/model-selector.d.ts +43 -0
- package/dist/types/modes/components/settings-selector.d.ts +6 -0
- package/dist/types/modes/controllers/selector-controller.d.ts +2 -0
- package/dist/types/modes/prompt-suggestion-controller.d.ts +1 -1
- package/dist/types/modes/theme/theme.d.ts +1 -0
- package/dist/types/modes/utils/host-status.d.ts +15 -11
- package/dist/types/runtime-mcp/content-limits.d.ts +4 -0
- package/dist/types/runtime-mcp/manager.d.ts +7 -0
- package/dist/types/runtime-mcp/plugin-mcp-name-filter.d.ts +22 -0
- package/dist/types/runtime-mcp/project-host-values.d.ts +11 -5
- package/dist/types/runtime-mcp/tool-bridge.d.ts +4 -0
- package/dist/types/sdk/broker/broker-exit.d.ts +3 -3
- package/dist/types/sdk/broker/broker.d.ts +29 -2
- package/dist/types/sdk/broker/daemon-entry.d.ts +11 -1
- package/dist/types/sdk/broker/doctor-restart.d.ts +1 -1
- package/dist/types/sdk/broker/ensure.d.ts +141 -9
- package/dist/types/sdk/broker/hop.d.ts +45 -0
- package/dist/types/sdk/broker/lifecycle-ledger.d.ts +18 -10
- package/dist/types/sdk/broker/lifecycle.d.ts +22 -0
- package/dist/types/sdk/broker/lock-host-identity.d.ts +5 -0
- package/dist/types/sdk/broker/session-index.d.ts +6 -1
- package/dist/types/sdk/broker/transport.d.ts +2 -0
- package/dist/types/sdk/bus/chat-command-policy.d.ts +2 -1
- package/dist/types/sdk/bus/index.d.ts +44 -0
- package/dist/types/sdk/bus/reconciliation-store.d.ts +10 -0
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +9 -1
- package/dist/types/sdk/bus/telegram-daemon.d.ts +2 -0
- package/dist/types/sdk/bus/threaded-render.d.ts +2 -1
- package/dist/types/sdk/cli/session-cli.d.ts +0 -1
- package/dist/types/sdk/host/control/operations.d.ts +5 -1
- package/dist/types/sdk/host/events.d.ts +4 -0
- package/dist/types/sdk/host/host.d.ts +2 -1
- package/dist/types/sdk/host/prompt-image-upload.d.ts +43 -0
- package/dist/types/sdk/host/session-runtime.d.ts +40 -8
- package/dist/types/sdk/host/surface-policy.d.ts +2 -1
- package/dist/types/sdk/lifecycle/service.d.ts +12 -0
- package/dist/types/sdk/prompt-deadline-flush.d.ts +42 -4
- package/dist/types/sdk/prompt-deadline-manager.d.ts +2 -0
- package/dist/types/sdk/prompt-status.d.ts +11 -4
- package/dist/types/sdk/protocol/adapter-validation.d.ts +10 -4
- package/dist/types/sdk/reconciliation-extensions.d.ts +1 -1
- package/dist/types/sdk/session-list.d.ts +1 -1
- package/dist/types/session/agent-session.d.ts +107 -9
- package/dist/types/session/internal/managed-session-scope.d.ts +2 -2
- package/dist/types/session/internal/managed-session-storage.d.ts +1 -1
- package/dist/types/session/internal/native-publish-outcome.d.ts +1 -1
- package/dist/types/session/messages.d.ts +5 -1
- package/dist/types/session/session-manager.d.ts +29 -3
- package/dist/types/session/startup-auth-config.d.ts +24 -2
- package/dist/types/session/streaming-output.d.ts +11 -0
- package/dist/types/session/terminal-abort.d.ts +3 -1
- package/dist/types/session-import/service.d.ts +1 -1
- package/dist/types/skill-state/workflow-mutation-guard.d.ts +20 -4
- package/dist/types/slash-commands/helpers/mcp.d.ts +5 -0
- package/dist/types/slash-commands/helpers/provider-auth-status.d.ts +8 -0
- package/dist/types/ssh/ssh-executor.d.ts +8 -1
- package/dist/types/system-prompt.d.ts +3 -2
- package/dist/types/task/executor.d.ts +19 -2
- package/dist/types/task/role-body.d.ts +11 -0
- package/dist/types/tools/ast-edit-write-path.d.ts +10 -0
- package/dist/types/tools/atomic-file-write.d.ts +9 -7
- package/dist/types/tools/awaiting-input.d.ts +28 -0
- package/dist/types/tools/bash-allowed-prefixes.d.ts +17 -0
- package/dist/types/tools/bash-skill-urls.d.ts +4 -0
- package/dist/types/tools/bash.d.ts +7 -0
- package/dist/types/tools/descriptors.d.ts +15 -2
- package/dist/types/tools/fetch.d.ts +7 -1
- package/dist/types/tools/index.d.ts +2 -0
- package/dist/types/tools/irc.d.ts +5 -3
- package/dist/types/tools/python.d.ts +1 -1
- package/dist/types/tools/report-issue.d.ts +41 -0
- package/dist/types/tools/subagent.d.ts +23 -0
- package/dist/types/tools/tmux-self-injection-guard.d.ts +2 -0
- package/dist/types/tools/ultragoal-ask-guard.d.ts +1 -1
- package/dist/types/tools/write.d.ts +2 -0
- package/dist/types/utils/file-mentions.d.ts +5 -0
- package/dist/types/utils/image-limits.d.ts +7 -0
- package/dist/types/utils/image-loading.d.ts +0 -1
- package/dist/types/utils/open.d.ts +0 -1
- package/dist/types/utils/pasted-image-loading.d.ts +1 -5
- package/dist/types/utils/prompt-suggestion.d.ts +2 -2
- package/dist/types/utils/shell-snapshot.d.ts +2 -0
- package/dist/types/utils/title-generator.d.ts +13 -3
- package/dist/types/web/scrapers/types.d.ts +8 -1
- package/dist/types/web/search/providers/codex.d.ts +6 -7
- package/dist/types/web/search/providers/insane.d.ts +7 -1
- package/dist/types/web/search/providers/searxng.d.ts +5 -0
- package/package.json +10 -9
- package/scripts/acp-conformance-agent.ts +12 -2
- package/scripts/build-binary.ts +2 -1
- package/scripts/capture-subagent-compact-panel-showcase.ts +105 -0
- package/scripts/generate-docs-index.ts +8 -1
- package/scripts/generate-sdk-operation-inventory.ts +38 -4
- package/src/async/job-manager.ts +356 -56
- package/src/async/result-formatting.ts +40 -0
- package/src/autoresearch/git.ts +9 -2
- package/src/autoresearch/prompts/prompt-setup.md +1 -1
- package/src/capability/fs.ts +58 -22
- package/src/capability/index.ts +2 -2
- package/src/capability/rule.ts +11 -2
- package/src/cli/accounts-cli.ts +176 -8
- package/src/cli/append-system-prompt.ts +12 -0
- package/src/cli/args.ts +11 -7
- package/src/cli/auth-broker-cli.ts +21 -11
- package/src/cli/customize-doctor-precedence.ts +31 -0
- package/src/cli/customize-doctor.ts +49 -39
- package/src/cli/doctor/install-repairs.ts +35 -5
- package/src/cli/fast-help.ts +1 -3
- package/src/cli/install-activation.ts +47 -4
- package/src/cli/migrate-cli.ts +19 -6
- package/src/cli/public-command-errors.ts +6 -0
- package/src/cli/root-flags.ts +2 -4
- package/src/cli/stats-cli.ts +9 -5
- package/src/cli/update-cli.ts +471 -13
- package/src/cli-ordinary.ts +7 -2
- package/src/commands/accounts.ts +10 -5
- package/src/commands/harness.ts +25 -15
- package/src/commands/migrate.ts +3 -3
- package/src/commands/sdk.ts +277 -50
- package/src/commands/ultragoal.ts +16 -8
- package/src/commit/agentic/agent.ts +6 -6
- package/src/commit/analysis/conventional.ts +14 -5
- package/src/commit/changelog/index.ts +39 -1
- package/src/commit/map-reduce/index.ts +7 -7
- package/src/commit/message.ts +10 -3
- package/src/commit/pipeline.ts +12 -12
- package/src/config/autorouting-tier-map.ts +50 -1
- package/src/config/config-file.ts +106 -3
- package/src/config/config-hot-reload-trust.ts +148 -0
- package/src/config/config-hot-reload.ts +742 -0
- package/src/config/file-lock.ts +1615 -328
- package/src/config/keybindings.ts +154 -7
- package/src/config/model-bindings-applier.ts +85 -47
- package/src/config/model-discovery-manager.ts +10 -0
- package/src/config/model-profile-activation.ts +889 -148
- package/src/config/model-registry.ts +1706 -205
- package/src/config/model-resolver.ts +52 -22
- package/src/config/models-config-schema.ts +6 -0
- package/src/config/settings-schema.ts +73 -4
- package/src/config/settings.ts +460 -24
- package/src/coordinator-mcp/policy.ts +26 -1
- package/src/coordinator-mcp/server.ts +37 -2
- package/src/crash/sanitize.ts +7 -1
- package/src/customization/import.ts +279 -8
- package/src/customization/inventory.ts +24 -8
- package/src/customization/types.ts +1 -0
- package/src/dap/client.ts +3 -2
- package/src/dap/config.ts +31 -11
- package/src/dap/defaults.json +1 -1
- package/src/dap/session.ts +161 -36
- package/src/debug/crash-diagnostics.ts +89 -6
- package/src/debug/report-bundle.ts +90 -2
- package/src/debug/system-info.ts +8 -3
- package/src/defaults/gjc/extensions/grok-cli-vendor/src/shared/base-url.ts +21 -7
- package/src/discovery/agents-md.ts +1 -1
- package/src/discovery/builtin.ts +4 -3
- package/src/discovery/helpers.ts +25 -16
- package/src/discovery/mcp-compat.ts +120 -17
- package/src/edit/apply-patch/index.ts +12 -1
- package/src/edit/index.ts +204 -22
- package/src/edit/modes/patch.ts +214 -8
- package/src/edit/modes/replace.ts +136 -0
- package/src/eval/js/context-manager.ts +29 -3
- package/src/eval/js/worker-entry.ts +51 -18
- package/src/eval/py/executor.ts +14 -4
- package/src/eval/py/runner.py +144 -5
- package/src/eval/py/runtime.ts +44 -4
- package/src/exec/bash-executor.ts +81 -4
- package/src/exec/bash-shell-guardian.ts +4 -1
- package/src/exec/bash-shell-supervisor.ts +8 -4
- package/src/exec/isolated-shell.ts +5 -1
- package/src/exec/non-interactive-env.ts +0 -1
- package/src/export/html/index.ts +86 -6
- package/src/export/ttsr.ts +176 -1
- package/src/extensibility/custom-tools/wrapper.ts +3 -1
- package/src/extensibility/extensions/loader.ts +10 -1
- package/src/extensibility/extensions/ouroboros-ooo-bridge.ts +63 -1
- package/src/extensibility/extensions/types.ts +5 -1
- package/src/extensibility/hooks/loader.ts +10 -2
- package/src/extensibility/plugins/marketplace/fetcher.ts +2 -2
- package/src/extensibility/plugins/marketplace/manager.ts +36 -10
- package/src/extensibility/slash-commands.ts +5 -0
- package/src/gjc-runtime/gc-runtime.ts +37 -7
- package/src/gjc-runtime/launch-tmux.ts +30 -15
- package/src/gjc-runtime/launch-worktree.test.ts +148 -0
- package/src/gjc-runtime/launch-worktree.ts +101 -14
- package/src/gjc-runtime/managed-owner-admission.ts +46 -2
- package/src/gjc-runtime/ralplan-current-final.ts +294 -0
- package/src/gjc-runtime/ralplan-runtime.ts +95 -1
- package/src/gjc-runtime/session-resolution.ts +38 -6
- package/src/gjc-runtime/session-state-lock.ts +59 -14
- package/src/gjc-runtime/state-runtime.ts +23 -19
- package/src/gjc-runtime/state-writer.ts +109 -5
- package/src/gjc-runtime/tmux-sessions.ts +93 -13
- package/src/gjc-runtime/ultragoal-change-set.ts +90 -11
- package/src/gjc-runtime/ultragoal-guard.ts +9 -1
- package/src/gjc-runtime/ultragoal-runtime.ts +15 -5
- package/src/harness-control-plane/finalize.ts +11 -0
- package/src/harness-control-plane/receipt-spool.ts +105 -28
- package/src/harness-control-plane/storage.ts +124 -6
- package/src/hindsight/content.ts +116 -16
- package/src/hindsight/mental-models.ts +22 -10
- package/src/hindsight/state.ts +7 -4
- package/src/hooks/native-skill-hook.ts +17 -12
- package/src/internal-urls/artifact-protocol.ts +3 -1
- package/src/internal-urls/docs-index.generated.ts +23 -22
- package/src/internal-urls/local-protocol.ts +167 -8
- package/src/internal-urls/types.ts +2 -0
- package/src/lsp/client.ts +2 -1
- package/src/lsp/clients/biome-client.ts +2 -0
- package/src/lsp/clients/swiftlint-client.ts +2 -0
- package/src/lsp/index.ts +29 -0
- package/src/lsp/workspace-path.ts +23 -0
- package/src/main.ts +330 -92
- package/src/memories/index.ts +25 -2
- package/src/migrate/action-planner.ts +574 -2
- package/src/migrate/adapters/claude-code.ts +162 -5
- package/src/migrate/adapters/codex.ts +77 -7
- package/src/migrate/adapters/index.ts +258 -5
- package/src/migrate/adapters/opencode.ts +10 -1
- package/src/migrate/executor.ts +222 -7
- package/src/migrate/hook-module.ts +193 -0
- package/src/migrate/report.ts +63 -2
- package/src/migrate/types.ts +84 -4
- package/src/modes/DESIGN.md +51 -0
- package/src/modes/acp/acp-agent.ts +10 -1
- package/src/modes/acp/permission-mode.ts +18 -1
- package/src/modes/components/agent-dashboard.ts +20 -4
- package/src/modes/components/assistant-message.ts +55 -1
- package/src/modes/components/customization/customization-dashboard.ts +7 -0
- package/src/modes/components/customization/import-wizard.ts +29 -3
- package/src/modes/components/model-selector.ts +157 -103
- package/src/modes/components/settings-selector.ts +103 -37
- package/src/modes/components/welcome.ts +3 -1
- package/src/modes/controllers/command-controller.ts +300 -9
- package/src/modes/controllers/event-controller.ts +1 -1
- package/src/modes/controllers/extension-ui-controller.ts +31 -1
- package/src/modes/controllers/goal-mode-controller.ts +79 -10
- package/src/modes/controllers/input-controller.ts +2 -0
- package/src/modes/controllers/plan-mode-controller.ts +66 -11
- package/src/modes/controllers/runtime-mcp-command-controller.ts +7 -6
- package/src/modes/controllers/selector-controller.ts +76 -7
- package/src/modes/interactive-mode.ts +123 -4
- package/src/modes/prompt-suggestion-controller.ts +1 -1
- package/src/modes/runtime-init.ts +5 -1
- package/src/modes/theme/theme.ts +15 -0
- package/src/modes/utils/host-status.ts +21 -10
- package/src/prompts/agent-fragments/browser-aside.md +2 -2
- package/src/prompts/system/irc-incoming.md +3 -1
- package/src/prompts/tools/debug.md +1 -1
- package/src/prompts/tools/irc.md +1 -1
- package/src/prompts/tools/read.md +1 -1
- package/src/prompts/tools/report-issue.md +13 -0
- package/src/prompts/tools/task.md +1 -1
- package/src/runtime-credential-selector.ts +2 -2
- package/src/runtime-mcp/content-limits.ts +7 -0
- package/src/runtime-mcp/manager-pool.test.ts +5 -4
- package/src/runtime-mcp/manager.ts +40 -3
- package/src/runtime-mcp/oauth-flow.ts +32 -6
- package/src/runtime-mcp/plugin-mcp-name-filter.ts +62 -0
- package/src/runtime-mcp/project-host-values.ts +12 -8
- package/src/runtime-mcp/render.ts +16 -1
- package/src/runtime-mcp/tool-bridge.ts +194 -21
- package/src/runtime-mcp/transports/stdio.ts +2 -1
- package/src/sdk/broker/broker-exit.ts +10 -5
- package/src/sdk/broker/broker.ts +484 -85
- package/src/sdk/broker/daemon-entry.ts +338 -116
- package/src/sdk/broker/doctor-restart.ts +2 -1
- package/src/sdk/broker/ensure.ts +1214 -268
- package/src/sdk/broker/hop.ts +286 -0
- package/src/sdk/broker/lifecycle-ledger.ts +38 -11
- package/src/sdk/broker/lifecycle.ts +102 -6
- package/src/sdk/broker/lock-host-identity.ts +29 -0
- package/src/sdk/broker/session-index.ts +91 -16
- package/src/sdk/broker/transport.ts +17 -1
- package/src/sdk/bus/chat-command-policy.ts +16 -3
- package/src/sdk/bus/chat-daemon-control.ts +2 -2
- package/src/sdk/bus/index.ts +460 -35
- package/src/sdk/bus/reconciliation-store.ts +201 -8
- package/src/sdk/bus/session-control.ts +2 -0
- package/src/sdk/bus/slack-daemon.ts +105 -9
- package/src/sdk/bus/telegram-daemon-contract.ts +9 -1
- package/src/sdk/bus/telegram-daemon.ts +10 -2
- package/src/sdk/bus/threaded-render.ts +20 -1
- package/src/sdk/cli/session-cli.ts +23 -6
- package/src/sdk/host/control/dispatch.ts +13 -1
- package/src/sdk/host/control/operations.ts +10 -1
- package/src/sdk/host/events.ts +67 -4
- package/src/sdk/host/host.ts +8 -2
- package/src/sdk/host/prompt-image-upload.ts +438 -0
- package/src/sdk/host/sdk-surface-parity.test.ts +15 -0
- package/src/sdk/host/session-runtime.test.ts +1737 -129
- package/src/sdk/host/session-runtime.ts +684 -83
- package/src/sdk/host/surface-policy.ts +4 -0
- package/src/sdk/host/websocket-transport.lifecycle.test.ts +90 -2
- package/src/sdk/host/websocket-transport.ts +19 -7
- package/src/sdk/lifecycle/service.ts +15 -1
- package/src/sdk/prompt-deadline-flush.ts +78 -5
- package/src/sdk/prompt-deadline-manager.ts +68 -14
- package/src/sdk/prompt-status.ts +6 -4
- package/src/sdk/protocol/adapter-validation.ts +81 -12
- package/src/sdk/protocol/operation-inventory.generated.json +261 -2
- package/src/sdk/protocol/operation-registry.ts +33 -3
- package/src/sdk/reconciliation-extensions.ts +1 -0
- package/src/sdk/session-list.ts +1 -0
- package/src/sdk/session.ts +237 -97
- package/src/session/agent-session.ts +2726 -479
- package/src/session/history-storage.ts +182 -12
- package/src/session/internal/managed-session-scope.ts +173 -57
- package/src/session/internal/managed-session-storage.ts +85 -12
- package/src/session/internal/native-publish-outcome.ts +5 -1
- package/src/session/messages.ts +47 -6
- package/src/session/session-manager.ts +326 -19
- package/src/session/startup-auth-config.ts +116 -8
- package/src/session/streaming-output.ts +262 -4
- package/src/session/terminal-abort.ts +14 -2
- package/src/session-import/redact.ts +53 -2
- package/src/session-import/service.ts +1 -0
- package/src/skill-state/workflow-mutation-guard.ts +2145 -206
- package/src/slash-commands/builtin-registry.ts +21 -6
- package/src/slash-commands/helpers/credential-switch.ts +10 -5
- package/src/slash-commands/helpers/mcp.ts +11 -3
- package/src/slash-commands/helpers/provider-auth-status.ts +456 -0
- package/src/ssh/ssh-executor.ts +9 -2
- package/src/stt/recorder.ts +26 -9
- package/src/system-prompt.ts +61 -16
- package/src/task/executor.ts +115 -20
- package/src/task/index.ts +389 -175
- package/src/task/role-body.ts +84 -0
- package/src/task/token-log-mode.test.ts +162 -0
- package/src/task/token-log.ts +91 -2
- package/src/tools/archive-reader.ts +650 -37
- package/src/tools/ask.ts +1 -0
- package/src/tools/ast-edit-write-path.ts +64 -0
- package/src/tools/ast-edit.ts +18 -1
- package/src/tools/ast-grep.ts +7 -2
- package/src/tools/atomic-file-write.ts +46 -15
- package/src/tools/auto-generated-guard.ts +15 -3
- package/src/tools/awaiting-input.ts +114 -0
- package/src/tools/bash-allowed-prefixes.ts +214 -6
- package/src/tools/bash-interactive.ts +14 -2
- package/src/tools/bash-skill-urls.ts +58 -5
- package/src/tools/bash.ts +113 -26
- package/src/tools/browser/tab-worker.ts +39 -13
- package/src/tools/browser.ts +17 -7
- package/src/tools/cron.ts +10 -1
- package/src/tools/debug.ts +16 -8
- package/src/tools/descriptors.test.ts +44 -0
- package/src/tools/descriptors.ts +50 -6
- package/src/tools/eval.ts +15 -0
- package/src/tools/fetch.ts +93 -4
- package/src/tools/gh.ts +27 -12
- package/src/tools/image-gen.ts +20 -6
- package/src/tools/index.ts +2 -0
- package/src/tools/irc.ts +5 -3
- package/src/tools/monitor.ts +9 -1
- package/src/tools/output-meta.ts +74 -5
- package/src/tools/python.ts +1 -1
- package/src/tools/read.ts +26 -37
- package/src/tools/recipe/runner.ts +23 -12
- package/src/tools/render-utils.ts +2 -2
- package/src/tools/report-issue.ts +184 -0
- package/src/tools/search.ts +3 -2
- package/src/tools/ssh.ts +274 -8
- package/src/tools/subagent-render.ts +114 -12
- package/src/tools/subagent.ts +118 -5
- package/src/tools/tmux-self-injection-guard.ts +3301 -122
- package/src/tools/todo-write.ts +41 -3
- package/src/tools/tool-catalog.generated.ts +32 -4
- package/src/tools/ultragoal-ask-guard.ts +13 -1
- package/src/tools/write.ts +42 -3
- package/src/tui/tree-list.ts +15 -1
- package/src/utils/commit-message-generator.ts +12 -4
- package/src/utils/external-editor.ts +21 -7
- package/src/utils/file-mentions.ts +75 -7
- package/src/utils/git.ts +38 -7
- package/src/utils/image-limits.ts +8 -0
- package/src/utils/image-loading.ts +1 -1
- package/src/utils/open.ts +73 -4
- package/src/utils/pasted-image-loading.ts +9 -8
- package/src/utils/prompt-suggestion.ts +5 -4
- package/src/utils/shell-snapshot.ts +9 -1
- package/src/utils/title-generator.ts +72 -22
- package/src/web/scrapers/index.ts +3 -1
- package/src/web/scrapers/types.ts +8 -0
- package/src/web/scrapers/youtube.ts +3 -2
- package/src/web/search/index.ts +2 -1
- package/src/web/search/providers/codex.ts +29 -32
- package/src/web/search/providers/insane.ts +91 -28
- package/src/web/search/providers/searxng.ts +62 -10
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
import {
|
|
10
10
|
Container,
|
|
11
11
|
fuzzyFilter,
|
|
12
|
+
fuzzyMatch,
|
|
12
13
|
getKeybindings,
|
|
13
14
|
Input,
|
|
14
15
|
matchesKey,
|
|
@@ -99,6 +100,150 @@ function computeModelRank(model: Model, roles: Record<string, RoleAssignment | u
|
|
|
99
100
|
return roles.default && modelsAreEqual(roles.default.model, model) ? 0 : 1;
|
|
100
101
|
}
|
|
101
102
|
|
|
103
|
+
/**
|
|
104
|
+
* Compute and assign fuzzy scores to model items based on a query.
|
|
105
|
+
* Scores are based on fuzzy matching against the model's searchable text.
|
|
106
|
+
*/
|
|
107
|
+
function fuzzyTokensScore(query: string, text: string): number | undefined {
|
|
108
|
+
const tokens = query
|
|
109
|
+
.trim()
|
|
110
|
+
.split(/\s+/)
|
|
111
|
+
.filter(token => token.length > 0);
|
|
112
|
+
if (tokens.length === 0) return undefined;
|
|
113
|
+
let total = 0;
|
|
114
|
+
for (const token of tokens) {
|
|
115
|
+
const match = fuzzyMatch(token, text);
|
|
116
|
+
if (!match.matches) return undefined;
|
|
117
|
+
total += match.score;
|
|
118
|
+
}
|
|
119
|
+
return total;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export function assignFuzzyScoresToModels(items: ModelItem[], query: string): void {
|
|
123
|
+
if (!query.trim()) {
|
|
124
|
+
for (const item of items) item.fuzzyScore = undefined;
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
for (const item of items) {
|
|
128
|
+
// Overwrite every item so a raw-query miss cannot retain an earlier score.
|
|
129
|
+
item.fuzzyScore = fuzzyTokensScore(query, `${item.id} ${item.provider}`);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Compute and assign fuzzy scores to canonical model items based on a query.
|
|
135
|
+
*/
|
|
136
|
+
export function assignFuzzyScoresToCanonicalModels(items: CanonicalModelItem[], query: string): void {
|
|
137
|
+
if (!query.trim()) {
|
|
138
|
+
for (const item of items) item.fuzzyScore = undefined;
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
for (const item of items) {
|
|
142
|
+
item.fuzzyScore = fuzzyTokensScore(query, item.searchText);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export interface RankedModelOrderContext {
|
|
147
|
+
roles: RoleAssignments;
|
|
148
|
+
mruIndex: ReadonlyMap<string, number>;
|
|
149
|
+
providerAuthStateById: ReadonlyMap<string, ProviderAuthState>;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const MODEL_DATE_RE = /-(\d{8})$/;
|
|
153
|
+
const MODEL_LATEST_RE = /-latest$/;
|
|
154
|
+
|
|
155
|
+
/** Ranking shared by the provider view: fuzzy quality, default, MRU, provider, recency. */
|
|
156
|
+
export function compareModelItemsForRanking(a: ModelItem, b: ModelItem, context: RankedModelOrderContext): number {
|
|
157
|
+
const { roles, mruIndex, providerAuthStateById } = context;
|
|
158
|
+
const aHasFuzzyScore = a.fuzzyScore !== undefined;
|
|
159
|
+
const bHasFuzzyScore = b.fuzzyScore !== undefined;
|
|
160
|
+
if (aHasFuzzyScore || bHasFuzzyScore) {
|
|
161
|
+
const aScore = a.fuzzyScore ?? Number.MAX_SAFE_INTEGER;
|
|
162
|
+
const bScore = b.fuzzyScore ?? Number.MAX_SAFE_INTEGER;
|
|
163
|
+
if (aScore !== bScore) return aScore - bScore;
|
|
164
|
+
// Ties keep the established default-first, then MRU/provider ordering.
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const aRank = computeModelRank(a.model, roles);
|
|
168
|
+
const bRank = computeModelRank(b.model, roles);
|
|
169
|
+
if (aRank !== bRank) return aRank - bRank;
|
|
170
|
+
|
|
171
|
+
const aMru = mruIndex.get(a.selector) ?? Number.MAX_SAFE_INTEGER;
|
|
172
|
+
const bMru = mruIndex.get(b.selector) ?? Number.MAX_SAFE_INTEGER;
|
|
173
|
+
if (aMru !== bMru) return aMru - bMru;
|
|
174
|
+
|
|
175
|
+
const providerCmp = compareRankedProviders(
|
|
176
|
+
{ id: a.provider, label: a.provider, authState: providerAuthStateById.get(a.provider) ?? "none" },
|
|
177
|
+
{ id: b.provider, label: b.provider, authState: providerAuthStateById.get(b.provider) ?? "none" },
|
|
178
|
+
);
|
|
179
|
+
if (providerCmp !== 0) return providerCmp;
|
|
180
|
+
|
|
181
|
+
// Priority field (lower = better, e.g. OpenAI code backend priority values)
|
|
182
|
+
const aPri = a.model.priority ?? Number.MAX_SAFE_INTEGER;
|
|
183
|
+
const bPri = b.model.priority ?? Number.MAX_SAFE_INTEGER;
|
|
184
|
+
if (aPri !== bPri) return aPri - bPri;
|
|
185
|
+
|
|
186
|
+
// Version number descending (higher version = better model)
|
|
187
|
+
const aVer = extractVersionNumber(a.id);
|
|
188
|
+
const bVer = extractVersionNumber(b.id);
|
|
189
|
+
if (aVer !== bVer) return bVer - aVer;
|
|
190
|
+
|
|
191
|
+
const aIsLatest = MODEL_LATEST_RE.test(a.id);
|
|
192
|
+
const bIsLatest = MODEL_LATEST_RE.test(b.id);
|
|
193
|
+
const aDate = a.id.match(MODEL_DATE_RE)?.[1] ?? "";
|
|
194
|
+
const bDate = b.id.match(MODEL_DATE_RE)?.[1] ?? "";
|
|
195
|
+
|
|
196
|
+
const aHasRecency = aIsLatest || aDate !== "";
|
|
197
|
+
const bHasRecency = bIsLatest || bDate !== "";
|
|
198
|
+
if (aHasRecency !== bHasRecency) return aHasRecency ? -1 : 1;
|
|
199
|
+
if (!aHasRecency) return a.id.localeCompare(b.id);
|
|
200
|
+
if (aIsLatest !== bIsLatest) return aIsLatest ? -1 : 1;
|
|
201
|
+
if (aDate && bDate) return bDate.localeCompare(aDate);
|
|
202
|
+
return aIsLatest ? -1 : bIsLatest ? 1 : a.id.localeCompare(b.id);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/** Ranking shared by the canonical view: fuzzy quality, default, MRU, provider, then id. */
|
|
206
|
+
export function compareCanonicalModelItemsForRanking(
|
|
207
|
+
a: CanonicalModelItem,
|
|
208
|
+
b: CanonicalModelItem,
|
|
209
|
+
context: RankedModelOrderContext,
|
|
210
|
+
): number {
|
|
211
|
+
const { roles, mruIndex, providerAuthStateById } = context;
|
|
212
|
+
const aHasFuzzyScore = a.fuzzyScore !== undefined;
|
|
213
|
+
const bHasFuzzyScore = b.fuzzyScore !== undefined;
|
|
214
|
+
if (aHasFuzzyScore || bHasFuzzyScore) {
|
|
215
|
+
const aScore = a.fuzzyScore ?? Number.MAX_SAFE_INTEGER;
|
|
216
|
+
const bScore = b.fuzzyScore ?? Number.MAX_SAFE_INTEGER;
|
|
217
|
+
if (aScore !== bScore) return aScore - bScore;
|
|
218
|
+
// Ties keep the established default-first, then MRU/provider ordering.
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
const aRank = computeModelRank(a.model, roles);
|
|
222
|
+
const bRank = computeModelRank(b.model, roles);
|
|
223
|
+
if (aRank !== bRank) return aRank - bRank;
|
|
224
|
+
|
|
225
|
+
const aKey = `${a.model.provider}/${a.model.id}`;
|
|
226
|
+
const bKey = `${b.model.provider}/${b.model.id}`;
|
|
227
|
+
const aMru = mruIndex.get(aKey) ?? Number.MAX_SAFE_INTEGER;
|
|
228
|
+
const bMru = mruIndex.get(bKey) ?? Number.MAX_SAFE_INTEGER;
|
|
229
|
+
if (aMru !== bMru) return aMru - bMru;
|
|
230
|
+
|
|
231
|
+
const providerCmp = compareRankedProviders(
|
|
232
|
+
{
|
|
233
|
+
id: a.model.provider,
|
|
234
|
+
label: a.model.provider,
|
|
235
|
+
authState: providerAuthStateById.get(a.model.provider) ?? "none",
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
id: b.model.provider,
|
|
239
|
+
label: b.model.provider,
|
|
240
|
+
authState: providerAuthStateById.get(b.model.provider) ?? "none",
|
|
241
|
+
},
|
|
242
|
+
);
|
|
243
|
+
if (providerCmp !== 0) return providerCmp;
|
|
244
|
+
return a.id.localeCompare(b.id);
|
|
245
|
+
}
|
|
246
|
+
|
|
102
247
|
interface ModelItem {
|
|
103
248
|
kind: "provider";
|
|
104
249
|
provider: string;
|
|
@@ -107,6 +252,7 @@ interface ModelItem {
|
|
|
107
252
|
selector: string;
|
|
108
253
|
thinkingLevel?: ThinkingLevel;
|
|
109
254
|
explicitThinkingLevel?: boolean;
|
|
255
|
+
fuzzyScore?: number;
|
|
110
256
|
}
|
|
111
257
|
|
|
112
258
|
interface CanonicalModelItem {
|
|
@@ -120,6 +266,7 @@ interface CanonicalModelItem {
|
|
|
120
266
|
compactSearchText: string;
|
|
121
267
|
thinkingLevel?: ThinkingLevel;
|
|
122
268
|
explicitThinkingLevel?: boolean;
|
|
269
|
+
fuzzyScore?: number;
|
|
123
270
|
}
|
|
124
271
|
|
|
125
272
|
type ScopedModelItem = ScopedModelSelection;
|
|
@@ -646,7 +793,7 @@ export class ModelSelectorComponent extends Container {
|
|
|
646
793
|
this.#configuredDefaultChain ?? normalizeModelSelectorValue(this.#settings.getModelRole("default"));
|
|
647
794
|
if (configuredChain.length < 2) return false;
|
|
648
795
|
|
|
649
|
-
const allModels = this.#modelRegistry.getAll();
|
|
796
|
+
const allModels = this.#modelRegistry.getAll(this.#authSessionId);
|
|
650
797
|
const matchPreferences = { usageOrder: this.#settings.getStorage()?.getModelUsageOrder() };
|
|
651
798
|
return configuredChain.slice(1).some(selector => {
|
|
652
799
|
const resolved = resolveModelRoleValue(selector, allModels, {
|
|
@@ -662,7 +809,7 @@ export class ModelSelectorComponent extends Container {
|
|
|
662
809
|
|
|
663
810
|
#loadRoleModels(): RoleAssignments {
|
|
664
811
|
const roles: RoleAssignments = {};
|
|
665
|
-
const allModels = this.#modelRegistry.getAll();
|
|
812
|
+
const allModels = this.#modelRegistry.getAll(this.#authSessionId);
|
|
666
813
|
const matchPreferences = { usageOrder: this.#settings.getStorage()?.getModelUsageOrder() };
|
|
667
814
|
const agentModelOverrides = this.#settings.get("task.agentModelOverrides");
|
|
668
815
|
const activeProfile = this.#activeModelProfile
|
|
@@ -738,7 +885,6 @@ export class ModelSelectorComponent extends Container {
|
|
|
738
885
|
}
|
|
739
886
|
|
|
740
887
|
#sortModels(models: ModelItem[], roles: RoleAssignments = this.#roles): void {
|
|
741
|
-
// Sort: default-tagged model first, then MRU, then provider ranking
|
|
742
888
|
const mruOrder = this.#settings.getStorage()?.getModelUsageOrder() ?? [];
|
|
743
889
|
const mruIndex = new Map(mruOrder.map((key, i) => [key, i]));
|
|
744
890
|
const providerAuthStateById = new Map<string, ProviderAuthState>();
|
|
@@ -747,74 +893,7 @@ export class ModelSelectorComponent extends Container {
|
|
|
747
893
|
providerAuthStateById.set(item.provider, this.#resolveProviderAuthState(item.provider));
|
|
748
894
|
}
|
|
749
895
|
}
|
|
750
|
-
|
|
751
|
-
const modelRank = (item: ModelItem) => computeModelRank(item.model, roles);
|
|
752
|
-
|
|
753
|
-
const dateRe = /-(\d{8})$/;
|
|
754
|
-
const latestRe = /-latest$/;
|
|
755
|
-
|
|
756
|
-
models.sort((a, b) => {
|
|
757
|
-
const aKey = a.selector;
|
|
758
|
-
const bKey = b.selector;
|
|
759
|
-
|
|
760
|
-
const aRank = modelRank(a);
|
|
761
|
-
const bRank = modelRank(b);
|
|
762
|
-
if (aRank !== bRank) return aRank - bRank;
|
|
763
|
-
|
|
764
|
-
// Then MRU order (models in mruIndex come before those not in it)
|
|
765
|
-
const aMru = mruIndex.get(aKey) ?? Number.MAX_SAFE_INTEGER;
|
|
766
|
-
const bMru = mruIndex.get(bKey) ?? Number.MAX_SAFE_INTEGER;
|
|
767
|
-
if (aMru !== bMru) return aMru - bMru;
|
|
768
|
-
|
|
769
|
-
// By provider, then recency within provider
|
|
770
|
-
const providerCmp = compareRankedProviders(
|
|
771
|
-
{
|
|
772
|
-
id: a.provider,
|
|
773
|
-
label: a.provider,
|
|
774
|
-
authState: providerAuthStateById.get(a.provider) ?? "none",
|
|
775
|
-
},
|
|
776
|
-
{
|
|
777
|
-
id: b.provider,
|
|
778
|
-
label: b.provider,
|
|
779
|
-
authState: providerAuthStateById.get(b.provider) ?? "none",
|
|
780
|
-
},
|
|
781
|
-
);
|
|
782
|
-
if (providerCmp !== 0) return providerCmp;
|
|
783
|
-
|
|
784
|
-
// Priority field (lower = better, e.g. OpenAI code backend priority values)
|
|
785
|
-
const aPri = a.model.priority ?? Number.MAX_SAFE_INTEGER;
|
|
786
|
-
const bPri = b.model.priority ?? Number.MAX_SAFE_INTEGER;
|
|
787
|
-
if (aPri !== bPri) return aPri - bPri;
|
|
788
|
-
|
|
789
|
-
// Version number descending (higher version = better model)
|
|
790
|
-
const aVer = extractVersionNumber(a.id);
|
|
791
|
-
const bVer = extractVersionNumber(b.id);
|
|
792
|
-
if (aVer !== bVer) return bVer - aVer;
|
|
793
|
-
|
|
794
|
-
const aIsLatest = latestRe.test(a.id);
|
|
795
|
-
const bIsLatest = latestRe.test(b.id);
|
|
796
|
-
const aDate = a.id.match(dateRe)?.[1] ?? "";
|
|
797
|
-
const bDate = b.id.match(dateRe)?.[1] ?? "";
|
|
798
|
-
|
|
799
|
-
// Both have dates or latest tags — sort by recency
|
|
800
|
-
const aHasRecency = aIsLatest || aDate !== "";
|
|
801
|
-
const bHasRecency = bIsLatest || bDate !== "";
|
|
802
|
-
|
|
803
|
-
// Models with recency info come before those without
|
|
804
|
-
if (aHasRecency !== bHasRecency) return aHasRecency ? -1 : 1;
|
|
805
|
-
|
|
806
|
-
// If neither has recency info, fall back to alphabetical
|
|
807
|
-
if (!aHasRecency) return a.id.localeCompare(b.id);
|
|
808
|
-
|
|
809
|
-
// -latest always sorts first within recency group
|
|
810
|
-
if (aIsLatest !== bIsLatest) return aIsLatest ? -1 : 1;
|
|
811
|
-
|
|
812
|
-
// Both have dates — descending (newest first)
|
|
813
|
-
if (aDate && bDate) return bDate.localeCompare(aDate);
|
|
814
|
-
|
|
815
|
-
// One has date, other is latest — latest first
|
|
816
|
-
return aIsLatest ? -1 : bIsLatest ? 1 : a.id.localeCompare(b.id);
|
|
817
|
-
});
|
|
896
|
+
models.sort((a, b) => compareModelItemsForRanking(a, b, { roles, mruIndex, providerAuthStateById }));
|
|
818
897
|
}
|
|
819
898
|
|
|
820
899
|
#sortCanonicalModels(models: CanonicalModelItem[], roles: RoleAssignments = this.#roles): void {
|
|
@@ -826,34 +905,7 @@ export class ModelSelectorComponent extends Container {
|
|
|
826
905
|
providerAuthStateById.set(item.model.provider, this.#resolveProviderAuthState(item.model.provider));
|
|
827
906
|
}
|
|
828
907
|
}
|
|
829
|
-
|
|
830
|
-
const modelRank = (item: CanonicalModelItem) => computeModelRank(item.model, roles);
|
|
831
|
-
|
|
832
|
-
models.sort((a, b) => {
|
|
833
|
-
const aRank = modelRank(a);
|
|
834
|
-
const bRank = modelRank(b);
|
|
835
|
-
if (aRank !== bRank) return aRank - bRank;
|
|
836
|
-
|
|
837
|
-
const aMru = mruIndex.get(`${a.model.provider}/${a.model.id}`) ?? Number.MAX_SAFE_INTEGER;
|
|
838
|
-
const bMru = mruIndex.get(`${b.model.provider}/${b.model.id}`) ?? Number.MAX_SAFE_INTEGER;
|
|
839
|
-
if (aMru !== bMru) return aMru - bMru;
|
|
840
|
-
|
|
841
|
-
const providerCmp = compareRankedProviders(
|
|
842
|
-
{
|
|
843
|
-
id: a.model.provider,
|
|
844
|
-
label: a.model.provider,
|
|
845
|
-
authState: providerAuthStateById.get(a.model.provider) ?? "none",
|
|
846
|
-
},
|
|
847
|
-
{
|
|
848
|
-
id: b.model.provider,
|
|
849
|
-
label: b.model.provider,
|
|
850
|
-
authState: providerAuthStateById.get(b.model.provider) ?? "none",
|
|
851
|
-
},
|
|
852
|
-
);
|
|
853
|
-
if (providerCmp !== 0) return providerCmp;
|
|
854
|
-
|
|
855
|
-
return a.id.localeCompare(b.id);
|
|
856
|
-
});
|
|
908
|
+
models.sort((a, b) => compareCanonicalModelItemsForRanking(a, b, { roles, mruIndex, providerAuthStateById }));
|
|
857
909
|
}
|
|
858
910
|
|
|
859
911
|
#buildScopedModelItems(): ModelItem[] {
|
|
@@ -869,7 +921,7 @@ export class ModelSelectorComponent extends Container {
|
|
|
869
921
|
}
|
|
870
922
|
|
|
871
923
|
#buildAvailableModelItems(): ModelItem[] {
|
|
872
|
-
return this.#modelRegistry.getAvailable().map((model: Model) => ({
|
|
924
|
+
return this.#modelRegistry.getAvailable(this.#authSessionId).map((model: Model) => ({
|
|
873
925
|
kind: "provider",
|
|
874
926
|
provider: model.provider,
|
|
875
927
|
id: model.id,
|
|
@@ -1205,10 +1257,12 @@ export class ModelSelectorComponent extends Container {
|
|
|
1205
1257
|
? alphaFiltered
|
|
1206
1258
|
: baseCanonicalModels;
|
|
1207
1259
|
const fuzzyMatches = fuzzyFilter(fuzzySource, query, ({ searchText }) => searchText);
|
|
1260
|
+
assignFuzzyScoresToCanonicalModels(fuzzyMatches, query);
|
|
1208
1261
|
this.#sortCanonicalModels(fuzzyMatches);
|
|
1209
1262
|
this.#filteredCanonicalModels = fuzzyMatches;
|
|
1210
1263
|
} else {
|
|
1211
1264
|
const fuzzyMatches = fuzzyFilter(baseModels, query, ({ id, provider }) => `${id} ${provider}`);
|
|
1265
|
+
assignFuzzyScoresToModels(fuzzyMatches, query);
|
|
1212
1266
|
this.#sortModels(fuzzyMatches);
|
|
1213
1267
|
this.#filteredModels = fuzzyMatches;
|
|
1214
1268
|
}
|
|
@@ -1256,7 +1310,7 @@ export class ModelSelectorComponent extends Container {
|
|
|
1256
1310
|
if (isInheritedRoleSelector(configuredSelector)) continue;
|
|
1257
1311
|
const selectors = resolveConfiguredModelPatterns(configuredSelector, this.#settings);
|
|
1258
1312
|
for (const selector of selectors.length > 0 ? selectors : [configuredSelector]) {
|
|
1259
|
-
const resolved = resolveModelRoleValue(selector, this.#modelRegistry.getAll(), {
|
|
1313
|
+
const resolved = resolveModelRoleValue(selector, this.#modelRegistry.getAll(this.#authSessionId), {
|
|
1260
1314
|
settings: this.#settings,
|
|
1261
1315
|
matchPreferences: { usageOrder: this.#settings.getStorage()?.getModelUsageOrder() },
|
|
1262
1316
|
modelRegistry: this.#modelRegistry,
|
|
@@ -1369,7 +1423,7 @@ export class ModelSelectorComponent extends Container {
|
|
|
1369
1423
|
}
|
|
1370
1424
|
|
|
1371
1425
|
#getProfileAvailableModels(): Model[] {
|
|
1372
|
-
return this.#modelRegistry.getAvailable();
|
|
1426
|
+
return this.#modelRegistry.getAvailable(this.#authSessionId);
|
|
1373
1427
|
}
|
|
1374
1428
|
|
|
1375
1429
|
#createProfileResolutionRegistry(availableModels: readonly Model[]) {
|
|
@@ -2108,7 +2162,7 @@ export class ModelSelectorComponent extends Container {
|
|
|
2108
2162
|
for (const role of PROFILE_ROLE_PREVIEW_ORDER) {
|
|
2109
2163
|
const selector = profile.modelMapping[role];
|
|
2110
2164
|
if (!selector) continue;
|
|
2111
|
-
const resolved = resolveModelRoleValue(selector, this.#modelRegistry.getAll(), {
|
|
2165
|
+
const resolved = resolveModelRoleValue(selector, this.#modelRegistry.getAll(this.#authSessionId), {
|
|
2112
2166
|
settings: this.#settings,
|
|
2113
2167
|
matchPreferences: { usageOrder: this.#settings.getStorage()?.getModelUsageOrder() },
|
|
2114
2168
|
modelRegistry: this.#modelRegistry,
|
|
@@ -108,9 +108,9 @@ class SelectSubmenu extends Container {
|
|
|
108
108
|
description: string,
|
|
109
109
|
options: ReadonlyArray<SelectItem>,
|
|
110
110
|
currentValue: string,
|
|
111
|
-
onSelect: (value: string) => void,
|
|
112
|
-
onCancel: () => void,
|
|
113
|
-
onSelectionChange?: (value: string) => void | Promise<void>,
|
|
111
|
+
private readonly onSelect: (value: string) => void,
|
|
112
|
+
private readonly onCancel: () => void,
|
|
113
|
+
private readonly onSelectionChange?: (value: string) => void | Promise<void>,
|
|
114
114
|
private readonly getPreview?: () => string,
|
|
115
115
|
) {
|
|
116
116
|
super();
|
|
@@ -137,46 +137,54 @@ class SelectSubmenu extends Container {
|
|
|
137
137
|
// Spacer
|
|
138
138
|
this.addChild(new Spacer(1));
|
|
139
139
|
|
|
140
|
-
|
|
141
|
-
this.#selectList
|
|
142
|
-
|
|
143
|
-
// Pre-select current value
|
|
144
|
-
const currentIndex = options.findIndex(o => o.value === currentValue);
|
|
145
|
-
if (currentIndex !== -1) {
|
|
146
|
-
this.#selectList.setSelectedIndex(currentIndex);
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
this.#selectList.onSelect = item => {
|
|
150
|
-
onSelect(item.value);
|
|
151
|
-
};
|
|
140
|
+
this.#selectList = this.#createSelectList(options, currentValue);
|
|
141
|
+
this.addChild(this.#selectList);
|
|
152
142
|
|
|
153
|
-
|
|
143
|
+
// Hint
|
|
144
|
+
this.addChild(new Spacer(1));
|
|
145
|
+
this.addChild(
|
|
146
|
+
new DynamicThemeText(() => theme.fg("dim", uiString(settings.get("ui.language"), "settings.selectHint"))),
|
|
147
|
+
);
|
|
148
|
+
}
|
|
154
149
|
|
|
155
|
-
|
|
156
|
-
|
|
150
|
+
#createSelectList(options: ReadonlyArray<SelectItem>, selectedValue?: string): SelectList {
|
|
151
|
+
const selectList = new SelectList(options, Math.min(options.length, 10), () => getSelectListTheme());
|
|
152
|
+
const selectedIndex = options.findIndex(option => option.value === selectedValue);
|
|
153
|
+
if (selectedIndex !== -1) selectList.setSelectedIndex(selectedIndex);
|
|
154
|
+
selectList.onSelect = item => this.onSelect(item.value);
|
|
155
|
+
selectList.onCancel = this.onCancel;
|
|
156
|
+
if (this.onSelectionChange) {
|
|
157
|
+
selectList.onSelectionChange = item => {
|
|
157
158
|
const requestId = ++this.#previewUpdateRequestId;
|
|
158
|
-
const result = onSelectionChange(item.value);
|
|
159
|
+
const result = this.onSelectionChange?.(item.value);
|
|
159
160
|
if (result && typeof (result as Promise<void>).then === "function") {
|
|
160
161
|
void (result as Promise<void>).finally(() => {
|
|
161
|
-
if (requestId === this.#previewUpdateRequestId)
|
|
162
|
-
this.#updatePreview();
|
|
163
|
-
}
|
|
162
|
+
if (requestId === this.#previewUpdateRequestId) this.#updatePreview();
|
|
164
163
|
});
|
|
165
164
|
return;
|
|
166
165
|
}
|
|
167
|
-
if (requestId === this.#previewUpdateRequestId)
|
|
168
|
-
this.#updatePreview();
|
|
169
|
-
}
|
|
166
|
+
if (requestId === this.#previewUpdateRequestId) this.#updatePreview();
|
|
170
167
|
};
|
|
171
168
|
}
|
|
169
|
+
return selectList;
|
|
170
|
+
}
|
|
172
171
|
|
|
173
|
-
|
|
172
|
+
refreshOptions(options: ReadonlyArray<SelectItem>, retainMissingSelection = false): void {
|
|
173
|
+
const previous = this.#selectList;
|
|
174
|
+
const selectedItem = previous.getSelectedItem();
|
|
175
|
+
if (retainMissingSelection && selectedItem && !options.some(option => option.value === selectedItem.value)) {
|
|
176
|
+
const label = selectedItem.label.endsWith(" (unavailable)")
|
|
177
|
+
? selectedItem.label
|
|
178
|
+
: `${selectedItem.label} (unavailable)`;
|
|
179
|
+
options = [...options, { ...selectedItem, label }];
|
|
180
|
+
}
|
|
181
|
+
const selectedValue = selectedItem?.value;
|
|
182
|
+
this.#selectList = this.#createSelectList(options, selectedValue);
|
|
183
|
+
this.replaceChildren(this.children.map(child => (child === previous ? this.#selectList : child)));
|
|
184
|
+
}
|
|
174
185
|
|
|
175
|
-
|
|
176
|
-
this
|
|
177
|
-
this.addChild(
|
|
178
|
-
new DynamicThemeText(() => theme.fg("dim", uiString(settings.get("ui.language"), "settings.selectHint"))),
|
|
179
|
-
);
|
|
186
|
+
refreshPreview(): void {
|
|
187
|
+
this.#updatePreview();
|
|
180
188
|
}
|
|
181
189
|
|
|
182
190
|
#updatePreview(): void {
|
|
@@ -1528,6 +1536,10 @@ export interface SettingsCallbacks {
|
|
|
1528
1536
|
onPetCommit?: (mode: string) => boolean;
|
|
1529
1537
|
/** Called for status line preview while configuring */
|
|
1530
1538
|
onStatusLinePreview?: (settings: StatusLinePreviewSettings) => void;
|
|
1539
|
+
/** Called when a status-line submenu begins an uncommitted preview. */
|
|
1540
|
+
onStatusLinePreviewStart?: () => void;
|
|
1541
|
+
/** Called when a status-line preview is committed, cancelled, or disposed. */
|
|
1542
|
+
onStatusLinePreviewEnd?: () => void;
|
|
1531
1543
|
/** Get current rendered status line for inline preview */
|
|
1532
1544
|
getStatusLinePreview?: (width?: number) => string;
|
|
1533
1545
|
/** Render a status-line preview for supplied draft settings without mutating the live status line. */
|
|
@@ -1582,6 +1594,8 @@ export class SettingsSelectorComponent extends Container {
|
|
|
1582
1594
|
#currentTabId: SettingTab | "plugins" | "gjc-bundles" = "appearance";
|
|
1583
1595
|
#textInputActive = false;
|
|
1584
1596
|
#activeProviderOrderEditor: Container | null = null;
|
|
1597
|
+
#activeSelectSubmenu: SelectSubmenu | null = null;
|
|
1598
|
+
#activeModelProfileSubmenu: SelectSubmenu | null = null;
|
|
1585
1599
|
|
|
1586
1600
|
constructor(
|
|
1587
1601
|
private readonly context: SettingsRuntimeContext,
|
|
@@ -1634,9 +1648,15 @@ export class SettingsSelectorComponent extends Container {
|
|
|
1634
1648
|
}
|
|
1635
1649
|
|
|
1636
1650
|
#switchToTab(tabId: SettingTab | "plugins" | "gjc-bundles"): void {
|
|
1651
|
+
if (this.#currentTabId === "appearance" && tabId !== "appearance") {
|
|
1652
|
+
this.callbacks.onStatusLinePreviewEnd?.();
|
|
1653
|
+
}
|
|
1637
1654
|
if (this.#currentTabId === "notifications" && tabId !== "notifications" && !this.#disposeNotificationsEditor()) {
|
|
1638
1655
|
return;
|
|
1639
1656
|
}
|
|
1657
|
+
this.#activeSelectSubmenu?.dispose();
|
|
1658
|
+
this.#activeSelectSubmenu = null;
|
|
1659
|
+
this.#activeModelProfileSubmenu = null;
|
|
1640
1660
|
// Release an open provider-order editor (and its context subscriptions)
|
|
1641
1661
|
// before switching tabs; the submenu's done() never runs on tab change,
|
|
1642
1662
|
// so without this the abandoned editor's listeners would survive.
|
|
@@ -1833,6 +1853,18 @@ export class SettingsSelectorComponent extends Container {
|
|
|
1833
1853
|
// Preview handlers
|
|
1834
1854
|
let onPreview: ((value: string) => void | Promise<void>) | undefined;
|
|
1835
1855
|
let onPreviewCancel: (() => void) | undefined;
|
|
1856
|
+
let onPreviewEnd: (() => void) | undefined;
|
|
1857
|
+
let statusLinePreviewStarted = false;
|
|
1858
|
+
const startStatusLinePreview = (): void => {
|
|
1859
|
+
if (statusLinePreviewStarted) return;
|
|
1860
|
+
statusLinePreviewStarted = true;
|
|
1861
|
+
this.callbacks.onStatusLinePreviewStart?.();
|
|
1862
|
+
};
|
|
1863
|
+
const endStatusLinePreview = (): void => {
|
|
1864
|
+
if (!statusLinePreviewStarted) return;
|
|
1865
|
+
statusLinePreviewStarted = false;
|
|
1866
|
+
this.callbacks.onStatusLinePreviewEnd?.();
|
|
1867
|
+
};
|
|
1836
1868
|
|
|
1837
1869
|
if (def.path === "theme.dark" || def.path === "theme.light") {
|
|
1838
1870
|
const activeThemeBeforePreview = getCurrentThemeName() ?? currentValue;
|
|
@@ -1844,6 +1876,7 @@ export class SettingsSelectorComponent extends Container {
|
|
|
1844
1876
|
};
|
|
1845
1877
|
} else if (def.path === "statusLine.preset") {
|
|
1846
1878
|
onPreview = value => {
|
|
1879
|
+
startStatusLinePreview();
|
|
1847
1880
|
const presetDef = getPreset(value as StatusLinePreset);
|
|
1848
1881
|
this.callbacks.onStatusLinePreview?.({
|
|
1849
1882
|
preset: value as StatusLinePreset,
|
|
@@ -1854,6 +1887,7 @@ export class SettingsSelectorComponent extends Container {
|
|
|
1854
1887
|
});
|
|
1855
1888
|
this.#updateStatusPreview();
|
|
1856
1889
|
};
|
|
1890
|
+
onPreviewEnd = endStatusLinePreview;
|
|
1857
1891
|
onPreviewCancel = () => {
|
|
1858
1892
|
const currentPreset = settings.get("statusLine.preset");
|
|
1859
1893
|
const presetDef = getPreset(currentPreset);
|
|
@@ -1880,9 +1914,11 @@ export class SettingsSelectorComponent extends Container {
|
|
|
1880
1914
|
};
|
|
1881
1915
|
} else if (def.path === "statusLine.separator") {
|
|
1882
1916
|
onPreview = value => {
|
|
1917
|
+
startStatusLinePreview();
|
|
1883
1918
|
this.callbacks.onStatusLinePreview?.({ separator: value as StatusLineSeparatorStyle });
|
|
1884
1919
|
this.#updateStatusPreview();
|
|
1885
1920
|
};
|
|
1921
|
+
onPreviewEnd = endStatusLinePreview;
|
|
1886
1922
|
onPreviewCancel = () => {
|
|
1887
1923
|
const separator = settings.get("statusLine.separator");
|
|
1888
1924
|
this.callbacks.onStatusLinePreview?.({ separator, previewHighlightSegment: undefined });
|
|
@@ -1890,9 +1926,11 @@ export class SettingsSelectorComponent extends Container {
|
|
|
1890
1926
|
};
|
|
1891
1927
|
} else if (def.path === "statusLine.maxRows") {
|
|
1892
1928
|
onPreview = value => {
|
|
1929
|
+
startStatusLinePreview();
|
|
1893
1930
|
this.callbacks.onStatusLinePreview?.({ maxRows: Number(value) });
|
|
1894
1931
|
this.#updateStatusPreview();
|
|
1895
1932
|
};
|
|
1933
|
+
onPreviewEnd = endStatusLinePreview;
|
|
1896
1934
|
onPreviewCancel = () => {
|
|
1897
1935
|
this.callbacks.onStatusLinePreview?.({
|
|
1898
1936
|
maxRows: settings.get("statusLine.maxRows"),
|
|
@@ -1914,7 +1952,14 @@ export class SettingsSelectorComponent extends Container {
|
|
|
1914
1952
|
const isThemeSetting = def.path === "theme.dark" || def.path === "theme.light";
|
|
1915
1953
|
const getPreview = isThemeSetting ? this.callbacks.getStatusLinePreview : undefined;
|
|
1916
1954
|
|
|
1917
|
-
|
|
1955
|
+
let submenu: SelectSubmenu;
|
|
1956
|
+
const finish = (value?: string): void => {
|
|
1957
|
+
if (this.#activeSelectSubmenu === submenu) this.#activeSelectSubmenu = null;
|
|
1958
|
+
if (this.#activeModelProfileSubmenu === submenu) this.#activeModelProfileSubmenu = null;
|
|
1959
|
+
submenu.dispose();
|
|
1960
|
+
done(value);
|
|
1961
|
+
};
|
|
1962
|
+
submenu = new SelectSubmenu(
|
|
1918
1963
|
title,
|
|
1919
1964
|
description,
|
|
1920
1965
|
options,
|
|
@@ -1922,7 +1967,7 @@ export class SettingsSelectorComponent extends Container {
|
|
|
1922
1967
|
value => {
|
|
1923
1968
|
if (def.path === "modelProfile.default") {
|
|
1924
1969
|
this.callbacks.onChange(def.path, value);
|
|
1925
|
-
|
|
1970
|
+
finish(value);
|
|
1926
1971
|
return;
|
|
1927
1972
|
}
|
|
1928
1973
|
if (def.path === "theme.dark" || def.path === "theme.light") {
|
|
@@ -1937,7 +1982,7 @@ export class SettingsSelectorComponent extends Container {
|
|
|
1937
1982
|
}
|
|
1938
1983
|
if (!this.callbacks.onThemeCommit) return;
|
|
1939
1984
|
void this.callbacks.onThemeCommit(def.path, value, currentValue).then(accepted => {
|
|
1940
|
-
if (accepted)
|
|
1985
|
+
if (accepted) finish(value);
|
|
1941
1986
|
});
|
|
1942
1987
|
return;
|
|
1943
1988
|
}
|
|
@@ -1953,21 +1998,26 @@ export class SettingsSelectorComponent extends Container {
|
|
|
1953
1998
|
) {
|
|
1954
1999
|
return;
|
|
1955
2000
|
}
|
|
1956
|
-
|
|
2001
|
+
finish(accepted ? value : undefined);
|
|
1957
2002
|
return;
|
|
1958
2003
|
}
|
|
1959
2004
|
if (!commitInteractiveSettings(this.callbacks, () => this.#setSettingValue(def.path, value))) return;
|
|
1960
2005
|
this.callbacks.onChange(def.path, value);
|
|
1961
2006
|
if (def.path === "ui.language") this.#refreshTabBarLanguage();
|
|
1962
|
-
|
|
2007
|
+
onPreviewEnd?.();
|
|
2008
|
+
finish(value);
|
|
1963
2009
|
},
|
|
1964
2010
|
() => {
|
|
1965
2011
|
onPreviewCancel?.();
|
|
1966
|
-
|
|
2012
|
+
onPreviewEnd?.();
|
|
2013
|
+
finish();
|
|
1967
2014
|
},
|
|
1968
2015
|
onPreview,
|
|
1969
2016
|
getPreview,
|
|
1970
2017
|
);
|
|
2018
|
+
this.#activeSelectSubmenu = submenu;
|
|
2019
|
+
if (def.path === "modelProfile.default") this.#activeModelProfileSubmenu = submenu;
|
|
2020
|
+
return submenu;
|
|
1971
2021
|
}
|
|
1972
2022
|
|
|
1973
2023
|
/**
|
|
@@ -2277,8 +2327,24 @@ export class SettingsSelectorComponent extends Container {
|
|
|
2277
2327
|
return (this.#currentList || this.#pluginComponent || this.#gjcBundleComponent || this.#notificationsEditor)!;
|
|
2278
2328
|
}
|
|
2279
2329
|
|
|
2330
|
+
/** Refresh saved rows and model-profile choices without replacing active editors. */
|
|
2331
|
+
refreshFromConfiguration(availableModelProfiles: readonly string[]): void {
|
|
2332
|
+
this.context.availableModelProfiles = [...availableModelProfiles];
|
|
2333
|
+
this.#refreshCurrentTabItems();
|
|
2334
|
+
this.#activeModelProfileSubmenu?.refreshOptions(
|
|
2335
|
+
this.context.availableModelProfiles.map(profile => ({ value: profile, label: profile })),
|
|
2336
|
+
true,
|
|
2337
|
+
);
|
|
2338
|
+
this.#activeSelectSubmenu?.refreshPreview();
|
|
2339
|
+
this.#updateStatusPreview();
|
|
2340
|
+
}
|
|
2341
|
+
|
|
2280
2342
|
override dispose(): void {
|
|
2281
2343
|
if (this.#notificationsEditor?.navigationLocked) return;
|
|
2344
|
+
this.callbacks.onStatusLinePreviewEnd?.();
|
|
2345
|
+
this.#activeSelectSubmenu?.dispose();
|
|
2346
|
+
this.#activeSelectSubmenu = null;
|
|
2347
|
+
this.#activeModelProfileSubmenu = null;
|
|
2282
2348
|
// Release an open provider-order editor (and its context subscriptions)
|
|
2283
2349
|
// when the whole selector is torn down without a normal close.
|
|
2284
2350
|
this.#activeProviderOrderEditor?.dispose();
|
|
@@ -3,6 +3,7 @@ import { APP_NAME } from "@gajae-code/utils";
|
|
|
3
3
|
import { formatBuildLabel } from "../../build-metadata";
|
|
4
4
|
import { formatKeyHint, type KeyDisplayContext } from "../../config/keybindings";
|
|
5
5
|
import { type ThemeColor, theme } from "../../modes/theme/theme";
|
|
6
|
+
import { sanitizeStatusText } from "../shared";
|
|
6
7
|
|
|
7
8
|
export interface RecentSession {
|
|
8
9
|
name: string;
|
|
@@ -536,7 +537,8 @@ export class WelcomeComponent implements Component {
|
|
|
536
537
|
}
|
|
537
538
|
|
|
538
539
|
#pill(icon: string, text: string, color: ThemeColor): string {
|
|
539
|
-
|
|
540
|
+
const safeText = sanitizeStatusText(text);
|
|
541
|
+
return `${theme.fg("borderMuted", "[")} ${theme.fg(color, icon)} ${theme.fg("muted", safeText)} ${theme.fg(
|
|
540
542
|
"borderMuted",
|
|
541
543
|
"]",
|
|
542
544
|
)}`;
|