@humain/humain-code-contracts 0.3.2
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/CHANGELOG.md +51 -0
- package/README.md +92 -0
- package/dist/index.d.ts +224 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +218 -0
- package/dist/index.js.map +1 -0
- package/dist/orchestration.d.ts +327 -0
- package/dist/orchestration.d.ts.map +1 -0
- package/dist/orchestration.js +307 -0
- package/dist/orchestration.js.map +1 -0
- package/dist/rpc.d.ts +63 -0
- package/dist/rpc.d.ts.map +1 -0
- package/dist/rpc.js +147 -0
- package/dist/rpc.js.map +1 -0
- package/dist/subagent-progress.d.ts +106 -0
- package/dist/subagent-progress.d.ts.map +1 -0
- package/dist/subagent-progress.js +440 -0
- package/dist/subagent-progress.js.map +1 -0
- package/dist/testing.d.ts +390 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +431 -0
- package/dist/testing.js.map +1 -0
- package/dist/trace-api.d.ts +293 -0
- package/dist/trace-api.d.ts.map +1 -0
- package/dist/trace-api.js +202 -0
- package/dist/trace-api.js.map +1 -0
- package/dist/trace-artifact.d.ts +94 -0
- package/dist/trace-artifact.d.ts.map +1 -0
- package/dist/trace-artifact.js +168 -0
- package/dist/trace-artifact.js.map +1 -0
- package/dist/trace-canonical.d.ts +23 -0
- package/dist/trace-canonical.d.ts.map +1 -0
- package/dist/trace-canonical.js +240 -0
- package/dist/trace-canonical.js.map +1 -0
- package/dist/trace-export.d.ts +94 -0
- package/dist/trace-export.d.ts.map +1 -0
- package/dist/trace-export.js +374 -0
- package/dist/trace-export.js.map +1 -0
- package/dist/trace-http.d.ts +1294 -0
- package/dist/trace-http.d.ts.map +1 -0
- package/dist/trace-http.js +1481 -0
- package/dist/trace-http.js.map +1 -0
- package/dist/trace-payload.d.ts +425 -0
- package/dist/trace-payload.d.ts.map +1 -0
- package/dist/trace-payload.js +1519 -0
- package/dist/trace-payload.js.map +1 -0
- package/dist/trace.d.ts +257 -0
- package/dist/trace.d.ts.map +1 -0
- package/dist/trace.js +1014 -0
- package/dist/trace.js.map +1 -0
- package/package.json +64 -0
|
@@ -0,0 +1,440 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Subagent progress projection contract (C1, schemaVersion 1).
|
|
3
|
+
*
|
|
4
|
+
* This module is the runtime-neutral core of the contract: it imports nothing, uses no Node APIs and no
|
|
5
|
+
* schema library, so the `./rpc` entry can validate progress metadata without pulling TypeBox. The
|
|
6
|
+
* TypeBox schemas in `orchestration.ts` describe the same shapes and are checked against the types here
|
|
7
|
+
* at compile time.
|
|
8
|
+
*/
|
|
9
|
+
export const SUBAGENT_PROGRESS_SCHEMA_VERSION = 1;
|
|
10
|
+
export const SUBAGENT_WORKER_STATUSES = [
|
|
11
|
+
"queued",
|
|
12
|
+
"waiting",
|
|
13
|
+
"running",
|
|
14
|
+
"completed",
|
|
15
|
+
"failed",
|
|
16
|
+
"cancelled",
|
|
17
|
+
"skipped",
|
|
18
|
+
"unresolved",
|
|
19
|
+
];
|
|
20
|
+
export const SUBAGENT_CANCELLATION_OUTCOMES = [
|
|
21
|
+
"none",
|
|
22
|
+
"not_started",
|
|
23
|
+
"direct_worker_terminated",
|
|
24
|
+
"unconfirmed",
|
|
25
|
+
];
|
|
26
|
+
export const SUBAGENT_FAILURE_KINDS = ["spawn_failed", "process_error", "model_error", "merge_failed"];
|
|
27
|
+
export const SUBAGENT_RUN_MODES = ["single", "parallel", "chain"];
|
|
28
|
+
export const SUBAGENT_PROGRESS_MAX_RUNS = 64;
|
|
29
|
+
export const SUBAGENT_PROGRESS_MAX_FINALIZED_RUNS = 16;
|
|
30
|
+
export const SUBAGENT_PROGRESS_MAX_WORKERS_PER_RUN = 32;
|
|
31
|
+
export const SUBAGENT_PROGRESS_MAX_RUN_UTF8_BYTES = 64 * 1024;
|
|
32
|
+
export const SUBAGENT_PROGRESS_MAX_RUN_CODE_UNITS = 64 * 1024;
|
|
33
|
+
export const SUBAGENT_PROGRESS_MAX_RETAINED_RUNS_UTF8_BYTES = 64 * 64 * 1024;
|
|
34
|
+
export const SUBAGENT_PROGRESS_MAX_ENVELOPE_UTF8_BYTES = 4 * 1024 * 1024 + 64 * 1024;
|
|
35
|
+
export const SUBAGENT_PROGRESS_MAX_ENVELOPE_CODE_UNITS = 4 * 1024 * 1024 + 64 * 1024;
|
|
36
|
+
export const SUBAGENT_PROGRESS_TASK_MAX_CODE_UNITS = 120;
|
|
37
|
+
export const SUBAGENT_PROGRESS_RESULT_PREVIEW_MAX_CODE_UNITS = 160;
|
|
38
|
+
export const SUBAGENT_PROGRESS_AGENT_MAX_CODE_UNITS = 64;
|
|
39
|
+
export const SUBAGENT_PROGRESS_LABEL_MAX_CODE_UNITS = 64;
|
|
40
|
+
export const SUBAGENT_PROGRESS_MODEL_MAX_CODE_UNITS = 128;
|
|
41
|
+
export const SUBAGENT_PROGRESS_TOOL_CALL_ID_MAX_CODE_UNITS = 256;
|
|
42
|
+
/** Regular-expression sources shared with the TypeBox schemas in `orchestration.ts`. */
|
|
43
|
+
export const SUBAGENT_PROGRESS_UUID_PATTERN = "^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$";
|
|
44
|
+
export const SUBAGENT_PROGRESS_IDENTIFIER_PATTERN = "^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$";
|
|
45
|
+
export const SUBAGENT_PROGRESS_MODEL_PATTERN = "^[A-Za-z0-9][A-Za-z0-9._:/@+-]{0,127}$";
|
|
46
|
+
export const SUBAGENT_PROGRESS_TOOL_CALL_ID_PATTERN = "^[\\x21-\\x7E]{1,256}$";
|
|
47
|
+
/** Structural subset of the presentation-text rule; the parsers additionally reject lone surrogates and edge whitespace. */
|
|
48
|
+
export const SUBAGENT_PROGRESS_TEXT_PATTERN = "^[^\\u0000-\\u001F\\u007F-\\u009F\\u00AD\\u034F\\u061C\\u180E\\u200B-\\u200F\\u2028-\\u202E\\u2060-\\u2069\\uFEFF]+$";
|
|
49
|
+
const UUID_REGEX = new RegExp(SUBAGENT_PROGRESS_UUID_PATTERN);
|
|
50
|
+
const IDENTIFIER_REGEX = new RegExp(SUBAGENT_PROGRESS_IDENTIFIER_PATTERN);
|
|
51
|
+
const MODEL_REGEX = new RegExp(SUBAGENT_PROGRESS_MODEL_PATTERN);
|
|
52
|
+
const TOOL_CALL_ID_REGEX = new RegExp(SUBAGENT_PROGRESS_TOOL_CALL_ID_PATTERN);
|
|
53
|
+
/** True only for lowercase canonical v4 UUIDs as produced by `crypto.randomUUID()`. */
|
|
54
|
+
export function isCanonicalSubagentProgressUuid(value) {
|
|
55
|
+
return typeof value === "string" && value.length === 36 && UUID_REGEX.test(value);
|
|
56
|
+
}
|
|
57
|
+
const progressTextEncoder = new TextEncoder();
|
|
58
|
+
/**
|
|
59
|
+
* Compact JSON size in UTF-8 bytes and UTF-16 code units.
|
|
60
|
+
* Intended for plain normalized snapshots only; it does not sanitize arbitrary input.
|
|
61
|
+
* Throws a fixed error if the value does not serialize to a JSON string.
|
|
62
|
+
*/
|
|
63
|
+
export function measureSubagentProgressJson(value) {
|
|
64
|
+
let text;
|
|
65
|
+
try {
|
|
66
|
+
text = JSON.stringify(value);
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
throw invalidSnapshot();
|
|
70
|
+
}
|
|
71
|
+
if (typeof text !== "string")
|
|
72
|
+
throw invalidSnapshot();
|
|
73
|
+
return { utf8Bytes: progressTextEncoder.encode(text).length, codeUnits: text.length };
|
|
74
|
+
}
|
|
75
|
+
function isForbiddenTextCodeUnit(unit) {
|
|
76
|
+
return (unit <= 0x1f ||
|
|
77
|
+
(unit >= 0x7f && unit <= 0x9f) ||
|
|
78
|
+
unit === 0xad ||
|
|
79
|
+
unit === 0x34f ||
|
|
80
|
+
unit === 0x61c ||
|
|
81
|
+
unit === 0x180e ||
|
|
82
|
+
(unit >= 0x200b && unit <= 0x200f) ||
|
|
83
|
+
(unit >= 0x2028 && unit <= 0x202e) ||
|
|
84
|
+
(unit >= 0x2060 && unit <= 0x2069) ||
|
|
85
|
+
unit === 0xfeff);
|
|
86
|
+
}
|
|
87
|
+
function isHighSurrogate(unit) {
|
|
88
|
+
return unit >= 0xd800 && unit <= 0xdbff;
|
|
89
|
+
}
|
|
90
|
+
function isLowSurrogate(unit) {
|
|
91
|
+
return unit >= 0xdc00 && unit <= 0xdfff;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Presentation text: non-empty, at most `max` UTF-16 code units, no leading/trailing whitespace,
|
|
95
|
+
* no lone surrogates and no control, bidirectional-control, zero-width or line/paragraph separator characters.
|
|
96
|
+
*/
|
|
97
|
+
export function isSubagentPresentationText(value, max) {
|
|
98
|
+
if (typeof value !== "string" || value.length === 0 || value.length > max || value !== value.trim())
|
|
99
|
+
return false;
|
|
100
|
+
for (let i = 0; i < value.length; i++) {
|
|
101
|
+
const unit = value.charCodeAt(i);
|
|
102
|
+
if (isHighSurrogate(unit)) {
|
|
103
|
+
if (!isLowSurrogate(value.charCodeAt(i + 1)))
|
|
104
|
+
return false;
|
|
105
|
+
i += 1;
|
|
106
|
+
}
|
|
107
|
+
else if (isLowSurrogate(unit) || isForbiddenTextCodeUnit(unit)) {
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return true;
|
|
112
|
+
}
|
|
113
|
+
/** Code units examined by `toSubagentPresentationText`: once while skipping leading blanks, once while collecting. */
|
|
114
|
+
export const SUBAGENT_PRESENTATION_SCAN_WINDOW_CODE_UNITS = 4096;
|
|
115
|
+
const WHITESPACE_UNIT_REGEX = /\s/;
|
|
116
|
+
/** True for a code unit (at `index`) that the sanitizer turns into a separator: whitespace, forbidden, lone surrogate. */
|
|
117
|
+
function isSeparatorAt(input, index) {
|
|
118
|
+
const unit = input.charCodeAt(index);
|
|
119
|
+
if (isHighSurrogate(unit))
|
|
120
|
+
return !isLowSurrogate(input.charCodeAt(index + 1));
|
|
121
|
+
return isLowSurrogate(unit) || isForbiddenTextCodeUnit(unit) || WHITESPACE_UNIT_REGEX.test(input[index]);
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Producer helper: turns arbitrary input into presentation text or null.
|
|
125
|
+
* Forbidden characters, whitespace and lone surrogates act as separators; separator runs collapse to one space and
|
|
126
|
+
* leading/trailing separators are dropped. Output longer than `max` is cut on a code-point boundary to `max - 1`
|
|
127
|
+
* code units plus "…".
|
|
128
|
+
*
|
|
129
|
+
* Work is bounded regardless of input size: at most `SUBAGENT_PRESENTATION_SCAN_WINDOW_CODE_UNITS` code units are
|
|
130
|
+
* skipped at the start (an input that is only separators within that window yields null) and at most that many more
|
|
131
|
+
* are examined while collecting at most `max` code units of output. Input left unexamined when the collecting window
|
|
132
|
+
* ends is treated as truncated. The input is never passed to replace/split/trim.
|
|
133
|
+
* A non-null result always satisfies `isSubagentPresentationText(result, max)`.
|
|
134
|
+
*/
|
|
135
|
+
export function toSubagentPresentationText(input, max) {
|
|
136
|
+
if (typeof input !== "string" || max < 2)
|
|
137
|
+
return null;
|
|
138
|
+
const length = input.length;
|
|
139
|
+
let i = 0;
|
|
140
|
+
const skipEnd = Math.min(length, SUBAGENT_PRESENTATION_SCAN_WINDOW_CODE_UNITS);
|
|
141
|
+
while (i < skipEnd && isSeparatorAt(input, i))
|
|
142
|
+
i += 1;
|
|
143
|
+
if (i === length || i === skipEnd)
|
|
144
|
+
return null;
|
|
145
|
+
const collectEnd = Math.min(length, i + SUBAGENT_PRESENTATION_SCAN_WINDOW_CODE_UNITS);
|
|
146
|
+
let out = "";
|
|
147
|
+
let pendingSpace = false;
|
|
148
|
+
let truncated = false;
|
|
149
|
+
while (i < collectEnd) {
|
|
150
|
+
if (isSeparatorAt(input, i)) {
|
|
151
|
+
pendingSpace = true;
|
|
152
|
+
i += 1;
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
const width = isHighSurrogate(input.charCodeAt(i)) ? 2 : 1;
|
|
156
|
+
if (out.length + (pendingSpace ? 1 : 0) + width > max) {
|
|
157
|
+
truncated = true;
|
|
158
|
+
break;
|
|
159
|
+
}
|
|
160
|
+
if (pendingSpace) {
|
|
161
|
+
out += " ";
|
|
162
|
+
pendingSpace = false;
|
|
163
|
+
}
|
|
164
|
+
out += input.slice(i, i + width);
|
|
165
|
+
i += width;
|
|
166
|
+
}
|
|
167
|
+
if (!truncated && i < length)
|
|
168
|
+
truncated = true;
|
|
169
|
+
if (!truncated)
|
|
170
|
+
return out;
|
|
171
|
+
let end = Math.min(out.length, max - 1);
|
|
172
|
+
if (isHighSurrogate(out.charCodeAt(end - 1)))
|
|
173
|
+
end -= 1;
|
|
174
|
+
if (out.charCodeAt(end - 1) === 0x20)
|
|
175
|
+
end -= 1;
|
|
176
|
+
return `${out.slice(0, end)}…`;
|
|
177
|
+
}
|
|
178
|
+
function invalidSnapshot() {
|
|
179
|
+
return new Error("Invalid subagent progress snapshot");
|
|
180
|
+
}
|
|
181
|
+
function isTerminalStatus(status) {
|
|
182
|
+
return status !== "queued" && status !== "waiting" && status !== "running";
|
|
183
|
+
}
|
|
184
|
+
function assertWorkerInvariants(worker, runFinal) {
|
|
185
|
+
const { status, attempt, cancelRequested, cancellationOutcome: outcome } = worker;
|
|
186
|
+
let valid = true;
|
|
187
|
+
if (status === "unresolved" && !runFinal)
|
|
188
|
+
valid = false;
|
|
189
|
+
if (runFinal && !isTerminalStatus(status))
|
|
190
|
+
valid = false;
|
|
191
|
+
if (status === "unresolved" && attempt < 1)
|
|
192
|
+
valid = false;
|
|
193
|
+
if (status === "unresolved" && cancelRequested && outcome !== "unconfirmed")
|
|
194
|
+
valid = false;
|
|
195
|
+
if (!isTerminalStatus(status) && cancelRequested && outcome !== "unconfirmed")
|
|
196
|
+
valid = false;
|
|
197
|
+
if (!cancelRequested && outcome !== "none")
|
|
198
|
+
valid = false;
|
|
199
|
+
if (status === "cancelled") {
|
|
200
|
+
if (!cancelRequested || (outcome !== "not_started" && outcome !== "direct_worker_terminated"))
|
|
201
|
+
valid = false;
|
|
202
|
+
}
|
|
203
|
+
else if (outcome === "not_started" || outcome === "direct_worker_terminated") {
|
|
204
|
+
valid = false;
|
|
205
|
+
}
|
|
206
|
+
if (outcome === "not_started" && attempt !== 0)
|
|
207
|
+
valid = false;
|
|
208
|
+
if (outcome === "direct_worker_terminated" && attempt < 1)
|
|
209
|
+
valid = false;
|
|
210
|
+
if ((status === "running" || status === "completed") && attempt < 1)
|
|
211
|
+
valid = false;
|
|
212
|
+
if ((status === "queued" || status === "waiting" || status === "skipped") && attempt !== 0)
|
|
213
|
+
valid = false;
|
|
214
|
+
if (worker.failureKind !== null && status !== "failed")
|
|
215
|
+
valid = false;
|
|
216
|
+
if (worker.resultPreview !== null && status !== "completed" && status !== "failed")
|
|
217
|
+
valid = false;
|
|
218
|
+
if ((worker.startedAt !== null) !== attempt >= 1)
|
|
219
|
+
valid = false;
|
|
220
|
+
if (worker.endedAt !== null) {
|
|
221
|
+
if (worker.startedAt === null || !isTerminalStatus(status) || worker.endedAt < worker.startedAt)
|
|
222
|
+
valid = false;
|
|
223
|
+
}
|
|
224
|
+
if (!valid)
|
|
225
|
+
throw invalidSnapshot();
|
|
226
|
+
}
|
|
227
|
+
function assertRunInvariants(run) {
|
|
228
|
+
if ((run.endedAt !== null) !== run.final || (run.endedAt !== null && run.endedAt < run.startedAt)) {
|
|
229
|
+
throw invalidSnapshot();
|
|
230
|
+
}
|
|
231
|
+
const workerIds = new Set();
|
|
232
|
+
for (const worker of run.workers) {
|
|
233
|
+
if (workerIds.has(worker.workerId))
|
|
234
|
+
throw invalidSnapshot();
|
|
235
|
+
workerIds.add(worker.workerId);
|
|
236
|
+
assertWorkerInvariants(worker, run.final);
|
|
237
|
+
}
|
|
238
|
+
const size = measureSubagentProgressJson(run);
|
|
239
|
+
if (size.utf8Bytes > SUBAGENT_PROGRESS_MAX_RUN_UTF8_BYTES || size.codeUnits > SUBAGENT_PROGRESS_MAX_RUN_CODE_UNITS) {
|
|
240
|
+
throw invalidSnapshot();
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
const RUN_KEYS = ["runId", "seq", "final", "workers", "toolCallId", "mode", "startedAt", "endedAt"];
|
|
244
|
+
const WORKER_KEYS = [
|
|
245
|
+
"workerId",
|
|
246
|
+
"attempt",
|
|
247
|
+
"status",
|
|
248
|
+
"cancelRequested",
|
|
249
|
+
"cancellationOutcome",
|
|
250
|
+
"agent",
|
|
251
|
+
"label",
|
|
252
|
+
"task",
|
|
253
|
+
"model",
|
|
254
|
+
"startedAt",
|
|
255
|
+
"endedAt",
|
|
256
|
+
"turns",
|
|
257
|
+
"toolCalls",
|
|
258
|
+
"failureKind",
|
|
259
|
+
"resultPreview",
|
|
260
|
+
];
|
|
261
|
+
const ENVELOPE_KEYS = ["schemaVersion", "runtimeId", "sessionEpoch", "complete", "runs"];
|
|
262
|
+
/**
|
|
263
|
+
* Reads the exact fixed own data fields of a plain object; never invokes accessors.
|
|
264
|
+
* Proxy reflection traps (getPrototypeOf/ownKeys/getOwnPropertyDescriptor) may still run:
|
|
265
|
+
* executable objects are outside the trust model beyond error masking (callers catch and
|
|
266
|
+
* normalize every failure to a fixed message).
|
|
267
|
+
*/
|
|
268
|
+
function readPlainFields(value, keys) {
|
|
269
|
+
if (value === null || typeof value !== "object" || Array.isArray(value))
|
|
270
|
+
throw invalidSnapshot();
|
|
271
|
+
const proto = Object.getPrototypeOf(value);
|
|
272
|
+
if (proto !== Object.prototype && proto !== null)
|
|
273
|
+
throw invalidSnapshot();
|
|
274
|
+
const own = Reflect.ownKeys(value);
|
|
275
|
+
if (own.length !== keys.length)
|
|
276
|
+
throw invalidSnapshot();
|
|
277
|
+
const out = {};
|
|
278
|
+
for (const key of keys) {
|
|
279
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
280
|
+
if (!descriptor?.enumerable || !("value" in descriptor))
|
|
281
|
+
throw invalidSnapshot();
|
|
282
|
+
out[key] = descriptor.value;
|
|
283
|
+
}
|
|
284
|
+
// Equal counts and every expected key present as a string key => no extra or symbol keys.
|
|
285
|
+
return out;
|
|
286
|
+
}
|
|
287
|
+
/** Returns the dense element values of a plain array after enforcing the cap before touching any element. */
|
|
288
|
+
function readPlainArray(value, maxItems) {
|
|
289
|
+
if (!Array.isArray(value) || Object.getPrototypeOf(value) !== Array.prototype)
|
|
290
|
+
throw invalidSnapshot();
|
|
291
|
+
const lengthDescriptor = Object.getOwnPropertyDescriptor(value, "length");
|
|
292
|
+
const length = lengthDescriptor?.value;
|
|
293
|
+
if (typeof length !== "number" || !Number.isInteger(length) || length < 0 || length > maxItems) {
|
|
294
|
+
throw invalidSnapshot();
|
|
295
|
+
}
|
|
296
|
+
const own = Reflect.ownKeys(value);
|
|
297
|
+
if (own.length !== length + 1 || own[length] !== "length")
|
|
298
|
+
throw invalidSnapshot();
|
|
299
|
+
const out = [];
|
|
300
|
+
for (let i = 0; i < length; i++) {
|
|
301
|
+
if (own[i] !== String(i))
|
|
302
|
+
throw invalidSnapshot();
|
|
303
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, i);
|
|
304
|
+
if (!descriptor?.enumerable || !("value" in descriptor))
|
|
305
|
+
throw invalidSnapshot();
|
|
306
|
+
out.push(descriptor.value);
|
|
307
|
+
}
|
|
308
|
+
return out;
|
|
309
|
+
}
|
|
310
|
+
function readUuid(value) {
|
|
311
|
+
if (!isCanonicalSubagentProgressUuid(value))
|
|
312
|
+
throw invalidSnapshot();
|
|
313
|
+
return value;
|
|
314
|
+
}
|
|
315
|
+
function readBoolean(value) {
|
|
316
|
+
if (typeof value !== "boolean")
|
|
317
|
+
throw invalidSnapshot();
|
|
318
|
+
return value;
|
|
319
|
+
}
|
|
320
|
+
function readInteger(value, minimum) {
|
|
321
|
+
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < minimum)
|
|
322
|
+
throw invalidSnapshot();
|
|
323
|
+
return value;
|
|
324
|
+
}
|
|
325
|
+
function readNullableInteger(value) {
|
|
326
|
+
return value === null ? null : readInteger(value, 0);
|
|
327
|
+
}
|
|
328
|
+
function readMember(value, allowed) {
|
|
329
|
+
const member = allowed.find((candidate) => candidate === value);
|
|
330
|
+
if (member === undefined)
|
|
331
|
+
throw invalidSnapshot();
|
|
332
|
+
return member;
|
|
333
|
+
}
|
|
334
|
+
function readNullableMember(value, allowed) {
|
|
335
|
+
return value === null ? null : readMember(value, allowed);
|
|
336
|
+
}
|
|
337
|
+
function readNullablePattern(value, pattern) {
|
|
338
|
+
if (value === null)
|
|
339
|
+
return null;
|
|
340
|
+
if (typeof value !== "string" || !pattern.test(value))
|
|
341
|
+
throw invalidSnapshot();
|
|
342
|
+
return value;
|
|
343
|
+
}
|
|
344
|
+
function readNullableText(value, max) {
|
|
345
|
+
if (value === null)
|
|
346
|
+
return null;
|
|
347
|
+
if (!isSubagentPresentationText(value, max))
|
|
348
|
+
throw invalidSnapshot();
|
|
349
|
+
return value;
|
|
350
|
+
}
|
|
351
|
+
function readWorker(value) {
|
|
352
|
+
const f = readPlainFields(value, WORKER_KEYS);
|
|
353
|
+
return {
|
|
354
|
+
workerId: readUuid(f.workerId),
|
|
355
|
+
attempt: readInteger(f.attempt, 0),
|
|
356
|
+
status: readMember(f.status, SUBAGENT_WORKER_STATUSES),
|
|
357
|
+
cancelRequested: readBoolean(f.cancelRequested),
|
|
358
|
+
cancellationOutcome: readMember(f.cancellationOutcome, SUBAGENT_CANCELLATION_OUTCOMES),
|
|
359
|
+
agent: readNullablePattern(f.agent, IDENTIFIER_REGEX),
|
|
360
|
+
label: readNullablePattern(f.label, IDENTIFIER_REGEX),
|
|
361
|
+
task: readNullableText(f.task, SUBAGENT_PROGRESS_TASK_MAX_CODE_UNITS),
|
|
362
|
+
model: readNullablePattern(f.model, MODEL_REGEX),
|
|
363
|
+
startedAt: readNullableInteger(f.startedAt),
|
|
364
|
+
endedAt: readNullableInteger(f.endedAt),
|
|
365
|
+
turns: readInteger(f.turns, 0),
|
|
366
|
+
toolCalls: readInteger(f.toolCalls, 0),
|
|
367
|
+
failureKind: readNullableMember(f.failureKind, SUBAGENT_FAILURE_KINDS),
|
|
368
|
+
resultPreview: readNullableText(f.resultPreview, SUBAGENT_PROGRESS_RESULT_PREVIEW_MAX_CODE_UNITS),
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
function readRun(value) {
|
|
372
|
+
const f = readPlainFields(value, RUN_KEYS);
|
|
373
|
+
return {
|
|
374
|
+
runId: readUuid(f.runId),
|
|
375
|
+
seq: readInteger(f.seq, 1),
|
|
376
|
+
final: readBoolean(f.final),
|
|
377
|
+
workers: readPlainArray(f.workers, SUBAGENT_PROGRESS_MAX_WORKERS_PER_RUN).map(readWorker),
|
|
378
|
+
toolCallId: readNullablePattern(f.toolCallId, TOOL_CALL_ID_REGEX),
|
|
379
|
+
mode: readMember(f.mode, SUBAGENT_RUN_MODES),
|
|
380
|
+
startedAt: readInteger(f.startedAt, 0),
|
|
381
|
+
endedAt: readNullableInteger(f.endedAt),
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
function readEnvelope(value) {
|
|
385
|
+
const f = readPlainFields(value, ENVELOPE_KEYS);
|
|
386
|
+
if (f.schemaVersion !== SUBAGENT_PROGRESS_SCHEMA_VERSION)
|
|
387
|
+
throw invalidSnapshot();
|
|
388
|
+
return {
|
|
389
|
+
schemaVersion: SUBAGENT_PROGRESS_SCHEMA_VERSION,
|
|
390
|
+
runtimeId: readUuid(f.runtimeId),
|
|
391
|
+
sessionEpoch: readUuid(f.sessionEpoch),
|
|
392
|
+
complete: readBoolean(f.complete),
|
|
393
|
+
runs: readPlainArray(f.runs, SUBAGENT_PROGRESS_MAX_RUNS).map(readRun),
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
export function parseSubagentRunSnapshot(value) {
|
|
397
|
+
try {
|
|
398
|
+
const run = readRun(value);
|
|
399
|
+
assertRunInvariants(run);
|
|
400
|
+
return deepFreeze(run);
|
|
401
|
+
}
|
|
402
|
+
catch {
|
|
403
|
+
throw invalidSnapshot();
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
export function parseSubagentProgressSnapshot(value) {
|
|
407
|
+
try {
|
|
408
|
+
const snapshot = readEnvelope(value);
|
|
409
|
+
const runIds = new Set();
|
|
410
|
+
let finalized = 0;
|
|
411
|
+
for (const run of snapshot.runs) {
|
|
412
|
+
if (runIds.has(run.runId))
|
|
413
|
+
throw invalidSnapshot();
|
|
414
|
+
runIds.add(run.runId);
|
|
415
|
+
if (run.final)
|
|
416
|
+
finalized += 1;
|
|
417
|
+
assertRunInvariants(run);
|
|
418
|
+
}
|
|
419
|
+
if (finalized > SUBAGENT_PROGRESS_MAX_FINALIZED_RUNS)
|
|
420
|
+
throw invalidSnapshot();
|
|
421
|
+
const size = measureSubagentProgressJson(snapshot);
|
|
422
|
+
if (size.utf8Bytes > SUBAGENT_PROGRESS_MAX_ENVELOPE_UTF8_BYTES ||
|
|
423
|
+
size.codeUnits > SUBAGENT_PROGRESS_MAX_ENVELOPE_CODE_UNITS) {
|
|
424
|
+
throw invalidSnapshot();
|
|
425
|
+
}
|
|
426
|
+
return deepFreeze(snapshot);
|
|
427
|
+
}
|
|
428
|
+
catch {
|
|
429
|
+
throw invalidSnapshot();
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
function deepFreeze(value) {
|
|
433
|
+
if (value === null || typeof value !== "object" || Object.isFrozen(value))
|
|
434
|
+
return value;
|
|
435
|
+
Object.freeze(value);
|
|
436
|
+
for (const child of Object.values(value))
|
|
437
|
+
deepFreeze(child);
|
|
438
|
+
return value;
|
|
439
|
+
}
|
|
440
|
+
//# sourceMappingURL=subagent-progress.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subagent-progress.js","sourceRoot":"","sources":["../src/subagent-progress.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Subagent progress projection contract (C1, schemaVersion 1).\n *\n * This module is the runtime-neutral core of the contract: it imports nothing, uses no Node APIs and no\n * schema library, so the `./rpc` entry can validate progress metadata without pulling TypeBox. The\n * TypeBox schemas in `orchestration.ts` describe the same shapes and are checked against the types here\n * at compile time.\n */\n\nexport const SUBAGENT_PROGRESS_SCHEMA_VERSION = 1 as const;\n\nexport const SUBAGENT_WORKER_STATUSES = [\n\t\"queued\",\n\t\"waiting\",\n\t\"running\",\n\t\"completed\",\n\t\"failed\",\n\t\"cancelled\",\n\t\"skipped\",\n\t\"unresolved\",\n] as const;\nexport type SubagentWorkerStatus = (typeof SUBAGENT_WORKER_STATUSES)[number];\n\nexport const SUBAGENT_CANCELLATION_OUTCOMES = [\n\t\"none\",\n\t\"not_started\",\n\t\"direct_worker_terminated\",\n\t\"unconfirmed\",\n] as const;\nexport type SubagentCancellationOutcome = (typeof SUBAGENT_CANCELLATION_OUTCOMES)[number];\n\nexport const SUBAGENT_FAILURE_KINDS = [\"spawn_failed\", \"process_error\", \"model_error\", \"merge_failed\"] as const;\nexport type SubagentFailureKind = (typeof SUBAGENT_FAILURE_KINDS)[number];\n\nexport const SUBAGENT_RUN_MODES = [\"single\", \"parallel\", \"chain\"] as const;\nexport type SubagentRunMode = (typeof SUBAGENT_RUN_MODES)[number];\n\nexport const SUBAGENT_PROGRESS_MAX_RUNS = 64;\nexport const SUBAGENT_PROGRESS_MAX_FINALIZED_RUNS = 16;\nexport const SUBAGENT_PROGRESS_MAX_WORKERS_PER_RUN = 32;\nexport const SUBAGENT_PROGRESS_MAX_RUN_UTF8_BYTES = 64 * 1024;\nexport const SUBAGENT_PROGRESS_MAX_RUN_CODE_UNITS = 64 * 1024;\nexport const SUBAGENT_PROGRESS_MAX_RETAINED_RUNS_UTF8_BYTES = 64 * 64 * 1024;\nexport const SUBAGENT_PROGRESS_MAX_ENVELOPE_UTF8_BYTES = 4 * 1024 * 1024 + 64 * 1024;\nexport const SUBAGENT_PROGRESS_MAX_ENVELOPE_CODE_UNITS = 4 * 1024 * 1024 + 64 * 1024;\n\nexport const SUBAGENT_PROGRESS_TASK_MAX_CODE_UNITS = 120;\nexport const SUBAGENT_PROGRESS_RESULT_PREVIEW_MAX_CODE_UNITS = 160;\nexport const SUBAGENT_PROGRESS_AGENT_MAX_CODE_UNITS = 64;\nexport const SUBAGENT_PROGRESS_LABEL_MAX_CODE_UNITS = 64;\nexport const SUBAGENT_PROGRESS_MODEL_MAX_CODE_UNITS = 128;\nexport const SUBAGENT_PROGRESS_TOOL_CALL_ID_MAX_CODE_UNITS = 256;\n\n/** Regular-expression sources shared with the TypeBox schemas in `orchestration.ts`. */\nexport const SUBAGENT_PROGRESS_UUID_PATTERN = \"^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$\";\nexport const SUBAGENT_PROGRESS_IDENTIFIER_PATTERN = \"^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$\";\nexport const SUBAGENT_PROGRESS_MODEL_PATTERN = \"^[A-Za-z0-9][A-Za-z0-9._:/@+-]{0,127}$\";\nexport const SUBAGENT_PROGRESS_TOOL_CALL_ID_PATTERN = \"^[\\\\x21-\\\\x7E]{1,256}$\";\n/** Structural subset of the presentation-text rule; the parsers additionally reject lone surrogates and edge whitespace. */\nexport const SUBAGENT_PROGRESS_TEXT_PATTERN =\n\t\"^[^\\\\u0000-\\\\u001F\\\\u007F-\\\\u009F\\\\u00AD\\\\u034F\\\\u061C\\\\u180E\\\\u200B-\\\\u200F\\\\u2028-\\\\u202E\\\\u2060-\\\\u2069\\\\uFEFF]+$\";\n\nconst UUID_REGEX = new RegExp(SUBAGENT_PROGRESS_UUID_PATTERN);\nconst IDENTIFIER_REGEX = new RegExp(SUBAGENT_PROGRESS_IDENTIFIER_PATTERN);\nconst MODEL_REGEX = new RegExp(SUBAGENT_PROGRESS_MODEL_PATTERN);\nconst TOOL_CALL_ID_REGEX = new RegExp(SUBAGENT_PROGRESS_TOOL_CALL_ID_PATTERN);\n\nexport interface SubagentWorkerSnapshot {\n\tworkerId: string;\n\tattempt: number;\n\tstatus: SubagentWorkerStatus;\n\tcancelRequested: boolean;\n\tcancellationOutcome: SubagentCancellationOutcome;\n\tagent: string | null;\n\tlabel: string | null;\n\ttask: string | null;\n\tmodel: string | null;\n\tstartedAt: number | null;\n\tendedAt: number | null;\n\tturns: number;\n\ttoolCalls: number;\n\tfailureKind: SubagentFailureKind | null;\n\tresultPreview: string | null;\n}\n\nexport interface SubagentRunSnapshot {\n\trunId: string;\n\tseq: number;\n\tfinal: boolean;\n\tworkers: SubagentWorkerSnapshot[];\n\ttoolCallId: string | null;\n\tmode: SubagentRunMode;\n\tstartedAt: number;\n\tendedAt: number | null;\n}\n\nexport interface SubagentProgressSnapshot {\n\tschemaVersion: typeof SUBAGENT_PROGRESS_SCHEMA_VERSION;\n\truntimeId: string;\n\tsessionEpoch: string;\n\tcomplete: boolean;\n\truns: SubagentRunSnapshot[];\n}\n\n/** True only for lowercase canonical v4 UUIDs as produced by `crypto.randomUUID()`. */\nexport function isCanonicalSubagentProgressUuid(value: unknown): value is string {\n\treturn typeof value === \"string\" && value.length === 36 && UUID_REGEX.test(value);\n}\n\nconst progressTextEncoder = new TextEncoder();\n\n/**\n * Compact JSON size in UTF-8 bytes and UTF-16 code units.\n * Intended for plain normalized snapshots only; it does not sanitize arbitrary input.\n * Throws a fixed error if the value does not serialize to a JSON string.\n */\nexport function measureSubagentProgressJson(value: unknown): { utf8Bytes: number; codeUnits: number } {\n\tlet text: unknown;\n\ttry {\n\t\ttext = JSON.stringify(value);\n\t} catch {\n\t\tthrow invalidSnapshot();\n\t}\n\tif (typeof text !== \"string\") throw invalidSnapshot();\n\treturn { utf8Bytes: progressTextEncoder.encode(text).length, codeUnits: text.length };\n}\n\nfunction isForbiddenTextCodeUnit(unit: number): boolean {\n\treturn (\n\t\tunit <= 0x1f ||\n\t\t(unit >= 0x7f && unit <= 0x9f) ||\n\t\tunit === 0xad ||\n\t\tunit === 0x34f ||\n\t\tunit === 0x61c ||\n\t\tunit === 0x180e ||\n\t\t(unit >= 0x200b && unit <= 0x200f) ||\n\t\t(unit >= 0x2028 && unit <= 0x202e) ||\n\t\t(unit >= 0x2060 && unit <= 0x2069) ||\n\t\tunit === 0xfeff\n\t);\n}\n\nfunction isHighSurrogate(unit: number): boolean {\n\treturn unit >= 0xd800 && unit <= 0xdbff;\n}\n\nfunction isLowSurrogate(unit: number): boolean {\n\treturn unit >= 0xdc00 && unit <= 0xdfff;\n}\n\n/**\n * Presentation text: non-empty, at most `max` UTF-16 code units, no leading/trailing whitespace,\n * no lone surrogates and no control, bidirectional-control, zero-width or line/paragraph separator characters.\n */\nexport function isSubagentPresentationText(value: unknown, max: number): value is string {\n\tif (typeof value !== \"string\" || value.length === 0 || value.length > max || value !== value.trim()) return false;\n\tfor (let i = 0; i < value.length; i++) {\n\t\tconst unit = value.charCodeAt(i);\n\t\tif (isHighSurrogate(unit)) {\n\t\t\tif (!isLowSurrogate(value.charCodeAt(i + 1))) return false;\n\t\t\ti += 1;\n\t\t} else if (isLowSurrogate(unit) || isForbiddenTextCodeUnit(unit)) {\n\t\t\treturn false;\n\t\t}\n\t}\n\treturn true;\n}\n\n/** Code units examined by `toSubagentPresentationText`: once while skipping leading blanks, once while collecting. */\nexport const SUBAGENT_PRESENTATION_SCAN_WINDOW_CODE_UNITS = 4096;\n\nconst WHITESPACE_UNIT_REGEX = /\\s/;\n\n/** True for a code unit (at `index`) that the sanitizer turns into a separator: whitespace, forbidden, lone surrogate. */\nfunction isSeparatorAt(input: string, index: number): boolean {\n\tconst unit = input.charCodeAt(index);\n\tif (isHighSurrogate(unit)) return !isLowSurrogate(input.charCodeAt(index + 1));\n\treturn isLowSurrogate(unit) || isForbiddenTextCodeUnit(unit) || WHITESPACE_UNIT_REGEX.test(input[index]);\n}\n\n/**\n * Producer helper: turns arbitrary input into presentation text or null.\n * Forbidden characters, whitespace and lone surrogates act as separators; separator runs collapse to one space and\n * leading/trailing separators are dropped. Output longer than `max` is cut on a code-point boundary to `max - 1`\n * code units plus \"…\".\n *\n * Work is bounded regardless of input size: at most `SUBAGENT_PRESENTATION_SCAN_WINDOW_CODE_UNITS` code units are\n * skipped at the start (an input that is only separators within that window yields null) and at most that many more\n * are examined while collecting at most `max` code units of output. Input left unexamined when the collecting window\n * ends is treated as truncated. The input is never passed to replace/split/trim.\n * A non-null result always satisfies `isSubagentPresentationText(result, max)`.\n */\nexport function toSubagentPresentationText(input: unknown, max: number): string | null {\n\tif (typeof input !== \"string\" || max < 2) return null;\n\tconst length = input.length;\n\tlet i = 0;\n\tconst skipEnd = Math.min(length, SUBAGENT_PRESENTATION_SCAN_WINDOW_CODE_UNITS);\n\twhile (i < skipEnd && isSeparatorAt(input, i)) i += 1;\n\tif (i === length || i === skipEnd) return null;\n\n\tconst collectEnd = Math.min(length, i + SUBAGENT_PRESENTATION_SCAN_WINDOW_CODE_UNITS);\n\tlet out = \"\";\n\tlet pendingSpace = false;\n\tlet truncated = false;\n\twhile (i < collectEnd) {\n\t\tif (isSeparatorAt(input, i)) {\n\t\t\tpendingSpace = true;\n\t\t\ti += 1;\n\t\t\tcontinue;\n\t\t}\n\t\tconst width = isHighSurrogate(input.charCodeAt(i)) ? 2 : 1;\n\t\tif (out.length + (pendingSpace ? 1 : 0) + width > max) {\n\t\t\ttruncated = true;\n\t\t\tbreak;\n\t\t}\n\t\tif (pendingSpace) {\n\t\t\tout += \" \";\n\t\t\tpendingSpace = false;\n\t\t}\n\t\tout += input.slice(i, i + width);\n\t\ti += width;\n\t}\n\tif (!truncated && i < length) truncated = true;\n\tif (!truncated) return out;\n\tlet end = Math.min(out.length, max - 1);\n\tif (isHighSurrogate(out.charCodeAt(end - 1))) end -= 1;\n\tif (out.charCodeAt(end - 1) === 0x20) end -= 1;\n\treturn `${out.slice(0, end)}…`;\n}\n\nfunction invalidSnapshot(): Error {\n\treturn new Error(\"Invalid subagent progress snapshot\");\n}\n\nfunction isTerminalStatus(status: SubagentWorkerStatus): boolean {\n\treturn status !== \"queued\" && status !== \"waiting\" && status !== \"running\";\n}\n\nfunction assertWorkerInvariants(worker: SubagentWorkerSnapshot, runFinal: boolean): void {\n\tconst { status, attempt, cancelRequested, cancellationOutcome: outcome } = worker;\n\tlet valid = true;\n\tif (status === \"unresolved\" && !runFinal) valid = false;\n\tif (runFinal && !isTerminalStatus(status)) valid = false;\n\tif (status === \"unresolved\" && attempt < 1) valid = false;\n\tif (status === \"unresolved\" && cancelRequested && outcome !== \"unconfirmed\") valid = false;\n\tif (!isTerminalStatus(status) && cancelRequested && outcome !== \"unconfirmed\") valid = false;\n\tif (!cancelRequested && outcome !== \"none\") valid = false;\n\tif (status === \"cancelled\") {\n\t\tif (!cancelRequested || (outcome !== \"not_started\" && outcome !== \"direct_worker_terminated\")) valid = false;\n\t} else if (outcome === \"not_started\" || outcome === \"direct_worker_terminated\") {\n\t\tvalid = false;\n\t}\n\tif (outcome === \"not_started\" && attempt !== 0) valid = false;\n\tif (outcome === \"direct_worker_terminated\" && attempt < 1) valid = false;\n\tif ((status === \"running\" || status === \"completed\") && attempt < 1) valid = false;\n\tif ((status === \"queued\" || status === \"waiting\" || status === \"skipped\") && attempt !== 0) valid = false;\n\tif (worker.failureKind !== null && status !== \"failed\") valid = false;\n\tif (worker.resultPreview !== null && status !== \"completed\" && status !== \"failed\") valid = false;\n\tif ((worker.startedAt !== null) !== attempt >= 1) valid = false;\n\tif (worker.endedAt !== null) {\n\t\tif (worker.startedAt === null || !isTerminalStatus(status) || worker.endedAt < worker.startedAt) valid = false;\n\t}\n\tif (!valid) throw invalidSnapshot();\n}\n\nfunction assertRunInvariants(run: SubagentRunSnapshot): void {\n\tif ((run.endedAt !== null) !== run.final || (run.endedAt !== null && run.endedAt < run.startedAt)) {\n\t\tthrow invalidSnapshot();\n\t}\n\tconst workerIds = new Set<string>();\n\tfor (const worker of run.workers) {\n\t\tif (workerIds.has(worker.workerId)) throw invalidSnapshot();\n\t\tworkerIds.add(worker.workerId);\n\t\tassertWorkerInvariants(worker, run.final);\n\t}\n\tconst size = measureSubagentProgressJson(run);\n\tif (size.utf8Bytes > SUBAGENT_PROGRESS_MAX_RUN_UTF8_BYTES || size.codeUnits > SUBAGENT_PROGRESS_MAX_RUN_CODE_UNITS) {\n\t\tthrow invalidSnapshot();\n\t}\n}\n\nconst RUN_KEYS = [\"runId\", \"seq\", \"final\", \"workers\", \"toolCallId\", \"mode\", \"startedAt\", \"endedAt\"] as const;\nconst WORKER_KEYS = [\n\t\"workerId\",\n\t\"attempt\",\n\t\"status\",\n\t\"cancelRequested\",\n\t\"cancellationOutcome\",\n\t\"agent\",\n\t\"label\",\n\t\"task\",\n\t\"model\",\n\t\"startedAt\",\n\t\"endedAt\",\n\t\"turns\",\n\t\"toolCalls\",\n\t\"failureKind\",\n\t\"resultPreview\",\n] as const;\nconst ENVELOPE_KEYS = [\"schemaVersion\", \"runtimeId\", \"sessionEpoch\", \"complete\", \"runs\"] as const;\n\n/**\n * Reads the exact fixed own data fields of a plain object; never invokes accessors.\n * Proxy reflection traps (getPrototypeOf/ownKeys/getOwnPropertyDescriptor) may still run:\n * executable objects are outside the trust model beyond error masking (callers catch and\n * normalize every failure to a fixed message).\n */\nfunction readPlainFields(value: unknown, keys: readonly string[]): Record<string, unknown> {\n\tif (value === null || typeof value !== \"object\" || Array.isArray(value)) throw invalidSnapshot();\n\tconst proto = Object.getPrototypeOf(value);\n\tif (proto !== Object.prototype && proto !== null) throw invalidSnapshot();\n\tconst own = Reflect.ownKeys(value);\n\tif (own.length !== keys.length) throw invalidSnapshot();\n\tconst out: Record<string, unknown> = {};\n\tfor (const key of keys) {\n\t\tconst descriptor = Object.getOwnPropertyDescriptor(value, key);\n\t\tif (!descriptor?.enumerable || !(\"value\" in descriptor)) throw invalidSnapshot();\n\t\tout[key] = descriptor.value;\n\t}\n\t// Equal counts and every expected key present as a string key => no extra or symbol keys.\n\treturn out;\n}\n\n/** Returns the dense element values of a plain array after enforcing the cap before touching any element. */\nfunction readPlainArray(value: unknown, maxItems: number): unknown[] {\n\tif (!Array.isArray(value) || Object.getPrototypeOf(value) !== Array.prototype) throw invalidSnapshot();\n\tconst lengthDescriptor = Object.getOwnPropertyDescriptor(value, \"length\");\n\tconst length = lengthDescriptor?.value;\n\tif (typeof length !== \"number\" || !Number.isInteger(length) || length < 0 || length > maxItems) {\n\t\tthrow invalidSnapshot();\n\t}\n\tconst own = Reflect.ownKeys(value);\n\tif (own.length !== length + 1 || own[length] !== \"length\") throw invalidSnapshot();\n\tconst out: unknown[] = [];\n\tfor (let i = 0; i < length; i++) {\n\t\tif (own[i] !== String(i)) throw invalidSnapshot();\n\t\tconst descriptor = Object.getOwnPropertyDescriptor(value, i);\n\t\tif (!descriptor?.enumerable || !(\"value\" in descriptor)) throw invalidSnapshot();\n\t\tout.push(descriptor.value);\n\t}\n\treturn out;\n}\n\nfunction readUuid(value: unknown): string {\n\tif (!isCanonicalSubagentProgressUuid(value)) throw invalidSnapshot();\n\treturn value;\n}\n\nfunction readBoolean(value: unknown): boolean {\n\tif (typeof value !== \"boolean\") throw invalidSnapshot();\n\treturn value;\n}\n\nfunction readInteger(value: unknown, minimum: number): number {\n\tif (typeof value !== \"number\" || !Number.isSafeInteger(value) || value < minimum) throw invalidSnapshot();\n\treturn value;\n}\n\nfunction readNullableInteger(value: unknown): number | null {\n\treturn value === null ? null : readInteger(value, 0);\n}\n\nfunction readMember<T extends string>(value: unknown, allowed: readonly T[]): T {\n\tconst member = allowed.find((candidate) => candidate === value);\n\tif (member === undefined) throw invalidSnapshot();\n\treturn member;\n}\n\nfunction readNullableMember<T extends string>(value: unknown, allowed: readonly T[]): T | null {\n\treturn value === null ? null : readMember(value, allowed);\n}\n\nfunction readNullablePattern(value: unknown, pattern: RegExp): string | null {\n\tif (value === null) return null;\n\tif (typeof value !== \"string\" || !pattern.test(value)) throw invalidSnapshot();\n\treturn value;\n}\n\nfunction readNullableText(value: unknown, max: number): string | null {\n\tif (value === null) return null;\n\tif (!isSubagentPresentationText(value, max)) throw invalidSnapshot();\n\treturn value;\n}\n\nfunction readWorker(value: unknown): SubagentWorkerSnapshot {\n\tconst f = readPlainFields(value, WORKER_KEYS);\n\treturn {\n\t\tworkerId: readUuid(f.workerId),\n\t\tattempt: readInteger(f.attempt, 0),\n\t\tstatus: readMember(f.status, SUBAGENT_WORKER_STATUSES),\n\t\tcancelRequested: readBoolean(f.cancelRequested),\n\t\tcancellationOutcome: readMember(f.cancellationOutcome, SUBAGENT_CANCELLATION_OUTCOMES),\n\t\tagent: readNullablePattern(f.agent, IDENTIFIER_REGEX),\n\t\tlabel: readNullablePattern(f.label, IDENTIFIER_REGEX),\n\t\ttask: readNullableText(f.task, SUBAGENT_PROGRESS_TASK_MAX_CODE_UNITS),\n\t\tmodel: readNullablePattern(f.model, MODEL_REGEX),\n\t\tstartedAt: readNullableInteger(f.startedAt),\n\t\tendedAt: readNullableInteger(f.endedAt),\n\t\tturns: readInteger(f.turns, 0),\n\t\ttoolCalls: readInteger(f.toolCalls, 0),\n\t\tfailureKind: readNullableMember(f.failureKind, SUBAGENT_FAILURE_KINDS),\n\t\tresultPreview: readNullableText(f.resultPreview, SUBAGENT_PROGRESS_RESULT_PREVIEW_MAX_CODE_UNITS),\n\t};\n}\n\nfunction readRun(value: unknown): SubagentRunSnapshot {\n\tconst f = readPlainFields(value, RUN_KEYS);\n\treturn {\n\t\trunId: readUuid(f.runId),\n\t\tseq: readInteger(f.seq, 1),\n\t\tfinal: readBoolean(f.final),\n\t\tworkers: readPlainArray(f.workers, SUBAGENT_PROGRESS_MAX_WORKERS_PER_RUN).map(readWorker),\n\t\ttoolCallId: readNullablePattern(f.toolCallId, TOOL_CALL_ID_REGEX),\n\t\tmode: readMember(f.mode, SUBAGENT_RUN_MODES),\n\t\tstartedAt: readInteger(f.startedAt, 0),\n\t\tendedAt: readNullableInteger(f.endedAt),\n\t};\n}\n\nfunction readEnvelope(value: unknown): SubagentProgressSnapshot {\n\tconst f = readPlainFields(value, ENVELOPE_KEYS);\n\tif (f.schemaVersion !== SUBAGENT_PROGRESS_SCHEMA_VERSION) throw invalidSnapshot();\n\treturn {\n\t\tschemaVersion: SUBAGENT_PROGRESS_SCHEMA_VERSION,\n\t\truntimeId: readUuid(f.runtimeId),\n\t\tsessionEpoch: readUuid(f.sessionEpoch),\n\t\tcomplete: readBoolean(f.complete),\n\t\truns: readPlainArray(f.runs, SUBAGENT_PROGRESS_MAX_RUNS).map(readRun),\n\t};\n}\n\nexport function parseSubagentRunSnapshot(value: unknown): SubagentRunSnapshot {\n\ttry {\n\t\tconst run = readRun(value);\n\t\tassertRunInvariants(run);\n\t\treturn deepFreeze(run);\n\t} catch {\n\t\tthrow invalidSnapshot();\n\t}\n}\n\nexport function parseSubagentProgressSnapshot(value: unknown): SubagentProgressSnapshot {\n\ttry {\n\t\tconst snapshot = readEnvelope(value);\n\t\tconst runIds = new Set<string>();\n\t\tlet finalized = 0;\n\t\tfor (const run of snapshot.runs) {\n\t\t\tif (runIds.has(run.runId)) throw invalidSnapshot();\n\t\t\trunIds.add(run.runId);\n\t\t\tif (run.final) finalized += 1;\n\t\t\tassertRunInvariants(run);\n\t\t}\n\t\tif (finalized > SUBAGENT_PROGRESS_MAX_FINALIZED_RUNS) throw invalidSnapshot();\n\t\tconst size = measureSubagentProgressJson(snapshot);\n\t\tif (\n\t\t\tsize.utf8Bytes > SUBAGENT_PROGRESS_MAX_ENVELOPE_UTF8_BYTES ||\n\t\t\tsize.codeUnits > SUBAGENT_PROGRESS_MAX_ENVELOPE_CODE_UNITS\n\t\t) {\n\t\t\tthrow invalidSnapshot();\n\t\t}\n\t\treturn deepFreeze(snapshot);\n\t} catch {\n\t\tthrow invalidSnapshot();\n\t}\n}\n\nfunction deepFreeze<T>(value: T): T {\n\tif (value === null || typeof value !== \"object\" || Object.isFrozen(value)) return value;\n\tObject.freeze(value);\n\tfor (const child of Object.values(value)) deepFreeze(child);\n\treturn value;\n}\n"]}
|