@interactive-inc/claude-funnel 0.8.1 → 0.10.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 (354) hide show
  1. package/README.md +179 -80
  2. package/dist/bin.js +726 -658
  3. package/dist/connector-adapter-CXB-q_XC.d.ts +11 -0
  4. package/dist/connector-adapter-D5Utumgz.js +4 -0
  5. package/dist/connectors/discord.d.ts +76 -0
  6. package/dist/connectors/discord.js +2 -0
  7. package/dist/connectors/gh.d.ts +38 -0
  8. package/dist/connectors/gh.js +2 -0
  9. package/dist/connectors/schedule.d.ts +53 -0
  10. package/dist/connectors/schedule.js +2 -0
  11. package/dist/connectors/slack.d.ts +34 -0
  12. package/dist/connectors/slack.js +2 -0
  13. package/dist/discord-connector-schema-Dww2I4zH.d.ts +14 -0
  14. package/dist/discord-connector-schema-ygf5Df-2.js +173 -0
  15. package/dist/file-system-Co60LrmR.d.ts +74 -0
  16. package/dist/gateway/daemon.js +233 -183
  17. package/dist/gh-connector-schema-2ml29MBC.js +218 -0
  18. package/dist/gh-connector-schema-BZFAS-p-.d.ts +45 -0
  19. package/dist/index.d.ts +3881 -36
  20. package/dist/index.js +6217 -3483
  21. package/dist/logger-CTlXs7z4.d.ts +33 -0
  22. package/dist/node-logger-DQz_BGOD.js +61 -0
  23. package/dist/schedule-connector-schema-CkuIQ0JQ.js +325 -0
  24. package/dist/slack-connector-schema-Cd22WiHB.js +153 -0
  25. package/dist/slack-event-processor-CS-bAit9.d.ts +43 -0
  26. package/package.json +34 -28
  27. package/dist/cli/factory.d.ts +0 -7
  28. package/dist/cli/router/query-to-cli-args.d.ts +0 -1
  29. package/dist/cli/router/to-request.d.ts +0 -5
  30. package/dist/cli/router/validator.d.ts +0 -5
  31. package/dist/cli/routes/channels.$channel.connectors.$connector.d.ts +0 -42
  32. package/dist/cli/routes/channels.$channel.connectors.$connector.rename.$newName.d.ts +0 -46
  33. package/dist/cli/routes/channels.$channel.connectors.$connector.request.d.ts +0 -54
  34. package/dist/cli/routes/channels.$channel.connectors.$connector.schedules.add.$id.d.ts +0 -66
  35. package/dist/cli/routes/channels.$channel.connectors.$connector.schedules.d.ts +0 -42
  36. package/dist/cli/routes/channels.$channel.connectors.$connector.schedules.remove.$id.d.ts +0 -46
  37. package/dist/cli/routes/channels.$channel.connectors.add.$connector.d.ts +0 -90
  38. package/dist/cli/routes/channels.$channel.connectors.d.ts +0 -38
  39. package/dist/cli/routes/channels.$channel.connectors.remove.$connector.d.ts +0 -42
  40. package/dist/cli/routes/channels.$channel.connectors.set.$connector.d.ts +0 -62
  41. package/dist/cli/routes/channels.$channel.d.ts +0 -38
  42. package/dist/cli/routes/channels.$channel.rename.$newName.d.ts +0 -42
  43. package/dist/cli/routes/channels.$channel.set.delivery.$mode.d.ts +0 -28
  44. package/dist/cli/routes/channels.add.$channel.d.ts +0 -46
  45. package/dist/cli/routes/channels.d.ts +0 -16
  46. package/dist/cli/routes/channels.remove.$channel.d.ts +0 -38
  47. package/dist/cli/routes/claude.d.ts +0 -32
  48. package/dist/cli/routes/gateway.d.ts +0 -20
  49. package/dist/cli/routes/gateway.listeners.d.ts +0 -17
  50. package/dist/cli/routes/gateway.logs.d.ts +0 -24
  51. package/dist/cli/routes/gateway.restart.d.ts +0 -24
  52. package/dist/cli/routes/gateway.run.d.ts +0 -24
  53. package/dist/cli/routes/gateway.start.d.ts +0 -24
  54. package/dist/cli/routes/gateway.status.d.ts +0 -13
  55. package/dist/cli/routes/gateway.stop.d.ts +0 -16
  56. package/dist/cli/routes/index.d.ts +0 -1222
  57. package/dist/cli/routes/profiles.$profile.as-default.d.ts +0 -38
  58. package/dist/cli/routes/profiles.$profile.rename.$newName.d.ts +0 -42
  59. package/dist/cli/routes/profiles.$profile.run.d.ts +0 -46
  60. package/dist/cli/routes/profiles.add.$profile.d.ts +0 -54
  61. package/dist/cli/routes/profiles.d.ts +0 -16
  62. package/dist/cli/routes/profiles.remove.$profile.d.ts +0 -38
  63. package/dist/cli/routes/profiles.set.$profile.d.ts +0 -54
  64. package/dist/cli/routes/status.d.ts +0 -16
  65. package/dist/cli/routes/update.d.ts +0 -16
  66. package/dist/connectors/connector-adapter.d.ts +0 -8
  67. package/dist/connectors/connector-config-schema.d.ts +0 -43
  68. package/dist/connectors/connector-factory.d.ts +0 -32
  69. package/dist/connectors/connector-listener.d.ts +0 -17
  70. package/dist/connectors/discord-adapter.d.ts +0 -14
  71. package/dist/connectors/discord-connector-schema.d.ts +0 -10
  72. package/dist/connectors/discord-event-processor.d.ts +0 -26
  73. package/dist/connectors/discord-listener.d.ts +0 -17
  74. package/dist/connectors/gh-adapter.d.ts +0 -11
  75. package/dist/connectors/gh-connector-schema.d.ts +0 -10
  76. package/dist/connectors/gh-listener.d.ts +0 -26
  77. package/dist/connectors/match-cron.d.ts +0 -1
  78. package/dist/connectors/schedule-connector-schema.d.ts +0 -45
  79. package/dist/connectors/schedule-listener.d.ts +0 -30
  80. package/dist/connectors/schedule-state-store.d.ts +0 -19
  81. package/dist/connectors/slack-adapter.d.ts +0 -15
  82. package/dist/connectors/slack-connector-schema.d.ts +0 -11
  83. package/dist/connectors/slack-event-processor.d.ts +0 -27
  84. package/dist/connectors/slack-listener.d.ts +0 -17
  85. package/dist/engine/channels/channels.d.ts +0 -106
  86. package/dist/engine/claude/claude.d.ts +0 -49
  87. package/dist/engine/claude/gateway-controller.d.ts +0 -6
  88. package/dist/engine/fs/file-system.d.ts +0 -24
  89. package/dist/engine/fs/memory-file-system.d.ts +0 -31
  90. package/dist/engine/fs/node-file-system.d.ts +0 -15
  91. package/dist/engine/http/http-client.d.ts +0 -15
  92. package/dist/engine/http/memory-http-client.d.ts +0 -12
  93. package/dist/engine/http/node-http-client.d.ts +0 -5
  94. package/dist/engine/id/id-generator.d.ts +0 -7
  95. package/dist/engine/id/memory-id-generator.d.ts +0 -11
  96. package/dist/engine/id/node-id-generator.d.ts +0 -4
  97. package/dist/engine/logger/logger.d.ts +0 -11
  98. package/dist/engine/logger/memory-logger.d.ts +0 -14
  99. package/dist/engine/logger/node-logger.d.ts +0 -15
  100. package/dist/engine/logger/noop-logger.d.ts +0 -7
  101. package/dist/engine/mcp/channel-server.d.ts +0 -1
  102. package/dist/engine/mcp/mcp.d.ts +0 -22
  103. package/dist/engine/process/memory-process-runner.d.ts +0 -43
  104. package/dist/engine/process/node-process-runner.d.ts +0 -9
  105. package/dist/engine/process/process-runner.d.ts +0 -29
  106. package/dist/engine/profiles/profile-channel-checker.d.ts +0 -7
  107. package/dist/engine/profiles/profiles.d.ts +0 -31
  108. package/dist/engine/settings/mock-settings-reader.d.ts +0 -9
  109. package/dist/engine/settings/settings-reader.d.ts +0 -5
  110. package/dist/engine/settings/settings-schema.d.ts +0 -132
  111. package/dist/engine/settings/settings-store.d.ts +0 -18
  112. package/dist/engine/time/clock.d.ts +0 -9
  113. package/dist/engine/time/memory-clock.d.ts +0 -12
  114. package/dist/engine/time/node-clock.d.ts +0 -4
  115. package/dist/funnel.d.ts +0 -95
  116. package/dist/gateway/auth-middleware.d.ts +0 -14
  117. package/dist/gateway/broadcaster.d.ts +0 -122
  118. package/dist/gateway/daemon.d.ts +0 -2
  119. package/dist/gateway/factory.d.ts +0 -7
  120. package/dist/gateway/funnel-event-store.d.ts +0 -81
  121. package/dist/gateway/gateway-server.d.ts +0 -94
  122. package/dist/gateway/gateway-token.d.ts +0 -33
  123. package/dist/gateway/gateway.d.ts +0 -58
  124. package/dist/gateway/kill-competing-slack-gateways.d.ts +0 -9
  125. package/dist/gateway/listener-supervisor.d.ts +0 -85
  126. package/dist/gateway/listeners-client.d.ts +0 -53
  127. package/dist/gateway/resolve-daemon-script.d.ts +0 -11
  128. package/dist/gateway/routes/channels.connectors.call.d.ts +0 -41
  129. package/dist/gateway/routes/health.d.ts +0 -17
  130. package/dist/gateway/routes/index.d.ts +0 -209
  131. package/dist/gateway/routes/listeners.list.d.ts +0 -14
  132. package/dist/gateway/routes/listeners.restart.d.ts +0 -34
  133. package/dist/gateway/routes/listeners.start.d.ts +0 -34
  134. package/dist/gateway/routes/listeners.stop.d.ts +0 -34
  135. package/dist/gateway/routes/route-deps.d.ts +0 -10
  136. package/dist/gateway/routes/status.d.ts +0 -30
  137. package/dist/gateway/routes/validator.d.ts +0 -19
  138. package/dist/logger/leuco-human-file-writer.d.ts +0 -33
  139. package/dist/logger/leuco-human-logger.d.ts +0 -46
  140. package/dist/logger/leuco-human-record.d.ts +0 -15
  141. package/dist/logger/leuco-human-stdout-writer.d.ts +0 -20
  142. package/dist/logger/leuco-human-writer.d.ts +0 -13
  143. package/dist/logger/leuco-logger-memory-sink.d.ts +0 -33
  144. package/dist/logger/leuco-logger-record.d.ts +0 -13
  145. package/dist/logger/leuco-logger-sink.d.ts +0 -34
  146. package/dist/logger/leuco-logger-sqlite-sink.d.ts +0 -102
  147. package/dist/logger/leuco-logger.d.ts +0 -56
  148. package/lib/bin.ts +0 -78
  149. package/lib/cli/factory.ts +0 -10
  150. package/lib/cli/router/query-to-cli-args.ts +0 -20
  151. package/lib/cli/router/to-request.ts +0 -112
  152. package/lib/cli/router/validator.ts +0 -27
  153. package/lib/cli/routes/channels.$channel.connectors.$connector.rename.$newName.ts +0 -27
  154. package/lib/cli/routes/channels.$channel.connectors.$connector.request.ts +0 -40
  155. package/lib/cli/routes/channels.$channel.connectors.$connector.schedules.add.$id.ts +0 -41
  156. package/lib/cli/routes/channels.$channel.connectors.$connector.schedules.remove.$id.ts +0 -22
  157. package/lib/cli/routes/channels.$channel.connectors.$connector.schedules.ts +0 -23
  158. package/lib/cli/routes/channels.$channel.connectors.$connector.ts +0 -26
  159. package/lib/cli/routes/channels.$channel.connectors.add.$connector.ts +0 -92
  160. package/lib/cli/routes/channels.$channel.connectors.remove.$connector.ts +0 -22
  161. package/lib/cli/routes/channels.$channel.connectors.set.$connector.ts +0 -63
  162. package/lib/cli/routes/channels.$channel.connectors.ts +0 -26
  163. package/lib/cli/routes/channels.$channel.rename.$newName.ts +0 -22
  164. package/lib/cli/routes/channels.$channel.set.delivery.$mode.ts +0 -34
  165. package/lib/cli/routes/channels.$channel.ts +0 -34
  166. package/lib/cli/routes/channels.add.$channel.ts +0 -33
  167. package/lib/cli/routes/channels.remove.$channel.ts +0 -20
  168. package/lib/cli/routes/channels.ts +0 -39
  169. package/lib/cli/routes/claude.ts +0 -69
  170. package/lib/cli/routes/gateway.listeners.ts +0 -41
  171. package/lib/cli/routes/gateway.logs.ts +0 -123
  172. package/lib/cli/routes/gateway.restart.ts +0 -50
  173. package/lib/cli/routes/gateway.run.ts +0 -41
  174. package/lib/cli/routes/gateway.start.ts +0 -50
  175. package/lib/cli/routes/gateway.status.ts +0 -19
  176. package/lib/cli/routes/gateway.stop.ts +0 -32
  177. package/lib/cli/routes/gateway.ts +0 -55
  178. package/lib/cli/routes/index.ts +0 -202
  179. package/lib/cli/routes/profiles.$profile.as-default.ts +0 -22
  180. package/lib/cli/routes/profiles.$profile.rename.$newName.ts +0 -22
  181. package/lib/cli/routes/profiles.$profile.run.ts +0 -36
  182. package/lib/cli/routes/profiles.add.$profile.ts +0 -46
  183. package/lib/cli/routes/profiles.remove.$profile.ts +0 -20
  184. package/lib/cli/routes/profiles.set.$profile.ts +0 -46
  185. package/lib/cli/routes/profiles.ts +0 -40
  186. package/lib/cli/routes/status.ts +0 -93
  187. package/lib/cli/routes/update.ts +0 -27
  188. package/lib/connectors/connector-adapter.ts +0 -9
  189. package/lib/connectors/connector-config-schema.ts +0 -16
  190. package/lib/connectors/connector-factory.ts +0 -94
  191. package/lib/connectors/connector-listener.ts +0 -20
  192. package/lib/connectors/discord-adapter.ts +0 -51
  193. package/lib/connectors/discord-connector-schema.ts +0 -12
  194. package/lib/connectors/discord-event-processor.ts +0 -48
  195. package/lib/connectors/discord-listener.ts +0 -111
  196. package/lib/connectors/gh-adapter.ts +0 -48
  197. package/lib/connectors/gh-connector-schema.ts +0 -12
  198. package/lib/connectors/gh-listener.ts +0 -137
  199. package/lib/connectors/match-cron.ts +0 -78
  200. package/lib/connectors/schedule-connector-schema.ts +0 -33
  201. package/lib/connectors/schedule-listener.ts +0 -207
  202. package/lib/connectors/schedule-state-store.ts +0 -54
  203. package/lib/connectors/slack-adapter.ts +0 -36
  204. package/lib/connectors/slack-connector-schema.ts +0 -13
  205. package/lib/connectors/slack-event-processor.ts +0 -97
  206. package/lib/connectors/slack-listener.ts +0 -97
  207. package/lib/engine/channels/channels.ts +0 -520
  208. package/lib/engine/claude/claude.ts +0 -199
  209. package/lib/engine/claude/gateway-controller.ts +0 -4
  210. package/lib/engine/fs/file-system.ts +0 -23
  211. package/lib/engine/fs/memory-file-system.ts +0 -102
  212. package/lib/engine/fs/node-file-system.ts +0 -68
  213. package/lib/engine/http/http-client.ts +0 -17
  214. package/lib/engine/http/memory-http-client.ts +0 -36
  215. package/lib/engine/http/node-http-client.ts +0 -23
  216. package/lib/engine/id/id-generator.ts +0 -7
  217. package/lib/engine/id/memory-id-generator.ts +0 -20
  218. package/lib/engine/id/node-id-generator.ts +0 -7
  219. package/lib/engine/logger/logger.ts +0 -11
  220. package/lib/engine/logger/memory-logger.ts +0 -28
  221. package/lib/engine/logger/node-logger.ts +0 -49
  222. package/lib/engine/logger/noop-logger.ts +0 -9
  223. package/lib/engine/mcp/channel-server.ts +0 -204
  224. package/lib/engine/mcp/mcp.ts +0 -126
  225. package/lib/engine/process/memory-process-runner.ts +0 -88
  226. package/lib/engine/process/node-process-runner.ts +0 -91
  227. package/lib/engine/process/process-runner.ts +0 -33
  228. package/lib/engine/profiles/profile-channel-checker.ts +0 -7
  229. package/lib/engine/profiles/profiles.ts +0 -126
  230. package/lib/engine/settings/mock-settings-reader.ts +0 -27
  231. package/lib/engine/settings/settings-reader.ts +0 -6
  232. package/lib/engine/settings/settings-schema.ts +0 -46
  233. package/lib/engine/settings/settings-store.ts +0 -110
  234. package/lib/engine/time/clock.ts +0 -15
  235. package/lib/engine/time/memory-clock.ts +0 -26
  236. package/lib/engine/time/node-clock.ts +0 -7
  237. package/lib/funnel.ts +0 -187
  238. package/lib/gateway/auth-middleware.ts +0 -44
  239. package/lib/gateway/broadcaster.ts +0 -319
  240. package/lib/gateway/daemon.ts +0 -47
  241. package/lib/gateway/factory.ts +0 -10
  242. package/lib/gateway/funnel-event-store.ts +0 -155
  243. package/lib/gateway/gateway-server.ts +0 -414
  244. package/lib/gateway/gateway-token.ts +0 -79
  245. package/lib/gateway/gateway.ts +0 -209
  246. package/lib/gateway/kill-competing-slack-gateways.ts +0 -56
  247. package/lib/gateway/listener-supervisor.ts +0 -339
  248. package/lib/gateway/listeners-client.ts +0 -128
  249. package/lib/gateway/resolve-daemon-script.ts +0 -26
  250. package/lib/gateway/routes/channels.connectors.call.ts +0 -39
  251. package/lib/gateway/routes/health.ts +0 -13
  252. package/lib/gateway/routes/index.ts +0 -24
  253. package/lib/gateway/routes/listeners.list.ts +0 -6
  254. package/lib/gateway/routes/listeners.restart.ts +0 -15
  255. package/lib/gateway/routes/listeners.start.ts +0 -15
  256. package/lib/gateway/routes/listeners.stop.ts +0 -15
  257. package/lib/gateway/routes/route-deps.ts +0 -11
  258. package/lib/gateway/routes/status.ts +0 -15
  259. package/lib/gateway/routes/validator.ts +0 -17
  260. package/lib/index.ts +0 -52
  261. package/lib/logger/leuco-human-file-writer.ts +0 -65
  262. package/lib/logger/leuco-human-logger.ts +0 -98
  263. package/lib/logger/leuco-human-record.ts +0 -16
  264. package/lib/logger/leuco-human-stdout-writer.ts +0 -26
  265. package/lib/logger/leuco-human-writer.ts +0 -14
  266. package/lib/logger/leuco-logger-memory-sink.ts +0 -67
  267. package/lib/logger/leuco-logger-record.ts +0 -13
  268. package/lib/logger/leuco-logger-sink.ts +0 -33
  269. package/lib/logger/leuco-logger-sqlite-sink.ts +0 -355
  270. package/lib/logger/leuco-logger.ts +0 -135
  271. package/lib/tui/app.tsx +0 -357
  272. package/lib/tui/components/add-row.tsx +0 -18
  273. package/lib/tui/components/brand.tsx +0 -27
  274. package/lib/tui/components/card.tsx +0 -44
  275. package/lib/tui/components/detail-bar.tsx +0 -46
  276. package/lib/tui/components/editable-field.tsx +0 -33
  277. package/lib/tui/components/empty-state.tsx +0 -11
  278. package/lib/tui/components/gateway-status.tsx +0 -66
  279. package/lib/tui/components/keymap.tsx +0 -29
  280. package/lib/tui/components/menu-item.tsx +0 -73
  281. package/lib/tui/components/menu.tsx +0 -26
  282. package/lib/tui/components/panel-header.tsx +0 -22
  283. package/lib/tui/components/readonly-field.tsx +0 -18
  284. package/lib/tui/components/section-header.tsx +0 -25
  285. package/lib/tui/components/selection-accent.tsx +0 -32
  286. package/lib/tui/components/session-item.tsx +0 -33
  287. package/lib/tui/components/session-list.tsx +0 -33
  288. package/lib/tui/components/ui/hascii/accordion-item.tsx +0 -88
  289. package/lib/tui/components/ui/hascii/accordion.tsx +0 -96
  290. package/lib/tui/components/ui/hascii/alert-dialog.tsx +0 -43
  291. package/lib/tui/components/ui/hascii/badge.tsx +0 -51
  292. package/lib/tui/components/ui/hascii/breadcrumb.tsx +0 -58
  293. package/lib/tui/components/ui/hascii/button.tsx +0 -194
  294. package/lib/tui/components/ui/hascii/card-content.tsx +0 -14
  295. package/lib/tui/components/ui/hascii/card-description.tsx +0 -13
  296. package/lib/tui/components/ui/hascii/card-footer.tsx +0 -14
  297. package/lib/tui/components/ui/hascii/card-header.tsx +0 -14
  298. package/lib/tui/components/ui/hascii/card-title.tsx +0 -13
  299. package/lib/tui/components/ui/hascii/card.tsx +0 -27
  300. package/lib/tui/components/ui/hascii/checkbox.tsx +0 -65
  301. package/lib/tui/components/ui/hascii/command.tsx +0 -159
  302. package/lib/tui/components/ui/hascii/dialog-content.tsx +0 -14
  303. package/lib/tui/components/ui/hascii/dialog-description.tsx +0 -13
  304. package/lib/tui/components/ui/hascii/dialog-footer.tsx +0 -14
  305. package/lib/tui/components/ui/hascii/dialog-header.tsx +0 -14
  306. package/lib/tui/components/ui/hascii/dialog-title.tsx +0 -13
  307. package/lib/tui/components/ui/hascii/dialog.tsx +0 -27
  308. package/lib/tui/components/ui/hascii/file-tree.tsx +0 -142
  309. package/lib/tui/components/ui/hascii/focus-group.tsx +0 -62
  310. package/lib/tui/components/ui/hascii/form-item.tsx +0 -43
  311. package/lib/tui/components/ui/hascii/input-otp.tsx +0 -86
  312. package/lib/tui/components/ui/hascii/input.tsx +0 -130
  313. package/lib/tui/components/ui/hascii/pagination.tsx +0 -105
  314. package/lib/tui/components/ui/hascii/progress.tsx +0 -28
  315. package/lib/tui/components/ui/hascii/select.tsx +0 -131
  316. package/lib/tui/components/ui/hascii/separator.tsx +0 -35
  317. package/lib/tui/components/ui/hascii/sidebar-content.tsx +0 -23
  318. package/lib/tui/components/ui/hascii/sidebar-header.tsx +0 -14
  319. package/lib/tui/components/ui/hascii/sidebar-menu-item.tsx +0 -67
  320. package/lib/tui/components/ui/hascii/sidebar.tsx +0 -24
  321. package/lib/tui/components/ui/hascii/skeleton.tsx +0 -60
  322. package/lib/tui/components/ui/hascii/slider.tsx +0 -91
  323. package/lib/tui/components/ui/hascii/snackbar.tsx +0 -75
  324. package/lib/tui/components/ui/hascii/sparkline.tsx +0 -53
  325. package/lib/tui/components/ui/hascii/spinner.tsx +0 -47
  326. package/lib/tui/components/ui/hascii/stepper.tsx +0 -54
  327. package/lib/tui/components/ui/hascii/switch.tsx +0 -66
  328. package/lib/tui/components/ui/hascii/table.tsx +0 -95
  329. package/lib/tui/components/ui/hascii/tabs.tsx +0 -59
  330. package/lib/tui/components/ui/hascii/toggle-group-item.tsx +0 -45
  331. package/lib/tui/components/ui/hascii/toggle-group.tsx +0 -99
  332. package/lib/tui/components/ui/hascii/tree.tsx +0 -104
  333. package/lib/tui/components/view-shell.tsx +0 -44
  334. package/lib/tui/filter-input.tsx +0 -33
  335. package/lib/tui/hooks/hascii/use-pressable.ts +0 -54
  336. package/lib/tui/parse-comma-list.ts +0 -14
  337. package/lib/tui/profile-launcher.tsx +0 -61
  338. package/lib/tui/scrollbar-options.ts +0 -19
  339. package/lib/tui/sidebar.tsx +0 -50
  340. package/lib/tui/theme.ts +0 -40
  341. package/lib/tui/tui.tsx +0 -20
  342. package/lib/tui/types.ts +0 -38
  343. package/lib/tui/unique-name.ts +0 -18
  344. package/lib/tui/use-event-stream.ts +0 -133
  345. package/lib/tui/use-snapshot.ts +0 -99
  346. package/lib/tui/utils/hascii/form-item-context.tsx +0 -23
  347. package/lib/tui/utils/hascii/input-focus-context.tsx +0 -31
  348. package/lib/tui/utils/hascii/theme-context.tsx +0 -26
  349. package/lib/tui/utils/hascii/theme.ts +0 -176
  350. package/lib/tui/views/channels-view.tsx +0 -108
  351. package/lib/tui/views/connectors-view.tsx +0 -164
  352. package/lib/tui/views/events-view.tsx +0 -160
  353. package/lib/tui/views/listeners-view.tsx +0 -80
  354. package/lib/tui/views/profiles-view.tsx +0 -152
@@ -1,199 +0,0 @@
1
- import { join } from "node:path"
2
- import type { FunnelChannels } from "@/engine/channels/channels"
3
- import type { GatewayController } from "@/engine/claude/gateway-controller"
4
- import { FunnelFileSystem } from "@/engine/fs/file-system"
5
- import { NodeFunnelFileSystem } from "@/engine/fs/node-file-system"
6
- import { FunnelLogger } from "@/engine/logger/logger"
7
- import { NodeFunnelLogger } from "@/engine/logger/node-logger"
8
- import type { FunnelMcp } from "@/engine/mcp/mcp"
9
- import { FunnelProcessRunner } from "@/engine/process/process-runner"
10
- import { NodeFunnelProcessRunner } from "@/engine/process/node-process-runner"
11
- import { FUNNEL_DIR } from "@/engine/settings/settings-store"
12
-
13
- export type LaunchOptions = {
14
- channel: string
15
- cwd?: string
16
- subAgent?: string
17
- userArgs?: string[]
18
- profileName?: string
19
- }
20
-
21
- type Deps = {
22
- channels: FunnelChannels
23
- mcp: FunnelMcp
24
- gateway: GatewayController
25
- process?: FunnelProcessRunner
26
- fs?: FunnelFileSystem
27
- logger?: FunnelLogger
28
- dir?: string
29
- }
30
-
31
- const defaultProcess = new NodeFunnelProcessRunner()
32
- const defaultFs = new NodeFunnelFileSystem()
33
- const defaultLogger = new NodeFunnelLogger()
34
-
35
- /**
36
- * Launches Claude Code with funnel pre-wired: ensures the gateway is running,
37
- * installs the funnel MCP into the target repo's `.mcp.json` if missing,
38
- * injects `FUNNEL_CHANNEL_ID` into the child env, and writes a per-profile
39
- * PID file to enforce singleton launches.
40
- */
41
- export class FunnelClaude {
42
- private readonly channels: FunnelChannels
43
- private readonly mcp: FunnelMcp
44
- private readonly gateway: GatewayController
45
- private readonly process: FunnelProcessRunner
46
- private readonly fs: FunnelFileSystem
47
- private readonly logger: FunnelLogger
48
- private readonly pidDir: string
49
-
50
- constructor(deps: Deps) {
51
- this.channels = deps.channels
52
- this.mcp = deps.mcp
53
- this.gateway = deps.gateway
54
- this.process = deps.process ?? defaultProcess
55
- this.fs = deps.fs ?? defaultFs
56
- this.logger = deps.logger ?? defaultLogger
57
- this.pidDir = join(deps.dir ?? FUNNEL_DIR, "claude")
58
- Object.freeze(this)
59
- }
60
-
61
- async launch(options: LaunchOptions): Promise<number> {
62
- const channel = this.channels.get(options.channel) ?? this.channels.getById(options.channel)
63
-
64
- if (!channel) {
65
- throw new Error(`channel "${options.channel}" not found`)
66
- }
67
-
68
- if (options.profileName && this.isRunning(options.profileName)) {
69
- throw new Error(`profile "${options.profileName}" is already running`)
70
- }
71
-
72
- const cwd = options.cwd ?? globalThis.process.cwd()
73
-
74
- if (!this.mcp.findInstalledName(cwd)) {
75
- this.mcp.install(cwd)
76
-
77
- this.logger.info(`added funnel MCP to .mcp.json`, { cwd })
78
- }
79
-
80
- if (!this.gateway.isRunning()) {
81
- this.logger.info(`starting gateway automatically`)
82
- await this.gateway.start()
83
- }
84
-
85
- if (options.profileName) {
86
- this.writePidFile(options.profileName)
87
- this.installCleanup(options.profileName)
88
- }
89
-
90
- const claudeArgs = this.buildArgs(options, cwd)
91
- const env = this.buildEnv(channel.id)
92
-
93
- this.logger.info(`claude launch`, {
94
- channel: options.channel,
95
- channelId: channel.id,
96
- subAgent: options.subAgent,
97
- cwd,
98
- })
99
-
100
- try {
101
- return await this.process.attach(["claude", ...claudeArgs], { cwd, env })
102
- } finally {
103
- if (options.profileName) this.removePidFile(options.profileName)
104
- }
105
- }
106
-
107
- isRunning(profileName: string): boolean {
108
- const pid = this.readPid(profileName)
109
-
110
- if (!pid) return false
111
-
112
- return this.isProcessAlive(pid)
113
- }
114
-
115
- private pidPath(profileName: string): string {
116
- return join(this.pidDir, `${profileName}.pid`)
117
- }
118
-
119
- private readPid(profileName: string): number | null {
120
- const path = this.pidPath(profileName)
121
-
122
- if (!this.fs.existsSync(path)) return null
123
-
124
- try {
125
- const content = this.fs.readFileSync(path).trim()
126
- const pid = Number(content)
127
-
128
- if (!pid || pid <= 0) return null
129
-
130
- return pid
131
- } catch {
132
- return null
133
- }
134
- }
135
-
136
- private writePidFile(profileName: string): void {
137
- this.fs.mkdirSync(this.pidDir, { recursive: true })
138
- this.fs.writeFileSync(this.pidPath(profileName), String(globalThis.process.pid))
139
- }
140
-
141
- private removePidFile(profileName: string): void {
142
- const path = this.pidPath(profileName)
143
-
144
- if (this.fs.existsSync(path)) this.fs.unlink(path)
145
- }
146
-
147
- private installCleanup(profileName: string): void {
148
- // Default Bun behavior on SIGINT/SIGTERM is process.exit(130/143), which
149
- // fires the "exit" event. Hooking only "exit" keeps the PID file cleanup
150
- // running while letting the signal terminate the process normally —
151
- // adding our own SIGINT handler would suppress the default exit and leave
152
- // funnel hanging until claude responds.
153
- globalThis.process.once("exit", () => this.removePidFile(profileName))
154
- }
155
-
156
- private isProcessAlive(pid: number): boolean {
157
- const result = this.process.runSync(["ps", "-p", String(pid), "-o", "state="])
158
-
159
- if (result.exitCode !== 0) return false
160
-
161
- const state = result.stdout.trim()
162
-
163
- if (!state) return false
164
-
165
- return !state.startsWith("Z")
166
- }
167
-
168
- private buildArgs(options: LaunchOptions, cwd: string): string[] {
169
- const result = [...(options.userArgs ?? [])]
170
-
171
- const mcpName = this.mcp.findInstalledName(cwd)
172
-
173
- if (
174
- mcpName &&
175
- !result.includes("--dangerously-load-development-channels") &&
176
- !result.includes("--channels")
177
- ) {
178
- result.push("--dangerously-load-development-channels", `server:${mcpName}`)
179
- }
180
-
181
- if (!result.includes("--agent") && options.subAgent) {
182
- result.push("--agent", options.subAgent)
183
- }
184
-
185
- return result
186
- }
187
-
188
- private buildEnv(channelId: string): Record<string, string> {
189
- const env: Record<string, string> = {}
190
-
191
- for (const [key, value] of Object.entries(globalThis.process.env)) {
192
- if (typeof value === "string") env[key] = value
193
- }
194
-
195
- env.FUNNEL_CHANNEL_ID = channelId
196
-
197
- return env
198
- }
199
- }
@@ -1,4 +0,0 @@
1
- export type GatewayController = {
2
- isRunning(): boolean
3
- start(options?: { caffeinate?: boolean }): Promise<boolean>
4
- }
@@ -1,23 +0,0 @@
1
- export type FileStat = {
2
- mtimeMs: number
3
- /** POSIX mode bits (e.g. 0o600). `null` when the underlying FS does not expose mode. */
4
- mode: number | null
5
- }
6
-
7
- /**
8
- * Filesystem boundary used everywhere funnel reads or writes.
9
- * Default is NodeFunnelFileSystem (real `node:fs`); MemoryFunnelFileSystem
10
- * provides a sandbox for tests and embedded use.
11
- */
12
- export abstract class FunnelFileSystem {
13
- abstract existsSync(path: string): boolean
14
- abstract readFileSync(path: string): string
15
- abstract writeFileSync(path: string, data: string): void
16
- /** Write `data` and ensure the resulting file is owner-only (0600). Use for tokens and any file that may contain secrets. */
17
- abstract writeSecretFileSync(path: string, data: string): void
18
- abstract appendFileSync(path: string, data: string): void
19
- abstract unlink(path: string): void
20
- abstract mkdirSync(path: string, options?: { recursive?: boolean }): void
21
- abstract readdirSync(path: string): string[]
22
- abstract statSync(path: string): FileStat
23
- }
@@ -1,102 +0,0 @@
1
- import { type FileStat, FunnelFileSystem } from "@/engine/fs/file-system"
2
-
3
- type Props = {
4
- dirs?: string[]
5
- files?: Record<string, string>
6
- mtimes?: Record<string, number>
7
- modes?: Record<string, number>
8
- now?: () => number
9
- }
10
-
11
- const SECRET_MODE = 0o600
12
-
13
- export class MemoryFunnelFileSystem extends FunnelFileSystem {
14
- private readonly dirs: Set<string>
15
- private readonly files: Map<string, string>
16
- private readonly mtimes: Map<string, number>
17
- private readonly modes: Map<string, number>
18
- private readonly now: () => number
19
-
20
- constructor(props: Props = {}) {
21
- super()
22
- this.dirs = new Set(props.dirs ?? [])
23
- this.files = new Map(Object.entries(props.files ?? {}))
24
- this.mtimes = new Map(Object.entries(props.mtimes ?? {}))
25
- this.modes = new Map(Object.entries(props.modes ?? {}))
26
- this.now = props.now ?? (() => Date.now())
27
- }
28
-
29
- existsSync(path: string): boolean {
30
- return this.dirs.has(path) || this.files.has(path)
31
- }
32
-
33
- readFileSync(path: string): string {
34
- return this.files.get(path) ?? ""
35
- }
36
-
37
- writeFileSync(path: string, data: string): void {
38
- this.files.set(path, data)
39
- this.touch(path)
40
- }
41
-
42
- writeSecretFileSync(path: string, data: string): void {
43
- this.files.set(path, data)
44
- this.modes.set(path, SECRET_MODE)
45
- this.touch(path)
46
- }
47
-
48
- appendFileSync(path: string, data: string): void {
49
- const prev = this.files.get(path) ?? ""
50
- this.files.set(path, prev + data)
51
- this.touch(path)
52
- }
53
-
54
- unlink(path: string): void {
55
- this.files.delete(path)
56
- this.mtimes.delete(path)
57
- this.modes.delete(path)
58
- }
59
-
60
- mkdirSync(path: string, options?: { recursive?: boolean }): void {
61
- void options
62
- this.dirs.add(path)
63
- }
64
-
65
- readdirSync(path: string): string[] {
66
- const prefix = path.endsWith("/") ? path : `${path}/`
67
- const names: string[] = []
68
-
69
- for (const file of this.files.keys()) {
70
- if (!file.startsWith(prefix)) continue
71
-
72
- const rest = file.slice(prefix.length)
73
-
74
- if (!rest.includes("/")) names.push(rest)
75
- }
76
-
77
- return names
78
- }
79
-
80
- statSync(path: string): FileStat {
81
- const mtimeMs = this.mtimes.get(path)
82
-
83
- if (mtimeMs === undefined) {
84
- throw new Error(`not found: ${path}`)
85
- }
86
-
87
- return { mtimeMs, mode: this.modes.get(path) ?? null }
88
- }
89
-
90
- setMtime(path: string, mtimeMs: number): void {
91
- this.mtimes.set(path, mtimeMs)
92
- }
93
-
94
- setMode(path: string, mode: number): void {
95
- this.modes.set(path, mode)
96
- }
97
-
98
- private touch(path: string): void {
99
- if (!this.mtimes.has(path)) this.mtimes.set(path, this.now())
100
- else this.mtimes.set(path, this.now())
101
- }
102
- }
@@ -1,68 +0,0 @@
1
- import {
2
- appendFileSync,
3
- chmodSync,
4
- existsSync,
5
- mkdirSync,
6
- readdirSync,
7
- readFileSync,
8
- statSync,
9
- unlinkSync,
10
- writeFileSync,
11
- } from "node:fs"
12
- import { type FileStat, FunnelFileSystem } from "@/engine/fs/file-system"
13
-
14
- const SECRET_MODE = 0o600
15
-
16
- export class NodeFunnelFileSystem extends FunnelFileSystem {
17
- constructor() {
18
- super()
19
- Object.freeze(this)
20
- }
21
-
22
- existsSync(path: string): boolean {
23
- return existsSync(path)
24
- }
25
-
26
- readFileSync(path: string): string {
27
- return readFileSync(path, "utf-8")
28
- }
29
-
30
- writeFileSync(path: string, data: string): void {
31
- writeFileSync(path, data)
32
- }
33
-
34
- writeSecretFileSync(path: string, data: string): void {
35
- writeFileSync(path, data, { mode: SECRET_MODE })
36
- try {
37
- chmodSync(path, SECRET_MODE)
38
- } catch {
39
- // ignore — best-effort tightening for files that already existed with looser perms
40
- }
41
- }
42
-
43
- appendFileSync(path: string, data: string): void {
44
- appendFileSync(path, data)
45
- }
46
-
47
- unlink(path: string): void {
48
- try {
49
- unlinkSync(path)
50
- } catch {
51
- // ignore
52
- }
53
- }
54
-
55
- mkdirSync(path: string, options?: { recursive?: boolean }): void {
56
- mkdirSync(path, { recursive: options?.recursive ?? false })
57
- }
58
-
59
- readdirSync(path: string): string[] {
60
- return readdirSync(path)
61
- }
62
-
63
- statSync(path: string): FileStat {
64
- const stat = statSync(path)
65
-
66
- return { mtimeMs: stat.mtimeMs, mode: stat.mode & 0o777 }
67
- }
68
- }
@@ -1,17 +0,0 @@
1
- export type HttpRequest = {
2
- method: string
3
- url: string
4
- headers?: Record<string, string>
5
- body?: string
6
- }
7
-
8
- export type HttpResponse = {
9
- status: number
10
- ok: boolean
11
- text(): Promise<string>
12
- json(): Promise<unknown>
13
- }
14
-
15
- export abstract class FunnelHttpClient {
16
- abstract fetch(request: HttpRequest): Promise<HttpResponse>
17
- }
@@ -1,36 +0,0 @@
1
- import { FunnelHttpClient, type HttpRequest, type HttpResponse } from "@/engine/http/http-client"
2
-
3
- export type MemoryHttpResponse = {
4
- status?: number
5
- body?: string
6
- }
7
-
8
- export type MemoryHttpHandler = (
9
- request: HttpRequest,
10
- ) => MemoryHttpResponse | Promise<MemoryHttpResponse>
11
-
12
- export class MemoryFunnelHttpClient extends FunnelHttpClient {
13
- readonly calls: HttpRequest[] = []
14
- private handler: MemoryHttpHandler = () => ({ status: 200, body: "" })
15
-
16
- on(handler: MemoryHttpHandler): this {
17
- this.handler = handler
18
-
19
- return this
20
- }
21
-
22
- async fetch(request: HttpRequest): Promise<HttpResponse> {
23
- this.calls.push(request)
24
-
25
- const response = await this.handler(request)
26
- const status = response.status ?? 200
27
- const body = response.body ?? ""
28
-
29
- return {
30
- status,
31
- ok: status >= 200 && status < 300,
32
- text: async () => body,
33
- json: async () => JSON.parse(body),
34
- }
35
- }
36
- }
@@ -1,23 +0,0 @@
1
- import { FunnelHttpClient, type HttpRequest, type HttpResponse } from "@/engine/http/http-client"
2
-
3
- export class NodeFunnelHttpClient extends FunnelHttpClient {
4
- constructor() {
5
- super()
6
- Object.freeze(this)
7
- }
8
-
9
- async fetch(request: HttpRequest): Promise<HttpResponse> {
10
- const res = await globalThis.fetch(request.url, {
11
- method: request.method,
12
- headers: request.headers,
13
- body: request.body,
14
- })
15
-
16
- return {
17
- status: res.status,
18
- ok: res.ok,
19
- text: () => res.text(),
20
- json: () => res.json(),
21
- }
22
- }
23
- }
@@ -1,7 +0,0 @@
1
- /**
2
- * ID generator boundary. Default NodeFunnelIdGenerator wraps `crypto.randomUUID()`;
3
- * MemoryFunnelIdGenerator emits `<prefix>-1, <prefix>-2, ...` for deterministic tests.
4
- */
5
- export abstract class FunnelIdGenerator {
6
- abstract generate(): string
7
- }
@@ -1,20 +0,0 @@
1
- import { FunnelIdGenerator } from "@/engine/id/id-generator"
2
-
3
- type Props = {
4
- prefix?: string
5
- }
6
-
7
- export class MemoryFunnelIdGenerator extends FunnelIdGenerator {
8
- private counter = 0
9
- private readonly prefix: string
10
-
11
- constructor(props: Props = {}) {
12
- super()
13
- this.prefix = props.prefix ?? "id"
14
- }
15
-
16
- generate(): string {
17
- this.counter++
18
- return `${this.prefix}-${this.counter}`
19
- }
20
- }
@@ -1,7 +0,0 @@
1
- import { FunnelIdGenerator } from "@/engine/id/id-generator"
2
-
3
- export class NodeFunnelIdGenerator extends FunnelIdGenerator {
4
- generate(): string {
5
- return crypto.randomUUID()
6
- }
7
- }
@@ -1,11 +0,0 @@
1
- /**
2
- * Structured logger with three levels and an optional log-file path.
3
- * Defaults to NodeFunnelLogger (appends to /tmp/funnel/funnel.log);
4
- * MemoryFunnelLogger captures entries in memory and NoopFunnelLogger silences output.
5
- */
6
- export abstract class FunnelLogger {
7
- abstract info(message: string, meta?: Record<string, unknown>): void
8
- abstract warn(message: string, meta?: Record<string, unknown>): void
9
- abstract error(message: string, meta?: Record<string, unknown>): void
10
- abstract readonly file: string | null
11
- }
@@ -1,28 +0,0 @@
1
- import { FunnelLogger } from "@/engine/logger/logger"
2
-
3
- export type LogEntry = {
4
- level: "info" | "warn" | "error"
5
- message: string
6
- meta?: Record<string, unknown>
7
- }
8
-
9
- export class MemoryFunnelLogger extends FunnelLogger {
10
- readonly file = null
11
- readonly entries: LogEntry[] = []
12
-
13
- info(message: string, meta?: Record<string, unknown>): void {
14
- this.entries.push({ level: "info", message, meta })
15
- }
16
-
17
- warn(message: string, meta?: Record<string, unknown>): void {
18
- this.entries.push({ level: "warn", message, meta })
19
- }
20
-
21
- error(message: string, meta?: Record<string, unknown>): void {
22
- this.entries.push({ level: "error", message, meta })
23
- }
24
-
25
- clear(): void {
26
- this.entries.length = 0
27
- }
28
- }
@@ -1,49 +0,0 @@
1
- import { appendFileSync, mkdirSync } from "node:fs"
2
- import { dirname, join } from "node:path"
3
- import { FunnelLogger } from "@/engine/logger/logger"
4
-
5
- const DEFAULT_LOG_FILE = join("/tmp/funnel", "funnel.log")
6
-
7
- type Level = "info" | "warn" | "error"
8
-
9
- type Props = {
10
- file?: string
11
- now?: () => Date
12
- }
13
-
14
- export class NodeFunnelLogger extends FunnelLogger {
15
- readonly file: string
16
- private readonly now: () => Date
17
-
18
- constructor(props: Props = {}) {
19
- super()
20
- this.file = props.file ?? DEFAULT_LOG_FILE
21
- this.now = props.now ?? (() => new Date())
22
- Object.freeze(this)
23
- }
24
-
25
- info(message: string, meta?: Record<string, unknown>): void {
26
- this.write("info", message, meta)
27
- }
28
-
29
- warn(message: string, meta?: Record<string, unknown>): void {
30
- this.write("warn", message, meta)
31
- }
32
-
33
- error(message: string, meta?: Record<string, unknown>): void {
34
- this.write("error", message, meta)
35
- }
36
-
37
- private write(level: Level, message: string, meta?: Record<string, unknown>): void {
38
- mkdirSync(dirname(this.file), { recursive: true })
39
-
40
- const entry = {
41
- time: this.now().toISOString(),
42
- level,
43
- message,
44
- ...(meta ? { meta } : {}),
45
- }
46
-
47
- appendFileSync(this.file, `${JSON.stringify(entry)}\n`)
48
- }
49
- }
@@ -1,9 +0,0 @@
1
- import { FunnelLogger } from "@/engine/logger/logger"
2
-
3
- export class NoopFunnelLogger extends FunnelLogger {
4
- readonly file = null
5
-
6
- info(): void {}
7
- warn(): void {}
8
- error(): void {}
9
- }