import { z } from "zod"; import type { db as prodDb } from "../../../db/index.ts"; import { createItem, deleteItem, getAllItems, getItemById, updateItem, } from "../../services/item.service.ts"; type Db = typeof prodDb; interface ToolResult { content: Array<{ type: "text"; text: string }>; } function textResult(data: unknown): ToolResult { return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] }; } function errorResult(message: string): ToolResult { return { content: [{ type: "text", text: JSON.stringify({ error: message }) }], }; } export const itemToolDefinitions = [ { name: "list_items", description: "List all items in the gear collection, optionally filtered by category.", inputSchema: { categoryId: z.number().optional().describe("Filter items by category ID"), }, }, { name: "get_item", description: "Get a single item by its ID, including all details.", inputSchema: { id: z.number().describe("The item ID"), }, }, { name: "create_item", description: "Add a new item to the gear collection. Use this for items you've already decided on. For items you're still researching, use create_thread instead.", inputSchema: { name: z.string().describe("Item name"), categoryId: z.number().describe("Category ID"), weightGrams: z.number().optional().describe("Weight in grams"), priceCents: z.number().optional().describe("Price in cents"), notes: z.string().optional().describe("Notes about the item"), productUrl: z.string().optional().describe("URL to the product page"), imageFilename: z .string() .optional() .describe("Filename of an uploaded image"), imageSourceUrl: z .string() .optional() .describe("Original URL the image was fetched from"), }, }, { name: "update_item", description: "Update an existing item's fields.", inputSchema: { id: z.number().describe("The item ID to update"), name: z.string().optional().describe("Item name"), categoryId: z.number().optional().describe("Category ID"), weightGrams: z.number().optional().describe("Weight in grams"), priceCents: z.number().optional().describe("Price in cents"), notes: z.string().optional().describe("Notes about the item"), productUrl: z.string().optional().describe("URL to the product page"), imageFilename: z .string() .optional() .describe("Filename of an uploaded image"), imageSourceUrl: z .string() .optional() .describe("Original URL the image was fetched from"), }, }, { name: "delete_item", description: "Delete an item from the gear collection by ID.", inputSchema: { id: z.number().describe("The item ID to delete"), }, }, ]; export function registerItemTools(db: Db, userId: number) { return { list_items: async (args: { categoryId?: number }): Promise => { try { const items = await getAllItems(db, userId); if (args.categoryId) { return textResult( items.filter((i) => i.categoryId === args.categoryId), ); } return textResult(items); } catch (err) { return errorResult((err as Error).message); } }, get_item: async (args: { id: number }): Promise => { try { const item = await getItemById(db, userId, args.id); if (!item) return errorResult(`Item ${args.id} not found`); return textResult(item); } catch (err) { return errorResult((err as Error).message); } }, create_item: async (args: { name: string; categoryId: number; weightGrams?: number; priceCents?: number; notes?: string; productUrl?: string; imageFilename?: string; imageSourceUrl?: string; }): Promise => { try { const item = await createItem(db, userId, args); return textResult(item); } catch (err) { return errorResult((err as Error).message); } }, update_item: async (args: { id: number; name?: string; categoryId?: number; weightGrams?: number; priceCents?: number; notes?: string; productUrl?: string; imageFilename?: string; imageSourceUrl?: string; }): Promise => { try { const { id, ...data } = args; const item = await updateItem(db, userId, id, data); if (!item) return errorResult(`Item ${id} not found`); return textResult(item); } catch (err) { return errorResult((err as Error).message); } }, delete_item: async (args: { id: number }): Promise => { try { const item = await deleteItem(db, userId, args.id); if (!item) return errorResult(`Item ${args.id} not found`); return textResult({ deleted: true, item }); } catch (err) { return errorResult((err as Error).message); } }, }; }