@chances-ai/engine 28.0.0 → 30.0.0

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 (151) hide show
  1. package/dist/agents/index.js +1 -1
  2. package/dist/ai/adapters/ai-sdk-stream.js +15 -0
  3. package/dist/ai/adapters/ai-sdk-stream.js.map +1 -1
  4. package/dist/ai/adapters/ai-sdk.js +1 -1
  5. package/dist/ai/adapters/ai-sdk.js.map +1 -1
  6. package/dist/ai/setup.d.ts +1 -1
  7. package/dist/ai/setup.js +1 -1
  8. package/dist/ai/types.d.ts +13 -1
  9. package/dist/ai/types.d.ts.map +1 -1
  10. package/dist/core/engine.d.ts +17 -3
  11. package/dist/core/engine.d.ts.map +1 -1
  12. package/dist/core/engine.js +49 -3
  13. package/dist/core/engine.js.map +1 -1
  14. package/dist/core/task-tool.d.ts +1 -1
  15. package/dist/core/task-tool.js +1 -1
  16. package/dist/core/workspace-query.d.ts +1 -1
  17. package/dist/core/workspace-query.js +1 -1
  18. package/dist/hashline/apply.d.ts +9 -0
  19. package/dist/hashline/apply.d.ts.map +1 -0
  20. package/dist/hashline/apply.js +523 -0
  21. package/dist/hashline/apply.js.map +1 -0
  22. package/dist/hashline/block.d.ts +25 -0
  23. package/dist/hashline/block.d.ts.map +1 -0
  24. package/dist/hashline/block.js +71 -0
  25. package/dist/hashline/block.js.map +1 -0
  26. package/dist/hashline/format.d.ts +106 -0
  27. package/dist/hashline/format.d.ts.map +1 -0
  28. package/dist/hashline/format.js +191 -0
  29. package/dist/hashline/format.js.map +1 -0
  30. package/dist/hashline/fs.d.ts +87 -0
  31. package/dist/hashline/fs.d.ts.map +1 -0
  32. package/dist/hashline/fs.js +123 -0
  33. package/dist/hashline/fs.js.map +1 -0
  34. package/dist/hashline/index.d.ts +27 -0
  35. package/dist/hashline/index.d.ts.map +1 -0
  36. package/dist/hashline/index.js +27 -0
  37. package/dist/hashline/index.js.map +1 -0
  38. package/dist/hashline/input.d.ts +101 -0
  39. package/dist/hashline/input.d.ts.map +1 -0
  40. package/dist/hashline/input.js +378 -0
  41. package/dist/hashline/input.js.map +1 -0
  42. package/dist/hashline/messages.d.ts +87 -0
  43. package/dist/hashline/messages.d.ts.map +1 -0
  44. package/dist/hashline/messages.js +94 -0
  45. package/dist/hashline/messages.js.map +1 -0
  46. package/dist/hashline/mismatch.d.ts +45 -0
  47. package/dist/hashline/mismatch.d.ts.map +1 -0
  48. package/dist/hashline/mismatch.js +118 -0
  49. package/dist/hashline/mismatch.js.map +1 -0
  50. package/dist/hashline/normalize.d.ts +22 -0
  51. package/dist/hashline/normalize.d.ts.map +1 -0
  52. package/dist/hashline/normalize.js +31 -0
  53. package/dist/hashline/normalize.js.map +1 -0
  54. package/dist/hashline/parser.d.ts +24 -0
  55. package/dist/hashline/parser.d.ts.map +1 -0
  56. package/dist/hashline/parser.js +295 -0
  57. package/dist/hashline/parser.js.map +1 -0
  58. package/dist/hashline/patcher.d.ts +111 -0
  59. package/dist/hashline/patcher.d.ts.map +1 -0
  60. package/dist/hashline/patcher.js +332 -0
  61. package/dist/hashline/patcher.js.map +1 -0
  62. package/dist/hashline/recovery.d.ts +41 -0
  63. package/dist/hashline/recovery.d.ts.map +1 -0
  64. package/dist/hashline/recovery.js +175 -0
  65. package/dist/hashline/recovery.js.map +1 -0
  66. package/dist/hashline/snapshots.d.ts +62 -0
  67. package/dist/hashline/snapshots.d.ts.map +1 -0
  68. package/dist/hashline/snapshots.js +127 -0
  69. package/dist/hashline/snapshots.js.map +1 -0
  70. package/dist/hashline/tokenizer.d.ts +66 -0
  71. package/dist/hashline/tokenizer.d.ts.map +1 -0
  72. package/dist/hashline/tokenizer.js +408 -0
  73. package/dist/hashline/tokenizer.js.map +1 -0
  74. package/dist/hashline/types.d.ts +117 -0
  75. package/dist/hashline/types.d.ts.map +1 -0
  76. package/dist/hashline/types.js +13 -0
  77. package/dist/hashline/types.js.map +1 -0
  78. package/dist/local-vault/index.d.ts +1 -1
  79. package/dist/local-vault/index.js +1 -1
  80. package/dist/lsp/index.d.ts +1 -1
  81. package/dist/lsp/index.js +1 -1
  82. package/dist/lsp/types.d.ts +2 -2
  83. package/dist/mcp/host.d.ts +3 -3
  84. package/dist/mcp/load-mcp-host.d.ts +4 -4
  85. package/dist/mcp/load-mcp-host.js +4 -4
  86. package/dist/mcp/oauth/provider.d.ts.map +1 -1
  87. package/dist/mcp/oauth/provider.js +10 -1
  88. package/dist/mcp/oauth/provider.js.map +1 -1
  89. package/dist/plugin-api/index.d.ts +10 -2
  90. package/dist/plugin-api/index.d.ts.map +1 -1
  91. package/dist/plugin-api/index.js +15 -0
  92. package/dist/plugin-api/index.js.map +1 -1
  93. package/dist/tools/approval.d.ts +1 -1
  94. package/dist/tools/approval.js +1 -1
  95. package/dist/tools/builtins/_hashline-fs.d.ts +16 -0
  96. package/dist/tools/builtins/_hashline-fs.d.ts.map +1 -0
  97. package/dist/tools/builtins/_hashline-fs.js +62 -0
  98. package/dist/tools/builtins/_hashline-fs.js.map +1 -0
  99. package/dist/tools/builtins/_image.d.ts +26 -0
  100. package/dist/tools/builtins/_image.d.ts.map +1 -0
  101. package/dist/tools/builtins/_image.js +76 -0
  102. package/dist/tools/builtins/_image.js.map +1 -0
  103. package/dist/tools/builtins/_login-shell.d.ts +17 -0
  104. package/dist/tools/builtins/_login-shell.d.ts.map +1 -0
  105. package/dist/tools/builtins/_login-shell.js +66 -0
  106. package/dist/tools/builtins/_login-shell.js.map +1 -0
  107. package/dist/tools/builtins/_notebook.d.ts +15 -0
  108. package/dist/tools/builtins/_notebook.d.ts.map +1 -0
  109. package/dist/tools/builtins/_notebook.js +81 -0
  110. package/dist/tools/builtins/_notebook.js.map +1 -0
  111. package/dist/tools/builtins/_pdf.d.ts +19 -0
  112. package/dist/tools/builtins/_pdf.d.ts.map +1 -0
  113. package/dist/tools/builtins/_pdf.js +42 -0
  114. package/dist/tools/builtins/_pdf.js.map +1 -0
  115. package/dist/tools/builtins/_shared.d.ts +11 -0
  116. package/dist/tools/builtins/_shared.d.ts.map +1 -1
  117. package/dist/tools/builtins/_shared.js +40 -1
  118. package/dist/tools/builtins/_shared.js.map +1 -1
  119. package/dist/tools/builtins/ast-edit.d.ts +18 -0
  120. package/dist/tools/builtins/ast-edit.d.ts.map +1 -0
  121. package/dist/tools/builtins/ast-edit.js +109 -0
  122. package/dist/tools/builtins/ast-edit.js.map +1 -0
  123. package/dist/tools/builtins/ast-grep.d.ts +6 -0
  124. package/dist/tools/builtins/ast-grep.d.ts.map +1 -0
  125. package/dist/tools/builtins/ast-grep.js +67 -0
  126. package/dist/tools/builtins/ast-grep.js.map +1 -0
  127. package/dist/tools/builtins/bash.d.ts.map +1 -1
  128. package/dist/tools/builtins/bash.js +13 -2
  129. package/dist/tools/builtins/bash.js.map +1 -1
  130. package/dist/tools/builtins/edit.d.ts.map +1 -1
  131. package/dist/tools/builtins/edit.js +112 -31
  132. package/dist/tools/builtins/edit.js.map +1 -1
  133. package/dist/tools/builtins/lsp.js +1 -1
  134. package/dist/tools/builtins/pty.d.ts +1 -1
  135. package/dist/tools/builtins/read.d.ts.map +1 -1
  136. package/dist/tools/builtins/read.js +187 -11
  137. package/dist/tools/builtins/read.js.map +1 -1
  138. package/dist/tools/builtins.d.ts.map +1 -1
  139. package/dist/tools/builtins.js +4 -0
  140. package/dist/tools/builtins.js.map +1 -1
  141. package/dist/tools/file-lock.d.ts +8 -0
  142. package/dist/tools/file-lock.d.ts.map +1 -1
  143. package/dist/tools/file-lock.js +22 -0
  144. package/dist/tools/file-lock.js.map +1 -1
  145. package/dist/tools/index.d.ts +1 -1
  146. package/dist/tools/index.d.ts.map +1 -1
  147. package/dist/tools/index.js.map +1 -1
  148. package/dist/tools/types.d.ts +27 -1
  149. package/dist/tools/types.d.ts.map +1 -1
  150. package/dist/tools/types.js.map +1 -1
  151. package/package.json +8 -3
@@ -0,0 +1,76 @@
1
+ /** Long-edge cap (px) — matches Anthropic's vision guidance; keeps the encoded
2
+ * image well under a sane per-image token budget. */
3
+ const MAX_EDGE = 1568;
4
+ /** Magic-byte → MIME sniffer for the formats we support. Returns null for non-images. */
5
+ export function sniffImageMime(buf) {
6
+ if (buf.length >= 8 && buf[0] === 0x89 && buf[1] === 0x50 && buf[2] === 0x4e && buf[3] === 0x47)
7
+ return "image/png";
8
+ if (buf.length >= 3 && buf[0] === 0xff && buf[1] === 0xd8 && buf[2] === 0xff)
9
+ return "image/jpeg";
10
+ if (buf.length >= 6 && buf[0] === 0x47 && buf[1] === 0x49 && buf[2] === 0x46 && buf[3] === 0x38)
11
+ return "image/gif";
12
+ if (buf.length >= 12 &&
13
+ buf[0] === 0x52 && buf[1] === 0x49 && buf[2] === 0x46 && buf[3] === 0x46 && // RIFF
14
+ buf[8] === 0x57 && buf[9] === 0x45 && buf[10] === 0x42 && buf[11] === 0x50 // WEBP
15
+ ) {
16
+ return "image/webp";
17
+ }
18
+ return null;
19
+ }
20
+ /** Map a sharp output format to a MIME type. */
21
+ function formatToMime(format, fallback) {
22
+ switch (format) {
23
+ case "png":
24
+ return "image/png";
25
+ case "jpeg":
26
+ case "jpg":
27
+ return "image/jpeg";
28
+ case "gif":
29
+ return "image/gif";
30
+ case "webp":
31
+ return "image/webp";
32
+ default:
33
+ return fallback;
34
+ }
35
+ }
36
+ /**
37
+ * Read `buf` (already sniffed as `mime`) into a vision-ready {@link ToolImagePart}.
38
+ * Resizes the long edge to {@link MAX_EDGE} (never enlarges) so the encoded image
39
+ * fits a sane token budget; returns base64 bytes + MIME. Without the `sharp`
40
+ * peer, returns an actionable `ok:false` instead of shipping a multi-MB original.
41
+ */
42
+ export async function readImageAsParts(buf, displayPath, mime) {
43
+ // Lazy optional peer: a non-literal specifier keeps it out of the type graph
44
+ // (sharp isn't a declared dependency), so a missing peer is a runtime null.
45
+ const specifier = "sharp";
46
+ const mod = (await import(specifier).catch(() => null));
47
+ const sharp = mod?.default;
48
+ if (typeof sharp !== "function") {
49
+ return {
50
+ ok: false,
51
+ output: `Cannot read image ${displayPath}: the optional 'sharp' peer is not installed. Run \`bun add sharp\` to enable image reading.`,
52
+ };
53
+ }
54
+ try {
55
+ const pipeline = sharp(buf);
56
+ const meta = await pipeline.metadata();
57
+ const w = meta.width ?? 0;
58
+ const h = meta.height ?? 0;
59
+ const needsResize = w > MAX_EDGE || h > MAX_EDGE;
60
+ const out = needsResize
61
+ ? await pipeline.resize({ width: MAX_EDGE, height: MAX_EDGE, fit: "inside", withoutEnlargement: true }).toBuffer()
62
+ : buf;
63
+ const outMime = formatToMime(meta.format, mime);
64
+ const dims = w && h ? ` ${w}×${h}` : "";
65
+ const resizedNote = needsResize ? ` (resized to fit ${MAX_EDGE}px for the model)` : "";
66
+ return {
67
+ ok: true,
68
+ output: `[image: ${displayPath}${dims}, ${outMime}${resizedNote}]`,
69
+ images: [{ data: out.toString("base64"), mimeType: outMime }],
70
+ };
71
+ }
72
+ catch (err) {
73
+ return { ok: false, output: `Failed to decode image ${displayPath}: ${err instanceof Error ? err.message : String(err)}` };
74
+ }
75
+ }
76
+ //# sourceMappingURL=_image.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_image.js","sourceRoot":"","sources":["../../../src/tools/builtins/_image.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /** Merge `login` PATH entries into `current`, appending only entries not already
2
+ * present (current dirs keep priority). Pure — the unit-testable core. */
3
+ export declare function mergePath(current: string, login: string): string;
4
+ /** Ask the login shell for its PATH (`$SHELL -lc 'printf %s "$PATH"'`). Returns
5
+ * the trimmed PATH, or null on any failure. Injectable for tests. */
6
+ export declare function resolveLoginPath(run?: (shell: string, args: string[]) => {
7
+ status: number | null;
8
+ stdout: string;
9
+ }): string | null;
10
+ /**
11
+ * Resolve + merge the login-shell PATH into `process.env.PATH` once per process.
12
+ * Best-effort and idempotent; safe to call before every bash run.
13
+ */
14
+ export declare function ensureLoginShellPath(): void;
15
+ /** Test-only: re-arm the one-shot guard. */
16
+ export declare function __resetLoginShellPath(): void;
17
+ //# sourceMappingURL=_login-shell.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_login-shell.d.ts","sourceRoot":"","sources":["../../../src/tools/builtins/_login-shell.ts"],"names":[],"mappings":"AAeA;0EAC0E;AAC1E,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAUhE;AAED;qEACqE;AACrE,wBAAgB,gBAAgB,CAC9B,GAAG,GAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK;IAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAG9E,GACA,MAAM,GAAG,IAAI,CAUf;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,IAAI,IAAI,CAQ3C;AAED,4CAA4C;AAC5C,wBAAgB,qBAAqB,IAAI,IAAI,CAE5C"}
@@ -0,0 +1,66 @@
1
+ /**
2
+ * (7.9 [5.9], goose) Login-shell PATH pre-resolution. A GUI-launched process
3
+ * (the Electron desktop, a double-clicked app) inherits a minimal `PATH` that
4
+ * omits the user's real toolchain dirs (`/opt/homebrew/bin`, nvm, cargo, …), so
5
+ * `bash` can't find `node`/`cargo`/`rg`. goose fixes this by asking the user's
6
+ * login shell for its `PATH` once and merging the missing entries into
7
+ * `process.env.PATH`, which every child process then inherits.
8
+ *
9
+ * One-shot + idempotent. No-op on Windows, when opted out
10
+ * (`CHANCES_NO_LOGIN_PATH=1`), or when the login shell can't be queried.
11
+ */
12
+ import { spawnSync } from "node:child_process";
13
+ let resolved = false;
14
+ /** Merge `login` PATH entries into `current`, appending only entries not already
15
+ * present (current dirs keep priority). Pure — the unit-testable core. */
16
+ export function mergePath(current, login) {
17
+ const out = current.split(":").filter(Boolean);
18
+ const seen = new Set(out);
19
+ for (const entry of login.split(":").filter(Boolean)) {
20
+ if (!seen.has(entry)) {
21
+ out.push(entry);
22
+ seen.add(entry);
23
+ }
24
+ }
25
+ return out.join(":");
26
+ }
27
+ /** Ask the login shell for its PATH (`$SHELL -lc 'printf %s "$PATH"'`). Returns
28
+ * the trimmed PATH, or null on any failure. Injectable for tests. */
29
+ export function resolveLoginPath(run = (shell, args) => {
30
+ const r = spawnSync(shell, args, { encoding: "utf8", timeout: 3000 });
31
+ return { status: r.status, stdout: r.stdout ?? "" };
32
+ }) {
33
+ const shell = process.env.SHELL || "/bin/bash";
34
+ try {
35
+ const r = run(shell, ["-lc", 'printf %s "$PATH"']);
36
+ if (r.status !== 0)
37
+ return null;
38
+ const path = r.stdout.trim();
39
+ return path.length > 0 ? path : null;
40
+ }
41
+ catch {
42
+ return null;
43
+ }
44
+ }
45
+ /**
46
+ * Resolve + merge the login-shell PATH into `process.env.PATH` once per process.
47
+ * Best-effort and idempotent; safe to call before every bash run.
48
+ */
49
+ export function ensureLoginShellPath() {
50
+ if (resolved)
51
+ return;
52
+ resolved = true;
53
+ if (process.platform === "win32")
54
+ return;
55
+ if (process.env.CHANCES_NO_LOGIN_PATH === "1")
56
+ return;
57
+ const login = resolveLoginPath();
58
+ if (!login)
59
+ return;
60
+ process.env.PATH = mergePath(process.env.PATH ?? "", login);
61
+ }
62
+ /** Test-only: re-arm the one-shot guard. */
63
+ export function __resetLoginShellPath() {
64
+ resolved = false;
65
+ }
66
+ //# sourceMappingURL=_login-shell.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_login-shell.js","sourceRoot":"","sources":["../../../src/tools/builtins/_login-shell.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAE/C,IAAI,QAAQ,GAAG,KAAK,CAAC;AAErB;0EAC0E;AAC1E,MAAM,UAAU,SAAS,CAAC,OAAe,EAAE,KAAa;IACtD,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC/C,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;IAC1B,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;QACrD,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YACrB,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAChB,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACvB,CAAC;AAED;qEACqE;AACrE,MAAM,UAAU,gBAAgB,CAC9B,MAAoF,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;IAClG,MAAM,CAAC,GAAG,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;IACtE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC;AACtD,CAAC;IAED,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,WAAW,CAAC;IAC/C,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,GAAG,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,mBAAmB,CAAC,CAAC,CAAC;QACnD,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;QAChC,MAAM,IAAI,GAAG,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QAC7B,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;IACvC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,oBAAoB;IAClC,IAAI,QAAQ;QAAE,OAAO;IACrB,QAAQ,GAAG,IAAI,CAAC;IAChB,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO;QAAE,OAAO;IACzC,IAAI,OAAO,CAAC,GAAG,CAAC,qBAAqB,KAAK,GAAG;QAAE,OAAO;IACtD,MAAM,KAAK,GAAG,gBAAgB,EAAE,CAAC;IACjC,IAAI,CAAC,KAAK;QAAE,OAAO;IACnB,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,EAAE,KAAK,CAAC,CAAC;AAC9D,CAAC;AAED,4CAA4C;AAC5C,MAAM,UAAU,qBAAqB;IACnC,QAAQ,GAAG,KAAK,CAAC;AACnB,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Jupyter notebook (`.ipynb`) rendering for the `read` tool (7.9 [5.5], the
3
+ * "notebooks last" stage of the staged multimodal decision — delivered this
4
+ * task, no longer deferred). A notebook is JSON, so reading the raw file would
5
+ * dump unreadable escaped source + base64 output blobs at the model. Instead we
6
+ * parse `cells[]` and render a compact, legible cell view (source + text
7
+ * outputs). This is a READ-ONLY view: it carries no `¶path#tag` hashline header
8
+ * because the model must not line-edit a rendered notebook — to change a
9
+ * notebook, edit the raw `.ipynb` JSON (a future NotebookEdit tool). No external
10
+ * dependency: pure `JSON.parse`.
11
+ */
12
+ import type { ToolResult } from "../types.js";
13
+ /** Render an `.ipynb` JSON document as a compact, read-only cell view. */
14
+ export declare function renderNotebook(raw: string, displayPath: string): ToolResult;
15
+ //# sourceMappingURL=_notebook.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_notebook.d.ts","sourceRoot":"","sources":["../../../src/tools/builtins/_notebook.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AA6D9C,0EAA0E;AAC1E,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,UAAU,CA+B3E"}
@@ -0,0 +1,81 @@
1
+ /** Char budget for the rendered notebook before truncation (≈ read token cap). */
2
+ const MAX_RENDER_CHARS = 200_000;
3
+ /** Per-cell output char cap so one chatty cell can't dominate the render. */
4
+ const MAX_OUTPUT_CHARS = 4_000;
5
+ /** `.ipynb` source/text fields are either a string or an array of line strings. */
6
+ function joinSource(src) {
7
+ if (Array.isArray(src))
8
+ return src.join("");
9
+ return typeof src === "string" ? src : "";
10
+ }
11
+ function stripAnsi(text) {
12
+ // Strip terminal control sequences that show up in stream/traceback output.
13
+ // biome-ignore lint/suspicious/noControlCharactersInRegex: stripping ANSI by design.
14
+ return text.replace(/\[[0-9;]*m/g, "");
15
+ }
16
+ function renderOutputs(outputs) {
17
+ const blocks = [];
18
+ for (const out of outputs) {
19
+ switch (out.output_type) {
20
+ case "stream":
21
+ blocks.push(stripAnsi(joinSource(out.text)));
22
+ break;
23
+ case "execute_result":
24
+ case "display_data": {
25
+ const plain = out.data?.["text/plain"];
26
+ if (plain !== undefined)
27
+ blocks.push(joinSource(plain));
28
+ else if (out.data)
29
+ blocks.push(`[${Object.keys(out.data).join(", ")} output]`);
30
+ break;
31
+ }
32
+ case "error":
33
+ blocks.push(stripAnsi([`${out.ename ?? "Error"}: ${out.evalue ?? ""}`, ...(out.traceback ?? [])].join("\n")));
34
+ break;
35
+ default:
36
+ break;
37
+ }
38
+ }
39
+ let text = blocks.join("\n").replace(/\n+$/, "");
40
+ if (text.length > MAX_OUTPUT_CHARS)
41
+ text = `${text.slice(0, MAX_OUTPUT_CHARS)}\n… [output truncated]`;
42
+ return text;
43
+ }
44
+ /** Render an `.ipynb` JSON document as a compact, read-only cell view. */
45
+ export function renderNotebook(raw, displayPath) {
46
+ let nb;
47
+ try {
48
+ nb = JSON.parse(raw);
49
+ }
50
+ catch (err) {
51
+ return { ok: false, output: `Not a valid .ipynb (JSON parse failed) ${displayPath}: ${err instanceof Error ? err.message : String(err)}` };
52
+ }
53
+ const cells = Array.isArray(nb.cells) ? nb.cells : null;
54
+ if (!cells)
55
+ return { ok: false, output: `No cells[] found in ${displayPath} — not a Jupyter notebook.` };
56
+ const parts = [
57
+ `[notebook: ${displayPath}, ${cells.length} cell(s) — read-only rendering; edit the raw .ipynb JSON to change it]`,
58
+ ];
59
+ let truncated = false;
60
+ for (let i = 0; i < cells.length; i++) {
61
+ if (parts.join("\n").length > MAX_RENDER_CHARS) {
62
+ truncated = true;
63
+ break;
64
+ }
65
+ const cell = cells[i];
66
+ const type = cell.cell_type ?? "unknown";
67
+ const src = joinSource(cell.source).replace(/\n$/, "");
68
+ parts.push(`\n# Cell ${i + 1} · ${type}`);
69
+ if (src.length > 0)
70
+ parts.push(src);
71
+ if (type === "code" && Array.isArray(cell.outputs) && cell.outputs.length > 0) {
72
+ const outText = renderOutputs(cell.outputs);
73
+ if (outText.length > 0)
74
+ parts.push(`## Output:\n${outText}`);
75
+ }
76
+ }
77
+ if (truncated)
78
+ parts.push(`\n… [notebook truncated at ${MAX_RENDER_CHARS} chars — open the raw file for the rest]`);
79
+ return { ok: true, output: parts.join("\n") };
80
+ }
81
+ //# sourceMappingURL=_notebook.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_notebook.js","sourceRoot":"","sources":["../../../src/tools/builtins/_notebook.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * PDF text extraction for the `read` tool (7.9 [5.5], the "PDF after image"
3
+ * stage — delivered this task, no longer deferred). PDFs are binary, so they
4
+ * route here before the binary reject (like images). Text is extracted via
5
+ * `unpdf` — a LAZY optional peer (absent ⇒ a clear `bun add unpdf` hint; the
6
+ * tool degrades, nothing else breaks), mirroring the `sharp` image peer. The
7
+ * extracted text is a READ-ONLY view (no `¶path#tag`): the model cannot
8
+ * line-edit a PDF.
9
+ */
10
+ import type { ToolResult } from "../types.js";
11
+ /** Magic-byte sniff: a PDF starts with `%PDF`. */
12
+ export declare function sniffPdf(buf: Buffer): boolean;
13
+ /**
14
+ * Extract text from a PDF `buf` into a read-only tool result. Without the
15
+ * `unpdf` peer, returns an actionable `ok:false` instead of refusing as a
16
+ * generic binary file.
17
+ */
18
+ export declare function readPdfAsText(buf: Buffer, displayPath: string): Promise<ToolResult>;
19
+ //# sourceMappingURL=_pdf.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_pdf.d.ts","sourceRoot":"","sources":["../../../src/tools/builtins/_pdf.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAK9C,kDAAkD;AAClD,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAE7C;AAUD;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CA4BzF"}
@@ -0,0 +1,42 @@
1
+ /** Char budget for extracted PDF text before truncation (≈ read token cap). */
2
+ const MAX_TEXT_CHARS = 200_000;
3
+ /** Magic-byte sniff: a PDF starts with `%PDF`. */
4
+ export function sniffPdf(buf) {
5
+ return buf.length >= 5 && buf[0] === 0x25 && buf[1] === 0x50 && buf[2] === 0x44 && buf[3] === 0x46;
6
+ }
7
+ /**
8
+ * Extract text from a PDF `buf` into a read-only tool result. Without the
9
+ * `unpdf` peer, returns an actionable `ok:false` instead of refusing as a
10
+ * generic binary file.
11
+ */
12
+ export async function readPdfAsText(buf, displayPath) {
13
+ // Lazy optional peer: a non-literal specifier keeps it out of the type graph
14
+ // (unpdf isn't a declared dependency), so a missing peer is a runtime null.
15
+ const specifier = "unpdf";
16
+ const mod = (await import(specifier).catch(() => null));
17
+ if (!mod || typeof mod.getDocumentProxy !== "function" || typeof mod.extractText !== "function") {
18
+ return {
19
+ ok: false,
20
+ output: `Cannot read PDF ${displayPath}: the optional 'unpdf' peer is not installed. Run \`bun add unpdf\` to enable PDF reading.`,
21
+ };
22
+ }
23
+ try {
24
+ const doc = await mod.getDocumentProxy(new Uint8Array(buf));
25
+ const { totalPages, text } = await mod.extractText(doc, { mergePages: true });
26
+ let body = Array.isArray(text) ? text.join("\n\n") : String(text);
27
+ let truncated = false;
28
+ if (body.length > MAX_TEXT_CHARS) {
29
+ body = body.slice(0, MAX_TEXT_CHARS);
30
+ truncated = true;
31
+ }
32
+ const note = truncated ? `\n\n… [PDF text truncated at ${MAX_TEXT_CHARS} chars]` : "";
33
+ return {
34
+ ok: true,
35
+ output: `[pdf: ${displayPath}, ${totalPages} page(s), text extracted — read-only]\n\n${body}${note}`,
36
+ };
37
+ }
38
+ catch (err) {
39
+ return { ok: false, output: `Failed to extract PDF text from ${displayPath}: ${err instanceof Error ? err.message : String(err)}` };
40
+ }
41
+ }
42
+ //# sourceMappingURL=_pdf.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_pdf.js","sourceRoot":"","sources":["../../../src/tools/builtins/_pdf.ts"],"names":[],"mappings":"AAWA,+EAA+E;AAC/E,MAAM,cAAc,GAAG,OAAO,CAAC;AAE/B,kDAAkD;AAClD,MAAM,UAAU,QAAQ,CAAC,GAAW;IAClC,OAAO,GAAG,CAAC,MAAM,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;AACrG,CAAC;AAUD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,GAAW,EAAE,WAAmB;IAClE,6EAA6E;IAC7E,4EAA4E;IAC5E,MAAM,SAAS,GAAG,OAAO,CAAC;IAC1B,MAAM,GAAG,GAAG,CAAC,MAAM,MAAM,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAuB,CAAC;IAC9E,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,CAAC,gBAAgB,KAAK,UAAU,IAAI,OAAO,GAAG,CAAC,WAAW,KAAK,UAAU,EAAE,CAAC;QAChG,OAAO;YACL,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,mBAAmB,WAAW,4FAA4F;SACnI,CAAC;IACJ,CAAC;IACD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,gBAAgB,CAAC,IAAI,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;QAC5D,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,GAAG,MAAM,GAAG,CAAC,WAAW,CAAC,GAAG,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9E,IAAI,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAClE,IAAI,SAAS,GAAG,KAAK,CAAC;QACtB,IAAI,IAAI,CAAC,MAAM,GAAG,cAAc,EAAE,CAAC;YACjC,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC;YACrC,SAAS,GAAG,IAAI,CAAC;QACnB,CAAC;QACD,MAAM,IAAI,GAAG,SAAS,CAAC,CAAC,CAAC,gCAAgC,cAAc,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;QACtF,OAAO;YACL,EAAE,EAAE,IAAI;YACR,MAAM,EAAE,SAAS,WAAW,KAAK,UAAU,4CAA4C,IAAI,GAAG,IAAI,EAAE;SACrG,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,mCAAmC,WAAW,KAAK,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;IACtI,CAAC;AACH,CAAC"}
@@ -45,6 +45,12 @@ export declare function guardWrite(ctx: ToolContext, p: string): string;
45
45
  export declare function safePath(ctx: ToolContext, p: string, opts?: {
46
46
  resolveSymlinks?: boolean;
47
47
  }): string;
48
+ /** **Hashline snapshot key.** The canonical absolute path under which `read`
49
+ * records a file's full-text snapshot and `edit`'s patcher resolves the section
50
+ * tag — both MUST agree or every edit would re-read. Lexical `resolve(cwd, p)`
51
+ * (NOT realpath): it must match how the model re-states the path in a patch
52
+ * header, and the realpath jail already runs at write time. (7.9) */
53
+ export declare function hashlineSnapshotKey(ctx: ToolContext, p: string): string;
48
54
  /** Atomically write `body` to `path`: write a sibling temp file then `rename`
49
55
  * over the target (rename is atomic within a filesystem), so a crash mid-write
50
56
  * never leaves a half-written file. Creates parent dirs. The temp lives in the
@@ -82,5 +88,10 @@ export declare function safeArtifactId(raw: string): string;
82
88
  * bit on Windows; ACL-based access control is not enforced via this
83
89
  * argument. POSIX-first audience; explicit DACL hardening is a follow-up.
84
90
  */
91
+ /** (7.9 [5.10]) Bound the `.chances/tool-results/` ring: keep the `max`
92
+ * most-recently-modified artifact dirs, delete the rest. Best-effort — a prune
93
+ * failure never affects the tool result. Called after a bash persist so a long
94
+ * session's persisted outputs can't grow unbounded. */
95
+ export declare function pruneToolResultsRing(workspaceRoot: string, max?: number): void;
85
96
  export declare function persistFullOutput(workspaceRoot: string, body: string, prefix?: string, filename?: string, id?: string): string | null;
86
97
  //# sourceMappingURL=_shared.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"_shared.d.ts","sourceRoot":"","sources":["../../../src/tools/builtins/_shared.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAErD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C;;sDAEsD;AACtD,eAAO,MAAM,gBAAgB,QAAa,CAAC;AAE3C,wBAAgB,GAAG,CAAC,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAIxD;AAED,wBAAgB,MAAM,CAAC,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAKvE;AAED,wBAAgB,MAAM,CAAC,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAOvE;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAKzE;AAED;;;;;;;yCAOyC;AACzC,wBAAgB,eAAe,CAAC,GAAG,EAAE,WAAW,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAOnE;AAED;;;;;;;;;;;;mCAYmC;AACnC,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,WAAW,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAOpE;AAED;;;;;wEAKwE;AACxE,wBAAgB,UAAU,CAAC,GAAG,EAAE,WAAW,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAU9D;AAED;;;eAGe;AACf,wBAAgB,QAAQ,CAAC,GAAG,EAAE,WAAW,EAAE,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;IAAE,eAAe,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,MAAM,CAGlG;AAED;;;kEAGkE;AAClE,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAahE;AAED,6EAA6E;AAC7E,wBAAgB,OAAO,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAGzC;AAaD,OAAO,EAAE,WAAW,EAAE,oBAAoB,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAEnF;;;;;;;;;;;mFAWmF;AACnF,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAGlD;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,iBAAiB,CAC/B,aAAa,EAAE,MAAM,EACrB,IAAI,EAAE,MAAM,EACZ,MAAM,SAAS,EACf,QAAQ,SAAe,EACvB,EAAE,CAAC,EAAE,MAAM,GACV,MAAM,GAAG,IAAI,CAef"}
1
+ {"version":3,"file":"_shared.d.ts","sourceRoot":"","sources":["../../../src/tools/builtins/_shared.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAErD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C;;sDAEsD;AACtD,eAAO,MAAM,gBAAgB,QAAa,CAAC;AAE3C,wBAAgB,GAAG,CAAC,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAIxD;AAED,wBAAgB,MAAM,CAAC,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAKvE;AAED,wBAAgB,MAAM,CAAC,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAOvE;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAKzE;AAED;;;;;;;yCAOyC;AACzC,wBAAgB,eAAe,CAAC,GAAG,EAAE,WAAW,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAOnE;AAED;;;;;;;;;;;;mCAYmC;AACnC,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,WAAW,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAOpE;AAED;;;;;wEAKwE;AACxE,wBAAgB,UAAU,CAAC,GAAG,EAAE,WAAW,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAU9D;AAED;;;eAGe;AACf,wBAAgB,QAAQ,CAAC,GAAG,EAAE,WAAW,EAAE,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;IAAE,eAAe,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,MAAM,CAGlG;AAED;;;;qEAIqE;AACrE,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,WAAW,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAEvE;AAED;;;kEAGkE;AAClE,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAahE;AAED,6EAA6E;AAC7E,wBAAgB,OAAO,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAGzC;AAaD,OAAO,EAAE,WAAW,EAAE,oBAAoB,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAEnF;;;;;;;;;;;mFAWmF;AACnF,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAGlD;AAED;;;;;;;;;;;;;;;GAeG;AACH;;;uDAGuD;AACvD,wBAAgB,oBAAoB,CAAC,aAAa,EAAE,MAAM,EAAE,GAAG,SAAM,GAAG,IAAI,CAuB3E;AAED,wBAAgB,iBAAiB,CAC/B,aAAa,EAAE,MAAM,EACrB,IAAI,EAAE,MAAM,EACZ,MAAM,SAAS,EACf,QAAQ,SAAe,EACvB,EAAE,CAAC,EAAE,MAAM,GACV,MAAM,GAAG,IAAI,CAef"}
@@ -1,5 +1,5 @@
1
1
  import { createHash } from "node:crypto";
2
- import { chmodSync, mkdirSync, renameSync, statSync, writeFileSync } from "node:fs";
2
+ import { chmodSync, mkdirSync, readdirSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
3
3
  import { dirname, isAbsolute, join, relative, resolve } from "node:path";
4
4
  import { native } from "@chances-ai/native";
5
5
  import { AppError, ErrorCode, createId, currentCwdOverride } from "@chances-ai/runtime";
@@ -98,6 +98,14 @@ export function safePath(ctx, p, opts) {
98
98
  const isolated = currentCwdOverride() !== undefined;
99
99
  return isolated || opts?.resolveSymlinks ? containWritePath(ctx, p) : containReadPath(ctx, p);
100
100
  }
101
+ /** **Hashline snapshot key.** The canonical absolute path under which `read`
102
+ * records a file's full-text snapshot and `edit`'s patcher resolves the section
103
+ * tag — both MUST agree or every edit would re-read. Lexical `resolve(cwd, p)`
104
+ * (NOT realpath): it must match how the model re-states the path in a patch
105
+ * header, and the realpath jail already runs at write time. (7.9) */
106
+ export function hashlineSnapshotKey(ctx, p) {
107
+ return isAbsolute(p) ? p : resolve(ctx.cwd, p);
108
+ }
101
109
  /** Atomically write `body` to `path`: write a sibling temp file then `rename`
102
110
  * over the target (rename is atomic within a filesystem), so a crash mid-write
103
111
  * never leaves a half-written file. Creates parent dirs. The temp lives in the
@@ -167,6 +175,37 @@ export function safeArtifactId(raw) {
167
175
  * bit on Windows; ACL-based access control is not enforced via this
168
176
  * argument. POSIX-first audience; explicit DACL hardening is a follow-up.
169
177
  */
178
+ /** (7.9 [5.10]) Bound the `.chances/tool-results/` ring: keep the `max`
179
+ * most-recently-modified artifact dirs, delete the rest. Best-effort — a prune
180
+ * failure never affects the tool result. Called after a bash persist so a long
181
+ * session's persisted outputs can't grow unbounded. */
182
+ export function pruneToolResultsRing(workspaceRoot, max = 100) {
183
+ try {
184
+ const dir = join(workspaceRoot, ".chances", "tool-results");
185
+ const entries = readdirSync(dir, { withFileTypes: true }).filter((e) => e.isDirectory());
186
+ if (entries.length <= max)
187
+ return;
188
+ const byMtime = entries
189
+ .map((e) => {
190
+ const full = join(dir, e.name);
191
+ let mtimeMs = 0;
192
+ try {
193
+ mtimeMs = statSync(full).mtimeMs;
194
+ }
195
+ catch {
196
+ /* racing removal — treat as oldest */
197
+ }
198
+ return { full, mtimeMs };
199
+ })
200
+ .sort((a, b) => a.mtimeMs - b.mtimeMs);
201
+ for (const victim of byMtime.slice(0, byMtime.length - max)) {
202
+ rmSync(victim.full, { recursive: true, force: true });
203
+ }
204
+ }
205
+ catch {
206
+ /* best-effort */
207
+ }
208
+ }
170
209
  export function persistFullOutput(workspaceRoot, body, prefix = "tool", filename = "output.txt", id) {
171
210
  try {
172
211
  // `id !== undefined` (not truthiness) so an empty-string call id still
@@ -1 +1 @@
1
- {"version":3,"file":"_shared.js","sourceRoot":"","sources":["../../../src/tools/builtins/_shared.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"_shared.js","sourceRoot":"","sources":["../../../src/tools/builtins/_shared.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import type { Tool } from "../types.js";
2
+ /**
3
+ * Structural rewrite across files (ast-grep `pattern` → `rewrite`). High-risk:
4
+ * the native pass walks a directory and rewrites every match, so the TS wrapper
5
+ * (R1-M2) enforces the workspace's write safety the native layer can't:
6
+ *
7
+ * 1. realpath-jail the search root;
8
+ * 2. dry-run to learn the affected file set;
9
+ * 3. `guardWrite` EVERY affected file (jail + protected-path floor) — any
10
+ * failure aborts the whole pass with zero writes;
11
+ * 4. hold all affected files' mutation locks (sorted, deadlock-free);
12
+ * 5. only then run the real (write) pass; invalidate fs-scan caches.
13
+ *
14
+ * The `permission()` hook scopes the approval cache to `ctx.callId`, so every
15
+ * invocation re-prompts — ast_edit is never auto-approved (R1-OQ6).
16
+ */
17
+ export declare const astEditTool: Tool;
18
+ //# sourceMappingURL=ast-edit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ast-edit.d.ts","sourceRoot":"","sources":["../../../src/tools/builtins/ast-edit.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAwB,IAAI,EAA2B,MAAM,aAAa,CAAC;AAIvF;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,WAAW,EAAE,IAuFzB,CAAC"}
@@ -0,0 +1,109 @@
1
+ import { dirname, join } from "node:path";
2
+ import { native } from "@chances-ai/native";
3
+ import { withSortedFileLocks } from "../file-lock.js";
4
+ import { astErr } from "./ast-grep.js";
5
+ import { containWritePath, guardWrite, optStr, preview, str } from "./_shared.js";
6
+ /**
7
+ * Structural rewrite across files (ast-grep `pattern` → `rewrite`). High-risk:
8
+ * the native pass walks a directory and rewrites every match, so the TS wrapper
9
+ * (R1-M2) enforces the workspace's write safety the native layer can't:
10
+ *
11
+ * 1. realpath-jail the search root;
12
+ * 2. dry-run to learn the affected file set;
13
+ * 3. `guardWrite` EVERY affected file (jail + protected-path floor) — any
14
+ * failure aborts the whole pass with zero writes;
15
+ * 4. hold all affected files' mutation locks (sorted, deadlock-free);
16
+ * 5. only then run the real (write) pass; invalidate fs-scan caches.
17
+ *
18
+ * The `permission()` hook scopes the approval cache to `ctx.callId`, so every
19
+ * invocation re-prompts — ast_edit is never auto-approved (R1-OQ6).
20
+ */
21
+ export const astEditTool = {
22
+ name: "ast_edit",
23
+ category: "file-write",
24
+ description: "Structural find-and-replace across files with an ast-grep pattern → rewrite (e.g. `console.log($A)` → " +
25
+ "`logger.info($A)`). Matches by SYNTAX and rewrites every occurrence under `path` (a file or directory, " +
26
+ "default: workspace root), so it is the right tool for a global rename/refactor that `edit` would need many " +
27
+ "hunks for. Each run is previewed (dry-run) and requires explicit approval — it can touch many files. " +
28
+ "`$A`/`$$$` metavariables captured by the pattern can be referenced in the rewrite.",
29
+ parameters: {
30
+ type: "object",
31
+ properties: {
32
+ pattern: { type: "string" },
33
+ rewrite: { type: "string", description: "Replacement template; may reference $A/$$$ metavars from the pattern." },
34
+ path: { type: "string", description: "File or directory to rewrite (default: workspace root)." },
35
+ lang: { type: "string" },
36
+ glob: { type: "string", description: "Glob filter for relative paths in a directory walk." },
37
+ },
38
+ required: ["pattern", "rewrite"],
39
+ },
40
+ // Never auto-approve: a per-call cacheKey means the gate prompts every time.
41
+ permission(args, ctx) {
42
+ return {
43
+ name: "ast_edit",
44
+ category: "file-write",
45
+ summary: `ast_edit (structural rewrite, may touch multiple files): ${preview(str(args, "pattern"))} → ${preview(str(args, "rewrite"))}${optStr(args, "path") ? ` under ${optStr(args, "path")}` : ""}`,
46
+ args,
47
+ cacheKey: `ast_edit:${ctx.callId ?? "no-call"}`,
48
+ };
49
+ },
50
+ summarize: (args) => {
51
+ const where = optStr(args, "path");
52
+ return `ast_edit ${preview(str(args, "pattern"))} → ${preview(str(args, "rewrite"))}${where ? ` under ${where}` : ""}`;
53
+ },
54
+ async execute(args, ctx) {
55
+ const pattern = str(args, "pattern");
56
+ const rewrite = str(args, "rewrite");
57
+ const lang = optStr(args, "lang");
58
+ const glob = optStr(args, "glob");
59
+ // (R1-M2 step 1) realpath-jail the search root within the workspace.
60
+ let root;
61
+ try {
62
+ root = containWritePath(ctx, optStr(args, "path") ?? ".");
63
+ }
64
+ catch (err) {
65
+ return { ok: false, output: err instanceof Error ? err.message : String(err) };
66
+ }
67
+ // (R1-M2 step 2) dry-run to learn the affected file set.
68
+ let dry;
69
+ try {
70
+ dry = await native.astEdit({ pattern, rewrite, path: root, lang, glob, dryRun: true });
71
+ }
72
+ catch (err) {
73
+ return { ok: false, output: astErr(err, "ast_edit") };
74
+ }
75
+ if (dry.replacements === 0) {
76
+ return { ok: true, output: `No matches for ${JSON.stringify(pattern)} — nothing rewritten.` };
77
+ }
78
+ // (R1-M2 step 3) guardWrite EVERY affected file (jail + protected floor).
79
+ // Any rejection aborts before a single byte is written.
80
+ const affected = dry.files.map((f) => join(root, f.path));
81
+ try {
82
+ for (const abs of affected)
83
+ guardWrite(ctx, abs);
84
+ }
85
+ catch (err) {
86
+ return { ok: false, output: `ast_edit refused: ${err instanceof Error ? err.message : String(err)}` };
87
+ }
88
+ // (R1-M2 steps 4-5) hold all locks, run the real pass, invalidate caches.
89
+ return withSortedFileLocks(affected, async () => {
90
+ let result;
91
+ try {
92
+ result = await native.astEdit({ pattern, rewrite, path: root, lang, glob, dryRun: false });
93
+ }
94
+ catch (err) {
95
+ return { ok: false, output: astErr(err, "ast_edit") };
96
+ }
97
+ for (const dir of new Set(affected.map((p) => dirname(p)))) {
98
+ native.invalidateFsScanCache(dir);
99
+ }
100
+ const fileList = result.files.map((f) => ` ${f.path} (${f.count})`).join("\n");
101
+ return {
102
+ ok: true,
103
+ output: `Rewrote ${result.replacements} occurrence(s) across ${result.files.length} file(s). ` +
104
+ `Re-read any file before a follow-up hashline edit (its tag changed):\n${fileList}`,
105
+ };
106
+ });
107
+ },
108
+ };
109
+ //# sourceMappingURL=ast-edit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ast-edit.js","sourceRoot":"","sources":["../../../src/tools/builtins/ast-edit.ts"],"names":[],"mappings":"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"}