import { z } from "zod" import type { DataSource } from "../types" import type { ToolDef } from "./data" import { zodToJsonSchema } from "./data" const listThemesSchema = z.object({}) const setThemeSchema = z.object({ themeId: z.string().describe("The theme ID to activate"), }) const generateThemeSchema = z.object({ name: z.string().describe("Theme display name"), description: z.string().describe("Brief theme description"), light: z .record(z.string(), z.string()) .describe( "Light mode color map with all 32 ThemeColorKey entries" ), dark: z .record(z.string(), z.string()) .describe( "Dark mode color map with all 32 ThemeColorKey entries" ), fonts: z .object({ sans: z.string(), serif: z.string(), mono: z.string(), }) .describe("CSS font-family strings"), googleFonts: z .array(z.string()) .optional() .describe("Google Font names to load (case-sensitive)"), radius: z .string() .optional() .describe("Border radius (e.g. '0.5rem')"), spacing: z .string() .optional() .describe("Base spacing (e.g. '0.25rem')"), }) const editThemeSchema = z.object({ themeId: z .string() .describe("ID of existing custom theme to edit"), name: z.string().optional().describe("New display name"), description: z .string() .optional() .describe("New description"), light: z .record(z.string(), z.string()) .optional() .describe("Partial light color overrides (only changed keys)"), dark: z .record(z.string(), z.string()) .optional() .describe("Partial dark color overrides (only changed keys)"), fonts: z .object({ sans: z.string().optional(), serif: z.string().optional(), mono: z.string().optional(), }) .optional() .describe("Partial font overrides"), googleFonts: z .array(z.string()) .optional() .describe("Replace Google Font list"), radius: z .string() .optional() .describe("New border radius"), spacing: z .string() .optional() .describe("New base spacing"), }) export function themeTools(dataSource: DataSource): ToolDef[] { return [ { name: "listThemes", description: "List available visual themes (presets + user custom " + "themes).", input_schema: zodToJsonSchema(listThemesSchema), run: async (): Promise => { const result = await dataSource.fetch( "/api/compass/themes/list" ) return JSON.stringify(result) }, }, { name: "setTheme", description: "Switch the user's visual theme. Use a preset ID " + "(native-compass, corpo, notebook, doom-64, " + "bubblegum, developers-choice, anslopics-clood, " + "violet-bloom, soy, mocha) or a custom theme UUID.", input_schema: zodToJsonSchema(setThemeSchema), run: async (input: unknown): Promise => { const args = setThemeSchema.parse(input) const result = await dataSource.fetch( "/api/compass/themes/set", args ) return JSON.stringify(result) }, }, { name: "generateTheme", description: "Generate and save a custom visual theme. Provide " + "complete light and dark color maps (all 32 keys), " + "fonts, optional Google Font names, and design tokens. " + "All colors must be in oklch() format.", input_schema: zodToJsonSchema(generateThemeSchema), run: async (input: unknown): Promise => { const args = generateThemeSchema.parse(input) const result = await dataSource.fetch( "/api/compass/themes/generate", args ) return JSON.stringify(result) }, }, { name: "editTheme", description: "Edit an existing custom theme. Provide the theme ID " + "and only the properties you want to change. " + "Unspecified properties are preserved from the existing " + "theme. Only works on custom themes (not presets).", input_schema: zodToJsonSchema(editThemeSchema), run: async (input: unknown): Promise => { const args = editThemeSchema.parse(input) const result = await dataSource.fetch( "/api/compass/themes/edit", args ) return JSON.stringify(result) }, }, ] }