@jmoyers/harness 0.1.11 → 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 -39
- 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/packages/harness-ui/src/modal-manager.ts +222 -0
- 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 -3872
- package/scripts/control-plane-daemon.ts +11 -0
- 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 -3019
- package/scripts/nim-tui-smoke.ts +748 -0
- package/src/cli/auth/runtime.ts +948 -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 +348 -8
- package/src/config/harness.config.template.jsonc +33 -0
- package/src/control-plane/agent-realtime-api.ts +82 -427
- 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-command.ts +376 -69
- package/src/control-plane/stream-server-session-runtime.ts +3 -2
- package/src/control-plane/stream-server.ts +864 -70
- 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/workspace.ts +68 -5
- 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 +13 -131
- 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-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 +77 -12
- package/src/mux/live-mux/modal-overlays.ts +168 -34
- package/src/mux/live-mux/modal-pointer.ts +3 -7
- package/src/mux/live-mux/modal-prompt-handlers.ts +23 -2
- 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 +10 -101
- 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 +73 -46
- package/src/services/runtime-conversation-starter.ts +53 -45
- 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 -72
- 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 +360 -56
- package/src/store/event-store.ts +366 -8
- 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 -85
- 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 -195
- package/src/services/runtime-main-pane-input.ts +0 -230
- package/src/services/runtime-modal-input.ts +0 -137
- package/src/services/runtime-navigation-input.ts +0 -197
- package/src/services/runtime-rail-input.ts +0 -279
- 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 -269
- 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/modals/manager.ts +0 -218
- package/src/ui/repository-fold-input.ts +0 -91
- package/src/ui/surface.ts +0 -224
|
@@ -1,11 +1,27 @@
|
|
|
1
1
|
export type ControlPlaneOpPriority = 'interactive' | 'background';
|
|
2
2
|
|
|
3
|
+
type ControlPlaneOpSupersedeMode = 'none' | 'pending' | 'pending-and-running';
|
|
4
|
+
|
|
5
|
+
interface ControlPlaneOpTaskOptions {
|
|
6
|
+
readonly signal: AbortSignal;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
type ControlPlaneOpTask = (options: ControlPlaneOpTaskOptions) => Promise<void>;
|
|
10
|
+
|
|
11
|
+
interface ControlPlaneOpEnqueueOptions {
|
|
12
|
+
readonly key?: string;
|
|
13
|
+
readonly supersede?: ControlPlaneOpSupersedeMode;
|
|
14
|
+
}
|
|
15
|
+
|
|
3
16
|
interface QueuedControlPlaneOp {
|
|
4
17
|
readonly id: number;
|
|
5
18
|
readonly priority: ControlPlaneOpPriority;
|
|
6
19
|
readonly label: string;
|
|
7
20
|
readonly enqueuedAtMs: number;
|
|
8
|
-
readonly
|
|
21
|
+
readonly key: string | null;
|
|
22
|
+
readonly supersede: ControlPlaneOpSupersedeMode;
|
|
23
|
+
readonly controller: AbortController;
|
|
24
|
+
readonly task: ControlPlaneOpTask;
|
|
9
25
|
}
|
|
10
26
|
|
|
11
27
|
interface ControlPlaneOpQueueMetrics {
|
|
@@ -45,6 +61,11 @@ interface ControlPlaneOpQueueOptions {
|
|
|
45
61
|
metrics: ControlPlaneOpQueueMetrics,
|
|
46
62
|
error: unknown,
|
|
47
63
|
) => void;
|
|
64
|
+
readonly onCanceled?: (
|
|
65
|
+
event: ControlPlaneOpQueueStartEvent,
|
|
66
|
+
metrics: ControlPlaneOpQueueMetrics,
|
|
67
|
+
reason: 'pre-start-abort' | 'running-abort',
|
|
68
|
+
) => void;
|
|
48
69
|
readonly onFatal?: (error: unknown) => void;
|
|
49
70
|
}
|
|
50
71
|
|
|
@@ -59,6 +80,7 @@ export class ControlPlaneOpQueue {
|
|
|
59
80
|
private readonly onStart: ControlPlaneOpQueueOptions['onStart'];
|
|
60
81
|
private readonly onSuccess: ControlPlaneOpQueueOptions['onSuccess'];
|
|
61
82
|
private readonly onError: ControlPlaneOpQueueOptions['onError'];
|
|
83
|
+
private readonly onCanceled: ControlPlaneOpQueueOptions['onCanceled'];
|
|
62
84
|
private readonly onFatal: ControlPlaneOpQueueOptions['onFatal'];
|
|
63
85
|
|
|
64
86
|
private readonly interactiveQueue: QueuedControlPlaneOp[] = [];
|
|
@@ -67,6 +89,7 @@ export class ControlPlaneOpQueue {
|
|
|
67
89
|
private nextId = 1;
|
|
68
90
|
private running = false;
|
|
69
91
|
private pumpScheduled = false;
|
|
92
|
+
private runningOp: QueuedControlPlaneOp | null = null;
|
|
70
93
|
|
|
71
94
|
constructor(options: ControlPlaneOpQueueOptions = {}) {
|
|
72
95
|
this.nowMs = options.nowMs ?? Date.now;
|
|
@@ -75,15 +98,24 @@ export class ControlPlaneOpQueue {
|
|
|
75
98
|
this.onStart = options.onStart;
|
|
76
99
|
this.onSuccess = options.onSuccess;
|
|
77
100
|
this.onError = options.onError;
|
|
101
|
+
this.onCanceled = options.onCanceled;
|
|
78
102
|
this.onFatal = options.onFatal;
|
|
79
103
|
}
|
|
80
104
|
|
|
81
|
-
enqueueInteractive(
|
|
82
|
-
|
|
105
|
+
enqueueInteractive(
|
|
106
|
+
task: ControlPlaneOpTask,
|
|
107
|
+
label = 'interactive-op',
|
|
108
|
+
options: ControlPlaneOpEnqueueOptions = {},
|
|
109
|
+
): void {
|
|
110
|
+
this.enqueue(task, 'interactive', label, options);
|
|
83
111
|
}
|
|
84
112
|
|
|
85
|
-
enqueueBackground(
|
|
86
|
-
|
|
113
|
+
enqueueBackground(
|
|
114
|
+
task: ControlPlaneOpTask,
|
|
115
|
+
label = 'background-op',
|
|
116
|
+
options: ControlPlaneOpEnqueueOptions = {},
|
|
117
|
+
): void {
|
|
118
|
+
this.enqueue(task, 'background', label, options);
|
|
87
119
|
}
|
|
88
120
|
|
|
89
121
|
async waitForDrain(): Promise<void> {
|
|
@@ -104,15 +136,33 @@ export class ControlPlaneOpQueue {
|
|
|
104
136
|
}
|
|
105
137
|
|
|
106
138
|
private enqueue(
|
|
107
|
-
task:
|
|
139
|
+
task: ControlPlaneOpTask,
|
|
108
140
|
priority: ControlPlaneOpPriority,
|
|
109
141
|
label: string,
|
|
142
|
+
options: ControlPlaneOpEnqueueOptions,
|
|
110
143
|
): void {
|
|
144
|
+
const key = options.key?.trim() ?? null;
|
|
145
|
+
const supersede = options.supersede ?? 'none';
|
|
146
|
+
if (key !== null && (supersede === 'pending' || supersede === 'pending-and-running')) {
|
|
147
|
+
this.abortPendingByKey(key);
|
|
148
|
+
}
|
|
149
|
+
if (
|
|
150
|
+
key !== null &&
|
|
151
|
+
supersede === 'pending-and-running' &&
|
|
152
|
+
this.runningOp !== null &&
|
|
153
|
+
this.runningOp.key === key
|
|
154
|
+
) {
|
|
155
|
+
this.runningOp.controller.abort();
|
|
156
|
+
}
|
|
157
|
+
|
|
111
158
|
const op: QueuedControlPlaneOp = {
|
|
112
159
|
id: this.nextId,
|
|
113
160
|
priority,
|
|
114
161
|
label,
|
|
115
162
|
enqueuedAtMs: this.nowMs(),
|
|
163
|
+
key,
|
|
164
|
+
supersede,
|
|
165
|
+
controller: new AbortController(),
|
|
116
166
|
task,
|
|
117
167
|
};
|
|
118
168
|
this.nextId += 1;
|
|
@@ -135,6 +185,26 @@ export class ControlPlaneOpQueue {
|
|
|
135
185
|
this.schedulePump();
|
|
136
186
|
}
|
|
137
187
|
|
|
188
|
+
private abortPendingByKey(key: string): void {
|
|
189
|
+
const filterPending = (queue: QueuedControlPlaneOp[]): QueuedControlPlaneOp[] => {
|
|
190
|
+
const kept: QueuedControlPlaneOp[] = [];
|
|
191
|
+
for (const entry of queue) {
|
|
192
|
+
if (entry.key === key) {
|
|
193
|
+
entry.controller.abort();
|
|
194
|
+
continue;
|
|
195
|
+
}
|
|
196
|
+
kept.push(entry);
|
|
197
|
+
}
|
|
198
|
+
return kept;
|
|
199
|
+
};
|
|
200
|
+
const nextInteractive = filterPending(this.interactiveQueue);
|
|
201
|
+
const nextBackground = filterPending(this.backgroundQueue);
|
|
202
|
+
this.interactiveQueue.length = 0;
|
|
203
|
+
this.backgroundQueue.length = 0;
|
|
204
|
+
this.interactiveQueue.push(...nextInteractive);
|
|
205
|
+
this.backgroundQueue.push(...nextBackground);
|
|
206
|
+
}
|
|
207
|
+
|
|
138
208
|
private metricsSnapshot(): ControlPlaneOpQueueMetrics {
|
|
139
209
|
return {
|
|
140
210
|
interactiveQueued: this.interactiveQueue.length,
|
|
@@ -197,13 +267,29 @@ export class ControlPlaneOpQueue {
|
|
|
197
267
|
|
|
198
268
|
try {
|
|
199
269
|
this.onStart?.(startEvent, this.metricsSnapshot());
|
|
270
|
+
if (next.controller.signal.aborted) {
|
|
271
|
+
this.onCanceled?.(startEvent, this.metricsSnapshot(), 'pre-start-abort');
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
this.runningOp = next;
|
|
200
275
|
try {
|
|
201
|
-
await next.task(
|
|
276
|
+
await next.task({
|
|
277
|
+
signal: next.controller.signal,
|
|
278
|
+
});
|
|
279
|
+
if (next.controller.signal.aborted) {
|
|
280
|
+
this.onCanceled?.(startEvent, this.metricsSnapshot(), 'running-abort');
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
202
283
|
this.onSuccess?.(startEvent, this.metricsSnapshot());
|
|
203
284
|
} catch (error: unknown) {
|
|
285
|
+
if (next.controller.signal.aborted) {
|
|
286
|
+
this.onCanceled?.(startEvent, this.metricsSnapshot(), 'running-abort');
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
204
289
|
this.onError?.(startEvent, this.metricsSnapshot(), error);
|
|
205
290
|
}
|
|
206
291
|
} finally {
|
|
292
|
+
this.runningOp = null;
|
|
207
293
|
this.running = false;
|
|
208
294
|
this.resolveDrainIfIdle();
|
|
209
295
|
this.schedulePump();
|
|
@@ -4,14 +4,11 @@ import type {
|
|
|
4
4
|
StreamSessionStatusModel,
|
|
5
5
|
} from '../control-plane/stream-protocol.ts';
|
|
6
6
|
import { padOrTrimDisplay } from './dual-pane-core.ts';
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
renderUiSurfaceAnsiRows,
|
|
13
|
-
} from '../ui/surface.ts';
|
|
14
|
-
import { paintUiRow } from '../ui/kit.ts';
|
|
7
|
+
import { UiKit } from '../../packages/harness-ui/src/kit.ts';
|
|
8
|
+
import { DEFAULT_UI_STYLE, SurfaceBuffer } from '../../packages/harness-ui/src/surface.ts';
|
|
9
|
+
import { getActiveMuxTheme } from '../ui/mux-theme.ts';
|
|
10
|
+
|
|
11
|
+
const UI_KIT = new UiKit();
|
|
15
12
|
|
|
16
13
|
export interface ConversationRailSessionSummary {
|
|
17
14
|
readonly sessionId: string;
|
|
@@ -194,56 +191,6 @@ export function buildConversationRailLines(
|
|
|
194
191
|
return rows.map((row) => padOrTrimDisplay(row.text, safeWidth));
|
|
195
192
|
}
|
|
196
193
|
|
|
197
|
-
const HEADER_ROW_STYLE = {
|
|
198
|
-
fg: { kind: 'indexed', index: 250 } as const,
|
|
199
|
-
bg: { kind: 'indexed', index: 236 } as const,
|
|
200
|
-
bold: false,
|
|
201
|
-
};
|
|
202
|
-
const NORMAL_ROW_STYLE = DEFAULT_UI_STYLE;
|
|
203
|
-
const ACTIVE_ROW_STYLE = {
|
|
204
|
-
fg: { kind: 'indexed', index: 255 } as const,
|
|
205
|
-
bg: { kind: 'indexed', index: 238 } as const,
|
|
206
|
-
bold: false,
|
|
207
|
-
};
|
|
208
|
-
const ACTIVE_INDICATOR_STYLE = {
|
|
209
|
-
fg: { kind: 'indexed', index: 231 } as const,
|
|
210
|
-
bg: { kind: 'indexed', index: 238 } as const,
|
|
211
|
-
bold: true,
|
|
212
|
-
};
|
|
213
|
-
const BADGE_STYLES = {
|
|
214
|
-
'needs-input': {
|
|
215
|
-
fg: { kind: 'indexed', index: 231 } as const,
|
|
216
|
-
bg: { kind: 'indexed', index: 166 } as const,
|
|
217
|
-
bold: true,
|
|
218
|
-
},
|
|
219
|
-
running: {
|
|
220
|
-
fg: { kind: 'indexed', index: 231 } as const,
|
|
221
|
-
bg: { kind: 'indexed', index: 24 } as const,
|
|
222
|
-
bold: true,
|
|
223
|
-
},
|
|
224
|
-
completed: {
|
|
225
|
-
fg: { kind: 'indexed', index: 231 } as const,
|
|
226
|
-
bg: { kind: 'indexed', index: 28 } as const,
|
|
227
|
-
bold: true,
|
|
228
|
-
},
|
|
229
|
-
exited: {
|
|
230
|
-
fg: { kind: 'indexed', index: 250 } as const,
|
|
231
|
-
bg: { kind: 'indexed', index: 239 } as const,
|
|
232
|
-
bold: true,
|
|
233
|
-
},
|
|
234
|
-
} as const;
|
|
235
|
-
const ACTIVE_TEXT_STYLE = {
|
|
236
|
-
fg: { kind: 'indexed', index: 255 } as const,
|
|
237
|
-
bg: { kind: 'indexed', index: 238 } as const,
|
|
238
|
-
bold: false,
|
|
239
|
-
};
|
|
240
|
-
const NORMAL_TEXT_STYLE = DEFAULT_UI_STYLE;
|
|
241
|
-
const MUTED_TEXT_STYLE = {
|
|
242
|
-
fg: { kind: 'indexed', index: 245 } as const,
|
|
243
|
-
bg: { kind: 'default' } as const,
|
|
244
|
-
bold: false,
|
|
245
|
-
};
|
|
246
|
-
|
|
247
194
|
function badgeLabel(status: StreamSessionRuntimeStatus): string {
|
|
248
195
|
if (status === 'needs-input') {
|
|
249
196
|
return 'NEED';
|
|
@@ -276,45 +223,55 @@ export function renderConversationRailAnsiRows(
|
|
|
276
223
|
): readonly string[] {
|
|
277
224
|
const safeWidth = Math.max(1, width);
|
|
278
225
|
const rows = buildConversationRailRows(sessions, activeSessionId, maxRows, order);
|
|
279
|
-
const surface =
|
|
226
|
+
const surface = new SurfaceBuffer(safeWidth, rows.length, DEFAULT_UI_STYLE);
|
|
227
|
+
const theme = getActiveMuxTheme().conversationRail;
|
|
280
228
|
|
|
281
229
|
for (let rowIndex = 0; rowIndex < rows.length; rowIndex += 1) {
|
|
282
230
|
const row = rows[rowIndex]!;
|
|
283
231
|
if (row.kind === 'header') {
|
|
284
|
-
|
|
232
|
+
UI_KIT.paintRow(surface, rowIndex, row.text, theme.headerStyle, theme.headerStyle, 1);
|
|
285
233
|
continue;
|
|
286
234
|
}
|
|
287
235
|
|
|
288
236
|
if (row.kind === 'empty') {
|
|
289
|
-
|
|
237
|
+
UI_KIT.paintRow(surface, rowIndex, '', theme.normalRowStyle, theme.normalRowStyle);
|
|
290
238
|
continue;
|
|
291
239
|
}
|
|
292
240
|
|
|
293
241
|
const session = row.session!;
|
|
294
242
|
const active = row.active === true;
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
surface,
|
|
243
|
+
surface.fillRow(rowIndex, active ? theme.activeRowStyle : theme.normalRowStyle);
|
|
244
|
+
surface.drawText(
|
|
298
245
|
0,
|
|
299
246
|
rowIndex,
|
|
300
247
|
active ? '>' : ' ',
|
|
301
|
-
active ?
|
|
248
|
+
active ? theme.activeIndicatorStyle : theme.normalTextStyle,
|
|
249
|
+
);
|
|
250
|
+
surface.drawText(
|
|
251
|
+
2,
|
|
252
|
+
rowIndex,
|
|
253
|
+
badgeLabel(session.status),
|
|
254
|
+
session.status === 'needs-input'
|
|
255
|
+
? theme.statusBadgeStyles.needsInput
|
|
256
|
+
: session.status === 'running'
|
|
257
|
+
? theme.statusBadgeStyles.running
|
|
258
|
+
: session.status === 'completed'
|
|
259
|
+
? theme.statusBadgeStyles.completed
|
|
260
|
+
: theme.statusBadgeStyles.exited,
|
|
302
261
|
);
|
|
303
|
-
|
|
304
|
-
drawUiText(
|
|
305
|
-
surface,
|
|
262
|
+
surface.drawText(
|
|
306
263
|
7,
|
|
307
264
|
rowIndex,
|
|
308
265
|
rowBodyText(session),
|
|
309
|
-
active ?
|
|
266
|
+
active ? theme.activeTextStyle : theme.normalTextStyle,
|
|
310
267
|
);
|
|
311
268
|
|
|
312
269
|
if (!session.live && session.attentionReason === null) {
|
|
313
|
-
|
|
270
|
+
surface.drawText(7, rowIndex, rowBodyText(session), theme.deadTextStyle);
|
|
314
271
|
}
|
|
315
272
|
}
|
|
316
273
|
|
|
317
|
-
return
|
|
274
|
+
return surface.renderAnsiRows();
|
|
318
275
|
}
|
|
319
276
|
|
|
320
277
|
export function cycleConversationId(
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { measureDisplayWidth, wrapTextForColumns } from '../terminal/snapshot-oracle.ts';
|
|
2
|
+
import { computeDualPaneLayoutWithLayers } from '../../packages/harness-ui/src/layout.ts';
|
|
2
3
|
|
|
3
4
|
const MIN_LEFT_PANE_COLS = 28;
|
|
4
5
|
const MIN_RIGHT_PANE_COLS = 20;
|
|
@@ -92,22 +93,21 @@ export function computeDualPaneLayout(
|
|
|
92
93
|
): DualPaneLayout {
|
|
93
94
|
const normalizedCols = Math.max(3, cols);
|
|
94
95
|
const normalizedRows = Math.max(2, rows);
|
|
95
|
-
const paneRows = Math.max(1, normalizedRows - 1);
|
|
96
|
-
const statusRow = paneRows + 1;
|
|
97
|
-
|
|
98
|
-
const availablePaneCols = normalizedCols - 1;
|
|
99
96
|
const leftCols = resolveLeftPaneCols(normalizedCols, options.leftCols ?? null);
|
|
100
|
-
const
|
|
97
|
+
const layout = computeDualPaneLayoutWithLayers(normalizedCols, normalizedRows, {
|
|
98
|
+
leftCols,
|
|
99
|
+
statusRows: 1,
|
|
100
|
+
});
|
|
101
101
|
|
|
102
102
|
return {
|
|
103
|
-
cols:
|
|
104
|
-
rows:
|
|
105
|
-
paneRows,
|
|
106
|
-
statusRow,
|
|
107
|
-
leftCols,
|
|
108
|
-
rightCols,
|
|
109
|
-
separatorCol:
|
|
110
|
-
rightStartCol:
|
|
103
|
+
cols: layout.cols,
|
|
104
|
+
rows: layout.rows,
|
|
105
|
+
paneRows: layout.paneRows,
|
|
106
|
+
statusRow: layout.statusRow,
|
|
107
|
+
leftCols: layout.leftCols,
|
|
108
|
+
rightCols: layout.rightCols,
|
|
109
|
+
separatorCol: layout.separatorCol,
|
|
110
|
+
rightStartCol: layout.rightStartCol,
|
|
111
111
|
};
|
|
112
112
|
}
|
|
113
113
|
|