Files
2025-11-30 08:25:37 +08:00

328 lines
10 KiB
TypeScript

/**
* Common Zod Schemas for Tool Calling
*
* Reusable schemas for common tools across any framework.
* These schemas provide runtime validation and type safety.
*
* Usage:
* import { webSearchTool, createOrderTool } from "./tool-schemas";
* import zodToJsonSchema from "zod-to-json-schema";
*
* const tools = [webSearchTool, createOrderTool];
*
* await client.beta.chat.completions.runTools({
* model: "c1/openai/gpt-5/v-20250930",
* messages: [...],
* tools,
* });
*/
import { z } from "zod";
import zodToJsonSchema from "zod-to-json-schema";
// ============================================================================
// Web Search Tool
// ============================================================================
export const webSearchSchema = z.object({
query: z.string().min(1).describe("The search query"),
max_results: z
.number()
.int()
.min(1)
.max(10)
.default(5)
.describe("Maximum number of results to return (1-10)"),
include_answer: z
.boolean()
.default(true)
.describe("Include AI-generated answer summary"),
});
export type WebSearchArgs = z.infer<typeof webSearchSchema>;
export const webSearchTool = {
type: "function" as const,
function: {
name: "web_search",
description:
"Search the web for current information using a search API. Use this for recent events, news, or information that may have changed recently.",
parameters: zodToJsonSchema(webSearchSchema),
},
};
// ============================================================================
// Product/Inventory Tools
// ============================================================================
export const productLookupSchema = z.object({
product_type: z
.enum(["gloves", "hat", "scarf", "all"])
.optional()
.describe("Type of product to lookup, or 'all' for entire inventory"),
filter: z
.object({
min_price: z.number().optional(),
max_price: z.number().optional(),
in_stock_only: z.boolean().default(true),
})
.optional()
.describe("Optional filters for product search"),
});
export type ProductLookupArgs = z.infer<typeof productLookupSchema>;
export const productLookupTool = {
type: "function" as const,
function: {
name: "lookup_product",
description:
"Look up products in the inventory database. Returns product details including price, availability, and specifications.",
parameters: zodToJsonSchema(productLookupSchema),
},
};
// ============================================================================
// Order Creation Tool
// ============================================================================
const orderItemSchema = z.discriminatedUnion("type", [
z.object({
type: z.literal("gloves"),
size: z.enum(["XS", "S", "M", "L", "XL", "XXL"]),
color: z.string().min(1),
quantity: z.number().int().min(1).max(100),
}),
z.object({
type: z.literal("hat"),
style: z.enum(["beanie", "baseball", "fedora", "bucket"]),
color: z.string().min(1),
quantity: z.number().int().min(1).max(100),
}),
z.object({
type: z.literal("scarf"),
length: z.enum(["short", "medium", "long"]),
material: z.enum(["wool", "cotton", "silk", "cashmere"]),
quantity: z.number().int().min(1).max(100),
}),
]);
export const createOrderSchema = z.object({
customer_email: z
.string()
.email()
.describe("Customer's email address for order confirmation"),
items: z
.array(orderItemSchema)
.min(1)
.max(20)
.describe("Array of items to include in the order (max 20)"),
shipping_address: z.object({
street: z.string().min(1),
city: z.string().min(1),
state: z.string().length(2), // US state code
zip: z.string().regex(/^\d{5}(-\d{4})?$/), // ZIP or ZIP+4
country: z.string().default("US"),
}),
notes: z.string().optional().describe("Optional order notes or instructions"),
});
export type CreateOrderArgs = z.infer<typeof createOrderSchema>;
export type OrderItem = z.infer<typeof orderItemSchema>;
export const createOrderTool = {
type: "function" as const,
function: {
name: "create_order",
description:
"Create a new product order with customer information, items, and shipping address. Returns order ID and confirmation details.",
parameters: zodToJsonSchema(createOrderSchema),
},
};
// ============================================================================
// Database Query Tool
// ============================================================================
export const databaseQuerySchema = z.object({
query_type: z
.enum(["select", "aggregate", "search"])
.describe("Type of database query to perform"),
table: z
.string()
.describe("Database table name (e.g., 'users', 'products', 'orders')"),
filters: z
.record(z.any())
.optional()
.describe("Filter conditions as key-value pairs"),
limit: z.number().int().min(1).max(100).default(20).describe("Result limit"),
});
export type DatabaseQueryArgs = z.infer<typeof databaseQuerySchema>;
export const databaseQueryTool = {
type: "function" as const,
function: {
name: "query_database",
description:
"Query the database for information. Supports select, aggregate, and search operations on various tables.",
parameters: zodToJsonSchema(databaseQuerySchema),
},
};
// ============================================================================
// Data Visualization Tool
// ============================================================================
export const createVisualizationSchema = z.object({
chart_type: z
.enum(["bar", "line", "pie", "scatter", "area"])
.describe("Type of chart to create"),
data: z
.array(
z.object({
label: z.string(),
value: z.number(),
})
)
.min(1)
.describe("Data points for the visualization"),
title: z.string().min(1).describe("Chart title"),
x_label: z.string().optional().describe("X-axis label"),
y_label: z.string().optional().describe("Y-axis label"),
});
export type CreateVisualizationArgs = z.infer<typeof createVisualizationSchema>;
export const createVisualizationTool = {
type: "function" as const,
function: {
name: "create_visualization",
description:
"Create a data visualization chart. Returns chart configuration that will be rendered in the UI.",
parameters: zodToJsonSchema(createVisualizationSchema),
},
};
// ============================================================================
// Email Tool
// ============================================================================
export const sendEmailSchema = z.object({
to: z.string().email().describe("Recipient email address"),
subject: z.string().min(1).max(200).describe("Email subject line"),
body: z.string().min(1).describe("Email body content (supports HTML)"),
cc: z.array(z.string().email()).optional().describe("CC recipients"),
bcc: z.array(z.string().email()).optional().describe("BCC recipients"),
});
export type SendEmailArgs = z.infer<typeof sendEmailSchema>;
export const sendEmailTool = {
type: "function" as const,
function: {
name: "send_email",
description:
"Send an email to one or more recipients. Use this to send notifications, confirmations, or responses to customers.",
parameters: zodToJsonSchema(sendEmailSchema),
},
};
// ============================================================================
// Calendar/Scheduling Tool
// ============================================================================
export const scheduleEventSchema = z.object({
title: z.string().min(1).describe("Event title"),
start_time: z.string().datetime().describe("Event start time (ISO 8601)"),
end_time: z.string().datetime().describe("Event end time (ISO 8601)"),
description: z.string().optional().describe("Event description"),
attendees: z
.array(z.string().email())
.optional()
.describe("List of attendee email addresses"),
location: z.string().optional().describe("Event location or meeting link"),
reminder_minutes: z
.number()
.int()
.min(0)
.default(15)
.describe("Minutes before event to send reminder"),
});
export type ScheduleEventArgs = z.infer<typeof scheduleEventSchema>;
export const scheduleEventTool = {
type: "function" as const,
function: {
name: "schedule_event",
description:
"Schedule a calendar event with attendees, location, and reminders.",
parameters: zodToJsonSchema(scheduleEventSchema),
},
};
// ============================================================================
// File Upload Tool
// ============================================================================
export const uploadFileSchema = z.object({
file_name: z.string().min(1).describe("Name of the file"),
file_type: z
.string()
.describe("MIME type (e.g., 'image/png', 'application/pdf')"),
file_size: z.number().int().min(1).describe("File size in bytes"),
description: z.string().optional().describe("File description or metadata"),
});
export type UploadFileArgs = z.infer<typeof uploadFileSchema>;
export const uploadFileTool = {
type: "function" as const,
function: {
name: "upload_file",
description:
"Upload a file to cloud storage. Returns storage URL and file metadata.",
parameters: zodToJsonSchema(uploadFileSchema),
},
};
// ============================================================================
// Export All Tools
// ============================================================================
export const allTools = [
webSearchTool,
productLookupTool,
createOrderTool,
databaseQueryTool,
createVisualizationTool,
sendEmailTool,
scheduleEventTool,
uploadFileTool,
];
/**
* Helper to get tools by category
*/
export function getToolsByCategory(category: "ecommerce" | "data" | "communication" | "all") {
const categories = {
ecommerce: [productLookupTool, createOrderTool],
data: [databaseQueryTool, createVisualizationTool],
communication: [sendEmailTool, scheduleEventTool],
all: allTools,
};
return categories[category];
}
/**
* Validation helper
*/
export function validateToolArgs<T extends z.ZodType>(
schema: T,
args: unknown
): z.infer<T> {
return schema.parse(args);
}