@odla-ai/harness 0.9.1 → 0.9.3
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/{chunk-HDIR4MM5.js → chunk-5LRYJKUI.js} +3 -3
- package/dist/{chunk-4EPJJMFG.js → chunk-AEAISFY3.js} +157 -217
- package/dist/chunk-AEAISFY3.js.map +1 -0
- package/dist/chunk-FAN2R3GW.js +166 -0
- package/dist/chunk-FAN2R3GW.js.map +1 -0
- package/dist/{chunk-CIKYMC67.js → chunk-OZBJNTML.js} +4 -4
- package/dist/{chunk-I43KTCJ2.js → chunk-U324RQ4N.js} +1 -1
- package/dist/{chunk-I43KTCJ2.js.map → chunk-U324RQ4N.js.map} +1 -1
- package/dist/{chunk-VGNIDRKM.js → chunk-VDY5V7ZG.js} +2 -2
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +4 -4
- package/dist/code-runtime-cli.cjs +258 -163
- package/dist/code-runtime-cli.cjs.map +1 -1
- package/dist/code-runtime-cli.js +6 -5
- package/dist/code-runtime-cli.js.map +1 -1
- package/dist/index.cjs +172 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +24 -3
- package/dist/index.d.ts +24 -3
- package/dist/index.js +11 -3
- package/dist/index.js.map +1 -1
- package/dist/node.cjs +261 -162
- package/dist/node.cjs.map +1 -1
- package/dist/node.d.cts +39 -6
- package/dist/node.d.ts +39 -6
- package/dist/node.js +10 -5
- package/dist/node.js.map +1 -1
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.d.cts +1 -1
- package/dist/testing.d.ts +1 -1
- package/dist/testing.js +1 -1
- package/dist/{types-BazqxWK8.d.cts → types-_8y8vBDI.d.cts} +5 -1
- package/dist/{types-BazqxWK8.d.ts → types-_8y8vBDI.d.ts} +5 -1
- package/package.json +1 -1
- package/dist/chunk-4EPJJMFG.js.map +0 -1
- /package/dist/{chunk-HDIR4MM5.js.map → chunk-5LRYJKUI.js.map} +0 -0
- /package/dist/{chunk-CIKYMC67.js.map → chunk-OZBJNTML.js.map} +0 -0
- /package/dist/{chunk-VGNIDRKM.js.map → chunk-VDY5V7ZG.js.map} +0 -0
|
@@ -1,13 +1,16 @@
|
|
|
1
|
+
import {
|
|
2
|
+
observedBroker
|
|
3
|
+
} from "./chunk-FAN2R3GW.js";
|
|
1
4
|
import {
|
|
2
5
|
SKIP_WORKSPACE_DIRS,
|
|
3
6
|
assertPinnedImage,
|
|
4
7
|
stageWorkspace,
|
|
5
8
|
stageWorkspacePair,
|
|
6
9
|
verifyContainerEngineBoundary
|
|
7
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-5LRYJKUI.js";
|
|
8
11
|
import {
|
|
9
12
|
HARNESS_PROTOCOL_VERSION
|
|
10
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-U324RQ4N.js";
|
|
11
14
|
|
|
12
15
|
// src/workspace-digest.ts
|
|
13
16
|
import { createHash } from "crypto";
|
|
@@ -344,7 +347,7 @@ async function parseSource(value) {
|
|
|
344
347
|
}
|
|
345
348
|
function parseReview(value) {
|
|
346
349
|
const review = record(record(value)?.review);
|
|
347
|
-
if (!review || !["approved", "rejected"].includes(String(review.verdict)) || typeof review.reviewDigest !== "string" || !/^sha256:[0-9a-f]{64}$/.test(review.reviewDigest) || typeof review.provider !== "string" || !review.provider || typeof review.model !== "string" || !review.model || !Number.isSafeInteger(review.policyVersion) || Number(review.policyVersion) < 1) throw invalid("review");
|
|
350
|
+
if (!review || !["approved", "rejected"].includes(String(review.verdict)) || typeof review.reviewDigest !== "string" || !/^sha256:[0-9a-f]{64}$/.test(review.reviewDigest) || typeof review.provider !== "string" || !review.provider || typeof review.model !== "string" || !review.model || !Number.isSafeInteger(review.policyVersion) || Number(review.policyVersion) < 1 || !Number.isSafeInteger(review.score) || Number(review.score) < 0 || Number(review.score) > 100 || typeof review.summary !== "string" || !Array.isArray(review.findings) || review.findings.length > 12) throw invalid("review");
|
|
348
351
|
return review;
|
|
349
352
|
}
|
|
350
353
|
function parseCandidate(value) {
|
|
@@ -451,10 +454,41 @@ var SECRET = /^(?:\.env(?:\..+)?|\.dev\.vars|credentials(?:\..+)?\.json|dev-toke
|
|
|
451
454
|
var PATH = /^[A-Za-z0-9_@+.,-]+(?:\/[A-Za-z0-9_@+.,-]+)*$/;
|
|
452
455
|
var FORBIDDEN = /^(?:GIT binary patch|Binary files |rename (?:from|to) |copy (?:from|to) |similarity index |old mode |new mode |deleted file mode 160000|new file mode 160000)/m;
|
|
453
456
|
function stripPatchEnvelope(patch2) {
|
|
454
|
-
if (!/^\*\*\* (?:Begin|End) Patch\s*$/m.test(patch2)) return patch2;
|
|
457
|
+
if (!/^\*\*\* (?:Begin|End) Patch\s*$/m.test(patch2)) return applyPatchDialectToDiff(patch2);
|
|
455
458
|
const kept = patch2.split("\n").filter((line) => !/^\*\*\* (?:Begin|End) Patch\s*$/.test(line));
|
|
456
459
|
const stripped = kept.join("\n");
|
|
457
|
-
|
|
460
|
+
if (/^diff --git /m.test(stripped)) return stripped;
|
|
461
|
+
const translated = applyPatchDialectToDiff(stripped);
|
|
462
|
+
return translated === stripped ? patch2 : translated;
|
|
463
|
+
}
|
|
464
|
+
function applyPatchDialectToDiff(patch2) {
|
|
465
|
+
if (!/^\*\*\* (?:Update|Add|Delete) File: /m.test(patch2)) return patch2;
|
|
466
|
+
const out = [];
|
|
467
|
+
let open = false;
|
|
468
|
+
for (const line of patch2.split("\n")) {
|
|
469
|
+
const file = /^\*\*\* (Update|Add|Delete) File: (.+?)\s*$/.exec(line);
|
|
470
|
+
if (file) {
|
|
471
|
+
const [, verb, raw] = file;
|
|
472
|
+
const path = raw.trim();
|
|
473
|
+
if (!PATH.test(path)) return patch2;
|
|
474
|
+
out.push(`diff --git a/${path} b/${path}`);
|
|
475
|
+
if (verb === "Add") out.push("new file mode 100644", "--- /dev/null", `+++ b/${path}`);
|
|
476
|
+
else if (verb === "Delete") out.push(`--- a/${path}`, "+++ /dev/null");
|
|
477
|
+
else out.push(`--- a/${path}`, `+++ b/${path}`);
|
|
478
|
+
open = true;
|
|
479
|
+
continue;
|
|
480
|
+
}
|
|
481
|
+
if (/^\*\*\* /.test(line)) continue;
|
|
482
|
+
if (!open) continue;
|
|
483
|
+
if (/^@@/.test(line)) {
|
|
484
|
+
out.push("@@ -1 +1 @@");
|
|
485
|
+
continue;
|
|
486
|
+
}
|
|
487
|
+
out.push(line);
|
|
488
|
+
}
|
|
489
|
+
if (!open) return patch2;
|
|
490
|
+
return `${out.join("\n").replace(/\n+$/, "")}
|
|
491
|
+
`;
|
|
458
492
|
}
|
|
459
493
|
function validateCodePatch(rawPatch, maxBytes) {
|
|
460
494
|
const patch2 = stripPatchEnvelope(rawPatch);
|
|
@@ -470,7 +504,7 @@ function validateCodePatch(rawPatch, maxBytes) {
|
|
|
470
504
|
if (FORBIDDEN.test(patch2) || /(?:old|new)(?: file)? mode 120000/.test(patch2)) {
|
|
471
505
|
throw new TypeError("patch uses a forbidden binary, link, mode, rename, or copy operation");
|
|
472
506
|
}
|
|
473
|
-
const
|
|
507
|
+
const paths = [];
|
|
474
508
|
const lines = patch2.split("\n");
|
|
475
509
|
for (let index = 0; index < lines.length; index += 1) {
|
|
476
510
|
const line = lines[index];
|
|
@@ -486,10 +520,10 @@ function validateCodePatch(rawPatch, maxBytes) {
|
|
|
486
520
|
if (!validHeaderPath(oldPath, path, "a") || !validHeaderPath(newPath, path, "b")) {
|
|
487
521
|
throw new TypeError("patch file headers do not match the declared path");
|
|
488
522
|
}
|
|
489
|
-
|
|
523
|
+
paths.push(path);
|
|
490
524
|
}
|
|
491
|
-
if (!
|
|
492
|
-
return
|
|
525
|
+
if (!paths.length || new Set(paths).size !== paths.length) throw new TypeError("patch has no diffs or repeats a path");
|
|
526
|
+
return paths;
|
|
493
527
|
}
|
|
494
528
|
function validHeaderPath(value, path, prefix) {
|
|
495
529
|
return value === "/dev/null" || value === `${prefix}/${path}`;
|
|
@@ -507,18 +541,21 @@ function resolveCodePath(workspaceDir, path) {
|
|
|
507
541
|
if (target !== root && !target.startsWith(`${root}${sep}`)) throw new TypeError("path escapes the staged workspace");
|
|
508
542
|
return target;
|
|
509
543
|
}
|
|
544
|
+
function hasContextFreeHunk(patch2) {
|
|
545
|
+
const bodies = patch2.split(/^@@.*$/m).slice(1);
|
|
546
|
+
return bodies.some((body) => !body.split("\n").some((line) => line.startsWith(" ") && line.trim().length > 0));
|
|
547
|
+
}
|
|
510
548
|
function describePatchFailure(patch2, detail) {
|
|
511
549
|
const hunks = patch2.split("\n").filter((line) => line.startsWith("@@"));
|
|
512
|
-
const
|
|
513
|
-
const contextless = bodies.some((body) => !body.split("\n").some((line) => line.startsWith(" ") && line.trim().length > 0));
|
|
514
|
-
const hint = hunks.length > 0 && contextless ? " A hunk has no context lines; include at least one unchanged line above or below each change." : "";
|
|
550
|
+
const hint = hunks.length > 0 && hasContextFreeHunk(patch2) ? " A hunk has no context lines; include at least one unchanged line above or below each change." : "";
|
|
515
551
|
return `patch did not apply: ${detail}${hint}`;
|
|
516
552
|
}
|
|
517
|
-
async function applyCodePatch(workspaceDir, rawPatch,
|
|
553
|
+
async function applyCodePatch(workspaceDir, rawPatch, paths) {
|
|
518
554
|
const patch2 = stripPatchEnvelope(rawPatch);
|
|
519
|
-
|
|
520
|
-
await gitApply(workspaceDir, patch2,
|
|
521
|
-
|
|
555
|
+
const zero = hasContextFreeHunk(patch2);
|
|
556
|
+
await gitApply(workspaceDir, patch2, true, zero);
|
|
557
|
+
await gitApply(workspaceDir, patch2, false, zero);
|
|
558
|
+
for (const path of paths) {
|
|
522
559
|
try {
|
|
523
560
|
const info = await lstat(resolveCodePath(workspaceDir, path));
|
|
524
561
|
if (info.isSymbolicLink() || !info.isFile() && !info.isDirectory()) {
|
|
@@ -529,9 +566,16 @@ async function applyCodePatch(workspaceDir, rawPatch, paths2) {
|
|
|
529
566
|
}
|
|
530
567
|
}
|
|
531
568
|
}
|
|
532
|
-
function gitApply(cwd, patch2, check) {
|
|
569
|
+
function gitApply(cwd, patch2, check, unidiffZero = false) {
|
|
533
570
|
return new Promise((accept, reject) => {
|
|
534
|
-
const args = [
|
|
571
|
+
const args = [
|
|
572
|
+
"apply",
|
|
573
|
+
"--recount",
|
|
574
|
+
...unidiffZero ? ["--unidiff-zero"] : [],
|
|
575
|
+
"--whitespace=nowarn",
|
|
576
|
+
...check ? ["--check"] : [],
|
|
577
|
+
"-"
|
|
578
|
+
];
|
|
535
579
|
const child = spawn("git", args, {
|
|
536
580
|
cwd,
|
|
537
581
|
shell: false,
|
|
@@ -540,8 +584,8 @@ function gitApply(cwd, patch2, check) {
|
|
|
540
584
|
});
|
|
541
585
|
let stderr = "";
|
|
542
586
|
child.stderr.setEncoding("utf8");
|
|
543
|
-
child.stderr.on("data", (
|
|
544
|
-
if (stderr.length < 4e3) stderr +=
|
|
587
|
+
child.stderr.on("data", (text) => {
|
|
588
|
+
if (stderr.length < 4e3) stderr += text.slice(0, 4e3);
|
|
545
589
|
});
|
|
546
590
|
child.once("error", reject);
|
|
547
591
|
child.once("exit", (code) => code === 0 ? accept() : reject(new TypeError(describePatchFailure(patch2, stderr.trim().slice(0, 500)))));
|
|
@@ -571,8 +615,8 @@ async function restoreCodeWorkspaceCheckpoint(input) {
|
|
|
571
615
|
const workspace = await stageWorkspace(input.trustedBaseDir, input.stage);
|
|
572
616
|
try {
|
|
573
617
|
if (checkpoint.patch) {
|
|
574
|
-
const
|
|
575
|
-
await applyCodePatch(workspace.workspaceDir, checkpoint.patch,
|
|
618
|
+
const paths = validateCodePatch(checkpoint.patch, 256 * 1024);
|
|
619
|
+
await applyCodePatch(workspace.workspaceDir, checkpoint.patch, paths);
|
|
576
620
|
}
|
|
577
621
|
return { workspace, checkpoint };
|
|
578
622
|
} catch (error) {
|
|
@@ -741,8 +785,8 @@ async function verifyCodeCandidate(input) {
|
|
|
741
785
|
try {
|
|
742
786
|
const baseDigest = await digestStagedWorkspace(staged.workspaceDir, limits);
|
|
743
787
|
if (baseDigest !== input.trustedBaseDigest) throw new TypeError("trusted base does not match its registered digest");
|
|
744
|
-
const
|
|
745
|
-
await applyCodePatch(staged.workspaceDir, input.candidatePatch,
|
|
788
|
+
const paths = validateCodePatch(input.candidatePatch, policy.maximumPatchBytes);
|
|
789
|
+
await applyCodePatch(staged.workspaceDir, input.candidatePatch, paths);
|
|
746
790
|
const sourceDigest = await digestStagedWorkspace(staged.workspaceDir, limits);
|
|
747
791
|
const policyDigest = digestPolicy(policy);
|
|
748
792
|
const patchDigest = digestBytes(input.candidatePatch);
|
|
@@ -751,7 +795,7 @@ async function verifyCodeCandidate(input) {
|
|
|
751
795
|
trustedBaseDigest: input.trustedBaseDigest,
|
|
752
796
|
patchDigest
|
|
753
797
|
});
|
|
754
|
-
const changedTests = changedTestPaths(
|
|
798
|
+
const changedTests = changedTestPaths(paths, policy);
|
|
755
799
|
if (changedTests.length > policy.maximumChangedTests) throw new TypeError("candidate changes too many test files");
|
|
756
800
|
const recipes = [];
|
|
757
801
|
const logs = [];
|
|
@@ -818,8 +862,8 @@ function validate(input) {
|
|
|
818
862
|
}
|
|
819
863
|
return result;
|
|
820
864
|
}
|
|
821
|
-
function changedTestPaths(
|
|
822
|
-
return
|
|
865
|
+
function changedTestPaths(paths, policy) {
|
|
866
|
+
return paths.filter((path) => policy.testPathSuffixes.some((suffix) => path.endsWith(suffix)) || policy.testPathPrefixes.some((prefix) => path.startsWith(prefix) || path.includes(`/${prefix}`))).sort();
|
|
823
867
|
}
|
|
824
868
|
function recipeReceipt(recipe2, result, artifacts) {
|
|
825
869
|
const status = result.timedOut ? "timed_out" : result.outputLimitExceeded ? "output_limited" : result.exitCode === 0 && artifacts.every((item) => item.status === "verified") ? "passed" : "failed";
|
|
@@ -943,9 +987,9 @@ async function prepareRuntimeCheckpoint(input) {
|
|
|
943
987
|
if (evidence.receipt.outcome === "passed") {
|
|
944
988
|
verification = evidence.receipt;
|
|
945
989
|
review = await input.review(patch2, verification);
|
|
946
|
-
note = review
|
|
990
|
+
note = describeReview(review);
|
|
947
991
|
} else {
|
|
948
|
-
note =
|
|
992
|
+
note = describeGateFailure(evidence);
|
|
949
993
|
}
|
|
950
994
|
} catch (cause) {
|
|
951
995
|
note = `Candidate verification or review failed closed: ${message(cause)}`;
|
|
@@ -970,6 +1014,23 @@ async function prepareRuntimeCheckpoint(input) {
|
|
|
970
1014
|
});
|
|
971
1015
|
return { checkpoint, verification, review, note };
|
|
972
1016
|
}
|
|
1017
|
+
function describeReview(review) {
|
|
1018
|
+
const findings = review.findings.map((finding) => ` - [${finding.severity}] ${finding.detail}`).join("\n");
|
|
1019
|
+
const head = review.verdict === "approved" ? `Clean verification and independent review passed (score ${review.score}/100).` : `Clean verification passed; independent review REJECTED this candidate (score ${review.score}/100). Address the findings and checkpoint again.`;
|
|
1020
|
+
return [head, review.summary, findings].filter(Boolean).join("\n").slice(0, 4e3);
|
|
1021
|
+
}
|
|
1022
|
+
function describeGateFailure(evidence) {
|
|
1023
|
+
const failed = evidence.receipt.recipes.filter((recipe2) => recipe2.status !== "passed");
|
|
1024
|
+
const detail = failed.map((recipe2) => {
|
|
1025
|
+
const log = evidence.logs.find((entry) => entry.recipeId === recipe2.recipeId);
|
|
1026
|
+
const output = `${log?.stdout ?? ""}
|
|
1027
|
+
${log?.stderr ?? ""}`.trim();
|
|
1028
|
+
return `${recipe2.recipeId}=${recipe2.status}${output ? `
|
|
1029
|
+
${output.slice(0, 1500)}` : ""}`;
|
|
1030
|
+
}).join("\n\n");
|
|
1031
|
+
return `Clean verification failed. Fix this and checkpoint again:
|
|
1032
|
+
${detail}`.slice(0, 4e3);
|
|
1033
|
+
}
|
|
973
1034
|
var message = (value) => (value instanceof Error ? value.message : String(value)).slice(0, 500);
|
|
974
1035
|
|
|
975
1036
|
// src/code-runtime-checkpoint-manager.ts
|
|
@@ -1205,12 +1266,24 @@ async function materializeCommandWorkspace(input) {
|
|
|
1205
1266
|
resume
|
|
1206
1267
|
});
|
|
1207
1268
|
if (command.payload.sourceSet) {
|
|
1208
|
-
|
|
1209
|
-
if (selected.repository !== metadata.repository || selected.commitSha !== metadata.baseCommitSha || selected.treeDigest !== metadata.sourceTreeDigest) {
|
|
1269
|
+
if (prepared.trustedBaseDigest !== metadata.sourceTreeDigest) {
|
|
1210
1270
|
await prepared.workspace.cleanup();
|
|
1211
1271
|
throw new TypeError("Code local source does not match the selected GitHub primary source");
|
|
1212
1272
|
}
|
|
1213
|
-
|
|
1273
|
+
const set = command.payload.sourceSet && typeof command.payload.sourceSet === "object" && !Array.isArray(command.payload.sourceSet) ? command.payload.sourceSet : null;
|
|
1274
|
+
const references = set?.references;
|
|
1275
|
+
if (!Array.isArray(references)) {
|
|
1276
|
+
await prepared.workspace.cleanup();
|
|
1277
|
+
throw new TypeError("Code selected source set is invalid");
|
|
1278
|
+
}
|
|
1279
|
+
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) {
|
|
1282
|
+
await prepared.workspace.cleanup();
|
|
1283
|
+
throw new TypeError("Code local source does not match the selected GitHub primary source");
|
|
1284
|
+
}
|
|
1285
|
+
await attachCodeRuntimeReferences(prepared.workspace, selected.references ?? []);
|
|
1286
|
+
}
|
|
1214
1287
|
}
|
|
1215
1288
|
return {
|
|
1216
1289
|
workspace: prepared.workspace,
|
|
@@ -1626,7 +1699,7 @@ function createWorkspaceFileRegistry(limit = DEFAULT_MAX_FILES, enumerate = regi
|
|
|
1626
1699
|
files(root) {
|
|
1627
1700
|
const existing = cache2.get(root);
|
|
1628
1701
|
if (existing) return existing;
|
|
1629
|
-
const pending = enumerate(root, limit).then((
|
|
1702
|
+
const pending = enumerate(root, limit).then((paths) => Object.freeze(paths));
|
|
1630
1703
|
cache2.set(root, pending);
|
|
1631
1704
|
void pending.catch(() => {
|
|
1632
1705
|
if (cache2.get(root) === pending) cache2.delete(root);
|
|
@@ -1639,7 +1712,7 @@ function createWorkspaceFileRegistry(limit = DEFAULT_MAX_FILES, enumerate = regi
|
|
|
1639
1712
|
};
|
|
1640
1713
|
}
|
|
1641
1714
|
async function registeredFiles(root, limit = DEFAULT_MAX_FILES) {
|
|
1642
|
-
const
|
|
1715
|
+
const paths = [];
|
|
1643
1716
|
const walk = async (directory) => {
|
|
1644
1717
|
for (const entry of await readdir2(directory, { withFileTypes: true })) {
|
|
1645
1718
|
if (SKIP_WORKSPACE_DIRS.has(entry.name)) continue;
|
|
@@ -1653,26 +1726,26 @@ async function registeredFiles(root, limit = DEFAULT_MAX_FILES) {
|
|
|
1653
1726
|
} catch {
|
|
1654
1727
|
continue;
|
|
1655
1728
|
}
|
|
1656
|
-
|
|
1657
|
-
if (
|
|
1729
|
+
paths.push(path);
|
|
1730
|
+
if (paths.length > limit) throw new TypeError("workspace file registry exceeds its bound");
|
|
1658
1731
|
}
|
|
1659
1732
|
}
|
|
1660
1733
|
};
|
|
1661
1734
|
await walk(resolve4(root));
|
|
1662
|
-
return
|
|
1735
|
+
return paths.sort();
|
|
1663
1736
|
}
|
|
1664
|
-
function listWorkspace(
|
|
1737
|
+
function listWorkspace(paths, options = {}) {
|
|
1665
1738
|
const max = options.maxEntries ?? 1e3;
|
|
1666
1739
|
const prefix = options.prefix?.replace(/\/+$/, "");
|
|
1667
|
-
const scoped = prefix ?
|
|
1740
|
+
const scoped = prefix ? paths.filter((path) => path === prefix || path.startsWith(`${prefix}/`)) : [...paths];
|
|
1668
1741
|
return scoped.slice(0, max);
|
|
1669
1742
|
}
|
|
1670
|
-
async function searchWorkspace(root,
|
|
1743
|
+
async function searchWorkspace(root, paths, options) {
|
|
1671
1744
|
options.signal?.throwIfAborted();
|
|
1672
1745
|
if (!options.query) throw new TypeError("search query must be a non-empty string");
|
|
1673
1746
|
const maxResults = options.maxResults ?? DEFAULT_MAX_RESULTS;
|
|
1674
1747
|
const maxFileBytes = options.maxFileBytes ?? DEFAULT_MAX_FILE_BYTES;
|
|
1675
|
-
const scoped = listWorkspace(
|
|
1748
|
+
const scoped = listWorkspace(paths, { ...options.prefix ? { prefix: options.prefix } : {}, maxEntries: paths.length });
|
|
1676
1749
|
if (scoped.length === 0) return [];
|
|
1677
1750
|
try {
|
|
1678
1751
|
return await nativeSearch(root, scoped, { ...options, maxResults, maxFileBytes });
|
|
@@ -1682,11 +1755,11 @@ async function searchWorkspace(root, paths2, options) {
|
|
|
1682
1755
|
}
|
|
1683
1756
|
}
|
|
1684
1757
|
var MAX_NATIVE_ARG_BYTES = 96 * 1024;
|
|
1685
|
-
async function nativeSearch(root,
|
|
1758
|
+
async function nativeSearch(root, paths, options) {
|
|
1686
1759
|
const batches = [];
|
|
1687
1760
|
let batch = [];
|
|
1688
1761
|
let bytes = 0;
|
|
1689
|
-
for (const path of
|
|
1762
|
+
for (const path of paths) {
|
|
1690
1763
|
const size = Buffer.byteLength(path) + 1;
|
|
1691
1764
|
if (batch.length > 0 && bytes + size > MAX_NATIVE_ARG_BYTES) {
|
|
1692
1765
|
batches.push(batch);
|
|
@@ -1705,7 +1778,7 @@ async function nativeSearch(root, paths2, options) {
|
|
|
1705
1778
|
}
|
|
1706
1779
|
return matches;
|
|
1707
1780
|
}
|
|
1708
|
-
function nativeSearchBatch(root,
|
|
1781
|
+
function nativeSearchBatch(root, paths, options, remaining) {
|
|
1709
1782
|
return new Promise((resolveMatches, reject) => {
|
|
1710
1783
|
const args = [
|
|
1711
1784
|
"--fixed-strings",
|
|
@@ -1718,7 +1791,7 @@ function nativeSearchBatch(root, paths2, options, remaining) {
|
|
|
1718
1791
|
options.caseSensitive === false ? "--ignore-case" : "--case-sensitive",
|
|
1719
1792
|
"--",
|
|
1720
1793
|
options.query,
|
|
1721
|
-
...
|
|
1794
|
+
...paths
|
|
1722
1795
|
];
|
|
1723
1796
|
const child = spawn3("rg", args, {
|
|
1724
1797
|
cwd: root,
|
|
@@ -1916,16 +1989,16 @@ function createCodePolicyGate(options) {
|
|
|
1916
1989
|
}
|
|
1917
1990
|
};
|
|
1918
1991
|
}
|
|
1919
|
-
function directoryPrefixes(
|
|
1992
|
+
function directoryPrefixes(paths) {
|
|
1920
1993
|
const prefixes = /* @__PURE__ */ new Set(["."]);
|
|
1921
|
-
for (const path of
|
|
1994
|
+
for (const path of paths) {
|
|
1922
1995
|
const parts = path.split("/");
|
|
1923
1996
|
for (let index = 1; index < parts.length; index += 1) prefixes.add(parts.slice(0, index).join("/"));
|
|
1924
1997
|
}
|
|
1925
1998
|
return [...prefixes].sort();
|
|
1926
1999
|
}
|
|
1927
|
-
async function safePrefix(base,
|
|
1928
|
-
const prefixes = directoryPrefixes(
|
|
2000
|
+
async function safePrefix(base, paths, prefix) {
|
|
2001
|
+
const prefixes = directoryPrefixes(paths);
|
|
1929
2002
|
const conversions = await conversionRegistry(
|
|
1930
2003
|
[await registeredPolicy("code.prefix.v1", "code.prefixes.v1", prefixes)],
|
|
1931
2004
|
{ "code.prefixes.v1": prefixes }
|
|
@@ -2035,8 +2108,14 @@ function optionalInteger(value) {
|
|
|
2035
2108
|
if (!Number.isSafeInteger(value) || value < 1) throw new TypeError("line bounds must be positive integers");
|
|
2036
2109
|
return value;
|
|
2037
2110
|
}
|
|
2111
|
+
var DEFAULT_FAILURE_REASON = {
|
|
2112
|
+
"tool denied by CaMeL policy": "tool denied by CaMeL policy",
|
|
2113
|
+
"review sessions are read-only": "review session is read-only; workspace changes are not permitted"
|
|
2114
|
+
};
|
|
2038
2115
|
function response(request, ok, content, details) {
|
|
2039
|
-
return { requestId: request.requestId, ok, content, ...details ? { details } : {} };
|
|
2116
|
+
if (ok) return { requestId: request.requestId, ok, content, ...details ? { details } : {} };
|
|
2117
|
+
const failureReason = typeof details?.failureReason === "string" && details.failureReason || DEFAULT_FAILURE_REASON[content] || content || "tool request failed; inspect the tool input and workspace state";
|
|
2118
|
+
return { requestId: request.requestId, ok, content, details: { ...details, failureReason } };
|
|
2040
2119
|
}
|
|
2041
2120
|
|
|
2042
2121
|
// src/code-tool-reads.ts
|
|
@@ -2055,7 +2134,7 @@ import {
|
|
|
2055
2134
|
} from "@odla-ai/graph";
|
|
2056
2135
|
import { buildCodeGraph, FILE, IMPORTS, PACKAGE, READS, SYMBOL, WRITES } from "@odla-ai/graph/code";
|
|
2057
2136
|
var cache = /* @__PURE__ */ new Map();
|
|
2058
|
-
function workspaceGraphs(workspaceDir,
|
|
2137
|
+
function workspaceGraphs(workspaceDir, paths) {
|
|
2059
2138
|
const existing = cache.get(workspaceDir);
|
|
2060
2139
|
if (existing) return existing;
|
|
2061
2140
|
const read2 = (path) => readFile3(join3(workspaceDir, path), "utf8");
|
|
@@ -2063,7 +2142,7 @@ function workspaceGraphs(workspaceDir, paths2) {
|
|
|
2063
2142
|
// No knownTables: a staged workspace may not carry migrations, and a filter
|
|
2064
2143
|
// that silently drops every table is worse than an unfiltered one. Callers
|
|
2065
2144
|
// with ground truth should build the graph themselves.
|
|
2066
|
-
graph: await buildCodeGraph({ paths
|
|
2145
|
+
graph: await buildCodeGraph({ paths, read: read2, data: { ignore: (path) => path.includes(".generated.") } })
|
|
2067
2146
|
}))();
|
|
2068
2147
|
cache.set(workspaceDir, built);
|
|
2069
2148
|
return built;
|
|
@@ -2125,11 +2204,11 @@ async function read(context, request, options, policy, registry) {
|
|
|
2125
2204
|
if (endLine < startLine || endLine - startLine + 1 > (options.maxReadLines ?? 2e3)) {
|
|
2126
2205
|
throw new TypeError("requested line range exceeds its bound");
|
|
2127
2206
|
}
|
|
2128
|
-
const
|
|
2129
|
-
if (!
|
|
2207
|
+
const paths = await registry.files(context.workspaceDir);
|
|
2208
|
+
if (!paths.includes(path)) {
|
|
2130
2209
|
throw new TypeError(`no such file in the staged workspace: "${path}". Use sandbox.overview, sandbox.where_is or sandbox.search to find the correct path.`);
|
|
2131
2210
|
}
|
|
2132
|
-
const allowed = await policy.read(policyContext(context, request, options, { paths
|
|
2211
|
+
const allowed = await policy.read(policyContext(context, request, options, { paths, path, startLine, endLine }));
|
|
2133
2212
|
if (!allowed) return response(request, false, "tool denied by CaMeL policy");
|
|
2134
2213
|
const target = resolveCodePath(context.workspaceDir, path);
|
|
2135
2214
|
const info = await stat(target);
|
|
@@ -2151,16 +2230,16 @@ async function list(context, request, options, policy, registry) {
|
|
|
2151
2230
|
const prefix = typeof raw === "string" && raw.length > 0 ? raw : void 0;
|
|
2152
2231
|
const maxEntries = optionalInteger(request.input.maxEntries) ?? 1e3;
|
|
2153
2232
|
if (maxEntries > 5e3) throw new TypeError("maxEntries exceeds its bound");
|
|
2154
|
-
const
|
|
2155
|
-
const allowed = await policy.list(policyContext(context, request, options, { paths
|
|
2233
|
+
const paths = await registry.files(context.workspaceDir);
|
|
2234
|
+
const allowed = await policy.list(policyContext(context, request, options, { paths, ...prefix ? { prefix } : {} }));
|
|
2156
2235
|
if (!allowed) return response(request, false, "tool denied by CaMeL policy");
|
|
2157
|
-
const entries = listWorkspace(
|
|
2236
|
+
const entries = listWorkspace(paths, { ...prefix ? { prefix } : {}, maxEntries });
|
|
2158
2237
|
if (!entries.length) {
|
|
2159
2238
|
return response(request, true, prefix ? `No files under "${prefix}".` : "Workspace is empty.", { count: 0 });
|
|
2160
2239
|
}
|
|
2161
|
-
const truncated = entries.length <
|
|
2162
|
-
const hint = !prefix &&
|
|
2163
|
-
\u2026 ${
|
|
2240
|
+
const truncated = entries.length < paths.length && entries.length === maxEntries;
|
|
2241
|
+
const hint = !prefix && paths.length > 500 ? `
|
|
2242
|
+
\u2026 ${paths.length} files total. sandbox.overview is far cheaper for orientation; use a prefix here once you know the area.` : "";
|
|
2164
2243
|
return response(
|
|
2165
2244
|
request,
|
|
2166
2245
|
true,
|
|
@@ -2178,10 +2257,10 @@ async function search(context, request, options, policy, registry) {
|
|
|
2178
2257
|
const maxResults = optionalInteger(request.input.maxResults) ?? 100;
|
|
2179
2258
|
if (maxResults > 500) throw new TypeError("maxResults exceeds its bound");
|
|
2180
2259
|
const caseSensitive = request.input.caseSensitive === void 0 ? true : request.input.caseSensitive === true;
|
|
2181
|
-
const
|
|
2182
|
-
const allowed = await policy.search(policyContext(context, request, options, { paths
|
|
2260
|
+
const paths = await registry.files(context.workspaceDir);
|
|
2261
|
+
const allowed = await policy.search(policyContext(context, request, options, { paths, query, ...prefix ? { prefix } : {} }));
|
|
2183
2262
|
if (!allowed) return response(request, false, "tool denied by CaMeL policy");
|
|
2184
|
-
const matches = await searchWorkspace(context.workspaceDir,
|
|
2263
|
+
const matches = await searchWorkspace(context.workspaceDir, paths, {
|
|
2185
2264
|
query,
|
|
2186
2265
|
maxResults,
|
|
2187
2266
|
caseSensitive,
|
|
@@ -2203,8 +2282,8 @@ async function graphQuery(context, request, options, policy, registry) {
|
|
|
2203
2282
|
selector: query
|
|
2204
2283
|
}));
|
|
2205
2284
|
if (!allowed) return response(request, false, "tool denied by CaMeL policy");
|
|
2206
|
-
const
|
|
2207
|
-
const graphs = await workspaceGraphs(context.workspaceDir,
|
|
2285
|
+
const paths = await registry.files(context.workspaceDir);
|
|
2286
|
+
const graphs = await workspaceGraphs(context.workspaceDir, paths);
|
|
2208
2287
|
if (request.tool === "sandbox.overview") {
|
|
2209
2288
|
return response(request, true, renderOverview(graphs, query || void 0));
|
|
2210
2289
|
}
|
|
@@ -2268,16 +2347,16 @@ function toolFailureMessage(reason) {
|
|
|
2268
2347
|
async function patch(context, request, options, policy, registry) {
|
|
2269
2348
|
exactKeys(request.input, ["patch"]);
|
|
2270
2349
|
const value = stringField(request.input, "patch");
|
|
2271
|
-
const
|
|
2272
|
-
if (
|
|
2350
|
+
const paths = validateCodePatch(value, options.maxPatchBytes ?? 256 * 1024);
|
|
2351
|
+
if (paths.some((path) => options.readOnlyPrefixes?.some((prefix) => path === prefix || path.startsWith(`${prefix}/`)))) {
|
|
2273
2352
|
throw new TypeError("patch targets a read-only reference source");
|
|
2274
2353
|
}
|
|
2275
2354
|
const allowed = await policy.patch(policyContext(context, request, options, { patch: value }));
|
|
2276
2355
|
if (!allowed) return response(request, false, "tool denied by CaMeL policy");
|
|
2277
|
-
await applyCodePatch(context.workspaceDir, value,
|
|
2356
|
+
await applyCodePatch(context.workspaceDir, value, paths);
|
|
2278
2357
|
registry.invalidate(context.workspaceDir);
|
|
2279
2358
|
forgetWorkspaceGraphs(context.workspaceDir);
|
|
2280
|
-
return response(request, true, `Applied patch to ${
|
|
2359
|
+
return response(request, true, `Applied patch to ${paths.length} file(s).`, { paths });
|
|
2281
2360
|
}
|
|
2282
2361
|
async function recipe(context, request, options, recipes, policy) {
|
|
2283
2362
|
exactKeys(request.input, ["recipeId"]);
|
|
@@ -2668,122 +2747,6 @@ async function appendCodeRuntimeEvent(control, command, event, refs) {
|
|
|
2668
2747
|
var digestRuntimeValue = (value) => `sha256:${createHash3("sha256").update(value).digest("hex")}`;
|
|
2669
2748
|
var runtimeErrorMessage = (value) => value instanceof Error ? value.message : String(value);
|
|
2670
2749
|
|
|
2671
|
-
// src/code-tool-presentation.ts
|
|
2672
|
-
var text = (value, maximum) => {
|
|
2673
|
-
if (typeof value !== "string") return void 0;
|
|
2674
|
-
const bounded = value.replace(/[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f]/g, " ").trim();
|
|
2675
|
-
return bounded ? bounded.slice(0, maximum) : void 0;
|
|
2676
|
-
};
|
|
2677
|
-
var integer2 = (value) => Number.isSafeInteger(value) && Number(value) >= 0 ? Number(value) : void 0;
|
|
2678
|
-
var record3 = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
2679
|
-
var excerpt = (value, tail = false) => {
|
|
2680
|
-
if (typeof value !== "string") return void 0;
|
|
2681
|
-
const safe = value.replace(/[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f]/g, " ");
|
|
2682
|
-
const source = (tail ? safe.slice(-1e4) : safe.slice(0, 1e4)).trim();
|
|
2683
|
-
if (!source) return void 0;
|
|
2684
|
-
const lines = source.split("\n").filter((line) => line.trim()).map((line) => line.slice(0, 240));
|
|
2685
|
-
const selected = tail ? lines.slice(-10) : lines.slice(0, 10);
|
|
2686
|
-
return text(selected.join("\n"), 2400);
|
|
2687
|
-
};
|
|
2688
|
-
var paths = (value) => {
|
|
2689
|
-
if (!Array.isArray(value)) return void 0;
|
|
2690
|
-
const items = value.flatMap((item) => {
|
|
2691
|
-
const path = text(item, 1024);
|
|
2692
|
-
return path ? [path] : [];
|
|
2693
|
-
}).slice(0, 12);
|
|
2694
|
-
return items.length ? items : void 0;
|
|
2695
|
-
};
|
|
2696
|
-
function patchStats(value) {
|
|
2697
|
-
if (typeof value !== "string") return {};
|
|
2698
|
-
let additions = 0;
|
|
2699
|
-
let deletions = 0;
|
|
2700
|
-
for (const line of value.slice(0, 262144).split("\n")) {
|
|
2701
|
-
if (line.startsWith("+++") || line.startsWith("---")) continue;
|
|
2702
|
-
if (line.startsWith("+")) additions += 1;
|
|
2703
|
-
else if (line.startsWith("-")) deletions += 1;
|
|
2704
|
-
}
|
|
2705
|
-
return { ...additions ? { additions } : {}, ...deletions ? { deletions } : {} };
|
|
2706
|
-
}
|
|
2707
|
-
function searchResults(value) {
|
|
2708
|
-
if (typeof value !== "string") return void 0;
|
|
2709
|
-
const results = value.split("\n").flatMap((line) => {
|
|
2710
|
-
const match = /^([^:\n]{1,1024}):(\d+):\s?(.*)$/.exec(line);
|
|
2711
|
-
if (!match) return [];
|
|
2712
|
-
const lineNumber = Number(match[2]);
|
|
2713
|
-
const itemText = text(match[3], 240);
|
|
2714
|
-
if (!Number.isSafeInteger(lineNumber) || lineNumber < 1) return [];
|
|
2715
|
-
return [{ path: match[1], line: lineNumber, ...itemText ? { text: itemText } : {} }];
|
|
2716
|
-
}).slice(0, 5);
|
|
2717
|
-
return results.length ? results : void 0;
|
|
2718
|
-
}
|
|
2719
|
-
function codeToolRequestPresentation(request) {
|
|
2720
|
-
const input = request.input;
|
|
2721
|
-
if (request.tool === "sandbox.read") {
|
|
2722
|
-
const path = text(input.path, 1024);
|
|
2723
|
-
if (!path) return void 0;
|
|
2724
|
-
const startLine = integer2(input.startLine);
|
|
2725
|
-
const endLine = integer2(input.endLine);
|
|
2726
|
-
return { kind: "read", path, ...startLine ? { startLine } : {}, ...endLine ? { endLine } : {} };
|
|
2727
|
-
}
|
|
2728
|
-
if (request.tool === "sandbox.list") {
|
|
2729
|
-
const scope = text(input.prefix, 1024);
|
|
2730
|
-
return { kind: "list", ...scope ? { scope } : {} };
|
|
2731
|
-
}
|
|
2732
|
-
if (request.tool === "sandbox.search" || request.tool === "sandbox.overview" || request.tool === "sandbox.where_is" || request.tool === "sandbox.who_imports" || request.tool === "sandbox.who_touches") {
|
|
2733
|
-
const query = text(input.query, 512);
|
|
2734
|
-
const scope = request.tool === "sandbox.search" ? text(input.prefix, 1024) : void 0;
|
|
2735
|
-
if (request.tool === "sandbox.search" && !query) return void 0;
|
|
2736
|
-
return { kind: "query", ...query ? { query } : {}, ...scope ? { scope } : {} };
|
|
2737
|
-
}
|
|
2738
|
-
if (request.tool === "sandbox.apply_patch") {
|
|
2739
|
-
return { kind: "patch", ...patchStats(input.patch) };
|
|
2740
|
-
}
|
|
2741
|
-
const recipeId = text(input.recipeId, 120);
|
|
2742
|
-
return recipeId ? { kind: "recipe", recipeId } : void 0;
|
|
2743
|
-
}
|
|
2744
|
-
function codeToolResultPresentation(request, response2) {
|
|
2745
|
-
const started = codeToolRequestPresentation(request);
|
|
2746
|
-
if (!started || !response2.ok) return started;
|
|
2747
|
-
const details = record3(response2.details);
|
|
2748
|
-
if (started.kind === "read") {
|
|
2749
|
-
return {
|
|
2750
|
-
...started,
|
|
2751
|
-
...integer2(details?.startLine) ? { startLine: integer2(details?.startLine) } : {},
|
|
2752
|
-
...integer2(details?.endLine) ? { endLine: integer2(details?.endLine) } : {},
|
|
2753
|
-
...excerpt(response2.content) ? { excerpt: excerpt(response2.content) } : {}
|
|
2754
|
-
};
|
|
2755
|
-
}
|
|
2756
|
-
if (started.kind === "list") {
|
|
2757
|
-
const listed = response2.content.split("\n").filter((line) => line && !line.startsWith("\u2026") && !line.startsWith("Workspace ")).map((line) => text(line, 1024)).filter((line) => Boolean(line)).slice(0, 8);
|
|
2758
|
-
return {
|
|
2759
|
-
...started,
|
|
2760
|
-
...integer2(details?.count) !== void 0 ? { count: integer2(details?.count) } : {},
|
|
2761
|
-
...listed.length ? { paths: listed } : {}
|
|
2762
|
-
};
|
|
2763
|
-
}
|
|
2764
|
-
if (started.kind === "query") {
|
|
2765
|
-
const results = request.tool === "sandbox.search" ? searchResults(response2.content) : void 0;
|
|
2766
|
-
const resultExcerpt = request.tool === "sandbox.search" ? void 0 : excerpt(response2.content);
|
|
2767
|
-
return {
|
|
2768
|
-
...started,
|
|
2769
|
-
...integer2(details?.count) !== void 0 ? { count: integer2(details?.count) } : {},
|
|
2770
|
-
...results ? { results } : {},
|
|
2771
|
-
...resultExcerpt ? { excerpt: resultExcerpt } : {}
|
|
2772
|
-
};
|
|
2773
|
-
}
|
|
2774
|
-
if (started.kind === "patch") {
|
|
2775
|
-
return { ...started, ...paths(details?.paths) ? { paths: paths(details?.paths) } : {} };
|
|
2776
|
-
}
|
|
2777
|
-
const output = response2.content.replace(/^Recipe [^\n]*\.?\s*/u, "");
|
|
2778
|
-
return {
|
|
2779
|
-
...started,
|
|
2780
|
-
...integer2(details?.exitCode) !== void 0 ? { exitCode: integer2(details?.exitCode) } : {},
|
|
2781
|
-
...typeof details?.timedOut === "boolean" ? { timedOut: details.timedOut } : {},
|
|
2782
|
-
...typeof details?.outputLimitExceeded === "boolean" ? { outputLimitExceeded: details.outputLimitExceeded } : {},
|
|
2783
|
-
...excerpt(output, true) ? { excerpt: excerpt(output, true) } : {}
|
|
2784
|
-
};
|
|
2785
|
-
}
|
|
2786
|
-
|
|
2787
2750
|
// src/code-runtime-acknowledgement-gate.ts
|
|
2788
2751
|
function codeRuntimeAcknowledgementGate(signal) {
|
|
2789
2752
|
let settle;
|
|
@@ -3090,36 +3053,11 @@ var TheseusRuntimeEngine = class {
|
|
|
3090
3053
|
}
|
|
3091
3054
|
/** Report every brokered effect as it starts and finishes. */
|
|
3092
3055
|
#observed(command, active, broker) {
|
|
3093
|
-
return {
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
await this.#event(
|
|
3099
|
-
command,
|
|
3100
|
-
{
|
|
3101
|
-
type: "tool",
|
|
3102
|
-
phase: "started",
|
|
3103
|
-
tool: request.tool,
|
|
3104
|
-
operationId,
|
|
3105
|
-
...startedPresentation ? { presentation: startedPresentation } : {}
|
|
3106
|
-
},
|
|
3107
|
-
active.conversationRefs
|
|
3108
|
-
).catch(() => void 0);
|
|
3109
|
-
const response2 = await broker.execute(context, request);
|
|
3110
|
-
const completedPresentation = codeToolResultPresentation(request, response2);
|
|
3111
|
-
await this.#event(command, {
|
|
3112
|
-
type: "tool",
|
|
3113
|
-
phase: "completed",
|
|
3114
|
-
tool: request.tool,
|
|
3115
|
-
ok: response2.ok,
|
|
3116
|
-
durationMs: Date.now() - startedAt,
|
|
3117
|
-
operationId,
|
|
3118
|
-
...completedPresentation ? { presentation: completedPresentation } : {}
|
|
3119
|
-
}, active.conversationRefs).catch(() => void 0);
|
|
3120
|
-
return response2;
|
|
3121
|
-
}
|
|
3122
|
-
};
|
|
3056
|
+
return observedBroker({
|
|
3057
|
+
broker,
|
|
3058
|
+
operationIdFor: (requestId) => digestRuntimeValue(`${command.commandId}:${requestId}`),
|
|
3059
|
+
emit: (event) => this.#event(command, event, active.conversationRefs).catch(() => void 0)
|
|
3060
|
+
});
|
|
3123
3061
|
}
|
|
3124
3062
|
async #checkpoint(command) {
|
|
3125
3063
|
const active = this.#active.get(command.sessionId);
|
|
@@ -3156,9 +3094,11 @@ export {
|
|
|
3156
3094
|
runCodeRuntimeHeartbeatLoop,
|
|
3157
3095
|
CodeRuntimeReconciler,
|
|
3158
3096
|
stripPatchEnvelope,
|
|
3097
|
+
applyPatchDialectToDiff,
|
|
3159
3098
|
validateCodePatch,
|
|
3160
3099
|
validateRelativePath,
|
|
3161
3100
|
resolveCodePath,
|
|
3101
|
+
hasContextFreeHunk,
|
|
3162
3102
|
describePatchFailure,
|
|
3163
3103
|
applyCodePatch,
|
|
3164
3104
|
createCodeWorkspaceCheckpoint,
|
|
@@ -3193,4 +3133,4 @@ export {
|
|
|
3193
3133
|
runGoal,
|
|
3194
3134
|
TheseusRuntimeEngine
|
|
3195
3135
|
};
|
|
3196
|
-
//# sourceMappingURL=chunk-
|
|
3136
|
+
//# sourceMappingURL=chunk-AEAISFY3.js.map
|