@vertesia/fusion-ux 1.3.0 → 1.4.0-dev.20260615.042033Z
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/LICENSE +198 -10
- package/lib/fusion-fragment/ChartRenderer.d.ts.map +1 -0
- package/lib/{esm/fusion-fragment → fusion-fragment}/ChartRenderer.js +8 -6
- package/lib/fusion-fragment/ChartRenderer.js.map +1 -0
- package/lib/{types/fusion-fragment → fusion-fragment}/FieldRenderer.d.ts +1 -1
- package/lib/fusion-fragment/FieldRenderer.d.ts.map +1 -0
- package/lib/{esm/fusion-fragment → fusion-fragment}/FieldRenderer.js +14 -8
- package/lib/fusion-fragment/FieldRenderer.js.map +1 -0
- package/lib/{types/fusion-fragment → fusion-fragment}/FusionFragmentContext.d.ts +3 -3
- package/lib/fusion-fragment/FusionFragmentContext.d.ts.map +1 -0
- package/lib/{esm/fusion-fragment → fusion-fragment}/FusionFragmentContext.js +2 -2
- package/lib/fusion-fragment/FusionFragmentContext.js.map +1 -0
- package/lib/fusion-fragment/FusionFragmentHandler.d.ts.map +1 -0
- package/lib/{esm/fusion-fragment → fusion-fragment}/FusionFragmentHandler.js +7 -14
- package/lib/fusion-fragment/FusionFragmentHandler.js.map +1 -0
- package/lib/fusion-fragment/FusionFragmentRenderer.d.ts.map +1 -0
- package/lib/{esm/fusion-fragment → fusion-fragment}/FusionFragmentRenderer.js +2 -2
- package/lib/fusion-fragment/FusionFragmentRenderer.js.map +1 -0
- package/lib/{types/fusion-fragment → fusion-fragment}/SectionRenderer.d.ts +1 -1
- package/lib/fusion-fragment/SectionRenderer.d.ts.map +1 -0
- package/lib/{esm/fusion-fragment → fusion-fragment}/SectionRenderer.js +12 -5
- package/lib/fusion-fragment/SectionRenderer.js.map +1 -0
- package/lib/fusion-fragment/TableRenderer.d.ts.map +1 -0
- package/lib/{esm/fusion-fragment → fusion-fragment}/TableRenderer.js +9 -7
- package/lib/fusion-fragment/TableRenderer.js.map +1 -0
- package/lib/{types/fusion-fragment → fusion-fragment}/index.d.ts +4 -4
- package/lib/fusion-fragment/index.d.ts.map +1 -0
- package/lib/{esm/fusion-fragment → fusion-fragment}/index.js +4 -4
- package/lib/fusion-fragment/index.js.map +1 -0
- package/lib/{types/index.d.ts → index.d.ts} +4 -4
- package/lib/index.d.ts.map +1 -0
- package/lib/{esm/index.js → index.js} +4 -4
- package/lib/index.js.map +1 -0
- package/lib/{types/render → render}/index.d.ts +1 -1
- package/lib/render/index.d.ts.map +1 -0
- package/lib/{esm/render → render}/index.js +1 -1
- package/lib/render/index.js.map +1 -0
- package/lib/render/textPreview.d.ts.map +1 -0
- package/lib/{esm/render → render}/textPreview.js +12 -9
- package/lib/render/textPreview.js.map +1 -0
- package/lib/types.d.ts.map +1 -0
- package/lib/types.js.map +1 -0
- package/lib/validation/formatErrors.d.ts.map +1 -0
- package/lib/{esm/validation → validation}/formatErrors.js +1 -1
- package/lib/validation/formatErrors.js.map +1 -0
- package/lib/validation/fuzzyMatch.d.ts.map +1 -0
- package/lib/{esm/validation → validation}/fuzzyMatch.js +3 -4
- package/lib/validation/fuzzyMatch.js.map +1 -0
- package/lib/validation/index.d.ts +8 -0
- package/lib/validation/index.d.ts.map +1 -0
- package/lib/validation/index.js +8 -0
- package/lib/validation/index.js.map +1 -0
- package/lib/{types/validation → validation}/schemas.d.ts +1 -1
- package/lib/validation/schemas.d.ts.map +1 -0
- package/lib/{esm/validation → validation}/schemas.js +25 -25
- package/lib/validation/schemas.js.map +1 -0
- package/lib/validation/validateTemplate.d.ts.map +1 -0
- package/lib/{esm/validation → validation}/validateTemplate.js +23 -21
- package/lib/validation/validateTemplate.js.map +1 -0
- package/lib/vertesia-fusion-ux.js +1 -1
- package/lib/vertesia-fusion-ux.js.map +1 -1
- package/package.json +23 -35
- package/src/fusion-fragment/ChartRenderer.tsx +95 -96
- package/src/fusion-fragment/FieldRenderer.tsx +173 -174
- package/src/fusion-fragment/FusionFragmentContext.tsx +31 -37
- package/src/fusion-fragment/FusionFragmentHandler.tsx +214 -223
- package/src/fusion-fragment/FusionFragmentRenderer.tsx +102 -107
- package/src/fusion-fragment/SectionRenderer.tsx +174 -169
- package/src/fusion-fragment/TableRenderer.tsx +175 -171
- package/src/fusion-fragment/index.ts +11 -11
- package/src/index.ts +42 -45
- package/src/render/index.ts +3 -3
- package/src/render/textPreview.ts +183 -186
- package/src/types.ts +174 -174
- package/src/validation/formatErrors.ts +86 -86
- package/src/validation/fuzzyMatch.ts +69 -77
- package/src/validation/index.ts +3 -3
- package/src/validation/schemas.ts +120 -120
- package/src/validation/validateTemplate.ts +225 -226
- package/lib/esm/fusion-fragment/ChartRenderer.js.map +0 -1
- package/lib/esm/fusion-fragment/FieldRenderer.js.map +0 -1
- package/lib/esm/fusion-fragment/FusionFragmentContext.js.map +0 -1
- package/lib/esm/fusion-fragment/FusionFragmentHandler.js.map +0 -1
- package/lib/esm/fusion-fragment/FusionFragmentRenderer.js.map +0 -1
- package/lib/esm/fusion-fragment/SectionRenderer.js.map +0 -1
- package/lib/esm/fusion-fragment/TableRenderer.js.map +0 -1
- package/lib/esm/fusion-fragment/index.js.map +0 -1
- package/lib/esm/index.js.map +0 -1
- package/lib/esm/render/index.js.map +0 -1
- package/lib/esm/render/textPreview.js.map +0 -1
- package/lib/esm/types.js.map +0 -1
- package/lib/esm/validation/formatErrors.js.map +0 -1
- package/lib/esm/validation/fuzzyMatch.js.map +0 -1
- package/lib/esm/validation/index.js +0 -8
- package/lib/esm/validation/index.js.map +0 -1
- package/lib/esm/validation/schemas.js.map +0 -1
- package/lib/esm/validation/validateTemplate.js.map +0 -1
- package/lib/tsconfig.tsbuildinfo +0 -1
- package/lib/types/fusion-fragment/ChartRenderer.d.ts.map +0 -1
- package/lib/types/fusion-fragment/FieldRenderer.d.ts.map +0 -1
- package/lib/types/fusion-fragment/FusionFragmentContext.d.ts.map +0 -1
- package/lib/types/fusion-fragment/FusionFragmentHandler.d.ts.map +0 -1
- package/lib/types/fusion-fragment/FusionFragmentRenderer.d.ts.map +0 -1
- package/lib/types/fusion-fragment/SectionRenderer.d.ts.map +0 -1
- package/lib/types/fusion-fragment/TableRenderer.d.ts.map +0 -1
- package/lib/types/fusion-fragment/index.d.ts.map +0 -1
- package/lib/types/index.d.ts.map +0 -1
- package/lib/types/render/index.d.ts.map +0 -1
- package/lib/types/render/textPreview.d.ts.map +0 -1
- package/lib/types/types.d.ts.map +0 -1
- package/lib/types/validation/formatErrors.d.ts.map +0 -1
- package/lib/types/validation/fuzzyMatch.d.ts.map +0 -1
- package/lib/types/validation/index.d.ts +0 -8
- package/lib/types/validation/index.d.ts.map +0 -1
- package/lib/types/validation/schemas.d.ts.map +0 -1
- package/lib/types/validation/validateTemplate.d.ts.map +0 -1
- /package/lib/{types/fusion-fragment → fusion-fragment}/ChartRenderer.d.ts +0 -0
- /package/lib/{types/fusion-fragment → fusion-fragment}/FusionFragmentHandler.d.ts +0 -0
- /package/lib/{types/fusion-fragment → fusion-fragment}/FusionFragmentRenderer.d.ts +0 -0
- /package/lib/{types/fusion-fragment → fusion-fragment}/TableRenderer.d.ts +0 -0
- /package/lib/{types/render → render}/textPreview.d.ts +0 -0
- /package/lib/{types/types.d.ts → types.d.ts} +0 -0
- /package/lib/{esm/types.js → types.js} +0 -0
- /package/lib/{types/validation → validation}/formatErrors.d.ts +0 -0
- /package/lib/{types/validation → validation}/fuzzyMatch.d.ts +0 -0
- /package/lib/{types/validation → validation}/validateTemplate.d.ts +0 -0
|
@@ -3,229 +3,226 @@
|
|
|
3
3
|
* Generates a text description of what the fragment will look like
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import type {
|
|
6
|
+
import type { FieldTemplate, FragmentTemplate } from '../types.js';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Generate sample data for preview rendering
|
|
10
10
|
* Creates placeholder values based on field definitions
|
|
11
11
|
*/
|
|
12
|
-
export function generateSampleData(
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
data[field.key] = getSampleValue(field);
|
|
12
|
+
export function generateSampleData(template: FragmentTemplate, dataKeys: string[]): Record<string, unknown> {
|
|
13
|
+
const data: Record<string, unknown> = {};
|
|
14
|
+
|
|
15
|
+
// Add provided data keys with placeholder values
|
|
16
|
+
for (const key of dataKeys) {
|
|
17
|
+
data[key] = `<${key}>`;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Override with more specific placeholders based on field format
|
|
21
|
+
for (const section of template.sections) {
|
|
22
|
+
if (section.fields) {
|
|
23
|
+
for (const field of section.fields) {
|
|
24
|
+
if (field.key in data) {
|
|
25
|
+
data[field.key] = getSampleValue(field);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
29
28
|
}
|
|
30
|
-
}
|
|
31
29
|
}
|
|
32
|
-
}
|
|
33
30
|
|
|
34
|
-
|
|
31
|
+
return data;
|
|
35
32
|
}
|
|
36
33
|
|
|
37
34
|
/**
|
|
38
35
|
* Get a sample value for a field based on its format
|
|
39
36
|
*/
|
|
40
37
|
function getSampleValue(field: FieldTemplate): unknown {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
}
|
|
38
|
+
switch (field.format) {
|
|
39
|
+
case 'number':
|
|
40
|
+
return 1234;
|
|
41
|
+
case 'currency':
|
|
42
|
+
return 1000000;
|
|
43
|
+
case 'percent':
|
|
44
|
+
return 25;
|
|
45
|
+
case 'date':
|
|
46
|
+
return new Date().toISOString().split('T')[0];
|
|
47
|
+
case 'boolean':
|
|
48
|
+
return true;
|
|
49
|
+
default:
|
|
50
|
+
return `Sample ${field.label}`;
|
|
51
|
+
}
|
|
56
52
|
}
|
|
57
53
|
|
|
58
54
|
/**
|
|
59
55
|
* Generate a text description of the template for preview
|
|
60
56
|
* Used for non-vision models
|
|
61
57
|
*/
|
|
62
|
-
export function generateTextPreview(
|
|
63
|
-
|
|
64
|
-
dataKeys: string[]
|
|
65
|
-
): string {
|
|
66
|
-
const lines: string[] = [];
|
|
58
|
+
export function generateTextPreview(template: FragmentTemplate, dataKeys: string[]): string {
|
|
59
|
+
const lines: string[] = [];
|
|
67
60
|
|
|
68
|
-
|
|
69
|
-
lines.push('');
|
|
70
|
-
|
|
71
|
-
if (template.title) {
|
|
72
|
-
lines.push(`## ${template.title}`);
|
|
61
|
+
lines.push('Template structure preview:');
|
|
73
62
|
lines.push('');
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
for (const section of template.sections) {
|
|
77
|
-
const layout = section.layout || 'grid-3';
|
|
78
|
-
|
|
79
|
-
lines.push(`### ${section.title}`);
|
|
80
|
-
|
|
81
|
-
if (layout === 'table') {
|
|
82
|
-
lines.push(`Layout: table`);
|
|
83
|
-
if (section.dataKey) {
|
|
84
|
-
lines.push(`Data key: \`${section.dataKey}\``);
|
|
85
|
-
}
|
|
86
|
-
lines.push('');
|
|
87
|
-
|
|
88
|
-
if (section.columns) {
|
|
89
|
-
lines.push('Columns:');
|
|
90
|
-
for (const col of section.columns) {
|
|
91
|
-
let colLine = `- **${col.header}** \u2192 \`${col.key}\``;
|
|
92
|
-
if (col.format && col.format !== 'text') {
|
|
93
|
-
colLine += ` (${col.format})`;
|
|
94
|
-
}
|
|
95
|
-
lines.push(colLine);
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
} else if (layout === 'chart') {
|
|
99
|
-
lines.push(`Layout: chart`);
|
|
100
|
-
if (section.chart) {
|
|
101
|
-
const chart = section.chart;
|
|
102
|
-
if (chart.title) {
|
|
103
|
-
lines.push(`Chart title: ${chart.title}`);
|
|
104
|
-
}
|
|
105
|
-
if (chart.description) {
|
|
106
|
-
lines.push(`Description: ${chart.description}`);
|
|
107
|
-
}
|
|
108
63
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
if (chart.dataKey) {
|
|
115
|
-
lines.push(`Data key: \`${chart.dataKey}\``);
|
|
116
|
-
if (!dataKeys.includes(chart.dataKey)) {
|
|
117
|
-
lines.push('\u26a0\ufe0f **dataKey not found in data**');
|
|
118
|
-
}
|
|
119
|
-
} else if (chart.spec.data?.values) {
|
|
120
|
-
lines.push(`Inline data: ${(chart.spec.data.values as unknown[]).length} points`);
|
|
121
|
-
}
|
|
64
|
+
if (template.title) {
|
|
65
|
+
lines.push(`## ${template.title}`);
|
|
66
|
+
lines.push('');
|
|
67
|
+
}
|
|
122
68
|
|
|
123
|
-
|
|
124
|
-
|
|
69
|
+
for (const section of template.sections) {
|
|
70
|
+
const layout = section.layout || 'grid-3';
|
|
71
|
+
|
|
72
|
+
lines.push(`### ${section.title}`);
|
|
73
|
+
|
|
74
|
+
if (layout === 'table') {
|
|
75
|
+
lines.push(`Layout: table`);
|
|
76
|
+
if (section.dataKey) {
|
|
77
|
+
lines.push(`Data key: \`${section.dataKey}\``);
|
|
78
|
+
}
|
|
79
|
+
lines.push('');
|
|
80
|
+
|
|
81
|
+
if (section.columns) {
|
|
82
|
+
lines.push('Columns:');
|
|
83
|
+
for (const col of section.columns) {
|
|
84
|
+
let colLine = `- **${col.header}** \u2192 \`${col.key}\``;
|
|
85
|
+
if (col.format && col.format !== 'text') {
|
|
86
|
+
colLine += ` (${col.format})`;
|
|
87
|
+
}
|
|
88
|
+
lines.push(colLine);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
} else if (layout === 'chart') {
|
|
92
|
+
lines.push(`Layout: chart`);
|
|
93
|
+
if (section.chart) {
|
|
94
|
+
const chart = section.chart;
|
|
95
|
+
if (chart.title) {
|
|
96
|
+
lines.push(`Chart title: ${chart.title}`);
|
|
97
|
+
}
|
|
98
|
+
if (chart.description) {
|
|
99
|
+
lines.push(`Description: ${chart.description}`);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const markType = chart.spec.mark
|
|
103
|
+
? typeof chart.spec.mark === 'string'
|
|
104
|
+
? chart.spec.mark
|
|
105
|
+
: (chart.spec.mark as { type?: string }).type || 'unknown'
|
|
106
|
+
: 'composite';
|
|
107
|
+
lines.push(`Chart type: ${markType}`);
|
|
108
|
+
|
|
109
|
+
if (chart.dataKey) {
|
|
110
|
+
lines.push(`Data key: \`${chart.dataKey}\``);
|
|
111
|
+
if (!dataKeys.includes(chart.dataKey)) {
|
|
112
|
+
lines.push('\u26a0\ufe0f **dataKey not found in data**');
|
|
113
|
+
}
|
|
114
|
+
} else if (chart.spec.data?.values) {
|
|
115
|
+
lines.push(`Inline data: ${(chart.spec.data.values as unknown[]).length} points`);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (chart.height) {
|
|
119
|
+
lines.push(`Height: ${chart.height}px`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
lines.push('');
|
|
123
|
+
} else {
|
|
124
|
+
const layoutDesc = layout === 'list' ? 'vertical list' : `${layout.split('-')[1]}-column grid`;
|
|
125
|
+
lines.push(`Layout: ${layoutDesc}${section.collapsed ? ' (collapsed by default)' : ''}`);
|
|
126
|
+
lines.push('');
|
|
127
|
+
|
|
128
|
+
if (section.fields) {
|
|
129
|
+
for (const field of section.fields) {
|
|
130
|
+
let fieldLine = `- **${field.label}** \u2192 \`${field.key}\``;
|
|
131
|
+
|
|
132
|
+
const attributes: string[] = [];
|
|
133
|
+
if (field.format && field.format !== 'text') {
|
|
134
|
+
attributes.push(field.format);
|
|
135
|
+
}
|
|
136
|
+
if (field.unit) {
|
|
137
|
+
attributes.push(`unit: "${field.unit}"`);
|
|
138
|
+
}
|
|
139
|
+
if (field.editable) {
|
|
140
|
+
attributes.push('editable');
|
|
141
|
+
}
|
|
142
|
+
if (field.highlight) {
|
|
143
|
+
attributes.push(`highlight: ${field.highlight}`);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (attributes.length > 0) {
|
|
147
|
+
fieldLine += ` (${attributes.join(', ')})`;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Check if key exists in data
|
|
151
|
+
if (!dataKeys.includes(field.key)) {
|
|
152
|
+
fieldLine += ' \u26a0\ufe0f **key not found in data**';
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
lines.push(fieldLine);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
125
158
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
} else {
|
|
129
|
-
const layoutDesc = layout === 'list' ? 'vertical list' : `${layout.split('-')[1]}-column grid`;
|
|
130
|
-
lines.push(`Layout: ${layoutDesc}${section.collapsed ? ' (collapsed by default)' : ''}`);
|
|
131
|
-
lines.push('');
|
|
132
|
-
|
|
133
|
-
if (section.fields) {
|
|
134
|
-
for (const field of section.fields) {
|
|
135
|
-
let fieldLine = `- **${field.label}** \u2192 \`${field.key}\``;
|
|
136
|
-
|
|
137
|
-
const attributes: string[] = [];
|
|
138
|
-
if (field.format && field.format !== 'text') {
|
|
139
|
-
attributes.push(field.format);
|
|
140
|
-
}
|
|
141
|
-
if (field.unit) {
|
|
142
|
-
attributes.push(`unit: "${field.unit}"`);
|
|
143
|
-
}
|
|
144
|
-
if (field.editable) {
|
|
145
|
-
attributes.push('editable');
|
|
146
|
-
}
|
|
147
|
-
if (field.highlight) {
|
|
148
|
-
attributes.push(`highlight: ${field.highlight}`);
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
if (attributes.length > 0) {
|
|
152
|
-
fieldLine += ` (${attributes.join(', ')})`;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
// Check if key exists in data
|
|
156
|
-
if (!dataKeys.includes(field.key)) {
|
|
157
|
-
fieldLine += ' \u26a0\ufe0f **key not found in data**';
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
lines.push(fieldLine);
|
|
161
|
-
}
|
|
162
|
-
}
|
|
159
|
+
|
|
160
|
+
lines.push('');
|
|
163
161
|
}
|
|
164
162
|
|
|
165
|
-
|
|
166
|
-
|
|
163
|
+
if (template.footer) {
|
|
164
|
+
lines.push('---');
|
|
165
|
+
lines.push(`Footer: ${template.footer}`);
|
|
166
|
+
lines.push('');
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Summary
|
|
170
|
+
const totalFields = template.sections.reduce(
|
|
171
|
+
(sum, s) => sum + (s.fields?.length || 0) + (s.columns?.length || 0),
|
|
172
|
+
0,
|
|
173
|
+
);
|
|
174
|
+
const missingKeys = template.sections
|
|
175
|
+
.flatMap((s) => s.fields || [])
|
|
176
|
+
.filter((f) => !dataKeys.includes(f.key))
|
|
177
|
+
.map((f) => f.key);
|
|
167
178
|
|
|
168
|
-
if (template.footer) {
|
|
169
179
|
lines.push('---');
|
|
170
|
-
lines.push(`
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
const missingKeys = template.sections
|
|
180
|
-
.flatMap(s => s.fields || [])
|
|
181
|
-
.filter(f => !dataKeys.includes(f.key))
|
|
182
|
-
.map(f => f.key);
|
|
183
|
-
|
|
184
|
-
lines.push('---');
|
|
185
|
-
lines.push(`Summary: ${template.sections.length} section(s), ${totalFields} field(s)/column(s)`);
|
|
186
|
-
|
|
187
|
-
if (missingKeys.length > 0) {
|
|
188
|
-
lines.push(`\u26a0\ufe0f Missing keys: ${missingKeys.join(', ')}`);
|
|
189
|
-
} else {
|
|
190
|
-
lines.push('\u2705 All field keys found in data');
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
return lines.join('\n');
|
|
180
|
+
lines.push(`Summary: ${template.sections.length} section(s), ${totalFields} field(s)/column(s)`);
|
|
181
|
+
|
|
182
|
+
if (missingKeys.length > 0) {
|
|
183
|
+
lines.push(`\u26a0\ufe0f Missing keys: ${missingKeys.join(', ')}`);
|
|
184
|
+
} else {
|
|
185
|
+
lines.push('\u2705 All field keys found in data');
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return lines.join('\n');
|
|
194
189
|
}
|
|
195
190
|
|
|
196
191
|
/**
|
|
197
192
|
* Generate a compact description for tool responses
|
|
198
193
|
*/
|
|
199
194
|
export function generateCompactPreview(template: FragmentTemplate): string {
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
195
|
+
const sections = template.sections.map((s) => {
|
|
196
|
+
if (s.layout === 'table' && s.columns) {
|
|
197
|
+
const colList = s.columns
|
|
198
|
+
.slice(0, 3)
|
|
199
|
+
.map((c) => c.header)
|
|
200
|
+
.join(', ');
|
|
201
|
+
const more = s.columns.length > 3 ? `, +${s.columns.length - 3} more` : '';
|
|
202
|
+
return `${s.title} (table): ${colList}${more}`;
|
|
203
|
+
}
|
|
209
204
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
205
|
+
if (s.layout === 'chart' && s.chart) {
|
|
206
|
+
const markType = s.chart.spec.mark
|
|
207
|
+
? typeof s.chart.spec.mark === 'string'
|
|
208
|
+
? s.chart.spec.mark
|
|
209
|
+
: (s.chart.spec.mark as { type?: string }).type || 'chart'
|
|
210
|
+
: 'chart';
|
|
211
|
+
return `${s.title} (${markType} chart)`;
|
|
212
|
+
}
|
|
216
213
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
214
|
+
if (s.fields) {
|
|
215
|
+
const fieldList = s.fields
|
|
216
|
+
.slice(0, 3)
|
|
217
|
+
.map((f) => f.label)
|
|
218
|
+
.join(', ');
|
|
219
|
+
const more = s.fields.length > 3 ? `, +${s.fields.length - 3} more` : '';
|
|
220
|
+
return `${s.title}: ${fieldList}${more}`;
|
|
221
|
+
}
|
|
225
222
|
|
|
226
|
-
|
|
227
|
-
|
|
223
|
+
return s.title;
|
|
224
|
+
});
|
|
228
225
|
|
|
229
|
-
|
|
230
|
-
|
|
226
|
+
const title = template.title ? `"${template.title}" - ` : '';
|
|
227
|
+
return `${title}${sections.join(' | ')}`;
|
|
231
228
|
}
|