01-builder-fields.md documentaba `checkbox` y `colorpicker` como tipos validos —y usaba colorpicker en un ejemplo— pero el parser no los reconocia. Verificado contra el parser real: ambos salian con `type` indefinido, y en ese caso funciones.php hace `continue` y **descarta la variable en silencio**. O sea que el doc mandaba al agente a escribir campos que nunca llegaban al builder.json. En cambio no documentaba `colors`, `corners` ni `ratio`, que si funcionan. - Se documentan los cuatro tipos reales, con el formato de valor de cada uno. `colors` es una paleta de N colores en una sola variable (JSON de pares nombre/color, nombres declarados en data-field-colors); `colorpicker` es un color suelto (hex plano). - `colorpicker` pasa a existir de verdad: se anade al parser y al compilador (companion en el plugin maestro). Forge ya tenia widget para ambos — ColorsField y ColorField— asi que solo faltaba la pieza del parser. - `checkbox` se marca explicitamente como inexistente, con la alternativa (`list` de dos opciones). - set_module_example_data documenta el formato de ambos, que el agente no podia adivinar. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
104 lines
5.8 KiB
JavaScript
104 lines
5.8 KiB
JavaScript
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).
|
|
- 'colors' como STRING con un JSON de pares nombre/color, usando los nombres declarados en data-field-colors: "{\\"fondo\\":\\"#ffffff\\",\\"titulo\\":\\"#111111\\"}". Cada color admite hex o linear-gradient(...).
|
|
- 'colorpicker' como un hex plano ("#ff0000"), no como objeto.
|
|
- '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 });
|
|
}
|
|
})
|
|
);
|
|
}
|