A2UI parity: restore chart-type guidance in system prompt, add detailed schemas for form fields, card actions, tab content, and mindmap nodes

This commit is contained in:
2026-05-31 14:05:13 +02:00
parent ef6f8a54b2
commit a33131ddea
7 changed files with 809 additions and 37 deletions

View File

@@ -786,15 +786,16 @@ defmodule BDS.AI.Chat do
"- Use list_tags, list_categories, and count_posts for taxonomy and grouped analytics questions.",
"If a requested blog fact is available through these tools, call the tool instead of saying you cannot access the data.",
"",
"Available UI Render Tools:",
"- Use render_chart to show data as a bar, stacked-bar, line, area, pie, donut, or heatmap chart. Use it when presenting statistics or comparisons. Prefer heatmap over tables with emoji or color indicators for intensity grids or calendar-style activity.",
"- Use render_table for tabular data, comparisons, and structured listings.",
"- Use render_form to collect structured user input.",
"- Use render_card for summaries, highlights, or actionable items.",
"- Use render_metric for a single KPI or important statistic.",
"- Use render_list for bullet lists, checklists, or simple enumerations.",
"- Use render_tabs to organize multiple views into switchable tabs; tab content can contain text, metrics, lists, charts, and tables.",
"When presenting data, statistics, or comparisons, prefer render tools over plain text. When building any visualization, render it as soon as you have enough data."
"Available UI Render Tools (use these to show rich interactive elements):",
"- render_chart: Show data as a bar, stacked-bar, line, area, pie, donut, or heatmap chart. Use when presenting statistics or comparisons. Use stacked-bar when each bar has multiple segments (e.g., published vs draft posts per year). Use area for cumulative or trend data where the filled region emphasizes volume. Use donut for proportional breakdowns with a total displayed in the center. Use heatmap for grid/matrix visualizations where color intensity shows magnitude — e.g., posts per month across years (each series entry is a row like a year, each segment is a column like a month), or a calendar view where rows are weekdays and columns are week numbers. ALWAYS prefer heatmap over a table with emojis or color indicators when showing intensity grids or calendar-style activity views. IMPORTANT: a heatmap needs structured data — each entry in 'series' is a ROW and must include a 'segments' array whose entries are the COLUMNS (every segment needs a 'label' and a numeric 'value'); the row's own 'value' is ignored. Plan what the rows and columns represent before fetching data (e.g. rows = years, columns = months). A heatmap sent without segments renders empty.",
"- render_table: Show data in a structured table. Use for tabular comparisons and listings.",
"- render_form: Show an interactive form to collect user input (e.g., metadata edits, settings).",
"- render_card: Show an information card with title, body, and action buttons.",
"- render_metric: Show a single KPI or statistic prominently.",
"- render_list: Show a bulleted list of items.",
"- render_tabs: Organize information into switchable tabs. Tab content supports all content types: text, metrics, lists, charts, and tables.",
"",
"When presenting data, statistics, or comparisons, prefer using render tools (render_chart, render_table, render_metric) to show rich interactive UI instead of plain text. When you need user input for a multi-field operation, use render_form to present a structured form. Use render_card with action buttons when presenting items the user might want to navigate to (e.g., posts, media). When comparing data across multiple dimensions (e.g., statistics per year), use render_tabs with embedded charts or tables in each tab. When building any visualization, render it as soon as you have enough data."
],
"\n"
)

View File

@@ -803,10 +803,40 @@ defmodule BDS.AI.ChatTools do
%{
"type" => "object",
"properties" => %{
"title" => %{"type" => "string"},
"fields" => %{"type" => "array"},
"submitLabel" => %{"type" => "string"},
"submitAction" => %{"type" => "string"}
"title" => %{"type" => "string", "description" => "Optional form title"},
"fields" => %{
"type" => "array",
"description" => "Form fields to display",
"items" => %{
"type" => "object",
"properties" => %{
"key" => %{"type" => "string", "description" => "Field identifier"},
"label" => %{"type" => "string", "description" => "Field label shown to user"},
"inputType" => %{
"type" => "string",
"enum" => ["text", "textarea", "select", "checkbox", "date", "number"],
"description" => "Type of input control"
},
"placeholder" => %{"type" => "string", "description" => "Placeholder text"},
"defaultValue" => %{"type" => "string", "description" => "Default value"},
"options" => %{
"type" => "array",
"description" => "Options for select fields",
"items" => %{
"type" => "object",
"properties" => %{
"label" => %{"type" => "string"},
"value" => %{"type" => "string"}
}
}
},
"required" => %{"type" => "boolean", "description" => "Whether the field is required"}
},
"required" => ["key", "label", "inputType"]
}
},
"submitLabel" => %{"type" => "string", "description" => "Label for the submit button"},
"submitAction" => %{"type" => "string", "description" => "Action to dispatch on submit"}
}
}
end
@@ -815,10 +845,25 @@ defmodule BDS.AI.ChatTools do
%{
"type" => "object",
"properties" => %{
"title" => %{"type" => "string"},
"subtitle" => %{"type" => "string"},
"body" => %{"type" => "string"},
"actions" => %{"type" => "array"}
"title" => %{"type" => "string", "description" => "Card title"},
"subtitle" => %{"type" => "string", "description" => "Optional subtitle"},
"body" => %{"type" => "string", "description" => "Card body text (supports markdown)"},
"actions" => %{
"type" => "array",
"description" => "Optional action buttons on the card",
"items" => %{
"type" => "object",
"properties" => %{
"label" => %{"type" => "string", "description" => "Button label"},
"action" => %{"type" => "string", "description" => "Action name to dispatch"},
"payload" => %{
"type" => "object",
"description" => "Optional action payload"
}
},
"required" => ["label", "action"]
}
}
}
}
end
@@ -827,8 +872,8 @@ defmodule BDS.AI.ChatTools do
%{
"type" => "object",
"properties" => %{
"label" => %{"type" => "string"},
"value" => %{"type" => "string"}
"label" => %{"type" => "string", "description" => "Metric label"},
"value" => %{"type" => "string", "description" => "Metric value (displayed prominently)"}
}
}
end
@@ -837,8 +882,12 @@ defmodule BDS.AI.ChatTools do
%{
"type" => "object",
"properties" => %{
"title" => %{"type" => "string"},
"items" => %{"type" => "array"}
"title" => %{"type" => "string", "description" => "Optional list title"},
"items" => %{
"type" => "array",
"items" => %{"type" => "string"},
"description" => "List items"
}
}
}
end
@@ -847,8 +896,58 @@ defmodule BDS.AI.ChatTools do
%{
"type" => "object",
"properties" => %{
"title" => %{"type" => "string"},
"tabs" => %{"type" => "array"}
"title" => %{"type" => "string", "description" => "Optional tabs title"},
"tabs" => %{
"type" => "array",
"description" => "Array of tabs",
"items" => %{
"type" => "object",
"properties" => %{
"label" => %{"type" => "string", "description" => "Tab label"},
"content" => %{
"type" => "array",
"description" => "Content items within the tab",
"items" => %{
"type" => "object",
"properties" => %{
"type" => %{
"type" => "string",
"enum" => ["text", "metric", "list", "chart", "table"],
"description" => "Content type"
},
"text" => %{"type" => "string", "description" => "Text content (for type text)"},
"label" => %{"type" => "string", "description" => "Label (for type metric)"},
"value" => %{"type" => "string", "description" => "Display value (for type metric)"},
"title" => %{"type" => "string", "description" => "Title (for type list, chart, or table)"},
"items" => %{
"type" => "array", "items" => %{"type" => "string"},
"description" => "Items (for type list)"
},
"chartType" => %{
"type" => "string",
"enum" => ["bar", "stacked-bar", "line", "area", "pie", "donut", "heatmap"],
"description" => "Chart type (for type chart)"
},
"series" => %{
"type" => "array",
"description" => "Data series (for type chart)"
},
"columns" => %{
"type" => "array", "items" => %{"type" => "string"},
"description" => "Column headers (for type table)"
},
"rows" => %{
"type" => "array", "items" => %{"type" => "array", "items" => %{"type" => "string"}},
"description" => "Table rows (for type table)"
}
},
"required" => ["type"]
}
}
},
"required" => ["label", "content"]
}
}
}
}
end
@@ -857,8 +956,24 @@ defmodule BDS.AI.ChatTools do
%{
"type" => "object",
"properties" => %{
"title" => %{"type" => "string"},
"nodes" => %{"type" => "array"}
"title" => %{"type" => "string", "description" => "Optional mind map title"},
"nodes" => %{
"type" => "array",
"description" => "Flat array of nodes. The first node is the root. Each node references children by ID.",
"items" => %{
"type" => "object",
"properties" => %{
"id" => %{"type" => "string", "description" => "Unique node identifier"},
"label" => %{"type" => "string", "description" => "Node label text"},
"children" => %{
"type" => "array",
"items" => %{"type" => "string"},
"description" => "IDs of child nodes"
}
},
"required" => ["id", "label"]
}
}
}
}
end