Files
agenticSystem/mcp-server/tools/orchestrator/workflows/createSection.js
Jordan Diaz e84a36c83d mcp tablas
2026-04-25 08:51:17 +00:00

115 lines
8.6 KiB
JavaScript

export const createSectionWorkflow = {
id: "create_section",
name: "Create New Section",
description: "Full workflow for creating a new website section: table + fields + module + template + content.",
steps: [
{
step: 1,
action: "Understand requirements",
description: "Clarify with user: section name, type (multi/single/category), fields needed, whether it needs URL (enlace), SEO meta tags.",
tool: null,
critical: "Ask before acting. Multi = multiple records (blog, products). Single = one record (about page). Category = grouping for other sections."
},
{
step: 2,
action: "Check existing tables",
description: "List current tables to avoid naming conflicts and understand existing structure.",
tool: "list_tables",
critical: "Table names must be unique. Check if a similar section already exists."
},
{
step: 3,
action: "Create the table",
description: "Create the database table with correct type and configuration. Pass enlace=true if records need public URLs; pass seoMetas=true if records need SEO meta fields. Those flags are enough — there is no update_table_schema step afterwards.",
tool: "create_table",
critical: "menuType must be: 'multi' (multiple records), 'single' (one record), 'category' (grouping), or 'separador' (menu separator). Set enlace=true if records need their own URL page. Set seoMetas=true if you want the SEO meta fields added from the start."
},
{
step: 4,
action: "Add fields to the table",
description: "Create each necessary field with the correct type. create_field is a single-field operation — call it once per field.",
tool: "create_field",
critical: "One call per field. Field types: textfield, textbox, wysiwyg, date, checkbox, list, upload, multitext, codigo, separator. Pass isRequired / maxLength / listType / etc. via initialProps."
},
{
step: 5,
action: "Verify table schema",
description: "Get the complete schema to confirm all fields were created correctly.",
tool: "get_table_schema",
critical: "Verify all fields exist with correct types before proceeding to module creation."
},
{
step: 6,
action: "Design and create the listing module",
description: "Create the listing module that displays a list/grid of records. Use create_module to scaffold the folder, then acai-write on index-base.tpl with the Twig (compile runs automatically).",
tool: "create_module",
critical: "Use Twig syntax. Access records with the 'get' filter. Primary key is 'num' not 'id'. Upload fields are ALWAYS arrays: use record.field[0].urlPath | imagec(width). After create_module, use acai-write on index-base.tpl to set the actual template."
},
{
step: 7,
action: "Set module example data",
description: "Set example/static data for module preview. MUST call get_module_config_vars first to discover ALL variables.",
tool: "set_module_example_data",
critical: "Every builder variable must have example data. Missing variables cause blank previews."
},
{
step: 8,
action: "Add sample content",
description: "Create 2-3 sample records with realistic content and images. If table has enlace=true, include the 'enlace' field with a URL slug.",
tool: "create_or_update_record",
critical: "Date format: YYYY-MM-DD HH:mm:ss. Checkbox: 1 or 0. Upload fields: use upload_record_image separately. For sections with enlace, create records BEFORE creating the general section to ensure directory structure is ready."
},
{
step: 9,
action: "Create the general section (detail template) — if enlace=true",
description: "If the table has enlace enabled, create a module named literally 'custom-{tableName}' in template/estandar/modulos/. This module renders every record's URL automatically; there is NO _detailPage field to configure. Use acai-write on template/estandar/modulos/custom-{tableName}/index-base.tpl — it creates the folder and triggers the compile.",
tool: "acai-write",
critical: "Folder name must be EXACTLY 'custom-' + tableName (e.g. table 'vacantes' → 'custom-vacantes'). The CMS routes by this convention. Inside the template access the current record via `thisrecord.fieldname`. Do NOT create a separate listing page in 'apartados' for details, do NOT use query params, do NOT use hooks to fetch the record."
},
{
step: 10,
action: "Verify the result",
description: "Check module rendering with actual variable values.",
tool: "check_module",
critical: "Test with actual variable values to ensure no rendering errors."
}
],
context: {
twig_filters: "Use 'get' filter for DB queries: {% set items = 'tablename' | get('WHERE active=1', 'ORDER BY num DESC', 10) %}. Use 'imagec' for image resize: {{ path | imagec(400) }}. Use 'module' to include other modules: {{ 'modulename' | module(vars) }}.",
field_types: "textfield (single line), textbox (multiline), wysiwyg (rich HTML), date (YYYY-MM-DD), checkbox (0/1), list (dropdown/radio/checkbox), upload (files/images), multitext (key-value pairs), codigo (code editor), separator (visual divider).",
list_field_config: "Static options: optionsType='text', optionsText='value1|Label 1\\nvalue2|Label 2'. Table relation: optionsType='table', optionsTablename='tablename', optionsValueField='num', optionsLabelField='name'. SQL: optionsType='query', optionsQuery='SELECT num,name FROM cms_tablename'.",
builder_vars: "data-field-type attribute on HTML elements creates editable fields. Types: textfield, headfield, textbox, wysiwyg, link, upload, uploadBackground, uploadMulti, list, multiv2. Variable names derived from labels (lowercase, no spaces/accents).",
upload_rules: "Upload fields ALWAYS return arrays. Single image: {{ record.imagen[0].urlPath | imagec(WIDTH) }}. Gallery loop: {% for img in record.galeria %}{{ img.urlPath }}{% endfor %}. Check existence: {% if record.imagen and record.imagen|length > 0 %}.",
general_section_convention: "For any table with enlace=true, the detail template is a module at template/estandar/modulos/custom-{tableName}/. The CMS binds it automatically — no configuration required. Use `thisrecord.field` inside the Twig to access the record being rendered."
},
rules: [
"Table names WITHOUT 'cms_' prefix in all tool calls",
"Primary key is ALWAYS 'num', never 'id'",
"Upload fields are ALWAYS arrays of objects with urlPath property",
"Use ONLY Twig FILTERS (pipe syntax), not Twig functions",
"Date format: YYYY-MM-DD HH:mm:ss",
"Checkbox values: 1 or 0 (number, not boolean)",
"Enlace (URL slug): auto-formatted to /path/ with slashes",
"Variable names in modules: lowercase, no spaces, no accents, no special chars",
"c-if='varname' for conditional rendering, c-hidden='true' for invisible config vars",
"When using 'get' filter: SQL string syntax, NOT objects. Example: 'WHERE num > 5'",
"The general section (record detail) is ALWAYS a module named 'custom-{tableName}' — never a separate page in 'apartados'."
],
warnings: [
"DO NOT use record.imagen.urlPath — it's record.imagen[0].urlPath (array!)",
"DO NOT use 'id' as primary key — Acai uses 'num'",
"DO NOT forget to set example data after creating a module — it will look blank",
"DO NOT create a detail template if enlace is false — there's no URL to navigate to",
"DO NOT use Twig functions like range() — only filters (pipe syntax) are available",
"DO NOT configure '_detailPage' or any similar field — it does not exist; routing is by the 'custom-{tableName}' convention.",
"DO NOT create individual pages in 'apartados' for each record — the general section handles all records of the table automatically.",
"For best results with new enlace sections, create records BEFORE creating the general section so the directory structure exists."
],
resources: [
"acai://resources/guia-builder-vars",
"acai://resources/guia-twig-filters",
"acai://resources/guia-atributos-acai",
"acai://resources/guia-registros"
]
};