@jini-ai/agentic 0.3.6 → 0.4.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/CHANGELOG.md +94 -0
- package/README.md +33 -6
- package/dist/core/a2ui/agent-to-renderer.d.ts +3 -1
- package/dist/core/a2ui/agent-to-renderer.js +1 -1
- package/dist/core/a2ui/catalog.d.ts +14 -5
- package/dist/core/a2ui/catalog.js +5 -5
- package/dist/core/a2ui/common-types.d.ts +11 -3
- package/dist/core/a2ui/common-types.js +5 -3
- package/dist/core/a2ui/index.d.ts +1 -1
- package/dist/core/a2ui/index.js +1 -1
- package/dist/core/a2ui/interpreter.d.ts +45 -10
- package/dist/core/a2ui/interpreter.js +38 -43
- package/dist/core/a2ui/json-pointer.d.ts +16 -4
- package/dist/core/a2ui/json-pointer.js +7 -7
- package/dist/core/a2ui/renderer-to-agent.d.ts +22 -8
- package/dist/core/a2ui/renderer-to-agent.js +5 -5
- package/dist/core/a2ui/resolve.d.ts +7 -2
- package/dist/core/a2ui/resolve.js +10 -9
- package/dist/core/a2ui/tree.d.ts +8 -2
- package/dist/core/a2ui/tree.js +2 -2
- package/dist/core/ag-ui.d.ts +17 -9
- package/dist/core/ag-ui.js +4 -4
- package/dist/core/capability.d.ts +12 -3
- package/dist/core/capability.js +3 -3
- package/dist/core/dom/dom-page-driver.d.ts +8 -4
- package/dist/core/dom/dom-page-driver.js +47 -26
- package/dist/core/dom/index.d.ts +3 -3
- package/dist/core/dom/index.js +1 -1
- package/dist/core/dom/model-context.d.ts +18 -8
- package/dist/core/dom/model-context.js +12 -15
- package/dist/core/dom/native-model-context.d.ts +6 -0
- package/dist/core/dom/native-model-context.js +19 -0
- package/dist/core/element-handles.d.ts +12 -2
- package/dist/core/element-handles.js +9 -3
- package/dist/core/gen-ui/encoder.d.ts +21 -11
- package/dist/core/gen-ui/encoder.js +8 -7
- package/dist/core/gen-ui/events.d.ts +6 -5
- package/dist/core/gen-ui/events.js +6 -5
- package/dist/core/gen-ui/index.d.ts +1 -1
- package/dist/core/gen-ui/index.js +1 -1
- package/dist/core/guards.d.ts +17 -5
- package/dist/core/guards.js +6 -6
- package/dist/core/handle.d.ts +12 -5
- package/dist/core/handle.js +9 -8
- package/dist/core/index.d.ts +3 -2
- package/dist/core/index.js +3 -2
- package/dist/core/list-handles.d.ts +4 -1
- package/dist/core/list-handles.js +1 -1
- package/dist/core/mcp-ui-apps.d.ts +39 -9
- package/dist/core/mcp-ui-apps.js +10 -8
- package/dist/core/messages.d.ts +6 -0
- package/dist/core/messages.js +6 -0
- package/dist/core/page-capabilities.d.ts +0 -11
- package/dist/core/page-capabilities.js +13 -1
- package/dist/core/page-driver.d.ts +32 -11
- package/dist/core/page-executor.d.ts +8 -2
- package/dist/core/page-executor.js +31 -31
- package/dist/core/webmcp.d.ts +27 -8
- package/dist/core/webmcp.js +14 -14
- package/dist/index.d.ts +30 -0
- package/dist/index.js +30 -0
- package/dist/skills/install/archive.d.ts +8 -0
- package/dist/skills/install/archive.js +47 -0
- package/dist/skills/install/fetch-adapter.d.ts +6 -0
- package/dist/skills/install/fetch-adapter.js +6 -0
- package/dist/skills/install/github.d.ts +21 -0
- package/dist/skills/install/github.js +92 -0
- package/dist/skills/install/index.d.ts +11 -0
- package/dist/skills/install/index.js +11 -0
- package/dist/skills/install/install-service.d.ts +44 -0
- package/dist/skills/install/install-service.js +121 -0
- package/dist/skills/install/layout.d.ts +13 -0
- package/dist/skills/install/layout.js +22 -0
- package/dist/skills/install/live-registration.d.ts +61 -0
- package/dist/skills/install/live-registration.js +64 -0
- package/dist/skills/install/node-filesystem.d.ts +4 -0
- package/dist/skills/install/node-filesystem.js +41 -0
- package/dist/skills/install/ports.d.ts +101 -0
- package/dist/skills/install/ports.js +2 -0
- package/dist/skills/install/state.d.ts +13 -0
- package/dist/skills/install/state.js +23 -0
- package/dist/skills/install/validation.d.ts +45 -0
- package/dist/skills/install/validation.js +104 -0
- package/package.json +19 -3
- package/dist/a2ui/agent-to-renderer.d.ts.map +0 -1
- package/dist/a2ui/agent-to-renderer.js.map +0 -1
- package/dist/a2ui/catalog.d.ts.map +0 -1
- package/dist/a2ui/catalog.js.map +0 -1
- package/dist/a2ui/common-types.d.ts.map +0 -1
- package/dist/a2ui/common-types.js.map +0 -1
- package/dist/a2ui/index.d.ts.map +0 -1
- package/dist/a2ui/index.js.map +0 -1
- package/dist/a2ui/interpreter.d.ts.map +0 -1
- package/dist/a2ui/interpreter.js.map +0 -1
- package/dist/a2ui/json-pointer.d.ts.map +0 -1
- package/dist/a2ui/json-pointer.js.map +0 -1
- package/dist/a2ui/renderer-to-agent.d.ts.map +0 -1
- package/dist/a2ui/renderer-to-agent.js.map +0 -1
- package/dist/a2ui/resolve.d.ts.map +0 -1
- package/dist/a2ui/resolve.js.map +0 -1
- package/dist/a2ui/tree.d.ts.map +0 -1
- package/dist/a2ui/tree.js.map +0 -1
- package/dist/ag-ui.d.ts.map +0 -1
- package/dist/ag-ui.js.map +0 -1
- package/dist/agui/encoder.d.ts.map +0 -1
- package/dist/agui/encoder.js.map +0 -1
- package/dist/agui/events.d.ts.map +0 -1
- package/dist/agui/events.js.map +0 -1
- package/dist/capability.d.ts.map +0 -1
- package/dist/capability.js.map +0 -1
- 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/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/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/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/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/webmcp.d.ts.map +0 -1
- package/dist/core/webmcp.js.map +0 -1
- package/dist/dom/dom-page-driver.d.ts.map +0 -1
- package/dist/dom/dom-page-driver.js.map +0 -1
- package/dist/dom/index.d.ts.map +0 -1
- package/dist/dom/index.js.map +0 -1
- package/dist/dom/model-context.d.ts.map +0 -1
- package/dist/dom/model-context.js.map +0 -1
- package/dist/element-handles.d.ts.map +0 -1
- package/dist/element-handles.js.map +0 -1
- package/dist/gen-ui/encoder.d.ts.map +0 -1
- package/dist/gen-ui/encoder.js.map +0 -1
- package/dist/gen-ui/events.d.ts.map +0 -1
- package/dist/gen-ui/events.js.map +0 -1
- package/dist/gen-ui/index.d.ts.map +0 -1
- package/dist/gen-ui/index.js.map +0 -1
- package/dist/guards.d.ts.map +0 -1
- package/dist/guards.js.map +0 -1
- package/dist/handle.d.ts.map +0 -1
- package/dist/handle.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/mcp-ui-apps.d.ts.map +0 -1
- package/dist/mcp-ui-apps.js.map +0 -1
- package/dist/mcp-ui.d.ts.map +0 -1
- package/dist/mcp-ui.js.map +0 -1
- package/dist/page-capabilities.d.ts.map +0 -1
- package/dist/page-capabilities.js.map +0 -1
- package/dist/page-driver.d.ts.map +0 -1
- package/dist/page-driver.js.map +0 -1
- package/dist/page-executor.d.ts.map +0 -1
- package/dist/page-executor.js.map +0 -1
- package/dist/webmcp.d.ts.map +0 -1
- package/dist/webmcp.js.map +0 -1
package/dist/core/capability.js
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* @param id - Capability id to resolve.
|
|
18
18
|
* @returns The definition, or `undefined` when the id is not in the manifest.
|
|
19
19
|
*/
|
|
20
|
-
export function findCapability(capabilities, id) {
|
|
20
|
+
export function findCapability({ capabilities, id }, _optional = {}) {
|
|
21
21
|
return capabilities.find((capability) => capability.id === id);
|
|
22
22
|
}
|
|
23
23
|
/**
|
|
@@ -33,7 +33,7 @@ export function findCapability(capabilities, id) {
|
|
|
33
33
|
* @param input - Raw caller-supplied arguments.
|
|
34
34
|
* @returns An error message, or `null` when the input is acceptable.
|
|
35
35
|
*/
|
|
36
|
-
export function findCapabilityInputError(capability, input) {
|
|
36
|
+
export function findCapabilityInputError({ capability, input }, _optional = {}) {
|
|
37
37
|
const { properties, required, additionalProperties } = capability.inputSchema;
|
|
38
38
|
for (const name of required ?? []) {
|
|
39
39
|
if (input[name] === undefined)
|
|
@@ -73,7 +73,7 @@ export function findCapabilityInputError(capability, input) {
|
|
|
73
73
|
* @param hasSession - Whether a live frontend session is attached.
|
|
74
74
|
* @returns Only the capabilities that can actually be satisfied right now.
|
|
75
75
|
*/
|
|
76
|
-
export function availableCapabilities(capabilities, hasSession) {
|
|
76
|
+
export function availableCapabilities({ capabilities, hasSession }, _optional = {}) {
|
|
77
77
|
return hasSession ? capabilities : capabilities.filter((c) => c.surface === 'server');
|
|
78
78
|
}
|
|
79
79
|
//# sourceMappingURL=capability.js.map
|
|
@@ -4,15 +4,17 @@ export interface DomPageDriverPage {
|
|
|
4
4
|
/** Shown to a caller by `page.find_elements`/`page.navigate`'s refusal message — see
|
|
5
5
|
* `PageSummary.label` for why this exists at all. */
|
|
6
6
|
readonly label: string;
|
|
7
|
-
readonly navigate: () => void;
|
|
7
|
+
readonly navigate: (required: Record<string, never>) => void;
|
|
8
8
|
}
|
|
9
|
-
export interface
|
|
9
|
+
export interface DomPageDriverRequired {
|
|
10
10
|
/** The subtree to expose. Never pass `document`. */
|
|
11
11
|
readonly root: ParentNode & {
|
|
12
12
|
querySelector: Element['querySelector'];
|
|
13
13
|
};
|
|
14
14
|
/** Page ids this driver may navigate to, each with its label and how to get there. */
|
|
15
15
|
readonly pages: Readonly<Record<string, DomPageDriverPage>>;
|
|
16
|
+
}
|
|
17
|
+
export interface DomPageDriverOptions {
|
|
16
18
|
/**
|
|
17
19
|
* The id of the page currently shown, reported on every element.
|
|
18
20
|
*
|
|
@@ -30,7 +32,9 @@ export interface DomPageDriverOptions {
|
|
|
30
32
|
* @param options - The subtree, the navigable pages, and the current page id.
|
|
31
33
|
* @returns A driver ready to hand to `executePageCapability`.
|
|
32
34
|
*/
|
|
33
|
-
export declare function createDomPageDriver(
|
|
35
|
+
export declare function createDomPageDriver({ root, pages }: DomPageDriverRequired, options?: DomPageDriverOptions): PageDriver;
|
|
34
36
|
/** Reads the current page's `data-agent-page`, for hosts that tag the body. */
|
|
35
|
-
export declare function currentAgentPage(root
|
|
37
|
+
export declare function currentAgentPage({ root }: {
|
|
38
|
+
root: ParentNode;
|
|
39
|
+
}, _optional?: Record<string, never>): string | undefined;
|
|
36
40
|
//# sourceMappingURL=dom-page-driver.d.ts.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AGENT_ELEMENT_ATTRIBUTE, AGENT_LABEL_ATTRIBUTE, AGENT_PAGE_ATTRIBUTE, AGENT_ROLE_ATTRIBUTE, AGENT_ELEMENT_ROLES, resolveHandleSelector, } from '../element-handles.js';
|
|
1
|
+
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
2
|
import { normalizeAgentLabel } from '../guards.js';
|
|
3
3
|
/**
|
|
4
4
|
* A {@link PageDriver} over a real DOM subtree.
|
|
@@ -178,10 +178,30 @@ function disabledOf(control) {
|
|
|
178
178
|
? control.matches(':disabled')
|
|
179
179
|
: undefined;
|
|
180
180
|
}
|
|
181
|
+
const PRIVATE_SELECTOR = `[${AGENT_PRIVATE_ATTRIBUTE}]`;
|
|
182
|
+
/** Whether `node` is inside (or is) a `[data-agent-private]` subtree. @complexity O(depth). */
|
|
183
|
+
function isPrivate(node) {
|
|
184
|
+
return node.closest(PRIVATE_SELECTOR) !== null;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* `element`'s text content with every `[data-agent-private]` subtree left out — the only text
|
|
188
|
+
* this driver ever reports, so a secret shown inside a published card never rides out on the
|
|
189
|
+
* card's own text. @complexity O(subtree size).
|
|
190
|
+
*/
|
|
191
|
+
function publicTextOf(element) {
|
|
192
|
+
if (element.querySelector(PRIVATE_SELECTOR) === null) {
|
|
193
|
+
/* c8 ignore next -- `Node.textContent` is typed nullable for the abstract node; on an Element it is always a string, so the `?? ''` satisfies the type and is not a reachable path. */
|
|
194
|
+
return element.textContent ?? '';
|
|
195
|
+
}
|
|
196
|
+
const copy = element.cloneNode(true);
|
|
197
|
+
for (const hidden of Array.from(copy.querySelectorAll(PRIVATE_SELECTOR)))
|
|
198
|
+
hidden.remove();
|
|
199
|
+
/* c8 ignore next -- as above. */
|
|
200
|
+
return copy.textContent ?? '';
|
|
201
|
+
}
|
|
181
202
|
function describe(element, page) {
|
|
182
203
|
const role = element.getAttribute(AGENT_ROLE_ATTRIBUTE);
|
|
183
|
-
|
|
184
|
-
const text = element.textContent ?? '';
|
|
204
|
+
const text = publicTextOf(element);
|
|
185
205
|
// Live text is a fine fallback label for an ordinary element — it is the page's own ontology,
|
|
186
206
|
// rendered openly. For an editable region it is not: a contenteditable's content is the *user's
|
|
187
207
|
// data*, so falling back to it published the contents of a rich-text field to every
|
|
@@ -208,8 +228,7 @@ function describe(element, page) {
|
|
|
208
228
|
* @param options - The subtree, the navigable pages, and the current page id.
|
|
209
229
|
* @returns A driver ready to hand to `executePageCapability`.
|
|
210
230
|
*/
|
|
211
|
-
export function createDomPageDriver(options) {
|
|
212
|
-
const { root, pages } = options;
|
|
231
|
+
export function createDomPageDriver({ root, pages }, options = {}) {
|
|
213
232
|
/**
|
|
214
233
|
* The page a specific element belongs to — its own nearest `[data-agent-page]` ancestor, not a
|
|
215
234
|
* single document-wide guess.
|
|
@@ -237,7 +256,8 @@ export function createDomPageDriver(options) {
|
|
|
237
256
|
* publishes the same handle twice makes `find`'s single-match resolution ambiguous — surfaced
|
|
238
257
|
* here so both callers below can refuse rather than silently pick one.
|
|
239
258
|
*/
|
|
240
|
-
const findAll = (handle) => Array.from(root.querySelectorAll(resolveHandleSelector(handle)))
|
|
259
|
+
const findAll = (handle) => Array.from(root.querySelectorAll(resolveHandleSelector({ handle })))
|
|
260
|
+
.filter((element) => !isPrivate(element));
|
|
241
261
|
/**
|
|
242
262
|
* More than one element answers to the same handle — a page-authoring bug (duplicate
|
|
243
263
|
* `data-agent-element`), not something a caller passing that handle can resolve on its own.
|
|
@@ -284,14 +304,16 @@ export function createDomPageDriver(options) {
|
|
|
284
304
|
// `<li><label><input>` this descent exists for. Filtering to descendants whose nearest
|
|
285
305
|
// published ancestor is still `element` itself excludes exactly that case while leaving
|
|
286
306
|
// ordinary wrapper descent untouched.
|
|
287
|
-
const owned = (node) => node.closest(`[${AGENT_ELEMENT_ATTRIBUTE}]`) === element
|
|
307
|
+
const owned = (node) => node.closest(`[${AGENT_ELEMENT_ATTRIBUTE}]`) === element
|
|
308
|
+
&& !isPrivate(node);
|
|
288
309
|
const candidate = Array.from(element.querySelectorAll('input, textarea, select, button, a, summary'))
|
|
289
310
|
.find(owned);
|
|
290
311
|
return candidate ?? element;
|
|
291
312
|
};
|
|
292
313
|
return {
|
|
293
|
-
async findElements(filter) {
|
|
314
|
+
async findElements(_required, filter = {}) {
|
|
294
315
|
const found = Array.from(root.querySelectorAll(`[${AGENT_ELEMENT_ATTRIBUTE}]`))
|
|
316
|
+
.filter((element) => !isPrivate(element))
|
|
295
317
|
.map((element) => describe(element, pageOf(element)))
|
|
296
318
|
.filter((element) => element.handle.length > 0);
|
|
297
319
|
const query = filter.query?.toLowerCase();
|
|
@@ -304,16 +326,16 @@ export function createDomPageDriver(options) {
|
|
|
304
326
|
|| element.label.toLowerCase().includes(query);
|
|
305
327
|
});
|
|
306
328
|
},
|
|
307
|
-
async listPages() {
|
|
329
|
+
async listPages(_required, _optional = {}) {
|
|
308
330
|
// `Object.entries`, same own-enumerable-keys-only guarantee `Object.keys` gives `navigate`'s
|
|
309
331
|
// own `hasOwnProperty` check above — no risk of a `pages.label`/`pages.navigate`-shaped
|
|
310
332
|
// prototype entry leaking in as a fake page id.
|
|
311
333
|
return Object.entries(pages).map(([id, page]) => ({ id, label: page.label }));
|
|
312
334
|
},
|
|
313
|
-
async describeField(handle) {
|
|
335
|
+
async describeField({ handle }, _optional = {}) {
|
|
314
336
|
return fieldDescriptorOf(controlOf(find(handle)));
|
|
315
337
|
},
|
|
316
|
-
async describeState(handle) {
|
|
338
|
+
async describeState({ handle }, _optional = {}) {
|
|
317
339
|
// Unlike every other method here, a handle that no longer resolves is an answer rather than
|
|
318
340
|
// an error: an element that a click removed is exactly what the caller is asking about. A
|
|
319
341
|
// handle resolving to *more than one* element is a different situation entirely — not an
|
|
@@ -348,8 +370,7 @@ export function createDomPageDriver(options) {
|
|
|
348
370
|
const value = field !== null
|
|
349
371
|
? control.value
|
|
350
372
|
: dropdown?.value;
|
|
351
|
-
|
|
352
|
-
const text = element.textContent ?? '';
|
|
373
|
+
const text = publicTextOf(element);
|
|
353
374
|
return {
|
|
354
375
|
text,
|
|
355
376
|
// A contenteditable region has no `.value`; its content IS its value, so `text` is the
|
|
@@ -380,7 +401,7 @@ export function createDomPageDriver(options) {
|
|
|
380
401
|
* would hang for the whole life of a backgrounded tab; without the frames every write would
|
|
381
402
|
* report its own target unchanged, because the read would beat the render.
|
|
382
403
|
*/
|
|
383
|
-
async settle() {
|
|
404
|
+
async settle(_required, _optional = {}) {
|
|
384
405
|
await new Promise((resolve) => {
|
|
385
406
|
let timer;
|
|
386
407
|
// No re-entry guard: whichever side loses the race calls this again, and both of its
|
|
@@ -400,7 +421,7 @@ export function createDomPageDriver(options) {
|
|
|
400
421
|
raf(() => raf(finish));
|
|
401
422
|
});
|
|
402
423
|
},
|
|
403
|
-
async highlight(handle, durationMs) {
|
|
424
|
+
async highlight({ handle, durationMs }, _optional = {}) {
|
|
404
425
|
const element = find(handle);
|
|
405
426
|
// Same refusal as `click()`, for the same reason: an SVG (or other non-HTMLElement) target
|
|
406
427
|
// has no `.style` to draw an outline on, so silently returning here drew nothing while
|
|
@@ -426,16 +447,16 @@ export function createDomPageDriver(options) {
|
|
|
426
447
|
}, durationMs);
|
|
427
448
|
highlights.set(handle, { timer, restore });
|
|
428
449
|
},
|
|
429
|
-
async scrollTo(handle) {
|
|
450
|
+
async scrollTo({ handle }, _optional = {}) {
|
|
430
451
|
find(handle).scrollIntoView({ behavior: 'smooth', block: 'center' });
|
|
431
452
|
},
|
|
432
|
-
async click(handle) {
|
|
453
|
+
async click({ handle }, _optional = {}) {
|
|
433
454
|
const control = controlOf(find(handle));
|
|
434
455
|
if (!(control instanceof HTMLElement))
|
|
435
456
|
throw new Error(`"${handle}" is not clickable`);
|
|
436
457
|
control.click();
|
|
437
458
|
},
|
|
438
|
-
async fill(handle, text) {
|
|
459
|
+
async fill({ handle, text }, _optional = {}) {
|
|
439
460
|
const control = controlOf(find(handle));
|
|
440
461
|
if (isEditableRegion(control)) {
|
|
441
462
|
// A contenteditable region has no `value`; its content *is* its children, and a real
|
|
@@ -461,7 +482,7 @@ export function createDomPageDriver(options) {
|
|
|
461
482
|
control.dispatchEvent(new Event('input', { bubbles: true }));
|
|
462
483
|
control.dispatchEvent(new Event('change', { bubbles: true }));
|
|
463
484
|
},
|
|
464
|
-
async selectOption(handle, option, selected = true) {
|
|
485
|
+
async selectOption({ handle, option }, { selected = true } = {}) {
|
|
465
486
|
const control = controlOf(find(handle));
|
|
466
487
|
if (!(control instanceof HTMLSelectElement)) {
|
|
467
488
|
throw new Error(`"${handle}" is not a dropdown`);
|
|
@@ -496,8 +517,8 @@ export function createDomPageDriver(options) {
|
|
|
496
517
|
// the same shape of problem regardless of which side authored it. `handle` needs no
|
|
497
518
|
// treatment: it is already validated ASCII, length-capped by isValidElementHandle before
|
|
498
519
|
// this driver is ever called.
|
|
499
|
-
const safeOption = normalizeAgentLabel(option).text;
|
|
500
|
-
const available = options.map((entry) => normalizeAgentLabel(entry.text.trim()).text)
|
|
520
|
+
const safeOption = normalizeAgentLabel({ raw: option }).text;
|
|
521
|
+
const available = options.map((entry) => normalizeAgentLabel({ raw: entry.text.trim() }).text)
|
|
501
522
|
.filter((text) => text.length > 0);
|
|
502
523
|
throw new Error(`"${safeOption}" is not an option of "${handle}". Available: ${available.length > 0 ? available.join(', ') : '(none)'}`);
|
|
503
524
|
}
|
|
@@ -513,7 +534,7 @@ export function createDomPageDriver(options) {
|
|
|
513
534
|
// ignoring this would tell the caller a deselect happened when nothing changed, and clearing
|
|
514
535
|
// the control would invent a third state (no selection) that a native <select> cannot hold.
|
|
515
536
|
throw new Error(`"${handle}" is a single-select; its choice cannot be removed, only replaced — `
|
|
516
|
-
+ `select a different option instead of deselecting "${normalizeAgentLabel(option).text}"`);
|
|
537
|
+
+ `select a different option instead of deselecting "${normalizeAgentLabel({ raw: option }).text}"`);
|
|
517
538
|
}
|
|
518
539
|
else {
|
|
519
540
|
// Same prototype-setter dance as `fill`, for the same reason: React tracks the previous
|
|
@@ -527,7 +548,7 @@ export function createDomPageDriver(options) {
|
|
|
527
548
|
control.dispatchEvent(new Event('input', { bubbles: true }));
|
|
528
549
|
control.dispatchEvent(new Event('change', { bubbles: true }));
|
|
529
550
|
},
|
|
530
|
-
async navigate(page) {
|
|
551
|
+
async navigate({ page }, _optional = {}) {
|
|
531
552
|
// `hasOwnProperty`, not `pages[page]`: a plain object literal inherits everything
|
|
532
553
|
// `Object.prototype` contributes, so a bare lookup answered `navigate("constructor")` with
|
|
533
554
|
// the `Object` constructor — a function the host never published, which this then called,
|
|
@@ -542,8 +563,8 @@ export function createDomPageDriver(options) {
|
|
|
542
563
|
// the executor entirely, hands `page` in unsanitized, so the same bound-and-strip treatment
|
|
543
564
|
// applies here too rather than assuming the only caller is the one that already checked.
|
|
544
565
|
if (!published)
|
|
545
|
-
throw new Error(`"${normalizeAgentLabel(page).text}" is not a published page`);
|
|
546
|
-
pages[page].navigate();
|
|
566
|
+
throw new Error(`"${normalizeAgentLabel({ raw: page }).text}" is not a published page`);
|
|
567
|
+
pages[page].navigate({});
|
|
547
568
|
},
|
|
548
569
|
};
|
|
549
570
|
}
|
|
@@ -594,7 +615,7 @@ function fillEditableRegion(control, text) {
|
|
|
594
615
|
control.dispatchEvent(new Event('input', { bubbles: true }));
|
|
595
616
|
}
|
|
596
617
|
/** Reads the current page's `data-agent-page`, for hosts that tag the body. */
|
|
597
|
-
export function currentAgentPage(root) {
|
|
618
|
+
export function currentAgentPage({ root }, _optional = {}) {
|
|
598
619
|
const tagged = root.querySelector(`[${AGENT_PAGE_ATTRIBUTE}]`);
|
|
599
620
|
return tagged?.getAttribute(AGENT_PAGE_ATTRIBUTE) ?? undefined;
|
|
600
621
|
}
|
package/dist/core/dom/index.d.ts
CHANGED
|
@@ -3,15 +3,15 @@
|
|
|
3
3
|
*
|
|
4
4
|
* The one `PageDriver` (see `@jini-ai/agentic`'s `page-driver.ts`) that reads and writes a real DOM
|
|
5
5
|
* subtree. Split into its own entry point, compiled under its own `DOM`-lib `tsconfig.dom.json`,
|
|
6
|
-
* so the rest of this package can stay provably DOM-free — see
|
|
6
|
+
* so the rest of this package can stay provably DOM-free — see archived provenance ledger's "The DOM split".
|
|
7
7
|
*
|
|
8
8
|
* `@jini-ai/chat-react` is this package's one in-repo consumer today.
|
|
9
9
|
*/
|
|
10
|
-
export { createDomPageDriver, currentAgentPage, type DomPageDriverOptions, type DomPageDriverPage, } from './dom-page-driver.js';
|
|
10
|
+
export { createDomPageDriver, currentAgentPage, type DomPageDriverRequired, type DomPageDriverOptions, type DomPageDriverPage, } from './dom-page-driver.js';
|
|
11
11
|
/**
|
|
12
12
|
* WebMCP feature detection — moved 2026-07-26 from `@jini-ai/ui`'s `agent-tools/model-context.ts`
|
|
13
13
|
* (plan §8 step 6). See `model-context.ts`'s module doc for why it lives here rather than
|
|
14
14
|
* alongside `../webmcp.ts`'s DOM-free projection.
|
|
15
15
|
*/
|
|
16
|
-
export { getAgentModelContext, type AgentModelContextLike, type AgentModelContextToolRegistration, } from './model-context.js';
|
|
16
|
+
export { getAgentModelContext, type AgentModelContextLike, type ModelContextHostPort, type AgentModelContextRegisterToolOptions, type AgentModelContextToolRegistration, } from './model-context.js';
|
|
17
17
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/core/dom/index.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* The one `PageDriver` (see `@jini-ai/agentic`'s `page-driver.ts`) that reads and writes a real DOM
|
|
5
5
|
* subtree. Split into its own entry point, compiled under its own `DOM`-lib `tsconfig.dom.json`,
|
|
6
|
-
* so the rest of this package can stay provably DOM-free — see
|
|
6
|
+
* so the rest of this package can stay provably DOM-free — see archived provenance ledger's "The DOM split".
|
|
7
7
|
*
|
|
8
8
|
* `@jini-ai/chat-react` is this package's one in-repo consumer today.
|
|
9
9
|
*/
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @module dom/model-context
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* `document.modelContext`,
|
|
4
|
+
* Host-injected access to the browser's (draft) WebMCP surface —
|
|
5
|
+
* the host supplies `document.modelContext`, followed by the deprecated `navigator.modelContext`
|
|
6
6
|
* alias (the spec moved the getter from Navigator to Document in 2026;
|
|
7
7
|
* see the polyfill ecosystem's own back-compat posture). No `@mcp-b/*` or
|
|
8
8
|
* other WebMCP package dependency: this module only needs the shape, the
|
|
@@ -11,11 +11,11 @@
|
|
|
11
11
|
* bridges already use.
|
|
12
12
|
* A page that wants `document.modelContext` to actually exist in a browser
|
|
13
13
|
* without native support must load a real polyfill itself (e.g.
|
|
14
|
-
* `@mcp-b/webmcp-polyfill`) — this module only
|
|
14
|
+
* `@mcp-b/webmcp-polyfill`) — this module adapts only the candidates the host supplies.
|
|
15
15
|
*
|
|
16
16
|
* Moved 2026-07-26 from `@jini-ai/ui/src/features/agent-tools/model-context.ts` (plan §4/§8 step 6).
|
|
17
17
|
* Lives under `src/dom/`, not alongside `../webmcp.ts`'s pure `CapabilityDef` → WebMCP-tool
|
|
18
|
-
* projection, because it
|
|
18
|
+
* projection, because it adapts the native browser API — `webmcp.ts`'s own module doc is explicit
|
|
19
19
|
* that "that detection is deliberately NOT here: it touches browser globals, and this package
|
|
20
20
|
* holds none," which is exactly the DOM-free guarantee `src/dom/` exists to carve an exception
|
|
21
21
|
* for. See `dom/index.ts`'s re-export of this module.
|
|
@@ -56,14 +56,24 @@ export interface AgentModelContextLike {
|
|
|
56
56
|
* ModelContextRegisterToolOptions options = {})` — it is **async**. Callers must not assume it
|
|
57
57
|
* has taken effect synchronously, and must not let a rejection escape.
|
|
58
58
|
*/
|
|
59
|
-
registerTool(
|
|
59
|
+
registerTool(required: {
|
|
60
|
+
tool: AgentModelContextToolRegistration;
|
|
61
|
+
}, options?: AgentModelContextRegisterToolOptions): Promise<void>;
|
|
60
62
|
/**
|
|
61
63
|
* NOT in the spec — the draft's only unregistration mechanism is aborting the `signal` passed to
|
|
62
64
|
* `registerTool`. Kept optional purely so a polyfill that happens to expose one can be used;
|
|
63
65
|
* never rely on its presence, and always pass a `signal` as the real cleanup path.
|
|
64
66
|
*/
|
|
65
|
-
unregisterTool?(
|
|
67
|
+
unregisterTool?(required: {
|
|
68
|
+
name: string;
|
|
69
|
+
}, _optional?: Record<string, never>): void;
|
|
66
70
|
}
|
|
67
|
-
/**
|
|
68
|
-
export
|
|
71
|
+
/** Ordered host candidates: modern document first, then any deprecated navigator alias. */
|
|
72
|
+
export interface ModelContextHostPort {
|
|
73
|
+
candidates(required: Record<string, never>): readonly unknown[];
|
|
74
|
+
}
|
|
75
|
+
/** Adapts the first installed native surface to Jini's argument-object port. */
|
|
76
|
+
export declare function getAgentModelContext({ host }: {
|
|
77
|
+
host: ModelContextHostPort;
|
|
78
|
+
}, _optional?: Record<string, never>): AgentModelContextLike | undefined;
|
|
69
79
|
//# sourceMappingURL=model-context.d.ts.map
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @module dom/model-context
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* `document.modelContext`,
|
|
4
|
+
* Host-injected access to the browser's (draft) WebMCP surface —
|
|
5
|
+
* the host supplies `document.modelContext`, followed by the deprecated `navigator.modelContext`
|
|
6
6
|
* alias (the spec moved the getter from Navigator to Document in 2026;
|
|
7
7
|
* see the polyfill ecosystem's own back-compat posture). No `@mcp-b/*` or
|
|
8
8
|
* other WebMCP package dependency: this module only needs the shape, the
|
|
@@ -11,11 +11,11 @@
|
|
|
11
11
|
* bridges already use.
|
|
12
12
|
* A page that wants `document.modelContext` to actually exist in a browser
|
|
13
13
|
* without native support must load a real polyfill itself (e.g.
|
|
14
|
-
* `@mcp-b/webmcp-polyfill`) — this module only
|
|
14
|
+
* `@mcp-b/webmcp-polyfill`) — this module adapts only the candidates the host supplies.
|
|
15
15
|
*
|
|
16
16
|
* Moved 2026-07-26 from `@jini-ai/ui/src/features/agent-tools/model-context.ts` (plan §4/§8 step 6).
|
|
17
17
|
* Lives under `src/dom/`, not alongside `../webmcp.ts`'s pure `CapabilityDef` → WebMCP-tool
|
|
18
|
-
* projection, because it
|
|
18
|
+
* projection, because it adapts the native browser API — `webmcp.ts`'s own module doc is explicit
|
|
19
19
|
* that "that detection is deliberately NOT here: it touches browser globals, and this package
|
|
20
20
|
* holds none," which is exactly the DOM-free guarantee `src/dom/` exists to carve an exception
|
|
21
21
|
* for. See `dom/index.ts`'s re-export of this module.
|
|
@@ -28,17 +28,14 @@
|
|
|
28
28
|
* fixture: a raw (non-`toWebMcpTool`) registration carrying a `title` failed TypeScript's
|
|
29
29
|
* excess-property check against the un-widened type here.
|
|
30
30
|
*/
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
const nav = globalThis.navigator;
|
|
40
|
-
if (isModelContext(nav?.modelContext))
|
|
41
|
-
return nav.modelContext;
|
|
31
|
+
import { adaptNativeModelContext } from './native-model-context.js';
|
|
32
|
+
/** Adapts the first installed native surface to Jini's argument-object port. */
|
|
33
|
+
export function getAgentModelContext({ host }, _optional = {}) {
|
|
34
|
+
for (const value of host.candidates({})) {
|
|
35
|
+
const context = adaptNativeModelContext({ value });
|
|
36
|
+
if (context)
|
|
37
|
+
return context;
|
|
38
|
+
}
|
|
42
39
|
return undefined;
|
|
43
40
|
}
|
|
44
41
|
//# sourceMappingURL=model-context.js.map
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { AgentModelContextLike } from './model-context.js';
|
|
2
|
+
/** Preserve native receiver binding and stable port identity across feature detection. */
|
|
3
|
+
export declare function adaptNativeModelContext({ value }: {
|
|
4
|
+
value: unknown;
|
|
5
|
+
}): AgentModelContextLike | undefined;
|
|
6
|
+
//# sourceMappingURL=native-model-context.d.ts.map
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const adapters = new WeakMap();
|
|
2
|
+
/** Preserve native receiver binding and stable port identity across feature detection. */
|
|
3
|
+
export function adaptNativeModelContext({ value }) {
|
|
4
|
+
if (typeof value !== 'object' || value === null || typeof value.registerTool !== 'function')
|
|
5
|
+
return undefined;
|
|
6
|
+
const existing = adapters.get(value);
|
|
7
|
+
if (existing)
|
|
8
|
+
return existing;
|
|
9
|
+
const native = value;
|
|
10
|
+
const adapter = {
|
|
11
|
+
registerTool: ({ tool }, options) => native.registerTool(tool, options),
|
|
12
|
+
...(typeof native.unregisterTool === 'function'
|
|
13
|
+
? { unregisterTool: ({ name }) => native.unregisterTool(name) }
|
|
14
|
+
: {}),
|
|
15
|
+
};
|
|
16
|
+
adapters.set(value, adapter);
|
|
17
|
+
return adapter;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=native-model-context.js.map
|
|
@@ -13,6 +13,12 @@ export declare const AGENT_ELEMENT_ATTRIBUTE = "data-agent-element";
|
|
|
13
13
|
export declare const AGENT_ROLE_ATTRIBUTE = "data-agent-role";
|
|
14
14
|
export declare const AGENT_LABEL_ATTRIBUTE = "data-agent-label";
|
|
15
15
|
export declare const AGENT_PAGE_ATTRIBUTE = "data-agent-page";
|
|
16
|
+
/**
|
|
17
|
+
* Marks a subtree the page driver must treat as absent: nothing inside it is published, adopted
|
|
18
|
+
* as a wrapper's control, or counted in any ancestor's text. For a secret the page shows a human
|
|
19
|
+
* (a revealed key), since a published ancestor's state otherwise reports its whole text content.
|
|
20
|
+
*/
|
|
21
|
+
export declare const AGENT_PRIVATE_ATTRIBUTE = "data-agent-private";
|
|
16
22
|
/** What verb applies to a tagged element. Mirrors the convention documented in the sample markup. */
|
|
17
23
|
export type AgentElementRole = 'button' | 'checkbox' | 'field' | 'form' | 'list' | 'status' | 'region' | 'link';
|
|
18
24
|
export declare const AGENT_ELEMENT_ROLES: readonly AgentElementRole[];
|
|
@@ -22,7 +28,9 @@ export declare const AGENT_ELEMENT_ROLES: readonly AgentElementRole[];
|
|
|
22
28
|
* @param handle - Candidate handle, typically caller-supplied.
|
|
23
29
|
* @returns True when it is safe to interpolate into an attribute selector.
|
|
24
30
|
*/
|
|
25
|
-
export declare function isValidElementHandle(handle
|
|
31
|
+
export declare function isValidElementHandle({ handle }: {
|
|
32
|
+
handle: string;
|
|
33
|
+
}, _optional?: Record<string, never>): boolean;
|
|
26
34
|
/**
|
|
27
35
|
* Builds the one selector shape this system will ever resolve.
|
|
28
36
|
*
|
|
@@ -30,7 +38,9 @@ export declare function isValidElementHandle(handle: string): boolean;
|
|
|
30
38
|
* @returns The attribute selector for that handle.
|
|
31
39
|
* @throws If the handle is not valid — never fall back to treating it as a raw selector.
|
|
32
40
|
*/
|
|
33
|
-
export declare function resolveHandleSelector(handle
|
|
41
|
+
export declare function resolveHandleSelector({ handle }: {
|
|
42
|
+
handle: string;
|
|
43
|
+
}, _optional?: Record<string, never>): string;
|
|
34
44
|
/** A tagged element as described back to a caller. `label` is page-authored, so it is untrusted. */
|
|
35
45
|
export interface AgentElementDescriptor {
|
|
36
46
|
readonly handle: string;
|
|
@@ -2,6 +2,12 @@ export const AGENT_ELEMENT_ATTRIBUTE = 'data-agent-element';
|
|
|
2
2
|
export const AGENT_ROLE_ATTRIBUTE = 'data-agent-role';
|
|
3
3
|
export const AGENT_LABEL_ATTRIBUTE = 'data-agent-label';
|
|
4
4
|
export const AGENT_PAGE_ATTRIBUTE = 'data-agent-page';
|
|
5
|
+
/**
|
|
6
|
+
* Marks a subtree the page driver must treat as absent: nothing inside it is published, adopted
|
|
7
|
+
* as a wrapper's control, or counted in any ancestor's text. For a secret the page shows a human
|
|
8
|
+
* (a revealed key), since a published ancestor's state otherwise reports its whole text content.
|
|
9
|
+
*/
|
|
10
|
+
export const AGENT_PRIVATE_ATTRIBUTE = 'data-agent-private';
|
|
5
11
|
export const AGENT_ELEMENT_ROLES = [
|
|
6
12
|
'button', 'checkbox', 'field', 'form', 'list', 'status', 'region', 'link',
|
|
7
13
|
];
|
|
@@ -19,7 +25,7 @@ const MAX_HANDLE_LENGTH = 128;
|
|
|
19
25
|
* @param handle - Candidate handle, typically caller-supplied.
|
|
20
26
|
* @returns True when it is safe to interpolate into an attribute selector.
|
|
21
27
|
*/
|
|
22
|
-
export function isValidElementHandle(handle) {
|
|
28
|
+
export function isValidElementHandle({ handle }, _optional = {}) {
|
|
23
29
|
return handle.length > 0 && handle.length <= MAX_HANDLE_LENGTH && HANDLE_PATTERN.test(handle);
|
|
24
30
|
}
|
|
25
31
|
/**
|
|
@@ -29,8 +35,8 @@ export function isValidElementHandle(handle) {
|
|
|
29
35
|
* @returns The attribute selector for that handle.
|
|
30
36
|
* @throws If the handle is not valid — never fall back to treating it as a raw selector.
|
|
31
37
|
*/
|
|
32
|
-
export function resolveHandleSelector(handle) {
|
|
33
|
-
if (!isValidElementHandle(handle)) {
|
|
38
|
+
export function resolveHandleSelector({ handle }, _optional = {}) {
|
|
39
|
+
if (!isValidElementHandle({ handle })) {
|
|
34
40
|
throw new Error(`invalid element handle "${handle.slice(0, MAX_HANDLE_LENGTH)}": `
|
|
35
41
|
+ 'handles are lowercase words joined by single hyphens, and are never CSS selectors');
|
|
36
42
|
}
|
|
@@ -1,18 +1,20 @@
|
|
|
1
|
+
import type { Clock } from "@jini-ai/core/primitives";
|
|
1
2
|
/**
|
|
2
|
-
* @module
|
|
3
|
+
* @module gen-ui/encoder
|
|
3
4
|
*
|
|
4
|
-
* Encodes `@jini-ai/protocol`'s `RunProtocolEvent` stream into
|
|
5
|
+
* Encodes `@jini-ai/protocol`'s `RunProtocolEvent` stream into custom gen-ui wire events (see
|
|
5
6
|
* `./events.ts`'s module doc). Rewritten from scratch against `@jini-ai/protocol`'s actual
|
|
6
7
|
* current shape — the ported adapter's original encoder targeted a different, product-specific
|
|
7
8
|
* event union with no direct correspondence to `RunProtocolEvent`/`RunAgentPayload`; only the
|
|
8
9
|
* *shape* of the job (a big per-event-kind switch, unrecognized events silently dropped) carried
|
|
9
|
-
* over. See `
|
|
10
|
+
* over. See `archived provenance ledger` for the full old→new field-mapping table and the generalization
|
|
10
11
|
* writeup for the six event kinds that had no generic equivalent before this task.
|
|
11
12
|
*
|
|
12
13
|
* Folded in 2026-07-26 from the standalone `@jini-ai/agui` package (plan §3a) into this `src/gen-ui/`
|
|
13
14
|
* subdirectory — kept out of the flat `ag-ui.ts` namespace because that file is a different
|
|
14
15
|
* projection ({@link CapabilityDef} → an AG-UI *frontend tool*); this one turns a run's event
|
|
15
|
-
* stream into
|
|
16
|
+
* stream into Jini's own gen-ui *wire* events. These are separate protocols; the old package name
|
|
17
|
+
* did not make this custom event vocabulary compatible with external AG-UI.
|
|
16
18
|
*/
|
|
17
19
|
import type { RunProtocolEvent } from '@jini-ai/protocol';
|
|
18
20
|
import type { GenUiEvent } from './events.js';
|
|
@@ -20,12 +22,12 @@ export interface GenUiEncodeContext {
|
|
|
20
22
|
/** The run this event belongs to — stamped onto every produced `GenUiEvent`. */
|
|
21
23
|
readonly runId: string;
|
|
22
24
|
/** Passed through onto the produced event's `seq`, when the caller tracks one (e.g. an SSE `Last-Event-ID`-shaped cursor). Omitted entirely (not set to `undefined`) when absent, matching the original adapter's own base-field construction. */
|
|
23
|
-
readonly seq?: number;
|
|
24
|
-
/**
|
|
25
|
-
readonly now?: () => number;
|
|
25
|
+
readonly seq?: number | undefined;
|
|
26
|
+
/** Optional clock override for this event; the factory's required clock supplies the default. */
|
|
27
|
+
readonly now?: ((required: Record<string, never>) => number) | undefined;
|
|
26
28
|
}
|
|
27
29
|
/**
|
|
28
|
-
* A stateful
|
|
30
|
+
* A stateful gen-ui encoder for one run's event stream. Stateful because `tool_use`/`tool_result`
|
|
29
31
|
* correlation requires remembering each in-flight tool call's name/args between the two protocol
|
|
30
32
|
* events that describe its start and end — a pure per-event function cannot do this alone. Create
|
|
31
33
|
* one instance per run (e.g. one per `RunLifecycle.stream(runId, ...)` subscription); do not share
|
|
@@ -34,11 +36,17 @@ export interface GenUiEncodeContext {
|
|
|
34
36
|
*/
|
|
35
37
|
export interface GenUiEncoder {
|
|
36
38
|
/**
|
|
37
|
-
* Encodes one `RunProtocolEvent` into
|
|
39
|
+
* Encodes one `RunProtocolEvent` into a `GenUiEvent`, or `null` if this event has no gen-ui
|
|
38
40
|
* equivalent (an unrecognized/not-yet-generalized event kind — silently dropped by the relay,
|
|
39
41
|
* matching the original adapter's own default behavior).
|
|
40
42
|
*/
|
|
41
|
-
encode(
|
|
43
|
+
encode(required: {
|
|
44
|
+
event: RunProtocolEvent;
|
|
45
|
+
runId: string;
|
|
46
|
+
}, optional?: {
|
|
47
|
+
seq?: number | undefined;
|
|
48
|
+
now?: ((required: Record<string, never>) => number) | undefined;
|
|
49
|
+
}): GenUiEvent | null;
|
|
42
50
|
}
|
|
43
51
|
/**
|
|
44
52
|
* Creates a fresh `GenUiEncoder` with its own, empty tool-call correlation map.
|
|
@@ -46,5 +54,7 @@ export interface GenUiEncoder {
|
|
|
46
54
|
* of currently in-flight (not yet resolved) tool calls for the run this instance encodes.
|
|
47
55
|
* @overallScore 100/100
|
|
48
56
|
*/
|
|
49
|
-
export declare function createGenUiEncoder(
|
|
57
|
+
export declare function createGenUiEncoder({ clock }: {
|
|
58
|
+
clock: Clock;
|
|
59
|
+
}, _optional?: Record<string, never>): GenUiEncoder;
|
|
50
60
|
//# sourceMappingURL=encoder.d.ts.map
|
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
* of currently in-flight (not yet resolved) tool calls for the run this instance encodes.
|
|
5
5
|
* @overallScore 100/100
|
|
6
6
|
*/
|
|
7
|
-
export function createGenUiEncoder() {
|
|
7
|
+
export function createGenUiEncoder({ clock }, _optional = {}) {
|
|
8
8
|
const pendingToolCalls = new Map();
|
|
9
9
|
function baseFields(ctx) {
|
|
10
|
-
const ts = ctx.now ? ctx.now() :
|
|
10
|
+
const ts = ctx.now ? ctx.now({}) : clock.nowMs();
|
|
11
11
|
return ctx.seq !== undefined ? { runId: ctx.runId, ts, seq: ctx.seq } : { runId: ctx.runId, ts };
|
|
12
12
|
}
|
|
13
13
|
function encodeAgentPayload(payload, ctx) {
|
|
@@ -38,7 +38,7 @@ export function createGenUiEncoder() {
|
|
|
38
38
|
result: payload.content,
|
|
39
39
|
};
|
|
40
40
|
}
|
|
41
|
-
// Generalization (see
|
|
41
|
+
// Generalization (see archived provenance ledger): pipeline_stage_started/completed generalized into a
|
|
42
42
|
// named-stage boundary any multi-step driver can emit, flowing through the same 'agent'
|
|
43
43
|
// channel as tool_use/tool_result.
|
|
44
44
|
case 'stage_start':
|
|
@@ -57,19 +57,20 @@ export function createGenUiEncoder() {
|
|
|
57
57
|
stageId: payload.stageId,
|
|
58
58
|
...(payload.iteration !== undefined ? { iteration: payload.iteration } : {}),
|
|
59
59
|
};
|
|
60
|
-
// Generalization (see
|
|
60
|
+
// Generalization (see archived provenance ledger): genui_surface_request/response generalized into a
|
|
61
61
|
// generic human-in-the-loop ask/answer pair.
|
|
62
62
|
case 'surface_request':
|
|
63
63
|
return { ...base, kind: 'ui.surface_requested', surfaceId: payload.surfaceId, surfaceKind: payload.surfaceKind, payload: payload.payload };
|
|
64
64
|
case 'surface_response':
|
|
65
65
|
return { ...base, kind: 'ui.surface_responded', surfaceId: payload.surfaceId, value: payload.value, respondedBy: payload.respondedBy };
|
|
66
66
|
// 'status' / 'thinking_start' / 'thinking_delta' / 'tool_input_delta' / 'usage' / 'raw':
|
|
67
|
-
// no
|
|
67
|
+
// no gen-ui equivalent — silently dropped, matching the original adapter's default behavior.
|
|
68
68
|
default:
|
|
69
69
|
return null;
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
|
-
function encode(event,
|
|
72
|
+
function encode({ event, runId }, { seq, now } = {}) {
|
|
73
|
+
const ctx = { runId, seq, now };
|
|
73
74
|
switch (event.kind) {
|
|
74
75
|
case 'start':
|
|
75
76
|
return { ...baseFields(ctx), kind: 'run.lifecycle', status: 'started' };
|
|
@@ -86,7 +87,7 @@ export function createGenUiEncoder() {
|
|
|
86
87
|
}
|
|
87
88
|
case 'agent':
|
|
88
89
|
return encodeAgentPayload(event.payload, ctx);
|
|
89
|
-
// 'stdout' / 'stderr' / 'error': no
|
|
90
|
+
// 'stdout' / 'stderr' / 'error': no gen-ui equivalent — silently dropped, matching the
|
|
90
91
|
// original adapter's default behavior for unrecognized event kinds.
|
|
91
92
|
default:
|
|
92
93
|
return null;
|