@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
|
@@ -72,7 +72,7 @@ function parseArgs(argv: string[], invocationDirectory: string): DaemonOptions {
|
|
|
72
72
|
const defaultAuthToken = process.env.HARNESS_CONTROL_PLANE_AUTH_TOKEN ?? null;
|
|
73
73
|
const defaultStateDbPath = resolveHarnessRuntimePath(
|
|
74
74
|
invocationDirectory,
|
|
75
|
-
|
|
75
|
+
'.harness/control-plane.sqlite',
|
|
76
76
|
);
|
|
77
77
|
|
|
78
78
|
let host = defaultHost;
|
|
@@ -117,7 +117,7 @@ function parseArgs(argv: string[], invocationDirectory: string): DaemonOptions {
|
|
|
117
117
|
if (value === undefined) {
|
|
118
118
|
throw new Error('missing value for --state-db-path');
|
|
119
119
|
}
|
|
120
|
-
stateDbPath = value;
|
|
120
|
+
stateDbPath = resolveHarnessRuntimePath(invocationDirectory, value);
|
|
121
121
|
idx += 1;
|
|
122
122
|
continue;
|
|
123
123
|
}
|
|
@@ -132,6 +132,17 @@ function parseArgs(argv: string[], invocationDirectory: string): DaemonOptions {
|
|
|
132
132
|
if (!loopbackHosts.has(host) && authToken === null) {
|
|
133
133
|
throw new Error('non-loopback hosts require --auth-token or HARNESS_CONTROL_PLANE_AUTH_TOKEN');
|
|
134
134
|
}
|
|
135
|
+
const workspaceRuntimeRoot = resolveHarnessWorkspaceDirectory(invocationDirectory, process.env);
|
|
136
|
+
const normalizedRuntimeRoot = resolve(workspaceRuntimeRoot);
|
|
137
|
+
const normalizedStateDbPath = resolve(stateDbPath);
|
|
138
|
+
if (
|
|
139
|
+
normalizedStateDbPath !== normalizedRuntimeRoot &&
|
|
140
|
+
!normalizedStateDbPath.startsWith(`${normalizedRuntimeRoot}/`)
|
|
141
|
+
) {
|
|
142
|
+
throw new Error(
|
|
143
|
+
`invalid --state-db-path: ${stateDbPath}. state db path must be under workspace runtime root ${workspaceRuntimeRoot}`,
|
|
144
|
+
);
|
|
145
|
+
}
|
|
135
146
|
|
|
136
147
|
return {
|
|
137
148
|
host,
|
|
@@ -220,7 +231,18 @@ async function main(): Promise<number> {
|
|
|
220
231
|
branchStrategy: loadedConfig.config.github.branchStrategy,
|
|
221
232
|
viewerLogin: loadedConfig.config.github.viewerLogin,
|
|
222
233
|
},
|
|
234
|
+
linear: {
|
|
235
|
+
enabled: loadedConfig.config.linear.enabled,
|
|
236
|
+
apiBaseUrl: loadedConfig.config.linear.apiBaseUrl,
|
|
237
|
+
tokenEnvVar: loadedConfig.config.linear.tokenEnvVar,
|
|
238
|
+
},
|
|
223
239
|
lifecycleHooks: loadedConfig.config.hooks.lifecycle,
|
|
240
|
+
storageLifecyclePolicy: loadedConfig.config.storage.lifecycle,
|
|
241
|
+
storageLifecyclePolicyReload: {
|
|
242
|
+
cwd: invocationDirectory,
|
|
243
|
+
filePath: configPath,
|
|
244
|
+
env: process.env,
|
|
245
|
+
},
|
|
224
246
|
startSession: (input) => {
|
|
225
247
|
const sessionOptions: Parameters<typeof startCodexLiveSession>[0] = {
|
|
226
248
|
args: input.args,
|
package/scripts/harness-bin.js
CHANGED
|
@@ -67,8 +67,13 @@ if (!ensureBunAvailable({ command: bunCommand })) {
|
|
|
67
67
|
const here = dirname(fileURLToPath(import.meta.url));
|
|
68
68
|
const scriptPath = resolve(here, './harness.ts');
|
|
69
69
|
const runtimeArgs = [scriptPath, ...process.argv.slice(2)];
|
|
70
|
+
const runtimeEnv = {
|
|
71
|
+
...process.env,
|
|
72
|
+
HARNESS_INVOKE_CWD: process.cwd(),
|
|
73
|
+
};
|
|
70
74
|
const child = spawn(bunCommand, runtimeArgs, {
|
|
71
75
|
stdio: 'inherit',
|
|
76
|
+
env: runtimeEnv,
|
|
72
77
|
});
|
|
73
78
|
|
|
74
79
|
child.once('exit', (code, signal) => {
|
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
import { Command, Flags } from '@oclif/core';
|
|
2
|
+
import {
|
|
3
|
+
parseSessionName,
|
|
4
|
+
runAnimateCli,
|
|
5
|
+
runAuthCli,
|
|
6
|
+
runClientCli,
|
|
7
|
+
runCursorHooksCli,
|
|
8
|
+
runDiffCli,
|
|
9
|
+
runGatewayCli,
|
|
10
|
+
runNimCli,
|
|
11
|
+
runProfileCli,
|
|
12
|
+
runRenderTraceCli,
|
|
13
|
+
runStatusTimelineCli,
|
|
14
|
+
runUpdateCli,
|
|
15
|
+
} from './harness-runtime.ts';
|
|
16
|
+
|
|
17
|
+
const sessionFlag = Flags.string({
|
|
18
|
+
description:
|
|
19
|
+
'Session namespace used to isolate gateway record/log/db/profile/status-trace artifacts.',
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
interface SessionParseResult {
|
|
23
|
+
sessionName: string | null;
|
|
24
|
+
argv: readonly string[];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
abstract class HarnessCommandBase extends Command {
|
|
28
|
+
static override strict = false;
|
|
29
|
+
|
|
30
|
+
protected extractSessionArg(argv: readonly string[]): SessionParseResult {
|
|
31
|
+
const passthrough: string[] = [];
|
|
32
|
+
let sessionName: string | null = null;
|
|
33
|
+
|
|
34
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
35
|
+
const arg = argv[index]!;
|
|
36
|
+
if (arg === '--session') {
|
|
37
|
+
const value = argv[index + 1];
|
|
38
|
+
if (value === undefined) {
|
|
39
|
+
throw new Error('missing value for --session');
|
|
40
|
+
}
|
|
41
|
+
sessionName = parseSessionName(value);
|
|
42
|
+
index += 1;
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
passthrough.push(arg);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
sessionName,
|
|
50
|
+
argv: passthrough,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
protected exitIfNeeded(code: number): void {
|
|
55
|
+
if (code !== 0) {
|
|
56
|
+
this.exit(code);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
class ClientCommand extends HarnessCommandBase {
|
|
62
|
+
static override summary = 'Launch the mux client (default when no explicit command is provided).';
|
|
63
|
+
|
|
64
|
+
static override usage = [
|
|
65
|
+
'[--session <name>] [mux-args...]',
|
|
66
|
+
'client [--session <name>] [mux-args...]',
|
|
67
|
+
];
|
|
68
|
+
|
|
69
|
+
static override flags = {
|
|
70
|
+
help: Flags.help({ char: 'h' }),
|
|
71
|
+
session: sessionFlag,
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
override async run(): Promise<void> {
|
|
75
|
+
const parsed = this.extractSessionArg(this.argv);
|
|
76
|
+
const code = await runClientCli(parsed.argv, parsed.sessionName);
|
|
77
|
+
this.exitIfNeeded(code);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
class GatewayCommand extends HarnessCommandBase {
|
|
82
|
+
static override summary = 'Manage the control-plane gateway lifecycle and direct command calls.';
|
|
83
|
+
|
|
84
|
+
static override usage = [
|
|
85
|
+
'gateway [--session <name>] start [--host <host>] [--port <port>] [--auth-token <token>] [--state-db-path <path>]',
|
|
86
|
+
'gateway [--session <name>] run [--host <host>] [--port <port>] [--auth-token <token>] [--state-db-path <path>]',
|
|
87
|
+
'gateway [--session <name>] stop [--force] [--timeout-ms <ms>] [--cleanup-orphans|--no-cleanup-orphans]',
|
|
88
|
+
'gateway [--session <name>] status',
|
|
89
|
+
'gateway [--session <name>] restart [--host <host>] [--port <port>] [--auth-token <token>] [--state-db-path <path>]',
|
|
90
|
+
'gateway [--session <name>] call --json \'{"type":"session.list"}\'',
|
|
91
|
+
'gateway [--session <name>] gc [--older-than-days <days>]',
|
|
92
|
+
];
|
|
93
|
+
|
|
94
|
+
static override flags = {
|
|
95
|
+
help: Flags.help({ char: 'h' }),
|
|
96
|
+
session: sessionFlag,
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
override async run(): Promise<void> {
|
|
100
|
+
const parsed = this.extractSessionArg(this.argv);
|
|
101
|
+
if (parsed.argv.length === 0) {
|
|
102
|
+
this.error('missing gateway subcommand', { exit: 2 });
|
|
103
|
+
}
|
|
104
|
+
const code = await runGatewayCli(parsed.argv, parsed.sessionName);
|
|
105
|
+
this.exitIfNeeded(code);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
class ProfileCommand extends HarnessCommandBase {
|
|
110
|
+
static override summary =
|
|
111
|
+
'Manage gateway/client CPU profiling and live inspector profiling sessions.';
|
|
112
|
+
|
|
113
|
+
static override usage = [
|
|
114
|
+
'profile [--session <name>] start [--profile-dir <path>]',
|
|
115
|
+
'profile [--session <name>] stop [--timeout-ms <ms>]',
|
|
116
|
+
'profile [--session <name>] run [--profile-dir <path>] [mux-args...]',
|
|
117
|
+
'profile [--session <name>] [--profile-dir <path>] [mux-args...]',
|
|
118
|
+
];
|
|
119
|
+
|
|
120
|
+
static override flags = {
|
|
121
|
+
help: Flags.help({ char: 'h' }),
|
|
122
|
+
session: sessionFlag,
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
override async run(): Promise<void> {
|
|
126
|
+
const parsed = this.extractSessionArg(this.argv);
|
|
127
|
+
const code = await runProfileCli(parsed.argv, parsed.sessionName);
|
|
128
|
+
this.exitIfNeeded(code);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
class StatusTimelineCommand extends HarnessCommandBase {
|
|
133
|
+
static override summary = 'Start or stop writing status timeline artifacts for a session.';
|
|
134
|
+
|
|
135
|
+
static override usage = [
|
|
136
|
+
'status-timeline [--session <name>] start [--output-path <path>]',
|
|
137
|
+
'status-timeline [--session <name>] stop',
|
|
138
|
+
'status-timeline [--session <name>] [--output-path <path>]',
|
|
139
|
+
];
|
|
140
|
+
|
|
141
|
+
static override flags = {
|
|
142
|
+
help: Flags.help({ char: 'h' }),
|
|
143
|
+
session: sessionFlag,
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
override async run(): Promise<void> {
|
|
147
|
+
const parsed = this.extractSessionArg(this.argv);
|
|
148
|
+
const code = await runStatusTimelineCli(parsed.argv, parsed.sessionName);
|
|
149
|
+
this.exitIfNeeded(code);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
class RenderTraceCommand extends HarnessCommandBase {
|
|
154
|
+
static override summary = 'Start or stop render trace recording for a session.';
|
|
155
|
+
|
|
156
|
+
static override usage = [
|
|
157
|
+
'render-trace [--session <name>] start [--output-path <path>] [--conversation-id <id>]',
|
|
158
|
+
'render-trace [--session <name>] stop',
|
|
159
|
+
'render-trace [--session <name>] [--output-path <path>] [--conversation-id <id>]',
|
|
160
|
+
];
|
|
161
|
+
|
|
162
|
+
static override flags = {
|
|
163
|
+
help: Flags.help({ char: 'h' }),
|
|
164
|
+
session: sessionFlag,
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
override async run(): Promise<void> {
|
|
168
|
+
const parsed = this.extractSessionArg(this.argv);
|
|
169
|
+
const code = await runRenderTraceCli(parsed.argv, parsed.sessionName);
|
|
170
|
+
this.exitIfNeeded(code);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
class AuthCommand extends HarnessCommandBase {
|
|
175
|
+
static override summary = 'Authenticate providers and manage saved credential state.';
|
|
176
|
+
|
|
177
|
+
static override usage = [
|
|
178
|
+
'auth login <github|linear> [--no-browser] [--timeout-ms <ms>] [--scopes <list>] [--callback-port <port>]',
|
|
179
|
+
'auth logout <github|linear|all>',
|
|
180
|
+
'auth status [--json]',
|
|
181
|
+
];
|
|
182
|
+
|
|
183
|
+
static override flags = {
|
|
184
|
+
help: Flags.help({ char: 'h' }),
|
|
185
|
+
session: sessionFlag,
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
override async run(): Promise<void> {
|
|
189
|
+
const parsed = this.extractSessionArg(this.argv);
|
|
190
|
+
const code = await runAuthCli(parsed.argv, parsed.sessionName);
|
|
191
|
+
this.exitIfNeeded(code);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
class UpdateCommand extends HarnessCommandBase {
|
|
196
|
+
static override summary = 'Install the latest Harness package globally using Bun.';
|
|
197
|
+
|
|
198
|
+
static override aliases = ['upgrade'];
|
|
199
|
+
|
|
200
|
+
static override usage = ['update', 'upgrade'];
|
|
201
|
+
|
|
202
|
+
static override flags = {
|
|
203
|
+
help: Flags.help({ char: 'h' }),
|
|
204
|
+
session: sessionFlag,
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
override async run(): Promise<void> {
|
|
208
|
+
const parsed = this.extractSessionArg(this.argv);
|
|
209
|
+
const code = runUpdateCli(parsed.argv, parsed.sessionName);
|
|
210
|
+
this.exitIfNeeded(code);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
class CursorHooksCommand extends HarnessCommandBase {
|
|
215
|
+
static override summary = 'Install or uninstall managed Cursor hooks.';
|
|
216
|
+
|
|
217
|
+
static override usage = [
|
|
218
|
+
'cursor-hooks [--session <name>] install [--hooks-file <path>]',
|
|
219
|
+
'cursor-hooks [--session <name>] uninstall [--hooks-file <path>]',
|
|
220
|
+
];
|
|
221
|
+
|
|
222
|
+
static override flags = {
|
|
223
|
+
help: Flags.help({ char: 'h' }),
|
|
224
|
+
session: sessionFlag,
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
override async run(): Promise<void> {
|
|
228
|
+
const parsed = this.extractSessionArg(this.argv);
|
|
229
|
+
const code = await runCursorHooksCli(parsed.argv, parsed.sessionName);
|
|
230
|
+
this.exitIfNeeded(code);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
class AnimateCommand extends HarnessCommandBase {
|
|
235
|
+
static override summary = 'Render the terminal animation benchmark scene.';
|
|
236
|
+
|
|
237
|
+
static override usage = [
|
|
238
|
+
'animate [--fps <fps>] [--frames <count>] [--duration-ms <ms>] [--seed <seed>] [--no-color]',
|
|
239
|
+
];
|
|
240
|
+
|
|
241
|
+
static override flags = {
|
|
242
|
+
help: Flags.help({ char: 'h' }),
|
|
243
|
+
session: sessionFlag,
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
override async run(): Promise<void> {
|
|
247
|
+
const parsed = this.extractSessionArg(this.argv);
|
|
248
|
+
const code = await runAnimateCli(parsed.argv);
|
|
249
|
+
this.exitIfNeeded(code);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
class NimCommand extends HarnessCommandBase {
|
|
254
|
+
static override summary = 'Run Nim interactive TUI smoke/debug client.';
|
|
255
|
+
|
|
256
|
+
static override usage = ['nim [options]'];
|
|
257
|
+
|
|
258
|
+
static override flags = {
|
|
259
|
+
help: Flags.help({ char: 'h' }),
|
|
260
|
+
session: sessionFlag,
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
override async run(): Promise<void> {
|
|
264
|
+
const parsed = this.extractSessionArg(this.argv);
|
|
265
|
+
const code = await runNimCli(parsed.argv, parsed.sessionName);
|
|
266
|
+
this.exitIfNeeded(code);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
class DiffCommand extends HarnessCommandBase {
|
|
271
|
+
static override summary = 'Render git diffs in the diff TUI/CLI view.';
|
|
272
|
+
|
|
273
|
+
static override usage = ['diff [--session <name>] [diff-options...]'];
|
|
274
|
+
|
|
275
|
+
static override flags = {
|
|
276
|
+
session: sessionFlag,
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
override async run(): Promise<void> {
|
|
280
|
+
const parsed = this.extractSessionArg(this.argv);
|
|
281
|
+
const code = await runDiffCli(parsed.argv, parsed.sessionName);
|
|
282
|
+
this.exitIfNeeded(code);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
const commands = {
|
|
287
|
+
client: ClientCommand,
|
|
288
|
+
gateway: GatewayCommand,
|
|
289
|
+
profile: ProfileCommand,
|
|
290
|
+
'status-timeline': StatusTimelineCommand,
|
|
291
|
+
'render-trace': RenderTraceCommand,
|
|
292
|
+
auth: AuthCommand,
|
|
293
|
+
update: UpdateCommand,
|
|
294
|
+
'cursor-hooks': CursorHooksCommand,
|
|
295
|
+
nim: NimCommand,
|
|
296
|
+
animate: AnimateCommand,
|
|
297
|
+
diff: DiffCommand,
|
|
298
|
+
} satisfies Record<string, Command.Class>;
|
|
299
|
+
|
|
300
|
+
export default commands;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { runHarnessAnimate } from './harness-animate.ts';
|
|
2
|
+
import { runNimTuiSmoke } from './nim-tui-smoke.ts';
|
|
3
|
+
import {
|
|
4
|
+
createDefaultHarnessRuntimeApplication,
|
|
5
|
+
type HarnessRuntimeApplication,
|
|
6
|
+
} from '../src/cli/runtime-app/application.ts';
|
|
7
|
+
import { parseGlobalCliOptions, parseSessionName } from '../src/cli/parsing/session.ts';
|
|
8
|
+
|
|
9
|
+
const app: HarnessRuntimeApplication = createDefaultHarnessRuntimeApplication();
|
|
10
|
+
|
|
11
|
+
export { parseGlobalCliOptions, parseSessionName };
|
|
12
|
+
|
|
13
|
+
export async function runGatewayCli(
|
|
14
|
+
args: readonly string[],
|
|
15
|
+
sessionName: string | null,
|
|
16
|
+
): Promise<number> {
|
|
17
|
+
return await app.runGatewayCli(args, sessionName);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export async function runProfileCli(
|
|
21
|
+
args: readonly string[],
|
|
22
|
+
sessionName: string | null,
|
|
23
|
+
): Promise<number> {
|
|
24
|
+
return await app.runProfileCli(args, sessionName);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export async function runStatusTimelineCli(
|
|
28
|
+
args: readonly string[],
|
|
29
|
+
sessionName: string | null,
|
|
30
|
+
): Promise<number> {
|
|
31
|
+
return await app.runStatusTimelineCli(args, sessionName);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export async function runRenderTraceCli(
|
|
35
|
+
args: readonly string[],
|
|
36
|
+
sessionName: string | null,
|
|
37
|
+
): Promise<number> {
|
|
38
|
+
return await app.runRenderTraceCli(args, sessionName);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export async function runAuthCli(
|
|
42
|
+
args: readonly string[],
|
|
43
|
+
sessionName: string | null,
|
|
44
|
+
): Promise<number> {
|
|
45
|
+
return await app.runAuthCli(args, sessionName);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function runUpdateCli(args: readonly string[], sessionName: string | null): number {
|
|
49
|
+
return app.runUpdateCli(args, sessionName);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export async function runCursorHooksCli(
|
|
53
|
+
args: readonly string[],
|
|
54
|
+
sessionName: string | null,
|
|
55
|
+
): Promise<number> {
|
|
56
|
+
return await app.runCursorHooksCli(args, sessionName);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export async function runDiffCli(
|
|
60
|
+
args: readonly string[],
|
|
61
|
+
sessionName: string | null,
|
|
62
|
+
): Promise<number> {
|
|
63
|
+
return await app.runDiffCli(args, sessionName);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export async function runClientCli(
|
|
67
|
+
args: readonly string[],
|
|
68
|
+
sessionName: string | null,
|
|
69
|
+
): Promise<number> {
|
|
70
|
+
return await app.runClientCli(args, sessionName);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export async function runAnimateCli(args: readonly string[]): Promise<number> {
|
|
74
|
+
return await runHarnessAnimate(args);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export async function runNimCli(
|
|
78
|
+
args: readonly string[],
|
|
79
|
+
sessionName: string | null,
|
|
80
|
+
): Promise<number> {
|
|
81
|
+
return await runNimTuiSmoke(args, { sessionName });
|
|
82
|
+
}
|