@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,938 @@
1
+ // ============================================
2
+ // OpenSwarm - Web Interface
3
+ // ============================================
4
+ import { createServer } from 'node:http';
5
+ import { writeFileSync, readFileSync, existsSync } from 'node:fs';
6
+ import { join } from 'node:path';
7
+ import { homedir } from 'node:os';
8
+ import { execFile } from 'node:child_process';
9
+ import { getChatHistory } from '../discord/index.js';
10
+ import { addSSEClient, getActiveSSECount, broadcastEvent, getLogBuffer, getStageBuffer, getChatBuffer } from '../core/eventHub.js';
11
+ import { formatCost } from './costTracker.js';
12
+ import { getRateLimiterMetrics } from './rateLimiter.js';
13
+ import { scanLocalProjects, invalidateProjectCache } from './projectMapper.js';
14
+ import { DASHBOARD_HTML } from './dashboardHtml.js';
15
+ import { getGraph, toProjectSlug, getProjectHealth, scanAndCache, listGraphs } from '../knowledge/index.js';
16
+ import { getProjectGitInfo, startGitStatusPoller } from './gitStatus.js';
17
+ import { getActiveMonitors, registerMonitor, unregisterMonitor } from '../automation/longRunningMonitor.js';
18
+ import { getAllProcesses, killProcess, startHealthChecker } from '../adapters/processRegistry.js';
19
+ import { setDefaultAdapter } from '../adapters/index.js';
20
+ import * as memory from '../memory/index.js';
21
+ import { fetchQuota } from './quotaTracker.js';
22
+ import { PairPipeline } from '../agents/pairPipeline.js';
23
+ import { initLocale } from '../locale/index.js';
24
+ import { runChatCompletion, getDefaultChatModel } from './chatBackend.js';
25
+ let server = null;
26
+ let runnerRef;
27
+ const execTasks = new Map();
28
+ function cleanupExecTask(taskId) {
29
+ setTimeout(() => { execTasks.delete(taskId); }, 3600000); // 1 hour
30
+ }
31
+ // Pinned + enabled repos persistence
32
+ const REPOS_FILE = join(homedir(), '.claude', 'openswarm-repos.json');
33
+ function loadReposConfig() {
34
+ try {
35
+ if (existsSync(REPOS_FILE)) {
36
+ return JSON.parse(readFileSync(REPOS_FILE, 'utf-8'));
37
+ }
38
+ }
39
+ catch { }
40
+ return { pinned: [], enabled: [], basePaths: [], removedConfigPaths: [] };
41
+ }
42
+ function saveReposConfig() {
43
+ try {
44
+ const cfg = {
45
+ pinned: Array.from(pinnedProjects),
46
+ enabled: runnerRef?.getEnabledProjects() ?? [],
47
+ basePaths: Array.from(customBasePaths),
48
+ removedConfigPaths: Array.from(removedConfigPaths),
49
+ };
50
+ writeFileSync(REPOS_FILE, JSON.stringify(cfg, null, 2));
51
+ }
52
+ catch (e) {
53
+ console.warn('[Web] Failed to save repos config:', e);
54
+ }
55
+ }
56
+ const _reposCfg = loadReposConfig();
57
+ const pinnedProjects = new Set(_reposCfg.pinned);
58
+ const customBasePaths = new Set(_reposCfg.basePaths ?? []);
59
+ const removedConfigPaths = new Set(_reposCfg.removedConfigPaths ?? []);
60
+ /**
61
+ * Set runner reference (call after autonomous runner is initialized)
62
+ */
63
+ export function setWebRunner(runner) {
64
+ runnerRef = runner;
65
+ // Restore persisted enabled state
66
+ for (const path of _reposCfg.enabled) {
67
+ runner.enableProject(path);
68
+ }
69
+ // 대시보드에서 제거된 config 경로를 runner의 allowedProjects에서도 제거
70
+ if (removedConfigPaths.size > 0) {
71
+ const current = runner.getAllowedProjects();
72
+ const filtered = current.filter(p => !removedConfigPaths.has(p));
73
+ if (filtered.length !== current.length) {
74
+ runner.updateAllowedProjects(filtered);
75
+ }
76
+ }
77
+ // Pre-seed path cache from pinned + enabled projects so tasks without execution history are still matched
78
+ const allSeeded = new Set([...pinnedProjects, ..._reposCfg.enabled]);
79
+ for (const path of allSeeded) {
80
+ const name = path.split('/').pop();
81
+ if (name)
82
+ runner.registerProjectPath(name, path);
83
+ }
84
+ }
85
+ // Read POST body helper
86
+ function readBody(req) {
87
+ return new Promise((resolve) => {
88
+ let data = '';
89
+ req.on('data', (chunk) => { data += chunk.toString(); });
90
+ req.on('end', () => resolve(data));
91
+ });
92
+ }
93
+ // Start web server
94
+ export async function startWebServer(port = 3847) {
95
+ if (server) {
96
+ console.log('Web interface already running, skipping...');
97
+ return;
98
+ }
99
+ return new Promise((resolve, reject) => {
100
+ server = createServer(async (req, res) => {
101
+ const url = req.url?.split('?')[0] || '/';
102
+ // CORS: allow localhost and Tailscale network
103
+ const origin = req.headers.origin;
104
+ if (origin && (origin.startsWith('http://localhost:') ||
105
+ origin.startsWith('http://127.0.0.1:') ||
106
+ origin.startsWith('http://100.') // Tailscale CGNAT range (100.64.0.0/10)
107
+ )) {
108
+ res.setHeader('Access-Control-Allow-Origin', origin);
109
+ res.setHeader('Access-Control-Allow-Methods', 'GET, POST, DELETE');
110
+ }
111
+ // ---- Dashboard ----
112
+ if (url === '/' || url === '/index.html') {
113
+ res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
114
+ res.end(DASHBOARD_HTML);
115
+ // ---- SSE stream ----
116
+ }
117
+ else if (url === '/api/events') {
118
+ const skipReplay = req.url?.includes('skipReplay=1') ?? false;
119
+ res.writeHead(200, {
120
+ 'Content-Type': 'text/event-stream',
121
+ 'Cache-Control': 'no-cache',
122
+ 'Connection': 'keep-alive',
123
+ });
124
+ res.write(':connected\n\n');
125
+ addSSEClient(res, skipReplay);
126
+ // ---- Stats ----
127
+ }
128
+ else if (url === '/api/stats') {
129
+ const stats = runnerRef?.getStats();
130
+ const state = runnerRef?.getState();
131
+ const adapters = runnerRef?.getAdapterSummary();
132
+ res.writeHead(200, { 'Content-Type': 'application/json' });
133
+ res.end(JSON.stringify({
134
+ runningTasks: stats?.schedulerStats?.running ?? 0,
135
+ queuedTasks: stats?.schedulerStats?.queued ?? 0,
136
+ completedToday: stats?.schedulerStats?.completed ?? 0,
137
+ uptime: state?.startedAt ? Date.now() - state.startedAt : 0,
138
+ isRunning: stats?.isRunning ?? false,
139
+ sseClients: getActiveSSECount(),
140
+ adapters,
141
+ turboMode: stats?.turboMode ?? false,
142
+ turboExpiresAt: stats?.turboExpiresAt ?? null,
143
+ dailyPace: stats?.dailyPace ?? null,
144
+ }));
145
+ // ---- Tasks ----
146
+ }
147
+ else if (url === '/api/tasks') {
148
+ const running = runnerRef?.getRunningTasks() ?? [];
149
+ const queued = runnerRef?.getQueuedTasks() ?? [];
150
+ res.writeHead(200, { 'Content-Type': 'application/json' });
151
+ res.end(JSON.stringify({ running, queued }));
152
+ // ---- Pipeline GET (detailed pipeline stages) ----
153
+ }
154
+ else if (url === '/api/pipeline') {
155
+ const stages = getStageBuffer();
156
+ res.writeHead(200, { 'Content-Type': 'application/json' });
157
+ res.end(JSON.stringify({ stages }));
158
+ // ---- Rate Limiter Metrics GET ----
159
+ }
160
+ else if (url === '/api/rate-limits') {
161
+ const metrics = getRateLimiterMetrics();
162
+ res.writeHead(200, { 'Content-Type': 'application/json' });
163
+ res.end(JSON.stringify(metrics));
164
+ // ---- Projects GET (pinned + active projects) ----
165
+ }
166
+ else if (url === '/api/projects' && req.method === 'GET') {
167
+ const enabledPaths = new Set(runnerRef?.getEnabledProjects() ?? []);
168
+ const taskInfo = runnerRef?.getProjectsInfo() ?? [];
169
+ const byPath = new Map(taskInfo.filter(p => p.path).map(p => [p.path, p]));
170
+ // Fallback: match by project name (for tasks not yet executed → path not cached)
171
+ const byName = new Map(taskInfo.map(p => [p.name, p]));
172
+ // Start with pinned projects
173
+ const allPaths = new Set(pinnedProjects);
174
+ // Auto-include enabled projects and projects with active tasks
175
+ for (const path of enabledPaths)
176
+ allPaths.add(path);
177
+ for (const info of taskInfo) {
178
+ if (info.path && (info.running.length > 0 || info.queued.length > 0)) {
179
+ allPaths.add(info.path);
180
+ }
181
+ }
182
+ const result = await Promise.all(Array.from(allPaths).map(async (p) => {
183
+ const dirName = p.split('/').pop() ?? p;
184
+ const info = byPath.get(p) ?? byName.get(dirName);
185
+ const gitInfo = await getProjectGitInfo(p);
186
+ return {
187
+ path: p,
188
+ name: dirName,
189
+ enabled: enabledPaths.has(p),
190
+ pinned: pinnedProjects.has(p),
191
+ running: info?.running ?? [],
192
+ queued: info?.queued ?? [],
193
+ pending: info?.pending ?? [],
194
+ git: gitInfo.git,
195
+ prs: gitInfo.prs,
196
+ };
197
+ }));
198
+ result.sort((a, b) => {
199
+ const aActive = a.running.length + a.queued.length + a.pending.length;
200
+ const bActive = b.running.length + b.queued.length + b.pending.length;
201
+ if (aActive !== bActive)
202
+ return bActive - aActive;
203
+ return a.name.localeCompare(b.name);
204
+ });
205
+ res.writeHead(200, { 'Content-Type': 'application/json' });
206
+ res.end(JSON.stringify(result));
207
+ // ---- Local projects for picker ----
208
+ }
209
+ else if (url === '/api/local-projects' && req.method === 'GET') {
210
+ const configPaths = runnerRef?.getAllowedProjects() ?? [];
211
+ const allBasePaths = [...new Set([...configPaths, ...customBasePaths])];
212
+ try {
213
+ const locals = await scanLocalProjects(allBasePaths);
214
+ const SKIP = ['/node_modules/', '/.git/', '/dist/', '/build/', '/__pycache__/', '/venv/', '/.venv/'];
215
+ const filtered = locals.filter(l => !SKIP.some(s => l.path.includes(s)));
216
+ res.writeHead(200, { 'Content-Type': 'application/json' });
217
+ res.end(JSON.stringify(filtered.map(l => ({ path: l.path, name: l.name, pinned: pinnedProjects.has(l.path) }))));
218
+ }
219
+ catch (e) {
220
+ res.writeHead(500, { 'Content-Type': 'application/json' });
221
+ res.end(JSON.stringify({ error: String(e) }));
222
+ }
223
+ // ---- Pin project ----
224
+ }
225
+ else if (url === '/api/projects/pin' && req.method === 'POST') {
226
+ const body = await readBody(req);
227
+ try {
228
+ const { projectPath } = JSON.parse(body);
229
+ if (typeof projectPath === 'string' && projectPath) {
230
+ pinnedProjects.add(projectPath);
231
+ saveReposConfig();
232
+ // Seed path cache so Linear project name matches immediately
233
+ const name = projectPath.split('/').pop();
234
+ if (name && runnerRef)
235
+ runnerRef.registerProjectPath(name, projectPath);
236
+ }
237
+ res.writeHead(200, { 'Content-Type': 'application/json' });
238
+ res.end(JSON.stringify({ ok: true }));
239
+ }
240
+ catch {
241
+ res.writeHead(400).end(JSON.stringify({ error: 'Invalid JSON' }));
242
+ }
243
+ // ---- Unpin project ----
244
+ }
245
+ else if (url === '/api/projects/unpin' && req.method === 'POST') {
246
+ const body = await readBody(req);
247
+ try {
248
+ const { projectPath } = JSON.parse(body);
249
+ if (typeof projectPath === 'string') {
250
+ pinnedProjects.delete(projectPath);
251
+ // Also disable the project so it doesn't reappear via enabledPaths
252
+ runnerRef?.disableProject(projectPath);
253
+ saveReposConfig();
254
+ }
255
+ res.writeHead(200, { 'Content-Type': 'application/json' });
256
+ res.end(JSON.stringify({ ok: true }));
257
+ }
258
+ catch {
259
+ res.writeHead(400).end(JSON.stringify({ error: 'Invalid JSON' }));
260
+ }
261
+ // ---- Projects Toggle ----
262
+ }
263
+ else if (url === '/api/projects/toggle' && req.method === 'POST') {
264
+ const body = await readBody(req);
265
+ try {
266
+ const { projectPath, enabled } = JSON.parse(body);
267
+ if (typeof projectPath === 'string' && typeof enabled === 'boolean') {
268
+ if (enabled)
269
+ runnerRef?.enableProject(projectPath);
270
+ else
271
+ runnerRef?.disableProject(projectPath);
272
+ saveReposConfig();
273
+ broadcastEvent({ type: 'project:toggled', data: { projectPath, enabled } });
274
+ }
275
+ res.writeHead(200, { 'Content-Type': 'application/json' });
276
+ res.end(JSON.stringify({ ok: true }));
277
+ }
278
+ catch {
279
+ res.writeHead(400, { 'Content-Type': 'application/json' });
280
+ res.end(JSON.stringify({ error: 'Invalid JSON' }));
281
+ }
282
+ // ---- Move Issue to Todo ----
283
+ }
284
+ else if (url === '/api/issue/move-to-todo' && req.method === 'POST') {
285
+ const body = await readBody(req);
286
+ try {
287
+ const { issueId } = JSON.parse(body);
288
+ if (!issueId) {
289
+ res.writeHead(400, { 'Content-Type': 'application/json' });
290
+ res.end(JSON.stringify({ error: 'Missing issueId' }));
291
+ return;
292
+ }
293
+ // Import linear dynamically to avoid circular deps
294
+ const linearModule = await import('../linear/index.js');
295
+ await linearModule.updateIssueState(issueId, 'Todo');
296
+ res.writeHead(200, { 'Content-Type': 'application/json' });
297
+ res.end(JSON.stringify({ ok: true }));
298
+ }
299
+ catch (error) {
300
+ console.error('[Web] Failed to move issue to Todo:', error);
301
+ res.writeHead(500, { 'Content-Type': 'application/json' });
302
+ res.end(JSON.stringify({ error: String(error) }));
303
+ }
304
+ // ---- Heartbeat (manual trigger) ----
305
+ }
306
+ else if (url === '/api/heartbeat' && req.method === 'POST') {
307
+ res.writeHead(202, { 'Content-Type': 'application/json' });
308
+ res.end(JSON.stringify({ ok: true }));
309
+ // Non-blocking heartbeat
310
+ runnerRef?.heartbeat().catch((e) => console.error('[Web] Heartbeat error:', e));
311
+ // ---- Provider toggle ----
312
+ }
313
+ else if (url === '/api/provider' && req.method === 'POST') {
314
+ const body = await readBody(req);
315
+ try {
316
+ const { provider } = JSON.parse(body);
317
+ if (provider !== 'claude' && provider !== 'codex') {
318
+ res.writeHead(400, { 'Content-Type': 'application/json' });
319
+ res.end(JSON.stringify({ error: 'Invalid provider' }));
320
+ return;
321
+ }
322
+ setDefaultAdapter(provider);
323
+ runnerRef?.switchProvider(provider);
324
+ broadcastEvent({
325
+ type: 'log',
326
+ data: { taskId: 'system', stage: 'provider', line: `Provider switched to ${provider}` },
327
+ });
328
+ res.writeHead(200, { 'Content-Type': 'application/json' });
329
+ res.end(JSON.stringify({ ok: true, provider }));
330
+ }
331
+ catch {
332
+ res.writeHead(400, { 'Content-Type': 'application/json' });
333
+ res.end(JSON.stringify({ error: 'Invalid JSON' }));
334
+ }
335
+ // ---- Turbo Mode Toggle ----
336
+ }
337
+ else if (url === '/api/turbo' && req.method === 'POST') {
338
+ const body = await readBody(req);
339
+ try {
340
+ const { enabled } = JSON.parse(body);
341
+ if (typeof enabled !== 'boolean') {
342
+ res.writeHead(400, { 'Content-Type': 'application/json' });
343
+ res.end(JSON.stringify({ error: 'enabled must be boolean' }));
344
+ return;
345
+ }
346
+ runnerRef?.setTurboMode(enabled);
347
+ res.writeHead(200, { 'Content-Type': 'application/json' });
348
+ res.end(JSON.stringify({ ok: true, turboMode: enabled }));
349
+ }
350
+ catch {
351
+ res.writeHead(400, { 'Content-Type': 'application/json' });
352
+ res.end(JSON.stringify({ error: 'Invalid JSON' }));
353
+ }
354
+ // ---- PR Processor Status ----
355
+ }
356
+ else if (url === '/api/pr-processor-status' && req.method === 'GET') {
357
+ try {
358
+ const { getPRProcessor } = await import('../core/service.js');
359
+ const processor = getPRProcessor();
360
+ const status = processor ? processor.getStatus() : null;
361
+ res.writeHead(200, { 'Content-Type': 'application/json' });
362
+ res.end(JSON.stringify(status));
363
+ }
364
+ catch (error) {
365
+ res.writeHead(500, { 'Content-Type': 'application/json' });
366
+ res.end(JSON.stringify({ error: String(error) }));
367
+ }
368
+ // ---- Trigger PR Processor ----
369
+ }
370
+ else if (url === '/api/trigger-pr-processor' && req.method === 'POST') {
371
+ try {
372
+ const { getPRProcessor } = await import('../core/service.js');
373
+ const processor = getPRProcessor();
374
+ if (!processor) {
375
+ res.writeHead(404, { 'Content-Type': 'application/json' });
376
+ res.end(JSON.stringify({ error: 'PR Processor not initialized' }));
377
+ return;
378
+ }
379
+ res.writeHead(202, { 'Content-Type': 'application/json' });
380
+ res.end(JSON.stringify({ ok: true }));
381
+ // Non-blocking PR processing
382
+ processor.processPRs().catch((e) => console.error('[Web] PR Processor error:', e));
383
+ }
384
+ catch (error) {
385
+ res.writeHead(500, { 'Content-Type': 'application/json' });
386
+ res.end(JSON.stringify({ error: String(error) }));
387
+ }
388
+ // ---- CI Worker Status ----
389
+ }
390
+ else if (url === '/api/ci-worker-status' && req.method === 'GET') {
391
+ try {
392
+ const { getCIWorkerStatus } = await import('../automation/ciWorker.js');
393
+ const status = getCIWorkerStatus();
394
+ res.writeHead(200, { 'Content-Type': 'application/json' });
395
+ res.end(JSON.stringify(status));
396
+ }
397
+ catch (error) {
398
+ res.writeHead(500, { 'Content-Type': 'application/json' });
399
+ res.end(JSON.stringify({ error: String(error) }));
400
+ }
401
+ // ---- Stuck/Failed Issues ----
402
+ }
403
+ else if (url === '/api/stuck-issues' && req.method === 'GET') {
404
+ try {
405
+ const linearModule = await import('../linear/index.js');
406
+ const result = await linearModule.getStuckIssues();
407
+ res.writeHead(200, { 'Content-Type': 'application/json' });
408
+ res.end(JSON.stringify(result));
409
+ }
410
+ catch (error) {
411
+ console.error('[Web] Failed to fetch stuck issues:', error);
412
+ res.writeHead(500, { 'Content-Type': 'application/json' });
413
+ res.end(JSON.stringify({ error: String(error) }));
414
+ }
415
+ // ---- Chat history ----
416
+ }
417
+ else if (url === '/api/chat/history' && req.method === 'GET') {
418
+ const buf = getChatBuffer();
419
+ const history = buf
420
+ .filter((ev) => ev.type === 'chat:user' || ev.type === 'chat:agent')
421
+ .map(ev => ({
422
+ role: ev.type === 'chat:user' ? 'user' : 'agent',
423
+ text: ev.data.text,
424
+ ts: ev.data.ts,
425
+ }));
426
+ res.writeHead(200, { 'Content-Type': 'application/json' });
427
+ res.end(JSON.stringify(history.slice(-50)));
428
+ // ---- Log buffer snapshot ----
429
+ }
430
+ else if (url === '/api/logs' && req.method === 'GET') {
431
+ // 성능 최적화: 최근 200개 로그만 반환 (응답 시간 단축)
432
+ const allLogs = getLogBuffer();
433
+ const recentLogs = allLogs.slice(-200);
434
+ res.writeHead(200, { 'Content-Type': 'application/json' });
435
+ res.end(JSON.stringify(recentLogs));
436
+ // ---- Stage buffer snapshot ----
437
+ }
438
+ else if (url === '/api/stages' && req.method === 'GET') {
439
+ // 성능 최적화: 최근 100개 스테이지만 반환 (응답 시간 단축)
440
+ const allStages = getStageBuffer();
441
+ const recentStages = allStages.slice(-100);
442
+ res.writeHead(200, { 'Content-Type': 'application/json' });
443
+ res.end(JSON.stringify(recentStages));
444
+ // ---- Chat message ----
445
+ }
446
+ else if (url === '/api/chat' && req.method === 'POST') {
447
+ const body = await readBody(req);
448
+ let message;
449
+ try {
450
+ message = JSON.parse(body).message?.trim();
451
+ }
452
+ catch {
453
+ res.writeHead(400, { 'Content-Type': 'application/json' });
454
+ res.end(JSON.stringify({ error: 'Invalid JSON' }));
455
+ return;
456
+ }
457
+ if (!message) {
458
+ res.writeHead(400, { 'Content-Type': 'application/json' });
459
+ res.end(JSON.stringify({ error: 'Empty message' }));
460
+ return;
461
+ }
462
+ broadcastEvent({ type: 'chat:user', data: { text: message, ts: Date.now() } });
463
+ // Build context-aware prompt (including previous conversation)
464
+ const stats = runnerRef?.getStats();
465
+ const projects = runnerRef?.getProjectsInfo() ?? [];
466
+ const enabled = projects.filter(p => p.enabled).length;
467
+ const state = runnerRef?.getState();
468
+ const uptimeSec = state?.startedAt ? Math.floor((Date.now() - state.startedAt) / 1000) : 0;
469
+ // 1. Short-term memory: recent chat buffer
470
+ const chatBuf = getChatBuffer()
471
+ .filter((ev) => ev.type === 'chat:user' || ev.type === 'chat:agent');
472
+ const recentHistory = chatBuf.slice(-11, -1);
473
+ const historyBlock = recentHistory.length > 0
474
+ ? recentHistory.map(m => (m.type === 'chat:user' ? 'User' : 'OpenSwarm') + ': ' + m.data.text).join('\n\n')
475
+ : '';
476
+ // 2. Long-term memory: semantic search (shared with Discord)
477
+ const memories = await memory.searchMemory(message, {
478
+ types: ['journal'],
479
+ repo: 'chat', // Shared repo for both Discord and Dashboard
480
+ limit: 5,
481
+ minSimilarity: 0.4,
482
+ minTrust: 0.5,
483
+ });
484
+ const memoryContext = memories.length > 0
485
+ ? '## Relevant Past Discussions\n' + memories.map(m => `- ${m.content.replace(/^Q: |^A: /g, '')}`).join('\n')
486
+ : '';
487
+ const provider = runnerRef?.getAdapterSummary().defaultAdapter ?? 'claude';
488
+ const model = runnerRef?.getAdapterSummary().worker?.model ?? getDefaultChatModel(provider);
489
+ const contextPrompt = [
490
+ 'You are OpenSwarm, an autonomous code development supervisor.',
491
+ 'You manage a fleet of coding agents that autonomously work on Linear issues.',
492
+ `Current chat provider: ${provider}`,
493
+ `Current chat model: ${model}`,
494
+ '',
495
+ 'Current system status:',
496
+ '- Running tasks: ' + (stats?.schedulerStats?.running ?? 0),
497
+ '- Queued tasks: ' + (stats?.schedulerStats?.queued ?? 0),
498
+ '- Completed today: ' + (stats?.schedulerStats?.completed ?? 0),
499
+ '- Active repos: ' + enabled + '/' + projects.length,
500
+ '- Uptime: ' + uptimeSec + 's',
501
+ '',
502
+ ...(historyBlock ? [
503
+ 'Conversation history (most recent first):',
504
+ historyBlock,
505
+ '',
506
+ ] : []),
507
+ ...(memoryContext ? [memoryContext, ''] : []),
508
+ 'Answer the user concisely and helpfully in the same language they use. Use the status data above if relevant.',
509
+ '',
510
+ 'User: ' + message,
511
+ ].join('\n');
512
+ const result = await runChatCompletion({
513
+ prompt: contextPrompt,
514
+ provider,
515
+ model,
516
+ cwd: process.cwd(),
517
+ timeoutMs: 180000,
518
+ }).catch((error) => ({
519
+ response: `[Error: ${error.message}]`,
520
+ provider,
521
+ model,
522
+ cost: undefined,
523
+ tokens: undefined,
524
+ }));
525
+ const response = result.response;
526
+ if (result.cost !== undefined) {
527
+ console.log(`[Web Chat] Cost: ${formatCost({
528
+ costUsd: result.cost,
529
+ inputTokens: result.tokens ?? 0,
530
+ outputTokens: 0,
531
+ cacheReadTokens: 0,
532
+ cacheCreationTokens: 0,
533
+ durationMs: 0,
534
+ model: result.model,
535
+ })}`);
536
+ }
537
+ broadcastEvent({ type: 'chat:agent', data: { text: response, ts: Date.now() } });
538
+ // 3. Save conversation to long-term memory
539
+ await memory.saveConversation('dashboard', // channelId (fixed for dashboard)
540
+ 'dashboard-user', // userId
541
+ 'User', // userName
542
+ message, response);
543
+ console.log(`[Dashboard Chat] Saved to memory (${message.length} + ${response.length} chars)`);
544
+ res.writeHead(200, { 'Content-Type': 'application/json' });
545
+ res.end(JSON.stringify({ ok: true, response, provider: result.provider, model: result.model }));
546
+ // ---- Service control: status ----
547
+ }
548
+ else if (url === '/api/service/status' && req.method === 'GET') {
549
+ try {
550
+ const result = await new Promise((resolve) => {
551
+ execFile('systemctl', ['--user', 'is-active', 'openswarm'], (_err, stdout) => {
552
+ resolve(stdout.trim());
553
+ });
554
+ });
555
+ res.writeHead(200, { 'Content-Type': 'application/json' });
556
+ res.end(JSON.stringify({ status: result }));
557
+ }
558
+ catch {
559
+ res.writeHead(500, { 'Content-Type': 'application/json' });
560
+ res.end(JSON.stringify({ status: 'unknown' }));
561
+ }
562
+ // ---- Service control: stop ----
563
+ }
564
+ else if (url === '/api/service/stop' && req.method === 'POST') {
565
+ try {
566
+ await new Promise((resolve, reject) => {
567
+ execFile('systemctl', ['--user', 'stop', 'openswarm'], (err) => {
568
+ if (err)
569
+ reject(err);
570
+ else
571
+ resolve();
572
+ });
573
+ });
574
+ res.writeHead(200, { 'Content-Type': 'application/json' });
575
+ res.end(JSON.stringify({ ok: true }));
576
+ }
577
+ catch (e) {
578
+ res.writeHead(500, { 'Content-Type': 'application/json' });
579
+ res.end(JSON.stringify({ error: String(e) }));
580
+ }
581
+ // ---- Service control: restart ----
582
+ }
583
+ else if (url === '/api/service/restart' && req.method === 'POST') {
584
+ try {
585
+ await new Promise((resolve, reject) => {
586
+ execFile('systemctl', ['--user', 'restart', 'openswarm'], (err) => {
587
+ if (err)
588
+ reject(err);
589
+ else
590
+ resolve();
591
+ });
592
+ });
593
+ res.writeHead(200, { 'Content-Type': 'application/json' });
594
+ res.end(JSON.stringify({ ok: true }));
595
+ }
596
+ catch (e) {
597
+ res.writeHead(500, { 'Content-Type': 'application/json' });
598
+ res.end(JSON.stringify({ error: String(e) }));
599
+ }
600
+ // ---- Knowledge Graph: project health ----
601
+ }
602
+ else if (url.startsWith('/api/knowledge/') && req.method === 'GET') {
603
+ const projectSlug = url.replace('/api/knowledge/', '').split('?')[0];
604
+ if (!projectSlug) {
605
+ res.writeHead(400, { 'Content-Type': 'application/json' });
606
+ res.end(JSON.stringify({ error: 'Missing project slug' }));
607
+ }
608
+ else {
609
+ try {
610
+ const graph = await getGraph(projectSlug);
611
+ if (!graph) {
612
+ res.writeHead(404, { 'Content-Type': 'application/json' });
613
+ res.end(JSON.stringify({ error: 'Graph not found. Run a scan first.' }));
614
+ }
615
+ else {
616
+ const health = getProjectHealth(graph);
617
+ res.writeHead(200, { 'Content-Type': 'application/json' });
618
+ res.end(JSON.stringify({
619
+ slug: projectSlug,
620
+ scannedAt: graph.scannedAt,
621
+ nodeCount: graph.nodeCount,
622
+ edgeCount: graph.edgeCount,
623
+ ...health,
624
+ }));
625
+ }
626
+ }
627
+ catch (e) {
628
+ res.writeHead(500, { 'Content-Type': 'application/json' });
629
+ res.end(JSON.stringify({ error: String(e) }));
630
+ }
631
+ }
632
+ // ---- Knowledge Graph: list all ----
633
+ }
634
+ else if (url === '/api/knowledge' && req.method === 'GET') {
635
+ try {
636
+ const slugs = await listGraphs();
637
+ const result = [];
638
+ for (const slug of slugs) {
639
+ const graph = await getGraph(slug);
640
+ if (graph) {
641
+ result.push({
642
+ slug,
643
+ nodeCount: graph.nodeCount,
644
+ edgeCount: graph.edgeCount,
645
+ scannedAt: graph.scannedAt,
646
+ summary: graph.buildSummary(),
647
+ });
648
+ }
649
+ }
650
+ res.writeHead(200, { 'Content-Type': 'application/json' });
651
+ res.end(JSON.stringify(result));
652
+ }
653
+ catch (e) {
654
+ res.writeHead(500, { 'Content-Type': 'application/json' });
655
+ res.end(JSON.stringify({ error: String(e) }));
656
+ }
657
+ // ---- Knowledge Graph: trigger scan ----
658
+ }
659
+ else if (url === '/api/knowledge/scan' && req.method === 'POST') {
660
+ const body = await readBody(req);
661
+ try {
662
+ const { projectPath } = JSON.parse(body);
663
+ if (!projectPath) {
664
+ res.writeHead(400, { 'Content-Type': 'application/json' });
665
+ res.end(JSON.stringify({ error: 'Missing projectPath' }));
666
+ }
667
+ else {
668
+ const resolvedPath = projectPath.replace('~', homedir());
669
+ res.writeHead(202, { 'Content-Type': 'application/json' });
670
+ res.end(JSON.stringify({ ok: true, slug: toProjectSlug(resolvedPath) }));
671
+ // Non-blocking scan
672
+ scanAndCache(resolvedPath, { force: true }).catch(e => console.error('[Web] Knowledge scan error:', e));
673
+ }
674
+ }
675
+ catch {
676
+ res.writeHead(400, { 'Content-Type': 'application/json' });
677
+ res.end(JSON.stringify({ error: 'Invalid JSON' }));
678
+ }
679
+ // ---- Pipeline history (time-ordered) ----
680
+ }
681
+ else if (url === '/api/pipeline/history' && req.method === 'GET') {
682
+ const limitParam = (req.url?.split('?')[1] || '').match(/limit=(\d+)/);
683
+ const limit = limitParam ? Math.min(Number(limitParam[1]), 100) : 50;
684
+ const history = runnerRef?.getPipelineHistory(limit) ?? [];
685
+ res.writeHead(200, { 'Content-Type': 'application/json' });
686
+ res.end(JSON.stringify(history));
687
+ // ---- Monitors: list ----
688
+ }
689
+ else if (url === '/api/monitors' && req.method === 'GET') {
690
+ res.writeHead(200, { 'Content-Type': 'application/json' });
691
+ res.end(JSON.stringify(getActiveMonitors()));
692
+ // ---- Monitors: register ----
693
+ }
694
+ else if (url === '/api/monitors' && req.method === 'POST') {
695
+ const body = await readBody(req);
696
+ try {
697
+ const config = JSON.parse(body);
698
+ if (!config.id || !config.name || !config.checkCommand || !config.completionCheck) {
699
+ res.writeHead(400, { 'Content-Type': 'application/json' });
700
+ res.end(JSON.stringify({ error: 'Missing required fields: id, name, checkCommand, completionCheck' }));
701
+ return;
702
+ }
703
+ const monitor = registerMonitor(config);
704
+ res.writeHead(201, { 'Content-Type': 'application/json' });
705
+ res.end(JSON.stringify(monitor));
706
+ }
707
+ catch {
708
+ res.writeHead(400, { 'Content-Type': 'application/json' });
709
+ res.end(JSON.stringify({ error: 'Invalid JSON' }));
710
+ }
711
+ // ---- Monitors: delete ----
712
+ }
713
+ else if (url.startsWith('/api/monitors/') && req.method === 'DELETE') {
714
+ const monitorId = url.replace('/api/monitors/', '');
715
+ const deleted = unregisterMonitor(monitorId);
716
+ res.writeHead(deleted ? 200 : 404, { 'Content-Type': 'application/json' });
717
+ res.end(JSON.stringify({ ok: deleted }));
718
+ // ---- Processes: list ----
719
+ }
720
+ else if (url === '/api/processes' && req.method === 'GET') {
721
+ res.writeHead(200, { 'Content-Type': 'application/json' });
722
+ res.end(JSON.stringify(getAllProcesses()));
723
+ // ---- Processes: kill ----
724
+ }
725
+ else if (url.startsWith('/api/processes/') && req.method === 'DELETE') {
726
+ const pidStr = url.replace('/api/processes/', '');
727
+ const pid = parseInt(pidStr, 10);
728
+ if (isNaN(pid)) {
729
+ res.writeHead(400, { 'Content-Type': 'application/json' });
730
+ res.end(JSON.stringify({ error: 'Invalid PID' }));
731
+ }
732
+ else {
733
+ const killed = await killProcess(pid);
734
+ res.writeHead(killed ? 200 : 404, { 'Content-Type': 'application/json' });
735
+ res.end(JSON.stringify({ ok: killed }));
736
+ }
737
+ // ---- Scan Paths: list ----
738
+ }
739
+ else if (url === '/api/scan-paths' && req.method === 'GET') {
740
+ // removedConfigPaths에 있는 경로는 UI에 표시하지 않음
741
+ const allConfigPaths = runnerRef?.getAllowedProjects() ?? [];
742
+ const configPaths = allConfigPaths.filter(p => !removedConfigPaths.has(p));
743
+ res.writeHead(200, { 'Content-Type': 'application/json' });
744
+ res.end(JSON.stringify({
745
+ configPaths,
746
+ customPaths: Array.from(customBasePaths),
747
+ }));
748
+ // ---- Scan Paths: add ----
749
+ }
750
+ else if (url === '/api/scan-paths' && req.method === 'POST') {
751
+ const body = await readBody(req);
752
+ try {
753
+ const { path: newPath } = JSON.parse(body);
754
+ if (typeof newPath !== 'string' || !newPath.trim()) {
755
+ res.writeHead(400, { 'Content-Type': 'application/json' });
756
+ res.end(JSON.stringify({ error: 'Missing path' }));
757
+ }
758
+ else {
759
+ customBasePaths.add(newPath.trim());
760
+ invalidateProjectCache();
761
+ // Update runner's allowedProjects with merged list
762
+ const configPaths = runnerRef?.getAllowedProjects() ?? [];
763
+ const merged = [...new Set([...configPaths, ...customBasePaths])];
764
+ runnerRef?.updateAllowedProjects(merged);
765
+ saveReposConfig();
766
+ res.writeHead(200, { 'Content-Type': 'application/json' });
767
+ res.end(JSON.stringify({ ok: true }));
768
+ }
769
+ }
770
+ catch {
771
+ res.writeHead(400, { 'Content-Type': 'application/json' });
772
+ res.end(JSON.stringify({ error: 'Invalid JSON' }));
773
+ }
774
+ // ---- Scan Paths: remove ----
775
+ }
776
+ else if (url.startsWith('/api/scan-paths/') && req.method === 'DELETE') {
777
+ const encodedPath = url.replace('/api/scan-paths/', '');
778
+ const decodedPath = decodeURIComponent(encodedPath);
779
+ // customPaths에서 제거
780
+ customBasePaths.delete(decodedPath);
781
+ // configPaths에서도 제거: removedConfigPaths에 기록하고 runner에서 즉시 반영
782
+ const allConfigPaths = runnerRef?.getAllowedProjects() ?? [];
783
+ if (allConfigPaths.includes(decodedPath)) {
784
+ removedConfigPaths.add(decodedPath);
785
+ runnerRef?.updateAllowedProjects(allConfigPaths.filter(p => p !== decodedPath));
786
+ }
787
+ invalidateProjectCache();
788
+ saveReposConfig();
789
+ res.writeHead(200, { 'Content-Type': 'application/json' });
790
+ res.end(JSON.stringify({ ok: true }));
791
+ // ---- Claude Code Quota ----
792
+ }
793
+ else if (url === '/api/quota' && req.method === 'GET') {
794
+ const quota = await fetchQuota();
795
+ res.writeHead(200, { 'Content-Type': 'application/json' });
796
+ res.end(JSON.stringify(quota ?? { error: 'unavailable' }));
797
+ // ---- Discord history (legacy) ----
798
+ }
799
+ else if (url === '/api/history') {
800
+ const history = await getChatHistory();
801
+ res.writeHead(200, { 'Content-Type': 'application/json' });
802
+ res.end(JSON.stringify(history));
803
+ // ---- Exec: submit task ----
804
+ }
805
+ else if (url === '/api/exec' && req.method === 'POST') {
806
+ const body = await readBody(req);
807
+ try {
808
+ const { prompt, projectPath, pipeline, workerOnly, model } = JSON.parse(body);
809
+ if (!prompt?.trim()) {
810
+ res.writeHead(400, { 'Content-Type': 'application/json' });
811
+ res.end(JSON.stringify({ error: 'Missing prompt' }));
812
+ return;
813
+ }
814
+ const taskId = `exec-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
815
+ const resolvedPath = projectPath ?? process.cwd();
816
+ const entry = {
817
+ taskId,
818
+ status: 'queued',
819
+ createdAt: Date.now(),
820
+ };
821
+ execTasks.set(taskId, entry);
822
+ res.writeHead(202, { 'Content-Type': 'application/json' });
823
+ res.end(JSON.stringify({ taskId, status: 'queued' }));
824
+ // Run pipeline asynchronously
825
+ (async () => {
826
+ try {
827
+ initLocale('en');
828
+ entry.status = 'running';
829
+ // Determine stages
830
+ let stages;
831
+ if (workerOnly) {
832
+ stages = ['worker'];
833
+ }
834
+ else if (pipeline) {
835
+ stages = ['worker', 'reviewer', 'tester', 'documenter'];
836
+ }
837
+ else {
838
+ stages = ['worker', 'reviewer'];
839
+ }
840
+ // Build role config
841
+ const roles = {};
842
+ if (model) {
843
+ roles.worker = { enabled: true, model, timeoutMs: 0 };
844
+ }
845
+ const task = {
846
+ id: taskId,
847
+ source: 'local',
848
+ title: prompt,
849
+ description: prompt,
850
+ priority: 3,
851
+ projectPath: resolvedPath,
852
+ createdAt: Date.now(),
853
+ };
854
+ const pipelineInstance = new PairPipeline({
855
+ stages,
856
+ maxIterations: 3,
857
+ roles: Object.keys(roles).length > 0 ? roles : undefined,
858
+ });
859
+ pipelineInstance.on('stage:start', ({ stage }) => {
860
+ entry.currentStage = stage;
861
+ });
862
+ const result = await pipelineInstance.run(task, resolvedPath);
863
+ entry.status = 'completed';
864
+ entry.result = {
865
+ success: result.success,
866
+ summary: result.workerResult?.summary,
867
+ finalStatus: result.finalStatus,
868
+ };
869
+ }
870
+ catch (err) {
871
+ entry.status = 'failed';
872
+ entry.error = err instanceof Error ? err.message : String(err);
873
+ }
874
+ finally {
875
+ cleanupExecTask(taskId);
876
+ }
877
+ })();
878
+ }
879
+ catch {
880
+ res.writeHead(400, { 'Content-Type': 'application/json' });
881
+ res.end(JSON.stringify({ error: 'Invalid JSON' }));
882
+ }
883
+ // ---- Exec: task status ----
884
+ }
885
+ else if (url.startsWith('/api/exec/') && req.method === 'GET') {
886
+ const taskId = url.replace('/api/exec/', '');
887
+ const entry = execTasks.get(taskId);
888
+ if (!entry) {
889
+ res.writeHead(404, { 'Content-Type': 'application/json' });
890
+ res.end(JSON.stringify({ error: 'Task not found' }));
891
+ }
892
+ else {
893
+ res.writeHead(200, { 'Content-Type': 'application/json' });
894
+ res.end(JSON.stringify({
895
+ taskId: entry.taskId,
896
+ status: entry.status,
897
+ currentStage: entry.currentStage,
898
+ result: entry.result,
899
+ error: entry.error,
900
+ }));
901
+ }
902
+ }
903
+ else {
904
+ res.writeHead(404);
905
+ res.end('Not Found');
906
+ }
907
+ });
908
+ server.on('error', (err) => {
909
+ if (err.code === 'EADDRINUSE') {
910
+ console.warn(`Port ${port} is already in use, skipping web server...`);
911
+ server = null;
912
+ resolve();
913
+ }
914
+ else {
915
+ reject(err);
916
+ }
917
+ });
918
+ server.listen(port, '0.0.0.0', () => {
919
+ const tailscaleIP = '100.95.200.28'; // Current Tailscale IP
920
+ console.log(`Web interface running at:`);
921
+ console.log(` - http://127.0.0.1:${port} (localhost)`);
922
+ console.log(` - http://${tailscaleIP}:${port} (Tailscale)`);
923
+ startGitStatusPoller(() => Array.from(pinnedProjects));
924
+ startHealthChecker(30000);
925
+ resolve();
926
+ });
927
+ });
928
+ }
929
+ /**
930
+ * Stop the web server
931
+ */
932
+ export async function stopWebServer() {
933
+ if (server) {
934
+ server.close();
935
+ server = null;
936
+ }
937
+ }
938
+ //# sourceMappingURL=web.js.map