@kilnai/runtime 0.1.15 → 0.9.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 (249) hide show
  1. package/README.md +7 -3
  2. package/dist/channels/email-api.d.ts +29 -0
  3. package/dist/channels/email-api.d.ts.map +1 -0
  4. package/dist/channels/email-api.js +133 -0
  5. package/dist/channels/email-api.js.map +1 -0
  6. package/dist/channels/email-channel.d.ts +26 -0
  7. package/dist/channels/email-channel.d.ts.map +1 -0
  8. package/dist/channels/email-channel.js +59 -0
  9. package/dist/channels/email-channel.js.map +1 -0
  10. package/dist/channels/email-template.d.ts +10 -0
  11. package/dist/channels/email-template.d.ts.map +1 -0
  12. package/dist/channels/email-template.js +63 -0
  13. package/dist/channels/email-template.js.map +1 -0
  14. package/dist/channels/instagram-api.d.ts +29 -0
  15. package/dist/channels/instagram-api.d.ts.map +1 -0
  16. package/dist/channels/instagram-api.js +75 -0
  17. package/dist/channels/instagram-api.js.map +1 -0
  18. package/dist/channels/instagram-channel.d.ts +24 -0
  19. package/dist/channels/instagram-channel.d.ts.map +1 -0
  20. package/dist/channels/instagram-channel.js +55 -0
  21. package/dist/channels/instagram-channel.js.map +1 -0
  22. package/dist/channels/message-formatter.d.ts +17 -0
  23. package/dist/channels/message-formatter.d.ts.map +1 -1
  24. package/dist/channels/message-formatter.js +27 -0
  25. package/dist/channels/message-formatter.js.map +1 -1
  26. package/dist/channels/messenger-api.d.ts +27 -0
  27. package/dist/channels/messenger-api.d.ts.map +1 -0
  28. package/dist/channels/messenger-api.js +75 -0
  29. package/dist/channels/messenger-api.js.map +1 -0
  30. package/dist/channels/messenger-channel.d.ts +23 -0
  31. package/dist/channels/messenger-channel.d.ts.map +1 -0
  32. package/dist/channels/messenger-channel.js +55 -0
  33. package/dist/channels/messenger-channel.js.map +1 -0
  34. package/dist/channels/web-channel.d.ts +2 -0
  35. package/dist/channels/web-channel.d.ts.map +1 -1
  36. package/dist/channels/web-channel.js +9 -0
  37. package/dist/channels/web-channel.js.map +1 -1
  38. package/dist/enrichment/enrichment-runner.d.ts +17 -0
  39. package/dist/enrichment/enrichment-runner.d.ts.map +1 -0
  40. package/dist/enrichment/enrichment-runner.js +45 -0
  41. package/dist/enrichment/enrichment-runner.js.map +1 -0
  42. package/dist/enrichment/sqlite-enrichment-store.d.ts +14 -0
  43. package/dist/enrichment/sqlite-enrichment-store.d.ts.map +1 -0
  44. package/dist/enrichment/sqlite-enrichment-store.js +69 -0
  45. package/dist/enrichment/sqlite-enrichment-store.js.map +1 -0
  46. package/dist/gateway/audio-preprocessor.d.ts +11 -0
  47. package/dist/gateway/audio-preprocessor.d.ts.map +1 -0
  48. package/dist/gateway/audio-preprocessor.js +76 -0
  49. package/dist/gateway/audio-preprocessor.js.map +1 -0
  50. package/dist/gateway/auth-middleware.d.ts.map +1 -1
  51. package/dist/gateway/auth-middleware.js +10 -2
  52. package/dist/gateway/auth-middleware.js.map +1 -1
  53. package/dist/gateway/contact-memory-admin-routes.d.ts +9 -0
  54. package/dist/gateway/contact-memory-admin-routes.d.ts.map +1 -0
  55. package/dist/gateway/contact-memory-admin-routes.js +42 -0
  56. package/dist/gateway/contact-memory-admin-routes.js.map +1 -0
  57. package/dist/gateway/context-formatter.d.ts +5 -0
  58. package/dist/gateway/context-formatter.d.ts.map +1 -0
  59. package/dist/gateway/context-formatter.js +16 -0
  60. package/dist/gateway/context-formatter.js.map +1 -0
  61. package/dist/gateway/conversation-event-emitter.d.ts +4 -1
  62. package/dist/gateway/conversation-event-emitter.d.ts.map +1 -1
  63. package/dist/gateway/conversation-event-emitter.js +44 -13
  64. package/dist/gateway/conversation-event-emitter.js.map +1 -1
  65. package/dist/gateway/dev-routes.d.ts +1 -1
  66. package/dist/gateway/dev-routes.d.ts.map +1 -1
  67. package/dist/gateway/dev-routes.js +2 -2
  68. package/dist/gateway/dev-routes.js.map +1 -1
  69. package/dist/gateway/email-loop-guard.d.ts +10 -0
  70. package/dist/gateway/email-loop-guard.d.ts.map +1 -0
  71. package/dist/gateway/email-loop-guard.js +39 -0
  72. package/dist/gateway/email-loop-guard.js.map +1 -0
  73. package/dist/gateway/email-thread-store.d.ts +24 -0
  74. package/dist/gateway/email-thread-store.d.ts.map +1 -0
  75. package/dist/gateway/email-thread-store.js +34 -0
  76. package/dist/gateway/email-thread-store.js.map +1 -0
  77. package/dist/gateway/email-webhook-routes.d.ts +32 -0
  78. package/dist/gateway/email-webhook-routes.d.ts.map +1 -0
  79. package/dist/gateway/email-webhook-routes.js +411 -0
  80. package/dist/gateway/email-webhook-routes.js.map +1 -0
  81. package/dist/gateway/enrichment-admin-routes.d.ts +9 -0
  82. package/dist/gateway/enrichment-admin-routes.d.ts.map +1 -0
  83. package/dist/gateway/enrichment-admin-routes.js +41 -0
  84. package/dist/gateway/enrichment-admin-routes.js.map +1 -0
  85. package/dist/gateway/gateway-routes.d.ts +17 -1
  86. package/dist/gateway/gateway-routes.d.ts.map +1 -1
  87. package/dist/gateway/gateway-routes.js +55 -1
  88. package/dist/gateway/gateway-routes.js.map +1 -1
  89. package/dist/gateway/gateway-server.d.ts.map +1 -1
  90. package/dist/gateway/gateway-server.js +250 -14
  91. package/dist/gateway/gateway-server.js.map +1 -1
  92. package/dist/gateway/handoff-routes.d.ts +15 -0
  93. package/dist/gateway/handoff-routes.d.ts.map +1 -0
  94. package/dist/gateway/handoff-routes.js +253 -0
  95. package/dist/gateway/handoff-routes.js.map +1 -0
  96. package/dist/gateway/instagram-webhook-routes.d.ts +30 -0
  97. package/dist/gateway/instagram-webhook-routes.d.ts.map +1 -0
  98. package/dist/gateway/instagram-webhook-routes.js +394 -0
  99. package/dist/gateway/instagram-webhook-routes.js.map +1 -0
  100. package/dist/gateway/knowledge-admin-routes.d.ts +9 -0
  101. package/dist/gateway/knowledge-admin-routes.d.ts.map +1 -0
  102. package/dist/gateway/knowledge-admin-routes.js +84 -0
  103. package/dist/gateway/knowledge-admin-routes.js.map +1 -0
  104. package/dist/gateway/knowledge-factory.d.ts +19 -0
  105. package/dist/gateway/knowledge-factory.d.ts.map +1 -0
  106. package/dist/gateway/knowledge-factory.js +122 -0
  107. package/dist/gateway/knowledge-factory.js.map +1 -0
  108. package/dist/gateway/message-pipeline.d.ts +69 -0
  109. package/dist/gateway/message-pipeline.d.ts.map +1 -0
  110. package/dist/gateway/message-pipeline.js +185 -0
  111. package/dist/gateway/message-pipeline.js.map +1 -0
  112. package/dist/gateway/messenger-webhook-routes.d.ts +30 -0
  113. package/dist/gateway/messenger-webhook-routes.d.ts.map +1 -0
  114. package/dist/gateway/messenger-webhook-routes.js +394 -0
  115. package/dist/gateway/messenger-webhook-routes.js.map +1 -0
  116. package/dist/gateway/meta-webhook-foundation.d.ts +12 -0
  117. package/dist/gateway/meta-webhook-foundation.d.ts.map +1 -0
  118. package/dist/gateway/meta-webhook-foundation.js +25 -0
  119. package/dist/gateway/meta-webhook-foundation.js.map +1 -0
  120. package/dist/gateway/mode-b-routes.d.ts +8 -0
  121. package/dist/gateway/mode-b-routes.d.ts.map +1 -1
  122. package/dist/gateway/mode-b-routes.js +74 -36
  123. package/dist/gateway/mode-b-routes.js.map +1 -1
  124. package/dist/gateway/outbound-routes.d.ts.map +1 -1
  125. package/dist/gateway/outbound-routes.js +49 -21
  126. package/dist/gateway/outbound-routes.js.map +1 -1
  127. package/dist/gateway/routing-test-routes.d.ts +10 -0
  128. package/dist/gateway/routing-test-routes.d.ts.map +1 -0
  129. package/dist/gateway/routing-test-routes.js +76 -0
  130. package/dist/gateway/routing-test-routes.js.map +1 -0
  131. package/dist/gateway/sqlite-email-thread-store.d.ts +13 -0
  132. package/dist/gateway/sqlite-email-thread-store.d.ts.map +1 -0
  133. package/dist/gateway/sqlite-email-thread-store.js +66 -0
  134. package/dist/gateway/sqlite-email-thread-store.js.map +1 -0
  135. package/dist/gateway/stt-factory.d.ts +3 -0
  136. package/dist/gateway/stt-factory.d.ts.map +1 -0
  137. package/dist/gateway/stt-factory.js +21 -0
  138. package/dist/gateway/stt-factory.js.map +1 -0
  139. package/dist/gateway/tenant-admin-routes.d.ts.map +1 -1
  140. package/dist/gateway/tenant-admin-routes.js +17 -3
  141. package/dist/gateway/tenant-admin-routes.js.map +1 -1
  142. package/dist/gateway/tenant-routes.d.ts.map +1 -1
  143. package/dist/gateway/tenant-routes.js +18 -27
  144. package/dist/gateway/tenant-routes.js.map +1 -1
  145. package/dist/gateway/tenant-tool-factory.d.ts +10 -0
  146. package/dist/gateway/tenant-tool-factory.d.ts.map +1 -0
  147. package/dist/gateway/tenant-tool-factory.js +55 -0
  148. package/dist/gateway/tenant-tool-factory.js.map +1 -0
  149. package/dist/gateway/trace-context.d.ts +8 -0
  150. package/dist/gateway/trace-context.d.ts.map +1 -0
  151. package/dist/gateway/trace-context.js +17 -0
  152. package/dist/gateway/trace-context.js.map +1 -0
  153. package/dist/gateway/webhook-dedup.d.ts +13 -0
  154. package/dist/gateway/webhook-dedup.d.ts.map +1 -0
  155. package/dist/gateway/webhook-dedup.js +37 -0
  156. package/dist/gateway/webhook-dedup.js.map +1 -0
  157. package/dist/gateway/webhook-tool-executor.d.ts +17 -0
  158. package/dist/gateway/webhook-tool-executor.d.ts.map +1 -0
  159. package/dist/gateway/webhook-tool-executor.js +69 -0
  160. package/dist/gateway/webhook-tool-executor.js.map +1 -0
  161. package/dist/gateway/whatsapp-webhook-routes.d.ts +11 -0
  162. package/dist/gateway/whatsapp-webhook-routes.d.ts.map +1 -1
  163. package/dist/gateway/whatsapp-webhook-routes.js +205 -33
  164. package/dist/gateway/whatsapp-webhook-routes.js.map +1 -1
  165. package/dist/gateway/ws-tenant-routes.d.ts +9 -0
  166. package/dist/gateway/ws-tenant-routes.d.ts.map +1 -1
  167. package/dist/gateway/ws-tenant-routes.js +184 -7
  168. package/dist/gateway/ws-tenant-routes.js.map +1 -1
  169. package/dist/index.d.ts +63 -3
  170. package/dist/index.d.ts.map +1 -1
  171. package/dist/index.js +39 -1
  172. package/dist/index.js.map +1 -1
  173. package/dist/observability/composite-event-store.d.ts +13 -0
  174. package/dist/observability/composite-event-store.d.ts.map +1 -0
  175. package/dist/observability/composite-event-store.js +37 -0
  176. package/dist/observability/composite-event-store.js.map +1 -0
  177. package/dist/observability/prometheus-collector.d.ts +33 -0
  178. package/dist/observability/prometheus-collector.d.ts.map +1 -0
  179. package/dist/observability/prometheus-collector.js +170 -0
  180. package/dist/observability/prometheus-collector.js.map +1 -0
  181. package/dist/session/agent-handoff-summarizer.d.ts +11 -0
  182. package/dist/session/agent-handoff-summarizer.d.ts.map +1 -0
  183. package/dist/session/agent-handoff-summarizer.js +26 -0
  184. package/dist/session/agent-handoff-summarizer.js.map +1 -0
  185. package/dist/session/context-summarizer.d.ts +11 -0
  186. package/dist/session/context-summarizer.d.ts.map +1 -0
  187. package/dist/session/context-summarizer.js +23 -0
  188. package/dist/session/context-summarizer.js.map +1 -0
  189. package/dist/session/escalation-detector.d.ts +27 -0
  190. package/dist/session/escalation-detector.d.ts.map +1 -0
  191. package/dist/session/escalation-detector.js +75 -0
  192. package/dist/session/escalation-detector.js.map +1 -0
  193. package/dist/session/in-memory-session-store.d.ts +11 -0
  194. package/dist/session/in-memory-session-store.d.ts.map +1 -0
  195. package/dist/session/in-memory-session-store.js +26 -0
  196. package/dist/session/in-memory-session-store.js.map +1 -0
  197. package/dist/session/mode-b-orchestrator.d.ts +54 -1
  198. package/dist/session/mode-b-orchestrator.d.ts.map +1 -1
  199. package/dist/session/mode-b-orchestrator.js +349 -17
  200. package/dist/session/mode-b-orchestrator.js.map +1 -1
  201. package/dist/session/mode-b-session.d.ts +48 -1
  202. package/dist/session/mode-b-session.d.ts.map +1 -1
  203. package/dist/session/mode-b-session.js +105 -0
  204. package/dist/session/mode-b-session.js.map +1 -1
  205. package/dist/session/redis-session-store.d.ts +22 -0
  206. package/dist/session/redis-session-store.d.ts.map +1 -0
  207. package/dist/session/redis-session-store.js +44 -0
  208. package/dist/session/redis-session-store.js.map +1 -0
  209. package/dist/session/session-mode.d.ts +4 -0
  210. package/dist/session/session-mode.d.ts.map +1 -0
  211. package/dist/session/session-mode.js +20 -0
  212. package/dist/session/session-mode.js.map +1 -0
  213. package/dist/session/session-registry.d.ts +17 -9
  214. package/dist/session/session-registry.d.ts.map +1 -1
  215. package/dist/session/session-registry.js +80 -29
  216. package/dist/session/session-registry.js.map +1 -1
  217. package/dist/session/session-serializer.d.ts +4 -0
  218. package/dist/session/session-serializer.d.ts.map +1 -0
  219. package/dist/session/session-serializer.js +26 -0
  220. package/dist/session/session-serializer.js.map +1 -0
  221. package/dist/session/session-store.d.ts +9 -0
  222. package/dist/session/session-store.d.ts.map +1 -0
  223. package/dist/session/session-store.js +2 -0
  224. package/dist/session/session-store.js.map +1 -0
  225. package/dist/tenant/agent-resolver.d.ts +26 -0
  226. package/dist/tenant/agent-resolver.d.ts.map +1 -0
  227. package/dist/tenant/agent-resolver.js +232 -0
  228. package/dist/tenant/agent-resolver.js.map +1 -0
  229. package/dist/tenant/ping-pong-guard.d.ts +9 -0
  230. package/dist/tenant/ping-pong-guard.d.ts.map +1 -0
  231. package/dist/tenant/ping-pong-guard.js +30 -0
  232. package/dist/tenant/ping-pong-guard.js.map +1 -0
  233. package/dist/tenant/system-prompt-builder.d.ts +1 -1
  234. package/dist/tenant/system-prompt-builder.d.ts.map +1 -1
  235. package/dist/tenant/system-prompt-builder.js +13 -1
  236. package/dist/tenant/system-prompt-builder.js.map +1 -1
  237. package/dist/tenant/tenant-registry.d.ts +3 -0
  238. package/dist/tenant/tenant-registry.d.ts.map +1 -1
  239. package/dist/tenant/tenant-registry.js +83 -4
  240. package/dist/tenant/tenant-registry.js.map +1 -1
  241. package/dist/tenant/tenant-router.d.ts +27 -0
  242. package/dist/tenant/tenant-router.d.ts.map +1 -0
  243. package/dist/tenant/tenant-router.js +72 -0
  244. package/dist/tenant/tenant-router.js.map +1 -0
  245. package/dist/utils/hmac.d.ts +1 -0
  246. package/dist/utils/hmac.d.ts.map +1 -1
  247. package/dist/utils/hmac.js +3 -0
  248. package/dist/utils/hmac.js.map +1 -1
  249. package/package.json +7 -3
@@ -2,6 +2,10 @@
2
2
  // Single source of truth for adapting content to channel-specific formats
3
3
  /** WhatsApp Cloud API enforces a 4096-character limit per text message */
4
4
  const WHATSAPP_MAX_MESSAGE_LENGTH = 4096;
5
+ /** Instagram Messaging API enforces a 1000-character limit per text message */
6
+ const INSTAGRAM_MAX_MESSAGE_LENGTH = 1000;
7
+ /** Messenger Send API enforces a 2000-character limit per text message */
8
+ const MESSENGER_MAX_MESSAGE_LENGTH = 2000;
5
9
  /** Adapt content for a specific channel format */
6
10
  export function formatForChannel(content, format) {
7
11
  switch (format) {
@@ -33,6 +37,29 @@ export function formatForChannel(content, format) {
33
37
  export function toWhatsAppFormat(text) {
34
38
  return convertMarkdownToWhatsApp(text).slice(0, WHATSAPP_MAX_MESSAGE_LENGTH);
35
39
  }
40
+ /**
41
+ * Convert content to Instagram-compatible plain text.
42
+ * Instagram DM API supports plain text only (no markdown, no formatting).
43
+ * Truncates to 1000-char API limit.
44
+ */
45
+ export function toInstagramFormat(text) {
46
+ return stripMarkdown(text).slice(0, INSTAGRAM_MAX_MESSAGE_LENGTH);
47
+ }
48
+ /**
49
+ * Convert content to Messenger-compatible plain text.
50
+ * Messenger supports plain text only (no markdown).
51
+ * Truncates to 2000-char API limit.
52
+ */
53
+ export function toMessengerFormat(text) {
54
+ return stripMarkdown(text).slice(0, MESSENGER_MAX_MESSAGE_LENGTH);
55
+ }
56
+ /**
57
+ * Format content for email -- keep full markdown (email supports rich formatting).
58
+ * No character truncation (email has no message length limit).
59
+ */
60
+ export function toEmailFormat(text) {
61
+ return text;
62
+ }
36
63
  /** Strip basic markdown formatting for plain text channels */
37
64
  function stripMarkdown(text) {
38
65
  return text
@@ -1 +1 @@
1
- {"version":3,"file":"message-formatter.js","sourceRoot":"","sources":["../../src/channels/message-formatter.ts"],"names":[],"mappings":"AAAA,sDAAsD;AACtD,0EAA0E;AAI1E,0EAA0E;AAC1E,MAAM,2BAA2B,GAAG,IAAI,CAAC;AAEzC,kDAAkD;AAClD,MAAM,UAAU,gBAAgB,CAAC,OAAe,EAAE,MAAqB;IACrE,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,OAAO;YACV,qDAAqD;YACrD,OAAO,aAAa,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,2BAA2B,CAAC,CAAC;QACtE,KAAK,MAAM;YACT,kCAAkC;YAClC,OAAO,OAAO,CAAC;QACjB,KAAK,YAAY;YACf,6CAA6C;YAC7C,OAAO,OAAO,CAAC;QACjB;YACE,OAAO,OAAO,CAAC;IACnB,CAAC;AACH,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,OAAO,yBAAyB,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,2BAA2B,CAAC,CAAC;AAC/E,CAAC;AAED,8DAA8D;AAC9D,SAAS,aAAa,CAAC,IAAY;IACjC,OAAO,IAAI;SACR,OAAO,CAAC,iBAAiB,EAAE,cAAc,CAAC,CAAC,cAAc;SACzD,OAAO,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC,cAAc;SAC1C,OAAO,CAAC,kBAAkB,EAAE,IAAI,CAAC,CAAC,OAAO;SACzC,OAAO,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC,SAAS;SACvC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,UAAU;SAC/B,OAAO,CAAC,wBAAwB,EAAE,IAAI,CAAC,CAAC,QAAQ;SAChD,OAAO,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC,CAAC,aAAa;AAC9C,CAAC;AAED,6EAA6E;AAC7E,yDAAyD;AACzD,MAAM,SAAS,GAAG,MAAM,CAAC;AACzB,MAAM,UAAU,GAAG,MAAM,CAAC;AAE1B,SAAS,yBAAyB,CAAC,IAAY;IAC7C,OAAO,CACL,IAAI;QACF,+DAA+D;SAC9D,OAAO,CAAC,+BAA+B,EAAE,UAAU,CAAC;QACrD,mCAAmC;SAClC,OAAO,CAAC,YAAY,EAAE,UAAU,CAAC;QAClC,2EAA2E;SAC1E,OAAO,CAAC,kBAAkB,EAAE,GAAG,SAAS,KAAK,UAAU,EAAE,CAAC;QAC3D,2CAA2C;SAC1C,OAAO,CAAC,cAAc,EAAE,MAAM,CAAC;QAChC,mDAAmD;SAClD,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC;QACvC,mCAAmC;SAClC,OAAO,CAAC,cAAc,EAAE,MAAM,CAAC;QAChC,iDAAiD;SAChD,OAAO,CAAC,mBAAmB,EAAE,MAAM,CAAC;QACrC,kCAAkC;SACjC,OAAO,CAAC,0BAA0B,EAAE,SAAS,CAAC;QAC/C,8CAA8C;SAC7C,OAAO,CAAC,YAAY,EAAE,SAAS,CAAC,CACpC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"message-formatter.js","sourceRoot":"","sources":["../../src/channels/message-formatter.ts"],"names":[],"mappings":"AAAA,sDAAsD;AACtD,0EAA0E;AAI1E,0EAA0E;AAC1E,MAAM,2BAA2B,GAAG,IAAI,CAAC;AAEzC,+EAA+E;AAC/E,MAAM,4BAA4B,GAAG,IAAI,CAAC;AAE1C,0EAA0E;AAC1E,MAAM,4BAA4B,GAAG,IAAI,CAAC;AAE1C,kDAAkD;AAClD,MAAM,UAAU,gBAAgB,CAAC,OAAe,EAAE,MAAqB;IACrE,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,OAAO;YACV,qDAAqD;YACrD,OAAO,aAAa,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,2BAA2B,CAAC,CAAC;QACtE,KAAK,MAAM;YACT,kCAAkC;YAClC,OAAO,OAAO,CAAC;QACjB,KAAK,YAAY;YACf,6CAA6C;YAC7C,OAAO,OAAO,CAAC;QACjB;YACE,OAAO,OAAO,CAAC;IACnB,CAAC;AACH,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,OAAO,yBAAyB,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,2BAA2B,CAAC,CAAC;AAC/E,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,OAAO,aAAa,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,4BAA4B,CAAC,CAAC;AACpE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,OAAO,aAAa,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,4BAA4B,CAAC,CAAC;AACpE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,OAAO,IAAI,CAAC;AACd,CAAC;AAED,8DAA8D;AAC9D,SAAS,aAAa,CAAC,IAAY;IACjC,OAAO,IAAI;SACR,OAAO,CAAC,iBAAiB,EAAE,cAAc,CAAC,CAAC,cAAc;SACzD,OAAO,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC,cAAc;SAC1C,OAAO,CAAC,kBAAkB,EAAE,IAAI,CAAC,CAAC,OAAO;SACzC,OAAO,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC,SAAS;SACvC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,UAAU;SAC/B,OAAO,CAAC,wBAAwB,EAAE,IAAI,CAAC,CAAC,QAAQ;SAChD,OAAO,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC,CAAC,aAAa;AAC9C,CAAC;AAED,6EAA6E;AAC7E,yDAAyD;AACzD,MAAM,SAAS,GAAG,MAAM,CAAC;AACzB,MAAM,UAAU,GAAG,MAAM,CAAC;AAE1B,SAAS,yBAAyB,CAAC,IAAY;IAC7C,OAAO,CACL,IAAI;QACF,+DAA+D;SAC9D,OAAO,CAAC,+BAA+B,EAAE,UAAU,CAAC;QACrD,mCAAmC;SAClC,OAAO,CAAC,YAAY,EAAE,UAAU,CAAC;QAClC,2EAA2E;SAC1E,OAAO,CAAC,kBAAkB,EAAE,GAAG,SAAS,KAAK,UAAU,EAAE,CAAC;QAC3D,2CAA2C;SAC1C,OAAO,CAAC,cAAc,EAAE,MAAM,CAAC;QAChC,mDAAmD;SAClD,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC;QACvC,mCAAmC;SAClC,OAAO,CAAC,cAAc,EAAE,MAAM,CAAC;QAChC,iDAAiD;SAChD,OAAO,CAAC,mBAAmB,EAAE,MAAM,CAAC;QACrC,kCAAkC;SACjC,OAAO,CAAC,0BAA0B,EAAE,SAAS,CAAC;QAC/C,8CAA8C;SAC7C,OAAO,CAAC,YAAY,EAAE,SAAS,CAAC,CACpC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,27 @@
1
+ /** Messenger Graph API version */
2
+ export declare const MESSENGER_GRAPH_API_VERSION = "v21.0";
3
+ /** Build the Messenger Send API endpoint URL */
4
+ export declare function messengerMessagesUrl(): string;
5
+ /** Response from Messenger Send API */
6
+ export interface MessengerSendResult {
7
+ readonly recipientId: string;
8
+ readonly messageId: string;
9
+ }
10
+ /**
11
+ * Send a text message via Messenger Send API.
12
+ *
13
+ * @param accessToken - Page access token
14
+ * @param recipientId - Page-scoped user ID (PSID)
15
+ * @param text - Message text (max 2000 chars)
16
+ */
17
+ export declare function sendMessengerMessage(accessToken: string, recipientId: string, text: string): Promise<MessengerSendResult>;
18
+ /**
19
+ * Send a media message (image) via Messenger Send API.
20
+ *
21
+ * @param accessToken - Page access token
22
+ * @param recipientId - Page-scoped user ID (PSID)
23
+ * @param mediaUrl - Public URL of the media
24
+ * @param mediaType - Type of media ("image")
25
+ */
26
+ export declare function sendMessengerMediaMessage(accessToken: string, recipientId: string, mediaUrl: string, mediaType: "image"): Promise<MessengerSendResult>;
27
+ //# sourceMappingURL=messenger-api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messenger-api.d.ts","sourceRoot":"","sources":["../../src/channels/messenger-api.ts"],"names":[],"mappings":"AAGA,kCAAkC;AAClC,eAAO,MAAM,2BAA2B,UAAU,CAAC;AAEnD,gDAAgD;AAChD,wBAAgB,oBAAoB,IAAI,MAAM,CAE7C;AAED,uCAAuC;AACvC,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CACxC,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,mBAAmB,CAAC,CAwB9B;AAED;;;;;;;GAOG;AACH,wBAAsB,yBAAyB,CAC7C,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,OAAO,GACjB,OAAO,CAAC,mBAAmB,CAAC,CA6B9B"}
@@ -0,0 +1,75 @@
1
+ // Facebook Messenger Send API client
2
+ // Uses the Messenger Platform Graph API for page-scoped messaging
3
+ /** Messenger Graph API version */
4
+ export const MESSENGER_GRAPH_API_VERSION = "v21.0";
5
+ /** Build the Messenger Send API endpoint URL */
6
+ export function messengerMessagesUrl() {
7
+ return `https://graph.facebook.com/${MESSENGER_GRAPH_API_VERSION}/me/messages`;
8
+ }
9
+ /**
10
+ * Send a text message via Messenger Send API.
11
+ *
12
+ * @param accessToken - Page access token
13
+ * @param recipientId - Page-scoped user ID (PSID)
14
+ * @param text - Message text (max 2000 chars)
15
+ */
16
+ export async function sendMessengerMessage(accessToken, recipientId, text) {
17
+ const res = await fetch(messengerMessagesUrl(), {
18
+ method: "POST",
19
+ headers: {
20
+ "Content-Type": "application/json",
21
+ Authorization: `Bearer ${accessToken}`,
22
+ },
23
+ body: JSON.stringify({
24
+ messaging_type: "RESPONSE",
25
+ recipient: { id: recipientId },
26
+ message: { text },
27
+ }),
28
+ });
29
+ if (!res.ok) {
30
+ const body = await res.text().catch(() => "(unreadable)");
31
+ throw new Error(`Messenger API error ${res.status}: ${body}`);
32
+ }
33
+ const json = (await res.json());
34
+ return {
35
+ recipientId: json.recipient_id ?? recipientId,
36
+ messageId: json.message_id ?? "",
37
+ };
38
+ }
39
+ /**
40
+ * Send a media message (image) via Messenger Send API.
41
+ *
42
+ * @param accessToken - Page access token
43
+ * @param recipientId - Page-scoped user ID (PSID)
44
+ * @param mediaUrl - Public URL of the media
45
+ * @param mediaType - Type of media ("image")
46
+ */
47
+ export async function sendMessengerMediaMessage(accessToken, recipientId, mediaUrl, mediaType) {
48
+ const res = await fetch(messengerMessagesUrl(), {
49
+ method: "POST",
50
+ headers: {
51
+ "Content-Type": "application/json",
52
+ Authorization: `Bearer ${accessToken}`,
53
+ },
54
+ body: JSON.stringify({
55
+ messaging_type: "RESPONSE",
56
+ recipient: { id: recipientId },
57
+ message: {
58
+ attachment: {
59
+ type: mediaType,
60
+ payload: { url: mediaUrl },
61
+ },
62
+ },
63
+ }),
64
+ });
65
+ if (!res.ok) {
66
+ const body = await res.text().catch(() => "(unreadable)");
67
+ throw new Error(`Messenger API error ${res.status}: ${body}`);
68
+ }
69
+ const json = (await res.json());
70
+ return {
71
+ recipientId: json.recipient_id ?? recipientId,
72
+ messageId: json.message_id ?? "",
73
+ };
74
+ }
75
+ //# sourceMappingURL=messenger-api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messenger-api.js","sourceRoot":"","sources":["../../src/channels/messenger-api.ts"],"names":[],"mappings":"AAAA,qCAAqC;AACrC,kEAAkE;AAElE,kCAAkC;AAClC,MAAM,CAAC,MAAM,2BAA2B,GAAG,OAAO,CAAC;AAEnD,gDAAgD;AAChD,MAAM,UAAU,oBAAoB;IAClC,OAAO,8BAA8B,2BAA2B,cAAc,CAAC;AACjF,CAAC;AAQD;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,WAAmB,EACnB,WAAmB,EACnB,IAAY;IAEZ,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,oBAAoB,EAAE,EAAE;QAC9C,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACP,cAAc,EAAE,kBAAkB;YAClC,aAAa,EAAE,UAAU,WAAW,EAAE;SACvC;QACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;YACnB,cAAc,EAAE,UAAU;YAC1B,SAAS,EAAE,EAAE,EAAE,EAAE,WAAW,EAAE;YAC9B,OAAO,EAAE,EAAE,IAAI,EAAE;SAClB,CAAC;KACH,CAAC,CAAC;IAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,cAAc,CAAC,CAAC;QAC1D,MAAM,IAAI,KAAK,CAAC,uBAAuB,GAAG,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC,CAAC;IAChE,CAAC;IAED,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAmD,CAAC;IAClF,OAAO;QACL,WAAW,EAAE,IAAI,CAAC,YAAY,IAAI,WAAW;QAC7C,SAAS,EAAE,IAAI,CAAC,UAAU,IAAI,EAAE;KACjC,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAC7C,WAAmB,EACnB,WAAmB,EACnB,QAAgB,EAChB,SAAkB;IAElB,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,oBAAoB,EAAE,EAAE;QAC9C,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACP,cAAc,EAAE,kBAAkB;YAClC,aAAa,EAAE,UAAU,WAAW,EAAE;SACvC;QACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;YACnB,cAAc,EAAE,UAAU;YAC1B,SAAS,EAAE,EAAE,EAAE,EAAE,WAAW,EAAE;YAC9B,OAAO,EAAE;gBACP,UAAU,EAAE;oBACV,IAAI,EAAE,SAAS;oBACf,OAAO,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE;iBAC3B;aACF;SACF,CAAC;KACH,CAAC,CAAC;IAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,cAAc,CAAC,CAAC;QAC1D,MAAM,IAAI,KAAK,CAAC,uBAAuB,GAAG,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC,CAAC;IAChE,CAAC;IAED,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAmD,CAAC;IAClF,OAAO;QACL,WAAW,EAAE,IAAI,CAAC,YAAY,IAAI,WAAW;QAC7C,SAAS,EAAE,IAAI,CAAC,UAAU,IAAI,EAAE;KACjC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,23 @@
1
+ import type { Channel, IncomingMessage, OutgoingMessage, EngineEvent, MessageFormat, Modality } from "@kilnai/core";
2
+ export interface MessengerConfig {
3
+ readonly accessToken: string;
4
+ }
5
+ /**
6
+ * Channel adapter for Facebook Messenger.
7
+ * receive() accepts parsed webhook messages from Messenger Platform.
8
+ * send() posts text/image messages via graph.facebook.com/me/messages.
9
+ * stream() sends each engine event as a summarized text message.
10
+ */
11
+ export declare class MessengerChannel implements Channel {
12
+ readonly name = "messenger";
13
+ readonly defaultFormat: MessageFormat;
14
+ readonly supportedModalities: readonly Modality[];
15
+ private readonly config;
16
+ private messageHandler;
17
+ constructor(config: MessengerConfig);
18
+ onMessage(handler: (message: IncomingMessage) => void): void;
19
+ receive(message: IncomingMessage): Promise<void>;
20
+ send(response: OutgoingMessage): Promise<void>;
21
+ stream(events: AsyncIterable<EngineEvent>): Promise<void>;
22
+ }
23
+ //# sourceMappingURL=messenger-channel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messenger-channel.d.ts","sourceRoot":"","sources":["../../src/channels/messenger-channel.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,WAAW,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAKpH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED;;;;;GAKG;AACH,qBAAa,gBAAiB,YAAW,OAAO;IAC9C,QAAQ,CAAC,IAAI,eAAe;IAC5B,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAW;IAChD,QAAQ,CAAC,mBAAmB,EAAE,SAAS,QAAQ,EAAE,CAAqB;IAEtE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;IACzC,OAAO,CAAC,cAAc,CAAqD;gBAE/D,MAAM,EAAE,eAAe;IAInC,SAAS,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,IAAI,GAAG,IAAI;IAItD,OAAO,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAMhD,IAAI,CAAC,QAAQ,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAmB9C,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,WAAW,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;CAShE"}
@@ -0,0 +1,55 @@
1
+ // MessengerChannel: Facebook Messenger Platform adapter
2
+ // Uses Messenger Send API via shared API client
3
+ import { extractText, textParts } from "@kilnai/core";
4
+ import { toMessengerFormat } from "./message-formatter.js";
5
+ import { sendMessengerMessage, sendMessengerMediaMessage } from "./messenger-api.js";
6
+ /**
7
+ * Channel adapter for Facebook Messenger.
8
+ * receive() accepts parsed webhook messages from Messenger Platform.
9
+ * send() posts text/image messages via graph.facebook.com/me/messages.
10
+ * stream() sends each engine event as a summarized text message.
11
+ */
12
+ export class MessengerChannel {
13
+ name = "messenger";
14
+ defaultFormat = "short";
15
+ supportedModalities = ["text", "image"];
16
+ config;
17
+ messageHandler = null;
18
+ constructor(config) {
19
+ this.config = config;
20
+ }
21
+ onMessage(handler) {
22
+ this.messageHandler = handler;
23
+ }
24
+ async receive(message) {
25
+ if (this.messageHandler) {
26
+ this.messageHandler(message);
27
+ }
28
+ }
29
+ async send(response) {
30
+ const { accessToken } = this.config;
31
+ const to = response.target;
32
+ // Send image parts first
33
+ for (const part of response.parts) {
34
+ if (part.type === "image" && part.url) {
35
+ await sendMessengerMediaMessage(accessToken, to, part.url, "image");
36
+ }
37
+ }
38
+ // Send text content
39
+ const text = extractText(response.parts);
40
+ if (text) {
41
+ const formatted = toMessengerFormat(text);
42
+ await sendMessengerMessage(accessToken, to, formatted);
43
+ }
44
+ }
45
+ async stream(events) {
46
+ for await (const event of events) {
47
+ await this.send({
48
+ parts: textParts(`[${event.type}] ${JSON.stringify(event.payload)}`),
49
+ target: "stream",
50
+ format: this.defaultFormat,
51
+ });
52
+ }
53
+ }
54
+ }
55
+ //# sourceMappingURL=messenger-channel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messenger-channel.js","sourceRoot":"","sources":["../../src/channels/messenger-channel.ts"],"names":[],"mappings":"AAAA,wDAAwD;AACxD,gDAAgD;AAGhD,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAMrF;;;;;GAKG;AACH,MAAM,OAAO,gBAAgB;IAClB,IAAI,GAAG,WAAW,CAAC;IACnB,aAAa,GAAkB,OAAO,CAAC;IACvC,mBAAmB,GAAwB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAErD,MAAM,CAAkB;IACjC,cAAc,GAAgD,IAAI,CAAC;IAE3E,YAAY,MAAuB;QACjC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED,SAAS,CAAC,OAA2C;QACnD,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC;IAChC,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,OAAwB;QACpC,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACxB,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;QAC/B,CAAC;IACH,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,QAAyB;QAClC,MAAM,EAAE,WAAW,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC;QACpC,MAAM,EAAE,GAAG,QAAQ,CAAC,MAAM,CAAC;QAE3B,yBAAyB;QACzB,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;YAClC,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;gBACtC,MAAM,yBAAyB,CAAC,WAAW,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;YACtE,CAAC;QACH,CAAC;QAED,oBAAoB;QACpB,MAAM,IAAI,GAAG,WAAW,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QACzC,IAAI,IAAI,EAAE,CAAC;YACT,MAAM,SAAS,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;YAC1C,MAAM,oBAAoB,CAAC,WAAW,EAAE,EAAE,EAAE,SAAS,CAAC,CAAC;QACzD,CAAC;IACH,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,MAAkC;QAC7C,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YACjC,MAAM,IAAI,CAAC,IAAI,CAAC;gBACd,KAAK,EAAE,SAAS,CAAC,IAAI,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;gBACpE,MAAM,EAAE,QAAQ;gBAChB,MAAM,EAAE,IAAI,CAAC,aAAa;aAC3B,CAAC,CAAC;QACL,CAAC;IACH,CAAC;CACF"}
@@ -28,6 +28,8 @@ export declare class WebChannel implements Channel {
28
28
  receive(message: IncomingMessage): Promise<void>;
29
29
  send(response: OutgoingMessage): Promise<void>;
30
30
  stream(events: AsyncIterable<EngineEvent>): Promise<void>;
31
+ /** Send a payload to all WebSocket clients for a given user/session */
32
+ sendToUser(userId: string, payload: string): void;
31
33
  /** Send to clients in a specific session */
32
34
  private sendToSession;
33
35
  /** Send to all clients across all sessions */
@@ -1 +1 @@
1
- {"version":3,"file":"web-channel.d.ts","sourceRoot":"","sources":["../../src/channels/web-channel.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,WAAW,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAIpH,mEAAmE;AACnE,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;;GAMG;AACH,qBAAa,UAAW,YAAW,OAAO;IACxC,QAAQ,CAAC,IAAI,SAAS;IACtB,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAU;IAC/C,QAAQ,CAAC,mBAAmB,EAAE,SAAS,QAAQ,EAAE,CAAsC;IAEvF,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAyC;IAClE,OAAO,CAAC,cAAc,CAAqD;IAE3E,yDAAyD;IACzD,SAAS,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,IAAI,GAAG,IAAI;IAI5D,kDAAkD;IAClD,SAAS,CAAC,EAAE,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;IASrD,mEAAmE;IACnE,YAAY,CAAC,EAAE,EAAE,aAAa,GAAG,IAAI;IAWrC,4DAA4D;IAC5D,IAAI,WAAW,IAAI,MAAM,CAMxB;IAEK,OAAO,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAMhD,IAAI,CAAC,QAAQ,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAmB9C,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,WAAW,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAY/D,4CAA4C;IAC5C,OAAO,CAAC,aAAa;IAQrB,8CAA8C;IAC9C,OAAO,CAAC,YAAY;IAQpB,OAAO,CAAC,OAAO;CAShB"}
1
+ {"version":3,"file":"web-channel.d.ts","sourceRoot":"","sources":["../../src/channels/web-channel.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,WAAW,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAIpH,mEAAmE;AACnE,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;;GAMG;AACH,qBAAa,UAAW,YAAW,OAAO;IACxC,QAAQ,CAAC,IAAI,SAAS;IACtB,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAU;IAC/C,QAAQ,CAAC,mBAAmB,EAAE,SAAS,QAAQ,EAAE,CAAsC;IAEvF,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAyC;IAClE,OAAO,CAAC,cAAc,CAAqD;IAE3E,yDAAyD;IACzD,SAAS,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,IAAI,GAAG,IAAI;IAI5D,kDAAkD;IAClD,SAAS,CAAC,EAAE,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;IASrD,mEAAmE;IACnE,YAAY,CAAC,EAAE,EAAE,aAAa,GAAG,IAAI;IAWrC,4DAA4D;IAC5D,IAAI,WAAW,IAAI,MAAM,CAMxB;IAEK,OAAO,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAMhD,IAAI,CAAC,QAAQ,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAmB9C,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,WAAW,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAY/D,uEAAuE;IACvE,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IAQjD,4CAA4C;IAC5C,OAAO,CAAC,aAAa;IAQrB,8CAA8C;IAC9C,OAAO,CAAC,YAAY;IAQpB,OAAO,CAAC,OAAO;CAShB"}
@@ -81,6 +81,15 @@ export class WebChannel {
81
81
  this.broadcastAll(payload);
82
82
  }
83
83
  }
84
+ /** Send a payload to all WebSocket clients for a given user/session */
85
+ sendToUser(userId, payload) {
86
+ const set = this.sessions.get(userId);
87
+ if (!set)
88
+ return;
89
+ for (const client of set) {
90
+ this.trySend(set, client, payload);
91
+ }
92
+ }
84
93
  /** Send to clients in a specific session */
85
94
  sendToSession(sessionId, payload) {
86
95
  const set = this.sessions.get(sessionId);
@@ -1 +1 @@
1
- {"version":3,"file":"web-channel.js","sourceRoot":"","sources":["../../src/channels/web-channel.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"web-channel.js","sourceRoot":"","sources":["../../src/channels/web-channel.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import type { ConversationEnricher, CompletedSession, EnrichmentStore } from "@kilnai/core";
2
+ import type { ConversationEventEmitter } from "../gateway/conversation-event-emitter.js";
3
+ export interface EnrichmentRunnerConfig {
4
+ readonly enricher: ConversationEnricher;
5
+ readonly store: EnrichmentStore;
6
+ readonly eventEmitter?: ConversationEventEmitter;
7
+ readonly timeoutMs?: number;
8
+ }
9
+ export declare class EnrichmentRunner {
10
+ private readonly config;
11
+ private readonly timeoutMs;
12
+ constructor(config: EnrichmentRunnerConfig);
13
+ /** Run enrichment for a completed session. Fire-and-forget. */
14
+ runPostConversation(session: CompletedSession): void;
15
+ private executeEnrichment;
16
+ }
17
+ //# sourceMappingURL=enrichment-runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enrichment-runner.d.ts","sourceRoot":"","sources":["../../src/enrichment/enrichment-runner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,oBAAoB,EACpB,gBAAgB,EAChB,eAAe,EAChB,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,0CAA0C,CAAC;AAEzF,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,QAAQ,EAAE,oBAAoB,CAAC;IACxC,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAC;IAChC,QAAQ,CAAC,YAAY,CAAC,EAAE,wBAAwB,CAAC;IACjD,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAyB;IAChD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;gBAEvB,MAAM,EAAE,sBAAsB;IAK1C,+DAA+D;IAC/D,mBAAmB,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI;YAMtC,iBAAiB;CAkChC"}
@@ -0,0 +1,45 @@
1
+ export class EnrichmentRunner {
2
+ config;
3
+ timeoutMs;
4
+ constructor(config) {
5
+ this.config = config;
6
+ this.timeoutMs = config.timeoutMs ?? 10_000;
7
+ }
8
+ /** Run enrichment for a completed session. Fire-and-forget. */
9
+ runPostConversation(session) {
10
+ this.executeEnrichment(session).catch((err) => {
11
+ console.warn("[enrichment] Post-conversation enrichment failed:", err);
12
+ });
13
+ }
14
+ async executeEnrichment(session) {
15
+ const controller = new AbortController();
16
+ const timeout = setTimeout(() => controller.abort(), this.timeoutMs);
17
+ try {
18
+ const enrichment = await Promise.race([
19
+ this.config.enricher.enrich(session),
20
+ new Promise((_, reject) => {
21
+ controller.signal.addEventListener("abort", () => reject(new Error("Enrichment timeout")));
22
+ }),
23
+ ]);
24
+ if (enrichment) {
25
+ await this.config.store.save(enrichment);
26
+ // Emit CONVERSATION_ENRICHED conversation event
27
+ if (this.config.eventEmitter) {
28
+ this.config.eventEmitter.emit({
29
+ eventType: "CONVERSATION_ENRICHED",
30
+ tenantId: session.tenantId,
31
+ channel: "unknown",
32
+ externalUserId: "",
33
+ sessionId: session.sessionId,
34
+ schemaVersion: "1",
35
+ timestamp: new Date().toISOString(),
36
+ });
37
+ }
38
+ }
39
+ }
40
+ finally {
41
+ clearTimeout(timeout);
42
+ }
43
+ }
44
+ }
45
+ //# sourceMappingURL=enrichment-runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enrichment-runner.js","sourceRoot":"","sources":["../../src/enrichment/enrichment-runner.ts"],"names":[],"mappings":"AAcA,MAAM,OAAO,gBAAgB;IACV,MAAM,CAAyB;IAC/B,SAAS,CAAS;IAEnC,YAAY,MAA8B;QACxC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC;IAC9C,CAAC;IAED,+DAA+D;IAC/D,mBAAmB,CAAC,OAAyB;QAC3C,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;YAC5C,OAAO,CAAC,IAAI,CAAC,mDAAmD,EAAE,GAAG,CAAC,CAAC;QACzE,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,KAAK,CAAC,iBAAiB,CAAC,OAAyB;QACvD,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;QAErE,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC;gBACpC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC;gBACpC,IAAI,OAAO,CAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE;oBAC/B,UAAU,CAAC,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE,CAC/C,MAAM,CAAC,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC,CACxC,CAAC;gBACJ,CAAC,CAAC;aACH,CAAC,CAAC;YAEH,IAAI,UAAU,EAAE,CAAC;gBACf,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;gBAEzC,gDAAgD;gBAChD,IAAI,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE,CAAC;oBAC7B,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC;wBAC5B,SAAS,EAAE,uBAAuB;wBAClC,QAAQ,EAAE,OAAO,CAAC,QAAQ;wBAC1B,OAAO,EAAE,SAAS;wBAClB,cAAc,EAAE,EAAE;wBAClB,SAAS,EAAE,OAAO,CAAC,SAAS;wBAC5B,aAAa,EAAE,GAAG;wBAClB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;qBACpC,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;QACH,CAAC;gBAAS,CAAC;YACT,YAAY,CAAC,OAAO,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,14 @@
1
+ import type { EnrichmentStore, ConversationEnrichment } from "@kilnai/core";
2
+ export declare class SqliteEnrichmentStore implements EnrichmentStore {
3
+ private readonly db;
4
+ constructor(dbPath?: string);
5
+ save(enrichment: ConversationEnrichment): Promise<void>;
6
+ get(sessionId: string): Promise<ConversationEnrichment | undefined>;
7
+ listByTenant(tenantId: string, limit?: number, cursor?: string): Promise<{
8
+ readonly enrichments: readonly ConversationEnrichment[];
9
+ readonly nextCursor?: string;
10
+ }>;
11
+ delete(sessionId: string): Promise<boolean>;
12
+ close(): void;
13
+ }
14
+ //# sourceMappingURL=sqlite-enrichment-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite-enrichment-store.d.ts","sourceRoot":"","sources":["../../src/enrichment/sqlite-enrichment-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,sBAAsB,EACvB,MAAM,cAAc,CAAC;AAGtB,qBAAa,qBAAsB,YAAW,eAAe;IAC3D,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAW;gBAElB,MAAM,GAAE,MAAmB;IAkBjC,IAAI,CAAC,UAAU,EAAE,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC;IAavD,GAAG,CACP,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,sBAAsB,GAAG,SAAS,CAAC;IAUxC,YAAY,CAChB,QAAQ,EAAE,MAAM,EAChB,KAAK,SAAK,EACV,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC;QACT,QAAQ,CAAC,WAAW,EAAE,SAAS,sBAAsB,EAAE,CAAC;QACxD,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;KAC9B,CAAC;IA4BI,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAejD,KAAK,IAAI,IAAI;CAGd"}
@@ -0,0 +1,69 @@
1
+ import { Database } from "bun:sqlite";
2
+ export class SqliteEnrichmentStore {
3
+ db;
4
+ constructor(dbPath = ":memory:") {
5
+ this.db = new Database(dbPath);
6
+ this.db.exec("PRAGMA journal_mode=WAL;");
7
+ this.db.exec("PRAGMA busy_timeout=5000;");
8
+ this.db.exec(`
9
+ CREATE TABLE IF NOT EXISTS conversation_enrichments (
10
+ session_id TEXT PRIMARY KEY,
11
+ tenant_id TEXT NOT NULL,
12
+ enrichment_json TEXT NOT NULL,
13
+ created_at TEXT NOT NULL
14
+ );
15
+ `);
16
+ this.db.exec(`
17
+ CREATE INDEX IF NOT EXISTS idx_enrichments_tenant_created
18
+ ON conversation_enrichments (tenant_id, created_at);
19
+ `);
20
+ }
21
+ async save(enrichment) {
22
+ this.db
23
+ .prepare("INSERT OR REPLACE INTO conversation_enrichments (session_id, tenant_id, enrichment_json, created_at) VALUES (?, ?, ?, ?)")
24
+ .run(enrichment.sessionId, enrichment.tenantId, JSON.stringify(enrichment), enrichment.enrichedAt);
25
+ }
26
+ async get(sessionId) {
27
+ const row = this.db
28
+ .prepare("SELECT enrichment_json FROM conversation_enrichments WHERE session_id = ?")
29
+ .get(sessionId);
30
+ if (!row)
31
+ return undefined;
32
+ return JSON.parse(row.enrichment_json);
33
+ }
34
+ async listByTenant(tenantId, limit = 50, cursor) {
35
+ let rows;
36
+ if (cursor) {
37
+ rows = this.db
38
+ .prepare("SELECT enrichment_json FROM conversation_enrichments WHERE tenant_id = ? AND created_at < ? ORDER BY created_at DESC LIMIT ?")
39
+ .all(tenantId, cursor, limit + 1);
40
+ }
41
+ else {
42
+ rows = this.db
43
+ .prepare("SELECT enrichment_json FROM conversation_enrichments WHERE tenant_id = ? ORDER BY created_at DESC LIMIT ?")
44
+ .all(tenantId, limit + 1);
45
+ }
46
+ const hasMore = rows.length > limit;
47
+ const trimmed = hasMore ? rows.slice(0, limit) : rows;
48
+ const enrichments = trimmed.map((r) => JSON.parse(r.enrichment_json));
49
+ const nextCursor = hasMore
50
+ ? enrichments[enrichments.length - 1]?.enrichedAt
51
+ : undefined;
52
+ return { enrichments, nextCursor };
53
+ }
54
+ async delete(sessionId) {
55
+ const existing = this.db
56
+ .prepare("SELECT 1 FROM conversation_enrichments WHERE session_id = ?")
57
+ .get(sessionId);
58
+ if (!existing)
59
+ return false;
60
+ this.db
61
+ .prepare("DELETE FROM conversation_enrichments WHERE session_id = ?")
62
+ .run(sessionId);
63
+ return true;
64
+ }
65
+ close() {
66
+ this.db.close();
67
+ }
68
+ }
69
+ //# sourceMappingURL=sqlite-enrichment-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite-enrichment-store.js","sourceRoot":"","sources":["../../src/enrichment/sqlite-enrichment-store.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,MAAM,OAAO,qBAAqB;IACf,EAAE,CAAW;IAE9B,YAAY,SAAiB,UAAU;QACrC,IAAI,CAAC,EAAE,GAAG,IAAI,QAAQ,CAAC,MAAM,CAAC,CAAC;QAC/B,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;QACzC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;QAC1C,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC;;;;;;;KAOZ,CAAC,CAAC;QACH,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC;;;KAGZ,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,UAAkC;QAC3C,IAAI,CAAC,EAAE;aACJ,OAAO,CACN,0HAA0H,CAC3H;aACA,GAAG,CACF,UAAU,CAAC,SAAS,EACpB,UAAU,CAAC,QAAQ,EACnB,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,EAC1B,UAAU,CAAC,UAAU,CACtB,CAAC;IACN,CAAC;IAED,KAAK,CAAC,GAAG,CACP,SAAiB;QAEjB,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE;aAChB,OAAO,CACN,2EAA2E,CAC5E;aACA,GAAG,CAAC,SAAS,CAAuC,CAAC;QACxD,IAAI,CAAC,GAAG;YAAE,OAAO,SAAS,CAAC;QAC3B,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,eAAe,CAA2B,CAAC;IACnE,CAAC;IAED,KAAK,CAAC,YAAY,CAChB,QAAgB,EAChB,KAAK,GAAG,EAAE,EACV,MAAe;QAKf,IAAI,IAAmC,CAAC;QACxC,IAAI,MAAM,EAAE,CAAC;YACX,IAAI,GAAG,IAAI,CAAC,EAAE;iBACX,OAAO,CACN,8HAA8H,CAC/H;iBACA,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,GAAG,CAAC,CAAkC,CAAC;QACvE,CAAC;aAAM,CAAC;YACN,IAAI,GAAG,IAAI,CAAC,EAAE;iBACX,OAAO,CACN,2GAA2G,CAC5G;iBACA,GAAG,CAAC,QAAQ,EAAE,KAAK,GAAG,CAAC,CAAkC,CAAC;QAC/D,CAAC;QAED,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QACpC,MAAM,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACtD,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAC7B,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,eAAe,CAA2B,CAC/D,CAAC;QACF,MAAM,UAAU,GAAG,OAAO;YACxB,CAAC,CAAC,WAAW,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,UAAU;YACjD,CAAC,CAAC,SAAS,CAAC;QAEd,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC;IACrC,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,SAAiB;QAC5B,MAAM,QAAQ,GAAG,IAAI,CAAC,EAAE;aACrB,OAAO,CACN,6DAA6D,CAC9D;aACA,GAAG,CAAC,SAAS,CAAC,CAAC;QAClB,IAAI,CAAC,QAAQ;YAAE,OAAO,KAAK,CAAC;QAC5B,IAAI,CAAC,EAAE;aACJ,OAAO,CACN,2DAA2D,CAC5D;aACA,GAAG,CAAC,SAAS,CAAC,CAAC;QAClB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK;QACH,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC;IAClB,CAAC;CACF"}
@@ -0,0 +1,11 @@
1
+ import type { ContentPart, SttAdapter } from "@kilnai/core";
2
+ export interface MediaDownloader {
3
+ download(url: string): Promise<{
4
+ data: Uint8Array;
5
+ mimeType: string;
6
+ }>;
7
+ }
8
+ export declare function createWhatsAppMediaDownloader(accessToken: string): MediaDownloader;
9
+ export declare function createGenericMediaDownloader(): MediaDownloader;
10
+ export declare function preprocessAudio(parts: readonly ContentPart[], stt: SttAdapter, downloader: MediaDownloader): Promise<readonly ContentPart[]>;
11
+ //# sourceMappingURL=audio-preprocessor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audio-preprocessor.d.ts","sourceRoot":"","sources":["../../src/gateway/audio-preprocessor.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE5D,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,UAAU,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACxE;AAED,wBAAgB,6BAA6B,CAAC,WAAW,EAAE,MAAM,GAAG,eAAe,CAwBlF;AAED,wBAAgB,4BAA4B,IAAI,eAAe,CAY9D;AAED,wBAAsB,eAAe,CACnC,KAAK,EAAE,SAAS,WAAW,EAAE,EAC7B,GAAG,EAAE,UAAU,EACf,UAAU,EAAE,eAAe,GAC1B,OAAO,CAAC,SAAS,WAAW,EAAE,CAAC,CAuCjC"}
@@ -0,0 +1,76 @@
1
+ // Audio preprocessor -- transcribes AudioParts to TextParts before orchestration
2
+ export function createWhatsAppMediaDownloader(accessToken) {
3
+ return {
4
+ async download(url) {
5
+ // Step 1: Resolve media URL from Graph API (url is graph.facebook.com/.../mediaId)
6
+ const metaRes = await fetch(url, {
7
+ headers: { Authorization: `Bearer ${accessToken}` },
8
+ });
9
+ if (!metaRes.ok) {
10
+ throw new Error(`WhatsApp media metadata fetch failed: ${metaRes.status}`);
11
+ }
12
+ const meta = (await metaRes.json());
13
+ // Step 2: Download actual media binary
14
+ const mediaRes = await fetch(meta.url, {
15
+ headers: { Authorization: `Bearer ${accessToken}` },
16
+ });
17
+ if (!mediaRes.ok) {
18
+ throw new Error(`WhatsApp media download failed: ${mediaRes.status}`);
19
+ }
20
+ const buffer = await mediaRes.arrayBuffer();
21
+ return { data: new Uint8Array(buffer), mimeType: meta.mime_type };
22
+ },
23
+ };
24
+ }
25
+ export function createGenericMediaDownloader() {
26
+ return {
27
+ async download(url) {
28
+ const res = await fetch(url);
29
+ if (!res.ok) {
30
+ throw new Error(`Media download failed: ${res.status}`);
31
+ }
32
+ const buffer = await res.arrayBuffer();
33
+ const mimeType = res.headers.get("content-type") ?? "audio/ogg";
34
+ return { data: new Uint8Array(buffer), mimeType };
35
+ },
36
+ };
37
+ }
38
+ export async function preprocessAudio(parts, stt, downloader) {
39
+ const result = [];
40
+ for (const part of parts) {
41
+ if (part.type !== "audio") {
42
+ result.push(part);
43
+ continue;
44
+ }
45
+ try {
46
+ let data;
47
+ let mimeType;
48
+ if (part.url) {
49
+ const downloaded = await downloader.download(part.url);
50
+ data = downloaded.data;
51
+ mimeType = downloaded.mimeType;
52
+ }
53
+ else if (part.data) {
54
+ // Base64-encoded audio
55
+ const binary = atob(part.data);
56
+ const bytes = new Uint8Array(binary.length);
57
+ for (let i = 0; i < binary.length; i++) {
58
+ bytes[i] = binary.charCodeAt(i);
59
+ }
60
+ data = bytes;
61
+ mimeType = part.mimeType;
62
+ }
63
+ else {
64
+ result.push({ type: "text", text: "[Voice note: transcription unavailable]" });
65
+ continue;
66
+ }
67
+ const transcription = await stt.transcribe(data, mimeType);
68
+ result.push({ type: "text", text: `[Voice note transcription]: ${transcription.text}` });
69
+ }
70
+ catch {
71
+ result.push({ type: "text", text: "[Voice note: transcription unavailable]" });
72
+ }
73
+ }
74
+ return result;
75
+ }
76
+ //# sourceMappingURL=audio-preprocessor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audio-preprocessor.js","sourceRoot":"","sources":["../../src/gateway/audio-preprocessor.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"auth-middleware.d.ts","sourceRoot":"","sources":["../../src/gateway/auth-middleware.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAG1C;;GAEG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAQ/F;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAQjG;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,GACjB,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAetD;AAID;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,EAAE,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAYlG"}
1
+ {"version":3,"file":"auth-middleware.d.ts","sourceRoot":"","sources":["../../src/gateway/auth-middleware.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAU1C;;GAEG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAQ/F;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CASjG;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,GACjB,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAetD;AAID;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,EAAE,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAYlG"}
@@ -1,13 +1,20 @@
1
1
  // Composable auth middleware for gateway routes
2
2
  // Each function returns a Hono middleware or utility for a specific auth mechanism
3
+ import { timingSafeEqual } from "node:crypto";
3
4
  import { verifyHmacSha256 } from "../utils/hmac.js";
5
+ /** Timing-safe string comparison. Returns false immediately for different lengths (safe — no content leak). */
6
+ function safeEqual(a, b) {
7
+ if (a.length !== b.length)
8
+ return false;
9
+ return timingSafeEqual(Buffer.from(a), Buffer.from(b));
10
+ }
4
11
  /**
5
12
  * Require API key via X-Api-Key header. Returns 401 if missing or invalid.
6
13
  */
7
14
  export function requireApiKey(key) {
8
15
  return async (c, next) => {
9
16
  const provided = c.req.header("x-api-key");
10
- if (!provided || provided !== key) {
17
+ if (!provided || !safeEqual(provided, key)) {
11
18
  return c.json({ error: "unauthorized", message: "Invalid or missing API key" }, 401);
12
19
  }
13
20
  return next();
@@ -19,7 +26,8 @@ export function requireApiKey(key) {
19
26
  export function requireBearer(token) {
20
27
  return async (c, next) => {
21
28
  const auth = c.req.header("authorization");
22
- if (!auth || auth !== `Bearer ${token}`) {
29
+ const expected = `Bearer ${token}`;
30
+ if (!auth || !safeEqual(auth, expected)) {
23
31
  return c.json({ error: "unauthorized", message: "Invalid or missing Bearer token" }, 401);
24
32
  }
25
33
  return next();
@@ -1 +1 @@
1
- {"version":3,"file":"auth-middleware.js","sourceRoot":"","sources":["../../src/gateway/auth-middleware.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,mFAAmF;AAGnF,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEpD;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,GAAW;IACvC,OAAO,KAAK,EAAE,CAAU,EAAE,IAAU,EAA4B,EAAE;QAChE,MAAM,QAAQ,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAC3C,IAAI,CAAC,QAAQ,IAAI,QAAQ,KAAK,GAAG,EAAE,CAAC;YAClC,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,4BAA4B,EAAE,EAAE,GAAG,CAAC,CAAC;QACvF,CAAC;QACD,OAAO,IAAI,EAAE,CAAC;IAChB,CAAC,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,KAAa;IACzC,OAAO,KAAK,EAAE,CAAU,EAAE,IAAU,EAA4B,EAAE;QAChE,MAAM,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;QAC3C,IAAI,CAAC,IAAI,IAAI,IAAI,KAAK,UAAU,KAAK,EAAE,EAAE,CAAC;YACxC,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,iCAAiC,EAAE,EAAE,GAAG,CAAC,CAAC;QAC5F,CAAC;QACD,OAAO,IAAI,EAAE,CAAC;IAChB,CAAC,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,uBAAuB,CACrC,MAAc,EACd,UAAkB;IAElB,OAAO,KAAK,EAAE,CAAU,EAAE,IAAU,EAA4B,EAAE;QAChE,MAAM,SAAS,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QAC3C,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,WAAW,UAAU,SAAS,EAAE,EAAE,GAAG,CAAC,CAAC;QACzF,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;QAChC,MAAM,GAAG,GAAG,SAAS,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAC7E,IAAI,CAAC,gBAAgB,CAAC,MAAM,EAAE,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC;YACzC,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,2BAA2B,EAAE,EAAE,GAAG,CAAC,CAAC;QACtF,CAAC;QAED,OAAO,IAAI,EAAE,CAAC;IAChB,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,mBAAmB,GAAG,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC,CAAC;AAEhE;;;;;;;GAOG;AACH,MAAM,UAAU,eAAe,CAAC,MAAqB,EAAE,cAAkC;IACvF,IAAI,CAAC,cAAc,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAChE,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAEzB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;QAC5B,IAAI,mBAAmB,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC;YAAE,OAAO,IAAI,CAAC;IACzD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,cAAc,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;AACzC,CAAC"}
1
+ {"version":3,"file":"auth-middleware.js","sourceRoot":"","sources":["../../src/gateway/auth-middleware.ts"],"names":[],"mappings":"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"}