@inkeep/agents-run-api 0.39.5 → 0.41.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 (180) hide show
  1. package/dist/_virtual/_raw_/home/runner/work/agents/agents/agents-run-api/templates/v1/phase1/system-prompt.js +5 -0
  2. package/dist/_virtual/_raw_/home/runner/work/agents/agents/agents-run-api/templates/v1/phase1/thinking-preparation.js +5 -0
  3. package/dist/_virtual/_raw_/home/runner/work/agents/agents/agents-run-api/templates/v1/phase1/tool.js +5 -0
  4. package/dist/_virtual/_raw_/home/runner/work/agents/agents/agents-run-api/templates/v1/phase2/data-component.js +5 -0
  5. package/dist/_virtual/_raw_/home/runner/work/agents/agents/agents-run-api/templates/v1/phase2/data-components.js +5 -0
  6. package/dist/_virtual/_raw_/home/runner/work/agents/agents/agents-run-api/templates/v1/phase2/system-prompt.js +5 -0
  7. package/dist/_virtual/_raw_/home/runner/work/agents/agents/agents-run-api/templates/v1/shared/artifact-retrieval-guidance.js +5 -0
  8. package/dist/_virtual/_raw_/home/runner/work/agents/agents/agents-run-api/templates/v1/shared/artifact.js +5 -0
  9. package/dist/a2a/client.d.ts +184 -0
  10. package/dist/a2a/client.js +510 -0
  11. package/dist/a2a/handlers.d.ts +7 -0
  12. package/dist/a2a/handlers.js +576 -0
  13. package/dist/a2a/transfer.d.ts +22 -0
  14. package/dist/a2a/transfer.js +46 -0
  15. package/dist/a2a/types.d.ts +79 -0
  16. package/dist/a2a/types.js +22 -0
  17. package/dist/agents/Agent.d.ts +268 -0
  18. package/dist/agents/Agent.js +1932 -0
  19. package/dist/agents/ModelFactory.d.ts +63 -0
  20. package/dist/agents/ModelFactory.js +194 -0
  21. package/dist/agents/SystemPromptBuilder.d.ts +21 -0
  22. package/dist/agents/SystemPromptBuilder.js +48 -0
  23. package/dist/agents/ToolSessionManager.d.ts +63 -0
  24. package/dist/agents/ToolSessionManager.js +146 -0
  25. package/dist/agents/generateTaskHandler.d.ts +49 -0
  26. package/dist/agents/generateTaskHandler.js +523 -0
  27. package/dist/agents/relationTools.d.ts +57 -0
  28. package/dist/agents/relationTools.js +262 -0
  29. package/dist/agents/types.d.ts +28 -0
  30. package/dist/agents/types.js +1 -0
  31. package/dist/agents/versions/v1/Phase1Config.d.ts +27 -0
  32. package/dist/agents/versions/v1/Phase1Config.js +424 -0
  33. package/dist/agents/versions/v1/Phase2Config.d.ts +31 -0
  34. package/dist/agents/versions/v1/Phase2Config.js +330 -0
  35. package/dist/constants/execution-limits/defaults.d.ts +51 -0
  36. package/dist/constants/execution-limits/defaults.js +52 -0
  37. package/dist/constants/execution-limits/index.d.ts +6 -0
  38. package/dist/constants/execution-limits/index.js +21 -0
  39. package/dist/create-app.d.ts +9 -0
  40. package/dist/create-app.js +195 -0
  41. package/dist/data/agent.d.ts +7 -0
  42. package/dist/data/agent.js +72 -0
  43. package/dist/data/agents.d.ts +34 -0
  44. package/dist/data/agents.js +139 -0
  45. package/dist/data/conversations.d.ts +128 -0
  46. package/dist/data/conversations.js +522 -0
  47. package/dist/data/db/dbClient.d.ts +6 -0
  48. package/dist/data/db/dbClient.js +17 -0
  49. package/dist/env.d.ts +57 -0
  50. package/dist/env.js +1 -2
  51. package/dist/handlers/executionHandler.d.ts +41 -0
  52. package/dist/handlers/executionHandler.js +457 -0
  53. package/dist/index.d.ts +8 -29
  54. package/dist/index.js +5 -11386
  55. package/dist/instrumentation.d.ts +1 -2
  56. package/dist/instrumentation.js +66 -3
  57. package/dist/{logger2.js → logger.d.ts} +1 -2
  58. package/dist/logger.js +1 -1
  59. package/dist/middleware/api-key-auth.d.ts +26 -0
  60. package/dist/middleware/api-key-auth.js +240 -0
  61. package/dist/middleware/index.d.ts +2 -0
  62. package/dist/middleware/index.js +3 -0
  63. package/dist/openapi.d.ts +4 -0
  64. package/dist/openapi.js +54 -0
  65. package/dist/routes/agents.d.ts +12 -0
  66. package/dist/routes/agents.js +147 -0
  67. package/dist/routes/chat.d.ts +13 -0
  68. package/dist/routes/chat.js +305 -0
  69. package/dist/routes/chatDataStream.d.ts +13 -0
  70. package/dist/routes/chatDataStream.js +365 -0
  71. package/dist/routes/mcp.d.ts +13 -0
  72. package/dist/routes/mcp.js +495 -0
  73. package/dist/services/AgentSession.d.ts +356 -0
  74. package/dist/services/AgentSession.js +1208 -0
  75. package/dist/services/ArtifactParser.d.ts +105 -0
  76. package/dist/services/ArtifactParser.js +338 -0
  77. package/dist/services/ArtifactService.d.ts +123 -0
  78. package/dist/services/ArtifactService.js +612 -0
  79. package/dist/services/BaseCompressor.d.ts +183 -0
  80. package/dist/services/BaseCompressor.js +500 -0
  81. package/dist/services/ConversationCompressor.d.ts +32 -0
  82. package/dist/services/ConversationCompressor.js +91 -0
  83. package/dist/services/IncrementalStreamParser.d.ts +98 -0
  84. package/dist/services/IncrementalStreamParser.js +327 -0
  85. package/dist/services/MidGenerationCompressor.d.ts +63 -0
  86. package/dist/services/MidGenerationCompressor.js +104 -0
  87. package/dist/services/PendingToolApprovalManager.d.ts +62 -0
  88. package/dist/services/PendingToolApprovalManager.js +133 -0
  89. package/dist/services/ResponseFormatter.d.ts +39 -0
  90. package/dist/services/ResponseFormatter.js +152 -0
  91. package/dist/tools/NativeSandboxExecutor.d.ts +38 -0
  92. package/dist/tools/NativeSandboxExecutor.js +432 -0
  93. package/dist/tools/SandboxExecutorFactory.d.ts +36 -0
  94. package/dist/tools/SandboxExecutorFactory.js +80 -0
  95. package/dist/tools/VercelSandboxExecutor.d.ts +71 -0
  96. package/dist/tools/VercelSandboxExecutor.js +340 -0
  97. package/dist/tools/distill-conversation-history-tool.d.ts +62 -0
  98. package/dist/tools/distill-conversation-history-tool.js +206 -0
  99. package/dist/tools/distill-conversation-tool.d.ts +41 -0
  100. package/dist/tools/distill-conversation-tool.js +141 -0
  101. package/dist/tools/sandbox-utils.d.ts +18 -0
  102. package/dist/tools/sandbox-utils.js +53 -0
  103. package/dist/types/chat.d.ts +27 -0
  104. package/dist/types/chat.js +1 -0
  105. package/dist/types/execution-context.d.ts +46 -0
  106. package/dist/types/execution-context.js +27 -0
  107. package/dist/types/xml.d.ts +5 -0
  108. package/dist/utils/SchemaProcessor.d.ts +52 -0
  109. package/dist/utils/SchemaProcessor.js +182 -0
  110. package/dist/utils/agent-operations.d.ts +62 -0
  111. package/dist/utils/agent-operations.js +53 -0
  112. package/dist/utils/artifact-component-schema.d.ts +42 -0
  113. package/dist/utils/artifact-component-schema.js +186 -0
  114. package/dist/utils/cleanup.d.ts +21 -0
  115. package/dist/utils/cleanup.js +59 -0
  116. package/dist/utils/data-component-schema.d.ts +2 -0
  117. package/dist/utils/data-component-schema.js +3 -0
  118. package/dist/utils/default-status-schemas.d.ts +20 -0
  119. package/dist/utils/default-status-schemas.js +24 -0
  120. package/dist/utils/json-postprocessor.d.ts +13 -0
  121. package/dist/{json-postprocessor.cjs → utils/json-postprocessor.js} +2 -3
  122. package/dist/utils/model-context-utils.d.ts +39 -0
  123. package/dist/utils/model-context-utils.js +181 -0
  124. package/dist/utils/model-resolver.d.ts +6 -0
  125. package/dist/utils/model-resolver.js +34 -0
  126. package/dist/utils/schema-validation.d.ts +44 -0
  127. package/dist/utils/schema-validation.js +97 -0
  128. package/dist/utils/stream-helpers.d.ts +197 -0
  129. package/dist/utils/stream-helpers.js +518 -0
  130. package/dist/utils/stream-registry.d.ts +22 -0
  131. package/dist/utils/stream-registry.js +34 -0
  132. package/dist/utils/token-estimator.d.ts +69 -0
  133. package/dist/utils/token-estimator.js +53 -0
  134. package/dist/utils/tracer.d.ts +7 -0
  135. package/dist/utils/tracer.js +7 -0
  136. package/package.json +10 -26
  137. package/dist/SandboxExecutorFactory.cjs +0 -895
  138. package/dist/SandboxExecutorFactory.js +0 -893
  139. package/dist/SandboxExecutorFactory.js.map +0 -1
  140. package/dist/chunk-VBDAOXYI.cjs +0 -927
  141. package/dist/chunk-VBDAOXYI.js +0 -832
  142. package/dist/chunk-VBDAOXYI.js.map +0 -1
  143. package/dist/chunk.cjs +0 -34
  144. package/dist/conversations.cjs +0 -7
  145. package/dist/conversations.js +0 -7
  146. package/dist/conversations2.cjs +0 -209
  147. package/dist/conversations2.js +0 -180
  148. package/dist/conversations2.js.map +0 -1
  149. package/dist/dbClient.cjs +0 -9676
  150. package/dist/dbClient.js +0 -9670
  151. package/dist/dbClient.js.map +0 -1
  152. package/dist/dbClient2.cjs +0 -5
  153. package/dist/dbClient2.js +0 -5
  154. package/dist/env.cjs +0 -59
  155. package/dist/env.js.map +0 -1
  156. package/dist/execution-limits.cjs +0 -260
  157. package/dist/execution-limits.js +0 -63
  158. package/dist/execution-limits.js.map +0 -1
  159. package/dist/index.cjs +0 -11411
  160. package/dist/index.d.cts +0 -36
  161. package/dist/index.d.cts.map +0 -1
  162. package/dist/index.d.ts.map +0 -1
  163. package/dist/index.js.map +0 -1
  164. package/dist/instrumentation.cjs +0 -12
  165. package/dist/instrumentation.d.cts +0 -18
  166. package/dist/instrumentation.d.cts.map +0 -1
  167. package/dist/instrumentation.d.ts.map +0 -1
  168. package/dist/instrumentation2.cjs +0 -116
  169. package/dist/instrumentation2.js +0 -69
  170. package/dist/instrumentation2.js.map +0 -1
  171. package/dist/json-postprocessor.js +0 -20
  172. package/dist/json-postprocessor.js.map +0 -1
  173. package/dist/logger.cjs +0 -5
  174. package/dist/logger2.cjs +0 -1
  175. package/dist/nodefs.cjs +0 -29
  176. package/dist/nodefs.js +0 -27
  177. package/dist/nodefs.js.map +0 -1
  178. package/dist/opfs-ahp.cjs +0 -367
  179. package/dist/opfs-ahp.js +0 -368
  180. package/dist/opfs-ahp.js.map +0 -1
@@ -0,0 +1,305 @@
1
+ import { getLogger } from "../logger.js";
2
+ import dbClient_default from "../data/db/dbClient.js";
3
+ import { errorOp } from "../utils/agent-operations.js";
4
+ import { createSSEStreamHelper } from "../utils/stream-helpers.js";
5
+ import { ExecutionHandler } from "../handlers/executionHandler.js";
6
+ import { OpenAPIHono, createRoute, z } from "@hono/zod-openapi";
7
+ import { contextValidationMiddleware, createApiError, createMessage, createOrGetConversation, generateId, getActiveAgentForConversation, getAgentWithDefaultSubAgent, getConversationId, getFullAgent, getRequestExecutionContext, getSubAgentById, handleContextResolution, setActiveAgentForConversation } from "@inkeep/agents-core";
8
+ import { context, propagation, trace } from "@opentelemetry/api";
9
+ import { streamSSE } from "hono/streaming";
10
+
11
+ //#region src/routes/chat.ts
12
+ const app = new OpenAPIHono();
13
+ const logger = getLogger("completionsHandler");
14
+ const chatCompletionsRoute = createRoute({
15
+ method: "post",
16
+ path: "/completions",
17
+ tags: ["chat"],
18
+ summary: "Create chat completion",
19
+ description: "Creates a new chat completion with streaming SSE response using the configured agent",
20
+ security: [{ bearerAuth: [] }],
21
+ request: { body: { content: { "application/json": { schema: z.object({
22
+ model: z.string().describe("The model to use for the completion"),
23
+ messages: z.array(z.object({
24
+ role: z.enum([
25
+ "system",
26
+ "user",
27
+ "assistant",
28
+ "function",
29
+ "tool"
30
+ ]).describe("The role of the message"),
31
+ content: z.union([z.string(), z.array(z.strictObject({
32
+ type: z.string(),
33
+ text: z.string().optional()
34
+ }))]).describe("The message content"),
35
+ name: z.string().optional().describe("The name of the message sender")
36
+ })).describe("The conversation messages"),
37
+ temperature: z.number().optional().describe("Controls randomness (0-1)"),
38
+ top_p: z.number().optional().describe("Controls nucleus sampling"),
39
+ n: z.number().optional().describe("Number of completions to generate"),
40
+ stream: z.boolean().optional().describe("Whether to stream the response"),
41
+ max_tokens: z.number().optional().describe("Maximum tokens to generate"),
42
+ presence_penalty: z.number().optional().describe("Presence penalty (-2 to 2)"),
43
+ frequency_penalty: z.number().optional().describe("Frequency penalty (-2 to 2)"),
44
+ logit_bias: z.record(z.string(), z.number()).optional().describe("Token logit bias"),
45
+ user: z.string().optional().describe("User identifier"),
46
+ conversationId: z.string().optional().describe("Conversation ID for multi-turn chat"),
47
+ tools: z.array(z.string()).optional().describe("Available tools"),
48
+ runConfig: z.record(z.string(), z.unknown()).optional().describe("Run configuration"),
49
+ headers: z.record(z.string(), z.unknown()).optional().describe("Headers data for template processing (validated against context config schema)")
50
+ }) } } } },
51
+ responses: {
52
+ 200: {
53
+ description: "Streaming chat completion response in Server-Sent Events format",
54
+ headers: z.object({
55
+ "Content-Type": z.string().default("text/event-stream"),
56
+ "Cache-Control": z.string().default("no-cache"),
57
+ Connection: z.string().default("keep-alive")
58
+ }),
59
+ content: { "text/event-stream": { schema: z.string().describe("Server-Sent Events stream with chat completion chunks") } }
60
+ },
61
+ 400: {
62
+ description: "Invalid request context or parameters",
63
+ content: { "application/json": { schema: z.object({
64
+ error: z.string(),
65
+ details: z.array(z.object({
66
+ field: z.string(),
67
+ message: z.string(),
68
+ value: z.unknown().optional()
69
+ })).optional()
70
+ }) } }
71
+ },
72
+ 404: {
73
+ description: "Agent or agent not found",
74
+ content: { "application/json": { schema: z.object({ error: z.string() }) } }
75
+ },
76
+ 500: {
77
+ description: "Internal server error",
78
+ content: { "application/json": { schema: z.object({
79
+ error: z.string(),
80
+ message: z.string()
81
+ }) } }
82
+ }
83
+ }
84
+ });
85
+ app.use("/completions", contextValidationMiddleware(dbClient_default));
86
+ app.openapi(chatCompletionsRoute, async (c) => {
87
+ getLogger("chat").info({
88
+ path: c.req.path,
89
+ method: c.req.method,
90
+ params: c.req.param()
91
+ }, "Chat route accessed");
92
+ const otelHeaders = {
93
+ traceparent: c.req.header("traceparent"),
94
+ tracestate: c.req.header("tracestate"),
95
+ baggage: c.req.header("baggage")
96
+ };
97
+ logger.info({
98
+ otelHeaders,
99
+ path: c.req.path,
100
+ method: c.req.method
101
+ }, "OpenTelemetry headers: chat");
102
+ try {
103
+ const executionContext = getRequestExecutionContext(c);
104
+ const { tenantId, projectId, agentId } = executionContext;
105
+ getLogger("chat").debug({
106
+ tenantId,
107
+ agentId
108
+ }, "Extracted chat parameters from API key context");
109
+ const body = c.get("requestBody") || {};
110
+ const conversationId = body.conversationId || getConversationId();
111
+ const targetTenantId = c.req.header("x-target-tenant-id");
112
+ const targetProjectId = c.req.header("x-target-project-id");
113
+ const targetAgentId = c.req.header("x-target-agent-id");
114
+ const activeSpan = trace.getActiveSpan();
115
+ if (activeSpan) activeSpan.setAttributes({
116
+ "conversation.id": conversationId,
117
+ "tenant.id": tenantId,
118
+ "agent.id": agentId,
119
+ "project.id": projectId,
120
+ ...targetTenantId && { "target.tenant.id": targetTenantId },
121
+ ...targetProjectId && { "target.project.id": targetProjectId },
122
+ ...targetAgentId && { "target.agent.id": targetAgentId }
123
+ });
124
+ let currentBag = propagation.getBaggage(context.active());
125
+ if (!currentBag) currentBag = propagation.createBaggage();
126
+ currentBag = currentBag.setEntry("conversation.id", { value: conversationId });
127
+ const ctxWithBaggage = propagation.setBaggage(context.active(), currentBag);
128
+ return await context.with(ctxWithBaggage, async () => {
129
+ const fullAgent = await getFullAgent(dbClient_default)({ scopes: {
130
+ tenantId,
131
+ projectId,
132
+ agentId
133
+ } });
134
+ let agent;
135
+ let defaultSubAgentId;
136
+ if (fullAgent) {
137
+ agent = {
138
+ id: fullAgent.id,
139
+ name: fullAgent.name,
140
+ tenantId,
141
+ projectId,
142
+ defaultSubAgentId: fullAgent.defaultSubAgentId
143
+ };
144
+ const agentKeys = Object.keys(fullAgent.subAgents || {});
145
+ const firstAgentId = agentKeys.length > 0 ? agentKeys[0] : "";
146
+ defaultSubAgentId = fullAgent.defaultSubAgentId || firstAgentId;
147
+ } else {
148
+ agent = await getAgentWithDefaultSubAgent(dbClient_default)({ scopes: {
149
+ tenantId,
150
+ projectId,
151
+ agentId
152
+ } });
153
+ if (!agent) throw createApiError({
154
+ code: "not_found",
155
+ message: "Agent not found"
156
+ });
157
+ defaultSubAgentId = agent.defaultSubAgentId || "";
158
+ }
159
+ if (!defaultSubAgentId) throw createApiError({
160
+ code: "not_found",
161
+ message: "No default agent found in agent"
162
+ });
163
+ await createOrGetConversation(dbClient_default)({
164
+ tenantId,
165
+ projectId,
166
+ id: conversationId,
167
+ activeSubAgentId: defaultSubAgentId
168
+ });
169
+ const activeAgent = await getActiveAgentForConversation(dbClient_default)({
170
+ scopes: {
171
+ tenantId,
172
+ projectId
173
+ },
174
+ conversationId
175
+ });
176
+ if (!activeAgent) setActiveAgentForConversation(dbClient_default)({
177
+ scopes: {
178
+ tenantId,
179
+ projectId
180
+ },
181
+ conversationId,
182
+ subAgentId: defaultSubAgentId
183
+ });
184
+ const subAgentId = activeAgent?.activeSubAgentId || defaultSubAgentId;
185
+ if (!await getSubAgentById(dbClient_default)({
186
+ scopes: {
187
+ tenantId,
188
+ projectId,
189
+ agentId
190
+ },
191
+ subAgentId
192
+ })) throw createApiError({
193
+ code: "not_found",
194
+ message: "Agent not found"
195
+ });
196
+ const validatedContext = c.get("validatedContext") || body.headers || {};
197
+ await handleContextResolution({
198
+ tenantId,
199
+ projectId,
200
+ agentId,
201
+ conversationId,
202
+ headers: validatedContext,
203
+ dbClient: dbClient_default,
204
+ credentialStores: c.get("credentialStores")
205
+ });
206
+ logger.info({
207
+ tenantId,
208
+ projectId,
209
+ agentId,
210
+ conversationId,
211
+ defaultSubAgentId,
212
+ activeSubAgentId: activeAgent?.activeSubAgentId || "none",
213
+ hasContextConfig: !!agent.contextConfigId,
214
+ hasHeaders: !!body.headers,
215
+ hasValidatedContext: !!validatedContext,
216
+ validatedContextKeys: Object.keys(validatedContext)
217
+ }, "parameters");
218
+ const requestId = `chatcmpl-${Date.now()}`;
219
+ const timestamp = Math.floor(Date.now() / 1e3);
220
+ const lastUserMessage = body.messages.filter((msg) => msg.role === "user").slice(-1)[0];
221
+ const userMessage = lastUserMessage ? getMessageText(lastUserMessage.content) : "";
222
+ const messageSpan = trace.getActiveSpan();
223
+ if (messageSpan) {
224
+ messageSpan.setAttributes({
225
+ "message.content": userMessage,
226
+ "message.timestamp": Date.now()
227
+ });
228
+ if (executionContext.metadata?.initiatedBy) {
229
+ messageSpan.setAttribute("user.type", executionContext.metadata.initiatedBy.type);
230
+ messageSpan.setAttribute("user.id", executionContext.metadata.initiatedBy.id);
231
+ }
232
+ }
233
+ await createMessage(dbClient_default)({
234
+ id: generateId(),
235
+ tenantId,
236
+ projectId,
237
+ conversationId,
238
+ role: "user",
239
+ content: { text: userMessage },
240
+ visibility: "user-facing",
241
+ messageType: "chat"
242
+ });
243
+ if (messageSpan) messageSpan.addEvent("user.message.stored", {
244
+ "message.id": conversationId,
245
+ "database.operation": "insert"
246
+ });
247
+ return streamSSE(c, async (stream$1) => {
248
+ try {
249
+ const sseHelper = createSSEStreamHelper(stream$1, requestId, timestamp);
250
+ await sseHelper.writeRole();
251
+ logger.info({ subAgentId }, "Starting execution");
252
+ const emitOperations = c.req.header("x-emit-operations") === "true";
253
+ const forwardedHeaders = {};
254
+ const xForwardedCookie = c.req.header("x-forwarded-cookie");
255
+ const cookie = c.req.header("cookie");
256
+ if (xForwardedCookie) forwardedHeaders["x-forwarded-cookie"] = xForwardedCookie;
257
+ else if (cookie) forwardedHeaders["x-forwarded-cookie"] = cookie;
258
+ const result = await new ExecutionHandler().execute({
259
+ executionContext,
260
+ conversationId,
261
+ userMessage,
262
+ initialAgentId: subAgentId,
263
+ requestId,
264
+ sseHelper,
265
+ emitOperations,
266
+ forwardedHeaders
267
+ });
268
+ logger.info({ result }, `Execution completed: ${result.success ? "success" : "failed"} after ${result.iterations} iterations`);
269
+ if (!result.success) await sseHelper.writeOperation(errorOp("Sorry, I was unable to process your request at this time. Please try again.", "system"));
270
+ await sseHelper.complete();
271
+ } catch (error) {
272
+ logger.error({
273
+ error: error instanceof Error ? error.message : error,
274
+ stack: error instanceof Error ? error.stack : void 0
275
+ }, "Error during streaming execution");
276
+ try {
277
+ const sseHelper = createSSEStreamHelper(stream$1, requestId, timestamp);
278
+ await sseHelper.writeOperation(errorOp("Sorry, I was unable to process your request at this time. Please try again.", "system"));
279
+ await sseHelper.complete();
280
+ } catch (streamError) {
281
+ logger.error({ streamError }, "Failed to write error to stream");
282
+ }
283
+ }
284
+ });
285
+ });
286
+ } catch (error) {
287
+ logger.error({
288
+ error: error instanceof Error ? error.message : error,
289
+ stack: error instanceof Error ? error.stack : void 0
290
+ }, "Error in chat completions endpoint before streaming");
291
+ if (error && typeof error === "object" && "status" in error) throw error;
292
+ throw createApiError({
293
+ code: "internal_server_error",
294
+ message: error instanceof Error ? error.message : "Failed to process chat completion"
295
+ });
296
+ }
297
+ });
298
+ const getMessageText = (content) => {
299
+ if (typeof content === "string") return content;
300
+ return content.filter((item) => item.type === "text" && item.text).map((item) => item.text).join(" ");
301
+ };
302
+ var chat_default = app;
303
+
304
+ //#endregion
305
+ export { chat_default as default };
@@ -0,0 +1,13 @@
1
+ import { OpenAPIHono } from "@hono/zod-openapi";
2
+ import { CredentialStoreRegistry } from "@inkeep/agents-core";
3
+
4
+ //#region src/routes/chatDataStream.d.ts
5
+ type AppVariables = {
6
+ credentialStores: CredentialStoreRegistry;
7
+ requestBody?: any;
8
+ };
9
+ declare const app: OpenAPIHono<{
10
+ Variables: AppVariables;
11
+ }, {}, "/">;
12
+ //#endregion
13
+ export { app as default };
@@ -0,0 +1,365 @@
1
+ import { getLogger } from "../logger.js";
2
+ import dbClient_default from "../data/db/dbClient.js";
3
+ import { pendingToolApprovalManager } from "../services/PendingToolApprovalManager.js";
4
+ import { errorOp } from "../utils/agent-operations.js";
5
+ import { createBufferingStreamHelper, createVercelStreamHelper } from "../utils/stream-helpers.js";
6
+ import { ExecutionHandler } from "../handlers/executionHandler.js";
7
+ import { OpenAPIHono, createRoute, z } from "@hono/zod-openapi";
8
+ import { commonGetErrorResponses, contextValidationMiddleware, createApiError, createMessage, generateId, getActiveAgentForConversation, getAgentWithDefaultSubAgent, getConversation, getConversationId, getRequestExecutionContext, getSubAgentById, handleContextResolution, loggerFactory, setActiveAgentForConversation } from "@inkeep/agents-core";
9
+ import { context, propagation, trace } from "@opentelemetry/api";
10
+ import { stream } from "hono/streaming";
11
+ import { JsonToSseTransformStream, createUIMessageStream } from "ai";
12
+
13
+ //#region src/routes/chatDataStream.ts
14
+ const app = new OpenAPIHono();
15
+ const logger = getLogger("chatDataStream");
16
+ const chatDataStreamRoute = createRoute({
17
+ method: "post",
18
+ path: "/chat",
19
+ tags: ["chat"],
20
+ summary: "Chat (Vercel Streaming Protocol)",
21
+ description: "Chat completion endpoint streaming with Vercel data stream protocol.",
22
+ security: [{ bearerAuth: [] }],
23
+ request: { body: { content: { "application/json": { schema: z.object({
24
+ model: z.string().optional(),
25
+ messages: z.array(z.object({
26
+ role: z.enum([
27
+ "system",
28
+ "user",
29
+ "assistant",
30
+ "function",
31
+ "tool"
32
+ ]),
33
+ content: z.any(),
34
+ parts: z.array(z.object({
35
+ type: z.union([z.enum([
36
+ "text",
37
+ "image",
38
+ "audio",
39
+ "video",
40
+ "file"
41
+ ]), z.string().regex(/^data-/, "Type must start with \"data-\"")]),
42
+ text: z.string().optional()
43
+ })).optional()
44
+ })),
45
+ id: z.string().optional(),
46
+ conversationId: z.string().optional(),
47
+ stream: z.boolean().optional().describe("Whether to stream the response").default(true),
48
+ max_tokens: z.number().optional().describe("Maximum tokens to generate"),
49
+ headers: z.record(z.string(), z.unknown()).optional().describe("Headers data for template processing"),
50
+ runConfig: z.record(z.string(), z.unknown()).optional().describe("Run configuration")
51
+ }) } } } },
52
+ responses: {
53
+ 200: {
54
+ description: "Streamed chat completion",
55
+ headers: z.object({
56
+ "Content-Type": z.string().default("text/plain; charset=utf-8"),
57
+ "x-vercel-ai-data-stream": z.string().default("v1")
58
+ })
59
+ },
60
+ ...commonGetErrorResponses
61
+ }
62
+ });
63
+ app.use("/chat", contextValidationMiddleware(dbClient_default));
64
+ app.openapi(chatDataStreamRoute, async (c) => {
65
+ try {
66
+ const executionContext = getRequestExecutionContext(c);
67
+ const { tenantId, projectId, agentId } = executionContext;
68
+ loggerFactory.getLogger("chatDataStream").debug({
69
+ tenantId,
70
+ projectId,
71
+ agentId
72
+ }, "Extracted chatDataStream parameters");
73
+ const body = c.get("requestBody") || {};
74
+ const conversationId = body.conversationId || getConversationId();
75
+ const targetTenantId = c.req.header("x-target-tenant-id");
76
+ const targetProjectId = c.req.header("x-target-project-id");
77
+ const targetAgentId = c.req.header("x-target-agent-id");
78
+ const forwardedHeaders = {};
79
+ const xForwardedCookie = c.req.header("x-forwarded-cookie");
80
+ const cookie = c.req.header("cookie");
81
+ if (xForwardedCookie) forwardedHeaders["x-forwarded-cookie"] = xForwardedCookie;
82
+ else if (cookie) forwardedHeaders["x-forwarded-cookie"] = cookie;
83
+ const activeSpan = trace.getActiveSpan();
84
+ if (activeSpan) activeSpan.setAttributes({
85
+ "conversation.id": conversationId,
86
+ "tenant.id": tenantId,
87
+ "agent.id": agentId,
88
+ "project.id": projectId,
89
+ ...targetTenantId && { "target.tenant.id": targetTenantId },
90
+ ...targetProjectId && { "target.project.id": targetProjectId },
91
+ ...targetAgentId && { "target.agent.id": targetAgentId }
92
+ });
93
+ let currentBag = propagation.getBaggage(context.active());
94
+ if (!currentBag) currentBag = propagation.createBaggage();
95
+ currentBag = currentBag.setEntry("conversation.id", { value: conversationId });
96
+ const ctxWithBaggage = propagation.setBaggage(context.active(), currentBag);
97
+ return await context.with(ctxWithBaggage, async () => {
98
+ const agent = await getAgentWithDefaultSubAgent(dbClient_default)({ scopes: {
99
+ tenantId,
100
+ projectId,
101
+ agentId
102
+ } });
103
+ if (!agent) throw createApiError({
104
+ code: "not_found",
105
+ message: "Agent not found"
106
+ });
107
+ const defaultSubAgentId = agent.defaultSubAgentId;
108
+ const agentName = agent.name;
109
+ if (!defaultSubAgentId) throw createApiError({
110
+ code: "bad_request",
111
+ message: "Agent does not have a default agent configured"
112
+ });
113
+ const activeAgent = await getActiveAgentForConversation(dbClient_default)({
114
+ scopes: {
115
+ tenantId,
116
+ projectId
117
+ },
118
+ conversationId
119
+ });
120
+ if (!activeAgent) setActiveAgentForConversation(dbClient_default)({
121
+ scopes: {
122
+ tenantId,
123
+ projectId
124
+ },
125
+ conversationId,
126
+ subAgentId: defaultSubAgentId
127
+ });
128
+ const subAgentId = activeAgent?.activeSubAgentId || defaultSubAgentId;
129
+ if (!await getSubAgentById(dbClient_default)({
130
+ scopes: {
131
+ tenantId,
132
+ projectId,
133
+ agentId
134
+ },
135
+ subAgentId
136
+ })) throw createApiError({
137
+ code: "not_found",
138
+ message: "Agent not found"
139
+ });
140
+ await handleContextResolution({
141
+ tenantId,
142
+ projectId,
143
+ agentId,
144
+ conversationId,
145
+ headers: c.get("validatedContext") || body.headers || {},
146
+ dbClient: dbClient_default,
147
+ credentialStores: c.get("credentialStores")
148
+ });
149
+ const lastUserMessage = body.messages.filter((m) => m.role === "user").slice(-1)[0];
150
+ const userText = typeof lastUserMessage?.content === "string" ? lastUserMessage.content : lastUserMessage?.parts?.map((p) => p.text).join("") || "";
151
+ logger.info({
152
+ userText,
153
+ lastUserMessage
154
+ }, "userText");
155
+ const messageSpan = trace.getActiveSpan();
156
+ if (messageSpan) {
157
+ messageSpan.setAttributes({
158
+ "message.timestamp": (/* @__PURE__ */ new Date()).toISOString(),
159
+ "message.content": userText,
160
+ "agent.name": agentName
161
+ });
162
+ if (executionContext.metadata?.initiatedBy) {
163
+ messageSpan.setAttribute("user.type", executionContext.metadata.initiatedBy.type);
164
+ messageSpan.setAttribute("user.id", executionContext.metadata.initiatedBy.id);
165
+ }
166
+ }
167
+ await createMessage(dbClient_default)({
168
+ id: generateId(),
169
+ tenantId,
170
+ projectId,
171
+ conversationId,
172
+ role: "user",
173
+ content: { text: userText },
174
+ visibility: "user-facing",
175
+ messageType: "chat"
176
+ });
177
+ if (messageSpan) messageSpan.addEvent("user.message.stored", {
178
+ "message.id": conversationId,
179
+ "database.operation": "insert"
180
+ });
181
+ if (!(body.stream !== false)) {
182
+ const emitOperations = c.req.header("x-emit-operations") === "true";
183
+ const bufferingHelper = createBufferingStreamHelper();
184
+ const result = await new ExecutionHandler().execute({
185
+ executionContext,
186
+ conversationId,
187
+ userMessage: userText,
188
+ initialAgentId: subAgentId,
189
+ requestId: `chat-${Date.now()}`,
190
+ sseHelper: bufferingHelper,
191
+ emitOperations,
192
+ forwardedHeaders
193
+ });
194
+ const captured = bufferingHelper.getCapturedResponse();
195
+ return c.json({
196
+ id: `chat-${Date.now()}`,
197
+ object: "chat.completion",
198
+ created: Math.floor(Date.now() / 1e3),
199
+ model: agentName,
200
+ choices: [{
201
+ index: 0,
202
+ message: {
203
+ role: "assistant",
204
+ content: captured.hasError ? captured.errorMessage : captured.text
205
+ },
206
+ finish_reason: result.success && !captured.hasError ? "stop" : "error"
207
+ }],
208
+ usage: {
209
+ prompt_tokens: 0,
210
+ completion_tokens: 0,
211
+ total_tokens: 0
212
+ }
213
+ });
214
+ }
215
+ const dataStream = createUIMessageStream({ execute: async ({ writer }) => {
216
+ const streamHelper = createVercelStreamHelper(writer);
217
+ try {
218
+ const emitOperations = c.req.header("x-emit-operations") === "true";
219
+ if (!(await new ExecutionHandler().execute({
220
+ executionContext,
221
+ conversationId,
222
+ userMessage: userText,
223
+ initialAgentId: subAgentId,
224
+ requestId: `chatds-${Date.now()}`,
225
+ sseHelper: streamHelper,
226
+ emitOperations,
227
+ forwardedHeaders
228
+ })).success) await streamHelper.writeOperation(errorOp("Unable to process request", "system"));
229
+ } catch (err) {
230
+ logger.error({ err }, "Streaming error");
231
+ await streamHelper.writeOperation(errorOp("Internal server error", "system"));
232
+ } finally {
233
+ if ("cleanup" in streamHelper && typeof streamHelper.cleanup === "function") streamHelper.cleanup();
234
+ }
235
+ } });
236
+ c.header("content-type", "text/event-stream");
237
+ c.header("cache-control", "no-cache");
238
+ c.header("connection", "keep-alive");
239
+ c.header("x-vercel-ai-data-stream", "v2");
240
+ c.header("x-accel-buffering", "no");
241
+ return stream(c, (stream$1) => stream$1.pipe(dataStream.pipeThrough(new JsonToSseTransformStream()).pipeThrough(new TextEncoderStream())));
242
+ });
243
+ } catch (error) {
244
+ logger.error({
245
+ error,
246
+ errorMessage: error instanceof Error ? error.message : String(error),
247
+ errorStack: error instanceof Error ? error.stack : void 0,
248
+ errorType: error?.constructor?.name
249
+ }, "chatDataStream error - DETAILED");
250
+ throw createApiError({
251
+ code: "internal_server_error",
252
+ message: "Failed to process chat completion"
253
+ });
254
+ }
255
+ });
256
+ const toolApprovalRoute = createRoute({
257
+ method: "post",
258
+ path: "/tool-approvals",
259
+ tags: ["chat"],
260
+ summary: "Approve or deny tool execution",
261
+ description: "Handle user approval/denial of tool execution requests during conversations",
262
+ security: [{ bearerAuth: [] }],
263
+ request: { body: { content: { "application/json": { schema: z.object({
264
+ conversationId: z.string().describe("The conversation ID"),
265
+ toolCallId: z.string().describe("The tool call ID to respond to"),
266
+ approved: z.boolean().describe("Whether the tool execution is approved"),
267
+ reason: z.string().optional().describe("Optional reason for the decision")
268
+ }) } } } },
269
+ responses: {
270
+ 200: {
271
+ description: "Tool approval response processed successfully",
272
+ content: { "application/json": { schema: z.object({
273
+ success: z.boolean(),
274
+ message: z.string().optional()
275
+ }) } }
276
+ },
277
+ 400: {
278
+ description: "Bad request - invalid tool call ID or conversation ID",
279
+ content: { "application/json": { schema: z.object({ error: z.string() }) } }
280
+ },
281
+ 404: {
282
+ description: "Tool call not found or already processed",
283
+ content: { "application/json": { schema: z.object({ error: z.string() }) } }
284
+ },
285
+ 500: {
286
+ description: "Internal server error",
287
+ content: { "application/json": { schema: z.object({
288
+ error: z.string(),
289
+ message: z.string()
290
+ }) } }
291
+ }
292
+ }
293
+ });
294
+ app.openapi(toolApprovalRoute, async (c) => {
295
+ return trace.getTracer("tool-approval-handler").startActiveSpan("tool_approval_request", async (span) => {
296
+ try {
297
+ const { tenantId, projectId } = getRequestExecutionContext(c);
298
+ const { conversationId, toolCallId, approved, reason } = await c.req.json();
299
+ logger.info({
300
+ conversationId,
301
+ toolCallId,
302
+ approved,
303
+ reason,
304
+ tenantId,
305
+ projectId
306
+ }, "Processing tool approval request");
307
+ if (!await getConversation(dbClient_default)({
308
+ scopes: {
309
+ tenantId,
310
+ projectId
311
+ },
312
+ conversationId
313
+ })) {
314
+ span.setStatus({
315
+ code: 1,
316
+ message: "Conversation not found"
317
+ });
318
+ return c.json({ error: "Conversation not found" }, 404);
319
+ }
320
+ let success = false;
321
+ if (approved) success = pendingToolApprovalManager.approveToolCall(toolCallId);
322
+ else success = pendingToolApprovalManager.denyToolCall(toolCallId, reason);
323
+ if (!success) {
324
+ span.setStatus({
325
+ code: 1,
326
+ message: "Tool call not found"
327
+ });
328
+ return c.json({ error: "Tool call not found or already processed" }, 404);
329
+ }
330
+ logger.info({
331
+ conversationId,
332
+ toolCallId,
333
+ approved
334
+ }, "Tool approval processed successfully");
335
+ span.setStatus({
336
+ code: 1,
337
+ message: "Success"
338
+ });
339
+ return c.json({
340
+ success: true,
341
+ message: approved ? "Tool execution approved" : "Tool execution denied"
342
+ });
343
+ } catch (error) {
344
+ const errorMessage = error instanceof Error ? error.message : "Unknown error";
345
+ logger.error({
346
+ error: errorMessage,
347
+ stack: error instanceof Error ? error.stack : void 0
348
+ }, "Failed to process tool approval");
349
+ span.setStatus({
350
+ code: 2,
351
+ message: errorMessage
352
+ });
353
+ return c.json({
354
+ error: "Internal server error",
355
+ message: errorMessage
356
+ }, 500);
357
+ } finally {
358
+ span.end();
359
+ }
360
+ });
361
+ });
362
+ var chatDataStream_default = app;
363
+
364
+ //#endregion
365
+ export { chatDataStream_default as default };
@@ -0,0 +1,13 @@
1
+ import { OpenAPIHono } from "@hono/zod-openapi";
2
+ import { CredentialStoreRegistry } from "@inkeep/agents-core";
3
+
4
+ //#region src/routes/mcp.d.ts
5
+ type AppVariables = {
6
+ credentialStores: CredentialStoreRegistry;
7
+ requestBody?: any;
8
+ };
9
+ declare const app: OpenAPIHono<{
10
+ Variables: AppVariables;
11
+ }, {}, "/">;
12
+ //#endregion
13
+ export { app as default };