@jini-ai/agentic 0.1.2 → 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 +16 -9
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module page-executor
|
|
3
|
+
*
|
|
4
|
+
* The six `page.*` verbs, as policy over a {@link PageDriver}.
|
|
5
|
+
*
|
|
6
|
+
* Every refusal happens here, before the driver is called: schema validation, handle validation,
|
|
7
|
+
* the field guard, the page allowlist, highlight clamping. A driver is mechanical and is trusted
|
|
8
|
+
* to be — which means a second driver (same-document, sandboxed frame, a future native host)
|
|
9
|
+
* inherits identical behavior for free rather than re-deriving it and getting one case wrong.
|
|
10
|
+
*
|
|
11
|
+
* Nothing here touches the DOM. That is what makes the interesting half testable without a
|
|
12
|
+
* browser: "does it refuse to type into a password box" is a unit test, not an integration test.
|
|
13
|
+
*/
|
|
14
|
+
import { findCapabilityInputError, } from './capability.js';
|
|
15
|
+
import { AGENT_ELEMENT_ROLES, isValidElementHandle, } from './element-handles.js';
|
|
16
|
+
import { describeFieldReadRefusal, describeFieldRefusal, findFieldFillRefusal, findFieldReadRefusal, normalizeAgentLabel, } from './guards.js';
|
|
17
|
+
import { PAGE_CAPABILITIES } from './page-capabilities.js';
|
|
18
|
+
/** Default marker lifetime, long enough to notice and short enough not to linger. */
|
|
19
|
+
export const DEFAULT_HIGHLIGHT_MS = 3_000;
|
|
20
|
+
/**
|
|
21
|
+
* Hard cap on a marker's lifetime. A caller asking for a very long highlight is really asking to
|
|
22
|
+
* leave a permanent mark on someone else's page, which is a change of appearance rather than a
|
|
23
|
+
* transient hint — and `page.highlight` is classified `read` precisely because it is transient.
|
|
24
|
+
*/
|
|
25
|
+
export const MAX_HIGHLIGHT_MS = 15_000;
|
|
26
|
+
/**
|
|
27
|
+
* How many elements `withState` will describe in one call.
|
|
28
|
+
*
|
|
29
|
+
* State is per-element work and per-element payload, so an unfiltered `withState` on a large page
|
|
30
|
+
* is both the slowest and the largest thing this surface can be asked for. The cap turns that into
|
|
31
|
+
* a bounded answer plus an explicit `stateTruncated`, rather than a caller discovering the limit
|
|
32
|
+
* as a timeout or a truncated blob. Narrowing with `role`/`query` is the intended way past it.
|
|
33
|
+
*/
|
|
34
|
+
export const MAX_STATEFUL_ELEMENTS = 50;
|
|
35
|
+
function requireHandle(input, key) {
|
|
36
|
+
const value = input[key];
|
|
37
|
+
if (typeof value !== 'string' || !isValidElementHandle(value)) {
|
|
38
|
+
throw new Error(`"${key}" must be a published element handle from page.find_elements — `
|
|
39
|
+
+ 'lowercase words joined by single hyphens, never a CSS selector');
|
|
40
|
+
}
|
|
41
|
+
return value;
|
|
42
|
+
}
|
|
43
|
+
function clampHighlightDuration(value) {
|
|
44
|
+
if (typeof value !== 'number' || !Number.isFinite(value) || value <= 0)
|
|
45
|
+
return DEFAULT_HIGHLIGHT_MS;
|
|
46
|
+
return Math.min(value, MAX_HIGHLIGHT_MS);
|
|
47
|
+
}
|
|
48
|
+
function isAgentElementRole(value) {
|
|
49
|
+
return typeof value === 'string' && AGENT_ELEMENT_ROLES.includes(value);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Turns a driver's raw reading into what a caller may see.
|
|
53
|
+
*
|
|
54
|
+
* The one decision here that is not formatting: whether a field's contents are reportable at all.
|
|
55
|
+
* That runs on the descriptor the driver supplied, in this layer, for the same reason the fill
|
|
56
|
+
* guard does — a secrecy rule re-derived by each driver is a secrecy rule that will eventually be
|
|
57
|
+
* derived wrong. A value arriving with no descriptor to check is withheld rather than trusted.
|
|
58
|
+
*/
|
|
59
|
+
export function projectElementState(raw) {
|
|
60
|
+
const text = normalizeAgentLabel(raw.text);
|
|
61
|
+
// Computed once, up front, so `checked` is gated by the exact same refusal as `value` below
|
|
62
|
+
// rather than being copied through unconditionally. A checkbox/radio's `checked` is a second
|
|
63
|
+
// secrecy channel, not a formatting detail: for a field like `health_disclosure_password`,
|
|
64
|
+
// *which* option is ticked is itself the secret, even though it is a boolean and `value` was
|
|
65
|
+
// already withheld. `text` is deliberately NOT gated here, on purpose, even for a refused
|
|
66
|
+
// field: for a checkbox/radio, `text` is the option's own visible label (e.g. "I am HIV
|
|
67
|
+
// positive") — page-authored content the page already renders openly to anyone who looks at
|
|
68
|
+
// it, exactly like a `<select>`'s `options` below. The secret is which option is checked, not
|
|
69
|
+
// what the option is called; withholding the label too would blind a caller to the page's own
|
|
70
|
+
// ontology for no reduction in what actually leaks.
|
|
71
|
+
const refusal = raw.field !== undefined ? findFieldReadRefusal(raw.field) : null;
|
|
72
|
+
// The one element whose `text` is NOT page-authored chrome: an editable region, whose contents
|
|
73
|
+
// are the user's data and whose driver has no `value` to report them as. It is gated by exactly
|
|
74
|
+
// the rules `value` is gated by below, including the "arrived with nothing to check it against"
|
|
75
|
+
// one — an unverifiable secret is withheld, not trusted.
|
|
76
|
+
const withheldText = raw.textIsValue !== true
|
|
77
|
+
? undefined
|
|
78
|
+
: raw.field === undefined
|
|
79
|
+
? 'this element reported contents without the attributes needed to check them for secrets'
|
|
80
|
+
: refusal !== null ? describeFieldReadRefusal(refusal) : undefined;
|
|
81
|
+
const base = {
|
|
82
|
+
text: withheldText === undefined ? text.text : '',
|
|
83
|
+
textTruncated: withheldText === undefined ? text.truncated : false,
|
|
84
|
+
...(withheldText !== undefined ? { textWithheld: withheldText } : {}),
|
|
85
|
+
...(raw.checked !== undefined && refusal === null ? { checked: raw.checked } : {}),
|
|
86
|
+
...(raw.disabled !== undefined ? { disabled: raw.disabled } : {}),
|
|
87
|
+
...(raw.visible !== undefined ? { visible: raw.visible } : {}),
|
|
88
|
+
// Bounded like every other page-authored string, but never withheld: the options a dropdown
|
|
89
|
+
// offers are part of the UI's shape, not the user's data.
|
|
90
|
+
...(raw.options !== undefined
|
|
91
|
+
? { options: raw.options.map((option) => normalizeAgentLabel(option).text) }
|
|
92
|
+
: {}),
|
|
93
|
+
};
|
|
94
|
+
if (raw.value === undefined)
|
|
95
|
+
return base;
|
|
96
|
+
if (raw.field === undefined) {
|
|
97
|
+
return {
|
|
98
|
+
...base,
|
|
99
|
+
valueWithheld: 'this element reported a value without the attributes needed to check it for secrets',
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
if (refusal !== null)
|
|
103
|
+
return { ...base, valueWithheld: describeFieldReadRefusal(refusal) };
|
|
104
|
+
const value = normalizeAgentLabel(raw.value);
|
|
105
|
+
return { ...base, value: value.text, valueTruncated: value.truncated };
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Whether two readings of the same element are indistinguishable to a caller.
|
|
109
|
+
*
|
|
110
|
+
* Compares only what the caller can actually see: a withheld value is compared as "withheld",
|
|
111
|
+
* so a secret that changed reads as unchanged. That is the honest answer — a change no caller may
|
|
112
|
+
* observe is not one this can report — and is why the field it feeds is named `targetChanged`.
|
|
113
|
+
*/
|
|
114
|
+
function sameElementState(a, b) {
|
|
115
|
+
return a.text === b.text
|
|
116
|
+
// Compared for the same reason `valueWithheld` is: without it, an editable region whose
|
|
117
|
+
// contents are withheld reads as `text: ''` before and after, and a write into it would
|
|
118
|
+
// report `targetChanged: false` — an answer that says "nothing happened" rather than the
|
|
119
|
+
// honest "no caller may observe whether it did".
|
|
120
|
+
&& a.textWithheld === b.textWithheld
|
|
121
|
+
&& a.value === b.value
|
|
122
|
+
&& a.valueWithheld === b.valueWithheld
|
|
123
|
+
&& a.checked === b.checked
|
|
124
|
+
&& a.disabled === b.disabled
|
|
125
|
+
&& a.visible === b.visible;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Reads one element's state, or `undefined` when there is nothing to read.
|
|
129
|
+
*
|
|
130
|
+
* Two different absences collapse here on purpose: a driver that cannot observe at all, and an
|
|
131
|
+
* element that no longer resolves. A caller distinguishes them from context — `before` present
|
|
132
|
+
* with `after` absent means the action removed its own target; both absent means the surface does
|
|
133
|
+
* not report state.
|
|
134
|
+
*/
|
|
135
|
+
async function observeElement(driver, handle) {
|
|
136
|
+
if (driver.describeState === undefined || !isValidElementHandle(handle))
|
|
137
|
+
return undefined;
|
|
138
|
+
const raw = await driver.describeState(handle);
|
|
139
|
+
return raw === null ? undefined : projectElementState(raw);
|
|
140
|
+
}
|
|
141
|
+
/** Runs a write between two readings of its target, waiting for the surface to settle in between. */
|
|
142
|
+
async function observeWrite(driver, handle, write) {
|
|
143
|
+
const before = await observeElement(driver, handle);
|
|
144
|
+
await write();
|
|
145
|
+
if (driver.settle !== undefined)
|
|
146
|
+
await driver.settle();
|
|
147
|
+
const after = await observeElement(driver, handle);
|
|
148
|
+
return {
|
|
149
|
+
...(before !== undefined ? { before } : {}),
|
|
150
|
+
...(after !== undefined ? { after } : {}),
|
|
151
|
+
...(before !== undefined && after !== undefined
|
|
152
|
+
? { targetChanged: !sameElementState(before, after) }
|
|
153
|
+
: {}),
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Reads the showing page from the elements themselves, which is where a driver reports it. A
|
|
158
|
+
* surface that publishes nothing has no page id to report, and says so rather than guessing.
|
|
159
|
+
*/
|
|
160
|
+
async function summarizePage(driver) {
|
|
161
|
+
const elements = await driver.findElements({});
|
|
162
|
+
return {
|
|
163
|
+
page: elements.find((element) => element.page !== undefined)?.page,
|
|
164
|
+
elementCount: elements.length,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Runs one `page.*` capability.
|
|
169
|
+
*
|
|
170
|
+
* @param driver - The host's page driver.
|
|
171
|
+
* @param capabilityId - A `page.*` id from {@link PAGE_CAPABILITIES}.
|
|
172
|
+
* @param input - Raw caller arguments, validated here against the declared schema.
|
|
173
|
+
* @returns The capability's result.
|
|
174
|
+
* @throws If the id is unknown, the input fails validation, a handle is malformed, the target is
|
|
175
|
+
* a field no automated caller may fill, or the page is not published. Refusals are errors on
|
|
176
|
+
* purpose: a caller must be told why, not handed a silent no-op it will retry forever.
|
|
177
|
+
*/
|
|
178
|
+
export async function executePageCapability(driver, capabilityId, input) {
|
|
179
|
+
const capability = PAGE_CAPABILITIES.find((entry) => entry.id === capabilityId);
|
|
180
|
+
if (capability === undefined)
|
|
181
|
+
throw new Error(`unknown page capability: ${capabilityId}`);
|
|
182
|
+
const inputError = findCapabilityInputError(capability, input);
|
|
183
|
+
if (inputError !== null) {
|
|
184
|
+
// The schema rides along with the refusal rather than making a caller spend a second
|
|
185
|
+
// round trip on describe_tool to learn what it already tried to guess — ai-control-plane.md
|
|
186
|
+
// §29.4's "schema-on-error" requirement, empirically forced by a real run: page.fill was
|
|
187
|
+
// called with `handle` instead of the argument's old name, `element`, twice before the caller
|
|
188
|
+
// gave up and looked the schema up separately. One JSON-Schema object, embedded once, turned
|
|
189
|
+
// that into a same-turn self-correction for every page.* verb this gate guards, not just the
|
|
190
|
+
// one that got measured — self-correction is why that mismatch was survivable at all, given
|
|
191
|
+
// every verb here needs a handle from `page.find_elements`, whose own response has always
|
|
192
|
+
// called this same value `handle` (`AgentElementDescriptor.handle`). The argument itself was
|
|
193
|
+
// later renamed from `element` to `handle` to match, closing the gap this comment describes
|
|
194
|
+
// rather than merely papering over it turn by turn.
|
|
195
|
+
throw new Error(`${capabilityId}: ${inputError}. Expected input: ${JSON.stringify(capability.inputSchema)}`);
|
|
196
|
+
}
|
|
197
|
+
switch (capabilityId) {
|
|
198
|
+
case 'page.find_elements': {
|
|
199
|
+
const role = input['role'];
|
|
200
|
+
// The schema's enum check has already run; this narrows the type for the driver.
|
|
201
|
+
const filter = {
|
|
202
|
+
...(isAgentElementRole(role) ? { role } : {}),
|
|
203
|
+
...(typeof input['query'] === 'string' ? { query: input['query'] } : {}),
|
|
204
|
+
};
|
|
205
|
+
const [found, rawPages] = await Promise.all([driver.findElements(filter), driver.listPages()]);
|
|
206
|
+
const withState = input['withState'] === true;
|
|
207
|
+
const observing = withState && driver.describeState !== undefined;
|
|
208
|
+
const elements = await Promise.all(found.map(async (element, index) => {
|
|
209
|
+
const label = normalizeAgentLabel(element.label);
|
|
210
|
+
const base = {
|
|
211
|
+
handle: element.handle,
|
|
212
|
+
role: element.role,
|
|
213
|
+
label: label.text,
|
|
214
|
+
labelTruncated: label.truncated,
|
|
215
|
+
page: element.page,
|
|
216
|
+
};
|
|
217
|
+
if (!observing || index >= MAX_STATEFUL_ELEMENTS)
|
|
218
|
+
return base;
|
|
219
|
+
const state = await observeElement(driver, element.handle);
|
|
220
|
+
return state === undefined ? base : { ...base, state };
|
|
221
|
+
}));
|
|
222
|
+
// `label` is page-authored the same way an element's is — bounded here for the same reason
|
|
223
|
+
// `page.navigate`'s refusal message bounds it below, rather than trusting a host to have kept
|
|
224
|
+
// every `data-agent-page` label short and clean.
|
|
225
|
+
const pages = rawPages.map((page) => ({
|
|
226
|
+
id: page.id,
|
|
227
|
+
label: normalizeAgentLabel(page.label).text,
|
|
228
|
+
}));
|
|
229
|
+
return {
|
|
230
|
+
elements,
|
|
231
|
+
pages,
|
|
232
|
+
untrustedFields: observing
|
|
233
|
+
? ['elements[].label', 'elements[].state.text', 'elements[].state.value', 'pages[].label']
|
|
234
|
+
: ['elements[].label', 'pages[].label'],
|
|
235
|
+
...(withState && !observing ? { stateUnavailable: true } : {}),
|
|
236
|
+
...(observing && found.length > MAX_STATEFUL_ELEMENTS ? { stateTruncated: true } : {}),
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
case 'page.highlight': {
|
|
240
|
+
const handle = requireHandle(input, 'handle');
|
|
241
|
+
const durationMs = clampHighlightDuration(input['durationMs']);
|
|
242
|
+
await driver.highlight(handle, durationMs);
|
|
243
|
+
return { highlighted: handle, durationMs };
|
|
244
|
+
}
|
|
245
|
+
case 'page.scroll_to': {
|
|
246
|
+
const handle = requireHandle(input, 'handle');
|
|
247
|
+
await driver.scrollTo(handle);
|
|
248
|
+
return { scrolledTo: handle };
|
|
249
|
+
}
|
|
250
|
+
case 'page.click': {
|
|
251
|
+
const handle = requireHandle(input, 'handle');
|
|
252
|
+
const observation = await observeWrite(driver, handle, () => driver.click(handle));
|
|
253
|
+
return { clicked: handle, ...observation };
|
|
254
|
+
}
|
|
255
|
+
case 'page.fill': {
|
|
256
|
+
const handle = requireHandle(input, 'handle');
|
|
257
|
+
// Declared required and typed `string` in the manifest, and `findCapabilityInputError`
|
|
258
|
+
// enforced both above — re-checking here would be an unreachable branch, not a safeguard.
|
|
259
|
+
const text = input['text'];
|
|
260
|
+
// Ask the page what this field actually is before writing to it. A handle proves the page
|
|
261
|
+
// published the element; it says nothing about whether it holds a password.
|
|
262
|
+
const field = await driver.describeField(handle);
|
|
263
|
+
if (field === null)
|
|
264
|
+
throw new Error(`"${handle}" is not a fillable field`);
|
|
265
|
+
const refusal = findFieldFillRefusal(field);
|
|
266
|
+
if (refusal !== null) {
|
|
267
|
+
throw new Error(`refusing to fill "${handle}": ${describeFieldRefusal(refusal)}`);
|
|
268
|
+
}
|
|
269
|
+
const observation = await observeWrite(driver, handle, () => driver.fill(handle, text));
|
|
270
|
+
return { filled: handle, ...observation };
|
|
271
|
+
}
|
|
272
|
+
case 'page.select_option': {
|
|
273
|
+
const handle = requireHandle(input, 'handle');
|
|
274
|
+
// Required and string-typed by the manifest, already enforced above. See page.fill.
|
|
275
|
+
const option = input['option'];
|
|
276
|
+
// Optional and boolean-typed by the manifest; absent means "select it", same as before this
|
|
277
|
+
// argument existed.
|
|
278
|
+
const selected = input['selected'] === false ? false : true;
|
|
279
|
+
// No field guard: a dropdown's options are authored by the page, so choosing one reveals
|
|
280
|
+
// nothing the page had not already published, and none of the credential field types this
|
|
281
|
+
// surface refuses can be a `<select>`.
|
|
282
|
+
const observation = await observeWrite(driver, handle, () => driver.selectOption(handle, option, selected));
|
|
283
|
+
// `optionSelected` names the boolean rather than reusing `selected`, which already means
|
|
284
|
+
// "the handle this call acted on" for every verb in this switch (`clicked`, `filled`, …).
|
|
285
|
+
return { selected: handle, option, optionSelected: selected, ...observation };
|
|
286
|
+
}
|
|
287
|
+
case 'page.navigate': {
|
|
288
|
+
// Required and string-typed by the manifest, already enforced above. See page.fill.
|
|
289
|
+
const page = input['page'];
|
|
290
|
+
const pages = await driver.listPages();
|
|
291
|
+
if (!pages.some((candidate) => candidate.id === page)) {
|
|
292
|
+
// Every other piece of page-authored (or, here, caller-authored-but-page-shaped) text
|
|
293
|
+
// this system hands to a model goes through normalizeAgentLabel first — bounded, control-
|
|
294
|
+
// and bidi-stripped. This refusal was the one path that skipped it: the raw `page`
|
|
295
|
+
// argument, and the `pages` this host actually publishes (itself read verbatim off
|
|
296
|
+
// `data-agent-page` attributes with no length bound), were interpolated straight into the
|
|
297
|
+
// thrown message. A 5000+-char bidi payload survived verbatim as a result. The lookup
|
|
298
|
+
// above still runs on the raw values — only the text that reaches the message is bounded.
|
|
299
|
+
//
|
|
300
|
+
// `id (label)`, not just the id: a refusal is the one moment a caller that guessed wrong
|
|
301
|
+
// is looking straight at the real menu, so it is worth spending the label here even though
|
|
302
|
+
// `page.find_elements` already carries the same information — a caller that jumped
|
|
303
|
+
// straight to `page.navigate` without calling that first still lands on the right id.
|
|
304
|
+
const safePage = normalizeAgentLabel(page).text;
|
|
305
|
+
const safePages = pages.map((candidate) => `${normalizeAgentLabel(candidate.id).text} (${normalizeAgentLabel(candidate.label).text})`);
|
|
306
|
+
throw new Error(`"${safePage}" is not a published page. Available: ${safePages.length > 0 ? safePages.join(', ') : '(none)'}`);
|
|
307
|
+
}
|
|
308
|
+
const before = await summarizePage(driver);
|
|
309
|
+
await driver.navigate(page);
|
|
310
|
+
if (driver.settle !== undefined)
|
|
311
|
+
await driver.settle();
|
|
312
|
+
const after = await summarizePage(driver);
|
|
313
|
+
return { navigatedTo: page, before, after };
|
|
314
|
+
}
|
|
315
|
+
/* c8 ignore next 2 -- unreachable: the id was matched against PAGE_CAPABILITIES above. */
|
|
316
|
+
default:
|
|
317
|
+
throw new Error(`unhandled page capability: ${capabilityId}`);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
//# sourceMappingURL=page-executor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"page-executor.js","sourceRoot":"","sources":["../../src/core/page-executor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module webmcp
|
|
3
|
+
*
|
|
4
|
+
* Projection: {@link CapabilityDef} → a WebMCP tool registration.
|
|
5
|
+
*
|
|
6
|
+
* WebMCP (`document.modelContext.registerTool`) is the browser API by which a *page* offers
|
|
7
|
+
* tools to an agent running inside the browser. It is a W3C Community Group draft, not a
|
|
8
|
+
* standards-track spec, and it moves: the API relocated from `navigator.modelContext` to
|
|
9
|
+
* `document.modelContext` on 2026-07-21, Chrome 150 deprecated the `navigator` location while
|
|
10
|
+
* still serving it during the origin trial (Chrome 149–156), Edge ships it behind a flag, and
|
|
11
|
+
* Firefox and Safari have made no commitment. Feature detection must therefore check `document`
|
|
12
|
+
* first and fall back to `navigator`.
|
|
13
|
+
*
|
|
14
|
+
* That detection is deliberately NOT here: it touches browser globals, and this package holds
|
|
15
|
+
* none. Framework bindings own host access; this file owns only the shape translation, so when
|
|
16
|
+
* the registration shape changes again there is exactly one place to change it.
|
|
17
|
+
*
|
|
18
|
+
* Re-verified 2026-07-28 against the primary spec source
|
|
19
|
+
* (https://webmachinelearning.github.io/webmcp/, `index.bs`). Four real gaps closed this pass,
|
|
20
|
+
* all additive — none change the confirmation gate below, which is Jini's own addition and has
|
|
21
|
+
* no spec counterpart:
|
|
22
|
+
*
|
|
23
|
+
* 1. **`signal`/`exposedTo`** — `ModelContextRegisterToolOptions`, the *second* positional
|
|
24
|
+
* argument to `registerTool(tool, options)`. `signal` is the spec's ONLY unregistration
|
|
25
|
+
* mechanism (there is no `unregisterTool()`); aborting it removes the tool and fires
|
|
26
|
+
* `toolchange`. `exposedTo` scopes which cross-origin documents in the same tree may see the
|
|
27
|
+
* tool. Neither belongs on the `ModelContextTool` dict itself, so they are not fields of
|
|
28
|
+
* {@link WebMcpToolRegistration} — they ride along on its optional `registerOptions`, computed
|
|
29
|
+
* from {@link ToWebMcpToolOptions}, so a caller has exactly one object to destructure:
|
|
30
|
+
* `modelContext.registerTool(reg, reg.registerOptions)`.
|
|
31
|
+
* 2. **`title`/`annotations`** — real `ModelContextTool` dict fields (`USVString title`,
|
|
32
|
+
* `ToolAnnotations annotations`), now on {@link WebMcpToolRegistration}. `annotations.readOnlyHint`
|
|
33
|
+
* defaults from {@link CapabilityDef.risk} (`'read'` → `true`) since Jini's manifests already
|
|
34
|
+
* carry that judgment; a caller may override or add `untrustedContentHint` via `options.annotations`.
|
|
35
|
+
* 3. **Tool name validation** — the spec's `registerTool` algorithm rejects (with an
|
|
36
|
+
* `InvalidStateError` `DOMException`) a name that is empty, over 128 code points, or contains
|
|
37
|
+
* anything outside ASCII alphanumeric plus `_`, `-`, `.`. `capability.id` becomes `name`
|
|
38
|
+
* verbatim, so a malformed manifest entry previously surfaced as a cryptic browser-side
|
|
39
|
+
* rejection days later; {@link toWebMcpTool} now checks it at projection time and names the
|
|
40
|
+
* offending capability.
|
|
41
|
+
* 4. **Schema-on-error** — WebMCP defines no input validation of its own (the spec's
|
|
42
|
+
* `ToolExecuteCallback` is just `Promise<any> (object input)`), and this module's own doc used
|
|
43
|
+
* to say so ("the caller is responsible for validating it... WebMCP does not"). That left a
|
|
44
|
+
* wrong-schema call to fail deep inside whatever `execute` does, with no way for the caller to
|
|
45
|
+
* self-correct in the same turn. `execute` now runs the manifest's own
|
|
46
|
+
* {@link findCapabilityInputError} first and, on failure, throws the same
|
|
47
|
+
* `"<id>: <reason>. Expected input: <schema>"` shape `page-executor.ts` already uses for
|
|
48
|
+
* `page.*` — one discipline, not two.
|
|
49
|
+
*/
|
|
50
|
+
import { type CapabilityDef, type CapabilityInputSchema } from './capability.js';
|
|
51
|
+
/** The registration object `registerTool` accepts. WebMCP names the schema field `inputSchema`. */
|
|
52
|
+
export interface WebMcpToolRegistration {
|
|
53
|
+
readonly name: string;
|
|
54
|
+
/**
|
|
55
|
+
* `ModelContextTool.title` — an optional human-readable label, distinct from `name` (the
|
|
56
|
+
* machine identifier) and `description` (what an agent reads to decide whether to call it). The
|
|
57
|
+
* spec recommends localizing it to the user's language; this projection makes no attempt at
|
|
58
|
+
* that; a caller wanting a localized title supplies it via `options.title`.
|
|
59
|
+
*/
|
|
60
|
+
readonly title?: string;
|
|
61
|
+
readonly description: string;
|
|
62
|
+
readonly inputSchema: CapabilityInputSchema;
|
|
63
|
+
readonly execute: (args: Record<string, unknown>) => Promise<unknown>;
|
|
64
|
+
/** `ModelContextTool.annotations` — behavior hints. See {@link WebMcpToolAnnotations}. */
|
|
65
|
+
readonly annotations?: WebMcpToolAnnotations;
|
|
66
|
+
/**
|
|
67
|
+
* The SECOND positional argument `registerTool(tool, options)` expects — the spec's
|
|
68
|
+
* `ModelContextRegisterToolOptions`, not part of the `ModelContextTool` dict this object
|
|
69
|
+
* otherwise models. Present only when `options.signal` or `options.exposedTo` was supplied.
|
|
70
|
+
* Bundled here rather than returned as a second value so `toWebMcpTool`'s output stays a single
|
|
71
|
+
* object a caller can pass straight through: `modelContext.registerTool(reg, reg.registerOptions)`.
|
|
72
|
+
*/
|
|
73
|
+
readonly registerOptions?: WebMcpRegisterToolOptions;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* `ToolAnnotations` — optional behavior hints a host UI or agent may use to decide how to treat a
|
|
77
|
+
* tool without calling it. Both default to `false` in the spec; this projection only ever sets
|
|
78
|
+
* `readOnlyHint` by default (from {@link CapabilityDef.risk}) and leaves `untrustedContentHint`
|
|
79
|
+
* unset unless a caller supplies one, since nothing in {@link CapabilityDef} implies it.
|
|
80
|
+
*/
|
|
81
|
+
export interface WebMcpToolAnnotations {
|
|
82
|
+
/** True when the tool never mutates state. Defaults from `capability.risk === 'read'`. */
|
|
83
|
+
readonly readOnlyHint?: boolean;
|
|
84
|
+
/** True when the tool's return value may contain content from outside the page's trust boundary. */
|
|
85
|
+
readonly untrustedContentHint?: boolean;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* `ModelContextRegisterToolOptions` — the second positional argument to the real
|
|
89
|
+
* `registerTool(tool, options)`, per the spec IDL:
|
|
90
|
+
* `dictionary ModelContextRegisterToolOptions { AbortSignal signal; sequence<USVString> exposedTo; }`.
|
|
91
|
+
*/
|
|
92
|
+
export interface WebMcpRegisterToolOptions {
|
|
93
|
+
/**
|
|
94
|
+
* Aborting this unregisters the tool and rejects the in-flight `registerTool()` promise with the
|
|
95
|
+
* signal's abort reason — the spec's ONLY unregistration mechanism. There is no `unregisterTool()`
|
|
96
|
+
* in the current draft; a host that wants to drop a tool later must have registered it with a
|
|
97
|
+
* signal in the first place.
|
|
98
|
+
*/
|
|
99
|
+
readonly signal?: AbortSignal;
|
|
100
|
+
/** Origins (besides same-origin, always allowed) that may see and call this tool from other documents in the same tree. */
|
|
101
|
+
readonly exposedTo?: readonly string[];
|
|
102
|
+
}
|
|
103
|
+
/** What a confirmation handler is asked to approve. */
|
|
104
|
+
export interface WebMcpUserInteraction {
|
|
105
|
+
readonly capability: CapabilityDef;
|
|
106
|
+
readonly args: Record<string, unknown>;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Asks the human to approve one call before it runs. Resolve `true` to proceed, `false` to refuse.
|
|
110
|
+
*
|
|
111
|
+
* **This is Jini's hook, not the browser's.** Earlier WebMCP drafts floated a
|
|
112
|
+
* `requestUserInteraction()` on the page's model-context surface; the current draft
|
|
113
|
+
* (https://webmachinelearning.github.io/webmcp/) does not define one, so there is nothing to
|
|
114
|
+
* feature-detect and nothing standard to call. A host that wants a confirmed WebMCP tool supplies
|
|
115
|
+
* this itself.
|
|
116
|
+
*
|
|
117
|
+
* Independently re-confirmed 2026-07-28: the reference polyfill `@mcp-b/webmcp-polyfill` (the
|
|
118
|
+
* `MCP-B`/`WebMCP-org` community project, not the W3C CG spec) DOES pass a second
|
|
119
|
+
* `client: { requestUserInteraction(callback) }` argument to `execute`, as one of its own
|
|
120
|
+
* non-standard "MCPB extensions". That is further evidence the idea is real and wanted, and
|
|
121
|
+
* further confirmation it is NOT part of the standardized `ToolExecuteCallback` — whose IDL is
|
|
122
|
+
* `Promise<any> (object input)`, one argument. This module's `execute` wrapper below takes one
|
|
123
|
+
* argument for exactly that reason; a second, ignored argument from a polyfill is harmless.
|
|
124
|
+
*/
|
|
125
|
+
export type RequestUserInteraction = (interaction: WebMcpUserInteraction) => Promise<boolean>;
|
|
126
|
+
export interface ToWebMcpToolOptions {
|
|
127
|
+
readonly requestUserInteraction?: RequestUserInteraction;
|
|
128
|
+
/**
|
|
129
|
+
* `ModelContextTool.title`. Meaningful per-capability, so pass this through {@link toWebMcpTool}
|
|
130
|
+
* (one capability) rather than {@link toWebMcpTools} (a whole manifest) — the latter shares one
|
|
131
|
+
* `options` object across every capability in the batch, and a shared title would repeat
|
|
132
|
+
* verbatim across dissimilar tools.
|
|
133
|
+
*/
|
|
134
|
+
readonly title?: string;
|
|
135
|
+
/**
|
|
136
|
+
* Overrides or extends the default `annotations` (`{ readOnlyHint: capability.risk === 'read' }`).
|
|
137
|
+
* Fields set here win over the default.
|
|
138
|
+
*/
|
|
139
|
+
readonly annotations?: WebMcpToolAnnotations;
|
|
140
|
+
/** See {@link WebMcpRegisterToolOptions.signal}. Safe to share across a whole {@link toWebMcpTools} batch — one `AbortController` per registration session, aborted once on teardown. */
|
|
141
|
+
readonly signal?: AbortSignal;
|
|
142
|
+
/** See {@link WebMcpRegisterToolOptions.exposedTo}. Safe to share across a whole {@link toWebMcpTools} batch when every capability in it gets the same scoping. */
|
|
143
|
+
readonly exposedTo?: readonly string[];
|
|
144
|
+
}
|
|
145
|
+
/** Thrown in place of executing, when a call needed confirmation and did not get it. */
|
|
146
|
+
export declare class WebMcpConfirmationRequiredError extends Error {
|
|
147
|
+
readonly capabilityId: string;
|
|
148
|
+
readonly reason: 'declined' | 'no-handler';
|
|
149
|
+
constructor(capabilityId: string, reason: 'declined' | 'no-handler');
|
|
150
|
+
}
|
|
151
|
+
/** Whether `name` satisfies the spec's tool-name rule. Exported so a caller can pre-check a manifest without registering anything. */
|
|
152
|
+
export declare function isValidWebMcpToolName(name: string): boolean;
|
|
153
|
+
/**
|
|
154
|
+
* Thrown synchronously by {@link toWebMcpTool} for a capability whose `id` cannot legally become a
|
|
155
|
+
* WebMCP tool name. Distinct from {@link WebMcpConfirmationRequiredError}: this is a manifest
|
|
156
|
+
* defect caught before any registration is attempted, not a runtime refusal of a call.
|
|
157
|
+
*/
|
|
158
|
+
export declare class InvalidWebMcpToolNameError extends Error {
|
|
159
|
+
readonly capabilityId: string;
|
|
160
|
+
constructor(capabilityId: string);
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Projects one capability into a WebMCP registration.
|
|
164
|
+
*
|
|
165
|
+
* **The confirmation gate is fail-closed.** A capability with `requiresConfirmation` will not run
|
|
166
|
+
* unless `options.requestUserInteraction` is supplied *and* resolves `true`. Omitting the handler
|
|
167
|
+
* does not silently downgrade to "just run it" — it makes the tool permanently refuse, which is
|
|
168
|
+
* the only safe reading of a manifest that asked for confirmation.
|
|
169
|
+
*
|
|
170
|
+
* This does not make WebMCP governed. It is a page-local gate over a path that still has no run,
|
|
171
|
+
* no principal, no `ToolExecutor` and no audit trail (see this package's `frontend-session-registry`
|
|
172
|
+
* note and §11 of the capability report). It closes the *accidental* case — a destructive
|
|
173
|
+
* capability reaching the page with nothing in front of it — not the authorization gap.
|
|
174
|
+
*
|
|
175
|
+
* @param capability - The capability to expose.
|
|
176
|
+
* @param execute - Runs the capability. Receives the raw argument object, already checked against
|
|
177
|
+
* `capability.inputSchema` — a caller-supplied value that fails validation never reaches this.
|
|
178
|
+
* @param options - Optional confirmation handler, title/annotations, and registration options
|
|
179
|
+
* (`signal`/`exposedTo`); required in practice for any capability declaring `requiresConfirmation`.
|
|
180
|
+
* @returns The registration object to hand to `registerTool`.
|
|
181
|
+
* @throws {@link InvalidWebMcpToolNameError} synchronously, if `capability.id` cannot be a WebMCP
|
|
182
|
+
* tool name.
|
|
183
|
+
* @throws {@link WebMcpConfirmationRequiredError} from `execute`, when confirmation is required
|
|
184
|
+
* and is either declined or unobtainable.
|
|
185
|
+
*/
|
|
186
|
+
export declare function toWebMcpTool(capability: CapabilityDef, execute: (id: string, args: Record<string, unknown>) => Promise<unknown>, options?: ToWebMcpToolOptions): WebMcpToolRegistration;
|
|
187
|
+
/**
|
|
188
|
+
* Projects a whole manifest.
|
|
189
|
+
*
|
|
190
|
+
* `options` is shared across every capability — safe for `requestUserInteraction`, `signal`, and
|
|
191
|
+
* `exposedTo`, which are naturally uniform for one registration session; do not pass `title`
|
|
192
|
+
* through this one, since it would repeat verbatim across every tool in the manifest (see
|
|
193
|
+
* {@link ToWebMcpToolOptions.title}).
|
|
194
|
+
*
|
|
195
|
+
* @param capabilities - Capabilities to expose, already filtered by whatever policy applies.
|
|
196
|
+
* @param execute - Shared dispatcher, keyed by capability id.
|
|
197
|
+
* @returns One registration per capability, in manifest order.
|
|
198
|
+
* @throws {@link InvalidWebMcpToolNameError} synchronously, for the first capability whose `id`
|
|
199
|
+
* cannot be a WebMCP tool name.
|
|
200
|
+
*/
|
|
201
|
+
export declare function toWebMcpTools(capabilities: readonly CapabilityDef[], execute: (id: string, args: Record<string, unknown>) => Promise<unknown>, options?: ToWebMcpToolOptions): readonly WebMcpToolRegistration[];
|
|
202
|
+
//# sourceMappingURL=webmcp.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webmcp.d.ts","sourceRoot":"","sources":["../../src/core/webmcp.ts"],"names":[],"mappings":"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"}
|