@odla-ai/harness 0.9.0 → 0.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-CR6RE3A2.js → chunk-5LRYJKUI.js} +3 -3
- package/dist/chunk-FAN2R3GW.js +166 -0
- package/dist/chunk-FAN2R3GW.js.map +1 -0
- package/dist/{chunk-NWNBSX56.js → chunk-OZBJNTML.js} +4 -4
- package/dist/{chunk-NG7AYYH3.js → chunk-Q4NL5XO3.js} +204 -217
- package/dist/chunk-Q4NL5XO3.js.map +1 -0
- package/dist/{chunk-RXNHCGWE.js → chunk-U324RQ4N.js} +1 -1
- package/dist/{chunk-RXNHCGWE.js.map → chunk-U324RQ4N.js.map} +1 -1
- package/dist/{chunk-Q7CKOT7T.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 +311 -164
- package/dist/code-runtime-cli.cjs.map +1 -1
- package/dist/code-runtime-cli.js +12 -6
- 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 +308 -162
- package/dist/node.cjs.map +1 -1
- package/dist/node.d.cts +44 -7
- package/dist/node.d.ts +44 -7
- 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-BNJikP5h.d.ts → types-_8y8vBDI.d.cts} +19 -1
- package/dist/{types-BNJikP5h.d.cts → types-_8y8vBDI.d.ts} +19 -1
- package/package.json +1 -1
- package/dist/chunk-NG7AYYH3.js.map +0 -1
- /package/dist/{chunk-CR6RE3A2.js.map → chunk-5LRYJKUI.js.map} +0 -0
- /package/dist/{chunk-NWNBSX56.js.map → chunk-OZBJNTML.js.map} +0 -0
- /package/dist/{chunk-Q7CKOT7T.js.map → chunk-VDY5V7ZG.js.map} +0 -0
package/dist/node.cjs
CHANGED
|
@@ -33,6 +33,7 @@ __export(node_exports, {
|
|
|
33
33
|
V2_SYSTEM_PROMPT: () => V2_SYSTEM_PROMPT,
|
|
34
34
|
V3_SYSTEM_PROMPT: () => V3_SYSTEM_PROMPT,
|
|
35
35
|
applyCodePatch: () => applyCodePatch,
|
|
36
|
+
applyPatchDialectToDiff: () => applyPatchDialectToDiff,
|
|
36
37
|
assertCodeBuildRecipe: () => assertCodeBuildRecipe,
|
|
37
38
|
assertDisjointPlan: () => assertDisjointPlan,
|
|
38
39
|
assertPinnedImage: () => assertPinnedImage,
|
|
@@ -50,6 +51,7 @@ __export(node_exports, {
|
|
|
50
51
|
describePatchFailure: () => describePatchFailure,
|
|
51
52
|
digestStagedWorkspace: () => digestStagedWorkspace,
|
|
52
53
|
feedbackIsActionable: () => feedbackIsActionable,
|
|
54
|
+
hasContextFreeHunk: () => hasContextFreeHunk,
|
|
53
55
|
hazardFromAttempt: () => hazardFromAttempt,
|
|
54
56
|
installedDependencies: () => installedDependencies,
|
|
55
57
|
integrateSubGoals: () => integrateSubGoals,
|
|
@@ -999,7 +1001,7 @@ async function parseSource(value) {
|
|
|
999
1001
|
}
|
|
1000
1002
|
function parseReview(value) {
|
|
1001
1003
|
const review = record2(record2(value)?.review);
|
|
1002
|
-
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");
|
|
1004
|
+
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");
|
|
1003
1005
|
return review;
|
|
1004
1006
|
}
|
|
1005
1007
|
function parseCandidate(value) {
|
|
@@ -1240,12 +1242,14 @@ async function runCodeRuntimeHeartbeatLoop(options) {
|
|
|
1240
1242
|
} while (!options.signal?.aborted);
|
|
1241
1243
|
}
|
|
1242
1244
|
var CodeRuntimeReconciler = class {
|
|
1243
|
-
constructor(control, engine) {
|
|
1245
|
+
constructor(control, engine, onDiagnostic) {
|
|
1244
1246
|
this.control = control;
|
|
1245
1247
|
this.engine = engine;
|
|
1248
|
+
this.onDiagnostic = onDiagnostic;
|
|
1246
1249
|
}
|
|
1247
1250
|
control;
|
|
1248
1251
|
engine;
|
|
1252
|
+
onDiagnostic;
|
|
1249
1253
|
results = /* @__PURE__ */ new Map();
|
|
1250
1254
|
async reconcile(snapshot) {
|
|
1251
1255
|
for (const command of snapshot.commands) {
|
|
@@ -1263,7 +1267,13 @@ var CodeRuntimeReconciler = class {
|
|
|
1263
1267
|
}
|
|
1264
1268
|
await this.control.acknowledge(command.commandId, completed.result);
|
|
1265
1269
|
if (!completed.notified) {
|
|
1266
|
-
|
|
1270
|
+
try {
|
|
1271
|
+
await this.engine.acknowledged?.(command, completed.result);
|
|
1272
|
+
} catch (error) {
|
|
1273
|
+
this.onDiagnostic?.(
|
|
1274
|
+
`command ${command.commandId} acknowledged handling failed \xB7 ${error instanceof Error ? error.message : String(error)}`
|
|
1275
|
+
);
|
|
1276
|
+
}
|
|
1267
1277
|
completed.notified = true;
|
|
1268
1278
|
}
|
|
1269
1279
|
}
|
|
@@ -1298,10 +1308,41 @@ var SECRET = /^(?:\.env(?:\..+)?|\.dev\.vars|credentials(?:\..+)?\.json|dev-toke
|
|
|
1298
1308
|
var PATH = /^[A-Za-z0-9_@+.,-]+(?:\/[A-Za-z0-9_@+.,-]+)*$/;
|
|
1299
1309
|
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;
|
|
1300
1310
|
function stripPatchEnvelope(patch2) {
|
|
1301
|
-
if (!/^\*\*\* (?:Begin|End) Patch\s*$/m.test(patch2)) return patch2;
|
|
1311
|
+
if (!/^\*\*\* (?:Begin|End) Patch\s*$/m.test(patch2)) return applyPatchDialectToDiff(patch2);
|
|
1302
1312
|
const kept = patch2.split("\n").filter((line) => !/^\*\*\* (?:Begin|End) Patch\s*$/.test(line));
|
|
1303
1313
|
const stripped = kept.join("\n");
|
|
1304
|
-
|
|
1314
|
+
if (/^diff --git /m.test(stripped)) return stripped;
|
|
1315
|
+
const translated = applyPatchDialectToDiff(stripped);
|
|
1316
|
+
return translated === stripped ? patch2 : translated;
|
|
1317
|
+
}
|
|
1318
|
+
function applyPatchDialectToDiff(patch2) {
|
|
1319
|
+
if (!/^\*\*\* (?:Update|Add|Delete) File: /m.test(patch2)) return patch2;
|
|
1320
|
+
const out = [];
|
|
1321
|
+
let open = false;
|
|
1322
|
+
for (const line of patch2.split("\n")) {
|
|
1323
|
+
const file = /^\*\*\* (Update|Add|Delete) File: (.+?)\s*$/.exec(line);
|
|
1324
|
+
if (file) {
|
|
1325
|
+
const [, verb, raw] = file;
|
|
1326
|
+
const path = raw.trim();
|
|
1327
|
+
if (!PATH.test(path)) return patch2;
|
|
1328
|
+
out.push(`diff --git a/${path} b/${path}`);
|
|
1329
|
+
if (verb === "Add") out.push("new file mode 100644", "--- /dev/null", `+++ b/${path}`);
|
|
1330
|
+
else if (verb === "Delete") out.push(`--- a/${path}`, "+++ /dev/null");
|
|
1331
|
+
else out.push(`--- a/${path}`, `+++ b/${path}`);
|
|
1332
|
+
open = true;
|
|
1333
|
+
continue;
|
|
1334
|
+
}
|
|
1335
|
+
if (/^\*\*\* /.test(line)) continue;
|
|
1336
|
+
if (!open) continue;
|
|
1337
|
+
if (/^@@/.test(line)) {
|
|
1338
|
+
out.push("@@ -1 +1 @@");
|
|
1339
|
+
continue;
|
|
1340
|
+
}
|
|
1341
|
+
out.push(line);
|
|
1342
|
+
}
|
|
1343
|
+
if (!open) return patch2;
|
|
1344
|
+
return `${out.join("\n").replace(/\n+$/, "")}
|
|
1345
|
+
`;
|
|
1305
1346
|
}
|
|
1306
1347
|
function validateCodePatch(rawPatch, maxBytes) {
|
|
1307
1348
|
const patch2 = stripPatchEnvelope(rawPatch);
|
|
@@ -1354,17 +1395,20 @@ function resolveCodePath(workspaceDir, path) {
|
|
|
1354
1395
|
if (target !== root && !target.startsWith(`${root}${import_node_path6.sep}`)) throw new TypeError("path escapes the staged workspace");
|
|
1355
1396
|
return target;
|
|
1356
1397
|
}
|
|
1398
|
+
function hasContextFreeHunk(patch2) {
|
|
1399
|
+
const bodies = patch2.split(/^@@.*$/m).slice(1);
|
|
1400
|
+
return bodies.some((body) => !body.split("\n").some((line) => line.startsWith(" ") && line.trim().length > 0));
|
|
1401
|
+
}
|
|
1357
1402
|
function describePatchFailure(patch2, detail) {
|
|
1358
1403
|
const hunks = patch2.split("\n").filter((line) => line.startsWith("@@"));
|
|
1359
|
-
const
|
|
1360
|
-
const contextless = bodies.some((body) => !body.split("\n").some((line) => line.startsWith(" ") && line.trim().length > 0));
|
|
1361
|
-
const hint = hunks.length > 0 && contextless ? " A hunk has no context lines; include at least one unchanged line above or below each change." : "";
|
|
1404
|
+
const hint = hunks.length > 0 && hasContextFreeHunk(patch2) ? " A hunk has no context lines; include at least one unchanged line above or below each change." : "";
|
|
1362
1405
|
return `patch did not apply: ${detail}${hint}`;
|
|
1363
1406
|
}
|
|
1364
1407
|
async function applyCodePatch(workspaceDir, rawPatch, paths2) {
|
|
1365
1408
|
const patch2 = stripPatchEnvelope(rawPatch);
|
|
1366
|
-
|
|
1367
|
-
await gitApply(workspaceDir, patch2,
|
|
1409
|
+
const zero = hasContextFreeHunk(patch2);
|
|
1410
|
+
await gitApply(workspaceDir, patch2, true, zero);
|
|
1411
|
+
await gitApply(workspaceDir, patch2, false, zero);
|
|
1368
1412
|
for (const path of paths2) {
|
|
1369
1413
|
try {
|
|
1370
1414
|
const info = await (0, import_promises6.lstat)(resolveCodePath(workspaceDir, path));
|
|
@@ -1376,9 +1420,16 @@ async function applyCodePatch(workspaceDir, rawPatch, paths2) {
|
|
|
1376
1420
|
}
|
|
1377
1421
|
}
|
|
1378
1422
|
}
|
|
1379
|
-
function gitApply(cwd, patch2, check) {
|
|
1423
|
+
function gitApply(cwd, patch2, check, unidiffZero = false) {
|
|
1380
1424
|
return new Promise((accept, reject) => {
|
|
1381
|
-
const args = [
|
|
1425
|
+
const args = [
|
|
1426
|
+
"apply",
|
|
1427
|
+
"--recount",
|
|
1428
|
+
...unidiffZero ? ["--unidiff-zero"] : [],
|
|
1429
|
+
"--whitespace=nowarn",
|
|
1430
|
+
...check ? ["--check"] : [],
|
|
1431
|
+
"-"
|
|
1432
|
+
];
|
|
1382
1433
|
const child = (0, import_node_child_process4.spawn)("git", args, {
|
|
1383
1434
|
cwd,
|
|
1384
1435
|
shell: false,
|
|
@@ -1786,9 +1837,9 @@ async function prepareRuntimeCheckpoint(input) {
|
|
|
1786
1837
|
if (evidence.receipt.outcome === "passed") {
|
|
1787
1838
|
verification = evidence.receipt;
|
|
1788
1839
|
review = await input.review(patch2, verification);
|
|
1789
|
-
note = review
|
|
1840
|
+
note = describeReview(review);
|
|
1790
1841
|
} else {
|
|
1791
|
-
note =
|
|
1842
|
+
note = describeGateFailure(evidence);
|
|
1792
1843
|
}
|
|
1793
1844
|
} catch (cause) {
|
|
1794
1845
|
note = `Candidate verification or review failed closed: ${message(cause)}`;
|
|
@@ -1813,6 +1864,23 @@ async function prepareRuntimeCheckpoint(input) {
|
|
|
1813
1864
|
});
|
|
1814
1865
|
return { checkpoint, verification, review, note };
|
|
1815
1866
|
}
|
|
1867
|
+
function describeReview(review) {
|
|
1868
|
+
const findings = review.findings.map((finding) => ` - [${finding.severity}] ${finding.detail}`).join("\n");
|
|
1869
|
+
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.`;
|
|
1870
|
+
return [head, review.summary, findings].filter(Boolean).join("\n").slice(0, 4e3);
|
|
1871
|
+
}
|
|
1872
|
+
function describeGateFailure(evidence) {
|
|
1873
|
+
const failed = evidence.receipt.recipes.filter((recipe2) => recipe2.status !== "passed");
|
|
1874
|
+
const detail = failed.map((recipe2) => {
|
|
1875
|
+
const log = evidence.logs.find((entry) => entry.recipeId === recipe2.recipeId);
|
|
1876
|
+
const output = `${log?.stdout ?? ""}
|
|
1877
|
+
${log?.stderr ?? ""}`.trim();
|
|
1878
|
+
return `${recipe2.recipeId}=${recipe2.status}${output ? `
|
|
1879
|
+
${output.slice(0, 1500)}` : ""}`;
|
|
1880
|
+
}).join("\n\n");
|
|
1881
|
+
return `Clean verification failed. Fix this and checkpoint again:
|
|
1882
|
+
${detail}`.slice(0, 4e3);
|
|
1883
|
+
}
|
|
1816
1884
|
var message = (value) => (value instanceof Error ? value.message : String(value)).slice(0, 500);
|
|
1817
1885
|
|
|
1818
1886
|
// src/code-runtime-checkpoint-manager.ts
|
|
@@ -2457,6 +2525,166 @@ function createCodeRuntimeInference(options) {
|
|
|
2457
2525
|
};
|
|
2458
2526
|
}
|
|
2459
2527
|
|
|
2528
|
+
// src/code-tool-presentation.ts
|
|
2529
|
+
var text = (value, maximum) => {
|
|
2530
|
+
if (typeof value !== "string") return void 0;
|
|
2531
|
+
const bounded = value.replace(/[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f]/g, " ").trim();
|
|
2532
|
+
return bounded ? bounded.slice(0, maximum) : void 0;
|
|
2533
|
+
};
|
|
2534
|
+
var integer2 = (value) => Number.isSafeInteger(value) && Number(value) >= 0 ? Number(value) : void 0;
|
|
2535
|
+
var record4 = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
2536
|
+
var excerpt = (value, tail = false) => {
|
|
2537
|
+
if (typeof value !== "string") return void 0;
|
|
2538
|
+
const safe = value.replace(/[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f]/g, " ");
|
|
2539
|
+
const source = (tail ? safe.slice(-1e4) : safe.slice(0, 1e4)).trim();
|
|
2540
|
+
if (!source) return void 0;
|
|
2541
|
+
const lines = source.split("\n").filter((line) => line.trim()).map((line) => line.slice(0, 240));
|
|
2542
|
+
const selected = tail ? lines.slice(-10) : lines.slice(0, 10);
|
|
2543
|
+
return text(selected.join("\n"), 2400);
|
|
2544
|
+
};
|
|
2545
|
+
var paths = (value) => {
|
|
2546
|
+
if (!Array.isArray(value)) return void 0;
|
|
2547
|
+
const items = value.flatMap((item) => {
|
|
2548
|
+
const path = text(item, 1024);
|
|
2549
|
+
return path ? [path] : [];
|
|
2550
|
+
}).slice(0, 12);
|
|
2551
|
+
return items.length ? items : void 0;
|
|
2552
|
+
};
|
|
2553
|
+
function patchStats(value) {
|
|
2554
|
+
if (typeof value !== "string") return {};
|
|
2555
|
+
let additions = 0;
|
|
2556
|
+
let deletions = 0;
|
|
2557
|
+
for (const line of value.slice(0, 262144).split("\n")) {
|
|
2558
|
+
if (line.startsWith("+++") || line.startsWith("---")) continue;
|
|
2559
|
+
if (line.startsWith("+")) additions += 1;
|
|
2560
|
+
else if (line.startsWith("-")) deletions += 1;
|
|
2561
|
+
}
|
|
2562
|
+
return { ...additions ? { additions } : {}, ...deletions ? { deletions } : {} };
|
|
2563
|
+
}
|
|
2564
|
+
function searchResults(value) {
|
|
2565
|
+
if (typeof value !== "string") return void 0;
|
|
2566
|
+
const results = value.split("\n").flatMap((line) => {
|
|
2567
|
+
const match = /^([^:\n]{1,1024}):(\d+):\s?(.*)$/.exec(line);
|
|
2568
|
+
if (!match) return [];
|
|
2569
|
+
const lineNumber = Number(match[2]);
|
|
2570
|
+
const itemText = text(match[3], 240);
|
|
2571
|
+
if (!Number.isSafeInteger(lineNumber) || lineNumber < 1) return [];
|
|
2572
|
+
return [{ path: match[1], line: lineNumber, ...itemText ? { text: itemText } : {} }];
|
|
2573
|
+
}).slice(0, 5);
|
|
2574
|
+
return results.length ? results : void 0;
|
|
2575
|
+
}
|
|
2576
|
+
function codeToolRequestPresentation(request) {
|
|
2577
|
+
const input = request.input;
|
|
2578
|
+
if (request.tool === "sandbox.read") {
|
|
2579
|
+
const path = text(input.path, 1024);
|
|
2580
|
+
if (!path) return void 0;
|
|
2581
|
+
const startLine = integer2(input.startLine);
|
|
2582
|
+
const endLine = integer2(input.endLine);
|
|
2583
|
+
return { kind: "read", path, ...startLine ? { startLine } : {}, ...endLine ? { endLine } : {} };
|
|
2584
|
+
}
|
|
2585
|
+
if (request.tool === "sandbox.list") {
|
|
2586
|
+
const scope = text(input.prefix, 1024);
|
|
2587
|
+
return { kind: "list", ...scope ? { scope } : {} };
|
|
2588
|
+
}
|
|
2589
|
+
if (request.tool === "sandbox.search" || request.tool === "sandbox.overview" || request.tool === "sandbox.where_is" || request.tool === "sandbox.who_imports" || request.tool === "sandbox.who_touches") {
|
|
2590
|
+
const query = text(input.query, 512);
|
|
2591
|
+
const scope = request.tool === "sandbox.search" ? text(input.prefix, 1024) : void 0;
|
|
2592
|
+
if (request.tool === "sandbox.search" && !query) return void 0;
|
|
2593
|
+
return { kind: "query", ...query ? { query } : {}, ...scope ? { scope } : {} };
|
|
2594
|
+
}
|
|
2595
|
+
if (request.tool === "sandbox.apply_patch") {
|
|
2596
|
+
return { kind: "patch", ...patchStats(input.patch) };
|
|
2597
|
+
}
|
|
2598
|
+
const recipeId = text(input.recipeId, 120);
|
|
2599
|
+
return recipeId ? { kind: "recipe", recipeId } : void 0;
|
|
2600
|
+
}
|
|
2601
|
+
function codeToolResultPresentation(request, response2) {
|
|
2602
|
+
const started = codeToolRequestPresentation(request);
|
|
2603
|
+
if (!started || !response2.ok) return started;
|
|
2604
|
+
const details = record4(response2.details);
|
|
2605
|
+
if (started.kind === "read") {
|
|
2606
|
+
return {
|
|
2607
|
+
...started,
|
|
2608
|
+
...integer2(details?.startLine) ? { startLine: integer2(details?.startLine) } : {},
|
|
2609
|
+
...integer2(details?.endLine) ? { endLine: integer2(details?.endLine) } : {},
|
|
2610
|
+
...excerpt(response2.content) ? { excerpt: excerpt(response2.content) } : {}
|
|
2611
|
+
};
|
|
2612
|
+
}
|
|
2613
|
+
if (started.kind === "list") {
|
|
2614
|
+
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);
|
|
2615
|
+
return {
|
|
2616
|
+
...started,
|
|
2617
|
+
...integer2(details?.count) !== void 0 ? { count: integer2(details?.count) } : {},
|
|
2618
|
+
...listed.length ? { paths: listed } : {}
|
|
2619
|
+
};
|
|
2620
|
+
}
|
|
2621
|
+
if (started.kind === "query") {
|
|
2622
|
+
const results = request.tool === "sandbox.search" ? searchResults(response2.content) : void 0;
|
|
2623
|
+
const resultExcerpt = request.tool === "sandbox.search" ? void 0 : excerpt(response2.content);
|
|
2624
|
+
return {
|
|
2625
|
+
...started,
|
|
2626
|
+
...integer2(details?.count) !== void 0 ? { count: integer2(details?.count) } : {},
|
|
2627
|
+
...results ? { results } : {},
|
|
2628
|
+
...resultExcerpt ? { excerpt: resultExcerpt } : {}
|
|
2629
|
+
};
|
|
2630
|
+
}
|
|
2631
|
+
if (started.kind === "patch") {
|
|
2632
|
+
return { ...started, ...paths(details?.paths) ? { paths: paths(details?.paths) } : {} };
|
|
2633
|
+
}
|
|
2634
|
+
const output = response2.content.replace(/^Recipe [^\n]*\.?\s*/u, "");
|
|
2635
|
+
return {
|
|
2636
|
+
...started,
|
|
2637
|
+
...integer2(details?.exitCode) !== void 0 ? { exitCode: integer2(details?.exitCode) } : {},
|
|
2638
|
+
...typeof details?.timedOut === "boolean" ? { timedOut: details.timedOut } : {},
|
|
2639
|
+
...typeof details?.outputLimitExceeded === "boolean" ? { outputLimitExceeded: details.outputLimitExceeded } : {},
|
|
2640
|
+
...excerpt(output, true) ? { excerpt: excerpt(output, true) } : {}
|
|
2641
|
+
};
|
|
2642
|
+
}
|
|
2643
|
+
|
|
2644
|
+
// src/code-runtime-observer.ts
|
|
2645
|
+
var MAX_FAILURE_REASON = 240;
|
|
2646
|
+
function toolFailureReason(response2) {
|
|
2647
|
+
if (response2.ok) return void 0;
|
|
2648
|
+
const supplied = response2.details?.failureReason;
|
|
2649
|
+
const reason = typeof supplied === "string" && supplied || DEFAULT_FAILURE_REASON[response2.content] || response2.content || "tool request failed; inspect the tool input and workspace state";
|
|
2650
|
+
return reason.slice(0, MAX_FAILURE_REASON);
|
|
2651
|
+
}
|
|
2652
|
+
var DEFAULT_FAILURE_REASON = {
|
|
2653
|
+
"tool denied by CaMeL policy": "tool denied by CaMeL policy",
|
|
2654
|
+
"review sessions are read-only": "review session is read-only; workspace changes are not permitted"
|
|
2655
|
+
};
|
|
2656
|
+
function observedBroker(input) {
|
|
2657
|
+
const now = input.now ?? Date.now;
|
|
2658
|
+
return {
|
|
2659
|
+
execute: async (context, request) => {
|
|
2660
|
+
const startedAt = now();
|
|
2661
|
+
const operationId = input.operationIdFor(request.requestId);
|
|
2662
|
+
const startedPresentation = codeToolRequestPresentation(request);
|
|
2663
|
+
await input.emit({
|
|
2664
|
+
type: "tool",
|
|
2665
|
+
phase: "started",
|
|
2666
|
+
tool: request.tool,
|
|
2667
|
+
operationId,
|
|
2668
|
+
...startedPresentation ? { presentation: startedPresentation } : {}
|
|
2669
|
+
});
|
|
2670
|
+
const response2 = await input.broker.execute(context, request);
|
|
2671
|
+
const completedPresentation = codeToolResultPresentation(request, response2);
|
|
2672
|
+
const failureReason = toolFailureReason(response2);
|
|
2673
|
+
await input.emit({
|
|
2674
|
+
type: "tool",
|
|
2675
|
+
phase: "completed",
|
|
2676
|
+
tool: request.tool,
|
|
2677
|
+
ok: response2.ok,
|
|
2678
|
+
durationMs: now() - startedAt,
|
|
2679
|
+
operationId,
|
|
2680
|
+
...failureReason ? { failureReason } : {},
|
|
2681
|
+
...completedPresentation ? { presentation: completedPresentation } : {}
|
|
2682
|
+
});
|
|
2683
|
+
return response2;
|
|
2684
|
+
}
|
|
2685
|
+
};
|
|
2686
|
+
}
|
|
2687
|
+
|
|
2460
2688
|
// src/code-tool-policy.ts
|
|
2461
2689
|
var import_camel = require("@odla-ai/camel");
|
|
2462
2690
|
var import_policy = require("@odla-ai/camel/policy");
|
|
@@ -2695,8 +2923,14 @@ function optionalInteger(value) {
|
|
|
2695
2923
|
if (!Number.isSafeInteger(value) || value < 1) throw new TypeError("line bounds must be positive integers");
|
|
2696
2924
|
return value;
|
|
2697
2925
|
}
|
|
2926
|
+
var DEFAULT_FAILURE_REASON2 = {
|
|
2927
|
+
"tool denied by CaMeL policy": "tool denied by CaMeL policy",
|
|
2928
|
+
"review sessions are read-only": "review session is read-only; workspace changes are not permitted"
|
|
2929
|
+
};
|
|
2698
2930
|
function response(request, ok, content, details) {
|
|
2699
|
-
return { requestId: request.requestId, ok, content, ...details ? { details } : {} };
|
|
2931
|
+
if (ok) return { requestId: request.requestId, ok, content, ...details ? { details } : {} };
|
|
2932
|
+
const failureReason = typeof details?.failureReason === "string" && details.failureReason || DEFAULT_FAILURE_REASON2[content] || content || "tool request failed; inspect the tool input and workspace state";
|
|
2933
|
+
return { requestId: request.requestId, ok, content, details: { ...details, failureReason } };
|
|
2700
2934
|
}
|
|
2701
2935
|
|
|
2702
2936
|
// src/code-tool-reads.ts
|
|
@@ -3497,122 +3731,6 @@ async function appendCodeRuntimeEvent(control, command, event, refs) {
|
|
|
3497
3731
|
var digestRuntimeValue = (value) => `sha256:${(0, import_node_crypto4.createHash)("sha256").update(value).digest("hex")}`;
|
|
3498
3732
|
var runtimeErrorMessage = (value) => value instanceof Error ? value.message : String(value);
|
|
3499
3733
|
|
|
3500
|
-
// src/code-tool-presentation.ts
|
|
3501
|
-
var text = (value, maximum) => {
|
|
3502
|
-
if (typeof value !== "string") return void 0;
|
|
3503
|
-
const bounded = value.replace(/[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f]/g, " ").trim();
|
|
3504
|
-
return bounded ? bounded.slice(0, maximum) : void 0;
|
|
3505
|
-
};
|
|
3506
|
-
var integer2 = (value) => Number.isSafeInteger(value) && Number(value) >= 0 ? Number(value) : void 0;
|
|
3507
|
-
var record4 = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
3508
|
-
var excerpt = (value, tail = false) => {
|
|
3509
|
-
if (typeof value !== "string") return void 0;
|
|
3510
|
-
const safe = value.replace(/[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f]/g, " ");
|
|
3511
|
-
const source = (tail ? safe.slice(-1e4) : safe.slice(0, 1e4)).trim();
|
|
3512
|
-
if (!source) return void 0;
|
|
3513
|
-
const lines = source.split("\n").filter((line) => line.trim()).map((line) => line.slice(0, 240));
|
|
3514
|
-
const selected = tail ? lines.slice(-10) : lines.slice(0, 10);
|
|
3515
|
-
return text(selected.join("\n"), 2400);
|
|
3516
|
-
};
|
|
3517
|
-
var paths = (value) => {
|
|
3518
|
-
if (!Array.isArray(value)) return void 0;
|
|
3519
|
-
const items = value.flatMap((item) => {
|
|
3520
|
-
const path = text(item, 1024);
|
|
3521
|
-
return path ? [path] : [];
|
|
3522
|
-
}).slice(0, 12);
|
|
3523
|
-
return items.length ? items : void 0;
|
|
3524
|
-
};
|
|
3525
|
-
function patchStats(value) {
|
|
3526
|
-
if (typeof value !== "string") return {};
|
|
3527
|
-
let additions = 0;
|
|
3528
|
-
let deletions = 0;
|
|
3529
|
-
for (const line of value.slice(0, 262144).split("\n")) {
|
|
3530
|
-
if (line.startsWith("+++") || line.startsWith("---")) continue;
|
|
3531
|
-
if (line.startsWith("+")) additions += 1;
|
|
3532
|
-
else if (line.startsWith("-")) deletions += 1;
|
|
3533
|
-
}
|
|
3534
|
-
return { ...additions ? { additions } : {}, ...deletions ? { deletions } : {} };
|
|
3535
|
-
}
|
|
3536
|
-
function searchResults(value) {
|
|
3537
|
-
if (typeof value !== "string") return void 0;
|
|
3538
|
-
const results = value.split("\n").flatMap((line) => {
|
|
3539
|
-
const match = /^([^:\n]{1,1024}):(\d+):\s?(.*)$/.exec(line);
|
|
3540
|
-
if (!match) return [];
|
|
3541
|
-
const lineNumber = Number(match[2]);
|
|
3542
|
-
const itemText = text(match[3], 240);
|
|
3543
|
-
if (!Number.isSafeInteger(lineNumber) || lineNumber < 1) return [];
|
|
3544
|
-
return [{ path: match[1], line: lineNumber, ...itemText ? { text: itemText } : {} }];
|
|
3545
|
-
}).slice(0, 5);
|
|
3546
|
-
return results.length ? results : void 0;
|
|
3547
|
-
}
|
|
3548
|
-
function codeToolRequestPresentation(request) {
|
|
3549
|
-
const input = request.input;
|
|
3550
|
-
if (request.tool === "sandbox.read") {
|
|
3551
|
-
const path = text(input.path, 1024);
|
|
3552
|
-
if (!path) return void 0;
|
|
3553
|
-
const startLine = integer2(input.startLine);
|
|
3554
|
-
const endLine = integer2(input.endLine);
|
|
3555
|
-
return { kind: "read", path, ...startLine ? { startLine } : {}, ...endLine ? { endLine } : {} };
|
|
3556
|
-
}
|
|
3557
|
-
if (request.tool === "sandbox.list") {
|
|
3558
|
-
const scope = text(input.prefix, 1024);
|
|
3559
|
-
return { kind: "list", ...scope ? { scope } : {} };
|
|
3560
|
-
}
|
|
3561
|
-
if (request.tool === "sandbox.search" || request.tool === "sandbox.overview" || request.tool === "sandbox.where_is" || request.tool === "sandbox.who_imports" || request.tool === "sandbox.who_touches") {
|
|
3562
|
-
const query = text(input.query, 512);
|
|
3563
|
-
const scope = request.tool === "sandbox.search" ? text(input.prefix, 1024) : void 0;
|
|
3564
|
-
if (request.tool === "sandbox.search" && !query) return void 0;
|
|
3565
|
-
return { kind: "query", ...query ? { query } : {}, ...scope ? { scope } : {} };
|
|
3566
|
-
}
|
|
3567
|
-
if (request.tool === "sandbox.apply_patch") {
|
|
3568
|
-
return { kind: "patch", ...patchStats(input.patch) };
|
|
3569
|
-
}
|
|
3570
|
-
const recipeId = text(input.recipeId, 120);
|
|
3571
|
-
return recipeId ? { kind: "recipe", recipeId } : void 0;
|
|
3572
|
-
}
|
|
3573
|
-
function codeToolResultPresentation(request, response2) {
|
|
3574
|
-
const started = codeToolRequestPresentation(request);
|
|
3575
|
-
if (!started || !response2.ok) return started;
|
|
3576
|
-
const details = record4(response2.details);
|
|
3577
|
-
if (started.kind === "read") {
|
|
3578
|
-
return {
|
|
3579
|
-
...started,
|
|
3580
|
-
...integer2(details?.startLine) ? { startLine: integer2(details?.startLine) } : {},
|
|
3581
|
-
...integer2(details?.endLine) ? { endLine: integer2(details?.endLine) } : {},
|
|
3582
|
-
...excerpt(response2.content) ? { excerpt: excerpt(response2.content) } : {}
|
|
3583
|
-
};
|
|
3584
|
-
}
|
|
3585
|
-
if (started.kind === "list") {
|
|
3586
|
-
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);
|
|
3587
|
-
return {
|
|
3588
|
-
...started,
|
|
3589
|
-
...integer2(details?.count) !== void 0 ? { count: integer2(details?.count) } : {},
|
|
3590
|
-
...listed.length ? { paths: listed } : {}
|
|
3591
|
-
};
|
|
3592
|
-
}
|
|
3593
|
-
if (started.kind === "query") {
|
|
3594
|
-
const results = request.tool === "sandbox.search" ? searchResults(response2.content) : void 0;
|
|
3595
|
-
const resultExcerpt = request.tool === "sandbox.search" ? void 0 : excerpt(response2.content);
|
|
3596
|
-
return {
|
|
3597
|
-
...started,
|
|
3598
|
-
...integer2(details?.count) !== void 0 ? { count: integer2(details?.count) } : {},
|
|
3599
|
-
...results ? { results } : {},
|
|
3600
|
-
...resultExcerpt ? { excerpt: resultExcerpt } : {}
|
|
3601
|
-
};
|
|
3602
|
-
}
|
|
3603
|
-
if (started.kind === "patch") {
|
|
3604
|
-
return { ...started, ...paths(details?.paths) ? { paths: paths(details?.paths) } : {} };
|
|
3605
|
-
}
|
|
3606
|
-
const output = response2.content.replace(/^Recipe [^\n]*\.?\s*/u, "");
|
|
3607
|
-
return {
|
|
3608
|
-
...started,
|
|
3609
|
-
...integer2(details?.exitCode) !== void 0 ? { exitCode: integer2(details?.exitCode) } : {},
|
|
3610
|
-
...typeof details?.timedOut === "boolean" ? { timedOut: details.timedOut } : {},
|
|
3611
|
-
...typeof details?.outputLimitExceeded === "boolean" ? { outputLimitExceeded: details.outputLimitExceeded } : {},
|
|
3612
|
-
...excerpt(output, true) ? { excerpt: excerpt(output, true) } : {}
|
|
3613
|
-
};
|
|
3614
|
-
}
|
|
3615
|
-
|
|
3616
3734
|
// src/code-runtime-acknowledgement-gate.ts
|
|
3617
3735
|
function codeRuntimeAcknowledgementGate(signal) {
|
|
3618
3736
|
let settle;
|
|
@@ -3632,6 +3750,57 @@ function codeRuntimeAcknowledgementGate(signal) {
|
|
|
3632
3750
|
return { ready, release };
|
|
3633
3751
|
}
|
|
3634
3752
|
|
|
3753
|
+
// src/code-runtime-session-activity.ts
|
|
3754
|
+
function observeCodeRuntimeSessionSkills(command, skills, emit) {
|
|
3755
|
+
return skills.map((skill) => ({
|
|
3756
|
+
...skill,
|
|
3757
|
+
tools: skill.tools.map((tool) => {
|
|
3758
|
+
if (!tool.handler) return tool;
|
|
3759
|
+
const handler = tool.handler;
|
|
3760
|
+
return {
|
|
3761
|
+
...tool,
|
|
3762
|
+
handler: async (input, context) => {
|
|
3763
|
+
const startedAt = Date.now();
|
|
3764
|
+
const operationId = digestRuntimeValue(
|
|
3765
|
+
`${command.commandId}:${skill.name}:${tool.name}:${context.toolCallId ?? "missing"}`
|
|
3766
|
+
);
|
|
3767
|
+
await emit({
|
|
3768
|
+
type: "collaboration",
|
|
3769
|
+
phase: "started",
|
|
3770
|
+
skill: skill.name,
|
|
3771
|
+
tool: tool.name,
|
|
3772
|
+
operationId
|
|
3773
|
+
}).catch(() => void 0);
|
|
3774
|
+
try {
|
|
3775
|
+
const output = await handler(input, context);
|
|
3776
|
+
await emit({
|
|
3777
|
+
type: "collaboration",
|
|
3778
|
+
phase: "completed",
|
|
3779
|
+
skill: skill.name,
|
|
3780
|
+
tool: tool.name,
|
|
3781
|
+
operationId,
|
|
3782
|
+
ok: output.isError !== true,
|
|
3783
|
+
durationMs: Date.now() - startedAt
|
|
3784
|
+
}).catch(() => void 0);
|
|
3785
|
+
return output;
|
|
3786
|
+
} catch (cause) {
|
|
3787
|
+
await emit({
|
|
3788
|
+
type: "collaboration",
|
|
3789
|
+
phase: "completed",
|
|
3790
|
+
skill: skill.name,
|
|
3791
|
+
tool: tool.name,
|
|
3792
|
+
operationId,
|
|
3793
|
+
ok: false,
|
|
3794
|
+
durationMs: Date.now() - startedAt
|
|
3795
|
+
}).catch(() => void 0);
|
|
3796
|
+
throw cause;
|
|
3797
|
+
}
|
|
3798
|
+
}
|
|
3799
|
+
};
|
|
3800
|
+
})
|
|
3801
|
+
}));
|
|
3802
|
+
}
|
|
3803
|
+
|
|
3635
3804
|
// src/code-runtime-engine.ts
|
|
3636
3805
|
var TheseusRuntimeEngine = class {
|
|
3637
3806
|
constructor(options) {
|
|
@@ -3829,7 +3998,7 @@ var TheseusRuntimeEngine = class {
|
|
|
3829
3998
|
event: (event) => this.#event(command, event, active.conversationRefs)
|
|
3830
3999
|
});
|
|
3831
4000
|
await this.#event(command, { type: "status", status: "running" }, active.conversationRefs);
|
|
3832
|
-
const extraSkills = await sessionSkillsFor(this.options, command);
|
|
4001
|
+
const extraSkills = observeCodeRuntimeSessionSkills(command, await sessionSkillsFor(this.options, command), (event) => this.#event(command, event, active.conversationRefs));
|
|
3833
4002
|
const result = await this.#attempt({
|
|
3834
4003
|
inference,
|
|
3835
4004
|
broker,
|
|
@@ -3868,36 +4037,11 @@ var TheseusRuntimeEngine = class {
|
|
|
3868
4037
|
}
|
|
3869
4038
|
/** Report every brokered effect as it starts and finishes. */
|
|
3870
4039
|
#observed(command, active, broker) {
|
|
3871
|
-
return {
|
|
3872
|
-
|
|
3873
|
-
|
|
3874
|
-
|
|
3875
|
-
|
|
3876
|
-
await this.#event(
|
|
3877
|
-
command,
|
|
3878
|
-
{
|
|
3879
|
-
type: "tool",
|
|
3880
|
-
phase: "started",
|
|
3881
|
-
tool: request.tool,
|
|
3882
|
-
operationId,
|
|
3883
|
-
...startedPresentation ? { presentation: startedPresentation } : {}
|
|
3884
|
-
},
|
|
3885
|
-
active.conversationRefs
|
|
3886
|
-
).catch(() => void 0);
|
|
3887
|
-
const response2 = await broker.execute(context, request);
|
|
3888
|
-
const completedPresentation = codeToolResultPresentation(request, response2);
|
|
3889
|
-
await this.#event(command, {
|
|
3890
|
-
type: "tool",
|
|
3891
|
-
phase: "completed",
|
|
3892
|
-
tool: request.tool,
|
|
3893
|
-
ok: response2.ok,
|
|
3894
|
-
durationMs: Date.now() - startedAt,
|
|
3895
|
-
operationId,
|
|
3896
|
-
...completedPresentation ? { presentation: completedPresentation } : {}
|
|
3897
|
-
}, active.conversationRefs).catch(() => void 0);
|
|
3898
|
-
return response2;
|
|
3899
|
-
}
|
|
3900
|
-
};
|
|
4040
|
+
return observedBroker({
|
|
4041
|
+
broker,
|
|
4042
|
+
operationIdFor: (requestId) => digestRuntimeValue(`${command.commandId}:${requestId}`),
|
|
4043
|
+
emit: (event) => this.#event(command, event, active.conversationRefs).catch(() => void 0)
|
|
4044
|
+
});
|
|
3901
4045
|
}
|
|
3902
4046
|
async #checkpoint(command) {
|
|
3903
4047
|
const active = this.#active.get(command.sessionId);
|
|
@@ -4241,6 +4385,7 @@ async function installedDependencies(repoRoot) {
|
|
|
4241
4385
|
V2_SYSTEM_PROMPT,
|
|
4242
4386
|
V3_SYSTEM_PROMPT,
|
|
4243
4387
|
applyCodePatch,
|
|
4388
|
+
applyPatchDialectToDiff,
|
|
4244
4389
|
assertCodeBuildRecipe,
|
|
4245
4390
|
assertDisjointPlan,
|
|
4246
4391
|
assertPinnedImage,
|
|
@@ -4258,6 +4403,7 @@ async function installedDependencies(repoRoot) {
|
|
|
4258
4403
|
describePatchFailure,
|
|
4259
4404
|
digestStagedWorkspace,
|
|
4260
4405
|
feedbackIsActionable,
|
|
4406
|
+
hasContextFreeHunk,
|
|
4261
4407
|
hazardFromAttempt,
|
|
4262
4408
|
installedDependencies,
|
|
4263
4409
|
integrateSubGoals,
|