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