import { z } from "zod"; import { withAuth } from "../../auth/index.js"; import { handleToolError, validateRequired } from "../helpers/errorHandler.js"; import { withAuthParams } from "../helpers/authSchema.js"; import { pythonPost } from "../helpers/pythonServerClient.js"; import { getCurrentProjectInfo } from "../files/helpers.js"; // Antes esta tool llamaba a `action_ws=setStaticVars`, que hacia un // file_put_contents del builder.json ENTERO en la web para cambiar una sola // clave. Eso se saltaba el bloqueo de escritura de builder.json y, si caia una // compilacion entre su lectura y su escritura, devolvia el mapeo var->columna // anterior encima del recien generado (contenido rotado en todas las paginas // que usan el modulo). Ahora delega en el endpoint quirurgico de Forge, que // escribe SOLO las claves de su allowlist. export function registerSetModuleExampleDataTool(server) { server.tool( "set_module_example_data", `Define datos de ejemplo para el preview del módulo en el editor. Antes de llamar, lee el builder.json del módulo (con 'acai-view') o usa 'get_module_config_vars' para conocer las variables exactas. Rellena TODAS las variables del schema. Reglas críticas: - Uploads SIEMPRE como [{ urlPath: "..." }] (nunca strings ni objetos sueltos). - 'multiv2' como array con al menos 2 items para que el preview se vea representativo. - Los nombres de variables se derivan de 'data-field-label' (minúsculas, sin espacios ni acentos). - Para URLs de imagen usa 'generate_image' o un placeholder (e.g. https://placehold.co/800x600). Si dudas del formato exacto, lee 'read_doc({ name: "01-builder-fields" })'.`, withAuthParams({ moduleId: z.string().describe("ID del módulo"), moduleSchema: z.object({}).passthrough().describe("Schema completo del módulo (del builder.json o de 'get_module_config_vars')"), exampleData: z.object({}).passthrough().describe("Datos de ejemplo para TODAS las variables del schema. La estructura debe coincidir exactamente."), }), { readOnlyHint: false, destructiveHint: false }, withAuth(async ({ moduleId, moduleSchema, exampleData }, extra) => { try { // Validate required parameters const validationError = validateRequired({ moduleId, exampleData }, ['moduleId', 'exampleData'], 'set_module_example_data'); if (validationError) return validationError; // Validate that all schema variables are present in exampleData if (moduleSchema && moduleSchema.codeVars) { const schemaVars = Object.keys(moduleSchema.codeVars); const dataVars = Object.keys(exampleData); const missingVars = schemaVars.filter(v => !dataVars.includes(v)); if (missingVars.length > 0) { console.warn(`[set_module_example_data] WARNING: Missing variables in exampleData: ${missingVars.join(', ')}`); } // Check for upload fields that are not arrays for (const [varName, varInfo] of Object.entries(moduleSchema.codeVars)) { if (varInfo.type === 'upload' && exampleData[varName]) { if (!Array.isArray(exampleData[varName])) { console.error(`[set_module_example_data] ERROR: Upload field '${varName}' is not an array! Current value: ${JSON.stringify(exampleData[varName])}`); console.error(`[set_module_example_data] Upload fields MUST be arrays with urlPath objects: [{"urlPath": "..."}]`); } else if (exampleData[varName].length > 0 && !exampleData[varName][0].urlPath) { console.error(`[set_module_example_data] ERROR: Upload field '${varName}' items missing 'urlPath' property!`); } } } } console.error(`[set_module_example_data] Module ID: ${moduleId}, vars: ${Object.keys(exampleData).length}`); const { projectSlug } = getCurrentProjectInfo(); const result = await pythonPost("/api/modules/update-metadata", { project: projectSlug, module: moduleId, staticVars: exampleData, }); if (!result?.success) { return { content: [{ type: "text", text: JSON.stringify({ success: false, error: result?.error || "Could not set module example data", }), }], isError: true, }; } return { content: [{ type: "text", text: JSON.stringify({ success: true, message: `Example data set successfully for module '${moduleId}'`, moduleId: result.module || moduleId, dataCount: Object.keys(exampleData).length, schemaVarsCount: moduleSchema?.codeVars ? Object.keys(moduleSchema.codeVars).length : 0, }, null, 2) }], }; } catch (error) { return handleToolError(error, 'set_module_example_data', { moduleId }); } }) ); }