@odla-ai/harness 0.10.0 → 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.
package/dist/node.cjs CHANGED
@@ -56,6 +56,7 @@ __export(node_exports, {
56
56
  installedDependencies: () => installedDependencies,
57
57
  integrateSubGoals: () => integrateSubGoals,
58
58
  isCheckpointEffectCompleted: () => isCheckpointEffectCompleted,
59
+ materializeCodeRuntimeArchive: () => materializeCodeRuntimeArchive,
59
60
  materializeCodeRuntimeSource: () => materializeCodeRuntimeSource,
60
61
  materializeCommandWorkspace: () => materializeCommandWorkspace,
61
62
  materializeGitTree: () => materializeGitTree,
@@ -232,7 +233,7 @@ async function selectContainerEngine(requested = "auto", options = {}) {
232
233
  throw new TypeError("no supported container engine found");
233
234
  }
234
235
  function inspectRootlessPodman() {
235
- return new Promise((resolve7, reject) => {
236
+ return new Promise((resolve8, reject) => {
236
237
  (0, import_node_child_process.execFile)(
237
238
  "podman",
238
239
  ["info", "--format", "{{.Host.Security.Rootless}}"],
@@ -242,7 +243,7 @@ function inspectRootlessPodman() {
242
243
  reject(new TypeError("could not verify that the active Podman service is rootless"));
243
244
  return;
244
245
  }
245
- resolve7(stdout.trim() === "true");
246
+ resolve8(stdout.trim() === "true");
246
247
  }
247
248
  );
248
249
  });
@@ -1140,6 +1141,34 @@ function createCodeRuntimeControlClient(options) {
1140
1141
  }
1141
1142
  return value;
1142
1143
  };
1144
+ const callRaw = async (path, body) => {
1145
+ const timeout = AbortSignal.timeout(modelRequestTimeoutMs);
1146
+ const signals = [options.signal, timeout].filter((item) => Boolean(item));
1147
+ const signal = signals.length === 1 ? signals[0] : AbortSignal.any(signals);
1148
+ let response2;
1149
+ try {
1150
+ response2 = await request(`${endpoint}${path}`, {
1151
+ method: "POST",
1152
+ headers: { authorization: `Bearer ${options.token}`, "content-type": "application/json" },
1153
+ body: JSON.stringify(body),
1154
+ redirect: "error",
1155
+ signal
1156
+ });
1157
+ } catch (cause) {
1158
+ if (options.signal?.aborted) throw cause;
1159
+ throw new CodeRuntimeControlError("Code source archive is unavailable", 503, "transport_unavailable");
1160
+ }
1161
+ if (!response2.ok) {
1162
+ const value = await response2.json().catch(() => null);
1163
+ const problem = record2(record2(value)?.error);
1164
+ throw new CodeRuntimeControlError(
1165
+ typeof problem?.message === "string" ? problem.message : `Code runtime request failed (${response2.status})`,
1166
+ response2.status,
1167
+ typeof problem?.code === "string" ? problem.code : void 0
1168
+ );
1169
+ }
1170
+ return response2;
1171
+ };
1143
1172
  return {
1144
1173
  heartbeat: async (version, capabilities) => {
1145
1174
  validateHeartbeat(version, capabilities);
@@ -1151,6 +1180,14 @@ function createCodeRuntimeControlClient(options) {
1151
1180
  source: async (sessionId) => parseSource(
1152
1181
  await call(`/registry/code/runtime/sessions/${validSessionId(sessionId)}/source`, {})
1153
1182
  ),
1183
+ sourceArchive: async (sessionId, alias) => {
1184
+ if (!/^[a-z][a-z0-9-]{0,39}$/.test(alias)) throw new TypeError("invalid Code source alias");
1185
+ const response2 = await callRaw(
1186
+ `/registry/code/runtime/sessions/${validSessionId(sessionId)}/source/archive`,
1187
+ { alias }
1188
+ );
1189
+ return parseSourceArchiveResponse(response2, alias);
1190
+ },
1154
1191
  infer: async (sessionId, inference) => {
1155
1192
  const value = record2(await call(
1156
1193
  `/registry/code/runtime/sessions/${validSessionId(sessionId)}/inference`,
@@ -1215,9 +1252,70 @@ function createCodeRuntimeControlClient(options) {
1215
1252
  }
1216
1253
  };
1217
1254
  }
1255
+ var ARCHIVE_LIMIT_MAXIMA = {
1256
+ maxCompressedBytes: 64 * 1024 * 1024,
1257
+ maxDecompressedBytes: 96 * 1024 * 1024,
1258
+ maxEntries: 2e5,
1259
+ maxFiles: 1e5,
1260
+ maxFileBytes: 16 * 1024 * 1024,
1261
+ maxTotalFileBytes: 80 * 1024 * 1024,
1262
+ maxPathBytes: 4096,
1263
+ maxExtendedHeaderBytes: 32 * 1024
1264
+ };
1265
+ async function parseSourceArchiveResponse(response2, expectedAlias) {
1266
+ const alias = response2.headers.get("x-odla-source-alias") ?? "";
1267
+ const repository = response2.headers.get("x-odla-source-repository") ?? "";
1268
+ const commitSha = response2.headers.get("x-odla-source-commit") ?? "";
1269
+ if (alias !== expectedAlias || !/^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/.test(repository) || !/^[0-9a-f]{40}$/.test(commitSha)) {
1270
+ await response2.body?.cancel().catch(() => void 0);
1271
+ throw new CodeRuntimeControlError("invalid Code source archive identity", 502, "invalid_response");
1272
+ }
1273
+ const limits = Object.fromEntries(Object.entries(ARCHIVE_LIMIT_MAXIMA).map(([key, maximum]) => {
1274
+ const header = `x-odla-${key.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`)}`;
1275
+ const value = response2.headers.get(header) ?? "";
1276
+ if (!/^\d+$/.test(value) || !Number.isSafeInteger(Number(value)) || Number(value) < 1 || Number(value) > maximum) {
1277
+ throw new CodeRuntimeControlError("invalid Code source archive limits", 502, "invalid_response");
1278
+ }
1279
+ return [key, Number(value)];
1280
+ }));
1281
+ const length = response2.headers.get("content-length");
1282
+ if (length && (!/^\d+$/.test(length) || Number(length) > limits.maxCompressedBytes)) {
1283
+ await response2.body?.cancel().catch(() => void 0);
1284
+ throw new CodeRuntimeControlError("Code source archive exceeds its byte bound", 502, "invalid_response");
1285
+ }
1286
+ const compressed = await readBoundedResponse(response2.body, limits.maxCompressedBytes);
1287
+ return { alias, repository, commitSha, compressed, limits };
1288
+ }
1289
+ async function readBoundedResponse(body, maximum) {
1290
+ if (!body) throw new CodeRuntimeControlError("Code source archive body is missing", 502, "invalid_response");
1291
+ const reader = body.getReader();
1292
+ const chunks = [];
1293
+ let size = 0;
1294
+ try {
1295
+ while (true) {
1296
+ const { done, value } = await reader.read();
1297
+ if (done) break;
1298
+ size += value.byteLength;
1299
+ if (size > maximum) {
1300
+ await reader.cancel().catch(() => void 0);
1301
+ throw new CodeRuntimeControlError("Code source archive exceeds its byte bound", 502, "invalid_response");
1302
+ }
1303
+ chunks.push(value);
1304
+ }
1305
+ } finally {
1306
+ reader.releaseLock();
1307
+ }
1308
+ const result = new Uint8Array(size);
1309
+ let offset = 0;
1310
+ for (const chunk of chunks) {
1311
+ result.set(chunk, offset);
1312
+ offset += chunk.byteLength;
1313
+ }
1314
+ return result;
1315
+ }
1218
1316
 
1219
1317
  // src/code-runtime.ts
1220
- var CODE_RUNTIME_PROTOCOL_VERSION = 2;
1318
+ var CODE_RUNTIME_PROTOCOL_VERSION = 3;
1221
1319
  async function runCodeRuntimeHeartbeatLoop(options) {
1222
1320
  const heartbeatMs = options.heartbeatMs ?? 15e3;
1223
1321
  if (!Number.isSafeInteger(heartbeatMs) || heartbeatMs < 1e3 || heartbeatMs > 3e5) {
@@ -1286,12 +1384,12 @@ function retryableControlFailure(value) {
1286
1384
  return failure.status === 408 || failure.status === 425 || failure.status === 429 || failure.status >= 500;
1287
1385
  }
1288
1386
  function wait(ms, signal) {
1289
- return new Promise((resolve7) => {
1290
- if (signal?.aborted) return resolve7();
1291
- const timer = setTimeout(resolve7, ms);
1387
+ return new Promise((resolve8) => {
1388
+ if (signal?.aborted) return resolve8();
1389
+ const timer = setTimeout(resolve8, ms);
1292
1390
  signal?.addEventListener("abort", () => {
1293
1391
  clearTimeout(timer);
1294
- resolve7();
1392
+ resolve8();
1295
1393
  }, { once: true });
1296
1394
  });
1297
1395
  }
@@ -1949,7 +2047,8 @@ function codeCommandMetadata(payload, resume) {
1949
2047
  const repository = trusted?.repository;
1950
2048
  const baseCommitSha = trusted?.commitSha;
1951
2049
  const sourceTreeDigest = trusted?.treeDigest;
1952
- 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)) {
2050
+ const hostMaterialized = record3(payload.sourceSet) !== null && sourceTreeDigest === void 0;
2051
+ 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))) {
1953
2052
  throw new TypeError(`invalid Code ${resume ? "resume" : "start"} trusted base`);
1954
2053
  }
1955
2054
  if (!Number.isSafeInteger(maxTokensPerInteraction) || Number(maxTokensPerInteraction) < 4e3 || Number(maxTokensPerInteraction) > 2e5) {
@@ -1965,7 +2064,7 @@ function codeCommandMetadata(payload, resume) {
1965
2064
  attestationDigest: typeof attestation === "string" ? attestation : "resume",
1966
2065
  repository,
1967
2066
  baseCommitSha,
1968
- sourceTreeDigest
2067
+ sourceTreeDigest: typeof sourceTreeDigest === "string" ? sourceTreeDigest : null
1969
2068
  };
1970
2069
  }
1971
2070
  function codeLocalSource(payload) {
@@ -2030,19 +2129,320 @@ async function prepareRuntimeLocalSource(input) {
2030
2129
  }
2031
2130
 
2032
2131
  // src/code-runtime-source.ts
2132
+ var import_promises10 = require("fs/promises");
2133
+ var import_node_os4 = require("os");
2134
+ var import_node_path10 = require("path");
2135
+
2136
+ // src/code-runtime-archive.ts
2137
+ var import_node_zlib = require("zlib");
2033
2138
  var import_promises8 = require("fs/promises");
2034
2139
  var import_node_os3 = require("os");
2035
2140
  var import_node_path8 = require("path");
2036
2141
  var RESERVED2 = /* @__PURE__ */ new Set([".git", ".odla", ".wrangler", "node_modules", "dist", "coverage"]);
2037
2142
  var SECRET2 = /^(?:\.env(?:\..+)?|\.dev\.vars|credentials(?:\..+)?\.json|dev-token(?:\..+)?\.json)$/i;
2143
+ var MAX_NUL_SHARE = 0.1;
2144
+ async function materializeCodeRuntimeArchive(archive, visiblePaths, tempRoot = (0, import_node_os3.tmpdir)()) {
2145
+ if (!archive.compressed.byteLength || archive.compressed.byteLength > archive.limits.maxCompressedBytes) {
2146
+ throw new TypeError("Code source archive exceeds its compressed byte bound");
2147
+ }
2148
+ let bytes;
2149
+ try {
2150
+ bytes = archive.compressed[0] === 31 && archive.compressed[1] === 139 ? (0, import_node_zlib.gunzipSync)(archive.compressed, { maxOutputLength: archive.limits.maxDecompressedBytes }) : archive.compressed;
2151
+ } catch {
2152
+ throw new TypeError("Code source archive is not a valid bounded gzip stream");
2153
+ }
2154
+ if (bytes.byteLength > archive.limits.maxDecompressedBytes) {
2155
+ throw new TypeError("Code source archive exceeds its decompressed byte bound");
2156
+ }
2157
+ const entries = parseTar(bytes, archive.limits);
2158
+ const root = await (0, import_promises8.mkdtemp)((0, import_node_path8.join)(tempRoot, "odla-code-archive-"));
2159
+ const sourceDir = (0, import_node_path8.join)(root, "source");
2160
+ await (0, import_promises8.mkdir)(sourceDir);
2161
+ let visible = 0;
2162
+ try {
2163
+ for (const entry of entries) {
2164
+ if (entry.directory || visiblePaths && !visiblePaths.has(entry.path)) continue;
2165
+ if (filteredPath(entry.path)) continue;
2166
+ let content;
2167
+ try {
2168
+ content = new TextDecoder("utf-8", { fatal: true, ignoreBOM: false }).decode(entry.bytes);
2169
+ } catch {
2170
+ continue;
2171
+ }
2172
+ if (nulShare(content) > MAX_NUL_SHARE) continue;
2173
+ const target = (0, import_node_path8.resolve)(sourceDir, entry.path);
2174
+ if (!target.startsWith(`${(0, import_node_path8.resolve)(sourceDir)}${import_node_path8.sep}`)) throw new TypeError("Code source path escapes its root");
2175
+ await (0, import_promises8.mkdir)((0, import_node_path8.dirname)(target), { recursive: true });
2176
+ await (0, import_promises8.writeFile)(target, content, { flag: "wx", mode: 420 });
2177
+ visible += 1;
2178
+ }
2179
+ if (!visible && !visiblePaths) throw new TypeError("GitHub commit has no Code-visible text source");
2180
+ return { sourceDir, cleanup: () => (0, import_promises8.rm)(root, { recursive: true, force: true }) };
2181
+ } catch (cause) {
2182
+ await (0, import_promises8.rm)(root, { recursive: true, force: true });
2183
+ throw cause;
2184
+ }
2185
+ }
2186
+ function parseTar(bytes, limits) {
2187
+ const decoder = new TextDecoder("utf-8", { fatal: true, ignoreBOM: false });
2188
+ const entries = [];
2189
+ const archivePaths = /* @__PURE__ */ new Set();
2190
+ let entryCount = 0;
2191
+ let fileCount = 0;
2192
+ let totalFileBytes = 0;
2193
+ let pendingPath;
2194
+ let pendingPaxPath;
2195
+ let offset = 0;
2196
+ let ended = false;
2197
+ while (offset + 512 <= bytes.byteLength) {
2198
+ const header = bytes.subarray(offset, offset + 512);
2199
+ offset += 512;
2200
+ if (zeroBlock(header)) {
2201
+ ended = true;
2202
+ assertZeroTail(bytes, offset);
2203
+ break;
2204
+ }
2205
+ entryCount += 1;
2206
+ if (entryCount > limits.maxEntries) throw new TypeError("Code source archive has too many entries");
2207
+ validateChecksum(header);
2208
+ const type = header[156] ?? 0;
2209
+ const size = tarNumber(header.subarray(124, 136));
2210
+ if (size > limits.maxDecompressedBytes || offset + aligned(size) > bytes.byteLength) {
2211
+ throw new TypeError("Code source archive entry is invalid or too large");
2212
+ }
2213
+ const payload = bytes.subarray(offset, offset + size);
2214
+ offset += aligned(size);
2215
+ if (type === 120 || type === 103) {
2216
+ if (size > limits.maxExtendedHeaderBytes) throw new TypeError("Code source archive extended header is too large");
2217
+ const pax = parsePax(payload, decoder, limits.maxPathBytes);
2218
+ if (pax.linkpath !== void 0 || pax.size !== void 0 || Object.keys(pax).some((key) => key.toLowerCase().includes("sparse"))) {
2219
+ throw new TypeError("Code source archive contains an unsupported entry");
2220
+ }
2221
+ if (type === 103 && pax.path !== void 0) throw new TypeError("Code source archive path is unsafe");
2222
+ if (type === 120 && pax.path !== void 0) {
2223
+ if (pendingPaxPath !== void 0 || pendingPath !== void 0) throw new TypeError("Code source archive is invalid");
2224
+ pendingPaxPath = pax.path;
2225
+ }
2226
+ continue;
2227
+ }
2228
+ if (type === 76) {
2229
+ if (size > limits.maxExtendedHeaderBytes || pendingPath !== void 0 || pendingPaxPath !== void 0) {
2230
+ throw new TypeError("Code source archive long path is invalid");
2231
+ }
2232
+ pendingPath = validateArchivePath(decode(payload, decoder).replace(/\0+$/, "").replace(/\n$/, ""), limits.maxPathBytes);
2233
+ continue;
2234
+ }
2235
+ if (type === 75) throw new TypeError("Code source archive contains an unsupported link");
2236
+ const path = validateArchivePath(pendingPaxPath ?? pendingPath ?? tarPath(header, decoder), limits.maxPathBytes);
2237
+ pendingPaxPath = void 0;
2238
+ pendingPath = void 0;
2239
+ const directory = type === 53;
2240
+ const regular = type === 0 || type === 48;
2241
+ if (!directory && !regular || directory && size !== 0 || archivePaths.has(path)) {
2242
+ throw new TypeError("Code source archive contains an invalid or duplicate entry");
2243
+ }
2244
+ archivePaths.add(path);
2245
+ if (regular) {
2246
+ fileCount += 1;
2247
+ totalFileBytes += size;
2248
+ if (fileCount > limits.maxFiles || size > limits.maxFileBytes || totalFileBytes > limits.maxTotalFileBytes) {
2249
+ throw new TypeError("Code source archive exceeds its file bounds");
2250
+ }
2251
+ }
2252
+ entries.push({ path, directory, ...regular ? { bytes: payload } : {} });
2253
+ }
2254
+ if (!ended || pendingPath !== void 0 || pendingPaxPath !== void 0 || !entries.length || !fileCount) {
2255
+ throw new TypeError("Code source archive is incomplete");
2256
+ }
2257
+ return unwrapRepository(entries, limits.maxPathBytes);
2258
+ }
2259
+ function unwrapRepository(entries, maxPathBytes) {
2260
+ const root = entries[0].path.split("/")[0];
2261
+ if (!root || entries.some((entry) => entry.path !== root && !entry.path.startsWith(`${root}/`))) {
2262
+ throw new TypeError("Code source archive has no single repository root");
2263
+ }
2264
+ const output = [];
2265
+ const kinds = /* @__PURE__ */ new Map();
2266
+ for (const entry of entries) {
2267
+ if (entry.path === root) {
2268
+ if (!entry.directory) throw new TypeError("Code source archive root is not a directory");
2269
+ continue;
2270
+ }
2271
+ const path = entry.path.slice(root.length + 1);
2272
+ validateRepositoryPath(path, maxPathBytes);
2273
+ const parts = path.split("/");
2274
+ for (let index = 1; index < parts.length; index += 1) {
2275
+ if (kinds.get(parts.slice(0, index).join("/")) === "file") throw new TypeError("Code source archive path conflicts");
2276
+ }
2277
+ if (!entry.directory) {
2278
+ for (const existing of kinds.keys()) {
2279
+ if (existing.startsWith(`${path}/`)) throw new TypeError("Code source archive path conflicts");
2280
+ }
2281
+ }
2282
+ if (kinds.has(path)) throw new TypeError("Code source archive repeats a path");
2283
+ kinds.set(path, entry.directory ? "directory" : "file");
2284
+ output.push({ ...entry, path });
2285
+ }
2286
+ return output.sort((left, right) => left.path.localeCompare(right.path));
2287
+ }
2288
+ function parsePax(bytes, decoder, maxPathBytes) {
2289
+ const result = {};
2290
+ let offset = 0;
2291
+ while (offset < bytes.byteLength) {
2292
+ const space = bytes.indexOf(32, offset);
2293
+ if (space < 0) throw new TypeError("Code source archive PAX header is invalid");
2294
+ const lengthText = ascii(bytes.subarray(offset, space));
2295
+ if (!/^[1-9][0-9]{0,8}$/.test(lengthText)) throw new TypeError("Code source archive PAX length is invalid");
2296
+ const length = Number(lengthText);
2297
+ const end = offset + length;
2298
+ if (!Number.isSafeInteger(length) || end > bytes.byteLength || bytes[end - 1] !== 10) {
2299
+ throw new TypeError("Code source archive PAX record is invalid");
2300
+ }
2301
+ const record5 = decode(bytes.subarray(space + 1, end - 1), decoder);
2302
+ const equals = record5.indexOf("=");
2303
+ if (equals < 1) throw new TypeError("Code source archive PAX field is invalid");
2304
+ const key = record5.slice(0, equals);
2305
+ if (Object.hasOwn(result, key)) throw new TypeError("Code source archive PAX field repeats");
2306
+ result[key] = record5.slice(equals + 1);
2307
+ offset = end;
2308
+ }
2309
+ if (result.path !== void 0) result.path = validateArchivePath(result.path, maxPathBytes);
2310
+ return result;
2311
+ }
2312
+ var aligned = (size) => Math.ceil(size / 512) * 512;
2313
+ var zeroBlock = (block) => block.every((value) => value === 0);
2314
+ function validateChecksum(header) {
2315
+ const expected = tarNumber(header.subarray(148, 156));
2316
+ let actual = 0;
2317
+ for (let index = 0; index < header.length; index += 1) actual += index >= 148 && index < 156 ? 32 : header[index];
2318
+ if (actual !== expected) throw new TypeError("Code source archive checksum is invalid");
2319
+ }
2320
+ function tarNumber(field) {
2321
+ if ((field[0] ?? 0) & 128) throw new TypeError("Code source archive numeric format is unsupported");
2322
+ const value = ascii(field).replaceAll("\0", "").trim();
2323
+ if (!value) return 0;
2324
+ if (!/^[0-7]+$/.test(value)) throw new TypeError("Code source archive number is invalid");
2325
+ const parsed = Number.parseInt(value, 8);
2326
+ if (!Number.isSafeInteger(parsed) || parsed < 0) throw new TypeError("Code source archive number is too large");
2327
+ return parsed;
2328
+ }
2329
+ function tarPath(header, decoder) {
2330
+ const name = decodeNul(header.subarray(0, 100), decoder);
2331
+ const prefix = decodeNul(header.subarray(345, 500), decoder);
2332
+ return prefix ? `${prefix}/${name}` : name;
2333
+ }
2334
+ function decodeNul(value, decoder) {
2335
+ const end = value.indexOf(0);
2336
+ return decode(end < 0 ? value : value.subarray(0, end), decoder);
2337
+ }
2338
+ function decode(value, decoder) {
2339
+ try {
2340
+ return decoder.decode(value);
2341
+ } catch {
2342
+ throw new TypeError("Code source archive text is invalid UTF-8");
2343
+ }
2344
+ }
2345
+ function ascii(value) {
2346
+ let output = "";
2347
+ for (const byte of value) output += String.fromCharCode(byte);
2348
+ return output;
2349
+ }
2350
+ function validateArchivePath(input, maximum) {
2351
+ const path = input.endsWith("/") ? input.slice(0, -1) : input;
2352
+ validateRepositoryPath(path, maximum);
2353
+ return path;
2354
+ }
2355
+ function validateRepositoryPath(path, maximum) {
2356
+ if (!path || path.startsWith("/") || path.includes("\\") || /[\u0000-\u001f\u007f]/.test(path) || new TextEncoder().encode(path).byteLength > maximum || path.split("/").some((part) => !part || part === "." || part === "..")) {
2357
+ throw new TypeError("Code source archive path is unsafe");
2358
+ }
2359
+ }
2360
+ function assertZeroTail(bytes, offset) {
2361
+ for (let index = offset; index < bytes.byteLength; index += 1) {
2362
+ if (bytes[index] !== 0) throw new TypeError("Code source archive has data after its end marker");
2363
+ }
2364
+ }
2365
+ function filteredPath(path) {
2366
+ const parts = path.split("/");
2367
+ return parts.some((part) => RESERVED2.has(part) || SECRET2.test(part));
2368
+ }
2369
+ function nulShare(content) {
2370
+ if (!content.length) return 0;
2371
+ let count = 0;
2372
+ for (let index = 0; index < content.length; index += 1) if (content.charCodeAt(index) === 0) count += 1;
2373
+ return count / content.length;
2374
+ }
2375
+
2376
+ // src/code-runtime-selected-source.ts
2377
+ var import_promises9 = require("fs/promises");
2378
+ var import_node_path9 = require("path");
2379
+ function selectedSourceSet(payload) {
2380
+ if (!payload.sourceSet) return null;
2381
+ const set = payload.sourceSet && typeof payload.sourceSet === "object" && !Array.isArray(payload.sourceSet) ? payload.sourceSet : null;
2382
+ if (!set) throw new TypeError("Code selected source set is invalid");
2383
+ const parse = (value, primary2) => {
2384
+ const item = value && typeof value === "object" && !Array.isArray(value) ? value : null;
2385
+ const alias = item?.alias;
2386
+ const repository = item?.repository;
2387
+ const commitSha = item?.commitSha;
2388
+ const materialization = item?.materialization ?? "registry_snapshot";
2389
+ 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))) {
2390
+ throw new TypeError("Code selected source identity is invalid");
2391
+ }
2392
+ const visiblePaths = item?.visiblePaths;
2393
+ if (visiblePaths !== void 0 && (!Array.isArray(visiblePaths) || visiblePaths.length > 2e3 || visiblePaths.some((path) => typeof path !== "string" || path.length > 4096))) {
2394
+ throw new TypeError("Code selected source visibility slice is invalid");
2395
+ }
2396
+ return {
2397
+ alias,
2398
+ repository,
2399
+ commitSha,
2400
+ materialization,
2401
+ ...visiblePaths ? { visiblePaths } : {}
2402
+ };
2403
+ };
2404
+ if (!Array.isArray(set.references)) throw new TypeError("Code selected source references are invalid");
2405
+ const primary = parse(set.primary, true);
2406
+ const references = set.references.map((item) => parse(item, false));
2407
+ const aliases = /* @__PURE__ */ new Set([primary.alias, ...references.map((item) => item.alias)]);
2408
+ if (aliases.size !== references.length + 1) throw new TypeError("Code selected source aliases repeat");
2409
+ return { primary, references };
2410
+ }
2411
+ async function attachReferenceDirectories(workspace, references) {
2412
+ for (const reference of references) {
2413
+ validateAlias(reference.alias);
2414
+ for (const root of [workspace.baselineDir, workspace.workspaceDir]) {
2415
+ const target = (0, import_node_path9.join)(root, ".odla-references", reference.alias);
2416
+ await (0, import_promises9.mkdir)((0, import_node_path9.dirname)(target), { recursive: true });
2417
+ await (0, import_promises9.cp)(reference.sourceDir, target, { recursive: true, errorOnExist: true, force: false });
2418
+ await makeTreeReadOnly(target);
2419
+ }
2420
+ }
2421
+ }
2422
+ function validateAlias(alias) {
2423
+ if (!/^[a-z][a-z0-9-]{0,39}$/.test(alias) || alias === "primary") {
2424
+ throw new TypeError("Code reference alias is invalid");
2425
+ }
2426
+ }
2427
+ async function makeTreeReadOnly(root) {
2428
+ for (const entry of await (0, import_promises9.readdir)(root, { withFileTypes: true })) {
2429
+ const target = (0, import_node_path9.join)(root, entry.name);
2430
+ if (entry.isDirectory()) await makeTreeReadOnly(target);
2431
+ else if (entry.isFile()) await (0, import_promises9.chmod)(target, 292);
2432
+ }
2433
+ }
2434
+
2435
+ // src/code-runtime-source.ts
2436
+ var RESERVED3 = /* @__PURE__ */ new Set([".git", ".odla", ".wrangler", "node_modules", "dist", "coverage"]);
2437
+ var SECRET3 = /^(?:\.env(?:\..+)?|\.dev\.vars|credentials(?:\..+)?\.json|dev-token(?:\..+)?\.json)$/i;
2038
2438
  var SOURCE_MAX_FILES = 1e5;
2039
2439
  var SOURCE_MAX_BYTES = 80 * 1024 * 1024;
2040
2440
  var SOURCE_SET_MAX_BYTES = 480 * 1024 * 1024;
2041
- async function materializeCodeRuntimeSource(snapshot, tempRoot = (0, import_node_os3.tmpdir)()) {
2441
+ async function materializeCodeRuntimeSource(snapshot, tempRoot = (0, import_node_os4.tmpdir)()) {
2042
2442
  if (!snapshot.files.length || snapshot.files.length > SOURCE_MAX_FILES) throw new TypeError("Code source file count is invalid");
2043
- const root = await (0, import_promises8.mkdtemp)((0, import_node_path8.join)(tempRoot, "odla-code-source-"));
2044
- const sourceDir = (0, import_node_path8.join)(root, "source");
2045
- await (0, import_promises8.mkdir)(sourceDir);
2443
+ const root = await (0, import_promises10.mkdtemp)((0, import_node_path10.join)(tempRoot, "odla-code-source-"));
2444
+ const sourceDir = (0, import_node_path10.join)(root, "source");
2445
+ await (0, import_promises10.mkdir)(sourceDir);
2046
2446
  const seen = /* @__PURE__ */ new Set();
2047
2447
  let bytes = 0;
2048
2448
  try {
@@ -2052,13 +2452,13 @@ async function materializeCodeRuntimeSource(snapshot, tempRoot = (0, import_node
2052
2452
  seen.add(file.path);
2053
2453
  bytes += Buffer.byteLength(file.path) + Buffer.byteLength(file.content);
2054
2454
  if (bytes > SOURCE_MAX_BYTES) throw new TypeError("Code source exceeds its byte bound");
2055
- const target = (0, import_node_path8.resolve)(sourceDir, file.path);
2056
- if (!target.startsWith(`${(0, import_node_path8.resolve)(sourceDir)}${import_node_path8.sep}`)) throw new TypeError("Code source path escapes its root");
2057
- await (0, import_promises8.mkdir)((0, import_node_path8.dirname)(target), { recursive: true });
2058
- await (0, import_promises8.writeFile)(target, file.content, { flag: "wx", mode: 420 });
2455
+ const target = (0, import_node_path10.resolve)(sourceDir, file.path);
2456
+ if (!target.startsWith(`${(0, import_node_path10.resolve)(sourceDir)}${import_node_path10.sep}`)) throw new TypeError("Code source path escapes its root");
2457
+ await (0, import_promises10.mkdir)((0, import_node_path10.dirname)(target), { recursive: true });
2458
+ await (0, import_promises10.writeFile)(target, file.content, { flag: "wx", mode: 420 });
2059
2459
  }
2060
2460
  for (const reference of snapshot.references ?? []) {
2061
- validateAlias(reference.alias);
2461
+ validateAlias2(reference.alias);
2062
2462
  if (!reference.files.length || reference.files.length > SOURCE_MAX_FILES) throw new TypeError("Code reference file count is invalid");
2063
2463
  for (const file of reference.files) {
2064
2464
  validatePath(file.path);
@@ -2067,19 +2467,19 @@ async function materializeCodeRuntimeSource(snapshot, tempRoot = (0, import_node
2067
2467
  seen.add(path);
2068
2468
  bytes += Buffer.byteLength(path) + Buffer.byteLength(file.content);
2069
2469
  if (bytes > SOURCE_SET_MAX_BYTES) throw new TypeError("Code source set exceeds its byte bound");
2070
- const target = (0, import_node_path8.resolve)(sourceDir, path);
2071
- if (!target.startsWith(`${(0, import_node_path8.resolve)(sourceDir)}${import_node_path8.sep}`)) throw new TypeError("Code reference path escapes its root");
2072
- await (0, import_promises8.mkdir)((0, import_node_path8.dirname)(target), { recursive: true });
2073
- await (0, import_promises8.writeFile)(target, file.content, { flag: "wx", mode: 292 });
2470
+ const target = (0, import_node_path10.resolve)(sourceDir, path);
2471
+ if (!target.startsWith(`${(0, import_node_path10.resolve)(sourceDir)}${import_node_path10.sep}`)) throw new TypeError("Code reference path escapes its root");
2472
+ await (0, import_promises10.mkdir)((0, import_node_path10.dirname)(target), { recursive: true });
2473
+ await (0, import_promises10.writeFile)(target, file.content, { flag: "wx", mode: 292 });
2074
2474
  }
2075
2475
  }
2076
- return { sourceDir, cleanup: () => (0, import_promises8.rm)(root, { recursive: true, force: true }) };
2476
+ return { sourceDir, cleanup: () => (0, import_promises10.rm)(root, { recursive: true, force: true }) };
2077
2477
  } catch (cause) {
2078
- await (0, import_promises8.rm)(root, { recursive: true, force: true });
2478
+ await (0, import_promises10.rm)(root, { recursive: true, force: true });
2079
2479
  throw cause;
2080
2480
  }
2081
2481
  }
2082
- function validateAlias(alias) {
2482
+ function validateAlias2(alias) {
2083
2483
  if (!/^[a-z][a-z0-9-]{0,39}$/.test(alias) || alias === "primary") {
2084
2484
  throw new TypeError("Code reference alias is invalid");
2085
2485
  }
@@ -2087,24 +2487,24 @@ function validateAlias(alias) {
2087
2487
  async function attachCodeRuntimeReferences(workspace, references) {
2088
2488
  let bytes = 0;
2089
2489
  for (const reference of references) {
2090
- validateAlias(reference.alias);
2490
+ validateAlias2(reference.alias);
2091
2491
  for (const file of reference.files) {
2092
2492
  validatePath(file.path);
2093
2493
  const path = `.odla-references/${reference.alias}/${file.path}`;
2094
2494
  bytes += Buffer.byteLength(path) + Buffer.byteLength(file.content);
2095
2495
  if (bytes > SOURCE_SET_MAX_BYTES - SOURCE_MAX_BYTES) throw new TypeError("Code reference set exceeds its byte bound");
2096
2496
  for (const root of [workspace.baselineDir, workspace.workspaceDir]) {
2097
- const target = (0, import_node_path8.resolve)(root, path);
2098
- if (!target.startsWith(`${(0, import_node_path8.resolve)(root)}${import_node_path8.sep}`)) throw new TypeError("Code reference path escapes its root");
2099
- await (0, import_promises8.mkdir)((0, import_node_path8.dirname)(target), { recursive: true });
2100
- await (0, import_promises8.writeFile)(target, file.content, { flag: "wx", mode: 292 });
2497
+ const target = (0, import_node_path10.resolve)(root, path);
2498
+ if (!target.startsWith(`${(0, import_node_path10.resolve)(root)}${import_node_path10.sep}`)) throw new TypeError("Code reference path escapes its root");
2499
+ await (0, import_promises10.mkdir)((0, import_node_path10.dirname)(target), { recursive: true });
2500
+ await (0, import_promises10.writeFile)(target, file.content, { flag: "wx", mode: 292 });
2101
2501
  }
2102
2502
  }
2103
2503
  }
2104
2504
  }
2105
2505
  function validatePath(path) {
2106
2506
  const parts = path.split("/");
2107
- if (!path || path.startsWith("/") || path.includes("\\") || path.includes("\0") || parts.some((part) => !part || part === "." || part === ".." || RESERVED2.has(part) || SECRET2.test(part))) {
2507
+ if (!path || path.startsWith("/") || path.includes("\\") || path.includes("\0") || parts.some((part) => !part || part === "." || part === ".." || RESERVED3.has(part) || SECRET3.test(part))) {
2108
2508
  throw new TypeError("Code source contains an unsafe path");
2109
2509
  }
2110
2510
  }
@@ -2132,12 +2532,12 @@ async function materializeCommandWorkspace(input) {
2132
2532
  throw new TypeError("Code selected source set is invalid");
2133
2533
  }
2134
2534
  if (references.length) {
2135
- const selected = await input.control.source(command.sessionId);
2136
- if (selected.repository !== metadata.repository || selected.commitSha !== metadata.baseCommitSha || selected.treeDigest !== metadata.sourceTreeDigest) {
2535
+ const selected2 = await input.control.source(command.sessionId);
2536
+ if (selected2.repository !== metadata.repository || selected2.commitSha !== metadata.baseCommitSha || selected2.treeDigest !== metadata.sourceTreeDigest) {
2137
2537
  await prepared.workspace.cleanup();
2138
2538
  throw new TypeError("Code local source does not match the selected GitHub primary source");
2139
2539
  }
2140
- await attachCodeRuntimeReferences(prepared.workspace, selected.references ?? []);
2540
+ await attachCodeRuntimeReferences(prepared.workspace, selected2.references ?? []);
2141
2541
  }
2142
2542
  }
2143
2543
  return {
@@ -2147,6 +2547,63 @@ async function materializeCommandWorkspace(input) {
2147
2547
  requestedLocal
2148
2548
  };
2149
2549
  }
2550
+ const selected = selectedSourceSet(command.payload);
2551
+ if (selected?.primary.materialization === "host_archive") {
2552
+ if (!input.control.sourceArchive) {
2553
+ throw new TypeError("Code runtime protocol does not support host source materialization");
2554
+ }
2555
+ const sources = [selected.primary, ...selected.references];
2556
+ const materialized2 = [];
2557
+ try {
2558
+ for (const descriptor2 of sources) {
2559
+ if (descriptor2.materialization !== "host_archive") {
2560
+ throw new TypeError("Code selected source set mixes incompatible materialization modes");
2561
+ }
2562
+ const archive = await input.control.sourceArchive(command.sessionId, descriptor2.alias);
2563
+ if (archive.repository !== descriptor2.repository || archive.commitSha !== descriptor2.commitSha) {
2564
+ throw new TypeError("Code source archive does not match its selected repository and commit");
2565
+ }
2566
+ const source2 = await materializeCodeRuntimeArchive(
2567
+ archive,
2568
+ descriptor2.visiblePaths ? new Set(descriptor2.visiblePaths) : void 0
2569
+ );
2570
+ const treeDigest = await digestStagedWorkspace(source2.sourceDir, {
2571
+ maxFiles: archive.limits.maxFiles,
2572
+ maxBytes: archive.limits.maxTotalFileBytes
2573
+ });
2574
+ materialized2.push({ descriptor: descriptor2, source: source2, treeDigest });
2575
+ }
2576
+ const primary = materialized2[0];
2577
+ const workspace = resume ? (await restoreCodeWorkspaceCheckpoint({
2578
+ trustedBaseDir: primary.source.sourceDir,
2579
+ trustedBaseCommitSha: primary.descriptor.commitSha,
2580
+ checkpoint: codeCheckpointPayload(command.payload)
2581
+ })).workspace : await stageWorkspace(primary.source.sourceDir, {
2582
+ maxFiles: SOURCE_MAX_FILES,
2583
+ maxBytes: SOURCE_SET_MAX_BYTES
2584
+ });
2585
+ try {
2586
+ await attachReferenceDirectories(workspace, materialized2.slice(1).map((item) => ({
2587
+ alias: item.descriptor.alias,
2588
+ sourceDir: item.source.sourceDir
2589
+ })));
2590
+ } catch (cause) {
2591
+ await workspace.cleanup();
2592
+ throw cause;
2593
+ }
2594
+ return {
2595
+ workspace,
2596
+ sourceDigest: primary.treeDigest,
2597
+ requestedLocal: null,
2598
+ sourceDigests: materialized2.map((item) => ({
2599
+ alias: item.descriptor.alias,
2600
+ treeDigest: item.treeDigest
2601
+ }))
2602
+ };
2603
+ } finally {
2604
+ await Promise.allSettled(materialized2.map((item) => item.source.cleanup()));
2605
+ }
2606
+ }
2150
2607
  const source = await input.control.source(command.sessionId);
2151
2608
  const materialized = await materializeCodeRuntimeSource(source);
2152
2609
  try {
@@ -2484,14 +2941,40 @@ async function sessionSkillsFor(options, command) {
2484
2941
  }
2485
2942
 
2486
2943
  // src/code-runtime-inference.ts
2944
+ var OVERLOAD_RETRY_DELAYS_MS = [2e3, 4e3, 8e3, 16e3];
2945
+ var RETRYABLE_CODES = /* @__PURE__ */ new Set(["control_plane_overloaded", "registry_overloaded", "transport_unavailable"]);
2946
+ function overloadedControlFailure(cause) {
2947
+ return cause instanceof CodeRuntimeControlError && cause.status === 503 && RETRYABLE_CODES.has(cause.code);
2948
+ }
2949
+ async function inferWithBackoff(infer, wait2, onRetry) {
2950
+ for (let attempt = 0; ; attempt += 1) {
2951
+ try {
2952
+ return await infer();
2953
+ } catch (cause) {
2954
+ const delayMs = OVERLOAD_RETRY_DELAYS_MS[attempt];
2955
+ if (delayMs === void 0 || !overloadedControlFailure(cause)) throw cause;
2956
+ await onRetry(cause, delayMs);
2957
+ await wait2(delayMs);
2958
+ }
2959
+ }
2960
+ }
2487
2961
  async function handleCodeRuntimeInference(input) {
2488
2962
  const { command, request, state } = input;
2489
2963
  const startedAt = Date.now();
2490
- const response2 = await input.control.infer(command.sessionId, {
2491
- requestId: request.requestId,
2492
- interactionId: command.commandId,
2493
- call: request.call
2494
- });
2964
+ const wait2 = input.wait ?? ((ms) => new Promise((resolve8) => setTimeout(resolve8, ms)));
2965
+ const response2 = await inferWithBackoff(
2966
+ () => input.control.infer(command.sessionId, {
2967
+ requestId: request.requestId,
2968
+ interactionId: command.commandId,
2969
+ call: request.call
2970
+ }),
2971
+ wait2,
2972
+ (cause, delayMs) => input.event({
2973
+ type: "diagnostic",
2974
+ level: "error",
2975
+ message: `Code control plane overloaded (${cause.code}); retrying the model call in ${delayMs / 1e3}s`
2976
+ }).catch(() => void 0)
2977
+ );
2495
2978
  state.tokens += response2.receipt.inputTokens + response2.receipt.outputTokens;
2496
2979
  const { costUsd } = response2.receipt;
2497
2980
  if (costUsd === void 0) state.costKnown = false;
@@ -2954,12 +3437,12 @@ function response(request, ok, content, details) {
2954
3437
  }
2955
3438
 
2956
3439
  // src/code-tool-reads.ts
2957
- var import_promises11 = require("fs/promises");
3440
+ var import_promises13 = require("fs/promises");
2958
3441
 
2959
3442
  // src/code-tool-discovery.ts
2960
3443
  var import_node_child_process6 = require("child_process");
2961
- var import_promises9 = require("fs/promises");
2962
- var import_node_path9 = require("path");
3444
+ var import_promises11 = require("fs/promises");
3445
+ var import_node_path11 = require("path");
2963
3446
  var DEFAULT_MAX_FILES = 2e4;
2964
3447
  var DEFAULT_MAX_RESULTS = 100;
2965
3448
  var DEFAULT_MAX_FILE_BYTES = 512 * 1024;
@@ -2984,13 +3467,13 @@ function createWorkspaceFileRegistry(limit = DEFAULT_MAX_FILES, enumerate = regi
2984
3467
  async function registeredFiles(root, limit = DEFAULT_MAX_FILES) {
2985
3468
  const paths2 = [];
2986
3469
  const walk = async (directory) => {
2987
- for (const entry of await (0, import_promises9.readdir)(directory, { withFileTypes: true })) {
3470
+ for (const entry of await (0, import_promises11.readdir)(directory, { withFileTypes: true })) {
2988
3471
  if (SKIP_WORKSPACE_DIRS.has(entry.name)) continue;
2989
3472
  if (entry.isSymbolicLink()) throw new TypeError("workspace contains a symbolic link");
2990
- const target = (0, import_node_path9.resolve)(directory, entry.name);
3473
+ const target = (0, import_node_path11.resolve)(directory, entry.name);
2991
3474
  if (entry.isDirectory()) await walk(target);
2992
3475
  else if (entry.isFile()) {
2993
- const path = (0, import_node_path9.relative)(root, target).split("\\").join("/");
3476
+ const path = (0, import_node_path11.relative)(root, target).split("\\").join("/");
2994
3477
  try {
2995
3478
  validateRelativePath(path);
2996
3479
  } catch {
@@ -3001,7 +3484,7 @@ async function registeredFiles(root, limit = DEFAULT_MAX_FILES) {
3001
3484
  }
3002
3485
  }
3003
3486
  };
3004
- await walk((0, import_node_path9.resolve)(root));
3487
+ await walk((0, import_node_path11.resolve)(root));
3005
3488
  return paths2.sort();
3006
3489
  }
3007
3490
  function listWorkspace(paths2, options = {}) {
@@ -3115,7 +3598,7 @@ async function fallbackSearch(root, scoped, options) {
3115
3598
  if (matches.length >= options.maxResults) break;
3116
3599
  let source;
3117
3600
  try {
3118
- source = await (0, import_promises9.readFile)((0, import_node_path9.resolve)(root, path));
3601
+ source = await (0, import_promises11.readFile)((0, import_node_path11.resolve)(root, path));
3119
3602
  } catch {
3120
3603
  continue;
3121
3604
  }
@@ -3133,15 +3616,15 @@ async function fallbackSearch(root, scoped, options) {
3133
3616
  }
3134
3617
 
3135
3618
  // src/code-tool-graph.ts
3136
- var import_promises10 = require("fs/promises");
3137
- var import_node_path10 = require("path");
3619
+ var import_promises12 = require("fs/promises");
3620
+ var import_node_path12 = require("path");
3138
3621
  var import_graph = require("@odla-ai/graph");
3139
3622
  var import_code4 = require("@odla-ai/graph/code");
3140
3623
  var cache = /* @__PURE__ */ new Map();
3141
3624
  function workspaceGraphs(workspaceDir, paths2) {
3142
3625
  const existing = cache.get(workspaceDir);
3143
3626
  if (existing) return existing;
3144
- const read2 = (path) => (0, import_promises10.readFile)((0, import_node_path10.join)(workspaceDir, path), "utf8");
3627
+ const read2 = (path) => (0, import_promises12.readFile)((0, import_node_path12.join)(workspaceDir, path), "utf8");
3145
3628
  const built = (async () => ({
3146
3629
  // No knownTables: a staged workspace may not carry migrations, and a filter
3147
3630
  // that silently drops every table is worse than an unfiltered one. Callers
@@ -3215,11 +3698,11 @@ async function read(context, request, options, policy, registry) {
3215
3698
  const allowed = await policy.read(policyContext(context, request, options, { paths: paths2, path, startLine, endLine }));
3216
3699
  if (!allowed) return response(request, false, "tool denied by CaMeL policy");
3217
3700
  const target = resolveCodePath(context.workspaceDir, path);
3218
- const info = await (0, import_promises11.stat)(target);
3701
+ const info = await (0, import_promises13.stat)(target);
3219
3702
  if (!info.isFile() || info.size > Math.max(options.maxReadBytes ?? 128 * 1024, 2 * 1024 * 1024)) {
3220
3703
  throw new TypeError("file is not a bounded regular source file");
3221
3704
  }
3222
- const source = await (0, import_promises11.readFile)(target);
3705
+ const source = await (0, import_promises13.readFile)(target);
3223
3706
  if (source.includes(0)) throw new TypeError("binary files are not readable through this tool");
3224
3707
  const lines = source.toString("utf8").split("\n");
3225
3708
  const content = lines.slice(startLine - 1, endLine).join("\n");
@@ -3764,8 +4247,8 @@ var runtimeErrorMessage = (value) => value instanceof Error ? value.message : St
3764
4247
  function codeRuntimeAcknowledgementGate(signal) {
3765
4248
  let settle;
3766
4249
  let settled = false;
3767
- const ready = new Promise((resolve7) => {
3768
- settle = resolve7;
4250
+ const ready = new Promise((resolve8) => {
4251
+ settle = resolve8;
3769
4252
  });
3770
4253
  const release = (run) => {
3771
4254
  if (settled) return;
@@ -3874,7 +4357,7 @@ var TheseusRuntimeEngine = class {
3874
4357
  async #start(command, resume) {
3875
4358
  if (this.#active.has(command.sessionId)) throw new TypeError("Code session is already active on this runtime");
3876
4359
  const metadata = codeCommandMetadata(command.payload, resume);
3877
- const { workspace, sourceDigest, localTrustedBaseDigest, requestedLocal } = await materializeCommandWorkspace({
4360
+ const { workspace, sourceDigest, sourceDigests, localTrustedBaseDigest, requestedLocal } = await materializeCommandWorkspace({
3878
4361
  command,
3879
4362
  metadata,
3880
4363
  resume,
@@ -3895,7 +4378,7 @@ var TheseusRuntimeEngine = class {
3895
4378
  maxTokensPerInteraction: metadata.maxTokensPerInteraction,
3896
4379
  baseCommitSha: metadata.baseCommitSha,
3897
4380
  repository: metadata.repository,
3898
- sourceTreeDigest: metadata.sourceTreeDigest,
4381
+ sourceTreeDigest: metadata.sourceTreeDigest ?? sourceDigest,
3899
4382
  trustedBaseDigest: requestedLocal ? localTrustedBaseDigest : await digestStagedWorkspace(workspace.baselineDir, {
3900
4383
  maxFiles: 2e4,
3901
4384
  maxBytes: 512 * 1024 * 1024
@@ -3921,7 +4404,11 @@ var TheseusRuntimeEngine = class {
3921
4404
  await this.#failure(command, active, detail);
3922
4405
  return null;
3923
4406
  });
3924
- return { status: "running", message: resume ? "Theseus resumed from a portable checkpoint" : "Theseus started" };
4407
+ return {
4408
+ status: "running",
4409
+ message: resume ? "Theseus resumed from a portable checkpoint" : "Theseus started",
4410
+ ...sourceDigests ? { sourceDigests } : {}
4411
+ };
3925
4412
  }
3926
4413
  /**
3927
4414
  * Pursue a goal: attempt, judge with the clean verifier, re-prompt from what
@@ -4370,12 +4857,12 @@ function chooseStrategy(signals = {}) {
4370
4857
  var feedbackIsActionable = actionable;
4371
4858
 
4372
4859
  // src/code-recipe-dependencies.ts
4373
- var import_promises12 = require("fs/promises");
4374
- var import_node_path11 = require("path");
4860
+ var import_promises14 = require("fs/promises");
4861
+ var import_node_path13 = require("path");
4375
4862
  var RESERVED_MOUNTS = /* @__PURE__ */ new Set(["node_modules", "dist", "coverage"]);
4376
4863
  function withRecipeDependencies(executor, dependencies) {
4377
4864
  const mountAs = dependencies.mountAs ?? "node_modules";
4378
- if (!(0, import_node_path11.isAbsolute)(dependencies.source)) {
4865
+ if (!(0, import_node_path13.isAbsolute)(dependencies.source)) {
4379
4866
  throw new TypeError("recipe dependency source must be an absolute path");
4380
4867
  }
4381
4868
  if (!RESERVED_MOUNTS.has(mountAs)) {
@@ -4383,24 +4870,24 @@ function withRecipeDependencies(executor, dependencies) {
4383
4870
  }
4384
4871
  return {
4385
4872
  run: async (input) => {
4386
- const target = (0, import_node_path11.join)(input.workspaceDir, mountAs);
4873
+ const target = (0, import_node_path13.join)(input.workspaceDir, mountAs);
4387
4874
  let linked = false;
4388
4875
  try {
4389
- const existing = await (0, import_promises12.lstat)(target).catch(() => null);
4876
+ const existing = await (0, import_promises14.lstat)(target).catch(() => null);
4390
4877
  if (!existing) {
4391
- await (0, import_promises12.symlink)(dependencies.source, target, "dir");
4878
+ await (0, import_promises14.symlink)(dependencies.source, target, "dir");
4392
4879
  linked = true;
4393
4880
  }
4394
4881
  return await executor.run(input);
4395
4882
  } finally {
4396
- if (linked) await (0, import_promises12.rm)(target, { force: true, recursive: false }).catch(() => void 0);
4883
+ if (linked) await (0, import_promises14.rm)(target, { force: true, recursive: false }).catch(() => void 0);
4397
4884
  }
4398
4885
  }
4399
4886
  };
4400
4887
  }
4401
4888
  async function installedDependencies(repoRoot) {
4402
- const source = (0, import_node_path11.join)(repoRoot, "node_modules");
4403
- const info = await (0, import_promises12.lstat)(source).catch(() => null);
4889
+ const source = (0, import_node_path13.join)(repoRoot, "node_modules");
4890
+ const info = await (0, import_promises14.lstat)(source).catch(() => null);
4404
4891
  return info?.isDirectory() ? { source } : null;
4405
4892
  }
4406
4893
  // Annotate the CommonJS export names for ESM import in node:
@@ -4441,6 +4928,7 @@ async function installedDependencies(repoRoot) {
4441
4928
  installedDependencies,
4442
4929
  integrateSubGoals,
4443
4930
  isCheckpointEffectCompleted,
4931
+ materializeCodeRuntimeArchive,
4444
4932
  materializeCodeRuntimeSource,
4445
4933
  materializeCommandWorkspace,
4446
4934
  materializeGitTree,