@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,6 @@
1
+ import type { Tool } from "../types.js";
2
+ /** Turn an `AST_UNAVAILABLE`/native error into model-facing guidance. */
3
+ declare function astErr(err: unknown, tool: string): string;
4
+ export declare const astGrepTool: Tool;
5
+ export { astErr };
6
+ //# sourceMappingURL=ast-grep.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ast-grep.d.ts","sourceRoot":"","sources":["../../../src/tools/builtins/ast-grep.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAc,MAAM,aAAa,CAAC;AASpD,yEAAyE;AACzE,iBAAS,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAMlD;AAED,eAAO,MAAM,WAAW,EAAE,IAiDzB,CAAC;AAEF,OAAO,EAAE,MAAM,EAAE,CAAC"}
@@ -0,0 +1,67 @@
1
+ import { native } from "@chances-ai/native";
2
+ import { containReadPath, optNum, optStr, preview, str } from "./_shared.js";
3
+ /** Collapse a (possibly multi-line) match to a single trimmed preview line. */
4
+ function oneLine(text, max = 100) {
5
+ const flat = text.replace(/\s+/g, " ").trim();
6
+ return flat.length > max ? `${flat.slice(0, max)}…` : flat;
7
+ }
8
+ /** Turn an `AST_UNAVAILABLE`/native error into model-facing guidance. */
9
+ function astErr(err, tool) {
10
+ const msg = err instanceof Error ? err.message : String(err);
11
+ if (/AST|unavailable|not a function/i.test(msg)) {
12
+ return `${tool} is unavailable in this build (the native tree-sitter module is absent). Use grep for a text search instead.`;
13
+ }
14
+ return `${tool} failed: ${msg}`;
15
+ }
16
+ export const astGrepTool = {
17
+ name: "ast_grep",
18
+ category: "file-read",
19
+ description: "Structural code search with an ast-grep pattern (e.g. `console.log($A)`, `function $F($$$) { $$$ }`). " +
20
+ "Matches by SYNTAX, not text — robust to formatting, whitespace, and line breaks. Returns `path:line:col` " +
21
+ "hits. Prefer over `grep` when you want to match a code shape rather than a string. `path` may be a file or " +
22
+ "directory (default: workspace root); `lang` is inferred from extension; `glob` filters a directory walk.",
23
+ parameters: {
24
+ type: "object",
25
+ properties: {
26
+ pattern: { type: "string" },
27
+ path: { type: "string", description: "File or directory to search (default: workspace root)." },
28
+ lang: { type: "string", description: "Language alias (e.g. ts, rust); inferred from extension if omitted." },
29
+ glob: { type: "string", description: "Glob filter for relative paths in a directory search." },
30
+ limit: { type: "number", description: "Max matches to return (default 100)." },
31
+ },
32
+ required: ["pattern"],
33
+ },
34
+ summarize: (args) => {
35
+ const where = optStr(args, "path");
36
+ return `ast-grep ${preview(str(args, "pattern"))}${where ? ` in ${where}` : ""}`;
37
+ },
38
+ async execute(args, ctx) {
39
+ const pattern = str(args, "pattern");
40
+ const path = containReadPath(ctx, optStr(args, "path") ?? ".");
41
+ try {
42
+ const res = await native.astGrep({
43
+ pattern,
44
+ path,
45
+ lang: optStr(args, "lang"),
46
+ glob: optStr(args, "glob"),
47
+ limit: optNum(args, "limit"),
48
+ });
49
+ if (res.matches.length === 0) {
50
+ return { ok: true, output: `No matches for ${JSON.stringify(pattern)} (searched ${res.filesSearched} file(s)).` };
51
+ }
52
+ const lines = res.matches.map((m) => `${m.path}:${m.startLine}:${m.startColumn} ${oneLine(m.text)}`);
53
+ const more = res.limitReached
54
+ ? `\n… ${res.totalMatches} total matches; showing ${res.matches.length}. Raise limit or narrow the pattern.`
55
+ : "";
56
+ return {
57
+ ok: true,
58
+ output: `${res.totalMatches} match(es) across ${res.filesSearched} file(s):\n${lines.join("\n")}${more}`,
59
+ };
60
+ }
61
+ catch (err) {
62
+ return { ok: false, output: astErr(err, "ast_grep") };
63
+ }
64
+ },
65
+ };
66
+ export { astErr };
67
+ //# sourceMappingURL=ast-grep.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ast-grep.js","sourceRoot":"","sources":["../../../src/tools/builtins/ast-grep.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"bash.d.ts","sourceRoot":"","sources":["../../../src/tools/builtins/bash.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAc,MAAM,aAAa,CAAC;AA6GpD,eAAO,MAAM,QAAQ,EAAE,IA2EtB,CAAC"}
1
+ {"version":3,"file":"bash.d.ts","sourceRoot":"","sources":["../../../src/tools/builtins/bash.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAc,MAAM,aAAa,CAAC;AAoHpD,eAAO,MAAM,QAAQ,EAAE,IA+EtB,CAAC"}
@@ -1,6 +1,7 @@
1
1
  import { native } from "@chances-ai/native";
2
2
  import { isBashCommandReadOnly } from "../bash-readonly.js";
3
- import { cleanOutput, optNum, persistFullOutput, str } from "./_shared.js";
3
+ import { cleanOutput, optNum, persistFullOutput, pruneToolResultsRing, str } from "./_shared.js";
4
+ import { ensureLoginShellPath } from "./_login-shell.js";
4
5
  /**
5
6
  * `bash` runs a shell command in a real PTY when the native addon is
6
7
  * loaded — programs see `isatty(stdout) === true`, signals propagate to
@@ -83,9 +84,16 @@ function formatBody(cleaned, workspaceRoot, runtimeDropped, callId) {
83
84
  };
84
85
  }
85
86
  const persistedPath = persistFullOutput(workspaceRoot, cleaned, "bash", "output.txt", callId);
87
+ // (7.9 [5.10], goose) Give the model EXACT read-back commands, not a vague
88
+ // "output truncated" — it can page the persisted file deterministically.
89
+ const readBack = persistedPath
90
+ ? ` Read more with \`sed -n '1,400p' ${persistedPath}\`, \`tail -n 200 ${persistedPath}\`, or \`grep -n PATTERN ${persistedPath}\`.`
91
+ : "";
86
92
  const banner = persistedPath
87
- ? `[output truncated: showing first ${headStr} KB of ${totalStr} KB; full output saved to ${persistedPath}${runtimeNote}]`
93
+ ? `[output truncated: showing first ${headStr} KB of ${totalStr} KB; full output saved to ${persistedPath}${runtimeNote}.${readBack}]`
88
94
  : `[output truncated: showing first ${headStr} KB of ${totalStr} KB; persistence failed, remainder dropped${runtimeNote}]`;
95
+ if (persistedPath)
96
+ pruneToolResultsRing(workspaceRoot);
89
97
  return {
90
98
  body: `${banner}\n${head}`,
91
99
  persistedPath,
@@ -122,6 +130,9 @@ export const bashTool = {
122
130
  async execute(args, ctx) {
123
131
  const command = str(args, "command");
124
132
  const timeoutMs = clampTimeoutMs(optNum(args, "timeout"));
133
+ // (7.9 [5.9]) Ensure the child inherits the user's real PATH even when the
134
+ // process was GUI-launched (Electron desktop). One-shot, best-effort.
135
+ ensureLoginShellPath();
125
136
  const result = await native.ptyRun({
126
137
  command,
127
138
  cwd: ctx.cwd,
@@ -1 +1 @@
1
- {"version":3,"file":"bash.js","sourceRoot":"","sources":["../../../src/tools/builtins/bash.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"bash.js","sourceRoot":"","sources":["../../../src/tools/builtins/bash.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"edit.d.ts","sourceRoot":"","sources":["../../../src/tools/builtins/edit.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,IAAI,EAAc,MAAM,aAAa,CAAC;AAGpD,eAAO,MAAM,QAAQ,EAAE,IAmCtB,CAAC"}
1
+ {"version":3,"file":"edit.d.ts","sourceRoot":"","sources":["../../../src/tools/builtins/edit.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,IAAI,EAA2B,MAAM,aAAa,CAAC;AAyDjE,eAAO,MAAM,QAAQ,EAAE,IA+DtB,CAAC"}
@@ -1,45 +1,126 @@
1
1
  import { existsSync, readFileSync } from "node:fs";
2
- import { dirname } from "node:path";
3
- import { native } from "@chances-ai/native";
2
+ import { AppError, ErrorCode } from "@chances-ai/runtime";
3
+ import { InMemorySnapshotStore, MismatchError, Patch, Patcher, } from "../../hashline/index.js";
4
4
  import { linesDiff } from "../diff.js";
5
- import { withFileLock } from "../file-lock.js";
6
- import { guardWrite, preview, str, writeFileAtomic } from "./_shared.js";
5
+ import { withSortedFileLocks } from "../file-lock.js";
6
+ import { EngineToolFs, makeBlockResolver } from "./_hashline-fs.js";
7
+ import { hashlineSnapshotKey, str } from "./_shared.js";
8
+ /**
9
+ * The model-facing hashline edit contract (7.9 [5.1], R1-S8/S9). Carried on the
10
+ * tool `description` so it reaches the provider. Distilled from oh-my-pi's
11
+ * battle-tested `prompt.md`.
12
+ */
13
+ const EDIT_TOOL_PROMPT = `Edit existing files with a hashline patch. (To CREATE a file, use the write tool.)
14
+
15
+ A patch is one or more file sections. Each section starts with a header copied verbatim from your latest read/search output:
16
+ ¶path#TAG
17
+ TAG is the 4-hex snapshot tag; it binds the edit to that exact file version and is REQUIRED.
18
+
19
+ Ops (line numbers are from read's LINE:TEXT, refer to the ORIGINAL file, and stay valid for the whole patch — they do NOT shift as hunks apply):
20
+ replace N..M: replace original lines N..M with the +body rows below (single line: replace N..N: or replace N:).
21
+ replace block N: replace the whole syntactic block that BEGINS on line N (tree-sitter; point N at the opening line, not a closing brace).
22
+ delete N..M delete original lines N..M. No body. (single: delete N)
23
+ delete block N delete the whole syntactic block beginning on line N. No body.
24
+ insert before N: insert the +body rows immediately before line N.
25
+ insert after N: insert the +body rows immediately after line N.
26
+ insert head: insert at the very start of the file.
27
+ insert tail: insert at the very end of the file.
28
+
29
+ Body rows appear only under a ':' header and are ALWAYS '+TEXT' (a new literal line, verbatim; '+' alone is a blank line). There is NO '-old' row and no bare/context row — the range does the deleting; the body is only the final new content. To insert a line starting with '+' or '-', prefix it: '++x' / '+-x'.
30
+
31
+ Rules:
32
+ - Keep ranges TIGHT: cover only lines whose content actually changes. To change lines 2 and 5 while keeping 3-4, issue two hunks (replace 2..2: and replace 5..5:).
33
+ - Multiple files / multiple hunks: just stack more sections / ops (this replaces any separate multi-edit tool). For a global rename across files, prefer the ast_edit tool.
34
+ - RE-GROUND AFTER EVERY EDIT: each applied edit mints a fresh #TAG and renumbers the file, so the tag and line numbers you just used are dead. Anchor the next edit on the ¶path#TAG and lines from THIS edit's response (or re-read). On a stale-tag rejection or any unexpected result, STOP and re-read — never stack more line-numbered edits onto output you have not re-grounded.
35
+
36
+ Example:
37
+ ¶src/util.ts#1A2B
38
+ replace 2..2:
39
+ + const greeting = "Hi";
40
+ delete 5`;
41
+ /** Extract a human-readable message from an unknown thrown value. */
42
+ function errMsg(err) {
43
+ return err instanceof Error ? err.message : String(err);
44
+ }
45
+ /** Best-effort structured-diff preview for one section (permission overlay). */
46
+ function previewSection(section, ctx) {
47
+ try {
48
+ const abs = hashlineSnapshotKey(ctx, section.path);
49
+ if (!existsSync(abs))
50
+ return `edit ${section.path}: (file not found)`;
51
+ const before = readFileSync(abs, "utf8").replace(/\r\n?/g, "\n");
52
+ const after = section.applyPartialTo(before, makeBlockResolver()).text;
53
+ return `edit ${section.path}\n${linesDiff(before, after)}`;
54
+ }
55
+ catch {
56
+ const hunks = section.diff.split("\n").filter((l) => /^\s*(replace|delete|insert)\b/.test(l)).length;
57
+ return `edit ${section.path}: ${hunks} hunk(s)`;
58
+ }
59
+ }
7
60
  export const editTool = {
8
61
  name: "edit",
9
- description: "Replace an exact, unique substring in a workspace file.",
10
62
  category: "file-write",
63
+ description: EDIT_TOOL_PROMPT,
11
64
  parameters: {
12
65
  type: "object",
13
- properties: { path: { type: "string" }, find: { type: "string" }, replace: { type: "string" } },
14
- required: ["path", "find", "replace"],
66
+ properties: { patch: { type: "string", description: "A hashline patch (see the tool description)." } },
67
+ required: ["patch"],
15
68
  },
16
- summarize: (args) => {
17
- const path = str(args, "path");
18
- const find = str(args, "find");
19
- const replace = str(args, "replace");
20
- if (!find.includes("\n") && !replace.includes("\n")) {
21
- return `edit ${path}: replace ${preview(find)} ${preview(replace)}`;
69
+ summarize: (args, ctx) => {
70
+ try {
71
+ const patch = Patch.parse(str(args, "patch"), { cwd: ctx.cwd });
72
+ if (patch.sections.length === 0)
73
+ return "edit (no sections)";
74
+ return patch.sections.map((s) => previewSection(s, ctx)).join("\n");
75
+ }
76
+ catch (err) {
77
+ return `edit (unparseable patch: ${errMsg(err)})`;
22
78
  }
23
- return `edit ${path}\n${linesDiff(find, replace)}`;
24
79
  },
25
80
  async execute(args, ctx) {
26
- const path = guardWrite(ctx, str(args, "path"));
27
- // (7.7 §3.4) Hold the per-file mutation lock for the whole read-modify-write
28
- // so a concurrent edit/write to the SAME file (another subagent, task 08)
29
- // can't interleave and corrupt it. Reads never take the lock.
30
- return withFileLock(path, async () => {
31
- if (!existsSync(path))
32
- return { ok: false, output: `No such file: ${str(args, "path")}` };
33
- const find = str(args, "find");
34
- const content = readFileSync(path, "utf8");
35
- const count = content.split(find).length - 1;
36
- if (count === 0)
37
- return { ok: false, output: `Substring not found in ${str(args, "path")}` };
38
- if (count > 1)
39
- return { ok: false, output: `Substring not unique (${count} matches)` };
40
- writeFileAtomic(path, content.replace(find, str(args, "replace")));
41
- native.invalidateFsScanCache(dirname(path));
42
- return { ok: true, output: `Edited ${str(args, "path")}` };
81
+ let patch;
82
+ try {
83
+ patch = Patch.parse(str(args, "patch"), { cwd: ctx.cwd });
84
+ }
85
+ catch (err) {
86
+ return { ok: false, output: errMsg(err) };
87
+ }
88
+ if (patch.sections.length === 0) {
89
+ return { ok: false, output: "No hashline sections found. Each section starts with `¶path#TAG` from your latest read." };
90
+ }
91
+ const snapshots = ctx.snapshots ?? new InMemorySnapshotStore();
92
+ const fs = new EngineToolFs(ctx);
93
+ const patcher = new Patcher({ fs, snapshots, blockResolver: makeBlockResolver() });
94
+ const lockPaths = patch.sections.map((s) => hashlineSnapshotKey(ctx, s.path));
95
+ // (R1-M1) Hold every affected file's mutation lock across the WHOLE
96
+ // prepare(all)+commit(all) span — hash check, apply, restore, and write all
97
+ // run inside the lock so a concurrent writer (another subagent, task 08)
98
+ // can't slip between preflight and write. Sorted acquisition = deadlock-free.
99
+ return withSortedFileLocks(lockPaths, async () => {
100
+ try {
101
+ const result = await patcher.apply(patch);
102
+ const blocks = result.sections.map((s) => {
103
+ const firstChange = s.firstChangedLine !== undefined ? ` (first change at line ${s.firstChangedLine})` : "";
104
+ const warns = s.warnings.length > 0 ? `\n${s.warnings.map((w) => `⚠ ${w}`).join("\n")}` : "";
105
+ return `${s.header}${firstChange}${warns}`;
106
+ });
107
+ return {
108
+ ok: true,
109
+ output: `Edited ${result.sections.length} file(s). The tags below are fresh — anchor any follow-up edit on them ` +
110
+ `(the tags and line numbers you just used are now dead):\n${blocks.join("\n")}`,
111
+ };
112
+ }
113
+ catch (err) {
114
+ // Security violations (realpath jail escape / protected path) are hard
115
+ // failures — let them propagate so the write path can never be coaxed
116
+ // into a soft "couldn't apply" that the model might retry around.
117
+ if (err instanceof AppError && err.code === ErrorCode.Permission)
118
+ throw err;
119
+ // Stale-tag / unrecoverable mismatch → re-read (carries the file preview).
120
+ if (err instanceof MismatchError)
121
+ return { ok: false, output: err.displayMessage };
122
+ return { ok: false, output: errMsg(err) };
123
+ }
43
124
  });
44
125
  },
45
126
  };
@@ -1 +1 @@
1
- {"version":3,"file":"edit.js","sourceRoot":"","sources":["../../../src/tools/builtins/edit.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"edit.js","sourceRoot":"","sources":["../../../src/tools/builtins/edit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EACL,qBAAqB,EACrB,aAAa,EACb,KAAK,EAEL,OAAO,GACR,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAEtD,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACpE,OAAO,EAAE,mBAAmB,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAExD;;;;GAIG;AACH,MAAM,gBAAgB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;WA2Bd,CAAC;AAEZ,qEAAqE;AACrE,SAAS,MAAM,CAAC,GAAY;IAC1B,OAAO,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;AAC1D,CAAC;AAED,gFAAgF;AAChF,SAAS,cAAc,CAAC,OAAqB,EAAE,GAAgB;IAC7D,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,mBAAmB,CAAC,GAAG,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;QACnD,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,OAAO,QAAQ,OAAO,CAAC,IAAI,oBAAoB,CAAC;QACtE,MAAM,MAAM,GAAG,YAAY,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QACjE,MAAM,KAAK,GAAG,OAAO,CAAC,cAAc,CAAC,MAAM,EAAE,iBAAiB,EAAE,CAAC,CAAC,IAAI,CAAC;QACvE,OAAO,QAAQ,OAAO,CAAC,IAAI,KAAK,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC;IAC7D,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,+BAA+B,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;QACrG,OAAO,QAAQ,OAAO,CAAC,IAAI,KAAK,KAAK,UAAU,CAAC;IAClD,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,QAAQ,GAAS;IAC5B,IAAI,EAAE,MAAM;IACZ,QAAQ,EAAE,YAAY;IACtB,WAAW,EAAE,gBAAgB;IAC7B,UAAU,EAAE;QACV,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,8CAA8C,EAAE,EAAE;QACtG,QAAQ,EAAE,CAAC,OAAO,CAAC;KACpB;IACD,SAAS,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE;QACvB,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC;YAChE,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,oBAAoB,CAAC;YAC7D,OAAO,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,4BAA4B,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC;QACpD,CAAC;IACH,CAAC;IACD,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG;QACrB,IAAI,KAAY,CAAC;QACjB,IAAI,CAAC;YACH,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC;QAC5D,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;QAC5C,CAAC;QACD,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAChC,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,yFAAyF,EAAE,CAAC;QAC1H,CAAC;QAED,MAAM,SAAS,GAAG,GAAG,CAAC,SAAS,IAAI,IAAI,qBAAqB,EAAE,CAAC;QAC/D,MAAM,EAAE,GAAG,IAAI,YAAY,CAAC,GAAG,CAAC,CAAC;QACjC,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,aAAa,EAAE,iBAAiB,EAAE,EAAE,CAAC,CAAC;QACnF,MAAM,SAAS,GAAG,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,mBAAmB,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QAE9E,oEAAoE;QACpE,4EAA4E;QAC5E,yEAAyE;QACzE,8EAA8E;QAC9E,OAAO,mBAAmB,CAAC,SAAS,EAAE,KAAK,IAAyB,EAAE;YACpE,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;gBAC1C,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;oBACvC,MAAM,WAAW,GAAG,CAAC,CAAC,gBAAgB,KAAK,SAAS,CAAC,CAAC,CAAC,0BAA0B,CAAC,CAAC,gBAAgB,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;oBAC5G,MAAM,KAAK,GAAG,CAAC,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBAC7F,OAAO,GAAG,CAAC,CAAC,MAAM,GAAG,WAAW,GAAG,KAAK,EAAE,CAAC;gBAC7C,CAAC,CAAC,CAAC;gBACH,OAAO;oBACL,EAAE,EAAE,IAAI;oBACR,MAAM,EACJ,UAAU,MAAM,CAAC,QAAQ,CAAC,MAAM,yEAAyE;wBACzG,4DAA4D,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;iBAClF,CAAC;YACJ,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,uEAAuE;gBACvE,sEAAsE;gBACtE,kEAAkE;gBAClE,IAAI,GAAG,YAAY,QAAQ,IAAI,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,UAAU;oBAAE,MAAM,GAAG,CAAC;gBAC5E,2EAA2E;gBAC3E,IAAI,GAAG,YAAY,aAAa;oBAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,cAAc,EAAE,CAAC;gBACnF,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;YAC5C,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;CACF,CAAC"}
@@ -2,7 +2,7 @@
2
2
  * (4.2) `lsp` built-in tool — read-only LSP queries.
3
3
  *
4
4
  * One tool, nine ops, claude-code-shape. The actual host
5
- * (`@chances-ai/lsp`) is wired in at boot via `ToolContext.lsp`;
5
+ * (`@chances-ai/engine/lsp`) is wired in at boot via `ToolContext.lsp`;
6
6
  * when absent, the tool fails fast so the model sees the install hint.
7
7
  *
8
8
  * Category is `integration` (codex Round-1 MUST-FIX #4) — NOT `search`.
@@ -56,7 +56,7 @@ export interface CreatePtyToolDeps {
56
56
  worktreeCwd?: string;
57
57
  /** Handle factory injected from outside — the engine wires this to
58
58
  * `native.createPtySession.bind(native)`. Threaded through the deps
59
- * object rather than imported so `@chances-ai/tools` stays free of a
59
+ * object rather than imported so `@chances-ai/engine/tools` stays free of a
60
60
  * `@chances-ai/native` runtime import. */
61
61
  createHandle: PtyHandleFactory;
62
62
  }
@@ -1 +1 @@
1
- {"version":3,"file":"read.d.ts","sourceRoot":"","sources":["../../../src/tools/builtins/read.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAc,MAAM,aAAa,CAAC;AAGpD,eAAO,MAAM,QAAQ,EAAE,IAatB,CAAC"}
1
+ {"version":3,"file":"read.d.ts","sourceRoot":"","sources":["../../../src/tools/builtins/read.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAc,MAAM,aAAa,CAAC;AA2EpD,eAAO,MAAM,QAAQ,EAAE,IA+HtB,CAAC"}
@@ -1,18 +1,194 @@
1
- import { existsSync, readFileSync } from "node:fs";
2
- import { safePath, str } from "./_shared.js";
1
+ import { existsSync, readFileSync, statSync } from "node:fs";
2
+ import { native } from "@chances-ai/native";
3
+ import { formatHashlineHeader, formatNumberedLine, normalizeToLF, stripBom } from "../../hashline/index.js";
4
+ import { readImageAsParts, sniffImageMime } from "./_image.js";
5
+ import { renderNotebook } from "./_notebook.js";
6
+ import { readPdfAsText, sniffPdf } from "./_pdf.js";
7
+ import { containReadPath, hashlineSnapshotKey, optNum, str } from "./_shared.js";
8
+ /** Hard ceiling on file size we will read into memory at all. */
9
+ const MAX_READ_BYTES = 50 * 1024 * 1024;
10
+ /** First-window byte sample used for binary/UTF-8 sniffing. */
11
+ const SNIFF_BYTES = 8192;
12
+ /** Default token budget for a single read's rendered body (override per env). */
13
+ const DEFAULT_MAX_TOKENS = 25_000;
14
+ /** Token cap from the environment, clamped to a sane floor. (7.9 R1-OQ2) */
15
+ function readMaxTokens() {
16
+ const raw = Number.parseInt(process.env.CHANCES_READ_MAX_TOKENS ?? "", 10);
17
+ return Number.isFinite(raw) && raw >= 1000 ? raw : DEFAULT_MAX_TOKENS;
18
+ }
19
+ /**
20
+ * Read-dedup stub (7.9 [5.4]): a bounded ring of `key|offset|limit → mtimeMs`.
21
+ * A repeated read of the same window whose file mtime is unchanged returns an
22
+ * "unchanged" note (plus the live `¶path#TAG` so a follow-up edit still anchors)
23
+ * instead of re-spending tokens on the body.
24
+ *
25
+ * **Per-session, not per-process (7.9 §3.3 fix):** the ring is keyed by the
26
+ * session's `SnapshotStore` identity via a `WeakMap`, so a long-running `serve`
27
+ * process can never return "unchanged since your last read" to a client session
28
+ * that never read the file (cross-session leakage in the original global map).
29
+ * It is GC-collected with the session. A shared fallback map covers direct tool
30
+ * calls / tests that wire no store (single-process, no isolation concern).
31
+ */
32
+ const READ_DEDUP_CAP = 256;
33
+ const READ_DEDUP_BY_SESSION = new WeakMap();
34
+ const READ_DEDUP_FALLBACK = new Map();
35
+ function dedupStoreFor(ctx) {
36
+ const owner = ctx.snapshots;
37
+ if (!owner)
38
+ return READ_DEDUP_FALLBACK;
39
+ let store = READ_DEDUP_BY_SESSION.get(owner);
40
+ if (!store) {
41
+ store = new Map();
42
+ READ_DEDUP_BY_SESSION.set(owner, store);
43
+ }
44
+ return store;
45
+ }
46
+ function dedupRemember(store, key, mtimeMs) {
47
+ store.delete(key);
48
+ store.set(key, mtimeMs);
49
+ while (store.size > READ_DEDUP_CAP) {
50
+ const oldest = store.keys().next().value;
51
+ if (oldest === undefined)
52
+ break;
53
+ store.delete(oldest);
54
+ }
55
+ }
56
+ /** True when `buf` looks binary: a NUL byte, or invalid UTF-8 in the sniff window. */
57
+ function looksBinary(buf) {
58
+ const window = buf.subarray(0, SNIFF_BYTES);
59
+ if (window.includes(0))
60
+ return true;
61
+ try {
62
+ new TextDecoder("utf-8", { fatal: true }).decode(window);
63
+ return false;
64
+ }
65
+ catch {
66
+ return true;
67
+ }
68
+ }
69
+ /** Estimate tokens with a 4×-byte fast-reject before the (more expensive) real
70
+ * count (claude-code shape): if a 4-bytes-per-token lower bound is already under
71
+ * the cap, skip the native count entirely. */
72
+ function withinTokenCap(text, cap) {
73
+ if (Buffer.byteLength(text, "utf8") / 4 <= cap)
74
+ return true;
75
+ return native.countTokensExact(text).tokens <= cap;
76
+ }
3
77
  export const readTool = {
4
78
  name: "read",
5
- description: "Read a UTF-8 text file from the workspace.",
6
79
  category: "file-read",
7
- parameters: { type: "object", properties: { path: { type: "string" } }, required: ["path"] },
8
- summarize: (args) => `read ${str(args, "path")}`,
80
+ description: "Read a UTF-8 text file from the workspace. Output is `¶path#TAG` (the hashline " +
81
+ "snapshot tag) followed by `LINE:TEXT` numbered lines (1-indexed). Copy the " +
82
+ "`¶path#TAG` header and the bare LINE numbers into the `edit` tool — the tag binds " +
83
+ "your edit to this exact file version. Use `offset` (1-indexed start line) and " +
84
+ "`limit` (line count) to page large files; oversized output is capped and asks you " +
85
+ "to page. Images are returned as vision input; PDFs and Jupyter notebooks (.ipynb) " +
86
+ "are rendered as read-only text (no editable tag). Binary, device, and over-large " +
87
+ "files are refused.",
88
+ parameters: {
89
+ type: "object",
90
+ properties: {
91
+ path: { type: "string" },
92
+ offset: { type: "number", description: "1-indexed first line to show (default 1)." },
93
+ limit: { type: "number", description: "Maximum number of lines to show." },
94
+ },
95
+ required: ["path"],
96
+ },
97
+ summarize: (args) => {
98
+ const offset = optNum(args, "offset");
99
+ const limit = optNum(args, "limit");
100
+ const window = offset !== undefined || limit !== undefined ? ` (lines ${offset ?? 1}..${limit ? (offset ?? 1) + limit - 1 : "end"})` : "";
101
+ return `read ${str(args, "path")}${window}`;
102
+ },
9
103
  async execute(args, ctx) {
10
- const path = safePath(ctx, str(args, "path"));
11
- if (!existsSync(path))
12
- return { ok: false, output: `No such file: ${str(args, "path")}` };
13
- const content = readFileSync(path, "utf8");
14
- const clipped = content.length > 60_000 ? content.slice(0, 60_000) + "\n…(truncated)" : content;
15
- return { ok: true, output: clipped };
104
+ const rel = str(args, "path");
105
+ const abs = containReadPath(ctx, rel);
106
+ if (!existsSync(abs))
107
+ return { ok: false, output: `No such file: ${rel}` };
108
+ const stat = statSync(abs);
109
+ if (!stat.isFile()) {
110
+ return { ok: false, output: `Not a regular file (device/socket/fifo/directory): ${rel}` };
111
+ }
112
+ if (stat.size > MAX_READ_BYTES) {
113
+ return { ok: false, output: `File too large to read (${stat.size} bytes > ${MAX_READ_BYTES}). Use grep/glob to locate, or a bash tail/sed window.` };
114
+ }
115
+ const buf = readFileSync(abs);
116
+ // (7.9 [5.5]) Image files → vision content parts (before the binary reject,
117
+ // which would otherwise refuse them). The model sees the pixels via the
118
+ // engine's vision-gated injection; clients render them from the tool:result.
119
+ const imageMime = sniffImageMime(buf);
120
+ if (imageMime) {
121
+ return readImageAsParts(buf, rel, imageMime);
122
+ }
123
+ // (7.9 [5.5]) PDFs are binary → extract text before the binary reject.
124
+ if (sniffPdf(buf)) {
125
+ return readPdfAsText(buf, rel);
126
+ }
127
+ // (7.9 [5.5]) Jupyter notebooks are JSON text, but the raw escaped source +
128
+ // base64 output blobs are unreadable — render a compact cell view instead.
129
+ if (rel.toLowerCase().endsWith(".ipynb")) {
130
+ return renderNotebook(buf.toString("utf8"), rel);
131
+ }
132
+ if (looksBinary(buf)) {
133
+ return { ok: false, output: `Binary file, not shown (${stat.size} bytes): ${rel}` };
134
+ }
135
+ // Canonical full text the tag binds to + the snapshot key both read and edit agree on.
136
+ const raw = buf.toString("utf8");
137
+ const { text: noBom } = stripBom(raw);
138
+ const fullText = normalizeToLF(noBom);
139
+ const key = hashlineSnapshotKey(ctx, rel);
140
+ const tag = ctx.snapshots?.record(key, fullText);
141
+ const header = tag ? formatHashlineHeader(rel, tag) : `¶${rel}`;
142
+ const offset = Math.max(1, Math.trunc(optNum(args, "offset") ?? 1));
143
+ const limitArg = optNum(args, "limit");
144
+ const limit = limitArg !== undefined ? Math.max(0, Math.trunc(limitArg)) : undefined;
145
+ // read-dedup: same window + unchanged mtime → skip the body, keep the tag.
146
+ const dedup = dedupStoreFor(ctx);
147
+ const dedupKey = `${key}|${offset}|${limit ?? "all"}`;
148
+ if (dedup.get(dedupKey) === stat.mtimeMs) {
149
+ return {
150
+ ok: true,
151
+ output: `${header}\n(unchanged since your last read of this window — file not modified. Use the tag above to edit, or read a different window.)`,
152
+ };
153
+ }
154
+ const lines = fullText.split("\n");
155
+ const total = lines.length;
156
+ const start = Math.min(offset, total + 1);
157
+ const end = limit !== undefined ? Math.min(start - 1 + limit, total) : total;
158
+ const windowLines = lines.slice(start - 1, end);
159
+ let body = windowLines.map((line, i) => formatNumberedLine(start + i, line)).join("\n");
160
+ const cap = readMaxTokens();
161
+ let capped = false;
162
+ // Number of lines actually shown — drives the continue-offset. (R2-SHOULD:
163
+ // counting non-blank lines undercounts windows with blank lines.)
164
+ let shownCount = windowLines.length;
165
+ if (!withinTokenCap(body, cap)) {
166
+ // Binary-search the largest line prefix that fits the token cap.
167
+ let lo = 0;
168
+ let hi = windowLines.length;
169
+ while (lo < hi) {
170
+ const mid = Math.ceil((lo + hi) / 2);
171
+ const candidate = windowLines.slice(0, mid).map((line, i) => formatNumberedLine(start + i, line)).join("\n");
172
+ if (withinTokenCap(candidate, cap))
173
+ lo = mid;
174
+ else
175
+ hi = mid - 1;
176
+ }
177
+ body = windowLines.slice(0, lo).map((line, i) => formatNumberedLine(start + i, line)).join("\n");
178
+ shownCount = lo;
179
+ capped = true;
180
+ }
181
+ dedupRemember(dedup, dedupKey, stat.mtimeMs);
182
+ const shownEnd = capped ? start - 1 + shownCount : end;
183
+ const footerParts = [];
184
+ if (start > 1 || shownEnd < total) {
185
+ footerParts.push(`(showing lines ${start}..${shownEnd} of ${total})`);
186
+ }
187
+ if (capped) {
188
+ footerParts.push(`output capped at ~${cap} tokens — continue with offset:${shownEnd + 1}`);
189
+ }
190
+ const footer = footerParts.length > 0 ? `\n${footerParts.join(" ")}` : "";
191
+ return { ok: true, output: `${header}\n${body}${footer}` };
16
192
  },
17
193
  };
18
194
  //# sourceMappingURL=read.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"read.js","sourceRoot":"","sources":["../../../src/tools/builtins/read.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEnD,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAE7C,MAAM,CAAC,MAAM,QAAQ,GAAS;IAC5B,IAAI,EAAE,MAAM;IACZ,WAAW,EAAE,4CAA4C;IACzD,QAAQ,EAAE,WAAW;IACrB,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,MAAM,CAAC,EAAE;IAC5F,SAAS,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE;IAChD,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG;QACrB,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;QAC9C,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,iBAAiB,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC;QAC1F,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAC3C,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAC,OAAO,CAAC;QAChG,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;IACvC,CAAC;CACF,CAAC"}
1
+ {"version":3,"file":"read.js","sourceRoot":"","sources":["../../../src/tools/builtins/read.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"builtins.d.ts","sourceRoot":"","sources":["../../src/tools/builtins.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAYvC;;;;;GAKG;AACH,eAAO,MAAM,YAAY,EAAE,IAAI,EAW9B,CAAC"}
1
+ {"version":3,"file":"builtins.d.ts","sourceRoot":"","sources":["../../src/tools/builtins.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAcvC;;;;;GAKG;AACH,eAAO,MAAM,YAAY,EAAE,IAAI,EAa9B,CAAC"}
@@ -8,6 +8,8 @@ import { diffTool } from "./builtins/diff.js";
8
8
  import { webFetchTool } from "./builtins/web-fetch.js";
9
9
  import { lspTool } from "./builtins/lsp.js";
10
10
  import { askUserQuestionTool } from "./builtins/ask-user-question.js";
11
+ import { astGrepTool } from "./builtins/ast-grep.js";
12
+ import { astEditTool } from "./builtins/ast-edit.js";
11
13
  /**
12
14
  * Registry of first-party tools the engine ships with. New tools live in their
13
15
  * own module under `./builtins/<name>.ts`; this file is a pure barrel so the
@@ -25,5 +27,7 @@ export const builtinTools = [
25
27
  webFetchTool,
26
28
  lspTool,
27
29
  askUserQuestionTool,
30
+ astGrepTool,
31
+ astEditTool,
28
32
  ];
29
33
  //# sourceMappingURL=builtins.js.map