@interactive-inc/claude-funnel 0.7.1 → 0.8.1

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 (472) hide show
  1. package/README.md +155 -133
  2. package/dist/bin.js +1344 -0
  3. package/dist/cli/factory.d.ts +7 -0
  4. package/dist/cli/router/query-to-cli-args.d.ts +1 -0
  5. package/dist/cli/router/to-request.d.ts +5 -0
  6. package/dist/cli/router/validator.d.ts +5 -0
  7. package/dist/cli/routes/channels.$channel.connectors.$connector.d.ts +42 -0
  8. package/dist/cli/routes/channels.$channel.connectors.$connector.rename.$newName.d.ts +46 -0
  9. package/dist/cli/routes/channels.$channel.connectors.$connector.request.d.ts +54 -0
  10. package/dist/cli/routes/channels.$channel.connectors.$connector.schedules.add.$id.d.ts +66 -0
  11. package/dist/cli/routes/channels.$channel.connectors.$connector.schedules.d.ts +42 -0
  12. package/dist/cli/routes/channels.$channel.connectors.$connector.schedules.remove.$id.d.ts +46 -0
  13. package/dist/cli/routes/channels.$channel.connectors.add.$connector.d.ts +90 -0
  14. package/dist/cli/routes/channels.$channel.connectors.d.ts +38 -0
  15. package/dist/cli/routes/channels.$channel.connectors.remove.$connector.d.ts +42 -0
  16. package/dist/cli/routes/channels.$channel.connectors.set.$connector.d.ts +62 -0
  17. package/dist/cli/routes/channels.$channel.d.ts +38 -0
  18. package/dist/cli/routes/channels.$channel.rename.$newName.d.ts +42 -0
  19. package/dist/cli/routes/channels.$channel.set.delivery.$mode.d.ts +28 -0
  20. package/dist/cli/routes/channels.add.$channel.d.ts +46 -0
  21. package/dist/cli/routes/channels.d.ts +16 -0
  22. package/dist/cli/routes/channels.remove.$channel.d.ts +38 -0
  23. package/dist/cli/routes/claude.d.ts +32 -0
  24. package/dist/cli/routes/gateway.d.ts +20 -0
  25. package/dist/cli/routes/gateway.listeners.d.ts +17 -0
  26. package/dist/cli/routes/gateway.logs.d.ts +24 -0
  27. package/dist/cli/routes/gateway.restart.d.ts +24 -0
  28. package/dist/cli/routes/gateway.run.d.ts +24 -0
  29. package/dist/cli/routes/gateway.start.d.ts +24 -0
  30. package/dist/cli/routes/gateway.status.d.ts +13 -0
  31. package/dist/cli/routes/gateway.stop.d.ts +16 -0
  32. package/dist/cli/routes/index.d.ts +1222 -0
  33. package/dist/cli/routes/profiles.$profile.as-default.d.ts +38 -0
  34. package/dist/cli/routes/profiles.$profile.rename.$newName.d.ts +42 -0
  35. package/dist/cli/routes/profiles.$profile.run.d.ts +46 -0
  36. package/dist/cli/routes/profiles.add.$profile.d.ts +54 -0
  37. package/dist/cli/routes/profiles.d.ts +16 -0
  38. package/dist/cli/routes/profiles.remove.$profile.d.ts +38 -0
  39. package/dist/cli/routes/profiles.set.$profile.d.ts +54 -0
  40. package/dist/cli/routes/status.d.ts +16 -0
  41. package/dist/cli/routes/update.d.ts +16 -0
  42. package/dist/connectors/connector-adapter.d.ts +8 -0
  43. package/dist/connectors/connector-config-schema.d.ts +43 -0
  44. package/dist/connectors/connector-factory.d.ts +32 -0
  45. package/dist/connectors/connector-listener.d.ts +17 -0
  46. package/dist/connectors/discord-adapter.d.ts +14 -0
  47. package/dist/connectors/discord-connector-schema.d.ts +10 -0
  48. package/dist/connectors/discord-event-processor.d.ts +26 -0
  49. package/dist/connectors/discord-listener.d.ts +17 -0
  50. package/dist/connectors/gh-adapter.d.ts +11 -0
  51. package/dist/connectors/gh-connector-schema.d.ts +10 -0
  52. package/dist/connectors/gh-listener.d.ts +26 -0
  53. package/dist/connectors/match-cron.d.ts +1 -0
  54. package/dist/connectors/schedule-connector-schema.d.ts +45 -0
  55. package/dist/connectors/schedule-listener.d.ts +30 -0
  56. package/dist/connectors/schedule-state-store.d.ts +19 -0
  57. package/dist/connectors/slack-adapter.d.ts +15 -0
  58. package/dist/connectors/slack-connector-schema.d.ts +11 -0
  59. package/dist/connectors/slack-event-processor.d.ts +27 -0
  60. package/dist/connectors/slack-listener.d.ts +17 -0
  61. package/dist/engine/channels/channels.d.ts +106 -0
  62. package/dist/engine/claude/claude.d.ts +49 -0
  63. package/dist/engine/claude/gateway-controller.d.ts +6 -0
  64. package/dist/engine/fs/file-system.d.ts +24 -0
  65. package/dist/engine/fs/memory-file-system.d.ts +31 -0
  66. package/dist/engine/fs/node-file-system.d.ts +15 -0
  67. package/dist/engine/http/http-client.d.ts +15 -0
  68. package/dist/engine/http/memory-http-client.d.ts +12 -0
  69. package/dist/engine/http/node-http-client.d.ts +5 -0
  70. package/dist/engine/id/id-generator.d.ts +7 -0
  71. package/dist/engine/id/memory-id-generator.d.ts +11 -0
  72. package/dist/engine/id/node-id-generator.d.ts +4 -0
  73. package/dist/engine/logger/logger.d.ts +11 -0
  74. package/dist/engine/logger/memory-logger.d.ts +14 -0
  75. package/dist/engine/logger/node-logger.d.ts +15 -0
  76. package/dist/engine/logger/noop-logger.d.ts +7 -0
  77. package/dist/engine/mcp/channel-server.d.ts +1 -0
  78. package/dist/engine/mcp/mcp.d.ts +22 -0
  79. package/dist/engine/process/memory-process-runner.d.ts +43 -0
  80. package/dist/engine/process/node-process-runner.d.ts +9 -0
  81. package/dist/engine/process/process-runner.d.ts +29 -0
  82. package/dist/engine/profiles/profile-channel-checker.d.ts +7 -0
  83. package/dist/engine/profiles/profiles.d.ts +31 -0
  84. package/dist/engine/settings/mock-settings-reader.d.ts +9 -0
  85. package/dist/engine/settings/settings-reader.d.ts +5 -0
  86. package/dist/engine/settings/settings-schema.d.ts +132 -0
  87. package/dist/engine/settings/settings-store.d.ts +18 -0
  88. package/dist/engine/time/clock.d.ts +9 -0
  89. package/dist/engine/time/memory-clock.d.ts +12 -0
  90. package/dist/engine/time/node-clock.d.ts +4 -0
  91. package/dist/funnel.d.ts +95 -0
  92. package/dist/gateway/auth-middleware.d.ts +14 -0
  93. package/dist/gateway/broadcaster.d.ts +122 -0
  94. package/dist/gateway/daemon.d.ts +2 -0
  95. package/dist/gateway/daemon.js +485 -0
  96. package/dist/gateway/factory.d.ts +7 -0
  97. package/dist/gateway/funnel-event-store.d.ts +81 -0
  98. package/dist/gateway/gateway-server.d.ts +94 -0
  99. package/dist/gateway/gateway-token.d.ts +33 -0
  100. package/dist/gateway/gateway.d.ts +58 -0
  101. package/dist/gateway/kill-competing-slack-gateways.d.ts +9 -0
  102. package/dist/gateway/listener-supervisor.d.ts +85 -0
  103. package/dist/gateway/listeners-client.d.ts +53 -0
  104. package/dist/gateway/resolve-daemon-script.d.ts +11 -0
  105. package/dist/gateway/routes/channels.connectors.call.d.ts +41 -0
  106. package/dist/gateway/routes/health.d.ts +17 -0
  107. package/dist/gateway/routes/index.d.ts +209 -0
  108. package/dist/gateway/routes/listeners.list.d.ts +14 -0
  109. package/dist/gateway/routes/listeners.restart.d.ts +34 -0
  110. package/dist/gateway/routes/listeners.start.d.ts +34 -0
  111. package/dist/gateway/routes/listeners.stop.d.ts +34 -0
  112. package/dist/gateway/routes/route-deps.d.ts +10 -0
  113. package/dist/gateway/routes/status.d.ts +30 -0
  114. package/dist/gateway/routes/validator.d.ts +19 -0
  115. package/dist/highlights-eq9cgrbb.scm +604 -0
  116. package/dist/highlights-ghv9g403.scm +205 -0
  117. package/dist/highlights-hk7bwhj4.scm +284 -0
  118. package/dist/highlights-r812a2qc.scm +150 -0
  119. package/dist/highlights-x6tmsnaa.scm +115 -0
  120. package/dist/index.d.ts +36 -0
  121. package/dist/index.js +3575 -0
  122. package/dist/injections-73j83es3.scm +27 -0
  123. package/dist/logger/leuco-human-file-writer.d.ts +33 -0
  124. package/dist/logger/leuco-human-logger.d.ts +46 -0
  125. package/dist/logger/leuco-human-record.d.ts +15 -0
  126. package/dist/logger/leuco-human-stdout-writer.d.ts +20 -0
  127. package/dist/logger/leuco-human-writer.d.ts +13 -0
  128. package/dist/logger/leuco-logger-memory-sink.d.ts +33 -0
  129. package/dist/logger/leuco-logger-record.d.ts +13 -0
  130. package/dist/logger/leuco-logger-sink.d.ts +34 -0
  131. package/dist/logger/leuco-logger-sqlite-sink.d.ts +102 -0
  132. package/dist/logger/leuco-logger.d.ts +56 -0
  133. package/dist/tree-sitter-javascript-nd0q4pe9.wasm +0 -0
  134. package/dist/tree-sitter-markdown-411r6y9b.wasm +0 -0
  135. package/dist/tree-sitter-markdown_inline-j5349f42.wasm +0 -0
  136. package/dist/tree-sitter-typescript-zxjzwt75.wasm +0 -0
  137. package/dist/tree-sitter-zig-e78zbjpm.wasm +0 -0
  138. package/lib/bin.ts +78 -0
  139. package/lib/{modules → cli}/router/to-request.ts +13 -20
  140. package/lib/cli/routes/channels.$channel.connectors.$connector.rename.$newName.ts +27 -0
  141. package/lib/cli/routes/channels.$channel.connectors.$connector.request.ts +40 -0
  142. package/lib/cli/routes/channels.$channel.connectors.$connector.schedules.add.$id.ts +41 -0
  143. package/lib/cli/routes/channels.$channel.connectors.$connector.schedules.remove.$id.ts +22 -0
  144. package/lib/cli/routes/channels.$channel.connectors.$connector.schedules.ts +23 -0
  145. package/lib/cli/routes/channels.$channel.connectors.$connector.ts +26 -0
  146. package/lib/cli/routes/channels.$channel.connectors.add.$connector.ts +92 -0
  147. package/lib/cli/routes/channels.$channel.connectors.remove.$connector.ts +22 -0
  148. package/lib/cli/routes/channels.$channel.connectors.set.$connector.ts +63 -0
  149. package/lib/cli/routes/channels.$channel.connectors.ts +26 -0
  150. package/lib/cli/routes/channels.$channel.rename.$newName.ts +22 -0
  151. package/lib/cli/routes/channels.$channel.set.delivery.$mode.ts +34 -0
  152. package/lib/cli/routes/channels.$channel.ts +34 -0
  153. package/lib/cli/routes/channels.add.$channel.ts +33 -0
  154. package/lib/cli/routes/channels.remove.$channel.ts +20 -0
  155. package/lib/cli/routes/channels.ts +39 -0
  156. package/lib/cli/routes/claude.ts +69 -0
  157. package/lib/cli/routes/gateway.listeners.ts +41 -0
  158. package/lib/cli/routes/gateway.logs.ts +123 -0
  159. package/lib/{routes/gateway/restart.ts → cli/routes/gateway.restart.ts} +20 -5
  160. package/lib/cli/routes/gateway.run.ts +41 -0
  161. package/lib/cli/routes/gateway.start.ts +50 -0
  162. package/lib/cli/routes/gateway.status.ts +19 -0
  163. package/lib/cli/routes/gateway.stop.ts +32 -0
  164. package/lib/cli/routes/gateway.ts +55 -0
  165. package/lib/cli/routes/index.ts +202 -0
  166. package/lib/cli/routes/profiles.$profile.as-default.ts +22 -0
  167. package/lib/cli/routes/profiles.$profile.rename.$newName.ts +22 -0
  168. package/lib/cli/routes/profiles.$profile.run.ts +36 -0
  169. package/lib/cli/routes/profiles.add.$profile.ts +46 -0
  170. package/lib/cli/routes/profiles.remove.$profile.ts +20 -0
  171. package/lib/cli/routes/profiles.set.$profile.ts +46 -0
  172. package/lib/cli/routes/profiles.ts +40 -0
  173. package/lib/cli/routes/status.ts +93 -0
  174. package/lib/cli/routes/update.ts +27 -0
  175. package/lib/connectors/connector-config-schema.ts +16 -0
  176. package/lib/connectors/connector-factory.ts +94 -0
  177. package/lib/connectors/connector-listener.ts +20 -0
  178. package/lib/{modules/connectors/funnel-discord-adapter.ts → connectors/discord-adapter.ts} +6 -11
  179. package/lib/{modules/connectors → connectors}/discord-connector-schema.ts +4 -1
  180. package/lib/connectors/discord-listener.ts +111 -0
  181. package/lib/{modules/connectors/funnel-gh-adapter.ts → connectors/gh-adapter.ts} +3 -6
  182. package/lib/{modules/connectors → connectors}/gh-connector-schema.ts +4 -1
  183. package/lib/{modules/connectors/funnel-gh-listener.ts → connectors/gh-listener.ts} +45 -19
  184. package/lib/{modules/connectors → connectors}/match-cron.ts +10 -4
  185. package/lib/connectors/schedule-connector-schema.ts +33 -0
  186. package/lib/connectors/schedule-listener.ts +207 -0
  187. package/lib/connectors/schedule-state-store.ts +54 -0
  188. package/lib/connectors/slack-adapter.ts +36 -0
  189. package/lib/{modules/connectors → connectors}/slack-connector-schema.ts +4 -1
  190. package/lib/{modules/connectors/funnel-slack-event-processor.ts → connectors/slack-event-processor.ts} +15 -9
  191. package/lib/{modules/connectors/funnel-slack-listener.ts → connectors/slack-listener.ts} +33 -14
  192. package/lib/engine/channels/channels.ts +520 -0
  193. package/lib/{modules/claude/funnel-claude.ts → engine/claude/claude.ts} +28 -55
  194. package/lib/engine/claude/gateway-controller.ts +4 -0
  195. package/lib/{modules/fs/funnel-file-system.ts → engine/fs/file-system.ts} +4 -0
  196. package/lib/{modules/fs/memory-funnel-file-system.ts → engine/fs/memory-file-system.ts} +20 -3
  197. package/lib/{modules/fs/node-funnel-file-system.ts → engine/fs/node-file-system.ts} +14 -2
  198. package/lib/{modules/http/memory-funnel-http-client.ts → engine/http/memory-http-client.ts} +1 -5
  199. package/lib/{modules/http/node-funnel-http-client.ts → engine/http/node-http-client.ts} +1 -5
  200. package/lib/{modules/id/memory-funnel-id-generator.ts → engine/id/memory-id-generator.ts} +1 -1
  201. package/lib/{modules/id/node-funnel-id-generator.ts → engine/id/node-id-generator.ts} +1 -1
  202. package/lib/{modules/logger/memory-funnel-logger.ts → engine/logger/memory-logger.ts} +1 -1
  203. package/lib/{modules/logger/node-funnel-logger.ts → engine/logger/node-logger.ts} +1 -1
  204. package/lib/{modules/logger/noop-funnel-logger.ts → engine/logger/noop-logger.ts} +1 -1
  205. package/lib/engine/mcp/channel-server.ts +204 -0
  206. package/lib/{modules/mcp/funnel-mcp.ts → engine/mcp/mcp.ts} +24 -10
  207. package/lib/{modules/process/memory-funnel-process-runner.ts → engine/process/memory-process-runner.ts} +1 -1
  208. package/lib/{modules/process/node-funnel-process-runner.ts → engine/process/node-process-runner.ts} +12 -21
  209. package/lib/engine/profiles/profile-channel-checker.ts +7 -0
  210. package/lib/{modules/profiles/funnel-profiles.ts → engine/profiles/profiles.ts} +41 -43
  211. package/lib/{modules/settings/mock-funnel-settings-reader.ts → engine/settings/mock-settings-reader.ts} +4 -3
  212. package/lib/{modules/settings/funnel-settings-reader.ts → engine/settings/settings-reader.ts} +1 -1
  213. package/lib/engine/settings/settings-schema.ts +46 -0
  214. package/lib/engine/settings/settings-store.ts +110 -0
  215. package/lib/{modules/time/memory-funnel-clock.ts → engine/time/memory-clock.ts} +1 -1
  216. package/lib/{modules/time/node-funnel-clock.ts → engine/time/node-clock.ts} +1 -1
  217. package/lib/funnel.ts +83 -78
  218. package/lib/gateway/auth-middleware.ts +44 -0
  219. package/lib/gateway/broadcaster.ts +319 -0
  220. package/lib/gateway/daemon.ts +47 -0
  221. package/lib/gateway/factory.ts +10 -0
  222. package/lib/gateway/funnel-event-store.ts +155 -0
  223. package/lib/gateway/gateway-server.ts +414 -0
  224. package/lib/gateway/gateway-token.ts +79 -0
  225. package/lib/{modules/gateway/funnel-gateway.ts → gateway/gateway.ts} +27 -13
  226. package/lib/{modules/gateway → gateway}/kill-competing-slack-gateways.ts +4 -4
  227. package/lib/gateway/listener-supervisor.ts +339 -0
  228. package/lib/gateway/listeners-client.ts +128 -0
  229. package/lib/gateway/resolve-daemon-script.ts +26 -0
  230. package/lib/gateway/routes/channels.connectors.call.ts +39 -0
  231. package/lib/gateway/routes/health.ts +13 -0
  232. package/lib/gateway/routes/index.ts +24 -0
  233. package/lib/gateway/routes/listeners.list.ts +6 -0
  234. package/lib/gateway/routes/listeners.restart.ts +15 -0
  235. package/lib/gateway/routes/listeners.start.ts +15 -0
  236. package/lib/gateway/routes/listeners.stop.ts +15 -0
  237. package/lib/gateway/routes/route-deps.ts +11 -0
  238. package/lib/gateway/routes/status.ts +15 -0
  239. package/lib/gateway/routes/validator.ts +17 -0
  240. package/lib/index.ts +52 -92
  241. package/lib/logger/leuco-human-file-writer.ts +65 -0
  242. package/lib/logger/leuco-human-logger.ts +98 -0
  243. package/lib/logger/leuco-human-record.ts +16 -0
  244. package/lib/logger/leuco-human-stdout-writer.ts +26 -0
  245. package/lib/logger/leuco-human-writer.ts +14 -0
  246. package/lib/logger/leuco-logger-memory-sink.ts +67 -0
  247. package/lib/logger/leuco-logger-record.ts +13 -0
  248. package/lib/logger/leuco-logger-sink.ts +33 -0
  249. package/lib/logger/leuco-logger-sqlite-sink.ts +355 -0
  250. package/lib/logger/leuco-logger.ts +135 -0
  251. package/lib/tui/app.tsx +357 -0
  252. package/lib/tui/components/add-row.tsx +18 -0
  253. package/lib/tui/components/brand.tsx +27 -0
  254. package/lib/tui/components/card.tsx +44 -0
  255. package/lib/tui/components/detail-bar.tsx +46 -0
  256. package/lib/tui/components/editable-field.tsx +33 -0
  257. package/lib/tui/components/empty-state.tsx +11 -0
  258. package/lib/tui/components/gateway-status.tsx +66 -0
  259. package/lib/tui/components/keymap.tsx +29 -0
  260. package/lib/tui/components/menu-item.tsx +73 -0
  261. package/lib/tui/components/menu.tsx +26 -0
  262. package/lib/tui/components/panel-header.tsx +22 -0
  263. package/lib/tui/components/readonly-field.tsx +18 -0
  264. package/lib/tui/components/section-header.tsx +25 -0
  265. package/lib/tui/components/selection-accent.tsx +32 -0
  266. package/lib/tui/components/session-item.tsx +33 -0
  267. package/lib/tui/components/session-list.tsx +33 -0
  268. package/lib/tui/components/ui/hascii/accordion-item.tsx +88 -0
  269. package/lib/tui/components/ui/hascii/accordion.tsx +96 -0
  270. package/lib/tui/components/ui/hascii/alert-dialog.tsx +43 -0
  271. package/lib/tui/components/ui/hascii/badge.tsx +51 -0
  272. package/lib/tui/components/ui/hascii/breadcrumb.tsx +58 -0
  273. package/lib/tui/components/ui/hascii/button.tsx +194 -0
  274. package/lib/tui/components/ui/hascii/card-content.tsx +14 -0
  275. package/lib/tui/components/ui/hascii/card-description.tsx +13 -0
  276. package/lib/tui/components/ui/hascii/card-footer.tsx +14 -0
  277. package/lib/tui/components/ui/hascii/card-header.tsx +14 -0
  278. package/lib/tui/components/ui/hascii/card-title.tsx +13 -0
  279. package/lib/tui/components/ui/hascii/card.tsx +27 -0
  280. package/lib/tui/components/ui/hascii/checkbox.tsx +65 -0
  281. package/lib/tui/components/ui/hascii/command.tsx +159 -0
  282. package/lib/tui/components/ui/hascii/dialog-content.tsx +14 -0
  283. package/lib/tui/components/ui/hascii/dialog-description.tsx +13 -0
  284. package/lib/tui/components/ui/hascii/dialog-footer.tsx +14 -0
  285. package/lib/tui/components/ui/hascii/dialog-header.tsx +14 -0
  286. package/lib/tui/components/ui/hascii/dialog-title.tsx +13 -0
  287. package/lib/tui/components/ui/hascii/dialog.tsx +27 -0
  288. package/lib/tui/components/ui/hascii/file-tree.tsx +142 -0
  289. package/lib/tui/components/ui/hascii/focus-group.tsx +62 -0
  290. package/lib/tui/components/ui/hascii/form-item.tsx +43 -0
  291. package/lib/tui/components/ui/hascii/input-otp.tsx +86 -0
  292. package/lib/tui/components/ui/hascii/input.tsx +130 -0
  293. package/lib/tui/components/ui/hascii/pagination.tsx +105 -0
  294. package/lib/tui/components/ui/hascii/progress.tsx +28 -0
  295. package/lib/tui/components/ui/hascii/select.tsx +131 -0
  296. package/lib/tui/components/ui/hascii/separator.tsx +35 -0
  297. package/lib/tui/components/ui/hascii/sidebar-content.tsx +23 -0
  298. package/lib/tui/components/ui/hascii/sidebar-header.tsx +14 -0
  299. package/lib/tui/components/ui/hascii/sidebar-menu-item.tsx +67 -0
  300. package/lib/tui/components/ui/hascii/sidebar.tsx +24 -0
  301. package/lib/tui/components/ui/hascii/skeleton.tsx +60 -0
  302. package/lib/tui/components/ui/hascii/slider.tsx +91 -0
  303. package/lib/tui/components/ui/hascii/snackbar.tsx +75 -0
  304. package/lib/tui/components/ui/hascii/sparkline.tsx +53 -0
  305. package/lib/tui/components/ui/hascii/spinner.tsx +47 -0
  306. package/lib/tui/components/ui/hascii/stepper.tsx +54 -0
  307. package/lib/tui/components/ui/hascii/switch.tsx +66 -0
  308. package/lib/tui/components/ui/hascii/table.tsx +95 -0
  309. package/lib/tui/components/ui/hascii/tabs.tsx +59 -0
  310. package/lib/tui/components/ui/hascii/toggle-group-item.tsx +45 -0
  311. package/lib/tui/components/ui/hascii/toggle-group.tsx +99 -0
  312. package/lib/tui/components/ui/hascii/tree.tsx +104 -0
  313. package/lib/tui/components/view-shell.tsx +44 -0
  314. package/lib/tui/filter-input.tsx +33 -0
  315. package/lib/tui/hooks/hascii/use-pressable.ts +54 -0
  316. package/lib/tui/parse-comma-list.ts +14 -0
  317. package/lib/tui/profile-launcher.tsx +61 -0
  318. package/lib/tui/scrollbar-options.ts +19 -0
  319. package/lib/tui/sidebar.tsx +50 -0
  320. package/lib/tui/theme.ts +40 -0
  321. package/lib/tui/tui.tsx +20 -0
  322. package/lib/tui/types.ts +38 -0
  323. package/lib/tui/unique-name.ts +18 -0
  324. package/lib/tui/use-event-stream.ts +133 -0
  325. package/lib/tui/use-snapshot.ts +99 -0
  326. package/lib/tui/utils/hascii/form-item-context.tsx +23 -0
  327. package/lib/tui/utils/hascii/input-focus-context.tsx +31 -0
  328. package/lib/tui/utils/hascii/theme-context.tsx +26 -0
  329. package/lib/tui/utils/hascii/theme.ts +176 -0
  330. package/lib/tui/views/channels-view.tsx +108 -0
  331. package/lib/tui/views/connectors-view.tsx +164 -0
  332. package/lib/tui/views/events-view.tsx +160 -0
  333. package/lib/tui/views/listeners-view.tsx +80 -0
  334. package/lib/tui/views/profiles-view.tsx +152 -0
  335. package/package.json +55 -44
  336. package/lib/api.ts +0 -54
  337. package/lib/modules/channels/channel-connector-ref-updater.ts +0 -4
  338. package/lib/modules/channels/funnel-channels.ts +0 -160
  339. package/lib/modules/connectors/connector-config-schema.ts +0 -16
  340. package/lib/modules/connectors/connector-existence-checker.ts +0 -3
  341. package/lib/modules/connectors/funnel-callable-connector-store.ts +0 -9
  342. package/lib/modules/connectors/funnel-connector-listener.ts +0 -5
  343. package/lib/modules/connectors/funnel-connector-stores.ts +0 -52
  344. package/lib/modules/connectors/funnel-connector-type-store.ts +0 -24
  345. package/lib/modules/connectors/funnel-connectors.ts +0 -151
  346. package/lib/modules/connectors/funnel-discord-listener.ts +0 -71
  347. package/lib/modules/connectors/funnel-discord-store.ts +0 -88
  348. package/lib/modules/connectors/funnel-gh-store.ts +0 -101
  349. package/lib/modules/connectors/funnel-json-connector-store.ts +0 -100
  350. package/lib/modules/connectors/funnel-schedule-listener.ts +0 -130
  351. package/lib/modules/connectors/funnel-schedule-store.ts +0 -195
  352. package/lib/modules/connectors/funnel-slack-adapter.ts +0 -31
  353. package/lib/modules/connectors/funnel-slack-store.ts +0 -90
  354. package/lib/modules/connectors/migrate-legacy-connectors.ts +0 -81
  355. package/lib/modules/connectors/schedule-connector-schema.ts +0 -18
  356. package/lib/modules/connectors/schedule-last-fired-store.ts +0 -48
  357. package/lib/modules/gateway/daemon.ts +0 -74
  358. package/lib/modules/gateway/funnel-broadcaster.ts +0 -37
  359. package/lib/modules/gateway/funnel-event-logger.ts +0 -59
  360. package/lib/modules/gateway/funnel-gateway-server.ts +0 -241
  361. package/lib/modules/mcp/channel-server.ts +0 -76
  362. package/lib/modules/profiles/profile-channel-checker.ts +0 -3
  363. package/lib/modules/profiles/profile-channel-ref-updater.ts +0 -3
  364. package/lib/modules/repos/funnel-repositories.ts +0 -112
  365. package/lib/modules/schedule/funnel-schedule.ts +0 -39
  366. package/lib/modules/settings/funnel-settings-store.ts +0 -56
  367. package/lib/modules/settings/settings-schema.ts +0 -33
  368. package/lib/modules/tui/app.tsx +0 -44
  369. package/lib/modules/tui/tui.tsx +0 -13
  370. package/lib/routes/channels/add.help.ts +0 -3
  371. package/lib/routes/channels/add.ts +0 -21
  372. package/lib/routes/channels/connectors-attach.help.ts +0 -3
  373. package/lib/routes/channels/connectors-attach.ts +0 -17
  374. package/lib/routes/channels/connectors-detach.help.ts +0 -3
  375. package/lib/routes/channels/connectors-detach.ts +0 -17
  376. package/lib/routes/channels/group.help.ts +0 -16
  377. package/lib/routes/channels/group.ts +0 -22
  378. package/lib/routes/channels/remove.help.ts +0 -3
  379. package/lib/routes/channels/remove.ts +0 -17
  380. package/lib/routes/channels/rename.help.ts +0 -5
  381. package/lib/routes/channels/rename.ts +0 -17
  382. package/lib/routes/channels/routes.ts +0 -19
  383. package/lib/routes/channels/show.help.ts +0 -1
  384. package/lib/routes/channels/show.ts +0 -26
  385. package/lib/routes/claude/claude.help.ts +0 -16
  386. package/lib/routes/claude/claude.ts +0 -76
  387. package/lib/routes/claude/routes.ts +0 -4
  388. package/lib/routes/connectors/add.help.ts +0 -28
  389. package/lib/routes/connectors/add.ts +0 -64
  390. package/lib/routes/connectors/group.help.ts +0 -14
  391. package/lib/routes/connectors/group.ts +0 -18
  392. package/lib/routes/connectors/remove.help.ts +0 -3
  393. package/lib/routes/connectors/remove.ts +0 -17
  394. package/lib/routes/connectors/rename.help.ts +0 -5
  395. package/lib/routes/connectors/rename.ts +0 -17
  396. package/lib/routes/connectors/routes.ts +0 -23
  397. package/lib/routes/connectors/schedules-add.help.ts +0 -11
  398. package/lib/routes/connectors/schedules-add.ts +0 -33
  399. package/lib/routes/connectors/schedules-group.help.ts +0 -1
  400. package/lib/routes/connectors/schedules-group.ts +0 -38
  401. package/lib/routes/connectors/schedules-remove.help.ts +0 -3
  402. package/lib/routes/connectors/schedules-remove.ts +0 -17
  403. package/lib/routes/connectors/set.help.ts +0 -8
  404. package/lib/routes/connectors/set.ts +0 -72
  405. package/lib/routes/connectors/show.help.ts +0 -1
  406. package/lib/routes/connectors/show.ts +0 -41
  407. package/lib/routes/gateway/group.help.ts +0 -15
  408. package/lib/routes/gateway/group.ts +0 -28
  409. package/lib/routes/gateway/logs.help.ts +0 -13
  410. package/lib/routes/gateway/logs.ts +0 -102
  411. package/lib/routes/gateway/restart.help.ts +0 -10
  412. package/lib/routes/gateway/routes.ts +0 -18
  413. package/lib/routes/gateway/run.help.ts +0 -12
  414. package/lib/routes/gateway/run.ts +0 -35
  415. package/lib/routes/gateway/start.help.ts +0 -15
  416. package/lib/routes/gateway/start.ts +0 -32
  417. package/lib/routes/gateway/status.help.ts +0 -9
  418. package/lib/routes/gateway/status.ts +0 -28
  419. package/lib/routes/gateway/stop.help.ts +0 -8
  420. package/lib/routes/gateway/stop.ts +0 -21
  421. package/lib/routes/profiles/add.help.ts +0 -3
  422. package/lib/routes/profiles/add.ts +0 -33
  423. package/lib/routes/profiles/group.help.ts +0 -16
  424. package/lib/routes/profiles/group.ts +0 -25
  425. package/lib/routes/profiles/launch.help.ts +0 -4
  426. package/lib/routes/profiles/launch.ts +0 -36
  427. package/lib/routes/profiles/remove.help.ts +0 -3
  428. package/lib/routes/profiles/remove.ts +0 -17
  429. package/lib/routes/profiles/rename.help.ts +0 -5
  430. package/lib/routes/profiles/rename.ts +0 -17
  431. package/lib/routes/profiles/routes.ts +0 -18
  432. package/lib/routes/profiles/set.help.ts +0 -5
  433. package/lib/routes/profiles/set.ts +0 -32
  434. package/lib/routes/repos/add.help.ts +0 -6
  435. package/lib/routes/repos/add.ts +0 -20
  436. package/lib/routes/repos/group.help.ts +0 -11
  437. package/lib/routes/repos/group.ts +0 -18
  438. package/lib/routes/repos/remove.help.ts +0 -3
  439. package/lib/routes/repos/remove.ts +0 -17
  440. package/lib/routes/repos/rename.help.ts +0 -5
  441. package/lib/routes/repos/rename.ts +0 -17
  442. package/lib/routes/repos/routes.ts +0 -17
  443. package/lib/routes/repos/set.help.ts +0 -5
  444. package/lib/routes/repos/set.ts +0 -21
  445. package/lib/routes/repos/show.help.ts +0 -1
  446. package/lib/routes/repos/show.ts +0 -19
  447. package/lib/routes/request/discord-help.ts +0 -9
  448. package/lib/routes/request/discord.help.ts +0 -19
  449. package/lib/routes/request/discord.ts +0 -65
  450. package/lib/routes/request/group.help.ts +0 -15
  451. package/lib/routes/request/group.ts +0 -9
  452. package/lib/routes/request/routes.ts +0 -14
  453. package/lib/routes/request/slack-help.ts +0 -9
  454. package/lib/routes/request/slack.help.ts +0 -19
  455. package/lib/routes/request/slack.ts +0 -61
  456. package/lib/routes/status/routes.ts +0 -4
  457. package/lib/routes/status/status.help.ts +0 -6
  458. package/lib/routes/status/status.ts +0 -77
  459. package/lib/routes/update/routes.ts +0 -4
  460. package/lib/routes/update/update.help.ts +0 -5
  461. package/lib/routes/update/update.ts +0 -21
  462. package/lib/routes.ts +0 -40
  463. /package/lib/{factory.ts → cli/factory.ts} +0 -0
  464. /package/lib/{modules → cli}/router/query-to-cli-args.ts +0 -0
  465. /package/lib/{modules → cli}/router/validator.ts +0 -0
  466. /package/lib/{modules/connectors/funnel-connector-adapter.ts → connectors/connector-adapter.ts} +0 -0
  467. /package/lib/{modules/connectors/funnel-discord-event-processor.ts → connectors/discord-event-processor.ts} +0 -0
  468. /package/lib/{modules/http/funnel-http-client.ts → engine/http/http-client.ts} +0 -0
  469. /package/lib/{modules/id/funnel-id-generator.ts → engine/id/id-generator.ts} +0 -0
  470. /package/lib/{modules/logger/funnel-logger.ts → engine/logger/logger.ts} +0 -0
  471. /package/lib/{modules/process/funnel-process-runner.ts → engine/process/process-runner.ts} +0 -0
  472. /package/lib/{modules/time/funnel-clock.ts → engine/time/clock.ts} +0 -0
@@ -0,0 +1,22 @@
1
+ import { z } from "zod"
2
+ import { factory } from "@/cli/factory"
3
+ import { zValidator } from "@/cli/router/validator"
4
+
5
+ export const removeHelp = `funnel channels <ch> connectors <conn> schedules remove <id>
6
+
7
+ usage: funnel channels <ch> connectors <conn> schedules remove <id>`
8
+
9
+ export const channelsConnectorsSchedulesRemoveHandler = factory.createHandlers(
10
+ zValidator("param", z.object({ channel: z.string(), connector: z.string(), id: z.string() })),
11
+ zValidator("query", z.object({}), removeHelp),
12
+ async (c) => {
13
+ const param = c.req.valid("param")
14
+ const funnel = c.var.funnel
15
+
16
+ funnel.channels.removeScheduleEntry(param.channel, param.connector, param.id)
17
+
18
+ await funnel.listeners.restart(param.channel, param.connector)
19
+
20
+ return c.text(`removed schedule entry "${param.id}"`)
21
+ },
22
+ )
@@ -0,0 +1,23 @@
1
+ import { z } from "zod"
2
+ import { factory } from "@/cli/factory"
3
+ import { zValidator } from "@/cli/router/validator"
4
+
5
+ export const groupHelp = `funnel channels <ch> connectors <conn> schedules — list schedule entries
6
+
7
+ usage: funnel channels <ch> connectors <conn> schedules`
8
+
9
+ export const channelsConnectorsSchedulesGroupHandler = factory.createHandlers(
10
+ zValidator("param", z.object({ channel: z.string(), connector: z.string() })),
11
+ zValidator("query", z.object({}), groupHelp),
12
+ (c) => {
13
+ const param = c.req.valid("param")
14
+ const funnel = c.var.funnel
15
+ const entries = funnel.channels.listScheduleEntries(param.channel, param.connector)
16
+
17
+ if (entries.length === 0) return c.text("no schedule entries")
18
+
19
+ return c.text(
20
+ entries.map((e) => `${e.id}\t${e.cron}\t${e.enabled ? "on" : "off"}\t${e.prompt}`).join("\n"),
21
+ )
22
+ },
23
+ )
@@ -0,0 +1,26 @@
1
+ import { HTTPException } from "hono/http-exception"
2
+ import { z } from "zod"
3
+ import { factory } from "@/cli/factory"
4
+ import { zValidator } from "@/cli/router/validator"
5
+
6
+ export const showHelp = `funnel channels <channel> connectors show <connector> — show connector config
7
+
8
+ usage: funnel channels <channel> connectors show <connector>`
9
+
10
+ export const channelsConnectorsShowHandler = factory.createHandlers(
11
+ zValidator("param", z.object({ channel: z.string(), connector: z.string() })),
12
+ zValidator("query", z.object({}), showHelp),
13
+ (c) => {
14
+ const param = c.req.valid("param")
15
+ const funnel = c.var.funnel
16
+ const connector = funnel.channels.getConnector(param.channel, param.connector)
17
+
18
+ if (!connector) {
19
+ throw new HTTPException(404, {
20
+ message: `connector "${param.connector}" not found in channel "${param.channel}"`,
21
+ })
22
+ }
23
+
24
+ return c.text(JSON.stringify(connector, null, 2))
25
+ },
26
+ )
@@ -0,0 +1,92 @@
1
+ import { z } from "zod"
2
+ import { factory } from "@/cli/factory"
3
+ import { zValidator } from "@/cli/router/validator"
4
+
5
+ export const addHelp = `funnel channels <channel> connectors add <connector> — add a connector to a channel
6
+
7
+ usage:
8
+ funnel channels <channel> connectors add <connector> --type=slack --bot-token=xoxb-... --app-token=xapp-...
9
+ funnel channels <channel> connectors add <connector> --type=gh [--poll-interval=60]
10
+ funnel channels <channel> connectors add <connector> --type=discord --bot-token=...
11
+ funnel channels <channel> connectors add <connector> --type=schedule
12
+
13
+ Token uniqueness is enforced across all channels.`
14
+
15
+ const slackBody = z.object({
16
+ type: z.literal("slack"),
17
+ "bot-token": z.string().startsWith("xoxb-"),
18
+ "app-token": z.string().startsWith("xapp-"),
19
+ })
20
+
21
+ const ghBody = z.object({
22
+ type: z.literal("gh"),
23
+ "poll-interval": z.coerce.number().int().positive().optional(),
24
+ })
25
+
26
+ const discordBody = z.object({
27
+ type: z.literal("discord"),
28
+ "bot-token": z.string().min(10),
29
+ })
30
+
31
+ const scheduleBody = z.object({
32
+ type: z.literal("schedule"),
33
+ })
34
+
35
+ const addBody = z.discriminatedUnion("type", [slackBody, ghBody, discordBody, scheduleBody])
36
+
37
+ export const channelsConnectorsAddHandler = factory.createHandlers(
38
+ zValidator("param", z.object({ channel: z.string(), connector: z.string() })),
39
+ zValidator("query", addBody, addHelp),
40
+ async (c) => {
41
+ const param = c.req.valid("param")
42
+ const query = c.req.valid("query")
43
+ const funnel = c.var.funnel
44
+
45
+ if (query.type === "slack") {
46
+ const created = funnel.channels.addConnector(param.channel, {
47
+ type: "slack",
48
+ name: param.connector,
49
+ botToken: query["bot-token"],
50
+ appToken: query["app-token"],
51
+ })
52
+
53
+ await funnel.listeners.start(param.channel, created.name)
54
+
55
+ return c.text(`added slack connector "${created.name}" to channel "${param.channel}"`)
56
+ }
57
+
58
+ if (query.type === "gh") {
59
+ const created = funnel.channels.addConnector(param.channel, {
60
+ type: "gh",
61
+ name: param.connector,
62
+ ...(query["poll-interval"] !== undefined ? { pollInterval: query["poll-interval"] } : {}),
63
+ })
64
+
65
+ await funnel.listeners.start(param.channel, created.name)
66
+
67
+ return c.text(`added gh connector "${created.name}" to channel "${param.channel}"`)
68
+ }
69
+
70
+ if (query.type === "discord") {
71
+ const created = funnel.channels.addConnector(param.channel, {
72
+ type: "discord",
73
+ name: param.connector,
74
+ botToken: query["bot-token"],
75
+ })
76
+
77
+ await funnel.listeners.start(param.channel, created.name)
78
+
79
+ return c.text(`added discord connector "${created.name}" to channel "${param.channel}"`)
80
+ }
81
+
82
+ const created = funnel.channels.addConnector(param.channel, {
83
+ type: "schedule",
84
+ name: param.connector,
85
+ entries: [],
86
+ })
87
+
88
+ await funnel.listeners.start(param.channel, created.name)
89
+
90
+ return c.text(`added schedule connector "${created.name}" to channel "${param.channel}"`)
91
+ },
92
+ )
@@ -0,0 +1,22 @@
1
+ import { z } from "zod"
2
+ import { factory } from "@/cli/factory"
3
+ import { zValidator } from "@/cli/router/validator"
4
+
5
+ export const removeHelp = `funnel channels <channel> connectors remove <connector> — remove a connector
6
+
7
+ usage: funnel channels <channel> connectors remove <connector>`
8
+
9
+ export const channelsConnectorsRemoveHandler = factory.createHandlers(
10
+ zValidator("param", z.object({ channel: z.string(), connector: z.string() })),
11
+ zValidator("query", z.object({}), removeHelp),
12
+ async (c) => {
13
+ const param = c.req.valid("param")
14
+ const funnel = c.var.funnel
15
+
16
+ await funnel.listeners.stop(param.channel, param.connector)
17
+
18
+ funnel.channels.removeConnector(param.channel, param.connector)
19
+
20
+ return c.text(`removed connector "${param.connector}" from channel "${param.channel}"`)
21
+ },
22
+ )
@@ -0,0 +1,63 @@
1
+ import { HTTPException } from "hono/http-exception"
2
+ import { z } from "zod"
3
+ import { factory } from "@/cli/factory"
4
+ import { zValidator } from "@/cli/router/validator"
5
+
6
+ export const setHelp = `funnel channels <channel> connectors set <connector> — update connector fields
7
+
8
+ usage:
9
+ funnel channels <ch> connectors set <conn> [--bot-token=...] [--app-token=...] # slack
10
+ funnel channels <ch> connectors set <conn> [--bot-token=...] # discord
11
+ funnel channels <ch> connectors set <conn> [--poll-interval=N] # gh`
12
+
13
+ export const channelsConnectorsSetHandler = factory.createHandlers(
14
+ zValidator("param", z.object({ channel: z.string(), connector: z.string() })),
15
+ zValidator(
16
+ "query",
17
+ z
18
+ .object({
19
+ "bot-token": z.string().optional(),
20
+ "app-token": z.string().optional(),
21
+ "poll-interval": z.coerce.number().int().positive().optional(),
22
+ })
23
+ .passthrough(),
24
+ setHelp,
25
+ ),
26
+ async (c) => {
27
+ const param = c.req.valid("param")
28
+ const query = c.req.valid("query")
29
+ const funnel = c.var.funnel
30
+ const existing = funnel.channels.getConnector(param.channel, param.connector)
31
+
32
+ if (!existing) {
33
+ throw new HTTPException(404, {
34
+ message: `connector "${param.connector}" not found in channel "${param.channel}"`,
35
+ })
36
+ }
37
+
38
+ if (existing.type === "slack") {
39
+ funnel.channels.updateSlackConnector(param.channel, param.connector, {
40
+ ...(query["bot-token"] !== undefined ? { botToken: query["bot-token"] } : {}),
41
+ ...(query["app-token"] !== undefined ? { appToken: query["app-token"] } : {}),
42
+ })
43
+ } else if (existing.type === "discord") {
44
+ funnel.channels.updateDiscordConnector(
45
+ param.channel,
46
+ param.connector,
47
+ query["bot-token"] !== undefined ? { botToken: query["bot-token"] } : {},
48
+ )
49
+ } else if (existing.type === "gh") {
50
+ funnel.channels.updateGhConnector(
51
+ param.channel,
52
+ param.connector,
53
+ query["poll-interval"] !== undefined ? { pollInterval: query["poll-interval"] } : {},
54
+ )
55
+ } else {
56
+ throw new HTTPException(400, { message: "schedule connectors have no settable fields" })
57
+ }
58
+
59
+ await funnel.listeners.restart(param.channel, param.connector)
60
+
61
+ return c.text(`updated connector "${param.connector}" in channel "${param.channel}"`)
62
+ },
63
+ )
@@ -0,0 +1,26 @@
1
+ import { HTTPException } from "hono/http-exception"
2
+ import { z } from "zod"
3
+ import { factory } from "@/cli/factory"
4
+ import { zValidator } from "@/cli/router/validator"
5
+
6
+ export const groupHelp = `funnel channels <channel> connectors — list connectors in a channel
7
+
8
+ usage: funnel channels <channel> connectors`
9
+
10
+ export const channelsConnectorsGroupHandler = factory.createHandlers(
11
+ zValidator("param", z.object({ channel: z.string() })),
12
+ zValidator("query", z.object({}), groupHelp),
13
+ (c) => {
14
+ const param = c.req.valid("param")
15
+ const funnel = c.var.funnel
16
+ const channel = funnel.channels.get(param.channel)
17
+
18
+ if (!channel) {
19
+ throw new HTTPException(404, { message: `channel "${param.channel}" not found` })
20
+ }
21
+
22
+ if (channel.connectors.length === 0) return c.text(`no connectors in channel "${channel.name}"`)
23
+
24
+ return c.text(channel.connectors.map((c) => `${c.name} (${c.type}, id: ${c.id})`).join("\n"))
25
+ },
26
+ )
@@ -0,0 +1,22 @@
1
+ import { z } from "zod"
2
+ import { factory } from "@/cli/factory"
3
+ import { zValidator } from "@/cli/router/validator"
4
+
5
+ export const renameHelp = `funnel channels rename — rename a channel
6
+
7
+ usage:
8
+ funnel channels rename <old> <new>
9
+ funnel channels <old> rename <new>`
10
+
11
+ export const channelsRenameHandler = factory.createHandlers(
12
+ zValidator("param", z.object({ channel: z.string(), newName: z.string() })),
13
+ zValidator("query", z.object({}), renameHelp),
14
+ (c) => {
15
+ const param = c.req.valid("param")
16
+ const funnel = c.var.funnel
17
+
18
+ funnel.channels.rename(param.channel, param.newName)
19
+
20
+ return c.text(`renamed channel "${param.channel}" to "${param.newName}"`)
21
+ },
22
+ )
@@ -0,0 +1,34 @@
1
+ import { z } from "zod"
2
+ import { factory } from "@/cli/factory"
3
+ import { zValidator } from "@/cli/router/validator"
4
+ import { channelDeliveryModeSchema } from "@/engine/settings/settings-schema"
5
+
6
+ export const setDeliveryHelp = `funnel channels <name> set delivery <mode> — change a channel's routing mode
7
+
8
+ usage: funnel channels <name> set delivery fanout | exclusive
9
+
10
+ modes:
11
+ fanout every connected WS client receives every event (default)
12
+ exclusive each event is delivered to exactly one connected client (round-robin)
13
+
14
+ tap=all clients (TUI dashboard, debugging) always receive regardless of mode.
15
+ `
16
+
17
+ export const channelsSetDeliveryHandler = factory.createHandlers(
18
+ zValidator(
19
+ "param",
20
+ z.object({
21
+ channel: z.string(),
22
+ mode: channelDeliveryModeSchema,
23
+ }),
24
+ setDeliveryHelp,
25
+ ),
26
+ (c) => {
27
+ const param = c.req.valid("param")
28
+ const funnel = c.var.funnel
29
+
30
+ funnel.channels.setDelivery(param.channel, param.mode)
31
+
32
+ return c.text(`channel "${param.channel}" delivery set to ${param.mode}`)
33
+ },
34
+ )
@@ -0,0 +1,34 @@
1
+ import { HTTPException } from "hono/http-exception"
2
+ import { z } from "zod"
3
+ import { factory } from "@/cli/factory"
4
+ import { zValidator } from "@/cli/router/validator"
5
+
6
+ export const showHelp = `funnel channels <name> — show channel details`
7
+
8
+ export const channelsShowHandler = factory.createHandlers(
9
+ zValidator("param", z.object({ channel: z.string() })),
10
+ zValidator("query", z.object({}), showHelp),
11
+ (c) => {
12
+ const param = c.req.valid("param")
13
+ const funnel = c.var.funnel
14
+ const channel = funnel.channels.get(param.channel)
15
+
16
+ if (!channel) {
17
+ throw new HTTPException(404, { message: `channel "${param.channel}" not found` })
18
+ }
19
+
20
+ const connectorLines = channel.connectors.length
21
+ ? channel.connectors.map((c) => ` - ${c.name} (${c.type}, id: ${c.id})`)
22
+ : [" (none)"]
23
+
24
+ const lines = [
25
+ `id: ${channel.id}`,
26
+ `name: ${channel.name}`,
27
+ `delivery: ${channel.delivery}`,
28
+ `connectors:`,
29
+ ...connectorLines,
30
+ ]
31
+
32
+ return c.text(lines.join("\n"))
33
+ },
34
+ )
@@ -0,0 +1,33 @@
1
+ import { z } from "zod"
2
+ import { factory } from "@/cli/factory"
3
+ import { zValidator } from "@/cli/router/validator"
4
+ import { channelDeliveryModeSchema } from "@/engine/settings/settings-schema"
5
+
6
+ export const addHelp = `funnel channels add — add a channel
7
+
8
+ usage: funnel channels add <name> [--delivery fanout|exclusive]
9
+
10
+ options:
11
+ --delivery routing mode (default fanout):
12
+ fanout every connected client receives every event
13
+ exclusive each event delivered to exactly one client (round-robin)`
14
+
15
+ export const channelsAddHandler = factory.createHandlers(
16
+ zValidator("param", z.object({ channel: z.string() })),
17
+ zValidator(
18
+ "query",
19
+ z.object({
20
+ delivery: channelDeliveryModeSchema.optional(),
21
+ }),
22
+ addHelp,
23
+ ),
24
+ (c) => {
25
+ const param = c.req.valid("param")
26
+ const query = c.req.valid("query")
27
+ const funnel = c.var.funnel
28
+
29
+ const created = funnel.channels.add({ name: param.channel, delivery: query.delivery })
30
+
31
+ return c.text(`added channel "${created.name}" (id: ${created.id})`)
32
+ },
33
+ )
@@ -0,0 +1,20 @@
1
+ import { z } from "zod"
2
+ import { factory } from "@/cli/factory"
3
+ import { zValidator } from "@/cli/router/validator"
4
+
5
+ export const removeHelp = `funnel channels remove — remove a channel
6
+
7
+ usage: funnel channels remove <name>`
8
+
9
+ export const channelsRemoveHandler = factory.createHandlers(
10
+ zValidator("param", z.object({ channel: z.string() })),
11
+ zValidator("query", z.object({}), removeHelp),
12
+ (c) => {
13
+ const param = c.req.valid("param")
14
+ const funnel = c.var.funnel
15
+
16
+ funnel.channels.remove(param.channel)
17
+
18
+ return c.text(`removed channel "${param.channel}"`)
19
+ },
20
+ )
@@ -0,0 +1,39 @@
1
+ import { z } from "zod"
2
+ import { factory } from "@/cli/factory"
3
+ import { zValidator } from "@/cli/router/validator"
4
+
5
+ export const groupHelp = `funnel channels — manage subscription boxes
6
+
7
+ usage: funnel channels [subcommand]
8
+
9
+ subcommands:
10
+ (none) list
11
+ add <name> add
12
+ remove <name> remove
13
+ <name> show details
14
+ <name> connectors list connectors
15
+ <name> connectors add <c> --type=... add a connector
16
+
17
+ examples:
18
+ funnel channels add prod-inbox
19
+ funnel channels prod-inbox connectors add prod-slack --type=slack --bot-token=xoxb-... --app-token=xapp-...
20
+ funnel channels prod-inbox`
21
+
22
+ export const channelsGroupHandler = factory.createHandlers(
23
+ zValidator("query", z.object({}), groupHelp),
24
+ (c) => {
25
+ const funnel = c.var.funnel
26
+ const channels = funnel.channels.list()
27
+
28
+ if (channels.length === 0) return c.text("no channels")
29
+
30
+ const lines = channels.map((ch) => {
31
+ const names = ch.connectors.map((c) => c.name)
32
+ const connectors = names.length > 0 ? names.join(", ") : "(none)"
33
+
34
+ return `${ch.name} [${connectors}]`
35
+ })
36
+
37
+ return c.text(lines.join("\n"))
38
+ },
39
+ )
@@ -0,0 +1,69 @@
1
+ import { HTTPException } from "hono/http-exception"
2
+ import { z } from "zod"
3
+ import { factory } from "@/cli/factory"
4
+ import { queryToCliArgs } from "@/cli/router/query-to-cli-args"
5
+ import { zValidator } from "@/cli/router/validator"
6
+
7
+ export const claudeHelp = `funnel claude — launch Claude Code
8
+
9
+ usage:
10
+ funnel claude launch the default profile (first in the list)
11
+ funnel claude -p <name> launch a named profile
12
+ funnel claude --profile <name> (long form)
13
+ funnel claude --channel <name> raw launch (no profile, cwd = current dir)
14
+
15
+ options:
16
+ -p, --profile profile name to launch
17
+ --channel channel name (raw launch, ignored when --profile is given)
18
+
19
+ Any other arguments are forwarded to the claude CLI.
20
+ On launch the FUNNEL_CHANNEL_ID env var is set and MCP connects to the gateway.`
21
+
22
+ const RESERVED_KEYS = ["profile", "channel"]
23
+
24
+ export const claudeHandler = factory.createHandlers(
25
+ zValidator(
26
+ "query",
27
+ z
28
+ .object({
29
+ profile: z.string().optional(),
30
+ channel: z.string().optional(),
31
+ })
32
+ .passthrough(),
33
+ claudeHelp,
34
+ ),
35
+ async (c) => {
36
+ const query = c.req.valid("query")
37
+ const funnel = c.var.funnel
38
+
39
+ if (query.channel && !query.profile) {
40
+ const exitCode = await funnel.claude.launch({
41
+ channel: query.channel,
42
+ userArgs: queryToCliArgs(c.req.url, RESERVED_KEYS),
43
+ })
44
+
45
+ process.exit(exitCode)
46
+ }
47
+
48
+ const profile = query.profile
49
+ ? funnel.profiles.get(query.profile)
50
+ : funnel.profiles.getDefault()
51
+
52
+ if (!profile) {
53
+ if (query.profile) {
54
+ throw new HTTPException(404, { message: `profile "${query.profile}" not found` })
55
+ }
56
+ return c.text(claudeHelp)
57
+ }
58
+
59
+ const exitCode = await funnel.claude.launch({
60
+ channel: profile.channelId,
61
+ cwd: profile.path,
62
+ subAgent: profile.subAgent,
63
+ userArgs: queryToCliArgs(c.req.url, RESERVED_KEYS),
64
+ profileName: profile.name,
65
+ })
66
+
67
+ process.exit(exitCode)
68
+ },
69
+ )
@@ -0,0 +1,41 @@
1
+ import { HTTPException } from "hono/http-exception"
2
+ import { z } from "zod"
3
+ import { factory } from "@/cli/factory"
4
+ import { zValidator } from "@/cli/router/validator"
5
+
6
+ export const listenersHelp = `funnel gateway listeners — show running connector listeners
7
+
8
+ usage: funnel gateway listeners
9
+
10
+ Reads /listeners from the running gateway daemon and prints the live registry.
11
+
12
+ examples:
13
+ funnel gateway listeners`
14
+
15
+ export const gatewayListenersHandler = factory.createHandlers(
16
+ zValidator("query", z.object({}), listenersHelp),
17
+ async (c) => {
18
+ const funnel = c.var.funnel
19
+ const result = await funnel.listeners.list()
20
+
21
+ if (result.state === "offline") {
22
+ throw new HTTPException(503, { message: "funnel gateway: not running" })
23
+ }
24
+
25
+ if (result.state === "error") {
26
+ throw new HTTPException(503, { message: `funnel gateway: ${result.reason}` })
27
+ }
28
+
29
+ if (result.listeners.length === 0) {
30
+ return c.text("funnel gateway: no running listeners")
31
+ }
32
+
33
+ const lines = result.listeners.map((entry) => {
34
+ const health = entry.alive ? "alive" : "dead"
35
+
36
+ return ` [${health.padEnd(5)}] ${entry.type.padEnd(8)} ${entry.name}`
37
+ })
38
+
39
+ return c.text(`funnel gateway: running listeners\n${lines.join("\n")}`)
40
+ },
41
+ )