fixo-cli 1.0.3 → 2.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.

Potentially problematic release.


This version of fixo-cli might be problematic. Click here for more details.

Files changed (222) hide show
  1. package/CHANGELOG.md +62 -0
  2. package/README.md +18 -14
  3. package/dist/agent/agent-client.d.ts +28 -6
  4. package/dist/agent/agent-client.d.ts.map +1 -1
  5. package/dist/agent/agent-client.js +118 -39
  6. package/dist/agent/agent-client.js.map +1 -1
  7. package/dist/agent/agent-pool.d.ts +55 -6
  8. package/dist/agent/agent-pool.d.ts.map +1 -1
  9. package/dist/agent/agent-pool.js +120 -20
  10. package/dist/agent/agent-pool.js.map +1 -1
  11. package/dist/agent/auto-verifier.d.ts +55 -0
  12. package/dist/agent/auto-verifier.d.ts.map +1 -0
  13. package/dist/agent/auto-verifier.js +50 -0
  14. package/dist/agent/auto-verifier.js.map +1 -0
  15. package/dist/agent/command-parser.d.ts +37 -0
  16. package/dist/agent/command-parser.d.ts.map +1 -1
  17. package/dist/agent/command-parser.js +473 -1
  18. package/dist/agent/command-parser.js.map +1 -1
  19. package/dist/agent/context-builder.d.ts +24 -0
  20. package/dist/agent/context-builder.d.ts.map +1 -0
  21. package/dist/agent/context-builder.js +197 -0
  22. package/dist/agent/context-builder.js.map +1 -0
  23. package/dist/agent/conversation.d.ts +32 -2
  24. package/dist/agent/conversation.d.ts.map +1 -1
  25. package/dist/agent/conversation.js +84 -9
  26. package/dist/agent/conversation.js.map +1 -1
  27. package/dist/agent/duration.d.ts +24 -0
  28. package/dist/agent/duration.d.ts.map +1 -0
  29. package/dist/agent/duration.js +42 -0
  30. package/dist/agent/duration.js.map +1 -0
  31. package/dist/agent/file-writing-rules.d.ts +19 -0
  32. package/dist/agent/file-writing-rules.d.ts.map +1 -0
  33. package/dist/agent/file-writing-rules.js +31 -0
  34. package/dist/agent/file-writing-rules.js.map +1 -0
  35. package/dist/agent/mcp-bridge.js +1 -1
  36. package/dist/agent/mcp-bridge.js.map +1 -1
  37. package/dist/agent/orchestrator.d.ts +45 -0
  38. package/dist/agent/orchestrator.d.ts.map +1 -1
  39. package/dist/agent/orchestrator.js +140 -3
  40. package/dist/agent/orchestrator.js.map +1 -1
  41. package/dist/agent/parser-adapter.d.ts +17 -0
  42. package/dist/agent/parser-adapter.d.ts.map +1 -1
  43. package/dist/agent/parser-adapter.js +311 -7
  44. package/dist/agent/parser-adapter.js.map +1 -1
  45. package/dist/agent/predictive-gate.d.ts.map +1 -1
  46. package/dist/agent/predictive-gate.js +4 -1
  47. package/dist/agent/predictive-gate.js.map +1 -1
  48. package/dist/agent/provider-cooldown.d.ts.map +1 -1
  49. package/dist/agent/provider-cooldown.js +3 -2
  50. package/dist/agent/provider-cooldown.js.map +1 -1
  51. package/dist/agent/providers-manager.d.ts +5 -0
  52. package/dist/agent/providers-manager.d.ts.map +1 -1
  53. package/dist/agent/providers-manager.js +119 -8
  54. package/dist/agent/providers-manager.js.map +1 -1
  55. package/dist/agent/repo-map.d.ts +18 -1
  56. package/dist/agent/repo-map.d.ts.map +1 -1
  57. package/dist/agent/repo-map.js +144 -54
  58. package/dist/agent/repo-map.js.map +1 -1
  59. package/dist/agent/retry.js +1 -2
  60. package/dist/agent/retry.js.map +1 -1
  61. package/dist/agent/single-agent.d.ts +13 -0
  62. package/dist/agent/single-agent.d.ts.map +1 -1
  63. package/dist/agent/single-agent.js +225 -37
  64. package/dist/agent/single-agent.js.map +1 -1
  65. package/dist/agent/skills.d.ts.map +1 -1
  66. package/dist/agent/skills.js +2 -1
  67. package/dist/agent/skills.js.map +1 -1
  68. package/dist/agent/subagent.js +2 -2
  69. package/dist/agent/subagent.js.map +1 -1
  70. package/dist/agent/task-router.d.ts +46 -0
  71. package/dist/agent/task-router.d.ts.map +1 -0
  72. package/dist/agent/task-router.js +352 -0
  73. package/dist/agent/task-router.js.map +1 -0
  74. package/dist/agent/telemetry.d.ts +29 -1
  75. package/dist/agent/telemetry.d.ts.map +1 -1
  76. package/dist/agent/telemetry.js +29 -11
  77. package/dist/agent/telemetry.js.map +1 -1
  78. package/dist/agent/tool-definitions.d.ts +3 -0
  79. package/dist/agent/tool-definitions.d.ts.map +1 -0
  80. package/dist/agent/tool-definitions.js +519 -0
  81. package/dist/agent/tool-definitions.js.map +1 -0
  82. package/dist/agent/tool-executor.d.ts +6 -1
  83. package/dist/agent/tool-executor.d.ts.map +1 -1
  84. package/dist/agent/tool-executor.js +99 -553
  85. package/dist/agent/tool-executor.js.map +1 -1
  86. package/dist/agent/tools/command-tools.d.ts +6 -0
  87. package/dist/agent/tools/command-tools.d.ts.map +1 -0
  88. package/dist/agent/tools/command-tools.js +104 -0
  89. package/dist/agent/tools/command-tools.js.map +1 -0
  90. package/dist/agent/tools/file-tools.d.ts +15 -0
  91. package/dist/agent/tools/file-tools.d.ts.map +1 -0
  92. package/dist/agent/tools/file-tools.js +551 -0
  93. package/dist/agent/tools/file-tools.js.map +1 -0
  94. package/dist/agent/tools/todo-tools.d.ts +3 -0
  95. package/dist/agent/tools/todo-tools.d.ts.map +1 -0
  96. package/dist/agent/tools/todo-tools.js +70 -0
  97. package/dist/agent/tools/todo-tools.js.map +1 -0
  98. package/dist/agent/web-impl.d.ts.map +1 -1
  99. package/dist/agent/web-impl.js +45 -0
  100. package/dist/agent/web-impl.js.map +1 -1
  101. package/dist/agent/worker-agent.d.ts +3 -1
  102. package/dist/agent/worker-agent.d.ts.map +1 -1
  103. package/dist/agent/worker-agent.js +56 -16
  104. package/dist/agent/worker-agent.js.map +1 -1
  105. package/dist/config.d.ts +253 -1
  106. package/dist/config.d.ts.map +1 -1
  107. package/dist/config.js +81 -1
  108. package/dist/config.js.map +1 -1
  109. package/dist/git/git-manager.d.ts +33 -2
  110. package/dist/git/git-manager.d.ts.map +1 -1
  111. package/dist/git/git-manager.js +111 -15
  112. package/dist/git/git-manager.js.map +1 -1
  113. package/dist/git/git-ops.d.ts.map +1 -1
  114. package/dist/git/git-ops.js +2 -1
  115. package/dist/git/git-ops.js.map +1 -1
  116. package/dist/index.js +89 -8
  117. package/dist/index.js.map +1 -1
  118. package/dist/lsp/lsp-manager.js +1 -1
  119. package/dist/lsp/lsp-manager.js.map +1 -1
  120. package/dist/model-outcomes.d.ts.map +1 -1
  121. package/dist/model-outcomes.js +2 -1
  122. package/dist/model-outcomes.js.map +1 -1
  123. package/dist/planner.d.ts +0 -9
  124. package/dist/planner.d.ts.map +1 -1
  125. package/dist/planner.js +0 -9
  126. package/dist/planner.js.map +1 -1
  127. package/dist/project-memory.d.ts +12 -1
  128. package/dist/project-memory.d.ts.map +1 -1
  129. package/dist/project-memory.js +8 -6
  130. package/dist/project-memory.js.map +1 -1
  131. package/dist/runtime/loop-mitigation.d.ts +119 -0
  132. package/dist/runtime/loop-mitigation.d.ts.map +1 -0
  133. package/dist/runtime/loop-mitigation.js +192 -0
  134. package/dist/runtime/loop-mitigation.js.map +1 -0
  135. package/dist/runtime/os-sandbox.d.ts +100 -0
  136. package/dist/runtime/os-sandbox.d.ts.map +1 -0
  137. package/dist/runtime/os-sandbox.js +246 -0
  138. package/dist/runtime/os-sandbox.js.map +1 -0
  139. package/dist/runtime/run-inventory.d.ts +17 -0
  140. package/dist/runtime/run-inventory.d.ts.map +1 -0
  141. package/dist/runtime/run-inventory.js +49 -0
  142. package/dist/runtime/run-inventory.js.map +1 -0
  143. package/dist/runtime/session-snapshots.d.ts +52 -2
  144. package/dist/runtime/session-snapshots.d.ts.map +1 -1
  145. package/dist/runtime/session-snapshots.js +76 -1
  146. package/dist/runtime/session-snapshots.js.map +1 -1
  147. package/dist/runtime/staging.d.ts.map +1 -1
  148. package/dist/runtime/staging.js +4 -1
  149. package/dist/runtime/staging.js.map +1 -1
  150. package/dist/runtime/task-session.d.ts +14 -0
  151. package/dist/runtime/task-session.d.ts.map +1 -1
  152. package/dist/runtime/task-session.js +26 -0
  153. package/dist/runtime/task-session.js.map +1 -1
  154. package/dist/setup-wizard.d.ts +11 -3
  155. package/dist/setup-wizard.d.ts.map +1 -1
  156. package/dist/setup-wizard.js +113 -15
  157. package/dist/setup-wizard.js.map +1 -1
  158. package/dist/types.d.ts +8 -0
  159. package/dist/types.d.ts.map +1 -1
  160. package/dist/ui/commands/context-commands.d.ts +7 -0
  161. package/dist/ui/commands/context-commands.d.ts.map +1 -0
  162. package/dist/ui/commands/context-commands.js +241 -0
  163. package/dist/ui/commands/context-commands.js.map +1 -0
  164. package/dist/ui/commands/index.d.ts +3 -0
  165. package/dist/ui/commands/index.d.ts.map +1 -0
  166. package/dist/ui/commands/index.js +46 -0
  167. package/dist/ui/commands/index.js.map +1 -0
  168. package/dist/ui/commands/info-commands.d.ts +15 -0
  169. package/dist/ui/commands/info-commands.d.ts.map +1 -0
  170. package/dist/ui/commands/info-commands.js +122 -0
  171. package/dist/ui/commands/info-commands.js.map +1 -0
  172. package/dist/ui/commands/model-commands.d.ts +5 -0
  173. package/dist/ui/commands/model-commands.d.ts.map +1 -0
  174. package/dist/ui/commands/model-commands.js +417 -0
  175. package/dist/ui/commands/model-commands.js.map +1 -0
  176. package/dist/ui/commands/session-commands.d.ts +5 -0
  177. package/dist/ui/commands/session-commands.d.ts.map +1 -0
  178. package/dist/ui/commands/session-commands.js +154 -0
  179. package/dist/ui/commands/session-commands.js.map +1 -0
  180. package/dist/ui/commands/task-commands.d.ts +8 -0
  181. package/dist/ui/commands/task-commands.d.ts.map +1 -0
  182. package/dist/ui/commands/task-commands.js +152 -0
  183. package/dist/ui/commands/task-commands.js.map +1 -0
  184. package/dist/ui/commands/types.d.ts +46 -0
  185. package/dist/ui/commands/types.d.ts.map +1 -0
  186. package/dist/ui/commands/types.js +2 -0
  187. package/dist/ui/commands/types.js.map +1 -0
  188. package/dist/ui/commands/workspace-commands.d.ts +8 -0
  189. package/dist/ui/commands/workspace-commands.d.ts.map +1 -0
  190. package/dist/ui/commands/workspace-commands.js +131 -0
  191. package/dist/ui/commands/workspace-commands.js.map +1 -0
  192. package/dist/ui/loading-animation.d.ts +24 -0
  193. package/dist/ui/loading-animation.d.ts.map +1 -0
  194. package/dist/ui/loading-animation.js +123 -0
  195. package/dist/ui/loading-animation.js.map +1 -0
  196. package/dist/ui/markdown-stream.js +2 -2
  197. package/dist/ui/markdown-stream.js.map +1 -1
  198. package/dist/ui/prompt.d.ts +7 -0
  199. package/dist/ui/prompt.d.ts.map +1 -1
  200. package/dist/ui/prompt.js +461 -1143
  201. package/dist/ui/prompt.js.map +1 -1
  202. package/dist/ui/render-primitives.d.ts +6 -0
  203. package/dist/ui/render-primitives.d.ts.map +1 -1
  204. package/dist/ui/render-primitives.js +30 -13
  205. package/dist/ui/render-primitives.js.map +1 -1
  206. package/dist/ui/render.d.ts.map +1 -1
  207. package/dist/ui/render.js +2 -0
  208. package/dist/ui/render.js.map +1 -1
  209. package/dist/ui/session-header.d.ts +13 -0
  210. package/dist/ui/session-header.d.ts.map +1 -1
  211. package/dist/ui/session-header.js +6 -0
  212. package/dist/ui/session-header.js.map +1 -1
  213. package/package.json +22 -4
  214. package/scripts/check-vendor-wasm.js +55 -0
  215. package/vendor/tree-sitter-bash.wasm +0 -0
  216. package/vendor/tree-sitter-go.wasm +0 -0
  217. package/vendor/tree-sitter-javascript.wasm +0 -0
  218. package/vendor/tree-sitter-python.wasm +0 -0
  219. package/vendor/tree-sitter-rust.wasm +0 -0
  220. package/vendor/tree-sitter-tsx.wasm +0 -0
  221. package/vendor/tree-sitter-typescript.wasm +0 -0
  222. package/vendor/tree-sitter.wasm +0 -0
@@ -36,7 +36,7 @@ export const DEFAULT_RETRYABLE_STATUS_CODES = new Set([
36
36
  export function defaultIsRetryable(err) {
37
37
  if (err instanceof Error) {
38
38
  const name = err.name;
39
- if (name === 'AbortError' || name === 'AbortError' || /abort/i.test(err.message)) {
39
+ if (name === 'AbortError' || /abort/i.test(err.message)) {
40
40
  return false;
41
41
  }
42
42
  if (name === 'HttpError' && 'status' in err) {
@@ -269,7 +269,6 @@ function emitRetryEvent(hook, event) {
269
269
  catch (hookErr) {
270
270
  // Telemetry must never break the retry chain.
271
271
  const msg = hookErr instanceof Error ? hookErr.message : String(hookErr);
272
- // eslint-disable-next-line no-console
273
272
  console.warn(`[retry] onRetry hook threw: ${msg}`);
274
273
  }
275
274
  }
@@ -1 +1 @@
1
- {"version":3,"file":"retry.js","sourceRoot":"","sources":["../../src/agent/retry.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"retry.js","sourceRoot":"","sources":["../../src/agent/retry.ts"],"names":[],"mappings":"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"}
@@ -13,6 +13,19 @@ export declare const promptsWrapper: {
13
13
  isCancel: typeof p.isCancel;
14
14
  };
15
15
  import type readline from 'readline';
16
+ /**
17
+ * Tools that mutate the workspace, the git tree, the network, or any
18
+ * external state. Exported so the budget logic and the permission
19
+ * prompt logic share one source of truth — keeping the
20
+ * "investigation vs mutation" classification aligned with what the
21
+ * user sees in the approval prompt.
22
+ */
23
+ export declare const MUTATING_TOOL_NAMES: ReadonlySet<string>;
24
+ /**
25
+ * Returns true when the given tool name is a pure read / analysis
26
+ * operation (read_file, search_code, list_dir, extract_symbols, ...).
27
+ */
28
+ export declare function isReadOnlyTool(name: string): boolean;
16
29
  export declare function evaluateInputIntent(task: string): 'CHAT_ONLY' | 'MUTATION';
17
30
  export declare class SingleAgent {
18
31
  private client;
@@ -1 +1 @@
1
- {"version":3,"file":"single-agent.d.ts","sourceRoot":"","sources":["../../src/agent/single-agent.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,WAAW,EAAqC,MAAM,mBAAmB,CAAC;AACnF,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAIxD,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAoB7D,OAAO,KAAK,CAAC,MAAM,gBAAgB,CAAC;AACpC,eAAO,MAAM,cAAc;;;;mBAkDgG,CAAC;kBAEnH,CAAC,cAAc,CAAC;qBAAoC,CAAC;;;CA/C7D,CAAC;AACF,OAAO,KAAK,QAAQ,MAAM,UAAU,CAAC;AA0BrC,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,UAAU,CAiC1E;AAkJD,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,QAAQ,CAAS;IACzB,0EAA0E;IAC1E,OAAO,CAAC,eAAe,CAAyB;IAChD;qDACiD;IACjD,OAAO,CAAC,qBAAqB,CAAS;gBAE1B,OAAO,UAAQ;IAM3B,2EAA2E;IAC3E,SAAS,IAAI,WAAW;IAIxB;uDACmD;IACnD,KAAK,IAAI,IAAI;IAKb;;8DAE0D;IAC1D,KAAK,IAAI,IAAI;IAKP,YAAY,CAChB,OAAO,EAAE,YAAY,EACrB,YAAY,EAAE,mBAAmB,EACjC,EAAE,CAAC,EAAE,QAAQ,CAAC,SAAS,GACtB,OAAO,CAAC,WAAW,CAAC;IAyavB;;;;;;;;OAQG;YACW,aAAa;IAuD3B;;;;;;;OAOG;YACW,cAAc;YA6Dd,qBAAqB;IAqCnC;;;OAGG;YACW,mBAAmB;IA2BjC;;;;;;;;;;;;;;;;;OAiBG;IACG,oBAAoB,CACxB,YAAY,EAAE,mBAAmB,EACjC,YAAY,EAAE,MAAM,EACpB,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,SAAS,EAAE,OAAO,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC;IAyCzE,sCAAsC;IAChC,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC;CAG/B"}
1
+ {"version":3,"file":"single-agent.d.ts","sourceRoot":"","sources":["../../src/agent/single-agent.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,WAAW,EAAqC,MAAM,mBAAmB,CAAC;AACnF,OAAO,EAAE,mBAAmB,EAAuB,MAAM,mBAAmB,CAAC;AAK7E,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAyB7D,OAAO,KAAK,CAAC,MAAM,gBAAgB,CAAC;AACpC,eAAO,MAAM,cAAc;;;;mBAgDgB,CAAC;kBACvB,CAAC,cAAc,CAAC;qBAIzB,CAAC;;;CAhDZ,CAAC;AACF,OAAO,KAAK,QAAQ,MAAM,UAAU,CAAC;AAerC;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,EAAE,WAAW,CAAC,MAAM,CAclD,CAAC;AAEH;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEpD;AAcD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,UAAU,CAiC1E;AAoJD,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,QAAQ,CAAS;IACzB,0EAA0E;IAC1E,OAAO,CAAC,eAAe,CAAyB;IAChD;qDACiD;IACjD,OAAO,CAAC,qBAAqB,CAAS;gBAE1B,OAAO,UAAQ;IAY3B,2EAA2E;IAC3E,SAAS,IAAI,WAAW;IAIxB;uDACmD;IACnD,KAAK,IAAI,IAAI;IAKb;;8DAE0D;IAC1D,KAAK,IAAI,IAAI;IAKP,YAAY,CAChB,OAAO,EAAE,YAAY,EACrB,YAAY,EAAE,mBAAmB,EACjC,EAAE,CAAC,EAAE,QAAQ,CAAC,SAAS,GACtB,OAAO,CAAC,WAAW,CAAC;IAumBvB;;;;;;;;OAQG;YACW,aAAa;IA0C3B;;;;;;;OAOG;YACW,cAAc;YA6Dd,qBAAqB;IAwCnC;;;OAGG;YACW,mBAAmB;IA2BjC;;;;;;;;;;;;;;;;;OAiBG;IACG,oBAAoB,CACxB,YAAY,EAAE,mBAAmB,EACjC,YAAY,EAAE,MAAM,EACpB,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,SAAS,EAAE,OAAO,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC;IAyCzE,sCAAsC;IAChC,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC;CAG/B"}
@@ -1,17 +1,19 @@
1
1
  import { AgentClient } from './agent-client.js';
2
- import { ConversationManager } from './conversation.js';
2
+ import { ConversationManager, sanitizeUserContent } from './conversation.js';
3
3
  import { getActiveTools, executeTool, classifyExecutionRole } from './tool-executor.js';
4
4
  import { isTrivialQuery } from '../planner.js';
5
+ import { decideAutoVerify, classifyVerifyOutput, buildRepairMessage } from './auto-verifier.js';
5
6
  import { buildRepoMap } from './repo-map.js';
6
- import { loadConfig } from '../config.js';
7
+ import { loadConfig, getAgentLoopGuardConfig } from '../config.js';
7
8
  import { recordTelemetry, telemetry } from './telemetry.js';
8
9
  import { buildProjectInstructionsBlock, recordFixoMdLoad, } from '../context/fixo-md.js';
9
10
  import { loadTodoList, summariseTodoList, } from '../context/todo.js';
10
11
  import { C } from '../ui/colors.js';
11
12
  import { MarkdownStreamRenderer, renderMarkdown } from '../ui/markdown-stream.js';
12
13
  import { SemanticLoopDetector, SemanticLoopAbortedError, toSafetyAlertDirective, } from '../runtime/loop-trap.js';
14
+ import { LoopMitigationTracker, isReadTool, buildLoopBlockedReadResult, } from '../runtime/loop-mitigation.js';
13
15
  import { dashboard } from '../ui/render.js';
14
- import { TaskStatusIndicator } from '../ui/render-primitives.js';
16
+ import { LoadingAnimation } from '../ui/loading-animation.js';
15
17
  import * as p from '@clack/prompts';
16
18
  export const promptsWrapper = {
17
19
  select: p.select,
@@ -22,8 +24,38 @@ export const promptsWrapper = {
22
24
  import { TaskSession } from '../runtime/task-session.js';
23
25
  import { BackgroundAwareness } from './background-awareness.js';
24
26
  import { FixoMdWatcher } from '../context/fixo-md-watcher.js';
27
+ import { FILE_WRITING_RULES_BLOCK } from './file-writing-rules.js';
25
28
  /* ──────────────────────── Constants ──────────────────────── */
26
29
  const MAX_TOOL_RESULT_LENGTH = 30_000;
30
+ /**
31
+ * Tools that mutate the workspace, the git tree, the network, or any
32
+ * external state. Exported so the budget logic and the permission
33
+ * prompt logic share one source of truth — keeping the
34
+ * "investigation vs mutation" classification aligned with what the
35
+ * user sees in the approval prompt.
36
+ */
37
+ export const MUTATING_TOOL_NAMES = new Set([
38
+ 'write_file',
39
+ 'run_command',
40
+ 'run_command_async',
41
+ 'apply_patch',
42
+ 'replace_range',
43
+ 'insert_after',
44
+ 'str_replace',
45
+ 'rename_file',
46
+ 'delete_file',
47
+ 'create_branch',
48
+ 'commit_changes',
49
+ 'push_branch',
50
+ 'create_pull_request',
51
+ ]);
52
+ /**
53
+ * Returns true when the given tool name is a pure read / analysis
54
+ * operation (read_file, search_code, list_dir, extract_symbols, ...).
55
+ */
56
+ export function isReadOnlyTool(name) {
57
+ return !MUTATING_TOOL_NAMES.has(name);
58
+ }
27
59
  const colors = {
28
60
  reset: C.RESET,
29
61
  bold: C.BOLD,
@@ -104,10 +136,11 @@ function formatPermissionPrompt(name, args) {
104
136
  */
105
137
  function buildUserContent(context) {
106
138
  const attachments = context.pendingAttachments;
139
+ const sanitizedTask = sanitizeUserContent(context.task);
107
140
  if (!attachments || attachments.length === 0) {
108
- return context.task;
141
+ return sanitizedTask;
109
142
  }
110
- const blocks = [{ type: 'text', text: context.task }];
143
+ const blocks = [{ type: 'text', text: sanitizedTask }];
111
144
  for (const a of attachments)
112
145
  blocks.push(a);
113
146
  return blocks;
@@ -115,7 +148,7 @@ function buildUserContent(context) {
115
148
  function buildSystemPrompt(repoMap, context, enableTools = true) {
116
149
  const parts = [];
117
150
  if (enableTools) {
118
- parts.push(`You are FixO CLI, an autonomous AI coding agent. You help developers by reading, writing, and modifying code files in their workspace.`, ``, `## Capabilities`, `You have access to these tools:`, `- **read_file(path)** — Read a file's contents`, `- **write_file(path, content)** — Create or overwrite a file`, `- **run_command(command)** — Execute a shell command (npm test, git status, etc.)`, `- **search_code(query)** — Search for patterns in the codebase`, `- **list_dir(path)** — List directory contents`, ``, `## Guidelines`, `1. ALWAYS read existing files before modifying them to understand current code.`, `2. For new files, write complete contents — never use placeholders like "// ... rest of the file". For edits to existing files, follow the Editing Discipline below.`, `3. After making changes, run the verification command if one is configured.`, `4. Keep your text responses concise. Focus on what you did and why.`, `5. If the task is ambiguous, ask a clarifying question instead of guessing.`, `6. Preserve existing code comments and formatting unless asked to change them.`, ``, `## Editing Discipline`, `Pick the narrowest tool that fits the change. Rewriting a file you only need to tweak burns tokens, defeats the LSP pre-save granularity, and risks clobbering concurrent edits.`, `- **Single-region edit on an existing file** (one symbol, one block, one line) → use \`str_replace\`. It is surgical and atomic. By default it errors when the snippet is non-unique — narrow the snippet, don't disable the check.`, `- **Multi-region or hunked edit on an existing file** (several non-adjacent changes, or a diff you already have) → use \`apply_patch\` with a unified diff. One tool call, all hunks atomic.`, `- **New file** OR **full rewrite** where the prior content is genuinely irrelevant → use \`write_file\`. This is the only sanctioned use of \`write_file\` on an existing path.`, `Never use \`write_file\` to "edit" an existing file by rewriting it whole. If the diff is small enough to describe, it is small enough for \`str_replace\` or \`apply_patch\`.`);
151
+ parts.push(`You are FixO CLI, an autonomous AI coding agent. You help developers by reading, writing, and modifying code files in their workspace.`, ``, `## Capabilities`, `You have access to these tools:`, `- **read_file(path)** — Read a file's contents`, `- **write_file(path, content)** — Create or overwrite a file`, `- **run_command(command)** — Execute a shell command (npm test, git status, etc.)`, `- **search_code(query)** — Search for patterns in the codebase`, `- **list_dir(path)** — List directory contents`, ``, `## Guidelines`, `1. ALWAYS read existing files before modifying them to understand current code.`, `2. For new files, write complete contents — never use placeholders like "// ... rest of the file". For edits to existing files, follow the Editing Discipline below.`, `3. After making changes, run the verification command if one is configured.`, `4. Keep your text responses concise. Focus on what you did and why.`, `5. If the task is ambiguous, ask a clarifying question instead of guessing.`, `6. Preserve existing code comments and formatting unless asked to change them.`, ``, `## Editing Discipline`, `Pick the narrowest tool that fits the change. Rewriting a file you only need to tweak burns tokens, defeats the LSP pre-save granularity, and risks clobbering concurrent edits.`, `- **Single-region edit on an existing file** (one symbol, one block, one line) → use \`str_replace\`. It is surgical and atomic. By default it errors when the snippet is non-unique — narrow the snippet, don't disable the check.`, `- **Multi-region or hunked edit on an existing file** (several non-adjacent changes, or a diff you already have) → use \`apply_patch\` with a unified diff. One tool call, all hunks atomic.`, `- **New file** OR **full rewrite** where the prior content is genuinely irrelevant → use \`write_file\`. This is the only sanctioned use of \`write_file\` on an existing path.`, `Never use \`write_file\` to "edit" an existing file by rewriting it whole. If the diff is small enough to describe, it is small enough for \`str_replace\` or \`apply_patch\`.`, FILE_WRITING_RULES_BLOCK);
119
152
  }
120
153
  else {
121
154
  parts.push(`You are FixO CLI, a friendly AI coding assistant. You help developers by answering questions, explaining code, and discussing software engineering concepts.`, ``, `## Guidelines`, `1. Provide clear, detailed, and accurate explanations.`, `2. Keep your responses focused and helpful.`, `3. If you refer to code structure, do so conceptually as you currently do not have active tool access to modify code.`);
@@ -164,7 +197,7 @@ export class SingleAgent {
164
197
  markedForCancellation = false;
165
198
  constructor(verbose = false) {
166
199
  const config = loadConfig();
167
- this.client = new AgentClient(config.freellmapi_api_key || '', config.apiUrl, verbose);
200
+ this.client = new AgentClient(config.freellmapi_api_key || '', config.apiUrl, verbose, config.provider_mode, config.preferences.modelRouting);
168
201
  this.verbose = verbose;
169
202
  }
170
203
  /** Expose the underlying client for direct API calls (e.g. compaction). */
@@ -222,8 +255,28 @@ export class SingleAgent {
222
255
  return await this.executePureChatStream(context.task, conversation, context);
223
256
  }
224
257
  // ──── Complex task → tool loop ────
225
- const repoMap = buildRepoMap(context.cwd);
226
- const systemPrompt = buildSystemPrompt(repoMap, context);
258
+ const repoMap = await buildRepoMap(context.cwd, {
259
+ maxDepth: loadConfig().preferences.repoMap?.maxDepth,
260
+ maxFiles: loadConfig().preferences.repoMap?.maxFiles,
261
+ });
262
+ // Phase 3.2 — auto-collect cross-file references for the files
263
+ // this run is likely to mutate (user-pinned files via /select).
264
+ // The block is empty if no LSP server is on $PATH, so adding it
265
+ // unconditionally is safe on machines without an LSP installed.
266
+ let referencesBlock = '';
267
+ if (context.selectedFiles && context.selectedFiles.length > 0) {
268
+ try {
269
+ const { gatherReferencesForTargets } = await import('./context-builder.js');
270
+ const { getLspManager } = await import('./tool-executor.js');
271
+ referencesBlock = await gatherReferencesForTargets(context.cwd, context.selectedFiles.map((f) => ({ file: f })), () => getLspManager(context.cwd));
272
+ }
273
+ catch {
274
+ // safe: any failure in the LSP path must not block the run
275
+ }
276
+ }
277
+ const systemPrompt = referencesBlock
278
+ ? `${buildSystemPrompt(repoMap, context)}\n\n${referencesBlock}`
279
+ : buildSystemPrompt(repoMap, context);
227
280
  // Auto-compact before building messages if context is near limit
228
281
  await this.autoCompactIfNeeded(conversation, systemPrompt, context.task, context.model);
229
282
  // Pillar 4 — proactive budget enforcement
@@ -284,6 +337,27 @@ export class SingleAgent {
284
337
  const budget = safety.toolCalls;
285
338
  let toolCallLimit = Math.max(1, budget.softLimit);
286
339
  const toolCallHardLimit = Math.max(toolCallLimit, budget.hardLimit);
340
+ /**
341
+ * Investigation budget — applies when the agent has only invoked
342
+ * read-only tools so far. Audits, reviews, and "find vulnerabilities"
343
+ * tasks routinely need to read 80+ files before answering; if we
344
+ * cap them at `hardLimit` they force the user to type `continue`
345
+ * mid-investigation (the failure mode seen in Test 2 of the log).
346
+ * Snaps back to `hardLimit` the moment a mutation fires.
347
+ */
348
+ const investigationMultiplier = Math.max(1, budget.investigationMultiplier ?? 1);
349
+ const toolCallInvestigationCeiling = Math.max(toolCallHardLimit, Math.floor(toolCallHardLimit * investigationMultiplier));
350
+ let anyMutationSeen = false;
351
+ let investigationModeAnnounced = false;
352
+ // Phase 2.2 — automatic post-edit verifier. After the tool loop
353
+ // reports "no more tool calls", re-check the project's tests
354
+ // (when configured) and — on failure — push a repair-request
355
+ // back into the same conversation up to `autoVerifyMaxRepairs`
356
+ // times before returning. Disabled outside BUILD mode and when
357
+ // no file-mutating tool ran. Gate + classification + message
358
+ // shape live in ./auto-verifier (testable in isolation).
359
+ let autoVerifyRepairsUsed = 0;
360
+ const autoVerifyMaxRepairs = Math.max(0, safety.autoVerifyMaxRepairs ?? 1);
287
361
  // Pillar 2 — semantic loop detector. Tracks per-file frequency so
288
362
  // an LLM which varies its search arguments but keeps hammering
289
363
  // the same file still trips. The composite LoopTrapDetector is
@@ -291,6 +365,15 @@ export class SingleAgent {
291
365
  // detectors run in parallel; the semantic one covers the most
292
366
  // common accidental "stare at one file" failure mode.
293
367
  const semanticLoopDetector = new SemanticLoopDetector(safety.semanticLoopTrap);
368
+ // Phase 1b — opt-in sliding-window block accounting. Default is OFF
369
+ // (legacy session-lifetime lockout) until Phase 7 flips the default
370
+ // after soak. Sliding mode prevents the "immortal file" deadlock
371
+ // observed in the June 22, 2026 log session.
372
+ const loopGuardConfig = getAgentLoopGuardConfig();
373
+ const loopMitigation = new LoopMitigationTracker({
374
+ useSlidingWindow: loopGuardConfig.useSlidingWindow,
375
+ blockWindowTurns: loopGuardConfig.blockWindowTurns,
376
+ });
294
377
  let pendingSafetyDirective = null;
295
378
  // Pillar 5 — per-turn background-job awareness. The LLM
296
379
  // routinely forgets jobs it spawned earlier; we counter that by
@@ -304,21 +387,36 @@ export class SingleAgent {
304
387
  // mid-run create/update/delete surfaces as a [Project
305
388
  // Instructions] directive on the next chat().
306
389
  const fixoMdWatcher = new FixoMdWatcher(context.cwd);
307
- const indicator = new TaskStatusIndicator();
390
+ const indicator = new LoadingAnimation();
308
391
  indicator.start();
392
+ let lastUsage = null;
309
393
  try {
310
394
  while (toolCallCount < toolCallLimit) {
311
395
  // Auto-extend the budget when the agent is at the soft limit
312
396
  // but the semantic loop detector is quiet — i.e. the work is
313
- // still progressing, not thrashing. Capped at hardLimit.
397
+ // still progressing, not thrashing. Capped at hardLimit for
398
+ // mutating runs; lifted to the investigation ceiling
399
+ // (hardLimit * investigationMultiplier) while only read-only
400
+ // tools have fired.
314
401
  if (budget.autoExtend &&
315
402
  toolCallCount + 1 >= toolCallLimit &&
316
- toolCallLimit < toolCallHardLimit &&
317
403
  pendingSafetyDirective === null) {
318
- const previous = toolCallLimit;
319
- toolCallLimit = Math.min(toolCallHardLimit, toolCallLimit * 2);
320
- if (toolCallLimit > previous) {
321
- console.log(`${colors.dim}↳ tool-call budget extended ${previous} → ${toolCallLimit} (no loop detected)${colors.reset}`);
404
+ const ceiling = !anyMutationSeen && investigationMultiplier > 1
405
+ ? toolCallInvestigationCeiling
406
+ : toolCallHardLimit;
407
+ if (toolCallLimit < ceiling) {
408
+ const previous = toolCallLimit;
409
+ toolCallLimit = Math.min(ceiling, toolCallLimit * 2);
410
+ if (toolCallLimit > previous) {
411
+ const investigation = !anyMutationSeen && investigationMultiplier > 1;
412
+ if (investigation && !investigationModeAnnounced) {
413
+ console.log(`${colors.dim}ⓘ Investigation mode — extended budget to ${toolCallLimit} (read-only tools only).${colors.reset}`);
414
+ investigationModeAnnounced = true;
415
+ }
416
+ else if (!investigation) {
417
+ console.log(`${colors.dim}↳ tool-call budget extended ${previous} → ${toolCallLimit} (no loop detected)${colors.reset}`);
418
+ }
419
+ }
322
420
  }
323
421
  }
324
422
  // Background-job awareness: surface newly-finished and
@@ -343,8 +441,8 @@ export class SingleAgent {
343
441
  injectSafetyDirective(fixoDirective);
344
442
  }
345
443
  }
346
- const spinner = promptsWrapper.spinner();
347
- spinner.start(`⚡ Agent is analyzing context paths… (turn ${toolCallCount + 1})`);
444
+ indicator.setPhase({ id: 'reasoning', label: 'Reasoning…', detail: 'Analyzing context paths', icon: '⚡' });
445
+ indicator.setTurn(toolCallCount + 1);
348
446
  dashboard.emit({
349
447
  type: 'turn-start',
350
448
  turnIndex: toolCallCount + 1,
@@ -366,7 +464,7 @@ export class SingleAgent {
366
464
  catch (err) {
367
465
  // Handle context overflow — auto-compact and retry once
368
466
  if (ConversationManager.isContextOverflowError(err)) {
369
- spinner.stop('🔄 Context overflow detected');
467
+ indicator.setPhase({ id: 'reasoning', label: 'Context full…', detail: 'Auto-compacting history', icon: '🔄' });
370
468
  console.log(`${colors.yellow}🔄 Context window full — auto-compacting...${colors.reset}`);
371
469
  const compacted = await conversation.compact(this.client, context.model);
372
470
  if (compacted) {
@@ -381,7 +479,6 @@ export class SingleAgent {
381
479
  throw err;
382
480
  }
383
481
  finally {
384
- spinner.stop('🤖 Thought completed');
385
482
  dashboard.emit({
386
483
  type: 'status',
387
484
  message: `Turn ${toolCallCount + 1} complete`,
@@ -390,15 +487,47 @@ export class SingleAgent {
390
487
  totalUsage.prompt_tokens += result.usage.prompt_tokens;
391
488
  totalUsage.completion_tokens += result.usage.completion_tokens;
392
489
  totalUsage.total_tokens += result.usage.total_tokens;
393
- // No tool calls → stream final response
490
+ lastUsage = result.usage;
491
+ // No tool calls → potentially run the auto-verifier, then
492
+ // either continue the loop (one repair pass) or return.
394
493
  if (!result.tool_calls || result.tool_calls.length === 0) {
395
494
  const response = result.content ?? '';
396
495
  // Print the response (already received in non-streaming mode)
397
496
  if (response) {
398
497
  renderMarkdown(response);
399
498
  }
499
+ // Phase 2.2 — automatic verifier.
500
+ const verifyGate = decideAutoVerify({
501
+ safety,
502
+ context,
503
+ modifiedFilesCount: modifiedFiles.length,
504
+ repairsUsed: autoVerifyRepairsUsed,
505
+ });
506
+ if (verifyGate.run) {
507
+ const { runProjectTests } = await import('../test-runner.js');
508
+ const verifyOutput = runProjectTests(context.cwd);
509
+ const outcome = classifyVerifyOutput(verifyOutput);
510
+ if (outcome === 'failing') {
511
+ autoVerifyRepairsUsed += 1;
512
+ console.log(`\n${colors.yellow}🔍 [Auto-Verify] Verification failed (repair attempt ${autoVerifyRepairsUsed}/${autoVerifyMaxRepairs}). Asking the model to fix...${colors.reset}`);
513
+ if (this.verbose) {
514
+ console.log(`${colors.dim}${verifyOutput}${colors.reset}\n`);
515
+ }
516
+ messages.push({ role: 'assistant', content: response });
517
+ messages.push({ role: 'user', content: buildRepairMessage(verifyOutput) });
518
+ // Counts toward tool budget so pathological repairs
519
+ // don't extend the run indefinitely.
520
+ toolCallCount += 1;
521
+ continue;
522
+ }
523
+ // outcome === 'passing' or 'no-command' → fall through
524
+ // to the success return below.
525
+ }
400
526
  indicator.stop();
401
527
  conversation.addTurn(context.task, response);
528
+ if (result.usage && result.usage.total_tokens) {
529
+ conversation.setProviderReportedTokens(result.usage.total_tokens);
530
+ }
402
531
  taskSession.finish('success', response);
403
532
  return {
404
533
  success: true,
@@ -439,6 +568,13 @@ export class SingleAgent {
439
568
  pendingSafetyDirective = toSafetyAlertDirective(verdict);
440
569
  console.log(`${colors.yellow}⚠ Semantic loop warning: ${verdict.target} ` +
441
570
  `accessed ${verdict.count}× in the last ${verdict.windowSize} turns.${colors.reset}`);
571
+ const nowBlocking = loopMitigation.recordWarn(verdict.target, toolCallCount);
572
+ if (nowBlocking) {
573
+ const blockMsg = loopGuardConfig.useSlidingWindow
574
+ ? `Further reads of ${verdict.target} will be rejected for the next ${loopGuardConfig.blockWindowTurns} turns — agent will be forced to pivot.`
575
+ : `Further reads of ${verdict.target} will be rejected this session — agent will be forced to pivot.`;
576
+ console.log(`${colors.yellow}⚠ ${blockMsg}${colors.reset}`);
577
+ }
442
578
  }
443
579
  else if (verdict.state === 'hard-abort') {
444
580
  // Rollback any staged writes from this run before
@@ -462,6 +598,41 @@ export class SingleAgent {
462
598
  injectSafetyDirective(pendingSafetyDirective);
463
599
  pendingSafetyDirective = null;
464
600
  }
601
+ // Active loop mitigation: if the model is trying to read
602
+ // a target the loop-trap has already warned on N times,
603
+ // short-circuit with a tool-error result instead of letting
604
+ // the LLM stare at the same file again. The mitigation
605
+ // tracker is per-session, so a future user task can re-read
606
+ // the same file freely.
607
+ if (isReadTool(toolCall.function.name) &&
608
+ typeof parsedArgs.path === 'string' &&
609
+ loopMitigation.isBlocked(parsedArgs.path, toolCallCount)) {
610
+ const warns = loopMitigation.warnsFor(parsedArgs.path, toolCallCount);
611
+ const blockedResult = buildLoopBlockedReadResult(parsedArgs.path, warns);
612
+ console.log(`${colors.yellow}⚠ Loop-blocked read intercepted: ${parsedArgs.path}${colors.reset}`);
613
+ messages.push({
614
+ role: 'tool',
615
+ tool_call_id: toolCall.id,
616
+ content: blockedResult,
617
+ });
618
+ toolCallCount++;
619
+ continue;
620
+ }
621
+ // Phase 1b — escape valve for the loop-mitigation deadlock.
622
+ // If the model is now trying to MUTATE a loop-blocked file
623
+ // (write, rename, delete, patch), the prior canMutate check
624
+ // would refuse it because the read was never satisfied. We
625
+ // register a forced read hash on the session so the next
626
+ // canMutate call succeeds — preserving the staleness-check
627
+ // intent without trapping the file as "immortal". Clearing
628
+ // the loop block as well prevents the lockout from carrying
629
+ // over after the pivot has already happened.
630
+ if (MUTATING_TOOL_NAMES.has(toolCall.function.name) &&
631
+ typeof parsedArgs.path === 'string' &&
632
+ loopMitigation.isBlocked(parsedArgs.path, toolCallCount)) {
633
+ taskSession.noteReadForMutation(parsedArgs.path);
634
+ loopMitigation.reset(parsedArgs.path);
635
+ }
465
636
  const allowed = await this.askPermission(toolCall.function.name, parsedArgs, rl, context.yes);
466
637
  let event;
467
638
  if (!allowed) {
@@ -482,6 +653,19 @@ export class SingleAgent {
482
653
  }
483
654
  else {
484
655
  const toolStart = Date.now();
656
+ // Set dynamic phase based on tool kind
657
+ if (isReadTool(toolCall.function.name)) {
658
+ indicator.setPhase({ id: 'reading', label: 'Reading codebase…', detail: parsedArgs.path || parsedArgs.from || '', icon: '✦' });
659
+ }
660
+ else if (toolCall.function.name === 'run_command' || toolCall.function.name === 'run_command_async') {
661
+ indicator.setPhase({ id: 'executing', label: 'Running command…', detail: parsedArgs.command || '', icon: '$' });
662
+ }
663
+ else if (toolCall.function.name === 'search_code' || toolCall.function.name === 'search_symbols') {
664
+ indicator.setPhase({ id: 'searching', label: 'Searching…', detail: parsedArgs.query || '', icon: '⌕' });
665
+ }
666
+ else {
667
+ indicator.setPhase({ id: 'writing', label: 'Writing code…', detail: parsedArgs.path || parsedArgs.file || '', icon: '✎' });
668
+ }
485
669
  dashboard.emit({
486
670
  type: 'tool-start',
487
671
  tool: toolCall.function.name,
@@ -507,7 +691,18 @@ export class SingleAgent {
507
691
  modifiedFiles.push(event.affectedPath);
508
692
  }
509
693
  }
510
- let toolResult = event.result;
694
+ // Investigation-budget gate: any mutating tool snaps the
695
+ // ceiling back to hardLimit on the next iteration. We check
696
+ // the tool name (not just event.isWrite) because run_command
697
+ // is mutating-by-default even when it doesn't touch a file.
698
+ if (!anyMutationSeen &&
699
+ (event.isWrite || MUTATING_TOOL_NAMES.has(toolCall.function.name))) {
700
+ anyMutationSeen = true;
701
+ if (toolCallLimit > toolCallHardLimit) {
702
+ toolCallLimit = toolCallHardLimit;
703
+ }
704
+ }
705
+ let toolResult = sanitizeUserContent(event.result);
511
706
  if (toolResult.length > MAX_TOOL_RESULT_LENGTH) {
512
707
  toolResult =
513
708
  toolResult.slice(0, MAX_TOOL_RESULT_LENGTH) +
@@ -524,6 +719,9 @@ export class SingleAgent {
524
719
  indicator.stop();
525
720
  console.log(`${colors.yellow}⚠ Tool call limit reached (${toolCallLimit}).${colors.reset}`);
526
721
  conversation.addTurn(context.task, `Task processed with ${toolCallCount} tool calls.`);
722
+ if (lastUsage && lastUsage.total_tokens) {
723
+ conversation.setProviderReportedTokens(lastUsage.total_tokens);
724
+ }
527
725
  const limitResponse = `Completed with ${toolCallCount} tool calls (limit reached).`;
528
726
  taskSession.finish('success', limitResponse);
529
727
  return {
@@ -553,20 +751,7 @@ export class SingleAgent {
553
751
  * are auto-allowed.
554
752
  */
555
753
  async askPermission(name, args, rl, allowWithoutPrompt) {
556
- const MUTATING_TOOLS = new Set([
557
- 'write_file',
558
- 'run_command',
559
- 'apply_patch',
560
- 'replace_range',
561
- 'insert_after',
562
- 'rename_file',
563
- 'delete_file',
564
- 'create_branch',
565
- 'commit_changes',
566
- 'push_branch',
567
- 'create_pull_request',
568
- ]);
569
- if (!MUTATING_TOOLS.has(name)) {
754
+ if (!MUTATING_TOOL_NAMES.has(name)) {
570
755
  return true;
571
756
  }
572
757
  if (allowWithoutPrompt || this.allowAll) {
@@ -660,7 +845,10 @@ export class SingleAgent {
660
845
  async executePureChatStream(task, conversation, context) {
661
846
  const startTime = Date.now();
662
847
  const totalUsage = { prompt_tokens: 0, completion_tokens: 0, total_tokens: 0 };
663
- const repoMap = buildRepoMap(context.cwd);
848
+ const repoMap = await buildRepoMap(context.cwd, {
849
+ maxDepth: loadConfig().preferences.repoMap?.maxDepth,
850
+ maxFiles: loadConfig().preferences.repoMap?.maxFiles,
851
+ });
664
852
  const systemPrompt = buildSystemPrompt(repoMap, context, false);
665
853
  // Auto-compact before chat if context is near limit
666
854
  await this.autoCompactIfNeeded(conversation, systemPrompt, task, context.model);