@kilnai/runtime 0.1.16 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (211) hide show
  1. package/README.md +2 -2
  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/enrichment/enrichment-runner.d.ts +17 -0
  35. package/dist/enrichment/enrichment-runner.d.ts.map +1 -0
  36. package/dist/enrichment/enrichment-runner.js +45 -0
  37. package/dist/enrichment/enrichment-runner.js.map +1 -0
  38. package/dist/enrichment/sqlite-enrichment-store.d.ts +14 -0
  39. package/dist/enrichment/sqlite-enrichment-store.d.ts.map +1 -0
  40. package/dist/enrichment/sqlite-enrichment-store.js +69 -0
  41. package/dist/enrichment/sqlite-enrichment-store.js.map +1 -0
  42. package/dist/gateway/audio-preprocessor.d.ts +11 -0
  43. package/dist/gateway/audio-preprocessor.d.ts.map +1 -0
  44. package/dist/gateway/audio-preprocessor.js +76 -0
  45. package/dist/gateway/audio-preprocessor.js.map +1 -0
  46. package/dist/gateway/auth-middleware.d.ts.map +1 -1
  47. package/dist/gateway/auth-middleware.js +10 -2
  48. package/dist/gateway/auth-middleware.js.map +1 -1
  49. package/dist/gateway/contact-memory-admin-routes.d.ts +9 -0
  50. package/dist/gateway/contact-memory-admin-routes.d.ts.map +1 -0
  51. package/dist/gateway/contact-memory-admin-routes.js +42 -0
  52. package/dist/gateway/contact-memory-admin-routes.js.map +1 -0
  53. package/dist/gateway/context-formatter.d.ts +5 -0
  54. package/dist/gateway/context-formatter.d.ts.map +1 -0
  55. package/dist/gateway/context-formatter.js +16 -0
  56. package/dist/gateway/context-formatter.js.map +1 -0
  57. package/dist/gateway/conversation-event-emitter.d.ts +4 -1
  58. package/dist/gateway/conversation-event-emitter.d.ts.map +1 -1
  59. package/dist/gateway/conversation-event-emitter.js +44 -13
  60. package/dist/gateway/conversation-event-emitter.js.map +1 -1
  61. package/dist/gateway/dev-routes.js +1 -1
  62. package/dist/gateway/dev-routes.js.map +1 -1
  63. package/dist/gateway/email-loop-guard.d.ts +10 -0
  64. package/dist/gateway/email-loop-guard.d.ts.map +1 -0
  65. package/dist/gateway/email-loop-guard.js +39 -0
  66. package/dist/gateway/email-loop-guard.js.map +1 -0
  67. package/dist/gateway/email-thread-store.d.ts +24 -0
  68. package/dist/gateway/email-thread-store.d.ts.map +1 -0
  69. package/dist/gateway/email-thread-store.js +34 -0
  70. package/dist/gateway/email-thread-store.js.map +1 -0
  71. package/dist/gateway/email-webhook-routes.d.ts +32 -0
  72. package/dist/gateway/email-webhook-routes.d.ts.map +1 -0
  73. package/dist/gateway/email-webhook-routes.js +411 -0
  74. package/dist/gateway/email-webhook-routes.js.map +1 -0
  75. package/dist/gateway/enrichment-admin-routes.d.ts +9 -0
  76. package/dist/gateway/enrichment-admin-routes.d.ts.map +1 -0
  77. package/dist/gateway/enrichment-admin-routes.js +41 -0
  78. package/dist/gateway/enrichment-admin-routes.js.map +1 -0
  79. package/dist/gateway/gateway-routes.d.ts +17 -1
  80. package/dist/gateway/gateway-routes.d.ts.map +1 -1
  81. package/dist/gateway/gateway-routes.js +41 -0
  82. package/dist/gateway/gateway-routes.js.map +1 -1
  83. package/dist/gateway/gateway-server.d.ts.map +1 -1
  84. package/dist/gateway/gateway-server.js +248 -12
  85. package/dist/gateway/gateway-server.js.map +1 -1
  86. package/dist/gateway/handoff-routes.d.ts.map +1 -1
  87. package/dist/gateway/handoff-routes.js +39 -0
  88. package/dist/gateway/handoff-routes.js.map +1 -1
  89. package/dist/gateway/instagram-webhook-routes.d.ts +30 -0
  90. package/dist/gateway/instagram-webhook-routes.d.ts.map +1 -0
  91. package/dist/gateway/instagram-webhook-routes.js +394 -0
  92. package/dist/gateway/instagram-webhook-routes.js.map +1 -0
  93. package/dist/gateway/knowledge-admin-routes.d.ts +9 -0
  94. package/dist/gateway/knowledge-admin-routes.d.ts.map +1 -0
  95. package/dist/gateway/knowledge-admin-routes.js +84 -0
  96. package/dist/gateway/knowledge-admin-routes.js.map +1 -0
  97. package/dist/gateway/knowledge-factory.d.ts +19 -0
  98. package/dist/gateway/knowledge-factory.d.ts.map +1 -0
  99. package/dist/gateway/knowledge-factory.js +122 -0
  100. package/dist/gateway/knowledge-factory.js.map +1 -0
  101. package/dist/gateway/message-pipeline.d.ts +22 -2
  102. package/dist/gateway/message-pipeline.d.ts.map +1 -1
  103. package/dist/gateway/message-pipeline.js +90 -4
  104. package/dist/gateway/message-pipeline.js.map +1 -1
  105. package/dist/gateway/messenger-webhook-routes.d.ts +30 -0
  106. package/dist/gateway/messenger-webhook-routes.d.ts.map +1 -0
  107. package/dist/gateway/messenger-webhook-routes.js +394 -0
  108. package/dist/gateway/messenger-webhook-routes.js.map +1 -0
  109. package/dist/gateway/meta-webhook-foundation.d.ts +12 -0
  110. package/dist/gateway/meta-webhook-foundation.d.ts.map +1 -0
  111. package/dist/gateway/meta-webhook-foundation.js +25 -0
  112. package/dist/gateway/meta-webhook-foundation.js.map +1 -0
  113. package/dist/gateway/mode-b-routes.d.ts +8 -0
  114. package/dist/gateway/mode-b-routes.d.ts.map +1 -1
  115. package/dist/gateway/mode-b-routes.js +53 -2
  116. package/dist/gateway/mode-b-routes.js.map +1 -1
  117. package/dist/gateway/outbound-routes.d.ts.map +1 -1
  118. package/dist/gateway/outbound-routes.js +49 -21
  119. package/dist/gateway/outbound-routes.js.map +1 -1
  120. package/dist/gateway/routing-test-routes.d.ts +10 -0
  121. package/dist/gateway/routing-test-routes.d.ts.map +1 -0
  122. package/dist/gateway/routing-test-routes.js +76 -0
  123. package/dist/gateway/routing-test-routes.js.map +1 -0
  124. package/dist/gateway/sqlite-email-thread-store.d.ts +13 -0
  125. package/dist/gateway/sqlite-email-thread-store.d.ts.map +1 -0
  126. package/dist/gateway/sqlite-email-thread-store.js +66 -0
  127. package/dist/gateway/sqlite-email-thread-store.js.map +1 -0
  128. package/dist/gateway/stt-factory.d.ts +3 -0
  129. package/dist/gateway/stt-factory.d.ts.map +1 -0
  130. package/dist/gateway/stt-factory.js +21 -0
  131. package/dist/gateway/stt-factory.js.map +1 -0
  132. package/dist/gateway/tenant-admin-routes.d.ts +1 -1
  133. package/dist/gateway/tenant-admin-routes.d.ts.map +1 -1
  134. package/dist/gateway/tenant-admin-routes.js +16 -2
  135. package/dist/gateway/tenant-admin-routes.js.map +1 -1
  136. package/dist/gateway/tenant-tool-factory.d.ts +10 -0
  137. package/dist/gateway/tenant-tool-factory.d.ts.map +1 -0
  138. package/dist/gateway/tenant-tool-factory.js +55 -0
  139. package/dist/gateway/tenant-tool-factory.js.map +1 -0
  140. package/dist/gateway/webhook-dedup.d.ts +13 -0
  141. package/dist/gateway/webhook-dedup.d.ts.map +1 -0
  142. package/dist/gateway/webhook-dedup.js +37 -0
  143. package/dist/gateway/webhook-dedup.js.map +1 -0
  144. package/dist/gateway/webhook-tool-executor.d.ts +17 -0
  145. package/dist/gateway/webhook-tool-executor.d.ts.map +1 -0
  146. package/dist/gateway/webhook-tool-executor.js +69 -0
  147. package/dist/gateway/webhook-tool-executor.js.map +1 -0
  148. package/dist/gateway/whatsapp-webhook-routes.d.ts +11 -0
  149. package/dist/gateway/whatsapp-webhook-routes.d.ts.map +1 -1
  150. package/dist/gateway/whatsapp-webhook-routes.js +158 -22
  151. package/dist/gateway/whatsapp-webhook-routes.js.map +1 -1
  152. package/dist/gateway/ws-tenant-routes.d.ts +9 -0
  153. package/dist/gateway/ws-tenant-routes.d.ts.map +1 -1
  154. package/dist/gateway/ws-tenant-routes.js +149 -6
  155. package/dist/gateway/ws-tenant-routes.js.map +1 -1
  156. package/dist/index.d.ts +47 -3
  157. package/dist/index.d.ts.map +1 -1
  158. package/dist/index.js +28 -1
  159. package/dist/index.js.map +1 -1
  160. package/dist/observability/composite-event-store.d.ts +13 -0
  161. package/dist/observability/composite-event-store.d.ts.map +1 -0
  162. package/dist/observability/composite-event-store.js +37 -0
  163. package/dist/observability/composite-event-store.js.map +1 -0
  164. package/dist/observability/prometheus-collector.d.ts +33 -0
  165. package/dist/observability/prometheus-collector.d.ts.map +1 -0
  166. package/dist/observability/prometheus-collector.js +169 -0
  167. package/dist/observability/prometheus-collector.js.map +1 -0
  168. package/dist/session/agent-handoff-summarizer.d.ts +11 -0
  169. package/dist/session/agent-handoff-summarizer.d.ts.map +1 -0
  170. package/dist/session/agent-handoff-summarizer.js +26 -0
  171. package/dist/session/agent-handoff-summarizer.js.map +1 -0
  172. package/dist/session/mode-b-orchestrator.d.ts +47 -1
  173. package/dist/session/mode-b-orchestrator.d.ts.map +1 -1
  174. package/dist/session/mode-b-orchestrator.js +286 -18
  175. package/dist/session/mode-b-orchestrator.js.map +1 -1
  176. package/dist/session/mode-b-session.d.ts +24 -4
  177. package/dist/session/mode-b-session.d.ts.map +1 -1
  178. package/dist/session/mode-b-session.js +37 -4
  179. package/dist/session/mode-b-session.js.map +1 -1
  180. package/dist/session/session-registry.d.ts +3 -2
  181. package/dist/session/session-registry.d.ts.map +1 -1
  182. package/dist/session/session-registry.js +35 -2
  183. package/dist/session/session-registry.js.map +1 -1
  184. package/dist/session/session-serializer.d.ts.map +1 -1
  185. package/dist/session/session-serializer.js +4 -0
  186. package/dist/session/session-serializer.js.map +1 -1
  187. package/dist/tenant/agent-resolver.d.ts +26 -0
  188. package/dist/tenant/agent-resolver.d.ts.map +1 -0
  189. package/dist/tenant/agent-resolver.js +232 -0
  190. package/dist/tenant/agent-resolver.js.map +1 -0
  191. package/dist/tenant/ping-pong-guard.d.ts +9 -0
  192. package/dist/tenant/ping-pong-guard.d.ts.map +1 -0
  193. package/dist/tenant/ping-pong-guard.js +30 -0
  194. package/dist/tenant/ping-pong-guard.js.map +1 -0
  195. package/dist/tenant/system-prompt-builder.d.ts +1 -1
  196. package/dist/tenant/system-prompt-builder.d.ts.map +1 -1
  197. package/dist/tenant/system-prompt-builder.js +13 -1
  198. package/dist/tenant/system-prompt-builder.js.map +1 -1
  199. package/dist/tenant/tenant-registry.d.ts +3 -0
  200. package/dist/tenant/tenant-registry.d.ts.map +1 -1
  201. package/dist/tenant/tenant-registry.js +83 -4
  202. package/dist/tenant/tenant-registry.js.map +1 -1
  203. package/dist/tenant/tenant-router.d.ts +27 -0
  204. package/dist/tenant/tenant-router.d.ts.map +1 -0
  205. package/dist/tenant/tenant-router.js +72 -0
  206. package/dist/tenant/tenant-router.js.map +1 -0
  207. package/dist/utils/hmac.d.ts +1 -0
  208. package/dist/utils/hmac.d.ts.map +1 -1
  209. package/dist/utils/hmac.js +3 -0
  210. package/dist/utils/hmac.js.map +1 -1
  211. package/package.json +2 -2
@@ -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;AAIxE,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,CA+KlE"}
1
+ {"version":3,"file":"gateway-routes.d.ts","sourceRoot":"","sources":["../../src/gateway/gateway-routes.ts"],"names":[],"mappings":"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"}
@@ -8,7 +8,13 @@ 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";
13
19
  import { createHandoffRoutes } from "./handoff-routes.js";
14
20
  import { HealthRegistry } from "./health-registry.js";
@@ -101,6 +107,21 @@ export function createGatewayApp(config) {
101
107
  const webhookApp = createWhatsAppWebhookRoutes(loadedApp.whatsappWebhookConfig);
102
108
  app.route(`/whatsapp/${loadedApp.name}`, webhookApp);
103
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
+ }
104
125
  // WebSocket route for web channel
105
126
  if (channel.type === "web" && loadedApp.webChannel && config.upgradeWebSocket) {
106
127
  if (loadedApp.tenantRuntime) {
@@ -115,6 +136,10 @@ export function createGatewayApp(config) {
115
136
  billing: tenantRuntime.billing,
116
137
  eventEmitter: loadedApp.eventEmitter,
117
138
  allowedOrigins: channel.allowedOrigins,
139
+ sttAdapter: loadedApp.sttAdapter,
140
+ knowledgePipeline: loadedApp.knowledgePipeline?.pipeline,
141
+ knowledgeMode: loadedApp.app.knowledge?.mode,
142
+ contactMemoryService: loadedApp.contactMemoryService,
118
143
  });
119
144
  app.route(`/apps/${loadedApp.name}`, wsTenantApp);
120
145
  }
@@ -128,6 +153,7 @@ export function createGatewayApp(config) {
128
153
  processMessage: async (userId, parts) => {
129
154
  const session = await runtime.sessionRegistry.getOrCreate({
130
155
  appName: loadedApp.name,
156
+ tenantId: "_default",
131
157
  userId,
132
158
  systemPrompt: runtime.systemPrompt,
133
159
  });
@@ -163,6 +189,21 @@ export function createGatewayApp(config) {
163
189
  app.route(`/handoff/${loadedApp.name}`, handoffApp);
164
190
  }
165
191
  }
192
+ // Knowledge admin routes (available for any app with knowledge config)
193
+ if (loadedApp.knowledgeAdminConfig) {
194
+ const knowledgeAdminApp = createKnowledgeAdminRoutes(loadedApp.knowledgeAdminConfig);
195
+ app.route(`/admin/${loadedApp.name}/knowledge`, knowledgeAdminApp);
196
+ }
197
+ // Contact memory admin routes (GDPR: forget, forgetAll)
198
+ if (loadedApp.contactMemoryAdminConfig) {
199
+ const contactMemoryAdminApp = createContactMemoryAdminRoutes(loadedApp.contactMemoryAdminConfig);
200
+ app.route(`/admin/${loadedApp.name}/contact-memory`, contactMemoryAdminApp);
201
+ }
202
+ // Enrichment admin routes (GDPR: get, list, delete)
203
+ if (loadedApp.enrichmentAdminConfig) {
204
+ const enrichmentAdminApp = createEnrichmentAdminRoutes(loadedApp.enrichmentAdminConfig);
205
+ app.route(`/admin/${loadedApp.name}/enrichment`, enrichmentAdminApp);
206
+ }
166
207
  }
167
208
  // Mount webhook trigger routes per app
168
209
  if (config.triggerRegistry) {