@tanstack/ai 0.1.0 → 0.2.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.
@@ -1,7 +1,4 @@
1
- function isZodSchema(schema) {
2
- if (!schema) return false;
3
- return "_zod" in schema && typeof schema._zod === "object";
4
- }
1
+ import { isStandardSchema, parseWithStandardSchema } from "./schema-converter.js";
5
2
  class ToolCallManager {
6
3
  constructor(tools) {
7
4
  this.toolCallsMap = /* @__PURE__ */ new Map();
@@ -68,28 +65,31 @@ class ToolCallManager {
68
65
  `Failed to parse tool arguments as JSON: ${toolCall.function.arguments}`
69
66
  );
70
67
  }
71
- if (tool.inputSchema && isZodSchema(tool.inputSchema)) {
68
+ if (tool.inputSchema && isStandardSchema(tool.inputSchema)) {
72
69
  try {
73
- args = tool.inputSchema.parse(args);
70
+ args = parseWithStandardSchema(tool.inputSchema, args);
74
71
  } catch (validationError) {
72
+ const message = validationError instanceof Error ? validationError.message : "Validation failed";
75
73
  throw new Error(
76
- `Input validation failed for tool ${tool.name}: ${validationError.message}`
74
+ `Input validation failed for tool ${tool.name}: ${message}`
77
75
  );
78
76
  }
79
77
  }
80
78
  let result = await tool.execute(args);
81
- if (tool.outputSchema && isZodSchema(tool.outputSchema) && result !== void 0 && result !== null) {
79
+ if (tool.outputSchema && isStandardSchema(tool.outputSchema) && result !== void 0 && result !== null) {
82
80
  try {
83
- result = tool.outputSchema.parse(result);
81
+ result = parseWithStandardSchema(tool.outputSchema, result);
84
82
  } catch (validationError) {
83
+ const message = validationError instanceof Error ? validationError.message : "Validation failed";
85
84
  throw new Error(
86
- `Output validation failed for tool ${tool.name}: ${validationError.message}`
85
+ `Output validation failed for tool ${tool.name}: ${message}`
87
86
  );
88
87
  }
89
88
  }
90
89
  toolResultContent = typeof result === "string" ? result : JSON.stringify(result);
91
90
  } catch (error) {
92
- toolResultContent = `Error executing tool: ${error.message}`;
91
+ const message = error instanceof Error ? error.message : "Unknown error";
92
+ toolResultContent = `Error executing tool: ${message}`;
93
93
  }
94
94
  } else {
95
95
  toolResultContent = `Tool ${toolCall.function.name} does not have an execute function`;
@@ -146,15 +146,16 @@ async function executeToolCalls(toolCalls, tools, approvals = /* @__PURE__ */ ne
146
146
  throw new Error(`Failed to parse tool arguments as JSON: ${argsStr}`);
147
147
  }
148
148
  }
149
- if (tool.inputSchema && isZodSchema(tool.inputSchema)) {
149
+ if (tool.inputSchema && isStandardSchema(tool.inputSchema)) {
150
150
  try {
151
- input = tool.inputSchema.parse(input);
151
+ input = parseWithStandardSchema(tool.inputSchema, input);
152
152
  } catch (validationError) {
153
+ const message = validationError instanceof Error ? validationError.message : "Validation failed";
153
154
  results.push({
154
155
  toolCallId: toolCall.id,
155
156
  toolName,
156
157
  result: {
157
- error: `Input validation failed for tool ${tool.name}: ${validationError.message}`
158
+ error: `Input validation failed for tool ${tool.name}: ${message}`
158
159
  },
159
160
  state: "output-error"
160
161
  });
@@ -222,15 +223,8 @@ async function executeToolCalls(toolCalls, tools, approvals = /* @__PURE__ */ ne
222
223
  try {
223
224
  let result = await tool.execute(input);
224
225
  const duration = Date.now() - startTime2;
225
- if (tool.outputSchema && isZodSchema(tool.outputSchema) && result !== void 0 && result !== null) {
226
- const parsed = tool.outputSchema.safeParse(result);
227
- if (parsed.success) {
228
- result = parsed.data;
229
- } else {
230
- throw new Error(
231
- `Output validation failed for tool ${tool.name}: ${parsed.error.message}`
232
- );
233
- }
226
+ if (tool.outputSchema && isStandardSchema(tool.outputSchema) && result !== void 0 && result !== null) {
227
+ result = parseWithStandardSchema(tool.outputSchema, result);
234
228
  }
235
229
  results.push({
236
230
  toolCallId: toolCall.id,
@@ -240,10 +234,11 @@ async function executeToolCalls(toolCalls, tools, approvals = /* @__PURE__ */ ne
240
234
  });
241
235
  } catch (error) {
242
236
  const duration = Date.now() - startTime2;
237
+ const message = error instanceof Error ? error.message : "Unknown error";
243
238
  results.push({
244
239
  toolCallId: toolCall.id,
245
240
  toolName,
246
- result: { error: error.message },
241
+ result: { error: message },
247
242
  state: "output-error",
248
243
  duration
249
244
  });
@@ -270,15 +265,8 @@ async function executeToolCalls(toolCalls, tools, approvals = /* @__PURE__ */ ne
270
265
  try {
271
266
  let result = await tool.execute(input);
272
267
  const duration = Date.now() - startTime;
273
- if (tool.outputSchema && isZodSchema(tool.outputSchema) && result !== void 0 && result !== null) {
274
- const parsed = tool.outputSchema.safeParse(result);
275
- if (parsed.success) {
276
- result = parsed.data;
277
- } else {
278
- throw new Error(
279
- `Output validation failed for tool ${tool.name}: ${parsed.error.message}`
280
- );
281
- }
268
+ if (tool.outputSchema && isStandardSchema(tool.outputSchema) && result !== void 0 && result !== null) {
269
+ result = parseWithStandardSchema(tool.outputSchema, result);
282
270
  }
283
271
  results.push({
284
272
  toolCallId: toolCall.id,
@@ -288,10 +276,11 @@ async function executeToolCalls(toolCalls, tools, approvals = /* @__PURE__ */ ne
288
276
  });
289
277
  } catch (error) {
290
278
  const duration = Date.now() - startTime;
279
+ const message = error instanceof Error ? error.message : "Unknown error";
291
280
  results.push({
292
281
  toolCallId: toolCall.id,
293
282
  toolName,
294
- result: { error: error.message },
283
+ result: { error: message },
295
284
  state: "output-error",
296
285
  duration
297
286
  });
@@ -1 +1 @@
1
- {"version":3,"file":"tool-calls.js","sources":["../../../../../src/activities/chat/tools/tool-calls.ts"],"sourcesContent":["import type {\n DoneStreamChunk,\n ModelMessage,\n SchemaInput,\n Tool,\n ToolCall,\n ToolResultStreamChunk,\n} from '../../../types'\nimport type { z } from 'zod'\n\n/**\n * Check if a value is a Zod schema by looking for Zod-specific internals.\n */\nfunction isZodSchema(schema: SchemaInput | undefined): schema is z.ZodType {\n if (!schema) return false\n return '_zod' in schema && typeof (schema as any)._zod === 'object'\n}\n\n/**\n * Manages tool call accumulation and execution for the chat() method's automatic tool execution loop.\n *\n * Responsibilities:\n * - Accumulates streaming tool call chunks (ID, name, arguments)\n * - Validates tool calls (filters out incomplete ones)\n * - Executes tool `execute` functions with parsed arguments\n * - Emits `tool_result` chunks for client visibility\n * - Returns tool result messages for conversation history\n *\n * This class is used internally by the AI.chat() method to handle the automatic\n * tool execution loop. It can also be used independently for custom tool execution logic.\n *\n * @example\n * ```typescript\n * const manager = new ToolCallManager(tools);\n *\n * // During streaming, accumulate tool calls\n * for await (const chunk of stream) {\n * if (chunk.type === \"tool_call\") {\n * manager.addToolCallChunk(chunk);\n * }\n * }\n *\n * // After stream completes, execute tools\n * if (manager.hasToolCalls()) {\n * const toolResults = yield* manager.executeTools(doneChunk);\n * messages = [...messages, ...toolResults];\n * manager.clear();\n * }\n * ```\n */\nexport class ToolCallManager {\n private toolCallsMap = new Map<number, ToolCall>()\n private tools: ReadonlyArray<Tool>\n\n constructor(tools: ReadonlyArray<Tool>) {\n this.tools = tools\n }\n\n /**\n * Add a tool call chunk to the accumulator\n * Handles streaming tool calls by accumulating arguments\n */\n addToolCallChunk(chunk: {\n toolCall: {\n id: string\n type: 'function'\n function: {\n name: string\n arguments: string\n }\n }\n index: number\n }): void {\n const index = chunk.index\n const existing = this.toolCallsMap.get(index)\n\n if (!existing) {\n // Only create entry if we have a tool call ID and name\n if (chunk.toolCall.id && chunk.toolCall.function.name) {\n this.toolCallsMap.set(index, {\n id: chunk.toolCall.id,\n type: 'function',\n function: {\n name: chunk.toolCall.function.name,\n arguments: chunk.toolCall.function.arguments || '',\n },\n })\n }\n } else {\n // Update name if it wasn't set before\n if (chunk.toolCall.function.name && !existing.function.name) {\n existing.function.name = chunk.toolCall.function.name\n }\n // Accumulate arguments for streaming tool calls\n if (chunk.toolCall.function.arguments) {\n existing.function.arguments += chunk.toolCall.function.arguments\n }\n }\n }\n\n /**\n * Check if there are any complete tool calls to execute\n */\n hasToolCalls(): boolean {\n return this.getToolCalls().length > 0\n }\n\n /**\n * Get all complete tool calls (filtered for valid ID and name)\n */\n getToolCalls(): Array<ToolCall> {\n return Array.from(this.toolCallsMap.values()).filter(\n (tc) => tc.id && tc.function.name && tc.function.name.trim().length > 0,\n )\n }\n\n /**\n * Execute all tool calls and return tool result messages\n * Also yields tool_result chunks for streaming\n */\n async *executeTools(\n doneChunk: DoneStreamChunk,\n ): AsyncGenerator<ToolResultStreamChunk, Array<ModelMessage>, void> {\n const toolCallsArray = this.getToolCalls()\n const toolResults: Array<ModelMessage> = []\n\n for (const toolCall of toolCallsArray) {\n const tool = this.tools.find((t) => t.name === toolCall.function.name)\n\n let toolResultContent: string\n if (tool?.execute) {\n try {\n // Parse arguments\n let args: any\n try {\n args = JSON.parse(toolCall.function.arguments)\n } catch (parseError) {\n throw new Error(\n `Failed to parse tool arguments as JSON: ${toolCall.function.arguments}`,\n )\n }\n\n // Validate input against inputSchema (only for Zod schemas)\n if (tool.inputSchema && isZodSchema(tool.inputSchema)) {\n try {\n args = tool.inputSchema.parse(args)\n } catch (validationError: any) {\n throw new Error(\n `Input validation failed for tool ${tool.name}: ${validationError.message}`,\n )\n }\n }\n\n // Execute the tool\n let result = await tool.execute(args)\n\n // Validate output against outputSchema if provided (only for Zod schemas)\n if (\n tool.outputSchema &&\n isZodSchema(tool.outputSchema) &&\n result !== undefined &&\n result !== null\n ) {\n try {\n result = tool.outputSchema.parse(result)\n } catch (validationError: any) {\n throw new Error(\n `Output validation failed for tool ${tool.name}: ${validationError.message}`,\n )\n }\n }\n\n toolResultContent =\n typeof result === 'string' ? result : JSON.stringify(result)\n } catch (error: any) {\n // If tool execution fails, add error message\n toolResultContent = `Error executing tool: ${error.message}`\n }\n } else {\n // Tool doesn't have execute function, add placeholder\n toolResultContent = `Tool ${toolCall.function.name} does not have an execute function`\n }\n\n // Emit tool_result chunk so callers can track tool execution\n yield {\n type: 'tool_result',\n id: doneChunk.id,\n model: doneChunk.model,\n timestamp: Date.now(),\n toolCallId: toolCall.id,\n content: toolResultContent,\n }\n\n // Add tool result message\n toolResults.push({\n role: 'tool',\n content: toolResultContent,\n toolCallId: toolCall.id,\n })\n }\n\n return toolResults\n }\n\n /**\n * Clear the tool calls map for the next iteration\n */\n clear(): void {\n this.toolCallsMap.clear()\n }\n}\n\nexport interface ToolResult {\n toolCallId: string\n toolName: string\n result: any\n state?: 'output-available' | 'output-error'\n /** Duration of tool execution in milliseconds (only for server-executed tools) */\n duration?: number\n}\n\nexport interface ApprovalRequest {\n toolCallId: string\n toolName: string\n input: any\n approvalId: string\n}\n\nexport interface ClientToolRequest {\n toolCallId: string\n toolName: string\n input: any\n}\n\ninterface ExecuteToolCallsResult {\n /** Tool results ready to send to LLM */\n results: Array<ToolResult>\n /** Tools that need user approval before execution */\n needsApproval: Array<ApprovalRequest>\n /** Tools that need client-side execution */\n needsClientExecution: Array<ClientToolRequest>\n}\n\n/**\n * Execute tool calls based on their configuration\n *\n * Handles three cases:\n * 1. Client tools (no execute) - request client to execute\n * 2. Server tools with approval - check approval before executing\n * 3. Normal server tools - execute immediately\n *\n * @param toolCalls - Tool calls from the LLM\n * @param tools - Available tools with their configurations\n * @param approvals - Map of approval decisions (approval.id -> approved boolean)\n * @param clientResults - Map of client-side execution results (toolCallId -> result)\n */\nexport async function executeToolCalls(\n toolCalls: Array<ToolCall>,\n tools: ReadonlyArray<Tool>,\n approvals: Map<string, boolean> = new Map(),\n clientResults: Map<string, any> = new Map(),\n): Promise<ExecuteToolCallsResult> {\n const results: Array<ToolResult> = []\n const needsApproval: Array<ApprovalRequest> = []\n const needsClientExecution: Array<ClientToolRequest> = []\n\n // Create tool lookup map\n const toolMap = new Map<string, Tool>()\n for (const tool of tools) {\n toolMap.set(tool.name, tool)\n }\n\n for (const toolCall of toolCalls) {\n const tool = toolMap.get(toolCall.function.name)\n const toolName = toolCall.function.name\n\n if (!tool) {\n // Unknown tool - return error\n results.push({\n toolCallId: toolCall.id,\n toolName,\n result: { error: `Unknown tool: ${toolName}` },\n state: 'output-error',\n })\n continue\n }\n\n // Parse arguments, throwing error if invalid JSON\n let input: any = {}\n const argsStr = toolCall.function.arguments.trim() || '{}'\n if (argsStr) {\n try {\n input = JSON.parse(argsStr)\n } catch (parseError) {\n // If parsing fails, throw error to fail fast\n throw new Error(`Failed to parse tool arguments as JSON: ${argsStr}`)\n }\n }\n\n // Validate input against inputSchema (only for Zod schemas)\n if (tool.inputSchema && isZodSchema(tool.inputSchema)) {\n try {\n input = tool.inputSchema.parse(input)\n } catch (validationError: any) {\n results.push({\n toolCallId: toolCall.id,\n toolName,\n result: {\n error: `Input validation failed for tool ${tool.name}: ${validationError.message}`,\n },\n state: 'output-error',\n })\n continue\n }\n }\n\n // CASE 1: Client-side tool (no execute function)\n if (!tool.execute) {\n // Check if tool needs approval\n if (tool.needsApproval) {\n const approvalId = `approval_${toolCall.id}`\n\n // Check if approval decision exists\n if (approvals.has(approvalId)) {\n const approved = approvals.get(approvalId)\n\n if (approved) {\n // Approved - check if client has executed\n if (clientResults.has(toolCall.id)) {\n results.push({\n toolCallId: toolCall.id,\n toolName,\n result: clientResults.get(toolCall.id),\n })\n } else {\n // Approved but not executed yet - request client execution\n needsClientExecution.push({\n toolCallId: toolCall.id,\n toolName,\n input,\n })\n }\n } else {\n // User declined\n results.push({\n toolCallId: toolCall.id,\n toolName,\n result: { error: 'User declined tool execution' },\n state: 'output-error',\n })\n }\n } else {\n // Need approval first\n needsApproval.push({\n toolCallId: toolCall.id,\n toolName: toolCall.function.name,\n input,\n approvalId,\n })\n }\n } else {\n // No approval needed - check if client has executed\n if (clientResults.has(toolCall.id)) {\n results.push({\n toolCallId: toolCall.id,\n toolName,\n result: clientResults.get(toolCall.id),\n })\n } else {\n // Request client execution\n needsClientExecution.push({\n toolCallId: toolCall.id,\n toolName,\n input,\n })\n }\n }\n continue\n }\n\n // CASE 2: Server tool with approval required\n if (tool.needsApproval) {\n const approvalId = `approval_${toolCall.id}`\n\n // Check if approval decision exists\n if (approvals.has(approvalId)) {\n const approved = approvals.get(approvalId)\n\n if (approved) {\n // Execute after approval\n const startTime = Date.now()\n try {\n let result = await tool.execute(input)\n const duration = Date.now() - startTime\n\n // Validate output against outputSchema if provided (only for Zod schemas)\n if (\n tool.outputSchema &&\n isZodSchema(tool.outputSchema) &&\n result !== undefined &&\n result !== null\n ) {\n const parsed = tool.outputSchema.safeParse(result)\n if (parsed.success) {\n result = parsed.data\n } else {\n throw new Error(\n `Output validation failed for tool ${tool.name}: ${parsed.error.message}`,\n )\n }\n }\n\n results.push({\n toolCallId: toolCall.id,\n toolName,\n result:\n typeof result === 'string'\n ? JSON.parse(result)\n : result || null,\n duration,\n })\n } catch (error: any) {\n const duration = Date.now() - startTime\n results.push({\n toolCallId: toolCall.id,\n toolName,\n result: { error: error.message },\n state: 'output-error',\n duration,\n })\n }\n } else {\n // User declined\n results.push({\n toolCallId: toolCall.id,\n toolName,\n result: { error: 'User declined tool execution' },\n state: 'output-error',\n })\n }\n } else {\n // Need approval\n needsApproval.push({\n toolCallId: toolCall.id,\n toolName,\n input,\n approvalId,\n })\n }\n continue\n }\n\n // CASE 3: Normal server tool - execute immediately\n const startTime = Date.now()\n try {\n let result = await tool.execute(input)\n const duration = Date.now() - startTime\n\n // Validate output against outputSchema if provided (only for Zod schemas)\n if (\n tool.outputSchema &&\n isZodSchema(tool.outputSchema) &&\n result !== undefined &&\n result !== null\n ) {\n const parsed = tool.outputSchema.safeParse(result)\n if (parsed.success) {\n result = parsed.data\n } else {\n throw new Error(\n `Output validation failed for tool ${tool.name}: ${parsed.error.message}`,\n )\n }\n }\n\n results.push({\n toolCallId: toolCall.id,\n toolName,\n result:\n typeof result === 'string' ? JSON.parse(result) : result || null,\n duration,\n })\n } catch (error: any) {\n const duration = Date.now() - startTime\n results.push({\n toolCallId: toolCall.id,\n toolName,\n result: { error: error.message },\n state: 'output-error',\n duration,\n })\n }\n }\n\n return { results, needsApproval, needsClientExecution }\n}\n"],"names":["startTime"],"mappings":"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"}
1
+ {"version":3,"file":"tool-calls.js","sources":["../../../../../src/activities/chat/tools/tool-calls.ts"],"sourcesContent":["import { isStandardSchema, parseWithStandardSchema } from './schema-converter'\nimport type {\n DoneStreamChunk,\n ModelMessage,\n Tool,\n ToolCall,\n ToolResultStreamChunk,\n} from '../../../types'\n\n/**\n * Manages tool call accumulation and execution for the chat() method's automatic tool execution loop.\n *\n * Responsibilities:\n * - Accumulates streaming tool call chunks (ID, name, arguments)\n * - Validates tool calls (filters out incomplete ones)\n * - Executes tool `execute` functions with parsed arguments\n * - Emits `tool_result` chunks for client visibility\n * - Returns tool result messages for conversation history\n *\n * This class is used internally by the AI.chat() method to handle the automatic\n * tool execution loop. It can also be used independently for custom tool execution logic.\n *\n * @example\n * ```typescript\n * const manager = new ToolCallManager(tools);\n *\n * // During streaming, accumulate tool calls\n * for await (const chunk of stream) {\n * if (chunk.type === \"tool_call\") {\n * manager.addToolCallChunk(chunk);\n * }\n * }\n *\n * // After stream completes, execute tools\n * if (manager.hasToolCalls()) {\n * const toolResults = yield* manager.executeTools(doneChunk);\n * messages = [...messages, ...toolResults];\n * manager.clear();\n * }\n * ```\n */\nexport class ToolCallManager {\n private toolCallsMap = new Map<number, ToolCall>()\n private tools: ReadonlyArray<Tool>\n\n constructor(tools: ReadonlyArray<Tool>) {\n this.tools = tools\n }\n\n /**\n * Add a tool call chunk to the accumulator\n * Handles streaming tool calls by accumulating arguments\n */\n addToolCallChunk(chunk: {\n toolCall: {\n id: string\n type: 'function'\n function: {\n name: string\n arguments: string\n }\n }\n index: number\n }): void {\n const index = chunk.index\n const existing = this.toolCallsMap.get(index)\n\n if (!existing) {\n // Only create entry if we have a tool call ID and name\n if (chunk.toolCall.id && chunk.toolCall.function.name) {\n this.toolCallsMap.set(index, {\n id: chunk.toolCall.id,\n type: 'function',\n function: {\n name: chunk.toolCall.function.name,\n arguments: chunk.toolCall.function.arguments || '',\n },\n })\n }\n } else {\n // Update name if it wasn't set before\n if (chunk.toolCall.function.name && !existing.function.name) {\n existing.function.name = chunk.toolCall.function.name\n }\n // Accumulate arguments for streaming tool calls\n if (chunk.toolCall.function.arguments) {\n existing.function.arguments += chunk.toolCall.function.arguments\n }\n }\n }\n\n /**\n * Check if there are any complete tool calls to execute\n */\n hasToolCalls(): boolean {\n return this.getToolCalls().length > 0\n }\n\n /**\n * Get all complete tool calls (filtered for valid ID and name)\n */\n getToolCalls(): Array<ToolCall> {\n return Array.from(this.toolCallsMap.values()).filter(\n (tc) => tc.id && tc.function.name && tc.function.name.trim().length > 0,\n )\n }\n\n /**\n * Execute all tool calls and return tool result messages\n * Also yields tool_result chunks for streaming\n */\n async *executeTools(\n doneChunk: DoneStreamChunk,\n ): AsyncGenerator<ToolResultStreamChunk, Array<ModelMessage>, void> {\n const toolCallsArray = this.getToolCalls()\n const toolResults: Array<ModelMessage> = []\n\n for (const toolCall of toolCallsArray) {\n const tool = this.tools.find((t) => t.name === toolCall.function.name)\n\n let toolResultContent: string\n if (tool?.execute) {\n try {\n // Parse arguments\n let args: unknown\n try {\n args = JSON.parse(toolCall.function.arguments)\n } catch (parseError) {\n throw new Error(\n `Failed to parse tool arguments as JSON: ${toolCall.function.arguments}`,\n )\n }\n\n // Validate input against inputSchema (for Standard Schema compliant schemas)\n if (tool.inputSchema && isStandardSchema(tool.inputSchema)) {\n try {\n args = parseWithStandardSchema(tool.inputSchema, args)\n } catch (validationError: unknown) {\n const message =\n validationError instanceof Error\n ? validationError.message\n : 'Validation failed'\n throw new Error(\n `Input validation failed for tool ${tool.name}: ${message}`,\n )\n }\n }\n\n // Execute the tool\n let result = await tool.execute(args)\n\n // Validate output against outputSchema if provided (for Standard Schema compliant schemas)\n if (\n tool.outputSchema &&\n isStandardSchema(tool.outputSchema) &&\n result !== undefined &&\n result !== null\n ) {\n try {\n result = parseWithStandardSchema(tool.outputSchema, result)\n } catch (validationError: unknown) {\n const message =\n validationError instanceof Error\n ? validationError.message\n : 'Validation failed'\n throw new Error(\n `Output validation failed for tool ${tool.name}: ${message}`,\n )\n }\n }\n\n toolResultContent =\n typeof result === 'string' ? result : JSON.stringify(result)\n } catch (error: unknown) {\n // If tool execution fails, add error message\n const message =\n error instanceof Error ? error.message : 'Unknown error'\n toolResultContent = `Error executing tool: ${message}`\n }\n } else {\n // Tool doesn't have execute function, add placeholder\n toolResultContent = `Tool ${toolCall.function.name} does not have an execute function`\n }\n\n // Emit tool_result chunk so callers can track tool execution\n yield {\n type: 'tool_result',\n id: doneChunk.id,\n model: doneChunk.model,\n timestamp: Date.now(),\n toolCallId: toolCall.id,\n content: toolResultContent,\n }\n\n // Add tool result message\n toolResults.push({\n role: 'tool',\n content: toolResultContent,\n toolCallId: toolCall.id,\n })\n }\n\n return toolResults\n }\n\n /**\n * Clear the tool calls map for the next iteration\n */\n clear(): void {\n this.toolCallsMap.clear()\n }\n}\n\nexport interface ToolResult {\n toolCallId: string\n toolName: string\n result: any\n state?: 'output-available' | 'output-error'\n /** Duration of tool execution in milliseconds (only for server-executed tools) */\n duration?: number\n}\n\nexport interface ApprovalRequest {\n toolCallId: string\n toolName: string\n input: any\n approvalId: string\n}\n\nexport interface ClientToolRequest {\n toolCallId: string\n toolName: string\n input: any\n}\n\ninterface ExecuteToolCallsResult {\n /** Tool results ready to send to LLM */\n results: Array<ToolResult>\n /** Tools that need user approval before execution */\n needsApproval: Array<ApprovalRequest>\n /** Tools that need client-side execution */\n needsClientExecution: Array<ClientToolRequest>\n}\n\n/**\n * Execute tool calls based on their configuration\n *\n * Handles three cases:\n * 1. Client tools (no execute) - request client to execute\n * 2. Server tools with approval - check approval before executing\n * 3. Normal server tools - execute immediately\n *\n * @param toolCalls - Tool calls from the LLM\n * @param tools - Available tools with their configurations\n * @param approvals - Map of approval decisions (approval.id -> approved boolean)\n * @param clientResults - Map of client-side execution results (toolCallId -> result)\n */\nexport async function executeToolCalls(\n toolCalls: Array<ToolCall>,\n tools: ReadonlyArray<Tool>,\n approvals: Map<string, boolean> = new Map(),\n clientResults: Map<string, any> = new Map(),\n): Promise<ExecuteToolCallsResult> {\n const results: Array<ToolResult> = []\n const needsApproval: Array<ApprovalRequest> = []\n const needsClientExecution: Array<ClientToolRequest> = []\n\n // Create tool lookup map\n const toolMap = new Map<string, Tool>()\n for (const tool of tools) {\n toolMap.set(tool.name, tool)\n }\n\n for (const toolCall of toolCalls) {\n const tool = toolMap.get(toolCall.function.name)\n const toolName = toolCall.function.name\n\n if (!tool) {\n // Unknown tool - return error\n results.push({\n toolCallId: toolCall.id,\n toolName,\n result: { error: `Unknown tool: ${toolName}` },\n state: 'output-error',\n })\n continue\n }\n\n // Parse arguments, throwing error if invalid JSON\n let input: unknown = {}\n const argsStr = toolCall.function.arguments.trim() || '{}'\n if (argsStr) {\n try {\n input = JSON.parse(argsStr)\n } catch (parseError) {\n // If parsing fails, throw error to fail fast\n throw new Error(`Failed to parse tool arguments as JSON: ${argsStr}`)\n }\n }\n\n // Validate input against inputSchema (for Standard Schema compliant schemas)\n if (tool.inputSchema && isStandardSchema(tool.inputSchema)) {\n try {\n input = parseWithStandardSchema(tool.inputSchema, input)\n } catch (validationError: unknown) {\n const message =\n validationError instanceof Error\n ? validationError.message\n : 'Validation failed'\n results.push({\n toolCallId: toolCall.id,\n toolName,\n result: {\n error: `Input validation failed for tool ${tool.name}: ${message}`,\n },\n state: 'output-error',\n })\n continue\n }\n }\n\n // CASE 1: Client-side tool (no execute function)\n if (!tool.execute) {\n // Check if tool needs approval\n if (tool.needsApproval) {\n const approvalId = `approval_${toolCall.id}`\n\n // Check if approval decision exists\n if (approvals.has(approvalId)) {\n const approved = approvals.get(approvalId)\n\n if (approved) {\n // Approved - check if client has executed\n if (clientResults.has(toolCall.id)) {\n results.push({\n toolCallId: toolCall.id,\n toolName,\n result: clientResults.get(toolCall.id),\n })\n } else {\n // Approved but not executed yet - request client execution\n needsClientExecution.push({\n toolCallId: toolCall.id,\n toolName,\n input,\n })\n }\n } else {\n // User declined\n results.push({\n toolCallId: toolCall.id,\n toolName,\n result: { error: 'User declined tool execution' },\n state: 'output-error',\n })\n }\n } else {\n // Need approval first\n needsApproval.push({\n toolCallId: toolCall.id,\n toolName: toolCall.function.name,\n input,\n approvalId,\n })\n }\n } else {\n // No approval needed - check if client has executed\n if (clientResults.has(toolCall.id)) {\n results.push({\n toolCallId: toolCall.id,\n toolName,\n result: clientResults.get(toolCall.id),\n })\n } else {\n // Request client execution\n needsClientExecution.push({\n toolCallId: toolCall.id,\n toolName,\n input,\n })\n }\n }\n continue\n }\n\n // CASE 2: Server tool with approval required\n if (tool.needsApproval) {\n const approvalId = `approval_${toolCall.id}`\n\n // Check if approval decision exists\n if (approvals.has(approvalId)) {\n const approved = approvals.get(approvalId)\n\n if (approved) {\n // Execute after approval\n const startTime = Date.now()\n try {\n let result = await tool.execute(input)\n const duration = Date.now() - startTime\n\n // Validate output against outputSchema if provided (for Standard Schema compliant schemas)\n if (\n tool.outputSchema &&\n isStandardSchema(tool.outputSchema) &&\n result !== undefined &&\n result !== null\n ) {\n result = parseWithStandardSchema(tool.outputSchema, result)\n }\n\n results.push({\n toolCallId: toolCall.id,\n toolName,\n result:\n typeof result === 'string'\n ? JSON.parse(result)\n : result || null,\n duration,\n })\n } catch (error: unknown) {\n const duration = Date.now() - startTime\n const message =\n error instanceof Error ? error.message : 'Unknown error'\n results.push({\n toolCallId: toolCall.id,\n toolName,\n result: { error: message },\n state: 'output-error',\n duration,\n })\n }\n } else {\n // User declined\n results.push({\n toolCallId: toolCall.id,\n toolName,\n result: { error: 'User declined tool execution' },\n state: 'output-error',\n })\n }\n } else {\n // Need approval\n needsApproval.push({\n toolCallId: toolCall.id,\n toolName,\n input,\n approvalId,\n })\n }\n continue\n }\n\n // CASE 3: Normal server tool - execute immediately\n const startTime = Date.now()\n try {\n let result = await tool.execute(input)\n const duration = Date.now() - startTime\n\n // Validate output against outputSchema if provided (for Standard Schema compliant schemas)\n if (\n tool.outputSchema &&\n isStandardSchema(tool.outputSchema) &&\n result !== undefined &&\n result !== null\n ) {\n result = parseWithStandardSchema(tool.outputSchema, result)\n }\n\n results.push({\n toolCallId: toolCall.id,\n toolName,\n result:\n typeof result === 'string' ? JSON.parse(result) : result || null,\n duration,\n })\n } catch (error: unknown) {\n const duration = Date.now() - startTime\n const message = error instanceof Error ? error.message : 'Unknown error'\n results.push({\n toolCallId: toolCall.id,\n toolName,\n result: { error: message },\n state: 'output-error',\n duration,\n })\n }\n }\n\n return { results, needsApproval, needsClientExecution }\n}\n"],"names":["startTime"],"mappings":"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"}
@@ -1,34 +1,34 @@
1
- import { z } from 'zod';
1
+ import { StandardJSONSchemaV1 } from '@standard-schema/spec';
2
2
  import { InferSchemaType, JSONSchema, SchemaInput, Tool } from '../../../types.js';
3
3
  /**
4
4
  * Marker type for server-side tools
5
5
  */
6
- export interface ServerTool<TInput extends SchemaInput = z.ZodType, TOutput extends SchemaInput = z.ZodType, TName extends string = string> extends Tool<TInput, TOutput, TName> {
6
+ export interface ServerTool<TInput extends SchemaInput = SchemaInput, TOutput extends SchemaInput = SchemaInput, TName extends string = string> extends Tool<TInput, TOutput, TName> {
7
7
  __toolSide: 'server';
8
8
  }
9
9
  /**
10
10
  * Marker type for client-side tools
11
11
  */
12
- export interface ClientTool<TInput extends SchemaInput = z.ZodType, TOutput extends SchemaInput = z.ZodType, TName extends string = string> {
12
+ export interface ClientTool<TInput extends SchemaInput = SchemaInput, TOutput extends SchemaInput = SchemaInput, TName extends string = string> {
13
13
  __toolSide: 'client';
14
14
  name: TName;
15
15
  description: string;
16
16
  inputSchema?: TInput;
17
17
  outputSchema?: TOutput;
18
18
  needsApproval?: boolean;
19
- metadata?: Record<string, any>;
19
+ metadata?: Record<string, unknown>;
20
20
  execute?: (args: InferSchemaType<TInput>) => Promise<InferSchemaType<TOutput>> | InferSchemaType<TOutput>;
21
21
  }
22
22
  /**
23
23
  * Tool definition that can be used directly or instantiated for server/client
24
24
  */
25
- export interface ToolDefinitionInstance<TInput extends SchemaInput = z.ZodType, TOutput extends SchemaInput = z.ZodType, TName extends string = string> extends Tool<TInput, TOutput, TName> {
25
+ export interface ToolDefinitionInstance<TInput extends SchemaInput = SchemaInput, TOutput extends SchemaInput = SchemaInput, TName extends string = string> extends Tool<TInput, TOutput, TName> {
26
26
  __toolSide: 'definition';
27
27
  }
28
28
  /**
29
29
  * Union type for any kind of client-side tool (client tool or definition)
30
30
  */
31
- export type AnyClientTool = ClientTool<any, any> | ToolDefinitionInstance<any, any>;
31
+ export type AnyClientTool = ClientTool<SchemaInput, SchemaInput> | ToolDefinitionInstance<SchemaInput, SchemaInput>;
32
32
  /**
33
33
  * Extract the tool name as a literal type
34
34
  */
@@ -36,32 +36,32 @@ export type InferToolName<T> = T extends {
36
36
  name: infer N;
37
37
  } ? N : never;
38
38
  /**
39
- * Extract the input type from a tool (inferred from Zod schema, or `any` for JSONSchema)
39
+ * Extract the input type from a tool (inferred from Standard JSON Schema, or `unknown` for plain JSONSchema)
40
40
  */
41
41
  export type InferToolInput<T> = T extends {
42
42
  inputSchema?: infer TInput;
43
- } ? TInput extends z.ZodType ? z.infer<TInput> : TInput extends JSONSchema ? any : any : any;
43
+ } ? TInput extends StandardJSONSchemaV1<infer TInferred, unknown> ? TInferred : TInput extends JSONSchema ? unknown : unknown : unknown;
44
44
  /**
45
- * Extract the output type from a tool (inferred from Zod schema, or `any` for JSONSchema)
45
+ * Extract the output type from a tool (inferred from Standard JSON Schema, or `unknown` for plain JSONSchema)
46
46
  */
47
47
  export type InferToolOutput<T> = T extends {
48
48
  outputSchema?: infer TOutput;
49
- } ? TOutput extends z.ZodType ? z.infer<TOutput> : TOutput extends JSONSchema ? any : any : any;
49
+ } ? TOutput extends StandardJSONSchemaV1<infer TInferred, unknown> ? TInferred : TOutput extends JSONSchema ? unknown : unknown : unknown;
50
50
  /**
51
51
  * Tool definition configuration
52
52
  */
53
- export interface ToolDefinitionConfig<TInput extends SchemaInput = z.ZodType, TOutput extends SchemaInput = z.ZodType, TName extends string = string> {
53
+ export interface ToolDefinitionConfig<TInput extends SchemaInput = SchemaInput, TOutput extends SchemaInput = SchemaInput, TName extends string = string> {
54
54
  name: TName;
55
55
  description: string;
56
56
  inputSchema?: TInput;
57
57
  outputSchema?: TOutput;
58
58
  needsApproval?: boolean;
59
- metadata?: Record<string, any>;
59
+ metadata?: Record<string, unknown>;
60
60
  }
61
61
  /**
62
62
  * Tool definition builder that allows creating server or client tools from a shared definition
63
63
  */
64
- export interface ToolDefinition<TInput extends SchemaInput = z.ZodType, TOutput extends SchemaInput = z.ZodType, TName extends string = string> extends ToolDefinitionInstance<TInput, TOutput, TName> {
64
+ export interface ToolDefinition<TInput extends SchemaInput = SchemaInput, TOutput extends SchemaInput = SchemaInput, TName extends string = string> extends ToolDefinitionInstance<TInput, TOutput, TName> {
65
65
  /**
66
66
  * Create a server-side tool with execute function
67
67
  */
@@ -79,11 +79,15 @@ export interface ToolDefinition<TInput extends SchemaInput = z.ZodType, TOutput
79
79
  * 2. Instantiated as a server tool with .server()
80
80
  * 3. Instantiated as a client tool with .client()
81
81
  *
82
+ * Supports any Standard JSON Schema compliant library (Zod v4+, ArkType, Valibot, etc.)
83
+ * or plain JSON Schema objects.
84
+ *
82
85
  * @example
83
86
  * ```typescript
84
87
  * import { toolDefinition } from '@tanstack/ai';
85
88
  * import { z } from 'zod';
86
89
  *
90
+ * // Using Zod (natively supports Standard JSON Schema)
87
91
  * const addToCartTool = toolDefinition({
88
92
  * name: 'addToCart',
89
93
  * description: 'Add a guitar to the shopping cart (requires approval)',
@@ -122,4 +126,4 @@ export interface ToolDefinition<TInput extends SchemaInput = z.ZodType, TOutput
122
126
  * });
123
127
  * ```
124
128
  */
125
- export declare function toolDefinition<TInput extends SchemaInput = z.ZodAny, TOutput extends SchemaInput = z.ZodAny, TName extends string = string>(config: ToolDefinitionConfig<TInput, TOutput, TName>): ToolDefinition<TInput, TOutput, TName>;
129
+ export declare function toolDefinition<TInput extends SchemaInput = SchemaInput, TOutput extends SchemaInput = SchemaInput, TName extends string = string>(config: ToolDefinitionConfig<TInput, TOutput, TName>): ToolDefinition<TInput, TOutput, TName>;
@@ -1 +1 @@
1
- {"version":3,"file":"tool-definition.js","sources":["../../../../../src/activities/chat/tools/tool-definition.ts"],"sourcesContent":["import type { z } from 'zod'\nimport type {\n InferSchemaType,\n JSONSchema,\n SchemaInput,\n Tool,\n} from '../../../types'\n\n/**\n * Marker type for server-side tools\n */\nexport interface ServerTool<\n TInput extends SchemaInput = z.ZodType,\n TOutput extends SchemaInput = z.ZodType,\n TName extends string = string,\n> extends Tool<TInput, TOutput, TName> {\n __toolSide: 'server'\n}\n\n/**\n * Marker type for client-side tools\n */\nexport interface ClientTool<\n TInput extends SchemaInput = z.ZodType,\n TOutput extends SchemaInput = z.ZodType,\n TName extends string = string,\n> {\n __toolSide: 'client'\n name: TName\n description: string\n inputSchema?: TInput\n outputSchema?: TOutput\n needsApproval?: boolean\n metadata?: Record<string, any>\n execute?: (\n args: InferSchemaType<TInput>,\n ) => Promise<InferSchemaType<TOutput>> | InferSchemaType<TOutput>\n}\n\n/**\n * Tool definition that can be used directly or instantiated for server/client\n */\nexport interface ToolDefinitionInstance<\n TInput extends SchemaInput = z.ZodType,\n TOutput extends SchemaInput = z.ZodType,\n TName extends string = string,\n> extends Tool<TInput, TOutput, TName> {\n __toolSide: 'definition'\n}\n\n/**\n * Union type for any kind of client-side tool (client tool or definition)\n */\nexport type AnyClientTool =\n | ClientTool<any, any>\n | ToolDefinitionInstance<any, any>\n\n/**\n * Extract the tool name as a literal type\n */\nexport type InferToolName<T> = T extends { name: infer N } ? N : never\n\n/**\n * Extract the input type from a tool (inferred from Zod schema, or `any` for JSONSchema)\n */\nexport type InferToolInput<T> = T extends { inputSchema?: infer TInput }\n ? TInput extends z.ZodType\n ? z.infer<TInput>\n : TInput extends JSONSchema\n ? any\n : any\n : any\n\n/**\n * Extract the output type from a tool (inferred from Zod schema, or `any` for JSONSchema)\n */\nexport type InferToolOutput<T> = T extends { outputSchema?: infer TOutput }\n ? TOutput extends z.ZodType\n ? z.infer<TOutput>\n : TOutput extends JSONSchema\n ? any\n : any\n : any\n\n/**\n * Tool definition configuration\n */\nexport interface ToolDefinitionConfig<\n TInput extends SchemaInput = z.ZodType,\n TOutput extends SchemaInput = z.ZodType,\n TName extends string = string,\n> {\n name: TName\n description: string\n inputSchema?: TInput\n outputSchema?: TOutput\n needsApproval?: boolean\n metadata?: Record<string, any>\n}\n\n/**\n * Tool definition builder that allows creating server or client tools from a shared definition\n */\nexport interface ToolDefinition<\n TInput extends SchemaInput = z.ZodType,\n TOutput extends SchemaInput = z.ZodType,\n TName extends string = string,\n> extends ToolDefinitionInstance<TInput, TOutput, TName> {\n /**\n * Create a server-side tool with execute function\n */\n server: (\n execute: (\n args: InferSchemaType<TInput>,\n ) => Promise<InferSchemaType<TOutput>> | InferSchemaType<TOutput>,\n ) => ServerTool<TInput, TOutput, TName>\n\n /**\n * Create a client-side tool with optional execute function\n */\n client: (\n execute?: (\n args: InferSchemaType<TInput>,\n ) => Promise<InferSchemaType<TOutput>> | InferSchemaType<TOutput>,\n ) => ClientTool<TInput, TOutput, TName>\n}\n\n/**\n * Create an isomorphic tool definition that can be used directly or instantiated for server/client\n *\n * The definition contains all tool metadata (name, description, schemas) and can be:\n * 1. Used directly in chat() on the server (as a tool definition without execute)\n * 2. Instantiated as a server tool with .server()\n * 3. Instantiated as a client tool with .client()\n *\n * @example\n * ```typescript\n * import { toolDefinition } from '@tanstack/ai';\n * import { z } from 'zod';\n *\n * const addToCartTool = toolDefinition({\n * name: 'addToCart',\n * description: 'Add a guitar to the shopping cart (requires approval)',\n * needsApproval: true,\n * inputSchema: z.object({\n * guitarId: z.string(),\n * quantity: z.number(),\n * }),\n * outputSchema: z.object({\n * success: z.boolean(),\n * cartId: z.string(),\n * totalItems: z.number(),\n * }),\n * });\n *\n * // Use directly in chat (server-side, no execute function)\n * chat({\n * tools: [addToCartTool],\n * // ...\n * });\n *\n * // Or create server-side implementation\n * const addToCartServer = addToCartTool.server(async (args) => {\n * // args is typed as { guitarId: string; quantity: number }\n * return {\n * success: true,\n * cartId: 'CART_' + Date.now(),\n * totalItems: args.quantity,\n * };\n * });\n *\n * // Or create client-side implementation\n * const addToCartClient = addToCartTool.client(async (args) => {\n * // Client-specific logic (e.g., localStorage)\n * return { success: true, cartId: 'local', totalItems: 1 };\n * });\n * ```\n */\nexport function toolDefinition<\n TInput extends SchemaInput = z.ZodAny,\n TOutput extends SchemaInput = z.ZodAny,\n TName extends string = string,\n>(\n config: ToolDefinitionConfig<TInput, TOutput, TName>,\n): ToolDefinition<TInput, TOutput, TName> {\n const definition: ToolDefinition<TInput, TOutput, TName> = {\n __toolSide: 'definition',\n ...config,\n server(\n execute: (\n args: InferSchemaType<TInput>,\n ) => Promise<InferSchemaType<TOutput>> | InferSchemaType<TOutput>,\n ): ServerTool<TInput, TOutput, TName> {\n return {\n __toolSide: 'server',\n ...config,\n execute,\n }\n },\n\n client(\n execute?: (\n args: InferSchemaType<TInput>,\n ) => Promise<InferSchemaType<TOutput>> | InferSchemaType<TOutput>,\n ): ClientTool<TInput, TOutput, TName> {\n return {\n __toolSide: 'client',\n ...config,\n execute,\n }\n },\n }\n\n return definition\n}\n"],"names":[],"mappings":"AAkLO,SAAS,eAKd,QACwC;AACxC,QAAM,aAAqD;AAAA,IACzD,YAAY;AAAA,IACZ,GAAG;AAAA,IACH,OACE,SAGoC;AACpC,aAAO;AAAA,QACL,YAAY;AAAA,QACZ,GAAG;AAAA,QACH;AAAA,MAAA;AAAA,IAEJ;AAAA,IAEA,OACE,SAGoC;AACpC,aAAO;AAAA,QACL,YAAY;AAAA,QACZ,GAAG;AAAA,QACH;AAAA,MAAA;AAAA,IAEJ;AAAA,EAAA;AAGF,SAAO;AACT;"}
1
+ {"version":3,"file":"tool-definition.js","sources":["../../../../../src/activities/chat/tools/tool-definition.ts"],"sourcesContent":["import type { StandardJSONSchemaV1 } from '@standard-schema/spec'\nimport type {\n InferSchemaType,\n JSONSchema,\n SchemaInput,\n Tool,\n} from '../../../types'\n\n/**\n * Marker type for server-side tools\n */\nexport interface ServerTool<\n TInput extends SchemaInput = SchemaInput,\n TOutput extends SchemaInput = SchemaInput,\n TName extends string = string,\n> extends Tool<TInput, TOutput, TName> {\n __toolSide: 'server'\n}\n\n/**\n * Marker type for client-side tools\n */\nexport interface ClientTool<\n TInput extends SchemaInput = SchemaInput,\n TOutput extends SchemaInput = SchemaInput,\n TName extends string = string,\n> {\n __toolSide: 'client'\n name: TName\n description: string\n inputSchema?: TInput\n outputSchema?: TOutput\n needsApproval?: boolean\n metadata?: Record<string, unknown>\n execute?: (\n args: InferSchemaType<TInput>,\n ) => Promise<InferSchemaType<TOutput>> | InferSchemaType<TOutput>\n}\n\n/**\n * Tool definition that can be used directly or instantiated for server/client\n */\nexport interface ToolDefinitionInstance<\n TInput extends SchemaInput = SchemaInput,\n TOutput extends SchemaInput = SchemaInput,\n TName extends string = string,\n> extends Tool<TInput, TOutput, TName> {\n __toolSide: 'definition'\n}\n\n/**\n * Union type for any kind of client-side tool (client tool or definition)\n */\nexport type AnyClientTool =\n | ClientTool<SchemaInput, SchemaInput>\n | ToolDefinitionInstance<SchemaInput, SchemaInput>\n\n/**\n * Extract the tool name as a literal type\n */\nexport type InferToolName<T> = T extends { name: infer N } ? N : never\n\n/**\n * Extract the input type from a tool (inferred from Standard JSON Schema, or `unknown` for plain JSONSchema)\n */\nexport type InferToolInput<T> = T extends { inputSchema?: infer TInput }\n ? TInput extends StandardJSONSchemaV1<infer TInferred, unknown>\n ? TInferred\n : TInput extends JSONSchema\n ? unknown\n : unknown\n : unknown\n\n/**\n * Extract the output type from a tool (inferred from Standard JSON Schema, or `unknown` for plain JSONSchema)\n */\nexport type InferToolOutput<T> = T extends { outputSchema?: infer TOutput }\n ? TOutput extends StandardJSONSchemaV1<infer TInferred, unknown>\n ? TInferred\n : TOutput extends JSONSchema\n ? unknown\n : unknown\n : unknown\n\n/**\n * Tool definition configuration\n */\nexport interface ToolDefinitionConfig<\n TInput extends SchemaInput = SchemaInput,\n TOutput extends SchemaInput = SchemaInput,\n TName extends string = string,\n> {\n name: TName\n description: string\n inputSchema?: TInput\n outputSchema?: TOutput\n needsApproval?: boolean\n metadata?: Record<string, unknown>\n}\n\n/**\n * Tool definition builder that allows creating server or client tools from a shared definition\n */\nexport interface ToolDefinition<\n TInput extends SchemaInput = SchemaInput,\n TOutput extends SchemaInput = SchemaInput,\n TName extends string = string,\n> extends ToolDefinitionInstance<TInput, TOutput, TName> {\n /**\n * Create a server-side tool with execute function\n */\n server: (\n execute: (\n args: InferSchemaType<TInput>,\n ) => Promise<InferSchemaType<TOutput>> | InferSchemaType<TOutput>,\n ) => ServerTool<TInput, TOutput, TName>\n\n /**\n * Create a client-side tool with optional execute function\n */\n client: (\n execute?: (\n args: InferSchemaType<TInput>,\n ) => Promise<InferSchemaType<TOutput>> | InferSchemaType<TOutput>,\n ) => ClientTool<TInput, TOutput, TName>\n}\n\n/**\n * Create an isomorphic tool definition that can be used directly or instantiated for server/client\n *\n * The definition contains all tool metadata (name, description, schemas) and can be:\n * 1. Used directly in chat() on the server (as a tool definition without execute)\n * 2. Instantiated as a server tool with .server()\n * 3. Instantiated as a client tool with .client()\n *\n * Supports any Standard JSON Schema compliant library (Zod v4+, ArkType, Valibot, etc.)\n * or plain JSON Schema objects.\n *\n * @example\n * ```typescript\n * import { toolDefinition } from '@tanstack/ai';\n * import { z } from 'zod';\n *\n * // Using Zod (natively supports Standard JSON Schema)\n * const addToCartTool = toolDefinition({\n * name: 'addToCart',\n * description: 'Add a guitar to the shopping cart (requires approval)',\n * needsApproval: true,\n * inputSchema: z.object({\n * guitarId: z.string(),\n * quantity: z.number(),\n * }),\n * outputSchema: z.object({\n * success: z.boolean(),\n * cartId: z.string(),\n * totalItems: z.number(),\n * }),\n * });\n *\n * // Use directly in chat (server-side, no execute function)\n * chat({\n * tools: [addToCartTool],\n * // ...\n * });\n *\n * // Or create server-side implementation\n * const addToCartServer = addToCartTool.server(async (args) => {\n * // args is typed as { guitarId: string; quantity: number }\n * return {\n * success: true,\n * cartId: 'CART_' + Date.now(),\n * totalItems: args.quantity,\n * };\n * });\n *\n * // Or create client-side implementation\n * const addToCartClient = addToCartTool.client(async (args) => {\n * // Client-specific logic (e.g., localStorage)\n * return { success: true, cartId: 'local', totalItems: 1 };\n * });\n * ```\n */\nexport function toolDefinition<\n TInput extends SchemaInput = SchemaInput,\n TOutput extends SchemaInput = SchemaInput,\n TName extends string = string,\n>(\n config: ToolDefinitionConfig<TInput, TOutput, TName>,\n): ToolDefinition<TInput, TOutput, TName> {\n const definition: ToolDefinition<TInput, TOutput, TName> = {\n __toolSide: 'definition',\n ...config,\n server(\n execute: (\n args: InferSchemaType<TInput>,\n ) => Promise<InferSchemaType<TOutput>> | InferSchemaType<TOutput>,\n ): ServerTool<TInput, TOutput, TName> {\n return {\n __toolSide: 'server',\n ...config,\n execute,\n }\n },\n\n client(\n execute?: (\n args: InferSchemaType<TInput>,\n ) => Promise<InferSchemaType<TOutput>> | InferSchemaType<TOutput>,\n ): ClientTool<TInput, TOutput, TName> {\n return {\n __toolSide: 'client',\n ...config,\n execute,\n }\n },\n }\n\n return definition\n}\n"],"names":[],"mappings":"AAsLO,SAAS,eAKd,QACwC;AACxC,QAAM,aAAqD;AAAA,IACzD,YAAY;AAAA,IACZ,GAAG;AAAA,IACH,OACE,SAGoC;AACpC,aAAO;AAAA,QACL,YAAY;AAAA,QACZ,GAAG;AAAA,QACH;AAAA,MAAA;AAAA,IAEJ;AAAA,IAEA,OACE,SAGoC;AACpC,aAAO;AAAA,QACL,YAAY;AAAA,QACZ,GAAG;AAAA,QACH;AAAA,MAAA;AAAA,IAEJ;AAAA,EAAA;AAGF,SAAO;AACT;"}
@@ -7,7 +7,7 @@ export { createSpeechOptions } from './activities/generateSpeech/index.js';
7
7
  export { createTranscriptionOptions } from './activities/generateTranscription/index.js';
8
8
  export type { AIAdapter, ImageAdapter, AnyImageAdapter, TextAdapter, AnyTextAdapter, AnySummarizeAdapter, SummarizeAdapter, AnyTTSAdapter, TTSAdapter, AnyTranscriptionAdapter, TranscriptionAdapter, AnyVideoAdapter, VideoAdapter, } from './activities/index.js';
9
9
  export { toolDefinition, type ToolDefinition, type ToolDefinitionInstance, type ToolDefinitionConfig, type ServerTool, type ClientTool, type AnyClientTool, type InferToolName, type InferToolInput, type InferToolOutput, } from './activities/chat/tools/tool-definition.js';
10
- export { convertZodToJsonSchema } from './activities/chat/tools/zod-converter.js';
10
+ export { convertSchemaToJsonSchema } from './activities/chat/tools/schema-converter.js';
11
11
  export { streamToText, toServerSentEventsStream, toStreamResponse, toHttpStream, } from './stream-to-response.js';
12
12
  export { ToolCallManager } from './activities/chat/tools/tool-calls.js';
13
13
  export { maxIterations, untilFinishReason, combineStrategies, } from './activities/chat/agent-loop-strategies.js';
package/dist/esm/index.js CHANGED
@@ -5,7 +5,7 @@ import { createVideoOptions, generateVideo, getVideoJobStatus } from "./activiti
5
5
  import { createSpeechOptions, generateSpeech } from "./activities/generateSpeech/index.js";
6
6
  import { createTranscriptionOptions, generateTranscription } from "./activities/generateTranscription/index.js";
7
7
  import { toolDefinition } from "./activities/chat/tools/tool-definition.js";
8
- import { convertZodToJsonSchema } from "./activities/chat/tools/zod-converter.js";
8
+ import { convertSchemaToJsonSchema } from "./activities/chat/tools/schema-converter.js";
9
9
  import { streamToText, toHttpStream, toServerSentEventsStream, toStreamResponse } from "./stream-to-response.js";
10
10
  import { ToolCallManager } from "./activities/chat/tools/tool-calls.js";
11
11
  import { combineStrategies, maxIterations, untilFinishReason } from "./activities/chat/agent-loop-strategies.js";
@@ -27,7 +27,7 @@ export {
27
27
  chat,
28
28
  combineStrategies,
29
29
  convertMessagesToModelMessages,
30
- convertZodToJsonSchema,
30
+ convertSchemaToJsonSchema,
31
31
  createChatOptions,
32
32
  createImageOptions,
33
33
  createReplayStream,
@@ -1,4 +1,4 @@
1
- import { z } from 'zod';
1
+ import { StandardJSONSchemaV1 } from '@standard-schema/spec';
2
2
  /**
3
3
  * Tool call states - track the lifecycle of a tool call
4
4
  */
@@ -9,17 +9,17 @@ export type ToolCallState = 'awaiting-input' | 'input-streaming' | 'input-comple
9
9
  export type ToolResultState = 'streaming' | 'complete' | 'error';
10
10
  /**
11
11
  * JSON Schema type for defining tool input/output schemas as raw JSON Schema objects.
12
- * This allows tools to be defined without Zod when you have JSON Schema definitions available.
12
+ * This allows tools to be defined without schema libraries when you have JSON Schema definitions available.
13
13
  */
14
14
  export interface JSONSchema {
15
15
  type?: string | Array<string>;
16
16
  properties?: Record<string, JSONSchema>;
17
17
  items?: JSONSchema | Array<JSONSchema>;
18
18
  required?: Array<string>;
19
- enum?: Array<any>;
20
- const?: any;
19
+ enum?: Array<unknown>;
20
+ const?: unknown;
21
21
  description?: string;
22
- default?: any;
22
+ default?: unknown;
23
23
  $ref?: string;
24
24
  $defs?: Record<string, JSONSchema>;
25
25
  definitions?: Record<string, JSONSchema>;
@@ -48,19 +48,26 @@ export interface JSONSchema {
48
48
  minProperties?: number;
49
49
  maxProperties?: number;
50
50
  title?: string;
51
- examples?: Array<any>;
52
- [key: string]: any;
51
+ examples?: Array<unknown>;
52
+ [key: string]: unknown;
53
53
  }
54
54
  /**
55
- * Union type for schema input - can be either a Zod schema or a JSONSchema object.
55
+ * Union type for schema input - can be any Standard JSON Schema compliant schema or a plain JSONSchema object.
56
+ *
57
+ * Standard JSON Schema compliant libraries include:
58
+ * - Zod v4.2+ (natively supports StandardJSONSchemaV1)
59
+ * - ArkType v2.1.28+ (natively supports StandardJSONSchemaV1)
60
+ * - Valibot v1.2+ (via `toStandardJsonSchema()` from `@valibot/to-json-schema`)
61
+ *
62
+ * @see https://standardschema.dev/json-schema
56
63
  */
57
- export type SchemaInput = z.ZodType | JSONSchema;
64
+ export type SchemaInput = StandardJSONSchemaV1<any, any> | JSONSchema;
58
65
  /**
59
66
  * Infer the TypeScript type from a schema.
60
- * For Zod schemas, uses z.infer to get the proper type.
61
- * For JSONSchema, returns `any` since we can't infer types from JSON Schema at compile time.
67
+ * For Standard JSON Schema compliant schemas, extracts the input type.
68
+ * For plain JSONSchema, returns `any` since we can't infer types from JSON Schema at compile time.
62
69
  */
63
- export type InferSchemaType<T> = T extends z.ZodType ? z.infer<T> : any;
70
+ export type InferSchemaType<T> = T extends StandardJSONSchemaV1<infer TInput, unknown> ? TInput : unknown;
64
71
  export interface ToolCall {
65
72
  id: string;
66
73
  type: 'function';
@@ -234,12 +241,14 @@ export type ConstrainedModelMessage<TInputModalitiesTypes extends InputModalitie
234
241
  * Tools allow the model to interact with external systems, APIs, or perform computations.
235
242
  * The model will decide when to call tools based on the user's request and the tool descriptions.
236
243
  *
237
- * Tools can use either Zod schemas or JSON Schema objects for runtime validation and type safety.
244
+ * Tools can use any Standard JSON Schema compliant library (Zod, ArkType, Valibot, etc.)
245
+ * or plain JSON Schema objects for runtime validation and type safety.
238
246
  *
239
247
  * @see https://platform.openai.com/docs/guides/function-calling
240
248
  * @see https://docs.anthropic.com/claude/docs/tool-use
249
+ * @see https://standardschema.dev/json-schema
241
250
  */
242
- export interface Tool<TInput extends SchemaInput = z.ZodType, TOutput extends SchemaInput = z.ZodType, TName extends string = string> {
251
+ export interface Tool<TInput extends SchemaInput = SchemaInput, TOutput extends SchemaInput = SchemaInput, TName extends string = string> {
243
252
  /**
244
253
  * Unique name of the tool (used by the model to call it).
245
254
  *
@@ -261,16 +270,16 @@ export interface Tool<TInput extends SchemaInput = z.ZodType, TOutput extends Sc
261
270
  /**
262
271
  * Schema describing the tool's input parameters.
263
272
  *
264
- * Can be either a Zod schema or a JSON Schema object.
273
+ * Can be any Standard JSON Schema compliant schema (Zod, ArkType, Valibot, etc.) or a plain JSON Schema object.
265
274
  * Defines the structure and types of arguments the tool accepts.
266
275
  * The model will generate arguments matching this schema.
267
- * Zod schemas are converted to JSON Schema for LLM providers.
276
+ * Standard JSON Schema compliant schemas are converted to JSON Schema for LLM providers.
268
277
  *
269
- * @see https://zod.dev/
278
+ * @see https://standardschema.dev/json-schema
270
279
  * @see https://json-schema.org/
271
280
  *
272
281
  * @example
273
- * // Using Zod schema
282
+ * // Using Zod v4+ schema (natively supports Standard JSON Schema)
274
283
  * import { z } from 'zod';
275
284
  * z.object({
276
285
  * location: z.string().describe("City name or coordinates"),
@@ -278,7 +287,15 @@ export interface Tool<TInput extends SchemaInput = z.ZodType, TOutput extends Sc
278
287
  * })
279
288
  *
280
289
  * @example
281
- * // Using JSON Schema
290
+ * // Using ArkType (natively supports Standard JSON Schema)
291
+ * import { type } from 'arktype';
292
+ * type({
293
+ * location: 'string',
294
+ * unit: "'celsius' | 'fahrenheit'"
295
+ * })
296
+ *
297
+ * @example
298
+ * // Using plain JSON Schema
282
299
  * {
283
300
  * type: 'object',
284
301
  * properties: {
@@ -292,15 +309,16 @@ export interface Tool<TInput extends SchemaInput = z.ZodType, TOutput extends Sc
292
309
  /**
293
310
  * Optional schema for validating tool output.
294
311
  *
295
- * Can be either a Zod schema or a JSON Schema object.
296
- * If provided with a Zod schema, tool results will be validated against this schema before
297
- * being sent back to the model. This catches bugs in tool implementations
298
- * and ensures consistent output formatting.
312
+ * Can be any Standard JSON Schema compliant schema or a plain JSON Schema object.
313
+ * If provided with a Standard Schema compliant schema, tool results will be validated
314
+ * against this schema before being sent back to the model. This catches bugs in tool
315
+ * implementations and ensures consistent output formatting.
299
316
  *
300
317
  * Note: This is client-side validation only - not sent to LLM providers.
301
- * Note: JSON Schema output validation is not performed at runtime.
318
+ * Note: Plain JSON Schema output validation is not performed at runtime.
302
319
  *
303
320
  * @example
321
+ * // Using Zod
304
322
  * z.object({
305
323
  * temperature: z.number(),
306
324
  * conditions: z.string(),
@@ -502,12 +520,13 @@ export interface TextOptions<TProviderOptionsSuperset extends Record<string, any
502
520
  modelOptions?: TProviderOptionsForModel;
503
521
  request?: Request | RequestInit;
504
522
  /**
505
- * Zod schema for structured output.
523
+ * Schema for structured output.
506
524
  * When provided, the adapter should use the provider's native structured output API
507
525
  * to ensure the response conforms to this schema.
508
526
  * The schema will be converted to JSON Schema format before being sent to the provider.
527
+ * Supports any Standard JSON Schema compliant library (Zod, ArkType, Valibot, etc.).
509
528
  */
510
- outputSchema?: z.ZodType;
529
+ outputSchema?: SchemaInput;
511
530
  /**
512
531
  * Conversation ID for correlating client and server-side devtools events.
513
532
  * When provided, server-side events will be linked to the client conversation in devtools.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/ai",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Core TanStack AI library - Open source AI SDK",
5
5
  "author": "Tanner Linsley",
6
6
  "license": "MIT",
@@ -46,13 +46,10 @@
46
46
  "@tanstack/devtools-event-client": "^0.4.0",
47
47
  "partial-json": "^0.1.7"
48
48
  },
49
- "peerDependencies": {
50
- "@alcyone-labs/zod-to-json-schema": "^4.0.0",
51
- "zod": "^3.0.0 || ^4.0.0"
52
- },
53
49
  "devDependencies": {
50
+ "@standard-schema/spec": "^1.1.0",
54
51
  "@vitest/coverage-v8": "4.0.14",
55
- "zod": "^4.1.13"
52
+ "zod": "^4.2.0"
56
53
  },
57
54
  "scripts": {
58
55
  "build": "vite build",