@interactive-inc/claude-funnel 0.4.1 → 0.8.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 (349) hide show
  1. package/README.md +233 -111
  2. package/dist/bin.js +1417 -0
  3. package/dist/gateway/daemon.js +513 -0
  4. package/dist/highlights-eq9cgrbb.scm +604 -0
  5. package/dist/highlights-ghv9g403.scm +205 -0
  6. package/dist/highlights-hk7bwhj4.scm +284 -0
  7. package/dist/highlights-r812a2qc.scm +150 -0
  8. package/dist/highlights-x6tmsnaa.scm +115 -0
  9. package/dist/injections-73j83es3.scm +27 -0
  10. package/dist/tree-sitter-javascript-nd0q4pe9.wasm +0 -0
  11. package/dist/tree-sitter-markdown-411r6y9b.wasm +0 -0
  12. package/dist/tree-sitter-markdown_inline-j5349f42.wasm +0 -0
  13. package/dist/tree-sitter-typescript-zxjzwt75.wasm +0 -0
  14. package/dist/tree-sitter-zig-e78zbjpm.wasm +0 -0
  15. package/lib/bin.ts +78 -0
  16. package/lib/{modules → cli}/router/to-request.ts +13 -20
  17. package/lib/cli/routes/channels.$channel.connectors.$connector.rename.$newName.ts +27 -0
  18. package/lib/cli/routes/channels.$channel.connectors.$connector.request.ts +40 -0
  19. package/lib/cli/routes/channels.$channel.connectors.$connector.schedules.add.$id.ts +41 -0
  20. package/lib/cli/routes/channels.$channel.connectors.$connector.schedules.remove.$id.ts +22 -0
  21. package/lib/cli/routes/channels.$channel.connectors.$connector.schedules.ts +23 -0
  22. package/lib/cli/routes/channels.$channel.connectors.$connector.ts +26 -0
  23. package/lib/cli/routes/channels.$channel.connectors.add.$connector.ts +92 -0
  24. package/lib/cli/routes/channels.$channel.connectors.remove.$connector.ts +22 -0
  25. package/lib/cli/routes/channels.$channel.connectors.set.$connector.ts +63 -0
  26. package/lib/cli/routes/channels.$channel.connectors.ts +26 -0
  27. package/lib/cli/routes/channels.$channel.rename.$newName.ts +22 -0
  28. package/lib/cli/routes/channels.$channel.set.delivery.$mode.ts +34 -0
  29. package/lib/cli/routes/channels.$channel.ts +34 -0
  30. package/lib/cli/routes/channels.add.$channel.ts +33 -0
  31. package/lib/cli/routes/channels.remove.$channel.ts +20 -0
  32. package/lib/cli/routes/channels.ts +39 -0
  33. package/lib/cli/routes/claude.ts +69 -0
  34. package/lib/cli/routes/gateway.listeners.ts +41 -0
  35. package/lib/cli/routes/gateway.logs.ts +123 -0
  36. package/lib/{routes/gateway/restart.ts → cli/routes/gateway.restart.ts} +20 -5
  37. package/lib/cli/routes/gateway.run.ts +41 -0
  38. package/lib/cli/routes/gateway.start.ts +50 -0
  39. package/lib/cli/routes/gateway.status.ts +19 -0
  40. package/lib/cli/routes/gateway.stop.ts +32 -0
  41. package/lib/cli/routes/gateway.ts +55 -0
  42. package/lib/cli/routes/index.ts +202 -0
  43. package/lib/cli/routes/profiles.$profile.as-default.ts +22 -0
  44. package/lib/cli/routes/profiles.$profile.rename.$newName.ts +22 -0
  45. package/lib/cli/routes/profiles.$profile.run.ts +36 -0
  46. package/lib/cli/routes/profiles.add.$profile.ts +46 -0
  47. package/lib/cli/routes/profiles.remove.$profile.ts +20 -0
  48. package/lib/cli/routes/profiles.set.$profile.ts +46 -0
  49. package/lib/cli/routes/profiles.ts +40 -0
  50. package/lib/cli/routes/status.ts +93 -0
  51. package/lib/cli/routes/update.ts +27 -0
  52. package/lib/connectors/connector-config-schema.ts +16 -0
  53. package/lib/connectors/connector-factory.ts +94 -0
  54. package/lib/connectors/connector-listener.ts +20 -0
  55. package/lib/{modules/connectors/funnel-discord-adapter.ts → connectors/discord-adapter.ts} +6 -11
  56. package/lib/{modules/connectors → connectors}/discord-connector-schema.ts +4 -1
  57. package/lib/connectors/discord-listener.ts +111 -0
  58. package/lib/{modules/connectors/funnel-gh-adapter.ts → connectors/gh-adapter.ts} +3 -6
  59. package/lib/{modules/connectors → connectors}/gh-connector-schema.ts +4 -1
  60. package/lib/{modules/connectors/funnel-gh-listener.ts → connectors/gh-listener.ts} +57 -22
  61. package/lib/{modules/connectors → connectors}/match-cron.ts +10 -4
  62. package/lib/connectors/schedule-connector-schema.ts +33 -0
  63. package/lib/connectors/schedule-listener.ts +207 -0
  64. package/lib/connectors/schedule-state-store.ts +54 -0
  65. package/lib/connectors/slack-adapter.ts +36 -0
  66. package/lib/{modules/connectors → connectors}/slack-connector-schema.ts +4 -1
  67. package/lib/{modules/connectors/funnel-slack-event-processor.ts → connectors/slack-event-processor.ts} +15 -9
  68. package/lib/{modules/connectors/funnel-slack-listener.ts → connectors/slack-listener.ts} +39 -14
  69. package/lib/engine/channels/channels.ts +520 -0
  70. package/lib/{modules/claude/funnel-claude.ts → engine/claude/claude.ts} +47 -62
  71. package/lib/engine/claude/gateway-controller.ts +4 -0
  72. package/lib/{modules/fs/funnel-file-system.ts → engine/fs/file-system.ts} +9 -0
  73. package/lib/{modules/fs/memory-funnel-file-system.ts → engine/fs/memory-file-system.ts} +20 -3
  74. package/lib/{modules/fs/node-funnel-file-system.ts → engine/fs/node-file-system.ts} +14 -2
  75. package/lib/{modules/http/memory-funnel-http-client.ts → engine/http/memory-http-client.ts} +1 -5
  76. package/lib/{modules/http/node-funnel-http-client.ts → engine/http/node-http-client.ts} +1 -5
  77. package/lib/engine/id/id-generator.ts +7 -0
  78. package/lib/engine/id/memory-id-generator.ts +20 -0
  79. package/lib/engine/id/node-id-generator.ts +7 -0
  80. package/lib/engine/logger/logger.ts +11 -0
  81. package/lib/engine/logger/memory-logger.ts +28 -0
  82. package/lib/engine/logger/node-logger.ts +49 -0
  83. package/lib/engine/logger/noop-logger.ts +9 -0
  84. package/lib/engine/mcp/channel-server.ts +204 -0
  85. package/lib/{modules/mcp/funnel-mcp.ts → engine/mcp/mcp.ts} +29 -10
  86. package/lib/{modules/process/memory-funnel-process-runner.ts → engine/process/memory-process-runner.ts} +1 -1
  87. package/lib/{modules/process/node-funnel-process-runner.ts → engine/process/node-process-runner.ts} +12 -21
  88. package/lib/{modules/process/funnel-process-runner.ts → engine/process/process-runner.ts} +5 -0
  89. package/lib/engine/profiles/profile-channel-checker.ts +7 -0
  90. package/lib/engine/profiles/profiles.ts +126 -0
  91. package/lib/{modules/settings/mock-funnel-settings-reader.ts → engine/settings/mock-settings-reader.ts} +4 -3
  92. package/lib/{modules/settings/funnel-settings-reader.ts → engine/settings/settings-reader.ts} +1 -1
  93. package/lib/engine/settings/settings-schema.ts +46 -0
  94. package/lib/engine/settings/settings-store.ts +110 -0
  95. package/lib/engine/time/clock.ts +15 -0
  96. package/lib/engine/time/memory-clock.ts +26 -0
  97. package/lib/engine/time/node-clock.ts +7 -0
  98. package/lib/funnel.ts +148 -56
  99. package/lib/gateway/auth-middleware.ts +44 -0
  100. package/lib/gateway/broadcaster.ts +319 -0
  101. package/lib/gateway/daemon.ts +47 -0
  102. package/lib/gateway/factory.ts +10 -0
  103. package/lib/gateway/funnel-event-store.ts +155 -0
  104. package/lib/gateway/gateway-server.ts +414 -0
  105. package/lib/gateway/gateway-token.ts +79 -0
  106. package/lib/{modules/gateway/funnel-gateway.ts → gateway/gateway.ts} +70 -27
  107. package/lib/{modules/gateway → gateway}/kill-competing-slack-gateways.ts +7 -3
  108. package/lib/gateway/listener-supervisor.ts +339 -0
  109. package/lib/gateway/listeners-client.ts +128 -0
  110. package/lib/gateway/resolve-daemon-script.ts +26 -0
  111. package/lib/gateway/routes/channels.connectors.call.ts +39 -0
  112. package/lib/gateway/routes/health.ts +13 -0
  113. package/lib/gateway/routes/index.ts +24 -0
  114. package/lib/gateway/routes/listeners.list.ts +6 -0
  115. package/lib/gateway/routes/listeners.restart.ts +15 -0
  116. package/lib/gateway/routes/listeners.start.ts +15 -0
  117. package/lib/gateway/routes/listeners.stop.ts +15 -0
  118. package/lib/gateway/routes/route-deps.ts +11 -0
  119. package/lib/gateway/routes/status.ts +15 -0
  120. package/lib/gateway/routes/validator.ts +17 -0
  121. package/lib/index.ts +50 -92
  122. package/lib/logger/leuco-human-file-writer.ts +65 -0
  123. package/lib/logger/leuco-human-logger.ts +98 -0
  124. package/lib/logger/leuco-human-record.ts +16 -0
  125. package/lib/logger/leuco-human-stdout-writer.ts +26 -0
  126. package/lib/logger/leuco-human-writer.ts +14 -0
  127. package/lib/logger/leuco-logger-memory-sink.ts +67 -0
  128. package/lib/logger/leuco-logger-record.ts +13 -0
  129. package/lib/logger/leuco-logger-sink.ts +33 -0
  130. package/lib/logger/leuco-logger-sqlite-sink.ts +355 -0
  131. package/lib/logger/leuco-logger.ts +135 -0
  132. package/lib/tui/app.tsx +357 -0
  133. package/lib/tui/components/add-row.tsx +18 -0
  134. package/lib/tui/components/brand.tsx +27 -0
  135. package/lib/tui/components/card.tsx +44 -0
  136. package/lib/tui/components/detail-bar.tsx +46 -0
  137. package/lib/tui/components/editable-field.tsx +33 -0
  138. package/lib/tui/components/empty-state.tsx +11 -0
  139. package/lib/tui/components/gateway-status.tsx +66 -0
  140. package/lib/tui/components/keymap.tsx +29 -0
  141. package/lib/tui/components/menu-item.tsx +73 -0
  142. package/lib/tui/components/menu.tsx +26 -0
  143. package/lib/tui/components/panel-header.tsx +22 -0
  144. package/lib/tui/components/readonly-field.tsx +18 -0
  145. package/lib/tui/components/section-header.tsx +25 -0
  146. package/lib/tui/components/selection-accent.tsx +32 -0
  147. package/lib/tui/components/session-item.tsx +33 -0
  148. package/lib/tui/components/session-list.tsx +33 -0
  149. package/lib/tui/components/ui/hascii/accordion-item.tsx +88 -0
  150. package/lib/tui/components/ui/hascii/accordion.tsx +96 -0
  151. package/lib/tui/components/ui/hascii/alert-dialog.tsx +43 -0
  152. package/lib/tui/components/ui/hascii/badge.tsx +51 -0
  153. package/lib/tui/components/ui/hascii/breadcrumb.tsx +58 -0
  154. package/lib/tui/components/ui/hascii/button.tsx +194 -0
  155. package/lib/tui/components/ui/hascii/card-content.tsx +14 -0
  156. package/lib/tui/components/ui/hascii/card-description.tsx +13 -0
  157. package/lib/tui/components/ui/hascii/card-footer.tsx +14 -0
  158. package/lib/tui/components/ui/hascii/card-header.tsx +14 -0
  159. package/lib/tui/components/ui/hascii/card-title.tsx +13 -0
  160. package/lib/tui/components/ui/hascii/card.tsx +27 -0
  161. package/lib/tui/components/ui/hascii/checkbox.tsx +65 -0
  162. package/lib/tui/components/ui/hascii/command.tsx +159 -0
  163. package/lib/tui/components/ui/hascii/dialog-content.tsx +14 -0
  164. package/lib/tui/components/ui/hascii/dialog-description.tsx +13 -0
  165. package/lib/tui/components/ui/hascii/dialog-footer.tsx +14 -0
  166. package/lib/tui/components/ui/hascii/dialog-header.tsx +14 -0
  167. package/lib/tui/components/ui/hascii/dialog-title.tsx +13 -0
  168. package/lib/tui/components/ui/hascii/dialog.tsx +27 -0
  169. package/lib/tui/components/ui/hascii/file-tree.tsx +142 -0
  170. package/lib/tui/components/ui/hascii/focus-group.tsx +62 -0
  171. package/lib/tui/components/ui/hascii/form-item.tsx +43 -0
  172. package/lib/tui/components/ui/hascii/input-otp.tsx +86 -0
  173. package/lib/tui/components/ui/hascii/input.tsx +130 -0
  174. package/lib/tui/components/ui/hascii/pagination.tsx +105 -0
  175. package/lib/tui/components/ui/hascii/progress.tsx +28 -0
  176. package/lib/tui/components/ui/hascii/select.tsx +131 -0
  177. package/lib/tui/components/ui/hascii/separator.tsx +35 -0
  178. package/lib/tui/components/ui/hascii/sidebar-content.tsx +23 -0
  179. package/lib/tui/components/ui/hascii/sidebar-header.tsx +14 -0
  180. package/lib/tui/components/ui/hascii/sidebar-menu-item.tsx +67 -0
  181. package/lib/tui/components/ui/hascii/sidebar.tsx +24 -0
  182. package/lib/tui/components/ui/hascii/skeleton.tsx +60 -0
  183. package/lib/tui/components/ui/hascii/slider.tsx +91 -0
  184. package/lib/tui/components/ui/hascii/snackbar.tsx +75 -0
  185. package/lib/tui/components/ui/hascii/sparkline.tsx +53 -0
  186. package/lib/tui/components/ui/hascii/spinner.tsx +47 -0
  187. package/lib/tui/components/ui/hascii/stepper.tsx +54 -0
  188. package/lib/tui/components/ui/hascii/switch.tsx +66 -0
  189. package/lib/tui/components/ui/hascii/table.tsx +95 -0
  190. package/lib/tui/components/ui/hascii/tabs.tsx +59 -0
  191. package/lib/tui/components/ui/hascii/toggle-group-item.tsx +45 -0
  192. package/lib/tui/components/ui/hascii/toggle-group.tsx +99 -0
  193. package/lib/tui/components/ui/hascii/tree.tsx +104 -0
  194. package/lib/tui/components/view-shell.tsx +44 -0
  195. package/lib/tui/filter-input.tsx +33 -0
  196. package/lib/tui/hooks/hascii/use-pressable.ts +54 -0
  197. package/lib/tui/parse-comma-list.ts +14 -0
  198. package/lib/tui/profile-launcher.tsx +61 -0
  199. package/lib/tui/scrollbar-options.ts +19 -0
  200. package/lib/tui/sidebar.tsx +50 -0
  201. package/lib/tui/theme.ts +40 -0
  202. package/lib/tui/tui.tsx +20 -0
  203. package/lib/tui/types.ts +38 -0
  204. package/lib/tui/unique-name.ts +18 -0
  205. package/lib/tui/use-event-stream.ts +133 -0
  206. package/lib/tui/use-snapshot.ts +99 -0
  207. package/lib/tui/utils/hascii/form-item-context.tsx +23 -0
  208. package/lib/tui/utils/hascii/input-focus-context.tsx +31 -0
  209. package/lib/tui/utils/hascii/theme-context.tsx +26 -0
  210. package/lib/tui/utils/hascii/theme.ts +176 -0
  211. package/lib/tui/views/channels-view.tsx +108 -0
  212. package/lib/tui/views/connectors-view.tsx +164 -0
  213. package/lib/tui/views/events-view.tsx +160 -0
  214. package/lib/tui/views/listeners-view.tsx +80 -0
  215. package/lib/tui/views/profiles-view.tsx +152 -0
  216. package/package.json +51 -34
  217. package/lib/modules/channels/channel-connector-ref-updater.ts +0 -4
  218. package/lib/modules/channels/funnel-channels.ts +0 -155
  219. package/lib/modules/connectors/connector-config-schema.ts +0 -16
  220. package/lib/modules/connectors/connector-existence-checker.ts +0 -3
  221. package/lib/modules/connectors/funnel-callable-connector-store.ts +0 -9
  222. package/lib/modules/connectors/funnel-connector-listener.ts +0 -5
  223. package/lib/modules/connectors/funnel-connector-stores.ts +0 -24
  224. package/lib/modules/connectors/funnel-connector-type-store.ts +0 -24
  225. package/lib/modules/connectors/funnel-connectors.ts +0 -145
  226. package/lib/modules/connectors/funnel-discord-listener.ts +0 -65
  227. package/lib/modules/connectors/funnel-discord-store.ts +0 -84
  228. package/lib/modules/connectors/funnel-gh-store.ts +0 -84
  229. package/lib/modules/connectors/funnel-json-connector-store.ts +0 -100
  230. package/lib/modules/connectors/funnel-schedule-listener.ts +0 -124
  231. package/lib/modules/connectors/funnel-schedule-store.ts +0 -178
  232. package/lib/modules/connectors/funnel-slack-adapter.ts +0 -31
  233. package/lib/modules/connectors/funnel-slack-store.ts +0 -86
  234. package/lib/modules/connectors/migrate-legacy-connectors.ts +0 -77
  235. package/lib/modules/connectors/schedule-connector-schema.ts +0 -18
  236. package/lib/modules/connectors/schedule-last-fired-store.ts +0 -48
  237. package/lib/modules/gateway/daemon.ts +0 -207
  238. package/lib/modules/gateway/funnel-broadcaster.ts +0 -37
  239. package/lib/modules/gateway/funnel-event-logger.ts +0 -59
  240. package/lib/modules/logger.ts +0 -26
  241. package/lib/modules/mcp/channel-server.ts +0 -76
  242. package/lib/modules/profiles/funnel-profiles.ts +0 -123
  243. package/lib/modules/profiles/profile-channel-checker.ts +0 -3
  244. package/lib/modules/profiles/profile-channel-ref-updater.ts +0 -3
  245. package/lib/modules/repos/funnel-repositories.ts +0 -107
  246. package/lib/modules/schedule/funnel-schedule.ts +0 -34
  247. package/lib/modules/settings/funnel-settings-store.ts +0 -56
  248. package/lib/modules/settings/settings-schema.ts +0 -33
  249. package/lib/modules/tui/app.tsx +0 -44
  250. package/lib/modules/tui/tui.tsx +0 -13
  251. package/lib/routes/channels/add.help.ts +0 -3
  252. package/lib/routes/channels/add.ts +0 -21
  253. package/lib/routes/channels/connectors-attach.help.ts +0 -3
  254. package/lib/routes/channels/connectors-attach.ts +0 -17
  255. package/lib/routes/channels/connectors-detach.help.ts +0 -3
  256. package/lib/routes/channels/connectors-detach.ts +0 -17
  257. package/lib/routes/channels/group.help.ts +0 -16
  258. package/lib/routes/channels/group.ts +0 -22
  259. package/lib/routes/channels/remove.help.ts +0 -3
  260. package/lib/routes/channels/remove.ts +0 -17
  261. package/lib/routes/channels/rename.help.ts +0 -5
  262. package/lib/routes/channels/rename.ts +0 -17
  263. package/lib/routes/channels/routes.ts +0 -19
  264. package/lib/routes/channels/show.help.ts +0 -1
  265. package/lib/routes/channels/show.ts +0 -26
  266. package/lib/routes/claude/claude.help.ts +0 -16
  267. package/lib/routes/claude/claude.ts +0 -76
  268. package/lib/routes/claude/routes.ts +0 -4
  269. package/lib/routes/connectors/add.help.ts +0 -28
  270. package/lib/routes/connectors/add.ts +0 -64
  271. package/lib/routes/connectors/group.help.ts +0 -14
  272. package/lib/routes/connectors/group.ts +0 -18
  273. package/lib/routes/connectors/remove.help.ts +0 -3
  274. package/lib/routes/connectors/remove.ts +0 -17
  275. package/lib/routes/connectors/rename.help.ts +0 -5
  276. package/lib/routes/connectors/rename.ts +0 -17
  277. package/lib/routes/connectors/routes.ts +0 -23
  278. package/lib/routes/connectors/schedules-add.help.ts +0 -11
  279. package/lib/routes/connectors/schedules-add.ts +0 -33
  280. package/lib/routes/connectors/schedules-group.help.ts +0 -1
  281. package/lib/routes/connectors/schedules-group.ts +0 -38
  282. package/lib/routes/connectors/schedules-remove.help.ts +0 -3
  283. package/lib/routes/connectors/schedules-remove.ts +0 -17
  284. package/lib/routes/connectors/set.help.ts +0 -8
  285. package/lib/routes/connectors/set.ts +0 -72
  286. package/lib/routes/connectors/show.help.ts +0 -1
  287. package/lib/routes/connectors/show.ts +0 -41
  288. package/lib/routes/gateway/group.help.ts +0 -15
  289. package/lib/routes/gateway/group.ts +0 -28
  290. package/lib/routes/gateway/logs.help.ts +0 -13
  291. package/lib/routes/gateway/logs.ts +0 -100
  292. package/lib/routes/gateway/restart.help.ts +0 -10
  293. package/lib/routes/gateway/routes.ts +0 -18
  294. package/lib/routes/gateway/run.help.ts +0 -12
  295. package/lib/routes/gateway/run.ts +0 -35
  296. package/lib/routes/gateway/start.help.ts +0 -15
  297. package/lib/routes/gateway/start.ts +0 -32
  298. package/lib/routes/gateway/status.help.ts +0 -9
  299. package/lib/routes/gateway/status.ts +0 -28
  300. package/lib/routes/gateway/stop.help.ts +0 -8
  301. package/lib/routes/gateway/stop.ts +0 -21
  302. package/lib/routes/profiles/add.help.ts +0 -3
  303. package/lib/routes/profiles/add.ts +0 -33
  304. package/lib/routes/profiles/group.help.ts +0 -16
  305. package/lib/routes/profiles/group.ts +0 -25
  306. package/lib/routes/profiles/launch.help.ts +0 -4
  307. package/lib/routes/profiles/launch.ts +0 -36
  308. package/lib/routes/profiles/remove.help.ts +0 -3
  309. package/lib/routes/profiles/remove.ts +0 -17
  310. package/lib/routes/profiles/rename.help.ts +0 -5
  311. package/lib/routes/profiles/rename.ts +0 -17
  312. package/lib/routes/profiles/routes.ts +0 -18
  313. package/lib/routes/profiles/set.help.ts +0 -5
  314. package/lib/routes/profiles/set.ts +0 -32
  315. package/lib/routes/repos/add.help.ts +0 -6
  316. package/lib/routes/repos/add.ts +0 -20
  317. package/lib/routes/repos/group.help.ts +0 -11
  318. package/lib/routes/repos/group.ts +0 -18
  319. package/lib/routes/repos/remove.help.ts +0 -3
  320. package/lib/routes/repos/remove.ts +0 -17
  321. package/lib/routes/repos/rename.help.ts +0 -5
  322. package/lib/routes/repos/rename.ts +0 -17
  323. package/lib/routes/repos/routes.ts +0 -17
  324. package/lib/routes/repos/set.help.ts +0 -5
  325. package/lib/routes/repos/set.ts +0 -21
  326. package/lib/routes/repos/show.help.ts +0 -1
  327. package/lib/routes/repos/show.ts +0 -19
  328. package/lib/routes/request/discord-help.ts +0 -9
  329. package/lib/routes/request/discord.help.ts +0 -19
  330. package/lib/routes/request/discord.ts +0 -65
  331. package/lib/routes/request/group.help.ts +0 -15
  332. package/lib/routes/request/group.ts +0 -9
  333. package/lib/routes/request/routes.ts +0 -14
  334. package/lib/routes/request/slack-help.ts +0 -9
  335. package/lib/routes/request/slack.help.ts +0 -19
  336. package/lib/routes/request/slack.ts +0 -61
  337. package/lib/routes/status/routes.ts +0 -4
  338. package/lib/routes/status/status.help.ts +0 -6
  339. package/lib/routes/status/status.ts +0 -77
  340. package/lib/routes/update/routes.ts +0 -4
  341. package/lib/routes/update/update.help.ts +0 -5
  342. package/lib/routes/update/update.ts +0 -21
  343. package/lib/routes.ts +0 -40
  344. /package/lib/{factory.ts → cli/factory.ts} +0 -0
  345. /package/lib/{modules → cli}/router/query-to-cli-args.ts +0 -0
  346. /package/lib/{modules → cli}/router/validator.ts +0 -0
  347. /package/lib/{modules/connectors/funnel-connector-adapter.ts → connectors/connector-adapter.ts} +0 -0
  348. /package/lib/{modules/connectors/funnel-discord-event-processor.ts → connectors/discord-event-processor.ts} +0 -0
  349. /package/lib/{modules/http/funnel-http-client.ts → engine/http/http-client.ts} +0 -0
@@ -1,17 +0,0 @@
1
- import { z } from "zod"
2
- import { factory } from "@/factory"
3
- import { zValidator } from "@/modules/router/validator"
4
- import { help } from "@/routes/connectors/rename.help"
5
-
6
- export const connectorsRenameHandler = factory.createHandlers(
7
- zValidator("param", z.object({ name: z.string(), newName: z.string() })),
8
- zValidator("query", z.object({}), help),
9
- (c) => {
10
- const param = c.req.valid("param")
11
- const funnel = c.var.funnel
12
-
13
- funnel.connectors.rename(param.name, param["newName"])
14
-
15
- return c.text(`renamed connector "${param.name}" to "${param["newName"]}"`)
16
- },
17
- )
@@ -1,23 +0,0 @@
1
- import { factory } from "@/factory"
2
- import { connectorsAddHandler } from "@/routes/connectors/add"
3
- import { connectorsGroupHandler } from "@/routes/connectors/group"
4
- import { connectorsRemoveHandler } from "@/routes/connectors/remove"
5
- import { connectorsRenameHandler } from "@/routes/connectors/rename"
6
- import { connectorsSchedulesAddHandler } from "@/routes/connectors/schedules-add"
7
- import { connectorsSchedulesGroupHandler } from "@/routes/connectors/schedules-group"
8
- import { connectorsSchedulesRemoveHandler } from "@/routes/connectors/schedules-remove"
9
- import { connectorsSetHandler } from "@/routes/connectors/set"
10
- import { connectorsShowHandler } from "@/routes/connectors/show"
11
-
12
- export const connectorsRoutes = factory
13
- .createApp()
14
- .get("/", ...connectorsGroupHandler)
15
- .put("/:name/rename/:newName", ...connectorsRenameHandler)
16
- .put("/rename/:name/:newName", ...connectorsRenameHandler)
17
- .post("/:name/schedules", ...connectorsSchedulesAddHandler)
18
- .get("/:name/schedules", ...connectorsSchedulesGroupHandler)
19
- .delete("/:name/schedules/:id", ...connectorsSchedulesRemoveHandler)
20
- .post("/:name", ...connectorsAddHandler)
21
- .put("/:name", ...connectorsSetHandler)
22
- .delete("/:name", ...connectorsRemoveHandler)
23
- .get("/:name", ...connectorsShowHandler)
@@ -1,11 +0,0 @@
1
- export const help = `funnel connectors <name> schedules add — add a schedule entry
2
-
3
- usage: funnel connectors <name> schedules add --cron "<expr>" --prompt "<text>" [--disabled]
4
-
5
- options:
6
- --cron 5-field cron expression (min hour dom month dow)
7
- --prompt prompt text delivered to subscribing channels when the cron fires
8
- --disabled create the entry in disabled state
9
-
10
- example:
11
- funnel connectors my-cron schedules add --cron "*/5 * * * *" --prompt "status check"`
@@ -1,33 +0,0 @@
1
- import { z } from "zod"
2
- import { factory } from "@/factory"
3
- import { matchCron } from "@/modules/connectors/match-cron"
4
- import { zValidator } from "@/modules/router/validator"
5
- import { help } from "@/routes/connectors/schedules-add.help"
6
-
7
- export const connectorsSchedulesAddHandler = factory.createHandlers(
8
- zValidator("param", z.object({ name: z.string() })),
9
- zValidator(
10
- "query",
11
- z.object({
12
- cron: z.string(),
13
- prompt: z.string(),
14
- disabled: z.string().optional(),
15
- }),
16
- help,
17
- ),
18
- (c) => {
19
- const param = c.req.valid("param")
20
- const query = c.req.valid("query")
21
- const funnel = c.var.funnel
22
-
23
- matchCron(query.cron, new Date())
24
-
25
- const entry = funnel.schedule.addEntry(param.name, {
26
- cron: query.cron,
27
- prompt: query.prompt,
28
- enabled: query.disabled !== "true",
29
- })
30
-
31
- return c.text(`added schedule entry "${entry.id}" to connector "${param.name}"`)
32
- },
33
- )
@@ -1 +0,0 @@
1
- export const help = `funnel connectors <name> schedules — list schedule entries`
@@ -1,38 +0,0 @@
1
- import { HTTPException } from "hono/http-exception"
2
- import { z } from "zod"
3
- import { factory } from "@/factory"
4
- import { zValidator } from "@/modules/router/validator"
5
- import { help } from "@/routes/connectors/schedules-group.help"
6
-
7
- export const connectorsSchedulesGroupHandler = factory.createHandlers(
8
- zValidator("param", z.object({ name: z.string() })),
9
- zValidator("query", z.object({}), help),
10
- (c) => {
11
- const param = c.req.valid("param")
12
- const funnel = c.var.funnel
13
- const connector = funnel.connectors.get(param.name)
14
-
15
- if (!connector) {
16
- throw new HTTPException(404, { message: `connector "${param.name}" not found` })
17
- }
18
-
19
- if (connector.type !== "schedule") {
20
- throw new HTTPException(400, {
21
- message: `connector "${param.name}" is type "${connector.type}", not "schedule"`,
22
- })
23
- }
24
-
25
- const entries = funnel.schedule.listEntries(param.name)
26
-
27
- if (entries.length === 0) return c.text("no schedule entries")
28
-
29
- const lines: string[] = []
30
-
31
- for (const entry of entries) {
32
- const status = entry.enabled ? "" : " (disabled)"
33
- lines.push(`${entry.id}${status} ${entry.cron} ${entry.prompt}`)
34
- }
35
-
36
- return c.text(lines.join("\n"))
37
- },
38
- )
@@ -1,3 +0,0 @@
1
- export const help = `funnel connectors <name> schedules remove — remove a schedule entry
2
-
3
- usage: funnel connectors <name> schedules remove <id>`
@@ -1,17 +0,0 @@
1
- import { z } from "zod"
2
- import { factory } from "@/factory"
3
- import { zValidator } from "@/modules/router/validator"
4
- import { help } from "@/routes/connectors/schedules-remove.help"
5
-
6
- export const connectorsSchedulesRemoveHandler = factory.createHandlers(
7
- zValidator("param", z.object({ name: z.string(), id: z.string() })),
8
- zValidator("query", z.object({}), help),
9
- (c) => {
10
- const param = c.req.valid("param")
11
- const funnel = c.var.funnel
12
-
13
- funnel.schedule.removeEntry(param.name, param.id)
14
-
15
- return c.text(`removed schedule entry "${param.id}" from connector "${param.name}"`)
16
- },
17
- )
@@ -1,8 +0,0 @@
1
- export const help = `funnel connectors <name> set — update a connector
2
-
3
- usage: funnel connectors <name> set [--bot-token ...] [--app-token ...] [--poll-interval ...]
4
-
5
- fields available per type:
6
- slack : --bot-token / --app-token
7
- gh : --poll-interval
8
- discord : --bot-token`
@@ -1,72 +0,0 @@
1
- import { HTTPException } from "hono/http-exception"
2
- import { z } from "zod"
3
- import { factory } from "@/factory"
4
- import { zValidator } from "@/modules/router/validator"
5
- import { help } from "@/routes/connectors/set.help"
6
-
7
- const SLACK_FIELDS = ["bot-token", "app-token"] as const
8
- const GH_FIELDS = ["poll-interval"] as const
9
- const DISCORD_FIELDS = ["bot-token"] as const
10
-
11
- const rejectExtraneous = (
12
- query: Record<string, string | undefined>,
13
- allowed: ReadonlyArray<string>,
14
- type: string,
15
- ): void => {
16
- for (const key of ["bot-token", "app-token", "poll-interval"]) {
17
- if (query[key] === undefined) continue
18
- if (allowed.includes(key)) continue
19
-
20
- throw new HTTPException(400, {
21
- message: `connector type "${type}" does not accept --${key}`,
22
- })
23
- }
24
- }
25
-
26
- export const connectorsSetHandler = factory.createHandlers(
27
- zValidator("param", z.object({ name: z.string() })),
28
- zValidator(
29
- "query",
30
- z.object({
31
- "bot-token": z.string().optional(),
32
- "app-token": z.string().optional(),
33
- "poll-interval": z.string().optional(),
34
- }),
35
- help,
36
- ),
37
- (c) => {
38
- const param = c.req.valid("param")
39
- const query = c.req.valid("query")
40
- const funnel = c.var.funnel
41
-
42
- const current = funnel.connectors.get(param.name)
43
-
44
- if (!current) {
45
- throw new HTTPException(404, { message: `connector "${param.name}" not found` })
46
- }
47
-
48
- if (current.type === "slack") {
49
- rejectExtraneous(query, SLACK_FIELDS, "slack")
50
- funnel.connectors.updateSlack(param.name, {
51
- botToken: query["bot-token"],
52
- appToken: query["app-token"],
53
- })
54
- } else if (current.type === "gh") {
55
- rejectExtraneous(query, GH_FIELDS, "gh")
56
- funnel.connectors.updateGh(param.name, {
57
- pollInterval: query["poll-interval"] ? Number(query["poll-interval"]) : undefined,
58
- })
59
- } else if (current.type === "discord") {
60
- rejectExtraneous(query, DISCORD_FIELDS, "discord")
61
- funnel.connectors.updateDiscord(param.name, {
62
- botToken: query["bot-token"],
63
- })
64
- } else {
65
- throw new HTTPException(400, {
66
- message: `schedule connectors have no top-level fields — use schedules add/remove`,
67
- })
68
- }
69
-
70
- return c.text(`updated connector "${param.name}"`)
71
- },
72
- )
@@ -1 +0,0 @@
1
- export const help = `funnel connectors <name> — show connector details`
@@ -1,41 +0,0 @@
1
- import { HTTPException } from "hono/http-exception"
2
- import { z } from "zod"
3
- import { factory } from "@/factory"
4
- import { zValidator } from "@/modules/router/validator"
5
- import { help } from "@/routes/connectors/show.help"
6
-
7
- export const connectorsShowHandler = factory.createHandlers(
8
- zValidator("param", z.object({ name: z.string() })),
9
- zValidator("query", z.object({}), help),
10
- (c) => {
11
- const param = c.req.valid("param")
12
- const funnel = c.var.funnel
13
- const connector = funnel.connectors.get(param.name)
14
-
15
- if (!connector) {
16
- throw new HTTPException(404, { message: `connector "${param.name}" not found` })
17
- }
18
-
19
- const lines: string[] = [`name: ${connector.name}`, `type: ${connector.type}`]
20
-
21
- if (connector.type === "slack") {
22
- lines.push(`botToken: ${connector.botToken.slice(0, 8)}...`)
23
- lines.push(`appToken: ${connector.appToken.slice(0, 8)}...`)
24
- } else if (connector.type === "gh") {
25
- lines.push(`pollInterval: ${connector.pollInterval ?? 60}s`)
26
- } else if (connector.type === "discord") {
27
- lines.push(`botToken: ${connector.botToken.slice(0, 8)}...`)
28
- } else if (connector.type === "schedule") {
29
- lines.push(`entries: ${connector.entries.length}`)
30
-
31
- for (const entry of connector.entries) {
32
- const status = entry.enabled ? "" : " (disabled)"
33
- lines.push(` - ${entry.id}${status}`)
34
- lines.push(` cron: ${entry.cron}`)
35
- lines.push(` prompt: ${entry.prompt}`)
36
- }
37
- }
38
-
39
- return c.text(lines.join("\n"))
40
- },
41
- )
@@ -1,15 +0,0 @@
1
- export const help = `funnel gateway — manage the gateway
2
-
3
- usage: funnel gateway [subcommand]
4
-
5
- subcommands:
6
- status show running status (default)
7
- start start in background
8
- stop stop
9
- restart stop then start
10
- run start in foreground (for developers)
11
- logs [-n <N>] show event logs
12
-
13
- examples:
14
- funnel gateway check status
15
- funnel gateway restart restart`
@@ -1,28 +0,0 @@
1
- import { z } from "zod"
2
- import { factory } from "@/factory"
3
- import { zValidator } from "@/modules/router/validator"
4
- import { help } from "@/routes/gateway/group.help"
5
-
6
- export const gatewayGroupHandler = factory.createHandlers(
7
- zValidator("query", z.object({}), help),
8
- async (c) => {
9
- const funnel = c.var.funnel
10
- const status = funnel.gateway.getStatus()
11
-
12
- if (!status.running) {
13
- return c.text("funnel gateway: not running", 503)
14
- }
15
-
16
- const res = await fetch(`http://localhost:${status.port}/health`).catch(() => null)
17
-
18
- if (!res) {
19
- return c.text(`funnel gateway: running (pid ${status.pid}) — health check failed`)
20
- }
21
-
22
- const health = (await res.json()) as Record<string, unknown>
23
-
24
- return c.text(
25
- `funnel gateway: running (pid ${status.pid})\n port: ${status.port}\n clients: ${health.clients ?? 0}`,
26
- )
27
- },
28
- )
@@ -1,13 +0,0 @@
1
- export const help = `funnel gateway logs — tail event logs
2
-
3
- usage: funnel gateway logs [-n <N>]
4
-
5
- options:
6
- -n <N> number of trailing lines to show (default: 20)
7
-
8
- Tails the latest /tmp/funnel/events/*.jsonl file. Exit with SIGINT.
9
- Output is formatted as YAML.
10
-
11
- examples:
12
- funnel gateway logs
13
- funnel gateway logs -n 100`
@@ -1,100 +0,0 @@
1
- import { readdirSync } from "node:fs"
2
- import { join } from "node:path"
3
- import { stringify } from "yaml"
4
- import { z } from "zod"
5
- import { factory } from "@/factory"
6
- import { logger } from "@/modules/logger"
7
- import { zValidator } from "@/modules/router/validator"
8
- import { help } from "@/routes/gateway/logs.help"
9
-
10
- const tryParseJson = (s: string): unknown => {
11
- try {
12
- return JSON.parse(s)
13
- } catch {
14
- return null
15
- }
16
- }
17
-
18
- export const gatewayLogsHandler = factory.createHandlers(
19
- zValidator(
20
- "query",
21
- z.object({
22
- n: z.string().optional(),
23
- }),
24
- help,
25
- ),
26
- async (c) => {
27
- const query = c.req.valid("query")
28
- const funnel = c.var.funnel
29
- const logDir = funnel.gateway.getLogDir()
30
-
31
- const files = readdirSync(logDir)
32
- .filter((name) => name.endsWith(".jsonl"))
33
- .sort()
34
-
35
- if (files.length === 0) {
36
- return c.text("no logs")
37
- }
38
-
39
- const latestFile = join(logDir, files[files.length - 1]!)
40
- const lineCount = query.n ? Number(query.n) : 20
41
-
42
- const tail = Bun.spawn(["tail", "-f", "-n", String(lineCount), latestFile], {
43
- stdout: "pipe",
44
- stderr: "inherit",
45
- })
46
-
47
- const forward = (signal: "SIGINT" | "SIGTERM") => {
48
- tail.kill(signal)
49
- }
50
-
51
- process.on("SIGINT", () => forward("SIGINT"))
52
- process.on("SIGTERM", () => forward("SIGTERM"))
53
-
54
- const reader = tail.stdout.getReader()
55
- const decoder = new TextDecoder()
56
- let buffer = ""
57
-
58
- logger.info("gateway.logs tail start", { file: latestFile })
59
-
60
- while (true) {
61
- const result = await reader.read()
62
-
63
- if (result.done) break
64
-
65
- buffer += decoder.decode(result.value, { stream: true })
66
-
67
- const lines = buffer.split("\n")
68
- buffer = lines.pop() ?? ""
69
-
70
- for (const line of lines) {
71
- if (!line.trim()) continue
72
-
73
- const entry = tryParseJson(line) as {
74
- timestamp: string
75
- eventType: string
76
- meta?: unknown
77
- content: string
78
- } | null
79
-
80
- if (!entry) {
81
- process.stdout.write(`${line}\n`)
82
- continue
83
- }
84
-
85
- const parsedContent = tryParseJson(entry.content) ?? entry.content
86
- const output = {
87
- time: entry.timestamp,
88
- type: entry.eventType,
89
- ...(entry.meta ? { meta: entry.meta } : {}),
90
- content: parsedContent,
91
- }
92
-
93
- process.stdout.write(`---\n${stringify(output)}`)
94
- }
95
- }
96
-
97
- await tail.exited
98
- process.exit(0)
99
- },
100
- )
@@ -1,10 +0,0 @@
1
- export const help = `funnel gateway restart — restart the gateway
2
-
3
- usage: funnel gateway restart [--no-caffeine]
4
-
5
- Stops the running process then starts it again in background.
6
- On macOS wraps with caffeinate -i by default. Use --no-caffeine to disable.
7
-
8
- examples:
9
- funnel gateway restart
10
- funnel gateway restart --no-caffeine`
@@ -1,18 +0,0 @@
1
- import { factory } from "@/factory"
2
- import { gatewayGroupHandler } from "@/routes/gateway/group"
3
- import { gatewayLogsHandler } from "@/routes/gateway/logs"
4
- import { gatewayRestartHandler } from "@/routes/gateway/restart"
5
- import { gatewayRunHandler } from "@/routes/gateway/run"
6
- import { gatewayStartHandler } from "@/routes/gateway/start"
7
- import { gatewayStatusHandler } from "@/routes/gateway/status"
8
- import { gatewayStopHandler } from "@/routes/gateway/stop"
9
-
10
- export const gatewayRoutes = factory
11
- .createApp()
12
- .get("/", ...gatewayGroupHandler)
13
- .get("/status", ...gatewayStatusHandler)
14
- .get("/start", ...gatewayStartHandler)
15
- .get("/stop", ...gatewayStopHandler)
16
- .get("/restart", ...gatewayRestartHandler)
17
- .get("/run", ...gatewayRunHandler)
18
- .get("/logs", ...gatewayLogsHandler)
@@ -1,12 +0,0 @@
1
- export const help = `funnel gateway run — run the gateway in foreground
2
-
3
- usage: funnel gateway run [--no-caffeine]
4
-
5
- For developers. The process is tied to the current terminal and exits on SIGINT / SIGTERM.
6
- On macOS wraps with caffeinate -i by default. Use --no-caffeine to disable.
7
-
8
- For normal usage prefer funnel gateway start.
9
-
10
- examples:
11
- funnel gateway run
12
- funnel gateway run --no-caffeine`
@@ -1,35 +0,0 @@
1
- import { resolve } from "node:path"
2
- import { z } from "zod"
3
- import { factory } from "@/factory"
4
- import { zValidator } from "@/modules/router/validator"
5
- import { help } from "@/routes/gateway/run.help"
6
-
7
- export const gatewayRunHandler = factory.createHandlers(
8
- zValidator(
9
- "query",
10
- z.object({
11
- "no-caffeine": z.string().optional(),
12
- }),
13
- help,
14
- ),
15
- async (c) => {
16
- const query = c.req.valid("query")
17
- const gatewayScript = resolve(import.meta.dir, "../../modules/gateway/daemon.ts")
18
-
19
- const useCaffeinate = query["no-caffeine"] !== "true" && process.platform === "darwin"
20
- const command = useCaffeinate
21
- ? ["caffeinate", "-i", "bun", gatewayScript]
22
- : ["bun", gatewayScript]
23
-
24
- const proc = Bun.spawn(command, {
25
- stdio: ["inherit", "inherit", "inherit"],
26
- })
27
-
28
- process.on("SIGINT", () => proc.kill("SIGINT"))
29
- process.on("SIGTERM", () => proc.kill("SIGTERM"))
30
-
31
- const exitCode = await proc.exited
32
-
33
- process.exit(exitCode)
34
- },
35
- )
@@ -1,15 +0,0 @@
1
- export const help = `funnel gateway start — start the gateway in background
2
-
3
- usage: funnel gateway start [--no-caffeine]
4
-
5
- Daemonized with nohup, so it keeps running after the terminal is closed.
6
- On macOS wraps the process with caffeinate -i by default to prevent idle sleep.
7
- Use --no-caffeine to disable caffeinate.
8
-
9
- port: 9742 (override via FUNNEL_PORT)
10
- pid: ~/.funnel/gateway.pid
11
- log: /tmp/funnel/gateway.log
12
-
13
- examples:
14
- funnel gateway start
15
- funnel gateway start --no-caffeine`
@@ -1,32 +0,0 @@
1
- import { z } from "zod"
2
- import { factory } from "@/factory"
3
- import { zValidator } from "@/modules/router/validator"
4
- import { help } from "@/routes/gateway/start.help"
5
-
6
- export const gatewayStartHandler = factory.createHandlers(
7
- zValidator(
8
- "query",
9
- z.object({
10
- "no-caffeine": z.string().optional(),
11
- }),
12
- help,
13
- ),
14
- async (c) => {
15
- const query = c.req.valid("query")
16
- const funnel = c.var.funnel
17
-
18
- if (funnel.gateway.isRunning()) {
19
- const status = funnel.gateway.getStatus()
20
-
21
- return c.text(`funnel gateway: already running (pid ${status.pid})`)
22
- }
23
-
24
- const started = await funnel.gateway.start({
25
- caffeinate: query["no-caffeine"] !== "true",
26
- })
27
-
28
- return started
29
- ? c.text("funnel gateway: started")
30
- : c.text("funnel gateway: failed to start", 500)
31
- },
32
- )
@@ -1,9 +0,0 @@
1
- export const help = `funnel gateway status — show gateway running status
2
-
3
- usage: funnel gateway status
4
-
5
- When running, prints PID, port, and connected channel count. When not running, exits with 503.
6
-
7
- examples:
8
- funnel gateway status
9
- funnel gateway`
@@ -1,28 +0,0 @@
1
- import { z } from "zod"
2
- import { factory } from "@/factory"
3
- import { zValidator } from "@/modules/router/validator"
4
- import { help } from "@/routes/gateway/status.help"
5
-
6
- export const gatewayStatusHandler = factory.createHandlers(
7
- zValidator("query", z.object({}), help),
8
- async (c) => {
9
- const funnel = c.var.funnel
10
- const status = funnel.gateway.getStatus()
11
-
12
- if (!status.running) {
13
- return c.text("funnel gateway: not running", 503)
14
- }
15
-
16
- const res = await fetch(`http://localhost:${status.port}/health`).catch(() => null)
17
-
18
- if (!res) {
19
- return c.text(`funnel gateway: running (pid ${status.pid}) — health check failed`)
20
- }
21
-
22
- const health = (await res.json()) as Record<string, unknown>
23
-
24
- return c.text(
25
- `funnel gateway: running (pid ${status.pid})\n port: ${status.port}\n clients: ${health.clients ?? 0}`,
26
- )
27
- },
28
- )
@@ -1,8 +0,0 @@
1
- export const help = `funnel gateway stop — stop the gateway
2
-
3
- usage: funnel gateway stop
4
-
5
- Terminates the process whose PID is stored in ~/.funnel/gateway.pid.
6
-
7
- examples:
8
- funnel gateway stop`
@@ -1,21 +0,0 @@
1
- import { z } from "zod"
2
- import { factory } from "@/factory"
3
- import { zValidator } from "@/modules/router/validator"
4
- import { help } from "@/routes/gateway/stop.help"
5
-
6
- export const gatewayStopHandler = factory.createHandlers(
7
- zValidator("query", z.object({}), help),
8
- async (c) => {
9
- const funnel = c.var.funnel
10
-
11
- if (!funnel.gateway.isRunning()) {
12
- return c.text("funnel gateway: no running process")
13
- }
14
-
15
- const stopped = await funnel.gateway.stop()
16
-
17
- return stopped
18
- ? c.text("funnel gateway: stopped")
19
- : c.text("funnel gateway: failed to stop", 500)
20
- },
21
- )
@@ -1,3 +0,0 @@
1
- export const help = `funnel profiles add — add a profile
2
-
3
- usage: funnel profiles add <name> --channel <ch> [--repo <r>] [--sub-agent <s>] [--env-file <f>]`