refactor: set_module_example_data escribe via el server Python
La tool llamaba a `action_ws=setStaticVars`, que hace un file_put_contents del builder.json ENTERO en la web para cambiar una sola clave. Eso se saltaba las dos garantias que protegen ese fichero: el bloqueo de escritura de la API de ficheros (BLOCKED_GENERATED_FILENAMES en handlers/files.py) y la allowlist de /api/modules/update-metadata. El riesgo no era teorico. El builder.json es la unica memoria de que variable vive en que columna de builder_custom: si una compilacion caia entre la lectura y la escritura de setStaticVars, esta devolvia el mapeo var->columna anterior encima del recien generado y el contenido guardado quedaba colgado de la variable equivocada en TODAS las paginas que usan el modulo. Ahora delega en /api/modules/update-metadata, que ya es la via quirurgica para la metadata y acepta staticVars en su allowlist (objeto, <=64KB, <=200 claves). Se aprovecha para quitar el volcado del schema y del payload completos por consola en cada llamada. Companion en el repo de Forge: compiler.js reenvia staticVars en cada compilacion. Antes no lo mandaba, asi que el CMS lo tiraba al regenerar el builder.json — solo 5 de 4870 modulos lo conservaban. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,17 @@
|
|||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { withAuth, getSessionCredentials, getApiClient, getCommonParams } from "../../auth/index.js";
|
import { withAuth } from "../../auth/index.js";
|
||||||
import { handleToolError, validateRequired, handleApiResponse } from "../helpers/errorHandler.js";
|
import { handleToolError, validateRequired } from "../helpers/errorHandler.js";
|
||||||
import { withAuthParams } from "../helpers/authSchema.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) {
|
export function registerSetModuleExampleDataTool(server) {
|
||||||
server.tool(
|
server.tool(
|
||||||
@@ -50,42 +60,36 @@ Si dudas del formato exacto, lee 'read_doc({ name: "01-builder-fields" })'.`,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const credentials = await getSessionCredentials(extra.sessionId);
|
console.error(`[set_module_example_data] Module ID: ${moduleId}, vars: ${Object.keys(exampleData).length}`);
|
||||||
const client = await getApiClient(extra.sessionId);
|
|
||||||
|
|
||||||
// Log data for debugging
|
const { projectSlug } = getCurrentProjectInfo();
|
||||||
console.error(`[set_module_example_data] Module ID: ${moduleId}`);
|
const result = await pythonPost("/api/modules/update-metadata", {
|
||||||
console.error(`[set_module_example_data] Module Schema:`, JSON.stringify(moduleSchema, null, 2));
|
project: projectSlug,
|
||||||
console.error(`[set_module_example_data] Example Data:`, JSON.stringify(exampleData, null, 2));
|
module: moduleId,
|
||||||
|
|
||||||
// Prepare payload for setStaticVars action
|
|
||||||
const payload = await getCommonParams(extra.sessionId, {
|
|
||||||
action_ws: "setStaticVars",
|
|
||||||
moduleId: moduleId,
|
|
||||||
staticVars: exampleData,
|
staticVars: exampleData,
|
||||||
schema: moduleSchema
|
|
||||||
});
|
});
|
||||||
|
|
||||||
console.error(`[set_module_example_data] Full Payload:`, JSON.stringify(payload, null, 2));
|
if (!result?.success) {
|
||||||
|
return {
|
||||||
// Send to viewer_functions
|
content: [{
|
||||||
const response = await client.post("/cms/lib/viewer_functions.php", payload);
|
type: "text",
|
||||||
|
text: JSON.stringify({
|
||||||
console.error(`[set_module_example_data] Response:`, JSON.stringify(response.data, null, 2));
|
success: false,
|
||||||
|
error: result?.error || "Could not set module example data",
|
||||||
// Check for API errors in response
|
}),
|
||||||
const apiError = handleApiResponse(response.data, 'set_module_example_data');
|
}],
|
||||||
if (apiError) return apiError;
|
isError: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
content: [{
|
content: [{
|
||||||
type: "text", text: JSON.stringify({
|
type: "text", text: JSON.stringify({
|
||||||
success: true,
|
success: true,
|
||||||
message: `Example data set successfully for module '${moduleId}'`,
|
message: `Example data set successfully for module '${moduleId}'`,
|
||||||
moduleId: moduleId,
|
moduleId: result.module || moduleId,
|
||||||
dataCount: Object.keys(exampleData).length,
|
dataCount: Object.keys(exampleData).length,
|
||||||
schemaVarsCount: moduleSchema?.codeVars ? Object.keys(moduleSchema.codeVars).length : 0,
|
schemaVarsCount: moduleSchema?.codeVars ? Object.keys(moduleSchema.codeVars).length : 0,
|
||||||
response: response.data
|
|
||||||
}, null, 2)
|
}, null, 2)
|
||||||
}],
|
}],
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user