Skip to content

feat(web_core): add resolveAction and improve error handling#856

Merged
gspencergoog merged 9 commits intogoogle:mainfrom
gspencergoog:web_core
Mar 16, 2026
Merged

feat(web_core): add resolveAction and improve error handling#856
gspencergoog merged 9 commits intogoogle:mainfrom
gspencergoog:web_core

Conversation

@gspencergoog
Copy link
Collaborator

Changes in renderers/web_core

Here are some changes to web_core to prepare for the 0.9 angular renderer.

Public API Changes

1. DataContext (New Method)

  • Added: resolveAction(action: Action): any
    • Description: This method takes an Action object and resolves its top-level DynamicValue properties (e.g., event context values) using the current DataContext. This bridges the gap between static component action definitions and the actual data bound to them.

2. Type-Safe Action Propagation

  • SurfaceModel:
    • Change: onAction stream and dispatchAction method are now strictly typed to use the Action interface from the schema instead of any.
  • SurfaceGroupModel:
    • Change: onAction now emits a strictly typed SurfaceGroupAction (Action & { surfaceId: string }). Spreading an action with surfaceId is now statically validated for type safety.

3. Error Handling (Enhanced Specificity)

  • Functions and evaluation pipelines now throw A2uiExpressionError instead of generic errors or silent failures:
    • DataContext: Both resolveDynamicValue and evaluateFunctionReactive translate ZodError into A2uiExpressionError with detail scopes (issues or errors).
    • Catalog: getFunction() now catches ZodError during argument parsing and raises A2uiExpressionError.
    • RegexImplementation: Now throws A2uiExpressionError on invalid regex patterns rather than returning false with a warning.

Internal Refactorings & Improvements

1. Reactivity Upgrades (DataContext)

  • resolveSignal: Substantially refactored.
    • Switched from maintaining continuous background resolution to a structured execution model with nested computed argument bundles and isolated effect subscriptions.
    • Ensures much safer AbortController cleanup to prevent resource leakage on unsubscription.

2. DataModel Edge Cases

  • Path Forcing: DataModel.set now verifies that the base reference is populated (this.data = {}) before traversing branches, preventing crashes on absolute root paths.

3. Testing Modernization

  • Updated continuous execution test cases in function_execution.spec.ts from old Node-style Node (done) callbacks to modern Promise-based resolutions.

File Reorganization

  • FunctionInvoker: The type definition was moved from src/v0_9/catalog/types.ts into a standalone file src/v0_9/catalog/function_invoker.ts and re-exported via index.ts. This was done to avoid import circular references There are no changes to the declaration itself.

…updates

- Update logical functions (`and`, `or`) to require the `values` array argument, removing deprecated individual arguments.
- Update `formatDate` to require `format` parameter, utilizing `date-fns`.
- Update expressions and math schemas with a preprocess layer for cleaner `null` layout to `undefined` coercion.
- Update guards and data-context tests for expanded v0.9 safety checks.
@gspencergoog gspencergoog changed the title feat(web_core): bump version to 0.9.0 with expression and formatDate … feat(web_core): bump version to 0.9.0 and add resolveAction Mar 14, 2026
@gspencergoog gspencergoog changed the title feat(web_core): bump version to 0.9.0 and add resolveAction feat(web_core): bump version to 0.9.0 and add resolveAction Mar 14, 2026
@google google deleted a comment from gemini-code-assist bot Mar 14, 2026
- Added SurfaceModel.dispatchError to format and emit error events conforming to v0.9 generic error schema.
- Updated DataContext.resolveDynamicValue and evaluateFunctionReactive to capture A2uiExpressionError & ZodError, dispatching to surface and returning fallbacks to avoid crashes.
- Updated ComponentContext and test suites (data-context, basic_functions, function_execution) to align with return-instead-of-throw design.
- All tests passing green.
@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

The pull request primarily focuses on upgrading the core web rendering library to version 0.9.0, which includes significant updates to expression parsing and function validation. Key changes involve updating package-lock.json files across various renderers (Angular, Lit, Markdown) to reflect the new web_core version and its dependencies, notably adding date-fns and @preact/signals-core while removing rxjs. The CHANGELOG.md was updated to document changes such as logical functions (and, or) now requiring a values array, formatDate needing a format parameter, and improved validation for math and comparison expressions. Code changes include minor formatting, increased icon font size, and extensive updates to function schemas using z.preprocess for null to undefined coercion and .refine for stricter argument validation. Error handling for function calls has been enhanced to catch ZodError and re-throw as A2uiExpressionError, which is then dispatched to the surface model. The DataContext and ComponentModel were refactored to better integrate with the SurfaceModel and its error dispatching mechanism. A review comment highlighted an issue where a test case incorrectly expected an A2uiExpressionError for divide with an invalid number, when z.coerce.number returns NaN, suggesting the test should assert NaN instead. Another comment pointed out that the email validation regex is too basic and should be replaced with a more robust version for improved quality.

import { Action } from "../schema/common-types.js";

/** An action wrapper that includes the origin surface ID. */
export type SurfaceGroupAction = Action & { surfaceId: string };
Copy link
Collaborator

Choose a reason for hiding this comment

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

I have a few changes in #866 which address a similar problem in a slightly different way (adding a full A2uiClientActionSchema), though this is a strict improvement, so let's go with it and my PR can refine it if necessary.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Sure, no problem. This felt like a "minimum" solution to me: it could probably be made better with a more formalized schema.

{
"name": "@a2ui/web_core",
"version": "0.8.5",
"version": "0.9.0",
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can we keep this at v0.8.5 for now, just in case @ditman and I need to push another v0.8 version of a renderer with fixes in web_core etc.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Sure. I was thinking of bumping it with the 0.9 renderer implementation, but I don't have to.

e.errors ?? e.issues,
);
this.surface.dispatchError({
code: "EXPRESSION_ERROR",
Copy link
Collaborator

Choose a reason for hiding this comment

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

A couple of thoughts:

  • Should we add this to the client_to_server.json spec in v0.10? For v0.9 could it make sense to use the VALIDATION_FAILED error type which has some structure around surfaceId and path etc? No stress for this PR, just curious about direction.

  • Should we have some centralized mapping from error classes e.g. A2uiExpressionError to whatever dispatchError actually accepts, to reduce the boilerplate here?

Neither of these blocking - i'm thrilled to see error handling overall.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I thought about adding it as a type in the client-to-server schema, but expressions are part of the basic catalog, not the main spec, so I wasn't sure if it belonged there.

A centralized mapping might make sense: at least it would give us a good place to add future mappings.

gspencergoog and others added 3 commits March 16, 2026 08:22
…tions.test.ts

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Updated the `EmailImplementation` to use a restricting regex requiring a 2-char TLD and standard valid characters. Increased the test coverage in `basic_functions.test.ts` for multiple email formats and fixed an unrelated issue in the `divide` test that was causing test failures due to strict type checking.
… design

Updated the comment in `resolveAction` to explain that its one-level non-recursive behavior aligns with the schema spec, which requires values to be single `DynamicValue` types and restricts arbitrary nesting.
@gspencergoog gspencergoog changed the title feat(web_core): bump version to 0.9.0 and add resolveAction feat(web_core): add resolveAction and improve error handling Mar 16, 2026
@gspencergoog gspencergoog marked this pull request as ready for review March 16, 2026 16:30
@gspencergoog gspencergoog merged commit 98fc29a into google:main Mar 16, 2026
11 checks passed
@github-project-automation github-project-automation bot moved this from Todo to Done in A2UI Mar 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants