@jini-ai/agentic 0.6.15-rc.2 → 0.6.16
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/dist/core/a2ui/catalog.js +5 -2
- package/dist/core/a2ui/common-types.d.ts +1 -1
- package/dist/core/a2ui/renderer-to-agent.d.ts +8 -8
- package/dist/core/a2ui/renderer-to-agent.js +3 -1
- package/dist/core/a2ui/resolve.js +18 -13
- package/dist/core/a2ui/tree.js +18 -14
- package/dist/core/ag-ui.d.ts +0 -12
- package/dist/core/ag-ui.js +5 -3
- package/dist/core/annotated-actions-script.js +3 -1
- package/dist/core/capability.d.ts +12 -7
- package/dist/core/capability.js +10 -3
- package/dist/core/dom/dom-page-driver.d.ts +9 -1
- package/dist/core/dom/dom-page-driver.js +71 -25
- package/dist/core/dom/publication-filter.d.ts +26 -0
- package/dist/core/dom/publication-filter.js +129 -0
- package/dist/core/element-handles.d.ts +4 -0
- package/dist/core/gen-ui/encoder.js +2 -1
- package/dist/core/guards.js +11 -5
- package/dist/core/handle.js +2 -1
- package/dist/core/index.d.ts +3 -0
- package/dist/core/index.js +2 -0
- package/dist/core/list-handles.js +11 -1
- package/dist/core/messages.js +2 -1
- package/dist/core/omit-keys.d.ts +7 -0
- package/dist/core/omit-keys.js +12 -0
- package/dist/core/page-capabilities.js +4 -2
- package/dist/core/page-driver.d.ts +3 -1
- package/dist/core/page-executor.d.ts +3 -1
- package/dist/core/page-executor.js +93 -19
- package/dist/core/page-navigation.d.ts +59 -0
- package/dist/core/page-navigation.js +58 -0
- package/dist/core/page-publication.d.ts +22 -0
- package/dist/core/page-publication.js +5 -0
- package/dist/core/site-guide/site-guide.js +2 -3
- package/dist/core/site-guide/topic-schema.js +2 -2
- package/dist/skills/install/archive.js +7 -2
- package/dist/skills/install/github.js +11 -3
- package/dist/skills/install/install-service.js +4 -3
- package/dist/skills/install/layout.js +2 -1
- package/dist/skills/install/node-filesystem.js +9 -1
- package/dist/skills/install/unsafe-chars.d.ts +9 -0
- package/dist/skills/install/unsafe-chars.js +18 -0
- package/dist/skills/install/validation.js +4 -2
- package/dist/skills/install/yauzl-archive-reader.js +4 -1
- package/package.json +11 -8
- package/dist/core/a2ui/agent-to-renderer.d.ts.map +0 -1
- package/dist/core/a2ui/agent-to-renderer.js.map +0 -1
- package/dist/core/a2ui/catalog.d.ts.map +0 -1
- package/dist/core/a2ui/catalog.js.map +0 -1
- package/dist/core/a2ui/common-types.d.ts.map +0 -1
- package/dist/core/a2ui/common-types.js.map +0 -1
- package/dist/core/a2ui/index.d.ts.map +0 -1
- package/dist/core/a2ui/index.js.map +0 -1
- package/dist/core/a2ui/interpreter.d.ts.map +0 -1
- package/dist/core/a2ui/interpreter.js.map +0 -1
- package/dist/core/a2ui/json-pointer.d.ts.map +0 -1
- package/dist/core/a2ui/json-pointer.js.map +0 -1
- package/dist/core/a2ui/renderer-to-agent.d.ts.map +0 -1
- package/dist/core/a2ui/renderer-to-agent.js.map +0 -1
- package/dist/core/a2ui/resolve.d.ts.map +0 -1
- package/dist/core/a2ui/resolve.js.map +0 -1
- package/dist/core/a2ui/surface-properties.d.ts.map +0 -1
- package/dist/core/a2ui/surface-properties.js.map +0 -1
- package/dist/core/a2ui/tree.d.ts.map +0 -1
- package/dist/core/a2ui/tree.js.map +0 -1
- package/dist/core/ag-ui.d.ts.map +0 -1
- package/dist/core/ag-ui.js.map +0 -1
- package/dist/core/annotated-actions-script.d.ts.map +0 -1
- package/dist/core/annotated-actions-script.js.map +0 -1
- package/dist/core/capability.d.ts.map +0 -1
- package/dist/core/capability.js.map +0 -1
- package/dist/core/dom/dom-page-driver.d.ts.map +0 -1
- package/dist/core/dom/dom-page-driver.js.map +0 -1
- package/dist/core/dom/index.d.ts.map +0 -1
- package/dist/core/dom/index.js.map +0 -1
- package/dist/core/dom/model-context.d.ts.map +0 -1
- package/dist/core/dom/model-context.js.map +0 -1
- package/dist/core/dom/native-model-context.d.ts.map +0 -1
- package/dist/core/dom/native-model-context.js.map +0 -1
- package/dist/core/element-handles.d.ts.map +0 -1
- package/dist/core/element-handles.js.map +0 -1
- package/dist/core/gen-ui/encoder.d.ts.map +0 -1
- package/dist/core/gen-ui/encoder.js.map +0 -1
- package/dist/core/gen-ui/events.d.ts.map +0 -1
- package/dist/core/gen-ui/events.js.map +0 -1
- package/dist/core/gen-ui/index.d.ts.map +0 -1
- package/dist/core/gen-ui/index.js.map +0 -1
- package/dist/core/guards.d.ts.map +0 -1
- package/dist/core/guards.js.map +0 -1
- package/dist/core/handle.d.ts.map +0 -1
- package/dist/core/handle.js.map +0 -1
- package/dist/core/index.d.ts.map +0 -1
- package/dist/core/index.js.map +0 -1
- package/dist/core/list-handles.d.ts.map +0 -1
- package/dist/core/list-handles.js.map +0 -1
- package/dist/core/mcp-ui-apps.d.ts.map +0 -1
- package/dist/core/mcp-ui-apps.js.map +0 -1
- package/dist/core/messages.d.ts.map +0 -1
- package/dist/core/messages.js.map +0 -1
- package/dist/core/page-capabilities.d.ts.map +0 -1
- package/dist/core/page-capabilities.js.map +0 -1
- package/dist/core/page-driver.d.ts.map +0 -1
- package/dist/core/page-driver.js.map +0 -1
- package/dist/core/page-executor.d.ts.map +0 -1
- package/dist/core/page-executor.js.map +0 -1
- package/dist/core/site-guide/index.d.ts.map +0 -1
- package/dist/core/site-guide/index.js.map +0 -1
- package/dist/core/site-guide/site-guide.d.ts.map +0 -1
- package/dist/core/site-guide/site-guide.js.map +0 -1
- package/dist/core/site-guide/topic-schema.d.ts.map +0 -1
- package/dist/core/site-guide/topic-schema.js.map +0 -1
- package/dist/core/site-guide/types.d.ts.map +0 -1
- package/dist/core/site-guide/types.js.map +0 -1
- package/dist/core/webmcp.d.ts.map +0 -1
- package/dist/core/webmcp.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/skills/install/archive.d.ts.map +0 -1
- package/dist/skills/install/archive.js.map +0 -1
- package/dist/skills/install/fetch-adapter.d.ts.map +0 -1
- package/dist/skills/install/fetch-adapter.js.map +0 -1
- package/dist/skills/install/github.d.ts.map +0 -1
- package/dist/skills/install/github.js.map +0 -1
- package/dist/skills/install/index.d.ts.map +0 -1
- package/dist/skills/install/index.js.map +0 -1
- package/dist/skills/install/install-service.d.ts.map +0 -1
- package/dist/skills/install/install-service.js.map +0 -1
- package/dist/skills/install/layout.d.ts.map +0 -1
- package/dist/skills/install/layout.js.map +0 -1
- package/dist/skills/install/live-registration.d.ts.map +0 -1
- package/dist/skills/install/live-registration.js.map +0 -1
- package/dist/skills/install/node-filesystem.d.ts.map +0 -1
- package/dist/skills/install/node-filesystem.js.map +0 -1
- package/dist/skills/install/ports.d.ts.map +0 -1
- package/dist/skills/install/ports.js.map +0 -1
- package/dist/skills/install/state.d.ts.map +0 -1
- package/dist/skills/install/state.js.map +0 -1
- package/dist/skills/install/validation.d.ts.map +0 -1
- package/dist/skills/install/validation.js.map +0 -1
- package/dist/skills/install/yauzl-archive-reader.d.ts.map +0 -1
- package/dist/skills/install/yauzl-archive-reader.js.map +0 -1
|
@@ -211,8 +211,11 @@ const SliderPropsSchema = checkableComponentProps({
|
|
|
211
211
|
* mutually exclusive in practice, so exactly-one and at-least-one coincide.
|
|
212
212
|
*/
|
|
213
213
|
const ISO_DATE = /^\d{4}-\d{2}-\d{2}$/;
|
|
214
|
-
|
|
215
|
-
const
|
|
214
|
+
// `hh:mm[:ss[.fff]]` and an optional `Z`/`±hh:mm` offset, shared by the time and date-time forms.
|
|
215
|
+
const CLOCK_TIME = /\d{2}:\d{2}(?::\d{2}(?:\.\d+)?)?/.source;
|
|
216
|
+
const UTC_OFFSET = /(?:[Zz]|[+-]\d{2}:\d{2})?/.source;
|
|
217
|
+
const ISO_TIME = new RegExp(`^${CLOCK_TIME}${UTC_OFFSET}$`);
|
|
218
|
+
const ISO_DATE_TIME = new RegExp(`^\\d{4}-\\d{2}-\\d{2}[Tt ]${CLOCK_TIME}${UTC_OFFSET}$`);
|
|
216
219
|
const IsoDateTimeBoundSchema = DynamicStringSchema.superRefine((value, ctx) => {
|
|
217
220
|
if (typeof value !== 'string')
|
|
218
221
|
return;
|
|
@@ -226,7 +226,7 @@ export declare const ComponentCommonSchema: z.ZodObject<{
|
|
|
226
226
|
export type ComponentCommon = z.infer<typeof ComponentCommonSchema>;
|
|
227
227
|
/** `common_types.json#/$defs/Child` — "A reference to a single child component ID." */
|
|
228
228
|
export declare const ChildSchema: z.ZodString;
|
|
229
|
-
export type Child =
|
|
229
|
+
export type Child = z.infer<typeof ChildSchema>;
|
|
230
230
|
/**
|
|
231
231
|
* `common_types.json#/$defs/ChildList` — either a static array of `ComponentId`s, or a template
|
|
232
232
|
* object (`{componentId, path}`) that generates one child per item in a data-model list.
|
|
@@ -78,15 +78,15 @@ export declare const ValidationFailedErrorSchema: z.ZodObject<{
|
|
|
78
78
|
path: z.ZodString;
|
|
79
79
|
message: z.ZodString;
|
|
80
80
|
}, "strict", z.ZodTypeAny, {
|
|
81
|
+
path: string;
|
|
81
82
|
surfaceId: string;
|
|
82
83
|
code: "VALIDATION_FAILED";
|
|
83
84
|
message: string;
|
|
84
|
-
path: string;
|
|
85
85
|
}, {
|
|
86
|
+
path: string;
|
|
86
87
|
surfaceId: string;
|
|
87
88
|
code: "VALIDATION_FAILED";
|
|
88
89
|
message: string;
|
|
89
|
-
path: string;
|
|
90
90
|
}>;
|
|
91
91
|
export type ValidationFailedError = z.infer<typeof ValidationFailedErrorSchema>;
|
|
92
92
|
export declare const GenericErrorSchema: z.ZodEffects<z.ZodObject<{
|
|
@@ -122,15 +122,15 @@ export declare const ErrorPayloadSchema: z.ZodUnion<[z.ZodObject<{
|
|
|
122
122
|
path: z.ZodString;
|
|
123
123
|
message: z.ZodString;
|
|
124
124
|
}, "strict", z.ZodTypeAny, {
|
|
125
|
+
path: string;
|
|
125
126
|
surfaceId: string;
|
|
126
127
|
code: "VALIDATION_FAILED";
|
|
127
128
|
message: string;
|
|
128
|
-
path: string;
|
|
129
129
|
}, {
|
|
130
|
+
path: string;
|
|
130
131
|
surfaceId: string;
|
|
131
132
|
code: "VALIDATION_FAILED";
|
|
132
133
|
message: string;
|
|
133
|
-
path: string;
|
|
134
134
|
}>, z.ZodEffects<z.ZodObject<{
|
|
135
135
|
code: z.ZodEffects<z.ZodString, string, string>;
|
|
136
136
|
message: z.ZodString;
|
|
@@ -257,15 +257,15 @@ export declare const ErrorMessageSchema: z.ZodObject<{
|
|
|
257
257
|
path: z.ZodString;
|
|
258
258
|
message: z.ZodString;
|
|
259
259
|
}, "strict", z.ZodTypeAny, {
|
|
260
|
+
path: string;
|
|
260
261
|
surfaceId: string;
|
|
261
262
|
code: "VALIDATION_FAILED";
|
|
262
263
|
message: string;
|
|
263
|
-
path: string;
|
|
264
264
|
}, {
|
|
265
|
+
path: string;
|
|
265
266
|
surfaceId: string;
|
|
266
267
|
code: "VALIDATION_FAILED";
|
|
267
268
|
message: string;
|
|
268
|
-
path: string;
|
|
269
269
|
}>, z.ZodEffects<z.ZodObject<{
|
|
270
270
|
code: z.ZodEffects<z.ZodString, string, string>;
|
|
271
271
|
message: z.ZodString;
|
|
@@ -294,10 +294,10 @@ export declare const ErrorMessageSchema: z.ZodObject<{
|
|
|
294
294
|
}, z.ZodTypeAny, "passthrough">>]>;
|
|
295
295
|
}, "strict", z.ZodTypeAny, {
|
|
296
296
|
error: {
|
|
297
|
+
path: string;
|
|
297
298
|
surfaceId: string;
|
|
298
299
|
code: "VALIDATION_FAILED";
|
|
299
300
|
message: string;
|
|
300
|
-
path: string;
|
|
301
301
|
} | z.objectOutputType<{
|
|
302
302
|
code: z.ZodEffects<z.ZodString, string, string>;
|
|
303
303
|
message: z.ZodString;
|
|
@@ -307,10 +307,10 @@ export declare const ErrorMessageSchema: z.ZodObject<{
|
|
|
307
307
|
version: "v1.0";
|
|
308
308
|
}, {
|
|
309
309
|
error: {
|
|
310
|
+
path: string;
|
|
310
311
|
surfaceId: string;
|
|
311
312
|
code: "VALIDATION_FAILED";
|
|
312
313
|
message: string;
|
|
313
|
-
path: string;
|
|
314
314
|
} | z.objectInputType<{
|
|
315
315
|
code: z.ZodEffects<z.ZodString, string, string>;
|
|
316
316
|
message: z.ZodString;
|
|
@@ -85,6 +85,8 @@ export function buildGenericErrorMessage({ code, message, target }, _optional =
|
|
|
85
85
|
return { version: PROTOCOL_VERSION, error: { code, message, ...target } };
|
|
86
86
|
}
|
|
87
87
|
const MESSAGE_KEYS = ['action', 'functionResponse', 'error'];
|
|
88
|
+
/** The schema each message key's envelope is validated against. */
|
|
89
|
+
const MESSAGE_SCHEMAS = { action: ActionMessageSchema, functionResponse: FunctionResponseMessageSchema, error: ErrorMessageSchema };
|
|
88
90
|
/** Same "inspect the shape, validate the one matching branch" dispatcher as `parseAgentToRendererMessage` — see that function's doc for why this beats a plain `z.union`. Used by tests and by anything on the agent side of this fixture that needs to validate what the browser sent. */
|
|
89
91
|
export function parseRendererToAgentMessage({ raw }, _optional = {}) {
|
|
90
92
|
if (typeof raw !== 'object' || raw === null || Array.isArray(raw)) {
|
|
@@ -99,7 +101,7 @@ export function parseRendererToAgentMessage({ raw }, _optional = {}) {
|
|
|
99
101
|
return { ok: false, reason: `expected exactly one of ${MESSAGE_KEYS.join(', ')}, found ${presentKeys.length}` };
|
|
100
102
|
}
|
|
101
103
|
const key = presentKeys[0];
|
|
102
|
-
const schema = key
|
|
104
|
+
const schema = MESSAGE_SCHEMAS[key];
|
|
103
105
|
const result = schema.safeParse(obj);
|
|
104
106
|
if (!result.success) {
|
|
105
107
|
// Same zod guarantee as `parseAgentToRendererMessage` relies on: `success: false` implies a
|
|
@@ -27,26 +27,29 @@ import { callableFromOf, isFunctionRegistered } from './catalog.js';
|
|
|
27
27
|
* `applyAgentMessage`, which this module's own doc says cannot happen.
|
|
28
28
|
*/
|
|
29
29
|
function isDataBinding(value) {
|
|
30
|
-
return
|
|
31
|
-
&& value !== null
|
|
32
|
-
&& !Array.isArray(value)
|
|
33
|
-
&& 'path' in value
|
|
34
|
-
&& typeof value.path === 'string'
|
|
35
|
-
&& Object.keys(value).length === 1;
|
|
30
|
+
return hasStringField(value, 'path') && Object.keys(value).length === 1;
|
|
36
31
|
}
|
|
37
32
|
function isFunctionCall(value) {
|
|
38
|
-
return
|
|
33
|
+
return hasStringField(value, 'call');
|
|
34
|
+
}
|
|
35
|
+
/** A plain (non-array) object whose `key` holds a string. */
|
|
36
|
+
function hasStringField(value, key) {
|
|
37
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value))
|
|
38
|
+
return false;
|
|
39
|
+
return key in value && typeof value[key] === 'string';
|
|
40
|
+
}
|
|
41
|
+
/** A relative path resolved under the current list item, or null outside any list-template item. */
|
|
42
|
+
function itemRelativePointer(path, ctx) {
|
|
43
|
+
if (!ctx.itemScope)
|
|
44
|
+
return null;
|
|
45
|
+
return joinPointer({ base: ctx.itemScope.basePath, tokens: [String(ctx.itemScope.index), ...parsePointerTokens({ pointer: `/${path}` })] });
|
|
39
46
|
}
|
|
40
47
|
function resolveBindingPath(path, ctx) {
|
|
41
48
|
// A relative path is still RFC 6901 syntax, so its `~0`/`~1` escapes must be decoded into real
|
|
42
49
|
// token text before `joinPointer` re-escapes them. Splitting the raw string on `/` instead would
|
|
43
50
|
// hand `joinPointer` already-escaped text and double-escape it, making a relative `a~1b` resolve
|
|
44
51
|
// the literal key `a~1b` while the equivalent absolute pointer correctly resolves `a/b`.
|
|
45
|
-
const absolute = path.startsWith('/')
|
|
46
|
-
? path
|
|
47
|
-
: ctx.itemScope
|
|
48
|
-
? joinPointer({ base: ctx.itemScope.basePath, tokens: [String(ctx.itemScope.index), ...parsePointerTokens({ pointer: `/${path}` })] })
|
|
49
|
-
: null;
|
|
52
|
+
const absolute = path.startsWith('/') ? path : itemRelativePointer(path, ctx);
|
|
50
53
|
if (absolute === null) {
|
|
51
54
|
return { ok: false, reason: 'RELATIVE_PATH_OUTSIDE_LIST_CONTEXT', detail: `relative path "${path}" used outside a list-template item context` };
|
|
52
55
|
}
|
|
@@ -69,7 +72,9 @@ function resolveIndexCall(call, ctx) {
|
|
|
69
72
|
return { ok: true, value: ctx.itemScope.index + offset };
|
|
70
73
|
}
|
|
71
74
|
function isCallableFromSide(callableFrom, side) {
|
|
72
|
-
|
|
75
|
+
if (callableFrom === 'rendererOrAgent')
|
|
76
|
+
return true;
|
|
77
|
+
return (callableFrom === 'rendererOnly' && side === 'renderer') || (callableFrom === 'agentOnly' && side === 'agent');
|
|
73
78
|
}
|
|
74
79
|
/** The catalog-side refusals, in the order they apply: not registered, then the `callableFrom` boundary, then no implementation. Returns the implementation when all three pass. */
|
|
75
80
|
function lookUpCallableImpl(call, ctx) {
|
package/dist/core/a2ui/tree.js
CHANGED
|
@@ -11,6 +11,23 @@
|
|
|
11
11
|
* is orders of magnitude smaller), so this is a fail-safe, not a design budget.
|
|
12
12
|
*/
|
|
13
13
|
export const MAX_RENDER_NODES = 50_000;
|
|
14
|
+
/** Emits one node: a cycle back to an ancestor, a missing component, or a rendered node whose
|
|
15
|
+
* children are queued (after a `leave` frame that pops it off the ancestor path). */
|
|
16
|
+
function visitNode({ id, depth }, walk) {
|
|
17
|
+
if (walk.ancestors.has(id)) {
|
|
18
|
+
walk.output.push({ id, depth, status: 'cycle' });
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
const component = walk.components.get(id);
|
|
22
|
+
if (!component) {
|
|
23
|
+
walk.output.push({ id, depth, status: 'missing' });
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
walk.output.push({ id, depth, status: 'ok' });
|
|
27
|
+
walk.ancestors.add(id);
|
|
28
|
+
walk.stack.push({ leave: id });
|
|
29
|
+
pushChildren(walk.stack, walk.getChildIds({ component }), depth + 1);
|
|
30
|
+
}
|
|
14
31
|
/** Pushes `childIds` onto the walk's stack at `depth`. */
|
|
15
32
|
function pushChildren(stack, childIds, depth) {
|
|
16
33
|
// Pushed in reverse so the first child is popped first, preserving pre-order.
|
|
@@ -57,20 +74,7 @@ export function flattenRenderTree({ components, rootId, getChildIds }, _optional
|
|
|
57
74
|
output.push({ id: frame.id, depth: frame.depth, status: 'truncated' });
|
|
58
75
|
return output;
|
|
59
76
|
}
|
|
60
|
-
|
|
61
|
-
if (ancestors.has(id)) {
|
|
62
|
-
output.push({ id, depth, status: 'cycle' });
|
|
63
|
-
continue;
|
|
64
|
-
}
|
|
65
|
-
const component = components.get(id);
|
|
66
|
-
if (!component) {
|
|
67
|
-
output.push({ id, depth, status: 'missing' });
|
|
68
|
-
continue;
|
|
69
|
-
}
|
|
70
|
-
output.push({ id, depth, status: 'ok' });
|
|
71
|
-
ancestors.add(id);
|
|
72
|
-
stack.push({ leave: id });
|
|
73
|
-
pushChildren(stack, getChildIds({ component }), depth + 1);
|
|
77
|
+
visitNode(frame, { output, ancestors, stack, components, getChildIds });
|
|
74
78
|
}
|
|
75
79
|
return output;
|
|
76
80
|
}
|
package/dist/core/ag-ui.d.ts
CHANGED
|
@@ -64,18 +64,6 @@ export declare function toAgUiTool({ capability }: {
|
|
|
64
64
|
export declare function toAgUiTools({ capabilities }: {
|
|
65
65
|
capabilities: readonly CapabilityDef[];
|
|
66
66
|
}, _optional?: Record<string, never>): readonly AgUiTool[];
|
|
67
|
-
/**
|
|
68
|
-
* Builds the result message for a completed frontend tool call.
|
|
69
|
-
*
|
|
70
|
-
* AG-UI carries the result as a string, so structured output is JSON-encoded. Errors are
|
|
71
|
-
* returned through this same channel rather than thrown — the agent needs to see the refusal
|
|
72
|
-
* (a fill guard saying no, an unavailable capability) as a result it can reason about.
|
|
73
|
-
*
|
|
74
|
-
* @param messageId - Id for the result message itself.
|
|
75
|
-
* @param toolCallId - The `toolCallId` from `TOOL_CALL_START`.
|
|
76
|
-
* @param outcome - What happened.
|
|
77
|
-
* @returns The `role: "tool"` message to send back.
|
|
78
|
-
*/
|
|
79
67
|
export declare function createAgUiToolResult({ messageId, toolCallId, outcome }: {
|
|
80
68
|
messageId: string;
|
|
81
69
|
toolCallId: string;
|
package/dist/core/ag-ui.js
CHANGED
|
@@ -76,10 +76,12 @@ function encodeToolContent(output) {
|
|
|
76
76
|
* @param outcome - What happened.
|
|
77
77
|
* @returns The `role: "tool"` message to send back.
|
|
78
78
|
*/
|
|
79
|
+
/** A string output verbatim; anything else through the tool-content encoder. */
|
|
80
|
+
function toolOutputText(output) {
|
|
81
|
+
return typeof output === 'string' ? output : encodeToolContent(output);
|
|
82
|
+
}
|
|
79
83
|
export function createAgUiToolResult({ messageId, toolCallId, outcome }, _optional = {}) {
|
|
80
|
-
const content = outcome.ok
|
|
81
|
-
? typeof outcome.output === 'string' ? outcome.output : encodeToolContent(outcome.output)
|
|
82
|
-
: JSON.stringify({ error: outcome.error });
|
|
84
|
+
const content = outcome.ok ? toolOutputText(outcome.output) : JSON.stringify({ error: outcome.error });
|
|
83
85
|
return { id: messageId, role: 'tool', content, toolCallId };
|
|
84
86
|
}
|
|
85
87
|
//# sourceMappingURL=ag-ui.js.map
|
|
@@ -63,6 +63,8 @@ export function createAnnotatedActionsScript({ preferenceKey, confirmationMessag
|
|
|
63
63
|
return true;
|
|
64
64
|
}
|
|
65
65
|
function descriptor(element) {
|
|
66
|
+
// Visitor discovery/disclosure marks are not external WebMCP action declarations.
|
|
67
|
+
if (['read', 'menu', 'accordion'].includes(element.getAttribute('data-tool-action'))) return null;
|
|
66
68
|
var name = element.getAttribute('data-toolname') || '';
|
|
67
69
|
var description = element.getAttribute('data-tooldescription') || '';
|
|
68
70
|
if (!/^[A-Za-z0-9_.-]{1,128}$/.test(name) || !description.trim() || !visible(element)) return null;
|
|
@@ -140,7 +142,7 @@ export function createAnnotatedActionsScript({ preferenceKey, confirmationMessag
|
|
|
140
142
|
refresh();
|
|
141
143
|
observer = new MutationObserver(refresh);
|
|
142
144
|
observer.observe(doc.documentElement, { subtree: true, childList: true, attributes: true,
|
|
143
|
-
attributeFilter: ['data-toolname', 'data-tooldescription', 'toolname', 'href', 'download', 'type', 'disabled', 'aria-disabled', 'hidden', 'inert', 'aria-hidden', 'style', 'class', 'open'] });
|
|
145
|
+
attributeFilter: ['data-tool-action', 'data-toolname', 'data-tooldescription', 'toolname', 'href', 'download', 'type', 'disabled', 'aria-disabled', 'hidden', 'inert', 'aria-hidden', 'style', 'class', 'open'] });
|
|
144
146
|
})(` + config + ');';
|
|
145
147
|
}
|
|
146
148
|
//# sourceMappingURL=annotated-actions-script.js.map
|
|
@@ -24,13 +24,17 @@ export type CapabilityRisk = 'read' | 'write';
|
|
|
24
24
|
* instead of waiting for a timeout that will never resolve.
|
|
25
25
|
*/
|
|
26
26
|
export type CapabilitySurface = 'session' | 'server';
|
|
27
|
+
export interface CapabilityInputProperty {
|
|
28
|
+
readonly type: string;
|
|
29
|
+
readonly description?: string;
|
|
30
|
+
readonly enum?: readonly string[];
|
|
31
|
+
readonly properties?: Record<string, CapabilityInputProperty>;
|
|
32
|
+
readonly required?: readonly string[];
|
|
33
|
+
readonly additionalProperties?: boolean | CapabilityInputProperty;
|
|
34
|
+
}
|
|
27
35
|
export interface CapabilityInputSchema {
|
|
28
36
|
readonly type: 'object';
|
|
29
|
-
readonly properties: Record<string,
|
|
30
|
-
type: string;
|
|
31
|
-
description?: string;
|
|
32
|
-
enum?: readonly string[];
|
|
33
|
-
}>;
|
|
37
|
+
readonly properties: Record<string, CapabilityInputProperty>;
|
|
34
38
|
readonly required?: readonly string[];
|
|
35
39
|
readonly additionalProperties?: boolean;
|
|
36
40
|
}
|
|
@@ -65,8 +69,9 @@ export declare function findCapability({ capabilities, id }: {
|
|
|
65
69
|
* Manifests advertise `additionalProperties: false` and a `required` list, but nothing was
|
|
66
70
|
* enforcing either — handlers read the fields they knew about and ignored the rest, so a
|
|
67
71
|
* misnamed argument silently became a missing one. This closes that for any surface that calls
|
|
68
|
-
* it. Intentionally a shallow check, not a JSON Schema engine
|
|
69
|
-
*
|
|
72
|
+
* it. Intentionally a shallow check, not a JSON Schema engine. Nested schemas describe the public
|
|
73
|
+
* contract; the owning executor enforces their shape before any effect (for example navigation
|
|
74
|
+
* entity/query inputs). This check enforces top-level types, required and unknown arguments.
|
|
70
75
|
*
|
|
71
76
|
* @param capability - The capability being invoked.
|
|
72
77
|
* @param input - Raw caller-supplied arguments.
|
package/dist/core/capability.js
CHANGED
|
@@ -26,8 +26,9 @@ export function findCapability({ capabilities, id }, _optional = {}) {
|
|
|
26
26
|
* Manifests advertise `additionalProperties: false` and a `required` list, but nothing was
|
|
27
27
|
* enforcing either — handlers read the fields they knew about and ignored the rest, so a
|
|
28
28
|
* misnamed argument silently became a missing one. This closes that for any surface that calls
|
|
29
|
-
* it. Intentionally a shallow check, not a JSON Schema engine
|
|
30
|
-
*
|
|
29
|
+
* it. Intentionally a shallow check, not a JSON Schema engine. Nested schemas describe the public
|
|
30
|
+
* contract; the owning executor enforces their shape before any effect (for example navigation
|
|
31
|
+
* entity/query inputs). This check enforces top-level types, required and unknown arguments.
|
|
31
32
|
*
|
|
32
33
|
* @param capability - The capability being invoked.
|
|
33
34
|
* @param input - Raw caller-supplied arguments.
|
|
@@ -80,8 +81,14 @@ function findPropertyInputError({ properties, input }, _optional = {}) {
|
|
|
80
81
|
}
|
|
81
82
|
return null;
|
|
82
83
|
}
|
|
84
|
+
/** `typeof`, except `null` and arrays get their own names. */
|
|
85
|
+
function valueKind(value) {
|
|
86
|
+
if (value === null)
|
|
87
|
+
return 'null';
|
|
88
|
+
return Array.isArray(value) ? 'array' : typeof value;
|
|
89
|
+
}
|
|
83
90
|
function propertyInputError({ name, schema, value }) {
|
|
84
|
-
const actual =
|
|
91
|
+
const actual = valueKind(value);
|
|
85
92
|
if (!matchesPropertyType({ value, actual, expected: schema.type })) {
|
|
86
93
|
const received = typeof value === 'number' && !Number.isFinite(value) ? String(value) : actual;
|
|
87
94
|
return `"${name}" must be a ${schema.type}, received ${received}`;
|
|
@@ -1,10 +1,13 @@
|
|
|
1
|
+
import type { PagePublication } from '../page-publication.js';
|
|
2
|
+
import type { AgentNavigationScreen, PageNavigationInput, PageNavigationResult } from '../page-navigation.js';
|
|
1
3
|
import type { PageDriver } from '../page-driver.js';
|
|
2
4
|
/** One page a host allows navigation to: its human label, and how to actually get there. */
|
|
3
5
|
export interface DomPageDriverPage {
|
|
4
6
|
/** Shown to a caller by `page.find_elements`/`page.navigate`'s refusal message — see
|
|
5
7
|
* `PageSummary.label` for why this exists at all. */
|
|
6
8
|
readonly label: string;
|
|
7
|
-
readonly
|
|
9
|
+
readonly navigation?: AgentNavigationScreen;
|
|
10
|
+
readonly navigate: (required: PageNavigationInput) => void | PageNavigationResult | Promise<void | PageNavigationResult>;
|
|
8
11
|
}
|
|
9
12
|
export interface DomPageDriverRequired {
|
|
10
13
|
/** The subtree to expose. Never pass `document`. */
|
|
@@ -25,6 +28,11 @@ export interface DomPageDriverOptions {
|
|
|
25
28
|
* view (it is bound to the connection, not the render).
|
|
26
29
|
*/
|
|
27
30
|
readonly currentPage?: string | undefined;
|
|
31
|
+
readonly publication?: PagePublication;
|
|
32
|
+
/** Public hosts acknowledge terminal native submissions before executing the one saved effect. */
|
|
33
|
+
readonly deferSubmit?: (args: {
|
|
34
|
+
execute: () => Promise<void>;
|
|
35
|
+
}) => void;
|
|
28
36
|
}
|
|
29
37
|
/**
|
|
30
38
|
* Builds a driver over `root`.
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createPublicationFilter, publishedText } from './publication-filter.js';
|
|
1
2
|
import { AGENT_ELEMENT_ATTRIBUTE, AGENT_LABEL_ATTRIBUTE, AGENT_PAGE_ATTRIBUTE, AGENT_PRIVATE_ATTRIBUTE, AGENT_ROLE_ATTRIBUTE, AGENT_ELEMENT_ROLES, resolveHandleSelector, } from '../element-handles.js';
|
|
2
3
|
import { normalizeAgentLabel } from '../guards.js';
|
|
3
4
|
/**
|
|
@@ -147,6 +148,7 @@ function dropdownFieldDescriptorOf({ dropdown }, _optional = {}) {
|
|
|
147
148
|
return null;
|
|
148
149
|
return {
|
|
149
150
|
type: 'select',
|
|
151
|
+
autocomplete: dropdown.getAttribute('autocomplete')?.toLowerCase() || undefined,
|
|
150
152
|
name: dropdown.name || undefined,
|
|
151
153
|
id: dropdown.id || undefined,
|
|
152
154
|
// Same reason `fieldDescriptorOf` carries these: a `<select aria-label="Card number"
|
|
@@ -160,6 +162,7 @@ function dropdownFieldDescriptorOf({ dropdown }, _optional = {}) {
|
|
|
160
162
|
}
|
|
161
163
|
function rawElementStateOf({ element, control, checkable, readable, value, dropdown }, _optional = {}) {
|
|
162
164
|
const text = publicTextOf(element);
|
|
165
|
+
const expanded = expansionOf({ element, control });
|
|
163
166
|
return {
|
|
164
167
|
text,
|
|
165
168
|
// A contenteditable region has no `.value`; its content IS its value, so `text` is the
|
|
@@ -172,6 +175,7 @@ function rawElementStateOf({ element, control, checkable, readable, value, dropd
|
|
|
172
175
|
// driver deciding here which values are secret is a driver holding policy.
|
|
173
176
|
...(value !== undefined ? { value } : {}),
|
|
174
177
|
...(checkable ? { checked: control.checked } : {}),
|
|
178
|
+
...(expanded !== undefined ? { expanded } : {}),
|
|
175
179
|
...(disabledOf(control) !== undefined ? { disabled: disabledOf(control) } : {}),
|
|
176
180
|
...(visibilityOf(element) !== undefined ? { visible: visibilityOf(element) } : {}),
|
|
177
181
|
...(readable !== null ? { field: readable } : {}),
|
|
@@ -184,6 +188,20 @@ function rawElementStateOf({ element, control, checkable, readable, value, dropd
|
|
|
184
188
|
: {}),
|
|
185
189
|
};
|
|
186
190
|
}
|
|
191
|
+
/** Read disclosure semantics, not text changes: opening a panel often leaves its button unchanged.
|
|
192
|
+
* Native summaries have no aria-expanded; their owning details element carries the open state.
|
|
193
|
+
* @returns The platform's disclosure state, or undefined when this is not a disclosure control.
|
|
194
|
+
*/
|
|
195
|
+
function expansionOf({ element, control }, _options = {}) {
|
|
196
|
+
const aria = control.getAttribute('aria-expanded') ?? element.getAttribute('aria-expanded');
|
|
197
|
+
if (aria === 'true' || aria === 'false')
|
|
198
|
+
return aria === 'true';
|
|
199
|
+
if (element instanceof HTMLDetailsElement)
|
|
200
|
+
return element.open;
|
|
201
|
+
if (control.matches('summary') && control.parentElement instanceof HTMLDetailsElement)
|
|
202
|
+
return control.parentElement.open;
|
|
203
|
+
return undefined;
|
|
204
|
+
}
|
|
187
205
|
/**
|
|
188
206
|
* Whether the element is actually rendered, or `undefined` when the platform cannot say.
|
|
189
207
|
*
|
|
@@ -216,12 +234,9 @@ function visibilityOf(element) {
|
|
|
216
234
|
* form submission entirely. `:disabled` is the platform's own answer and covers both cases.
|
|
217
235
|
*/
|
|
218
236
|
function disabledOf(control) {
|
|
219
|
-
|
|
220
|
-
|| control instanceof
|
|
221
|
-
|
|
222
|
-
|| control instanceof HTMLSelectElement
|
|
223
|
-
? control.matches(':disabled')
|
|
224
|
-
: undefined;
|
|
237
|
+
const formControl = control instanceof HTMLInputElement || control instanceof HTMLTextAreaElement
|
|
238
|
+
|| control instanceof HTMLButtonElement || control instanceof HTMLSelectElement;
|
|
239
|
+
return formControl ? control.matches(':disabled') : undefined;
|
|
225
240
|
}
|
|
226
241
|
const PRIVATE_SELECTOR = `[${AGENT_PRIVATE_ATTRIBUTE}]`;
|
|
227
242
|
/** Whether `node` is inside (or is) a `[data-agent-private]` subtree. @complexity O(depth). */
|
|
@@ -244,9 +259,9 @@ function publicTextOf(element) {
|
|
|
244
259
|
/* c8 ignore next -- as above. */
|
|
245
260
|
return copy.textContent ?? '';
|
|
246
261
|
}
|
|
247
|
-
function describe(element, page) {
|
|
262
|
+
function describe(element, page, publicText) {
|
|
248
263
|
const role = element.getAttribute(AGENT_ROLE_ATTRIBUTE);
|
|
249
|
-
const text = publicTextOf(element);
|
|
264
|
+
const text = publicText ?? publicTextOf(element);
|
|
250
265
|
// Live text is a fine fallback label for an ordinary element — it is the page's own ontology,
|
|
251
266
|
// rendered openly. For an editable region it is not: a contenteditable's content is the *user's
|
|
252
267
|
// data*, so falling back to it published the contents of a rich-text field to every
|
|
@@ -325,8 +340,12 @@ export function createDomPageDriver({ root, pages }, options = {}) {
|
|
|
325
340
|
* publishes the same handle twice makes `find`'s single-match resolution ambiguous — surfaced
|
|
326
341
|
* here so both callers below can refuse rather than silently pick one.
|
|
327
342
|
*/
|
|
328
|
-
const findAll = (handle) =>
|
|
329
|
-
.
|
|
343
|
+
const findAll = (handle) => {
|
|
344
|
+
const matches = Array.from(root.querySelectorAll(resolveHandleSelector({ handle })));
|
|
345
|
+
if (options.publication && matches.length !== 1)
|
|
346
|
+
return [];
|
|
347
|
+
return matches.filter(element => !isPrivate(element) && (!publicationFilter || publicationFilter.allows({ element, action: 'read' })));
|
|
348
|
+
};
|
|
330
349
|
/**
|
|
331
350
|
* More than one element answers to the same handle — a page-authoring bug (duplicate
|
|
332
351
|
* `data-agent-element`), not something a caller passing that handle can resolve on its own.
|
|
@@ -338,13 +357,16 @@ export function createDomPageDriver({ root, pages }, options = {}) {
|
|
|
338
357
|
const ambiguousHandleError = (handle, count) => new Error(`"${handle}" is published on ${count} elements on this page, so which one it addresses is `
|
|
339
358
|
+ 'ambiguous — this is a page-authoring bug (duplicate data-agent-element), not something a '
|
|
340
359
|
+ 'caller can resolve; publish a unique handle per element');
|
|
341
|
-
const find = (handle) => {
|
|
360
|
+
const find = (handle, action = 'read') => {
|
|
342
361
|
const matches = findAll(handle);
|
|
343
362
|
if (matches.length === 0)
|
|
344
363
|
throw new Error(`no element published as "${handle}" on this page`);
|
|
345
364
|
if (matches.length > 1)
|
|
346
365
|
throw ambiguousHandleError(handle, matches.length);
|
|
347
|
-
|
|
366
|
+
const element = matches[0];
|
|
367
|
+
if (publicationFilter && !publicationFilter.allows({ element: controlOf(element), action }))
|
|
368
|
+
throw new Error('Published action unavailable');
|
|
369
|
+
return element;
|
|
348
370
|
};
|
|
349
371
|
/**
|
|
350
372
|
* The control a handle addresses — for a wrapper like `<li><label><input>`, the input.
|
|
@@ -379,11 +401,13 @@ export function createDomPageDriver({ root, pages }, options = {}) {
|
|
|
379
401
|
.find(owned);
|
|
380
402
|
return candidate ?? element;
|
|
381
403
|
};
|
|
404
|
+
const publicationFilter = options.publication ? createPublicationFilter({ root, publication: options.publication,
|
|
405
|
+
fieldOf: element => fieldDescriptorOf(controlOf(element)) ?? dropdownFieldDescriptorOf({ dropdown: element instanceof HTMLSelectElement ? element : undefined }) }) : undefined;
|
|
382
406
|
return {
|
|
383
407
|
async findElements(_required, filter = {}) {
|
|
384
408
|
const found = Array.from(root.querySelectorAll(`[${AGENT_ELEMENT_ATTRIBUTE}]`))
|
|
385
|
-
.filter(
|
|
386
|
-
.map((element) => describe(element, pageOf(element)))
|
|
409
|
+
.filter(element => !isPrivate(element) && (!publicationFilter || findAll(element.getAttribute(AGENT_ELEMENT_ATTRIBUTE) ?? '').includes(element)))
|
|
410
|
+
.map((element) => describe(element, pageOf(element), publicationFilter ? publishedText({ element }) : undefined))
|
|
387
411
|
.filter((element) => element.handle.length > 0);
|
|
388
412
|
const query = filter.query?.toLowerCase();
|
|
389
413
|
return found.filter((element) => {
|
|
@@ -399,7 +423,7 @@ export function createDomPageDriver({ root, pages }, options = {}) {
|
|
|
399
423
|
// `Object.entries`, same own-enumerable-keys-only guarantee `Object.keys` gives `navigate`'s
|
|
400
424
|
// own `hasOwnProperty` check above — no risk of a `pages.label`/`pages.navigate`-shaped
|
|
401
425
|
// prototype entry leaking in as a fake page id.
|
|
402
|
-
return Object.entries(pages).map(([id, page]) => ({ id, label: page.label }));
|
|
426
|
+
return Object.entries(pages).map(([id, page]) => ({ id, label: page.label, ...(page.navigation ? { navigation: page.navigation } : {}) }));
|
|
403
427
|
},
|
|
404
428
|
async describeField({ handle }, _optional = {}) {
|
|
405
429
|
return fieldDescriptorOf(controlOf(find(handle)));
|
|
@@ -428,7 +452,8 @@ export function createDomPageDriver({ root, pages }, options = {}) {
|
|
|
428
452
|
const value = field !== null
|
|
429
453
|
? control.value
|
|
430
454
|
: dropdown?.value;
|
|
431
|
-
|
|
455
|
+
const state = rawElementStateOf({ element, control, checkable, readable, value, dropdown });
|
|
456
|
+
return publicationState({ state, element, filtered: Boolean(publicationFilter) });
|
|
432
457
|
},
|
|
433
458
|
/**
|
|
434
459
|
* Two animation frames — long enough for a framework to have re-rendered and the browser to
|
|
@@ -457,7 +482,7 @@ export function createDomPageDriver({ root, pages }, options = {}) {
|
|
|
457
482
|
});
|
|
458
483
|
},
|
|
459
484
|
async highlight({ handle, durationMs }, _optional = {}) {
|
|
460
|
-
const element = find(handle);
|
|
485
|
+
const element = find(handle, 'highlight');
|
|
461
486
|
// Same refusal as `click()`, for the same reason: an SVG (or other non-HTMLElement) target
|
|
462
487
|
// has no `.style` to draw an outline on, so silently returning here drew nothing while
|
|
463
488
|
// `page-executor.ts` unconditionally reports the highlight as successful — a guaranteed
|
|
@@ -474,7 +499,9 @@ export function createDomPageDriver({ root, pages }, options = {}) {
|
|
|
474
499
|
borderRadius: element.style.borderRadius,
|
|
475
500
|
};
|
|
476
501
|
Object.assign(element.style, HIGHLIGHT_STYLE);
|
|
477
|
-
|
|
502
|
+
// Embedded DOMs may omit scrolling; highlighting must still restore its styles.
|
|
503
|
+
if (typeof element.scrollIntoView === 'function')
|
|
504
|
+
element.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
|
478
505
|
const timer = setTimeout(() => {
|
|
479
506
|
// Restore what was there rather than clearing: the element may have had its own outline.
|
|
480
507
|
Object.assign(element.style, restore);
|
|
@@ -483,16 +510,29 @@ export function createDomPageDriver({ root, pages }, options = {}) {
|
|
|
483
510
|
highlights.set(handle, { timer, restore });
|
|
484
511
|
},
|
|
485
512
|
async scrollTo({ handle }, _optional = {}) {
|
|
486
|
-
find(handle
|
|
513
|
+
const element = find(handle, 'scrollTo');
|
|
514
|
+
// Revealing a clicked control is best-effort in DOMs without layout (including jsdom).
|
|
515
|
+
if (typeof element.scrollIntoView === 'function')
|
|
516
|
+
element.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
|
487
517
|
},
|
|
488
518
|
async click({ handle }, _optional = {}) {
|
|
489
|
-
const control = controlOf(find(handle));
|
|
519
|
+
const control = controlOf(find(handle, 'click'));
|
|
490
520
|
if (!(control instanceof HTMLElement))
|
|
491
521
|
throw new Error(`"${handle}" is not clickable`);
|
|
492
|
-
|
|
522
|
+
if (options.deferSubmit && nativeSubmitter(control)) {
|
|
523
|
+
options.deferSubmit({ execute: async () => {
|
|
524
|
+
// A changed or replaced form/submitter cannot inherit the accepted plan.
|
|
525
|
+
const live = controlOf(find(handle, 'click'));
|
|
526
|
+
if (live !== control)
|
|
527
|
+
throw new Error('Submission target changed');
|
|
528
|
+
control.click();
|
|
529
|
+
} });
|
|
530
|
+
}
|
|
531
|
+
else
|
|
532
|
+
control.click();
|
|
493
533
|
},
|
|
494
534
|
async fill({ handle, text }, _optional = {}) {
|
|
495
|
-
const control = controlOf(find(handle));
|
|
535
|
+
const control = controlOf(find(handle, 'fill'));
|
|
496
536
|
if (isEditableRegion(control)) {
|
|
497
537
|
// A contenteditable region has no `value`; its content *is* its children, and a real
|
|
498
538
|
// editor owns that subtree. See `fillEditableRegion` for why this drives it through
|
|
@@ -518,7 +558,7 @@ export function createDomPageDriver({ root, pages }, options = {}) {
|
|
|
518
558
|
control.dispatchEvent(new Event('change', { bubbles: true }));
|
|
519
559
|
},
|
|
520
560
|
async selectOption({ handle, option }, { selected = true } = {}) {
|
|
521
|
-
const control = controlOf(find(handle));
|
|
561
|
+
const control = controlOf(find(handle, 'selectOption'));
|
|
522
562
|
if (!(control instanceof HTMLSelectElement)) {
|
|
523
563
|
throw new Error(`"${handle}" is not a dropdown`);
|
|
524
564
|
}
|
|
@@ -563,7 +603,7 @@ export function createDomPageDriver({ root, pages }, options = {}) {
|
|
|
563
603
|
control.dispatchEvent(new Event('input', { bubbles: true }));
|
|
564
604
|
control.dispatchEvent(new Event('change', { bubbles: true }));
|
|
565
605
|
},
|
|
566
|
-
async navigate({ page }, _optional = {}) {
|
|
606
|
+
async navigate({ page, ...input }, _optional = {}) {
|
|
567
607
|
// `hasOwnProperty`, not `pages[page]`: a plain object literal inherits everything
|
|
568
608
|
// `Object.prototype` contributes, so a bare lookup answered `navigate("constructor")` with
|
|
569
609
|
// the `Object` constructor — a function the host never published, which this then called,
|
|
@@ -579,7 +619,7 @@ export function createDomPageDriver({ root, pages }, options = {}) {
|
|
|
579
619
|
// applies here too rather than assuming the only caller is the one that already checked.
|
|
580
620
|
if (!published)
|
|
581
621
|
throw new Error(`"${normalizeAgentLabel({ raw: page }).text}" is not a published page`);
|
|
582
|
-
pages[page].navigate(
|
|
622
|
+
return pages[page].navigate(input);
|
|
583
623
|
},
|
|
584
624
|
};
|
|
585
625
|
}
|
|
@@ -634,4 +674,10 @@ export function currentAgentPage({ root }, _optional = {}) {
|
|
|
634
674
|
const tagged = root.querySelector(`[${AGENT_PAGE_ATTRIBUTE}]`);
|
|
635
675
|
return tagged?.getAttribute(AGENT_PAGE_ATTRIBUTE) ?? undefined;
|
|
636
676
|
}
|
|
677
|
+
function publicationState({ state, element, filtered }) {
|
|
678
|
+
return filtered ? { ...state, text: publishedText({ element }) } : state;
|
|
679
|
+
}
|
|
680
|
+
function nativeSubmitter(control) {
|
|
681
|
+
return (control instanceof HTMLButtonElement || control instanceof HTMLInputElement) && control.type === 'submit' && control.form !== null;
|
|
682
|
+
}
|
|
637
683
|
//# sourceMappingURL=dom-page-driver.js.map
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { PagePublication } from '../page-publication.js';
|
|
2
|
+
import { type FieldDescriptor } from '../guards.js';
|
|
3
|
+
/** Rendering/private checks include ancestors, even where checkVisibility is unavailable. */
|
|
4
|
+
export declare function publicElement({ element }: {
|
|
5
|
+
element: Element;
|
|
6
|
+
}, _options?: {}): boolean;
|
|
7
|
+
/** Read only public text nodes. Never clone private/hidden text or form values into a label.
|
|
8
|
+
* O(n) over this already-published region, never the document. */
|
|
9
|
+
export declare function publishedText({ element }: {
|
|
10
|
+
element: Element;
|
|
11
|
+
}, _options?: {}): string;
|
|
12
|
+
/** Snapshot identities and targets once; a re-rendered control needs a fresh publication/binding.
|
|
13
|
+
* O(p × m) snapshot for p manifest entries and m scoped handles; O(depth) checks plus live duplicate detection per operation. */
|
|
14
|
+
export declare function createPublicationFilter({ root, publication, fieldOf }: {
|
|
15
|
+
root: ParentNode & {
|
|
16
|
+
querySelector: Element['querySelector'];
|
|
17
|
+
};
|
|
18
|
+
publication: PagePublication;
|
|
19
|
+
fieldOf: (element: Element) => FieldDescriptor | null;
|
|
20
|
+
}, _options?: {}): {
|
|
21
|
+
allows({ element, action }: {
|
|
22
|
+
element: Element;
|
|
23
|
+
action: string;
|
|
24
|
+
}): boolean;
|
|
25
|
+
};
|
|
26
|
+
//# sourceMappingURL=publication-filter.d.ts.map
|