a2ui_core 0.3.0
a2ui_core: ^0.3.0 copied to clipboard
Core of the A2UI protocol for Dart: messages, the data model, data binding and expressions shared by A2UI renderers and agents.
a2ui_core Changelog #
0.3.0 #
-
Catalog.commonTypesSchemaand the bundledcommon_typesschemas listdescriptionaftertype, following the reordered specification files. -
Breaking: Renamed
A2uiClientActionandA2uiClientErrortoA2uiRendererActionandA2uiRendererError. -
Breaking: Renamed
MessageProcessor.groupModeltoMessageProcessor.modeland removed theMessageProcessor.processalias forprocessMessages. -
Breaking: Renamed
DataContext.resolveSyncandresolveListenabletoresolveDynamicValueandresolveSignal, and addedresolveSignalWithPending.DataContextaddsprotocolVersion(A2uiProtocolVersion?),atLeastV10(true for v1.0 and every later version) andusesDirectives. -
Breaking: Renamed
EventListenable<T>toEventSource<T>and replacedaddListener/removeListenerwithEventSource.subscribe, returning aSubscriptionwith an idempotentunsubscribe()method. AddedDataModel.subscribe<T>, returning aDataSubscription<T>(which implementsSubscription). -
Breaking:
PayloadValidatorderives its rules andcommon_types.jsondocument fromcatalog.protocolVersion, and gains aconfigparameter (ValidationConfig).PayloadValidator.commonTypesFor(A2uiProtocolVersion)returns the embeddedcommon_types.jsondocument of a version. AddsValidationConfig.allowUnknownElements,A2uiValidationError.surfaceId, andComponentApi.allowedParents/allowedChildren. RemovedA2uiValidationError.detailsandMinimalCatalog. -
Adds dependencies on
package:intl(^0.20.0) andpackage:logging(^1.3.0). -
Behavior change: Self-referential and cyclic component references now throw
A2uiIntegrityError(INTEGRITY_ERROR) instead ofA2uiRecursionError(RECURSION_ERROR), reservingA2uiRecursionErrorfor exceeding the maximum component traversal depth (maxDepth) or function-call nesting depth (maxFunctionCallDepth). -
Export
GenericBinder,Behavior,BehaviorNode,resolveSchemaRefs, andinlineLocalRefsfrompackage:a2ui_core/a2ui_core.dart. -
Resolve cross-catalog
$refpointers across peer catalogs inresolvedComponentSchemas,validationSchema,refMap,PayloadValidatorandMessageProcessor:Catalog.withPeerCatalogsreturns a new linked catalog whoseCatalog.peerCatalogslists the given peers (and the catalog a pruned peer was derived from); the receiver is not changed. The linked copy is aCatalogeven when the receiver is a subclass.linkCatalogsreturns linked copies of the catalogs it is given, each linked with the others and with the optionalextraPeers. A catalog whose document holds no$refinto another catalog document is returned as it is.MessageProcessorlinks copies of the catalogs passed to it and holds those copies inMessageProcessor.catalogs; the catalogs passed in, such as a shared basic catalog, are not changed.- A
$refnames the peer whosecatalogIdor$idequals its document part, or of which one is a path suffix of the other, and failing that the peer with the same file name. A barecatalog.json, or a path ending in/catalog.jsonthat no peer matches exactly, names the catalog itself. resolveSchemaRefstakes an optionalpeersargument andinlineLocalRefsan optional fourthpeersargument: the documents cross-catalog references resolve against.
-
Catalog.fromJsonvalidates shorthandparametersmap keys against UAX #31 in v1.0 mode and wraps shorthand parameter maps in an object schema. -
CallRendererFunctionMessageandCallRendererFunctionOpaccept an optionalsurfaceId(String?). When provided,MessageProcessorevaluates the function call against that surface's rootDataContext(returningINVALID_FUNCTION_CALLif no such surface exists); when omitted, the call executes against an isolated empty root data model. -
Catalog.fromJsonmerges a component'sallOfpieces from least to most specific, so a property the component defines itself overrides the same property from a mixin or local definition (#3053). -
DataContextaddsparent,index,childContext(path, {index}), andsubscribeDynamicValue<T>, which returns aDataSubscription<T>.nestednow returns a child context linked to its parent. In v1.0 contexts, the@indexsystem function returns the enclosing template item's index plus an optionaloffset, and throwsA2uiValidationErroroutside a collection template. Dynamic values nested deeper thanmaxDynamicValueDepth(1000) fail withA2uiExpressionError.DataModeladdshas(path). -
NodeResolverlinks each node's data context to its parent node's context and gives template children their item index.ComponentNode.contextexposes the node'sComponentContext(null for placeholders), which the package barrel now exports, andNodeResolveraccepts an optionalcatalog:that must be the surface's default catalog.ChildNodeaddsindexfor template-expanded entries. -
Behavior change: A data binding to a path missing from the data model emits one
MISSING_DATA_BINDINGwarning per path onSurfaceModel.onWarning.NodeResolverdelivers these after the tree update commits, andComponentContexttakes anonMissingDatareporter to override delivery. -
Behavior change:
GenericBinderbinds theaccessibilityenvelope property'slabelanddescriptionas dynamic strings on every component, including components whose schema does not declareaccessibility. -
Behavior change: Template
ChildLists in v1.0 surfaces bind theirpathwith the v1.0@pathkey, so v1.0 templates expand. -
Added
Catalog.protocolVersion(A2uiProtocolVersion?) andCatalog.instructions.Catalog.fromJsonreads the document's value as a semantic version (1.0,v1.0and1.0.0all name v1.0; pre-release and build suffixes are ignored), takes anA2uiProtocolVersionfallback for documents that declare none, and throwsA2uiCatalogErrorfor a value it cannot parse or a version this SDK does not implement.toJsonandvalidationSchemawrite the version back as the bare form the catalog definition schema requires (1.0, notv1.0) and, from1.0, name functions under@callinstead ofcall.validationSchemarequiresargsonly for functions with required parameters.A2uiProtocolVersionaddssemverValueandtryParseSemVer. -
The package now embeds both
specification/v0_9/json/common_types.jsonand the updatedspecification/v1_0/json/common_types.json.CommonSchemasgainsdynamicNumber,dynamicStringList,dynamicValue,accessibilityAttributes,checkRuleandcomponentCommon, and the newCommonSchemasV1holds the v1.0 shapes keyed on@pathand@call; itsdynamicValuerejects literal objects with reserved single-@keys. -
Behavior change: envelope keys (
id,component,catalogId, plusaccessibilityandmetadatafrom v1.0) are stripped from every component, and from its schema's requirements, before the schema check, unless the component schema declares them;Catalogleavesid,componentandcatalogIdout of its component schemas, so those are always stripped. A closed (additionalProperties: false) schema usingallOfnow validates, a component that names its catalog passes a closed schema, and v1.0 componentmetadatais never rejected for being undeclared; from v1.0,accessibilityandmetadatathe schema doesn't declare are checked againstComponentCommon. AcatalogIdmust still be a string. -
Behavior change: composition constraints.
allowedParentsandallowedChildrenin a catalog are enforced byMessageProcessor, with the surface (Surface) as the implicit parent of the surface's root id; violations throwA2uiValidationErrorwith codeUNALLOWED_PARENTorUNALLOWED_CHILD, thesurfaceId, and a JSON Pointerpathinto the message when the offending parent arrived in it. -
Behavior change:
validateComponentchecks every nested function call against the catalog's schema for it, keyed on@callfor v1.0 catalogs andcallbelow that, and rejects calls passing more than 1000 arguments (also checked whenDataContextevaluates a call). For v1.0 catalogs, a call to a function the catalog does not declare passes with its arguments unchecked whenValidationConfig.allowUnknownElementsis true (or when targeting a foreign catalog withcatalogId), because a renderer forwards it to the agent; otherwise an unknown function is rejected. -
Behavior change: v1.0 catalogs require UAX #31 identifiers for component ids, component and property names, function names and argument names, and
createSurface.metadata.extensionskeys, reject@-prefixed function names inCatalog.fromJson(reserving@for system functions such as@index), and reject objects with unrecognized single-@keys (codeINVALID_RESERVED_KEY);@@nameremains an escaped literal key. -
Behavior change: a
$refinto a document the SDK holds that names nothing now throwsA2uiCatalogError("Unresolvable schema reference: '<ref>'")instead of silently leaving the subschema unconstrained, and pointers follow array indices (#/$defs/X/oneOf/0). A local#/$defs/<Name>the catalog does not define falls back tocommon_types.json. A shared type that only the other protocol version'scommon_types.jsondefines (such as the v1.0Childin a catalog that declares no version) resolves against that document; types both versions define, such asDataBindingandFunctionCall, always resolve against the catalog's own version, so a v0.9 catalog does not accept@pathor@callshapes.resolveSchemaRefsreads only a document named exactlycatalog.json, or a path ending in/catalog.json, as the catalog itself, and onlycommon_types.json, or a path ending in/common_types.json, as the common types. A reference to any other document that no peer catalog matches, such asother.json#/components/Xormcp_catalog.json#/..., throwsA2uiCatalogErroras well, soPayloadValidatorreports it rather than accepting any value. -
Validation errors carry JSON Pointer
paths and per-errorerrorsdetails; a dangling reference reports/components/<index>/children/<n>. -
Added
MessageProcessor.getRendererCapabilities(CapabilitiesOptions), which returns anA2uiRendererCapabilitieswith one entry per requested version and raisesA2uiValidationErrorfor an empty version list. Inline catalogs use the legacy shape below v1.0 and the catalog document from v1.0. -
Breaking:
A2uiVersionCapabilities.toJsontakes a requiredversionand shapes inline catalogs for it;A2uiRendererCapabilities.toJsonandgetRendererCapabilitiesuse the same code. -
Behavior change: Legacy inline catalogs are derived from
Catalog.validationSchema, so a component's properties and required list match the catalog document (which mergesallOfmembers).idandcomponentare left to theComponentCommonenvelope, bundled common-type refs becomecommon_types.json#/$defs/...refs again, other local refs are inlined when they resolve and dropped otherwise, and function entries carrydescription. -
Breaking: Removed
MessageProcessor.getClientCapabilitiesandgetClientDataModel. UsegetRendererCapabilities(CapabilitiesOptions(versions: [A2uiProtocolVersion.v0_9], includeInlineCatalogs: ...)).toJson()andgetRendererDataModel(). -
Behavior change:
getRendererDataModeltakes an optionalversion. With one, it returns only the surfaces compatible with that version. Without one, it reports the version the surfaces share, defaults tov1.0when none records a version, and raisesA2uiValidationErrorwhen the surfaces record different versions. It returnsMap<String, Object?>?. -
Added the RPC layer:
RpcHandlersendscallAgentFunctionmessages through anOutboundMessageListenerand settles them fromagentFunctionResponse, and answerscallRendererFunctionwith arendererFunctionResponse.CallOptionssets a call'sfunctionCallId,timeout, envelopeversionandCancellationSignal;ExecutionContextsays whether an inbound call runs within a user activation.RpcErrorCodelists the protocol's codes andA2uiRpcErrorcarries one with thefunctionCallIdand any agent-reported details. An inbound call is refused withINVALID_FUNCTION_CALLwhen its catalog or function is missing, the catalog's protocol version does not match the message's, the function isrendererOnly, it requires a user activation the call lacks, or its arguments fail the schema; a function that throws answersEXECUTION_ERROR. -
MessageProcessorowns anRpcHandlerasrpc, takes anoutboundListener(OutboundMessageListener) for the messages it sends and adefaultTimeoutfor outbound calls, mirrorscallAgentFunction, and addsdispose, which cancels pending calls and disposes every surface. Behavior change:callRendererFunctionandagentFunctionResponsemessages are now executed rather than ignored.processMessagesandprocessMessagesAsynctakeisUserActivated; the latter completes once everycallRendererFunctionin the payload has been answered. -
FunctionApiaddsallowedCallers(AllowedCallers.rendererOnly,agentOnlyorrendererOrAgent, defaultrendererOnly) andrequiresUserActivation, read byCatalog.fromJsonfrom both function forms.declaredAllowedCallersanddeclaredRequiresUserActivationhold what the definition states, null when it states nothing, andtoJsonandvalidationSchemaemit a value only when it is declared, even when it is the default.BasicFunctioncarries them, soBasicCatalog.v1_0().functions['openUrl']requires a user activation. -
On a v1.0 surface, a function call that no available catalog implements (an unknown catalog, no default catalog, or an unknown function; never an argument or execution failure) is sent to the agent as
callAgentFunctionthrough the newSurfaceModel.callAgentFunction(AgentFunctionCaller) hook, whichMessageProcessorwires to itsRpcHandler. A dynamic value resolves to null until the response arrives and then updates; achecksrule that is waiting is left out ofisValid,validationErrorsandvalidationResults, and the resolved props gainvalidationPending, true while any rule waits. An action awaits the agent's result. An agent error or timeout (A2uiRpcError) is reported onSurfaceModel.onErrorasEXECUTION_ERRORwith thefunctionCallId, and a non-RPC listener exception in a dynamic value or check asEXPRESSION_ERROR; the value stays null and a waiting rule then fails with its message. v0.9 and v0.9.1 surfaces keep reportingEXPRESSION_ERROR.A2uiCatalogResolutionError, a subclass ofA2uiCatalogError, is whatSurfaceModel.resolveCatalogandCatalog.invokethrow for such a lookup miss. -
DataContextaddsisUserActivated,withUserActivation(),evaluateFunctionCall(what an action runs: locally when possible, otherwise through the agent),isPendingAgentCallandresolveSignalWithPending(returning a signal ofDynamicValueState), and takescallAgentFunction(AgentFunctionCaller).CatalogInvokerExtension.argumentErrorsreturns a function's argument schema failures without throwing. Behavior change:Catalog.invokerefuses a function that isagentOnly, or one withrequiresUserActivationunless the context is user activated. The binder runs actions withwithUserActivation(), soopenUrlworks from an action and is refused from a dynamic value. -
Added
MessageProcessor.forAgent, which an agent checks its own outbound payloads with. It takes the negotiatedCatalogApis, holds each function as a signature that cannot be invoked, and validates underValidationConfig.strictby default. It checks acallRendererFunctioninstead of running it, and throwsA2uiValidationErrorwhere a renderer would answer it with an error. -
Added
MessageProcessor.checkRendererFunctionCall, which checks acallRendererFunctionasforAgentdoes without looking up its surface, for an agent that checks a call on its own, such as one it streams. -
Added
PayloadValidator.validateFunctionCallFields, which rejects a field thatFunctionCalldoes not allow on a call written on its own. -
Exported
checkDuplicateComponentIds, the checkMessageProcessorruns on each batch of components, for an agent that checks one message's components in several batches as they stream. Itsearlierargument takes the ids of the earlier batches. -
A
MessageProcessorwhosevalidationConfigallows dangling references, and orphan components or a missing root, as an agent checking a payload that is still arriving does, checks eachupdateComponentswithout walking the whole surface. The surface's component model keeps a bound on its chains of references, and walks only the components the update reaches when the bound shows the surface has no cycle and no chain past the depth limit; otherwise it walks the whole surface as before, so the same updates fail with the same errors. A processor also skips the composition checks when no catalog its surface draws on declaresallowedParentsorallowedChildren. -
Added
AgentToRendererMessage.typesFor, the message types an agent may send in a protocol version. -
Breaking:
MessageProcessorroutes each message through theVersionAdapterfor the version it declares, so one processor holds v0.9, v0.9.1 and v1.0 surfaces side by side. The requiredprotocolVersionparameter and field are replaced by an optionaldefaultVersion. -
Breaking:
processMessagesand the newprocessMessagesAsynctakeObject?: raw decoded JSON (a lone envelope, a list of envelopes or the{messages: [...]}wrapper) or parsed messages (AgentToRendererMessagePayload, oneAgentToRendererMessage, or a list of them). Every message is parsed before any is applied. -
Behavior change:
createSurfaceraisesA2uiCatalogErrorwhen its catalog declares aprotocolVersionincompatible with the message's version. A catalog that declares none is pre-v1.0: accepted by a v0.9 or v0.9.1 message and rejected by a v1.0 one. -
Behavior change: a v1.0
createSurfacewrites its inlinedataModelas one root write, then applies its inlinecomponents(checked as one batch before the surface is added, so a batch that fails creates nothing). Without acatalogIdit creates a surface with no default catalog; there is no fallback to the processor's catalogs. A v0.9createSurfacewithout acatalogIdis rejected, as the v0.9 schema requires one. -
SurfaceModel.protocolVersionis the version of the message that created the surface, soDataContext.atLeastV10follows each surface's own version. -
New
InternalOperation(CreateSurfaceOp,UpdateComponentsOp,UpdateDataModelOp,DeleteSurfaceOp,CallRendererFunctionOp,AgentFunctionResponseOp),VersionAdapter,V0_9Adapter(v0.9 and v0.9.1),V1_0Adapter, andVersionAdapterRegistry, whichMessageProcessortakes asadapterRegistry. -
Catalogbecomes a lossless model of a catalog document.Catalog.fromJsonkeeps each component's schema as written inComponentApi.schema(withallOfmixins, local#/$defs/...andcommon_types.jsonreferences, descriptions and closure keywords intact;allowedParentsandallowedChildrenmove to their fields) and each function's definition as written in the newFunctionApi.definition(FunctionImplementationtakes and forwards it too), from whichargumentSchema,returnTypeand the other fields are read, and reads the rest of the document into fields:schemaDialect($schema),schemaId,title,description,protocolVersion,instructions,themeSchema, anddefinitions(the shared$defs). Keys it does not model, the form offunctions(map or list) and where the theme lives are kept too. -
Breaking:
ComponentApi.schemaof a component read byCatalog.fromJsonis now the definition as written, with itsallOfmixins, references and envelope properties kept, rather than the flattened schema. ReadCatalog.resolvedComponentSchema(name)orCatalog.resolvedComponentSchemasfor the flattened schema renderers and validators used before. -
Behavior change:
Catalog.componentsandCatalog.functionsare unmodifiable, and so are the component, function and theme schemas of a catalog read byCatalog.fromJson, so the cachedtoJson,validationSchemaandresolvedComponentSchemascannot go stale. UsecopyWithorwithFunctionsfor a changed catalog. -
CatalogaddstoJson, which assembles the catalog document from the model, soCatalog.fromJson(document).toJson()equalsdocumentup to key order (excluding components and functions omitted fromanyComponent.oneOfandanyFunction.oneOf). TheanyComponentandanyFunctionunions are computed from the components and functions; references are left as written. It writes theprotocolVersionas the document declared it, andcatalogIdonly when the document declared one. A catalog built in code is written in the shape of itsprotocolVersion, with each component schema as defined, and so is a function without adefinition. The document is built once per catalog and each call returns a copy. -
CatalogaddsresolvedComponentSchemasandresolvedComponentSchema, each component's schema with its mixins merged, local references inlined and envelope properties left out: what renderers bind and validators check. Each is computed once per component. -
The
Catalogconstructor takesdefinitions,schemaDialectanddeclaresProtocolVersion.copyWithkeeps thedefinitionsexcept one that only removed entries referenced. -
Catalog.fromJsontakes acatalogId, used as the catalog's id in place of the declared one, so a document that declares none, such as the published v0.8 basic catalog, can be loaded. -
CatalogaddswithFunctions, which returns a copy with functions of anotherFunctionApitype, such asFunctionImplementations, and keeps the document fields anddefinitionsthattoJsonandvalidationSchemaread. -
CatalogaddsvalidationSchema, the self-contained schema used to validate messages. Its standard$defsfollow the catalog'sprotocolVersion: the v1.0 common types from1.0, the v0.9 ones below. -
catalogSchemais deprecated; usevalidationSchema. -
Behavior change: the schema
validationSchema(and socatalogSchema) returns now matches the other SDKs:- It carries
$schema,catalogId, theprotocolVersionthe catalog declares as a bare semantic version (not a fallback passed tofromJson),instructions,components,functionsand$defs. The catalog's$id,titleanddescriptionare left totoJson. - Every reference is local: references to
common_types.jsonin function arguments, and the standardFunctionCall's reference tocatalog.json#/$defs/anyFunction, point into its own$defs. A catalog without functions gets ananyFunctionthat matches nothing, and from1.0the union lists only the catalog's functions. A deep pointer into the common types, such asDynamicString/oneOf/0, keeps its full path. - A component property or function argument that references one of the
catalog's own
$defs, such as#/$defs/PositiveInt, keeps the reference, and the definitions it reaches are copied into$defs; a standard definition of the same name takes precedence. Mixins reached throughallOfare still flattened into the component. - A reference to a standard definition, including each component's
idand a reference that was already local, such as#/$defs/DynamicStringin function arguments, takes that definition's description when it has none of its own. FlattenedComponentCommonandCheckableenvelopes use the common types descriptions, and from1.0aComponentCommonmixin also contributes the standardmetadataproperty. - Components carry
idin every version, and non-emptyallowedParentsandallowedChildren. - Below
1.0, components and function entries are closed withunevaluatedProperties(the authored value, elsefalse). From1.0, function entries take the published v1 shape (a top-levelreturnType, andallowedCallersandrequiresUserActivationwhen they differ from the defaults or the document declares them), and neither function entries nor components are closed unless authored, because the protocol's envelopes close them. Objectargsare closed in every version. - A theme that sets neither
additionalPropertiesnorunevaluatedPropertiesis open (additionalProperties: true).
- It carries
-
BasicCatalog.v0_9()reports protocol versionv0.9. -
CatalogaddstoLegacyInlineCatalog, the inline catalog shape that renderer capabilities send below v1.0, derived fromvalidationSchemaas described below. Function parameters and the theme are written as defined, without the closing keywordsvalidationSchemaadds. -
BasicFunctiontakesdescription,allowedCallersandrequiresUserActivation, and the basic catalog's functions carry their publisheddescription. -
Behavior change: from v1.0, inline catalogs in renderer capabilities are the catalog documents
Catalog.toJsonreturns, rather than a copy of the bundled validation schema. Below v1.0 they aretoLegacyInlineCatalog. -
SurfaceModeladdsmetadata, from v1.0createSurface. -
Breaking:
SurfaceModel.catalogis replaced by a nullabledefaultCatalog, and the constructor'scatalog:argument bydefaultCatalog:.SurfaceModeladdsavailableCatalogs,metadata,onWarning/dispatchWarning(with the newA2uiWarning), andresolveCatalog(catalogId, {subject}), which resolves an item's owncatalogId, then the default, and otherwise throwsA2uiCatalogError:Catalog not found: <id>. ...for a catalog the surface doesn't have, or... has no default catalogId.when the item names none.subjectnames the item in the message. There is no fallback to a sole catalog. A catalog whoseprotocolVersionis incompatible with the surface's throwsA2uiCatalogErrorat construction. A catalog without aprotocolVersionis pre-v1.0: a v0.9 or v0.9.1 surface accepts it and a v1.0 or later surface rejects it. -
Behavior change:
NodeResolver,GenericBinderandDataContextresolve components and function calls throughsurface.resolveCatalog, so a component or function call naming another catalog'scatalogIdrenders or runs with that catalog. A call'scatalogIdcounts only from v1.0; before v1.0 every call runs in the default catalog.FunctionCalladdscatalogId, andDataContextaddsinvokerForCatalog. -
Behavior change:
MessageProcessorgives each surface the processor catalogs compatible with its protocol version asavailableCatalogs, andcreateSurfacewithout acatalogIdcreates a surface with no default catalog instead of throwing. A component that names no catalog on such a surface throwsA2uiCatalogError, even when the processor supports one catalog.createSurfacemetadata is kept onSurfaceModel.metadata. -
Behavior change:
SurfaceGroupModel.addSurfacethrowsA2uiStateErrorfor a surface id it already holds, instead of ignoring the new surface. -
Behavior change:
CatalogthrowsA2uiCatalogErrorfor two components or two functions with one name, for a component namedSurface, for a function name starting with@, and for a function declaringreturnType: 'validationResult'when the catalog's effectiveprotocolVersionis below1.0(an omittedprotocolVersiondefaults to'0.9'). -
Behavior change:
Catalog.invokechecks arguments against the function's argument schema and throwsA2uiExpressionErroron a mismatch before the function runs. Parameters that referencecommon_types.jsonor a definition the catalog bundles are checked against the referenced definition. Null arguments, such as bindings to missing data, are not checked. -
SurfaceModel.dispatchActioncopies the action'scatalogIdontoA2uiRendererAction.catalogId. -
Catalog.resolvedComponentSchemasexpands the standardComponentCommonandCheckablemixins of a component'sallOfenvelopes into the properties they contribute, andCommonSchemascarriescommonTypesRefmetadata in place ofREF:description prefixes. -
Adds
FunctionApi.descriptionandFunctionImplementation.description, and updatesCatalog.catalogSchemato rebuild component envelopes, emitanyComponent.discriminatorand functiondescription, and restorecommon_types.json#/$defs/...references. -
Resolves local
#/...pointers that are absent from the catalog document againstcommonTypesinresolveSchemaRefs. -
Support non-ASCII data model keys in templates.
-
A2uiVersionCapabilities.fromJsonthrowsA2uiCatalogErrorwheninlineCatalogsis present but isn't an array, or contains an entry that isn't an object.A2uiRendererCapabilities.fromJsonreads an inline catalog that states noprotocolVersionas targeting the version of the entry it is declared in;A2uiVersionCapabilities.fromJsontakes that version asprotocolVersion. -
Breaking (v1.0): An empty
catalogId("") names a catalog like any other, so it never falls back to the default:MessageProcessorrejects it withA2uiCatalogError(Catalog not found). -
Breaking (v1.0): Every component in
updateComponentsmust name itscomponenttype, as the specification requires;MessageProcessorno longer lets an update omit it and keep the previous type. An update that names nocatalogIdresolves to the surface's default catalog, like any other component, instead of keeping the catalog of the component it replaces. An update that changes a component's catalog, even with the same type, replaces itsComponentModelrather than updating the existing one in place. -
PayloadValidator(v1.0): a nested function call is fully checked against the validator's catalog when it runs there: when it names that catalog, or names nocatalogIdwhile the component is in the surface default catalog, including calls nested in the arguments of a call that runs elsewhere. Called directly, the validator takes a component that names nocatalogIdto be in the surface default. These calls are checked before the component's own schema, so the error names the function and argument. Any other call runs in a catalog the validator can't see, so it is checked only for its names: function and argument names must be UAX #31 identifiers (so an empty function name is rejected rather than skipped), and the only@-prefixed name allowed is@index. An emptycatalogIdnames a catalog too, and a non-stringcatalogIdis rejected.validateFunctionjudges the calls in its arguments as in a component that names nocatalogId. The calls are checked even in a component whose type the catalog doesn't declare, whenallowUnknownElementslets that component through. A call that omitsargsis read as passing{}, so it is accepted when the function requires no argument.MessageProcessordecides whether a component is in the surface default from the catalog it resolves to, so a component that explicitly names the default catalog has its catalogless calls checked like one that names none. It resolves every nested call's catalog and checks the calls the component's validator leaves unjudged against the catalog they resolve to, and rejects a component whosecatalogIdis not a string withA2uiValidationErrorinstead of resolving it to the default. -
PayloadValidatornormalizes untyped map and list literals (such as{'args': {}}) before schema validation, so they fail validation withA2uiValidationErrorinstead of throwing aTypeError. -
A function call whose catalog can't be resolved (it names a catalog the surface doesn't have, or names none on a surface without a default) is reported on the surface error channel with code
CATALOG_ERRORinstead ofEXPRESSION_ERROR, byComponentContextandNodeResolveralike; aDataContexterror reporter receives anA2uiExpressionErrorwhosecodeisCATALOG_ERROR. Every other evaluation failure, including a function missing from the catalog the call resolved to and an unknown system function, keepsEXPRESSION_ERROR. -
The reserved
@indexsystem function (v1.0) belongs to no catalog:MessageProcessorvalidates it andDataContextevaluates it without resolving a catalog, and it takes only anoffset.@-prefixed names other than@indexare rejected by validation, and evaluating one fails withA2uiExpressionError. A system function call that names acatalogId, whatever its value, is rejected by validation, and evaluating it fails with codeEXPRESSION_ERRORrather than with anA2uiValidationErrorfrom parsing the call. -
UpdateDataModelMessageaddshasValue(defaulting totrue) sotoJson()emits'value': nullfor explicit null deletions whilefromJson()distinguishes an omittedvaluefrom an explicitnull. -
Breaking:
SurfaceModel.dispatchActionrecords action timestamps in UTC (DateTime.now().toUtc()) andA2uiRendererAction.toJson()serializes timestamps in UTC (timestamp.toUtc().toIso8601String()) so serialized timestamps always end withZper RFC 3339. -
Breaking:
A2uiRendererErrorvalidates in its constructor (not only in debug assertions) that aVALIDATION_FAILEDerror provides a non-emptypath, throwingA2uiValidationError. -
ComponentModel.toJsonwritesidandcomponentafter the component's properties, so a property namedidorcomponentno longer replaces the model's own. -
Breaking: Removed
DataPath.DataModelparses JSON Pointers itself, as web_core and the Python core do, and every path API (get,set,delete,hasPath,watch) takes aString. Parsing validates RFC 6901~0/~1escape sequences and rejects prototype-pollution segment names (__proto__,constructor,prototype) withA2uiDataError. -
Breaking:
DataModeltakes a modifiable deep copy of incoming data on initialization andset, normalizing string-keyed maps (including untypedMap<dynamic, dynamic>) toMap<String, Object?>and lists toList<Object?>so external mutations do not alias internal state and untyped maps are traversable. -
Add
DataModel.delete,DataModel.hasPath, andDataModel.resolvePath. -
EventNotifier.emitisolates listener exceptions, logging them viaLogger('a2ui.EventNotifier')and continuing delivery to remaining listeners. -
Validate
DataBinding,FunctionCall,Action, andChildListTemplatefields during JSON deserialization (A2uiValidationError), preservereservedKeys(@path/@call) acrosstoJson, andcatalogIdin the@callform (which omitsreturnType, as the v1.0 schema declares none; the v0.9callform has nocatalogId), defaultFunctionCall.returnTypetoA2uiReturnType.any, treat a non-listchecksvalue as no rules (as web_core and the Python core do) and guard dynamic map casts againstTypeError, and throwA2uiStateErrorfromComponentContext.childContextandA2uiExpressionErrorfromCatalogInvokerExtension.invokewhen the catalog has no such function. -
Add
isValidUax31IdentifierandassertUax31Identifierfor UAX #31 identifier validation,A2uiErrorDetail,causechaining onA2uiErrorsubclasses, andcode/path/errorsonA2uiValidationError.A2uiErrornow takescodeas a named parameter, andA2uiValidationErroraligns its default code to'VALIDATION_FAILED'. -
Add
Catalog.refMap, a cachedComponentRefMapof each component type's child-reference properties.MessageProcessorgraph validation andNodeResolverboth read it, so a property the validator checks is one the resolver mounts.ComponentRefMap,RefFieldsand theRefKindtypes (SingleRef,ListRef,NestedRef) are now exported. -
Recognize v1.0
common_types.json#/$defs/Child(and#/$defs/Child) as a single child reference, for dangling-reference and orphan checks and for resolution. -
Add
Catalog.commonTypesSchema, the embeddedcommon_types.jsondocument selected by the catalog'sprotocolVersion(v1.0 for 1.0 and later, v0.9 otherwise, including when undeclared), decoded once per catalog.Catalog.refMapandGenericBinderresolvecommon_types.json#/$defs/...pointers against it, andComponentRefMaptakes the same optionalcommonTypesdocument, so a v1.0 catalog's shared types (such as the v1.0CheckRule) read the v1.0 definitions rather than the v0.9 default. -
Behavior change:
NodeResolvernow mounts an unmarked stringchildand string-arraychildren, which graph validation already checked. Previously such a catalog validated but rendered its children as plain ids. -
Behavior change: a dangling id inside a child list is reported with its index (
children[2]rather thanchildren), and only an object with both a stringcomponentIdand a stringpathis read as aChildListtemplate. -
Breaking:
MessageProcessor.validationConfigis nullable and defaults tonull. Without a config the processor still rejects duplicate ids within anupdateComponentsbatch and checks declared component types and themes against their catalog schemas, accepts undeclared types, and skips the root, dangling-reference, reachability, cycle, depth and data-model path checks, so a surface may arrive across several messages in any order.ValidationConfig.strictis the opt-in to those checks. -
Behavior change: under a
ValidationConfig,MessageProcessorchecks the component graph on everyupdateComponentsmessage rather than once per payload. Each batch is applied to a copy of the surface's components first, and the result must pass the root, dangling-reference, cycle, depth and reachability checks the config's flags require before anything is committed. A surface streamed across several messages under a config needsValidationConfig.relaxedor the individualallow*flags. -
ValidationConfigaddsallowUnknownElements,targetVersion,allowedMessages,rootIdandmaxDepth.ValidationConfig.relaxednow also setsallowUnknownElements. -
Before v1.0, an
updateComponentsentry that omitscomponentis checked against the existing component's type and catalog schema, and keeps itscatalogIdandmetadatawhen it omits those too; its properties still replace the existing ones. -
ComponentModeladdscatalog(the component'scatalogId) andmetadata, andpropertiesno longer holdscatalogIdormetadata. A component whose type changes, or whosecatalogIdresolves to a different catalog, is recreated (onDeleted, thenonCreated). -
SurfaceModeladdsrootId, defaulting torootor toValidationConfig.rootId, andNodeResolverroots the tree at it. -
SurfaceComponentsModeladdsgetAll(),has(),size,entries,keys,values,getChildIds(),validateTopology(),detectCycles(),validateReferences()andvalidateComponentsUpdate(). -
Added
ValidationResultandA2uiReturnType.validationResultfor structured client-side validation outcomes (valid,message,code,severity), and exposedvalidationResultsalongsideisValidandvalidationErrorson resolved component properties.A2uiReturnType.validationResultis an API-level value; the v0.9CommonSchemas.functionCallwire schema still accepts only the seven v0.9 return types.ValidationResult.validityOfexposes the rule the binder uses to read a check result's validity. -
Fixed
checksevaluation inGenericBinder:- Rules evaluate once during initial binding without a duplicate object-branch pass.
- Non-map rule entries emit a
VALIDATION_FAILEDclient error on the surface instead of throwing aTypeError. - Checkable properties are classified from schema markers or
CheckRuleitem structure rather than matching the property name'checks'.
-
ReferenceSchemaReaderresolves externalcommon_types.json#/$defs/...pointers against thecommon_types.jsondocument the caller supplies (the embedded v0.9 document by default) so catalogs loaded viaCatalog.fromJsonclassifyCheckable,DynamicValue,Action, andChildListproperties identically to code-constructed catalogs.extractRefFieldsforwards the same optionalcommonTypesdocument. -
Breaking: Message constructors no longer default
versionto'v0.9'; everyAgentToRendererMessageandRendererToAgentMessagesubclass takes a requiredversion.A2uiRendererAction.fromJsonandA2uiRendererError.fromJsontake a requiredprotocolVersion. -
A2uiProtocolVersionaddsv0_9_1andv1_0.'v0.9.1'now parses tov0_9_1instead ofv0_9. The enum addsparse,major,minor,compareToandisAtLeast. Payload parsers andPayloadValidatoraccept v0.9.1 envelopes where v0.9 is configured, and the reverse.A2uiRendererCapabilities.forVersionfalls back to a compatible declared version in the same way. -
Added
isCatalogVersionCompatibleandcompareVersions, matching the TypeScript and Python SDKs.isCatalogVersionCompatibleaccepts a null catalog version, which is compatible with versions below 1.0 only. -
Added the v1.0 messages
CallRendererFunctionMessage,AgentFunctionResponseMessage,CallAgentFunctionMessageandRendererFunctionResponseMessage, withA2uiFunctionResponseandA2uiFunctionResponseErrorfor function results. They are rejected in v0.9 and v0.9.1 envelopes. -
CreateSurfaceMessage.catalogIdis optional, as v1.0 allows. The class adds the v1.0components,dataModelandmetadatafields. v1.0 rejectstheme, and v0.9 rejects the v1.0 fields. -
A2uiRendererActionaddscatalogIdandmetadata. -
A2uiRendererErrorfollows the v1.0 rules.UNALLOWED_PARENTandUNALLOWED_CHILDare path errors likeVALIDATION_FAILED, and path errors reject extra fields. A generic error names exactly one ofsurfaceIdand the newfunctionCallId, and keeps its other fields inadditionalProperties.surfaceIdis now nullable. -
Envelope parsing checks each version's allowed and required keys. It rejects unknown envelope and body keys, an empty
componentslist, and a v1.0updateDataModelwithoutvalue. -
Harden
ExpressionParserto clamp scanner bounds at EOF, reject unclosed string literals and trailing backslashes withA2uiExpressionError, accept@-prefixed function names (such as${@index()}and${@index(offset: 1)}), and accept~0and~1JSON Pointer escapes inside${}paths while rejecting malformed~escapes and non-leading@tokens. -
Added
BasicCatalog.v0_9()andBasicCatalog.v1_0(), which carry the basic catalog's 14 functions (required,regex,length,numeric,email,formatString,formatNumber,formatCurrency,formatDate,pluralize,openUrl,and,or,not), and its 18 components, theme and shared definitions. They are defined in code, andtoJsonwrites the published document.- v0.9 validation rules return
bool; v1.0 rules return aValidationResultwith a failure message. - In v1.0,
and,or, andnotread the validity of aValidationResult(or a map with avalidkey) instead of treating every object as truthy, so the v1.0 spec's nestedand(required, or(required, required))check blocks a submit when a field is empty. v0.9 keeps plain truthiness, since its validators return booleans. - Formatting uses
package:intlfor thelocaleargument (defaulten-US).formatDatereads a timestamp without an offset as UTC, keeps the wall-clock time of one with an offset, and emits the UTC instant for theISOpattern. It returns an empty string for a date that does not exist, such as2026-02-30, instead of rolling it into the next month. openUrlaccepts only absolutehttp,https,mailtoandtelURLs and passes them to anOpenUrlCallback. Without a callback it throws, which a binder reports asEXECUTION_ERROR.- The embedded v1.0 document matches
catalogs/basic/v1/catalog.json, whose instruction examples write bindings and calls as@pathand@calland use fullCheckRuleobjects.
- v0.9 validation rules return
-
FormatStringFunctionnow delegates to the basic catalog'sformatString: it coerces a non-stringvalueinstead of throwing, renders integral doubles without.0, and resolves template bindings and calls on a v1.0 surface. -
Add
DataContext.isDataBinding,DataContext.isFunctionCall,DataContext.bindingFor, andDataContext.adaptExpressionPartfor protocol-version-aware binding and function-call detection; adaptFormatStringFunctionparser AST nodes (@path/@call) in v1.0 mode, pre-build function argument signals outsidecomputedinDataContext.resolveSignal, skip binding/call validation insideupdateDataModel.valueincheckPathsAndRecursion, and report unrecognized or invalid action payloads onSurfaceModel.onErrorwith codeINVALID_ACTION. -
Add
DataContext.resolveActionmethod for resolving dynamic values inside action payloads. -
FormatStringFunctioncoerces null expression arguments to empty strings and encodes maps and lists as JSON. -
Deprecated:
SchemaCatalogis renamedCatalogApi, matchingComponentApiandFunctionApi.SchemaCatalogstays as a deprecated alias and will be removed in a later release. -
Support reserved protocol key prefix (
@path,@call) inDataBindingandFunctionCall, dynamic prefix doubling unescaping (@@path→@path) during dynamic evaluation, and@pathin dynamic setter generation. -
Lower SDK floor constraint to
">=3.5.0 <4.0.0"(replacing post-3.5 null-aware collection element syntax with collection-if) to support Flutter 3.24+ and Dart 3.5+ environments. -
Execute
functionCallandcallcomponent actions locally inGenericBinder, against the component's data context. A function that throws, fails asynchronously or is missing from the catalog is reported throughSurfaceModel.onErrorwith codeEXECUTION_ERRORrather than escaping the action callback. -
Behavior change:
SurfaceModel.dispatchActiononly emits agent-boundeventandnameactions. A direct caller that passes afunctionCallpayload previously had the function run against the root data context; the call is now ignored. Run local functions through the binder orDataContext.resolveDynamicValueinstead. -
Action
contextvalues are resolved one entry at a time, so a context key namedpathorcallreaches the agent as a literal key instead of being read as a data binding or function call. -
Added optional
userMessagefield toA2uiRendererAction. -
ExpressionParseraccepts number literals with a leading decimal point (.5,-.5,+.5,.5e2), including as function-call arguments. A.inside a path such asa.5is still part of the path, and.foois still a path. This matches the TypeScript, Python and Swift parsers. -
ExpressionParserrejects a number literal outside the double range, such as1e999, withA2uiExpressionError. It used to returndouble.infinity, whichjsonEncodecan't encode. -
ExpressionParserparses thenullkeyword as an empty string, as the TypeScript and Python parsers do. A template still drops it, so the change shows in function arguments:${f(x: null)}now passes''instead of null. -
MessageProcessor,PayloadValidator, andCatalogalign surface lifecycle error reporting (A2uiIntegrityErrorandA2uiRecursionErrorextendingA2uiValidationError, per-message completeness validation, safe no-opdeleteSurfaceon unknown surfaces) and support"v0.9.1"inA2uiProtocolVersion.tryParse. -
ExpressionParserenforces recursion depth (maxDepth = 100), template length (maxTemplateLength = 10000), and template parts (maxTemplateParts = 1000) limits across nested interpolations and function arguments. -
DataModelandDataContextenforce JSON Pointer validation (A2uiDataErroron non-pointer paths, forbidden prototype-pollution segments, primitive traversal/root mutation, and array index bounds) and supportDataContext.index. -
Added:
DataContextaccepts an optionalExpressionErrorReporterthroughonError. With a reporter, a missing or failing catalog function resolves to null and the reporter receives the error; without one, the error propagates. -
Added:
NodeResolver(surface)builds a reactive tree of read-onlyComponentNodes with resolved child references, scoped templates, dynamic bindings, callable actions, and placeholder states for unresolved nodes. It owns node subscriptions and cleanup; consumers dispose the resolver before its surface. Node props and container-valued bindings are detached, recursively unmodifiable snapshots.ComponentNode.propscarries dynamic properties asResolvedBindingvalues, with no synthesizedset<Property>setter entries. A property bound to a data path is aWritableBinding, even when the path holds no data; writes go throughWritableBinding.set, andWritableBinding.pathis the path as authored. -
Node bindings report a missing or failing catalog function as an
EXPRESSION_ERRORclient error on the surface, and a call whose catalog can't be resolved asCATALOG_ERROR, and resolve to null. -
Validation and node resolution recognize wire/local
$refpointers andREF:description markers. Resolution additionally recognizes unmarked structuralChildListschemas, which validation deliberately ignores so a batch is never rejected on that guess. Resolution mounts top-level child references and lists, including single-reference fields within arrays of objects. -
A
ChildListexpands to at mostmaxDynamicChildListSize(10,000) items, matching the TypeScript core'sMAX_DYNAMIC_CHILD_LIST_SIZE. -
Changed:
ChildNodedescriptors compare by component id and data scope and serialize as plain JSON in node props. NestedChildListvalues remain scoped descriptors rather than mounted nodes. -
Fixed:
DataContext.resolveSignalresolves array and map payloads per entry and tracks nested bindings reactively; previously a container holding bindings (such as a function argument list or a nested{path}value) was passed through as a static literal. -
pub.dev now recognizes the license. The package
LICENSElinkedhttps://where the Apache text hashttp://, which pana does not match, and carried the root's notice foreval/bin/transcrypt, a file outside this package. Also a longerdescriptionand an example.
0.2.2 #
ExpressionParseraccepts signed number literals (-42,+1,-3.5) and exponent notation (1e5,1E5,1.5e-3,2.5E+4), including as function-call arguments. Previously-42parsed as the path-42and1e5failed withUnexpected characters at end of expression. A-inside a path such asa-1is still part of the path. This matches the TypeScript and Python parsers.- Fixed
DataModel.setwith anullvalue (a delete) at a list index at or past the end of the list padding the list withnullup to that index. It now leaves the list unchanged; only a write extends a list. - Remove
A2uiCompileErrorfroma2ui_core(compilation is an agent SDK responsibility). - Validate that catalog function definitions have a non-empty
namestring inCatalog.fromJson, throwingA2uiCatalogErrorif missing or empty. - Validate that message object fields and
thememaps have string keys inAgentToRendererMessage.fromJson, throwingA2uiValidationErrorwhen encountering non-string keys. - Enhanced child reference detection in
ComponentRefsto recognize string-typedchildproperties and string listchildrenproperties as component references. - Expanded conformance test coverage for validator, expressions, and data model suites across protocol versions v0.8, v0.9, and v1.0.
0.2.1 #
- Widen
preact_signalsdependency constraint to">=1.9.4 <8.0.0"to supportpreact_signals: ^7.0.0and downstream modern signal-based ecosystems.
0.2.0 #
- Breaking:
MessageProcessor.processMessagestakes anAgentToRendererMessagePayloadrather than aList<AgentToRendererMessage>, andAgentToRendererMessage.parseAllreturns one. The processor is where untrusted wire data enters the SDK, so the accepted set is every shape an agent or a transport realistically sends — a batch of parsed messages, a lone message throughAgentToRendererMessagePayload.of, or raw decoded JSON throughAgentToRendererMessagePayload.fromJson, which takes a lone envelope, a list of envelopes or the{messages: [...]}wrapper. Naming that set lets a signature reference it rather than restate it, and keeps trivial normalization out of every transport. A payload holds its messages unmodifiably, so the list a caller passed cannot change under a processor part-way through applying it. - Added
RendererToAgentMessage, withActionMessageandErrorMessage, and the symmetricRendererToAgentMessagePayload. The renderer-to-agent direction had bodies but no envelope:A2uiClientActionandA2uiClientErrormatchedclient_to_server.json'sactionanderrorobjects, leaving every transport to build the{version, action}envelope and the batch around it. Each message wraps the body a surface's event source already emits rather than a second representation of it, andA2uiClientAction.fromJsonandA2uiClientError.fromJsonparse the bodies an agent receives. A malformedtimestampis reported asA2uiValidationErrorrather than escaping as the platform'sFormatException. A2uiClientErrorcarriespath, the JSON pointer theVALIDATION_FAILEDvariant ofclient_to_server.jsonrequires. No other field names the field that failed, so without it a validation failure lost its location on the way throughtoJsonandA2uiClientError.fromJson. The variant requires it, sofromJsonrejects aVALIDATION_FAILEDbody that names nopath, and the constructor asserts the same.- The
{messages: [...]}wrapper is handled by each payload'sfromJsonandtoJsonrather than by a wrapper class per direction: it carries nothing but the list, so a type holding one field would be a second name for it.toJsonListemits the bare list the*_list.jsonschemas describe. - Breaking:
MessageProcessor.processMessagesvalidates messages as it processes them, and is the single entry point for validation as well as for processing. A message that does not match its catalog now throws instead of being applied. Added the requiredprotocolVersionconstructor parameter andcommonTypesSchema, which configure the validators it builds. It keeps one validator per catalog, reachable throughvalidatorFor, resolves the catalog for each item throughcatalogFor, and checks each component against the catalog it resolves to rather than against every catalog the processor supports. - Breaking:
MessageProcessor.processMessageschecks every surface the payload creates as one graph once the payload has been applied: arootcomponent exists, every reference resolves, and every component is reachable from the root. These three cannot be checked as each message arrives, because a payload may declare a parent before its child, so they answer for the surface the payload leaves behind. A surface the payload only updates is an incremental update to a render it does not own, and is not checked that way. - Breaking: Added
ValidationConfig, withallowOrphanComponents,allowDanglingReferencesandallowMissingRoot, and thestrictandrelaxedpresets.MessageProcessortakes one, defaulting tostrict. A caller whose transport delivers one surface across several payloads relaxes the checks that span them; a caller that receives a whole render in one payload leaves them on. Everything else stays unconditional: the catalog schema, duplicate ids, self-references, cycles, depth and data-model paths are not waiting on a later message. - Breaking:
A2uiMessageis renamedAgentToRendererMessage, the name thea2ui_coreblueprint gives the type a payload parses into andMessageProcessor.processMessagesaccepts. It says which direction the message travels, which the old name left open, and leaves the other direction its own name:RendererToAgentMessage. - Breaking: Envelope parsing moved to
AgentToRendererMessage.parseAll, fromPayloadValidator.parseMessages. Parsing needs no catalog, so it belongs to the message model rather than to a validator. - An invalid number literal in an expression, such as
${1.2.3}, now throwsA2uiExpressionErrorinstead of aFormatExceptionfromnum.parse— an error outside theA2uiErrorhierarchy thatavoid_catching_errorsdiscourages catching. The accepted shape is stated in the parser rather than inherited from the platform's number parser, so every implementation accepts the same literals. - The expression parser now runs the shared conformance suite at
conformance/core/expressions.yaml, alongside the TypeScript client. - The expression parser's nesting limit is now enforced. The depth guard sat in
parse(), which is only entered at depth 0, so neither nested interpolations nor function-call arguments were ever counted: a deeply nested template recursed until the stack overflowed, raisingStackOverflowErrorrather than the intendedA2uiExpressionError. The limit is also raised from 10 to 100, matching web_core. - Breaking:
MessageProcessorchecks each batch of components as a graph against the surface it joins, so duplicate ids, cycles and over-deep chains now throw. Whether a reference resolves is not checked there: a payload may declare a parent before its child, as the basic catalog's00_incrementalexample does, so references are resolved once the payload that created the surface has been applied in full. - Breaking:
Catalognow takes two type parameters,Catalog<C extends ComponentApi, F extends FunctionApi>. - Breaking:
ComponentApiandFunctionApiare concrete classes with generative constructors, andFunctionImplementationforwards toFunctionApi's. Subclasses of all three passname,schemaorargumentSchema, andreturnTypetosuperrather than overriding getters. - Behaviour change:
AgentToRendererMessage.fromJsonthrowsA2uiValidationErrorrather thanTypeErrorfor a malformed message body. - Behaviour change:
DataModelobservers no longer fire when a write leaves their own value unchanged. - Added
A2uiProtocolVersion. Every entry point accepts protocol v0.9 only. - Added
Catalog.fromJson,Catalog.catalogSchemaandCatalog.copyWith, plus theSchemaCatalogalias forCatalog<ComponentApi, FunctionApi>. Catalogcarries the document's$id,titleanddescriptionasschemaId,titleanddescription, andcatalogSchemaemits them along with$schema, so a catalog document round trips with its identity intact.- The shared
conformance/core/catalog.yamlsuite gains acatalog_schemaaction, exercised bytest/conformance/catalog_schema_conformance_test.dart. - Added
A2uiRendererCapabilitiesandA2uiVersionCapabilities. - Added
PayloadValidator, which checks one component, one function call or one theme against one catalog, throughvalidateComponent,validateFunctionandvalidateTheme. It is scoped to a singlecatalog, since a component belongs to exactly one, and it takes a requiredprotocolVersion. - Deciding which catalog an item belongs to is
MessageProcessor's job, not the validator's. From v1.0 one surface may mix catalogs — a component or function call may carry acatalogIdoverriding the surface-level default — so the catalog is resolved per item, in the order: the item's owncatalogId, the surface's default, then the sole supported catalog.A2uiCatalogErroris thrown when none of those settles it, or when the resolved id is not one the processor supports. - Added
PayloadValidator.parseMessages, a static that checks envelopes without a catalog, so a payload can be parsed before each message is matched to a surface. - The package now publishes the specification's
common_types.jsonasPayloadValidator.commonTypesFor, andcommonTypesSchemadefaults to it, so the shared types are checked without the caller supplying the document. - Added the
A2uiParseError,A2uiCompileError,A2uiCatalogError,A2uiIntegrityErrorandA2uiRecursionErrorcategories. - Fixed
DataModel.setsilently dropping a write whose parent path resolves to a primitive; it now throwsA2uiDataError. - Behaviour change:
MessageProcessorthrowsA2uiCatalogErrorrather thanA2uiStateErrorfor acreateSurfacenaming a catalog it does not support, which is what the blueprint's validation matrix calls for. MessageProcessorandDataModelare exercised by the sharedconformance/core/validator_v0_8.yaml,validator_v0_9.yaml,validator_v1_0.yamlandconformance/core/data_model.yamlsuites.
0.1.1 #
- The source code is moved from genui repo to a2ui repo.
0.1.0 #
- Initial version.