A data-binding scope: the absolute path relative bindings resolve against, the collection-template iteration index, and — when built for a surface — what is needed to evaluate dynamic values.
The root scope is "/". A component rendered for item 2 of a
/items template runs in the nested scope "/items/2/", so its
relative path name resolves to /items/2/name.
Path resolution
Follows the reference:
an absolute path (starting with
/) is returned unchanged,""and"."resolve to the scope itself,any other path is joined to the scope, ignoring trailing slashes on the scope.
iex> ctx = A2UICore.Resolution.DataContext.new("/user") iex> A2UICore.Resolution.DataContext.resolve_path(ctx, "name") "/user/name" iex> A2UICore.Resolution.DataContext.resolve_path(ctx, "/other") "/other" iex> A2UICore.Resolution.DataContext.resolve_path(ctx, ".") "/user"
Dynamic values
resolve_dynamic_value/2 evaluates a literal, a data binding
({"path": …} in v0.9, {"@path": …} in v1.0) or a function call
({"call": …, "args": …} / {"@call": …, "args": …}, optionally with
a catalogId) against the data model, recursing through arrays and
objects. It never raises: what the reference reports through the
surface comes back as effects next to the value —
{:warning, %{code: "MISSING_DATA_BINDING", path: …, message: …}}when a bound path is absent (once per path per call),{:error, %{code: "EXPRESSION_ERROR", message: …, expression: …}}when a function call fails; the call's value is thennil.
A function can ask for more through its effects — the MCP catalog's
functions do (A2UICore.Functions.MCP):
{:write, %{path: path, value: value}}— write the data model;{:messages, %{messages: messages, source: :resource | :inline}}— apply A2UI messages.
They come back in evaluation order. A renderer applies them when they
come from an action (A2UICore.Resolution.NodeResolver.invoke/5);
rendering ignores them.
Agent functions
From v1.0 a function that the catalog a call resolves to does not
declare, or declares without an implementation, may be the agent's: a
renderer sends it to the agent as a callAgentFunction message. A
scope built with the :agent_calls option routes such calls instead
of failing them. The option holds what the renderer knows of the calls
it sent, keyed by {name, catalog_id, args} (catalog_id is the one
the call names, else nil; args are resolved):
:pending— sent, no response yet; the call's value isnil;{:ok, value}— the agent's response; the call's value isvalue;{:error, payload}— the call failed; its value isnil.
Every routed call comes back as an
{:agent_call, %{key: key, call: call}} effect, where call is the
function call object to send ("@call", resolved "args", and the
"catalogId" the call named), so that the renderer sends the calls it
has not sent yet. With agent_calls: {:send, calls}, the scope of a
function-call action, the call the action makes is always routed
without a lookup, and its effect also carries action: true; the
calls in its arguments are looked up in calls. A call that names a
catalog the scope does not reach is still a catalog error.
Who may call
A function the renderer runs is refused, with an EXPRESSION_ERROR,
when its catalog reserves it for the agent (allowedCallers: "agentOnly"), and when it requires a user gesture
(requiresUserActivation: true, as openUrl does) and the scope was
not built for one with user_activated: true. A renderer builds its
action scopes that way (A2UICore.Resolution.NodeResolver.invoke/5);
property bindings and check conditions never are.
v1.0 objects follow the reserved-key rule
(A2UICore.Validation.ReservedKeys): @@x is the literal key @x,
any other single-@ key is an INVALID_RESERVED_KEY error.
Summary
Types
What a renderer knows of an agent function call it sent.
The agent function calls a scope knows, by {name, catalog_id, args};
nil when the scope does not route calls to the agent.
A warning or error produced while resolving, what a function asks for, or a call routed to the agent.
Functions
Creates the root scope for a A2UICore.State.Surface: its data
model, its default catalog and the catalogs it can reach.
The active collection index: the nearest scope's recorded index, or
the numeric last segment of its path, walking outward; nil outside a
collection.
Creates a child scope for relative_path (a leading / is ignored),
optionally recording the iteration index of a collection template.
Creates a root scope at path (default "/"). The stored path always
ends with a slash.
Resolves an action's dynamic parts: an event's context and
userMessage, a plain action object, or a function call.
Evaluates a dynamic value; see the module documentation.
Resolves path against the scope to an absolute pointer.
Whether bindings use the v1.0 @path/@call spelling, decided by
the scope's protocol version (that of its surface, which outlives a
missing default catalog).
Types
What a renderer knows of an agent function call it sent.
@type agent_calls() :: nil | %{optional(term()) => agent_call_state()} | {:send, %{optional(term()) => agent_call_state()}}
The agent function calls a scope knows, by {name, catalog_id, args};
nil when the scope does not route calls to the agent.
@type effect() :: {:warning, map()} | {:error, map()} | {:write, map()} | {:messages, map()} | {:agent_call, map()}
A warning or error produced while resolving, what a function asks for, or a call routed to the agent.
@type t() :: %A2UICore.Resolution.DataContext{ agent_calls: agent_calls(), catalog: A2UICore.Catalog.t() | nil, catalogs: %{optional(String.t()) => A2UICore.Catalog.t()}, data_model: A2UICore.State.DataModel.t() | nil, index: non_neg_integer() | nil, locale: String.t() | nil, parent: t() | nil, path: String.t(), protocol_version: String.t() | nil, surface_id: String.t() | nil, user_activated: boolean() }
Functions
@spec for_surface(A2UICore.State.Surface.t(), keyword()) :: t()
Creates the root scope for a A2UICore.State.Surface: its data
model, its default catalog and the catalogs it can reach.
Options: :path (default "/"), :locale (default: the surface's),
:agent_calls and :user_activated.
@spec index(t()) :: non_neg_integer() | nil
The active collection index: the nearest scope's recorded index, or
the numeric last segment of its path, walking outward; nil outside a
collection.
iex> root = A2UICore.Resolution.DataContext.new()
iex> item = A2UICore.Resolution.DataContext.nested(root, "items/3")
iex> A2UICore.Resolution.DataContext.index(item)
3
iex> A2UICore.Resolution.DataContext.index(root)
nil
@spec nested(t(), String.t(), non_neg_integer() | nil) :: t()
Creates a child scope for relative_path (a leading / is ignored),
optionally recording the iteration index of a collection template.
Creates a root scope at path (default "/"). The stored path always
ends with a slash.
Options: :data_model, :catalog (the default catalog, if any),
:catalogs (%{catalog_id => catalog} reachable by catalogId),
:protocol_version (default: the default catalog's), :surface_id
(for messages), :locale, :agent_calls (see
Agent functions), :user_activated (see
Who may call; default false).
Resolves an action's dynamic parts: an event's context and
userMessage, a plain action object, or a function call.
Evaluates a dynamic value; see the module documentation.
Resolves path against the scope to an absolute pointer.
Whether bindings use the v1.0 @path/@call spelling, decided by
the scope's protocol version (that of its surface, which outlives a
missing default catalog).