88 lines
2.1 KiB
TypeScript
88 lines
2.1 KiB
TypeScript
import {
|
|
InvalidToolArgumentsError,
|
|
LanguageModelV1FunctionToolCall,
|
|
NoSuchToolError,
|
|
} from '@ai-sdk/provider';
|
|
import { z } from 'zod';
|
|
import { safeParseJSON } from '../../spec';
|
|
import { ExperimentalTool } from '../tool';
|
|
import { ValueOf } from '../util/value-of';
|
|
|
|
/**
|
|
Typed tool call that is returned by generateText and streamText.
|
|
It contains the tool call ID, the tool name, and the tool arguments.
|
|
*/
|
|
export interface ToolCall<NAME extends string, ARGS> {
|
|
/**
|
|
ID of the tool call. This ID is used to match the tool call with the tool result.
|
|
*/
|
|
toolCallId: string;
|
|
|
|
/**
|
|
Name of the tool that is being called.
|
|
*/
|
|
toolName: NAME;
|
|
|
|
/**
|
|
Arguments of the tool call. This is a JSON-serializable object that matches the tool's input schema.
|
|
*/
|
|
args: ARGS;
|
|
}
|
|
|
|
// transforms the tools into a tool call union
|
|
export type ToToolCall<TOOLS extends Record<string, ExperimentalTool>> =
|
|
ValueOf<{
|
|
[NAME in keyof TOOLS]: {
|
|
type: 'tool-call';
|
|
toolCallId: string;
|
|
toolName: NAME & string;
|
|
args: z.infer<TOOLS[NAME]['parameters']>;
|
|
};
|
|
}>;
|
|
|
|
export type ToToolCallArray<TOOLS extends Record<string, ExperimentalTool>> =
|
|
Array<ToToolCall<TOOLS>>;
|
|
|
|
export function parseToolCall<TOOLS extends Record<string, ExperimentalTool>>({
|
|
toolCall,
|
|
tools,
|
|
}: {
|
|
toolCall: LanguageModelV1FunctionToolCall;
|
|
tools?: TOOLS;
|
|
}): ToToolCall<TOOLS> {
|
|
const toolName = toolCall.toolName as keyof TOOLS & string;
|
|
|
|
if (tools == null) {
|
|
throw new NoSuchToolError({ toolName: toolCall.toolName });
|
|
}
|
|
|
|
const tool = tools[toolName];
|
|
|
|
if (tool == null) {
|
|
throw new NoSuchToolError({
|
|
toolName: toolCall.toolName,
|
|
availableTools: Object.keys(tools),
|
|
});
|
|
}
|
|
|
|
const parseResult = safeParseJSON({
|
|
text: toolCall.args,
|
|
schema: tool.parameters,
|
|
});
|
|
|
|
if (parseResult.success === false) {
|
|
throw new InvalidToolArgumentsError({
|
|
toolName,
|
|
toolArgs: toolCall.args,
|
|
cause: parseResult.error,
|
|
});
|
|
}
|
|
|
|
return {
|
|
type: 'tool-call',
|
|
toolCallId: toolCall.toolCallId,
|
|
toolName,
|
|
args: parseResult.value,
|
|
};
|
|
}
|