@jini-ai/agentic 0.1.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +92 -0
- package/dist/a2ui/agent-to-renderer.d.ts +36 -2
- package/dist/a2ui/agent-to-renderer.d.ts.map +1 -1
- package/dist/a2ui/agent-to-renderer.js +23 -1
- package/dist/a2ui/agent-to-renderer.js.map +1 -1
- package/dist/a2ui/interpreter.d.ts +24 -1
- package/dist/a2ui/interpreter.d.ts.map +1 -1
- package/dist/a2ui/interpreter.js +115 -65
- package/dist/a2ui/interpreter.js.map +1 -1
- package/dist/a2ui/json-pointer.d.ts.map +1 -1
- package/dist/a2ui/json-pointer.js +28 -3
- package/dist/a2ui/json-pointer.js.map +1 -1
- package/dist/a2ui/renderer-to-agent.d.ts +35 -11
- package/dist/a2ui/renderer-to-agent.d.ts.map +1 -1
- package/dist/a2ui/renderer-to-agent.js +15 -2
- package/dist/a2ui/renderer-to-agent.js.map +1 -1
- package/dist/a2ui/resolve.d.ts +1 -1
- package/dist/a2ui/resolve.d.ts.map +1 -1
- package/dist/a2ui/resolve.js +29 -3
- package/dist/a2ui/resolve.js.map +1 -1
- package/dist/a2ui/tree.d.ts +27 -2
- package/dist/a2ui/tree.d.ts.map +1 -1
- package/dist/a2ui/tree.js +48 -9
- package/dist/a2ui/tree.js.map +1 -1
- package/dist/ag-ui.d.ts.map +1 -1
- package/dist/ag-ui.js +30 -1
- package/dist/ag-ui.js.map +1 -1
- package/dist/core/a2ui/agent-to-renderer.d.ts +613 -0
- package/dist/core/a2ui/agent-to-renderer.d.ts.map +1 -0
- package/dist/core/a2ui/agent-to-renderer.js +191 -0
- package/dist/core/a2ui/agent-to-renderer.js.map +1 -0
- package/dist/core/a2ui/catalog.d.ts +73 -0
- package/dist/core/a2ui/catalog.d.ts.map +1 -0
- package/dist/core/a2ui/catalog.js +304 -0
- package/dist/core/a2ui/catalog.js.map +1 -0
- package/dist/core/a2ui/common-types.d.ts +401 -0
- package/dist/core/a2ui/common-types.d.ts.map +1 -0
- package/dist/core/a2ui/common-types.js +130 -0
- package/dist/core/a2ui/common-types.js.map +1 -0
- package/dist/core/a2ui/index.d.ts +16 -0
- package/dist/core/a2ui/index.d.ts.map +1 -0
- package/dist/core/a2ui/index.js +16 -0
- package/dist/core/a2ui/index.js.map +1 -0
- package/dist/core/a2ui/interpreter.d.ts +71 -0
- package/dist/core/a2ui/interpreter.d.ts.map +1 -0
- package/dist/core/a2ui/interpreter.js +341 -0
- package/dist/core/a2ui/interpreter.js.map +1 -0
- package/dist/core/a2ui/json-pointer.d.ts +48 -0
- package/dist/core/a2ui/json-pointer.d.ts.map +1 -0
- package/dist/core/a2ui/json-pointer.js +174 -0
- package/dist/core/a2ui/json-pointer.js.map +1 -0
- package/dist/core/a2ui/renderer-to-agent.d.ts +342 -0
- package/dist/core/a2ui/renderer-to-agent.d.ts.map +1 -0
- package/dist/core/a2ui/renderer-to-agent.js +111 -0
- package/dist/core/a2ui/renderer-to-agent.js.map +1 -0
- package/dist/core/a2ui/resolve.d.ts +28 -0
- package/dist/core/a2ui/resolve.d.ts.map +1 -0
- package/dist/core/a2ui/resolve.js +144 -0
- package/dist/core/a2ui/resolve.js.map +1 -0
- package/dist/core/a2ui/tree.d.ts +66 -0
- package/dist/core/a2ui/tree.d.ts.map +1 -0
- package/dist/core/a2ui/tree.js +74 -0
- package/dist/core/a2ui/tree.js.map +1 -0
- package/dist/core/ag-ui.d.ts +82 -0
- package/dist/core/ag-ui.d.ts.map +1 -0
- package/dist/core/ag-ui.js +85 -0
- package/dist/core/ag-ui.js.map +1 -0
- package/dist/core/capability.d.ts +81 -0
- package/dist/core/capability.d.ts.map +1 -0
- package/dist/core/capability.js +79 -0
- package/dist/core/capability.js.map +1 -0
- package/dist/core/dom/dom-page-driver.d.ts +36 -0
- package/dist/core/dom/dom-page-driver.d.ts.map +1 -0
- package/dist/core/dom/dom-page-driver.js +601 -0
- package/dist/core/dom/dom-page-driver.js.map +1 -0
- package/dist/core/dom/index.d.ts +17 -0
- package/dist/core/dom/index.d.ts.map +1 -0
- package/dist/core/dom/index.js +17 -0
- package/dist/core/dom/index.js.map +1 -0
- package/dist/core/dom/model-context.d.ts +69 -0
- package/dist/core/dom/model-context.d.ts.map +1 -0
- package/dist/core/dom/model-context.js +44 -0
- package/dist/core/dom/model-context.js.map +1 -0
- package/dist/core/element-handles.d.ts +120 -0
- package/dist/core/element-handles.d.ts.map +1 -0
- package/dist/core/element-handles.js +39 -0
- package/dist/core/element-handles.js.map +1 -0
- package/dist/core/gen-ui/encoder.d.ts +50 -0
- package/dist/core/gen-ui/encoder.d.ts.map +1 -0
- package/dist/core/gen-ui/encoder.js +97 -0
- package/dist/core/gen-ui/encoder.js.map +1 -0
- package/dist/core/gen-ui/events.d.ts +59 -0
- package/dist/core/gen-ui/events.d.ts.map +1 -0
- package/dist/core/gen-ui/events.js +15 -0
- package/dist/core/gen-ui/events.js.map +1 -0
- package/dist/core/gen-ui/index.d.ts +18 -0
- package/dist/core/gen-ui/index.d.ts.map +1 -0
- package/dist/core/gen-ui/index.js +17 -0
- package/dist/core/gen-ui/index.js.map +1 -0
- package/dist/core/guards.d.ts +96 -0
- package/dist/core/guards.d.ts.map +1 -0
- package/dist/core/guards.js +186 -0
- package/dist/core/guards.js.map +1 -0
- package/dist/core/handle.d.ts +41 -0
- package/dist/core/handle.d.ts.map +1 -0
- package/dist/core/handle.js +41 -0
- package/dist/core/handle.js.map +1 -0
- package/dist/core/index.d.ts +75 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +74 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/list-handles.d.ts +43 -0
- package/dist/core/list-handles.d.ts.map +1 -0
- package/dist/core/list-handles.js +57 -0
- package/dist/core/list-handles.js.map +1 -0
- package/dist/core/mcp-ui-apps.d.ts +223 -0
- package/dist/core/mcp-ui-apps.d.ts.map +1 -0
- package/dist/core/mcp-ui-apps.js +252 -0
- package/dist/core/mcp-ui-apps.js.map +1 -0
- package/dist/core/page-capabilities.d.ts +14 -0
- package/dist/core/page-capabilities.d.ts.map +1 -0
- package/dist/core/page-capabilities.js +129 -0
- package/dist/core/page-capabilities.js.map +1 -0
- package/dist/core/page-driver.d.ts +120 -0
- package/dist/core/page-driver.d.ts.map +1 -0
- package/dist/core/page-driver.js +2 -0
- package/dist/core/page-driver.js.map +1 -0
- package/dist/core/page-executor.d.ts +94 -0
- package/dist/core/page-executor.d.ts.map +1 -0
- package/dist/core/page-executor.js +320 -0
- package/dist/core/page-executor.js.map +1 -0
- package/dist/core/webmcp.d.ts +202 -0
- package/dist/core/webmcp.d.ts.map +1 -0
- package/dist/core/webmcp.js +173 -0
- package/dist/core/webmcp.js.map +1 -0
- package/dist/dom/dom-page-driver.d.ts +9 -2
- package/dist/dom/dom-page-driver.d.ts.map +1 -1
- package/dist/dom/dom-page-driver.js +84 -40
- package/dist/dom/dom-page-driver.js.map +1 -1
- package/dist/dom/index.d.ts +1 -1
- package/dist/dom/index.d.ts.map +1 -1
- package/dist/dom/index.js +1 -1
- package/dist/dom/index.js.map +1 -1
- package/dist/element-handles.d.ts +22 -1
- package/dist/element-handles.d.ts.map +1 -1
- package/dist/gen-ui/encoder.d.ts +8 -8
- package/dist/gen-ui/encoder.d.ts.map +1 -1
- package/dist/gen-ui/encoder.js +2 -2
- package/dist/gen-ui/encoder.js.map +1 -1
- package/dist/gen-ui/events.d.ts +10 -10
- package/dist/gen-ui/events.d.ts.map +1 -1
- package/dist/gen-ui/index.d.ts +3 -3
- package/dist/gen-ui/index.d.ts.map +1 -1
- package/dist/gen-ui/index.js +2 -2
- package/dist/gen-ui/index.js.map +1 -1
- package/dist/guards.d.ts +8 -3
- package/dist/guards.d.ts.map +1 -1
- package/dist/guards.js +6 -1
- package/dist/guards.js.map +1 -1
- package/dist/index.d.ts +4 -62
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -61
- package/dist/index.js.map +1 -1
- package/dist/mcp-ui-apps.d.ts +19 -0
- package/dist/mcp-ui-apps.d.ts.map +1 -1
- package/dist/mcp-ui-apps.js +50 -5
- package/dist/mcp-ui-apps.js.map +1 -1
- package/dist/page-capabilities.js +6 -6
- package/dist/page-capabilities.js.map +1 -1
- package/dist/page-driver.d.ts +15 -2
- package/dist/page-driver.d.ts.map +1 -1
- package/dist/page-executor.d.ts +11 -4
- package/dist/page-executor.d.ts.map +1 -1
- package/dist/page-executor.js +47 -15
- package/dist/page-executor.js.map +1 -1
- package/package.json +18 -9
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module interpreter
|
|
3
|
+
*
|
|
4
|
+
* The minimal A2UI client-side interpreter: client state (a component map + a JSON-Pointer-
|
|
5
|
+
* addressed data model, per surface) that processes agent→renderer messages
|
|
6
|
+
* (`createSurface -> updateComponents -> updateDataModel -> ...`) and produces renderer→agent
|
|
7
|
+
* messages (`action`/`functionResponse`/`error`) in return. This is the piece GenUI/AG-UI
|
|
8
|
+
* (`packages/agentic/src/gen-ui/`, this repo's existing, much smaller GenUI surface-request shim)
|
|
9
|
+
* has no equivalent of — AG-UI streams
|
|
10
|
+
* opaque `ui.surface_requested`/`ui.surface_responded` events with no component tree, no catalog,
|
|
11
|
+
* no data binding; A2UI's interpreter has to actually hold and mutate structured state.
|
|
12
|
+
*
|
|
13
|
+
* **Design decisions made where the spec text (fetched from
|
|
14
|
+
* https://github.com/a2ui-project/a2ui, `main` branch, this session) is silent, documented here
|
|
15
|
+
* rather than left implicit:**
|
|
16
|
+
*
|
|
17
|
+
* 1. **Per-component, not per-message, validation granularity.** `updateComponents`'s own spec
|
|
18
|
+
* text says forward-referenced children/bindings should be handled gracefully — the spirit of
|
|
19
|
+
* that is "don't be brittle about partial/out-of-order information." This interpreter extends
|
|
20
|
+
* that spirit to catalog violations: one bad component in a 5-component `updateComponents`
|
|
21
|
+
* message produces one `VALIDATION_FAILED` error for that component and is skipped, while the
|
|
22
|
+
* other 4 valid components are still applied. The alternative (reject the whole message
|
|
23
|
+
* atomically) was considered and rejected as more brittle than the spec's own examples call for,
|
|
24
|
+
* not as spec-mandated either way.
|
|
25
|
+
* 2. **`callFunction`/`actionResponse` are not surface-scoped on the wire** (verified directly
|
|
26
|
+
* against the fetched JSON Schemas — neither message type has a `surfaceId` field). Functions
|
|
27
|
+
* are catalog-global (one active catalog per interpreter instance); `actionResponse` is
|
|
28
|
+
* correlated by `actionId` searched across every open surface's own pending-action table.
|
|
29
|
+
* 3. **`callFunction`'s `args` may contain `DataBinding` paths** (`FunctionCall.args` is typed
|
|
30
|
+
* against `DynamicValue` in `common_types.json`, which includes `DataBinding`) **but
|
|
31
|
+
* `callFunction` has no data model to bind against** (see point 2) — a real spec ambiguity, not
|
|
32
|
+
* an oversight in this port. Resolved pragmatically: such args resolve against an empty/absent
|
|
33
|
+
* data model, so any `DataBinding`-typed arg simply fails to resolve (`PATH_NOT_FOUND`,
|
|
34
|
+
* degrading sanely per `resolve.ts`'s contract) rather than crashing or guessing which surface's
|
|
35
|
+
* data model was "meant."
|
|
36
|
+
* 4. **An envelope malformed enough to have no attributable `surfaceId`/`functionCallId` at all**
|
|
37
|
+
* (missing `version`, no/ambiguous message-type key) cannot be turned into a spec-shaped
|
|
38
|
+
* `error` message — `renderer_to_agent.json`'s own generic-error schema *requires* one of those
|
|
39
|
+
* two identifiers. Rather than fabricate one, `applyAgentMessage` surfaces this case out-of-band
|
|
40
|
+
* via `unattributedViolation` (a string, not sent over the wire) instead of forcing a fake
|
|
41
|
+
* identifier into a wire-conformant shape.
|
|
42
|
+
*/
|
|
43
|
+
import { AGENT_TO_RENDERER_MESSAGE_KEYS, parseAgentToRendererMessage } from './agent-to-renderer.js';
|
|
44
|
+
import { WireComponentSchema } from './agent-to-renderer.js';
|
|
45
|
+
import { buildActionMessage, buildFunctionResponseMessage, buildGenericErrorMessage, buildValidationFailedMessage, } from './renderer-to-agent.js';
|
|
46
|
+
import { setAtPointer } from './json-pointer.js';
|
|
47
|
+
import { isComponentAllowed } from './catalog.js';
|
|
48
|
+
import { resolveDynamicValue } from './resolve.js';
|
|
49
|
+
import { isLocalFunctionAction, } from './common-types.js';
|
|
50
|
+
let actionIdCounter = 0;
|
|
51
|
+
function nextActionId() {
|
|
52
|
+
actionIdCounter += 1;
|
|
53
|
+
return `a2ui-action-${actionIdCounter}-${Date.now().toString(36)}`;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Best-effort `surfaceId` extraction from a raw envelope's message-type-keyed body, without
|
|
57
|
+
* assuming the envelope is well-formed. Used only to attribute a parse failure to a surface when
|
|
58
|
+
* possible (see `buildParseFailureResult`); never trusted for anything else.
|
|
59
|
+
*/
|
|
60
|
+
function bestEffortSurfaceId(raw, key) {
|
|
61
|
+
if (typeof raw !== 'object' || raw === null)
|
|
62
|
+
return undefined;
|
|
63
|
+
const body = raw[key];
|
|
64
|
+
if (typeof body !== 'object' || body === null)
|
|
65
|
+
return undefined;
|
|
66
|
+
const surfaceId = body.surfaceId;
|
|
67
|
+
return typeof surfaceId === 'string' ? surfaceId : undefined;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Turns a `ParseFailure` (from `parseAgentToRendererMessage`) into what `applyAgentMessage`
|
|
71
|
+
* returns for it. See this module's doc, decision 4: an envelope malformed enough to carry no
|
|
72
|
+
* attributable `surfaceId`/`functionCallId` cannot be turned into a spec-shaped `error` message —
|
|
73
|
+
* `renderer_to_agent.json`'s own generic-error schema *requires* one of those two identifiers —
|
|
74
|
+
* so it surfaces out-of-band via `unattributedViolation` (a string, not sent over the wire)
|
|
75
|
+
* instead of forcing a fake identifier into a wire-conformant shape.
|
|
76
|
+
*
|
|
77
|
+
* Exported and pure — it only reads `parsed`/`raw`, so the surfaceId-attribution rule can be
|
|
78
|
+
* tested directly, without a live interpreter instance.
|
|
79
|
+
*/
|
|
80
|
+
export function buildParseFailureResult(parsed, raw) {
|
|
81
|
+
if (parsed.code === 'MISSING_VERSION'
|
|
82
|
+
|| parsed.code === 'UNSUPPORTED_VERSION'
|
|
83
|
+
|| parsed.code === 'NO_MESSAGE_KEY'
|
|
84
|
+
|| parsed.code === 'AMBIGUOUS_MESSAGE') {
|
|
85
|
+
return { rendererMessages: [], unattributedViolation: parsed.message };
|
|
86
|
+
}
|
|
87
|
+
// VALIDATION_FAILED from the dispatcher: either `raw` wasn't even an object (`bestEffortSurfaceId`
|
|
88
|
+
// safely returns `undefined` for that, same as every other shape it doesn't recognize — no
|
|
89
|
+
// separate guard needed here), or exactly one of the six known message-type keys was present
|
|
90
|
+
// and its body failed schema validation. Checked against the *known* keys specifically
|
|
91
|
+
// (`AGENT_TO_RENDERER_MESSAGE_KEYS`), not "whatever the first non-version object key happens to
|
|
92
|
+
// be" — an envelope could carry unrelated extra top-level junk ahead of the real message key in
|
|
93
|
+
// insertion order, and grabbing that first would attribute the error to the wrong place. Best-
|
|
94
|
+
// effort surfaceId extraction so this can still be a spec-shaped error where possible
|
|
95
|
+
// (createSurface/updateComponents/updateDataModel/deleteSurface all carry surfaceId at the top
|
|
96
|
+
// of their body even when some other field is what actually failed validation); callFunction/
|
|
97
|
+
// actionResponse have no surfaceId at all, so those fall back to the out-of-band channel too.
|
|
98
|
+
const surfaceId = AGENT_TO_RENDERER_MESSAGE_KEYS.map((key) => bestEffortSurfaceId(raw, key)).find((id) => id !== undefined);
|
|
99
|
+
if (surfaceId) {
|
|
100
|
+
// `parsed.path` is guaranteed set here: `ParseFailure.path` is only ever omitted for the
|
|
101
|
+
// "raw input wasn't even an object" case (`agent-to-renderer.ts`'s very first guard), and
|
|
102
|
+
// `surfaceId` above could only have resolved to a truthy value if `raw` *was* an object
|
|
103
|
+
// (`bestEffortSurfaceId` requires that) — so this specific combination (object-shaped raw,
|
|
104
|
+
// yet no `path`) cannot occur. Asserted, not defensively branched, per this package's
|
|
105
|
+
// testing discipline (see the zod-issues-array comments elsewhere in this file).
|
|
106
|
+
return { rendererMessages: [buildValidationFailedMessage(surfaceId, parsed.path, parsed.message)] };
|
|
107
|
+
}
|
|
108
|
+
return { rendererMessages: [], unattributedViolation: parsed.message };
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Runs a component's local `functionCall` action synchronously against `dataModel` — no network
|
|
112
|
+
* round trip, no pending-action bookkeeping (that only applies to the agent-event branch; see
|
|
113
|
+
* `interpreter`'s `buildAction`/`buildAgentEventAction`).
|
|
114
|
+
*
|
|
115
|
+
* Exported and pure given its inputs, so "a local action resolves against the surface's actual
|
|
116
|
+
* data model, and a resolution failure becomes a typed refusal rather than a thrown error" can be
|
|
117
|
+
* tested without a live interpreter instance.
|
|
118
|
+
*/
|
|
119
|
+
export function runLocalFunctionAction(dataModel, catalog, action) {
|
|
120
|
+
const result = resolveDynamicValue(action.functionCall, { dataModel, catalog, side: 'renderer' });
|
|
121
|
+
return result.ok ? { ok: true, kind: 'local', result: result.value } : { ok: false, reason: result.detail };
|
|
122
|
+
}
|
|
123
|
+
export function createA2uiInterpreter(catalog) {
|
|
124
|
+
const surfaces = new Map();
|
|
125
|
+
const listeners = new Set();
|
|
126
|
+
function notify() {
|
|
127
|
+
for (const listener of listeners)
|
|
128
|
+
listener();
|
|
129
|
+
}
|
|
130
|
+
function applyComponentsList(surface, wireComponents) {
|
|
131
|
+
const errors = [];
|
|
132
|
+
wireComponents.forEach((wireComponent, index) => {
|
|
133
|
+
const { id, component: type, ...rest } = wireComponent;
|
|
134
|
+
if (!isComponentAllowed(catalog, type)) {
|
|
135
|
+
errors.push(buildValidationFailedMessage(surface.surfaceId, `/components/${index}/component`, `Component type "${type}" is not in catalog "${catalog.catalogId}" — refused, not rendered.`));
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
const spec = catalog.components.get(type);
|
|
139
|
+
const parsed = spec.propsSchema.safeParse(rest);
|
|
140
|
+
if (!parsed.success) {
|
|
141
|
+
// zod guarantees a non-empty `issues` array on failure — see agent-to-renderer.ts's
|
|
142
|
+
// parseAgentToRendererMessage for the same asserted (not defensively branched) invariant.
|
|
143
|
+
const issue = parsed.error.issues[0];
|
|
144
|
+
// `issue.message` alone ("Required") names no field — Zod puts the field on `issue.path`
|
|
145
|
+
// instead, so it has to be spliced back in here or the only place a human sees this (this
|
|
146
|
+
// string, not the sibling `path` pointer on the built message) never says which prop.
|
|
147
|
+
const field = issue.path.length > 0 ? issue.path.join('.') : '(root)';
|
|
148
|
+
errors.push(buildValidationFailedMessage(surface.surfaceId, `/components/${index}/${issue.path.join('/')}`, `Component "${id}" (${type}) failed catalog validation: ${field}: ${issue.message}`));
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
surface.components.set(id, { id, component: type, props: parsed.data });
|
|
152
|
+
});
|
|
153
|
+
return errors;
|
|
154
|
+
}
|
|
155
|
+
function handleCreateSurface(message) {
|
|
156
|
+
const { surfaceId, catalogId, components, dataModel } = message.createSurface;
|
|
157
|
+
if (catalogId !== catalog.catalogId) {
|
|
158
|
+
return [buildValidationFailedMessage(surfaceId, '/createSurface/catalogId', `Unknown catalogId "${catalogId}" — this renderer only has "${catalog.catalogId}" loaded.`)];
|
|
159
|
+
}
|
|
160
|
+
if (surfaces.has(surfaceId)) {
|
|
161
|
+
return [buildValidationFailedMessage(surfaceId, '/createSurface/surfaceId', `Surface "${surfaceId}" already exists — delete it before recreating (per spec).`)];
|
|
162
|
+
}
|
|
163
|
+
const surface = {
|
|
164
|
+
surfaceId,
|
|
165
|
+
catalogId,
|
|
166
|
+
components: new Map(),
|
|
167
|
+
dataModel: dataModel ?? {},
|
|
168
|
+
sendDataModel: message.createSurface.sendDataModel ?? false,
|
|
169
|
+
pendingActions: new Map(),
|
|
170
|
+
};
|
|
171
|
+
surfaces.set(surfaceId, surface);
|
|
172
|
+
return components ? applyComponentsList(surface, components) : [];
|
|
173
|
+
}
|
|
174
|
+
function handleUpdateComponents(message) {
|
|
175
|
+
const { surfaceId, components } = message.updateComponents;
|
|
176
|
+
const surface = surfaces.get(surfaceId);
|
|
177
|
+
if (!surface) {
|
|
178
|
+
return [buildValidationFailedMessage(surfaceId, '/updateComponents/surfaceId', `Unknown surfaceId "${surfaceId}" — createSurface must be sent first.`)];
|
|
179
|
+
}
|
|
180
|
+
return applyComponentsList(surface, components);
|
|
181
|
+
}
|
|
182
|
+
function handleUpdateDataModel(message) {
|
|
183
|
+
const { surfaceId, path, value } = message.updateDataModel;
|
|
184
|
+
const surface = surfaces.get(surfaceId);
|
|
185
|
+
if (!surface) {
|
|
186
|
+
return [buildValidationFailedMessage(surfaceId, '/updateDataModel/surfaceId', `Unknown surfaceId "${surfaceId}" — createSurface must be sent first.`)];
|
|
187
|
+
}
|
|
188
|
+
surface.dataModel = setAtPointer(surface.dataModel, path ?? '/', value);
|
|
189
|
+
return [];
|
|
190
|
+
}
|
|
191
|
+
function handleDeleteSurface(message) {
|
|
192
|
+
const { surfaceId } = message.deleteSurface;
|
|
193
|
+
if (!surfaces.has(surfaceId)) {
|
|
194
|
+
return [buildValidationFailedMessage(surfaceId, '/deleteSurface/surfaceId', `Unknown surfaceId "${surfaceId}" — nothing to delete.`)];
|
|
195
|
+
}
|
|
196
|
+
// Dropping the whole SurfaceState also drops its pendingActions map — any actionResponse that
|
|
197
|
+
// arrives afterward for an actionId that lived here simply won't be found (handled gracefully
|
|
198
|
+
// in handleActionResponse below), which is exactly the "deleteSurface mid-flight" adversarial
|
|
199
|
+
// case this is designed to answer.
|
|
200
|
+
surfaces.delete(surfaceId);
|
|
201
|
+
return [];
|
|
202
|
+
}
|
|
203
|
+
function handleCallFunction(message) {
|
|
204
|
+
const { functionCallId, callFunction, wantResponse } = message;
|
|
205
|
+
const result = resolveDynamicValue(callFunction, { dataModel: undefined, catalog, side: 'agent' });
|
|
206
|
+
if (!result.ok) {
|
|
207
|
+
const code = result.reason === 'FUNCTION_NOT_CALLABLE_FROM_SIDE' || result.reason === 'FUNCTION_NOT_REGISTERED' ? 'INVALID_FUNCTION_CALL' : result.reason;
|
|
208
|
+
return [buildGenericErrorMessage(code, result.detail, { functionCallId })];
|
|
209
|
+
}
|
|
210
|
+
if (!wantResponse)
|
|
211
|
+
return [];
|
|
212
|
+
// `?? null` because `functionResponse.value` is required on the wire and JSON has no
|
|
213
|
+
// `undefined`: a `returnType: 'void'` function (the catalog has three) resolves to
|
|
214
|
+
// `undefined`, and passing that straight through built a message whose `value` vanished on
|
|
215
|
+
// serialization — one this package's own `parseRendererToAgentMessage` correctly refuses.
|
|
216
|
+
return [buildFunctionResponseMessage({ functionCallId, call: callFunction.call, value: result.value ?? null })];
|
|
217
|
+
}
|
|
218
|
+
function handleActionResponse(message) {
|
|
219
|
+
const { actionId, actionResponse } = message;
|
|
220
|
+
for (const surface of surfaces.values()) {
|
|
221
|
+
const pending = surface.pendingActions.get(actionId);
|
|
222
|
+
if (!pending)
|
|
223
|
+
continue;
|
|
224
|
+
surface.pendingActions.delete(actionId);
|
|
225
|
+
if ('value' in actionResponse && pending.responsePath) {
|
|
226
|
+
surface.dataModel = setAtPointer(surface.dataModel, pending.responsePath, actionResponse.value);
|
|
227
|
+
}
|
|
228
|
+
return [];
|
|
229
|
+
}
|
|
230
|
+
// No surface has a pending action under this id — already resolved, never existed, or its
|
|
231
|
+
// surface was deleted while the action was in flight. Graceful no-op, not an error: the agent
|
|
232
|
+
// sent a well-formed message, it just arrived too late (or was mistaken) to mean anything now.
|
|
233
|
+
return [];
|
|
234
|
+
}
|
|
235
|
+
/** Routes one successfully-parsed envelope to its message-type handler. */
|
|
236
|
+
function dispatchAgentMessage(message) {
|
|
237
|
+
if ('createSurface' in message)
|
|
238
|
+
return handleCreateSurface(message);
|
|
239
|
+
if ('updateComponents' in message)
|
|
240
|
+
return handleUpdateComponents(message);
|
|
241
|
+
if ('updateDataModel' in message)
|
|
242
|
+
return handleUpdateDataModel(message);
|
|
243
|
+
if ('deleteSurface' in message)
|
|
244
|
+
return handleDeleteSurface(message);
|
|
245
|
+
if ('callFunction' in message)
|
|
246
|
+
return handleCallFunction(message);
|
|
247
|
+
return handleActionResponse(message);
|
|
248
|
+
}
|
|
249
|
+
function applyAgentMessage(raw) {
|
|
250
|
+
const parsed = parseAgentToRendererMessage(raw);
|
|
251
|
+
if (!parsed.ok)
|
|
252
|
+
return buildParseFailureResult(parsed, raw);
|
|
253
|
+
const rendererMessages = dispatchAgentMessage(parsed.message);
|
|
254
|
+
notify();
|
|
255
|
+
return { rendererMessages };
|
|
256
|
+
}
|
|
257
|
+
function getSurface(surfaceId) {
|
|
258
|
+
const surface = surfaces.get(surfaceId);
|
|
259
|
+
if (!surface)
|
|
260
|
+
return undefined;
|
|
261
|
+
return { surfaceId: surface.surfaceId, catalogId: surface.catalogId, components: surface.components, dataModel: surface.dataModel };
|
|
262
|
+
}
|
|
263
|
+
function getRoot(surfaceId) {
|
|
264
|
+
return surfaces.get(surfaceId)?.components.get('root');
|
|
265
|
+
}
|
|
266
|
+
function resolve(surfaceId, value, itemBasePath, itemIndex) {
|
|
267
|
+
const surface = surfaces.get(surfaceId);
|
|
268
|
+
const itemScope = itemBasePath !== undefined && itemIndex !== undefined ? { basePath: itemBasePath, index: itemIndex } : undefined;
|
|
269
|
+
return resolveDynamicValue(value, { dataModel: surface?.dataModel, catalog, side: 'renderer', ...(itemScope ? { itemScope } : {}) });
|
|
270
|
+
}
|
|
271
|
+
function resolveActionContext(context, surfaceId) {
|
|
272
|
+
const resolved = {};
|
|
273
|
+
for (const [key, value] of Object.entries(context ?? {})) {
|
|
274
|
+
const result = resolve(surfaceId, value);
|
|
275
|
+
resolved[key] = result.ok ? result.value : null;
|
|
276
|
+
}
|
|
277
|
+
return resolved;
|
|
278
|
+
}
|
|
279
|
+
/** Looks up the surface, component, and `action` prop `buildAction` needs, or the specific reason it can't. */
|
|
280
|
+
function resolveActionTarget(surfaceId, componentId) {
|
|
281
|
+
const surface = surfaces.get(surfaceId);
|
|
282
|
+
if (!surface)
|
|
283
|
+
return { ok: false, reason: `unknown surfaceId "${surfaceId}"` };
|
|
284
|
+
const component = surface.components.get(componentId);
|
|
285
|
+
if (!component)
|
|
286
|
+
return { ok: false, reason: `unknown componentId "${componentId}" on surface "${surfaceId}"` };
|
|
287
|
+
const action = component.props.action;
|
|
288
|
+
if (!action)
|
|
289
|
+
return { ok: false, reason: `component "${componentId}" has no action` };
|
|
290
|
+
return { ok: true, surface, action };
|
|
291
|
+
}
|
|
292
|
+
/** Builds the `action` wire envelope for an agent-event action, registering a pending response if `wantResponse` was set. */
|
|
293
|
+
function buildAgentEventAction(surface, surfaceId, componentId, event, now) {
|
|
294
|
+
const { name, context, wantResponse, responsePath } = event;
|
|
295
|
+
const actionId = wantResponse ? nextActionId() : undefined;
|
|
296
|
+
if (actionId) {
|
|
297
|
+
surface.pendingActions.set(actionId, { name, sourceComponentId: componentId, responsePath });
|
|
298
|
+
}
|
|
299
|
+
const payload = {
|
|
300
|
+
name,
|
|
301
|
+
surfaceId,
|
|
302
|
+
sourceComponentId: componentId,
|
|
303
|
+
timestamp: new Date(now()).toISOString(),
|
|
304
|
+
context: resolveActionContext(context, surfaceId),
|
|
305
|
+
...(wantResponse !== undefined ? { wantResponse } : {}),
|
|
306
|
+
...(actionId !== undefined ? { actionId } : {}),
|
|
307
|
+
};
|
|
308
|
+
return { ok: true, kind: 'agent', message: buildActionMessage(payload) };
|
|
309
|
+
}
|
|
310
|
+
function buildAction(surfaceId, componentId, now = Date.now) {
|
|
311
|
+
const target = resolveActionTarget(surfaceId, componentId);
|
|
312
|
+
if (!target.ok)
|
|
313
|
+
return target;
|
|
314
|
+
const { surface, action } = target;
|
|
315
|
+
if (isLocalFunctionAction(action)) {
|
|
316
|
+
return runLocalFunctionAction(surface.dataModel, catalog, action);
|
|
317
|
+
}
|
|
318
|
+
// `ActionSchema` (validated when this component's props were ingested — see
|
|
319
|
+
// `applyComponentsList`) is a closed 2-branch union: `{event}` | `{functionCall}`. Having
|
|
320
|
+
// already eliminated the `functionCall` branch above, TypeScript itself narrows `action` to
|
|
321
|
+
// the `event` branch here — no runtime `isAgentEventAction` re-check is reachable to fail; a
|
|
322
|
+
// malformed third shape could never have made it into `component.props.action` in the first
|
|
323
|
+
// place. (Not defensively branched-and-left-untested, per this package's own testing
|
|
324
|
+
// discipline — see the zod-issues-array comments above for the same principle.)
|
|
325
|
+
return buildAgentEventAction(surface, surfaceId, componentId, action.event, now);
|
|
326
|
+
}
|
|
327
|
+
return {
|
|
328
|
+
applyAgentMessage,
|
|
329
|
+
getSurface,
|
|
330
|
+
listSurfaceIds: () => [...surfaces.keys()],
|
|
331
|
+
getRoot,
|
|
332
|
+
buildAction,
|
|
333
|
+
resolve,
|
|
334
|
+
subscribe: (listener) => {
|
|
335
|
+
listeners.add(listener);
|
|
336
|
+
return () => listeners.delete(listener);
|
|
337
|
+
},
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
export { WireComponentSchema };
|
|
341
|
+
//# sourceMappingURL=interpreter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interpreter.js","sourceRoot":"","sources":["../../../src/core/a2ui/interpreter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module json-pointer
|
|
3
|
+
*
|
|
4
|
+
* A minimal RFC 6901 (JSON Pointer) implementation for A2UI's data-model bindings
|
|
5
|
+
* (`common_types.json#/$defs/DataBinding`: `{"path": "/user/name"}`). Deliberately small — no
|
|
6
|
+
* external dependency pulled in for this; the operations A2UI actually needs (root-scope read,
|
|
7
|
+
* collection-scope relative read via string concatenation, write-with-null-deletes) are a thin
|
|
8
|
+
* slice of the full RFC.
|
|
9
|
+
*
|
|
10
|
+
* One documented, deliberate deviation from strict RFC 6901: `updateDataModel`'s own spec text
|
|
11
|
+
* (`agent_to_renderer.json`, `UpdateDataModelMessage.path`'s description, fetched verbatim) says
|
|
12
|
+
* "An optional path to a location within the data model (e.g., '/user/name'). If omitted, or set
|
|
13
|
+
* to '/', refers to the entire data model." Under strict RFC 6901, `""` (empty string) is the
|
|
14
|
+
* pointer to the whole document and `"/"` is the pointer to the property keyed by the empty
|
|
15
|
+
* string on the root object — two different things. A2UI's own spec text explicitly overloads
|
|
16
|
+
* `"/"` to mean "the whole document," not "the empty-string-keyed property." This module follows
|
|
17
|
+
* A2UI's own wording exactly (not raw RFC 6901) since that is what a conformant renderer must do;
|
|
18
|
+
* flagged here rather than silently treated as an oversight.
|
|
19
|
+
*/
|
|
20
|
+
export interface PointerGetResult {
|
|
21
|
+
readonly found: boolean;
|
|
22
|
+
readonly value: unknown;
|
|
23
|
+
}
|
|
24
|
+
/** Splits a non-root pointer into its unescaped reference tokens. `pointer` must start with `/`. */
|
|
25
|
+
export declare function parsePointerTokens(pointer: string): string[];
|
|
26
|
+
export declare function joinPointer(base: string, ...tokens: string[]): string;
|
|
27
|
+
/** Reads the value at `pointer` in `doc`. Never throws on a non-resolving path — `found: false` degrades sanely, matching this port's "a bad binding must not crash the renderer" adversarial requirement (see `resolve.ts`). */
|
|
28
|
+
export declare function getAtPointer(doc: unknown, pointer: string): PointerGetResult;
|
|
29
|
+
/**
|
|
30
|
+
* Writes `value` at `pointer` in `doc`, returning a **new** document (the original is never
|
|
31
|
+
* mutated — every intermediate object on the path is shallow-copied). Missing intermediate
|
|
32
|
+
* segments are created as plain objects (this port does not attempt array-vs-object inference for
|
|
33
|
+
* not-yet-existing intermediate segments — a documented simplification, not a spec requirement).
|
|
34
|
+
* `value === null` at a non-root pointer deletes the key/value at that location, per
|
|
35
|
+
* `updateDataModel`'s own spec text ("To delete the key/value at path, set value explicitly to
|
|
36
|
+
* null."). At the root pointer, `value === null` replaces the entire data model with `null` (there
|
|
37
|
+
* is no "key" to delete at the root; documented as this port's own consistent interpretation).
|
|
38
|
+
*
|
|
39
|
+
* Never throws on a malformed pointer (e.g. missing leading `/`) — degrades to a no-op (`doc`
|
|
40
|
+
* returned unchanged), matching `getAtPointer`'s "a bad binding must not crash the renderer"
|
|
41
|
+
* contract. `updateDataModel`'s `path` is agent-authored wire data; an uncaught throw here had no
|
|
42
|
+
* error boundary above it anywhere in `packages/chat-react` or its hosts to stop it from
|
|
43
|
+
* unmounting the whole chat React root (see `ExtEventErrorBoundary`, added as a systemic backstop
|
|
44
|
+
* for the same class of bug — this is the specific root cause it would otherwise have had to
|
|
45
|
+
* catch).
|
|
46
|
+
*/
|
|
47
|
+
export declare function setAtPointer(doc: unknown, pointer: string, value: unknown): unknown;
|
|
48
|
+
//# sourceMappingURL=json-pointer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json-pointer.d.ts","sourceRoot":"","sources":["../../../src/core/a2ui/json-pointer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACzB;AA4CD,oGAAoG;AACpG,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAM5D;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAGrE;AAED,iOAAiO;AACjO,wBAAgB,YAAY,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,gBAAgB,CA4B5E;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAkDnF"}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module json-pointer
|
|
3
|
+
*
|
|
4
|
+
* A minimal RFC 6901 (JSON Pointer) implementation for A2UI's data-model bindings
|
|
5
|
+
* (`common_types.json#/$defs/DataBinding`: `{"path": "/user/name"}`). Deliberately small — no
|
|
6
|
+
* external dependency pulled in for this; the operations A2UI actually needs (root-scope read,
|
|
7
|
+
* collection-scope relative read via string concatenation, write-with-null-deletes) are a thin
|
|
8
|
+
* slice of the full RFC.
|
|
9
|
+
*
|
|
10
|
+
* One documented, deliberate deviation from strict RFC 6901: `updateDataModel`'s own spec text
|
|
11
|
+
* (`agent_to_renderer.json`, `UpdateDataModelMessage.path`'s description, fetched verbatim) says
|
|
12
|
+
* "An optional path to a location within the data model (e.g., '/user/name'). If omitted, or set
|
|
13
|
+
* to '/', refers to the entire data model." Under strict RFC 6901, `""` (empty string) is the
|
|
14
|
+
* pointer to the whole document and `"/"` is the pointer to the property keyed by the empty
|
|
15
|
+
* string on the root object — two different things. A2UI's own spec text explicitly overloads
|
|
16
|
+
* `"/"` to mean "the whole document," not "the empty-string-keyed property." This module follows
|
|
17
|
+
* A2UI's own wording exactly (not raw RFC 6901) since that is what a conformant renderer must do;
|
|
18
|
+
* flagged here rather than silently treated as an oversight.
|
|
19
|
+
*/
|
|
20
|
+
/**
|
|
21
|
+
* Whether `record` itself carries `token` — never whether it *inherits* it.
|
|
22
|
+
*
|
|
23
|
+
* A JSON Pointer addresses a member of a JSON document, and a JSON document has no inherited
|
|
24
|
+
* members. The `token in record` form this replaced answered `true` for everything
|
|
25
|
+
* `Object.prototype` contributes, so `getAtPointer({}, "/constructor")` resolved the `Object`
|
|
26
|
+
* constructor as though the agent's data model contained it.
|
|
27
|
+
*/
|
|
28
|
+
function hasOwnToken(record, token) {
|
|
29
|
+
return Object.prototype.hasOwnProperty.call(record, token);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Writes one own, plain data property — never through an inherited accessor.
|
|
33
|
+
*
|
|
34
|
+
* `record[token] = value` looks like it defines a key, and does for every token but one:
|
|
35
|
+
* `__proto__` is an inherited accessor on `Object.prototype`, so assigning to it *sets the
|
|
36
|
+
* object's prototype* instead. An agent sending `{"path": "/__proto__", "value": {...}}` therefore
|
|
37
|
+
* reshaped the object this function was building rather than putting a key in it. (Narrower than
|
|
38
|
+
* classic prototype pollution — the shallow-copy discipline here means only the one returned
|
|
39
|
+
* object was affected, never the global `Object.prototype` — but a pointer must address the
|
|
40
|
+
* document, so this defines the key RFC 6901 actually named.)
|
|
41
|
+
*/
|
|
42
|
+
function defineOwn(record, token, value) {
|
|
43
|
+
Object.defineProperty(record, token, { value, writable: true, enumerable: true, configurable: true });
|
|
44
|
+
}
|
|
45
|
+
/** `true` for the two spellings A2UI's own spec treats as "the whole document" (see module doc). Anything else is parsed as a normal RFC 6901 pointer. */
|
|
46
|
+
function isRootPointer(pointer) {
|
|
47
|
+
return pointer === '' || pointer === '/';
|
|
48
|
+
}
|
|
49
|
+
function unescapeToken(token) {
|
|
50
|
+
// RFC 6901 §4: ~1 must be decoded *before* ~0 is checked (a literal '~' that was itself part of
|
|
51
|
+
// an escaped '/' must not be re-decoded as '~0').
|
|
52
|
+
return token.replaceAll('~1', '/').replaceAll('~0', '~');
|
|
53
|
+
}
|
|
54
|
+
function escapeToken(token) {
|
|
55
|
+
return token.replaceAll('~', '~0').replaceAll('/', '~1');
|
|
56
|
+
}
|
|
57
|
+
/** Splits a non-root pointer into its unescaped reference tokens. `pointer` must start with `/`. */
|
|
58
|
+
export function parsePointerTokens(pointer) {
|
|
59
|
+
if (pointer === '')
|
|
60
|
+
return [];
|
|
61
|
+
if (!pointer.startsWith('/')) {
|
|
62
|
+
throw new Error(`invalid JSON Pointer (must start with "/"): ${JSON.stringify(pointer)}`);
|
|
63
|
+
}
|
|
64
|
+
return pointer.slice(1).split('/').map(unescapeToken);
|
|
65
|
+
}
|
|
66
|
+
export function joinPointer(base, ...tokens) {
|
|
67
|
+
const baseTokens = base === '' || base === '/' ? [] : parsePointerTokens(base);
|
|
68
|
+
return '/' + [...baseTokens, ...tokens].map(escapeToken).join('/');
|
|
69
|
+
}
|
|
70
|
+
/** Reads the value at `pointer` in `doc`. Never throws on a non-resolving path — `found: false` degrades sanely, matching this port's "a bad binding must not crash the renderer" adversarial requirement (see `resolve.ts`). */
|
|
71
|
+
export function getAtPointer(doc, pointer) {
|
|
72
|
+
if (isRootPointer(pointer))
|
|
73
|
+
return { found: true, value: doc };
|
|
74
|
+
let tokens;
|
|
75
|
+
try {
|
|
76
|
+
tokens = parsePointerTokens(pointer);
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
return { found: false, value: undefined };
|
|
80
|
+
}
|
|
81
|
+
let current = doc;
|
|
82
|
+
for (const token of tokens) {
|
|
83
|
+
if (Array.isArray(current)) {
|
|
84
|
+
if (!/^(0|[1-9]\d*)$/.test(token))
|
|
85
|
+
return { found: false, value: undefined };
|
|
86
|
+
const index = Number(token);
|
|
87
|
+
if (index >= current.length)
|
|
88
|
+
return { found: false, value: undefined };
|
|
89
|
+
current = current[index];
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
if (current !== null && typeof current === 'object') {
|
|
93
|
+
const record = current;
|
|
94
|
+
if (!hasOwnToken(record, token))
|
|
95
|
+
return { found: false, value: undefined };
|
|
96
|
+
current = record[token];
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
return { found: false, value: undefined };
|
|
100
|
+
}
|
|
101
|
+
return { found: true, value: current };
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Writes `value` at `pointer` in `doc`, returning a **new** document (the original is never
|
|
105
|
+
* mutated — every intermediate object on the path is shallow-copied). Missing intermediate
|
|
106
|
+
* segments are created as plain objects (this port does not attempt array-vs-object inference for
|
|
107
|
+
* not-yet-existing intermediate segments — a documented simplification, not a spec requirement).
|
|
108
|
+
* `value === null` at a non-root pointer deletes the key/value at that location, per
|
|
109
|
+
* `updateDataModel`'s own spec text ("To delete the key/value at path, set value explicitly to
|
|
110
|
+
* null."). At the root pointer, `value === null` replaces the entire data model with `null` (there
|
|
111
|
+
* is no "key" to delete at the root; documented as this port's own consistent interpretation).
|
|
112
|
+
*
|
|
113
|
+
* Never throws on a malformed pointer (e.g. missing leading `/`) — degrades to a no-op (`doc`
|
|
114
|
+
* returned unchanged), matching `getAtPointer`'s "a bad binding must not crash the renderer"
|
|
115
|
+
* contract. `updateDataModel`'s `path` is agent-authored wire data; an uncaught throw here had no
|
|
116
|
+
* error boundary above it anywhere in `packages/chat-react` or its hosts to stop it from
|
|
117
|
+
* unmounting the whole chat React root (see `ExtEventErrorBoundary`, added as a systemic backstop
|
|
118
|
+
* for the same class of bug — this is the specific root cause it would otherwise have had to
|
|
119
|
+
* catch).
|
|
120
|
+
*/
|
|
121
|
+
export function setAtPointer(doc, pointer, value) {
|
|
122
|
+
if (isRootPointer(pointer))
|
|
123
|
+
return value;
|
|
124
|
+
let tokens;
|
|
125
|
+
try {
|
|
126
|
+
tokens = parsePointerTokens(pointer);
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
return doc;
|
|
130
|
+
}
|
|
131
|
+
const parentTokens = tokens.slice(0, -1);
|
|
132
|
+
const lastToken = tokens[tokens.length - 1];
|
|
133
|
+
function recurse(current, remaining) {
|
|
134
|
+
if (remaining.length === 0) {
|
|
135
|
+
// `current` here is the parent container; apply the final write/delete.
|
|
136
|
+
if (Array.isArray(current)) {
|
|
137
|
+
if (!/^(0|[1-9]\d*)$/.test(lastToken))
|
|
138
|
+
return current;
|
|
139
|
+
const index = Number(lastToken);
|
|
140
|
+
const next = current.slice();
|
|
141
|
+
if (value === null) {
|
|
142
|
+
if (index < next.length)
|
|
143
|
+
next.splice(index, 1);
|
|
144
|
+
return next;
|
|
145
|
+
}
|
|
146
|
+
next[index] = value;
|
|
147
|
+
return next;
|
|
148
|
+
}
|
|
149
|
+
const record = current !== null && typeof current === 'object' ? { ...current } : {};
|
|
150
|
+
if (value === null) {
|
|
151
|
+
delete record[lastToken];
|
|
152
|
+
return record;
|
|
153
|
+
}
|
|
154
|
+
defineOwn(record, lastToken, value);
|
|
155
|
+
return record;
|
|
156
|
+
}
|
|
157
|
+
const [head, ...rest] = remaining;
|
|
158
|
+
if (Array.isArray(current)) {
|
|
159
|
+
if (!head || !/^(0|[1-9]\d*)$/.test(head))
|
|
160
|
+
return current;
|
|
161
|
+
const index = Number(head);
|
|
162
|
+
const next = current.slice();
|
|
163
|
+
next[index] = recurse(index < next.length ? next[index] : {}, rest);
|
|
164
|
+
return next;
|
|
165
|
+
}
|
|
166
|
+
const record = current !== null && typeof current === 'object' ? { ...current } : {};
|
|
167
|
+
if (!head)
|
|
168
|
+
return record;
|
|
169
|
+
defineOwn(record, head, recurse(hasOwnToken(record, head) ? record[head] : {}, rest));
|
|
170
|
+
return record;
|
|
171
|
+
}
|
|
172
|
+
return recurse(doc, parentTokens);
|
|
173
|
+
}
|
|
174
|
+
//# sourceMappingURL=json-pointer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json-pointer.js","sourceRoot":"","sources":["../../../src/core/a2ui/json-pointer.ts"],"names":[],"mappings":"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"}
|