@phuetz/code-buddy 1.1.0 → 1.3.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 (381) hide show
  1. package/README.md +211 -163
  2. package/dist/agent/autonomous/agentic-coding-contract.d.ts +12 -12
  3. package/dist/agent/base-agent.d.ts +4 -0
  4. package/dist/agent/base-agent.js +6 -0
  5. package/dist/agent/codebuddy-agent.d.ts +1 -1
  6. package/dist/agent/codebuddy-agent.js +69 -14
  7. package/dist/agent/execution/agent-executor.js +122 -12
  8. package/dist/agent/execution/tool-dependency-graph.js +7 -0
  9. package/dist/agent/execution/tool-hooks.d.ts +6 -0
  10. package/dist/agent/execution/tool-hooks.js +13 -5
  11. package/dist/agent/execution/tool-selection-strategy.d.ts +11 -2
  12. package/dist/agent/execution/tool-selection-strategy.js +67 -10
  13. package/dist/agent/extended-thinking.d.ts +8 -0
  14. package/dist/agent/extended-thinking.js +27 -0
  15. package/dist/agent/facades/infrastructure-facade.d.ts +9 -2
  16. package/dist/agent/facades/infrastructure-facade.js +15 -6
  17. package/dist/agent/hermes-browser-backends.js +151 -11
  18. package/dist/agent/hermes-claw-migrate.d.ts +59 -0
  19. package/dist/agent/hermes-claw-migrate.js +427 -26
  20. package/dist/agent/hermes-parity-manifest.js +78 -71
  21. package/dist/agent/hermes-runtime-lifecycle.d.ts +67 -0
  22. package/dist/agent/hermes-runtime-lifecycle.js +468 -0
  23. package/dist/agent/middleware/index.d.ts +1 -0
  24. package/dist/agent/middleware/index.js +1 -0
  25. package/dist/agent/middleware/visual-validation-middleware.d.ts +17 -0
  26. package/dist/agent/middleware/visual-validation-middleware.js +67 -0
  27. package/dist/agent/model-benchmark.d.ts +77 -0
  28. package/dist/agent/model-benchmark.js +309 -0
  29. package/dist/agent/model-tier.d.ts +14 -0
  30. package/dist/agent/model-tier.js +71 -0
  31. package/dist/agent/multi-agent/agents/orchestrator-agent.js +17 -6
  32. package/dist/agent/multi-agent/multi-agent-system.js +3 -1
  33. package/dist/agent/multi-agent/session-fleet-bridge.d.ts +2 -0
  34. package/dist/agent/multi-agent/session-fleet-bridge.js +9 -1
  35. package/dist/agent/multi-agent/session-tools.js +22 -5
  36. package/dist/agent/reasoning/mcts.js +20 -6
  37. package/dist/agent/self-improvement/authored-artifact-gate.d.ts +18 -0
  38. package/dist/agent/self-improvement/authored-artifact-gate.js +42 -0
  39. package/dist/agent/self-improvement/authored-tool-runtime.d.ts +27 -0
  40. package/dist/agent/self-improvement/authored-tool-runtime.js +57 -0
  41. package/dist/agent/self-improvement/authored-tool-store.d.ts +24 -0
  42. package/dist/agent/self-improvement/authored-tool-store.js +57 -0
  43. package/dist/agent/self-improvement/llm-tool-proposer.d.ts +41 -0
  44. package/dist/agent/self-improvement/llm-tool-proposer.js +136 -0
  45. package/dist/agent/self-improvement/sandbox-scorer.d.ts +17 -0
  46. package/dist/agent/self-improvement/sandbox-scorer.js +43 -0
  47. package/dist/agent/self-improvement/self-knowledge.d.ts +8 -0
  48. package/dist/agent/self-improvement/self-knowledge.js +24 -0
  49. package/dist/agent/self-improvement/skill-benchmark.d.ts +9 -0
  50. package/dist/agent/self-improvement/skill-benchmark.js +22 -0
  51. package/dist/agent/self-improvement/skill-consolidator.d.ts +71 -0
  52. package/dist/agent/self-improvement/skill-consolidator.js +137 -0
  53. package/dist/agent/self-improvement/skill-engine.d.ts +42 -0
  54. package/dist/agent/self-improvement/skill-engine.js +87 -0
  55. package/dist/agent/self-improvement/skill-gate.d.ts +19 -0
  56. package/dist/agent/self-improvement/skill-gate.js +62 -0
  57. package/dist/agent/self-improvement/skill-mutator.d.ts +74 -0
  58. package/dist/agent/self-improvement/skill-mutator.js +223 -0
  59. package/dist/agent/self-improvement/skill-proposer.d.ts +40 -0
  60. package/dist/agent/self-improvement/skill-proposer.js +82 -0
  61. package/dist/agent/self-improvement/skill-types.d.ts +41 -0
  62. package/dist/agent/self-improvement/skill-types.js +13 -0
  63. package/dist/agent/self-improvement/tool-benchmark.d.ts +10 -0
  64. package/dist/agent/self-improvement/tool-benchmark.js +37 -0
  65. package/dist/agent/self-improvement/tool-engine.d.ts +54 -0
  66. package/dist/agent/self-improvement/tool-engine.js +101 -0
  67. package/dist/agent/self-improvement/tool-gate.d.ts +20 -0
  68. package/dist/agent/self-improvement/tool-gate.js +78 -0
  69. package/dist/agent/self-improvement/tool-proposer.d.ts +31 -0
  70. package/dist/agent/self-improvement/tool-proposer.js +34 -0
  71. package/dist/agent/self-improvement/tool-skill-mutator.d.ts +40 -0
  72. package/dist/agent/self-improvement/tool-skill-mutator.js +79 -0
  73. package/dist/agent/self-improvement/tool-types.d.ts +48 -0
  74. package/dist/agent/self-improvement/tool-types.js +9 -0
  75. package/dist/agent/self-improvement/types.d.ts +3 -1
  76. package/dist/agent/session-end-flush.d.ts +6 -1
  77. package/dist/agent/session-end-flush.js +20 -4
  78. package/dist/agent/streaming/streaming-handler.d.ts +7 -0
  79. package/dist/agent/streaming/streaming-handler.js +8 -1
  80. package/dist/agent/tool-executor.js +1 -0
  81. package/dist/agent/tool-handler.d.ts +5 -0
  82. package/dist/agent/tool-handler.js +133 -4
  83. package/dist/browser-automation/browser-operator-executor.js +15 -0
  84. package/dist/browser-automation/browser-use-runner.d.ts +96 -0
  85. package/dist/browser-automation/browser-use-runner.js +492 -0
  86. package/dist/browser-automation/camofox-runner.d.ts +107 -0
  87. package/dist/browser-automation/camofox-runner.js +287 -0
  88. package/dist/channels/dingtalk/index.js +3 -0
  89. package/dist/channels/discord/client.d.ts +9 -0
  90. package/dist/channels/discord/client.js +12 -0
  91. package/dist/channels/feishu/index.d.ts +167 -1
  92. package/dist/channels/feishu/index.js +432 -7
  93. package/dist/channels/gateway-lifecycle.d.ts +132 -0
  94. package/dist/channels/gateway-lifecycle.js +219 -0
  95. package/dist/channels/google-chat/index.d.ts +5 -1
  96. package/dist/channels/google-chat/index.js +5 -1
  97. package/dist/channels/imessage/index.d.ts +14 -0
  98. package/dist/channels/imessage/index.js +64 -17
  99. package/dist/channels/index.d.ts +4 -0
  100. package/dist/channels/index.js +4 -0
  101. package/dist/channels/irc/index.d.ts +73 -3
  102. package/dist/channels/irc/index.js +446 -11
  103. package/dist/channels/line/index.js +3 -0
  104. package/dist/channels/mattermost/index.d.ts +51 -4
  105. package/dist/channels/mattermost/index.js +303 -20
  106. package/dist/channels/nextcloud-talk/index.d.ts +89 -8
  107. package/dist/channels/nextcloud-talk/index.js +367 -16
  108. package/dist/channels/nostr/index.d.ts +121 -1
  109. package/dist/channels/nostr/index.js +396 -8
  110. package/dist/channels/ntfy/index.js +3 -0
  111. package/dist/channels/qq/index.js +3 -0
  112. package/dist/channels/slash-parity.d.ts +117 -0
  113. package/dist/channels/slash-parity.js +185 -0
  114. package/dist/channels/synology-chat/index.js +3 -0
  115. package/dist/channels/teams/index.d.ts +3 -0
  116. package/dist/channels/teams/index.js +3 -0
  117. package/dist/channels/telegram/client.d.ts +9 -0
  118. package/dist/channels/telegram/client.js +12 -0
  119. package/dist/channels/twilio-voice/index.js +3 -0
  120. package/dist/channels/webchat/index.d.ts +7 -1
  121. package/dist/channels/webchat/index.js +7 -1
  122. package/dist/channels/wecom/index.js +3 -0
  123. package/dist/channels/weixin/index.js +3 -0
  124. package/dist/channels/zalo/index.js +3 -0
  125. package/dist/cli/config-loader.js +1 -1
  126. package/dist/codebuddy/client.d.ts +30 -1
  127. package/dist/codebuddy/client.js +167 -20
  128. package/dist/codebuddy/providers/provider-chatgpt-responses.d.ts +5 -0
  129. package/dist/codebuddy/providers/provider-chatgpt-responses.js +7 -1
  130. package/dist/codebuddy/providers/provider-gemini-native.js +1 -1
  131. package/dist/codebuddy/providers/provider-openai-compat.d.ts +5 -0
  132. package/dist/codebuddy/providers/provider-openai-compat.js +82 -2
  133. package/dist/codebuddy/tool-definitions/computer-control-tools.js +32 -2
  134. package/dist/codebuddy/tool-definitions/core-tools.js +3 -3
  135. package/dist/codebuddy/tool-definitions/index.d.ts +2 -1
  136. package/dist/codebuddy/tool-definitions/index.js +2 -1
  137. package/dist/codebuddy/tool-definitions/multimodal-tools.d.ts +1 -0
  138. package/dist/codebuddy/tool-definitions/multimodal-tools.js +44 -1
  139. package/dist/codebuddy/tool-definitions/windows-tools.d.ts +2 -0
  140. package/dist/codebuddy/tool-definitions/windows-tools.js +34 -0
  141. package/dist/codebuddy/tools.d.ts +8 -1
  142. package/dist/codebuddy/tools.js +67 -24
  143. package/dist/commands/cli/hermes-commands.js +108 -0
  144. package/dist/commands/cli/improve-command.js +123 -0
  145. package/dist/commands/cli/native-engine-commands.js +102 -3
  146. package/dist/commands/cli/utility-commands.js +45 -0
  147. package/dist/commands/enhanced-command-handler.js +2 -2
  148. package/dist/commands/goal-cli.d.ts +30 -0
  149. package/dist/commands/goal-cli.js +210 -27
  150. package/dist/commands/handlers/goal-handler.d.ts +9 -2
  151. package/dist/commands/handlers/goal-handler.js +36 -9
  152. package/dist/commands/handlers/infra-handlers.js +36 -0
  153. package/dist/commands/handlers/memory-handlers.js +96 -1
  154. package/dist/commands/handlers/missing-handlers.d.ts +1 -1
  155. package/dist/commands/handlers/missing-handlers.js +26 -3
  156. package/dist/commands/headless-slash.d.ts +2 -0
  157. package/dist/commands/headless-slash.js +12 -0
  158. package/dist/commands/llm-provider-resolution.d.ts +5 -3
  159. package/dist/commands/llm-provider-resolution.js +87 -33
  160. package/dist/commands/ollama.d.ts +25 -0
  161. package/dist/commands/ollama.js +100 -0
  162. package/dist/commands/provider.d.ts +5 -0
  163. package/dist/commands/provider.js +106 -55
  164. package/dist/commands/skills-cli/index.js +123 -0
  165. package/dist/commands/slash/builtin-commands.js +1 -1
  166. package/dist/commands/spec-next.js +2 -1
  167. package/dist/commands/spec-plan.js +5 -16
  168. package/dist/commands/tunnel.d.ts +2 -0
  169. package/dist/commands/tunnel.js +48 -0
  170. package/dist/companion/percepts.js +11 -1
  171. package/dist/config/config-resolver.d.ts +2 -1
  172. package/dist/config/config-resolver.js +54 -41
  173. package/dist/config/constants.d.ts +28 -0
  174. package/dist/config/constants.js +7 -0
  175. package/dist/config/env-schema.js +756 -0
  176. package/dist/config/model-tools.js +4 -4
  177. package/dist/config/toml-config.d.ts +16 -0
  178. package/dist/config/toml-config.js +3 -0
  179. package/dist/context/bootstrap-loader.js +6 -23
  180. package/dist/context/context-manager-v2.js +1 -0
  181. package/dist/context/import-directive-parser.d.ts +4 -0
  182. package/dist/context/import-directive-parser.js +51 -6
  183. package/dist/context/instruction-excludes.d.ts +30 -1
  184. package/dist/context/instruction-excludes.js +71 -1
  185. package/dist/context/jit-context.d.ts +8 -10
  186. package/dist/context/jit-context.js +28 -106
  187. package/dist/context/project-context.d.ts +90 -0
  188. package/dist/context/project-context.js +295 -0
  189. package/dist/daemon/autonomous-daemon.d.ts +1 -1
  190. package/dist/daemon/autonomous-daemon.js +3 -3
  191. package/dist/daemon/autonomous-loop.d.ts +31 -1
  192. package/dist/daemon/autonomous-loop.js +91 -4
  193. package/dist/daemon/colab-goal.js +9 -1
  194. package/dist/daemon/cron-agent-bridge.d.ts +12 -3
  195. package/dist/daemon/cron-agent-bridge.js +25 -9
  196. package/dist/desktop/codebuddy-engine-adapter.d.ts +32 -0
  197. package/dist/desktop/codebuddy-engine-adapter.js +257 -80
  198. package/dist/desktop/engine-adapter.d.ts +14 -0
  199. package/dist/desktop-automation/automation-manager.js +16 -0
  200. package/dist/desktop-automation/omniparser-runner.d.ts +63 -0
  201. package/dist/desktop-automation/omniparser-runner.js +115 -0
  202. package/dist/desktop-automation/smart-snapshot.d.ts +11 -0
  203. package/dist/desktop-automation/smart-snapshot.js +72 -5
  204. package/dist/doctor/index.js +40 -23
  205. package/dist/events/types.d.ts +11 -0
  206. package/dist/fleet/colab-store.js +14 -2
  207. package/dist/fleet/peer-session-bridge.js +50 -12
  208. package/dist/fleet/peer-tool-bridge.js +14 -0
  209. package/dist/goals/goal-decomposer.d.ts +27 -0
  210. package/dist/goals/goal-decomposer.js +293 -0
  211. package/dist/goals/goal-judge-client.d.ts +15 -0
  212. package/dist/goals/goal-judge-client.js +45 -0
  213. package/dist/goals/goal-judge.d.ts +2 -0
  214. package/dist/goals/goal-judge.js +35 -6
  215. package/dist/goals/goal-loop.d.ts +14 -0
  216. package/dist/goals/goal-loop.js +47 -2
  217. package/dist/goals/goal-manager.d.ts +6 -0
  218. package/dist/goals/goal-manager.js +67 -14
  219. package/dist/goals/goal-state.d.ts +13 -0
  220. package/dist/goals/goal-state.js +83 -13
  221. package/dist/goals/goal-store.d.ts +3 -0
  222. package/dist/goals/goal-store.js +31 -15
  223. package/dist/harness/contract.d.ts +28 -28
  224. package/dist/hooks/user-hooks.js +17 -3
  225. package/dist/identity/identity-manager.js +3 -2
  226. package/dist/index.js +481 -26
  227. package/dist/input/text-to-speech.d.ts +2 -6
  228. package/dist/input/text-to-speech.js +2 -27
  229. package/dist/integrations/screenpipe/screenpipe-client.d.ts +10 -0
  230. package/dist/integrations/screenpipe/screenpipe-client.js +12 -2
  231. package/dist/integrations/tailscale.d.ts +13 -0
  232. package/dist/integrations/tailscale.js +87 -34
  233. package/dist/knowledge/workspace-indexer.js +53 -9
  234. package/dist/mcp/client.js +1 -0
  235. package/dist/mcp/mcp-desktop-tools.d.ts +23 -0
  236. package/dist/mcp/mcp-desktop-tools.js +158 -0
  237. package/dist/mcp/mcp-resources.js +2 -3
  238. package/dist/mcp/mcp-server.js +2 -0
  239. package/dist/memory/enhanced-memory.d.ts +10 -0
  240. package/dist/memory/enhanced-memory.js +33 -2
  241. package/dist/memory/index.d.ts +3 -1
  242. package/dist/memory/index.js +4 -1
  243. package/dist/memory/memory-auto-proposer.d.ts +23 -0
  244. package/dist/memory/memory-auto-proposer.js +308 -0
  245. package/dist/memory/memory-candidate-queue.d.ts +92 -0
  246. package/dist/memory/memory-candidate-queue.js +261 -0
  247. package/dist/memory/persistent-memory.d.ts +45 -2
  248. package/dist/memory/persistent-memory.js +236 -40
  249. package/dist/ml/bayesian-qualifier.d.ts +1 -1
  250. package/dist/ml/bayesian-qualifier.js +35 -2
  251. package/dist/openclaw/gateway-bridge.js +5 -0
  252. package/dist/plugins/marketplace.d.ts +1 -0
  253. package/dist/plugins/marketplace.js +7 -0
  254. package/dist/prompts/execution-discipline.d.ts +14 -0
  255. package/dist/prompts/execution-discipline.js +29 -0
  256. package/dist/prompts/variation-injector.js +9 -2
  257. package/dist/protocols/acp/acp-agentic-runner.d.ts +7 -6
  258. package/dist/protocols/acp/acp-agentic-runner.js +115 -18
  259. package/dist/protocols/acp/acp-session-store.d.ts +23 -0
  260. package/dist/protocols/acp/acp-session-store.js +77 -0
  261. package/dist/protocols/acp/acp-stdio-server.d.ts +7 -0
  262. package/dist/protocols/acp/acp-stdio-server.js +71 -16
  263. package/dist/providers/active-llm-registry.d.ts +37 -0
  264. package/dist/providers/active-llm-registry.js +186 -0
  265. package/dist/providers/auxiliary-provider.d.ts +25 -0
  266. package/dist/providers/auxiliary-provider.js +192 -0
  267. package/dist/providers/codex-oauth.d.ts +1 -1
  268. package/dist/providers/codex-oauth.js +27 -4
  269. package/dist/providers/index.d.ts +3 -0
  270. package/dist/providers/index.js +4 -0
  271. package/dist/providers/provider-catalog.d.ts +70 -0
  272. package/dist/providers/provider-catalog.js +738 -0
  273. package/dist/providers/provider-fallback.d.ts +35 -0
  274. package/dist/providers/provider-fallback.js +171 -0
  275. package/dist/providers/xai-oauth.d.ts +128 -0
  276. package/dist/providers/xai-oauth.js +735 -0
  277. package/dist/scheduler/cron-scheduler.d.ts +15 -3
  278. package/dist/scheduler/cron-scheduler.js +53 -7
  279. package/dist/scheduler/script-runner.d.ts +2 -0
  280. package/dist/scheduler/script-runner.js +19 -4
  281. package/dist/scheduler/watchdog-handlers.js +7 -20
  282. package/dist/search/usearch-index.js +7 -2
  283. package/dist/security/tool-policy/tool-groups.js +2 -0
  284. package/dist/sensory/dreaming.d.ts +45 -0
  285. package/dist/sensory/dreaming.js +114 -0
  286. package/dist/sensory/heartbeat-scheduler.d.ts +38 -0
  287. package/dist/sensory/heartbeat-scheduler.js +72 -0
  288. package/dist/sensory/reactions.d.ts +24 -0
  289. package/dist/sensory/reactions.js +31 -0
  290. package/dist/sensory/screen-reaction.d.ts +23 -0
  291. package/dist/sensory/screen-reaction.js +59 -0
  292. package/dist/sensory/sensory-bridge.d.ts +23 -0
  293. package/dist/sensory/sensory-bridge.js +85 -0
  294. package/dist/sensory/sensory-memory.d.ts +20 -0
  295. package/dist/sensory/sensory-memory.js +39 -0
  296. package/dist/sensory/speech-reaction.d.ts +21 -0
  297. package/dist/sensory/speech-reaction.js +83 -0
  298. package/dist/sensory/vision-reaction.d.ts +31 -0
  299. package/dist/sensory/vision-reaction.js +74 -0
  300. package/dist/server/index.js +106 -2
  301. package/dist/server/routes/mobile.d.ts +12 -4
  302. package/dist/server/routes/mobile.js +116 -1
  303. package/dist/server/tls-config.d.ts +35 -0
  304. package/dist/server/tls-config.js +142 -0
  305. package/dist/server/tunnel-manager.d.ts +20 -0
  306. package/dist/server/tunnel-manager.js +58 -0
  307. package/dist/server/websocket/fleet-bridge.js +5 -0
  308. package/dist/services/prompt-builder.d.ts +11 -0
  309. package/dist/services/prompt-builder.js +124 -17
  310. package/dist/shared/engine-types.d.ts +15 -1
  311. package/dist/sidecar/sidecar-bridge.d.ts +1 -0
  312. package/dist/sidecar/sidecar-bridge.js +21 -10
  313. package/dist/skills/parser.js +3 -0
  314. package/dist/skills/skill-importer.d.ts +58 -0
  315. package/dist/skills/skill-importer.js +261 -0
  316. package/dist/skills/skill-sources.d.ts +20 -0
  317. package/dist/skills/skill-sources.js +102 -0
  318. package/dist/skills/types.d.ts +6 -0
  319. package/dist/spec/spec-store.js +8 -1
  320. package/dist/talk-mode/providers/audioreader-tts.d.ts +1 -1
  321. package/dist/talk-mode/providers/audioreader-tts.js +8 -8
  322. package/dist/templates/project-scaffolding.js +3 -2
  323. package/dist/themes/theme-schema.d.ts +10 -10
  324. package/dist/tools/application-profiles.js +38 -0
  325. package/dist/tools/bash/bash-tool.d.ts +1 -0
  326. package/dist/tools/bash/bash-tool.js +16 -2
  327. package/dist/tools/bash/command-validator.js +3 -0
  328. package/dist/tools/bash/rtk-rewrite.d.ts +16 -0
  329. package/dist/tools/bash/rtk-rewrite.js +100 -0
  330. package/dist/tools/bash/streaming-executor.js +14 -1
  331. package/dist/tools/computer-control-tool.d.ts +16 -1
  332. package/dist/tools/computer-control-tool.js +317 -5
  333. package/dist/tools/document-generator.d.ts +14 -0
  334. package/dist/tools/document-generator.js +79 -0
  335. package/dist/tools/execute-code-rpc-invoker.d.ts +26 -2
  336. package/dist/tools/execute-code-rpc-invoker.js +46 -5
  337. package/dist/tools/metadata.js +28 -0
  338. package/dist/tools/office-macro-tool.d.ts +10 -0
  339. package/dist/tools/office-macro-tool.js +93 -0
  340. package/dist/tools/register-tool-handler.d.ts +25 -0
  341. package/dist/tools/register-tool-handler.js +100 -0
  342. package/dist/tools/registry/index.d.ts +2 -1
  343. package/dist/tools/registry/index.js +2 -1
  344. package/dist/tools/registry/memory-tools.d.ts +20 -0
  345. package/dist/tools/registry/memory-tools.js +225 -3
  346. package/dist/tools/registry/multimodal-tools.js +2 -2
  347. package/dist/tools/registry/vision-tools.d.ts +33 -0
  348. package/dist/tools/registry/vision-tools.js +308 -6
  349. package/dist/tools/registry/windows-tools.d.ts +2 -0
  350. package/dist/tools/registry/windows-tools.js +47 -0
  351. package/dist/tools/registry.d.ts +6 -0
  352. package/dist/tools/registry.js +8 -0
  353. package/dist/tools/route-peer-tool.js +14 -0
  354. package/dist/tools/screenshot-tool.js +14 -2
  355. package/dist/tools/text-to-speech-tool.d.ts +1 -1
  356. package/dist/tools/text-to-speech-tool.js +2 -12
  357. package/dist/tools/tool-selector.js +3 -59
  358. package/dist/utils/config-validation/schema.d.ts +40 -7
  359. package/dist/utils/config-validation/schema.js +130 -1
  360. package/dist/utils/cost-tracker.js +21 -1
  361. package/dist/utils/disk-guard.d.ts +180 -0
  362. package/dist/utils/disk-guard.js +404 -0
  363. package/dist/utils/init-project.d.ts +7 -0
  364. package/dist/utils/init-project.js +37 -0
  365. package/dist/utils/interactive-setup.js +35 -2
  366. package/dist/utils/model-utils.js +11 -2
  367. package/dist/utils/output-sanitizer.js +11 -0
  368. package/dist/utils/provider-detector.d.ts +8 -7
  369. package/dist/utils/provider-detector.js +19 -77
  370. package/dist/utils/settings-manager.d.ts +19 -0
  371. package/dist/utils/token-display.d.ts +3 -3
  372. package/dist/utils/token-display.js +22 -4
  373. package/dist/wizard/onboarding.d.ts +39 -0
  374. package/dist/wizard/onboarding.js +433 -21
  375. package/dist/wizard/provider-onboarding.d.ts +8 -23
  376. package/dist/wizard/provider-onboarding.js +39 -158
  377. package/package.json +4 -2
  378. package/dist/plugins/provider-onboarding.d.ts +0 -23
  379. package/dist/plugins/provider-onboarding.js +0 -116
  380. package/dist/utils/kokoro-tts.d.ts +0 -8
  381. package/dist/utils/kokoro-tts.js +0 -67
@@ -1,25 +1,104 @@
1
1
  /**
2
2
  * IRC Channel Adapter
3
3
  *
4
- * Connects to IRC servers for sending/receiving messages.
5
- * Supports multiple channels, SASL auth, and TLS.
4
+ * Connects to IRC servers for sending/receiving messages over a real,
5
+ * long-lived TCP (or TLS) socket implementing an RFC 1459/2812 subset.
6
+ * Supports multiple channels, password auth, TLS, and auto-reconnect with
7
+ * exponential backoff (shared ReconnectionManager idiom — same as
8
+ * imessage/discord/slack).
6
9
  */
10
+ import { EventEmitter } from 'events';
11
+ import * as net from 'node:net';
12
+ import * as tls from 'node:tls';
7
13
  import { logger } from '../../utils/logger.js';
8
- import { BaseChannel } from '../core.js';
9
- export class IRCAdapter {
14
+ import { BaseChannel, } from '../core.js';
15
+ import { ReconnectionManager } from '../reconnection-manager.js';
16
+ /**
17
+ * Parse a raw IRC line (without the trailing CRLF) into prefix/command/params.
18
+ *
19
+ * Handles both prefixed and unprefixed lines — this distinction is
20
+ * load-bearing: the welcome reply `001 <nick> :Welcome` has NO prefix while
21
+ * `:nick!u@h PRIVMSG #cb :text` does. Treating tokens[0] as always-prefix (or
22
+ * never-prefix) misparses one of them.
23
+ */
24
+ export function parseIRCLine(line) {
25
+ let rest = line;
26
+ let prefix;
27
+ if (rest.startsWith(':')) {
28
+ const spaceIdx = rest.indexOf(' ');
29
+ if (spaceIdx === -1)
30
+ return null;
31
+ prefix = rest.slice(1, spaceIdx);
32
+ rest = rest.slice(spaceIdx + 1);
33
+ }
34
+ // Split off the trailing parameter (everything after " :") which may
35
+ // contain spaces.
36
+ let trailing;
37
+ const trailingIdx = rest.indexOf(' :');
38
+ if (rest.startsWith(':')) {
39
+ // Whole remainder is the trailing param.
40
+ trailing = rest.slice(1);
41
+ rest = '';
42
+ }
43
+ else if (trailingIdx !== -1) {
44
+ trailing = rest.slice(trailingIdx + 2);
45
+ rest = rest.slice(0, trailingIdx);
46
+ }
47
+ const tokens = rest.length > 0 ? rest.split(' ').filter((t) => t.length > 0) : [];
48
+ const command = tokens.shift();
49
+ if (!command) {
50
+ // Possible only if the line was entirely a trailing param — invalid.
51
+ return null;
52
+ }
53
+ const params = tokens;
54
+ if (trailing !== undefined)
55
+ params.push(trailing);
56
+ return { prefix, command: command.toUpperCase(), params };
57
+ }
58
+ /** Extract the nick portion of an IRC prefix (`nick!user@host` → `nick`). */
59
+ function nickFromPrefix(prefix) {
60
+ if (!prefix)
61
+ return '';
62
+ const bang = prefix.indexOf('!');
63
+ return bang === -1 ? prefix : prefix.slice(0, bang);
64
+ }
65
+ export class IRCAdapter extends EventEmitter {
10
66
  config;
11
67
  running = false;
12
68
  joinedChannels = new Set();
69
+ socket = null;
70
+ recvBuffer = '';
71
+ /** True while an intentional disconnect is in progress — suppresses reconnect. */
72
+ closing = false;
73
+ /** True once a close/error for the current socket has been handled (de-dup). */
74
+ closeHandled = false;
75
+ reconnecting = false;
76
+ reconnectionManager;
13
77
  constructor(config) {
78
+ super();
14
79
  this.config = {
15
80
  port: config.useTLS ? 6697 : 6667,
16
81
  username: config.nick,
17
82
  realname: config.nick,
18
83
  useTLS: false,
19
84
  sasl: false,
85
+ connectTimeoutMs: 15000,
86
+ maxRetries: 10,
87
+ retryDelayMs: 2000,
20
88
  ...config,
21
89
  };
90
+ // IRC is a genuinely persistent protocol (one long-lived TCP socket); a
91
+ // dropped socket is recovered with the shared exponential-backoff manager,
92
+ // same idiom as discord/imessage/slack.
93
+ this.reconnectionManager = new ReconnectionManager('irc', {
94
+ maxRetries: this.config.maxRetries ?? 10,
95
+ initialDelayMs: this.config.retryDelayMs ?? 2000,
96
+ maxDelayMs: 60000,
97
+ });
22
98
  }
99
+ // ==========================================================================
100
+ // Lifecycle
101
+ // ==========================================================================
23
102
  async start() {
24
103
  if (this.running) {
25
104
  throw new Error('IRCAdapter is already running');
@@ -30,26 +109,333 @@ export class IRCAdapter {
30
109
  nick: this.config.nick,
31
110
  tls: this.config.useTLS,
32
111
  });
112
+ await this.connectInternal();
113
+ // Connectivity confirmed for this session — reset any inherited backoff
114
+ // state so a fresh start() never starts pre-exhausted.
115
+ this.reconnectionManager.onConnected();
33
116
  this.running = true;
34
- for (const ch of this.config.channels) {
35
- this.joinedChannels.add(ch);
36
- }
117
+ this.emit('connected');
118
+ logger.info('IRCAdapter: connected', { server: this.config.server, nick: this.config.nick });
37
119
  }
38
120
  async stop() {
39
121
  if (!this.running) {
40
122
  throw new Error('IRCAdapter is not running');
41
123
  }
42
124
  logger.debug('IRCAdapter: disconnecting');
125
+ this.closing = true;
126
+ this.reconnectionManager.cancel();
127
+ this.reconnecting = false;
128
+ const sock = this.socket;
129
+ if (sock) {
130
+ try {
131
+ if (sock.writable) {
132
+ sock.write('QUIT :Code Buddy signing off\r\n');
133
+ }
134
+ }
135
+ catch {
136
+ // best-effort QUIT
137
+ }
138
+ sock.removeAllListeners();
139
+ sock.destroy();
140
+ }
141
+ this.socket = null;
142
+ this.recvBuffer = '';
43
143
  this.joinedChannels.clear();
44
144
  this.running = false;
145
+ this.emit('disconnected');
146
+ logger.info('IRCAdapter: disconnected');
45
147
  }
46
148
  isRunning() {
47
149
  return this.running;
48
150
  }
151
+ getConfig() {
152
+ return { ...this.config };
153
+ }
154
+ /**
155
+ * Open the socket, perform the registration handshake, and resolve once the
156
+ * server sends the 001 welcome numeric. Used by both start() and the
157
+ * reconnect callback (so it deliberately omits the running-guard).
158
+ */
159
+ connectInternal() {
160
+ return new Promise((resolve, reject) => {
161
+ this.closing = false;
162
+ this.closeHandled = false;
163
+ this.recvBuffer = '';
164
+ const host = this.config.server;
165
+ const port = this.config.port ?? (this.config.useTLS ? 6697 : 6667);
166
+ let settled = false;
167
+ let timeout = null;
168
+ const cleanupSettle = () => {
169
+ if (timeout) {
170
+ clearTimeout(timeout);
171
+ timeout = null;
172
+ }
173
+ };
174
+ const onWelcome = () => {
175
+ if (settled)
176
+ return;
177
+ settled = true;
178
+ cleanupSettle();
179
+ resolve();
180
+ };
181
+ const onFail = (err) => {
182
+ if (settled)
183
+ return;
184
+ settled = true;
185
+ cleanupSettle();
186
+ if (sock) {
187
+ sock.removeAllListeners();
188
+ sock.destroy();
189
+ }
190
+ if (this.socket === sock)
191
+ this.socket = null;
192
+ reject(err);
193
+ };
194
+ const onConnectTcp = () => {
195
+ // TCP is up; perform the IRC registration handshake. The connection is
196
+ // not "ready" until the server replies 001.
197
+ try {
198
+ if (this.config.password) {
199
+ this.write(`PASS ${this.config.password}`);
200
+ }
201
+ this.write(`NICK ${this.config.nick}`);
202
+ this.write(`USER ${this.config.username ?? this.config.nick} 0 * :${this.config.realname ?? this.config.nick}`);
203
+ }
204
+ catch (err) {
205
+ onFail(err instanceof Error ? err : new Error(String(err)));
206
+ }
207
+ };
208
+ let sock;
209
+ try {
210
+ if (this.config.useTLS) {
211
+ sock = tls.connect({ host, port, servername: host }, onConnectTcp);
212
+ }
213
+ else {
214
+ sock = net.createConnection({ host, port }, onConnectTcp);
215
+ }
216
+ }
217
+ catch (err) {
218
+ onFail(err instanceof Error ? err : new Error(String(err)));
219
+ return;
220
+ }
221
+ this.socket = sock;
222
+ sock.setEncoding('utf8');
223
+ sock.on('data', (chunk) => {
224
+ this.handleData(chunk, onWelcome);
225
+ });
226
+ sock.on('error', (err) => {
227
+ if (!settled) {
228
+ onFail(err);
229
+ return;
230
+ }
231
+ this.handleSocketClosed(sock, err);
232
+ });
233
+ sock.on('close', () => {
234
+ if (!settled) {
235
+ onFail(new Error('IRC socket closed before registration completed'));
236
+ return;
237
+ }
238
+ this.handleSocketClosed(sock);
239
+ });
240
+ timeout = setTimeout(() => {
241
+ onFail(new Error(`IRC registration timed out after ${this.config.connectTimeoutMs}ms`));
242
+ }, this.config.connectTimeoutMs ?? 15000);
243
+ timeout.unref?.();
244
+ });
245
+ }
246
+ // ==========================================================================
247
+ // Inbound handling
248
+ // ==========================================================================
249
+ /**
250
+ * Buffer incoming bytes and dispatch complete CRLF-terminated lines.
251
+ * `onWelcome` is invoked when the 001 numeric is seen (resolves connect()).
252
+ */
253
+ handleData(chunk, onWelcome) {
254
+ this.recvBuffer += chunk;
255
+ // RFC 1459 caps a line at 512 bytes. Guard against a peer that streams bytes
256
+ // without ever sending a newline (unbounded buffer growth -> OOM): drop the
257
+ // connection, which the close handler turns into a backoff reconnect.
258
+ if (this.recvBuffer.length > 8192) {
259
+ logger.warn('IRCAdapter: line buffer overflow, dropping connection', { size: this.recvBuffer.length });
260
+ this.recvBuffer = '';
261
+ this.socket?.destroy(new Error('IRC line buffer overflow'));
262
+ return;
263
+ }
264
+ let idx;
265
+ // IRC servers terminate lines with \r\n, but be lenient and split on \n.
266
+ while ((idx = this.recvBuffer.indexOf('\n')) !== -1) {
267
+ let line = this.recvBuffer.slice(0, idx);
268
+ this.recvBuffer = this.recvBuffer.slice(idx + 1);
269
+ if (line.endsWith('\r'))
270
+ line = line.slice(0, -1);
271
+ if (line.length === 0)
272
+ continue;
273
+ this.handleLine(line, onWelcome);
274
+ }
275
+ }
276
+ handleLine(line, onWelcome) {
277
+ const msg = parseIRCLine(line);
278
+ if (!msg)
279
+ return;
280
+ switch (msg.command) {
281
+ case 'PING': {
282
+ // Reply with the same token so the server keeps the link alive.
283
+ const token = msg.params[msg.params.length - 1] ?? '';
284
+ this.write(`PONG :${token}`);
285
+ return;
286
+ }
287
+ case '001': {
288
+ // Welcome numeric — registration succeeded. Join configured channels.
289
+ for (const ch of this.config.channels) {
290
+ this.write(`JOIN ${ch}`);
291
+ this.joinedChannels.add(ch);
292
+ }
293
+ onWelcome();
294
+ return;
295
+ }
296
+ case 'PRIVMSG': {
297
+ this.handlePrivmsg(msg);
298
+ return;
299
+ }
300
+ case 'ERROR': {
301
+ logger.debug('IRCAdapter: server ERROR', { text: msg.params.join(' ') });
302
+ return;
303
+ }
304
+ default:
305
+ // Other numerics / commands are ignored for this subset.
306
+ return;
307
+ }
308
+ }
309
+ handlePrivmsg(msg) {
310
+ const target = msg.params[0] ?? '';
311
+ const text = msg.params[1] ?? '';
312
+ const senderNick = nickFromPrefix(msg.prefix);
313
+ // CTCP ACTION (/me) arrives wrapped in \x01ACTION ... \x01.
314
+ let content = text;
315
+ let contentType = 'text';
316
+ if (text.startsWith('ACTION ') && text.endsWith('')) {
317
+ content = text.slice('ACTION '.length, -1);
318
+ }
319
+ const isCommand = content.startsWith('/');
320
+ if (isCommand)
321
+ contentType = 'command';
322
+ const message = {
323
+ id: `irc-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
324
+ channel: {
325
+ id: target,
326
+ type: 'irc',
327
+ name: target,
328
+ isDM: !target.startsWith('#') && !target.startsWith('&'),
329
+ isGroup: target.startsWith('#') || target.startsWith('&'),
330
+ },
331
+ sender: {
332
+ id: senderNick,
333
+ username: senderNick,
334
+ displayName: senderNick,
335
+ },
336
+ content,
337
+ contentType,
338
+ timestamp: new Date(),
339
+ raw: { prefix: msg.prefix, command: msg.command, params: msg.params },
340
+ };
341
+ if (isCommand) {
342
+ const parts = content.slice(1).split(/\s+/);
343
+ message.isCommand = true;
344
+ message.commandName = parts[0];
345
+ message.commandArgs = parts.slice(1);
346
+ }
347
+ this.emit('message', message);
348
+ if (isCommand) {
349
+ this.emit('command', message);
350
+ }
351
+ }
352
+ // ==========================================================================
353
+ // Reconnection
354
+ // ==========================================================================
355
+ /**
356
+ * Handle a socket 'close' or 'error' that was NOT triggered by an
357
+ * intentional disconnect. De-dupes the error→close pair (ECONNRESET fires
358
+ * 'error' then 'close') and drives a single reconnect via the shared
359
+ * ReconnectionManager.
360
+ */
361
+ handleSocketClosed(sock, err) {
362
+ // Only act on the socket we currently own and only once per drop.
363
+ if (sock !== this.socket || this.closeHandled)
364
+ return;
365
+ this.closeHandled = true;
366
+ if (err) {
367
+ logger.warn('IRCAdapter: socket error', { error: err.message });
368
+ }
369
+ sock.removeAllListeners();
370
+ this.socket = null;
371
+ // Intentional disconnect — do not reconnect.
372
+ if (this.closing || !this.running) {
373
+ return;
374
+ }
375
+ logger.warn('IRCAdapter: connection dropped, scheduling reconnect');
376
+ this.emit('disconnected', err ?? new Error('IRC connection dropped'));
377
+ this.reconnect();
378
+ }
379
+ /**
380
+ * Recover a dropped connection via the shared ReconnectionManager
381
+ * (exponential backoff + jitter + exhaustion). `scheduleReconnect` is
382
+ * single-shot, so a failed attempt re-drives it (deferred past the manager's
383
+ * internal active-guard) until recovery or exhaustion.
384
+ */
385
+ reconnect() {
386
+ if (this.reconnecting)
387
+ return;
388
+ if (this.reconnectionManager.listenerCount('exhausted') === 0) {
389
+ this.reconnectionManager.on('exhausted', () => {
390
+ this.reconnecting = false;
391
+ this.running = false;
392
+ this.emit('disconnected', new Error('IRC reconnection failed after all retries'));
393
+ logger.error('IRCAdapter: reconnection failed permanently');
394
+ });
395
+ }
396
+ this.reconnecting = true;
397
+ this.reconnectionManager.scheduleReconnect(async () => {
398
+ try {
399
+ await this.connectInternal();
400
+ this.reconnecting = false;
401
+ this.reconnectionManager.onConnected();
402
+ this.emit('reconnected');
403
+ this.emit('connected');
404
+ logger.info('IRCAdapter: reconnected successfully');
405
+ }
406
+ catch (error) {
407
+ // Re-drive after the manager clears its internal active-flag (it does
408
+ // so in its own finally once this closure settles).
409
+ if (this.running && !this.closing) {
410
+ setTimeout(() => {
411
+ if (this.running && this.reconnecting && !this.closing) {
412
+ this.reconnecting = false;
413
+ this.reconnect();
414
+ }
415
+ }, 0).unref?.();
416
+ }
417
+ throw error instanceof Error ? error : new Error(String(error));
418
+ }
419
+ });
420
+ }
421
+ // ==========================================================================
422
+ // Outbound / API
423
+ // ==========================================================================
424
+ write(line) {
425
+ const sock = this.socket;
426
+ if (!sock || !sock.writable) {
427
+ throw new Error('IRCAdapter: socket is not writable');
428
+ }
429
+ sock.write(`${line}\r\n`);
430
+ }
49
431
  async sendMessage(target, text) {
50
432
  if (!this.running) {
51
433
  throw new Error('IRCAdapter is not running');
52
434
  }
435
+ // Split on newlines: IRC PRIVMSG is one line per message.
436
+ for (const line of text.split(/\r?\n/)) {
437
+ this.write(`PRIVMSG ${target} :${line}`);
438
+ }
53
439
  logger.debug('IRCAdapter: PRIVMSG', { target, textLength: text.length });
54
440
  return { success: true };
55
441
  }
@@ -57,6 +443,9 @@ export class IRCAdapter {
57
443
  if (!this.running) {
58
444
  throw new Error('IRCAdapter is not running');
59
445
  }
446
+ for (const line of text.split(/\r?\n/)) {
447
+ this.write(`NOTICE ${target} :${line}`);
448
+ }
60
449
  logger.debug('IRCAdapter: NOTICE', { target, textLength: text.length });
61
450
  return { success: true };
62
451
  }
@@ -64,6 +453,7 @@ export class IRCAdapter {
64
453
  if (!this.running) {
65
454
  throw new Error('IRCAdapter is not running');
66
455
  }
456
+ this.write(`PRIVMSG ${target} :ACTION ${text}`);
67
457
  logger.debug('IRCAdapter: ACTION', { target, textLength: text.length });
68
458
  return { success: true };
69
459
  }
@@ -71,6 +461,7 @@ export class IRCAdapter {
71
461
  if (!this.running) {
72
462
  throw new Error('IRCAdapter is not running');
73
463
  }
464
+ this.write(`JOIN ${channel}`);
74
465
  this.joinedChannels.add(channel);
75
466
  logger.debug('IRCAdapter: JOIN', { channel });
76
467
  }
@@ -78,6 +469,7 @@ export class IRCAdapter {
78
469
  if (!this.running) {
79
470
  throw new Error('IRCAdapter is not running');
80
471
  }
472
+ this.write(reason ? `PART ${channel} :${reason}` : `PART ${channel}`);
81
473
  this.joinedChannels.delete(channel);
82
474
  logger.debug('IRCAdapter: PART', { channel, reason });
83
475
  }
@@ -91,6 +483,7 @@ export class IRCAdapter {
91
483
  if (!this.running) {
92
484
  throw new Error('IRCAdapter is not running');
93
485
  }
486
+ this.write(`NICK ${nick}`);
94
487
  this.config.nick = nick;
95
488
  logger.debug('IRCAdapter: NICK', { nick });
96
489
  }
@@ -112,24 +505,66 @@ export class IRCChannel extends BaseChannel {
112
505
  channels: cfg.channels || [],
113
506
  useTLS: cfg.useTLS,
114
507
  sasl: cfg.sasl,
508
+ connectTimeoutMs: cfg.connectTimeoutMs,
509
+ maxRetries: cfg.maxRetries,
510
+ retryDelayMs: cfg.retryDelayMs,
511
+ });
512
+ // Forward adapter events onto the BaseChannel event surface.
513
+ this.adapter.on('message', (message) => {
514
+ this.status.lastActivity = new Date();
515
+ this.emit('message', message);
516
+ });
517
+ this.adapter.on('command', (message) => {
518
+ this.emit('command', message);
519
+ });
520
+ this.adapter.on('reconnected', () => {
521
+ this.status.connected = true;
522
+ this.status.lastActivity = new Date();
523
+ });
524
+ this.adapter.on('disconnected', (err) => {
525
+ this.status.connected = false;
526
+ // A mid-session 'disconnected' from the adapter means an unexpected drop
527
+ // (the adapter is now reconnecting); surface it without tearing down.
528
+ this.emit('disconnected', this.type, err);
529
+ });
530
+ this.adapter.on('error', (err) => {
531
+ this.status.error = err.message;
532
+ this.emit('error', this.type, err);
115
533
  });
116
534
  await this.adapter.start();
117
535
  this.status.connected = true;
536
+ this.status.authenticated = true;
537
+ this.status.lastActivity = new Date();
538
+ this.emit('connected', this.type);
118
539
  }
119
540
  async disconnect() {
120
541
  if (this.adapter) {
121
- await this.adapter.stop();
542
+ if (this.adapter.isRunning()) {
543
+ await this.adapter.stop();
544
+ }
545
+ this.adapter.removeAllListeners();
122
546
  this.adapter = null;
123
547
  }
124
548
  this.status.connected = false;
125
549
  }
126
550
  async send(message) {
127
- if (!this.adapter) {
551
+ if (!this.adapter || !this.adapter.isRunning()) {
128
552
  return { success: false, error: 'Not connected', timestamp: new Date() };
129
553
  }
130
554
  const target = message.channelId || this.config.channels?.[0] || '';
131
- const result = await this.adapter.sendMessage(target, message.content);
132
- return { success: result.success, timestamp: new Date() };
555
+ try {
556
+ const result = await this.adapter.sendMessage(target, message.content);
557
+ this.status.lastActivity = new Date();
558
+ return { success: result.success, timestamp: new Date() };
559
+ }
560
+ catch (error) {
561
+ return {
562
+ success: false,
563
+ error: error instanceof Error ? error.message : String(error),
564
+ timestamp: new Date(),
565
+ };
566
+ }
133
567
  }
134
568
  }
569
+ export default IRCAdapter;
135
570
  //# sourceMappingURL=index.js.map
@@ -88,6 +88,9 @@ export class LINEChannel extends BaseChannel {
88
88
  port: config.port,
89
89
  });
90
90
  }
91
+ // REST/webhook adapter — outbound via the LINE Messaging API, inbound via
92
+ // webhook callbacks; no persistent connection is held open, so reconnection
93
+ // (ReconnectionManager) is N/A.
91
94
  async connect() {
92
95
  await this.adapter.start();
93
96
  this.status.connected = true;
@@ -1,20 +1,46 @@
1
1
  /**
2
2
  * Mattermost Channel Adapter
3
3
  *
4
- * Connects to Mattermost via WebSocket for real-time messaging.
5
- * Provides a lightweight in-process adapter for lifecycle and send flows.
4
+ * Connects to Mattermost via its real-time WebSocket gateway
5
+ * (`/api/v4/websocket`) for inbound events and the REST API
6
+ * (`/api/v4/posts`) for outbound messages.
7
+ *
8
+ * Transport details:
9
+ * - Auth: a personal-access / bot token (`config.token`) is sent both as a
10
+ * `Bearer` header on REST calls and via the WebSocket
11
+ * `authentication_challenge` action after the socket opens.
12
+ * - Inbound: the WS pushes JSON events; `posted` events carry the new post as
13
+ * a nested JSON string which we parse into an `InboundMessage`.
14
+ * - Outbound: `send()` POSTs `{channel_id, message}` to `/api/v4/posts`.
15
+ * - Resilience: unintended socket drops are recovered through the shared
16
+ * `ReconnectionManager` (exponential backoff + jitter), the same idiom used
17
+ * by the discord / slack / imessage adapters. An explicit `disconnect()`
18
+ * sets a `closing` flag and cancels any pending reconnect so a deliberate
19
+ * close never spins the backoff loop.
6
20
  */
7
21
  import { BaseChannel, ChannelConfig, DeliveryResult, OutboundMessage } from '../core.js';
8
22
  export interface MattermostConfig {
9
23
  url: string;
10
24
  token: string;
11
25
  teamId?: string;
26
+ maxRetries?: number;
27
+ retryDelay?: number;
12
28
  }
13
29
  export interface MattermostChannelConfig extends ChannelConfig {
14
30
  url: string;
15
31
  token: string;
16
32
  teamId?: string;
33
+ maxRetries?: number;
34
+ retryDelay?: number;
17
35
  }
36
+ /**
37
+ * Legacy in-process adapter.
38
+ *
39
+ * @deprecated The real transport now lives in {@link MattermostChannel}, which
40
+ * opens a genuine WebSocket and POSTs through the REST API. This class is kept
41
+ * only for backward-compatible imports (`channels/index.ts` re-export and the
42
+ * `new-channels.test.ts` lifecycle suite) and performs no network I/O.
43
+ */
18
44
  export declare class MattermostAdapter {
19
45
  private config;
20
46
  private running;
@@ -38,10 +64,31 @@ export declare class MattermostAdapter {
38
64
  getConfig(): MattermostConfig;
39
65
  }
40
66
  export declare class MattermostChannel extends BaseChannel {
41
- private adapter;
67
+ private readonly mmConfig;
68
+ private ws;
69
+ private readonly reconnectionManager;
70
+ /** Monotonic sequence number for outbound WS actions. */
71
+ private seq;
72
+ /** True once `disconnect()` is in progress so drops aren't treated as faults. */
73
+ private closing;
74
+ /** Guards against resolving the connect() promise more than once. */
75
+ private connectSettled;
42
76
  constructor(config: MattermostChannelConfig);
43
77
  connect(): Promise<void>;
44
78
  disconnect(): Promise<void>;
45
79
  send(message: OutboundMessage): Promise<DeliveryResult>;
80
+ private openSocket;
81
+ private handleWsEvent;
82
+ private onAuthenticated;
83
+ private handlePostedEvent;
84
+ /**
85
+ * Handle a socket drop. If the close was intentional (`disconnect()`), do
86
+ * nothing. Otherwise schedule a reconnect through the shared manager.
87
+ */
88
+ private handleDrop;
89
+ private sendAction;
90
+ /** Expose the resolved WS gateway URL (handy for diagnostics / tests). */
91
+ getWebSocketUrl(): string;
92
+ getConfig(): MattermostConfig;
46
93
  }
47
- export default MattermostAdapter;
94
+ export default MattermostChannel;