@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,998 @@
1
+ #!/usr/bin/env tsx
2
+ // OpenSwarm - Rich TUI Chat Interface
3
+ // Claude Code style tabbed interface with real-time updates
4
+ import blessed from 'blessed';
5
+ import { homedir } from 'node:os';
6
+ import { resolve } from 'node:path';
7
+ import { readFile, writeFile, mkdir } from 'node:fs/promises';
8
+ import { existsSync } from 'node:fs';
9
+ import { loadConfig } from '../core/config.js';
10
+ import { getDefaultAdapterName } from '../adapters/index.js';
11
+ import { getDefaultChatModel, resolveChatModel, runChatCompletion, shortenChatModel } from './chatBackend.js';
12
+ // Constants
13
+ const CHAT_DIR = resolve(homedir(), '.openswarm', 'chat');
14
+ // Render guard: blessed는 동시 render() 호출 시 화면이 검은색으로 깨질 수 있음
15
+ let renderScheduled = false;
16
+ let screenRef = null;
17
+ function safeRender() {
18
+ if (renderScheduled || !screenRef)
19
+ return;
20
+ renderScheduled = true;
21
+ process.nextTick(() => {
22
+ renderScheduled = false;
23
+ try {
24
+ screenRef.render();
25
+ }
26
+ catch {
27
+ // render 실패 시 복구 시도
28
+ try {
29
+ screenRef.alloc();
30
+ screenRef.render();
31
+ }
32
+ catch {
33
+ // 무시 — 다음 사이클에서 복구
34
+ }
35
+ }
36
+ });
37
+ }
38
+ // Session Management
39
+ async function ensureChatDir() {
40
+ await mkdir(CHAT_DIR, { recursive: true });
41
+ }
42
+ async function saveSession(session) {
43
+ await ensureChatDir();
44
+ session.updatedAt = new Date().toISOString();
45
+ const path = resolve(CHAT_DIR, `${session.id}.json`);
46
+ await writeFile(path, JSON.stringify(session, null, 2));
47
+ }
48
+ async function loadSession(id) {
49
+ const path = resolve(CHAT_DIR, `${id}.json`);
50
+ if (!existsSync(path))
51
+ return null;
52
+ const data = JSON.parse(await readFile(path, 'utf-8'));
53
+ const provider = data.provider ?? inferProvider(undefined, data.model);
54
+ return {
55
+ ...data,
56
+ provider,
57
+ model: data.model ?? getDefaultChatModel(provider),
58
+ totalCost: data.totalCost ?? 0,
59
+ totalTokens: data.totalTokens ?? 0,
60
+ };
61
+ }
62
+ function generateSessionId() {
63
+ const now = new Date();
64
+ const pad = (n) => String(n).padStart(2, '0');
65
+ return `${now.getFullYear()}${pad(now.getMonth() + 1)}${pad(now.getDate())}-${pad(now.getHours())}${pad(now.getMinutes())}`;
66
+ }
67
+ function inferProvider(provider, model) {
68
+ if (provider)
69
+ return provider;
70
+ if (model?.startsWith('gpt-') || model?.includes('codex'))
71
+ return 'codex';
72
+ return loadDefaultProvider();
73
+ }
74
+ function loadDefaultProvider() {
75
+ try {
76
+ return loadConfig().adapter ?? getDefaultAdapterName();
77
+ }
78
+ catch {
79
+ return getDefaultAdapterName();
80
+ }
81
+ }
82
+ // Shared chat backend
83
+ async function callChatModel(prompt, provider, model, sessionId, onStream) {
84
+ const result = await runChatCompletion({
85
+ prompt,
86
+ provider,
87
+ model,
88
+ sessionId: provider === 'claude' ? sessionId : undefined,
89
+ timeoutMs: 180000,
90
+ onText: onStream,
91
+ });
92
+ return {
93
+ response: result.response,
94
+ sessionId: result.sessionId ?? '',
95
+ cost: result.cost ?? 0,
96
+ tokens: result.tokens ?? 0,
97
+ };
98
+ }
99
+ // Warhammer 40k Loading Messages
100
+ const LOADING_MESSAGES = [
101
+ 'Initializing cogitator arrays',
102
+ 'Querying data-vault archives',
103
+ 'Accessing servitor protocols',
104
+ 'Compiling neural responses',
105
+ 'Interfacing with the Noosphere',
106
+ 'Scanning data-streams',
107
+ 'Calibrating logic engines',
108
+ 'Decoding transmission packets',
109
+ 'Loading archive databases',
110
+ 'Synchronizing machine protocols',
111
+ 'Analyzing pattern matrices',
112
+ 'Establishing neural link',
113
+ 'Processing data-core output',
114
+ 'Running diagnostics sequence',
115
+ 'Activating response circuits',
116
+ ];
117
+ const SPINNER_FRAMES = ['⣾', '⣽', '⣻', '⢿', '⡿', '⣟', '⣯', '⣷'];
118
+ // UI Components - Claude Code Style
119
+ function createUI() {
120
+ const screen = blessed.screen({
121
+ smartCSR: true,
122
+ title: 'OpenSwarm Chat',
123
+ fullUnicode: true,
124
+ terminal: 'xterm-256color',
125
+ forceUnicode: true,
126
+ warnings: false, // Suppress warnings that can corrupt display
127
+ dockBorders: true, // Better border handling in tmux
128
+ fastCSR: true, // Faster rendering for streaming
129
+ });
130
+ const colors = {
131
+ bg: '#1a1a1a',
132
+ statusBg: '#2d3748',
133
+ statusFg: '#e2e8f0',
134
+ tabActiveBg: '#4a5568',
135
+ tabActiveFg: '#f7fafc',
136
+ tabInactiveBg: '#2d3748',
137
+ tabInactiveFg: '#a0aec0',
138
+ border: '#4a5568',
139
+ borderActive: '#667eea',
140
+ inputBorder: '#48bb78',
141
+ scrollbar: '#4a5568',
142
+ userMessage: '#60a5fa',
143
+ assistantMessage: '#34d399',
144
+ dimText: '#718096',
145
+ };
146
+ const statusBar = blessed.box({
147
+ top: 0,
148
+ left: 0,
149
+ width: '100%',
150
+ height: 1,
151
+ tags: true,
152
+ style: {
153
+ fg: colors.statusFg,
154
+ bg: colors.statusBg,
155
+ },
156
+ });
157
+ const tabBar = blessed.box({
158
+ top: 1,
159
+ left: 0,
160
+ width: '100%',
161
+ height: 1,
162
+ tags: true,
163
+ style: {
164
+ fg: colors.tabInactiveFg,
165
+ bg: colors.tabInactiveBg,
166
+ },
167
+ });
168
+ // Chat tab content - clean borders (adjusted for taller input box)
169
+ const chatLog = blessed.log({
170
+ top: 2,
171
+ left: 0,
172
+ width: '100%',
173
+ height: '100%-9', // Increased from -7 to -9 for 5-line input box
174
+ scrollable: true,
175
+ alwaysScroll: true,
176
+ mouse: true,
177
+ scrollbar: {
178
+ ch: '│',
179
+ track: {
180
+ bg: '#1a1a1a',
181
+ },
182
+ style: {
183
+ fg: colors.scrollbar,
184
+ },
185
+ },
186
+ tags: true,
187
+ border: { type: 'line' },
188
+ style: {
189
+ fg: '#e2e8f0',
190
+ bg: '#1a1a1a',
191
+ border: {
192
+ fg: colors.border,
193
+ },
194
+ },
195
+ });
196
+ const projectsBox = blessed.box({
197
+ top: 2,
198
+ left: 0,
199
+ width: '100%',
200
+ height: '100%-9', // Adjusted for taller input box
201
+ content: '{center}{#718096-fg}Loading projects...{/}{/center}',
202
+ tags: true,
203
+ scrollable: true,
204
+ mouse: true,
205
+ scrollbar: {
206
+ ch: '│',
207
+ style: { fg: colors.scrollbar },
208
+ },
209
+ border: { type: 'line' },
210
+ style: {
211
+ fg: '#e2e8f0',
212
+ bg: '#1a1a1a',
213
+ border: { fg: colors.border },
214
+ },
215
+ hidden: true,
216
+ });
217
+ const tasksBox = blessed.box({
218
+ top: 2,
219
+ left: 0,
220
+ width: '100%',
221
+ height: '100%-9', // Adjusted for taller input box
222
+ content: '{center}{#718096-fg}Loading tasks...{/}{/center}',
223
+ tags: true,
224
+ scrollable: true,
225
+ mouse: true,
226
+ scrollbar: {
227
+ ch: '│',
228
+ style: { fg: colors.scrollbar },
229
+ },
230
+ border: { type: 'line' },
231
+ style: {
232
+ fg: '#e2e8f0',
233
+ bg: '#1a1a1a',
234
+ border: { fg: colors.border },
235
+ },
236
+ hidden: true,
237
+ });
238
+ const stuckBox = blessed.box({
239
+ top: 2,
240
+ left: 0,
241
+ width: '100%',
242
+ height: '100%-9',
243
+ content: '{center}{#718096-fg}Loading stuck issues...{/}{/center}',
244
+ tags: true,
245
+ scrollable: true,
246
+ alwaysScroll: true,
247
+ mouse: true,
248
+ keys: true,
249
+ vi: true,
250
+ scrollbar: {
251
+ ch: '█',
252
+ style: { fg: colors.scrollbar },
253
+ },
254
+ style: {
255
+ border: { fg: colors.border },
256
+ },
257
+ hidden: true,
258
+ });
259
+ const logsBox = blessed.log({
260
+ top: 2,
261
+ left: 0,
262
+ width: '100%',
263
+ height: '100%-9', // Adjusted for taller input box
264
+ scrollable: true,
265
+ alwaysScroll: true,
266
+ mouse: true,
267
+ scrollbar: {
268
+ ch: '│',
269
+ style: { fg: colors.scrollbar },
270
+ },
271
+ tags: true,
272
+ border: { type: 'line' },
273
+ style: {
274
+ fg: '#e2e8f0',
275
+ bg: '#1a1a1a',
276
+ border: { fg: colors.border },
277
+ },
278
+ hidden: true,
279
+ });
280
+ // Input box - textarea for multiline + Korean support
281
+ const inputBox = blessed.textarea({
282
+ bottom: 1,
283
+ left: 0,
284
+ width: '100%',
285
+ height: 5, // Increased height for multiline
286
+ inputOnFocus: true,
287
+ border: { type: 'line' },
288
+ label: ' {#718096-fg}Message (Shift+Enter: newline, Enter: send){/} ',
289
+ tags: true,
290
+ keys: true, // Enable key handling
291
+ mouse: true,
292
+ scrollable: true,
293
+ alwaysScroll: false,
294
+ style: {
295
+ fg: '#f7fafc',
296
+ bg: '#1a1a1a',
297
+ border: { fg: colors.border },
298
+ focus: {
299
+ border: { fg: colors.borderActive },
300
+ bg: '#0d1117',
301
+ },
302
+ },
303
+ });
304
+ const helpBar = blessed.box({
305
+ bottom: 0,
306
+ left: 0,
307
+ width: '100%',
308
+ height: 1,
309
+ content: ' {#718096-fg}Tab{/} Switch {#718096-fg}Enter{/} Send {#718096-fg}Shift+Enter{/} Newline {#718096-fg}Esc{/} Exit Input {#718096-fg}i{/} Focus Input {#718096-fg}Ctrl+C{/} Exit {#718096-fg}/help{/} Cmds',
310
+ tags: true,
311
+ style: {
312
+ fg: '#a0aec0',
313
+ bg: colors.statusBg,
314
+ },
315
+ });
316
+ screen.append(statusBar);
317
+ screen.append(tabBar);
318
+ screen.append(chatLog);
319
+ screen.append(projectsBox);
320
+ screen.append(tasksBox);
321
+ screen.append(stuckBox);
322
+ screen.append(logsBox);
323
+ screen.append(inputBox);
324
+ screen.append(helpBar);
325
+ return {
326
+ screen,
327
+ statusBar,
328
+ tabBar,
329
+ chatLog,
330
+ projectsBox,
331
+ tasksBox,
332
+ stuckBox,
333
+ logsBox,
334
+ inputBox,
335
+ helpBar,
336
+ };
337
+ }
338
+ // Tab Management
339
+ function updateTabBar(ui, currentTab) {
340
+ const tabs = [
341
+ { key: '1', name: 'Chat', icon: '💬' },
342
+ { key: '2', name: 'Projects', icon: '📁' },
343
+ { key: '3', name: 'Tasks', icon: '✓' },
344
+ { key: '4', name: 'Stuck', icon: '⚠' },
345
+ { key: '5', name: 'Logs', icon: '📝' },
346
+ ];
347
+ const content = tabs.map((tab, idx) => {
348
+ if (idx === currentTab) {
349
+ // Active tab - highlighted
350
+ return `{#4a5568-bg}{#f7fafc-fg}{bold} ${tab.icon} ${tab.name} {/bold}{/}{/}`;
351
+ }
352
+ // Inactive tab - dimmed
353
+ return `{#2d3748-bg}{#a0aec0-fg} ${tab.icon} ${tab.name} {/}{/}`;
354
+ }).join(' ');
355
+ ui.tabBar.setContent(' ' + content);
356
+ }
357
+ function switchTab(state, ui, tabIndex) {
358
+ state.currentTab = tabIndex;
359
+ ui.chatLog.hide();
360
+ ui.projectsBox.hide();
361
+ ui.tasksBox.hide();
362
+ ui.stuckBox.hide();
363
+ ui.logsBox.hide();
364
+ switch (tabIndex) {
365
+ case 0:
366
+ ui.chatLog.show();
367
+ break;
368
+ case 1:
369
+ ui.projectsBox.show();
370
+ loadProjectsData(ui.projectsBox);
371
+ break;
372
+ case 2:
373
+ ui.tasksBox.show();
374
+ loadTasksData(ui.tasksBox);
375
+ break;
376
+ case 3:
377
+ ui.stuckBox.show();
378
+ loadStuckData(ui.stuckBox);
379
+ break;
380
+ case 4:
381
+ ui.logsBox.show();
382
+ break;
383
+ }
384
+ updateTabBar(ui, tabIndex);
385
+ safeRender();
386
+ }
387
+ // Data Loaders
388
+ async function loadProjectsData(box) {
389
+ try {
390
+ const response = await fetch('http://127.0.0.1:3847/api/projects');
391
+ const projects = await response.json();
392
+ if (projects.length === 0) {
393
+ box.setContent('\n{center}{#718096-fg}No projects tracked{/}{/center}');
394
+ return;
395
+ }
396
+ const lines = [
397
+ '',
398
+ ` {#a0aec0-fg}${projects.length} project${projects.length > 1 ? 's' : ''} tracked{/}`,
399
+ '',
400
+ ];
401
+ for (const p of projects) {
402
+ const status = p.enabled ? '{#34d399-fg}●{/}' : '{#718096-fg}○{/}';
403
+ const running = p.running.length > 0 ? `{#60a5fa-fg}${p.running.length} running{/}` : '';
404
+ const queued = p.queued.length > 0 ? `{#f59e0b-fg}${p.queued.length} queued{/}` : '';
405
+ const tasks = [running, queued].filter(Boolean).join(' · ');
406
+ lines.push(` ${status} {bold}${p.name}{/bold}`);
407
+ if (tasks) {
408
+ lines.push(` ${tasks}`);
409
+ }
410
+ lines.push(` {#718096-fg}${p.path}{/}`);
411
+ lines.push('');
412
+ }
413
+ box.setContent(lines.join('\n'));
414
+ }
415
+ catch (err) {
416
+ box.setContent(`\n{center}{#ef4444-fg}Failed to load projects{/}\n{#718096-fg}${err}{/}{/center}`);
417
+ }
418
+ }
419
+ async function loadTasksData(box) {
420
+ try {
421
+ const response = await fetch('http://127.0.0.1:3847/api/pipeline');
422
+ const { stages } = await response.json();
423
+ if (stages.length === 0) {
424
+ box.setContent('\n{center}{#718096-fg}No pipeline events{/}{/center}');
425
+ return;
426
+ }
427
+ // Build task info map and extract stage events
428
+ const taskInfo = new Map();
429
+ const allStageEvents = [];
430
+ for (const event of stages) {
431
+ if (event.type === 'task:started' && event.data.taskId) {
432
+ taskInfo.set(event.data.taskId, { title: event.data.title, issueIdentifier: event.data.issueIdentifier });
433
+ }
434
+ else if (event.type === 'pipeline:stage' && event.data.taskId && event.data.stage) {
435
+ allStageEvents.push({
436
+ taskId: event.data.taskId,
437
+ stage: event.data.stage,
438
+ status: event.data.status || '',
439
+ model: event.data.model,
440
+ inputTokens: event.data.inputTokens,
441
+ outputTokens: event.data.outputTokens,
442
+ costUsd: event.data.costUsd,
443
+ });
444
+ }
445
+ }
446
+ if (allStageEvents.length === 0) {
447
+ box.setContent('\n{center}{#718096-fg}No active pipeline stages{/}{/center}');
448
+ return;
449
+ }
450
+ // Render pipeline table
451
+ const recentStages = allStageEvents.slice(-15).reverse();
452
+ const lines = [
453
+ '',
454
+ ` {#34d399-fg}{bold}Pipeline Events{/bold} {#718096-fg}(${recentStages.length} recent){/}{/}`,
455
+ '',
456
+ ` {#718096-fg}${'TASK'.padEnd(12)} ${'STAGE'.padEnd(10)} ${'MODEL'.padEnd(12)} ${'TOKENS'.padEnd(15)} STATUS{/}`,
457
+ ` {#444444-fg}${'─'.repeat(70)}{/}`,
458
+ ];
459
+ for (const ev of recentStages) {
460
+ const info = taskInfo.get(ev.taskId);
461
+ const task = (info?.issueIdentifier || ev.taskId.slice(0, 8)).padEnd(12).slice(0, 12);
462
+ const stage = ev.stage.padEnd(10).slice(0, 10);
463
+ const statusMap = {
464
+ start: ['◐', '#f59e0b'],
465
+ complete: ['●', '#34d399'],
466
+ fail: ['✗', '#ef4444'],
467
+ };
468
+ const [icon, color] = statusMap[ev.status] || ['○', '#718096'];
469
+ let model = '';
470
+ if (ev.model?.includes('sonnet-4-5'))
471
+ model = 'sonnet-4.5';
472
+ else if (ev.model?.includes('haiku-4-5'))
473
+ model = 'haiku-4.5';
474
+ else if (ev.model?.includes('opus-4'))
475
+ model = 'opus-4';
476
+ else if (ev.model)
477
+ model = ev.model.split('-').pop() || '';
478
+ model = model.padEnd(12).slice(0, 12);
479
+ let tokens = '';
480
+ if (ev.inputTokens || ev.outputTokens) {
481
+ const inK = ev.inputTokens ? Math.round(ev.inputTokens / 1000) : 0;
482
+ const outK = ev.outputTokens ? Math.round(ev.outputTokens / 1000) : 0;
483
+ tokens = `${inK}k/${outK}k`;
484
+ if (ev.costUsd != null)
485
+ tokens += ` $${ev.costUsd.toFixed(2)}`;
486
+ }
487
+ tokens = tokens.padEnd(15).slice(0, 15);
488
+ lines.push(` {#34d399-fg}${task}{/} {#718096-fg}${stage}{/} {#34d399-fg}${model}{/} {#718096-fg}${tokens}{/} {${color}-fg}${icon} ${ev.status}{/}`);
489
+ }
490
+ box.setContent(lines.join('\n'));
491
+ }
492
+ catch (err) {
493
+ box.setContent(`\n{center}{#ef4444-fg}Failed to load pipeline{/}\n{#718096-fg}${err}{/}{/center}`);
494
+ }
495
+ }
496
+ async function loadStuckData(box) {
497
+ try {
498
+ const response = await fetch('http://127.0.0.1:3847/api/stuck-issues');
499
+ const { stuckIssues, failedIssues } = await response.json();
500
+ const totalStuck = stuckIssues.length;
501
+ const totalFailed = failedIssues.length;
502
+ const total = totalStuck + totalFailed;
503
+ if (total === 0) {
504
+ box.setContent('\n{center}{#34d399-fg}✓ All issues healthy{/}{/center}');
505
+ return;
506
+ }
507
+ const lines = [
508
+ '',
509
+ ` {#ef4444-fg}⚠ ${total} issue${total > 1 ? 's' : ''} need attention{/}`,
510
+ '',
511
+ ];
512
+ // Stuck issues
513
+ if (totalStuck > 0) {
514
+ lines.push(` {#f59e0b-fg}{bold}⏱ STUCK (${totalStuck}){/bold}{/}`);
515
+ lines.push('');
516
+ for (const issue of stuckIssues) {
517
+ const priorityIcon = issue.priority === 1 ? '{#ef4444-fg}🔴{/}' : issue.priority === 2 ? '{#f59e0b-fg}🟡{/}' : '{#718096-fg}⚪{/}';
518
+ lines.push(` ${priorityIcon} {bold}${issue.identifier}{/bold}`);
519
+ lines.push(` ${issue.title.substring(0, 60)}${issue.title.length > 60 ? '...' : ''}`);
520
+ lines.push(` {#f59e0b-fg}${issue.reason}{/}`);
521
+ if (issue.project?.name) {
522
+ lines.push(` {#718096-fg}📁 ${issue.project.name}{/}`);
523
+ }
524
+ lines.push('');
525
+ }
526
+ }
527
+ // Failed issues
528
+ if (totalFailed > 0) {
529
+ lines.push(` {#ef4444-fg}{bold}✖ FAILED (${totalFailed}){/bold}{/}`);
530
+ lines.push('');
531
+ for (const issue of failedIssues) {
532
+ const priorityIcon = issue.priority === 1 ? '{#ef4444-fg}🔴{/}' : issue.priority === 2 ? '{#f59e0b-fg}🟡{/}' : '{#718096-fg}⚪{/}';
533
+ lines.push(` ${priorityIcon} {bold}${issue.identifier}{/bold}`);
534
+ lines.push(` ${issue.title.substring(0, 60)}${issue.title.length > 60 ? '...' : ''}`);
535
+ lines.push(` {#ef4444-fg}${issue.reason}{/}`);
536
+ if (issue.project?.name) {
537
+ lines.push(` {#718096-fg}📁 ${issue.project.name}{/}`);
538
+ }
539
+ lines.push('');
540
+ }
541
+ }
542
+ box.setContent(lines.join('\n'));
543
+ }
544
+ catch (err) {
545
+ box.setContent(`\n{center}{#ef4444-fg}Failed to load stuck issues{/}\n{#718096-fg}${err}{/}{/center}`);
546
+ }
547
+ }
548
+ // Loading Spinner (inline in chat)
549
+ function startSpinner(ui) {
550
+ let frameIndex = 0;
551
+ const loadingMessage = LOADING_MESSAGES[Math.floor(Math.random() * LOADING_MESSAGES.length)];
552
+ const lines = ui.chatLog.getLines();
553
+ const lineIndex = lines.length;
554
+ const interval = setInterval(() => {
555
+ const spinner = SPINNER_FRAMES[frameIndex % SPINNER_FRAMES.length];
556
+ const content = ` {#667eea-fg}${spinner}{/} {#718096-fg}${loadingMessage}...{/}`;
557
+ ui.chatLog.setLine(lineIndex, content);
558
+ ui.chatLog.setScrollPerc(100);
559
+ safeRender();
560
+ frameIndex++;
561
+ }, 80);
562
+ return { interval, lineIndex };
563
+ }
564
+ function stopSpinner(ui, spinnerData) {
565
+ clearInterval(spinnerData.interval);
566
+ ui.chatLog.deleteLine(spinnerData.lineIndex);
567
+ safeRender();
568
+ }
569
+ // Chat Logic
570
+ async function sendMessage(state, ui, message) {
571
+ if (!message.trim())
572
+ return;
573
+ ui.chatLog.log('');
574
+ ui.chatLog.log(`{#60a5fa-fg}{bold}▸ You{/bold}{/}`);
575
+ ui.chatLog.log(` ${message}`);
576
+ ui.chatLog.log('');
577
+ ui.chatLog.setScrollPerc(100);
578
+ safeRender();
579
+ state.session.messages.push({ role: 'user', content: message });
580
+ ui.chatLog.log(`{#34d399-fg}{bold}▸ Assistant{/bold}{/}`);
581
+ const assistantHeaderLine = ui.chatLog.getLines().length - 1;
582
+ let assistantContent = '';
583
+ let lastRenderTime = 0;
584
+ let spinnerStopped = false;
585
+ let contentStartLine = assistantHeaderLine + 1;
586
+ const spinnerData = startSpinner(ui);
587
+ try {
588
+ const result = await callChatModel(message, state.session.provider, state.session.model, state.session.claudeSessionId, (chunk, isThinking) => {
589
+ // Handle thinking notification (show/resume spinner)
590
+ if (isThinking) {
591
+ if (spinnerStopped) {
592
+ // Resume spinner for thinking phase
593
+ spinnerStopped = false;
594
+ const newSpinner = startSpinner(ui);
595
+ Object.assign(spinnerData, newSpinner);
596
+ }
597
+ return;
598
+ }
599
+ // Stop spinner on first text chunk
600
+ if (!spinnerStopped && chunk) {
601
+ stopSpinner(ui, spinnerData);
602
+ spinnerStopped = true;
603
+ }
604
+ if (!chunk)
605
+ return;
606
+ assistantContent += chunk;
607
+ // Throttle rendering for smoother streaming (30fps)
608
+ const now = Date.now();
609
+ if (now - lastRenderTime < 33)
610
+ return;
611
+ lastRenderTime = now;
612
+ // Clear previous content lines (안전한 역순 삭제)
613
+ const currentLines = ui.chatLog.getLines().length;
614
+ const deleteCount = Math.max(0, Math.min(currentLines - contentStartLine, currentLines));
615
+ for (let i = 0; i < deleteCount; i++) {
616
+ ui.chatLog.deleteLine(contentStartLine);
617
+ }
618
+ // Add updated content line by line with proper empty line handling
619
+ const contentLines = assistantContent.split('\n');
620
+ for (const line of contentLines) {
621
+ // Always add line, even if empty (preserves paragraph breaks)
622
+ ui.chatLog.log(line ? ` ${line}` : ' ');
623
+ }
624
+ ui.chatLog.setScrollPerc(100);
625
+ safeRender();
626
+ });
627
+ // Ensure spinner is stopped
628
+ if (!spinnerStopped) {
629
+ stopSpinner(ui, spinnerData);
630
+ spinnerStopped = true;
631
+ }
632
+ if (state.session.provider === 'claude' && result.sessionId) {
633
+ state.session.claudeSessionId = result.sessionId;
634
+ }
635
+ // Update session stats
636
+ state.session.totalCost += result.cost;
637
+ state.session.totalTokens += result.tokens;
638
+ // Finalize assistant message with cost
639
+ // Clear streaming content first (안전한 삭제)
640
+ const finalLines = ui.chatLog.getLines().length;
641
+ const finalDeleteCount = Math.max(0, Math.min(finalLines - contentStartLine, finalLines));
642
+ for (let i = 0; i < finalDeleteCount; i++) {
643
+ ui.chatLog.deleteLine(contentStartLine);
644
+ }
645
+ // Add final content line by line with proper empty line handling
646
+ const contentLines = result.response.split('\n');
647
+ for (const line of contentLines) {
648
+ // Always add line, even if empty (preserves paragraph breaks)
649
+ ui.chatLog.log(line ? ` ${line}` : ' ');
650
+ }
651
+ // Add cost info if available
652
+ if (result.cost > 0) {
653
+ ui.chatLog.log(` {#718096-fg}${result.tokens} tokens · $${result.cost.toFixed(4)}{/}`);
654
+ }
655
+ ui.chatLog.log('');
656
+ state.session.messages.push({
657
+ role: 'assistant',
658
+ content: result.response,
659
+ cost: result.cost,
660
+ });
661
+ await saveSession(state.session);
662
+ updateStatusBar(state, ui);
663
+ safeRender();
664
+ }
665
+ catch (err) {
666
+ if (!spinnerStopped) {
667
+ stopSpinner(ui, spinnerData);
668
+ }
669
+ const msg = err instanceof Error ? err.message : String(err);
670
+ ui.chatLog.log(`{#ef4444-fg}{bold}✗ Error{/bold}{/}`);
671
+ ui.chatLog.log(` ${msg}`);
672
+ ui.chatLog.log('');
673
+ state.session.messages.pop(); // Remove user message on failure
674
+ safeRender();
675
+ }
676
+ }
677
+ // Status Bar Update
678
+ function updateStatusBar(state, ui) {
679
+ const modelShort = shortenChatModel(state.session.model);
680
+ const cost = state.session.totalCost > 0 ? `$${state.session.totalCost.toFixed(4)}` : '$0.00';
681
+ const msgs = state.session.messages.length;
682
+ const status = [
683
+ '{bold}OpenSwarm{/bold}',
684
+ `{#718096-fg}│{/}`,
685
+ `{#a0aec0-fg}${state.session.id}{/}`,
686
+ `{#718096-fg}│{/}`,
687
+ `{#c084fc-fg}${state.session.provider}{/}`,
688
+ `{#718096-fg}│{/}`,
689
+ `{#60a5fa-fg}${modelShort}{/}`,
690
+ `{#718096-fg}│{/}`,
691
+ `{#a0aec0-fg}${msgs} messages{/}`,
692
+ `{#718096-fg}│{/}`,
693
+ `{#34d399-fg}${cost}{/}`,
694
+ ].join(' ');
695
+ ui.statusBar.setContent(' ' + status);
696
+ }
697
+ // Command Handler
698
+ async function handleCommand(cmd, state, ui) {
699
+ const [command, ...args] = cmd.slice(1).split(' ');
700
+ switch (command) {
701
+ case 'clear':
702
+ case 'c':
703
+ state.session.messages = [];
704
+ state.session.claudeSessionId = undefined;
705
+ state.session.totalCost = 0;
706
+ state.session.totalTokens = 0;
707
+ ui.chatLog.setContent('');
708
+ ui.chatLog.log('');
709
+ ui.chatLog.log('{#34d399-fg}✓ Conversation cleared{/}');
710
+ ui.chatLog.log('');
711
+ updateStatusBar(state, ui);
712
+ safeRender();
713
+ break;
714
+ case 'provider':
715
+ case 'p': {
716
+ const next = args[0];
717
+ ui.chatLog.log('');
718
+ if (!next) {
719
+ ui.chatLog.log(` {bold}Current provider:{/bold} {#c084fc-fg}${state.session.provider}{/}`);
720
+ ui.chatLog.log(' {#718096-fg}Available providers:{/}');
721
+ ui.chatLog.log(' {#a0aec0-fg}claude{/}');
722
+ ui.chatLog.log(' {#a0aec0-fg}codex{/}');
723
+ }
724
+ else if (next !== 'claude' && next !== 'codex') {
725
+ ui.chatLog.log(` {#ef4444-fg}Unknown provider: ${next}{/}`);
726
+ }
727
+ else {
728
+ state.session.provider = next;
729
+ state.session.model = getDefaultChatModel(next);
730
+ state.session.claudeSessionId = undefined;
731
+ ui.chatLog.log(` {#34d399-fg}✓ Provider changed to {bold}${next}{/bold}{/}`);
732
+ ui.chatLog.log(` {#34d399-fg}✓ Model changed to {bold}${state.session.model}{/bold}{/}`);
733
+ updateStatusBar(state, ui);
734
+ }
735
+ ui.chatLog.log('');
736
+ safeRender();
737
+ break;
738
+ }
739
+ case 'model':
740
+ case 'm': {
741
+ const newModel = args[0];
742
+ ui.chatLog.log('');
743
+ if (!newModel) {
744
+ ui.chatLog.log(` {bold}Current provider:{/bold} {#c084fc-fg}${state.session.provider}{/}`);
745
+ ui.chatLog.log(` {bold}Current model:{/bold} {#60a5fa-fg}${shortenChatModel(state.session.model)}{/}`);
746
+ ui.chatLog.log('');
747
+ ui.chatLog.log(' {#718096-fg}Available models:{/}');
748
+ if (state.session.provider === 'claude') {
749
+ ui.chatLog.log(' {#a0aec0-fg}sonnet{/} {#718096-fg}→{/} claude-sonnet-4-5');
750
+ ui.chatLog.log(' {#a0aec0-fg}haiku{/} {#718096-fg}→{/} claude-haiku-4-5');
751
+ ui.chatLog.log(' {#a0aec0-fg}opus{/} {#718096-fg}→{/} claude-opus-4-6');
752
+ }
753
+ else {
754
+ ui.chatLog.log(' {#a0aec0-fg}codex{/} {#718096-fg}→{/} gpt-5-codex');
755
+ }
756
+ }
757
+ else {
758
+ state.session.model = resolveChatModel(newModel, state.session.provider);
759
+ state.session.claudeSessionId = undefined;
760
+ const shortName = shortenChatModel(state.session.model);
761
+ ui.chatLog.log(` {#34d399-fg}✓ Model changed to {bold}${shortName}{/bold}{/}`);
762
+ updateStatusBar(state, ui);
763
+ }
764
+ ui.chatLog.log('');
765
+ safeRender();
766
+ break;
767
+ }
768
+ case 'save': {
769
+ const name = args[0] || state.session.id;
770
+ state.session.id = name;
771
+ await saveSession(state.session);
772
+ ui.chatLog.log('');
773
+ ui.chatLog.log(` {#34d399-fg}✓ Session saved: {bold}${name}{/bold}{/}`);
774
+ ui.chatLog.log('');
775
+ updateStatusBar(state, ui);
776
+ safeRender();
777
+ break;
778
+ }
779
+ case 'help':
780
+ case 'h':
781
+ case '?':
782
+ ui.chatLog.log('');
783
+ ui.chatLog.log(' {bold}Available Commands{/bold}');
784
+ ui.chatLog.log('');
785
+ ui.chatLog.log(' {#60a5fa-fg}/clear{/} Clear conversation');
786
+ ui.chatLog.log(' {#60a5fa-fg}/provider{/} [id] Change provider {#718096-fg}(claude/codex){/}');
787
+ ui.chatLog.log(' {#60a5fa-fg}/model{/} [name] Change model {#718096-fg}(sonnet/haiku/opus){/}');
788
+ ui.chatLog.log(' {#60a5fa-fg}/save{/} [name] Save session');
789
+ ui.chatLog.log(' {#60a5fa-fg}/help{/} Show this help');
790
+ ui.chatLog.log('');
791
+ ui.chatLog.log(' {bold}Navigation{/bold}');
792
+ ui.chatLog.log('');
793
+ ui.chatLog.log(' {#718096-fg}1-4{/} Switch tabs directly');
794
+ ui.chatLog.log(' {#718096-fg}Tab/Shift+Tab{/} Cycle through tabs');
795
+ ui.chatLog.log(' {#718096-fg}Esc{/} Exit input mode (blur)');
796
+ ui.chatLog.log(' {#718096-fg}i / Enter{/} Focus input (from chat)');
797
+ ui.chatLog.log(' {#718096-fg}Ctrl+C{/} Exit (double press to confirm)');
798
+ ui.chatLog.log('');
799
+ safeRender();
800
+ break;
801
+ default:
802
+ ui.chatLog.log('');
803
+ ui.chatLog.log(` {#ef4444-fg}Unknown command: /{bold}${command}{/bold}{/}`);
804
+ ui.chatLog.log(` {#718096-fg}Type {/}{#60a5fa-fg}/help{/}{#718096-fg} for available commands{/}`);
805
+ ui.chatLog.log('');
806
+ safeRender();
807
+ }
808
+ return false;
809
+ }
810
+ // Main
811
+ export async function main() {
812
+ const defaultProvider = loadDefaultProvider();
813
+ const loadArg = process.argv[2];
814
+ let session;
815
+ if (loadArg && loadArg !== '--' && !loadArg.startsWith('-')) {
816
+ const loaded = await loadSession(loadArg);
817
+ if (loaded) {
818
+ session = loaded;
819
+ }
820
+ else {
821
+ session = {
822
+ id: loadArg,
823
+ provider: defaultProvider,
824
+ model: getDefaultChatModel(defaultProvider),
825
+ messages: [],
826
+ totalCost: 0,
827
+ totalTokens: 0,
828
+ createdAt: new Date().toISOString(),
829
+ updatedAt: new Date().toISOString(),
830
+ };
831
+ }
832
+ }
833
+ else {
834
+ session = {
835
+ id: generateSessionId(),
836
+ provider: defaultProvider,
837
+ model: getDefaultChatModel(defaultProvider),
838
+ messages: [],
839
+ totalCost: 0,
840
+ totalTokens: 0,
841
+ createdAt: new Date().toISOString(),
842
+ updatedAt: new Date().toISOString(),
843
+ };
844
+ }
845
+ const state = {
846
+ session,
847
+ currentTab: 0,
848
+ inputMode: 'normal',
849
+ multilineBuffer: [],
850
+ showBinary: false,
851
+ diagnostics: {
852
+ lastResponseTime: 0,
853
+ avgTokensPerSec: 0,
854
+ totalRequests: 0,
855
+ },
856
+ };
857
+ const ui = createUI();
858
+ screenRef = ui.screen; // safeRender용 참조 설정
859
+ updateStatusBar(state, ui);
860
+ updateTabBar(ui, state.currentTab);
861
+ // Restore chat history - Claude Code style with proper line breaks
862
+ for (const msg of session.messages) {
863
+ ui.chatLog.log('');
864
+ if (msg.role === 'user') {
865
+ ui.chatLog.log(`{#60a5fa-fg}{bold}▸ You{/bold}{/}`);
866
+ // Split multiline user messages
867
+ const userLines = msg.content.split('\n');
868
+ for (const line of userLines) {
869
+ ui.chatLog.log(line ? ` ${line}` : ' ');
870
+ }
871
+ }
872
+ else {
873
+ ui.chatLog.log(`{#34d399-fg}{bold}▸ Assistant{/bold}{/}`);
874
+ // Split multiline assistant messages properly
875
+ const assistantLines = msg.content.split('\n');
876
+ for (const line of assistantLines) {
877
+ ui.chatLog.log(line ? ` ${line}` : ' ');
878
+ }
879
+ if (msg.cost) {
880
+ ui.chatLog.log(` {#718096-fg}$${msg.cost.toFixed(4)}{/}`);
881
+ }
882
+ }
883
+ }
884
+ if (session.messages.length > 0) {
885
+ ui.chatLog.log('');
886
+ }
887
+ // Key bindings
888
+ ui.screen.key(['1'], () => switchTab(state, ui, 0));
889
+ ui.screen.key(['2'], () => switchTab(state, ui, 1));
890
+ ui.screen.key(['3'], () => switchTab(state, ui, 2));
891
+ ui.screen.key(['4'], () => switchTab(state, ui, 3));
892
+ ui.screen.key(['5'], () => switchTab(state, ui, 4));
893
+ ui.screen.key(['tab'], () => {
894
+ const next = (state.currentTab + 1) % 5;
895
+ switchTab(state, ui, next);
896
+ });
897
+ ui.screen.key(['S-tab'], () => {
898
+ const prev = (state.currentTab - 1 + 5) % 5;
899
+ switchTab(state, ui, prev);
900
+ });
901
+ // Ctrl+C: Clear input or exit (Claude Code style)
902
+ let ctrlCPressed = false;
903
+ ui.screen.key(['C-c'], async () => {
904
+ const currentValue = ui.inputBox.getValue();
905
+ if (currentValue && currentValue.trim()) {
906
+ // If input has text, just clear it
907
+ ui.inputBox.clearValue();
908
+ ui.inputBox.focus();
909
+ safeRender();
910
+ ctrlCPressed = false;
911
+ }
912
+ else {
913
+ // If input is empty, exit with double Ctrl+C
914
+ if (ctrlCPressed) {
915
+ await saveSession(state.session);
916
+ process.exit(0);
917
+ }
918
+ else {
919
+ ctrlCPressed = true;
920
+ ui.statusBar.setContent(' {#f59e0b-fg}Press Ctrl+C again to exit{/}');
921
+ safeRender();
922
+ setTimeout(() => {
923
+ ctrlCPressed = false;
924
+ updateStatusBar(state, ui);
925
+ safeRender();
926
+ }, 2000);
927
+ }
928
+ }
929
+ });
930
+ // Escape: Clear input and blur (exit input mode)
931
+ ui.screen.key(['escape'], () => {
932
+ const currentValue = ui.inputBox.getValue();
933
+ if (currentValue && currentValue.trim()) {
934
+ // Clear input if has content
935
+ ui.inputBox.clearValue();
936
+ }
937
+ // Blur input box to exit input mode
938
+ ui.chatLog.focus();
939
+ safeRender();
940
+ });
941
+ // Enter in chatLog: focus input
942
+ ui.chatLog.key(['enter', 'i'], () => {
943
+ ui.inputBox.focus();
944
+ safeRender();
945
+ });
946
+ // Shift+Enter: Insert newline (handled by textarea by default)
947
+ // Enter: Submit message
948
+ ui.inputBox.key(['enter'], async () => {
949
+ const value = ui.inputBox.getValue();
950
+ const trimmed = value.trim();
951
+ if (!trimmed)
952
+ return;
953
+ ui.inputBox.clearValue();
954
+ ui.inputBox.focus();
955
+ safeRender();
956
+ if (trimmed.startsWith('/')) {
957
+ await handleCommand(trimmed, state, ui);
958
+ }
959
+ else {
960
+ await sendMessage(state, ui, trimmed);
961
+ }
962
+ });
963
+ // Focus input by default
964
+ ui.inputBox.focus();
965
+ // Handle terminal resize (important for tmux) — debounce로 연속 resize 시 깜빡임 방지
966
+ let resizeTimer = null;
967
+ process.stdout.on('resize', () => {
968
+ if (resizeTimer)
969
+ clearTimeout(resizeTimer);
970
+ resizeTimer = setTimeout(() => {
971
+ ui.screen.alloc();
972
+ ui.screen.realloc();
973
+ safeRender();
974
+ }, 50);
975
+ });
976
+ // Render
977
+ safeRender();
978
+ // Auto-refresh Projects/Tasks/Stuck tabs every 5s
979
+ setInterval(() => {
980
+ if (state.currentTab === 1)
981
+ loadProjectsData(ui.projectsBox);
982
+ if (state.currentTab === 2)
983
+ loadTasksData(ui.tasksBox);
984
+ if (state.currentTab === 3)
985
+ loadStuckData(ui.stuckBox);
986
+ safeRender();
987
+ }, 5000);
988
+ // System logs (example - hook into eventHub in real implementation)
989
+ ui.logsBox.log('{gray-fg}System initialized{/gray-fg}');
990
+ }
991
+ // Auto-run if called directly
992
+ if (import.meta.url === `file://${process.argv[1]}`) {
993
+ main().catch((err) => {
994
+ console.error('Fatal:', err);
995
+ process.exit(1);
996
+ });
997
+ }
998
+ //# sourceMappingURL=chatTui.js.map