@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,11 +1,19 @@
|
|
|
1
1
|
import type { WorkspaceModel } from '../domain/workspace.ts';
|
|
2
2
|
import type { PaneSelection, PaneSelectionDrag } from '../mux/live-mux/selection.ts';
|
|
3
3
|
|
|
4
|
-
interface
|
|
4
|
+
interface RuntimeRenderStateDirectoryLookup {
|
|
5
|
+
hasDirectory(directoryId: string): boolean;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
interface RuntimeRenderStateConversationLookup<TConversation> {
|
|
9
|
+
readonly activeConversationId: string | null;
|
|
10
|
+
getActiveConversation(): TConversation | null;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface RuntimeRenderStateOptions<TConversation, TFrame> {
|
|
5
14
|
readonly workspace: WorkspaceModel;
|
|
6
|
-
readonly
|
|
7
|
-
readonly
|
|
8
|
-
readonly activeConversation: () => TConversation | null;
|
|
15
|
+
readonly directories: RuntimeRenderStateDirectoryLookup;
|
|
16
|
+
readonly conversations: RuntimeRenderStateConversationLookup<TConversation>;
|
|
9
17
|
readonly snapshotFrame: (conversation: TConversation) => TFrame;
|
|
10
18
|
readonly selectionVisibleRows: (
|
|
11
19
|
frame: TFrame,
|
|
@@ -13,60 +21,65 @@ interface RuntimeRenderStateOptions<TConversation, TFrame> {
|
|
|
13
21
|
) => readonly number[];
|
|
14
22
|
}
|
|
15
23
|
|
|
16
|
-
interface RuntimeRenderStateResult<TConversation, TFrame> {
|
|
24
|
+
export interface RuntimeRenderStateResult<TConversation, TFrame> {
|
|
17
25
|
readonly projectPaneActive: boolean;
|
|
18
26
|
readonly homePaneActive: boolean;
|
|
27
|
+
readonly nimPaneActive: boolean;
|
|
19
28
|
readonly activeConversation: TConversation | null;
|
|
20
29
|
readonly rightFrame: TFrame | null;
|
|
21
30
|
readonly renderSelection: PaneSelection | null;
|
|
22
31
|
readonly selectionRows: readonly number[];
|
|
23
32
|
}
|
|
24
33
|
|
|
25
|
-
export
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
34
|
+
export function prepareRuntimeRenderState<TConversation, TFrame>(
|
|
35
|
+
options: RuntimeRenderStateOptions<TConversation, TFrame>,
|
|
36
|
+
selection: PaneSelection | null,
|
|
37
|
+
selectionDrag: PaneSelectionDrag | null,
|
|
38
|
+
): RuntimeRenderStateResult<TConversation, TFrame> | null {
|
|
39
|
+
const workspace = options.workspace;
|
|
40
|
+
const projectPaneActive =
|
|
41
|
+
workspace.mainPaneMode === 'project' &&
|
|
42
|
+
workspace.activeDirectoryId !== null &&
|
|
43
|
+
options.directories.hasDirectory(workspace.activeDirectoryId);
|
|
44
|
+
const homePaneActive = workspace.mainPaneMode === 'home';
|
|
45
|
+
const nimPaneActive = workspace.mainPaneMode === 'nim';
|
|
46
|
+
if (
|
|
47
|
+
!projectPaneActive &&
|
|
48
|
+
!homePaneActive &&
|
|
49
|
+
!nimPaneActive &&
|
|
50
|
+
options.conversations.activeConversationId === null
|
|
51
|
+
) {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
41
54
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
55
|
+
const activeConversation = options.conversations.getActiveConversation();
|
|
56
|
+
if (!projectPaneActive && !homePaneActive && !nimPaneActive && activeConversation === null) {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
46
59
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
60
|
+
const rightFrame =
|
|
61
|
+
!projectPaneActive && !homePaneActive && !nimPaneActive && activeConversation !== null
|
|
62
|
+
? options.snapshotFrame(activeConversation)
|
|
63
|
+
: null;
|
|
64
|
+
const renderSelection =
|
|
65
|
+
rightFrame !== null && selectionDrag !== null && selectionDrag.hasDragged
|
|
66
|
+
? {
|
|
67
|
+
anchor: selectionDrag.anchor,
|
|
68
|
+
focus: selectionDrag.focus,
|
|
69
|
+
text: '',
|
|
70
|
+
}
|
|
71
|
+
: rightFrame !== null
|
|
72
|
+
? selection
|
|
50
73
|
: null;
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
rightFrame === null ? [] : this.options.selectionVisibleRows(rightFrame, renderSelection);
|
|
63
|
-
return {
|
|
64
|
-
projectPaneActive,
|
|
65
|
-
homePaneActive,
|
|
66
|
-
activeConversation,
|
|
67
|
-
rightFrame,
|
|
68
|
-
renderSelection,
|
|
69
|
-
selectionRows,
|
|
70
|
-
};
|
|
71
|
-
}
|
|
74
|
+
const selectionRows =
|
|
75
|
+
rightFrame === null ? [] : options.selectionVisibleRows(rightFrame, renderSelection);
|
|
76
|
+
return {
|
|
77
|
+
projectPaneActive,
|
|
78
|
+
homePaneActive,
|
|
79
|
+
nimPaneActive,
|
|
80
|
+
activeConversation,
|
|
81
|
+
rightFrame,
|
|
82
|
+
renderSelection,
|
|
83
|
+
selectionRows,
|
|
84
|
+
};
|
|
72
85
|
}
|
|
@@ -24,7 +24,7 @@ interface RuntimeRepositoryActionService<TRepository extends RepositoryRecordSha
|
|
|
24
24
|
archiveRepository(repositoryId: string): Promise<unknown>;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
interface RuntimeRepositoryActionsOptions<TRepository extends RepositoryRecordShape> {
|
|
27
|
+
export interface RuntimeRepositoryActionsOptions<TRepository extends RepositoryRecordShape> {
|
|
28
28
|
readonly workspace: WorkspaceModel;
|
|
29
29
|
readonly repositories: Map<string, TRepository>;
|
|
30
30
|
readonly controlPlaneService: RuntimeRepositoryActionService<TRepository>;
|
|
@@ -49,51 +49,85 @@ function repositoryHomePriority(repository: RepositoryRecordShape): number | nul
|
|
|
49
49
|
return raw;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
export
|
|
53
|
-
|
|
52
|
+
export interface RuntimeRepositoryActions {
|
|
53
|
+
openRepositoryPromptForCreate(): void;
|
|
54
|
+
openRepositoryPromptForEdit(repositoryId: string): void;
|
|
55
|
+
queueRepositoryPriorityOrder(orderedRepositoryIds: readonly string[], label: string): void;
|
|
56
|
+
reorderRepositoryByDrop(
|
|
57
|
+
draggedRepositoryId: string,
|
|
58
|
+
targetRepositoryId: string,
|
|
59
|
+
orderedRepositoryIds: readonly string[],
|
|
60
|
+
): void;
|
|
61
|
+
upsertRepositoryByRemoteUrl(remoteUrl: string, existingRepositoryId?: string): Promise<void>;
|
|
62
|
+
archiveRepositoryById(repositoryId: string): Promise<void>;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function createRuntimeRepositoryActions<TRepository extends RepositoryRecordShape>(
|
|
66
|
+
options: RuntimeRepositoryActionsOptions<TRepository>,
|
|
67
|
+
): RuntimeRepositoryActions {
|
|
68
|
+
const reorderIdsByMove = (
|
|
69
|
+
orderedIds: readonly string[],
|
|
70
|
+
movedId: string,
|
|
71
|
+
targetId: string,
|
|
72
|
+
): readonly string[] | null => {
|
|
73
|
+
const fromIndex = orderedIds.indexOf(movedId);
|
|
74
|
+
const targetIndex = orderedIds.indexOf(targetId);
|
|
75
|
+
if (fromIndex < 0 || targetIndex < 0 || fromIndex === targetIndex) {
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
const reordered = [...orderedIds];
|
|
79
|
+
const moved = reordered.splice(fromIndex, 1)[0]!;
|
|
80
|
+
reordered.splice(targetIndex, 0, moved);
|
|
81
|
+
return reordered;
|
|
82
|
+
};
|
|
54
83
|
|
|
55
|
-
openRepositoryPromptForCreate(): void {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
84
|
+
const openRepositoryPromptForCreate = (): void => {
|
|
85
|
+
options.workspace.newThreadPrompt = null;
|
|
86
|
+
options.workspace.addDirectoryPrompt = null;
|
|
87
|
+
options.workspace.apiKeyPrompt = null;
|
|
88
|
+
if (options.workspace.conversationTitleEdit !== null) {
|
|
89
|
+
options.stopConversationTitleEdit();
|
|
60
90
|
}
|
|
61
|
-
|
|
62
|
-
|
|
91
|
+
options.workspace.conversationTitleEditClickState = null;
|
|
92
|
+
options.workspace.repositoryPrompt = {
|
|
63
93
|
mode: 'add',
|
|
64
94
|
repositoryId: null,
|
|
65
95
|
value: '',
|
|
66
96
|
error: null,
|
|
67
97
|
};
|
|
68
|
-
|
|
69
|
-
}
|
|
98
|
+
options.markDirty();
|
|
99
|
+
};
|
|
70
100
|
|
|
71
|
-
openRepositoryPromptForEdit(repositoryId: string): void {
|
|
72
|
-
const repository =
|
|
101
|
+
const openRepositoryPromptForEdit = (repositoryId: string): void => {
|
|
102
|
+
const repository = options.repositories.get(repositoryId);
|
|
73
103
|
if (repository === undefined) {
|
|
74
104
|
return;
|
|
75
105
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
106
|
+
options.workspace.newThreadPrompt = null;
|
|
107
|
+
options.workspace.addDirectoryPrompt = null;
|
|
108
|
+
options.workspace.apiKeyPrompt = null;
|
|
109
|
+
if (options.workspace.conversationTitleEdit !== null) {
|
|
110
|
+
options.stopConversationTitleEdit();
|
|
80
111
|
}
|
|
81
|
-
|
|
82
|
-
|
|
112
|
+
options.workspace.conversationTitleEditClickState = null;
|
|
113
|
+
options.workspace.repositoryPrompt = {
|
|
83
114
|
mode: 'edit',
|
|
84
115
|
repositoryId,
|
|
85
116
|
value: repository.remoteUrl,
|
|
86
117
|
error: null,
|
|
87
118
|
};
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
}
|
|
119
|
+
options.workspace.taskPaneSelectionFocus = 'repository';
|
|
120
|
+
options.markDirty();
|
|
121
|
+
};
|
|
91
122
|
|
|
92
|
-
queueRepositoryPriorityOrder
|
|
123
|
+
const queueRepositoryPriorityOrder = (
|
|
124
|
+
orderedRepositoryIds: readonly string[],
|
|
125
|
+
label: string,
|
|
126
|
+
): void => {
|
|
93
127
|
const updates: Array<{ repositoryId: string; metadata: Record<string, unknown> }> = [];
|
|
94
128
|
for (let index = 0; index < orderedRepositoryIds.length; index += 1) {
|
|
95
129
|
const repositoryId = orderedRepositoryIds[index]!;
|
|
96
|
-
const repository =
|
|
130
|
+
const repository = options.repositories.get(repositoryId);
|
|
97
131
|
if (repository === undefined) {
|
|
98
132
|
continue;
|
|
99
133
|
}
|
|
@@ -111,25 +145,25 @@ export class RuntimeRepositoryActions<TRepository extends RepositoryRecordShape>
|
|
|
111
145
|
if (updates.length === 0) {
|
|
112
146
|
return;
|
|
113
147
|
}
|
|
114
|
-
|
|
148
|
+
options.queueControlPlaneOp(async () => {
|
|
115
149
|
for (const update of updates) {
|
|
116
|
-
const repository = await
|
|
150
|
+
const repository = await options.controlPlaneService.updateRepository({
|
|
117
151
|
repositoryId: update.repositoryId,
|
|
118
152
|
metadata: update.metadata,
|
|
119
153
|
});
|
|
120
|
-
|
|
154
|
+
options.repositories.set(repository.repositoryId, repository);
|
|
121
155
|
}
|
|
122
|
-
|
|
123
|
-
|
|
156
|
+
options.syncTaskPaneRepositorySelection();
|
|
157
|
+
options.markDirty();
|
|
124
158
|
}, label);
|
|
125
|
-
}
|
|
159
|
+
};
|
|
126
160
|
|
|
127
|
-
reorderRepositoryByDrop(
|
|
161
|
+
const reorderRepositoryByDrop = (
|
|
128
162
|
draggedRepositoryId: string,
|
|
129
163
|
targetRepositoryId: string,
|
|
130
164
|
orderedRepositoryIds: readonly string[],
|
|
131
|
-
): void {
|
|
132
|
-
const reordered =
|
|
165
|
+
): void => {
|
|
166
|
+
const reordered = reorderIdsByMove(
|
|
133
167
|
orderedRepositoryIds,
|
|
134
168
|
draggedRepositoryId,
|
|
135
169
|
targetRepositoryId,
|
|
@@ -137,22 +171,22 @@ export class RuntimeRepositoryActions<TRepository extends RepositoryRecordShape>
|
|
|
137
171
|
if (reordered === null) {
|
|
138
172
|
return;
|
|
139
173
|
}
|
|
140
|
-
|
|
141
|
-
}
|
|
174
|
+
queueRepositoryPriorityOrder(reordered, 'repositories-reorder-drag');
|
|
175
|
+
};
|
|
142
176
|
|
|
143
|
-
async
|
|
177
|
+
const upsertRepositoryByRemoteUrl = async (
|
|
144
178
|
remoteUrl: string,
|
|
145
179
|
existingRepositoryId?: string,
|
|
146
|
-
): Promise<void> {
|
|
147
|
-
const normalizedRemoteUrl =
|
|
180
|
+
): Promise<void> => {
|
|
181
|
+
const normalizedRemoteUrl = options.normalizeGitHubRemoteUrl(remoteUrl);
|
|
148
182
|
if (normalizedRemoteUrl === null) {
|
|
149
183
|
throw new Error('github url required');
|
|
150
184
|
}
|
|
151
|
-
const repositoryName =
|
|
185
|
+
const repositoryName = options.repositoryNameFromGitHubRemoteUrl(normalizedRemoteUrl);
|
|
152
186
|
const repository =
|
|
153
187
|
existingRepositoryId === undefined
|
|
154
|
-
? await
|
|
155
|
-
repositoryId:
|
|
188
|
+
? await options.controlPlaneService.upsertRepository({
|
|
189
|
+
repositoryId: options.createRepositoryId(),
|
|
156
190
|
name: repositoryName,
|
|
157
191
|
remoteUrl: normalizedRemoteUrl,
|
|
158
192
|
defaultBranch: 'main',
|
|
@@ -160,38 +194,31 @@ export class RuntimeRepositoryActions<TRepository extends RepositoryRecordShape>
|
|
|
160
194
|
source: 'mux-manual',
|
|
161
195
|
},
|
|
162
196
|
})
|
|
163
|
-
: await
|
|
197
|
+
: await options.controlPlaneService.updateRepository({
|
|
164
198
|
repositoryId: existingRepositoryId,
|
|
165
199
|
name: repositoryName,
|
|
166
200
|
remoteUrl: normalizedRemoteUrl,
|
|
167
201
|
});
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
}
|
|
202
|
+
options.repositories.set(repository.repositoryId, repository);
|
|
203
|
+
options.syncRepositoryAssociationsWithDirectorySnapshots();
|
|
204
|
+
options.syncTaskPaneRepositorySelection();
|
|
205
|
+
options.markDirty();
|
|
206
|
+
};
|
|
173
207
|
|
|
174
|
-
async
|
|
175
|
-
await
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
}
|
|
208
|
+
const archiveRepositoryById = async (repositoryId: string): Promise<void> => {
|
|
209
|
+
await options.controlPlaneService.archiveRepository(repositoryId);
|
|
210
|
+
options.repositories.delete(repositoryId);
|
|
211
|
+
options.syncRepositoryAssociationsWithDirectorySnapshots();
|
|
212
|
+
options.syncTaskPaneRepositorySelection();
|
|
213
|
+
options.markDirty();
|
|
214
|
+
};
|
|
181
215
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
return null;
|
|
191
|
-
}
|
|
192
|
-
const reordered = [...orderedIds];
|
|
193
|
-
const moved = reordered.splice(fromIndex, 1)[0]!;
|
|
194
|
-
reordered.splice(targetIndex, 0, moved);
|
|
195
|
-
return reordered;
|
|
196
|
-
}
|
|
216
|
+
return {
|
|
217
|
+
openRepositoryPromptForCreate,
|
|
218
|
+
openRepositoryPromptForEdit,
|
|
219
|
+
queueRepositoryPriorityOrder,
|
|
220
|
+
reorderRepositoryByDrop,
|
|
221
|
+
upsertRepositoryByRemoteUrl,
|
|
222
|
+
archiveRepositoryById,
|
|
223
|
+
};
|
|
197
224
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { WorkspaceModel } from '../domain/workspace.ts';
|
|
2
|
-
import type { TaskManager } from '../domain/tasks.ts';
|
|
3
2
|
import type { ProjectPaneSnapshot } from '../mux/harness-core-ui.ts';
|
|
4
3
|
import type { TaskComposerBuffer } from '../mux/task-composer.ts';
|
|
4
|
+
import type { NimPaneViewModel } from '../ui/panes/nim.ts';
|
|
5
5
|
import type {
|
|
6
6
|
TaskFocusedPaneRepositoryRecord,
|
|
7
7
|
TaskFocusedPaneTaskRecord,
|
|
@@ -9,7 +9,7 @@ import type {
|
|
|
9
9
|
} from '../mux/task-focused-pane.ts';
|
|
10
10
|
import type { TerminalSnapshotFrameCore } from '../terminal/snapshot-oracle.ts';
|
|
11
11
|
|
|
12
|
-
interface RuntimeRightPaneLayout {
|
|
12
|
+
export interface RuntimeRightPaneLayout {
|
|
13
13
|
readonly rightCols: number;
|
|
14
14
|
readonly paneRows: number;
|
|
15
15
|
}
|
|
@@ -25,6 +25,7 @@ interface HomePaneRenderInput<
|
|
|
25
25
|
readonly layout: RuntimeRightPaneLayout;
|
|
26
26
|
readonly repositories: ReadonlyMap<string, TRepositoryRecord>;
|
|
27
27
|
readonly tasks: ReadonlyMap<string, TTaskRecord>;
|
|
28
|
+
readonly showTaskPlanningUi?: boolean;
|
|
28
29
|
readonly selectedRepositoryId: string | null;
|
|
29
30
|
readonly repositoryDropdownOpen: boolean;
|
|
30
31
|
readonly editorTarget: WorkspaceModel['taskEditorTarget'];
|
|
@@ -52,81 +53,107 @@ interface ProjectPaneLike {
|
|
|
52
53
|
};
|
|
53
54
|
}
|
|
54
55
|
|
|
55
|
-
interface
|
|
56
|
+
interface NimPaneLike {
|
|
57
|
+
render(input: { layout: RuntimeRightPaneLayout; viewModel: NimPaneViewModel }): {
|
|
58
|
+
readonly rows: readonly string[];
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export interface RuntimeRightPaneRenderInput<
|
|
63
|
+
TRepositoryRecord extends TaskFocusedPaneRepositoryRecord,
|
|
64
|
+
TTaskRecord extends TaskFocusedPaneTaskRecord,
|
|
65
|
+
> {
|
|
56
66
|
readonly layout: RuntimeRightPaneLayout;
|
|
57
67
|
readonly rightFrame: TerminalSnapshotFrameCore | null;
|
|
58
68
|
readonly homePaneActive: boolean;
|
|
69
|
+
readonly nimPaneActive: boolean;
|
|
59
70
|
readonly projectPaneActive: boolean;
|
|
60
71
|
readonly activeDirectoryId: string | null;
|
|
72
|
+
readonly snapshot: RuntimeRightPaneRenderSnapshot<TRepositoryRecord, TTaskRecord>;
|
|
61
73
|
}
|
|
62
74
|
|
|
63
|
-
interface
|
|
75
|
+
export interface RuntimeRightPaneRenderSnapshot<
|
|
64
76
|
TRepositoryRecord extends TaskFocusedPaneRepositoryRecord,
|
|
65
77
|
TTaskRecord extends TaskFocusedPaneTaskRecord,
|
|
66
78
|
> {
|
|
67
|
-
readonly workspace: WorkspaceModel;
|
|
68
79
|
readonly repositories: ReadonlyMap<string, TRepositoryRecord>;
|
|
69
|
-
readonly
|
|
80
|
+
readonly tasks: ReadonlyMap<string, TTaskRecord>;
|
|
81
|
+
readonly taskComposers: ReadonlyMap<string, TaskComposerBuffer>;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export interface RuntimeRightPaneRenderOptions<
|
|
85
|
+
TRepositoryRecord extends TaskFocusedPaneRepositoryRecord,
|
|
86
|
+
TTaskRecord extends TaskFocusedPaneTaskRecord,
|
|
87
|
+
> {
|
|
88
|
+
readonly workspace: WorkspaceModel;
|
|
89
|
+
readonly showTasks?: boolean;
|
|
70
90
|
readonly conversationPane: ConversationPaneLike;
|
|
71
91
|
readonly homePane: HomePaneLike<TRepositoryRecord, TTaskRecord>;
|
|
72
92
|
readonly projectPane: ProjectPaneLike;
|
|
93
|
+
readonly nimPane: NimPaneLike;
|
|
94
|
+
readonly getNimViewModel: () => NimPaneViewModel;
|
|
73
95
|
readonly refreshProjectPaneSnapshot: (directoryId: string) => ProjectPaneSnapshot | null;
|
|
74
96
|
readonly emptyTaskPaneView: () => TaskFocusedPaneView;
|
|
75
97
|
}
|
|
76
98
|
|
|
77
|
-
export
|
|
99
|
+
export function renderRuntimeRightPaneRows<
|
|
78
100
|
TRepositoryRecord extends TaskFocusedPaneRepositoryRecord,
|
|
79
101
|
TTaskRecord extends TaskFocusedPaneTaskRecord,
|
|
80
|
-
>
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
102
|
+
>(
|
|
103
|
+
options: RuntimeRightPaneRenderOptions<TRepositoryRecord, TTaskRecord>,
|
|
104
|
+
input: RuntimeRightPaneRenderInput<TRepositoryRecord, TTaskRecord>,
|
|
105
|
+
): readonly string[] {
|
|
106
|
+
const workspace = options.workspace;
|
|
107
|
+
workspace.latestTaskPaneView = options.emptyTaskPaneView();
|
|
84
108
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
109
|
+
if (input.rightFrame !== null) {
|
|
110
|
+
return options.conversationPane.render(input.rightFrame, input.layout);
|
|
111
|
+
}
|
|
88
112
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
113
|
+
if (input.homePaneActive) {
|
|
114
|
+
const view = options.homePane.render({
|
|
115
|
+
layout: input.layout,
|
|
116
|
+
repositories: input.snapshot.repositories,
|
|
117
|
+
tasks: input.snapshot.tasks,
|
|
118
|
+
showTaskPlanningUi:
|
|
119
|
+
(options.showTasks ?? true) && workspace.leftNavSelection.kind === 'tasks',
|
|
120
|
+
selectedRepositoryId: workspace.taskPaneSelectedRepositoryId,
|
|
121
|
+
repositoryDropdownOpen: workspace.taskRepositoryDropdownOpen,
|
|
122
|
+
editorTarget: workspace.taskEditorTarget,
|
|
123
|
+
draftBuffer: workspace.taskDraftComposer,
|
|
124
|
+
taskBufferById: input.snapshot.taskComposers,
|
|
125
|
+
notice: workspace.taskPaneNotice,
|
|
126
|
+
scrollTop: workspace.taskPaneScrollTop,
|
|
127
|
+
});
|
|
128
|
+
workspace.taskPaneSelectedRepositoryId = view.selectedRepositoryId;
|
|
129
|
+
workspace.taskPaneScrollTop = view.top;
|
|
130
|
+
workspace.latestTaskPaneView = view;
|
|
131
|
+
return view.rows;
|
|
132
|
+
}
|
|
92
133
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
editorTarget: workspace.taskEditorTarget,
|
|
101
|
-
draftBuffer: workspace.taskDraftComposer,
|
|
102
|
-
taskBufferById: this.options.taskManager.readonlyTaskComposers(),
|
|
103
|
-
notice: workspace.taskPaneNotice,
|
|
104
|
-
scrollTop: workspace.taskPaneScrollTop,
|
|
105
|
-
});
|
|
106
|
-
workspace.taskPaneSelectedRepositoryId = view.selectedRepositoryId;
|
|
107
|
-
workspace.taskPaneScrollTop = view.top;
|
|
108
|
-
workspace.latestTaskPaneView = view;
|
|
109
|
-
return view.rows;
|
|
110
|
-
}
|
|
134
|
+
if (input.nimPaneActive) {
|
|
135
|
+
const view = options.nimPane.render({
|
|
136
|
+
layout: input.layout,
|
|
137
|
+
viewModel: options.getNimViewModel(),
|
|
138
|
+
});
|
|
139
|
+
return view.rows;
|
|
140
|
+
}
|
|
111
141
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
input.activeDirectoryId,
|
|
119
|
-
);
|
|
120
|
-
}
|
|
121
|
-
const view = this.options.projectPane.render({
|
|
122
|
-
layout: input.layout,
|
|
123
|
-
snapshot: workspace.projectPaneSnapshot,
|
|
124
|
-
scrollTop: workspace.projectPaneScrollTop,
|
|
125
|
-
});
|
|
126
|
-
workspace.projectPaneScrollTop = view.scrollTop;
|
|
127
|
-
return view.rows;
|
|
142
|
+
if (input.projectPaneActive && input.activeDirectoryId !== null) {
|
|
143
|
+
const needsSnapshotRefresh =
|
|
144
|
+
workspace.projectPaneSnapshot === null ||
|
|
145
|
+
workspace.projectPaneSnapshot.directoryId !== input.activeDirectoryId;
|
|
146
|
+
if (needsSnapshotRefresh) {
|
|
147
|
+
workspace.projectPaneSnapshot = options.refreshProjectPaneSnapshot(input.activeDirectoryId);
|
|
128
148
|
}
|
|
129
|
-
|
|
130
|
-
|
|
149
|
+
const view = options.projectPane.render({
|
|
150
|
+
layout: input.layout,
|
|
151
|
+
snapshot: workspace.projectPaneSnapshot,
|
|
152
|
+
scrollTop: workspace.projectPaneScrollTop,
|
|
153
|
+
});
|
|
154
|
+
workspace.projectPaneScrollTop = view.scrollTop;
|
|
155
|
+
return view.rows;
|
|
131
156
|
}
|
|
157
|
+
|
|
158
|
+
return Array.from({ length: input.layout.paneRows }, () => ' '.repeat(input.layout.rightCols));
|
|
132
159
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
interface RuntimeShutdownServiceOptions {
|
|
1
|
+
export interface RuntimeShutdownServiceOptions {
|
|
2
2
|
readonly screen: {
|
|
3
3
|
clearDirty: () => void;
|
|
4
4
|
};
|
|
@@ -11,12 +11,15 @@ interface RuntimeShutdownServiceOptions {
|
|
|
11
11
|
readonly clearResizeTimer: () => void;
|
|
12
12
|
readonly clearPtyResizeTimer: () => void;
|
|
13
13
|
readonly clearHomePaneBackgroundTimer: () => void;
|
|
14
|
+
readonly clearStorageLifecycleTimer: () => void;
|
|
15
|
+
readonly clearProjectPaneGitHubReviewRefreshTimer: () => void;
|
|
14
16
|
readonly persistMuxUiStateNow: () => void;
|
|
15
17
|
readonly clearConversationTitleEditTimer: () => void;
|
|
16
18
|
readonly flushTaskComposerPersist: () => void;
|
|
17
19
|
readonly clearRenderScheduled: () => void;
|
|
18
20
|
readonly detachProcessListeners: () => void;
|
|
19
21
|
readonly removeEnvelopeListener: () => void;
|
|
22
|
+
readonly stopWorkspaceObservedEvents: () => void;
|
|
20
23
|
readonly unsubscribeTaskPlanningEvents: () => Promise<void>;
|
|
21
24
|
readonly closeKeyEventSubscription: () => Promise<void>;
|
|
22
25
|
readonly clearRuntimeFatalExitTimer: () => void;
|
|
@@ -41,39 +44,39 @@ interface RuntimeShutdownServiceOptions {
|
|
|
41
44
|
readonly shutdownPerfCore: () => void;
|
|
42
45
|
}
|
|
43
46
|
|
|
44
|
-
export
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
this.options.eventPersistence.flush('shutdown');
|
|
72
|
-
const recordingCloseError = await this.options.recordingService.closeWriter();
|
|
73
|
-
this.options.store.close();
|
|
74
|
-
this.options.restoreTerminalState();
|
|
75
|
-
await this.options.recordingService.finalizeAfterShutdown(recordingCloseError);
|
|
76
|
-
this.options.startupShutdownService.finalize();
|
|
77
|
-
this.options.shutdownPerfCore();
|
|
47
|
+
export async function finalizeRuntimeShutdown(
|
|
48
|
+
options: RuntimeShutdownServiceOptions,
|
|
49
|
+
): Promise<void> {
|
|
50
|
+
options.screen.clearDirty();
|
|
51
|
+
options.outputLoadSampler.stop();
|
|
52
|
+
options.startupBackgroundProbeService.stop();
|
|
53
|
+
options.clearResizeTimer();
|
|
54
|
+
options.clearPtyResizeTimer();
|
|
55
|
+
options.clearHomePaneBackgroundTimer();
|
|
56
|
+
options.clearStorageLifecycleTimer();
|
|
57
|
+
options.clearProjectPaneGitHubReviewRefreshTimer();
|
|
58
|
+
options.persistMuxUiStateNow();
|
|
59
|
+
options.clearConversationTitleEditTimer();
|
|
60
|
+
options.flushTaskComposerPersist();
|
|
61
|
+
options.clearRenderScheduled();
|
|
62
|
+
options.detachProcessListeners();
|
|
63
|
+
options.removeEnvelopeListener();
|
|
64
|
+
options.stopWorkspaceObservedEvents();
|
|
65
|
+
await options.unsubscribeTaskPlanningEvents();
|
|
66
|
+
await options.closeKeyEventSubscription();
|
|
67
|
+
options.clearRuntimeFatalExitTimer();
|
|
68
|
+
try {
|
|
69
|
+
await options.waitForControlPlaneDrain();
|
|
70
|
+
await options.controlPlaneClient.close();
|
|
71
|
+
} catch {
|
|
72
|
+
// Best-effort shutdown only.
|
|
78
73
|
}
|
|
74
|
+
|
|
75
|
+
options.eventPersistence.flush('shutdown');
|
|
76
|
+
const recordingCloseError = await options.recordingService.closeWriter();
|
|
77
|
+
options.store.close();
|
|
78
|
+
options.restoreTerminalState();
|
|
79
|
+
await options.recordingService.finalizeAfterShutdown(recordingCloseError);
|
|
80
|
+
options.startupShutdownService.finalize();
|
|
81
|
+
options.shutdownPerfCore();
|
|
79
82
|
}
|