@osolmaz/pi-workflows 0.7.0 → 0.8.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 +3 -2
- package/dist/job-progress/index.d.ts +3 -0
- package/dist/job-progress/index.js +4 -0
- package/dist/job-progress/index.js.map +1 -0
- package/dist/job-progress/reporter.d.ts +8 -0
- package/dist/job-progress/reporter.js +243 -0
- package/dist/job-progress/reporter.js.map +1 -0
- package/dist/job-progress/types.d.ts +65 -0
- package/dist/job-progress/types.js +2 -0
- package/dist/job-progress/types.js.map +1 -0
- package/dist/job-progress/validation.d.ts +5 -0
- package/dist/job-progress/validation.js +227 -0
- package/dist/job-progress/validation.js.map +1 -0
- package/docs/JOB_PROGRESS.md +119 -0
- package/docs/MONITOR.md +5 -0
- package/docs/plans/2026-08-17-bundled-skills-plan.md +1 -1
- package/docs/plans/2026-08-17-durable-job-progress-plan.md +176 -0
- package/docs/workflows.md +10 -0
- package/package.json +5 -1
- package/skills/monitor/SKILL.md +12 -0
- package/src/job-progress/index.ts +24 -0
- package/src/job-progress/reporter.ts +304 -0
- package/src/job-progress/types.ts +92 -0
- package/src/job-progress/validation.ts +255 -0
package/README.md
CHANGED
|
@@ -13,8 +13,9 @@ structured, validated output to route on. See the
|
|
|
13
13
|
[design philosophy](docs/DESIGN_PHILOSOPHY.md) for the principles behind the
|
|
14
14
|
engine and its public parts. Running steps can publish durable [workflow
|
|
15
15
|
updates](docs/WORKFLOW_UPDATES.md), including progress counts and ETA data.
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
Remote workers can publish the same tracks through the storage-neutral
|
|
17
|
+
[durable job progress API](docs/JOB_PROGRESS.md). Agent instructions use compact
|
|
18
|
+
[workflow step messages](docs/WORKFLOW_STEP_MESSAGES.md), and the built-in
|
|
18
19
|
[monitor](docs/MONITOR.md) reports every check without starting an extra
|
|
19
20
|
assistant turn.
|
|
20
21
|
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { createJobProgressReporter, estimateJobProgress, type JobProgressReporter, } from "./reporter.js";
|
|
2
|
+
export { isTerminalJobProgressState, MAX_JOB_PROGRESS_BYTES, MAX_JOB_PROGRESS_TRACKS, validateJobProgressSnapshot, } from "./validation.js";
|
|
3
|
+
export { JOB_PROGRESS_SCHEMA, type JobProgressCost, type JobProgressEstimate, type JobProgressIdentity, type JobProgressPublish, type JobProgressPublishResult, type JobProgressReporterOptions, type JobProgressSnapshot, type JobProgressState, type JobProgressTrack, type JobProgressUpdate, } from "./types.js";
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { createJobProgressReporter, estimateJobProgress, } from "./reporter.js";
|
|
2
|
+
export { isTerminalJobProgressState, MAX_JOB_PROGRESS_BYTES, MAX_JOB_PROGRESS_TRACKS, validateJobProgressSnapshot, } from "./validation.js";
|
|
3
|
+
export { JOB_PROGRESS_SCHEMA, } from "./types.js";
|
|
4
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/job-progress/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,yBAAyB,EACzB,mBAAmB,GAEpB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,0BAA0B,EAC1B,sBAAsB,EACtB,uBAAuB,EACvB,2BAA2B,GAC5B,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,mBAAmB,GAWpB,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type JobProgressEstimate, type JobProgressPublishResult, type JobProgressReporterOptions, type JobProgressSnapshot, type JobProgressUpdate } from "./types.js";
|
|
2
|
+
export type JobProgressReporter = {
|
|
3
|
+
report(update: JobProgressUpdate): Promise<JobProgressPublishResult>;
|
|
4
|
+
flush(): Promise<JobProgressPublishResult>;
|
|
5
|
+
snapshot(): JobProgressSnapshot;
|
|
6
|
+
};
|
|
7
|
+
export declare function createJobProgressReporter(options: JobProgressReporterOptions): JobProgressReporter;
|
|
8
|
+
export declare function estimateJobProgress(snapshots: JobProgressSnapshot[], now?: Date): JobProgressEstimate;
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
import { estimateProgress, } from "../workflows/index.js";
|
|
2
|
+
import { JOB_PROGRESS_SCHEMA, } from "./types.js";
|
|
3
|
+
import { isTerminalJobProgressState, validateJobProgressSnapshot } from "./validation.js";
|
|
4
|
+
const DEFAULT_MINIMUM_INTERVAL_MS = 30_000;
|
|
5
|
+
const DEFAULT_PUBLISH_TIMEOUT_MS = 15_000;
|
|
6
|
+
export function createJobProgressReporter(options) {
|
|
7
|
+
const now = options.now ?? (() => new Date());
|
|
8
|
+
const minimumIntervalMs = nonNegativeInteger(options.minimumIntervalMs ?? DEFAULT_MINIMUM_INTERVAL_MS, "minimumIntervalMs");
|
|
9
|
+
const publishTimeoutMs = positiveInteger(options.publishTimeoutMs ?? DEFAULT_PUBLISH_TIMEOUT_MS, "publishTimeoutMs");
|
|
10
|
+
let current = options.previousSnapshot === undefined
|
|
11
|
+
? validateJobProgressSnapshot({
|
|
12
|
+
schema: JOB_PROGRESS_SCHEMA,
|
|
13
|
+
application: options.application,
|
|
14
|
+
component: options.component,
|
|
15
|
+
jobId: options.jobId,
|
|
16
|
+
sourceRevision: options.sourceRevision,
|
|
17
|
+
contractHash: options.contractHash,
|
|
18
|
+
sequence: 0,
|
|
19
|
+
state: options.initialState ?? "running",
|
|
20
|
+
phase: options.initialPhase ?? "starting",
|
|
21
|
+
startedAt: options.startedAt,
|
|
22
|
+
updatedAt: options.startedAt,
|
|
23
|
+
...(options.deadlineAt === undefined ? {} : { deadlineAt: options.deadlineAt }),
|
|
24
|
+
tracks: options.initialTracks,
|
|
25
|
+
})
|
|
26
|
+
: validatePreviousSnapshot(options, options.previousSnapshot);
|
|
27
|
+
const resumed = options.previousSnapshot !== undefined;
|
|
28
|
+
let lastQueuedAtMs = resumed ? Date.parse(current.updatedAt) : Number.NEGATIVE_INFINITY;
|
|
29
|
+
let lastQueuedSequence = -1;
|
|
30
|
+
let lastPublishedSequence = resumed ? current.sequence : -1;
|
|
31
|
+
let queuedOperation;
|
|
32
|
+
let tail = Promise.resolve();
|
|
33
|
+
const enqueue = (snapshot) => {
|
|
34
|
+
if (lastQueuedSequence === snapshot.sequence && queuedOperation !== undefined) {
|
|
35
|
+
return queuedOperation;
|
|
36
|
+
}
|
|
37
|
+
lastQueuedAtMs = Date.parse(snapshot.updatedAt);
|
|
38
|
+
lastQueuedSequence = snapshot.sequence;
|
|
39
|
+
const started = tail.then(() => startPublication(options.publish, cloneSnapshot(snapshot), publishTimeoutMs));
|
|
40
|
+
const operation = started.then(async (publication) => {
|
|
41
|
+
await publication.result;
|
|
42
|
+
lastPublishedSequence = Math.max(lastPublishedSequence, snapshot.sequence);
|
|
43
|
+
});
|
|
44
|
+
queuedOperation = operation;
|
|
45
|
+
tail = started.then((publication) => publication.settled).catch(() => undefined);
|
|
46
|
+
void operation
|
|
47
|
+
.finally(() => {
|
|
48
|
+
if (lastQueuedSequence === snapshot.sequence) {
|
|
49
|
+
lastQueuedSequence = -1;
|
|
50
|
+
queuedOperation = undefined;
|
|
51
|
+
}
|
|
52
|
+
})
|
|
53
|
+
.catch(() => undefined);
|
|
54
|
+
return operation;
|
|
55
|
+
};
|
|
56
|
+
return {
|
|
57
|
+
async report(update) {
|
|
58
|
+
if (isTerminalJobProgressState(current.state)) {
|
|
59
|
+
throw new Error("job progress cannot change after a terminal state");
|
|
60
|
+
}
|
|
61
|
+
if (current.sequence >= Number.MAX_SAFE_INTEGER) {
|
|
62
|
+
throw new Error("job progress sequence is exhausted");
|
|
63
|
+
}
|
|
64
|
+
const timestamp = now().toISOString();
|
|
65
|
+
const state = update.state ?? current.state;
|
|
66
|
+
const phase = update.phase ?? current.phase;
|
|
67
|
+
const finishedAt = isTerminalJobProgressState(state)
|
|
68
|
+
? (update.finishedAt ?? timestamp)
|
|
69
|
+
: update.finishedAt;
|
|
70
|
+
const tracks = isTerminalJobProgressState(state)
|
|
71
|
+
? terminalizeTracks(update.tracks ?? current.tracks, state)
|
|
72
|
+
: (update.tracks ?? current.tracks);
|
|
73
|
+
const next = validateJobProgressSnapshot({
|
|
74
|
+
...current,
|
|
75
|
+
sequence: current.sequence + 1,
|
|
76
|
+
state,
|
|
77
|
+
phase,
|
|
78
|
+
updatedAt: timestamp,
|
|
79
|
+
tracks,
|
|
80
|
+
...(update.cost === undefined ? {} : { cost: update.cost }),
|
|
81
|
+
...(finishedAt === undefined ? {} : { finishedAt }),
|
|
82
|
+
});
|
|
83
|
+
assertMonotonicTracks(current, next);
|
|
84
|
+
const publishNow = update.force === true ||
|
|
85
|
+
phase !== current.phase ||
|
|
86
|
+
isTerminalJobProgressState(state) ||
|
|
87
|
+
Date.parse(timestamp) - lastQueuedAtMs >= minimumIntervalMs;
|
|
88
|
+
current = next;
|
|
89
|
+
if (!publishNow)
|
|
90
|
+
return { snapshot: cloneSnapshot(next), published: false };
|
|
91
|
+
await enqueue(next);
|
|
92
|
+
return { snapshot: cloneSnapshot(next), published: true };
|
|
93
|
+
},
|
|
94
|
+
async flush() {
|
|
95
|
+
const snapshot = current;
|
|
96
|
+
if (lastPublishedSequence >= snapshot.sequence) {
|
|
97
|
+
await tail;
|
|
98
|
+
return { snapshot: cloneSnapshot(snapshot), published: false };
|
|
99
|
+
}
|
|
100
|
+
await enqueue(snapshot);
|
|
101
|
+
return { snapshot: cloneSnapshot(snapshot), published: true };
|
|
102
|
+
},
|
|
103
|
+
snapshot() {
|
|
104
|
+
return cloneSnapshot(current);
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
export function estimateJobProgress(snapshots, now = new Date()) {
|
|
109
|
+
if (snapshots.length === 0)
|
|
110
|
+
throw new Error("job progress estimation requires at least one snapshot");
|
|
111
|
+
const validated = snapshots
|
|
112
|
+
.map(validateJobProgressSnapshot)
|
|
113
|
+
.sort((left, right) => left.sequence - right.sequence);
|
|
114
|
+
const latest = validated.at(-1);
|
|
115
|
+
for (const snapshot of validated)
|
|
116
|
+
assertSameIdentity(latest, snapshot);
|
|
117
|
+
for (let index = 1; index < validated.length; index += 1) {
|
|
118
|
+
const previous = validated[index - 1];
|
|
119
|
+
const current = validated[index];
|
|
120
|
+
if (previous.sequence === current.sequence) {
|
|
121
|
+
throw new Error(`job progress sequence ${current.sequence} is duplicated`);
|
|
122
|
+
}
|
|
123
|
+
if (Date.parse(previous.updatedAt) > Date.parse(current.updatedAt)) {
|
|
124
|
+
throw new Error("job progress updatedAt must not decrease as sequence increases");
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
const keys = latest.tracks.map((track) => track.key);
|
|
128
|
+
const tracks = keys.map((key) => {
|
|
129
|
+
const samples = validated.flatMap((snapshot) => {
|
|
130
|
+
const track = snapshot.tracks.find((candidate) => candidate.key === key);
|
|
131
|
+
return track === undefined ? [] : [{ at: snapshot.updatedAt, data: track.data }];
|
|
132
|
+
});
|
|
133
|
+
return { key, samples, estimate: estimateProgress(key, samples, now) };
|
|
134
|
+
});
|
|
135
|
+
return {
|
|
136
|
+
snapshot: cloneSnapshot(latest),
|
|
137
|
+
tracks,
|
|
138
|
+
estimates: tracks.map((track) => track.estimate),
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
function terminalizeTracks(tracks, state) {
|
|
142
|
+
return tracks.map((track) => ({
|
|
143
|
+
key: track.key,
|
|
144
|
+
data: {
|
|
145
|
+
...track.data,
|
|
146
|
+
status: track.data.status === "completed" ||
|
|
147
|
+
track.data.status === "failed" ||
|
|
148
|
+
track.data.status === "cancelled"
|
|
149
|
+
? track.data.status
|
|
150
|
+
: state,
|
|
151
|
+
},
|
|
152
|
+
}));
|
|
153
|
+
}
|
|
154
|
+
function assertMonotonicTracks(previous, next) {
|
|
155
|
+
if (previous.phase !== next.phase)
|
|
156
|
+
return;
|
|
157
|
+
for (const track of next.tracks) {
|
|
158
|
+
const prior = previous.tracks.find((candidate) => candidate.key === track.key);
|
|
159
|
+
if (prior === undefined || resetsTrack(prior, track))
|
|
160
|
+
continue;
|
|
161
|
+
if (prior.data.completed !== undefined &&
|
|
162
|
+
track.data.completed !== undefined &&
|
|
163
|
+
track.data.completed < prior.data.completed) {
|
|
164
|
+
throw new Error(`job progress track ${track.key} completed value must not decrease`);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
function resetsTrack(previous, next) {
|
|
169
|
+
return (previous.data.phase !== next.data.phase ||
|
|
170
|
+
previous.data.unit !== next.data.unit ||
|
|
171
|
+
previous.data.total !== next.data.total);
|
|
172
|
+
}
|
|
173
|
+
function assertSameIdentity(expected, actual) {
|
|
174
|
+
for (const field of [
|
|
175
|
+
"application",
|
|
176
|
+
"component",
|
|
177
|
+
"jobId",
|
|
178
|
+
"sourceRevision",
|
|
179
|
+
"contractHash",
|
|
180
|
+
"startedAt",
|
|
181
|
+
]) {
|
|
182
|
+
if (expected[field] !== actual[field]) {
|
|
183
|
+
throw new Error(`job progress sample ${field} does not match`);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
function startPublication(publish, snapshot, timeoutMs) {
|
|
188
|
+
const controller = new AbortController();
|
|
189
|
+
let timeout;
|
|
190
|
+
const write = publish(snapshot, controller.signal);
|
|
191
|
+
const deadline = new Promise((_resolve, reject) => {
|
|
192
|
+
timeout = setTimeout(() => {
|
|
193
|
+
controller.abort();
|
|
194
|
+
reject(new Error(`job progress publication timed out after ${timeoutMs} ms`));
|
|
195
|
+
}, timeoutMs);
|
|
196
|
+
});
|
|
197
|
+
const result = Promise.race([write, deadline]).finally(() => {
|
|
198
|
+
if (timeout !== undefined)
|
|
199
|
+
clearTimeout(timeout);
|
|
200
|
+
});
|
|
201
|
+
return {
|
|
202
|
+
result,
|
|
203
|
+
settled: write.then(() => undefined, () => undefined),
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
function validatePreviousSnapshot(identity, previous) {
|
|
207
|
+
const validated = validateJobProgressSnapshot(previous);
|
|
208
|
+
for (const field of [
|
|
209
|
+
"application",
|
|
210
|
+
"component",
|
|
211
|
+
"jobId",
|
|
212
|
+
"sourceRevision",
|
|
213
|
+
"contractHash",
|
|
214
|
+
"startedAt",
|
|
215
|
+
]) {
|
|
216
|
+
if (identity[field] !== validated[field]) {
|
|
217
|
+
throw new Error(`job progress previous snapshot ${field} does not match`);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
if (isTerminalJobProgressState(validated.state)) {
|
|
221
|
+
throw new Error("job progress cannot resume from a terminal snapshot");
|
|
222
|
+
}
|
|
223
|
+
if (identity.deadlineAt !== validated.deadlineAt) {
|
|
224
|
+
throw new Error("job progress previous snapshot deadlineAt does not match");
|
|
225
|
+
}
|
|
226
|
+
return validated;
|
|
227
|
+
}
|
|
228
|
+
function cloneSnapshot(snapshot) {
|
|
229
|
+
return structuredClone(snapshot);
|
|
230
|
+
}
|
|
231
|
+
function nonNegativeInteger(value, field) {
|
|
232
|
+
if (!Number.isSafeInteger(value) || value < 0) {
|
|
233
|
+
throw new Error(`${field} must be a non-negative safe integer`);
|
|
234
|
+
}
|
|
235
|
+
return value;
|
|
236
|
+
}
|
|
237
|
+
function positiveInteger(value, field) {
|
|
238
|
+
if (!Number.isSafeInteger(value) || value <= 0) {
|
|
239
|
+
throw new Error(`${field} must be a positive safe integer`);
|
|
240
|
+
}
|
|
241
|
+
return value;
|
|
242
|
+
}
|
|
243
|
+
//# sourceMappingURL=reporter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reporter.js","sourceRoot":"","sources":["../../src/job-progress/reporter.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,GAGjB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,mBAAmB,GAOpB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,0BAA0B,EAAE,2BAA2B,EAAE,MAAM,iBAAiB,CAAC;AAE1F,MAAM,2BAA2B,GAAG,MAAM,CAAC;AAC3C,MAAM,0BAA0B,GAAG,MAAM,CAAC;AAQ1C,MAAM,UAAU,yBAAyB,CACvC,OAAmC;IAEnC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;IAC9C,MAAM,iBAAiB,GAAG,kBAAkB,CAC1C,OAAO,CAAC,iBAAiB,IAAI,2BAA2B,EACxD,mBAAmB,CACpB,CAAC;IACF,MAAM,gBAAgB,GAAG,eAAe,CACtC,OAAO,CAAC,gBAAgB,IAAI,0BAA0B,EACtD,kBAAkB,CACnB,CAAC;IACF,IAAI,OAAO,GACT,OAAO,CAAC,gBAAgB,KAAK,SAAS;QACpC,CAAC,CAAC,2BAA2B,CAAC;YAC1B,MAAM,EAAE,mBAAmB;YAC3B,WAAW,EAAE,OAAO,CAAC,WAAW;YAChC,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,cAAc,EAAE,OAAO,CAAC,cAAc;YACtC,YAAY,EAAE,OAAO,CAAC,YAAY;YAClC,QAAQ,EAAE,CAAC;YACX,KAAK,EAAE,OAAO,CAAC,YAAY,IAAI,SAAS;YACxC,KAAK,EAAE,OAAO,CAAC,YAAY,IAAI,UAAU;YACzC,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,GAAG,CAAC,OAAO,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,CAAC;YAC/E,MAAM,EAAE,OAAO,CAAC,aAAa;SAC9B,CAAC;QACJ,CAAC,CAAC,wBAAwB,CAAC,OAAO,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAClE,MAAM,OAAO,GAAG,OAAO,CAAC,gBAAgB,KAAK,SAAS,CAAC;IACvD,IAAI,cAAc,GAAG,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,iBAAiB,CAAC;IACxF,IAAI,kBAAkB,GAAG,CAAC,CAAC,CAAC;IAC5B,IAAI,qBAAqB,GAAG,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5D,IAAI,eAA0C,CAAC;IAC/C,IAAI,IAAI,GAAkB,OAAO,CAAC,OAAO,EAAE,CAAC;IAE5C,MAAM,OAAO,GAAG,CAAC,QAA6B,EAAiB,EAAE;QAC/D,IAAI,kBAAkB,KAAK,QAAQ,CAAC,QAAQ,IAAI,eAAe,KAAK,SAAS,EAAE,CAAC;YAC9E,OAAO,eAAe,CAAC;QACzB,CAAC;QACD,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;QAChD,kBAAkB,GAAG,QAAQ,CAAC,QAAQ,CAAC;QACvC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAC7B,gBAAgB,CAAC,OAAO,CAAC,OAAO,EAAE,aAAa,CAAC,QAAQ,CAAC,EAAE,gBAAgB,CAAC,CAC7E,CAAC;QACF,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE;YACnD,MAAM,WAAW,CAAC,MAAM,CAAC;YACzB,qBAAqB,GAAG,IAAI,CAAC,GAAG,CAAC,qBAAqB,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAC7E,CAAC,CAAC,CAAC;QACH,eAAe,GAAG,SAAS,CAAC;QAC5B,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QACjF,KAAK,SAAS;aACX,OAAO,CAAC,GAAG,EAAE;YACZ,IAAI,kBAAkB,KAAK,QAAQ,CAAC,QAAQ,EAAE,CAAC;gBAC7C,kBAAkB,GAAG,CAAC,CAAC,CAAC;gBACxB,eAAe,GAAG,SAAS,CAAC;YAC9B,CAAC;QACH,CAAC,CAAC;aACD,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QAC1B,OAAO,SAAS,CAAC;IACnB,CAAC,CAAC;IAEF,OAAO;QACL,KAAK,CAAC,MAAM,CAAC,MAAM;YACjB,IAAI,0BAA0B,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC9C,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;YACvE,CAAC;YACD,IAAI,OAAO,CAAC,QAAQ,IAAI,MAAM,CAAC,gBAAgB,EAAE,CAAC;gBAChD,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;YACxD,CAAC;YACD,MAAM,SAAS,GAAG,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC;YACtC,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,OAAO,CAAC,KAAK,CAAC;YAC5C,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,OAAO,CAAC,KAAK,CAAC;YAC5C,MAAM,UAAU,GAAG,0BAA0B,CAAC,KAAK,CAAC;gBAClD,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,IAAI,SAAS,CAAC;gBAClC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC;YACtB,MAAM,MAAM,GAAG,0BAA0B,CAAC,KAAK,CAAC;gBAC9C,CAAC,CAAC,iBAAiB,CAAC,MAAM,CAAC,MAAM,IAAI,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC;gBAC3D,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;YACtC,MAAM,IAAI,GAAG,2BAA2B,CAAC;gBACvC,GAAG,OAAO;gBACV,QAAQ,EAAE,OAAO,CAAC,QAAQ,GAAG,CAAC;gBAC9B,KAAK;gBACL,KAAK;gBACL,SAAS,EAAE,SAAS;gBACpB,MAAM;gBACN,GAAG,CAAC,MAAM,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC;gBAC3D,GAAG,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC;aACpD,CAAC,CAAC;YACH,qBAAqB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;YACrC,MAAM,UAAU,GACd,MAAM,CAAC,KAAK,KAAK,IAAI;gBACrB,KAAK,KAAK,OAAO,CAAC,KAAK;gBACvB,0BAA0B,CAAC,KAAK,CAAC;gBACjC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,GAAG,cAAc,IAAI,iBAAiB,CAAC;YAC9D,OAAO,GAAG,IAAI,CAAC;YACf,IAAI,CAAC,UAAU;gBAAE,OAAO,EAAE,QAAQ,EAAE,aAAa,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;YAC5E,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;YACpB,OAAO,EAAE,QAAQ,EAAE,aAAa,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;QAC5D,CAAC;QAED,KAAK,CAAC,KAAK;YACT,MAAM,QAAQ,GAAG,OAAO,CAAC;YACzB,IAAI,qBAAqB,IAAI,QAAQ,CAAC,QAAQ,EAAE,CAAC;gBAC/C,MAAM,IAAI,CAAC;gBACX,OAAO,EAAE,QAAQ,EAAE,aAAa,CAAC,QAAQ,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;YACjE,CAAC;YACD,MAAM,OAAO,CAAC,QAAQ,CAAC,CAAC;YACxB,OAAO,EAAE,QAAQ,EAAE,aAAa,CAAC,QAAQ,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;QAChE,CAAC;QAED,QAAQ;YACN,OAAO,aAAa,CAAC,OAAO,CAAC,CAAC;QAChC,CAAC;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,SAAgC,EAChC,GAAG,GAAG,IAAI,IAAI,EAAE;IAEhB,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;IAC5E,MAAM,SAAS,GAAG,SAAS;SACxB,GAAG,CAAC,2BAA2B,CAAC;SAChC,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC;IACzD,MAAM,MAAM,GAAG,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,CAAwB,CAAC;IACvD,KAAK,MAAM,QAAQ,IAAI,SAAS;QAAE,kBAAkB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACvE,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,SAAS,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QACzD,MAAM,QAAQ,GAAG,SAAS,CAAC,KAAK,GAAG,CAAC,CAAwB,CAAC;QAC7D,MAAM,OAAO,GAAG,SAAS,CAAC,KAAK,CAAwB,CAAC;QACxD,IAAI,QAAQ,CAAC,QAAQ,KAAK,OAAO,CAAC,QAAQ,EAAE,CAAC;YAC3C,MAAM,IAAI,KAAK,CAAC,yBAAyB,OAAO,CAAC,QAAQ,gBAAgB,CAAC,CAAC;QAC7E,CAAC;QACD,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;YACnE,MAAM,IAAI,KAAK,CAAC,gEAAgE,CAAC,CAAC;QACpF,CAAC;IACH,CAAC;IACD,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACrD,MAAM,MAAM,GAAyB,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;QACpD,MAAM,OAAO,GAAqB,SAAS,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE;YAC/D,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC;YACzE,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,QAAQ,CAAC,SAAS,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;QACnF,CAAC,CAAC,CAAC;QACH,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,gBAAgB,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,CAAC,EAAE,CAAC;IACzE,CAAC,CAAC,CAAC;IACH,OAAO;QACL,QAAQ,EAAE,aAAa,CAAC,MAAM,CAAC;QAC/B,MAAM;QACN,SAAS,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC;KACjD,CAAC;AACJ,CAAC;AAED,SAAS,iBAAiB,CACxB,MAA0B,EAC1B,KAA2C;IAE3C,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAC5B,GAAG,EAAE,KAAK,CAAC,GAAG;QACd,IAAI,EAAE;YACJ,GAAG,KAAK,CAAC,IAAI;YACb,MAAM,EACJ,KAAK,CAAC,IAAI,CAAC,MAAM,KAAK,WAAW;gBACjC,KAAK,CAAC,IAAI,CAAC,MAAM,KAAK,QAAQ;gBAC9B,KAAK,CAAC,IAAI,CAAC,MAAM,KAAK,WAAW;gBAC/B,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM;gBACnB,CAAC,CAAC,KAAK;SACZ;KACF,CAAC,CAAC,CAAC;AACN,CAAC;AAED,SAAS,qBAAqB,CAAC,QAA6B,EAAE,IAAyB;IACrF,IAAI,QAAQ,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK;QAAE,OAAO;IAC1C,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAChC,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,KAAK,KAAK,CAAC,GAAG,CAAC,CAAC;QAC/E,IAAI,KAAK,KAAK,SAAS,IAAI,WAAW,CAAC,KAAK,EAAE,KAAK,CAAC;YAAE,SAAS;QAC/D,IACE,KAAK,CAAC,IAAI,CAAC,SAAS,KAAK,SAAS;YAClC,KAAK,CAAC,IAAI,CAAC,SAAS,KAAK,SAAS;YAClC,KAAK,CAAC,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,SAAS,EAC3C,CAAC;YACD,MAAM,IAAI,KAAK,CAAC,sBAAsB,KAAK,CAAC,GAAG,oCAAoC,CAAC,CAAC;QACvF,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAAC,QAA0B,EAAE,IAAsB;IACrE,OAAO,CACL,QAAQ,CAAC,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,IAAI,CAAC,KAAK;QACvC,QAAQ,CAAC,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,CAAC,IAAI;QACrC,QAAQ,CAAC,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,IAAI,CAAC,KAAK,CACxC,CAAC;AACJ,CAAC;AAED,SAAS,kBAAkB,CAAC,QAA6B,EAAE,MAA2B;IACpF,KAAK,MAAM,KAAK,IAAI;QAClB,aAAa;QACb,WAAW;QACX,OAAO;QACP,gBAAgB;QAChB,cAAc;QACd,WAAW;KACH,EAAE,CAAC;QACX,IAAI,QAAQ,CAAC,KAAK,CAAC,KAAK,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;YACtC,MAAM,IAAI,KAAK,CAAC,uBAAuB,KAAK,iBAAiB,CAAC,CAAC;QACjE,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,gBAAgB,CACvB,OAA8C,EAC9C,QAA6B,EAC7B,SAAiB;IAEjB,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,IAAI,OAAmC,CAAC;IACxC,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;IACnD,MAAM,QAAQ,GAAG,IAAI,OAAO,CAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE;QACvD,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE;YACxB,UAAU,CAAC,KAAK,EAAE,CAAC;YACnB,MAAM,CAAC,IAAI,KAAK,CAAC,4CAA4C,SAAS,KAAK,CAAC,CAAC,CAAC;QAChF,CAAC,EAAE,SAAS,CAAC,CAAC;IAChB,CAAC,CAAC,CAAC;IACH,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE;QAC1D,IAAI,OAAO,KAAK,SAAS;YAAE,YAAY,CAAC,OAAO,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IACH,OAAO;QACL,MAAM;QACN,OAAO,EAAE,KAAK,CAAC,IAAI,CACjB,GAAG,EAAE,CAAC,SAAS,EACf,GAAG,EAAE,CAAC,SAAS,CAChB;KACF,CAAC;AACJ,CAAC;AAED,SAAS,wBAAwB,CAC/B,QAAoC,EACpC,QAA6B;IAE7B,MAAM,SAAS,GAAG,2BAA2B,CAAC,QAAQ,CAAC,CAAC;IACxD,KAAK,MAAM,KAAK,IAAI;QAClB,aAAa;QACb,WAAW;QACX,OAAO;QACP,gBAAgB;QAChB,cAAc;QACd,WAAW;KACH,EAAE,CAAC;QACX,IAAI,QAAQ,CAAC,KAAK,CAAC,KAAK,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;YACzC,MAAM,IAAI,KAAK,CAAC,kCAAkC,KAAK,iBAAiB,CAAC,CAAC;QAC5E,CAAC;IACH,CAAC;IACD,IAAI,0BAA0B,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;QAChD,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;IACzE,CAAC;IACD,IAAI,QAAQ,CAAC,UAAU,KAAK,SAAS,CAAC,UAAU,EAAE,CAAC;QACjD,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAC;IAC9E,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,aAAa,CAAC,QAA6B;IAClD,OAAO,eAAe,CAAC,QAAQ,CAAC,CAAC;AACnC,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAa,EAAE,KAAa;IACtD,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QAC9C,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,sCAAsC,CAAC,CAAC;IAClE,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,eAAe,CAAC,KAAa,EAAE,KAAa;IACnD,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;QAC/C,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,kCAAkC,CAAC,CAAC;IAC9D,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { ProgressEstimate, ProgressTrackState, WorkflowProgressData } from "../workflows/index.js";
|
|
2
|
+
export declare const JOB_PROGRESS_SCHEMA: "pi-workflows.job-progress.v1";
|
|
3
|
+
export type JobProgressState = "queued" | "running" | "waiting" | "blocked" | "completed" | "failed" | "cancelled" | "unknown";
|
|
4
|
+
export type JobProgressTrack = {
|
|
5
|
+
key: string;
|
|
6
|
+
data: WorkflowProgressData;
|
|
7
|
+
};
|
|
8
|
+
export type JobProgressCost = {
|
|
9
|
+
settledUsd: number;
|
|
10
|
+
reservedUsd: number;
|
|
11
|
+
};
|
|
12
|
+
export type JobProgressSnapshot = {
|
|
13
|
+
schema: typeof JOB_PROGRESS_SCHEMA;
|
|
14
|
+
application: string;
|
|
15
|
+
component: string;
|
|
16
|
+
jobId: string;
|
|
17
|
+
sourceRevision: string;
|
|
18
|
+
contractHash: string;
|
|
19
|
+
sequence: number;
|
|
20
|
+
state: JobProgressState;
|
|
21
|
+
phase: string;
|
|
22
|
+
startedAt: string;
|
|
23
|
+
updatedAt: string;
|
|
24
|
+
deadlineAt?: string;
|
|
25
|
+
finishedAt?: string;
|
|
26
|
+
tracks: JobProgressTrack[];
|
|
27
|
+
cost?: JobProgressCost;
|
|
28
|
+
};
|
|
29
|
+
export type JobProgressIdentity = Pick<JobProgressSnapshot, "application" | "component" | "jobId" | "sourceRevision" | "contractHash" | "startedAt"> & {
|
|
30
|
+
deadlineAt?: string;
|
|
31
|
+
};
|
|
32
|
+
export type JobProgressUpdate = {
|
|
33
|
+
state?: JobProgressState;
|
|
34
|
+
phase?: string;
|
|
35
|
+
tracks?: JobProgressTrack[];
|
|
36
|
+
cost?: JobProgressCost;
|
|
37
|
+
finishedAt?: string;
|
|
38
|
+
force?: boolean;
|
|
39
|
+
};
|
|
40
|
+
export type JobProgressPublish = (snapshot: JobProgressSnapshot, signal: AbortSignal) => Promise<void>;
|
|
41
|
+
type JobProgressReporterBaseOptions = JobProgressIdentity & {
|
|
42
|
+
initialState?: Exclude<JobProgressState, "completed" | "failed" | "cancelled">;
|
|
43
|
+
initialPhase?: string;
|
|
44
|
+
publish: JobProgressPublish;
|
|
45
|
+
minimumIntervalMs?: number;
|
|
46
|
+
publishTimeoutMs?: number;
|
|
47
|
+
now?: () => Date;
|
|
48
|
+
};
|
|
49
|
+
export type JobProgressReporterOptions = JobProgressReporterBaseOptions & ({
|
|
50
|
+
initialTracks: JobProgressTrack[];
|
|
51
|
+
previousSnapshot?: never;
|
|
52
|
+
} | {
|
|
53
|
+
initialTracks?: JobProgressTrack[];
|
|
54
|
+
previousSnapshot: JobProgressSnapshot;
|
|
55
|
+
});
|
|
56
|
+
export type JobProgressPublishResult = {
|
|
57
|
+
snapshot: JobProgressSnapshot;
|
|
58
|
+
published: boolean;
|
|
59
|
+
};
|
|
60
|
+
export type JobProgressEstimate = {
|
|
61
|
+
snapshot: JobProgressSnapshot;
|
|
62
|
+
tracks: ProgressTrackState[];
|
|
63
|
+
estimates: ProgressEstimate[];
|
|
64
|
+
};
|
|
65
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/job-progress/types.ts"],"names":[],"mappings":"AAMA,MAAM,CAAC,MAAM,mBAAmB,GAAG,8BAAuC,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { type JobProgressSnapshot, type JobProgressState } from "./types.js";
|
|
2
|
+
export declare const MAX_JOB_PROGRESS_BYTES: number;
|
|
3
|
+
export declare const MAX_JOB_PROGRESS_TRACKS = 128;
|
|
4
|
+
export declare function validateJobProgressSnapshot(value: unknown): JobProgressSnapshot;
|
|
5
|
+
export declare function isTerminalJobProgressState(state: JobProgressState): state is "completed" | "failed" | "cancelled";
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import { validateProgressData } from "../workflows/index.js";
|
|
2
|
+
import { JOB_PROGRESS_SCHEMA, } from "./types.js";
|
|
3
|
+
export const MAX_JOB_PROGRESS_BYTES = 64 * 1024;
|
|
4
|
+
export const MAX_JOB_PROGRESS_TRACKS = 128;
|
|
5
|
+
const SNAPSHOT_FIELDS = new Set([
|
|
6
|
+
"schema",
|
|
7
|
+
"application",
|
|
8
|
+
"component",
|
|
9
|
+
"jobId",
|
|
10
|
+
"sourceRevision",
|
|
11
|
+
"contractHash",
|
|
12
|
+
"sequence",
|
|
13
|
+
"state",
|
|
14
|
+
"phase",
|
|
15
|
+
"startedAt",
|
|
16
|
+
"updatedAt",
|
|
17
|
+
"deadlineAt",
|
|
18
|
+
"finishedAt",
|
|
19
|
+
"tracks",
|
|
20
|
+
"cost",
|
|
21
|
+
]);
|
|
22
|
+
const TRACK_FIELDS = new Set(["key", "data"]);
|
|
23
|
+
const COST_FIELDS = new Set(["settledUsd", "reservedUsd"]);
|
|
24
|
+
const STATES = new Set([
|
|
25
|
+
"queued",
|
|
26
|
+
"running",
|
|
27
|
+
"waiting",
|
|
28
|
+
"blocked",
|
|
29
|
+
"completed",
|
|
30
|
+
"failed",
|
|
31
|
+
"cancelled",
|
|
32
|
+
"unknown",
|
|
33
|
+
]);
|
|
34
|
+
const KEY_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._:/-]{0,127}$/;
|
|
35
|
+
const RFC_3339_PATTERN = /^(\d{4})-(\d{2})-(\d{2})T(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z|[+-](?:[01]\d|2[0-3]):[0-5]\d)$/;
|
|
36
|
+
export function validateJobProgressSnapshot(value) {
|
|
37
|
+
const bytes = jsonBytes(value);
|
|
38
|
+
if (bytes > MAX_JOB_PROGRESS_BYTES) {
|
|
39
|
+
throw new Error(`job progress snapshot must be at most ${MAX_JOB_PROGRESS_BYTES} bytes`);
|
|
40
|
+
}
|
|
41
|
+
if (!isRecord(value))
|
|
42
|
+
throw new Error("job progress snapshot must be an object");
|
|
43
|
+
rejectUnknown(value, SNAPSHOT_FIELDS, "job progress");
|
|
44
|
+
if (value.schema !== JOB_PROGRESS_SCHEMA) {
|
|
45
|
+
throw new Error(`job progress.schema must equal ${JOB_PROGRESS_SCHEMA}`);
|
|
46
|
+
}
|
|
47
|
+
const application = requiredText(value.application, "job progress.application", 100);
|
|
48
|
+
const component = requiredText(value.component, "job progress.component", 100);
|
|
49
|
+
const jobId = requiredText(value.jobId, "job progress.jobId", 200);
|
|
50
|
+
const sourceRevision = requiredText(value.sourceRevision, "job progress.sourceRevision", 200);
|
|
51
|
+
const contractHash = requiredText(value.contractHash, "job progress.contractHash", 200);
|
|
52
|
+
const sequence = requiredInteger(value.sequence, "job progress.sequence");
|
|
53
|
+
const state = requiredState(value.state);
|
|
54
|
+
const phase = requiredText(value.phase, "job progress.phase", 100);
|
|
55
|
+
const startedAt = requiredTimestamp(value.startedAt, "job progress.startedAt");
|
|
56
|
+
const updatedAt = requiredTimestamp(value.updatedAt, "job progress.updatedAt");
|
|
57
|
+
const deadlineAt = optionalTimestamp(value.deadlineAt, "job progress.deadlineAt");
|
|
58
|
+
const finishedAt = optionalTimestamp(value.finishedAt, "job progress.finishedAt");
|
|
59
|
+
const tracks = requiredTracks(value.tracks);
|
|
60
|
+
const cost = optionalCost(value.cost);
|
|
61
|
+
if (Date.parse(updatedAt) < Date.parse(startedAt)) {
|
|
62
|
+
throw new Error("job progress.updatedAt must not be before startedAt");
|
|
63
|
+
}
|
|
64
|
+
if (deadlineAt !== undefined && Date.parse(deadlineAt) <= Date.parse(startedAt)) {
|
|
65
|
+
throw new Error("job progress.deadlineAt must be after startedAt");
|
|
66
|
+
}
|
|
67
|
+
if (finishedAt !== undefined && Date.parse(finishedAt) < Date.parse(startedAt)) {
|
|
68
|
+
throw new Error("job progress.finishedAt must not be before startedAt");
|
|
69
|
+
}
|
|
70
|
+
if (finishedAt !== undefined && Date.parse(finishedAt) > Date.parse(updatedAt)) {
|
|
71
|
+
throw new Error("job progress.finishedAt must not be after updatedAt");
|
|
72
|
+
}
|
|
73
|
+
if (isTerminal(state) && finishedAt === undefined) {
|
|
74
|
+
throw new Error("job progress.finishedAt is required for a terminal state");
|
|
75
|
+
}
|
|
76
|
+
if (!isTerminal(state) && finishedAt !== undefined) {
|
|
77
|
+
throw new Error("job progress.finishedAt is allowed only for a terminal state");
|
|
78
|
+
}
|
|
79
|
+
if (isTerminal(state) && tracks.some((track) => !isTerminalTrack(track))) {
|
|
80
|
+
throw new Error("job progress tracks must be terminal when the job state is terminal");
|
|
81
|
+
}
|
|
82
|
+
return {
|
|
83
|
+
schema: JOB_PROGRESS_SCHEMA,
|
|
84
|
+
application,
|
|
85
|
+
component,
|
|
86
|
+
jobId,
|
|
87
|
+
sourceRevision,
|
|
88
|
+
contractHash,
|
|
89
|
+
sequence,
|
|
90
|
+
state,
|
|
91
|
+
phase,
|
|
92
|
+
startedAt,
|
|
93
|
+
updatedAt,
|
|
94
|
+
...(deadlineAt === undefined ? {} : { deadlineAt }),
|
|
95
|
+
...(finishedAt === undefined ? {} : { finishedAt }),
|
|
96
|
+
tracks,
|
|
97
|
+
...(cost === undefined ? {} : { cost }),
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
export function isTerminalJobProgressState(state) {
|
|
101
|
+
return isTerminal(state);
|
|
102
|
+
}
|
|
103
|
+
function requiredTracks(value) {
|
|
104
|
+
if (!Array.isArray(value))
|
|
105
|
+
throw new Error("job progress.tracks must be an array");
|
|
106
|
+
if (value.length < 1)
|
|
107
|
+
throw new Error("job progress.tracks must contain at least one entry");
|
|
108
|
+
if (value.length > MAX_JOB_PROGRESS_TRACKS) {
|
|
109
|
+
throw new Error(`job progress.tracks must contain at most ${MAX_JOB_PROGRESS_TRACKS} entries`);
|
|
110
|
+
}
|
|
111
|
+
const keys = new Set();
|
|
112
|
+
return value.map((item, index) => {
|
|
113
|
+
if (!isRecord(item))
|
|
114
|
+
throw new Error(`job progress.tracks[${index}] must be an object`);
|
|
115
|
+
rejectUnknown(item, TRACK_FIELDS, `job progress.tracks[${index}]`);
|
|
116
|
+
if (typeof item.key !== "string" || !KEY_PATTERN.test(item.key)) {
|
|
117
|
+
throw new Error(`job progress.tracks[${index}].key must match [A-Za-z0-9][A-Za-z0-9._:/-]{0,127}`);
|
|
118
|
+
}
|
|
119
|
+
if (keys.has(item.key))
|
|
120
|
+
throw new Error(`job progress track key ${item.key} is duplicated`);
|
|
121
|
+
keys.add(item.key);
|
|
122
|
+
if (!isRecord(item.data)) {
|
|
123
|
+
throw new Error(`job progress.tracks[${index}].data must be an object`);
|
|
124
|
+
}
|
|
125
|
+
return { key: item.key, data: structuredClone(validateProgressData(item.data)) };
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
function optionalCost(value) {
|
|
129
|
+
if (value === undefined)
|
|
130
|
+
return undefined;
|
|
131
|
+
if (!isRecord(value))
|
|
132
|
+
throw new Error("job progress.cost must be an object");
|
|
133
|
+
rejectUnknown(value, COST_FIELDS, "job progress.cost");
|
|
134
|
+
return {
|
|
135
|
+
settledUsd: requiredNonNegative(value.settledUsd, "job progress.cost.settledUsd"),
|
|
136
|
+
reservedUsd: requiredNonNegative(value.reservedUsd, "job progress.cost.reservedUsd"),
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
function requiredState(value) {
|
|
140
|
+
if (typeof value !== "string" || !STATES.has(value)) {
|
|
141
|
+
throw new Error("job progress.state is invalid");
|
|
142
|
+
}
|
|
143
|
+
return value;
|
|
144
|
+
}
|
|
145
|
+
function requiredText(value, field, max) {
|
|
146
|
+
if (typeof value !== "string" || value.trim().length < 1 || value.trim().length > max) {
|
|
147
|
+
throw new Error(`${field} must be 1 to ${max} characters`);
|
|
148
|
+
}
|
|
149
|
+
if ([...value].some(isControlCharacter))
|
|
150
|
+
throw new Error(`${field} must not contain control characters`);
|
|
151
|
+
return value;
|
|
152
|
+
}
|
|
153
|
+
function requiredInteger(value, field) {
|
|
154
|
+
if (!Number.isSafeInteger(value) || value < 0) {
|
|
155
|
+
throw new Error(`${field} must be a non-negative safe integer`);
|
|
156
|
+
}
|
|
157
|
+
return value;
|
|
158
|
+
}
|
|
159
|
+
function requiredNonNegative(value, field) {
|
|
160
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value < 0) {
|
|
161
|
+
throw new Error(`${field} must be a finite non-negative number`);
|
|
162
|
+
}
|
|
163
|
+
return value;
|
|
164
|
+
}
|
|
165
|
+
function requiredTimestamp(value, field) {
|
|
166
|
+
const parsed = optionalTimestamp(value, field);
|
|
167
|
+
if (parsed === undefined)
|
|
168
|
+
throw new Error(`${field} is required`);
|
|
169
|
+
return parsed;
|
|
170
|
+
}
|
|
171
|
+
function optionalTimestamp(value, field) {
|
|
172
|
+
if (value === undefined)
|
|
173
|
+
return undefined;
|
|
174
|
+
if (typeof value !== "string") {
|
|
175
|
+
throw new Error(`${field} must be an RFC 3339 timestamp with an offset`);
|
|
176
|
+
}
|
|
177
|
+
const match = RFC_3339_PATTERN.exec(value);
|
|
178
|
+
if (match === null || !validCalendarDate(match[1], match[2], match[3])) {
|
|
179
|
+
throw new Error(`${field} must be an RFC 3339 timestamp with an offset`);
|
|
180
|
+
}
|
|
181
|
+
return value;
|
|
182
|
+
}
|
|
183
|
+
function validCalendarDate(yearText, monthText, dayText) {
|
|
184
|
+
const year = Number(yearText);
|
|
185
|
+
const month = Number(monthText);
|
|
186
|
+
const day = Number(dayText);
|
|
187
|
+
if (!Number.isInteger(year) || year < 1 || month < 1 || month > 12 || day < 1)
|
|
188
|
+
return false;
|
|
189
|
+
return day <= new Date(Date.UTC(year, month, 0)).getUTCDate();
|
|
190
|
+
}
|
|
191
|
+
function rejectUnknown(value, allowed, field) {
|
|
192
|
+
for (const key of Object.keys(value)) {
|
|
193
|
+
if (!allowed.has(key))
|
|
194
|
+
throw new Error(`${field}.${key} is not supported`);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
function isRecord(value) {
|
|
198
|
+
if (value === null || typeof value !== "object" || Array.isArray(value))
|
|
199
|
+
return false;
|
|
200
|
+
const prototype = Object.getPrototypeOf(value);
|
|
201
|
+
return prototype === Object.prototype || prototype === null;
|
|
202
|
+
}
|
|
203
|
+
function jsonBytes(value) {
|
|
204
|
+
let encoded;
|
|
205
|
+
try {
|
|
206
|
+
encoded = JSON.stringify(value);
|
|
207
|
+
}
|
|
208
|
+
catch {
|
|
209
|
+
throw new Error("job progress snapshot must be JSON serializable");
|
|
210
|
+
}
|
|
211
|
+
if (encoded === undefined)
|
|
212
|
+
throw new Error("job progress snapshot must be JSON serializable");
|
|
213
|
+
return Buffer.byteLength(encoded, "utf8");
|
|
214
|
+
}
|
|
215
|
+
function isControlCharacter(character) {
|
|
216
|
+
const code = character.codePointAt(0) ?? 0;
|
|
217
|
+
return code < 32 || (code >= 127 && code <= 159);
|
|
218
|
+
}
|
|
219
|
+
function isTerminal(state) {
|
|
220
|
+
return state === "completed" || state === "failed" || state === "cancelled";
|
|
221
|
+
}
|
|
222
|
+
function isTerminalTrack(track) {
|
|
223
|
+
return (track.data.status === "completed" ||
|
|
224
|
+
track.data.status === "failed" ||
|
|
225
|
+
track.data.status === "cancelled");
|
|
226
|
+
}
|
|
227
|
+
//# sourceMappingURL=validation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/job-progress/validation.ts"],"names":[],"mappings":"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"}
|