@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
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import { buildFinderResults } from './finder.ts';
|
|
2
|
+
import { maxTopRowForModel } from './model.ts';
|
|
3
|
+
import type { DiffUiModel, DiffUiState, DiffUiStateAction, DiffUiViewMode } from './types.ts';
|
|
4
|
+
|
|
5
|
+
const AUTO_SPLIT_MIN_WIDTH = 120;
|
|
6
|
+
|
|
7
|
+
function clamp(value: number, min: number, max: number): number {
|
|
8
|
+
if (value < min) {
|
|
9
|
+
return min;
|
|
10
|
+
}
|
|
11
|
+
if (value > max) {
|
|
12
|
+
return max;
|
|
13
|
+
}
|
|
14
|
+
return value;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function clampIndex(value: number, length: number): number {
|
|
18
|
+
if (length <= 0) {
|
|
19
|
+
return 0;
|
|
20
|
+
}
|
|
21
|
+
return clamp(value, 0, length - 1);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function firstHunkIndexForFile(model: DiffUiModel, fileIndex: number): number {
|
|
25
|
+
const row = model.rows.find(
|
|
26
|
+
(candidate) => candidate.kind === 'hunk-header' && candidate.fileIndex === fileIndex,
|
|
27
|
+
);
|
|
28
|
+
return row?.hunkIndex ?? 0;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function resolveTopForFile(model: DiffUiModel, fileIndex: number): number {
|
|
32
|
+
if (model.fileStartRows.length === 0) {
|
|
33
|
+
return 0;
|
|
34
|
+
}
|
|
35
|
+
return model.fileStartRows[clampIndex(fileIndex, model.fileStartRows.length)] ?? 0;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function resolveTopForHunk(model: DiffUiModel, hunkIndex: number): number {
|
|
39
|
+
if (model.hunkStartRows.length === 0) {
|
|
40
|
+
return 0;
|
|
41
|
+
}
|
|
42
|
+
return model.hunkStartRows[clampIndex(hunkIndex, model.hunkStartRows.length)] ?? 0;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function resolveEffectiveViewMode(
|
|
46
|
+
viewMode: DiffUiViewMode,
|
|
47
|
+
viewportWidth: number,
|
|
48
|
+
): 'split' | 'unified' {
|
|
49
|
+
if (viewMode === 'split') {
|
|
50
|
+
return 'split';
|
|
51
|
+
}
|
|
52
|
+
if (viewMode === 'unified') {
|
|
53
|
+
return 'unified';
|
|
54
|
+
}
|
|
55
|
+
return viewportWidth >= AUTO_SPLIT_MIN_WIDTH ? 'split' : 'unified';
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function createInitialDiffUiState(
|
|
59
|
+
model: DiffUiModel,
|
|
60
|
+
viewMode: DiffUiViewMode,
|
|
61
|
+
viewportWidth: number,
|
|
62
|
+
): DiffUiState {
|
|
63
|
+
return {
|
|
64
|
+
viewMode,
|
|
65
|
+
effectiveViewMode: resolveEffectiveViewMode(viewMode, viewportWidth),
|
|
66
|
+
topRow: 0,
|
|
67
|
+
activeFileIndex: model.diff.files.length === 0 ? 0 : 0,
|
|
68
|
+
activeHunkIndex: model.hunkStartRows.length === 0 ? 0 : 0,
|
|
69
|
+
finderOpen: false,
|
|
70
|
+
finderQuery: '',
|
|
71
|
+
finderSelectedIndex: 0,
|
|
72
|
+
finderResults: buildFinderResults(model, ''),
|
|
73
|
+
searchQuery: '',
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function withClampedTop(
|
|
78
|
+
state: DiffUiState,
|
|
79
|
+
model: DiffUiModel,
|
|
80
|
+
viewportHeight: number,
|
|
81
|
+
): DiffUiState {
|
|
82
|
+
const maxTop = maxTopRowForModel(model, viewportHeight);
|
|
83
|
+
return {
|
|
84
|
+
...state,
|
|
85
|
+
topRow: clamp(state.topRow, 0, maxTop),
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export function reduceDiffUiState(input: {
|
|
90
|
+
readonly model: DiffUiModel;
|
|
91
|
+
readonly state: DiffUiState;
|
|
92
|
+
readonly action: DiffUiStateAction;
|
|
93
|
+
readonly viewportWidth: number;
|
|
94
|
+
readonly viewportHeight: number;
|
|
95
|
+
}): DiffUiState {
|
|
96
|
+
const { model, action, viewportHeight, viewportWidth } = input;
|
|
97
|
+
let next: DiffUiState = input.state;
|
|
98
|
+
|
|
99
|
+
if (action.type === 'viewport.changed') {
|
|
100
|
+
next = {
|
|
101
|
+
...next,
|
|
102
|
+
effectiveViewMode: resolveEffectiveViewMode(next.viewMode, action.width),
|
|
103
|
+
};
|
|
104
|
+
return withClampedTop(next, model, viewportHeight);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (action.type === 'view.setMode') {
|
|
108
|
+
next = {
|
|
109
|
+
...next,
|
|
110
|
+
viewMode: action.mode,
|
|
111
|
+
effectiveViewMode: resolveEffectiveViewMode(action.mode, viewportWidth),
|
|
112
|
+
};
|
|
113
|
+
return withClampedTop(next, model, viewportHeight);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (action.type === 'nav.scroll') {
|
|
117
|
+
next = {
|
|
118
|
+
...next,
|
|
119
|
+
topRow: next.topRow + action.delta,
|
|
120
|
+
};
|
|
121
|
+
return withClampedTop(next, model, viewportHeight);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (action.type === 'nav.page') {
|
|
125
|
+
next = {
|
|
126
|
+
...next,
|
|
127
|
+
topRow: next.topRow + action.delta * Math.max(1, action.pageSize),
|
|
128
|
+
};
|
|
129
|
+
return withClampedTop(next, model, viewportHeight);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (action.type === 'nav.gotoFile') {
|
|
133
|
+
const fileIndex = clampIndex(action.fileIndex, model.diff.files.length);
|
|
134
|
+
next = {
|
|
135
|
+
...next,
|
|
136
|
+
activeFileIndex: fileIndex,
|
|
137
|
+
activeHunkIndex: firstHunkIndexForFile(model, fileIndex),
|
|
138
|
+
topRow: resolveTopForFile(model, fileIndex),
|
|
139
|
+
finderOpen: false,
|
|
140
|
+
};
|
|
141
|
+
return withClampedTop(next, model, viewportHeight);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (action.type === 'nav.gotoHunk') {
|
|
145
|
+
const hunkIndex = clampIndex(action.hunkIndex, model.hunkStartRows.length);
|
|
146
|
+
const hunkRow = model.rows.find(
|
|
147
|
+
(row) => row.kind === 'hunk-header' && row.hunkIndex === hunkIndex,
|
|
148
|
+
);
|
|
149
|
+
next = {
|
|
150
|
+
...next,
|
|
151
|
+
activeHunkIndex: hunkIndex,
|
|
152
|
+
activeFileIndex: hunkRow?.fileIndex ?? next.activeFileIndex,
|
|
153
|
+
topRow: resolveTopForHunk(model, hunkIndex),
|
|
154
|
+
finderOpen: false,
|
|
155
|
+
};
|
|
156
|
+
return withClampedTop(next, model, viewportHeight);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if (action.type === 'finder.open') {
|
|
160
|
+
next = {
|
|
161
|
+
...next,
|
|
162
|
+
finderOpen: true,
|
|
163
|
+
finderResults: buildFinderResults(model, next.finderQuery),
|
|
164
|
+
finderSelectedIndex: 0,
|
|
165
|
+
};
|
|
166
|
+
return withClampedTop(next, model, viewportHeight);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (action.type === 'finder.close') {
|
|
170
|
+
next = {
|
|
171
|
+
...next,
|
|
172
|
+
finderOpen: false,
|
|
173
|
+
};
|
|
174
|
+
return withClampedTop(next, model, viewportHeight);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (action.type === 'finder.query') {
|
|
178
|
+
const results = buildFinderResults(model, action.query);
|
|
179
|
+
next = {
|
|
180
|
+
...next,
|
|
181
|
+
finderOpen: true,
|
|
182
|
+
finderQuery: action.query,
|
|
183
|
+
finderResults: results,
|
|
184
|
+
finderSelectedIndex: 0,
|
|
185
|
+
};
|
|
186
|
+
return withClampedTop(next, model, viewportHeight);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if (action.type === 'finder.move') {
|
|
190
|
+
const selected = clampIndex(next.finderSelectedIndex + action.delta, next.finderResults.length);
|
|
191
|
+
next = {
|
|
192
|
+
...next,
|
|
193
|
+
finderSelectedIndex: selected,
|
|
194
|
+
};
|
|
195
|
+
return withClampedTop(next, model, viewportHeight);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
if (action.type === 'finder.accept') {
|
|
199
|
+
if (next.finderResults.length === 0) {
|
|
200
|
+
return withClampedTop(next, model, viewportHeight);
|
|
201
|
+
}
|
|
202
|
+
const selection =
|
|
203
|
+
next.finderResults[clampIndex(next.finderSelectedIndex, next.finderResults.length)] ??
|
|
204
|
+
next.finderResults[0]!;
|
|
205
|
+
next = {
|
|
206
|
+
...next,
|
|
207
|
+
activeFileIndex: selection.fileIndex,
|
|
208
|
+
activeHunkIndex: firstHunkIndexForFile(model, selection.fileIndex),
|
|
209
|
+
topRow: resolveTopForFile(model, selection.fileIndex),
|
|
210
|
+
finderOpen: false,
|
|
211
|
+
};
|
|
212
|
+
return withClampedTop(next, model, viewportHeight);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
if (action.type === 'search.set') {
|
|
216
|
+
next = {
|
|
217
|
+
...next,
|
|
218
|
+
searchQuery: action.query,
|
|
219
|
+
};
|
|
220
|
+
return withClampedTop(next, model, viewportHeight);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
return withClampedTop(next, model, viewportHeight);
|
|
224
|
+
}
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
import type { DiffCoverageReason, DiffMode, NormalizedDiff } from '../diff/types.ts';
|
|
2
|
+
|
|
3
|
+
export type DiffUiViewMode = 'auto' | 'split' | 'unified';
|
|
4
|
+
type DiffUiEffectiveViewMode = 'split' | 'unified';
|
|
5
|
+
export type DiffUiSyntaxMode = 'auto' | 'on' | 'off';
|
|
6
|
+
export type DiffUiWordDiffMode = 'auto' | 'on' | 'off';
|
|
7
|
+
|
|
8
|
+
interface DiffUiBudget {
|
|
9
|
+
readonly maxFiles: number;
|
|
10
|
+
readonly maxHunks: number;
|
|
11
|
+
readonly maxLines: number;
|
|
12
|
+
readonly maxBytes: number;
|
|
13
|
+
readonly maxRuntimeMs: number;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface DiffUiCliOptions {
|
|
17
|
+
readonly cwd: string;
|
|
18
|
+
readonly mode: DiffMode;
|
|
19
|
+
readonly baseRef: string | null;
|
|
20
|
+
readonly headRef: string | null;
|
|
21
|
+
readonly includeGenerated: boolean;
|
|
22
|
+
readonly includeBinary: boolean;
|
|
23
|
+
readonly noRenames: boolean;
|
|
24
|
+
readonly renameLimit: number | null;
|
|
25
|
+
readonly viewMode: DiffUiViewMode;
|
|
26
|
+
readonly syntaxMode: DiffUiSyntaxMode;
|
|
27
|
+
readonly wordDiffMode: DiffUiWordDiffMode;
|
|
28
|
+
readonly color: boolean;
|
|
29
|
+
readonly pager: boolean;
|
|
30
|
+
readonly watch: boolean;
|
|
31
|
+
readonly jsonEvents: boolean;
|
|
32
|
+
readonly rpcStdio: boolean;
|
|
33
|
+
readonly snapshot: boolean;
|
|
34
|
+
readonly width: number | null;
|
|
35
|
+
readonly height: number | null;
|
|
36
|
+
readonly theme: string | null;
|
|
37
|
+
readonly budget: DiffUiBudget;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export type DiffUiRowKind =
|
|
41
|
+
| 'file-header'
|
|
42
|
+
| 'hunk-header'
|
|
43
|
+
| 'code-context'
|
|
44
|
+
| 'code-add'
|
|
45
|
+
| 'code-del'
|
|
46
|
+
| 'notice';
|
|
47
|
+
|
|
48
|
+
export interface DiffUiVirtualRow {
|
|
49
|
+
readonly kind: DiffUiRowKind;
|
|
50
|
+
readonly unified: string;
|
|
51
|
+
readonly left: string;
|
|
52
|
+
readonly right: string;
|
|
53
|
+
readonly fileId: string | null;
|
|
54
|
+
readonly hunkId: string | null;
|
|
55
|
+
readonly fileIndex: number | null;
|
|
56
|
+
readonly hunkIndex: number | null;
|
|
57
|
+
readonly language: string | null;
|
|
58
|
+
readonly oldLine: number | null;
|
|
59
|
+
readonly newLine: number | null;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export interface DiffUiModel {
|
|
63
|
+
readonly diff: NormalizedDiff;
|
|
64
|
+
readonly rows: readonly DiffUiVirtualRow[];
|
|
65
|
+
readonly fileStartRows: readonly number[];
|
|
66
|
+
readonly hunkStartRows: readonly number[];
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export interface DiffUiFinderResult {
|
|
70
|
+
readonly fileIndex: number;
|
|
71
|
+
readonly fileId: string;
|
|
72
|
+
readonly path: string;
|
|
73
|
+
readonly score: number;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export interface DiffUiState {
|
|
77
|
+
readonly viewMode: DiffUiViewMode;
|
|
78
|
+
readonly effectiveViewMode: DiffUiEffectiveViewMode;
|
|
79
|
+
readonly topRow: number;
|
|
80
|
+
readonly activeFileIndex: number;
|
|
81
|
+
readonly activeHunkIndex: number;
|
|
82
|
+
readonly finderOpen: boolean;
|
|
83
|
+
readonly finderQuery: string;
|
|
84
|
+
readonly finderSelectedIndex: number;
|
|
85
|
+
readonly finderResults: readonly DiffUiFinderResult[];
|
|
86
|
+
readonly searchQuery: string;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export type DiffUiStateAction =
|
|
90
|
+
| {
|
|
91
|
+
readonly type: 'viewport.changed';
|
|
92
|
+
readonly width: number;
|
|
93
|
+
}
|
|
94
|
+
| {
|
|
95
|
+
readonly type: 'view.setMode';
|
|
96
|
+
readonly mode: DiffUiViewMode;
|
|
97
|
+
}
|
|
98
|
+
| {
|
|
99
|
+
readonly type: 'nav.scroll';
|
|
100
|
+
readonly delta: number;
|
|
101
|
+
}
|
|
102
|
+
| {
|
|
103
|
+
readonly type: 'nav.page';
|
|
104
|
+
readonly delta: number;
|
|
105
|
+
readonly pageSize: number;
|
|
106
|
+
}
|
|
107
|
+
| {
|
|
108
|
+
readonly type: 'nav.gotoFile';
|
|
109
|
+
readonly fileIndex: number;
|
|
110
|
+
}
|
|
111
|
+
| {
|
|
112
|
+
readonly type: 'nav.gotoHunk';
|
|
113
|
+
readonly hunkIndex: number;
|
|
114
|
+
}
|
|
115
|
+
| {
|
|
116
|
+
readonly type: 'finder.open';
|
|
117
|
+
}
|
|
118
|
+
| {
|
|
119
|
+
readonly type: 'finder.close';
|
|
120
|
+
}
|
|
121
|
+
| {
|
|
122
|
+
readonly type: 'finder.query';
|
|
123
|
+
readonly query: string;
|
|
124
|
+
}
|
|
125
|
+
| {
|
|
126
|
+
readonly type: 'finder.move';
|
|
127
|
+
readonly delta: number;
|
|
128
|
+
}
|
|
129
|
+
| {
|
|
130
|
+
readonly type: 'finder.accept';
|
|
131
|
+
}
|
|
132
|
+
| {
|
|
133
|
+
readonly type: 'search.set';
|
|
134
|
+
readonly query: string;
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
export type DiffUiCommand =
|
|
138
|
+
| {
|
|
139
|
+
readonly type: 'view.setMode';
|
|
140
|
+
readonly mode: DiffUiViewMode;
|
|
141
|
+
}
|
|
142
|
+
| {
|
|
143
|
+
readonly type: 'nav.scroll';
|
|
144
|
+
readonly delta: number;
|
|
145
|
+
}
|
|
146
|
+
| {
|
|
147
|
+
readonly type: 'nav.page';
|
|
148
|
+
readonly delta: number;
|
|
149
|
+
}
|
|
150
|
+
| {
|
|
151
|
+
readonly type: 'nav.gotoFile';
|
|
152
|
+
readonly index: number;
|
|
153
|
+
}
|
|
154
|
+
| {
|
|
155
|
+
readonly type: 'nav.gotoHunk';
|
|
156
|
+
readonly index: number;
|
|
157
|
+
}
|
|
158
|
+
| {
|
|
159
|
+
readonly type: 'finder.open';
|
|
160
|
+
}
|
|
161
|
+
| {
|
|
162
|
+
readonly type: 'finder.close';
|
|
163
|
+
}
|
|
164
|
+
| {
|
|
165
|
+
readonly type: 'finder.query';
|
|
166
|
+
readonly query: string;
|
|
167
|
+
}
|
|
168
|
+
| {
|
|
169
|
+
readonly type: 'finder.move';
|
|
170
|
+
readonly delta: number;
|
|
171
|
+
}
|
|
172
|
+
| {
|
|
173
|
+
readonly type: 'finder.accept';
|
|
174
|
+
}
|
|
175
|
+
| {
|
|
176
|
+
readonly type: 'search.set';
|
|
177
|
+
readonly query: string;
|
|
178
|
+
}
|
|
179
|
+
| {
|
|
180
|
+
readonly type: 'session.quit';
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
export type DiffUiEvent =
|
|
184
|
+
| {
|
|
185
|
+
readonly type: 'diff.loaded';
|
|
186
|
+
readonly files: number;
|
|
187
|
+
readonly hunks: number;
|
|
188
|
+
readonly lines: number;
|
|
189
|
+
readonly coverageReason: DiffCoverageReason;
|
|
190
|
+
}
|
|
191
|
+
| {
|
|
192
|
+
readonly type: 'state.changed';
|
|
193
|
+
readonly state: DiffUiState;
|
|
194
|
+
}
|
|
195
|
+
| {
|
|
196
|
+
readonly type: 'render.completed';
|
|
197
|
+
readonly rows: number;
|
|
198
|
+
readonly width: number;
|
|
199
|
+
readonly height: number;
|
|
200
|
+
readonly view: DiffUiEffectiveViewMode;
|
|
201
|
+
}
|
|
202
|
+
| {
|
|
203
|
+
readonly type: 'warning';
|
|
204
|
+
readonly message: string;
|
|
205
|
+
}
|
|
206
|
+
| {
|
|
207
|
+
readonly type: 'session.quit';
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
export interface DiffUiRenderTheme {
|
|
211
|
+
readonly headerAnsi: string;
|
|
212
|
+
readonly footerAnsi: string;
|
|
213
|
+
readonly fileHeaderAnsi: string;
|
|
214
|
+
readonly hunkHeaderAnsi: string;
|
|
215
|
+
readonly contextAnsi: string;
|
|
216
|
+
readonly addAnsi: string;
|
|
217
|
+
readonly delAnsi: string;
|
|
218
|
+
readonly noticeAnsi: string;
|
|
219
|
+
readonly gutterAnsi: string;
|
|
220
|
+
readonly resetAnsi: string;
|
|
221
|
+
readonly syntaxKeywordAnsi: string;
|
|
222
|
+
readonly syntaxStringAnsi: string;
|
|
223
|
+
readonly syntaxCommentAnsi: string;
|
|
224
|
+
readonly syntaxNumberAnsi: string;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export interface DiffUiRenderOutput {
|
|
228
|
+
readonly lines: readonly string[];
|
|
229
|
+
readonly state: DiffUiState;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
export interface DiffUiRunOutput {
|
|
233
|
+
readonly exitCode: number;
|
|
234
|
+
readonly events: readonly DiffUiEvent[];
|
|
235
|
+
readonly renderedLines: readonly string[];
|
|
236
|
+
}
|
|
@@ -290,6 +290,8 @@ export class ConversationManager {
|
|
|
290
290
|
|
|
291
291
|
upsertFromPersistedRecord(input: UpsertPersistedConversationInput): ConversationState {
|
|
292
292
|
const { record } = input;
|
|
293
|
+
const existing = this.conversationsBySessionId.get(record.conversationId);
|
|
294
|
+
const preserveLiveRuntime = existing?.live === true;
|
|
293
295
|
const conversation = input.ensureConversation(record.conversationId, {
|
|
294
296
|
directoryId: record.directoryId,
|
|
295
297
|
title: record.title,
|
|
@@ -299,14 +301,16 @@ export class ConversationManager {
|
|
|
299
301
|
conversation.scope.tenantId = record.tenantId;
|
|
300
302
|
conversation.scope.userId = record.userId;
|
|
301
303
|
conversation.scope.workspaceId = record.workspaceId;
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
304
|
+
if (!preserveLiveRuntime) {
|
|
305
|
+
const runtimeStatusModel = record.runtimeStatusModel;
|
|
306
|
+
conversation.status = record.runtimeStatus;
|
|
307
|
+
conversation.statusModel = runtimeStatusModel;
|
|
308
|
+
conversation.attentionReason = runtimeStatusModel?.attentionReason ?? null;
|
|
309
|
+
conversation.lastKnownWork = runtimeStatusModel?.lastKnownWork ?? null;
|
|
310
|
+
conversation.lastKnownWorkAt = runtimeStatusModel?.lastKnownWorkAt ?? null;
|
|
311
|
+
}
|
|
308
312
|
// Persisted runtime flags are advisory; session.list is authoritative for live sessions.
|
|
309
|
-
conversation.live = false;
|
|
313
|
+
conversation.live = preserveLiveRuntime ? true : false;
|
|
310
314
|
return conversation;
|
|
311
315
|
}
|
|
312
316
|
|
package/src/domain/workspace.ts
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import type { ProjectPaneSnapshot } from '../mux/harness-core-ui.ts';
|
|
2
2
|
import type { CommandMenuState } from '../mux/live-mux/command-menu.ts';
|
|
3
3
|
import type { LeftNavSelection } from '../mux/live-mux/left-nav.ts';
|
|
4
|
+
import type { LinePromptInputState } from '../mux/live-mux/modal-input-reducers.ts';
|
|
4
5
|
import type { PaneSelection, PaneSelectionDrag } from '../mux/live-mux/selection.ts';
|
|
5
6
|
import type { createNewThreadPromptState } from '../mux/new-thread-prompt.ts';
|
|
6
7
|
import type { TaskComposerBuffer } from '../mux/task-composer.ts';
|
|
7
8
|
import type { TaskFocusedPaneView } from '../mux/task-focused-pane.ts';
|
|
8
9
|
import type { buildWorkspaceRailViewRows } from '../mux/workspace-rail-model.ts';
|
|
9
10
|
|
|
10
|
-
type MainPaneMode = 'conversation' | 'project' | 'home';
|
|
11
|
+
type MainPaneMode = 'conversation' | 'project' | 'home' | 'nim';
|
|
11
12
|
|
|
12
13
|
export interface ConversationTitleEditState {
|
|
13
14
|
conversationId: string;
|
|
@@ -25,11 +26,20 @@ export interface RepositoryPromptState {
|
|
|
25
26
|
readonly error: string | null;
|
|
26
27
|
}
|
|
27
28
|
|
|
29
|
+
interface ApiKeyPromptState {
|
|
30
|
+
readonly keyName: string;
|
|
31
|
+
readonly displayName: string;
|
|
32
|
+
readonly value: string;
|
|
33
|
+
readonly error: string | null;
|
|
34
|
+
readonly hasExistingValue: boolean;
|
|
35
|
+
readonly lineInputState?: LinePromptInputState;
|
|
36
|
+
}
|
|
37
|
+
|
|
28
38
|
export interface TaskEditorPromptState {
|
|
29
39
|
mode: 'create' | 'edit';
|
|
30
40
|
taskId: string | null;
|
|
31
41
|
title: string;
|
|
32
|
-
|
|
42
|
+
body: string;
|
|
33
43
|
repositoryIds: readonly string[];
|
|
34
44
|
repositoryIndex: number;
|
|
35
45
|
fieldIndex: 0 | 1 | 2;
|
|
@@ -52,7 +62,8 @@ interface WorkspaceModelInit {
|
|
|
52
62
|
latestTaskPaneView: TaskFocusedPaneView;
|
|
53
63
|
taskDraftComposer: TaskComposerBuffer;
|
|
54
64
|
repositoriesCollapsed: boolean;
|
|
55
|
-
shortcutsCollapsed
|
|
65
|
+
shortcutsCollapsed?: boolean;
|
|
66
|
+
showDebugBar?: boolean;
|
|
56
67
|
}
|
|
57
68
|
|
|
58
69
|
export class WorkspaceModel {
|
|
@@ -80,6 +91,7 @@ export class WorkspaceModel {
|
|
|
80
91
|
selectionDrag: PaneSelectionDrag | null = null;
|
|
81
92
|
selectionPinnedFollowOutput: boolean | null = null;
|
|
82
93
|
repositoryPrompt: RepositoryPromptState | null = null;
|
|
94
|
+
apiKeyPrompt: ApiKeyPromptState | null = null;
|
|
83
95
|
commandMenu: CommandMenuState | null = null;
|
|
84
96
|
newThreadPrompt: ReturnType<typeof createNewThreadPromptState> | null = null;
|
|
85
97
|
addDirectoryPrompt: { value: string; error: string | null } | null = null;
|
|
@@ -89,9 +101,12 @@ export class WorkspaceModel {
|
|
|
89
101
|
paneDividerDragActive = false;
|
|
90
102
|
previousSelectionRows: readonly number[] = [];
|
|
91
103
|
latestRailViewRows: ReturnType<typeof buildWorkspaceRailViewRows> = [];
|
|
104
|
+
visibleGitHubDirectoryIds = new Set<string>();
|
|
105
|
+
expandedGitHubDirectoryIds = new Set<string>();
|
|
92
106
|
|
|
93
107
|
repositoriesCollapsed: boolean;
|
|
94
108
|
shortcutsCollapsed: boolean;
|
|
109
|
+
showDebugBar: boolean;
|
|
95
110
|
|
|
96
111
|
constructor(init: WorkspaceModelInit) {
|
|
97
112
|
this.activeDirectoryId = init.activeDirectoryId;
|
|
@@ -99,7 +114,8 @@ export class WorkspaceModel {
|
|
|
99
114
|
this.latestTaskPaneView = init.latestTaskPaneView;
|
|
100
115
|
this.taskDraftComposer = init.taskDraftComposer;
|
|
101
116
|
this.repositoriesCollapsed = init.repositoriesCollapsed;
|
|
102
|
-
this.shortcutsCollapsed = init.shortcutsCollapsed;
|
|
117
|
+
this.shortcutsCollapsed = init.shortcutsCollapsed ?? false;
|
|
118
|
+
this.showDebugBar = init.showDebugBar ?? false;
|
|
103
119
|
}
|
|
104
120
|
|
|
105
121
|
selectLeftNavHome(): void {
|
|
@@ -108,6 +124,18 @@ export class WorkspaceModel {
|
|
|
108
124
|
};
|
|
109
125
|
}
|
|
110
126
|
|
|
127
|
+
selectLeftNavNim(): void {
|
|
128
|
+
this.leftNavSelection = {
|
|
129
|
+
kind: 'nim',
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
selectLeftNavTasks(): void {
|
|
134
|
+
this.leftNavSelection = {
|
|
135
|
+
kind: 'tasks',
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
|
|
111
139
|
selectLeftNavRepository(repositoryGroupId: string): void {
|
|
112
140
|
this.activeRepositorySelectionId = repositoryGroupId;
|
|
113
141
|
this.leftNavSelection = {
|
|
@@ -124,6 +152,14 @@ export class WorkspaceModel {
|
|
|
124
152
|
};
|
|
125
153
|
}
|
|
126
154
|
|
|
155
|
+
selectLeftNavGitHub(directoryId: string, repositoryGroupId: string): void {
|
|
156
|
+
this.activeRepositorySelectionId = repositoryGroupId;
|
|
157
|
+
this.leftNavSelection = {
|
|
158
|
+
kind: 'github',
|
|
159
|
+
directoryId,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
|
|
127
163
|
selectLeftNavConversation(sessionId: string): void {
|
|
128
164
|
this.leftNavSelection = {
|
|
129
165
|
kind: 'conversation',
|
|
@@ -141,6 +177,16 @@ export class WorkspaceModel {
|
|
|
141
177
|
this.projectPaneScrollTop = 0;
|
|
142
178
|
}
|
|
143
179
|
|
|
180
|
+
enterGitHubPane(directoryId: string, repositoryGroupId: string): void {
|
|
181
|
+
this.activeDirectoryId = directoryId;
|
|
182
|
+
this.selectLeftNavGitHub(directoryId, repositoryGroupId);
|
|
183
|
+
this.mainPaneMode = 'project';
|
|
184
|
+
this.homePaneDragState = null;
|
|
185
|
+
this.taskPaneTaskEditClickState = null;
|
|
186
|
+
this.taskPaneRepositoryEditClickState = null;
|
|
187
|
+
this.projectPaneScrollTop = 0;
|
|
188
|
+
}
|
|
189
|
+
|
|
144
190
|
enterHomePane(): void {
|
|
145
191
|
this.mainPaneMode = 'home';
|
|
146
192
|
this.selectLeftNavHome();
|
|
@@ -153,4 +199,30 @@ export class WorkspaceModel {
|
|
|
153
199
|
this.taskPaneRepositoryEditClickState = null;
|
|
154
200
|
this.homePaneDragState = null;
|
|
155
201
|
}
|
|
202
|
+
|
|
203
|
+
enterNimPane(): void {
|
|
204
|
+
this.mainPaneMode = 'nim';
|
|
205
|
+
this.selectLeftNavNim();
|
|
206
|
+
this.projectPaneSnapshot = null;
|
|
207
|
+
this.projectPaneScrollTop = 0;
|
|
208
|
+
this.taskPaneScrollTop = 0;
|
|
209
|
+
this.taskPaneNotice = null;
|
|
210
|
+
this.taskRepositoryDropdownOpen = false;
|
|
211
|
+
this.taskPaneTaskEditClickState = null;
|
|
212
|
+
this.taskPaneRepositoryEditClickState = null;
|
|
213
|
+
this.homePaneDragState = null;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
enterTasksPane(): void {
|
|
217
|
+
this.mainPaneMode = 'home';
|
|
218
|
+
this.selectLeftNavTasks();
|
|
219
|
+
this.projectPaneSnapshot = null;
|
|
220
|
+
this.projectPaneScrollTop = 0;
|
|
221
|
+
this.taskPaneScrollTop = 0;
|
|
222
|
+
this.taskPaneNotice = null;
|
|
223
|
+
this.taskRepositoryDropdownOpen = false;
|
|
224
|
+
this.taskPaneTaskEditClickState = null;
|
|
225
|
+
this.taskPaneRepositoryEditClickState = null;
|
|
226
|
+
this.homePaneDragState = null;
|
|
227
|
+
}
|
|
156
228
|
}
|