@odla-ai/harness 0.9.1 → 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.
Files changed (38) hide show
  1. package/dist/{chunk-HDIR4MM5.js → chunk-5LRYJKUI.js} +3 -3
  2. package/dist/chunk-FAN2R3GW.js +166 -0
  3. package/dist/chunk-FAN2R3GW.js.map +1 -0
  4. package/dist/{chunk-CIKYMC67.js → chunk-OZBJNTML.js} +4 -4
  5. package/dist/{chunk-4EPJJMFG.js → chunk-Q4NL5XO3.js} +142 -214
  6. package/dist/chunk-Q4NL5XO3.js.map +1 -0
  7. package/dist/{chunk-I43KTCJ2.js → chunk-U324RQ4N.js} +1 -1
  8. package/dist/{chunk-I43KTCJ2.js.map → chunk-U324RQ4N.js.map} +1 -1
  9. package/dist/{chunk-VGNIDRKM.js → chunk-VDY5V7ZG.js} +2 -2
  10. package/dist/cli.cjs.map +1 -1
  11. package/dist/cli.js +4 -4
  12. package/dist/code-runtime-cli.cjs +243 -160
  13. package/dist/code-runtime-cli.cjs.map +1 -1
  14. package/dist/code-runtime-cli.js +6 -5
  15. package/dist/code-runtime-cli.js.map +1 -1
  16. package/dist/index.cjs +172 -6
  17. package/dist/index.cjs.map +1 -1
  18. package/dist/index.d.cts +24 -3
  19. package/dist/index.d.ts +24 -3
  20. package/dist/index.js +11 -3
  21. package/dist/index.js.map +1 -1
  22. package/dist/node.cjs +246 -159
  23. package/dist/node.cjs.map +1 -1
  24. package/dist/node.d.cts +39 -6
  25. package/dist/node.d.ts +39 -6
  26. package/dist/node.js +10 -5
  27. package/dist/node.js.map +1 -1
  28. package/dist/testing.cjs.map +1 -1
  29. package/dist/testing.d.cts +1 -1
  30. package/dist/testing.d.ts +1 -1
  31. package/dist/testing.js +1 -1
  32. package/dist/{types-BazqxWK8.d.cts → types-_8y8vBDI.d.cts} +5 -1
  33. package/dist/{types-BazqxWK8.d.ts → types-_8y8vBDI.d.ts} +5 -1
  34. package/package.json +1 -1
  35. package/dist/chunk-4EPJJMFG.js.map +0 -1
  36. /package/dist/{chunk-HDIR4MM5.js.map → chunk-5LRYJKUI.js.map} +0 -0
  37. /package/dist/{chunk-CIKYMC67.js.map → chunk-OZBJNTML.js.map} +0 -0
  38. /package/dist/{chunk-VGNIDRKM.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) {
@@ -1306,10 +1308,41 @@ var SECRET = /^(?:\.env(?:\..+)?|\.dev\.vars|credentials(?:\..+)?\.json|dev-toke
1306
1308
  var PATH = /^[A-Za-z0-9_@+.,-]+(?:\/[A-Za-z0-9_@+.,-]+)*$/;
1307
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;
1308
1310
  function stripPatchEnvelope(patch2) {
1309
- if (!/^\*\*\* (?:Begin|End) Patch\s*$/m.test(patch2)) return patch2;
1311
+ if (!/^\*\*\* (?:Begin|End) Patch\s*$/m.test(patch2)) return applyPatchDialectToDiff(patch2);
1310
1312
  const kept = patch2.split("\n").filter((line) => !/^\*\*\* (?:Begin|End) Patch\s*$/.test(line));
1311
1313
  const stripped = kept.join("\n");
1312
- return /^diff --git /m.test(stripped) ? stripped : patch2;
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
+ `;
1313
1346
  }
1314
1347
  function validateCodePatch(rawPatch, maxBytes) {
1315
1348
  const patch2 = stripPatchEnvelope(rawPatch);
@@ -1362,17 +1395,20 @@ function resolveCodePath(workspaceDir, path) {
1362
1395
  if (target !== root && !target.startsWith(`${root}${import_node_path6.sep}`)) throw new TypeError("path escapes the staged workspace");
1363
1396
  return target;
1364
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
+ }
1365
1402
  function describePatchFailure(patch2, detail) {
1366
1403
  const hunks = patch2.split("\n").filter((line) => line.startsWith("@@"));
1367
- const bodies = patch2.split(/^@@.*$/m).slice(1);
1368
- const contextless = bodies.some((body) => !body.split("\n").some((line) => line.startsWith(" ") && line.trim().length > 0));
1369
- 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." : "";
1370
1405
  return `patch did not apply: ${detail}${hint}`;
1371
1406
  }
1372
1407
  async function applyCodePatch(workspaceDir, rawPatch, paths2) {
1373
1408
  const patch2 = stripPatchEnvelope(rawPatch);
1374
- await gitApply(workspaceDir, patch2, true);
1375
- await gitApply(workspaceDir, patch2, false);
1409
+ const zero = hasContextFreeHunk(patch2);
1410
+ await gitApply(workspaceDir, patch2, true, zero);
1411
+ await gitApply(workspaceDir, patch2, false, zero);
1376
1412
  for (const path of paths2) {
1377
1413
  try {
1378
1414
  const info = await (0, import_promises6.lstat)(resolveCodePath(workspaceDir, path));
@@ -1384,9 +1420,16 @@ async function applyCodePatch(workspaceDir, rawPatch, paths2) {
1384
1420
  }
1385
1421
  }
1386
1422
  }
1387
- function gitApply(cwd, patch2, check) {
1423
+ function gitApply(cwd, patch2, check, unidiffZero = false) {
1388
1424
  return new Promise((accept, reject) => {
1389
- const args = ["apply", "--recount", "--whitespace=nowarn", ...check ? ["--check"] : [], "-"];
1425
+ const args = [
1426
+ "apply",
1427
+ "--recount",
1428
+ ...unidiffZero ? ["--unidiff-zero"] : [],
1429
+ "--whitespace=nowarn",
1430
+ ...check ? ["--check"] : [],
1431
+ "-"
1432
+ ];
1390
1433
  const child = (0, import_node_child_process4.spawn)("git", args, {
1391
1434
  cwd,
1392
1435
  shell: false,
@@ -1794,9 +1837,9 @@ async function prepareRuntimeCheckpoint(input) {
1794
1837
  if (evidence.receipt.outcome === "passed") {
1795
1838
  verification = evidence.receipt;
1796
1839
  review = await input.review(patch2, verification);
1797
- note = review.verdict === "approved" ? "Clean verification and independent review passed" : "Clean verification passed; independent review rejected the candidate";
1840
+ note = describeReview(review);
1798
1841
  } else {
1799
- note = `Clean verification failed: ${evidence.receipt.recipes.filter((recipe2) => recipe2.status !== "passed").map((recipe2) => `${recipe2.recipeId}=${recipe2.status}`).join(", ")}`;
1842
+ note = describeGateFailure(evidence);
1800
1843
  }
1801
1844
  } catch (cause) {
1802
1845
  note = `Candidate verification or review failed closed: ${message(cause)}`;
@@ -1821,6 +1864,23 @@ async function prepareRuntimeCheckpoint(input) {
1821
1864
  });
1822
1865
  return { checkpoint, verification, review, note };
1823
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
+ }
1824
1884
  var message = (value) => (value instanceof Error ? value.message : String(value)).slice(0, 500);
1825
1885
 
1826
1886
  // src/code-runtime-checkpoint-manager.ts
@@ -2465,6 +2525,166 @@ function createCodeRuntimeInference(options) {
2465
2525
  };
2466
2526
  }
2467
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
+
2468
2688
  // src/code-tool-policy.ts
2469
2689
  var import_camel = require("@odla-ai/camel");
2470
2690
  var import_policy = require("@odla-ai/camel/policy");
@@ -2703,8 +2923,14 @@ function optionalInteger(value) {
2703
2923
  if (!Number.isSafeInteger(value) || value < 1) throw new TypeError("line bounds must be positive integers");
2704
2924
  return value;
2705
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
+ };
2706
2930
  function response(request, ok, content, details) {
2707
- 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 } };
2708
2934
  }
2709
2935
 
2710
2936
  // src/code-tool-reads.ts
@@ -3505,122 +3731,6 @@ async function appendCodeRuntimeEvent(control, command, event, refs) {
3505
3731
  var digestRuntimeValue = (value) => `sha256:${(0, import_node_crypto4.createHash)("sha256").update(value).digest("hex")}`;
3506
3732
  var runtimeErrorMessage = (value) => value instanceof Error ? value.message : String(value);
3507
3733
 
3508
- // src/code-tool-presentation.ts
3509
- var text = (value, maximum) => {
3510
- if (typeof value !== "string") return void 0;
3511
- const bounded = value.replace(/[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f]/g, " ").trim();
3512
- return bounded ? bounded.slice(0, maximum) : void 0;
3513
- };
3514
- var integer2 = (value) => Number.isSafeInteger(value) && Number(value) >= 0 ? Number(value) : void 0;
3515
- var record4 = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
3516
- var excerpt = (value, tail = false) => {
3517
- if (typeof value !== "string") return void 0;
3518
- const safe = value.replace(/[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f]/g, " ");
3519
- const source = (tail ? safe.slice(-1e4) : safe.slice(0, 1e4)).trim();
3520
- if (!source) return void 0;
3521
- const lines = source.split("\n").filter((line) => line.trim()).map((line) => line.slice(0, 240));
3522
- const selected = tail ? lines.slice(-10) : lines.slice(0, 10);
3523
- return text(selected.join("\n"), 2400);
3524
- };
3525
- var paths = (value) => {
3526
- if (!Array.isArray(value)) return void 0;
3527
- const items = value.flatMap((item) => {
3528
- const path = text(item, 1024);
3529
- return path ? [path] : [];
3530
- }).slice(0, 12);
3531
- return items.length ? items : void 0;
3532
- };
3533
- function patchStats(value) {
3534
- if (typeof value !== "string") return {};
3535
- let additions = 0;
3536
- let deletions = 0;
3537
- for (const line of value.slice(0, 262144).split("\n")) {
3538
- if (line.startsWith("+++") || line.startsWith("---")) continue;
3539
- if (line.startsWith("+")) additions += 1;
3540
- else if (line.startsWith("-")) deletions += 1;
3541
- }
3542
- return { ...additions ? { additions } : {}, ...deletions ? { deletions } : {} };
3543
- }
3544
- function searchResults(value) {
3545
- if (typeof value !== "string") return void 0;
3546
- const results = value.split("\n").flatMap((line) => {
3547
- const match = /^([^:\n]{1,1024}):(\d+):\s?(.*)$/.exec(line);
3548
- if (!match) return [];
3549
- const lineNumber = Number(match[2]);
3550
- const itemText = text(match[3], 240);
3551
- if (!Number.isSafeInteger(lineNumber) || lineNumber < 1) return [];
3552
- return [{ path: match[1], line: lineNumber, ...itemText ? { text: itemText } : {} }];
3553
- }).slice(0, 5);
3554
- return results.length ? results : void 0;
3555
- }
3556
- function codeToolRequestPresentation(request) {
3557
- const input = request.input;
3558
- if (request.tool === "sandbox.read") {
3559
- const path = text(input.path, 1024);
3560
- if (!path) return void 0;
3561
- const startLine = integer2(input.startLine);
3562
- const endLine = integer2(input.endLine);
3563
- return { kind: "read", path, ...startLine ? { startLine } : {}, ...endLine ? { endLine } : {} };
3564
- }
3565
- if (request.tool === "sandbox.list") {
3566
- const scope = text(input.prefix, 1024);
3567
- return { kind: "list", ...scope ? { scope } : {} };
3568
- }
3569
- if (request.tool === "sandbox.search" || request.tool === "sandbox.overview" || request.tool === "sandbox.where_is" || request.tool === "sandbox.who_imports" || request.tool === "sandbox.who_touches") {
3570
- const query = text(input.query, 512);
3571
- const scope = request.tool === "sandbox.search" ? text(input.prefix, 1024) : void 0;
3572
- if (request.tool === "sandbox.search" && !query) return void 0;
3573
- return { kind: "query", ...query ? { query } : {}, ...scope ? { scope } : {} };
3574
- }
3575
- if (request.tool === "sandbox.apply_patch") {
3576
- return { kind: "patch", ...patchStats(input.patch) };
3577
- }
3578
- const recipeId = text(input.recipeId, 120);
3579
- return recipeId ? { kind: "recipe", recipeId } : void 0;
3580
- }
3581
- function codeToolResultPresentation(request, response2) {
3582
- const started = codeToolRequestPresentation(request);
3583
- if (!started || !response2.ok) return started;
3584
- const details = record4(response2.details);
3585
- if (started.kind === "read") {
3586
- return {
3587
- ...started,
3588
- ...integer2(details?.startLine) ? { startLine: integer2(details?.startLine) } : {},
3589
- ...integer2(details?.endLine) ? { endLine: integer2(details?.endLine) } : {},
3590
- ...excerpt(response2.content) ? { excerpt: excerpt(response2.content) } : {}
3591
- };
3592
- }
3593
- if (started.kind === "list") {
3594
- 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);
3595
- return {
3596
- ...started,
3597
- ...integer2(details?.count) !== void 0 ? { count: integer2(details?.count) } : {},
3598
- ...listed.length ? { paths: listed } : {}
3599
- };
3600
- }
3601
- if (started.kind === "query") {
3602
- const results = request.tool === "sandbox.search" ? searchResults(response2.content) : void 0;
3603
- const resultExcerpt = request.tool === "sandbox.search" ? void 0 : excerpt(response2.content);
3604
- return {
3605
- ...started,
3606
- ...integer2(details?.count) !== void 0 ? { count: integer2(details?.count) } : {},
3607
- ...results ? { results } : {},
3608
- ...resultExcerpt ? { excerpt: resultExcerpt } : {}
3609
- };
3610
- }
3611
- if (started.kind === "patch") {
3612
- return { ...started, ...paths(details?.paths) ? { paths: paths(details?.paths) } : {} };
3613
- }
3614
- const output = response2.content.replace(/^Recipe [^\n]*\.?\s*/u, "");
3615
- return {
3616
- ...started,
3617
- ...integer2(details?.exitCode) !== void 0 ? { exitCode: integer2(details?.exitCode) } : {},
3618
- ...typeof details?.timedOut === "boolean" ? { timedOut: details.timedOut } : {},
3619
- ...typeof details?.outputLimitExceeded === "boolean" ? { outputLimitExceeded: details.outputLimitExceeded } : {},
3620
- ...excerpt(output, true) ? { excerpt: excerpt(output, true) } : {}
3621
- };
3622
- }
3623
-
3624
3734
  // src/code-runtime-acknowledgement-gate.ts
3625
3735
  function codeRuntimeAcknowledgementGate(signal) {
3626
3736
  let settle;
@@ -3927,36 +4037,11 @@ var TheseusRuntimeEngine = class {
3927
4037
  }
3928
4038
  /** Report every brokered effect as it starts and finishes. */
3929
4039
  #observed(command, active, broker) {
3930
- return {
3931
- execute: async (context, request) => {
3932
- const startedAt = Date.now();
3933
- const operationId = digestRuntimeValue(`${command.commandId}:${request.requestId}`);
3934
- const startedPresentation = codeToolRequestPresentation(request);
3935
- await this.#event(
3936
- command,
3937
- {
3938
- type: "tool",
3939
- phase: "started",
3940
- tool: request.tool,
3941
- operationId,
3942
- ...startedPresentation ? { presentation: startedPresentation } : {}
3943
- },
3944
- active.conversationRefs
3945
- ).catch(() => void 0);
3946
- const response2 = await broker.execute(context, request);
3947
- const completedPresentation = codeToolResultPresentation(request, response2);
3948
- await this.#event(command, {
3949
- type: "tool",
3950
- phase: "completed",
3951
- tool: request.tool,
3952
- ok: response2.ok,
3953
- durationMs: Date.now() - startedAt,
3954
- operationId,
3955
- ...completedPresentation ? { presentation: completedPresentation } : {}
3956
- }, active.conversationRefs).catch(() => void 0);
3957
- return response2;
3958
- }
3959
- };
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
+ });
3960
4045
  }
3961
4046
  async #checkpoint(command) {
3962
4047
  const active = this.#active.get(command.sessionId);
@@ -4300,6 +4385,7 @@ async function installedDependencies(repoRoot) {
4300
4385
  V2_SYSTEM_PROMPT,
4301
4386
  V3_SYSTEM_PROMPT,
4302
4387
  applyCodePatch,
4388
+ applyPatchDialectToDiff,
4303
4389
  assertCodeBuildRecipe,
4304
4390
  assertDisjointPlan,
4305
4391
  assertPinnedImage,
@@ -4317,6 +4403,7 @@ async function installedDependencies(repoRoot) {
4317
4403
  describePatchFailure,
4318
4404
  digestStagedWorkspace,
4319
4405
  feedbackIsActionable,
4406
+ hasContextFreeHunk,
4320
4407
  hazardFromAttempt,
4321
4408
  installedDependencies,
4322
4409
  integrateSubGoals,