@tanstack/ai 0.36.0 → 0.38.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 (215) hide show
  1. package/dist/esm/activities/chat/adapter.d.ts +163 -0
  2. package/dist/esm/activities/chat/adapter.js +17 -0
  3. package/dist/esm/activities/chat/adapter.js.map +1 -0
  4. package/dist/esm/activities/chat/agent-loop-strategies.d.ts +59 -0
  5. package/dist/esm/activities/chat/agent-loop-strategies.js +23 -0
  6. package/dist/esm/activities/chat/agent-loop-strategies.js.map +1 -0
  7. package/dist/esm/activities/chat/index.d.ts +270 -0
  8. package/dist/esm/activities/chat/index.js +1724 -0
  9. package/dist/esm/activities/chat/index.js.map +1 -0
  10. package/dist/esm/activities/chat/mcp/manager.d.ts +25 -0
  11. package/dist/esm/activities/chat/mcp/manager.js +80 -0
  12. package/dist/esm/activities/chat/mcp/manager.js.map +1 -0
  13. package/dist/esm/activities/chat/mcp/types.d.ts +78 -0
  14. package/dist/esm/activities/chat/messages.d.ts +78 -0
  15. package/dist/esm/activities/chat/messages.js +374 -0
  16. package/dist/esm/activities/chat/messages.js.map +1 -0
  17. package/dist/esm/activities/chat/middleware/builder.d.ts +46 -0
  18. package/dist/esm/activities/chat/middleware/builder.js +17 -0
  19. package/dist/esm/activities/chat/middleware/builder.js.map +1 -0
  20. package/dist/esm/activities/chat/middleware/capabilities.d.ts +93 -0
  21. package/dist/esm/activities/chat/middleware/capabilities.js +45 -0
  22. package/dist/esm/activities/chat/middleware/capabilities.js.map +1 -0
  23. package/dist/esm/activities/chat/middleware/compose.d.ts +87 -0
  24. package/dist/esm/activities/chat/middleware/compose.js +510 -0
  25. package/dist/esm/activities/chat/middleware/compose.js.map +1 -0
  26. package/dist/esm/activities/chat/middleware/define.d.ts +20 -0
  27. package/dist/esm/activities/chat/middleware/define.js +7 -0
  28. package/dist/esm/activities/chat/middleware/define.js.map +1 -0
  29. package/dist/esm/activities/chat/middleware/index.d.ts +10 -0
  30. package/dist/esm/activities/chat/middleware/tool-cache-middleware.d.ts +89 -0
  31. package/dist/esm/activities/chat/middleware/tool-cache-middleware.js +76 -0
  32. package/dist/esm/activities/chat/middleware/tool-cache-middleware.js.map +1 -0
  33. package/dist/esm/activities/chat/middleware/types.d.ts +405 -0
  34. package/dist/esm/activities/chat/middleware/validate.d.ts +19 -0
  35. package/dist/esm/activities/chat/middleware/validate.js +30 -0
  36. package/dist/esm/activities/chat/middleware/validate.js.map +1 -0
  37. package/dist/esm/activities/chat/runtime-context-types.d.ts +43 -0
  38. package/dist/esm/activities/chat/stream/index.d.ts +11 -0
  39. package/dist/esm/activities/chat/stream/json-parser.d.ts +38 -0
  40. package/dist/esm/activities/chat/stream/json-parser.js +28 -0
  41. package/dist/esm/activities/chat/stream/json-parser.js.map +1 -0
  42. package/dist/esm/activities/chat/stream/message-updaters.d.ts +81 -0
  43. package/dist/esm/activities/chat/stream/message-updaters.js +253 -0
  44. package/dist/esm/activities/chat/stream/message-updaters.js.map +1 -0
  45. package/dist/esm/activities/chat/stream/processor.d.ts +439 -0
  46. package/dist/esm/activities/chat/stream/processor.js +1449 -0
  47. package/dist/esm/activities/chat/stream/processor.js.map +1 -0
  48. package/dist/esm/activities/chat/stream/strategies.d.ts +43 -0
  49. package/dist/esm/activities/chat/stream/strategies.js +54 -0
  50. package/dist/esm/activities/chat/stream/strategies.js.map +1 -0
  51. package/dist/esm/activities/chat/stream/types.d.ts +90 -0
  52. package/dist/esm/activities/chat/tools/lazy-tool-manager.d.ts +82 -0
  53. package/dist/esm/activities/chat/tools/lazy-tool-manager.js +194 -0
  54. package/dist/esm/activities/chat/tools/lazy-tool-manager.js.map +1 -0
  55. package/dist/esm/activities/chat/tools/lazy-tools.d.ts +15 -0
  56. package/dist/esm/activities/chat/tools/lazy-tools.js +16 -0
  57. package/dist/esm/activities/chat/tools/lazy-tools.js.map +1 -0
  58. package/dist/esm/activities/chat/tools/schema-converter.d.ts +140 -0
  59. package/dist/esm/activities/chat/tools/schema-converter.js +167 -0
  60. package/dist/esm/activities/chat/tools/schema-converter.js.map +1 -0
  61. package/dist/esm/activities/chat/tools/tool-calls.d.ts +145 -0
  62. package/dist/esm/activities/chat/tools/tool-calls.js +548 -0
  63. package/dist/esm/activities/chat/tools/tool-calls.js.map +1 -0
  64. package/dist/esm/activities/chat/tools/tool-definition.d.ts +135 -0
  65. package/dist/esm/activities/chat/tools/tool-definition.js +25 -0
  66. package/dist/esm/activities/chat/tools/tool-definition.js.map +1 -0
  67. package/dist/esm/activities/error-payload.d.ts +30 -0
  68. package/dist/esm/activities/error-payload.js +54 -0
  69. package/dist/esm/activities/error-payload.js.map +1 -0
  70. package/dist/esm/activities/generateAudio/adapter.d.ts +62 -0
  71. package/dist/esm/activities/generateAudio/adapter.js +16 -0
  72. package/dist/esm/activities/generateAudio/adapter.js.map +1 -0
  73. package/dist/esm/activities/generateAudio/index.d.ts +85 -0
  74. package/dist/esm/activities/generateAudio/index.js +114 -0
  75. package/dist/esm/activities/generateAudio/index.js.map +1 -0
  76. package/dist/esm/activities/generateImage/adapter.d.ts +78 -0
  77. package/dist/esm/activities/generateImage/adapter.js +16 -0
  78. package/dist/esm/activities/generateImage/adapter.js.map +1 -0
  79. package/dist/esm/activities/generateImage/index.d.ts +134 -0
  80. package/dist/esm/activities/generateImage/index.js +121 -0
  81. package/dist/esm/activities/generateImage/index.js.map +1 -0
  82. package/dist/esm/activities/generateSpeech/adapter.d.ts +62 -0
  83. package/dist/esm/activities/generateSpeech/adapter.js +16 -0
  84. package/dist/esm/activities/generateSpeech/adapter.js.map +1 -0
  85. package/dist/esm/activities/generateSpeech/index.d.ts +96 -0
  86. package/dist/esm/activities/generateSpeech/index.js +119 -0
  87. package/dist/esm/activities/generateSpeech/index.js.map +1 -0
  88. package/dist/esm/activities/generateTranscription/adapter.d.ts +62 -0
  89. package/dist/esm/activities/generateTranscription/adapter.js +16 -0
  90. package/dist/esm/activities/generateTranscription/adapter.js.map +1 -0
  91. package/dist/esm/activities/generateTranscription/index.d.ts +109 -0
  92. package/dist/esm/activities/generateTranscription/index.js +109 -0
  93. package/dist/esm/activities/generateTranscription/index.js.map +1 -0
  94. package/dist/esm/activities/generateVideo/adapter.d.ts +145 -0
  95. package/dist/esm/activities/generateVideo/adapter.js +30 -0
  96. package/dist/esm/activities/generateVideo/adapter.js.map +1 -0
  97. package/dist/esm/activities/generateVideo/index.d.ts +223 -0
  98. package/dist/esm/activities/generateVideo/index.js +295 -0
  99. package/dist/esm/activities/generateVideo/index.js.map +1 -0
  100. package/dist/esm/activities/generateVideo/snap.d.ts +14 -0
  101. package/dist/esm/activities/generateVideo/snap.js +54 -0
  102. package/dist/esm/activities/generateVideo/snap.js.map +1 -0
  103. package/dist/esm/activities/index.d.ts +27 -0
  104. package/dist/esm/activities/index.js +43 -0
  105. package/dist/esm/activities/index.js.map +1 -0
  106. package/dist/esm/activities/middleware/index.d.ts +2 -0
  107. package/dist/esm/activities/middleware/run.d.ts +20 -0
  108. package/dist/esm/activities/middleware/run.js +42 -0
  109. package/dist/esm/activities/middleware/run.js.map +1 -0
  110. package/dist/esm/activities/middleware/types.d.ts +118 -0
  111. package/dist/esm/activities/stream-generation-result.d.ts +15 -0
  112. package/dist/esm/activities/stream-generation-result.js +49 -0
  113. package/dist/esm/activities/stream-generation-result.js.map +1 -0
  114. package/dist/esm/activities/summarize/adapter.d.ts +74 -0
  115. package/dist/esm/activities/summarize/adapter.js +16 -0
  116. package/dist/esm/activities/summarize/adapter.js.map +1 -0
  117. package/dist/esm/activities/summarize/chat-stream-summarize.d.ts +45 -0
  118. package/dist/esm/activities/summarize/chat-stream-summarize.js +212 -0
  119. package/dist/esm/activities/summarize/chat-stream-summarize.js.map +1 -0
  120. package/dist/esm/activities/summarize/index.d.ts +108 -0
  121. package/dist/esm/activities/summarize/index.js +113 -0
  122. package/dist/esm/activities/summarize/index.js.map +1 -0
  123. package/dist/esm/adapter-internals.d.ts +5 -0
  124. package/dist/esm/adapter-internals.js +10 -0
  125. package/dist/esm/adapter-internals.js.map +1 -0
  126. package/dist/esm/client.d.ts +44 -0
  127. package/dist/esm/client.js +67 -0
  128. package/dist/esm/client.js.map +1 -0
  129. package/dist/esm/extend-adapter.d.ts +152 -0
  130. package/dist/esm/extend-adapter.js +21 -0
  131. package/dist/esm/extend-adapter.js.map +1 -0
  132. package/dist/esm/index.d.ts +45 -0
  133. package/dist/esm/index.js +109 -0
  134. package/dist/esm/index.js.map +1 -0
  135. package/dist/esm/logger/console-logger.d.ts +29 -0
  136. package/dist/esm/logger/console-logger.js +83 -0
  137. package/dist/esm/logger/console-logger.js.map +1 -0
  138. package/dist/esm/logger/internal-logger.d.ts +41 -0
  139. package/dist/esm/logger/internal-logger.js +86 -0
  140. package/dist/esm/logger/internal-logger.js.map +1 -0
  141. package/dist/esm/logger/resolve.d.ts +14 -0
  142. package/dist/esm/logger/resolve.js +54 -0
  143. package/dist/esm/logger/resolve.js.map +1 -0
  144. package/dist/esm/logger/types.d.ts +75 -0
  145. package/dist/esm/middlewares/content-guard.d.ts +77 -0
  146. package/dist/esm/middlewares/content-guard.js +156 -0
  147. package/dist/esm/middlewares/content-guard.js.map +1 -0
  148. package/dist/esm/middlewares/index.d.ts +2 -0
  149. package/dist/esm/middlewares/index.js +7 -0
  150. package/dist/esm/middlewares/index.js.map +1 -0
  151. package/dist/esm/middlewares/otel.d.ts +81 -0
  152. package/dist/esm/middlewares/otel.js +745 -0
  153. package/dist/esm/middlewares/otel.js.map +1 -0
  154. package/dist/esm/middlewares/tool-cache.d.ts +1 -0
  155. package/dist/esm/middlewares/usage-attributes.d.ts +24 -0
  156. package/dist/esm/middlewares/usage-attributes.js +43 -0
  157. package/dist/esm/middlewares/usage-attributes.js.map +1 -0
  158. package/dist/esm/realtime/index.d.ts +28 -0
  159. package/dist/esm/realtime/index.js +8 -0
  160. package/dist/esm/realtime/index.js.map +1 -0
  161. package/dist/esm/realtime/types.d.ts +282 -0
  162. package/dist/esm/stream-to-response.d.ts +102 -0
  163. package/dist/esm/stream-to-response.js +121 -0
  164. package/dist/esm/stream-to-response.js.map +1 -0
  165. package/dist/esm/strip-to-spec-middleware.d.ts +18 -0
  166. package/dist/esm/strip-to-spec-middleware.js +20 -0
  167. package/dist/esm/strip-to-spec-middleware.js.map +1 -0
  168. package/dist/esm/system-prompts.d.ts +66 -0
  169. package/dist/esm/system-prompts.js +23 -0
  170. package/dist/esm/system-prompts.js.map +1 -0
  171. package/dist/esm/tool-registry.d.ts +81 -0
  172. package/dist/esm/tool-registry.js +49 -0
  173. package/dist/esm/tool-registry.js.map +1 -0
  174. package/dist/esm/tools/provider-tool.d.ts +30 -0
  175. package/dist/esm/tools/provider-tool.js +7 -0
  176. package/dist/esm/tools/provider-tool.js.map +1 -0
  177. package/dist/esm/types.d.ts +1627 -0
  178. package/dist/esm/utilities/ag-ui-wire.d.ts +44 -0
  179. package/dist/esm/utilities/ag-ui-wire.js +107 -0
  180. package/dist/esm/utilities/ag-ui-wire.js.map +1 -0
  181. package/dist/esm/utilities/chat-params.d.ts +85 -0
  182. package/dist/esm/utilities/chat-params.js +100 -0
  183. package/dist/esm/utilities/chat-params.js.map +1 -0
  184. package/dist/esm/utilities/errors.d.ts +13 -0
  185. package/dist/esm/utilities/errors.js +22 -0
  186. package/dist/esm/utilities/errors.js.map +1 -0
  187. package/dist/esm/utilities/media-prompt.d.ts +35 -0
  188. package/dist/esm/utilities/media-prompt.js +43 -0
  189. package/dist/esm/utilities/media-prompt.js.map +1 -0
  190. package/dist/esm/utilities/numbers.d.ts +8 -0
  191. package/dist/esm/utilities/numbers.js +12 -0
  192. package/dist/esm/utilities/numbers.js.map +1 -0
  193. package/dist/esm/utilities/sampling-keys.d.ts +20 -0
  194. package/dist/esm/utilities/sampling-keys.js +20 -0
  195. package/dist/esm/utilities/sampling-keys.js.map +1 -0
  196. package/dist/esm/utilities/tool-result.d.ts +21 -0
  197. package/dist/esm/utilities/tool-result.js +37 -0
  198. package/dist/esm/utilities/tool-result.js.map +1 -0
  199. package/dist/esm/utilities/usage.d.ts +31 -0
  200. package/dist/esm/utilities/usage.js +11 -0
  201. package/dist/esm/utilities/usage.js.map +1 -0
  202. package/dist/esm/utils.d.ts +17 -0
  203. package/dist/esm/utils.js +20 -0
  204. package/dist/esm/utils.js.map +1 -0
  205. package/package.json +3 -3
  206. package/skills/ai-core/chat-experience/SKILL.md +30 -2
  207. package/skills/ai-core/media-generation/SKILL.md +13 -0
  208. package/skills/ai-core/tool-calling/SKILL.md +10 -3
  209. package/src/activities/chat/mcp/manager.ts +31 -1
  210. package/src/activities/chat/mcp/types.ts +23 -0
  211. package/src/activities/chat/messages.ts +5 -0
  212. package/src/activities/chat/stream/processor.ts +42 -0
  213. package/src/activities/chat/tools/tool-calls.ts +96 -2
  214. package/src/client.ts +1 -0
  215. package/src/types.ts +31 -0
@@ -0,0 +1,145 @@
1
+ import { AnyTool, CustomEvent, ModelMessage, RunFinishedEvent, Tool, ToolCall, ToolCallArgsEvent, ToolCallEndEvent, ToolCallStartEvent, ToolExecutionContext } from '../../../types.js';
2
+ import { AfterToolCallInfo, BeforeToolCallDecision } from '../middleware/types.js';
3
+ import { ContextFromTool, DefinedContext, MergeContext, UnionToIntersection } from '../runtime-context-types.js';
4
+ /**
5
+ * Optional middleware hooks for tool execution.
6
+ * When provided, these callbacks are invoked before/after each tool execution.
7
+ */
8
+ export interface ToolExecutionMiddlewareHooks {
9
+ onBeforeToolCall?: (toolCall: ToolCall, tool: Tool | undefined, args: unknown) => Promise<BeforeToolCallDecision>;
10
+ onAfterToolCall?: (info: AfterToolCallInfo) => Promise<void>;
11
+ }
12
+ /**
13
+ * Error thrown when middleware decides to abort the chat run during tool execution.
14
+ */
15
+ export declare class MiddlewareAbortError extends Error {
16
+ constructor(reason: string);
17
+ }
18
+ type RequiredContextFromToolUnion<T> = T extends unknown ? undefined extends ContextFromTool<T> ? never : ContextFromTool<T> : never;
19
+ type ContextFromToolUnion<T> = [
20
+ UnionToIntersection<DefinedContext<ContextFromTool<T>>>
21
+ ] extends [never] ? unknown : [RequiredContextFromToolUnion<T>] extends [never] ? UnionToIntersection<DefinedContext<ContextFromTool<T>>> | undefined : UnionToIntersection<DefinedContext<ContextFromTool<T>>>;
22
+ type ContextFromTools<TTools> = TTools extends readonly [
23
+ infer THead,
24
+ ...infer TTail
25
+ ] ? MergeContext<ContextFromTool<THead>, ContextFromTools<TTail>> : TTools extends ReadonlyArray<infer TTool> ? ContextFromToolUnion<TTool> : unknown;
26
+ type ExecuteToolsContextArgs<TContext> = undefined extends TContext ? [userContext?: TContext] : [userContext: TContext];
27
+ /**
28
+ * Manages tool call accumulation and execution for the chat() method's automatic tool execution loop.
29
+ *
30
+ * Responsibilities:
31
+ * - Accumulates streaming tool call events (ID, name, arguments)
32
+ * - Validates tool calls (filters out incomplete ones)
33
+ * - Executes tool `execute` functions with parsed arguments
34
+ * - Emits `TOOL_CALL_END` events for client visibility
35
+ * - Returns tool result messages for conversation history
36
+ *
37
+ * This class is used internally by the AI.chat() method to handle the automatic
38
+ * tool execution loop. It can also be used independently for custom tool execution logic.
39
+ *
40
+ * @example
41
+ * ```typescript
42
+ * const manager = new ToolCallManager(tools);
43
+ *
44
+ * // During streaming, accumulate tool calls
45
+ * for await (const chunk of stream) {
46
+ * if (chunk.type === 'TOOL_CALL_START') {
47
+ * manager.addToolCallStartEvent(chunk);
48
+ * } else if (chunk.type === 'TOOL_CALL_ARGS') {
49
+ * manager.addToolCallArgsEvent(chunk);
50
+ * }
51
+ * }
52
+ *
53
+ * // After stream completes, execute tools
54
+ * if (manager.hasToolCalls()) {
55
+ * const toolResults = yield* manager.executeTools(finishEvent);
56
+ * messages = [...messages, ...toolResults];
57
+ * manager.clear();
58
+ * }
59
+ * ```
60
+ */
61
+ export declare class ToolCallManager<TToolsOrContext = ReadonlyArray<AnyTool>, TContext = TToolsOrContext extends ReadonlyArray<AnyTool> ? ContextFromTools<TToolsOrContext> : TToolsOrContext> {
62
+ private readonly toolCallsMap;
63
+ private readonly tools;
64
+ constructor(tools: TToolsOrContext extends ReadonlyArray<AnyTool> ? TToolsOrContext : ReadonlyArray<AnyTool>);
65
+ /**
66
+ * Add a TOOL_CALL_START event to begin tracking a tool call (AG-UI)
67
+ */
68
+ addToolCallStartEvent(event: ToolCallStartEvent): void;
69
+ /**
70
+ * Add a TOOL_CALL_ARGS event to accumulate arguments (AG-UI)
71
+ */
72
+ addToolCallArgsEvent(event: ToolCallArgsEvent): void;
73
+ /**
74
+ * Complete a tool call with its final input
75
+ * Called when TOOL_CALL_END is received
76
+ */
77
+ completeToolCall(event: ToolCallEndEvent): void;
78
+ /**
79
+ * Check if there are any complete tool calls to execute
80
+ */
81
+ hasToolCalls(): boolean;
82
+ /**
83
+ * Get all complete tool calls (filtered for valid ID and name)
84
+ */
85
+ getToolCalls(): Array<ToolCall>;
86
+ /**
87
+ * Execute all tool calls and return tool result messages
88
+ * Yields TOOL_CALL_END events for streaming
89
+ * @param finishEvent - RUN_FINISHED event from the stream
90
+ */
91
+ executeTools(finishEvent: RunFinishedEvent, ...contextArgs: ExecuteToolsContextArgs<TContext>): AsyncGenerator<ToolCallEndEvent, Array<ModelMessage>, void>;
92
+ /**
93
+ * Clear the tool calls map for the next iteration
94
+ */
95
+ clear(): void;
96
+ }
97
+ export interface ToolResult {
98
+ toolCallId: string;
99
+ toolName: string;
100
+ result: any;
101
+ state?: 'output-available' | 'output-error';
102
+ /** Duration of tool execution in milliseconds (only for server-executed tools) */
103
+ duration?: number;
104
+ }
105
+ export interface ApprovalRequest {
106
+ toolCallId: string;
107
+ toolName: string;
108
+ input: any;
109
+ approvalId: string;
110
+ }
111
+ export interface ClientToolRequest {
112
+ toolCallId: string;
113
+ toolName: string;
114
+ input: any;
115
+ }
116
+ interface ExecuteToolCallsResult {
117
+ /** Tool results ready to send to LLM */
118
+ results: Array<ToolResult>;
119
+ /** Tools that need user approval before execution */
120
+ needsApproval: Array<ApprovalRequest>;
121
+ /** Tools that need client-side execution */
122
+ needsClientExecution: Array<ClientToolRequest>;
123
+ }
124
+ /**
125
+ * Execute a server-side tool with event polling, output validation, and middleware hooks.
126
+ * Yields CustomEvent chunks during execution and pushes the result to the results array.
127
+ */
128
+ export declare function executeServerTool<TContext = unknown>(toolCall: ToolCall, tool: AnyTool, toolName: string, input: unknown, context: ToolExecutionContext<TContext>, pendingEvents: Array<CustomEvent>, results: Array<ToolResult>, middlewareHooks?: ToolExecutionMiddlewareHooks): AsyncGenerator<CustomEvent, void, void>;
129
+ /**
130
+ * Execute tool calls based on their configuration.
131
+ * Yields CustomEvent chunks during tool execution for real-time progress updates.
132
+ *
133
+ * Handles three cases:
134
+ * 1. Client tools (no execute) - request client to execute
135
+ * 2. Server tools with approval - check approval before executing
136
+ * 3. Normal server tools - execute immediately
137
+ *
138
+ * @param toolCalls - Tool calls from the LLM
139
+ * @param tools - Available tools with their configurations
140
+ * @param approvals - Map of approval decisions (approval.id -> approved boolean)
141
+ * @param clientResults - Map of client-side execution results (toolCallId -> result)
142
+ * @param createCustomEventChunk - Factory to create CustomEvent chunks (optional)
143
+ */
144
+ export declare function executeToolCalls<TContext = unknown>(toolCalls: Array<ToolCall>, tools: ReadonlyArray<AnyTool>, approvals?: Map<string, boolean>, clientResults?: Map<string, any>, createCustomEventChunk?: (eventName: string, value: Record<string, any>) => CustomEvent, middlewareHooks?: ToolExecutionMiddlewareHooks, userContext?: TContext, abortSignal?: AbortSignal): AsyncGenerator<CustomEvent, ExecuteToolCallsResult, void>;
145
+ export {};
@@ -0,0 +1,548 @@
1
+ import { normalizeToolResult } from "../../../utilities/tool-result.js";
2
+ import { isStandardSchema, parseWithStandardSchema } from "./schema-converter.js";
3
+ function safeJsonParse(value) {
4
+ try {
5
+ return JSON.parse(value);
6
+ } catch {
7
+ return value;
8
+ }
9
+ }
10
+ function readMcpAppMeta(tool) {
11
+ const meta = tool.metadata?.mcp;
12
+ return meta;
13
+ }
14
+ async function emitUiResourceIfLinked(tool, context) {
15
+ const mcp = readMcpAppMeta(tool);
16
+ const uiUri = mcp?.uiResourceUri;
17
+ if (!uiUri || !mcp.readResource) return;
18
+ let matched;
19
+ try {
20
+ const res = await mcp.readResource(uiUri);
21
+ matched = res.contents.find((c) => c.uri === uiUri);
22
+ } catch (err) {
23
+ console.warn(`[mcp-apps] failed to read ui resource ${uiUri}:`, err);
24
+ return;
25
+ }
26
+ if (!matched) {
27
+ console.warn(
28
+ `[mcp-apps] ui resource ${uiUri} returned no content matching that uri; not emitting`
29
+ );
30
+ return;
31
+ }
32
+ context.emitCustomEvent("ui-resource", {
33
+ resource: {
34
+ uri: matched.uri,
35
+ mimeType: matched.mimeType ?? "text/html",
36
+ text: matched.text,
37
+ blob: matched.blob
38
+ },
39
+ serverId: mcp.serverId,
40
+ toolName: mcp.serverToolName ?? tool.name,
41
+ meta: void 0
42
+ });
43
+ }
44
+ class MiddlewareAbortError extends Error {
45
+ constructor(reason) {
46
+ super(reason);
47
+ this.name = "MiddlewareAbortError";
48
+ }
49
+ }
50
+ class ToolCallManager {
51
+ toolCallsMap = /* @__PURE__ */ new Map();
52
+ tools;
53
+ constructor(tools) {
54
+ this.tools = tools;
55
+ }
56
+ /**
57
+ * Add a TOOL_CALL_START event to begin tracking a tool call (AG-UI)
58
+ */
59
+ addToolCallStartEvent(event) {
60
+ const index = event.index ?? this.toolCallsMap.size;
61
+ const runtimeEvent = event;
62
+ const name = runtimeEvent.toolCallName ?? runtimeEvent.toolName;
63
+ this.toolCallsMap.set(index, {
64
+ id: event.toolCallId,
65
+ type: "function",
66
+ function: {
67
+ name,
68
+ arguments: ""
69
+ },
70
+ ...event.metadata !== void 0 && { metadata: event.metadata }
71
+ });
72
+ }
73
+ /**
74
+ * Add a TOOL_CALL_ARGS event to accumulate arguments (AG-UI)
75
+ */
76
+ addToolCallArgsEvent(event) {
77
+ for (const [, toolCall] of this.toolCallsMap.entries()) {
78
+ if (toolCall.id === event.toolCallId) {
79
+ toolCall.function.arguments += event.delta;
80
+ break;
81
+ }
82
+ }
83
+ }
84
+ /**
85
+ * Complete a tool call with its final input
86
+ * Called when TOOL_CALL_END is received
87
+ */
88
+ completeToolCall(event) {
89
+ for (const [, toolCall] of this.toolCallsMap.entries()) {
90
+ if (toolCall.id === event.toolCallId) {
91
+ if (event.input !== void 0) {
92
+ const normalized = event.input && typeof event.input === "object" ? event.input : {};
93
+ toolCall.function.arguments = JSON.stringify(normalized);
94
+ }
95
+ break;
96
+ }
97
+ }
98
+ }
99
+ /**
100
+ * Check if there are any complete tool calls to execute
101
+ */
102
+ hasToolCalls() {
103
+ return this.getToolCalls().length > 0;
104
+ }
105
+ /**
106
+ * Get all complete tool calls (filtered for valid ID and name)
107
+ */
108
+ getToolCalls() {
109
+ return Array.from(this.toolCallsMap.values()).filter(
110
+ (tc) => tc.id && tc.function.name && tc.function.name.trim().length > 0
111
+ );
112
+ }
113
+ /**
114
+ * Execute all tool calls and return tool result messages
115
+ * Yields TOOL_CALL_END events for streaming
116
+ * @param finishEvent - RUN_FINISHED event from the stream
117
+ */
118
+ async *executeTools(finishEvent, ...contextArgs) {
119
+ const toolCallsArray = this.getToolCalls();
120
+ const toolResults = [];
121
+ const hasRuntimeContext = contextArgs.length > 0;
122
+ const userContext = contextArgs[0];
123
+ for (const toolCall of toolCallsArray) {
124
+ const tool = this.tools.find((t) => t.name === toolCall.function.name);
125
+ let toolResultContent;
126
+ let toolResultState;
127
+ if (tool?.execute) {
128
+ try {
129
+ let args;
130
+ try {
131
+ const argsString = toolCall.function.arguments.trim() || "{}";
132
+ const parsed = JSON.parse(argsString);
133
+ args = parsed && typeof parsed === "object" ? parsed : {};
134
+ } catch (parseError) {
135
+ throw new Error(
136
+ `Failed to parse tool arguments as JSON: ${toolCall.function.arguments}`
137
+ );
138
+ }
139
+ if (tool.inputSchema && isStandardSchema(tool.inputSchema)) {
140
+ try {
141
+ args = parseWithStandardSchema(tool.inputSchema, args);
142
+ } catch (validationError) {
143
+ const message = validationError instanceof Error ? validationError.message : "Validation failed";
144
+ throw new Error(
145
+ `Input validation failed for tool ${tool.name}: ${message}`
146
+ );
147
+ }
148
+ }
149
+ const executionContext = {
150
+ toolCallId: toolCall.id,
151
+ context: userContext,
152
+ emitCustomEvent: () => {
153
+ }
154
+ };
155
+ let result = hasRuntimeContext ? await tool.execute(args, executionContext) : await tool.execute(args);
156
+ if (tool.outputSchema && isStandardSchema(tool.outputSchema)) {
157
+ try {
158
+ result = parseWithStandardSchema(tool.outputSchema, result);
159
+ } catch (validationError) {
160
+ const message = validationError instanceof Error ? validationError.message : "Validation failed";
161
+ throw new Error(
162
+ `Output validation failed for tool ${tool.name}: ${message}`
163
+ );
164
+ }
165
+ }
166
+ toolResultContent = normalizeToolResult(result);
167
+ } catch (error) {
168
+ const message = error instanceof Error ? error.message : "Unknown error";
169
+ toolResultContent = `Error executing tool: ${message}`;
170
+ toolResultState = "output-error";
171
+ }
172
+ } else {
173
+ toolResultContent = `Tool ${toolCall.function.name} does not have an execute function`;
174
+ }
175
+ yield {
176
+ type: "TOOL_CALL_END",
177
+ toolCallId: toolCall.id,
178
+ toolCallName: toolCall.function.name,
179
+ toolName: toolCall.function.name,
180
+ model: finishEvent.model,
181
+ timestamp: Date.now(),
182
+ result: toolResultContent,
183
+ ...toolResultState !== void 0 && { state: toolResultState }
184
+ };
185
+ toolResults.push({
186
+ role: "tool",
187
+ content: toolResultContent,
188
+ toolCallId: toolCall.id
189
+ });
190
+ }
191
+ return toolResults;
192
+ }
193
+ /**
194
+ * Clear the tool calls map for the next iteration
195
+ */
196
+ clear() {
197
+ this.toolCallsMap.clear();
198
+ }
199
+ }
200
+ async function* executeWithEventPolling(executionPromise, pendingEvents) {
201
+ const state = { done: false, result: void 0 };
202
+ const executionWithFlag = executionPromise.then((r) => {
203
+ state.done = true;
204
+ state.result = r;
205
+ return r;
206
+ });
207
+ while (!state.done) {
208
+ await Promise.race([
209
+ executionWithFlag,
210
+ new Promise((resolve) => setTimeout(resolve, 10))
211
+ ]);
212
+ let event2;
213
+ while ((event2 = pendingEvents.shift()) !== void 0) {
214
+ yield event2;
215
+ }
216
+ }
217
+ let event;
218
+ while ((event = pendingEvents.shift()) !== void 0) {
219
+ yield event;
220
+ }
221
+ return state.result;
222
+ }
223
+ async function applyBeforeToolCallDecision(toolCall, tool, input, toolName, middlewareHooks, results) {
224
+ if (!middlewareHooks.onBeforeToolCall) {
225
+ return { proceed: true, input };
226
+ }
227
+ const decision = await middlewareHooks.onBeforeToolCall(toolCall, tool, input);
228
+ if (!decision) {
229
+ return { proceed: true, input };
230
+ }
231
+ if (decision.type === "abort") {
232
+ throw new MiddlewareAbortError(decision.reason || "Aborted by middleware");
233
+ }
234
+ if (decision.type === "skip") {
235
+ const skipResult = decision.result;
236
+ results.push({
237
+ toolCallId: toolCall.id,
238
+ toolName,
239
+ result: typeof skipResult === "string" ? safeJsonParse(skipResult) : skipResult ?? null,
240
+ duration: 0
241
+ });
242
+ if (middlewareHooks.onAfterToolCall) {
243
+ await middlewareHooks.onAfterToolCall({
244
+ toolCall,
245
+ tool,
246
+ toolName,
247
+ toolCallId: toolCall.id,
248
+ ok: true,
249
+ duration: 0,
250
+ result: skipResult
251
+ });
252
+ }
253
+ return { proceed: false };
254
+ }
255
+ return { proceed: true, input: decision.args };
256
+ }
257
+ async function* executeServerTool(toolCall, tool, toolName, input, context, pendingEvents, results, middlewareHooks) {
258
+ const startTime = Date.now();
259
+ try {
260
+ if (!tool.execute) {
261
+ throw new Error(`Tool ${toolName} has no execute() implementation`);
262
+ }
263
+ const executionPromise = Promise.resolve(tool.execute(input, context));
264
+ let result = yield* executeWithEventPolling(executionPromise, pendingEvents);
265
+ const duration = Date.now() - startTime;
266
+ await emitUiResourceIfLinked(tool, context);
267
+ let pendingEvent;
268
+ while ((pendingEvent = pendingEvents.shift()) !== void 0) {
269
+ yield pendingEvent;
270
+ }
271
+ if (tool.outputSchema && isStandardSchema(tool.outputSchema)) {
272
+ result = parseWithStandardSchema(tool.outputSchema, result);
273
+ }
274
+ const finalResult = typeof result === "string" ? safeJsonParse(result) : result ?? null;
275
+ results.push({
276
+ toolCallId: toolCall.id,
277
+ toolName,
278
+ result: finalResult,
279
+ duration
280
+ });
281
+ if (middlewareHooks?.onAfterToolCall) {
282
+ await middlewareHooks.onAfterToolCall({
283
+ toolCall,
284
+ tool,
285
+ toolName,
286
+ toolCallId: toolCall.id,
287
+ ok: true,
288
+ duration,
289
+ result: finalResult
290
+ });
291
+ }
292
+ } catch (error) {
293
+ const duration = Date.now() - startTime;
294
+ let pendingEvent;
295
+ while ((pendingEvent = pendingEvents.shift()) !== void 0) {
296
+ yield pendingEvent;
297
+ }
298
+ if (error instanceof MiddlewareAbortError) {
299
+ throw error;
300
+ }
301
+ const message = error instanceof Error ? error.message : "Unknown error";
302
+ results.push({
303
+ toolCallId: toolCall.id,
304
+ toolName,
305
+ result: { error: message },
306
+ state: "output-error",
307
+ duration
308
+ });
309
+ if (middlewareHooks?.onAfterToolCall) {
310
+ await middlewareHooks.onAfterToolCall({
311
+ toolCall,
312
+ tool,
313
+ toolName,
314
+ toolCallId: toolCall.id,
315
+ ok: false,
316
+ duration,
317
+ error
318
+ });
319
+ }
320
+ }
321
+ }
322
+ function buildClientToolResult(toolCallId, toolName, tool, rawResult) {
323
+ try {
324
+ let result = rawResult;
325
+ if (tool.outputSchema && isStandardSchema(tool.outputSchema)) {
326
+ result = parseWithStandardSchema(tool.outputSchema, result);
327
+ }
328
+ return {
329
+ toolCallId,
330
+ toolName,
331
+ result: typeof result === "string" ? safeJsonParse(result) : result ?? null
332
+ };
333
+ } catch (error) {
334
+ const message = error instanceof Error ? error.message : "Validation failed";
335
+ return {
336
+ toolCallId,
337
+ toolName,
338
+ result: { error: message },
339
+ state: "output-error"
340
+ };
341
+ }
342
+ }
343
+ async function* executeToolCalls(toolCalls, tools, approvals = /* @__PURE__ */ new Map(), clientResults = /* @__PURE__ */ new Map(), createCustomEventChunk, middlewareHooks, userContext, abortSignal) {
344
+ const results = [];
345
+ const needsApproval = [];
346
+ const needsClientExecution = [];
347
+ const toolMap = /* @__PURE__ */ new Map();
348
+ for (const tool of tools) {
349
+ toolMap.set(tool.name, tool);
350
+ }
351
+ const hasPendingApprovals = toolCalls.some((tc) => {
352
+ const t = toolMap.get(tc.function.name);
353
+ return t?.needsApproval && !approvals.has(`approval_${tc.id}`);
354
+ });
355
+ for (const toolCall of toolCalls) {
356
+ const tool = toolMap.get(toolCall.function.name);
357
+ const toolName = toolCall.function.name;
358
+ if (!tool) {
359
+ results.push({
360
+ toolCallId: toolCall.id,
361
+ toolName,
362
+ result: { error: `Unknown tool: ${toolName}` },
363
+ state: "output-error"
364
+ });
365
+ continue;
366
+ }
367
+ if (hasPendingApprovals) {
368
+ if (!tool.needsApproval || approvals.has(`approval_${toolCall.id}`)) {
369
+ continue;
370
+ }
371
+ }
372
+ let input = {};
373
+ const argsStr = toolCall.function.arguments.trim() || "{}";
374
+ {
375
+ try {
376
+ const parsed = JSON.parse(argsStr);
377
+ input = parsed && typeof parsed === "object" ? parsed : {};
378
+ } catch (parseError) {
379
+ throw new Error(`Failed to parse tool arguments as JSON: ${argsStr}`);
380
+ }
381
+ }
382
+ if (tool.inputSchema && isStandardSchema(tool.inputSchema)) {
383
+ try {
384
+ input = parseWithStandardSchema(tool.inputSchema, input);
385
+ } catch (validationError) {
386
+ const message = validationError instanceof Error ? validationError.message : "Validation failed";
387
+ results.push({
388
+ toolCallId: toolCall.id,
389
+ toolName,
390
+ result: {
391
+ error: `Input validation failed for tool ${tool.name}: ${message}`
392
+ },
393
+ state: "output-error"
394
+ });
395
+ continue;
396
+ }
397
+ }
398
+ const pendingEvents = [];
399
+ const context = {
400
+ toolCallId: toolCall.id,
401
+ context: userContext,
402
+ abortSignal,
403
+ emitCustomEvent: (eventName, value) => {
404
+ if (createCustomEventChunk) {
405
+ pendingEvents.push(
406
+ createCustomEventChunk(eventName, {
407
+ ...value,
408
+ toolCallId: toolCall.id
409
+ })
410
+ );
411
+ }
412
+ }
413
+ };
414
+ if (!tool.execute) {
415
+ if (tool.needsApproval) {
416
+ const approvalId = `approval_${toolCall.id}`;
417
+ if (approvals.has(approvalId)) {
418
+ const approved = approvals.get(approvalId);
419
+ if (approved) {
420
+ if (clientResults.has(toolCall.id)) {
421
+ results.push(
422
+ buildClientToolResult(
423
+ toolCall.id,
424
+ toolName,
425
+ tool,
426
+ clientResults.get(toolCall.id)
427
+ )
428
+ );
429
+ } else {
430
+ needsClientExecution.push({
431
+ toolCallId: toolCall.id,
432
+ toolName,
433
+ input
434
+ });
435
+ }
436
+ } else {
437
+ results.push({
438
+ toolCallId: toolCall.id,
439
+ toolName,
440
+ result: { error: "User declined tool execution" },
441
+ state: "output-error"
442
+ });
443
+ }
444
+ } else {
445
+ needsApproval.push({
446
+ toolCallId: toolCall.id,
447
+ toolName: toolCall.function.name,
448
+ input,
449
+ approvalId
450
+ });
451
+ }
452
+ } else {
453
+ if (clientResults.has(toolCall.id)) {
454
+ results.push(
455
+ buildClientToolResult(
456
+ toolCall.id,
457
+ toolName,
458
+ tool,
459
+ clientResults.get(toolCall.id)
460
+ )
461
+ );
462
+ } else {
463
+ needsClientExecution.push({
464
+ toolCallId: toolCall.id,
465
+ toolName,
466
+ input
467
+ });
468
+ }
469
+ }
470
+ continue;
471
+ }
472
+ if (tool.needsApproval) {
473
+ const approvalId = `approval_${toolCall.id}`;
474
+ if (approvals.has(approvalId)) {
475
+ const approved = approvals.get(approvalId);
476
+ if (approved) {
477
+ if (middlewareHooks) {
478
+ const decision = await applyBeforeToolCallDecision(
479
+ toolCall,
480
+ tool,
481
+ input,
482
+ toolName,
483
+ middlewareHooks,
484
+ results
485
+ );
486
+ if (!decision.proceed) continue;
487
+ input = decision.input;
488
+ }
489
+ yield* executeServerTool(
490
+ toolCall,
491
+ tool,
492
+ toolName,
493
+ input,
494
+ context,
495
+ pendingEvents,
496
+ results,
497
+ middlewareHooks
498
+ );
499
+ } else {
500
+ results.push({
501
+ toolCallId: toolCall.id,
502
+ toolName,
503
+ result: { error: "User declined tool execution" },
504
+ state: "output-error"
505
+ });
506
+ }
507
+ } else {
508
+ needsApproval.push({
509
+ toolCallId: toolCall.id,
510
+ toolName,
511
+ input,
512
+ approvalId
513
+ });
514
+ }
515
+ continue;
516
+ }
517
+ if (middlewareHooks) {
518
+ const decision = await applyBeforeToolCallDecision(
519
+ toolCall,
520
+ tool,
521
+ input,
522
+ toolName,
523
+ middlewareHooks,
524
+ results
525
+ );
526
+ if (!decision.proceed) continue;
527
+ input = decision.input;
528
+ }
529
+ yield* executeServerTool(
530
+ toolCall,
531
+ tool,
532
+ toolName,
533
+ input,
534
+ context,
535
+ pendingEvents,
536
+ results,
537
+ middlewareHooks
538
+ );
539
+ }
540
+ return { results, needsApproval, needsClientExecution };
541
+ }
542
+ export {
543
+ MiddlewareAbortError,
544
+ ToolCallManager,
545
+ executeServerTool,
546
+ executeToolCalls
547
+ };
548
+ //# sourceMappingURL=tool-calls.js.map