Skip to content

feat(web_core): settle Promise-valued function arguments before validation - #3578

Open
josemontespg wants to merge 1 commit into
web-core-export-safe-regexfrom
web-core-settle-async-args
Open

josemontespg wants to merge 1 commit into
web-core-export-safe-regexfrom
web-core-settle-async-args

Conversation

@josemontespg

@josemontespg josemontespg commented Oct 23, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

The runtime now awaits PromiseLike values nested in a function call's resolved arguments before validating and running the function, so a synchronous catalog function can take the result of an asynchronous one (jmespath(callMcpTool(...))) without widening its schema or awaiting by hand. Synchronous expressions stay synchronous: settleDeep returns its input unchanged when nothing is pending, and requiresUserActivation is still checked in the user gesture's turn. A rejected inner call aborts the outer call and reports one EXPRESSION_ERROR; in reactive bindings the signal keeps its value until the call settles.

Changes

  • @a2ui/web_core: src/common/settle_deep.ts (isThenable, settleDeep, internal to web_core); createCatalogInvoker, DataContext (resolveDynamicValue, resolveFunctionCallValue, resolveSignal) and RpcHandler.handleCallRendererFunction settle arguments; tests and CHANGELOG.

Known limitation

In a reactive binding (not an action) whose outer function wraps an asynchronous call, the outer function runs once with undefined while the inner call is pending and reports a validation EXPRESSION_ERROR before re-running with the settled value. Actions, which the MCP examples and the filesystem sample use, do not go through that path.

Verification

  • yarn workspace @a2ui/web_core run build | test | lint (1094 tests) passes locally.

@github-project-automation github-project-automation Bot moved this to Todo in A2UI Oct 23, 2026
@josemontespg
josemontespg force-pushed the web-core-settle-async-args branch from 7059a9f to 1597a1b Compare October 23, 2026 23:36
@josemontespg
josemontespg added this pull request to stack #3585 October 23, 2026 23:38

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

Copy link
Copy Markdown
Contributor

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 refactors the A2UI expression runtime to automatically and recursively await pending Promises in function arguments before validating and executing the functions. This centralizes the asynchronous argument resolution logic via a new settleDeep utility, allowing individual function implementations (such as jmespath, parseJson, split, and regex functions) to be simplified and to use stricter Zod schemas instead of z.unknown(). The changes are well-supported by extensive unit tests and updated documentation. I have no feedback to provide as there are no review comments to address.

@josemontespg
josemontespg force-pushed the web-core-settle-async-args branch from 1597a1b to e86a97e Compare October 23, 2026 23:43
@josemontespg
josemontespg force-pushed the web-core-settle-async-args branch from e86a97e to fab6316 Compare October 23, 2026 23:56
@josemontespg
josemontespg force-pushed the web-core-settle-async-args branch from fab6316 to f5a49d4 Compare October 24, 2026 00:06
@josemontespg
josemontespg force-pushed the web-core-settle-async-args branch from f5a49d4 to b513612 Compare October 24, 2026 01:13
@josemontespg
josemontespg force-pushed the web-core-settle-async-args branch from b513612 to a5e3834 Compare October 24, 2026 01:26
@josemontespg
josemontespg removed this pull request from stack #3585 October 24, 2026 01:26
@josemontespg
josemontespg added this pull request to stack #3594 October 24, 2026 01:26
@josemontespg
josemontespg force-pushed the web-core-settle-async-args branch from a5e3834 to 08d3fbc Compare October 24, 2026 01:32
@josemontespg
josemontespg force-pushed the web-core-settle-async-args branch from 08d3fbc to faf12c5 Compare October 24, 2026 01:47
@josemontespg
josemontespg force-pushed the web-core-settle-async-args branch from faf12c5 to 8930a21 Compare October 26, 2026 09:10
@josemontespg
josemontespg force-pushed the web-core-settle-async-args branch from 8930a21 to 7ac69ed Compare October 26, 2026 09:51
@josemontespg
josemontespg force-pushed the web-core-settle-async-args branch 2 times, most recently from b231dd3 to f31be4d Compare October 26, 2026 17:28
@josemontespg
josemontespg force-pushed the web-core-settle-async-args branch 2 times, most recently from 19bc420 to 1233d9c Compare October 26, 2026 18:18
@josemontespg
josemontespg force-pushed the web-core-settle-async-args branch from b40f1c4 to e2ef243 Compare October 26, 2026 20:10
@josemontespg
josemontespg force-pushed the web-core-settle-async-args branch 2 times, most recently from bc19517 to 56acdc1 Compare October 26, 2026 20:31
@josemontespg
josemontespg removed this pull request from stack #3629 October 26, 2026 20:34
@josemontespg
josemontespg added this pull request to stack #3640 October 26, 2026 20:34
@josemontespg
josemontespg force-pushed the web-core-settle-async-args branch from 56acdc1 to 29ea6f6 Compare October 26, 2026 20:38
@josemontespg
josemontespg removed this pull request from stack #3640 October 26, 2026 21:37
@josemontespg
josemontespg force-pushed the web-core-settle-async-args branch from 29ea6f6 to f505d6b Compare October 26, 2026 21:38
@josemontespg
josemontespg changed the base branch from catalogs-docs-guide to catalogs-mcp-docs-guide October 26, 2026 21:38
@josemontespg
josemontespg added this pull request to stack #3643 October 26, 2026 21:38
@josemontespg
josemontespg removed this pull request from stack #3643 October 26, 2026 22:01
@josemontespg
josemontespg force-pushed the web-core-settle-async-args branch from f505d6b to 0e4857d Compare October 26, 2026 22:01
@josemontespg
josemontespg changed the base branch from catalogs-mcp-docs-guide to web-core-export-safe-regex October 26, 2026 22:02
@josemontespg
josemontespg added this pull request to stack #3645 October 26, 2026 22:04
Comment thread typescript/core/web_core/CHANGELOG.md Outdated
Comment thread typescript/core/web_core/src/rpc/rpc-handler.ts
Comment thread typescript/core/web_core/src/rpc/rpc.test.ts Outdated
…ation

The runtime now awaits pending Promises nested anywhere in the resolved
arguments of a function call before it validates them and runs the
function. Calls whose arguments are all settled stay synchronous. At the
top level of an expression a rejected call is reported as an
EXPRESSION_ERROR and resolves to undefined; nested, the rejection fails
the enclosing call. A reactive subscription to an asynchronous call holds
undefined until the result settles and ignores completions that arrive
after its arguments changed, and RpcHandler awaits pending arguments
before validating a callRendererFunction.
@josemontespg
josemontespg removed this pull request from stack #3645 October 26, 2026 23:14
@josemontespg
josemontespg added this pull request to stack #3647 October 26, 2026 23:17
@josemontespg
josemontespg force-pushed the web-core-settle-async-args branch 2 times, most recently from 0e4857d to 13166ac Compare October 26, 2026 23:28
@josemontespg
josemontespg marked this pull request as ready for review October 26, 2026 23:37
@josemontespg
josemontespg requested a review from ditman October 26, 2026 23:37
@josemontespg
josemontespg removed this pull request from stack #3647 October 27, 2026 00:30
@josemontespg
josemontespg added this pull request to stack #3649 October 27, 2026 00:32

@ditman ditman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM! Moving this below the catalog PRs so it only touches typescript/core/web_core/ and keeping isThenable and settleDeep internal to web_core makes this super clean. This will also let sample-local functions (like in a2ui-over-mcp-filesystem) compose with callMcpTool without custom Promise-settling wrappers.

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants