Describe the Bug
DataContext.resolveDynamicValue() treats arrays as literals and returns them as-is, without recursively resolving DynamicValue elements inside the array. This means array-typed arguments (e.g., values: [...] in and/or function calls) containing path bindings or nested function calls are never resolved—the function receives raw {path: "..."} or {call: "..."} objects instead of their actual resolved values.
Steps to Reproduce
A. UI (React Gallery)
- From the monorepo root, install deps if needed.
- Start the React explorer:
cd renderers/react/a2ui_explorer
yarn dev
- Open the printed URL (e.g. http://localhost:5173)
- In the left sample list, select
Advanced Form Validator
(specification/v0_9_1/catalogs/basic/examples/32_advanced-form-validator.json)
- Advance all messages so the surface is fully rendered
- Leave the form empty (do not fill email/phone/zip, do not check “I agree…”)
- Observe the Submit Registration button
B. Minimal binder check (optional)
- Load example 32_advanced-form-validator.json via MessageProcessor + basicCatalog
- Create a GenericBinder for component id submit-btn with ButtonApi.schema
- Inspect binder.snapshot.isValid with the default data model
Expected Behavior
The Sumbit button should be disabled. When resolveDynamicValue encounters an array, it should recursively resolve each element (each element may itself be a path binding, function call, or nested array) and return an array of resolved values. Likewise, resolveSignal should establish reactive subscriptions for each array element.
Screenshots / Video / Logs
The screenshots above demonstrate the bug in example 32_advanced-form-validator a form with and/or validation.All form fields are blank, yet the submit button remains enabled (i.e., passes validation). This happens because the validation expression's and/or values array is never resolved.
Environment Details
- OS: macOS
- Browser/Platform: Node.js ≥ 20
- SDK/Package Name & Version: @a2ui/web-core v0.9
- Protocol Version: v0.9
- Agent Framework & LLM Model: N/A
Additional Context
The root cause is in data-context.ts. Both resolveDynamicValue and resolveSignal have an early-return guard that conflates arrays with primitives:
// Before (buggy): arrays are returned as-is
if (value === null || typeof value !== 'object' || Array.isArray(value)) {
return value as V;
}
The type definition in common-types.ts explicitly includes z.array(z.any()) as a DynamicValue variant, confirming that arrays are containers of DynamicValues and not terminal values. The fix is to separate the array check so that each element is recursively resolved:
// After (fixed): primitives only in the early return
if (value === null || typeof value !== 'object') {
return value as V;
}
// Arrays: resolve each element
if (Array.isArray(value)) {
return value.map(item => this.resolveDynamicValue(item)) as V;
}
The same fix applies to resolveSignal for reaelements.
Describe the Bug
DataContext.resolveDynamicValue()treats arrays as literals and returns them as-is, without recursively resolvingDynamicValueelements inside the array. This means array-typed arguments (e.g.,values: [...]in and/or function calls) containing path bindings or nested function calls are never resolved—the function receives raw{path: "..."}or{call: "..."}objects instead of their actual resolved values.Steps to Reproduce
A. UI (React Gallery)
Advanced Form Validator(specification/v0_9_1/catalogs/basic/examples/32_advanced-form-validator.json)
B. Minimal binder check (optional)
Expected Behavior
The Sumbit button should be disabled. When resolveDynamicValue encounters an array, it should recursively resolve each element (each element may itself be a path binding, function call, or nested array) and return an array of resolved values. Likewise, resolveSignal should establish reactive subscriptions for each array element.
Screenshots / Video / Logs
The screenshots above demonstrate the bug in example
32_advanced-form-validatora form withand/orvalidation.All form fields are blank, yet the submit button remains enabled (i.e., passes validation). This happens because the validation expression'sand/orvalues array is never resolved.Environment Details
Additional Context
The root cause is in data-context.ts. Both resolveDynamicValue and resolveSignal have an early-return guard that conflates arrays with primitives:
The type definition in common-types.ts explicitly includes z.array(z.any()) as a DynamicValue variant, confirming that arrays are containers of DynamicValues and not terminal values. The fix is to separate the array check so that each element is recursively resolved:
The same fix applies to resolveSignal for reaelements.