@pellux/goodvibes-tui 2.0.21 → 2.1.1
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 +65 -1
- package/README.md +30 -29
- package/docs/README.md +8 -5
- package/docs/foundation-artifacts/operator-contract.json +1 -1
- package/package.json +28 -19
- package/src/cli/management.ts +5 -2
- package/src/cli/tui-startup.ts +34 -39
- package/src/core/agent-view-render.ts +157 -0
- package/src/core/approval-alert.ts +49 -11
- package/src/core/bookmark-navigation.ts +7 -1
- package/src/core/budget-breach-notifier.ts +27 -8
- package/src/core/compaction-receipt.ts +1 -1
- package/src/core/context-usage.ts +1 -1
- package/src/core/conversation-compaction-render.ts +3 -3
- package/src/core/conversation-display-only.ts +86 -0
- package/src/core/conversation-event-navigation.ts +27 -0
- package/src/core/conversation-line-cache.ts +216 -447
- package/src/core/conversation-render-context.ts +20 -27
- package/src/core/conversation-rendering.ts +157 -575
- package/src/core/conversation-splash-state.ts +6 -1
- package/src/core/conversation-types.ts +35 -0
- package/src/core/conversation-usage.ts +12 -0
- package/src/core/conversation.ts +130 -131
- package/src/core/long-task-notifier.ts +100 -31
- package/src/core/notices.ts +75 -0
- package/src/core/pairing-tailscale-gateway.ts +1 -1
- package/src/core/process-output-log.ts +143 -0
- package/src/core/rewind-receipt.ts +1 -1
- package/src/core/session-focus.ts +190 -0
- package/src/core/session-resume-core.ts +23 -81
- package/src/core/stream-event-wiring.ts +31 -5
- package/src/core/system-message-noise.ts +2 -2
- package/src/core/system-message-router.ts +16 -18
- package/src/core/turn-event-wiring.ts +272 -33
- package/src/core/work-tree-focus.ts +290 -0
- package/src/core/work-tree-fold-store.ts +143 -0
- package/src/core/work-tree-model.ts +799 -0
- package/src/core/work-tree-render.ts +384 -0
- package/src/core/work-tree-sources.ts +184 -0
- package/src/core/work-tree-wiring.ts +176 -0
- package/src/core/workstream-notification.ts +36 -6
- package/src/core/wrfc-notice-titles.ts +37 -0
- package/src/input/agents-modal-text.ts +119 -0
- package/src/input/agents-modal.ts +699 -0
- package/src/input/bookmark-modal.ts +33 -9
- package/src/input/changes-git.ts +251 -0
- package/src/input/changes-modal.ts +629 -0
- package/src/input/changes-model.ts +125 -0
- package/src/input/command-palette-types.ts +41 -0
- package/src/input/command-palette.ts +272 -0
- package/src/input/command-reference.ts +2 -2
- package/src/input/command-registry.ts +77 -35
- package/src/input/commands/acp-runtime.ts +19 -9
- package/src/input/commands/channel-runtime.ts +2 -2
- package/src/input/commands/ci-runtime.ts +1 -1
- package/src/input/commands/codebase-runtime.ts +1 -1
- package/src/input/commands/config.ts +7 -1
- package/src/input/commands/context-window.ts +25 -19
- package/src/input/commands/control-room-runtime.ts +18 -18
- package/src/input/commands/conversation-runtime.ts +0 -1
- package/src/input/commands/cost-runtime.ts +29 -20
- package/src/input/commands/diff-runtime.ts +35 -181
- package/src/input/commands/eval.ts +1 -1
- package/src/input/commands/experience-runtime.ts +3 -7
- package/src/input/commands/fresh-conversation.ts +86 -0
- package/src/input/commands/git-runtime.ts +5 -22
- package/src/input/commands/graph-runtime.ts +1 -1
- package/src/input/commands/guidance-runtime.ts +1 -1
- package/src/input/commands/health-runtime.ts +8 -9
- package/src/input/commands/hooks-runtime.ts +2 -2
- package/src/input/commands/hosted-runtime.ts +3 -3
- package/src/input/commands/incident-runtime.ts +3 -3
- package/src/input/commands/intelligence-runtime.ts +6 -9
- package/src/input/commands/knowledge.ts +2 -2
- package/src/input/commands/legacy-panel-command.ts +57 -0
- package/src/input/commands/local-auth-runtime.ts +8 -9
- package/src/input/commands/local-provider-runtime.ts +7 -4
- package/src/input/commands/local-runtime.ts +12 -15
- package/src/input/commands/local-setup-review.ts +1 -1
- package/src/input/commands/local-setup.ts +13 -19
- package/src/input/commands/memory.ts +1 -1
- package/src/input/commands/notify-runtime.ts +9 -0
- package/src/input/commands/operator-runtime.ts +10 -12
- package/src/input/commands/permissions-provenance.ts +3 -3
- package/src/input/commands/planning-runtime.ts +7 -7
- package/src/input/commands/platform-sandbox-runtime.ts +2 -2
- package/src/input/commands/platform-services-runtime.ts +1 -1
- package/src/input/commands/policy-dispatch.ts +2 -2
- package/src/input/commands/policy.ts +3 -3
- package/src/input/commands/provider.ts +1 -1
- package/src/input/commands/remote-runtime.ts +1 -1
- package/src/input/commands/review-runtime.ts +39 -94
- package/src/input/commands/rewind-runtime.ts +81 -108
- package/src/input/commands/runtime-services.ts +15 -17
- package/src/input/commands/services-runtime.ts +2 -2
- package/src/input/commands/session-content.ts +21 -5
- package/src/input/commands/session-workflow.ts +13 -38
- package/src/input/commands/settings-sync-runtime.ts +2 -2
- package/src/input/commands/shell-core.ts +19 -4
- package/src/input/commands/skills-runtime.ts +2 -2
- package/src/input/commands/status-runtime.ts +13 -0
- package/src/input/commands/subscription-runtime.ts +1 -1
- package/src/input/commands/tasks-runtime.ts +2 -8
- package/src/input/commands/work-plan-runtime.ts +4 -4
- package/src/input/commands/workstream-attempts.ts +24 -47
- package/src/input/commands/workstream-runtime.ts +2 -2
- package/src/input/commands/worktree-runtime.ts +3 -3
- package/src/input/commands.ts +3 -1
- package/src/input/composer-editor.ts +44 -0
- package/src/input/concealed-input.ts +1 -1
- package/src/input/config-modal-types.ts +20 -8
- package/src/input/config-modal.ts +106 -105
- package/src/input/confirm-dialog-types.ts +28 -0
- package/src/input/confirm-dialog.ts +70 -0
- package/src/input/delete-key-policy.ts +3 -3
- package/src/input/feed-context-factory.ts +15 -16
- package/src/input/handler-command-route.ts +7 -42
- package/src/input/handler-content-actions.ts +16 -15
- package/src/input/handler-feed-routes.ts +26 -211
- package/src/input/handler-feed.ts +68 -95
- package/src/input/handler-interactions.ts +5 -3
- package/src/input/handler-modal-routes.ts +215 -216
- package/src/input/handler-modal-stack.ts +81 -11
- package/src/input/handler-modal-token-routes.ts +4 -0
- package/src/input/handler-onboarding.ts +0 -1
- package/src/input/handler-picker-routes.ts +65 -107
- package/src/input/handler-session-view-route.ts +149 -0
- package/src/input/handler-shortcuts.ts +16 -154
- package/src/input/handler-types.ts +4 -2
- package/src/input/handler-ui-state.ts +45 -15
- package/src/input/handler-work-tree-route.ts +123 -0
- package/src/input/handler.ts +25 -70
- package/src/input/keybindings.ts +16 -71
- package/src/input/masked-entry-modal.ts +117 -0
- package/src/input/mcp-workspace.ts +48 -17
- package/src/input/model-picker-filter.ts +8 -0
- package/src/input/model-picker-open.ts +99 -0
- package/src/input/model-picker-types.ts +1 -1
- package/src/input/model-picker.ts +92 -9
- package/src/input/notifications-modal.ts +123 -0
- package/src/input/overlay-filter.ts +26 -0
- package/src/input/profile-picker-modal.ts +37 -8
- package/src/input/search.ts +3 -3
- package/src/input/selection-modal-queue.ts +2 -0
- package/src/input/selection-modal.ts +28 -16
- package/src/input/session-picker-modal.ts +33 -8
- package/src/input/settings-modal-activation.ts +7 -2
- package/src/input/settings-modal-data.ts +11 -6
- package/src/input/settings-modal-types.ts +1 -1
- package/src/input/settings-modal.ts +20 -20
- package/src/input/submission-intent.ts +1 -1
- package/src/input/submission-router.ts +4 -9
- package/src/input/surface-modal-host.ts +110 -0
- package/src/input/theme-settings-actions.ts +82 -0
- package/src/input/usage-modal.ts +183 -0
- package/src/input/views.ts +97 -0
- package/src/main.ts +175 -165
- package/src/permissions/hunk-selection.ts +1 -1
- package/src/permissions/prompt-card.ts +511 -0
- package/src/permissions/prompt.ts +59 -622
- package/src/renderer/agents-modal.ts +310 -0
- package/src/renderer/autocomplete-overlay.ts +42 -220
- package/src/renderer/back-to-bottom.ts +80 -0
- package/src/renderer/block-actions-overlay.ts +30 -48
- package/src/renderer/bookmark-modal.ts +48 -79
- package/src/renderer/changes-modal.ts +325 -0
- package/src/renderer/code-block.ts +184 -106
- package/src/renderer/command-palette.ts +93 -0
- package/src/renderer/composer-fragments.ts +4 -4
- package/src/renderer/composer.ts +146 -0
- package/src/renderer/compositor.ts +26 -160
- package/src/renderer/config-modal.ts +185 -81
- package/src/renderer/confirm-dialog.ts +50 -0
- package/src/renderer/context-inspector.ts +116 -154
- package/src/renderer/context-status-hint.ts +4 -4
- package/src/renderer/conversation-layout.ts +20 -0
- package/src/renderer/conversation-overlays.ts +94 -84
- package/src/renderer/conversation-surface.ts +19 -38
- package/src/renderer/diff-tint.ts +98 -0
- package/src/renderer/file-picker-overlay.ts +63 -90
- package/src/renderer/footer-targets.ts +38 -0
- package/src/renderer/git-status.ts +3 -4
- package/src/renderer/header-line.ts +140 -117
- package/src/renderer/help-overlay.ts +133 -219
- package/src/renderer/history-search-overlay.ts +15 -12
- package/src/renderer/lane-graph/bead.ts +800 -0
- package/src/renderer/lane-graph/glyphs.ts +134 -0
- package/src/renderer/lane-graph/layout.ts +248 -0
- package/src/renderer/lane-graph/paint.ts +537 -0
- package/src/renderer/lane-graph/semantic-memo.ts +77 -0
- package/src/renderer/layout-engine.ts +2 -57
- package/src/renderer/layout.ts +7 -13
- package/src/renderer/markdown-inline.ts +2 -1
- package/src/renderer/markdown-table.ts +17 -12
- package/src/renderer/markdown.ts +92 -34
- package/src/renderer/masked-entry-modal.ts +78 -0
- package/src/renderer/mcp-workspace.ts +166 -203
- package/src/renderer/model-workspace.ts +381 -436
- package/src/renderer/notifications-modal.ts +116 -0
- package/src/renderer/onboarding/onboarding-wizard.ts +178 -588
- package/src/renderer/process-view.ts +192 -0
- package/src/renderer/profile-picker-modal.ts +58 -110
- package/src/renderer/search-overlay.ts +6 -3
- package/src/renderer/selection-modal-overlay.ts +87 -327
- package/src/renderer/semantic-diff.ts +2 -2
- package/src/renderer/session-chips.ts +102 -0
- package/src/renderer/session-picker-modal.ts +177 -297
- package/src/renderer/settings-modal-connections.ts +14 -23
- package/src/renderer/settings-modal-context.ts +367 -0
- package/src/renderer/settings-modal-helpers.ts +6 -11
- package/src/renderer/settings-modal.ts +322 -726
- package/src/renderer/shell-surface.ts +277 -175
- package/src/renderer/shortcuts-overlay.ts +217 -0
- package/src/renderer/status-line.ts +475 -0
- package/src/renderer/surface-compose.ts +174 -0
- package/src/renderer/surface-kit-extra.ts +303 -0
- package/src/renderer/surface-kit-list.ts +366 -0
- package/src/renderer/surface-kit-parts.ts +360 -0
- package/src/renderer/surface-kit.ts +568 -0
- package/src/renderer/syntax-highlighter.ts +280 -197
- package/src/renderer/syntax-theme.ts +51 -0
- package/src/renderer/system-message.ts +0 -1
- package/src/renderer/term-caps.ts +42 -1
- package/src/renderer/terminal-bg-probe.ts +116 -19
- package/src/renderer/terminal-palette-probe.ts +322 -0
- package/src/renderer/terminal-palette-reader.ts +183 -0
- package/src/renderer/terminal-palette.ts +58 -0
- package/src/renderer/theme-mode-config.ts +16 -1
- package/src/renderer/theme.ts +234 -207
- package/src/renderer/thinking.ts +0 -1
- package/src/renderer/throbber.ts +188 -0
- package/src/renderer/toast-center.ts +119 -0
- package/src/renderer/ui-factory.ts +39 -602
- package/src/renderer/ui-primitives.ts +8 -25
- package/src/renderer/usage-modal.ts +353 -0
- package/src/renderer/user-message.ts +58 -0
- package/src/renderer/voice-capture-chip.ts +53 -0
- package/src/runtime/bootstrap-command-context.ts +0 -5
- package/src/runtime/bootstrap-command-parts.ts +38 -89
- package/src/runtime/bootstrap-core.ts +13 -15
- package/src/runtime/bootstrap-hook-bridge.ts +12 -21
- package/src/runtime/bootstrap-notifier-sync.ts +17 -1
- package/src/runtime/bootstrap-shell.ts +16 -50
- package/src/runtime/bootstrap.ts +14 -14
- package/src/runtime/client/fleet-union.ts +5 -5
- package/src/runtime/client/hosted-exit.ts +2 -2
- package/src/runtime/client/hosted-sessions.ts +1 -1
- package/src/runtime/client/spine-adoption.ts +1 -1
- package/src/runtime/context-accounting-source.ts +5 -4
- package/src/runtime/index.ts +1 -0
- package/src/runtime/notification-dispatch.ts +102 -29
- package/src/runtime/recovery-offer-wiring.ts +4 -1
- package/src/runtime/recovery-prompt.ts +31 -15
- package/src/runtime/runtime-services-types.ts +10 -6
- package/src/runtime/services.ts +17 -12
- package/src/runtime/session-continuity-hints.ts +2 -5
- package/src/runtime/session-inbound-inputs.ts +1 -1
- package/src/runtime/session-resume-liveness-confirm.ts +14 -2
- package/src/runtime/startup-typeahead-gate.ts +103 -0
- package/src/runtime/store/domains/domain-read-matrix.ts +0 -1
- package/src/runtime/store/domains/index.ts +0 -8
- package/src/runtime/store/selectors/index.ts +0 -28
- package/src/runtime/store/state.ts +0 -8
- package/src/runtime/ui-services.ts +4 -6
- package/src/runtime/usage-tracker.ts +348 -0
- package/src/runtime/wrfc-persistence.ts +4 -4
- package/src/shell/blocking-input.ts +92 -2
- package/src/shell/recovery-input-helpers.ts +1 -1
- package/src/shell/session-views.ts +539 -0
- package/src/shell/status-report.ts +86 -0
- package/src/shell/transcript-scroll.ts +68 -0
- package/src/shell/ui-openers.ts +84 -172
- package/src/shell/view-openers.ts +205 -0
- package/src/tools/wrfc-agent-guard.ts +22 -2
- package/src/utils/format-duration.ts +4 -8
- package/src/utils/splash-lines.ts +9 -1
- package/src/utils/terminal-width.ts +56 -0
- package/src/verification/live-verifier.ts +0 -10
- package/src/version.ts +1 -1
- package/src/{panels → views}/agent-inspector-shared.ts +2 -2
- package/src/{panels → views}/builtin-modals.ts +22 -21
- package/src/views/builtin-views.ts +135 -0
- package/src/{panels → views}/confirm-state.ts +9 -9
- package/src/{panels → views}/diff-review-model.ts +10 -3
- package/src/{panels → views}/eval-registry.ts +1 -1
- package/src/{panels → views}/fleet-acts.ts +49 -85
- package/src/{panels/fleet-panel-format.ts → views/fleet-format.ts} +40 -40
- package/src/{panels → views}/fleet-gateway.ts +5 -5
- package/src/{panels → views}/fleet-observed-render.ts +16 -16
- package/src/{panels → views}/fleet-read-model.ts +9 -9
- package/src/{panels/fleet-tabs.ts → views/fleet-session-tabs.ts} +13 -13
- package/src/{panels → views}/fleet-spawn.ts +33 -49
- package/src/{panels → views}/fleet-steer.ts +12 -12
- package/src/{panels → views}/fleet-stop.ts +4 -4
- package/src/{panels → views}/fleet-transcript.ts +26 -27
- package/src/{panels/fleet-panel-worktree-detail.ts → views/fleet-worktree-detail.ts} +7 -7
- package/src/{panels → views}/hosted-session-feed.ts +6 -6
- package/src/views/modal-surface-registry.ts +41 -0
- package/src/{panels → views}/modals/devices-modal.ts +2 -2
- package/src/{panels → views}/modals/hooks-modal.ts +13 -13
- package/src/{panels → views}/modals/keybindings-modal.ts +19 -27
- package/src/{panels → views}/modals/knowledge-modal.ts +6 -5
- package/src/{panels → views}/modals/local-auth-modal.ts +22 -21
- package/src/{panels → views}/modals/marketplace-modal.ts +11 -11
- package/src/{panels → views}/modals/memory-modal.ts +8 -8
- package/src/{panels → views}/modals/modal-surface-helpers.ts +15 -5
- package/src/{panels → views}/modals/pairing-modal.ts +9 -9
- package/src/{panels → views}/modals/planning-modal.ts +15 -20
- package/src/{panels → views}/modals/plugins-modal.ts +6 -6
- package/src/{panels → views}/modals/policy-modal.ts +13 -5
- package/src/{panels → views}/modals/provider-health-modal.ts +4 -4
- package/src/{panels → views}/modals/remote-modal.ts +3 -3
- package/src/{panels → views}/modals/sandbox-modal.ts +4 -4
- package/src/{panels → views}/modals/security-modal.ts +22 -16
- package/src/{panels → views}/modals/services-modal.ts +3 -3
- package/src/{panels → views}/modals/settings-sync-modal.ts +4 -4
- package/src/{panels → views}/modals/skills-modal.ts +9 -9
- package/src/{panels → views}/modals/subscription-modal.ts +3 -3
- package/src/{panels → views}/modals/work-plan-modal.ts +10 -13
- package/src/views/notifications-feed.ts +314 -0
- package/src/{panels → views}/polish-core.ts +38 -36
- package/src/{panels → views}/polish-tables.ts +35 -26
- package/src/{panels → views}/polish.ts +101 -95
- package/src/{panels → views}/project-planning-answer-actions.ts +3 -3
- package/src/{panels → views}/provider-health-routes.ts +14 -14
- package/src/{panels → views}/search-focus.ts +8 -8
- package/src/{panels → views}/session-maintenance.ts +11 -11
- package/src/views/skills-discovery.ts +159 -0
- package/src/views/view-deps.ts +80 -0
- package/src/views/view-panel-adapter.ts +53 -0
- package/src/{panels → views}/workstream-graph-render.ts +1 -1
- package/src/core/conversation-fold.ts +0 -101
- package/src/core/conversation-turn-structure.ts +0 -464
- package/src/core/conversation-user-receipts.ts +0 -42
- package/src/input/commands/operator-panel-runtime.ts +0 -186
- package/src/input/panel-integration-actions.ts +0 -33
- package/src/input/panel-mouse-geometry.ts +0 -97
- package/src/input/panel-paste-flood-guard.ts +0 -86
- package/src/panels/base-panel.ts +0 -301
- package/src/panels/builtin/agent.ts +0 -27
- package/src/panels/builtin/development.ts +0 -92
- package/src/panels/builtin/knowledge.ts +0 -12
- package/src/panels/builtin/operations.ts +0 -177
- package/src/panels/builtin/session.ts +0 -81
- package/src/panels/builtin/shared.ts +0 -357
- package/src/panels/builtin-panels.ts +0 -28
- package/src/panels/cost-tracker-panel.ts +0 -746
- package/src/panels/diff-panel.ts +0 -797
- package/src/panels/diff-review-panel.ts +0 -395
- package/src/panels/expandable-list-panel.ts +0 -189
- package/src/panels/fleet-deep-link.ts +0 -31
- package/src/panels/fleet-panel.ts +0 -799
- package/src/panels/git-panel.ts +0 -800
- package/src/panels/hosted-session-panel.ts +0 -221
- package/src/panels/index.ts +0 -21
- package/src/panels/local-auth-panel.ts +0 -478
- package/src/panels/notifications-feed.ts +0 -127
- package/src/panels/notifications-panel.ts +0 -160
- package/src/panels/panel-confirm-overlay.ts +0 -72
- package/src/panels/panel-manager.ts +0 -791
- package/src/panels/plugins-panel.ts +0 -371
- package/src/panels/scrollable-list-panel.ts +0 -498
- package/src/panels/skills-panel.ts +0 -454
- package/src/panels/token-budget-panel.ts +0 -688
- package/src/panels/types.ts +0 -191
- package/src/panels/wrfc-panel-format.ts +0 -133
- package/src/renderer/diff-view.ts +0 -134
- package/src/renderer/fleet-tab-strip.ts +0 -56
- package/src/renderer/footer-tips.ts +0 -53
- package/src/renderer/fullscreen-primitives.ts +0 -146
- package/src/renderer/fullscreen-workspace.ts +0 -194
- package/src/renderer/hint-grammar.ts +0 -52
- package/src/renderer/modal-factory.ts +0 -480
- package/src/renderer/overlay-box.ts +0 -154
- package/src/renderer/overlay-viewport.ts +0 -104
- package/src/renderer/panel-composite.ts +0 -145
- package/src/renderer/panel-workspace-bar.ts +0 -54
- package/src/renderer/process-indicator.ts +0 -163
- package/src/renderer/tab-strip.ts +0 -222
- package/src/renderer/text-layout.ts +0 -31
- package/src/renderer/tool-call.ts +0 -276
- package/src/renderer/tool-result-expanded-lines.ts +0 -48
- package/src/renderer/tool-result-summary.ts +0 -219
- package/src/runtime/diagnostics/panels/index.ts +0 -21
- package/src/runtime/diagnostics/panels/ops.ts +0 -156
- package/src/runtime/perf/panel-contracts.ts +0 -32
- package/src/runtime/store/domains/panels.ts +0 -117
- package/src/verification/verification-ledger.ts +0 -707
- /package/src/{panels → views}/memory-consolidation-gateway.ts +0 -0
- /package/src/{panels → views}/modals/modal-theme.ts +0 -0
- /package/src/{panels → views}/provider-health-domains.ts +0 -0
|
@@ -4,7 +4,6 @@ import type { SearchManager } from './search.ts';
|
|
|
4
4
|
import type { HistorySearch } from './input-history.ts';
|
|
5
5
|
import type { ConversationManager } from '../core/conversation';
|
|
6
6
|
import type { AutocompleteEngine } from './autocomplete.ts';
|
|
7
|
-
import type { PanelManager } from '../panels/panel-manager.ts';
|
|
8
7
|
import type { KeybindingsManager } from './keybindings.ts';
|
|
9
8
|
import type { KillRing } from './kill-ring.ts';
|
|
10
9
|
import { wordBoundaryBack, wordBoundaryForward } from './kill-ring.ts';
|
|
@@ -17,8 +16,6 @@ type WrappedPromptInfo = {
|
|
|
17
16
|
};
|
|
18
17
|
|
|
19
18
|
export type GlobalShortcutRouteState = {
|
|
20
|
-
panelFocused: boolean;
|
|
21
|
-
panelManager: PanelManager;
|
|
22
19
|
keybindingsManager: KeybindingsManager;
|
|
23
20
|
prompt: string;
|
|
24
21
|
cursorPos: number;
|
|
@@ -45,7 +42,6 @@ export type GlobalShortcutRouteState = {
|
|
|
45
42
|
handleRedo: () => void;
|
|
46
43
|
handlePaste: () => void;
|
|
47
44
|
handleEscape: () => void;
|
|
48
|
-
cyclePanelTab: (direction: 'next' | 'prev') => void;
|
|
49
45
|
killRing: KillRing;
|
|
50
46
|
};
|
|
51
47
|
|
|
@@ -56,40 +52,27 @@ export function handleGlobalShortcutToken(
|
|
|
56
52
|
): boolean {
|
|
57
53
|
if (token.type !== 'key') return false;
|
|
58
54
|
|
|
59
|
-
// Fast-path: BARE pageup/pagedown scroll the transcript
|
|
60
|
-
//
|
|
61
|
-
// chords, so they must fall through to the keybinding lookup below instead of
|
|
62
|
-
// being swallowed here as a scroll.
|
|
55
|
+
// Fast-path: BARE pageup/pagedown scroll the transcript (modified ones fall
|
|
56
|
+
// through to the keybinding lookup below).
|
|
63
57
|
if (token.logicalName === 'pageup' && !token.ctrl) {
|
|
64
|
-
if (state.panelFocused) return false;
|
|
65
58
|
state.scroll(-Math.max(1, viewportHeight - 2));
|
|
66
59
|
return true;
|
|
67
60
|
}
|
|
68
61
|
if (token.logicalName === 'pagedown' && !token.ctrl) {
|
|
69
|
-
if (state.panelFocused) return false;
|
|
70
62
|
state.scroll(Math.max(1, viewportHeight - 2));
|
|
71
63
|
return true;
|
|
72
64
|
}
|
|
73
65
|
// Bare escape is also not in the keybinding table.
|
|
74
|
-
if (token.logicalName === 'escape'
|
|
66
|
+
if (token.logicalName === 'escape') {
|
|
75
67
|
state.handleEscape();
|
|
76
68
|
return true;
|
|
77
69
|
}
|
|
78
70
|
|
|
79
|
-
// Bare F2
|
|
80
|
-
//
|
|
81
|
-
// in handlePromptKeyToken (handler-feed-routes.ts) where it used to live.
|
|
82
|
-
// That location only ever runs when the panel workspace does NOT already
|
|
83
|
-
// own focus (handlePanelFocusToken, which runs before it, swallows every
|
|
84
|
-
// unclaimed key once panelFocused is true and reports it handled). The
|
|
85
|
-
// practical effect was that F2 could OPEN+focus the Fleet panel exactly
|
|
86
|
-
// once; every subsequent press while already focused vanished silently,
|
|
87
|
-
// "F2 pressed 4x never closed the panel" (evaluator finding). Routing
|
|
88
|
-
// it here, before handlePanelFocusToken ever sees the token, gives F2 the
|
|
89
|
-
// same toggle semantics as Ctrl+O below, matching how Ctrl+P/panel-picker
|
|
90
|
-
// was already reachable regardless of panelFocused.
|
|
71
|
+
// Bare F2 opens the Agents modal (hardcoded, like pageup/pagedown/escape;
|
|
72
|
+
// F2 inside the Agents modal closes it, see input/agents-modal.ts).
|
|
91
73
|
if (token.logicalName === 'f2' && !token.ctrl && !token.meta) {
|
|
92
|
-
|
|
74
|
+
state.commandContext?.openAgents?.();
|
|
75
|
+
state.requestRender();
|
|
93
76
|
return true;
|
|
94
77
|
}
|
|
95
78
|
|
|
@@ -98,10 +81,9 @@ export function handleGlobalShortcutToken(
|
|
|
98
81
|
// escape/f2, because it is not in the keybinding table and bare Tab is
|
|
99
82
|
// already heavily overloaded. Arrives as the legacy xterm backtab literal
|
|
100
83
|
// ('\x1b[Z') OR, under a kitty/CSI-u terminal, as tab-with-shift. Only when
|
|
101
|
-
// the composer owns focus
|
|
102
|
-
//
|
|
103
|
-
|
|
104
|
-
if (!state.panelFocused && (token.logicalName === '\x1b[Z' || (token.logicalName === 'tab' && token.shift))) {
|
|
84
|
+
// the composer owns focus; modal/picker routes run earlier and swallow the
|
|
85
|
+
// token before it reaches here, so overlays keep their reverse-tab too.
|
|
86
|
+
if (token.logicalName === '\x1b[Z' || (token.logicalName === 'tab' && token.shift)) {
|
|
105
87
|
cycleSessionPermissionMode(state);
|
|
106
88
|
return true;
|
|
107
89
|
}
|
|
@@ -133,10 +115,9 @@ export function handleGlobalShortcutToken(
|
|
|
133
115
|
return true;
|
|
134
116
|
|
|
135
117
|
case 'voice-input':
|
|
136
|
-
// Start recording, or stop the recording already running. Routed globally
|
|
137
|
-
//
|
|
138
|
-
//
|
|
139
|
-
// not wired, so a stray Alt+V never lands in the prompt as text.
|
|
118
|
+
// Start recording, or stop the recording already running. Routed globally;
|
|
119
|
+
// still consumed when voice input is not wired, so a stray Alt+V never
|
|
120
|
+
// lands in the prompt as text.
|
|
140
121
|
state.commandContext?.toggleVoiceInput?.();
|
|
141
122
|
return true;
|
|
142
123
|
|
|
@@ -154,110 +135,17 @@ export function handleGlobalShortcutToken(
|
|
|
154
135
|
state.commandContext?.clearScreen?.();
|
|
155
136
|
return true;
|
|
156
137
|
|
|
157
|
-
case 'panel-close-all': {
|
|
158
|
-
const pm = state.panelManager;
|
|
159
|
-
for (const p of pm.getAllOpen()) pm.close(p.id);
|
|
160
|
-
pm.hide();
|
|
161
|
-
state.panelFocused = false;
|
|
162
|
-
state.requestRender();
|
|
163
|
-
return true;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
case 'panel-close': {
|
|
167
|
-
const pm = state.panelManager;
|
|
168
|
-
const active = pm.getActivePanel();
|
|
169
|
-
// Give the active panel a chance to consume Ctrl+X for an
|
|
170
|
-
// in-panel action (FleetPanel session-tab detach) before it closes the
|
|
171
|
-
// panel outright, see Panel.interceptPanelClose's doc comment.
|
|
172
|
-
if (active?.interceptPanelClose?.()) {
|
|
173
|
-
// fix: a consumed Ctrl+X (the Fleet panel's session-tab detach)
|
|
174
|
-
// used to leave panelFocused untouched, so focus stayed on the panel
|
|
175
|
-
//, the evaluator's "Ctrl+X detach landed focus in the panel and a
|
|
176
|
-
// typed question became nav keys". Detach is a leave-taking action:
|
|
177
|
-
// like the ordinary close below, it hands control back to the
|
|
178
|
-
// composer rather than leaving the user stranded on the fleet tree.
|
|
179
|
-
state.panelFocused = false;
|
|
180
|
-
state.requestRender();
|
|
181
|
-
return true;
|
|
182
|
-
}
|
|
183
|
-
if (active) {
|
|
184
|
-
pm.close(active.id);
|
|
185
|
-
state.requestRender();
|
|
186
|
-
}
|
|
187
|
-
state.panelFocused = false;
|
|
188
|
-
return true;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
138
|
case 'command-palette':
|
|
192
139
|
state.commandContext?.openCommandPalette?.();
|
|
193
140
|
state.requestRender();
|
|
194
141
|
return true;
|
|
195
142
|
|
|
196
|
-
case '
|
|
197
|
-
|
|
198
|
-
state.
|
|
143
|
+
case 'open-agents':
|
|
144
|
+
// Ctrl+O: the Agents modal (the same as F2).
|
|
145
|
+
state.commandContext?.openAgents?.();
|
|
199
146
|
state.requestRender();
|
|
200
147
|
return true;
|
|
201
148
|
|
|
202
|
-
case 'panel-focus-toggle': {
|
|
203
|
-
// Global entry point for the focus-toggle key (Ctrl+G): from the prompt
|
|
204
|
-
// it grabs focus for the panel workspace. Once the workspace already has
|
|
205
|
-
// focus we let it fall through (return false) so handlePanelFocusToken
|
|
206
|
-
// can do the top/bottom pane swap, keeping that behavior in one place.
|
|
207
|
-
if (state.panelFocused) return false;
|
|
208
|
-
const pm = state.panelManager;
|
|
209
|
-
if (pm.isVisible() && pm.getAllOpen().length > 0) {
|
|
210
|
-
state.panelFocused = true;
|
|
211
|
-
state.requestRender();
|
|
212
|
-
return true;
|
|
213
|
-
}
|
|
214
|
-
return false;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
case 'panel-tab-next':
|
|
218
|
-
state.cyclePanelTab('next');
|
|
219
|
-
return true;
|
|
220
|
-
|
|
221
|
-
case 'panel-tab-prev':
|
|
222
|
-
state.cyclePanelTab('prev');
|
|
223
|
-
return true;
|
|
224
|
-
|
|
225
|
-
case 'panel-tab-1':
|
|
226
|
-
case 'panel-tab-2':
|
|
227
|
-
case 'panel-tab-3':
|
|
228
|
-
case 'panel-tab-4':
|
|
229
|
-
case 'panel-tab-5':
|
|
230
|
-
case 'panel-tab-6':
|
|
231
|
-
case 'panel-tab-7':
|
|
232
|
-
case 'panel-tab-8':
|
|
233
|
-
case 'panel-tab-9': {
|
|
234
|
-
// Alt+1..9: jump directly to the Nth workspace tab. Routed globally (like
|
|
235
|
-
// panel-tab-next/prev) so the jump works whether focus is on the prompt or
|
|
236
|
-
// the workspace; gated on visibility, matching cyclePanelTab semantics.
|
|
237
|
-
// a chord jump is "I'm going panel-driving" (focus rule 1a), the
|
|
238
|
-
// jump now also grabs keyboard focus, matching F2/Ctrl+O/Ctrl+P, so j/k
|
|
239
|
-
// land in the newly-active tab immediately instead of the composer.
|
|
240
|
-
const pm = state.panelManager;
|
|
241
|
-
if (pm.isVisible()) {
|
|
242
|
-
const index = Number(action.slice('panel-tab-'.length)) - 1;
|
|
243
|
-
pm.activateWorkspaceIndex(index);
|
|
244
|
-
pm.focusPanels();
|
|
245
|
-
state.panelFocused = true;
|
|
246
|
-
state.requestRender();
|
|
247
|
-
}
|
|
248
|
-
return true;
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
case 'panel-ops': {
|
|
252
|
-
// Ctrl+O: TOGGLE the Fleet panel (same semantics as F2 above; see
|
|
253
|
-
// toggleFleetPanel's doc comment). The former Ops Control panel was
|
|
254
|
-
// retired to an 'ops-control' -> 'fleet' alias; rather than route
|
|
255
|
-
// through the now-aliased openOpsPanel callback (which opens without
|
|
256
|
-
// transferring focus), this operates on 'fleet' directly.
|
|
257
|
-
toggleFleetPanel(state);
|
|
258
|
-
return true;
|
|
259
|
-
}
|
|
260
|
-
|
|
261
149
|
case 'history-search':
|
|
262
150
|
state.historySearch.open(state.prompt);
|
|
263
151
|
state.requestRender();
|
|
@@ -433,17 +321,6 @@ export function handleGlobalShortcutToken(
|
|
|
433
321
|
}
|
|
434
322
|
}
|
|
435
323
|
|
|
436
|
-
/**
|
|
437
|
-
* toggleFleetPanel, the shared F2 / Ctrl+O TOGGLE (item 2): if the
|
|
438
|
-
* Fleet panel is open AND the panel workspace currently owns keyboard focus
|
|
439
|
-
* with Fleet as the active tab, the chord CLOSES it and returns focus to the
|
|
440
|
-
* composer; if Fleet is open but not the focused/active tab, the chord brings
|
|
441
|
-
* it to front and focuses it; if Fleet isn't open at all, the chord opens and
|
|
442
|
-
* focuses it. Uses `state.panelFocused` (not a panelManager query) for the
|
|
443
|
-
* focus check, consistent with every other case in this file and with what
|
|
444
|
-
* the mocked PanelManager test doubles in global-shortcuts.test.ts actually
|
|
445
|
-
* implement.
|
|
446
|
-
*/
|
|
447
324
|
/**
|
|
448
325
|
* Cycle the session permission mode (Shift+Tab). The change goes through the
|
|
449
326
|
* SDK config surface, configManager.set('permissions.mode', ...), which is
|
|
@@ -461,18 +338,3 @@ function cycleSessionPermissionMode(state: GlobalShortcutRouteState): void {
|
|
|
461
338
|
state.commandContext?.print(`[Permissions] Mode: ${permissionModeLabel(next)}`);
|
|
462
339
|
state.requestRender();
|
|
463
340
|
}
|
|
464
|
-
|
|
465
|
-
function toggleFleetPanel(state: GlobalShortcutRouteState): void {
|
|
466
|
-
const pm = state.panelManager;
|
|
467
|
-
const fleetOpen = pm.getAllOpen().some((p) => p.id === 'fleet');
|
|
468
|
-
const fleetIsFocusedActive = fleetOpen && state.panelFocused && pm.getActivePanel()?.id === 'fleet';
|
|
469
|
-
if (fleetIsFocusedActive) {
|
|
470
|
-
pm.close('fleet');
|
|
471
|
-
state.panelFocused = false;
|
|
472
|
-
} else {
|
|
473
|
-
pm.open('fleet');
|
|
474
|
-
pm.focusPanels();
|
|
475
|
-
state.panelFocused = true;
|
|
476
|
-
}
|
|
477
|
-
state.requestRender();
|
|
478
|
-
}
|
|
@@ -97,8 +97,7 @@ export interface InputHandlerLike {
|
|
|
97
97
|
// ── Modal state ───────────────────────────────────────────────────────────
|
|
98
98
|
commandMode: boolean;
|
|
99
99
|
modalStack: string[];
|
|
100
|
-
modalReturnFocus: 'prompt' | '
|
|
101
|
-
panelFocused: boolean;
|
|
100
|
+
modalReturnFocus: 'prompt' | 'indicator';
|
|
102
101
|
indicatorFocused: boolean;
|
|
103
102
|
helpOverlayActive: boolean;
|
|
104
103
|
helpScrollOffset: number;
|
|
@@ -118,6 +117,9 @@ export interface InputHandlerLike {
|
|
|
118
117
|
modelPicker: ModelPickerModal;
|
|
119
118
|
filePicker: FilePickerModal;
|
|
120
119
|
blockActionsMenu: BlockActionsMenu;
|
|
120
|
+
surfaceModals: import('./surface-modal-host.ts').SurfaceModalHost;
|
|
121
|
+
sessionView: import('./handler-session-view-route.ts').SessionViewControls | null;
|
|
122
|
+
transcriptScroll: import('./handler-modal-stack.ts').TranscriptScrollControls | null;
|
|
121
123
|
selectionModal: SelectionModal;
|
|
122
124
|
|
|
123
125
|
// ── Onboarding ────────────────────────────────────────────────────────────
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { InputToken } from '@pellux/goodvibes-sdk/platform/core';
|
|
2
2
|
import type { InfiniteBuffer } from '@pellux/goodvibes-terminal-shell';
|
|
3
3
|
import type { SearchManager } from './search.ts';
|
|
4
|
+
import type { OverlayFilter, OverlayFilters } from './overlay-filter.ts';
|
|
5
|
+
import { isTextBackspace } from './delete-key-policy.ts';
|
|
4
6
|
import type { HistorySearch } from './input-history.ts';
|
|
5
7
|
import type { ConversationManager } from '../core/conversation';
|
|
6
8
|
import type {
|
|
@@ -289,36 +291,64 @@ type OverlayRouteState = {
|
|
|
289
291
|
helpScrollOffset: number;
|
|
290
292
|
shortcutsOverlayActive: boolean;
|
|
291
293
|
shortcutsScrollOffset: number;
|
|
294
|
+
/** The overlays' always-live search rows (absent in minimal test states). */
|
|
295
|
+
overlayFilters?: OverlayFilters;
|
|
292
296
|
requestRender: () => void;
|
|
293
297
|
handleEscape: () => void;
|
|
294
298
|
};
|
|
295
299
|
|
|
300
|
+
/**
|
|
301
|
+
* Keys shared by the help and shortcuts overlays: ↑↓ and PgUp/PgDn scroll
|
|
302
|
+
* (never past the end the renderer recorded), printable text goes into the
|
|
303
|
+
* always-live search row (the offset returns to the top as the list
|
|
304
|
+
* narrows), Backspace edits it, Esc closes. Returns the new scroll offset.
|
|
305
|
+
*/
|
|
306
|
+
function routeFilteredOverlayKey(token: InputToken, offset: number, filter: OverlayFilter | undefined): number {
|
|
307
|
+
const max = filter ? filter.maxScroll : 100;
|
|
308
|
+
if (token.type === 'key') {
|
|
309
|
+
if (token.logicalName === 'up') return Math.max(0, Math.min(offset, max) - 1);
|
|
310
|
+
if (token.logicalName === 'down') return Math.min(offset + 1, max);
|
|
311
|
+
if (token.logicalName === 'pageup') return Math.max(0, Math.min(offset, max) - 10);
|
|
312
|
+
if (token.logicalName === 'pagedown') return Math.min(offset + 10, max);
|
|
313
|
+
if (filter && isTextBackspace(token.logicalName ?? '') && filter.query.length > 0) {
|
|
314
|
+
filter.query = filter.query.slice(0, -1);
|
|
315
|
+
return 0;
|
|
316
|
+
}
|
|
317
|
+
return offset;
|
|
318
|
+
}
|
|
319
|
+
if (token.type === 'text' && filter) {
|
|
320
|
+
filter.query += token.value;
|
|
321
|
+
return 0;
|
|
322
|
+
}
|
|
323
|
+
return offset;
|
|
324
|
+
}
|
|
325
|
+
|
|
296
326
|
export function handleOverlayToken(state: OverlayRouteState, token: InputToken): boolean {
|
|
297
327
|
if (state.helpOverlayActive) {
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
328
|
+
const filter = state.overlayFilters?.help;
|
|
329
|
+
if (token.type === 'key' && token.logicalName === 'escape') {
|
|
330
|
+
state.handleEscape();
|
|
331
|
+
return true;
|
|
332
|
+
}
|
|
333
|
+
// '?' toggles help closed, but only while the query is empty; once
|
|
334
|
+
// something is typed, '?' is just another character.
|
|
335
|
+
if (token.type === 'text' && token.value === '?' && (!filter || filter.query.length === 0)) {
|
|
306
336
|
state.helpOverlayActive = false;
|
|
307
337
|
state.helpScrollOffset = 0;
|
|
338
|
+
filter?.clear();
|
|
339
|
+
} else {
|
|
340
|
+
state.helpScrollOffset = routeFilteredOverlayKey(token, state.helpScrollOffset, filter);
|
|
308
341
|
}
|
|
309
342
|
state.requestRender();
|
|
310
343
|
return true;
|
|
311
344
|
}
|
|
312
345
|
|
|
313
346
|
if (state.shortcutsOverlayActive) {
|
|
314
|
-
if (token.type === 'key') {
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
return true;
|
|
318
|
-
}
|
|
319
|
-
if (token.logicalName === 'up') state.shortcutsScrollOffset = Math.max(0, state.shortcutsScrollOffset - 1);
|
|
320
|
-
else if (token.logicalName === 'down') state.shortcutsScrollOffset = Math.min(state.shortcutsScrollOffset + 1, 50);
|
|
347
|
+
if (token.type === 'key' && token.logicalName === 'escape') {
|
|
348
|
+
state.handleEscape();
|
|
349
|
+
return true;
|
|
321
350
|
}
|
|
351
|
+
state.shortcutsScrollOffset = routeFilteredOverlayKey(token, state.shortcutsScrollOffset, state.overlayFilters?.shortcuts);
|
|
322
352
|
state.requestRender();
|
|
323
353
|
return true;
|
|
324
354
|
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* handler-work-tree-route.ts, the keyboard inside the conversation work tree.
|
|
3
|
+
*
|
|
4
|
+
* The `focus-work-tree` binding (Alt+Up, Ctrl+Up) moves the keyboard from the
|
|
5
|
+
* composer onto the work tree's rows. There:
|
|
6
|
+
*
|
|
7
|
+
* ↑ ↓ move between beads (and turn headers and agent lanes)
|
|
8
|
+
* ← → fold / unfold
|
|
9
|
+
* Enter open a bead's body; on an agent lane open that agent full
|
|
10
|
+
* screen; on a ▶ bead open that background process's output
|
|
11
|
+
* y copy the focused row's content
|
|
12
|
+
* Esc back to typing (never stops or cancels anything)
|
|
13
|
+
*
|
|
14
|
+
* Any other key hands the keyboard back to the composer and is typed there,
|
|
15
|
+
* so starting to type never needs an Esc first.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import type { InputToken } from '@pellux/goodvibes-sdk/platform/core';
|
|
19
|
+
import type { ConversationManager } from '../core/conversation.ts';
|
|
20
|
+
import { handleBlockCopy } from './handler-content-actions.ts';
|
|
21
|
+
|
|
22
|
+
export interface WorkTreeRouteState {
|
|
23
|
+
readonly conversationManager: ConversationManager | null;
|
|
24
|
+
/** The token matches the `focus-work-tree` binding. */
|
|
25
|
+
readonly enterMatch: boolean;
|
|
26
|
+
/** The last visible transcript line (where focus lands on entry). */
|
|
27
|
+
readonly anchorLine: number;
|
|
28
|
+
readonly scrollTop: number;
|
|
29
|
+
readonly viewportHeight: number;
|
|
30
|
+
readonly scroll: (delta: number) => void;
|
|
31
|
+
readonly requestRender: () => void;
|
|
32
|
+
readonly onCopied: () => void;
|
|
33
|
+
/** Open an agent full screen (Enter on its lane); false when it cannot be opened. */
|
|
34
|
+
readonly openAgent?: (agentId: string) => boolean;
|
|
35
|
+
/** Open a background process's output (Enter on its ▶ bead); false when it cannot be opened. */
|
|
36
|
+
readonly openProcess?: (processId: string) => boolean;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** Scroll so the focused row (and as much of its opened body as fits) is visible. */
|
|
40
|
+
function revealFocus(state: WorkTreeRouteState): void {
|
|
41
|
+
const block = state.conversationManager?.workTree.focusBlock();
|
|
42
|
+
if (!block) return;
|
|
43
|
+
const top = block.startLine;
|
|
44
|
+
const bottom = block.startLine + Math.min(Math.max(1, block.lineCount), state.viewportHeight) - 1;
|
|
45
|
+
if (top < state.scrollTop) state.scroll(top - state.scrollTop);
|
|
46
|
+
else if (bottom >= state.scrollTop + state.viewportHeight) state.scroll(bottom - (state.scrollTop + state.viewportHeight) + 1);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** Returns true when the token was handled here. */
|
|
50
|
+
export function handleWorkTreeToken(state: WorkTreeRouteState, token: InputToken): boolean {
|
|
51
|
+
const cm = state.conversationManager;
|
|
52
|
+
if (!cm) return false;
|
|
53
|
+
const tree = cm.workTree;
|
|
54
|
+
|
|
55
|
+
if (!tree.focused) {
|
|
56
|
+
if (token.type !== 'key' || !state.enterMatch) return false;
|
|
57
|
+
if (tree.enter(state.anchorLine)) revealFocus(state);
|
|
58
|
+
state.requestRender();
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (token.type === 'text') {
|
|
63
|
+
if (token.value === 'y') {
|
|
64
|
+
const block = tree.focusBlock();
|
|
65
|
+
if (block) handleBlockCopy(cm, () => block.startLine, state.requestRender, state.onCopied);
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
// Typing goes back to the composer.
|
|
69
|
+
tree.leave();
|
|
70
|
+
state.requestRender();
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
if (token.type !== 'key') return false;
|
|
74
|
+
|
|
75
|
+
if (!token.ctrl && !token.meta) {
|
|
76
|
+
switch (token.logicalName) {
|
|
77
|
+
case 'escape':
|
|
78
|
+
tree.leave();
|
|
79
|
+
state.requestRender();
|
|
80
|
+
return true;
|
|
81
|
+
case 'up':
|
|
82
|
+
case 'down':
|
|
83
|
+
tree.move(token.logicalName === 'up' ? -1 : 1);
|
|
84
|
+
revealFocus(state);
|
|
85
|
+
state.requestRender();
|
|
86
|
+
return true;
|
|
87
|
+
case 'enter': {
|
|
88
|
+
const wt = tree.focusBlock()?.workTree;
|
|
89
|
+
const opened = wt?.kind === 'lane' && wt.agentId ? state.openAgent?.(wt.agentId)
|
|
90
|
+
: wt?.kind === 'bead' && wt.processId ? state.openProcess?.(wt.processId)
|
|
91
|
+
: false;
|
|
92
|
+
if (opened) {
|
|
93
|
+
tree.leave();
|
|
94
|
+
state.requestRender();
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
tree.act('activate');
|
|
98
|
+
revealFocus(state);
|
|
99
|
+
state.requestRender();
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
case 'left':
|
|
103
|
+
case 'right':
|
|
104
|
+
tree.act(token.logicalName === 'left' ? 'fold' : 'unfold');
|
|
105
|
+
revealFocus(state);
|
|
106
|
+
state.requestRender();
|
|
107
|
+
return true;
|
|
108
|
+
case 'y':
|
|
109
|
+
{
|
|
110
|
+
const block = tree.focusBlock();
|
|
111
|
+
if (block) handleBlockCopy(cm, () => block.startLine, state.requestRender, state.onCopied);
|
|
112
|
+
}
|
|
113
|
+
return true;
|
|
114
|
+
default:
|
|
115
|
+
break;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
if (state.enterMatch) return true;
|
|
119
|
+
// Anything else goes back to the composer (and is handled there).
|
|
120
|
+
tree.leave();
|
|
121
|
+
state.requestRender();
|
|
122
|
+
return false;
|
|
123
|
+
}
|