@pellux/goodvibes-tui 1.1.0 → 1.7.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 +85 -21
- package/README.md +20 -11
- package/docs/foundation-artifacts/operator-contract.json +1 -1
- package/package.json +2 -2
- package/src/core/alert-gating.ts +67 -0
- package/src/core/approval-alert.ts +72 -0
- package/src/core/budget-breach-notifier.ts +106 -0
- package/src/core/conversation-rendering.ts +19 -0
- package/src/core/conversation.ts +18 -0
- package/src/core/focus-tracker.ts +41 -0
- package/src/core/long-task-notifier.ts +33 -6
- package/src/core/system-message-router.ts +37 -51
- package/src/core/turn-cancellation.ts +20 -0
- package/src/core/turn-event-wiring.ts +64 -3
- package/src/export/cost-utils.ts +36 -0
- package/src/input/command-registry.ts +38 -1
- package/src/input/commands/checkpoint-runtime.ts +280 -0
- package/src/input/commands/codebase-runtime.ts +192 -0
- package/src/input/commands/eval.ts +1 -1
- package/src/input/commands/health-runtime.ts +1 -1
- package/src/input/commands/image-runtime.ts +112 -0
- package/src/input/commands/intelligence-runtime.ts +11 -1
- package/src/input/commands/local-auth-runtime.ts +4 -1
- package/src/input/commands/local-runtime.ts +9 -3
- package/src/input/commands/marketplace-runtime.ts +2 -2
- package/src/input/commands/memory.ts +6 -1
- package/src/input/commands/operator-panel-runtime.ts +40 -24
- package/src/input/commands/planning-runtime.ts +26 -3
- package/src/input/commands/platform-sandbox-runtime.ts +1 -6
- package/src/input/commands/plugin-runtime.ts +2 -2
- package/src/input/commands/policy-dispatch.ts +21 -0
- package/src/input/commands/provider-accounts-runtime.ts +1 -1
- package/src/input/commands/qrcode-runtime.ts +3 -3
- package/src/input/commands/recall-review.ts +35 -0
- package/src/input/commands/remote-runtime.ts +3 -3
- package/src/input/commands/runtime-services.ts +54 -13
- package/src/input/commands/services-runtime.ts +1 -1
- package/src/input/commands/session-workflow.ts +16 -1
- package/src/input/commands/settings-sync-runtime.ts +1 -1
- package/src/input/commands/shell-core.ts +15 -7
- package/src/input/commands/skills-runtime.ts +2 -8
- package/src/input/commands/subscription-runtime.ts +2 -2
- package/src/input/commands/test-runtime.ts +277 -0
- package/src/input/commands/websearch-runtime.ts +101 -0
- package/src/input/commands/work-plan-runtime.ts +36 -10
- package/src/input/commands/workstream-runtime.ts +338 -0
- package/src/input/commands.ts +12 -0
- package/src/input/config-modal-types.ts +161 -0
- package/src/input/config-modal.ts +377 -0
- package/src/input/feed-context-factory.ts +7 -8
- package/src/input/handler-command-route.ts +27 -17
- package/src/input/handler-feed-routes.ts +61 -23
- package/src/input/handler-feed.ts +47 -23
- package/src/input/handler-interactions.ts +1 -3
- package/src/input/handler-modal-routes.ts +65 -0
- package/src/input/handler-modal-stack.ts +3 -5
- package/src/input/handler-modal-token-routes.ts +16 -49
- package/src/input/handler-picker-routes.ts +11 -94
- package/src/input/handler-shortcuts.ts +24 -14
- package/src/input/handler-types.ts +2 -6
- package/src/input/handler-ui-state.ts +10 -22
- package/src/input/handler.ts +6 -28
- package/src/input/keybindings.ts +22 -8
- package/src/input/model-picker-types.ts +24 -6
- package/src/input/model-picker.ts +58 -0
- package/src/input/panel-integration-actions.ts +9 -170
- package/src/input/settings-modal-data.ts +95 -0
- package/src/input/settings-modal-mutations.ts +6 -4
- package/src/main.ts +24 -27
- package/src/panels/agent-inspector-shared.ts +2 -1
- package/src/panels/base-panel.ts +22 -1
- package/src/panels/builtin/agent.ts +21 -107
- package/src/panels/builtin/development.ts +15 -61
- package/src/panels/builtin/knowledge.ts +8 -32
- package/src/panels/builtin/operations.ts +84 -428
- package/src/panels/builtin/session.ts +21 -112
- package/src/panels/builtin/shared.ts +9 -43
- package/src/panels/builtin-modals.ts +218 -0
- package/src/panels/builtin-panels.ts +5 -0
- package/src/panels/cost-tracker-panel.ts +36 -10
- package/src/panels/diff-panel.ts +12 -43
- package/src/panels/eval-registry.ts +60 -0
- package/src/panels/fleet-panel.ts +800 -0
- package/src/panels/fleet-read-model.ts +477 -0
- package/src/panels/fleet-steer.ts +92 -0
- package/src/panels/fleet-stop.ts +125 -0
- package/src/panels/fleet-tabs.ts +230 -0
- package/src/panels/fleet-transcript.ts +356 -0
- package/src/panels/index.ts +7 -31
- package/src/panels/modals/hooks-modal.ts +187 -0
- package/src/panels/modals/keybindings-modal.ts +151 -0
- package/src/panels/modals/knowledge-modal.ts +158 -0
- package/src/panels/modals/local-auth-modal.ts +132 -0
- package/src/panels/modals/marketplace-modal.ts +218 -0
- package/src/panels/modals/memory-modal.ts +180 -0
- package/src/panels/modals/modal-surface-helpers.ts +54 -0
- package/src/panels/modals/modal-theme.ts +36 -0
- package/src/panels/modals/pairing-modal.ts +144 -0
- package/src/panels/modals/planning-modal.ts +282 -0
- package/src/panels/modals/plugins-modal.ts +174 -0
- package/src/panels/modals/policy-modal.ts +256 -0
- package/src/panels/modals/provider-health-modal.ts +136 -0
- package/src/panels/modals/remote-modal.ts +115 -0
- package/src/panels/modals/sandbox-modal.ts +150 -0
- package/src/panels/modals/security-modal.ts +217 -0
- package/src/panels/modals/services-modal.ts +179 -0
- package/src/panels/modals/settings-sync-modal.ts +142 -0
- package/src/panels/modals/skills-modal.ts +189 -0
- package/src/panels/modals/subscription-modal.ts +172 -0
- package/src/panels/modals/work-plan-modal.ts +149 -0
- package/src/panels/panel-confirm-overlay.ts +72 -0
- package/src/panels/panel-manager.ts +108 -5
- package/src/panels/project-planning-answer-actions.ts +4 -2
- package/src/panels/skills-panel.ts +7 -51
- package/src/panels/types.ts +13 -0
- package/src/permissions/hunk-selection.ts +179 -0
- package/src/permissions/prompt.ts +60 -4
- package/src/renderer/compaction-history-modal.ts +19 -3
- package/src/renderer/compaction-preview.ts +13 -2
- package/src/renderer/compaction-quality.ts +100 -0
- package/src/renderer/config-modal.ts +81 -0
- package/src/renderer/conversation-overlays.ts +10 -17
- package/src/renderer/fleet-tab-strip.ts +56 -0
- package/src/renderer/footer-tips.ts +10 -2
- package/src/renderer/git-status.ts +40 -0
- package/src/renderer/help-overlay.ts +2 -2
- package/src/renderer/model-workspace.ts +44 -1
- package/src/renderer/panel-workspace-bar.ts +8 -2
- package/src/renderer/turn-injection.ts +114 -0
- package/src/runtime/bootstrap-command-context.ts +21 -1
- package/src/runtime/bootstrap-command-parts.ts +34 -7
- package/src/runtime/bootstrap-core.ts +14 -4
- package/src/runtime/bootstrap-shell.ts +29 -16
- package/src/runtime/bootstrap.ts +11 -17
- package/src/runtime/code-index-services.ts +112 -0
- package/src/runtime/orchestrator-core-services.ts +49 -0
- package/src/runtime/process-lifecycle.ts +3 -1
- package/src/runtime/services.ts +91 -43
- package/src/runtime/ui-services.ts +8 -0
- package/src/runtime/workstream-services.ts +195 -0
- package/src/shell/blocking-input.ts +22 -1
- package/src/shell/ui-openers.ts +129 -17
- package/src/utils/format-duration.ts +8 -18
- package/src/utils/splash-lines.ts +1 -1
- package/src/version.ts +1 -1
- package/src/panels/agent-inspector-panel.ts +0 -786
- package/src/panels/approval-panel.ts +0 -252
- package/src/panels/automation-control-panel.ts +0 -479
- package/src/panels/cockpit-panel.ts +0 -481
- package/src/panels/cockpit-read-model.ts +0 -238
- package/src/panels/communication-panel.ts +0 -256
- package/src/panels/control-plane-panel.ts +0 -470
- package/src/panels/debug-panel.ts +0 -615
- package/src/panels/docs-panel.ts +0 -384
- package/src/panels/eval-panel.ts +0 -627
- package/src/panels/file-explorer-panel.ts +0 -673
- package/src/panels/file-preview-panel.ts +0 -517
- package/src/panels/hooks-panel.ts +0 -401
- package/src/panels/incident-review-panel.ts +0 -406
- package/src/panels/intelligence-panel.ts +0 -383
- package/src/panels/knowledge-graph-panel.ts +0 -515
- package/src/panels/marketplace-panel.ts +0 -399
- package/src/panels/memory-panel.ts +0 -558
- package/src/panels/ops-control-panel.ts +0 -329
- package/src/panels/ops-strategy-panel.ts +0 -321
- package/src/panels/orchestration-panel.ts +0 -465
- package/src/panels/panel-list-panel.ts +0 -566
- package/src/panels/plan-dashboard-panel.ts +0 -707
- package/src/panels/policy-panel.ts +0 -517
- package/src/panels/project-planning-panel.ts +0 -731
- package/src/panels/provider-health-panel.ts +0 -678
- package/src/panels/provider-health-tracker.ts +0 -310
- package/src/panels/provider-health-views.ts +0 -567
- package/src/panels/qr-panel.ts +0 -280
- package/src/panels/remote-panel.ts +0 -534
- package/src/panels/routes-panel.ts +0 -241
- package/src/panels/sandbox-panel.ts +0 -456
- package/src/panels/security-panel.ts +0 -447
- package/src/panels/services-panel.ts +0 -329
- package/src/panels/session-browser-panel.ts +0 -496
- package/src/panels/settings-sync-panel.ts +0 -398
- package/src/panels/subscription-panel.ts +0 -342
- package/src/panels/symbol-outline-panel.ts +0 -619
- package/src/panels/system-messages-panel.ts +0 -364
- package/src/panels/tasks-panel.ts +0 -608
- package/src/panels/thinking-panel.ts +0 -333
- package/src/panels/tool-inspector-panel.ts +0 -537
- package/src/panels/work-plan-panel.ts +0 -540
- package/src/panels/worktree-panel.ts +0 -360
- package/src/panels/wrfc-panel.ts +0 -790
- package/src/renderer/agent-detail-modal.ts +0 -466
- package/src/renderer/live-tail-modal.ts +0 -156
- package/src/renderer/process-modal.ts +0 -671
- package/src/renderer/qr-renderer.ts +0 -120
|
@@ -9,15 +9,13 @@ import type { SelectionResult } from './selection-modal.ts';
|
|
|
9
9
|
import { SearchManager } from './search.ts';
|
|
10
10
|
import type { InputHistory, HistorySearch } from './input-history.ts';
|
|
11
11
|
import type { BlockMeta, ConversationManager } from '../core/conversation';
|
|
12
|
-
import { ProcessModal } from '../renderer/process-modal.ts';
|
|
13
|
-
import { LiveTailModal } from '../renderer/live-tail-modal.ts';
|
|
14
12
|
import { BlockActionsMenu } from '../renderer/block-actions.ts';
|
|
15
|
-
import { AgentDetailModal } from '../renderer/agent-detail-modal.ts';
|
|
16
13
|
import { ContextInspectorModal } from '../renderer/context-inspector.ts';
|
|
17
14
|
import { BookmarkModal } from './bookmark-modal.ts';
|
|
18
15
|
import { SettingsModal } from './settings-modal.ts';
|
|
19
16
|
import type { McpWorkspace } from './mcp-workspace.ts';
|
|
20
17
|
import { SessionPickerModal } from './session-picker-modal.ts';
|
|
18
|
+
import type { ConfigModal } from './config-modal.ts';
|
|
21
19
|
import { ProfilePickerModal } from './profile-picker-modal.ts';
|
|
22
20
|
import type { OnboardingWizardController } from './onboarding/onboarding-wizard.ts';
|
|
23
21
|
import type { OnboardingWizardAction } from './onboarding/onboarding-wizard.ts';
|
|
@@ -45,6 +43,7 @@ import type { PanelManager } from '../panels/panel-manager.ts';
|
|
|
45
43
|
import type { KeybindingsManager } from './keybindings.ts';
|
|
46
44
|
import type { ModelPickerTarget } from './model-picker.ts';
|
|
47
45
|
import type { KillRing } from './kill-ring.ts';
|
|
46
|
+
import type { FocusTracker } from '../core/focus-tracker.ts';
|
|
48
47
|
|
|
49
48
|
/**
|
|
50
49
|
* InputFeedContext — The single long-lived context object passed to feedInputTokens
|
|
@@ -72,8 +71,8 @@ import type { KillRing } from './kill-ring.ts';
|
|
|
72
71
|
* - `pasteRegistry`, `imageRegistry` — owned Maps, never replaced
|
|
73
72
|
* - `selectionModal`, `bookmarkModal`, `settingsModal`, `sessionPickerModal`,
|
|
74
73
|
* `profilePickerModal` — modal objects constructed once in InputHandler constructor
|
|
75
|
-
* - `filePicker`, `modelPicker`, `onboardingWizard`,
|
|
76
|
-
* `
|
|
74
|
+
* - `filePicker`, `modelPicker`, `onboardingWizard`,
|
|
75
|
+
* `contextInspectorModal`, `blockActionsMenu`, `searchManager`, `historySearch` —
|
|
77
76
|
* service objects constructed once
|
|
78
77
|
* - `panelManager`, `keybindingsManager` — from uiServices, stable for app lifetime
|
|
79
78
|
* - `modalStack` — reference to the handler's shared array (mutated in place)
|
|
@@ -111,6 +110,7 @@ export interface InputFeedContext {
|
|
|
111
110
|
readonly mcpWorkspace: McpWorkspace;
|
|
112
111
|
readonly sessionPickerModal: SessionPickerModal;
|
|
113
112
|
readonly profilePickerModal: ProfilePickerModal;
|
|
113
|
+
readonly configModal: ConfigModal;
|
|
114
114
|
readonly historySearch: HistorySearch;
|
|
115
115
|
commandRegistry: CommandRegistry | null;
|
|
116
116
|
commandContext: CommandContext | undefined;
|
|
@@ -118,9 +118,6 @@ export interface InputFeedContext {
|
|
|
118
118
|
readonly filePicker: FilePickerModal;
|
|
119
119
|
readonly modelPicker: ModelPickerModal;
|
|
120
120
|
readonly onboardingWizard: OnboardingWizardController;
|
|
121
|
-
readonly processModal: ProcessModal;
|
|
122
|
-
readonly liveTailModal: LiveTailModal;
|
|
123
|
-
readonly agentDetailModal: AgentDetailModal;
|
|
124
121
|
readonly contextInspectorModal: ContextInspectorModal;
|
|
125
122
|
readonly blockActionsMenu: BlockActionsMenu;
|
|
126
123
|
readonly searchManager: SearchManager;
|
|
@@ -131,6 +128,8 @@ export interface InputFeedContext {
|
|
|
131
128
|
inputHistory: InputHistory | null;
|
|
132
129
|
conversationManager: ConversationManager | null;
|
|
133
130
|
readonly killRing: KillRing;
|
|
131
|
+
/** Terminal focus tracker (W2.3) — updated here from 'focus' tokens, read by the unfocused-alert notifiers in core/. */
|
|
132
|
+
readonly focusTracker: FocusTracker;
|
|
134
133
|
readonly getHistory: () => InfiniteBuffer;
|
|
135
134
|
readonly getViewportHeight: () => number;
|
|
136
135
|
readonly getScrollTop: () => number;
|
|
@@ -180,17 +179,34 @@ export function feedInputTokens(context: InputFeedContext, tokens: readonly Inpu
|
|
|
180
179
|
const lineCount = history.getLineCount();
|
|
181
180
|
const keybindings = context.keybindingsManager;
|
|
182
181
|
|
|
183
|
-
//
|
|
184
|
-
//
|
|
185
|
-
//
|
|
186
|
-
//
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
182
|
+
// Shared opener for the Fleet panel: makes it visible AND transfers keyboard
|
|
183
|
+
// focus to it. panelManager.open() only makes the panel active — focus is a
|
|
184
|
+
// separate axis (see PanelManager.focusPanels()/getFocusTarget()); without the
|
|
185
|
+
// focusPanels() call, j/k/i/K land silently in the composer until Tab. Used by
|
|
186
|
+
// the footer indicator's [Enter] and by F2 (W6.2 e: F2 and the footer
|
|
187
|
+
// indicator both subsume the retired process modal). Mirrors the Ctrl+P
|
|
188
|
+
// panel-picker launcher (ui-openers.ts openPanelPicker).
|
|
189
|
+
const openFleetPanel = (): void => {
|
|
190
|
+
context.panelManager.open('fleet');
|
|
191
|
+
context.panelManager.focusPanels();
|
|
192
|
+
context.panelFocused = true;
|
|
193
|
+
};
|
|
192
194
|
|
|
195
|
+
// Paste-ness is a per-TOKEN property, computed at the handlePanelFocusToken
|
|
196
|
+
// call below — never a per-feed character sum. The SDK tokenizer emits a
|
|
197
|
+
// bracketed paste (\x1b[?2004h, enabled in main.ts terminal init) as ONE
|
|
198
|
+
// 'text' token holding the whole payload, while discrete keystrokes — even
|
|
199
|
+
// several batched into one feed() by render-tick latency — arrive as
|
|
200
|
+
// separate 1-char 'text' tokens. The old per-feed sum misread two quick nav
|
|
201
|
+
// keystrokes (e.g. j then k in one drain) as a "burst" and yanked focus.
|
|
193
202
|
for (const token of tokens) {
|
|
203
|
+
// Focus-reporting tokens (CSI ?1004h, W2.3) never reach the composer or any
|
|
204
|
+
// modal route — consumed here, first, unconditionally. No render needed.
|
|
205
|
+
if (token.type === 'focus') {
|
|
206
|
+
context.focusTracker.setFocused(token.action === 'in');
|
|
207
|
+
continue;
|
|
208
|
+
}
|
|
209
|
+
|
|
194
210
|
if (token.type === 'key' && context.keybindingsManager.matches('clear-cancel', token)) {
|
|
195
211
|
context.handleCtrlC();
|
|
196
212
|
continue;
|
|
@@ -210,6 +226,7 @@ export function feedInputTokens(context: InputFeedContext, tokens: readonly Inpu
|
|
|
210
226
|
mcpWorkspace: context.mcpWorkspace,
|
|
211
227
|
sessionPickerModal: context.sessionPickerModal,
|
|
212
228
|
profilePickerModal: context.profilePickerModal,
|
|
229
|
+
configModal: context.configModal,
|
|
213
230
|
onboardingWizard: context.onboardingWizard,
|
|
214
231
|
helpOverlayActive: context.helpOverlayActive,
|
|
215
232
|
helpScrollOffset: context.helpScrollOffset,
|
|
@@ -224,9 +241,6 @@ export function feedInputTokens(context: InputFeedContext, tokens: readonly Inpu
|
|
|
224
241
|
getViewportHeight: context.getViewportHeight,
|
|
225
242
|
requestRender: context.requestRender,
|
|
226
243
|
handleEscape: context.handleEscape,
|
|
227
|
-
liveTailModal: context.liveTailModal,
|
|
228
|
-
processModal: context.processModal,
|
|
229
|
-
agentDetailModal: context.agentDetailModal,
|
|
230
244
|
contextInspectorModal: context.contextInspectorModal,
|
|
231
245
|
modalOpened: context.modalOpened,
|
|
232
246
|
filePicker: context.filePicker,
|
|
@@ -330,7 +344,17 @@ export function feedInputTokens(context: InputFeedContext, tokens: readonly Inpu
|
|
|
330
344
|
panelManager: context.panelManager,
|
|
331
345
|
keybindingsManager: context.keybindingsManager,
|
|
332
346
|
onPanelInputConsumed: context.onPanelInputConsumed,
|
|
333
|
-
|
|
347
|
+
// Per-token paste classification (Invariant B): a paste is a single
|
|
348
|
+
// 'text' token whose value holds more than one character.
|
|
349
|
+
isPasteToken: token.type === 'text' && token.value.length > 1,
|
|
350
|
+
// One-shot honesty hint when a paste is dropped into a non-capturing
|
|
351
|
+
// focused panel (Invariant A: focus never silently flips to the composer).
|
|
352
|
+
onPasteDropped: (panelName: string) =>
|
|
353
|
+
context.commandContext?.print(
|
|
354
|
+
`paste ignored — focus is on ${panelName}; Tab returns to composer`,
|
|
355
|
+
),
|
|
356
|
+
isTurnActive: () => context.commandContext?.isGenerating?.() ?? false,
|
|
357
|
+
cancelGeneration: () => context.commandContext?.cancelGeneration?.(),
|
|
334
358
|
}, token);
|
|
335
359
|
context.panelFocused = panelRoute.panelFocused;
|
|
336
360
|
if (panelRoute.handled) {
|
|
@@ -340,7 +364,7 @@ export function feedInputTokens(context: InputFeedContext, tokens: readonly Inpu
|
|
|
340
364
|
const indicatorRoute = handleIndicatorFocusToken({
|
|
341
365
|
indicatorFocused: context.indicatorFocused,
|
|
342
366
|
modalOpened: context.modalOpened,
|
|
343
|
-
|
|
367
|
+
openFleetPanel,
|
|
344
368
|
requestRender: context.requestRender,
|
|
345
369
|
}, token);
|
|
346
370
|
context.indicatorFocused = indicatorRoute.indicatorFocused;
|
|
@@ -422,7 +446,7 @@ export function feedInputTokens(context: InputFeedContext, tokens: readonly Inpu
|
|
|
422
446
|
commandRegistry: context.commandRegistry,
|
|
423
447
|
autocomplete: context.autocomplete,
|
|
424
448
|
blockActionsMenu: { open: (block: BlockMeta) => context.blockActionsMenu.open(block) },
|
|
425
|
-
|
|
449
|
+
openFleetPanel,
|
|
426
450
|
modalOpened: context.modalOpened,
|
|
427
451
|
saveUndoState: context.saveUndoState,
|
|
428
452
|
breakUndoCoalesce: context.breakUndoCoalesce,
|
|
@@ -225,14 +225,12 @@ export function handleEscapeForHandler(handler: InputHandler): void {
|
|
|
225
225
|
helpOverlayActive: handler.helpOverlayActive,
|
|
226
226
|
shortcutsOverlayActive: handler.shortcutsOverlayActive,
|
|
227
227
|
bookmarkModal: handler.bookmarkModal,
|
|
228
|
-
agentDetailModal: handler.agentDetailModal,
|
|
229
|
-
liveTailModal: handler.liveTailModal,
|
|
230
228
|
settingsModal: handler.settingsModal,
|
|
231
229
|
mcpWorkspace: handler.mcpWorkspace,
|
|
232
230
|
sessionPickerModal: handler.sessionPickerModal,
|
|
233
231
|
profilePickerModal: handler.profilePickerModal,
|
|
232
|
+
configModal: handler.configModal,
|
|
234
233
|
contextInspectorModal: handler.contextInspectorModal,
|
|
235
|
-
processModal: handler.processModal,
|
|
236
234
|
modelPicker: handler.modelPicker,
|
|
237
235
|
filePicker: handler.filePicker,
|
|
238
236
|
blockActionsMenu: handler.blockActionsMenu,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { InputToken } from '@pellux/goodvibes-sdk/platform/core';
|
|
2
2
|
import type { SelectionResult, SelectionAction } from './selection-modal.ts';
|
|
3
3
|
import type { CommandContext } from './command-registry.ts';
|
|
4
|
+
import type { ConfigModal } from './config-modal.ts';
|
|
4
5
|
import { openTtsProviderPicker, openTtsVoicePicker } from './tts-settings-actions.ts';
|
|
5
6
|
import { isTextBackspace } from './delete-key-policy.ts';
|
|
6
7
|
import { summarizeError } from '@pellux/goodvibes-sdk/platform/utils';
|
|
@@ -533,3 +534,67 @@ export function handleProfilePickerToken(state: ProfilePickerRouteState, token:
|
|
|
533
534
|
state.requestRender();
|
|
534
535
|
return true;
|
|
535
536
|
}
|
|
537
|
+
|
|
538
|
+
type ConfigModalRouteState = {
|
|
539
|
+
configModal: ConfigModal;
|
|
540
|
+
commandContext?: CommandContext;
|
|
541
|
+
requestRender: () => void;
|
|
542
|
+
handleEscape: () => void;
|
|
543
|
+
};
|
|
544
|
+
|
|
545
|
+
/**
|
|
546
|
+
* Route a key to the generic config-modal host (W6.1 MIGRATE-TO-MODAL
|
|
547
|
+
* surfaces). The host owns the reserved navigation keys (Esc, up/down/j/k tab
|
|
548
|
+
* left/right); every other key is offered to the active surface's declarative
|
|
549
|
+
* action table (fireAction handles the two-press confirm for destructive
|
|
550
|
+
* actions). Any unrecognised key is absorbed so the modal stays modal — this is
|
|
551
|
+
* the same "active modal captures all keys" shape as the other modal routers.
|
|
552
|
+
*/
|
|
553
|
+
export function handleConfigModalToken(state: ConfigModalRouteState, token: InputToken): boolean {
|
|
554
|
+
if (!state.configModal.active) return false;
|
|
555
|
+
|
|
556
|
+
if (token.type === 'key') {
|
|
557
|
+
switch (token.logicalName) {
|
|
558
|
+
case 'escape':
|
|
559
|
+
state.handleEscape();
|
|
560
|
+
return true;
|
|
561
|
+
case 'up':
|
|
562
|
+
state.configModal.moveUp();
|
|
563
|
+
state.requestRender();
|
|
564
|
+
return true;
|
|
565
|
+
case 'down':
|
|
566
|
+
state.configModal.moveDown();
|
|
567
|
+
state.requestRender();
|
|
568
|
+
return true;
|
|
569
|
+
case 'left':
|
|
570
|
+
state.configModal.prevTab();
|
|
571
|
+
state.requestRender();
|
|
572
|
+
return true;
|
|
573
|
+
case 'right':
|
|
574
|
+
case 'tab':
|
|
575
|
+
state.configModal.nextTab();
|
|
576
|
+
state.requestRender();
|
|
577
|
+
return true;
|
|
578
|
+
}
|
|
579
|
+
} else if (token.type === 'text') {
|
|
580
|
+
if (token.value === 'j') { state.configModal.moveDown(); state.requestRender(); return true; }
|
|
581
|
+
if (token.value === 'k') { state.configModal.moveUp(); state.requestRender(); return true; }
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
const actionKey = token.type === 'key' ? (token.logicalName ?? '') : token.type === 'text' ? token.value : '';
|
|
585
|
+
const fired = actionKey.length > 0 && state.configModal.fireAction(actionKey, {
|
|
586
|
+
print: (message: string) => state.commandContext?.print(message),
|
|
587
|
+
executeCommand: state.commandContext?.executeCommand,
|
|
588
|
+
openModal: state.commandContext?.openModal,
|
|
589
|
+
});
|
|
590
|
+
if (fired) {
|
|
591
|
+
state.requestRender();
|
|
592
|
+
return true;
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
// Unhandled key while a config modal is open: drop any pending confirm and
|
|
596
|
+
// absorb the key (the modal owns the keyboard while it is active).
|
|
597
|
+
state.configModal.clearConfirmOnMiss();
|
|
598
|
+
state.requestRender();
|
|
599
|
+
return true;
|
|
600
|
+
}
|
|
@@ -40,12 +40,12 @@ export type EscapeState = ModalStackState & {
|
|
|
40
40
|
selectionCallback: ((result: SelectionResult | null) => void) | null;
|
|
41
41
|
bookmarkModal: ModalStackState['bookmarkModal'] & { open: () => void };
|
|
42
42
|
contextInspectorModal: ModalStackState['contextInspectorModal'] & { open: () => void };
|
|
43
|
-
processModal: ModalStackState['processModal'] & { open: () => void };
|
|
44
43
|
settingsModal: ModalStackState['settingsModal'] & {
|
|
45
44
|
editingMode: boolean;
|
|
46
45
|
cancelEdit: () => void;
|
|
47
46
|
};
|
|
48
47
|
mcpWorkspace?: ModalStackState['mcpWorkspace'];
|
|
48
|
+
configModal: ModalStackState['configModal'] & { reopen: () => void };
|
|
49
49
|
selectionModal: ModalStackState['selectionModal'];
|
|
50
50
|
autocompleteReset: () => void;
|
|
51
51
|
autocompleteUpdate?: (query: string) => void;
|
|
@@ -120,14 +120,12 @@ export function handleEscape(state: EscapeState): {
|
|
|
120
120
|
shortcutsScrollOffset = 0;
|
|
121
121
|
},
|
|
122
122
|
closeBookmark: () => state.bookmarkModal.close(),
|
|
123
|
-
closeAgentDetail: () => state.agentDetailModal.close(),
|
|
124
|
-
closeLiveTail: () => state.liveTailModal.close(),
|
|
125
123
|
closeSettings: () => state.settingsModal.close(),
|
|
126
124
|
closeMcpWorkspace: () => state.mcpWorkspace?.close(),
|
|
127
125
|
closeSessionPicker: () => state.sessionPickerModal.close(),
|
|
128
126
|
closeProfilePicker: () => state.profilePickerModal.close(),
|
|
127
|
+
closeConfigModal: () => state.configModal.close(),
|
|
129
128
|
closeContextInspector: () => state.contextInspectorModal.close(),
|
|
130
|
-
closeProcess: () => state.processModal.close(),
|
|
131
129
|
closeModelPicker: () => {
|
|
132
130
|
state.modelPicker.close();
|
|
133
131
|
state.restoreOnboardingModelPickerCancelState?.();
|
|
@@ -161,8 +159,8 @@ export function handleEscape(state: EscapeState): {
|
|
|
161
159
|
openHelp: () => { helpOverlayActive = true; },
|
|
162
160
|
openShortcuts: () => { shortcutsOverlayActive = true; },
|
|
163
161
|
openBookmark: () => state.bookmarkModal.open(),
|
|
164
|
-
openProcess: () => state.processModal.open(),
|
|
165
162
|
openContextInspector: () => state.contextInspectorModal.open(),
|
|
163
|
+
openConfigModal: () => state.configModal.reopen(),
|
|
166
164
|
openMcpWorkspace: () => state.mcpWorkspace?.reopen(),
|
|
167
165
|
openOnboarding: () => state.onboardingWizard?.reopen(),
|
|
168
166
|
openCommandMode: () => {
|
|
@@ -5,13 +5,11 @@ import type { BookmarkModal } from './bookmark-modal.ts';
|
|
|
5
5
|
import type { SettingsModal } from './settings-modal.ts';
|
|
6
6
|
import type { SessionPickerModal } from './session-picker-modal.ts';
|
|
7
7
|
import type { ProfilePickerModal } from './profile-picker-modal.ts';
|
|
8
|
+
import type { ConfigModal } from './config-modal.ts';
|
|
8
9
|
import type { HistorySearch } from './input-history.ts';
|
|
9
10
|
import type { ModelPickerModal } from './model-picker.ts';
|
|
10
11
|
import { handleMcpWorkspaceToken, type McpWorkspace } from './mcp-workspace.ts';
|
|
11
12
|
import type { CommandContext } from './command-registry.ts';
|
|
12
|
-
import type { LiveTailModal } from '../renderer/live-tail-modal.ts';
|
|
13
|
-
import type { ProcessModal } from '../renderer/process-modal.ts';
|
|
14
|
-
import type { AgentDetailModal } from '../renderer/agent-detail-modal.ts';
|
|
15
13
|
import type { ContextInspectorModal } from '../renderer/context-inspector.ts';
|
|
16
14
|
import type { FilePickerModal } from './file-picker.ts';
|
|
17
15
|
import type { BlockActionsMenu, BlockActionId } from '../renderer/block-actions.ts';
|
|
@@ -21,6 +19,7 @@ import { handleHistorySearchToken, handleOverlayToken, handleSearchModeToken } f
|
|
|
21
19
|
import { handleOnboardingWizardToken } from './onboarding/handler-onboarding-routes.ts';
|
|
22
20
|
import {
|
|
23
21
|
handleBookmarkModalToken,
|
|
22
|
+
handleConfigModalToken,
|
|
24
23
|
handleProfilePickerToken,
|
|
25
24
|
handleSelectionModalToken,
|
|
26
25
|
handleSessionPickerToken,
|
|
@@ -30,9 +29,7 @@ import {
|
|
|
30
29
|
handleBlockActionsToken,
|
|
31
30
|
handleEscapeOnlyModalToken,
|
|
32
31
|
handleFilePickerToken,
|
|
33
|
-
handleLiveTailToken,
|
|
34
32
|
handleModelPickerToken,
|
|
35
|
-
handleProcessModalToken,
|
|
36
33
|
} from './handler-picker-routes.ts';
|
|
37
34
|
|
|
38
35
|
export type ModalTokenRouteState = {
|
|
@@ -47,6 +44,7 @@ export type ModalTokenRouteState = {
|
|
|
47
44
|
mcpWorkspace: McpWorkspace;
|
|
48
45
|
sessionPickerModal: SessionPickerModal;
|
|
49
46
|
profilePickerModal: ProfilePickerModal;
|
|
47
|
+
configModal: ConfigModal;
|
|
50
48
|
onboardingWizard: OnboardingWizardController;
|
|
51
49
|
helpOverlayActive: boolean;
|
|
52
50
|
helpScrollOffset: number;
|
|
@@ -61,9 +59,6 @@ export type ModalTokenRouteState = {
|
|
|
61
59
|
getViewportHeight: () => number;
|
|
62
60
|
requestRender: () => void;
|
|
63
61
|
handleEscape: () => void;
|
|
64
|
-
liveTailModal: LiveTailModal;
|
|
65
|
-
processModal: ProcessModal;
|
|
66
|
-
agentDetailModal: AgentDetailModal;
|
|
67
62
|
contextInspectorModal: ContextInspectorModal;
|
|
68
63
|
modalOpened: (name: string) => void;
|
|
69
64
|
filePicker: FilePickerModal;
|
|
@@ -177,6 +172,15 @@ export function handleModalTokenRoutes(state: ModalTokenRouteState, token: Input
|
|
|
177
172
|
return withState(state, true);
|
|
178
173
|
}
|
|
179
174
|
|
|
175
|
+
if (handleConfigModalToken({
|
|
176
|
+
configModal: state.configModal,
|
|
177
|
+
commandContext: state.commandContext,
|
|
178
|
+
requestRender: state.requestRender,
|
|
179
|
+
handleEscape: state.handleEscape,
|
|
180
|
+
}, token)) {
|
|
181
|
+
return withState(state, true);
|
|
182
|
+
}
|
|
183
|
+
|
|
180
184
|
const overlayState = {
|
|
181
185
|
helpOverlayActive: state.helpOverlayActive,
|
|
182
186
|
helpScrollOffset: state.helpScrollOffset,
|
|
@@ -223,36 +227,10 @@ export function handleModalTokenRoutes(state: ModalTokenRouteState, token: Input
|
|
|
223
227
|
return withState(state, true);
|
|
224
228
|
}
|
|
225
229
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
handleEscape: state.handleEscape,
|
|
231
|
-
}, token)) {
|
|
232
|
-
return withState(state, true);
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
// Agent detail modal: route c + confirm keys before escape-close.
|
|
236
|
-
// handleKey() consumes confirm-flow keys (y, Enter, n, Esc) and the 'c'
|
|
237
|
-
// initiator; unhandled keys (including Esc when no confirm is pending)
|
|
238
|
-
// fall through to escape-close below.
|
|
239
|
-
if (state.agentDetailModal.active) {
|
|
240
|
-
const keyStr: string =
|
|
241
|
-
token.type === 'key' ? (token.logicalName ?? '') :
|
|
242
|
-
token.type === 'text' ? token.value : '';
|
|
243
|
-
if (keyStr && state.agentDetailModal.handleKey(keyStr)) {
|
|
244
|
-
state.requestRender();
|
|
245
|
-
return withState(state, true);
|
|
246
|
-
}
|
|
247
|
-
// 'c' was not consumed (non-cancellable), or any other key.
|
|
248
|
-
// Esc closes the modal; all other keys are absorbed by the active modal.
|
|
249
|
-
if (token.type === 'key' && token.logicalName === 'escape') {
|
|
250
|
-
state.handleEscape();
|
|
251
|
-
return withState(state, true);
|
|
252
|
-
}
|
|
253
|
-
state.requestRender();
|
|
254
|
-
return withState(state, true);
|
|
255
|
-
}
|
|
230
|
+
// W6.1 retirement: the live-tail, agent-detail, and process-modal token
|
|
231
|
+
// routes were removed with those modals (F2 now opens Fleet, which subsumes
|
|
232
|
+
// the live process tree; the three modals were structurally unreachable after
|
|
233
|
+
// the F2 repoint and were deleted).
|
|
256
234
|
|
|
257
235
|
if (handleEscapeOnlyModalToken({
|
|
258
236
|
active: state.contextInspectorModal.active,
|
|
@@ -262,17 +240,6 @@ export function handleModalTokenRoutes(state: ModalTokenRouteState, token: Input
|
|
|
262
240
|
return withState(state, true);
|
|
263
241
|
}
|
|
264
242
|
|
|
265
|
-
if (handleProcessModalToken({
|
|
266
|
-
processModal: state.processModal,
|
|
267
|
-
liveTailModal: state.liveTailModal,
|
|
268
|
-
agentDetailModal: state.agentDetailModal,
|
|
269
|
-
modalOpened: state.modalOpened,
|
|
270
|
-
requestRender: state.requestRender,
|
|
271
|
-
handleEscape: state.handleEscape,
|
|
272
|
-
}, token)) {
|
|
273
|
-
return withState(state, true);
|
|
274
|
-
}
|
|
275
|
-
|
|
276
243
|
const filePickerState = {
|
|
277
244
|
filePicker: state.filePicker,
|
|
278
245
|
prompt: state.prompt,
|
|
@@ -5,7 +5,6 @@ import type { CapabilityFilter, CategoryFilter, ModelPickerModal } from './model
|
|
|
5
5
|
import { MODEL_PICKER_CHROME_LINES } from '../renderer/model-picker-overlay.ts';
|
|
6
6
|
import { resolveAndValidatePath } from '@pellux/goodvibes-sdk/platform/utils';
|
|
7
7
|
import { logger } from '@pellux/goodvibes-sdk/platform/utils';
|
|
8
|
-
import type { ProcessEntry } from '../renderer/process-modal.ts';
|
|
9
8
|
import type { BlockActionId } from '../renderer/block-actions.ts';
|
|
10
9
|
|
|
11
10
|
type ModelPickerRouteState = {
|
|
@@ -93,6 +92,13 @@ export function handleModelPickerToken(state: ModelPickerRouteState, token: Inpu
|
|
|
93
92
|
}
|
|
94
93
|
state.modelPicker.close();
|
|
95
94
|
if (state.modalStack[state.modalStack.length - 1] === 'modelPicker') state.modalStack.pop();
|
|
95
|
+
} else if (mode === 'embeddingProvider') {
|
|
96
|
+
const selectedProvider = state.modelPicker.embeddingProviders[idx];
|
|
97
|
+
if (selectedProvider) {
|
|
98
|
+
state.commandContext?.completeEmbeddingProviderSelection?.(selectedProvider.id);
|
|
99
|
+
}
|
|
100
|
+
state.modelPicker.close();
|
|
101
|
+
if (state.modalStack[state.modalStack.length - 1] === 'modelPicker') state.modalStack.pop();
|
|
96
102
|
} else if (mode === 'contextCap') {
|
|
97
103
|
const capModel = state.modelPicker.contextCapPendingModel;
|
|
98
104
|
if (capModel) {
|
|
@@ -201,99 +207,10 @@ function cycleCapabilityFilter(modelPicker: ModelPickerModal): void {
|
|
|
201
207
|
modelPicker.setCapabilityFilter(cycle[(cur + 1) % cycle.length]!);
|
|
202
208
|
}
|
|
203
209
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
moveDown: () => void;
|
|
209
|
-
getSelected: () => ProcessEntry | undefined;
|
|
210
|
-
close: () => void;
|
|
211
|
-
open: () => void;
|
|
212
|
-
killSelected: () => boolean;
|
|
213
|
-
refresh: () => void;
|
|
214
|
-
};
|
|
215
|
-
liveTailModal: {
|
|
216
|
-
open: (entry: ProcessEntry) => void;
|
|
217
|
-
};
|
|
218
|
-
agentDetailModal: {
|
|
219
|
-
open: (id: string) => void;
|
|
220
|
-
};
|
|
221
|
-
modalOpened: (name: string) => void;
|
|
222
|
-
requestRender: () => void;
|
|
223
|
-
handleEscape: () => void;
|
|
224
|
-
};
|
|
225
|
-
|
|
226
|
-
export function handleProcessModalToken(state: ProcessRouteState, token: InputToken): boolean {
|
|
227
|
-
if (!state.processModal.active) return false;
|
|
228
|
-
|
|
229
|
-
if (token.type === 'key') {
|
|
230
|
-
if (token.logicalName === 'escape') {
|
|
231
|
-
state.handleEscape();
|
|
232
|
-
return true;
|
|
233
|
-
}
|
|
234
|
-
if (token.logicalName === 'up') state.processModal.moveUp();
|
|
235
|
-
else if (token.logicalName === 'down') state.processModal.moveDown();
|
|
236
|
-
else if (token.logicalName === 'enter') {
|
|
237
|
-
const entry = state.processModal.getSelected();
|
|
238
|
-
if (entry) {
|
|
239
|
-
if (entry.type === 'agent') {
|
|
240
|
-
state.modalOpened('agentDetail');
|
|
241
|
-
state.processModal.close();
|
|
242
|
-
state.agentDetailModal.open(entry.id);
|
|
243
|
-
} else {
|
|
244
|
-
state.modalOpened('liveTail');
|
|
245
|
-
state.processModal.close();
|
|
246
|
-
state.liveTailModal.open(entry);
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
} else if (token.type === 'text' && token.value === 'k') {
|
|
251
|
-
const killed = state.processModal.killSelected();
|
|
252
|
-
if (killed) state.processModal.refresh();
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
state.requestRender();
|
|
256
|
-
return true;
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
type LiveTailRouteState = {
|
|
260
|
-
liveTailModal: {
|
|
261
|
-
active: boolean;
|
|
262
|
-
scrollUp: () => void;
|
|
263
|
-
scrollDown: () => void;
|
|
264
|
-
killProcess: () => void;
|
|
265
|
-
close: () => void;
|
|
266
|
-
};
|
|
267
|
-
processModal: {
|
|
268
|
-
open: () => void;
|
|
269
|
-
};
|
|
270
|
-
requestRender: () => void;
|
|
271
|
-
handleEscape: () => void;
|
|
272
|
-
};
|
|
273
|
-
|
|
274
|
-
export function handleLiveTailToken(state: LiveTailRouteState, token: InputToken): boolean {
|
|
275
|
-
if (!state.liveTailModal.active) return false;
|
|
276
|
-
|
|
277
|
-
const killAndReturn = (): void => {
|
|
278
|
-
state.liveTailModal.killProcess();
|
|
279
|
-
state.handleEscape();
|
|
280
|
-
};
|
|
281
|
-
|
|
282
|
-
if (token.type === 'key') {
|
|
283
|
-
if (token.logicalName === 'escape') {
|
|
284
|
-
state.handleEscape();
|
|
285
|
-
return true;
|
|
286
|
-
}
|
|
287
|
-
if (token.logicalName === 'up') state.liveTailModal.scrollUp();
|
|
288
|
-
else if (token.logicalName === 'down') state.liveTailModal.scrollDown();
|
|
289
|
-
else if (token.logicalName === 'k') killAndReturn();
|
|
290
|
-
} else if (token.type === 'text' && token.value === 'k') {
|
|
291
|
-
killAndReturn();
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
state.requestRender();
|
|
295
|
-
return true;
|
|
296
|
-
}
|
|
210
|
+
// W6.2 e / W6.1 retirement: the process-modal and live-tail-modal token routes
|
|
211
|
+
// were removed with those modals (F2 now opens Fleet, which subsumes the live
|
|
212
|
+
// process tree). ProcessModal/AgentDetailModal/LiveTailModal were structurally
|
|
213
|
+
// unreachable after the F2 repoint and were deleted.
|
|
297
214
|
|
|
298
215
|
type EscapeOnlyModalRouteState = {
|
|
299
216
|
active: boolean;
|
|
@@ -55,13 +55,16 @@ export function handleGlobalShortcutToken(
|
|
|
55
55
|
): boolean {
|
|
56
56
|
if (token.type !== 'key') return false;
|
|
57
57
|
|
|
58
|
-
// Fast-path:
|
|
59
|
-
|
|
58
|
+
// Fast-path: BARE pageup/pagedown scroll the transcript. The `!token.ctrl`
|
|
59
|
+
// guard is load-bearing: Ctrl+PageUp/PageDown are the panel-tab-prev/next
|
|
60
|
+
// chords, so they must fall through to the keybinding lookup below instead of
|
|
61
|
+
// being swallowed here as a scroll.
|
|
62
|
+
if (token.logicalName === 'pageup' && !token.ctrl) {
|
|
60
63
|
if (state.panelFocused) return false;
|
|
61
64
|
state.scroll(-Math.max(1, viewportHeight - 2));
|
|
62
65
|
return true;
|
|
63
66
|
}
|
|
64
|
-
if (token.logicalName === 'pagedown') {
|
|
67
|
+
if (token.logicalName === 'pagedown' && !token.ctrl) {
|
|
65
68
|
if (state.panelFocused) return false;
|
|
66
69
|
state.scroll(Math.max(1, viewportHeight - 2));
|
|
67
70
|
return true;
|
|
@@ -101,6 +104,13 @@ export function handleGlobalShortcutToken(
|
|
|
101
104
|
case 'panel-close': {
|
|
102
105
|
const pm = state.panelManager;
|
|
103
106
|
const active = pm.getActivePanel();
|
|
107
|
+
// Wave-3: give the active panel a chance to consume Ctrl+X for an
|
|
108
|
+
// in-panel action (FleetPanel session-tab detach) before it closes the
|
|
109
|
+
// panel outright — see Panel.interceptPanelClose's doc comment.
|
|
110
|
+
if (active?.interceptPanelClose?.()) {
|
|
111
|
+
state.requestRender();
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
104
114
|
if (active) {
|
|
105
115
|
pm.close(active.id);
|
|
106
116
|
state.requestRender();
|
|
@@ -160,17 +170,17 @@ export function handleGlobalShortcutToken(
|
|
|
160
170
|
}
|
|
161
171
|
|
|
162
172
|
case 'panel-ops': {
|
|
163
|
-
// Ctrl+O: open the
|
|
164
|
-
//
|
|
165
|
-
//
|
|
166
|
-
//
|
|
167
|
-
//
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
173
|
+
// Ctrl+O: open AND focus the Fleet panel. The former Ops Control panel was
|
|
174
|
+
// retired to an 'ops-control' -> 'fleet' alias (W6.1); rather than route
|
|
175
|
+
// through the now-aliased openOpsPanel callback (which opens without
|
|
176
|
+
// transferring focus), open 'fleet' directly and grab focus — mirroring
|
|
177
|
+
// the footer indicator's [Enter] -> openFleetPanel path so j/k/i/K land in
|
|
178
|
+
// the panel immediately instead of the composer.
|
|
179
|
+
const pm = state.panelManager;
|
|
180
|
+
pm.open('fleet');
|
|
181
|
+
pm.focusPanels();
|
|
182
|
+
state.panelFocused = true;
|
|
183
|
+
state.requestRender();
|
|
174
184
|
return true;
|
|
175
185
|
}
|
|
176
186
|
|
|
@@ -23,14 +23,12 @@ import type { SelectionManager } from './selection.ts';
|
|
|
23
23
|
import type { InfiniteBuffer } from '../core/history.ts';
|
|
24
24
|
import type { AutocompleteEngine } from './autocomplete.ts';
|
|
25
25
|
import type { BookmarkModal } from './bookmark-modal.ts';
|
|
26
|
-
import type { AgentDetailModal } from '../renderer/agent-detail-modal.ts';
|
|
27
|
-
import type { LiveTailModal } from '../renderer/live-tail-modal.ts';
|
|
28
26
|
import type { SettingsModal } from './settings-modal.ts';
|
|
29
27
|
import type { McpWorkspace } from './mcp-workspace.ts';
|
|
30
28
|
import type { SessionPickerModal } from './session-picker-modal.ts';
|
|
29
|
+
import type { ConfigModal } from './config-modal.ts';
|
|
31
30
|
import type { ProfilePickerModal } from './profile-picker-modal.ts';
|
|
32
31
|
import type { ContextInspectorModal } from '../renderer/context-inspector.ts';
|
|
33
|
-
import type { ProcessModal } from '../renderer/process-modal.ts';
|
|
34
32
|
import type { FilePickerModal } from './file-picker.ts';
|
|
35
33
|
import type { BlockActionsMenu } from '../renderer/block-actions.ts';
|
|
36
34
|
import type { SelectionModal } from './selection-modal.ts';
|
|
@@ -105,14 +103,12 @@ export interface InputHandlerLike {
|
|
|
105
103
|
|
|
106
104
|
// ── Modal objects ─────────────────────────────────────────────────────────
|
|
107
105
|
bookmarkModal: BookmarkModal;
|
|
108
|
-
agentDetailModal: AgentDetailModal;
|
|
109
|
-
liveTailModal: LiveTailModal;
|
|
110
106
|
settingsModal: SettingsModal;
|
|
111
107
|
mcpWorkspace: McpWorkspace;
|
|
112
108
|
sessionPickerModal: SessionPickerModal;
|
|
113
109
|
profilePickerModal: ProfilePickerModal;
|
|
110
|
+
configModal: ConfigModal;
|
|
114
111
|
contextInspectorModal: ContextInspectorModal;
|
|
115
|
-
processModal: ProcessModal;
|
|
116
112
|
modelPicker: ModelPickerModal;
|
|
117
113
|
filePicker: FilePickerModal;
|
|
118
114
|
blockActionsMenu: BlockActionsMenu;
|