@absolutejs/ai 0.0.33 → 0.0.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai/index.js +54 -2
- package/dist/ai/index.js.map +3 -3
- package/dist/ai/ui/index.js +54 -2
- package/dist/ai/ui/index.js.map +3 -3
- package/dist/src/ai/ui/catalog.d.ts +25 -0
- package/dist/src/ai/ui/index.d.ts +1 -1
- package/package.json +1 -1
package/dist/ai/ui/index.js
CHANGED
|
@@ -100,10 +100,13 @@ var CHART_MAX_POINTS = 24;
|
|
|
100
100
|
var TABLE_MAX_COLUMNS = 8;
|
|
101
101
|
var TABLE_MAX_ROWS = 30;
|
|
102
102
|
var STAT_TILES_MAX = 6;
|
|
103
|
+
var UI_ACTIONS_MAX = 3;
|
|
103
104
|
var LABEL_MAX_CHARS = 80;
|
|
104
105
|
var TITLE_MAX_CHARS = 120;
|
|
105
106
|
var CELL_MAX_CHARS = 160;
|
|
106
107
|
var UNIT_MAX_CHARS = 8;
|
|
108
|
+
var ACTION_LABEL_MAX_CHARS = 40;
|
|
109
|
+
var ACTION_TOOL_PATTERN = /^[a-z][a-z0-9_]{1,63}$/;
|
|
107
110
|
var isRecord = (value) => typeof value === "object" && value !== null;
|
|
108
111
|
var cleanString = (value, maxChars) => typeof value === "string" && value.trim().length > 0 ? value.trim().slice(0, maxChars) : null;
|
|
109
112
|
var cleanStringArray = (value, maxItems, maxChars) => {
|
|
@@ -127,6 +130,40 @@ var cleanNumberArray = (value, maxItems) => {
|
|
|
127
130
|
}
|
|
128
131
|
return cleaned;
|
|
129
132
|
};
|
|
133
|
+
var parseUiActions = (value) => {
|
|
134
|
+
if (!Array.isArray(value) || value.length === 0)
|
|
135
|
+
return;
|
|
136
|
+
const actions = [];
|
|
137
|
+
for (const raw of value.slice(0, UI_ACTIONS_MAX)) {
|
|
138
|
+
if (!isRecord(raw))
|
|
139
|
+
continue;
|
|
140
|
+
const label = cleanString(raw.label, ACTION_LABEL_MAX_CHARS);
|
|
141
|
+
const tool = typeof raw.tool === "string" && ACTION_TOOL_PATTERN.test(raw.tool) ? raw.tool : null;
|
|
142
|
+
if (!label || !tool || !isRecord(raw.input))
|
|
143
|
+
continue;
|
|
144
|
+
actions.push({ input: raw.input, label, tool });
|
|
145
|
+
}
|
|
146
|
+
return actions.length > 0 ? actions : undefined;
|
|
147
|
+
};
|
|
148
|
+
var ACTIONS_SCHEMA = {
|
|
149
|
+
description: "Optional action buttons under the card (max 3): each invokes one of YOUR tools with a fully-resolved input when the member clicks it. Use real ids you looked up — never placeholders. Approval-gated tools queue their normal approval card.",
|
|
150
|
+
items: {
|
|
151
|
+
properties: {
|
|
152
|
+
input: {
|
|
153
|
+
description: "The exact tool input to send on click",
|
|
154
|
+
type: "object"
|
|
155
|
+
},
|
|
156
|
+
label: {
|
|
157
|
+
description: 'Short button label, e.g. "Create follow-up task"',
|
|
158
|
+
type: "string"
|
|
159
|
+
},
|
|
160
|
+
tool: { description: "The tool name to invoke", type: "string" }
|
|
161
|
+
},
|
|
162
|
+
required: ["label", "tool", "input"],
|
|
163
|
+
type: "object"
|
|
164
|
+
},
|
|
165
|
+
type: "array"
|
|
166
|
+
};
|
|
130
167
|
var parseChartSpec = (input) => {
|
|
131
168
|
if (!isRecord(input))
|
|
132
169
|
return null;
|
|
@@ -163,6 +200,9 @@ var parseChartSpec = (input) => {
|
|
|
163
200
|
spec.unitPrefix = unitPrefix;
|
|
164
201
|
if (unitSuffix)
|
|
165
202
|
spec.unitSuffix = unitSuffix;
|
|
203
|
+
const actions = parseUiActions(input.actions);
|
|
204
|
+
if (actions)
|
|
205
|
+
spec.actions = actions;
|
|
166
206
|
return spec;
|
|
167
207
|
};
|
|
168
208
|
var parseTableSpec = (input) => {
|
|
@@ -186,6 +226,9 @@ var parseTableSpec = (input) => {
|
|
|
186
226
|
const title = cleanString(input.title, TITLE_MAX_CHARS);
|
|
187
227
|
if (title)
|
|
188
228
|
spec.title = title;
|
|
229
|
+
const actions = parseUiActions(input.actions);
|
|
230
|
+
if (actions)
|
|
231
|
+
spec.actions = actions;
|
|
189
232
|
return spec;
|
|
190
233
|
};
|
|
191
234
|
var parseStatTilesSpec = (input) => {
|
|
@@ -210,7 +253,11 @@ var parseStatTilesSpec = (input) => {
|
|
|
210
253
|
}
|
|
211
254
|
tiles.push(tile);
|
|
212
255
|
}
|
|
213
|
-
|
|
256
|
+
const spec = { tiles };
|
|
257
|
+
const actions = parseUiActions(input.actions);
|
|
258
|
+
if (actions)
|
|
259
|
+
spec.actions = actions;
|
|
260
|
+
return spec;
|
|
214
261
|
};
|
|
215
262
|
var SERIES_SCHEMA = {
|
|
216
263
|
properties: {
|
|
@@ -229,6 +276,7 @@ var chartCard = {
|
|
|
229
276
|
description: "Render a real chart inline in the chat from data you have (tool results, the conversation). Use whenever numbers COMPARE or TREND: revenue by partner (bar), pipeline over time (line), share of a whole (donut). Rules: bar/line take up to 8 series aligned to the same labels; donut takes exactly ONE series of non-negative values (one slice per label). Prefer a chart over a wall of numbers, but never invent data for it.",
|
|
230
277
|
inputSchema: {
|
|
231
278
|
properties: {
|
|
279
|
+
actions: ACTIONS_SCHEMA,
|
|
232
280
|
labels: {
|
|
233
281
|
description: "Category labels — x-axis for bar/line, slice names for donut (max 24)",
|
|
234
282
|
items: { type: "string" },
|
|
@@ -261,6 +309,7 @@ var tableCard = {
|
|
|
261
309
|
description: "Render a compact data table inline in the chat (max 8 columns × 30 rows). Use for structured comparisons the member will scan — matches side by side, deal terms, task lists with dates. All cells are strings; format numbers yourself.",
|
|
262
310
|
inputSchema: {
|
|
263
311
|
properties: {
|
|
312
|
+
actions: ACTIONS_SCHEMA,
|
|
264
313
|
columns: {
|
|
265
314
|
description: "Column headers (max 8)",
|
|
266
315
|
items: { type: "string" },
|
|
@@ -284,6 +333,7 @@ var statTilesCard = {
|
|
|
284
333
|
description: "Render a row of headline stat tiles inline in the chat (max 6): a label, a big value, and an optional delta with direction. Use for the 2-4 numbers that ARE the answer — total attributed revenue, pipeline value, credits remaining — instead of burying them in prose.",
|
|
285
334
|
inputSchema: {
|
|
286
335
|
properties: {
|
|
336
|
+
actions: ACTIONS_SCHEMA,
|
|
287
337
|
tiles: {
|
|
288
338
|
description: "The tiles (max 6)",
|
|
289
339
|
items: {
|
|
@@ -532,11 +582,13 @@ export {
|
|
|
532
582
|
tableCard,
|
|
533
583
|
statTilesCard,
|
|
534
584
|
renderChartSvg,
|
|
585
|
+
parseUiActions,
|
|
535
586
|
parseTableSpec,
|
|
536
587
|
parseStatTilesSpec,
|
|
537
588
|
parseChartSpec,
|
|
538
589
|
createUiCards,
|
|
539
590
|
chartCard,
|
|
591
|
+
UI_ACTIONS_MAX,
|
|
540
592
|
TABLE_MAX_ROWS,
|
|
541
593
|
TABLE_MAX_COLUMNS,
|
|
542
594
|
STAT_TILES_MAX,
|
|
@@ -548,5 +600,5 @@ export {
|
|
|
548
600
|
BUILTIN_UI_CARDS
|
|
549
601
|
};
|
|
550
602
|
|
|
551
|
-
//# debugId=
|
|
603
|
+
//# debugId=361FE26314A51E4B64756E2164756E21
|
|
552
604
|
//# sourceMappingURL=index.js.map
|
package/dist/ai/ui/index.js.map
CHANGED
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
"sources": ["../src/ai/ui/uiCards.ts", "../src/ai/ui/catalog.ts", "../src/ai/ui/svg.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
5
|
"import type { AIToolMap } from \"../../../types/ai\";\n\n/**\n * UI cards — the generative-UI primitive extracted from onSpark's chat.\n *\n * A \"card\" is a schema-only tool: the model calls it with a structured payload,\n * the handler only ACKNOWLEDGES (steering the model's continuation), and the\n * host watches the executed tool calls to render the payload as a real,\n * host-styled component (a chart, a table, an approval card, a deep link…).\n * No model-written code ever executes: the payload is validated by the card's\n * `parse` before anything renders, so a malformed call simply drops.\n */\nexport type UiCardDefinition<T = unknown> = {\n /** Tool name the model calls, e.g. \"render_chart\". */\n name: string;\n /** Tool description — steer WHEN the model should render this card. */\n description: string;\n /** JSON schema for the tool input. */\n inputSchema: Record<string, unknown>;\n /** Tool-result text fed back to the model (e.g. \"(chart rendered — don't\n * repeat its numbers in text)\"). */\n ack: string;\n /** Validate + narrow the raw model input to the card payload. Return null\n * to reject the call (the card is dropped, the ack still steered). */\n parse: (input: unknown) => T | null;\n};\n\nexport type UiCardEvent = {\n /** The card's tool name. */\n card: string;\n /** The parsed, validated payload. */\n data: unknown;\n};\n\nexport type UiCards = {\n /** AIToolMap entries (ack handlers) — spread into the tools you hand to\n * streamAIWithTools / generateAIWithTools. */\n tools: AIToolMap;\n /** Pull validated card events out of a turn's tool calls, in call order.\n * Invalid payloads and non-card tools are skipped. */\n collect: (\n calls: readonly { name: string; input: unknown }[],\n ) => UiCardEvent[];\n /** Is this tool name one of the registered cards? */\n has: (name: string) => boolean;\n};\n\n/** Build the tool map + collector for a set of UI cards. */\nexport const createUiCards = (\n definitions: readonly UiCardDefinition[],\n): UiCards => {\n const byName = new Map(\n definitions.map((definition) => [definition.name, definition]),\n );\n\n const tools: AIToolMap = Object.fromEntries(\n definitions.map((definition) => [\n definition.name,\n {\n description: definition.description,\n handler: () => definition.ack,\n input: definition.inputSchema,\n },\n ]),\n );\n\n const collect = (calls: readonly { name: string; input: unknown }[]) => {\n const events: UiCardEvent[] = [];\n for (const call of calls) {\n const definition = byName.get(call.name);\n if (!definition) continue;\n const data = definition.parse(call.input);\n if (data !== null) events.push({ card: definition.name, data });\n }\n\n return events;\n };\n\n return { collect, has: (name: string) => byName.has(name), tools };\n};\n",
|
|
6
|
-
"import type { UiCardDefinition } from \"./uiCards\";\n\n/**\n * Built-in UI card catalog: chart, table, stat tiles. Declarative specs the\n * model authors and the host renders — see svg.ts for the dependency-free\n * default renderer. Caps are hard product guards (a model can't render a\n * 400-row table into a chat bubble).\n */\n\nexport const CHART_TYPES = [\"bar\", \"line\", \"donut\"] as const;\nexport type ChartType = (typeof CHART_TYPES)[number];\n\nexport type ChartSeries = { name: string; values: number[] };\n\nexport type ChartSpec = {\n type: ChartType;\n title: string;\n /** Category labels: x-axis (bar/line) or slice names (donut). */\n labels: string[];\n /** ≤ 8 series (fixed hue order). Donut charts use exactly one series. */\n series: ChartSeries[];\n /** Value formatting, e.g. \"$\" / \"%\". */\n unitPrefix?: string;\n unitSuffix?: string;\n};\n\nexport type TableSpec = {\n title?: string;\n columns: string[];\n rows: string[][];\n};\n\nexport type StatTile = {\n label: string;\n value: string;\n /** Optional change annotation, e.g. \"+12% vs last month\". */\n delta?: string;\n deltaDirection?: \"up\" | \"down\" | \"flat\";\n};\n\nexport type StatTilesSpec = { tiles: StatTile[] };\n\n// Hard caps — chat-bubble scale, and the fixed 8-slot categorical order.\nexport const CHART_MAX_SERIES = 8;\nexport const CHART_MAX_POINTS = 24;\nexport const TABLE_MAX_COLUMNS = 8;\nexport const TABLE_MAX_ROWS = 30;\nexport const STAT_TILES_MAX = 6;\nconst LABEL_MAX_CHARS = 80;\nconst TITLE_MAX_CHARS = 120;\nconst CELL_MAX_CHARS = 160;\nconst UNIT_MAX_CHARS = 8;\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null;\n\nconst cleanString = (value: unknown, maxChars: number) =>\n typeof value === \"string\" && value.trim().length > 0\n ? value.trim().slice(0, maxChars)\n : null;\n\nconst cleanStringArray = (\n value: unknown,\n maxItems: number,\n maxChars: number,\n) => {\n if (!Array.isArray(value) || value.length === 0) return null;\n const cleaned: string[] = [];\n for (const entry of value.slice(0, maxItems)) {\n const text = cleanString(entry, maxChars);\n cleaned.push(text ?? \"\");\n }\n\n return cleaned;\n};\n\nconst cleanNumberArray = (value: unknown, maxItems: number) => {\n if (!Array.isArray(value) || value.length === 0) return null;\n const cleaned: number[] = [];\n for (const entry of value.slice(0, maxItems)) {\n if (typeof entry !== \"number\" || !Number.isFinite(entry)) return null;\n cleaned.push(entry);\n }\n\n return cleaned;\n};\n\nexport const parseChartSpec = (input: unknown): ChartSpec | null => {\n if (!isRecord(input)) return null;\n const type = CHART_TYPES.find((entry) => entry === input.type);\n const title = cleanString(input.title, TITLE_MAX_CHARS);\n const labels = cleanStringArray(\n input.labels,\n CHART_MAX_POINTS,\n LABEL_MAX_CHARS,\n );\n if (!type || !title || !labels) return null;\n\n if (!Array.isArray(input.series) || input.series.length === 0) return null;\n const series: ChartSeries[] = [];\n for (const raw of input.series.slice(0, CHART_MAX_SERIES)) {\n if (!isRecord(raw)) return null;\n const name = cleanString(raw.name, LABEL_MAX_CHARS);\n const values = cleanNumberArray(raw.values, CHART_MAX_POINTS);\n if (!name || !values) return null;\n // Every series aligns with the label axis; pad/trim mismatches drop.\n if (values.length !== labels.length) return null;\n series.push({ name, values });\n }\n // Donut: one series, non-negative slices.\n if (type === \"donut\") {\n const [only] = series;\n if (series.length !== 1 || !only) return null;\n if (only.values.some((value) => value < 0)) return null;\n }\n\n const spec: ChartSpec = { labels, series, title, type };\n const unitPrefix = cleanString(input.unitPrefix, UNIT_MAX_CHARS);\n const unitSuffix = cleanString(input.unitSuffix, UNIT_MAX_CHARS);\n if (unitPrefix) spec.unitPrefix = unitPrefix;\n if (unitSuffix) spec.unitSuffix = unitSuffix;\n\n return spec;\n};\n\nexport const parseTableSpec = (input: unknown): TableSpec | null => {\n if (!isRecord(input)) return null;\n const columns = cleanStringArray(\n input.columns,\n TABLE_MAX_COLUMNS,\n LABEL_MAX_CHARS,\n );\n if (!columns) return null;\n if (!Array.isArray(input.rows) || input.rows.length === 0) return null;\n const rows: string[][] = [];\n for (const raw of input.rows.slice(0, TABLE_MAX_ROWS)) {\n const cells = cleanStringArray(raw, TABLE_MAX_COLUMNS, CELL_MAX_CHARS);\n if (!cells) return null;\n // Normalize ragged rows to the header width.\n while (cells.length < columns.length) cells.push(\"\");\n rows.push(cells.slice(0, columns.length));\n }\n\n const spec: TableSpec = { columns, rows };\n const title = cleanString(input.title, TITLE_MAX_CHARS);\n if (title) spec.title = title;\n\n return spec;\n};\n\nexport const parseStatTilesSpec = (input: unknown): StatTilesSpec | null => {\n if (!isRecord(input)) return null;\n if (!Array.isArray(input.tiles) || input.tiles.length === 0) return null;\n const tiles: StatTile[] = [];\n for (const raw of input.tiles.slice(0, STAT_TILES_MAX)) {\n if (!isRecord(raw)) return null;\n const label = cleanString(raw.label, LABEL_MAX_CHARS);\n const value = cleanString(raw.value, LABEL_MAX_CHARS);\n if (!label || !value) return null;\n const tile: StatTile = { label, value };\n const delta = cleanString(raw.delta, LABEL_MAX_CHARS);\n if (delta) tile.delta = delta;\n if (\n raw.deltaDirection === \"up\" ||\n raw.deltaDirection === \"down\" ||\n raw.deltaDirection === \"flat\"\n ) {\n tile.deltaDirection = raw.deltaDirection;\n }\n tiles.push(tile);\n }\n\n return { tiles };\n};\n\nconst SERIES_SCHEMA = {\n properties: {\n name: { description: \"Series name (shown in the legend)\", type: \"string\" },\n values: {\n description: \"One number per label, same order as labels\",\n items: { type: \"number\" },\n type: \"array\",\n },\n },\n required: [\"name\", \"values\"],\n type: \"object\",\n};\n\n/** render_chart — bar / line / donut from data you already have. */\nexport const chartCard: UiCardDefinition<ChartSpec> = {\n ack: \"(chart rendered inline — do not repeat its numbers as text; add at most a 1-2 line takeaway)\",\n description:\n \"Render a real chart inline in the chat from data you have (tool results, the conversation). Use whenever numbers COMPARE or TREND: revenue by partner (bar), pipeline over time (line), share of a whole (donut). Rules: bar/line take up to 8 series aligned to the same labels; donut takes exactly ONE series of non-negative values (one slice per label). Prefer a chart over a wall of numbers, but never invent data for it.\",\n inputSchema: {\n properties: {\n labels: {\n description:\n \"Category labels — x-axis for bar/line, slice names for donut (max 24)\",\n items: { type: \"string\" },\n type: \"array\",\n },\n series: {\n description: \"Data series (max 8; donut exactly 1)\",\n items: SERIES_SCHEMA,\n type: \"array\",\n },\n title: { description: \"Short chart title\", type: \"string\" },\n type: { enum: [...CHART_TYPES], type: \"string\" },\n unitPrefix: {\n description: 'Prepended to values, e.g. \"$\"',\n type: \"string\",\n },\n unitSuffix: {\n description: 'Appended to values, e.g. \"%\"',\n type: \"string\",\n },\n },\n required: [\"type\", \"title\", \"labels\", \"series\"],\n type: \"object\",\n },\n name: \"render_chart\",\n parse: parseChartSpec,\n};\n\n/** render_table — a compact data table. */\nexport const tableCard: UiCardDefinition<TableSpec> = {\n ack: \"(table rendered inline — do not repeat its rows as text)\",\n description:\n \"Render a compact data table inline in the chat (max 8 columns × 30 rows). Use for structured comparisons the member will scan — matches side by side, deal terms, task lists with dates. All cells are strings; format numbers yourself.\",\n inputSchema: {\n properties: {\n columns: {\n description: \"Column headers (max 8)\",\n items: { type: \"string\" },\n type: \"array\",\n },\n rows: {\n description: \"Rows of cells, each aligned to columns (max 30)\",\n items: { items: { type: \"string\" }, type: \"array\" },\n type: \"array\",\n },\n title: { description: \"Optional table title\", type: \"string\" },\n },\n required: [\"columns\", \"rows\"],\n type: \"object\",\n },\n name: \"render_table\",\n parse: parseTableSpec,\n};\n\n/** render_stat_tiles — a row of headline numbers. */\nexport const statTilesCard: UiCardDefinition<StatTilesSpec> = {\n ack: \"(stat tiles rendered inline — do not repeat the numbers as text)\",\n description:\n \"Render a row of headline stat tiles inline in the chat (max 6): a label, a big value, and an optional delta with direction. Use for the 2-4 numbers that ARE the answer — total attributed revenue, pipeline value, credits remaining — instead of burying them in prose.\",\n inputSchema: {\n properties: {\n tiles: {\n description: \"The tiles (max 6)\",\n items: {\n properties: {\n delta: {\n description: 'Optional change note, e.g. \"+12% vs last month\"',\n type: \"string\",\n },\n deltaDirection: { enum: [\"up\", \"down\", \"flat\"], type: \"string\" },\n label: { description: \"What the number is\", type: \"string\" },\n value: {\n description: 'The formatted headline value, e.g. \"$42,300\"',\n type: \"string\",\n },\n },\n required: [\"label\", \"value\"],\n type: \"object\",\n },\n type: \"array\",\n },\n },\n required: [\"tiles\"],\n type: \"object\",\n },\n name: \"render_stat_tiles\",\n parse: parseStatTilesSpec,\n};\n\n/** The built-in catalog, ready for createUiCards. */\nexport const BUILTIN_UI_CARDS = [chartCard, tableCard, statTilesCard] as const;\n",
|
|
6
|
+
"import type { UiCardDefinition } from \"./uiCards\";\n\n/**\n * Built-in UI card catalog: chart, table, stat tiles. Declarative specs the\n * model authors and the host renders — see svg.ts for the dependency-free\n * default renderer. Caps are hard product guards (a model can't render a\n * 400-row table into a chat bubble).\n */\n\nexport const CHART_TYPES = [\"bar\", \"line\", \"donut\"] as const;\nexport type ChartType = (typeof CHART_TYPES)[number];\n\nexport type ChartSeries = { name: string; values: number[] };\n\nexport type ChartSpec = {\n type: ChartType;\n title: string;\n /** Category labels: x-axis (bar/line) or slice names (donut). */\n labels: string[];\n /** ≤ 8 series (fixed hue order). Donut charts use exactly one series. */\n series: ChartSeries[];\n /** Value formatting, e.g. \"$\" / \"%\". */\n unitPrefix?: string;\n unitSuffix?: string;\n /** Optional action buttons rendered under the card (≤ 3). */\n actions?: UiAction[];\n};\n\nexport type TableSpec = {\n title?: string;\n columns: string[];\n rows: string[][];\n /** Optional action buttons rendered under the card (≤ 3). */\n actions?: UiAction[];\n};\n\nexport type StatTile = {\n label: string;\n value: string;\n /** Optional change annotation, e.g. \"+12% vs last month\". */\n delta?: string;\n deltaDirection?: \"up\" | \"down\" | \"flat\";\n};\n\nexport type StatTilesSpec = { tiles: StatTile[]; actions?: UiAction[] };\n\n/**\n * An action binding on a UI card: a button the host renders under the card\n * that, on click, invokes one of the HOST'S OWN tools with a model-authored\n * input. The host decides which tools are click-invokable (approval-gated\n * tools should queue their normal approval flow, and anything like \"approve a\n * pending action\" should be refused outright) and validates the input against\n * the tool exactly as if the model had called it.\n */\nexport type UiAction = {\n /** Button label, e.g. \"Create follow-up task\". */\n label: string;\n /** The host tool to invoke, e.g. \"create_task\". */\n tool: string;\n /** The tool input, fully resolved by the model (real ids, not placeholders). */\n input: Record<string, unknown>;\n};\n\n// Hard caps — chat-bubble scale, and the fixed 8-slot categorical order.\nexport const CHART_MAX_SERIES = 8;\nexport const CHART_MAX_POINTS = 24;\nexport const TABLE_MAX_COLUMNS = 8;\nexport const TABLE_MAX_ROWS = 30;\nexport const STAT_TILES_MAX = 6;\nexport const UI_ACTIONS_MAX = 3;\nconst LABEL_MAX_CHARS = 80;\nconst TITLE_MAX_CHARS = 120;\nconst CELL_MAX_CHARS = 160;\nconst UNIT_MAX_CHARS = 8;\nconst ACTION_LABEL_MAX_CHARS = 40;\n// Tool names are host identifiers, not prose.\nconst ACTION_TOOL_PATTERN = /^[a-z][a-z0-9_]{1,63}$/;\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null;\n\nconst cleanString = (value: unknown, maxChars: number) =>\n typeof value === \"string\" && value.trim().length > 0\n ? value.trim().slice(0, maxChars)\n : null;\n\nconst cleanStringArray = (\n value: unknown,\n maxItems: number,\n maxChars: number,\n) => {\n if (!Array.isArray(value) || value.length === 0) return null;\n const cleaned: string[] = [];\n for (const entry of value.slice(0, maxItems)) {\n const text = cleanString(entry, maxChars);\n cleaned.push(text ?? \"\");\n }\n\n return cleaned;\n};\n\nconst cleanNumberArray = (value: unknown, maxItems: number) => {\n if (!Array.isArray(value) || value.length === 0) return null;\n const cleaned: number[] = [];\n for (const entry of value.slice(0, maxItems)) {\n if (typeof entry !== \"number\" || !Number.isFinite(entry)) return null;\n cleaned.push(entry);\n }\n\n return cleaned;\n};\n\n/** Validate a spec's optional action bindings; undefined when none/invalid.\n * Malformed entries drop individually — a bad button never sinks the card. */\nexport const parseUiActions = (value: unknown): UiAction[] | undefined => {\n if (!Array.isArray(value) || value.length === 0) return undefined;\n const actions: UiAction[] = [];\n for (const raw of value.slice(0, UI_ACTIONS_MAX)) {\n if (!isRecord(raw)) continue;\n const label = cleanString(raw.label, ACTION_LABEL_MAX_CHARS);\n const tool =\n typeof raw.tool === \"string\" && ACTION_TOOL_PATTERN.test(raw.tool)\n ? raw.tool\n : null;\n if (!label || !tool || !isRecord(raw.input)) continue;\n actions.push({ input: raw.input, label, tool });\n }\n\n return actions.length > 0 ? actions : undefined;\n};\n\nconst ACTIONS_SCHEMA = {\n description:\n \"Optional action buttons under the card (max 3): each invokes one of YOUR tools with a fully-resolved input when the member clicks it. Use real ids you looked up — never placeholders. Approval-gated tools queue their normal approval card.\",\n items: {\n properties: {\n input: {\n description: \"The exact tool input to send on click\",\n type: \"object\",\n },\n label: {\n description: 'Short button label, e.g. \"Create follow-up task\"',\n type: \"string\",\n },\n tool: { description: \"The tool name to invoke\", type: \"string\" },\n },\n required: [\"label\", \"tool\", \"input\"],\n type: \"object\",\n },\n type: \"array\",\n};\n\nexport const parseChartSpec = (input: unknown): ChartSpec | null => {\n if (!isRecord(input)) return null;\n const type = CHART_TYPES.find((entry) => entry === input.type);\n const title = cleanString(input.title, TITLE_MAX_CHARS);\n const labels = cleanStringArray(\n input.labels,\n CHART_MAX_POINTS,\n LABEL_MAX_CHARS,\n );\n if (!type || !title || !labels) return null;\n\n if (!Array.isArray(input.series) || input.series.length === 0) return null;\n const series: ChartSeries[] = [];\n for (const raw of input.series.slice(0, CHART_MAX_SERIES)) {\n if (!isRecord(raw)) return null;\n const name = cleanString(raw.name, LABEL_MAX_CHARS);\n const values = cleanNumberArray(raw.values, CHART_MAX_POINTS);\n if (!name || !values) return null;\n // Every series aligns with the label axis; pad/trim mismatches drop.\n if (values.length !== labels.length) return null;\n series.push({ name, values });\n }\n // Donut: one series, non-negative slices.\n if (type === \"donut\") {\n const [only] = series;\n if (series.length !== 1 || !only) return null;\n if (only.values.some((value) => value < 0)) return null;\n }\n\n const spec: ChartSpec = { labels, series, title, type };\n const unitPrefix = cleanString(input.unitPrefix, UNIT_MAX_CHARS);\n const unitSuffix = cleanString(input.unitSuffix, UNIT_MAX_CHARS);\n if (unitPrefix) spec.unitPrefix = unitPrefix;\n if (unitSuffix) spec.unitSuffix = unitSuffix;\n const actions = parseUiActions(input.actions);\n if (actions) spec.actions = actions;\n\n return spec;\n};\n\nexport const parseTableSpec = (input: unknown): TableSpec | null => {\n if (!isRecord(input)) return null;\n const columns = cleanStringArray(\n input.columns,\n TABLE_MAX_COLUMNS,\n LABEL_MAX_CHARS,\n );\n if (!columns) return null;\n if (!Array.isArray(input.rows) || input.rows.length === 0) return null;\n const rows: string[][] = [];\n for (const raw of input.rows.slice(0, TABLE_MAX_ROWS)) {\n const cells = cleanStringArray(raw, TABLE_MAX_COLUMNS, CELL_MAX_CHARS);\n if (!cells) return null;\n // Normalize ragged rows to the header width.\n while (cells.length < columns.length) cells.push(\"\");\n rows.push(cells.slice(0, columns.length));\n }\n\n const spec: TableSpec = { columns, rows };\n const title = cleanString(input.title, TITLE_MAX_CHARS);\n if (title) spec.title = title;\n const actions = parseUiActions(input.actions);\n if (actions) spec.actions = actions;\n\n return spec;\n};\n\nexport const parseStatTilesSpec = (input: unknown): StatTilesSpec | null => {\n if (!isRecord(input)) return null;\n if (!Array.isArray(input.tiles) || input.tiles.length === 0) return null;\n const tiles: StatTile[] = [];\n for (const raw of input.tiles.slice(0, STAT_TILES_MAX)) {\n if (!isRecord(raw)) return null;\n const label = cleanString(raw.label, LABEL_MAX_CHARS);\n const value = cleanString(raw.value, LABEL_MAX_CHARS);\n if (!label || !value) return null;\n const tile: StatTile = { label, value };\n const delta = cleanString(raw.delta, LABEL_MAX_CHARS);\n if (delta) tile.delta = delta;\n if (\n raw.deltaDirection === \"up\" ||\n raw.deltaDirection === \"down\" ||\n raw.deltaDirection === \"flat\"\n ) {\n tile.deltaDirection = raw.deltaDirection;\n }\n tiles.push(tile);\n }\n\n const spec: StatTilesSpec = { tiles };\n const actions = parseUiActions(input.actions);\n if (actions) spec.actions = actions;\n\n return spec;\n};\n\nconst SERIES_SCHEMA = {\n properties: {\n name: { description: \"Series name (shown in the legend)\", type: \"string\" },\n values: {\n description: \"One number per label, same order as labels\",\n items: { type: \"number\" },\n type: \"array\",\n },\n },\n required: [\"name\", \"values\"],\n type: \"object\",\n};\n\n/** render_chart — bar / line / donut from data you already have. */\nexport const chartCard: UiCardDefinition<ChartSpec> = {\n ack: \"(chart rendered inline — do not repeat its numbers as text; add at most a 1-2 line takeaway)\",\n description:\n \"Render a real chart inline in the chat from data you have (tool results, the conversation). Use whenever numbers COMPARE or TREND: revenue by partner (bar), pipeline over time (line), share of a whole (donut). Rules: bar/line take up to 8 series aligned to the same labels; donut takes exactly ONE series of non-negative values (one slice per label). Prefer a chart over a wall of numbers, but never invent data for it.\",\n inputSchema: {\n properties: {\n actions: ACTIONS_SCHEMA,\n labels: {\n description:\n \"Category labels — x-axis for bar/line, slice names for donut (max 24)\",\n items: { type: \"string\" },\n type: \"array\",\n },\n series: {\n description: \"Data series (max 8; donut exactly 1)\",\n items: SERIES_SCHEMA,\n type: \"array\",\n },\n title: { description: \"Short chart title\", type: \"string\" },\n type: { enum: [...CHART_TYPES], type: \"string\" },\n unitPrefix: {\n description: 'Prepended to values, e.g. \"$\"',\n type: \"string\",\n },\n unitSuffix: {\n description: 'Appended to values, e.g. \"%\"',\n type: \"string\",\n },\n },\n required: [\"type\", \"title\", \"labels\", \"series\"],\n type: \"object\",\n },\n name: \"render_chart\",\n parse: parseChartSpec,\n};\n\n/** render_table — a compact data table. */\nexport const tableCard: UiCardDefinition<TableSpec> = {\n ack: \"(table rendered inline — do not repeat its rows as text)\",\n description:\n \"Render a compact data table inline in the chat (max 8 columns × 30 rows). Use for structured comparisons the member will scan — matches side by side, deal terms, task lists with dates. All cells are strings; format numbers yourself.\",\n inputSchema: {\n properties: {\n actions: ACTIONS_SCHEMA,\n columns: {\n description: \"Column headers (max 8)\",\n items: { type: \"string\" },\n type: \"array\",\n },\n rows: {\n description: \"Rows of cells, each aligned to columns (max 30)\",\n items: { items: { type: \"string\" }, type: \"array\" },\n type: \"array\",\n },\n title: { description: \"Optional table title\", type: \"string\" },\n },\n required: [\"columns\", \"rows\"],\n type: \"object\",\n },\n name: \"render_table\",\n parse: parseTableSpec,\n};\n\n/** render_stat_tiles — a row of headline numbers. */\nexport const statTilesCard: UiCardDefinition<StatTilesSpec> = {\n ack: \"(stat tiles rendered inline — do not repeat the numbers as text)\",\n description:\n \"Render a row of headline stat tiles inline in the chat (max 6): a label, a big value, and an optional delta with direction. Use for the 2-4 numbers that ARE the answer — total attributed revenue, pipeline value, credits remaining — instead of burying them in prose.\",\n inputSchema: {\n properties: {\n actions: ACTIONS_SCHEMA,\n tiles: {\n description: \"The tiles (max 6)\",\n items: {\n properties: {\n delta: {\n description: 'Optional change note, e.g. \"+12% vs last month\"',\n type: \"string\",\n },\n deltaDirection: { enum: [\"up\", \"down\", \"flat\"], type: \"string\" },\n label: { description: \"What the number is\", type: \"string\" },\n value: {\n description: 'The formatted headline value, e.g. \"$42,300\"',\n type: \"string\",\n },\n },\n required: [\"label\", \"value\"],\n type: \"object\",\n },\n type: \"array\",\n },\n },\n required: [\"tiles\"],\n type: \"object\",\n },\n name: \"render_stat_tiles\",\n parse: parseStatTilesSpec,\n};\n\n/** The built-in catalog, ready for createUiCards. */\nexport const BUILTIN_UI_CARDS = [chartCard, tableCard, statTilesCard] as const;\n",
|
|
7
7
|
"import type { ChartSpec } from \"./catalog\";\n\n/**\n * Dependency-free default chart renderer: a validated ChartSpec in, a\n * self-contained SVG string out. Pure — no DOM — so it runs server-side or in\n * any framework component (call it client-side with the viewer's mode so dark\n * themes get the dark-stepped palette, not an automatic flip).\n *\n * Design method: thin marks with rounded data-ends, 2px surface gaps between\n * adjacent fills, recessive horizontal grid, a legend for ≥2 series plus\n * direct labels, all text in text tokens (never series colors), native <title>\n * hover tooltips per mark. The default palette is the validated reference set\n * (worst adjacent CVD ΔE 24.2 light / 10.3 dark) — override `palette` with\n * your brand's VALIDATED hues, in their fixed slot order.\n */\n\nexport type UiSvgTheme = {\n /** Categorical hues in fixed slot order (series 1..n). */\n palette: string[];\n surface: string;\n textPrimary: string;\n textSecondary: string;\n grid: string;\n};\n\nexport const LIGHT_UI_THEME: UiSvgTheme = {\n grid: \"#e4e4e0\",\n palette: [\n \"#2a78d6\",\n \"#1baf7a\",\n \"#eda100\",\n \"#008300\",\n \"#4a3aa7\",\n \"#e34948\",\n \"#e87ba4\",\n \"#eb6834\",\n ],\n surface: \"#fcfcfb\",\n textPrimary: \"#0b0b0b\",\n textSecondary: \"#52514e\",\n};\n\nexport const DARK_UI_THEME: UiSvgTheme = {\n grid: \"#333331\",\n palette: [\n \"#3987e5\",\n \"#199e70\",\n \"#c98500\",\n \"#008300\",\n \"#9085e9\",\n \"#e66767\",\n \"#d55181\",\n \"#d95926\",\n ],\n surface: \"#1a1a19\",\n textPrimary: \"#ffffff\",\n textSecondary: \"#c3c2b7\",\n};\n\nexport type RenderChartSvgOptions = {\n mode?: \"light\" | \"dark\";\n /** Override any theme slot (e.g. your brand palette / chat-bubble surface). */\n theme?: Partial<UiSvgTheme>;\n width?: number;\n height?: number;\n};\n\nconst WIDTH = 640;\nconst HEIGHT = 340;\nconst MARGIN = { bottom: 42, left: 56, right: 16, top: 64 };\nconst BAR_END_RADIUS = 4;\nconst MARK_GAP = 2;\nconst LINE_WIDTH = 2;\nconst MAX_DIRECT_LABELED_SERIES = 4;\nconst TICK_TARGET = 4;\nconst FONT =\n \"system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif\";\n\nconst escapeXml = (value: string) =>\n value\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\");\n\nconst formatValue = (value: number, spec: ChartSpec) => {\n // Sign leads the unit (\"-$4k\", not \"$-4000\").\n const sign = value < 0 ? \"-\" : \"\";\n const abs = Math.abs(value);\n const compact =\n abs >= 1_000_000\n ? `${(abs / 1_000_000).toFixed(1).replace(/\\.0$/, \"\")}M`\n : abs >= 10_000\n ? `${(abs / 1_000).toFixed(1).replace(/\\.0$/, \"\")}k`\n : abs >= 1_000\n ? abs.toLocaleString(\"en-US\")\n : `${Number.isInteger(abs) ? abs : abs.toFixed(1)}`;\n\n return `${sign}${spec.unitPrefix ?? \"\"}${compact}${spec.unitSuffix ?? \"\"}`;\n};\n\n// \"Nice\" tick step: 1/2/5 × 10^n covering the domain in ~TICK_TARGET steps.\nconst niceTicks = (min: number, max: number) => {\n const span = max - min || 1;\n const rough = span / TICK_TARGET;\n const power = Math.pow(10, Math.floor(Math.log10(rough)));\n const candidates = [1, 2, 5, 10].map((step) => step * power);\n const step =\n candidates.find((candidate) => candidate >= rough) ??\n candidates[candidates.length - 1] ??\n rough;\n const start = Math.floor(min / step) * step;\n const ticks: number[] = [];\n for (let tick = start; tick <= max + step / 2; tick += step) {\n ticks.push(Math.abs(tick) < step / 1e6 ? 0 : tick);\n }\n\n return ticks;\n};\n\ntype Frame = {\n theme: UiSvgTheme;\n plotLeft: number;\n plotRight: number;\n plotTop: number;\n plotBottom: number;\n};\n\nconst headerSvg = (spec: ChartSpec, frame: Frame) => {\n const { theme } = frame;\n const parts = [\n `<text x=\"${frame.plotLeft}\" y=\"24\" fill=\"${theme.textPrimary}\" font-size=\"15\" font-weight=\"600\">${escapeXml(spec.title)}</text>`,\n ];\n // Legend only when identity needs it: 2+ series (a single series is named\n // by the title). Swatch + name in text ink, never colored text.\n if (spec.series.length > 1) {\n let x = frame.plotLeft;\n const swatches = spec.series.map((series, index) => {\n const color = theme.palette[index % theme.palette.length];\n const label = escapeXml(series.name);\n const item = `<rect x=\"${x}\" y=\"38\" width=\"10\" height=\"10\" rx=\"2\" fill=\"${color}\"/><text x=\"${x + 14}\" y=\"47\" fill=\"${theme.textSecondary}\" font-size=\"11\">${label}</text>`;\n x += 14 + series.name.length * 6 + 18;\n\n return item;\n });\n parts.push(...swatches);\n }\n\n return parts.join(\"\");\n};\n\nconst gridSvg = (\n ticks: number[],\n yFor: (value: number) => number,\n spec: ChartSpec,\n frame: Frame,\n) =>\n ticks\n .map((tick) => {\n const y = yFor(tick);\n const isZero = tick === 0;\n\n return `<line x1=\"${frame.plotLeft}\" y1=\"${y}\" x2=\"${frame.plotRight}\" y2=\"${y}\" stroke=\"${isZero ? frame.theme.textSecondary : frame.theme.grid}\" stroke-width=\"1\"/><text x=\"${frame.plotLeft - 8}\" y=\"${y + 3.5}\" fill=\"${frame.theme.textSecondary}\" font-size=\"10\" text-anchor=\"end\">${escapeXml(formatValue(tick, spec))}</text>`;\n })\n .join(\"\");\n\nconst xLabelsSvg = (\n spec: ChartSpec,\n xCenter: (index: number) => number,\n frame: Frame,\n) => {\n // Thin out crowded label axes instead of colliding.\n const every = Math.ceil(spec.labels.length / 12);\n\n return spec.labels\n .map((label, index) => {\n if (index % every !== 0) return \"\";\n const short = label.length > 12 ? `${label.slice(0, 11)}…` : label;\n\n return `<text x=\"${xCenter(index)}\" y=\"${frame.plotBottom + 18}\" fill=\"${frame.theme.textSecondary}\" font-size=\"10\" text-anchor=\"middle\">${escapeXml(short)}</text>`;\n })\n .join(\"\");\n};\n\n// Bar with a rounded TOP data-end anchored to the baseline (flipped when the\n// value is negative). Radius collapses on very short bars.\nconst barPath = (\n x: number,\n yValue: number,\n yBase: number,\n width: number,\n): string => {\n const up = yValue <= yBase;\n const top = Math.min(yValue, yBase);\n const bottom = Math.max(yValue, yBase);\n const radius = Math.min(BAR_END_RADIUS, width / 2, bottom - top);\n if (radius <= 0) return \"\";\n if (up) {\n return `M${x},${bottom} L${x},${top + radius} Q${x},${top} ${x + radius},${top} L${x + width - radius},${top} Q${x + width},${top} ${x + width},${top + radius} L${x + width},${bottom} Z`;\n }\n\n return `M${x},${top} L${x},${bottom - radius} Q${x},${bottom} ${x + radius},${bottom} L${x + width - radius},${bottom} Q${x + width},${bottom} ${x + width},${bottom - radius} L${x + width},${top} Z`;\n};\n\nconst valueDomain = (spec: ChartSpec) => {\n const all = spec.series.flatMap((series) => series.values);\n const min = Math.min(0, ...all);\n const max = Math.max(0, ...all);\n\n return max === min ? { max: min + 1, min } : { max, min };\n};\n\nconst cartesianSvg = (spec: ChartSpec, frame: Frame) => {\n const { theme } = frame;\n const domain = valueDomain(spec);\n const ticks = niceTicks(domain.min, domain.max);\n const lo = Math.min(domain.min, ticks[0] ?? domain.min);\n const hi = Math.max(domain.max, ticks[ticks.length - 1] ?? domain.max);\n const yFor = (value: number) =>\n frame.plotBottom -\n ((value - lo) / (hi - lo)) * (frame.plotBottom - frame.plotTop);\n const slot = (frame.plotRight - frame.plotLeft) / spec.labels.length;\n const xCenter = (index: number) => frame.plotLeft + slot * (index + 0.5);\n\n const parts: string[] = [gridSvg(ticks, yFor, spec, frame)];\n\n if (spec.type === \"bar\") {\n const group = Math.min(slot * 0.72, 64);\n const barWidth = Math.max(\n 2,\n (group - MARK_GAP * (spec.series.length - 1)) / spec.series.length,\n );\n const yBase = yFor(Math.max(lo, Math.min(hi, 0)));\n spec.series.forEach((series, seriesIndex) => {\n const color = theme.palette[seriesIndex % theme.palette.length];\n series.values.forEach((value, index) => {\n const x =\n xCenter(index) - group / 2 + seriesIndex * (barWidth + MARK_GAP);\n const tooltip = `${escapeXml(series.name)} · ${escapeXml(spec.labels[index] ?? \"\")}: ${escapeXml(formatValue(value, spec))}`;\n\n parts.push(\n `<path d=\"${barPath(x, yFor(value), yBase, barWidth)}\" fill=\"${color}\"><title>${tooltip}</title></path>`,\n );\n });\n });\n // Selective direct labels: single series with few bars gets its values.\n const [only] = spec.series;\n if (spec.series.length === 1 && only && spec.labels.length <= 8) {\n only.values.forEach((value, index) => {\n const above = value >= 0;\n parts.push(\n `<text x=\"${xCenter(index)}\" y=\"${yFor(value) + (above ? -6 : 14)}\" fill=\"${theme.textSecondary}\" font-size=\"10\" text-anchor=\"middle\">${escapeXml(formatValue(value, spec))}</text>`,\n );\n });\n }\n } else {\n spec.series.forEach((series, seriesIndex) => {\n const color = theme.palette[seriesIndex % theme.palette.length];\n const points = series.values.map(\n (value, index) => `${xCenter(index)},${yFor(value)}`,\n );\n parts.push(\n `<polyline points=\"${points.join(\" \")}\" fill=\"none\" stroke=\"${color}\" stroke-width=\"${LINE_WIDTH}\" stroke-linejoin=\"round\" stroke-linecap=\"round\"/>`,\n );\n series.values.forEach((value, index) => {\n const tooltip = `${escapeXml(series.name)} · ${escapeXml(spec.labels[index] ?? \"\")}: ${escapeXml(formatValue(value, spec))}`;\n // ≥8px hover targets with a 2px surface ring where marks may overlap.\n parts.push(\n `<circle cx=\"${xCenter(index)}\" cy=\"${yFor(value)}\" r=\"4\" fill=\"${color}\" stroke=\"${theme.surface}\" stroke-width=\"2\"><title>${tooltip}</title></circle>`,\n );\n });\n // Direct series label at the line's end for small multiples.\n const last = series.values[series.values.length - 1];\n if (\n spec.series.length <= MAX_DIRECT_LABELED_SERIES &&\n last !== undefined\n ) {\n parts.push(\n `<text x=\"${frame.plotRight + 4}\" y=\"${yFor(last) + 3.5}\" fill=\"${theme.textSecondary}\" font-size=\"10\">${escapeXml(series.name)}</text>`,\n );\n }\n });\n }\n parts.push(xLabelsSvg(spec, xCenter, frame));\n\n return parts.join(\"\");\n};\n\nconst donutSvg = (spec: ChartSpec, frame: Frame) => {\n const { theme } = frame;\n const [series] = spec.series;\n if (!series) return \"\";\n const total = series.values.reduce((sum, value) => sum + value, 0);\n if (total <= 0) return \"\";\n const cx = (frame.plotLeft + frame.plotRight) / 2;\n const cy = (frame.plotTop + frame.plotBottom) / 2 + 4;\n const radius = Math.min(\n (frame.plotBottom - frame.plotTop) / 2 - 4,\n (frame.plotRight - frame.plotLeft) / 4,\n );\n const ring = Math.max(14, radius * 0.34);\n const mid = radius - ring / 2;\n // 2px surface gap between segments, expressed as an angle at mid-radius.\n const gapAngle = MARK_GAP / mid;\n\n const parts: string[] = [];\n let angle = -Math.PI / 2;\n series.values.forEach((value, index) => {\n const sweep = (value / total) * Math.PI * 2;\n const start = angle + gapAngle / 2;\n const end = angle + sweep - gapAngle / 2;\n angle += sweep;\n if (end <= start) return;\n const large = end - start > Math.PI ? 1 : 0;\n const x1 = cx + mid * Math.cos(start);\n const y1 = cy + mid * Math.sin(start);\n const x2 = cx + mid * Math.cos(end);\n const y2 = cy + mid * Math.sin(end);\n const color = theme.palette[index % theme.palette.length];\n const share = `${Math.round((value / total) * 100)}%`;\n const tooltip = `${escapeXml(spec.labels[index] ?? \"\")}: ${escapeXml(formatValue(value, spec))} (${share})`;\n parts.push(\n `<path d=\"M${x1},${y1} A${mid},${mid} 0 ${large} 1 ${x2},${y2}\" fill=\"none\" stroke=\"${color}\" stroke-width=\"${ring}\"><title>${tooltip}</title></path>`,\n );\n });\n parts.push(\n `<text x=\"${cx}\" y=\"${cy + 5}\" fill=\"${theme.textPrimary}\" font-size=\"16\" font-weight=\"600\" text-anchor=\"middle\">${escapeXml(formatValue(total, spec))}</text>`,\n );\n // Slice identity lives in the legend row for donuts.\n let x = frame.plotLeft;\n spec.labels.forEach((label, index) => {\n const color = theme.palette[index % theme.palette.length];\n parts.push(\n `<rect x=\"${x}\" y=\"38\" width=\"10\" height=\"10\" rx=\"2\" fill=\"${color}\"/><text x=\"${x + 14}\" y=\"47\" fill=\"${theme.textSecondary}\" font-size=\"11\">${escapeXml(label)}</text>`,\n );\n x += 14 + label.length * 6 + 18;\n });\n\n return parts.join(\"\");\n};\n\n/** Render a validated ChartSpec to a self-contained SVG string. */\nexport const renderChartSvg = (\n spec: ChartSpec,\n options: RenderChartSvgOptions = {},\n) => {\n const base = options.mode === \"dark\" ? DARK_UI_THEME : LIGHT_UI_THEME;\n const theme: UiSvgTheme = { ...base, ...options.theme };\n const width = options.width ?? WIDTH;\n const height = options.height ?? HEIGHT;\n const frame: Frame = {\n plotBottom: height - MARGIN.bottom,\n plotLeft: MARGIN.left,\n plotRight:\n width -\n MARGIN.right -\n // Room for end-of-line direct labels.\n (spec.type === \"line\" ? 64 : 0),\n plotTop: MARGIN.top,\n theme,\n };\n\n const body =\n spec.type === \"donut\" ? donutSvg(spec, frame) : cartesianSvg(spec, frame);\n\n return `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 ${width} ${height}\" role=\"img\" aria-label=\"${escapeXml(spec.title)}\" font-family=\"${FONT}\"><rect width=\"${width}\" height=\"${height}\" fill=\"${theme.surface}\" rx=\"12\"/>${spec.type === \"donut\" ? headerSvg({ ...spec, series: [] }, frame) : headerSvg(spec, frame)}${body}</svg>`;\n};\n"
|
|
8
8
|
],
|
|
9
|
-
"mappings": "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",
|
|
10
|
-
"debugId": "
|
|
9
|
+
"mappings": "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",
|
|
10
|
+
"debugId": "361FE26314A51E4B64756E2164756E21",
|
|
11
11
|
"names": []
|
|
12
12
|
}
|
|
@@ -21,11 +21,15 @@ export type ChartSpec = {
|
|
|
21
21
|
/** Value formatting, e.g. "$" / "%". */
|
|
22
22
|
unitPrefix?: string;
|
|
23
23
|
unitSuffix?: string;
|
|
24
|
+
/** Optional action buttons rendered under the card (≤ 3). */
|
|
25
|
+
actions?: UiAction[];
|
|
24
26
|
};
|
|
25
27
|
export type TableSpec = {
|
|
26
28
|
title?: string;
|
|
27
29
|
columns: string[];
|
|
28
30
|
rows: string[][];
|
|
31
|
+
/** Optional action buttons rendered under the card (≤ 3). */
|
|
32
|
+
actions?: UiAction[];
|
|
29
33
|
};
|
|
30
34
|
export type StatTile = {
|
|
31
35
|
label: string;
|
|
@@ -36,12 +40,33 @@ export type StatTile = {
|
|
|
36
40
|
};
|
|
37
41
|
export type StatTilesSpec = {
|
|
38
42
|
tiles: StatTile[];
|
|
43
|
+
actions?: UiAction[];
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* An action binding on a UI card: a button the host renders under the card
|
|
47
|
+
* that, on click, invokes one of the HOST'S OWN tools with a model-authored
|
|
48
|
+
* input. The host decides which tools are click-invokable (approval-gated
|
|
49
|
+
* tools should queue their normal approval flow, and anything like "approve a
|
|
50
|
+
* pending action" should be refused outright) and validates the input against
|
|
51
|
+
* the tool exactly as if the model had called it.
|
|
52
|
+
*/
|
|
53
|
+
export type UiAction = {
|
|
54
|
+
/** Button label, e.g. "Create follow-up task". */
|
|
55
|
+
label: string;
|
|
56
|
+
/** The host tool to invoke, e.g. "create_task". */
|
|
57
|
+
tool: string;
|
|
58
|
+
/** The tool input, fully resolved by the model (real ids, not placeholders). */
|
|
59
|
+
input: Record<string, unknown>;
|
|
39
60
|
};
|
|
40
61
|
export declare const CHART_MAX_SERIES = 8;
|
|
41
62
|
export declare const CHART_MAX_POINTS = 24;
|
|
42
63
|
export declare const TABLE_MAX_COLUMNS = 8;
|
|
43
64
|
export declare const TABLE_MAX_ROWS = 30;
|
|
44
65
|
export declare const STAT_TILES_MAX = 6;
|
|
66
|
+
export declare const UI_ACTIONS_MAX = 3;
|
|
67
|
+
/** Validate a spec's optional action bindings; undefined when none/invalid.
|
|
68
|
+
* Malformed entries drop individually — a bad button never sinks the card. */
|
|
69
|
+
export declare const parseUiActions: (value: unknown) => UiAction[] | undefined;
|
|
45
70
|
export declare const parseChartSpec: (input: unknown) => ChartSpec | null;
|
|
46
71
|
export declare const parseTableSpec: (input: unknown) => TableSpec | null;
|
|
47
72
|
export declare const parseStatTilesSpec: (input: unknown) => StatTilesSpec | null;
|
|
@@ -9,5 +9,5 @@
|
|
|
9
9
|
* default chart renderer (pure string — server or client, light/dark).
|
|
10
10
|
*/
|
|
11
11
|
export { createUiCards, type UiCardDefinition, type UiCardEvent, type UiCards, } from "./uiCards";
|
|
12
|
-
export { BUILTIN_UI_CARDS, chartCard, CHART_MAX_POINTS, CHART_MAX_SERIES, CHART_TYPES, parseChartSpec, parseStatTilesSpec, parseTableSpec, STAT_TILES_MAX, statTilesCard, TABLE_MAX_COLUMNS, TABLE_MAX_ROWS, tableCard, type ChartSeries, type ChartSpec, type ChartType, type StatTile, type StatTilesSpec, type TableSpec, } from "./catalog";
|
|
12
|
+
export { BUILTIN_UI_CARDS, chartCard, CHART_MAX_POINTS, CHART_MAX_SERIES, CHART_TYPES, parseChartSpec, parseStatTilesSpec, parseTableSpec, parseUiActions, STAT_TILES_MAX, statTilesCard, TABLE_MAX_COLUMNS, TABLE_MAX_ROWS, tableCard, UI_ACTIONS_MAX, type ChartSeries, type ChartSpec, type ChartType, type StatTile, type StatTilesSpec, type TableSpec, type UiAction, } from "./catalog";
|
|
13
13
|
export { DARK_UI_THEME, LIGHT_UI_THEME, renderChartSvg, type RenderChartSvgOptions, type UiSvgTheme, } from "./svg";
|