@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.
- package/README.md +6 -6
- package/dist/client/activity.d.ts +2 -0
- package/dist/client/activity.js +6 -0
- package/dist/client/activity.js.map +1 -0
- package/dist/client/client.d.ts +101 -0
- package/dist/client/client.js +733 -0
- package/dist/client/client.js.map +1 -0
- package/dist/client/index.d.ts +3 -0
- package/dist/client/index.js +3 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/materialize.d.ts +7 -0
- package/dist/client/materialize.js +177 -0
- package/dist/client/materialize.js.map +1 -0
- package/dist/client/protocol.d.ts +60 -0
- package/dist/client/protocol.js +269 -0
- package/dist/client/protocol.js.map +1 -0
- package/dist/client/resolver.d.ts +23 -0
- package/dist/client/resolver.js +2 -0
- package/dist/client/resolver.js.map +1 -0
- package/dist/client/view.d.ts +118 -0
- package/dist/client/view.js +3 -0
- package/dist/client/view.js.map +1 -0
- package/dist/controllers/sqlite.d.ts +43 -0
- package/dist/controllers/sqlite.js +137 -2
- package/dist/controllers/sqlite.js.map +1 -1
- package/dist/extension/index.d.ts +1 -0
- package/dist/extension/index.js +278 -183
- package/dist/extension/index.js.map +1 -1
- package/dist/extension/session-view.d.ts +7 -2
- package/dist/extension/session-view.js +60 -52
- package/dist/extension/session-view.js.map +1 -1
- package/dist/extension/widget.d.ts +2 -1
- package/dist/extension/widget.js +14 -7
- package/dist/extension/widget.js.map +1 -1
- package/dist/host/child-worker-supervisor.js +1 -1
- package/dist/host/child-worker-supervisor.js.map +1 -1
- package/dist/host/resolver-entry.d.ts +2 -23
- package/dist/host/resolver-entry.js +1 -1
- package/dist/host/resolver-entry.js.map +1 -1
- package/dist/host/runner.d.ts +11 -0
- package/dist/host/runner.js +473 -17
- package/dist/host/runner.js.map +1 -1
- package/dist/host/state.d.ts +6 -3
- package/dist/host/state.js +52 -26
- package/dist/host/state.js.map +1 -1
- package/dist/host/view.d.ts +73 -0
- package/dist/host/view.js +871 -0
- package/dist/host/view.js.map +1 -0
- package/dist/host/worker-protocol.js +1 -1
- package/dist/host/worker-protocol.js.map +1 -1
- package/dist/state/database.d.ts +1 -0
- package/dist/state/database.js +15 -0
- package/dist/state/database.js.map +1 -1
- package/dist/state/prune.d.ts +3 -1
- package/dist/state/prune.js +6 -8
- package/dist/state/prune.js.map +1 -1
- package/dist/state/schema.js +12 -1
- package/dist/state/schema.js.map +1 -1
- package/dist/viewer/backup.d.ts +2 -0
- package/dist/viewer/backup.js +28 -0
- package/dist/viewer/backup.js.map +1 -0
- package/dist/viewer/cli.d.ts +4 -0
- package/dist/viewer/cli.js +150 -170
- package/dist/viewer/cli.js.map +1 -1
- package/dist/viewer/tui.d.ts +5 -7
- package/dist/viewer/tui.js +188 -108
- package/dist/viewer/tui.js.map +1 -1
- package/dist/workflows/store.d.ts +62 -1
- package/dist/workflows/store.js +350 -44
- package/dist/workflows/store.js.map +1 -1
- package/docs/2026-09-01-unified-workflow-client-plan.md +381 -0
- package/docs/2026-09-02-installed-live-e2e-plan.md +225 -0
- package/docs/SQLITE_STATE.md +13 -11
- package/docs/WORKFLOW_HOST.md +74 -61
- package/docs/development.md +2 -1
- package/docs/live-replay-protocol.md +70 -132
- package/docs/tui-viewer.md +10 -14
- package/docs/workflows.md +44 -1
- package/herdr-plugin.toml +1 -1
- package/package.json +9 -3
- package/protocol/client.v1.schema.json +137 -0
- package/protocol/fixtures/client-v1.json +23 -0
- package/src/client/activity.ts +6 -0
- package/src/client/client.ts +935 -0
- package/src/client/index.ts +24 -0
- package/src/client/materialize.ts +228 -0
- package/src/client/protocol.ts +327 -0
- package/src/client/resolver.ts +26 -0
- package/src/client/view.ts +138 -0
- package/src/controllers/sqlite.ts +213 -2
- package/src/extension/index.ts +349 -208
- package/src/extension/session-view.ts +73 -50
- package/src/extension/widget.ts +16 -8
- package/src/host/child-worker-supervisor.ts +1 -1
- package/src/host/resolver-entry.ts +11 -26
- package/src/host/runner.ts +648 -48
- package/src/host/state.ts +71 -43
- package/src/host/view.ts +1084 -0
- package/src/host/worker-protocol.ts +1 -1
- package/src/state/database.ts +13 -0
- package/src/state/prune.ts +11 -11
- package/src/state/schema.ts +12 -1
- package/src/viewer/backup.ts +29 -0
- package/src/viewer/cli.ts +171 -185
- package/src/viewer/tui.ts +196 -124
- package/src/workflows/store.ts +500 -45
- package/dist/host/client.d.ts +0 -48
- package/dist/host/client.js +0 -216
- package/dist/host/client.js.map +0 -1
- package/dist/host/protocol.d.ts +0 -38
- package/dist/host/protocol.js +0 -156
- package/dist/host/protocol.js.map +0 -1
- package/dist/viewer/watch.d.ts +0 -6
- package/dist/viewer/watch.js +0 -46
- package/dist/viewer/watch.js.map +0 -1
- package/src/host/client.ts +0 -293
- package/src/host/protocol.ts +0 -196
- package/src/viewer/watch.ts +0 -51
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import type { JsonValue } from "../state/json.js";
|
|
2
|
+
|
|
3
|
+
export const RUN_VIEW_SCHEMA = "pi-workflows.run-view.v1" as const;
|
|
4
|
+
export const SESSION_VIEW_SCHEMA = "pi-workflows.session-view.v1" as const;
|
|
5
|
+
|
|
6
|
+
export type WorkflowDisplayStatus =
|
|
7
|
+
| "queued"
|
|
8
|
+
| "running"
|
|
9
|
+
| "waiting"
|
|
10
|
+
| "paused"
|
|
11
|
+
| "completed"
|
|
12
|
+
| "failed"
|
|
13
|
+
| "timed_out"
|
|
14
|
+
| "cancelled"
|
|
15
|
+
| "ambiguous";
|
|
16
|
+
|
|
17
|
+
export type WorkflowDisplay = {
|
|
18
|
+
status: WorkflowDisplayStatus;
|
|
19
|
+
activity: "supervised_worker" | "origin_turn" | null;
|
|
20
|
+
controls: Array<"pause" | "resume" | "cancel" | "answer" | "review">;
|
|
21
|
+
reason: string | null;
|
|
22
|
+
reasonContent?: JsonValue;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export type WorkflowRunQueueView = {
|
|
26
|
+
runId: string;
|
|
27
|
+
workflowName: string;
|
|
28
|
+
workflowSourceRef: string;
|
|
29
|
+
initialized: boolean;
|
|
30
|
+
definitionDigest: string;
|
|
31
|
+
status: "queued" | "starting" | "running" | "parked" | "done" | "failed" | "cancelled";
|
|
32
|
+
originSessionId: string | null;
|
|
33
|
+
executionMode: "interactive" | "headless";
|
|
34
|
+
parentRunId: string | null;
|
|
35
|
+
errorCode: string | null;
|
|
36
|
+
createdAt: string;
|
|
37
|
+
updatedAt: string;
|
|
38
|
+
startedAt: string | null;
|
|
39
|
+
finishedAt: string | null;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export type WorkflowRunView = {
|
|
43
|
+
schema: typeof RUN_VIEW_SCHEMA;
|
|
44
|
+
runId: string;
|
|
45
|
+
revision: number;
|
|
46
|
+
display: WorkflowDisplay;
|
|
47
|
+
manifest: JsonValue;
|
|
48
|
+
state: JsonValue;
|
|
49
|
+
workflow: JsonValue;
|
|
50
|
+
queue: WorkflowRunQueueView;
|
|
51
|
+
updates: JsonValue[];
|
|
52
|
+
graphSteps: JsonValue[];
|
|
53
|
+
graphStepStart: number;
|
|
54
|
+
graphStepTotal: number;
|
|
55
|
+
takenTransitions: string[];
|
|
56
|
+
graphHistory: JsonValue;
|
|
57
|
+
takenTransitionStart: number;
|
|
58
|
+
takenTransitionTotal: number;
|
|
59
|
+
graphCursor: number;
|
|
60
|
+
stepStart: number;
|
|
61
|
+
stepTotal: number;
|
|
62
|
+
tracePage: JsonValue;
|
|
63
|
+
session: JsonValue;
|
|
64
|
+
settingsScopes: JsonValue[];
|
|
65
|
+
settingsStart: number;
|
|
66
|
+
settingsTotal: number;
|
|
67
|
+
followUpQueue: JsonValue;
|
|
68
|
+
followUpStart: number;
|
|
69
|
+
followUpTotal: number;
|
|
70
|
+
updateStart: number;
|
|
71
|
+
updateTotal: number;
|
|
72
|
+
live: boolean;
|
|
73
|
+
possiblyInterrupted: boolean;
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
export type WorkflowRunListPage = {
|
|
77
|
+
schema: "pi-workflows.run-list-page.v1";
|
|
78
|
+
revision: string;
|
|
79
|
+
start: number;
|
|
80
|
+
total: number;
|
|
81
|
+
items: WorkflowRunSummary[];
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
export type WorkflowRunSummary = {
|
|
85
|
+
runId: string;
|
|
86
|
+
workflowName: string;
|
|
87
|
+
originSessionId: string | null;
|
|
88
|
+
createdAt: string;
|
|
89
|
+
updatedAt: string;
|
|
90
|
+
display: WorkflowDisplay;
|
|
91
|
+
manifest: JsonValue;
|
|
92
|
+
live: boolean;
|
|
93
|
+
possiblyInterrupted: boolean;
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
export type ClientInteractiveRequest = {
|
|
97
|
+
requestId: string;
|
|
98
|
+
runId: string;
|
|
99
|
+
attemptId: string;
|
|
100
|
+
targetSessionId: string;
|
|
101
|
+
kind: "agent" | "assistant" | "decision";
|
|
102
|
+
contract: JsonValue;
|
|
103
|
+
revision: number;
|
|
104
|
+
status: "pending" | "presenting" | "settled" | "cancelled";
|
|
105
|
+
presenterId: string | null;
|
|
106
|
+
presentationClaimExpiresAt: string | null;
|
|
107
|
+
presentationSessionEntryId: string | null;
|
|
108
|
+
acceptedSubmissionId: string | null;
|
|
109
|
+
createdAt: string;
|
|
110
|
+
updatedAt: string;
|
|
111
|
+
settledAt: string | null;
|
|
112
|
+
consumedAt: string | null;
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
export type WorkflowDeliveryAvailability = {
|
|
116
|
+
notification: boolean;
|
|
117
|
+
turn: boolean;
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
export type WorkflowSessionView = {
|
|
121
|
+
schema: typeof SESSION_VIEW_SCHEMA;
|
|
122
|
+
sessionId: string;
|
|
123
|
+
run: WorkflowRunView | null;
|
|
124
|
+
pendingInteractions: JsonValue[];
|
|
125
|
+
pendingInteractionStart: number;
|
|
126
|
+
pendingInteractionTotal: number;
|
|
127
|
+
deliveries: WorkflowDeliveryAvailability;
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
export type OriginActivityReport = {
|
|
131
|
+
sessionId: string;
|
|
132
|
+
runId: string;
|
|
133
|
+
requestId: string;
|
|
134
|
+
deliveryId: string;
|
|
135
|
+
sessionEntryId: string;
|
|
136
|
+
sequence: number;
|
|
137
|
+
state: "started" | "refresh" | "settled";
|
|
138
|
+
};
|
|
@@ -62,6 +62,27 @@ export type WorkflowRunClaimOptions = WorkflowRunReservationOptions & {
|
|
|
62
62
|
leaseMs: number;
|
|
63
63
|
};
|
|
64
64
|
|
|
65
|
+
export type WorkflowRunQueueViewRecord = {
|
|
66
|
+
runId: string;
|
|
67
|
+
workflowName: string;
|
|
68
|
+
workflowSourceRef: string;
|
|
69
|
+
workflowSource: unknown;
|
|
70
|
+
initialized: boolean;
|
|
71
|
+
definitionDigest: string;
|
|
72
|
+
runStateStatus: string;
|
|
73
|
+
paused: boolean;
|
|
74
|
+
status: WorkflowRunLaunchStatus;
|
|
75
|
+
originSessionId: string | null;
|
|
76
|
+
executionMode: "interactive" | "headless";
|
|
77
|
+
parentRunId: string | null;
|
|
78
|
+
errorCode: string | null;
|
|
79
|
+
errorMessage: string | null;
|
|
80
|
+
createdAt: string;
|
|
81
|
+
updatedAt: string;
|
|
82
|
+
startedAt: string | null;
|
|
83
|
+
finishedAt: string | null;
|
|
84
|
+
};
|
|
85
|
+
|
|
65
86
|
export type WorkflowRunQueueRecord = {
|
|
66
87
|
runId: string;
|
|
67
88
|
workflowName: string;
|
|
@@ -213,6 +234,34 @@ type RunRow = {
|
|
|
213
234
|
ownerId: string | null;
|
|
214
235
|
claimExpiresAt: number | null;
|
|
215
236
|
};
|
|
237
|
+
type WorkflowRunViewRow = {
|
|
238
|
+
runId: string;
|
|
239
|
+
workflowName: string;
|
|
240
|
+
workflowRef: string;
|
|
241
|
+
runStatus: string;
|
|
242
|
+
paused: number;
|
|
243
|
+
definitionDigest: Buffer;
|
|
244
|
+
status: WorkflowRunLaunchStatus;
|
|
245
|
+
originSessionId: string | null;
|
|
246
|
+
executionMode: "interactive" | "headless";
|
|
247
|
+
parentRunId: string | null;
|
|
248
|
+
errorCode: string | null;
|
|
249
|
+
errorMessage: string | null;
|
|
250
|
+
createdAt: number;
|
|
251
|
+
updatedAt: number;
|
|
252
|
+
startedAt: number | null;
|
|
253
|
+
finishedAt: number | null;
|
|
254
|
+
sourceType: "builtin" | "file";
|
|
255
|
+
sourceRef: string;
|
|
256
|
+
sourceRevision: string;
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
type RunListRevisionRow = {
|
|
260
|
+
count: number;
|
|
261
|
+
revisionSum: number;
|
|
262
|
+
updatedAt: number;
|
|
263
|
+
};
|
|
264
|
+
|
|
216
265
|
type RunSourceIdentityRow = {
|
|
217
266
|
mountPath: string;
|
|
218
267
|
sourceType: "builtin" | "file";
|
|
@@ -1239,6 +1288,40 @@ export class SqliteControllerStore implements ControllerStore {
|
|
|
1239
1288
|
return row === undefined ? undefined : this.mapWorkflowRun(row);
|
|
1240
1289
|
}
|
|
1241
1290
|
|
|
1291
|
+
getWorkflowRunView(runId: string): WorkflowRunQueueViewRecord | undefined {
|
|
1292
|
+
const row = this.workflowRunViewRows("WHERE r.run_id = ?", [runId])[0];
|
|
1293
|
+
return row === undefined ? undefined : workflowRunViewRecord(row);
|
|
1294
|
+
}
|
|
1295
|
+
|
|
1296
|
+
workflowRunListRevision(): { total: number; revision: string } {
|
|
1297
|
+
const row = this.state.connection
|
|
1298
|
+
.prepare(
|
|
1299
|
+
`SELECT count(*) AS count, COALESCE(sum(res.revision), 0) AS revisionSum,
|
|
1300
|
+
COALESCE(max(q.updated_at), 0) AS updatedAt
|
|
1301
|
+
FROM runs r JOIN run_queue q ON q.run_id = r.run_id
|
|
1302
|
+
JOIN resources res ON res.resource_id = r.resource_id`,
|
|
1303
|
+
)
|
|
1304
|
+
.get();
|
|
1305
|
+
if (!isRunListRevisionRow(row)) throw new Error("Workflow run list revision is invalid");
|
|
1306
|
+
return {
|
|
1307
|
+
total: row.count,
|
|
1308
|
+
revision: `${row.count}:${row.revisionSum}:${row.updatedAt}`,
|
|
1309
|
+
};
|
|
1310
|
+
}
|
|
1311
|
+
|
|
1312
|
+
listWorkflowRunViews(options: { offset: number; limit: number }): {
|
|
1313
|
+
total: number;
|
|
1314
|
+
revision: string;
|
|
1315
|
+
runs: WorkflowRunQueueViewRecord[];
|
|
1316
|
+
} {
|
|
1317
|
+
const current = this.workflowRunListRevision();
|
|
1318
|
+
const rows = this.workflowRunViewRows("ORDER BY q.created_at DESC LIMIT ? OFFSET ?", [
|
|
1319
|
+
options.limit,
|
|
1320
|
+
options.offset,
|
|
1321
|
+
]);
|
|
1322
|
+
return { ...current, runs: rows.map(workflowRunViewRecord) };
|
|
1323
|
+
}
|
|
1324
|
+
|
|
1242
1325
|
workflowRunProjectPath(runId: string): string | undefined {
|
|
1243
1326
|
const row = this.state.connection
|
|
1244
1327
|
.prepare(
|
|
@@ -1270,11 +1353,11 @@ export class SqliteControllerStore implements ControllerStore {
|
|
|
1270
1353
|
clauses.push(`r.run_id NOT IN (${options.excludeRunIds.map(() => "?").join(", ")})`);
|
|
1271
1354
|
params.push(...options.excludeRunIds);
|
|
1272
1355
|
}
|
|
1273
|
-
params.push(options.limit
|
|
1356
|
+
if (options.limit !== undefined) params.push(options.limit);
|
|
1274
1357
|
const rows = this.state.connection
|
|
1275
1358
|
.prepare(
|
|
1276
1359
|
workflowRunSelect(
|
|
1277
|
-
`${clauses.length === 0 ? "" : `WHERE ${clauses.join(" AND ")}`} ORDER BY q.created_at DESC LIMIT
|
|
1360
|
+
`${clauses.length === 0 ? "" : `WHERE ${clauses.join(" AND ")}`} ORDER BY q.created_at DESC${options.limit === undefined ? "" : " LIMIT ?"}`,
|
|
1278
1361
|
),
|
|
1279
1362
|
)
|
|
1280
1363
|
.all(...params);
|
|
@@ -1292,6 +1375,14 @@ export class SqliteControllerStore implements ControllerStore {
|
|
|
1292
1375
|
return isRunRow(row) ? this.mapWorkflowRun(row) : undefined;
|
|
1293
1376
|
}
|
|
1294
1377
|
|
|
1378
|
+
findSessionReservationView(sessionId: string): WorkflowRunQueueViewRecord | undefined {
|
|
1379
|
+
const row = this.workflowRunViewRows(
|
|
1380
|
+
"WHERE b.origin_session_id = ? AND q.status NOT IN ('done', 'failed', 'cancelled') ORDER BY q.created_at DESC LIMIT 1",
|
|
1381
|
+
[sessionId],
|
|
1382
|
+
)[0];
|
|
1383
|
+
return row === undefined ? undefined : workflowRunViewRecord(row);
|
|
1384
|
+
}
|
|
1385
|
+
|
|
1295
1386
|
claimWorkflowRun(options: {
|
|
1296
1387
|
runId: string;
|
|
1297
1388
|
runnerId: string;
|
|
@@ -2198,6 +2289,24 @@ export class SqliteControllerStore implements ControllerStore {
|
|
|
2198
2289
|
return claimed;
|
|
2199
2290
|
}
|
|
2200
2291
|
|
|
2292
|
+
hasClaimableWorkflowTurnIntent(options: { targetSessionId: string; now?: string }): boolean {
|
|
2293
|
+
const now = epoch(validTimestamp(options.now));
|
|
2294
|
+
const row = this.state.connection
|
|
2295
|
+
.prepare(
|
|
2296
|
+
`SELECT 1 AS present
|
|
2297
|
+
FROM turn_intents t
|
|
2298
|
+
JOIN effects e ON e.effect_id = t.effect_id
|
|
2299
|
+
JOIN leases l ON l.resource_id = e.resource_id
|
|
2300
|
+
WHERE t.target_session_id = ? AND t.resolved_at IS NULL
|
|
2301
|
+
AND t.eligible_at IS NOT NULL AND t.eligible_at <= ?
|
|
2302
|
+
AND e.status = 'pending'
|
|
2303
|
+
AND (l.owner_id IS NULL OR l.expires_at IS NULL OR l.expires_at <= ?)
|
|
2304
|
+
LIMIT 1`,
|
|
2305
|
+
)
|
|
2306
|
+
.get(options.targetSessionId, now, now);
|
|
2307
|
+
return row !== undefined;
|
|
2308
|
+
}
|
|
2309
|
+
|
|
2201
2310
|
makeWorkflowTurnIntentEligible(options: {
|
|
2202
2311
|
intentId: string;
|
|
2203
2312
|
fallbackFacts: WorkflowTurnIntentFacts;
|
|
@@ -2354,6 +2463,22 @@ export class SqliteControllerStore implements ControllerStore {
|
|
|
2354
2463
|
return this.requireNotification(options.runId, options.attemptId, options.notificationIndex);
|
|
2355
2464
|
}
|
|
2356
2465
|
|
|
2466
|
+
hasClaimableWorkflowNotification(options: { targetSessionId: string; now?: string }): boolean {
|
|
2467
|
+
const now = epoch(validTimestamp(options.now));
|
|
2468
|
+
const row = this.state.connection
|
|
2469
|
+
.prepare(
|
|
2470
|
+
`SELECT 1 AS present
|
|
2471
|
+
FROM notifications n
|
|
2472
|
+
JOIN effects e ON e.effect_id = n.effect_id
|
|
2473
|
+
JOIN leases l ON l.resource_id = e.resource_id
|
|
2474
|
+
WHERE n.target_session_id = ? AND e.status = 'pending'
|
|
2475
|
+
AND (l.owner_id IS NULL OR l.expires_at IS NULL OR l.expires_at <= ?)
|
|
2476
|
+
LIMIT 1`,
|
|
2477
|
+
)
|
|
2478
|
+
.get(options.targetSessionId, now);
|
|
2479
|
+
return row !== undefined;
|
|
2480
|
+
}
|
|
2481
|
+
|
|
2357
2482
|
listPendingWorkflowNotifications(options: {
|
|
2358
2483
|
targetSessionId: string;
|
|
2359
2484
|
limit?: number;
|
|
@@ -2899,6 +3024,13 @@ export class SqliteControllerStore implements ControllerStore {
|
|
|
2899
3024
|
}
|
|
2900
3025
|
}
|
|
2901
3026
|
|
|
3027
|
+
private workflowRunViewRows(clause: string, params: unknown[]): WorkflowRunViewRow[] {
|
|
3028
|
+
return this.state.connection
|
|
3029
|
+
.prepare(workflowRunViewSelect(clause))
|
|
3030
|
+
.all(...params)
|
|
3031
|
+
.filter(isWorkflowRunViewRow);
|
|
3032
|
+
}
|
|
3033
|
+
|
|
2902
3034
|
/* istanbul ignore next -- pure projection covered by integration tests */
|
|
2903
3035
|
private mapWorkflowRun(row: RunRow): WorkflowRunQueueRecord {
|
|
2904
3036
|
return {
|
|
@@ -3596,6 +3728,24 @@ function workflowRunSelect(clause: string): string {
|
|
|
3596
3728
|
JOIN leases l ON l.resource_id = r.resource_id ${clause}`;
|
|
3597
3729
|
}
|
|
3598
3730
|
|
|
3731
|
+
function workflowRunViewSelect(clause: string): string {
|
|
3732
|
+
return `SELECT r.run_id AS runId, d.workflow_name AS workflowName,
|
|
3733
|
+
r.workflow_ref AS workflowRef, r.status AS runStatus, r.paused,
|
|
3734
|
+
r.definition_digest AS definitionDigest, q.status,
|
|
3735
|
+
b.origin_session_id AS originSessionId, b.execution_mode AS executionMode,
|
|
3736
|
+
r.parent_run_id AS parentRunId, q.error_code AS errorCode,
|
|
3737
|
+
CAST(error.content AS TEXT) AS errorMessage,
|
|
3738
|
+
q.created_at AS createdAt, q.updated_at AS updatedAt,
|
|
3739
|
+
q.started_at AS startedAt, q.finished_at AS finishedAt,
|
|
3740
|
+
source.source_type AS sourceType, source.source_ref AS sourceRef,
|
|
3741
|
+
source.source_revision AS sourceRevision
|
|
3742
|
+
FROM runs r JOIN workflow_definitions d ON d.definition_digest = r.definition_digest
|
|
3743
|
+
JOIN run_queue q ON q.run_id = r.run_id
|
|
3744
|
+
LEFT JOIN run_bindings b ON b.run_id = r.run_id
|
|
3745
|
+
LEFT JOIN run_sources source ON source.run_id = r.run_id AND source.mount_path = ''
|
|
3746
|
+
LEFT JOIN blobs error ON error.blob_hash = q.error_hash ${clause}`;
|
|
3747
|
+
}
|
|
3748
|
+
|
|
3599
3749
|
function turnIntentSelect(clause: string): string {
|
|
3600
3750
|
return `SELECT t.turn_intent_id AS intentId, t.source_event_id AS sourceEventId,
|
|
3601
3751
|
t.run_id AS runId, t.workflow_ref AS workflowRef,
|
|
@@ -3687,6 +3837,67 @@ function isControllerRow(value: unknown): value is ControllerRow {
|
|
|
3687
3837
|
function isLeaseRow(value: unknown): value is LeaseRow {
|
|
3688
3838
|
return isRecord(value);
|
|
3689
3839
|
}
|
|
3840
|
+
function workflowRunViewRecord(row: WorkflowRunViewRow): WorkflowRunQueueViewRecord {
|
|
3841
|
+
const root =
|
|
3842
|
+
row.sourceType === "builtin"
|
|
3843
|
+
? { kind: "builtin", id: row.sourceRef, revision: row.sourceRevision }
|
|
3844
|
+
: { kind: "file", path: row.sourceRef, hash: row.sourceRevision };
|
|
3845
|
+
return {
|
|
3846
|
+
runId: row.runId,
|
|
3847
|
+
workflowName: row.workflowName,
|
|
3848
|
+
workflowSourceRef: row.workflowRef,
|
|
3849
|
+
workflowSource: { root, mounted: [] },
|
|
3850
|
+
initialized: row.runStatus !== "queued",
|
|
3851
|
+
definitionDigest: `sha256:${row.definitionDigest.toString("hex")}`,
|
|
3852
|
+
runStateStatus: row.runStatus,
|
|
3853
|
+
paused: row.paused === 1,
|
|
3854
|
+
status: row.status,
|
|
3855
|
+
originSessionId: row.executionMode === "headless" ? null : row.originSessionId,
|
|
3856
|
+
executionMode: row.executionMode,
|
|
3857
|
+
parentRunId: row.parentRunId,
|
|
3858
|
+
errorCode: row.errorCode,
|
|
3859
|
+
errorMessage: row.errorMessage,
|
|
3860
|
+
createdAt: new Date(row.createdAt).toISOString(),
|
|
3861
|
+
updatedAt: new Date(row.updatedAt).toISOString(),
|
|
3862
|
+
startedAt: row.startedAt === null ? null : new Date(row.startedAt).toISOString(),
|
|
3863
|
+
finishedAt: row.finishedAt === null ? null : new Date(row.finishedAt).toISOString(),
|
|
3864
|
+
};
|
|
3865
|
+
}
|
|
3866
|
+
|
|
3867
|
+
function isWorkflowRunViewRow(value: unknown): value is WorkflowRunViewRow {
|
|
3868
|
+
return (
|
|
3869
|
+
isRecord(value) &&
|
|
3870
|
+
typeof value.runId === "string" &&
|
|
3871
|
+
typeof value.workflowName === "string" &&
|
|
3872
|
+
typeof value.workflowRef === "string" &&
|
|
3873
|
+
typeof value.runStatus === "string" &&
|
|
3874
|
+
typeof value.paused === "number" &&
|
|
3875
|
+
Buffer.isBuffer(value.definitionDigest) &&
|
|
3876
|
+
typeof value.status === "string" &&
|
|
3877
|
+
(value.originSessionId === null || typeof value.originSessionId === "string") &&
|
|
3878
|
+
(value.executionMode === "interactive" || value.executionMode === "headless") &&
|
|
3879
|
+
(value.parentRunId === null || typeof value.parentRunId === "string") &&
|
|
3880
|
+
(value.errorCode === null || typeof value.errorCode === "string") &&
|
|
3881
|
+
(value.errorMessage === null || typeof value.errorMessage === "string") &&
|
|
3882
|
+
typeof value.createdAt === "number" &&
|
|
3883
|
+
typeof value.updatedAt === "number" &&
|
|
3884
|
+
(value.startedAt === null || typeof value.startedAt === "number") &&
|
|
3885
|
+
(value.finishedAt === null || typeof value.finishedAt === "number") &&
|
|
3886
|
+
(value.sourceType === "builtin" || value.sourceType === "file") &&
|
|
3887
|
+
typeof value.sourceRef === "string" &&
|
|
3888
|
+
typeof value.sourceRevision === "string"
|
|
3889
|
+
);
|
|
3890
|
+
}
|
|
3891
|
+
|
|
3892
|
+
function isRunListRevisionRow(value: unknown): value is RunListRevisionRow {
|
|
3893
|
+
return (
|
|
3894
|
+
isRecord(value) &&
|
|
3895
|
+
typeof value.count === "number" &&
|
|
3896
|
+
typeof value.revisionSum === "number" &&
|
|
3897
|
+
typeof value.updatedAt === "number"
|
|
3898
|
+
);
|
|
3899
|
+
}
|
|
3900
|
+
|
|
3690
3901
|
function isRunRow(value: unknown): value is RunRow {
|
|
3691
3902
|
return isRecord(value);
|
|
3692
3903
|
}
|