veryfront 0.1.261 → 0.1.262

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 (53) hide show
  1. package/esm/cli/commands/knowledge/command.d.ts.map +1 -1
  2. package/esm/cli/commands/knowledge/command.js +19 -26
  3. package/esm/deno.js +1 -1
  4. package/esm/src/agent/ag-ui-detached-start.d.ts +1 -4
  5. package/esm/src/agent/ag-ui-detached-start.d.ts.map +1 -1
  6. package/esm/src/agent/ag-ui-detached-start.js +4 -67
  7. package/esm/src/agent/ag-ui-handler.d.ts +1 -4
  8. package/esm/src/agent/ag-ui-handler.d.ts.map +1 -1
  9. package/esm/src/agent/ag-ui-handler.js +3 -61
  10. package/esm/src/agent/ag-ui-host-support.d.ts.map +1 -1
  11. package/esm/src/agent/ag-ui-host-support.js +2 -21
  12. package/esm/src/agent/ag-ui-request-shared.d.ts +4 -0
  13. package/esm/src/agent/ag-ui-request-shared.d.ts.map +1 -0
  14. package/esm/src/agent/ag-ui-request-shared.js +47 -0
  15. package/esm/src/agent/ag-ui-run-control.d.ts.map +1 -1
  16. package/esm/src/agent/ag-ui-run-control.js +1 -23
  17. package/esm/src/agent/ag-ui-runtime-handler.d.ts +1 -5
  18. package/esm/src/agent/ag-ui-runtime-handler.d.ts.map +1 -1
  19. package/esm/src/agent/ag-ui-runtime-handler.js +3 -67
  20. package/esm/src/agent/ag-ui-tool-shared.d.ts +15 -0
  21. package/esm/src/agent/ag-ui-tool-shared.d.ts.map +1 -0
  22. package/esm/src/agent/ag-ui-tool-shared.js +47 -0
  23. package/esm/src/agent/index.d.ts +2 -0
  24. package/esm/src/agent/index.d.ts.map +1 -1
  25. package/esm/src/agent/index.js +1 -0
  26. package/esm/src/agent/runtime-ag-ui-contract.d.ts.map +1 -1
  27. package/esm/src/agent/runtime-ag-ui-contract.js +2 -21
  28. package/esm/src/chat/chat-ui-message-helpers.d.ts +18 -0
  29. package/esm/src/chat/chat-ui-message-helpers.d.ts.map +1 -0
  30. package/esm/src/chat/chat-ui-message-helpers.js +84 -0
  31. package/esm/src/chat/index.d.ts +2 -0
  32. package/esm/src/chat/index.d.ts.map +1 -1
  33. package/esm/src/chat/index.js +1 -0
  34. package/esm/src/chat/protocol.d.ts +109 -0
  35. package/esm/src/chat/protocol.d.ts.map +1 -1
  36. package/esm/src/utils/version-constant.d.ts +1 -1
  37. package/esm/src/utils/version-constant.js +1 -1
  38. package/package.json +1 -1
  39. package/src/cli/commands/knowledge/command.ts +27 -32
  40. package/src/deno.js +1 -1
  41. package/src/src/agent/ag-ui-detached-start.ts +4 -92
  42. package/src/src/agent/ag-ui-handler.ts +3 -81
  43. package/src/src/agent/ag-ui-host-support.ts +5 -28
  44. package/src/src/agent/ag-ui-request-shared.ts +62 -0
  45. package/src/src/agent/ag-ui-run-control.ts +1 -27
  46. package/src/src/agent/ag-ui-runtime-handler.ts +3 -86
  47. package/src/src/agent/ag-ui-tool-shared.ts +77 -0
  48. package/src/src/agent/index.ts +15 -0
  49. package/src/src/agent/runtime-ag-ui-contract.ts +5 -28
  50. package/src/src/chat/chat-ui-message-helpers.ts +114 -0
  51. package/src/src/chat/index.ts +17 -0
  52. package/src/src/chat/protocol.ts +148 -0
  53. package/src/src/utils/version-constant.ts +1 -1
@@ -1,13 +1,9 @@
1
1
  import { z } from "zod";
2
2
  import { INVALID_ARGUMENT } from "../errors/index.js";
3
- import { SKILL_TOOL_IDS } from "../skill/types.js";
4
- import { type Tool, toolRegistry } from "../tool/index.js";
5
3
  import { streamDataStreamEvents } from "./data-stream.js";
6
- import {
7
- type AgUiInjectedTool,
8
- AgUiRequestSchema,
9
- normalizeAgUiMessages,
10
- } from "./ag-ui-host-support.js";
4
+ import { AgUiRequestSchema, normalizeAgUiMessages } from "./ag-ui-host-support.js";
5
+ import { extractRequest } from "./ag-ui-request-shared.js";
6
+ import { type AgUiResumeValue, buildMergedAgUiTools } from "./ag-ui-tool-shared.js";
11
7
  import {
12
8
  AgentRuntime,
13
9
  RunAlreadyExistsError,
@@ -17,10 +13,6 @@ import type { Agent } from "./types.js";
17
13
 
18
14
  const AGENT_ID_PATTERN = /^[a-zA-Z0-9_-]+$/;
19
15
  const AG_UI_DETACHED_RUN_ID_SCHEMA = z.string().min(1).max(128).regex(AGENT_ID_PATTERN);
20
- type AgUiResumeValue = {
21
- result: unknown;
22
- isError: boolean;
23
- };
24
16
 
25
17
  type AgUiContextValue =
26
18
  | Record<string, unknown>
@@ -28,32 +20,6 @@ type AgUiContextValue =
28
20
 
29
21
  type AgUiRuntimePart = Record<string, unknown> & { type: string };
30
22
 
31
- function isRequest(obj: unknown): obj is Request {
32
- return (
33
- typeof obj === "object" &&
34
- obj !== null &&
35
- "json" in obj &&
36
- typeof obj.json === "function" &&
37
- "url" in obj &&
38
- typeof obj.url === "string" &&
39
- "method" in obj &&
40
- typeof obj.method === "string"
41
- );
42
- }
43
-
44
- function extractRequest(requestOrCtx: unknown): Request {
45
- if (isRequest(requestOrCtx)) return requestOrCtx;
46
-
47
- if (typeof requestOrCtx === "object" && requestOrCtx !== null && "request" in requestOrCtx) {
48
- const candidate = (requestOrCtx as Record<string, unknown>).request;
49
- if (isRequest(candidate)) return candidate;
50
- }
51
-
52
- throw INVALID_ARGUMENT.create({
53
- detail: "Invalid handler argument: expected Request or APIContext",
54
- });
55
- }
56
-
57
23
  function buildStreamContext(
58
24
  request: AgUiDetachedStartRequest,
59
25
  baseContext: Record<string, unknown>,
@@ -71,66 +37,12 @@ function buildStreamContext(
71
37
  };
72
38
  }
73
39
 
74
- function createInjectedAgUiTool(
75
- runId: string,
76
- tool: AgUiInjectedTool,
77
- sessionManager: RunResumeSessionManager<AgUiResumeValue>,
78
- ): Tool {
79
- return {
80
- id: tool.name,
81
- type: "function",
82
- description: tool.description ?? tool.name,
83
- inputSchema: z.record(z.string(), z.unknown()),
84
- inputSchemaJson: (tool.parameters ??
85
- { type: "object", properties: {}, additionalProperties: true }) as Tool["inputSchemaJson"],
86
- execute: async (_input, context) => {
87
- const toolCallId = typeof context?.toolCallId === "string" ? context.toolCallId : null;
88
- if (!toolCallId) {
89
- throw new Error(`Missing toolCallId for injected tool "${tool.name}"`);
90
- }
91
-
92
- sessionManager.prepareForSignal(runId, toolCallId);
93
- const submitted = await sessionManager.waitForSignal(runId, toolCallId);
94
- if (submitted.isError) {
95
- throw new Error(
96
- typeof submitted.result === "string"
97
- ? submitted.result
98
- : JSON.stringify(submitted.result),
99
- );
100
- }
101
- return submitted.result;
102
- },
103
- };
104
- }
105
-
106
40
  function buildMergedTools(
107
41
  agent: Agent,
108
42
  request: AgUiDetachedStartRequest,
109
43
  sessionManager: RunResumeSessionManager<AgUiResumeValue>,
110
44
  ): Agent["config"]["tools"] {
111
- const injectedTools = Object.fromEntries(
112
- request.tools.map((tool) => [
113
- tool.name,
114
- createInjectedAgUiTool(request.runId, tool, sessionManager),
115
- ]),
116
- );
117
-
118
- if (!agent.config.tools) {
119
- return Object.keys(injectedTools).length > 0 ? injectedTools : undefined;
120
- }
121
-
122
- if (agent.config.tools === true) {
123
- const merged: Record<string, Tool | boolean> = {};
124
- for (const [toolId] of toolRegistry.getAll()) {
125
- if (!agent.config.skills && SKILL_TOOL_IDS.has(toolId)) {
126
- continue;
127
- }
128
- merged[toolId] = true;
129
- }
130
- return { ...merged, ...injectedTools };
131
- }
132
-
133
- return { ...agent.config.tools, ...injectedTools };
45
+ return buildMergedAgUiTools(agent, request.runId, request.tools, sessionManager);
134
46
  }
135
47
 
136
48
  function scheduleDetachedTask(requestOrCtx: unknown, task: Promise<void>): void {
@@ -7,9 +7,6 @@ import {
7
7
  RunAlreadyExistsError,
8
8
  type RunResumeSessionManager,
9
9
  } from "./runtime/index.js";
10
- import { INVALID_ARGUMENT } from "../errors/index.js";
11
- import { SKILL_TOOL_IDS } from "../skill/types.js";
12
- import { type Tool, toolRegistry } from "../tool/index.js";
13
10
  import {
14
11
  createStreamTransformState,
15
12
  finalizeRunEvents,
@@ -18,11 +15,12 @@ import {
18
15
  } from "../internal-agents/ag-ui-sse.js";
19
16
  import { streamDataStreamEvents } from "./data-stream.js";
20
17
  import {
21
- type AgUiInjectedTool,
22
18
  type AgUiRequest,
23
19
  normalizeAgUiMessages,
24
20
  parseAgUiRequestOrError,
25
21
  } from "./ag-ui-host-support.js";
22
+ import { extractRequest } from "./ag-ui-request-shared.js";
23
+ import { type AgUiResumeValue, buildMergedAgUiTools } from "./ag-ui-tool-shared.js";
26
24
 
27
25
  export {
28
26
  type AgUiContextItem,
@@ -39,35 +37,8 @@ const AG_UI_HEADERS: Record<string, string> = {
39
37
  Connection: "keep-alive",
40
38
  };
41
39
 
42
- type AgUiResumeValue = { result: unknown; isError: boolean };
43
40
  type AgUiRuntimePart = Record<string, unknown> & { type: string };
44
41
 
45
- function isRequest(obj: unknown): obj is Request {
46
- return (
47
- typeof obj === "object" &&
48
- obj !== null &&
49
- "json" in obj &&
50
- typeof obj.json === "function" &&
51
- "url" in obj &&
52
- typeof obj.url === "string" &&
53
- "method" in obj &&
54
- typeof obj.method === "string"
55
- );
56
- }
57
-
58
- function extractRequest(requestOrCtx: unknown): Request {
59
- if (isRequest(requestOrCtx)) return requestOrCtx;
60
-
61
- if (typeof requestOrCtx === "object" && requestOrCtx !== null && "request" in requestOrCtx) {
62
- const candidate = (requestOrCtx as Record<string, unknown>).request;
63
- if (isRequest(candidate)) return candidate;
64
- }
65
-
66
- throw INVALID_ARGUMENT.create({
67
- detail: "Invalid handler argument: expected Request or APIContext",
68
- });
69
- }
70
-
71
42
  function generateRunId(): string {
72
43
  return `run_${dntShim.crypto.randomUUID().replaceAll("-", "")}`;
73
44
  }
@@ -240,38 +211,6 @@ async function createAgUiDirectStreamResponse(
240
211
  });
241
212
  }
242
213
 
243
- function createInjectedAgUiTool(
244
- runId: string,
245
- tool: AgUiInjectedTool,
246
- sessionManager: RunResumeSessionManager<AgUiResumeValue>,
247
- ): Tool {
248
- return {
249
- id: tool.name,
250
- type: "function",
251
- description: tool.description ?? tool.name,
252
- inputSchema: z.record(z.string(), z.unknown()),
253
- inputSchemaJson: (tool.parameters ??
254
- { type: "object", properties: {}, additionalProperties: true }) as Tool["inputSchemaJson"],
255
- execute: async (_input, context) => {
256
- const toolCallId = typeof context?.toolCallId === "string" ? context.toolCallId : null;
257
- if (!toolCallId) {
258
- throw new Error(`Missing toolCallId for injected tool "${tool.name}"`);
259
- }
260
-
261
- sessionManager.prepareForSignal(runId, toolCallId);
262
- const submitted = await sessionManager.waitForSignal(runId, toolCallId);
263
- if (submitted.isError) {
264
- throw new Error(
265
- typeof submitted.result === "string"
266
- ? submitted.result
267
- : JSON.stringify(submitted.result),
268
- );
269
- }
270
- return submitted.result;
271
- },
272
- };
273
- }
274
-
275
214
  async function createAgUiInjectedToolsStreamResponse(
276
215
  agent: Agent,
277
216
  request: AgUiRequest,
@@ -290,26 +229,9 @@ async function createAgUiInjectedToolsStreamResponse(
290
229
  throw error;
291
230
  }
292
231
 
293
- const injectedTools = Object.fromEntries(
294
- request.tools.map((tool) => [tool.name, createInjectedAgUiTool(runId, tool, sessionManager)]),
295
- );
296
-
297
- const mergedTools: Agent["config"]["tools"] = !agent.config.tools
298
- ? injectedTools
299
- : agent.config.tools === true
300
- ? {
301
- ...Object.fromEntries(
302
- [...toolRegistry.getAll()]
303
- .filter(([toolId]) => agent.config.skills || !SKILL_TOOL_IDS.has(toolId))
304
- .map(([toolId]) => [toolId, true]),
305
- ),
306
- ...injectedTools,
307
- }
308
- : { ...agent.config.tools, ...injectedTools };
309
-
310
232
  const runtime = new AgentRuntime(agent.id, {
311
233
  ...agent.config,
312
- tools: mergedTools,
234
+ tools: buildMergedAgUiTools(agent, runId, request.tools, sessionManager),
313
235
  });
314
236
 
315
237
  let upstreamBody: ReadableStream<Uint8Array>;
@@ -1,6 +1,7 @@
1
1
  import { z } from "zod";
2
2
  import { formatAgUiEvent } from "../internal-agents/ag-ui-sse.js";
3
3
  import type { Message } from "./types.js";
4
+ import { parseAgUiJsonRequestOrError } from "./ag-ui-request-shared.js";
4
5
 
5
6
  const AGENT_ID_PATTERN = /^[a-zA-Z0-9_-]+$/;
6
7
  const MAX_TOOL_PARAMETERS_BYTES = 16_384;
@@ -173,34 +174,10 @@ export async function parseAgUiRequest(request: Request): Promise<AgUiRequest> {
173
174
  export async function parseAgUiRequestOrError(
174
175
  request: Request,
175
176
  ): Promise<AgUiRequest | Response> {
176
- try {
177
- return await parseAgUiRequest(request);
178
- } catch (error) {
179
- if (error instanceof z.ZodError) {
180
- return Response.json(
181
- {
182
- error: "Invalid AG-UI request",
183
- details: error.issues.map((issue) => ({
184
- path: issue.path,
185
- message: issue.message,
186
- })),
187
- },
188
- { status: 400 },
189
- );
190
- }
191
-
192
- if (error instanceof SyntaxError || error instanceof TypeError) {
193
- return Response.json(
194
- {
195
- error: "Invalid AG-UI request",
196
- details: [{ path: [], message: "Malformed JSON request body" }],
197
- },
198
- { status: 400 },
199
- );
200
- }
201
-
202
- throw error;
203
- }
177
+ return await parseAgUiJsonRequestOrError(
178
+ () => parseAgUiRequest(request),
179
+ "Invalid AG-UI request",
180
+ );
204
181
  }
205
182
 
206
183
  export function normalizeAgUiMessages(messages: AgUiRequest["messages"]): Message[] {
@@ -0,0 +1,62 @@
1
+ import { z } from "zod";
2
+ import { INVALID_ARGUMENT } from "../errors/index.js";
3
+
4
+ export function isRequest(value: unknown): value is Request {
5
+ return (
6
+ typeof value === "object" &&
7
+ value !== null &&
8
+ "json" in value &&
9
+ typeof value.json === "function" &&
10
+ "url" in value &&
11
+ typeof value.url === "string" &&
12
+ "method" in value &&
13
+ typeof value.method === "string"
14
+ );
15
+ }
16
+
17
+ export function extractRequest(requestOrCtx: unknown): Request {
18
+ if (isRequest(requestOrCtx)) return requestOrCtx;
19
+
20
+ if (typeof requestOrCtx === "object" && requestOrCtx !== null && "request" in requestOrCtx) {
21
+ const candidate = (requestOrCtx as Record<string, unknown>).request;
22
+ if (isRequest(candidate)) return candidate;
23
+ }
24
+
25
+ throw INVALID_ARGUMENT.create({
26
+ detail: "Invalid handler argument: expected Request or APIContext",
27
+ });
28
+ }
29
+
30
+ export async function parseAgUiJsonRequestOrError<T>(
31
+ parseRequest: () => Promise<T>,
32
+ errorLabel: string,
33
+ ): Promise<T | Response> {
34
+ try {
35
+ return await parseRequest();
36
+ } catch (error) {
37
+ if (error instanceof z.ZodError) {
38
+ return Response.json(
39
+ {
40
+ error: errorLabel,
41
+ details: error.issues.map((issue) => ({
42
+ path: issue.path,
43
+ message: issue.message,
44
+ })),
45
+ },
46
+ { status: 400 },
47
+ );
48
+ }
49
+
50
+ if (error instanceof SyntaxError || error instanceof TypeError) {
51
+ return Response.json(
52
+ {
53
+ error: errorLabel,
54
+ details: [{ path: [], message: "Malformed JSON request body" }],
55
+ },
56
+ { status: 400 },
57
+ );
58
+ }
59
+
60
+ throw error;
61
+ }
62
+ }
@@ -1,5 +1,5 @@
1
1
  import { z } from "zod";
2
- import { INVALID_ARGUMENT } from "../errors/index.js";
2
+ import { extractRequest } from "./ag-ui-request-shared.js";
3
3
  import {
4
4
  RunNotActiveError,
5
5
  RunResumeSessionManager,
@@ -26,32 +26,6 @@ type ResumeValue = {
26
26
  isError: boolean;
27
27
  };
28
28
 
29
- function isRequest(value: unknown): value is Request {
30
- return (
31
- typeof value === "object" &&
32
- value !== null &&
33
- "json" in value &&
34
- typeof value.json === "function" &&
35
- "url" in value &&
36
- typeof value.url === "string" &&
37
- "method" in value &&
38
- typeof value.method === "string"
39
- );
40
- }
41
-
42
- function extractRequest(requestOrCtx: unknown): Request {
43
- if (isRequest(requestOrCtx)) return requestOrCtx;
44
-
45
- if (typeof requestOrCtx === "object" && requestOrCtx !== null && "request" in requestOrCtx) {
46
- const candidate = (requestOrCtx as Record<string, unknown>).request;
47
- if (isRequest(candidate)) return candidate;
48
- }
49
-
50
- throw INVALID_ARGUMENT.create({
51
- detail: "Invalid handler argument: expected Request or APIContext",
52
- });
53
- }
54
-
55
29
  function getRunId(pathname: string, regex: RegExp): string | null {
56
30
  return regex.exec(pathname)?.[1] ?? null;
57
31
  }
@@ -1,7 +1,4 @@
1
1
  import { z } from "zod";
2
- import { INVALID_ARGUMENT } from "../errors/index.js";
3
- import { SKILL_TOOL_IDS } from "../skill/types.js";
4
- import { type Tool, toolRegistry } from "../tool/index.js";
5
2
  import {
6
3
  AgentRuntime,
7
4
  RunAlreadyExistsError,
@@ -9,10 +6,11 @@ import {
9
6
  } from "./runtime/index.js";
10
7
  import type { Agent } from "./types.js";
11
8
  import {
12
- type AgUiRuntimeInjectedTool,
13
9
  type AgUiRuntimeRequest,
14
10
  parseAgUiRuntimeRequestOrError,
15
11
  } from "./runtime-ag-ui-contract.js";
12
+ import { extractRequest } from "./ag-ui-request-shared.js";
13
+ import { type AgUiResumeValue, buildMergedAgUiTools } from "./ag-ui-tool-shared.js";
16
14
  import { normalizeAgUiRuntimeMessages } from "./ag-ui-runtime-support.js";
17
15
  import {
18
16
  createStreamTransformState,
@@ -28,7 +26,6 @@ const AG_UI_HEADERS: Record<string, string> = {
28
26
  Connection: "keep-alive",
29
27
  };
30
28
 
31
- type AgUiResumeValue = { result: unknown; isError: boolean };
32
29
  type AgUiRuntimePart = Record<string, unknown> & { type: string };
33
30
 
34
31
  export interface AgUiRuntimeLifecycleContext {
@@ -64,36 +61,10 @@ async function invokeLifecycleCallbackAndWait(
64
61
  }
65
62
  }
66
63
 
67
- function isRequest(obj: unknown): obj is Request {
68
- return (
69
- typeof obj === "object" &&
70
- obj !== null &&
71
- "json" in obj &&
72
- typeof obj.json === "function" &&
73
- "url" in obj &&
74
- typeof obj.url === "string" &&
75
- "method" in obj &&
76
- typeof obj.method === "string"
77
- );
78
- }
79
-
80
64
  function isRecord(value: unknown): value is Record<string, unknown> {
81
65
  return typeof value === "object" && value !== null && !Array.isArray(value);
82
66
  }
83
67
 
84
- function extractRequest(requestOrCtx: unknown): Request {
85
- if (isRequest(requestOrCtx)) return requestOrCtx;
86
-
87
- if (typeof requestOrCtx === "object" && requestOrCtx !== null && "request" in requestOrCtx) {
88
- const candidate = (requestOrCtx as Record<string, unknown>).request;
89
- if (isRequest(candidate)) return candidate;
90
- }
91
-
92
- throw INVALID_ARGUMENT.create({
93
- detail: "Invalid handler argument: expected Request or APIContext",
94
- });
95
- }
96
-
97
68
  function buildStreamContext(
98
69
  request: AgUiRuntimeRequest,
99
70
  baseContext: Record<string, unknown>,
@@ -271,66 +242,12 @@ async function createAgUiRuntimeDirectStreamResponse(
271
242
  });
272
243
  }
273
244
 
274
- function createInjectedAgUiTool(
275
- runId: string,
276
- tool: AgUiRuntimeInjectedTool,
277
- sessionManager: RunResumeSessionManager<AgUiResumeValue>,
278
- ): Tool {
279
- return {
280
- id: tool.name,
281
- type: "function",
282
- description: tool.description ?? tool.name,
283
- inputSchema: z.record(z.string(), z.unknown()),
284
- inputSchemaJson: (tool.parameters ??
285
- { type: "object", properties: {}, additionalProperties: true }) as Tool["inputSchemaJson"],
286
- execute: async (_input, context) => {
287
- const toolCallId = typeof context?.toolCallId === "string" ? context.toolCallId : null;
288
- if (!toolCallId) {
289
- throw new Error(`Missing toolCallId for injected tool "${tool.name}"`);
290
- }
291
-
292
- sessionManager.prepareForSignal(runId, toolCallId);
293
- const submitted = await sessionManager.waitForSignal(runId, toolCallId);
294
- if (submitted.isError) {
295
- throw new Error(
296
- typeof submitted.result === "string"
297
- ? submitted.result
298
- : JSON.stringify(submitted.result),
299
- );
300
- }
301
- return submitted.result;
302
- },
303
- };
304
- }
305
-
306
245
  function buildMergedTools(
307
246
  agent: Agent,
308
247
  request: AgUiRuntimeRequest,
309
248
  sessionManager: RunResumeSessionManager<AgUiResumeValue>,
310
249
  ): Agent["config"]["tools"] {
311
- const injectedTools = Object.fromEntries(
312
- request.tools.map((tool) => [
313
- tool.name,
314
- createInjectedAgUiTool(request.runId, tool, sessionManager),
315
- ]),
316
- );
317
-
318
- if (!agent.config.tools) {
319
- return Object.keys(injectedTools).length > 0 ? injectedTools : undefined;
320
- }
321
-
322
- if (agent.config.tools === true) {
323
- const merged: Record<string, Tool | boolean> = {};
324
- for (const [toolId] of toolRegistry.getAll()) {
325
- if (!agent.config.skills && SKILL_TOOL_IDS.has(toolId)) {
326
- continue;
327
- }
328
- merged[toolId] = true;
329
- }
330
- return { ...merged, ...injectedTools };
331
- }
332
-
333
- return { ...agent.config.tools, ...injectedTools };
250
+ return buildMergedAgUiTools(agent, request.runId, request.tools, sessionManager);
334
251
  }
335
252
 
336
253
  async function createAgUiRuntimeInjectedToolsStreamResponse(
@@ -0,0 +1,77 @@
1
+ import { z } from "zod";
2
+ import { SKILL_TOOL_IDS } from "../skill/types.js";
3
+ import { toolRegistry } from "../tool/registry.js";
4
+ import type { Tool } from "../tool/types.js";
5
+ import type { RunResumeSessionManager } from "./runtime/index.js";
6
+ import type { Agent } from "./types.js";
7
+
8
+ export type AgUiResumeValue = { result: unknown; isError: boolean };
9
+
10
+ export interface AgUiInjectedToolLike {
11
+ name: string;
12
+ description?: string;
13
+ parameters?: unknown;
14
+ }
15
+
16
+ export function createInjectedAgUiTool(
17
+ runId: string,
18
+ tool: AgUiInjectedToolLike,
19
+ sessionManager: RunResumeSessionManager<AgUiResumeValue>,
20
+ ): Tool {
21
+ return {
22
+ id: tool.name,
23
+ type: "function",
24
+ description: tool.description ?? tool.name,
25
+ inputSchema: z.record(z.string(), z.unknown()),
26
+ inputSchemaJson: (tool.parameters ??
27
+ { type: "object", properties: {}, additionalProperties: true }) as Tool["inputSchemaJson"],
28
+ execute: async (_input, context) => {
29
+ const toolCallId = typeof context?.toolCallId === "string" ? context.toolCallId : null;
30
+ if (!toolCallId) {
31
+ throw new Error(`Missing toolCallId for injected tool "${tool.name}"`);
32
+ }
33
+
34
+ sessionManager.prepareForSignal(runId, toolCallId);
35
+ const submitted = await sessionManager.waitForSignal(runId, toolCallId);
36
+ if (submitted.isError) {
37
+ throw new Error(
38
+ typeof submitted.result === "string"
39
+ ? submitted.result
40
+ : JSON.stringify(submitted.result),
41
+ );
42
+ }
43
+ return submitted.result;
44
+ },
45
+ };
46
+ }
47
+
48
+ export function buildMergedAgUiTools(
49
+ agent: Agent,
50
+ runId: string,
51
+ tools: AgUiInjectedToolLike[],
52
+ sessionManager: RunResumeSessionManager<AgUiResumeValue>,
53
+ ): Agent["config"]["tools"] {
54
+ const injectedTools = Object.fromEntries(
55
+ tools.map((tool) => [
56
+ tool.name,
57
+ createInjectedAgUiTool(runId, tool, sessionManager),
58
+ ]),
59
+ );
60
+
61
+ if (!agent.config.tools) {
62
+ return Object.keys(injectedTools).length > 0 ? injectedTools : undefined;
63
+ }
64
+
65
+ if (agent.config.tools === true) {
66
+ const merged: Record<string, Tool | boolean> = {};
67
+ for (const [toolId] of toolRegistry.getAll()) {
68
+ if (!agent.config.skills && SKILL_TOOL_IDS.has(toolId)) {
69
+ continue;
70
+ }
71
+ merged[toolId] = true;
72
+ }
73
+ return { ...merged, ...injectedTools };
74
+ }
75
+
76
+ return { ...agent.config.tools, ...injectedTools };
77
+ }
@@ -379,6 +379,21 @@ export {
379
379
  streamDataStreamEvents,
380
380
  stripLeadingEmptyObjectPlaceholder,
381
381
  } from "./data-stream.js";
382
+ export type {
383
+ ChatMessageMetadata,
384
+ ChatMessageMetadataUsage,
385
+ ChatUiMessageChunk,
386
+ ChildRunAudit,
387
+ ChildRunAuditToolCall,
388
+ ChildRunAuditToolResult,
389
+ } from "../chat/protocol.js";
390
+ export {
391
+ buildChatStreamChunkMessageMetadata,
392
+ type BuildChatStreamChunkMessageMetadataInput,
393
+ extractChatMessageMetadata,
394
+ normalizeChatMessageMetadata,
395
+ normalizeChatUiMessageChunk,
396
+ } from "../chat/chat-ui-message-helpers.js";
382
397
  export {
383
398
  expandAllowedRemoteToolNames,
384
399
  getProviderNativeToolNames,
@@ -1,4 +1,5 @@
1
1
  import { z } from "zod";
2
+ import { parseAgUiJsonRequestOrError } from "./ag-ui-request-shared.js";
2
3
 
3
4
  const AGENT_ID_PATTERN = /^[a-zA-Z0-9_-]+$/;
4
5
  const MAX_TOOL_PARAMETERS_BYTES = 16_384;
@@ -172,32 +173,8 @@ export async function parseAgUiRuntimeRequest(request: Request): Promise<AgUiRun
172
173
  export async function parseAgUiRuntimeRequestOrError(
173
174
  request: Request,
174
175
  ): Promise<AgUiRuntimeRequest | Response> {
175
- try {
176
- return await parseAgUiRuntimeRequest(request);
177
- } catch (error) {
178
- if (error instanceof z.ZodError) {
179
- return Response.json(
180
- {
181
- error: "Invalid AG-UI runtime request",
182
- details: error.issues.map((issue) => ({
183
- path: issue.path,
184
- message: issue.message,
185
- })),
186
- },
187
- { status: 400 },
188
- );
189
- }
190
-
191
- if (error instanceof SyntaxError || error instanceof TypeError) {
192
- return Response.json(
193
- {
194
- error: "Invalid AG-UI runtime request",
195
- details: [{ path: [], message: "Malformed JSON request body" }],
196
- },
197
- { status: 400 },
198
- );
199
- }
200
-
201
- throw error;
202
- }
176
+ return await parseAgUiJsonRequestOrError(
177
+ () => parseAgUiRuntimeRequest(request),
178
+ "Invalid AG-UI runtime request",
179
+ );
203
180
  }