agent-nuvira 1.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (379) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +891 -0
  3. package/dist/agent-sdk/src/agent.d.ts +118 -0
  4. package/dist/agent-sdk/src/agent.d.ts.map +1 -0
  5. package/dist/agent-sdk/src/agent.js +88 -0
  6. package/dist/agent-sdk/src/agent.js.map +1 -0
  7. package/dist/agent-sdk/src/index.d.ts +33 -0
  8. package/dist/agent-sdk/src/index.d.ts.map +1 -0
  9. package/dist/agent-sdk/src/index.js +32 -0
  10. package/dist/agent-sdk/src/index.js.map +1 -0
  11. package/dist/agent-sdk/src/register.d.ts +70 -0
  12. package/dist/agent-sdk/src/register.d.ts.map +1 -0
  13. package/dist/agent-sdk/src/register.js +181 -0
  14. package/dist/agent-sdk/src/register.js.map +1 -0
  15. package/dist/agent-sdk/src/scaffold.d.ts +50 -0
  16. package/dist/agent-sdk/src/scaffold.d.ts.map +1 -0
  17. package/dist/agent-sdk/src/scaffold.js +291 -0
  18. package/dist/agent-sdk/src/scaffold.js.map +1 -0
  19. package/dist/agent-sdk/src/testing.d.ts +187 -0
  20. package/dist/agent-sdk/src/testing.d.ts.map +1 -0
  21. package/dist/agent-sdk/src/testing.js +243 -0
  22. package/dist/agent-sdk/src/testing.js.map +1 -0
  23. package/dist/agent-sdk/src/types.d.ts +202 -0
  24. package/dist/agent-sdk/src/types.d.ts.map +1 -0
  25. package/dist/agent-sdk/src/types.js +11 -0
  26. package/dist/agent-sdk/src/types.js.map +1 -0
  27. package/dist/agents/agent.d.ts +132 -0
  28. package/dist/agents/agent.d.ts.map +1 -0
  29. package/dist/agents/agent.js +19 -0
  30. package/dist/agents/agent.js.map +1 -0
  31. package/dist/agents/agents/context-gatherer.d.ts +42 -0
  32. package/dist/agents/agents/context-gatherer.d.ts.map +1 -0
  33. package/dist/agents/agents/context-gatherer.js +366 -0
  34. package/dist/agents/agents/context-gatherer.js.map +1 -0
  35. package/dist/agents/agents/debugger.d.ts +58 -0
  36. package/dist/agents/agents/debugger.d.ts.map +1 -0
  37. package/dist/agents/agents/debugger.js +257 -0
  38. package/dist/agents/agents/debugger.js.map +1 -0
  39. package/dist/agents/agents/git-agent.d.ts +34 -0
  40. package/dist/agents/agents/git-agent.d.ts.map +1 -0
  41. package/dist/agents/agents/git-agent.js +200 -0
  42. package/dist/agents/agents/git-agent.js.map +1 -0
  43. package/dist/agents/agents/github-release-agent.d.ts +65 -0
  44. package/dist/agents/agents/github-release-agent.d.ts.map +1 -0
  45. package/dist/agents/agents/github-release-agent.js +439 -0
  46. package/dist/agents/agents/github-release-agent.js.map +1 -0
  47. package/dist/agents/agents/package-agent.d.ts +33 -0
  48. package/dist/agents/agents/package-agent.d.ts.map +1 -0
  49. package/dist/agents/agents/package-agent.js +233 -0
  50. package/dist/agents/agents/package-agent.js.map +1 -0
  51. package/dist/agents/agents/planner.d.ts +26 -0
  52. package/dist/agents/agents/planner.d.ts.map +1 -0
  53. package/dist/agents/agents/planner.js +222 -0
  54. package/dist/agents/agents/planner.js.map +1 -0
  55. package/dist/agents/agents/reviewer.d.ts +34 -0
  56. package/dist/agents/agents/reviewer.d.ts.map +1 -0
  57. package/dist/agents/agents/reviewer.js +159 -0
  58. package/dist/agents/agents/reviewer.js.map +1 -0
  59. package/dist/agents/agents/runner.d.ts +73 -0
  60. package/dist/agents/agents/runner.d.ts.map +1 -0
  61. package/dist/agents/agents/runner.js +299 -0
  62. package/dist/agents/agents/runner.js.map +1 -0
  63. package/dist/agents/agents/security-agent.d.ts +33 -0
  64. package/dist/agents/agents/security-agent.d.ts.map +1 -0
  65. package/dist/agents/agents/security-agent.js +184 -0
  66. package/dist/agents/agents/security-agent.js.map +1 -0
  67. package/dist/agents/agents/tester.d.ts +96 -0
  68. package/dist/agents/agents/tester.d.ts.map +1 -0
  69. package/dist/agents/agents/tester.js +410 -0
  70. package/dist/agents/agents/tester.js.map +1 -0
  71. package/dist/agents/agents/writer.d.ts +51 -0
  72. package/dist/agents/agents/writer.d.ts.map +1 -0
  73. package/dist/agents/agents/writer.js +384 -0
  74. package/dist/agents/agents/writer.js.map +1 -0
  75. package/dist/agents/context-vault.d.ts +49 -0
  76. package/dist/agents/context-vault.d.ts.map +1 -0
  77. package/dist/agents/context-vault.js +134 -0
  78. package/dist/agents/context-vault.js.map +1 -0
  79. package/dist/agents/orchestrator.d.ts +97 -0
  80. package/dist/agents/orchestrator.d.ts.map +1 -0
  81. package/dist/agents/orchestrator.js +696 -0
  82. package/dist/agents/orchestrator.js.map +1 -0
  83. package/dist/agents/utils/file-tree.d.ts +28 -0
  84. package/dist/agents/utils/file-tree.d.ts.map +1 -0
  85. package/dist/agents/utils/file-tree.js +93 -0
  86. package/dist/agents/utils/file-tree.js.map +1 -0
  87. package/dist/cli/agent.d.ts +25 -0
  88. package/dist/cli/agent.d.ts.map +1 -0
  89. package/dist/cli/agent.js +374 -0
  90. package/dist/cli/agent.js.map +1 -0
  91. package/dist/cli/benchmark.d.ts +24 -0
  92. package/dist/cli/benchmark.d.ts.map +1 -0
  93. package/dist/cli/benchmark.js +235 -0
  94. package/dist/cli/benchmark.js.map +1 -0
  95. package/dist/cli/cache.d.ts +12 -0
  96. package/dist/cli/cache.d.ts.map +1 -0
  97. package/dist/cli/cache.js +58 -0
  98. package/dist/cli/cache.js.map +1 -0
  99. package/dist/cli/chat.d.ts +37 -0
  100. package/dist/cli/chat.d.ts.map +1 -0
  101. package/dist/cli/chat.js +393 -0
  102. package/dist/cli/chat.js.map +1 -0
  103. package/dist/cli/commands.d.ts +24 -0
  104. package/dist/cli/commands.d.ts.map +1 -0
  105. package/dist/cli/commands.js +18 -0
  106. package/dist/cli/commands.js.map +1 -0
  107. package/dist/cli/config.d.ts +19 -0
  108. package/dist/cli/config.d.ts.map +1 -0
  109. package/dist/cli/config.js +162 -0
  110. package/dist/cli/config.js.map +1 -0
  111. package/dist/cli/dashboard.d.ts +34 -0
  112. package/dist/cli/dashboard.d.ts.map +1 -0
  113. package/dist/cli/dashboard.js +126 -0
  114. package/dist/cli/dashboard.js.map +1 -0
  115. package/dist/cli/doctor.d.ts +68 -0
  116. package/dist/cli/doctor.d.ts.map +1 -0
  117. package/dist/cli/doctor.js +585 -0
  118. package/dist/cli/doctor.js.map +1 -0
  119. package/dist/cli/edit.d.ts +11 -0
  120. package/dist/cli/edit.d.ts.map +1 -0
  121. package/dist/cli/edit.js +86 -0
  122. package/dist/cli/edit.js.map +1 -0
  123. package/dist/cli/execute.d.ts +25 -0
  124. package/dist/cli/execute.d.ts.map +1 -0
  125. package/dist/cli/execute.js +186 -0
  126. package/dist/cli/execute.js.map +1 -0
  127. package/dist/cli/federation.d.ts +31 -0
  128. package/dist/cli/federation.d.ts.map +1 -0
  129. package/dist/cli/federation.js +387 -0
  130. package/dist/cli/federation.js.map +1 -0
  131. package/dist/cli/history.d.ts +22 -0
  132. package/dist/cli/history.d.ts.map +1 -0
  133. package/dist/cli/history.js +140 -0
  134. package/dist/cli/history.js.map +1 -0
  135. package/dist/cli/init.d.ts +49 -0
  136. package/dist/cli/init.d.ts.map +1 -0
  137. package/dist/cli/init.js +423 -0
  138. package/dist/cli/init.js.map +1 -0
  139. package/dist/cli/learn.d.ts +31 -0
  140. package/dist/cli/learn.d.ts.map +1 -0
  141. package/dist/cli/learn.js +320 -0
  142. package/dist/cli/learn.js.map +1 -0
  143. package/dist/cli/memory.d.ts +38 -0
  144. package/dist/cli/memory.d.ts.map +1 -0
  145. package/dist/cli/memory.js +295 -0
  146. package/dist/cli/memory.js.map +1 -0
  147. package/dist/cli/model-picker.d.ts +18 -0
  148. package/dist/cli/model-picker.d.ts.map +1 -0
  149. package/dist/cli/model-picker.js +225 -0
  150. package/dist/cli/model-picker.js.map +1 -0
  151. package/dist/cli/models.d.ts +11 -0
  152. package/dist/cli/models.d.ts.map +1 -0
  153. package/dist/cli/models.js +132 -0
  154. package/dist/cli/models.js.map +1 -0
  155. package/dist/cli/plan.d.ts +11 -0
  156. package/dist/cli/plan.d.ts.map +1 -0
  157. package/dist/cli/plan.js +94 -0
  158. package/dist/cli/plan.js.map +1 -0
  159. package/dist/cli/plugins.d.ts +15 -0
  160. package/dist/cli/plugins.d.ts.map +1 -0
  161. package/dist/cli/plugins.js +123 -0
  162. package/dist/cli/plugins.js.map +1 -0
  163. package/dist/cli/router.d.ts +20 -0
  164. package/dist/cli/router.d.ts.map +1 -0
  165. package/dist/cli/router.js +142 -0
  166. package/dist/cli/router.js.map +1 -0
  167. package/dist/cli/run.d.ts +22 -0
  168. package/dist/cli/run.d.ts.map +1 -0
  169. package/dist/cli/run.js +110 -0
  170. package/dist/cli/run.js.map +1 -0
  171. package/dist/cli/sandbox.d.ts +27 -0
  172. package/dist/cli/sandbox.d.ts.map +1 -0
  173. package/dist/cli/sandbox.js +264 -0
  174. package/dist/cli/sandbox.js.map +1 -0
  175. package/dist/cli/sdk.d.ts +27 -0
  176. package/dist/cli/sdk.d.ts.map +1 -0
  177. package/dist/cli/sdk.js +204 -0
  178. package/dist/cli/sdk.js.map +1 -0
  179. package/dist/cli/stats.d.ts +18 -0
  180. package/dist/cli/stats.d.ts.map +1 -0
  181. package/dist/cli/stats.js +78 -0
  182. package/dist/cli/stats.js.map +1 -0
  183. package/dist/cli/team.d.ts +42 -0
  184. package/dist/cli/team.d.ts.map +1 -0
  185. package/dist/cli/team.js +473 -0
  186. package/dist/cli/team.js.map +1 -0
  187. package/dist/cli/workflow.d.ts +27 -0
  188. package/dist/cli/workflow.d.ts.map +1 -0
  189. package/dist/cli/workflow.js +347 -0
  190. package/dist/cli/workflow.js.map +1 -0
  191. package/dist/config/manager.d.ts +37 -0
  192. package/dist/config/manager.d.ts.map +1 -0
  193. package/dist/config/manager.js +147 -0
  194. package/dist/config/manager.js.map +1 -0
  195. package/dist/config/types.d.ts +53 -0
  196. package/dist/config/types.d.ts.map +1 -0
  197. package/dist/config/types.js +2 -0
  198. package/dist/config/types.js.map +1 -0
  199. package/dist/context/cache.d.ts +27 -0
  200. package/dist/context/cache.d.ts.map +1 -0
  201. package/dist/context/cache.js +116 -0
  202. package/dist/context/cache.js.map +1 -0
  203. package/dist/context/history.d.ts +87 -0
  204. package/dist/context/history.d.ts.map +1 -0
  205. package/dist/context/history.js +249 -0
  206. package/dist/context/history.js.map +1 -0
  207. package/dist/context/parser.d.ts +61 -0
  208. package/dist/context/parser.d.ts.map +1 -0
  209. package/dist/context/parser.js +194 -0
  210. package/dist/context/parser.js.map +1 -0
  211. package/dist/federation/client.d.ts +49 -0
  212. package/dist/federation/client.d.ts.map +1 -0
  213. package/dist/federation/client.js +239 -0
  214. package/dist/federation/client.js.map +1 -0
  215. package/dist/federation/protocol.d.ts +155 -0
  216. package/dist/federation/protocol.d.ts.map +1 -0
  217. package/dist/federation/protocol.js +57 -0
  218. package/dist/federation/protocol.js.map +1 -0
  219. package/dist/federation/server.d.ts +25 -0
  220. package/dist/federation/server.d.ts.map +1 -0
  221. package/dist/federation/server.js +401 -0
  222. package/dist/federation/server.js.map +1 -0
  223. package/dist/index.d.ts +67 -0
  224. package/dist/index.d.ts.map +1 -0
  225. package/dist/index.js +93 -0
  226. package/dist/index.js.map +1 -0
  227. package/dist/inference/factory.d.ts +20 -0
  228. package/dist/inference/factory.d.ts.map +1 -0
  229. package/dist/inference/factory.js +46 -0
  230. package/dist/inference/factory.js.map +1 -0
  231. package/dist/inference/gemini-adapter.d.ts +17 -0
  232. package/dist/inference/gemini-adapter.d.ts.map +1 -0
  233. package/dist/inference/gemini-adapter.js +176 -0
  234. package/dist/inference/gemini-adapter.js.map +1 -0
  235. package/dist/inference/groq-adapter.d.ts +17 -0
  236. package/dist/inference/groq-adapter.d.ts.map +1 -0
  237. package/dist/inference/groq-adapter.js +103 -0
  238. package/dist/inference/groq-adapter.js.map +1 -0
  239. package/dist/inference/interface.d.ts +49 -0
  240. package/dist/inference/interface.d.ts.map +1 -0
  241. package/dist/inference/interface.js +2 -0
  242. package/dist/inference/interface.js.map +1 -0
  243. package/dist/inference/local-adapter.d.ts +35 -0
  244. package/dist/inference/local-adapter.d.ts.map +1 -0
  245. package/dist/inference/local-adapter.js +311 -0
  246. package/dist/inference/local-adapter.js.map +1 -0
  247. package/dist/inference/model-catalog.d.ts +53 -0
  248. package/dist/inference/model-catalog.d.ts.map +1 -0
  249. package/dist/inference/model-catalog.js +306 -0
  250. package/dist/inference/model-catalog.js.map +1 -0
  251. package/dist/inference/nim-adapter.d.ts +17 -0
  252. package/dist/inference/nim-adapter.d.ts.map +1 -0
  253. package/dist/inference/nim-adapter.js +103 -0
  254. package/dist/inference/nim-adapter.js.map +1 -0
  255. package/dist/inference/openrouter-adapter.d.ts +17 -0
  256. package/dist/inference/openrouter-adapter.d.ts.map +1 -0
  257. package/dist/inference/openrouter-adapter.js +105 -0
  258. package/dist/inference/openrouter-adapter.js.map +1 -0
  259. package/dist/inference/sse.d.ts +20 -0
  260. package/dist/inference/sse.d.ts.map +1 -0
  261. package/dist/inference/sse.js +91 -0
  262. package/dist/inference/sse.js.map +1 -0
  263. package/dist/learning/agent-stats.d.ts +109 -0
  264. package/dist/learning/agent-stats.d.ts.map +1 -0
  265. package/dist/learning/agent-stats.js +240 -0
  266. package/dist/learning/agent-stats.js.map +1 -0
  267. package/dist/learning/benchmark.d.ts +161 -0
  268. package/dist/learning/benchmark.d.ts.map +1 -0
  269. package/dist/learning/benchmark.js +589 -0
  270. package/dist/learning/benchmark.js.map +1 -0
  271. package/dist/learning/cost-tracker.d.ts +101 -0
  272. package/dist/learning/cost-tracker.d.ts.map +1 -0
  273. package/dist/learning/cost-tracker.js +224 -0
  274. package/dist/learning/cost-tracker.js.map +1 -0
  275. package/dist/learning/feedback.d.ts +88 -0
  276. package/dist/learning/feedback.d.ts.map +1 -0
  277. package/dist/learning/feedback.js +169 -0
  278. package/dist/learning/feedback.js.map +1 -0
  279. package/dist/learning/hybrid-router.d.ts +201 -0
  280. package/dist/learning/hybrid-router.d.ts.map +1 -0
  281. package/dist/learning/hybrid-router.js +450 -0
  282. package/dist/learning/hybrid-router.js.map +1 -0
  283. package/dist/learning/model-compare.d.ts +76 -0
  284. package/dist/learning/model-compare.d.ts.map +1 -0
  285. package/dist/learning/model-compare.js +252 -0
  286. package/dist/learning/model-compare.js.map +1 -0
  287. package/dist/learning/model-router.d.ts +68 -0
  288. package/dist/learning/model-router.d.ts.map +1 -0
  289. package/dist/learning/model-router.js +140 -0
  290. package/dist/learning/model-router.js.map +1 -0
  291. package/dist/learning/pattern-extractor.d.ts +99 -0
  292. package/dist/learning/pattern-extractor.d.ts.map +1 -0
  293. package/dist/learning/pattern-extractor.js +310 -0
  294. package/dist/learning/pattern-extractor.js.map +1 -0
  295. package/dist/learning/scorer.d.ts +51 -0
  296. package/dist/learning/scorer.d.ts.map +1 -0
  297. package/dist/learning/scorer.js +64 -0
  298. package/dist/learning/scorer.js.map +1 -0
  299. package/dist/learning/self-improver.d.ts +48 -0
  300. package/dist/learning/self-improver.d.ts.map +1 -0
  301. package/dist/learning/self-improver.js +161 -0
  302. package/dist/learning/self-improver.js.map +1 -0
  303. package/dist/memory/embedder.d.ts +65 -0
  304. package/dist/memory/embedder.d.ts.map +1 -0
  305. package/dist/memory/embedder.js +424 -0
  306. package/dist/memory/embedder.js.map +1 -0
  307. package/dist/memory/memory-integration.d.ts +56 -0
  308. package/dist/memory/memory-integration.d.ts.map +1 -0
  309. package/dist/memory/memory-integration.js +95 -0
  310. package/dist/memory/memory-integration.js.map +1 -0
  311. package/dist/memory/trajectory-store.d.ts +149 -0
  312. package/dist/memory/trajectory-store.d.ts.map +1 -0
  313. package/dist/memory/trajectory-store.js +476 -0
  314. package/dist/memory/trajectory-store.js.map +1 -0
  315. package/dist/memory/vector-store.d.ts +78 -0
  316. package/dist/memory/vector-store.d.ts.map +1 -0
  317. package/dist/memory/vector-store.js +186 -0
  318. package/dist/memory/vector-store.js.map +1 -0
  319. package/dist/plugins/agent-plugin.d.ts +73 -0
  320. package/dist/plugins/agent-plugin.d.ts.map +1 -0
  321. package/dist/plugins/agent-plugin.js +199 -0
  322. package/dist/plugins/agent-plugin.js.map +1 -0
  323. package/dist/plugins/registry.d.ts +61 -0
  324. package/dist/plugins/registry.d.ts.map +1 -0
  325. package/dist/plugins/registry.js +67 -0
  326. package/dist/plugins/registry.js.map +1 -0
  327. package/dist/sandbox/images.d.ts +31 -0
  328. package/dist/sandbox/images.d.ts.map +1 -0
  329. package/dist/sandbox/images.js +129 -0
  330. package/dist/sandbox/images.js.map +1 -0
  331. package/dist/sandbox/manager.d.ts +134 -0
  332. package/dist/sandbox/manager.d.ts.map +1 -0
  333. package/dist/sandbox/manager.js +470 -0
  334. package/dist/sandbox/manager.js.map +1 -0
  335. package/dist/sandbox/types.d.ts +113 -0
  336. package/dist/sandbox/types.d.ts.map +1 -0
  337. package/dist/sandbox/types.js +107 -0
  338. package/dist/sandbox/types.js.map +1 -0
  339. package/dist/security/scanner.d.ts +53 -0
  340. package/dist/security/scanner.d.ts.map +1 -0
  341. package/dist/security/scanner.js +271 -0
  342. package/dist/security/scanner.js.map +1 -0
  343. package/dist/team/config.d.ts +50 -0
  344. package/dist/team/config.d.ts.map +1 -0
  345. package/dist/team/config.js +108 -0
  346. package/dist/team/config.js.map +1 -0
  347. package/dist/team/memory.d.ts +63 -0
  348. package/dist/team/memory.d.ts.map +1 -0
  349. package/dist/team/memory.js +282 -0
  350. package/dist/team/memory.js.map +1 -0
  351. package/dist/team/review.d.ts +123 -0
  352. package/dist/team/review.d.ts.map +1 -0
  353. package/dist/team/review.js +293 -0
  354. package/dist/team/review.js.map +1 -0
  355. package/dist/utils/env.d.ts +19 -0
  356. package/dist/utils/env.d.ts.map +1 -0
  357. package/dist/utils/env.js +250 -0
  358. package/dist/utils/env.js.map +1 -0
  359. package/dist/utils/logger.d.ts +11 -0
  360. package/dist/utils/logger.d.ts.map +1 -0
  361. package/dist/utils/logger.js +45 -0
  362. package/dist/utils/logger.js.map +1 -0
  363. package/dist/web-dashboard/server.d.ts +59 -0
  364. package/dist/web-dashboard/server.d.ts.map +1 -0
  365. package/dist/web-dashboard/server.js +418 -0
  366. package/dist/web-dashboard/server.js.map +1 -0
  367. package/dist/workflow/registry.d.ts +127 -0
  368. package/dist/workflow/registry.d.ts.map +1 -0
  369. package/dist/workflow/registry.js +482 -0
  370. package/dist/workflow/registry.js.map +1 -0
  371. package/dist/workflow/templates.d.ts +93 -0
  372. package/dist/workflow/templates.d.ts.map +1 -0
  373. package/dist/workflow/templates.js +481 -0
  374. package/dist/workflow/templates.js.map +1 -0
  375. package/package.json +78 -0
  376. package/src/web-dashboard/public/assets/index-B08nDkSB.css +1 -0
  377. package/src/web-dashboard/public/assets/index-BKL8YOFD.js +135 -0
  378. package/src/web-dashboard/public/assets/index-BKL8YOFD.js.map +1 -0
  379. package/src/web-dashboard/public/index.html +13 -0
@@ -0,0 +1,696 @@
1
+ /**
2
+ * Orchestrator — The central coordinator of the multi-agent system.
3
+ *
4
+ * Responsibilities:
5
+ * 1. Accept a user goal and optionally a provider/model config
6
+ * 2. Create a ContextVault (shared context bus)
7
+ * 3. Build the project file tree and inject it for the Planner
8
+ * 4. Optionally retrieve memory context from past similar trajectories
9
+ * 5. Run the PlannerAgent to produce an execution plan
10
+ * 6. Execute tasks sequentially, respecting dependencies
11
+ * 7. Spawn the appropriate agent for each task
12
+ * 8. Apply file changes to disk
13
+ * 9. Execute runner commands and capture output
14
+ * 10. Optionally store the trajectory in memory
15
+ * 11. Synthesize and return the final result
16
+ *
17
+ * Called by the `agent-nuvira execute` CLI command.
18
+ */
19
+ import { existsSync, writeFileSync, mkdirSync } from 'node:fs';
20
+ import { dirname, isAbsolute, resolve } from 'node:path';
21
+ import inquirer from 'inquirer';
22
+ import { ProviderFactory } from '../inference/factory.js';
23
+ import { ConfigManager } from '../config/manager.js';
24
+ import { showModelPicker } from '../cli/model-picker.js';
25
+ import { logger } from '../utils/logger.js';
26
+ import { ContextVault } from './context-vault.js';
27
+ import { buildProjectFileTree, truncateTree } from './utils/file-tree.js';
28
+ import { PlannerAgent } from './agents/planner.js';
29
+ import { ContextGathererAgent } from './agents/context-gatherer.js';
30
+ import { WriterAgent } from './agents/writer.js';
31
+ import { ReviewerAgent } from './agents/reviewer.js';
32
+ import { RunnerAgent } from './agents/runner.js';
33
+ import { TesterAgent, cleanupSandbox } from './agents/tester.js';
34
+ import { DebuggerAgent } from './agents/debugger.js';
35
+ import { GitAgent } from './agents/git-agent.js';
36
+ import { PackageAgent } from './agents/package-agent.js';
37
+ import { GitHubReleaseAgent } from './agents/github-release-agent.js';
38
+ import { SecurityAgent } from './agents/security-agent.js';
39
+ import { scanForInjections, formatScanReport } from '../security/scanner.js';
40
+ import { buildAgentModelMap } from '../learning/model-router.js';
41
+ import { createReviewFromResult } from '../team/review.js';
42
+ // ─── DAG Integration (optional — dashboard may not be built) ─────────────────
43
+ /**
44
+ * Push a DAG update to the live dashboard, if the server is running.
45
+ * Uses dynamic import so the orchestrator doesn't crash if the dashboard
46
+ * module hasn't been built or isn't available.
47
+ */
48
+ let dagModule = undefined;
49
+ async function ensureDAGModule() {
50
+ if (dagModule !== undefined)
51
+ return; // already attempted (null = failed, object = loaded)
52
+ try {
53
+ dagModule = await import('../web-dashboard/server.js');
54
+ }
55
+ catch {
56
+ dagModule = null; // dashboard module not available — mark as failed
57
+ }
58
+ }
59
+ async function tryPushDAG(update) {
60
+ await ensureDAGModule();
61
+ if (dagModule)
62
+ dagModule.pushDAGUpdate(update);
63
+ }
64
+ async function tryUpdateDAGNode(nodeId, update) {
65
+ await ensureDAGModule();
66
+ if (dagModule)
67
+ dagModule.updateDAGNode(nodeId, update);
68
+ }
69
+ async function tryResetDAG() {
70
+ await ensureDAGModule();
71
+ if (dagModule)
72
+ dagModule.resetDAG();
73
+ }
74
+ // ─── Agent Registry ─────────────────────────────────────────────────────────
75
+ // ─── Spinner Icons ─────────────────────────────────────────────────────────
76
+ /** Icons for each agent type, shown in the spinner during execution */
77
+ const AGENT_ICONS = {
78
+ 'context-gatherer': '📂',
79
+ 'planner': '📋',
80
+ 'writer': '✏️',
81
+ 'reviewer': '👁️',
82
+ 'tester': '🧪',
83
+ 'debugger': '🐛',
84
+ 'runner': '▶️',
85
+ 'git': '🔀',
86
+ 'package': '📦',
87
+ 'github-release': '🏷️',
88
+ 'security': '🔒',
89
+ };
90
+ function createAgent(agentType, _options) {
91
+ switch (agentType) {
92
+ case 'context-gatherer':
93
+ return new ContextGathererAgent();
94
+ case 'planner':
95
+ return new PlannerAgent();
96
+ case 'writer':
97
+ return new WriterAgent();
98
+ case 'reviewer':
99
+ return new ReviewerAgent();
100
+ case 'runner':
101
+ return new RunnerAgent();
102
+ case 'tester':
103
+ return new TesterAgent();
104
+ case 'debugger':
105
+ return new DebuggerAgent();
106
+ case 'git':
107
+ return new GitAgent();
108
+ case 'package':
109
+ return new PackageAgent();
110
+ case 'github-release':
111
+ return new GitHubReleaseAgent();
112
+ case 'security':
113
+ return new SecurityAgent();
114
+ default:
115
+ return null;
116
+ }
117
+ }
118
+ // ─── Orchestrator ───────────────────────────────────────────────────────────
119
+ export class Orchestrator {
120
+ configManager;
121
+ constructor(configManager) {
122
+ this.configManager = configManager ?? new ConfigManager();
123
+ }
124
+ /**
125
+ * Execute a multi-agent pipeline for the given goal.
126
+ */
127
+ async execute(goal, options = {}) {
128
+ const startTime = Date.now();
129
+ const vault = new ContextVault(goal, process.cwd());
130
+ const defaultCallLLM = this.createLLMProvider(options);
131
+ const agentResults = [];
132
+ const contextFiles = [];
133
+ // ── 2b. Build project file tree and inject for Planner ────────────────
134
+ if (options.verbose)
135
+ logger.highlight('\n📂 Scanning project structure...');
136
+ try {
137
+ const fullTree = await buildProjectFileTree(process.cwd());
138
+ // Truncate to 100 lines max to avoid blowing token limits
139
+ const treeForPlanner = truncateTree(fullTree, 100);
140
+ vault.setMeta('projectFileTree', treeForPlanner);
141
+ if (options.verbose) {
142
+ const fileCount = fullTree.split('\n').filter((l) => l.includes('📄')).length;
143
+ logger.info(` Found ${fileCount} source files in project`);
144
+ }
145
+ }
146
+ catch (err) {
147
+ logger.debug(`File tree build failed (non-critical): ${err}`);
148
+ vault.setMeta('projectFileTree', '');
149
+ }
150
+ // ── 3. Memory Retrieval ──────────────────────────────────────────────
151
+ let memoryContext = '';
152
+ if (options.useMemory) {
153
+ if (options.verbose)
154
+ logger.highlight('\n🔍 Searching memory for similar past tasks...');
155
+ let patternContext = '';
156
+ try {
157
+ const { retrieveMemoryContext } = await import('../memory/memory-integration.js');
158
+ const memoryResult = await retrieveMemoryContext(goal, defaultCallLLM, 3);
159
+ memoryContext = memoryResult.fewShotContext;
160
+ // Also inject coding patterns if available
161
+ patternContext = memoryResult.patternContext || '';
162
+ if (options.verbose) {
163
+ if (memoryResult.trajectories.length > 0) {
164
+ logger.info(` Found ${memoryResult.trajectories.length} similar past trajectories`);
165
+ }
166
+ else {
167
+ logger.info(' No similar past tasks found in memory');
168
+ }
169
+ }
170
+ }
171
+ catch (err) {
172
+ logger.debug(`Memory retrieval failed: ${err}`);
173
+ }
174
+ // Inject memory context and patterns into vault for agents
175
+ if (memoryContext) {
176
+ vault.setMeta('memoryContext', memoryContext);
177
+ }
178
+ if (patternContext) {
179
+ vault.setMeta('patternContext', patternContext);
180
+ memoryContext += `\n${patternContext}`;
181
+ }
182
+ }
183
+ // ── 3b. Auto-route models ─────────────────────────────────────────────
184
+ if (options.autoRouteModels && !options.agentModels) {
185
+ const autoModels = buildAgentModelMap();
186
+ options.agentModels = autoModels;
187
+ if (options.verbose) {
188
+ logger.info(' Auto-routing models based on task type');
189
+ }
190
+ }
191
+ // ── 4. Planner (or pre-built plan from workflow template) ────────────
192
+ if (options.prefillPlan && options.prefillPlan.length > 0) {
193
+ for (const step of options.prefillPlan) {
194
+ vault.context.taskPlan.push({ ...step });
195
+ }
196
+ agentResults.push({ agent: 'Planner', success: true, summary: `Using pre-built '${options.prefillPlan.length}-step' workflow plan` });
197
+ if (options.verbose) {
198
+ logger.highlight('\n📋 Using workflow template plan...');
199
+ logger.info(` Using ${options.prefillPlan.length} pre-defined steps`);
200
+ for (const step of options.prefillPlan) {
201
+ logger.info(` [${step.agentType}] ${step.description}`);
202
+ }
203
+ }
204
+ }
205
+ else {
206
+ if (options.verbose)
207
+ logger.highlight('\n📋 Planning...');
208
+ const planResult = await this.runAgent(new PlannerAgent(), vault, defaultCallLLM, options);
209
+ agentResults.push({ agent: 'Planner', success: planResult.success, summary: planResult.summary });
210
+ if (!planResult.success) {
211
+ return this.buildResult(false, goal, agentResults, vault, {
212
+ error: planResult.error || 'Planning failed',
213
+ });
214
+ }
215
+ if (vault.context.taskPlan.length === 0) {
216
+ return this.buildResult(false, goal, agentResults, vault, {
217
+ error: 'Planner did not produce a valid task plan',
218
+ });
219
+ }
220
+ if (options.verbose) {
221
+ logger.info(` Created ${vault.context.taskPlan.length} task steps`);
222
+ for (const step of vault.context.taskPlan) {
223
+ logger.info(` [${step.agentType}] ${step.description}`);
224
+ }
225
+ }
226
+ }
227
+ // ── 4b. Push initial DAG state to dashboard ─────────────────────────
228
+ if (vault.context.taskPlan.length > 0) {
229
+ await tryResetDAG();
230
+ const nodes = vault.context.taskPlan.map((step) => ({
231
+ id: step.id,
232
+ agentType: step.agentType,
233
+ status: 'pending',
234
+ description: step.description,
235
+ }));
236
+ const edges = [];
237
+ for (const step of vault.context.taskPlan) {
238
+ for (const dep of step.dependsOn) {
239
+ edges.push({ from: dep, to: step.id });
240
+ }
241
+ }
242
+ await tryPushDAG({
243
+ pipelineId: goal,
244
+ pipelineDescription: goal.slice(0, 80),
245
+ nodes,
246
+ edges,
247
+ });
248
+ }
249
+ // ── 5. Execute tasks ─────────────────────────────────────────────────
250
+ if (options.verbose)
251
+ logger.highlight('\n⚡ Executing tasks...');
252
+ // Update spinner to show we've moved past planning into execution
253
+ if (options.spinner && vault.context.taskPlan.length > 0) {
254
+ const total = vault.context.taskPlan.length;
255
+ options.spinner.start(`⚡ Executing ${total} task${total !== 1 ? 's' : ''}...`);
256
+ }
257
+ for (let iteration = 0; iteration < 50; iteration++) {
258
+ if (vault.isComplete)
259
+ break;
260
+ const runnableTasks = vault.getRunnableTasks();
261
+ if (runnableTasks.length === 0 && !vault.isComplete) {
262
+ const stuck = vault.context.taskPlan.filter((s) => s.status === 'pending');
263
+ for (const s of stuck) {
264
+ const failedDep = vault.context.taskPlan.find((d) => s.dependsOn.includes(d.id) && d.status === 'failed');
265
+ const reason = failedDep
266
+ ? `Dependency failed: ${failedDep.id} (${failedDep.description.slice(0, 60)})`
267
+ : 'Deadlocked: dependencies could not be satisfied';
268
+ vault.updateTaskStatus(s.id, 'failed', reason);
269
+ }
270
+ break;
271
+ }
272
+ // Runner and sandbox agents need exclusive access (no parallel)
273
+ const exclusiveAgentTypes = ['tester', 'debugger', 'runner'];
274
+ const canParallel = runnableTasks.length > 1 &&
275
+ !runnableTasks.some((t) => exclusiveAgentTypes.includes(t.agentType));
276
+ if (canParallel) {
277
+ for (const task of runnableTasks) {
278
+ vault.updateTaskStatus(task.id, 'running');
279
+ }
280
+ if (options.verbose) {
281
+ logger.info(`\n ⚡ Running ${runnableTasks.length} tasks in parallel...`);
282
+ }
283
+ const taskPromises = runnableTasks.map((task) => this.executeSingleTask(task, vault, options, agentResults, contextFiles, defaultCallLLM));
284
+ await Promise.all(taskPromises);
285
+ }
286
+ else {
287
+ for (const task of runnableTasks) {
288
+ await this.executeSingleTask(task, vault, options, agentResults, contextFiles, defaultCallLLM);
289
+ }
290
+ }
291
+ }
292
+ // ── 6. Clean up sandbox if any ────────────────────────────────────────
293
+ const sandboxPath = vault.getMeta('sandboxPath');
294
+ if (sandboxPath) {
295
+ try {
296
+ cleanupSandbox(sandboxPath);
297
+ }
298
+ catch {
299
+ // Best-effort cleanup
300
+ }
301
+ }
302
+ // ── 6b. Review mode — create a review bundle instead of applying changes
303
+ let reviewId;
304
+ if (options.reviewMode && vault.context.fileChanges.filter(c => c.newContent || c.status === 'deleted').length > 0) {
305
+ const fileChanges = vault.context.fileChanges.map((c) => ({
306
+ path: c.path,
307
+ originalContent: c.originalContent,
308
+ newContent: c.newContent,
309
+ status: c.status,
310
+ }));
311
+ // Build a summary from agent results
312
+ const summaryLines = agentResults.map((r) => `${r.success ? '✅' : '❌'} ${r.agent}: ${r.summary.slice(0, 120)}`);
313
+ summaryLines.push('');
314
+ summaryLines.push(vault.getDiffSummary());
315
+ const fullSummary = summaryLines.join('\n');
316
+ const review = createReviewFromResult(goal, fileChanges, fullSummary, {
317
+ provider: options.provider,
318
+ model: options.model,
319
+ author: process.env.USER || 'agent-nuvira',
320
+ });
321
+ reviewId = review.id;
322
+ if (options.verbose) {
323
+ logger.highlight(`\n📋 Created review bundle: ${review.id}`);
324
+ logger.info(` Run \`buff team review show ${review.id}\` to view`);
325
+ logger.info(` Run \`buff team review approve ${review.id}\` then \`buff team review merge ${review.id}\` to apply`);
326
+ }
327
+ }
328
+ // ── 6c. Apply file changes ────────────────────────────────────────────
329
+ if (!options.reviewMode && !options.dryRun) {
330
+ const applied = this.applyFileChanges(vault);
331
+ if (applied > 0 && options.verbose) {
332
+ logger.success(`\n 💾 Applied ${applied} file change${applied !== 1 ? 's' : ''} to disk`);
333
+ }
334
+ }
335
+ else if (options.verbose && options.reviewMode) {
336
+ logger.info(' 📋 Review mode — changes saved as review bundle instead of written to disk');
337
+ }
338
+ // ── 6d. Collect runner output for display ────────────────────────────
339
+ let runOutput;
340
+ const runResult = vault.getMeta('runResult');
341
+ if (runResult) {
342
+ const lines = [];
343
+ lines.push(`$ ${runResult.command}`);
344
+ lines.push(`Exit code: ${runResult.exitCode} | Duration: ${runResult.duration}ms`);
345
+ if (runResult.stdout) {
346
+ lines.push('');
347
+ lines.push(runResult.stdout.slice(0, 2000)); // Limit displayed output
348
+ if (runResult.stdout.length > 2000) {
349
+ lines.push('... (output truncated)');
350
+ }
351
+ }
352
+ if (runResult.stderr && runResult.exitCode !== 0) {
353
+ lines.push('');
354
+ lines.push('stderr:');
355
+ lines.push(runResult.stderr.slice(0, 1000));
356
+ }
357
+ runOutput = lines.join('\n');
358
+ }
359
+ // ── 7. Store trajectory in memory + self-improvement loop ───────────
360
+ let trajectoryId = '';
361
+ if (options.useMemory) {
362
+ try {
363
+ const orchestrationSummary = {
364
+ success: !vault.hasFailedTasks,
365
+ goal,
366
+ summary: '',
367
+ tasksCompleted: vault.context.taskPlan.filter((s) => s.status === 'completed').length,
368
+ tasksTotal: vault.context.taskPlan.length,
369
+ agentResults,
370
+ fileChanges: vault.getDiffSummary(),
371
+ };
372
+ const { storeExecutionTrajectory } = await import('../memory/memory-integration.js');
373
+ trajectoryId = await storeExecutionTrajectory(orchestrationSummary, defaultCallLLM, vault.context.taskPlan, contextFiles, options.verbose);
374
+ // Self-improvement
375
+ try {
376
+ const { getSelfImprover } = await import('../learning/self-improver.js');
377
+ const improver = getSelfImprover();
378
+ await improver.processRun({ ...orchestrationSummary, trajectoryId }, defaultCallLLM, options.agentModels, options.verbose);
379
+ if (options.verbose && trajectoryId) {
380
+ logger.info(' Self-improvement stats saved. Run `buff learn optimize` to see recommendations.');
381
+ }
382
+ }
383
+ catch (err) {
384
+ logger.debug(`Self-improvement loop failed: ${err}`);
385
+ }
386
+ }
387
+ catch (err) {
388
+ logger.debug(`Trajectory storage failed: ${err}`);
389
+ }
390
+ }
391
+ // ── 8. Synthesize result ─────────────────────────────────────────────
392
+ const elapsed = ((Date.now() - startTime) / 1000).toFixed(1);
393
+ const completed = vault.context.taskPlan.filter((s) => s.status === 'completed').length;
394
+ const total = vault.context.taskPlan.length;
395
+ const hasFailures = vault.hasFailedTasks;
396
+ const summaryLines = [];
397
+ summaryLines.push(hasFailures
398
+ ? `Completed ${completed}/${total} tasks with some failures in ${elapsed}s`
399
+ : `Completed all ${completed} tasks successfully in ${elapsed}s`);
400
+ summaryLines.push('');
401
+ summaryLines.push('Changes:');
402
+ summaryLines.push(vault.getDiffSummary());
403
+ return this.buildResult(!hasFailures, goal, agentResults, vault, {
404
+ summary: summaryLines.join('\n'),
405
+ tasksCompleted: completed,
406
+ tasksTotal: total,
407
+ trajectoryId,
408
+ reviewId,
409
+ runOutput,
410
+ });
411
+ }
412
+ // ─── Private Helpers ──────────────────────────────────────────────────
413
+ createLLMProvider(options) {
414
+ const providerType = (options.provider ||
415
+ this.configManager.getAll().defaultProvider);
416
+ const { config } = this.configManager.getProviderConfig(providerType);
417
+ const provider = ProviderFactory.createProvider(providerType, config);
418
+ return async (prompt, inferenceOptions) => {
419
+ // Runtime injection guardrail
420
+ const injectionFindings = scanForInjections(prompt);
421
+ if (injectionFindings.length > 0) {
422
+ const report = formatScanReport({
423
+ passed: false,
424
+ findings: injectionFindings,
425
+ summary: 'Prompt injection detected — call blocked',
426
+ });
427
+ throw new Error(`Injection guardrail blocked LLM call:\n${report}`);
428
+ }
429
+ const mergedOptions = {
430
+ ...inferenceOptions,
431
+ model: options.model || inferenceOptions?.model || config.model,
432
+ temperature: inferenceOptions?.temperature ?? config.temperature ?? 0.7,
433
+ maxTokens: inferenceOptions?.maxTokens ?? config.maxTokens ?? 4096,
434
+ };
435
+ return provider.generate(prompt, mergedOptions);
436
+ };
437
+ }
438
+ async runAgent(agent, vault, callLLM, _options) {
439
+ try {
440
+ return await agent.execute(vault.context, callLLM);
441
+ }
442
+ catch (err) {
443
+ const msg = err instanceof Error ? err.message : String(err);
444
+ return { success: false, summary: `${agent.name} errored`, error: msg };
445
+ }
446
+ }
447
+ /**
448
+ * Create the onRateLimit callback that prompts the user.
449
+ * Returns undefined if we're in non-interactive mode (no TTY or dry-run).
450
+ */
451
+ createRateLimitHandler(options, currentModel) {
452
+ // Don't prompt in non-interactive or dry-run mode — just use auto-retry
453
+ if (options.dryRun || !process.stdout.isTTY) {
454
+ return undefined;
455
+ }
456
+ return async (info) => {
457
+ // ── Stop the CLI spinner before showing interactive prompts ──────
458
+ const spl = options.spinner;
459
+ if (spl)
460
+ spl.stop();
461
+ const waitSeconds = (info.retryAfterMs / 1000).toFixed(1);
462
+ const modelStr = info.modelName
463
+ ? `Model: ${info.modelName}`
464
+ : currentModel
465
+ ? `Model: ${currentModel}`
466
+ : '';
467
+ console.log('');
468
+ logger.warn(`\u26A0\uFE0F Rate limit hit for ${info.agentName}`);
469
+ logger.info(` ${modelStr}`);
470
+ logger.info(` Please wait ${waitSeconds}s before next request`);
471
+ console.log('');
472
+ const { action } = await inquirer.prompt([
473
+ {
474
+ type: 'list',
475
+ name: 'action',
476
+ message: `What would you like to do?`,
477
+ prefix: '\u{1F504}',
478
+ choices: [
479
+ { name: `\u23F3 Wait ${waitSeconds}s and retry`, value: 'retry' },
480
+ { name: '\u{1F500} Switch to a different model', value: 'switch-model' },
481
+ { name: '\u23ED Skip this step', value: 'skip' },
482
+ { name: '\u274C Abort the pipeline', value: 'abort' },
483
+ ],
484
+ },
485
+ ]);
486
+ console.log('');
487
+ // Helper to restart the spinner before returning
488
+ const restartSpinner = () => {
489
+ if (spl)
490
+ spl.start();
491
+ };
492
+ if (action === 'retry') {
493
+ logger.info(`Waiting ${waitSeconds}s as requested...`);
494
+ restartSpinner();
495
+ return { action: 'retry' };
496
+ }
497
+ if (action === 'skip') {
498
+ logger.info('Skipping this step.');
499
+ restartSpinner();
500
+ return { action: 'skip' };
501
+ }
502
+ if (action === 'abort') {
503
+ logger.error('Pipeline aborted by user.');
504
+ // Don't restart spinner — pipeline is ending
505
+ return { action: 'abort' };
506
+ }
507
+ if (action === 'switch-model') {
508
+ // Show the categorized model picker so the user can choose visually
509
+ const picked = await showModelPicker(this.configManager);
510
+ if (!picked) {
511
+ logger.info('Model selection cancelled — retrying with current model.');
512
+ restartSpinner();
513
+ return { action: 'retry' };
514
+ }
515
+ console.log('');
516
+ logger.info(`Switching to model: ${picked.model} (provider: ${picked.provider})`);
517
+ // Create a new LLM provider with the switched model
518
+ const newOptions = {
519
+ ...options,
520
+ provider: picked.provider,
521
+ model: picked.model,
522
+ };
523
+ const newCallLLM = this.createLLMProvider(newOptions);
524
+ restartSpinner();
525
+ return { action: 'switch-model', callLLM: newCallLLM };
526
+ }
527
+ // Fallback: retry
528
+ restartSpinner();
529
+ return { action: 'retry' };
530
+ };
531
+ }
532
+ async executeSingleTask(task, vault, options, agentResults, contextFiles, defaultCallLLM) {
533
+ vault.updateTaskStatus(task.id, 'running');
534
+ await tryUpdateDAGNode(task.id, { status: 'running' });
535
+ // Update spinner text to show which task is currently executing
536
+ if (options.spinner) {
537
+ const agentIcon = AGENT_ICONS[task.agentType] || '⚙️';
538
+ const shortDesc = task.description.slice(0, 60);
539
+ options.spinner.start(`${agentIcon} ${shortDesc}${task.description.length > 60 ? '...' : ''}`);
540
+ }
541
+ if (options.verbose) {
542
+ logger.info(`\n ▶️ ${task.agentType}: ${task.description.slice(0, 80)}${task.description.length > 80 ? '...' : ''}`);
543
+ }
544
+ try {
545
+ const agentModel = options.model || options.agentModels?.[task.agentType];
546
+ const agentCallLLM = agentModel
547
+ ? this.createLLMProvider({ ...options, model: agentModel })
548
+ : defaultCallLLM;
549
+ // Skip runner tasks in dry-run mode (no commands executed)
550
+ if (task.agentType === 'runner' && options.dryRun) {
551
+ vault.updateTaskStatus(task.id, 'completed', 'Skipped (dry-run mode)');
552
+ agentResults.push({
553
+ agent: 'runner',
554
+ success: true,
555
+ summary: 'Skipped (dry-run mode — no commands executed)',
556
+ });
557
+ if (options.verbose) {
558
+ logger.info(' ⏭️ Skipped (dry-run — no commands executed)');
559
+ }
560
+ return;
561
+ }
562
+ const agent = createAgent(task.agentType, options);
563
+ if (!agent) {
564
+ vault.updateTaskStatus(task.id, 'failed', `Unknown agent type: ${task.agentType}`);
565
+ agentResults.push({
566
+ agent: task.agentType,
567
+ success: false,
568
+ summary: `Unknown agent type: ${task.agentType}`,
569
+ });
570
+ return;
571
+ }
572
+ // Wire up the rate-limit handler so agents can prompt the user
573
+ vault.context.onRateLimit = this.createRateLimitHandler(options, agentModel || options.model);
574
+ const result = await agent.execute(vault.context, agentCallLLM);
575
+ vault.updateTaskStatus(task.id, result.success ? 'completed' : 'failed', result.summary);
576
+ await tryUpdateDAGNode(task.id, {
577
+ status: result.success ? 'completed' : 'failed',
578
+ summary: result.summary,
579
+ });
580
+ agentResults.push({ agent: task.agentType, success: result.success, summary: result.summary });
581
+ // Track sandbox path for cleanup
582
+ if (result.success && task.agentType === 'tester') {
583
+ const testResult = vault.getMeta('testResult');
584
+ if (testResult?.sandboxPath) {
585
+ vault.setMeta('sandboxPath', testResult.sandboxPath);
586
+ }
587
+ }
588
+ // After debugger step: write debugger's fixes to disk immediately
589
+ // The DebuggerAgent's syncChangesToContext() updates context.fileChanges
590
+ // with LLM-generated fixes. If a runner step follows the debugger, those
591
+ // fixes must be on disk before the runner executes.
592
+ if (task.agentType === 'debugger' && result.success && !options.dryRun) {
593
+ const applied = this.applyFileChanges(vault);
594
+ if (applied > 0 && options.verbose) {
595
+ logger.info(` 💾 Applied ${applied} debug fix(es) to disk`);
596
+ }
597
+ }
598
+ // After writer step: write files to disk immediately and sync into artifacts
599
+ // IMPORTANT: files MUST be on disk before the RunnerAgent tries to execute them
600
+ if (task.agentType === 'writer' && result.success) {
601
+ if (!options.dryRun) {
602
+ const applied = this.applyFileChanges(vault);
603
+ if (applied > 0 && options.verbose) {
604
+ logger.info(` 💾 Applied ${applied} file change${applied !== 1 ? 's' : ''} to disk`);
605
+ }
606
+ }
607
+ const newArtifacts = vault.context.fileChanges
608
+ .filter((c) => c.status === 'created' || c.status === 'modified')
609
+ .filter((c) => c.newContent)
610
+ .map((c) => ({
611
+ path: c.path,
612
+ content: c.newContent,
613
+ description: `${c.status} by WriterAgent (${task.description.slice(0, 60)})`,
614
+ }));
615
+ for (const artifact of newArtifacts) {
616
+ const existing = vault.context.artifacts.findIndex((a) => a.path === artifact.path);
617
+ if (existing >= 0) {
618
+ vault.context.artifacts[existing] = artifact;
619
+ }
620
+ else {
621
+ vault.context.artifacts.push(artifact);
622
+ }
623
+ }
624
+ }
625
+ // After runner step: refresh artifacts with any files created during execution
626
+ if (task.agentType === 'runner' && result.success) {
627
+ const runResult = vault.getMeta('runResult');
628
+ if (runResult?.stdout) {
629
+ vault.setMeta('runOutput', runResult.stdout);
630
+ }
631
+ }
632
+ // Track context file paths for memory storage
633
+ if (task.agentType === 'context-gatherer' && result.success) {
634
+ for (const artifact of vault.context.artifacts) {
635
+ if (!contextFiles.includes(artifact.path)) {
636
+ contextFiles.push(artifact.path);
637
+ }
638
+ }
639
+ }
640
+ if (options.verbose) {
641
+ const icon = result.success ? '✅' : '⚠️';
642
+ logger.info(` ${icon} ${result.summary}`);
643
+ // If it's a runner, show the output inline
644
+ if (task.agentType === 'runner' && result.success && result.details) {
645
+ const outputLines = result.details.split('\n').filter((l) => l.startsWith('stdout:') || l.startsWith('Command:'));
646
+ for (const line of outputLines) {
647
+ logger.info(` ${line}`);
648
+ }
649
+ }
650
+ }
651
+ }
652
+ catch (err) {
653
+ const msg = err instanceof Error ? err.message : String(err);
654
+ vault.updateTaskStatus(task.id, 'failed', msg);
655
+ await tryUpdateDAGNode(task.id, { status: 'failed', summary: msg });
656
+ agentResults.push({ agent: task.agentType, success: false, summary: `Error: ${msg}` });
657
+ }
658
+ }
659
+ applyFileChanges(vault) {
660
+ let count = 0;
661
+ for (const change of vault.context.fileChanges) {
662
+ if (change.status === 'deleted')
663
+ continue;
664
+ if (!change.newContent)
665
+ continue;
666
+ const absolutePath = isAbsolute(change.path)
667
+ ? change.path
668
+ : resolve(process.cwd(), change.path);
669
+ const dir = dirname(absolutePath);
670
+ if (!existsSync(dir)) {
671
+ mkdirSync(dir, { recursive: true });
672
+ }
673
+ writeFileSync(absolutePath, change.newContent, 'utf-8');
674
+ count++;
675
+ }
676
+ return count;
677
+ }
678
+ buildResult(success, goal, agentResults, vault, overrides = {}) {
679
+ const completed = overrides.tasksCompleted ?? agentResults.filter((r) => r.success).length;
680
+ const total = overrides.tasksTotal ?? agentResults.length;
681
+ return {
682
+ success,
683
+ goal,
684
+ summary: overrides.summary || `Execution completed with status: ${success ? 'success' : 'failure'}`,
685
+ tasksCompleted: completed,
686
+ tasksTotal: total,
687
+ agentResults,
688
+ fileChanges: vault.getDiffSummary(),
689
+ runOutput: overrides.runOutput,
690
+ error: overrides.error,
691
+ trajectoryId: overrides.trajectoryId,
692
+ reviewId: overrides.reviewId,
693
+ };
694
+ }
695
+ }
696
+ //# sourceMappingURL=orchestrator.js.map