@osolmaz/pi-workflows 0.15.3 → 0.16.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.
Files changed (118) hide show
  1. package/README.md +6 -6
  2. package/dist/client/activity.d.ts +2 -0
  3. package/dist/client/activity.js +6 -0
  4. package/dist/client/activity.js.map +1 -0
  5. package/dist/client/client.d.ts +101 -0
  6. package/dist/client/client.js +733 -0
  7. package/dist/client/client.js.map +1 -0
  8. package/dist/client/index.d.ts +3 -0
  9. package/dist/client/index.js +3 -0
  10. package/dist/client/index.js.map +1 -0
  11. package/dist/client/materialize.d.ts +7 -0
  12. package/dist/client/materialize.js +177 -0
  13. package/dist/client/materialize.js.map +1 -0
  14. package/dist/client/protocol.d.ts +60 -0
  15. package/dist/client/protocol.js +269 -0
  16. package/dist/client/protocol.js.map +1 -0
  17. package/dist/client/resolver.d.ts +23 -0
  18. package/dist/client/resolver.js +2 -0
  19. package/dist/client/resolver.js.map +1 -0
  20. package/dist/client/view.d.ts +118 -0
  21. package/dist/client/view.js +3 -0
  22. package/dist/client/view.js.map +1 -0
  23. package/dist/controllers/sqlite.d.ts +43 -0
  24. package/dist/controllers/sqlite.js +137 -2
  25. package/dist/controllers/sqlite.js.map +1 -1
  26. package/dist/extension/index.d.ts +1 -0
  27. package/dist/extension/index.js +278 -183
  28. package/dist/extension/index.js.map +1 -1
  29. package/dist/extension/session-view.d.ts +7 -2
  30. package/dist/extension/session-view.js +60 -52
  31. package/dist/extension/session-view.js.map +1 -1
  32. package/dist/extension/widget.d.ts +2 -1
  33. package/dist/extension/widget.js +14 -7
  34. package/dist/extension/widget.js.map +1 -1
  35. package/dist/host/child-worker-supervisor.js +1 -1
  36. package/dist/host/child-worker-supervisor.js.map +1 -1
  37. package/dist/host/resolver-entry.d.ts +2 -23
  38. package/dist/host/resolver-entry.js +1 -1
  39. package/dist/host/resolver-entry.js.map +1 -1
  40. package/dist/host/runner.d.ts +11 -0
  41. package/dist/host/runner.js +473 -17
  42. package/dist/host/runner.js.map +1 -1
  43. package/dist/host/state.d.ts +6 -3
  44. package/dist/host/state.js +52 -26
  45. package/dist/host/state.js.map +1 -1
  46. package/dist/host/view.d.ts +73 -0
  47. package/dist/host/view.js +871 -0
  48. package/dist/host/view.js.map +1 -0
  49. package/dist/host/worker-protocol.js +1 -1
  50. package/dist/host/worker-protocol.js.map +1 -1
  51. package/dist/state/database.d.ts +1 -0
  52. package/dist/state/database.js +15 -0
  53. package/dist/state/database.js.map +1 -1
  54. package/dist/state/prune.d.ts +3 -1
  55. package/dist/state/prune.js +6 -8
  56. package/dist/state/prune.js.map +1 -1
  57. package/dist/state/schema.js +12 -1
  58. package/dist/state/schema.js.map +1 -1
  59. package/dist/viewer/backup.d.ts +2 -0
  60. package/dist/viewer/backup.js +28 -0
  61. package/dist/viewer/backup.js.map +1 -0
  62. package/dist/viewer/cli.d.ts +4 -0
  63. package/dist/viewer/cli.js +150 -170
  64. package/dist/viewer/cli.js.map +1 -1
  65. package/dist/viewer/tui.d.ts +5 -7
  66. package/dist/viewer/tui.js +188 -108
  67. package/dist/viewer/tui.js.map +1 -1
  68. package/dist/workflows/store.d.ts +62 -1
  69. package/dist/workflows/store.js +350 -44
  70. package/dist/workflows/store.js.map +1 -1
  71. package/docs/2026-09-01-unified-workflow-client-plan.md +381 -0
  72. package/docs/2026-09-02-installed-live-e2e-plan.md +225 -0
  73. package/docs/SQLITE_STATE.md +13 -11
  74. package/docs/WORKFLOW_HOST.md +74 -61
  75. package/docs/development.md +2 -1
  76. package/docs/live-replay-protocol.md +70 -132
  77. package/docs/tui-viewer.md +10 -14
  78. package/docs/workflows.md +44 -1
  79. package/herdr-plugin.toml +1 -1
  80. package/package.json +9 -3
  81. package/protocol/client.v1.schema.json +137 -0
  82. package/protocol/fixtures/client-v1.json +23 -0
  83. package/src/client/activity.ts +6 -0
  84. package/src/client/client.ts +935 -0
  85. package/src/client/index.ts +24 -0
  86. package/src/client/materialize.ts +228 -0
  87. package/src/client/protocol.ts +327 -0
  88. package/src/client/resolver.ts +26 -0
  89. package/src/client/view.ts +138 -0
  90. package/src/controllers/sqlite.ts +213 -2
  91. package/src/extension/index.ts +349 -208
  92. package/src/extension/session-view.ts +73 -50
  93. package/src/extension/widget.ts +16 -8
  94. package/src/host/child-worker-supervisor.ts +1 -1
  95. package/src/host/resolver-entry.ts +11 -26
  96. package/src/host/runner.ts +648 -48
  97. package/src/host/state.ts +71 -43
  98. package/src/host/view.ts +1084 -0
  99. package/src/host/worker-protocol.ts +1 -1
  100. package/src/state/database.ts +13 -0
  101. package/src/state/prune.ts +11 -11
  102. package/src/state/schema.ts +12 -1
  103. package/src/viewer/backup.ts +29 -0
  104. package/src/viewer/cli.ts +171 -185
  105. package/src/viewer/tui.ts +196 -124
  106. package/src/workflows/store.ts +500 -45
  107. package/dist/host/client.d.ts +0 -48
  108. package/dist/host/client.js +0 -216
  109. package/dist/host/client.js.map +0 -1
  110. package/dist/host/protocol.d.ts +0 -38
  111. package/dist/host/protocol.js +0 -156
  112. package/dist/host/protocol.js.map +0 -1
  113. package/dist/viewer/watch.d.ts +0 -6
  114. package/dist/viewer/watch.js +0 -46
  115. package/dist/viewer/watch.js.map +0 -1
  116. package/src/host/client.ts +0 -293
  117. package/src/host/protocol.ts +0 -196
  118. package/src/viewer/watch.ts +0 -51
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolver.js","sourceRoot":"","sources":["../../src/client/resolver.ts"],"names":[],"mappings":""}
@@ -0,0 +1,118 @@
1
+ import type { JsonValue } from "../state/json.js";
2
+ export declare const RUN_VIEW_SCHEMA: "pi-workflows.run-view.v1";
3
+ export declare const SESSION_VIEW_SCHEMA: "pi-workflows.session-view.v1";
4
+ export type WorkflowDisplayStatus = "queued" | "running" | "waiting" | "paused" | "completed" | "failed" | "timed_out" | "cancelled" | "ambiguous";
5
+ export type WorkflowDisplay = {
6
+ status: WorkflowDisplayStatus;
7
+ activity: "supervised_worker" | "origin_turn" | null;
8
+ controls: Array<"pause" | "resume" | "cancel" | "answer" | "review">;
9
+ reason: string | null;
10
+ reasonContent?: JsonValue;
11
+ };
12
+ export type WorkflowRunQueueView = {
13
+ runId: string;
14
+ workflowName: string;
15
+ workflowSourceRef: string;
16
+ initialized: boolean;
17
+ definitionDigest: string;
18
+ status: "queued" | "starting" | "running" | "parked" | "done" | "failed" | "cancelled";
19
+ originSessionId: string | null;
20
+ executionMode: "interactive" | "headless";
21
+ parentRunId: string | null;
22
+ errorCode: string | null;
23
+ createdAt: string;
24
+ updatedAt: string;
25
+ startedAt: string | null;
26
+ finishedAt: string | null;
27
+ };
28
+ export type WorkflowRunView = {
29
+ schema: typeof RUN_VIEW_SCHEMA;
30
+ runId: string;
31
+ revision: number;
32
+ display: WorkflowDisplay;
33
+ manifest: JsonValue;
34
+ state: JsonValue;
35
+ workflow: JsonValue;
36
+ queue: WorkflowRunQueueView;
37
+ updates: JsonValue[];
38
+ graphSteps: JsonValue[];
39
+ graphStepStart: number;
40
+ graphStepTotal: number;
41
+ takenTransitions: string[];
42
+ graphHistory: JsonValue;
43
+ takenTransitionStart: number;
44
+ takenTransitionTotal: number;
45
+ graphCursor: number;
46
+ stepStart: number;
47
+ stepTotal: number;
48
+ tracePage: JsonValue;
49
+ session: JsonValue;
50
+ settingsScopes: JsonValue[];
51
+ settingsStart: number;
52
+ settingsTotal: number;
53
+ followUpQueue: JsonValue;
54
+ followUpStart: number;
55
+ followUpTotal: number;
56
+ updateStart: number;
57
+ updateTotal: number;
58
+ live: boolean;
59
+ possiblyInterrupted: boolean;
60
+ };
61
+ export type WorkflowRunListPage = {
62
+ schema: "pi-workflows.run-list-page.v1";
63
+ revision: string;
64
+ start: number;
65
+ total: number;
66
+ items: WorkflowRunSummary[];
67
+ };
68
+ export type WorkflowRunSummary = {
69
+ runId: string;
70
+ workflowName: string;
71
+ originSessionId: string | null;
72
+ createdAt: string;
73
+ updatedAt: string;
74
+ display: WorkflowDisplay;
75
+ manifest: JsonValue;
76
+ live: boolean;
77
+ possiblyInterrupted: boolean;
78
+ };
79
+ export type ClientInteractiveRequest = {
80
+ requestId: string;
81
+ runId: string;
82
+ attemptId: string;
83
+ targetSessionId: string;
84
+ kind: "agent" | "assistant" | "decision";
85
+ contract: JsonValue;
86
+ revision: number;
87
+ status: "pending" | "presenting" | "settled" | "cancelled";
88
+ presenterId: string | null;
89
+ presentationClaimExpiresAt: string | null;
90
+ presentationSessionEntryId: string | null;
91
+ acceptedSubmissionId: string | null;
92
+ createdAt: string;
93
+ updatedAt: string;
94
+ settledAt: string | null;
95
+ consumedAt: string | null;
96
+ };
97
+ export type WorkflowDeliveryAvailability = {
98
+ notification: boolean;
99
+ turn: boolean;
100
+ };
101
+ export type WorkflowSessionView = {
102
+ schema: typeof SESSION_VIEW_SCHEMA;
103
+ sessionId: string;
104
+ run: WorkflowRunView | null;
105
+ pendingInteractions: JsonValue[];
106
+ pendingInteractionStart: number;
107
+ pendingInteractionTotal: number;
108
+ deliveries: WorkflowDeliveryAvailability;
109
+ };
110
+ export type OriginActivityReport = {
111
+ sessionId: string;
112
+ runId: string;
113
+ requestId: string;
114
+ deliveryId: string;
115
+ sessionEntryId: string;
116
+ sequence: number;
117
+ state: "started" | "refresh" | "settled";
118
+ };
@@ -0,0 +1,3 @@
1
+ export const RUN_VIEW_SCHEMA = "pi-workflows.run-view.v1";
2
+ export const SESSION_VIEW_SCHEMA = "pi-workflows.session-view.v1";
3
+ //# sourceMappingURL=view.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"view.js","sourceRoot":"","sources":["../../src/client/view.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,eAAe,GAAG,0BAAmC,CAAC;AACnE,MAAM,CAAC,MAAM,mBAAmB,GAAG,8BAAuC,CAAC"}
@@ -22,6 +22,26 @@ export type WorkflowRunClaimOptions = WorkflowRunReservationOptions & {
22
22
  claimToken: string;
23
23
  leaseMs: number;
24
24
  };
25
+ export type WorkflowRunQueueViewRecord = {
26
+ runId: string;
27
+ workflowName: string;
28
+ workflowSourceRef: string;
29
+ workflowSource: unknown;
30
+ initialized: boolean;
31
+ definitionDigest: string;
32
+ runStateStatus: string;
33
+ paused: boolean;
34
+ status: WorkflowRunLaunchStatus;
35
+ originSessionId: string | null;
36
+ executionMode: "interactive" | "headless";
37
+ parentRunId: string | null;
38
+ errorCode: string | null;
39
+ errorMessage: string | null;
40
+ createdAt: string;
41
+ updatedAt: string;
42
+ startedAt: string | null;
43
+ finishedAt: string | null;
44
+ };
25
45
  export type WorkflowRunQueueRecord = {
26
46
  runId: string;
27
47
  workflowName: string;
@@ -212,6 +232,19 @@ export declare class SqliteControllerStore implements ControllerStore {
212
232
  prepareOrAdoptWorkflowRun(options: WorkflowRunClaimOptions): WorkflowRunPreparationResult;
213
233
  enqueueWorkflowRun(options: WorkflowRunClaimOptions): WorkflowRunQueueRecord;
214
234
  getWorkflowRun(runId: string): WorkflowRunQueueRecord | undefined;
235
+ getWorkflowRunView(runId: string): WorkflowRunQueueViewRecord | undefined;
236
+ workflowRunListRevision(): {
237
+ total: number;
238
+ revision: string;
239
+ };
240
+ listWorkflowRunViews(options: {
241
+ offset: number;
242
+ limit: number;
243
+ }): {
244
+ total: number;
245
+ revision: string;
246
+ runs: WorkflowRunQueueViewRecord[];
247
+ };
215
248
  workflowRunProjectPath(runId: string): string | undefined;
216
249
  listWorkflowRuns(options?: {
217
250
  statuses?: WorkflowRunLaunchStatus[];
@@ -219,6 +252,7 @@ export declare class SqliteControllerStore implements ControllerStore {
219
252
  limit?: number;
220
253
  }): WorkflowRunQueueRecord[];
221
254
  findSessionReservation(sessionId: string): WorkflowRunQueueRecord | undefined;
255
+ findSessionReservationView(sessionId: string): WorkflowRunQueueViewRecord | undefined;
222
256
  claimWorkflowRun(options: {
223
257
  runId: string;
224
258
  runnerId: string;
@@ -386,6 +420,10 @@ export declare class SqliteControllerStore implements ControllerStore {
386
420
  now?: string;
387
421
  limit?: number;
388
422
  }): WorkflowTurnIntentRecord[];
423
+ hasClaimableWorkflowTurnIntent(options: {
424
+ targetSessionId: string;
425
+ now?: string;
426
+ }): boolean;
389
427
  makeWorkflowTurnIntentEligible(options: {
390
428
  intentId: string;
391
429
  fallbackFacts: WorkflowTurnIntentFacts;
@@ -421,6 +459,10 @@ export declare class SqliteControllerStore implements ControllerStore {
421
459
  content: string;
422
460
  now?: string;
423
461
  }): WorkflowNotificationRecord;
462
+ hasClaimableWorkflowNotification(options: {
463
+ targetSessionId: string;
464
+ now?: string;
465
+ }): boolean;
424
466
  listPendingWorkflowNotifications(options: {
425
467
  targetSessionId: string;
426
468
  limit?: number;
@@ -478,6 +520,7 @@ export declare class SqliteControllerStore implements ControllerStore {
478
520
  private requireWorkflowRunRow;
479
521
  private requireWorkflowRun;
480
522
  private assertWorkflowRunPreparationCompatible;
523
+ private workflowRunViewRows;
481
524
  private mapWorkflowRun;
482
525
  private claimRun;
483
526
  private claimRunInTransaction;
@@ -640,6 +640,32 @@ export class SqliteControllerStore {
640
640
  const row = this.workflowRunRow(runId);
641
641
  return row === undefined ? undefined : this.mapWorkflowRun(row);
642
642
  }
643
+ getWorkflowRunView(runId) {
644
+ const row = this.workflowRunViewRows("WHERE r.run_id = ?", [runId])[0];
645
+ return row === undefined ? undefined : workflowRunViewRecord(row);
646
+ }
647
+ workflowRunListRevision() {
648
+ const row = this.state.connection
649
+ .prepare(`SELECT count(*) AS count, COALESCE(sum(res.revision), 0) AS revisionSum,
650
+ COALESCE(max(q.updated_at), 0) AS updatedAt
651
+ FROM runs r JOIN run_queue q ON q.run_id = r.run_id
652
+ JOIN resources res ON res.resource_id = r.resource_id`)
653
+ .get();
654
+ if (!isRunListRevisionRow(row))
655
+ throw new Error("Workflow run list revision is invalid");
656
+ return {
657
+ total: row.count,
658
+ revision: `${row.count}:${row.revisionSum}:${row.updatedAt}`,
659
+ };
660
+ }
661
+ listWorkflowRunViews(options) {
662
+ const current = this.workflowRunListRevision();
663
+ const rows = this.workflowRunViewRows("ORDER BY q.created_at DESC LIMIT ? OFFSET ?", [
664
+ options.limit,
665
+ options.offset,
666
+ ]);
667
+ return { ...current, runs: rows.map(workflowRunViewRecord) };
668
+ }
643
669
  workflowRunProjectPath(runId) {
644
670
  const row = this.state.connection
645
671
  .prepare(`SELECT p.canonical_path AS canonicalPath
@@ -662,9 +688,10 @@ export class SqliteControllerStore {
662
688
  clauses.push(`r.run_id NOT IN (${options.excludeRunIds.map(() => "?").join(", ")})`);
663
689
  params.push(...options.excludeRunIds);
664
690
  }
665
- params.push(options.limit ?? 100);
691
+ if (options.limit !== undefined)
692
+ params.push(options.limit);
666
693
  const rows = this.state.connection
667
- .prepare(workflowRunSelect(`${clauses.length === 0 ? "" : `WHERE ${clauses.join(" AND ")}`} ORDER BY q.created_at DESC LIMIT ?`))
694
+ .prepare(workflowRunSelect(`${clauses.length === 0 ? "" : `WHERE ${clauses.join(" AND ")}`} ORDER BY q.created_at DESC${options.limit === undefined ? "" : " LIMIT ?"}`))
668
695
  .all(...params);
669
696
  return rows.filter(isRunRow).map((row) => this.mapWorkflowRun(row));
670
697
  }
@@ -674,6 +701,10 @@ export class SqliteControllerStore {
674
701
  .get(sessionId);
675
702
  return isRunRow(row) ? this.mapWorkflowRun(row) : undefined;
676
703
  }
704
+ findSessionReservationView(sessionId) {
705
+ const row = this.workflowRunViewRows("WHERE b.origin_session_id = ? AND q.status NOT IN ('done', 'failed', 'cancelled') ORDER BY q.created_at DESC LIMIT 1", [sessionId])[0];
706
+ return row === undefined ? undefined : workflowRunViewRecord(row);
707
+ }
677
708
  claimWorkflowRun(options) {
678
709
  const now = epoch(validTimestamp(options.now));
679
710
  return this.claimRun(options.runId, options.runnerId, options.claimToken, options.leaseMs, now);
@@ -1206,6 +1237,21 @@ export class SqliteControllerStore {
1206
1237
  }
1207
1238
  return claimed;
1208
1239
  }
1240
+ hasClaimableWorkflowTurnIntent(options) {
1241
+ const now = epoch(validTimestamp(options.now));
1242
+ const row = this.state.connection
1243
+ .prepare(`SELECT 1 AS present
1244
+ FROM turn_intents t
1245
+ JOIN effects e ON e.effect_id = t.effect_id
1246
+ JOIN leases l ON l.resource_id = e.resource_id
1247
+ WHERE t.target_session_id = ? AND t.resolved_at IS NULL
1248
+ AND t.eligible_at IS NOT NULL AND t.eligible_at <= ?
1249
+ AND e.status = 'pending'
1250
+ AND (l.owner_id IS NULL OR l.expires_at IS NULL OR l.expires_at <= ?)
1251
+ LIMIT 1`)
1252
+ .get(options.targetSessionId, now, now);
1253
+ return row !== undefined;
1254
+ }
1209
1255
  makeWorkflowTurnIntentEligible(options) {
1210
1256
  const eligibleAt = epoch(validTimestamp(options.eligibleAt ?? options.now));
1211
1257
  const factsHash = this.state.putJson(options.fallbackFacts, eligibleAt);
@@ -1284,6 +1330,19 @@ export class SqliteControllerStore {
1284
1330
  });
1285
1331
  return this.requireNotification(options.runId, options.attemptId, options.notificationIndex);
1286
1332
  }
1333
+ hasClaimableWorkflowNotification(options) {
1334
+ const now = epoch(validTimestamp(options.now));
1335
+ const row = this.state.connection
1336
+ .prepare(`SELECT 1 AS present
1337
+ FROM notifications n
1338
+ JOIN effects e ON e.effect_id = n.effect_id
1339
+ JOIN leases l ON l.resource_id = e.resource_id
1340
+ WHERE n.target_session_id = ? AND e.status = 'pending'
1341
+ AND (l.owner_id IS NULL OR l.expires_at IS NULL OR l.expires_at <= ?)
1342
+ LIMIT 1`)
1343
+ .get(options.targetSessionId, now);
1344
+ return row !== undefined;
1345
+ }
1287
1346
  listPendingWorkflowNotifications(options) {
1288
1347
  const now = Date.now();
1289
1348
  return this.notificationRows(options.targetSessionId, options.limit ?? 20)
@@ -1678,6 +1737,12 @@ export class SqliteControllerStore {
1678
1737
  throw new Error(`Workflow run preparation conflicts: ${options.runId}`);
1679
1738
  }
1680
1739
  }
1740
+ workflowRunViewRows(clause, params) {
1741
+ return this.state.connection
1742
+ .prepare(workflowRunViewSelect(clause))
1743
+ .all(...params)
1744
+ .filter(isWorkflowRunViewRow);
1745
+ }
1681
1746
  /* istanbul ignore next -- pure projection covered by integration tests */
1682
1747
  mapWorkflowRun(row) {
1683
1748
  return {
@@ -2120,6 +2185,23 @@ function workflowRunSelect(clause) {
2120
2185
  LEFT JOIN run_bindings b ON b.run_id = r.run_id
2121
2186
  JOIN leases l ON l.resource_id = r.resource_id ${clause}`;
2122
2187
  }
2188
+ function workflowRunViewSelect(clause) {
2189
+ return `SELECT r.run_id AS runId, d.workflow_name AS workflowName,
2190
+ r.workflow_ref AS workflowRef, r.status AS runStatus, r.paused,
2191
+ r.definition_digest AS definitionDigest, q.status,
2192
+ b.origin_session_id AS originSessionId, b.execution_mode AS executionMode,
2193
+ r.parent_run_id AS parentRunId, q.error_code AS errorCode,
2194
+ CAST(error.content AS TEXT) AS errorMessage,
2195
+ q.created_at AS createdAt, q.updated_at AS updatedAt,
2196
+ q.started_at AS startedAt, q.finished_at AS finishedAt,
2197
+ source.source_type AS sourceType, source.source_ref AS sourceRef,
2198
+ source.source_revision AS sourceRevision
2199
+ FROM runs r JOIN workflow_definitions d ON d.definition_digest = r.definition_digest
2200
+ JOIN run_queue q ON q.run_id = r.run_id
2201
+ LEFT JOIN run_bindings b ON b.run_id = r.run_id
2202
+ LEFT JOIN run_sources source ON source.run_id = r.run_id AND source.mount_path = ''
2203
+ LEFT JOIN blobs error ON error.blob_hash = q.error_hash ${clause}`;
2204
+ }
2123
2205
  function turnIntentSelect(clause) {
2124
2206
  return `SELECT t.turn_intent_id AS intentId, t.source_event_id AS sourceEventId,
2125
2207
  t.run_id AS runId, t.workflow_ref AS workflowRef,
@@ -2152,6 +2234,59 @@ function isControllerRow(value) {
2152
2234
  function isLeaseRow(value) {
2153
2235
  return isRecord(value);
2154
2236
  }
2237
+ function workflowRunViewRecord(row) {
2238
+ const root = row.sourceType === "builtin"
2239
+ ? { kind: "builtin", id: row.sourceRef, revision: row.sourceRevision }
2240
+ : { kind: "file", path: row.sourceRef, hash: row.sourceRevision };
2241
+ return {
2242
+ runId: row.runId,
2243
+ workflowName: row.workflowName,
2244
+ workflowSourceRef: row.workflowRef,
2245
+ workflowSource: { root, mounted: [] },
2246
+ initialized: row.runStatus !== "queued",
2247
+ definitionDigest: `sha256:${row.definitionDigest.toString("hex")}`,
2248
+ runStateStatus: row.runStatus,
2249
+ paused: row.paused === 1,
2250
+ status: row.status,
2251
+ originSessionId: row.executionMode === "headless" ? null : row.originSessionId,
2252
+ executionMode: row.executionMode,
2253
+ parentRunId: row.parentRunId,
2254
+ errorCode: row.errorCode,
2255
+ errorMessage: row.errorMessage,
2256
+ createdAt: new Date(row.createdAt).toISOString(),
2257
+ updatedAt: new Date(row.updatedAt).toISOString(),
2258
+ startedAt: row.startedAt === null ? null : new Date(row.startedAt).toISOString(),
2259
+ finishedAt: row.finishedAt === null ? null : new Date(row.finishedAt).toISOString(),
2260
+ };
2261
+ }
2262
+ function isWorkflowRunViewRow(value) {
2263
+ return (isRecord(value) &&
2264
+ typeof value.runId === "string" &&
2265
+ typeof value.workflowName === "string" &&
2266
+ typeof value.workflowRef === "string" &&
2267
+ typeof value.runStatus === "string" &&
2268
+ typeof value.paused === "number" &&
2269
+ Buffer.isBuffer(value.definitionDigest) &&
2270
+ typeof value.status === "string" &&
2271
+ (value.originSessionId === null || typeof value.originSessionId === "string") &&
2272
+ (value.executionMode === "interactive" || value.executionMode === "headless") &&
2273
+ (value.parentRunId === null || typeof value.parentRunId === "string") &&
2274
+ (value.errorCode === null || typeof value.errorCode === "string") &&
2275
+ (value.errorMessage === null || typeof value.errorMessage === "string") &&
2276
+ typeof value.createdAt === "number" &&
2277
+ typeof value.updatedAt === "number" &&
2278
+ (value.startedAt === null || typeof value.startedAt === "number") &&
2279
+ (value.finishedAt === null || typeof value.finishedAt === "number") &&
2280
+ (value.sourceType === "builtin" || value.sourceType === "file") &&
2281
+ typeof value.sourceRef === "string" &&
2282
+ typeof value.sourceRevision === "string");
2283
+ }
2284
+ function isRunListRevisionRow(value) {
2285
+ return (isRecord(value) &&
2286
+ typeof value.count === "number" &&
2287
+ typeof value.revisionSum === "number" &&
2288
+ typeof value.updatedAt === "number");
2289
+ }
2155
2290
  function isRunRow(value) {
2156
2291
  return isRecord(value);
2157
2292
  }