Skip to content

Web core update#764

Open
gspencergoog wants to merge 39 commits intogoogle:mainfrom
gspencergoog:web_core_update
Open

Web core update#764
gspencergoog wants to merge 39 commits intogoogle:mainfrom
gspencergoog:web_core_update

Conversation

@gspencergoog
Copy link
Collaborator

@gspencergoog gspencergoog commented Mar 4, 2026

Description

Specific Changes

  • v0.9 Function and expression support:
    • Added ExpressionEvaluator, ExpressionParser, and BasicFunctions.
    • Added MessageProcessor.
  • Test Coverage: Added comprehensive tests for web_core v0.9 components including ExpressionEvaluator, ExpressionParser, BasicFunctions, and MessageProcessor. Also added tests for v0.8 ModelProcessor and styles.
  • Documentation: Cleaned up implementation comments in test files to match documentation standards (concise, factual, third-person).
  • Compliance: Added 2025 Google LLC copyright headers to all source files in renderers/web_core.
  • Refactoring: Updated index.ts exports in web_core for better organization and clarity.
  • Fixes: Resolved Angular import issues and updated Lit sample dependencies to ensure correct builds.
  • Parity: Converted v0_8 schemas to Zod schemas and added a validation script to add schema validation and still make sure that the schemas don't drift from specification.

Verification

  • Automated Tests: Ran npm test in renderers/web_core, confirming 130 passing tests with no regressions.
  • Manual Verification: Verified copyright headers were correctly applied to 29 source files, skipping generated and config files.

Summary of Changes

This pull request significantly advances the web_core library by introducing version 0.9, which brings powerful expression evaluation and function support, alongside a refined message processing system. These updates aim to provide more dynamic and flexible UI rendering capabilities. The changes also include crucial maintenance, dependency updates, and compliance efforts, ensuring the library remains robust and up-to-date.

Highlights

  • Web Core v0.9 Upgrade: Introduced a new version (v0.9) of the web_core library, bringing advanced expression and function evaluation capabilities.
  • Expression and Function Support: Added ExpressionEvaluator, ExpressionParser, and BasicFunctions to enable dynamic logic and data manipulation within the web_core framework.
  • Enhanced Message Processing: Implemented a new MessageProcessor for v0.9, improving how messages are handled and state is managed across surfaces.
  • Comprehensive Test Coverage: Expanded test suites for both v0.8 components (like ModelProcessor and styles) and all new v0.9 components, ensuring robustness and correctness.
  • Codebase Maintenance and Compliance: Refactored index.ts exports for better organization, resolved Angular import issues, updated Lit sample dependencies, and added 2025 Google LLC copyright headers to all source files.
Changelog
  • renderers/angular/src/lib/data/processor.ts
    • Updated import paths for A2uiMessageProcessor and Types to use the v0_8 barrel export, resolving Angular import issues.
  • renderers/web_core/package-lock.json
    • Added rxjs and tslib dependencies.
    • Removed resolved fields from various node_modules entries, likely due to a package-lock.json regeneration.
  • renderers/web_core/package.json
    • Refactored exports field to use versioned entry points (./v0_8, ./v0_9, etc.) for better modularity.
    • Removed direct data/* and schemas/* exports, streamlining the API surface.
    • Added rxjs to dependencies.
    • Updated the test command to run tests across the entire dist directory.
  • renderers/web_core/scripts/copy-spec.js
    • Added 2025 Google LLC copyright header.
  • renderers/web_core/src/v0_8/data/model-processor.test.ts
    • Added comprehensive tests for A2uiMessageProcessor functionality, covering rendering, surface updates, data model interaction, component reference resolution, template expansion, and path normalization.
  • renderers/web_core/src/v0_8/index.ts
    • Added 2025 Google LLC copyright header.
    • Reordered exports for consistency and clarity.
  • renderers/web_core/src/v0_8/styles/styles.test.ts
    • Added tests for style utility functions including merge, appendToAll, toProp, and createThemeStyles.
  • renderers/web_core/src/v0_9/basic_catalog/expressions/expression_evaluator.test.ts
    • Added tests for ExpressionEvaluator, covering primitive evaluation, data bindings, function calls, nested expressions, recursion depth limits, and graceful handling of unknown functions.
  • renderers/web_core/src/v0_9/basic_catalog/expressions/expression_evaluator.ts
    • Implemented ExpressionEvaluator class to support evaluation of function calls, data bindings, and primitive values.
    • Added type guards (isFunctionCall, isDataBinding) for robust expression type checking.
    • Added 2025 Google LLC copyright header.
  • renderers/web_core/src/v0_9/basic_catalog/expressions/expression_parser.test.ts
    • Added tests for ExpressionParser, covering string interpolation, function calls, literals, nested expressions, escaped characters, and error handling for malformed input.
  • renderers/web_core/src/v0_9/basic_catalog/expressions/expression_parser.ts
    • Implemented ExpressionParser for parsing string interpolations and expressions, including handling of literals, function calls, and data bindings.
    • Added 2025 Google LLC copyright header.
  • renderers/web_core/src/v0_9/basic_catalog/functions/basic_functions.test.ts
    • Added tests for BASIC_FUNCTIONS, covering arithmetic, comparison, logical, string manipulation, validation, and formatting functions.
  • renderers/web_core/src/v0_9/basic_catalog/functions/basic_functions.ts
    • Defined BASIC_FUNCTIONS object containing implementations for various arithmetic, comparison, logical, string, validation, and formatting functions.
    • Added 2025 Google LLC copyright header.
  • renderers/web_core/src/v0_9/basic_catalog/index.ts
    • Added a new barrel export file for the basic_catalog module.
    • Added 2025 Google LLC copyright header.
  • renderers/web_core/src/v0_9/catalog/types.ts
    • Added 2025 Google LLC copyright header.
  • renderers/web_core/src/v0_9/common/events.ts
    • Added 2025 Google LLC copyright header.
    • Added JSDoc comments for EventEmitter methods (subscribe, emit, dispose).
  • renderers/web_core/src/v0_9/index.ts
    • Added 2025 Google LLC copyright header.
    • Reordered exports for better organization and clarity.
  • renderers/web_core/src/v0_9/processing/message-processor.test.ts
    • Added tests for MessageProcessor, covering surface creation/deletion, component updates, data model interaction, and various error/warning scenarios (e.g., multiple update types, missing component type, duplicate surface, non-existent surface).
  • renderers/web_core/src/v0_9/processing/message-processor.ts
    • Added 2025 Google LLC copyright header.
    • Updated constructor to make actionHandler optional.
    • Added JSDoc comments for processMessages method.
    • Implemented getData, resolvePath, and setData methods for data model interaction.
  • renderers/web_core/src/v0_9/rendering/component-context.test.ts
    • Added tests for ComponentContext, covering correct initialization, action dispatching, error handling for non-existent components, and data context path configuration.
  • renderers/web_core/src/v0_9/rendering/component-context.ts
    • Added 2025 Google LLC copyright header.
    • Added JSDoc comments for the constructor and dispatchAction method.
  • renderers/web_core/src/v0_9/rendering/data-context.test.ts
    • Added 2025 Google LLC copyright header.
  • renderers/web_core/src/v0_9/rendering/data-context.ts
    • Added 2025 Google LLC copyright header.
  • renderers/web_core/src/v0_9/schema/common-types.ts
    • Added 2025 Google LLC copyright header.
  • renderers/web_core/src/v0_9/schema/index.ts
    • Added 2025 Google LLC copyright header.
  • renderers/web_core/src/v0_9/schema/server-to-client.ts
    • Added 2025 Google LLC copyright header.
  • renderers/web_core/src/v0_9/state/component-model.test.ts
    • Added tests for ComponentModel, covering update notifications, unsubscription behavior, and the componentTree representation.
  • renderers/web_core/src/v0_9/state/component-model.ts
    • Added 2025 Google LLC copyright header.
    • Added JSDoc comments for the class, constructor, properties getter, and dispose method.
    • Implemented a componentTree getter to provide a JSON representation of the component.
  • renderers/web_core/src/v0_9/state/data-model.test.ts
    • Added 2025 Google LLC copyright header.
    • Added tests to ensure proper error handling when null or undefined paths are used for get and set operations.
  • renderers/web_core/src/v0_9/state/surface-components-model.test.ts
    • Added 2025 Google LLC copyright header.
  • renderers/web_core/src/v0_9/state/surface-components-model.ts
    • Added 2025 Google LLC copyright header.
    • Added JSDoc comments for the class and its methods.
    • Implemented an entries getter to provide an iterator over components.
  • renderers/web_core/src/v0_9/state/surface-group-model.test.ts
    • Added 2025 Google LLC copyright header.
  • renderers/web_core/src/v0_9/state/surface-group-model.ts
    • Added 2025 Google LLC copyright header.
    • Added JSDoc comments for the class and its methods.
    • Implemented a surfacesMap getter to provide a readonly map of active surfaces.
  • renderers/web_core/src/v0_9/state/surface-model.test.ts
    • Added 2025 Google LLC copyright header.
    • Added tests to verify proper resource disposal of the SurfaceModel.
  • renderers/web_core/src/v0_9/state/surface-model.ts
    • Added 2025 Google LLC copyright header.
    • Added JSDoc comments for the class, constructor, dispatchAction, and dispose methods.
  • renderers/web_core/src/v0_9/test/test-utils.ts
    • Added 2025 Google LLC copyright header.

gspencergoog and others added 13 commits March 3, 2026 14:21
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
- Added `model-processor.test.ts` for v0.8 coverage.
- Added `expression_evaluator.test.ts` and `basic_functions.test.ts` for v0.9 coverage.
- Updated `message-processor.test.ts` with edge case tests.
- Fixed `ExpressionEvaluator` to include `getFunction` for testing.
- Aligned tests with v0.9 specification (removed unused functions).
- Added `expression_parser.test.ts` to test strict interpolation logic.
- Added `styles.test.ts` to verify style utility functions.
- Verified all 119 tests pass.
- Added `component-context.test.ts` to verify context initialization and action dispatching.
- Verified all 123 tests pass.
- Added edge case tests for MessageProcessor (warnings).
- Added null/undefined path validation for DataModel.
- Added pass-through test for ExpressionEvaluator.
- Added dispose test for SurfaceModel.
- Added componentTree getter test for ComponentModel.
- Verified all 130 tests pass.
…rage

- Reviewed and updated implementation comments in test files to match documentation standards.
- Added comprehensive test coverage for v0.8 model processor.
- Added test coverage for v0.9 expression evaluator, parser, and basic functions.
- Verified all tests pass.
- Added 2025 Google LLC copyright header to all checks-in source files in renderers/web_core.
- Skipped generated, JSON, and Markdown files.
gemini-code-assist[bot]

This comment was marked as resolved.

gspencergoog and others added 5 commits March 3, 2026 17:29
…tions.ts

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
- Remove legacy v0.8 primitive wrappers (literalString, etc.)
- Implement recursive evaluation for Arrays and Objects with depth limit
- Add tests for deep recursion and nested structures
- Wrap `parse` logic in try-catch to prevent synchronous throws.
- Return `throwError` on failure to allow graceful error handling by consumers.
- Add tests for error scenarios (recursion limits, malformed input).
@google google deleted a comment from gemini-code-assist bot Mar 4, 2026
@gspencergoog
Copy link
Collaborator Author

/gemini review

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a significant update to web_core with version 0.9, adding expression and function evaluation capabilities. The changes are extensive, including new parsers, evaluators, a suite of basic functions, and a new message processor, all backed by comprehensive tests. The PR also includes important maintenance work like refactoring exports for better modularity and adding copyright headers. My review found one issue in the implementation of a new basic function.

Note: Security Review did not run due to the size of the PR.

- Add `./data/*` to `exports` in `package.json` to allow importing `model-processor` and `guards` from `web_core`.
- This fixes `Cannot find module` errors in `renderers/lit` during CI build.
- Add `.` export pointing to `./dist/src/v0_8/index.js` (and types)
- Required because `exports` field usage disables default `main` lookup for the package root.
@gspencergoog gspencergoog requested a review from paullewis as a code owner March 4, 2026 03:40
Copy link
Collaborator

@jacobsimionato jacobsimionato left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall LGTM to fixing the copyright headers and adding expression parsing stuff

I'd love to see the function resolution pipeline and the APIs for the basic catalog items also move into the core library, but that can be in a future step.

…basic functions

- Expressions: Refactored `ExpressionParser` to consume `DataContext` directly, simplifying observable subscription patterns for reactive function calls.
- Functions: Hardened the `divide` function in `basic_functions` to handle `null`, `undefined`, and division by zero. Added a new `openUrl` action wrapper.
- Data Context: Refactored `DataContext.subscribeDynamicValue` to robustly resolve dynamic argument streams and reactively evaluate function outputs. Added `function_execution.spec.ts` for coverage.
- Docs: Updated `.gemini/GEMINI.md` repository structure to match the latest layout across protocol versions (`v0.8` through `v0.10`) and new tool extensions.
- Style: Applied comprehensive code formatting standard sweep across the `v0_9` directory.
Add the ability to gracefully track evaluation errors natively
inside DataContext during dynamic value resolution instead of throwing.

- Add `errors`, `reportError`, and `clearErrors` to DataContext
- Change `console.warn` occurrences to populate error context
- Update unit tests with new expectations
…ssageProcessor

These methods were vestiges of the v0.8 architecture where data binding relied on the physical component node itself. In v0.9, the data model is accessed directly via absolute JSON Pointer paths directly against the SurfaceModel, rendering the processor-level abstractions unnecessary.

Removed the methods from `MessageProcessor.ts` and their associated tests over in `message-processor.test.ts`. Verified building and vitest passes successfully.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to not keep a copy of the schemas in the renderer library?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. Let me remedy that.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, I removed the schemas that were checked in (accidentally) in v0_8.

In v0_9, I had used Zod schemas so that we can do schema validation, and so I converted the v0_8 schemas to also be Zod schemas.

To make sure that they won't drift from the schemas in the specification, I added a validation script tha runs with the tests in web_core, ao CI should fail if they diverge.

Restores the  script to copy the authoritative schemas from
the central  folder into the local
directory during the build. This avoids referencing files outside of the
package distribution directory which causes issues when publishing to
npm.

Also updates the npm  script to reference the  files
directly as Node's test runner can no longer resolve the  directory
to an entrypoint without an  under certain conditions.
All generated JSON schemas are ignored via  to avoid
duplicate check-ins.
- Explicitly matches Zod definitions to JSON structure using \`zod-to-json-schema\`
- Validates the entire definitions tree and root oneOf structure
- Handles edge-case structural mismatches such as the \`A2uiMessage\` definition expansion and const string metadata
- Refactors schema validation on MessageProcessor to enforce correct schema validation and skips missing IDs.
- Injects \`npx tsx scripts/verify-schema.ts\` before tests
- Marked task as complete in \`task.md\`
- Add strict Zod schemas inside src/v0_8/schema matching standard specifications
- Migrate v0.8 Typescript interfaces to use z.infer for DRYness and exact type-safety
- Add validation to v0.8 model-processor
- Update verify-schema.ts testing script to cover v0.8 backwards compatibility and enforce strict structural parity with standard catalog json schema
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The schemas folder now only has a .gitignore file. What about moving the file on its parent folder and remove the schemas folder?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, yes, needs to be removed. Done.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, actually, we should be ignoring things there still. The schemas are still copied here in order to be able to export them for use in prompts. It was doing that for v0.8, and I added it for v0.9.

I moved the .gitignore up to the web_core directory so that they don't get checked in again.

- Updated `styles.color` to `styles.primaryColor: "#0000ff"`
- Injected `usageHint` implicitly removed from component scope
- Skipped test cases dependent on deprecated CRDT `valueMap`
- Explicitly verified compilation with TS noEmit
Updated copy-spec.js script and wireit config to copy the canonical JSON schema definitions for v0.9 into renderers/web_core/src/v0_9/schemas on build.

Exported the v0.9 server_to_client.json payload under Schemas namespace inside v0_9/index.ts to allow prompt synchronization on tools expecting the raw schema.

Added a local .gitignore within renderers/web_core to correctly prevent the dynamically generated /schemas directories from tracking in version control.
- `ExpressionParser` now decodes string interpolation directly into `DynamicValue` ASTs instead of evaluating them aggressively.
- Deleted `ExpressionEvaluator` as parser + context handles dynamic resolution.
- `DataContext` error accumulation replaced with robust logging meant for the message processor pipeline.
- `verify-schema.ts` migrated to native `node:test` suite for v0.8 and v0.9.
@gspencergoog
Copy link
Collaborator Author

Okay, @jacobsimionato I think I addressed all of your comments. PTAL.

Copy link
Collaborator

@jacobsimionato jacobsimionato left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Amazing - looks very close!

processMessages(messages: ServerToClientMessage[]): void {
for (const message of messages) {
for (const rawMessage of messages) {
const message = A2uiMessageSchema.parse(rawMessage);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this necessary when the message type passed in is ServerToClientMessage ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the runtime type checking that Zod provides. The input has been parsed as JSON, and cast to ServerToClientMessage, but unless you run it through the Zod schema, it doesn't actually check the types of anything (ServerToClientMessage is a TypeScript type, but JS doesn't know about it). Once it has been parsed, it is guaranteed to match the schema, and if it fails, it fails here with a Zod message, rather than later with a generic TypeError.

* Parses an input string into an array of DynamicValues.
* If the input contains no interpolation, it returns the raw string as a single literal.
*/
public parse(input: string, depth = 0): DynamicValue[] {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So neat!!

/**
* Optional map of functions provided by this catalog.
*/
readonly functions?: ReadonlyMap<string, any>;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/any/FunctionImplementation ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call. Changed.

/**
* A function implementation that can be registered with the evaluator or basic catalog.
*/
export type FunctionImplementation = (
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't really a schema, so I think it should live in catalog/types.ts

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow, this is hectic but it looks about right. The use of rxjs internally is neat!

formatString: (args) => {
const template = String(args["value"] || "");
const parser = new ExpressionParser();
return parser.parse(template);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still think this might be wrong, because parser.parse() returns type DynamicValue[], while this function should actually return a formatted string, right?

I imagine it needs to do an additional step like call dataContext.resolve(value) for each of the parsed DynamicValues, then subscribe to all the results and return an observable that concatenates them all together etc.

I think you already set up the FunctionImplementation interface such that this does have access to DataContext which is great, so hopefully it's not a huge change.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't see a test for it either so that could be good to verify it works!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

3 participants