@odla-ai/harness 0.9.4 → 0.10.1

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.
@@ -87,6 +87,34 @@ function createCodeRuntimeControlClient(options) {
87
87
  }
88
88
  return value;
89
89
  };
90
+ const callRaw = async (path, body) => {
91
+ const timeout = AbortSignal.timeout(modelRequestTimeoutMs);
92
+ const signals = [options.signal, timeout].filter((item) => Boolean(item));
93
+ const signal = signals.length === 1 ? signals[0] : AbortSignal.any(signals);
94
+ let response2;
95
+ try {
96
+ response2 = await request(`${endpoint}${path}`, {
97
+ method: "POST",
98
+ headers: { authorization: `Bearer ${options.token}`, "content-type": "application/json" },
99
+ body: JSON.stringify(body),
100
+ redirect: "error",
101
+ signal
102
+ });
103
+ } catch (cause) {
104
+ if (options.signal?.aborted) throw cause;
105
+ throw new CodeRuntimeControlError("Code source archive is unavailable", 503, "transport_unavailable");
106
+ }
107
+ if (!response2.ok) {
108
+ const value = await response2.json().catch(() => null);
109
+ const problem = record(record(value)?.error);
110
+ throw new CodeRuntimeControlError(
111
+ typeof problem?.message === "string" ? problem.message : `Code runtime request failed (${response2.status})`,
112
+ response2.status,
113
+ typeof problem?.code === "string" ? problem.code : void 0
114
+ );
115
+ }
116
+ return response2;
117
+ };
90
118
  return {
91
119
  heartbeat: async (version, capabilities) => {
92
120
  validateHeartbeat(version, capabilities);
@@ -98,6 +126,14 @@ function createCodeRuntimeControlClient(options) {
98
126
  source: async (sessionId) => parseSource(
99
127
  await call(`/registry/code/runtime/sessions/${validSessionId(sessionId)}/source`, {})
100
128
  ),
129
+ sourceArchive: async (sessionId, alias) => {
130
+ if (!/^[a-z][a-z0-9-]{0,39}$/.test(alias)) throw new TypeError("invalid Code source alias");
131
+ const response2 = await callRaw(
132
+ `/registry/code/runtime/sessions/${validSessionId(sessionId)}/source/archive`,
133
+ { alias }
134
+ );
135
+ return parseSourceArchiveResponse(response2, alias);
136
+ },
101
137
  infer: async (sessionId, inference) => {
102
138
  const value = record(await call(
103
139
  `/registry/code/runtime/sessions/${validSessionId(sessionId)}/inference`,
@@ -162,9 +198,70 @@ function createCodeRuntimeControlClient(options) {
162
198
  }
163
199
  };
164
200
  }
201
+ var ARCHIVE_LIMIT_MAXIMA = {
202
+ maxCompressedBytes: 64 * 1024 * 1024,
203
+ maxDecompressedBytes: 96 * 1024 * 1024,
204
+ maxEntries: 2e5,
205
+ maxFiles: 1e5,
206
+ maxFileBytes: 16 * 1024 * 1024,
207
+ maxTotalFileBytes: 80 * 1024 * 1024,
208
+ maxPathBytes: 4096,
209
+ maxExtendedHeaderBytes: 32 * 1024
210
+ };
211
+ async function parseSourceArchiveResponse(response2, expectedAlias) {
212
+ const alias = response2.headers.get("x-odla-source-alias") ?? "";
213
+ const repository = response2.headers.get("x-odla-source-repository") ?? "";
214
+ const commitSha = response2.headers.get("x-odla-source-commit") ?? "";
215
+ if (alias !== expectedAlias || !/^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/.test(repository) || !/^[0-9a-f]{40}$/.test(commitSha)) {
216
+ await response2.body?.cancel().catch(() => void 0);
217
+ throw new CodeRuntimeControlError("invalid Code source archive identity", 502, "invalid_response");
218
+ }
219
+ const limits = Object.fromEntries(Object.entries(ARCHIVE_LIMIT_MAXIMA).map(([key, maximum]) => {
220
+ const header = `x-odla-${key.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`)}`;
221
+ const value = response2.headers.get(header) ?? "";
222
+ if (!/^\d+$/.test(value) || !Number.isSafeInteger(Number(value)) || Number(value) < 1 || Number(value) > maximum) {
223
+ throw new CodeRuntimeControlError("invalid Code source archive limits", 502, "invalid_response");
224
+ }
225
+ return [key, Number(value)];
226
+ }));
227
+ const length = response2.headers.get("content-length");
228
+ if (length && (!/^\d+$/.test(length) || Number(length) > limits.maxCompressedBytes)) {
229
+ await response2.body?.cancel().catch(() => void 0);
230
+ throw new CodeRuntimeControlError("Code source archive exceeds its byte bound", 502, "invalid_response");
231
+ }
232
+ const compressed = await readBoundedResponse(response2.body, limits.maxCompressedBytes);
233
+ return { alias, repository, commitSha, compressed, limits };
234
+ }
235
+ async function readBoundedResponse(body, maximum) {
236
+ if (!body) throw new CodeRuntimeControlError("Code source archive body is missing", 502, "invalid_response");
237
+ const reader = body.getReader();
238
+ const chunks = [];
239
+ let size = 0;
240
+ try {
241
+ while (true) {
242
+ const { done, value } = await reader.read();
243
+ if (done) break;
244
+ size += value.byteLength;
245
+ if (size > maximum) {
246
+ await reader.cancel().catch(() => void 0);
247
+ throw new CodeRuntimeControlError("Code source archive exceeds its byte bound", 502, "invalid_response");
248
+ }
249
+ chunks.push(value);
250
+ }
251
+ } finally {
252
+ reader.releaseLock();
253
+ }
254
+ const result = new Uint8Array(size);
255
+ let offset = 0;
256
+ for (const chunk of chunks) {
257
+ result.set(chunk, offset);
258
+ offset += chunk.byteLength;
259
+ }
260
+ return result;
261
+ }
165
262
 
166
263
  // src/code-runtime.ts
167
- var CODE_RUNTIME_PROTOCOL_VERSION = 1;
264
+ var CODE_RUNTIME_PROTOCOL_VERSION = 3;
168
265
  async function runCodeRuntimeHeartbeatLoop(options) {
169
266
  const heartbeatMs = options.heartbeatMs ?? 15e3;
170
267
  if (!Number.isSafeInteger(heartbeatMs) || heartbeatMs < 1e3 || heartbeatMs > 3e5) {
@@ -233,12 +330,12 @@ function retryableControlFailure(value) {
233
330
  return failure.status === 408 || failure.status === 425 || failure.status === 429 || failure.status >= 500;
234
331
  }
235
332
  function wait(ms, signal) {
236
- return new Promise((resolve5) => {
237
- if (signal?.aborted) return resolve5();
238
- const timer = setTimeout(resolve5, ms);
333
+ return new Promise((resolve6) => {
334
+ if (signal?.aborted) return resolve6();
335
+ const timer = setTimeout(resolve6, ms);
239
336
  signal?.addEventListener("abort", () => {
240
337
  clearTimeout(timer);
241
- resolve5();
338
+ resolve6();
242
339
  }, { once: true });
243
340
  });
244
341
  }
@@ -1080,6 +1177,246 @@ var CodeRuntimeCheckpointManager = class {
1080
1177
  }
1081
1178
  };
1082
1179
 
1180
+ // src/code-runtime-archive.ts
1181
+ import { gunzipSync } from "zlib";
1182
+ import { mkdir, mkdtemp, rm, writeFile } from "fs/promises";
1183
+ import { tmpdir } from "os";
1184
+ import { dirname, join as join2, resolve as resolve3, sep as sep2 } from "path";
1185
+ var RESERVED2 = /* @__PURE__ */ new Set([".git", ".odla", ".wrangler", "node_modules", "dist", "coverage"]);
1186
+ var SECRET2 = /^(?:\.env(?:\..+)?|\.dev\.vars|credentials(?:\..+)?\.json|dev-token(?:\..+)?\.json)$/i;
1187
+ var MAX_NUL_SHARE = 0.1;
1188
+ async function materializeCodeRuntimeArchive(archive, visiblePaths, tempRoot = tmpdir()) {
1189
+ if (!archive.compressed.byteLength || archive.compressed.byteLength > archive.limits.maxCompressedBytes) {
1190
+ throw new TypeError("Code source archive exceeds its compressed byte bound");
1191
+ }
1192
+ let bytes;
1193
+ try {
1194
+ bytes = archive.compressed[0] === 31 && archive.compressed[1] === 139 ? gunzipSync(archive.compressed, { maxOutputLength: archive.limits.maxDecompressedBytes }) : archive.compressed;
1195
+ } catch {
1196
+ throw new TypeError("Code source archive is not a valid bounded gzip stream");
1197
+ }
1198
+ if (bytes.byteLength > archive.limits.maxDecompressedBytes) {
1199
+ throw new TypeError("Code source archive exceeds its decompressed byte bound");
1200
+ }
1201
+ const entries = parseTar(bytes, archive.limits);
1202
+ const root = await mkdtemp(join2(tempRoot, "odla-code-archive-"));
1203
+ const sourceDir = join2(root, "source");
1204
+ await mkdir(sourceDir);
1205
+ let visible = 0;
1206
+ try {
1207
+ for (const entry of entries) {
1208
+ if (entry.directory || visiblePaths && !visiblePaths.has(entry.path)) continue;
1209
+ if (filteredPath(entry.path)) continue;
1210
+ let content;
1211
+ try {
1212
+ content = new TextDecoder("utf-8", { fatal: true, ignoreBOM: false }).decode(entry.bytes);
1213
+ } catch {
1214
+ continue;
1215
+ }
1216
+ if (nulShare(content) > MAX_NUL_SHARE) continue;
1217
+ const target = resolve3(sourceDir, entry.path);
1218
+ if (!target.startsWith(`${resolve3(sourceDir)}${sep2}`)) throw new TypeError("Code source path escapes its root");
1219
+ await mkdir(dirname(target), { recursive: true });
1220
+ await writeFile(target, content, { flag: "wx", mode: 420 });
1221
+ visible += 1;
1222
+ }
1223
+ if (!visible && !visiblePaths) throw new TypeError("GitHub commit has no Code-visible text source");
1224
+ return { sourceDir, cleanup: () => rm(root, { recursive: true, force: true }) };
1225
+ } catch (cause) {
1226
+ await rm(root, { recursive: true, force: true });
1227
+ throw cause;
1228
+ }
1229
+ }
1230
+ function parseTar(bytes, limits) {
1231
+ const decoder = new TextDecoder("utf-8", { fatal: true, ignoreBOM: false });
1232
+ const entries = [];
1233
+ const archivePaths = /* @__PURE__ */ new Set();
1234
+ let entryCount = 0;
1235
+ let fileCount = 0;
1236
+ let totalFileBytes = 0;
1237
+ let pendingPath;
1238
+ let pendingPaxPath;
1239
+ let offset = 0;
1240
+ let ended = false;
1241
+ while (offset + 512 <= bytes.byteLength) {
1242
+ const header = bytes.subarray(offset, offset + 512);
1243
+ offset += 512;
1244
+ if (zeroBlock(header)) {
1245
+ ended = true;
1246
+ assertZeroTail(bytes, offset);
1247
+ break;
1248
+ }
1249
+ entryCount += 1;
1250
+ if (entryCount > limits.maxEntries) throw new TypeError("Code source archive has too many entries");
1251
+ validateChecksum(header);
1252
+ const type = header[156] ?? 0;
1253
+ const size = tarNumber(header.subarray(124, 136));
1254
+ if (size > limits.maxDecompressedBytes || offset + aligned(size) > bytes.byteLength) {
1255
+ throw new TypeError("Code source archive entry is invalid or too large");
1256
+ }
1257
+ const payload = bytes.subarray(offset, offset + size);
1258
+ offset += aligned(size);
1259
+ if (type === 120 || type === 103) {
1260
+ if (size > limits.maxExtendedHeaderBytes) throw new TypeError("Code source archive extended header is too large");
1261
+ const pax = parsePax(payload, decoder, limits.maxPathBytes);
1262
+ if (pax.linkpath !== void 0 || pax.size !== void 0 || Object.keys(pax).some((key) => key.toLowerCase().includes("sparse"))) {
1263
+ throw new TypeError("Code source archive contains an unsupported entry");
1264
+ }
1265
+ if (type === 103 && pax.path !== void 0) throw new TypeError("Code source archive path is unsafe");
1266
+ if (type === 120 && pax.path !== void 0) {
1267
+ if (pendingPaxPath !== void 0 || pendingPath !== void 0) throw new TypeError("Code source archive is invalid");
1268
+ pendingPaxPath = pax.path;
1269
+ }
1270
+ continue;
1271
+ }
1272
+ if (type === 76) {
1273
+ if (size > limits.maxExtendedHeaderBytes || pendingPath !== void 0 || pendingPaxPath !== void 0) {
1274
+ throw new TypeError("Code source archive long path is invalid");
1275
+ }
1276
+ pendingPath = validateArchivePath(decode(payload, decoder).replace(/\0+$/, "").replace(/\n$/, ""), limits.maxPathBytes);
1277
+ continue;
1278
+ }
1279
+ if (type === 75) throw new TypeError("Code source archive contains an unsupported link");
1280
+ const path = validateArchivePath(pendingPaxPath ?? pendingPath ?? tarPath(header, decoder), limits.maxPathBytes);
1281
+ pendingPaxPath = void 0;
1282
+ pendingPath = void 0;
1283
+ const directory = type === 53;
1284
+ const regular = type === 0 || type === 48;
1285
+ if (!directory && !regular || directory && size !== 0 || archivePaths.has(path)) {
1286
+ throw new TypeError("Code source archive contains an invalid or duplicate entry");
1287
+ }
1288
+ archivePaths.add(path);
1289
+ if (regular) {
1290
+ fileCount += 1;
1291
+ totalFileBytes += size;
1292
+ if (fileCount > limits.maxFiles || size > limits.maxFileBytes || totalFileBytes > limits.maxTotalFileBytes) {
1293
+ throw new TypeError("Code source archive exceeds its file bounds");
1294
+ }
1295
+ }
1296
+ entries.push({ path, directory, ...regular ? { bytes: payload } : {} });
1297
+ }
1298
+ if (!ended || pendingPath !== void 0 || pendingPaxPath !== void 0 || !entries.length || !fileCount) {
1299
+ throw new TypeError("Code source archive is incomplete");
1300
+ }
1301
+ return unwrapRepository(entries, limits.maxPathBytes);
1302
+ }
1303
+ function unwrapRepository(entries, maxPathBytes) {
1304
+ const root = entries[0].path.split("/")[0];
1305
+ if (!root || entries.some((entry) => entry.path !== root && !entry.path.startsWith(`${root}/`))) {
1306
+ throw new TypeError("Code source archive has no single repository root");
1307
+ }
1308
+ const output = [];
1309
+ const kinds = /* @__PURE__ */ new Map();
1310
+ for (const entry of entries) {
1311
+ if (entry.path === root) {
1312
+ if (!entry.directory) throw new TypeError("Code source archive root is not a directory");
1313
+ continue;
1314
+ }
1315
+ const path = entry.path.slice(root.length + 1);
1316
+ validateRepositoryPath(path, maxPathBytes);
1317
+ const parts = path.split("/");
1318
+ for (let index = 1; index < parts.length; index += 1) {
1319
+ if (kinds.get(parts.slice(0, index).join("/")) === "file") throw new TypeError("Code source archive path conflicts");
1320
+ }
1321
+ if (!entry.directory) {
1322
+ for (const existing of kinds.keys()) {
1323
+ if (existing.startsWith(`${path}/`)) throw new TypeError("Code source archive path conflicts");
1324
+ }
1325
+ }
1326
+ if (kinds.has(path)) throw new TypeError("Code source archive repeats a path");
1327
+ kinds.set(path, entry.directory ? "directory" : "file");
1328
+ output.push({ ...entry, path });
1329
+ }
1330
+ return output.sort((left, right) => left.path.localeCompare(right.path));
1331
+ }
1332
+ function parsePax(bytes, decoder, maxPathBytes) {
1333
+ const result = {};
1334
+ let offset = 0;
1335
+ while (offset < bytes.byteLength) {
1336
+ const space = bytes.indexOf(32, offset);
1337
+ if (space < 0) throw new TypeError("Code source archive PAX header is invalid");
1338
+ const lengthText = ascii(bytes.subarray(offset, space));
1339
+ if (!/^[1-9][0-9]{0,8}$/.test(lengthText)) throw new TypeError("Code source archive PAX length is invalid");
1340
+ const length = Number(lengthText);
1341
+ const end = offset + length;
1342
+ if (!Number.isSafeInteger(length) || end > bytes.byteLength || bytes[end - 1] !== 10) {
1343
+ throw new TypeError("Code source archive PAX record is invalid");
1344
+ }
1345
+ const record3 = decode(bytes.subarray(space + 1, end - 1), decoder);
1346
+ const equals = record3.indexOf("=");
1347
+ if (equals < 1) throw new TypeError("Code source archive PAX field is invalid");
1348
+ const key = record3.slice(0, equals);
1349
+ if (Object.hasOwn(result, key)) throw new TypeError("Code source archive PAX field repeats");
1350
+ result[key] = record3.slice(equals + 1);
1351
+ offset = end;
1352
+ }
1353
+ if (result.path !== void 0) result.path = validateArchivePath(result.path, maxPathBytes);
1354
+ return result;
1355
+ }
1356
+ var aligned = (size) => Math.ceil(size / 512) * 512;
1357
+ var zeroBlock = (block) => block.every((value) => value === 0);
1358
+ function validateChecksum(header) {
1359
+ const expected = tarNumber(header.subarray(148, 156));
1360
+ let actual = 0;
1361
+ for (let index = 0; index < header.length; index += 1) actual += index >= 148 && index < 156 ? 32 : header[index];
1362
+ if (actual !== expected) throw new TypeError("Code source archive checksum is invalid");
1363
+ }
1364
+ function tarNumber(field) {
1365
+ if ((field[0] ?? 0) & 128) throw new TypeError("Code source archive numeric format is unsupported");
1366
+ const value = ascii(field).replaceAll("\0", "").trim();
1367
+ if (!value) return 0;
1368
+ if (!/^[0-7]+$/.test(value)) throw new TypeError("Code source archive number is invalid");
1369
+ const parsed = Number.parseInt(value, 8);
1370
+ if (!Number.isSafeInteger(parsed) || parsed < 0) throw new TypeError("Code source archive number is too large");
1371
+ return parsed;
1372
+ }
1373
+ function tarPath(header, decoder) {
1374
+ const name = decodeNul(header.subarray(0, 100), decoder);
1375
+ const prefix = decodeNul(header.subarray(345, 500), decoder);
1376
+ return prefix ? `${prefix}/${name}` : name;
1377
+ }
1378
+ function decodeNul(value, decoder) {
1379
+ const end = value.indexOf(0);
1380
+ return decode(end < 0 ? value : value.subarray(0, end), decoder);
1381
+ }
1382
+ function decode(value, decoder) {
1383
+ try {
1384
+ return decoder.decode(value);
1385
+ } catch {
1386
+ throw new TypeError("Code source archive text is invalid UTF-8");
1387
+ }
1388
+ }
1389
+ function ascii(value) {
1390
+ let output = "";
1391
+ for (const byte of value) output += String.fromCharCode(byte);
1392
+ return output;
1393
+ }
1394
+ function validateArchivePath(input, maximum) {
1395
+ const path = input.endsWith("/") ? input.slice(0, -1) : input;
1396
+ validateRepositoryPath(path, maximum);
1397
+ return path;
1398
+ }
1399
+ function validateRepositoryPath(path, maximum) {
1400
+ if (!path || path.startsWith("/") || path.includes("\\") || /[\u0000-\u001f\u007f]/.test(path) || new TextEncoder().encode(path).byteLength > maximum || path.split("/").some((part) => !part || part === "." || part === "..")) {
1401
+ throw new TypeError("Code source archive path is unsafe");
1402
+ }
1403
+ }
1404
+ function assertZeroTail(bytes, offset) {
1405
+ for (let index = offset; index < bytes.byteLength; index += 1) {
1406
+ if (bytes[index] !== 0) throw new TypeError("Code source archive has data after its end marker");
1407
+ }
1408
+ }
1409
+ function filteredPath(path) {
1410
+ const parts = path.split("/");
1411
+ return parts.some((part) => RESERVED2.has(part) || SECRET2.test(part));
1412
+ }
1413
+ function nulShare(content) {
1414
+ if (!content.length) return 0;
1415
+ let count = 0;
1416
+ for (let index = 0; index < content.length; index += 1) if (content.charCodeAt(index) === 0) count += 1;
1417
+ return count / content.length;
1418
+ }
1419
+
1083
1420
  // src/code-runtime-task.ts
1084
1421
  function codeCommandMetadata(payload, resume) {
1085
1422
  const trusted = record2(payload.trustedBase);
@@ -1090,12 +1427,17 @@ function codeCommandMetadata(payload, resume) {
1090
1427
  if (role !== "coding" && role !== "review" || typeof title !== "string" || typeof prompt !== "string") {
1091
1428
  throw new TypeError(`invalid Code ${resume ? "resume" : "start"} metadata`);
1092
1429
  }
1430
+ if (payload.readOnly !== void 0 && typeof payload.readOnly !== "boolean") {
1431
+ throw new TypeError(`invalid Code ${resume ? "resume" : "start"} read-only capability`);
1432
+ }
1433
+ const readOnly = role === "review" || payload.readOnly === true;
1093
1434
  const planning = trusted?.planningInputDigest;
1094
1435
  const attestation = trusted?.attestationDigest;
1095
1436
  const repository = trusted?.repository;
1096
1437
  const baseCommitSha = trusted?.commitSha;
1097
1438
  const sourceTreeDigest = trusted?.treeDigest;
1098
- if (typeof repository !== "string" || !repository.includes("/") || typeof baseCommitSha !== "string" || !/^[0-9a-f]{40}$/.test(baseCommitSha) || typeof sourceTreeDigest !== "string" || !/^sha256:[0-9a-f]{64}$/.test(sourceTreeDigest)) {
1439
+ const hostMaterialized = record2(payload.sourceSet) !== null && sourceTreeDigest === void 0;
1440
+ if (typeof repository !== "string" || !repository.includes("/") || typeof baseCommitSha !== "string" || !/^[0-9a-f]{40}$/.test(baseCommitSha) || !hostMaterialized && (typeof sourceTreeDigest !== "string" || !/^sha256:[0-9a-f]{64}$/.test(sourceTreeDigest))) {
1099
1441
  throw new TypeError(`invalid Code ${resume ? "resume" : "start"} trusted base`);
1100
1442
  }
1101
1443
  if (!Number.isSafeInteger(maxTokensPerInteraction) || Number(maxTokensPerInteraction) < 4e3 || Number(maxTokensPerInteraction) > 2e5) {
@@ -1103,6 +1445,7 @@ function codeCommandMetadata(payload, resume) {
1103
1445
  }
1104
1446
  return {
1105
1447
  role,
1448
+ readOnly,
1106
1449
  title,
1107
1450
  prompt,
1108
1451
  maxTokensPerInteraction: Number(maxTokensPerInteraction),
@@ -1110,7 +1453,7 @@ function codeCommandMetadata(payload, resume) {
1110
1453
  attestationDigest: typeof attestation === "string" ? attestation : "resume",
1111
1454
  repository,
1112
1455
  baseCommitSha,
1113
- sourceTreeDigest
1456
+ sourceTreeDigest: typeof sourceTreeDigest === "string" ? sourceTreeDigest : null
1114
1457
  };
1115
1458
  }
1116
1459
  function codeLocalSource(payload) {
@@ -1175,19 +1518,80 @@ async function prepareRuntimeLocalSource(input) {
1175
1518
  }
1176
1519
 
1177
1520
  // src/code-runtime-source.ts
1178
- import { mkdir, mkdtemp, rm, writeFile } from "fs/promises";
1179
- import { tmpdir } from "os";
1180
- import { dirname, join as join2, resolve as resolve3, sep as sep2 } from "path";
1181
- var RESERVED2 = /* @__PURE__ */ new Set([".git", ".odla", ".wrangler", "node_modules", "dist", "coverage"]);
1182
- var SECRET2 = /^(?:\.env(?:\..+)?|\.dev\.vars|credentials(?:\..+)?\.json|dev-token(?:\..+)?\.json)$/i;
1521
+ import { mkdir as mkdir3, mkdtemp as mkdtemp2, rm as rm2, writeFile as writeFile2 } from "fs/promises";
1522
+ import { tmpdir as tmpdir2 } from "os";
1523
+ import { dirname as dirname3, join as join4, resolve as resolve4, sep as sep3 } from "path";
1524
+
1525
+ // src/code-runtime-selected-source.ts
1526
+ import { chmod, cp, mkdir as mkdir2, readdir as readdir2 } from "fs/promises";
1527
+ import { dirname as dirname2, join as join3 } from "path";
1528
+ function selectedSourceSet(payload) {
1529
+ if (!payload.sourceSet) return null;
1530
+ const set = payload.sourceSet && typeof payload.sourceSet === "object" && !Array.isArray(payload.sourceSet) ? payload.sourceSet : null;
1531
+ if (!set) throw new TypeError("Code selected source set is invalid");
1532
+ const parse = (value, primary2) => {
1533
+ const item = value && typeof value === "object" && !Array.isArray(value) ? value : null;
1534
+ const alias = item?.alias;
1535
+ const repository = item?.repository;
1536
+ const commitSha = item?.commitSha;
1537
+ const materialization = item?.materialization ?? "registry_snapshot";
1538
+ if (typeof alias !== "string" || alias !== (primary2 ? "primary" : alias) || !/^[a-z][a-z0-9-]{0,39}$/.test(alias) || typeof repository !== "string" || !/^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/.test(repository) || typeof commitSha !== "string" || !/^[0-9a-f]{40}$/.test(commitSha) || !["registry_snapshot", "local_checkout", "host_archive"].includes(String(materialization))) {
1539
+ throw new TypeError("Code selected source identity is invalid");
1540
+ }
1541
+ const visiblePaths = item?.visiblePaths;
1542
+ if (visiblePaths !== void 0 && (!Array.isArray(visiblePaths) || visiblePaths.length > 2e3 || visiblePaths.some((path) => typeof path !== "string" || path.length > 4096))) {
1543
+ throw new TypeError("Code selected source visibility slice is invalid");
1544
+ }
1545
+ return {
1546
+ alias,
1547
+ repository,
1548
+ commitSha,
1549
+ materialization,
1550
+ ...visiblePaths ? { visiblePaths } : {}
1551
+ };
1552
+ };
1553
+ if (!Array.isArray(set.references)) throw new TypeError("Code selected source references are invalid");
1554
+ const primary = parse(set.primary, true);
1555
+ const references = set.references.map((item) => parse(item, false));
1556
+ const aliases = /* @__PURE__ */ new Set([primary.alias, ...references.map((item) => item.alias)]);
1557
+ if (aliases.size !== references.length + 1) throw new TypeError("Code selected source aliases repeat");
1558
+ return { primary, references };
1559
+ }
1560
+ async function attachReferenceDirectories(workspace, references) {
1561
+ for (const reference of references) {
1562
+ validateAlias(reference.alias);
1563
+ for (const root of [workspace.baselineDir, workspace.workspaceDir]) {
1564
+ const target = join3(root, ".odla-references", reference.alias);
1565
+ await mkdir2(dirname2(target), { recursive: true });
1566
+ await cp(reference.sourceDir, target, { recursive: true, errorOnExist: true, force: false });
1567
+ await makeTreeReadOnly(target);
1568
+ }
1569
+ }
1570
+ }
1571
+ function validateAlias(alias) {
1572
+ if (!/^[a-z][a-z0-9-]{0,39}$/.test(alias) || alias === "primary") {
1573
+ throw new TypeError("Code reference alias is invalid");
1574
+ }
1575
+ }
1576
+ async function makeTreeReadOnly(root) {
1577
+ for (const entry of await readdir2(root, { withFileTypes: true })) {
1578
+ const target = join3(root, entry.name);
1579
+ if (entry.isDirectory()) await makeTreeReadOnly(target);
1580
+ else if (entry.isFile()) await chmod(target, 292);
1581
+ }
1582
+ }
1583
+
1584
+ // src/code-runtime-source.ts
1585
+ var RESERVED3 = /* @__PURE__ */ new Set([".git", ".odla", ".wrangler", "node_modules", "dist", "coverage"]);
1586
+ var SECRET3 = /^(?:\.env(?:\..+)?|\.dev\.vars|credentials(?:\..+)?\.json|dev-token(?:\..+)?\.json)$/i;
1183
1587
  var SOURCE_MAX_FILES = 1e5;
1184
1588
  var SOURCE_MAX_BYTES = 80 * 1024 * 1024;
1185
1589
  var SOURCE_SET_MAX_BYTES = 480 * 1024 * 1024;
1186
- async function materializeCodeRuntimeSource(snapshot, tempRoot = tmpdir()) {
1590
+ async function materializeCodeRuntimeSource(snapshot, tempRoot = tmpdir2()) {
1187
1591
  if (!snapshot.files.length || snapshot.files.length > SOURCE_MAX_FILES) throw new TypeError("Code source file count is invalid");
1188
- const root = await mkdtemp(join2(tempRoot, "odla-code-source-"));
1189
- const sourceDir = join2(root, "source");
1190
- await mkdir(sourceDir);
1592
+ const root = await mkdtemp2(join4(tempRoot, "odla-code-source-"));
1593
+ const sourceDir = join4(root, "source");
1594
+ await mkdir3(sourceDir);
1191
1595
  const seen = /* @__PURE__ */ new Set();
1192
1596
  let bytes = 0;
1193
1597
  try {
@@ -1197,13 +1601,13 @@ async function materializeCodeRuntimeSource(snapshot, tempRoot = tmpdir()) {
1197
1601
  seen.add(file.path);
1198
1602
  bytes += Buffer.byteLength(file.path) + Buffer.byteLength(file.content);
1199
1603
  if (bytes > SOURCE_MAX_BYTES) throw new TypeError("Code source exceeds its byte bound");
1200
- const target = resolve3(sourceDir, file.path);
1201
- if (!target.startsWith(`${resolve3(sourceDir)}${sep2}`)) throw new TypeError("Code source path escapes its root");
1202
- await mkdir(dirname(target), { recursive: true });
1203
- await writeFile(target, file.content, { flag: "wx", mode: 420 });
1604
+ const target = resolve4(sourceDir, file.path);
1605
+ if (!target.startsWith(`${resolve4(sourceDir)}${sep3}`)) throw new TypeError("Code source path escapes its root");
1606
+ await mkdir3(dirname3(target), { recursive: true });
1607
+ await writeFile2(target, file.content, { flag: "wx", mode: 420 });
1204
1608
  }
1205
1609
  for (const reference of snapshot.references ?? []) {
1206
- validateAlias(reference.alias);
1610
+ validateAlias2(reference.alias);
1207
1611
  if (!reference.files.length || reference.files.length > SOURCE_MAX_FILES) throw new TypeError("Code reference file count is invalid");
1208
1612
  for (const file of reference.files) {
1209
1613
  validatePath(file.path);
@@ -1212,19 +1616,19 @@ async function materializeCodeRuntimeSource(snapshot, tempRoot = tmpdir()) {
1212
1616
  seen.add(path);
1213
1617
  bytes += Buffer.byteLength(path) + Buffer.byteLength(file.content);
1214
1618
  if (bytes > SOURCE_SET_MAX_BYTES) throw new TypeError("Code source set exceeds its byte bound");
1215
- const target = resolve3(sourceDir, path);
1216
- if (!target.startsWith(`${resolve3(sourceDir)}${sep2}`)) throw new TypeError("Code reference path escapes its root");
1217
- await mkdir(dirname(target), { recursive: true });
1218
- await writeFile(target, file.content, { flag: "wx", mode: 292 });
1619
+ const target = resolve4(sourceDir, path);
1620
+ if (!target.startsWith(`${resolve4(sourceDir)}${sep3}`)) throw new TypeError("Code reference path escapes its root");
1621
+ await mkdir3(dirname3(target), { recursive: true });
1622
+ await writeFile2(target, file.content, { flag: "wx", mode: 292 });
1219
1623
  }
1220
1624
  }
1221
- return { sourceDir, cleanup: () => rm(root, { recursive: true, force: true }) };
1625
+ return { sourceDir, cleanup: () => rm2(root, { recursive: true, force: true }) };
1222
1626
  } catch (cause) {
1223
- await rm(root, { recursive: true, force: true });
1627
+ await rm2(root, { recursive: true, force: true });
1224
1628
  throw cause;
1225
1629
  }
1226
1630
  }
1227
- function validateAlias(alias) {
1631
+ function validateAlias2(alias) {
1228
1632
  if (!/^[a-z][a-z0-9-]{0,39}$/.test(alias) || alias === "primary") {
1229
1633
  throw new TypeError("Code reference alias is invalid");
1230
1634
  }
@@ -1232,24 +1636,24 @@ function validateAlias(alias) {
1232
1636
  async function attachCodeRuntimeReferences(workspace, references) {
1233
1637
  let bytes = 0;
1234
1638
  for (const reference of references) {
1235
- validateAlias(reference.alias);
1639
+ validateAlias2(reference.alias);
1236
1640
  for (const file of reference.files) {
1237
1641
  validatePath(file.path);
1238
1642
  const path = `.odla-references/${reference.alias}/${file.path}`;
1239
1643
  bytes += Buffer.byteLength(path) + Buffer.byteLength(file.content);
1240
1644
  if (bytes > SOURCE_SET_MAX_BYTES - SOURCE_MAX_BYTES) throw new TypeError("Code reference set exceeds its byte bound");
1241
1645
  for (const root of [workspace.baselineDir, workspace.workspaceDir]) {
1242
- const target = resolve3(root, path);
1243
- if (!target.startsWith(`${resolve3(root)}${sep2}`)) throw new TypeError("Code reference path escapes its root");
1244
- await mkdir(dirname(target), { recursive: true });
1245
- await writeFile(target, file.content, { flag: "wx", mode: 292 });
1646
+ const target = resolve4(root, path);
1647
+ if (!target.startsWith(`${resolve4(root)}${sep3}`)) throw new TypeError("Code reference path escapes its root");
1648
+ await mkdir3(dirname3(target), { recursive: true });
1649
+ await writeFile2(target, file.content, { flag: "wx", mode: 292 });
1246
1650
  }
1247
1651
  }
1248
1652
  }
1249
1653
  }
1250
1654
  function validatePath(path) {
1251
1655
  const parts = path.split("/");
1252
- if (!path || path.startsWith("/") || path.includes("\\") || path.includes("\0") || parts.some((part) => !part || part === "." || part === ".." || RESERVED2.has(part) || SECRET2.test(part))) {
1656
+ if (!path || path.startsWith("/") || path.includes("\\") || path.includes("\0") || parts.some((part) => !part || part === "." || part === ".." || RESERVED3.has(part) || SECRET3.test(part))) {
1253
1657
  throw new TypeError("Code source contains an unsafe path");
1254
1658
  }
1255
1659
  }
@@ -1277,12 +1681,12 @@ async function materializeCommandWorkspace(input) {
1277
1681
  throw new TypeError("Code selected source set is invalid");
1278
1682
  }
1279
1683
  if (references.length) {
1280
- const selected = await input.control.source(command.sessionId);
1281
- if (selected.repository !== metadata.repository || selected.commitSha !== metadata.baseCommitSha || selected.treeDigest !== metadata.sourceTreeDigest) {
1684
+ const selected2 = await input.control.source(command.sessionId);
1685
+ if (selected2.repository !== metadata.repository || selected2.commitSha !== metadata.baseCommitSha || selected2.treeDigest !== metadata.sourceTreeDigest) {
1282
1686
  await prepared.workspace.cleanup();
1283
1687
  throw new TypeError("Code local source does not match the selected GitHub primary source");
1284
1688
  }
1285
- await attachCodeRuntimeReferences(prepared.workspace, selected.references ?? []);
1689
+ await attachCodeRuntimeReferences(prepared.workspace, selected2.references ?? []);
1286
1690
  }
1287
1691
  }
1288
1692
  return {
@@ -1292,6 +1696,63 @@ async function materializeCommandWorkspace(input) {
1292
1696
  requestedLocal
1293
1697
  };
1294
1698
  }
1699
+ const selected = selectedSourceSet(command.payload);
1700
+ if (selected?.primary.materialization === "host_archive") {
1701
+ if (!input.control.sourceArchive) {
1702
+ throw new TypeError("Code runtime protocol does not support host source materialization");
1703
+ }
1704
+ const sources = [selected.primary, ...selected.references];
1705
+ const materialized2 = [];
1706
+ try {
1707
+ for (const descriptor2 of sources) {
1708
+ if (descriptor2.materialization !== "host_archive") {
1709
+ throw new TypeError("Code selected source set mixes incompatible materialization modes");
1710
+ }
1711
+ const archive = await input.control.sourceArchive(command.sessionId, descriptor2.alias);
1712
+ if (archive.repository !== descriptor2.repository || archive.commitSha !== descriptor2.commitSha) {
1713
+ throw new TypeError("Code source archive does not match its selected repository and commit");
1714
+ }
1715
+ const source2 = await materializeCodeRuntimeArchive(
1716
+ archive,
1717
+ descriptor2.visiblePaths ? new Set(descriptor2.visiblePaths) : void 0
1718
+ );
1719
+ const treeDigest = await digestStagedWorkspace(source2.sourceDir, {
1720
+ maxFiles: archive.limits.maxFiles,
1721
+ maxBytes: archive.limits.maxTotalFileBytes
1722
+ });
1723
+ materialized2.push({ descriptor: descriptor2, source: source2, treeDigest });
1724
+ }
1725
+ const primary = materialized2[0];
1726
+ const workspace = resume ? (await restoreCodeWorkspaceCheckpoint({
1727
+ trustedBaseDir: primary.source.sourceDir,
1728
+ trustedBaseCommitSha: primary.descriptor.commitSha,
1729
+ checkpoint: codeCheckpointPayload(command.payload)
1730
+ })).workspace : await stageWorkspace(primary.source.sourceDir, {
1731
+ maxFiles: SOURCE_MAX_FILES,
1732
+ maxBytes: SOURCE_SET_MAX_BYTES
1733
+ });
1734
+ try {
1735
+ await attachReferenceDirectories(workspace, materialized2.slice(1).map((item) => ({
1736
+ alias: item.descriptor.alias,
1737
+ sourceDir: item.source.sourceDir
1738
+ })));
1739
+ } catch (cause) {
1740
+ await workspace.cleanup();
1741
+ throw cause;
1742
+ }
1743
+ return {
1744
+ workspace,
1745
+ sourceDigest: primary.treeDigest,
1746
+ requestedLocal: null,
1747
+ sourceDigests: materialized2.map((item) => ({
1748
+ alias: item.descriptor.alias,
1749
+ treeDigest: item.treeDigest
1750
+ }))
1751
+ };
1752
+ } finally {
1753
+ await Promise.allSettled(materialized2.map((item) => item.source.cleanup()));
1754
+ }
1755
+ }
1295
1756
  const source = await input.control.source(command.sessionId);
1296
1757
  const materialized = await materializeCodeRuntimeSource(source);
1297
1758
  try {
@@ -1628,14 +2089,40 @@ async function sessionSkillsFor(options, command) {
1628
2089
  }
1629
2090
 
1630
2091
  // src/code-runtime-inference.ts
2092
+ var OVERLOAD_RETRY_DELAYS_MS = [2e3, 4e3, 8e3, 16e3];
2093
+ var RETRYABLE_CODES = /* @__PURE__ */ new Set(["control_plane_overloaded", "registry_overloaded", "transport_unavailable"]);
2094
+ function overloadedControlFailure(cause) {
2095
+ return cause instanceof CodeRuntimeControlError && cause.status === 503 && RETRYABLE_CODES.has(cause.code);
2096
+ }
2097
+ async function inferWithBackoff(infer, wait2, onRetry) {
2098
+ for (let attempt = 0; ; attempt += 1) {
2099
+ try {
2100
+ return await infer();
2101
+ } catch (cause) {
2102
+ const delayMs = OVERLOAD_RETRY_DELAYS_MS[attempt];
2103
+ if (delayMs === void 0 || !overloadedControlFailure(cause)) throw cause;
2104
+ await onRetry(cause, delayMs);
2105
+ await wait2(delayMs);
2106
+ }
2107
+ }
2108
+ }
1631
2109
  async function handleCodeRuntimeInference(input) {
1632
2110
  const { command, request, state } = input;
1633
2111
  const startedAt = Date.now();
1634
- const response2 = await input.control.infer(command.sessionId, {
1635
- requestId: request.requestId,
1636
- interactionId: command.commandId,
1637
- call: request.call
1638
- });
2112
+ const wait2 = input.wait ?? ((ms) => new Promise((resolve6) => setTimeout(resolve6, ms)));
2113
+ const response2 = await inferWithBackoff(
2114
+ () => input.control.infer(command.sessionId, {
2115
+ requestId: request.requestId,
2116
+ interactionId: command.commandId,
2117
+ call: request.call
2118
+ }),
2119
+ wait2,
2120
+ (cause, delayMs) => input.event({
2121
+ type: "diagnostic",
2122
+ level: "error",
2123
+ message: `Code control plane overloaded (${cause.code}); retrying the model call in ${delayMs / 1e3}s`
2124
+ }).catch(() => void 0)
2125
+ );
1639
2126
  state.tokens += response2.receipt.inputTokens + response2.receipt.outputTokens;
1640
2127
  const { costUsd } = response2.receipt;
1641
2128
  if (costUsd === void 0) state.costKnown = false;
@@ -1691,8 +2178,8 @@ function createCodeRuntimeInference(options) {
1691
2178
 
1692
2179
  // src/code-tool-discovery.ts
1693
2180
  import { spawn as spawn3 } from "child_process";
1694
- import { readFile as readFile2, readdir as readdir2 } from "fs/promises";
1695
- import { relative as relative2, resolve as resolve4 } from "path";
2181
+ import { readFile as readFile2, readdir as readdir3 } from "fs/promises";
2182
+ import { relative as relative2, resolve as resolve5 } from "path";
1696
2183
  var DEFAULT_MAX_FILES = 2e4;
1697
2184
  var DEFAULT_MAX_RESULTS = 100;
1698
2185
  var DEFAULT_MAX_FILE_BYTES = 512 * 1024;
@@ -1717,10 +2204,10 @@ function createWorkspaceFileRegistry(limit = DEFAULT_MAX_FILES, enumerate = regi
1717
2204
  async function registeredFiles(root, limit = DEFAULT_MAX_FILES) {
1718
2205
  const paths = [];
1719
2206
  const walk = async (directory) => {
1720
- for (const entry of await readdir2(directory, { withFileTypes: true })) {
2207
+ for (const entry of await readdir3(directory, { withFileTypes: true })) {
1721
2208
  if (SKIP_WORKSPACE_DIRS.has(entry.name)) continue;
1722
2209
  if (entry.isSymbolicLink()) throw new TypeError("workspace contains a symbolic link");
1723
- const target = resolve4(directory, entry.name);
2210
+ const target = resolve5(directory, entry.name);
1724
2211
  if (entry.isDirectory()) await walk(target);
1725
2212
  else if (entry.isFile()) {
1726
2213
  const path = relative2(root, target).split("\\").join("/");
@@ -1734,7 +2221,7 @@ async function registeredFiles(root, limit = DEFAULT_MAX_FILES) {
1734
2221
  }
1735
2222
  }
1736
2223
  };
1737
- await walk(resolve4(root));
2224
+ await walk(resolve5(root));
1738
2225
  return paths.sort();
1739
2226
  }
1740
2227
  function listWorkspace(paths, options = {}) {
@@ -1848,7 +2335,7 @@ async function fallbackSearch(root, scoped, options) {
1848
2335
  if (matches.length >= options.maxResults) break;
1849
2336
  let source;
1850
2337
  try {
1851
- source = await readFile2(resolve4(root, path));
2338
+ source = await readFile2(resolve5(root, path));
1852
2339
  } catch {
1853
2340
  continue;
1854
2341
  }
@@ -2126,7 +2613,7 @@ import { readFile as readFile4, stat } from "fs/promises";
2126
2613
 
2127
2614
  // src/code-tool-graph.ts
2128
2615
  import { readFile as readFile3 } from "fs/promises";
2129
- import { join as join3 } from "path";
2616
+ import { join as join5 } from "path";
2130
2617
  import {
2131
2618
  hubs,
2132
2619
  incident,
@@ -2140,7 +2627,7 @@ var cache = /* @__PURE__ */ new Map();
2140
2627
  function workspaceGraphs(workspaceDir, paths) {
2141
2628
  const existing = cache.get(workspaceDir);
2142
2629
  if (existing) return existing;
2143
- const read2 = (path) => readFile3(join3(workspaceDir, path), "utf8");
2630
+ const read2 = (path) => readFile3(join5(workspaceDir, path), "utf8");
2144
2631
  const built = (async () => ({
2145
2632
  // No knownTables: a staged workspace may not carry migrations, and a filter
2146
2633
  // that silently drops every table is worse than an unfiltered one. Callers
@@ -2763,8 +3250,8 @@ var runtimeErrorMessage = (value) => value instanceof Error ? value.message : St
2763
3250
  function codeRuntimeAcknowledgementGate(signal) {
2764
3251
  let settle;
2765
3252
  let settled = false;
2766
- const ready = new Promise((resolve5) => {
2767
- settle = resolve5;
3253
+ const ready = new Promise((resolve6) => {
3254
+ settle = resolve6;
2768
3255
  });
2769
3256
  const release = (run) => {
2770
3257
  if (settled) return;
@@ -2873,7 +3360,7 @@ var TheseusRuntimeEngine = class {
2873
3360
  async #start(command, resume) {
2874
3361
  if (this.#active.has(command.sessionId)) throw new TypeError("Code session is already active on this runtime");
2875
3362
  const metadata = codeCommandMetadata(command.payload, resume);
2876
- const { workspace, sourceDigest, localTrustedBaseDigest, requestedLocal } = await materializeCommandWorkspace({
3363
+ const { workspace, sourceDigest, sourceDigests, localTrustedBaseDigest, requestedLocal } = await materializeCommandWorkspace({
2877
3364
  command,
2878
3365
  metadata,
2879
3366
  resume,
@@ -2889,11 +3376,12 @@ var TheseusRuntimeEngine = class {
2889
3376
  acknowledged: false,
2890
3377
  startGate,
2891
3378
  role: metadata.role,
3379
+ readOnly: metadata.readOnly,
2892
3380
  title: metadata.title,
2893
3381
  maxTokensPerInteraction: metadata.maxTokensPerInteraction,
2894
3382
  baseCommitSha: metadata.baseCommitSha,
2895
3383
  repository: metadata.repository,
2896
- sourceTreeDigest: metadata.sourceTreeDigest,
3384
+ sourceTreeDigest: metadata.sourceTreeDigest ?? sourceDigest,
2897
3385
  trustedBaseDigest: requestedLocal ? localTrustedBaseDigest : await digestStagedWorkspace(workspace.baselineDir, {
2898
3386
  maxFiles: 2e4,
2899
3387
  maxBytes: 512 * 1024 * 1024
@@ -2919,7 +3407,11 @@ var TheseusRuntimeEngine = class {
2919
3407
  await this.#failure(command, active, detail);
2920
3408
  return null;
2921
3409
  });
2922
- return { status: "running", message: resume ? "Theseus resumed from a portable checkpoint" : "Theseus started" };
3410
+ return {
3411
+ status: "running",
3412
+ message: resume ? "Theseus resumed from a portable checkpoint" : "Theseus started",
3413
+ ...sourceDigests ? { sourceDigests } : {}
3414
+ };
2923
3415
  }
2924
3416
  /**
2925
3417
  * Pursue a goal: attempt, judge with the clean verifier, re-prompt from what
@@ -2945,6 +3437,7 @@ var TheseusRuntimeEngine = class {
2945
3437
  event: (event) => this.#event(command, event, active.conversationRefs).then(() => void 0, () => void 0),
2946
3438
  attempt: (prompt) => this.#runAttempt(command, {
2947
3439
  role: active.role,
3440
+ readOnly: active.readOnly,
2948
3441
  title: active.title,
2949
3442
  prompt,
2950
3443
  maxTokensPerInteraction: active.maxTokensPerInteraction,
@@ -2987,6 +3480,7 @@ var TheseusRuntimeEngine = class {
2987
3480
  await this.#takeOver(command, "prompt requires an active Code session");
2988
3481
  active.done = this.#runAttempt(command, {
2989
3482
  role: active.role,
3483
+ readOnly: active.readOnly,
2990
3484
  title: active.title,
2991
3485
  prompt,
2992
3486
  maxTokensPerInteraction: active.maxTokensPerInteraction,
@@ -3034,7 +3528,7 @@ var TheseusRuntimeEngine = class {
3034
3528
  workspaceDir: active.workspace.workspaceDir,
3035
3529
  prompt: metadata.prompt,
3036
3530
  signal: active.abort.signal,
3037
- readOnly: metadata.role === "review",
3531
+ readOnly: metadata.readOnly,
3038
3532
  recipeIds: this.options.recipes.map((recipe2) => recipe2.id),
3039
3533
  ...extraSkills.length ? { extraSkills } : {}
3040
3534
  });
@@ -3123,6 +3617,7 @@ export {
3123
3617
  verifyCodeCandidate,
3124
3618
  prepareRuntimeCheckpoint,
3125
3619
  CodeRuntimeCheckpointManager,
3620
+ materializeCodeRuntimeArchive,
3126
3621
  materializeCodeRuntimeSource,
3127
3622
  attachCodeRuntimeReferences,
3128
3623
  materializeCommandWorkspace,
@@ -3146,4 +3641,4 @@ export {
3146
3641
  runGoal,
3147
3642
  TheseusRuntimeEngine
3148
3643
  };
3149
- //# sourceMappingURL=chunk-XSUUHWNX.js.map
3644
+ //# sourceMappingURL=chunk-WM34GGTK.js.map