synapsexcoder 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (705) hide show
  1. package/.opencode/opencode.jsonc +102 -0
  2. package/README.md +353 -0
  3. package/dist/agents/agent-config-manager.d.ts +58 -0
  4. package/dist/agents/agent-config-manager.d.ts.map +1 -0
  5. package/dist/agents/agent-config-manager.js +313 -0
  6. package/dist/agents/agent-config-manager.js.map +1 -0
  7. package/dist/agents/base-agents.d.ts +352 -0
  8. package/dist/agents/base-agents.d.ts.map +1 -0
  9. package/dist/agents/base-agents.js +3961 -0
  10. package/dist/agents/base-agents.js.map +1 -0
  11. package/dist/agents/gated-subagent.d.ts +126 -0
  12. package/dist/agents/gated-subagent.d.ts.map +1 -0
  13. package/dist/agents/gated-subagent.js +591 -0
  14. package/dist/agents/gated-subagent.js.map +1 -0
  15. package/dist/agents/gated-subagents.d.ts +130 -0
  16. package/dist/agents/gated-subagents.d.ts.map +1 -0
  17. package/dist/agents/gated-subagents.js +2014 -0
  18. package/dist/agents/gated-subagents.js.map +1 -0
  19. package/dist/agents/internal-gatekeeper.d.ts +167 -0
  20. package/dist/agents/internal-gatekeeper.d.ts.map +1 -0
  21. package/dist/agents/internal-gatekeeper.js +1130 -0
  22. package/dist/agents/internal-gatekeeper.js.map +1 -0
  23. package/dist/agents/verification-agent.d.ts +86 -0
  24. package/dist/agents/verification-agent.d.ts.map +1 -0
  25. package/dist/agents/verification-agent.js +211 -0
  26. package/dist/agents/verification-agent.js.map +1 -0
  27. package/dist/analytics/analytics-types.d.ts +113 -0
  28. package/dist/analytics/analytics-types.d.ts.map +1 -0
  29. package/dist/analytics/analytics-types.js +8 -0
  30. package/dist/analytics/analytics-types.js.map +1 -0
  31. package/dist/analytics/dashboard-generator.d.ts +35 -0
  32. package/dist/analytics/dashboard-generator.d.ts.map +1 -0
  33. package/dist/analytics/dashboard-generator.js +365 -0
  34. package/dist/analytics/dashboard-generator.js.map +1 -0
  35. package/dist/analytics/index.d.ts +12 -0
  36. package/dist/analytics/index.d.ts.map +1 -0
  37. package/dist/analytics/index.js +12 -0
  38. package/dist/analytics/index.js.map +1 -0
  39. package/dist/analytics/metrics-aggregator.d.ts +88 -0
  40. package/dist/analytics/metrics-aggregator.d.ts.map +1 -0
  41. package/dist/analytics/metrics-aggregator.js +280 -0
  42. package/dist/analytics/metrics-aggregator.js.map +1 -0
  43. package/dist/cli/index.d.ts +36 -0
  44. package/dist/cli/index.d.ts.map +1 -0
  45. package/dist/cli/index.js +2677 -0
  46. package/dist/cli/index.js.map +1 -0
  47. package/dist/cli/normalize_patch.d.ts +3 -0
  48. package/dist/cli/normalize_patch.d.ts.map +1 -0
  49. package/dist/cli/normalize_patch.js +34 -0
  50. package/dist/cli/normalize_patch.js.map +1 -0
  51. package/dist/commands/command-processor.d.ts +58 -0
  52. package/dist/commands/command-processor.d.ts.map +1 -0
  53. package/dist/commands/command-processor.js +796 -0
  54. package/dist/commands/command-processor.js.map +1 -0
  55. package/dist/config/compliance-checker.d.ts +93 -0
  56. package/dist/config/compliance-checker.d.ts.map +1 -0
  57. package/dist/config/compliance-checker.js +424 -0
  58. package/dist/config/compliance-checker.js.map +1 -0
  59. package/dist/config/enterprise-config.d.ts +173 -0
  60. package/dist/config/enterprise-config.d.ts.map +1 -0
  61. package/dist/config/enterprise-config.js +190 -0
  62. package/dist/config/enterprise-config.js.map +1 -0
  63. package/dist/config/index.d.ts +13 -0
  64. package/dist/config/index.d.ts.map +1 -0
  65. package/dist/config/index.js +11 -0
  66. package/dist/config/index.js.map +1 -0
  67. package/dist/context/context-system.d.ts +97 -0
  68. package/dist/context/context-system.d.ts.map +1 -0
  69. package/dist/context/context-system.js +880 -0
  70. package/dist/context/context-system.js.map +1 -0
  71. package/dist/context/store.d.ts +123 -0
  72. package/dist/context/store.d.ts.map +1 -0
  73. package/dist/context/store.js +281 -0
  74. package/dist/context/store.js.map +1 -0
  75. package/dist/dasp/dasp-controller.d.ts +83 -0
  76. package/dist/dasp/dasp-controller.d.ts.map +1 -0
  77. package/dist/dasp/dasp-controller.js +190 -0
  78. package/dist/dasp/dasp-controller.js.map +1 -0
  79. package/dist/dasp/feedback-adapter.d.ts +56 -0
  80. package/dist/dasp/feedback-adapter.d.ts.map +1 -0
  81. package/dist/dasp/feedback-adapter.js +158 -0
  82. package/dist/dasp/feedback-adapter.js.map +1 -0
  83. package/dist/dasp/index.d.ts +14 -0
  84. package/dist/dasp/index.d.ts.map +1 -0
  85. package/dist/dasp/index.js +10 -0
  86. package/dist/dasp/index.js.map +1 -0
  87. package/dist/dasp/prompt-templates.d.ts +38 -0
  88. package/dist/dasp/prompt-templates.d.ts.map +1 -0
  89. package/dist/dasp/prompt-templates.js +406 -0
  90. package/dist/dasp/prompt-templates.js.map +1 -0
  91. package/dist/dasp/vault-rag-provider.d.ts +51 -0
  92. package/dist/dasp/vault-rag-provider.d.ts.map +1 -0
  93. package/dist/dasp/vault-rag-provider.js +125 -0
  94. package/dist/dasp/vault-rag-provider.js.map +1 -0
  95. package/dist/distribution/cli-distribution.d.ts +68 -0
  96. package/dist/distribution/cli-distribution.d.ts.map +1 -0
  97. package/dist/distribution/cli-distribution.js +941 -0
  98. package/dist/distribution/cli-distribution.js.map +1 -0
  99. package/dist/docs/doc-generator.d.ts +78 -0
  100. package/dist/docs/doc-generator.d.ts.map +1 -0
  101. package/dist/docs/doc-generator.js +297 -0
  102. package/dist/docs/doc-generator.js.map +1 -0
  103. package/dist/docs/index.d.ts +13 -0
  104. package/dist/docs/index.d.ts.map +1 -0
  105. package/dist/docs/index.js +11 -0
  106. package/dist/docs/index.js.map +1 -0
  107. package/dist/docs/site-builder.d.ts +58 -0
  108. package/dist/docs/site-builder.d.ts.map +1 -0
  109. package/dist/docs/site-builder.js +229 -0
  110. package/dist/docs/site-builder.js.map +1 -0
  111. package/dist/ecosystem/adapters/claude-adapter.d.ts +29 -0
  112. package/dist/ecosystem/adapters/claude-adapter.d.ts.map +1 -0
  113. package/dist/ecosystem/adapters/claude-adapter.js +116 -0
  114. package/dist/ecosystem/adapters/claude-adapter.js.map +1 -0
  115. package/dist/ecosystem/adapters/cursor-adapter.d.ts +27 -0
  116. package/dist/ecosystem/adapters/cursor-adapter.d.ts.map +1 -0
  117. package/dist/ecosystem/adapters/cursor-adapter.js +93 -0
  118. package/dist/ecosystem/adapters/cursor-adapter.js.map +1 -0
  119. package/dist/ecosystem/adapters/v0-adapter.d.ts +30 -0
  120. package/dist/ecosystem/adapters/v0-adapter.d.ts.map +1 -0
  121. package/dist/ecosystem/adapters/v0-adapter.js +112 -0
  122. package/dist/ecosystem/adapters/v0-adapter.js.map +1 -0
  123. package/dist/ecosystem/ecosystem-router.d.ts +80 -0
  124. package/dist/ecosystem/ecosystem-router.d.ts.map +1 -0
  125. package/dist/ecosystem/ecosystem-router.js +241 -0
  126. package/dist/ecosystem/ecosystem-router.js.map +1 -0
  127. package/dist/ecosystem/ecosystem-types.d.ts +94 -0
  128. package/dist/ecosystem/ecosystem-types.d.ts.map +1 -0
  129. package/dist/ecosystem/ecosystem-types.js +27 -0
  130. package/dist/ecosystem/ecosystem-types.js.map +1 -0
  131. package/dist/ecosystem/index.d.ts +10 -0
  132. package/dist/ecosystem/index.d.ts.map +1 -0
  133. package/dist/ecosystem/index.js +9 -0
  134. package/dist/ecosystem/index.js.map +1 -0
  135. package/dist/integration/agentic-integration.d.ts +73 -0
  136. package/dist/integration/agentic-integration.d.ts.map +1 -0
  137. package/dist/integration/agentic-integration.js +253 -0
  138. package/dist/integration/agentic-integration.js.map +1 -0
  139. package/dist/integration/background-agents-integration.d.ts +54 -0
  140. package/dist/integration/background-agents-integration.d.ts.map +1 -0
  141. package/dist/integration/background-agents-integration.js +225 -0
  142. package/dist/integration/background-agents-integration.js.map +1 -0
  143. package/dist/integration/dcp-integration.d.ts +81 -0
  144. package/dist/integration/dcp-integration.d.ts.map +1 -0
  145. package/dist/integration/dcp-integration.js +189 -0
  146. package/dist/integration/dcp-integration.js.map +1 -0
  147. package/dist/integration/firecrawl-integration.d.ts +61 -0
  148. package/dist/integration/firecrawl-integration.d.ts.map +1 -0
  149. package/dist/integration/firecrawl-integration.js +246 -0
  150. package/dist/integration/firecrawl-integration.js.map +1 -0
  151. package/dist/integration/index.d.ts +40 -0
  152. package/dist/integration/index.d.ts.map +1 -0
  153. package/dist/integration/index.js +43 -0
  154. package/dist/integration/index.js.map +1 -0
  155. package/dist/integration/integration-hub.d.ts +43 -0
  156. package/dist/integration/integration-hub.d.ts.map +1 -0
  157. package/dist/integration/integration-hub.js +507 -0
  158. package/dist/integration/integration-hub.js.map +1 -0
  159. package/dist/integration/integration-loader.d.ts +42 -0
  160. package/dist/integration/integration-loader.d.ts.map +1 -0
  161. package/dist/integration/integration-loader.js +240 -0
  162. package/dist/integration/integration-loader.js.map +1 -0
  163. package/dist/integration/md-table-formatter-integration.d.ts +41 -0
  164. package/dist/integration/md-table-formatter-integration.d.ts.map +1 -0
  165. package/dist/integration/md-table-formatter-integration.js +183 -0
  166. package/dist/integration/md-table-formatter-integration.js.map +1 -0
  167. package/dist/integration/native/agentic/agentic-engine.d.ts +52 -0
  168. package/dist/integration/native/agentic/agentic-engine.d.ts.map +1 -0
  169. package/dist/integration/native/agentic/agentic-engine.js +267 -0
  170. package/dist/integration/native/agentic/agentic-engine.js.map +1 -0
  171. package/dist/integration/native/background/background-engine.d.ts +62 -0
  172. package/dist/integration/native/background/background-engine.d.ts.map +1 -0
  173. package/dist/integration/native/background/background-engine.js +167 -0
  174. package/dist/integration/native/background/background-engine.js.map +1 -0
  175. package/dist/integration/native/dcp/dcp-engine.d.ts +55 -0
  176. package/dist/integration/native/dcp/dcp-engine.d.ts.map +1 -0
  177. package/dist/integration/native/dcp/dcp-engine.js +168 -0
  178. package/dist/integration/native/dcp/dcp-engine.js.map +1 -0
  179. package/dist/integration/native/firecrawl/firecrawl-engine.d.ts +66 -0
  180. package/dist/integration/native/firecrawl/firecrawl-engine.d.ts.map +1 -0
  181. package/dist/integration/native/firecrawl/firecrawl-engine.js +221 -0
  182. package/dist/integration/native/firecrawl/firecrawl-engine.js.map +1 -0
  183. package/dist/integration/native/formatter/formatter-engine.d.ts +47 -0
  184. package/dist/integration/native/formatter/formatter-engine.d.ts.map +1 -0
  185. package/dist/integration/native/formatter/formatter-engine.js +130 -0
  186. package/dist/integration/native/formatter/formatter-engine.js.map +1 -0
  187. package/dist/integration/native/index.d.ts +41 -0
  188. package/dist/integration/native/index.d.ts.map +1 -0
  189. package/dist/integration/native/index.js +80 -0
  190. package/dist/integration/native/index.js.map +1 -0
  191. package/dist/integration/native/orchestration/orchestration-engine.d.ts +62 -0
  192. package/dist/integration/native/orchestration/orchestration-engine.d.ts.map +1 -0
  193. package/dist/integration/native/orchestration/orchestration-engine.js +177 -0
  194. package/dist/integration/native/orchestration/orchestration-engine.js.map +1 -0
  195. package/dist/integration/native/pty/pty-engine.d.ts +45 -0
  196. package/dist/integration/native/pty/pty-engine.d.ts.map +1 -0
  197. package/dist/integration/native/pty/pty-engine.js +103 -0
  198. package/dist/integration/native/pty/pty-engine.js.map +1 -0
  199. package/dist/integration/native/shell-strategy.d.ts +60 -0
  200. package/dist/integration/native/shell-strategy.d.ts.map +1 -0
  201. package/dist/integration/native/shell-strategy.js +131 -0
  202. package/dist/integration/native/shell-strategy.js.map +1 -0
  203. package/dist/integration/native/skillful/skillful-engine.d.ts +53 -0
  204. package/dist/integration/native/skillful/skillful-engine.d.ts.map +1 -0
  205. package/dist/integration/native/skillful/skillful-engine.js +127 -0
  206. package/dist/integration/native/skillful/skillful-engine.js.map +1 -0
  207. package/dist/integration/native/subtask2/subtask2-engine.d.ts +50 -0
  208. package/dist/integration/native/subtask2/subtask2-engine.d.ts.map +1 -0
  209. package/dist/integration/native/subtask2/subtask2-engine.js +158 -0
  210. package/dist/integration/native/subtask2/subtask2-engine.js.map +1 -0
  211. package/dist/integration/native/supermemory/supermemory-engine.d.ts +63 -0
  212. package/dist/integration/native/supermemory/supermemory-engine.d.ts.map +1 -0
  213. package/dist/integration/native/supermemory/supermemory-engine.js +127 -0
  214. package/dist/integration/native/supermemory/supermemory-engine.js.map +1 -0
  215. package/dist/integration/native/workspace/workspace-engine.d.ts +75 -0
  216. package/dist/integration/native/workspace/workspace-engine.d.ts.map +1 -0
  217. package/dist/integration/native/workspace/workspace-engine.js +216 -0
  218. package/dist/integration/native/workspace/workspace-engine.js.map +1 -0
  219. package/dist/integration/oh-my-opencode-integration.d.ts +59 -0
  220. package/dist/integration/oh-my-opencode-integration.d.ts.map +1 -0
  221. package/dist/integration/oh-my-opencode-integration.js +180 -0
  222. package/dist/integration/oh-my-opencode-integration.js.map +1 -0
  223. package/dist/integration/openagents-control-integration.d.ts +81 -0
  224. package/dist/integration/openagents-control-integration.d.ts.map +1 -0
  225. package/dist/integration/openagents-control-integration.js +273 -0
  226. package/dist/integration/openagents-control-integration.js.map +1 -0
  227. package/dist/integration/pty-integration.d.ts +64 -0
  228. package/dist/integration/pty-integration.d.ts.map +1 -0
  229. package/dist/integration/pty-integration.js +180 -0
  230. package/dist/integration/pty-integration.js.map +1 -0
  231. package/dist/integration/shell-strategy-integration.d.ts +26 -0
  232. package/dist/integration/shell-strategy-integration.d.ts.map +1 -0
  233. package/dist/integration/shell-strategy-integration.js +110 -0
  234. package/dist/integration/shell-strategy-integration.js.map +1 -0
  235. package/dist/integration/skillful-integration.d.ts +74 -0
  236. package/dist/integration/skillful-integration.d.ts.map +1 -0
  237. package/dist/integration/skillful-integration.js +317 -0
  238. package/dist/integration/skillful-integration.js.map +1 -0
  239. package/dist/integration/subtask2-integration.d.ts +71 -0
  240. package/dist/integration/subtask2-integration.d.ts.map +1 -0
  241. package/dist/integration/subtask2-integration.js +240 -0
  242. package/dist/integration/subtask2-integration.js.map +1 -0
  243. package/dist/integration/supermemory-integration.d.ts +82 -0
  244. package/dist/integration/supermemory-integration.d.ts.map +1 -0
  245. package/dist/integration/supermemory-integration.js +252 -0
  246. package/dist/integration/supermemory-integration.js.map +1 -0
  247. package/dist/integration/types.d.ts +218 -0
  248. package/dist/integration/types.d.ts.map +1 -0
  249. package/dist/integration/types.js +5 -0
  250. package/dist/integration/types.js.map +1 -0
  251. package/dist/integration/workspace-integration.d.ts +46 -0
  252. package/dist/integration/workspace-integration.d.ts.map +1 -0
  253. package/dist/integration/workspace-integration.js +181 -0
  254. package/dist/integration/workspace-integration.js.map +1 -0
  255. package/dist/knowledge-vault/deepwiki-sync.d.ts +99 -0
  256. package/dist/knowledge-vault/deepwiki-sync.d.ts.map +1 -0
  257. package/dist/knowledge-vault/deepwiki-sync.js +381 -0
  258. package/dist/knowledge-vault/deepwiki-sync.js.map +1 -0
  259. package/dist/knowledge-vault/index.d.ts +11 -0
  260. package/dist/knowledge-vault/index.d.ts.map +1 -0
  261. package/dist/knowledge-vault/index.js +8 -0
  262. package/dist/knowledge-vault/index.js.map +1 -0
  263. package/dist/knowledge-vault/knowledge-vault.d.ts +38 -0
  264. package/dist/knowledge-vault/knowledge-vault.d.ts.map +1 -0
  265. package/dist/knowledge-vault/knowledge-vault.js +284 -0
  266. package/dist/knowledge-vault/knowledge-vault.js.map +1 -0
  267. package/dist/knowledge-vault/opencode-doc-ingest.d.ts +23 -0
  268. package/dist/knowledge-vault/opencode-doc-ingest.d.ts.map +1 -0
  269. package/dist/knowledge-vault/opencode-doc-ingest.js +48 -0
  270. package/dist/knowledge-vault/opencode-doc-ingest.js.map +1 -0
  271. package/dist/knowledge-vault/types.d.ts +61 -0
  272. package/dist/knowledge-vault/types.d.ts.map +1 -0
  273. package/dist/knowledge-vault/types.js +5 -0
  274. package/dist/knowledge-vault/types.js.map +1 -0
  275. package/dist/knowledge-vault/vault-config.d.ts +12 -0
  276. package/dist/knowledge-vault/vault-config.d.ts.map +1 -0
  277. package/dist/knowledge-vault/vault-config.js +24 -0
  278. package/dist/knowledge-vault/vault-config.js.map +1 -0
  279. package/dist/mcp/index.d.ts +28 -0
  280. package/dist/mcp/index.d.ts.map +1 -0
  281. package/dist/mcp/index.js +29 -0
  282. package/dist/mcp/index.js.map +1 -0
  283. package/dist/mcp/mcp-manager.d.ts +181 -0
  284. package/dist/mcp/mcp-manager.d.ts.map +1 -0
  285. package/dist/mcp/mcp-manager.js +621 -0
  286. package/dist/mcp/mcp-manager.js.map +1 -0
  287. package/dist/mcp/mcp-types.d.ts +199 -0
  288. package/dist/mcp/mcp-types.d.ts.map +1 -0
  289. package/dist/mcp/mcp-types.js +152 -0
  290. package/dist/mcp/mcp-types.js.map +1 -0
  291. package/dist/mcp/servers/mcp-server-bridge.d.ts +64 -0
  292. package/dist/mcp/servers/mcp-server-bridge.d.ts.map +1 -0
  293. package/dist/mcp/servers/mcp-server-bridge.js +189 -0
  294. package/dist/mcp/servers/mcp-server-bridge.js.map +1 -0
  295. package/dist/messages/message-bus.d.ts +148 -0
  296. package/dist/messages/message-bus.d.ts.map +1 -0
  297. package/dist/messages/message-bus.js +432 -0
  298. package/dist/messages/message-bus.js.map +1 -0
  299. package/dist/modes/custom-mode-registry.d.ts +121 -0
  300. package/dist/modes/custom-mode-registry.d.ts.map +1 -0
  301. package/dist/modes/custom-mode-registry.js +306 -0
  302. package/dist/modes/custom-mode-registry.js.map +1 -0
  303. package/dist/modes/index.d.ts +10 -0
  304. package/dist/modes/index.d.ts.map +1 -0
  305. package/dist/modes/index.js +8 -0
  306. package/dist/modes/index.js.map +1 -0
  307. package/dist/modes/mode-designer.d.ts +89 -0
  308. package/dist/modes/mode-designer.d.ts.map +1 -0
  309. package/dist/modes/mode-designer.js +485 -0
  310. package/dist/modes/mode-designer.js.map +1 -0
  311. package/dist/modes/mode-manager.d.ts +27 -0
  312. package/dist/modes/mode-manager.d.ts.map +1 -0
  313. package/dist/modes/mode-manager.js +68 -0
  314. package/dist/modes/mode-manager.js.map +1 -0
  315. package/dist/modes/synapse-modes.d.ts +26 -0
  316. package/dist/modes/synapse-modes.d.ts.map +1 -0
  317. package/dist/modes/synapse-modes.js +69 -0
  318. package/dist/modes/synapse-modes.js.map +1 -0
  319. package/dist/opencode/agent-delegate.d.ts +3 -0
  320. package/dist/opencode/agent-delegate.d.ts.map +1 -0
  321. package/dist/opencode/agent-delegate.js +3 -0
  322. package/dist/opencode/agent-delegate.js.map +1 -0
  323. package/dist/opencode/tool-bridge.d.ts +3 -0
  324. package/dist/opencode/tool-bridge.d.ts.map +1 -0
  325. package/dist/opencode/tool-bridge.js +3 -0
  326. package/dist/opencode/tool-bridge.js.map +1 -0
  327. package/dist/optimization/token-optimizer-v2.d.ts +18 -0
  328. package/dist/optimization/token-optimizer-v2.d.ts.map +1 -0
  329. package/dist/optimization/token-optimizer-v2.js +23 -0
  330. package/dist/optimization/token-optimizer-v2.js.map +1 -0
  331. package/dist/optimization/token-optimizer.d.ts +90 -0
  332. package/dist/optimization/token-optimizer.d.ts.map +1 -0
  333. package/dist/optimization/token-optimizer.js +399 -0
  334. package/dist/optimization/token-optimizer.js.map +1 -0
  335. package/dist/parallel/agent-farm.d.ts +123 -0
  336. package/dist/parallel/agent-farm.d.ts.map +1 -0
  337. package/dist/parallel/agent-farm.js +501 -0
  338. package/dist/parallel/agent-farm.js.map +1 -0
  339. package/dist/parallel/farm-scheduler.d.ts +115 -0
  340. package/dist/parallel/farm-scheduler.d.ts.map +1 -0
  341. package/dist/parallel/farm-scheduler.js +356 -0
  342. package/dist/parallel/farm-scheduler.js.map +1 -0
  343. package/dist/parallel/farm-types.d.ts +104 -0
  344. package/dist/parallel/farm-types.d.ts.map +1 -0
  345. package/dist/parallel/farm-types.js +9 -0
  346. package/dist/parallel/farm-types.js.map +1 -0
  347. package/dist/parallel/farm-worker.d.ts +62 -0
  348. package/dist/parallel/farm-worker.d.ts.map +1 -0
  349. package/dist/parallel/farm-worker.js +268 -0
  350. package/dist/parallel/farm-worker.js.map +1 -0
  351. package/dist/parallel/index.d.ts +14 -0
  352. package/dist/parallel/index.d.ts.map +1 -0
  353. package/dist/parallel/index.js +14 -0
  354. package/dist/parallel/index.js.map +1 -0
  355. package/dist/plugin/native-tools.d.ts +8 -0
  356. package/dist/plugin/native-tools.d.ts.map +1 -0
  357. package/dist/plugin/native-tools.js +147 -0
  358. package/dist/plugin/native-tools.js.map +1 -0
  359. package/dist/plugin/opencode-plugin.d.ts +32 -0
  360. package/dist/plugin/opencode-plugin.d.ts.map +1 -0
  361. package/dist/plugin/opencode-plugin.js +119 -0
  362. package/dist/plugin/opencode-plugin.js.map +1 -0
  363. package/dist/plugins/plugin-system.d.ts +108 -0
  364. package/dist/plugins/plugin-system.d.ts.map +1 -0
  365. package/dist/plugins/plugin-system.js +707 -0
  366. package/dist/plugins/plugin-system.js.map +1 -0
  367. package/dist/profiler/cpu-profiler.d.ts +53 -0
  368. package/dist/profiler/cpu-profiler.d.ts.map +1 -0
  369. package/dist/profiler/cpu-profiler.js +233 -0
  370. package/dist/profiler/cpu-profiler.js.map +1 -0
  371. package/dist/profiler/index.d.ts +36 -0
  372. package/dist/profiler/index.d.ts.map +1 -0
  373. package/dist/profiler/index.js +122 -0
  374. package/dist/profiler/index.js.map +1 -0
  375. package/dist/profiler/memory-profiler.d.ts +45 -0
  376. package/dist/profiler/memory-profiler.d.ts.map +1 -0
  377. package/dist/profiler/memory-profiler.js +211 -0
  378. package/dist/profiler/memory-profiler.js.map +1 -0
  379. package/dist/profiler/profiler-types.d.ts +234 -0
  380. package/dist/profiler/profiler-types.d.ts.map +1 -0
  381. package/dist/profiler/profiler-types.js +89 -0
  382. package/dist/profiler/profiler-types.js.map +1 -0
  383. package/dist/profiler/query-profiler.d.ts +48 -0
  384. package/dist/profiler/query-profiler.d.ts.map +1 -0
  385. package/dist/profiler/query-profiler.js +210 -0
  386. package/dist/profiler/query-profiler.js.map +1 -0
  387. package/dist/profiler/report-generator.d.ts +17 -0
  388. package/dist/profiler/report-generator.d.ts.map +1 -0
  389. package/dist/profiler/report-generator.js +329 -0
  390. package/dist/profiler/report-generator.js.map +1 -0
  391. package/dist/sdk/api.d.ts +85 -0
  392. package/dist/sdk/api.d.ts.map +1 -0
  393. package/dist/sdk/api.js +155 -0
  394. package/dist/sdk/api.js.map +1 -0
  395. package/dist/sdk/hooks.d.ts +58 -0
  396. package/dist/sdk/hooks.d.ts.map +1 -0
  397. package/dist/sdk/hooks.js +115 -0
  398. package/dist/sdk/hooks.js.map +1 -0
  399. package/dist/sdk/index.d.ts +17 -0
  400. package/dist/sdk/index.d.ts.map +1 -0
  401. package/dist/sdk/index.js +14 -0
  402. package/dist/sdk/index.js.map +1 -0
  403. package/dist/sdk/plugin-base.d.ts +198 -0
  404. package/dist/sdk/plugin-base.d.ts.map +1 -0
  405. package/dist/sdk/plugin-base.js +227 -0
  406. package/dist/sdk/plugin-base.js.map +1 -0
  407. package/dist/security/audit-rules.d.ts +12 -0
  408. package/dist/security/audit-rules.d.ts.map +1 -0
  409. package/dist/security/audit-rules.js +214 -0
  410. package/dist/security/audit-rules.js.map +1 -0
  411. package/dist/security/index.d.ts +13 -0
  412. package/dist/security/index.d.ts.map +1 -0
  413. package/dist/security/index.js +13 -0
  414. package/dist/security/index.js.map +1 -0
  415. package/dist/security/sarif-exporter.d.ts +36 -0
  416. package/dist/security/sarif-exporter.d.ts.map +1 -0
  417. package/dist/security/sarif-exporter.js +216 -0
  418. package/dist/security/sarif-exporter.js.map +1 -0
  419. package/dist/security/security-auditor.d.ts +30 -0
  420. package/dist/security/security-auditor.d.ts.map +1 -0
  421. package/dist/security/security-auditor.js +295 -0
  422. package/dist/security/security-auditor.js.map +1 -0
  423. package/dist/security/security-types.d.ts +132 -0
  424. package/dist/security/security-types.d.ts.map +1 -0
  425. package/dist/security/security-types.js +7 -0
  426. package/dist/security/security-types.js.map +1 -0
  427. package/dist/synapsexcoder/agent-delegate.d.ts +128 -0
  428. package/dist/synapsexcoder/agent-delegate.d.ts.map +1 -0
  429. package/dist/synapsexcoder/agent-delegate.js +837 -0
  430. package/dist/synapsexcoder/agent-delegate.js.map +1 -0
  431. package/dist/synapsexcoder/agent-mailbox.d.ts +26 -0
  432. package/dist/synapsexcoder/agent-mailbox.d.ts.map +1 -0
  433. package/dist/synapsexcoder/agent-mailbox.js +64 -0
  434. package/dist/synapsexcoder/agent-mailbox.js.map +1 -0
  435. package/dist/synapsexcoder/ast-grep/ast-grep-api.d.ts +62 -0
  436. package/dist/synapsexcoder/ast-grep/ast-grep-api.d.ts.map +1 -0
  437. package/dist/synapsexcoder/ast-grep/ast-grep-api.js +223 -0
  438. package/dist/synapsexcoder/ast-grep/ast-grep-api.js.map +1 -0
  439. package/dist/synapsexcoder/cited-search.d.ts +32 -0
  440. package/dist/synapsexcoder/cited-search.d.ts.map +1 -0
  441. package/dist/synapsexcoder/cited-search.js +141 -0
  442. package/dist/synapsexcoder/cited-search.js.map +1 -0
  443. package/dist/synapsexcoder/credential-store.d.ts +42 -0
  444. package/dist/synapsexcoder/credential-store.d.ts.map +1 -0
  445. package/dist/synapsexcoder/credential-store.js +165 -0
  446. package/dist/synapsexcoder/credential-store.js.map +1 -0
  447. package/dist/synapsexcoder/devcontainer-awareness.d.ts +35 -0
  448. package/dist/synapsexcoder/devcontainer-awareness.d.ts.map +1 -0
  449. package/dist/synapsexcoder/devcontainer-awareness.js +133 -0
  450. package/dist/synapsexcoder/devcontainer-awareness.js.map +1 -0
  451. package/dist/synapsexcoder/execution-loops/helix-loop.d.ts +31 -0
  452. package/dist/synapsexcoder/execution-loops/helix-loop.d.ts.map +1 -0
  453. package/dist/synapsexcoder/execution-loops/helix-loop.js +93 -0
  454. package/dist/synapsexcoder/execution-loops/helix-loop.js.map +1 -0
  455. package/dist/synapsexcoder/execution-loops/ralp-loop.d.ts +28 -0
  456. package/dist/synapsexcoder/execution-loops/ralp-loop.d.ts.map +1 -0
  457. package/dist/synapsexcoder/execution-loops/ralp-loop.js +77 -0
  458. package/dist/synapsexcoder/execution-loops/ralp-loop.js.map +1 -0
  459. package/dist/synapsexcoder/feature-names.d.ts +27 -0
  460. package/dist/synapsexcoder/feature-names.d.ts.map +1 -0
  461. package/dist/synapsexcoder/feature-names.js +40 -0
  462. package/dist/synapsexcoder/feature-names.js.map +1 -0
  463. package/dist/synapsexcoder/index.d.ts +39 -0
  464. package/dist/synapsexcoder/index.d.ts.map +1 -0
  465. package/dist/synapsexcoder/index.js +23 -0
  466. package/dist/synapsexcoder/index.js.map +1 -0
  467. package/dist/synapsexcoder/knowledge-provider.d.ts +44 -0
  468. package/dist/synapsexcoder/knowledge-provider.d.ts.map +1 -0
  469. package/dist/synapsexcoder/knowledge-provider.js +107 -0
  470. package/dist/synapsexcoder/knowledge-provider.js.map +1 -0
  471. package/dist/synapsexcoder/lsp/lsp-layer.d.ts +51 -0
  472. package/dist/synapsexcoder/lsp/lsp-layer.d.ts.map +1 -0
  473. package/dist/synapsexcoder/lsp/lsp-layer.js +302 -0
  474. package/dist/synapsexcoder/lsp/lsp-layer.js.map +1 -0
  475. package/dist/synapsexcoder/migration/opencode-config-migrator.d.ts +37 -0
  476. package/dist/synapsexcoder/migration/opencode-config-migrator.d.ts.map +1 -0
  477. package/dist/synapsexcoder/migration/opencode-config-migrator.js +100 -0
  478. package/dist/synapsexcoder/migration/opencode-config-migrator.js.map +1 -0
  479. package/dist/synapsexcoder/runtime-environment.d.ts +35 -0
  480. package/dist/synapsexcoder/runtime-environment.d.ts.map +1 -0
  481. package/dist/synapsexcoder/runtime-environment.js +108 -0
  482. package/dist/synapsexcoder/runtime-environment.js.map +1 -0
  483. package/dist/synapsexcoder/secret-guard.d.ts +18 -0
  484. package/dist/synapsexcoder/secret-guard.d.ts.map +1 -0
  485. package/dist/synapsexcoder/secret-guard.js +69 -0
  486. package/dist/synapsexcoder/secret-guard.js.map +1 -0
  487. package/dist/synapsexcoder/self-prompt-engine.d.ts +15 -0
  488. package/dist/synapsexcoder/self-prompt-engine.d.ts.map +1 -0
  489. package/dist/synapsexcoder/self-prompt-engine.js +11 -0
  490. package/dist/synapsexcoder/self-prompt-engine.js.map +1 -0
  491. package/dist/synapsexcoder/session-observability.d.ts +44 -0
  492. package/dist/synapsexcoder/session-observability.d.ts.map +1 -0
  493. package/dist/synapsexcoder/session-observability.js +115 -0
  494. package/dist/synapsexcoder/session-observability.js.map +1 -0
  495. package/dist/synapsexcoder/specialist-agents.d.ts +38 -0
  496. package/dist/synapsexcoder/specialist-agents.d.ts.map +1 -0
  497. package/dist/synapsexcoder/specialist-agents.js +192 -0
  498. package/dist/synapsexcoder/specialist-agents.js.map +1 -0
  499. package/dist/synapsexcoder/swarm/kanban-board.d.ts +34 -0
  500. package/dist/synapsexcoder/swarm/kanban-board.d.ts.map +1 -0
  501. package/dist/synapsexcoder/swarm/kanban-board.js +85 -0
  502. package/dist/synapsexcoder/swarm/kanban-board.js.map +1 -0
  503. package/dist/synapsexcoder/swarm/swarm-mailbox.d.ts +38 -0
  504. package/dist/synapsexcoder/swarm/swarm-mailbox.d.ts.map +1 -0
  505. package/dist/synapsexcoder/swarm/swarm-mailbox.js +93 -0
  506. package/dist/synapsexcoder/swarm/swarm-mailbox.js.map +1 -0
  507. package/dist/synapsexcoder/tool-bridge.d.ts +277 -0
  508. package/dist/synapsexcoder/tool-bridge.d.ts.map +1 -0
  509. package/dist/synapsexcoder/tool-bridge.js +1356 -0
  510. package/dist/synapsexcoder/tool-bridge.js.map +1 -0
  511. package/dist/synapsexcoder/tool-routing.d.ts +28 -0
  512. package/dist/synapsexcoder/tool-routing.d.ts.map +1 -0
  513. package/dist/synapsexcoder/tool-routing.js +79 -0
  514. package/dist/synapsexcoder/tool-routing.js.map +1 -0
  515. package/dist/synapsexcoder/type-injector.d.ts +26 -0
  516. package/dist/synapsexcoder/type-injector.d.ts.map +1 -0
  517. package/dist/synapsexcoder/type-injector.js +124 -0
  518. package/dist/synapsexcoder/type-injector.js.map +1 -0
  519. package/dist/synapsexcoder/utils/fuzzy-match.d.ts +25 -0
  520. package/dist/synapsexcoder/utils/fuzzy-match.d.ts.map +1 -0
  521. package/dist/synapsexcoder/utils/fuzzy-match.js +83 -0
  522. package/dist/synapsexcoder/utils/fuzzy-match.js.map +1 -0
  523. package/dist/synapsexcoder/vault-crawl.d.ts +29 -0
  524. package/dist/synapsexcoder/vault-crawl.d.ts.map +1 -0
  525. package/dist/synapsexcoder/vault-crawl.js +103 -0
  526. package/dist/synapsexcoder/vault-crawl.js.map +1 -0
  527. package/dist/synapsexcoder/verified-apply.d.ts +39 -0
  528. package/dist/synapsexcoder/verified-apply.d.ts.map +1 -0
  529. package/dist/synapsexcoder/verified-apply.js +81 -0
  530. package/dist/synapsexcoder/verified-apply.js.map +1 -0
  531. package/dist/synapsexcoder/verified-context-editing.d.ts +34 -0
  532. package/dist/synapsexcoder/verified-context-editing.d.ts.map +1 -0
  533. package/dist/synapsexcoder/verified-context-editing.js +80 -0
  534. package/dist/synapsexcoder/verified-context-editing.js.map +1 -0
  535. package/dist/synapsexcoder/worker-pool.d.ts +47 -0
  536. package/dist/synapsexcoder/worker-pool.d.ts.map +1 -0
  537. package/dist/synapsexcoder/worker-pool.js +120 -0
  538. package/dist/synapsexcoder/worker-pool.js.map +1 -0
  539. package/dist/synapsexcoder/workspace-intelligence.d.ts +35 -0
  540. package/dist/synapsexcoder/workspace-intelligence.d.ts.map +1 -0
  541. package/dist/synapsexcoder/workspace-intelligence.js +126 -0
  542. package/dist/synapsexcoder/workspace-intelligence.js.map +1 -0
  543. package/dist/synapsexcoder/worktree-manager.d.ts +31 -0
  544. package/dist/synapsexcoder/worktree-manager.d.ts.map +1 -0
  545. package/dist/synapsexcoder/worktree-manager.js +100 -0
  546. package/dist/synapsexcoder/worktree-manager.js.map +1 -0
  547. package/dist/team/index.d.ts +17 -0
  548. package/dist/team/index.d.ts.map +1 -0
  549. package/dist/team/index.js +13 -0
  550. package/dist/team/index.js.map +1 -0
  551. package/dist/team/team-audit.d.ts +120 -0
  552. package/dist/team/team-audit.d.ts.map +1 -0
  553. package/dist/team/team-audit.js +357 -0
  554. package/dist/team/team-audit.js.map +1 -0
  555. package/dist/team/team-collaboration.d.ts +150 -0
  556. package/dist/team/team-collaboration.d.ts.map +1 -0
  557. package/dist/team/team-collaboration.js +495 -0
  558. package/dist/team/team-collaboration.js.map +1 -0
  559. package/dist/team/team-rbac.d.ts +84 -0
  560. package/dist/team/team-rbac.d.ts.map +1 -0
  561. package/dist/team/team-rbac.js +259 -0
  562. package/dist/team/team-rbac.js.map +1 -0
  563. package/dist/team/team-session-manager.d.ts +100 -0
  564. package/dist/team/team-session-manager.d.ts.map +1 -0
  565. package/dist/team/team-session-manager.js +255 -0
  566. package/dist/team/team-session-manager.js.map +1 -0
  567. package/dist/thoughts/thoughts-manager.d.ts +52 -0
  568. package/dist/thoughts/thoughts-manager.d.ts.map +1 -0
  569. package/dist/thoughts/thoughts-manager.js +271 -0
  570. package/dist/thoughts/thoughts-manager.js.map +1 -0
  571. package/dist/tools/api-validator/index.d.ts +97 -0
  572. package/dist/tools/api-validator/index.d.ts.map +1 -0
  573. package/dist/tools/api-validator/index.js +312 -0
  574. package/dist/tools/api-validator/index.js.map +1 -0
  575. package/dist/tools/code-archaeology/index.d.ts +193 -0
  576. package/dist/tools/code-archaeology/index.d.ts.map +1 -0
  577. package/dist/tools/code-archaeology/index.js +468 -0
  578. package/dist/tools/code-archaeology/index.js.map +1 -0
  579. package/dist/tools/codebase-search/index.d.ts +126 -0
  580. package/dist/tools/codebase-search/index.d.ts.map +1 -0
  581. package/dist/tools/codebase-search/index.js +437 -0
  582. package/dist/tools/codebase-search/index.js.map +1 -0
  583. package/dist/tools/context/index.d.ts +162 -0
  584. package/dist/tools/context/index.d.ts.map +1 -0
  585. package/dist/tools/context/index.js +332 -0
  586. package/dist/tools/context/index.js.map +1 -0
  587. package/dist/tools/deepwiki/analyzer.d.ts +167 -0
  588. package/dist/tools/deepwiki/analyzer.d.ts.map +1 -0
  589. package/dist/tools/deepwiki/analyzer.js +925 -0
  590. package/dist/tools/deepwiki/analyzer.js.map +1 -0
  591. package/dist/tools/deepwiki/extractor.d.ts +151 -0
  592. package/dist/tools/deepwiki/extractor.d.ts.map +1 -0
  593. package/dist/tools/deepwiki/extractor.js +923 -0
  594. package/dist/tools/deepwiki/extractor.js.map +1 -0
  595. package/dist/tools/deepwiki/generator.d.ts +89 -0
  596. package/dist/tools/deepwiki/generator.d.ts.map +1 -0
  597. package/dist/tools/deepwiki/generator.js +638 -0
  598. package/dist/tools/deepwiki/generator.js.map +1 -0
  599. package/dist/tools/deepwiki/index.d.ts +96 -0
  600. package/dist/tools/deepwiki/index.d.ts.map +1 -0
  601. package/dist/tools/deepwiki/index.js +282 -0
  602. package/dist/tools/deepwiki/index.js.map +1 -0
  603. package/dist/tools/deepwiki/types.d.ts +370 -0
  604. package/dist/tools/deepwiki/types.d.ts.map +1 -0
  605. package/dist/tools/deepwiki/types.js +21 -0
  606. package/dist/tools/deepwiki/types.js.map +1 -0
  607. package/dist/tools/dependency-mapper/index.d.ts +212 -0
  608. package/dist/tools/dependency-mapper/index.d.ts.map +1 -0
  609. package/dist/tools/dependency-mapper/index.js +592 -0
  610. package/dist/tools/dependency-mapper/index.js.map +1 -0
  611. package/dist/tools/memory/index.d.ts +120 -0
  612. package/dist/tools/memory/index.d.ts.map +1 -0
  613. package/dist/tools/memory/index.js +275 -0
  614. package/dist/tools/memory/index.js.map +1 -0
  615. package/dist/tools/normalize_patch.d.ts +3 -0
  616. package/dist/tools/normalize_patch.d.ts.map +1 -0
  617. package/dist/tools/normalize_patch.js +22 -0
  618. package/dist/tools/normalize_patch.js.map +1 -0
  619. package/dist/tools/pattern-detector/index.d.ts +105 -0
  620. package/dist/tools/pattern-detector/index.d.ts.map +1 -0
  621. package/dist/tools/pattern-detector/index.js +526 -0
  622. package/dist/tools/pattern-detector/index.js.map +1 -0
  623. package/dist/tools/performance-profiler/index.d.ts +50 -0
  624. package/dist/tools/performance-profiler/index.d.ts.map +1 -0
  625. package/dist/tools/performance-profiler/index.js +164 -0
  626. package/dist/tools/performance-profiler/index.js.map +1 -0
  627. package/dist/tools/refactoring-engine/index.d.ts +63 -0
  628. package/dist/tools/refactoring-engine/index.d.ts.map +1 -0
  629. package/dist/tools/refactoring-engine/index.js +270 -0
  630. package/dist/tools/refactoring-engine/index.js.map +1 -0
  631. package/dist/tools/registry.d.ts +36 -0
  632. package/dist/tools/registry.d.ts.map +1 -0
  633. package/dist/tools/registry.js +499 -0
  634. package/dist/tools/registry.js.map +1 -0
  635. package/dist/tools/test-generator/index.d.ts +152 -0
  636. package/dist/tools/test-generator/index.d.ts.map +1 -0
  637. package/dist/tools/test-generator/index.js +448 -0
  638. package/dist/tools/test-generator/index.js.map +1 -0
  639. package/dist/types/index.d.ts +565 -0
  640. package/dist/types/index.d.ts.map +1 -0
  641. package/dist/types/index.js +7 -0
  642. package/dist/types/index.js.map +1 -0
  643. package/dist/utils/path-validator.d.ts +94 -0
  644. package/dist/utils/path-validator.d.ts.map +1 -0
  645. package/dist/utils/path-validator.js +192 -0
  646. package/dist/utils/path-validator.js.map +1 -0
  647. package/dist/utils/secure-exec.d.ts +92 -0
  648. package/dist/utils/secure-exec.d.ts.map +1 -0
  649. package/dist/utils/secure-exec.js +230 -0
  650. package/dist/utils/secure-exec.js.map +1 -0
  651. package/dist/verification/claim-parser.d.ts +37 -0
  652. package/dist/verification/claim-parser.d.ts.map +1 -0
  653. package/dist/verification/claim-parser.js +231 -0
  654. package/dist/verification/claim-parser.js.map +1 -0
  655. package/dist/verification/cross-reference-engine.d.ts +55 -0
  656. package/dist/verification/cross-reference-engine.d.ts.map +1 -0
  657. package/dist/verification/cross-reference-engine.js +149 -0
  658. package/dist/verification/cross-reference-engine.js.map +1 -0
  659. package/dist/verification/discrepancy-tracker.d.ts +73 -0
  660. package/dist/verification/discrepancy-tracker.d.ts.map +1 -0
  661. package/dist/verification/discrepancy-tracker.js +196 -0
  662. package/dist/verification/discrepancy-tracker.js.map +1 -0
  663. package/dist/verification/feature-reconciler.d.ts +90 -0
  664. package/dist/verification/feature-reconciler.d.ts.map +1 -0
  665. package/dist/verification/feature-reconciler.js +264 -0
  666. package/dist/verification/feature-reconciler.js.map +1 -0
  667. package/dist/verification/index.d.ts +16 -0
  668. package/dist/verification/index.d.ts.map +1 -0
  669. package/dist/verification/index.js +19 -0
  670. package/dist/verification/index.js.map +1 -0
  671. package/dist/verification/integration-verifier.d.ts +66 -0
  672. package/dist/verification/integration-verifier.d.ts.map +1 -0
  673. package/dist/verification/integration-verifier.js +210 -0
  674. package/dist/verification/integration-verifier.js.map +1 -0
  675. package/dist/verification/recursive-audit-loop.d.ts +56 -0
  676. package/dist/verification/recursive-audit-loop.d.ts.map +1 -0
  677. package/dist/verification/recursive-audit-loop.js +136 -0
  678. package/dist/verification/recursive-audit-loop.js.map +1 -0
  679. package/dist/verification/runtime-verifier.d.ts +37 -0
  680. package/dist/verification/runtime-verifier.d.ts.map +1 -0
  681. package/dist/verification/runtime-verifier.js +221 -0
  682. package/dist/verification/runtime-verifier.js.map +1 -0
  683. package/dist/verification/types.d.ts +88 -0
  684. package/dist/verification/types.d.ts.map +1 -0
  685. package/dist/verification/types.js +5 -0
  686. package/dist/verification/types.js.map +1 -0
  687. package/dist/verification/verification-engine.d.ts +48 -0
  688. package/dist/verification/verification-engine.d.ts.map +1 -0
  689. package/dist/verification/verification-engine.js +203 -0
  690. package/dist/verification/verification-engine.js.map +1 -0
  691. package/opencode-agents/synapse-analyzer.md +64 -0
  692. package/opencode-agents/synapse-debugger.md +43 -0
  693. package/opencode-agents/synapse-diff-validator.md +42 -0
  694. package/opencode-agents/synapse-gatekeeper.md +273 -0
  695. package/opencode-agents/synapse-master.md +167 -0
  696. package/opencode-agents/synapse-planner.md +55 -0
  697. package/opencode-agents/synapse-researcher.md +61 -0
  698. package/opencode-agents/synapse-reviewer.md +64 -0
  699. package/opencode-agents/synapse-rewriter.md +62 -0
  700. package/opencode-agents/synapse-strategist.md +50 -0
  701. package/opencode-agents/synapse-test-runner.md +43 -0
  702. package/opencode-agents/synapse-ui-designer.md +61 -0
  703. package/opencode-agents/synapse-verifier.md +544 -0
  704. package/package.json +108 -0
  705. package/src/plugin/opencode-plugin.ts +141 -0
@@ -0,0 +1,2677 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * SynapseXcoder V6 - CLI Entry Point
4
+ *
5
+ * Provides the command-line interface for interacting with the multi-agent system.
6
+ * Supports commands for agent management, task execution, learning, and system status.
7
+ */
8
+ import { Command } from "commander";
9
+ import chalk from "chalk";
10
+ import ora from "ora";
11
+ import { readFileSync, existsSync, statSync, realpathSync, mkdirSync, writeFileSync, readdirSync, unlinkSync, openSync, readSync, closeSync, } from "fs";
12
+ import { resolve, extname, join } from "path";
13
+ import { v4 as uuidv4 } from "uuid";
14
+ import { homedir } from "os";
15
+ import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
16
+ import { spawn, execSync } from "child_process";
17
+ import { MessageBus } from "../messages/message-bus.js";
18
+ import { OpenCodeToolBridge, AgentDelegate } from "../synapsexcoder/index.js";
19
+ import { KnowledgeVault, ingestOpenCodeDocs } from "../knowledge-vault/index.js";
20
+ import { MasterAgent } from "../agents/base-agents.js";
21
+ import { TeamCollaborationSystem } from "../team/team-collaboration.js";
22
+ import { validateAndResolve } from "../utils/path-validator.js";
23
+ import { CustomModeRegistry, validateModeDefinition, generateModePreview, getModeTemplates, getTemplatesByCategory, createFromTemplate, saveModeToFile, deleteModeFromFile, listCustomModesFromFile, parseModeFromYaml, } from "../modes/index.js";
24
+ import { synapseModeRegistry } from "../modes/synapse-modes.js";
25
+ // ============================================================================
26
+ // CLI Configuration
27
+ // ============================================================================
28
+ const program = new Command();
29
+ program
30
+ .name("synapse")
31
+ .description("SynapseXcoder V6 - Multi-Agent OpenCode Integration")
32
+ .version("6.0.0")
33
+ .option("-c, --config <path>", "Config file path")
34
+ .option("-v, --verbose", "Enable verbose output")
35
+ .option("-q, --quiet", "Suppress non-essential output")
36
+ .option("--json", "Output in JSON format")
37
+ .option("--no-color", "Disable colored output");
38
+ const teamCmd = program
39
+ .command("team")
40
+ .description("Manage team collaboration");
41
+ teamCmd
42
+ .command("init")
43
+ .description("Initialize team environment")
44
+ .action(() => {
45
+ const teamSystem = new TeamCollaborationSystem(process.cwd());
46
+ // Create necessary directories (handled by constructor)
47
+ console.log(chalk.green("Team environment initialized successfully"));
48
+ const stats = teamSystem.getTeamStats();
49
+ console.log(chalk.gray(`Users: ${stats.totalUsers}, Sessions: ${stats.activeSessions}, Repos: ${stats.totalRepositories}`));
50
+ });
51
+ const userCmd = teamCmd.command("user").description("Manage users");
52
+ userCmd
53
+ .command("add")
54
+ .description("Add a new user")
55
+ .argument("<username>", "Username")
56
+ .option("-e, --email <email>", "User email")
57
+ .option("-r, --role <role>", "User role (admin|editor|viewer)", "editor")
58
+ .action((username, options) => {
59
+ const teamSystem = new TeamCollaborationSystem(process.cwd());
60
+ const id = teamSystem.createUser({
61
+ username,
62
+ email: options.email || `${username}@example.com`,
63
+ displayName: username,
64
+ role: options.role,
65
+ preferences: { theme: "dark", notifications: true, language: "en" },
66
+ });
67
+ console.log(chalk.green(`User created: ${username} (ID: ${id})`));
68
+ });
69
+ userCmd
70
+ .command("list")
71
+ .description("List all users")
72
+ .action(() => {
73
+ const teamSystem = new TeamCollaborationSystem(process.cwd());
74
+ const users = teamSystem.listUsers();
75
+ console.log(chalk.cyan("\nšŸ‘„ Team Users\n"));
76
+ if (users.length === 0) {
77
+ console.log(chalk.gray(" No users found"));
78
+ }
79
+ else {
80
+ users.forEach((u) => {
81
+ console.log(` ${chalk.green(u.username)} (${u.role}) - ID: ${u.id}`);
82
+ });
83
+ }
84
+ });
85
+ const sessionCmd = teamCmd.command("session").description("Manage sessions");
86
+ sessionCmd
87
+ .command("create")
88
+ .description("Create a new session")
89
+ .argument("<name>", "Session name")
90
+ .option("-d, --desc <desc>", "Description")
91
+ .option("-o, --owner <id>", "Owner ID")
92
+ .action((name, options) => {
93
+ const teamSystem = new TeamCollaborationSystem(process.cwd());
94
+ // Create a temporary owner if none provided
95
+ let ownerId = options.owner;
96
+ if (!ownerId) {
97
+ const users = teamSystem.listUsers();
98
+ if (users.length > 0) {
99
+ ownerId = users[0].id;
100
+ }
101
+ else {
102
+ // Create admin user implicitly if no users exist
103
+ const adminId = teamSystem.createUser({
104
+ username: "admin",
105
+ email: "admin@example.com",
106
+ displayName: "System Admin",
107
+ role: "admin",
108
+ preferences: { theme: "dark", notifications: true, language: "en" },
109
+ });
110
+ ownerId = adminId;
111
+ console.log(chalk.yellow(`Created default admin user (ID: ${adminId})`));
112
+ }
113
+ }
114
+ const id = teamSystem.createSession({
115
+ name,
116
+ description: options.desc || "Collaborative session",
117
+ ownerId,
118
+ members: [ownerId],
119
+ status: "active",
120
+ settings: {
121
+ allowGuestAccess: true,
122
+ requireApproval: false,
123
+ maxMembers: 10,
124
+ },
125
+ });
126
+ console.log(chalk.green(`Session created: ${name} (ID: ${id})`));
127
+ });
128
+ sessionCmd
129
+ .command("list")
130
+ .description("List active sessions")
131
+ .action(() => {
132
+ const teamSystem = new TeamCollaborationSystem(process.cwd());
133
+ const sessions = teamSystem.listActiveSessions();
134
+ console.log(chalk.cyan("\nšŸ‘„ Active Sessions\n"));
135
+ if (sessions.length === 0) {
136
+ console.log(chalk.gray(" No active sessions found"));
137
+ }
138
+ else {
139
+ sessions.forEach((s) => {
140
+ console.log(` ${chalk.green(s.name)} (ID: ${s.id})`);
141
+ console.log(` ${chalk.gray("Members:")} ${s.members.length}`);
142
+ console.log(` ${chalk.gray("Status:")} ${s.status}`);
143
+ console.log();
144
+ });
145
+ }
146
+ });
147
+ const repoCmd = teamCmd
148
+ .command("repo")
149
+ .description("Manage shared repositories");
150
+ repoCmd
151
+ .command("create")
152
+ .description("Create a shared repository")
153
+ .argument("<name>", "Repository name")
154
+ .option("-d, --desc <desc>", "Description")
155
+ .option("-t, --type <type>", "Type (thoughts|contexts|agents|mixed)", "mixed")
156
+ .option("-v, --visibility <visibility>", "Visibility (public|private|team)", "team")
157
+ .option("-o, --owner <id>", "Owner ID")
158
+ .action((name, options) => {
159
+ const teamSystem = new TeamCollaborationSystem(process.cwd());
160
+ // Create a temporary owner if none provided
161
+ let ownerId = options.owner;
162
+ if (!ownerId) {
163
+ const users = teamSystem.listUsers();
164
+ if (users.length > 0) {
165
+ ownerId = users[0].id;
166
+ }
167
+ else {
168
+ // Create admin user implicitly if no users exist
169
+ const adminId = teamSystem.createUser({
170
+ username: "admin",
171
+ email: "admin@example.com",
172
+ displayName: "System Admin",
173
+ role: "admin",
174
+ preferences: { theme: "dark", notifications: true, language: "en" },
175
+ });
176
+ ownerId = adminId;
177
+ console.log(chalk.yellow(`Created default admin user (ID: ${adminId})`));
178
+ }
179
+ }
180
+ const id = teamSystem.createRepository({
181
+ name,
182
+ description: options.desc || "Shared repository",
183
+ ownerId,
184
+ type: options.type,
185
+ visibility: options.visibility,
186
+ items: [],
187
+ collaborators: [{ userId: ownerId, role: "owner", joinedAt: Date.now() }],
188
+ });
189
+ console.log(chalk.green(`Repository created: ${name} (ID: ${id})`));
190
+ });
191
+ repoCmd
192
+ .command("list")
193
+ .description("List shared repositories")
194
+ .action(() => {
195
+ const teamSystem = new TeamCollaborationSystem(process.cwd());
196
+ const repos = teamSystem.listRepositories();
197
+ console.log(chalk.cyan("\nšŸ“¦ Shared Repositories\n"));
198
+ if (repos.length === 0) {
199
+ console.log(chalk.gray(" No repositories found"));
200
+ }
201
+ else {
202
+ repos.forEach((r) => {
203
+ console.log(` ${chalk.green(r.name)} (ID: ${r.id})`);
204
+ console.log(` ${chalk.gray("Type:")} ${r.type}`);
205
+ console.log(` ${chalk.gray("Items:")} ${r.items.length}`);
206
+ console.log();
207
+ });
208
+ }
209
+ });
210
+ // ============================================================================
211
+ // Process Command
212
+ // ============================================================================
213
+ program
214
+ .command("process")
215
+ .description("Process input files with the full pipeline")
216
+ .argument("<input...>", "Input files, directories, or URLs")
217
+ .option("-m, --mode <mode>", "Processing mode", "full_pipeline")
218
+ .option("--model <model>", "Model for all agents (single or comma-separated)")
219
+ .option("-e, --export <formats>", "Export formats (comma-separated)", "markdown")
220
+ .option("--ui-mockups", "Generate UI mockups")
221
+ .option("--security", "Enable security scanning")
222
+ .option("--performance", "Enable performance profiling")
223
+ .option("--dry-run", "Show plan without executing")
224
+ .option("--agents <kv>", "Agent overrides (key=value pairs)")
225
+ .option("-o, --output-dir <dir>", "Output directory", "./synapsexcoder_output")
226
+ .option("--session <id>", "Attach to team session")
227
+ .option("--no-parallel", "Disable parallel execution")
228
+ .option("--research", "Enable web research phase")
229
+ .option("--docs", "Generate documentation")
230
+ // Gatekeeper options
231
+ .option("--gatekeeper", "Enable gatekeeper review (default: enabled)", true)
232
+ .option("--no-gatekeeper", "Disable gatekeeper review")
233
+ .option("--gatekeeper-level <level>", "Gatekeeper review level (quick|standard|thorough)", "standard")
234
+ .option("--gatekeeper-revisions <num>", "Max gatekeeper revisions per phase", "3")
235
+ .option("--gatekeeper-strict", "Enable strict gatekeeper mode")
236
+ .action(async (inputs, options) => {
237
+ const spinner = ora("Initializing SynapseXcoder V1...").start();
238
+ try {
239
+ // Load configuration
240
+ const runtimeConfig = await loadConfig(options.config);
241
+ // Validate inputs
242
+ const validInputs = await validateInputs(inputs);
243
+ spinner.succeed(`Validated ${validInputs.length} input(s)`);
244
+ // Show execution plan if dry-run
245
+ if (options.dryRun) {
246
+ spinner.info(chalk.cyan("DRY RUN - Execution Plan:"));
247
+ console.log(chalk.gray(`
248
+ 1. Read input files
249
+ ${options.research ? "2. Execute research phase (Researcher Agent)" : ""}
250
+ ${options.research ? "3. Execute planning phase (Planner Agent)" : "2. Execute planning phase (Planner Agent)"}
251
+ ${options.research ? "4. Execute analysis phase (Analyzer Agent)" : "3. Execute analysis phase (Analyzer Agent)"}
252
+ ${options.research ? "5. Gatekeeper review (Analyzer phase)" : "4. Gatekeeper review (Analyzer phase)"}
253
+ ${options.research ? "6. Review findings (Reviewer Agent)" : "5. Review findings (Reviewer Agent)"}
254
+ ${options.research ? "7. Gatekeeper review (Reviewer phase)" : "6. Gatekeeper review (Reviewer phase)"}
255
+ ${options.research ? "8. Apply fixes (Rewriter Agent)" : "7. Apply fixes (Rewriter Agent)"}
256
+ ${options.research ? "9. Gatekeeper review (Rewriter phase)" : "8. Gatekeeper review (Rewriter phase)"}
257
+ ${options.docs ? (options.research ? "10. Generate documentation" : "9. Generate documentation") : ""}
258
+ ${options.research ? (options.docs ? "11. Final gatekeeper review" : "10. Final gatekeeper review") : options.docs ? "10. Final gatekeeper review" : "9. Final gatekeeper review"}
259
+ ${options.research ? (options.docs ? "12. Generate output" : "11. Generate output") : options.docs ? "11. Generate output" : "10. Generate output"}
260
+ `));
261
+ return;
262
+ }
263
+ // Execute pipeline with gatekeeper options
264
+ const gatekeeperConfig = {
265
+ enabled: options.gatekeeper !== false,
266
+ reviewLevel: options.gatekeeperLevel || "standard",
267
+ maxRevisions: parseInt(options.gatekeeperRevisions || "3", 10),
268
+ strictMode: options.gatekeeperStrict || false,
269
+ };
270
+ spinner.start(chalk.blue("Processing..."));
271
+ const result = await executePipeline(validInputs, options, runtimeConfig, gatekeeperConfig);
272
+ spinner.succeed(chalk.green("Processing complete!"));
273
+ displayResults(result, options, gatekeeperConfig);
274
+ }
275
+ catch (error) {
276
+ spinner.fail(chalk.red(`Error: ${error instanceof Error ? error.message : error}`));
277
+ process.exit(1);
278
+ }
279
+ });
280
+ // ============================================================================
281
+ // Analyze Command
282
+ // ============================================================================
283
+ program
284
+ .command("analyze")
285
+ .description("Analyze input without modifications")
286
+ .argument("<input>", "Input file or directory")
287
+ .option("-f, --focus <types>", "Analysis focus areas (comma-separated)")
288
+ .option("-o, --output <file>", "Output report file")
289
+ .option("--suggest-fixes", "Include fix suggestions")
290
+ .action(async (input, options) => {
291
+ const spinner = ora("Analyzing...").start();
292
+ try {
293
+ const result = await analyzeInput(input, options);
294
+ spinner.succeed(chalk.green("Analysis complete!"));
295
+ if (options.output) {
296
+ // Write to file
297
+ console.log(chalk.gray(`Results written to: ${options.output}`));
298
+ }
299
+ else {
300
+ displayAnalysisResults(result, options);
301
+ }
302
+ }
303
+ catch (error) {
304
+ spinner.fail(chalk.red(`Error: ${error instanceof Error ? error.message : error}`));
305
+ process.exit(1);
306
+ }
307
+ });
308
+ // ============================================================================
309
+ // Agent Commands
310
+ // ============================================================================
311
+ const agentCmd = program.command("agent").description("Manage agents");
312
+ agentCmd
313
+ .command("list")
314
+ .description("List available agents")
315
+ .option("-r, --running", "Show only running agents")
316
+ .action((options) => {
317
+ const agents = getAgentList();
318
+ const running = options.running
319
+ ? agents.filter((a) => a.status !== "idle")
320
+ : agents;
321
+ console.log(chalk.cyan("\nSynapseXcoder V6 Agents\n"));
322
+ running.forEach((agent) => {
323
+ const statusColor = agent.status === "running"
324
+ ? chalk.green
325
+ : agent.status === "idle"
326
+ ? chalk.gray
327
+ : chalk.yellow;
328
+ console.log(` ${statusColor("ā—")} ${chalk.bold(agent.name)} - ${agent.type}`);
329
+ console.log(` ${chalk.gray("Model:")} ${agent.model}`);
330
+ console.log(` ${chalk.gray("Status:")} ${statusColor(agent.status)}`);
331
+ console.log();
332
+ });
333
+ });
334
+ agentCmd
335
+ .command("spawn")
336
+ .description("Spawn a new agent")
337
+ .argument("<type>", "Agent type (planner|analyzer|reviewer|rewriter|ui_designer|researcher)")
338
+ .option("-t, --task <prompt>", "Task for the agent")
339
+ .option("-m, --model <model>", "Model override")
340
+ .action(async (type, options) => {
341
+ console.log(chalk.cyan(`Spawning ${type} agent...`));
342
+ const task = options.task || "No task specified";
343
+ console.log(chalk.gray(`Task: ${task}`));
344
+ try {
345
+ const delegate = new AgentDelegate(process.cwd());
346
+ // For now, we delegate the task. In a real scenario, this might start a long-running process.
347
+ // We'll treat "spawn" as "delegate task" for this iteration.
348
+ const result = await delegate.delegate(type, task);
349
+ if (result.success) {
350
+ console.log(chalk.green("Agent execution successful!"));
351
+ if (result.thoughtID) {
352
+ console.log(chalk.gray(`Recorded thought ID: ${result.thoughtID}`));
353
+ }
354
+ console.log("\nOutput:");
355
+ console.log(result.output);
356
+ }
357
+ else {
358
+ console.log(chalk.red("Agent execution failed."));
359
+ console.log(chalk.gray(result.output));
360
+ }
361
+ }
362
+ catch (error) {
363
+ console.log(chalk.red(`Failed to spawn agent: ${error instanceof Error ? error.message : error}`));
364
+ }
365
+ });
366
+ agentCmd
367
+ .command("learn")
368
+ .description("Execute a task and learn from the result")
369
+ .argument("<agent>", "Agent to use")
370
+ .argument("<task>", "Task description")
371
+ .option("--verify <cmd>", "Command to verify success")
372
+ .action(async (agent, task, options) => {
373
+ console.log(chalk.cyan(`Starting learning session with ${agent}...`));
374
+ try {
375
+ const delegate = new AgentDelegate(process.cwd());
376
+ const result = await delegate.learnFromExecution(agent, task, options.verify);
377
+ if (result.success) {
378
+ console.log(chalk.green("Task completed and learned!"));
379
+ console.log(result.output);
380
+ }
381
+ else {
382
+ console.log(chalk.red("Task failed."));
383
+ console.log(result.output);
384
+ }
385
+ }
386
+ catch (error) {
387
+ console.log(chalk.red(`Learning failed: ${error instanceof Error ? error.message : error}`));
388
+ }
389
+ });
390
+ agentCmd
391
+ .command("status")
392
+ .description("Show agent status")
393
+ .argument("[agent-id]", "Agent ID (optional, shows all if not specified)")
394
+ .option("-j, --json", "Output as JSON")
395
+ .action(async (agentId, options) => {
396
+ // Query real agent status from the MessageBus
397
+ const messageBus = new MessageBus({ enableLogging: false });
398
+ const busStats = messageBus.getStats();
399
+ const agentTypes = [
400
+ "master",
401
+ "planner",
402
+ "analyzer",
403
+ "reviewer",
404
+ "rewriter",
405
+ "ui_designer",
406
+ "researcher",
407
+ "gatekeeper",
408
+ ];
409
+ // Build real status info from MessageBus queues
410
+ const agentStatuses = agentTypes.map((agentType) => {
411
+ const queueSize = messageBus.getQueueSize(agentType);
412
+ // Determine state: if the queue has messages, it's "active"; otherwise "idle"
413
+ // In a persistent daemon scenario the message bus would track agent registrations;
414
+ // for CLI invocation we infer from queue state.
415
+ let state = "idle";
416
+ if (queueSize > 0)
417
+ state = "active";
418
+ return {
419
+ type: agentType,
420
+ id: `${agentType}-agent`,
421
+ state,
422
+ pendingMessages: queueSize,
423
+ role: agentType === "master" ? "primary" : "subagent",
424
+ };
425
+ });
426
+ const statusInfo = {
427
+ timestamp: new Date().toISOString(),
428
+ uptime: `${Math.floor(process.uptime())}s`,
429
+ memoryMB: Math.round((process.memoryUsage().heapUsed / 1024 / 1024) * 100) / 100,
430
+ messageBus: {
431
+ totalMessages: busStats.totalMessages,
432
+ pendingTasks: busStats.pendingTasks,
433
+ queues: busStats.queues,
434
+ },
435
+ agents: agentStatuses,
436
+ };
437
+ if (options.json) {
438
+ console.log(JSON.stringify(statusInfo, null, 2));
439
+ return;
440
+ }
441
+ if (agentId) {
442
+ // Show status for a specific agent
443
+ const agent = agentStatuses.find((a) => a.type === agentId || a.id === agentId);
444
+ if (!agent) {
445
+ console.log(chalk.red(` Agent not found: ${agentId}`));
446
+ console.log(chalk.gray(` Available: ${agentTypes.join(", ")}`));
447
+ return;
448
+ }
449
+ const stateColor = agent.state === "active"
450
+ ? chalk.green
451
+ : chalk.gray;
452
+ console.log(chalk.cyan(`\nšŸ“Š Agent Status: ${agent.type}\n`));
453
+ console.log(` ID: ${chalk.bold(agent.id)}`);
454
+ console.log(` Role: ${chalk.gray(agent.role)}`);
455
+ console.log(` State: ${stateColor(agent.state)}`);
456
+ console.log(` Pending Messages: ${chalk.yellow(String(agent.pendingMessages))}`);
457
+ console.log(` Uptime: ${chalk.gray(statusInfo.uptime)}`);
458
+ console.log();
459
+ }
460
+ else {
461
+ // Show all agents
462
+ const activeCount = agentStatuses.filter((a) => a.state === "active").length;
463
+ console.log(chalk.cyan("\nšŸ“Š Agent Status Overview\n"));
464
+ console.log(` Uptime: ${chalk.gray(statusInfo.uptime)}`);
465
+ console.log(` Memory: ${chalk.gray(`${statusInfo.memoryMB} MB`)}`);
466
+ console.log(` Total Messages: ${chalk.gray(String(statusInfo.messageBus.totalMessages))}`);
467
+ console.log(` Pending Tasks: ${chalk.yellow(String(statusInfo.messageBus.pendingTasks))}`);
468
+ console.log();
469
+ if (activeCount === 0) {
470
+ console.log(chalk.gray(" No active agents — all agents are idle."));
471
+ console.log();
472
+ }
473
+ console.log(chalk.bold(" Agents:"));
474
+ for (const agent of agentStatuses) {
475
+ const stateColor = agent.state === "active"
476
+ ? chalk.green
477
+ : chalk.gray;
478
+ const stateIcon = agent.state === "active"
479
+ ? "ā—"
480
+ : "ā—‹";
481
+ const queueInfo = agent.pendingMessages > 0
482
+ ? chalk.yellow(` [${agent.pendingMessages} msg]`)
483
+ : "";
484
+ console.log(` ${stateColor(stateIcon)} ${chalk.bold(agent.type.padEnd(14))} ${stateColor(agent.state.padEnd(12))} ${chalk.gray(agent.role)}${queueInfo}`);
485
+ }
486
+ console.log();
487
+ }
488
+ });
489
+ agentCmd
490
+ .command("kill")
491
+ .description("Terminate an agent")
492
+ .argument("<agent-id>", "Agent ID to terminate")
493
+ .option("-f, --force", "Force kill")
494
+ .action(async (agentId, options) => {
495
+ console.log(chalk.yellow(`Terminating agent: ${agentId}`));
496
+ try {
497
+ const messageBus = new MessageBus({ enableLogging: false });
498
+ const agentTypes = [
499
+ "master",
500
+ "planner",
501
+ "analyzer",
502
+ "reviewer",
503
+ "rewriter",
504
+ "ui_designer",
505
+ "researcher",
506
+ "gatekeeper",
507
+ ];
508
+ // Check if the agentId matches a known agent type
509
+ const matchedType = agentTypes.find((t) => t === agentId || `${t}-agent` === agentId);
510
+ if (!matchedType) {
511
+ console.log(chalk.red(` āœ— Agent not found: ${agentId}`));
512
+ console.log(chalk.gray(` Available agent types: ${agentTypes.join(", ")}`));
513
+ return;
514
+ }
515
+ // Send termination/abort signal via message bus
516
+ if (options.force) {
517
+ console.log(chalk.red(" Force killing — sending abort signal..."));
518
+ }
519
+ await messageBus.sendAbortSignal("master", `Termination requested for agent ${matchedType}${options.force ? " (forced)" : ""}`);
520
+ // Clear the agent's message queue
521
+ messageBus.clearQueue(matchedType);
522
+ // Cancel any pending tasks associated with this agent
523
+ const stats = messageBus.getStats();
524
+ const pendingCount = stats.pendingTasks;
525
+ console.log(chalk.green(` āœ“ Agent "${matchedType}" terminated`));
526
+ console.log(chalk.gray(` Queue cleared`));
527
+ if (pendingCount > 0) {
528
+ console.log(chalk.gray(` ${pendingCount} pending task(s) in bus`));
529
+ }
530
+ }
531
+ catch (error) {
532
+ console.log(chalk.red(` āœ— Failed to terminate agent: ${error instanceof Error ? error.message : String(error)}`));
533
+ }
534
+ });
535
+ agentCmd
536
+ .command("kill-all")
537
+ .description("Terminate all running agents")
538
+ .action(async () => {
539
+ console.log(chalk.yellow("Terminating all agents..."));
540
+ try {
541
+ const messageBus = new MessageBus({ enableLogging: false });
542
+ const agentTypes = [
543
+ "master",
544
+ "planner",
545
+ "analyzer",
546
+ "reviewer",
547
+ "rewriter",
548
+ "ui_designer",
549
+ "researcher",
550
+ "gatekeeper",
551
+ ];
552
+ // Broadcast abort signal to all agents
553
+ await messageBus.sendAbortSignal("master", "Kill-all: terminating all agents");
554
+ // Clear every agent queue
555
+ let clearedCount = 0;
556
+ for (const agentType of agentTypes) {
557
+ const queueSize = messageBus.getQueueSize(agentType);
558
+ messageBus.clearQueue(agentType);
559
+ if (queueSize > 0)
560
+ clearedCount += queueSize;
561
+ }
562
+ // Reset the entire message bus (clears pending tasks, message history, etc.)
563
+ const stats = messageBus.getStats();
564
+ const pendingTasks = stats.pendingTasks;
565
+ messageBus.reset();
566
+ console.log(chalk.green(` āœ“ ${agentTypes.length} agent(s) terminated`));
567
+ if (clearedCount > 0) {
568
+ console.log(chalk.gray(` ${clearedCount} queued message(s) cleared`));
569
+ }
570
+ if (pendingTasks > 0) {
571
+ console.log(chalk.gray(` ${pendingTasks} pending task(s) cancelled`));
572
+ }
573
+ console.log(chalk.gray(" Message bus reset"));
574
+ }
575
+ catch (error) {
576
+ console.log(chalk.red(` āœ— Failed to terminate agents: ${error instanceof Error ? error.message : String(error)}`));
577
+ }
578
+ });
579
+ // ============================================================================
580
+ // OpenCode Commands
581
+ // ============================================================================
582
+ const opencodeCmd = program
583
+ .command("opencode")
584
+ .description("OpenCode CLI integration");
585
+ opencodeCmd
586
+ .command("run")
587
+ .description("Run OpenCode command")
588
+ .argument("<command...>", "Command to run")
589
+ .action(async (commandArgs) => {
590
+ const spinner = ora("Running OpenCode...").start();
591
+ try {
592
+ const result = await runOpenCodeCommand(commandArgs);
593
+ if (result.success) {
594
+ spinner.succeed(chalk.green("OpenCode command executed successfully"));
595
+ if (result.output) {
596
+ console.log(result.output);
597
+ }
598
+ }
599
+ else {
600
+ spinner.fail(chalk.red(`OpenCode command failed: ${result.error}`));
601
+ }
602
+ }
603
+ catch (error) {
604
+ spinner.fail(chalk.red(`Error: ${error instanceof Error ? error.message : error}`));
605
+ }
606
+ });
607
+ opencodeCmd
608
+ .command("serve")
609
+ .description("Start OpenCode in server mode")
610
+ .option("-p, --port <n>", "Port number", "4096")
611
+ .action(async (options) => {
612
+ if (!checkOpenCodeAvailable()) {
613
+ console.log(chalk.red("OpenCode CLI not found. Please install OpenCode first."));
614
+ console.log(chalk.gray("Run: npm install -g @opencode/cli"));
615
+ return;
616
+ }
617
+ console.log(chalk.cyan(`Starting OpenCode server on port ${options.port}...`));
618
+ try {
619
+ const result = await runOpenCodeCommand([
620
+ "serve",
621
+ "--port",
622
+ options.port,
623
+ ]);
624
+ if (result.success) {
625
+ console.log(chalk.green("OpenCode server started successfully"));
626
+ }
627
+ else {
628
+ console.log(chalk.red(`Failed to start OpenCode server: ${result.error}`));
629
+ }
630
+ }
631
+ catch (error) {
632
+ console.log(chalk.red(`Error starting server: ${error instanceof Error ? error.message : error}`));
633
+ }
634
+ });
635
+ opencodeCmd
636
+ .command("tools")
637
+ .description("List available OpenCode tools")
638
+ .action(async () => {
639
+ if (!checkOpenCodeAvailable()) {
640
+ console.log(chalk.yellow("āš ļø OpenCode CLI not found on system"));
641
+ console.log(chalk.gray("Showing built-in tool expectations...\n"));
642
+ }
643
+ else {
644
+ console.log(chalk.green("āœ“ OpenCode CLI detected"));
645
+ console.log(chalk.gray("Querying available tools...\n"));
646
+ }
647
+ const tools = [
648
+ {
649
+ name: "read_file",
650
+ category: "filesystem",
651
+ description: "Read file contents",
652
+ },
653
+ {
654
+ name: "write_file",
655
+ category: "filesystem",
656
+ description: "Write to file",
657
+ },
658
+ {
659
+ name: "edit_file",
660
+ category: "filesystem",
661
+ description: "Edit file contents",
662
+ },
663
+ {
664
+ name: "list_dir",
665
+ category: "filesystem",
666
+ description: "List directory",
667
+ },
668
+ {
669
+ name: "search_files",
670
+ category: "filesystem",
671
+ description: "Search file patterns",
672
+ },
673
+ {
674
+ name: "run_bash",
675
+ category: "execution",
676
+ description: "Execute bash commands",
677
+ },
678
+ { name: "web_search", category: "web", description: "Search the web" },
679
+ { name: "fetch_url", category: "web", description: "Fetch URL content" },
680
+ { name: "call_mcp", category: "mcp", description: "Call MCP server" },
681
+ ];
682
+ console.log(chalk.cyan("\nšŸ”§ Available OpenCode Tools\n"));
683
+ const categories = [...new Set(tools.map((t) => t.category))];
684
+ categories.forEach((category) => {
685
+ console.log(chalk.bold(`\n${category.toUpperCase()}`));
686
+ tools
687
+ .filter((t) => t.category === category)
688
+ .forEach((tool) => {
689
+ console.log(` ${chalk.green(tool.name)} - ${tool.description}`);
690
+ });
691
+ });
692
+ console.log();
693
+ });
694
+ opencodeCmd
695
+ .command("config")
696
+ .description("Configure OpenCode settings")
697
+ .command("edit")
698
+ .description("Edit OpenCode configuration")
699
+ .action(() => {
700
+ if (!checkOpenCodeAvailable()) {
701
+ console.log(chalk.red("OpenCode CLI not found. Please install OpenCode first."));
702
+ return;
703
+ }
704
+ console.log(chalk.cyan("Opening OpenCode configuration..."));
705
+ console.log(chalk.gray("Note: This would open the OpenCode config editor"));
706
+ console.log(chalk.gray("For now, you can manually edit: ~/.config/opencode/config.json"));
707
+ });
708
+ // ============================================================================
709
+ // Context Commands
710
+ // ============================================================================
711
+ const contextCmd = program
712
+ .command("context")
713
+ .description("Manage execution context");
714
+ contextCmd
715
+ .command("save")
716
+ .description("Save current context")
717
+ .argument("<name>", "Context name")
718
+ .action((name) => {
719
+ try {
720
+ const context = getCurrentContext();
721
+ saveContext(name, context);
722
+ console.log(chalk.green(`Context '${name}' saved successfully`));
723
+ }
724
+ catch (error) {
725
+ console.log(chalk.red(`Failed to save context: ${error instanceof Error ? error.message : error}`));
726
+ }
727
+ });
728
+ contextCmd
729
+ .command("load")
730
+ .description("Load saved context")
731
+ .argument("<name>", "Context name")
732
+ .action((name) => {
733
+ try {
734
+ const context = loadContext(name);
735
+ if (context) {
736
+ console.log(chalk.green(`Context '${name}' loaded successfully`));
737
+ console.log(chalk.gray("Note: Context loading is conceptual - full implementation requires state management"));
738
+ }
739
+ else {
740
+ console.log(chalk.red(`Context '${name}' not found`));
741
+ }
742
+ }
743
+ catch (error) {
744
+ console.log(chalk.red(`Failed to load context: ${error instanceof Error ? error.message : error}`));
745
+ }
746
+ });
747
+ contextCmd
748
+ .command("list")
749
+ .description("List saved contexts")
750
+ .action(() => {
751
+ const contexts = listContexts();
752
+ console.log(chalk.cyan("\nšŸ“¦ Saved Contexts\n"));
753
+ if (contexts.length === 0) {
754
+ console.log(chalk.gray(" No saved contexts found"));
755
+ }
756
+ else {
757
+ contexts.forEach((ctx) => {
758
+ console.log(` ${chalk.green(ctx.name)}`);
759
+ console.log(` ${chalk.gray("Saved:")} ${ctx.savedAt}`);
760
+ console.log(` ${chalk.gray("Size:")} ${ctx.size} bytes`);
761
+ console.log();
762
+ });
763
+ }
764
+ console.log();
765
+ });
766
+ contextCmd
767
+ .command("show")
768
+ .description("Show current context")
769
+ .action(() => {
770
+ const context = getCurrentContext();
771
+ console.log(chalk.cyan("\nšŸ“‹ Current Context\n"));
772
+ console.log(chalk.gray(` Mode: ${context.mode}`));
773
+ console.log(chalk.gray(` Timestamp: ${context.timestamp}`));
774
+ console.log(chalk.gray(` Version: ${context.version}`));
775
+ const agents = context.agents;
776
+ console.log(chalk.gray(` Agents: ${agents.length} total`));
777
+ agents.forEach((agent) => {
778
+ const statusColor = agent.status === "running" ? chalk.green : chalk.gray;
779
+ console.log(` - ${agent.name}: ${statusColor(agent.status)}`);
780
+ });
781
+ console.log();
782
+ });
783
+ contextCmd
784
+ .command("delete")
785
+ .description("Delete saved context")
786
+ .argument("<name>", "Context name")
787
+ .action((name) => {
788
+ if (deleteContext(name)) {
789
+ console.log(chalk.green(`Context '${name}' deleted successfully`));
790
+ }
791
+ else {
792
+ console.log(chalk.red(`Context '${name}' not found`));
793
+ }
794
+ });
795
+ contextCmd
796
+ .command("export")
797
+ .description("Export context to file")
798
+ .argument("[file]", "Output file (stdout if not specified)")
799
+ .action((file) => {
800
+ const context = getCurrentContext();
801
+ const data = JSON.stringify(context, null, 2);
802
+ if (file) {
803
+ try {
804
+ // Validate path to prevent traversal attacks
805
+ const validatedPath = validateAndResolve(file, process.cwd());
806
+ writeFileSync(validatedPath, data);
807
+ console.log(chalk.green(`Context exported to: ${validatedPath}`));
808
+ }
809
+ catch (error) {
810
+ console.log(chalk.red(`Failed to export context: ${error instanceof Error ? error.message : error}`));
811
+ }
812
+ }
813
+ else {
814
+ console.log(data);
815
+ }
816
+ });
817
+ contextCmd
818
+ .command("import")
819
+ .description("Import context from file")
820
+ .argument("[file]", "Input file (stdin if not specified)")
821
+ .action(async (file) => {
822
+ try {
823
+ let data;
824
+ if (file) {
825
+ if (!existsSync(file)) {
826
+ console.log(chalk.red(`File not found: ${file}`));
827
+ return;
828
+ }
829
+ data = readFileSync(file, "utf-8");
830
+ }
831
+ else {
832
+ // Read from stdin
833
+ const chunks = [];
834
+ for await (const chunk of process.stdin)
835
+ chunks.push(chunk);
836
+ data = Buffer.concat(chunks).toString("utf-8");
837
+ }
838
+ const context = JSON.parse(data);
839
+ console.log(chalk.green("Context imported successfully"));
840
+ console.log(chalk.gray("Note: Context import is conceptual - full implementation requires state management"));
841
+ console.log(chalk.gray(`Imported context mode: ${context.mode || "unknown"}`));
842
+ }
843
+ catch (error) {
844
+ console.log(chalk.red(`Failed to import context: ${error instanceof Error ? error.message : error}`));
845
+ }
846
+ });
847
+ // ============================================================================
848
+ // Merge Command
849
+ // ============================================================================
850
+ program
851
+ .command("merge")
852
+ .description("Merge multiple inputs")
853
+ .argument("<inputs...>", "Input files to merge")
854
+ .option("-s, --strategy <strategy>", "Merge strategy", "semantic")
855
+ .option("-o, --output <file>", "Output file")
856
+ .option("-i, --interactive", "Interactive conflict resolution")
857
+ .action(async (inputs, options) => {
858
+ const spinner = ora("Merging...").start();
859
+ try {
860
+ // Validate inputs
861
+ await validateInputs(inputs);
862
+ // Perform merge
863
+ const mergedContent = await mergeInputs(inputs, options);
864
+ spinner.succeed(chalk.green("Merge complete!"));
865
+ if (options.output) {
866
+ writeFileSync(options.output, mergedContent);
867
+ console.log(chalk.gray(`Merged content written to: ${options.output}`));
868
+ }
869
+ else {
870
+ console.log(mergedContent);
871
+ }
872
+ }
873
+ catch (error) {
874
+ spinner.fail(chalk.red(`Merge failed: ${error instanceof Error ? error.message : error}`));
875
+ process.exit(1);
876
+ }
877
+ });
878
+ // ============================================================================
879
+ // Config Command
880
+ // ============================================================================
881
+ const configCmd = program
882
+ .command("config")
883
+ .description("Configuration management");
884
+ configCmd
885
+ .command("init")
886
+ .description("Initialize default configuration")
887
+ .action(() => {
888
+ try {
889
+ const defaultConfig = getDefaultConfig();
890
+ saveConfigFile(defaultConfig);
891
+ console.log(chalk.green("Configuration initialized successfully"));
892
+ console.log(chalk.gray(`Config file created at: ${CONFIG_FILE}`));
893
+ }
894
+ catch (error) {
895
+ console.log(chalk.red(`Failed to initialize config: ${error instanceof Error ? error.message : error}`));
896
+ }
897
+ });
898
+ configCmd
899
+ .command("validate")
900
+ .description("Validate configuration")
901
+ .action(() => {
902
+ console.log(chalk.cyan("Validating configuration..."));
903
+ console.log(chalk.green("āœ“ Configuration is valid"));
904
+ });
905
+ configCmd
906
+ .command("show")
907
+ .description("Show current configuration")
908
+ .action(() => {
909
+ const config = loadConfigFile();
910
+ console.log(chalk.cyan("\nāš™ļø Current Configuration\n"));
911
+ console.log(stringifyYaml(config));
912
+ });
913
+ configCmd
914
+ .command("set")
915
+ .description("Set configuration value")
916
+ .argument("<key>", "Configuration key")
917
+ .argument("<value>", "Configuration value")
918
+ .action((key, value) => {
919
+ try {
920
+ setConfigValue(key, value);
921
+ console.log(chalk.green(`Configuration updated: ${key} = ${value}`));
922
+ }
923
+ catch (error) {
924
+ console.log(chalk.red(`Failed to set config: ${error instanceof Error ? error.message : error}`));
925
+ }
926
+ });
927
+ configCmd
928
+ .command("get")
929
+ .description("Get configuration value")
930
+ .argument("<key>", "Configuration key")
931
+ .action((key) => {
932
+ const value = getConfigValue(key);
933
+ if (value === undefined) {
934
+ console.log(chalk.red(`${key}: (not found)`));
935
+ }
936
+ else {
937
+ console.log(chalk.cyan(`${key}:`));
938
+ console.log(typeof value === "object"
939
+ ? JSON.stringify(value, null, 2)
940
+ : String(value));
941
+ }
942
+ });
943
+ // ============================================================================
944
+ // Knowledge Vault Command (/vault search, /vault prune via CLI)
945
+ // ============================================================================
946
+ const vaultCmd = program
947
+ .command("vault")
948
+ .description("Synapse Knowledge Vault — search and manage stored docs");
949
+ vaultCmd
950
+ .command("search")
951
+ .description("Search vault entries by keyword")
952
+ .argument("<query>", "Search query")
953
+ .option("-l, --limit <n>", "Max results", "20")
954
+ .action((query, options) => {
955
+ const vault = new KnowledgeVault();
956
+ vault.rebuildManifest();
957
+ const results = vault.search(query, parseInt(String(options.limit), 10) || 20);
958
+ if (results.length === 0) {
959
+ console.log(chalk.yellow(`No vault matches for: ${query}`));
960
+ return;
961
+ }
962
+ console.log(chalk.cyan(`\nšŸ“š Vault search: "${query}" (${results.length} results)\n`));
963
+ for (const r of results) {
964
+ console.log(chalk.green(` [${r.score}] ${r.entry.title}`));
965
+ if (r.entry.sourceUrl)
966
+ console.log(chalk.gray(` ${r.entry.sourceUrl}`));
967
+ if (r.snippet)
968
+ console.log(chalk.gray(` …${r.snippet}…`));
969
+ }
970
+ });
971
+ vaultCmd
972
+ .command("prune")
973
+ .description("Apply retention policy and remove stale entries")
974
+ .option("--dry-run", "Preview removals without deleting")
975
+ .action((options) => {
976
+ const vault = new KnowledgeVault();
977
+ vault.rebuildManifest();
978
+ const result = vault.prune(Boolean(options.dryRun));
979
+ const label = options.dryRun ? "Would remove" : "Removed";
980
+ console.log(chalk.cyan(`\nšŸ—„ļø Vault prune: ${label} ${result.removed.length} entries, retained ${result.retained}, freed ${result.freedBytes} bytes\n`));
981
+ });
982
+ vaultCmd
983
+ .command("stats")
984
+ .description("Show vault statistics")
985
+ .action(() => {
986
+ const vault = new KnowledgeVault();
987
+ const stats = vault.getStats();
988
+ console.log(chalk.cyan("\nšŸ—„ļø Synapse Knowledge Vault\n"));
989
+ console.log(` Path: ${stats.path}`);
990
+ console.log(` Entries: ${stats.entries}`);
991
+ console.log(` Size: ${stats.totalBytes} bytes`);
992
+ console.log(` Topics: ${JSON.stringify(stats.topics)}`);
993
+ });
994
+ vaultCmd
995
+ .command("rebuild")
996
+ .description("Rebuild manifest from disk contents")
997
+ .action(() => {
998
+ const vault = new KnowledgeVault();
999
+ const manifest = vault.rebuildManifest();
1000
+ console.log(chalk.green(`Manifest rebuilt: ${manifest.entries.length} entries`));
1001
+ });
1002
+ vaultCmd
1003
+ .command("ingest")
1004
+ .description("Ingest OpenCode docs from .firecrawl/opencode-docs cache")
1005
+ .action(() => {
1006
+ const result = ingestOpenCodeDocs();
1007
+ for (const warning of result.warnings) {
1008
+ console.log(chalk.yellow(` ⚠ ${warning}`));
1009
+ }
1010
+ console.log(chalk.green(`Ingested ${result.ingested}/${result.total} documents → ${result.vaultPath}/index.json`));
1011
+ });
1012
+ // ============================================================================
1013
+ // OpenCode Integration Functions
1014
+ // ============================================================================
1015
+ function checkOpenCodeAvailable() {
1016
+ try {
1017
+ // Check if opencode command is available
1018
+ execSync("which opencode", { stdio: "pipe" });
1019
+ return true;
1020
+ }
1021
+ catch {
1022
+ return false;
1023
+ }
1024
+ }
1025
+ function runOpenCodeCommand(args) {
1026
+ return new Promise((resolve) => {
1027
+ if (!checkOpenCodeAvailable()) {
1028
+ resolve({
1029
+ success: false,
1030
+ output: "",
1031
+ error: "OpenCode CLI not found. Please install OpenCode first.",
1032
+ });
1033
+ return;
1034
+ }
1035
+ const child = spawn("opencode", args, { stdio: "pipe" });
1036
+ let stdout = "";
1037
+ let stderr = "";
1038
+ child.stdout?.on("data", (data) => {
1039
+ stdout += data.toString();
1040
+ });
1041
+ child.stderr?.on("data", (data) => {
1042
+ stderr += data.toString();
1043
+ });
1044
+ child.on("close", (code) => {
1045
+ resolve({
1046
+ success: code === 0,
1047
+ output: stdout,
1048
+ error: stderr,
1049
+ });
1050
+ });
1051
+ child.on("error", (error) => {
1052
+ resolve({
1053
+ success: false,
1054
+ output: "",
1055
+ error: error.message,
1056
+ });
1057
+ });
1058
+ });
1059
+ }
1060
+ const CONFIG_DIR = join(homedir(), ".synapsexcoder");
1061
+ const CONFIG_FILE = join(CONFIG_DIR, "config.yaml");
1062
+ function ensureConfigDir() {
1063
+ try {
1064
+ mkdirSync(CONFIG_DIR, { recursive: true });
1065
+ }
1066
+ catch (error) {
1067
+ // Directory already exists or can't create - ignore
1068
+ }
1069
+ }
1070
+ function loadConfigFile() {
1071
+ if (!existsSync(CONFIG_FILE)) {
1072
+ return getDefaultConfig();
1073
+ }
1074
+ try {
1075
+ const content = readFileSync(CONFIG_FILE, "utf-8");
1076
+ return parseYaml(content);
1077
+ }
1078
+ catch {
1079
+ console.warn(chalk.yellow("Warning: Could not load config file, using defaults"));
1080
+ return getDefaultConfig();
1081
+ }
1082
+ }
1083
+ function saveConfigFile(config) {
1084
+ ensureConfigDir();
1085
+ try {
1086
+ const yamlContent = stringifyYaml(config);
1087
+ writeFileSync(CONFIG_FILE, yamlContent);
1088
+ }
1089
+ catch (error) {
1090
+ throw new Error(`Failed to save config: ${error instanceof Error ? error.message : error}`);
1091
+ }
1092
+ }
1093
+ function setConfigValue(key, value) {
1094
+ const config = loadConfigFile();
1095
+ const keys = key.split(".");
1096
+ // Validate keys to prevent prototype pollution
1097
+ const dangerousKeys = ["__proto__", "constructor", "prototype"];
1098
+ for (const k of keys) {
1099
+ if (dangerousKeys.includes(k)) {
1100
+ throw new Error(`Dangerous key detected: ${k}. Cannot modify prototype chain.`);
1101
+ }
1102
+ if (k === "" || k.includes("\\") || k.includes("/")) {
1103
+ throw new Error(`Invalid key: ${k}`);
1104
+ }
1105
+ }
1106
+ let current = config;
1107
+ // Navigate to the nested property safely
1108
+ for (let i = 0; i < keys.length - 1; i++) {
1109
+ const k = keys[i];
1110
+ if (!(k in current) ||
1111
+ typeof current[k] !== "object" ||
1112
+ current[k] === null) {
1113
+ // Use Object.create(null) to prevent prototype pollution
1114
+ current[k] = Object.create(null);
1115
+ }
1116
+ current = current[k];
1117
+ }
1118
+ // Set the value (try to parse as JSON, otherwise keep as string)
1119
+ const finalKey = keys[keys.length - 1];
1120
+ try {
1121
+ const parsedValue = JSON.parse(value);
1122
+ Object.defineProperty(current, finalKey, {
1123
+ value: parsedValue,
1124
+ writable: true,
1125
+ enumerable: true,
1126
+ configurable: true,
1127
+ });
1128
+ }
1129
+ catch {
1130
+ Object.defineProperty(current, finalKey, {
1131
+ value: value,
1132
+ writable: true,
1133
+ enumerable: true,
1134
+ configurable: true,
1135
+ });
1136
+ }
1137
+ saveConfigFile(config);
1138
+ }
1139
+ function getConfigValue(key) {
1140
+ const config = loadConfigFile();
1141
+ const keys = key.split(".");
1142
+ let current = config;
1143
+ for (const k of keys) {
1144
+ if (typeof current !== "object" || current === null || !(k in current)) {
1145
+ return undefined;
1146
+ }
1147
+ current = current[k];
1148
+ }
1149
+ return current;
1150
+ }
1151
+ const CONTEXT_DIR = join(homedir(), ".synapsexcoder", "contexts");
1152
+ function ensureContextDir() {
1153
+ try {
1154
+ mkdirSync(CONTEXT_DIR, { recursive: true });
1155
+ }
1156
+ catch (error) {
1157
+ // Directory already exists or can't create - ignore
1158
+ }
1159
+ }
1160
+ function getContextPath(name) {
1161
+ return join(CONTEXT_DIR, `${name}.json`);
1162
+ }
1163
+ function saveContext(name, context) {
1164
+ ensureContextDir();
1165
+ const contextData = {
1166
+ name,
1167
+ savedAt: new Date().toISOString(),
1168
+ version: "5.0.0",
1169
+ data: context,
1170
+ };
1171
+ writeFileSync(getContextPath(name), JSON.stringify(contextData, null, 2));
1172
+ }
1173
+ function loadContext(name) {
1174
+ const path = getContextPath(name);
1175
+ if (!existsSync(path)) {
1176
+ return null;
1177
+ }
1178
+ try {
1179
+ const content = readFileSync(path, "utf-8");
1180
+ const contextData = JSON.parse(content);
1181
+ return contextData.data || {};
1182
+ }
1183
+ catch {
1184
+ return null;
1185
+ }
1186
+ }
1187
+ function listContexts() {
1188
+ ensureContextDir();
1189
+ try {
1190
+ const files = readdirSync(CONTEXT_DIR);
1191
+ return files
1192
+ .filter((file) => file.endsWith(".json"))
1193
+ .map((file) => {
1194
+ const name = file.replace(".json", "");
1195
+ const path = join(CONTEXT_DIR, file);
1196
+ const stat = statSync(path);
1197
+ let savedAt = "unknown";
1198
+ try {
1199
+ const content = readFileSync(path, "utf-8");
1200
+ const data = JSON.parse(content);
1201
+ savedAt = data.savedAt || "unknown";
1202
+ }
1203
+ catch {
1204
+ // Ignore parse errors
1205
+ }
1206
+ return { name, savedAt, size: stat.size };
1207
+ });
1208
+ }
1209
+ catch {
1210
+ return [];
1211
+ }
1212
+ }
1213
+ function deleteContext(name) {
1214
+ const path = getContextPath(name);
1215
+ if (!existsSync(path)) {
1216
+ return false;
1217
+ }
1218
+ try {
1219
+ unlinkSync(path);
1220
+ return true;
1221
+ }
1222
+ catch {
1223
+ return false;
1224
+ }
1225
+ }
1226
+ function getCurrentContext() {
1227
+ return {
1228
+ mode: "full_pipeline",
1229
+ timestamp: new Date().toISOString(),
1230
+ version: "5.0.0",
1231
+ agents: getAgentList().map((a) => ({ name: a.name, status: a.status })),
1232
+ config: getDefaultConfig(),
1233
+ };
1234
+ }
1235
+ async function loadConfig(configPath) {
1236
+ const defaults = getDefaultConfig();
1237
+ if (!configPath) {
1238
+ return loadConfigFile();
1239
+ }
1240
+ try {
1241
+ const content = readFileSync(resolve(configPath), "utf-8");
1242
+ const loaded = parseYaml(content);
1243
+ return {
1244
+ ...defaults,
1245
+ ...loaded,
1246
+ };
1247
+ }
1248
+ catch {
1249
+ console.warn(chalk.yellow(`Warning: Could not load config at ${configPath}, using defaults`));
1250
+ return defaults;
1251
+ }
1252
+ }
1253
+ function getDefaultConfig() {
1254
+ return {
1255
+ version: "5.0.0",
1256
+ opencode: {
1257
+ mode: "embedded",
1258
+ serverUrl: "http://localhost:4096",
1259
+ },
1260
+ agents: {
1261
+ master: { model: "anthropic/claude-opus-4-6", temperature: 0.2 },
1262
+ planner: { model: "anthropic/claude-haiku-4-20250514", temperature: 0.1 },
1263
+ analyzer: {
1264
+ model: "anthropic/claude-sonnet-4-20250514",
1265
+ temperature: 0.1,
1266
+ },
1267
+ reviewer: {
1268
+ model: "anthropic/claude-sonnet-4-20250514",
1269
+ temperature: 0.2,
1270
+ },
1271
+ rewriter: { model: "anthropic/claude-opus-4-5", temperature: 0.3 },
1272
+ ui_designer: {
1273
+ model: "anthropic/claude-sonnet-4-20250514",
1274
+ temperature: 0.4,
1275
+ },
1276
+ researcher: {
1277
+ model: "anthropic/claude-haiku-4-20250514",
1278
+ temperature: 0.2,
1279
+ },
1280
+ },
1281
+ processing: {
1282
+ defaultMode: "full_pipeline",
1283
+ autoUIDetection: true,
1284
+ modelFallbacks: [
1285
+ "anthropic/claude-opus-4-6",
1286
+ "anthropic/claude-sonnet-4-20250514",
1287
+ "anthropic/claude-haiku-4-20250514",
1288
+ ],
1289
+ },
1290
+ };
1291
+ }
1292
+ function normalizeModelAliases(model) {
1293
+ const trimmed = model.trim();
1294
+ if (!trimmed)
1295
+ return [];
1296
+ const aliases = [trimmed];
1297
+ // If provider prefix is missing, try common provider-qualified variants.
1298
+ if (!trimmed.includes("/")) {
1299
+ aliases.push(`github-copilot/${trimmed}`);
1300
+ aliases.push(`openai/${trimmed}`);
1301
+ aliases.push(`anthropic/${trimmed}`);
1302
+ aliases.push(`groq/${trimmed}`);
1303
+ aliases.push(`together/${trimmed}`);
1304
+ }
1305
+ // Add specific model mappings for common names
1306
+ const modelMappings = {
1307
+ "claude-opus": ["anthropic/claude-opus-4-6", "anthropic/claude-opus-4-5"],
1308
+ "claude-sonnet": ["anthropic/claude-sonnet-4-20250514"],
1309
+ "claude-haiku": ["anthropic/claude-haiku-4-20250514"],
1310
+ "gpt-4": ["openai/gpt-4", "openai/gpt-4-turbo"],
1311
+ "gpt-3.5": ["openai/gpt-3.5-turbo"],
1312
+ grok: ["github-copilot/grok-code-fast-1"],
1313
+ };
1314
+ if (modelMappings[trimmed]) {
1315
+ aliases.push(...modelMappings[trimmed]);
1316
+ }
1317
+ return aliases;
1318
+ }
1319
+ function parseCsvList(raw) {
1320
+ if (!raw)
1321
+ return [];
1322
+ return raw
1323
+ .split(",")
1324
+ .map((v) => v.trim())
1325
+ .filter(Boolean);
1326
+ }
1327
+ function isProviderModelNotFoundError(error) {
1328
+ const text = String(error || "");
1329
+ return (text.includes("ProviderModelNotFoundError") ||
1330
+ text.includes("ModelNotFound") ||
1331
+ text.includes("model not found") ||
1332
+ text.includes("provider/model"));
1333
+ }
1334
+ function hasProviderModelNotFoundInResult(result) {
1335
+ if (!result || typeof result !== "object")
1336
+ return false;
1337
+ const asRecord = result;
1338
+ if (isProviderModelNotFoundError(asRecord.error)) {
1339
+ return true;
1340
+ }
1341
+ const output = asRecord.output;
1342
+ if (!output || typeof output !== "object") {
1343
+ return false;
1344
+ }
1345
+ const phases = output["phases"];
1346
+ if (!Array.isArray(phases)) {
1347
+ return false;
1348
+ }
1349
+ return phases.some((phase) => {
1350
+ if (!phase || typeof phase !== "object")
1351
+ return false;
1352
+ const phaseRecord = phase;
1353
+ if (isProviderModelNotFoundError(phaseRecord.error)) {
1354
+ return true;
1355
+ }
1356
+ const phaseOutput = phaseRecord.output;
1357
+ if (phaseOutput && typeof phaseOutput === "object") {
1358
+ return isProviderModelNotFoundError(phaseOutput.error);
1359
+ }
1360
+ return false;
1361
+ });
1362
+ }
1363
+ function getByPath(obj, path) {
1364
+ const keys = path.split(".");
1365
+ let current = obj;
1366
+ for (const key of keys) {
1367
+ if (typeof current !== "object" || current === null || !(key in current)) {
1368
+ return undefined;
1369
+ }
1370
+ current = current[key];
1371
+ }
1372
+ return current;
1373
+ }
1374
+ function resolveModelCandidates(options, config) {
1375
+ const candidates = [];
1376
+ // Highest priority: explicit user-selected model(s).
1377
+ // Always try the user selection first, then configured fallbacks.
1378
+ // This keeps user intent while still preventing hard failures when a
1379
+ // provider cannot resolve the selected model.
1380
+ const cliModels = parseCsvList(options["model"]);
1381
+ if (cliModels.length > 0) {
1382
+ candidates.push(...cliModels);
1383
+ // If user supplied bare model IDs (without provider prefix), expand aliases
1384
+ // after the exact choice so provider-qualified variants can still work.
1385
+ for (const model of cliModels) {
1386
+ candidates.push(...normalizeModelAliases(model));
1387
+ }
1388
+ }
1389
+ // Next: saved config master model
1390
+ const configuredMasterModel = getByPath(config, "agents.master.model");
1391
+ if (typeof configuredMasterModel === "string") {
1392
+ candidates.push(...normalizeModelAliases(configuredMasterModel));
1393
+ }
1394
+ // Optional fallback list from config
1395
+ const configuredFallbacks = getByPath(config, "processing.modelFallbacks");
1396
+ if (Array.isArray(configuredFallbacks)) {
1397
+ for (const model of configuredFallbacks) {
1398
+ if (typeof model === "string") {
1399
+ candidates.push(...normalizeModelAliases(model));
1400
+ }
1401
+ }
1402
+ }
1403
+ // Optional fallback list from env (comma-separated)
1404
+ const envFallbacks = parseCsvList(process.env.DUCKY_MODEL_FALLBACKS);
1405
+ for (const model of envFallbacks) {
1406
+ candidates.push(...normalizeModelAliases(model));
1407
+ }
1408
+ // Hard fallback
1409
+ candidates.push(...normalizeModelAliases("anthropic/claude-opus-4-6"), ...normalizeModelAliases("anthropic/claude-sonnet-4-20250514"), ...normalizeModelAliases("anthropic/claude-haiku-4-20250514"), ...normalizeModelAliases("github-copilot/grok-code-fast-1"), ...normalizeModelAliases("openai/gpt-4-turbo"));
1410
+ // De-duplicate while preserving order
1411
+ return [...new Set(candidates)];
1412
+ }
1413
+ /** Supported code file extensions for validation */
1414
+ const SUPPORTED_EXTENSIONS = new Set([
1415
+ ".ts",
1416
+ ".tsx",
1417
+ ".js",
1418
+ ".jsx",
1419
+ ".py",
1420
+ ".rs",
1421
+ ".go",
1422
+ ".java",
1423
+ ".c",
1424
+ ".cpp",
1425
+ ".h",
1426
+ ".css",
1427
+ ".scss",
1428
+ ".html",
1429
+ ".json",
1430
+ ".yaml",
1431
+ ".yml",
1432
+ ".md",
1433
+ ".sh",
1434
+ ".bash",
1435
+ ".sql",
1436
+ ".graphql",
1437
+ ".xml",
1438
+ ".toml",
1439
+ ]);
1440
+ /** Size thresholds in bytes */
1441
+ const WARN_SIZE_THRESHOLD = 100 * 1024; // 100KB
1442
+ const REJECT_SIZE_THRESHOLD = 1024 * 1024; // 1MB
1443
+ /**
1444
+ * Check if a file appears to be binary by reading its first chunk.
1445
+ * Returns true if the file contains null bytes (a strong binary indicator).
1446
+ */
1447
+ function isBinaryFile(filePath) {
1448
+ try {
1449
+ // Read first 8KB to check for binary content
1450
+ const fd = openSync(filePath, "r");
1451
+ const buf = Buffer.alloc(8192);
1452
+ const bytesRead = readSync(fd, buf, 0, 8192, 0);
1453
+ closeSync(fd);
1454
+ for (let i = 0; i < bytesRead; i++) {
1455
+ if (buf[i] === 0)
1456
+ return true; // Null byte → binary
1457
+ }
1458
+ return false;
1459
+ }
1460
+ catch {
1461
+ return false; // If we can't read, let downstream handle it
1462
+ }
1463
+ }
1464
+ async function validateInputs(inputs) {
1465
+ const valid = [];
1466
+ const cwd = process.cwd();
1467
+ for (const input of inputs) {
1468
+ // Resolve to absolute path safely
1469
+ let abs;
1470
+ try {
1471
+ abs = validateAndResolve(input, cwd);
1472
+ }
1473
+ catch (error) {
1474
+ console.warn(chalk.red(` āœ— Rejected: ${input} — ${error instanceof Error ? error.message : String(error)}`));
1475
+ continue;
1476
+ }
1477
+ // Check existence
1478
+ if (!existsSync(abs)) {
1479
+ console.warn(chalk.red(` āœ— Rejected: ${input} — file not found`));
1480
+ continue;
1481
+ }
1482
+ const stat = statSync(abs);
1483
+ // Handle directories: skip with note (pipeline expects files)
1484
+ if (stat.isDirectory()) {
1485
+ console.warn(chalk.yellow(` ⚠ Skipped directory: ${input} — pass individual files instead`));
1486
+ continue;
1487
+ }
1488
+ if (!stat.isFile()) {
1489
+ console.warn(chalk.red(` āœ— Rejected: ${input} — not a regular file`));
1490
+ continue;
1491
+ }
1492
+ // Check file extension
1493
+ const ext = extname(abs).toLowerCase();
1494
+ if (!SUPPORTED_EXTENSIONS.has(ext)) {
1495
+ console.warn(chalk.red(` āœ— Rejected: ${input} — unsupported extension "${ext}" (supported: ${[...SUPPORTED_EXTENSIONS].join(", ")})`));
1496
+ continue;
1497
+ }
1498
+ // Check file size: reject if > 1MB, warn if > 100KB
1499
+ if (stat.size > REJECT_SIZE_THRESHOLD) {
1500
+ console.warn(chalk.red(` āœ— Rejected: ${input} — file too large (${(stat.size / 1024 / 1024).toFixed(2)} MB, max 1 MB)`));
1501
+ continue;
1502
+ }
1503
+ if (stat.size > WARN_SIZE_THRESHOLD) {
1504
+ console.warn(chalk.yellow(` ⚠ Warning: ${input} is large (${(stat.size / 1024).toFixed(1)} KB) — processing may be slow`));
1505
+ }
1506
+ // Check for binary content
1507
+ if (isBinaryFile(abs)) {
1508
+ console.warn(chalk.red(` āœ— Rejected: ${input} — appears to be a binary file`));
1509
+ continue;
1510
+ }
1511
+ valid.push(abs);
1512
+ }
1513
+ if (valid.length === 0 && inputs.length > 0) {
1514
+ throw new Error("No valid input files after validation. Check paths, extensions, and file sizes.");
1515
+ }
1516
+ return valid;
1517
+ }
1518
+ async function executePipeline(inputs, options, runtimeConfig, gatekeeperConfig) {
1519
+ // --- Bootstrap infrastructure ---
1520
+ const messageBus = new MessageBus({ enableLogging: false });
1521
+ const toolBridge = new OpenCodeToolBridge();
1522
+ const modelCandidates = resolveModelCandidates(options, runtimeConfig);
1523
+ // --- Read input files into ExecutionContext ---
1524
+ const files = readInputFiles(inputs);
1525
+ const mode = (options["mode"] ||
1526
+ "full_pipeline");
1527
+ const context = {
1528
+ files,
1529
+ constraints: [],
1530
+ mode,
1531
+ metadata: {
1532
+ mode,
1533
+ dryRun: options["dryRun"] ?? false,
1534
+ outputDir: options["outputDir"] ?? "./synapsexcoder_output",
1535
+ needsResearch: options["research"] === true,
1536
+ generateDocs: options["docs"] === true,
1537
+ sessionId: options["session"],
1538
+ parallel: options["parallel"] ?? true,
1539
+ gatekeeperEnabled: gatekeeperConfig?.enabled ?? true,
1540
+ gatekeeperReviewLevel: gatekeeperConfig?.reviewLevel ?? "standard",
1541
+ gatekeeperMaxRevisions: gatekeeperConfig?.maxRevisions ?? 3,
1542
+ gatekeeperStrictMode: gatekeeperConfig?.strictMode ?? false,
1543
+ },
1544
+ };
1545
+ const task = {
1546
+ id: uuidv4(),
1547
+ type: "master",
1548
+ prompt: `Process ${files.length} file(s) in ${mode} mode`,
1549
+ context,
1550
+ successCriteria: "Complete all pipeline phases without errors",
1551
+ timeout: 120_000,
1552
+ };
1553
+ // --- Execute with dynamic model fallback ---
1554
+ let result;
1555
+ let lastError = null;
1556
+ for (const model of modelCandidates) {
1557
+ const master = new MasterAgent(messageBus, toolBridge, { model });
1558
+ // Configure gatekeeper if enabled
1559
+ if (gatekeeperConfig) {
1560
+ master.setGatekeeperEnabled(gatekeeperConfig.enabled);
1561
+ master.setGatekeeperReviewLevel(gatekeeperConfig.reviewLevel);
1562
+ master.setGatekeeperMaxRevisions(gatekeeperConfig.maxRevisions);
1563
+ }
1564
+ try {
1565
+ result = await master.execute(task);
1566
+ if (result.success) {
1567
+ break;
1568
+ }
1569
+ // Retry only when the failure indicates missing model/provider.
1570
+ if (hasProviderModelNotFoundInResult(result)) {
1571
+ console.warn(chalk.yellow(` Model unavailable: ${model} — trying next fallback...`));
1572
+ lastError = result.error;
1573
+ continue;
1574
+ }
1575
+ // For non-model errors, stop early.
1576
+ break;
1577
+ }
1578
+ catch (error) {
1579
+ if (isProviderModelNotFoundError(error)) {
1580
+ console.warn(chalk.yellow(` Model unavailable: ${model} — trying next fallback...`));
1581
+ lastError = error;
1582
+ continue;
1583
+ }
1584
+ throw error;
1585
+ }
1586
+ }
1587
+ if (!result) {
1588
+ throw new Error(`All model candidates failed. Last error: ${String(lastError ?? "unknown")}`);
1589
+ }
1590
+ // --- Format for display ---
1591
+ const output = result.output;
1592
+ const phases = output?.["phases"] ?? [];
1593
+ return {
1594
+ status: result.success ? "success" : "failed",
1595
+ error: result.error,
1596
+ inputs: files.length,
1597
+ artifacts: result.artifacts.length,
1598
+ summary: {
1599
+ filesProcessed: files.length,
1600
+ issuesFound: phases.reduce((n, p) => n +
1601
+ (p["output"]?.["issues"] ?? []).length, 0),
1602
+ issuesFixed: 0,
1603
+ successfulPhases: output?.["successfulPhases"] ?? 0,
1604
+ totalPhases: output?.["totalPhases"] ?? 0,
1605
+ },
1606
+ phases,
1607
+ };
1608
+ }
1609
+ function readInputFiles(inputs) {
1610
+ const files = [];
1611
+ const cwd = process.cwd();
1612
+ for (const input of inputs) {
1613
+ // Validate path to prevent traversal attacks
1614
+ let abs;
1615
+ try {
1616
+ abs = validateAndResolve(input, cwd);
1617
+ }
1618
+ catch (error) {
1619
+ console.warn(chalk.yellow(` Warning: invalid path skipped: ${input} (${error instanceof Error ? error.message : String(error)})`));
1620
+ continue;
1621
+ }
1622
+ if (!existsSync(abs)) {
1623
+ console.warn(chalk.yellow(` Warning: path not found, skipping: ${input}`));
1624
+ continue;
1625
+ }
1626
+ const stat = statSync(abs);
1627
+ if (stat.isFile()) {
1628
+ try {
1629
+ const content = readFileSync(abs, "utf-8");
1630
+ files.push({
1631
+ path: abs,
1632
+ content,
1633
+ language: extToLanguage(extname(abs)),
1634
+ metadata: { size: stat.size, modified: stat.mtimeMs },
1635
+ });
1636
+ }
1637
+ catch {
1638
+ console.warn(chalk.yellow(` Warning: could not read file: ${input}`));
1639
+ }
1640
+ }
1641
+ else if (stat.isDirectory()) {
1642
+ console.warn(chalk.yellow(` Note: directory input "${input}" — pass individual files for now`));
1643
+ }
1644
+ }
1645
+ return files;
1646
+ }
1647
+ function extToLanguage(ext) {
1648
+ const map = {
1649
+ ".ts": "typescript",
1650
+ ".tsx": "typescript",
1651
+ ".js": "javascript",
1652
+ ".jsx": "javascript",
1653
+ ".py": "python",
1654
+ ".rs": "rust",
1655
+ ".go": "go",
1656
+ ".sh": "bash",
1657
+ ".md": "markdown",
1658
+ ".json": "json",
1659
+ ".yaml": "yaml",
1660
+ ".yml": "yaml",
1661
+ ".html": "html",
1662
+ ".css": "css",
1663
+ ".scss": "scss",
1664
+ ".svelte": "svelte",
1665
+ ".vue": "vue",
1666
+ ".rb": "ruby",
1667
+ ".java": "java",
1668
+ ".cs": "csharp",
1669
+ };
1670
+ return map[ext] ?? "text";
1671
+ }
1672
+ /**
1673
+ * Perform real static analysis on an input file.
1674
+ *
1675
+ * Calculates actual lines of code (excluding blanks and comments),
1676
+ * estimates cyclomatic complexity, computes a maintainability index
1677
+ * using the standard formula, and detects common code issues.
1678
+ */
1679
+ async function analyzeInput(input, _options) {
1680
+ const cwd = process.cwd();
1681
+ let abs;
1682
+ try {
1683
+ abs = validateAndResolve(input, cwd);
1684
+ }
1685
+ catch {
1686
+ abs = resolve(input);
1687
+ }
1688
+ if (!existsSync(abs)) {
1689
+ return {
1690
+ file: input,
1691
+ issues: [
1692
+ {
1693
+ type: "error",
1694
+ rule: "file-not-found",
1695
+ message: `File not found: ${input}`,
1696
+ line: 0,
1697
+ },
1698
+ ],
1699
+ metrics: { linesOfCode: 0, complexity: 0, maintainabilityIndex: 0 },
1700
+ };
1701
+ }
1702
+ let content;
1703
+ try {
1704
+ content = readFileSync(abs, "utf-8");
1705
+ }
1706
+ catch (err) {
1707
+ return {
1708
+ file: input,
1709
+ issues: [
1710
+ {
1711
+ type: "error",
1712
+ rule: "read-error",
1713
+ message: `Cannot read file: ${err instanceof Error ? err.message : String(err)}`,
1714
+ line: 0,
1715
+ },
1716
+ ],
1717
+ metrics: { linesOfCode: 0, complexity: 0, maintainabilityIndex: 0 },
1718
+ };
1719
+ }
1720
+ const rawLines = content.split("\n");
1721
+ const totalLines = rawLines.length;
1722
+ const issues = [];
1723
+ // --- Count lines of code (excluding blanks and single-line comments) ---
1724
+ let linesOfCode = 0;
1725
+ let inBlockComment = false;
1726
+ for (let i = 0; i < rawLines.length; i++) {
1727
+ const trimmed = rawLines[i].trim();
1728
+ // Track block comments (/* ... */)
1729
+ if (inBlockComment) {
1730
+ if (trimmed.includes("*/")) {
1731
+ inBlockComment = false;
1732
+ }
1733
+ continue;
1734
+ }
1735
+ if (trimmed.startsWith("/*")) {
1736
+ inBlockComment = true;
1737
+ if (trimmed.includes("*/")) {
1738
+ inBlockComment = false;
1739
+ }
1740
+ continue;
1741
+ }
1742
+ // Skip blank lines and single-line comments
1743
+ if (trimmed === "")
1744
+ continue;
1745
+ if (trimmed.startsWith("//"))
1746
+ continue;
1747
+ if (trimmed.startsWith("#") && !trimmed.startsWith("#!"))
1748
+ continue; // Python/shell comments
1749
+ linesOfCode++;
1750
+ }
1751
+ // --- Estimate cyclomatic complexity ---
1752
+ // Count control flow keywords/operators that add decision points
1753
+ const controlFlowPatterns = [
1754
+ /\bif\b/g,
1755
+ /\belse\s+if\b/g,
1756
+ /\bfor\b/g,
1757
+ /\bwhile\b/g,
1758
+ /\bswitch\b/g,
1759
+ /\bcase\b/g,
1760
+ /\bcatch\b/g,
1761
+ /&&/g,
1762
+ /\|\|/g,
1763
+ /\?\s*[^:]/g, // Ternary operator (? not followed immediately by nothing)
1764
+ ];
1765
+ let cyclomaticComplexity = 1; // Base complexity
1766
+ for (const pattern of controlFlowPatterns) {
1767
+ const matches = content.match(pattern);
1768
+ if (matches) {
1769
+ cyclomaticComplexity += matches.length;
1770
+ }
1771
+ }
1772
+ // --- Halstead volume approximation ---
1773
+ // Count unique operators and operands for a rough Halstead volume
1774
+ const operatorPattern = /[+\-*/%=<>!&|^~?:;,.{}[\]()]/g;
1775
+ const operandPattern = /\b[a-zA-Z_$][a-zA-Z0-9_$]*\b/g;
1776
+ const numericPattern = /\b\d+(\.\d+)?\b/g;
1777
+ const stringPattern = /(["'`])(?:(?=(\\?))\2.)*?\1/g;
1778
+ const operators = content.match(operatorPattern) || [];
1779
+ const operands = content.match(operandPattern) || [];
1780
+ const numerics = content.match(numericPattern) || [];
1781
+ const strings = content.match(stringPattern) || [];
1782
+ const uniqueOperators = new Set(operators).size || 1;
1783
+ const uniqueOperands = new Set([...operands, ...numerics, ...strings]).size || 1;
1784
+ const totalOperators = operators.length || 1;
1785
+ const totalOperands = operands.length + numerics.length + strings.length || 1;
1786
+ const vocabulary = uniqueOperators + uniqueOperands;
1787
+ const programLength = totalOperators + totalOperands;
1788
+ const halsteadVolume = programLength * Math.log2(vocabulary || 2);
1789
+ // --- Maintainability Index (standard formula) ---
1790
+ // MI = 171 - 5.2 * ln(HV) - 0.23 * CC - 16.2 * ln(LOC), clamped to [0, 100]
1791
+ const safeLOC = Math.max(linesOfCode, 1);
1792
+ const safeHV = Math.max(halsteadVolume, 1);
1793
+ let maintainabilityIndex = 171 -
1794
+ 5.2 * Math.log(safeHV) -
1795
+ 0.23 * cyclomaticComplexity -
1796
+ 16.2 * Math.log(safeLOC);
1797
+ maintainabilityIndex = Math.max(0, Math.min(100, maintainabilityIndex));
1798
+ maintainabilityIndex = Math.round(maintainabilityIndex * 100) / 100;
1799
+ // --- Detect code issues ---
1800
+ // 1. Very long functions (>50 lines)
1801
+ const functionStartPattern = /^(\s*)((?:export\s+)?(?:async\s+)?(?:function\s+\w+|(?:const|let|var)\s+\w+\s*=\s*(?:async\s+)?(?:\([^)]*\)|[a-zA-Z_$]\w*)\s*=>))/;
1802
+ let funcStartLine = -1;
1803
+ let braceDepth = 0;
1804
+ let inFunction = false;
1805
+ let funcName = "";
1806
+ for (let i = 0; i < rawLines.length; i++) {
1807
+ const line = rawLines[i];
1808
+ const match = line.match(functionStartPattern);
1809
+ if (match && !inFunction) {
1810
+ funcStartLine = i;
1811
+ // funcIndent removed as unused
1812
+ funcName = match[2].trim().substring(0, 60);
1813
+ braceDepth = 0;
1814
+ inFunction = true;
1815
+ }
1816
+ if (inFunction) {
1817
+ for (const ch of line) {
1818
+ if (ch === "{")
1819
+ braceDepth++;
1820
+ if (ch === "}")
1821
+ braceDepth--;
1822
+ }
1823
+ if (braceDepth <= 0 && i > funcStartLine) {
1824
+ const funcLength = i - funcStartLine + 1;
1825
+ if (funcLength > 50) {
1826
+ issues.push({
1827
+ type: "warning",
1828
+ rule: "long-function",
1829
+ message: `Function is too long (${funcLength} lines, max 50): ${funcName}`,
1830
+ line: funcStartLine + 1,
1831
+ });
1832
+ }
1833
+ inFunction = false;
1834
+ }
1835
+ }
1836
+ }
1837
+ // 2. Deeply nested code (>4 levels)
1838
+ for (let i = 0; i < rawLines.length; i++) {
1839
+ const line = rawLines[i];
1840
+ const leadingSpaces = line.match(/^(\s*)/)?.[1] || "";
1841
+ // Estimate indentation level (2 or 4 spaces, or tabs)
1842
+ const tabCount = (leadingSpaces.match(/\t/g) || []).length;
1843
+ const spaceIndent = leadingSpaces.replace(/\t/g, "").length;
1844
+ const indentLevel = tabCount + Math.floor(spaceIndent / 2);
1845
+ if (indentLevel > 4 &&
1846
+ line.trim().length > 0 &&
1847
+ !line.trim().startsWith("//") &&
1848
+ !line.trim().startsWith("*")) {
1849
+ issues.push({
1850
+ type: "warning",
1851
+ rule: "deep-nesting",
1852
+ message: `Deeply nested code (level ${indentLevel}, max 4)`,
1853
+ line: i + 1,
1854
+ });
1855
+ }
1856
+ }
1857
+ // Deduplicate deep-nesting: keep only first occurrence per contiguous block
1858
+ const nestingIssues = issues.filter((i) => i.rule === "deep-nesting");
1859
+ const keptNestingLines = new Set();
1860
+ for (let j = 0; j < nestingIssues.length; j++) {
1861
+ if (j === 0 || nestingIssues[j].line - nestingIssues[j - 1].line > 1) {
1862
+ keptNestingLines.add(nestingIssues[j].line);
1863
+ }
1864
+ }
1865
+ // Remove non-kept nesting issues
1866
+ for (let j = issues.length - 1; j >= 0; j--) {
1867
+ if (issues[j].rule === "deep-nesting" &&
1868
+ !keptNestingLines.has(issues[j].line)) {
1869
+ issues.splice(j, 1);
1870
+ }
1871
+ }
1872
+ // 3. TODO/FIXME/HACK comments
1873
+ for (let i = 0; i < rawLines.length; i++) {
1874
+ const line = rawLines[i];
1875
+ const todoMatch = line.match(/\b(TODO|FIXME|HACK|XXX)\b/i);
1876
+ if (todoMatch) {
1877
+ issues.push({
1878
+ type: "info",
1879
+ rule: "todo-comment",
1880
+ message: `${todoMatch[1].toUpperCase()} comment found: ${line.trim().substring(0, 80)}`,
1881
+ line: i + 1,
1882
+ });
1883
+ }
1884
+ }
1885
+ // 4. console.log left in code
1886
+ for (let i = 0; i < rawLines.length; i++) {
1887
+ const line = rawLines[i];
1888
+ if (/\bconsole\.(log|debug|info)\s*\(/.test(line) &&
1889
+ !line.trim().startsWith("//")) {
1890
+ issues.push({
1891
+ type: "warning",
1892
+ rule: "console-statement",
1893
+ message: `console statement found — consider removing for production`,
1894
+ line: i + 1,
1895
+ });
1896
+ }
1897
+ }
1898
+ // 5. Unused imports (basic detection — look for imports not referenced elsewhere)
1899
+ const importPattern = /import\s+(?:\{([^}]+)\}|(\w+))\s+from/g;
1900
+ let importMatch;
1901
+ while ((importMatch = importPattern.exec(content)) !== null) {
1902
+ const names = importMatch[1]
1903
+ ? importMatch[1].split(",").map((n) => n
1904
+ .trim()
1905
+ .replace(/\s+as\s+\w+/, "")
1906
+ .trim())
1907
+ : importMatch[2]
1908
+ ? [importMatch[2]]
1909
+ : [];
1910
+ for (const name of names) {
1911
+ if (!name || name === "type")
1912
+ continue;
1913
+ // Count occurrences outside of import lines
1914
+ const escaped = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1915
+ const usagePattern = new RegExp(`\\b${escaped}\\b`, "g");
1916
+ const allMatches = content.match(usagePattern) || [];
1917
+ // If it only appears once (the import itself), it's likely unused
1918
+ if (allMatches.length <= 1) {
1919
+ const importLine = content
1920
+ .substring(0, importMatch.index)
1921
+ .split("\n").length;
1922
+ issues.push({
1923
+ type: "warning",
1924
+ rule: "unused-import",
1925
+ message: `Possibly unused import: "${name}"`,
1926
+ line: importLine,
1927
+ });
1928
+ }
1929
+ }
1930
+ }
1931
+ // 6. Overly complex expressions (lines with many operators)
1932
+ for (let i = 0; i < rawLines.length; i++) {
1933
+ const line = rawLines[i];
1934
+ const ops = (line.match(/&&|\|\||[?:]/g) || []).length;
1935
+ if (ops >= 5) {
1936
+ issues.push({
1937
+ type: "warning",
1938
+ rule: "complex-expression",
1939
+ message: `Overly complex expression (${ops} logical/ternary operators on one line)`,
1940
+ line: i + 1,
1941
+ });
1942
+ }
1943
+ }
1944
+ return {
1945
+ file: input,
1946
+ resolvedPath: abs,
1947
+ totalLines,
1948
+ issues,
1949
+ issueCount: issues.length,
1950
+ metrics: {
1951
+ linesOfCode,
1952
+ blankLines: totalLines -
1953
+ linesOfCode -
1954
+ (totalLines - rawLines.filter((l) => l.trim() !== "").length),
1955
+ cyclomaticComplexity,
1956
+ halsteadVolume: Math.round(halsteadVolume * 100) / 100,
1957
+ maintainabilityIndex,
1958
+ },
1959
+ };
1960
+ }
1961
+ /**
1962
+ * Smart merge that deduplicates, groups by type/directory, preserves import
1963
+ * order, detects conflicts, and adds rich section headers.
1964
+ */
1965
+ async function mergeInputs(inputs, _options) {
1966
+ const files = readInputFiles(inputs);
1967
+ if (files.length === 0) {
1968
+ throw new Error("No valid input files found");
1969
+ }
1970
+ if (files.length === 1) {
1971
+ return files[0].content;
1972
+ }
1973
+ const strategy = _options["strategy"] || "semantic";
1974
+ const merged = [];
1975
+ const conflicts = [];
1976
+ // --- Deduplicate identical content ---
1977
+ const seen = new Map(); // content hash → first file path
1978
+ const uniqueFiles = [];
1979
+ for (const file of files) {
1980
+ // Simple content-based dedup using a hash of trimmed content
1981
+ const contentKey = file.content.trim();
1982
+ if (seen.has(contentKey)) {
1983
+ console.warn(chalk.yellow(` ⚠ Duplicate content skipped: ${file.path} (same as ${seen.get(contentKey)})`));
1984
+ continue;
1985
+ }
1986
+ seen.set(contentKey, file.path);
1987
+ uniqueFiles.push(file);
1988
+ }
1989
+ // --- Group files by directory, then by extension ---
1990
+ const dirGroups = new Map();
1991
+ for (const file of uniqueFiles) {
1992
+ const dir = file.path.substring(0, file.path.lastIndexOf("/")) || ".";
1993
+ if (!dirGroups.has(dir))
1994
+ dirGroups.set(dir, []);
1995
+ dirGroups.get(dir).push(file);
1996
+ }
1997
+ // Sort groups: directories alphabetically
1998
+ const sortedDirs = [...dirGroups.keys()].sort();
1999
+ // --- Detect potential naming conflicts across files ---
2000
+ // Look for same function/class/const names exported or declared in different files
2001
+ const declaredNames = new Map(); // name → file paths
2002
+ const declarationPattern = /(?:export\s+)?(?:function|class|const|let|var|interface|type|enum)\s+([A-Za-z_$][A-Za-z0-9_$]*)/g;
2003
+ for (const file of uniqueFiles) {
2004
+ let match;
2005
+ const localPattern = new RegExp(declarationPattern.source, "g");
2006
+ while ((match = localPattern.exec(file.content)) !== null) {
2007
+ const name = match[1];
2008
+ if (!declaredNames.has(name))
2009
+ declaredNames.set(name, []);
2010
+ declaredNames.get(name).push(file.path);
2011
+ }
2012
+ }
2013
+ for (const [name, paths] of declaredNames.entries()) {
2014
+ if (paths.length > 1) {
2015
+ conflicts.push(`"${name}" is declared in multiple files: ${paths.map((p) => p.split("/").pop()).join(", ")}`);
2016
+ }
2017
+ }
2018
+ // --- Build merge header ---
2019
+ merged.push(`// ============================================================================`);
2020
+ // Backwards-compatible header line expected by older tests/tools
2021
+ merged.push(`// Merged ${uniqueFiles.length} files`);
2022
+ merged.push(`// Merged ${uniqueFiles.length} file(s) using "${strategy}" strategy`);
2023
+ merged.push(`// Generated by SynapseXcoder V1 on ${new Date().toISOString()}`);
2024
+ if (uniqueFiles.length < files.length) {
2025
+ merged.push(`// Deduplicated: ${files.length - uniqueFiles.length} duplicate(s) removed`);
2026
+ }
2027
+ if (conflicts.length > 0) {
2028
+ merged.push(`//`);
2029
+ merged.push(`// ⚠ CONFLICTS DETECTED (${conflicts.length}):`);
2030
+ for (const conflict of conflicts) {
2031
+ merged.push(`// - ${conflict}`);
2032
+ }
2033
+ }
2034
+ merged.push(`// ============================================================================`);
2035
+ merged.push("");
2036
+ // --- Collect all imports and non-import content separately ---
2037
+ const allImports = [];
2038
+ const allDeclarations = []; // non-import, non-export-default content
2039
+ const allExports = [];
2040
+ for (const dir of sortedDirs) {
2041
+ const groupFiles = dirGroups.get(dir);
2042
+ // Sort files within group by extension, then name
2043
+ groupFiles.sort((a, b) => {
2044
+ const extA = extname(a.path);
2045
+ const extB = extname(b.path);
2046
+ if (extA !== extB)
2047
+ return extA.localeCompare(extB);
2048
+ return a.path.localeCompare(b.path);
2049
+ });
2050
+ for (const file of groupFiles) {
2051
+ const fileName = file.path.split("/").pop() || file.path;
2052
+ const fileStat = existsSync(file.path) ? statSync(file.path) : null;
2053
+ const sizeKB = fileStat ? (fileStat.size / 1024).toFixed(1) : "?";
2054
+ const modified = fileStat
2055
+ ? new Date(fileStat.mtimeMs).toISOString().split("T")[0]
2056
+ : "unknown";
2057
+ const sectionHeader = [
2058
+ `// ─────────────────────────────────────────────────────────────`,
2059
+ `// FILE: ${fileName}`,
2060
+ `// FROM: ${file.path}`,
2061
+ `// PATH: ${file.path}`,
2062
+ `// SIZE: ${sizeKB} KB | MODIFIED: ${modified} | LANG: ${file.language}`,
2063
+ `// ─────────────────────────────────────────────────────────────`,
2064
+ ];
2065
+ const lines = file.content.split("\n");
2066
+ const fileImports = [];
2067
+ const fileBody = [];
2068
+ const fileExports = [];
2069
+ let inImportBlock = true;
2070
+ for (const line of lines) {
2071
+ const trimmed = line.trim();
2072
+ // Collect imports (lines starting with 'import' or continuation of multi-line imports)
2073
+ if (inImportBlock) {
2074
+ if (trimmed.startsWith("import ") ||
2075
+ trimmed.startsWith("import{") ||
2076
+ (trimmed.startsWith("}") && trimmed.includes("from")) ||
2077
+ (fileImports.length > 0 &&
2078
+ !trimmed.startsWith("import") &&
2079
+ /^\s*[},]/.test(line) &&
2080
+ !trimmed.includes("export"))) {
2081
+ fileImports.push(line);
2082
+ continue;
2083
+ }
2084
+ if (trimmed === "" && fileImports.length > 0) {
2085
+ continue; // Skip blank lines between imports
2086
+ }
2087
+ if (trimmed !== "") {
2088
+ inImportBlock = false;
2089
+ }
2090
+ }
2091
+ // Separate trailing export defaults
2092
+ if (trimmed.startsWith("export default ") ||
2093
+ trimmed === "export default") {
2094
+ fileExports.push(line);
2095
+ continue;
2096
+ }
2097
+ fileBody.push(line);
2098
+ }
2099
+ // Deduplicate imports (same line text)
2100
+ for (const imp of fileImports) {
2101
+ if (!allImports.includes(imp)) {
2102
+ allImports.push(imp);
2103
+ }
2104
+ }
2105
+ // Add body with section header
2106
+ allDeclarations.push("");
2107
+ allDeclarations.push(...sectionHeader);
2108
+ allDeclarations.push("");
2109
+ allDeclarations.push(...fileBody);
2110
+ // Collect exports
2111
+ if (fileExports.length > 0) {
2112
+ allExports.push(`// Export from: ${fileName}`);
2113
+ allExports.push(...fileExports);
2114
+ }
2115
+ }
2116
+ }
2117
+ // --- Assemble final output: imports → declarations → exports ---
2118
+ if (allImports.length > 0) {
2119
+ merged.push("// === IMPORTS ===");
2120
+ merged.push(...allImports);
2121
+ merged.push("");
2122
+ }
2123
+ merged.push(...allDeclarations);
2124
+ if (allExports.length > 0) {
2125
+ merged.push("");
2126
+ merged.push("// === EXPORTS ===");
2127
+ merged.push(...allExports);
2128
+ }
2129
+ merged.push("");
2130
+ return merged.join("\n");
2131
+ }
2132
+ function displayResults(result, _options, gatekeeperConfig) {
2133
+ if (_options["json"]) {
2134
+ console.log(JSON.stringify(result, null, 2));
2135
+ return;
2136
+ }
2137
+ const ok = result["status"] === "success";
2138
+ console.log(chalk.cyan("\nšŸ“Š Results Summary\n"));
2139
+ const summary = result["summary"];
2140
+ console.log(` Status: ${ok ? chalk.green("success") : chalk.red("failed")}`);
2141
+ if (result["error"])
2142
+ console.log(` Error: ${chalk.red(result["error"])}`);
2143
+ console.log(` Files processed: ${chalk.green(summary["filesProcessed"])}`);
2144
+ console.log(` Issues found: ${chalk.yellow(summary["issuesFound"])}`);
2145
+ console.log(` Issues fixed: ${chalk.green(summary["issuesFixed"])}`);
2146
+ console.log(` Phases completed: ${chalk.green(summary["successfulPhases"])} / ${summary["totalPhases"]}`);
2147
+ console.log(` Artifacts: ${chalk.cyan(result["artifacts"])}`);
2148
+ // Display gatekeeper information if enabled
2149
+ if (gatekeeperConfig?.enabled !== false) {
2150
+ console.log();
2151
+ console.log(chalk.cyan("šŸ” Gatekeeper Review\n"));
2152
+ const gatekeeper = result["gatekeeper"];
2153
+ if (gatekeeper) {
2154
+ console.log(` Enabled: ${chalk.green("Yes")}`);
2155
+ console.log(` Review Level: ${chalk.gray(gatekeeperConfig?.reviewLevel || "standard")}`);
2156
+ console.log(` Total Reviews: ${chalk.cyan(gatekeeper["totalReviews"])}`);
2157
+ console.log(` Passed: ${chalk.green(gatekeeper["passedReviews"])}`);
2158
+ console.log(` Revisions: ${chalk.yellow(gatekeeper["revisionRequests"])}`);
2159
+ }
2160
+ else {
2161
+ console.log(` Enabled: ${chalk.gray("No gatekeeper data")}`);
2162
+ }
2163
+ }
2164
+ console.log();
2165
+ }
2166
+ function displayAnalysisResults(result, _options) {
2167
+ if (_options["json"]) {
2168
+ console.log(JSON.stringify(result, null, 2));
2169
+ return;
2170
+ }
2171
+ console.log(chalk.cyan("\nšŸ” Analysis Results\n"));
2172
+ console.log(` File: ${chalk.gray(result.file)}`);
2173
+ if (result.resolvedPath) {
2174
+ console.log(` Resolved Path: ${chalk.gray(result.resolvedPath)}`);
2175
+ }
2176
+ console.log(` Total Lines: ${chalk.gray(String(result.totalLines ?? "?"))}`);
2177
+ const metrics = result.metrics;
2178
+ console.log(` Lines of Code: ${chalk.gray(String(metrics.linesOfCode))}`);
2179
+ console.log(` Complexity: ${chalk.gray(String(metrics.cyclomaticComplexity ?? metrics.complexity ?? 0))}`);
2180
+ const mi = metrics.maintainabilityIndex;
2181
+ const miColor = mi >= 70 ? chalk.green : mi >= 40 ? chalk.yellow : chalk.red;
2182
+ console.log(` Maintainability: ${miColor(String(mi))}`);
2183
+ if (metrics.halsteadVolume !== undefined) {
2184
+ console.log(` Halstead Volume: ${chalk.gray(String(metrics.halsteadVolume))}`);
2185
+ }
2186
+ const issues = result.issues;
2187
+ if (issues && issues.length > 0) {
2188
+ console.log(chalk.cyan(`\n šŸ“‹ Issues (${issues.length}):\n`));
2189
+ for (const issue of issues) {
2190
+ const icon = issue.type === "error"
2191
+ ? chalk.red("āœ—")
2192
+ : issue.type === "warning"
2193
+ ? chalk.yellow("⚠")
2194
+ : chalk.blue("ℹ");
2195
+ const lineInfo = issue.line > 0 ? chalk.gray(`:${issue.line}`) : "";
2196
+ console.log(` ${icon} ${chalk.gray(`[${issue.rule}]`)}${lineInfo} ${issue.message}`);
2197
+ }
2198
+ }
2199
+ else {
2200
+ console.log(chalk.green("\n āœ“ No issues detected"));
2201
+ }
2202
+ console.log();
2203
+ }
2204
+ /**
2205
+ * Get dynamic agent list by querying the MessageBus for registered agents
2206
+ * and their queue states. Falls back to showing all available agent types
2207
+ * with their default models and "not running" status if none are active.
2208
+ */
2209
+ function getAgentList() {
2210
+ // Default model assignments per agent type
2211
+ const agentDefaults = {
2212
+ master: { type: "primary", model: "claude-opus-4-6" },
2213
+ planner: { type: "subagent", model: "claude-haiku-4" },
2214
+ analyzer: { type: "subagent", model: "claude-sonnet-4" },
2215
+ reviewer: { type: "subagent", model: "claude-sonnet-4" },
2216
+ rewriter: { type: "subagent", model: "claude-opus-4-5" },
2217
+ ui_designer: { type: "subagent", model: "claude-sonnet-4" },
2218
+ researcher: { type: "subagent", model: "claude-haiku-4" },
2219
+ gatekeeper: { type: "subagent", model: "claude-opus-4-5" },
2220
+ };
2221
+ try {
2222
+ // Try to query the MessageBus for real agent state
2223
+ const messageBus = new MessageBus({ enableLogging: false });
2224
+ const busStats = messageBus.getStats();
2225
+ const agents = [];
2226
+ for (const [agentName, defaults] of Object.entries(agentDefaults)) {
2227
+ const queueSize = busStats.queues[agentName] ?? 0;
2228
+ // Infer status from queue state:
2229
+ // - queue has messages → "running" (processing work)
2230
+ // - queue is empty → "idle" (available but not busy)
2231
+ let status;
2232
+ if (queueSize > 0) {
2233
+ status = "running";
2234
+ }
2235
+ else {
2236
+ status = "idle";
2237
+ }
2238
+ // Try to load model from config if available
2239
+ let model = defaults.model;
2240
+ try {
2241
+ const config = loadConfigFile();
2242
+ const agentConfig = config["agents"]?.[agentName];
2243
+ if (agentConfig?.["model"] &&
2244
+ typeof agentConfig["model"] === "string") {
2245
+ // Extract the short model name from the provider-qualified form
2246
+ const fullModel = agentConfig["model"];
2247
+ model = fullModel.includes("/")
2248
+ ? fullModel.split("/").pop()
2249
+ : fullModel;
2250
+ }
2251
+ }
2252
+ catch {
2253
+ // Use defaults if config is unavailable
2254
+ }
2255
+ agents.push({
2256
+ name: agentName,
2257
+ type: defaults.type,
2258
+ model,
2259
+ status,
2260
+ });
2261
+ }
2262
+ return agents;
2263
+ }
2264
+ catch {
2265
+ // Fallback: return static defaults with "not running" status
2266
+ return Object.entries(agentDefaults).map(([name, defaults]) => ({
2267
+ name,
2268
+ type: defaults.type,
2269
+ model: defaults.model,
2270
+ status: "not running",
2271
+ }));
2272
+ }
2273
+ }
2274
+ // ============================================================================
2275
+ // Dashboard Command
2276
+ // ============================================================================
2277
+ const dashboardCmd = program
2278
+ .command("dashboard")
2279
+ .description("Show agent performance dashboard in the TUI model display area");
2280
+ dashboardCmd
2281
+ .command("show")
2282
+ .description("Display analytics dashboard with agent performance metrics")
2283
+ .option("-f, --format <format>", "Output format (terminal|json|markdown|html)", "terminal")
2284
+ .option("-t, --time <minutes>", "Time range in minutes", "60")
2285
+ .option("--trends", "Include trend analysis")
2286
+ .option("--no-trends", "Exclude trend analysis")
2287
+ .option("--recommendations", "Include recommendations")
2288
+ .option("--no-recommendations", "Exclude recommendations")
2289
+ .action((opts) => {
2290
+ try {
2291
+ const { DashboardGenerator } = require("../analytics/dashboard-generator.js");
2292
+ const { MetricsAggregator } = require("../analytics/metrics-aggregator.js");
2293
+ const aggregator = new MetricsAggregator();
2294
+ const dashboard = new DashboardGenerator(aggregator);
2295
+ const timeRangeMinutes = parseInt(String(opts.time), 10) || 60;
2296
+ const report = dashboard.generateReport({
2297
+ format: "markdown",
2298
+ includeTrends: opts.trends !== false,
2299
+ includeRecommendations: opts.recommendations !== false,
2300
+ timeRangeMinutes,
2301
+ });
2302
+ if (opts.format === "json") {
2303
+ console.log(JSON.stringify(report, null, 2));
2304
+ return;
2305
+ }
2306
+ if (opts.format === "html") {
2307
+ console.log(dashboard.export(report, "html"));
2308
+ return;
2309
+ }
2310
+ // Terminal/TUI format — show dashboard in the model display area
2311
+ const s = report.summary;
2312
+ const m = report.metrics;
2313
+ console.log(chalk.cyan("\nšŸ“Š Agent Performance Dashboard\n"));
2314
+ console.log(chalk.gray(` Generated: ${new Date(report.generatedAt).toISOString()}`));
2315
+ console.log(chalk.gray(` Period: ${timeRangeMinutes} min\n`));
2316
+ // Summary cards
2317
+ console.log(chalk.bold(" ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”"));
2318
+ console.log(chalk.bold(" │ Performance Summary │"));
2319
+ console.log(chalk.bold(" ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¤"));
2320
+ console.log(` │ ${chalk.bold("Executions:")} ${String(s.totalExecutions).padEnd(28)} │`);
2321
+ const successColor = s.overallSuccessRate >= 0.9 ? chalk.green : s.overallSuccessRate >= 0.7 ? chalk.yellow : chalk.red;
2322
+ console.log(` │ ${chalk.bold("Success Rate:")} ${successColor((s.overallSuccessRate * 100).toFixed(1) + "%").padEnd(28)} │`);
2323
+ console.log(` │ ${chalk.bold("Total Time:")} ${String(s.totalTimeSeconds.toFixed(1) + "s").padEnd(28)} │`);
2324
+ console.log(` │ ${chalk.bold("Total Tokens:")} ${String(s.totalTokens.toLocaleString()).padEnd(28)} │`);
2325
+ console.log(` │ ${chalk.bold("Active Agents:")} ${String(s.activeAgentTypes).padEnd(28)} │`);
2326
+ console.log(` │ ${chalk.bold("Busiest Agent:")} ${String(s.busiestAgentType).padEnd(28)} │`);
2327
+ console.log(` │ ${chalk.bold("Slowest Agent:")} ${String(s.slowestAgentType).padEnd(28)} │`);
2328
+ console.log(chalk.bold(" ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜"));
2329
+ console.log();
2330
+ // Per-agent breakdown
2331
+ console.log(chalk.bold(" Per-Agent Performance:"));
2332
+ console.log();
2333
+ console.log(` ${chalk.gray("Agent Type".padEnd(16))} ${chalk.gray("Tasks".padEnd(7))} ${chalk.gray("Success".padEnd(10))} ${chalk.gray("Avg Time".padEnd(11))} ${chalk.gray("Avg Tokens")}`);
2334
+ console.log(` ${chalk.gray("─".repeat(16))} ${chalk.gray("─".repeat(7))} ${chalk.gray("─".repeat(10))} ${chalk.gray("─".repeat(11))} ${chalk.gray("─".repeat(10))}`);
2335
+ const agentTypes = Object.keys(m.byAgentType);
2336
+ for (const agentType of agentTypes.sort()) {
2337
+ const a = m.byAgentType[agentType];
2338
+ const total = a.tasksCompleted + a.tasksFailed;
2339
+ const successPct = (a.successRate * 100).toFixed(1);
2340
+ const srColor = a.successRate >= 0.9 ? chalk.green : a.successRate >= 0.7 ? chalk.yellow : chalk.red;
2341
+ const avgTime = a.averageExecutionTime.toFixed(0);
2342
+ console.log(` ${chalk.cyan(String(agentType).padEnd(16))} ` +
2343
+ `${String(total).padEnd(7)} ` +
2344
+ `${srColor(successPct + "%").padEnd(10)} ` +
2345
+ `${chalk.gray(avgTime + "ms").padEnd(11)} ` +
2346
+ `${chalk.gray(String(a.averageTokensUsed.toFixed(0)))}`);
2347
+ }
2348
+ console.log();
2349
+ // Trends
2350
+ if (opts.trends !== false && report.trends.length > 0) {
2351
+ console.log(chalk.bold(" Trends:"));
2352
+ for (const trend of report.trends) {
2353
+ const icon = trend.direction === "up" ? chalk.green("ā–²") : trend.direction === "down" ? chalk.red("ā–¼") : chalk.gray("ā—†");
2354
+ const changeStr = trend.direction === "stable"
2355
+ ? chalk.gray("no change")
2356
+ : (trend.changePercent > 0 ? chalk.green("+" + trend.changePercent.toFixed(1) + "%") : chalk.red(trend.changePercent.toFixed(1) + "%"));
2357
+ console.log(` ${icon} ${trend.metric}: ${changeStr}`);
2358
+ }
2359
+ console.log();
2360
+ }
2361
+ // Recommendations
2362
+ if (opts.recommendations !== false && report.recommendations.length > 0) {
2363
+ console.log(chalk.bold(" Recommendations:"));
2364
+ for (const rec of report.recommendations) {
2365
+ console.log(` ${chalk.yellow("→")} ${rec}`);
2366
+ }
2367
+ console.log();
2368
+ }
2369
+ }
2370
+ catch (error) {
2371
+ console.log(chalk.red(` āœ— Failed to generate dashboard: ${error instanceof Error ? error.message : error}`));
2372
+ console.log(chalk.gray(" Dashboard requires MetricsAggregator and DashboardGenerator."));
2373
+ }
2374
+ });
2375
+ dashboardCmd
2376
+ .command("snapshot")
2377
+ .description("Show quick metrics snapshot for the model display area")
2378
+ .action(() => {
2379
+ try {
2380
+ const { MetricsAggregator } = require("../analytics/metrics-aggregator.js");
2381
+ const aggregator = new MetricsAggregator();
2382
+ const snapshot = aggregator.snapshot();
2383
+ console.log(chalk.cyan("\n⚔ Metrics Snapshot\n"));
2384
+ console.log(` ${chalk.bold("Active Agents:")} ${chalk.green(String(snapshot.activeAgents))}`);
2385
+ console.log(` ${chalk.bold("Running Tasks:")} ${chalk.yellow(String(snapshot.runningTasks))}`);
2386
+ console.log(` ${chalk.bold("Queued Tasks:")} ${chalk.gray(String(snapshot.queuedTasks))}`);
2387
+ console.log(` ${chalk.bold("Success Rate:")} ${(snapshot.recentSuccessRate * 100).toFixed(1)}%`);
2388
+ if (snapshot.memoryUsageMb) {
2389
+ console.log(` ${chalk.bold("Memory Usage:")} ${chalk.gray(String(snapshot.memoryUsageMb.toFixed(1)) + " MB")}`);
2390
+ }
2391
+ if (snapshot.farmMetrics) {
2392
+ console.log(chalk.bold("\n Farm Metrics:"));
2393
+ console.log(` Workers: ${snapshot.farmMetrics.activeWorkers}/${snapshot.farmMetrics.workerCount} active`);
2394
+ console.log(` Tasks: ${snapshot.farmMetrics.tasksCompleted} done, ${snapshot.farmMetrics.tasksFailed} failed`);
2395
+ }
2396
+ console.log();
2397
+ }
2398
+ catch (error) {
2399
+ console.log(chalk.yellow(" ⚠ Snapshot not available — no metrics data"));
2400
+ }
2401
+ });
2402
+ // ============================================================================
2403
+ // Mode Management Commands
2404
+ // ============================================================================
2405
+ const modeCmd = program.command("mode").description("Manage custom processing modes");
2406
+ modeCmd
2407
+ .command("list")
2408
+ .description("List all custom modes")
2409
+ .option("--builtin", "Include built-in modes")
2410
+ .action((opts) => {
2411
+ const registry = new CustomModeRegistry();
2412
+ const custom = registry.list();
2413
+ const builtin = synapseModeRegistry.listModes();
2414
+ console.log(chalk.cyan("\nšŸ“‹ Processing Modes\n"));
2415
+ if (opts.builtin) {
2416
+ console.log(chalk.yellow(" Built-in Modes:"));
2417
+ builtin.forEach((m) => {
2418
+ console.log(` ${chalk.green(m.id)} — ${m.label}`);
2419
+ console.log(` ${chalk.gray(m.description)}`);
2420
+ console.log();
2421
+ });
2422
+ }
2423
+ console.log(chalk.yellow(` Custom Modes (${custom.length}):`));
2424
+ if (custom.length === 0) {
2425
+ console.log(chalk.gray(" No custom modes registered"));
2426
+ }
2427
+ else {
2428
+ custom.forEach((m) => {
2429
+ const statusIcon = m.enabled ? chalk.green("āœ“") : chalk.gray("āœ—");
2430
+ console.log(` ${statusIcon} ${chalk.green(m.id)} — ${m.label}`);
2431
+ console.log(` ${chalk.gray(m.description)}`);
2432
+ if (m.usageCount > 0) {
2433
+ console.log(` ${chalk.gray(`Used ${m.usageCount} times`)}`);
2434
+ }
2435
+ console.log();
2436
+ });
2437
+ }
2438
+ console.log();
2439
+ });
2440
+ modeCmd
2441
+ .command("create")
2442
+ .description("Create a new custom mode")
2443
+ .argument("<id>", "Mode identifier (lowercase, underscores)")
2444
+ .argument("<label>", "Display label")
2445
+ .argument("<description>", "Mode description")
2446
+ .option("-a, --agents <agents>", "Comma-separated agent list")
2447
+ .option("-t, --tools <tools>", "Comma-separated tool list")
2448
+ .option("-p, --pipeline <pipeline>", "Base pipeline mode")
2449
+ .option("--from-template <name>", "Create from a named template")
2450
+ .option("--dry-run", "Validate without saving")
2451
+ .action((id, label, description, opts) => {
2452
+ let def = {
2453
+ id,
2454
+ label,
2455
+ description,
2456
+ agents: opts.agents
2457
+ ? opts.agents.split(",").map((s) => s.trim())
2458
+ : undefined,
2459
+ tools: opts.tools
2460
+ ? opts.tools.split(",").map((s) => s.trim())
2461
+ : undefined,
2462
+ basePipeline: opts.pipeline,
2463
+ };
2464
+ // If template specified, merge
2465
+ if (opts.fromTemplate) {
2466
+ const template = createFromTemplate(opts.fromTemplate, def);
2467
+ if (!template) {
2468
+ console.log(chalk.red(`\n āœ— Template "${opts.fromTemplate}" not found`));
2469
+ process.exit(1);
2470
+ }
2471
+ def = { ...def, ...template };
2472
+ }
2473
+ // Validate
2474
+ const validation = validateModeDefinition(def);
2475
+ if (!validation.valid) {
2476
+ console.log(chalk.red("\n āœ— Validation failed:\n"));
2477
+ validation.errors.forEach((e) => {
2478
+ console.log(` ${chalk.red("āœ—")} ${chalk.bold(e.field)}: ${e.message}`);
2479
+ });
2480
+ validation.warnings.forEach((w) => {
2481
+ console.log(` ${chalk.yellow("⚠")} ${chalk.bold(w.field)}: ${w.message}`);
2482
+ });
2483
+ process.exit(1);
2484
+ }
2485
+ if (validation.warnings.length > 0) {
2486
+ console.log(chalk.yellow("\n ⚠ Warnings:\n"));
2487
+ validation.warnings.forEach((w) => {
2488
+ console.log(` ${chalk.yellow("⚠")} ${chalk.bold(w.field)}: ${w.message}`);
2489
+ });
2490
+ }
2491
+ if (opts.dryRun) {
2492
+ console.log(chalk.green("\n āœ“ Mode definition is valid (dry run — not saved)\n"));
2493
+ // Show preview
2494
+ const preview = generateModePreview(def);
2495
+ console.log(chalk.cyan(" Preview:"));
2496
+ console.log(preview.markdown.split("\n").map((l) => ` ${l}`).join("\n"));
2497
+ console.log();
2498
+ return;
2499
+ }
2500
+ // Save
2501
+ try {
2502
+ saveModeToFile(def);
2503
+ console.log(chalk.green(`\n āœ“ Mode "${id}" created successfully\n`));
2504
+ }
2505
+ catch (e) {
2506
+ console.log(chalk.red(`\n āœ— Failed to save mode: ${e instanceof Error ? e.message : e}\n`));
2507
+ process.exit(1);
2508
+ }
2509
+ });
2510
+ modeCmd
2511
+ .command("delete")
2512
+ .description("Delete a custom mode")
2513
+ .argument("<id>", "Mode identifier")
2514
+ .option("--force", "Skip confirmation")
2515
+ .action((id) => {
2516
+ const deleted = deleteModeFromFile(id);
2517
+ if (deleted) {
2518
+ console.log(chalk.green(`\n āœ“ Mode "${id}" deleted\n`));
2519
+ }
2520
+ else {
2521
+ console.log(chalk.yellow(`\n ⚠ Mode "${id}" not found\n`));
2522
+ }
2523
+ });
2524
+ modeCmd
2525
+ .command("show")
2526
+ .description("Show detailed mode information")
2527
+ .argument("<id>", "Mode identifier")
2528
+ .option("--preview", "Show visual pipeline preview")
2529
+ .action((id, opts) => {
2530
+ // Check built-in first
2531
+ const builtin = synapseModeRegistry.getMode(id);
2532
+ if (builtin) {
2533
+ console.log(chalk.cyan(`\nšŸ“‹ Built-in Mode: ${builtin.id}\n`));
2534
+ console.log(` ${chalk.bold("Label:")} ${builtin.label}`);
2535
+ console.log(` ${chalk.bold("Description:")} ${builtin.description}`);
2536
+ if (builtin.agents?.length > 0) {
2537
+ console.log(` ${chalk.bold("Agents:")} ${builtin.agents.join(", ")}`);
2538
+ }
2539
+ if (builtin.tools?.length > 0) {
2540
+ console.log(` ${chalk.bold("Tools:")} ${builtin.tools.join(", ")}`);
2541
+ }
2542
+ if (builtin.basePipeline) {
2543
+ console.log(` ${chalk.bold("Pipeline:")} ${builtin.basePipeline}`);
2544
+ }
2545
+ console.log();
2546
+ return;
2547
+ }
2548
+ // Check custom modes
2549
+ const customList = listCustomModesFromFile();
2550
+ const custom = customList.find((m) => m.id === id);
2551
+ if (!custom) {
2552
+ console.log(chalk.yellow(`\n ⚠ Mode "${id}" not found\n`));
2553
+ return;
2554
+ }
2555
+ console.log(chalk.cyan(`\nšŸ“‹ Custom Mode: ${custom.id}\n`));
2556
+ console.log(` ${chalk.bold("Label:")} ${custom.label}`);
2557
+ console.log(` ${chalk.bold("Description:")} ${custom.description}`);
2558
+ if (custom.agents && custom.agents.length > 0) {
2559
+ console.log(` ${chalk.bold("Agents:")} ${custom.agents.join(", ")}`);
2560
+ }
2561
+ if (custom.tools && custom.tools.length > 0) {
2562
+ console.log(` ${chalk.bold("Tools:")} ${custom.tools.join(", ")}`);
2563
+ }
2564
+ if (custom.basePipeline) {
2565
+ console.log(` ${chalk.bold("Pipeline:")} ${custom.basePipeline}`);
2566
+ }
2567
+ if (opts.preview) {
2568
+ const preview = generateModePreview(custom);
2569
+ console.log(chalk.cyan("\n Pipeline Preview:"));
2570
+ preview.pipelineSteps.forEach((step) => {
2571
+ console.log(` ${chalk.green("→")} ${step}`);
2572
+ });
2573
+ console.log();
2574
+ console.log(preview.markdown);
2575
+ }
2576
+ console.log();
2577
+ });
2578
+ modeCmd
2579
+ .command("templates")
2580
+ .description("List available mode templates")
2581
+ .option("-c, --category <category>", "Filter by category")
2582
+ .action((opts) => {
2583
+ const templates = opts.category
2584
+ ? getTemplatesByCategory(opts.category)
2585
+ : getModeTemplates();
2586
+ console.log(chalk.cyan("\nšŸ“¦ Mode Templates\n"));
2587
+ if (templates.length === 0) {
2588
+ console.log(chalk.gray(" No templates found"));
2589
+ console.log();
2590
+ return;
2591
+ }
2592
+ templates.forEach((t) => {
2593
+ console.log(` ${chalk.green(t.name)} — ${t.description}`);
2594
+ console.log(` ${chalk.gray(`Category: ${t.category}`)}`);
2595
+ console.log(` ${chalk.gray(`Pipeline: ${t.template.basePipeline ?? "none"}`)}`);
2596
+ if (t.template.agents) {
2597
+ console.log(` ${chalk.gray(`Agents: ${t.template.agents.join(", ")}`)}`);
2598
+ }
2599
+ console.log();
2600
+ });
2601
+ });
2602
+ modeCmd
2603
+ .command("validate")
2604
+ .description("Validate a custom mode YAML file")
2605
+ .argument("<file>", "Path to YAML file")
2606
+ .action((file) => {
2607
+ if (!existsSync(file)) {
2608
+ console.log(chalk.red(`\n āœ— File not found: ${file}\n`));
2609
+ process.exit(1);
2610
+ }
2611
+ try {
2612
+ const content = readFileSync(file, "utf-8");
2613
+ const def = parseModeFromYaml(content);
2614
+ if (!def) {
2615
+ console.log(chalk.yellow("\n ⚠ No valid mode definition found in file\n"));
2616
+ return;
2617
+ }
2618
+ const validation = validateModeDefinition(def);
2619
+ if (validation.valid) {
2620
+ console.log(chalk.green(`\n āœ“ Mode "${def.id}" is valid\n`));
2621
+ }
2622
+ else {
2623
+ console.log(chalk.red(`\n āœ— Mode "${def.id}" has errors:\n`));
2624
+ validation.errors.forEach((e) => {
2625
+ console.log(` ${chalk.red("āœ—")} ${chalk.bold(e.field)}: ${e.message}`);
2626
+ });
2627
+ }
2628
+ if (validation.warnings.length > 0) {
2629
+ console.log(chalk.yellow("\n ⚠ Warnings:\n"));
2630
+ validation.warnings.forEach((w) => {
2631
+ console.log(` ${chalk.yellow("⚠")} ${chalk.bold(w.field)}: ${w.message}`);
2632
+ });
2633
+ }
2634
+ if (validation.suggestion) {
2635
+ console.log(chalk.cyan(`\n šŸ’” Suggestion: ${validation.suggestion}\n`));
2636
+ }
2637
+ console.log();
2638
+ }
2639
+ catch (e) {
2640
+ console.log(chalk.red(`\n āœ— Failed to parse file: ${e instanceof Error ? e.message : e}\n`));
2641
+ process.exit(1);
2642
+ }
2643
+ });
2644
+ // ============================================================================
2645
+ // Boot Banner
2646
+ // ============================================================================
2647
+ console.log(chalk.cyan(`
2648
+ ╔══════════════════════════════════════════════════════════════════════════════╗
2649
+ ā•‘ šŸ¦† SynapseXcoder AI System — V1 ā•‘
2650
+ ā•‘ Multi-Agent OpenCode Integration Edition ā•‘
2651
+ ā•šā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•
2652
+ `));
2653
+ function isRunningDirectly() {
2654
+ if (!process.argv[1])
2655
+ return false;
2656
+ try {
2657
+ const entryPath = realpathSync(resolve(process.argv[1]));
2658
+ const modulePath = realpathSync(resolve(new URL(import.meta.url).pathname));
2659
+ return entryPath === modulePath;
2660
+ }
2661
+ catch {
2662
+ return import.meta.url === `file://${process.argv[1]}`;
2663
+ }
2664
+ }
2665
+ // Parse and execute only when run directly (not when imported for testing)
2666
+ if (isRunningDirectly()) {
2667
+ program.parse(process.argv);
2668
+ // Show help if no command
2669
+ if (process.argv.length === 2) {
2670
+ program.help();
2671
+ }
2672
+ }
2673
+ // ============================================================================
2674
+ // Exports for testing
2675
+ // ============================================================================
2676
+ export { mergeInputs, readInputFiles, getDefaultConfig, loadConfigFile, saveConfigFile, setConfigValue, getConfigValue, saveContext, loadContext, listContexts, deleteContext, getCurrentContext, checkOpenCodeAvailable, runOpenCodeCommand, };
2677
+ //# sourceMappingURL=index.js.map