@jmoyers/harness 0.1.0
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/LICENSE +21 -0
- package/README.md +145 -0
- package/native/ptyd/Cargo.lock +16 -0
- package/native/ptyd/Cargo.toml +7 -0
- package/native/ptyd/src/main.rs +257 -0
- package/package.json +90 -0
- package/scripts/build-ptyd.sh +73 -0
- package/scripts/control-plane-daemon.ts +277 -0
- package/scripts/cursor-hook-relay.ts +82 -0
- package/scripts/harness-animate.ts +469 -0
- package/scripts/harness-bin.js +77 -0
- package/scripts/harness-core.ts +1 -0
- package/scripts/harness-inspector.ts +439 -0
- package/scripts/harness.ts +2493 -0
- package/src/adapters/agent-session-state.ts +390 -0
- package/src/cli/gateway-record.ts +173 -0
- package/src/codex/live-session.ts +872 -0
- package/src/config/config-core.ts +1359 -0
- package/src/config/secrets-core.ts +170 -0
- package/src/control-plane/agent-realtime-api.ts +2441 -0
- package/src/control-plane/codex-session-stream.ts +392 -0
- package/src/control-plane/codex-telemetry.ts +1325 -0
- package/src/control-plane/lifecycle-hooks.ts +706 -0
- package/src/control-plane/session-summary.ts +380 -0
- package/src/control-plane/status/agent-status-reducer.ts +21 -0
- package/src/control-plane/status/reducer-base.ts +170 -0
- package/src/control-plane/status/reducers/claude-status-reducer.ts +37 -0
- package/src/control-plane/status/reducers/codex-status-reducer.ts +48 -0
- package/src/control-plane/status/reducers/critique-status-reducer.ts +15 -0
- package/src/control-plane/status/reducers/cursor-status-reducer.ts +37 -0
- package/src/control-plane/status/reducers/terminal-status-reducer.ts +15 -0
- package/src/control-plane/status/session-status-engine.ts +76 -0
- package/src/control-plane/stream-client.ts +396 -0
- package/src/control-plane/stream-command-parser.ts +1673 -0
- package/src/control-plane/stream-protocol.ts +1808 -0
- package/src/control-plane/stream-server-background.ts +486 -0
- package/src/control-plane/stream-server-command.ts +2557 -0
- package/src/control-plane/stream-server-connection.ts +234 -0
- package/src/control-plane/stream-server-observed-filter.ts +112 -0
- package/src/control-plane/stream-server-session-runtime.ts +566 -0
- package/src/control-plane/stream-server-state-store.ts +15 -0
- package/src/control-plane/stream-server.ts +3192 -0
- package/src/cursor/managed-hooks.ts +282 -0
- package/src/domain/conversations.ts +414 -0
- package/src/domain/directories.ts +78 -0
- package/src/domain/repositories.ts +123 -0
- package/src/domain/tasks.ts +148 -0
- package/src/domain/workspace.ts +156 -0
- package/src/events/normalized-events.ts +124 -0
- package/src/mux/ansi-integrity.ts +103 -0
- package/src/mux/control-plane-op-queue.ts +212 -0
- package/src/mux/conversation-rail.ts +339 -0
- package/src/mux/double-click.ts +78 -0
- package/src/mux/dual-pane-core.ts +435 -0
- package/src/mux/harness-core-ui.ts +817 -0
- package/src/mux/input-shortcuts.ts +667 -0
- package/src/mux/live-mux/actions-conversation.ts +344 -0
- package/src/mux/live-mux/actions-repository.ts +246 -0
- package/src/mux/live-mux/actions-task.ts +115 -0
- package/src/mux/live-mux/args.ts +142 -0
- package/src/mux/live-mux/command-menu.ts +298 -0
- package/src/mux/live-mux/control-plane-records.ts +546 -0
- package/src/mux/live-mux/conversation-state.ts +188 -0
- package/src/mux/live-mux/directory-resolution.ts +34 -0
- package/src/mux/live-mux/event-mapping.ts +96 -0
- package/src/mux/live-mux/gateway-profiler.ts +152 -0
- package/src/mux/live-mux/gateway-render-trace.ts +177 -0
- package/src/mux/live-mux/gateway-status-timeline.ts +166 -0
- package/src/mux/live-mux/git-parsing.ts +131 -0
- package/src/mux/live-mux/git-snapshot.ts +263 -0
- package/src/mux/live-mux/git-state.ts +136 -0
- package/src/mux/live-mux/global-shortcut-handlers.ts +143 -0
- package/src/mux/live-mux/home-pane-actions.ts +58 -0
- package/src/mux/live-mux/home-pane-drop.ts +44 -0
- package/src/mux/live-mux/home-pane-entity-click.ts +96 -0
- package/src/mux/live-mux/home-pane-pointer.ts +96 -0
- package/src/mux/live-mux/input-forwarding.ts +112 -0
- package/src/mux/live-mux/layout.ts +30 -0
- package/src/mux/live-mux/left-nav-activation.ts +103 -0
- package/src/mux/live-mux/left-nav.ts +85 -0
- package/src/mux/live-mux/left-rail-actions.ts +118 -0
- package/src/mux/live-mux/left-rail-conversation-click.ts +82 -0
- package/src/mux/live-mux/left-rail-pointer.ts +74 -0
- package/src/mux/live-mux/modal-command-menu-handler.ts +101 -0
- package/src/mux/live-mux/modal-conversation-handlers.ts +217 -0
- package/src/mux/live-mux/modal-input-reducers.ts +94 -0
- package/src/mux/live-mux/modal-overlays.ts +287 -0
- package/src/mux/live-mux/modal-pointer.ts +70 -0
- package/src/mux/live-mux/modal-prompt-handlers.ts +187 -0
- package/src/mux/live-mux/modal-task-editor-handler.ts +156 -0
- package/src/mux/live-mux/observed-stream.ts +87 -0
- package/src/mux/live-mux/palette-parsing.ts +128 -0
- package/src/mux/live-mux/pointer-routing.ts +108 -0
- package/src/mux/live-mux/process-usage.ts +53 -0
- package/src/mux/live-mux/project-pane-pointer.ts +44 -0
- package/src/mux/live-mux/rail-layout.ts +244 -0
- package/src/mux/live-mux/render-trace-analysis.ts +213 -0
- package/src/mux/live-mux/render-trace-state.ts +84 -0
- package/src/mux/live-mux/repository-folding.ts +207 -0
- package/src/mux/live-mux/runtime-shutdown.ts +51 -0
- package/src/mux/live-mux/selection.ts +411 -0
- package/src/mux/live-mux/startup-utils.ts +187 -0
- package/src/mux/live-mux/status-timeline-state.ts +82 -0
- package/src/mux/live-mux/task-pane-shortcuts.ts +206 -0
- package/src/mux/live-mux/terminal-palette.ts +79 -0
- package/src/mux/new-thread-prompt.ts +165 -0
- package/src/mux/project-tree.ts +295 -0
- package/src/mux/render-frame.ts +113 -0
- package/src/mux/runtime-wiring.ts +185 -0
- package/src/mux/selector-index.ts +160 -0
- package/src/mux/startup-sequencer.ts +238 -0
- package/src/mux/task-composer.ts +289 -0
- package/src/mux/task-focused-pane.ts +417 -0
- package/src/mux/task-screen-keybindings.ts +539 -0
- package/src/mux/terminal-input-modes.ts +35 -0
- package/src/mux/workspace-path.ts +55 -0
- package/src/mux/workspace-rail-model.ts +701 -0
- package/src/mux/workspace-rail.ts +247 -0
- package/src/perf/perf-core.ts +307 -0
- package/src/pty/pty_host.ts +217 -0
- package/src/pty/session-broker.ts +158 -0
- package/src/recording/terminal-recording.ts +383 -0
- package/src/services/control-plane.ts +567 -0
- package/src/services/conversation-lifecycle.ts +176 -0
- package/src/services/conversation-startup-hydration.ts +47 -0
- package/src/services/directory-hydration.ts +49 -0
- package/src/services/event-persistence.ts +104 -0
- package/src/services/mux-ui-state-persistence.ts +82 -0
- package/src/services/output-load-sampler.ts +231 -0
- package/src/services/process-usage-refresh.ts +88 -0
- package/src/services/recording.ts +75 -0
- package/src/services/render-trace-recorder.ts +177 -0
- package/src/services/runtime-control-actions.ts +123 -0
- package/src/services/runtime-control-plane-ops.ts +131 -0
- package/src/services/runtime-conversation-actions.ts +113 -0
- package/src/services/runtime-conversation-activation.ts +78 -0
- package/src/services/runtime-conversation-starter.ts +171 -0
- package/src/services/runtime-conversation-title-edit.ts +149 -0
- package/src/services/runtime-directory-actions.ts +164 -0
- package/src/services/runtime-envelope-handler.ts +198 -0
- package/src/services/runtime-git-state.ts +92 -0
- package/src/services/runtime-input-pipeline.ts +50 -0
- package/src/services/runtime-input-router.ts +202 -0
- package/src/services/runtime-layout-resize.ts +236 -0
- package/src/services/runtime-left-rail-render.ts +159 -0
- package/src/services/runtime-main-pane-input.ts +230 -0
- package/src/services/runtime-modal-input.ts +119 -0
- package/src/services/runtime-navigation-input.ts +207 -0
- package/src/services/runtime-process-wiring.ts +68 -0
- package/src/services/runtime-rail-input.ts +287 -0
- package/src/services/runtime-render-flush.ts +146 -0
- package/src/services/runtime-render-lifecycle.ts +104 -0
- package/src/services/runtime-render-orchestrator.ts +108 -0
- package/src/services/runtime-render-pipeline.ts +167 -0
- package/src/services/runtime-render-state.ts +72 -0
- package/src/services/runtime-repository-actions.ts +197 -0
- package/src/services/runtime-right-pane-render.ts +132 -0
- package/src/services/runtime-shutdown.ts +79 -0
- package/src/services/runtime-stream-subscriptions.ts +56 -0
- package/src/services/runtime-task-composer-persistence.ts +139 -0
- package/src/services/runtime-task-editor-actions.ts +83 -0
- package/src/services/runtime-task-pane-actions.ts +198 -0
- package/src/services/runtime-task-pane-shortcuts.ts +189 -0
- package/src/services/runtime-task-pane.ts +62 -0
- package/src/services/runtime-workspace-actions.ts +153 -0
- package/src/services/runtime-workspace-observed-events.ts +190 -0
- package/src/services/session-projection-instrumentation.ts +190 -0
- package/src/services/startup-background-probe.ts +91 -0
- package/src/services/startup-background-resume.ts +65 -0
- package/src/services/startup-orchestrator.ts +166 -0
- package/src/services/startup-output-tracker.ts +54 -0
- package/src/services/startup-paint-tracker.ts +115 -0
- package/src/services/startup-persisted-conversation-queue.ts +45 -0
- package/src/services/startup-settled-gate.ts +67 -0
- package/src/services/startup-shutdown.ts +53 -0
- package/src/services/startup-span-tracker.ts +77 -0
- package/src/services/startup-state-hydration.ts +94 -0
- package/src/services/startup-visibility.ts +35 -0
- package/src/services/status-timeline-recorder.ts +144 -0
- package/src/services/task-pane-selection-actions.ts +153 -0
- package/src/services/task-planning-hydration.ts +58 -0
- package/src/services/task-planning-observed-events.ts +89 -0
- package/src/services/workspace-observed-events.ts +113 -0
- package/src/store/control-plane-store-normalize.ts +760 -0
- package/src/store/control-plane-store-types.ts +224 -0
- package/src/store/control-plane-store.ts +2951 -0
- package/src/store/event-store.ts +253 -0
- package/src/store/sqlite.ts +81 -0
- package/src/terminal/compat-matrix.ts +345 -0
- package/src/terminal/differential-checkpoints.ts +132 -0
- package/src/terminal/parity-suite.ts +441 -0
- package/src/terminal/snapshot-oracle.ts +1840 -0
- package/src/ui/conversation-input-forwarder.ts +114 -0
- package/src/ui/conversation-selection-input.ts +103 -0
- package/src/ui/debug-footer-notice.ts +39 -0
- package/src/ui/global-shortcut-input.ts +126 -0
- package/src/ui/input-preflight.ts +68 -0
- package/src/ui/input-token-router.ts +312 -0
- package/src/ui/input.ts +238 -0
- package/src/ui/kit.ts +509 -0
- package/src/ui/left-nav-input.ts +80 -0
- package/src/ui/left-rail-pointer-input.ts +148 -0
- package/src/ui/main-pane-pointer-input.ts +150 -0
- package/src/ui/modals/manager.ts +192 -0
- package/src/ui/mux-theme.ts +529 -0
- package/src/ui/panes/conversation.ts +19 -0
- package/src/ui/panes/home-gridfire.ts +302 -0
- package/src/ui/panes/home.ts +109 -0
- package/src/ui/panes/left-rail.ts +12 -0
- package/src/ui/panes/project.ts +44 -0
- package/src/ui/pointer-routing-input.ts +158 -0
- package/src/ui/repository-fold-input.ts +91 -0
- package/src/ui/screen.ts +210 -0
- package/src/ui/surface.ts +224 -0
|
@@ -0,0 +1,546 @@
|
|
|
1
|
+
import type { StreamSessionController } from '../../control-plane/stream-protocol.ts';
|
|
2
|
+
import type { StreamSessionStatusModel } from '../../control-plane/stream-protocol.ts';
|
|
3
|
+
import type { ConversationRailSessionSummary } from '../conversation-rail.ts';
|
|
4
|
+
|
|
5
|
+
interface ControlPlaneDirectoryRecord {
|
|
6
|
+
readonly directoryId: string;
|
|
7
|
+
readonly tenantId: string;
|
|
8
|
+
readonly userId: string;
|
|
9
|
+
readonly workspaceId: string;
|
|
10
|
+
readonly path: string;
|
|
11
|
+
readonly createdAt: string | null;
|
|
12
|
+
readonly archivedAt: string | null;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
interface ControlPlaneConversationRecord {
|
|
16
|
+
readonly conversationId: string;
|
|
17
|
+
readonly directoryId: string;
|
|
18
|
+
readonly tenantId: string;
|
|
19
|
+
readonly userId: string;
|
|
20
|
+
readonly workspaceId: string;
|
|
21
|
+
readonly title: string;
|
|
22
|
+
readonly agentType: string;
|
|
23
|
+
readonly adapterState: Record<string, unknown>;
|
|
24
|
+
readonly runtimeStatus: ConversationRailSessionSummary['status'];
|
|
25
|
+
readonly runtimeStatusModel: StreamSessionStatusModel | null;
|
|
26
|
+
readonly runtimeLive: boolean;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
interface ControlPlaneRepositoryRecord {
|
|
30
|
+
readonly repositoryId: string;
|
|
31
|
+
readonly tenantId: string;
|
|
32
|
+
readonly userId: string;
|
|
33
|
+
readonly workspaceId: string;
|
|
34
|
+
readonly name: string;
|
|
35
|
+
readonly remoteUrl: string;
|
|
36
|
+
readonly defaultBranch: string;
|
|
37
|
+
readonly metadata: Record<string, unknown>;
|
|
38
|
+
readonly createdAt: string | null;
|
|
39
|
+
readonly archivedAt: string | null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
interface ControlPlaneGitSummaryRecord {
|
|
43
|
+
readonly branch: string;
|
|
44
|
+
readonly changedFiles: number;
|
|
45
|
+
readonly additions: number;
|
|
46
|
+
readonly deletions: number;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
interface ControlPlaneGitRepositorySnapshotRecord {
|
|
50
|
+
readonly normalizedRemoteUrl: string | null;
|
|
51
|
+
readonly commitCount: number | null;
|
|
52
|
+
readonly lastCommitAt: string | null;
|
|
53
|
+
readonly shortCommitHash: string | null;
|
|
54
|
+
readonly inferredName: string | null;
|
|
55
|
+
readonly defaultBranch: string | null;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
interface ControlPlaneDirectoryGitStatusRecord {
|
|
59
|
+
readonly directoryId: string;
|
|
60
|
+
readonly summary: ControlPlaneGitSummaryRecord;
|
|
61
|
+
readonly repositorySnapshot: ControlPlaneGitRepositorySnapshotRecord;
|
|
62
|
+
readonly repositoryId: string | null;
|
|
63
|
+
readonly repository: ControlPlaneRepositoryRecord | null;
|
|
64
|
+
readonly observedAt: string;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
type TaskStatus = 'draft' | 'ready' | 'in-progress' | 'completed';
|
|
68
|
+
type TaskScopeKind = 'global' | 'repository' | 'project';
|
|
69
|
+
|
|
70
|
+
interface ControlPlaneTaskRecord {
|
|
71
|
+
readonly taskId: string;
|
|
72
|
+
readonly tenantId: string;
|
|
73
|
+
readonly userId: string;
|
|
74
|
+
readonly workspaceId: string;
|
|
75
|
+
readonly repositoryId: string | null;
|
|
76
|
+
readonly scopeKind: TaskScopeKind;
|
|
77
|
+
readonly projectId: string | null;
|
|
78
|
+
readonly title: string;
|
|
79
|
+
readonly description: string;
|
|
80
|
+
readonly status: TaskStatus;
|
|
81
|
+
readonly orderIndex: number;
|
|
82
|
+
readonly claimedByControllerId: string | null;
|
|
83
|
+
readonly claimedByDirectoryId: string | null;
|
|
84
|
+
readonly branchName: string | null;
|
|
85
|
+
readonly baseBranch: string | null;
|
|
86
|
+
readonly claimedAt: string | null;
|
|
87
|
+
readonly completedAt: string | null;
|
|
88
|
+
readonly createdAt: string;
|
|
89
|
+
readonly updatedAt: string;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function asRecord(value: unknown): Record<string, unknown> | null {
|
|
93
|
+
if (typeof value !== 'object' || value === null) {
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
return value as Record<string, unknown>;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function asRequiredString(value: unknown): string | null {
|
|
100
|
+
return typeof value === 'string' ? value : null;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Accept null/undefined as null; return undefined for invalid non-string non-null values.
|
|
104
|
+
function asOptionalString(value: unknown): string | null | undefined {
|
|
105
|
+
if (value === null || value === undefined) {
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
return typeof value === 'string' ? value : undefined;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Accept null/string only. Undefined and other types are invalid.
|
|
112
|
+
function asNullableString(value: unknown): string | null | undefined {
|
|
113
|
+
if (value === null) {
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
return typeof value === 'string' ? value : undefined;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function asObjectRecord(value: unknown): Record<string, unknown> | null {
|
|
120
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value)) {
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
return value as Record<string, unknown>;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function parseRuntimeStatusModel(value: unknown): StreamSessionStatusModel | null | undefined {
|
|
127
|
+
if (value === null) {
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
const model = asObjectRecord(value);
|
|
131
|
+
if (model === null) {
|
|
132
|
+
return undefined;
|
|
133
|
+
}
|
|
134
|
+
const runtimeStatus = model['runtimeStatus'];
|
|
135
|
+
const phase = model['phase'];
|
|
136
|
+
const glyph = model['glyph'];
|
|
137
|
+
const badge = model['badge'];
|
|
138
|
+
const detailText = asRequiredString(model['detailText']);
|
|
139
|
+
const attentionReason = asNullableString(model['attentionReason']);
|
|
140
|
+
const lastKnownWork = asNullableString(model['lastKnownWork']);
|
|
141
|
+
const lastKnownWorkAt = asNullableString(model['lastKnownWorkAt']);
|
|
142
|
+
const phaseHint = model['phaseHint'];
|
|
143
|
+
const observedAt = asRequiredString(model['observedAt']);
|
|
144
|
+
if (
|
|
145
|
+
detailText === null ||
|
|
146
|
+
attentionReason === undefined ||
|
|
147
|
+
lastKnownWork === undefined ||
|
|
148
|
+
lastKnownWorkAt === undefined ||
|
|
149
|
+
observedAt === null
|
|
150
|
+
) {
|
|
151
|
+
return undefined;
|
|
152
|
+
}
|
|
153
|
+
if (
|
|
154
|
+
runtimeStatus !== 'running' &&
|
|
155
|
+
runtimeStatus !== 'needs-input' &&
|
|
156
|
+
runtimeStatus !== 'completed' &&
|
|
157
|
+
runtimeStatus !== 'exited'
|
|
158
|
+
) {
|
|
159
|
+
return undefined;
|
|
160
|
+
}
|
|
161
|
+
if (
|
|
162
|
+
phase !== 'needs-action' &&
|
|
163
|
+
phase !== 'starting' &&
|
|
164
|
+
phase !== 'working' &&
|
|
165
|
+
phase !== 'idle' &&
|
|
166
|
+
phase !== 'exited'
|
|
167
|
+
) {
|
|
168
|
+
return undefined;
|
|
169
|
+
}
|
|
170
|
+
if (glyph !== '▲' && glyph !== '◔' && glyph !== '◆' && glyph !== '○' && glyph !== '■') {
|
|
171
|
+
return undefined;
|
|
172
|
+
}
|
|
173
|
+
if (badge !== 'NEED' && badge !== 'RUN ' && badge !== 'DONE' && badge !== 'EXIT') {
|
|
174
|
+
return undefined;
|
|
175
|
+
}
|
|
176
|
+
if (
|
|
177
|
+
phaseHint !== null &&
|
|
178
|
+
phaseHint !== 'needs-action' &&
|
|
179
|
+
phaseHint !== 'working' &&
|
|
180
|
+
phaseHint !== 'idle'
|
|
181
|
+
) {
|
|
182
|
+
return undefined;
|
|
183
|
+
}
|
|
184
|
+
return {
|
|
185
|
+
runtimeStatus,
|
|
186
|
+
phase,
|
|
187
|
+
glyph,
|
|
188
|
+
badge,
|
|
189
|
+
detailText,
|
|
190
|
+
attentionReason,
|
|
191
|
+
lastKnownWork,
|
|
192
|
+
lastKnownWorkAt,
|
|
193
|
+
phaseHint,
|
|
194
|
+
observedAt,
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
export function parseDirectoryRecord(value: unknown): ControlPlaneDirectoryRecord | null {
|
|
199
|
+
const record = asRecord(value);
|
|
200
|
+
if (record === null) {
|
|
201
|
+
return null;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
const directoryId = asRequiredString(record['directoryId']);
|
|
205
|
+
const tenantId = asRequiredString(record['tenantId']);
|
|
206
|
+
const userId = asRequiredString(record['userId']);
|
|
207
|
+
const workspaceId = asRequiredString(record['workspaceId']);
|
|
208
|
+
const path = asRequiredString(record['path']);
|
|
209
|
+
const createdAt = asOptionalString(record['createdAt']);
|
|
210
|
+
const archivedAt = asOptionalString(record['archivedAt']);
|
|
211
|
+
|
|
212
|
+
if (
|
|
213
|
+
directoryId === null ||
|
|
214
|
+
tenantId === null ||
|
|
215
|
+
userId === null ||
|
|
216
|
+
workspaceId === null ||
|
|
217
|
+
path === null ||
|
|
218
|
+
createdAt === undefined ||
|
|
219
|
+
archivedAt === undefined
|
|
220
|
+
) {
|
|
221
|
+
return null;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
return {
|
|
225
|
+
directoryId,
|
|
226
|
+
tenantId,
|
|
227
|
+
userId,
|
|
228
|
+
workspaceId,
|
|
229
|
+
path,
|
|
230
|
+
createdAt,
|
|
231
|
+
archivedAt,
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
export function parseConversationRecord(value: unknown): ControlPlaneConversationRecord | null {
|
|
236
|
+
const record = asRecord(value);
|
|
237
|
+
if (record === null) {
|
|
238
|
+
return null;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
const conversationId = asRequiredString(record['conversationId']);
|
|
242
|
+
const directoryId = asRequiredString(record['directoryId']);
|
|
243
|
+
const tenantId = asRequiredString(record['tenantId']);
|
|
244
|
+
const userId = asRequiredString(record['userId']);
|
|
245
|
+
const workspaceId = asRequiredString(record['workspaceId']);
|
|
246
|
+
const title = asRequiredString(record['title']);
|
|
247
|
+
const agentType = asRequiredString(record['agentType']);
|
|
248
|
+
const adapterState = asObjectRecord(record['adapterState']);
|
|
249
|
+
const runtimeStatus = record['runtimeStatus'];
|
|
250
|
+
const runtimeStatusModel = parseRuntimeStatusModel(record['runtimeStatusModel']);
|
|
251
|
+
const runtimeLive = record['runtimeLive'];
|
|
252
|
+
|
|
253
|
+
if (
|
|
254
|
+
conversationId === null ||
|
|
255
|
+
directoryId === null ||
|
|
256
|
+
tenantId === null ||
|
|
257
|
+
userId === null ||
|
|
258
|
+
workspaceId === null ||
|
|
259
|
+
title === null ||
|
|
260
|
+
agentType === null ||
|
|
261
|
+
adapterState === null ||
|
|
262
|
+
runtimeStatusModel === undefined ||
|
|
263
|
+
typeof runtimeLive !== 'boolean'
|
|
264
|
+
) {
|
|
265
|
+
return null;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
if (
|
|
269
|
+
runtimeStatus !== 'running' &&
|
|
270
|
+
runtimeStatus !== 'needs-input' &&
|
|
271
|
+
runtimeStatus !== 'completed' &&
|
|
272
|
+
runtimeStatus !== 'exited'
|
|
273
|
+
) {
|
|
274
|
+
return null;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
return {
|
|
278
|
+
conversationId,
|
|
279
|
+
directoryId,
|
|
280
|
+
tenantId,
|
|
281
|
+
userId,
|
|
282
|
+
workspaceId,
|
|
283
|
+
title,
|
|
284
|
+
agentType,
|
|
285
|
+
adapterState,
|
|
286
|
+
runtimeStatus,
|
|
287
|
+
runtimeStatusModel,
|
|
288
|
+
runtimeLive,
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
export function parseRepositoryRecord(value: unknown): ControlPlaneRepositoryRecord | null {
|
|
293
|
+
const record = asRecord(value);
|
|
294
|
+
if (record === null) {
|
|
295
|
+
return null;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
const repositoryId = asRequiredString(record['repositoryId']);
|
|
299
|
+
const tenantId = asRequiredString(record['tenantId']);
|
|
300
|
+
const userId = asRequiredString(record['userId']);
|
|
301
|
+
const workspaceId = asRequiredString(record['workspaceId']);
|
|
302
|
+
const name = asRequiredString(record['name']);
|
|
303
|
+
const remoteUrl = asRequiredString(record['remoteUrl']);
|
|
304
|
+
const defaultBranch = asRequiredString(record['defaultBranch']);
|
|
305
|
+
const metadata = asObjectRecord(record['metadata']);
|
|
306
|
+
const createdAt = asOptionalString(record['createdAt']);
|
|
307
|
+
const archivedAt = asOptionalString(record['archivedAt']);
|
|
308
|
+
|
|
309
|
+
if (
|
|
310
|
+
repositoryId === null ||
|
|
311
|
+
tenantId === null ||
|
|
312
|
+
userId === null ||
|
|
313
|
+
workspaceId === null ||
|
|
314
|
+
name === null ||
|
|
315
|
+
remoteUrl === null ||
|
|
316
|
+
defaultBranch === null ||
|
|
317
|
+
metadata === null ||
|
|
318
|
+
createdAt === undefined ||
|
|
319
|
+
archivedAt === undefined
|
|
320
|
+
) {
|
|
321
|
+
return null;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
return {
|
|
325
|
+
repositoryId,
|
|
326
|
+
tenantId,
|
|
327
|
+
userId,
|
|
328
|
+
workspaceId,
|
|
329
|
+
name,
|
|
330
|
+
remoteUrl,
|
|
331
|
+
defaultBranch,
|
|
332
|
+
metadata,
|
|
333
|
+
createdAt,
|
|
334
|
+
archivedAt,
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
export function parseDirectoryGitStatusRecord(
|
|
339
|
+
value: unknown,
|
|
340
|
+
): ControlPlaneDirectoryGitStatusRecord | null {
|
|
341
|
+
const record = asRecord(value);
|
|
342
|
+
if (record === null) {
|
|
343
|
+
return null;
|
|
344
|
+
}
|
|
345
|
+
const directoryId = asRequiredString(record['directoryId']);
|
|
346
|
+
const summaryRecord = asRecord(record['summary']);
|
|
347
|
+
const repositorySnapshotRecord = asRecord(record['repositorySnapshot']);
|
|
348
|
+
const repositoryId = asOptionalString(record['repositoryId']);
|
|
349
|
+
const observedAt = asRequiredString(record['observedAt']);
|
|
350
|
+
|
|
351
|
+
if (
|
|
352
|
+
directoryId === null ||
|
|
353
|
+
summaryRecord === null ||
|
|
354
|
+
repositorySnapshotRecord === null ||
|
|
355
|
+
repositoryId === undefined ||
|
|
356
|
+
observedAt === null
|
|
357
|
+
) {
|
|
358
|
+
return null;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
const summaryBranch = asRequiredString(summaryRecord['branch']);
|
|
362
|
+
const changedFiles = summaryRecord['changedFiles'];
|
|
363
|
+
const additions = summaryRecord['additions'];
|
|
364
|
+
const deletions = summaryRecord['deletions'];
|
|
365
|
+
const normalizedRemoteUrl = asOptionalString(repositorySnapshotRecord['normalizedRemoteUrl']);
|
|
366
|
+
const commitCountRaw = repositorySnapshotRecord['commitCount'];
|
|
367
|
+
const lastCommitAt = asOptionalString(repositorySnapshotRecord['lastCommitAt']);
|
|
368
|
+
const shortCommitHash = asOptionalString(repositorySnapshotRecord['shortCommitHash']);
|
|
369
|
+
const inferredName = asOptionalString(repositorySnapshotRecord['inferredName']);
|
|
370
|
+
const defaultBranch = asOptionalString(repositorySnapshotRecord['defaultBranch']);
|
|
371
|
+
const repositoryRaw = record['repository'];
|
|
372
|
+
const repository =
|
|
373
|
+
repositoryRaw === null || repositoryRaw === undefined
|
|
374
|
+
? null
|
|
375
|
+
: parseRepositoryRecord(repositoryRaw);
|
|
376
|
+
|
|
377
|
+
if (
|
|
378
|
+
summaryBranch === null ||
|
|
379
|
+
typeof changedFiles !== 'number' ||
|
|
380
|
+
!Number.isFinite(changedFiles) ||
|
|
381
|
+
typeof additions !== 'number' ||
|
|
382
|
+
!Number.isFinite(additions) ||
|
|
383
|
+
typeof deletions !== 'number' ||
|
|
384
|
+
!Number.isFinite(deletions) ||
|
|
385
|
+
normalizedRemoteUrl === undefined ||
|
|
386
|
+
lastCommitAt === undefined ||
|
|
387
|
+
shortCommitHash === undefined ||
|
|
388
|
+
inferredName === undefined ||
|
|
389
|
+
defaultBranch === undefined ||
|
|
390
|
+
(commitCountRaw !== null &&
|
|
391
|
+
(typeof commitCountRaw !== 'number' || !Number.isFinite(commitCountRaw))) ||
|
|
392
|
+
(repositoryRaw !== null && repositoryRaw !== undefined && repository === null)
|
|
393
|
+
) {
|
|
394
|
+
return null;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
return {
|
|
398
|
+
directoryId,
|
|
399
|
+
summary: {
|
|
400
|
+
branch: summaryBranch,
|
|
401
|
+
changedFiles,
|
|
402
|
+
additions,
|
|
403
|
+
deletions,
|
|
404
|
+
},
|
|
405
|
+
repositorySnapshot: {
|
|
406
|
+
normalizedRemoteUrl,
|
|
407
|
+
commitCount: commitCountRaw,
|
|
408
|
+
lastCommitAt,
|
|
409
|
+
shortCommitHash,
|
|
410
|
+
inferredName,
|
|
411
|
+
defaultBranch,
|
|
412
|
+
},
|
|
413
|
+
repositoryId,
|
|
414
|
+
repository,
|
|
415
|
+
observedAt,
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
export function parseTaskStatus(value: unknown): TaskStatus | null {
|
|
420
|
+
if (value === 'queued') {
|
|
421
|
+
return 'ready';
|
|
422
|
+
}
|
|
423
|
+
if (value === 'draft' || value === 'ready' || value === 'in-progress' || value === 'completed') {
|
|
424
|
+
return value;
|
|
425
|
+
}
|
|
426
|
+
return null;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
function parseTaskScopeKind(
|
|
430
|
+
value: unknown,
|
|
431
|
+
repositoryId: string | null | undefined,
|
|
432
|
+
projectId: string | null | undefined,
|
|
433
|
+
): TaskScopeKind | null {
|
|
434
|
+
if (value === 'global' || value === 'repository' || value === 'project') {
|
|
435
|
+
return value;
|
|
436
|
+
}
|
|
437
|
+
if (projectId !== null) {
|
|
438
|
+
return 'project';
|
|
439
|
+
}
|
|
440
|
+
if (repositoryId !== null) {
|
|
441
|
+
return 'repository';
|
|
442
|
+
}
|
|
443
|
+
if (value === null || value === undefined) return 'global';
|
|
444
|
+
return null;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
export function parseTaskRecord(value: unknown): ControlPlaneTaskRecord | null {
|
|
448
|
+
const record = asRecord(value);
|
|
449
|
+
if (record === null) {
|
|
450
|
+
return null;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
const taskId = asRequiredString(record['taskId']);
|
|
454
|
+
const tenantId = asRequiredString(record['tenantId']);
|
|
455
|
+
const userId = asRequiredString(record['userId']);
|
|
456
|
+
const workspaceId = asRequiredString(record['workspaceId']);
|
|
457
|
+
const repositoryId = asOptionalString(record['repositoryId']);
|
|
458
|
+
const projectId = asOptionalString(record['projectId']);
|
|
459
|
+
const title = asRequiredString(record['title']);
|
|
460
|
+
const description = asRequiredString(record['description']);
|
|
461
|
+
const status = parseTaskStatus(record['status']);
|
|
462
|
+
const scopeKind = parseTaskScopeKind(record['scopeKind'], repositoryId, projectId);
|
|
463
|
+
const orderIndex = record['orderIndex'];
|
|
464
|
+
const claimedByControllerId = asOptionalString(record['claimedByControllerId']);
|
|
465
|
+
const claimedByDirectoryId = asOptionalString(record['claimedByDirectoryId']);
|
|
466
|
+
const branchName = asOptionalString(record['branchName']);
|
|
467
|
+
const baseBranch = asOptionalString(record['baseBranch']);
|
|
468
|
+
const claimedAt = asOptionalString(record['claimedAt']);
|
|
469
|
+
const completedAt = asOptionalString(record['completedAt']);
|
|
470
|
+
const createdAt = asRequiredString(record['createdAt']);
|
|
471
|
+
const updatedAt = asRequiredString(record['updatedAt']);
|
|
472
|
+
|
|
473
|
+
if (
|
|
474
|
+
taskId === null ||
|
|
475
|
+
tenantId === null ||
|
|
476
|
+
userId === null ||
|
|
477
|
+
workspaceId === null ||
|
|
478
|
+
repositoryId === undefined ||
|
|
479
|
+
projectId === undefined ||
|
|
480
|
+
scopeKind === null ||
|
|
481
|
+
title === null ||
|
|
482
|
+
description === null ||
|
|
483
|
+
status === null ||
|
|
484
|
+
typeof orderIndex !== 'number' ||
|
|
485
|
+
claimedByControllerId === undefined ||
|
|
486
|
+
claimedByDirectoryId === undefined ||
|
|
487
|
+
branchName === undefined ||
|
|
488
|
+
baseBranch === undefined ||
|
|
489
|
+
claimedAt === undefined ||
|
|
490
|
+
completedAt === undefined ||
|
|
491
|
+
createdAt === null ||
|
|
492
|
+
updatedAt === null
|
|
493
|
+
) {
|
|
494
|
+
return null;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
return {
|
|
498
|
+
taskId,
|
|
499
|
+
tenantId,
|
|
500
|
+
userId,
|
|
501
|
+
workspaceId,
|
|
502
|
+
repositoryId,
|
|
503
|
+
scopeKind,
|
|
504
|
+
projectId,
|
|
505
|
+
title,
|
|
506
|
+
description,
|
|
507
|
+
status,
|
|
508
|
+
orderIndex,
|
|
509
|
+
claimedByControllerId,
|
|
510
|
+
claimedByDirectoryId,
|
|
511
|
+
branchName,
|
|
512
|
+
baseBranch,
|
|
513
|
+
claimedAt,
|
|
514
|
+
completedAt,
|
|
515
|
+
createdAt,
|
|
516
|
+
updatedAt,
|
|
517
|
+
};
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
export function parseSessionControllerRecord(value: unknown): StreamSessionController | null {
|
|
521
|
+
const record = asRecord(value);
|
|
522
|
+
if (record === null) {
|
|
523
|
+
return null;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
const controllerId = asRequiredString(record['controllerId']);
|
|
527
|
+
const controllerType = record['controllerType'];
|
|
528
|
+
const controllerLabel = asNullableString(record['controllerLabel']);
|
|
529
|
+
const claimedAt = asRequiredString(record['claimedAt']);
|
|
530
|
+
|
|
531
|
+
if (
|
|
532
|
+
controllerId === null ||
|
|
533
|
+
(controllerType !== 'human' && controllerType !== 'agent' && controllerType !== 'automation') ||
|
|
534
|
+
controllerLabel === undefined ||
|
|
535
|
+
claimedAt === null
|
|
536
|
+
) {
|
|
537
|
+
return null;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
return {
|
|
541
|
+
controllerId,
|
|
542
|
+
controllerType,
|
|
543
|
+
controllerLabel,
|
|
544
|
+
claimedAt,
|
|
545
|
+
};
|
|
546
|
+
}
|