@gajae-code/coding-agent 0.18.7 → 0.18.9
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 +377 -1
- package/dist/types/async/endpoint-id.d.ts +16 -0
- package/dist/types/async/job-manager.d.ts +1 -1
- package/dist/types/async/support.d.ts +0 -14
- package/dist/types/capability/mcp.d.ts +2 -0
- package/dist/types/capability/skill.d.ts +2 -0
- package/dist/types/capability/types.d.ts +2 -0
- package/dist/types/cli/public-command-errors.d.ts +3 -1
- package/dist/types/cli/setup-cli.d.ts +1 -1
- package/dist/types/commands/deep-interview.d.ts +3 -0
- package/dist/types/commands/mcp-serve.d.ts +4 -0
- package/dist/types/config/autorouting-tier-map.d.ts +348 -9
- package/dist/types/config/file-lock.d.ts +1 -0
- package/dist/types/config/model-bindings-applier.d.ts +2 -0
- package/dist/types/config/model-profile-activation.d.ts +11 -3
- package/dist/types/config/model-registry.d.ts +4 -9
- package/dist/types/config/skill-settings-defaults.d.ts +2 -0
- package/dist/types/cursor-delete-path.d.ts +1 -0
- package/dist/types/cursor-mcp-name.d.ts +8 -0
- package/dist/types/customization/inventory.d.ts +2 -0
- package/dist/types/debug/report-bundle-parent.d.ts +2 -0
- package/dist/types/defaults/gjc/extensions/grok-cli-vendor/src/provider/stream.d.ts +1 -0
- package/dist/types/defaults/gjc/extensions/grok-cli-vendor/src/provider/version-manager.d.ts +31 -0
- package/dist/types/defaults/gjc-skills.generated.d.ts +5 -6
- package/dist/types/discovery/helpers.d.ts +6 -1
- package/dist/types/discovery/mcp-json.d.ts +1 -0
- package/dist/types/eval/py/kernel.d.ts +18 -0
- package/dist/types/export/html/css-color.d.ts +2 -0
- package/dist/types/export/html/html-export-destination.d.ts +2 -0
- package/dist/types/export/html/template.generated.d.ts +1 -1
- package/dist/types/extensibility/extensions/function-hooks-internal.d.ts +5 -0
- package/dist/types/extensibility/extensions/types.d.ts +7 -0
- package/dist/types/extensibility/gjc-plugins/runtime-adapters.d.ts +14 -1
- package/dist/types/extensibility/plugins/marketplace/cache.d.ts +2 -0
- package/dist/types/extensibility/plugins/plugin-link-path.d.ts +2 -0
- package/dist/types/extensibility/runtime-skill-discovery.d.ts +3 -1
- package/dist/types/extensibility/skill-management.d.ts +4 -1
- package/dist/types/extensibility/skills.d.ts +2 -0
- package/dist/types/gjc-runtime/deep-interview-crystallize.d.ts +74 -0
- package/dist/types/gjc-runtime/deep-interview-runtime.d.ts +11 -0
- package/dist/types/gjc-runtime/gc-runtime.d.ts +5 -0
- package/dist/types/gjc-runtime/psmux-detect.d.ts +3 -3
- package/dist/types/gjc-runtime/ralplan-runtime.d.ts +0 -5
- package/dist/types/gjc-runtime/sidecar-bootstrap-env.d.ts +6 -0
- package/dist/types/gjc-runtime/state-argv.d.ts +1 -1
- package/dist/types/gjc-runtime/state-migrations.d.ts +8 -0
- package/dist/types/gjc-runtime/state-runtime.d.ts +95 -0
- package/dist/types/gjc-runtime/state-writer.d.ts +14 -1
- package/dist/types/gjc-runtime/tmux-common.d.ts +8 -5
- package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +8 -0
- package/dist/types/internal-urls/skill-path.d.ts +1 -0
- package/dist/types/lsp/config.d.ts +8 -5
- package/dist/types/lsp/workspace-path.d.ts +1 -0
- package/dist/types/modes/acp/acp-agent.d.ts +7 -0
- package/dist/types/modes/components/custom-editor.d.ts +6 -0
- package/dist/types/modes/components/customization/customization-dashboard.d.ts +1 -0
- package/dist/types/modes/components/extensions/state-manager.d.ts +4 -3
- package/dist/types/modes/controllers/input-controller.d.ts +9 -0
- package/dist/types/modes/interactive-mode.d.ts +1 -0
- package/dist/types/modes/utils/interrupt-ownership.d.ts +3 -0
- package/dist/types/modes/utils/keybinding-matchers.d.ts +1 -0
- package/dist/types/modes/utils/macos-option-forwarding.d.ts +17 -0
- package/dist/types/progress/collect-project-progress.d.ts +38 -0
- package/dist/types/progress/progress-contract.d.ts +154 -0
- package/dist/types/progress/progress-snapshot.d.ts +11 -0
- package/dist/types/progress/project-progress.d.ts +141 -0
- package/dist/types/progress/render-progress.d.ts +28 -0
- package/dist/types/runtime-mcp/manager.d.ts +2 -1
- package/dist/types/runtime-mcp/mcp-redirect.d.ts +9 -0
- package/dist/types/runtime-mcp/oauth-public-url.d.ts +3 -0
- package/dist/types/runtime-mcp/plugin-network-boundary.d.ts +1 -0
- package/dist/types/runtime-mcp/project-host-values.d.ts +27 -0
- package/dist/types/runtime-mcp/smithery-registry.d.ts +24 -0
- package/dist/types/runtime-mcp/types.d.ts +6 -0
- package/dist/types/sdk/acp/adapter.d.ts +1 -1
- package/dist/types/sdk/broker/broker-exit.d.ts +6 -2
- package/dist/types/sdk/broker/broker.d.ts +24 -2
- package/dist/types/sdk/broker/doctor-restart.d.ts +5 -0
- package/dist/types/sdk/broker/ensure.d.ts +14 -1
- package/dist/types/sdk/broker/session-index.d.ts +12 -6
- package/dist/types/sdk/bus/index.d.ts +12 -1
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +6 -1
- package/dist/types/sdk/client/client.d.ts +2 -0
- package/dist/types/sdk/host/query/handlers.d.ts +3 -0
- package/dist/types/sdk/index.d.ts +1 -0
- package/dist/types/sdk/router/session-router.d.ts +2 -0
- package/dist/types/sdk/session-list.d.ts +1 -1
- package/dist/types/sdk/session.d.ts +8 -0
- package/dist/types/session/agent-session.d.ts +38 -9
- package/dist/types/session/artifacts.d.ts +2 -2
- package/dist/types/session/internal/managed-gc-retirement-codec.d.ts +32 -0
- package/dist/types/session/internal/managed-session-scope.d.ts +79 -2
- package/dist/types/session/internal/managed-session-storage.d.ts +26 -1
- package/dist/types/session/internal/managed-task-owner-cleanup.d.ts +62 -0
- package/dist/types/session/internal/task-artifact-owner-access.d.ts +2 -0
- package/dist/types/session/internal/task-artifact-owner-transcript.d.ts +9 -1
- package/dist/types/session/session-manager.d.ts +31 -5
- package/dist/types/session/session-retirement.d.ts +31 -7
- package/dist/types/session/session-storage.d.ts +69 -2
- package/dist/types/session/task-artifact-owner-codec.d.ts +2 -0
- package/dist/types/setup/credential-auto-import.d.ts +1 -1
- package/dist/types/setup/credential-import.d.ts +6 -4
- package/dist/types/skill-state/active-state.d.ts +38 -0
- package/dist/types/skill-state/workflow-mutation-guard.d.ts +3 -0
- package/dist/types/slash-commands/helpers/progress-report.d.ts +8 -0
- package/dist/types/task/executor.d.ts +3 -0
- package/dist/types/task/isolation-dir.d.ts +26 -0
- package/dist/types/tools/ast-edit-write-path.d.ts +13 -0
- package/dist/types/tools/bash-skill-urls.d.ts +1 -1
- package/dist/types/tools/browser/cdp-url.d.ts +2 -0
- package/dist/types/tools/github-side-effect.d.ts +22 -0
- package/dist/types/tools/index.d.ts +3 -0
- package/dist/types/tools/monitor-mutation.d.ts +9 -0
- package/dist/types/tools/python.d.ts +9 -1
- package/dist/types/tools/recipe/recipe-guard.d.ts +7 -0
- package/dist/types/tools/restricted-cwd.d.ts +1 -0
- package/dist/types/tools/todo-write.d.ts +6 -0
- package/dist/types/utils/tools-checksum.d.ts +7 -0
- package/package.json +7 -7
- package/scripts/generate-sdk-operation-inventory.ts +21 -0
- package/scripts/verify-managed-empty-stop.ts +28 -0
- package/src/async/endpoint-id.ts +26 -0
- package/src/async/job-manager.ts +247 -132
- package/src/async/support.ts +0 -25
- package/src/capability/index.ts +15 -0
- package/src/capability/mcp.ts +2 -0
- package/src/capability/skill.ts +2 -0
- package/src/capability/types.ts +2 -0
- package/src/cli/auth-broker-cli.ts +1 -1
- package/src/cli/customize-doctor.ts +15 -2
- package/src/cli/doctor/repairs.ts +4 -1
- package/src/cli/doctor-supervisor.ts +3 -0
- package/src/cli/public-command-errors.ts +21 -1
- package/src/cli/public-command-registry.ts +28 -6
- package/src/cli/setup-cli.ts +4 -4
- package/src/cli/skills-cli.ts +5 -0
- package/src/commands/deep-interview.ts +47 -8
- package/src/commands/mcp-serve.ts +7 -0
- package/src/commands/sdk.ts +455 -397
- package/src/config/autorouting-tier-map.ts +117 -7
- package/src/config/file-lock.ts +316 -79
- package/src/config/mcp-schema.json +4 -0
- package/src/config/model-bindings-applier.ts +20 -0
- package/src/config/model-profile-activation.ts +240 -46
- package/src/config/model-registry.ts +47 -153
- package/src/config/skill-settings-defaults.ts +7 -0
- package/src/coordinator-mcp/policy.ts +3 -2
- package/src/coordinator-mcp/server.ts +2 -0
- package/src/cursor-delete-path.ts +10 -0
- package/src/cursor-mcp-name.ts +15 -0
- package/src/cursor.ts +13 -2
- package/src/customization/inventory.ts +4 -13
- package/src/dap/config.ts +2 -2
- package/src/debug/report-bundle-parent.ts +22 -0
- package/src/debug/report-bundle.ts +3 -0
- package/src/debug/system-info.ts +13 -1
- package/src/defaults/gjc/extensions/grok-cli-vendor/src/provider/register.ts +10 -6
- package/src/defaults/gjc/extensions/grok-cli-vendor/src/provider/stream.ts +67 -4
- package/src/defaults/gjc/extensions/grok-cli-vendor/src/provider/version-manager.ts +80 -0
- package/src/defaults/gjc/skills/deep-interview/SKILL.md +105 -10
- package/src/defaults/gjc/skills/ralplan/SKILL.md +6 -4
- package/src/defaults/gjc-defaults.test.ts +18 -1
- package/src/defaults/gjc-defaults.ts +3 -0
- package/src/defaults/gjc-skills.generated.ts +58 -36
- package/src/discovery/agents.ts +6 -1
- package/src/discovery/builtin.ts +13 -1
- package/src/discovery/helpers.ts +171 -29
- package/src/discovery/mcp-json.ts +26 -12
- package/src/discovery/ssh.ts +1 -1
- package/src/discovery/substitute-plugin-root.ts +3 -1
- package/src/edit/file-read-cache.ts +1 -1
- package/src/eval/py/executor.ts +796 -154
- package/src/eval/py/kernel.ts +79 -13
- package/src/eval/py/tool-bridge.ts +4 -0
- package/src/export/html/css-color.ts +9 -0
- package/src/export/html/html-export-destination.ts +16 -0
- package/src/export/html/index.ts +7 -10
- package/src/export/html/template.generated.ts +1 -1
- package/src/extensibility/extensions/function-hooks-internal.ts +27 -0
- package/src/extensibility/extensions/runner.ts +15 -1
- package/src/extensibility/extensions/types.ts +7 -0
- package/src/extensibility/gjc-plugins/mcp-policy.ts +2 -1
- package/src/extensibility/gjc-plugins/runtime-adapters.ts +85 -8
- package/src/extensibility/plugins/manager.ts +3 -2
- package/src/extensibility/plugins/marketplace/cache.ts +15 -0
- package/src/extensibility/plugins/marketplace/manager.ts +11 -3
- package/src/extensibility/plugins/plugin-link-path.ts +12 -0
- package/src/extensibility/runtime-skill-discovery.ts +20 -2
- package/src/extensibility/skill-management.ts +9 -2
- package/src/extensibility/skills.ts +6 -1
- package/src/gjc-runtime/deep-interview-crystallize.ts +1814 -0
- package/src/gjc-runtime/deep-interview-recorder.ts +20 -2
- package/src/gjc-runtime/deep-interview-runtime.ts +1415 -13
- package/src/gjc-runtime/deep-interview-stage.ts +98 -21
- package/src/gjc-runtime/gc-runtime.ts +206 -9
- package/src/gjc-runtime/launch-worktree.ts +70 -9
- package/src/gjc-runtime/psmux-detect.ts +28 -4
- package/src/gjc-runtime/ralplan-runtime.ts +447 -52
- package/src/gjc-runtime/session-state-sidecar.ts +3 -2
- package/src/gjc-runtime/sidecar-bootstrap-env.ts +19 -0
- package/src/gjc-runtime/state-argv.ts +2 -0
- package/src/gjc-runtime/state-migrations.ts +91 -29
- package/src/gjc-runtime/state-runtime.ts +3716 -135
- package/src/gjc-runtime/state-writer.ts +105 -16
- package/src/gjc-runtime/tmux-common.ts +8 -5
- package/src/gjc-runtime/ultragoal-runtime.ts +16 -4
- package/src/gjc-runtime/workflow-manifest.generated.json +70 -42
- package/src/gjc-runtime/workflow-manifest.ts +54 -21
- package/src/harness-control-plane/operate.ts +12 -4
- package/src/harness-control-plane/owner.ts +5 -1
- package/src/hashline/parser.ts +48 -9
- package/src/hashline/recovery.ts +13 -4
- package/src/internal-urls/docs-index.generated.ts +20 -19
- package/src/internal-urls/skill-path.ts +19 -0
- package/src/internal-urls/skill-protocol.ts +2 -0
- package/src/lsp/config.ts +12 -63
- package/src/lsp/edits.ts +6 -0
- package/src/lsp/workspace-path.ts +51 -0
- package/src/main.ts +195 -31
- package/src/memories/index.ts +88 -7
- package/src/modes/acp/acp-agent.ts +88 -4
- package/src/modes/components/custom-editor.ts +14 -0
- package/src/modes/components/customization/customization-dashboard.ts +12 -0
- package/src/modes/components/extensions/extension-dashboard.ts +2 -2
- package/src/modes/components/extensions/state-manager.ts +15 -5
- package/src/modes/components/hook-editor.ts +1 -1
- package/src/modes/components/hook-selector.ts +1 -1
- package/src/modes/components/model-selector.ts +1 -4
- package/src/modes/components/provider-onboarding-selector.ts +1 -1
- package/src/modes/components/status-line/segments.ts +4 -0
- package/src/modes/controllers/event-controller.ts +11 -4
- package/src/modes/controllers/input-controller.ts +76 -31
- package/src/modes/controllers/runtime-mcp-command-controller.ts +29 -16
- package/src/modes/controllers/selector-controller.ts +24 -15
- package/src/modes/controllers/todo-command-controller.ts +1 -1
- package/src/modes/interactive-mode.ts +5 -1
- package/src/modes/runtime-init.ts +4 -0
- package/src/modes/utils/abort-message.ts +3 -1
- package/src/modes/utils/interrupt-ownership.ts +12 -0
- package/src/modes/utils/keybinding-matchers.ts +4 -0
- package/src/modes/utils/macos-option-forwarding.ts +80 -0
- package/src/progress/collect-project-progress.ts +153 -0
- package/src/progress/progress-contract.ts +172 -0
- package/src/progress/progress-snapshot.ts +140 -0
- package/src/progress/project-progress.ts +446 -0
- package/src/progress/render-progress.ts +209 -0
- package/src/prompts/system/master-mode.md +1 -0
- package/src/prompts/tools/skill-discovery.md +1 -1
- package/src/runtime-mcp/client.ts +4 -2
- package/src/runtime-mcp/config-writer.ts +10 -6
- package/src/runtime-mcp/config.ts +1 -0
- package/src/runtime-mcp/json-rpc.ts +2 -1
- package/src/runtime-mcp/manager.ts +29 -11
- package/src/runtime-mcp/mcp-redirect.ts +73 -0
- package/src/runtime-mcp/oauth-flow.ts +14 -2
- package/src/runtime-mcp/oauth-public-url.ts +14 -0
- package/src/runtime-mcp/plugin-network-boundary.ts +4 -0
- package/src/runtime-mcp/pool.ts +6 -0
- package/src/runtime-mcp/project-host-values.ts +46 -0
- package/src/runtime-mcp/smithery-registry.ts +22 -3
- package/src/runtime-mcp/transports/http.ts +4 -3
- package/src/runtime-mcp/types.ts +6 -0
- package/src/sdk/acp/adapter.ts +95 -8
- package/src/sdk/broker/broker-exit.ts +52 -23
- package/src/sdk/broker/broker.ts +81 -6
- package/src/sdk/broker/doctor-restart.ts +4 -0
- package/src/sdk/broker/ensure.ts +31 -2
- package/src/sdk/broker/lifecycle.ts +711 -66
- package/src/sdk/broker/session-index.ts +191 -81
- package/src/sdk/bus/chat-daemon-cli.ts +38 -1
- package/src/sdk/bus/chat-daemon-control.ts +2 -2
- package/src/sdk/bus/index.ts +238 -43
- package/src/sdk/bus/telegram-daemon-contract.ts +6 -1
- package/src/sdk/cli/session-cli.ts +17 -3
- package/src/sdk/client/client.ts +28 -8
- package/src/sdk/host/query/handlers.ts +9 -1
- package/src/sdk/host/session-runtime.test.ts +2705 -303
- package/src/sdk/host/session-runtime.ts +490 -143
- package/src/sdk/host/surface-policy.ts +1 -0
- package/src/sdk/index.ts +8 -0
- package/src/sdk/lifecycle-session.ts +3 -1
- package/src/sdk/prompt-deadline-manager.ts +15 -0
- package/src/sdk/protocol/operation-inventory.generated.json +146 -0
- package/src/sdk/protocol/operation-registry.ts +9 -2
- package/src/sdk/router/session-router.ts +82 -18
- package/src/sdk/session-list.ts +1 -0
- package/src/sdk/session.ts +69 -45
- package/src/session/agent-session.ts +679 -238
- package/src/session/artifacts.ts +176 -71
- package/src/session/internal/managed-gc-retirement-codec.ts +319 -0
- package/src/session/internal/managed-session-scope.ts +3779 -462
- package/src/session/internal/managed-session-storage.ts +501 -78
- package/src/session/internal/managed-task-owner-cleanup.ts +473 -0
- package/src/session/internal/task-artifact-owner-access.ts +19 -3
- package/src/session/internal/task-artifact-owner-transcript.ts +547 -1
- package/src/session/session-manager.ts +951 -133
- package/src/session/session-retirement.ts +573 -14
- package/src/session/session-storage.ts +447 -15
- package/src/session/task-artifact-owner-codec.ts +71 -8
- package/src/session/task-artifact-owner-retirement.ts +21 -19
- package/src/setup/credential-auto-import.ts +12 -3
- package/src/setup/credential-import.ts +176 -5
- package/src/setup/paseo/announce.ts +6 -1
- package/src/skill-state/active-state.ts +145 -2
- package/src/skill-state/workflow-mutation-guard.ts +102 -10
- package/src/slash-commands/builtin-registry.ts +39 -9
- package/src/slash-commands/helpers/mcp.ts +8 -4
- package/src/slash-commands/helpers/progress-report.ts +23 -0
- package/src/stt/setup.ts +3 -5
- package/src/task/commands.ts +3 -1
- package/src/task/executor.ts +4 -0
- package/src/task/index.ts +6 -0
- package/src/task/isolation-dir.ts +143 -0
- package/src/task/worktree.ts +16 -7
- package/src/tools/ask.ts +205 -6
- package/src/tools/ast-edit-write-path.ts +68 -0
- package/src/tools/ast-edit.ts +10 -1
- package/src/tools/bash-allowed-prefixes.ts +15 -0
- package/src/tools/bash-skill-urls.ts +56 -3
- package/src/tools/bash.ts +48 -79
- package/src/tools/browser/cdp-url.ts +18 -0
- package/src/tools/browser.ts +8 -1
- package/src/tools/descriptors.ts +5 -1
- package/src/tools/eval.ts +56 -36
- package/src/tools/gh.ts +10 -0
- package/src/tools/github-side-effect.ts +112 -0
- package/src/tools/image-gen.ts +1 -1
- package/src/tools/index.ts +3 -0
- package/src/tools/monitor-mutation.ts +27 -0
- package/src/tools/monitor.ts +7 -0
- package/src/tools/python.ts +188 -66
- package/src/tools/recipe/index.ts +9 -0
- package/src/tools/recipe/recipe-guard.ts +19 -0
- package/src/tools/restricted-cwd.ts +10 -0
- package/src/tools/skill-discovery.ts +5 -0
- package/src/tools/skill.ts +28 -1
- package/src/tools/todo-write.ts +10 -1
- package/src/tools/tool-catalog.generated.ts +1 -1
- package/src/tools/write.ts +1 -0
- package/src/utils/external-editor.ts +3 -2
- package/src/utils/tools-checksum.ts +34 -0
- package/src/utils/tools-manager.ts +24 -6
- package/src/web/insane/url-guard.ts +2 -1
- package/src/web/search/providers/codex.ts +3 -2
|
@@ -40,7 +40,9 @@ import { CommandPalette, type CommandPaletteAction, type CommandPaletteEntry } f
|
|
|
40
40
|
import type { PasteTextContext } from "../components/custom-editor";
|
|
41
41
|
import { QueuePaneComponent } from "../components/queue-pane";
|
|
42
42
|
import { type QueuedMessageMoveDirection, QueuedMessageSelectorComponent } from "../components/queued-message-selector";
|
|
43
|
+
import { focusedUiOwnsInterrupt } from "../utils/interrupt-ownership";
|
|
43
44
|
import { matchesAppInterrupt } from "../utils/keybinding-matchers";
|
|
45
|
+
import { createUnforwardedOptionChordWarner } from "../utils/macos-option-forwarding";
|
|
44
46
|
|
|
45
47
|
const QUEUE_SELECTOR_NAVIGATION_ACTIONS = [
|
|
46
48
|
"tui.select.up",
|
|
@@ -95,6 +97,8 @@ function isExpandable(obj: unknown): obj is Expandable {
|
|
|
95
97
|
export class InputController {
|
|
96
98
|
readonly actionRegistry: ActionRegistry<void>;
|
|
97
99
|
readonly #loadPastedImageBatch: typeof loadPastedImageBatch;
|
|
100
|
+
/** Session id with an automatic-title request pending, if any. */
|
|
101
|
+
#autoTitleInFlightSessionId: string | undefined;
|
|
98
102
|
#deferredSubmission?: {
|
|
99
103
|
text: string;
|
|
100
104
|
images?: InteractiveModeContext["pendingImages"];
|
|
@@ -546,15 +550,23 @@ export class InputController {
|
|
|
546
550
|
if (!isInterruptKey && !isClearKey) {
|
|
547
551
|
return undefined;
|
|
548
552
|
}
|
|
549
|
-
|
|
553
|
+
// Listeners run before focused handleInput. Yield interrupt/back to the
|
|
554
|
+
// focused UI before touching BTW, maintenance, retries or workflow state.
|
|
555
|
+
// Clear (Ctrl+C by default) remains a global abort, even if the same
|
|
556
|
+
// key is also configured as interrupt.
|
|
557
|
+
if (isInterruptKey && !isClearKey && focusedUiOwnsInterrupt(this.ctx)) {
|
|
558
|
+
this.#resetEscapeGestures();
|
|
559
|
+
return undefined;
|
|
560
|
+
}
|
|
561
|
+
if (isClearKey && this.ctx.hasActiveBtw() && this.ctx.handleBtwEscape()) {
|
|
550
562
|
this.#resetEscapeGestures();
|
|
551
563
|
return { consume: true };
|
|
552
564
|
}
|
|
553
|
-
if (isClearKey &&
|
|
565
|
+
if (isClearKey && this.ctx.hookSelector?.hasActiveInlineInput?.() === true) {
|
|
554
566
|
this.#resetEscapeGestures();
|
|
555
567
|
return undefined;
|
|
556
568
|
}
|
|
557
|
-
if (isClearKey
|
|
569
|
+
if (isClearKey) {
|
|
558
570
|
if (this.#handlePendingSteerInterrupt()) return { consume: true };
|
|
559
571
|
if (
|
|
560
572
|
this.#handleCancellableWorkEscape({
|
|
@@ -807,6 +819,12 @@ export class InputController {
|
|
|
807
819
|
this.ctx.editor.setActionKeys("app.message.queue", this.ctx.keybindings.getKeys("app.message.queue"));
|
|
808
820
|
this.ctx.editor.onQueue = () => this.#executeAction("app.message.queue");
|
|
809
821
|
this.#registerCommandPaletteAction("app.message.queue", queue, true);
|
|
822
|
+
this.ctx.editor.onUnforwardedOptionChord ??= createUnforwardedOptionChordWarner({
|
|
823
|
+
platform: process.platform,
|
|
824
|
+
terminalProgram: Bun.env.TERM_PROGRAM,
|
|
825
|
+
formatKeyHint: key => this.ctx.keybindings.formatKeyHint(key),
|
|
826
|
+
showWarning: message => this.ctx.showWarning(message),
|
|
827
|
+
});
|
|
810
828
|
|
|
811
829
|
this.ctx.editor.onViewportPageScroll = direction => this.ctx.ui.scrollViewportPages(direction);
|
|
812
830
|
this.ctx.editor.onViewportFollowLive = () => {
|
|
@@ -1163,6 +1181,7 @@ export class InputController {
|
|
|
1163
1181
|
return;
|
|
1164
1182
|
}
|
|
1165
1183
|
this.ctx.queueCompactionMessage(text, "steer", composer);
|
|
1184
|
+
this.#titleQueuedCompactionText(text);
|
|
1166
1185
|
return;
|
|
1167
1186
|
}
|
|
1168
1187
|
|
|
@@ -1172,6 +1191,9 @@ export class InputController {
|
|
|
1172
1191
|
// This handles extension commands (execute immediately), prompt template expansion, and queueing
|
|
1173
1192
|
if (this.ctx.session.isStreaming) {
|
|
1174
1193
|
invalidateSessionTitleGeneration(this.ctx.sessionManager);
|
|
1194
|
+
// A turn started by a skill command has no user message yet, so the
|
|
1195
|
+
// first typed message can arrive here instead of the idle path.
|
|
1196
|
+
this.maybeGenerateSessionTitle(text);
|
|
1175
1197
|
if (this.#canModifyComposer(composer)) {
|
|
1176
1198
|
this.ctx.editor.addToHistory(text);
|
|
1177
1199
|
this.ctx.editor.setText("");
|
|
@@ -1200,32 +1222,7 @@ export class InputController {
|
|
|
1200
1222
|
// First, move any pending bash components to chat
|
|
1201
1223
|
this.ctx.flushPendingBashComponents();
|
|
1202
1224
|
|
|
1203
|
-
|
|
1204
|
-
const hasUserMessages = this.ctx.session.messages.some((m: AgentMessage) => m.role === "user");
|
|
1205
|
-
if (!hasUserMessages && !this.ctx.sessionManager.getSessionName() && !$pickenv("GJC_NO_TITLE", "PI_NO_TITLE")) {
|
|
1206
|
-
const registry = this.ctx.session.modelRegistry;
|
|
1207
|
-
generateSessionTitle(
|
|
1208
|
-
text,
|
|
1209
|
-
registry,
|
|
1210
|
-
this.ctx.settings,
|
|
1211
|
-
this.ctx.session.credentialSessionId,
|
|
1212
|
-
this.ctx.session.model,
|
|
1213
|
-
provider => this.ctx.session.agent.metadataForProvider(provider),
|
|
1214
|
-
)
|
|
1215
|
-
.then(async title => {
|
|
1216
|
-
if (title) {
|
|
1217
|
-
const applied = await this.ctx.sessionManager.setSessionName(title, "auto");
|
|
1218
|
-
if (applied) {
|
|
1219
|
-
setSessionTerminalTitle(
|
|
1220
|
-
this.ctx.sessionManager.getSessionName()!,
|
|
1221
|
-
this.ctx.sessionManager.getCwd(),
|
|
1222
|
-
);
|
|
1223
|
-
this.ctx.updateEditorBorderColor();
|
|
1224
|
-
}
|
|
1225
|
-
}
|
|
1226
|
-
})
|
|
1227
|
-
.catch(() => {});
|
|
1228
|
-
}
|
|
1225
|
+
this.maybeGenerateSessionTitle(text);
|
|
1229
1226
|
|
|
1230
1227
|
if (this.ctx.onInputCallback) {
|
|
1231
1228
|
// Include any pending images from clipboard paste
|
|
@@ -1303,7 +1300,7 @@ export class InputController {
|
|
|
1303
1300
|
});
|
|
1304
1301
|
|
|
1305
1302
|
// Stop the TUI (restore terminal to normal mode)
|
|
1306
|
-
this.ctx.ui.
|
|
1303
|
+
this.ctx.ui.suspend();
|
|
1307
1304
|
|
|
1308
1305
|
// Send SIGTSTP to process group (pid=0 means all processes in group)
|
|
1309
1306
|
process.kill(0, "SIGTSTP");
|
|
@@ -1628,6 +1625,51 @@ export class InputController {
|
|
|
1628
1625
|
return this.ctx.settings.get("busyPromptMode") === "steer" ? "steer" : "followUp";
|
|
1629
1626
|
}
|
|
1630
1627
|
|
|
1628
|
+
/**
|
|
1629
|
+
* Generate the automatic session title from the first user message. Called
|
|
1630
|
+
* from the editor submit and queue-shortcut paths (idle and streaming) and
|
|
1631
|
+
* from interactive startup messages; it is a no-op once the session has a
|
|
1632
|
+
* user message, a name, or a title request already in flight. The result is
|
|
1633
|
+
* bound to the session that requested it: a completion that lands after the
|
|
1634
|
+
* session was replaced (New Session, switch, resume) is discarded.
|
|
1635
|
+
*/
|
|
1636
|
+
maybeGenerateSessionTitle(text: string): void {
|
|
1637
|
+
if (this.ctx.sessionManager.getSessionName()) return;
|
|
1638
|
+
const sessionId = this.ctx.sessionManager.getSessionId();
|
|
1639
|
+
if (this.#autoTitleInFlightSessionId === sessionId) return;
|
|
1640
|
+
if ($pickenv("GJC_NO_TITLE", "PI_NO_TITLE")) return;
|
|
1641
|
+
if (this.ctx.session.messages.some((m: AgentMessage) => m.role === "user")) return;
|
|
1642
|
+
// Keep locally intercepted command arguments away from the title model.
|
|
1643
|
+
if (this.ctx.session.isLocallyHandledSlashCommand(text)) return;
|
|
1644
|
+
this.#autoTitleInFlightSessionId = sessionId;
|
|
1645
|
+
generateSessionTitle(
|
|
1646
|
+
text,
|
|
1647
|
+
this.ctx.session.modelRegistry,
|
|
1648
|
+
this.ctx.settings,
|
|
1649
|
+
this.ctx.session.credentialSessionId,
|
|
1650
|
+
this.ctx.session.model,
|
|
1651
|
+
provider => this.ctx.session.agent.metadataForProvider(provider),
|
|
1652
|
+
)
|
|
1653
|
+
.then(async title => {
|
|
1654
|
+
if (!title || this.ctx.sessionManager.getSessionId() !== sessionId) return;
|
|
1655
|
+
const applied = await this.ctx.sessionManager.setSessionName(title, "auto");
|
|
1656
|
+
if (applied) {
|
|
1657
|
+
setSessionTerminalTitle(this.ctx.sessionManager.getSessionName()!, this.ctx.sessionManager.getCwd());
|
|
1658
|
+
this.ctx.updateEditorBorderColor();
|
|
1659
|
+
}
|
|
1660
|
+
})
|
|
1661
|
+
.catch(() => {})
|
|
1662
|
+
.finally(() => {
|
|
1663
|
+
if (this.#autoTitleInFlightSessionId === sessionId) this.#autoTitleInFlightSessionId = undefined;
|
|
1664
|
+
});
|
|
1665
|
+
}
|
|
1666
|
+
|
|
1667
|
+
/** Title text accepted into the compaction queue; skill commands replay through the skill path and are not titled. */
|
|
1668
|
+
#titleQueuedCompactionText(text: string): void {
|
|
1669
|
+
if (parseSkillInvocations(text, this.ctx.skillCommands ?? new Map()).length > 0) return;
|
|
1670
|
+
this.maybeGenerateSessionTitle(text);
|
|
1671
|
+
}
|
|
1672
|
+
|
|
1631
1673
|
/**
|
|
1632
1674
|
* Dispatch skill slash invocation(s) (`/skill:<name>`) through custom messages
|
|
1633
1675
|
* using the supplied `streamingBehavior`. Returns true if the text contains a
|
|
@@ -1736,6 +1778,7 @@ export class InputController {
|
|
|
1736
1778
|
return;
|
|
1737
1779
|
}
|
|
1738
1780
|
this.ctx.queueCompactionMessage(text, "followUp");
|
|
1781
|
+
this.#titleQueuedCompactionText(text);
|
|
1739
1782
|
return;
|
|
1740
1783
|
}
|
|
1741
1784
|
|
|
@@ -1750,6 +1793,7 @@ export class InputController {
|
|
|
1750
1793
|
followUpQueuePolicy: "sequential",
|
|
1751
1794
|
}),
|
|
1752
1795
|
);
|
|
1796
|
+
this.maybeGenerateSessionTitle(text);
|
|
1753
1797
|
this.ctx.updatePendingMessagesDisplay();
|
|
1754
1798
|
this.ctx.ui.requestRender();
|
|
1755
1799
|
return;
|
|
@@ -1761,6 +1805,7 @@ export class InputController {
|
|
|
1761
1805
|
return;
|
|
1762
1806
|
}
|
|
1763
1807
|
|
|
1808
|
+
this.maybeGenerateSessionTitle(text);
|
|
1764
1809
|
if (this.ctx.session.isStreaming) {
|
|
1765
1810
|
this.ctx.editor.addToHistory(text);
|
|
1766
1811
|
this.ctx.editor.setText("");
|
|
@@ -2517,7 +2562,7 @@ export class InputController {
|
|
|
2517
2562
|
let ttyHandle: fs.FileHandle | null = null;
|
|
2518
2563
|
try {
|
|
2519
2564
|
ttyHandle = await this.#openEditorTerminalHandle();
|
|
2520
|
-
this.ctx.ui.
|
|
2565
|
+
this.ctx.ui.suspend();
|
|
2521
2566
|
|
|
2522
2567
|
const stdio: [number | "inherit", number | "inherit", number | "inherit"] = ttyHandle
|
|
2523
2568
|
? [ttyHandle.fd, ttyHandle.fd, ttyHandle.fd]
|
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
updateMCPServer,
|
|
20
20
|
} from "../../runtime-mcp/config-writer";
|
|
21
21
|
import { canonicalMCPResourceUri, type MCPOAuthConfig, MCPOAuthFlow } from "../../runtime-mcp/oauth-flow";
|
|
22
|
+
import { nativeMcpSource } from "../../runtime-mcp/project-host-values";
|
|
22
23
|
import {
|
|
23
24
|
clearSmitheryApiKey,
|
|
24
25
|
createSmitheryCliAuthSession,
|
|
@@ -44,7 +45,8 @@ import { parseCommandArgs } from "../shared";
|
|
|
44
45
|
import { buildOAuthLoginAnchor, createOAuthUrlCopyLease } from "../shared/oauth-url-copy";
|
|
45
46
|
import { theme } from "../theme/theme";
|
|
46
47
|
import type { InteractiveModeContext } from "../types";
|
|
47
|
-
import {
|
|
48
|
+
import { focusedUiOwnsInterrupt } from "../utils/interrupt-ownership";
|
|
49
|
+
import { matchesAppClear, matchesAppInterrupt } from "../utils/keybinding-matchers";
|
|
48
50
|
import { groupBySource, parseRemoveArgs, readScopeFlag, showCommandMessage } from "./command-controller-shared";
|
|
49
51
|
|
|
50
52
|
function withTimeout<T>(promise: Promise<T>, timeoutMs: number, message: string): Promise<T> {
|
|
@@ -645,7 +647,9 @@ export class MCPCommandController {
|
|
|
645
647
|
const cancellationUnsubscribe =
|
|
646
648
|
signal === undefined && typeof this.ctx.ui.addInputListener === "function"
|
|
647
649
|
? this.ctx.ui.addInputListener(data => {
|
|
648
|
-
|
|
650
|
+
const isClearKey = data === "\x03" || matchesAppClear(data);
|
|
651
|
+
if (!isClearKey && !matchesAppInterrupt(data)) return;
|
|
652
|
+
if (!isClearKey && focusedUiOwnsInterrupt(this.ctx)) return;
|
|
649
653
|
userController.abort(new Error("OAuth flow cancelled"));
|
|
650
654
|
return { consume: true };
|
|
651
655
|
})
|
|
@@ -812,7 +816,7 @@ export class MCPCommandController {
|
|
|
812
816
|
* Test connection to an MCP server.
|
|
813
817
|
* Throws an error if connection fails (used for auto-detection).
|
|
814
818
|
*/
|
|
815
|
-
async #handleTestConnection(config: MCPServerConfig): Promise<void> {
|
|
819
|
+
async #handleTestConnection(config: MCPServerConfig, source?: SourceMeta): Promise<void> {
|
|
816
820
|
const testName = `test_${Date.now()}`;
|
|
817
821
|
const manager =
|
|
818
822
|
this.ctx.mcpManager ??
|
|
@@ -820,7 +824,7 @@ export class MCPCommandController {
|
|
|
820
824
|
sharedPoolIdleMs: this.ctx.settings.get("mcp.sharedPoolIdleMs"),
|
|
821
825
|
});
|
|
822
826
|
if (!this.ctx.mcpManager) manager.setAuthStorage(this.ctx.session.modelRegistry.authStorage);
|
|
823
|
-
await manager.withPreparedLease(testName, config, async () => {});
|
|
827
|
+
await manager.withPreparedLease(testName, config, async () => {}, { source });
|
|
824
828
|
}
|
|
825
829
|
|
|
826
830
|
async #findConfiguredServer(
|
|
@@ -877,7 +881,10 @@ export class MCPCommandController {
|
|
|
877
881
|
return next;
|
|
878
882
|
}
|
|
879
883
|
|
|
880
|
-
async #resolveOAuthEndpointsFromServer(
|
|
884
|
+
async #resolveOAuthEndpointsFromServer(
|
|
885
|
+
config: MCPServerConfig,
|
|
886
|
+
source?: SourceMeta,
|
|
887
|
+
): Promise<{
|
|
881
888
|
authorizationUrl: string;
|
|
882
889
|
tokenUrl: string;
|
|
883
890
|
clientId?: string;
|
|
@@ -885,11 +892,12 @@ export class MCPCommandController {
|
|
|
885
892
|
issuer?: string;
|
|
886
893
|
authorizationResponseIssSupported?: boolean;
|
|
887
894
|
}> {
|
|
888
|
-
// First test if server actually needs auth by connecting without OAuth
|
|
895
|
+
// First test if server actually needs auth by connecting without OAuth.
|
|
896
|
+
// A stored file keeps its source so project `!` and secret names stay gated.
|
|
889
897
|
let connectionSucceeded = false;
|
|
890
898
|
let connectionError: Error | undefined;
|
|
891
899
|
try {
|
|
892
|
-
await this.#handleTestConnection(this.#stripOAuthAuth(config));
|
|
900
|
+
await this.#handleTestConnection(this.#stripOAuthAuth(config), source);
|
|
893
901
|
connectionSucceeded = true;
|
|
894
902
|
} catch (error) {
|
|
895
903
|
connectionError = error as Error;
|
|
@@ -964,10 +972,10 @@ export class MCPCommandController {
|
|
|
964
972
|
}
|
|
965
973
|
}
|
|
966
974
|
|
|
967
|
-
async #syncManagerConnection(name: string, config: MCPServerConfig): Promise<void> {
|
|
975
|
+
async #syncManagerConnection(name: string, config: MCPServerConfig, source?: SourceMeta): Promise<void> {
|
|
968
976
|
if (!this.ctx.mcpManager) return;
|
|
969
977
|
if (this.ctx.mcpManager.getConnectionStatus(name) !== "disconnected") return;
|
|
970
|
-
await this.ctx.mcpManager.connectServers({ [name]: config }, {});
|
|
978
|
+
await this.ctx.mcpManager.connectServers({ [name]: config }, source ? { [name]: source } : {});
|
|
971
979
|
if (this.ctx.mcpManager.getConnectionStatus(name) === "connected") {
|
|
972
980
|
await this.ctx.session.refreshMCPTools(this.ctx.mcpManager.getTools());
|
|
973
981
|
}
|
|
@@ -995,9 +1003,10 @@ export class MCPCommandController {
|
|
|
995
1003
|
// report as connected to avoid false-negative messaging.
|
|
996
1004
|
if (!isConnected && !isConnecting && config.enabled !== false) {
|
|
997
1005
|
try {
|
|
998
|
-
|
|
1006
|
+
const source = nativeMcpSource(scope, filePath);
|
|
1007
|
+
await this.#handleTestConnection(config, source);
|
|
999
1008
|
isConnected = true;
|
|
1000
|
-
await this.#syncManagerConnection(name, config);
|
|
1009
|
+
await this.#syncManagerConnection(name, config, source);
|
|
1001
1010
|
} catch {
|
|
1002
1011
|
// Keep disconnected status
|
|
1003
1012
|
}
|
|
@@ -1273,7 +1282,8 @@ export class MCPCommandController {
|
|
|
1273
1282
|
return;
|
|
1274
1283
|
}
|
|
1275
1284
|
|
|
1276
|
-
const { config } = found;
|
|
1285
|
+
const { config, scope, filePath } = found;
|
|
1286
|
+
const source = nativeMcpSource(scope, filePath);
|
|
1277
1287
|
if (config.enabled === false) {
|
|
1278
1288
|
this.ctx.showError(`Server "${name}" is disabled. Run /mcp enable ${name} first.`);
|
|
1279
1289
|
return;
|
|
@@ -1310,10 +1320,10 @@ export class MCPCommandController {
|
|
|
1310
1320
|
}
|
|
1311
1321
|
|
|
1312
1322
|
lines.push("");
|
|
1313
|
-
await this.#syncManagerConnection(name, config);
|
|
1323
|
+
await this.#syncManagerConnection(name, config, source);
|
|
1314
1324
|
this.#showMessage(lines.join("\n"));
|
|
1315
1325
|
},
|
|
1316
|
-
{ signal: abortController.signal },
|
|
1326
|
+
{ signal: abortController.signal, source },
|
|
1317
1327
|
);
|
|
1318
1328
|
} catch (error) {
|
|
1319
1329
|
if (abortController.signal.aborted || (error instanceof Error && error.name === "AbortError")) {
|
|
@@ -1489,7 +1499,8 @@ export class MCPCommandController {
|
|
|
1489
1499
|
}
|
|
1490
1500
|
|
|
1491
1501
|
const baseConfig = this.#stripOAuthAuth(found.config);
|
|
1492
|
-
const
|
|
1502
|
+
const source = nativeMcpSource(found.scope, found.filePath);
|
|
1503
|
+
const oauth = await this.#resolveOAuthEndpointsFromServer(baseConfig, source);
|
|
1493
1504
|
const oauthClientSecret = found.config.oauth?.clientSecret ?? currentAuth?.clientSecret ?? "";
|
|
1494
1505
|
|
|
1495
1506
|
this.#showMessage(["", theme.fg("muted", `Reauthorizing "${name}"...`), ""].join("\n"));
|
|
@@ -1839,7 +1850,9 @@ export class MCPCommandController {
|
|
|
1839
1850
|
const oauthUrlCopyLease = createOAuthUrlCopyLease(this.ctx);
|
|
1840
1851
|
const abortController = new AbortController();
|
|
1841
1852
|
const interruptUnsubscribe = this.ctx.ui.addInputListener?.(data => {
|
|
1842
|
-
|
|
1853
|
+
const isClearKey = data === "\x03" || matchesAppClear(data);
|
|
1854
|
+
if (!isClearKey && !matchesAppInterrupt(data)) return;
|
|
1855
|
+
if (!isClearKey && focusedUiOwnsInterrupt(this.ctx)) return;
|
|
1843
1856
|
abortController.abort(new Error("Smithery authorization cancelled."));
|
|
1844
1857
|
return { consume: true };
|
|
1845
1858
|
});
|
|
@@ -1612,7 +1612,7 @@ export class SelectorController {
|
|
|
1612
1612
|
}
|
|
1613
1613
|
|
|
1614
1614
|
async #handleCredentialImport(): Promise<void> {
|
|
1615
|
-
this.ctx.showStatus("Scanning for existing Claude Code / Codex CLI credentials…");
|
|
1615
|
+
this.ctx.showStatus("Scanning for existing Claude Code / Codex CLI / Kiro CLI credentials…");
|
|
1616
1616
|
const preview = await runExternalCredentialAutoImport({
|
|
1617
1617
|
authStorage: {
|
|
1618
1618
|
importCredentialIfAbsent: async () => ({
|
|
@@ -2494,17 +2494,20 @@ export class SelectorController {
|
|
|
2494
2494
|
* default) then refresh the status surfaces. Rethrows so callers surface errors.
|
|
2495
2495
|
*/
|
|
2496
2496
|
async #applyModelProfile(profileName: string, persistDefault: boolean): Promise<void> {
|
|
2497
|
+
this.ctx.session.markUserModelSelection();
|
|
2497
2498
|
const profileLabel = formatModelProfileDisplayLabel(
|
|
2498
2499
|
this.ctx.session.modelRegistry.getModelProfile(profileName) ?? { name: profileName },
|
|
2499
2500
|
);
|
|
2500
|
-
await
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2501
|
+
await this.ctx.session.withSdkControlMutation(() =>
|
|
2502
|
+
activateModelProfile(
|
|
2503
|
+
{
|
|
2504
|
+
session: this.ctx.session,
|
|
2505
|
+
modelRegistry: this.ctx.session.modelRegistry,
|
|
2506
|
+
settings: this.ctx.settings,
|
|
2507
|
+
profileName,
|
|
2508
|
+
},
|
|
2509
|
+
{ persistDefault },
|
|
2510
|
+
),
|
|
2508
2511
|
);
|
|
2509
2512
|
this.ctx.statusLine.invalidate();
|
|
2510
2513
|
this.ctx.updateEditorBorderColor();
|
|
@@ -2779,6 +2782,7 @@ export class SelectorController {
|
|
|
2779
2782
|
await this.ctx.session.setModelTemporary(model, thinkingLevel, {
|
|
2780
2783
|
cause: "temporary-operation",
|
|
2781
2784
|
reason: "other",
|
|
2785
|
+
onMutationStarted: () => this.ctx.session.markUserModelSelection(),
|
|
2782
2786
|
});
|
|
2783
2787
|
this.ctx.session.setDefaultFallbackRuntimeModel(
|
|
2784
2788
|
selectedSelector ?? formatModelSelectorValue(`${model.provider}/${model.id}`, thinkingLevel),
|
|
@@ -2816,6 +2820,7 @@ export class SelectorController {
|
|
|
2816
2820
|
selectedSelector && thinkingLevel && selectedSelector.endsWith(`:${thinkingLevel}`)
|
|
2817
2821
|
? selectedSelector.slice(0, -thinkingLevel.length - 1)
|
|
2818
2822
|
: selectedSelector;
|
|
2823
|
+
if (includesRoleAgent && !includesDefault) this.ctx.session.markUserModelSelection();
|
|
2819
2824
|
|
|
2820
2825
|
const rollbackSnapshot = this.#captureDefaultAssignmentRollback();
|
|
2821
2826
|
let defaultMutationStarted = false;
|
|
@@ -2938,6 +2943,7 @@ export class SelectorController {
|
|
|
2938
2943
|
}
|
|
2939
2944
|
const value =
|
|
2940
2945
|
selectedSelector ?? formatModelSelectorValue(`${model.provider}/${model.id}`, thinkingLevel);
|
|
2946
|
+
this.ctx.session.markUserModelSelection();
|
|
2941
2947
|
const assignments = new Map<GjcModelAssignmentTargetId, string>([[role, value]]);
|
|
2942
2948
|
const materializedProfile = materializeActiveModelProfileAssignments({
|
|
2943
2949
|
session: this.ctx.session,
|
|
@@ -3677,12 +3683,15 @@ export class SelectorController {
|
|
|
3677
3683
|
return;
|
|
3678
3684
|
}
|
|
3679
3685
|
|
|
3680
|
-
|
|
3681
|
-
|
|
3682
|
-
|
|
3683
|
-
|
|
3684
|
-
|
|
3685
|
-
|
|
3686
|
+
this.ctx.session.markUserModelSelection();
|
|
3687
|
+
await this.ctx.session.withSdkControlMutation(() =>
|
|
3688
|
+
activateModelProfile({
|
|
3689
|
+
session: this.ctx.session,
|
|
3690
|
+
modelRegistry: this.ctx.session.modelRegistry,
|
|
3691
|
+
settings: this.ctx.settings,
|
|
3692
|
+
profileName: recommendedProfile.name,
|
|
3693
|
+
}),
|
|
3694
|
+
);
|
|
3686
3695
|
}
|
|
3687
3696
|
|
|
3688
3697
|
async #handleOAuthLogin(providerId: string, options?: OAuthSelectorOptions): Promise<void> {
|
|
@@ -409,7 +409,7 @@ export class TodoCommandController {
|
|
|
409
409
|
current.length > 0 ? phasesToMarkdown(current) : "# Todos\n- [ ] (replace this with your tasks)\n";
|
|
410
410
|
|
|
411
411
|
const fileHandle = await this.#openTtyHandle();
|
|
412
|
-
this.ctx.ui.
|
|
412
|
+
this.ctx.ui.suspend();
|
|
413
413
|
try {
|
|
414
414
|
const stdio: [number | "inherit", number | "inherit", number | "inherit"] = fileHandle
|
|
415
415
|
? [fileHandle.fd, fileHandle.fd, fileHandle.fd]
|
|
@@ -679,7 +679,7 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
679
679
|
startPendingSubmission: input => thisMode.startPendingSubmission(input),
|
|
680
680
|
addChatChild: child => addChatChild(thisMode, child),
|
|
681
681
|
requestRender: full => thisMode.ui.requestRender(full),
|
|
682
|
-
stopUi: () => thisMode.ui.
|
|
682
|
+
stopUi: () => thisMode.ui.suspend(),
|
|
683
683
|
startUi: () => thisMode.ui.start(),
|
|
684
684
|
showStatus: message => thisMode.showStatus(message),
|
|
685
685
|
showWarning: message => thisMode.showWarning(message),
|
|
@@ -2642,6 +2642,10 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
2642
2642
|
this.#inputController.handleBackgroundCommand();
|
|
2643
2643
|
}
|
|
2644
2644
|
|
|
2645
|
+
maybeGenerateSessionTitle(text: string): void {
|
|
2646
|
+
this.#inputController.maybeGenerateSessionTitle(text);
|
|
2647
|
+
}
|
|
2648
|
+
|
|
2645
2649
|
handleImagePaste(): Promise<boolean> {
|
|
2646
2650
|
return this.#inputController.handleImagePaste();
|
|
2647
2651
|
}
|
|
@@ -11,6 +11,8 @@ import { ThinkingLevel } from "@gajae-code/agent-core";
|
|
|
11
11
|
import { runExtensionCompact, runExtensionSetModel } from "../extensibility/extensions/compact-handler";
|
|
12
12
|
import { getSessionSlashCommands } from "../extensibility/extensions/get-commands-handler";
|
|
13
13
|
import type { ExtensionError, ExtensionUIContext } from "../extensibility/extensions/types";
|
|
14
|
+
import { buildSessionProjectProgress } from "../progress/collect-project-progress";
|
|
15
|
+
import { toProjectProgressSnapshot } from "../progress/progress-snapshot";
|
|
14
16
|
import {
|
|
15
17
|
parseSyntheticModelId,
|
|
16
18
|
resolveSyntheticModelSelection,
|
|
@@ -201,6 +203,8 @@ export async function initializeExtensions(session: AgentSession, options: Initi
|
|
|
201
203
|
return { bytes: new Uint8Array(await file.slice(start, end).arrayBuffer()), totalBytes: file.size };
|
|
202
204
|
},
|
|
203
205
|
getJobs: () => session.getAsyncJobSnapshot(),
|
|
206
|
+
getProjectProgress: async () =>
|
|
207
|
+
toProjectProgressSnapshot(await buildSessionProjectProgress(session, session.sessionManager)),
|
|
204
208
|
onJobFold: listener => session.onJobFold(listener),
|
|
205
209
|
onSessionEvent: listener => session.subscribe(listener),
|
|
206
210
|
setSdkPermissionProvider: provider => session.setSdkPermissionProvider(provider),
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { getStreamIdleTimeoutRemediationMs } from "@gajae-code/ai/utils/idle-iterator";
|
|
2
|
+
|
|
1
3
|
const STREAM_IDLE_TIMEOUT_PATTERN = /\bstream stalled while waiting for the next event\b/i;
|
|
2
4
|
const GENERIC_ABORT_PATTERN = /^Request was aborted\.?$/i;
|
|
3
5
|
const ABORT_DISPLAY_LABEL_PATTERN = /^(?:Operation aborted|Aborted after \d+ retry attempts?)(?::|$)/;
|
|
@@ -37,5 +39,5 @@ function normalizeAbortCause(errorMessage: string | undefined): string {
|
|
|
37
39
|
function streamIdleTimeoutHint(cause: string): string {
|
|
38
40
|
if (!STREAM_IDLE_TIMEOUT_PATTERN.test(cause)) return "";
|
|
39
41
|
const separator = /[.!?]$/.test(cause) ? " " : ". ";
|
|
40
|
-
return `${separator}Hint: set PI_STREAM_IDLE_TIMEOUT_MS
|
|
42
|
+
return `${separator}Hint: set PI_STREAM_IDLE_TIMEOUT_MS=${getStreamIdleTimeoutRemediationMs()} for slow reasoning/proxy streams, or PI_STREAM_IDLE_TIMEOUT_MS=0 to disable the watchdog.`;
|
|
41
43
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { InteractiveModeContext } from "../types";
|
|
2
|
+
|
|
3
|
+
/** Ordinary focused UI owns interrupt/back before background work does. */
|
|
4
|
+
export function focusedUiOwnsInterrupt(
|
|
5
|
+
ctx: Pick<InteractiveModeContext, "ui" | "editor" | "hookSelector" | "hookInput" | "hookEditor">,
|
|
6
|
+
): boolean {
|
|
7
|
+
const focused = ctx.ui.getFocusedComponent?.();
|
|
8
|
+
if (!focused?.handleInput || focused === ctx.editor) return false;
|
|
9
|
+
// Non-inline hook prompts deliberately retain workflow-level interruption.
|
|
10
|
+
if (focused === ctx.hookSelector) return ctx.hookSelector.hasActiveInlineInput();
|
|
11
|
+
return focused !== ctx.hookInput && focused !== ctx.hookEditor;
|
|
12
|
+
}
|
|
@@ -16,6 +16,10 @@ export function matchesAppInterrupt(data: string): boolean {
|
|
|
16
16
|
return matchesKey(data, "escape") || matchesKey(data, "esc");
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
export function matchesAppClear(data: string): boolean {
|
|
20
|
+
return getKeybindings().matches(data, "app.clear");
|
|
21
|
+
}
|
|
22
|
+
|
|
19
23
|
export function matchesSelectCancel(data: string): boolean {
|
|
20
24
|
return getKeybindings().matches(data, "tui.select.cancel");
|
|
21
25
|
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import type { KeyId } from "@gajae-code/tui";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Characters macOS composes for Option+<letter> on the US/ABC layout when the
|
|
5
|
+
* terminal sends Option as text instead of Alt/Meta. Dead-key letters (e, i, n,
|
|
6
|
+
* u) compose nothing on their own and are absent.
|
|
7
|
+
*/
|
|
8
|
+
const MACOS_OPTION_COMPOSED_KEYS: ReadonlyMap<string, KeyId> = new Map<string, KeyId>([
|
|
9
|
+
["å", "alt+a"],
|
|
10
|
+
["∫", "alt+b"],
|
|
11
|
+
["ç", "alt+c"],
|
|
12
|
+
["∂", "alt+d"],
|
|
13
|
+
["ƒ", "alt+f"],
|
|
14
|
+
["©", "alt+g"],
|
|
15
|
+
["˙", "alt+h"],
|
|
16
|
+
["∆", "alt+j"],
|
|
17
|
+
["˚", "alt+k"],
|
|
18
|
+
["¬", "alt+l"],
|
|
19
|
+
["µ", "alt+m"],
|
|
20
|
+
["ø", "alt+o"],
|
|
21
|
+
["π", "alt+p"],
|
|
22
|
+
["œ", "alt+q"],
|
|
23
|
+
["®", "alt+r"],
|
|
24
|
+
["ß", "alt+s"],
|
|
25
|
+
["†", "alt+t"],
|
|
26
|
+
["√", "alt+v"],
|
|
27
|
+
["∑", "alt+w"],
|
|
28
|
+
["≈", "alt+x"],
|
|
29
|
+
["¥", "alt+y"],
|
|
30
|
+
["Ω", "alt+z"],
|
|
31
|
+
]);
|
|
32
|
+
|
|
33
|
+
/** The Option chord that composes `text` on the macOS US/ABC layout, if any. */
|
|
34
|
+
export function macosOptionChordForComposedText(text: string): KeyId | undefined {
|
|
35
|
+
return MACOS_OPTION_COMPOSED_KEYS.get(text);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Terminal-specific instruction for sending Option as Alt/Meta, when the terminal is known. */
|
|
39
|
+
export function macosOptionForwardingInstruction(terminalProgram: string | undefined): string | undefined {
|
|
40
|
+
const program = terminalProgram?.toLowerCase() ?? "";
|
|
41
|
+
if (program.includes("ghostty")) {
|
|
42
|
+
return "Ghostty: set macos-option-as-alt = true in its config, then reload the config or restart Ghostty.";
|
|
43
|
+
}
|
|
44
|
+
if (program === "apple_terminal") {
|
|
45
|
+
return "Terminal.app: enable Settings > Profiles > Keyboard > Use Option as Meta key.";
|
|
46
|
+
}
|
|
47
|
+
if (program === "iterm.app") {
|
|
48
|
+
return "iTerm2: set Settings > Profiles > Keys > Left and Right Option key to Esc+.";
|
|
49
|
+
}
|
|
50
|
+
return undefined;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface UnforwardedOptionChordWarnerOptions {
|
|
54
|
+
platform: NodeJS.Platform;
|
|
55
|
+
terminalProgram: string | undefined;
|
|
56
|
+
formatKeyHint: (key: KeyId) => string;
|
|
57
|
+
showWarning: (message: string) => void;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Builds the composer callback that explains, once, why a bound Option shortcut
|
|
62
|
+
* produced a character instead of firing. Returns undefined off macOS, where the
|
|
63
|
+
* composition table does not apply.
|
|
64
|
+
*/
|
|
65
|
+
export function createUnforwardedOptionChordWarner(
|
|
66
|
+
options: UnforwardedOptionChordWarnerOptions,
|
|
67
|
+
): ((key: KeyId, text: string) => void) | undefined {
|
|
68
|
+
if (options.platform !== "darwin") return undefined;
|
|
69
|
+
let warned = false;
|
|
70
|
+
return (key, text) => {
|
|
71
|
+
if (warned) return;
|
|
72
|
+
warned = true;
|
|
73
|
+
const instruction =
|
|
74
|
+
macosOptionForwardingInstruction(options.terminalProgram) ??
|
|
75
|
+
"Configure the terminal to send Option as Alt/Meta (Esc+).";
|
|
76
|
+
options.showWarning(
|
|
77
|
+
`${options.formatKeyHint(key)} arrived as "${text}": the terminal is sending Option as text, so Option shortcuts cannot reach GJC. ${instruction} Or remap the shortcut to a Control chord in keybindings.json.`,
|
|
78
|
+
);
|
|
79
|
+
};
|
|
80
|
+
}
|