55import 'dart:convert' ;
66
77import 'package:flutter/material.dart' ;
8+ import 'package:flutter/services.dart' ;
89
9- import '../model/a2ui_message.dart' ;
1010import '../model/catalog.dart' ;
1111import '../primitives/simple_items.dart' ;
1212
@@ -78,38 +78,54 @@ abstract class PromptBuilder {
7878 /// The builder will generate a prompt for a chat session,
7979 /// that instructs to create new surfaces for each response
8080 /// and restrict surface deletion and updates.
81- factory PromptBuilder . chat ({
81+ static Future < PromptBuilder > createChat ({
8282 required Catalog catalog,
8383 Iterable <String > systemPromptFragments = const [],
8484 String importancePrefix = defaultImportancePrefix,
8585 JsonMap ? clientDataModel,
86- }) {
86+ }) async {
87+ final String commonTypes = await rootBundle.loadString (
88+ 'packages/genui/submodules/a2ui/specification/v0_9/json/common_types.json' ,
89+ );
90+ final String serverToClient = await rootBundle.loadString (
91+ 'packages/genui/submodules/a2ui/specification/v0_9/json/server_to_client.json' ,
92+ );
8793 return _BasicPromptBuilder (
8894 catalog: catalog,
8995 systemPromptFragments: systemPromptFragments,
9096 allowedOperations: SurfaceOperations .createOnly (dataModel: false ),
9197 importancePrefix: importancePrefix,
9298 clientDataModel: clientDataModel,
9399 technicalPossibilities: const TechnicalPossibilities (),
100+ commonTypesSchema: commonTypes,
101+ serverToClientSchema: serverToClient,
94102 );
95103 }
96104
97- factory PromptBuilder . custom ({
105+ static Future < PromptBuilder > createCustom ({
98106 required Catalog catalog,
99107 required SurfaceOperations allowedOperations,
100108 Iterable <String > systemPromptFragments = const [],
101109 String importancePrefix = defaultImportancePrefix,
102110 TechnicalPossibilities technicalPossibilities =
103111 const TechnicalPossibilities (),
104112 JsonMap ? clientDataModel,
105- }) {
113+ }) async {
114+ final String commonTypes = await rootBundle.loadString (
115+ 'packages/genui/submodules/a2ui/specification/v0_9/json/common_types.json' ,
116+ );
117+ final String serverToClient = await rootBundle.loadString (
118+ 'packages/genui/submodules/a2ui/specification/v0_9/json/server_to_client.json' ,
119+ );
106120 return _BasicPromptBuilder (
107121 catalog: catalog,
108122 systemPromptFragments: systemPromptFragments,
109123 allowedOperations: allowedOperations,
110124 importancePrefix: importancePrefix,
111125 clientDataModel: clientDataModel,
112126 technicalPossibilities: technicalPossibilities,
127+ commonTypesSchema: commonTypes,
128+ serverToClientSchema: serverToClient,
113129 );
114130 }
115131
@@ -332,9 +348,13 @@ final class _BasicPromptBuilder extends PromptBuilder {
332348 required this .importancePrefix,
333349 required this .clientDataModel,
334350 required this .technicalPossibilities,
351+ required this .commonTypesSchema,
352+ required this .serverToClientSchema,
335353 }) : super ._();
336354
337355 final Catalog catalog;
356+ final String commonTypesSchema;
357+ final String serverToClientSchema;
338358
339359 final SurfaceOperations allowedOperations;
340360
@@ -359,36 +379,84 @@ final class _BasicPromptBuilder extends PromptBuilder {
359379
360380 @override
361381 Iterable <String > systemPrompt () {
362- final String a2uiSchema = A2uiMessage .a2uiMessageSchema (
363- catalog,
364- ).toJson (indent: ' ' );
382+ final String catalogSchema = _generateCatalogSchema (catalog);
365383
366384 final fragments = < String > [
367385 ...systemPromptFragments,
368386 'Use the provided tools to respond to user using rich UI elements.' ,
369387 ...technicalPossibilities.systemPromptFragment (),
370388 ...catalog.systemPromptFragments,
371389 ...allowedOperations.systemPromptFragments,
372- _fenced (a2uiSchema, sectionName: 'A2UI JSON SCHEMA' ),
373- if (catalog.functions.isNotEmpty)
374- _fenced (
375- const JsonEncoder .withIndent (' ' ).convert ([
376- for (final func in catalog.functions)
377- {
378- 'name' : func.name,
379- 'description' : func.description,
380- 'parameters' : func.argumentSchema.value,
381- 'returnType' : func.returnType.value,
382- },
383- ]),
384- sectionName: 'AVAILABLE FUNCTIONS' ,
385- ),
390+ _fenced (commonTypesSchema, sectionName: 'COMMON TYPES' ),
391+ _fenced (catalogSchema, sectionName: 'CATALOG SCHEMA' ),
392+ _fenced (serverToClientSchema, sectionName: 'MESSAGE SCHEMA' ),
386393 ? _encodedDataModel (clientDataModel),
387394 ];
388395
389396 return _fragmentsToPrompt (fragments);
390397 }
391398
399+ String _generateCatalogSchema (Catalog catalog) {
400+ final Map <String , dynamic > components = {
401+ for (final item in catalog.items)
402+ item.name: {
403+ 'type' : 'object' ,
404+ 'allOf' : [
405+ {r'$ref' : r'common_types.json#/$defs/ComponentCommon' },
406+ {r'$ref' : r'#/$defs/CatalogComponentCommon' },
407+ {
408+ 'type' : 'object' ,
409+ 'properties' : {
410+ 'component' : {'const' : item.name},
411+ ...item.dataSchema.value['properties' ] as Map <String , dynamic >,
412+ },
413+ 'required' : [
414+ 'component' ,
415+ ...? item.dataSchema.value['required' ] as List ? ,
416+ ],
417+ },
418+ ],
419+ 'unevaluatedProperties' : false ,
420+ },
421+ };
422+
423+ final Map <String , dynamic > functions = {
424+ for (final func in catalog.functions)
425+ func.name: {
426+ 'description' : func.description,
427+ 'parameters' : func.argumentSchema.value,
428+ 'returnType' : func.returnType.value,
429+ },
430+ };
431+
432+ final Map <String , dynamic > catalogJson = {
433+ r'$schema' : 'https://json-schema.org/draft/2020-12/schema' ,
434+ r'$id' : 'https://a2ui.org/specification/v0_9/catalog.json' ,
435+ 'title' : 'A2UI Catalog' ,
436+ 'description' : 'Custom catalog of A2UI components and functions.' ,
437+ if (catalog.catalogId != null ) 'catalogId' : catalog.catalogId,
438+ 'components' : components,
439+ if (functions.isNotEmpty) 'functions' : functions,
440+ r'$defs' : {
441+ 'CatalogComponentCommon' : {
442+ 'type' : 'object' ,
443+ 'properties' : {
444+ 'id' : {
445+ 'type' : 'string' ,
446+ 'description' :
447+ 'A unique identifier for this component instance within '
448+ 'the surface. This ID is used to refer to the component '
449+ 'in layout children arrays or event handlers.' ,
450+ },
451+ },
452+ 'required' : ['id' ],
453+ },
454+ },
455+ };
456+
457+ return const JsonEncoder .withIndent (' ' ).convert (catalogJson);
458+ }
459+
392460 static String ? _encodedDataModel (JsonMap ? clientDataModel) {
393461 if (clientDataModel == null ) return null ;
394462 final String encodedModel = const JsonEncoder .withIndent (
0 commit comments