swarm-engine 1.0.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 (431) hide show
  1. package/AGENTS.md +72 -0
  2. package/CLAUDE.md +89 -0
  3. package/LICENSE +21 -0
  4. package/README.md +235 -0
  5. package/agents/accessibility-reviewer.md +118 -0
  6. package/agents/api-contract-reviewer.md +99 -0
  7. package/agents/concurrency-reviewer.md +111 -0
  8. package/agents/data-integrity-reviewer.md +103 -0
  9. package/agents/debugger.md +99 -0
  10. package/agents/dependency-reviewer.md +115 -0
  11. package/agents/devils-advocate.md +94 -0
  12. package/agents/documentation-reviewer.md +114 -0
  13. package/agents/documenter.md +78 -0
  14. package/agents/error-handling-reviewer.md +113 -0
  15. package/agents/grounding.md +99 -0
  16. package/agents/guardian.md +87 -0
  17. package/agents/implementer.md +141 -0
  18. package/agents/integrator.md +95 -0
  19. package/agents/judge.md +79 -0
  20. package/agents/librarian.md +90 -0
  21. package/agents/orchestrator.md +331 -0
  22. package/agents/performance-reviewer.md +93 -0
  23. package/agents/planner.md +106 -0
  24. package/agents/refactorer.md +92 -0
  25. package/agents/researcher.md +97 -0
  26. package/agents/reviewer.md +117 -0
  27. package/agents/security-reviewer.md +107 -0
  28. package/agents/sentinel.md +92 -0
  29. package/agents/tester.md +93 -0
  30. package/agents/testing-reviewer.md +112 -0
  31. package/commands/diff-review.md +64 -0
  32. package/commands/fix-pr.md +78 -0
  33. package/commands/red-team.md +82 -0
  34. package/commands/research.md +59 -0
  35. package/commands/resume.md +80 -0
  36. package/commands/review-cycle.md +123 -0
  37. package/commands/swarm-setup.md +28 -0
  38. package/commands/swarm.md +126 -0
  39. package/commands/tdd.md +91 -0
  40. package/dist/cli/bin.d.ts +3 -0
  41. package/dist/cli/bin.d.ts.map +1 -0
  42. package/dist/cli/bin.js +3 -0
  43. package/dist/cli/bin.js.map +1 -0
  44. package/dist/cli/commands/acp.d.ts +3 -0
  45. package/dist/cli/commands/acp.d.ts.map +1 -0
  46. package/dist/cli/commands/acp.js +29 -0
  47. package/dist/cli/commands/acp.js.map +1 -0
  48. package/dist/cli/commands/agents.d.ts +3 -0
  49. package/dist/cli/commands/agents.d.ts.map +1 -0
  50. package/dist/cli/commands/agents.js +344 -0
  51. package/dist/cli/commands/agents.js.map +1 -0
  52. package/dist/cli/commands/backends.d.ts +3 -0
  53. package/dist/cli/commands/backends.d.ts.map +1 -0
  54. package/dist/cli/commands/backends.js +22 -0
  55. package/dist/cli/commands/backends.js.map +1 -0
  56. package/dist/cli/commands/completions.d.ts +3 -0
  57. package/dist/cli/commands/completions.d.ts.map +1 -0
  58. package/dist/cli/commands/completions.js +85 -0
  59. package/dist/cli/commands/completions.js.map +1 -0
  60. package/dist/cli/commands/compound.d.ts +3 -0
  61. package/dist/cli/commands/compound.d.ts.map +1 -0
  62. package/dist/cli/commands/compound.js +119 -0
  63. package/dist/cli/commands/compound.js.map +1 -0
  64. package/dist/cli/commands/configure.d.ts +3 -0
  65. package/dist/cli/commands/configure.d.ts.map +1 -0
  66. package/dist/cli/commands/configure.js +151 -0
  67. package/dist/cli/commands/configure.js.map +1 -0
  68. package/dist/cli/commands/convert.d.ts +15 -0
  69. package/dist/cli/commands/convert.d.ts.map +1 -0
  70. package/dist/cli/commands/convert.js +218 -0
  71. package/dist/cli/commands/convert.js.map +1 -0
  72. package/dist/cli/commands/doctor.d.ts +3 -0
  73. package/dist/cli/commands/doctor.d.ts.map +1 -0
  74. package/dist/cli/commands/doctor.js +96 -0
  75. package/dist/cli/commands/doctor.js.map +1 -0
  76. package/dist/cli/commands/init.d.ts +3 -0
  77. package/dist/cli/commands/init.d.ts.map +1 -0
  78. package/dist/cli/commands/init.js +154 -0
  79. package/dist/cli/commands/init.js.map +1 -0
  80. package/dist/cli/commands/learn.d.ts +3 -0
  81. package/dist/cli/commands/learn.d.ts.map +1 -0
  82. package/dist/cli/commands/learn.js +163 -0
  83. package/dist/cli/commands/learn.js.map +1 -0
  84. package/dist/cli/commands/mcp.d.ts +3 -0
  85. package/dist/cli/commands/mcp.d.ts.map +1 -0
  86. package/dist/cli/commands/mcp.js +89 -0
  87. package/dist/cli/commands/mcp.js.map +1 -0
  88. package/dist/cli/commands/memory.d.ts +3 -0
  89. package/dist/cli/commands/memory.d.ts.map +1 -0
  90. package/dist/cli/commands/memory.js +134 -0
  91. package/dist/cli/commands/memory.js.map +1 -0
  92. package/dist/cli/commands/orchestrate.d.ts +3 -0
  93. package/dist/cli/commands/orchestrate.d.ts.map +1 -0
  94. package/dist/cli/commands/orchestrate.js +237 -0
  95. package/dist/cli/commands/orchestrate.js.map +1 -0
  96. package/dist/cli/commands/patterns.d.ts +3 -0
  97. package/dist/cli/commands/patterns.d.ts.map +1 -0
  98. package/dist/cli/commands/patterns.js +25 -0
  99. package/dist/cli/commands/patterns.js.map +1 -0
  100. package/dist/cli/commands/plan.d.ts +3 -0
  101. package/dist/cli/commands/plan.d.ts.map +1 -0
  102. package/dist/cli/commands/plan.js +77 -0
  103. package/dist/cli/commands/plan.js.map +1 -0
  104. package/dist/cli/commands/plugin.d.ts +3 -0
  105. package/dist/cli/commands/plugin.d.ts.map +1 -0
  106. package/dist/cli/commands/plugin.js +124 -0
  107. package/dist/cli/commands/plugin.js.map +1 -0
  108. package/dist/cli/commands/resume.d.ts +3 -0
  109. package/dist/cli/commands/resume.d.ts.map +1 -0
  110. package/dist/cli/commands/resume.js +55 -0
  111. package/dist/cli/commands/resume.js.map +1 -0
  112. package/dist/cli/commands/run.d.ts +3 -0
  113. package/dist/cli/commands/run.d.ts.map +1 -0
  114. package/dist/cli/commands/run.js +78 -0
  115. package/dist/cli/commands/run.js.map +1 -0
  116. package/dist/cli/commands/share.d.ts +3 -0
  117. package/dist/cli/commands/share.d.ts.map +1 -0
  118. package/dist/cli/commands/share.js +34 -0
  119. package/dist/cli/commands/share.js.map +1 -0
  120. package/dist/cli/commands/status.d.ts +3 -0
  121. package/dist/cli/commands/status.d.ts.map +1 -0
  122. package/dist/cli/commands/status.js +148 -0
  123. package/dist/cli/commands/status.js.map +1 -0
  124. package/dist/cli/commands/template.d.ts +3 -0
  125. package/dist/cli/commands/template.d.ts.map +1 -0
  126. package/dist/cli/commands/template.js +213 -0
  127. package/dist/cli/commands/template.js.map +1 -0
  128. package/dist/cli/commands/vault.d.ts +3 -0
  129. package/dist/cli/commands/vault.d.ts.map +1 -0
  130. package/dist/cli/commands/vault.js +402 -0
  131. package/dist/cli/commands/vault.js.map +1 -0
  132. package/dist/cli/commands/verify.d.ts +3 -0
  133. package/dist/cli/commands/verify.d.ts.map +1 -0
  134. package/dist/cli/commands/verify.js +38 -0
  135. package/dist/cli/commands/verify.js.map +1 -0
  136. package/dist/cli/commands/version.d.ts +3 -0
  137. package/dist/cli/commands/version.d.ts.map +1 -0
  138. package/dist/cli/commands/version.js +19 -0
  139. package/dist/cli/commands/version.js.map +1 -0
  140. package/dist/cli/commands/watch.d.ts +3 -0
  141. package/dist/cli/commands/watch.d.ts.map +1 -0
  142. package/dist/cli/commands/watch.js +179 -0
  143. package/dist/cli/commands/watch.js.map +1 -0
  144. package/dist/cli/index.d.ts +3 -0
  145. package/dist/cli/index.d.ts.map +1 -0
  146. package/dist/cli/index.js +118 -0
  147. package/dist/cli/index.js.map +1 -0
  148. package/dist/core/checkpoint.d.ts +35 -0
  149. package/dist/core/checkpoint.d.ts.map +1 -0
  150. package/dist/core/checkpoint.js +80 -0
  151. package/dist/core/checkpoint.js.map +1 -0
  152. package/dist/core/event-bus.d.ts +41 -0
  153. package/dist/core/event-bus.d.ts.map +1 -0
  154. package/dist/core/event-bus.js +115 -0
  155. package/dist/core/event-bus.js.map +1 -0
  156. package/dist/core/lifecycle.d.ts +30 -0
  157. package/dist/core/lifecycle.d.ts.map +1 -0
  158. package/dist/core/lifecycle.js +72 -0
  159. package/dist/core/lifecycle.js.map +1 -0
  160. package/dist/core/patterns.d.ts +43 -0
  161. package/dist/core/patterns.d.ts.map +1 -0
  162. package/dist/core/patterns.js +372 -0
  163. package/dist/core/patterns.js.map +1 -0
  164. package/dist/core/permissions.d.ts +40 -0
  165. package/dist/core/permissions.d.ts.map +1 -0
  166. package/dist/core/permissions.js +113 -0
  167. package/dist/core/permissions.js.map +1 -0
  168. package/dist/core/registry.d.ts +80 -0
  169. package/dist/core/registry.d.ts.map +1 -0
  170. package/dist/core/registry.js +308 -0
  171. package/dist/core/registry.js.map +1 -0
  172. package/dist/core/snapshots.d.ts +20 -0
  173. package/dist/core/snapshots.d.ts.map +1 -0
  174. package/dist/core/snapshots.js +73 -0
  175. package/dist/core/snapshots.js.map +1 -0
  176. package/dist/core/types.d.ts +168 -0
  177. package/dist/core/types.d.ts.map +1 -0
  178. package/dist/core/types.js +33 -0
  179. package/dist/core/types.js.map +1 -0
  180. package/dist/hooks/cli.d.ts +11 -0
  181. package/dist/hooks/cli.d.ts.map +1 -0
  182. package/dist/hooks/cli.js +32 -0
  183. package/dist/hooks/cli.js.map +1 -0
  184. package/dist/hooks/index.d.ts +23 -0
  185. package/dist/hooks/index.d.ts.map +1 -0
  186. package/dist/hooks/index.js +58 -0
  187. package/dist/hooks/index.js.map +1 -0
  188. package/dist/index.d.ts +82 -0
  189. package/dist/index.d.ts.map +1 -0
  190. package/dist/index.js +49 -0
  191. package/dist/index.js.map +1 -0
  192. package/dist/memory/index.d.ts +105 -0
  193. package/dist/memory/index.d.ts.map +1 -0
  194. package/dist/memory/index.js +298 -0
  195. package/dist/memory/index.js.map +1 -0
  196. package/dist/memory/schema.d.ts +6 -0
  197. package/dist/memory/schema.d.ts.map +1 -0
  198. package/dist/memory/schema.js +71 -0
  199. package/dist/memory/schema.js.map +1 -0
  200. package/dist/plugin/index.d.ts +6 -0
  201. package/dist/plugin/index.d.ts.map +1 -0
  202. package/dist/plugin/index.js +182 -0
  203. package/dist/plugin/index.js.map +1 -0
  204. package/dist/runtime/acp.d.ts +41 -0
  205. package/dist/runtime/acp.d.ts.map +1 -0
  206. package/dist/runtime/acp.js +137 -0
  207. package/dist/runtime/acp.js.map +1 -0
  208. package/dist/runtime/adaptive.d.ts +34 -0
  209. package/dist/runtime/adaptive.d.ts.map +1 -0
  210. package/dist/runtime/adaptive.js +229 -0
  211. package/dist/runtime/adaptive.js.map +1 -0
  212. package/dist/runtime/autonomy.d.ts +21 -0
  213. package/dist/runtime/autonomy.d.ts.map +1 -0
  214. package/dist/runtime/autonomy.js +74 -0
  215. package/dist/runtime/autonomy.js.map +1 -0
  216. package/dist/runtime/backends/claude.d.ts +9 -0
  217. package/dist/runtime/backends/claude.d.ts.map +1 -0
  218. package/dist/runtime/backends/claude.js +134 -0
  219. package/dist/runtime/backends/claude.js.map +1 -0
  220. package/dist/runtime/backends/codex.d.ts +9 -0
  221. package/dist/runtime/backends/codex.d.ts.map +1 -0
  222. package/dist/runtime/backends/codex.js +132 -0
  223. package/dist/runtime/backends/codex.js.map +1 -0
  224. package/dist/runtime/backends/gemini.d.ts +9 -0
  225. package/dist/runtime/backends/gemini.d.ts.map +1 -0
  226. package/dist/runtime/backends/gemini.js +103 -0
  227. package/dist/runtime/backends/gemini.js.map +1 -0
  228. package/dist/runtime/backends/index.d.ts +17 -0
  229. package/dist/runtime/backends/index.d.ts.map +1 -0
  230. package/dist/runtime/backends/index.js +39 -0
  231. package/dist/runtime/backends/index.js.map +1 -0
  232. package/dist/runtime/backends/mock.d.ts +21 -0
  233. package/dist/runtime/backends/mock.d.ts.map +1 -0
  234. package/dist/runtime/backends/mock.js +46 -0
  235. package/dist/runtime/backends/mock.js.map +1 -0
  236. package/dist/runtime/backends/types.d.ts +34 -0
  237. package/dist/runtime/backends/types.d.ts.map +1 -0
  238. package/dist/runtime/backends/types.js +2 -0
  239. package/dist/runtime/backends/types.js.map +1 -0
  240. package/dist/runtime/backends/vercel-ai.d.ts +14 -0
  241. package/dist/runtime/backends/vercel-ai.d.ts.map +1 -0
  242. package/dist/runtime/backends/vercel-ai.js +137 -0
  243. package/dist/runtime/backends/vercel-ai.js.map +1 -0
  244. package/dist/runtime/cache-optimizer.d.ts +37 -0
  245. package/dist/runtime/cache-optimizer.d.ts.map +1 -0
  246. package/dist/runtime/cache-optimizer.js +54 -0
  247. package/dist/runtime/cache-optimizer.js.map +1 -0
  248. package/dist/runtime/cascade.d.ts +26 -0
  249. package/dist/runtime/cascade.d.ts.map +1 -0
  250. package/dist/runtime/cascade.js +54 -0
  251. package/dist/runtime/cascade.js.map +1 -0
  252. package/dist/runtime/chunker.d.ts +36 -0
  253. package/dist/runtime/chunker.d.ts.map +1 -0
  254. package/dist/runtime/chunker.js +210 -0
  255. package/dist/runtime/chunker.js.map +1 -0
  256. package/dist/runtime/compaction.d.ts +22 -0
  257. package/dist/runtime/compaction.d.ts.map +1 -0
  258. package/dist/runtime/compaction.js +36 -0
  259. package/dist/runtime/compaction.js.map +1 -0
  260. package/dist/runtime/compounder.d.ts +66 -0
  261. package/dist/runtime/compounder.d.ts.map +1 -0
  262. package/dist/runtime/compounder.js +276 -0
  263. package/dist/runtime/compounder.js.map +1 -0
  264. package/dist/runtime/cost-model.d.ts +24 -0
  265. package/dist/runtime/cost-model.d.ts.map +1 -0
  266. package/dist/runtime/cost-model.js +120 -0
  267. package/dist/runtime/cost-model.js.map +1 -0
  268. package/dist/runtime/distiller.d.ts +21 -0
  269. package/dist/runtime/distiller.d.ts.map +1 -0
  270. package/dist/runtime/distiller.js +70 -0
  271. package/dist/runtime/distiller.js.map +1 -0
  272. package/dist/runtime/engine.d.ts +123 -0
  273. package/dist/runtime/engine.d.ts.map +1 -0
  274. package/dist/runtime/engine.js +969 -0
  275. package/dist/runtime/engine.js.map +1 -0
  276. package/dist/runtime/executor.d.ts +71 -0
  277. package/dist/runtime/executor.d.ts.map +1 -0
  278. package/dist/runtime/executor.js +283 -0
  279. package/dist/runtime/executor.js.map +1 -0
  280. package/dist/runtime/heuristics.d.ts +33 -0
  281. package/dist/runtime/heuristics.d.ts.map +1 -0
  282. package/dist/runtime/heuristics.js +188 -0
  283. package/dist/runtime/heuristics.js.map +1 -0
  284. package/dist/runtime/living-spec.d.ts +34 -0
  285. package/dist/runtime/living-spec.d.ts.map +1 -0
  286. package/dist/runtime/living-spec.js +91 -0
  287. package/dist/runtime/living-spec.js.map +1 -0
  288. package/dist/runtime/lsp.d.ts +50 -0
  289. package/dist/runtime/lsp.d.ts.map +1 -0
  290. package/dist/runtime/lsp.js +110 -0
  291. package/dist/runtime/lsp.js.map +1 -0
  292. package/dist/runtime/mcp.d.ts +27 -0
  293. package/dist/runtime/mcp.d.ts.map +1 -0
  294. package/dist/runtime/mcp.js +154 -0
  295. package/dist/runtime/mcp.js.map +1 -0
  296. package/dist/runtime/model-router.d.ts +22 -0
  297. package/dist/runtime/model-router.d.ts.map +1 -0
  298. package/dist/runtime/model-router.js +94 -0
  299. package/dist/runtime/model-router.js.map +1 -0
  300. package/dist/runtime/panes.d.ts +76 -0
  301. package/dist/runtime/panes.d.ts.map +1 -0
  302. package/dist/runtime/panes.js +279 -0
  303. package/dist/runtime/panes.js.map +1 -0
  304. package/dist/runtime/plan-search.d.ts +41 -0
  305. package/dist/runtime/plan-search.d.ts.map +1 -0
  306. package/dist/runtime/plan-search.js +140 -0
  307. package/dist/runtime/plan-search.js.map +1 -0
  308. package/dist/runtime/plugins.d.ts +59 -0
  309. package/dist/runtime/plugins.d.ts.map +1 -0
  310. package/dist/runtime/plugins.js +121 -0
  311. package/dist/runtime/plugins.js.map +1 -0
  312. package/dist/runtime/reflexion.d.ts +22 -0
  313. package/dist/runtime/reflexion.d.ts.map +1 -0
  314. package/dist/runtime/reflexion.js +85 -0
  315. package/dist/runtime/reflexion.js.map +1 -0
  316. package/dist/runtime/review-schema.d.ts +75 -0
  317. package/dist/runtime/review-schema.d.ts.map +1 -0
  318. package/dist/runtime/review-schema.js +223 -0
  319. package/dist/runtime/review-schema.js.map +1 -0
  320. package/dist/runtime/rewriter.d.ts +8 -0
  321. package/dist/runtime/rewriter.d.ts.map +1 -0
  322. package/dist/runtime/rewriter.js +81 -0
  323. package/dist/runtime/rewriter.js.map +1 -0
  324. package/dist/runtime/sharing.d.ts +15 -0
  325. package/dist/runtime/sharing.d.ts.map +1 -0
  326. package/dist/runtime/sharing.js +48 -0
  327. package/dist/runtime/sharing.js.map +1 -0
  328. package/dist/runtime/stats.d.ts +53 -0
  329. package/dist/runtime/stats.d.ts.map +1 -0
  330. package/dist/runtime/stats.js +160 -0
  331. package/dist/runtime/stats.js.map +1 -0
  332. package/dist/runtime/templates.d.ts +77 -0
  333. package/dist/runtime/templates.d.ts.map +1 -0
  334. package/dist/runtime/templates.js +221 -0
  335. package/dist/runtime/templates.js.map +1 -0
  336. package/dist/runtime/traces.d.ts +60 -0
  337. package/dist/runtime/traces.d.ts.map +1 -0
  338. package/dist/runtime/traces.js +166 -0
  339. package/dist/runtime/traces.js.map +1 -0
  340. package/dist/runtime/verifier.d.ts +54 -0
  341. package/dist/runtime/verifier.d.ts.map +1 -0
  342. package/dist/runtime/verifier.js +172 -0
  343. package/dist/runtime/verifier.js.map +1 -0
  344. package/dist/runtime/worktree.d.ts +24 -0
  345. package/dist/runtime/worktree.d.ts.map +1 -0
  346. package/dist/runtime/worktree.js +82 -0
  347. package/dist/runtime/worktree.js.map +1 -0
  348. package/dist/tui/dashboard.d.ts +65 -0
  349. package/dist/tui/dashboard.d.ts.map +1 -0
  350. package/dist/tui/dashboard.js +496 -0
  351. package/dist/tui/dashboard.js.map +1 -0
  352. package/dist/tui/progress.d.ts +32 -0
  353. package/dist/tui/progress.d.ts.map +1 -0
  354. package/dist/tui/progress.js +257 -0
  355. package/dist/tui/progress.js.map +1 -0
  356. package/dist/tui/renderer.d.ts +72 -0
  357. package/dist/tui/renderer.d.ts.map +1 -0
  358. package/dist/tui/renderer.js +205 -0
  359. package/dist/tui/renderer.js.map +1 -0
  360. package/dist/utils/compact-format.d.ts +35 -0
  361. package/dist/utils/compact-format.d.ts.map +1 -0
  362. package/dist/utils/compact-format.js +106 -0
  363. package/dist/utils/compact-format.js.map +1 -0
  364. package/dist/utils/config.d.ts +73 -0
  365. package/dist/utils/config.d.ts.map +1 -0
  366. package/dist/utils/config.js +70 -0
  367. package/dist/utils/config.js.map +1 -0
  368. package/dist/utils/env.d.ts +6 -0
  369. package/dist/utils/env.d.ts.map +1 -0
  370. package/dist/utils/env.js +28 -0
  371. package/dist/utils/env.js.map +1 -0
  372. package/dist/utils/errors.d.ts +14 -0
  373. package/dist/utils/errors.d.ts.map +1 -0
  374. package/dist/utils/errors.js +120 -0
  375. package/dist/utils/errors.js.map +1 -0
  376. package/dist/utils/logger.d.ts +14 -0
  377. package/dist/utils/logger.d.ts.map +1 -0
  378. package/dist/utils/logger.js +56 -0
  379. package/dist/utils/logger.js.map +1 -0
  380. package/dist/utils/output.d.ts +10 -0
  381. package/dist/utils/output.d.ts.map +1 -0
  382. package/dist/utils/output.js +26 -0
  383. package/dist/utils/output.js.map +1 -0
  384. package/dist/utils/paths.d.ts +7 -0
  385. package/dist/utils/paths.d.ts.map +1 -0
  386. package/dist/utils/paths.js +16 -0
  387. package/dist/utils/paths.js.map +1 -0
  388. package/dist/utils/project-config.d.ts +18 -0
  389. package/dist/utils/project-config.d.ts.map +1 -0
  390. package/dist/utils/project-config.js +46 -0
  391. package/dist/utils/project-config.js.map +1 -0
  392. package/dist/utils/redact.d.ts +5 -0
  393. package/dist/utils/redact.d.ts.map +1 -0
  394. package/dist/utils/redact.js +25 -0
  395. package/dist/utils/redact.js.map +1 -0
  396. package/dist/utils/schemas.d.ts +109 -0
  397. package/dist/utils/schemas.d.ts.map +1 -0
  398. package/dist/utils/schemas.js +63 -0
  399. package/dist/utils/schemas.js.map +1 -0
  400. package/dist/utils/terminal.d.ts +33 -0
  401. package/dist/utils/terminal.d.ts.map +1 -0
  402. package/dist/utils/terminal.js +82 -0
  403. package/dist/utils/terminal.js.map +1 -0
  404. package/dist/utils/tokens.d.ts +9 -0
  405. package/dist/utils/tokens.d.ts.map +1 -0
  406. package/dist/utils/tokens.js +11 -0
  407. package/dist/utils/tokens.js.map +1 -0
  408. package/package.json +71 -0
  409. package/skills/design-system/SKILL.md +195 -0
  410. package/skills/orchestration-patterns/SKILL.md +81 -0
  411. package/skills/orchestration-patterns/examples/example-workflows.md +290 -0
  412. package/skills/orchestration-patterns/references/adversarial.md +51 -0
  413. package/skills/orchestration-patterns/references/batch.md +63 -0
  414. package/skills/orchestration-patterns/references/chaos.md +43 -0
  415. package/skills/orchestration-patterns/references/competitive.md +84 -0
  416. package/skills/orchestration-patterns/references/debate.md +44 -0
  417. package/skills/orchestration-patterns/references/emergence.md +50 -0
  418. package/skills/orchestration-patterns/references/fan-out-fan-in.md +74 -0
  419. package/skills/orchestration-patterns/references/iterative.md +99 -0
  420. package/skills/orchestration-patterns/references/pipeline.md +72 -0
  421. package/skills/swarm-output-style/SKILL.md +85 -0
  422. package/templates/add-endpoint.yml +44 -0
  423. package/templates/add-feature.yml +30 -0
  424. package/templates/agent-template.md +73 -0
  425. package/templates/bug-fix.yml +31 -0
  426. package/templates/explore.yml +21 -0
  427. package/templates/fix-pr.yml +30 -0
  428. package/templates/migration.yml +36 -0
  429. package/templates/refactor.yml +35 -0
  430. package/templates/security-audit.yml +27 -0
  431. package/templates/workflow-template.md +63 -0
@@ -0,0 +1,154 @@
1
+ import { spawn } from 'child_process';
2
+ import { randomUUID } from 'crypto';
3
+ import { safeEnv } from '../utils/env.js';
4
+ export class MCPClient {
5
+ servers = new Map();
6
+ tools = new Map();
7
+ bus;
8
+ constructor(bus) { this.bus = bus ?? null; }
9
+ async connect(config) {
10
+ const conn = config.transport === 'stdio' ? new StdioConn(config) : new HttpConn(config);
11
+ await conn.initialize();
12
+ this.servers.set(config.name, conn);
13
+ const tools = await conn.listTools();
14
+ for (const t of tools)
15
+ this.tools.set(`${config.name}:${t.name}`, { ...t, serverName: config.name });
16
+ return tools.map((t) => ({ ...t, serverName: config.name }));
17
+ }
18
+ async callTool(server, tool, args) {
19
+ const conn = this.servers.get(server);
20
+ if (!conn)
21
+ throw new Error(`MCP not connected: ${server}`);
22
+ return conn.callTool(tool, args);
23
+ }
24
+ getAllTools() { return [...this.tools.values()]; }
25
+ async disconnectAll() {
26
+ for (const c of this.servers.values())
27
+ try {
28
+ await c.shutdown();
29
+ }
30
+ catch { }
31
+ this.servers.clear();
32
+ this.tools.clear();
33
+ }
34
+ }
35
+ class StdioConn {
36
+ config;
37
+ proc = null;
38
+ pending = new Map();
39
+ buf = '';
40
+ constructor(config) {
41
+ this.config = config;
42
+ }
43
+ async initialize() {
44
+ this.proc = spawn(this.config.command, this.config.args ?? [], {
45
+ cwd: this.config.cwd, env: safeEnv(this.config.env), stdio: ['pipe', 'pipe', 'pipe'],
46
+ });
47
+ this.proc.stdout.on('data', (c) => { this.buf += c.toString(); this.flush(); });
48
+ await this.req('initialize', { protocolVersion: '2024-11-05', capabilities: {}, clientInfo: { name: 'swarm-engine', version: '1.0.0' } });
49
+ this.proc?.stdin?.write(JSON.stringify({ jsonrpc: '2.0', method: 'notifications/initialized', params: {} }) + '\n');
50
+ }
51
+ async listTools() { return (await this.req('tools/list', {})).tools ?? []; }
52
+ async callTool(name, args) { return (await this.req('tools/call', { name, arguments: args })).content; }
53
+ async shutdown() {
54
+ // Clear all pending request timers to prevent leaks
55
+ for (const [, entry] of this.pending) {
56
+ clearTimeout(entry.timer);
57
+ entry.reject(new Error('Connection shutdown'));
58
+ }
59
+ this.pending.clear();
60
+ this.proc?.kill('SIGTERM');
61
+ }
62
+ req(method, params) {
63
+ return new Promise((resolve, reject) => {
64
+ const id = randomUUID();
65
+ const timer = setTimeout(() => { if (this.pending.has(id)) {
66
+ this.pending.delete(id);
67
+ reject(new Error(`Timeout: ${method}`));
68
+ } }, 30_000);
69
+ this.pending.set(id, { resolve, reject, timer });
70
+ this.proc?.stdin?.write(JSON.stringify({ jsonrpc: '2.0', id, method, params }) + '\n');
71
+ });
72
+ }
73
+ flush() {
74
+ const lines = this.buf.split('\n');
75
+ this.buf = lines.pop() ?? '';
76
+ for (const l of lines) {
77
+ if (!l.trim())
78
+ continue;
79
+ try {
80
+ const m = JSON.parse(l);
81
+ if (m.id && this.pending.has(String(m.id))) {
82
+ const { resolve, reject, timer } = this.pending.get(String(m.id));
83
+ this.pending.delete(String(m.id));
84
+ clearTimeout(timer);
85
+ m.error ? reject(new Error(m.error.message)) : resolve(m.result);
86
+ }
87
+ }
88
+ catch { }
89
+ }
90
+ }
91
+ }
92
+ class HttpConn {
93
+ config;
94
+ constructor(config) {
95
+ this.config = config;
96
+ }
97
+ async initialize() {
98
+ if (!this.config.url)
99
+ throw new Error('HTTP MCP requires url');
100
+ await this.req('initialize', { protocolVersion: '2024-11-05', capabilities: {}, clientInfo: { name: 'swarm-engine', version: '1.0.0' } });
101
+ }
102
+ async listTools() { return (await this.req('tools/list', {})).tools ?? []; }
103
+ async callTool(name, args) { return (await this.req('tools/call', { name, arguments: args })).content; }
104
+ async shutdown() { }
105
+ validateUrl(url) {
106
+ const parsed = new URL(url);
107
+ const host = parsed.hostname.replace(/^\[|\]$/g, ''); // Strip IPv6 brackets
108
+ // Block obvious patterns
109
+ const blocked = [
110
+ '169.254.169.254', // AWS metadata
111
+ '0.0.0.0',
112
+ 'localhost',
113
+ '127.0.0.1',
114
+ '::1', // IPv6 loopback
115
+ '::ffff:127.0.0.1', // IPv6-mapped loopback
116
+ ];
117
+ if (blocked.includes(host)) {
118
+ throw new Error(`SSRF blocked: ${host}`);
119
+ }
120
+ // Block private ranges (IPv4)
121
+ const ipv4Match = host.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/);
122
+ if (ipv4Match) {
123
+ const [, a, b] = ipv4Match.map(Number);
124
+ if (a === 10 || a === 127 || // 10.x, 127.x
125
+ (a === 172 && b >= 16 && b <= 31) || // 172.16-31.x
126
+ (a === 192 && b === 168) || // 192.168.x
127
+ (a === 169 && b === 254)) { // 169.254.x
128
+ throw new Error(`SSRF blocked: ${host} is a private address`);
129
+ }
130
+ }
131
+ // Block IPv6 private/loopback
132
+ if (host.startsWith('::') || host.startsWith('fe80') || host.startsWith('fc') || host.startsWith('fd')) {
133
+ throw new Error(`SSRF blocked: ${host} is a private IPv6 address`);
134
+ }
135
+ // Block decimal/octal/hex IP representations
136
+ if (/^\d{8,}$/.test(host) || /^0\d/.test(host) || /^0x/i.test(host)) {
137
+ throw new Error(`SSRF blocked: ${host} uses non-standard IP representation`);
138
+ }
139
+ }
140
+ async req(method, params) {
141
+ this.validateUrl(this.config.url);
142
+ const r = await fetch(this.config.url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ jsonrpc: '2.0', id: randomUUID(), method, params }), redirect: 'manual' });
143
+ if (r.status >= 300 && r.status < 400) {
144
+ throw new Error(`SSRF blocked: MCP server returned redirect to ${r.headers.get('location')}`);
145
+ }
146
+ if (!r.ok)
147
+ throw new Error(`HTTP ${r.status}`);
148
+ const m = await r.json();
149
+ if (m.error)
150
+ throw new Error(m.error.message);
151
+ return m.result;
152
+ }
153
+ }
154
+ //# sourceMappingURL=mcp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp.js","sourceRoot":"","sources":["../../src/runtime/mcp.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ export interface ModelScore {
2
+ model: string;
3
+ taskType: string;
4
+ successes: number;
5
+ attempts: number;
6
+ avgReward: number;
7
+ ucbScore: number;
8
+ }
9
+ export declare class ModelRouter {
10
+ private db;
11
+ constructor(dbPath?: string);
12
+ private initSchema;
13
+ /** Record an outcome for a model on a task type */
14
+ record(model: string, taskType: string, success: boolean, reward?: number): void;
15
+ /** Select the best model for a task type using UCB1 */
16
+ recommend(taskType: string, candidates: string[]): string;
17
+ /** Get scores for all models for a task type */
18
+ getScores(taskType: string): ModelScore[];
19
+ prune(maxRows?: number): void;
20
+ close(): void;
21
+ }
22
+ //# sourceMappingURL=model-router.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-router.d.ts","sourceRoot":"","sources":["../../src/runtime/model-router.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,EAAE,CAAoB;gBAElB,MAAM,CAAC,EAAE,MAAM;IAU3B,OAAO,CAAC,UAAU;IAclB,mDAAmD;IACnD,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI;IAMhF,uDAAuD;IACvD,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,MAAM;IA0CzD,gDAAgD;IAChD,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,EAAE;IAoBzC,KAAK,CAAC,OAAO,GAAE,MAAc,GAAG,IAAI;IAIpC,KAAK,IAAI,IAAI;CACd"}
@@ -0,0 +1,94 @@
1
+ import Database from 'better-sqlite3';
2
+ import { existsSync, mkdirSync } from 'fs';
3
+ import { join, dirname } from 'path';
4
+ import { homedir } from 'os';
5
+ export class ModelRouter {
6
+ db;
7
+ constructor(dbPath) {
8
+ const path = dbPath ?? join(homedir(), '.swarm', 'data', 'router.db');
9
+ const dir = dirname(path);
10
+ if (!existsSync(dir))
11
+ mkdirSync(dir, { recursive: true, mode: 0o700 });
12
+ this.db = new Database(path);
13
+ this.db.pragma('journal_mode = WAL');
14
+ this.db.pragma('busy_timeout = 5000');
15
+ this.initSchema();
16
+ }
17
+ initSchema() {
18
+ this.db.exec(`
19
+ CREATE TABLE IF NOT EXISTS model_outcomes (
20
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
21
+ model TEXT NOT NULL,
22
+ task_type TEXT NOT NULL,
23
+ success INTEGER NOT NULL,
24
+ reward REAL DEFAULT 0,
25
+ created_at TEXT DEFAULT (datetime('now'))
26
+ );
27
+ CREATE INDEX IF NOT EXISTS idx_model_task ON model_outcomes(model, task_type);
28
+ `);
29
+ }
30
+ /** Record an outcome for a model on a task type */
31
+ record(model, taskType, success, reward) {
32
+ this.db.prepare('INSERT INTO model_outcomes (model, task_type, success, reward) VALUES (?, ?, ?, ?)').run(model, taskType, success ? 1 : 0, reward ?? (success ? 1.0 : 0.0));
33
+ }
34
+ /** Select the best model for a task type using UCB1 */
35
+ recommend(taskType, candidates) {
36
+ if (candidates.length === 0)
37
+ return 'sonnet';
38
+ // Single query for all models instead of N+1 per-candidate queries
39
+ const rows = this.db.prepare(`
40
+ SELECT model, COUNT(*) as attempts, AVG(reward) as avg_reward
41
+ FROM model_outcomes WHERE task_type = ?
42
+ GROUP BY model
43
+ `).all(taskType);
44
+ const statsMap = new Map();
45
+ let N = 0;
46
+ for (const row of rows) {
47
+ const attempts = row.attempts;
48
+ statsMap.set(row.model, { attempts, avgReward: row.avg_reward ?? 0.5 });
49
+ N += attempts;
50
+ }
51
+ if (N === 0)
52
+ N = 1;
53
+ let bestModel = candidates[0];
54
+ let bestScore = -Infinity;
55
+ for (const model of candidates) {
56
+ const stats = statsMap.get(model);
57
+ const attempts = stats?.attempts ?? 0;
58
+ const avgReward = stats?.avgReward ?? 0.5;
59
+ // UCB1 formula: avg_reward + sqrt(2 * ln(N) / n_i)
60
+ // For unexplored models, return Infinity (explore first)
61
+ const ucb = attempts === 0
62
+ ? Infinity
63
+ : avgReward + Math.sqrt(2 * Math.log(N) / attempts);
64
+ if (ucb > bestScore) {
65
+ bestScore = ucb;
66
+ bestModel = model;
67
+ }
68
+ }
69
+ return bestModel;
70
+ }
71
+ /** Get scores for all models for a task type */
72
+ getScores(taskType) {
73
+ const rows = this.db.prepare(`
74
+ SELECT model, task_type, COUNT(*) as attempts, SUM(success) as successes, AVG(reward) as avg_reward
75
+ FROM model_outcomes
76
+ WHERE task_type = ?
77
+ GROUP BY model
78
+ `).all(taskType);
79
+ const N = rows.reduce((sum, r) => sum + r.attempts, 0) || 1;
80
+ return rows.map(r => ({
81
+ model: r.model,
82
+ taskType: r.task_type,
83
+ successes: r.successes,
84
+ attempts: r.attempts,
85
+ avgReward: r.avg_reward ?? 0,
86
+ ucbScore: r.attempts === 0 ? Infinity : (r.avg_reward ?? 0) + Math.sqrt(2 * Math.log(N) / r.attempts),
87
+ }));
88
+ }
89
+ prune(maxRows = 10000) {
90
+ this.db.prepare('DELETE FROM model_outcomes WHERE id NOT IN (SELECT id FROM model_outcomes ORDER BY created_at DESC LIMIT ?)').run(maxRows);
91
+ }
92
+ close() { this.db.close(); }
93
+ }
94
+ //# sourceMappingURL=model-router.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-router.js","sourceRoot":"","sources":["../../src/runtime/model-router.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,76 @@
1
+ export interface PaneInfo {
2
+ paneId: string;
3
+ agentId: string;
4
+ agentName: string;
5
+ windowId: string;
6
+ status: 'running' | 'done' | 'error';
7
+ outputFile: string;
8
+ }
9
+ /**
10
+ * Tmux pane manager for visible agent execution.
11
+ *
12
+ * Creates a tmux session with split panes so each agent
13
+ * runs in its own visible terminal pane. Panes are titled
14
+ * by agent name and auto-close after completion.
15
+ */
16
+ export declare class PaneManager {
17
+ private sessionName;
18
+ private panes;
19
+ private active;
20
+ constructor(sessionName?: string);
21
+ /** Check if tmux is available on this system. */
22
+ static isAvailable(): boolean;
23
+ /** Start the tmux session with an initial orchestrator pane. */
24
+ start(orchestrationName: string): void;
25
+ /**
26
+ * Create a new pane for an agent and run a command in it.
27
+ * Returns the tmux pane ID.
28
+ */
29
+ createPane(agentId: string, agentName: string, command: string, env?: Record<string, string>): {
30
+ paneId: string;
31
+ outputFile: string;
32
+ };
33
+ /** Mark a pane as done -- show status and close after delay. */
34
+ markDone(agentId: string, success: boolean): void;
35
+ /** Print attachment instructions for the user. */
36
+ attach(): void;
37
+ /** Get the session name for external attachment. */
38
+ getSessionName(): string;
39
+ /** Kill the entire tmux session. */
40
+ stop(): void;
41
+ /** List active panes. */
42
+ list(): PaneInfo[];
43
+ /** Check if session is active. */
44
+ isActive(): boolean;
45
+ /**
46
+ * Wait for a pane's command to exit by polling tmux pane status.
47
+ * Resolves when the pane's process has finished.
48
+ */
49
+ waitForPane(paneId: string): Promise<void>;
50
+ /**
51
+ * Capture the output of a pane using tmux capture-pane.
52
+ */
53
+ capturePane(paneId: string): string;
54
+ /**
55
+ * Read captured output from the temp file (reliable, not lossy like tmux capture-pane).
56
+ */
57
+ captureFromFile(agentId: string): string;
58
+ /**
59
+ * Clean up the output file for an agent.
60
+ */
61
+ cleanupFile(agentId: string): void;
62
+ private setTitle;
63
+ }
64
+ /**
65
+ * Shell-escape a string by replacing single quotes with '\'' pattern.
66
+ */
67
+ export declare function shellEscape(s: string): string;
68
+ /**
69
+ * Build a CLI command string for a backend.
70
+ *
71
+ * For Codex: cd <cwd> && codex exec --full-auto --json --ephemeral '<prompt>'
72
+ * For Gemini: cd <cwd> && gemini -p '<prompt>' --output-format json -y
73
+ * For Claude: falls back to invisible execution (returns null)
74
+ */
75
+ export declare function buildPaneCommand(backendName: string, prompt: string, cwd: string): string | null;
76
+ //# sourceMappingURL=panes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"panes.d.ts","sourceRoot":"","sources":["../../src/runtime/panes.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,SAAS,GAAG,MAAM,GAAG,OAAO,CAAC;IACrC,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;GAMG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,KAAK,CAAoC;IACjD,OAAO,CAAC,MAAM,CAAS;gBAEX,WAAW,CAAC,EAAE,MAAM;IAIhC,iDAAiD;IACjD,MAAM,CAAC,WAAW,IAAI,OAAO;IAO7B,gEAAgE;IAChE,KAAK,CAAC,iBAAiB,EAAE,MAAM,GAAG,IAAI;IAmCtC;;;OAGG;IACH,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE;IAoDrI,gEAAgE;IAChE,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI;IAwBjD,kDAAkD;IAClD,MAAM,IAAI,IAAI;IAKd,oDAAoD;IACpD,cAAc,IAAI,MAAM;IAIxB,oCAAoC;IACpC,IAAI,IAAI,IAAI;IASZ,yBAAyB;IACzB,IAAI,IAAI,QAAQ,EAAE;IAIlB,kCAAkC;IAClC,QAAQ,IAAI,OAAO;IAInB;;;OAGG;IACH,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAoC1C;;OAEG;IACH,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAUnC;;OAEG;IACH,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;IAWxC;;OAEG;IACH,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAOlC,OAAO,CAAC,QAAQ;CAOjB;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE7C;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,GACV,MAAM,GAAG,IAAI,CAef"}
@@ -0,0 +1,279 @@
1
+ import { execFileSync } from 'child_process';
2
+ import { randomUUID } from 'crypto';
3
+ import { readFileSync, unlinkSync } from 'fs';
4
+ import { tmpdir } from 'os';
5
+ import { join } from 'path';
6
+ /**
7
+ * Tmux pane manager for visible agent execution.
8
+ *
9
+ * Creates a tmux session with split panes so each agent
10
+ * runs in its own visible terminal pane. Panes are titled
11
+ * by agent name and auto-close after completion.
12
+ */
13
+ export class PaneManager {
14
+ sessionName;
15
+ panes = new Map();
16
+ active = false;
17
+ constructor(sessionName) {
18
+ this.sessionName = sessionName ?? `swarm-${randomUUID().slice(0, 8)}`;
19
+ }
20
+ /** Check if tmux is available on this system. */
21
+ static isAvailable() {
22
+ try {
23
+ execFileSync('tmux', ['-V'], { encoding: 'utf-8' });
24
+ return true;
25
+ }
26
+ catch {
27
+ return false;
28
+ }
29
+ }
30
+ /** Start the tmux session with an initial orchestrator pane. */
31
+ start(orchestrationName) {
32
+ // Create a new detached session
33
+ execFileSync('tmux', [
34
+ 'new-session', '-d',
35
+ '-s', this.sessionName,
36
+ '-n', 'swarm',
37
+ '-x', '200', '-y', '50',
38
+ ]);
39
+ // Enable pane border titles
40
+ try {
41
+ execFileSync('tmux', [
42
+ 'set', '-t', this.sessionName, 'pane-border-status', 'top',
43
+ ]);
44
+ execFileSync('tmux', [
45
+ 'set', '-t', this.sessionName, 'pane-border-format',
46
+ ' #[bold]#{pane_title}#[default] ',
47
+ ]);
48
+ // Keep pane visible after command exits so we can capture output
49
+ execFileSync('tmux', [
50
+ 'set', '-t', this.sessionName, 'remain-on-exit', 'on',
51
+ ]);
52
+ }
53
+ catch { /* older tmux versions may not support these options */ }
54
+ // Set initial pane title
55
+ try {
56
+ execFileSync('tmux', [
57
+ 'select-pane', '-t', `${this.sessionName}:swarm`,
58
+ '-T', `swarm: ${orchestrationName.slice(0, 50)}`,
59
+ ]);
60
+ }
61
+ catch { /* ignore */ }
62
+ this.active = true;
63
+ }
64
+ /**
65
+ * Create a new pane for an agent and run a command in it.
66
+ * Returns the tmux pane ID.
67
+ */
68
+ createPane(agentId, agentName, command, env) {
69
+ if (!this.active)
70
+ throw new Error('Session not started');
71
+ // Build env prefix — validate env key names to prevent injection
72
+ const ENV_KEY_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
73
+ const envStr = env
74
+ ? Object.entries(env)
75
+ .filter(([k]) => ENV_KEY_RE.test(k))
76
+ .map(([k, v]) => `${k}=${shellEscape(v)}`).join(' ') + ' '
77
+ : '';
78
+ // Create a temp file to tee output for reliable parsing (tmux capture-pane is lossy)
79
+ const outputFile = join(tmpdir(), `swarm-pane-${agentId.replace(/[^a-zA-Z0-9-]/g, '')}.out`);
80
+ // The original command runs and output is tee'd to a file for reliable parsing
81
+ const wrappedCommand = `${envStr}${command} 2>&1 | tee ${shellEscape(outputFile)}; echo ""; echo "--- DONE ---"`;
82
+ // Split window and run the command directly via shell -c
83
+ // This way the pane's process IS the command, and pane_dead=1 when it exits
84
+ const result = execFileSync('tmux', [
85
+ 'split-window', '-t', `${this.sessionName}:swarm`,
86
+ '-h', // horizontal split
87
+ '-P', '-F', '#{pane_id}', // print the new pane ID
88
+ 'sh', '-c', wrappedCommand,
89
+ ], { encoding: 'utf-8' }).trim();
90
+ const paneId = result;
91
+ // Rebalance the layout
92
+ try {
93
+ execFileSync('tmux', ['select-layout', '-t', `${this.sessionName}:swarm`, 'tiled']);
94
+ }
95
+ catch { /* layout may fail if only 1 pane */ }
96
+ // Set pane title
97
+ execFileSync('tmux', [
98
+ 'select-pane', '-t', paneId,
99
+ '-T', agentName,
100
+ ]);
101
+ const info = {
102
+ paneId,
103
+ agentId,
104
+ agentName,
105
+ windowId: 'swarm',
106
+ status: 'running',
107
+ outputFile,
108
+ };
109
+ this.panes.set(agentId, info);
110
+ return { paneId, outputFile };
111
+ }
112
+ /** Mark a pane as done -- show status and close after delay. */
113
+ markDone(agentId, success) {
114
+ const pane = this.panes.get(agentId);
115
+ if (!pane)
116
+ return;
117
+ pane.status = success ? 'done' : 'error';
118
+ const msg = success ? 'DONE' : 'FAILED';
119
+ try {
120
+ // Send a visible completion message
121
+ execFileSync('tmux', [
122
+ 'send-keys', '-t', pane.paneId,
123
+ `echo "--- ${msg} ---"`, 'Enter',
124
+ ]);
125
+ // Close the pane after a short delay (3 seconds)
126
+ setTimeout(() => {
127
+ try {
128
+ execFileSync('tmux', ['kill-pane', '-t', pane.paneId]);
129
+ }
130
+ catch { /* pane may already be gone */ }
131
+ this.panes.delete(agentId);
132
+ }, 3000);
133
+ }
134
+ catch { /* pane may already be gone */ }
135
+ }
136
+ /** Print attachment instructions for the user. */
137
+ attach() {
138
+ if (!this.active)
139
+ return;
140
+ console.log(`\nView agents: tmux attach -t ${this.sessionName}\n`);
141
+ }
142
+ /** Get the session name for external attachment. */
143
+ getSessionName() {
144
+ return this.sessionName;
145
+ }
146
+ /** Kill the entire tmux session. */
147
+ stop() {
148
+ if (!this.active)
149
+ return;
150
+ try {
151
+ execFileSync('tmux', ['kill-session', '-t', this.sessionName]);
152
+ }
153
+ catch { /* session may already be gone */ }
154
+ this.active = false;
155
+ this.panes.clear();
156
+ }
157
+ /** List active panes. */
158
+ list() {
159
+ return [...this.panes.values()];
160
+ }
161
+ /** Check if session is active. */
162
+ isActive() {
163
+ return this.active;
164
+ }
165
+ /**
166
+ * Wait for a pane's command to exit by polling tmux pane status.
167
+ * Resolves when the pane's process has finished.
168
+ */
169
+ waitForPane(paneId) {
170
+ return new Promise((resolve) => {
171
+ const check = setInterval(() => {
172
+ try {
173
+ const dead = execFileSync('tmux', [
174
+ 'list-panes', '-t', `${this.sessionName}:swarm`,
175
+ '-F', '#{pane_id} #{pane_dead}',
176
+ ], { encoding: 'utf-8' });
177
+ // Parse output lines looking for our pane
178
+ const lines = dead.trim().split('\n');
179
+ for (const line of lines) {
180
+ const [id, isDead] = line.split(' ');
181
+ if (id === paneId && isDead === '1') {
182
+ clearInterval(check);
183
+ resolve();
184
+ return;
185
+ }
186
+ }
187
+ // If pane is no longer listed at all, it's gone
188
+ const paneIds = lines.map(l => l.split(' ')[0]);
189
+ if (!paneIds.includes(paneId)) {
190
+ clearInterval(check);
191
+ resolve();
192
+ return;
193
+ }
194
+ }
195
+ catch {
196
+ // Session/pane gone
197
+ clearInterval(check);
198
+ resolve();
199
+ }
200
+ }, 2000); // poll every 2 seconds
201
+ });
202
+ }
203
+ /**
204
+ * Capture the output of a pane using tmux capture-pane.
205
+ */
206
+ capturePane(paneId) {
207
+ try {
208
+ return execFileSync('tmux', [
209
+ 'capture-pane', '-t', paneId, '-p',
210
+ ], { encoding: 'utf-8' });
211
+ }
212
+ catch {
213
+ return '';
214
+ }
215
+ }
216
+ /**
217
+ * Read captured output from the temp file (reliable, not lossy like tmux capture-pane).
218
+ */
219
+ captureFromFile(agentId) {
220
+ const pane = this.panes.get(agentId);
221
+ if (!pane?.outputFile)
222
+ return this.capturePane(pane?.paneId ?? '');
223
+ try {
224
+ return readFileSync(pane.outputFile, 'utf-8');
225
+ }
226
+ catch {
227
+ return '';
228
+ }
229
+ }
230
+ /**
231
+ * Clean up the output file for an agent.
232
+ */
233
+ cleanupFile(agentId) {
234
+ const pane = this.panes.get(agentId);
235
+ if (pane?.outputFile) {
236
+ try {
237
+ unlinkSync(pane.outputFile);
238
+ }
239
+ catch { /* file may already be gone */ }
240
+ }
241
+ }
242
+ setTitle(title) {
243
+ try {
244
+ execFileSync('tmux', [
245
+ 'rename-window', '-t', `${this.sessionName}:0`, title.slice(0, 40),
246
+ ]);
247
+ }
248
+ catch { /* ignore */ }
249
+ }
250
+ }
251
+ /**
252
+ * Shell-escape a string by replacing single quotes with '\'' pattern.
253
+ */
254
+ export function shellEscape(s) {
255
+ return "'" + s.replace(/'/g, "'\\''") + "'";
256
+ }
257
+ /**
258
+ * Build a CLI command string for a backend.
259
+ *
260
+ * For Codex: cd <cwd> && codex exec --full-auto --json --ephemeral '<prompt>'
261
+ * For Gemini: cd <cwd> && gemini -p '<prompt>' --output-format json -y
262
+ * For Claude: falls back to invisible execution (returns null)
263
+ */
264
+ export function buildPaneCommand(backendName, prompt, cwd) {
265
+ const escaped = shellEscape(prompt);
266
+ switch (backendName) {
267
+ case 'codex':
268
+ return `cd ${shellEscape(cwd)} && codex exec --full-auto --json --ephemeral ${escaped}`;
269
+ case 'gemini':
270
+ return `cd ${shellEscape(cwd)} && gemini -p ${escaped} --output-format json -y`;
271
+ case 'claude':
272
+ // Claude uses the Agent SDK, not a CLI command for pane mode.
273
+ // Return null to signal fallback to invisible execution.
274
+ return null;
275
+ default:
276
+ return null;
277
+ }
278
+ }
279
+ //# sourceMappingURL=panes.js.map