@nexface/tools 0.1.14 → 0.1.15-alpha.1
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/browser/actions.js +10 -34
- package/dist/browser/actions.js.map +1 -0
- package/dist/browser/controller.js +74 -53
- package/dist/browser/controller.js.map +1 -0
- package/dist/browser/diagnostics.js +3 -8
- package/dist/browser/diagnostics.js.map +1 -0
- package/dist/browser/dom.js +28 -12
- package/dist/browser/dom.js.map +1 -0
- package/dist/browser/feedback.js +5 -6
- package/dist/browser/feedback.js.map +1 -0
- package/dist/browser/focus.js +1 -0
- package/dist/browser/focus.js.map +1 -0
- package/dist/browser/locator.js +9 -3
- package/dist/browser/locator.js.map +1 -0
- package/dist/browser/prompt.generated.js +1 -0
- package/dist/browser/prompt.generated.js.map +1 -0
- package/dist/browser/prompt.js +1 -0
- package/dist/browser/prompt.js.map +1 -0
- package/dist/browser/snapshot.js +22 -10
- package/dist/browser/snapshot.js.map +1 -0
- package/dist/browser/toolset.js +36 -42
- package/dist/browser/toolset.js.map +1 -0
- package/dist/browser/types.d.ts +1 -1
- package/dist/browser/types.js +1 -0
- package/dist/browser/types.js.map +1 -0
- package/dist/browser/worker-runner.js +1 -0
- package/dist/browser/worker-runner.js.map +1 -0
- package/dist/definition.d.ts +3 -1
- package/dist/definition.js +2 -2
- package/dist/definition.js.map +1 -0
- package/dist/index.browser.js +1 -0
- package/dist/index.browser.js.map +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -0
- package/dist/internal-react.d.ts +1 -1
- package/dist/internal-react.js +4 -3
- package/dist/internal-react.js.map +1 -0
- package/dist/internal-types.js +1 -0
- package/dist/internal-types.js.map +1 -0
- package/dist/navigation.js +1 -0
- package/dist/navigation.js.map +1 -0
- package/dist/operation-lock.js +2 -36
- package/dist/operation-lock.js.map +1 -0
- package/dist/operation-runtime.js +13 -41
- package/dist/operation-runtime.js.map +1 -0
- package/dist/operation-surface.js +41 -118
- package/dist/operation-surface.js.map +1 -0
- package/dist/operation-types.js +1 -0
- package/dist/operation-types.js.map +1 -0
- package/dist/operation-view.d.ts +1 -1
- package/dist/operation-view.js +60 -120
- package/dist/operation-view.js.map +1 -0
- package/dist/react.js +12 -9
- package/dist/react.js.map +1 -0
- package/dist/registration.d.ts +3 -0
- package/dist/registration.js +7 -5
- package/dist/registration.js.map +1 -0
- package/dist/runtime.d.ts +17 -6
- package/dist/runtime.js +59 -105
- package/dist/runtime.js.map +1 -0
- package/dist/shared/definition.js +1 -0
- package/dist/shared/definition.js.map +1 -0
- package/dist/shared/errors.d.ts +1 -1
- package/dist/shared/errors.js +1 -0
- package/dist/shared/errors.js.map +1 -0
- package/dist/shared/page-protocol.js +1 -0
- package/dist/shared/page-protocol.js.map +1 -0
- package/dist/shared/page-tools.js +1 -0
- package/dist/shared/page-tools.js.map +1 -0
- package/dist/shared/runtime-controller.d.ts +0 -1
- package/dist/shared/runtime-controller.js +1 -0
- package/dist/shared/runtime-controller.js.map +1 -0
- package/dist/shared/runtime-execution.js +1 -0
- package/dist/shared/runtime-execution.js.map +1 -0
- package/dist/shared/schema.js +19 -45
- package/dist/shared/schema.js.map +1 -0
- package/dist/styles.css +109 -879
- package/dist/types.js +1 -0
- package/dist/types.js.map +1 -0
- package/dist/webmcp.js +12 -38
- package/dist/webmcp.js.map +1 -0
- package/package.json +2 -6
- package/dist/tool-search.d.ts +0 -11
- package/dist/tool-search.js +0 -117
package/dist/browser/toolset.js
CHANGED
|
@@ -27,7 +27,11 @@ const DEFAULT_SNAPSHOT_LIMITS = {
|
|
|
27
27
|
fullMaxVisitedNodes: 40_000,
|
|
28
28
|
};
|
|
29
29
|
function isIgnoredMutationNode(node) {
|
|
30
|
-
const element = node instanceof Element
|
|
30
|
+
const element = node instanceof Element
|
|
31
|
+
? node
|
|
32
|
+
: node instanceof Text
|
|
33
|
+
? node.parentElement
|
|
34
|
+
: null;
|
|
31
35
|
return Boolean(element?.closest("[data-nexface-ignore]"));
|
|
32
36
|
}
|
|
33
37
|
function isRelevantMutation(record) {
|
|
@@ -36,7 +40,8 @@ function isRelevantMutation(record) {
|
|
|
36
40
|
if (record.type !== "childList")
|
|
37
41
|
return true;
|
|
38
42
|
const changedNodes = [...record.addedNodes, ...record.removedNodes];
|
|
39
|
-
return changedNodes.length === 0
|
|
43
|
+
return (changedNodes.length === 0
|
|
44
|
+
|| changedNodes.some((node) => !isIgnoredMutationNode(node)));
|
|
40
45
|
}
|
|
41
46
|
let activeHistoryPatch;
|
|
42
47
|
function subscribeHistoryChanges(subscriber) {
|
|
@@ -218,12 +223,12 @@ function validateInput(definition, input) {
|
|
|
218
223
|
}
|
|
219
224
|
}
|
|
220
225
|
export function browserToolsAvailable() {
|
|
221
|
-
return (typeof window !== "undefined"
|
|
222
|
-
typeof document !== "undefined"
|
|
223
|
-
typeof Worker !== "undefined"
|
|
224
|
-
typeof Blob !== "undefined"
|
|
225
|
-
typeof URL?.createObjectURL === "function"
|
|
226
|
-
typeof MutationObserver !== "undefined");
|
|
226
|
+
return (typeof window !== "undefined"
|
|
227
|
+
&& typeof document !== "undefined"
|
|
228
|
+
&& typeof Worker !== "undefined"
|
|
229
|
+
&& typeof Blob !== "undefined"
|
|
230
|
+
&& typeof URL?.createObjectURL === "function"
|
|
231
|
+
&& typeof MutationObserver !== "undefined");
|
|
227
232
|
}
|
|
228
233
|
export function createBrowserToolset(options = {}) {
|
|
229
234
|
if (!browserToolsAvailable()) {
|
|
@@ -231,14 +236,19 @@ export function createBrowserToolset(options = {}) {
|
|
|
231
236
|
}
|
|
232
237
|
const limits = {
|
|
233
238
|
...DEFAULT_EXECUTION_LIMITS,
|
|
234
|
-
maxDurationMs: options.limits?.maxDurationMs
|
|
235
|
-
|
|
236
|
-
|
|
239
|
+
maxDurationMs: options.limits?.maxDurationMs
|
|
240
|
+
?? DEFAULT_EXECUTION_LIMITS.maxDurationMs,
|
|
241
|
+
maxResultChars: options.limits?.maxResultChars
|
|
242
|
+
?? DEFAULT_EXECUTION_LIMITS.maxResultChars,
|
|
243
|
+
singleActionTimeoutMs: options.limits?.singleActionTimeoutMs
|
|
244
|
+
?? DEFAULT_EXECUTION_LIMITS.singleActionTimeoutMs,
|
|
237
245
|
};
|
|
238
246
|
const snapshotLimits = {
|
|
239
247
|
...DEFAULT_SNAPSHOT_LIMITS,
|
|
240
|
-
viewportMaxChars: options.snapshotLimits?.viewportMaxChars
|
|
241
|
-
|
|
248
|
+
viewportMaxChars: options.snapshotLimits?.viewportMaxChars
|
|
249
|
+
?? DEFAULT_SNAPSHOT_LIMITS.viewportMaxChars,
|
|
250
|
+
fullMaxChars: options.snapshotLimits?.fullMaxChars
|
|
251
|
+
?? DEFAULT_SNAPSHOT_LIMITS.fullMaxChars,
|
|
242
252
|
};
|
|
243
253
|
const feedback = new ActionFeedback();
|
|
244
254
|
const controller = new PageController(limits, feedback);
|
|
@@ -275,8 +285,7 @@ export function createBrowserToolset(options = {}) {
|
|
|
275
285
|
const scope = normalizedInput.scope;
|
|
276
286
|
const deadline = performance.now() + limits.maxDurationMs;
|
|
277
287
|
signal.throwIfAborted();
|
|
278
|
-
return (await observe(scope, { deadline, signal }, pageDecision ? "actions" : "text"))
|
|
279
|
-
.snapshot;
|
|
288
|
+
return (await observe(scope, { deadline, signal }, pageDecision ? "actions" : "text")).snapshot;
|
|
280
289
|
},
|
|
281
290
|
};
|
|
282
291
|
const executeObserved = async (signal, execute, cancel, mode = "code", onFeedback, assertActive) => {
|
|
@@ -307,8 +316,7 @@ export function createBrowserToolset(options = {}) {
|
|
|
307
316
|
}
|
|
308
317
|
result = await measurePagePhase("execution", () => execute(activeRegistry, workerBudget));
|
|
309
318
|
signal.throwIfAborted();
|
|
310
|
-
if (result.error &&
|
|
311
|
-
["EXECUTION_TIMEOUT", "WORKER_ERROR", "EXECUTION_OUTCOME_UNKNOWN"].includes(result.error.code)) {
|
|
319
|
+
if (result.error && ["EXECUTION_TIMEOUT", "WORKER_ERROR", "EXECUTION_OUTCOME_UNKNOWN"].includes(result.error.code)) {
|
|
312
320
|
result.error.code = "EXECUTION_OUTCOME_UNKNOWN";
|
|
313
321
|
}
|
|
314
322
|
if (!result.ok && result.completedActions.length === 0) {
|
|
@@ -317,7 +325,9 @@ export function createBrowserToolset(options = {}) {
|
|
|
317
325
|
try {
|
|
318
326
|
const settled = await measurePagePhase("settle", () => tracker.waitForSettle({ deadline, signal }));
|
|
319
327
|
signal.throwIfAborted();
|
|
320
|
-
if (settled.timedOut
|
|
328
|
+
if (settled.timedOut
|
|
329
|
+
&& settled.urlChanged
|
|
330
|
+
&& !settled.mutationObservedAfterUrlChange) {
|
|
321
331
|
result.snapshotUnavailable = true;
|
|
322
332
|
return expireRefs(result);
|
|
323
333
|
}
|
|
@@ -372,9 +382,7 @@ export function createBrowserToolset(options = {}) {
|
|
|
372
382
|
if (!bundle || bundle.snapshot.snapshotId !== input.snapshotId)
|
|
373
383
|
return undefined;
|
|
374
384
|
const selected = bundle.actions?.get(input.actionId);
|
|
375
|
-
if (!selected ||
|
|
376
|
-
selected.command.method === "scrollBy" ||
|
|
377
|
-
selected.command.method === "waitForTimeout")
|
|
385
|
+
if (!selected || selected.command.method === "scrollBy" || selected.command.method === "waitForTimeout")
|
|
378
386
|
return undefined;
|
|
379
387
|
const target = selected.command.target;
|
|
380
388
|
const element = target?.type === "ref" ? bundle.registry.refs.get(target.ref)?.element : undefined;
|
|
@@ -388,21 +396,14 @@ export function createBrowserToolset(options = {}) {
|
|
|
388
396
|
const selected = bundle.actions.get(input.actionId);
|
|
389
397
|
if (!selected)
|
|
390
398
|
throw new AgentToolError("INVALID_INPUT", "Action is not a candidate of this observation.");
|
|
391
|
-
if (selected.command.method === "fill"
|
|
392
|
-
? typeof input.text !== "string" || !input.text.trim()
|
|
393
|
-
: input.text !== undefined) {
|
|
399
|
+
if (selected.command.method === "fill" ? typeof input.text !== "string" || !input.text.trim() : input.text !== undefined) {
|
|
394
400
|
throw new AgentToolError("INVALID_INPUT", "Only fill actions require a non-empty text value.");
|
|
395
401
|
}
|
|
396
402
|
if (selected.command.method === "selectOption") {
|
|
397
403
|
const target = selected.command.target;
|
|
398
404
|
const element = target.type === "ref" ? bundle.registry.refs.get(target.ref)?.element : undefined;
|
|
399
|
-
const options = element instanceof HTMLSelectElement
|
|
400
|
-
|
|
401
|
-
: [];
|
|
402
|
-
if (options.length !== 1 ||
|
|
403
|
-
options[0].disabled ||
|
|
404
|
-
options[0].closest("optgroup[disabled]") ||
|
|
405
|
-
options[0].label.slice(0, 500) !== selected.candidate.option) {
|
|
405
|
+
const options = element instanceof HTMLSelectElement ? [...element.options].filter((option) => option.value === selected.command.args[0]) : [];
|
|
406
|
+
if (options.length !== 1 || options[0].disabled || options[0].closest("optgroup[disabled]") || options[0].label.slice(0, 500) !== selected.candidate.option) {
|
|
406
407
|
throw new AgentToolError("INVALID_INPUT", "The observed option changed or is no longer available. Observe again.");
|
|
407
408
|
}
|
|
408
409
|
}
|
|
@@ -412,9 +413,7 @@ export function createBrowserToolset(options = {}) {
|
|
|
412
413
|
let timer;
|
|
413
414
|
try {
|
|
414
415
|
const command = {
|
|
415
|
-
...selected.command,
|
|
416
|
-
executionId,
|
|
417
|
-
commandSeq: 1,
|
|
416
|
+
...selected.command, executionId, commandSeq: 1,
|
|
418
417
|
args: selected.command.method === "fill" ? [input.text] : selected.command.args,
|
|
419
418
|
};
|
|
420
419
|
const response = await Promise.race([
|
|
@@ -422,8 +421,7 @@ export function createBrowserToolset(options = {}) {
|
|
|
422
421
|
if (selected.optionElement) {
|
|
423
422
|
const target = selected.command.target;
|
|
424
423
|
const element = target.type === "ref" ? registry.refs.get(target.ref)?.element : undefined;
|
|
425
|
-
if (!selected.optionElement.isConnected ||
|
|
426
|
-
selected.optionElement.closest("select") !== element) {
|
|
424
|
+
if (!selected.optionElement.isConnected || selected.optionElement.closest("select") !== element) {
|
|
427
425
|
throw new AgentToolError("INVALID_INPUT", "The observed option was replaced. Observe again.");
|
|
428
426
|
}
|
|
429
427
|
}
|
|
@@ -436,12 +434,7 @@ export function createBrowserToolset(options = {}) {
|
|
|
436
434
|
}),
|
|
437
435
|
]);
|
|
438
436
|
const receipt = controller.completeExecution(executionId);
|
|
439
|
-
return {
|
|
440
|
-
executionId,
|
|
441
|
-
...receipt,
|
|
442
|
-
ok: response.ok,
|
|
443
|
-
...(response.error ? { error: response.error } : {}),
|
|
444
|
-
};
|
|
437
|
+
return { executionId, ...receipt, ok: response.ok, ...(response.error ? { error: response.error } : {}) };
|
|
445
438
|
}
|
|
446
439
|
finally {
|
|
447
440
|
clearTimeout(timer);
|
|
@@ -456,3 +449,4 @@ export function createBrowserToolset(options = {}) {
|
|
|
456
449
|
handlers: new Map(toolHandlers.map((tool) => [tool.definition.name, tool])),
|
|
457
450
|
};
|
|
458
451
|
}
|
|
452
|
+
//# sourceMappingURL=toolset.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toolset.js","sourceRoot":"","sources":["../../src/browser/toolset.ts"],"names":[],"mappings":"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","sourcesContent":["import { measurePagePhase } from \"./diagnostics.js\";\nimport { AgentToolError } from \"../runtime.js\";\nimport { validateAgentToolInput } from \"../shared/schema.js\";\nimport type { AgentToolDefinition } from \"../types.js\";\nimport { getSnapshotTool, executeActionTool, applyActionTool } from \"../shared/page-tools.js\";\nexport { getSnapshotTool, executeActionTool, applyActionTool } from \"../shared/page-tools.js\";\n\nimport { PageController } from \"./controller.js\";\nimport { ActionFeedback, type PageFeedbackListener } from \"./feedback.js\";\nimport { createSnapshot } from \"./snapshot.js\";\nimport type {\n ExecutionLimits,\n ExecutionResult,\n SnapshotBundle,\n SnapshotLimits,\n SnapshotScope,\n SnapshotFormat,\n PageCommand,\n} from \"./types.js\";\nimport { WorkerRunner } from \"./worker-runner.js\";\n\nexport const DEFAULT_EXECUTION_LIMITS: ExecutionLimits = {\n maxArgumentChars: 8_000,\n maxCodeLength: 12_000,\n maxDurationMs: 20_000,\n maxPageCalls: 30,\n maxResultChars: 64_000,\n singleActionTimeoutMs: 5_000,\n};\n\nconst MINIMUM_OBSERVATION_MS = 500;\nconst ACTION_OBSERVATION_MS = 150;\nconst QUIET_WINDOW_MS = 250;\nconst MAXIMUM_SETTLE_MS = 2_000;\nconst PAGE_POLL_INTERVAL_MS = 50;\n\nconst DEFAULT_SNAPSHOT_LIMITS: SnapshotLimits = {\n viewportMaxChars: 24_000,\n viewportMaxVisitedNodes: 12_000,\n fullMaxChars: 60_000,\n fullMaxVisitedNodes: 40_000,\n};\n\nexport interface PageAutomationOptions {\n limits?: {\n maxDurationMs?: number;\n maxResultChars?: number;\n singleActionTimeoutMs?: number;\n };\n snapshotLimits?: {\n viewportMaxChars?: number;\n fullMaxChars?: number;\n };\n}\n\nexport interface BrowserToolHandler {\n resolveTarget?(input: Record<string, unknown>): HTMLElement | undefined;\n definition: AgentToolDefinition<Record<string, unknown>, unknown>;\n execute(\n input: Record<string, unknown>,\n context: { signal: AbortSignal; onFeedback?: PageFeedbackListener; assertActive?: () => void; pageDecision?: boolean },\n ): Promise<unknown>;\n}\n\nexport interface BrowserToolset {\n definitions: AgentToolDefinition<Record<string, unknown>, unknown>[];\n handlers: Map<string, BrowserToolHandler>;\n}\n\nfunction isIgnoredMutationNode(node: Node | null): boolean {\n const element =\n node instanceof Element\n ? node\n : node instanceof Text\n ? node.parentElement\n : null;\n return Boolean(element?.closest(\"[data-nexface-ignore]\"));\n}\n\nfunction isRelevantMutation(record: MutationRecord): boolean {\n if (isIgnoredMutationNode(record.target)) return false;\n if (record.type !== \"childList\") return true;\n const changedNodes = [...record.addedNodes, ...record.removedNodes];\n return (\n changedNodes.length === 0\n || changedNodes.some((node) => !isIgnoredMutationNode(node))\n );\n}\n\nexport interface PageTransitionSettleResult {\n timedOut: boolean;\n urlChanged: boolean;\n mutationObservedAfterUrlChange: boolean;\n}\n\nexport interface PageTransitionTracker {\n waitForSettle(options: {\n deadline: number;\n signal: AbortSignal;\n }): Promise<PageTransitionSettleResult>;\n dispose(): void;\n}\n\ninterface HistoryChangeSubscriber {\n beforeChange(): void;\n afterChange(): void;\n}\n\ninterface HistoryPatch {\n subscribers: Set<HistoryChangeSubscriber>;\n originalPushState: History[\"pushState\"];\n originalReplaceState: History[\"replaceState\"];\n wrappedPushState: History[\"pushState\"];\n wrappedReplaceState: History[\"replaceState\"];\n onUrlEvent: () => void;\n}\n\nlet activeHistoryPatch: HistoryPatch | undefined;\n\nfunction subscribeHistoryChanges(\n subscriber: HistoryChangeSubscriber,\n): () => void {\n if (!activeHistoryPatch) {\n const subscribers = new Set<HistoryChangeSubscriber>();\n const originalPushState = history.pushState;\n const originalReplaceState = history.replaceState;\n const beforeChange = (): void => {\n for (const entry of [...subscribers]) entry.beforeChange();\n };\n const afterChange = (): void => {\n for (const entry of [...subscribers]) entry.afterChange();\n };\n const wrappedPushState: History[\"pushState\"] = function(\n this: History,\n data,\n unused,\n url,\n ): void {\n beforeChange();\n originalPushState.call(this, data, unused, url);\n afterChange();\n };\n const wrappedReplaceState: History[\"replaceState\"] = function(\n this: History,\n data,\n unused,\n url,\n ): void {\n beforeChange();\n originalReplaceState.call(this, data, unused, url);\n afterChange();\n };\n const onUrlEvent = (): void => {\n beforeChange();\n afterChange();\n };\n activeHistoryPatch = {\n subscribers,\n originalPushState,\n originalReplaceState,\n wrappedPushState,\n wrappedReplaceState,\n onUrlEvent,\n };\n history.pushState = wrappedPushState;\n history.replaceState = wrappedReplaceState;\n window.addEventListener(\"popstate\", onUrlEvent);\n window.addEventListener(\"hashchange\", onUrlEvent);\n }\n\n const patch = activeHistoryPatch;\n patch.subscribers.add(subscriber);\n let unsubscribed = false;\n return () => {\n if (unsubscribed) return;\n unsubscribed = true;\n patch.subscribers.delete(subscriber);\n if (patch.subscribers.size > 0 || activeHistoryPatch !== patch) return;\n if (history.pushState === patch.wrappedPushState) {\n history.pushState = patch.originalPushState;\n }\n if (history.replaceState === patch.wrappedReplaceState) {\n history.replaceState = patch.originalReplaceState;\n }\n window.removeEventListener(\"popstate\", patch.onUrlEvent);\n window.removeEventListener(\"hashchange\", patch.onUrlEvent);\n activeHistoryPatch = undefined;\n };\n}\n\nexport function startPageTransitionTracker(mode: \"code\" | \"action\" = \"code\"): PageTransitionTracker {\n const minimumObservationMs = mode === \"action\" ? ACTION_OBSERVATION_MS : MINIMUM_OBSERVATION_MS;\n const quietWindowMs = mode === \"action\" ? ACTION_OBSERVATION_MS : QUIET_WINDOW_MS;\n const initialUrl = location.href;\n let currentUrl = initialUrl;\n let urlChangedAt: number | undefined;\n let didUrlChange = false;\n let mutationObservedAfterUrlChange = false;\n let lastRelevantMutationAt = performance.now();\n let disposed = false;\n\n const syncUrl = (now: number): void => {\n const nextUrl = location.href;\n if (nextUrl === currentUrl) return;\n currentUrl = nextUrl;\n didUrlChange = true;\n urlChangedAt = now;\n mutationObservedAfterUrlChange = false;\n lastRelevantMutationAt = now;\n };\n\n let observer: MutationObserver;\n const recordMutations = (\n records: MutationRecord[],\n now: number,\n ): void => {\n if (!records.some(isRelevantMutation)) return;\n lastRelevantMutationAt = now;\n if (didUrlChange) mutationObservedAfterUrlChange = true;\n };\n const flushBeforeUrlChange = (): void => {\n recordMutations(observer.takeRecords(), performance.now());\n };\n\n observer = new MutationObserver((records) => {\n const now = performance.now();\n if (location.href !== currentUrl) {\n recordMutations(records, now);\n syncUrl(now);\n return;\n }\n recordMutations(records, now);\n });\n observer.observe(document.body, {\n attributes: true,\n childList: true,\n characterData: true,\n subtree: true,\n });\n\n const unsubscribeHistory = subscribeHistoryChanges({\n beforeChange: flushBeforeUrlChange,\n afterChange: () => syncUrl(performance.now()),\n });\n\n return {\n waitForSettle({ deadline, signal }) {\n signal.throwIfAborted();\n const startedAt = performance.now();\n syncUrl(startedAt);\n const settleDeadline = Math.min(\n deadline,\n startedAt + MAXIMUM_SETTLE_MS,\n );\n\n return new Promise((resolve, reject) => {\n let timer = 0;\n let settled = false;\n const cleanup = (): void => {\n window.clearInterval(timer);\n signal.removeEventListener(\"abort\", onAbort);\n };\n const finish = (timedOut: boolean): void => {\n if (settled) return;\n settled = true;\n cleanup();\n resolve({\n timedOut,\n urlChanged: didUrlChange,\n mutationObservedAfterUrlChange,\n });\n };\n const onAbort = (): void => {\n if (settled) return;\n settled = true;\n cleanup();\n reject(\n signal.reason instanceof Error\n ? signal.reason\n : new DOMException(\"Execution cancelled.\", \"AbortError\"),\n );\n };\n const check = (): void => {\n const now = performance.now();\n syncUrl(now);\n const minimumStartedAt = Math.max(\n startedAt,\n urlChangedAt ?? startedAt,\n );\n const reachedMinimum =\n now - minimumStartedAt >= minimumObservationMs;\n const isQuiet = now - lastRelevantMutationAt >= quietWindowMs;\n const urlReady =\n !didUrlChange || mutationObservedAfterUrlChange;\n if (reachedMinimum && isQuiet && urlReady) {\n finish(false);\n return;\n }\n if (now >= settleDeadline) finish(true);\n };\n\n signal.addEventListener(\"abort\", onAbort, { once: true });\n timer = window.setInterval(check, PAGE_POLL_INTERVAL_MS);\n check();\n });\n },\n dispose() {\n if (disposed) return;\n disposed = true;\n observer.disconnect();\n unsubscribeHistory();\n },\n };\n}\n\nfunction validateInput(\n definition: AgentToolDefinition,\n input: Record<string, unknown>,\n): void {\n const errors = validateAgentToolInput(definition.inputSchema, input);\n if (errors.length > 0) {\n throw new AgentToolError(\"INVALID_INPUT\", errors.join(\" \"), { errors });\n }\n}\n\nexport function browserToolsAvailable(): boolean {\n return (\n typeof window !== \"undefined\"\n && typeof document !== \"undefined\"\n && typeof Worker !== \"undefined\"\n && typeof Blob !== \"undefined\"\n && typeof URL?.createObjectURL === \"function\"\n && typeof MutationObserver !== \"undefined\"\n );\n}\n\nexport function createBrowserToolset(\n options: PageAutomationOptions = {},\n): BrowserToolset {\n if (!browserToolsAvailable()) {\n throw new AgentToolError(\n \"BROWSER_TOOLS_UNAVAILABLE\",\n \"Page automation requires document, Worker, Blob URL, and MutationObserver support.\",\n );\n }\n\n const limits: ExecutionLimits = {\n ...DEFAULT_EXECUTION_LIMITS,\n maxDurationMs: options.limits?.maxDurationMs\n ?? DEFAULT_EXECUTION_LIMITS.maxDurationMs,\n maxResultChars: options.limits?.maxResultChars\n ?? DEFAULT_EXECUTION_LIMITS.maxResultChars,\n singleActionTimeoutMs: options.limits?.singleActionTimeoutMs\n ?? DEFAULT_EXECUTION_LIMITS.singleActionTimeoutMs,\n };\n const snapshotLimits = {\n ...DEFAULT_SNAPSHOT_LIMITS,\n viewportMaxChars: options.snapshotLimits?.viewportMaxChars\n ?? DEFAULT_SNAPSHOT_LIMITS.viewportMaxChars,\n fullMaxChars: options.snapshotLimits?.fullMaxChars\n ?? DEFAULT_SNAPSHOT_LIMITS.fullMaxChars,\n };\n const feedback = new ActionFeedback();\n const controller = new PageController(limits, feedback);\n const runner = new WorkerRunner(controller, limits);\n let bundle: SnapshotBundle | undefined;\n\n const activate = (next: SnapshotBundle): SnapshotBundle => {\n bundle = next;\n return next;\n };\n\n const clearBundle = (): void => {\n bundle = undefined;\n };\n\n const expireRefs = (result: ExecutionResult): ExecutionResult => {\n clearBundle();\n result.refsExpired = true;\n return result;\n };\n\n const observe = async (\n scope: SnapshotScope,\n execution?: { deadline: number; signal: AbortSignal },\n format: SnapshotFormat = \"text\",\n ): Promise<SnapshotBundle> => {\n const next = await measurePagePhase(\"observation\", () => createSnapshot(scope, snapshotLimits, execution, format));\n execution?.signal.throwIfAborted();\n if (execution && performance.now() >= execution.deadline) {\n throw new DOMException(\n \"Snapshot collection exceeded the page automation deadline.\",\n \"TimeoutError\",\n );\n }\n return activate(next);\n };\n\n const getSnapshot: BrowserToolHandler = {\n definition: getSnapshotTool,\n async execute(input, { signal, pageDecision }) {\n const normalizedInput = {\n ...input,\n scope: input.scope ?? \"viewport\",\n };\n validateInput(getSnapshotTool, normalizedInput);\n const scope = normalizedInput.scope as SnapshotScope;\n const deadline = performance.now() + limits.maxDurationMs;\n signal.throwIfAborted();\n return (await observe(scope, { deadline, signal }, pageDecision ? \"actions\" : \"text\")).snapshot;\n },\n };\n\n const executeObserved = async (\n signal: AbortSignal,\n execute: (registry: SnapshotBundle[\"registry\"], budget: number) => Promise<ExecutionResult>,\n cancel: () => void,\n mode: \"code\" | \"action\" = \"code\",\n onFeedback?: PageFeedbackListener,\n assertActive?: () => void,\n ): Promise<ExecutionResult> => {\n if (!bundle) throw new AgentToolError(\"BROWSER_SNAPSHOT_REQUIRED\", \"A current page observation is required.\");\n const format: SnapshotFormat = mode === \"action\" ? \"actions\" : \"text\";\n const deadline = performance.now() + limits.maxDurationMs;\n signal.throwIfAborted();\n\n const onAbort = (): void => cancel();\n signal.addEventListener(\"abort\", onAbort, { once: true });\n const tracker = startPageTransitionTracker(mode);\n feedback.listener = onFeedback;\n feedback.assertActive = assertActive;\n let result: ExecutionResult;\n try {\n const activeRegistry = bundle.registry;\n const workerBudget = Math.max(0, deadline - performance.now());\n if (workerBudget <= 0) {\n return {\n executionId: \"deadline-exceeded\",\n ok: false,\n completedActions: [],\n error: {\n code: \"EXECUTION_TIMEOUT\",\n message: `Execution exceeded ${limits.maxDurationMs}ms.`,\n },\n } satisfies ExecutionResult;\n }\n result = await measurePagePhase(\"execution\", () => execute(activeRegistry, workerBudget));\n signal.throwIfAborted();\n if (result.error && [\"EXECUTION_TIMEOUT\", \"WORKER_ERROR\", \"EXECUTION_OUTCOME_UNKNOWN\"].includes(result.error.code)) {\n result.error.code = \"EXECUTION_OUTCOME_UNKNOWN\";\n }\n if (!result.ok && result.completedActions.length === 0) {\n return expireRefs(result);\n }\n try {\n const settled = await measurePagePhase(\"settle\", () => tracker.waitForSettle({ deadline, signal }));\n signal.throwIfAborted();\n if (\n settled.timedOut\n && settled.urlChanged\n && !settled.mutationObservedAfterUrlChange\n ) {\n result.snapshotUnavailable = true;\n return expireRefs(result);\n }\n const remainingBudget = deadline - performance.now();\n if (remainingBudget <= 0) {\n result.snapshotUnavailable = true;\n return expireRefs(result);\n }\n if (settled.timedOut) {\n const diagnostic = await measurePagePhase(\"observation\", () => createSnapshot(\n \"viewport\",\n snapshotLimits,\n { deadline, signal },\n format,\n ));\n result.snapshot = diagnostic.snapshot;\n result.postSnapshotTimedOut = true;\n return expireRefs(result);\n }\n const refreshed = await observe(\"viewport\", { deadline, signal }, format);\n signal.throwIfAborted();\n result.snapshot = refreshed.snapshot;\n } catch (error) {\n if (signal.aborted) {\n clearBundle();\n throw signal.reason;\n }\n result.snapshotUnavailable = true;\n expireRefs(result);\n }\n return result;\n } catch (error) {\n clearBundle();\n if (signal.aborted) throw signal.reason;\n throw new AgentToolError(\n \"EXECUTION_OUTCOME_UNKNOWN\",\n error instanceof Error ? error.message : \"Browser execution failed.\",\n { refsExpired: true },\n );\n } finally {\n feedback.listener = undefined;\n feedback.assertActive = undefined;\n tracker.dispose();\n signal.removeEventListener(\"abort\", onAbort);\n }\n };\n\n const executeCode: BrowserToolHandler = {\n definition: executeActionTool,\n async execute(input, { signal, onFeedback, assertActive }) {\n validateInput(executeActionTool, input);\n return executeObserved(signal, (registry, budget) => runner.execute(input.code as string, registry, budget), () => runner.cancel(), \"code\", onFeedback, assertActive);\n },\n };\n\n const applyAction: BrowserToolHandler = {\n definition: applyActionTool,\n resolveTarget(input) {\n if (!bundle || bundle.snapshot.snapshotId !== input.snapshotId) return undefined;\n const selected = bundle.actions?.get(input.actionId as string);\n if (!selected || selected.command.method === \"scrollBy\" || selected.command.method === \"waitForTimeout\") return undefined;\n const target = selected.command.target;\n const element = target?.type === \"ref\" ? bundle.registry.refs.get(target.ref)?.element : undefined;\n return element instanceof HTMLElement && element.isConnected ? element : undefined;\n },\n async execute(input, { signal, onFeedback, assertActive }) {\n validateInput(applyActionTool, input);\n if (!bundle || bundle.snapshot.snapshotId !== input.snapshotId || !bundle.actions) {\n throw new AgentToolError(\"BROWSER_SNAPSHOT_REQUIRED\", \"The actions observation is missing or expired.\");\n }\n const selected = bundle.actions.get(input.actionId as string);\n if (!selected) throw new AgentToolError(\"INVALID_INPUT\", \"Action is not a candidate of this observation.\");\n if (selected.command.method === \"fill\" ? typeof input.text !== \"string\" || !input.text.trim() : input.text !== undefined) {\n throw new AgentToolError(\"INVALID_INPUT\", \"Only fill actions require a non-empty text value.\");\n }\n if (selected.command.method === \"selectOption\") {\n const target = selected.command.target;\n const element = target.type === \"ref\" ? bundle.registry.refs.get(target.ref)?.element : undefined;\n const options = element instanceof HTMLSelectElement ? [...element.options].filter((option) => option.value === selected.command.args[0]) : [];\n if (options.length !== 1 || options[0]!.disabled || options[0]!.closest(\"optgroup[disabled]\") || options[0]!.label.slice(0, 500) !== selected.candidate.option) {\n throw new AgentToolError(\"INVALID_INPUT\", \"The observed option changed or is no longer available. Observe again.\");\n }\n }\n const executionId = crypto.randomUUID();\n return executeObserved(signal, async (registry, budget) => {\n controller.beginExecution(executionId, registry);\n let timer: ReturnType<typeof setTimeout> | undefined;\n try {\n const command: PageCommand = {\n ...selected.command, executionId, commandSeq: 1,\n args: selected.command.method === \"fill\" ? [input.text] : selected.command.args,\n };\n const response = await Promise.race([\n controller.execute(command, async () => {\n if (selected.optionElement) {\n const target = selected.command.target;\n const element = target.type === \"ref\" ? registry.refs.get(target.ref)?.element : undefined;\n if (!selected.optionElement.isConnected || selected.optionElement.closest(\"select\") !== element) {\n throw new AgentToolError(\"INVALID_INPUT\", \"The observed option was replaced. Observe again.\");\n }\n }\n }),\n new Promise<never>((_, reject) => {\n timer = setTimeout(() => {\n controller.cancelExecution(executionId);\n reject(new Error(\"Page action exceeded its execution budget.\"));\n }, budget);\n }),\n ]);\n const receipt = controller.completeExecution(executionId);\n return { executionId, ...receipt, ok: response.ok, ...(response.error ? { error: response.error } : {}) };\n } finally {\n clearTimeout(timer);\n controller.completeExecution(executionId);\n }\n }, () => controller.cancelExecution(executionId), \"action\", onFeedback, assertActive);\n },\n };\n\n const toolHandlers = [getSnapshot, executeCode, applyAction];\n return {\n definitions: toolHandlers.map(({ definition }) => definition),\n handlers: new Map(toolHandlers.map((tool) => [tool.definition.name, tool])),\n };\n}\n"]}
|
package/dist/browser/types.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ObservedAction } from "./actions.js";
|
|
2
2
|
import type { PageSnapshot } from "../shared/page-protocol.js";
|
|
3
|
-
export type { SnapshotScope, SnapshotFormat, SemanticState, PageActionCandidate, PageSnapshot
|
|
3
|
+
export type { SnapshotScope, SnapshotFormat, SemanticState, PageActionCandidate, PageSnapshot } from "../shared/page-protocol.js";
|
|
4
4
|
export interface RefTarget {
|
|
5
5
|
element: Element;
|
|
6
6
|
identity: string;
|
package/dist/browser/types.js
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/browser/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { ObservedAction } from \"./actions.js\";\n\nimport type { PageSnapshot } from \"../shared/page-protocol.js\";\nexport type { SnapshotScope, SnapshotFormat, SemanticState, PageActionCandidate, PageSnapshot } from \"../shared/page-protocol.js\";\n\nexport interface RefTarget {\n element: Element;\n identity: string;\n kind?: \"element\" | \"scrollable\";\n}\n\nexport interface SnapshotRegistry {\n snapshotId: string;\n refs: Map<string, RefTarget>;\n}\n\nexport interface SnapshotBundle {\n snapshot: PageSnapshot;\n registry: SnapshotRegistry;\n actions?: Map<string, ObservedAction>;\n}\n\nexport interface RegexValue {\n source: string;\n flags: string;\n}\n\nexport type TextMatcher = string | RegexValue;\n\nexport type LocatorStep =\n | {\n kind: \"role\";\n role: string;\n options?: { name?: TextMatcher; exact?: boolean };\n }\n | {\n kind: \"text\";\n text: TextMatcher;\n options?: { exact?: boolean };\n }\n | {\n kind: \"label\";\n text: TextMatcher;\n options?: { exact?: boolean };\n }\n | {\n kind: \"filter\";\n hasText: TextMatcher;\n };\n\nexport interface LocatorDescriptor {\n steps: LocatorStep[];\n}\n\nexport type LocatorMethod =\n | \"click\"\n | \"fill\"\n | \"press\"\n | \"check\"\n | \"uncheck\"\n | \"selectOption\"\n | \"setOptionSelected\"\n | \"hover\"\n | \"focus\"\n | \"blur\"\n | \"scrollBy\"\n | \"scrollTo\"\n | \"scrollIntoView\"\n | \"exists\"\n | \"text\"\n | \"waitFor\";\n\nexport type PageMethod = \"scrollBy\" | \"waitForTimeout\" | \"waitForURL\";\n\nexport type PageCommandTarget =\n | { type: \"page\" }\n | { type: \"ref\"; ref: string }\n | { type: \"locator\"; locator: LocatorDescriptor };\n\nexport interface PageCommand {\n executionId: string;\n commandSeq: number;\n target: PageCommandTarget;\n method: LocatorMethod | PageMethod;\n args: unknown[];\n}\n\nexport interface CommandError {\n code:\n | \"NOT_FOUND\"\n | \"AMBIGUOUS_TARGET\"\n | \"REF_ACTION_FAILED\"\n | \"NOT_VISIBLE\"\n | \"ELEMENT_COVERED\"\n | \"ELEMENT_DISABLED\"\n | \"NOT_EDITABLE\"\n | \"ACTION_TIMEOUT\"\n | \"EXECUTION_CANCELLED\"\n | \"EXECUTION_OUTCOME_UNKNOWN\"\n | \"INVALID_COMMAND\"\n | \"RESULT_TOO_LARGE\"\n | \"UNSUPPORTED_OPERATION\";\n message: string;\n candidates?: string[];\n}\n\nexport type JSONValue =\n | null\n | boolean\n | number\n | string\n | JSONValue[]\n | { [key: string]: JSONValue };\n\nexport interface CompletedAction {\n callIndex: number;\n method: LocatorMethod | PageMethod;\n target?: string;\n}\n\nexport interface FailedCall {\n callIndex: number;\n method: LocatorMethod | PageMethod;\n target?: string;\n}\n\nexport interface ExecutionResult {\n executionId: string;\n ok: boolean;\n value?: JSONValue;\n completedActions: CompletedAction[];\n failedCall?: FailedCall;\n error?: {\n code: string;\n message: string;\n statement?: string;\n };\n snapshot?: PageSnapshot;\n snapshotUnavailable?: boolean;\n postSnapshotTimedOut?: boolean;\n refsExpired?: boolean;\n}\n\nexport interface ExecutionLimits {\n maxArgumentChars: number;\n maxCodeLength: number;\n maxDurationMs: number;\n maxPageCalls: number;\n maxResultChars: number;\n singleActionTimeoutMs: number;\n}\n\nexport interface SnapshotLimits {\n fullMaxChars: number;\n fullMaxVisitedNodes: number;\n viewportMaxChars: number;\n viewportMaxVisitedNodes: number;\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker-runner.js","sourceRoot":"","sources":["../../src/browser/worker-runner.ts"],"names":[],"mappings":"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","sourcesContent":["import { PageController } from \"./controller.js\";\nimport type {\n ExecutionLimits,\n ExecutionResult,\n JSONValue,\n PageCommand,\n SnapshotRegistry,\n} from \"./types.js\";\n\ninterface WorkerCommandMessage {\n type: \"command\";\n requestId: number;\n command: PageCommand;\n}\n\ninterface WorkerDoneMessage {\n type: \"done\";\n hasValue: boolean;\n value?: unknown;\n}\n\ninterface WorkerErrorMessage {\n type: \"error\";\n error: { code: string; message: string; statement?: string };\n}\n\ntype WorkerMessage =\n | WorkerCommandMessage\n | WorkerDoneMessage\n | WorkerErrorMessage;\n\nexport function createWorkerRuntimeSource(\n executionId: string,\n code: string,\n): string {\n return `\nconst executionId = ${JSON.stringify(executionId)};\nlet requestId = 0;\nlet commandSeq = 0;\nconst pending = new Map();\n\nself.onmessage = (event) => {\n const message = event.data;\n if (message.type !== \"response\") return;\n const entry = pending.get(message.requestId);\n if (!entry) return;\n pending.delete(message.requestId);\n if (message.response.ok) entry.resolve(message.response.value);\n else {\n const error = new Error(message.response.error?.message || \"Page command failed\");\n error.code = message.response.error?.code || \"PAGE_COMMAND_FAILED\";\n error.candidates = message.response.error?.candidates;\n entry.reject(error);\n }\n};\n\nfunction normalizeRPCValue(value) {\n if (value instanceof RegExp) {\n return { source: value.source, flags: value.flags };\n }\n if (\n value === null ||\n typeof value === \"string\" ||\n typeof value === \"boolean\" ||\n (typeof value === \"number\" && Number.isFinite(value))\n ) {\n return value;\n }\n if (Array.isArray(value)) return value.map(normalizeRPCValue);\n if (value && typeof value === \"object\") {\n const prototype = Object.getPrototypeOf(value);\n if (prototype !== Object.prototype && prototype !== null) {\n throw new Error(\"Page API arguments must be plain JSON values or RegExp.\");\n }\n return Object.fromEntries(\n Object.entries(value).map(([key, item]) => [key, normalizeRPCValue(item)])\n );\n }\n throw new Error(\"Page API arguments contain an unsupported value.\");\n}\n\nfunction normalizeResult(value, seen = new Set()) {\n if (\n value === null ||\n typeof value === \"string\" ||\n typeof value === \"boolean\" ||\n (typeof value === \"number\" && Number.isFinite(value))\n ) {\n return value;\n }\n if (Array.isArray(value)) {\n if (seen.has(value)) throw new Error(\"nxf_executeAction returned a cyclic value.\");\n seen.add(value);\n const result = value.map((item) => normalizeResult(item, seen));\n seen.delete(value);\n return result;\n }\n if (value && typeof value === \"object\") {\n const prototype = Object.getPrototypeOf(value);\n if (prototype !== Object.prototype && prototype !== null) {\n throw new Error(\"nxf_executeAction must return JSON-serializable data.\");\n }\n if (seen.has(value)) throw new Error(\"nxf_executeAction returned a cyclic value.\");\n seen.add(value);\n const result = Object.fromEntries(\n Object.entries(value).map(([key, item]) => [key, normalizeResult(item, seen)])\n );\n seen.delete(value);\n return result;\n }\n throw new Error(\"nxf_executeAction must return JSON-serializable data.\");\n}\n\nfunction rpc(target, method, args) {\n if (pending.size > 0) {\n const error = new Error(\"Page API operations must be awaited sequentially.\");\n error.code = \"CONCURRENT_PAGE_OPERATION\";\n throw error;\n }\n const id = ++requestId;\n const command = {\n executionId,\n commandSeq: ++commandSeq,\n target: normalizeRPCValue(target),\n method,\n args: normalizeRPCValue(args)\n };\n self.postMessage({ type: \"command\", requestId: id, command });\n return new Promise((resolve, reject) =>\n pending.set(id, { resolve, reject })\n );\n}\n\nclass Locator {\n constructor(steps) { this.steps = steps; }\n getByRole(role, options = {}) {\n return new Locator([...this.steps, { kind: \"role\", role, options }]);\n }\n getByText(text, options = {}) {\n return new Locator([...this.steps, { kind: \"text\", text, options }]);\n }\n getByLabel(text, options = {}) {\n return new Locator([...this.steps, { kind: \"label\", text, options }]);\n }\n filter(options) {\n return new Locator([...this.steps, { kind: \"filter\", hasText: options.hasText }]);\n }\n call(method, ...args) {\n return rpc(\n { type: \"locator\", locator: { steps: this.steps } },\n method,\n args\n );\n }\n click() { return this.call(\"click\"); }\n fill(value) { return this.call(\"fill\", value); }\n press(key) { return this.call(\"press\", key); }\n check() { return this.call(\"check\"); }\n uncheck() { return this.call(\"uncheck\"); }\n selectOption(value) { return this.call(\"selectOption\", value); }\n hover() { return this.call(\"hover\"); }\n focus() { return this.call(\"focus\"); }\n blur() { return this.call(\"blur\"); }\n scrollBy(value) { return this.call(\"scrollBy\", value); }\n scrollTo(value) { return this.call(\"scrollTo\", value); }\n scrollIntoView() { return this.call(\"scrollIntoView\"); }\n exists() { return this.call(\"exists\"); }\n text() { return this.call(\"text\"); }\n waitFor(options = {}) { return this.call(\"waitFor\", options); }\n}\n\nconst uiTarget = Object.freeze({\n ref: (ref) => {\n if (typeof ref !== \"string\" || !/^@\\\\d+$/.test(ref)) {\n throw new Error(\"ui.ref(ref) requires a Snapshot ref such as @12.\");\n }\n return new LocatorProxy({ type: \"ref\", ref });\n },\n getByRole: (role, options = {}) =>\n new Locator([{ kind: \"role\", role, options }]),\n getByText: (text, options = {}) =>\n new Locator([{ kind: \"text\", text, options }]),\n getByLabel: (text, options = {}) =>\n new Locator([{ kind: \"label\", text, options }]),\n scrollBy: (value) => rpc({ type: \"page\" }, \"scrollBy\", [value]),\n waitForTimeout: (ms) => rpc({ type: \"page\" }, \"waitForTimeout\", [ms]),\n waitForURL: (url, options = {}) =>\n rpc({ type: \"page\" }, \"waitForURL\", [url, options])\n});\nconst ui = new Proxy(uiTarget, {\n get(target, property, receiver) {\n if (typeof property !== \"string\" || Object.hasOwn(target, property)) {\n return Reflect.get(target, property, receiver);\n }\n const error = new Error(\n 'UI API method \"' + property + '\" is not available. Supported methods: '\n + Object.keys(uiTarget).join(\", \") + \".\"\n );\n error.code = \"UI_API_NOT_AVAILABLE\";\n throw error;\n }\n});\n\nfunction LocatorProxy(target) {\n this.target = target;\n}\nLocatorProxy.prototype.call = function(method, ...args) {\n return rpc(this.target, method, args);\n};\nfor (const method of [\n \"click\",\n \"check\",\n \"uncheck\",\n \"hover\",\n \"focus\",\n \"blur\",\n \"scrollIntoView\",\n \"exists\",\n \"text\"\n]) {\n LocatorProxy.prototype[method] = function() {\n return this.call(method);\n };\n}\nLocatorProxy.prototype.fill = function(value) { return this.call(\"fill\", value); };\nLocatorProxy.prototype.press = function(key) { return this.call(\"press\", key); };\nLocatorProxy.prototype.selectOption = function(value) {\n return this.call(\"selectOption\", value);\n};\nLocatorProxy.prototype.scrollBy = function(value) {\n return this.call(\"scrollBy\", value);\n};\nLocatorProxy.prototype.scrollTo = function(value) {\n return this.call(\"scrollTo\", value);\n};\nLocatorProxy.prototype.waitFor = function(options = {}) {\n return this.call(\"waitFor\", options);\n};\n\n(async () => {\n try {\n const rawResult = await (async () => {\n${code}\n })();\n if (pending.size > 0) {\n const error = new Error(\"Every Page API operation must be awaited before nxf_executeAction returns.\");\n error.code = \"UNAWAITED_PAGE_OPERATION\";\n throw error;\n }\n const hasValue = rawResult !== undefined;\n const value = hasValue ? normalizeResult(rawResult) : undefined;\n self.postMessage({ type: \"done\", hasValue, value });\n } catch (error) {\n self.postMessage({\n type: \"error\",\n error: {\n code: error?.code || \"CODE_EXECUTION_FAILED\",\n message: error?.message || String(error),\n statement: error?.statement || error?.stack?.split(\"\\\\n\")[1]?.trim()\n }\n });\n }\n})();`;\n}\n\nfunction validateJSONValue(\n value: unknown,\n maxChars: number,\n): JSONValue {\n const serialized = JSON.stringify(value);\n if (serialized === undefined) {\n throw new Error(\"nxf_executeAction returned a non-JSON value.\");\n }\n if (serialized.length > maxChars) {\n throw new Error(\n `nxf_executeAction result exceeds ${maxChars} serialized characters.`,\n );\n }\n return JSON.parse(serialized) as JSONValue;\n}\n\nexport class WorkerRunner {\n private active:\n | {\n executionId: string;\n worker: Worker;\n objectUrl: string;\n settled: boolean;\n cancel: () => void;\n }\n | undefined;\n\n constructor(\n private readonly controller: PageController,\n private readonly limits: ExecutionLimits,\n ) {}\n\n async execute(\n code: string,\n registry: SnapshotRegistry,\n maxDurationMs = this.limits.maxDurationMs,\n ): Promise<ExecutionResult> {\n if (code.length > this.limits.maxCodeLength) {\n return {\n executionId: \"rejected\",\n ok: false,\n completedActions: [],\n error: {\n code: \"CODE_TOO_LONG\",\n message: `Code exceeds ${this.limits.maxCodeLength} characters.`,\n },\n };\n }\n\n if (this.active && !this.active.settled) {\n return {\n executionId: \"rejected\",\n ok: false,\n completedActions: [],\n error: {\n code: \"EXECUTION_IN_PROGRESS\",\n message: \"Another nxf_executeAction call is still running.\",\n },\n };\n }\n\n const executionId = crypto.randomUUID();\n const source = createWorkerRuntimeSource(executionId, code);\n const blob = new Blob([source], {\n type: \"text/javascript\",\n });\n const objectUrl = URL.createObjectURL(blob);\n const worker = new Worker(objectUrl, {\n name: `nexface-${executionId}`,\n });\n this.controller.beginExecution(executionId, registry);\n\n return new Promise<ExecutionResult>((resolve) => {\n const active: NonNullable<WorkerRunner[\"active\"]> = {\n executionId,\n worker,\n objectUrl,\n settled: false,\n cancel: () => {},\n };\n this.active = active;\n\n const settle = (\n partial: Omit<\n ExecutionResult,\n \"executionId\" | \"completedActions\" | \"failedCall\"\n >,\n ): void => {\n if (active.settled) return;\n active.settled = true;\n window.clearTimeout(timer);\n worker.terminate();\n URL.revokeObjectURL(objectUrl);\n const receipt = this.controller.completeExecution(executionId);\n if (this.active === active) this.active = undefined;\n resolve({\n executionId,\n ...partial,\n completedActions: receipt.completedActions,\n ...(receipt.failedCall ? { failedCall: receipt.failedCall } : {}),\n });\n };\n\n active.cancel = () => {\n this.controller.cancelExecution(executionId);\n settle({\n ok: false,\n error: {\n code: \"EXECUTION_CANCELLED\",\n message: \"Execution was cancelled.\",\n },\n });\n };\n\n const timer = window.setTimeout(() => {\n this.controller.cancelExecution(executionId);\n settle({\n ok: false,\n error: {\n code: \"EXECUTION_TIMEOUT\",\n message: `Execution exceeded ${maxDurationMs}ms.`,\n },\n });\n }, maxDurationMs);\n\n worker.onmessage = async (event: MessageEvent<WorkerMessage>) => {\n const message = event.data;\n if (message.type === \"command\") {\n let response = await this.controller.execute(message.command);\n if (response.ok && response.value !== undefined) {\n try {\n response = {\n ...response,\n value: validateJSONValue(\n response.value,\n this.limits.maxResultChars,\n ),\n };\n } catch (error) {\n response = {\n ok: false,\n error: {\n code: \"RESULT_TOO_LARGE\",\n message: error instanceof Error ? error.message : String(error),\n },\n };\n }\n }\n if (!active.settled) {\n worker.postMessage({\n type: \"response\",\n requestId: message.requestId,\n response,\n });\n }\n return;\n }\n if (message.type === \"done\") {\n if (!message.hasValue) {\n settle({ ok: true });\n return;\n }\n try {\n settle({\n ok: true,\n value: validateJSONValue(\n message.value,\n this.limits.maxResultChars,\n ),\n });\n } catch (error) {\n settle({\n ok: false,\n error: {\n code: \"RESULT_INVALID\",\n message:\n error instanceof Error ? error.message : String(error),\n },\n });\n }\n return;\n }\n settle({ ok: false, error: message.error });\n };\n\n worker.onerror = (event) => {\n settle({\n ok: false,\n error: {\n code: \"WORKER_ERROR\",\n message: event.message || \"Worker execution failed.\",\n },\n });\n };\n });\n }\n\n cancel(): void {\n const active = this.active;\n if (!active || active.settled) return;\n active.cancel();\n }\n}\n"]}
|
package/dist/definition.d.ts
CHANGED
|
@@ -8,5 +8,7 @@ export declare function isValidAgentContextName(name: string): boolean;
|
|
|
8
8
|
export declare function defineAgentTool<TResult = unknown>(metadata: AgentToolMetadataInput): AgentToolDefinition<Record<string, never>, TResult>;
|
|
9
9
|
export declare function defineAgentTool<TInput = never, TResult = unknown, const TSchema extends AgentToolInputSchema = AgentToolInputSchema>(metadata: AgentToolMetadataInput & {
|
|
10
10
|
inputSchema: TSchema;
|
|
11
|
-
}): AgentToolDefinition<[
|
|
11
|
+
}): AgentToolDefinition<[
|
|
12
|
+
TInput
|
|
13
|
+
] extends [never] ? InferJsonSchema<TSchema> : TInput, TResult>;
|
|
12
14
|
export {};
|
package/dist/definition.js
CHANGED
|
@@ -6,8 +6,7 @@ const emptyInputSchema = Object.freeze({
|
|
|
6
6
|
});
|
|
7
7
|
const agentNamePattern = /^[A-Za-z0-9_-]{1,64}$/;
|
|
8
8
|
const reservedContextNames = new Set([
|
|
9
|
-
"nxf_applyAction",
|
|
10
|
-
"nxf_delegatePageTask",
|
|
9
|
+
"nxf_applyAction", "nxf_delegatePageTask",
|
|
11
10
|
"nxf_callAppTool",
|
|
12
11
|
"nxf_finish",
|
|
13
12
|
"nxf_getSnapshot",
|
|
@@ -34,3 +33,4 @@ export function defineAgentTool(metadata) {
|
|
|
34
33
|
inputSchema: metadata.inputSchema === undefined ? emptyInputSchema : metadata.inputSchema,
|
|
35
34
|
});
|
|
36
35
|
}
|
|
36
|
+
//# sourceMappingURL=definition.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"definition.js","sourceRoot":"","sources":["../src/definition.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AAOnE,MAAM,gBAAgB,GAAyB,MAAM,CAAC,MAAM,CAAC;IAC3D,IAAI,EAAE,QAAQ;IACd,UAAU,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;IAC7B,oBAAoB,EAAE,KAAK;CAC5B,CAAC,CAAC;AAQH,MAAM,gBAAgB,GAAG,uBAAuB,CAAC;AAEjD,MAAM,oBAAoB,GAAG,IAAI,GAAG,CAAC;IACnC,iBAAiB,EAAE,sBAAsB;IACzC,iBAAiB;IACjB,YAAY;IACZ,iBAAiB;IACjB,mBAAmB;CACpB,CAAC,CAAC;AAEH,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC;IAChC,GAAG,oBAAoB;IACvB,eAAe;IACf,oBAAoB;IACpB,kBAAkB;CACnB,CAAC,CAAC;AAEH,MAAM,UAAU,uBAAuB,CAAC,IAAY;IAClD,OAAO,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACxE,CAAC;AAED,SAAS,UAAU,CAAC,IAAY;IAC9B,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;QAChE,MAAM,IAAI,KAAK,CAAC,wCAAwC,IAAI,GAAG,CAAC,CAAC;IACnE,CAAC;AACH,CAAC;AAeD,MAAM,UAAU,eAAe,CAC7B,QAAyE;IAEzE,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC1B,OAAO,yBAAyB,CAAC;QAC/B,GAAG,QAAQ;QACX,WAAW,EAAE,QAAQ,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,QAAQ,CAAC,WAAW;KAC1F,CAAC,CAAC;AACL,CAAC","sourcesContent":["import { createAgentToolDefinition } from \"./shared/definition.js\";\nimport type {\n AgentToolDefinition,\n AgentToolInputSchema,\n InferJsonSchema,\n} from \"./types.js\";\n\nconst emptyInputSchema: AgentToolInputSchema = Object.freeze({\n type: \"object\",\n properties: Object.freeze({}),\n additionalProperties: false,\n});\n\ninterface AgentToolMetadataInput {\n name: string;\n description: string;\n effect?: \"read\" | \"action\" | \"navigate\";\n}\n\nconst agentNamePattern = /^[A-Za-z0-9_-]{1,64}$/;\n\nconst reservedContextNames = new Set([\n \"nxf_applyAction\", \"nxf_delegatePageTask\",\n \"nxf_callAppTool\",\n \"nxf_finish\",\n \"nxf_getSnapshot\",\n \"nxf_executeAction\",\n]);\n\nconst reservedToolNames = new Set([\n ...reservedContextNames,\n \"nxf_loadSkill\",\n \"nxf_beginOperation\",\n \"nxf_endOperation\",\n]);\n\nexport function isValidAgentContextName(name: string): boolean {\n return agentNamePattern.test(name) && !reservedContextNames.has(name);\n}\n\nfunction assertName(name: string): void {\n if (!agentNamePattern.test(name) || reservedToolNames.has(name)) {\n throw new Error(`Invalid or reserved agent tool name: ${name}.`);\n }\n}\n\nexport function defineAgentTool<TResult = unknown>(\n metadata: AgentToolMetadataInput,\n): AgentToolDefinition<Record<string, never>, TResult>;\nexport function defineAgentTool<\n TInput = never,\n TResult = unknown,\n const TSchema extends AgentToolInputSchema = AgentToolInputSchema,\n>(\n metadata: AgentToolMetadataInput & { inputSchema: TSchema },\n): AgentToolDefinition<\n [TInput] extends [never] ? InferJsonSchema<TSchema> : TInput,\n TResult\n>;\nexport function defineAgentTool(\n metadata: AgentToolMetadataInput & { inputSchema?: AgentToolInputSchema },\n): AgentToolDefinition {\n assertName(metadata.name);\n return createAgentToolDefinition({\n ...metadata,\n inputSchema: metadata.inputSchema === undefined ? emptyInputSchema : metadata.inputSchema,\n });\n}\n"]}
|
package/dist/index.browser.js
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.browser.js","sourceRoot":"","sources":["../src/index.browser.ts"],"names":[],"mappings":"AAAA,OAAO,cAAc,CAAC;AAEtB,cAAc,YAAY,CAAC;AAE3B,OAAO,EAAE,iBAAiB,EAA4B,MAAM,mBAAmB,CAAC","sourcesContent":["import \"./styles.css\";\n\nexport * from \"./index.js\";\n\nexport { registerAgentTool, type RegisteredAgentTool } from \"./registration.js\";\n"]}
|
package/dist/index.js
CHANGED
|
@@ -4,3 +4,4 @@ export { AgentOperationSurface } from "./operation-surface.js";
|
|
|
4
4
|
export { createToolRuntime, isToolRuntimeError, } from "./runtime.js";
|
|
5
5
|
export { AgentContext, ToolsProvider, AgentUIAction, useAgentContext, useAgentNavigation, useAgentTool, } from "./react.js";
|
|
6
6
|
export { registerAgentTool } from "./registration.js";
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,EAAE,qBAAqB,EAAmC,MAAM,wBAAwB,CAAC;AAChG,OAAO,EACL,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,YAAY,EACZ,aAAa,EACb,aAAa,EACb,eAAe,EACf,kBAAkB,EAClB,YAAY,GACb,MAAM,YAAY,CAAC;AAqCpB,OAAO,EAAE,iBAAiB,EAA4B,MAAM,mBAAmB,CAAC","sourcesContent":["export { defineAgentTool } from \"./definition.js\";\nexport { defineAgentNavigation } from \"./navigation.js\";\nexport { AgentOperationSurface, type AgentOperationSurfaceProps } from \"./operation-surface.js\";\nexport {\n createToolRuntime,\n isToolRuntimeError,\n} from \"./runtime.js\";\nexport {\n AgentContext,\n ToolsProvider,\n AgentUIAction,\n useAgentContext,\n useAgentNavigation,\n useAgentTool,\n} from \"./react.js\";\nexport type {\n AgentNavigation,\n AgentNavigationConfig,\n AgentNavigationExecutors,\n AgentNavigationRouteConfig,\n} from \"./navigation.js\";\nexport type {\n AgentToolBinding,\n AgentToolChatConfirmationConfig,\n AgentToolPageConfirmationConfig,\n AgentUIActionChildProps,\n AgentUIActionEvent,\n AgentUIActionProps,\n UseAgentToolDefaultOptions,\n UseAgentToolPageConfirmationOptions,\n} from \"./react.js\";\nexport type {\n AgentToolConfirmationConfig,\n RuntimeAgentTool,\n ToolRuntime,\n ToolOperation,\n ToolRuntimeOptions,\n ToolRuntimeToolChangeEvent,\n} from \"./runtime.js\";\nexport type {\n AgentContextEntry,\n AgentContextValue,\n AgentToolDefinition,\n AgentToolEffect,\n AgentToolExecutionContext,\n AgentToolExecutor,\n AgentToolInputSchema,\n InferJsonSchema,\n JsonSchema,\n} from \"./types.js\";\n\nexport { registerAgentTool, type RegisteredAgentTool } from \"./registration.js\";\n"]}
|
package/dist/internal-react.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { type ToolRuntime, type InternalToolRuntime } from "./runtime.js";
|
|
|
3
3
|
export interface InternalToolRuntimeHostProps {
|
|
4
4
|
children: ReactNode;
|
|
5
5
|
}
|
|
6
|
-
export declare function InternalToolRuntimeHost({ children }: InternalToolRuntimeHostProps): ReactElement;
|
|
6
|
+
export declare function InternalToolRuntimeHost({ children, }: InternalToolRuntimeHostProps): ReactElement;
|
|
7
7
|
export declare function InternalToolRuntimeScope({ children, runtime, }: {
|
|
8
8
|
children: ReactNode;
|
|
9
9
|
runtime: ToolRuntime;
|
package/dist/internal-react.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import { createContext, useContext, useMemo } from "react";
|
|
2
|
+
import { createContext, useContext, useMemo, } from "react";
|
|
3
3
|
import { createToolRuntime, getInternalToolRuntime, } from "./runtime.js";
|
|
4
4
|
const InternalToolRuntimeContext = createContext(null);
|
|
5
|
-
export function InternalToolRuntimeHost({ children }) {
|
|
5
|
+
export function InternalToolRuntimeHost({ children, }) {
|
|
6
6
|
const runtime = useMemo(() => createToolRuntime(), []);
|
|
7
|
-
return React.createElement(InternalToolRuntimeScope, { runtime: runtime }, children);
|
|
7
|
+
return (React.createElement(InternalToolRuntimeScope, { runtime: runtime }, children));
|
|
8
8
|
}
|
|
9
9
|
export function InternalToolRuntimeScope({ children, runtime, }) {
|
|
10
10
|
const internalRuntime = getInternalToolRuntime(runtime);
|
|
@@ -20,3 +20,4 @@ export function useInternalToolRuntime() {
|
|
|
20
20
|
export function useOptionalInternalToolRuntime() {
|
|
21
21
|
return useContext(InternalToolRuntimeContext);
|
|
22
22
|
}
|
|
23
|
+
//# sourceMappingURL=internal-react.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"internal-react.js","sourceRoot":"","sources":["../src/internal-react.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EACL,aAAa,EACb,UAAU,EACV,OAAO,GAGR,MAAM,OAAO,CAAC;AAEf,OAAO,EACL,iBAAiB,EACjB,sBAAsB,GAGvB,MAAM,cAAc,CAAC;AAEtB,MAAM,0BAA0B,GAC9B,aAAa,CAA6B,IAAI,CAAC,CAAC;AAMlD,MAAM,UAAU,uBAAuB,CAAC,EACtC,QAAQ,GACqB;IAC7B,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,iBAAiB,EAAE,EAAE,EAAE,CAAC,CAAC;IACvD,OAAO,CACL,oBAAC,wBAAwB,IAAC,OAAO,EAAE,OAAO,IACvC,QAAQ,CACgB,CAC5B,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,EACvC,QAAQ,EACR,OAAO,GAIR;IACC,MAAM,eAAe,GAAG,sBAAsB,CAAC,OAAO,CAAC,CAAC;IACxD,OAAO,CACL,oBAAC,0BAA0B,CAAC,QAAQ,IAAC,KAAK,EAAE,eAAe,IACxD,QAAQ,CAC2B,CACvC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,sBAAsB;IACpC,MAAM,OAAO,GAAG,UAAU,CAAC,0BAA0B,CAAC,CAAC;IACvD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CACb,8EAA8E,CAC/E,CAAC;IACJ,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,8BAA8B;IAG5C,OAAO,UAAU,CAAC,0BAA0B,CAAC,CAAC;AAChD,CAAC","sourcesContent":["import * as React from \"react\";\nimport {\n createContext,\n useContext,\n useMemo,\n type ReactNode,\n type ReactElement,\n} from \"react\";\n\nimport {\n createToolRuntime,\n getInternalToolRuntime,\n type ToolRuntime,\n type InternalToolRuntime,\n} from \"./runtime.js\";\n\nconst InternalToolRuntimeContext =\n createContext<InternalToolRuntime | null>(null);\n\nexport interface InternalToolRuntimeHostProps {\n children: ReactNode;\n}\n\nexport function InternalToolRuntimeHost({\n children,\n}: InternalToolRuntimeHostProps): ReactElement {\n const runtime = useMemo(() => createToolRuntime(), []);\n return (\n <InternalToolRuntimeScope runtime={runtime}>\n {children}\n </InternalToolRuntimeScope>\n );\n}\n\nexport function InternalToolRuntimeScope({\n children,\n runtime,\n}: {\n children: ReactNode;\n runtime: ToolRuntime;\n}): ReactElement {\n const internalRuntime = getInternalToolRuntime(runtime);\n return (\n <InternalToolRuntimeContext.Provider value={internalRuntime}>\n {children}\n </InternalToolRuntimeContext.Provider>\n );\n}\n\nexport function useInternalToolRuntime(): InternalToolRuntime {\n const runtime = useContext(InternalToolRuntimeContext);\n if (!runtime) {\n throw new Error(\n \"Nexface components must be rendered inside ToolsProvider or NexfaceProvider.\",\n );\n }\n return runtime;\n}\n\nexport function useOptionalInternalToolRuntime():\n | InternalToolRuntime\n | null {\n return useContext(InternalToolRuntimeContext);\n}\n"]}
|
package/dist/internal-types.js
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"internal-types.js","sourceRoot":"","sources":["../src/internal-types.ts"],"names":[],"mappings":"","sourcesContent":["import type { RuntimeAgentTool } from \"./runtime.js\";\n\n/**\n * @experimental Status of an experimental execution notification.\n * @beta\n */\nexport type AgentToolExecutionStatus = \"running\" | \"success\" | \"error\";\n\n/**\n * @experimental Payload inferred by experimental execution listeners; not a named public export.\n * @beta\n */\nexport interface AgentToolExecutionEvent {\n tool: RuntimeAgentTool<any, any>;\n cancelled?: boolean;\n progressLabel?: string;\n id: string;\n operationId?: string;\n name: string;\n status: AgentToolExecutionStatus;\n startedAt: number;\n finishedAt?: number;\n input: unknown;\n result?: unknown;\n error?: unknown;\n}\n"]}
|
package/dist/navigation.js
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"navigation.js","sourceRoot":"","sources":["../src/navigation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AA6BlD,MAAM,wBAAwB,GAAG,UAAU,CAAC;AA4B5C,MAAM,iBAAiB,GAAG,IAAI,OAAO,EAGlC,CAAC;AAEJ,MAAM,UAAU,qBAAqB,CAGnC,MAOC;IAED,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAC;IAChC,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE;QACjE,MAAM,IAAI,GAAG,GAAG,wBAAwB,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;QACxD,MAAM,UAAU,GAAG,KAAK,CAAC,WAAW;YAClC,CAAC,CAAC,eAAe,CAAiC;gBAC9C,IAAI;gBACJ,MAAM,EAAE,UAAU;gBAClB,WAAW,EAAE,KAAK,CAAC,WAAW;gBAC9B,WAAW,EAAE,KAAK,CAAC,WAAW;aAC/B,CAAC;YACJ,CAAC,CAAC,eAAe,CAAwB;gBACrC,IAAI;gBACJ,MAAM,EAAE,UAAU;gBAClB,WAAW,EAAE,KAAK,CAAC,WAAW;aAC/B,CAAC,CAAC;QACP,IAAI,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YAC/B,MAAM,IAAI,KAAK,CAAC,mCAAmC,UAAU,CAAC,IAAI,GAAG,CAAC,CAAC;QACzE,CAAC;QACD,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QAC3B,OAAO,MAAM,CAAC,MAAM,CAAC;YACnB,GAAG;YACH,UAAU;SACX,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IACH,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,CAAwC,CAAC;IAC5E,iBAAiB,CAAC,GAAG,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;IAC1D,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,MAAM,UAAU,yBAAyB,CACvC,UAAgC;IAEhC,MAAM,OAAO,GAAG,iBAAiB,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IAClD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;IAC5E,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC","sourcesContent":["import { defineAgentTool } from \"./definition.js\";\nimport type {\n AgentToolDefinition,\n AgentToolExecutionContext,\n AgentToolInputSchema,\n InferJsonSchema,\n} from \"./types.js\";\n\nexport interface AgentNavigationResult {\n status: \"navigated\";\n}\n\ndeclare const agentNavigationBrand: unique symbol;\n\nexport interface AgentNavigationRouteConfig {\n name: string;\n description: string;\n inputSchema?: AgentToolInputSchema;\n}\n\nexport interface AgentNavigation<\n TRoutes extends Record<string, AgentNavigationRouteConfig> = Record<\n string,\n AgentNavigationRouteConfig\n >,\n> {\n readonly [agentNavigationBrand]: TRoutes;\n}\n\nconst navigationToolNamePrefix = \"nxf_nav_\";\n\nexport interface AgentNavigationConfig<\n TRoutes extends Record<string, AgentNavigationRouteConfig>,\n> {\n routes: TRoutes;\n}\n\nexport type AgentNavigationExecutors<\n TNavigation extends AgentNavigation,\n> = TNavigation extends AgentNavigation<infer TRoutes>\n ? {\n [TKey in keyof TRoutes]: (\n input: TRoutes[TKey] extends {\n readonly inputSchema: infer TSchema extends AgentToolInputSchema;\n }\n ? InferJsonSchema<TSchema>\n : Record<string, never>,\n context: AgentToolExecutionContext,\n ) => void | Promise<void>;\n }\n : never;\n\ninterface InternalAgentNavigationRoute {\n key: string;\n definition: AgentToolDefinition<any, AgentNavigationResult>;\n}\n\nconst navigationEntries = new WeakMap<\n AgentNavigation<any>,\n readonly InternalAgentNavigationRoute[]\n>();\n\nexport function defineAgentNavigation<\n const TRoutes extends Record<string, AgentNavigationRouteConfig>,\n>(\n config: AgentNavigationConfig<TRoutes> & {\n routes: {\n [TKey in keyof TRoutes]: Record<\n Exclude<keyof TRoutes[TKey], keyof AgentNavigationRouteConfig>,\n never\n >;\n };\n },\n): AgentNavigation<TRoutes> {\n const names = new Set<string>();\n const entries = Object.entries(config.routes).map(([key, route]) => {\n const name = `${navigationToolNamePrefix}${route.name}`;\n const definition = route.inputSchema\n ? defineAgentTool<unknown, AgentNavigationResult>({\n name,\n effect: \"navigate\",\n description: route.description,\n inputSchema: route.inputSchema,\n })\n : defineAgentTool<AgentNavigationResult>({\n name,\n effect: \"navigate\",\n description: route.description,\n });\n if (names.has(definition.name)) {\n throw new Error(`Duplicate navigation tool name: ${definition.name}.`);\n }\n names.add(definition.name);\n return Object.freeze({\n key,\n definition,\n });\n });\n const navigation = Object.freeze({}) as unknown as AgentNavigation<TRoutes>;\n navigationEntries.set(navigation, Object.freeze(entries));\n return navigation;\n}\n\nexport function getAgentNavigationEntries(\n navigation: AgentNavigation<any>,\n): readonly InternalAgentNavigationRoute[] {\n const entries = navigationEntries.get(navigation);\n if (!entries) {\n throw new Error(\"Navigation must be created by defineAgentNavigation().\");\n }\n return entries;\n}\n"]}
|
package/dist/operation-lock.js
CHANGED
|
@@ -30,42 +30,7 @@ export function lockOperationSurface(surface, redirectFocus) {
|
|
|
30
30
|
event.stopImmediatePropagation();
|
|
31
31
|
};
|
|
32
32
|
// Wheel and touch defaults are blocked here: React delegates them passively.
|
|
33
|
-
const events = [
|
|
34
|
-
"focus",
|
|
35
|
-
"focusin",
|
|
36
|
-
"mouseenter",
|
|
37
|
-
"mouseleave",
|
|
38
|
-
"pointerenter",
|
|
39
|
-
"pointerleave",
|
|
40
|
-
"pointerdown",
|
|
41
|
-
"pointerup",
|
|
42
|
-
"pointermove",
|
|
43
|
-
"pointerover",
|
|
44
|
-
"pointerout",
|
|
45
|
-
"mousedown",
|
|
46
|
-
"mouseup",
|
|
47
|
-
"mousemove",
|
|
48
|
-
"mouseover",
|
|
49
|
-
"mouseout",
|
|
50
|
-
"click",
|
|
51
|
-
"dblclick",
|
|
52
|
-
"auxclick",
|
|
53
|
-
"contextmenu",
|
|
54
|
-
"keydown",
|
|
55
|
-
"keyup",
|
|
56
|
-
"beforeinput",
|
|
57
|
-
"paste",
|
|
58
|
-
"cut",
|
|
59
|
-
"drop",
|
|
60
|
-
"dragstart",
|
|
61
|
-
"touchstart",
|
|
62
|
-
"touchmove",
|
|
63
|
-
"touchend",
|
|
64
|
-
"touchcancel",
|
|
65
|
-
"wheel",
|
|
66
|
-
"submit",
|
|
67
|
-
"reset",
|
|
68
|
-
];
|
|
33
|
+
const events = ["focus", "focusin", "mouseenter", "mouseleave", "pointerenter", "pointerleave", "pointerdown", "pointerup", "pointermove", "pointerover", "pointerout", "mousedown", "mouseup", "mousemove", "mouseover", "mouseout", "click", "dblclick", "auxclick", "contextmenu", "keydown", "keyup", "beforeinput", "paste", "cut", "drop", "dragstart", "touchstart", "touchmove", "touchend", "touchcancel", "wheel", "submit", "reset"];
|
|
69
34
|
lockedSurfaces.add(surface);
|
|
70
35
|
surface.setAttribute("aria-busy", "true");
|
|
71
36
|
for (const name of events)
|
|
@@ -80,3 +45,4 @@ export function lockOperationSurface(surface, redirectFocus) {
|
|
|
80
45
|
surface.setAttribute("aria-busy", previousBusy);
|
|
81
46
|
};
|
|
82
47
|
}
|
|
48
|
+
//# sourceMappingURL=operation-lock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operation-lock.js","sourceRoot":"","sources":["../src/operation-lock.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAErE,MAAM,cAAc,GAAG,IAAI,OAAO,EAAe,CAAC;AAElD,MAAM,UAAU,wBAAwB,CAAC,OAAoB;IAC3D,OAAO,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AACrC,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,oBAAoB,CAAC,OAAoB,EAAE,aAA0B;IACnF,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC;IACvD,MAAM,KAAK,GAAG,CAAC,KAAY,EAAE,EAAE;QAC7B,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,CAAC,IAAI,iBAAiB,EAAE;YAAE,OAAO;QACvF,IAAI,CAAC,KAAK,CAAC,SAAS;YAAE,OAAO;QAC7B,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YACvD,IAAI,YAAY,EAAE;gBAAE,OAAO;YAC3B,KAAK,CAAC,wBAAwB,EAAE,CAAC;YACjC,IAAI,KAAK,CAAC,MAAM,YAAY,WAAW;gBAAE,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;YAC7D,aAAa,EAAE,EAAE,CAAC;YAClB,OAAO;QACT,CAAC;QACD,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,IAAK,KAAuB,CAAC,GAAG,KAAK,KAAK,EAAE,CAAC;YACvE,KAAK,CAAC,cAAc,EAAE,CAAC;YACvB,KAAK,CAAC,wBAAwB,EAAE,CAAC;YACjC,aAAa,EAAE,EAAE,CAAC;YAClB,OAAO;QACT,CAAC;QACD,KAAK,CAAC,cAAc,EAAE,CAAC;QACvB,KAAK,CAAC,wBAAwB,EAAE,CAAC;IACnC,CAAC,CAAC;IACF,6EAA6E;IAC7E,MAAM,MAAM,GAAG,CAAC,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,cAAc,EAAE,aAAa,EAAE,WAAW,EAAE,aAAa,EAAE,aAAa,EAAE,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,aAAa,EAAE,SAAS,EAAE,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,aAAa,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IAChb,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAC5B,OAAO,CAAC,YAAY,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IAC1C,KAAK,MAAM,IAAI,IAAI,MAAM;QAAE,OAAO,CAAC,gBAAgB,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;IACpG,OAAO,GAAG,EAAE;QACV,cAAc,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC/B,KAAK,MAAM,IAAI,IAAI,MAAM;YAAE,OAAO,CAAC,mBAAmB,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;QAC1E,IAAI,YAAY,KAAK,IAAI;YAAE,OAAO,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC;;YAC3D,OAAO,CAAC,YAAY,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;IACvD,CAAC,CAAC;AACJ,CAAC","sourcesContent":["import { isAgentActivation, isAgentFocus } from \"./browser/focus.js\";\n\nconst lockedSurfaces = new WeakSet<HTMLElement>();\n\nexport function isOperationSurfaceLocked(surface: HTMLElement): boolean {\n return lockedSurfaces.has(surface);\n}\n\n/** Block user input inside the surface without hiding DOM from page tools. */\nexport function lockOperationSurface(surface: HTMLElement, redirectFocus?: () => void): () => void {\n const previousBusy = surface.getAttribute(\"aria-busy\");\n const block = (event: Event) => {\n if ((event.type === \"submit\" || event.type === \"reset\") && isAgentActivation()) return;\n if (!event.isTrusted) return;\n if (event.type === \"focus\" || event.type === \"focusin\") {\n if (isAgentFocus()) return;\n event.stopImmediatePropagation();\n if (event.target instanceof HTMLElement) event.target.blur();\n redirectFocus?.();\n return;\n }\n if (event.type === \"keydown\" && (event as KeyboardEvent).key === \"Tab\") {\n event.preventDefault();\n event.stopImmediatePropagation();\n redirectFocus?.();\n return;\n }\n event.preventDefault();\n event.stopImmediatePropagation();\n };\n // Wheel and touch defaults are blocked here: React delegates them passively.\n const events = [\"focus\", \"focusin\", \"mouseenter\", \"mouseleave\", \"pointerenter\", \"pointerleave\", \"pointerdown\", \"pointerup\", \"pointermove\", \"pointerover\", \"pointerout\", \"mousedown\", \"mouseup\", \"mousemove\", \"mouseover\", \"mouseout\", \"click\", \"dblclick\", \"auxclick\", \"contextmenu\", \"keydown\", \"keyup\", \"beforeinput\", \"paste\", \"cut\", \"drop\", \"dragstart\", \"touchstart\", \"touchmove\", \"touchend\", \"touchcancel\", \"wheel\", \"submit\", \"reset\"];\n lockedSurfaces.add(surface);\n surface.setAttribute(\"aria-busy\", \"true\");\n for (const name of events) surface.addEventListener(name, block, { capture: true, passive: false });\n return () => {\n lockedSurfaces.delete(surface);\n for (const name of events) surface.removeEventListener(name, block, true);\n if (previousBusy === null) surface.removeAttribute(\"aria-busy\");\n else surface.setAttribute(\"aria-busy\", previousBusy);\n };\n}\n"]}
|