@tanstack/ai 0.36.0 → 0.37.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 (205) 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 +71 -0
  12. package/dist/esm/activities/chat/mcp/manager.js.map +1 -0
  13. package/dist/esm/activities/chat/mcp/types.d.ts +56 -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 +1426 -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 +140 -0
  62. package/dist/esm/activities/chat/tools/tool-calls.js +512 -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 +1594 -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
@@ -0,0 +1,140 @@
1
+ import { AnyTool, CustomEvent, ModelMessage, RunFinishedEvent, Tool, ToolCall, ToolCallArgsEvent, ToolCallEndEvent, ToolCallStartEvent } 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 tool calls based on their configuration.
126
+ * Yields CustomEvent chunks during tool execution for real-time progress updates.
127
+ *
128
+ * Handles three cases:
129
+ * 1. Client tools (no execute) - request client to execute
130
+ * 2. Server tools with approval - check approval before executing
131
+ * 3. Normal server tools - execute immediately
132
+ *
133
+ * @param toolCalls - Tool calls from the LLM
134
+ * @param tools - Available tools with their configurations
135
+ * @param approvals - Map of approval decisions (approval.id -> approved boolean)
136
+ * @param clientResults - Map of client-side execution results (toolCallId -> result)
137
+ * @param createCustomEventChunk - Factory to create CustomEvent chunks (optional)
138
+ */
139
+ 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>;
140
+ export {};
@@ -0,0 +1,512 @@
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
+ class MiddlewareAbortError extends Error {
11
+ constructor(reason) {
12
+ super(reason);
13
+ this.name = "MiddlewareAbortError";
14
+ }
15
+ }
16
+ class ToolCallManager {
17
+ toolCallsMap = /* @__PURE__ */ new Map();
18
+ tools;
19
+ constructor(tools) {
20
+ this.tools = tools;
21
+ }
22
+ /**
23
+ * Add a TOOL_CALL_START event to begin tracking a tool call (AG-UI)
24
+ */
25
+ addToolCallStartEvent(event) {
26
+ const index = event.index ?? this.toolCallsMap.size;
27
+ const runtimeEvent = event;
28
+ const name = runtimeEvent.toolCallName ?? runtimeEvent.toolName;
29
+ this.toolCallsMap.set(index, {
30
+ id: event.toolCallId,
31
+ type: "function",
32
+ function: {
33
+ name,
34
+ arguments: ""
35
+ },
36
+ ...event.metadata !== void 0 && { metadata: event.metadata }
37
+ });
38
+ }
39
+ /**
40
+ * Add a TOOL_CALL_ARGS event to accumulate arguments (AG-UI)
41
+ */
42
+ addToolCallArgsEvent(event) {
43
+ for (const [, toolCall] of this.toolCallsMap.entries()) {
44
+ if (toolCall.id === event.toolCallId) {
45
+ toolCall.function.arguments += event.delta;
46
+ break;
47
+ }
48
+ }
49
+ }
50
+ /**
51
+ * Complete a tool call with its final input
52
+ * Called when TOOL_CALL_END is received
53
+ */
54
+ completeToolCall(event) {
55
+ for (const [, toolCall] of this.toolCallsMap.entries()) {
56
+ if (toolCall.id === event.toolCallId) {
57
+ if (event.input !== void 0) {
58
+ const normalized = event.input && typeof event.input === "object" ? event.input : {};
59
+ toolCall.function.arguments = JSON.stringify(normalized);
60
+ }
61
+ break;
62
+ }
63
+ }
64
+ }
65
+ /**
66
+ * Check if there are any complete tool calls to execute
67
+ */
68
+ hasToolCalls() {
69
+ return this.getToolCalls().length > 0;
70
+ }
71
+ /**
72
+ * Get all complete tool calls (filtered for valid ID and name)
73
+ */
74
+ getToolCalls() {
75
+ return Array.from(this.toolCallsMap.values()).filter(
76
+ (tc) => tc.id && tc.function.name && tc.function.name.trim().length > 0
77
+ );
78
+ }
79
+ /**
80
+ * Execute all tool calls and return tool result messages
81
+ * Yields TOOL_CALL_END events for streaming
82
+ * @param finishEvent - RUN_FINISHED event from the stream
83
+ */
84
+ async *executeTools(finishEvent, ...contextArgs) {
85
+ const toolCallsArray = this.getToolCalls();
86
+ const toolResults = [];
87
+ const hasRuntimeContext = contextArgs.length > 0;
88
+ const userContext = contextArgs[0];
89
+ for (const toolCall of toolCallsArray) {
90
+ const tool = this.tools.find((t) => t.name === toolCall.function.name);
91
+ let toolResultContent;
92
+ let toolResultState;
93
+ if (tool?.execute) {
94
+ try {
95
+ let args;
96
+ try {
97
+ const argsString = toolCall.function.arguments.trim() || "{}";
98
+ const parsed = JSON.parse(argsString);
99
+ args = parsed && typeof parsed === "object" ? parsed : {};
100
+ } catch (parseError) {
101
+ throw new Error(
102
+ `Failed to parse tool arguments as JSON: ${toolCall.function.arguments}`
103
+ );
104
+ }
105
+ if (tool.inputSchema && isStandardSchema(tool.inputSchema)) {
106
+ try {
107
+ args = parseWithStandardSchema(tool.inputSchema, args);
108
+ } catch (validationError) {
109
+ const message = validationError instanceof Error ? validationError.message : "Validation failed";
110
+ throw new Error(
111
+ `Input validation failed for tool ${tool.name}: ${message}`
112
+ );
113
+ }
114
+ }
115
+ const executionContext = {
116
+ toolCallId: toolCall.id,
117
+ context: userContext,
118
+ emitCustomEvent: () => {
119
+ }
120
+ };
121
+ let result = hasRuntimeContext ? await tool.execute(args, executionContext) : await tool.execute(args);
122
+ if (tool.outputSchema && isStandardSchema(tool.outputSchema)) {
123
+ try {
124
+ result = parseWithStandardSchema(tool.outputSchema, result);
125
+ } catch (validationError) {
126
+ const message = validationError instanceof Error ? validationError.message : "Validation failed";
127
+ throw new Error(
128
+ `Output validation failed for tool ${tool.name}: ${message}`
129
+ );
130
+ }
131
+ }
132
+ toolResultContent = normalizeToolResult(result);
133
+ } catch (error) {
134
+ const message = error instanceof Error ? error.message : "Unknown error";
135
+ toolResultContent = `Error executing tool: ${message}`;
136
+ toolResultState = "output-error";
137
+ }
138
+ } else {
139
+ toolResultContent = `Tool ${toolCall.function.name} does not have an execute function`;
140
+ }
141
+ yield {
142
+ type: "TOOL_CALL_END",
143
+ toolCallId: toolCall.id,
144
+ toolCallName: toolCall.function.name,
145
+ toolName: toolCall.function.name,
146
+ model: finishEvent.model,
147
+ timestamp: Date.now(),
148
+ result: toolResultContent,
149
+ ...toolResultState !== void 0 && { state: toolResultState }
150
+ };
151
+ toolResults.push({
152
+ role: "tool",
153
+ content: toolResultContent,
154
+ toolCallId: toolCall.id
155
+ });
156
+ }
157
+ return toolResults;
158
+ }
159
+ /**
160
+ * Clear the tool calls map for the next iteration
161
+ */
162
+ clear() {
163
+ this.toolCallsMap.clear();
164
+ }
165
+ }
166
+ async function* executeWithEventPolling(executionPromise, pendingEvents) {
167
+ const state = { done: false, result: void 0 };
168
+ const executionWithFlag = executionPromise.then((r) => {
169
+ state.done = true;
170
+ state.result = r;
171
+ return r;
172
+ });
173
+ while (!state.done) {
174
+ await Promise.race([
175
+ executionWithFlag,
176
+ new Promise((resolve) => setTimeout(resolve, 10))
177
+ ]);
178
+ let event2;
179
+ while ((event2 = pendingEvents.shift()) !== void 0) {
180
+ yield event2;
181
+ }
182
+ }
183
+ let event;
184
+ while ((event = pendingEvents.shift()) !== void 0) {
185
+ yield event;
186
+ }
187
+ return state.result;
188
+ }
189
+ async function applyBeforeToolCallDecision(toolCall, tool, input, toolName, middlewareHooks, results) {
190
+ if (!middlewareHooks.onBeforeToolCall) {
191
+ return { proceed: true, input };
192
+ }
193
+ const decision = await middlewareHooks.onBeforeToolCall(toolCall, tool, input);
194
+ if (!decision) {
195
+ return { proceed: true, input };
196
+ }
197
+ if (decision.type === "abort") {
198
+ throw new MiddlewareAbortError(decision.reason || "Aborted by middleware");
199
+ }
200
+ if (decision.type === "skip") {
201
+ const skipResult = decision.result;
202
+ results.push({
203
+ toolCallId: toolCall.id,
204
+ toolName,
205
+ result: typeof skipResult === "string" ? safeJsonParse(skipResult) : skipResult ?? null,
206
+ duration: 0
207
+ });
208
+ if (middlewareHooks.onAfterToolCall) {
209
+ await middlewareHooks.onAfterToolCall({
210
+ toolCall,
211
+ tool,
212
+ toolName,
213
+ toolCallId: toolCall.id,
214
+ ok: true,
215
+ duration: 0,
216
+ result: skipResult
217
+ });
218
+ }
219
+ return { proceed: false };
220
+ }
221
+ return { proceed: true, input: decision.args };
222
+ }
223
+ async function* executeServerTool(toolCall, tool, toolName, input, context, pendingEvents, results, middlewareHooks) {
224
+ const startTime = Date.now();
225
+ try {
226
+ if (!tool.execute) {
227
+ throw new Error(`Tool ${toolName} has no execute() implementation`);
228
+ }
229
+ const executionPromise = Promise.resolve(tool.execute(input, context));
230
+ let result = yield* executeWithEventPolling(executionPromise, pendingEvents);
231
+ const duration = Date.now() - startTime;
232
+ let pendingEvent;
233
+ while ((pendingEvent = pendingEvents.shift()) !== void 0) {
234
+ yield pendingEvent;
235
+ }
236
+ if (tool.outputSchema && isStandardSchema(tool.outputSchema)) {
237
+ result = parseWithStandardSchema(tool.outputSchema, result);
238
+ }
239
+ const finalResult = typeof result === "string" ? safeJsonParse(result) : result ?? null;
240
+ results.push({
241
+ toolCallId: toolCall.id,
242
+ toolName,
243
+ result: finalResult,
244
+ duration
245
+ });
246
+ if (middlewareHooks?.onAfterToolCall) {
247
+ await middlewareHooks.onAfterToolCall({
248
+ toolCall,
249
+ tool,
250
+ toolName,
251
+ toolCallId: toolCall.id,
252
+ ok: true,
253
+ duration,
254
+ result: finalResult
255
+ });
256
+ }
257
+ } catch (error) {
258
+ const duration = Date.now() - startTime;
259
+ let pendingEvent;
260
+ while ((pendingEvent = pendingEvents.shift()) !== void 0) {
261
+ yield pendingEvent;
262
+ }
263
+ if (error instanceof MiddlewareAbortError) {
264
+ throw error;
265
+ }
266
+ const message = error instanceof Error ? error.message : "Unknown error";
267
+ results.push({
268
+ toolCallId: toolCall.id,
269
+ toolName,
270
+ result: { error: message },
271
+ state: "output-error",
272
+ duration
273
+ });
274
+ if (middlewareHooks?.onAfterToolCall) {
275
+ await middlewareHooks.onAfterToolCall({
276
+ toolCall,
277
+ tool,
278
+ toolName,
279
+ toolCallId: toolCall.id,
280
+ ok: false,
281
+ duration,
282
+ error
283
+ });
284
+ }
285
+ }
286
+ }
287
+ function buildClientToolResult(toolCallId, toolName, tool, rawResult) {
288
+ try {
289
+ let result = rawResult;
290
+ if (tool.outputSchema && isStandardSchema(tool.outputSchema)) {
291
+ result = parseWithStandardSchema(tool.outputSchema, result);
292
+ }
293
+ return {
294
+ toolCallId,
295
+ toolName,
296
+ result: typeof result === "string" ? safeJsonParse(result) : result ?? null
297
+ };
298
+ } catch (error) {
299
+ const message = error instanceof Error ? error.message : "Validation failed";
300
+ return {
301
+ toolCallId,
302
+ toolName,
303
+ result: { error: message },
304
+ state: "output-error"
305
+ };
306
+ }
307
+ }
308
+ async function* executeToolCalls(toolCalls, tools, approvals = /* @__PURE__ */ new Map(), clientResults = /* @__PURE__ */ new Map(), createCustomEventChunk, middlewareHooks, userContext, abortSignal) {
309
+ const results = [];
310
+ const needsApproval = [];
311
+ const needsClientExecution = [];
312
+ const toolMap = /* @__PURE__ */ new Map();
313
+ for (const tool of tools) {
314
+ toolMap.set(tool.name, tool);
315
+ }
316
+ const hasPendingApprovals = toolCalls.some((tc) => {
317
+ const t = toolMap.get(tc.function.name);
318
+ return t?.needsApproval && !approvals.has(`approval_${tc.id}`);
319
+ });
320
+ for (const toolCall of toolCalls) {
321
+ const tool = toolMap.get(toolCall.function.name);
322
+ const toolName = toolCall.function.name;
323
+ if (!tool) {
324
+ results.push({
325
+ toolCallId: toolCall.id,
326
+ toolName,
327
+ result: { error: `Unknown tool: ${toolName}` },
328
+ state: "output-error"
329
+ });
330
+ continue;
331
+ }
332
+ if (hasPendingApprovals) {
333
+ if (!tool.needsApproval || approvals.has(`approval_${toolCall.id}`)) {
334
+ continue;
335
+ }
336
+ }
337
+ let input = {};
338
+ const argsStr = toolCall.function.arguments.trim() || "{}";
339
+ {
340
+ try {
341
+ const parsed = JSON.parse(argsStr);
342
+ input = parsed && typeof parsed === "object" ? parsed : {};
343
+ } catch (parseError) {
344
+ throw new Error(`Failed to parse tool arguments as JSON: ${argsStr}`);
345
+ }
346
+ }
347
+ if (tool.inputSchema && isStandardSchema(tool.inputSchema)) {
348
+ try {
349
+ input = parseWithStandardSchema(tool.inputSchema, input);
350
+ } catch (validationError) {
351
+ const message = validationError instanceof Error ? validationError.message : "Validation failed";
352
+ results.push({
353
+ toolCallId: toolCall.id,
354
+ toolName,
355
+ result: {
356
+ error: `Input validation failed for tool ${tool.name}: ${message}`
357
+ },
358
+ state: "output-error"
359
+ });
360
+ continue;
361
+ }
362
+ }
363
+ const pendingEvents = [];
364
+ const context = {
365
+ toolCallId: toolCall.id,
366
+ context: userContext,
367
+ abortSignal,
368
+ emitCustomEvent: (eventName, value) => {
369
+ if (createCustomEventChunk) {
370
+ pendingEvents.push(
371
+ createCustomEventChunk(eventName, {
372
+ ...value,
373
+ toolCallId: toolCall.id
374
+ })
375
+ );
376
+ }
377
+ }
378
+ };
379
+ if (!tool.execute) {
380
+ if (tool.needsApproval) {
381
+ const approvalId = `approval_${toolCall.id}`;
382
+ if (approvals.has(approvalId)) {
383
+ const approved = approvals.get(approvalId);
384
+ if (approved) {
385
+ if (clientResults.has(toolCall.id)) {
386
+ results.push(
387
+ buildClientToolResult(
388
+ toolCall.id,
389
+ toolName,
390
+ tool,
391
+ clientResults.get(toolCall.id)
392
+ )
393
+ );
394
+ } else {
395
+ needsClientExecution.push({
396
+ toolCallId: toolCall.id,
397
+ toolName,
398
+ input
399
+ });
400
+ }
401
+ } else {
402
+ results.push({
403
+ toolCallId: toolCall.id,
404
+ toolName,
405
+ result: { error: "User declined tool execution" },
406
+ state: "output-error"
407
+ });
408
+ }
409
+ } else {
410
+ needsApproval.push({
411
+ toolCallId: toolCall.id,
412
+ toolName: toolCall.function.name,
413
+ input,
414
+ approvalId
415
+ });
416
+ }
417
+ } else {
418
+ if (clientResults.has(toolCall.id)) {
419
+ results.push(
420
+ buildClientToolResult(
421
+ toolCall.id,
422
+ toolName,
423
+ tool,
424
+ clientResults.get(toolCall.id)
425
+ )
426
+ );
427
+ } else {
428
+ needsClientExecution.push({
429
+ toolCallId: toolCall.id,
430
+ toolName,
431
+ input
432
+ });
433
+ }
434
+ }
435
+ continue;
436
+ }
437
+ if (tool.needsApproval) {
438
+ const approvalId = `approval_${toolCall.id}`;
439
+ if (approvals.has(approvalId)) {
440
+ const approved = approvals.get(approvalId);
441
+ if (approved) {
442
+ if (middlewareHooks) {
443
+ const decision = await applyBeforeToolCallDecision(
444
+ toolCall,
445
+ tool,
446
+ input,
447
+ toolName,
448
+ middlewareHooks,
449
+ results
450
+ );
451
+ if (!decision.proceed) continue;
452
+ input = decision.input;
453
+ }
454
+ yield* executeServerTool(
455
+ toolCall,
456
+ tool,
457
+ toolName,
458
+ input,
459
+ context,
460
+ pendingEvents,
461
+ results,
462
+ middlewareHooks
463
+ );
464
+ } else {
465
+ results.push({
466
+ toolCallId: toolCall.id,
467
+ toolName,
468
+ result: { error: "User declined tool execution" },
469
+ state: "output-error"
470
+ });
471
+ }
472
+ } else {
473
+ needsApproval.push({
474
+ toolCallId: toolCall.id,
475
+ toolName,
476
+ input,
477
+ approvalId
478
+ });
479
+ }
480
+ continue;
481
+ }
482
+ if (middlewareHooks) {
483
+ const decision = await applyBeforeToolCallDecision(
484
+ toolCall,
485
+ tool,
486
+ input,
487
+ toolName,
488
+ middlewareHooks,
489
+ results
490
+ );
491
+ if (!decision.proceed) continue;
492
+ input = decision.input;
493
+ }
494
+ yield* executeServerTool(
495
+ toolCall,
496
+ tool,
497
+ toolName,
498
+ input,
499
+ context,
500
+ pendingEvents,
501
+ results,
502
+ middlewareHooks
503
+ );
504
+ }
505
+ return { results, needsApproval, needsClientExecution };
506
+ }
507
+ export {
508
+ MiddlewareAbortError,
509
+ ToolCallManager,
510
+ executeToolCalls
511
+ };
512
+ //# sourceMappingURL=tool-calls.js.map