@intrect/openswarm 0.2.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 (437) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +544 -0
  3. package/config.example.yaml +107 -0
  4. package/dist/adapters/base.d.ts +8 -0
  5. package/dist/adapters/base.d.ts.map +1 -0
  6. package/dist/adapters/base.js +104 -0
  7. package/dist/adapters/base.js.map +1 -0
  8. package/dist/adapters/claude.d.ts +13 -0
  9. package/dist/adapters/claude.d.ts.map +1 -0
  10. package/dist/adapters/claude.js +318 -0
  11. package/dist/adapters/claude.js.map +1 -0
  12. package/dist/adapters/codex.d.ts +14 -0
  13. package/dist/adapters/codex.d.ts.map +1 -0
  14. package/dist/adapters/codex.js +366 -0
  15. package/dist/adapters/codex.js.map +1 -0
  16. package/dist/adapters/cryptoQuantAdapter.d.ts +85 -0
  17. package/dist/adapters/cryptoQuantAdapter.d.ts.map +1 -0
  18. package/dist/adapters/cryptoQuantAdapter.js +238 -0
  19. package/dist/adapters/cryptoQuantAdapter.js.map +1 -0
  20. package/dist/adapters/index.d.ts +17 -0
  21. package/dist/adapters/index.d.ts.map +1 -0
  22. package/dist/adapters/index.js +47 -0
  23. package/dist/adapters/index.js.map +1 -0
  24. package/dist/adapters/processRegistry.d.ts +38 -0
  25. package/dist/adapters/processRegistry.d.ts.map +1 -0
  26. package/dist/adapters/processRegistry.js +147 -0
  27. package/dist/adapters/processRegistry.js.map +1 -0
  28. package/dist/adapters/streamBuffer.d.ts +59 -0
  29. package/dist/adapters/streamBuffer.d.ts.map +1 -0
  30. package/dist/adapters/streamBuffer.js +123 -0
  31. package/dist/adapters/streamBuffer.js.map +1 -0
  32. package/dist/adapters/types.d.ts +65 -0
  33. package/dist/adapters/types.d.ts.map +1 -0
  34. package/dist/adapters/types.js +6 -0
  35. package/dist/adapters/types.js.map +1 -0
  36. package/dist/agents/agentBus.d.ts +160 -0
  37. package/dist/agents/agentBus.d.ts.map +1 -0
  38. package/dist/agents/agentBus.js +350 -0
  39. package/dist/agents/agentBus.js.map +1 -0
  40. package/dist/agents/agentPair.d.ts +210 -0
  41. package/dist/agents/agentPair.d.ts.map +1 -0
  42. package/dist/agents/agentPair.js +420 -0
  43. package/dist/agents/agentPair.js.map +1 -0
  44. package/dist/agents/auditor.d.ts +27 -0
  45. package/dist/agents/auditor.d.ts.map +1 -0
  46. package/dist/agents/auditor.js +237 -0
  47. package/dist/agents/auditor.js.map +1 -0
  48. package/dist/agents/cliStreamParser.d.ts +18 -0
  49. package/dist/agents/cliStreamParser.d.ts.map +1 -0
  50. package/dist/agents/cliStreamParser.js +156 -0
  51. package/dist/agents/cliStreamParser.js.map +1 -0
  52. package/dist/agents/documenter.d.ts +31 -0
  53. package/dist/agents/documenter.d.ts.map +1 -0
  54. package/dist/agents/documenter.js +285 -0
  55. package/dist/agents/documenter.js.map +1 -0
  56. package/dist/agents/index.d.ts +10 -0
  57. package/dist/agents/index.d.ts.map +1 -0
  58. package/dist/agents/index.js +10 -0
  59. package/dist/agents/index.js.map +1 -0
  60. package/dist/agents/pairMetrics.d.ts +63 -0
  61. package/dist/agents/pairMetrics.d.ts.map +1 -0
  62. package/dist/agents/pairMetrics.js +231 -0
  63. package/dist/agents/pairMetrics.js.map +1 -0
  64. package/dist/agents/pairPipeline.d.ts +155 -0
  65. package/dist/agents/pairPipeline.d.ts.map +1 -0
  66. package/dist/agents/pairPipeline.js +793 -0
  67. package/dist/agents/pairPipeline.js.map +1 -0
  68. package/dist/agents/pairWebhook.d.ts +59 -0
  69. package/dist/agents/pairWebhook.d.ts.map +1 -0
  70. package/dist/agents/pairWebhook.js +242 -0
  71. package/dist/agents/pairWebhook.js.map +1 -0
  72. package/dist/agents/pipelineFormat.d.ts +11 -0
  73. package/dist/agents/pipelineFormat.d.ts.map +1 -0
  74. package/dist/agents/pipelineFormat.js +164 -0
  75. package/dist/agents/pipelineFormat.js.map +1 -0
  76. package/dist/agents/pipelineGuards.d.ts +23 -0
  77. package/dist/agents/pipelineGuards.d.ts.map +1 -0
  78. package/dist/agents/pipelineGuards.js +175 -0
  79. package/dist/agents/pipelineGuards.js.map +1 -0
  80. package/dist/agents/reviewer.d.ts +37 -0
  81. package/dist/agents/reviewer.d.ts.map +1 -0
  82. package/dist/agents/reviewer.js +213 -0
  83. package/dist/agents/reviewer.js.map +1 -0
  84. package/dist/agents/skillDocumenter.d.ts +23 -0
  85. package/dist/agents/skillDocumenter.d.ts.map +1 -0
  86. package/dist/agents/skillDocumenter.js +218 -0
  87. package/dist/agents/skillDocumenter.js.map +1 -0
  88. package/dist/agents/tester.d.ts +37 -0
  89. package/dist/agents/tester.d.ts.map +1 -0
  90. package/dist/agents/tester.js +308 -0
  91. package/dist/agents/tester.js.map +1 -0
  92. package/dist/agents/worker.d.ts +30 -0
  93. package/dist/agents/worker.d.ts.map +1 -0
  94. package/dist/agents/worker.js +128 -0
  95. package/dist/agents/worker.js.map +1 -0
  96. package/dist/automation/autonomousRunner.d.ts +123 -0
  97. package/dist/automation/autonomousRunner.d.ts.map +1 -0
  98. package/dist/automation/autonomousRunner.js +1082 -0
  99. package/dist/automation/autonomousRunner.js.map +1 -0
  100. package/dist/automation/ciWorker.d.ts +51 -0
  101. package/dist/automation/ciWorker.d.ts.map +1 -0
  102. package/dist/automation/ciWorker.js +282 -0
  103. package/dist/automation/ciWorker.js.map +1 -0
  104. package/dist/automation/conflictResolver.d.ts +29 -0
  105. package/dist/automation/conflictResolver.d.ts.map +1 -0
  106. package/dist/automation/conflictResolver.js +261 -0
  107. package/dist/automation/conflictResolver.js.map +1 -0
  108. package/dist/automation/dailyReporter.d.ts +26 -0
  109. package/dist/automation/dailyReporter.d.ts.map +1 -0
  110. package/dist/automation/dailyReporter.js +132 -0
  111. package/dist/automation/dailyReporter.js.map +1 -0
  112. package/dist/automation/index.d.ts +7 -0
  113. package/dist/automation/index.d.ts.map +1 -0
  114. package/dist/automation/index.js +7 -0
  115. package/dist/automation/index.js.map +1 -0
  116. package/dist/automation/longRunningMonitor.d.ts +26 -0
  117. package/dist/automation/longRunningMonitor.d.ts.map +1 -0
  118. package/dist/automation/longRunningMonitor.js +231 -0
  119. package/dist/automation/longRunningMonitor.js.map +1 -0
  120. package/dist/automation/prOwnership.d.ts +18 -0
  121. package/dist/automation/prOwnership.d.ts.map +1 -0
  122. package/dist/automation/prOwnership.js +61 -0
  123. package/dist/automation/prOwnership.js.map +1 -0
  124. package/dist/automation/prProcessor.d.ts +62 -0
  125. package/dist/automation/prProcessor.d.ts.map +1 -0
  126. package/dist/automation/prProcessor.js +700 -0
  127. package/dist/automation/prProcessor.js.map +1 -0
  128. package/dist/automation/runnerExecution.d.ts +49 -0
  129. package/dist/automation/runnerExecution.d.ts.map +1 -0
  130. package/dist/automation/runnerExecution.js +663 -0
  131. package/dist/automation/runnerExecution.js.map +1 -0
  132. package/dist/automation/runnerState.d.ts +170 -0
  133. package/dist/automation/runnerState.d.ts.map +1 -0
  134. package/dist/automation/runnerState.js +495 -0
  135. package/dist/automation/runnerState.js.map +1 -0
  136. package/dist/automation/runnerTypes.d.ts +46 -0
  137. package/dist/automation/runnerTypes.d.ts.map +1 -0
  138. package/dist/automation/runnerTypes.js +5 -0
  139. package/dist/automation/runnerTypes.js.map +1 -0
  140. package/dist/automation/scheduler.d.ts +75 -0
  141. package/dist/automation/scheduler.d.ts.map +1 -0
  142. package/dist/automation/scheduler.js +394 -0
  143. package/dist/automation/scheduler.js.map +1 -0
  144. package/dist/cli/promptHandler.d.ts +13 -0
  145. package/dist/cli/promptHandler.d.ts.map +1 -0
  146. package/dist/cli/promptHandler.js +189 -0
  147. package/dist/cli/promptHandler.js.map +1 -0
  148. package/dist/cli.d.ts +3 -0
  149. package/dist/cli.d.ts.map +1 -0
  150. package/dist/cli.js +138 -0
  151. package/dist/cli.js.map +1 -0
  152. package/dist/core/config.d.ts +308 -0
  153. package/dist/core/config.d.ts.map +1 -0
  154. package/dist/core/config.js +529 -0
  155. package/dist/core/config.js.map +1 -0
  156. package/dist/core/eventHub.d.ts +194 -0
  157. package/dist/core/eventHub.d.ts.map +1 -0
  158. package/dist/core/eventHub.js +136 -0
  159. package/dist/core/eventHub.js.map +1 -0
  160. package/dist/core/index.d.ts +6 -0
  161. package/dist/core/index.d.ts.map +1 -0
  162. package/dist/core/index.js +6 -0
  163. package/dist/core/index.js.map +1 -0
  164. package/dist/core/service.d.ts +27 -0
  165. package/dist/core/service.d.ts.map +1 -0
  166. package/dist/core/service.js +438 -0
  167. package/dist/core/service.js.map +1 -0
  168. package/dist/core/traceCollector.d.ts +105 -0
  169. package/dist/core/traceCollector.d.ts.map +1 -0
  170. package/dist/core/traceCollector.js +141 -0
  171. package/dist/core/traceCollector.js.map +1 -0
  172. package/dist/core/types.d.ts +413 -0
  173. package/dist/core/types.d.ts.map +1 -0
  174. package/dist/core/types.js +5 -0
  175. package/dist/core/types.js.map +1 -0
  176. package/dist/discord/discordCore.d.ts +104 -0
  177. package/dist/discord/discordCore.d.ts.map +1 -0
  178. package/dist/discord/discordCore.js +698 -0
  179. package/dist/discord/discordCore.js.map +1 -0
  180. package/dist/discord/discordHandlers.d.ts +86 -0
  181. package/dist/discord/discordHandlers.d.ts.map +1 -0
  182. package/dist/discord/discordHandlers.js +849 -0
  183. package/dist/discord/discordHandlers.js.map +1 -0
  184. package/dist/discord/discordPair.d.ts +6 -0
  185. package/dist/discord/discordPair.d.ts.map +1 -0
  186. package/dist/discord/discordPair.js +567 -0
  187. package/dist/discord/discordPair.js.map +1 -0
  188. package/dist/discord/index.d.ts +4 -0
  189. package/dist/discord/index.d.ts.map +1 -0
  190. package/dist/discord/index.js +11 -0
  191. package/dist/discord/index.js.map +1 -0
  192. package/dist/github/github.d.ts +236 -0
  193. package/dist/github/github.d.ts.map +1 -0
  194. package/dist/github/github.js +535 -0
  195. package/dist/github/github.js.map +1 -0
  196. package/dist/github/index.d.ts +2 -0
  197. package/dist/github/index.d.ts.map +1 -0
  198. package/dist/github/index.js +2 -0
  199. package/dist/github/index.js.map +1 -0
  200. package/dist/index.d.ts +3 -0
  201. package/dist/index.d.ts.map +1 -0
  202. package/dist/index.js +60 -0
  203. package/dist/index.js.map +1 -0
  204. package/dist/knowledge/analyzer.d.ts +36 -0
  205. package/dist/knowledge/analyzer.d.ts.map +1 -0
  206. package/dist/knowledge/analyzer.js +170 -0
  207. package/dist/knowledge/analyzer.js.map +1 -0
  208. package/dist/knowledge/gitInfo.d.ts +10 -0
  209. package/dist/knowledge/gitInfo.d.ts.map +1 -0
  210. package/dist/knowledge/gitInfo.js +134 -0
  211. package/dist/knowledge/gitInfo.js.map +1 -0
  212. package/dist/knowledge/graph.d.ts +45 -0
  213. package/dist/knowledge/graph.d.ts.map +1 -0
  214. package/dist/knowledge/graph.js +262 -0
  215. package/dist/knowledge/graph.js.map +1 -0
  216. package/dist/knowledge/graphqlExporter.d.ts +64 -0
  217. package/dist/knowledge/graphqlExporter.d.ts.map +1 -0
  218. package/dist/knowledge/graphqlExporter.js +333 -0
  219. package/dist/knowledge/graphqlExporter.js.map +1 -0
  220. package/dist/knowledge/index.d.ts +58 -0
  221. package/dist/knowledge/index.d.ts.map +1 -0
  222. package/dist/knowledge/index.js +212 -0
  223. package/dist/knowledge/index.js.map +1 -0
  224. package/dist/knowledge/repository.d.ts +64 -0
  225. package/dist/knowledge/repository.d.ts.map +1 -0
  226. package/dist/knowledge/repository.js +250 -0
  227. package/dist/knowledge/repository.js.map +1 -0
  228. package/dist/knowledge/riskOnAnalyzer.d.ts +79 -0
  229. package/dist/knowledge/riskOnAnalyzer.d.ts.map +1 -0
  230. package/dist/knowledge/riskOnAnalyzer.js +243 -0
  231. package/dist/knowledge/riskOnAnalyzer.js.map +1 -0
  232. package/dist/knowledge/scanner.d.ts +14 -0
  233. package/dist/knowledge/scanner.d.ts.map +1 -0
  234. package/dist/knowledge/scanner.js +350 -0
  235. package/dist/knowledge/scanner.js.map +1 -0
  236. package/dist/knowledge/store.d.ts +23 -0
  237. package/dist/knowledge/store.d.ts.map +1 -0
  238. package/dist/knowledge/store.js +86 -0
  239. package/dist/knowledge/store.js.map +1 -0
  240. package/dist/knowledge/types.d.ts +288 -0
  241. package/dist/knowledge/types.d.ts.map +1 -0
  242. package/dist/knowledge/types.js +111 -0
  243. package/dist/knowledge/types.js.map +1 -0
  244. package/dist/linear/index.d.ts +3 -0
  245. package/dist/linear/index.d.ts.map +1 -0
  246. package/dist/linear/index.js +3 -0
  247. package/dist/linear/index.js.map +1 -0
  248. package/dist/linear/linear.d.ts +160 -0
  249. package/dist/linear/linear.d.ts.map +1 -0
  250. package/dist/linear/linear.js +983 -0
  251. package/dist/linear/linear.js.map +1 -0
  252. package/dist/linear/projectUpdater.d.ts +23 -0
  253. package/dist/linear/projectUpdater.d.ts.map +1 -0
  254. package/dist/linear/projectUpdater.js +347 -0
  255. package/dist/linear/projectUpdater.js.map +1 -0
  256. package/dist/locale/en.d.ts +3 -0
  257. package/dist/locale/en.d.ts.map +1 -0
  258. package/dist/locale/en.js +436 -0
  259. package/dist/locale/en.js.map +1 -0
  260. package/dist/locale/index.d.ts +28 -0
  261. package/dist/locale/index.d.ts.map +1 -0
  262. package/dist/locale/index.js +89 -0
  263. package/dist/locale/index.js.map +1 -0
  264. package/dist/locale/ko.d.ts +3 -0
  265. package/dist/locale/ko.d.ts.map +1 -0
  266. package/dist/locale/ko.js +436 -0
  267. package/dist/locale/ko.js.map +1 -0
  268. package/dist/locale/prompts/en.d.ts +3 -0
  269. package/dist/locale/prompts/en.d.ts.map +1 -0
  270. package/dist/locale/prompts/en.js +278 -0
  271. package/dist/locale/prompts/en.js.map +1 -0
  272. package/dist/locale/prompts/ko.d.ts +3 -0
  273. package/dist/locale/prompts/ko.d.ts.map +1 -0
  274. package/dist/locale/prompts/ko.js +279 -0
  275. package/dist/locale/prompts/ko.js.map +1 -0
  276. package/dist/locale/types.d.ts +407 -0
  277. package/dist/locale/types.d.ts.map +1 -0
  278. package/dist/locale/types.js +5 -0
  279. package/dist/locale/types.js.map +1 -0
  280. package/dist/memory/codex.d.ts +93 -0
  281. package/dist/memory/codex.d.ts.map +1 -0
  282. package/dist/memory/codex.js +366 -0
  283. package/dist/memory/codex.js.map +1 -0
  284. package/dist/memory/compaction.d.ts +21 -0
  285. package/dist/memory/compaction.d.ts.map +1 -0
  286. package/dist/memory/compaction.js +205 -0
  287. package/dist/memory/compaction.js.map +1 -0
  288. package/dist/memory/index.d.ts +13 -0
  289. package/dist/memory/index.d.ts.map +1 -0
  290. package/dist/memory/index.js +13 -0
  291. package/dist/memory/index.js.map +1 -0
  292. package/dist/memory/memoryCore.d.ts +178 -0
  293. package/dist/memory/memoryCore.d.ts.map +1 -0
  294. package/dist/memory/memoryCore.js +623 -0
  295. package/dist/memory/memoryCore.js.map +1 -0
  296. package/dist/memory/memoryOps.d.ts +90 -0
  297. package/dist/memory/memoryOps.d.ts.map +1 -0
  298. package/dist/memory/memoryOps.js +606 -0
  299. package/dist/memory/memoryOps.js.map +1 -0
  300. package/dist/orchestration/conflictDetector.d.ts +15 -0
  301. package/dist/orchestration/conflictDetector.d.ts.map +1 -0
  302. package/dist/orchestration/conflictDetector.js +130 -0
  303. package/dist/orchestration/conflictDetector.js.map +1 -0
  304. package/dist/orchestration/decisionEngine.d.ts +177 -0
  305. package/dist/orchestration/decisionEngine.d.ts.map +1 -0
  306. package/dist/orchestration/decisionEngine.js +496 -0
  307. package/dist/orchestration/decisionEngine.js.map +1 -0
  308. package/dist/orchestration/index.d.ts +5 -0
  309. package/dist/orchestration/index.d.ts.map +1 -0
  310. package/dist/orchestration/index.js +5 -0
  311. package/dist/orchestration/index.js.map +1 -0
  312. package/dist/orchestration/taskParser.d.ts +67 -0
  313. package/dist/orchestration/taskParser.d.ts.map +1 -0
  314. package/dist/orchestration/taskParser.js +542 -0
  315. package/dist/orchestration/taskParser.js.map +1 -0
  316. package/dist/orchestration/taskScheduler.d.ts +141 -0
  317. package/dist/orchestration/taskScheduler.d.ts.map +1 -0
  318. package/dist/orchestration/taskScheduler.js +317 -0
  319. package/dist/orchestration/taskScheduler.js.map +1 -0
  320. package/dist/orchestration/workflow.d.ts +145 -0
  321. package/dist/orchestration/workflow.d.ts.map +1 -0
  322. package/dist/orchestration/workflow.js +301 -0
  323. package/dist/orchestration/workflow.js.map +1 -0
  324. package/dist/runners/cliRunner.d.ts +11 -0
  325. package/dist/runners/cliRunner.d.ts.map +1 -0
  326. package/dist/runners/cliRunner.js +194 -0
  327. package/dist/runners/cliRunner.js.map +1 -0
  328. package/dist/support/apiCache.d.ts +85 -0
  329. package/dist/support/apiCache.d.ts.map +1 -0
  330. package/dist/support/apiCache.js +163 -0
  331. package/dist/support/apiCache.js.map +1 -0
  332. package/dist/support/chat.d.ts +3 -0
  333. package/dist/support/chat.d.ts.map +1 -0
  334. package/dist/support/chat.js +304 -0
  335. package/dist/support/chat.js.map +1 -0
  336. package/dist/support/chatBackend.d.ts +25 -0
  337. package/dist/support/chatBackend.d.ts.map +1 -0
  338. package/dist/support/chatBackend.js +235 -0
  339. package/dist/support/chatBackend.js.map +1 -0
  340. package/dist/support/chatMemory.d.ts +71 -0
  341. package/dist/support/chatMemory.d.ts.map +1 -0
  342. package/dist/support/chatMemory.js +119 -0
  343. package/dist/support/chatMemory.js.map +1 -0
  344. package/dist/support/chatTui.d.ts +3 -0
  345. package/dist/support/chatTui.d.ts.map +1 -0
  346. package/dist/support/chatTui.js +998 -0
  347. package/dist/support/chatTui.js.map +1 -0
  348. package/dist/support/costTracker.d.ts +29 -0
  349. package/dist/support/costTracker.d.ts.map +1 -0
  350. package/dist/support/costTracker.js +113 -0
  351. package/dist/support/costTracker.js.map +1 -0
  352. package/dist/support/dashboardHtml.d.ts +3 -0
  353. package/dist/support/dashboardHtml.d.ts.map +1 -0
  354. package/dist/support/dashboardHtml.js +2070 -0
  355. package/dist/support/dashboardHtml.js.map +1 -0
  356. package/dist/support/delete-beliefs.d.ts +2 -0
  357. package/dist/support/delete-beliefs.d.ts.map +1 -0
  358. package/dist/support/delete-beliefs.js +34 -0
  359. package/dist/support/delete-beliefs.js.map +1 -0
  360. package/dist/support/dev.d.ts +55 -0
  361. package/dist/support/dev.d.ts.map +1 -0
  362. package/dist/support/dev.js +298 -0
  363. package/dist/support/dev.js.map +1 -0
  364. package/dist/support/editParser.d.ts +37 -0
  365. package/dist/support/editParser.d.ts.map +1 -0
  366. package/dist/support/editParser.js +365 -0
  367. package/dist/support/editParser.js.map +1 -0
  368. package/dist/support/gitStatus.d.ts +21 -0
  369. package/dist/support/gitStatus.d.ts.map +1 -0
  370. package/dist/support/gitStatus.js +108 -0
  371. package/dist/support/gitStatus.js.map +1 -0
  372. package/dist/support/gitTracker.d.ts +30 -0
  373. package/dist/support/gitTracker.d.ts.map +1 -0
  374. package/dist/support/gitTracker.js +143 -0
  375. package/dist/support/gitTracker.js.map +1 -0
  376. package/dist/support/index.d.ts +13 -0
  377. package/dist/support/index.d.ts.map +1 -0
  378. package/dist/support/index.js +13 -0
  379. package/dist/support/index.js.map +1 -0
  380. package/dist/support/planner.d.ts +58 -0
  381. package/dist/support/planner.d.ts.map +1 -0
  382. package/dist/support/planner.js +395 -0
  383. package/dist/support/planner.js.map +1 -0
  384. package/dist/support/projectMapper.d.ts +46 -0
  385. package/dist/support/projectMapper.d.ts.map +1 -0
  386. package/dist/support/projectMapper.js +259 -0
  387. package/dist/support/projectMapper.js.map +1 -0
  388. package/dist/support/quotaTracker.d.ts +29 -0
  389. package/dist/support/quotaTracker.d.ts.map +1 -0
  390. package/dist/support/quotaTracker.js +89 -0
  391. package/dist/support/quotaTracker.js.map +1 -0
  392. package/dist/support/rateLimiter.d.ts +101 -0
  393. package/dist/support/rateLimiter.d.ts.map +1 -0
  394. package/dist/support/rateLimiter.js +219 -0
  395. package/dist/support/rateLimiter.js.map +1 -0
  396. package/dist/support/rollback.d.ts +61 -0
  397. package/dist/support/rollback.d.ts.map +1 -0
  398. package/dist/support/rollback.js +328 -0
  399. package/dist/support/rollback.js.map +1 -0
  400. package/dist/support/stuckDetector.d.ts +68 -0
  401. package/dist/support/stuckDetector.d.ts.map +1 -0
  402. package/dist/support/stuckDetector.js +174 -0
  403. package/dist/support/stuckDetector.js.map +1 -0
  404. package/dist/support/timeWindow.d.ts +60 -0
  405. package/dist/support/timeWindow.d.ts.map +1 -0
  406. package/dist/support/timeWindow.js +236 -0
  407. package/dist/support/timeWindow.js.map +1 -0
  408. package/dist/support/web.d.ts +11 -0
  409. package/dist/support/web.d.ts.map +1 -0
  410. package/dist/support/web.js +938 -0
  411. package/dist/support/web.js.map +1 -0
  412. package/dist/support/workflowLinear.d.ts +99 -0
  413. package/dist/support/workflowLinear.d.ts.map +1 -0
  414. package/dist/support/workflowLinear.js +257 -0
  415. package/dist/support/workflowLinear.js.map +1 -0
  416. package/dist/support/worktreeManager.d.ts +20 -0
  417. package/dist/support/worktreeManager.d.ts.map +1 -0
  418. package/dist/support/worktreeManager.js +144 -0
  419. package/dist/support/worktreeManager.js.map +1 -0
  420. package/dist/taskState/store.d.ts +101 -0
  421. package/dist/taskState/store.d.ts.map +1 -0
  422. package/dist/taskState/store.js +346 -0
  423. package/dist/taskState/store.js.map +1 -0
  424. package/package.json +70 -0
  425. package/templates/AGENTS.md +432 -0
  426. package/templates/BOOT.md +25 -0
  427. package/templates/BOOTSTRAP.md +50 -0
  428. package/templates/CHANGELOG_AUDIT.md +74 -0
  429. package/templates/HEARTBEAT.md +86 -0
  430. package/templates/IDENTITY.md +27 -0
  431. package/templates/ISSUE_ANALYSIS.md +31 -0
  432. package/templates/PR_LAND.md +75 -0
  433. package/templates/PR_REVIEW.md +97 -0
  434. package/templates/SOUL.dev.md +52 -0
  435. package/templates/SOUL.md +81 -0
  436. package/templates/TOOLS.md +52 -0
  437. package/templates/USER.md +22 -0
@@ -0,0 +1,983 @@
1
+ // ============================================
2
+ // OpenSwarm - Linear Integration
3
+ // ============================================
4
+ import { LinearClient } from '@linear/sdk';
5
+ import { getDateLocale } from '../locale/index.js';
6
+ import { setLinearClient } from './projectUpdater.js';
7
+ import { withRateLimit } from '../support/rateLimiter.js';
8
+ /**
9
+ * Extract project info from an issue
10
+ */
11
+ async function getProjectInfo(issue) {
12
+ try {
13
+ const project = await issue.project;
14
+ if (!project)
15
+ return undefined;
16
+ return {
17
+ id: project.id,
18
+ name: project.name,
19
+ icon: project.icon ?? undefined,
20
+ color: project.color ?? undefined,
21
+ };
22
+ }
23
+ catch {
24
+ return undefined;
25
+ }
26
+ }
27
+ let client = null;
28
+ let teamId = '';
29
+ let teamIds = [];
30
+ /** Build a Linear team filter that works for both single and multiple team IDs */
31
+ function teamFilter() {
32
+ if (teamIds.length === 1) {
33
+ return { id: { eq: teamIds[0] } };
34
+ }
35
+ return { id: { in: teamIds } };
36
+ }
37
+ // Daily issue creation limit
38
+ const DAILY_ISSUE_LIMIT = 10;
39
+ let dailyIssueCount = 0;
40
+ let lastResetDate = '';
41
+ const inProgressCache = new Map();
42
+ const backlogCache = new Map();
43
+ const myIssuesCache = new Map();
44
+ const CACHE_TTL_MS = 300000; // 5 minute cache (was 1min, reduced API calls)
45
+ function isCacheValid(cache) {
46
+ if (!cache)
47
+ return false;
48
+ return Date.now() - cache.timestamp < CACHE_TTL_MS;
49
+ }
50
+ /**
51
+ * Clear all caches (call when issues are mutated)
52
+ */
53
+ export function clearLinearCache() {
54
+ inProgressCache.clear();
55
+ backlogCache.clear();
56
+ myIssuesCache.clear();
57
+ console.log('[Linear] Cache cleared');
58
+ }
59
+ /**
60
+ * Reset daily counter on date change
61
+ */
62
+ function resetDailyCounterIfNeeded() {
63
+ const today = new Date().toISOString().slice(0, 10); // YYYY-MM-DD
64
+ if (today !== lastResetDate) {
65
+ dailyIssueCount = 0;
66
+ lastResetDate = today;
67
+ }
68
+ }
69
+ /**
70
+ * Remaining issue creation quota for today
71
+ */
72
+ export function getRemainingDailyIssues() {
73
+ resetDailyCounterIfNeeded();
74
+ return Math.max(0, DAILY_ISSUE_LIMIT - dailyIssueCount);
75
+ }
76
+ /**
77
+ * Number of issues created today
78
+ */
79
+ export function getDailyIssueCount() {
80
+ resetDailyCounterIfNeeded();
81
+ return dailyIssueCount;
82
+ }
83
+ /**
84
+ * Initialize the Linear client
85
+ * Rate limiting is applied at the function level in this file
86
+ */
87
+ export function initLinear(apiKey, team) {
88
+ client = new LinearClient({ apiKey });
89
+ teamId = team;
90
+ teamIds = team.split(',').map(id => id.trim()).filter(Boolean);
91
+ setLinearClient(client);
92
+ console.log('[Linear] Client initialized');
93
+ }
94
+ /**
95
+ * Return the Linear client instance
96
+ */
97
+ export function getClient() {
98
+ if (!client) {
99
+ throw new Error('Linear client not initialized. Call initLinear() first.');
100
+ }
101
+ return client;
102
+ }
103
+ /**
104
+ * Get in-progress issues for an agent (with caching)
105
+ */
106
+ export async function getInProgressIssues(agentLabel) {
107
+ // Check cache first
108
+ const cached = inProgressCache.get(agentLabel);
109
+ if (cached && isCacheValid(cached)) {
110
+ console.log(`[Linear] Using cached in-progress issues for ${agentLabel}`);
111
+ return cached.data;
112
+ }
113
+ console.log(`[Linear] Fetching in-progress issues for ${agentLabel}`);
114
+ const linear = getClient();
115
+ const issues = await withRateLimit('linear', async () => linear.issues({
116
+ filter: {
117
+ team: teamFilter(),
118
+ state: { name: { in: ['In Progress', 'Started'] } },
119
+ labels: { name: { eq: agentLabel } },
120
+ },
121
+ }));
122
+ const result = [];
123
+ // Batch fetch all related data to minimize API calls
124
+ for (const issue of issues.nodes) {
125
+ // Use Promise.all to parallelize, but still results in N queries per issue
126
+ // Linear SDK doesn't support includes/eager loading, so this is unavoidable
127
+ const [comments, labels, state, project] = await Promise.all([
128
+ issue.comments(),
129
+ issue.labels(),
130
+ issue.state,
131
+ getProjectInfo(issue),
132
+ ]);
133
+ result.push({
134
+ id: issue.id,
135
+ identifier: issue.identifier,
136
+ title: issue.title,
137
+ description: issue.description ?? undefined,
138
+ state: state?.name ?? 'Unknown',
139
+ priority: issue.priority,
140
+ labels: labels.nodes.map((l) => l.name),
141
+ comments: comments.nodes.map((c) => ({
142
+ id: c.id,
143
+ body: c.body,
144
+ createdAt: c.createdAt.toISOString(),
145
+ user: undefined, // TODO: resolve user name
146
+ })),
147
+ project,
148
+ });
149
+ }
150
+ // Cache the result
151
+ inProgressCache.set(agentLabel, {
152
+ data: result,
153
+ timestamp: Date.now(),
154
+ agentLabel,
155
+ });
156
+ return result;
157
+ }
158
+ /**
159
+ * Get the next issue from the backlog (with caching)
160
+ */
161
+ export async function getNextBacklogIssue(agentLabel) {
162
+ // Check cache first
163
+ const cached = backlogCache.get(agentLabel);
164
+ if (cached && isCacheValid(cached) && cached.data.length > 0) {
165
+ console.log(`[Linear] Using cached backlog issue for ${agentLabel}`);
166
+ return cached.data[0];
167
+ }
168
+ console.log(`[Linear] Fetching backlog issues for ${agentLabel}`);
169
+ const linear = getClient();
170
+ const issues = await withRateLimit('linear', async () => linear.issues({
171
+ filter: {
172
+ team: teamFilter(),
173
+ state: { name: { in: ['Backlog', 'Todo'] } },
174
+ labels: { name: { eq: agentLabel } },
175
+ },
176
+ first: 10, // Fetch multiple and sort by priority
177
+ }));
178
+ // Sort by priority (lower = higher priority: 1=Urgent, 4=Low, 0=None)
179
+ const sorted = [...issues.nodes].sort((a, b) => {
180
+ // Push priority 0 (None) to the end
181
+ const pa = a.priority === 0 ? 999 : a.priority;
182
+ const pb = b.priority === 0 ? 999 : b.priority;
183
+ return pa - pb;
184
+ });
185
+ const issue = sorted[0];
186
+ if (!issue)
187
+ return null;
188
+ const [comments, labels, state, project] = await Promise.all([
189
+ issue.comments(),
190
+ issue.labels(),
191
+ issue.state,
192
+ getProjectInfo(issue),
193
+ ]);
194
+ const result = {
195
+ id: issue.id,
196
+ identifier: issue.identifier,
197
+ title: issue.title,
198
+ description: issue.description ?? undefined,
199
+ state: state?.name ?? 'Unknown',
200
+ priority: issue.priority,
201
+ labels: labels.nodes.map((l) => l.name),
202
+ comments: comments.nodes.map((c) => ({
203
+ id: c.id,
204
+ body: c.body,
205
+ createdAt: c.createdAt.toISOString(),
206
+ user: undefined,
207
+ })),
208
+ project,
209
+ };
210
+ // Cache the result
211
+ backlogCache.set(agentLabel, {
212
+ data: [result],
213
+ timestamp: Date.now(),
214
+ agentLabel,
215
+ });
216
+ return result;
217
+ }
218
+ /**
219
+ * Get assigned active issues (with caching)
220
+ * (Todo, In Progress, Review states - excludes Backlog)
221
+ */
222
+ export async function getMyIssues(agentLabelOrOptions) {
223
+ const opts = typeof agentLabelOrOptions === 'string'
224
+ ? { agentLabel: agentLabelOrOptions }
225
+ : agentLabelOrOptions ?? {};
226
+ const { agentLabel, slim = false, timeoutMs = 30000 } = opts;
227
+ // Generate cache key
228
+ const cacheKey = `${agentLabel || 'all'}:${slim}`;
229
+ // Check cache first
230
+ const cached = myIssuesCache.get(cacheKey);
231
+ if (cached && isCacheValid(cached)) {
232
+ console.log(`[Linear] Using cached issues for ${cacheKey}`);
233
+ return cached.data;
234
+ }
235
+ console.log(`[Linear] Fetching issues for ${cacheKey}`);
236
+ const linear = getClient();
237
+ const baseFilter = {
238
+ team: teamFilter(),
239
+ };
240
+ // Add label filter if agentLabel is provided
241
+ if (agentLabel) {
242
+ baseFilter.labels = { name: { eq: agentLabel } };
243
+ }
244
+ // Wrap with timeout
245
+ const fetchIssues = async () => {
246
+ // Slim mode: query each state separately to avoid lazy resolver calls for issue.state
247
+ // Full mode: combined query then resolve per-issue
248
+ const result = [];
249
+ if (slim) {
250
+ // Separate queries per state → tag each issue without resolver calls
251
+ // Build a project ID→info cache to avoid per-issue project resolver calls
252
+ const todoFilter = { ...baseFilter, state: { name: { in: ['Todo'] } } };
253
+ const inProgressFilter = { ...baseFilter, state: { name: { in: ['In Progress', 'In Review'] } } };
254
+ const backlogFilter = { ...baseFilter, state: { name: { in: ['Backlog'] } } };
255
+ const [todoIssues, inProgressIssues, backlogIssues] = await Promise.all([
256
+ withRateLimit('linear', async () => linear.issues({ filter: todoFilter, first: 50 })),
257
+ withRateLimit('linear', async () => linear.issues({ filter: inProgressFilter, first: 50 })),
258
+ withRateLimit('linear', async () => linear.issues({ filter: backlogFilter, first: 50 })),
259
+ ]);
260
+ const withState = [
261
+ ...todoIssues.nodes.map(i => ({ issue: i, state: 'Todo' })),
262
+ ...inProgressIssues.nodes.map(i => ({ issue: i, state: 'In Progress' })),
263
+ ...backlogIssues.nodes.map(i => ({ issue: i, state: 'Backlog' })),
264
+ ];
265
+ // Resolve all project info in parallel (one API call per issue, but batched)
266
+ // issue.project returns id+name together, cache by project id to avoid duplicates
267
+ const projectCache = new Map();
268
+ const projectResolutions = await Promise.all(withState.map(({ issue }) => withRateLimit('linear', () => Promise.resolve(issue.project)).catch(() => null)));
269
+ for (const p of projectResolutions) {
270
+ if (p && !projectCache.has(p.id)) {
271
+ projectCache.set(p.id, { id: p.id, name: p.name, icon: p.icon ?? undefined, color: p.color ?? undefined });
272
+ }
273
+ }
274
+ for (let i = 0; i < withState.length; i++) {
275
+ const { issue, state } = withState[i];
276
+ const p = projectResolutions[i];
277
+ const project = p ? projectCache.get(p.id) : undefined;
278
+ result.push({
279
+ id: issue.id,
280
+ identifier: issue.identifier,
281
+ title: issue.title,
282
+ description: issue.description ?? undefined,
283
+ state,
284
+ priority: issue.priority,
285
+ labels: [],
286
+ comments: [],
287
+ project,
288
+ });
289
+ }
290
+ return result;
291
+ }
292
+ // Full mode: fetch executable + backlog, then resolve per-issue
293
+ const executableFilter = { ...baseFilter, state: { name: { in: ['Todo', 'In Progress', 'In Review'] } } };
294
+ const backlogFilter = { ...baseFilter, state: { name: { in: ['Backlog'] } } };
295
+ const [executableIssues, backlogIssues] = await Promise.all([
296
+ withRateLimit('linear', async () => linear.issues({ filter: executableFilter, first: 50 })),
297
+ withRateLimit('linear', async () => linear.issues({ filter: backlogFilter, first: 50 })),
298
+ ]);
299
+ {
300
+ // Full mode: load all details (comments, labels, project)
301
+ const allNodes = [...executableIssues.nodes, ...backlogIssues.nodes];
302
+ for (const issue of allNodes) {
303
+ const [comments, labels, project] = await Promise.all([
304
+ issue.comments(),
305
+ issue.labels(),
306
+ getProjectInfo(issue),
307
+ ]);
308
+ result.push({
309
+ id: issue.id,
310
+ identifier: issue.identifier,
311
+ title: issue.title,
312
+ description: issue.description ?? undefined,
313
+ state: (await issue.state)?.name ?? 'Unknown',
314
+ priority: issue.priority,
315
+ labels: labels.nodes.map((l) => l.name),
316
+ comments: comments.nodes.map((c) => ({
317
+ id: c.id,
318
+ body: c.body,
319
+ createdAt: c.createdAt.toISOString(),
320
+ user: undefined,
321
+ })),
322
+ project,
323
+ });
324
+ }
325
+ }
326
+ // Sort by priority
327
+ return result.sort((a, b) => {
328
+ const pa = a.priority === 0 ? 999 : a.priority;
329
+ const pb = b.priority === 0 ? 999 : b.priority;
330
+ return pa - pb;
331
+ });
332
+ };
333
+ // Apply timeout
334
+ const result = await Promise.race([
335
+ fetchIssues(),
336
+ new Promise((_, reject) => setTimeout(() => reject(new Error(`getMyIssues timed out after ${timeoutMs}ms`)), timeoutMs)),
337
+ ]);
338
+ // Cache the result
339
+ myIssuesCache.set(cacheKey, {
340
+ data: result,
341
+ timestamp: Date.now(),
342
+ agentLabel: agentLabel || 'all',
343
+ });
344
+ return result;
345
+ }
346
+ /**
347
+ * Get a specific issue by ID or identifier
348
+ */
349
+ export async function getIssue(issueIdOrIdentifier) {
350
+ const linear = getClient();
351
+ try {
352
+ // Check if it's an identifier format (e.g., LIN-123)
353
+ const isIdentifier = /^[A-Z]+-\d+$/.test(issueIdOrIdentifier);
354
+ let issue;
355
+ if (isIdentifier) {
356
+ // Search by identifier - use number field
357
+ const numPart = issueIdOrIdentifier.split('-')[1];
358
+ const issueNumber = parseInt(numPart, 10);
359
+ const issues = await linear.issues({
360
+ filter: {
361
+ team: teamFilter(),
362
+ number: { eq: issueNumber },
363
+ },
364
+ first: 1,
365
+ });
366
+ issue = issues.nodes[0];
367
+ }
368
+ else {
369
+ // Look up directly by ID
370
+ issue = await linear.issue(issueIdOrIdentifier);
371
+ }
372
+ if (!issue)
373
+ return null;
374
+ const [comments, labels, project] = await Promise.all([
375
+ issue.comments(),
376
+ issue.labels(),
377
+ getProjectInfo(issue),
378
+ ]);
379
+ return {
380
+ id: issue.id,
381
+ identifier: issue.identifier,
382
+ title: issue.title,
383
+ description: issue.description ?? undefined,
384
+ state: (await issue.state)?.name ?? 'Unknown',
385
+ priority: issue.priority,
386
+ labels: labels.nodes.map((l) => l.name),
387
+ comments: comments.nodes.map((c) => ({
388
+ id: c.id,
389
+ body: c.body,
390
+ createdAt: c.createdAt.toISOString(),
391
+ user: undefined,
392
+ })),
393
+ project,
394
+ };
395
+ }
396
+ catch (error) {
397
+ console.error(`[Linear] getIssue error for ${issueIdOrIdentifier}:`, error);
398
+ return null;
399
+ }
400
+ }
401
+ /**
402
+ * Update issue state
403
+ */
404
+ export async function updateIssueState(issueId, stateName, retries = 2) {
405
+ const linear = getClient();
406
+ for (let attempt = 0; attempt <= retries; attempt++) {
407
+ try {
408
+ // Fetch the issue to get its actual team ID (avoids cross-team state mismatch)
409
+ const issue = await linear.issue(issueId);
410
+ const issueTeam = await issue.team;
411
+ const resolvedTeamId = issueTeam?.id ?? teamIds[0] ?? teamId;
412
+ // Get team workflow states
413
+ const team = await linear.team(resolvedTeamId);
414
+ const states = await team.states();
415
+ const targetState = states.nodes.find((s) => s.name.toLowerCase().includes(stateName.toLowerCase()));
416
+ if (!targetState) {
417
+ console.error(`[Linear] State "${stateName}" not found in team workflow`);
418
+ return;
419
+ }
420
+ await linear.updateIssue(issueId, {
421
+ stateId: targetState.id,
422
+ });
423
+ // Clear cache after mutation
424
+ clearLinearCache();
425
+ console.log(`[Linear] Issue ${issueId} state changed to ${stateName}`);
426
+ return;
427
+ }
428
+ catch (error) {
429
+ console.error(`[Linear] Failed to update issue state (attempt ${attempt + 1}/${retries + 1}):`, error);
430
+ if (attempt < retries) {
431
+ await new Promise(r => setTimeout(r, 1000 * (attempt + 1)));
432
+ }
433
+ }
434
+ }
435
+ console.error(`[Linear] All ${retries + 1} attempts to update issue ${issueId} to "${stateName}" failed`);
436
+ }
437
+ /**
438
+ * Add a comment to an issue
439
+ */
440
+ export async function addComment(issueId, body) {
441
+ const linear = getClient();
442
+ await linear.createComment({
443
+ issueId,
444
+ body,
445
+ });
446
+ }
447
+ /** Log a HALT event (low confidence) as a comment on a Linear issue */
448
+ export async function logHalt(issueId, sessionId, confidence, iteration, reason) {
449
+ await addComment(issueId, `⚠️ **[Automation] HALT - Low Confidence**\n\nSession: \`${sessionId}\` | Confidence: ${confidence}% | Attempt: #${iteration}\nReason: ${reason}\n\n**Action Required:** Review task requirements / provide context / break into sub-tasks\n\n---\n_Auto-generated_`);
450
+ }
451
+ /** Log work start comment for an agent */
452
+ export async function logWorkStart(issueId, sessionName) {
453
+ await addComment(issueId, `🤖 **[${sessionName}] Work Started**\n\nTime: ${new Date().toISOString()}\n\n---\n_Auto-generated_`);
454
+ await updateIssueState(issueId, 'In Progress');
455
+ }
456
+ /**
457
+ * Log progress comment for an agent
458
+ */
459
+ export async function logProgress(issueId, sessionName, progress) {
460
+ const timestamp = new Date().toISOString();
461
+ const body = `🤖 **[${sessionName}] Progress Update**
462
+
463
+ ${progress}
464
+
465
+ Time: ${timestamp}`;
466
+ await addComment(issueId, body);
467
+ }
468
+ /**
469
+ * Log work completion comment for an agent
470
+ */
471
+ export async function logWorkComplete(issueId, sessionName, summary) {
472
+ const timestamp = new Date().toISOString();
473
+ const body = `🤖 **[${sessionName}] ✅ Work Complete**
474
+
475
+ ${summary ?? ''}
476
+
477
+ Time: ${timestamp}`;
478
+ await addComment(issueId, body);
479
+ await updateIssueState(issueId, 'Done');
480
+ }
481
+ /**
482
+ * Log blocked comment for an agent
483
+ */
484
+ export async function logBlocked(issueId, sessionName, reason) {
485
+ const timestamp = new Date().toISOString();
486
+ const body = `🤖 **[${sessionName}] ⚠️ Blocked**
487
+
488
+ Reason: ${reason}
489
+
490
+ User intervention required
491
+
492
+ Time: ${timestamp}`;
493
+ await addComment(issueId, body);
494
+ // Use 'Todo' instead of 'Blocked' (Blocked state may not exist in team workflow)
495
+ await updateIssueState(issueId, 'Todo');
496
+ }
497
+ // Pair Mode Linear Integration
498
+ /**
499
+ * Log pair session start comment
500
+ */
501
+ export async function logPairStart(issueId, sessionId, projectPath) {
502
+ const timestamp = new Date().toLocaleString(getDateLocale());
503
+ const body = `👥 **[Pair Session] Work Started**
504
+
505
+ 🆔 Session: \`${sessionId}\`
506
+ 📁 Project: \`${projectPath}\`
507
+ ⏰ Time: ${timestamp}
508
+
509
+ Starting work in Worker/Reviewer pair mode.
510
+
511
+ ---
512
+ _Auto-generated_`;
513
+ await addComment(issueId, body);
514
+ await updateIssueState(issueId, 'In Progress');
515
+ }
516
+ /**
517
+ * Log pair session review start comment
518
+ */
519
+ export async function logPairReview(issueId, sessionId, attempt) {
520
+ const timestamp = new Date().toLocaleString(getDateLocale());
521
+ const body = `🔍 **[Pair Session] Reviewing**
522
+
523
+ 🆔 Session: \`${sessionId}\`
524
+ 🔢 Attempt: #${attempt}
525
+ ⏰ Time: ${timestamp}
526
+
527
+ Reviewer is reviewing Worker's output.`;
528
+ await addComment(issueId, body);
529
+ await updateIssueState(issueId, 'In Review');
530
+ }
531
+ /**
532
+ * Log pair session revision request comment
533
+ */
534
+ export async function logPairRevision(issueId, sessionId, feedback, issues) {
535
+ const timestamp = new Date().toLocaleString(getDateLocale());
536
+ const issueList = issues.length > 0
537
+ ? issues.map((i, idx) => `${idx + 1}. ${i}`).join('\n')
538
+ : '(none)';
539
+ const body = `🔄 **[Pair Session] Revision Requested**
540
+
541
+ 🆔 Session: \`${sessionId}\`
542
+ ⏰ Time: ${timestamp}
543
+
544
+ **Feedback:** ${feedback}
545
+
546
+ **Issues:**
547
+ ${issueList}
548
+
549
+ Worker will proceed with revisions.`;
550
+ await addComment(issueId, body);
551
+ await updateIssueState(issueId, 'In Progress');
552
+ }
553
+ /**
554
+ * Log pair session completion comment
555
+ */
556
+ export async function logPairComplete(issueId, sessionId, stats) {
557
+ const timestamp = new Date().toLocaleString(getDateLocale());
558
+ const durationStr = stats.duration < 60
559
+ ? `${stats.duration}s`
560
+ : `${Math.floor(stats.duration / 60)}m ${stats.duration % 60}s`;
561
+ const filesStr = stats.filesChanged.length > 0
562
+ ? stats.filesChanged.slice(0, 10).map(f => `- \`${f}\``).join('\n')
563
+ : '(none)';
564
+ // Build sections
565
+ const sections = [];
566
+ // Worker section
567
+ if (stats.workerSummary) {
568
+ sections.push(`## 🔨 Worker Report
569
+
570
+ **What was done:**
571
+ ${stats.workerSummary}`);
572
+ if (stats.workerCommands && stats.workerCommands.length > 0) {
573
+ const cmdStr = stats.workerCommands.slice(0, 5).map(c => `- \`${c}\``).join('\n');
574
+ sections.push(`**Commands executed:**
575
+ ${cmdStr}`);
576
+ }
577
+ }
578
+ // Reviewer section
579
+ if (stats.reviewerFeedback) {
580
+ sections.push(`## ✅ Reviewer Report
581
+
582
+ **Decision:** ${stats.reviewerDecision || 'APPROVE'}
583
+
584
+ **Feedback:**
585
+ ${stats.reviewerFeedback}`);
586
+ }
587
+ // Tester section
588
+ if (stats.testResults) {
589
+ const { passed, failed, coverage, failedTests } = stats.testResults;
590
+ const totalTests = passed + failed;
591
+ const passRate = totalTests > 0 ? ((passed / totalTests) * 100).toFixed(1) : '0';
592
+ let testSection = `## 🧪 Test Results
593
+
594
+ - ✅ Passed: ${passed}/${totalTests} (${passRate}%)`;
595
+ if (coverage !== undefined) {
596
+ testSection += `\n- 📊 Coverage: ${coverage.toFixed(1)}%`;
597
+ }
598
+ if (failed > 0 && failedTests && failedTests.length > 0) {
599
+ const failedStr = failedTests.slice(0, 3).map(t => `- ❌ ${t}`).join('\n');
600
+ testSection += `\n\n**Failed tests:**\n${failedStr}`;
601
+ if (failedTests.length > 3) {
602
+ testSection += `\n- ... and ${failedTests.length - 3} more`;
603
+ }
604
+ }
605
+ sections.push(testSection);
606
+ }
607
+ // Remaining work section
608
+ if (stats.remainingWork) {
609
+ sections.push(`## 📋 Remaining Work
610
+
611
+ ${stats.remainingWork}`);
612
+ }
613
+ const body = `✅ **[Automation] Task Complete**
614
+
615
+ 🆔 Session: \`${sessionId}\`
616
+ ⏰ Completed: ${timestamp}
617
+
618
+ **📊 Summary:**
619
+ - 🔄 Iterations: ${stats.attempts}
620
+ - ⏱️ Duration: ${durationStr}
621
+ - 📁 Files changed: ${stats.filesChanged.length}
622
+
623
+ **Changed files:**
624
+ ${filesStr}
625
+
626
+ ---
627
+
628
+ ${sections.join('\n\n---\n\n')}
629
+
630
+ ---
631
+ _Automated by Worker/Reviewer/Tester pipeline_`;
632
+ await addComment(issueId, body);
633
+ await updateIssueState(issueId, 'Done');
634
+ }
635
+ /**
636
+ * Log pair session failure/rejection comment
637
+ */
638
+ export async function logPairFailed(issueId, sessionId, reason, details) {
639
+ const timestamp = new Date().toLocaleString(getDateLocale());
640
+ const reasonText = {
641
+ rejected: '❌ Reviewer rejected the work',
642
+ max_attempts: '⚠️ Maximum retry attempts exceeded',
643
+ error: '💥 An error occurred',
644
+ }[reason];
645
+ const body = `❌ **[Pair Session] Work Failed**
646
+
647
+ 🆔 Session: \`${sessionId}\`
648
+ ⏰ Time: ${timestamp}
649
+
650
+ **Reason:** ${reasonText}
651
+
652
+ **Details:**
653
+ ${details}
654
+
655
+ ---
656
+ _Manual intervention required_`;
657
+ await addComment(issueId, body);
658
+ // Don't change state on failure; let the user decide
659
+ }
660
+ /**
661
+ * Create a new issue (with daily limit enforcement)
662
+ */
663
+ export async function createIssue(title, description, labels = [], options) {
664
+ resetDailyCounterIfNeeded();
665
+ // Check daily limit (unless bypassLimit is set)
666
+ if (!options?.bypassLimit && dailyIssueCount >= DAILY_ISSUE_LIMIT) {
667
+ return {
668
+ error: `Daily issue creation limit (${DAILY_ISSUE_LIMIT}) reached. Please try again tomorrow.`,
669
+ };
670
+ }
671
+ const linear = getClient();
672
+ // Look up label IDs
673
+ const team = await linear.team(teamIds[0] ?? teamId);
674
+ const teamLabels = await team.labels();
675
+ const labelIds = labels
676
+ .map((name) => teamLabels.nodes.find((l) => l.name === name)?.id)
677
+ .filter((id) => !!id);
678
+ const issuePayload = await linear.createIssue({
679
+ teamId,
680
+ title,
681
+ description,
682
+ labelIds,
683
+ });
684
+ const issue = await issuePayload.issue;
685
+ if (!issue) {
686
+ throw new Error('Failed to create issue');
687
+ }
688
+ // Increment counter
689
+ dailyIssueCount++;
690
+ // Clear cache after mutation
691
+ clearLinearCache();
692
+ return {
693
+ id: issue.id,
694
+ identifier: issue.identifier,
695
+ title: issue.title,
696
+ description: issue.description ?? undefined,
697
+ state: 'Backlog',
698
+ priority: issue.priority,
699
+ labels,
700
+ comments: [],
701
+ };
702
+ }
703
+ /**
704
+ * Create a sub-issue (for Planner decomposition)
705
+ * - Creates as a child of the parent issue via parentId
706
+ * - Exempt from daily limit (auto-decomposition is required work)
707
+ */
708
+ export async function createSubIssue(parentId, title, description, options) {
709
+ const linear = getClient();
710
+ try {
711
+ // Get parent issue info
712
+ const parentIssue = await linear.issue(parentId);
713
+ if (!parentIssue) {
714
+ return { error: `Parent issue not found: ${parentId}` };
715
+ }
716
+ // Look up label IDs
717
+ const team = await linear.team(teamIds[0] ?? teamId);
718
+ const teamLabels = await team.labels();
719
+ const labelIds = (options?.labels || [])
720
+ .map((name) => teamLabels.nodes.find((l) => l.name === name)?.id)
721
+ .filter((id) => !!id);
722
+ // Add auto-decomposed label
723
+ const autoLabel = teamLabels.nodes.find((l) => l.name === 'auto-decomposed');
724
+ if (autoLabel) {
725
+ labelIds.push(autoLabel.id);
726
+ }
727
+ // Create the sub-issue (use parent issue's team ID, not global)
728
+ const parentTeam = await parentIssue.team;
729
+ const subIssueTeamId = parentTeam?.id ?? (teamIds[0] ?? teamId);
730
+ const issuePayload = await linear.createIssue({
731
+ teamId: subIssueTeamId,
732
+ parentId, // Link to parent issue
733
+ title,
734
+ description,
735
+ labelIds,
736
+ priority: options?.priority ?? 3,
737
+ projectId: options?.projectId,
738
+ });
739
+ const issue = await issuePayload.issue;
740
+ if (!issue) {
741
+ throw new Error('Failed to create sub-issue');
742
+ }
743
+ console.log(`[Linear] Created sub-issue: ${issue.identifier} under ${parentIssue.identifier}`);
744
+ return {
745
+ id: issue.id,
746
+ identifier: issue.identifier,
747
+ title: issue.title,
748
+ description: issue.description ?? undefined,
749
+ state: 'Backlog',
750
+ priority: issue.priority,
751
+ labels: options?.labels || [],
752
+ comments: [],
753
+ };
754
+ }
755
+ catch (error) {
756
+ console.error('[Linear] createSubIssue error:', error);
757
+ return { error: error instanceof Error ? error.message : String(error) };
758
+ }
759
+ }
760
+ /**
761
+ * Mark a parent issue as 'decomposed'
762
+ */
763
+ export async function markAsDecomposed(issueId, subIssueCount, totalMinutes) {
764
+ const timestamp = new Date().toLocaleString(getDateLocale());
765
+ const body = `📋 **[Planner] Task Decomposition Complete**
766
+
767
+ ⏰ Time: ${timestamp}
768
+
769
+ **Decomposition result:**
770
+ - Sub-issues created: ${subIssueCount}
771
+ - Total estimated time: ${totalMinutes}min
772
+
773
+ This issue has been decomposed into sub-issues.
774
+ The parent issue remains active while child issues execute.
775
+ Once all sub-issues are completed, OpenSwarm will close this issue automatically.
776
+
777
+ ---
778
+ _Auto-decomposed by Planner agent_`;
779
+ await addComment(issueId, body);
780
+ // Keep parent issue active until all child issues complete.
781
+ try {
782
+ await updateIssueState(issueId, 'In Progress');
783
+ }
784
+ catch (err) {
785
+ console.warn('[Linear] Failed to mark decomposed parent as In Progress:', err);
786
+ }
787
+ // Add label (if decomposed label exists)
788
+ try {
789
+ const linear = getClient();
790
+ const team = await linear.team(teamIds[0] ?? teamId);
791
+ const teamLabels = await team.labels();
792
+ const decomposedLabel = teamLabels.nodes.find((l) => l.name === 'decomposed');
793
+ if (decomposedLabel) {
794
+ const issue = await linear.issue(issueId);
795
+ const currentLabels = await issue.labels();
796
+ const currentLabelIds = currentLabels.nodes.map(l => l.id);
797
+ await linear.updateIssue(issueId, {
798
+ labelIds: [...currentLabelIds, decomposedLabel.id],
799
+ });
800
+ }
801
+ }
802
+ catch (err) {
803
+ console.warn('[Linear] Failed to add decomposed label:', err);
804
+ }
805
+ }
806
+ /**
807
+ * Agent proposes work by creating a backlog issue
808
+ * - Enforces daily limit of 10
809
+ * - Automatically adds 'agent-proposal' label
810
+ * - Created with low priority (4)
811
+ */
812
+ export async function proposeWork(sessionName, title, rationale, suggestedApproach) {
813
+ resetDailyCounterIfNeeded();
814
+ // Check daily limit
815
+ if (dailyIssueCount >= DAILY_ISSUE_LIMIT) {
816
+ console.log(`[${sessionName}] Daily issue creation limit reached (${dailyIssueCount}/${DAILY_ISSUE_LIMIT})`);
817
+ return {
818
+ error: `Daily issue creation limit (${DAILY_ISSUE_LIMIT}) reached. Please defer the proposal to tomorrow.`,
819
+ };
820
+ }
821
+ const linear = getClient();
822
+ // Look up Backlog state ID
823
+ const team = await linear.team(teamIds[0] ?? teamId);
824
+ const states = await team.states();
825
+ const backlogState = states.nodes.find((s) => s.name.toLowerCase() === 'backlog');
826
+ // Look up label IDs (agent-proposal + sessionName)
827
+ const teamLabels = await team.labels();
828
+ const proposalLabel = teamLabels.nodes.find((l) => l.name === 'agent-proposal');
829
+ const sessionLabel = teamLabels.nodes.find((l) => l.name === sessionName);
830
+ const labelIds = [];
831
+ if (proposalLabel)
832
+ labelIds.push(proposalLabel.id);
833
+ if (sessionLabel)
834
+ labelIds.push(sessionLabel.id);
835
+ // Compose description
836
+ const description = `## 🤖 Agent Proposal
837
+
838
+ **Proposed by:** ${sessionName}
839
+ **Created at:** ${new Date().toISOString()}
840
+
841
+ ---
842
+
843
+ ### Rationale
844
+ ${rationale}
845
+
846
+ ${suggestedApproach ? `### Suggested Approach\n${suggestedApproach}` : ''}
847
+
848
+ ---
849
+ _This issue was auto-created by an agent. Please review and adjust priority or delete as needed._`;
850
+ const issuePayload = await linear.createIssue({
851
+ teamId,
852
+ title: `[Proposal] ${title}`,
853
+ description,
854
+ labelIds,
855
+ stateId: backlogState?.id,
856
+ priority: 4, // Low priority
857
+ });
858
+ const issue = await issuePayload.issue;
859
+ if (!issue) {
860
+ throw new Error('Failed to create proposal issue');
861
+ }
862
+ // Increment counter
863
+ dailyIssueCount++;
864
+ console.log(`[${sessionName}] Proposal created: ${issue.identifier} (today ${dailyIssueCount}/${DAILY_ISSUE_LIMIT})`);
865
+ return {
866
+ id: issue.id,
867
+ identifier: issue.identifier,
868
+ title: issue.title,
869
+ description: issue.description ?? undefined,
870
+ state: 'Backlog',
871
+ priority: 4,
872
+ labels: ['agent-proposal', sessionName].filter(Boolean),
873
+ comments: [],
874
+ };
875
+ }
876
+ /**
877
+ * Get stuck/failed issues and PRs (issues stuck in In Progress for >7 days, or with retry/failed labels)
878
+ */
879
+ export async function getStuckIssues() {
880
+ const linear = getClient();
881
+ const now = Date.now();
882
+ const STUCK_THRESHOLD_MS = 7 * 24 * 60 * 60 * 1000; // 7 days
883
+ // Fetch In Progress issues
884
+ const inProgressIssues = await withRateLimit('linear', async () => linear.issues({
885
+ filter: {
886
+ team: teamFilter(),
887
+ state: { name: { eq: 'In Progress' } },
888
+ },
889
+ first: 100,
890
+ }));
891
+ // Fetch issues with retry/failed/blocked labels
892
+ const problematicIssues = await withRateLimit('linear', async () => linear.issues({
893
+ filter: {
894
+ team: teamFilter(),
895
+ state: { name: { nin: ['Done', 'Canceled'] } },
896
+ labels: { name: { in: ['retry', 'failed', 'blocked', 'needs-help'] } },
897
+ },
898
+ first: 100,
899
+ }));
900
+ const stuckIssues = [];
901
+ const failedIssues = [];
902
+ // Process In Progress issues (check if stuck)
903
+ for (const issue of inProgressIssues.nodes) {
904
+ const updatedAt = new Date(issue.updatedAt).getTime();
905
+ const stuckMs = now - updatedAt;
906
+ if (stuckMs > STUCK_THRESHOLD_MS) {
907
+ const [state, labels, comments, project] = await Promise.all([
908
+ issue.state,
909
+ issue.labels(),
910
+ issue.comments(),
911
+ getProjectInfo(issue),
912
+ ]);
913
+ const stuckDays = Math.floor(stuckMs / (24 * 60 * 60 * 1000));
914
+ stuckIssues.push({
915
+ id: issue.id,
916
+ identifier: issue.identifier,
917
+ title: issue.title,
918
+ description: issue.description ?? undefined,
919
+ state: state?.name ?? 'Unknown',
920
+ priority: issue.priority,
921
+ labels: labels.nodes.map((l) => l.name),
922
+ comments: comments.nodes.map((c) => ({
923
+ id: c.id,
924
+ body: c.body,
925
+ createdAt: c.createdAt.toISOString(),
926
+ user: undefined,
927
+ })),
928
+ project,
929
+ stuckDays,
930
+ reason: `No updates for ${stuckDays} days`,
931
+ });
932
+ }
933
+ }
934
+ // Process problematic issues (retry, failed, blocked)
935
+ for (const issue of problematicIssues.nodes) {
936
+ const [state, labels, comments, project] = await Promise.all([
937
+ issue.state,
938
+ issue.labels(),
939
+ issue.comments(),
940
+ getProjectInfo(issue),
941
+ ]);
942
+ const labelNames = labels.nodes.map((l) => l.name);
943
+ let reason = 'Unknown issue';
944
+ if (labelNames.includes('failed')) {
945
+ reason = 'Marked as failed';
946
+ }
947
+ else if (labelNames.includes('retry')) {
948
+ reason = 'Requires retry';
949
+ }
950
+ else if (labelNames.includes('blocked')) {
951
+ reason = 'Blocked by dependencies';
952
+ }
953
+ else if (labelNames.includes('needs-help')) {
954
+ reason = 'Needs manual intervention';
955
+ }
956
+ failedIssues.push({
957
+ id: issue.id,
958
+ identifier: issue.identifier,
959
+ title: issue.title,
960
+ description: issue.description ?? undefined,
961
+ state: state?.name ?? 'Unknown',
962
+ priority: issue.priority,
963
+ labels: labelNames,
964
+ comments: comments.nodes.map((c) => ({
965
+ id: c.id,
966
+ body: c.body,
967
+ createdAt: c.createdAt.toISOString(),
968
+ user: undefined,
969
+ })),
970
+ project,
971
+ reason,
972
+ });
973
+ }
974
+ return {
975
+ stuckIssues: stuckIssues.sort((a, b) => b.stuckDays - a.stuckDays),
976
+ failedIssues: failedIssues.sort((a, b) => {
977
+ const pa = a.priority === 0 ? 999 : a.priority;
978
+ const pb = b.priority === 0 ? 999 : b.priority;
979
+ return pa - pb;
980
+ }),
981
+ };
982
+ }
983
+ //# sourceMappingURL=linear.js.map