profclaw 2.0.0 → 2.3.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 (477) hide show
  1. package/.env.example +14 -2
  2. package/CHANGELOG.md +37 -0
  3. package/CONTRIBUTING.md +20 -0
  4. package/Dockerfile +39 -23
  5. package/README.md +174 -40
  6. package/dist/agents/agent-summary.d.ts +44 -0
  7. package/dist/agents/agent-summary.js +176 -0
  8. package/dist/agents/auto-memory.d.ts +59 -0
  9. package/dist/agents/auto-memory.js +310 -0
  10. package/dist/agents/checkpoint-manager.d.ts +76 -0
  11. package/dist/agents/checkpoint-manager.js +156 -0
  12. package/dist/agents/circuit-breaker.d.ts +54 -0
  13. package/dist/agents/circuit-breaker.js +153 -0
  14. package/dist/agents/context-compactor.d.ts +70 -0
  15. package/dist/agents/context-compactor.js +361 -0
  16. package/dist/agents/conversation-branch.d.ts +55 -0
  17. package/dist/agents/conversation-branch.js +115 -0
  18. package/dist/agents/error-recovery.d.ts +44 -0
  19. package/dist/agents/error-recovery.js +197 -0
  20. package/dist/agents/events.d.ts +76 -0
  21. package/dist/agents/events.js +8 -0
  22. package/dist/agents/executor.d.ts +35 -1
  23. package/dist/agents/executor.js +573 -124
  24. package/dist/agents/file-snapshots.d.ts +72 -0
  25. package/dist/agents/file-snapshots.js +182 -0
  26. package/dist/agents/index.d.ts +2 -0
  27. package/dist/agents/orchestrator.d.ts +183 -0
  28. package/dist/agents/orchestrator.js +495 -0
  29. package/dist/agents/permissions.d.ts +63 -0
  30. package/dist/agents/permissions.js +138 -0
  31. package/dist/agents/plan-mode.d.ts +71 -0
  32. package/dist/agents/plan-mode.js +186 -0
  33. package/dist/agents/prompt-suggestions.d.ts +33 -0
  34. package/dist/agents/prompt-suggestions.js +208 -0
  35. package/dist/agents/rate-limit-monitor.d.ts +56 -0
  36. package/dist/agents/rate-limit-monitor.js +224 -0
  37. package/dist/agents/result-store.d.ts +37 -0
  38. package/dist/agents/result-store.js +104 -0
  39. package/dist/agents/session-diff.d.ts +43 -0
  40. package/dist/agents/session-diff.js +258 -0
  41. package/dist/agents/tool-loader.d.ts +65 -0
  42. package/dist/agents/tool-loader.js +273 -0
  43. package/dist/agents/transcript.d.ts +96 -0
  44. package/dist/agents/transcript.js +267 -0
  45. package/dist/agents/worktree-manager.d.ts +80 -0
  46. package/dist/agents/worktree-manager.js +203 -0
  47. package/dist/auth/middleware.js +14 -0
  48. package/dist/chat/agentic-executor.d.ts +7 -0
  49. package/dist/chat/agentic-executor.js +253 -30
  50. package/dist/chat/conversations.d.ts +2 -0
  51. package/dist/chat/conversations.js +8 -0
  52. package/dist/chat/execution/executor.d.ts +8 -0
  53. package/dist/chat/execution/executor.js +157 -103
  54. package/dist/chat/execution/index.js +5 -1
  55. package/dist/chat/execution/tool-router.js +40 -14
  56. package/dist/chat/execution/tools/canvas.d.ts +2 -2
  57. package/dist/chat/execution/tools/code-tools.d.ts +66 -0
  58. package/dist/chat/execution/tools/code-tools.js +353 -0
  59. package/dist/chat/execution/tools/complete-task.d.ts +2 -2
  60. package/dist/chat/execution/tools/cron-tool.d.ts +26 -10
  61. package/dist/chat/execution/tools/cron-tool.js +48 -3
  62. package/dist/chat/execution/tools/decompose-task.d.ts +58 -0
  63. package/dist/chat/execution/tools/decompose-task.js +166 -0
  64. package/dist/chat/execution/tools/exec.d.ts +5 -2
  65. package/dist/chat/execution/tools/exec.js +294 -155
  66. package/dist/chat/execution/tools/feed-tools.d.ts +77 -0
  67. package/dist/chat/execution/tools/feed-tools.js +142 -0
  68. package/dist/chat/execution/tools/file-ops.d.ts +1 -1
  69. package/dist/chat/execution/tools/github.d.ts +2 -2
  70. package/dist/chat/execution/tools/index.d.ts +14 -2
  71. package/dist/chat/execution/tools/index.js +86 -12
  72. package/dist/chat/execution/tools/integrations.d.ts +8 -8
  73. package/dist/chat/execution/tools/multi-patch.d.ts +53 -0
  74. package/dist/chat/execution/tools/multi-patch.js +373 -0
  75. package/dist/chat/execution/tools/openai-image-gen.d.ts +2 -2
  76. package/dist/chat/execution/tools/plan-tools.d.ts +80 -0
  77. package/dist/chat/execution/tools/plan-tools.js +134 -0
  78. package/dist/chat/execution/tools/profclaw-ops.d.ts +6 -6
  79. package/dist/chat/execution/tools/repl-tool.d.ts +46 -0
  80. package/dist/chat/execution/tools/repl-tool.js +207 -0
  81. package/dist/chat/execution/tools/sessions-send.d.ts +2 -2
  82. package/dist/chat/execution/tools/slack-actions.d.ts +2 -2
  83. package/dist/chat/execution/tools/system.d.ts +4 -4
  84. package/dist/chat/execution/tools/todo-tool.d.ts +72 -0
  85. package/dist/chat/execution/tools/todo-tool.js +152 -0
  86. package/dist/chat/execution/tools/tool-search.d.ts +50 -0
  87. package/dist/chat/execution/tools/tool-search.js +155 -0
  88. package/dist/chat/execution/types.d.ts +21 -14
  89. package/dist/chat/execution/workflows/executor.d.ts +11 -0
  90. package/dist/chat/execution/workflows/executor.js +99 -1
  91. package/dist/chat/execution/workflows/types.d.ts +35 -2
  92. package/dist/chat/format/index.d.ts +1 -0
  93. package/dist/chat/format/index.js +1 -0
  94. package/dist/chat/format/markdown-convert.d.ts +23 -0
  95. package/dist/chat/format/markdown-convert.js +149 -0
  96. package/dist/chat/index.d.ts +1 -1
  97. package/dist/chat/index.js +1 -1
  98. package/dist/chat/message-handler.js +58 -6
  99. package/dist/chat/proactive/index.d.ts +62 -0
  100. package/dist/chat/proactive/index.js +147 -0
  101. package/dist/chat/prompt-adapter.js +2 -0
  102. package/dist/chat/providers/irc/index.d.ts +2 -2
  103. package/dist/chat/providers/telegram/index.d.ts +2 -0
  104. package/dist/chat/providers/telegram/index.js +21 -2
  105. package/dist/chat/system-prompts.d.ts +3 -3
  106. package/dist/chat/system-prompts.js +116 -61
  107. package/dist/chat/tools.d.ts +6 -6
  108. package/dist/cli/commands/auth.js +64 -1
  109. package/dist/cli/commands/chat.js +1327 -138
  110. package/dist/cli/commands/doctor.js +222 -16
  111. package/dist/cli/commands/history.d.ts +3 -0
  112. package/dist/cli/commands/history.js +138 -0
  113. package/dist/cli/commands/import.d.ts +44 -0
  114. package/dist/cli/commands/import.js +526 -0
  115. package/dist/cli/commands/init.d.ts +13 -0
  116. package/dist/cli/commands/init.js +381 -0
  117. package/dist/cli/commands/onboard.js +210 -30
  118. package/dist/cli/commands/plan.d.ts +13 -0
  119. package/dist/cli/commands/plan.js +184 -0
  120. package/dist/cli/commands/serve.d.ts +7 -0
  121. package/dist/cli/commands/serve.js +77 -18
  122. package/dist/cli/commands/setup.js +84 -3
  123. package/dist/cli/commands/status.js +54 -0
  124. package/dist/cli/commands/tools.js +13 -13
  125. package/dist/cli/commands/tui.js +26 -1
  126. package/dist/cli/index.js +19 -0
  127. package/dist/cli/ink/App.d.ts +13 -0
  128. package/dist/cli/ink/App.js +6 -0
  129. package/dist/cli/ink/ChatApp.d.ts +60 -0
  130. package/dist/cli/ink/ChatApp.js +325 -0
  131. package/dist/cli/ink/DashboardApp.d.ts +3 -0
  132. package/dist/cli/ink/DashboardApp.js +143 -0
  133. package/dist/cli/ink/components/AgentStatus.d.ts +17 -0
  134. package/dist/cli/ink/components/AgentStatus.js +33 -0
  135. package/dist/cli/ink/components/ChannelList.d.ts +17 -0
  136. package/dist/cli/ink/components/ChannelList.js +33 -0
  137. package/dist/cli/ink/components/ConnectionStatus.d.ts +19 -0
  138. package/dist/cli/ink/components/ConnectionStatus.js +50 -0
  139. package/dist/cli/ink/components/CostBar.d.ts +19 -0
  140. package/dist/cli/ink/components/CostBar.js +35 -0
  141. package/dist/cli/ink/components/HookStatus.d.ts +15 -0
  142. package/dist/cli/ink/components/HookStatus.js +7 -0
  143. package/dist/cli/ink/components/PermissionPrompt.d.ts +21 -0
  144. package/dist/cli/ink/components/PermissionPrompt.js +51 -0
  145. package/dist/cli/ink/components/PlanView.d.ts +23 -0
  146. package/dist/cli/ink/components/PlanView.js +26 -0
  147. package/dist/cli/ink/components/ProviderList.d.ts +16 -0
  148. package/dist/cli/ink/components/ProviderList.js +16 -0
  149. package/dist/cli/ink/components/SessionHeader.d.ts +15 -0
  150. package/dist/cli/ink/components/SessionHeader.js +15 -0
  151. package/dist/cli/ink/components/StreamingMessage.d.ts +20 -0
  152. package/dist/cli/ink/components/StreamingMessage.js +27 -0
  153. package/dist/cli/ink/components/SuggestionBar.d.ts +15 -0
  154. package/dist/cli/ink/components/SuggestionBar.js +28 -0
  155. package/dist/cli/ink/components/SystemHealth.d.ts +20 -0
  156. package/dist/cli/ink/components/SystemHealth.js +39 -0
  157. package/dist/cli/ink/components/TaskList.d.ts +17 -0
  158. package/dist/cli/ink/components/TaskList.js +59 -0
  159. package/dist/cli/ink/components/ToolCall.d.ts +17 -0
  160. package/dist/cli/ink/components/ToolCall.js +43 -0
  161. package/dist/cli/ink/index.d.ts +23 -0
  162. package/dist/cli/ink/index.js +15 -0
  163. package/dist/cli/ink/keybindings.d.ts +35 -0
  164. package/dist/cli/ink/keybindings.js +105 -0
  165. package/dist/cli/ink/markdown-renderer.d.ts +47 -0
  166. package/dist/cli/ink/markdown-renderer.js +380 -0
  167. package/dist/cli/ink/output-styles.d.ts +39 -0
  168. package/dist/cli/ink/output-styles.js +119 -0
  169. package/dist/cli/interactive/auto-serve.d.ts +38 -0
  170. package/dist/cli/interactive/auto-serve.js +209 -0
  171. package/dist/cli/interactive/index.d.ts +25 -0
  172. package/dist/cli/interactive/index.js +23 -0
  173. package/dist/cli/interactive/picker.d.ts +28 -0
  174. package/dist/cli/interactive/picker.js +153 -0
  175. package/dist/cli/interactive/renderer.d.ts +26 -0
  176. package/dist/cli/interactive/renderer.js +555 -0
  177. package/dist/cli/interactive/repl.d.ts +14 -0
  178. package/dist/cli/interactive/repl.js +1516 -0
  179. package/dist/cli/interactive/stream-client.d.ts +59 -0
  180. package/dist/cli/interactive/stream-client.js +506 -0
  181. package/dist/cli/interactive/types.d.ts +121 -0
  182. package/dist/cli/interactive/types.js +10 -0
  183. package/dist/cli/utils/api.d.ts +9 -0
  184. package/dist/cli/utils/api.js +58 -2
  185. package/dist/cron/natural-language.d.ts +54 -0
  186. package/dist/cron/natural-language.js +569 -0
  187. package/dist/cron/scheduler.d.ts +34 -4
  188. package/dist/cron/scheduler.js +141 -9
  189. package/dist/cron/templates.d.ts +1 -1
  190. package/dist/cron/templates.js +219 -0
  191. package/dist/feeds/feed-engine.d.ts +149 -0
  192. package/dist/feeds/feed-engine.js +600 -0
  193. package/dist/feeds/index.d.ts +9 -0
  194. package/dist/feeds/index.js +8 -0
  195. package/dist/gateway/router.js +6 -1
  196. package/dist/hooks/built-in/audit-log.d.ts +11 -0
  197. package/dist/hooks/built-in/audit-log.js +84 -0
  198. package/dist/hooks/built-in/cost-warning.d.ts +10 -0
  199. package/dist/hooks/built-in/cost-warning.js +59 -0
  200. package/dist/hooks/built-in/dangerous-tool.d.ts +32 -0
  201. package/dist/hooks/built-in/dangerous-tool.js +80 -0
  202. package/dist/hooks/built-in/index.d.ts +14 -0
  203. package/dist/hooks/built-in/index.js +20 -0
  204. package/dist/hooks/index.d.ts +3 -0
  205. package/dist/hooks/index.js +6 -0
  206. package/dist/hooks/loader.d.ts +17 -0
  207. package/dist/hooks/loader.js +142 -0
  208. package/dist/hooks/registry.d.ts +62 -0
  209. package/dist/hooks/registry.js +127 -0
  210. package/dist/integrations/web-search.js +6 -3
  211. package/dist/memory/index.d.ts +1 -0
  212. package/dist/memory/index.js +2 -0
  213. package/dist/memory/memory-service.js +14 -13
  214. package/dist/memory/observational.d.ts +62 -0
  215. package/dist/memory/observational.js +396 -0
  216. package/dist/middleware/content-filter.d.ts +22 -0
  217. package/dist/middleware/content-filter.js +69 -0
  218. package/dist/middleware/request-validator.d.ts +159 -0
  219. package/dist/middleware/request-validator.js +93 -0
  220. package/dist/plugins/sdk.d.ts +22 -0
  221. package/dist/plugins/sdk.js +17 -1
  222. package/dist/projects/types.d.ts +10 -10
  223. package/dist/providers/ai-sdk.d.ts +11 -0
  224. package/dist/providers/ai-sdk.js +78 -19
  225. package/dist/providers/core/models.js +67 -1
  226. package/dist/providers/core/types.d.ts +3 -0
  227. package/dist/providers/index.d.ts +1 -0
  228. package/dist/providers/index.js +1 -0
  229. package/dist/providers/smart-router.d.ts +118 -0
  230. package/dist/providers/smart-router.js +685 -0
  231. package/dist/providers/types.d.ts +16 -16
  232. package/dist/routes/agents.js +50 -0
  233. package/dist/routes/auth.js +8 -1
  234. package/dist/routes/chat.js +259 -14
  235. package/dist/routes/costs.js +32 -0
  236. package/dist/routes/cron.js +80 -5
  237. package/dist/routes/feeds.d.ts +10 -0
  238. package/dist/routes/feeds.js +168 -0
  239. package/dist/routes/mcp.js +21 -0
  240. package/dist/routes/memory.js +130 -0
  241. package/dist/routes/skills.js +129 -0
  242. package/dist/routes/teams.d.ts +9 -0
  243. package/dist/routes/teams.js +210 -0
  244. package/dist/routes/tools.js +14 -0
  245. package/dist/routes/users.js +2 -0
  246. package/dist/server/route-loader.js +3 -1
  247. package/dist/server/stream-bridge.d.ts +19 -0
  248. package/dist/server/stream-bridge.js +38 -0
  249. package/dist/server.js +310 -36
  250. package/dist/skills/marketplace.d.ts +87 -0
  251. package/dist/skills/marketplace.js +268 -0
  252. package/dist/storage/index.d.ts +14 -0
  253. package/dist/storage/index.js +64 -3
  254. package/dist/storage/schema.d.ts +4 -4
  255. package/dist/storage/schema.js +1 -1
  256. package/dist/teams/index.d.ts +110 -0
  257. package/dist/teams/index.js +365 -0
  258. package/dist/tickets/types.d.ts +39 -39
  259. package/dist/types/summary.d.ts +5 -5
  260. package/dist/utils/auto-update.d.ts +23 -0
  261. package/dist/utils/auto-update.js +157 -0
  262. package/dist/utils/offline-detect.d.ts +55 -0
  263. package/dist/utils/offline-detect.js +121 -0
  264. package/dist/utils/pid-file.d.ts +36 -0
  265. package/dist/utils/pid-file.js +125 -0
  266. package/dist/utils/prevent-sleep.d.ts +27 -0
  267. package/dist/utils/prevent-sleep.js +95 -0
  268. package/dist/utils/sanitizer.d.ts +57 -0
  269. package/dist/utils/sanitizer.js +174 -0
  270. package/docker-compose.yml +13 -137
  271. package/package.json +31 -6
  272. package/skills/deploy-cloudflare/SKILL.md +62 -0
  273. package/skills/deploy-vercel/SKILL.md +67 -0
  274. package/skills/docker-deploy/SKILL.md +158 -0
  275. package/skills/full-stack-builder/SKILL.md +92 -0
  276. package/skills/humanizer/SKILL.md +488 -0
  277. package/skills/profclaw-assistant/SKILL.md +85 -56
  278. package/ui/dist/assets/ActivityView-Da6HQ8ws.js +1 -0
  279. package/ui/dist/assets/AgentList-H58R0kX3.js +1 -0
  280. package/ui/dist/assets/AnalyticsDashboard-B28AeRsc.js +1 -0
  281. package/ui/dist/assets/AreaChart-DwLzeAQ8.js +1 -0
  282. package/ui/dist/assets/CartesianChart-piKQsTAR.js +36 -0
  283. package/ui/dist/assets/ChatView-Dbj8rxU5.js +10 -0
  284. package/ui/dist/assets/CostsDashboard-C6F5df0F.js +1 -0
  285. package/ui/dist/assets/EstimateSelect-wga0rUKX.js +1 -0
  286. package/ui/dist/assets/FeedDashboard-Ef6FEzEf.js +1 -0
  287. package/ui/dist/assets/FloatingChatbot-0yhkUeCq.js +2 -0
  288. package/ui/dist/assets/InviteCodeManagement-tUXfx4Bc.js +2 -0
  289. package/ui/dist/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  290. package/ui/dist/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  291. package/ui/dist/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  292. package/ui/dist/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  293. package/ui/dist/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  294. package/ui/dist/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  295. package/ui/dist/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  296. package/ui/dist/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  297. package/ui/dist/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  298. package/ui/dist/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  299. package/ui/dist/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  300. package/ui/dist/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  301. package/ui/dist/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  302. package/ui/dist/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  303. package/ui/dist/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  304. package/ui/dist/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  305. package/ui/dist/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  306. package/ui/dist/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  307. package/ui/dist/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  308. package/ui/dist/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  309. package/ui/dist/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  310. package/ui/dist/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  311. package/ui/dist/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  312. package/ui/dist/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  313. package/ui/dist/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  314. package/ui/dist/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  315. package/ui/dist/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  316. package/ui/dist/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  317. package/ui/dist/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  318. package/ui/dist/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  319. package/ui/dist/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  320. package/ui/dist/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  321. package/ui/dist/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  322. package/ui/dist/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  323. package/ui/dist/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  324. package/ui/dist/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  325. package/ui/dist/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  326. package/ui/dist/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  327. package/ui/dist/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  328. package/ui/dist/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  329. package/ui/dist/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  330. package/ui/dist/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  331. package/ui/dist/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  332. package/ui/dist/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  333. package/ui/dist/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  334. package/ui/dist/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  335. package/ui/dist/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  336. package/ui/dist/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  337. package/ui/dist/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  338. package/ui/dist/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  339. package/ui/dist/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  340. package/ui/dist/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  341. package/ui/dist/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  342. package/ui/dist/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  343. package/ui/dist/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  344. package/ui/dist/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  345. package/ui/dist/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  346. package/ui/dist/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  347. package/ui/dist/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  348. package/ui/dist/assets/MarketplacePage-DGrLtolR.js +1 -0
  349. package/ui/dist/assets/{ProjectDetail--gPfvATB.js → ProjectDetail-BgWvA6UP.js} +2 -2
  350. package/ui/dist/assets/ProjectIcon-TDuliqwg.js +1 -0
  351. package/ui/dist/assets/ProjectList-DXgM4187.js +1 -0
  352. package/ui/dist/assets/{Settings-1kaf7VHE.js → Settings-xA8Zhi3p.js} +3 -3
  353. package/ui/dist/assets/StatusIndicator-B8vfFAxg.js +1 -0
  354. package/ui/dist/assets/{SummaryDetail-DV3AmONk.js → SummaryDetail-eedRfTtF.js} +2 -2
  355. package/ui/dist/assets/SummaryList-CLNX2P84.js +1 -0
  356. package/ui/dist/assets/TaskDetail-BtWclNiR.js +1 -0
  357. package/ui/dist/assets/TaskList-JjODAgSc.js +1 -0
  358. package/ui/dist/assets/TeamsPage-CBK5iAyx.js +1 -0
  359. package/ui/dist/assets/TicketBoard-C9aJNNYp.js +1 -0
  360. package/ui/dist/assets/TicketDetail-CV5JmL31.js +1 -0
  361. package/ui/dist/assets/TicketList-68V4lzUz.js +1 -0
  362. package/ui/dist/assets/UserManagement-DKTb6UpE.js +2 -0
  363. package/ui/dist/assets/ViewSwitcher-BvdQht2Y.js +1 -0
  364. package/ui/dist/assets/alert-dialog-O6qBOv_f.js +1 -0
  365. package/ui/dist/assets/{archive-BsLa7brF.js → archive-CX7UvZpf.js} +1 -1
  366. package/ui/dist/assets/badge-BbfnwDJP.js +1 -0
  367. package/ui/dist/assets/{bug-CmZI7jqM.js → bug-3WX0394-.js} +1 -1
  368. package/ui/dist/assets/{calendar-Bf0t2B82.js → calendar-buq77TaS.js} +1 -1
  369. package/ui/dist/assets/{chevron-up-CoUsOvZj.js → chevron-up-4ymsBJRo.js} +1 -1
  370. package/ui/dist/assets/{circle-x-Dgw11LgT.js → circle-x-ByXtwR6Y.js} +1 -1
  371. package/ui/dist/assets/constants-CVdDh7p0.js +1 -0
  372. package/ui/dist/assets/{cpu-DiPMQICV.js → cpu-CiuoCeDY.js} +1 -1
  373. package/ui/dist/assets/{database-BwTfupDi.js → database-BWXSBg5a.js} +1 -1
  374. package/ui/dist/assets/dialog-lDg4NvMV.js +1 -0
  375. package/ui/dist/assets/dollar-sign-Dmijd6DP.js +1 -0
  376. package/ui/dist/assets/{ellipsis-UJx4Xnf6.js → ellipsis-vT-5SVIp.js} +1 -1
  377. package/ui/dist/assets/{ellipsis-vertical-DoULYEKn.js → ellipsis-vertical-B4tAX_bL.js} +1 -1
  378. package/ui/dist/assets/feature-markdown-DBo5Q7uq.js +289 -0
  379. package/ui/dist/assets/{file-code-B2UrJLwi.js → file-code-ChOWdKXf.js} +1 -1
  380. package/ui/dist/assets/{folder-open-BJi577JH.js → folder-open-CkOUbIiP.js} +1 -1
  381. package/ui/dist/assets/{funnel-PkaD_HSR.js → funnel-uZkoSPP-.js} +1 -1
  382. package/ui/dist/assets/{git-branch-C_K30am0.js → git-branch-CwvUxj7C.js} +1 -1
  383. package/ui/dist/assets/{git-commit-horizontal-IT6ecxWQ.js → git-commit-horizontal-lxPzCvhD.js} +1 -1
  384. package/ui/dist/assets/{globe-f-jjCa_g.js → globe-D_WpJdsj.js} +1 -1
  385. package/ui/dist/assets/{hash-DNEv8Elo.js → hash-CA0hJ7vh.js} +1 -1
  386. package/ui/dist/assets/{history-BQSBo_1Q.js → history-CEWMLELs.js} +1 -1
  387. package/ui/dist/assets/inbox-ehtOptTV.js +1 -0
  388. package/ui/dist/assets/{index-nS3EErDg.js → index-C1rhbml4.js} +3 -3
  389. package/ui/dist/assets/index-CR8gfCHv.js +1 -0
  390. package/ui/dist/assets/index-DVXMpWai.js +1 -0
  391. package/ui/dist/assets/index-DaDJMM2v.js +1 -0
  392. package/ui/dist/assets/index-Djdq_0xu.js +1 -0
  393. package/ui/dist/assets/index-M46Gcb8K.css +1 -0
  394. package/ui/dist/assets/index-sEBN7w8J.js +109 -0
  395. package/ui/dist/assets/layers-C6Mhf8Nk.js +1 -0
  396. package/ui/dist/assets/{layout-dashboard-CcKt1hXw.js → layout-dashboard-BRUM0kpT.js} +1 -1
  397. package/ui/dist/assets/{lightbulb-Jhp7FvbU.js → lightbulb-CN2q1O5l.js} +1 -1
  398. package/ui/dist/assets/{link-2-DdO7ostF.js → link-2-CC4E28yJ.js} +1 -1
  399. package/ui/dist/assets/markdown-renderer-C6ENbB0u.js +10 -0
  400. package/ui/dist/assets/markdown-renderer-CfVKi3_s.css +1 -0
  401. package/ui/dist/assets/{message-square-CBgH65X7.js → message-square-Bbb241am.js} +1 -1
  402. package/ui/dist/assets/package-CwT3IzFx.js +1 -0
  403. package/ui/dist/assets/{pencil-CYXCEPQh.js → pencil-CDmiHzoj.js} +1 -1
  404. package/ui/dist/assets/{play-d1ONaH0-.js → play-tjy5jMQX.js} +1 -1
  405. package/ui/dist/assets/popover-CFHZf3pE.js +1 -0
  406. package/ui/dist/assets/progress-BboUHuLf.js +1 -0
  407. package/ui/dist/assets/{rocket-DhvUetsk.js → rocket--8ZHgdXJ.js} +1 -1
  408. package/ui/dist/assets/select-n108rXny.js +1 -0
  409. package/ui/dist/assets/{send-P0r5D7td.js → send-Cu7MR2Qh.js} +1 -1
  410. package/ui/dist/assets/server-DmodxZp-.js +1 -0
  411. package/ui/dist/assets/{settings-2-ocj5uHGx.js → settings-2-CkRNqkxj.js} +1 -1
  412. package/ui/dist/assets/sheet-7aUJkyzU.js +1 -0
  413. package/ui/dist/assets/{shield-check-DfVdE34l.js → shield-check-ViI3nMKE.js} +1 -1
  414. package/ui/dist/assets/{shield-off-8l0J6R-8.js → shield-off-DN3tagkn.js} +1 -1
  415. package/ui/dist/assets/skeleton-C0E1Nfro.js +1 -0
  416. package/ui/dist/assets/{smartphone-77_g3SQn.js → smartphone-5FghiXpA.js} +1 -1
  417. package/ui/dist/assets/{square-Ckzsr3Rn.js → square-DiNSx8K7.js} +1 -1
  418. package/ui/dist/assets/star-DhdFVidS.js +1 -0
  419. package/ui/dist/assets/switch-CIgVbZqQ.js +1 -0
  420. package/ui/dist/assets/table-BC56FVMV.js +1 -0
  421. package/ui/dist/assets/{tag-C35mgoEv.js → tag-CH_vQliw.js} +1 -1
  422. package/ui/dist/assets/textarea-CxDiKFXZ.js +1 -0
  423. package/ui/dist/assets/{timer-DHJBS2w1.js → timer-CdGVTb60.js} +1 -1
  424. package/ui/dist/assets/tooltip-BuW9A5UO.js +1 -0
  425. package/ui/dist/assets/{trash-2-keO5tKPE.js → trash-2-CucZJL0N.js} +1 -1
  426. package/ui/dist/assets/trending-down-BCezC1z2.js +1 -0
  427. package/ui/dist/assets/{trending-up-BBv8KbrY.js → trending-up-C5OYX2k2.js} +1 -1
  428. package/ui/dist/assets/vendor-query-C0p7b53x.js +4 -0
  429. package/ui/dist/assets/vendor-react-Mc5_kfYG.js +12 -0
  430. package/ui/dist/assets/vendor-ui-CXPAUBFv.js +51 -0
  431. package/ui/dist/assets/{wand-sparkles-BusQ52ZK.js → wand-sparkles-BaH6pJnc.js} +1 -1
  432. package/ui/dist/assets/{wrench-02YaOSiK.js → wrench-CjxjP6ok.js} +1 -1
  433. package/ui/dist/index.html +5 -2
  434. package/ui/dist/assets/ActivityView-BeshZXmE.js +0 -1
  435. package/ui/dist/assets/AgentList-QVHeldPi.js +0 -1
  436. package/ui/dist/assets/AnalyticsDashboard-C9R97dXE.js +0 -1
  437. package/ui/dist/assets/AreaChart-B73gaiVQ.js +0 -1
  438. package/ui/dist/assets/CartesianChart-CXYL2R-A.js +0 -36
  439. package/ui/dist/assets/ChatView-qjZErlrp.js +0 -10
  440. package/ui/dist/assets/CostsDashboard-O4DCLy1i.js +0 -1
  441. package/ui/dist/assets/EstimateSelect-1hQf4Osk.js +0 -1
  442. package/ui/dist/assets/FloatingChatbot-BZBzrJxd.js +0 -2
  443. package/ui/dist/assets/InviteCodeManagement-LEoGqYeA.js +0 -2
  444. package/ui/dist/assets/ProjectIcon-Chd_ofsw.js +0 -1
  445. package/ui/dist/assets/ProjectList-BvUfVB6c.js +0 -4
  446. package/ui/dist/assets/StatusIndicator-pRfkNcdV.js +0 -1
  447. package/ui/dist/assets/SummaryList-B6kXiTxL.js +0 -1
  448. package/ui/dist/assets/TaskDetail-CV6CzbOS.js +0 -1
  449. package/ui/dist/assets/TaskList-DL7brQKd.js +0 -1
  450. package/ui/dist/assets/TicketBoard-CrkkFj7C.js +0 -1
  451. package/ui/dist/assets/TicketDetail-hnnYclpD.js +0 -1
  452. package/ui/dist/assets/TicketList-CsDAyQCL.js +0 -1
  453. package/ui/dist/assets/UserManagement-BGFQyTSr.js +0 -2
  454. package/ui/dist/assets/ViewSwitcher-CnL0OqA8.js +0 -1
  455. package/ui/dist/assets/alert-dialog-SKM6Gjz4.js +0 -7
  456. package/ui/dist/assets/badge-CVHH1a-v.js +0 -1
  457. package/ui/dist/assets/brain-6o_RHVpe.js +0 -1
  458. package/ui/dist/assets/constants-Q5Zivl-a.js +0 -1
  459. package/ui/dist/assets/dialog-BUqN9Psj.js +0 -1
  460. package/ui/dist/assets/index-BUmnwPQr.js +0 -1
  461. package/ui/dist/assets/index-BfF5G4Cw.js +0 -1
  462. package/ui/dist/assets/index-C8N375c2.js +0 -1
  463. package/ui/dist/assets/index-CuxnqVVz.css +0 -1
  464. package/ui/dist/assets/index-CzMM3QOk.js +0 -1
  465. package/ui/dist/assets/index-lJlNPFVJ.js +0 -67
  466. package/ui/dist/assets/layers-jFqVrWMD.js +0 -1
  467. package/ui/dist/assets/markdown-renderer-n1ToC4XQ.js +0 -36
  468. package/ui/dist/assets/popover-CrmZgoWu.js +0 -1
  469. package/ui/dist/assets/progress-uv4SPkL5.js +0 -1
  470. package/ui/dist/assets/select-CeQ8AHGy.js +0 -1
  471. package/ui/dist/assets/server-CVHTZB72.js +0 -1
  472. package/ui/dist/assets/sheet-DuQExSho.js +0 -1
  473. package/ui/dist/assets/skeleton-TFiFJ3nB.js +0 -1
  474. package/ui/dist/assets/switch-CAePkd6k.js +0 -1
  475. package/ui/dist/assets/table-ZjAZ7hkt.js +0 -1
  476. package/ui/dist/assets/textarea-DsVPnSgR.js +0 -1
  477. package/ui/dist/assets/tooltip-BYmQ331W.js +0 -1
@@ -0,0 +1,495 @@
1
+ /**
2
+ * Multi-Agent Orchestrator
3
+ *
4
+ * Enables spawning, managing, and merging results from sub-agents.
5
+ * Supports orchestration patterns:
6
+ * - Fan-out: N parallel workers + 1 synthesizer
7
+ * - Pipeline: sequential agent chain (A -> B -> C)
8
+ * - Debate: 2+ agents argue, 1 judges
9
+ *
10
+ * Each sub-agent gets an isolated session with scoped tool access.
11
+ * Parent can set token budgets, timeouts, and tool policies per child.
12
+ */
13
+ import { randomUUID } from 'node:crypto';
14
+ import { createContextualLogger } from '../utils/logger.js';
15
+ const log = createContextualLogger('Orchestrator');
16
+ // Active orchestrations for cancellation
17
+ const activeOrchestrations = new Map();
18
+ /**
19
+ * Run a sub-agent in an isolated session.
20
+ */
21
+ async function runSubAgent(config, contextInput, signal) {
22
+ const startTime = Date.now();
23
+ try {
24
+ const { executeAgenticChat } = await import('../chat/agentic-executor.js');
25
+ const { createChatToolHandler } = await import('../chat/tool-handler.js');
26
+ const conversationId = `orchestrator-${config.id}-${randomUUID()}`;
27
+ const toolHandler = await createChatToolHandler({
28
+ conversationId,
29
+ securityMode: 'full',
30
+ });
31
+ // Filter tools if restricted
32
+ const allTools = toolHandler.getTools();
33
+ const tools = config.allowedTools?.length
34
+ ? allTools.filter((t) => config.allowedTools.includes(t.name))
35
+ : allTools;
36
+ // Build the prompt - inject pipeline context if provided
37
+ let fullPrompt = config.prompt;
38
+ if (contextInput) {
39
+ fullPrompt = `Context from previous step:\n${contextInput}\n\nYour task:\n${config.prompt}`;
40
+ }
41
+ const response = await Promise.race([
42
+ executeAgenticChat({
43
+ conversationId,
44
+ messages: [{
45
+ id: randomUUID(),
46
+ role: 'user',
47
+ content: fullPrompt,
48
+ timestamp: new Date().toISOString(),
49
+ }],
50
+ systemPrompt: config.systemPrompt || 'You are a focused AI agent working on a specific sub-task. Be concise and thorough.',
51
+ model: config.model,
52
+ effort: config.effort || 'medium',
53
+ toolHandler,
54
+ tools: tools.map((t) => ({
55
+ name: t.name,
56
+ description: t.description,
57
+ parameters: t.parameters,
58
+ })),
59
+ }),
60
+ new Promise((_, reject) => {
61
+ const timeout = config.timeoutMs || 300000;
62
+ const timer = setTimeout(() => reject(new Error(`Sub-agent "${config.name}" timed out after ${timeout}ms`)), timeout);
63
+ signal?.addEventListener('abort', () => {
64
+ clearTimeout(timer);
65
+ reject(new Error(`Sub-agent "${config.name}" cancelled`));
66
+ });
67
+ }),
68
+ ]);
69
+ return {
70
+ agentId: config.id,
71
+ agentName: config.name,
72
+ success: true,
73
+ output: response.content,
74
+ durationMs: Date.now() - startTime,
75
+ tokensUsed: response.usage?.totalTokens,
76
+ };
77
+ }
78
+ catch (error) {
79
+ return {
80
+ agentId: config.id,
81
+ agentName: config.name,
82
+ success: false,
83
+ output: '',
84
+ error: error instanceof Error ? error.message : String(error),
85
+ durationMs: Date.now() - startTime,
86
+ };
87
+ }
88
+ }
89
+ /**
90
+ * Execute a fan-out orchestration: run N agents in parallel, then synthesize.
91
+ */
92
+ async function executeFanOut(config, signal) {
93
+ const startTime = Date.now();
94
+ // Run all agents in parallel
95
+ const results = await Promise.allSettled(config.agents.map((agent) => runSubAgent(agent, undefined, signal)));
96
+ const agentResults = results.map((r, i) => {
97
+ if (r.status === 'fulfilled')
98
+ return r.value;
99
+ return {
100
+ agentId: config.agents[i].id,
101
+ agentName: config.agents[i].name,
102
+ success: false,
103
+ output: '',
104
+ error: r.reason instanceof Error ? r.reason.message : String(r.reason),
105
+ durationMs: Date.now() - startTime,
106
+ };
107
+ });
108
+ // Synthesize results
109
+ let finalOutput = '';
110
+ if (config.synthesizerPrompt) {
111
+ const synthesisInput = agentResults
112
+ .filter((r) => r.success)
113
+ .map((r) => `[${r.agentName}]:\n${r.output}`)
114
+ .join('\n\n---\n\n');
115
+ const synthesisResult = await runSubAgent({
116
+ id: 'synthesizer',
117
+ name: 'Synthesizer',
118
+ prompt: `${config.synthesizerPrompt}\n\nResults from ${agentResults.filter((r) => r.success).length} agents:\n\n${synthesisInput}`,
119
+ model: config.agents[0]?.model,
120
+ effort: 'medium',
121
+ }, undefined, signal);
122
+ agentResults.push(synthesisResult);
123
+ finalOutput = synthesisResult.output;
124
+ }
125
+ else {
126
+ finalOutput = agentResults
127
+ .filter((r) => r.success)
128
+ .map((r) => `## ${r.agentName}\n${r.output}`)
129
+ .join('\n\n');
130
+ }
131
+ const totalTokens = agentResults.reduce((sum, r) => sum + (r.tokensUsed || 0), 0);
132
+ return {
133
+ id: config.id,
134
+ pattern: 'fan_out',
135
+ success: agentResults.some((r) => r.success),
136
+ agentResults,
137
+ finalOutput,
138
+ totalDurationMs: Date.now() - startTime,
139
+ totalTokens,
140
+ };
141
+ }
142
+ /**
143
+ * Execute a pipeline orchestration: A -> B -> C
144
+ * Output of each agent becomes context for the next.
145
+ */
146
+ async function executePipeline(config, signal) {
147
+ const startTime = Date.now();
148
+ const agentResults = [];
149
+ let lastOutput = '';
150
+ for (const agent of config.agents) {
151
+ if (signal.aborted)
152
+ break;
153
+ const result = await runSubAgent(agent, lastOutput || undefined, signal);
154
+ agentResults.push(result);
155
+ if (!result.success && config.failFast) {
156
+ return {
157
+ id: config.id,
158
+ pattern: 'pipeline',
159
+ success: false,
160
+ agentResults,
161
+ finalOutput: '',
162
+ totalDurationMs: Date.now() - startTime,
163
+ totalTokens: agentResults.reduce((sum, r) => sum + (r.tokensUsed || 0), 0),
164
+ error: `Pipeline failed at step "${agent.name}": ${result.error}`,
165
+ };
166
+ }
167
+ if (result.success) {
168
+ lastOutput = result.output;
169
+ }
170
+ }
171
+ return {
172
+ id: config.id,
173
+ pattern: 'pipeline',
174
+ success: agentResults.some((r) => r.success),
175
+ agentResults,
176
+ finalOutput: lastOutput,
177
+ totalDurationMs: Date.now() - startTime,
178
+ totalTokens: agentResults.reduce((sum, r) => sum + (r.tokensUsed || 0), 0),
179
+ };
180
+ }
181
+ /**
182
+ * Execute a debate orchestration: agents argue, judge decides.
183
+ */
184
+ async function executeDebate(config, signal) {
185
+ const startTime = Date.now();
186
+ // Run debaters in parallel
187
+ const debaterResults = await Promise.allSettled(config.agents.map((agent) => runSubAgent(agent, undefined, signal)));
188
+ const agentResults = debaterResults.map((r, i) => {
189
+ if (r.status === 'fulfilled')
190
+ return r.value;
191
+ return {
192
+ agentId: config.agents[i].id,
193
+ agentName: config.agents[i].name,
194
+ success: false,
195
+ output: '',
196
+ error: r.reason instanceof Error ? r.reason.message : String(r.reason),
197
+ durationMs: Date.now() - startTime,
198
+ };
199
+ });
200
+ // Judge the debate
201
+ let finalOutput = '';
202
+ if (config.judgePrompt) {
203
+ const debateInput = agentResults
204
+ .filter((r) => r.success)
205
+ .map((r) => `[${r.agentName}] argues:\n${r.output}`)
206
+ .join('\n\n---\n\n');
207
+ const judgeResult = await runSubAgent({
208
+ id: 'judge',
209
+ name: 'Judge',
210
+ prompt: `${config.judgePrompt}\n\nArguments:\n\n${debateInput}`,
211
+ model: config.agents[0]?.model,
212
+ effort: 'high',
213
+ }, undefined, signal);
214
+ agentResults.push(judgeResult);
215
+ finalOutput = judgeResult.output;
216
+ }
217
+ else {
218
+ finalOutput = agentResults.filter((r) => r.success).map((r) => r.output).join('\n\n');
219
+ }
220
+ return {
221
+ id: config.id,
222
+ pattern: 'debate',
223
+ success: agentResults.some((r) => r.success),
224
+ agentResults,
225
+ finalOutput,
226
+ totalDurationMs: Date.now() - startTime,
227
+ totalTokens: agentResults.reduce((sum, r) => sum + (r.tokensUsed || 0), 0),
228
+ };
229
+ }
230
+ // Public API
231
+ /**
232
+ * Execute an orchestration.
233
+ */
234
+ export async function orchestrate(config) {
235
+ const abortController = new AbortController();
236
+ activeOrchestrations.set(config.id, abortController);
237
+ // Overall timeout
238
+ let timeoutHandle;
239
+ if (config.timeoutMs) {
240
+ timeoutHandle = setTimeout(() => abortController.abort(), config.timeoutMs);
241
+ }
242
+ log.info(`Starting orchestration: ${config.name} (${config.pattern}) with ${config.agents.length} agents`);
243
+ try {
244
+ let result;
245
+ switch (config.pattern) {
246
+ case 'fan_out':
247
+ result = await executeFanOut(config, abortController.signal);
248
+ break;
249
+ case 'pipeline':
250
+ result = await executePipeline(config, abortController.signal);
251
+ break;
252
+ case 'debate':
253
+ result = await executeDebate(config, abortController.signal);
254
+ break;
255
+ case 'custom':
256
+ // Custom: just run all in parallel (same as fan_out without synthesis)
257
+ result = await executeFanOut({ ...config, synthesizerPrompt: undefined }, abortController.signal);
258
+ break;
259
+ default:
260
+ throw new Error(`Unknown orchestration pattern: ${config.pattern}`);
261
+ }
262
+ log.info(`Orchestration complete: ${config.name} - ${result.success ? 'success' : 'failed'} in ${result.totalDurationMs}ms (${result.totalTokens} tokens)`);
263
+ return result;
264
+ }
265
+ finally {
266
+ if (timeoutHandle)
267
+ clearTimeout(timeoutHandle);
268
+ activeOrchestrations.delete(config.id);
269
+ }
270
+ }
271
+ /**
272
+ * Cancel a running orchestration.
273
+ */
274
+ export function cancelOrchestration(id) {
275
+ const controller = activeOrchestrations.get(id);
276
+ if (controller) {
277
+ controller.abort();
278
+ activeOrchestrations.delete(id);
279
+ log.info(`Cancelled orchestration: ${id}`);
280
+ return true;
281
+ }
282
+ return false;
283
+ }
284
+ /**
285
+ * List active orchestrations.
286
+ */
287
+ export function listActiveOrchestrations() {
288
+ return [...activeOrchestrations.keys()];
289
+ }
290
+ const DEFAULT_ORCHESTRATOR_CONFIG = {
291
+ maxConcurrent: 3,
292
+ timeoutMs: 300_000,
293
+ };
294
+ // Singleton instance
295
+ let _instance;
296
+ /**
297
+ * Class-based orchestrator for fan-out parallel sub-agent tasks.
298
+ *
299
+ * The caller provides an `apiCall` function that wraps the actual LLM API —
300
+ * following the same injected-client pattern used by ContextCompactor.
301
+ *
302
+ * Usage:
303
+ * ```ts
304
+ * const orch = getAgentOrchestrator({ maxConcurrent: 2 });
305
+ * const results = await orch.dispatch([
306
+ * { description: 'Summarise file A', prompt: '...' },
307
+ * { description: 'Summarise file B', prompt: '...' },
308
+ * ], myApiCall);
309
+ * console.log(orch.synthesize(results));
310
+ * ```
311
+ */
312
+ export class AgentOrchestrator {
313
+ tasks = new Map();
314
+ config;
315
+ /** Number of tasks currently in the 'running' state. */
316
+ running = 0;
317
+ /** Cancelled task IDs — checked before executing. */
318
+ cancelled = new Set();
319
+ constructor(config) {
320
+ this.config = { ...DEFAULT_ORCHESTRATOR_CONFIG, ...config };
321
+ }
322
+ // -------------------------------------------------------------------------
323
+ // Public API
324
+ // -------------------------------------------------------------------------
325
+ /**
326
+ * Dispatch multiple sub-tasks in parallel, respecting `maxConcurrent`.
327
+ * Resolves when every task has either completed, failed, or timed out.
328
+ */
329
+ async dispatch(taskDefs, apiCall) {
330
+ // Build task objects
331
+ const newTasks = taskDefs.map((def) => ({
332
+ id: randomUUID(),
333
+ description: def.description,
334
+ prompt: def.prompt,
335
+ status: 'pending',
336
+ tokensUsed: 0,
337
+ }));
338
+ for (const task of newTasks) {
339
+ this.tasks.set(task.id, task);
340
+ }
341
+ // Semaphore: release a "slot" whenever a task finishes so the next one starts.
342
+ const queue = [...newTasks];
343
+ const workers = [];
344
+ const next = () => {
345
+ const task = queue.shift();
346
+ if (!task)
347
+ return Promise.resolve();
348
+ if (this.cancelled.has(task.id)) {
349
+ task.status = 'failed';
350
+ task.error = 'Task was cancelled before it started';
351
+ return next();
352
+ }
353
+ this.running++;
354
+ return this.runTask(task, apiCall).then(() => {
355
+ this.running--;
356
+ return next();
357
+ });
358
+ };
359
+ // Seed up to maxConcurrent workers.
360
+ const concurrency = Math.min(this.config.maxConcurrent, newTasks.length);
361
+ for (let i = 0; i < concurrency; i++) {
362
+ workers.push(next());
363
+ }
364
+ await Promise.all(workers);
365
+ return newTasks;
366
+ }
367
+ /**
368
+ * Run a single sub-agent task with timeout and cancellation support.
369
+ * Mutates `task` in place and returns it.
370
+ */
371
+ async runTask(task, apiCall) {
372
+ if (this.cancelled.has(task.id)) {
373
+ task.status = 'failed';
374
+ task.error = 'Task was cancelled';
375
+ task.completedAt = Date.now();
376
+ return task;
377
+ }
378
+ task.status = 'running';
379
+ task.startedAt = Date.now();
380
+ const timeoutMs = this.config.timeoutMs;
381
+ try {
382
+ const result = await Promise.race([
383
+ apiCall(task.prompt),
384
+ new Promise((_, reject) => setTimeout(() => reject(new Error(`Task "${task.description}" timed out after ${timeoutMs}ms`)), timeoutMs)),
385
+ ]);
386
+ // Re-check cancellation — task may have been cancelled while the API call was in flight.
387
+ if (this.cancelled.has(task.id)) {
388
+ task.status = 'failed';
389
+ task.error = 'Task was cancelled';
390
+ }
391
+ else {
392
+ task.status = 'completed';
393
+ task.result = result;
394
+ }
395
+ }
396
+ catch (error) {
397
+ task.status = 'failed';
398
+ task.error = error instanceof Error ? error.message : String(error);
399
+ log.warn(`Sub-agent task failed: ${task.description} — ${task.error}`);
400
+ }
401
+ finally {
402
+ task.completedAt = Date.now();
403
+ }
404
+ return task;
405
+ }
406
+ /**
407
+ * Return a snapshot of all tasks tracked by this orchestrator.
408
+ */
409
+ getStatus() {
410
+ return [...this.tasks.values()];
411
+ }
412
+ /**
413
+ * Mark a task as cancelled. If it is still pending it will be skipped
414
+ * entirely; if it is already running the next post-API-call check will
415
+ * mark it failed.
416
+ */
417
+ cancel(taskId) {
418
+ this.cancelled.add(taskId);
419
+ const task = this.tasks.get(taskId);
420
+ if (task && task.status === 'pending') {
421
+ task.status = 'failed';
422
+ task.error = 'Task was cancelled';
423
+ task.completedAt = Date.now();
424
+ log.info(`Cancelled pending task: ${taskId}`);
425
+ }
426
+ }
427
+ /**
428
+ * Build a markdown summary of completed task results.
429
+ *
430
+ * ```markdown
431
+ * ## Task Results
432
+ * ### 1. Summarise file A ✓
433
+ * <result text>
434
+ * ### 2. Summarise file B ✗
435
+ * Error: timed out after 300000ms
436
+ * ```
437
+ */
438
+ synthesize(tasks) {
439
+ const lines = ['## Task Results', ''];
440
+ tasks.forEach((task, index) => {
441
+ const marker = task.status === 'completed' ? '✓' : '✗';
442
+ lines.push(`### ${index + 1}. ${task.description} ${marker}`);
443
+ if (task.status === 'completed' && task.result) {
444
+ lines.push(task.result);
445
+ }
446
+ else if (task.status === 'failed') {
447
+ lines.push(`Error: ${task.error ?? 'Unknown error'}`);
448
+ }
449
+ else {
450
+ lines.push(`Status: ${task.status}`);
451
+ }
452
+ lines.push('');
453
+ });
454
+ return lines.join('\n').trimEnd();
455
+ }
456
+ /**
457
+ * Wait until all currently-tracked tasks have left the 'pending' or
458
+ * 'running' state, or until the optional `timeoutMs` elapses.
459
+ *
460
+ * Resolves with the current task snapshot once settled.
461
+ */
462
+ async waitAll(timeoutMs) {
463
+ const poll = () => [...this.tasks.values()].every((t) => t.status === 'completed' || t.status === 'failed');
464
+ if (poll())
465
+ return this.getStatus();
466
+ const deadline = timeoutMs ? Date.now() + timeoutMs : Infinity;
467
+ const INTERVAL = 50;
468
+ return new Promise((resolve) => {
469
+ const check = () => {
470
+ if (poll()) {
471
+ resolve(this.getStatus());
472
+ return;
473
+ }
474
+ if (Date.now() >= deadline) {
475
+ resolve(this.getStatus());
476
+ return;
477
+ }
478
+ setTimeout(check, INTERVAL);
479
+ };
480
+ setTimeout(check, INTERVAL);
481
+ });
482
+ }
483
+ }
484
+ /**
485
+ * Return a lazily-created singleton `AgentOrchestrator`.
486
+ * Pass `config` on first call to customise defaults; subsequent calls with
487
+ * a different config will replace the singleton.
488
+ */
489
+ export function getAgentOrchestrator(config) {
490
+ if (!_instance || config) {
491
+ _instance = new AgentOrchestrator(config);
492
+ }
493
+ return _instance;
494
+ }
495
+ //# sourceMappingURL=orchestrator.js.map
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Permission Dialog System
3
+ *
4
+ * Manages per-session tool permissions with configurable rules.
5
+ * Dangerous tools always prompt; cautious tools prompt once then remember;
6
+ * safe tools (or unknown tools) are auto-allowed.
7
+ */
8
+ export type PermissionLevel = 'safe' | 'cautious' | 'dangerous';
9
+ export type PermissionResponse = 'allow' | 'deny' | 'always_allow' | 'always_deny';
10
+ export interface PermissionRule {
11
+ toolName: string;
12
+ level: PermissionLevel;
13
+ reason: string;
14
+ }
15
+ export interface PermissionState {
16
+ /** Tools permanently allowed for this session */
17
+ autoAllow: Set<string>;
18
+ /** Tools permanently denied for this session */
19
+ autoDeny: Set<string>;
20
+ }
21
+ export interface PermissionCheckResult {
22
+ allowed: boolean;
23
+ reason?: string;
24
+ }
25
+ export declare const DEFAULT_PERMISSION_RULES: PermissionRule[];
26
+ type PromptCallback = (toolName: string, args: unknown, rule: PermissionRule) => Promise<PermissionResponse>;
27
+ export declare class PermissionManager {
28
+ private state;
29
+ private rules;
30
+ private promptCallback?;
31
+ constructor(rules?: PermissionRule[]);
32
+ /**
33
+ * Register the interactive prompt callback.
34
+ * Without this, all tools (including dangerous ones) are allowed — non-interactive mode.
35
+ */
36
+ setPromptCallback(cb: PromptCallback): void;
37
+ /**
38
+ * Check whether a tool call is permitted.
39
+ *
40
+ * Resolution order:
41
+ * 1. autoAllow set → allowed immediately
42
+ * 2. autoDeny set → denied immediately
43
+ * 3. No rule / safe → allowed
44
+ * 4. cautious/dangerous → invoke promptCallback
45
+ * - allow → allow once
46
+ * - deny → deny once
47
+ * - always_allow → add to autoAllow, allow
48
+ * - always_deny → add to autoDeny, deny
49
+ * 5. No callback registered → allow (non-interactive)
50
+ */
51
+ check(toolName: string, args?: unknown): Promise<PermissionCheckResult>;
52
+ /**
53
+ * Return the permission level for a tool, or 'safe' if no rule exists.
54
+ */
55
+ getLevel(toolName: string): PermissionLevel;
56
+ /**
57
+ * Clear session-level autoAllow/autoDeny sets.
58
+ * Useful when starting a fresh session without constructing a new manager.
59
+ */
60
+ reset(): void;
61
+ }
62
+ export {};
63
+ //# sourceMappingURL=permissions.d.ts.map
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Permission Dialog System
3
+ *
4
+ * Manages per-session tool permissions with configurable rules.
5
+ * Dangerous tools always prompt; cautious tools prompt once then remember;
6
+ * safe tools (or unknown tools) are auto-allowed.
7
+ */
8
+ import { createContextualLogger } from '../utils/logger.js';
9
+ const log = createContextualLogger('PermissionManager');
10
+ // ---------------------------------------------------------------------------
11
+ // Default rules
12
+ // ---------------------------------------------------------------------------
13
+ export const DEFAULT_PERMISSION_RULES = [
14
+ // Dangerous — always ask
15
+ { toolName: 'bash', level: 'dangerous', reason: 'Executes arbitrary shell commands' },
16
+ { toolName: 'exec', level: 'dangerous', reason: 'Executes arbitrary shell commands' },
17
+ { toolName: 'delete_file', level: 'dangerous', reason: 'Permanently deletes files' },
18
+ { toolName: 'git_push', level: 'dangerous', reason: 'Pushes changes to remote repository' },
19
+ {
20
+ toolName: 'git_force_push',
21
+ level: 'dangerous',
22
+ reason: 'Force pushes, potentially losing remote changes',
23
+ },
24
+ // Cautious — ask first time, then remember
25
+ { toolName: 'write_file', level: 'cautious', reason: 'Modifies files on disk' },
26
+ { toolName: 'patch_file', level: 'cautious', reason: 'Modifies files on disk' },
27
+ { toolName: 'move_file', level: 'cautious', reason: 'Moves/renames files' },
28
+ { toolName: 'git_commit', level: 'cautious', reason: 'Creates git commits' },
29
+ { toolName: 'git_branch', level: 'cautious', reason: 'Creates/switches git branches' },
30
+ // Safe — auto-allow (read_file, search_files, git_status, git_diff, etc.)
31
+ ];
32
+ export class PermissionManager {
33
+ state;
34
+ rules;
35
+ promptCallback;
36
+ constructor(rules = DEFAULT_PERMISSION_RULES) {
37
+ this.state = {
38
+ autoAllow: new Set(),
39
+ autoDeny: new Set(),
40
+ };
41
+ this.rules = new Map();
42
+ for (const rule of rules) {
43
+ this.rules.set(rule.toolName, rule);
44
+ }
45
+ }
46
+ /**
47
+ * Register the interactive prompt callback.
48
+ * Without this, all tools (including dangerous ones) are allowed — non-interactive mode.
49
+ */
50
+ setPromptCallback(cb) {
51
+ this.promptCallback = cb;
52
+ }
53
+ /**
54
+ * Check whether a tool call is permitted.
55
+ *
56
+ * Resolution order:
57
+ * 1. autoAllow set → allowed immediately
58
+ * 2. autoDeny set → denied immediately
59
+ * 3. No rule / safe → allowed
60
+ * 4. cautious/dangerous → invoke promptCallback
61
+ * - allow → allow once
62
+ * - deny → deny once
63
+ * - always_allow → add to autoAllow, allow
64
+ * - always_deny → add to autoDeny, deny
65
+ * 5. No callback registered → allow (non-interactive)
66
+ */
67
+ async check(toolName, args) {
68
+ // 1. Session-level auto-allow
69
+ if (this.state.autoAllow.has(toolName)) {
70
+ log.debug('Tool auto-allowed (session rule)', { tool: toolName });
71
+ return { allowed: true };
72
+ }
73
+ // 2. Session-level auto-deny
74
+ if (this.state.autoDeny.has(toolName)) {
75
+ log.info('Tool auto-denied (session rule)', { tool: toolName });
76
+ return { allowed: false, reason: `Tool "${toolName}" has been denied for this session` };
77
+ }
78
+ // 3. Look up permission rule
79
+ const rule = this.rules.get(toolName);
80
+ if (!rule || rule.level === 'safe') {
81
+ return { allowed: true };
82
+ }
83
+ // 4. cautious or dangerous — need user confirmation
84
+ if (!this.promptCallback) {
85
+ // Non-interactive mode: allow but log
86
+ log.warn('No prompt callback registered — allowing tool in non-interactive mode', {
87
+ tool: toolName,
88
+ level: rule.level,
89
+ });
90
+ return { allowed: true };
91
+ }
92
+ log.debug('Prompting user for permission', { tool: toolName, level: rule.level });
93
+ let response;
94
+ try {
95
+ response = await this.promptCallback(toolName, args, rule);
96
+ }
97
+ catch (error) {
98
+ log.error('[PermissionManager] Prompt callback threw', {
99
+ tool: toolName,
100
+ error: error instanceof Error ? error.message : String(error),
101
+ });
102
+ // Fail-safe: deny on callback error
103
+ return { allowed: false, reason: 'Permission prompt failed' };
104
+ }
105
+ switch (response) {
106
+ case 'allow':
107
+ log.debug('User allowed tool (once)', { tool: toolName });
108
+ return { allowed: true };
109
+ case 'deny':
110
+ log.info('User denied tool (once)', { tool: toolName });
111
+ return { allowed: false, reason: `User denied "${toolName}"` };
112
+ case 'always_allow':
113
+ this.state.autoAllow.add(toolName);
114
+ log.info('User always-allowed tool for session', { tool: toolName });
115
+ return { allowed: true };
116
+ case 'always_deny':
117
+ this.state.autoDeny.add(toolName);
118
+ log.info('User always-denied tool for session', { tool: toolName });
119
+ return { allowed: false, reason: `User permanently denied "${toolName}" for this session` };
120
+ }
121
+ }
122
+ /**
123
+ * Return the permission level for a tool, or 'safe' if no rule exists.
124
+ */
125
+ getLevel(toolName) {
126
+ return this.rules.get(toolName)?.level ?? 'safe';
127
+ }
128
+ /**
129
+ * Clear session-level autoAllow/autoDeny sets.
130
+ * Useful when starting a fresh session without constructing a new manager.
131
+ */
132
+ reset() {
133
+ this.state.autoAllow.clear();
134
+ this.state.autoDeny.clear();
135
+ log.debug('PermissionManager session state reset');
136
+ }
137
+ }
138
+ //# sourceMappingURL=permissions.js.map