feat(swift): add component catalog protocols and resolved model types#2005
feat(swift): add component catalog protocols and resolved model types#2005pinieb wants to merge 20 commits into
Conversation
…ma dependency Replaces the custom JSONSchema target with a multi-target Swift package structure that uses the swift-json-schema fork (v0.13.1) as an external dependency. This is the foundation for porting the A2UI v0.9.1 protocol implementation from prototype to production quality. Changes: - Remove custom JSONSchema target (JSONValue.swift + tests) - Add swift-json-schema dependency (from: "0.13.1") to Package.swift - Bump swift-tools-version to 6.1 and add macOS 13 to platforms - Define 4 production targets: A2UIJSON, A2UICore, A2UISwiftUI, A2UISampleClient - Define 3 test targets with placeholder tests - Create stub source files for each target - Update AGENTS.md to document new target architecture - Update .gitignore for Swift Package Manager artifacts Verification: - `swift package resolve` resolves swift-json-schema at 0.13.1 - `swift build` compiles all 7 targets - `swift test --enable-swift-testing` passes (3 placeholder tests)
…chema Implements all 14 A2UI v0.9.1 common type JSON Schema definitions using the swift-json-schema fork. Schemas are defined as a raw JSON document matching the specification's common_types.json exactly, and registered into Context via the remoteSchema parameter for $ref resolution. Changes: - Define complete common types document in A2UICommonSchema (all 14 defs: ComponentId, AccessibilityAttributes, ComponentCommon, ChildList, DataBinding, DynamicValue, DynamicString, DynamicNumber, DynamicBoolean, DynamicStringList, FunctionCall, CheckRule, Checkable, Action) - Add A2UISchemaRegistry helper to create a Context pre-populated with A2UI schemas - Add 31 tests covering URI helpers, document structure, schema registry, validation of all schema types (positive and negative cases), and cross-reference resolution (including recursive Action → FunctionCall → DynamicValue chains) - Remove placeholder A2UIJSONTests (superseded by comprehensive tests) Design notes: - Raw JSON string approach used instead of JSONValue dictionary literals to avoid Swift type-checker issues with deeply nested expressions - FunctionCall's catalog.json oneOf reference omitted; catalog-level validation handled at runtime by ComponentCatalog - Context.remoteSchemaStorage is internal in the fork, so schemas are registered via the Context(remoteSchema:) initializer Verification: - swift build passes (all targets) - swift test passes (34 tests in 3 suites, 0.017s)
… message models Ports the foundational A2UICore types from the prototype: error types, JSONValue path-based subscripting, and all server/client message models. Changes: - Add 4 error types: ClientServerError, GenericError, ValidationFailedError, LocalFunctionError (now Sendable) - Add JSONValue+Path extensions with type-safe accessors and JSON Pointer get/set subscripting, adapted for the fork's OrderedDictionary-based JSONValue (including .integer case handling) - Add Resolved protocol and ResolvedAction model with identity-based equality - Add 6 message types: EnvelopeMessage, CreateSurfaceMessage, DeleteSurfaceMessage, UpdateComponentsMessage, UpdateDataModelMessage, ClientToServerMessage (with v0.9/v0.9.1 version validation) - Add OrderedJSON and JSONSchema product dependencies to A2UICore target - Add 50 tests covering type accessors, path operations, message decoding/encoding round-trips, and error cases - Remove placeholder A2UICore.swift stub and placeholder test Verification: - swift build passes (all targets) - swift test passes (84 tests in 5 suites)
Ports the component catalog system and resolved model types that SurfaceViewModel will consume in a future PR. Changes: - Add catalog protocols: LocalFunction, ComponentCatalog (schema lookup, theme parsing, function registration), ActionHandling - Add resolved models: Node (immutable thread-safe component node with children accessor), DataBinding (generic two-way binding with path/literal identity), ComponentProperties (validated unresolved properties), SurfaceTheme (marker protocol) - Add Resolved conformances for primitives (String, Double, Int, Bool, JSONValue) and Array where Element == Node - Adapt ComponentCatalog and ComponentProperties to use fork's Schema type instead of prototype's JSONSchema - Add 33 tests with concrete test implementations (TestCatalog, ConcatFunction, IsEmptyFunction, TestTheme) covering schema lookup, theme parsing, function evaluation, node equality, data binding get/set, and component properties Verification: - swift build passes (all targets) - swift test passes (117 tests in 10 suites)
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Signed-off-by: Pete Biencourt <piebie@google.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Signed-off-by: Pete Biencourt <piebie@google.com>
There was a problem hiding this comment.
Code Review
This pull request introduces core protocols, models, messages, errors, and schema definitions for the A2UI state machine and runtime engine, along with comprehensive unit tests. The review feedback highlights three critical issues in JSONValue+Path.swift: an order-of-operations bug in JSON Pointer unescaping (e.g., ~01 incorrectly unescaping to ~/), destructive behavior when updating an array node with a non-integer key (which replaces the array with an object), and a subscript setter bug that silently ignores non-object values when replacing the root.
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Signed-off-by: Pete Biencourt <piebie@google.com>
jacobsimionato
left a comment
There was a problem hiding this comment.
I think I like this, but let me take another look tomorrow!
There was a problem hiding this comment.
@andrewkolos is centralizing the design on this in https://docs.google.com/document/d/1aA_2ysLn_6NpRet2CtqII90SfPc1wCXZNVnPEmEJZDE/edit?resourcekey=0-sIEWbOROTyd9XRDWwS3tZQ&tab=t.0#heading=h.8ng5v0gkam8a
It'd be great to iterate towards consistency here. I think the biggest difference between this and Andrew's design is that the design has the properties as an observable.
| /// `DataBinding` connects a component property to a value in the data | ||
| /// model via a JSON Pointer path, or wraps a literal value. It provides | ||
| /// get/set closures for reading and writing the bound value. | ||
| public struct DataBinding<Value: Sendable>: Sendable { |
There was a problem hiding this comment.
@andrewkolos do we have anything like this currently?
I think I might prefer it to what we have in the web_core generic binder, but the inconsistency also bothers me.
Description
Introduce the component catalog system and resolved model types that
SurfaceViewModel will consume in a future PR.
Changes:
theme parsing, function registration), ActionHandling
children accessor), DataBinding (generic two-way binding with
path/literal identity), ComponentProperties (validated unresolved
properties), SurfaceTheme (marker protocol)
JSONValue) and Array where Element == Node
type instead of prototype's JSONSchema
ConcatFunction, IsEmptyFunction, TestTheme) covering schema lookup,
theme parsing, function evaluation, node equality, data binding
get/set, and component properties
Verification: