@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.
Files changed (126) hide show
  1. package/LICENSE +198 -10
  2. package/lib/fusion-fragment/ChartRenderer.d.ts.map +1 -0
  3. package/lib/{esm/fusion-fragment → fusion-fragment}/ChartRenderer.js +8 -6
  4. package/lib/fusion-fragment/ChartRenderer.js.map +1 -0
  5. package/lib/{types/fusion-fragment → fusion-fragment}/FieldRenderer.d.ts +1 -1
  6. package/lib/fusion-fragment/FieldRenderer.d.ts.map +1 -0
  7. package/lib/{esm/fusion-fragment → fusion-fragment}/FieldRenderer.js +14 -8
  8. package/lib/fusion-fragment/FieldRenderer.js.map +1 -0
  9. package/lib/{types/fusion-fragment → fusion-fragment}/FusionFragmentContext.d.ts +3 -3
  10. package/lib/fusion-fragment/FusionFragmentContext.d.ts.map +1 -0
  11. package/lib/{esm/fusion-fragment → fusion-fragment}/FusionFragmentContext.js +2 -2
  12. package/lib/fusion-fragment/FusionFragmentContext.js.map +1 -0
  13. package/lib/fusion-fragment/FusionFragmentHandler.d.ts.map +1 -0
  14. package/lib/{esm/fusion-fragment → fusion-fragment}/FusionFragmentHandler.js +7 -14
  15. package/lib/fusion-fragment/FusionFragmentHandler.js.map +1 -0
  16. package/lib/fusion-fragment/FusionFragmentRenderer.d.ts.map +1 -0
  17. package/lib/{esm/fusion-fragment → fusion-fragment}/FusionFragmentRenderer.js +2 -2
  18. package/lib/fusion-fragment/FusionFragmentRenderer.js.map +1 -0
  19. package/lib/{types/fusion-fragment → fusion-fragment}/SectionRenderer.d.ts +1 -1
  20. package/lib/fusion-fragment/SectionRenderer.d.ts.map +1 -0
  21. package/lib/{esm/fusion-fragment → fusion-fragment}/SectionRenderer.js +12 -5
  22. package/lib/fusion-fragment/SectionRenderer.js.map +1 -0
  23. package/lib/fusion-fragment/TableRenderer.d.ts.map +1 -0
  24. package/lib/{esm/fusion-fragment → fusion-fragment}/TableRenderer.js +9 -7
  25. package/lib/fusion-fragment/TableRenderer.js.map +1 -0
  26. package/lib/{types/fusion-fragment → fusion-fragment}/index.d.ts +4 -4
  27. package/lib/fusion-fragment/index.d.ts.map +1 -0
  28. package/lib/{esm/fusion-fragment → fusion-fragment}/index.js +4 -4
  29. package/lib/fusion-fragment/index.js.map +1 -0
  30. package/lib/{types/index.d.ts → index.d.ts} +4 -4
  31. package/lib/index.d.ts.map +1 -0
  32. package/lib/{esm/index.js → index.js} +4 -4
  33. package/lib/index.js.map +1 -0
  34. package/lib/{types/render → render}/index.d.ts +1 -1
  35. package/lib/render/index.d.ts.map +1 -0
  36. package/lib/{esm/render → render}/index.js +1 -1
  37. package/lib/render/index.js.map +1 -0
  38. package/lib/render/textPreview.d.ts.map +1 -0
  39. package/lib/{esm/render → render}/textPreview.js +12 -9
  40. package/lib/render/textPreview.js.map +1 -0
  41. package/lib/types.d.ts.map +1 -0
  42. package/lib/types.js.map +1 -0
  43. package/lib/validation/formatErrors.d.ts.map +1 -0
  44. package/lib/{esm/validation → validation}/formatErrors.js +1 -1
  45. package/lib/validation/formatErrors.js.map +1 -0
  46. package/lib/validation/fuzzyMatch.d.ts.map +1 -0
  47. package/lib/{esm/validation → validation}/fuzzyMatch.js +3 -4
  48. package/lib/validation/fuzzyMatch.js.map +1 -0
  49. package/lib/validation/index.d.ts +8 -0
  50. package/lib/validation/index.d.ts.map +1 -0
  51. package/lib/validation/index.js +8 -0
  52. package/lib/validation/index.js.map +1 -0
  53. package/lib/{types/validation → validation}/schemas.d.ts +1 -1
  54. package/lib/validation/schemas.d.ts.map +1 -0
  55. package/lib/{esm/validation → validation}/schemas.js +25 -25
  56. package/lib/validation/schemas.js.map +1 -0
  57. package/lib/validation/validateTemplate.d.ts.map +1 -0
  58. package/lib/{esm/validation → validation}/validateTemplate.js +23 -21
  59. package/lib/validation/validateTemplate.js.map +1 -0
  60. package/lib/vertesia-fusion-ux.js +1 -1
  61. package/lib/vertesia-fusion-ux.js.map +1 -1
  62. package/package.json +23 -35
  63. package/src/fusion-fragment/ChartRenderer.tsx +95 -96
  64. package/src/fusion-fragment/FieldRenderer.tsx +173 -174
  65. package/src/fusion-fragment/FusionFragmentContext.tsx +31 -37
  66. package/src/fusion-fragment/FusionFragmentHandler.tsx +214 -223
  67. package/src/fusion-fragment/FusionFragmentRenderer.tsx +102 -107
  68. package/src/fusion-fragment/SectionRenderer.tsx +174 -169
  69. package/src/fusion-fragment/TableRenderer.tsx +175 -171
  70. package/src/fusion-fragment/index.ts +11 -11
  71. package/src/index.ts +42 -45
  72. package/src/render/index.ts +3 -3
  73. package/src/render/textPreview.ts +183 -186
  74. package/src/types.ts +174 -174
  75. package/src/validation/formatErrors.ts +86 -86
  76. package/src/validation/fuzzyMatch.ts +69 -77
  77. package/src/validation/index.ts +3 -3
  78. package/src/validation/schemas.ts +120 -120
  79. package/src/validation/validateTemplate.ts +225 -226
  80. package/lib/esm/fusion-fragment/ChartRenderer.js.map +0 -1
  81. package/lib/esm/fusion-fragment/FieldRenderer.js.map +0 -1
  82. package/lib/esm/fusion-fragment/FusionFragmentContext.js.map +0 -1
  83. package/lib/esm/fusion-fragment/FusionFragmentHandler.js.map +0 -1
  84. package/lib/esm/fusion-fragment/FusionFragmentRenderer.js.map +0 -1
  85. package/lib/esm/fusion-fragment/SectionRenderer.js.map +0 -1
  86. package/lib/esm/fusion-fragment/TableRenderer.js.map +0 -1
  87. package/lib/esm/fusion-fragment/index.js.map +0 -1
  88. package/lib/esm/index.js.map +0 -1
  89. package/lib/esm/render/index.js.map +0 -1
  90. package/lib/esm/render/textPreview.js.map +0 -1
  91. package/lib/esm/types.js.map +0 -1
  92. package/lib/esm/validation/formatErrors.js.map +0 -1
  93. package/lib/esm/validation/fuzzyMatch.js.map +0 -1
  94. package/lib/esm/validation/index.js +0 -8
  95. package/lib/esm/validation/index.js.map +0 -1
  96. package/lib/esm/validation/schemas.js.map +0 -1
  97. package/lib/esm/validation/validateTemplate.js.map +0 -1
  98. package/lib/tsconfig.tsbuildinfo +0 -1
  99. package/lib/types/fusion-fragment/ChartRenderer.d.ts.map +0 -1
  100. package/lib/types/fusion-fragment/FieldRenderer.d.ts.map +0 -1
  101. package/lib/types/fusion-fragment/FusionFragmentContext.d.ts.map +0 -1
  102. package/lib/types/fusion-fragment/FusionFragmentHandler.d.ts.map +0 -1
  103. package/lib/types/fusion-fragment/FusionFragmentRenderer.d.ts.map +0 -1
  104. package/lib/types/fusion-fragment/SectionRenderer.d.ts.map +0 -1
  105. package/lib/types/fusion-fragment/TableRenderer.d.ts.map +0 -1
  106. package/lib/types/fusion-fragment/index.d.ts.map +0 -1
  107. package/lib/types/index.d.ts.map +0 -1
  108. package/lib/types/render/index.d.ts.map +0 -1
  109. package/lib/types/render/textPreview.d.ts.map +0 -1
  110. package/lib/types/types.d.ts.map +0 -1
  111. package/lib/types/validation/formatErrors.d.ts.map +0 -1
  112. package/lib/types/validation/fuzzyMatch.d.ts.map +0 -1
  113. package/lib/types/validation/index.d.ts +0 -8
  114. package/lib/types/validation/index.d.ts.map +0 -1
  115. package/lib/types/validation/schemas.d.ts.map +0 -1
  116. package/lib/types/validation/validateTemplate.d.ts.map +0 -1
  117. /package/lib/{types/fusion-fragment → fusion-fragment}/ChartRenderer.d.ts +0 -0
  118. /package/lib/{types/fusion-fragment → fusion-fragment}/FusionFragmentHandler.d.ts +0 -0
  119. /package/lib/{types/fusion-fragment → fusion-fragment}/FusionFragmentRenderer.d.ts +0 -0
  120. /package/lib/{types/fusion-fragment → fusion-fragment}/TableRenderer.d.ts +0 -0
  121. /package/lib/{types/render → render}/textPreview.d.ts +0 -0
  122. /package/lib/{types/types.d.ts → types.d.ts} +0 -0
  123. /package/lib/{esm/types.js → types.js} +0 -0
  124. /package/lib/{types/validation → validation}/formatErrors.d.ts +0 -0
  125. /package/lib/{types/validation → validation}/fuzzyMatch.d.ts +0 -0
  126. /package/lib/{types/validation → validation}/validateTemplate.d.ts +0 -0
package/src/types.ts CHANGED
@@ -13,74 +13,74 @@ import type React from 'react';
13
13
  * Root template structure for a fusion fragment
14
14
  */
15
15
  export interface FragmentTemplate {
16
- /** Optional title displayed at the top */
17
- title?: string;
18
- /** Type of entity being displayed - helps with context */
19
- entityType?: 'fund' | 'scenario' | 'portfolio' | 'transaction' | 'custom';
20
- /** Sections containing fields */
21
- sections: SectionTemplate[];
22
- /** Optional footer text */
23
- footer?: string;
16
+ /** Optional title displayed at the top */
17
+ title?: string;
18
+ /** Type of entity being displayed - helps with context */
19
+ entityType?: 'fund' | 'scenario' | 'portfolio' | 'transaction' | 'custom';
20
+ /** Sections containing fields */
21
+ sections: SectionTemplate[];
22
+ /** Optional footer text */
23
+ footer?: string;
24
24
  }
25
25
 
26
26
  /**
27
27
  * A section within the fragment, containing related fields, a table, or a chart
28
28
  */
29
29
  export interface SectionTemplate {
30
- /** Section title/header */
31
- title: string;
32
- /** Layout mode for the fields */
33
- layout?: 'grid-2' | 'grid-3' | 'grid-4' | 'list' | 'table' | 'chart';
34
- /** Whether the section is initially collapsed */
35
- collapsed?: boolean;
36
- /** Fields in this section (for grid/list layouts) */
37
- fields?: FieldTemplate[];
38
- /** Table columns (for table layout) */
39
- columns?: ColumnTemplate[];
40
- /** Data key for table rows - points to an array in data */
41
- dataKey?: string;
42
- /** Chart specification (for chart layout) */
43
- chart?: ChartTemplate;
30
+ /** Section title/header */
31
+ title: string;
32
+ /** Layout mode for the fields */
33
+ layout?: 'grid-2' | 'grid-3' | 'grid-4' | 'list' | 'table' | 'chart';
34
+ /** Whether the section is initially collapsed */
35
+ collapsed?: boolean;
36
+ /** Fields in this section (for grid/list layouts) */
37
+ fields?: FieldTemplate[];
38
+ /** Table columns (for table layout) */
39
+ columns?: ColumnTemplate[];
40
+ /** Data key for table rows - points to an array in data */
41
+ dataKey?: string;
42
+ /** Chart specification (for chart layout) */
43
+ chart?: ChartTemplate;
44
44
  }
45
45
 
46
46
  /**
47
47
  * A column definition for table layout
48
48
  */
49
49
  export interface ColumnTemplate {
50
- /** Column header text */
51
- header: string;
52
- /** Key to look up in each row object */
53
- key: string;
54
- /** Display format */
55
- format?: 'text' | 'number' | 'currency' | 'percent' | 'date' | 'boolean';
56
- /** Column width (optional, e.g., '100px', '20%') */
57
- width?: string;
58
- /** Text alignment */
59
- align?: 'left' | 'center' | 'right';
60
- /** Currency code for currency format */
61
- currency?: string;
62
- /** Number of decimal places */
63
- decimals?: number;
64
- /** Highlight based on value (function key in data or static) */
65
- highlight?: 'success' | 'warning' | 'error' | 'info';
50
+ /** Column header text */
51
+ header: string;
52
+ /** Key to look up in each row object */
53
+ key: string;
54
+ /** Display format */
55
+ format?: 'text' | 'number' | 'currency' | 'percent' | 'date' | 'boolean';
56
+ /** Column width (optional, e.g., '100px', '20%') */
57
+ width?: string;
58
+ /** Text alignment */
59
+ align?: 'left' | 'center' | 'right';
60
+ /** Currency code for currency format */
61
+ currency?: string;
62
+ /** Number of decimal places */
63
+ decimals?: number;
64
+ /** Highlight based on value (function key in data or static) */
65
+ highlight?: 'success' | 'warning' | 'error' | 'info';
66
66
  }
67
67
 
68
68
  /**
69
69
  * Chart specification for chart layout (Vega-Lite based)
70
70
  */
71
71
  export interface ChartTemplate {
72
- /** Chart title (displayed above the chart) */
73
- title?: string;
74
- /** Chart description */
75
- description?: string;
76
- /** Vega-Lite specification */
77
- spec: VegaLiteSpec;
78
- /** Chart height in pixels */
79
- height?: number;
80
- /** Chart width in pixels (defaults to container width) */
81
- width?: number;
82
- /** Data key - if provided, data from this key replaces spec.data.values */
83
- dataKey?: string;
72
+ /** Chart title (displayed above the chart) */
73
+ title?: string;
74
+ /** Chart description */
75
+ description?: string;
76
+ /** Vega-Lite specification */
77
+ spec: VegaLiteSpec;
78
+ /** Chart height in pixels */
79
+ height?: number;
80
+ /** Chart width in pixels (defaults to container width) */
81
+ width?: number;
82
+ /** Data key - if provided, data from this key replaces spec.data.values */
83
+ dataKey?: string;
84
84
  }
85
85
 
86
86
  /**
@@ -88,67 +88,67 @@ export interface ChartTemplate {
88
88
  * Full spec: https://vega.github.io/vega-lite/docs/spec.html
89
89
  */
90
90
  export interface VegaLiteSpec {
91
- /** Schema URL (optional) */
92
- $schema?: string;
93
- /** Inline data or data source */
94
- data?: {
95
- /** Inline data values */
96
- values?: Record<string, unknown>[];
97
- /** URL to fetch data from */
98
- url?: string;
99
- /** Data format */
100
- format?: { type?: 'json' | 'csv' | 'tsv' };
101
- };
102
- /** Mark type (bar, line, point, area, etc.) */
103
- mark?: string | { type: string; [key: string]: unknown };
104
- /** Encoding channels (x, y, color, size, etc.) */
105
- encoding?: Record<string, unknown>;
106
- /** Vertical concatenation */
107
- vconcat?: VegaLiteSpec[];
108
- /** Horizontal concatenation */
109
- hconcat?: VegaLiteSpec[];
110
- /** Layer multiple marks */
111
- layer?: VegaLiteSpec[];
112
- /** Transform operations */
113
- transform?: Record<string, unknown>[];
114
- /** Interactive parameters */
115
- params?: Record<string, unknown>[];
116
- /** Chart configuration */
117
- config?: Record<string, unknown>;
118
- /** Allow additional Vega-Lite properties */
119
- [key: string]: unknown;
91
+ /** Schema URL (optional) */
92
+ $schema?: string;
93
+ /** Inline data or data source */
94
+ data?: {
95
+ /** Inline data values */
96
+ values?: Record<string, unknown>[];
97
+ /** URL to fetch data from */
98
+ url?: string;
99
+ /** Data format */
100
+ format?: { type?: 'json' | 'csv' | 'tsv' };
101
+ };
102
+ /** Mark type (bar, line, point, area, etc.) */
103
+ mark?: string | { type: string; [key: string]: unknown };
104
+ /** Encoding channels (x, y, color, size, etc.) */
105
+ encoding?: Record<string, unknown>;
106
+ /** Vertical concatenation */
107
+ vconcat?: VegaLiteSpec[];
108
+ /** Horizontal concatenation */
109
+ hconcat?: VegaLiteSpec[];
110
+ /** Layer multiple marks */
111
+ layer?: VegaLiteSpec[];
112
+ /** Transform operations */
113
+ transform?: Record<string, unknown>[];
114
+ /** Interactive parameters */
115
+ params?: Record<string, unknown>[];
116
+ /** Chart configuration */
117
+ config?: Record<string, unknown>;
118
+ /** Allow additional Vega-Lite properties */
119
+ [key: string]: unknown;
120
120
  }
121
121
 
122
122
  /**
123
123
  * A single field definition
124
124
  */
125
125
  export interface FieldTemplate {
126
- /** Display label for the field */
127
- label: string;
128
- /** Key to look up in data - REQUIRED */
129
- key: string;
130
- /** Display format */
131
- format?: 'text' | 'number' | 'currency' | 'percent' | 'date' | 'boolean';
132
- /** Unit to display after value (e.g., "years", "USD") */
133
- unit?: string;
134
- /** Whether this field is editable */
135
- editable?: boolean;
136
- /** Input type when editing */
137
- inputType?: 'text' | 'number' | 'date' | 'select' | 'checkbox';
138
- /** Options for select input type */
139
- options?: Array<{ label: string; value: string }>;
140
- /** Min value for number inputs */
141
- min?: number;
142
- /** Max value for number inputs */
143
- max?: number;
144
- /** Visual highlight style */
145
- highlight?: 'success' | 'warning' | 'error' | 'info';
146
- /** Tooltip text on hover */
147
- tooltip?: string;
148
- /** Number of decimal places for number format */
149
- decimals?: number;
150
- /** Currency code for currency format */
151
- currency?: string;
126
+ /** Display label for the field */
127
+ label: string;
128
+ /** Key to look up in data - REQUIRED */
129
+ key: string;
130
+ /** Display format */
131
+ format?: 'text' | 'number' | 'currency' | 'percent' | 'date' | 'boolean';
132
+ /** Unit to display after value (e.g., "years", "USD") */
133
+ unit?: string;
134
+ /** Whether this field is editable */
135
+ editable?: boolean;
136
+ /** Input type when editing */
137
+ inputType?: 'text' | 'number' | 'date' | 'select' | 'checkbox';
138
+ /** Options for select input type */
139
+ options?: Array<{ label: string; value: string }>;
140
+ /** Min value for number inputs */
141
+ min?: number;
142
+ /** Max value for number inputs */
143
+ max?: number;
144
+ /** Visual highlight style */
145
+ highlight?: 'success' | 'warning' | 'error' | 'info';
146
+ /** Tooltip text on hover */
147
+ tooltip?: string;
148
+ /** Number of decimal places for number format */
149
+ decimals?: number;
150
+ /** Currency code for currency format */
151
+ currency?: string;
152
152
  }
153
153
 
154
154
  // ============ Validation Types ============
@@ -157,22 +157,22 @@ export interface FieldTemplate {
157
157
  * Result of template validation
158
158
  */
159
159
  export interface ValidationResult {
160
- /** Whether the template is valid */
161
- valid: boolean;
162
- /** List of validation errors */
163
- errors: ValidationError[];
160
+ /** Whether the template is valid */
161
+ valid: boolean;
162
+ /** List of validation errors */
163
+ errors: ValidationError[];
164
164
  }
165
165
 
166
166
  /**
167
167
  * A single validation error with path and suggestion
168
168
  */
169
169
  export interface ValidationError {
170
- /** JSON path to the error (e.g., "sections[0].fields[2].key") */
171
- path: string;
172
- /** Human-readable error message */
173
- message: string;
174
- /** Suggested fix (for model feedback) */
175
- suggestion?: string;
170
+ /** JSON path to the error (e.g., "sections[0].fields[2].key") */
171
+ path: string;
172
+ /** Human-readable error message */
173
+ message: string;
174
+ /** Suggested fix (for model feedback) */
175
+ suggestion?: string;
176
176
  }
177
177
 
178
178
  // ============ Component Props ============
@@ -181,48 +181,48 @@ export interface ValidationError {
181
181
  * Props for the main FusionFragmentRenderer component
182
182
  */
183
183
  export interface FusionFragmentRendererProps {
184
- /** The template structure (from model) */
185
- template: FragmentTemplate;
186
- /** Actual data values to display */
187
- data: Record<string, unknown>;
188
- /** Callback for field updates (direct mode) */
189
- onUpdate?: (key: string, value: unknown) => Promise<void>;
190
- /** Agent mode configuration */
191
- agentMode?: {
192
- enabled: true;
193
- /** Send message to conversation */
194
- sendMessage: (message: string) => void;
195
- };
196
- /** CSS class name */
197
- className?: string;
184
+ /** The template structure (from model) */
185
+ template: FragmentTemplate;
186
+ /** Actual data values to display */
187
+ data: Record<string, unknown>;
188
+ /** Callback for field updates (direct mode) */
189
+ onUpdate?: (key: string, value: unknown) => Promise<void>;
190
+ /** Agent mode configuration */
191
+ agentMode?: {
192
+ enabled: true;
193
+ /** Send message to conversation */
194
+ sendMessage: (message: string) => void;
195
+ };
196
+ /** CSS class name */
197
+ className?: string;
198
198
  }
199
199
 
200
200
  /**
201
201
  * Props for section renderer
202
202
  */
203
203
  export interface SectionRendererProps {
204
- /** Section template */
205
- section: SectionTemplate;
206
- /** Data for fields */
207
- data: Record<string, unknown>;
208
- /** Update callback */
209
- onUpdate?: (key: string, value: unknown) => Promise<void>;
210
- /** Agent mode */
211
- agentMode?: FusionFragmentRendererProps['agentMode'];
204
+ /** Section template */
205
+ section: SectionTemplate;
206
+ /** Data for fields */
207
+ data: Record<string, unknown>;
208
+ /** Update callback */
209
+ onUpdate?: (key: string, value: unknown) => Promise<void>;
210
+ /** Agent mode */
211
+ agentMode?: FusionFragmentRendererProps['agentMode'];
212
212
  }
213
213
 
214
214
  /**
215
215
  * Props for field renderer
216
216
  */
217
217
  export interface FieldRendererProps {
218
- /** Field template */
219
- field: FieldTemplate;
220
- /** Field value from data */
221
- value: unknown;
222
- /** Update callback */
223
- onUpdate?: (value: unknown) => Promise<void>;
224
- /** Agent mode */
225
- agentMode?: FusionFragmentRendererProps['agentMode'];
218
+ /** Field template */
219
+ field: FieldTemplate;
220
+ /** Field value from data */
221
+ value: unknown;
222
+ /** Update callback */
223
+ onUpdate?: (value: unknown) => Promise<void>;
224
+ /** Agent mode */
225
+ agentMode?: FusionFragmentRendererProps['agentMode'];
226
226
  }
227
227
 
228
228
  // ============ Context Types ============
@@ -231,34 +231,34 @@ export interface FieldRendererProps {
231
231
  * Props for the injected chart component (matches @vertesia/ui VegaLiteChart)
232
232
  */
233
233
  export interface ChartComponentProps {
234
- /** The chart specification in VegaLiteChartSpec format */
235
- spec: {
236
- library: 'vega-lite';
237
- title?: string;
238
- description?: string;
239
- spec: Record<string, unknown>;
240
- options?: {
241
- height?: number;
234
+ /** The chart specification in VegaLiteChartSpec format */
235
+ spec: {
236
+ library: 'vega-lite';
237
+ title?: string;
238
+ description?: string;
239
+ spec: Record<string, unknown>;
240
+ options?: {
241
+ height?: number;
242
+ };
242
243
  };
243
- };
244
- /** Optional artifact run ID for resolving artifact: URLs */
245
- artifactRunId?: string;
244
+ /** Optional artifact run ID for resolving artifact: URLs */
245
+ artifactRunId?: string;
246
246
  }
247
247
 
248
248
  /**
249
249
  * Context value for FusionFragment components
250
250
  */
251
251
  export interface FusionFragmentContextValue {
252
- /** Data to display */
253
- data: Record<string, unknown>;
254
- /** Update callback */
255
- onUpdate?: (key: string, value: unknown) => Promise<void>;
256
- /** Send message to agent */
257
- sendMessage?: (message: string) => void;
258
- /** Optional chart component to render Vega-Lite charts (injected to avoid circular deps) */
259
- ChartComponent?: React.ComponentType<ChartComponentProps>;
260
- /** Optional artifact run ID for resolving artifact references */
261
- artifactRunId?: string;
252
+ /** Data to display */
253
+ data: Record<string, unknown>;
254
+ /** Update callback */
255
+ onUpdate?: (key: string, value: unknown) => Promise<void>;
256
+ /** Send message to agent */
257
+ sendMessage?: (message: string) => void;
258
+ /** Optional chart component to render Vega-Lite charts (injected to avoid circular deps) */
259
+ ChartComponent?: React.ComponentType<ChartComponentProps>;
260
+ /** Optional artifact run ID for resolving artifact references */
261
+ artifactRunId?: string;
262
262
  }
263
263
 
264
264
  // ============ Tool Types ============
@@ -267,12 +267,12 @@ export interface FusionFragmentContextValue {
267
267
  * Input for validate_fusion_fragment tool
268
268
  */
269
269
  export interface ValidateFusionFragmentInput {
270
- /** The template to validate */
271
- template: FragmentTemplate;
272
- /** Available data keys */
273
- dataKeys: string[];
274
- /** Optional sample data for preview rendering */
275
- sampleData?: Record<string, unknown>;
276
- /** Preview mode */
277
- preview?: 'image' | 'text' | 'none';
270
+ /** The template to validate */
271
+ template: FragmentTemplate;
272
+ /** Available data keys */
273
+ dataKeys: string[];
274
+ /** Optional sample data for preview rendering */
275
+ sampleData?: Record<string, unknown>;
276
+ /** Preview mode */
277
+ preview?: 'image' | 'text' | 'none';
278
278
  }
@@ -10,22 +10,22 @@ import type { ValidationError } from '../types.js';
10
10
  * @returns Formatted error message
11
11
  */
12
12
  export function formatValidationErrors(errors: ValidationError[]): string {
13
- if (errors.length === 0) {
14
- return 'Template is valid.';
15
- }
13
+ if (errors.length === 0) {
14
+ return 'Template is valid.';
15
+ }
16
16
 
17
- const header = `Template validation failed with ${errors.length} error${errors.length > 1 ? 's' : ''}:\n`;
17
+ const header = `Template validation failed with ${errors.length} error${errors.length > 1 ? 's' : ''}:\n`;
18
18
 
19
- const formattedErrors = errors.map((error, index) => {
20
- let message = `${index + 1}. ${error.message}`;
21
- message += `\n Path: ${error.path}`;
22
- if (error.suggestion) {
23
- message += `\n \u2192 ${error.suggestion}`;
24
- }
25
- return message;
26
- });
19
+ const formattedErrors = errors.map((error, index) => {
20
+ let message = `${index + 1}. ${error.message}`;
21
+ message += `\n Path: ${error.path}`;
22
+ if (error.suggestion) {
23
+ message += `\n \u2192 ${error.suggestion}`;
24
+ }
25
+ return message;
26
+ });
27
27
 
28
- return header + '\n' + formattedErrors.join('\n\n');
28
+ return `${header}\n${formattedErrors.join('\n\n')}`;
29
29
  }
30
30
 
31
31
  /**
@@ -35,39 +35,42 @@ export function formatValidationErrors(errors: ValidationError[]): string {
35
35
  * @returns Success message with preview
36
36
  */
37
37
  export function formatValidationSuccess(
38
- template: { title?: string; sections: Array<{ title: string; fields: Array<{ label: string; key: string; format?: string }> }> },
39
- dataKeys: string[]
38
+ template: {
39
+ title?: string;
40
+ sections: Array<{ title: string; fields: Array<{ label: string; key: string; format?: string }> }>;
41
+ },
42
+ dataKeys: string[],
40
43
  ): string {
41
- const lines: string[] = ['Template valid. Preview:'];
42
- lines.push('');
43
-
44
- if (template.title) {
45
- lines.push(`**${template.title}**`);
44
+ const lines: string[] = ['Template valid. Preview:'];
46
45
  lines.push('');
47
- }
48
-
49
- for (const section of template.sections) {
50
- const fieldCount = section.fields.length;
51
- lines.push(`[${section.title}] ${fieldCount} field${fieldCount > 1 ? 's' : ''}:`);
52
46
 
53
- for (const field of section.fields) {
54
- let fieldDesc = `- ${field.label} (${field.key}`;
55
- if (field.format && field.format !== 'text') {
56
- fieldDesc += `, ${field.format}`;
57
- }
58
- fieldDesc += ')';
59
-
60
- // Check if key exists in data
61
- if (!dataKeys.includes(field.key)) {
62
- fieldDesc += ' \u26a0\ufe0f key not in data';
63
- }
47
+ if (template.title) {
48
+ lines.push(`**${template.title}**`);
49
+ lines.push('');
50
+ }
64
51
 
65
- lines.push(fieldDesc);
52
+ for (const section of template.sections) {
53
+ const fieldCount = section.fields.length;
54
+ lines.push(`[${section.title}] ${fieldCount} field${fieldCount > 1 ? 's' : ''}:`);
55
+
56
+ for (const field of section.fields) {
57
+ let fieldDesc = `- ${field.label} (${field.key}`;
58
+ if (field.format && field.format !== 'text') {
59
+ fieldDesc += `, ${field.format}`;
60
+ }
61
+ fieldDesc += ')';
62
+
63
+ // Check if key exists in data
64
+ if (!dataKeys.includes(field.key)) {
65
+ fieldDesc += ' \u26a0\ufe0f key not in data';
66
+ }
67
+
68
+ lines.push(fieldDesc);
69
+ }
70
+ lines.push('');
66
71
  }
67
- lines.push('');
68
- }
69
72
 
70
- return lines.join('\n');
73
+ return lines.join('\n');
71
74
  }
72
75
 
73
76
  /**
@@ -76,53 +79,50 @@ export function formatValidationSuccess(
76
79
  * @param groupByPrefix - Whether to group keys by common prefix
77
80
  * @returns Formatted key list
78
81
  */
79
- export function formatAvailableKeys(
80
- dataKeys: string[],
81
- groupByPrefix: boolean = true
82
- ): string {
83
- if (dataKeys.length === 0) {
84
- return 'No data keys available.';
85
- }
86
-
87
- if (!groupByPrefix || dataKeys.length <= 10) {
88
- return `Available keys: ${dataKeys.join(', ')}`;
89
- }
90
-
91
- // Group by prefix (e.g., fund.name, fund.type -> fund.*)
92
- const groups = new Map<string, string[]>();
93
-
94
- for (const key of dataKeys) {
95
- const dotIndex = key.indexOf('.');
96
- if (dotIndex > 0) {
97
- const prefix = key.substring(0, dotIndex);
98
- const rest = key.substring(dotIndex + 1);
99
- const group = groups.get(prefix) || [];
100
- group.push(rest);
101
- groups.set(prefix, group);
102
- } else {
103
- const group = groups.get('') || [];
104
- group.push(key);
105
- groups.set('', group);
82
+ export function formatAvailableKeys(dataKeys: string[], groupByPrefix: boolean = true): string {
83
+ if (dataKeys.length === 0) {
84
+ return 'No data keys available.';
106
85
  }
107
- }
108
-
109
- const lines: string[] = ['Available keys:'];
110
-
111
- // Top-level keys first
112
- const topLevel = groups.get('');
113
- if (topLevel && topLevel.length > 0) {
114
- lines.push(` ${topLevel.join(', ')}`);
115
- }
116
-
117
- // Grouped keys
118
- for (const [prefix, keys] of groups) {
119
- if (prefix === '') continue;
120
- if (keys.length <= 3) {
121
- lines.push(` ${prefix}: ${keys.join(', ')}`);
122
- } else {
123
- lines.push(` ${prefix}: ${keys.slice(0, 3).join(', ')}, ... (${keys.length} total)`);
86
+
87
+ if (!groupByPrefix || dataKeys.length <= 10) {
88
+ return `Available keys: ${dataKeys.join(', ')}`;
89
+ }
90
+
91
+ // Group by prefix (e.g., fund.name, fund.type -> fund.*)
92
+ const groups = new Map<string, string[]>();
93
+
94
+ for (const key of dataKeys) {
95
+ const dotIndex = key.indexOf('.');
96
+ if (dotIndex > 0) {
97
+ const prefix = key.substring(0, dotIndex);
98
+ const rest = key.substring(dotIndex + 1);
99
+ const group = groups.get(prefix) || [];
100
+ group.push(rest);
101
+ groups.set(prefix, group);
102
+ } else {
103
+ const group = groups.get('') || [];
104
+ group.push(key);
105
+ groups.set('', group);
106
+ }
107
+ }
108
+
109
+ const lines: string[] = ['Available keys:'];
110
+
111
+ // Top-level keys first
112
+ const topLevel = groups.get('');
113
+ if (topLevel && topLevel.length > 0) {
114
+ lines.push(` ${topLevel.join(', ')}`);
115
+ }
116
+
117
+ // Grouped keys
118
+ for (const [prefix, keys] of groups) {
119
+ if (prefix === '') continue;
120
+ if (keys.length <= 3) {
121
+ lines.push(` ${prefix}: ${keys.join(', ')}`);
122
+ } else {
123
+ lines.push(` ${prefix}: ${keys.slice(0, 3).join(', ')}, ... (${keys.length} total)`);
124
+ }
124
125
  }
125
- }
126
126
 
127
- return lines.join('\n');
127
+ return lines.join('\n');
128
128
  }