@visorcraft/idlehands 1.1.16 → 1.2.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 (212) hide show
  1. package/dist/agent/formatting.js +30 -13
  2. package/dist/agent/formatting.js.map +1 -1
  3. package/dist/agent/review-artifact.js +12 -8
  4. package/dist/agent/review-artifact.js.map +1 -1
  5. package/dist/agent/tool-calls.js +62 -21
  6. package/dist/agent/tool-calls.js.map +1 -1
  7. package/dist/agent/tool-loop-detection.js +310 -0
  8. package/dist/agent/tool-loop-detection.js.map +1 -0
  9. package/dist/agent/tool-loop-guard.js +235 -0
  10. package/dist/agent/tool-loop-guard.js.map +1 -0
  11. package/dist/agent.js +585 -144
  12. package/dist/agent.js.map +1 -1
  13. package/dist/anton/controller.js +46 -30
  14. package/dist/anton/controller.js.map +1 -1
  15. package/dist/anton/lock.js +5 -1
  16. package/dist/anton/lock.js.map +1 -1
  17. package/dist/anton/parser.js +18 -19
  18. package/dist/anton/parser.js.map +1 -1
  19. package/dist/anton/prompt.js +42 -11
  20. package/dist/anton/prompt.js.map +1 -1
  21. package/dist/anton/reporter.js.map +1 -1
  22. package/dist/anton/session.js.map +1 -1
  23. package/dist/anton/verifier.js +3 -5
  24. package/dist/anton/verifier.js.map +1 -1
  25. package/dist/bench/compare.js +53 -20
  26. package/dist/bench/compare.js.map +1 -1
  27. package/dist/bench/openclaw.js +4 -4
  28. package/dist/bench/openclaw.js.map +1 -1
  29. package/dist/bench/report.js +11 -3
  30. package/dist/bench/report.js.map +1 -1
  31. package/dist/bench/runner.js +20 -14
  32. package/dist/bench/runner.js.map +1 -1
  33. package/dist/bot/commands.js +69 -26
  34. package/dist/bot/commands.js.map +1 -1
  35. package/dist/bot/confirm-discord.js +32 -9
  36. package/dist/bot/confirm-discord.js.map +1 -1
  37. package/dist/bot/confirm-telegram.js +26 -10
  38. package/dist/bot/confirm-telegram.js.map +1 -1
  39. package/dist/bot/dir-guard.js +18 -3
  40. package/dist/bot/dir-guard.js.map +1 -1
  41. package/dist/bot/discord-routing.js +28 -4
  42. package/dist/bot/discord-routing.js.map +1 -1
  43. package/dist/bot/discord-streaming.js +3 -3
  44. package/dist/bot/discord-streaming.js.map +1 -1
  45. package/dist/bot/discord.js +93 -37
  46. package/dist/bot/discord.js.map +1 -1
  47. package/dist/bot/escalation.js +124 -0
  48. package/dist/bot/escalation.js.map +1 -0
  49. package/dist/bot/format.js +2 -5
  50. package/dist/bot/format.js.map +1 -1
  51. package/dist/bot/session-manager.js +17 -6
  52. package/dist/bot/session-manager.js.map +1 -1
  53. package/dist/bot/telegram.js +92 -29
  54. package/dist/bot/telegram.js.map +1 -1
  55. package/dist/cli/agent-turn.js +10 -4
  56. package/dist/cli/agent-turn.js.map +1 -1
  57. package/dist/cli/args.js +51 -9
  58. package/dist/cli/args.js.map +1 -1
  59. package/dist/cli/bot.js +19 -9
  60. package/dist/cli/bot.js.map +1 -1
  61. package/dist/cli/build-repl-context.js +60 -26
  62. package/dist/cli/build-repl-context.js.map +1 -1
  63. package/dist/cli/command-registry.js.map +1 -1
  64. package/dist/cli/commands/anton.js +5 -3
  65. package/dist/cli/commands/anton.js.map +1 -1
  66. package/dist/cli/commands/editing.js +27 -12
  67. package/dist/cli/commands/editing.js.map +1 -1
  68. package/dist/cli/commands/model.js +16 -7
  69. package/dist/cli/commands/model.js.map +1 -1
  70. package/dist/cli/commands/project.js +52 -17
  71. package/dist/cli/commands/project.js.map +1 -1
  72. package/dist/cli/commands/runtime.js +1 -1
  73. package/dist/cli/commands/runtime.js.map +1 -1
  74. package/dist/cli/commands/secrets.js +279 -0
  75. package/dist/cli/commands/secrets.js.map +1 -0
  76. package/dist/cli/commands/session.js +57 -2
  77. package/dist/cli/commands/session.js.map +1 -1
  78. package/dist/cli/commands/tools.js +3 -1
  79. package/dist/cli/commands/tools.js.map +1 -1
  80. package/dist/cli/commands/trifecta.js +1 -1
  81. package/dist/cli/commands/trifecta.js.map +1 -1
  82. package/dist/cli/commands/tui.js.map +1 -1
  83. package/dist/cli/init.js +50 -16
  84. package/dist/cli/init.js.map +1 -1
  85. package/dist/cli/input.js +25 -7
  86. package/dist/cli/input.js.map +1 -1
  87. package/dist/cli/oneshot.js +31 -19
  88. package/dist/cli/oneshot.js.map +1 -1
  89. package/dist/cli/repl-dispatch.js +10 -6
  90. package/dist/cli/repl-dispatch.js.map +1 -1
  91. package/dist/cli/runtime-cmds.js +110 -46
  92. package/dist/cli/runtime-cmds.js.map +1 -1
  93. package/dist/cli/service.js +3 -3
  94. package/dist/cli/service.js.map +1 -1
  95. package/dist/cli/session-state.js +12 -5
  96. package/dist/cli/session-state.js.map +1 -1
  97. package/dist/cli/setup.js +86 -33
  98. package/dist/cli/setup.js.map +1 -1
  99. package/dist/cli/shell.js +4 -4
  100. package/dist/cli/shell.js.map +1 -1
  101. package/dist/cli/status.js +56 -12
  102. package/dist/cli/status.js.map +1 -1
  103. package/dist/client.js +40 -21
  104. package/dist/client.js.map +1 -1
  105. package/dist/commands.js +1 -1
  106. package/dist/commands.js.map +1 -1
  107. package/dist/config.js +171 -15
  108. package/dist/config.js.map +1 -1
  109. package/dist/confirm/auto.js.map +1 -1
  110. package/dist/confirm/headless.js +13 -2
  111. package/dist/confirm/headless.js.map +1 -1
  112. package/dist/confirm/terminal.js +1 -5
  113. package/dist/confirm/terminal.js.map +1 -1
  114. package/dist/context.js +9 -3
  115. package/dist/context.js.map +1 -1
  116. package/dist/git.js +56 -61
  117. package/dist/git.js.map +1 -1
  118. package/dist/harnesses.js +137 -37
  119. package/dist/harnesses.js.map +1 -1
  120. package/dist/history.js +12 -4
  121. package/dist/history.js.map +1 -1
  122. package/dist/hooks/index.js +2 -2
  123. package/dist/hooks/index.js.map +1 -1
  124. package/dist/hooks/loader.js +6 -5
  125. package/dist/hooks/loader.js.map +1 -1
  126. package/dist/hooks/manager.js.map +1 -1
  127. package/dist/hooks/plugins/example-console.js.map +1 -1
  128. package/dist/hooks/scaffold.js +8 -6
  129. package/dist/hooks/scaffold.js.map +1 -1
  130. package/dist/index.js +120 -66
  131. package/dist/index.js.map +1 -1
  132. package/dist/indexer.js +6 -18
  133. package/dist/indexer.js.map +1 -1
  134. package/dist/jsonrpc.js.map +1 -1
  135. package/dist/lens.js +38 -16
  136. package/dist/lens.js.map +1 -1
  137. package/dist/lsp.js +60 -24
  138. package/dist/lsp.js.map +1 -1
  139. package/dist/markdown.js +6 -6
  140. package/dist/markdown.js.map +1 -1
  141. package/dist/mcp.js +15 -6
  142. package/dist/mcp.js.map +1 -1
  143. package/dist/model-customization.js +7 -3
  144. package/dist/model-customization.js.map +1 -1
  145. package/dist/progress/message-edit-scheduler.js +15 -3
  146. package/dist/progress/message-edit-scheduler.js.map +1 -1
  147. package/dist/progress/progress-message-renderer.js.map +1 -1
  148. package/dist/progress/progress-presenter.js +3 -3
  149. package/dist/progress/progress-presenter.js.map +1 -1
  150. package/dist/progress/serialize-telegram.js.map +1 -1
  151. package/dist/progress/tool-summary.js +3 -1
  152. package/dist/progress/tool-summary.js.map +1 -1
  153. package/dist/progress/turn-progress.js +3 -1
  154. package/dist/progress/turn-progress.js.map +1 -1
  155. package/dist/recovery.js +11 -3
  156. package/dist/recovery.js.map +1 -1
  157. package/dist/replay.js +9 -3
  158. package/dist/replay.js.map +1 -1
  159. package/dist/replay_cli.js +5 -3
  160. package/dist/replay_cli.js.map +1 -1
  161. package/dist/runtime/executor.js +66 -20
  162. package/dist/runtime/executor.js.map +1 -1
  163. package/dist/runtime/health.js.map +1 -1
  164. package/dist/runtime/host-runner.js +103 -0
  165. package/dist/runtime/host-runner.js.map +1 -0
  166. package/dist/runtime/planner.js +3 -1
  167. package/dist/runtime/planner.js.map +1 -1
  168. package/dist/runtime/secrets.js +102 -0
  169. package/dist/runtime/secrets.js.map +1 -0
  170. package/dist/runtime/store.js +95 -19
  171. package/dist/runtime/store.js.map +1 -1
  172. package/dist/safety.js +38 -21
  173. package/dist/safety.js.map +1 -1
  174. package/dist/spinner.js +7 -8
  175. package/dist/spinner.js.map +1 -1
  176. package/dist/sys/context.js +3 -3
  177. package/dist/sys/context.js.map +1 -1
  178. package/dist/term.js +1 -1
  179. package/dist/term.js.map +1 -1
  180. package/dist/themes.js +11 -5
  181. package/dist/themes.js.map +1 -1
  182. package/dist/tools/tool-error.js +2 -5
  183. package/dist/tools/tool-error.js.map +1 -1
  184. package/dist/tools.js +84 -35
  185. package/dist/tools.js.map +1 -1
  186. package/dist/tui/branch-picker.js +9 -3
  187. package/dist/tui/branch-picker.js.map +1 -1
  188. package/dist/tui/command-handler.js +88 -36
  189. package/dist/tui/command-handler.js.map +1 -1
  190. package/dist/tui/confirm.js.map +1 -1
  191. package/dist/tui/controller.js +234 -117
  192. package/dist/tui/controller.js.map +1 -1
  193. package/dist/tui/event-bridge.js.map +1 -1
  194. package/dist/tui/keymap.js +93 -71
  195. package/dist/tui/keymap.js.map +1 -1
  196. package/dist/tui/layout.js +9 -1
  197. package/dist/tui/layout.js.map +1 -1
  198. package/dist/tui/render.js +17 -5
  199. package/dist/tui/render.js.map +1 -1
  200. package/dist/tui/screen.js.map +1 -1
  201. package/dist/tui/state.js +129 -63
  202. package/dist/tui/state.js.map +1 -1
  203. package/dist/tui/theme.js +12 -3
  204. package/dist/tui/theme.js.map +1 -1
  205. package/dist/upgrade.js +28 -15
  206. package/dist/upgrade.js.map +1 -1
  207. package/dist/utils.js +8 -5
  208. package/dist/utils.js.map +1 -1
  209. package/dist/vault.js +48 -12
  210. package/dist/vault.js.map +1 -1
  211. package/dist/vim.js.map +1 -1
  212. package/package.json +11 -2
package/dist/themes.js CHANGED
@@ -8,9 +8,9 @@
8
8
  * Built-in: default, dark, light, minimal, hacker
9
9
  * Custom: ~/.config/idlehands/themes/<name>.json
10
10
  */
11
- import pc from 'picocolors';
12
11
  import fs from 'node:fs/promises';
13
12
  import path from 'node:path';
13
+ import pc from 'picocolors';
14
14
  import { configDir } from './utils.js';
15
15
  // All supported picocolors primitives.
16
16
  const PC = {
@@ -31,8 +31,8 @@ const PC = {
31
31
  };
32
32
  /** Resolve a palette string like "bold+cyan" to a composed function. */
33
33
  function resolveColor(spec) {
34
- const parts = spec.split('+').map(p => p.trim().toLowerCase());
35
- const fns = parts.map(p => PC[p]).filter(Boolean);
34
+ const parts = spec.split('+').map((p) => p.trim().toLowerCase());
35
+ const fns = parts.map((p) => PC[p]).filter(Boolean);
36
36
  if (fns.length === 0)
37
37
  return undefined;
38
38
  if (fns.length === 1)
@@ -41,8 +41,14 @@ function resolveColor(spec) {
41
41
  }
42
42
  /** The default (identity) palette — no remapping. */
43
43
  const DEFAULT_PALETTE = {
44
- dim: 'dim', bold: 'bold', red: 'red', yellow: 'yellow',
45
- green: 'green', cyan: 'cyan', magenta: 'magenta', blue: 'blue',
44
+ dim: 'dim',
45
+ bold: 'bold',
46
+ red: 'red',
47
+ yellow: 'yellow',
48
+ green: 'green',
49
+ cyan: 'cyan',
50
+ magenta: 'magenta',
51
+ blue: 'blue',
46
52
  };
47
53
  const BUILTIN_PALETTES = {
48
54
  default: {},
@@ -1 +1 @@
1
- {"version":3,"file":"themes.js","sourceRoot":"","sources":["../src/themes.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"themes.js","sourceRoot":"","sources":["../src/themes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAevC,uCAAuC;AACvC,MAAM,EAAE,GAA0C;IAChD,GAAG,EAAE,EAAE,CAAC,GAAG;IACX,IAAI,EAAE,EAAE,CAAC,IAAI;IACb,MAAM,EAAE,EAAE,CAAC,MAAM;IACjB,SAAS,EAAE,EAAE,CAAC,SAAS;IACvB,OAAO,EAAE,EAAE,CAAC,OAAO;IACnB,GAAG,EAAE,EAAE,CAAC,GAAG;IACX,MAAM,EAAE,EAAE,CAAC,MAAM;IACjB,KAAK,EAAE,EAAE,CAAC,KAAK;IACf,IAAI,EAAE,EAAE,CAAC,IAAI;IACb,OAAO,EAAE,EAAE,CAAC,OAAO;IACnB,IAAI,EAAE,EAAE,CAAC,IAAI;IACb,KAAK,EAAE,EAAE,CAAC,KAAK;IACf,IAAI,EAAE,EAAE,CAAC,IAAI;IACb,KAAK,EAAE,EAAE,CAAC,KAAK;CAChB,CAAC;AAEF,wEAAwE;AACxE,SAAS,YAAY,CAAC,IAAY;IAChC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;IACjE,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACpD,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IACvC,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC;IACpC,OAAO,CAAC,CAAS,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;AAC5D,CAAC;AAED,qDAAqD;AACrD,MAAM,eAAe,GAA2B;IAC9C,GAAG,EAAE,KAAK;IACV,IAAI,EAAE,MAAM;IACZ,GAAG,EAAE,KAAK;IACV,MAAM,EAAE,QAAQ;IAChB,KAAK,EAAE,OAAO;IACd,IAAI,EAAE,MAAM;IACZ,OAAO,EAAE,SAAS;IAClB,IAAI,EAAE,MAAM;CACb,CAAC;AAEF,MAAM,gBAAgB,GAAiC;IACrD,OAAO,EAAE,EAAE;IACX,IAAI,EAAE;QACJ,IAAI,EAAE,WAAW;QACjB,OAAO,EAAE,cAAc;QACvB,IAAI,EAAE,WAAW;KAClB;IACD,KAAK,EAAE;QACL,GAAG,EAAE,MAAM;QACX,IAAI,EAAE,MAAM;QACZ,IAAI,EAAE,MAAM;KACb;IACD,OAAO,EAAE;QACP,MAAM,EAAE,KAAK;QACb,KAAK,EAAE,KAAK;QACZ,IAAI,EAAE,KAAK;QACX,OAAO,EAAE,KAAK;QACd,IAAI,EAAE,KAAK;KACZ;IACD,MAAM,EAAE;QACN,IAAI,EAAE,YAAY;QAClB,MAAM,EAAE,OAAO;QACf,IAAI,EAAE,OAAO;QACb,OAAO,EAAE,OAAO;QAChB,IAAI,EAAE,OAAO;KACd;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,mBAAmB,GAAG,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;AAEjE,6EAA6E;AAC7E,MAAM,UAAU,cAAc,CAAC,OAAqB;IAClD,MAAM,GAAG,GAAG,EAAc,CAAC;IAC3B,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,eAAe,CAAgB,EAAE,CAAC;QAC/D,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,eAAe,CAAC,IAAI,CAAC,CAAC;QACpD,MAAM,EAAE,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;QAC9B,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC;IAC9C,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,iDAAiD;AACjD,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,MAAM,CAAC,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;IACjC,IAAI,CAAC,CAAC;QAAE,OAAO,SAAS,CAAC;IACzB,OAAO,cAAc,CAAC,CAAC,CAAC,CAAC;AAC3B,CAAC;AAED,+BAA+B;AAC/B,MAAM,UAAU,eAAe;IAC7B,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,QAAQ,CAAC,CAAC;AAC1C,CAAC;AAED,sEAAsE;AACtE,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,IAAY;IAChD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,EAAE,GAAG,IAAI,OAAO,CAAC,CAAC;IAC9D,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAChD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC/B,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ;YAAE,OAAO,SAAS,CAAC;QAC5D,OAAO,cAAc,CAAC,MAAsB,CAAC,CAAC;IAChD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,iEAAiE;AACjE,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,IAAY;IAC7C,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IACnC,IAAI,OAAO;QAAE,OAAO,OAAO,CAAC;IAC5B,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC;AAC/B,CAAC;AAED,sDAAsD;AACtD,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,MAAM,OAAO,GAAG,CAAC,GAAG,mBAAmB,CAAC,CAAC;IACzC,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,eAAe,EAAE,CAAC;QAC9B,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QAC/D,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;YACxB,IAAI,CAAC,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC3C,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,CAAC;YAC7C,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,uBAAuB;IACzB,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;AAC7B,CAAC"}
@@ -19,10 +19,7 @@ export class ToolError extends Error {
19
19
  * Format as a concise tool result content string
20
20
  */
21
21
  toToolResult() {
22
- const lines = [
23
- `ERROR: code=${this.code} retryable=${this.retryable}`,
24
- `msg=${this.message}`
25
- ];
22
+ const lines = [`ERROR: code=${this.code} retryable=${this.retryable}`, `msg=${this.message}`];
26
23
  if (this.hint) {
27
24
  lines.push(`hint=${this.hint}`);
28
25
  }
@@ -76,7 +73,7 @@ export class ToolError extends Error {
76
73
  export class ValidationError extends ToolError {
77
74
  errors;
78
75
  constructor(errors) {
79
- super('invalid_args', `Validation failed: ${errors.map(e => e.message).join('; ')}`, false, undefined, { fields: errors.map(e => e.field) });
76
+ super('invalid_args', `Validation failed: ${errors.map((e) => e.message).join('; ')}`, false, undefined, { fields: errors.map((e) => e.field) });
80
77
  this.errors = errors;
81
78
  this.name = 'ValidationError';
82
79
  }
@@ -1 +1 @@
1
- {"version":3,"file":"tool-error.js","sourceRoot":"","sources":["../../src/tools/tool-error.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tool-error.js","sourceRoot":"","sources":["../../src/tools/tool-error.ts"],"names":[],"mappings":"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"}
package/dist/tools.js CHANGED
@@ -279,8 +279,10 @@ export async function undo_path(ctx, args) {
279
279
  const p = directPath ? resolvePath(ctx, directPath) : ctx.lastEditedPath;
280
280
  if (!p)
281
281
  throw new Error('undo: missing path');
282
+ const absCwd = path.resolve(ctx.cwd);
283
+ const redactedPath = redactPath(p, absCwd);
282
284
  if (!ctx.noConfirm && ctx.confirm) {
283
- const ok = await ctx.confirm(`Restore latest backup for:\n ${p}\nThis will overwrite the current file. Proceed? (y/N) `);
285
+ const ok = await ctx.confirm(`Restore latest backup for:\n ${redactedPath}\nThis will overwrite the current file. Proceed? (y/N) `);
284
286
  if (!ok)
285
287
  return 'undo: cancelled';
286
288
  }
@@ -288,11 +290,13 @@ export async function undo_path(ctx, args) {
288
290
  throw new Error('undo: confirmation required (run with --no-confirm/--yolo or in interactive mode)');
289
291
  }
290
292
  if (ctx.dryRun)
291
- return `dry-run: would restore latest backup for ${p}`;
293
+ return `dry-run: would restore latest backup for ${redactedPath}`;
292
294
  return await restoreLatestBackup(p, ctx);
293
295
  }
294
296
  export async function read_file(ctx, args) {
295
297
  const p = resolvePath(ctx, args?.path);
298
+ const absCwd = path.resolve(ctx.cwd);
299
+ const redactedPath = redactPath(p, absCwd);
296
300
  const offset = args?.offset != null ? Number(args.offset) : undefined;
297
301
  const rawLimit = args?.limit != null ? Number(args.limit) : undefined;
298
302
  const limit = Number.isFinite(rawLimit) && rawLimit > 0
@@ -317,7 +321,7 @@ export async function read_file(ctx, args) {
317
321
  try {
318
322
  const stat = await fs.stat(p);
319
323
  if (stat.isDirectory()) {
320
- return `read_file: "${p}" is a directory, not a file. Use list_dir to see its contents, or search_files to find specific code.`;
324
+ return `read_file: "${redactedPath}" is a directory, not a file. Use list_dir to see its contents, or search_files to find specific code.`;
321
325
  }
322
326
  }
323
327
  catch (e) {
@@ -419,6 +423,8 @@ export async function read_files(ctx, args) {
419
423
  }
420
424
  export async function write_file(ctx, args) {
421
425
  const p = resolvePath(ctx, args?.path);
426
+ const absCwd = path.resolve(ctx.cwd);
427
+ const redactedPath = redactPath(p, absCwd);
422
428
  // Content may arrive as a string (normal) or as a parsed JSON object
423
429
  // (when llama-server's XML parser auto-parses JSON content values).
424
430
  const raw = args?.content;
@@ -434,6 +440,7 @@ export async function write_file(ctx, args) {
434
440
  throw new Error('write_file: missing path');
435
441
  if (content == null)
436
442
  throw new Error('write_file: missing content (got ' + typeof raw + ')');
443
+ const overwrite = Boolean(args?.overwrite ?? args?.force);
437
444
  enforceMutationWithinCwd('write_file', p, ctx);
438
445
  const cwdWarning = checkCwdWarning('write_file', p, ctx);
439
446
  // Path safety check (Phase 9)
@@ -443,7 +450,7 @@ export async function write_file(ctx, args) {
443
450
  }
444
451
  if (pathVerdict.tier === 'cautious' && !ctx.noConfirm) {
445
452
  if (ctx.confirm) {
446
- const ok = await ctx.confirm(pathVerdict.prompt || `Write to ${p}?`, { tool: 'write_file', args: { path: p } });
453
+ const ok = await ctx.confirm(pathVerdict.prompt || `Write to ${redactedPath}?`, { tool: 'write_file', args: { path: p } });
447
454
  if (!ok)
448
455
  throw new Error(`write_file: cancelled by user (${pathVerdict.reason})`);
449
456
  }
@@ -451,8 +458,15 @@ export async function write_file(ctx, args) {
451
458
  throw new Error(`write_file: blocked (${pathVerdict.reason}) without --no-confirm/--yolo`);
452
459
  }
453
460
  }
454
- if (ctx.dryRun)
455
- return `dry-run: would write ${p} (${Buffer.byteLength(content, 'utf8')} bytes)${cwdWarning}`;
461
+ const existingStat = await fs.stat(p).catch(() => null);
462
+ if (existingStat?.isFile() && existingStat.size > 0 && !overwrite) {
463
+ throw new Error(`write_file: refusing to overwrite existing non-empty file ${redactedPath} without explicit overwrite=true (or force=true). ` +
464
+ `Use edit_range/apply_patch for surgical edits, or set overwrite=true for intentional full-file replacement.`);
465
+ }
466
+ if (ctx.dryRun) {
467
+ const mode = existingStat?.isFile() ? (existingStat.size > 0 ? 'overwrite' : 'update-empty') : 'create';
468
+ return `dry-run: would write ${p} (${Buffer.byteLength(content, 'utf8')} bytes, mode=${mode}${overwrite ? ', explicit-overwrite' : ''})${cwdWarning}`;
469
+ }
456
470
  // Phase 9d: snapshot /etc/ files before editing
457
471
  if (ctx.mode === 'sys' && ctx.vault) {
458
472
  await snapshotBeforeEdit(ctx.vault, p).catch(() => { });
@@ -463,10 +477,12 @@ export async function write_file(ctx, args) {
463
477
  ctx.onMutation?.(p);
464
478
  const afterBuf = Buffer.from(content, 'utf8');
465
479
  const replayNote = await checkpointReplay(ctx, { op: 'write_file', filePath: p, before: beforeBuf, after: afterBuf });
466
- return `wrote ${p} (${Buffer.byteLength(content, 'utf8')} bytes)${replayNote}${cwdWarning}`;
480
+ return `wrote ${redactedPath} (${Buffer.byteLength(content, 'utf8')} bytes)${replayNote}${cwdWarning}`;
467
481
  }
468
482
  export async function insert_file(ctx, args) {
469
483
  const p = resolvePath(ctx, args?.path);
484
+ const absCwd = path.resolve(ctx.cwd);
485
+ const redactedPath = redactPath(p, absCwd);
470
486
  const line = Number(args?.line);
471
487
  const rawText = args?.text;
472
488
  const text = typeof rawText === 'string' ? rawText
@@ -485,7 +501,7 @@ export async function insert_file(ctx, args) {
485
501
  }
486
502
  if (pathVerdict.tier === 'cautious' && !ctx.noConfirm) {
487
503
  if (ctx.confirm) {
488
- const ok = await ctx.confirm(pathVerdict.prompt || `Insert into ${p}?`, { tool: 'insert_file', args: { path: p } });
504
+ const ok = await ctx.confirm(pathVerdict.prompt || `Insert into ${redactedPath}?`, { tool: 'insert_file', args: { path: p } });
489
505
  if (!ok)
490
506
  throw new Error(`insert_file: cancelled by user (${pathVerdict.reason})`);
491
507
  }
@@ -494,7 +510,7 @@ export async function insert_file(ctx, args) {
494
510
  }
495
511
  }
496
512
  if (ctx.dryRun)
497
- return `dry-run: would insert into ${p} at line=${line} (${Buffer.byteLength(text, 'utf8')} bytes)`;
513
+ return `dry-run: would insert into ${redactedPath} at line=${line} (${Buffer.byteLength(text, 'utf8')} bytes)`;
498
514
  // Phase 9d: snapshot /etc/ files before editing
499
515
  if (ctx.mode === 'sys' && ctx.vault) {
500
516
  await snapshotBeforeEdit(ctx.vault, p).catch(() => { });
@@ -515,7 +531,7 @@ export async function insert_file(ctx, args) {
515
531
  after: Buffer.from(out, 'utf8')
516
532
  });
517
533
  const cwdWarning = checkCwdWarning('insert_file', p, ctx);
518
- return `inserted into ${p} at 0${replayNote}${cwdWarning}`;
534
+ return `inserted into ${redactedPath} at 0${replayNote}${cwdWarning}`;
519
535
  }
520
536
  const lines = beforeText.split(/\r?\n/);
521
537
  let idx;
@@ -544,10 +560,12 @@ export async function insert_file(ctx, args) {
544
560
  after: Buffer.from(out, 'utf8')
545
561
  });
546
562
  const cwdWarning = checkCwdWarning('insert_file', p, ctx);
547
- return `inserted into ${p} at ${idx}${replayNote}${cwdWarning}`;
563
+ return `inserted into ${redactedPath} at ${idx}${replayNote}${cwdWarning}`;
548
564
  }
549
565
  export async function edit_file(ctx, args) {
550
566
  const p = resolvePath(ctx, args?.path);
567
+ const absCwd = path.resolve(ctx.cwd);
568
+ const redactedPath = redactPath(p, absCwd);
551
569
  const rawOld = args?.old_text;
552
570
  const oldText = typeof rawOld === 'string' ? rawOld
553
571
  : (rawOld != null && typeof rawOld === 'object' ? JSON.stringify(rawOld, null, 2) : undefined);
@@ -569,7 +587,7 @@ export async function edit_file(ctx, args) {
569
587
  }
570
588
  if (pathVerdict.tier === 'cautious' && !ctx.noConfirm) {
571
589
  if (ctx.confirm) {
572
- const ok = await ctx.confirm(pathVerdict.prompt || `Edit ${p}?`, { tool: 'edit_file', args: { path: p, old_text: oldText, new_text: newText } });
590
+ const ok = await ctx.confirm(pathVerdict.prompt || `Edit ${redactedPath}?`, { tool: 'edit_file', args: { path: p, old_text: oldText, new_text: newText } });
573
591
  if (!ok)
574
592
  throw new Error(`edit_file: cancelled by user (${pathVerdict.reason})`);
575
593
  }
@@ -582,7 +600,7 @@ export async function edit_file(ctx, args) {
582
600
  await snapshotBeforeEdit(ctx.vault, p).catch(() => { });
583
601
  }
584
602
  const cur = await fs.readFile(p, 'utf8').catch((e) => {
585
- throw new Error(`edit_file: cannot read ${p}: ${e?.message ?? String(e)}`);
603
+ throw new Error(`edit_file: cannot read ${redactedPath}: ${e?.message ?? String(e)}`);
586
604
  });
587
605
  const idx = cur.indexOf(oldText);
588
606
  if (idx === -1) {
@@ -618,11 +636,11 @@ export async function edit_file(ctx, args) {
618
636
  else {
619
637
  hint = `\nFile head (first 400 chars):\n${cur.slice(0, 400)}`;
620
638
  }
621
- throw new Error(`edit_file: old_text not found in ${p}. Re-read the file and retry with exact text.${hint}`);
639
+ throw new Error(`edit_file: old_text not found in ${redactedPath}. Re-read the file and retry with exact text.${hint}`);
622
640
  }
623
641
  const next = replaceAll ? cur.split(oldText).join(newText) : cur.slice(0, idx) + newText + cur.slice(idx + oldText.length);
624
642
  if (ctx.dryRun)
625
- return `dry-run: would edit ${p} (replace_all=${replaceAll})`;
643
+ return `dry-run: would edit ${redactedPath} (replace_all=${replaceAll})`;
626
644
  await backupFile(p, ctx);
627
645
  await atomicWrite(p, next);
628
646
  ctx.onMutation?.(p);
@@ -633,7 +651,7 @@ export async function edit_file(ctx, args) {
633
651
  after: Buffer.from(next, 'utf8')
634
652
  });
635
653
  const cwdWarning = checkCwdWarning('edit_file', p, ctx);
636
- return `edited ${p} (replace_all=${replaceAll})${replayNote}${cwdWarning}`;
654
+ return `edited ${redactedPath} (replace_all=${replaceAll})${replayNote}${cwdWarning}`;
637
655
  }
638
656
  function normalizePatchPath(p) {
639
657
  let s = String(p ?? '').trim();
@@ -766,6 +784,12 @@ export async function edit_range(ctx, args) {
766
784
  throw new Error('edit_range: missing/invalid end_line');
767
785
  if (replacement == null)
768
786
  throw new Error('edit_range: missing replacement (got ' + typeof rawReplacement + ')');
787
+ const hasLiteralEscapedNewlines = replacement.includes('\\n');
788
+ const hasRealNewlines = replacement.includes('\n') || replacement.includes('\r');
789
+ if (hasLiteralEscapedNewlines && !hasRealNewlines) {
790
+ throw new Error('edit_range: replacement appears double-escaped (contains literal "\\n" sequences). ' +
791
+ 'Resend replacement with REAL newline characters (multi-line string), not escaped backslash-n text.');
792
+ }
769
793
  enforceMutationWithinCwd('edit_range', p, ctx);
770
794
  // Path safety check (Phase 9)
771
795
  const pathVerdict = checkPathSafety(p);
@@ -877,7 +901,8 @@ export async function apply_patch(ctx, args) {
877
901
  if (chk.rc !== 0)
878
902
  throw new Error(`apply_patch: patch --dry-run failed:\n${chk.err || chk.out}`);
879
903
  }
880
- return `dry-run: patch would apply cleanly (${touched.paths.length} files): ${touched.paths.join(', ')}`;
904
+ const redactedPaths = touched.paths.map((rel) => redactPath(resolvePath(ctx, rel), path.resolve(ctx.cwd)));
905
+ return `dry-run: patch would apply cleanly (${touched.paths.length} files): ${redactedPaths.join(', ')}`;
881
906
  }
882
907
  // Snapshot + backup before applying
883
908
  const beforeMap = new Map();
@@ -923,7 +948,8 @@ export async function apply_patch(ctx, args) {
923
948
  replayNotes += replayNote;
924
949
  cwdWarnings += checkCwdWarning('apply_patch', abs, ctx);
925
950
  }
926
- return `applied patch (${touched.paths.length} files): ${touched.paths.join(', ')}${replayNotes}${cwdWarnings}`;
951
+ const redactedPaths = touched.paths.map((rel) => redactPath(resolvePath(ctx, rel), path.resolve(ctx.cwd)));
952
+ return `applied patch (${touched.paths.length} files): ${redactedPaths.join(', ')}${replayNotes}${cwdWarnings}`;
927
953
  }
928
954
  export async function list_dir(ctx, args) {
929
955
  const p = resolvePath(ctx, args?.path ?? '.');
@@ -931,6 +957,7 @@ export async function list_dir(ctx, args) {
931
957
  const maxEntries = Math.min(args?.max_entries ? Number(args.max_entries) : 200, 500);
932
958
  if (!p)
933
959
  throw new Error('list_dir: missing path');
960
+ const absCwd = path.resolve(ctx.cwd);
934
961
  const lines = [];
935
962
  let count = 0;
936
963
  async function walk(dir, depth) {
@@ -945,7 +972,7 @@ export async function list_dir(ctx, args) {
945
972
  const full = path.join(dir, ent.name);
946
973
  const st = await fs.lstat(full).catch(() => null);
947
974
  const kind = ent.isDirectory() ? 'dir' : ent.isSymbolicLink() ? 'link' : 'file';
948
- lines.push(`${kind}\t${st?.size ?? 0}\t${full}`);
975
+ lines.push(`${kind}\t${st?.size ?? 0}\t${redactPath(full, absCwd)}`);
949
976
  count++;
950
977
  if (recursive && ent.isDirectory() && depth < 3) {
951
978
  await walk(full, depth + 1);
@@ -956,7 +983,7 @@ export async function list_dir(ctx, args) {
956
983
  if (count >= maxEntries)
957
984
  lines.push(`[truncated after ${maxEntries} entries]`);
958
985
  if (!lines.length)
959
- return `[empty directory: ${p}]`;
986
+ return `[empty directory: ${redactPath(p, absCwd)}]`;
960
987
  return lines.join('\n');
961
988
  }
962
989
  export async function search_files(ctx, args) {
@@ -968,6 +995,7 @@ export async function search_files(ctx, args) {
968
995
  throw new Error('search_files: missing path');
969
996
  if (!pattern)
970
997
  throw new Error('search_files: missing pattern');
998
+ const absCwd = path.resolve(ctx.cwd);
971
999
  // Prefer rg if available (fast, bounded output)
972
1000
  if (await hasRg()) {
973
1001
  const cmd = ['rg', '-n', '--no-heading', '--color', 'never', pattern, root];
@@ -978,7 +1006,7 @@ export async function search_files(ctx, args) {
978
1006
  const parsed = JSON.parse(rawJson);
979
1007
  // rg exits 1 when no matches found (not an error), 2+ for real errors.
980
1008
  if (parsed.rc === 1 && !parsed.out?.trim()) {
981
- return `No matches for pattern "${pattern}" in ${root}. STOP — do NOT read files individually to search. Try a broader regex pattern, different keywords, or use exec: grep -rn "keyword" ${root}`;
1009
+ return `No matches for pattern \"${pattern}\" in ${root}. STOP — do NOT read files individually to search. Try a broader regex pattern, different keywords, or use exec: grep -rn \"keyword\" ${root}`;
982
1010
  }
983
1011
  if (parsed.rc >= 2) {
984
1012
  // Real rg error — fall through to regex fallback below
@@ -989,7 +1017,16 @@ export async function search_files(ctx, args) {
989
1017
  const lines = rgOutput.split(/\r?\n/).filter(Boolean).slice(0, maxResults);
990
1018
  if (lines.length >= maxResults)
991
1019
  lines.push(`[truncated after ${maxResults} results]`);
992
- return lines.join('\n');
1020
+ // Redact paths in rg output
1021
+ const redactedLines = lines.map(line => {
1022
+ const colonIdx = line.indexOf(':');
1023
+ if (colonIdx === -1)
1024
+ return line;
1025
+ const filePath = line.substring(0, colonIdx);
1026
+ const rest = line.substring(colonIdx + 1);
1027
+ return redactPath(filePath, absCwd) + ':' + rest;
1028
+ });
1029
+ return redactedLines.join('\n');
993
1030
  }
994
1031
  }
995
1032
  }
@@ -1003,7 +1040,7 @@ export async function search_files(ctx, args) {
1003
1040
  re = new RegExp(pattern);
1004
1041
  }
1005
1042
  catch (e) {
1006
- throw new ToolError('invalid_args', `search_files: invalid regex pattern: ${e?.message ?? String(e)}`, false, 'Escape regex metacharacters (\\, [, ], (, ), +, *, ?). If you intended literal text, use an escaped/literal pattern.');
1043
+ throw new ToolError('invalid_args', `search_files: invalid regex pattern: ${e?.message ?? String(e)}`, false, 'Escape regex metacharacters (\\\\, [, ], (, ), +, *, ?). If you intended literal text, use an escaped/literal pattern.');
1007
1044
  }
1008
1045
  const out = [];
1009
1046
  async function walk(dir, depth) {
@@ -1042,7 +1079,7 @@ export async function search_files(ctx, args) {
1042
1079
  const lines = buf.split(/\r?\n/);
1043
1080
  for (let i = 0; i < lines.length; i++) {
1044
1081
  if (re.test(lines[i])) {
1045
- out.push(`${full}:${i + 1}:${lines[i]}`);
1082
+ out.push(`${redactPath(full, absCwd)}:${i + 1}:${lines[i]}`);
1046
1083
  if (out.length >= maxResults)
1047
1084
  return;
1048
1085
  }
@@ -1052,10 +1089,9 @@ export async function search_files(ctx, args) {
1052
1089
  await walk(root, 0);
1053
1090
  if (out.length >= maxResults)
1054
1091
  out.push(`[truncated after ${maxResults} results]`);
1055
- const result = out.join('\n');
1056
- if (!result)
1057
- return `No matches for pattern "${pattern}" in ${root}. STOP — do NOT read files individually to search. Try a broader regex pattern, different keywords, or use exec: grep -rn "keyword" ${root}`;
1058
- return result;
1092
+ if (!out.length)
1093
+ return `No matches for pattern \"${pattern}\" in ${redactPath(root, absCwd)}.`;
1094
+ return out.join('\n');
1059
1095
  }
1060
1096
  function stripSimpleQuotedSegments(s) {
1061
1097
  // Best-effort quote stripping for lightweight shell pattern checks.
@@ -1390,7 +1426,7 @@ export async function exec(ctx, args) {
1390
1426
  }
1391
1427
  async function execWithPty(args) {
1392
1428
  const { pty, command, cwd, timeout, maxBytes, captureLimit, signal, execCwdWarning } = args;
1393
- const proc = pty.spawn(BASH_PATH, ['-lc', command], {
1429
+ const proc = pty.spawn(BASH_PATH, ['-c', command], {
1394
1430
  name: 'xterm-color',
1395
1431
  cwd,
1396
1432
  cols: 120,
@@ -1512,11 +1548,6 @@ export async function vault_search(ctx, args) {
1512
1548
  export async function sys_context(ctx, args) {
1513
1549
  return sysContextTool(ctx, args);
1514
1550
  }
1515
- function resolvePath(ctx, p) {
1516
- if (typeof p !== 'string' || !p.trim())
1517
- throw new Error('missing path');
1518
- return path.resolve(ctx.cwd, p);
1519
- }
1520
1551
  /**
1521
1552
  * Check if a target path is within a directory.
1522
1553
  * Handles the classic root directory edge case: when dir is `/`, every absolute path is valid.
@@ -1526,6 +1557,24 @@ function isWithinDir(target, dir) {
1526
1557
  return target.startsWith('/');
1527
1558
  return target === dir || target.startsWith(dir + path.sep);
1528
1559
  }
1560
+ function resolvePath(ctx, p) {
1561
+ if (typeof p !== 'string' || !p.trim())
1562
+ throw new Error('missing path');
1563
+ return path.resolve(ctx.cwd, p);
1564
+ }
1565
+ /**
1566
+ * Redact a path for safe output.
1567
+ * - Paths within cwd are shown as relative paths
1568
+ * - Paths outside cwd are redacted as [outside-cwd]/basename
1569
+ */
1570
+ function redactPath(filePath, absCwd) {
1571
+ const resolved = path.resolve(filePath);
1572
+ if (isWithinDir(resolved, absCwd)) {
1573
+ return path.relative(absCwd, resolved);
1574
+ }
1575
+ const basename = path.basename(resolved);
1576
+ return `[outside-cwd]/${basename}`;
1577
+ }
1529
1578
  /**
1530
1579
  * Check if a resolved path is outside the working directory.
1531
1580
  * Returns a model-visible warning string if so, empty string otherwise.
@@ -1586,7 +1635,7 @@ async function hasRg() {
1586
1635
  catch {
1587
1636
  // try PATH
1588
1637
  return await new Promise((resolve) => {
1589
- const c = spawn(BASH_PATH, ['-lc', 'command -v rg >/dev/null 2>&1'], { stdio: 'ignore' });
1638
+ const c = spawn(BASH_PATH, ['-c', 'command -v rg >/dev/null 2>&1'], { stdio: 'ignore' });
1590
1639
  c.on('error', () => resolve(false));
1591
1640
  c.on('close', (code) => resolve(code === 0));
1592
1641
  });