@h-rig/core 0.0.6-alpha.18 → 0.0.6-alpha.181

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.
Files changed (105) hide show
  1. package/dist/src/agent-role-registry.d.ts +4 -0
  2. package/dist/src/agent-role-registry.js +27 -0
  3. package/dist/src/authority-paths.d.ts +15 -0
  4. package/dist/src/authority-paths.js +80 -0
  5. package/dist/src/baked-secrets.d.ts +3 -0
  6. package/dist/src/baked-secrets.js +63 -0
  7. package/dist/src/build-time-config.d.ts +12 -0
  8. package/dist/src/build-time-config.js +25 -0
  9. package/dist/src/build-time-config.macro.d.ts +1 -0
  10. package/dist/src/capability-loaders.d.ts +51 -0
  11. package/dist/src/capability-loaders.js +870 -0
  12. package/dist/src/capability.d.ts +79 -0
  13. package/dist/src/capability.js +63 -0
  14. package/dist/src/checkout-root.d.ts +1 -0
  15. package/dist/src/checkout-root.js +30 -0
  16. package/dist/src/config-env.d.ts +4 -0
  17. package/dist/src/config-env.js +23 -0
  18. package/dist/src/config.d.ts +3 -0
  19. package/dist/src/config.js +44 -0
  20. package/dist/src/declarative-config.d.ts +14 -0
  21. package/dist/src/declarative-config.js +85 -0
  22. package/dist/src/default-kernel.d.ts +1 -0
  23. package/dist/src/default-kernel.js +12 -0
  24. package/dist/src/define-config.d.ts +20 -0
  25. package/dist/src/define-config.js +28 -15
  26. package/dist/src/define-plugin.d.ts +13 -0
  27. package/dist/src/define-plugin.js +4 -43
  28. package/dist/src/embedded-plugins.d.ts +59 -0
  29. package/dist/src/embedded-plugins.js +22 -0
  30. package/dist/src/exec.d.ts +13 -0
  31. package/dist/src/exec.js +101 -0
  32. package/dist/src/harness-paths.d.ts +9 -0
  33. package/dist/src/harness-paths.js +126 -0
  34. package/dist/src/hook-materializer.d.ts +21 -0
  35. package/dist/src/hook-materializer.js +152 -0
  36. package/dist/src/hook-protocol.d.ts +2 -0
  37. package/dist/src/hook-protocol.js +432 -0
  38. package/dist/src/hook-runner.d.ts +48 -0
  39. package/dist/src/hook-runner.js +868 -0
  40. package/dist/src/hook-runtime.d.ts +52 -0
  41. package/dist/src/hook-runtime.js +432 -0
  42. package/dist/src/index.d.ts +8 -0
  43. package/dist/src/index.js +210 -2499
  44. package/dist/src/json-files.d.ts +9 -0
  45. package/dist/src/json-files.js +124 -0
  46. package/dist/src/kernel-boot.d.ts +2 -0
  47. package/dist/src/kernel-boot.js +10 -0
  48. package/dist/src/kernel-entrypoint.d.ts +22 -0
  49. package/dist/src/kernel-entrypoint.js +660 -0
  50. package/dist/src/kernel-plugin-abi.d.ts +1 -0
  51. package/dist/src/kernel-plugin-abi.js +1 -0
  52. package/dist/src/kernel-resolver.d.ts +2 -0
  53. package/dist/src/kernel-resolver.js +6 -0
  54. package/dist/src/layout.d.ts +10 -0
  55. package/dist/src/layout.js +138 -0
  56. package/dist/src/load-config.d.ts +2 -0
  57. package/dist/src/load-config.js +535 -30
  58. package/dist/src/placement.d.ts +58 -0
  59. package/dist/src/placement.js +53 -0
  60. package/dist/src/plugin-host-context.d.ts +65 -0
  61. package/dist/src/plugin-host-context.js +1171 -0
  62. package/dist/src/plugin-host-registries.d.ts +31 -0
  63. package/dist/src/plugin-host-registries.js +79 -0
  64. package/dist/src/plugin-host.d.ts +77 -0
  65. package/dist/src/plugin-host.js +127 -63
  66. package/dist/src/plugin-runtime.d.ts +173 -0
  67. package/dist/src/project-plugins.d.ts +63 -0
  68. package/dist/src/project-plugins.js +905 -0
  69. package/dist/src/remote-config.d.ts +125 -0
  70. package/dist/src/remote-config.js +85 -0
  71. package/dist/src/root-resolver.d.ts +5 -0
  72. package/dist/src/root-resolver.js +68 -0
  73. package/dist/src/run-provisioning.d.ts +37 -0
  74. package/dist/src/run-provisioning.js +35 -0
  75. package/dist/src/runtime-context.d.ts +20 -0
  76. package/dist/src/runtime-context.js +257 -0
  77. package/dist/src/runtime-events.d.ts +44 -0
  78. package/dist/src/runtime-events.js +208 -0
  79. package/dist/src/runtime-overlay.d.ts +11 -0
  80. package/dist/src/runtime-overlay.js +69 -0
  81. package/dist/src/runtime-paths.d.ts +21 -0
  82. package/dist/src/runtime-paths.js +181 -0
  83. package/dist/src/runtime-provisioning-env.d.ts +5 -0
  84. package/dist/src/runtime-provisioning-env.js +217 -0
  85. package/dist/src/runtime-runner-context.d.ts +12 -0
  86. package/dist/src/runtime-runner-context.js +1 -0
  87. package/dist/src/safe-identifiers.d.ts +44 -0
  88. package/dist/src/safe-identifiers.js +96 -0
  89. package/dist/src/scope-rules.d.ts +4 -0
  90. package/dist/src/scope-rules.js +21 -0
  91. package/dist/src/server-paths.d.ts +22 -0
  92. package/dist/src/server-paths.js +219 -0
  93. package/dist/src/setup-version.d.ts +3 -0
  94. package/dist/src/setup-version.js +14 -0
  95. package/dist/src/task-record-reader.d.ts +3 -0
  96. package/dist/src/task-record-reader.js +9 -0
  97. package/dist/src/validator-registry.d.ts +27 -0
  98. package/dist/src/validator-registry.js +64 -0
  99. package/package.json +162 -10
  100. package/dist/src/engineReadModelReducer.js +0 -1780
  101. package/dist/src/rig-init-builder.js +0 -57
  102. package/dist/src/rigSelectors.js +0 -293
  103. package/dist/src/taskGraph.js +0 -64
  104. package/dist/src/taskGraphCodes.js +0 -26
  105. package/dist/src/taskGraphLayout.js +0 -374
@@ -1,1780 +0,0 @@
1
- // @bun
2
- // packages/core/src/engineReadModelReducer.ts
3
- import {
4
- ActionId,
5
- ConversationId,
6
- EngineRuntimeId,
7
- MessageId,
8
- RunId,
9
- TaskId,
10
- WorkspaceId,
11
- WorktreeId
12
- } from "@rig/contracts";
13
- function isRecord(value) {
14
- return typeof value === "object" && value !== null;
15
- }
16
- function readString(payload, key) {
17
- const value = payload[key];
18
- return typeof value === "string" ? value : undefined;
19
- }
20
- function readNullableString(payload, key) {
21
- const value = payload[key];
22
- return typeof value === "string" ? value : value === null ? null : undefined;
23
- }
24
- function readRecord(payload, key) {
25
- const value = payload[key];
26
- return isRecord(value) ? value : undefined;
27
- }
28
- function asWorkspaceId(value) {
29
- return WorkspaceId.makeUnsafe(value);
30
- }
31
- function asTaskId(value) {
32
- return TaskId.makeUnsafe(value);
33
- }
34
- function asRunId(value) {
35
- return RunId.makeUnsafe(value);
36
- }
37
- function conversationIdFromRunId(value) {
38
- return ConversationId.makeUnsafe(value);
39
- }
40
- function asActionId(value) {
41
- return ActionId.makeUnsafe(value);
42
- }
43
- function runtimeIdFromRunId(value) {
44
- return EngineRuntimeId.makeUnsafe(value);
45
- }
46
- function worktreeIdFromRunId(value) {
47
- return WorktreeId.makeUnsafe(value);
48
- }
49
- function asMessageId(value) {
50
- return MessageId.makeUnsafe(value);
51
- }
52
- function upsertById(items, entry) {
53
- const index = items.findIndex((candidate) => candidate.id === entry.id);
54
- if (index < 0) {
55
- return [...items, entry];
56
- }
57
- const next = items.slice();
58
- next[index] = entry;
59
- return next;
60
- }
61
- function removeById(items, id) {
62
- return items.filter((candidate) => candidate.id !== id);
63
- }
64
- function patchById(items, id, updater) {
65
- const index = items.findIndex((candidate) => candidate.id === id);
66
- if (index < 0) {
67
- return items.slice();
68
- }
69
- const next = items.slice();
70
- next[index] = updater(next[index]);
71
- return next;
72
- }
73
- function upsertByKey(items, entry, key) {
74
- const index = items.findIndex((candidate) => candidate[key] === entry[key]);
75
- if (index < 0) {
76
- return [...items, entry];
77
- }
78
- const next = items.slice();
79
- next[index] = entry;
80
- return next;
81
- }
82
- function patchByKey(items, keyValue, key, updater) {
83
- const index = items.findIndex((candidate) => candidate[key] === keyValue);
84
- if (index < 0) {
85
- return items.slice();
86
- }
87
- const next = items.slice();
88
- next[index] = updater(next[index]);
89
- return next;
90
- }
91
- function mergeById(items, incoming) {
92
- return incoming.reduce((acc, item) => upsertById(acc, item), [...items]);
93
- }
94
- function replaceWorkspaceSlice(items, workspaceId, incoming) {
95
- return [...items.filter((item) => item.workspaceId !== workspaceId), ...incoming];
96
- }
97
- function withQueuePositions(items) {
98
- return items.map((item, index) => Object.assign({}, item, {
99
- position: index
100
- }));
101
- }
102
- function maxIsoDate(left, right) {
103
- return left.localeCompare(right) >= 0 ? left : right;
104
- }
105
- var REMOTE_HOST_STATUS_ONLINE = new Set([
106
- "ready",
107
- "busy",
108
- "degraded",
109
- "draining"
110
- ]);
111
- function deriveRemoteFleetStatus(hosts, warnings) {
112
- if (hosts.length === 0)
113
- return "empty";
114
- if (warnings.length > 0)
115
- return "degraded";
116
- if (hosts.some((host) => host.status === "degraded" || host.status === "quarantined")) {
117
- return "degraded";
118
- }
119
- const onlineHostCount = hosts.filter((host) => REMOTE_HOST_STATUS_ONLINE.has(host.status)).length;
120
- return onlineHostCount > 0 ? "ready" : "degraded";
121
- }
122
- function buildRemoteFleetSummary(input) {
123
- const warnings = input.fleet?.warnings ?? [];
124
- const manifestCount = input.fleet?.manifestCount ?? 0;
125
- const onlineHostCount = input.hosts.filter((host) => REMOTE_HOST_STATUS_ONLINE.has(host.status)).length;
126
- return {
127
- updatedAt: input.updatedAt,
128
- status: deriveRemoteFleetStatus(input.hosts, warnings),
129
- manifestCount,
130
- hostCount: input.hosts.length,
131
- onlineHostCount,
132
- hosts: [...input.hosts].sort((left, right) => left.name.localeCompare(right.name)),
133
- warnings
134
- };
135
- }
136
- function toRunMode(interactionMode) {
137
- return interactionMode === "plan" ? "supervised" : "interactive";
138
- }
139
- function mapLegacySessionStatusToRunStatus(status) {
140
- switch (status) {
141
- case "starting":
142
- return "preparing";
143
- case "running":
144
- return "running";
145
- case "ready":
146
- return "completed";
147
- case "interrupted":
148
- return "paused";
149
- case "error":
150
- return "failed";
151
- case "stopped":
152
- return "cancelled";
153
- default:
154
- return "created";
155
- }
156
- }
157
- function mapLegacySessionStatusToRuntimeStatus(status) {
158
- switch (status) {
159
- case "starting":
160
- return "starting";
161
- case "running":
162
- return "running";
163
- case "interrupted":
164
- return "interrupted";
165
- case "error":
166
- return "failed";
167
- default:
168
- return "exited";
169
- }
170
- }
171
- function mapTaskStatusFromRunStatus(status, fallback) {
172
- if (fallback === "blocked" || fallback === "cancelled" || fallback === "completed" || fallback === "closed" || fallback === "unknown") {
173
- return fallback === "closed" ? "completed" : fallback;
174
- }
175
- switch (status) {
176
- case "created":
177
- return fallback;
178
- case "queued":
179
- return "queued";
180
- case "preparing":
181
- case "running":
182
- case "waiting-approval":
183
- case "waiting-user-input":
184
- case "validating":
185
- case "paused":
186
- return "in_progress";
187
- case "reviewing":
188
- return "under_review";
189
- case "completed":
190
- return "completed";
191
- case "failed":
192
- return "ready";
193
- case "cancelled":
194
- return "cancelled";
195
- }
196
- }
197
- function withSnapshotMetadata(snapshot, event, next) {
198
- return {
199
- ...snapshot,
200
- ...next,
201
- snapshotSequence: Math.max(snapshot.snapshotSequence, event.sequence),
202
- updatedAt: maxIsoDate(snapshot.updatedAt, event.createdAt)
203
- };
204
- }
205
- function ensureConversation(snapshot, run) {
206
- const conversationId = conversationIdFromRunId(run.id);
207
- if (snapshot.conversations.some((conversation) => conversation.id === conversationId)) {
208
- return snapshot;
209
- }
210
- return {
211
- ...snapshot,
212
- conversations: [
213
- ...snapshot.conversations,
214
- {
215
- id: conversationId,
216
- runId: run.id,
217
- title: run.title,
218
- createdAt: run.createdAt,
219
- updatedAt: run.updatedAt
220
- }
221
- ]
222
- };
223
- }
224
- function updateTaskFromRun(snapshot, run) {
225
- if (!run.taskId) {
226
- return snapshot;
227
- }
228
- return {
229
- ...snapshot,
230
- tasks: patchById(snapshot.tasks, run.taskId, (task) => ({
231
- ...task,
232
- status: mapTaskStatusFromRunStatus(run.status, task.status),
233
- updatedAt: maxIsoDate(task.updatedAt, run.updatedAt)
234
- }))
235
- };
236
- }
237
- function applyRun(snapshot, run) {
238
- const withConversation = ensureConversation(snapshot, run);
239
- const nextRuns = upsertById(withConversation.runs, run);
240
- return updateTaskFromRun({ ...withConversation, runs: nextRuns }, run);
241
- }
242
- function applyRuntime(snapshot, runtime) {
243
- return {
244
- ...snapshot,
245
- runtimes: upsertById(snapshot.runtimes, runtime)
246
- };
247
- }
248
- function applyWorktree(snapshot, worktree) {
249
- return {
250
- ...snapshot,
251
- worktrees: upsertById(snapshot.worktrees, worktree)
252
- };
253
- }
254
- function countPendingApprovals(approvals, runId) {
255
- return approvals.filter((approval) => approval.runId === runId && approval.status === "pending").length;
256
- }
257
- function countPendingUserInputs(userInputs, actions, runId) {
258
- const persistedCount = (userInputs ?? []).filter((request) => request.runId === runId && request.status === "pending").length;
259
- if (persistedCount > 0) {
260
- return persistedCount;
261
- }
262
- const openRequestIds = new Set;
263
- for (const action of actions) {
264
- if (action.runId !== runId || !isRecord(action.payload)) {
265
- continue;
266
- }
267
- const requestId = readString(action.payload, "requestId");
268
- if (!requestId) {
269
- continue;
270
- }
271
- if (action.actionType === "user-input.requested") {
272
- openRequestIds.add(requestId);
273
- }
274
- if (action.actionType === "user-input.resolved") {
275
- openRequestIds.delete(requestId);
276
- }
277
- }
278
- return openRequestIds.size;
279
- }
280
- function reconcileRunCounts(snapshot, runId, statusOverride) {
281
- return {
282
- ...snapshot,
283
- runs: patchById(snapshot.runs, runId, (run) => {
284
- const pendingApprovalCount = countPendingApprovals(snapshot.approvals, runId);
285
- const pendingUserInputCount = countPendingUserInputs(snapshot.userInputs, snapshot.actions, runId);
286
- const nextStatus = statusOverride ?? (pendingApprovalCount > 0 ? "waiting-approval" : pendingUserInputCount > 0 ? "waiting-user-input" : run.status === "waiting-approval" || run.status === "waiting-user-input" ? "running" : run.status);
287
- return {
288
- ...run,
289
- pendingApprovalCount,
290
- pendingUserInputCount,
291
- status: nextStatus
292
- };
293
- })
294
- };
295
- }
296
- function applyApprovalActivity(approvals, runId, action) {
297
- if (!isRecord(action.payload)) {
298
- return approvals.slice();
299
- }
300
- const requestId = readString(action.payload, "requestId");
301
- if (!requestId) {
302
- return approvals.slice();
303
- }
304
- if (action.actionType === "approval.requested") {
305
- const requestKind = readString(action.payload, "requestKind") ?? "command";
306
- return upsertById(approvals, {
307
- id: requestId,
308
- runId,
309
- actionId: action.id,
310
- requestKind,
311
- status: "pending",
312
- payload: action.payload,
313
- createdAt: action.startedAt,
314
- resolvedAt: null
315
- });
316
- }
317
- const shouldResolve = action.actionType === "approval.resolved" || action.actionType === "provider.approval.respond.failed" && ((readString(action.payload, "detail") ?? "").includes("Unknown pending permission request") || (readString(action.payload, "message") ?? "").includes("Unknown pending permission request"));
318
- if (!shouldResolve) {
319
- return approvals.slice();
320
- }
321
- return approvals.map((approval) => approval.id === requestId ? {
322
- ...approval,
323
- status: "resolved",
324
- resolvedAt: action.completedAt ?? action.startedAt
325
- } : approval);
326
- }
327
- function makeRuntimeFromRun(run, occurredAt) {
328
- return {
329
- id: run.activeRuntimeId ?? runtimeIdFromRunId(run.id),
330
- workspaceId: run.workspaceId,
331
- runId: run.id,
332
- adapterKind: run.runtimeAdapter,
333
- executionTarget: run.executionTarget ?? "local",
334
- remoteHostId: run.remoteHostId ?? null,
335
- status: run.status === "failed" ? "failed" : run.status === "paused" ? "interrupted" : "starting",
336
- sandboxMode: "danger-full-access",
337
- isolationMode: run.worktreePath ? "worktree" : "env",
338
- workspaceDir: run.worktreePath,
339
- homeDir: null,
340
- tmpDir: null,
341
- cacheDir: null,
342
- logsDir: null,
343
- stateDir: null,
344
- sessionDir: null,
345
- sessionLogPath: null,
346
- pid: null,
347
- startedAt: run.startedAt ?? occurredAt,
348
- updatedAt: occurredAt,
349
- exitedAt: run.completedAt
350
- };
351
- }
352
- function applySyntheticRuntimePreparation(snapshot, event) {
353
- if (!isRecord(event.payload)) {
354
- return { status: "ignored", snapshot };
355
- }
356
- const runId = readString(event.payload, "runId") ?? event.aggregateId;
357
- const workspaceId = readString(event.payload, "workspaceId");
358
- const taskId = readString(event.payload, "taskId") ?? null;
359
- const workspaceDir = readNullableString(event.payload, "workspaceDir");
360
- const homeDir = readNullableString(event.payload, "homeDir");
361
- const tmpDir = readNullableString(event.payload, "tmpDir");
362
- const cacheDir = readNullableString(event.payload, "cacheDir");
363
- const branchName = readString(event.payload, "taskExternalId") ?? snapshot.runs.find((run) => run.id === runId)?.branch ?? "task";
364
- const failed = event.type.endsWith(".failed");
365
- const finished = event.type.endsWith(".finished");
366
- const existingRun = snapshot.runs.find((run) => run.id === runId);
367
- if (!existingRun || !workspaceId) {
368
- return { status: "ignored", snapshot };
369
- }
370
- const runtimeRunId = asRunId(runId);
371
- const nextTaskId = taskId ? asTaskId(taskId) : null;
372
- const nextWorkspaceId = asWorkspaceId(workspaceId);
373
- const nextRun = {
374
- ...existingRun,
375
- taskId: existingRun.taskId ?? nextTaskId,
376
- runKind: existingRun.runKind === "adhoc" && nextTaskId ? "task" : existingRun.runKind,
377
- runtimeAdapter: "rig-native",
378
- initialPrompt: existingRun.initialPrompt ?? null,
379
- executionTarget: existingRun.executionTarget ?? "local",
380
- remoteHostId: existingRun.remoteHostId ?? null,
381
- activeRuntimeId: existingRun.activeRuntimeId ?? runtimeIdFromRunId(runtimeRunId),
382
- worktreePath: workspaceDir ?? existingRun.worktreePath,
383
- status: failed ? "failed" : finished ? "preparing" : "preparing",
384
- errorText: failed ? readString(event.payload, "message") ?? existingRun.errorText : existingRun.errorText,
385
- updatedAt: event.createdAt,
386
- completedAt: failed ? event.createdAt : existingRun.completedAt
387
- };
388
- const runtimeBase = snapshot.runtimes.find((runtime) => runtime.runId === runId) ?? makeRuntimeFromRun(nextRun, event.createdAt);
389
- const nextRuntime = {
390
- ...runtimeBase,
391
- workspaceId: nextWorkspaceId,
392
- runId: runtimeRunId,
393
- adapterKind: "rig-native",
394
- executionTarget: existingRun.executionTarget ?? "local",
395
- remoteHostId: existingRun.remoteHostId ?? null,
396
- status: failed ? "failed" : finished ? "prepared" : "starting",
397
- isolationMode: "worktree",
398
- workspaceDir: workspaceDir ?? runtimeBase.workspaceDir,
399
- homeDir: homeDir ?? runtimeBase.homeDir,
400
- tmpDir: tmpDir ?? runtimeBase.tmpDir,
401
- cacheDir: cacheDir ?? runtimeBase.cacheDir,
402
- updatedAt: event.createdAt,
403
- exitedAt: failed ? event.createdAt : runtimeBase.exitedAt
404
- };
405
- let nextSnapshot = applyRun(snapshot, nextRun);
406
- nextSnapshot = applyRuntime(nextSnapshot, nextRuntime);
407
- if (workspaceDir) {
408
- nextSnapshot = applyWorktree(nextSnapshot, {
409
- id: worktreeIdFromRunId(runtimeRunId),
410
- workspaceId: nextWorkspaceId,
411
- runId: runtimeRunId,
412
- taskId: nextRun.taskId,
413
- branchName,
414
- path: workspaceDir,
415
- status: failed ? "failed" : finished ? "prepared" : "preparing",
416
- createdAt: existingRun.createdAt,
417
- cleanedAt: null
418
- });
419
- }
420
- return {
421
- status: "applied",
422
- snapshot: withSnapshotMetadata(nextSnapshot, event, {})
423
- };
424
- }
425
- function applySyntheticRuntimePrepared(snapshot, event) {
426
- if (!isRecord(event.payload)) {
427
- return { status: "ignored", snapshot };
428
- }
429
- const runId = readString(event.payload, "runId") ?? event.aggregateId;
430
- const workspaceId = readString(event.payload, "workspaceId");
431
- const worktreePath = readString(event.payload, "worktreePath");
432
- const existingRun = snapshot.runs.find((run) => run.id === runId);
433
- if (!existingRun || !workspaceId || !worktreePath) {
434
- return { status: "ignored", snapshot };
435
- }
436
- const runtimeRunId = asRunId(runId);
437
- const nextWorkspaceId = asWorkspaceId(workspaceId);
438
- let nextSnapshot = applyRuntime(snapshot, {
439
- ...snapshot.runtimes.find((runtime) => runtime.runId === runId) ?? makeRuntimeFromRun(existingRun, event.createdAt),
440
- workspaceId: nextWorkspaceId,
441
- runId: runtimeRunId,
442
- adapterKind: "rig-native",
443
- executionTarget: existingRun.executionTarget ?? "local",
444
- remoteHostId: existingRun.remoteHostId ?? null,
445
- status: "prepared",
446
- isolationMode: "worktree",
447
- workspaceDir: worktreePath,
448
- updatedAt: event.createdAt
449
- });
450
- nextSnapshot = applyWorktree(nextSnapshot, {
451
- id: worktreeIdFromRunId(runtimeRunId),
452
- workspaceId: nextWorkspaceId,
453
- runId: runtimeRunId,
454
- taskId: existingRun.taskId,
455
- branchName: existingRun.branch ?? "task",
456
- path: worktreePath,
457
- status: "prepared",
458
- createdAt: existingRun.createdAt,
459
- cleanedAt: null
460
- });
461
- return {
462
- status: "applied",
463
- snapshot: withSnapshotMetadata(nextSnapshot, event, {})
464
- };
465
- }
466
- function applyLegacyProjectEvent(snapshot, event) {
467
- if (!isRecord(event.payload)) {
468
- return { status: "ignored", snapshot };
469
- }
470
- const payload = event.payload;
471
- if (event.type === "legacy.project.created") {
472
- const workspaceId = readString(payload, "projectId");
473
- const title = readString(payload, "title");
474
- const rootPath = readString(payload, "workspaceRoot");
475
- const createdAt = readString(payload, "createdAt");
476
- const updatedAt = readString(payload, "updatedAt");
477
- if (!workspaceId || !title || !rootPath || !createdAt || !updatedAt) {
478
- return { status: "ignored", snapshot };
479
- }
480
- const workspace = {
481
- id: asWorkspaceId(workspaceId),
482
- title,
483
- rootPath,
484
- sourceKind: "native",
485
- defaultRuntimeAdapter: "codex-app-server",
486
- defaultModel: readNullableString(payload, "defaultModel") ?? null,
487
- createdAt,
488
- updatedAt
489
- };
490
- return {
491
- status: "applied",
492
- snapshot: withSnapshotMetadata(snapshot, event, {
493
- workspaces: upsertById(snapshot.workspaces, workspace)
494
- })
495
- };
496
- }
497
- if (event.type === "legacy.project.meta-updated") {
498
- const workspaceId = readString(payload, "projectId");
499
- if (!workspaceId) {
500
- return { status: "ignored", snapshot };
501
- }
502
- return {
503
- status: "applied",
504
- snapshot: withSnapshotMetadata(snapshot, event, {
505
- workspaces: patchById(snapshot.workspaces, workspaceId, (workspace) => ({
506
- ...workspace,
507
- title: readString(payload, "title") ?? workspace.title,
508
- rootPath: readString(payload, "workspaceRoot") ?? workspace.rootPath,
509
- defaultModel: readNullableString(payload, "defaultModel") ?? workspace.defaultModel,
510
- updatedAt: readString(payload, "updatedAt") ?? event.createdAt
511
- }))
512
- })
513
- };
514
- }
515
- if (event.type === "legacy.project.deleted") {
516
- const workspaceId = readString(payload, "projectId");
517
- if (!workspaceId) {
518
- return { status: "ignored", snapshot };
519
- }
520
- return {
521
- status: "applied",
522
- snapshot: withSnapshotMetadata(snapshot, event, {
523
- workspaces: removeById(snapshot.workspaces, workspaceId),
524
- graphs: snapshot.graphs.filter((graph) => graph.workspaceId !== workspaceId),
525
- tasks: snapshot.tasks.filter((task) => task.workspaceId !== workspaceId),
526
- runs: snapshot.runs.filter((run) => run.workspaceId !== workspaceId),
527
- runtimes: snapshot.runtimes.filter((runtime) => runtime.workspaceId !== workspaceId),
528
- conversations: snapshot.conversations.filter((conversation) => {
529
- const run = snapshot.runs.find((candidate) => candidate.id === conversation.runId);
530
- return run?.workspaceId !== workspaceId;
531
- }),
532
- messages: snapshot.messages.filter((message) => {
533
- const conversation = snapshot.conversations.find((candidate) => candidate.id === message.conversationId);
534
- const run = snapshot.runs.find((candidate) => candidate.id === conversation?.runId);
535
- return run?.workspaceId !== workspaceId;
536
- }),
537
- actions: snapshot.actions.filter((action) => {
538
- const run = snapshot.runs.find((candidate) => candidate.id === action.runId);
539
- return run?.workspaceId !== workspaceId;
540
- }),
541
- approvals: snapshot.approvals.filter((approval) => {
542
- const run = snapshot.runs.find((candidate) => candidate.id === approval.runId);
543
- return run?.workspaceId !== workspaceId;
544
- }),
545
- queue: snapshot.queue.filter((entry) => {
546
- const task = snapshot.tasks.find((candidate) => candidate.id === entry.taskId);
547
- return task?.workspaceId !== workspaceId;
548
- }),
549
- worktrees: snapshot.worktrees.filter((worktree) => worktree.workspaceId !== workspaceId)
550
- })
551
- };
552
- }
553
- return { status: "ignored", snapshot };
554
- }
555
- function applyLegacyThreadEvent(snapshot, event) {
556
- if (!isRecord(event.payload)) {
557
- return { status: "ignored", snapshot };
558
- }
559
- const payload = event.payload;
560
- if (event.type === "legacy.thread.created") {
561
- const runId = readString(payload, "threadId");
562
- const workspaceId = readString(payload, "projectId");
563
- const title = readString(payload, "title");
564
- const model = readString(payload, "model");
565
- const createdAt = readString(payload, "createdAt");
566
- const updatedAt = readString(payload, "updatedAt");
567
- if (!runId || !workspaceId || !title || !model || !createdAt || !updatedAt) {
568
- return { status: "ignored", snapshot };
569
- }
570
- const run = {
571
- id: asRunId(runId),
572
- workspaceId: asWorkspaceId(workspaceId),
573
- taskId: null,
574
- title,
575
- runKind: "adhoc",
576
- mode: toRunMode(readString(payload, "interactionMode")),
577
- runtimeMode: "full-access",
578
- interactionMode: "default",
579
- status: "created",
580
- runtimeAdapter: "codex-app-server",
581
- model,
582
- initialPrompt: null,
583
- activeRuntimeId: null,
584
- latestMessageId: null,
585
- pendingApprovalCount: 0,
586
- pendingUserInputCount: 0,
587
- branch: readNullableString(payload, "branch") ?? null,
588
- worktreePath: readNullableString(payload, "worktreePath") ?? null,
589
- errorText: null,
590
- createdAt,
591
- updatedAt,
592
- startedAt: null,
593
- completedAt: null
594
- };
595
- let nextSnapshot = applyRun(snapshot, run);
596
- if (run.branch && run.worktreePath) {
597
- nextSnapshot = applyWorktree(nextSnapshot, {
598
- id: worktreeIdFromRunId(asRunId(runId)),
599
- workspaceId: asWorkspaceId(workspaceId),
600
- runId: asRunId(runId),
601
- taskId: null,
602
- branchName: run.branch,
603
- path: run.worktreePath,
604
- status: "active",
605
- createdAt,
606
- cleanedAt: null
607
- });
608
- }
609
- return {
610
- status: "applied",
611
- snapshot: withSnapshotMetadata(nextSnapshot, event, {})
612
- };
613
- }
614
- if (event.type === "legacy.thread.deleted") {
615
- const runId = readString(payload, "threadId");
616
- if (!runId) {
617
- return { status: "ignored", snapshot };
618
- }
619
- return {
620
- status: "applied",
621
- snapshot: withSnapshotMetadata(snapshot, event, {
622
- runs: removeById(snapshot.runs, runId),
623
- runtimes: snapshot.runtimes.filter((runtime) => runtime.runId !== runId),
624
- conversations: snapshot.conversations.filter((conversation) => conversation.runId !== runId),
625
- messages: snapshot.messages.filter((message) => message.conversationId !== runId),
626
- actions: snapshot.actions.filter((action) => action.runId !== runId),
627
- approvals: snapshot.approvals.filter((approval) => approval.runId !== runId),
628
- worktrees: snapshot.worktrees.filter((worktree) => worktree.runId !== runId)
629
- })
630
- };
631
- }
632
- if (event.type === "legacy.thread.meta-updated") {
633
- const runId = readString(payload, "threadId");
634
- if (!runId) {
635
- return { status: "ignored", snapshot };
636
- }
637
- let nextSnapshot = {
638
- ...snapshot,
639
- runs: patchById(snapshot.runs, runId, (run2) => ({
640
- ...run2,
641
- title: readString(payload, "title") ?? run2.title,
642
- model: readString(payload, "model") ?? run2.model,
643
- branch: readNullableString(payload, "branch") === undefined ? run2.branch : readNullableString(payload, "branch") ?? null,
644
- worktreePath: readNullableString(payload, "worktreePath") === undefined ? run2.worktreePath : readNullableString(payload, "worktreePath") ?? null,
645
- updatedAt: readString(payload, "updatedAt") ?? event.createdAt
646
- })),
647
- conversations: patchById(snapshot.conversations, runId, (conversation) => ({
648
- ...conversation,
649
- title: readString(payload, "title") ?? conversation.title,
650
- updatedAt: readString(payload, "updatedAt") ?? event.createdAt
651
- }))
652
- };
653
- const run = nextSnapshot.runs.find((candidate) => candidate.id === runId);
654
- if (run?.worktreePath && run.branch) {
655
- nextSnapshot = applyWorktree(nextSnapshot, {
656
- id: worktreeIdFromRunId(run.id),
657
- workspaceId: run.workspaceId,
658
- runId: run.id,
659
- taskId: run.taskId,
660
- branchName: run.branch,
661
- path: run.worktreePath,
662
- status: "active",
663
- createdAt: run.createdAt,
664
- cleanedAt: null
665
- });
666
- }
667
- if (run && run.worktreePath === null) {
668
- nextSnapshot = {
669
- ...nextSnapshot,
670
- worktrees: nextSnapshot.worktrees.filter((worktree) => worktree.runId !== runId)
671
- };
672
- }
673
- return {
674
- status: "applied",
675
- snapshot: withSnapshotMetadata(nextSnapshot, event, {})
676
- };
677
- }
678
- if (event.type === "legacy.thread.interaction-mode-set") {
679
- const runId = readString(payload, "threadId");
680
- if (!runId) {
681
- return { status: "ignored", snapshot };
682
- }
683
- return {
684
- status: "applied",
685
- snapshot: withSnapshotMetadata(snapshot, event, {
686
- runs: patchById(snapshot.runs, runId, (run) => ({
687
- ...run,
688
- mode: toRunMode(readString(payload, "interactionMode")),
689
- updatedAt: readString(payload, "updatedAt") ?? event.createdAt
690
- }))
691
- })
692
- };
693
- }
694
- if (event.type === "legacy.thread.runtime-mode-set") {
695
- const runId = readString(payload, "threadId");
696
- if (!runId) {
697
- return { status: "ignored", snapshot };
698
- }
699
- const runtimeMode = readString(payload, "runtimeMode");
700
- return {
701
- status: "applied",
702
- snapshot: withSnapshotMetadata(snapshot, event, {
703
- runtimes: patchById(snapshot.runtimes, runId, (runtime) => ({
704
- ...runtime,
705
- sandboxMode: runtimeMode === "approval-required" ? "workspace-write" : "danger-full-access",
706
- updatedAt: readString(payload, "updatedAt") ?? event.createdAt
707
- }))
708
- })
709
- };
710
- }
711
- if (event.type === "legacy.thread.message-sent") {
712
- const runId = readString(payload, "threadId");
713
- const messageId = readString(payload, "messageId");
714
- const role = readString(payload, "role");
715
- const text = readString(payload, "text");
716
- const createdAt = readString(payload, "createdAt");
717
- const updatedAt = readString(payload, "updatedAt");
718
- if (!runId || !messageId || !role || text === undefined || !createdAt || !updatedAt) {
719
- return { status: "ignored", snapshot };
720
- }
721
- const attachments = Array.isArray(payload.attachments) ? payload.attachments : [];
722
- const streaming = payload.streaming === true;
723
- const message = {
724
- id: asMessageId(messageId),
725
- conversationId: conversationIdFromRunId(asRunId(runId)),
726
- role: role === "assistant" || role === "system" ? role : "user",
727
- text,
728
- attachments,
729
- state: streaming ? "streaming" : "completed",
730
- createdAt,
731
- completedAt: streaming ? null : updatedAt
732
- };
733
- const existingRun = snapshot.runs.find((run) => run.id === runId);
734
- if (!existingRun) {
735
- return { status: "ignored", snapshot };
736
- }
737
- return {
738
- status: "applied",
739
- snapshot: withSnapshotMetadata(ensureConversation({
740
- ...snapshot,
741
- messages: upsertById(snapshot.messages, message),
742
- runs: patchById(snapshot.runs, runId, (run) => ({
743
- ...run,
744
- latestMessageId: asMessageId(messageId),
745
- updatedAt
746
- }))
747
- }, existingRun), event, {})
748
- };
749
- }
750
- if (event.type === "legacy.thread.session-set") {
751
- const runId = readString(event.payload, "threadId");
752
- const session = readRecord(event.payload, "session");
753
- if (!runId || !session) {
754
- return { status: "ignored", snapshot };
755
- }
756
- const existingRun = snapshot.runs.find((run) => run.id === runId);
757
- if (!existingRun) {
758
- return { status: "ignored", snapshot };
759
- }
760
- const sessionUpdatedAt = readString(session, "updatedAt") ?? event.createdAt;
761
- const providerName = readNullableString(session, "providerName");
762
- const nextRun = {
763
- ...existingRun,
764
- runtimeAdapter: providerName ?? existingRun.runtimeAdapter,
765
- initialPrompt: existingRun.initialPrompt ?? null,
766
- activeRuntimeId: runtimeIdFromRunId(asRunId(runId)),
767
- status: mapLegacySessionStatusToRunStatus(readString(session, "status")),
768
- errorText: readNullableString(session, "lastError") ?? existingRun.errorText,
769
- updatedAt: sessionUpdatedAt,
770
- completedAt: readString(session, "status") === "ready" || readString(session, "status") === "stopped" || readString(session, "status") === "error" ? sessionUpdatedAt : existingRun.completedAt
771
- };
772
- let nextSnapshot = applyRun(snapshot, nextRun);
773
- nextSnapshot = applyRuntime(nextSnapshot, {
774
- ...snapshot.runtimes.find((runtime) => runtime.runId === runId) ?? makeRuntimeFromRun(nextRun, sessionUpdatedAt),
775
- workspaceId: existingRun.workspaceId,
776
- runId: asRunId(runId),
777
- adapterKind: providerName ?? existingRun.runtimeAdapter,
778
- status: mapLegacySessionStatusToRuntimeStatus(readString(session, "status")),
779
- workspaceDir: existingRun.worktreePath,
780
- isolationMode: existingRun.worktreePath ? "worktree" : "env",
781
- updatedAt: sessionUpdatedAt,
782
- exitedAt: readString(session, "status") === "ready" || readString(session, "status") === "stopped" || readString(session, "status") === "error" ? sessionUpdatedAt : null
783
- });
784
- return {
785
- status: "applied",
786
- snapshot: withSnapshotMetadata(nextSnapshot, event, {})
787
- };
788
- }
789
- if (event.type === "legacy.thread.activity-appended") {
790
- const runId = readString(event.payload, "threadId");
791
- const activity = readRecord(event.payload, "activity");
792
- if (!runId || !activity) {
793
- return { status: "ignored", snapshot };
794
- }
795
- const actionId = readString(activity, "id");
796
- const actionType = readString(activity, "kind");
797
- const title = readString(activity, "summary");
798
- const startedAt = readString(activity, "createdAt");
799
- if (!actionId || !actionType || !title || !startedAt) {
800
- return { status: "ignored", snapshot };
801
- }
802
- const payload2 = readRecord(activity, "payload") ?? {};
803
- const detail = readString(payload2, "detail") ?? null;
804
- const action = {
805
- id: asActionId(actionId),
806
- runId: asRunId(runId),
807
- messageId: null,
808
- actionType,
809
- title,
810
- detail,
811
- state: "completed",
812
- payload: payload2,
813
- startedAt,
814
- completedAt: startedAt
815
- };
816
- let nextSnapshot = {
817
- ...snapshot,
818
- actions: upsertById(snapshot.actions, action),
819
- approvals: applyApprovalActivity(snapshot.approvals, asRunId(runId), action),
820
- runs: patchById(snapshot.runs, runId, (run) => ({
821
- ...run,
822
- updatedAt: maxIsoDate(run.updatedAt, startedAt),
823
- status: actionType === "engine.runtime.ready" ? "running" : actionType === "engine.runtime.failed" ? "failed" : run.status,
824
- errorText: actionType === "engine.runtime.failed" && detail ? detail : run.errorText,
825
- completedAt: actionType === "engine.runtime.failed" ? startedAt : run.completedAt
826
- }))
827
- };
828
- nextSnapshot = reconcileRunCounts(nextSnapshot, asRunId(runId));
829
- return {
830
- status: "applied",
831
- snapshot: withSnapshotMetadata(nextSnapshot, event, {})
832
- };
833
- }
834
- if (event.type === "legacy.thread.reverted") {
835
- return { status: "requires-resync", snapshot };
836
- }
837
- return { status: "ignored", snapshot };
838
- }
839
- function applyEngineEvent(snapshot, event) {
840
- if (event.sequence <= snapshot.snapshotSequence) {
841
- return { status: "ignored", snapshot };
842
- }
843
- if (event.sequence > snapshot.snapshotSequence + 1) {
844
- return { status: "requires-resync", snapshot };
845
- }
846
- const base = {
847
- ...snapshot,
848
- snapshotSequence: event.sequence,
849
- updatedAt: event.createdAt
850
- };
851
- const payload = event.payload && typeof event.payload === "object" ? event.payload : {};
852
- switch (event.type) {
853
- case "WorkspaceRegistered":
854
- case "RigWorkspaceImported": {
855
- const workspace = {
856
- id: payload.workspaceId,
857
- title: payload.title,
858
- rootPath: payload.rootPath,
859
- sourceKind: payload.sourceKind,
860
- defaultModel: payload.defaultModel ?? null,
861
- topology: undefined,
862
- remoteFleet: undefined,
863
- serviceFabric: undefined,
864
- createdAt: payload.createdAt,
865
- updatedAt: payload.createdAt
866
- };
867
- return {
868
- status: "applied",
869
- snapshot: {
870
- ...base,
871
- workspaces: upsertById(base.workspaces, workspace)
872
- }
873
- };
874
- }
875
- case "RigStateHydrated": {
876
- const workspaceRunIds = new Set([
877
- ...base.runs.filter((run) => run.workspaceId === payload.workspaceId).map((run) => run.id),
878
- ...(payload.runs ?? []).map((run) => run.id)
879
- ]);
880
- const withoutWorkspaceRunData = (items) => items.filter((item) => !workspaceRunIds.has(item.runId));
881
- const workspaces = payload.rootPath ? patchById(base.workspaces, payload.workspaceId, (workspace) => ({
882
- ...workspace,
883
- rootPath: payload.rootPath,
884
- updatedAt: payload.createdAt
885
- })) : base.workspaces;
886
- return {
887
- status: "applied",
888
- snapshot: {
889
- ...base,
890
- workspaces,
891
- graphs: upsertById(base.graphs, payload.graph),
892
- tasks: replaceWorkspaceSlice(base.tasks, payload.workspaceId, payload.tasks ?? []),
893
- runs: replaceWorkspaceSlice(base.runs, payload.workspaceId, payload.runs ?? []),
894
- runtimes: replaceWorkspaceSlice(base.runtimes, payload.workspaceId, payload.runtimes ?? []),
895
- actions: mergeById(withoutWorkspaceRunData(base.actions), payload.actions ?? []),
896
- logs: mergeById(withoutWorkspaceRunData(base.logs), payload.logs ?? []),
897
- userInputs: (base.userInputs ?? []).filter((request) => !workspaceRunIds.has(request.runId)),
898
- validations: mergeById(withoutWorkspaceRunData(base.validations), payload.validations ?? []),
899
- reviews: mergeById(withoutWorkspaceRunData(base.reviews), payload.reviews ?? []),
900
- artifacts: mergeById(withoutWorkspaceRunData(base.artifacts), payload.artifacts ?? []),
901
- policyDecisions: mergeById(withoutWorkspaceRunData(base.policyDecisions), payload.policyDecisions ?? []),
902
- queue: [...payload.queue ?? []]
903
- }
904
- };
905
- }
906
- case "WorkspaceTopologyCompiled": {
907
- return {
908
- status: "applied",
909
- snapshot: {
910
- ...base,
911
- workspaces: patchById(base.workspaces, payload.workspaceId, (workspace) => ({
912
- ...workspace,
913
- rootPath: payload.rootPath ?? workspace.rootPath,
914
- topology: payload.topology,
915
- updatedAt: payload.createdAt
916
- }))
917
- }
918
- };
919
- }
920
- case "WorkspaceRemoteFleetSynced": {
921
- return {
922
- status: "applied",
923
- snapshot: {
924
- ...base,
925
- workspaces: patchById(base.workspaces, payload.workspaceId, (workspace) => ({
926
- ...workspace,
927
- rootPath: payload.rootPath ?? workspace.rootPath,
928
- remoteFleet: payload.remoteFleet,
929
- updatedAt: payload.createdAt
930
- }))
931
- }
932
- };
933
- }
934
- case "WorkspaceServiceFabricSynced": {
935
- return {
936
- status: "applied",
937
- snapshot: {
938
- ...base,
939
- workspaces: patchById(base.workspaces, payload.workspaceId, (workspace) => ({
940
- ...workspace,
941
- rootPath: payload.rootPath ?? workspace.rootPath,
942
- serviceFabric: payload.serviceFabric,
943
- updatedAt: payload.createdAt
944
- }))
945
- }
946
- };
947
- }
948
- case "WorkspaceRemoteHostRegistered": {
949
- return {
950
- status: "applied",
951
- snapshot: {
952
- ...base,
953
- workspaces: patchById(base.workspaces, payload.workspaceId, (workspace) => {
954
- const withoutExisting = (workspace.remoteFleet?.hosts ?? []).filter((host) => host.id !== payload.host.id);
955
- return {
956
- ...workspace,
957
- remoteFleet: buildRemoteFleetSummary({
958
- fleet: workspace.remoteFleet,
959
- hosts: [...withoutExisting, payload.host],
960
- updatedAt: payload.createdAt
961
- }),
962
- updatedAt: payload.createdAt
963
- };
964
- })
965
- }
966
- };
967
- }
968
- case "WorkspaceRemoteHostStatusUpdated": {
969
- return {
970
- status: "applied",
971
- snapshot: {
972
- ...base,
973
- workspaces: patchById(base.workspaces, payload.workspaceId, (workspace) => {
974
- const fleet = workspace.remoteFleet;
975
- if (!fleet) {
976
- return {
977
- ...workspace,
978
- updatedAt: payload.createdAt
979
- };
980
- }
981
- const hosts = fleet.hosts.map((host) => host.id !== payload.hostId ? host : {
982
- ...host,
983
- status: payload.status,
984
- currentLeaseCount: typeof payload.currentLeaseCount === "number" ? payload.currentLeaseCount : host.currentLeaseCount,
985
- lastHeartbeatAt: payload.lastHeartbeatAt ?? host.lastHeartbeatAt
986
- });
987
- return {
988
- ...workspace,
989
- remoteFleet: buildRemoteFleetSummary({
990
- fleet,
991
- hosts,
992
- updatedAt: payload.createdAt
993
- }),
994
- updatedAt: payload.createdAt
995
- };
996
- })
997
- }
998
- };
999
- }
1000
- case "RunCreated": {
1001
- const run = {
1002
- id: payload.runId,
1003
- workspaceId: payload.workspaceId,
1004
- taskId: payload.taskId ?? null,
1005
- title: payload.title,
1006
- runKind: payload.runKind,
1007
- mode: payload.mode,
1008
- runtimeMode: payload.runtimeMode,
1009
- interactionMode: payload.interactionMode,
1010
- status: "created",
1011
- runtimeAdapter: payload.runtimeAdapter,
1012
- model: payload.model ?? null,
1013
- initialPrompt: payload.initialPrompt ?? null,
1014
- executionTarget: payload.executionTarget ?? (payload.remoteHostId ? "remote" : "local"),
1015
- remoteHostId: payload.remoteHostId ?? null,
1016
- remoteLeaseId: null,
1017
- remoteLeaseClaimedAt: null,
1018
- activeRuntimeId: null,
1019
- latestMessageId: null,
1020
- pendingApprovalCount: 0,
1021
- pendingUserInputCount: 0,
1022
- branch: null,
1023
- worktreePath: null,
1024
- errorText: null,
1025
- createdAt: payload.createdAt,
1026
- updatedAt: payload.createdAt,
1027
- startedAt: null,
1028
- completedAt: null
1029
- };
1030
- return {
1031
- status: "applied",
1032
- snapshot: { ...base, runs: upsertById(base.runs, run) }
1033
- };
1034
- }
1035
- case "RunInterrupted":
1036
- case "RunCancelled":
1037
- return {
1038
- status: "applied",
1039
- snapshot: {
1040
- ...base,
1041
- runs: patchById(base.runs, payload.runId, (run) => ({
1042
- ...run,
1043
- status: "cancelled",
1044
- updatedAt: payload.createdAt,
1045
- completedAt: payload.createdAt
1046
- }))
1047
- }
1048
- };
1049
- case "RunCompleted":
1050
- return {
1051
- status: "applied",
1052
- snapshot: {
1053
- ...base,
1054
- runs: patchById(base.runs, payload.runId, (run) => ({
1055
- ...run,
1056
- status: "completed",
1057
- updatedAt: payload.createdAt,
1058
- completedAt: payload.createdAt
1059
- }))
1060
- }
1061
- };
1062
- case "RunStatusSet":
1063
- return {
1064
- status: "applied",
1065
- snapshot: {
1066
- ...base,
1067
- runs: patchById(base.runs, payload.runId, (run) => ({
1068
- ...run,
1069
- status: payload.status,
1070
- updatedAt: payload.createdAt,
1071
- completedAt: null
1072
- }))
1073
- }
1074
- };
1075
- case "RunFailed":
1076
- return {
1077
- status: "applied",
1078
- snapshot: {
1079
- ...base,
1080
- runs: patchById(base.runs, payload.runId, (run) => ({
1081
- ...run,
1082
- status: "failed",
1083
- errorText: payload.errorText ?? null,
1084
- updatedAt: payload.createdAt,
1085
- completedAt: payload.createdAt
1086
- }))
1087
- }
1088
- };
1089
- case "RuntimeModeSet":
1090
- return {
1091
- status: "applied",
1092
- snapshot: {
1093
- ...base,
1094
- runs: patchById(base.runs, payload.runId, (run) => ({
1095
- ...run,
1096
- runtimeMode: payload.runtimeMode,
1097
- updatedAt: payload.createdAt
1098
- }))
1099
- }
1100
- };
1101
- case "InteractionModeSet":
1102
- return {
1103
- status: "applied",
1104
- snapshot: {
1105
- ...base,
1106
- runs: patchById(base.runs, payload.runId, (run) => ({
1107
- ...run,
1108
- interactionMode: payload.interactionMode,
1109
- updatedAt: payload.createdAt
1110
- }))
1111
- }
1112
- };
1113
- case "ConversationAttached": {
1114
- const conversation = {
1115
- id: payload.conversationId,
1116
- runId: payload.runId,
1117
- title: payload.title,
1118
- createdAt: payload.createdAt,
1119
- updatedAt: payload.createdAt
1120
- };
1121
- return {
1122
- status: "applied",
1123
- snapshot: {
1124
- ...base,
1125
- conversations: upsertById(base.conversations, conversation)
1126
- }
1127
- };
1128
- }
1129
- case "MessageAppended": {
1130
- const conversation = base.conversations.find((item) => item.runId === payload.runId);
1131
- if (!conversation) {
1132
- return { status: "ignored", snapshot: base };
1133
- }
1134
- const conversationId = conversation.id;
1135
- const message = {
1136
- id: payload.messageId,
1137
- conversationId,
1138
- role: payload.role,
1139
- text: payload.text,
1140
- attachments: payload.attachments ?? [],
1141
- state: payload.state ?? "completed",
1142
- createdAt: payload.createdAt,
1143
- completedAt: payload.completedAt ?? payload.createdAt
1144
- };
1145
- return {
1146
- status: "applied",
1147
- snapshot: {
1148
- ...base,
1149
- messages: upsertById(base.messages, message),
1150
- runs: patchById(base.runs, payload.runId, (run) => ({
1151
- ...run,
1152
- latestMessageId: payload.messageId,
1153
- updatedAt: payload.createdAt
1154
- }))
1155
- }
1156
- };
1157
- }
1158
- case "ActionStarted": {
1159
- const action = {
1160
- id: payload.actionId,
1161
- runId: payload.runId,
1162
- messageId: payload.messageId ?? null,
1163
- actionType: payload.actionType,
1164
- title: payload.title,
1165
- detail: payload.detail ?? null,
1166
- state: payload.state ?? "running",
1167
- payload: payload.payload ?? null,
1168
- startedAt: payload.startedAt,
1169
- completedAt: null
1170
- };
1171
- return {
1172
- status: "applied",
1173
- snapshot: {
1174
- ...base,
1175
- actions: upsertById(base.actions, action)
1176
- }
1177
- };
1178
- }
1179
- case "ActionCompleted":
1180
- return {
1181
- status: "applied",
1182
- snapshot: {
1183
- ...base,
1184
- actions: patchById(base.actions, payload.actionId, (action) => ({
1185
- ...action,
1186
- state: payload.state,
1187
- detail: payload.detail ?? null,
1188
- payload: payload.payload,
1189
- completedAt: payload.completedAt
1190
- }))
1191
- }
1192
- };
1193
- case "RunLogAppended": {
1194
- const log = {
1195
- id: payload.logId,
1196
- runId: payload.runId,
1197
- title: payload.title,
1198
- detail: payload.detail ?? null,
1199
- tone: payload.tone,
1200
- status: payload.status ?? null,
1201
- payload: payload.payload ?? null,
1202
- createdAt: payload.createdAt
1203
- };
1204
- return {
1205
- status: "applied",
1206
- snapshot: {
1207
- ...base,
1208
- logs: upsertById(base.logs, log),
1209
- runs: patchById(base.runs, payload.runId, (run) => ({
1210
- ...run,
1211
- updatedAt: payload.createdAt
1212
- }))
1213
- }
1214
- };
1215
- }
1216
- case "ValidationRecorded":
1217
- return {
1218
- status: "applied",
1219
- snapshot: {
1220
- ...base,
1221
- validations: upsertById(base.validations, {
1222
- id: payload.id,
1223
- runId: payload.runId,
1224
- taskId: payload.taskId ?? null,
1225
- validatorKey: payload.validatorKey,
1226
- status: payload.status,
1227
- output: payload.output,
1228
- startedAt: payload.startedAt,
1229
- completedAt: payload.completedAt ?? null
1230
- })
1231
- }
1232
- };
1233
- case "ReviewRecorded":
1234
- return {
1235
- status: "applied",
1236
- snapshot: {
1237
- ...base,
1238
- reviews: upsertById(base.reviews, {
1239
- id: payload.id,
1240
- runId: payload.runId,
1241
- taskId: payload.taskId ?? null,
1242
- provider: payload.provider,
1243
- mode: payload.mode,
1244
- status: payload.status,
1245
- summary: payload.summary ?? null,
1246
- output: payload.output,
1247
- createdAt: payload.createdAt,
1248
- completedAt: payload.completedAt ?? null
1249
- })
1250
- }
1251
- };
1252
- case "ArtifactRegistered":
1253
- return {
1254
- status: "applied",
1255
- snapshot: {
1256
- ...base,
1257
- artifacts: upsertById(base.artifacts, {
1258
- id: payload.id,
1259
- runId: payload.runId,
1260
- taskId: payload.taskId ?? null,
1261
- kind: payload.kind,
1262
- label: payload.label,
1263
- path: payload.path ?? null,
1264
- url: payload.url ?? null,
1265
- metadata: payload.metadata ?? {},
1266
- createdAt: payload.createdAt
1267
- })
1268
- }
1269
- };
1270
- case "ApprovalRequested": {
1271
- const run = base.runs.find((item) => item.id === payload.runId);
1272
- const approval = {
1273
- id: payload.requestId,
1274
- runId: payload.runId,
1275
- actionId: payload.actionId ?? null,
1276
- requestKind: payload.requestKind,
1277
- status: "pending",
1278
- payload: payload.payload ?? null,
1279
- createdAt: payload.createdAt,
1280
- resolvedAt: null
1281
- };
1282
- return {
1283
- status: "applied",
1284
- snapshot: {
1285
- ...base,
1286
- approvals: upsertById(base.approvals, approval),
1287
- runs: patchById(base.runs, payload.runId, (item) => ({
1288
- ...item,
1289
- pendingApprovalCount: (run?.pendingApprovalCount ?? 0) + 1,
1290
- status: "waiting-approval",
1291
- updatedAt: payload.createdAt
1292
- }))
1293
- }
1294
- };
1295
- }
1296
- case "ApprovalResolved": {
1297
- const approval = base.approvals.find((item) => item.id === payload.requestId && item.runId === payload.runId);
1298
- if (!approval) {
1299
- return { status: "applied", snapshot: base };
1300
- }
1301
- const run = base.runs.find((item) => item.id === payload.runId);
1302
- const pendingApprovalCount = run ? Math.max(0, Number(run.pendingApprovalCount) - 1) : 0;
1303
- const nextStatus = run?.status === "waiting-approval" && pendingApprovalCount === 0 ? "running" : run?.status;
1304
- return {
1305
- status: "applied",
1306
- snapshot: {
1307
- ...base,
1308
- approvals: patchById(base.approvals, payload.requestId, (item) => ({
1309
- ...item,
1310
- status: "resolved",
1311
- resolvedAt: payload.createdAt
1312
- })),
1313
- runs: patchById(base.runs, payload.runId, (item) => ({
1314
- ...item,
1315
- pendingApprovalCount,
1316
- ...nextStatus ? { status: nextStatus } : {},
1317
- updatedAt: payload.createdAt
1318
- }))
1319
- }
1320
- };
1321
- }
1322
- case "UserInputRequested": {
1323
- const run = base.runs.find((item) => item.id === payload.runId);
1324
- return {
1325
- status: "applied",
1326
- snapshot: {
1327
- ...base,
1328
- userInputs: upsertById(base.userInputs ?? [], {
1329
- id: payload.requestId,
1330
- runId: payload.runId,
1331
- status: "pending",
1332
- payload: payload.payload,
1333
- createdAt: payload.createdAt,
1334
- resolvedAt: null
1335
- }),
1336
- runs: patchById(base.runs, payload.runId, (item) => ({
1337
- ...item,
1338
- pendingUserInputCount: (run?.pendingUserInputCount ?? 0) + 1,
1339
- status: "waiting-user-input",
1340
- updatedAt: payload.createdAt
1341
- }))
1342
- }
1343
- };
1344
- }
1345
- case "UserInputResolved": {
1346
- const run = base.runs.find((item) => item.id === payload.runId);
1347
- const pendingUserInputCount = run ? Math.max(0, Number(run.pendingUserInputCount) - 1) : 0;
1348
- const nextStatus = run?.status === "waiting-user-input" && pendingUserInputCount === 0 ? "running" : run?.status;
1349
- return {
1350
- status: "applied",
1351
- snapshot: {
1352
- ...base,
1353
- userInputs: patchById(base.userInputs ?? [], payload.requestId, (item) => ({
1354
- ...item,
1355
- status: "resolved",
1356
- resolvedAt: payload.createdAt
1357
- })),
1358
- runs: patchById(base.runs, payload.runId, (item) => ({
1359
- ...item,
1360
- pendingUserInputCount,
1361
- ...nextStatus ? { status: nextStatus } : {},
1362
- updatedAt: payload.createdAt
1363
- }))
1364
- }
1365
- };
1366
- }
1367
- case "RuntimePrepared": {
1368
- const runtime = {
1369
- id: payload.runtimeId,
1370
- workspaceId: payload.workspaceId,
1371
- runId: payload.runId,
1372
- adapterKind: payload.adapter,
1373
- executionTarget: payload.executionTarget ?? "local",
1374
- remoteHostId: payload.remoteHostId ?? null,
1375
- status: "prepared",
1376
- sandboxMode: "read-only",
1377
- isolationMode: "none",
1378
- workspaceDir: null,
1379
- homeDir: null,
1380
- tmpDir: null,
1381
- cacheDir: null,
1382
- logsDir: null,
1383
- stateDir: null,
1384
- sessionDir: null,
1385
- sessionLogPath: null,
1386
- pid: null,
1387
- startedAt: null,
1388
- updatedAt: payload.createdAt,
1389
- exitedAt: null
1390
- };
1391
- return {
1392
- status: "applied",
1393
- snapshot: {
1394
- ...base,
1395
- runtimes: upsertById(base.runtimes, runtime),
1396
- runs: patchById(base.runs, payload.runId, (run) => ({
1397
- ...run,
1398
- status: "preparing",
1399
- executionTarget: payload.executionTarget ?? run.executionTarget ?? "local",
1400
- remoteHostId: payload.remoteHostId ?? run.remoteHostId ?? null,
1401
- updatedAt: payload.createdAt
1402
- }))
1403
- }
1404
- };
1405
- }
1406
- case "RunRemoteLeaseClaimed":
1407
- return {
1408
- status: "applied",
1409
- snapshot: {
1410
- ...base,
1411
- runs: patchById(base.runs, payload.runId, (run) => ({
1412
- ...run,
1413
- remoteHostId: payload.hostId,
1414
- remoteLeaseId: payload.leaseId,
1415
- remoteLeaseClaimedAt: payload.createdAt,
1416
- updatedAt: payload.createdAt
1417
- }))
1418
- }
1419
- };
1420
- case "RunRemoteLeaseReleased":
1421
- return {
1422
- status: "applied",
1423
- snapshot: {
1424
- ...base,
1425
- runs: patchById(base.runs, payload.runId, (run) => ({
1426
- ...run,
1427
- remoteLeaseId: null,
1428
- remoteLeaseClaimedAt: null,
1429
- updatedAt: payload.createdAt
1430
- }))
1431
- }
1432
- };
1433
- case "RuntimeAttached": {
1434
- const tasks = payload.taskId == null ? base.tasks : patchById(base.tasks, payload.taskId, (task) => ({
1435
- ...task,
1436
- status: "running",
1437
- updatedAt: payload.createdAt
1438
- }));
1439
- return {
1440
- status: "applied",
1441
- snapshot: {
1442
- ...base,
1443
- runs: patchById(base.runs, payload.runId, (run) => ({
1444
- ...run,
1445
- activeRuntimeId: payload.runtimeId,
1446
- status: "running",
1447
- startedAt: payload.createdAt,
1448
- updatedAt: payload.createdAt
1449
- })),
1450
- runtimes: patchById(base.runtimes, payload.runtimeId, (runtime) => ({
1451
- ...runtime,
1452
- status: "running",
1453
- startedAt: payload.createdAt,
1454
- updatedAt: payload.createdAt
1455
- })),
1456
- tasks
1457
- }
1458
- };
1459
- }
1460
- case "RuntimeDetached":
1461
- return {
1462
- status: "applied",
1463
- snapshot: {
1464
- ...base,
1465
- runs: patchById(base.runs, payload.runId, (run) => ({
1466
- ...run,
1467
- activeRuntimeId: null,
1468
- updatedAt: payload.createdAt
1469
- })),
1470
- runtimes: patchById(base.runtimes, payload.runtimeId, (runtime) => ({
1471
- ...runtime,
1472
- status: "exited",
1473
- exitedAt: payload.createdAt,
1474
- updatedAt: payload.createdAt
1475
- }))
1476
- }
1477
- };
1478
- case "RuntimeMetadataUpdated":
1479
- return {
1480
- status: "applied",
1481
- snapshot: {
1482
- ...base,
1483
- runs: patchById(base.runs, payload.runId, (run) => ({
1484
- ...run,
1485
- ...payload.branch !== undefined ? { branch: payload.branch } : {},
1486
- ...payload.worktreePath !== undefined ? { worktreePath: payload.worktreePath } : {},
1487
- updatedAt: payload.createdAt
1488
- })),
1489
- runtimes: patchById(base.runtimes, payload.runtimeId, (runtime) => ({
1490
- ...runtime,
1491
- ...payload.sandboxMode !== undefined ? { sandboxMode: payload.sandboxMode } : {},
1492
- ...payload.isolationMode !== undefined ? { isolationMode: payload.isolationMode } : {},
1493
- ...payload.workspaceDir !== undefined ? { workspaceDir: payload.workspaceDir } : {},
1494
- ...payload.homeDir !== undefined ? { homeDir: payload.homeDir } : {},
1495
- ...payload.tmpDir !== undefined ? { tmpDir: payload.tmpDir } : {},
1496
- ...payload.cacheDir !== undefined ? { cacheDir: payload.cacheDir } : {},
1497
- ...payload.logsDir !== undefined ? { logsDir: payload.logsDir } : {},
1498
- ...payload.stateDir !== undefined ? { stateDir: payload.stateDir } : {},
1499
- ...payload.sessionDir !== undefined ? { sessionDir: payload.sessionDir } : {},
1500
- ...payload.sessionLogPath !== undefined ? { sessionLogPath: payload.sessionLogPath } : {},
1501
- ...payload.pid !== undefined ? { pid: payload.pid } : {},
1502
- updatedAt: payload.createdAt
1503
- }))
1504
- }
1505
- };
1506
- case "TaskStatusChanged": {
1507
- const queue = payload.status === "queued" ? base.queue : withQueuePositions(base.queue.filter((item) => item.taskId !== payload.taskId));
1508
- return {
1509
- status: "applied",
1510
- snapshot: {
1511
- ...base,
1512
- tasks: patchById(base.tasks, payload.taskId, (task) => ({
1513
- ...task,
1514
- status: payload.status,
1515
- updatedAt: payload.createdAt
1516
- })),
1517
- queue
1518
- }
1519
- };
1520
- }
1521
- case "TaskEnqueued": {
1522
- const entry = {
1523
- taskId: payload.taskId,
1524
- score: payload.score,
1525
- unblockCount: 0,
1526
- position: base.queue.length
1527
- };
1528
- const positionedQueue = withQueuePositions([
1529
- ...base.queue.filter((item) => item.taskId !== payload.taskId),
1530
- entry
1531
- ]);
1532
- return {
1533
- status: "applied",
1534
- snapshot: {
1535
- ...base,
1536
- tasks: patchById(base.tasks, payload.taskId, (task) => ({
1537
- ...task,
1538
- status: "queued",
1539
- updatedAt: payload.createdAt
1540
- })),
1541
- queue: positionedQueue
1542
- }
1543
- };
1544
- }
1545
- case "RemoteEndpointRegistered": {
1546
- const endpoint = payload.endpoint;
1547
- if (!endpoint || !endpoint.id) {
1548
- return { status: "ignored", snapshot: base };
1549
- }
1550
- return {
1551
- status: "applied",
1552
- snapshot: {
1553
- ...base,
1554
- remoteEndpoints: upsertById(base.remoteEndpoints, endpoint)
1555
- }
1556
- };
1557
- }
1558
- case "RemoteEndpointRemoved": {
1559
- const endpointId = payload.endpointId;
1560
- if (!endpointId) {
1561
- return { status: "ignored", snapshot: base };
1562
- }
1563
- return {
1564
- status: "applied",
1565
- snapshot: {
1566
- ...base,
1567
- remoteEndpoints: removeById(base.remoteEndpoints, endpointId),
1568
- remoteConnections: base.remoteConnections.filter((conn) => conn.endpointId !== endpointId),
1569
- remoteOrchestrations: base.remoteOrchestrations.filter((orch) => orch.endpointId !== endpointId)
1570
- }
1571
- };
1572
- }
1573
- case "RemoteEndpointUpdated": {
1574
- const endpointId = payload.endpointId;
1575
- const updates = payload.updates;
1576
- if (!endpointId || !updates) {
1577
- return { status: "ignored", snapshot: base };
1578
- }
1579
- return {
1580
- status: "applied",
1581
- snapshot: {
1582
- ...base,
1583
- remoteEndpoints: patchById(base.remoteEndpoints, endpointId, (endpoint) => ({
1584
- ...endpoint,
1585
- ...updates
1586
- }))
1587
- }
1588
- };
1589
- }
1590
- case "RemoteConnectionChanged": {
1591
- const endpointId = payload.endpointId;
1592
- const status = payload.status;
1593
- if (!endpointId || !status) {
1594
- return { status: "ignored", snapshot: base };
1595
- }
1596
- const existing = base.remoteConnections.find((conn) => conn.endpointId === endpointId);
1597
- const connection = {
1598
- ...existing ?? {
1599
- endpointId,
1600
- status,
1601
- error: null,
1602
- connectedAt: null,
1603
- tokenExpiresAt: null,
1604
- latencyMs: null,
1605
- subscribedEvents: []
1606
- },
1607
- endpointId,
1608
- status,
1609
- ...payload.error !== undefined ? { error: payload.error ?? null } : {},
1610
- ...status === "connected" ? { connectedAt: event.createdAt } : {}
1611
- };
1612
- return {
1613
- status: "applied",
1614
- snapshot: {
1615
- ...base,
1616
- remoteConnections: upsertByKey(base.remoteConnections, connection, "endpointId")
1617
- }
1618
- };
1619
- }
1620
- case "RemoteWorkspaceHydrated": {
1621
- const endpointId = payload.endpointId;
1622
- const workspace = payload.workspace;
1623
- const tasks = payload.tasks;
1624
- const graph = payload.graph;
1625
- if (!endpointId || !workspace) {
1626
- return { status: "ignored", snapshot: base };
1627
- }
1628
- return {
1629
- status: "applied",
1630
- snapshot: {
1631
- ...base,
1632
- workspaces: upsertById(base.workspaces, workspace),
1633
- tasks: Array.isArray(tasks) ? replaceWorkspaceSlice(base.tasks, workspace.id, tasks) : base.tasks,
1634
- graphs: graph ? upsertById(base.graphs, graph) : base.graphs
1635
- }
1636
- };
1637
- }
1638
- case "RemoteStateRefreshed": {
1639
- const endpointId = payload.endpointId;
1640
- const tasks = payload.tasks;
1641
- if (!endpointId) {
1642
- return { status: "ignored", snapshot: base };
1643
- }
1644
- const remoteWorkspace = base.workspaces.find((ws) => ws.id === `remote-workspace:${endpointId}`);
1645
- return {
1646
- status: "applied",
1647
- snapshot: {
1648
- ...base,
1649
- tasks: Array.isArray(tasks) && remoteWorkspace ? replaceWorkspaceSlice(base.tasks, remoteWorkspace.id, tasks) : base.tasks
1650
- }
1651
- };
1652
- }
1653
- case "RemoteEventReceived":
1654
- return { status: "applied", snapshot: base };
1655
- case "RemoteOrchestrationStarted": {
1656
- const orchestration = payload.orchestration;
1657
- if (!orchestration || !orchestration.orchestrationId) {
1658
- return { status: "ignored", snapshot: base };
1659
- }
1660
- return {
1661
- status: "applied",
1662
- snapshot: {
1663
- ...base,
1664
- remoteOrchestrations: upsertByKey(base.remoteOrchestrations, orchestration, "orchestrationId")
1665
- }
1666
- };
1667
- }
1668
- case "RemoteOrchestrationUpdated": {
1669
- const orchestrationId = payload.orchestrationId;
1670
- const state = payload.state;
1671
- if (!orchestrationId) {
1672
- return { status: "ignored", snapshot: base };
1673
- }
1674
- return {
1675
- status: "applied",
1676
- snapshot: {
1677
- ...base,
1678
- remoteOrchestrations: patchByKey(base.remoteOrchestrations, orchestrationId, "orchestrationId", (orch) => ({
1679
- ...orch,
1680
- ...isRecord(state) ? state : {}
1681
- }))
1682
- }
1683
- };
1684
- }
1685
- }
1686
- if (event.type === "workspace.imported") {
1687
- return { status: "requires-resync", snapshot };
1688
- }
1689
- if (event.type === "task.run-linked") {
1690
- const payload2 = isRecord(event.payload) ? event.payload : {};
1691
- const runId = readString(payload2, "runId");
1692
- const taskId = readString(payload2, "taskId");
1693
- const workspaceId = readString(payload2, "workspaceId");
1694
- if (!runId || !taskId || !workspaceId) {
1695
- return { status: "ignored", snapshot };
1696
- }
1697
- const baseRun = snapshot.runs.find((run) => run.id === runId) ?? {
1698
- id: asRunId(runId),
1699
- workspaceId: asWorkspaceId(workspaceId),
1700
- taskId: asTaskId(taskId),
1701
- title: "Task run",
1702
- runKind: "task",
1703
- mode: "interactive",
1704
- runtimeMode: "full-access",
1705
- interactionMode: "default",
1706
- status: "created",
1707
- runtimeAdapter: "rig-native",
1708
- model: null,
1709
- initialPrompt: null,
1710
- activeRuntimeId: runtimeIdFromRunId(asRunId(runId)),
1711
- latestMessageId: null,
1712
- pendingApprovalCount: 0,
1713
- pendingUserInputCount: 0,
1714
- branch: null,
1715
- worktreePath: null,
1716
- errorText: null,
1717
- createdAt: event.createdAt,
1718
- updatedAt: event.createdAt,
1719
- startedAt: event.createdAt,
1720
- completedAt: null
1721
- };
1722
- const nextSnapshot = applyRun(snapshot, {
1723
- ...baseRun,
1724
- workspaceId: asWorkspaceId(workspaceId),
1725
- taskId: asTaskId(taskId),
1726
- runKind: "task",
1727
- runtimeAdapter: "rig-native",
1728
- activeRuntimeId: runtimeIdFromRunId(asRunId(runId)),
1729
- updatedAt: event.createdAt
1730
- });
1731
- return {
1732
- status: "applied",
1733
- snapshot: withSnapshotMetadata(nextSnapshot, event, {})
1734
- };
1735
- }
1736
- if (event.type.startsWith("runtime.prepare.")) {
1737
- return applySyntheticRuntimePreparation(snapshot, event);
1738
- }
1739
- if (event.type === "runtime.prepared") {
1740
- return applySyntheticRuntimePrepared(snapshot, event);
1741
- }
1742
- if (event.type.startsWith("legacy.project.")) {
1743
- return applyLegacyProjectEvent(snapshot, event);
1744
- }
1745
- if (event.type.startsWith("legacy.thread.")) {
1746
- return applyLegacyThreadEvent(snapshot, event);
1747
- }
1748
- return { status: "ignored", snapshot: base };
1749
- }
1750
- function applyEngineEvents(snapshot, events) {
1751
- let nextSnapshot = snapshot;
1752
- let requiresResync = false;
1753
- let applied = false;
1754
- for (const event of events) {
1755
- const result = applyEngineEvent(nextSnapshot, event);
1756
- nextSnapshot = result.snapshot;
1757
- if (result.status === "requires-resync") {
1758
- requiresResync = true;
1759
- }
1760
- if (result.status === "applied") {
1761
- applied = true;
1762
- }
1763
- }
1764
- return {
1765
- status: requiresResync ? "requires-resync" : applied ? "applied" : "ignored",
1766
- snapshot: nextSnapshot
1767
- };
1768
- }
1769
- function pruneQueueEntries(snapshot) {
1770
- return snapshot.queue.filter((entry) => {
1771
- const task = snapshot.tasks.find((candidate) => candidate.id === entry.taskId);
1772
- return task?.status !== "running" && task?.status !== "in_progress" && task?.status !== "under_review";
1773
- });
1774
- }
1775
- export {
1776
- pruneQueueEntries,
1777
- mapTaskStatusFromRunStatus,
1778
- applyEngineEvents,
1779
- applyEngineEvent
1780
- };