@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
@@ -0,0 +1,397 @@
1
+ /**
2
+ * Ada Intelligence Engine — Goal Engine reducer (puro).
3
+ *
4
+ * Reducer determinista: todas las transiciones de estado pasan por aquí.
5
+ * Reglas de seguridad integradas:
6
+ * - El goal se rota (nuevo id) al editar/reanudar → un turno viejo (id viejo)
7
+ * no puede completar el goal nuevo (guards anti-duplicados).
8
+ * - Las fases TDD son un orden FIJO (código, no elección del modelo).
9
+ * - `goal_complete` exige evidencia citada y juez con verdict done.
10
+ * - Un turno vacío/idéntico incrementa repeatedTurns → pause a la tolerancia.
11
+ */
12
+ export const TDD_PHASES = ["analysis", "bootstrap", "red", "green", "refactor", "verify", "done"];
13
+ export function nextPhase(phase) {
14
+ const i = TDD_PHASES.indexOf(phase);
15
+ return i >= 0 && i < TDD_PHASES.length - 1 ? TDD_PHASES[i + 1] : phase;
16
+ }
17
+ /** Crea un goal en estado setup (contrato primero, sin trabajo). */
18
+ export function createGoalState(input) {
19
+ return {
20
+ id: input.id ?? `goal-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 7)}`,
21
+ goal: input.goal,
22
+ sessionId: input.sessionId,
23
+ phase: "analysis",
24
+ status: "setup",
25
+ doneCriteria: input.doneCriteria,
26
+ verifyCommand: input.verifyCommand,
27
+ tasks: [],
28
+ iteration: 1,
29
+ iterations: [],
30
+ evidence: [],
31
+ judge: { model: null },
32
+ turnsUsed: 0,
33
+ tokensUsed: 0,
34
+ costUsed: 0,
35
+ repeatedTurns: 0,
36
+ lastAgentSummary: "",
37
+ createdAt: input.now ?? new Date().toISOString(),
38
+ updatedAt: input.now ?? new Date().toISOString(),
39
+ };
40
+ }
41
+ function taskFrom(action, tasks) {
42
+ return tasks.find((t) => t.id === action.taskId);
43
+ }
44
+ /** Reduce una acción sobre el estado. Devuelve nuevo estado + eventos derivados. */
45
+ export function reduceGoal(state, action, _frenos = {
46
+ maxTurns: 25,
47
+ repeatTolerance: 3,
48
+ stopFile: null,
49
+ tokenBudget: null,
50
+ costBudget: null,
51
+ askBefore: [],
52
+ }) {
53
+ const events = [];
54
+ const stopLoop = false;
55
+ switch (action.type) {
56
+ case "goal_approve": {
57
+ if (state.status !== "setup")
58
+ return { state, events, stopLoop };
59
+ return {
60
+ state: { ...state, status: "active", updatedAt: now() },
61
+ events: [{ phase: "analysis" }],
62
+ stopLoop,
63
+ };
64
+ }
65
+ case "goal_task_add": {
66
+ // TODO personalizado: añade una tarea sin reemplazar el plan.
67
+ const title = action.title.trim();
68
+ if (!title)
69
+ return { state, events, stopLoop };
70
+ const newTask = {
71
+ id: `task-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 6)}`,
72
+ title,
73
+ status: "pending",
74
+ };
75
+ return {
76
+ state: { ...state, tasks: [...state.tasks, newTask], updatedAt: now() },
77
+ events,
78
+ stopLoop,
79
+ };
80
+ }
81
+ case "goal_tasks": {
82
+ // Solo planificar en planning/active; reemplaza el plan.
83
+ if (state.status !== "active" && state.status !== "planning")
84
+ return { state, events, stopLoop };
85
+ return {
86
+ state: { ...state, tasks: action.tasks, status: "active", updatedAt: now() },
87
+ events,
88
+ stopLoop,
89
+ };
90
+ }
91
+ case "goal_task_launched": {
92
+ // El workflow dinámico de la sub-tarea está en marcha (un turno gastado).
93
+ return {
94
+ state: {
95
+ ...state,
96
+ tasks: state.tasks.map((t) => t.id === action.taskId
97
+ ? { ...t, status: "running", workflowRunId: action.workflowRunId }
98
+ : t),
99
+ turnsUsed: state.turnsUsed + 1,
100
+ updatedAt: now(),
101
+ },
102
+ events,
103
+ stopLoop,
104
+ };
105
+ }
106
+ case "goal_task_result": {
107
+ // El workflow de la sub-tarea terminó (done/failed) con resumen.
108
+ return {
109
+ state: {
110
+ ...state,
111
+ tasks: state.tasks.map((t) => t.id === action.taskId
112
+ ? { ...t, status: action.status, resultSummary: action.summary ?? t.resultSummary }
113
+ : t),
114
+ updatedAt: now(),
115
+ },
116
+ events,
117
+ stopLoop,
118
+ };
119
+ }
120
+ case "goal_replan": {
121
+ // P1: re-planificación completa. Nueva iteración, nuevo plan,
122
+ // historial anexado. Solo si el contrato está aprobado y el plan
123
+ // cambia materialmente (o no hay plan).
124
+ const clean = action.tasks
125
+ .filter((t) => t.title?.trim())
126
+ .map((t, i) => ({
127
+ id: `task-${Date.now().toString(36)}-${i}-${Math.random().toString(36).slice(2, 5)}`,
128
+ title: t.title.trim(),
129
+ status: "pending",
130
+ }));
131
+ const samePlan = state.tasks.length === clean.length &&
132
+ state.tasks.length > 0 &&
133
+ state.tasks.every((t, i) => t.title.trim() === clean[i]?.title);
134
+ // Sin cambio real del plan → no iterar (evita loops vacíos).
135
+ if (samePlan)
136
+ return { state, events, stopLoop: true };
137
+ const record = {
138
+ iteration: state.iteration,
139
+ plan: state.tasks.map((t) => ({ ...t })),
140
+ verdict: state.judge.lastVerdict,
141
+ reason: state.judge.lastReason ?? state.replanRationale,
142
+ replanRationale: action.rationale,
143
+ tokensUsed: state.tokensUsed,
144
+ costUsed: state.costUsed,
145
+ timestamp: now(),
146
+ };
147
+ return {
148
+ state: {
149
+ ...state,
150
+ tasks: clean,
151
+ iteration: state.iteration + 1,
152
+ iterations: [...state.iterations, record],
153
+ replanRationale: action.rationale,
154
+ repeatedTurns: 0, // plan nuevo → reset del repeat detector
155
+ updatedAt: now(),
156
+ },
157
+ events: [{ replan: { iteration: state.iteration + 1, tasks: clean } }],
158
+ stopLoop,
159
+ };
160
+ }
161
+ case "goal_task_remove": {
162
+ // P2: quitar una sub-tarea (no ejecutada).
163
+ const target = state.tasks.find((t) => t.id === action.taskId);
164
+ // No se puede quitar una sub-tarea con workflow en marcha aquí
165
+ // (el manager la aborta primero vía goal_task_result).
166
+ if (!target || target.status === "running")
167
+ return { state, events, stopLoop };
168
+ return {
169
+ state: {
170
+ ...state,
171
+ tasks: state.tasks.filter((t) => t.id !== action.taskId),
172
+ updatedAt: now(),
173
+ },
174
+ events: [{ tasksChanged: state.tasks.filter((t) => t.id !== action.taskId) }],
175
+ stopLoop,
176
+ };
177
+ }
178
+ case "goal_task_move": {
179
+ // P2: reordenar (arriba/abajo) en cualquier fase.
180
+ const idx = state.tasks.findIndex((t) => t.id === action.taskId);
181
+ if (idx === -1)
182
+ return { state, events, stopLoop };
183
+ const target = idx + (action.dir === "up" ? -1 : 1);
184
+ if (target < 0 || target >= state.tasks.length)
185
+ return { state, events, stopLoop };
186
+ const tasks = [...state.tasks];
187
+ [tasks[idx], tasks[target]] = [tasks[target], tasks[idx]];
188
+ return {
189
+ state: { ...state, tasks, updatedAt: now() },
190
+ events: [{ tasksChanged: tasks }],
191
+ stopLoop,
192
+ };
193
+ }
194
+ case "goal_task_update": {
195
+ const task = taskFrom(action, state.tasks);
196
+ if (!task)
197
+ return { state, events, stopLoop };
198
+ const tasks = state.tasks.map((t) => (t.id === action.taskId ? { ...t, status: action.status } : t));
199
+ return {
200
+ state: { ...state, tasks, updatedAt: now() },
201
+ events,
202
+ stopLoop,
203
+ };
204
+ }
205
+ case "goal_phase": {
206
+ // Orden fijo TDD: solo avanzar a la siguiente fase.
207
+ if (action.phase !== nextPhase(state.phase))
208
+ return { state, events, stopLoop };
209
+ return {
210
+ state: { ...state, phase: action.phase, updatedAt: now() },
211
+ events: [{ phase: action.phase }],
212
+ stopLoop,
213
+ };
214
+ }
215
+ case "goal_agent_turn": {
216
+ // El turno del agente: incrementa contadores, detecta repetición.
217
+ const summary = action.summary ?? "";
218
+ const repeated = summary.trim().length === 0 || summary === state.lastAgentSummary;
219
+ const repeatedTurns = repeated ? state.repeatedTurns + 1 : 0;
220
+ const turnsUsed = state.turnsUsed + 1;
221
+ let next = {
222
+ ...state,
223
+ turnsUsed,
224
+ repeatedTurns,
225
+ lastAgentSummary: summary,
226
+ tokensUsed: state.tokensUsed + (action.tokens ?? 0),
227
+ costUsed: state.costUsed + (action.cost ?? 0),
228
+ updatedAt: now(),
229
+ };
230
+ if (action.evidence?.length) {
231
+ // No duplicar evidencia idéntica.
232
+ const existing = new Set(state.evidence.map((e) => `${e.claim}|${e.source}`));
233
+ const fresh = action.evidence.filter((e) => !existing.has(`${e.claim}|${e.source}`));
234
+ next = { ...next, evidence: [...state.evidence, ...fresh] };
235
+ }
236
+ if (action.tasks?.length) {
237
+ const tasks = next.tasks.map((t) => {
238
+ const u = action.tasks.find((x) => x.taskId === t.id);
239
+ return u ? { ...t, status: u.status } : t;
240
+ });
241
+ next = { ...next, tasks };
242
+ }
243
+ return { state: next, events, stopLoop };
244
+ }
245
+ case "goal_pause": {
246
+ return {
247
+ state: {
248
+ ...state,
249
+ status: "paused",
250
+ waiting: { reason: action.reason ?? "pausado por el usuario" },
251
+ updatedAt: now(),
252
+ },
253
+ events,
254
+ stopLoop: true,
255
+ };
256
+ }
257
+ case "goal_resume": {
258
+ if (state.status !== "paused")
259
+ return { state, events, stopLoop };
260
+ return {
261
+ state: { ...state, status: "active", waiting: undefined, repeatedTurns: 0, updatedAt: now() },
262
+ events,
263
+ stopLoop,
264
+ };
265
+ }
266
+ case "goal_blocked": {
267
+ return {
268
+ state: { ...state, status: "blocked", waiting: { reason: action.reason }, updatedAt: now() },
269
+ events,
270
+ stopLoop: true,
271
+ };
272
+ }
273
+ case "goal_wait": {
274
+ return {
275
+ state: {
276
+ ...state,
277
+ status: "paused",
278
+ waiting: { reason: action.reason, resumeAfterMs: action.resumeAfterMs },
279
+ updatedAt: now(),
280
+ },
281
+ events,
282
+ stopLoop: true,
283
+ };
284
+ }
285
+ case "goal_questions": {
286
+ return {
287
+ state: {
288
+ ...state,
289
+ status: "blocked",
290
+ pendingQuestions: action.questions,
291
+ waiting: { reason: action.reason },
292
+ updatedAt: now(),
293
+ },
294
+ events,
295
+ stopLoop: true,
296
+ };
297
+ }
298
+ case "goal_answers": {
299
+ // Las respuestas limpian el bloqueo y reactivan.
300
+ return {
301
+ state: { ...state, status: "active", pendingQuestions: undefined, waiting: undefined, updatedAt: now() },
302
+ events,
303
+ stopLoop,
304
+ };
305
+ }
306
+ case "goal_usage_limited": {
307
+ return {
308
+ state: {
309
+ ...state,
310
+ status: "usage_limited",
311
+ waiting: { reason: "Presupuesto de tokens agotado" },
312
+ updatedAt: now(),
313
+ },
314
+ events,
315
+ stopLoop: true,
316
+ };
317
+ }
318
+ case "goal_budget_limited": {
319
+ return {
320
+ state: {
321
+ ...state,
322
+ status: "budget_limited",
323
+ waiting: { reason: "Presupuesto de coste agotado" },
324
+ updatedAt: now(),
325
+ },
326
+ events,
327
+ stopLoop: true,
328
+ };
329
+ }
330
+ case "goal_judge": {
331
+ // Al veredictar se anexa la iteración actual al historial (P3):
332
+ // veredicto + razón en el registro de la iteración en curso.
333
+ return {
334
+ state: {
335
+ ...state,
336
+ judge: {
337
+ model: action.crossModel ? "cross" : "same",
338
+ lastVerdict: action.verdict,
339
+ lastReason: action.reason,
340
+ },
341
+ iterations: state.iterations.map((it) => it.iteration === state.iteration ? { ...it, verdict: action.verdict, reason: action.reason } : it),
342
+ updatedAt: now(),
343
+ },
344
+ events,
345
+ stopLoop,
346
+ };
347
+ }
348
+ case "goal_complete": {
349
+ // JUEZ OBLIGATORIO (pi-until-done): sin veredicto done NO hay
350
+ // completación — continue bloquea done; nunca bypass.
351
+ if (state.status === "complete")
352
+ return { state, events, stopLoop: true };
353
+ if (state.judge.lastVerdict !== "done") {
354
+ return {
355
+ state: {
356
+ ...state,
357
+ waiting: { reason: "goal_complete requiere veredicto done del juez (sin bypass)" },
358
+ updatedAt: now(),
359
+ },
360
+ events,
361
+ stopLoop: true,
362
+ };
363
+ }
364
+ // Evidencia citada obligatoria (archivo:línea / URL).
365
+ if (action.evidence.length === 0 && state.evidence.length === 0) {
366
+ return {
367
+ state: { ...state, waiting: { reason: "goal_complete exige evidencia citada" }, updatedAt: now() },
368
+ events,
369
+ stopLoop: true,
370
+ };
371
+ }
372
+ const merged = mergeEvidence(state.evidence, action.evidence);
373
+ return {
374
+ state: {
375
+ ...state,
376
+ status: "complete",
377
+ phase: "done",
378
+ evidence: merged,
379
+ updatedAt: now(),
380
+ waiting: undefined,
381
+ },
382
+ events: [{ phase: "done" }],
383
+ stopLoop: true,
384
+ };
385
+ }
386
+ default:
387
+ return { state, events, stopLoop };
388
+ }
389
+ }
390
+ function mergeEvidence(a, b) {
391
+ const seen = new Set(a.map((e) => `${e.claim}|${e.source}`));
392
+ return [...a, ...b.filter((e) => !seen.has(`${e.claim}|${e.source}`))];
393
+ }
394
+ function now() {
395
+ return new Date().toISOString();
396
+ }
397
+ //# sourceMappingURL=state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.js","sourceRoot":"","sources":["../../../../src/core/workflows/goal-engine/state.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Ada Intelligence Engine — Goal Engine reducer (puro).\n *\n * Reducer determinista: todas las transiciones de estado pasan por aquí.\n * Reglas de seguridad integradas:\n * - El goal se rota (nuevo id) al editar/reanudar → un turno viejo (id viejo)\n * no puede completar el goal nuevo (guards anti-duplicados).\n * - Las fases TDD son un orden FIJO (código, no elección del modelo).\n * - `goal_complete` exige evidencia citada y juez con verdict done.\n * - Un turno vacío/idéntico incrementa repeatedTurns → pause a la tolerancia.\n */\n\nimport type { EvidenceItem, GoalAction, GoalFrenos, GoalPhase, GoalState, Task, TaskStatus } from \"./types.ts\";\n\nexport const TDD_PHASES: GoalPhase[] = [\"analysis\", \"bootstrap\", \"red\", \"green\", \"refactor\", \"verify\", \"done\"];\n\nexport function nextPhase(phase: GoalPhase): GoalPhase {\n\tconst i = TDD_PHASES.indexOf(phase);\n\treturn i >= 0 && i < TDD_PHASES.length - 1 ? TDD_PHASES[i + 1] : phase;\n}\n\n/** Crea un goal en estado setup (contrato primero, sin trabajo). */\nexport function createGoalState(input: {\n\tgoal: string;\n\tdoneCriteria: string[];\n\tverifyCommand: string;\n\tid?: string;\n\tnow?: string;\n\tsessionId?: string;\n}): GoalState {\n\treturn {\n\t\tid: input.id ?? `goal-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 7)}`,\n\t\tgoal: input.goal,\n\t\tsessionId: input.sessionId,\n\t\tphase: \"analysis\",\n\t\tstatus: \"setup\",\n\t\tdoneCriteria: input.doneCriteria,\n\t\tverifyCommand: input.verifyCommand,\n\t\ttasks: [],\n\t\titeration: 1,\n\t\titerations: [],\n\t\tevidence: [],\n\t\tjudge: { model: null },\n\t\tturnsUsed: 0,\n\t\ttokensUsed: 0,\n\t\tcostUsed: 0,\n\t\trepeatedTurns: 0,\n\t\tlastAgentSummary: \"\",\n\t\tcreatedAt: input.now ?? new Date().toISOString(),\n\t\tupdatedAt: input.now ?? new Date().toISOString(),\n\t};\n}\n\nfunction taskFrom(action: { taskId: string; status: TaskStatus }, tasks: Task[]): Task | undefined {\n\treturn tasks.find((t) => t.id === action.taskId);\n}\n\nexport interface ReduceResult {\n\tstate: GoalState;\n\t/** Transiciones que la UI debe conocer. */\n\tevents: Array<{\n\t\tphase?: GoalPhase;\n\t\tpaused?: boolean;\n\t\treplan?: { iteration: number; tasks: unknown[] };\n\t\ttasksChanged?: unknown[];\n\t}>;\n\t/** true si el bucle debe detenerse tras esta acción. */\n\tstopLoop: boolean;\n}\n\n/** Reduce una acción sobre el estado. Devuelve nuevo estado + eventos derivados. */\nexport function reduceGoal(\n\tstate: GoalState,\n\taction: GoalAction,\n\t_frenos: GoalFrenos = {\n\t\tmaxTurns: 25,\n\t\trepeatTolerance: 3,\n\t\tstopFile: null,\n\t\ttokenBudget: null,\n\t\tcostBudget: null,\n\t\taskBefore: [],\n\t},\n): ReduceResult {\n\tconst events: ReduceResult[\"events\"] = [];\n\tconst stopLoop = false;\n\n\tswitch (action.type) {\n\t\tcase \"goal_approve\": {\n\t\t\tif (state.status !== \"setup\") return { state, events, stopLoop };\n\t\t\treturn {\n\t\t\t\tstate: { ...state, status: \"active\", updatedAt: now() },\n\t\t\t\tevents: [{ phase: \"analysis\" }],\n\t\t\t\tstopLoop,\n\t\t\t};\n\t\t}\n\n\t\tcase \"goal_task_add\": {\n\t\t\t// TODO personalizado: añade una tarea sin reemplazar el plan.\n\t\t\tconst title = action.title.trim();\n\t\t\tif (!title) return { state, events, stopLoop };\n\t\t\tconst newTask: Task = {\n\t\t\t\tid: `task-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 6)}`,\n\t\t\t\ttitle,\n\t\t\t\tstatus: \"pending\",\n\t\t\t};\n\t\t\treturn {\n\t\t\t\tstate: { ...state, tasks: [...state.tasks, newTask], updatedAt: now() },\n\t\t\t\tevents,\n\t\t\t\tstopLoop,\n\t\t\t};\n\t\t}\n\n\t\tcase \"goal_tasks\": {\n\t\t\t// Solo planificar en planning/active; reemplaza el plan.\n\t\t\tif (state.status !== \"active\" && state.status !== \"planning\") return { state, events, stopLoop };\n\t\t\treturn {\n\t\t\t\tstate: { ...state, tasks: action.tasks, status: \"active\", updatedAt: now() },\n\t\t\t\tevents,\n\t\t\t\tstopLoop,\n\t\t\t};\n\t\t}\n\n\t\tcase \"goal_task_launched\": {\n\t\t\t// El workflow dinámico de la sub-tarea está en marcha (un turno gastado).\n\t\t\treturn {\n\t\t\t\tstate: {\n\t\t\t\t\t...state,\n\t\t\t\t\ttasks: state.tasks.map((t) =>\n\t\t\t\t\t\tt.id === action.taskId\n\t\t\t\t\t\t\t? { ...t, status: \"running\" as TaskStatus, workflowRunId: action.workflowRunId }\n\t\t\t\t\t\t\t: t,\n\t\t\t\t\t),\n\t\t\t\t\tturnsUsed: state.turnsUsed + 1,\n\t\t\t\t\tupdatedAt: now(),\n\t\t\t\t},\n\t\t\t\tevents,\n\t\t\t\tstopLoop,\n\t\t\t};\n\t\t}\n\n\t\tcase \"goal_task_result\": {\n\t\t\t// El workflow de la sub-tarea terminó (done/failed) con resumen.\n\t\t\treturn {\n\t\t\t\tstate: {\n\t\t\t\t\t...state,\n\t\t\t\t\ttasks: state.tasks.map((t) =>\n\t\t\t\t\t\tt.id === action.taskId\n\t\t\t\t\t\t\t? { ...t, status: action.status, resultSummary: action.summary ?? t.resultSummary }\n\t\t\t\t\t\t\t: t,\n\t\t\t\t\t),\n\t\t\t\t\tupdatedAt: now(),\n\t\t\t\t},\n\t\t\t\tevents,\n\t\t\t\tstopLoop,\n\t\t\t};\n\t\t}\n\n\t\tcase \"goal_replan\": {\n\t\t\t// P1: re-planificación completa. Nueva iteración, nuevo plan,\n\t\t\t// historial anexado. Solo si el contrato está aprobado y el plan\n\t\t\t// cambia materialmente (o no hay plan).\n\t\t\tconst clean = action.tasks\n\t\t\t\t.filter((t) => t.title?.trim())\n\t\t\t\t.map((t, i) => ({\n\t\t\t\t\tid: `task-${Date.now().toString(36)}-${i}-${Math.random().toString(36).slice(2, 5)}`,\n\t\t\t\t\ttitle: t.title.trim(),\n\t\t\t\t\tstatus: \"pending\" as TaskStatus,\n\t\t\t\t}));\n\t\t\tconst samePlan =\n\t\t\t\tstate.tasks.length === clean.length &&\n\t\t\t\tstate.tasks.length > 0 &&\n\t\t\t\tstate.tasks.every((t, i) => t.title.trim() === clean[i]?.title);\n\t\t\t// Sin cambio real del plan → no iterar (evita loops vacíos).\n\t\t\tif (samePlan) return { state, events, stopLoop: true };\n\t\t\tconst record = {\n\t\t\t\titeration: state.iteration,\n\t\t\t\tplan: state.tasks.map((t) => ({ ...t })),\n\t\t\t\tverdict: state.judge.lastVerdict,\n\t\t\t\treason: state.judge.lastReason ?? state.replanRationale,\n\t\t\t\treplanRationale: action.rationale,\n\t\t\t\ttokensUsed: state.tokensUsed,\n\t\t\t\tcostUsed: state.costUsed,\n\t\t\t\ttimestamp: now(),\n\t\t\t};\n\t\t\treturn {\n\t\t\t\tstate: {\n\t\t\t\t\t...state,\n\t\t\t\t\ttasks: clean,\n\t\t\t\t\titeration: state.iteration + 1,\n\t\t\t\t\titerations: [...state.iterations, record],\n\t\t\t\t\treplanRationale: action.rationale,\n\t\t\t\t\trepeatedTurns: 0, // plan nuevo → reset del repeat detector\n\t\t\t\t\tupdatedAt: now(),\n\t\t\t\t},\n\t\t\t\tevents: [{ replan: { iteration: state.iteration + 1, tasks: clean } }],\n\t\t\t\tstopLoop,\n\t\t\t};\n\t\t}\n\n\t\tcase \"goal_task_remove\": {\n\t\t\t// P2: quitar una sub-tarea (no ejecutada).\n\t\t\tconst target = state.tasks.find((t) => t.id === action.taskId);\n\t\t\t// No se puede quitar una sub-tarea con workflow en marcha aquí\n\t\t\t// (el manager la aborta primero vía goal_task_result).\n\t\t\tif (!target || target.status === \"running\") return { state, events, stopLoop };\n\t\t\treturn {\n\t\t\t\tstate: {\n\t\t\t\t\t...state,\n\t\t\t\t\ttasks: state.tasks.filter((t) => t.id !== action.taskId),\n\t\t\t\t\tupdatedAt: now(),\n\t\t\t\t},\n\t\t\t\tevents: [{ tasksChanged: state.tasks.filter((t) => t.id !== action.taskId) }],\n\t\t\t\tstopLoop,\n\t\t\t};\n\t\t}\n\n\t\tcase \"goal_task_move\": {\n\t\t\t// P2: reordenar (arriba/abajo) en cualquier fase.\n\t\t\tconst idx = state.tasks.findIndex((t) => t.id === action.taskId);\n\t\t\tif (idx === -1) return { state, events, stopLoop };\n\t\t\tconst target = idx + (action.dir === \"up\" ? -1 : 1);\n\t\t\tif (target < 0 || target >= state.tasks.length) return { state, events, stopLoop };\n\t\t\tconst tasks = [...state.tasks];\n\t\t\t[tasks[idx], tasks[target]] = [tasks[target], tasks[idx]];\n\t\t\treturn {\n\t\t\t\tstate: { ...state, tasks, updatedAt: now() },\n\t\t\t\tevents: [{ tasksChanged: tasks }],\n\t\t\t\tstopLoop,\n\t\t\t};\n\t\t}\n\n\t\tcase \"goal_task_update\": {\n\t\t\tconst task = taskFrom(action, state.tasks);\n\t\t\tif (!task) return { state, events, stopLoop };\n\t\t\tconst tasks = state.tasks.map((t) => (t.id === action.taskId ? { ...t, status: action.status } : t));\n\t\t\treturn {\n\t\t\t\tstate: { ...state, tasks, updatedAt: now() },\n\t\t\t\tevents,\n\t\t\t\tstopLoop,\n\t\t\t};\n\t\t}\n\n\t\tcase \"goal_phase\": {\n\t\t\t// Orden fijo TDD: solo avanzar a la siguiente fase.\n\t\t\tif (action.phase !== nextPhase(state.phase)) return { state, events, stopLoop };\n\t\t\treturn {\n\t\t\t\tstate: { ...state, phase: action.phase, updatedAt: now() },\n\t\t\t\tevents: [{ phase: action.phase }],\n\t\t\t\tstopLoop,\n\t\t\t};\n\t\t}\n\n\t\tcase \"goal_agent_turn\": {\n\t\t\t// El turno del agente: incrementa contadores, detecta repetición.\n\t\t\tconst summary = action.summary ?? \"\";\n\t\t\tconst repeated = summary.trim().length === 0 || summary === state.lastAgentSummary;\n\t\t\tconst repeatedTurns = repeated ? state.repeatedTurns + 1 : 0;\n\t\t\tconst turnsUsed = state.turnsUsed + 1;\n\t\t\tlet next: GoalState = {\n\t\t\t\t...state,\n\t\t\t\tturnsUsed,\n\t\t\t\trepeatedTurns,\n\t\t\t\tlastAgentSummary: summary,\n\t\t\t\ttokensUsed: state.tokensUsed + (action.tokens ?? 0),\n\t\t\t\tcostUsed: state.costUsed + (action.cost ?? 0),\n\t\t\t\tupdatedAt: now(),\n\t\t\t};\n\t\t\tif (action.evidence?.length) {\n\t\t\t\t// No duplicar evidencia idéntica.\n\t\t\t\tconst existing = new Set(state.evidence.map((e) => `${e.claim}|${e.source}`));\n\t\t\t\tconst fresh = action.evidence.filter((e) => !existing.has(`${e.claim}|${e.source}`));\n\t\t\t\tnext = { ...next, evidence: [...state.evidence, ...fresh] };\n\t\t\t}\n\t\t\tif (action.tasks?.length) {\n\t\t\t\tconst tasks = next.tasks.map((t) => {\n\t\t\t\t\tconst u = action.tasks!.find((x) => x.taskId === t.id);\n\t\t\t\t\treturn u ? { ...t, status: u.status } : t;\n\t\t\t\t});\n\t\t\t\tnext = { ...next, tasks };\n\t\t\t}\n\t\t\treturn { state: next, events, stopLoop };\n\t\t}\n\n\t\tcase \"goal_pause\": {\n\t\t\treturn {\n\t\t\t\tstate: {\n\t\t\t\t\t...state,\n\t\t\t\t\tstatus: \"paused\",\n\t\t\t\t\twaiting: { reason: action.reason ?? \"pausado por el usuario\" },\n\t\t\t\t\tupdatedAt: now(),\n\t\t\t\t},\n\t\t\t\tevents,\n\t\t\t\tstopLoop: true,\n\t\t\t};\n\t\t}\n\n\t\tcase \"goal_resume\": {\n\t\t\tif (state.status !== \"paused\") return { state, events, stopLoop };\n\t\t\treturn {\n\t\t\t\tstate: { ...state, status: \"active\", waiting: undefined, repeatedTurns: 0, updatedAt: now() },\n\t\t\t\tevents,\n\t\t\t\tstopLoop,\n\t\t\t};\n\t\t}\n\n\t\tcase \"goal_blocked\": {\n\t\t\treturn {\n\t\t\t\tstate: { ...state, status: \"blocked\", waiting: { reason: action.reason }, updatedAt: now() },\n\t\t\t\tevents,\n\t\t\t\tstopLoop: true,\n\t\t\t};\n\t\t}\n\n\t\tcase \"goal_wait\": {\n\t\t\treturn {\n\t\t\t\tstate: {\n\t\t\t\t\t...state,\n\t\t\t\t\tstatus: \"paused\",\n\t\t\t\t\twaiting: { reason: action.reason, resumeAfterMs: action.resumeAfterMs },\n\t\t\t\t\tupdatedAt: now(),\n\t\t\t\t},\n\t\t\t\tevents,\n\t\t\t\tstopLoop: true,\n\t\t\t};\n\t\t}\n\n\t\tcase \"goal_questions\": {\n\t\t\treturn {\n\t\t\t\tstate: {\n\t\t\t\t\t...state,\n\t\t\t\t\tstatus: \"blocked\",\n\t\t\t\t\tpendingQuestions: action.questions,\n\t\t\t\t\twaiting: { reason: action.reason },\n\t\t\t\t\tupdatedAt: now(),\n\t\t\t\t},\n\t\t\t\tevents,\n\t\t\t\tstopLoop: true,\n\t\t\t};\n\t\t}\n\n\t\tcase \"goal_answers\": {\n\t\t\t// Las respuestas limpian el bloqueo y reactivan.\n\t\t\treturn {\n\t\t\t\tstate: { ...state, status: \"active\", pendingQuestions: undefined, waiting: undefined, updatedAt: now() },\n\t\t\t\tevents,\n\t\t\t\tstopLoop,\n\t\t\t};\n\t\t}\n\n\t\tcase \"goal_usage_limited\": {\n\t\t\treturn {\n\t\t\t\tstate: {\n\t\t\t\t\t...state,\n\t\t\t\t\tstatus: \"usage_limited\",\n\t\t\t\t\twaiting: { reason: \"Presupuesto de tokens agotado\" },\n\t\t\t\t\tupdatedAt: now(),\n\t\t\t\t},\n\t\t\t\tevents,\n\t\t\t\tstopLoop: true,\n\t\t\t};\n\t\t}\n\n\t\tcase \"goal_budget_limited\": {\n\t\t\treturn {\n\t\t\t\tstate: {\n\t\t\t\t\t...state,\n\t\t\t\t\tstatus: \"budget_limited\",\n\t\t\t\t\twaiting: { reason: \"Presupuesto de coste agotado\" },\n\t\t\t\t\tupdatedAt: now(),\n\t\t\t\t},\n\t\t\t\tevents,\n\t\t\t\tstopLoop: true,\n\t\t\t};\n\t\t}\n\n\t\tcase \"goal_judge\": {\n\t\t\t// Al veredictar se anexa la iteración actual al historial (P3):\n\t\t\t// veredicto + razón en el registro de la iteración en curso.\n\t\t\treturn {\n\t\t\t\tstate: {\n\t\t\t\t\t...state,\n\t\t\t\t\tjudge: {\n\t\t\t\t\t\tmodel: action.crossModel ? \"cross\" : \"same\",\n\t\t\t\t\t\tlastVerdict: action.verdict,\n\t\t\t\t\t\tlastReason: action.reason,\n\t\t\t\t\t},\n\t\t\t\t\titerations: state.iterations.map((it) =>\n\t\t\t\t\t\tit.iteration === state.iteration ? { ...it, verdict: action.verdict, reason: action.reason } : it,\n\t\t\t\t\t),\n\t\t\t\t\tupdatedAt: now(),\n\t\t\t\t},\n\t\t\t\tevents,\n\t\t\t\tstopLoop,\n\t\t\t};\n\t\t}\n\n\t\tcase \"goal_complete\": {\n\t\t\t// JUEZ OBLIGATORIO (pi-until-done): sin veredicto done NO hay\n\t\t\t// completación — continue bloquea done; nunca bypass.\n\t\t\tif (state.status === \"complete\") return { state, events, stopLoop: true };\n\t\t\tif (state.judge.lastVerdict !== \"done\") {\n\t\t\t\treturn {\n\t\t\t\t\tstate: {\n\t\t\t\t\t\t...state,\n\t\t\t\t\t\twaiting: { reason: \"goal_complete requiere veredicto done del juez (sin bypass)\" },\n\t\t\t\t\t\tupdatedAt: now(),\n\t\t\t\t\t},\n\t\t\t\t\tevents,\n\t\t\t\t\tstopLoop: true,\n\t\t\t\t};\n\t\t\t}\n\t\t\t// Evidencia citada obligatoria (archivo:línea / URL).\n\t\t\tif (action.evidence.length === 0 && state.evidence.length === 0) {\n\t\t\t\treturn {\n\t\t\t\t\tstate: { ...state, waiting: { reason: \"goal_complete exige evidencia citada\" }, updatedAt: now() },\n\t\t\t\t\tevents,\n\t\t\t\t\tstopLoop: true,\n\t\t\t\t};\n\t\t\t}\n\t\t\tconst merged: EvidenceItem[] = mergeEvidence(state.evidence, action.evidence);\n\t\t\treturn {\n\t\t\t\tstate: {\n\t\t\t\t\t...state,\n\t\t\t\t\tstatus: \"complete\",\n\t\t\t\t\tphase: \"done\",\n\t\t\t\t\tevidence: merged,\n\t\t\t\t\tupdatedAt: now(),\n\t\t\t\t\twaiting: undefined,\n\t\t\t\t},\n\t\t\t\tevents: [{ phase: \"done\" }],\n\t\t\t\tstopLoop: true,\n\t\t\t};\n\t\t}\n\n\t\tdefault:\n\t\t\treturn { state, events, stopLoop };\n\t}\n}\n\nfunction mergeEvidence(a: EvidenceItem[], b: EvidenceItem[]): EvidenceItem[] {\n\tconst seen = new Set(a.map((e) => `${e.claim}|${e.source}`));\n\treturn [...a, ...b.filter((e) => !seen.has(`${e.claim}|${e.source}`))];\n}\n\nfunction now(): string {\n\treturn new Date().toISOString();\n}\n"]}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Ada Intelligence Engine — tools del Goal Engine.
3
+ *
4
+ * Herramientas que el agente usa durante un goal: goal_complete (con
5
+ * evidencia), goal_blocked, goal_wait, todo (checklist), ask_user_question
6
+ * (cuestionario tipado, pi-ask-user). Se registran en la sesión activa del
7
+ * goal; su estado vive en el GoalEngine (inyectado como "engine").
8
+ */
9
+ import type { ToolDefinition } from "../../extensions/types.ts";
10
+ import type { GoalEngine } from "./engine.ts";
11
+ export interface GoalToolContext {
12
+ engine: GoalEngine;
13
+ goalId: string;
14
+ }
15
+ /**
16
+ * goal_new — Crea el contrato de un goal (estado setup). Tool de SESIÓN:
17
+ * no depende de un goal activo (a diferencia de goalTools). El agente la usa
18
+ * cuando el usuario pide "crea un goal para X" en lenguaje natural.
19
+ */
20
+ export declare function createGoalNewTool(engine: GoalEngine, sessionId?: () => string | undefined): ToolDefinition;
21
+ /** Todas las tools del Goal Engine para una sesión con goal activo. */
22
+ export declare function goalTools(ctx: GoalToolContext): ToolDefinition[];
23
+ /**
24
+ * goalSessionTools — variante para una SESIÓN: el goalId se resuelve en cada
25
+ * ejecución al goal activo (o se pasa explícito). Permite registrar las tools
26
+ * del goal sin conocer el id en buildRuntime (los goals se crean después).
27
+ */
28
+ export declare function resolveActiveGoalId(engine: GoalEngine): Promise<string | null>;
29
+ /** Registra las tools del Goal Engine resolviendo el goal activo por llamada. */
30
+ export declare function goalSessionTools(engine: GoalEngine, sessionId?: () => string | undefined): ToolDefinition[];
31
+ //# sourceMappingURL=tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../../../src/core/workflows/goal-engine/tools.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAqC,cAAc,EAAE,MAAM,2BAA2B,CAAC;AACnG,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,MAAM,WAAW,eAAe;IAC/B,MAAM,EAAE,UAAU,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;CACf;AAYD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,UAAU,EAAE,SAAS,CAAC,EAAE,MAAM,MAAM,GAAG,SAAS,GAAG,cAAc,CAuC1G;AAED,wEAAuE;AACvE,wBAAgB,SAAS,CAAC,GAAG,EAAE,eAAe,GAAG,cAAc,EAAE,CAuKhE;AAED;;;;GAIG;AACH,wBAAsB,mBAAmB,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAIpF;AAED,iFAAiF;AACjF,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,UAAU,EAAE,SAAS,CAAC,EAAE,MAAM,MAAM,GAAG,SAAS,GAAG,cAAc,EAAE,CAS3G","sourcesContent":["/**\n * Ada Intelligence Engine — tools del Goal Engine.\n *\n * Herramientas que el agente usa durante un goal: goal_complete (con\n * evidencia), goal_blocked, goal_wait, todo (checklist), ask_user_question\n * (cuestionario tipado, pi-ask-user). Se registran en la sesión activa del\n * goal; su estado vive en el GoalEngine (inyectado como \"engine\").\n */\n\nimport { Type } from \"typebox\";\nimport type { AgentToolResult, ExtensionContext, ToolDefinition } from \"../../extensions/types.ts\";\nimport type { GoalEngine } from \"./engine.ts\";\n\nexport interface GoalToolContext {\n\tengine: GoalEngine;\n\tgoalId: string;\n}\n\ntype OkResult = AgentToolResult<undefined>;\n\nfunction ok(_content: string, extra: Record<string, unknown> = {}): OkResult {\n\treturn { details: undefined, content: [{ type: \"text\", text: JSON.stringify({ ok: true, ...extra }) }] };\n}\n\nfunction notOk(error: string): OkResult {\n\treturn { details: undefined, content: [{ type: \"text\", text: JSON.stringify({ ok: false, error }) }] };\n}\n\n/**\n * goal_new — Crea el contrato de un goal (estado setup). Tool de SESIÓN:\n * no depende de un goal activo (a diferencia de goalTools). El agente la usa\n * cuando el usuario pide \"crea un goal para X\" en lenguaje natural.\n */\nexport function createGoalNewTool(engine: GoalEngine, sessionId?: () => string | undefined): ToolDefinition {\n\treturn {\n\t\tname: \"goal_new\",\n\t\tlabel: \"Crear goal\",\n\t\tdescription:\n\t\t\t\"Crea el contrato de un goal del Ada Intelligence Engine en estado setup. El goal NO arranca hasta que el usuario lo aprueba (/goal approve <id> o la tool goal_approve). Usa doneCriteria medibles y verifyCommand ejecutable.\",\n\t\tpromptSnippet: \"Crea un goal con contrato (goal_new)\",\n\t\tpromptGuidelines: [\n\t\t\t\"Define doneCriteria observables y medibles (nunca vagas).\",\n\t\t\t\"El goal queda en setup hasta aprobarse — indícalo al usuario.\",\n\t\t],\n\t\tparameters: Type.Object({\n\t\t\tgoal: Type.String({ description: \"El objetivo verbatim\" }),\n\t\t\tdoneCriteria: Type.Array(Type.String(), { description: \"Criterios medibles de hechura\" }),\n\t\t\tverifyCommand: Type.String({ description: \"Comando de verificación (o string vacío)\" }),\n\t\t}),\n\t\tasync execute(_toolCallId: string, input: { goal: string; doneCriteria: string[]; verifyCommand: string }) {\n\t\t\tconst state = await engine.createGoal({\n\t\t\t\tgoal: input.goal,\n\t\t\t\tdoneCriteria: Array.isArray(input.doneCriteria) ? input.doneCriteria : [],\n\t\t\t\tverifyCommand: input.verifyCommand ?? \"\",\n\t\t\t\tsessionId: sessionId ? sessionId() : undefined,\n\t\t\t});\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\",\n\t\t\t\t\t\ttext: JSON.stringify({\n\t\t\t\t\t\t\tok: true,\n\t\t\t\t\t\t\tgoalId: state.id,\n\t\t\t\t\t\t\tstatus: state.status,\n\t\t\t\t\t\t\tmessage: `Contrato creado: ${state.id}. Apruebalo con /goal approve ${state.id}`,\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\n/** Todas las tools del Goal Engine para una sesión con goal activo. */\nexport function goalTools(ctx: GoalToolContext): ToolDefinition[] {\n\tconst { engine, goalId } = ctx;\n\n\treturn [\n\t\t{\n\t\t\tname: \"goal_complete\",\n\t\t\tlabel: \"Completar goal\",\n\t\t\tdescription:\n\t\t\t\t\"Declara el goal como completado. EXIGE evidencia citada (archivo:línea o URL) por cada criterio de hechura. Solo funciona si el juez ya emitió veredicto done — sin juez, sin completación.\",\n\t\t\tpromptSnippet: \"Completa el goal con evidencia citada (goal_complete)\",\n\t\t\tpromptGuidelines: [\n\t\t\t\t\"Nunca completes un goal sin evidencia citada archivo:línea o URL.\",\n\t\t\t\t\"Si el juez no ha dado done, sigue trabajando en lugar de forzar la completación.\",\n\t\t\t],\n\t\t\tparameters: Type.Object({\n\t\t\t\tsummary: Type.String({ description: \"Resumen de lo realizado\" }),\n\t\t\t\tevidence: Type.Array(\n\t\t\t\t\tType.Object({\n\t\t\t\t\t\tclaim: Type.String({ description: \"Afirmación verificable\" }),\n\t\t\t\t\t\tsource: Type.String({ description: \"archivo:línea, URL o comando que lo prueba\" }),\n\t\t\t\t\t}),\n\t\t\t\t\t{ description: \"Evidencia citada por cada criterio\" },\n\t\t\t\t),\n\t\t\t}),\n\t\t\tasync execute(\n\t\t\t\t_toolCallId: string,\n\t\t\t\tinput: { summary: string; evidence: Array<{ claim: string; source: string }> },\n\t\t\t\t_signal: AbortSignal | undefined,\n\t\t\t\t_onUpdate: unknown,\n\t\t\t\t_ctx: ExtensionContext,\n\t\t\t): Promise<OkResult> {\n\t\t\t\tconst state = await engine.complete(\n\t\t\t\t\tgoalId,\n\t\t\t\t\tinput.summary,\n\t\t\t\t\tinput.evidence.map((e) => ({ ...e, citedBy: \"agent\" })),\n\t\t\t\t);\n\t\t\t\treturn state.status === \"complete\"\n\t\t\t\t\t? ok(\"goal completado\", { status: state.status })\n\t\t\t\t\t: notOk(state.waiting?.reason ?? \"no completado\");\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"goal_blocked\",\n\t\t\tlabel: \"Bloquear goal\",\n\t\t\tdescription: \"Marca el goal como bloqueado con un motivo (necesita intervención del usuario).\",\n\t\t\tpromptSnippet: \"Bloquea el goal con motivo (goal_blocked)\",\n\t\t\tparameters: Type.Object({\n\t\t\t\treason: Type.String({ description: \"Motivo del bloqueo\" }),\n\t\t\t}),\n\t\t\tasync execute(\n\t\t\t\t_toolCallId: string,\n\t\t\t\tinput: { reason: string },\n\t\t\t\t_signal: AbortSignal | undefined,\n\t\t\t\t_onUpdate: unknown,\n\t\t\t\t_ctx: ExtensionContext,\n\t\t\t): Promise<OkResult> {\n\t\t\t\tconst state = await engine.blocked(goalId, input.reason);\n\t\t\t\treturn ok(\"goal bloqueado\", { status: state.status });\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"goal_wait\",\n\t\t\tlabel: \"Esperar\",\n\t\t\tdescription: \"Pausa el goal hasta que pase un tiempo o el usuario reanude.\",\n\t\t\tpromptSnippet: \"Pausa el goal (goal_wait)\",\n\t\t\tparameters: Type.Object({\n\t\t\t\treason: Type.String({ description: \"Por qué espera\" }),\n\t\t\t\tresumeAfterMs: Type.Optional(Type.Number({ description: \"Reanudar tras N ms\" })),\n\t\t\t}),\n\t\t\tasync execute(\n\t\t\t\t_toolCallId: string,\n\t\t\t\tinput: { reason: string; resumeAfterMs?: number },\n\t\t\t\t_signal: AbortSignal | undefined,\n\t\t\t\t_onUpdate: unknown,\n\t\t\t\t_ctx: ExtensionContext,\n\t\t\t): Promise<OkResult> {\n\t\t\t\tconst state = await engine.pause(goalId, input.reason);\n\t\t\t\treturn ok(\"goal pausado\", { status: state.status, resumeAfterMs: input.resumeAfterMs ?? null });\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"todo\",\n\t\t\tlabel: \"Checklist de tareas\",\n\t\t\tdescription:\n\t\t\t\t\"Reemplaza o actualiza la checklist de tareas del goal. Cada tarea: id estable (kebab-case), título, estado (pending|active|done). Se muestra en el panel en vivo.\",\n\t\t\tpromptSnippet: \"Actualiza la checklist del goal (todo)\",\n\t\t\tparameters: Type.Object({\n\t\t\t\ttasks: Type.Array(\n\t\t\t\t\tType.Object({\n\t\t\t\t\t\tid: Type.String({ description: \"id estable, kebab-case\" }),\n\t\t\t\t\t\ttitle: Type.String(),\n\t\t\t\t\t\tstatus: Type.Union([Type.Literal(\"pending\"), Type.Literal(\"active\"), Type.Literal(\"done\")]),\n\t\t\t\t\t\tdetail: Type.Optional(Type.String()),\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t}),\n\t\t\tasync execute(\n\t\t\t\t_toolCallId: string,\n\t\t\t\tinput: {\n\t\t\t\t\ttasks: Array<{ id: string; title: string; status: \"pending\" | \"active\" | \"done\"; detail?: string }>;\n\t\t\t\t},\n\t\t\t\t_signal: AbortSignal | undefined,\n\t\t\t\t_onUpdate: unknown,\n\t\t\t\t_ctx: ExtensionContext,\n\t\t\t): Promise<OkResult> {\n\t\t\t\tconst state = await engine.get(goalId);\n\t\t\t\tif (!state) return notOk(\"goal no encontrado\");\n\t\t\t\tawait engine.replaceTasks(goalId, input.tasks);\n\t\t\t\treturn ok(\"checklist actualizada\", { count: input.tasks.length });\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"ask_user_question\",\n\t\t\tlabel: \"Preguntar al usuario\",\n\t\t\tdescription:\n\t\t\t\t\"Cuando una decisión es ambigua o irreversible, pregunta al usuario con un cuestionario tipado (hasta 4 preguntas; single-select, multi-select o freeform). El goal se bloquea hasta que responda.\",\n\t\t\tpromptSnippet: \"Pregunta al usuario antes de decidir (ask_user_question)\",\n\t\t\tpromptGuidelines: [\n\t\t\t\t\"Usa ask_user_question cuando vayas a adivinar una decisión ambigua o irreversible.\",\n\t\t\t\t\"Máximo 4 preguntas; usa single-select con choices para decisiones cerradas.\",\n\t\t\t],\n\t\t\tparameters: Type.Object({\n\t\t\t\treason: Type.String({ description: \"Contexto de por qué preguntas\" }),\n\t\t\t\tquestions: Type.Array(\n\t\t\t\t\tType.Object({\n\t\t\t\t\t\tquestion: Type.String(),\n\t\t\t\t\t\ttype: Type.Union([\n\t\t\t\t\t\t\tType.Literal(\"single-select\"),\n\t\t\t\t\t\t\tType.Literal(\"multi-select\"),\n\t\t\t\t\t\t\tType.Literal(\"freeform\"),\n\t\t\t\t\t\t]),\n\t\t\t\t\t\tchoices: Type.Optional(Type.Array(Type.String())),\n\t\t\t\t\t\trequired: Type.Optional(Type.Boolean()),\n\t\t\t\t\t}),\n\t\t\t\t\t{ maxItems: 4 },\n\t\t\t\t),\n\t\t\t}),\n\t\t\tasync execute(\n\t\t\t\t_toolCallId: string,\n\t\t\t\tinput: {\n\t\t\t\t\treason: string;\n\t\t\t\t\tquestions: Array<{\n\t\t\t\t\t\tquestion: string;\n\t\t\t\t\t\ttype: \"single-select\" | \"multi-select\" | \"freeform\";\n\t\t\t\t\t\tchoices?: string[];\n\t\t\t\t\t\trequired?: boolean;\n\t\t\t\t\t}>;\n\t\t\t\t},\n\t\t\t\t_signal: AbortSignal | undefined,\n\t\t\t\t_onUpdate: unknown,\n\t\t\t\t_ctx: ExtensionContext,\n\t\t\t): Promise<OkResult> {\n\t\t\t\tconst state = await engine.askUser(\n\t\t\t\t\tgoalId,\n\t\t\t\t\tinput.reason,\n\t\t\t\t\tinput.questions.map((q, i) => ({\n\t\t\t\t\t\tid: `q${i + 1}`,\n\t\t\t\t\t\tquestion: q.question,\n\t\t\t\t\t\ttype: q.type,\n\t\t\t\t\t\tchoices: q.choices,\n\t\t\t\t\t\trequired: q.required,\n\t\t\t\t\t})),\n\t\t\t\t);\n\t\t\t\treturn ok(\"preguntas enviadas — goal bloqueado hasta respuesta\", { status: state.status });\n\t\t\t},\n\t\t},\n\t];\n}\n\n/**\n * goalSessionTools — variante para una SESIÓN: el goalId se resuelve en cada\n * ejecución al goal activo (o se pasa explícito). Permite registrar las tools\n * del goal sin conocer el id en buildRuntime (los goals se crean después).\n */\nexport async function resolveActiveGoalId(engine: GoalEngine): Promise<string | null> {\n\tconst goals = await engine.list().catch(() => []);\n\tconst active = goals.find((g) => g.status === \"active\" || g.status === \"setup\");\n\treturn active?.id ?? null;\n}\n\n/** Registra las tools del Goal Engine resolviendo el goal activo por llamada. */\nexport function goalSessionTools(engine: GoalEngine, sessionId?: () => string | undefined): ToolDefinition[] {\n\tconst staticCtx: GoalToolContext = { engine, goalId: \"\" };\n\t// Reusar las tools estáticas: su ctx.goalId se sobreescribe en cada llama\n\t// re-creando contexto con el goal activo.\n\t// goal_new no depende de goal activo — se registra tal cual.\n\treturn [\n\t\tcreateGoalNewTool(engine, sessionId),\n\t\t...goalTools(staticCtx).map((tool) => wrapResolvingGoal(tool, engine)),\n\t];\n}\n\ntype AnyTool = ToolDefinition<any, any, any>;\n\nfunction wrapResolvingGoal(tool: AnyTool, engine: GoalEngine): AnyTool {\n\tconst execute = tool.execute;\n\treturn {\n\t\t...tool,\n\t\texecute: async (toolCallId, params, signal, onUpdate, ctx) => {\n\t\t\tconst goalId = (await resolveActiveGoalId(engine)) ?? \"\";\n\t\t\tif (!goalId) {\n\t\t\t\treturn {\n\t\t\t\t\tdetails: undefined,\n\t\t\t\t\tcontent: [{ type: \"text\", text: JSON.stringify({ ok: false, error: \"no hay goal activo\" }) }],\n\t\t\t\t};\n\t\t\t}\n\t\t\tconst fresh = goalTools({ engine, goalId }).find((t) => t.name === tool.name);\n\t\t\tif (!fresh || !fresh.execute) {\n\t\t\t\treturn execute(toolCallId, params, signal, onUpdate, ctx);\n\t\t\t}\n\t\t\treturn fresh.execute(toolCallId, params, signal, onUpdate, ctx);\n\t\t},\n\t};\n}\n"]}