toque en imagenes y filtrado en los esquemas
This commit is contained in:
@@ -100,11 +100,11 @@ async function resolveLocalImageAsBase64(imageUrl) {
|
|||||||
export function registerUploadRecordImageTool(server) {
|
export function registerUploadRecordImageTool(server) {
|
||||||
server.tool(
|
server.tool(
|
||||||
"upload_record_image",
|
"upload_record_image",
|
||||||
"Upload an image to a specific record field in Acai CMS. Downloads the image from a URL and uploads it. Table names are WITHOUT the 'cms_' prefix. The recordId is the 'num' primary key, never 'id'. If the URL came from generate_image, prefer uploadUrl (or fullUrl) over dockerUrl in Forge environments.",
|
"Upload an image to a specific record field in Acai CMS. MANDATORY: before calling this tool, you MUST call get_table_schema with minimal=true to find the EXACT upload field name. Look for fields with type='upload'. NEVER guess field names. Table names WITHOUT 'cms_' prefix. recordId is 'num', never 'id'. If the URL came from generate_image, prefer uploadUrl (or fullUrl) over dockerUrl.",
|
||||||
withAuthParams({
|
withAuthParams({
|
||||||
tableName: z.string().describe("Table name without 'cms_' prefix (e.g., 'productos')"),
|
tableName: z.string().describe("Table name without 'cms_' prefix (e.g., 'productos')"),
|
||||||
recordId: z.string().describe("Record 'num' (primary key)"),
|
recordId: z.string().describe("Record 'num' (primary key)"),
|
||||||
fieldName: z.string().describe("Field name (e.g., 'galeria_imagenes')"),
|
fieldName: z.string().describe("EXACT field name from the schema. MUST match a field with type 'upload' from get_table_schema or get_module_config_vars. Do NOT guess."),
|
||||||
imageUrl: z.string().describe("URL of the image to upload"),
|
imageUrl: z.string().describe("URL of the image to upload"),
|
||||||
alt: z.string().optional().describe("Alt text for the image (optional)"),
|
alt: z.string().optional().describe("Alt text for the image (optional)"),
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -12,9 +12,10 @@ export function registerGetTableSchemaTool(server) {
|
|||||||
withAuthParams({
|
withAuthParams({
|
||||||
tableName: z.string().describe("Table name without cms_ prefix"),
|
tableName: z.string().describe("Table name without cms_ prefix"),
|
||||||
minimal: z.boolean().optional().describe("If true, returns only field names + types + labels"),
|
minimal: z.boolean().optional().describe("If true, returns only field names + types + labels"),
|
||||||
|
filterFields: z.string().optional().describe("Filter field names containing these terms (pipe-separated, e.g. 'galeria|foto|image'). Only matching fields are returned. Useful to find the exact field name without loading the full schema."),
|
||||||
}),
|
}),
|
||||||
{ readOnlyHint: true, destructiveHint: false },
|
{ readOnlyHint: true, destructiveHint: false },
|
||||||
withAuth(async ({ tableName, minimal }, extra) => {
|
withAuth(async ({ tableName, minimal, filterFields }, extra) => {
|
||||||
try {
|
try {
|
||||||
const validationError = validateRequired({ tableName }, ['tableName'], 'get_table_schema');
|
const validationError = validateRequired({ tableName }, ['tableName'], 'get_table_schema');
|
||||||
if (validationError) return validationError;
|
if (validationError) return validationError;
|
||||||
@@ -45,18 +46,41 @@ export function registerGetTableSchemaTool(server) {
|
|||||||
|
|
||||||
const parsed = parseIniSchema(iniContent);
|
const parsed = parseIniSchema(iniContent);
|
||||||
|
|
||||||
if (minimal) {
|
// Filtrar campos si se pasa filterFields (pipe-separated terms)
|
||||||
const minimalSchema = { menuName: parsed.menuName, menuType: parsed.menuType, enlace: parsed.enlace };
|
let fields = parsed.fields || {};
|
||||||
const minFields = {};
|
if (filterFields) {
|
||||||
for (const [key, value] of Object.entries(parsed.fields || {})) {
|
const terms = filterFields.toLowerCase().split("|").map(t => t.trim()).filter(Boolean);
|
||||||
minFields[key] = { type: value.type };
|
const filtered = {};
|
||||||
if (value.label) minFields[key].label = value.label;
|
for (const [key, value] of Object.entries(fields)) {
|
||||||
|
const keyLower = key.toLowerCase();
|
||||||
|
const labelLower = (value.label || "").toLowerCase();
|
||||||
|
if (terms.some(t => keyLower.includes(t) || labelLower.includes(t))) {
|
||||||
|
filtered[key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fields = filtered;
|
||||||
|
if (Object.keys(fields).length === 0) {
|
||||||
|
return { content: [{ type: "text", text: JSON.stringify({
|
||||||
|
tableName, filterFields, matches: 0,
|
||||||
|
message: "No fields matching filter. Try broader terms or omit filterFields to see all.",
|
||||||
|
}, null, 2) }] };
|
||||||
}
|
}
|
||||||
minimalSchema.fields = minFields;
|
|
||||||
return { content: [{ type: "text", text: JSON.stringify(minimalSchema, null, 2) }] };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return { content: [{ type: "text", text: JSON.stringify(parsed, null, 2) }] };
|
if (minimal || filterFields) {
|
||||||
|
const result = { menuName: parsed.menuName, tableName };
|
||||||
|
const minFields = {};
|
||||||
|
for (const [key, value] of Object.entries(fields)) {
|
||||||
|
minFields[key] = { type: value.type };
|
||||||
|
if (value.label) minFields[key].label = value.label;
|
||||||
|
if (value.maxUploads) minFields[key].maxUploads = value.maxUploads;
|
||||||
|
}
|
||||||
|
result.fields = minFields;
|
||||||
|
if (filterFields) result.filterFields = filterFields;
|
||||||
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
||||||
|
}
|
||||||
|
|
||||||
|
return { content: [{ type: "text", text: JSON.stringify({ ...parsed, fields }, null, 2) }] };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return handleToolError(error, 'get_table_schema', { tableName });
|
return handleToolError(error, 'get_table_schema', { tableName });
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user