@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
@@ -0,0 +1,411 @@
1
+ // Gateway: Email webhook routes -- Hono sub-app for inbound email processing
2
+ // Resolves tenant by recipient email address, processes messages via Mode B orchestrator, replies via EmailTransport
3
+ import { Hono } from "hono";
4
+ import { join } from "node:path";
5
+ import { mkdirSync } from "node:fs";
6
+ import { extractText, SqliteMemoryStore } from "@kilnai/core";
7
+ import { resolveAgentContextAsync } from "../tenant/agent-resolver.js";
8
+ import { checkBudget, reportUsage } from "./budget-middleware.js";
9
+ import { requireWebhookSignature } from "./auth-middleware.js";
10
+ import { TraceContext } from "./trace-context.js";
11
+ import { formatKnowledgeContext, formatContactContext, mergeContextSources } from "./context-formatter.js";
12
+ import { shouldRejectEmail } from "./email-loop-guard.js";
13
+ import { InMemoryEmailThreadStore } from "./email-thread-store.js";
14
+ import { renderEmailHtml, renderEmailPlainText } from "../channels/email-template.js";
15
+ /** Lazily-opened per-tenant memory stores. Keyed by tenantId. */
16
+ const memoryStores = new Map();
17
+ function getMemoryStore(memoryBasePath, tenantId) {
18
+ let store = memoryStores.get(tenantId);
19
+ if (store)
20
+ return store;
21
+ const dir = join(memoryBasePath, "memory");
22
+ mkdirSync(dir, { recursive: true });
23
+ store = new SqliteMemoryStore({
24
+ dbPath: join(dir, `${tenantId}.db`),
25
+ layer: "user",
26
+ tenantId,
27
+ });
28
+ memoryStores.set(tenantId, store);
29
+ return store;
30
+ }
31
+ /** Tool definition for knowledge_search -- injected when knowledge mode is "tool" */
32
+ const KNOWLEDGE_SEARCH_TOOL = {
33
+ name: "knowledge_search",
34
+ description: "Search the knowledge base for relevant information. Use this when the user asks a question that may be answered by stored documents or knowledge.",
35
+ inputSchema: {
36
+ type: "object",
37
+ properties: {
38
+ query: {
39
+ type: "string",
40
+ description: "The search query to find relevant knowledge.",
41
+ },
42
+ },
43
+ required: ["query"],
44
+ },
45
+ tags: new Set(["builtin"]),
46
+ };
47
+ /** Add Re: prefix to subject if not already present */
48
+ function replySubject(subject) {
49
+ const trimmed = subject.trim();
50
+ return /^re:/i.test(trimmed) ? trimmed : `Re: ${trimmed}`;
51
+ }
52
+ export function createEmailWebhookRoutes(config) {
53
+ const app = new Hono();
54
+ const threadStore = config.threadStore ?? new InMemoryEmailThreadStore();
55
+ // HMAC-SHA256 signature validation if webhook secret is configured
56
+ if (config.webhookSecret) {
57
+ app.use("/webhook", requireWebhookSignature(config.webhookSecret, "x-webhook-signature"));
58
+ }
59
+ // POST /webhook -- Incoming email from webhook provider
60
+ app.post("/webhook", async (c) => {
61
+ let payload;
62
+ try {
63
+ payload = await c.req.json();
64
+ }
65
+ catch {
66
+ return c.text("OK", 200);
67
+ }
68
+ const { from, to, subject, messageId, headers } = payload;
69
+ // Loop guard: reject auto-replies and system senders
70
+ const rejection = shouldRejectEmail(from, headers ?? {});
71
+ if (rejection.reject) {
72
+ const trace = new TraceContext();
73
+ trace.log("email", "Rejected inbound email", { from, reason: rejection.reason });
74
+ return c.text("OK", 200);
75
+ }
76
+ // Self-send detection: prevent loops from email forwarding
77
+ if (from.toLowerCase() === to.toLowerCase()) {
78
+ const trace = new TraceContext();
79
+ trace.log("email", "Rejected self-send", { from, to });
80
+ return c.text("OK", 200);
81
+ }
82
+ // Resolve tenant by recipient email address
83
+ const tenant = config.tenantRegistry
84
+ .resolveByEmailAddress(to, config.appName);
85
+ if (!tenant) {
86
+ const trace = new TraceContext();
87
+ trace.warn("email", "No tenant found", { to, appName: config.appName });
88
+ return c.text("OK", 200);
89
+ }
90
+ // Fire and forget -- process in background
91
+ const promise = processEmailMessage(config, threadStore, tenant.tenantId, from, to, subject ?? "(no subject)", messageId, payload);
92
+ promise.catch((err) => {
93
+ const failTrace = new TraceContext();
94
+ failTrace.warn("email", "Message processing failed", { error: String(err) });
95
+ });
96
+ return c.text("OK", 200);
97
+ });
98
+ return app;
99
+ }
100
+ async function processEmailMessage(config, threadStore, tenantId, senderEmail, _recipientEmail, subject, messageId, payload) {
101
+ const trace = new TraceContext();
102
+ trace.log("email", "Processing message", { tenantId, from: senderEmail, subject });
103
+ const tenant = config.tenantRegistry.get(tenantId);
104
+ if (!tenant)
105
+ return;
106
+ // Extract text content (prefer plain text over HTML)
107
+ const messageText = (payload.textBody ?? "").trim();
108
+ if (!messageText)
109
+ return;
110
+ const messageParts = [{ type: "text", text: messageText }];
111
+ // --- Thread tracking ---
112
+ const references = payload.references
113
+ ? payload.references.split(/\s+/).filter(Boolean)
114
+ : [];
115
+ const lookupRefs = payload.inReplyTo
116
+ ? [payload.inReplyTo, ...references]
117
+ : references;
118
+ let thread;
119
+ if (lookupRefs.length > 0) {
120
+ thread = threadStore.getByMessageId(payload.inReplyTo ?? "") ?? threadStore.getByReference(references);
121
+ }
122
+ if (thread) {
123
+ // Add this message to existing thread
124
+ thread.messageIds.push(messageId);
125
+ thread.lastActivityAt = new Date();
126
+ threadStore.save(thread);
127
+ }
128
+ else {
129
+ // Create new thread
130
+ thread = {
131
+ threadId: messageId,
132
+ tenantId,
133
+ senderEmail,
134
+ subject,
135
+ messageIds: [messageId],
136
+ createdAt: new Date(),
137
+ lastActivityAt: new Date(),
138
+ };
139
+ threadStore.save(thread);
140
+ }
141
+ const userId = `email:${senderEmail}`;
142
+ // --- Memory: recall past context about this user ---
143
+ let recalledMemory;
144
+ if (config.memoryBasePath) {
145
+ try {
146
+ const store = getMemoryStore(config.memoryBasePath, tenantId);
147
+ const query = `${senderEmail} ${messageText}`;
148
+ recalledMemory = await store.recall(query, 500) || undefined;
149
+ }
150
+ catch (err) {
151
+ trace.warn("email", "Memory recall failed", { tenantId, error: err instanceof Error ? err.message : String(err) });
152
+ }
153
+ }
154
+ // --- Knowledge: retrieve relevant context ---
155
+ let knowledgeContext;
156
+ if (config.knowledgePipeline && messageText.length > 0) {
157
+ const knowledgeMode = config.knowledgeMode ?? "auto";
158
+ if (knowledgeMode === "auto") {
159
+ try {
160
+ const results = await config.knowledgePipeline.retrieve(messageText, { topK: 5 });
161
+ knowledgeContext = formatKnowledgeContext(results);
162
+ }
163
+ catch (err) {
164
+ trace.warn("email", "Knowledge retrieval failed", { error: err instanceof Error ? err.message : String(err) });
165
+ }
166
+ }
167
+ }
168
+ // --- Contact memory: recall persistent facts about this user ---
169
+ let contactContext;
170
+ if (config.contactMemoryService) {
171
+ try {
172
+ const facts = await config.contactMemoryService.recall(senderEmail, tenantId);
173
+ contactContext = formatContactContext(facts);
174
+ }
175
+ catch (err) {
176
+ trace.warn("email", "Contact memory recall failed", { tenantId, error: err instanceof Error ? err.message : String(err) });
177
+ }
178
+ }
179
+ const combinedMemory = mergeContextSources(recalledMemory, knowledgeContext, contactContext);
180
+ // --- Tools: build per-call builtin tools ---
181
+ const callTools = new Map();
182
+ // Register knowledge_search tool for "tool" mode
183
+ if (config.knowledgePipeline && (config.knowledgeMode ?? "auto") === "tool") {
184
+ callTools.set("knowledge_search", async (input) => {
185
+ const query = String(input.query ?? "");
186
+ const results = await config.knowledgePipeline.retrieve(query, { topK: 5 });
187
+ return results.map((r) => ({ content: r.content, score: r.score }));
188
+ });
189
+ const hasKnowledgeTool = config.orchestrator.tools?.some((t) => t.name === "knowledge_search");
190
+ if (!hasKnowledgeTool) {
191
+ config.orchestrator.registerTools([KNOWLEDGE_SEARCH_TOOL]);
192
+ }
193
+ }
194
+ // Get or create session first (needed for ping-pong guard)
195
+ const session = await config.sessionRegistry.getOrCreate({
196
+ appName: config.appName,
197
+ tenantId,
198
+ userId,
199
+ systemPrompt: "",
200
+ idleTimeoutMs: tenant.idleTimeoutMs,
201
+ });
202
+ // Resolve agent context (multi-agent routing with ping-pong guard)
203
+ const agentCtx = await resolveAgentContextAsync(tenant, messageParts, session, { handoffSummarizer: config.handoffSummarizer, eventBus: config.eventBus }, "email", callTools);
204
+ // Update session with resolved prompt and agent
205
+ session.setSystemPrompt(agentCtx.systemPrompt);
206
+ if (agentCtx.activeAgentId) {
207
+ session.setActiveAgent(agentCtx.activeAgentId, agentCtx.handoffBrief);
208
+ }
209
+ const tenantToolCtx = agentCtx.tenantToolContext;
210
+ // Register webhook tool definitions on the orchestrator
211
+ if (tenantToolCtx.toolDefinitions.length > 0) {
212
+ config.orchestrator.registerTools(tenantToolCtx.toolDefinitions);
213
+ }
214
+ const perCallConfig = {
215
+ toolAllowlist: tenantToolCtx.toolAllowlist,
216
+ rateLimiter: tenantToolCtx.rateLimiter,
217
+ tenantId: tenant.tenantId,
218
+ additionalTools: tenantToolCtx.toolDefinitions.length > 0 ? tenantToolCtx.toolDefinitions : undefined,
219
+ };
220
+ // --- Budget check ---
221
+ const activeBilling = tenant.billing?.budgetEndpoint
222
+ ? tenant.billing
223
+ : config.billing;
224
+ if (activeBilling) {
225
+ const budgetResult = await checkBudget(activeBilling, tenantId);
226
+ if (!budgetResult.allowed) {
227
+ trace.log("email", "Budget exhausted", { tenantId, sender: senderEmail });
228
+ // Do not reply -- silently drop when budget exhausted for email
229
+ return;
230
+ }
231
+ }
232
+ // Emit MESSAGE_RECEIVED event (fire-and-forget)
233
+ if (config.eventEmitter) {
234
+ config.eventEmitter.emit({
235
+ eventType: "MESSAGE_RECEIVED",
236
+ tenantId,
237
+ channel: "email",
238
+ externalUserId: senderEmail,
239
+ messageContent: messageText,
240
+ messageRole: "USER",
241
+ traceId: trace.traceId,
242
+ timestamp: new Date().toISOString(),
243
+ });
244
+ }
245
+ let replyText;
246
+ try {
247
+ const result = await config.orchestrator.processMessage(session, messageParts, combinedMemory, tenantToolCtx.callBuiltinTools.size > 0 ? tenantToolCtx.callBuiltinTools : undefined, perCallConfig);
248
+ // Persist mutated session
249
+ await config.sessionRegistry.save(session);
250
+ // Emit handoff events when message was queued
251
+ if (result.queued && config.eventEmitter) {
252
+ config.eventEmitter.emit({
253
+ eventType: "HANDOFF_MESSAGE_QUEUED",
254
+ tenantId,
255
+ channel: "email",
256
+ externalUserId: senderEmail,
257
+ sessionMode: session.sessionMode,
258
+ traceId: trace.traceId,
259
+ timestamp: new Date().toISOString(),
260
+ });
261
+ }
262
+ // Emit escalation event when detected
263
+ if (result.escalation && config.eventEmitter) {
264
+ config.eventEmitter.emit({
265
+ eventType: "ESCALATION_DETECTED",
266
+ tenantId,
267
+ channel: "email",
268
+ externalUserId: senderEmail,
269
+ escalationReason: result.escalation.reason,
270
+ escalationDetail: result.escalation.detail,
271
+ summary: result.contextSummary,
272
+ sessionMode: session.sessionMode,
273
+ traceId: trace.traceId,
274
+ timestamp: new Date().toISOString(),
275
+ });
276
+ }
277
+ // Emit TOOL_EXECUTED events
278
+ if (result.toolExecutions && config.eventEmitter) {
279
+ for (const exec of result.toolExecutions) {
280
+ config.eventEmitter.emit({
281
+ eventType: "TOOL_EXECUTED",
282
+ tenantId,
283
+ channel: "email",
284
+ externalUserId: senderEmail,
285
+ toolName: exec.toolName,
286
+ durationMs: exec.durationMs,
287
+ success: exec.success,
288
+ resultSummary: exec.resultSummary,
289
+ traceId: trace.traceId,
290
+ timestamp: new Date().toISOString(),
291
+ });
292
+ }
293
+ }
294
+ // Emit AGENT_ROUTED when multi-agent routing is active
295
+ if (agentCtx.activeAgentId && config.eventEmitter) {
296
+ config.eventEmitter.emit({
297
+ eventType: "AGENT_ROUTED",
298
+ tenantId,
299
+ channel: "email",
300
+ externalUserId: senderEmail,
301
+ activeAgentId: agentCtx.activeAgentId,
302
+ activeAgentName: agentCtx.activeAgentName,
303
+ routingTier: agentCtx.routingResult?.tier,
304
+ routingConfidence: agentCtx.routingResult?.confidence,
305
+ traceId: trace.traceId,
306
+ timestamp: new Date().toISOString(),
307
+ });
308
+ }
309
+ // Emit AGENT_HANDOFF when an agent switch occurred (or was blocked)
310
+ if ((agentCtx.isHandoff || agentCtx.pingPongBlocked) && config.eventEmitter) {
311
+ const fromAgent = tenant.agents?.find((a) => a.id === agentCtx.previousAgentId);
312
+ const toAgent = tenant.agents?.find((a) => a.id === agentCtx.activeAgentId);
313
+ config.eventEmitter.emit({
314
+ eventType: "AGENT_HANDOFF",
315
+ tenantId,
316
+ channel: "email",
317
+ externalUserId: senderEmail,
318
+ fromAgentId: agentCtx.previousAgentId,
319
+ fromAgentName: fromAgent?.name,
320
+ toAgentId: agentCtx.activeAgentId,
321
+ toAgentName: toAgent?.name,
322
+ handoffBrief: agentCtx.handoffBrief,
323
+ handoffBlocked: agentCtx.pingPongBlocked,
324
+ handoffBlockReason: agentCtx.pingPongReason,
325
+ traceId: trace.traceId,
326
+ timestamp: new Date().toISOString(),
327
+ });
328
+ }
329
+ replyText = extractText(result.parts);
330
+ // Report usage (fire-and-forget)
331
+ if (activeBilling) {
332
+ reportUsage(activeBilling, {
333
+ tenantId,
334
+ messages: 1,
335
+ tokens: result.inputTokens + result.outputTokens,
336
+ model: config.orchestrator.model ?? "unknown",
337
+ });
338
+ }
339
+ // Emit MESSAGE_SENT event (fire-and-forget)
340
+ if (config.eventEmitter) {
341
+ config.eventEmitter.emit({
342
+ eventType: "MESSAGE_SENT",
343
+ tenantId,
344
+ channel: "email",
345
+ externalUserId: senderEmail,
346
+ messageContent: replyText,
347
+ messageRole: "ASSISTANT",
348
+ traceId: trace.traceId,
349
+ timestamp: new Date().toISOString(),
350
+ });
351
+ }
352
+ }
353
+ catch (err) {
354
+ trace.error("email", "Orchestrator error", { tenantId, error: err instanceof Error ? err.message : String(err) });
355
+ replyText = "Something went wrong. Please try again.";
356
+ }
357
+ // --- Send reply email ---
358
+ if (config.emailTransport) {
359
+ try {
360
+ const fromAddress = tenant.emailFromAddress ?? tenant.emailAddress ?? config.defaultFromAddress;
361
+ if (!fromAddress) {
362
+ trace.warn("email", "No from address configured", { tenantId });
363
+ }
364
+ else {
365
+ const branding = {
366
+ businessName: tenant.businessName ?? tenant.name,
367
+ };
368
+ const replySubj = replySubject(subject);
369
+ const threadRefs = thread.messageIds.join(" ");
370
+ const sendResult = await config.emailTransport.send({
371
+ from: fromAddress,
372
+ fromName: tenant.emailFromName ?? tenant.businessName ?? tenant.name ?? config.defaultFromName,
373
+ to: senderEmail,
374
+ subject: replySubj,
375
+ htmlBody: renderEmailHtml(replyText, branding),
376
+ textBody: renderEmailPlainText(replyText),
377
+ inReplyTo: messageId,
378
+ references: threadRefs,
379
+ headers: {
380
+ "Auto-Submitted": "auto-replied",
381
+ "X-Auto-Response-Suppress": "All",
382
+ },
383
+ });
384
+ // Update thread with outbound messageId
385
+ if (sendResult.messageId) {
386
+ thread.messageIds.push(sendResult.messageId);
387
+ thread.lastActivityAt = new Date();
388
+ threadStore.save(thread);
389
+ }
390
+ }
391
+ }
392
+ catch (err) {
393
+ trace.warn("email", "Failed to send reply", { tenantId, recipient: senderEmail, error: err instanceof Error ? err.message : String(err) });
394
+ }
395
+ }
396
+ // --- Memory: save what was learned from this exchange ---
397
+ if (config.memoryBasePath && messageText.length > 5) {
398
+ try {
399
+ const store = getMemoryStore(config.memoryBasePath, tenantId);
400
+ await store.save({
401
+ layer: "user",
402
+ content: `[${senderEmail}] User: ${messageText}\nAssistant: ${replyText}`,
403
+ tags: [senderEmail],
404
+ });
405
+ }
406
+ catch (err) {
407
+ trace.warn("email", "Memory save failed", { tenantId, error: err instanceof Error ? err.message : String(err) });
408
+ }
409
+ }
410
+ }
411
+ //# sourceMappingURL=email-webhook-routes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"email-webhook-routes.js","sourceRoot":"","sources":["../../src/gateway/email-webhook-routes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import { Hono } from "hono";
2
+ import type { EnrichmentStore } from "@kilnai/core";
3
+ export interface EnrichmentAdminRoutesConfig {
4
+ readonly enrichmentStore: EnrichmentStore;
5
+ readonly appName: string;
6
+ readonly adminToken?: string;
7
+ }
8
+ export declare function createEnrichmentAdminRoutes(config: EnrichmentAdminRoutesConfig): Hono;
9
+ //# sourceMappingURL=enrichment-admin-routes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enrichment-admin-routes.d.ts","sourceRoot":"","sources":["../../src/gateway/enrichment-admin-routes.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAGpD,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,eAAe,EAAE,eAAe,CAAC;IAC1C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,2BAA2B,GAAG,IAAI,CAwCrF"}
@@ -0,0 +1,41 @@
1
+ // Gateway: Enrichment admin routes -- Hono sub-app for enrichment data access and GDPR deletion
2
+ // Follows knowledge-admin-routes.ts pattern
3
+ import { Hono } from "hono";
4
+ import { requireBearer } from "./auth-middleware.js";
5
+ export function createEnrichmentAdminRoutes(config) {
6
+ const app = new Hono();
7
+ if (config.adminToken) {
8
+ app.use("*", requireBearer(config.adminToken));
9
+ }
10
+ // GET /enrichment/:sessionId -- get enrichment for a specific session
11
+ app.get("/enrichment/:sessionId", async (c) => {
12
+ const sessionId = c.req.param("sessionId");
13
+ const enrichment = await config.enrichmentStore.get(sessionId);
14
+ if (!enrichment) {
15
+ return c.json({ error: "Enrichment not found" }, 404);
16
+ }
17
+ return c.json(enrichment);
18
+ });
19
+ // GET /enrichment?tenantId=xxx&limit=50&cursor=xxx -- list enrichments for a tenant
20
+ app.get("/enrichment", async (c) => {
21
+ const tenantId = c.req.query("tenantId");
22
+ if (!tenantId) {
23
+ return c.json({ error: "Missing required query parameter: tenantId" }, 400);
24
+ }
25
+ const limit = parseInt(c.req.query("limit") ?? "50", 10);
26
+ const cursor = c.req.query("cursor");
27
+ const result = await config.enrichmentStore.listByTenant(tenantId, limit, cursor);
28
+ return c.json(result);
29
+ });
30
+ // DELETE /enrichment/:sessionId -- GDPR delete enrichment
31
+ app.delete("/enrichment/:sessionId", async (c) => {
32
+ const sessionId = c.req.param("sessionId");
33
+ const deleted = await config.enrichmentStore.delete(sessionId);
34
+ if (!deleted) {
35
+ return c.json({ error: "Enrichment not found" }, 404);
36
+ }
37
+ return c.json({ deleted: true });
38
+ });
39
+ return app;
40
+ }
41
+ //# sourceMappingURL=enrichment-admin-routes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enrichment-admin-routes.js","sourceRoot":"","sources":["../../src/gateway/enrichment-admin-routes.ts"],"names":[],"mappings":"AAAA,gGAAgG;AAChG,4CAA4C;AAE5C,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAQrD,MAAM,UAAU,2BAA2B,CAAC,MAAmC;IAC7E,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IAEvB,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;QACtB,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,aAAa,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC;IACjD,CAAC;IAED,sEAAsE;IACtE,GAAG,CAAC,GAAG,CAAC,wBAAwB,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QAC5C,MAAM,SAAS,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QAC3C,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC/D,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,sBAAsB,EAAE,EAAE,GAAG,CAAC,CAAC;QACxD,CAAC;QACD,OAAO,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;IAEH,oFAAoF;IACpF,GAAG,CAAC,GAAG,CAAC,aAAa,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QACjC,MAAM,QAAQ,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QACzC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,4CAA4C,EAAE,EAAE,GAAG,CAAC,CAAC;QAC9E,CAAC;QACD,MAAM,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC,CAAC;QACzD,MAAM,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QACrC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,YAAY,CAAC,QAAQ,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;QAClF,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACxB,CAAC,CAAC,CAAC;IAEH,0DAA0D;IAC1D,GAAG,CAAC,MAAM,CAAC,wBAAwB,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QAC/C,MAAM,SAAS,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QAC3C,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAC/D,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,sBAAsB,EAAE,EAAE,GAAG,CAAC,CAAC;QACxD,CAAC;QACD,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -1,5 +1,5 @@
1
1
  import { Hono } from "hono";
2
- import type { App } from "@kilnai/core";
2
+ import type { App, SttAdapter, ContactMemoryService } from "@kilnai/core";
3
3
  import type { GatewayAppBinding, SecurityConfig, AuditLog } from "@kilnai/core";
4
4
  import type { ChannelRegistry } from "../channels/channel-registry.js";
5
5
  import type { WebChannel } from "../channels/web-channel.js";
@@ -8,13 +8,20 @@ import type { WsRoutesConfig } from "./ws-routes.js";
8
8
  import type { DelegationRegistry } from "./delegation-handler.js";
9
9
  import type { TenantAppRuntime } from "./tenant-routes.js";
10
10
  import type { WhatsAppWebhookConfig } from "./whatsapp-webhook-routes.js";
11
+ import type { InstagramWebhookConfig } from "./instagram-webhook-routes.js";
12
+ import type { MessengerWebhookConfig } from "./messenger-webhook-routes.js";
13
+ import type { EmailWebhookConfig } from "./email-webhook-routes.js";
11
14
  import type { TenantAdminRoutesConfig } from "./tenant-admin-routes.js";
15
+ import type { KnowledgeAdminRoutesConfig } from "./knowledge-admin-routes.js";
16
+ import type { ContactMemoryAdminRoutesConfig } from "./contact-memory-admin-routes.js";
17
+ import type { EnrichmentAdminRoutesConfig } from "./enrichment-admin-routes.js";
12
18
  import { HealthRegistry } from "./health-registry.js";
13
19
  import type { SafetyPipeline } from "@kilnai/core";
14
20
  import type { DevRoutesConfig } from "./dev-routes.js";
15
21
  import type { MemoryRoutesConfig } from "./memory-routes.js";
16
22
  import type { TriggerRegistry } from "../trigger/trigger-registry.js";
17
23
  import type { ConversationEventEmitter } from "./conversation-event-emitter.js";
24
+ import type { KnowledgePipelineResult } from "./knowledge-factory.js";
18
25
  export interface LoadedApp {
19
26
  readonly name: string;
20
27
  readonly app: App;
@@ -23,9 +30,18 @@ export interface LoadedApp {
23
30
  modeBRuntime?: ModeBAppRuntime;
24
31
  tenantRuntime?: TenantAppRuntime;
25
32
  whatsappWebhookConfig?: WhatsAppWebhookConfig;
33
+ instagramWebhookConfig?: InstagramWebhookConfig;
34
+ messengerWebhookConfig?: MessengerWebhookConfig;
35
+ emailWebhookConfig?: EmailWebhookConfig;
26
36
  tenantAdminConfig?: TenantAdminRoutesConfig;
27
37
  webChannel?: WebChannel;
28
38
  eventEmitter?: ConversationEventEmitter;
39
+ sttAdapter?: SttAdapter;
40
+ knowledgePipeline?: KnowledgePipelineResult;
41
+ knowledgeAdminConfig?: KnowledgeAdminRoutesConfig;
42
+ contactMemoryService?: ContactMemoryService;
43
+ contactMemoryAdminConfig?: ContactMemoryAdminRoutesConfig;
44
+ enrichmentAdminConfig?: EnrichmentAdminRoutesConfig;
29
45
  }
30
46
  export interface GatewayServerConfig {
31
47
  readonly port: number;
@@ -1 +1 @@
1
- {"version":3,"file":"gateway-routes.d.ts","sourceRoot":"","sources":["../../src/gateway/gateway-routes.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAEhF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAE1D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAGrD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAElE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAE3D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAE1E,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAGxE,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAGtD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAGvD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAE7D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACtE,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,iCAAiC,CAAC;AAEhF,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;IAClB,QAAQ,CAAC,OAAO,EAAE,iBAAiB,CAAC;IACpC,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC;IACnC,YAAY,CAAC,EAAE,eAAe,CAAC;IAC/B,aAAa,CAAC,EAAE,gBAAgB,CAAC;IACjC,qBAAqB,CAAC,EAAE,qBAAqB,CAAC;IAC9C,iBAAiB,CAAC,EAAE,uBAAuB,CAAC;IAC5C,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,YAAY,CAAC,EAAE,wBAAwB,CAAC;CACzC;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,SAAS,SAAS,EAAE,CAAC;IACpC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;IACjD,QAAQ,CAAC,cAAc,CAAC,EAAE,cAAc,CAAC;IACzC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,cAAc,CAAC,EAAE,cAAc,CAAC;IACzC,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC;IAC7B,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,eAAe,CAAC,EAAE,eAAe,CAAC;IAC3C,QAAQ,CAAC,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;IACjD,QAAQ,CAAC,eAAe,CAAC,EAAE,eAAe,CAAC;IAC3C,QAAQ,CAAC,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IACvD,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,cAAc,CAAC,kBAAkB,CAAC,CAAC;IAC/D,QAAQ,CAAC,aAAa,CAAC,EAAE,cAAc,CAAC,eAAe,CAAC,CAAC;CAC1D;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,mBAAmB,GAAG,IAAI,CAiKlE"}
1
+ {"version":3,"file":"gateway-routes.d.ts","sourceRoot":"","sources":["../../src/gateway/gateway-routes.ts"],"names":[],"mappings":"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"}
@@ -8,8 +8,15 @@ import { createWsTenantRoutes } from "./ws-tenant-routes.js";
8
8
  import { createDelegationRoutes } from "./delegation-routes.js";
9
9
  import { createTenantRoutes } from "./tenant-routes.js";
10
10
  import { createWhatsAppWebhookRoutes } from "./whatsapp-webhook-routes.js";
11
+ import { createInstagramWebhookRoutes } from "./instagram-webhook-routes.js";
12
+ import { createMessengerWebhookRoutes } from "./messenger-webhook-routes.js";
13
+ import { createEmailWebhookRoutes } from "./email-webhook-routes.js";
11
14
  import { createTenantAdminRoutes } from "./tenant-admin-routes.js";
15
+ import { createKnowledgeAdminRoutes } from "./knowledge-admin-routes.js";
16
+ import { createContactMemoryAdminRoutes } from "./contact-memory-admin-routes.js";
17
+ import { createEnrichmentAdminRoutes } from "./enrichment-admin-routes.js";
12
18
  import { createOutboundRoutes } from "./outbound-routes.js";
19
+ import { createHandoffRoutes } from "./handoff-routes.js";
13
20
  import { HealthRegistry } from "./health-registry.js";
14
21
  import { securityMiddleware } from "./security-middleware.js";
15
22
  import { safetyMiddleware } from "./safety-middleware.js";
@@ -100,6 +107,21 @@ export function createGatewayApp(config) {
100
107
  const webhookApp = createWhatsAppWebhookRoutes(loadedApp.whatsappWebhookConfig);
101
108
  app.route(`/whatsapp/${loadedApp.name}`, webhookApp);
102
109
  }
110
+ // Instagram webhook routes for multi-tenant apps
111
+ if (channel.type === "instagram" && loadedApp.instagramWebhookConfig) {
112
+ const igWebhookApp = createInstagramWebhookRoutes(loadedApp.instagramWebhookConfig);
113
+ app.route(`/instagram/${loadedApp.name}`, igWebhookApp);
114
+ }
115
+ // Messenger webhook routes for multi-tenant apps
116
+ if (channel.type === "messenger" && loadedApp.messengerWebhookConfig) {
117
+ const msgWebhookApp = createMessengerWebhookRoutes(loadedApp.messengerWebhookConfig);
118
+ app.route(`/messenger/${loadedApp.name}`, msgWebhookApp);
119
+ }
120
+ // Email webhook routes for multi-tenant apps
121
+ if (channel.type === "email" && loadedApp.emailWebhookConfig) {
122
+ const emailWebhookApp = createEmailWebhookRoutes(loadedApp.emailWebhookConfig);
123
+ app.route(`/email/${loadedApp.name}`, emailWebhookApp);
124
+ }
103
125
  // WebSocket route for web channel
104
126
  if (channel.type === "web" && loadedApp.webChannel && config.upgradeWebSocket) {
105
127
  if (loadedApp.tenantRuntime) {
@@ -114,6 +136,10 @@ export function createGatewayApp(config) {
114
136
  billing: tenantRuntime.billing,
115
137
  eventEmitter: loadedApp.eventEmitter,
116
138
  allowedOrigins: channel.allowedOrigins,
139
+ sttAdapter: loadedApp.sttAdapter,
140
+ knowledgePipeline: loadedApp.knowledgePipeline?.pipeline,
141
+ knowledgeMode: loadedApp.app.knowledge?.mode,
142
+ contactMemoryService: loadedApp.contactMemoryService,
117
143
  });
118
144
  app.route(`/apps/${loadedApp.name}`, wsTenantApp);
119
145
  }
@@ -125,7 +151,7 @@ export function createGatewayApp(config) {
125
151
  validateToken: config.validateToken,
126
152
  apiKey: runtime.apiKey,
127
153
  processMessage: async (userId, parts) => {
128
- const session = runtime.sessionRegistry.getOrCreate({
154
+ const session = await runtime.sessionRegistry.getOrCreate({
129
155
  appName: loadedApp.name,
130
156
  userId,
131
157
  systemPrompt: runtime.systemPrompt,
@@ -148,6 +174,34 @@ export function createGatewayApp(config) {
148
174
  adminToken: loadedApp.tenantAdminConfig.adminToken,
149
175
  });
150
176
  app.route(`/outbound/${loadedApp.name}`, outboundApp);
177
+ // Handoff routes for multi-tenant apps (operator messaging, session transitions)
178
+ const sessionRegistry = loadedApp.tenantRuntime?.sessionRegistry ?? loadedApp.modeBRuntime?.sessionRegistry;
179
+ if (sessionRegistry) {
180
+ const handoffApp = createHandoffRoutes({
181
+ sessionRegistry,
182
+ tenantRegistry: loadedApp.tenantAdminConfig.tenantRegistry,
183
+ appName: loadedApp.name,
184
+ adminToken: loadedApp.tenantAdminConfig.adminToken,
185
+ webChannel: loadedApp.webChannel,
186
+ eventEmitter: loadedApp.eventEmitter,
187
+ });
188
+ app.route(`/handoff/${loadedApp.name}`, handoffApp);
189
+ }
190
+ }
191
+ // Knowledge admin routes (available for any app with knowledge config)
192
+ if (loadedApp.knowledgeAdminConfig) {
193
+ const knowledgeAdminApp = createKnowledgeAdminRoutes(loadedApp.knowledgeAdminConfig);
194
+ app.route(`/admin/${loadedApp.name}/knowledge`, knowledgeAdminApp);
195
+ }
196
+ // Contact memory admin routes (GDPR: forget, forgetAll)
197
+ if (loadedApp.contactMemoryAdminConfig) {
198
+ const contactMemoryAdminApp = createContactMemoryAdminRoutes(loadedApp.contactMemoryAdminConfig);
199
+ app.route(`/admin/${loadedApp.name}/contact-memory`, contactMemoryAdminApp);
200
+ }
201
+ // Enrichment admin routes (GDPR: get, list, delete)
202
+ if (loadedApp.enrichmentAdminConfig) {
203
+ const enrichmentAdminApp = createEnrichmentAdminRoutes(loadedApp.enrichmentAdminConfig);
204
+ app.route(`/admin/${loadedApp.name}/enrichment`, enrichmentAdminApp);
151
205
  }
152
206
  }
153
207
  // Mount webhook trigger routes per app