a2ui_core 0.2.2
a2ui_core: ^0.2.2 copied to clipboard
Core package for A2UI protocol.
a2ui_core Changelog #
Unreleased #
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.