@zhama/a2ui-core 0.1.0 → 0.3.0

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/index.js CHANGED
@@ -1,802 +1,3 @@
1
- // src/types/messages.ts
2
- function isV09Message(message) {
3
- return "createSurface" in message || "updateComponents" in message || "updateDataModel" in message;
4
- }
5
- function isV08Message(message) {
6
- return "beginRendering" in message || "surfaceUpdate" in message || "dataModelUpdate" in message;
7
- }
8
- var STANDARD_CATALOG_ID = "https://a2ui.dev/specification/0.9/standard_catalog_definition.json";
9
- var A2UI_EXTENSION_URI_V08 = "https://a2ui.org/a2a-extension/a2ui/v0.8";
10
- var A2UI_EXTENSION_URI = "https://a2ui.dev/specification/0.9";
11
- var A2UI_MIME_TYPE = "application/json+a2ui";
12
-
13
- // src/builders/id-generator.ts
14
- var componentIdCounter = 0;
15
- function generateId(prefix = "comp") {
16
- return `${prefix}_${Date.now()}_${componentIdCounter++}`;
17
- }
18
- function resetIdCounter() {
19
- componentIdCounter = 0;
20
- }
21
- function getIdCounter() {
22
- return componentIdCounter;
23
- }
24
-
25
- // src/builders/component-builder.ts
26
- function text(content, options = {}) {
27
- const { id = generateId("text"), weight, usageHint } = options;
28
- return {
29
- id,
30
- component: "Text",
31
- text: content,
32
- ...weight !== void 0 && { weight },
33
- ...usageHint && { usageHint }
34
- };
35
- }
36
- function image(url, options = {}) {
37
- const { id = generateId("image"), weight, fit, usageHint } = options;
38
- return {
39
- id,
40
- component: "Image",
41
- url,
42
- ...weight !== void 0 && { weight },
43
- ...fit && { fit },
44
- ...usageHint && { usageHint }
45
- };
46
- }
47
- function icon(name, options = {}) {
48
- const { id = generateId("icon"), weight } = options;
49
- return {
50
- id,
51
- component: "Icon",
52
- name,
53
- ...weight !== void 0 && { weight }
54
- };
55
- }
56
- function video(url, options = {}) {
57
- const { id = generateId("video"), weight } = options;
58
- return {
59
- id,
60
- component: "Video",
61
- url,
62
- ...weight !== void 0 && { weight }
63
- };
64
- }
65
- function audioPlayer(url, options = {}) {
66
- const { id = generateId("audio"), weight, description } = options;
67
- return {
68
- id,
69
- component: "AudioPlayer",
70
- url,
71
- ...weight !== void 0 && { weight },
72
- ...description && { description }
73
- };
74
- }
75
- function row(children, options = {}) {
76
- const { id = generateId("row"), weight, alignment, distribution } = options;
77
- return {
78
- id,
79
- component: "Row",
80
- children,
81
- ...weight !== void 0 && { weight },
82
- ...alignment && { alignment },
83
- ...distribution && { distribution }
84
- };
85
- }
86
- function column(children, options = {}) {
87
- const { id = generateId("column"), weight, alignment, distribution } = options;
88
- return {
89
- id,
90
- component: "Column",
91
- children,
92
- ...weight !== void 0 && { weight },
93
- ...alignment && { alignment },
94
- ...distribution && { distribution }
95
- };
96
- }
97
- function list(children, options = {}) {
98
- const { id = generateId("list"), weight, direction, alignment } = options;
99
- return {
100
- id,
101
- component: "List",
102
- children,
103
- ...weight !== void 0 && { weight },
104
- ...direction && { direction },
105
- ...alignment && { alignment }
106
- };
107
- }
108
- function card(childId, options = {}) {
109
- const { id = generateId("card"), weight } = options;
110
- return {
111
- id,
112
- component: "Card",
113
- child: childId,
114
- ...weight !== void 0 && { weight }
115
- };
116
- }
117
- function tabs(items, options = {}) {
118
- const { id = generateId("tabs"), weight } = options;
119
- return {
120
- id,
121
- component: "Tabs",
122
- tabItems: items.map((item) => ({
123
- title: item.title,
124
- child: item.childId
125
- })),
126
- ...weight !== void 0 && { weight }
127
- };
128
- }
129
- function divider(options = {}) {
130
- const { id = generateId("divider"), weight, axis } = options;
131
- return {
132
- id,
133
- component: "Divider",
134
- ...weight !== void 0 && { weight },
135
- ...axis && { axis }
136
- };
137
- }
138
- function modal(entryPointChildId, contentChildId, options = {}) {
139
- const { id = generateId("modal"), weight } = options;
140
- return {
141
- id,
142
- component: "Modal",
143
- entryPointChild: entryPointChildId,
144
- contentChild: contentChildId,
145
- ...weight !== void 0 && { weight }
146
- };
147
- }
148
- function button(childId, action, options = {}) {
149
- const { id = generateId("button"), weight, primary } = options;
150
- return {
151
- id,
152
- component: "Button",
153
- child: childId,
154
- action,
155
- ...weight !== void 0 && { weight },
156
- ...primary !== void 0 && { primary }
157
- };
158
- }
159
- function checkbox(label, value, options = {}) {
160
- const { id = generateId("checkbox"), weight } = options;
161
- return {
162
- id,
163
- component: "CheckBox",
164
- label,
165
- value,
166
- ...weight !== void 0 && { weight }
167
- };
168
- }
169
- function textField(label, textValue, options = {}) {
170
- const { id = generateId("textfield"), weight, usageHint, validationRegexp } = options;
171
- return {
172
- id,
173
- component: "TextField",
174
- label,
175
- ...textValue !== void 0 && { text: textValue },
176
- ...weight !== void 0 && { weight },
177
- ...usageHint && { usageHint },
178
- ...validationRegexp && { validationRegexp }
179
- };
180
- }
181
- function dateTimeInput(value, options = {}) {
182
- const { id = generateId("datetime"), weight, enableDate, enableTime, outputFormat, label } = options;
183
- return {
184
- id,
185
- component: "DateTimeInput",
186
- value,
187
- ...weight !== void 0 && { weight },
188
- ...enableDate !== void 0 && { enableDate },
189
- ...enableTime !== void 0 && { enableTime },
190
- ...outputFormat && { outputFormat },
191
- ...label && { label }
192
- };
193
- }
194
- function choicePicker(optionsList, value, usageHint, options = {}) {
195
- const { id = generateId("choice"), weight, label } = options;
196
- return {
197
- id,
198
- component: "ChoicePicker",
199
- options: optionsList,
200
- value,
201
- usageHint,
202
- ...weight !== void 0 && { weight },
203
- ...label && { label }
204
- };
205
- }
206
- function slider(value, options = {}) {
207
- const { id = generateId("slider"), weight, label, min, max } = options;
208
- return {
209
- id,
210
- component: "Slider",
211
- value,
212
- ...weight !== void 0 && { weight },
213
- ...label && { label },
214
- ...min !== void 0 && { min },
215
- ...max !== void 0 && { max }
216
- };
217
- }
218
- function textButton(buttonText, action, options = {}) {
219
- const textId = options.textId ?? generateId("btn_text");
220
- const textComp = text(buttonText, { id: textId });
221
- const buttonComp = button(textId, action, options);
222
- return [textComp, buttonComp];
223
- }
224
- function h1(content, options = {}) {
225
- return text(content, { ...options, usageHint: "h1" });
226
- }
227
- function h2(content, options = {}) {
228
- return text(content, { ...options, usageHint: "h2" });
229
- }
230
- function h3(content, options = {}) {
231
- return text(content, { ...options, usageHint: "h3" });
232
- }
233
- function h4(content, options = {}) {
234
- return text(content, { ...options, usageHint: "h4" });
235
- }
236
- function h5(content, options = {}) {
237
- return text(content, { ...options, usageHint: "h5" });
238
- }
239
- function caption(content, options = {}) {
240
- return text(content, { ...options, usageHint: "caption" });
241
- }
242
- function body(content, options = {}) {
243
- return text(content, { ...options, usageHint: "body" });
244
- }
245
-
246
- // src/builders/data-model-builder.ts
247
- var DEFAULT_PATH_MAPPINGS = {};
248
- function objectToValueMap(obj, prefix = "") {
249
- const entries = [];
250
- for (const [key, value] of Object.entries(obj)) {
251
- const fullKey = prefix ? `${prefix}/${key}` : `/${key}`;
252
- entries.push(valueToValueMap(fullKey, value));
253
- }
254
- return entries;
255
- }
256
- function valueToValueMap(key, value) {
257
- if (value === null || value === void 0) {
258
- return { key, valueString: "" };
259
- }
260
- if (typeof value === "string") {
261
- return { key, valueString: value };
262
- }
263
- if (typeof value === "number") {
264
- return { key, valueNumber: value };
265
- }
266
- if (typeof value === "boolean") {
267
- return { key, valueBoolean: value };
268
- }
269
- if (Array.isArray(value)) {
270
- return {
271
- key,
272
- valueMap: value.map((item, index) => valueToValueMap(String(index), item))
273
- };
274
- }
275
- if (typeof value === "object") {
276
- const nestedMaps = [];
277
- for (const [k, v] of Object.entries(value)) {
278
- nestedMaps.push(valueToValueMap(k, v));
279
- }
280
- return { key, valueMap: nestedMaps };
281
- }
282
- return { key, valueString: String(value) };
283
- }
284
- function normalizePath(path2, pathMappings = {}) {
285
- let normalizedPath = path2.replace(/\./g, "/");
286
- if (!normalizedPath.startsWith("/")) {
287
- normalizedPath = `/${normalizedPath}`;
288
- }
289
- for (const [from, to] of Object.entries(pathMappings)) {
290
- const fromPattern = new RegExp(`^/${from}(/|$)`);
291
- if (fromPattern.test(normalizedPath)) {
292
- normalizedPath = normalizedPath.replace(fromPattern, `/${to}$1`);
293
- }
294
- }
295
- return normalizedPath;
296
- }
297
- function updatesToValueMap(updates, basePath = "", pathMappings = DEFAULT_PATH_MAPPINGS) {
298
- const entries = [];
299
- for (const update of updates) {
300
- const rawPath = update.path.startsWith("/") ? update.path : `${basePath}/${update.path}`;
301
- const normalizedPath = normalizePath(rawPath, pathMappings);
302
- if (update.value !== null && typeof update.value === "object" && !Array.isArray(update.value)) {
303
- const flattenedEntries = flattenObjectToValueMap(
304
- update.value,
305
- normalizedPath
306
- );
307
- entries.push(...flattenedEntries);
308
- } else {
309
- entries.push(valueToValueMap(normalizedPath, update.value));
310
- }
311
- }
312
- return entries;
313
- }
314
- function flattenObjectToValueMap(obj, basePath) {
315
- const entries = [];
316
- for (const [key, value] of Object.entries(obj)) {
317
- const fullPath = `${basePath}/${key}`;
318
- if (value !== null && typeof value === "object" && !Array.isArray(value)) {
319
- const nestedEntries = flattenObjectToValueMap(value, fullPath);
320
- entries.push(...nestedEntries);
321
- } else {
322
- entries.push(valueToValueMap(fullPath, value));
323
- }
324
- }
325
- return entries;
326
- }
327
- function valueMapToObject(valueMaps) {
328
- const result = {};
329
- for (const valueMap of valueMaps) {
330
- const key = valueMap.key.startsWith("/") ? valueMap.key.slice(1) : valueMap.key;
331
- if (valueMap.valueString !== void 0) {
332
- result[key] = valueMap.valueString;
333
- } else if (valueMap.valueNumber !== void 0) {
334
- result[key] = valueMap.valueNumber;
335
- } else if (valueMap.valueBoolean !== void 0) {
336
- result[key] = valueMap.valueBoolean;
337
- } else if (valueMap.valueMap !== void 0) {
338
- result[key] = valueMapToObject(valueMap.valueMap);
339
- }
340
- }
341
- return result;
342
- }
343
-
344
- // src/builders/message-builder.ts
345
- function createSurface(surfaceId, catalogId = STANDARD_CATALOG_ID) {
346
- return {
347
- createSurface: {
348
- surfaceId,
349
- catalogId
350
- }
351
- };
352
- }
353
- function updateComponents(surfaceId, components) {
354
- return {
355
- updateComponents: {
356
- surfaceId,
357
- components
358
- }
359
- };
360
- }
361
- function updateDataModel(surfaceId, value, path2, op = "replace") {
362
- return {
363
- updateDataModel: {
364
- surfaceId,
365
- ...path2 && { path: path2 },
366
- op,
367
- ...op !== "remove" && { value }
368
- }
369
- };
370
- }
371
- function deleteSurface(surfaceId) {
372
- return {
373
- deleteSurface: {
374
- surfaceId
375
- }
376
- };
377
- }
378
- function createV09Messages(options) {
379
- const { surfaceId, catalogId = STANDARD_CATALOG_ID, components, dataModel } = options;
380
- const messages = [
381
- createSurface(surfaceId, catalogId),
382
- updateComponents(surfaceId, components)
383
- ];
384
- if (dataModel) {
385
- messages.push(updateDataModel(surfaceId, dataModel));
386
- }
387
- return messages;
388
- }
389
- function beginRendering(rootId, surfaceId = "@default", styles) {
390
- return {
391
- beginRendering: {
392
- surfaceId,
393
- root: rootId,
394
- ...styles && { styles }
395
- }
396
- };
397
- }
398
- function surfaceUpdate(components, surfaceId = "@default") {
399
- return {
400
- surfaceUpdate: {
401
- surfaceId,
402
- components
403
- }
404
- };
405
- }
406
- function dataModelUpdate(contents, surfaceId = "@default", path2) {
407
- return {
408
- dataModelUpdate: {
409
- surfaceId,
410
- contents,
411
- ...path2 && { path: path2 }
412
- }
413
- };
414
- }
415
- function dataModelInit(data, surfaceId = "@default") {
416
- return dataModelUpdate(objectToValueMap(data), surfaceId);
417
- }
418
- function pathUpdate(path2, value, surfaceId = "@default") {
419
- return {
420
- dataModelUpdate: {
421
- surfaceId,
422
- path: path2,
423
- contents: [valueToValueMap("", value)]
424
- }
425
- };
426
- }
427
- function deleteSurfaceV08(surfaceId) {
428
- return {
429
- deleteSurface: {
430
- surfaceId
431
- }
432
- };
433
- }
434
- function createV08Messages(options) {
435
- const { rootId, components, dataModel, surfaceId = "@default", styles } = options;
436
- const messages = [
437
- surfaceUpdate(components, surfaceId)
438
- ];
439
- if (dataModel) {
440
- messages.push(dataModelInit(dataModel, surfaceId));
441
- }
442
- messages.push(beginRendering(rootId, surfaceId, styles));
443
- return messages;
444
- }
445
- function messagesToJsonl(messages) {
446
- return messages.map((msg) => JSON.stringify(msg)).join("\n");
447
- }
448
- function jsonlToMessages(jsonl) {
449
- return jsonl.split("\n").filter((line) => line.trim()).map((line) => JSON.parse(line));
450
- }
451
-
452
- // src/validators/message-validator.ts
453
- var STANDARD_COMPONENT_TYPES = [
454
- "Text",
455
- "Image",
456
- "Icon",
457
- "Video",
458
- "AudioPlayer",
459
- "Row",
460
- "Column",
461
- "List",
462
- "Card",
463
- "Tabs",
464
- "Divider",
465
- "Modal",
466
- "Button",
467
- "CheckBox",
468
- "TextField",
469
- "DateTimeInput",
470
- "ChoicePicker",
471
- "Slider"
472
- ];
473
- function validateV09Message(message, options = {}) {
474
- const errors = [];
475
- const warnings = [];
476
- if ("createSurface" in message) {
477
- const { createSurface: createSurface2 } = message;
478
- if (!createSurface2.surfaceId) {
479
- errors.push({
480
- code: "MISSING_SURFACE_ID",
481
- message: "createSurface.surfaceId is required",
482
- path: "createSurface.surfaceId"
483
- });
484
- }
485
- if (!createSurface2.catalogId) {
486
- errors.push({
487
- code: "MISSING_CATALOG_ID",
488
- message: "createSurface.catalogId is required",
489
- path: "createSurface.catalogId"
490
- });
491
- }
492
- } else if ("updateComponents" in message) {
493
- const { updateComponents: updateComponents2 } = message;
494
- if (!updateComponents2.surfaceId) {
495
- errors.push({
496
- code: "MISSING_SURFACE_ID",
497
- message: "updateComponents.surfaceId is required",
498
- path: "updateComponents.surfaceId"
499
- });
500
- }
501
- if (!updateComponents2.components || !Array.isArray(updateComponents2.components)) {
502
- errors.push({
503
- code: "INVALID_COMPONENTS",
504
- message: "updateComponents.components must be an array",
505
- path: "updateComponents.components"
506
- });
507
- } else {
508
- validateComponentsV09(updateComponents2.components, errors, warnings, options);
509
- }
510
- } else if ("updateDataModel" in message) {
511
- const { updateDataModel: updateDataModel2 } = message;
512
- if (!updateDataModel2.surfaceId) {
513
- errors.push({
514
- code: "MISSING_SURFACE_ID",
515
- message: "updateDataModel.surfaceId is required",
516
- path: "updateDataModel.surfaceId"
517
- });
518
- }
519
- } else if ("deleteSurface" in message) {
520
- const { deleteSurface: deleteSurface2 } = message;
521
- if (!deleteSurface2.surfaceId) {
522
- errors.push({
523
- code: "MISSING_SURFACE_ID",
524
- message: "deleteSurface.surfaceId is required",
525
- path: "deleteSurface.surfaceId"
526
- });
527
- }
528
- } else {
529
- errors.push({
530
- code: "INVALID_MESSAGE_TYPE",
531
- message: "Message must contain one of: createSurface, updateComponents, updateDataModel, deleteSurface"
532
- });
533
- }
534
- return {
535
- valid: errors.length === 0,
536
- errors,
537
- warnings
538
- };
539
- }
540
- function validateV08Message(message, options = {}) {
541
- const errors = [];
542
- const warnings = [];
543
- if ("beginRendering" in message) {
544
- const { beginRendering: beginRendering2 } = message;
545
- if (!beginRendering2.surfaceId) {
546
- errors.push({
547
- code: "MISSING_SURFACE_ID",
548
- message: "beginRendering.surfaceId is required",
549
- path: "beginRendering.surfaceId"
550
- });
551
- }
552
- if (!beginRendering2.root) {
553
- errors.push({
554
- code: "MISSING_ROOT",
555
- message: "beginRendering.root is required",
556
- path: "beginRendering.root"
557
- });
558
- }
559
- } else if ("surfaceUpdate" in message) {
560
- const { surfaceUpdate: surfaceUpdate2 } = message;
561
- if (!surfaceUpdate2.surfaceId) {
562
- errors.push({
563
- code: "MISSING_SURFACE_ID",
564
- message: "surfaceUpdate.surfaceId is required",
565
- path: "surfaceUpdate.surfaceId"
566
- });
567
- }
568
- if (!surfaceUpdate2.components || !Array.isArray(surfaceUpdate2.components)) {
569
- errors.push({
570
- code: "INVALID_COMPONENTS",
571
- message: "surfaceUpdate.components must be an array",
572
- path: "surfaceUpdate.components"
573
- });
574
- } else {
575
- validateComponentsV08(surfaceUpdate2.components, errors, warnings, options);
576
- }
577
- } else if ("dataModelUpdate" in message) {
578
- const { dataModelUpdate: dataModelUpdate2 } = message;
579
- if (!dataModelUpdate2.surfaceId) {
580
- errors.push({
581
- code: "MISSING_SURFACE_ID",
582
- message: "dataModelUpdate.surfaceId is required",
583
- path: "dataModelUpdate.surfaceId"
584
- });
585
- }
586
- if (!dataModelUpdate2.contents || !Array.isArray(dataModelUpdate2.contents)) {
587
- errors.push({
588
- code: "INVALID_CONTENTS",
589
- message: "dataModelUpdate.contents must be an array",
590
- path: "dataModelUpdate.contents"
591
- });
592
- }
593
- } else if ("deleteSurface" in message) {
594
- const { deleteSurface: deleteSurface2 } = message;
595
- if (!deleteSurface2.surfaceId) {
596
- errors.push({
597
- code: "MISSING_SURFACE_ID",
598
- message: "deleteSurface.surfaceId is required",
599
- path: "deleteSurface.surfaceId"
600
- });
601
- }
602
- } else {
603
- errors.push({
604
- code: "INVALID_MESSAGE_TYPE",
605
- message: "Message must contain one of: beginRendering, surfaceUpdate, dataModelUpdate, deleteSurface"
606
- });
607
- }
608
- return {
609
- valid: errors.length === 0,
610
- errors,
611
- warnings
612
- };
613
- }
614
- function validateMessage(message, options = {}) {
615
- if ("createSurface" in message || "updateComponents" in message || "updateDataModel" in message) {
616
- return validateV09Message(message, options);
617
- }
618
- if ("beginRendering" in message || "surfaceUpdate" in message || "dataModelUpdate" in message) {
619
- return validateV08Message(message, options);
620
- }
621
- if ("deleteSurface" in message) {
622
- if (!message.deleteSurface.surfaceId) {
623
- return {
624
- valid: false,
625
- errors: [{
626
- code: "MISSING_SURFACE_ID",
627
- message: "deleteSurface.surfaceId is required",
628
- path: "deleteSurface.surfaceId"
629
- }],
630
- warnings: []
631
- };
632
- }
633
- return { valid: true, errors: [], warnings: [] };
634
- }
635
- return {
636
- valid: false,
637
- errors: [{
638
- code: "UNKNOWN_MESSAGE_TYPE",
639
- message: "Unknown message type"
640
- }],
641
- warnings: []
642
- };
643
- }
644
- function validateMessages(messages, options = {}) {
645
- const errors = [];
646
- const warnings = [];
647
- for (let i = 0; i < messages.length; i++) {
648
- const result = validateMessage(messages[i], options);
649
- for (const error of result.errors) {
650
- errors.push({
651
- ...error,
652
- path: `messages[${i}].${error.path || ""}`
653
- });
654
- }
655
- for (const warning of result.warnings) {
656
- warnings.push({
657
- ...warning,
658
- path: `messages[${i}].${warning.path || ""}`
659
- });
660
- }
661
- }
662
- return {
663
- valid: errors.length === 0,
664
- errors,
665
- warnings
666
- };
667
- }
668
- function validateComponentsV09(components, errors, warnings, options) {
669
- const componentIds = /* @__PURE__ */ new Set();
670
- let hasRoot = false;
671
- for (let i = 0; i < components.length; i++) {
672
- const comp = components[i];
673
- const path2 = `updateComponents.components[${i}]`;
674
- if (!comp.id) {
675
- errors.push({
676
- code: "MISSING_COMPONENT_ID",
677
- message: "Component id is required",
678
- path: `${path2}.id`
679
- });
680
- } else {
681
- if (componentIds.has(comp.id)) {
682
- errors.push({
683
- code: "DUPLICATE_COMPONENT_ID",
684
- message: `Duplicate component id: ${comp.id}`,
685
- path: `${path2}.id`
686
- });
687
- }
688
- componentIds.add(comp.id);
689
- if (comp.id === "root") {
690
- hasRoot = true;
691
- }
692
- }
693
- if (!comp.component) {
694
- errors.push({
695
- code: "MISSING_COMPONENT_TYPE",
696
- message: "Component type is required",
697
- path: `${path2}.component`
698
- });
699
- } else if (options.strict && options.allowedComponents) {
700
- if (!options.allowedComponents.includes(comp.component)) {
701
- warnings.push({
702
- code: "UNKNOWN_COMPONENT_TYPE",
703
- message: `Unknown component type: ${comp.component}`,
704
- path: `${path2}.component`
705
- });
706
- }
707
- }
708
- }
709
- if (!hasRoot && options.strict) {
710
- warnings.push({
711
- code: "MISSING_ROOT_COMPONENT",
712
- message: 'No component with id "root" found',
713
- path: "updateComponents.components"
714
- });
715
- }
716
- }
717
- function validateComponentsV08(components, errors, warnings, options) {
718
- const componentIds = /* @__PURE__ */ new Set();
719
- for (let i = 0; i < components.length; i++) {
720
- const comp = components[i];
721
- const path2 = `surfaceUpdate.components[${i}]`;
722
- if (!comp.id) {
723
- errors.push({
724
- code: "MISSING_COMPONENT_ID",
725
- message: "Component id is required",
726
- path: `${path2}.id`
727
- });
728
- } else {
729
- if (componentIds.has(comp.id)) {
730
- errors.push({
731
- code: "DUPLICATE_COMPONENT_ID",
732
- message: `Duplicate component id: ${comp.id}`,
733
- path: `${path2}.id`
734
- });
735
- }
736
- componentIds.add(comp.id);
737
- }
738
- if (!comp.component || typeof comp.component !== "object") {
739
- errors.push({
740
- code: "MISSING_COMPONENT",
741
- message: "Component definition is required",
742
- path: `${path2}.component`
743
- });
744
- } else {
745
- const componentType = Object.keys(comp.component)[0];
746
- if (options.strict && !STANDARD_COMPONENT_TYPES.includes(componentType)) {
747
- warnings.push({
748
- code: "UNKNOWN_COMPONENT_TYPE",
749
- message: `Unknown component type: ${componentType}`,
750
- path: `${path2}.component`
751
- });
752
- }
753
- }
754
- }
755
- }
756
-
757
- // src/utils/index.ts
758
- function isPathBinding(value) {
759
- return typeof value === "object" && value !== null && "path" in value;
760
- }
761
- function getLiteralValue(value) {
762
- if (isPathBinding(value)) {
763
- return void 0;
764
- }
765
- return value;
766
- }
767
- function getPathValue(value) {
768
- if (isPathBinding(value)) {
769
- return value.path;
770
- }
771
- return void 0;
772
- }
773
- function path(dataPath) {
774
- return { path: dataPath };
775
- }
776
- function deepMerge(target, source) {
777
- const result = { ...target };
778
- for (const key of Object.keys(source)) {
779
- const sourceValue = source[key];
780
- const targetValue = result[key];
781
- if (sourceValue !== void 0 && typeof sourceValue === "object" && sourceValue !== null && !Array.isArray(sourceValue) && typeof targetValue === "object" && targetValue !== null && !Array.isArray(targetValue)) {
782
- result[key] = deepMerge(
783
- targetValue,
784
- sourceValue
785
- );
786
- } else if (sourceValue !== void 0) {
787
- result[key] = sourceValue;
788
- }
789
- }
790
- return result;
791
- }
792
- function uuid() {
793
- return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
794
- const r = Math.random() * 16 | 0;
795
- const v = c === "x" ? r : r & 3 | 8;
796
- return v.toString(16);
797
- });
798
- }
799
-
800
- export { A2UI_EXTENSION_URI, A2UI_EXTENSION_URI_V08, A2UI_MIME_TYPE, DEFAULT_PATH_MAPPINGS, STANDARD_CATALOG_ID, audioPlayer, beginRendering, body, button, caption, card, checkbox, choicePicker, column, createSurface, createV08Messages, createV09Messages, dataModelInit, dataModelUpdate, dateTimeInput, deepMerge, deleteSurface, deleteSurfaceV08, divider, flattenObjectToValueMap, generateId, getIdCounter, getLiteralValue, getPathValue, h1, h2, h3, h4, h5, icon, image, isPathBinding, isV08Message, isV09Message, jsonlToMessages, list, messagesToJsonl, modal, normalizePath, objectToValueMap, path, pathUpdate, resetIdCounter, row, slider, surfaceUpdate, tabs, text, textButton, textField, updateComponents, updateDataModel, updatesToValueMap, uuid, validateMessage, validateMessages, validateV08Message, validateV09Message, valueMapToObject, valueToValueMap, video };
801
- //# sourceMappingURL=index.js.map
802
- //# sourceMappingURL=index.js.map
1
+ function U(e){return "createSurface"in e||"updateComponents"in e||"updateDataModel"in e}function N(e){return "beginRendering"in e||"surfaceUpdate"in e||"dataModelUpdate"in e}var l="https://a2ui.dev/specification/0.9/standard_catalog_definition.json",_="https://a2ui.org/a2a-extension/a2ui/v0.8",E="https://a2ui.dev/specification/0.9",R="application/json+a2ui";var f=0;function p(e="comp"){return `${e}_${Date.now()}_${f++}`}function w(){f=0;}function k(){return f}function d(e,t={}){let{id:n=p("text"),weight:a,usageHint:o}=t;return {id:n,component:"Text",text:e,...a!==void 0&&{weight:a},...o&&{usageHint:o}}}function j(e,t={}){let{id:n=p("image"),weight:a,fit:o,usageHint:r}=t;return {id:n,component:"Image",url:e,...a!==void 0&&{weight:a},...o&&{fit:o},...r&&{usageHint:r}}}function B(e,t={}){let{id:n=p("icon"),weight:a}=t;return {id:n,component:"Icon",name:e,...a!==void 0&&{weight:a}}}function L(e,t={}){let{id:n=p("video"),weight:a}=t;return {id:n,component:"Video",url:e,...a!==void 0&&{weight:a}}}function $(e,t={}){let{id:n=p("audio"),weight:a,description:o}=t;return {id:n,component:"AudioPlayer",url:e,...a!==void 0&&{weight:a},...o&&{description:o}}}function F(e,t={}){let{id:n=p("row"),weight:a,alignment:o,distribution:r}=t;return {id:n,component:"Row",children:e,...a!==void 0&&{weight:a},...o&&{alignment:o},...r&&{distribution:r}}}function G(e,t={}){let{id:n=p("column"),weight:a,alignment:o,distribution:r}=t;return {id:n,component:"Column",children:e,...a!==void 0&&{weight:a},...o&&{alignment:o},...r&&{distribution:r}}}function H(e,t={}){let{id:n=p("list"),weight:a,direction:o,alignment:r}=t;return {id:n,component:"List",children:e,...a!==void 0&&{weight:a},...o&&{direction:o},...r&&{alignment:r}}}function q(e,t={}){let{id:n=p("card"),weight:a}=t;return {id:n,component:"Card",child:e,...a!==void 0&&{weight:a}}}function W(e,t={}){let{id:n=p("tabs"),weight:a}=t;return {id:n,component:"Tabs",tabItems:e.map(o=>({title:o.title,child:o.childId})),...a!==void 0&&{weight:a}}}function Y(e={}){let{id:t=p("divider"),weight:n,axis:a}=e;return {id:t,component:"Divider",...n!==void 0&&{weight:n},...a&&{axis:a}}}function X(e,t,n={}){let{id:a=p("modal"),weight:o}=n;return {id:a,component:"Modal",entryPointChild:e,contentChild:t,...o!==void 0&&{weight:o}}}function C(e,t,n={}){let{id:a=p("button"),weight:o,primary:r}=n;return {id:a,component:"Button",child:e,action:t,...o!==void 0&&{weight:o},...r!==void 0&&{primary:r}}}function z(e,t,n={}){let{id:a=p("checkbox"),weight:o}=n;return {id:a,component:"CheckBox",label:e,value:t,...o!==void 0&&{weight:o}}}function J(e,t,n={}){let{id:a=p("textfield"),weight:o,usageHint:r,validationRegexp:i}=n;return {id:a,component:"TextField",label:e,...t!==void 0&&{text:t},...o!==void 0&&{weight:o},...r&&{usageHint:r},...i&&{validationRegexp:i}}}function K(e,t={}){let{id:n=p("datetime"),weight:a,enableDate:o,enableTime:r,outputFormat:i,label:s}=t;return {id:n,component:"DateTimeInput",value:e,...a!==void 0&&{weight:a},...o!==void 0&&{enableDate:o},...r!==void 0&&{enableTime:r},...i&&{outputFormat:i},...s&&{label:s}}}function Q(e,t,n,a={}){let{id:o=p("choice"),weight:r,label:i}=a;return {id:o,component:"ChoicePicker",options:e,value:t,usageHint:n,...r!==void 0&&{weight:r},...i&&{label:i}}}function Z(e,t={}){let{id:n=p("slider"),weight:a,label:o,min:r,max:i}=t;return {id:n,component:"Slider",value:e,...a!==void 0&&{weight:a},...o&&{label:o},...r!==void 0&&{min:r},...i!==void 0&&{max:i}}}function ee(e,t,n={}){let a=n.textId??p("btn_text"),o=d(e,{id:a}),r=C(a,t,n);return [o,r]}function te(e,t={}){return d(e,{...t,usageHint:"h1"})}function ne(e,t={}){return d(e,{...t,usageHint:"h2"})}function oe(e,t={}){return d(e,{...t,usageHint:"h3"})}function ae(e,t={}){return d(e,{...t,usageHint:"h4"})}function re(e,t={}){return d(e,{...t,usageHint:"h5"})}function ie(e,t={}){return d(e,{...t,usageHint:"caption"})}function se(e,t={}){return d(e,{...t,usageHint:"body"})}var M={};function g(e,t=""){let n=[];for(let[a,o]of Object.entries(e)){let r=t?`${t}/${a}`:`/${a}`;n.push(c(r,o));}return n}function c(e,t){if(t==null)return {key:e,valueString:""};if(typeof t=="string")return {key:e,valueString:t};if(typeof t=="number")return {key:e,valueNumber:t};if(typeof t=="boolean")return {key:e,valueBoolean:t};if(Array.isArray(t))return {key:e,valueMap:t.map((n,a)=>c(String(a),n))};if(typeof t=="object"){let n=[];for(let[a,o]of Object.entries(t))n.push(c(a,o));return {key:e,valueMap:n}}return {key:e,valueString:String(t)}}function I(e,t={}){let n=e.replace(/\./g,"/");n.startsWith("/")||(n=`/${n}`);for(let[a,o]of Object.entries(t)){let r=new RegExp(`^/${a}(/|$)`);r.test(n)&&(n=n.replace(r,`/${o}$1`));}return n}function pe(e,t="",n=M){let a=[];for(let o of e){let r=o.path.startsWith("/")?o.path:`${t}/${o.path}`,i=I(r,n);if(o.value!==null&&typeof o.value=="object"&&!Array.isArray(o.value)){let s=m(o.value,i);a.push(...s);}else a.push(c(i,o.value));}return a}function m(e,t){let n=[];for(let[a,o]of Object.entries(e)){let r=`${t}/${a}`;if(o!==null&&typeof o=="object"&&!Array.isArray(o)){let i=m(o,r);n.push(...i);}else n.push(c(r,o));}return n}function h(e){let t={};for(let n of e){let a=n.key.startsWith("/")?n.key.slice(1):n.key;n.valueString!==void 0?t[a]=n.valueString:n.valueNumber!==void 0?t[a]=n.valueNumber:n.valueBoolean!==void 0?t[a]=n.valueBoolean:n.valueMap!==void 0&&(t[a]=h(n.valueMap));}return t}function x(e,t=l){return {createSurface:{surfaceId:e,catalogId:t}}}function O(e,t){return {updateComponents:{surfaceId:e,components:t}}}function S(e,t,n,a="replace"){return {updateDataModel:{surfaceId:e,...n&&{path:n},op:a,...a!=="remove"&&{value:t}}}}function de(e){return {deleteSurface:{surfaceId:e}}}function ce(e){let{surfaceId:t,catalogId:n=l,components:a,dataModel:o}=e,r=[x(t,n),O(t,a)];return o&&r.push(S(t,o)),r}function T(e,t="@default",n){return {beginRendering:{surfaceId:t,root:e,...n&&{styles:n}}}}function y(e,t="@default"){return {surfaceUpdate:{surfaceId:t,components:e}}}function V(e,t="@default",n){return {dataModelUpdate:{surfaceId:t,contents:e,...n&&{path:n}}}}function D(e,t="@default"){return V(g(e),t)}function ue(e,t,n="@default"){return {dataModelUpdate:{surfaceId:n,path:e,contents:[c("",t)]}}}function le(e){return {deleteSurface:{surfaceId:e}}}function ge(e){let{rootId:t,components:n,dataModel:a,surfaceId:o="@default",styles:r}=e,i=[y(n,o)];return a&&i.push(D(a,o)),i.push(T(t,o,r)),i}function me(e){return e.map(t=>JSON.stringify(t)).join(`
2
+ `)}function fe(e){return e.split(`
3
+ `).filter(t=>t.trim()).map(t=>JSON.parse(t))}var Ie=["Text","Image","Icon","Video","AudioPlayer","Row","Column","List","Card","Tabs","Divider","Modal","Button","CheckBox","TextField","DateTimeInput","ChoicePicker","Slider"];function b(e,t={}){let n=[],a=[];if("createSurface"in e){let{createSurface:o}=e;o.surfaceId||n.push({code:"MISSING_SURFACE_ID",message:"createSurface.surfaceId is required",path:"createSurface.surfaceId"}),o.catalogId||n.push({code:"MISSING_CATALOG_ID",message:"createSurface.catalogId is required",path:"createSurface.catalogId"});}else if("updateComponents"in e){let{updateComponents:o}=e;o.surfaceId||n.push({code:"MISSING_SURFACE_ID",message:"updateComponents.surfaceId is required",path:"updateComponents.surfaceId"}),!o.components||!Array.isArray(o.components)?n.push({code:"INVALID_COMPONENTS",message:"updateComponents.components must be an array",path:"updateComponents.components"}):he(o.components,n,a,t);}else if("updateDataModel"in e){let{updateDataModel:o}=e;o.surfaceId||n.push({code:"MISSING_SURFACE_ID",message:"updateDataModel.surfaceId is required",path:"updateDataModel.surfaceId"});}else if("deleteSurface"in e){let{deleteSurface:o}=e;o.surfaceId||n.push({code:"MISSING_SURFACE_ID",message:"deleteSurface.surfaceId is required",path:"deleteSurface.surfaceId"});}else n.push({code:"INVALID_MESSAGE_TYPE",message:"Message must contain one of: createSurface, updateComponents, updateDataModel, deleteSurface"});return {valid:n.length===0,errors:n,warnings:a}}function P(e,t={}){let n=[],a=[];if("beginRendering"in e){let{beginRendering:o}=e;o.surfaceId||n.push({code:"MISSING_SURFACE_ID",message:"beginRendering.surfaceId is required",path:"beginRendering.surfaceId"}),o.root||n.push({code:"MISSING_ROOT",message:"beginRendering.root is required",path:"beginRendering.root"});}else if("surfaceUpdate"in e){let{surfaceUpdate:o}=e;o.surfaceId||n.push({code:"MISSING_SURFACE_ID",message:"surfaceUpdate.surfaceId is required",path:"surfaceUpdate.surfaceId"}),!o.components||!Array.isArray(o.components)?n.push({code:"INVALID_COMPONENTS",message:"surfaceUpdate.components must be an array",path:"surfaceUpdate.components"}):xe(o.components,n,a,t);}else if("dataModelUpdate"in e){let{dataModelUpdate:o}=e;o.surfaceId||n.push({code:"MISSING_SURFACE_ID",message:"dataModelUpdate.surfaceId is required",path:"dataModelUpdate.surfaceId"}),(!o.contents||!Array.isArray(o.contents))&&n.push({code:"INVALID_CONTENTS",message:"dataModelUpdate.contents must be an array",path:"dataModelUpdate.contents"});}else if("deleteSurface"in e){let{deleteSurface:o}=e;o.surfaceId||n.push({code:"MISSING_SURFACE_ID",message:"deleteSurface.surfaceId is required",path:"deleteSurface.surfaceId"});}else n.push({code:"INVALID_MESSAGE_TYPE",message:"Message must contain one of: beginRendering, surfaceUpdate, dataModelUpdate, deleteSurface"});return {valid:n.length===0,errors:n,warnings:a}}function v(e,t={}){return "createSurface"in e||"updateComponents"in e||"updateDataModel"in e?b(e,t):"beginRendering"in e||"surfaceUpdate"in e||"dataModelUpdate"in e?P(e,t):"deleteSurface"in e?e.deleteSurface.surfaceId?{valid:true,errors:[],warnings:[]}:{valid:false,errors:[{code:"MISSING_SURFACE_ID",message:"deleteSurface.surfaceId is required",path:"deleteSurface.surfaceId"}],warnings:[]}:{valid:false,errors:[{code:"UNKNOWN_MESSAGE_TYPE",message:"Unknown message type"}],warnings:[]}}function Ce(e,t={}){let n=[],a=[];for(let o=0;o<e.length;o++){let r=e[o];if(!r)continue;let i=v(r,t);for(let s of i.errors)n.push({...s,path:`messages[${o}].${s.path??""}`});for(let s of i.warnings)a.push({...s,path:`messages[${o}].${s.path??""}`});}return {valid:n.length===0,errors:n,warnings:a}}function he(e,t,n,a){let o=new Set,r=false;for(let i=0;i<e.length;i++){let s=e[i];if(!s)continue;let u=`updateComponents.components[${i}]`;s.id?(o.has(s.id)&&t.push({code:"DUPLICATE_COMPONENT_ID",message:`Duplicate component id: ${s.id}`,path:`${u}.id`}),o.add(s.id),s.id==="root"&&(r=true)):t.push({code:"MISSING_COMPONENT_ID",message:"Component id is required",path:`${u}.id`}),s.component?a.strict&&a.allowedComponents&&(a.allowedComponents.includes(s.component)||n.push({code:"UNKNOWN_COMPONENT_TYPE",message:`Unknown component type: ${s.component}`,path:`${u}.component`})):t.push({code:"MISSING_COMPONENT_TYPE",message:"Component type is required",path:`${u}.component`});}!r&&a.strict&&n.push({code:"MISSING_ROOT_COMPONENT",message:'No component with id "root" found',path:"updateComponents.components"});}function xe(e,t,n,a){let o=new Set;for(let r=0;r<e.length;r++){let i=e[r];if(!i)continue;let s=`surfaceUpdate.components[${r}]`;if(i.id?(o.has(i.id)&&t.push({code:"DUPLICATE_COMPONENT_ID",message:`Duplicate component id: ${i.id}`,path:`${s}.id`}),o.add(i.id)):t.push({code:"MISSING_COMPONENT_ID",message:"Component id is required",path:`${s}.id`}),!i.component||typeof i.component!="object")t.push({code:"MISSING_COMPONENT",message:"Component definition is required",path:`${s}.component`});else {let u=Object.keys(i.component)[0];u&&a.strict&&!Ie.includes(u)&&n.push({code:"UNKNOWN_COMPONENT_TYPE",message:`Unknown component type: ${u}`,path:`${s}.component`});}}}function A(e){return typeof e=="object"&&e!==null&&"path"in e}function Oe(e){if(!A(e))return e}function Se(e){if(A(e))return e.path}function Te(e){return {path:e}}function Me(e,t){let n={...e};for(let a of Object.keys(t)){let o=t[a],r=n[a];o!==void 0&&typeof o=="object"&&o!==null&&!Array.isArray(o)&&typeof r=="object"&&r!==null&&!Array.isArray(r)?n[a]=Me(r,o):o!==void 0&&(n[a]=o);}return n}function ye(){return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{let t=Math.random()*16|0;return (e==="x"?t:t&3|8).toString(16)})}export{E as A2UI_EXTENSION_URI,_ as A2UI_EXTENSION_URI_V08,R as A2UI_MIME_TYPE,M as DEFAULT_PATH_MAPPINGS,l as STANDARD_CATALOG_ID,$ as audioPlayer,T as beginRendering,se as body,C as button,ie as caption,q as card,z as checkbox,Q as choicePicker,G as column,x as createSurface,ge as createV08Messages,ce as createV09Messages,D as dataModelInit,V as dataModelUpdate,K as dateTimeInput,Me as deepMerge,de as deleteSurface,le as deleteSurfaceV08,Y as divider,m as flattenObjectToValueMap,p as generateId,k as getIdCounter,Oe as getLiteralValue,Se as getPathValue,te as h1,ne as h2,oe as h3,ae as h4,re as h5,B as icon,j as image,A as isPathBinding,N as isV08Message,U as isV09Message,fe as jsonlToMessages,H as list,me as messagesToJsonl,X as modal,I as normalizePath,g as objectToValueMap,Te as path,ue as pathUpdate,w as resetIdCounter,F as row,Z as slider,y as surfaceUpdate,W as tabs,d as text,ee as textButton,J as textField,O as updateComponents,S as updateDataModel,pe as updatesToValueMap,ye as uuid,v as validateMessage,Ce as validateMessages,P as validateV08Message,b as validateV09Message,h as valueMapToObject,c as valueToValueMap,L as video};