@jmoyers/harness 0.1.10 → 0.1.20
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/README.md +31 -35
- package/package.json +31 -11
- package/packages/harness-ai/src/anthropic-protocol.ts +68 -68
- package/packages/harness-ai/src/stream-text.ts +13 -91
- package/packages/harness-ui/src/frame-primitives.ts +158 -0
- package/packages/harness-ui/src/index.ts +18 -0
- package/packages/harness-ui/src/interaction/conversation-input-forwarder.ts +221 -0
- package/packages/harness-ui/src/interaction/conversation-selection-input.ts +213 -0
- package/packages/harness-ui/src/interaction/global-shortcut-input.ts +172 -0
- package/{src/ui → packages/harness-ui/src/interaction}/input-preflight.ts +10 -12
- package/{src/ui → packages/harness-ui/src/interaction}/input-token-router.ts +120 -69
- package/packages/harness-ui/src/interaction/input.ts +420 -0
- package/packages/harness-ui/src/interaction/left-nav-input.ts +166 -0
- package/{src/ui → packages/harness-ui/src/interaction}/main-pane-pointer-input.ts +91 -23
- package/{src/ui → packages/harness-ui/src/interaction}/pointer-routing-input.ts +112 -48
- package/packages/harness-ui/src/interaction/rail-pointer-input.ts +62 -0
- package/packages/harness-ui/src/interaction/repository-fold-input.ts +118 -0
- package/packages/harness-ui/src/kit.ts +476 -0
- package/packages/harness-ui/src/layout.ts +238 -0
- package/{src/ui/modals/manager.ts → packages/harness-ui/src/modal-manager.ts} +94 -64
- package/{src/ui → packages/harness-ui/src}/screen.ts +53 -26
- package/packages/harness-ui/src/surface.ts +252 -0
- package/packages/harness-ui/src/text-layout.ts +210 -0
- package/packages/nim-core/src/contracts.ts +239 -0
- package/packages/nim-core/src/event-store.ts +299 -0
- package/packages/nim-core/src/events.ts +53 -0
- package/packages/nim-core/src/index.ts +9 -0
- package/packages/nim-core/src/provider-router.ts +129 -0
- package/packages/nim-core/src/providers/anthropic-driver.ts +291 -0
- package/packages/nim-core/src/runtime-factory.ts +49 -0
- package/packages/nim-core/src/runtime.ts +1797 -0
- package/packages/nim-core/src/session-store.ts +516 -0
- package/packages/nim-core/src/telemetry.ts +48 -0
- package/packages/nim-test-tui/src/index.ts +150 -0
- package/packages/nim-ui-core/src/index.ts +1 -0
- package/packages/nim-ui-core/src/projection.ts +87 -0
- package/scripts/codex-live-mux-runtime.ts +2 -3721
- package/scripts/control-plane-daemon.ts +24 -2
- package/scripts/harness-bin.js +5 -0
- package/scripts/harness-commands.ts +300 -0
- package/scripts/harness-runtime.ts +82 -0
- package/scripts/harness.ts +33 -3007
- package/scripts/nim-tui-smoke.ts +748 -0
- package/src/cli/auth/runtime.ts +948 -0
- package/src/cli/default-gateway-pointer.ts +193 -0
- package/src/cli/gateway/runtime.ts +1872 -0
- package/src/cli/parsing/flags.ts +23 -0
- package/src/cli/parsing/session.ts +42 -0
- package/src/cli/runtime/context.ts +193 -0
- package/src/cli/runtime-app/application.ts +392 -0
- package/src/cli/runtime-infra/gateway-control.ts +729 -0
- package/{scripts/harness-inspector.ts → src/cli/workflows/inspector.ts} +14 -11
- package/src/cli/workflows/runtime.ts +965 -0
- package/src/clients/tui/left-rail-interactions.ts +519 -0
- package/src/clients/tui/main-pane-interactions.ts +509 -0
- package/src/clients/tui/modal-input-routing.ts +71 -0
- package/src/clients/tui/render-snapshot-adapter.ts +88 -0
- package/src/clients/web/synced-selectors.ts +132 -0
- package/src/codex/live-session.ts +82 -29
- package/src/config/config-core.ts +361 -10
- package/src/config/harness-paths.ts +4 -7
- package/src/config/harness-runtime-migration.ts +142 -19
- package/src/config/harness.config.template.jsonc +33 -0
- package/src/config/secrets-core.ts +92 -4
- package/src/control-plane/agent-realtime-api.ts +82 -427
- package/src/control-plane/prompt/thread-title-namer.ts +49 -23
- package/src/control-plane/session-summary.ts +10 -81
- package/src/control-plane/status/reducer-base.ts +12 -12
- package/src/control-plane/status/reducers/claude-status-reducer.ts +3 -3
- package/src/control-plane/status/reducers/codex-status-reducer.ts +4 -4
- package/src/control-plane/status/reducers/cursor-status-reducer.ts +3 -3
- package/src/control-plane/stream-client.ts +12 -2
- package/src/control-plane/stream-command-parser.ts +83 -143
- package/src/control-plane/stream-protocol.ts +53 -37
- package/src/control-plane/stream-server-background.ts +18 -2
- package/src/control-plane/stream-server-command.ts +376 -69
- package/src/control-plane/stream-server-session-runtime.ts +3 -2
- package/src/control-plane/stream-server.ts +943 -80
- package/src/control-plane/stream-session-runtime-types.ts +41 -0
- package/src/{mux/live-mux/control-plane-records.ts → core/contracts/records.ts} +24 -97
- package/src/core/state/observed-stream-cursor.ts +43 -0
- package/src/core/state/synced-observed-state.ts +273 -0
- package/src/core/store/harness-synced-store.ts +81 -0
- package/src/diff/budget.ts +136 -0
- package/src/diff/build.ts +289 -0
- package/src/diff/chunker.ts +146 -0
- package/src/diff/git-invoke.ts +315 -0
- package/src/diff/git-parse.ts +472 -0
- package/src/diff/hash.ts +70 -0
- package/src/diff/index.ts +24 -0
- package/src/diff/normalize.ts +134 -0
- package/src/diff/types.ts +178 -0
- package/src/diff-ui/args.ts +346 -0
- package/src/diff-ui/commands.ts +123 -0
- package/src/diff-ui/finder.ts +94 -0
- package/src/diff-ui/highlight.ts +127 -0
- package/src/diff-ui/index.ts +2 -0
- package/src/diff-ui/model.ts +141 -0
- package/src/diff-ui/pager.ts +412 -0
- package/src/diff-ui/render.ts +337 -0
- package/src/diff-ui/runtime.ts +379 -0
- package/src/diff-ui/state.ts +224 -0
- package/src/diff-ui/types.ts +236 -0
- package/src/domain/conversations.ts +11 -7
- package/src/domain/workspace.ts +76 -4
- package/src/mux/control-plane-op-queue.ts +93 -7
- package/src/mux/conversation-rail.ts +28 -71
- package/src/mux/dual-pane-core.ts +13 -13
- package/src/mux/harness-core-ui.ts +313 -42
- package/src/mux/input-shortcuts.ts +22 -112
- package/src/mux/keybinding-catalog.ts +340 -0
- package/src/mux/keybinding-registry.ts +103 -0
- package/src/mux/live-mux/command-menu-open-in.ts +280 -0
- package/src/mux/live-mux/command-menu.ts +167 -4
- package/src/mux/live-mux/conversation-state.ts +13 -0
- package/src/mux/live-mux/directory-resolution.ts +1 -1
- package/src/mux/live-mux/git-parsing.ts +16 -0
- package/src/mux/live-mux/git-snapshot.ts +33 -2
- package/src/mux/live-mux/global-shortcut-handlers.ts +6 -0
- package/src/mux/live-mux/home-pane-drop.ts +1 -1
- package/src/mux/live-mux/home-pane-pointer.ts +10 -0
- package/src/mux/live-mux/input-forwarding.ts +59 -2
- package/src/mux/live-mux/left-nav-activation.ts +124 -7
- package/src/mux/live-mux/left-nav.ts +35 -0
- package/src/mux/live-mux/link-click.ts +292 -0
- package/src/mux/live-mux/modal-command-menu-handler.ts +46 -9
- package/src/mux/live-mux/modal-conversation-handlers.ts +5 -1
- package/src/mux/live-mux/modal-input-reducers.ts +106 -8
- package/src/mux/live-mux/modal-overlays.ts +210 -31
- package/src/mux/live-mux/modal-pointer.ts +3 -7
- package/src/mux/live-mux/modal-prompt-handlers.ts +107 -1
- package/src/mux/live-mux/modal-release-notes-handler.ts +111 -0
- package/src/mux/live-mux/modal-task-editor-handler.ts +16 -11
- package/src/mux/live-mux/pointer-routing.ts +5 -2
- package/src/mux/live-mux/project-pane-pointer.ts +8 -0
- package/src/mux/live-mux/rail-layout.ts +33 -30
- package/src/mux/live-mux/release-notes.ts +383 -0
- package/src/mux/live-mux/render-trace-analysis.ts +52 -7
- package/src/mux/live-mux/repository-folding.ts +3 -0
- package/src/mux/live-mux/selection.ts +0 -4
- package/src/mux/live-mux/session-diagnostics-paths.ts +21 -0
- package/src/mux/project-pane-github-review.ts +271 -0
- package/src/mux/render-frame.ts +4 -0
- package/src/mux/runtime-app/codex-live-mux-runtime.ts +5191 -0
- package/src/mux/task-composer.ts +21 -14
- package/src/mux/task-focused-pane.ts +118 -117
- package/src/mux/task-screen-keybindings.ts +19 -82
- package/src/mux/workspace-rail-model.ts +270 -104
- package/src/mux/workspace-rail.ts +45 -22
- package/src/pty/session-broker.ts +1 -1
- package/{scripts → src/recording}/terminal-recording-gif-lib.ts +2 -2
- package/src/services/control-plane.ts +50 -32
- package/src/services/conversation-lifecycle.ts +118 -87
- package/src/services/conversation-startup-hydration.ts +20 -12
- package/src/services/directory-hydration.ts +21 -16
- package/src/services/event-persistence.ts +7 -0
- package/src/services/left-rail-pointer-handler.ts +329 -0
- package/src/services/mux-ui-state-persistence.ts +5 -1
- package/src/services/recording.ts +34 -26
- package/src/services/runtime-command-menu-agent-tools.ts +1 -1
- package/src/services/runtime-control-actions.ts +79 -61
- package/src/services/runtime-control-plane-ops.ts +122 -83
- package/src/services/runtime-conversation-actions.ts +40 -26
- package/src/services/runtime-conversation-activation.ts +82 -30
- package/src/services/runtime-conversation-starter.ts +80 -48
- package/src/services/runtime-conversation-title-edit.ts +91 -80
- package/src/services/runtime-envelope-handler.ts +107 -105
- package/src/services/runtime-git-state.ts +42 -29
- package/src/services/runtime-layout-resize.ts +3 -1
- package/src/services/runtime-left-rail-render.ts +99 -63
- package/src/services/runtime-nim-cli-session.ts +438 -0
- package/src/services/runtime-nim-session.ts +705 -0
- package/src/services/runtime-nim-tool-bridge.ts +141 -0
- package/src/services/runtime-observed-event-projection-pipeline.ts +45 -0
- package/src/services/runtime-process-wiring.ts +29 -36
- package/src/services/runtime-project-pane-github-review-cache.ts +164 -0
- package/src/services/runtime-render-flush.ts +63 -70
- package/src/services/runtime-render-lifecycle.ts +65 -64
- package/src/services/runtime-render-orchestrator.ts +55 -45
- package/src/services/runtime-render-pipeline.ts +106 -103
- package/src/services/runtime-render-state.ts +62 -49
- package/src/services/runtime-repository-actions.ts +97 -70
- package/src/services/runtime-right-pane-render.ts +80 -53
- package/src/services/runtime-shutdown.ts +38 -35
- package/src/services/runtime-stream-subscriptions.ts +35 -27
- package/src/services/runtime-task-composer-persistence.ts +71 -59
- package/src/services/runtime-task-composer-snapshot.ts +14 -0
- package/src/services/runtime-task-editor-actions.ts +46 -29
- package/src/services/runtime-task-pane-actions.ts +220 -134
- package/src/services/runtime-task-pane-shortcuts.ts +323 -123
- package/src/services/runtime-workspace-observed-effect-queue.ts +25 -0
- package/src/services/runtime-workspace-observed-events.ts +33 -184
- package/src/services/runtime-workspace-observed-transition-policy.ts +228 -0
- package/src/services/session-diagnostics-store.ts +217 -0
- package/src/services/startup-background-resume.ts +26 -21
- package/src/services/startup-orchestrator.ts +16 -13
- package/src/services/startup-paint-tracker.ts +29 -21
- package/src/services/startup-persisted-conversation-queue.ts +19 -13
- package/src/services/startup-settled-gate.ts +25 -15
- package/src/services/startup-shutdown.ts +18 -22
- package/src/services/startup-state-hydration.ts +44 -34
- package/src/services/startup-visibility.ts +12 -4
- package/src/services/task-pane-selection-actions.ts +89 -72
- package/src/services/task-planning-hydration.ts +24 -18
- package/src/services/task-planning-observed-events.ts +50 -52
- package/src/services/workspace-observed-events.ts +66 -63
- package/src/storage/storage-lifecycle-core.ts +438 -0
- package/src/store/control-plane-store-normalize.ts +33 -242
- package/src/store/control-plane-store-types.ts +1 -35
- package/src/store/control-plane-store.ts +396 -56
- package/src/store/event-store.ts +397 -3
- package/src/terminal/snapshot-oracle.ts +207 -94
- package/src/ui/mux-theme.ts +112 -8
- package/src/ui/panes/home-gridfire.ts +40 -31
- package/src/ui/panes/home.ts +10 -2
- package/src/ui/panes/nim.ts +315 -0
- package/src/mux/live-mux/actions-task.ts +0 -115
- package/src/mux/live-mux/left-rail-actions.ts +0 -118
- package/src/mux/live-mux/left-rail-conversation-click.ts +0 -82
- package/src/mux/live-mux/left-rail-pointer.ts +0 -74
- package/src/mux/live-mux/task-pane-shortcuts.ts +0 -206
- package/src/services/runtime-directory-actions.ts +0 -164
- package/src/services/runtime-input-pipeline.ts +0 -50
- package/src/services/runtime-input-router.ts +0 -189
- package/src/services/runtime-main-pane-input.ts +0 -230
- package/src/services/runtime-modal-input.ts +0 -119
- package/src/services/runtime-navigation-input.ts +0 -197
- package/src/services/runtime-rail-input.ts +0 -278
- package/src/services/runtime-task-pane.ts +0 -62
- package/src/services/runtime-workspace-actions.ts +0 -158
- package/src/ui/conversation-input-forwarder.ts +0 -114
- package/src/ui/conversation-selection-input.ts +0 -103
- package/src/ui/global-shortcut-input.ts +0 -89
- package/src/ui/input.ts +0 -238
- package/src/ui/kit.ts +0 -509
- package/src/ui/left-nav-input.ts +0 -80
- package/src/ui/left-rail-pointer-input.ts +0 -148
- package/src/ui/repository-fold-input.ts +0 -91
- package/src/ui/surface.ts +0 -224
|
@@ -1,34 +1,49 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
} from '../mux/dual-pane-core.ts';
|
|
6
|
-
import {
|
|
7
|
-
hasAltModifier as hasAltModifierFrame,
|
|
8
|
-
hasShiftModifier as hasShiftModifierFrame,
|
|
9
|
-
isLeftButtonPress as isLeftButtonPressFrame,
|
|
10
|
-
isMotionMouseCode as isMotionMouseCodeFrame,
|
|
11
|
-
type PaneSelection,
|
|
12
|
-
} from '../mux/live-mux/selection.ts';
|
|
13
|
-
import type { TerminalSnapshotFrameCore } from '../terminal/snapshot-oracle.ts';
|
|
1
|
+
import type {
|
|
2
|
+
ConversationSelectionSnapshotFrame,
|
|
3
|
+
PaneSelection,
|
|
4
|
+
} from './conversation-selection-input.ts';
|
|
14
5
|
|
|
15
|
-
type MainPaneMode = 'conversation' | 'project' | 'home';
|
|
16
|
-
type
|
|
17
|
-
type MuxInputToken = ReturnType<typeof parseMuxInputChunk>['tokens'][number];
|
|
18
|
-
type PointerTarget = ReturnType<typeof classifyPaneAtFrame>;
|
|
6
|
+
type MainPaneMode = 'conversation' | 'project' | 'home' | 'nim';
|
|
7
|
+
type PointerTarget = 'left' | 'right' | 'separator' | 'status' | 'outside';
|
|
19
8
|
|
|
20
9
|
interface MouseSelectionEvent {
|
|
10
|
+
readonly sequence: string;
|
|
21
11
|
readonly col: number;
|
|
22
12
|
readonly row: number;
|
|
23
13
|
readonly code: number;
|
|
24
14
|
readonly final: 'M' | 'm';
|
|
25
15
|
}
|
|
26
16
|
|
|
17
|
+
export interface InputTokenRouterLayout {
|
|
18
|
+
readonly paneRows: number;
|
|
19
|
+
readonly leftCols: number;
|
|
20
|
+
readonly rightCols: number;
|
|
21
|
+
readonly rightStartCol: number;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface InputTokenRouterMouseToken {
|
|
25
|
+
readonly kind: 'mouse';
|
|
26
|
+
readonly event: MouseSelectionEvent;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface InputTokenRouterPassthroughToken {
|
|
30
|
+
readonly kind: 'passthrough';
|
|
31
|
+
readonly text: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
type MuxInputToken = InputTokenRouterMouseToken | InputTokenRouterPassthroughToken;
|
|
35
|
+
|
|
36
|
+
interface HomePaneSelectionContext {
|
|
37
|
+
readonly viewportTop: number;
|
|
38
|
+
readonly totalRows: number;
|
|
39
|
+
readonly resolveSelectionText: (selection: PaneSelection) => string;
|
|
40
|
+
}
|
|
41
|
+
|
|
27
42
|
interface ConversationInputLike {
|
|
28
43
|
readonly oracle: {
|
|
29
44
|
isMouseTrackingEnabled: () => boolean;
|
|
30
45
|
scrollViewport: (delta: number) => void;
|
|
31
|
-
snapshotWithoutHash: () =>
|
|
46
|
+
snapshotWithoutHash: () => ConversationSelectionSnapshotFrame;
|
|
32
47
|
selectionText: (anchor: PaneSelection['anchor'], focus: PaneSelection['focus']) => string;
|
|
33
48
|
};
|
|
34
49
|
}
|
|
@@ -94,58 +109,85 @@ interface LeftRailPointerInputLike {
|
|
|
94
109
|
interface ConversationSelectionInputLike {
|
|
95
110
|
clearSelectionOnTextToken(textLength: number): boolean;
|
|
96
111
|
handleMouseSelection(input: {
|
|
97
|
-
layout:
|
|
98
|
-
frame:
|
|
112
|
+
layout: InputTokenRouterLayout;
|
|
113
|
+
frame: ConversationSelectionSnapshotFrame;
|
|
99
114
|
isMainPaneTarget: boolean;
|
|
100
115
|
resolveSelectionText?: (selection: PaneSelection) => string;
|
|
101
116
|
event: MouseSelectionEvent;
|
|
102
117
|
}): boolean;
|
|
103
118
|
}
|
|
104
119
|
|
|
105
|
-
interface InputTokenRouterOptions {
|
|
120
|
+
export interface InputTokenRouterOptions {
|
|
106
121
|
readonly getMainPaneMode: () => MainPaneMode;
|
|
122
|
+
readonly getHomePaneSelectionContext?: () => HomePaneSelectionContext | null;
|
|
107
123
|
readonly pointerRoutingInput: PointerRoutingInputLike;
|
|
108
124
|
readonly mainPanePointerInput: MainPanePointerInputLike;
|
|
109
125
|
readonly leftRailPointerInput: LeftRailPointerInputLike;
|
|
110
126
|
readonly conversationSelectionInput: ConversationSelectionInputLike;
|
|
111
127
|
}
|
|
112
128
|
|
|
113
|
-
interface
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
129
|
+
export interface InputTokenRouterStrategies {
|
|
130
|
+
classifyPaneAt(layout: InputTokenRouterLayout, col: number, row: number): PointerTarget;
|
|
131
|
+
isLeftButtonPress(code: number, final: 'M' | 'm'): boolean;
|
|
132
|
+
hasAltModifier(code: number): boolean;
|
|
133
|
+
hasShiftModifier(code: number): boolean;
|
|
134
|
+
isMotionMouseCode(code: number): boolean;
|
|
119
135
|
}
|
|
120
136
|
|
|
121
137
|
interface RouteTokensInput {
|
|
122
138
|
readonly tokens: readonly MuxInputToken[];
|
|
123
|
-
readonly layout:
|
|
139
|
+
readonly layout: InputTokenRouterLayout;
|
|
124
140
|
readonly conversation: ConversationInputLike | null;
|
|
125
|
-
readonly snapshotForInput:
|
|
141
|
+
readonly snapshotForInput: ConversationSelectionSnapshotFrame | null;
|
|
126
142
|
}
|
|
127
143
|
|
|
128
144
|
interface RouteTokensResult {
|
|
129
145
|
readonly routedTokens: MuxInputToken[];
|
|
130
|
-
readonly snapshotForInput:
|
|
146
|
+
readonly snapshotForInput: ConversationSelectionSnapshotFrame | null;
|
|
131
147
|
}
|
|
132
148
|
|
|
133
149
|
export class InputTokenRouter {
|
|
134
|
-
private readonly classifyPaneAt: typeof classifyPaneAtFrame;
|
|
135
|
-
private readonly isLeftButtonPress: typeof isLeftButtonPressFrame;
|
|
136
|
-
private readonly hasAltModifier: typeof hasAltModifierFrame;
|
|
137
|
-
private readonly hasShiftModifier: typeof hasShiftModifierFrame;
|
|
138
|
-
private readonly isMotionMouseCode: typeof isMotionMouseCodeFrame;
|
|
139
|
-
|
|
140
150
|
constructor(
|
|
141
151
|
private readonly options: InputTokenRouterOptions,
|
|
142
|
-
|
|
143
|
-
) {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
152
|
+
private readonly strategies: InputTokenRouterStrategies,
|
|
153
|
+
) {}
|
|
154
|
+
|
|
155
|
+
private buildHomeSelectionFrame(
|
|
156
|
+
layout: InputTokenRouterLayout,
|
|
157
|
+
context: HomePaneSelectionContext | null,
|
|
158
|
+
): ConversationSelectionSnapshotFrame | null {
|
|
159
|
+
if (context === null) {
|
|
160
|
+
return null;
|
|
161
|
+
}
|
|
162
|
+
return {
|
|
163
|
+
rows: Math.max(1, layout.paneRows),
|
|
164
|
+
cols: Math.max(1, layout.rightCols),
|
|
165
|
+
activeScreen: 'primary',
|
|
166
|
+
modes: {
|
|
167
|
+
bracketedPaste: false,
|
|
168
|
+
decMouseX10: false,
|
|
169
|
+
decMouseButtonEvent: false,
|
|
170
|
+
decMouseAnyEvent: false,
|
|
171
|
+
decFocusTracking: false,
|
|
172
|
+
decMouseSgrEncoding: false,
|
|
173
|
+
},
|
|
174
|
+
cursor: {
|
|
175
|
+
row: 0,
|
|
176
|
+
col: 0,
|
|
177
|
+
visible: false,
|
|
178
|
+
style: {
|
|
179
|
+
shape: 'block',
|
|
180
|
+
blinking: false,
|
|
181
|
+
},
|
|
182
|
+
},
|
|
183
|
+
viewport: {
|
|
184
|
+
top: Math.max(0, context.viewportTop),
|
|
185
|
+
totalRows: Math.max(1, context.totalRows),
|
|
186
|
+
followOutput: true,
|
|
187
|
+
},
|
|
188
|
+
lines: [],
|
|
189
|
+
richLines: [],
|
|
190
|
+
};
|
|
149
191
|
}
|
|
150
192
|
|
|
151
193
|
routeTokens(input: RouteTokensInput): RouteTokensResult {
|
|
@@ -174,7 +216,7 @@ export class InputTokenRouter {
|
|
|
174
216
|
continue;
|
|
175
217
|
}
|
|
176
218
|
|
|
177
|
-
const target = this.classifyPaneAt(input.layout, token.event.col, token.event.row);
|
|
219
|
+
const target = this.strategies.classifyPaneAt(input.layout, token.event.col, token.event.row);
|
|
178
220
|
const rowIndex = Math.max(0, Math.min(input.layout.paneRows - 1, token.event.row - 1));
|
|
179
221
|
const passThroughConversationMouse =
|
|
180
222
|
input.conversation !== null &&
|
|
@@ -184,7 +226,7 @@ export class InputTokenRouter {
|
|
|
184
226
|
snapshotForInput.activeScreen === 'alternate' &&
|
|
185
227
|
snapshotForInput.viewport.followOutput &&
|
|
186
228
|
input.conversation.oracle.isMouseTrackingEnabled() &&
|
|
187
|
-
!this.hasShiftModifier(token.event.code);
|
|
229
|
+
!this.strategies.hasShiftModifier(token.event.code);
|
|
188
230
|
if (
|
|
189
231
|
this.options.pointerRoutingInput.handleHomePaneDragRelease({
|
|
190
232
|
final: token.event.final,
|
|
@@ -265,9 +307,9 @@ export class InputTokenRouter {
|
|
|
265
307
|
}
|
|
266
308
|
const leftPaneConversationSelect =
|
|
267
309
|
target === 'left' &&
|
|
268
|
-
this.isLeftButtonPress(token.event.code, token.event.final) &&
|
|
269
|
-
!this.hasAltModifier(token.event.code) &&
|
|
270
|
-
!this.isMotionMouseCode(token.event.code);
|
|
310
|
+
this.strategies.isLeftButtonPress(token.event.code, token.event.final) &&
|
|
311
|
+
!this.strategies.hasAltModifier(token.event.code) &&
|
|
312
|
+
!this.strategies.isMotionMouseCode(token.event.code);
|
|
271
313
|
if (
|
|
272
314
|
this.options.leftRailPointerInput.handlePointerClick({
|
|
273
315
|
clickEligible: leftPaneConversationSelect,
|
|
@@ -279,27 +321,36 @@ export class InputTokenRouter {
|
|
|
279
321
|
) {
|
|
280
322
|
continue;
|
|
281
323
|
}
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
324
|
+
const mainPaneMode = this.options.getMainPaneMode();
|
|
325
|
+
const homeSelectionContext =
|
|
326
|
+
mainPaneMode === 'home' ? (this.options.getHomePaneSelectionContext?.() ?? null) : null;
|
|
327
|
+
const selectionFrame =
|
|
328
|
+
mainPaneMode === 'conversation'
|
|
329
|
+
? snapshotForInput
|
|
330
|
+
: this.buildHomeSelectionFrame(input.layout, homeSelectionContext);
|
|
331
|
+
const selectionResolver =
|
|
332
|
+
mainPaneMode === 'conversation'
|
|
333
|
+
? resolveSelectionText
|
|
334
|
+
: (homeSelectionContext?.resolveSelectionText ?? null);
|
|
335
|
+
if (selectionFrame !== null) {
|
|
336
|
+
const mouseSelectionInput =
|
|
337
|
+
selectionResolver === null
|
|
338
|
+
? {
|
|
339
|
+
layout: input.layout,
|
|
340
|
+
frame: selectionFrame,
|
|
341
|
+
isMainPaneTarget,
|
|
342
|
+
event: token.event,
|
|
343
|
+
}
|
|
344
|
+
: {
|
|
345
|
+
layout: input.layout,
|
|
346
|
+
frame: selectionFrame,
|
|
347
|
+
isMainPaneTarget,
|
|
348
|
+
resolveSelectionText: selectionResolver,
|
|
349
|
+
event: token.event,
|
|
350
|
+
};
|
|
351
|
+
if (this.options.conversationSelectionInput.handleMouseSelection(mouseSelectionInput)) {
|
|
352
|
+
continue;
|
|
353
|
+
}
|
|
303
354
|
}
|
|
304
355
|
|
|
305
356
|
routedTokens.push(token);
|
|
@@ -0,0 +1,420 @@
|
|
|
1
|
+
export type ThreadAgentType = 'codex' | 'claude' | 'cursor' | 'terminal' | 'critique';
|
|
2
|
+
|
|
3
|
+
type CommandMenuScope = 'all' | 'thread-start' | 'theme-select' | 'shortcuts';
|
|
4
|
+
|
|
5
|
+
export interface CommandMenuState {
|
|
6
|
+
readonly scope: CommandMenuScope;
|
|
7
|
+
readonly query: string;
|
|
8
|
+
readonly selectedIndex: number;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface CommandMenuActionDescriptor {
|
|
12
|
+
readonly id: string;
|
|
13
|
+
readonly title: string;
|
|
14
|
+
readonly aliases?: readonly string[];
|
|
15
|
+
readonly keywords?: readonly string[];
|
|
16
|
+
readonly detail?: string;
|
|
17
|
+
readonly screenLabel?: string;
|
|
18
|
+
readonly sectionLabel?: string;
|
|
19
|
+
readonly bindingHint?: string;
|
|
20
|
+
readonly priority?: number;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface NewThreadPromptState {
|
|
24
|
+
readonly directoryId: string;
|
|
25
|
+
readonly selectedAgentType: ThreadAgentType;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface TaskEditorPromptState {
|
|
29
|
+
readonly mode: 'create' | 'edit';
|
|
30
|
+
readonly taskId: string | null;
|
|
31
|
+
readonly title: string;
|
|
32
|
+
readonly body: string;
|
|
33
|
+
readonly repositoryIds: readonly string[];
|
|
34
|
+
readonly repositoryIndex: number;
|
|
35
|
+
readonly fieldIndex: 0 | 1 | 2;
|
|
36
|
+
readonly error: string | null;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface RepositoryPromptState {
|
|
40
|
+
readonly mode: 'add' | 'edit';
|
|
41
|
+
readonly repositoryId: string | null;
|
|
42
|
+
readonly value: string;
|
|
43
|
+
readonly error: string | null;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface ConversationTitleEditState {
|
|
47
|
+
readonly conversationId: string;
|
|
48
|
+
readonly value: string;
|
|
49
|
+
readonly lastSavedValue: string;
|
|
50
|
+
readonly error: string | null;
|
|
51
|
+
readonly persistInFlight: boolean;
|
|
52
|
+
readonly debounceTimer: NodeJS.Timeout | null;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface TaskEditorSubmitPayload {
|
|
56
|
+
readonly mode: 'create' | 'edit';
|
|
57
|
+
readonly taskId: string | null;
|
|
58
|
+
readonly repositoryId: string | null;
|
|
59
|
+
readonly projectId?: string | null;
|
|
60
|
+
readonly title: string | null;
|
|
61
|
+
readonly body: string;
|
|
62
|
+
readonly commandLabel: string;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export interface ApiKeyPromptState {
|
|
66
|
+
readonly keyName: string;
|
|
67
|
+
readonly displayName: string;
|
|
68
|
+
readonly value: string;
|
|
69
|
+
readonly error: string | null;
|
|
70
|
+
readonly hasExistingValue: boolean;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export interface InputRouterShortcutPorts {
|
|
74
|
+
readonly isModalDismissShortcut: (input: Buffer) => boolean;
|
|
75
|
+
readonly isCommandMenuToggleShortcut: (input: Buffer) => boolean;
|
|
76
|
+
readonly isArchiveConversationShortcut: (input: Buffer) => boolean;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export interface InputRouterOverlayPorts {
|
|
80
|
+
readonly dismissOnOutsideClick: (
|
|
81
|
+
input: Buffer,
|
|
82
|
+
dismiss: () => void,
|
|
83
|
+
onInsidePointerPress?: (col: number, row: number) => boolean,
|
|
84
|
+
) => boolean;
|
|
85
|
+
readonly buildConversationTitleModalOverlay: () => { top: number } | null;
|
|
86
|
+
readonly buildCommandMenuModalOverlay: () => { top: number } | null;
|
|
87
|
+
readonly buildNewThreadModalOverlay: () => { top: number } | null;
|
|
88
|
+
readonly resolveNewThreadPromptAgentByRow: (
|
|
89
|
+
overlayTop: number,
|
|
90
|
+
row: number,
|
|
91
|
+
) => ThreadAgentType | null;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export interface InputRouterActionPorts {
|
|
95
|
+
readonly stopConversationTitleEdit: (persistPending: boolean) => void;
|
|
96
|
+
readonly queueControlPlaneOp: (task: () => Promise<void>, label: string) => void;
|
|
97
|
+
readonly archiveConversation: (sessionId: string) => Promise<void>;
|
|
98
|
+
readonly createAndActivateConversationInDirectory: (
|
|
99
|
+
directoryId: string,
|
|
100
|
+
agentType: ThreadAgentType,
|
|
101
|
+
) => Promise<void>;
|
|
102
|
+
readonly addDirectoryByPath: (path: string) => Promise<void>;
|
|
103
|
+
readonly normalizeGitHubRemoteUrl: (remoteUrl: string) => string | null;
|
|
104
|
+
readonly upsertRepositoryByRemoteUrl: (
|
|
105
|
+
remoteUrl: string,
|
|
106
|
+
existingRepositoryId?: string,
|
|
107
|
+
) => Promise<void>;
|
|
108
|
+
readonly repositoriesHas: (repositoryId: string) => boolean;
|
|
109
|
+
readonly submitTaskEditorPayload: (payload: TaskEditorSubmitPayload) => void;
|
|
110
|
+
readonly resolveCommandMenuActions: () => readonly CommandMenuActionDescriptor[];
|
|
111
|
+
readonly executeCommandMenuAction: (actionId: string) => void;
|
|
112
|
+
readonly persistApiKey?: (keyName: string, value: string) => void;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export interface InputRouterStatePorts {
|
|
116
|
+
readonly markDirty: () => void;
|
|
117
|
+
readonly conversations: ReadonlyMap<string, { title: string }>;
|
|
118
|
+
readonly scheduleConversationTitlePersist: () => void;
|
|
119
|
+
readonly getTaskEditorPrompt: () => TaskEditorPromptState | null;
|
|
120
|
+
readonly setTaskEditorPrompt: (next: TaskEditorPromptState | null) => void;
|
|
121
|
+
readonly getApiKeyPrompt?: () => ApiKeyPromptState | null;
|
|
122
|
+
readonly setApiKeyPrompt?: (next: ApiKeyPromptState | null) => void;
|
|
123
|
+
readonly getConversationTitleEdit: () => ConversationTitleEditState | null;
|
|
124
|
+
readonly getCommandMenu: () => CommandMenuState | null;
|
|
125
|
+
readonly setCommandMenu: (menu: CommandMenuState | null) => void;
|
|
126
|
+
readonly getNewThreadPrompt: () => NewThreadPromptState | null;
|
|
127
|
+
readonly setNewThreadPrompt: (prompt: NewThreadPromptState | null) => void;
|
|
128
|
+
readonly getAddDirectoryPrompt: () => { value: string; error: string | null } | null;
|
|
129
|
+
readonly setAddDirectoryPrompt: (
|
|
130
|
+
next: {
|
|
131
|
+
value: string;
|
|
132
|
+
error: string | null;
|
|
133
|
+
} | null,
|
|
134
|
+
) => void;
|
|
135
|
+
readonly getRepositoryPrompt: () => RepositoryPromptState | null;
|
|
136
|
+
readonly setRepositoryPrompt: (next: RepositoryPromptState | null) => void;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export interface InputRouterOptions {
|
|
140
|
+
readonly shortcuts: InputRouterShortcutPorts;
|
|
141
|
+
readonly overlays: InputRouterOverlayPorts;
|
|
142
|
+
readonly actions: InputRouterActionPorts;
|
|
143
|
+
readonly state: InputRouterStatePorts;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export interface HandleCommandMenuInputOptions {
|
|
147
|
+
readonly input: Buffer;
|
|
148
|
+
readonly menu: CommandMenuState | null;
|
|
149
|
+
readonly isQuitShortcut: (input: Buffer) => boolean;
|
|
150
|
+
readonly isToggleShortcut: (input: Buffer) => boolean;
|
|
151
|
+
readonly dismissOnOutsideClick: (
|
|
152
|
+
input: Buffer,
|
|
153
|
+
dismiss: () => void,
|
|
154
|
+
onInsidePointerPress?: (col: number, row: number) => boolean,
|
|
155
|
+
) => boolean;
|
|
156
|
+
readonly buildCommandMenuModalOverlay: () => { top: number } | null;
|
|
157
|
+
readonly resolveActions: () => readonly CommandMenuActionDescriptor[];
|
|
158
|
+
readonly executeAction: (actionId: string) => void;
|
|
159
|
+
readonly setMenu: (next: CommandMenuState | null) => void;
|
|
160
|
+
readonly markDirty: () => void;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export interface HandleTaskEditorPromptInputOptions {
|
|
164
|
+
readonly input: Buffer;
|
|
165
|
+
readonly prompt: TaskEditorPromptState | null;
|
|
166
|
+
readonly isQuitShortcut: (input: Buffer) => boolean;
|
|
167
|
+
readonly dismissOnOutsideClick: (input: Buffer, dismiss: () => void) => boolean;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export interface HandleTaskEditorPromptInputResult {
|
|
171
|
+
readonly handled: boolean;
|
|
172
|
+
readonly nextPrompt?: TaskEditorPromptState | null;
|
|
173
|
+
readonly markDirty: boolean;
|
|
174
|
+
readonly submitPayload?: TaskEditorSubmitPayload;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export interface HandleApiKeyPromptInputOptions {
|
|
178
|
+
readonly input: Buffer;
|
|
179
|
+
readonly prompt: ApiKeyPromptState | null;
|
|
180
|
+
readonly isQuitShortcut: (input: Buffer) => boolean;
|
|
181
|
+
readonly dismissOnOutsideClick: (input: Buffer, dismiss: () => void) => boolean;
|
|
182
|
+
readonly setPrompt: (next: ApiKeyPromptState | null) => void;
|
|
183
|
+
readonly markDirty: () => void;
|
|
184
|
+
readonly persistApiKey: (keyName: string, value: string) => void;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export interface HandleConversationTitleEditInputOptions {
|
|
188
|
+
readonly input: Buffer;
|
|
189
|
+
readonly edit: ConversationTitleEditState | null;
|
|
190
|
+
readonly isQuitShortcut: (input: Buffer) => boolean;
|
|
191
|
+
readonly isArchiveShortcut: (input: Buffer) => boolean;
|
|
192
|
+
readonly dismissOnOutsideClick: (
|
|
193
|
+
input: Buffer,
|
|
194
|
+
dismiss: () => void,
|
|
195
|
+
onInsidePointerPress?: (col: number, row: number) => boolean,
|
|
196
|
+
) => boolean;
|
|
197
|
+
readonly buildConversationTitleModalOverlay: () => { top: number } | null;
|
|
198
|
+
readonly stopConversationTitleEdit: (persistPending: boolean) => void;
|
|
199
|
+
readonly queueControlPlaneOp: (task: () => Promise<void>, label: string) => void;
|
|
200
|
+
readonly archiveConversation: (sessionId: string) => Promise<void>;
|
|
201
|
+
readonly markDirty: () => void;
|
|
202
|
+
readonly conversations: ReadonlyMap<string, { title: string }>;
|
|
203
|
+
readonly scheduleConversationTitlePersist: () => void;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
export interface HandleNewThreadPromptInputOptions {
|
|
207
|
+
readonly input: Buffer;
|
|
208
|
+
readonly prompt: NewThreadPromptState | null;
|
|
209
|
+
readonly isQuitShortcut: (input: Buffer) => boolean;
|
|
210
|
+
readonly dismissOnOutsideClick: (
|
|
211
|
+
input: Buffer,
|
|
212
|
+
dismiss: () => void,
|
|
213
|
+
onInsidePointerPress?: (col: number, row: number) => boolean,
|
|
214
|
+
) => boolean;
|
|
215
|
+
readonly buildNewThreadModalOverlay: () => { top: number } | null;
|
|
216
|
+
readonly resolveNewThreadPromptAgentByRow: (
|
|
217
|
+
overlayTop: number,
|
|
218
|
+
row: number,
|
|
219
|
+
) => ThreadAgentType | null;
|
|
220
|
+
readonly queueControlPlaneOp: (task: () => Promise<void>, label: string) => void;
|
|
221
|
+
readonly createAndActivateConversationInDirectory: (
|
|
222
|
+
directoryId: string,
|
|
223
|
+
agentType: ThreadAgentType,
|
|
224
|
+
) => Promise<void>;
|
|
225
|
+
readonly markDirty: () => void;
|
|
226
|
+
readonly setPrompt: (prompt: NewThreadPromptState | null) => void;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
export interface HandleAddDirectoryPromptInputOptions {
|
|
230
|
+
readonly input: Buffer;
|
|
231
|
+
readonly prompt: { value: string; error: string | null } | null;
|
|
232
|
+
readonly isQuitShortcut: (input: Buffer) => boolean;
|
|
233
|
+
readonly dismissOnOutsideClick: (input: Buffer, dismiss: () => void) => boolean;
|
|
234
|
+
readonly setPrompt: (
|
|
235
|
+
next: {
|
|
236
|
+
value: string;
|
|
237
|
+
error: string | null;
|
|
238
|
+
} | null,
|
|
239
|
+
) => void;
|
|
240
|
+
readonly markDirty: () => void;
|
|
241
|
+
readonly queueControlPlaneOp: (task: () => Promise<void>, label: string) => void;
|
|
242
|
+
readonly addDirectoryByPath: (path: string) => Promise<void>;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
export interface HandleRepositoryPromptInputOptions {
|
|
246
|
+
readonly input: Buffer;
|
|
247
|
+
readonly prompt: RepositoryPromptState | null;
|
|
248
|
+
readonly isQuitShortcut: (input: Buffer) => boolean;
|
|
249
|
+
readonly dismissOnOutsideClick: (input: Buffer, dismiss: () => void) => boolean;
|
|
250
|
+
readonly setPrompt: (next: RepositoryPromptState | null) => void;
|
|
251
|
+
readonly markDirty: () => void;
|
|
252
|
+
readonly repositoriesHas: (repositoryId: string) => boolean;
|
|
253
|
+
readonly normalizeGitHubRemoteUrl: (remoteUrl: string) => string | null;
|
|
254
|
+
readonly queueControlPlaneOp: (task: () => Promise<void>, label: string) => void;
|
|
255
|
+
readonly upsertRepositoryByRemoteUrl: (
|
|
256
|
+
remoteUrl: string,
|
|
257
|
+
existingRepositoryId?: string,
|
|
258
|
+
) => Promise<void>;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
export interface InputRouterStrategies {
|
|
262
|
+
handleCommandMenuInput(options: HandleCommandMenuInputOptions): boolean;
|
|
263
|
+
handleTaskEditorPromptInput(
|
|
264
|
+
options: HandleTaskEditorPromptInputOptions,
|
|
265
|
+
): HandleTaskEditorPromptInputResult;
|
|
266
|
+
handleApiKeyPromptInput(options: HandleApiKeyPromptInputOptions): boolean;
|
|
267
|
+
handleConversationTitleEditInput(options: HandleConversationTitleEditInputOptions): boolean;
|
|
268
|
+
handleNewThreadPromptInput(options: HandleNewThreadPromptInputOptions): boolean;
|
|
269
|
+
handleAddDirectoryPromptInput(options: HandleAddDirectoryPromptInputOptions): boolean;
|
|
270
|
+
handleRepositoryPromptInput(options: HandleRepositoryPromptInputOptions): boolean;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
export class InputRouter {
|
|
274
|
+
constructor(
|
|
275
|
+
private readonly options: InputRouterOptions,
|
|
276
|
+
private readonly strategies: InputRouterStrategies,
|
|
277
|
+
) {}
|
|
278
|
+
|
|
279
|
+
handleCommandMenuInput(input: Buffer): boolean {
|
|
280
|
+
return this.strategies.handleCommandMenuInput({
|
|
281
|
+
input,
|
|
282
|
+
menu: this.options.state.getCommandMenu(),
|
|
283
|
+
isQuitShortcut: this.options.shortcuts.isModalDismissShortcut,
|
|
284
|
+
isToggleShortcut: this.options.shortcuts.isCommandMenuToggleShortcut,
|
|
285
|
+
dismissOnOutsideClick: this.options.overlays.dismissOnOutsideClick,
|
|
286
|
+
buildCommandMenuModalOverlay: this.options.overlays.buildCommandMenuModalOverlay,
|
|
287
|
+
resolveActions: this.options.actions.resolveCommandMenuActions,
|
|
288
|
+
executeAction: this.options.actions.executeCommandMenuAction,
|
|
289
|
+
setMenu: this.options.state.setCommandMenu,
|
|
290
|
+
markDirty: this.options.state.markDirty,
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
handleTaskEditorPromptInput(input: Buffer): boolean {
|
|
295
|
+
const handled = this.strategies.handleTaskEditorPromptInput({
|
|
296
|
+
input,
|
|
297
|
+
prompt: this.options.state.getTaskEditorPrompt(),
|
|
298
|
+
isQuitShortcut: this.options.shortcuts.isModalDismissShortcut,
|
|
299
|
+
dismissOnOutsideClick: this.options.overlays.dismissOnOutsideClick,
|
|
300
|
+
});
|
|
301
|
+
if (!handled.handled) {
|
|
302
|
+
return false;
|
|
303
|
+
}
|
|
304
|
+
if (handled.nextPrompt !== undefined) {
|
|
305
|
+
this.options.state.setTaskEditorPrompt(handled.nextPrompt);
|
|
306
|
+
}
|
|
307
|
+
if (handled.markDirty) {
|
|
308
|
+
this.options.state.markDirty();
|
|
309
|
+
}
|
|
310
|
+
if (handled.submitPayload !== undefined) {
|
|
311
|
+
this.options.actions.submitTaskEditorPayload(handled.submitPayload);
|
|
312
|
+
}
|
|
313
|
+
return true;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
handleRepositoryPromptInput(input: Buffer): boolean {
|
|
317
|
+
return this.strategies.handleRepositoryPromptInput({
|
|
318
|
+
input,
|
|
319
|
+
prompt: this.options.state.getRepositoryPrompt(),
|
|
320
|
+
isQuitShortcut: this.options.shortcuts.isModalDismissShortcut,
|
|
321
|
+
dismissOnOutsideClick: this.options.overlays.dismissOnOutsideClick,
|
|
322
|
+
setPrompt: this.options.state.setRepositoryPrompt,
|
|
323
|
+
markDirty: this.options.state.markDirty,
|
|
324
|
+
repositoriesHas: this.options.actions.repositoriesHas,
|
|
325
|
+
normalizeGitHubRemoteUrl: this.options.actions.normalizeGitHubRemoteUrl,
|
|
326
|
+
queueControlPlaneOp: this.options.actions.queueControlPlaneOp,
|
|
327
|
+
upsertRepositoryByRemoteUrl: this.options.actions.upsertRepositoryByRemoteUrl,
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
handleApiKeyPromptInput(input: Buffer): boolean {
|
|
332
|
+
if (
|
|
333
|
+
this.options.state.getApiKeyPrompt === undefined ||
|
|
334
|
+
this.options.state.setApiKeyPrompt === undefined ||
|
|
335
|
+
this.options.actions.persistApiKey === undefined
|
|
336
|
+
) {
|
|
337
|
+
return false;
|
|
338
|
+
}
|
|
339
|
+
return this.strategies.handleApiKeyPromptInput({
|
|
340
|
+
input,
|
|
341
|
+
prompt: this.options.state.getApiKeyPrompt(),
|
|
342
|
+
isQuitShortcut: this.options.shortcuts.isModalDismissShortcut,
|
|
343
|
+
dismissOnOutsideClick: this.options.overlays.dismissOnOutsideClick,
|
|
344
|
+
setPrompt: this.options.state.setApiKeyPrompt,
|
|
345
|
+
markDirty: this.options.state.markDirty,
|
|
346
|
+
persistApiKey: this.options.actions.persistApiKey,
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
handleNewThreadPromptInput(input: Buffer): boolean {
|
|
351
|
+
return this.strategies.handleNewThreadPromptInput({
|
|
352
|
+
input,
|
|
353
|
+
prompt: this.options.state.getNewThreadPrompt(),
|
|
354
|
+
isQuitShortcut: this.options.shortcuts.isModalDismissShortcut,
|
|
355
|
+
dismissOnOutsideClick: this.options.overlays.dismissOnOutsideClick,
|
|
356
|
+
buildNewThreadModalOverlay: this.options.overlays.buildNewThreadModalOverlay,
|
|
357
|
+
resolveNewThreadPromptAgentByRow: this.options.overlays.resolveNewThreadPromptAgentByRow,
|
|
358
|
+
queueControlPlaneOp: this.options.actions.queueControlPlaneOp,
|
|
359
|
+
createAndActivateConversationInDirectory:
|
|
360
|
+
this.options.actions.createAndActivateConversationInDirectory,
|
|
361
|
+
markDirty: this.options.state.markDirty,
|
|
362
|
+
setPrompt: this.options.state.setNewThreadPrompt,
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
handleConversationTitleEditInput(input: Buffer): boolean {
|
|
367
|
+
return this.strategies.handleConversationTitleEditInput({
|
|
368
|
+
input,
|
|
369
|
+
edit: this.options.state.getConversationTitleEdit(),
|
|
370
|
+
isQuitShortcut: this.options.shortcuts.isModalDismissShortcut,
|
|
371
|
+
isArchiveShortcut: this.options.shortcuts.isArchiveConversationShortcut,
|
|
372
|
+
dismissOnOutsideClick: this.options.overlays.dismissOnOutsideClick,
|
|
373
|
+
buildConversationTitleModalOverlay: this.options.overlays.buildConversationTitleModalOverlay,
|
|
374
|
+
stopConversationTitleEdit: this.options.actions.stopConversationTitleEdit,
|
|
375
|
+
queueControlPlaneOp: this.options.actions.queueControlPlaneOp,
|
|
376
|
+
archiveConversation: this.options.actions.archiveConversation,
|
|
377
|
+
markDirty: this.options.state.markDirty,
|
|
378
|
+
conversations: this.options.state.conversations,
|
|
379
|
+
scheduleConversationTitlePersist: this.options.state.scheduleConversationTitlePersist,
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
handleAddDirectoryPromptInput(input: Buffer): boolean {
|
|
384
|
+
return this.strategies.handleAddDirectoryPromptInput({
|
|
385
|
+
input,
|
|
386
|
+
prompt: this.options.state.getAddDirectoryPrompt(),
|
|
387
|
+
isQuitShortcut: this.options.shortcuts.isModalDismissShortcut,
|
|
388
|
+
dismissOnOutsideClick: this.options.overlays.dismissOnOutsideClick,
|
|
389
|
+
setPrompt: this.options.state.setAddDirectoryPrompt,
|
|
390
|
+
markDirty: this.options.state.markDirty,
|
|
391
|
+
queueControlPlaneOp: this.options.actions.queueControlPlaneOp,
|
|
392
|
+
addDirectoryByPath: this.options.actions.addDirectoryByPath,
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
routeModalInput(input: Buffer): boolean {
|
|
397
|
+
if (this.handleCommandMenuInput(input)) {
|
|
398
|
+
return true;
|
|
399
|
+
}
|
|
400
|
+
if (this.handleTaskEditorPromptInput(input)) {
|
|
401
|
+
return true;
|
|
402
|
+
}
|
|
403
|
+
if (this.handleRepositoryPromptInput(input)) {
|
|
404
|
+
return true;
|
|
405
|
+
}
|
|
406
|
+
if (this.handleApiKeyPromptInput(input)) {
|
|
407
|
+
return true;
|
|
408
|
+
}
|
|
409
|
+
if (this.handleNewThreadPromptInput(input)) {
|
|
410
|
+
return true;
|
|
411
|
+
}
|
|
412
|
+
if (this.handleConversationTitleEditInput(input)) {
|
|
413
|
+
return true;
|
|
414
|
+
}
|
|
415
|
+
if (this.handleAddDirectoryPromptInput(input)) {
|
|
416
|
+
return true;
|
|
417
|
+
}
|
|
418
|
+
return false;
|
|
419
|
+
}
|
|
420
|
+
}
|