@sayknow-cli/coding-agent 0.4.6 → 0.5.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 +112 -0
- package/dist/types/capability/index.d.ts +10 -20
- package/dist/types/capability/types.d.ts +3 -0
- package/dist/types/cli/args.d.ts +0 -2
- package/dist/types/cli/read-cli.d.ts +1 -0
- package/dist/types/cli.d.ts +9 -1
- package/dist/types/commands/daemon.d.ts +2 -2
- package/dist/types/commands/deep-interview.d.ts +9 -0
- package/dist/types/commands/harness.d.ts +22 -0
- package/dist/types/commands/read.d.ts +6 -0
- package/dist/types/commands/sdk.d.ts +20 -2
- package/dist/types/config/keybindings.d.ts +34 -4
- package/dist/types/config/model-profile-contract.d.ts +40 -0
- package/dist/types/config/model-profiles.d.ts +2 -3
- package/dist/types/config/model-registry.d.ts +5 -0
- package/dist/types/config/provider-auth-health.d.ts +14 -0
- package/dist/types/config/provider-ranking.d.ts +59 -0
- package/dist/types/config/settings-schema.d.ts +156 -10
- package/dist/types/config/settings.d.ts +3 -0
- package/dist/types/edit/modes/patch.d.ts +13 -0
- package/dist/types/edit/path-mutation-lock.d.ts +15 -0
- package/dist/types/eval/py/executor.d.ts +1 -1
- package/dist/types/eval/py/runner-artifact.d.ts +8 -0
- package/dist/types/eval/py/tool-bridge.d.ts +1 -2
- package/dist/types/extensibility/extensions/types.d.ts +43 -2
- package/dist/types/extensibility/shared-events.d.ts +6 -0
- package/dist/types/internal-urls/local-root-gc.d.ts +2 -0
- package/dist/types/main.d.ts +33 -2
- package/dist/types/memories/index.d.ts +2 -0
- package/dist/types/modes/acp/acp-agent.d.ts +22 -9
- package/dist/types/modes/components/assistant-message.d.ts +3 -1
- package/dist/types/modes/components/btw-panel.d.ts +1 -0
- package/dist/types/modes/components/irc-sidebar.d.ts +41 -0
- package/dist/types/modes/components/queue-pane.d.ts +8 -0
- package/dist/types/modes/components/queued-message-selector.d.ts +6 -0
- package/dist/types/modes/components/read-tool-group.d.ts +4 -4
- package/dist/types/modes/components/runtime-mcp-add-wizard.d.ts +2 -1
- package/dist/types/modes/components/session-observer-overlay.d.ts +4 -0
- package/dist/types/modes/components/settings-selector.d.ts +2 -0
- package/dist/types/modes/components/tool-execution.d.ts +8 -0
- package/dist/types/modes/components/tool-status-header.d.ts +4 -2
- package/dist/types/modes/components/welcome.d.ts +5 -0
- package/dist/types/modes/controllers/btw-controller.d.ts +5 -0
- package/dist/types/modes/controllers/command-controller.d.ts +2 -0
- package/dist/types/modes/controllers/event-controller.d.ts +3 -0
- package/dist/types/modes/interactive-mode.d.ts +13 -2
- package/dist/types/modes/irc-observation-ledger.d.ts +17 -1
- package/dist/types/modes/prompt-action-autocomplete.d.ts +6 -1
- package/dist/types/modes/prompt-suggestion-controller.d.ts +35 -0
- package/dist/types/modes/shared/agent-wire/workflow-gate-broker.d.ts +2 -2
- package/dist/types/modes/types.d.ts +6 -0
- package/dist/types/modes/utils/hotkeys-markdown.d.ts +2 -1
- package/dist/types/modes/utils/ui-helpers.d.ts +16 -0
- package/dist/types/runtime/memory-domain.d.ts +9 -0
- package/dist/types/runtime/memory-guard-contract.d.ts +71 -0
- package/dist/types/runtime/memory-guard.d.ts +39 -0
- package/dist/types/runtime/memory-limit.d.ts +11 -0
- package/dist/types/runtime-mcp/content-limits.d.ts +7 -0
- package/dist/types/runtime-mcp/discoverable-tool-metadata.d.ts +1 -1
- package/dist/types/runtime-mcp/manager.d.ts +9 -1
- package/dist/types/runtime-mcp/oauth-flow.d.ts +0 -5
- package/dist/types/runtime-mcp/plugin-network-boundary.d.ts +14 -0
- package/dist/types/runtime-mcp/redaction.d.ts +2 -0
- package/dist/types/runtime-mcp/smithery-auth.d.ts +5 -0
- package/dist/types/sdk/acp/final-text.d.ts +19 -0
- package/dist/types/sdk/acp/mcp.d.ts +23 -0
- package/dist/types/sdk/broker/broker.d.ts +2 -0
- package/dist/types/sdk/broker/lifecycle.d.ts +13 -0
- package/dist/types/sdk/bus/chat-daemon-control.d.ts +9 -1
- package/dist/types/sdk/bus/config-commands.d.ts +2 -2
- package/dist/types/sdk/bus/config.d.ts +2 -0
- package/dist/types/sdk/bus/control-drain-lease.d.ts +52 -0
- package/dist/types/sdk/bus/conversation-store.d.ts +1 -0
- package/dist/types/sdk/bus/daemon-paths.d.ts +1 -0
- package/dist/types/sdk/bus/index.d.ts +52 -4
- package/dist/types/sdk/bus/kind-aware-reconciliation.d.ts +37 -0
- package/dist/types/sdk/bus/lifecycle-commands.d.ts +5 -4
- package/dist/types/sdk/bus/notification-orchestration.d.ts +1 -0
- package/dist/types/sdk/bus/notification-service.d.ts +34 -0
- package/dist/types/sdk/bus/operator-runtime.d.ts +1 -0
- package/dist/types/sdk/bus/prompt-reconciliation.d.ts +106 -0
- package/dist/types/sdk/bus/rate-limit-pool.d.ts +2 -0
- package/dist/types/sdk/bus/reconciliation-store.d.ts +65 -0
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +33 -9
- package/dist/types/sdk/bus/telegram-daemon-control.d.ts +5 -1
- package/dist/types/sdk/bus/telegram-daemon.d.ts +286 -12
- package/dist/types/sdk/bus/telegram-reference.d.ts +2 -0
- package/dist/types/sdk/bus/topic-registry.d.ts +88 -2
- package/dist/types/sdk/client/discovery.d.ts +2 -0
- package/dist/types/sdk/client/liveness.d.ts +7 -0
- package/dist/types/sdk/host/control/operations.d.ts +3 -2
- package/dist/types/sdk/host/host.d.ts +3 -1
- package/dist/types/sdk/host/query/handlers.d.ts +14 -0
- package/dist/types/sdk/index.d.ts +2 -0
- package/dist/types/sdk/lifecycle-session.d.ts +10 -1
- package/dist/types/sdk/prompt-status.d.ts +88 -0
- package/dist/types/sdk/session-directory.d.ts +1 -1
- package/dist/types/sdk/session.d.ts +7 -0
- package/dist/types/sdk/startup-capability.d.ts +9 -0
- package/dist/types/sdk/transport/auth-preface.d.ts +9 -0
- package/dist/types/sdk/transport/index.d.ts +12 -0
- package/dist/types/sdk/transport/relay.d.ts +43 -0
- package/dist/types/sdk/transport/serve-cli.d.ts +4 -0
- package/dist/types/sdk/transport/socket.d.ts +7 -0
- package/dist/types/sdk/transport/stdio.d.ts +3 -0
- package/dist/types/session/agent-session.d.ts +83 -24
- package/dist/types/session/btw-contract.d.ts +16 -0
- package/dist/types/session/fallback-chain-controller.d.ts +18 -2
- package/dist/types/session/internal/managed-session-scope.d.ts +70 -10
- package/dist/types/session/internal/managed-session-storage.d.ts +34 -12
- package/dist/types/session/internal/native-publish-outcome.d.ts +48 -0
- package/dist/types/session/memory-guard-checkpoint-participant.d.ts +69 -0
- package/dist/types/session/session-manager.d.ts +89 -18
- package/dist/types/session/session-storage.d.ts +31 -0
- package/dist/types/session/streaming-output.d.ts +60 -5
- package/dist/types/setup/credential-import.d.ts +5 -1
- package/dist/types/setup/provider-onboarding.d.ts +2 -0
- package/dist/types/skc-runtime/deep-interview-runtime.d.ts +1 -1
- package/dist/types/skc-runtime/deep-interview-stage.d.ts +37 -0
- package/dist/types/skc-runtime/gc-runtime.d.ts +1 -1
- package/dist/types/skc-runtime/linux-proc.d.ts +22 -14
- package/dist/types/skc-runtime/memory-guard-owner-claims.d.ts +47 -0
- package/dist/types/skc-runtime/ralplan-runtime.d.ts +112 -1
- package/dist/types/skc-runtime/repository-binding.d.ts +63 -0
- package/dist/types/skc-runtime/state-runtime.d.ts +3 -1
- package/dist/types/skc-runtime/state-writer.d.ts +5 -1
- package/dist/types/skc-runtime/team-launch.d.ts +1 -1
- package/dist/types/skc-runtime/team-runtime.d.ts +9 -2
- package/dist/types/skc-runtime/team-store.d.ts +12 -0
- package/dist/types/skc-runtime/team-worker-memory-guard.d.ts +92 -0
- package/dist/types/skc-runtime/tmux-owner-isolation.d.ts +7 -0
- package/dist/types/skc-runtime/ultragoal-guard.d.ts +6 -5
- package/dist/types/skc-runtime/ultragoal-receipt-freshness.d.ts +28 -0
- package/dist/types/skc-runtime/ultragoal-runtime.d.ts +43 -5
- package/dist/types/skill-state/workflow-hud.d.ts +3 -0
- package/dist/types/ssh/utils.d.ts +1 -0
- package/dist/types/task/discovery.d.ts +3 -1
- package/dist/types/task/executor.d.ts +6 -0
- package/dist/types/task/index.d.ts +3 -1
- package/dist/types/task/provider-retry-status.d.ts +13 -0
- package/dist/types/task/receipt.d.ts +2 -0
- package/dist/types/task/types.d.ts +133 -0
- package/dist/types/task/ultragoal-redteam-activation.d.ts +33 -0
- package/dist/types/tools/browser/launch.d.ts +7 -0
- package/dist/types/tools/fetch.d.ts +22 -9
- package/dist/types/tools/image-gen.d.ts +63 -1
- package/dist/types/tools/index.d.ts +7 -1
- package/dist/types/tools/output-meta.d.ts +21 -1
- package/dist/types/tools/read-internals.d.ts +12 -0
- package/dist/types/tools/read.d.ts +45 -1
- package/dist/types/tools/resource-gc.d.ts +23 -0
- package/dist/types/tools/skill-discovery.d.ts +7 -0
- package/dist/types/tools/sqlite-reader.d.ts +7 -0
- package/dist/types/tools/tool-result.d.ts +7 -1
- package/dist/types/utils/prompt-suggestion.d.ts +33 -0
- package/dist/types/utils/shell-snapshot.d.ts +12 -0
- package/dist/types/web/insane/bridge.d.ts +1 -0
- package/dist/types/web/insane/url-guard.d.ts +17 -0
- package/package.json +8 -12
- package/scripts/benchmark-sticky-viewport-pr1.ts +239 -0
- package/scripts/capture-platform-shortcut-labels-showcase.ts +342 -0
- package/scripts/capture-sticky-viewport-showcase.ts +292 -0
- package/scripts/compile-args.ts +0 -1
- package/scripts/dogfood-repository-binding.ts +209 -0
- package/scripts/generate-docs-index.ts +4 -1
- package/scripts/generate-sdk-operation-inventory.ts +9 -0
- package/scripts/run-test-manifest.ts +6 -4
- package/scripts/verify-skc-sdk-canonicalization.ts +122 -18
- package/scripts/verify-sticky-viewport-showcase.ts +611 -0
- package/src/capability/index.ts +58 -42
- package/src/capability/types.ts +3 -0
- package/src/cli/args.ts +16 -100
- package/src/cli/fast-help.ts +1 -1
- package/src/cli/mcp-cli.ts +4 -21
- package/src/cli/notify-cli.ts +6 -38
- package/src/cli/read-cli.ts +2 -1
- package/src/cli/setup-cli.ts +10 -4
- package/src/cli.ts +133 -11
- package/src/commands/daemon.ts +22 -5
- package/src/commands/deep-interview.ts +26 -1
- package/src/commands/harness.ts +35 -12
- package/src/commands/read.ts +11 -2
- package/src/commands/sdk.ts +134 -17
- package/src/commands/team.ts +1 -1
- package/src/commit/agentic/index.ts +3 -3
- package/src/commit/map-reduce/index.ts +2 -2
- package/src/config/keybindings.ts +158 -25
- package/src/config/model-profile-contract.ts +174 -0
- package/src/config/model-profiles.ts +51 -10
- package/src/config/model-registry.ts +24 -4
- package/src/config/model-resolver.ts +2 -2
- package/src/config/provider-auth-health.ts +42 -0
- package/src/config/provider-ranking.ts +119 -0
- package/src/config/settings-schema.ts +157 -10
- package/src/config/settings.ts +254 -108
- package/src/coordinator-mcp/model-preset.ts +21 -74
- package/src/defaults/skc/skills/deep-interview/SKILL.md +147 -24
- package/src/defaults/skc/skills/ralplan/SKILL.md +91 -34
- package/src/defaults/skc/skills/team/SKILL.md +1 -1
- package/src/defaults/skc/skills/ultragoal/SKILL.md +68 -17
- package/src/discovery/ssh.ts +12 -1
- package/src/edit/index.ts +3 -6
- package/src/edit/modes/patch.ts +38 -1
- package/src/edit/modes/replace.ts +42 -0
- package/src/edit/path-mutation-lock.ts +112 -0
- package/src/eval/js/tool-bridge.ts +1 -1
- package/src/eval/py/executor.ts +37 -13
- package/src/eval/py/kernel.ts +1 -21
- package/src/eval/py/prelude.py +2 -2
- package/src/eval/py/runner-artifact.ts +84 -0
- package/src/eval/py/tool-bridge.ts +34 -18
- package/src/extensibility/extensions/runner.ts +4 -0
- package/src/extensibility/extensions/types.ts +42 -4
- package/src/extensibility/plugins/marketplace/fetcher.ts +191 -7
- package/src/extensibility/shared-events.ts +5 -0
- package/src/extensibility/skc-plugins/runtime-adapters.ts +2 -1
- package/src/hooks/native-skill-hook.ts +17 -4
- package/src/internal-urls/docs-index.generated.ts +17 -16
- package/src/internal-urls/local-protocol.ts +87 -25
- package/src/internal-urls/local-root-gc.ts +127 -0
- package/src/internal-urls/mcp-protocol.ts +73 -11
- package/src/main.ts +120 -42
- package/src/memories/index.ts +10 -0
- package/src/modes/DESIGN.md +52 -0
- package/src/modes/acp/acp-agent.ts +647 -83
- package/src/modes/acp/acp-event-mapper.ts +106 -12
- package/src/modes/acp/acp-mode.ts +39 -3
- package/src/modes/action-registry.ts +1 -1
- package/src/modes/components/assistant-message.ts +123 -22
- package/src/modes/components/btw-panel.ts +82 -16
- package/src/modes/components/irc-sidebar.ts +176 -62
- package/src/modes/components/model-selector.ts +61 -4
- package/src/modes/components/notifications-settings-editor.ts +1 -1
- package/src/modes/components/oauth-selector.ts +42 -12
- package/src/modes/components/plan-preview-overlay.ts +1 -1
- package/src/modes/components/queue-pane.ts +55 -9
- package/src/modes/components/queued-message-selector.ts +53 -10
- package/src/modes/components/read-tool-group.ts +82 -14
- package/src/modes/components/runtime-mcp-add-wizard.ts +5 -0
- package/src/modes/components/sayknow-pet-widget.ts +27 -8
- package/src/modes/components/session-observer-overlay.ts +187 -32
- package/src/modes/components/settings-selector.ts +60 -18
- package/src/modes/components/tool-execution.ts +138 -27
- package/src/modes/components/tool-status-header.ts +26 -8
- package/src/modes/components/welcome.ts +50 -23
- package/src/modes/controllers/btw-controller.ts +119 -36
- package/src/modes/controllers/command-controller.ts +101 -54
- package/src/modes/controllers/event-controller.ts +119 -27
- package/src/modes/controllers/extension-ui-controller.ts +23 -12
- package/src/modes/controllers/input-controller.ts +100 -8
- package/src/modes/controllers/runtime-mcp-command-controller.ts +29 -6
- package/src/modes/controllers/selector-controller.ts +4 -1
- package/src/modes/interactive-mode.ts +201 -60
- package/src/modes/irc-observation-ledger.ts +71 -15
- package/src/modes/prompt-action-autocomplete.ts +32 -13
- package/src/modes/prompt-suggestion-controller.ts +96 -0
- package/src/modes/runtime-init.ts +20 -2
- package/src/modes/shared/agent-wire/command-dispatch.ts +3 -3
- package/src/modes/shared/agent-wire/workflow-gate-broker.ts +2 -2
- package/src/modes/types.ts +6 -0
- package/src/modes/utils/hotkeys-markdown.ts +64 -36
- package/src/modes/utils/ui-helpers.ts +99 -4
- package/src/prompts/agent-fragments/restricted-bash.md +1 -1
- package/src/prompts/agents/architect.md +17 -3
- package/src/prompts/agents/critic.md +17 -2
- package/src/prompts/agents/executor.md +1 -1
- package/src/prompts/agents/planner.md +8 -1
- package/src/prompts/system/btw-user.md +3 -8
- package/src/prompts/system/prompt-suggestion-system.md +32 -0
- package/src/prompts/system/system-prompt.md +6 -3
- package/src/prompts/tools/cron.md +3 -1
- package/src/prompts/tools/read.md +4 -2
- package/src/prompts/tools/skill-discovery.md +1 -0
- package/src/runtime/memory-domain.ts +66 -0
- package/src/runtime/memory-guard-contract.ts +73 -0
- package/src/runtime/memory-guard.ts +292 -0
- package/src/runtime/memory-limit.ts +50 -0
- package/src/runtime-mcp/client.ts +41 -55
- package/src/runtime-mcp/content-limits.ts +71 -0
- package/src/runtime-mcp/discoverable-tool-metadata.ts +1 -1
- package/src/runtime-mcp/json-rpc.ts +28 -11
- package/src/runtime-mcp/manager.ts +77 -59
- package/src/runtime-mcp/oauth-flow.ts +0 -72
- package/src/runtime-mcp/plugin-network-boundary.ts +101 -0
- package/src/runtime-mcp/redaction.ts +30 -0
- package/src/runtime-mcp/smithery-auth.ts +17 -2
- package/src/runtime-mcp/smithery-connect.ts +11 -1
- package/src/runtime-mcp/transports/http.ts +63 -22
- package/src/sdk/acp/adapter.ts +8 -1
- package/src/sdk/acp/final-text.ts +40 -0
- package/src/sdk/acp/mcp.ts +26 -0
- package/src/sdk/broker/broker.ts +34 -20
- package/src/sdk/broker/identity.ts +22 -12
- package/src/sdk/broker/lifecycle.ts +293 -43
- package/src/sdk/broker/session-index.ts +11 -1
- package/src/sdk/bus/chat-daemon-cli.ts +2 -2
- package/src/sdk/bus/chat-daemon-control.ts +22 -5
- package/src/sdk/bus/config-commands.ts +2 -2
- package/src/sdk/bus/config.ts +10 -2
- package/src/sdk/bus/control-drain-lease.ts +104 -0
- package/src/sdk/bus/conversation-store.ts +40 -6
- package/src/sdk/bus/daemon-paths.ts +2 -0
- package/src/sdk/bus/index.ts +793 -121
- package/src/sdk/bus/kind-aware-reconciliation.ts +242 -0
- package/src/sdk/bus/lifecycle-commands.ts +63 -10
- package/src/sdk/bus/lifecycle-control-runtime.ts +11 -2
- package/src/sdk/bus/lifecycle-orchestrator.ts +32 -1
- package/src/sdk/bus/notification-orchestration.ts +12 -0
- package/src/sdk/bus/notification-service.ts +87 -25
- package/src/sdk/bus/operator-runtime.ts +31 -5
- package/src/sdk/bus/prompt-reconciliation.ts +240 -0
- package/src/sdk/bus/rate-limit-pool.ts +8 -0
- package/src/sdk/bus/recent-activity.ts +90 -26
- package/src/sdk/bus/reconciliation-store.ts +224 -0
- package/src/sdk/bus/telegram-cli.ts +6 -13
- package/src/sdk/bus/telegram-daemon-cli.ts +8 -3
- package/src/sdk/bus/telegram-daemon-contract.ts +34 -9
- package/src/sdk/bus/telegram-daemon-control.ts +161 -40
- package/src/sdk/bus/telegram-daemon.ts +3649 -593
- package/src/sdk/bus/telegram-reference.ts +20 -2
- package/src/sdk/bus/topic-registry.ts +451 -12
- package/src/sdk/cli/session-cli.ts +15 -2
- package/src/sdk/client/discovery.ts +19 -3
- package/src/sdk/client/liveness.ts +49 -0
- package/src/sdk/host/control/dispatch.ts +8 -2
- package/src/sdk/host/control/operations.ts +3 -2
- package/src/sdk/host/host.ts +27 -9
- package/src/sdk/host/query/handlers.ts +125 -5
- package/src/sdk/index.ts +12 -0
- package/src/sdk/lifecycle-session.ts +19 -3
- package/src/sdk/mcp/server.ts +46 -18
- package/src/sdk/prompt-status.ts +97 -0
- package/src/sdk/protocol/operation-inventory.generated.json +145 -0
- package/src/sdk/protocol/operation-registry.ts +24 -4
- package/src/sdk/session-directory.ts +5 -1
- package/src/sdk/session.ts +69 -8
- package/src/sdk/startup-capability.ts +15 -1
- package/src/sdk/transport/auth-preface.ts +82 -0
- package/src/sdk/transport/index.ts +18 -0
- package/src/sdk/transport/relay.ts +252 -0
- package/src/sdk/transport/serve-cli.ts +105 -0
- package/src/sdk/transport/socket.ts +197 -0
- package/src/sdk/transport/stdio.ts +17 -0
- package/src/session/agent-session.ts +1112 -314
- package/src/session/blob-store.ts +25 -7
- package/src/session/btw-contract.ts +59 -0
- package/src/session/fallback-chain-controller.ts +47 -8
- package/src/session/internal/managed-session-scope.ts +1426 -259
- package/src/session/internal/managed-session-storage.ts +414 -238
- package/src/session/internal/native-publish-outcome.ts +271 -0
- package/src/session/memory-guard-checkpoint-participant.ts +131 -0
- package/src/session/session-manager.ts +2079 -469
- package/src/session/session-storage.ts +151 -11
- package/src/session/streaming-output.ts +262 -43
- package/src/setup/credential-import.ts +28 -3
- package/src/setup/provider-onboarding.ts +49 -5
- package/src/setup/provider-presets.json +2 -1
- package/src/skc-runtime/deep-interview-runtime.ts +303 -36
- package/src/skc-runtime/deep-interview-stage.ts +1016 -0
- package/src/skc-runtime/deep-interview-state.ts +8 -5
- package/src/skc-runtime/gc-render.ts +1 -0
- package/src/skc-runtime/gc-runtime.ts +11 -1
- package/src/skc-runtime/linux-proc.ts +70 -36
- package/src/skc-runtime/managed-owner-supervisor.ts +83 -4
- package/src/skc-runtime/memory-guard-owner-claims.ts +389 -0
- package/src/skc-runtime/ralplan-runtime.ts +1057 -75
- package/src/skc-runtime/repository-binding.ts +267 -0
- package/src/skc-runtime/session-state-sidecar.ts +25 -9
- package/src/skc-runtime/state-runtime.ts +50 -12
- package/src/skc-runtime/state-writer.ts +68 -56
- package/src/skc-runtime/team-launch.ts +34 -5
- package/src/skc-runtime/team-runtime.ts +41 -1
- package/src/skc-runtime/team-store.ts +32 -0
- package/src/skc-runtime/team-worker-memory-guard.ts +363 -0
- package/src/skc-runtime/team-workers.ts +1 -0
- package/src/skc-runtime/tmux-common.ts +13 -2
- package/src/skc-runtime/tmux-owner-isolation.ts +20 -1
- package/src/skc-runtime/tmux-sessions.ts +45 -6
- package/src/skc-runtime/ultragoal-guard.ts +93 -15
- package/src/skc-runtime/ultragoal-receipt-freshness.ts +123 -0
- package/src/skc-runtime/ultragoal-runtime.ts +469 -38
- package/src/skc-runtime/workflow-manifest.generated.json +195 -5
- package/src/skc-runtime/workflow-manifest.ts +67 -3
- package/src/skill-state/workflow-hud.ts +25 -2
- package/src/skill-state/workflow-mutation-guard.ts +104 -12
- package/src/slash-commands/builtin-registry.ts +1 -1
- package/src/ssh/utils.ts +14 -0
- package/src/task/discovery.ts +8 -2
- package/src/task/executor.ts +165 -47
- package/src/task/index.ts +123 -15
- package/src/task/provider-retry-status.ts +88 -0
- package/src/task/receipt.ts +3 -0
- package/src/task/render.ts +45 -26
- package/src/task/skc-command.ts +2 -2
- package/src/task/types.ts +55 -10
- package/src/task/ultragoal-redteam-activation.ts +75 -0
- package/src/tools/ask.ts +1 -1
- package/src/tools/ast-edit.ts +2 -2
- package/src/tools/bash-allowed-prefixes.ts +45 -1
- package/src/tools/bash-pty-selection.ts +2 -2
- package/src/tools/browser/launch.ts +41 -6
- package/src/tools/browser/screenshot-format.ts +6 -1
- package/src/tools/cron.ts +1 -1
- package/src/tools/fetch.ts +127 -154
- package/src/tools/image-gen.ts +476 -23
- package/src/tools/index.ts +7 -1
- package/src/tools/output-meta.ts +176 -9
- package/src/tools/path-utils.ts +5 -1
- package/src/tools/read-internals.ts +44 -0
- package/src/tools/read.ts +1544 -310
- package/src/tools/resource-gc.ts +665 -125
- package/src/tools/skill-discovery.ts +39 -3
- package/src/tools/sqlite-reader.ts +63 -5
- package/src/tools/subagent-render.ts +74 -16
- package/src/tools/subagent.ts +2 -0
- package/src/tools/tool-result.ts +14 -1
- package/src/utils/edit-mode.ts +2 -2
- package/src/utils/pasted-image-path.ts +15 -6
- package/src/utils/prompt-suggestion.ts +265 -0
- package/src/utils/shell-snapshot.ts +173 -63
- package/src/utils/sixel.ts +3 -3
- package/src/web/insane/bridge.ts +5 -1
- package/src/web/insane/url-guard.ts +140 -27
- package/src/web/scrapers/docs-rs.ts +30 -5
- package/src/web/scrapers/types.ts +19 -49
- package/src/web/scrapers/utils.ts +12 -26
- package/src/web/search/providers/codex.ts +1 -1
- package/src/workflow/workflow-intent-diff.ts +4 -1
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* Handles /mcp subcommands for managing MCP servers.
|
|
5
5
|
*/
|
|
6
6
|
import * as path from "node:path";
|
|
7
|
+
import { resolveMCPOAuthResourceOrigin, resolveMCPOAuthTokenEndpoint } from "@sayknow-cli/ai";
|
|
7
8
|
import { Spacer, Text } from "@sayknow-cli/tui";
|
|
8
9
|
import { getMCPConfigPath, getProjectDir } from "@sayknow-cli/utils";
|
|
9
10
|
import type { SourceMeta } from "../../capability/types";
|
|
@@ -61,6 +62,7 @@ function withTimeout<T>(promise: Promise<T>, timeoutMs: number, message: string)
|
|
|
61
62
|
*/
|
|
62
63
|
interface OAuthFlowResult {
|
|
63
64
|
credentialId: string;
|
|
65
|
+
tokenEndpoint: string;
|
|
64
66
|
clientId?: string;
|
|
65
67
|
clientSecret?: string;
|
|
66
68
|
}
|
|
@@ -423,6 +425,7 @@ export class MCPCommandController {
|
|
|
423
425
|
try {
|
|
424
426
|
const oauthClientSecret = finalConfig.oauth?.clientSecret ?? "";
|
|
425
427
|
const oauthResult = await this.#handleOAuthFlow(
|
|
428
|
+
finalConfig.url,
|
|
426
429
|
oauth.authorizationUrl,
|
|
427
430
|
oauth.tokenUrl,
|
|
428
431
|
oauth.clientId ?? finalConfig.oauth?.clientId ?? "",
|
|
@@ -439,7 +442,7 @@ export class MCPCommandController {
|
|
|
439
442
|
auth: {
|
|
440
443
|
type: "oauth",
|
|
441
444
|
credentialId: oauthResult.credentialId,
|
|
442
|
-
tokenUrl:
|
|
445
|
+
tokenUrl: oauthResult.tokenEndpoint,
|
|
443
446
|
clientId: persistedClientId,
|
|
444
447
|
clientSecret: persistedClientSecret,
|
|
445
448
|
},
|
|
@@ -480,8 +483,15 @@ export class MCPCommandController {
|
|
|
480
483
|
done();
|
|
481
484
|
this.#handleWizardCancel();
|
|
482
485
|
},
|
|
483
|
-
async (
|
|
484
|
-
|
|
486
|
+
async (
|
|
487
|
+
endpointUrl: string,
|
|
488
|
+
authUrl: string,
|
|
489
|
+
tokenUrl: string,
|
|
490
|
+
clientId: string,
|
|
491
|
+
clientSecret: string,
|
|
492
|
+
scopes: string,
|
|
493
|
+
) => {
|
|
494
|
+
return await this.#handleOAuthFlow(endpointUrl, authUrl, tokenUrl, clientId, clientSecret, scopes);
|
|
485
495
|
},
|
|
486
496
|
async (config: MCPServerConfig) => {
|
|
487
497
|
return await this.#handleTestConnection(config);
|
|
@@ -503,6 +513,7 @@ export class MCPCommandController {
|
|
|
503
513
|
* Handle OAuth authentication flow for MCP server
|
|
504
514
|
*/
|
|
505
515
|
async #handleOAuthFlow(
|
|
516
|
+
endpointUrl: string,
|
|
506
517
|
authUrl: string,
|
|
507
518
|
tokenUrl: string,
|
|
508
519
|
clientId: string,
|
|
@@ -514,11 +525,13 @@ export class MCPCommandController {
|
|
|
514
525
|
): Promise<OAuthFlowResult> {
|
|
515
526
|
const authStorage = this.ctx.session.modelRegistry.authStorage;
|
|
516
527
|
let parsedAuthUrl: URL;
|
|
528
|
+
const resourceOrigin = resolveMCPOAuthResourceOrigin(endpointUrl);
|
|
529
|
+
const tokenEndpoint = resolveMCPOAuthTokenEndpoint(tokenUrl);
|
|
530
|
+
if (!resourceOrigin || !tokenEndpoint) throw new Error("Invalid MCP OAuth configuration.");
|
|
517
531
|
|
|
518
532
|
// Validate OAuth URLs
|
|
519
533
|
try {
|
|
520
534
|
parsedAuthUrl = new URL(authUrl);
|
|
521
|
-
new URL(tokenUrl);
|
|
522
535
|
} catch (_error) {
|
|
523
536
|
throw new Error(
|
|
524
537
|
`Invalid OAuth URLs. Please check:\n Authorization URL: ${authUrl}\n Token URL: ${tokenUrl}`,
|
|
@@ -533,7 +546,7 @@ export class MCPCommandController {
|
|
|
533
546
|
const flow = new MCPOAuthFlow(
|
|
534
547
|
{
|
|
535
548
|
authorizationUrl: authUrl,
|
|
536
|
-
tokenUrl:
|
|
549
|
+
tokenUrl: tokenEndpoint,
|
|
537
550
|
clientId: resolvedClientId,
|
|
538
551
|
clientSecret: resolvedClientSecret,
|
|
539
552
|
scopes: scopes || undefined,
|
|
@@ -618,6 +631,10 @@ export class MCPCommandController {
|
|
|
618
631
|
const oauthCredential: OAuthCredential = {
|
|
619
632
|
type: "oauth",
|
|
620
633
|
...credentials,
|
|
634
|
+
mcpBinding: {
|
|
635
|
+
resourceOrigin,
|
|
636
|
+
tokenEndpoint,
|
|
637
|
+
},
|
|
621
638
|
};
|
|
622
639
|
|
|
623
640
|
// Store under a synthetic provider name
|
|
@@ -625,6 +642,7 @@ export class MCPCommandController {
|
|
|
625
642
|
|
|
626
643
|
return {
|
|
627
644
|
credentialId,
|
|
645
|
+
tokenEndpoint,
|
|
628
646
|
clientId: flow.resolvedClientId,
|
|
629
647
|
clientSecret: flow.registeredClientSecret,
|
|
630
648
|
};
|
|
@@ -1328,6 +1346,10 @@ export class MCPCommandController {
|
|
|
1328
1346
|
this.ctx.showError(`Server "${name}" is disabled. Run /mcp enable ${name} first.`);
|
|
1329
1347
|
return;
|
|
1330
1348
|
}
|
|
1349
|
+
if (found.config.type !== "http" && found.config.type !== "sse") {
|
|
1350
|
+
this.ctx.showError(`Server "${name}" does not use a remote MCP transport.`);
|
|
1351
|
+
return;
|
|
1352
|
+
}
|
|
1331
1353
|
|
|
1332
1354
|
const currentAuth = (found.config as MCPServerConfig & { auth?: MCPAuthConfig }).auth;
|
|
1333
1355
|
if (currentAuth?.type === "oauth") {
|
|
@@ -1341,6 +1363,7 @@ export class MCPCommandController {
|
|
|
1341
1363
|
this.#showMessage(["", theme.fg("muted", `Reauthorizing "${name}"...`), ""].join("\n"));
|
|
1342
1364
|
|
|
1343
1365
|
const oauthResult = await this.#handleOAuthFlow(
|
|
1366
|
+
found.config.url,
|
|
1344
1367
|
oauth.authorizationUrl,
|
|
1345
1368
|
oauth.tokenUrl,
|
|
1346
1369
|
oauth.clientId ?? found.config.oauth?.clientId ?? "",
|
|
@@ -1359,7 +1382,7 @@ export class MCPCommandController {
|
|
|
1359
1382
|
auth: {
|
|
1360
1383
|
type: "oauth",
|
|
1361
1384
|
credentialId: oauthResult.credentialId,
|
|
1362
|
-
tokenUrl:
|
|
1385
|
+
tokenUrl: oauthResult.tokenEndpoint,
|
|
1363
1386
|
clientId: persistedClientId,
|
|
1364
1387
|
clientSecret: persistedClientSecret,
|
|
1365
1388
|
},
|
|
@@ -2057,7 +2057,10 @@ export class SelectorController {
|
|
|
2057
2057
|
this.#clearTransientSessionUi();
|
|
2058
2058
|
const migrationPolicy =
|
|
2059
2059
|
this.ctx.settings?.get("session.directoryMigration") === "disabled" ? "disabled" : "copy-retain";
|
|
2060
|
-
const writableSessionPath = await
|
|
2060
|
+
const writableSessionPath = await this.ctx.sessionManager.prepareManagedCandidateForWrite(
|
|
2061
|
+
sessionPath,
|
|
2062
|
+
migrationPolicy,
|
|
2063
|
+
);
|
|
2061
2064
|
|
|
2062
2065
|
// Switch session via AgentSession (emits hook and tool session events)
|
|
2063
2066
|
if (!(await this.ctx.session.switchSession(writableSessionPath))) return;
|
|
@@ -16,7 +16,14 @@ import {
|
|
|
16
16
|
import { APP_NAME, adjustHsv, getProjectDir, logger, postmortem } from "@sayknow-cli/utils";
|
|
17
17
|
import chalk from "chalk";
|
|
18
18
|
import { AsyncJobManager } from "../async";
|
|
19
|
-
import {
|
|
19
|
+
import {
|
|
20
|
+
type AppKeybinding,
|
|
21
|
+
defaultMessageQueueKeysForPlatform,
|
|
22
|
+
formatKeyHint,
|
|
23
|
+
formatKeyHints,
|
|
24
|
+
KeybindingsManager,
|
|
25
|
+
type KeyDisplayContext,
|
|
26
|
+
} from "../config/keybindings";
|
|
20
27
|
import { isSettingsInitialized, type Settings, settings } from "../config/settings";
|
|
21
28
|
import { DEFAULT_SKC_DEFINITION_NAMES } from "../defaults/skc-defaults";
|
|
22
29
|
import type {
|
|
@@ -41,6 +48,7 @@ import type { SessionContext, SessionManager } from "../session/session-manager"
|
|
|
41
48
|
import { getRecentSessions, getSessionMessageEntryId } from "../session/session-manager";
|
|
42
49
|
import type { LspStartupServerInfo } from "../tools";
|
|
43
50
|
import { formatPhaseDisplayName } from "../tools/todo-write";
|
|
51
|
+
import { copyToClipboard } from "../utils/clipboard";
|
|
44
52
|
import type { EventBus } from "../utils/event-bus";
|
|
45
53
|
import { getSessionAccentAnsi, getSessionAccentHex } from "../utils/session-color";
|
|
46
54
|
import { popTerminalTitle, pushTerminalTitle, setSessionTerminalTitle } from "../utils/title-generator";
|
|
@@ -52,7 +60,7 @@ import type { EvalExecutionComponent } from "./components/eval-execution";
|
|
|
52
60
|
import type { HookEditorComponent } from "./components/hook-editor";
|
|
53
61
|
import type { HookInputComponent } from "./components/hook-input";
|
|
54
62
|
import type { HookSelectorComponent } from "./components/hook-selector";
|
|
55
|
-
import { IrcSplitViewComponent } from "./components/irc-sidebar";
|
|
63
|
+
import { computeIrcSplitWidths, getIrcSidebarSemanticToken, IrcSplitViewComponent } from "./components/irc-sidebar";
|
|
56
64
|
import {
|
|
57
65
|
getPetUnavailableWarning,
|
|
58
66
|
isPetAvailable,
|
|
@@ -64,6 +72,7 @@ import type { ToolExecutionHandle } from "./components/tool-execution";
|
|
|
64
72
|
import { StatusLineComponent } from "./components/tool-status-header";
|
|
65
73
|
import { composeToolText } from "./components/tool-transcript-format";
|
|
66
74
|
import {
|
|
75
|
+
type RecentSession,
|
|
67
76
|
WelcomeComponent,
|
|
68
77
|
type WelcomeLogoMode,
|
|
69
78
|
type LspServerInfo as WelcomeLspServerInfo,
|
|
@@ -83,6 +92,7 @@ import { TodoCommandController } from "./controllers/todo-command-controller";
|
|
|
83
92
|
import { IrcObservationLedger } from "./irc-observation-ledger";
|
|
84
93
|
import { JobsObserver } from "./jobs-observer";
|
|
85
94
|
import { OAuthManualInputManager } from "./oauth-manual-input";
|
|
95
|
+
import { PromptSuggestionController } from "./prompt-suggestion-controller";
|
|
86
96
|
import { SessionObserverRegistry } from "./session-observer-registry";
|
|
87
97
|
import { interruptHint } from "./shared";
|
|
88
98
|
import { shouldShowExtensionCommand } from "./slash-command-visibility";
|
|
@@ -105,9 +115,60 @@ import {
|
|
|
105
115
|
import type { ParsedIrcMessage } from "./utils/irc-message";
|
|
106
116
|
import { addChatChild, prepareTranscriptRebuild, UiHelpers } from "./utils/ui-helpers";
|
|
107
117
|
|
|
108
|
-
|
|
109
|
-
|
|
118
|
+
function buildComposerPlaceholder(
|
|
119
|
+
keybindings: Pick<KeybindingsManager, "getDisplayString">,
|
|
120
|
+
context: KeyDisplayContext,
|
|
121
|
+
options: { readonly busy: boolean; readonly busyPromptMode: "steer" | "queue" },
|
|
122
|
+
): string {
|
|
123
|
+
const parts: string[] = [];
|
|
124
|
+
const submitKey = options.busy ? keybindings.getDisplayString("tui.input.submit", context) : "";
|
|
125
|
+
if (submitKey) {
|
|
126
|
+
const submitAction = options.busyPromptMode === "steer" ? "Steer" : "Queue";
|
|
127
|
+
parts.push(`${submitKey}: ${submitAction}`);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const queueKey = keybindings.getDisplayString("app.message.queue", context);
|
|
131
|
+
const submitQueues = options.busy && options.busyPromptMode === "queue" && submitKey;
|
|
132
|
+
if (queueKey && !submitQueues) parts.push(`${queueKey}: ${options.busy ? "Queue" : "Queue (busy)"}`);
|
|
133
|
+
|
|
134
|
+
const actionHints = [
|
|
135
|
+
["app.thinking.cycle", "Thinking"],
|
|
136
|
+
["app.model.select", "Model"],
|
|
137
|
+
["app.history.search", "History"],
|
|
138
|
+
] as const;
|
|
139
|
+
for (const [id, label] of actionHints) {
|
|
140
|
+
const key = keybindings.getDisplayString(id, context);
|
|
141
|
+
if (key) parts.push(`${key}: ${label}`);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const newlineKeys = context.platform === "win32" ? ["alt+enter", "ctrl+j"] : ["shift+enter", "ctrl+j"];
|
|
145
|
+
parts.push(`${formatKeyHints(newlineKeys, context)}: New line`, `${formatKeyHint("ctrl+c", context)}: Clear`);
|
|
146
|
+
return `Type your message... ${parts.join(" · ")}`;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export function getDefaultComposerPlaceholder(
|
|
150
|
+
context: KeyDisplayContext = { platform: process.platform },
|
|
151
|
+
keybindings?: Pick<KeybindingsManager, "getDisplayString">,
|
|
152
|
+
): string {
|
|
153
|
+
const effectiveKeybindings =
|
|
154
|
+
keybindings ??
|
|
155
|
+
KeybindingsManager.inMemory({
|
|
156
|
+
"app.message.queue": defaultMessageQueueKeysForPlatform(context.platform),
|
|
157
|
+
});
|
|
158
|
+
return buildComposerPlaceholder(effectiveKeybindings, context, { busy: false, busyPromptMode: "steer" });
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
export const DEFAULT_COMPOSER_PLACEHOLDER = getDefaultComposerPlaceholder();
|
|
162
|
+
|
|
163
|
+
export function getComposerPlaceholder(
|
|
164
|
+
keybindings: Pick<KeybindingsManager, "getDisplayString">,
|
|
165
|
+
context: KeyDisplayContext,
|
|
166
|
+
options: { readonly busy: boolean; readonly busyPromptMode: "steer" | "queue" },
|
|
167
|
+
): string {
|
|
168
|
+
return buildComposerPlaceholder(keybindings, context, options);
|
|
169
|
+
}
|
|
110
170
|
const WELCOME_RESERVED_CONTAINER_CHILD_LIMIT = 8;
|
|
171
|
+
const COMPOSER_RIGHT_GUTTER_WIDTH = 1;
|
|
111
172
|
|
|
112
173
|
const IRC_SIDEBAR_TOGGLE_SHADOWING_ACTIONS: readonly AppKeybinding[] = [
|
|
113
174
|
"app.plan.toggle",
|
|
@@ -128,23 +189,6 @@ export function getWelcomeTranscriptReservedRows(chatContainer: Container, width
|
|
|
128
189
|
? 0
|
|
129
190
|
: chatContainer.render(width).length;
|
|
130
191
|
}
|
|
131
|
-
const FRIENDLY_KEY_PARTS: Record<string, string> = {
|
|
132
|
-
alt: "Alt",
|
|
133
|
-
cmd: "Cmd",
|
|
134
|
-
command: "Cmd",
|
|
135
|
-
ctrl: "Ctrl",
|
|
136
|
-
enter: "Enter",
|
|
137
|
-
meta: process.platform === "darwin" ? "Command" : "Meta",
|
|
138
|
-
option: "Option",
|
|
139
|
-
shift: "Shift",
|
|
140
|
-
};
|
|
141
|
-
|
|
142
|
-
function formatShortcutForPlaceholder(key: string): string {
|
|
143
|
-
return key
|
|
144
|
-
.split("+")
|
|
145
|
-
.map(part => FRIENDLY_KEY_PARTS[part.toLowerCase()] ?? (part.length === 1 ? part.toUpperCase() : part))
|
|
146
|
-
.join("+");
|
|
147
|
-
}
|
|
148
192
|
|
|
149
193
|
const HINT_SHIMMER_PALETTE: ShimmerPalette = {
|
|
150
194
|
low: "dim",
|
|
@@ -169,9 +213,9 @@ function configureDefaultComposerChrome(editor: CustomEditor): void {
|
|
|
169
213
|
editor.setClosedBorderBox(true);
|
|
170
214
|
editor.setPromptGutter(undefined);
|
|
171
215
|
editor.setInputPrefix(getDefaultInputPrefix());
|
|
172
|
-
editor.setPlaceholder(
|
|
216
|
+
editor.setPlaceholder(getDefaultComposerPlaceholder());
|
|
173
217
|
editor.setPaddingX(1);
|
|
174
|
-
editor.setRightGutterWidth(
|
|
218
|
+
editor.setRightGutterWidth(COMPOSER_RIGHT_GUTTER_WIDTH);
|
|
175
219
|
editor.setTopBorder(undefined);
|
|
176
220
|
}
|
|
177
221
|
|
|
@@ -264,6 +308,10 @@ export interface InteractiveModeOptions {
|
|
|
264
308
|
initialMessages?: string[];
|
|
265
309
|
}
|
|
266
310
|
|
|
311
|
+
export function selectShutdownDraft(editorText: string, hasActiveBtw: boolean): string {
|
|
312
|
+
return hasActiveBtw ? "" : editorText;
|
|
313
|
+
}
|
|
314
|
+
|
|
267
315
|
export class InteractiveMode implements InteractiveModeContext {
|
|
268
316
|
session: AgentSession;
|
|
269
317
|
sessionManager: SessionManager;
|
|
@@ -336,6 +384,7 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
336
384
|
fileSlashCommands: Set<string> = new Set();
|
|
337
385
|
skillCommands: Map<string, Skill> = new Map();
|
|
338
386
|
oauthManualInput: OAuthManualInputManager = new OAuthManualInputManager();
|
|
387
|
+
promptSuggestion: PromptSuggestionController;
|
|
339
388
|
|
|
340
389
|
#baseSlashCommands: SlashCommand[] = [];
|
|
341
390
|
#resolvedSlashCommands: SlashCommand[] = [];
|
|
@@ -347,6 +396,7 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
347
396
|
#petUnavailableWarningDisposer?: () => void;
|
|
348
397
|
readonly #version: string;
|
|
349
398
|
readonly #changelogMarkdown: string | undefined;
|
|
399
|
+
readonly #keyDisplayContext: KeyDisplayContext;
|
|
350
400
|
|
|
351
401
|
readonly lspServers: LspStartupServerInfo[] | undefined = undefined;
|
|
352
402
|
mcpManager?: import("../runtime-mcp").MCPManager;
|
|
@@ -366,6 +416,9 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
366
416
|
#sttController: SttModeController | undefined;
|
|
367
417
|
#resizeHandler?: () => void;
|
|
368
418
|
#observerRegistry: SessionObserverRegistry;
|
|
419
|
+
#viewportOutputRevision = 0n;
|
|
420
|
+
#viewportOutputIdentity: string;
|
|
421
|
+
|
|
369
422
|
#transcriptRegistry = new TranscriptItemRegistry();
|
|
370
423
|
|
|
371
424
|
/** Direct controller capabilities for consumers that coordinate mode transitions. */
|
|
@@ -394,6 +447,7 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
394
447
|
lspServers: LspStartupServerInfo[] | undefined = undefined,
|
|
395
448
|
mcpManager?: import("../runtime-mcp").MCPManager,
|
|
396
449
|
eventBus?: EventBus,
|
|
450
|
+
keyDisplayContext: KeyDisplayContext = { platform: process.platform },
|
|
397
451
|
) {
|
|
398
452
|
this.session = session;
|
|
399
453
|
this.sessionManager = session.sessionManager;
|
|
@@ -432,6 +486,10 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
432
486
|
this.lspServers = lspServers;
|
|
433
487
|
this.mcpManager = mcpManager;
|
|
434
488
|
this.#eventBus = eventBus;
|
|
489
|
+
this.#keyDisplayContext = keyDisplayContext;
|
|
490
|
+
this.#viewportOutputIdentity = `session:${this.sessionManager.getSessionId()}`;
|
|
491
|
+
|
|
492
|
+
this.keybindings.setDisplayContext(this.#keyDisplayContext);
|
|
435
493
|
const thisMode = this;
|
|
436
494
|
this.#goalModeController = new GoalModeController({
|
|
437
495
|
session: this.session,
|
|
@@ -503,6 +561,14 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
503
561
|
|
|
504
562
|
this.ui = new TUI(new ProcessTerminal(), settings.get("showHardwareCursor"), {
|
|
505
563
|
enableMouse: settings.get("mouse.enabled"),
|
|
564
|
+
copySelection: async text => {
|
|
565
|
+
try {
|
|
566
|
+
await copyToClipboard(text);
|
|
567
|
+
this.showStatus("Selection copied to clipboard");
|
|
568
|
+
} catch (error) {
|
|
569
|
+
this.showError(`Failed to copy selection: ${error instanceof Error ? error.message : String(error)}`);
|
|
570
|
+
}
|
|
571
|
+
},
|
|
506
572
|
});
|
|
507
573
|
this.ui.setClearOnShrink(settings.get("clearOnShrink"));
|
|
508
574
|
this.chatContainer = new Container();
|
|
@@ -513,6 +579,7 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
513
579
|
this.btwContainer = new Container();
|
|
514
580
|
this.editor = new CustomEditor(getEditorTheme());
|
|
515
581
|
configureDefaultComposerChrome(this.editor);
|
|
582
|
+
this.editor.setPlaceholder(this.#getComposerPlaceholder());
|
|
516
583
|
this.editor.setUseTerminalCursor(this.ui.getShowHardwareCursor());
|
|
517
584
|
this.editor.setAutocompleteMaxVisible(settings.get("autocompleteMaxVisible"));
|
|
518
585
|
this.editor.onAutocompleteCancel = () => {
|
|
@@ -540,7 +607,11 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
540
607
|
this.hookWidgetContainerBelow = new Container();
|
|
541
608
|
this.editorContainer = new Container();
|
|
542
609
|
this.editorContainer.addChild(this.editor);
|
|
543
|
-
this.statusLine = new StatusLineComponent(session, {
|
|
610
|
+
this.statusLine = new StatusLineComponent(session, {
|
|
611
|
+
version: this.#version,
|
|
612
|
+
focusDomain: "composer",
|
|
613
|
+
keyDisplayContext: this.#keyDisplayContext,
|
|
614
|
+
});
|
|
544
615
|
this.statusLine.setAutoCompactEnabled(session.autoCompactionEnabled);
|
|
545
616
|
|
|
546
617
|
this.hideThinkingBlock = settings.get("hideThinkingBlock");
|
|
@@ -576,6 +647,7 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
576
647
|
this.#selectorController = new SelectorController(this);
|
|
577
648
|
this.#inputController = new InputController(this);
|
|
578
649
|
this.statusLine.setActionRegistry(this.#inputController.actionRegistry, () => this.keybindings);
|
|
650
|
+
this.promptSuggestion = new PromptSuggestionController(this);
|
|
579
651
|
this.#observerRegistry = new SessionObserverRegistry();
|
|
580
652
|
}
|
|
581
653
|
|
|
@@ -596,6 +668,7 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
596
668
|
if (this.isInitialized) return;
|
|
597
669
|
|
|
598
670
|
this.keybindings = logger.time("InteractiveMode.init:keybindings", () => KeybindingsManager.create());
|
|
671
|
+
this.keybindings.setDisplayContext(this.#keyDisplayContext);
|
|
599
672
|
|
|
600
673
|
// Register session manager flush for signal handlers (SIGINT, SIGTERM, SIGHUP)
|
|
601
674
|
this.#cleanupUnsubscribe = postmortem.register("session-manager-flush", () => this.sessionManager.flush());
|
|
@@ -618,15 +691,9 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
618
691
|
const modelName = this.session.model?.name ?? "Unknown";
|
|
619
692
|
const providerName = this.session.model?.provider ?? "Unknown";
|
|
620
693
|
|
|
621
|
-
//
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
sessions.map(s => ({
|
|
625
|
-
name: s.name,
|
|
626
|
-
timeAgo: s.timeAgo,
|
|
627
|
-
})),
|
|
628
|
-
),
|
|
629
|
-
);
|
|
694
|
+
// Session history is display-only. Never hold the editor and keyboard behind
|
|
695
|
+
// transcript I/O; populate the welcome trail after the interactive surface exists.
|
|
696
|
+
const recentSessions: RecentSession[] = [];
|
|
630
697
|
|
|
631
698
|
const startupQuiet = settings.get("startup.quiet");
|
|
632
699
|
const welcomeLogoMode = resolveWelcomeLogoMode(settings.get("startup.welcomeBannerMode"));
|
|
@@ -652,7 +719,9 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
652
719
|
getViewportRows: () => this.ui.terminal.rows,
|
|
653
720
|
getReservedBottomRows: getWelcomeReservedBottomRows,
|
|
654
721
|
changelogMarkdown: this.#changelogMarkdown,
|
|
722
|
+
rightGutterWidth: COMPOSER_RIGHT_GUTTER_WIDTH,
|
|
655
723
|
collapseChangelog: settings.get("collapseChangelog"),
|
|
724
|
+
keyDisplayContext: this.#keyDisplayContext,
|
|
656
725
|
},
|
|
657
726
|
);
|
|
658
727
|
|
|
@@ -674,6 +743,11 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
674
743
|
this.ui.addChild(this.hookWidgetContainerBelow);
|
|
675
744
|
this.ui.setBottomPinnedComponent(this.statusLine);
|
|
676
745
|
this.ui.setFocus(this.editor);
|
|
746
|
+
this.ui.setViewportOutputSource({
|
|
747
|
+
identity: this.#viewportOutputIdentity,
|
|
748
|
+
revision: this.#viewportOutputRevision,
|
|
749
|
+
});
|
|
750
|
+
|
|
677
751
|
this.petWidget?.dispose();
|
|
678
752
|
this.petWidget = this.#createPetWidget(this.editor);
|
|
679
753
|
const configuredPetMode = settings.get("pet.mode");
|
|
@@ -706,6 +780,12 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
706
780
|
|
|
707
781
|
this.#inputController.setupKeyHandlers();
|
|
708
782
|
this.#inputController.setupEditorSubmitHandler();
|
|
783
|
+
this.editor.onViewportPageScroll = direction => {
|
|
784
|
+
this.ui.scrollViewportPages(direction);
|
|
785
|
+
};
|
|
786
|
+
this.editor.onViewportFollowLive = () => {
|
|
787
|
+
this.ui.followLiveViewport();
|
|
788
|
+
};
|
|
709
789
|
|
|
710
790
|
// Wire observer registry to EventBus
|
|
711
791
|
if (this.#eventBus) {
|
|
@@ -749,6 +829,31 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
749
829
|
if (this.settings.get("tasksPane.defaultVisible")) this.showTasksPane();
|
|
750
830
|
this.#syncIrcSidebarAvailabilityFromSettings();
|
|
751
831
|
this.ui.requestRender(true);
|
|
832
|
+
if (this.#welcomeComponent) {
|
|
833
|
+
const welcomeComponent = this.#welcomeComponent;
|
|
834
|
+
const recentSessionsTimer = setTimeout(() => {
|
|
835
|
+
void logger
|
|
836
|
+
.time("InteractiveMode.init:recentSessions", () =>
|
|
837
|
+
getRecentSessions(this.sessionManager.getSessionDir()),
|
|
838
|
+
)
|
|
839
|
+
.then(sessions => {
|
|
840
|
+
if (this.#welcomeComponent !== welcomeComponent) return;
|
|
841
|
+
welcomeComponent.setRecentSessions(
|
|
842
|
+
sessions.map(session => ({
|
|
843
|
+
name: session.name,
|
|
844
|
+
timeAgo: session.timeAgo,
|
|
845
|
+
})),
|
|
846
|
+
);
|
|
847
|
+
this.ui.requestRender();
|
|
848
|
+
})
|
|
849
|
+
.catch(error => {
|
|
850
|
+
logger.debug("Failed to load recent sessions for welcome screen", {
|
|
851
|
+
error: error instanceof Error ? error.message : String(error),
|
|
852
|
+
});
|
|
853
|
+
});
|
|
854
|
+
}, 0);
|
|
855
|
+
recentSessionsTimer.unref?.();
|
|
856
|
+
}
|
|
752
857
|
|
|
753
858
|
// GitHub star reminder (interactive-only). Register the decline-driven
|
|
754
859
|
// injection contributor and schedule the launch nudge after the first
|
|
@@ -802,7 +907,9 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
802
907
|
// Set up theme file watcher
|
|
803
908
|
onThemeChange(() => {
|
|
804
909
|
clearRenderCache();
|
|
910
|
+
this.#ircSplitView.invalidateTheme();
|
|
805
911
|
configureDefaultComposerChrome(this.editor);
|
|
912
|
+
this.editor.setPlaceholder(this.#getComposerPlaceholder());
|
|
806
913
|
this.ui.invalidate();
|
|
807
914
|
this.updateEditorChrome();
|
|
808
915
|
this.ui.requestRender();
|
|
@@ -1021,25 +1128,11 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
1021
1128
|
return this.session.isStreaming || this.session.isCompacting;
|
|
1022
1129
|
}
|
|
1023
1130
|
|
|
1024
|
-
#getFirstKeyForAction(action: AppKeybinding): string | undefined {
|
|
1025
|
-
return this.keybindings.getKeys(action)[0];
|
|
1026
|
-
}
|
|
1027
|
-
|
|
1028
|
-
#getMessageQueueShortcut(): string | undefined {
|
|
1029
|
-
const preferredAction: AppKeybinding =
|
|
1030
|
-
process.platform === "darwin" ? "app.message.followUp" : "app.message.queue";
|
|
1031
|
-
const fallbackAction: AppKeybinding =
|
|
1032
|
-
process.platform === "darwin" ? "app.message.queue" : "app.message.followUp";
|
|
1033
|
-
return this.#getFirstKeyForAction(preferredAction) ?? this.#getFirstKeyForAction(fallbackAction);
|
|
1034
|
-
}
|
|
1035
|
-
|
|
1036
1131
|
#getComposerPlaceholder(): string {
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
if (queueKey) parts.push(`${formatShortcutForPlaceholder(queueKey)}: Queue`);
|
|
1042
|
-
return `${DEFAULT_COMPOSER_PLACEHOLDER} · ${parts.join(" · ")}`;
|
|
1132
|
+
return getComposerPlaceholder(this.keybindings, this.#keyDisplayContext, {
|
|
1133
|
+
busy: this.#isPromptDeliveryBusy(),
|
|
1134
|
+
busyPromptMode: this.settings.get("busyPromptMode"),
|
|
1135
|
+
});
|
|
1043
1136
|
}
|
|
1044
1137
|
|
|
1045
1138
|
#getWelcomeReservedRows(width: number): number {
|
|
@@ -1056,6 +1149,7 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
1056
1149
|
this.statusLine,
|
|
1057
1150
|
this.hookWidgetContainerAbove,
|
|
1058
1151
|
this.editorContainer,
|
|
1152
|
+
this.petFloorContainer,
|
|
1059
1153
|
this.hookWidgetContainerBelow,
|
|
1060
1154
|
].reduce((rows, component) => rows + component.render(width).length, 0);
|
|
1061
1155
|
|
|
@@ -1123,8 +1217,22 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
1123
1217
|
this.ui.requestRender();
|
|
1124
1218
|
return false;
|
|
1125
1219
|
}
|
|
1220
|
+
if (!settings.canWriteDurableConfig()) {
|
|
1221
|
+
this.showError(
|
|
1222
|
+
"Cannot change settings while config.yml has invalid YAML syntax. Repair config.yml and reload settings.",
|
|
1223
|
+
);
|
|
1224
|
+
return false;
|
|
1225
|
+
}
|
|
1226
|
+
try {
|
|
1227
|
+
settings.set("pet.mode", mode);
|
|
1228
|
+
} catch (error) {
|
|
1229
|
+
if (!settings.canWriteDurableConfig()) {
|
|
1230
|
+
this.showError(error instanceof Error ? error.message : String(error));
|
|
1231
|
+
return false;
|
|
1232
|
+
}
|
|
1233
|
+
throw error;
|
|
1234
|
+
}
|
|
1126
1235
|
apply(mode);
|
|
1127
|
-
settings.set("pet.mode", mode);
|
|
1128
1236
|
this.ui.requestRender();
|
|
1129
1237
|
return true;
|
|
1130
1238
|
}
|
|
@@ -1322,19 +1430,20 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
1322
1430
|
if (this.#isShuttingDown) return;
|
|
1323
1431
|
this.#isShuttingDown = true;
|
|
1324
1432
|
|
|
1325
|
-
//
|
|
1326
|
-
//
|
|
1327
|
-
|
|
1328
|
-
const draftText = this.editor.getText();
|
|
1433
|
+
// `/btw` owns the shared composer while its panel is open. Never persist a
|
|
1434
|
+
// side-chat draft or pending side-chat images into the main-session draft.
|
|
1435
|
+
const hadActiveBtw = this.#btwController.hasOpenPanel();
|
|
1436
|
+
const draftText = selectShutdownDraft(this.editor.getText(), hadActiveBtw);
|
|
1437
|
+
if (hadActiveBtw) this.pendingImages = [];
|
|
1438
|
+
this.#btwController.dispose();
|
|
1329
1439
|
|
|
1330
|
-
// Flush pending session writes before shutdown
|
|
1440
|
+
// Flush pending session writes before shutdown.
|
|
1331
1441
|
await this.sessionManager.flush();
|
|
1332
1442
|
try {
|
|
1333
1443
|
await this.sessionManager.saveDraft(draftText);
|
|
1334
1444
|
} catch (err) {
|
|
1335
1445
|
logger.warn("Failed to save session draft", { error: String(err) });
|
|
1336
1446
|
}
|
|
1337
|
-
this.#btwController.dispose();
|
|
1338
1447
|
|
|
1339
1448
|
// Emit shutdown event to hooks
|
|
1340
1449
|
this.session.setSdkPlanModeHandler(null);
|
|
@@ -1393,6 +1502,7 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
1393
1502
|
: new CustomEditor(getEditorTheme());
|
|
1394
1503
|
|
|
1395
1504
|
configureDefaultComposerChrome(nextEditor);
|
|
1505
|
+
nextEditor.setPlaceholder(this.#getComposerPlaceholder());
|
|
1396
1506
|
nextEditor.setUseTerminalCursor(this.ui.getShowHardwareCursor());
|
|
1397
1507
|
nextEditor.setAutocompleteMaxVisible(this.settings.get("autocompleteMaxVisible"));
|
|
1398
1508
|
nextEditor.onAutocompleteCancel = () => {
|
|
@@ -1421,6 +1531,12 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
1421
1531
|
|
|
1422
1532
|
this.#inputController.setupKeyHandlers();
|
|
1423
1533
|
this.#inputController.setupEditorSubmitHandler();
|
|
1534
|
+
this.editor.onViewportPageScroll = direction => {
|
|
1535
|
+
this.ui.scrollViewportPages(direction);
|
|
1536
|
+
};
|
|
1537
|
+
this.editor.onViewportFollowLive = () => {
|
|
1538
|
+
this.ui.followLiveViewport();
|
|
1539
|
+
};
|
|
1424
1540
|
|
|
1425
1541
|
void this.refreshSlashCommandState().catch(error => {
|
|
1426
1542
|
logger.warn("Failed to refresh slash command state for custom editor", { error: String(error) });
|
|
@@ -1571,6 +1687,21 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
1571
1687
|
return this.#uiHelpers.isKnownSlashCommand(text);
|
|
1572
1688
|
}
|
|
1573
1689
|
|
|
1690
|
+
/** Advances the sticky-viewport source only for semantic transcript output. */
|
|
1691
|
+
recordVisibleTranscriptMutation(): void {
|
|
1692
|
+
const identity = `session:${this.sessionManager.getSessionId()}`;
|
|
1693
|
+
if (identity !== this.#viewportOutputIdentity) {
|
|
1694
|
+
this.#viewportOutputIdentity = identity;
|
|
1695
|
+
this.#viewportOutputRevision = 0n;
|
|
1696
|
+
} else {
|
|
1697
|
+
this.#viewportOutputRevision += 1n;
|
|
1698
|
+
}
|
|
1699
|
+
this.ui.setViewportOutputSource({
|
|
1700
|
+
identity: this.#viewportOutputIdentity,
|
|
1701
|
+
revision: this.#viewportOutputRevision,
|
|
1702
|
+
});
|
|
1703
|
+
}
|
|
1704
|
+
|
|
1574
1705
|
addMessageToChat(message: AgentMessage, options?: { populateHistory?: boolean }): Component[] {
|
|
1575
1706
|
return this.#uiHelpers.addMessageToChat(message, options);
|
|
1576
1707
|
}
|
|
@@ -2025,7 +2156,11 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
2025
2156
|
}
|
|
2026
2157
|
|
|
2027
2158
|
hasActiveBtw(): boolean {
|
|
2028
|
-
return this.#btwController.
|
|
2159
|
+
return this.#btwController.hasOpenPanel();
|
|
2160
|
+
}
|
|
2161
|
+
|
|
2162
|
+
handleBtwFollowUp(question: string): Promise<"accepted" | "busy" | "closed" | "rejected"> {
|
|
2163
|
+
return this.#btwController.submitFollowUp(question);
|
|
2029
2164
|
}
|
|
2030
2165
|
|
|
2031
2166
|
handleBtwEscape(): boolean {
|
|
@@ -2094,12 +2229,18 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
2094
2229
|
}
|
|
2095
2230
|
|
|
2096
2231
|
resetIrcSidebarSession(): void {
|
|
2097
|
-
this.
|
|
2232
|
+
const sidebarVisible = this.#ircSplitView.effectiveSidebarVisible(this.ui.terminal.columns);
|
|
2233
|
+
const rightWidth = computeIrcSplitWidths(this.ui.terminal.columns).rightWidth;
|
|
2234
|
+
const beforeToken = sidebarVisible ? getIrcSidebarSemanticToken(this.ircLedger, rightWidth) : "";
|
|
2235
|
+
this.ircLedger.reset({ retireCurrentSessionIdentities: true });
|
|
2236
|
+
this.#ircSplitView.resetSource();
|
|
2237
|
+
const afterToken = sidebarVisible ? getIrcSidebarSemanticToken(this.ircLedger, rightWidth) : "";
|
|
2098
2238
|
this.#eventController.resetIrcObservations();
|
|
2099
2239
|
this.#ircSidebarRequestedVisible = false;
|
|
2100
2240
|
this.#ircSplitView.setVisible(false);
|
|
2101
2241
|
this.#uiHelpers.resetIrcSidebarHint();
|
|
2102
2242
|
this.#syncIrcSidebarAvailabilityFromSettings();
|
|
2243
|
+
if (sidebarVisible && beforeToken !== afterToken) this.recordVisibleTranscriptMutation();
|
|
2103
2244
|
}
|
|
2104
2245
|
|
|
2105
2246
|
#invalidateIrcSidebarRender(): void {
|