@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
|
@@ -17,17 +17,12 @@ import type {
|
|
|
17
17
|
ControlPlaneProjectTaskFocusMode,
|
|
18
18
|
ControlPlaneProjectThreadSpawnMode,
|
|
19
19
|
ControlPlaneRepositoryRecord,
|
|
20
|
-
ControlPlaneTaskLinearPriority,
|
|
21
|
-
ControlPlaneTaskLinearRecord,
|
|
22
20
|
ControlPlaneTaskRecord,
|
|
23
21
|
ControlPlaneTaskScopeKind,
|
|
24
22
|
ControlPlaneTaskStatus,
|
|
25
23
|
ControlPlaneTelemetryRecord,
|
|
26
|
-
TaskLinearInput,
|
|
27
24
|
} from './control-plane-store-types.ts';
|
|
28
25
|
|
|
29
|
-
const DATE_ONLY_PATTERN = /^\d{4}-\d{2}-\d{2}$/;
|
|
30
|
-
|
|
31
26
|
export function asRecord(value: unknown): Record<string, unknown> {
|
|
32
27
|
if (typeof value !== 'object' || value === null) {
|
|
33
28
|
throw new Error('expected object row');
|
|
@@ -151,16 +146,8 @@ function normalizeRuntimeStatusModel(value: unknown): StreamSessionStatusModel |
|
|
|
151
146
|
const attentionReason = asStringOrNull(model.attentionReason, 'attentionReason');
|
|
152
147
|
const lastKnownWork = asStringOrNull(model.lastKnownWork, 'lastKnownWork');
|
|
153
148
|
const lastKnownWorkAt = asStringOrNull(model.lastKnownWorkAt, 'lastKnownWorkAt');
|
|
154
|
-
const
|
|
149
|
+
const activityHintRaw = normalizeLegacyActivityHint(model.activityHint);
|
|
155
150
|
const observedAt = asString(model.observedAt, 'observedAt');
|
|
156
|
-
if (
|
|
157
|
-
phaseHintRaw !== null &&
|
|
158
|
-
phaseHintRaw !== 'needs-action' &&
|
|
159
|
-
phaseHintRaw !== 'working' &&
|
|
160
|
-
phaseHintRaw !== 'idle'
|
|
161
|
-
) {
|
|
162
|
-
throw new Error('expected phaseHint enum value');
|
|
163
|
-
}
|
|
164
151
|
return {
|
|
165
152
|
runtimeStatus: runtimeStatusRaw,
|
|
166
153
|
phase: phaseRaw,
|
|
@@ -170,11 +157,40 @@ function normalizeRuntimeStatusModel(value: unknown): StreamSessionStatusModel |
|
|
|
170
157
|
attentionReason,
|
|
171
158
|
lastKnownWork,
|
|
172
159
|
lastKnownWorkAt,
|
|
173
|
-
|
|
160
|
+
activityHint: activityHintRaw,
|
|
174
161
|
observedAt,
|
|
175
162
|
};
|
|
176
163
|
}
|
|
177
164
|
|
|
165
|
+
function normalizeLegacyActivityHint(value: unknown): StreamSessionStatusModel['activityHint'] {
|
|
166
|
+
if (value === undefined || value === null) {
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
if (typeof value === 'string') {
|
|
170
|
+
if (value === 'needs-action' || value === 'working' || value === 'idle') {
|
|
171
|
+
return value;
|
|
172
|
+
}
|
|
173
|
+
throw new Error('expected activityHint enum value');
|
|
174
|
+
}
|
|
175
|
+
if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
|
|
176
|
+
const legacy = value as Record<string, unknown>;
|
|
177
|
+
const legacyCandidate =
|
|
178
|
+
typeof legacy.kind === 'string'
|
|
179
|
+
? legacy.kind
|
|
180
|
+
: typeof legacy.value === 'string'
|
|
181
|
+
? legacy.value
|
|
182
|
+
: null;
|
|
183
|
+
if (
|
|
184
|
+
legacyCandidate === 'needs-action' ||
|
|
185
|
+
legacyCandidate === 'working' ||
|
|
186
|
+
legacyCandidate === 'idle'
|
|
187
|
+
) {
|
|
188
|
+
return legacyCandidate;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
return null;
|
|
192
|
+
}
|
|
193
|
+
|
|
178
194
|
export function normalizeStoredDirectoryRow(value: unknown): ControlPlaneDirectoryRecord {
|
|
179
195
|
const row = asRecord(value);
|
|
180
196
|
return {
|
|
@@ -287,231 +303,6 @@ function normalizeRepositoryMetadata(value: unknown): Record<string, unknown> {
|
|
|
287
303
|
}
|
|
288
304
|
}
|
|
289
305
|
|
|
290
|
-
export function defaultTaskLinearRecord(): ControlPlaneTaskLinearRecord {
|
|
291
|
-
return {
|
|
292
|
-
issueId: null,
|
|
293
|
-
identifier: null,
|
|
294
|
-
url: null,
|
|
295
|
-
teamId: null,
|
|
296
|
-
projectId: null,
|
|
297
|
-
projectMilestoneId: null,
|
|
298
|
-
cycleId: null,
|
|
299
|
-
stateId: null,
|
|
300
|
-
assigneeId: null,
|
|
301
|
-
priority: null,
|
|
302
|
-
estimate: null,
|
|
303
|
-
dueDate: null,
|
|
304
|
-
labelIds: [],
|
|
305
|
-
};
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
function normalizeOptionalTaskLinearString(value: string | null, field: string): string | null {
|
|
309
|
-
if (value === null) {
|
|
310
|
-
return null;
|
|
311
|
-
}
|
|
312
|
-
return normalizeNonEmptyLabel(value, field);
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
function normalizeTaskLinearPriority(
|
|
316
|
-
value: number | null,
|
|
317
|
-
field: string,
|
|
318
|
-
): ControlPlaneTaskLinearPriority | null {
|
|
319
|
-
if (value === null) {
|
|
320
|
-
return null;
|
|
321
|
-
}
|
|
322
|
-
if (!Number.isInteger(value) || value < 0 || value > 4) {
|
|
323
|
-
throw new Error(`expected integer [0..4] for ${field}`);
|
|
324
|
-
}
|
|
325
|
-
return value as ControlPlaneTaskLinearPriority;
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
function normalizeTaskLinearEstimate(value: number | null, field: string): number | null {
|
|
329
|
-
if (value === null) {
|
|
330
|
-
return null;
|
|
331
|
-
}
|
|
332
|
-
if (!Number.isInteger(value) || value < 0) {
|
|
333
|
-
throw new Error(`expected non-negative integer for ${field}`);
|
|
334
|
-
}
|
|
335
|
-
return value;
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
function normalizeTaskLinearDueDate(value: string | null, field: string): string | null {
|
|
339
|
-
if (value === null) {
|
|
340
|
-
return null;
|
|
341
|
-
}
|
|
342
|
-
const normalized = value.trim();
|
|
343
|
-
if (!DATE_ONLY_PATTERN.test(normalized)) {
|
|
344
|
-
throw new Error(`expected YYYY-MM-DD for ${field}`);
|
|
345
|
-
}
|
|
346
|
-
return normalized;
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
function normalizeTaskLinearLabelIds(
|
|
350
|
-
value: readonly string[] | null,
|
|
351
|
-
field: string,
|
|
352
|
-
): readonly string[] {
|
|
353
|
-
if (value === null) {
|
|
354
|
-
return [];
|
|
355
|
-
}
|
|
356
|
-
return uniqueValues(
|
|
357
|
-
value.map((entry, idx) => normalizeNonEmptyLabel(entry, `${field}[${String(idx)}]`)),
|
|
358
|
-
);
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
function parseTaskLinearInputRecord(
|
|
362
|
-
record: Record<string, unknown>,
|
|
363
|
-
field: string,
|
|
364
|
-
): TaskLinearInput {
|
|
365
|
-
const parsed: TaskLinearInput = {};
|
|
366
|
-
if ('issueId' in record) {
|
|
367
|
-
parsed.issueId = asStringOrNull(record.issueId, `${field}.issueId`);
|
|
368
|
-
}
|
|
369
|
-
if ('identifier' in record) {
|
|
370
|
-
parsed.identifier = asStringOrNull(record.identifier, `${field}.identifier`);
|
|
371
|
-
}
|
|
372
|
-
if ('url' in record) {
|
|
373
|
-
parsed.url = asStringOrNull(record.url, `${field}.url`);
|
|
374
|
-
}
|
|
375
|
-
if ('teamId' in record) {
|
|
376
|
-
parsed.teamId = asStringOrNull(record.teamId, `${field}.teamId`);
|
|
377
|
-
}
|
|
378
|
-
if ('projectId' in record) {
|
|
379
|
-
parsed.projectId = asStringOrNull(record.projectId, `${field}.projectId`);
|
|
380
|
-
}
|
|
381
|
-
if ('projectMilestoneId' in record) {
|
|
382
|
-
parsed.projectMilestoneId = asStringOrNull(
|
|
383
|
-
record.projectMilestoneId,
|
|
384
|
-
`${field}.projectMilestoneId`,
|
|
385
|
-
);
|
|
386
|
-
}
|
|
387
|
-
if ('cycleId' in record) {
|
|
388
|
-
parsed.cycleId = asStringOrNull(record.cycleId, `${field}.cycleId`);
|
|
389
|
-
}
|
|
390
|
-
if ('stateId' in record) {
|
|
391
|
-
parsed.stateId = asStringOrNull(record.stateId, `${field}.stateId`);
|
|
392
|
-
}
|
|
393
|
-
if ('assigneeId' in record) {
|
|
394
|
-
parsed.assigneeId = asStringOrNull(record.assigneeId, `${field}.assigneeId`);
|
|
395
|
-
}
|
|
396
|
-
if ('priority' in record) {
|
|
397
|
-
parsed.priority = asNumberOrNull(record.priority, `${field}.priority`);
|
|
398
|
-
}
|
|
399
|
-
if ('estimate' in record) {
|
|
400
|
-
parsed.estimate = asNumberOrNull(record.estimate, `${field}.estimate`);
|
|
401
|
-
}
|
|
402
|
-
if ('dueDate' in record) {
|
|
403
|
-
parsed.dueDate = asStringOrNull(record.dueDate, `${field}.dueDate`);
|
|
404
|
-
}
|
|
405
|
-
if ('labelIds' in record) {
|
|
406
|
-
const raw = record.labelIds;
|
|
407
|
-
if (raw === null) {
|
|
408
|
-
parsed.labelIds = null;
|
|
409
|
-
} else if (Array.isArray(raw) && raw.every((entry) => typeof entry === 'string')) {
|
|
410
|
-
parsed.labelIds = raw;
|
|
411
|
-
} else {
|
|
412
|
-
throw new Error(`expected string array or null for ${field}.labelIds`);
|
|
413
|
-
}
|
|
414
|
-
}
|
|
415
|
-
return parsed;
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
export function applyTaskLinearInput(
|
|
419
|
-
base: ControlPlaneTaskLinearRecord,
|
|
420
|
-
input: TaskLinearInput,
|
|
421
|
-
): ControlPlaneTaskLinearRecord {
|
|
422
|
-
return {
|
|
423
|
-
issueId:
|
|
424
|
-
input.issueId === undefined
|
|
425
|
-
? base.issueId
|
|
426
|
-
: normalizeOptionalTaskLinearString(input.issueId, 'linear.issueId'),
|
|
427
|
-
identifier:
|
|
428
|
-
input.identifier === undefined
|
|
429
|
-
? base.identifier
|
|
430
|
-
: normalizeOptionalTaskLinearString(input.identifier, 'linear.identifier'),
|
|
431
|
-
url:
|
|
432
|
-
input.url === undefined
|
|
433
|
-
? base.url
|
|
434
|
-
: normalizeOptionalTaskLinearString(input.url, 'linear.url'),
|
|
435
|
-
teamId:
|
|
436
|
-
input.teamId === undefined
|
|
437
|
-
? base.teamId
|
|
438
|
-
: normalizeOptionalTaskLinearString(input.teamId, 'linear.teamId'),
|
|
439
|
-
projectId:
|
|
440
|
-
input.projectId === undefined
|
|
441
|
-
? base.projectId
|
|
442
|
-
: normalizeOptionalTaskLinearString(input.projectId, 'linear.projectId'),
|
|
443
|
-
projectMilestoneId:
|
|
444
|
-
input.projectMilestoneId === undefined
|
|
445
|
-
? base.projectMilestoneId
|
|
446
|
-
: normalizeOptionalTaskLinearString(input.projectMilestoneId, 'linear.projectMilestoneId'),
|
|
447
|
-
cycleId:
|
|
448
|
-
input.cycleId === undefined
|
|
449
|
-
? base.cycleId
|
|
450
|
-
: normalizeOptionalTaskLinearString(input.cycleId, 'linear.cycleId'),
|
|
451
|
-
stateId:
|
|
452
|
-
input.stateId === undefined
|
|
453
|
-
? base.stateId
|
|
454
|
-
: normalizeOptionalTaskLinearString(input.stateId, 'linear.stateId'),
|
|
455
|
-
assigneeId:
|
|
456
|
-
input.assigneeId === undefined
|
|
457
|
-
? base.assigneeId
|
|
458
|
-
: normalizeOptionalTaskLinearString(input.assigneeId, 'linear.assigneeId'),
|
|
459
|
-
priority:
|
|
460
|
-
input.priority === undefined
|
|
461
|
-
? base.priority
|
|
462
|
-
: normalizeTaskLinearPriority(input.priority, 'linear.priority'),
|
|
463
|
-
estimate:
|
|
464
|
-
input.estimate === undefined
|
|
465
|
-
? base.estimate
|
|
466
|
-
: normalizeTaskLinearEstimate(input.estimate, 'linear.estimate'),
|
|
467
|
-
dueDate:
|
|
468
|
-
input.dueDate === undefined
|
|
469
|
-
? base.dueDate
|
|
470
|
-
: normalizeTaskLinearDueDate(input.dueDate, 'linear.dueDate'),
|
|
471
|
-
labelIds:
|
|
472
|
-
input.labelIds === undefined
|
|
473
|
-
? base.labelIds
|
|
474
|
-
: normalizeTaskLinearLabelIds(input.labelIds, 'linear.labelIds'),
|
|
475
|
-
};
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
export function serializeTaskLinear(linear: ControlPlaneTaskLinearRecord): string {
|
|
479
|
-
return JSON.stringify({
|
|
480
|
-
issueId: linear.issueId,
|
|
481
|
-
identifier: linear.identifier,
|
|
482
|
-
url: linear.url,
|
|
483
|
-
teamId: linear.teamId,
|
|
484
|
-
projectId: linear.projectId,
|
|
485
|
-
projectMilestoneId: linear.projectMilestoneId,
|
|
486
|
-
cycleId: linear.cycleId,
|
|
487
|
-
stateId: linear.stateId,
|
|
488
|
-
assigneeId: linear.assigneeId,
|
|
489
|
-
priority: linear.priority,
|
|
490
|
-
estimate: linear.estimate,
|
|
491
|
-
dueDate: linear.dueDate,
|
|
492
|
-
labelIds: [...linear.labelIds],
|
|
493
|
-
});
|
|
494
|
-
}
|
|
495
|
-
|
|
496
|
-
function normalizeTaskLinear(value: unknown): ControlPlaneTaskLinearRecord {
|
|
497
|
-
if (typeof value !== 'string') {
|
|
498
|
-
throw new Error('expected string for linear_json');
|
|
499
|
-
}
|
|
500
|
-
let parsed: unknown;
|
|
501
|
-
try {
|
|
502
|
-
parsed = JSON.parse(value) as unknown;
|
|
503
|
-
} catch {
|
|
504
|
-
return defaultTaskLinearRecord();
|
|
505
|
-
}
|
|
506
|
-
if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
|
|
507
|
-
return defaultTaskLinearRecord();
|
|
508
|
-
}
|
|
509
|
-
return applyTaskLinearInput(
|
|
510
|
-
defaultTaskLinearRecord(),
|
|
511
|
-
parseTaskLinearInputRecord(parsed as Record<string, unknown>, 'linear_json'),
|
|
512
|
-
);
|
|
513
|
-
}
|
|
514
|
-
|
|
515
306
|
function normalizeTaskStatus(value: unknown): ControlPlaneTaskStatus {
|
|
516
307
|
const status = asString(value, 'status');
|
|
517
308
|
if (
|
|
@@ -615,6 +406,7 @@ export function normalizeTaskRow(value: unknown): ControlPlaneTaskRecord {
|
|
|
615
406
|
const row = asRecord(value);
|
|
616
407
|
const repositoryId = asStringOrNull(row.repository_id, 'repository_id');
|
|
617
408
|
const projectId = asStringOrNull(row.project_id, 'project_id');
|
|
409
|
+
const bodyValue = row.body ?? row.description;
|
|
618
410
|
return {
|
|
619
411
|
taskId: asString(row.task_id, 'task_id'),
|
|
620
412
|
tenantId: asString(row.tenant_id, 'tenant_id'),
|
|
@@ -624,7 +416,7 @@ export function normalizeTaskRow(value: unknown): ControlPlaneTaskRecord {
|
|
|
624
416
|
scopeKind: normalizeTaskScopeKind(row.scope_kind, repositoryId, projectId),
|
|
625
417
|
projectId,
|
|
626
418
|
title: asString(row.title, 'title'),
|
|
627
|
-
|
|
419
|
+
body: asString(bodyValue, 'body'),
|
|
628
420
|
status: normalizeTaskStatus(row.status),
|
|
629
421
|
orderIndex: asNumberOrNull(row.order_index, 'order_index') as number,
|
|
630
422
|
claimedByControllerId: asStringOrNull(row.claimed_by_controller_id, 'claimed_by_controller_id'),
|
|
@@ -633,7 +425,6 @@ export function normalizeTaskRow(value: unknown): ControlPlaneTaskRecord {
|
|
|
633
425
|
baseBranch: asStringOrNull(row.base_branch, 'base_branch'),
|
|
634
426
|
claimedAt: asStringOrNull(row.claimed_at, 'claimed_at'),
|
|
635
427
|
completedAt: asStringOrNull(row.completed_at, 'completed_at'),
|
|
636
|
-
linear: normalizeTaskLinear(row.linear_json),
|
|
637
428
|
createdAt: asString(row.created_at, 'created_at'),
|
|
638
429
|
updatedAt: asString(row.updated_at, 'updated_at'),
|
|
639
430
|
};
|
|
@@ -59,7 +59,6 @@ export interface ControlPlaneTelemetrySummary {
|
|
|
59
59
|
|
|
60
60
|
export type ControlPlaneTaskStatus = 'draft' | 'ready' | 'in-progress' | 'completed';
|
|
61
61
|
export type ControlPlaneTaskScopeKind = 'global' | 'repository' | 'project';
|
|
62
|
-
export type ControlPlaneTaskLinearPriority = 0 | 1 | 2 | 3 | 4;
|
|
63
62
|
export type ControlPlaneProjectTaskFocusMode = 'balanced' | 'own-only';
|
|
64
63
|
export type ControlPlaneProjectThreadSpawnMode = 'new-thread' | 'reuse-thread';
|
|
65
64
|
export type ControlPlaneAutomationPolicyScope = 'global' | 'repository' | 'project';
|
|
@@ -72,38 +71,6 @@ export type ControlPlaneGitHubCiRollup =
|
|
|
72
71
|
| 'neutral'
|
|
73
72
|
| 'none';
|
|
74
73
|
|
|
75
|
-
export interface ControlPlaneTaskLinearRecord {
|
|
76
|
-
readonly issueId: string | null;
|
|
77
|
-
readonly identifier: string | null;
|
|
78
|
-
readonly url: string | null;
|
|
79
|
-
readonly teamId: string | null;
|
|
80
|
-
readonly projectId: string | null;
|
|
81
|
-
readonly projectMilestoneId: string | null;
|
|
82
|
-
readonly cycleId: string | null;
|
|
83
|
-
readonly stateId: string | null;
|
|
84
|
-
readonly assigneeId: string | null;
|
|
85
|
-
readonly priority: ControlPlaneTaskLinearPriority | null;
|
|
86
|
-
readonly estimate: number | null;
|
|
87
|
-
readonly dueDate: string | null;
|
|
88
|
-
readonly labelIds: readonly string[];
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
export interface TaskLinearInput {
|
|
92
|
-
issueId?: string | null;
|
|
93
|
-
identifier?: string | null;
|
|
94
|
-
url?: string | null;
|
|
95
|
-
teamId?: string | null;
|
|
96
|
-
projectId?: string | null;
|
|
97
|
-
projectMilestoneId?: string | null;
|
|
98
|
-
cycleId?: string | null;
|
|
99
|
-
stateId?: string | null;
|
|
100
|
-
assigneeId?: string | null;
|
|
101
|
-
priority?: number | null;
|
|
102
|
-
estimate?: number | null;
|
|
103
|
-
dueDate?: string | null;
|
|
104
|
-
labelIds?: readonly string[] | null;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
74
|
export interface ControlPlaneRepositoryRecord {
|
|
108
75
|
readonly repositoryId: string;
|
|
109
76
|
readonly tenantId: string;
|
|
@@ -126,7 +93,7 @@ export interface ControlPlaneTaskRecord {
|
|
|
126
93
|
readonly scopeKind: ControlPlaneTaskScopeKind;
|
|
127
94
|
readonly projectId: string | null;
|
|
128
95
|
readonly title: string;
|
|
129
|
-
readonly
|
|
96
|
+
readonly body: string;
|
|
130
97
|
readonly status: ControlPlaneTaskStatus;
|
|
131
98
|
readonly orderIndex: number;
|
|
132
99
|
readonly claimedByControllerId: string | null;
|
|
@@ -135,7 +102,6 @@ export interface ControlPlaneTaskRecord {
|
|
|
135
102
|
readonly baseBranch: string | null;
|
|
136
103
|
readonly claimedAt: string | null;
|
|
137
104
|
readonly completedAt: string | null;
|
|
138
|
-
readonly linear: ControlPlaneTaskLinearRecord;
|
|
139
105
|
readonly createdAt: string;
|
|
140
106
|
readonly updatedAt: string;
|
|
141
107
|
}
|