Vercel ai gateway (#10)

* feat: use vercel ai gateway

* fix: correct response handling

* ci: add pipeline
This commit is contained in:
2025-10-11 15:07:54 +02:00
committed by GitHub
parent 99a04d2a3e
commit 017e538396
11 changed files with 1116 additions and 1003 deletions

66
utils/aiGatewayClient.ts Normal file
View File

@@ -0,0 +1,66 @@
import 'dotenv/config';
import { generateText, tool, jsonSchema } from 'ai';
import type { JSONSchema7 } from 'json-schema';
export interface BaseTool {
readonly name: string;
readonly input_schema: {
readonly type: 'object';
readonly properties: Record<string, unknown>;
readonly required?: readonly string[];
readonly description?: string;
};
}
export interface ToolUseBlock {
type: 'tool_use';
id: string;
name: string;
input: Record<string, unknown>;
}
export async function makeRequest<T extends BaseTool>(
prompt: string,
toolDef: T
): Promise<Record<string, unknown>> {
try {
const { steps } = await generateText({
model: 'anthropic/claude-sonnet-4.5',
temperature: 1,
tools: {
[toolDef.name]: tool({
description: toolDef.input_schema.description || '',
inputSchema: jsonSchema(toolDef.input_schema as JSONSchema7),
execute: async args => args
})
},
toolChoice: {
type: 'tool',
toolName: toolDef.name
},
prompt
});
const toolCalls = steps.flatMap(step => step.toolCalls);
if (!toolCalls || toolCalls.length === 0) {
throw new Error('No tool calls found in response');
}
const typedCall = toolCalls[0] as unknown as {
toolName: string;
input: Record<string, unknown>;
};
if (typedCall.toolName !== toolDef.name) {
throw new Error(
`Expected tool ${toolDef.name} but got ${typedCall.toolName}`
);
}
return typedCall.input;
} catch (error) {
console.error('Error making request:', error);
throw Error('Vercel AI Gateway client error.');
}
}