@hoilab/ada-cli 0.84.21 → 0.84.22

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 (344) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.es.md +163 -0
  3. package/README.md +99 -652
  4. package/dist/cli/args.d.ts +3 -0
  5. package/dist/cli/args.d.ts.map +1 -1
  6. package/dist/cli/args.js +11 -0
  7. package/dist/cli/args.js.map +1 -1
  8. package/dist/cli/file-processor.d.ts.map +1 -1
  9. package/dist/cli/file-processor.js +2 -1
  10. package/dist/cli/file-processor.js.map +1 -1
  11. package/dist/cli/home-screen.d.ts.map +1 -1
  12. package/dist/cli/home-screen.js +2 -2
  13. package/dist/cli/home-screen.js.map +1 -1
  14. package/dist/cli/startup-ui.d.ts.map +1 -1
  15. package/dist/cli/startup-ui.js +9 -3
  16. package/dist/cli/startup-ui.js.map +1 -1
  17. package/dist/config.d.ts.map +1 -1
  18. package/dist/config.js +2 -1
  19. package/dist/config.js.map +1 -1
  20. package/dist/core/agent-session.d.ts +57 -7
  21. package/dist/core/agent-session.d.ts.map +1 -1
  22. package/dist/core/agent-session.js +449 -73
  23. package/dist/core/agent-session.js.map +1 -1
  24. package/dist/core/auth-storage.d.ts.map +1 -1
  25. package/dist/core/auth-storage.js +4 -3
  26. package/dist/core/auth-storage.js.map +1 -1
  27. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  28. package/dist/core/compaction/branch-summarization.js +3 -0
  29. package/dist/core/compaction/branch-summarization.js.map +1 -1
  30. package/dist/core/compaction/compaction.d.ts +4 -3
  31. package/dist/core/compaction/compaction.d.ts.map +1 -1
  32. package/dist/core/compaction/compaction.js +41 -32
  33. package/dist/core/compaction/compaction.js.map +1 -1
  34. package/dist/core/defaults.d.ts +1 -0
  35. package/dist/core/defaults.d.ts.map +1 -1
  36. package/dist/core/defaults.js +9 -0
  37. package/dist/core/defaults.js.map +1 -1
  38. package/dist/core/engine-personality.d.ts +12 -0
  39. package/dist/core/engine-personality.d.ts.map +1 -0
  40. package/dist/core/engine-personality.js +53 -0
  41. package/dist/core/engine-personality.js.map +1 -0
  42. package/dist/core/extensions/index.d.ts +1 -1
  43. package/dist/core/extensions/index.d.ts.map +1 -1
  44. package/dist/core/extensions/index.js.map +1 -1
  45. package/dist/core/extensions/loader.d.ts.map +1 -1
  46. package/dist/core/extensions/loader.js +10 -5
  47. package/dist/core/extensions/loader.js.map +1 -1
  48. package/dist/core/extensions/types.d.ts +23 -4
  49. package/dist/core/extensions/types.d.ts.map +1 -1
  50. package/dist/core/extensions/types.js.map +1 -1
  51. package/dist/core/keybindings.d.ts.map +1 -1
  52. package/dist/core/keybindings.js +2 -1
  53. package/dist/core/keybindings.js.map +1 -1
  54. package/dist/core/memory-engine/audit-export.d.ts +54 -0
  55. package/dist/core/memory-engine/audit-export.d.ts.map +1 -0
  56. package/dist/core/memory-engine/audit-export.js +85 -0
  57. package/dist/core/memory-engine/audit-export.js.map +1 -0
  58. package/dist/core/memory-engine/audit.d.ts.map +1 -1
  59. package/dist/core/memory-engine/audit.js +7 -8
  60. package/dist/core/memory-engine/audit.js.map +1 -1
  61. package/dist/core/memory-engine/engine.d.ts +2 -3
  62. package/dist/core/memory-engine/engine.d.ts.map +1 -1
  63. package/dist/core/memory-engine/engine.js +148 -50
  64. package/dist/core/memory-engine/engine.js.map +1 -1
  65. package/dist/core/memory-engine/inverted-index.d.ts.map +1 -1
  66. package/dist/core/memory-engine/inverted-index.js +67 -10
  67. package/dist/core/memory-engine/inverted-index.js.map +1 -1
  68. package/dist/core/memory-engine/keychain.d.ts.map +1 -1
  69. package/dist/core/memory-engine/keychain.js +1 -6
  70. package/dist/core/memory-engine/keychain.js.map +1 -1
  71. package/dist/core/memory-engine/observation-store.d.ts +1 -0
  72. package/dist/core/memory-engine/observation-store.d.ts.map +1 -1
  73. package/dist/core/memory-engine/observation-store.js +37 -8
  74. package/dist/core/memory-engine/observation-store.js.map +1 -1
  75. package/dist/core/memory-engine/scanner.d.ts.map +1 -1
  76. package/dist/core/memory-engine/scanner.js +25 -5
  77. package/dist/core/memory-engine/scanner.js.map +1 -1
  78. package/dist/core/memory-engine/security.d.ts.map +1 -1
  79. package/dist/core/memory-engine/security.js +131 -23
  80. package/dist/core/memory-engine/security.js.map +1 -1
  81. package/dist/core/memory-engine/session-indexer.d.ts.map +1 -1
  82. package/dist/core/memory-engine/session-indexer.js +8 -2
  83. package/dist/core/memory-engine/session-indexer.js.map +1 -1
  84. package/dist/core/memory-engine/tools.d.ts +2 -2
  85. package/dist/core/memory-engine/tools.d.ts.map +1 -1
  86. package/dist/core/memory-engine/tools.js +14 -7
  87. package/dist/core/memory-engine/tools.js.map +1 -1
  88. package/dist/core/memory-engine/vault.d.ts.map +1 -1
  89. package/dist/core/memory-engine/vault.js +2 -2
  90. package/dist/core/memory-engine/vault.js.map +1 -1
  91. package/dist/core/model-config.d.ts.map +1 -1
  92. package/dist/core/model-config.js +2 -1
  93. package/dist/core/model-config.js.map +1 -1
  94. package/dist/core/model-resolver.d.ts +1 -0
  95. package/dist/core/model-resolver.d.ts.map +1 -1
  96. package/dist/core/model-resolver.js +12 -6
  97. package/dist/core/model-resolver.js.map +1 -1
  98. package/dist/core/models-store.d.ts.map +1 -1
  99. package/dist/core/models-store.js +2 -1
  100. package/dist/core/models-store.js.map +1 -1
  101. package/dist/core/package-manager.d.ts.map +1 -1
  102. package/dist/core/package-manager.js +11 -6
  103. package/dist/core/package-manager.js.map +1 -1
  104. package/dist/core/pi-manifest.d.ts.map +1 -1
  105. package/dist/core/pi-manifest.js +2 -1
  106. package/dist/core/pi-manifest.js.map +1 -1
  107. package/dist/core/prompt-optimizer.d.ts +53 -0
  108. package/dist/core/prompt-optimizer.d.ts.map +1 -0
  109. package/dist/core/prompt-optimizer.js +138 -0
  110. package/dist/core/prompt-optimizer.js.map +1 -0
  111. package/dist/core/provider-attribution.d.ts.map +1 -1
  112. package/dist/core/provider-attribution.js +1 -1
  113. package/dist/core/provider-attribution.js.map +1 -1
  114. package/dist/core/remote-catalog-provider.d.ts.map +1 -1
  115. package/dist/core/remote-catalog-provider.js +2 -1
  116. package/dist/core/remote-catalog-provider.js.map +1 -1
  117. package/dist/core/resource-loader.d.ts +50 -0
  118. package/dist/core/resource-loader.d.ts.map +1 -1
  119. package/dist/core/resource-loader.js +233 -7
  120. package/dist/core/resource-loader.js.map +1 -1
  121. package/dist/core/sdk.d.ts +8 -0
  122. package/dist/core/sdk.d.ts.map +1 -1
  123. package/dist/core/sdk.js +11 -1
  124. package/dist/core/sdk.js.map +1 -1
  125. package/dist/core/session-manager.d.ts.map +1 -1
  126. package/dist/core/session-manager.js +2 -1
  127. package/dist/core/session-manager.js.map +1 -1
  128. package/dist/core/settings-diagnostics.d.ts +9 -0
  129. package/dist/core/settings-diagnostics.d.ts.map +1 -0
  130. package/dist/core/settings-diagnostics.js +21 -0
  131. package/dist/core/settings-diagnostics.js.map +1 -0
  132. package/dist/core/settings-manager.d.ts +52 -0
  133. package/dist/core/settings-manager.d.ts.map +1 -1
  134. package/dist/core/settings-manager.js +204 -10
  135. package/dist/core/settings-manager.js.map +1 -1
  136. package/dist/core/skills.d.ts.map +1 -1
  137. package/dist/core/skills.js +51 -33
  138. package/dist/core/skills.js.map +1 -1
  139. package/dist/core/slash-commands.d.ts.map +1 -1
  140. package/dist/core/slash-commands.js +2 -1
  141. package/dist/core/slash-commands.js.map +1 -1
  142. package/dist/core/tools/edit-diff.d.ts +0 -5
  143. package/dist/core/tools/edit-diff.d.ts.map +1 -1
  144. package/dist/core/tools/edit-diff.js +2 -5
  145. package/dist/core/tools/edit-diff.js.map +1 -1
  146. package/dist/core/tools/edit.d.ts.map +1 -1
  147. package/dist/core/tools/edit.js +20 -4
  148. package/dist/core/tools/edit.js.map +1 -1
  149. package/dist/core/tools/index.d.ts.map +1 -1
  150. package/dist/core/tools/index.js +2 -2
  151. package/dist/core/tools/index.js.map +1 -1
  152. package/dist/core/tools/project-memory-tool.d.ts.map +1 -1
  153. package/dist/core/tools/project-memory-tool.js +4 -1
  154. package/dist/core/tools/project-memory-tool.js.map +1 -1
  155. package/dist/core/trust-manager.d.ts.map +1 -1
  156. package/dist/core/trust-manager.js +2 -1
  157. package/dist/core/trust-manager.js.map +1 -1
  158. package/dist/core/workflows/agent-runner.d.ts +86 -0
  159. package/dist/core/workflows/agent-runner.d.ts.map +1 -0
  160. package/dist/core/workflows/agent-runner.js +225 -0
  161. package/dist/core/workflows/agent-runner.js.map +1 -0
  162. package/dist/core/workflows/builtins.d.ts +41 -0
  163. package/dist/core/workflows/builtins.d.ts.map +1 -0
  164. package/dist/core/workflows/builtins.js +282 -0
  165. package/dist/core/workflows/builtins.js.map +1 -0
  166. package/dist/core/workflows/goal-engine/engine.d.ts +134 -0
  167. package/dist/core/workflows/goal-engine/engine.d.ts.map +1 -0
  168. package/dist/core/workflows/goal-engine/engine.js +462 -0
  169. package/dist/core/workflows/goal-engine/engine.js.map +1 -0
  170. package/dist/core/workflows/goal-engine/errors.d.ts +7 -0
  171. package/dist/core/workflows/goal-engine/errors.d.ts.map +1 -0
  172. package/dist/core/workflows/goal-engine/errors.js +9 -0
  173. package/dist/core/workflows/goal-engine/errors.js.map +1 -0
  174. package/dist/core/workflows/goal-engine/index.d.ts +13 -0
  175. package/dist/core/workflows/goal-engine/index.d.ts.map +1 -0
  176. package/dist/core/workflows/goal-engine/index.js +8 -0
  177. package/dist/core/workflows/goal-engine/index.js.map +1 -0
  178. package/dist/core/workflows/goal-engine/persistence.d.ts +31 -0
  179. package/dist/core/workflows/goal-engine/persistence.d.ts.map +1 -0
  180. package/dist/core/workflows/goal-engine/persistence.js +145 -0
  181. package/dist/core/workflows/goal-engine/persistence.js.map +1 -0
  182. package/dist/core/workflows/goal-engine/prompts.d.ts +37 -0
  183. package/dist/core/workflows/goal-engine/prompts.d.ts.map +1 -0
  184. package/dist/core/workflows/goal-engine/prompts.js +131 -0
  185. package/dist/core/workflows/goal-engine/prompts.js.map +1 -0
  186. package/dist/core/workflows/goal-engine/state.d.ts +41 -0
  187. package/dist/core/workflows/goal-engine/state.d.ts.map +1 -0
  188. package/dist/core/workflows/goal-engine/state.js +397 -0
  189. package/dist/core/workflows/goal-engine/state.js.map +1 -0
  190. package/dist/core/workflows/goal-engine/tools.d.ts +31 -0
  191. package/dist/core/workflows/goal-engine/tools.d.ts.map +1 -0
  192. package/dist/core/workflows/goal-engine/tools.js +211 -0
  193. package/dist/core/workflows/goal-engine/tools.js.map +1 -0
  194. package/dist/core/workflows/goal-engine/types.d.ts +286 -0
  195. package/dist/core/workflows/goal-engine/types.d.ts.map +1 -0
  196. package/dist/core/workflows/goal-engine/types.js +17 -0
  197. package/dist/core/workflows/goal-engine/types.js.map +1 -0
  198. package/dist/core/workflows/goal-engine/worktree-fingerprint.d.ts +23 -0
  199. package/dist/core/workflows/goal-engine/worktree-fingerprint.d.ts.map +1 -0
  200. package/dist/core/workflows/goal-engine/worktree-fingerprint.js +72 -0
  201. package/dist/core/workflows/goal-engine/worktree-fingerprint.js.map +1 -0
  202. package/dist/core/workflows/graph-sync.d.ts +67 -0
  203. package/dist/core/workflows/graph-sync.d.ts.map +1 -0
  204. package/dist/core/workflows/graph-sync.js +188 -0
  205. package/dist/core/workflows/graph-sync.js.map +1 -0
  206. package/dist/core/workflows/graph.d.ts +143 -0
  207. package/dist/core/workflows/graph.d.ts.map +1 -0
  208. package/dist/core/workflows/graph.js +319 -0
  209. package/dist/core/workflows/graph.js.map +1 -0
  210. package/dist/core/workflows/index.d.ts +18 -0
  211. package/dist/core/workflows/index.d.ts.map +1 -0
  212. package/dist/core/workflows/index.js +14 -0
  213. package/dist/core/workflows/index.js.map +1 -0
  214. package/dist/core/workflows/journal.d.ts +68 -0
  215. package/dist/core/workflows/journal.d.ts.map +1 -0
  216. package/dist/core/workflows/journal.js +83 -0
  217. package/dist/core/workflows/journal.js.map +1 -0
  218. package/dist/core/workflows/manager.d.ts +112 -0
  219. package/dist/core/workflows/manager.d.ts.map +1 -0
  220. package/dist/core/workflows/manager.js +327 -0
  221. package/dist/core/workflows/manager.js.map +1 -0
  222. package/dist/core/workflows/resolve-script.d.ts +35 -0
  223. package/dist/core/workflows/resolve-script.d.ts.map +1 -0
  224. package/dist/core/workflows/resolve-script.js +66 -0
  225. package/dist/core/workflows/resolve-script.js.map +1 -0
  226. package/dist/core/workflows/runtime.d.ts +49 -0
  227. package/dist/core/workflows/runtime.d.ts.map +1 -0
  228. package/dist/core/workflows/runtime.js +301 -0
  229. package/dist/core/workflows/runtime.js.map +1 -0
  230. package/dist/core/workflows/shared-store.d.ts +31 -0
  231. package/dist/core/workflows/shared-store.d.ts.map +1 -0
  232. package/dist/core/workflows/shared-store.js +80 -0
  233. package/dist/core/workflows/shared-store.js.map +1 -0
  234. package/dist/core/workflows/subagent-host.d.ts +50 -0
  235. package/dist/core/workflows/subagent-host.d.ts.map +1 -0
  236. package/dist/core/workflows/subagent-host.js +225 -0
  237. package/dist/core/workflows/subagent-host.js.map +1 -0
  238. package/dist/core/workflows/tool-workflow.d.ts +22 -0
  239. package/dist/core/workflows/tool-workflow.d.ts.map +1 -0
  240. package/dist/core/workflows/tool-workflow.js +120 -0
  241. package/dist/core/workflows/tool-workflow.js.map +1 -0
  242. package/dist/core/workflows/types.d.ts +142 -0
  243. package/dist/core/workflows/types.d.ts.map +1 -0
  244. package/dist/core/workflows/types.js +26 -0
  245. package/dist/core/workflows/types.js.map +1 -0
  246. package/dist/core/workflows/worktree.d.ts +42 -0
  247. package/dist/core/workflows/worktree.d.ts.map +1 -0
  248. package/dist/core/workflows/worktree.js +107 -0
  249. package/dist/core/workflows/worktree.js.map +1 -0
  250. package/dist/extensions/llama/index.d.ts.map +1 -1
  251. package/dist/extensions/llama/index.js +2 -0
  252. package/dist/extensions/llama/index.js.map +1 -1
  253. package/dist/extensions/llama/provider.d.ts.map +1 -1
  254. package/dist/extensions/llama/provider.js +6 -2
  255. package/dist/extensions/llama/provider.js.map +1 -1
  256. package/dist/index.d.ts +16 -12
  257. package/dist/index.d.ts.map +1 -1
  258. package/dist/index.js +14 -11
  259. package/dist/index.js.map +1 -1
  260. package/dist/main.d.ts +4 -0
  261. package/dist/main.d.ts.map +1 -1
  262. package/dist/main.js +20 -15
  263. package/dist/main.js.map +1 -1
  264. package/dist/migrations.d.ts.map +1 -1
  265. package/dist/migrations.js +4 -3
  266. package/dist/migrations.js.map +1 -1
  267. package/dist/modes/interactive/components/home-screen.d.ts.map +1 -1
  268. package/dist/modes/interactive/components/home-screen.js +2 -2
  269. package/dist/modes/interactive/components/home-screen.js.map +1 -1
  270. package/dist/modes/interactive/components/model-selector.d.ts +2 -3
  271. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  272. package/dist/modes/interactive/components/model-selector.js +16 -6
  273. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  274. package/dist/modes/interactive/components/prompt-optimization.d.ts +16 -0
  275. package/dist/modes/interactive/components/prompt-optimization.d.ts.map +1 -0
  276. package/dist/modes/interactive/components/prompt-optimization.js +46 -0
  277. package/dist/modes/interactive/components/prompt-optimization.js.map +1 -0
  278. package/dist/modes/interactive/components/settings-selector.d.ts +19 -1
  279. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  280. package/dist/modes/interactive/components/settings-selector.js +247 -46
  281. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  282. package/dist/modes/interactive/components/settings-submenu.d.ts +72 -0
  283. package/dist/modes/interactive/components/settings-submenu.d.ts.map +1 -0
  284. package/dist/modes/interactive/components/settings-submenu.js +165 -0
  285. package/dist/modes/interactive/components/settings-submenu.js.map +1 -0
  286. package/dist/modes/interactive/components/thinking-selector.d.ts +8 -3
  287. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  288. package/dist/modes/interactive/components/thinking-selector.js +29 -3
  289. package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  290. package/dist/modes/interactive/external-editor.d.ts.map +1 -1
  291. package/dist/modes/interactive/external-editor.js +2 -1
  292. package/dist/modes/interactive/external-editor.js.map +1 -1
  293. package/dist/modes/interactive/interactive-mode.d.ts +24 -0
  294. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  295. package/dist/modes/interactive/interactive-mode.js +677 -34
  296. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  297. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  298. package/dist/modes/interactive/theme/theme.js +4 -3
  299. package/dist/modes/interactive/theme/theme.js.map +1 -1
  300. package/dist/modes/json-event.d.ts +16 -13
  301. package/dist/modes/json-event.d.ts.map +1 -1
  302. package/dist/modes/json-event.js +20 -6
  303. package/dist/modes/json-event.js.map +1 -1
  304. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  305. package/dist/modes/rpc/rpc-mode.js +173 -0
  306. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  307. package/dist/modes/rpc/rpc-types.d.ts +29 -0
  308. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  309. package/dist/modes/rpc/rpc-types.js.map +1 -1
  310. package/dist/package-manager-cli.d.ts.map +1 -1
  311. package/dist/package-manager-cli.js +1 -1
  312. package/dist/package-manager-cli.js.map +1 -1
  313. package/dist/skills/ada-engine/SKILL.md +153 -0
  314. package/dist/utils/frontmatter.d.ts.map +1 -1
  315. package/dist/utils/frontmatter.js +2 -1
  316. package/dist/utils/frontmatter.js.map +1 -1
  317. package/dist/utils/management-http.d.ts +5 -3
  318. package/dist/utils/management-http.d.ts.map +1 -1
  319. package/dist/utils/management-http.js +14 -10
  320. package/dist/utils/management-http.js.map +1 -1
  321. package/dist/utils/text.d.ts +8 -0
  322. package/dist/utils/text.d.ts.map +1 -0
  323. package/dist/utils/text.js +9 -0
  324. package/dist/utils/text.js.map +1 -0
  325. package/docs/compaction.md +15 -0
  326. package/docs/custom-provider.md +5 -2
  327. package/docs/extensions.md +11 -2
  328. package/docs/json.md +7 -2
  329. package/docs/llama-cpp.md +2 -0
  330. package/docs/models.md +8 -2
  331. package/docs/rpc.md +9 -3
  332. package/docs/settings.md +2 -2
  333. package/docs/skills.md +4 -3
  334. package/examples/extensions/border-status-editor.ts +1 -1
  335. package/examples/extensions/git-checkpoint.ts +2 -2
  336. package/examples/extensions/notify.ts +3 -1
  337. package/examples/extensions/subagent/README.md +1 -1
  338. package/examples/extensions/subagent/index.ts +6 -1
  339. package/examples/extensions/titlebar-spinner.ts +1 -1
  340. package/examples/rpc-extension-ui.ts +1 -1
  341. package/examples/sdk/06-extensions.ts +1 -1
  342. package/examples/sdk/README.md +1 -1
  343. package/npm-shrinkwrap.json +2 -12
  344. package/package.json +3 -3
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/tools/index.ts"],"names":[],"mappings":"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","sourcesContent":["export {\n\ttype BashOperations,\n\ttype BashSpawnContext,\n\ttype BashSpawnHook,\n\ttype BashToolDetails,\n\ttype BashToolInput,\n\ttype BashToolOptions,\n\tcreateBashTool,\n\tcreateBashToolDefinition,\n\tcreateLocalBashOperations,\n} from \"./bash.ts\";\nexport {\n\tcreateEditTool,\n\tcreateEditToolDefinition,\n\ttype EditOperations,\n\ttype EditToolDetails,\n\ttype EditToolInput,\n\ttype EditToolOptions,\n} from \"./edit.ts\";\nexport { withFileMutationQueue } from \"./file-mutation-queue.ts\";\nexport {\n\tcreateFindTool,\n\tcreateFindToolDefinition,\n\ttype FindOperations,\n\ttype FindToolDetails,\n\ttype FindToolInput,\n\ttype FindToolOptions,\n} from \"./find.ts\";\nexport {\n\tcreateGrepTool,\n\tcreateGrepToolDefinition,\n\ttype GrepOperations,\n\ttype GrepToolDetails,\n\ttype GrepToolInput,\n\ttype GrepToolOptions,\n} from \"./grep.ts\";\nexport {\n\tcreateLsTool,\n\tcreateLsToolDefinition,\n\ttype LsOperations,\n\ttype LsToolDetails,\n\ttype LsToolInput,\n\ttype LsToolOptions,\n} from \"./ls.ts\";\nexport {\n\tcreateReadTool,\n\tcreateReadToolDefinition,\n\ttype ReadOperations,\n\ttype ReadToolDetails,\n\ttype ReadToolInput,\n\ttype ReadToolOptions,\n} from \"./read.ts\";\nexport {\n\tDEFAULT_MAX_BYTES,\n\tDEFAULT_MAX_LINES,\n\tformatSize,\n\ttype TruncationOptions,\n\ttype TruncationResult,\n\ttruncateHead,\n\ttruncateLine,\n\ttruncateTail,\n} from \"./truncate.ts\";\nexport {\n\tcreateWriteTool,\n\tcreateWriteToolDefinition,\n\ttype WriteOperations,\n\ttype WriteToolInput,\n\ttype WriteToolOptions,\n} from \"./write.ts\";\n\nimport type { AgentTool } from \"@earendil-works/pi-agent-core\";\nimport { getAgentDir } from \"../../config.ts\";\nimport type { ToolDefinition } from \"../extensions/types.ts\";\nimport { createUpdateProjectMemoryTool } from \"./project-memory-tool.ts\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.ts\";\nimport { type BashToolOptions, createBashTool, createBashToolDefinition } from \"./bash.ts\";\nimport { createEditTool, createEditToolDefinition, type EditToolOptions } from \"./edit.ts\";\nimport { createFindTool, createFindToolDefinition, type FindToolOptions } from \"./find.ts\";\nimport { createGrepTool, createGrepToolDefinition, type GrepToolOptions } from \"./grep.ts\";\nimport { createLsTool, createLsToolDefinition, type LsToolOptions } from \"./ls.ts\";\nimport { createReadTool, createReadToolDefinition, type ReadToolOptions } from \"./read.ts\";\nimport { createWriteTool, createWriteToolDefinition, type WriteToolOptions } from \"./write.ts\";\n\nexport type Tool = AgentTool<any>;\nexport type ToolDef = ToolDefinition<any, any>;\nexport type ToolName =\n\t| \"read\"\n\t| \"bash\"\n\t| \"edit\"\n\t| \"write\"\n\t| \"grep\"\n\t| \"find\"\n\t| \"ls\"\n\t| \"update_project_memory\";\nexport const allToolNames: Set<ToolName> = new Set([\n\t\"read\",\n\t\"bash\",\n\t\"edit\",\n\t\"write\",\n\t\"grep\",\n\t\"find\",\n\t\"ls\",\n\t\"update_project_memory\",\n]);\n\nexport interface ToolsOptions {\n\tread?: ReadToolOptions;\n\tbash?: BashToolOptions;\n\twrite?: WriteToolOptions;\n\tedit?: EditToolOptions;\n\tgrep?: GrepToolOptions;\n\tfind?: FindToolOptions;\n\tls?: LsToolOptions;\n}\n\nexport function createToolDefinition(toolName: ToolName, cwd: string, options?: ToolsOptions): ToolDef {\n\tswitch (toolName) {\n\t\tcase \"read\":\n\t\t\treturn createReadToolDefinition(cwd, options?.read);\n\t\tcase \"bash\":\n\t\t\treturn createBashToolDefinition(cwd, options?.bash);\n\t\tcase \"edit\":\n\t\t\treturn createEditToolDefinition(cwd, options?.edit);\n\t\tcase \"write\":\n\t\t\treturn createWriteToolDefinition(cwd, options?.write);\n\t\tcase \"grep\":\n\t\t\treturn createGrepToolDefinition(cwd, options?.grep);\n\t\tcase \"find\":\n\t\t\treturn createFindToolDefinition(cwd, options?.find);\n\t\tcase \"ls\":\n\t\t\treturn createLsToolDefinition(cwd, options?.ls);\n\t\tdefault:\n\t\t\tthrow new Error(`Unknown tool name: ${toolName}`);\n\t}\n}\n\nexport function createTool(toolName: ToolName, cwd: string, options?: ToolsOptions): Tool {\n\tswitch (toolName) {\n\t\tcase \"read\":\n\t\t\treturn createReadTool(cwd, options?.read);\n\t\tcase \"bash\":\n\t\t\treturn createBashTool(cwd, options?.bash);\n\t\tcase \"edit\":\n\t\t\treturn createEditTool(cwd, options?.edit);\n\t\tcase \"write\":\n\t\t\treturn createWriteTool(cwd, options?.write);\n\t\tcase \"grep\":\n\t\t\treturn createGrepTool(cwd, options?.grep);\n\t\tcase \"find\":\n\t\t\treturn createFindTool(cwd, options?.find);\n\t\tcase \"ls\":\n\t\t\treturn createLsTool(cwd, options?.ls);\n\t\tdefault:\n\t\t\tthrow new Error(`Unknown tool name: ${toolName}`);\n\t}\n}\n\nexport function createCodingToolDefinitions(cwd: string, options?: ToolsOptions): ToolDef[] {\n\treturn [\n\t\tcreateReadToolDefinition(cwd, options?.read),\n\t\tcreateBashToolDefinition(cwd, options?.bash),\n\t\tcreateEditToolDefinition(cwd, options?.edit),\n\t\tcreateWriteToolDefinition(cwd, options?.write),\n\t];\n}\n\nexport function createReadOnlyToolDefinitions(cwd: string, options?: ToolsOptions): ToolDef[] {\n\treturn [\n\t\tcreateReadToolDefinition(cwd, options?.read),\n\t\tcreateGrepToolDefinition(cwd, options?.grep),\n\t\tcreateFindToolDefinition(cwd, options?.find),\n\t\tcreateLsToolDefinition(cwd, options?.ls),\n\t];\n}export function createAllToolDefinitions(\n\tcwd: string,\n\toptions?: ToolsOptions,\n\tagentDir: string = getAgentDir(),\n): Record<ToolName, ToolDef> {\n\treturn {\n\t\tread: createReadToolDefinition(cwd, options?.read),\n\t\tbash: createBashToolDefinition(cwd, options?.bash),\n\t\tedit: createEditToolDefinition(cwd, options?.edit),\n\t\twrite: createWriteToolDefinition(cwd, options?.write),\n\t\tgrep: createGrepToolDefinition(cwd, options?.grep),\n\t\tfind: createFindToolDefinition(cwd, options?.find),\n\t\tls: createLsToolDefinition(cwd, options?.ls),\n\t\tupdate_project_memory: createUpdateProjectMemoryTool(cwd, agentDir),\n\t};\n}\n\nexport function createCodingTools(cwd: string, options?: ToolsOptions): Tool[] {\n\treturn [\n\t\tcreateReadTool(cwd, options?.read),\n\t\tcreateBashTool(cwd, options?.bash),\n\t\tcreateEditTool(cwd, options?.edit),\n\t\tcreateWriteTool(cwd, options?.write),\n\t\twrapToolDefinition(createUpdateProjectMemoryTool(cwd, getAgentDir())),\n\t];\n}\n\nexport function createReadOnlyTools(cwd: string, options?: ToolsOptions): Tool[] {\n\treturn [\n\t\tcreateReadTool(cwd, options?.read),\n\t\tcreateGrepTool(cwd, options?.grep),\n\t\tcreateFindTool(cwd, options?.find),\n\t\tcreateLsTool(cwd, options?.ls),\n\t];\n}\n\nexport function createAllTools(cwd: string, options?: ToolsOptions): Record<ToolName, Tool> {\n\treturn {\n\t\tread: createReadTool(cwd, options?.read),\n\t\tbash: createBashTool(cwd, options?.bash),\n\t\tedit: createEditTool(cwd, options?.edit),\n\t\twrite: createWriteTool(cwd, options?.write),\n\t\tgrep: createGrepTool(cwd, options?.grep),\n\t\tfind: createFindTool(cwd, options?.find),\n\t\tls: createLsTool(cwd, options?.ls),\n\t\tupdate_project_memory: wrapToolDefinition(createUpdateProjectMemoryTool(cwd, getAgentDir())),\n\t};\n}"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/tools/index.ts"],"names":[],"mappings":"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","sourcesContent":["export {\n\ttype BashOperations,\n\ttype BashSpawnContext,\n\ttype BashSpawnHook,\n\ttype BashToolDetails,\n\ttype BashToolInput,\n\ttype BashToolOptions,\n\tcreateBashTool,\n\tcreateBashToolDefinition,\n\tcreateLocalBashOperations,\n} from \"./bash.ts\";\nexport {\n\tcreateEditTool,\n\tcreateEditToolDefinition,\n\ttype EditOperations,\n\ttype EditToolDetails,\n\ttype EditToolInput,\n\ttype EditToolOptions,\n} from \"./edit.ts\";\nexport { withFileMutationQueue } from \"./file-mutation-queue.ts\";\nexport {\n\tcreateFindTool,\n\tcreateFindToolDefinition,\n\ttype FindOperations,\n\ttype FindToolDetails,\n\ttype FindToolInput,\n\ttype FindToolOptions,\n} from \"./find.ts\";\nexport {\n\tcreateGrepTool,\n\tcreateGrepToolDefinition,\n\ttype GrepOperations,\n\ttype GrepToolDetails,\n\ttype GrepToolInput,\n\ttype GrepToolOptions,\n} from \"./grep.ts\";\nexport {\n\tcreateLsTool,\n\tcreateLsToolDefinition,\n\ttype LsOperations,\n\ttype LsToolDetails,\n\ttype LsToolInput,\n\ttype LsToolOptions,\n} from \"./ls.ts\";\nexport {\n\tcreateReadTool,\n\tcreateReadToolDefinition,\n\ttype ReadOperations,\n\ttype ReadToolDetails,\n\ttype ReadToolInput,\n\ttype ReadToolOptions,\n} from \"./read.ts\";\nexport {\n\tDEFAULT_MAX_BYTES,\n\tDEFAULT_MAX_LINES,\n\tformatSize,\n\ttype TruncationOptions,\n\ttype TruncationResult,\n\ttruncateHead,\n\ttruncateLine,\n\ttruncateTail,\n} from \"./truncate.ts\";\nexport {\n\tcreateWriteTool,\n\tcreateWriteToolDefinition,\n\ttype WriteOperations,\n\ttype WriteToolInput,\n\ttype WriteToolOptions,\n} from \"./write.ts\";\n\nimport type { AgentTool } from \"@earendil-works/pi-agent-core\";\nimport { getAgentDir } from \"../../config.ts\";\nimport type { ToolDefinition } from \"../extensions/types.ts\";\nimport { type BashToolOptions, createBashTool, createBashToolDefinition } from \"./bash.ts\";\nimport { createEditTool, createEditToolDefinition, type EditToolOptions } from \"./edit.ts\";\nimport { createFindTool, createFindToolDefinition, type FindToolOptions } from \"./find.ts\";\nimport { createGrepTool, createGrepToolDefinition, type GrepToolOptions } from \"./grep.ts\";\nimport { createLsTool, createLsToolDefinition, type LsToolOptions } from \"./ls.ts\";\nimport { createUpdateProjectMemoryTool } from \"./project-memory-tool.ts\";\nimport { createReadTool, createReadToolDefinition, type ReadToolOptions } from \"./read.ts\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.ts\";\nimport { createWriteTool, createWriteToolDefinition, type WriteToolOptions } from \"./write.ts\";\n\nexport type Tool = AgentTool<any>;\nexport type ToolDef = ToolDefinition<any, any>;\nexport type ToolName = \"read\" | \"bash\" | \"edit\" | \"write\" | \"grep\" | \"find\" | \"ls\" | \"update_project_memory\";\nexport const allToolNames: Set<ToolName> = new Set([\n\t\"read\",\n\t\"bash\",\n\t\"edit\",\n\t\"write\",\n\t\"grep\",\n\t\"find\",\n\t\"ls\",\n\t\"update_project_memory\",\n]);\n\nexport interface ToolsOptions {\n\tread?: ReadToolOptions;\n\tbash?: BashToolOptions;\n\twrite?: WriteToolOptions;\n\tedit?: EditToolOptions;\n\tgrep?: GrepToolOptions;\n\tfind?: FindToolOptions;\n\tls?: LsToolOptions;\n}\n\nexport function createToolDefinition(toolName: ToolName, cwd: string, options?: ToolsOptions): ToolDef {\n\tswitch (toolName) {\n\t\tcase \"read\":\n\t\t\treturn createReadToolDefinition(cwd, options?.read);\n\t\tcase \"bash\":\n\t\t\treturn createBashToolDefinition(cwd, options?.bash);\n\t\tcase \"edit\":\n\t\t\treturn createEditToolDefinition(cwd, options?.edit);\n\t\tcase \"write\":\n\t\t\treturn createWriteToolDefinition(cwd, options?.write);\n\t\tcase \"grep\":\n\t\t\treturn createGrepToolDefinition(cwd, options?.grep);\n\t\tcase \"find\":\n\t\t\treturn createFindToolDefinition(cwd, options?.find);\n\t\tcase \"ls\":\n\t\t\treturn createLsToolDefinition(cwd, options?.ls);\n\t\tdefault:\n\t\t\tthrow new Error(`Unknown tool name: ${toolName}`);\n\t}\n}\n\nexport function createTool(toolName: ToolName, cwd: string, options?: ToolsOptions): Tool {\n\tswitch (toolName) {\n\t\tcase \"read\":\n\t\t\treturn createReadTool(cwd, options?.read);\n\t\tcase \"bash\":\n\t\t\treturn createBashTool(cwd, options?.bash);\n\t\tcase \"edit\":\n\t\t\treturn createEditTool(cwd, options?.edit);\n\t\tcase \"write\":\n\t\t\treturn createWriteTool(cwd, options?.write);\n\t\tcase \"grep\":\n\t\t\treturn createGrepTool(cwd, options?.grep);\n\t\tcase \"find\":\n\t\t\treturn createFindTool(cwd, options?.find);\n\t\tcase \"ls\":\n\t\t\treturn createLsTool(cwd, options?.ls);\n\t\tdefault:\n\t\t\tthrow new Error(`Unknown tool name: ${toolName}`);\n\t}\n}\n\nexport function createCodingToolDefinitions(cwd: string, options?: ToolsOptions): ToolDef[] {\n\treturn [\n\t\tcreateReadToolDefinition(cwd, options?.read),\n\t\tcreateBashToolDefinition(cwd, options?.bash),\n\t\tcreateEditToolDefinition(cwd, options?.edit),\n\t\tcreateWriteToolDefinition(cwd, options?.write),\n\t];\n}\n\nexport function createReadOnlyToolDefinitions(cwd: string, options?: ToolsOptions): ToolDef[] {\n\treturn [\n\t\tcreateReadToolDefinition(cwd, options?.read),\n\t\tcreateGrepToolDefinition(cwd, options?.grep),\n\t\tcreateFindToolDefinition(cwd, options?.find),\n\t\tcreateLsToolDefinition(cwd, options?.ls),\n\t];\n}\nexport function createAllToolDefinitions(\n\tcwd: string,\n\toptions?: ToolsOptions,\n\tagentDir: string = getAgentDir(),\n): Record<ToolName, ToolDef> {\n\treturn {\n\t\tread: createReadToolDefinition(cwd, options?.read),\n\t\tbash: createBashToolDefinition(cwd, options?.bash),\n\t\tedit: createEditToolDefinition(cwd, options?.edit),\n\t\twrite: createWriteToolDefinition(cwd, options?.write),\n\t\tgrep: createGrepToolDefinition(cwd, options?.grep),\n\t\tfind: createFindToolDefinition(cwd, options?.find),\n\t\tls: createLsToolDefinition(cwd, options?.ls),\n\t\tupdate_project_memory: createUpdateProjectMemoryTool(cwd, agentDir),\n\t};\n}\n\nexport function createCodingTools(cwd: string, options?: ToolsOptions): Tool[] {\n\treturn [\n\t\tcreateReadTool(cwd, options?.read),\n\t\tcreateBashTool(cwd, options?.bash),\n\t\tcreateEditTool(cwd, options?.edit),\n\t\tcreateWriteTool(cwd, options?.write),\n\t\twrapToolDefinition(createUpdateProjectMemoryTool(cwd, getAgentDir())),\n\t];\n}\n\nexport function createReadOnlyTools(cwd: string, options?: ToolsOptions): Tool[] {\n\treturn [\n\t\tcreateReadTool(cwd, options?.read),\n\t\tcreateGrepTool(cwd, options?.grep),\n\t\tcreateFindTool(cwd, options?.find),\n\t\tcreateLsTool(cwd, options?.ls),\n\t];\n}\n\nexport function createAllTools(cwd: string, options?: ToolsOptions): Record<ToolName, Tool> {\n\treturn {\n\t\tread: createReadTool(cwd, options?.read),\n\t\tbash: createBashTool(cwd, options?.bash),\n\t\tedit: createEditTool(cwd, options?.edit),\n\t\twrite: createWriteTool(cwd, options?.write),\n\t\tgrep: createGrepTool(cwd, options?.grep),\n\t\tfind: createFindTool(cwd, options?.find),\n\t\tls: createLsTool(cwd, options?.ls),\n\t\tupdate_project_memory: wrapToolDefinition(createUpdateProjectMemoryTool(cwd, getAgentDir())),\n\t};\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"project-memory-tool.d.ts","sourceRoot":"","sources":["../../../src/core/tools/project-memory-tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EAIX,cAAc,EACd,MAAM,wBAAwB,CAAC;AAGhC,QAAA,MAAM,yBAAyB;;;EAU7B,CAAC;AAEH,MAAM,MAAM,wBAAwB,GAAG,MAAM,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAEhF;;;;;;;GAOG;AACH,wBAAgB,6BAA6B,CAC5C,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,MAAM,GACd,cAAc,CAAC,OAAO,yBAAyB,EAAE,SAAS,CAAC,CAoC7D","sourcesContent":["import { type Static, Type } from \"typebox\";\nimport type {\n\tAgentToolResult,\n\tAgentToolUpdateCallback,\n\tExtensionContext,\n\tToolDefinition,\n} from \"../extensions/types.ts\";\nimport { saveProjectMemory } from \"../project-memory.ts\";\n\nconst updateProjectMemorySchema = Type.Object({\n\tcontent: Type.String({\n\t\tdescription:\n\t\t\t\"The complete new content of the shared project memory file (Markdown). The previous content is REPLACED by this value, so include everything worth keeping.\",\n\t}),\n\treason: Type.Optional(\n\t\tType.String({\n\t\t\tdescription: \"Short reason for the update (shown in the confirmation message)\",\n\t\t}),\n\t),\n});\n\nexport type UpdateProjectMemoryInput = Static<typeof updateProjectMemorySchema>;\n\n/**\n * Tool for persisting durable, cross-session project knowledge.\n *\n * The memory file is included in the context of every conversation in the\n * project (CLI and desktop), so facts written here are available to future\n * sessions. Use it for architecture notes, conventions, decisions and anything\n * the user asks to remember.\n */\nexport function createUpdateProjectMemoryTool(\n\tcwd: string,\n\tagentDir: string,\n): ToolDefinition<typeof updateProjectMemorySchema, undefined> {\n\treturn {\n\t\tname: \"update_project_memory\",\n\t\tlabel: \"update project memory\",\n\t\tdescription:\n\t\t\t\"Update the shared project memory: durable knowledge (architecture, conventions, decisions, user preferences) that persists across ALL conversations of this project. Write concise Markdown. Replaces the previous content entirely.\",\n\t\tpromptSnippet: \"Persist durable project knowledge shared across conversations\",\n\t\tpromptGuidelines: [\n\t\t\t\"Use update_project_memory to save facts worth remembering across sessions (architecture, conventions, decisions, user preferences).\",\n\t\t\t\"Keep the memory concise: it is loaded into the context of every conversation in the project.\",\n\t\t],\n\t\tparameters: updateProjectMemorySchema,\n\t\tasync execute(\n\t\t\t_toolCallId: string,\n\t\t\tinput: UpdateProjectMemoryInput,\n\t\t\t_signal: AbortSignal | undefined,\n\t\t\t_onUpdate: AgentToolUpdateCallback<undefined> | undefined,\n\t\t\t_ctx: ExtensionContext,\n\t\t): Promise<AgentToolResult<undefined>> {\n\t\t\tconst { content, reason } = input;\n\t\t\tawait saveProjectMemory(cwd, agentDir, content);\n\t\t\tconst summary = content.split(\"\\n\").find((l) => l.trim().length > 0)?.trim() ?? \"\";\n\t\t\tconst truncated = summary.length > 80 ? `${summary.slice(0, 80)}…` : summary;\n\t\t\treturn {\n\t\t\t\tdetails: undefined,\n\t\t\t\tcontent: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: \"text\" as const,\n\t\t\t\t\t\ttext: `Project memory updated${reason ? ` (${reason})` : \"\"}. ${\n\t\t\t\t\t\t\ttruncated ? `First line: ${truncated}` : \"Empty memory.\"\n\t\t\t\t\t\t}`,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t};\n\t\t},\n\t};\n}\n"]}
1
+ {"version":3,"file":"project-memory-tool.d.ts","sourceRoot":"","sources":["../../../src/core/tools/project-memory-tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EAIX,cAAc,EACd,MAAM,wBAAwB,CAAC;AAGhC,QAAA,MAAM,yBAAyB;;;EAU7B,CAAC;AAEH,MAAM,MAAM,wBAAwB,GAAG,MAAM,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAEhF;;;;;;;GAOG;AACH,wBAAgB,6BAA6B,CAC5C,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,MAAM,GACd,cAAc,CAAC,OAAO,yBAAyB,EAAE,SAAS,CAAC,CAwC7D","sourcesContent":["import { type Static, Type } from \"typebox\";\nimport type {\n\tAgentToolResult,\n\tAgentToolUpdateCallback,\n\tExtensionContext,\n\tToolDefinition,\n} from \"../extensions/types.ts\";\nimport { saveProjectMemory } from \"../project-memory.ts\";\n\nconst updateProjectMemorySchema = Type.Object({\n\tcontent: Type.String({\n\t\tdescription:\n\t\t\t\"The complete new content of the shared project memory file (Markdown). The previous content is REPLACED by this value, so include everything worth keeping.\",\n\t}),\n\treason: Type.Optional(\n\t\tType.String({\n\t\t\tdescription: \"Short reason for the update (shown in the confirmation message)\",\n\t\t}),\n\t),\n});\n\nexport type UpdateProjectMemoryInput = Static<typeof updateProjectMemorySchema>;\n\n/**\n * Tool for persisting durable, cross-session project knowledge.\n *\n * The memory file is included in the context of every conversation in the\n * project (CLI and desktop), so facts written here are available to future\n * sessions. Use it for architecture notes, conventions, decisions and anything\n * the user asks to remember.\n */\nexport function createUpdateProjectMemoryTool(\n\tcwd: string,\n\tagentDir: string,\n): ToolDefinition<typeof updateProjectMemorySchema, undefined> {\n\treturn {\n\t\tname: \"update_project_memory\",\n\t\tlabel: \"update project memory\",\n\t\tdescription:\n\t\t\t\"Update the shared project memory: durable knowledge (architecture, conventions, decisions, user preferences) that persists across ALL conversations of this project. Write concise Markdown. Replaces the previous content entirely.\",\n\t\tpromptSnippet: \"Persist durable project knowledge shared across conversations\",\n\t\tpromptGuidelines: [\n\t\t\t\"Use update_project_memory to save facts worth remembering across sessions (architecture, conventions, decisions, user preferences).\",\n\t\t\t\"Keep the memory concise: it is loaded into the context of every conversation in the project.\",\n\t\t],\n\t\tparameters: updateProjectMemorySchema,\n\t\tasync execute(\n\t\t\t_toolCallId: string,\n\t\t\tinput: UpdateProjectMemoryInput,\n\t\t\t_signal: AbortSignal | undefined,\n\t\t\t_onUpdate: AgentToolUpdateCallback<undefined> | undefined,\n\t\t\t_ctx: ExtensionContext,\n\t\t): Promise<AgentToolResult<undefined>> {\n\t\t\tconst { content, reason } = input;\n\t\t\tawait saveProjectMemory(cwd, agentDir, content);\n\t\t\tconst summary =\n\t\t\t\tcontent\n\t\t\t\t\t.split(\"\\n\")\n\t\t\t\t\t.find((l) => l.trim().length > 0)\n\t\t\t\t\t?.trim() ?? \"\";\n\t\t\tconst truncated = summary.length > 80 ? `${summary.slice(0, 80)}…` : summary;\n\t\t\treturn {\n\t\t\t\tdetails: undefined,\n\t\t\t\tcontent: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: \"text\" as const,\n\t\t\t\t\t\ttext: `Project memory updated${reason ? ` (${reason})` : \"\"}. ${\n\t\t\t\t\t\t\ttruncated ? `First line: ${truncated}` : \"Empty memory.\"\n\t\t\t\t\t\t}`,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t};\n\t\t},\n\t};\n}\n"]}
@@ -30,7 +30,10 @@ export function createUpdateProjectMemoryTool(cwd, agentDir) {
30
30
  async execute(_toolCallId, input, _signal, _onUpdate, _ctx) {
31
31
  const { content, reason } = input;
32
32
  await saveProjectMemory(cwd, agentDir, content);
33
- const summary = content.split("\n").find((l) => l.trim().length > 0)?.trim() ?? "";
33
+ const summary = content
34
+ .split("\n")
35
+ .find((l) => l.trim().length > 0)
36
+ ?.trim() ?? "";
34
37
  const truncated = summary.length > 80 ? `${summary.slice(0, 80)}…` : summary;
35
38
  return {
36
39
  details: undefined,
@@ -1 +1 @@
1
- {"version":3,"file":"project-memory-tool.js","sourceRoot":"","sources":["../../../src/core/tools/project-memory-tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,IAAI,EAAE,MAAM,SAAS,CAAC;AAO5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAEzD,MAAM,yBAAyB,GAAG,IAAI,CAAC,MAAM,CAAC;IAC7C,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC;QACpB,WAAW,EACV,6JAA6J;KAC9J,CAAC;IACF,MAAM,EAAE,IAAI,CAAC,QAAQ,CACpB,IAAI,CAAC,MAAM,CAAC;QACX,WAAW,EAAE,iEAAiE;KAC9E,CAAC,CACF;CACD,CAAC,CAAC;AAIH;;;;;;;GAOG;AACH,MAAM,UAAU,6BAA6B,CAC5C,GAAW,EACX,QAAgB,EAC8C;IAC9D,OAAO;QACN,IAAI,EAAE,uBAAuB;QAC7B,KAAK,EAAE,uBAAuB;QAC9B,WAAW,EACV,sOAAsO;QACvO,aAAa,EAAE,+DAA+D;QAC9E,gBAAgB,EAAE;YACjB,qIAAqI;YACrI,8FAA8F;SAC9F;QACD,UAAU,EAAE,yBAAyB;QACrC,KAAK,CAAC,OAAO,CACZ,WAAmB,EACnB,KAA+B,EAC/B,OAAgC,EAChC,SAAyD,EACzD,IAAsB,EACgB;YACtC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC;YAClC,MAAM,iBAAiB,CAAC,GAAG,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;YAChD,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;YACnF,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,KAAG,CAAC,CAAC,CAAC,OAAO,CAAC;YAC7E,OAAO;gBACN,OAAO,EAAE,SAAS;gBAClB,OAAO,EAAE;oBACR;wBACC,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,yBAAyB,MAAM,CAAC,CAAC,CAAC,KAAK,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,KAC1D,SAAS,CAAC,CAAC,CAAC,eAAe,SAAS,EAAE,CAAC,CAAC,CAAC,eAC1C,EAAE;qBACF;iBACD;aACD,CAAC;QAAA,CACF;KACD,CAAC;AAAA,CACF","sourcesContent":["import { type Static, Type } from \"typebox\";\nimport type {\n\tAgentToolResult,\n\tAgentToolUpdateCallback,\n\tExtensionContext,\n\tToolDefinition,\n} from \"../extensions/types.ts\";\nimport { saveProjectMemory } from \"../project-memory.ts\";\n\nconst updateProjectMemorySchema = Type.Object({\n\tcontent: Type.String({\n\t\tdescription:\n\t\t\t\"The complete new content of the shared project memory file (Markdown). The previous content is REPLACED by this value, so include everything worth keeping.\",\n\t}),\n\treason: Type.Optional(\n\t\tType.String({\n\t\t\tdescription: \"Short reason for the update (shown in the confirmation message)\",\n\t\t}),\n\t),\n});\n\nexport type UpdateProjectMemoryInput = Static<typeof updateProjectMemorySchema>;\n\n/**\n * Tool for persisting durable, cross-session project knowledge.\n *\n * The memory file is included in the context of every conversation in the\n * project (CLI and desktop), so facts written here are available to future\n * sessions. Use it for architecture notes, conventions, decisions and anything\n * the user asks to remember.\n */\nexport function createUpdateProjectMemoryTool(\n\tcwd: string,\n\tagentDir: string,\n): ToolDefinition<typeof updateProjectMemorySchema, undefined> {\n\treturn {\n\t\tname: \"update_project_memory\",\n\t\tlabel: \"update project memory\",\n\t\tdescription:\n\t\t\t\"Update the shared project memory: durable knowledge (architecture, conventions, decisions, user preferences) that persists across ALL conversations of this project. Write concise Markdown. Replaces the previous content entirely.\",\n\t\tpromptSnippet: \"Persist durable project knowledge shared across conversations\",\n\t\tpromptGuidelines: [\n\t\t\t\"Use update_project_memory to save facts worth remembering across sessions (architecture, conventions, decisions, user preferences).\",\n\t\t\t\"Keep the memory concise: it is loaded into the context of every conversation in the project.\",\n\t\t],\n\t\tparameters: updateProjectMemorySchema,\n\t\tasync execute(\n\t\t\t_toolCallId: string,\n\t\t\tinput: UpdateProjectMemoryInput,\n\t\t\t_signal: AbortSignal | undefined,\n\t\t\t_onUpdate: AgentToolUpdateCallback<undefined> | undefined,\n\t\t\t_ctx: ExtensionContext,\n\t\t): Promise<AgentToolResult<undefined>> {\n\t\t\tconst { content, reason } = input;\n\t\t\tawait saveProjectMemory(cwd, agentDir, content);\n\t\t\tconst summary = content.split(\"\\n\").find((l) => l.trim().length > 0)?.trim() ?? \"\";\n\t\t\tconst truncated = summary.length > 80 ? `${summary.slice(0, 80)}…` : summary;\n\t\t\treturn {\n\t\t\t\tdetails: undefined,\n\t\t\t\tcontent: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: \"text\" as const,\n\t\t\t\t\t\ttext: `Project memory updated${reason ? ` (${reason})` : \"\"}. ${\n\t\t\t\t\t\t\ttruncated ? `First line: ${truncated}` : \"Empty memory.\"\n\t\t\t\t\t\t}`,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t};\n\t\t},\n\t};\n}\n"]}
1
+ {"version":3,"file":"project-memory-tool.js","sourceRoot":"","sources":["../../../src/core/tools/project-memory-tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,IAAI,EAAE,MAAM,SAAS,CAAC;AAO5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAEzD,MAAM,yBAAyB,GAAG,IAAI,CAAC,MAAM,CAAC;IAC7C,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC;QACpB,WAAW,EACV,6JAA6J;KAC9J,CAAC;IACF,MAAM,EAAE,IAAI,CAAC,QAAQ,CACpB,IAAI,CAAC,MAAM,CAAC;QACX,WAAW,EAAE,iEAAiE;KAC9E,CAAC,CACF;CACD,CAAC,CAAC;AAIH;;;;;;;GAOG;AACH,MAAM,UAAU,6BAA6B,CAC5C,GAAW,EACX,QAAgB,EAC8C;IAC9D,OAAO;QACN,IAAI,EAAE,uBAAuB;QAC7B,KAAK,EAAE,uBAAuB;QAC9B,WAAW,EACV,sOAAsO;QACvO,aAAa,EAAE,+DAA+D;QAC9E,gBAAgB,EAAE;YACjB,qIAAqI;YACrI,8FAA8F;SAC9F;QACD,UAAU,EAAE,yBAAyB;QACrC,KAAK,CAAC,OAAO,CACZ,WAAmB,EACnB,KAA+B,EAC/B,OAAgC,EAChC,SAAyD,EACzD,IAAsB,EACgB;YACtC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC;YAClC,MAAM,iBAAiB,CAAC,GAAG,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;YAChD,MAAM,OAAO,GACZ,OAAO;iBACL,KAAK,CAAC,IAAI,CAAC;iBACX,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;gBACjC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;YACjB,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,KAAG,CAAC,CAAC,CAAC,OAAO,CAAC;YAC7E,OAAO;gBACN,OAAO,EAAE,SAAS;gBAClB,OAAO,EAAE;oBACR;wBACC,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,yBAAyB,MAAM,CAAC,CAAC,CAAC,KAAK,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,KAC1D,SAAS,CAAC,CAAC,CAAC,eAAe,SAAS,EAAE,CAAC,CAAC,CAAC,eAC1C,EAAE;qBACF;iBACD;aACD,CAAC;QAAA,CACF;KACD,CAAC;AAAA,CACF","sourcesContent":["import { type Static, Type } from \"typebox\";\nimport type {\n\tAgentToolResult,\n\tAgentToolUpdateCallback,\n\tExtensionContext,\n\tToolDefinition,\n} from \"../extensions/types.ts\";\nimport { saveProjectMemory } from \"../project-memory.ts\";\n\nconst updateProjectMemorySchema = Type.Object({\n\tcontent: Type.String({\n\t\tdescription:\n\t\t\t\"The complete new content of the shared project memory file (Markdown). The previous content is REPLACED by this value, so include everything worth keeping.\",\n\t}),\n\treason: Type.Optional(\n\t\tType.String({\n\t\t\tdescription: \"Short reason for the update (shown in the confirmation message)\",\n\t\t}),\n\t),\n});\n\nexport type UpdateProjectMemoryInput = Static<typeof updateProjectMemorySchema>;\n\n/**\n * Tool for persisting durable, cross-session project knowledge.\n *\n * The memory file is included in the context of every conversation in the\n * project (CLI and desktop), so facts written here are available to future\n * sessions. Use it for architecture notes, conventions, decisions and anything\n * the user asks to remember.\n */\nexport function createUpdateProjectMemoryTool(\n\tcwd: string,\n\tagentDir: string,\n): ToolDefinition<typeof updateProjectMemorySchema, undefined> {\n\treturn {\n\t\tname: \"update_project_memory\",\n\t\tlabel: \"update project memory\",\n\t\tdescription:\n\t\t\t\"Update the shared project memory: durable knowledge (architecture, conventions, decisions, user preferences) that persists across ALL conversations of this project. Write concise Markdown. Replaces the previous content entirely.\",\n\t\tpromptSnippet: \"Persist durable project knowledge shared across conversations\",\n\t\tpromptGuidelines: [\n\t\t\t\"Use update_project_memory to save facts worth remembering across sessions (architecture, conventions, decisions, user preferences).\",\n\t\t\t\"Keep the memory concise: it is loaded into the context of every conversation in the project.\",\n\t\t],\n\t\tparameters: updateProjectMemorySchema,\n\t\tasync execute(\n\t\t\t_toolCallId: string,\n\t\t\tinput: UpdateProjectMemoryInput,\n\t\t\t_signal: AbortSignal | undefined,\n\t\t\t_onUpdate: AgentToolUpdateCallback<undefined> | undefined,\n\t\t\t_ctx: ExtensionContext,\n\t\t): Promise<AgentToolResult<undefined>> {\n\t\t\tconst { content, reason } = input;\n\t\t\tawait saveProjectMemory(cwd, agentDir, content);\n\t\t\tconst summary =\n\t\t\t\tcontent\n\t\t\t\t\t.split(\"\\n\")\n\t\t\t\t\t.find((l) => l.trim().length > 0)\n\t\t\t\t\t?.trim() ?? \"\";\n\t\t\tconst truncated = summary.length > 80 ? `${summary.slice(0, 80)}…` : summary;\n\t\t\treturn {\n\t\t\t\tdetails: undefined,\n\t\t\t\tcontent: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: \"text\" as const,\n\t\t\t\t\t\ttext: `Project memory updated${reason ? ` (${reason})` : \"\"}. ${\n\t\t\t\t\t\t\ttruncated ? `First line: ${truncated}` : \"Empty memory.\"\n\t\t\t\t\t\t}`,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t};\n\t\t},\n\t};\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"trust-manager.d.ts","sourceRoot":"","sources":["../../src/core/trust-manager.ts"],"names":[],"mappings":"AAOA,MAAM,MAAM,oBAAoB,GAAG,OAAO,GAAG,IAAI,CAAC;AAElD,MAAM,WAAW,sBAAsB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,kBAAkB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,oBAAoB,CAAC;CAC/B;AAED,MAAM,WAAW,kBAAkB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,kBAAkB,EAAE,CAAC;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAkCD,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAIzE;AAED,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;IAAE,kBAAkB,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,kBAAkB,EAAE,CA8BpH;AAkFD;;;;;;GAMG;AACH,wBAAgB,iCAAiC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAsBtE;AAED,qBAAa,iBAAiB;IAC7B,OAAO,CAAC,SAAS,CAAS;IAE1B,YAAY,QAAQ,EAAE,MAAM,EAE3B;IAED,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,oBAAoB,CAErC;IAED,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,sBAAsB,GAAG,IAAI,CAKnD;IAED,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,oBAAoB,GAAG,IAAI,CAErD;IAED,OAAO,CAAC,SAAS,EAAE,kBAAkB,EAAE,GAAG,IAAI,CAa7C;CACD","sourcesContent":["import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport lockfile from \"proper-lockfile\";\nimport { CONFIG_DIR_NAME } from \"../config.ts\";\nimport { canonicalizePath, resolvePath } from \"../utils/paths.ts\";\n\nexport type ProjectTrustDecision = boolean | null;\n\nexport interface ProjectTrustStoreEntry {\n\tpath: string;\n\tdecision: boolean;\n}\n\nexport interface ProjectTrustUpdate {\n\tpath: string;\n\tdecision: ProjectTrustDecision;\n}\n\nexport interface ProjectTrustOption {\n\tlabel: string;\n\ttrusted: boolean;\n\tupdates: ProjectTrustUpdate[];\n\tsavedPath?: string;\n}\n\ntype TrustFile = Record<string, boolean | null | undefined>;\n\nconst TRUST_REQUIRING_PROJECT_CONFIG_RESOURCES = [\n\t\"settings.json\",\n\t\"extensions\",\n\t\"skills\",\n\t\"prompts\",\n\t\"themes\",\n\t\"SYSTEM.md\",\n\t\"APPEND_SYSTEM.md\",\n] as const;\n\nfunction normalizeCwd(cwd: string): string {\n\treturn canonicalizePath(resolvePath(cwd));\n}\n\nfunction findNearestTrustEntry(data: TrustFile, cwd: string): ProjectTrustStoreEntry | null {\n\tlet currentDir = normalizeCwd(cwd);\n\twhile (true) {\n\t\tconst value = data[currentDir];\n\t\tif (value === true || value === false) {\n\t\t\treturn { path: currentDir, decision: value };\n\t\t}\n\n\t\tconst parentDir = dirname(currentDir);\n\t\tif (parentDir === currentDir) {\n\t\t\treturn null;\n\t\t}\n\t\tcurrentDir = parentDir;\n\t}\n}\n\nexport function getProjectTrustParentPath(cwd: string): string | undefined {\n\tconst trustPath = normalizeCwd(cwd);\n\tconst parentDir = dirname(trustPath);\n\treturn parentDir === trustPath ? undefined : parentDir;\n}\n\nexport function getProjectTrustOptions(cwd: string, options?: { includeSessionOnly?: boolean }): ProjectTrustOption[] {\n\tconst trustPath = normalizeCwd(cwd);\n\tconst trustOptions: ProjectTrustOption[] = [\n\t\t{ label: \"Trust\", trusted: true, updates: [{ path: trustPath, decision: true }], savedPath: trustPath },\n\t];\n\tconst parentPath = getProjectTrustParentPath(cwd);\n\tif (parentPath !== undefined) {\n\t\ttrustOptions.push({\n\t\t\tlabel: `Trust parent folder (${parentPath})`,\n\t\t\ttrusted: true,\n\t\t\tupdates: [\n\t\t\t\t{ path: parentPath, decision: true },\n\t\t\t\t{ path: trustPath, decision: null },\n\t\t\t],\n\t\t\tsavedPath: parentPath,\n\t\t});\n\t}\n\tif (options?.includeSessionOnly) {\n\t\ttrustOptions.push({ label: \"Trust (this session only)\", trusted: true, updates: [] });\n\t}\n\ttrustOptions.push({\n\t\tlabel: \"Do not trust\",\n\t\ttrusted: false,\n\t\tupdates: [{ path: trustPath, decision: false }],\n\t\tsavedPath: trustPath,\n\t});\n\tif (options?.includeSessionOnly) {\n\t\ttrustOptions.push({ label: \"Do not trust (this session only)\", trusted: false, updates: [] });\n\t}\n\treturn trustOptions;\n}\n\nfunction readTrustFile(path: string): TrustFile {\n\tif (!existsSync(path)) {\n\t\treturn {};\n\t}\n\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(readFileSync(path, \"utf-8\"));\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\tthrow new Error(`Failed to read trust store ${path}: ${message}`);\n\t}\n\n\tif (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) {\n\t\tthrow new Error(`Invalid trust store ${path}: expected an object`);\n\t}\n\n\tconst data: TrustFile = {};\n\tfor (const [key, value] of Object.entries(parsed)) {\n\t\tif (value !== true && value !== false && value !== null) {\n\t\t\tthrow new Error(`Invalid trust store ${path}: value for ${JSON.stringify(key)} must be true, false, or null`);\n\t\t}\n\t\tdata[key] = value;\n\t}\n\treturn data;\n}\n\nfunction writeTrustFile(path: string, data: TrustFile): void {\n\tconst sorted: TrustFile = {};\n\tfor (const key of Object.keys(data).sort()) {\n\t\tconst value = data[key];\n\t\tif (value === true || value === false || value === null) {\n\t\t\tsorted[key] = value;\n\t\t}\n\t}\n\tmkdirSync(dirname(path), { recursive: true });\n\twriteFileSync(path, `${JSON.stringify(sorted, null, 2)}\\n`, \"utf-8\");\n}\n\nfunction acquireTrustLockSync(path: string): () => void {\n\tconst trustDir = dirname(path);\n\tmkdirSync(trustDir, { recursive: true });\n\tconst maxAttempts = 10;\n\tconst delayMs = 20;\n\tlet lastError: unknown;\n\n\tfor (let attempt = 1; attempt <= maxAttempts; attempt++) {\n\t\ttry {\n\t\t\treturn lockfile.lockSync(trustDir, { realpath: false, lockfilePath: `${path}.lock` });\n\t\t} catch (error) {\n\t\t\tconst code =\n\t\t\t\ttypeof error === \"object\" && error !== null && \"code\" in error\n\t\t\t\t\t? String((error as { code?: unknown }).code)\n\t\t\t\t\t: undefined;\n\t\t\tif (code !== \"ELOCKED\" || attempt === maxAttempts) {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\tlastError = error;\n\t\t\tconst start = Date.now();\n\t\t\twhile (Date.now() - start < delayMs) {\n\t\t\t\t// Sleep synchronously to avoid changing trust store callers to async.\n\t\t\t}\n\t\t}\n\t}\n\n\tif (lastError instanceof Error) {\n\t\tthrow lastError;\n\t}\n\tthrow new Error(\"Failed to acquire trust store lock\");\n}\n\nfunction withTrustFileLock<T>(path: string, fn: () => T): T {\n\tconst release = acquireTrustLockSync(path);\n\ttry {\n\t\treturn fn();\n\t} finally {\n\t\trelease();\n\t}\n}\n\n/**\n * Returns true when cwd has project-local resources that must be gated by\n * project trust: trust-requiring entries under cwd/.pi, or .agents/skills in\n * cwd or one of its ancestors. Returns false when no such project resources\n * exist. The user/global ~/.agents/skills directory is always treated as a\n * trusted user resource and is ignored here, even when cwd is $HOME.\n */\nexport function hasTrustRequiringProjectResources(cwd: string): boolean {\n\tconst homeDir = canonicalizePath(resolvePath(process.env.HOME || homedir()));\n\tconst userAgentsSkillsDir = join(homeDir, \".agents\", \"skills\");\n\tlet currentDir = canonicalizePath(resolvePath(cwd));\n\n\tconst configDir = join(currentDir, CONFIG_DIR_NAME);\n\tif (TRUST_REQUIRING_PROJECT_CONFIG_RESOURCES.some((entry) => existsSync(join(configDir, entry)))) {\n\t\treturn true;\n\t}\n\n\twhile (true) {\n\t\tconst agentsSkillsDir = join(currentDir, \".agents\", \"skills\");\n\t\tif (agentsSkillsDir !== userAgentsSkillsDir && existsSync(agentsSkillsDir)) {\n\t\t\treturn true;\n\t\t}\n\n\t\tconst parentDir = dirname(currentDir);\n\t\tif (parentDir === currentDir) {\n\t\t\treturn false;\n\t\t}\n\t\tcurrentDir = parentDir;\n\t}\n}\n\nexport class ProjectTrustStore {\n\tprivate trustPath: string;\n\n\tconstructor(agentDir: string) {\n\t\tthis.trustPath = join(resolvePath(agentDir), \"trust.json\");\n\t}\n\n\tget(cwd: string): ProjectTrustDecision {\n\t\treturn this.getEntry(cwd)?.decision ?? null;\n\t}\n\n\tgetEntry(cwd: string): ProjectTrustStoreEntry | null {\n\t\treturn withTrustFileLock(this.trustPath, () => {\n\t\t\tconst data = readTrustFile(this.trustPath);\n\t\t\treturn findNearestTrustEntry(data, cwd);\n\t\t});\n\t}\n\n\tset(cwd: string, decision: ProjectTrustDecision): void {\n\t\tthis.setMany([{ path: cwd, decision }]);\n\t}\n\n\tsetMany(decisions: ProjectTrustUpdate[]): void {\n\t\twithTrustFileLock(this.trustPath, () => {\n\t\t\tconst data = readTrustFile(this.trustPath);\n\t\t\tfor (const { path, decision } of decisions) {\n\t\t\t\tconst key = normalizeCwd(path);\n\t\t\t\tif (decision === null) {\n\t\t\t\t\tdelete data[key];\n\t\t\t\t} else {\n\t\t\t\t\tdata[key] = decision;\n\t\t\t\t}\n\t\t\t}\n\t\t\twriteTrustFile(this.trustPath, data);\n\t\t});\n\t}\n}\n"]}
1
+ {"version":3,"file":"trust-manager.d.ts","sourceRoot":"","sources":["../../src/core/trust-manager.ts"],"names":[],"mappings":"AAQA,MAAM,MAAM,oBAAoB,GAAG,OAAO,GAAG,IAAI,CAAC;AAElD,MAAM,WAAW,sBAAsB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,kBAAkB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,oBAAoB,CAAC;CAC/B;AAED,MAAM,WAAW,kBAAkB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,kBAAkB,EAAE,CAAC;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAkCD,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAIzE;AAED,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;IAAE,kBAAkB,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,kBAAkB,EAAE,CA8BpH;AAkFD;;;;;;GAMG;AACH,wBAAgB,iCAAiC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAsBtE;AAED,qBAAa,iBAAiB;IAC7B,OAAO,CAAC,SAAS,CAAS;IAE1B,YAAY,QAAQ,EAAE,MAAM,EAE3B;IAED,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,oBAAoB,CAErC;IAED,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,sBAAsB,GAAG,IAAI,CAKnD;IAED,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,oBAAoB,GAAG,IAAI,CAErD;IAED,OAAO,CAAC,SAAS,EAAE,kBAAkB,EAAE,GAAG,IAAI,CAa7C;CACD","sourcesContent":["import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport lockfile from \"proper-lockfile\";\nimport { CONFIG_DIR_NAME } from \"../config.ts\";\nimport { canonicalizePath, resolvePath } from \"../utils/paths.ts\";\nimport { stripBom } from \"../utils/text.ts\";\n\nexport type ProjectTrustDecision = boolean | null;\n\nexport interface ProjectTrustStoreEntry {\n\tpath: string;\n\tdecision: boolean;\n}\n\nexport interface ProjectTrustUpdate {\n\tpath: string;\n\tdecision: ProjectTrustDecision;\n}\n\nexport interface ProjectTrustOption {\n\tlabel: string;\n\ttrusted: boolean;\n\tupdates: ProjectTrustUpdate[];\n\tsavedPath?: string;\n}\n\ntype TrustFile = Record<string, boolean | null | undefined>;\n\nconst TRUST_REQUIRING_PROJECT_CONFIG_RESOURCES = [\n\t\"settings.json\",\n\t\"extensions\",\n\t\"skills\",\n\t\"prompts\",\n\t\"themes\",\n\t\"SYSTEM.md\",\n\t\"APPEND_SYSTEM.md\",\n] as const;\n\nfunction normalizeCwd(cwd: string): string {\n\treturn canonicalizePath(resolvePath(cwd));\n}\n\nfunction findNearestTrustEntry(data: TrustFile, cwd: string): ProjectTrustStoreEntry | null {\n\tlet currentDir = normalizeCwd(cwd);\n\twhile (true) {\n\t\tconst value = data[currentDir];\n\t\tif (value === true || value === false) {\n\t\t\treturn { path: currentDir, decision: value };\n\t\t}\n\n\t\tconst parentDir = dirname(currentDir);\n\t\tif (parentDir === currentDir) {\n\t\t\treturn null;\n\t\t}\n\t\tcurrentDir = parentDir;\n\t}\n}\n\nexport function getProjectTrustParentPath(cwd: string): string | undefined {\n\tconst trustPath = normalizeCwd(cwd);\n\tconst parentDir = dirname(trustPath);\n\treturn parentDir === trustPath ? undefined : parentDir;\n}\n\nexport function getProjectTrustOptions(cwd: string, options?: { includeSessionOnly?: boolean }): ProjectTrustOption[] {\n\tconst trustPath = normalizeCwd(cwd);\n\tconst trustOptions: ProjectTrustOption[] = [\n\t\t{ label: \"Trust\", trusted: true, updates: [{ path: trustPath, decision: true }], savedPath: trustPath },\n\t];\n\tconst parentPath = getProjectTrustParentPath(cwd);\n\tif (parentPath !== undefined) {\n\t\ttrustOptions.push({\n\t\t\tlabel: `Trust parent folder (${parentPath})`,\n\t\t\ttrusted: true,\n\t\t\tupdates: [\n\t\t\t\t{ path: parentPath, decision: true },\n\t\t\t\t{ path: trustPath, decision: null },\n\t\t\t],\n\t\t\tsavedPath: parentPath,\n\t\t});\n\t}\n\tif (options?.includeSessionOnly) {\n\t\ttrustOptions.push({ label: \"Trust (this session only)\", trusted: true, updates: [] });\n\t}\n\ttrustOptions.push({\n\t\tlabel: \"Do not trust\",\n\t\ttrusted: false,\n\t\tupdates: [{ path: trustPath, decision: false }],\n\t\tsavedPath: trustPath,\n\t});\n\tif (options?.includeSessionOnly) {\n\t\ttrustOptions.push({ label: \"Do not trust (this session only)\", trusted: false, updates: [] });\n\t}\n\treturn trustOptions;\n}\n\nfunction readTrustFile(path: string): TrustFile {\n\tif (!existsSync(path)) {\n\t\treturn {};\n\t}\n\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(stripBom(readFileSync(path, \"utf-8\")));\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\tthrow new Error(`Failed to read trust store ${path}: ${message}`);\n\t}\n\n\tif (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) {\n\t\tthrow new Error(`Invalid trust store ${path}: expected an object`);\n\t}\n\n\tconst data: TrustFile = {};\n\tfor (const [key, value] of Object.entries(parsed)) {\n\t\tif (value !== true && value !== false && value !== null) {\n\t\t\tthrow new Error(`Invalid trust store ${path}: value for ${JSON.stringify(key)} must be true, false, or null`);\n\t\t}\n\t\tdata[key] = value;\n\t}\n\treturn data;\n}\n\nfunction writeTrustFile(path: string, data: TrustFile): void {\n\tconst sorted: TrustFile = {};\n\tfor (const key of Object.keys(data).sort()) {\n\t\tconst value = data[key];\n\t\tif (value === true || value === false || value === null) {\n\t\t\tsorted[key] = value;\n\t\t}\n\t}\n\tmkdirSync(dirname(path), { recursive: true });\n\twriteFileSync(path, `${JSON.stringify(sorted, null, 2)}\\n`, \"utf-8\");\n}\n\nfunction acquireTrustLockSync(path: string): () => void {\n\tconst trustDir = dirname(path);\n\tmkdirSync(trustDir, { recursive: true });\n\tconst maxAttempts = 10;\n\tconst delayMs = 20;\n\tlet lastError: unknown;\n\n\tfor (let attempt = 1; attempt <= maxAttempts; attempt++) {\n\t\ttry {\n\t\t\treturn lockfile.lockSync(trustDir, { realpath: false, lockfilePath: `${path}.lock` });\n\t\t} catch (error) {\n\t\t\tconst code =\n\t\t\t\ttypeof error === \"object\" && error !== null && \"code\" in error\n\t\t\t\t\t? String((error as { code?: unknown }).code)\n\t\t\t\t\t: undefined;\n\t\t\tif (code !== \"ELOCKED\" || attempt === maxAttempts) {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\tlastError = error;\n\t\t\tconst start = Date.now();\n\t\t\twhile (Date.now() - start < delayMs) {\n\t\t\t\t// Sleep synchronously to avoid changing trust store callers to async.\n\t\t\t}\n\t\t}\n\t}\n\n\tif (lastError instanceof Error) {\n\t\tthrow lastError;\n\t}\n\tthrow new Error(\"Failed to acquire trust store lock\");\n}\n\nfunction withTrustFileLock<T>(path: string, fn: () => T): T {\n\tconst release = acquireTrustLockSync(path);\n\ttry {\n\t\treturn fn();\n\t} finally {\n\t\trelease();\n\t}\n}\n\n/**\n * Returns true when cwd has project-local resources that must be gated by\n * project trust: trust-requiring entries under cwd/.pi, or .agents/skills in\n * cwd or one of its ancestors. Returns false when no such project resources\n * exist. The user/global ~/.agents/skills directory is always treated as a\n * trusted user resource and is ignored here, even when cwd is $HOME.\n */\nexport function hasTrustRequiringProjectResources(cwd: string): boolean {\n\tconst homeDir = canonicalizePath(resolvePath(process.env.HOME || homedir()));\n\tconst userAgentsSkillsDir = join(homeDir, \".agents\", \"skills\");\n\tlet currentDir = canonicalizePath(resolvePath(cwd));\n\n\tconst configDir = join(currentDir, CONFIG_DIR_NAME);\n\tif (TRUST_REQUIRING_PROJECT_CONFIG_RESOURCES.some((entry) => existsSync(join(configDir, entry)))) {\n\t\treturn true;\n\t}\n\n\twhile (true) {\n\t\tconst agentsSkillsDir = join(currentDir, \".agents\", \"skills\");\n\t\tif (agentsSkillsDir !== userAgentsSkillsDir && existsSync(agentsSkillsDir)) {\n\t\t\treturn true;\n\t\t}\n\n\t\tconst parentDir = dirname(currentDir);\n\t\tif (parentDir === currentDir) {\n\t\t\treturn false;\n\t\t}\n\t\tcurrentDir = parentDir;\n\t}\n}\n\nexport class ProjectTrustStore {\n\tprivate trustPath: string;\n\n\tconstructor(agentDir: string) {\n\t\tthis.trustPath = join(resolvePath(agentDir), \"trust.json\");\n\t}\n\n\tget(cwd: string): ProjectTrustDecision {\n\t\treturn this.getEntry(cwd)?.decision ?? null;\n\t}\n\n\tgetEntry(cwd: string): ProjectTrustStoreEntry | null {\n\t\treturn withTrustFileLock(this.trustPath, () => {\n\t\t\tconst data = readTrustFile(this.trustPath);\n\t\t\treturn findNearestTrustEntry(data, cwd);\n\t\t});\n\t}\n\n\tset(cwd: string, decision: ProjectTrustDecision): void {\n\t\tthis.setMany([{ path: cwd, decision }]);\n\t}\n\n\tsetMany(decisions: ProjectTrustUpdate[]): void {\n\t\twithTrustFileLock(this.trustPath, () => {\n\t\t\tconst data = readTrustFile(this.trustPath);\n\t\t\tfor (const { path, decision } of decisions) {\n\t\t\t\tconst key = normalizeCwd(path);\n\t\t\t\tif (decision === null) {\n\t\t\t\t\tdelete data[key];\n\t\t\t\t} else {\n\t\t\t\t\tdata[key] = decision;\n\t\t\t\t}\n\t\t\t}\n\t\t\twriteTrustFile(this.trustPath, data);\n\t\t});\n\t}\n}\n"]}
@@ -4,6 +4,7 @@ import { dirname, join } from "node:path";
4
4
  import lockfile from "proper-lockfile";
5
5
  import { CONFIG_DIR_NAME } from "../config.js";
6
6
  import { canonicalizePath, resolvePath } from "../utils/paths.js";
7
+ import { stripBom } from "../utils/text.js";
7
8
  const TRUST_REQUIRING_PROJECT_CONFIG_RESOURCES = [
8
9
  "settings.json",
9
10
  "extensions",
@@ -72,7 +73,7 @@ function readTrustFile(path) {
72
73
  }
73
74
  let parsed;
74
75
  try {
75
- parsed = JSON.parse(readFileSync(path, "utf-8"));
76
+ parsed = JSON.parse(stripBom(readFileSync(path, "utf-8")));
76
77
  }
77
78
  catch (error) {
78
79
  const message = error instanceof Error ? error.message : String(error);
@@ -1 +1 @@
1
- {"version":3,"file":"trust-manager.js","sourceRoot":"","sources":["../../src/core/trust-manager.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport lockfile from \"proper-lockfile\";\nimport { CONFIG_DIR_NAME } from \"../config.ts\";\nimport { canonicalizePath, resolvePath } from \"../utils/paths.ts\";\n\nexport type ProjectTrustDecision = boolean | null;\n\nexport interface ProjectTrustStoreEntry {\n\tpath: string;\n\tdecision: boolean;\n}\n\nexport interface ProjectTrustUpdate {\n\tpath: string;\n\tdecision: ProjectTrustDecision;\n}\n\nexport interface ProjectTrustOption {\n\tlabel: string;\n\ttrusted: boolean;\n\tupdates: ProjectTrustUpdate[];\n\tsavedPath?: string;\n}\n\ntype TrustFile = Record<string, boolean | null | undefined>;\n\nconst TRUST_REQUIRING_PROJECT_CONFIG_RESOURCES = [\n\t\"settings.json\",\n\t\"extensions\",\n\t\"skills\",\n\t\"prompts\",\n\t\"themes\",\n\t\"SYSTEM.md\",\n\t\"APPEND_SYSTEM.md\",\n] as const;\n\nfunction normalizeCwd(cwd: string): string {\n\treturn canonicalizePath(resolvePath(cwd));\n}\n\nfunction findNearestTrustEntry(data: TrustFile, cwd: string): ProjectTrustStoreEntry | null {\n\tlet currentDir = normalizeCwd(cwd);\n\twhile (true) {\n\t\tconst value = data[currentDir];\n\t\tif (value === true || value === false) {\n\t\t\treturn { path: currentDir, decision: value };\n\t\t}\n\n\t\tconst parentDir = dirname(currentDir);\n\t\tif (parentDir === currentDir) {\n\t\t\treturn null;\n\t\t}\n\t\tcurrentDir = parentDir;\n\t}\n}\n\nexport function getProjectTrustParentPath(cwd: string): string | undefined {\n\tconst trustPath = normalizeCwd(cwd);\n\tconst parentDir = dirname(trustPath);\n\treturn parentDir === trustPath ? undefined : parentDir;\n}\n\nexport function getProjectTrustOptions(cwd: string, options?: { includeSessionOnly?: boolean }): ProjectTrustOption[] {\n\tconst trustPath = normalizeCwd(cwd);\n\tconst trustOptions: ProjectTrustOption[] = [\n\t\t{ label: \"Trust\", trusted: true, updates: [{ path: trustPath, decision: true }], savedPath: trustPath },\n\t];\n\tconst parentPath = getProjectTrustParentPath(cwd);\n\tif (parentPath !== undefined) {\n\t\ttrustOptions.push({\n\t\t\tlabel: `Trust parent folder (${parentPath})`,\n\t\t\ttrusted: true,\n\t\t\tupdates: [\n\t\t\t\t{ path: parentPath, decision: true },\n\t\t\t\t{ path: trustPath, decision: null },\n\t\t\t],\n\t\t\tsavedPath: parentPath,\n\t\t});\n\t}\n\tif (options?.includeSessionOnly) {\n\t\ttrustOptions.push({ label: \"Trust (this session only)\", trusted: true, updates: [] });\n\t}\n\ttrustOptions.push({\n\t\tlabel: \"Do not trust\",\n\t\ttrusted: false,\n\t\tupdates: [{ path: trustPath, decision: false }],\n\t\tsavedPath: trustPath,\n\t});\n\tif (options?.includeSessionOnly) {\n\t\ttrustOptions.push({ label: \"Do not trust (this session only)\", trusted: false, updates: [] });\n\t}\n\treturn trustOptions;\n}\n\nfunction readTrustFile(path: string): TrustFile {\n\tif (!existsSync(path)) {\n\t\treturn {};\n\t}\n\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(readFileSync(path, \"utf-8\"));\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\tthrow new Error(`Failed to read trust store ${path}: ${message}`);\n\t}\n\n\tif (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) {\n\t\tthrow new Error(`Invalid trust store ${path}: expected an object`);\n\t}\n\n\tconst data: TrustFile = {};\n\tfor (const [key, value] of Object.entries(parsed)) {\n\t\tif (value !== true && value !== false && value !== null) {\n\t\t\tthrow new Error(`Invalid trust store ${path}: value for ${JSON.stringify(key)} must be true, false, or null`);\n\t\t}\n\t\tdata[key] = value;\n\t}\n\treturn data;\n}\n\nfunction writeTrustFile(path: string, data: TrustFile): void {\n\tconst sorted: TrustFile = {};\n\tfor (const key of Object.keys(data).sort()) {\n\t\tconst value = data[key];\n\t\tif (value === true || value === false || value === null) {\n\t\t\tsorted[key] = value;\n\t\t}\n\t}\n\tmkdirSync(dirname(path), { recursive: true });\n\twriteFileSync(path, `${JSON.stringify(sorted, null, 2)}\\n`, \"utf-8\");\n}\n\nfunction acquireTrustLockSync(path: string): () => void {\n\tconst trustDir = dirname(path);\n\tmkdirSync(trustDir, { recursive: true });\n\tconst maxAttempts = 10;\n\tconst delayMs = 20;\n\tlet lastError: unknown;\n\n\tfor (let attempt = 1; attempt <= maxAttempts; attempt++) {\n\t\ttry {\n\t\t\treturn lockfile.lockSync(trustDir, { realpath: false, lockfilePath: `${path}.lock` });\n\t\t} catch (error) {\n\t\t\tconst code =\n\t\t\t\ttypeof error === \"object\" && error !== null && \"code\" in error\n\t\t\t\t\t? String((error as { code?: unknown }).code)\n\t\t\t\t\t: undefined;\n\t\t\tif (code !== \"ELOCKED\" || attempt === maxAttempts) {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\tlastError = error;\n\t\t\tconst start = Date.now();\n\t\t\twhile (Date.now() - start < delayMs) {\n\t\t\t\t// Sleep synchronously to avoid changing trust store callers to async.\n\t\t\t}\n\t\t}\n\t}\n\n\tif (lastError instanceof Error) {\n\t\tthrow lastError;\n\t}\n\tthrow new Error(\"Failed to acquire trust store lock\");\n}\n\nfunction withTrustFileLock<T>(path: string, fn: () => T): T {\n\tconst release = acquireTrustLockSync(path);\n\ttry {\n\t\treturn fn();\n\t} finally {\n\t\trelease();\n\t}\n}\n\n/**\n * Returns true when cwd has project-local resources that must be gated by\n * project trust: trust-requiring entries under cwd/.pi, or .agents/skills in\n * cwd or one of its ancestors. Returns false when no such project resources\n * exist. The user/global ~/.agents/skills directory is always treated as a\n * trusted user resource and is ignored here, even when cwd is $HOME.\n */\nexport function hasTrustRequiringProjectResources(cwd: string): boolean {\n\tconst homeDir = canonicalizePath(resolvePath(process.env.HOME || homedir()));\n\tconst userAgentsSkillsDir = join(homeDir, \".agents\", \"skills\");\n\tlet currentDir = canonicalizePath(resolvePath(cwd));\n\n\tconst configDir = join(currentDir, CONFIG_DIR_NAME);\n\tif (TRUST_REQUIRING_PROJECT_CONFIG_RESOURCES.some((entry) => existsSync(join(configDir, entry)))) {\n\t\treturn true;\n\t}\n\n\twhile (true) {\n\t\tconst agentsSkillsDir = join(currentDir, \".agents\", \"skills\");\n\t\tif (agentsSkillsDir !== userAgentsSkillsDir && existsSync(agentsSkillsDir)) {\n\t\t\treturn true;\n\t\t}\n\n\t\tconst parentDir = dirname(currentDir);\n\t\tif (parentDir === currentDir) {\n\t\t\treturn false;\n\t\t}\n\t\tcurrentDir = parentDir;\n\t}\n}\n\nexport class ProjectTrustStore {\n\tprivate trustPath: string;\n\n\tconstructor(agentDir: string) {\n\t\tthis.trustPath = join(resolvePath(agentDir), \"trust.json\");\n\t}\n\n\tget(cwd: string): ProjectTrustDecision {\n\t\treturn this.getEntry(cwd)?.decision ?? null;\n\t}\n\n\tgetEntry(cwd: string): ProjectTrustStoreEntry | null {\n\t\treturn withTrustFileLock(this.trustPath, () => {\n\t\t\tconst data = readTrustFile(this.trustPath);\n\t\t\treturn findNearestTrustEntry(data, cwd);\n\t\t});\n\t}\n\n\tset(cwd: string, decision: ProjectTrustDecision): void {\n\t\tthis.setMany([{ path: cwd, decision }]);\n\t}\n\n\tsetMany(decisions: ProjectTrustUpdate[]): void {\n\t\twithTrustFileLock(this.trustPath, () => {\n\t\t\tconst data = readTrustFile(this.trustPath);\n\t\t\tfor (const { path, decision } of decisions) {\n\t\t\t\tconst key = normalizeCwd(path);\n\t\t\t\tif (decision === null) {\n\t\t\t\t\tdelete data[key];\n\t\t\t\t} else {\n\t\t\t\t\tdata[key] = decision;\n\t\t\t\t}\n\t\t\t}\n\t\t\twriteTrustFile(this.trustPath, data);\n\t\t});\n\t}\n}\n"]}
1
+ {"version":3,"file":"trust-manager.js","sourceRoot":"","sources":["../../src/core/trust-manager.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport lockfile from \"proper-lockfile\";\nimport { CONFIG_DIR_NAME } from \"../config.ts\";\nimport { canonicalizePath, resolvePath } from \"../utils/paths.ts\";\nimport { stripBom } from \"../utils/text.ts\";\n\nexport type ProjectTrustDecision = boolean | null;\n\nexport interface ProjectTrustStoreEntry {\n\tpath: string;\n\tdecision: boolean;\n}\n\nexport interface ProjectTrustUpdate {\n\tpath: string;\n\tdecision: ProjectTrustDecision;\n}\n\nexport interface ProjectTrustOption {\n\tlabel: string;\n\ttrusted: boolean;\n\tupdates: ProjectTrustUpdate[];\n\tsavedPath?: string;\n}\n\ntype TrustFile = Record<string, boolean | null | undefined>;\n\nconst TRUST_REQUIRING_PROJECT_CONFIG_RESOURCES = [\n\t\"settings.json\",\n\t\"extensions\",\n\t\"skills\",\n\t\"prompts\",\n\t\"themes\",\n\t\"SYSTEM.md\",\n\t\"APPEND_SYSTEM.md\",\n] as const;\n\nfunction normalizeCwd(cwd: string): string {\n\treturn canonicalizePath(resolvePath(cwd));\n}\n\nfunction findNearestTrustEntry(data: TrustFile, cwd: string): ProjectTrustStoreEntry | null {\n\tlet currentDir = normalizeCwd(cwd);\n\twhile (true) {\n\t\tconst value = data[currentDir];\n\t\tif (value === true || value === false) {\n\t\t\treturn { path: currentDir, decision: value };\n\t\t}\n\n\t\tconst parentDir = dirname(currentDir);\n\t\tif (parentDir === currentDir) {\n\t\t\treturn null;\n\t\t}\n\t\tcurrentDir = parentDir;\n\t}\n}\n\nexport function getProjectTrustParentPath(cwd: string): string | undefined {\n\tconst trustPath = normalizeCwd(cwd);\n\tconst parentDir = dirname(trustPath);\n\treturn parentDir === trustPath ? undefined : parentDir;\n}\n\nexport function getProjectTrustOptions(cwd: string, options?: { includeSessionOnly?: boolean }): ProjectTrustOption[] {\n\tconst trustPath = normalizeCwd(cwd);\n\tconst trustOptions: ProjectTrustOption[] = [\n\t\t{ label: \"Trust\", trusted: true, updates: [{ path: trustPath, decision: true }], savedPath: trustPath },\n\t];\n\tconst parentPath = getProjectTrustParentPath(cwd);\n\tif (parentPath !== undefined) {\n\t\ttrustOptions.push({\n\t\t\tlabel: `Trust parent folder (${parentPath})`,\n\t\t\ttrusted: true,\n\t\t\tupdates: [\n\t\t\t\t{ path: parentPath, decision: true },\n\t\t\t\t{ path: trustPath, decision: null },\n\t\t\t],\n\t\t\tsavedPath: parentPath,\n\t\t});\n\t}\n\tif (options?.includeSessionOnly) {\n\t\ttrustOptions.push({ label: \"Trust (this session only)\", trusted: true, updates: [] });\n\t}\n\ttrustOptions.push({\n\t\tlabel: \"Do not trust\",\n\t\ttrusted: false,\n\t\tupdates: [{ path: trustPath, decision: false }],\n\t\tsavedPath: trustPath,\n\t});\n\tif (options?.includeSessionOnly) {\n\t\ttrustOptions.push({ label: \"Do not trust (this session only)\", trusted: false, updates: [] });\n\t}\n\treturn trustOptions;\n}\n\nfunction readTrustFile(path: string): TrustFile {\n\tif (!existsSync(path)) {\n\t\treturn {};\n\t}\n\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(stripBom(readFileSync(path, \"utf-8\")));\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\tthrow new Error(`Failed to read trust store ${path}: ${message}`);\n\t}\n\n\tif (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) {\n\t\tthrow new Error(`Invalid trust store ${path}: expected an object`);\n\t}\n\n\tconst data: TrustFile = {};\n\tfor (const [key, value] of Object.entries(parsed)) {\n\t\tif (value !== true && value !== false && value !== null) {\n\t\t\tthrow new Error(`Invalid trust store ${path}: value for ${JSON.stringify(key)} must be true, false, or null`);\n\t\t}\n\t\tdata[key] = value;\n\t}\n\treturn data;\n}\n\nfunction writeTrustFile(path: string, data: TrustFile): void {\n\tconst sorted: TrustFile = {};\n\tfor (const key of Object.keys(data).sort()) {\n\t\tconst value = data[key];\n\t\tif (value === true || value === false || value === null) {\n\t\t\tsorted[key] = value;\n\t\t}\n\t}\n\tmkdirSync(dirname(path), { recursive: true });\n\twriteFileSync(path, `${JSON.stringify(sorted, null, 2)}\\n`, \"utf-8\");\n}\n\nfunction acquireTrustLockSync(path: string): () => void {\n\tconst trustDir = dirname(path);\n\tmkdirSync(trustDir, { recursive: true });\n\tconst maxAttempts = 10;\n\tconst delayMs = 20;\n\tlet lastError: unknown;\n\n\tfor (let attempt = 1; attempt <= maxAttempts; attempt++) {\n\t\ttry {\n\t\t\treturn lockfile.lockSync(trustDir, { realpath: false, lockfilePath: `${path}.lock` });\n\t\t} catch (error) {\n\t\t\tconst code =\n\t\t\t\ttypeof error === \"object\" && error !== null && \"code\" in error\n\t\t\t\t\t? String((error as { code?: unknown }).code)\n\t\t\t\t\t: undefined;\n\t\t\tif (code !== \"ELOCKED\" || attempt === maxAttempts) {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\tlastError = error;\n\t\t\tconst start = Date.now();\n\t\t\twhile (Date.now() - start < delayMs) {\n\t\t\t\t// Sleep synchronously to avoid changing trust store callers to async.\n\t\t\t}\n\t\t}\n\t}\n\n\tif (lastError instanceof Error) {\n\t\tthrow lastError;\n\t}\n\tthrow new Error(\"Failed to acquire trust store lock\");\n}\n\nfunction withTrustFileLock<T>(path: string, fn: () => T): T {\n\tconst release = acquireTrustLockSync(path);\n\ttry {\n\t\treturn fn();\n\t} finally {\n\t\trelease();\n\t}\n}\n\n/**\n * Returns true when cwd has project-local resources that must be gated by\n * project trust: trust-requiring entries under cwd/.pi, or .agents/skills in\n * cwd or one of its ancestors. Returns false when no such project resources\n * exist. The user/global ~/.agents/skills directory is always treated as a\n * trusted user resource and is ignored here, even when cwd is $HOME.\n */\nexport function hasTrustRequiringProjectResources(cwd: string): boolean {\n\tconst homeDir = canonicalizePath(resolvePath(process.env.HOME || homedir()));\n\tconst userAgentsSkillsDir = join(homeDir, \".agents\", \"skills\");\n\tlet currentDir = canonicalizePath(resolvePath(cwd));\n\n\tconst configDir = join(currentDir, CONFIG_DIR_NAME);\n\tif (TRUST_REQUIRING_PROJECT_CONFIG_RESOURCES.some((entry) => existsSync(join(configDir, entry)))) {\n\t\treturn true;\n\t}\n\n\twhile (true) {\n\t\tconst agentsSkillsDir = join(currentDir, \".agents\", \"skills\");\n\t\tif (agentsSkillsDir !== userAgentsSkillsDir && existsSync(agentsSkillsDir)) {\n\t\t\treturn true;\n\t\t}\n\n\t\tconst parentDir = dirname(currentDir);\n\t\tif (parentDir === currentDir) {\n\t\t\treturn false;\n\t\t}\n\t\tcurrentDir = parentDir;\n\t}\n}\n\nexport class ProjectTrustStore {\n\tprivate trustPath: string;\n\n\tconstructor(agentDir: string) {\n\t\tthis.trustPath = join(resolvePath(agentDir), \"trust.json\");\n\t}\n\n\tget(cwd: string): ProjectTrustDecision {\n\t\treturn this.getEntry(cwd)?.decision ?? null;\n\t}\n\n\tgetEntry(cwd: string): ProjectTrustStoreEntry | null {\n\t\treturn withTrustFileLock(this.trustPath, () => {\n\t\t\tconst data = readTrustFile(this.trustPath);\n\t\t\treturn findNearestTrustEntry(data, cwd);\n\t\t});\n\t}\n\n\tset(cwd: string, decision: ProjectTrustDecision): void {\n\t\tthis.setMany([{ path: cwd, decision }]);\n\t}\n\n\tsetMany(decisions: ProjectTrustUpdate[]): void {\n\t\twithTrustFileLock(this.trustPath, () => {\n\t\t\tconst data = readTrustFile(this.trustPath);\n\t\t\tfor (const { path, decision } of decisions) {\n\t\t\t\tconst key = normalizeCwd(path);\n\t\t\t\tif (decision === null) {\n\t\t\t\t\tdelete data[key];\n\t\t\t\t} else {\n\t\t\t\t\tdata[key] = decision;\n\t\t\t\t}\n\t\t\t}\n\t\t\twriteTrustFile(this.trustPath, data);\n\t\t});\n\t}\n}\n"]}
@@ -0,0 +1,86 @@
1
+ /**
2
+ * AgentRunner — subagente del Ada Intelligence Engine.
3
+ *
4
+ * Un subagente es una sesión del SDK (AgentSessionRuntime via createAgentSession)
5
+ * con: modelo resuelto (spec/tier/fallback), tools configuradas, cwd (base o
6
+ * worktree), instructions opcionales y límites (timeout, retries). El runner
7
+ * captura la respuesta final, el structured output (schema typebox con fallback
8
+ * a extracción de prosa) y el usage real (tokens/coste).
9
+ *
10
+ * La creación de la sesión es inyectable (createSession) para tests con fakes.
11
+ */
12
+ import type { TSchema } from "typebox";
13
+ import type { AgentSession } from "../agent-session.ts";
14
+ import type { ToolDefinition } from "../extensions/types.ts";
15
+ import type { AgentRunOptions, AgentRunResult, AgentUsage, WorkflowErrorCode } from "./types.ts";
16
+ export interface SubagentSession {
17
+ session: AgentSession;
18
+ dispose(): void;
19
+ getUsage(): AgentUsage;
20
+ }
21
+ export type CreateSubagentSession = (options: {
22
+ cwd: string;
23
+ agentDir: string;
24
+ modelSpec?: string;
25
+ tools?: string[];
26
+ customTools?: ToolDefinition[];
27
+ sessionName?: string;
28
+ instructions?: string;
29
+ }) => Promise<SubagentSession>;
30
+ export interface AgentRunnerOptions {
31
+ agentDir: string;
32
+ createSession: CreateSubagentSession;
33
+ /** Limiter compartido del run (concurrency). */
34
+ limiter: <T>(fn: () => Promise<T>) => Promise<T>;
35
+ /** Contador global de agentes del run (maxAgents). */
36
+ agentCounter: {
37
+ count: number;
38
+ };
39
+ /** Techo de agentes por run (`workflows.maxAgentsPerRun`). */
40
+ maxAgents: number;
41
+ retries?: number;
42
+ agentTimeoutMs?: number | null;
43
+ }
44
+ /** Hash de identidad del agente para el journal (prompt+model+phase+schema+stableKey). */
45
+ export declare function agentIdentityHash(options: {
46
+ prompt: string;
47
+ model?: string;
48
+ tier?: string;
49
+ phase?: string;
50
+ stableKey?: string;
51
+ schema?: TSchema | undefined;
52
+ }): string;
53
+ /** Extraer el texto de una respuesta (string o content array). */
54
+ export declare function messageText(content: unknown): string;
55
+ /** Extraer JSON del texto (para structured output fallback). */
56
+ export declare function extractJson(text: string): unknown | undefined;
57
+ /**
58
+ * Allowlist de tools del subagente.
59
+ *
60
+ * Desenreda un bug latente: `options.tools` son tools EXTRA (web_search…) y se
61
+ * pasaban a la vez como `customTools` y como allowlist, de modo que pedir una
62
+ * tool extra ESTRECHABA el permiso en silencio a solo esa — un agente que pedía
63
+ * `web_search` perdía `read`/`bash`/`edit`/`write` sin que nadie lo notara.
64
+ * Ahora las extra se SUMAN a la base, que es lo que el nombre siempre prometió.
65
+ */
66
+ export declare function resolveAllowedTools(options: {
67
+ readOnly?: boolean;
68
+ tools?: Array<{
69
+ name: string;
70
+ }>;
71
+ }): string[];
72
+ export declare class AgentRunner {
73
+ private agentDir;
74
+ private createSession;
75
+ private limiter;
76
+ private agentCounter;
77
+ private maxAgents;
78
+ private retries;
79
+ private agentTimeoutMs;
80
+ constructor(options: AgentRunnerOptions);
81
+ run<T = unknown>(options: AgentRunOptions): Promise<AgentRunResult<T> | null>;
82
+ private runOnce;
83
+ }
84
+ /** Tipos re-exportados para el index. */
85
+ export type { WorkflowErrorCode };
86
+ //# sourceMappingURL=agent-runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-runner.d.ts","sourceRoot":"","sources":["../../../src/core/workflows/agent-runner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,KAAK,EAAE,YAAY,EAAqB,MAAM,qBAAqB,CAAC;AAC3E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAIjG,MAAM,WAAW,eAAe;IAC/B,OAAO,EAAE,YAAY,CAAC;IACtB,OAAO,IAAI,IAAI,CAAC;IAChB,QAAQ,IAAI,UAAU,CAAC;CACvB;AAED,MAAM,MAAM,qBAAqB,GAAG,CAAC,OAAO,EAAE;IAC7C,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,WAAW,CAAC,EAAE,cAAc,EAAE,CAAC;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;CACtB,KAAK,OAAO,CAAC,eAAe,CAAC,CAAC;AAE/B,MAAM,WAAW,kBAAkB;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,qBAAqB,CAAC;IACrC,gDAAgD;IAChD,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;IACjD,sDAAsD;IACtD,YAAY,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAChC,8DAA8D;IAC9D,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,0FAA0F;AAC1F,wBAAgB,iBAAiB,CAAC,OAAO,EAAE;IAC1C,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CAC7B,GAAG,MAAM,CAUT;AAED,kEAAkE;AAClE,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAQpD;AAED,gEAAgE;AAChE,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAa7D;AAOD;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,GAAG,MAAM,EAAE,CAI9G;AAED,qBAAa,WAAW;IACvB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,aAAa,CAAwB;IAC7C,OAAO,CAAC,OAAO,CAAgC;IAC/C,OAAO,CAAC,YAAY,CAAqC;IACzD,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,cAAc,CAAgB;IAEtC,YAAY,OAAO,EAAE,kBAAkB,EAQtC;IAEK,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CA4BlF;YAEa,OAAO;CAsGrB;AAUD,yCAAyC;AACzC,YAAY,EAAE,iBAAiB,EAAE,CAAC","sourcesContent":["/**\n * AgentRunner — subagente del Ada Intelligence Engine.\n *\n * Un subagente es una sesión del SDK (AgentSessionRuntime via createAgentSession)\n * con: modelo resuelto (spec/tier/fallback), tools configuradas, cwd (base o\n * worktree), instructions opcionales y límites (timeout, retries). El runner\n * captura la respuesta final, el structured output (schema typebox con fallback\n * a extracción de prosa) y el usage real (tokens/coste).\n *\n * La creación de la sesión es inyectable (createSession) para tests con fakes.\n */\n\nimport { createHash } from \"node:crypto\";\nimport type { TextContent } from \"@earendil-works/pi-ai\";\nimport type { TSchema } from \"typebox\";\nimport type { AgentSession, AgentSessionEvent } from \"../agent-session.ts\";\nimport type { ToolDefinition } from \"../extensions/types.ts\";\nimport type { AgentRunOptions, AgentRunResult, AgentUsage, WorkflowErrorCode } from \"./types.ts\";\nimport { WorkflowError } from \"./types.ts\";\nimport { createWorktree, finalizeWorktree, type Worktree } from \"./worktree.ts\";\n\nexport interface SubagentSession {\n\tsession: AgentSession;\n\tdispose(): void;\n\tgetUsage(): AgentUsage;\n}\n\nexport type CreateSubagentSession = (options: {\n\tcwd: string;\n\tagentDir: string;\n\tmodelSpec?: string;\n\ttools?: string[];\n\tcustomTools?: ToolDefinition[];\n\tsessionName?: string;\n\tinstructions?: string;\n}) => Promise<SubagentSession>;\n\nexport interface AgentRunnerOptions {\n\tagentDir: string;\n\tcreateSession: CreateSubagentSession;\n\t/** Limiter compartido del run (concurrency). */\n\tlimiter: <T>(fn: () => Promise<T>) => Promise<T>;\n\t/** Contador global de agentes del run (maxAgents). */\n\tagentCounter: { count: number };\n\t/** Techo de agentes por run (`workflows.maxAgentsPerRun`). */\n\tmaxAgents: number;\n\tretries?: number;\n\tagentTimeoutMs?: number | null;\n}\n\n/** Hash de identidad del agente para el journal (prompt+model+phase+schema+stableKey). */\nexport function agentIdentityHash(options: {\n\tprompt: string;\n\tmodel?: string;\n\ttier?: string;\n\tphase?: string;\n\tstableKey?: string;\n\tschema?: TSchema | undefined;\n}): string {\n\tconst canonical = JSON.stringify({\n\t\tprompt: options.prompt,\n\t\tmodel: options.model ?? null,\n\t\ttier: options.tier ?? null,\n\t\tphase: options.phase ?? null,\n\t\tstableKey: options.stableKey ?? null,\n\t\tschema: options.schema ? JSON.stringify(options.schema) : null,\n\t});\n\treturn createHash(\"sha256\").update(canonical).digest(\"hex\");\n}\n\n/** Extraer el texto de una respuesta (string o content array). */\nexport function messageText(content: unknown): string {\n\tif (typeof content === \"string\") return content;\n\tif (!Array.isArray(content)) return \"\";\n\treturn content\n\t\t.filter((b): b is TextContent => typeof b === \"object\" && b !== null && (b as { type?: string }).type === \"text\")\n\t\t.map((b) => b.text ?? \"\")\n\t\t.join(\"\\n\")\n\t\t.trim();\n}\n\n/** Extraer JSON del texto (para structured output fallback). */\nexport function extractJson(text: string): unknown | undefined {\n\tconst cleaned = text\n\t\t.replace(/```json\\s*/g, \"\")\n\t\t.replace(/```/g, \"\")\n\t\t.trim();\n\tconst start = cleaned.indexOf(\"{\");\n\tconst end = cleaned.lastIndexOf(\"}\");\n\tif (start === -1 || end === -1) return undefined;\n\ttry {\n\t\treturn JSON.parse(cleaned.slice(start, end + 1));\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\n/** Tools por defecto de un subagente (espejo de sdk.ts:263). */\nconst SUBAGENT_DEFAULT_TOOLS = [\"read\", \"bash\", \"edit\", \"write\"];\n/** Mínimo privilegio: leer y buscar, nada de escribir ni ejecutar. */\nconst SUBAGENT_READONLY_TOOLS = [\"read\", \"grep\", \"find\", \"ls\"];\n\n/**\n * Allowlist de tools del subagente.\n *\n * Desenreda un bug latente: `options.tools` son tools EXTRA (web_search…) y se\n * pasaban a la vez como `customTools` y como allowlist, de modo que pedir una\n * tool extra ESTRECHABA el permiso en silencio a solo esa — un agente que pedía\n * `web_search` perdía `read`/`bash`/`edit`/`write` sin que nadie lo notara.\n * Ahora las extra se SUMAN a la base, que es lo que el nombre siempre prometió.\n */\nexport function resolveAllowedTools(options: { readOnly?: boolean; tools?: Array<{ name: string }> }): string[] {\n\tconst base = options.readOnly ? SUBAGENT_READONLY_TOOLS : SUBAGENT_DEFAULT_TOOLS;\n\tconst extras = (options.tools ?? []).map((t) => t.name);\n\treturn [...new Set([...base, ...extras])];\n}\n\nexport class AgentRunner {\n\tprivate agentDir: string;\n\tprivate createSession: CreateSubagentSession;\n\tprivate limiter: AgentRunnerOptions[\"limiter\"];\n\tprivate agentCounter: AgentRunnerOptions[\"agentCounter\"];\n\tprivate maxAgents: number;\n\tprivate retries: number;\n\tprivate agentTimeoutMs: number | null;\n\n\tconstructor(options: AgentRunnerOptions) {\n\t\tthis.agentDir = options.agentDir;\n\t\tthis.createSession = options.createSession;\n\t\tthis.limiter = options.limiter;\n\t\tthis.agentCounter = options.agentCounter;\n\t\tthis.maxAgents = options.maxAgents;\n\t\tthis.retries = options.retries ?? 3;\n\t\tthis.agentTimeoutMs = options.agentTimeoutMs ?? null;\n\t}\n\n\tasync run<T = unknown>(options: AgentRunOptions): Promise<AgentRunResult<T> | null> {\n\t\treturn this.limiter(async () => {\n\t\t\tif (this.agentCounter.count >= this.maxAgents) {\n\t\t\t\tthrow new WorkflowError(\n\t\t\t\t\t\"WORKFLOW_MAX_AGENTS\",\n\t\t\t\t\t`Límite de agentes del run alcanzado (${this.maxAgents}). Súbelo con el ajuste workflows.maxAgentsPerRun.`,\n\t\t\t\t\t{ recoverable: false },\n\t\t\t\t);\n\t\t\t}\n\t\t\tthis.agentCounter.count++;\n\n\t\t\tlet attempt = 0;\n\t\t\tlet lastError: Error | undefined;\n\t\t\tfor (; attempt <= this.retries; attempt++) {\n\t\t\t\tconst signal = options.signal;\n\t\t\t\tif (signal?.aborted) return null;\n\t\t\t\ttry {\n\t\t\t\t\treturn await this.runOnce<T>(options, signal);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (signal?.aborted) return null;\n\t\t\t\t\tif (isAbortError(error) || isTimeoutError(error)) throw error;\n\t\t\t\t\tlastError = error instanceof Error ? error : new Error(String(error));\n\t\t\t\t\tif (attempt >= this.retries) break;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (lastError) throw lastError;\n\t\t\treturn null;\n\t\t});\n\t}\n\n\tprivate async runOnce<T>(options: AgentRunOptions, signal?: AbortSignal): Promise<AgentRunResult<T> | null> {\n\t\t// Timeout combinado: el del agente + el del run.\n\t\tconst timeoutMs = options.timeoutMs ?? this.agentTimeoutMs;\n\t\tlet timeoutTimer: ReturnType<typeof setTimeout> | undefined;\n\t\tconst timeout = new Promise<never>((_resolve, reject) => {\n\t\t\tif (timeoutMs === null) return;\n\t\t\ttimeoutTimer = setTimeout(() => {\n\t\t\t\treject(\n\t\t\t\t\tnew WorkflowError(\"WORKFLOW_AGENT_TIMEOUT\", `Agent timed out after ${timeoutMs}ms`, {\n\t\t\t\t\t\trecoverable: false,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t}, timeoutMs);\n\t\t});\n\n\t\tconst baseCwd = options.cwd ?? process.cwd();\n\t\t// Aislamiento git: los agentes con escritura que corren en paralelo\n\t\t// editaban el MISMO checkout y se pisaban en silencio. El nombre es\n\t\t// determinista (isolationKey = runId:callIndex) para que un resume\n\t\t// reencuentre el mismo worktree. Fuera de un repo git hace no-op.\n\t\tlet worktree: Worktree | null = null;\n\t\tlet finalized: { branch?: string; kept: boolean } | undefined;\n\t\tconst worktreeMessage = `ada: ${options.label ?? options.isolationKey ?? \"agent\"}`;\n\t\tif (options.isolation === \"worktree\") {\n\t\t\tworktree = await createWorktree(baseCwd, options.isolationKey ?? options.label ?? \"agent\");\n\t\t}\n\n\t\tlet subagent: SubagentSession | null = null;\n\t\ttry {\n\t\t\tsubagent = await this.createSession({\n\t\t\t\tcwd: worktree?.cwd ?? baseCwd,\n\t\t\t\tagentDir: this.agentDir,\n\t\t\t\tmodelSpec: options.model ?? (options.tier ? `tier:${options.tier}` : undefined),\n\t\t\t\ttools: resolveAllowedTools(options),\n\t\t\t\tcustomTools: options.tools,\n\t\t\t\tsessionName: options.label ? `workflow:${options.label}` : undefined,\n\t\t\t\tinstructions: options.instructions,\n\t\t\t});\n\t\t\tconst session = subagent.session;\n\n\t\t\tconst lastAssistantText: string[] = [];\n\t\t\tconst unsubscribe = session.subscribe((event: AgentSessionEvent) => {\n\t\t\t\tif (event.type === \"message_end\" && event.message.role === \"assistant\") {\n\t\t\t\t\tconst text = messageText(event.message.content);\n\t\t\t\t\tif (text) lastAssistantText.push(text);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\ttry {\n\t\t\t\tawait Promise.race([session.sendUserMessage(options.prompt), timeout]);\n\t\t\t\tawait Promise.race([session.waitForIdle(), timeout]);\n\t\t\t} finally {\n\t\t\t\tunsubscribe();\n\t\t\t}\n\n\t\t\tif (signal?.aborted) return null;\n\n\t\t\tconst text = lastAssistantText.length > 0 ? lastAssistantText[lastAssistantText.length - 1] : \"\";\n\t\t\tlet result: T | null = null;\n\t\t\tlet _origin: \"structured\" | \"recovered\" = \"structured\";\n\n\t\t\tif (options.schema) {\n\t\t\t\tconst parsed = extractJson(text);\n\t\t\t\tif (parsed !== undefined) {\n\t\t\t\t\tresult = parsed as T;\n\t\t\t\t} else {\n\t\t\t\t\t_origin = \"recovered\";\n\t\t\t\t\t// Fallback: devolver la prosa (el caller decide si sirve).\n\t\t\t\t\tresult = text as unknown as T;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tresult = (text.length > 0 ? text : null) as unknown as T;\n\t\t\t}\n\n\t\t\t// Consolidar el worktree ANTES de devolver: si solo lo retirásemos, los\n\t\t\t// cambios sin commitear del agente se perderían y el aislamiento no\n\t\t\t// habría servido de nada. La rama sobrevive para que un humano la\n\t\t\t// mergee; no hay auto-merge a propósito.\n\t\t\tif (worktree && !finalized) {\n\t\t\t\tfinalized = await finalizeWorktree(worktree, worktreeMessage);\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tresult,\n\t\t\t\ttext,\n\t\t\t\tusage: subagent.getUsage(),\n\t\t\t\tsessionId: (\n\t\t\t\t\tsession as { sessionManager?: { getSessionId?: () => string } }\n\t\t\t\t).sessionManager?.getSessionId?.(),\n\t\t\t\tworktreeBranch: finalized?.branch,\n\t\t\t} as AgentRunResult<T>;\n\t\t} finally {\n\t\t\tif (timeoutTimer) clearTimeout(timeoutTimer);\n\t\t\tsubagent?.dispose();\n\t\t\t// Camino de error/abort/timeout: el return no llegó a consolidar, pero\n\t\t\t// el trabajo parcial del agente también merece sobrevivir para poder\n\t\t\t// inspeccionarlo — y hay que soltar el worktree igualmente.\n\t\t\tif (worktree && !finalized) {\n\t\t\t\tfinalized = await finalizeWorktree(worktree, worktreeMessage);\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction isAbortError(error: unknown): boolean {\n\treturn error instanceof Error && error.name === \"AbortError\";\n}\n\nfunction isTimeoutError(error: unknown): boolean {\n\treturn error instanceof WorkflowError && error.code === \"WORKFLOW_AGENT_TIMEOUT\";\n}\n\n/** Tipos re-exportados para el index. */\nexport type { WorkflowErrorCode };\n"]}
@@ -0,0 +1,225 @@
1
+ /**
2
+ * AgentRunner — subagente del Ada Intelligence Engine.
3
+ *
4
+ * Un subagente es una sesión del SDK (AgentSessionRuntime via createAgentSession)
5
+ * con: modelo resuelto (spec/tier/fallback), tools configuradas, cwd (base o
6
+ * worktree), instructions opcionales y límites (timeout, retries). El runner
7
+ * captura la respuesta final, el structured output (schema typebox con fallback
8
+ * a extracción de prosa) y el usage real (tokens/coste).
9
+ *
10
+ * La creación de la sesión es inyectable (createSession) para tests con fakes.
11
+ */
12
+ import { createHash } from "node:crypto";
13
+ import { WorkflowError } from "./types.js";
14
+ import { createWorktree, finalizeWorktree } from "./worktree.js";
15
+ /** Hash de identidad del agente para el journal (prompt+model+phase+schema+stableKey). */
16
+ export function agentIdentityHash(options) {
17
+ const canonical = JSON.stringify({
18
+ prompt: options.prompt,
19
+ model: options.model ?? null,
20
+ tier: options.tier ?? null,
21
+ phase: options.phase ?? null,
22
+ stableKey: options.stableKey ?? null,
23
+ schema: options.schema ? JSON.stringify(options.schema) : null,
24
+ });
25
+ return createHash("sha256").update(canonical).digest("hex");
26
+ }
27
+ /** Extraer el texto de una respuesta (string o content array). */
28
+ export function messageText(content) {
29
+ if (typeof content === "string")
30
+ return content;
31
+ if (!Array.isArray(content))
32
+ return "";
33
+ return content
34
+ .filter((b) => typeof b === "object" && b !== null && b.type === "text")
35
+ .map((b) => b.text ?? "")
36
+ .join("\n")
37
+ .trim();
38
+ }
39
+ /** Extraer JSON del texto (para structured output fallback). */
40
+ export function extractJson(text) {
41
+ const cleaned = text
42
+ .replace(/```json\s*/g, "")
43
+ .replace(/```/g, "")
44
+ .trim();
45
+ const start = cleaned.indexOf("{");
46
+ const end = cleaned.lastIndexOf("}");
47
+ if (start === -1 || end === -1)
48
+ return undefined;
49
+ try {
50
+ return JSON.parse(cleaned.slice(start, end + 1));
51
+ }
52
+ catch {
53
+ return undefined;
54
+ }
55
+ }
56
+ /** Tools por defecto de un subagente (espejo de sdk.ts:263). */
57
+ const SUBAGENT_DEFAULT_TOOLS = ["read", "bash", "edit", "write"];
58
+ /** Mínimo privilegio: leer y buscar, nada de escribir ni ejecutar. */
59
+ const SUBAGENT_READONLY_TOOLS = ["read", "grep", "find", "ls"];
60
+ /**
61
+ * Allowlist de tools del subagente.
62
+ *
63
+ * Desenreda un bug latente: `options.tools` son tools EXTRA (web_search…) y se
64
+ * pasaban a la vez como `customTools` y como allowlist, de modo que pedir una
65
+ * tool extra ESTRECHABA el permiso en silencio a solo esa — un agente que pedía
66
+ * `web_search` perdía `read`/`bash`/`edit`/`write` sin que nadie lo notara.
67
+ * Ahora las extra se SUMAN a la base, que es lo que el nombre siempre prometió.
68
+ */
69
+ export function resolveAllowedTools(options) {
70
+ const base = options.readOnly ? SUBAGENT_READONLY_TOOLS : SUBAGENT_DEFAULT_TOOLS;
71
+ const extras = (options.tools ?? []).map((t) => t.name);
72
+ return [...new Set([...base, ...extras])];
73
+ }
74
+ export class AgentRunner {
75
+ agentDir;
76
+ createSession;
77
+ limiter;
78
+ agentCounter;
79
+ maxAgents;
80
+ retries;
81
+ agentTimeoutMs;
82
+ constructor(options) {
83
+ this.agentDir = options.agentDir;
84
+ this.createSession = options.createSession;
85
+ this.limiter = options.limiter;
86
+ this.agentCounter = options.agentCounter;
87
+ this.maxAgents = options.maxAgents;
88
+ this.retries = options.retries ?? 3;
89
+ this.agentTimeoutMs = options.agentTimeoutMs ?? null;
90
+ }
91
+ async run(options) {
92
+ return this.limiter(async () => {
93
+ if (this.agentCounter.count >= this.maxAgents) {
94
+ throw new WorkflowError("WORKFLOW_MAX_AGENTS", `Límite de agentes del run alcanzado (${this.maxAgents}). Súbelo con el ajuste workflows.maxAgentsPerRun.`, { recoverable: false });
95
+ }
96
+ this.agentCounter.count++;
97
+ let attempt = 0;
98
+ let lastError;
99
+ for (; attempt <= this.retries; attempt++) {
100
+ const signal = options.signal;
101
+ if (signal?.aborted)
102
+ return null;
103
+ try {
104
+ return await this.runOnce(options, signal);
105
+ }
106
+ catch (error) {
107
+ if (signal?.aborted)
108
+ return null;
109
+ if (isAbortError(error) || isTimeoutError(error))
110
+ throw error;
111
+ lastError = error instanceof Error ? error : new Error(String(error));
112
+ if (attempt >= this.retries)
113
+ break;
114
+ }
115
+ }
116
+ if (lastError)
117
+ throw lastError;
118
+ return null;
119
+ });
120
+ }
121
+ async runOnce(options, signal) {
122
+ // Timeout combinado: el del agente + el del run.
123
+ const timeoutMs = options.timeoutMs ?? this.agentTimeoutMs;
124
+ let timeoutTimer;
125
+ const timeout = new Promise((_resolve, reject) => {
126
+ if (timeoutMs === null)
127
+ return;
128
+ timeoutTimer = setTimeout(() => {
129
+ reject(new WorkflowError("WORKFLOW_AGENT_TIMEOUT", `Agent timed out after ${timeoutMs}ms`, {
130
+ recoverable: false,
131
+ }));
132
+ }, timeoutMs);
133
+ });
134
+ const baseCwd = options.cwd ?? process.cwd();
135
+ // Aislamiento git: los agentes con escritura que corren en paralelo
136
+ // editaban el MISMO checkout y se pisaban en silencio. El nombre es
137
+ // determinista (isolationKey = runId:callIndex) para que un resume
138
+ // reencuentre el mismo worktree. Fuera de un repo git hace no-op.
139
+ let worktree = null;
140
+ let finalized;
141
+ const worktreeMessage = `ada: ${options.label ?? options.isolationKey ?? "agent"}`;
142
+ if (options.isolation === "worktree") {
143
+ worktree = await createWorktree(baseCwd, options.isolationKey ?? options.label ?? "agent");
144
+ }
145
+ let subagent = null;
146
+ try {
147
+ subagent = await this.createSession({
148
+ cwd: worktree?.cwd ?? baseCwd,
149
+ agentDir: this.agentDir,
150
+ modelSpec: options.model ?? (options.tier ? `tier:${options.tier}` : undefined),
151
+ tools: resolveAllowedTools(options),
152
+ customTools: options.tools,
153
+ sessionName: options.label ? `workflow:${options.label}` : undefined,
154
+ instructions: options.instructions,
155
+ });
156
+ const session = subagent.session;
157
+ const lastAssistantText = [];
158
+ const unsubscribe = session.subscribe((event) => {
159
+ if (event.type === "message_end" && event.message.role === "assistant") {
160
+ const text = messageText(event.message.content);
161
+ if (text)
162
+ lastAssistantText.push(text);
163
+ }
164
+ });
165
+ try {
166
+ await Promise.race([session.sendUserMessage(options.prompt), timeout]);
167
+ await Promise.race([session.waitForIdle(), timeout]);
168
+ }
169
+ finally {
170
+ unsubscribe();
171
+ }
172
+ if (signal?.aborted)
173
+ return null;
174
+ const text = lastAssistantText.length > 0 ? lastAssistantText[lastAssistantText.length - 1] : "";
175
+ let result = null;
176
+ let _origin = "structured";
177
+ if (options.schema) {
178
+ const parsed = extractJson(text);
179
+ if (parsed !== undefined) {
180
+ result = parsed;
181
+ }
182
+ else {
183
+ _origin = "recovered";
184
+ // Fallback: devolver la prosa (el caller decide si sirve).
185
+ result = text;
186
+ }
187
+ }
188
+ else {
189
+ result = (text.length > 0 ? text : null);
190
+ }
191
+ // Consolidar el worktree ANTES de devolver: si solo lo retirásemos, los
192
+ // cambios sin commitear del agente se perderían y el aislamiento no
193
+ // habría servido de nada. La rama sobrevive para que un humano la
194
+ // mergee; no hay auto-merge a propósito.
195
+ if (worktree && !finalized) {
196
+ finalized = await finalizeWorktree(worktree, worktreeMessage);
197
+ }
198
+ return {
199
+ result,
200
+ text,
201
+ usage: subagent.getUsage(),
202
+ sessionId: session.sessionManager?.getSessionId?.(),
203
+ worktreeBranch: finalized?.branch,
204
+ };
205
+ }
206
+ finally {
207
+ if (timeoutTimer)
208
+ clearTimeout(timeoutTimer);
209
+ subagent?.dispose();
210
+ // Camino de error/abort/timeout: el return no llegó a consolidar, pero
211
+ // el trabajo parcial del agente también merece sobrevivir para poder
212
+ // inspeccionarlo — y hay que soltar el worktree igualmente.
213
+ if (worktree && !finalized) {
214
+ finalized = await finalizeWorktree(worktree, worktreeMessage);
215
+ }
216
+ }
217
+ }
218
+ }
219
+ function isAbortError(error) {
220
+ return error instanceof Error && error.name === "AbortError";
221
+ }
222
+ function isTimeoutError(error) {
223
+ return error instanceof WorkflowError && error.code === "WORKFLOW_AGENT_TIMEOUT";
224
+ }
225
+ //# sourceMappingURL=agent-runner.js.map