@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
@@ -14,6 +14,7 @@ import { APP_NAME, APP_TITLE, CONFIG_DIR_NAME, getAgentDir, getAuthPath, getDebu
14
14
  import { parseSkillBlock } from "../../core/agent-session.js";
15
15
  import { SessionImportFileNotFoundError } from "../../core/agent-session-runtime.js";
16
16
  import { CACHE_TTL_MS, collectCacheMisses, computeCacheWaste, detectCacheMiss, } from "../../core/cache-stats.js";
17
+ import { DEFAULT_THINKING_LEVEL, THINKING_LEVEL_OPTIONS } from "../../core/defaults.js";
17
18
  import { FooterDataProvider } from "../../core/footer-data-provider.js";
18
19
  import { configureHttpDispatcher, formatHttpIdleTimeoutMs } from "../../core/http-dispatcher.js";
19
20
  import { KeybindingsManager } from "../../core/keybindings.js";
@@ -27,6 +28,7 @@ import { BUILTIN_SLASH_COMMANDS } from "../../core/slash-commands.js";
27
28
  import { isInstallTelemetryEnabled } from "../../core/telemetry.js";
28
29
  import { hasTrustRequiringProjectResources, ProjectTrustStore } from "../../core/trust-manager.js";
29
30
  import { getUsageCostBreakdown } from "../../core/usage-totals.js";
31
+ import { reduceGoal } from "../../core/workflows/goal-engine/state.js";
30
32
  import { getChangelogPath, getNewEntries, normalizeChangelogLinks, parseChangelog } from "../../utils/changelog.js";
31
33
  import { copyToClipboard, readClipboardText } from "../../utils/clipboard.js";
32
34
  import { extensionForImageMimeType, readClipboardImage } from "../../utils/clipboard-image.js";
@@ -58,11 +60,13 @@ import { LoginDialogComponent } from "./components/login-dialog.js";
58
60
  import { createMermaidMarkdownTransformer } from "./components/mermaid.js";
59
61
  import { ModelSelectorComponent } from "./components/model-selector.js";
60
62
  import { formatAuthSelectorProviderType, OAuthSelectorComponent, } from "./components/oauth-selector.js";
63
+ import { PromptOptimization } from "./components/prompt-optimization.js";
61
64
  import { ScopedModelsSelectorComponent } from "./components/scoped-models-selector.js";
62
65
  import { SessionSelectorComponent } from "./components/session-selector.js";
63
66
  import { SettingsSelectorComponent } from "./components/settings-selector.js";
64
67
  import { SkillInvocationMessageComponent } from "./components/skill-invocation-message.js";
65
68
  import { BranchSummaryStatusIndicator, CompactionStatusIndicator, IdleStatus, RetryStatusIndicator, WorkingStatusIndicator, } from "./components/status-indicator.js";
69
+ import { ThinkingSelectorComponent } from "./components/thinking-selector.js";
66
70
  import { ToolExecutionComponent } from "./components/tool-execution.js";
67
71
  import { TreeSelectorComponent } from "./components/tree-selector.js";
68
72
  import { TrustSelectorComponent } from "./components/trust-selector.js";
@@ -91,6 +95,9 @@ class ExpandableText extends Text {
91
95
  function isCustomSessionEntry(item) {
92
96
  return "type" in item && item.type === "custom";
93
97
  }
98
+ function isCompactionCostNotice(item) {
99
+ return "type" in item && item.type === "compaction_cost";
100
+ }
94
101
  const DEAD_TERMINAL_ERROR_CODES = new Set(["EIO", "EPIPE", "ENOTCONN"]);
95
102
  function isDeadTerminalError(error) {
96
103
  if (!error || typeof error !== "object" || !("code" in error)) {
@@ -99,6 +106,34 @@ function isDeadTerminalError(error) {
99
106
  const code = error.code;
100
107
  return code !== undefined && DEAD_TERMINAL_ERROR_CODES.has(code);
101
108
  }
109
+ export function parseDefaultFlagArgs(commandName, args) {
110
+ if (!args?.trim())
111
+ return { persist: false };
112
+ let persist = false;
113
+ const searchTerms = [];
114
+ for (const token of args.trim().split(/\s+/u)) {
115
+ if (token === "--default") {
116
+ persist = true;
117
+ continue;
118
+ }
119
+ if (token.startsWith("--default=")) {
120
+ persist = true;
121
+ const value = token.slice("--default=".length);
122
+ if (value)
123
+ searchTerms.push(value);
124
+ continue;
125
+ }
126
+ if (token.startsWith("--")) {
127
+ return {
128
+ persist,
129
+ searchTerm: searchTerms.join(" ") || undefined,
130
+ error: `Unknown /${commandName} option "${token}". Supported option: --default.`,
131
+ };
132
+ }
133
+ searchTerms.push(token);
134
+ }
135
+ return { persist, searchTerm: searchTerms.join(" ") || undefined };
136
+ }
102
137
  const ANTHROPIC_SUBSCRIPTION_AUTH_WARNING = "Anthropic subscription auth is active. Third-party harness usage draws from extra usage and is billed per token, not your Claude plan limits. Manage extra usage at https://claude.ai/settings/usage. Disable this warning in /settings.";
103
138
  function isAnthropicSubscriptionAuthKey(apiKey) {
104
139
  return typeof apiKey === "string" && apiKey.startsWith("sk-ant-oat");
@@ -130,6 +165,11 @@ export function formatResumeCommand(sessionManager) {
130
165
  function hasDefaultModelProvider(providerId) {
131
166
  return providerId in defaultModelPerProvider;
132
167
  }
168
+ function llamaCppPostLoginGuidance(actionLabel, loadedModelCount) {
169
+ return loadedModelCount === 0
170
+ ? `${actionLabel}. No llama.cpp models are loaded. Use /llama to load a model, then /model to select it.`
171
+ : `${actionLabel}. Use /model to select a loaded llama.cpp model, or /llama to manage models.`;
172
+ }
133
173
  const AUTH_TYPE_ORDER = { oauth: 0, api_key: 1 };
134
174
  function createFuzzyAutocompleteItems(items, prefix, getSearchText, toAutocompleteItem) {
135
175
  const filtered = fuzzyFilter(items, prefix, getSearchText);
@@ -446,6 +486,15 @@ export class InteractiveMode {
446
486
  const modelCommand = slashCommands.find((command) => command.name === "model");
447
487
  if (modelCommand) {
448
488
  modelCommand.getArgumentCompletions = (prefix) => {
489
+ const trimmedPrefix = prefix.trimStart();
490
+ if (trimmedPrefix.startsWith("--") && !trimmedPrefix.includes(" ")) {
491
+ return "--default".startsWith(trimmedPrefix)
492
+ ? [{ value: "--default ", label: "--default", description: "Set as startup default" }]
493
+ : null;
494
+ }
495
+ const parsed = parseDefaultFlagArgs("model", prefix);
496
+ if (parsed.error)
497
+ return null;
449
498
  const models = this.session.scopedModels.length > 0
450
499
  ? this.session.scopedModels.map((s) => s.model)
451
500
  : this.session.modelRuntime.getAvailableSnapshot();
@@ -458,10 +507,31 @@ export class InteractiveMode {
458
507
  name: m.name,
459
508
  label: `${m.provider}/${m.id}`,
460
509
  }));
461
- return createFuzzyAutocompleteItems(items, prefix, getModelSearchText, (item) => ({
462
- value: item.label,
510
+ const searchPrefix = parsed.persist ? (parsed.searchTerm ?? "") : prefix;
511
+ return createFuzzyAutocompleteItems(items, searchPrefix, getModelSearchText, (item) => ({
512
+ value: parsed.persist ? `--default ${item.label}` : item.label,
463
513
  label: item.id,
464
- description: item.provider,
514
+ description: parsed.persist ? `${item.provider} · set as startup default` : item.provider,
515
+ }));
516
+ };
517
+ }
518
+ const thinkingCommand = slashCommands.find((command) => command.name === "thinking");
519
+ if (thinkingCommand) {
520
+ thinkingCommand.getArgumentCompletions = (prefix) => {
521
+ const trimmedPrefix = prefix.trimStart();
522
+ if (trimmedPrefix.startsWith("--") && !trimmedPrefix.includes(" ")) {
523
+ return "--default".startsWith(trimmedPrefix)
524
+ ? [{ value: "--default ", label: "--default", description: "Set as startup default" }]
525
+ : null;
526
+ }
527
+ const parsed = parseDefaultFlagArgs("thinking", prefix);
528
+ if (parsed.error)
529
+ return null;
530
+ const searchPrefix = parsed.persist ? (parsed.searchTerm ?? "") : prefix;
531
+ return createFuzzyAutocompleteItems(this.session.getAvailableThinkingLevels(), searchPrefix, (level) => level, (level) => ({
532
+ value: parsed.persist ? `--default ${level}` : level,
533
+ label: level,
534
+ description: parsed.persist ? "set as startup default" : undefined,
465
535
  }));
466
536
  };
467
537
  }
@@ -679,7 +749,7 @@ export class InteractiveMode {
679
749
  const accent = (text) => theme.fg("accent", text);
680
750
  const dim = (text) => theme.fg("dim", text);
681
751
  const muted = (text) => theme.fg("muted", text);
682
- const logo = theme.bold(theme.fg("accent", APP_NAME)) + theme.fg("dim", ` v${this.version}`);
752
+ const _logo = theme.bold(theme.fg("accent", APP_NAME)) + theme.fg("dim", ` v${this.version}`);
683
753
  // Welcome screen (central): ASCII logo + environment status + quick commands
684
754
  const asciiLogo = [
685
755
  " █████╗ ██████╗ █████╗",
@@ -836,7 +906,18 @@ export class InteractiveMode {
836
906
  }
837
907
  });
838
908
  // Show startup warnings
839
- const { migratedProviders, modelFallbackMessage, initialMessage, initialImages, initialMessages } = this.options;
909
+ const { migratedProviders, startupDiagnostics, modelFallbackMessage, initialMessage, initialImages, initialMessages, } = this.options;
910
+ for (const diagnostic of startupDiagnostics ?? []) {
911
+ if (diagnostic.type === "error") {
912
+ this.showError(diagnostic.message);
913
+ }
914
+ else if (diagnostic.type === "warning") {
915
+ this.showWarning(diagnostic.message);
916
+ }
917
+ else {
918
+ this.showStatus(diagnostic.message);
919
+ }
920
+ }
840
921
  if (migratedProviders && migratedProviders.length > 0) {
841
922
  this.showWarning(`Migrated credentials to auth.json: ${migratedProviders.join(", ")}`);
842
923
  }
@@ -2373,9 +2454,23 @@ export class InteractiveMode {
2373
2454
  return;
2374
2455
  }
2375
2456
  if (text === "/model" || text.startsWith("/model ")) {
2376
- const searchTerm = text.startsWith("/model ") ? text.slice(7).trim() : undefined;
2457
+ const args = parseDefaultFlagArgs("model", text.startsWith("/model ") ? text.slice(7).trim() : undefined);
2377
2458
  this.editor.setText("");
2378
- await this.handleModelCommand(searchTerm);
2459
+ if (args.error) {
2460
+ this.showError(args.error);
2461
+ return;
2462
+ }
2463
+ await this.handleModelCommand(args.searchTerm, { persist: args.persist });
2464
+ return;
2465
+ }
2466
+ if (text === "/thinking" || text.startsWith("/thinking ")) {
2467
+ const args = parseDefaultFlagArgs("thinking", text.startsWith("/thinking ") ? text.slice(10).trim() : undefined);
2468
+ this.editor.setText("");
2469
+ if (args.error) {
2470
+ this.showError(args.error);
2471
+ return;
2472
+ }
2473
+ this.handleThinkingCommand(args.searchTerm, { persist: args.persist });
2379
2474
  return;
2380
2475
  }
2381
2476
  if (text === "/export" || text.startsWith("/export ")) {
@@ -2429,6 +2524,24 @@ export class InteractiveMode {
2429
2524
  void this.handleVaultCommand(args);
2430
2525
  return;
2431
2526
  }
2527
+ if (text === "/goal" || text.startsWith("/goal ")) {
2528
+ const args = text.startsWith("/goal ") ? text.slice(6).trim() : "";
2529
+ this.editor.setText("");
2530
+ void this.handleGoalCommand(args);
2531
+ return;
2532
+ }
2533
+ if (text === "/graph" || text.startsWith("/graph ")) {
2534
+ const args = text.startsWith("/graph ") ? text.slice(7).trim() : "";
2535
+ this.editor.setText("");
2536
+ void this.handleGraphCommand(args);
2537
+ return;
2538
+ }
2539
+ if (text === "/workflow" || text.startsWith("/workflow ")) {
2540
+ const args = text.startsWith("/workflow ") ? text.slice(10).trim() : "";
2541
+ this.editor.setText("");
2542
+ void this.handleWorkflowCommand(args);
2543
+ return;
2544
+ }
2432
2545
  if (text === "/changelog") {
2433
2546
  this.handleChangelogCommand();
2434
2547
  this.editor.setText("");
@@ -2584,6 +2697,9 @@ export class InteractiveMode {
2584
2697
  this.showStatus(event.message);
2585
2698
  }
2586
2699
  break;
2700
+ case "prompt_optimization":
2701
+ this.showPromptOptimization(event);
2702
+ break;
2587
2703
  case "agent_start":
2588
2704
  this.pendingTools.clear();
2589
2705
  if (this.settingsManager.getShowTerminalProgress()) {
@@ -2788,9 +2904,21 @@ export class InteractiveMode {
2788
2904
  }
2789
2905
  }
2790
2906
  else if (event.result) {
2907
+ const entries = this.sessionManager.buildContextEntries();
2908
+ if (entries[0]?.type !== "compaction") {
2909
+ throw new Error("Completed compaction is missing from the session context");
2910
+ }
2791
2911
  this.chatContainer.clear();
2792
- this.rebuildChatFromMessages();
2912
+ // The latest compaction is prepended for model context; append it below at its chronological position.
2913
+ this.renderSessionEntries(entries.slice(1));
2793
2914
  this.addMessageToChat(createCompactionSummaryMessage(event.result.summary, event.result.tokensBefore, new Date().toISOString()));
2915
+ if (event.result.usage) {
2916
+ this.addCompactionCostNotice({
2917
+ type: "compaction_cost",
2918
+ kind: "compaction",
2919
+ usage: event.result.usage,
2920
+ });
2921
+ }
2794
2922
  this.footer.invalidate();
2795
2923
  }
2796
2924
  else if (event.errorMessage) {
@@ -2882,6 +3010,23 @@ export class InteractiveMode {
2882
3010
  * If multiple status messages are emitted back-to-back (without anything else being added to the chat),
2883
3011
  * we update the previous status line instead of appending new ones to avoid log spam.
2884
3012
  */
3013
+ /** Muestra cómo el optimizador mejoró el prompt (o qué pregunta aclarar). */
3014
+ showPromptOptimization(event) {
3015
+ const component = new PromptOptimization(this.ui, event);
3016
+ if (this.streamingComponent) {
3017
+ const idx = this.chatContainer.children.indexOf(this.streamingComponent);
3018
+ if (idx >= 0) {
3019
+ this.chatContainer.children.splice(idx, 0, component);
3020
+ }
3021
+ else {
3022
+ this.chatContainer.addChild(component);
3023
+ }
3024
+ }
3025
+ else {
3026
+ this.chatContainer.addChild(component);
3027
+ }
3028
+ this.ui.requestRender();
3029
+ }
2885
3030
  showStatus(message) {
2886
3031
  const children = this.chatContainer.children;
2887
3032
  const last = children.length > 0 ? children[children.length - 1] : undefined;
@@ -2936,8 +3081,7 @@ export class InteractiveMode {
2936
3081
  // (sensitive data will not be stored in memory).
2937
3082
  const text = customMessageText(message.content);
2938
3083
  this.chatContainer.addChild(new Spacer(1));
2939
- this.chatContainer.addChild(new Text(theme.fg("warning", "⚠️ ") + theme.bold(theme.fg("warning", "Ada Memory")) +
2940
- "\n" + text, 1, 0));
3084
+ this.chatContainer.addChild(new Text(`${theme.fg("warning", "⚠️ ") + theme.bold(theme.fg("warning", "Ada Memory"))}\n${text}`, 1, 0));
2941
3085
  break;
2942
3086
  }
2943
3087
  const renderer = this.session.extensionRunner.getMessageRenderer(message.customType);
@@ -3021,6 +3165,10 @@ export class InteractiveMode {
3021
3165
  this.addCustomEntryToChat(item);
3022
3166
  continue;
3023
3167
  }
3168
+ if (isCompactionCostNotice(item)) {
3169
+ this.addCompactionCostNotice(item);
3170
+ continue;
3171
+ }
3024
3172
  const message = item;
3025
3173
  // Assistant messages need special handling for tool calls
3026
3174
  if (message.role === "assistant") {
@@ -3088,10 +3236,28 @@ export class InteractiveMode {
3088
3236
  if (entry.type === "custom") {
3089
3237
  return [entry];
3090
3238
  }
3091
- return sessionEntryToContextMessages(entry);
3239
+ const messages = sessionEntryToContextMessages(entry);
3240
+ if ((entry.type === "compaction" || entry.type === "branch_summary") && entry.usage && messages.length > 0) {
3241
+ return [...messages, { type: "compaction_cost", kind: entry.type, usage: entry.usage }];
3242
+ }
3243
+ return messages;
3092
3244
  });
3093
3245
  this.renderSessionItems(items, options);
3094
3246
  }
3247
+ /**
3248
+ * Render billing usage for a compaction or branch summary. The notice is derived
3249
+ * from persisted summary usage and is not stored as a separate session entry.
3250
+ */
3251
+ addCompactionCostNotice(notice) {
3252
+ if (!this.settingsManager.getShowCacheMissNotices())
3253
+ return;
3254
+ const { usage } = notice;
3255
+ const tokens = usage.input + usage.output + usage.cacheRead + usage.cacheWrite;
3256
+ const cost = usage.cost.total >= 0.01 ? ` (~$${usage.cost.total.toFixed(2)})` : "";
3257
+ const label = notice.kind === "compaction" ? "Compaction" : "Branch summary";
3258
+ this.chatContainer.addChild(new Spacer(1));
3259
+ this.chatContainer.addChild(new Text(theme.fg("warning", `${label}: ${formatTokens(tokens)} tokens billed${cost}`), 1, 0));
3260
+ }
3095
3261
  /**
3096
3262
  * Show a transcript notice when a completed assistant message paid for a
3097
3263
  * significant cache miss. Only states observable facts: the miss itself,
@@ -3728,21 +3894,34 @@ export class InteractiveMode {
3728
3894
  showSettingsSelector() {
3729
3895
  this.showSelector((done) => {
3730
3896
  let selector;
3897
+ const defaultProvider = this.settingsManager.getDefaultProvider();
3898
+ const defaultModelId = this.settingsManager.getDefaultModel();
3899
+ const defaultModel = defaultProvider && defaultModelId ? `${defaultProvider}/${defaultModelId}` : "not set";
3731
3900
  selector = new SettingsSelectorComponent({
3732
3901
  autoCompact: this.session.autoCompactionEnabled,
3902
+ defaultModel,
3903
+ availableDefaultModels: this.session.modelRuntime.getAvailableSnapshot(),
3733
3904
  showImages: this.settingsManager.getShowImages(),
3734
3905
  imageWidthCells: this.settingsManager.getImageWidthCells(),
3735
3906
  autoResizeImages: this.settingsManager.getImageAutoResize(),
3736
3907
  blockImages: this.settingsManager.getBlockImages(),
3737
3908
  projectMemory: this.settingsManager.getProjectMemoryEnabled(),
3738
3909
  memoryMode: this.settingsManager.getMemoryMode(),
3910
+ // Ada Intelligence Engine (§16.2)
3911
+ workflowsEnabled: this.settingsManager.getWorkflowsEnabled(),
3912
+ goalEngineEnabled: this.settingsManager.getGoalEngineEnabled(),
3913
+ goalWorkTier: this.settingsManager.getGoalWorkTier(),
3914
+ goalMaxTurns: this.settingsManager.getGoalMaxTurns(),
3915
+ goalRepeatTolerance: this.settingsManager.getGoalRepeatTolerance(),
3916
+ promptOptimizerMode: this.settingsManager.getPromptOptimizerMode(),
3739
3917
  enableSkillCommands: this.settingsManager.getEnableSkillCommands(),
3740
3918
  steeringMode: this.session.steeringMode,
3741
3919
  followUpMode: this.session.followUpMode,
3742
3920
  transport: this.settingsManager.getTransport(),
3743
3921
  httpIdleTimeoutMs: this.settingsManager.getHttpIdleTimeoutMs(),
3744
- thinkingLevel: this.session.thinkingLevel,
3745
- availableThinkingLevels: this.session.getAvailableThinkingLevels(),
3922
+ thinkingLevel: this.settingsManager.getDefaultThinkingLevel() ?? DEFAULT_THINKING_LEVEL,
3923
+ availableThinkingLevels: [...THINKING_LEVEL_OPTIONS],
3924
+ modelThinkingLevels: this.settingsManager.getAllModelThinkingLevels(),
3746
3925
  currentTheme: this.themeController.getThemeSelection() || "dark",
3747
3926
  terminalTheme: this.themeController.getTerminalTheme(),
3748
3927
  availableThemes: getAvailableThemes(),
@@ -3770,6 +3949,19 @@ export class InteractiveMode {
3770
3949
  this.session.setAutoCompactionEnabled(enabled);
3771
3950
  this.footer.setAutoCompactEnabled(enabled);
3772
3951
  },
3952
+ onDefaultModelChange: async (model) => {
3953
+ try {
3954
+ await this.session.setModel(model, { persist: true });
3955
+ this.footer.invalidate();
3956
+ this.updateEditorBorderColor();
3957
+ this.showStatus(`Default model: ${model.provider}/${model.id}`);
3958
+ void this.maybeWarnAboutAnthropicSubscriptionAuth(model);
3959
+ this.checkDaxnutsEasterEgg(model);
3960
+ }
3961
+ catch (error) {
3962
+ this.showError(error instanceof Error ? error.message : String(error));
3963
+ }
3964
+ },
3773
3965
  onShowImagesChange: (enabled) => {
3774
3966
  this.settingsManager.setShowImages(enabled);
3775
3967
  for (const child of this.chatContainer.children) {
@@ -3800,6 +3992,26 @@ export class InteractiveMode {
3800
3992
  // Rebuild the prompt so the new injection mode takes effect.
3801
3993
  this.session.rebuildSystemPrompt();
3802
3994
  },
3995
+ onWorkflowsEnabledChange: (enabled) => {
3996
+ this.settingsManager.setWorkflowsEnabled(enabled);
3997
+ },
3998
+ onPromptOptimizerModeChange: (mode) => {
3999
+ this.settingsManager.setPromptOptimizerMode(mode);
4000
+ // Aplica el modo en la sesión en vivo (sin reiniciar).
4001
+ this.session.setPromptOptimizerMode(mode);
4002
+ },
4003
+ onGoalEngineEnabledChange: (enabled) => {
4004
+ this.settingsManager.setGoalEngineEnabled(enabled);
4005
+ },
4006
+ onGoalWorkTierChange: (tier) => {
4007
+ this.settingsManager.setGoalWorkTier(tier);
4008
+ },
4009
+ onGoalMaxTurnsChange: (turns) => {
4010
+ this.settingsManager.setGoalMaxTurns(turns);
4011
+ },
4012
+ onRepeatToleranceChange: (tolerance) => {
4013
+ this.settingsManager.setGoalRepeatTolerance(tolerance);
4014
+ },
3803
4015
  onEnableSkillCommandsChange: (enabled) => {
3804
4016
  this.settingsManager.setEnableSkillCommands(enabled);
3805
4017
  this.setupAutocompleteProvider();
@@ -3820,10 +4032,31 @@ export class InteractiveMode {
3820
4032
  this.showStatus(`HTTP idle timeout: ${formatHttpIdleTimeoutMs(timeoutMs)}`);
3821
4033
  },
3822
4034
  onThinkingLevelChange: (level) => {
3823
- this.session.setThinkingLevel(level);
4035
+ this.session.setThinkingLevel(level, { persist: true });
3824
4036
  this.footer.invalidate();
3825
4037
  this.updateEditorBorderColor();
3826
4038
  },
4039
+ onModelThinkingLevelChange: (provider, modelId, level) => {
4040
+ this.settingsManager.setModelThinkingLevel(provider, modelId, level);
4041
+ // If the override is for the current model, apply it to the session too
4042
+ const current = this.session.model;
4043
+ if (current && current.provider === provider && current.id === modelId) {
4044
+ this.session.setThinkingLevel(level);
4045
+ this.footer.invalidate();
4046
+ this.updateEditorBorderColor();
4047
+ }
4048
+ },
4049
+ onModelThinkingLevelRemove: (provider, modelId) => {
4050
+ this.settingsManager.removeModelThinkingLevel(provider, modelId);
4051
+ // If the override was for the current model, revert to global default
4052
+ const current = this.session.model;
4053
+ if (current && current.provider === provider && current.id === modelId) {
4054
+ const globalDefault = this.settingsManager.getDefaultThinkingLevel() ?? DEFAULT_THINKING_LEVEL;
4055
+ this.session.setThinkingLevel(globalDefault);
4056
+ this.footer.invalidate();
4057
+ this.updateEditorBorderColor();
4058
+ }
4059
+ },
3827
4060
  onThemeChange: (themeSetting) => {
3828
4061
  this.settingsManager.setTheme(themeSetting);
3829
4062
  void this.themeController.setThemeSetting(themeSetting);
@@ -3943,18 +4176,56 @@ export class InteractiveMode {
3943
4176
  return { component: selector, focus: selector.getSettingsList() };
3944
4177
  });
3945
4178
  }
3946
- async handleModelCommand(searchTerm) {
4179
+ handleThinkingCommand(searchTerm, options = {}) {
4180
+ const availableLevels = this.session.getAvailableThinkingLevels();
3947
4181
  if (!searchTerm) {
3948
- this.showModelSelector();
4182
+ this.showThinkingSelector(options);
4183
+ return;
4184
+ }
4185
+ const normalized = searchTerm.trim().toLowerCase();
4186
+ const level = availableLevels.find((candidate) => candidate.toLowerCase() === normalized);
4187
+ if (!level) {
4188
+ this.showError(`Unknown thinking level "${searchTerm}". Available levels: ${availableLevels.join(", ")}.`);
4189
+ return;
4190
+ }
4191
+ this.selectThinkingLevel(level, options.persist === true);
4192
+ }
4193
+ selectThinkingLevel(level, persist) {
4194
+ try {
4195
+ this.session.setThinkingLevel(level, { persist });
4196
+ this.footer.invalidate();
4197
+ this.updateEditorBorderColor();
4198
+ this.showStatus(persist ? `Default thinking level: ${level}` : `Thinking level: ${level}`);
4199
+ }
4200
+ catch (error) {
4201
+ this.showError(error instanceof Error ? error.message : String(error));
4202
+ }
4203
+ }
4204
+ showThinkingSelector(options = {}) {
4205
+ this.showSelector((done) => {
4206
+ const selectLevel = (level, persist) => {
4207
+ this.selectThinkingLevel(level, persist);
4208
+ done();
4209
+ };
4210
+ const selector = new ThinkingSelectorComponent(this.session.thinkingLevel ?? DEFAULT_THINKING_LEVEL, this.session.getAvailableThinkingLevels(), (level) => selectLevel(level, options.persist === true), () => {
4211
+ done();
4212
+ this.ui.requestRender();
4213
+ }, (level) => selectLevel(level, true));
4214
+ return { component: selector, focus: selector };
4215
+ });
4216
+ }
4217
+ async handleModelCommand(searchTerm, options = {}) {
4218
+ if (!searchTerm) {
4219
+ this.showModelSelector(undefined, options);
3949
4220
  return;
3950
4221
  }
3951
4222
  const model = await this.findExactModelMatch(searchTerm);
3952
4223
  if (model) {
3953
4224
  try {
3954
- await this.session.setModel(model);
4225
+ await this.session.setModel(model, { persist: options.persist === true });
3955
4226
  this.footer.invalidate();
3956
4227
  this.updateEditorBorderColor();
3957
- this.showStatus(`Model: ${model.id}`);
4228
+ this.showStatus(options.persist ? `Default model: ${model.provider}/${model.id}` : `Model: ${model.id}`);
3958
4229
  void this.maybeWarnAboutAnthropicSubscriptionAuth(model);
3959
4230
  this.checkDaxnutsEasterEgg(model);
3960
4231
  }
@@ -3963,7 +4234,7 @@ export class InteractiveMode {
3963
4234
  }
3964
4235
  return;
3965
4236
  }
3966
- this.showModelSelector(searchTerm);
4237
+ this.showModelSelector(searchTerm, options);
3967
4238
  }
3968
4239
  async findExactModelMatch(searchTerm) {
3969
4240
  const cachedModels = this.session.scopedModels.length > 0
@@ -4078,15 +4349,15 @@ export class InteractiveMode {
4078
4349
  return { component: selector, focus: selector };
4079
4350
  });
4080
4351
  }
4081
- showModelSelector(initialSearchInput) {
4352
+ showModelSelector(initialSearchInput, options = {}) {
4082
4353
  this.showSelector((done) => {
4083
- const selector = new ModelSelectorComponent(this.ui, this.session.model, this.settingsManager, this.session.modelRuntime, this.session.scopedModels, async (model) => {
4354
+ const selectModel = async (model, persist) => {
4084
4355
  try {
4085
- await this.session.setModel(model);
4356
+ await this.session.setModel(model, { persist });
4086
4357
  this.footer.invalidate();
4087
4358
  this.updateEditorBorderColor();
4088
4359
  done();
4089
- this.showStatus(`Model: ${model.id}`);
4360
+ this.showStatus(persist ? `Default model: ${model.provider}/${model.id}` : `Model: ${model.id}`);
4090
4361
  void this.maybeWarnAboutAnthropicSubscriptionAuth(model);
4091
4362
  this.checkDaxnutsEasterEgg(model);
4092
4363
  }
@@ -4094,10 +4365,11 @@ export class InteractiveMode {
4094
4365
  done();
4095
4366
  this.showError(error instanceof Error ? error.message : String(error));
4096
4367
  }
4097
- }, () => {
4368
+ };
4369
+ const selector = new ModelSelectorComponent(this.ui, this.session.model, this.session.modelRuntime, this.session.scopedModels, (model) => selectModel(model, options.persist === true), () => {
4098
4370
  done();
4099
4371
  this.ui.requestRender();
4100
- }, initialSearchInput);
4372
+ }, initialSearchInput, (model) => selectModel(model, true));
4101
4373
  return { component: selector, focus: selector, dispose: () => selector.dispose() };
4102
4374
  });
4103
4375
  }
@@ -4653,7 +4925,11 @@ export class InteractiveMode {
4653
4925
  if (isUnknownModel(previousModel)) {
4654
4926
  const availableModels = this.session.modelRuntime.getAvailableSnapshot();
4655
4927
  const providerModels = availableModels.filter((model) => model.provider === providerId);
4656
- if (!hasDefaultModelProvider(providerId)) {
4928
+ // Matches LLAMA_PROVIDER_ID from extensions/llama/provider.ts; kept inline to avoid coupling interactive mode to the built-in extension.
4929
+ if (providerId === "llama.cpp") {
4930
+ selectionError = llamaCppPostLoginGuidance(actionLabel, providerModels.length);
4931
+ }
4932
+ else if (!hasDefaultModelProvider(providerId)) {
4657
4933
  selectionError = `${actionLabel}, but no default model is configured for provider "${providerId}". Use /model to select a model.`;
4658
4934
  }
4659
4935
  else if (providerModels.length === 0) {
@@ -4667,7 +4943,7 @@ export class InteractiveMode {
4667
4943
  }
4668
4944
  else {
4669
4945
  try {
4670
- await this.session.setModel(selectedModel);
4946
+ await this.session.setModel(selectedModel, { persist: true });
4671
4947
  }
4672
4948
  catch (error) {
4673
4949
  selectedModel = undefined;
@@ -5251,7 +5527,10 @@ export class InteractiveMode {
5251
5527
  let info = `${theme.bold("🧠 Ada Memory")}\n\n`;
5252
5528
  info += `${theme.fg("dim", "Enabled:")} ${status.enabled ? "yes" : "no"} · ${theme.fg("dim", "Mode:")} ${status.mode}\n`;
5253
5529
  info += `${theme.fg("dim", "Indexes:")} ${status.memoryIndexDocs} memory docs · ${status.sessionIndexDocs} session docs\n\n`;
5254
- info += entries.length > 0 ? entries.join("\n") : theme.fg("dim", "No memory entries yet. Ask the agent to remember something, or use memory_add.");
5530
+ info +=
5531
+ entries.length > 0
5532
+ ? entries.join("\n")
5533
+ : theme.fg("dim", "No memory entries yet. Ask the agent to remember something, or use memory_add.");
5255
5534
  this.chatContainer.addChild(new Spacer(1));
5256
5535
  this.chatContainer.addChild(new Text(info, 1, 0));
5257
5536
  this.ui.requestRender();
@@ -5295,7 +5574,7 @@ export class InteractiveMode {
5295
5574
  const entries = await memoryEngine.auditEntries(25);
5296
5575
  const lines = [
5297
5576
  `${theme.bold("🛡️ Memory audit")}`,
5298
- `${theme.fg("dim", "Integrity:")} ${integrity.valid ? theme.fg("success", "OK (" + integrity.entriesChecked + " entries)") : theme.fg("error", `TAMPERED at ${integrity.tamperedAt ?? "?"}`)}`,
5577
+ `${theme.fg("dim", "Integrity:")} ${integrity.valid ? theme.fg("success", `OK (${integrity.entriesChecked} entries)`) : theme.fg("error", `TAMPERED at ${integrity.tamperedAt ?? "?"}`)}`,
5299
5578
  ];
5300
5579
  if (entries.length === 0) {
5301
5580
  lines.push(theme.fg("dim", "No audit entries yet."));
@@ -5358,7 +5637,10 @@ export class InteractiveMode {
5358
5637
  return;
5359
5638
  }
5360
5639
  vault.add(name, value);
5361
- show([`✅ '${name}' saved to the project vault (encrypted).`, " Use @vault:" + name + " in a message to pass it to the agent."]);
5640
+ show([
5641
+ `✅ '${name}' saved to the project vault (encrypted).`,
5642
+ ` Use @vault:${name} in a message to pass it to the agent.`,
5643
+ ]);
5362
5644
  return;
5363
5645
  }
5364
5646
  case "session": {
@@ -5406,7 +5688,7 @@ export class InteractiveMode {
5406
5688
  }
5407
5689
  if (!name) {
5408
5690
  const names = available
5409
- .map((e) => ` ${e.name} (${e.source === "session" ? "sesión" : "proyecto"}${e.category ? " · " + e.category : ""})`)
5691
+ .map((e) => ` ${e.name} (${e.source === "session" ? "sesión" : "proyecto"}${e.category ? ` · ${e.category}` : ""})`)
5410
5692
  .join("\n");
5411
5693
  show([
5412
5694
  "Secretos disponibles:",
@@ -5418,12 +5700,13 @@ export class InteractiveMode {
5418
5700
  }
5419
5701
  const exists = available.some((e) => e.name === name);
5420
5702
  show(exists
5421
- ? [`Listo. Escribe esto en el chat: @vault:${name}`, "El agente recibirá el valor; nunca se persiste en la sesión."]
5703
+ ? [
5704
+ `Listo. Escribe esto en el chat: @vault:${name}`,
5705
+ "El agente recibirá el valor; nunca se persiste en la sesión.",
5706
+ ]
5422
5707
  : [`No existe el secreto '${name}'. /vault list para verlos.`]);
5423
5708
  return;
5424
5709
  }
5425
- case "list":
5426
- case "status":
5427
5710
  default: {
5428
5711
  const status = vault.status();
5429
5712
  const entries = vault.list();
@@ -5447,6 +5730,366 @@ export class InteractiveMode {
5447
5730
  }
5448
5731
  }
5449
5732
  }
5733
+ /** /goal <intent> | status | approve | pause | resume | list — Goal Engine CLI (§16.4). */
5734
+ async handleGoalCommand(args) {
5735
+ const goalEngine = this.session.resourceLoader.getGoalEngine?.();
5736
+ const show = (lines) => {
5737
+ this.chatContainer.addChild(new Spacer(1));
5738
+ this.chatContainer.addChild(new Text(lines.join("\n"), 1, 0));
5739
+ this.ui.requestRender();
5740
+ };
5741
+ if (!goalEngine) {
5742
+ show(["Goal Engine unavailable."]);
5743
+ return;
5744
+ }
5745
+ const [action, ...rest] = args.split(/\s+/).filter(Boolean);
5746
+ switch (action ?? "list") {
5747
+ case "list": {
5748
+ const goals = await goalEngine.list().catch(() => []);
5749
+ show([
5750
+ "Goals:",
5751
+ ...(goals.length === 0
5752
+ ? [" (none)"]
5753
+ : goals.map((g) => ` ${g.status === "active" ? "◆" : "·"} ${g.id} [${g.status}] ${g.goal}`)),
5754
+ ]);
5755
+ return;
5756
+ }
5757
+ case "status": {
5758
+ const id = rest[0] ?? "";
5759
+ if (!id) {
5760
+ show(["Uso: /goal status <id>"]);
5761
+ return;
5762
+ }
5763
+ const state = await goalEngine.get(id);
5764
+ if (!state) {
5765
+ show([`Goal no encontrado: ${id}`]);
5766
+ return;
5767
+ }
5768
+ show([
5769
+ `Goal: ${state.goal}`,
5770
+ ` id: ${state.id} · fase: ${state.phase} · estado: ${state.status}`,
5771
+ ` turnos: ${state.turnsUsed}/25 · repetidos: ${state.repeatedTurns}`,
5772
+ ` iteración: ${state.iteration}${state.iterations.length > 0 ? ` (${state.iterations.length} registrada${state.iterations.length === 1 ? "" : "s"})` : ""}`,
5773
+ ...(state.judge.lastVerdict
5774
+ ? [` juez: ${state.judge.lastVerdict} — ${state.judge.lastReason ?? ""}`]
5775
+ : []),
5776
+ ...(state.replanRationale ? [` último replan: ${state.replanRationale}`] : []),
5777
+ ...(state.evidence.length > 0 ? [` evidencia: ${state.evidence.length} citas`] : []),
5778
+ ...(state.tasks.length > 0
5779
+ ? [
5780
+ ` plan (${state.tasks.length}):`,
5781
+ ...state.tasks.map((t) => ` ${t.status === "done" ? "✓" : t.status === "running" ? "◐" : "○"} ${t.title}`),
5782
+ ]
5783
+ : []),
5784
+ ]);
5785
+ return;
5786
+ }
5787
+ case "replan": {
5788
+ // P1: re-planificación manual (también automática tras continue).
5789
+ const id = rest[0] ?? "";
5790
+ if (!id) {
5791
+ show(["Uso: /goal replan <id>"]);
5792
+ return;
5793
+ }
5794
+ const state = await goalEngine.replan(id).catch((e) => {
5795
+ show(["No se pudo re-planificar:", ` ${e instanceof Error ? e.message : String(e)}`]);
5796
+ return null;
5797
+ });
5798
+ if (state)
5799
+ show([
5800
+ `Re-planificado → iteración ${state.iteration}`,
5801
+ ` ${state.replanRationale ?? ""}`,
5802
+ ...state.tasks.map((t) => ` ○ ${t.title}`),
5803
+ ]);
5804
+ return;
5805
+ }
5806
+ case "add": {
5807
+ // P2: añadir sub-tarea en cualquier fase.
5808
+ const id = rest[0] ?? "";
5809
+ const title = rest.slice(1).join(" ");
5810
+ if (!id || !title) {
5811
+ show(["Uso: /goal add <id> <título>"]);
5812
+ return;
5813
+ }
5814
+ const state = await goalEngine.addTask(id, title).catch(() => null);
5815
+ show(state
5816
+ ? [`Añadida: ${title}`, ` plan (${state.tasks.length} sub-tareas)`]
5817
+ : ["No se pudo añadir (id inválido)"]);
5818
+ return;
5819
+ }
5820
+ case "rm": {
5821
+ // P2: quitar sub-tarea.
5822
+ const id = rest[0] ?? "";
5823
+ const taskId = rest[1] ?? "";
5824
+ if (!id || !taskId) {
5825
+ show(["Uso: /goal rm <id> <taskId>"]);
5826
+ return;
5827
+ }
5828
+ const state = await goalEngine.get(id);
5829
+ if (!state) {
5830
+ show(["Goal no encontrado"]);
5831
+ return;
5832
+ }
5833
+ const { state: next } = reduceGoal(state, { type: "goal_task_remove", taskId }, {
5834
+ repeatTolerance: 1,
5835
+ });
5836
+ await goalEngine.commit(state, next);
5837
+ show([`Quitada. Plan (${next.tasks.length}):`, ...next.tasks.map((t) => ` ${t.title}`)]);
5838
+ return;
5839
+ }
5840
+ case "mv": {
5841
+ // P2: reordenar sub-tarea.
5842
+ const id = rest[0] ?? "";
5843
+ const taskId = rest[1] ?? "";
5844
+ const dir = rest[2] === "down" ? "down" : "up";
5845
+ if (!id || !taskId) {
5846
+ show(["Uso: /goal mv <id> <taskId> up|down"]);
5847
+ return;
5848
+ }
5849
+ const state = await goalEngine.get(id);
5850
+ if (!state) {
5851
+ show(["Goal no encontrado"]);
5852
+ return;
5853
+ }
5854
+ const { state: next } = reduceGoal(state, { type: "goal_task_move", taskId, dir }, {
5855
+ repeatTolerance: 1,
5856
+ });
5857
+ await goalEngine.commit(state, next);
5858
+ show([`Reordenado. Plan (${next.tasks.length}):`, ...next.tasks.map((t) => ` ${t.title}`)]);
5859
+ return;
5860
+ }
5861
+ case "new": {
5862
+ const intent = rest.join(" ");
5863
+ if (!intent) {
5864
+ show(["Uso: /goal new <intent>"]);
5865
+ return;
5866
+ }
5867
+ const state = await goalEngine.createGoal({
5868
+ goal: intent,
5869
+ doneCriteria: [],
5870
+ verifyCommand: "",
5871
+ });
5872
+ show([`Contrato creado: ${state.id}`, " Aprueba con: /goal approve <id>", ` ${intent}`]);
5873
+ return;
5874
+ }
5875
+ case "approve": {
5876
+ const id = rest[0] ?? "";
5877
+ if (!id) {
5878
+ show(["Uso: /goal approve <id>"]);
5879
+ return;
5880
+ }
5881
+ const state = await goalEngine.approve(id).catch(() => null);
5882
+ show(state ? [`Goal activo: ${state.goal}`] : ["No se pudo aprobar (id inválido)"]);
5883
+ return;
5884
+ }
5885
+ case "pause": {
5886
+ const id = rest[0] ?? "";
5887
+ if (!id) {
5888
+ show(["Uso: /goal pause <id>"]);
5889
+ return;
5890
+ }
5891
+ const state = await goalEngine.pause(id, "pausado desde CLI");
5892
+ show([`Pausado: ${state.status}`]);
5893
+ return;
5894
+ }
5895
+ case "resume": {
5896
+ const id = rest[0] ?? "";
5897
+ if (!id) {
5898
+ show(["Uso: /goal resume <id>"]);
5899
+ return;
5900
+ }
5901
+ const state = await goalEngine.resume(id).catch(() => null);
5902
+ show(state ? [`Reanudado: ${state.status}`] : ["No se pudo reanudar"]);
5903
+ return;
5904
+ }
5905
+ case "plan-on": {
5906
+ // P5: modo plan-only (persistente).
5907
+ this.settingsManager.setPlanOnlyEnabled(true);
5908
+ show(["Plan-only ACTIVADO: el goal no ejecutará hasta aprobar el plan."]);
5909
+ return;
5910
+ }
5911
+ case "plan-off": {
5912
+ this.settingsManager.setPlanOnlyEnabled(false);
5913
+ show(["Plan-only desactivado: el goal lanza sub-tareas automáticamente."]);
5914
+ return;
5915
+ }
5916
+ default:
5917
+ show([
5918
+ "Subcomandos: new <intent> | list | status <id> | approve <id> | pause <id> | resume <id> | replan <id> | add <id> <título> | rm <id> <taskId> | mv <id> <taskId> up|down | plan-on | plan-off",
5919
+ ]);
5920
+ return;
5921
+ }
5922
+ }
5923
+ /** /graph gaps | context <id> | search <term> | add — Grafo CLI (§16.4). */
5924
+ async handleGraphCommand(args) {
5925
+ const graph = this.session.resourceLoader.getGraph?.();
5926
+ const show = (lines) => {
5927
+ this.chatContainer.addChild(new Spacer(1));
5928
+ this.chatContainer.addChild(new Text(lines.join("\n"), 1, 0));
5929
+ this.ui.requestRender();
5930
+ };
5931
+ if (!graph) {
5932
+ show(["Graph unavailable."]);
5933
+ return;
5934
+ }
5935
+ const [action, ...rest] = args.split(/\s+/).filter(Boolean);
5936
+ switch (action ?? "gaps") {
5937
+ case "gaps": {
5938
+ const gaps = graph.gaps();
5939
+ show([
5940
+ "Gaps (spine incompleto):",
5941
+ ...(gaps.length === 0 ? [" ✓ spine completo"] : gaps.map((g) => ` ${g.id}: falta ${g.missing}`)),
5942
+ ]);
5943
+ return;
5944
+ }
5945
+ case "context": {
5946
+ const id = rest[0] ?? "";
5947
+ if (!id) {
5948
+ show(["Uso: /graph context <id>"]);
5949
+ return;
5950
+ }
5951
+ const res = graph.context(id);
5952
+ if (!res.ok || !res.data || !res.data.node) {
5953
+ show([`Error: ${res.error ?? "no encontrado"}`]);
5954
+ return;
5955
+ }
5956
+ show([
5957
+ `Nodo: ${res.data.node.id} [${res.data.node.type}]`,
5958
+ ` ${res.data.node.description}`,
5959
+ ` vecinos: ${res.data.neighbors.length}`,
5960
+ ...res.data.neighbors.map((e) => ` ${e.subject} --${e.predicate}--> ${e.object}`),
5961
+ ]);
5962
+ return;
5963
+ }
5964
+ case "search": {
5965
+ const term = rest.join(" ");
5966
+ if (!term) {
5967
+ show(["Uso: /graph search <term>"]);
5968
+ return;
5969
+ }
5970
+ const hits = graph.search(term);
5971
+ show([
5972
+ `Resultados para "${term}":`,
5973
+ ...(hits.length === 0 ? [" (ninguno)"] : hits.map((h) => ` ${h.node.id} — ${h.node.description}`)),
5974
+ ]);
5975
+ return;
5976
+ }
5977
+ case "gate": {
5978
+ const res = graph.gate();
5979
+ show(res.data?.passed ? ["✓ Gate superado"] : [`✗ Gate bloqueado:`, ...(res.data?.failures ?? [])]);
5980
+ return;
5981
+ }
5982
+ default:
5983
+ show(["Subcomandos: gaps | context <id> | search <term> | gate"]);
5984
+ return;
5985
+ }
5986
+ }
5987
+ /** /workflow run <name> [k=v...] | list | status <id> | abort <id> — CLI del engine (§16.4). */
5988
+ async handleWorkflowCommand(args) {
5989
+ const manager = this.session.resourceLoader.getWorkflowManager?.();
5990
+ const show = (lines) => {
5991
+ this.chatContainer.addChild(new Spacer(1));
5992
+ this.chatContainer.addChild(new Text(lines.join("\n"), 1, 0));
5993
+ this.ui.requestRender();
5994
+ };
5995
+ if (!manager) {
5996
+ show(["Workflow manager unavailable."]);
5997
+ return;
5998
+ }
5999
+ const [action, ...rest] = args.split(/\s+/).filter(Boolean);
6000
+ switch (action ?? "list") {
6001
+ case "list": {
6002
+ const runs = await manager.list().catch(() => []);
6003
+ show([
6004
+ "Workflow runs:",
6005
+ ...(runs.length === 0
6006
+ ? [" (ninguno)"]
6007
+ : runs.slice(0, 20).map((r) => ` ${r.runId} [${r.status}] ${r.name} — ${r.updatedAt}`)),
6008
+ ]);
6009
+ return;
6010
+ }
6011
+ case "status": {
6012
+ const runId = rest[0] ?? "";
6013
+ if (!runId) {
6014
+ show(["Uso: /workflow status <runId>"]);
6015
+ return;
6016
+ }
6017
+ const state = await manager.state(runId).catch(() => null);
6018
+ if (!state) {
6019
+ show([`Run no encontrado: ${runId}`]);
6020
+ return;
6021
+ }
6022
+ show([
6023
+ `Run: ${state.name} (${state.runId})`,
6024
+ ` estado: ${state.status} · fase: ${state.currentPhase ?? "—"}`,
6025
+ ` agentes: ${state.agentCount} · tokens: ${state.tokenUsage.total} · coste: $${state.tokenUsage.cost.toFixed(4)}`,
6026
+ ]);
6027
+ return;
6028
+ }
6029
+ case "abort": {
6030
+ const runId = rest[0] ?? "";
6031
+ if (!runId) {
6032
+ show(["Uso: /workflow abort <runId>"]);
6033
+ return;
6034
+ }
6035
+ const aborted = manager.abort(runId);
6036
+ show(aborted ? [`Abort solicitado: ${runId}`] : [`No se pudo abortar (¿run inexistente?): ${runId}`]);
6037
+ return;
6038
+ }
6039
+ case "run": {
6040
+ const name = rest[0];
6041
+ if (!name) {
6042
+ show([
6043
+ "Uso: /workflow run <name> [k=v...]",
6044
+ " builtins: deep_research · code_review · product_build · codebase_audit · multi_perspective",
6045
+ ]);
6046
+ return;
6047
+ }
6048
+ // args k=v
6049
+ const wfArgs = {};
6050
+ for (const part of rest.slice(1)) {
6051
+ const eq = part.indexOf("=");
6052
+ if (eq > 0)
6053
+ wfArgs[part.slice(0, eq)] = part.slice(eq + 1);
6054
+ }
6055
+ const script = await this.resolveBuiltinWorkflow(name);
6056
+ if (!script) {
6057
+ show([`Workflow no encontrado: ${name}`]);
6058
+ return;
6059
+ }
6060
+ // Confirmación de coste estimado (fail-closed).
6061
+ const ok = await this.confirm(`Lanzar workflow "${name}" con ${Object.keys(wfArgs).length} args. Coste estimado: variable (ver settings.workflows.budget). ¿Continuar?`);
6062
+ if (!ok) {
6063
+ show(["Cancelado."]);
6064
+ return;
6065
+ }
6066
+ show([`Lanzando ${name}… (progreso: /workflow list, /workflow status <runId>)`]);
6067
+ void manager
6068
+ .execute(script, { args: wfArgs, sessionId: this.session.sessionManager.getSessionId() })
6069
+ .then((r) => show([`✓ ${name} terminó (${r.runId}).`]))
6070
+ .catch((e) => show([`✗ ${name} falló: ${e instanceof Error ? e.message : String(e)}`]));
6071
+ return;
6072
+ }
6073
+ default:
6074
+ show(["Subcomandos: run <name> [k=v...] | list | status <runId> | abort <runId>"]);
6075
+ return;
6076
+ }
6077
+ }
6078
+ /**
6079
+ * Confirmación fail-closed del TUI: pide "y"/"yes" explícito en el input
6080
+ * de diálogo. Cualquier otra respuesta (o escape) = NO.
6081
+ */
6082
+ async confirm(prompt) {
6083
+ const answer = await this.showExtensionInput(`${prompt} [y/N]`, "y");
6084
+ const normalized = (answer ?? "").trim().toLowerCase();
6085
+ return normalized === "y" || normalized === "yes";
6086
+ }
6087
+ /** Resuelve un workflow builtin (deep_research, code_review, …) a su script. */
6088
+ /** Resuelve un workflow por nombre: builtin o script guardado del usuario. */
6089
+ async resolveBuiltinWorkflow(name) {
6090
+ const { resolveWorkflowScriptByName } = await import("../../core/workflows/resolve-script.js");
6091
+ return resolveWorkflowScriptByName(this.session.resourceLoader.getAgentDir(), name)?.script ?? null;
6092
+ }
5450
6093
  handleChangelogCommand() {
5451
6094
  const changelogPath = getChangelogPath();
5452
6095
  const allEntries = parseChangelog(changelogPath);