@browserbasehq/orca 3.2.1-preview.2 → 3.4.0-preview.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/dist/cjs/lib/inference.js +2 -9
- package/dist/cjs/lib/inference.js.map +1 -1
- package/dist/cjs/lib/prompt.js +3 -1
- package/dist/cjs/lib/prompt.js.map +1 -1
- package/dist/cjs/lib/v3/agent/AgentProvider.js +3 -0
- package/dist/cjs/lib/v3/agent/AgentProvider.js.map +1 -1
- package/dist/cjs/lib/v3/agent/tools/fillFormVision.js +16 -12
- package/dist/cjs/lib/v3/agent/tools/fillFormVision.js.map +1 -1
- package/dist/cjs/lib/v3/agent/utils/validateExperimentalFeatures.js +0 -4
- package/dist/cjs/lib/v3/agent/utils/validateExperimentalFeatures.js.map +1 -1
- package/dist/cjs/lib/v3/api.d.ts +1 -0
- package/dist/cjs/lib/v3/api.js +15 -3
- package/dist/cjs/lib/v3/api.js.map +1 -1
- package/dist/cjs/lib/v3/dom/build/a11yScripts.generated.js +1 -1
- package/dist/cjs/lib/v3/dom/build/a11yScripts.generated.js.map +1 -1
- package/dist/cjs/lib/v3/dom/build/locatorScripts.generated.js +1 -1
- package/dist/cjs/lib/v3/dom/build/locatorScripts.generated.js.map +1 -1
- package/dist/cjs/lib/v3/dom/build/reRenderScriptContent.d.ts +1 -1
- package/dist/cjs/lib/v3/dom/build/reRenderScriptContent.js +1 -1
- package/dist/cjs/lib/v3/dom/build/reRenderScriptContent.js.map +1 -1
- package/dist/cjs/lib/v3/dom/build/screenshotScripts.generated.js +1 -1
- package/dist/cjs/lib/v3/dom/build/screenshotScripts.generated.js.map +1 -1
- package/dist/cjs/lib/v3/dom/build/scriptV3Content.d.ts +1 -1
- package/dist/cjs/lib/v3/dom/build/scriptV3Content.js +1 -1
- package/dist/cjs/lib/v3/dom/build/scriptV3Content.js.map +1 -1
- package/dist/cjs/lib/v3/handlers/extractHandler.js +3 -1
- package/dist/cjs/lib/v3/handlers/extractHandler.js.map +1 -1
- package/dist/cjs/lib/v3/handlers/v3AgentHandler.js +3 -5
- package/dist/cjs/lib/v3/handlers/v3AgentHandler.js.map +1 -1
- package/dist/cjs/lib/v3/index.d.ts +1 -1
- package/dist/cjs/lib/v3/llm/CerebrasClient.js +1 -1
- package/dist/cjs/lib/v3/llm/CerebrasClient.js.map +1 -1
- package/dist/cjs/lib/v3/llm/GroqClient.js +1 -1
- package/dist/cjs/lib/v3/llm/GroqClient.js.map +1 -1
- package/dist/cjs/lib/v3/types/private/agent.d.ts +5 -0
- package/dist/cjs/lib/v3/types/private/agent.js +11 -0
- package/dist/cjs/lib/v3/types/private/agent.js.map +1 -1
- package/dist/cjs/lib/v3/types/private/handlers.d.ts +1 -0
- package/dist/cjs/lib/v3/types/private/handlers.js.map +1 -1
- package/dist/cjs/lib/v3/types/private/snapshot.d.ts +8 -0
- package/dist/cjs/lib/v3/types/private/snapshot.js.map +1 -1
- package/dist/cjs/lib/v3/types/public/agent.d.ts +2 -3
- package/dist/cjs/lib/v3/types/public/agent.js +3 -0
- package/dist/cjs/lib/v3/types/public/agent.js.map +1 -1
- package/dist/cjs/lib/v3/types/public/api.d.ts +5 -1
- package/dist/cjs/lib/v3/types/public/api.js +15 -2
- package/dist/cjs/lib/v3/types/public/api.js.map +1 -1
- package/dist/cjs/lib/v3/types/public/methods.d.ts +1 -0
- package/dist/cjs/lib/v3/types/public/methods.js.map +1 -1
- package/dist/cjs/lib/v3/understudy/a11y/snapshot/a11yTree.js +21 -12
- package/dist/cjs/lib/v3/understudy/a11y/snapshot/a11yTree.js.map +1 -1
- package/dist/cjs/lib/v3/understudy/a11y/snapshot/capture.d.ts +11 -2
- package/dist/cjs/lib/v3/understudy/a11y/snapshot/capture.js +268 -21
- package/dist/cjs/lib/v3/understudy/a11y/snapshot/capture.js.map +1 -1
- package/dist/cjs/lib/v3/understudy/a11y/snapshot/domTree.js +60 -7
- package/dist/cjs/lib/v3/understudy/a11y/snapshot/domTree.js.map +1 -1
- package/dist/cjs/lib/v3/understudy/frameRegistry.js +16 -5
- package/dist/cjs/lib/v3/understudy/frameRegistry.js.map +1 -1
- package/dist/cjs/lib/v3/v3.d.ts +1 -0
- package/dist/cjs/lib/v3/v3.js +15 -14
- package/dist/cjs/lib/v3/v3.js.map +1 -1
- package/dist/cjs/lib/version.d.ts +1 -1
- package/dist/cjs/lib/version.js +1 -1
- package/dist/cjs/lib/version.js.map +1 -1
- package/dist/cjs/tests/integration/observe-element-id-format.spec.js +130 -0
- package/dist/cjs/tests/integration/observe-element-id-format.spec.js.map +1 -0
- package/dist/cjs/tests/unit/agent-mode-routing.test.js +88 -0
- package/dist/cjs/tests/unit/agent-mode-routing.test.js.map +1 -0
- package/dist/cjs/tests/unit/agent-temperature.test.d.ts +1 -0
- package/dist/cjs/tests/unit/agent-temperature.test.js +191 -0
- package/dist/cjs/tests/unit/agent-temperature.test.js.map +1 -0
- package/dist/cjs/tests/unit/agent-variables-validation.test.d.ts +1 -0
- package/dist/cjs/tests/unit/agent-variables-validation.test.js +43 -0
- package/dist/cjs/tests/unit/agent-variables-validation.test.js.map +1 -0
- package/dist/cjs/tests/unit/api-client-observe-variables.test.js +47 -0
- package/dist/cjs/tests/unit/api-client-observe-variables.test.js.map +1 -1
- package/dist/cjs/tests/unit/api-optional-model-api-key.test.js +60 -0
- package/dist/cjs/tests/unit/api-optional-model-api-key.test.js.map +1 -1
- package/dist/cjs/tests/unit/api-variables-schema.test.js +25 -0
- package/dist/cjs/tests/unit/api-variables-schema.test.js.map +1 -1
- package/dist/cjs/tests/unit/frame-registry-oopif-adoption.test.d.ts +1 -0
- package/dist/cjs/tests/unit/frame-registry-oopif-adoption.test.js +60 -0
- package/dist/cjs/tests/unit/frame-registry-oopif-adoption.test.js.map +1 -0
- package/dist/cjs/tests/unit/inference-temperature.test.d.ts +1 -0
- package/dist/cjs/tests/unit/inference-temperature.test.js +65 -0
- package/dist/cjs/tests/unit/inference-temperature.test.js.map +1 -0
- package/dist/cjs/tests/unit/openai-compatible-temperature.test.d.ts +1 -0
- package/dist/cjs/tests/unit/openai-compatible-temperature.test.js +84 -0
- package/dist/cjs/tests/unit/openai-compatible-temperature.test.js.map +1 -0
- package/dist/cjs/tests/unit/prompt-observe-variables.test.js +6 -0
- package/dist/cjs/tests/unit/prompt-observe-variables.test.js.map +1 -1
- package/dist/cjs/tests/unit/public-api/llm-and-agents.test.js +3 -0
- package/dist/cjs/tests/unit/public-api/llm-and-agents.test.js.map +1 -1
- package/dist/cjs/tests/unit/public-api/public-types.test.js.map +1 -1
- package/dist/cjs/tests/unit/snapshot-a11y-resolvers.test.js +106 -5
- package/dist/cjs/tests/unit/snapshot-a11y-resolvers.test.js.map +1 -1
- package/dist/cjs/tests/unit/snapshot-a11y-tree-utils.test.js +20 -0
- package/dist/cjs/tests/unit/snapshot-a11y-tree-utils.test.js.map +1 -1
- package/dist/cjs/tests/unit/snapshot-capture-orchestration.test.js +119 -9
- package/dist/cjs/tests/unit/snapshot-capture-orchestration.test.js.map +1 -1
- package/dist/esm/lib/inference.js +2 -9
- package/dist/esm/lib/inference.js.map +1 -1
- package/dist/esm/lib/prompt.js +3 -1
- package/dist/esm/lib/prompt.js.map +1 -1
- package/dist/esm/lib/v3/agent/AgentProvider.js +3 -0
- package/dist/esm/lib/v3/agent/AgentProvider.js.map +1 -1
- package/dist/esm/lib/v3/agent/tools/fillFormVision.js +16 -12
- package/dist/esm/lib/v3/agent/tools/fillFormVision.js.map +1 -1
- package/dist/esm/lib/v3/agent/utils/validateExperimentalFeatures.js +0 -4
- package/dist/esm/lib/v3/agent/utils/validateExperimentalFeatures.js.map +1 -1
- package/dist/esm/lib/v3/api.d.ts +1 -0
- package/dist/esm/lib/v3/api.js +15 -3
- package/dist/esm/lib/v3/api.js.map +1 -1
- package/dist/esm/lib/v3/dom/build/a11yScripts.generated.js +1 -1
- package/dist/esm/lib/v3/dom/build/a11yScripts.generated.js.map +1 -1
- package/dist/esm/lib/v3/dom/build/locatorScripts.generated.js +1 -1
- package/dist/esm/lib/v3/dom/build/locatorScripts.generated.js.map +1 -1
- package/dist/esm/lib/v3/dom/build/reRenderScriptContent.d.ts +1 -1
- package/dist/esm/lib/v3/dom/build/reRenderScriptContent.js +1 -1
- package/dist/esm/lib/v3/dom/build/reRenderScriptContent.js.map +1 -1
- package/dist/esm/lib/v3/dom/build/screenshotScripts.generated.js +1 -1
- package/dist/esm/lib/v3/dom/build/screenshotScripts.generated.js.map +1 -1
- package/dist/esm/lib/v3/dom/build/scriptV3Content.d.ts +1 -1
- package/dist/esm/lib/v3/dom/build/scriptV3Content.js +1 -1
- package/dist/esm/lib/v3/dom/build/scriptV3Content.js.map +1 -1
- package/dist/esm/lib/v3/handlers/extractHandler.js +3 -1
- package/dist/esm/lib/v3/handlers/extractHandler.js.map +1 -1
- package/dist/esm/lib/v3/handlers/v3AgentHandler.js +3 -5
- package/dist/esm/lib/v3/handlers/v3AgentHandler.js.map +1 -1
- package/dist/esm/lib/v3/index.d.ts +1 -1
- package/dist/esm/lib/v3/llm/CerebrasClient.js +1 -1
- package/dist/esm/lib/v3/llm/CerebrasClient.js.map +1 -1
- package/dist/esm/lib/v3/llm/GroqClient.js +1 -1
- package/dist/esm/lib/v3/llm/GroqClient.js.map +1 -1
- package/dist/esm/lib/v3/types/private/agent.d.ts +5 -0
- package/dist/esm/lib/v3/types/private/agent.js +10 -1
- package/dist/esm/lib/v3/types/private/agent.js.map +1 -1
- package/dist/esm/lib/v3/types/private/handlers.d.ts +1 -0
- package/dist/esm/lib/v3/types/private/handlers.js.map +1 -1
- package/dist/esm/lib/v3/types/private/snapshot.d.ts +8 -0
- package/dist/esm/lib/v3/types/private/snapshot.js.map +1 -1
- package/dist/esm/lib/v3/types/public/agent.d.ts +2 -3
- package/dist/esm/lib/v3/types/public/agent.js +3 -0
- package/dist/esm/lib/v3/types/public/agent.js.map +1 -1
- package/dist/esm/lib/v3/types/public/api.d.ts +5 -1
- package/dist/esm/lib/v3/types/public/api.js +15 -2
- package/dist/esm/lib/v3/types/public/api.js.map +1 -1
- package/dist/esm/lib/v3/types/public/methods.d.ts +1 -0
- package/dist/esm/lib/v3/types/public/methods.js.map +1 -1
- package/dist/esm/lib/v3/understudy/a11y/snapshot/a11yTree.js +21 -12
- package/dist/esm/lib/v3/understudy/a11y/snapshot/a11yTree.js.map +1 -1
- package/dist/esm/lib/v3/understudy/a11y/snapshot/capture.d.ts +11 -2
- package/dist/esm/lib/v3/understudy/a11y/snapshot/capture.js +267 -22
- package/dist/esm/lib/v3/understudy/a11y/snapshot/capture.js.map +1 -1
- package/dist/esm/lib/v3/understudy/a11y/snapshot/domTree.js +60 -7
- package/dist/esm/lib/v3/understudy/a11y/snapshot/domTree.js.map +1 -1
- package/dist/esm/lib/v3/understudy/frameRegistry.js +16 -5
- package/dist/esm/lib/v3/understudy/frameRegistry.js.map +1 -1
- package/dist/esm/lib/v3/v3.d.ts +1 -0
- package/dist/esm/lib/v3/v3.js +15 -14
- package/dist/esm/lib/v3/v3.js.map +1 -1
- package/dist/esm/lib/version.d.ts +1 -1
- package/dist/esm/lib/version.js +1 -1
- package/dist/esm/lib/version.js.map +1 -1
- package/dist/esm/tests/integration/observe-element-id-format.spec.d.ts +1 -0
- package/dist/esm/tests/integration/observe-element-id-format.spec.js +128 -0
- package/dist/esm/tests/integration/observe-element-id-format.spec.js.map +1 -0
- package/dist/esm/tests/unit/agent-mode-routing.test.d.ts +1 -0
- package/dist/esm/tests/unit/agent-mode-routing.test.js +86 -0
- package/dist/esm/tests/unit/agent-mode-routing.test.js.map +1 -0
- package/dist/esm/tests/unit/agent-temperature.test.d.ts +1 -0
- package/dist/esm/tests/unit/agent-temperature.test.js +189 -0
- package/dist/esm/tests/unit/agent-temperature.test.js.map +1 -0
- package/dist/esm/tests/unit/agent-variables-validation.test.d.ts +1 -0
- package/dist/esm/tests/unit/agent-variables-validation.test.js +41 -0
- package/dist/esm/tests/unit/agent-variables-validation.test.js.map +1 -0
- package/dist/esm/tests/unit/api-client-observe-variables.test.js +47 -0
- package/dist/esm/tests/unit/api-client-observe-variables.test.js.map +1 -1
- package/dist/esm/tests/unit/api-optional-model-api-key.test.js +60 -0
- package/dist/esm/tests/unit/api-optional-model-api-key.test.js.map +1 -1
- package/dist/esm/tests/unit/api-variables-schema.test.js +25 -0
- package/dist/esm/tests/unit/api-variables-schema.test.js.map +1 -1
- package/dist/esm/tests/unit/frame-registry-oopif-adoption.test.d.ts +1 -0
- package/dist/esm/tests/unit/frame-registry-oopif-adoption.test.js +58 -0
- package/dist/esm/tests/unit/frame-registry-oopif-adoption.test.js.map +1 -0
- package/dist/esm/tests/unit/inference-temperature.test.d.ts +1 -0
- package/dist/esm/tests/unit/inference-temperature.test.js +63 -0
- package/dist/esm/tests/unit/inference-temperature.test.js.map +1 -0
- package/dist/esm/tests/unit/openai-compatible-temperature.test.d.ts +1 -0
- package/dist/esm/tests/unit/openai-compatible-temperature.test.js +82 -0
- package/dist/esm/tests/unit/openai-compatible-temperature.test.js.map +1 -0
- package/dist/esm/tests/unit/prompt-observe-variables.test.js +6 -0
- package/dist/esm/tests/unit/prompt-observe-variables.test.js.map +1 -1
- package/dist/esm/tests/unit/public-api/llm-and-agents.test.js +3 -0
- package/dist/esm/tests/unit/public-api/llm-and-agents.test.js.map +1 -1
- package/dist/esm/tests/unit/public-api/public-types.test.js.map +1 -1
- package/dist/esm/tests/unit/snapshot-a11y-resolvers.test.js +106 -5
- package/dist/esm/tests/unit/snapshot-a11y-resolvers.test.js.map +1 -1
- package/dist/esm/tests/unit/snapshot-a11y-tree-utils.test.js +20 -0
- package/dist/esm/tests/unit/snapshot-a11y-tree-utils.test.js.map +1 -1
- package/dist/esm/tests/unit/snapshot-capture-orchestration.test.js +119 -9
- package/dist/esm/tests/unit/snapshot-capture-orchestration.test.js.map +1 -1
- package/package.json +1 -1
- package/dist/cjs/tests/integration/agent-captcha-autosolve.spec.js +0 -56
- package/dist/cjs/tests/integration/agent-captcha-autosolve.spec.js.map +0 -1
- package/dist/esm/tests/integration/agent-captcha-autosolve.spec.js +0 -54
- package/dist/esm/tests/integration/agent-captcha-autosolve.spec.js.map +0 -1
- /package/dist/cjs/tests/integration/{agent-captcha-autosolve.spec.d.ts → observe-element-id-format.spec.d.ts} +0 -0
- /package/dist/{esm/tests/integration/agent-captcha-autosolve.spec.d.ts → cjs/tests/unit/agent-mode-routing.test.d.ts} +0 -0
|
@@ -38,6 +38,7 @@ const capture = __importStar(require("../../lib/v3/understudy/a11y/snapshot/capt
|
|
|
38
38
|
const a11yTree = __importStar(require("../../lib/v3/understudy/a11y/snapshot/a11yTree.js"));
|
|
39
39
|
const domTree = __importStar(require("../../lib/v3/understudy/a11y/snapshot/domTree.js"));
|
|
40
40
|
const focusSelectors = __importStar(require("../../lib/v3/understudy/a11y/snapshot/focusSelectors.js"));
|
|
41
|
+
const selectorResolver_js_1 = require("../../lib/v3/understudy/selectorResolver.js");
|
|
41
42
|
const mockCDPSession_js_1 = require("./helpers/mockCDPSession.js");
|
|
42
43
|
const makeProtocolFrame = (id) => ({
|
|
43
44
|
id,
|
|
@@ -89,6 +90,22 @@ const makeSessionIndex = () => ({
|
|
|
89
90
|
[201, 200],
|
|
90
91
|
]),
|
|
91
92
|
contentDocRootByIframe: new Map([[150, 200]]),
|
|
93
|
+
enterByBe: new Map([
|
|
94
|
+
[100, 0],
|
|
95
|
+
[101, 1],
|
|
96
|
+
[102, 2],
|
|
97
|
+
[150, 3],
|
|
98
|
+
[200, 4],
|
|
99
|
+
[201, 5],
|
|
100
|
+
]),
|
|
101
|
+
exitByBe: new Map([
|
|
102
|
+
[101, 6],
|
|
103
|
+
[102, 7],
|
|
104
|
+
[201, 8],
|
|
105
|
+
[200, 9],
|
|
106
|
+
[150, 10],
|
|
107
|
+
[100, 11],
|
|
108
|
+
]),
|
|
92
109
|
});
|
|
93
110
|
(0, vitest_1.beforeEach)(() => {
|
|
94
111
|
vitest_1.vi.restoreAllMocks();
|
|
@@ -189,7 +206,7 @@ const makeSessionIndex = () => ({
|
|
|
189
206
|
urlMap: { [`url-${frameId}`]: `https://${frameId}.test` },
|
|
190
207
|
scopeApplied: false,
|
|
191
208
|
}));
|
|
192
|
-
const result = await capture.collectPerFrameMaps(page, context, sessionToIndex, { experimental: true }, true, context.frames);
|
|
209
|
+
const result = await capture.collectPerFrameMaps(page, context, sessionToIndex, { experimental: true }, true, context.frames, new Map());
|
|
193
210
|
(0, vitest_1.expect)(result.perFrameOutlines).toEqual([
|
|
194
211
|
{ frameId: "frame-1", outline: "outline-frame-1" },
|
|
195
212
|
{ frameId: "frame-2", outline: "outline-frame-2" },
|
|
@@ -228,7 +245,7 @@ const makeSessionIndex = () => ({
|
|
|
228
245
|
scopeApplied: false,
|
|
229
246
|
});
|
|
230
247
|
const sessionToIndex = new Map();
|
|
231
|
-
const result = await capture.collectPerFrameMaps(page, context, sessionToIndex, undefined, false, context.frames);
|
|
248
|
+
const result = await capture.collectPerFrameMaps(page, context, sessionToIndex, undefined, false, context.frames, new Map());
|
|
232
249
|
(0, vitest_1.expect)(buildSpy).toHaveBeenCalledWith(session, false);
|
|
233
250
|
(0, vitest_1.expect)(sessionToIndex.get("new-session")).toBe(idx);
|
|
234
251
|
(0, vitest_1.expect)(result.perFrameMaps.get("frame-9")?.xpathMap["2-100"]).toBe("/");
|
|
@@ -254,7 +271,7 @@ const makeSessionIndex = () => ({
|
|
|
254
271
|
urlMap: {},
|
|
255
272
|
scopeApplied: false,
|
|
256
273
|
});
|
|
257
|
-
const result = await capture.collectPerFrameMaps(page, context, sessionToIndex, undefined, true, ["frame-1"]);
|
|
274
|
+
const result = await capture.collectPerFrameMaps(page, context, sessionToIndex, undefined, true, ["frame-1"], new Map());
|
|
258
275
|
(0, vitest_1.expect)(a11ySpy).toHaveBeenCalledTimes(1);
|
|
259
276
|
(0, vitest_1.expect)(result.perFrameMaps.has("frame-2")).toBe(false);
|
|
260
277
|
(0, vitest_1.expect)(result.perFrameOutlines.map((o) => o.frameId)).toEqual(["frame-1"]);
|
|
@@ -286,9 +303,7 @@ const makeSessionIndex = () => ({
|
|
|
286
303
|
});
|
|
287
304
|
const buildIndexSpy = vitest_1.vi
|
|
288
305
|
.spyOn(domTree, "buildSessionDomIndex")
|
|
289
|
-
.
|
|
290
|
-
throw new Error("should not build session index when scoped");
|
|
291
|
-
});
|
|
306
|
+
.mockResolvedValue(makeSessionIndex());
|
|
292
307
|
const result = await capture.captureHybridSnapshot(page, options);
|
|
293
308
|
(0, vitest_1.expect)(result.combinedTree).toBe("scoped outline");
|
|
294
309
|
(0, vitest_1.expect)(result.combinedUrlMap["0-100"]).toBe("https://frame-1.test");
|
|
@@ -321,9 +336,7 @@ const makeSessionIndex = () => ({
|
|
|
321
336
|
});
|
|
322
337
|
const buildIndexSpy = vitest_1.vi
|
|
323
338
|
.spyOn(domTree, "buildSessionDomIndex")
|
|
324
|
-
.
|
|
325
|
-
throw new Error("should not build session index when scoped");
|
|
326
|
-
});
|
|
339
|
+
.mockResolvedValue(makeSessionIndex());
|
|
327
340
|
const result = await capture.captureHybridSnapshot(page, options);
|
|
328
341
|
(0, vitest_1.expect)(result.combinedTree).toBe("scoped outline");
|
|
329
342
|
(0, vitest_1.expect)(result.combinedUrlMap["0-100"]).toBe("https://frame-1.test");
|
|
@@ -331,6 +344,103 @@ const makeSessionIndex = () => ({
|
|
|
331
344
|
(0, vitest_1.expect)(a11ySpy).toHaveBeenCalled();
|
|
332
345
|
(0, vitest_1.expect)(buildIndexSpy).not.toHaveBeenCalled();
|
|
333
346
|
});
|
|
347
|
+
(0, vitest_1.it)("filters ignored nodes out of the merged snapshot artifacts", async () => {
|
|
348
|
+
const session = new mockCDPSession_js_1.MockCDPSession({
|
|
349
|
+
"DOM.getFrameOwner": async () => ({ backendNodeId: 150 }),
|
|
350
|
+
"DOM.describeNode": async (params) => ({
|
|
351
|
+
node: {
|
|
352
|
+
backendNodeId: params?.objectId === "ignored-object-a"
|
|
353
|
+
? 201
|
|
354
|
+
: params?.objectId === "ignored-object-b"
|
|
355
|
+
? 202
|
|
356
|
+
: 0,
|
|
357
|
+
},
|
|
358
|
+
}),
|
|
359
|
+
}, "session-a");
|
|
360
|
+
const page = makePage({
|
|
361
|
+
asProtocolFrameTree: () => makeFrameTree("frame-1", [makeFrameTree("frame-2")]),
|
|
362
|
+
listAllFrameIds: () => ["frame-1", "frame-2"],
|
|
363
|
+
getSessionForFrame: () => session,
|
|
364
|
+
getOrdinal: (frameId) => (frameId === "frame-1" ? 0 : 1),
|
|
365
|
+
});
|
|
366
|
+
const idx = makeSessionIndex();
|
|
367
|
+
idx.absByBe.set(202, "/html[1]/body[1]/iframe[1]/aside[1]");
|
|
368
|
+
idx.tagByBe.set(202, "aside");
|
|
369
|
+
idx.docRootOf.set(202, 200);
|
|
370
|
+
idx.enterByBe.set(202, 6);
|
|
371
|
+
idx.exitByBe.set(202, 7);
|
|
372
|
+
idx.exitByBe.set(201, 8);
|
|
373
|
+
idx.exitByBe.set(200, 9);
|
|
374
|
+
idx.exitByBe.set(150, 10);
|
|
375
|
+
idx.exitByBe.set(100, 11);
|
|
376
|
+
vitest_1.vi.spyOn(domTree, "buildSessionDomIndex").mockResolvedValue(idx);
|
|
377
|
+
vitest_1.vi.spyOn(focusSelectors, "resolveCssFocusFrameAndTail").mockResolvedValue({
|
|
378
|
+
targetFrameId: "frame-2",
|
|
379
|
+
tailSelector: ".ad",
|
|
380
|
+
absPrefix: "/html/body/iframe[1]",
|
|
381
|
+
});
|
|
382
|
+
vitest_1.vi.spyOn(selectorResolver_js_1.FrameSelectorResolver.prototype, "resolveAll").mockResolvedValue([
|
|
383
|
+
{ objectId: "ignored-object-a", nodeId: null },
|
|
384
|
+
{ objectId: "ignored-object-b", nodeId: null },
|
|
385
|
+
]);
|
|
386
|
+
vitest_1.vi.spyOn(a11yTree, "a11yForFrame").mockImplementation(async (_sess, frameId, opts) => ({
|
|
387
|
+
outline: opts.isIgnoredBackendNode?.(201) && opts.isIgnoredBackendNode?.(202)
|
|
388
|
+
? `outline-${frameId}-filtered`
|
|
389
|
+
: `outline-${frameId}`,
|
|
390
|
+
urlMap: frameId === "frame-2" &&
|
|
391
|
+
opts.isIgnoredBackendNode?.(201) &&
|
|
392
|
+
opts.isIgnoredBackendNode?.(202)
|
|
393
|
+
? {}
|
|
394
|
+
: { [`url-${frameId}`]: `https://${frameId}.test` },
|
|
395
|
+
scopeApplied: false,
|
|
396
|
+
}));
|
|
397
|
+
const snapshot = await capture.captureHybridSnapshot(page, {
|
|
398
|
+
ignoreSelectors: [".ad"],
|
|
399
|
+
});
|
|
400
|
+
(0, vitest_1.expect)(snapshot.combinedXpathMap["1-201"]).toBeUndefined();
|
|
401
|
+
(0, vitest_1.expect)(snapshot.combinedXpathMap["1-202"]).toBeUndefined();
|
|
402
|
+
(0, vitest_1.expect)(snapshot.combinedUrlMap["url-frame-2"]).toBeUndefined();
|
|
403
|
+
(0, vitest_1.expect)(snapshot.perFrame?.find((frame) => frame.frameId === "frame-2")?.outline).toContain("filtered");
|
|
404
|
+
});
|
|
405
|
+
(0, vitest_1.it)("excludes child frame subtrees when an ignored node is an iframe host", async () => {
|
|
406
|
+
const session = new mockCDPSession_js_1.MockCDPSession({
|
|
407
|
+
"DOM.getFrameOwner": async () => ({ backendNodeId: 150 }),
|
|
408
|
+
"DOM.describeNode": async (params) => ({
|
|
409
|
+
node: { backendNodeId: params?.objectId === "iframe-host" ? 150 : 0 },
|
|
410
|
+
}),
|
|
411
|
+
}, "session-a");
|
|
412
|
+
const page = makePage({
|
|
413
|
+
asProtocolFrameTree: () => makeFrameTree("frame-1", [makeFrameTree("frame-2")]),
|
|
414
|
+
listAllFrameIds: () => ["frame-1", "frame-2"],
|
|
415
|
+
getSessionForFrame: () => session,
|
|
416
|
+
getOrdinal: (frameId) => (frameId === "frame-1" ? 0 : 1),
|
|
417
|
+
});
|
|
418
|
+
vitest_1.vi.spyOn(domTree, "buildSessionDomIndex").mockResolvedValue(makeSessionIndex());
|
|
419
|
+
vitest_1.vi.spyOn(focusSelectors, "resolveCssFocusFrameAndTail").mockResolvedValue({
|
|
420
|
+
targetFrameId: "frame-1",
|
|
421
|
+
tailSelector: "iframe.ad",
|
|
422
|
+
absPrefix: "",
|
|
423
|
+
});
|
|
424
|
+
vitest_1.vi.spyOn(selectorResolver_js_1.FrameSelectorResolver.prototype, "resolveAll").mockResolvedValue([
|
|
425
|
+
{ objectId: "iframe-host", nodeId: null },
|
|
426
|
+
]);
|
|
427
|
+
vitest_1.vi.spyOn(a11yTree, "a11yForFrame").mockImplementation(async (_sess, frameId, opts) => ({
|
|
428
|
+
outline: frameId === "frame-2" && opts.isIgnoredBackendNode?.(200)
|
|
429
|
+
? ""
|
|
430
|
+
: `outline-${frameId}`,
|
|
431
|
+
urlMap: frameId === "frame-2" && opts.isIgnoredBackendNode?.(200)
|
|
432
|
+
? {}
|
|
433
|
+
: { [`url-${frameId}`]: `https://${frameId}.test` },
|
|
434
|
+
scopeApplied: false,
|
|
435
|
+
}));
|
|
436
|
+
const snapshot = await capture.captureHybridSnapshot(page, {
|
|
437
|
+
ignoreSelectors: ["iframe.ad"],
|
|
438
|
+
});
|
|
439
|
+
(0, vitest_1.expect)(snapshot.combinedXpathMap["1-200"]).toBeUndefined();
|
|
440
|
+
(0, vitest_1.expect)(snapshot.combinedXpathMap["1-201"]).toBeUndefined();
|
|
441
|
+
(0, vitest_1.expect)(snapshot.combinedUrlMap["url-frame-2"]).toBeUndefined();
|
|
442
|
+
(0, vitest_1.expect)(snapshot.combinedTree).not.toContain("outline-frame-2");
|
|
443
|
+
});
|
|
334
444
|
(0, vitest_1.it)("collects per-frame data and merges it when no scoped snapshot is available", async () => {
|
|
335
445
|
const session = new mockCDPSession_js_1.MockCDPSession({
|
|
336
446
|
"DOM.getFrameOwner": async () => ({ backendNodeId: 150 }),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"snapshot-capture-orchestration.test.js","sourceRoot":"","sources":["../../../../tests/unit/snapshot-capture-orchestration.test.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Protocol } from \"devtools-protocol\";\nimport { beforeEach, describe, expect, it, vi } from \"vitest\";\nimport type { CDPSessionLike } from \"../../lib/v3/understudy/cdp.js\";\nimport type { Page } from \"../../lib/v3/understudy/page.js\";\nimport type {\n FrameContext,\n SessionDomIndex,\n} from \"../../lib/v3/types/private/index.js\";\nimport * as capture from \"../../lib/v3/understudy/a11y/snapshot/capture.js\";\nimport * as a11yTree from \"../../lib/v3/understudy/a11y/snapshot/a11yTree.js\";\nimport * as domTree from \"../../lib/v3/understudy/a11y/snapshot/domTree.js\";\nimport * as focusSelectors from \"../../lib/v3/understudy/a11y/snapshot/focusSelectors.js\";\nimport { MockCDPSession } from \"./helpers/mockCDPSession.js\";\n\nconst makeProtocolFrame = (id: string): Protocol.Page.Frame =>\n ({\n id,\n loaderId: `${id}-loader`,\n url: \"https://example.com\",\n securityOrigin: \"https://example.com\",\n mimeType: \"text/html\",\n }) as unknown as Protocol.Page.Frame;\n\nconst makeFrameTree = (\n id: string,\n children: Protocol.Page.FrameTree[] = [],\n): Protocol.Page.FrameTree => ({\n frame: makeProtocolFrame(id),\n childFrames: children,\n});\n\ntype PageStub = Pick<\n Page,\n | \"mainFrameId\"\n | \"asProtocolFrameTree\"\n | \"listAllFrameIds\"\n | \"getSessionForFrame\"\n | \"getOrdinal\"\n>;\n\nconst makePage = (overrides: Partial<PageStub> = {}): Page => {\n const defaultSession = new MockCDPSession({}, \"default-session\");\n const base: PageStub = {\n mainFrameId: () => \"frame-1\",\n asProtocolFrameTree: () => makeFrameTree(\"frame-1\"),\n listAllFrameIds: () => [\"frame-1\"],\n getSessionForFrame: () => defaultSession,\n getOrdinal: () => 0,\n };\n return { ...base, ...overrides } as unknown as Page;\n};\n\nconst makeSessionIndex = (): SessionDomIndex => ({\n rootBackend: 100,\n absByBe: new Map([\n [100, \"/\"],\n [101, \"/html[1]\"],\n [102, \"/html[1]/body[1]\"],\n [150, \"/html[1]/body[1]/iframe[1]\"],\n [200, \"/html[1]/body[1]/iframe[1]\"],\n [201, \"/html[1]/body[1]/iframe[1]/div[1]\"],\n ]),\n tagByBe: new Map([\n [100, \"#document\"],\n [101, \"html\"],\n [102, \"body\"],\n [150, \"iframe\"],\n [200, \"#document\"],\n [201, \"div\"],\n ]),\n scrollByBe: new Map([[201, true]]),\n docRootOf: new Map([\n [100, 100],\n [101, 100],\n [102, 100],\n [150, 100],\n [200, 200],\n [201, 200],\n ]),\n contentDocRootByIframe: new Map([[150, 200]]),\n});\n\nbeforeEach(() => {\n vi.restoreAllMocks();\n});\n\ndescribe(\"buildFrameContext\", () => {\n it(\"indexes parent relationships from the frame tree\", () => {\n const frameTree = makeFrameTree(\"frame-1\", [\n makeFrameTree(\"frame-2\", [makeFrameTree(\"frame-3\")]),\n makeFrameTree(\"frame-4\"),\n ]);\n const page = makePage({\n asProtocolFrameTree: () => frameTree,\n listAllFrameIds: () => [\"frame-1\", \"frame-2\", \"frame-3\", \"frame-4\"],\n });\n\n const context = capture.buildFrameContext(page);\n\n expect(context.rootId).toBe(\"frame-1\");\n expect(context.frames).toEqual([\n \"frame-1\",\n \"frame-2\",\n \"frame-3\",\n \"frame-4\",\n ]);\n expect(context.parentByFrame.get(\"frame-1\")).toBeNull();\n expect(context.parentByFrame.get(\"frame-2\")).toBe(\"frame-1\");\n expect(context.parentByFrame.get(\"frame-3\")).toBe(\"frame-2\");\n expect(context.parentByFrame.get(\"frame-4\")).toBe(\"frame-1\");\n });\n});\n\ndescribe(\"buildSessionIndexes\", () => {\n it(\"deduplicates frames that share the same CDP session id\", async () => {\n const session = new MockCDPSession({}, \"session-a\");\n const page = makePage({\n // Every frame lookup returns the same session instance, so buildSessionIndexes\n // should call buildSessionDomIndex only once and reuse the result.\n getSessionForFrame: () => session,\n });\n const idx = makeSessionIndex();\n const spy = vi\n .spyOn(domTree, \"buildSessionDomIndex\")\n .mockResolvedValue(idx);\n\n const result = await capture.buildSessionIndexes(\n page,\n [\"frame-1\", \"frame-2\"],\n true,\n );\n\n expect(spy).toHaveBeenCalledTimes(1); // only one DOM.getDocument per session id\n expect(spy).toHaveBeenCalledWith(session, true);\n expect(result.get(\"session-a\")).toBe(idx);\n });\n\n it(\"builds indexes for sessions without ids using the 'root' key\", async () => {\n const sessionWithoutId: CDPSessionLike = {\n id: undefined,\n async send<R = unknown>(\n _method: string,\n _params?: Record<string, unknown>,\n ): Promise<R> {\n void _method;\n void _params;\n return {} as R;\n },\n on() {},\n off() {},\n async close() {},\n };\n const sessionWithId = new MockCDPSession({}, \"child-session\");\n const page = makePage({\n getSessionForFrame: (frameId: string) =>\n frameId === \"frame-1\" ? sessionWithoutId : sessionWithId,\n });\n\n const idxA = makeSessionIndex();\n const idxB = makeSessionIndex();\n const spy = vi\n .spyOn(domTree, \"buildSessionDomIndex\")\n .mockResolvedValueOnce(idxA)\n .mockResolvedValueOnce(idxB);\n\n const result = await capture.buildSessionIndexes(\n page,\n [\"frame-1\", \"frame-2\"],\n false,\n );\n\n // Verifies the helper invokes buildSessionDomIndex once for each unique session,\n // keying anonymous sessions as \"root\" so downstream lookups remain stable.\n expect(spy).toHaveBeenNthCalledWith(1, sessionWithoutId, false);\n expect(spy).toHaveBeenNthCalledWith(2, sessionWithId, false);\n expect(result.get(\"root\")).toBe(idxA);\n expect(result.get(\"child-session\")).toBe(idxB);\n });\n});\n\ndescribe(\"collectPerFrameMaps\", () => {\n it(\"builds per-frame xpath/tag maps and outlines from a shared session index\", async () => {\n const session = new MockCDPSession(\n {\n \"DOM.getFrameOwner\": async () => ({ backendNodeId: 150 }),\n },\n \"session-a\",\n );\n const page = makePage({\n getSessionForFrame: () => session,\n getOrdinal: (frameId: string) => (frameId === \"frame-1\" ? 0 : 1),\n });\n const context: FrameContext = {\n rootId: \"frame-1\",\n frames: [\"frame-1\", \"frame-2\"],\n parentByFrame: new Map([\n [\"frame-1\", null],\n [\"frame-2\", \"frame-1\"],\n ]),\n };\n const sessionIndex = makeSessionIndex();\n const sessionToIndex = new Map([[session.id, sessionIndex]]);\n\n vi.spyOn(a11yTree, \"a11yForFrame\").mockImplementation(\n async (_sess, frameId) => ({\n outline: `outline-${frameId}`,\n urlMap: { [`url-${frameId}`]: `https://${frameId}.test` },\n scopeApplied: false,\n }),\n );\n\n const result = await capture.collectPerFrameMaps(\n page,\n context,\n sessionToIndex,\n { experimental: true },\n true,\n context.frames,\n );\n\n expect(result.perFrameOutlines).toEqual([\n { frameId: \"frame-1\", outline: \"outline-frame-1\" },\n { frameId: \"frame-2\", outline: \"outline-frame-2\" },\n ]);\n const rootMaps = result.perFrameMaps.get(\"frame-1\");\n expect(rootMaps?.xpathMap[\"0-100\"]).toBe(\"/\");\n expect(rootMaps?.xpathMap[\"0-101\"]).toBe(\"/html[1]\");\n expect(rootMaps?.xpathMap[\"0-102\"]).toBe(\"/html[1]/body[1]\");\n const childMaps = result.perFrameMaps.get(\"frame-2\");\n expect(childMaps?.xpathMap[\"1-200\"]).toBe(\"/\");\n expect(childMaps?.xpathMap[\"1-201\"]).toBe(\"/div[1]\");\n expect(childMaps?.scrollableMap[\"1-201\"]).toBe(true);\n expect(childMaps?.urlMap).toEqual({\n \"url-frame-2\": \"https://frame-2.test\",\n });\n expect(session.callsFor(\"DOM.getFrameOwner\")).toHaveLength(1);\n });\n\n it(\"builds a missing session index on demand and memoizes it\", async () => {\n const session = new MockCDPSession({}, \"new-session\");\n const page = makePage({\n getSessionForFrame: () => session,\n getOrdinal: () => 2,\n });\n const context: FrameContext = {\n rootId: \"frame-9\",\n frames: [\"frame-9\"],\n parentByFrame: new Map([[\"frame-9\", null]]),\n };\n const idx = makeSessionIndex();\n const buildSpy = vi\n .spyOn(domTree, \"buildSessionDomIndex\")\n .mockResolvedValue(idx);\n vi.spyOn(a11yTree, \"a11yForFrame\").mockResolvedValue({\n outline: \"outline\",\n urlMap: {},\n scopeApplied: false,\n });\n\n const sessionToIndex = new Map<string, SessionDomIndex>();\n const result = await capture.collectPerFrameMaps(\n page,\n context,\n sessionToIndex,\n undefined,\n false,\n context.frames,\n );\n\n expect(buildSpy).toHaveBeenCalledWith(session, false);\n expect(sessionToIndex.get(\"new-session\")).toBe(idx);\n expect(result.perFrameMaps.get(\"frame-9\")?.xpathMap[\"2-100\"]).toBe(\"/\");\n });\n\n it(\"skips frames that are not listed in the frameIds argument\", async () => {\n const session = new MockCDPSession({}, \"session-a\");\n const page = makePage({\n getSessionForFrame: () => session,\n getOrdinal: (frameId: string) => (frameId === \"frame-1\" ? 0 : 1),\n });\n const context: FrameContext = {\n rootId: \"frame-1\",\n frames: [\"frame-1\", \"frame-2\"],\n parentByFrame: new Map([\n [\"frame-1\", null],\n [\"frame-2\", \"frame-1\"],\n ]),\n };\n const sessionIndex = makeSessionIndex();\n const sessionToIndex = new Map([[session.id, sessionIndex]]);\n\n const a11ySpy = vi.spyOn(a11yTree, \"a11yForFrame\").mockResolvedValue({\n outline: \"outline\",\n urlMap: {},\n scopeApplied: false,\n });\n\n const result = await capture.collectPerFrameMaps(\n page,\n context,\n sessionToIndex,\n undefined,\n true,\n [\"frame-1\"],\n );\n\n expect(a11ySpy).toHaveBeenCalledTimes(1);\n expect(result.perFrameMaps.has(\"frame-2\")).toBe(false);\n expect(result.perFrameOutlines.map((o) => o.frameId)).toEqual([\"frame-1\"]);\n });\n});\n\ndescribe(\"captureHybridSnapshot\", () => {\n it(\"returns early when the scoped snapshot path succeeds\", async () => {\n const session = new MockCDPSession({}, \"session-a\");\n const page = makePage({\n getSessionForFrame: () => session,\n });\n const options = { focusSelector: \"/html\" };\n\n vi.spyOn(focusSelectors, \"resolveFocusFrameAndTail\").mockResolvedValue({\n targetFrameId: \"frame-1\",\n tailXPath: \"\",\n absPrefix: \"\",\n });\n const domMapsSpy = vi\n .spyOn(domTree, \"domMapsForSession\")\n .mockResolvedValue({\n tagNameMap: { \"0-100\": \"#document\" },\n xpathMap: { \"0-100\": \"/\" },\n scrollableMap: {},\n });\n const a11ySpy = vi.spyOn(a11yTree, \"a11yForFrame\").mockResolvedValue({\n outline: \"scoped outline\",\n urlMap: { \"0-100\": \"https://frame-1.test\" },\n scopeApplied: true,\n });\n const buildIndexSpy = vi\n .spyOn(domTree, \"buildSessionDomIndex\")\n .mockImplementation(() => {\n throw new Error(\"should not build session index when scoped\");\n });\n\n const result = await capture.captureHybridSnapshot(page, options);\n\n expect(result.combinedTree).toBe(\"scoped outline\");\n expect(result.combinedUrlMap[\"0-100\"]).toBe(\"https://frame-1.test\");\n expect(domMapsSpy).toHaveBeenCalled();\n expect(a11ySpy).toHaveBeenCalled();\n expect(buildIndexSpy).not.toHaveBeenCalled();\n });\n\n it(\"scoped snapshot still succeeds when iframe inclusion is disabled\", async () => {\n const session = new MockCDPSession({}, \"session-a\");\n const page = makePage({\n getSessionForFrame: () => session,\n });\n const options = { focusSelector: \"/html\", includeIframes: false };\n\n vi.spyOn(focusSelectors, \"resolveFocusFrameAndTail\").mockResolvedValue({\n targetFrameId: \"frame-1\",\n tailXPath: \"\",\n absPrefix: \"\",\n });\n const domMapsSpy = vi\n .spyOn(domTree, \"domMapsForSession\")\n .mockResolvedValue({\n tagNameMap: { \"0-100\": \"#document\" },\n xpathMap: { \"0-100\": \"/\" },\n scrollableMap: {},\n });\n const a11ySpy = vi.spyOn(a11yTree, \"a11yForFrame\").mockResolvedValue({\n outline: \"scoped outline\",\n urlMap: { \"0-100\": \"https://frame-1.test\" },\n scopeApplied: true,\n });\n const buildIndexSpy = vi\n .spyOn(domTree, \"buildSessionDomIndex\")\n .mockImplementation(() => {\n throw new Error(\"should not build session index when scoped\");\n });\n\n const result = await capture.captureHybridSnapshot(page, options);\n\n expect(result.combinedTree).toBe(\"scoped outline\");\n expect(result.combinedUrlMap[\"0-100\"]).toBe(\"https://frame-1.test\");\n expect(domMapsSpy).toHaveBeenCalled();\n expect(a11ySpy).toHaveBeenCalled();\n expect(buildIndexSpy).not.toHaveBeenCalled();\n });\n\n it(\"collects per-frame data and merges it when no scoped snapshot is available\", async () => {\n const session = new MockCDPSession(\n {\n \"DOM.getFrameOwner\": async () => ({ backendNodeId: 150 }),\n },\n \"session-a\",\n );\n const page = makePage({\n asProtocolFrameTree: () =>\n makeFrameTree(\"frame-1\", [makeFrameTree(\"frame-2\")]),\n listAllFrameIds: () => [\"frame-1\", \"frame-2\"],\n getSessionForFrame: () => session,\n getOrdinal: (frameId: string) => (frameId === \"frame-1\" ? 0 : 1),\n });\n\n const idx = makeSessionIndex();\n vi.spyOn(domTree, \"buildSessionDomIndex\").mockResolvedValue(idx);\n vi.spyOn(a11yTree, \"a11yForFrame\").mockImplementation(\n async (_sess, frameId) => ({\n outline:\n frameId === \"frame-1\"\n ? \"[0-150] iframe host\"\n : \"[1-200] child subtree\",\n urlMap: { [`url-${frameId}`]: `https://${frameId}.test` },\n scopeApplied: false,\n }),\n );\n\n const snapshot = await capture.captureHybridSnapshot(page);\n\n expect(snapshot.combinedTree).toContain(\"[1-200] child subtree\");\n expect(snapshot.combinedXpathMap[\"0-100\"]).toBe(\"/\");\n expect(snapshot.combinedXpathMap[\"1-201\"]).toBe(\n \"/html[1]/body[1]/iframe[1]/div[1]\",\n );\n expect(snapshot.combinedUrlMap[\"url-frame-2\"]).toBe(\"https://frame-2.test\");\n expect(snapshot.perFrame?.map((pf) => pf.frameId)).toEqual([\n \"frame-1\",\n \"frame-2\",\n ]);\n });\n\n it(\"omits iframe frames when includeIframes is false\", async () => {\n const session = new MockCDPSession(\n {\n \"DOM.getFrameOwner\": async () => ({ backendNodeId: 150 }),\n },\n \"session-a\",\n );\n const page = makePage({\n asProtocolFrameTree: () =>\n makeFrameTree(\"frame-1\", [makeFrameTree(\"frame-2\")]),\n listAllFrameIds: () => [\"frame-1\", \"frame-2\"],\n getSessionForFrame: () => session,\n getOrdinal: (frameId: string) => (frameId === \"frame-1\" ? 0 : 1),\n });\n\n const idx = makeSessionIndex();\n vi.spyOn(domTree, \"buildSessionDomIndex\").mockResolvedValue(idx);\n const a11ySpy = vi\n .spyOn(a11yTree, \"a11yForFrame\")\n .mockImplementation(async (_sess, frameId) => ({\n outline:\n frameId === \"frame-1\"\n ? \"[0-150] iframe host\"\n : \"[1-200] child subtree\",\n urlMap: { [`url-${frameId}`]: `https://${frameId}.test` },\n scopeApplied: false,\n }));\n\n const snapshot = await capture.captureHybridSnapshot(page, {\n includeIframes: false,\n });\n\n expect(a11ySpy).toHaveBeenCalledTimes(1);\n expect(session.callsFor(\"DOM.getFrameOwner\")).toHaveLength(0);\n expect(snapshot.perFrame?.map((pf) => pf.frameId)).toEqual([\"frame-1\"]);\n expect(snapshot.combinedXpathMap[\"1-201\"]).toBeUndefined();\n expect(snapshot.combinedTree).not.toContain(\"[1-200] child subtree\");\n });\n});\n"]}
|
|
1
|
+
{"version":3,"file":"snapshot-capture-orchestration.test.js","sourceRoot":"","sources":["../../../../tests/unit/snapshot-capture-orchestration.test.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Protocol } from \"devtools-protocol\";\nimport { beforeEach, describe, expect, it, vi } from \"vitest\";\nimport type { CDPSessionLike } from \"../../lib/v3/understudy/cdp.js\";\nimport type { Page } from \"../../lib/v3/understudy/page.js\";\nimport type {\n FrameContext,\n SessionDomIndex,\n} from \"../../lib/v3/types/private/index.js\";\nimport * as capture from \"../../lib/v3/understudy/a11y/snapshot/capture.js\";\nimport * as a11yTree from \"../../lib/v3/understudy/a11y/snapshot/a11yTree.js\";\nimport * as domTree from \"../../lib/v3/understudy/a11y/snapshot/domTree.js\";\nimport * as focusSelectors from \"../../lib/v3/understudy/a11y/snapshot/focusSelectors.js\";\nimport { FrameSelectorResolver } from \"../../lib/v3/understudy/selectorResolver.js\";\nimport { MockCDPSession } from \"./helpers/mockCDPSession.js\";\n\nconst makeProtocolFrame = (id: string): Protocol.Page.Frame =>\n ({\n id,\n loaderId: `${id}-loader`,\n url: \"https://example.com\",\n securityOrigin: \"https://example.com\",\n mimeType: \"text/html\",\n }) as unknown as Protocol.Page.Frame;\n\nconst makeFrameTree = (\n id: string,\n children: Protocol.Page.FrameTree[] = [],\n): Protocol.Page.FrameTree => ({\n frame: makeProtocolFrame(id),\n childFrames: children,\n});\n\ntype PageStub = Pick<\n Page,\n | \"mainFrameId\"\n | \"asProtocolFrameTree\"\n | \"listAllFrameIds\"\n | \"getSessionForFrame\"\n | \"getOrdinal\"\n>;\n\nconst makePage = (overrides: Partial<PageStub> = {}): Page => {\n const defaultSession = new MockCDPSession({}, \"default-session\");\n const base: PageStub = {\n mainFrameId: () => \"frame-1\",\n asProtocolFrameTree: () => makeFrameTree(\"frame-1\"),\n listAllFrameIds: () => [\"frame-1\"],\n getSessionForFrame: () => defaultSession,\n getOrdinal: () => 0,\n };\n return { ...base, ...overrides } as unknown as Page;\n};\n\nconst makeSessionIndex = (): SessionDomIndex => ({\n rootBackend: 100,\n absByBe: new Map([\n [100, \"/\"],\n [101, \"/html[1]\"],\n [102, \"/html[1]/body[1]\"],\n [150, \"/html[1]/body[1]/iframe[1]\"],\n [200, \"/html[1]/body[1]/iframe[1]\"],\n [201, \"/html[1]/body[1]/iframe[1]/div[1]\"],\n ]),\n tagByBe: new Map([\n [100, \"#document\"],\n [101, \"html\"],\n [102, \"body\"],\n [150, \"iframe\"],\n [200, \"#document\"],\n [201, \"div\"],\n ]),\n scrollByBe: new Map([[201, true]]),\n docRootOf: new Map([\n [100, 100],\n [101, 100],\n [102, 100],\n [150, 100],\n [200, 200],\n [201, 200],\n ]),\n contentDocRootByIframe: new Map([[150, 200]]),\n enterByBe: new Map([\n [100, 0],\n [101, 1],\n [102, 2],\n [150, 3],\n [200, 4],\n [201, 5],\n ]),\n exitByBe: new Map([\n [101, 6],\n [102, 7],\n [201, 8],\n [200, 9],\n [150, 10],\n [100, 11],\n ]),\n});\n\nbeforeEach(() => {\n vi.restoreAllMocks();\n});\n\ndescribe(\"buildFrameContext\", () => {\n it(\"indexes parent relationships from the frame tree\", () => {\n const frameTree = makeFrameTree(\"frame-1\", [\n makeFrameTree(\"frame-2\", [makeFrameTree(\"frame-3\")]),\n makeFrameTree(\"frame-4\"),\n ]);\n const page = makePage({\n asProtocolFrameTree: () => frameTree,\n listAllFrameIds: () => [\"frame-1\", \"frame-2\", \"frame-3\", \"frame-4\"],\n });\n\n const context = capture.buildFrameContext(page);\n\n expect(context.rootId).toBe(\"frame-1\");\n expect(context.frames).toEqual([\n \"frame-1\",\n \"frame-2\",\n \"frame-3\",\n \"frame-4\",\n ]);\n expect(context.parentByFrame.get(\"frame-1\")).toBeNull();\n expect(context.parentByFrame.get(\"frame-2\")).toBe(\"frame-1\");\n expect(context.parentByFrame.get(\"frame-3\")).toBe(\"frame-2\");\n expect(context.parentByFrame.get(\"frame-4\")).toBe(\"frame-1\");\n });\n});\n\ndescribe(\"buildSessionIndexes\", () => {\n it(\"deduplicates frames that share the same CDP session id\", async () => {\n const session = new MockCDPSession({}, \"session-a\");\n const page = makePage({\n // Every frame lookup returns the same session instance, so buildSessionIndexes\n // should call buildSessionDomIndex only once and reuse the result.\n getSessionForFrame: () => session,\n });\n const idx = makeSessionIndex();\n const spy = vi\n .spyOn(domTree, \"buildSessionDomIndex\")\n .mockResolvedValue(idx);\n\n const result = await capture.buildSessionIndexes(\n page,\n [\"frame-1\", \"frame-2\"],\n true,\n );\n\n expect(spy).toHaveBeenCalledTimes(1); // only one DOM.getDocument per session id\n expect(spy).toHaveBeenCalledWith(session, true);\n expect(result.get(\"session-a\")).toBe(idx);\n });\n\n it(\"builds indexes for sessions without ids using the 'root' key\", async () => {\n const sessionWithoutId: CDPSessionLike = {\n id: undefined,\n async send<R = unknown>(\n _method: string,\n _params?: Record<string, unknown>,\n ): Promise<R> {\n void _method;\n void _params;\n return {} as R;\n },\n on() {},\n off() {},\n async close() {},\n };\n const sessionWithId = new MockCDPSession({}, \"child-session\");\n const page = makePage({\n getSessionForFrame: (frameId: string) =>\n frameId === \"frame-1\" ? sessionWithoutId : sessionWithId,\n });\n\n const idxA = makeSessionIndex();\n const idxB = makeSessionIndex();\n const spy = vi\n .spyOn(domTree, \"buildSessionDomIndex\")\n .mockResolvedValueOnce(idxA)\n .mockResolvedValueOnce(idxB);\n\n const result = await capture.buildSessionIndexes(\n page,\n [\"frame-1\", \"frame-2\"],\n false,\n );\n\n // Verifies the helper invokes buildSessionDomIndex once for each unique session,\n // keying anonymous sessions as \"root\" so downstream lookups remain stable.\n expect(spy).toHaveBeenNthCalledWith(1, sessionWithoutId, false);\n expect(spy).toHaveBeenNthCalledWith(2, sessionWithId, false);\n expect(result.get(\"root\")).toBe(idxA);\n expect(result.get(\"child-session\")).toBe(idxB);\n });\n});\n\ndescribe(\"collectPerFrameMaps\", () => {\n it(\"builds per-frame xpath/tag maps and outlines from a shared session index\", async () => {\n const session = new MockCDPSession(\n {\n \"DOM.getFrameOwner\": async () => ({ backendNodeId: 150 }),\n },\n \"session-a\",\n );\n const page = makePage({\n getSessionForFrame: () => session,\n getOrdinal: (frameId: string) => (frameId === \"frame-1\" ? 0 : 1),\n });\n const context: FrameContext = {\n rootId: \"frame-1\",\n frames: [\"frame-1\", \"frame-2\"],\n parentByFrame: new Map([\n [\"frame-1\", null],\n [\"frame-2\", \"frame-1\"],\n ]),\n };\n const sessionIndex = makeSessionIndex();\n const sessionToIndex = new Map([[session.id, sessionIndex]]);\n\n vi.spyOn(a11yTree, \"a11yForFrame\").mockImplementation(\n async (_sess, frameId) => ({\n outline: `outline-${frameId}`,\n urlMap: { [`url-${frameId}`]: `https://${frameId}.test` },\n scopeApplied: false,\n }),\n );\n\n const result = await capture.collectPerFrameMaps(\n page,\n context,\n sessionToIndex,\n { experimental: true },\n true,\n context.frames,\n new Map(),\n );\n\n expect(result.perFrameOutlines).toEqual([\n { frameId: \"frame-1\", outline: \"outline-frame-1\" },\n { frameId: \"frame-2\", outline: \"outline-frame-2\" },\n ]);\n const rootMaps = result.perFrameMaps.get(\"frame-1\");\n expect(rootMaps?.xpathMap[\"0-100\"]).toBe(\"/\");\n expect(rootMaps?.xpathMap[\"0-101\"]).toBe(\"/html[1]\");\n expect(rootMaps?.xpathMap[\"0-102\"]).toBe(\"/html[1]/body[1]\");\n const childMaps = result.perFrameMaps.get(\"frame-2\");\n expect(childMaps?.xpathMap[\"1-200\"]).toBe(\"/\");\n expect(childMaps?.xpathMap[\"1-201\"]).toBe(\"/div[1]\");\n expect(childMaps?.scrollableMap[\"1-201\"]).toBe(true);\n expect(childMaps?.urlMap).toEqual({\n \"url-frame-2\": \"https://frame-2.test\",\n });\n expect(session.callsFor(\"DOM.getFrameOwner\")).toHaveLength(1);\n });\n\n it(\"builds a missing session index on demand and memoizes it\", async () => {\n const session = new MockCDPSession({}, \"new-session\");\n const page = makePage({\n getSessionForFrame: () => session,\n getOrdinal: () => 2,\n });\n const context: FrameContext = {\n rootId: \"frame-9\",\n frames: [\"frame-9\"],\n parentByFrame: new Map([[\"frame-9\", null]]),\n };\n const idx = makeSessionIndex();\n const buildSpy = vi\n .spyOn(domTree, \"buildSessionDomIndex\")\n .mockResolvedValue(idx);\n vi.spyOn(a11yTree, \"a11yForFrame\").mockResolvedValue({\n outline: \"outline\",\n urlMap: {},\n scopeApplied: false,\n });\n\n const sessionToIndex = new Map<string, SessionDomIndex>();\n const result = await capture.collectPerFrameMaps(\n page,\n context,\n sessionToIndex,\n undefined,\n false,\n context.frames,\n new Map(),\n );\n\n expect(buildSpy).toHaveBeenCalledWith(session, false);\n expect(sessionToIndex.get(\"new-session\")).toBe(idx);\n expect(result.perFrameMaps.get(\"frame-9\")?.xpathMap[\"2-100\"]).toBe(\"/\");\n });\n\n it(\"skips frames that are not listed in the frameIds argument\", async () => {\n const session = new MockCDPSession({}, \"session-a\");\n const page = makePage({\n getSessionForFrame: () => session,\n getOrdinal: (frameId: string) => (frameId === \"frame-1\" ? 0 : 1),\n });\n const context: FrameContext = {\n rootId: \"frame-1\",\n frames: [\"frame-1\", \"frame-2\"],\n parentByFrame: new Map([\n [\"frame-1\", null],\n [\"frame-2\", \"frame-1\"],\n ]),\n };\n const sessionIndex = makeSessionIndex();\n const sessionToIndex = new Map([[session.id, sessionIndex]]);\n\n const a11ySpy = vi.spyOn(a11yTree, \"a11yForFrame\").mockResolvedValue({\n outline: \"outline\",\n urlMap: {},\n scopeApplied: false,\n });\n\n const result = await capture.collectPerFrameMaps(\n page,\n context,\n sessionToIndex,\n undefined,\n true,\n [\"frame-1\"],\n new Map(),\n );\n\n expect(a11ySpy).toHaveBeenCalledTimes(1);\n expect(result.perFrameMaps.has(\"frame-2\")).toBe(false);\n expect(result.perFrameOutlines.map((o) => o.frameId)).toEqual([\"frame-1\"]);\n });\n});\n\ndescribe(\"captureHybridSnapshot\", () => {\n it(\"returns early when the scoped snapshot path succeeds\", async () => {\n const session = new MockCDPSession({}, \"session-a\");\n const page = makePage({\n getSessionForFrame: () => session,\n });\n const options = { focusSelector: \"/html\" };\n\n vi.spyOn(focusSelectors, \"resolveFocusFrameAndTail\").mockResolvedValue({\n targetFrameId: \"frame-1\",\n tailXPath: \"\",\n absPrefix: \"\",\n });\n const domMapsSpy = vi\n .spyOn(domTree, \"domMapsForSession\")\n .mockResolvedValue({\n tagNameMap: { \"0-100\": \"#document\" },\n xpathMap: { \"0-100\": \"/\" },\n scrollableMap: {},\n });\n const a11ySpy = vi.spyOn(a11yTree, \"a11yForFrame\").mockResolvedValue({\n outline: \"scoped outline\",\n urlMap: { \"0-100\": \"https://frame-1.test\" },\n scopeApplied: true,\n });\n const buildIndexSpy = vi\n .spyOn(domTree, \"buildSessionDomIndex\")\n .mockResolvedValue(makeSessionIndex());\n\n const result = await capture.captureHybridSnapshot(page, options);\n\n expect(result.combinedTree).toBe(\"scoped outline\");\n expect(result.combinedUrlMap[\"0-100\"]).toBe(\"https://frame-1.test\");\n expect(domMapsSpy).toHaveBeenCalled();\n expect(a11ySpy).toHaveBeenCalled();\n expect(buildIndexSpy).not.toHaveBeenCalled();\n });\n\n it(\"scoped snapshot still succeeds when iframe inclusion is disabled\", async () => {\n const session = new MockCDPSession({}, \"session-a\");\n const page = makePage({\n getSessionForFrame: () => session,\n });\n const options = { focusSelector: \"/html\", includeIframes: false };\n\n vi.spyOn(focusSelectors, \"resolveFocusFrameAndTail\").mockResolvedValue({\n targetFrameId: \"frame-1\",\n tailXPath: \"\",\n absPrefix: \"\",\n });\n const domMapsSpy = vi\n .spyOn(domTree, \"domMapsForSession\")\n .mockResolvedValue({\n tagNameMap: { \"0-100\": \"#document\" },\n xpathMap: { \"0-100\": \"/\" },\n scrollableMap: {},\n });\n const a11ySpy = vi.spyOn(a11yTree, \"a11yForFrame\").mockResolvedValue({\n outline: \"scoped outline\",\n urlMap: { \"0-100\": \"https://frame-1.test\" },\n scopeApplied: true,\n });\n const buildIndexSpy = vi\n .spyOn(domTree, \"buildSessionDomIndex\")\n .mockResolvedValue(makeSessionIndex());\n\n const result = await capture.captureHybridSnapshot(page, options);\n\n expect(result.combinedTree).toBe(\"scoped outline\");\n expect(result.combinedUrlMap[\"0-100\"]).toBe(\"https://frame-1.test\");\n expect(domMapsSpy).toHaveBeenCalled();\n expect(a11ySpy).toHaveBeenCalled();\n expect(buildIndexSpy).not.toHaveBeenCalled();\n });\n\n it(\"filters ignored nodes out of the merged snapshot artifacts\", async () => {\n const session = new MockCDPSession(\n {\n \"DOM.getFrameOwner\": async () => ({ backendNodeId: 150 }),\n \"DOM.describeNode\": async (params) => ({\n node: {\n backendNodeId:\n params?.objectId === \"ignored-object-a\"\n ? 201\n : params?.objectId === \"ignored-object-b\"\n ? 202\n : 0,\n },\n }),\n },\n \"session-a\",\n );\n const page = makePage({\n asProtocolFrameTree: () =>\n makeFrameTree(\"frame-1\", [makeFrameTree(\"frame-2\")]),\n listAllFrameIds: () => [\"frame-1\", \"frame-2\"],\n getSessionForFrame: () => session,\n getOrdinal: (frameId: string) => (frameId === \"frame-1\" ? 0 : 1),\n });\n\n const idx = makeSessionIndex();\n idx.absByBe.set(202, \"/html[1]/body[1]/iframe[1]/aside[1]\");\n idx.tagByBe.set(202, \"aside\");\n idx.docRootOf.set(202, 200);\n idx.enterByBe.set(202, 6);\n idx.exitByBe.set(202, 7);\n idx.exitByBe.set(201, 8);\n idx.exitByBe.set(200, 9);\n idx.exitByBe.set(150, 10);\n idx.exitByBe.set(100, 11);\n vi.spyOn(domTree, \"buildSessionDomIndex\").mockResolvedValue(idx);\n vi.spyOn(focusSelectors, \"resolveCssFocusFrameAndTail\").mockResolvedValue({\n targetFrameId: \"frame-2\",\n tailSelector: \".ad\",\n absPrefix: \"/html/body/iframe[1]\",\n });\n vi.spyOn(FrameSelectorResolver.prototype, \"resolveAll\").mockResolvedValue([\n { objectId: \"ignored-object-a\", nodeId: null },\n { objectId: \"ignored-object-b\", nodeId: null },\n ]);\n vi.spyOn(a11yTree, \"a11yForFrame\").mockImplementation(\n async (_sess, frameId, opts) => ({\n outline:\n opts.isIgnoredBackendNode?.(201) && opts.isIgnoredBackendNode?.(202)\n ? `outline-${frameId}-filtered`\n : `outline-${frameId}`,\n urlMap:\n frameId === \"frame-2\" &&\n opts.isIgnoredBackendNode?.(201) &&\n opts.isIgnoredBackendNode?.(202)\n ? {}\n : { [`url-${frameId}`]: `https://${frameId}.test` },\n scopeApplied: false,\n }),\n );\n\n const snapshot = await capture.captureHybridSnapshot(page, {\n ignoreSelectors: [\".ad\"],\n });\n\n expect(snapshot.combinedXpathMap[\"1-201\"]).toBeUndefined();\n expect(snapshot.combinedXpathMap[\"1-202\"]).toBeUndefined();\n expect(snapshot.combinedUrlMap[\"url-frame-2\"]).toBeUndefined();\n expect(\n snapshot.perFrame?.find((frame) => frame.frameId === \"frame-2\")?.outline,\n ).toContain(\"filtered\");\n });\n\n it(\"excludes child frame subtrees when an ignored node is an iframe host\", async () => {\n const session = new MockCDPSession(\n {\n \"DOM.getFrameOwner\": async () => ({ backendNodeId: 150 }),\n \"DOM.describeNode\": async (params) => ({\n node: { backendNodeId: params?.objectId === \"iframe-host\" ? 150 : 0 },\n }),\n },\n \"session-a\",\n );\n const page = makePage({\n asProtocolFrameTree: () =>\n makeFrameTree(\"frame-1\", [makeFrameTree(\"frame-2\")]),\n listAllFrameIds: () => [\"frame-1\", \"frame-2\"],\n getSessionForFrame: () => session,\n getOrdinal: (frameId: string) => (frameId === \"frame-1\" ? 0 : 1),\n });\n\n vi.spyOn(domTree, \"buildSessionDomIndex\").mockResolvedValue(\n makeSessionIndex(),\n );\n vi.spyOn(focusSelectors, \"resolveCssFocusFrameAndTail\").mockResolvedValue({\n targetFrameId: \"frame-1\",\n tailSelector: \"iframe.ad\",\n absPrefix: \"\",\n });\n vi.spyOn(FrameSelectorResolver.prototype, \"resolveAll\").mockResolvedValue([\n { objectId: \"iframe-host\", nodeId: null },\n ]);\n vi.spyOn(a11yTree, \"a11yForFrame\").mockImplementation(\n async (_sess, frameId, opts) => ({\n outline:\n frameId === \"frame-2\" && opts.isIgnoredBackendNode?.(200)\n ? \"\"\n : `outline-${frameId}`,\n urlMap:\n frameId === \"frame-2\" && opts.isIgnoredBackendNode?.(200)\n ? {}\n : { [`url-${frameId}`]: `https://${frameId}.test` },\n scopeApplied: false,\n }),\n );\n\n const snapshot = await capture.captureHybridSnapshot(page, {\n ignoreSelectors: [\"iframe.ad\"],\n });\n\n expect(snapshot.combinedXpathMap[\"1-200\"]).toBeUndefined();\n expect(snapshot.combinedXpathMap[\"1-201\"]).toBeUndefined();\n expect(snapshot.combinedUrlMap[\"url-frame-2\"]).toBeUndefined();\n expect(snapshot.combinedTree).not.toContain(\"outline-frame-2\");\n });\n\n it(\"collects per-frame data and merges it when no scoped snapshot is available\", async () => {\n const session = new MockCDPSession(\n {\n \"DOM.getFrameOwner\": async () => ({ backendNodeId: 150 }),\n },\n \"session-a\",\n );\n const page = makePage({\n asProtocolFrameTree: () =>\n makeFrameTree(\"frame-1\", [makeFrameTree(\"frame-2\")]),\n listAllFrameIds: () => [\"frame-1\", \"frame-2\"],\n getSessionForFrame: () => session,\n getOrdinal: (frameId: string) => (frameId === \"frame-1\" ? 0 : 1),\n });\n\n const idx = makeSessionIndex();\n vi.spyOn(domTree, \"buildSessionDomIndex\").mockResolvedValue(idx);\n vi.spyOn(a11yTree, \"a11yForFrame\").mockImplementation(\n async (_sess, frameId) => ({\n outline:\n frameId === \"frame-1\"\n ? \"[0-150] iframe host\"\n : \"[1-200] child subtree\",\n urlMap: { [`url-${frameId}`]: `https://${frameId}.test` },\n scopeApplied: false,\n }),\n );\n\n const snapshot = await capture.captureHybridSnapshot(page);\n\n expect(snapshot.combinedTree).toContain(\"[1-200] child subtree\");\n expect(snapshot.combinedXpathMap[\"0-100\"]).toBe(\"/\");\n expect(snapshot.combinedXpathMap[\"1-201\"]).toBe(\n \"/html[1]/body[1]/iframe[1]/div[1]\",\n );\n expect(snapshot.combinedUrlMap[\"url-frame-2\"]).toBe(\"https://frame-2.test\");\n expect(snapshot.perFrame?.map((pf) => pf.frameId)).toEqual([\n \"frame-1\",\n \"frame-2\",\n ]);\n });\n\n it(\"omits iframe frames when includeIframes is false\", async () => {\n const session = new MockCDPSession(\n {\n \"DOM.getFrameOwner\": async () => ({ backendNodeId: 150 }),\n },\n \"session-a\",\n );\n const page = makePage({\n asProtocolFrameTree: () =>\n makeFrameTree(\"frame-1\", [makeFrameTree(\"frame-2\")]),\n listAllFrameIds: () => [\"frame-1\", \"frame-2\"],\n getSessionForFrame: () => session,\n getOrdinal: (frameId: string) => (frameId === \"frame-1\" ? 0 : 1),\n });\n\n const idx = makeSessionIndex();\n vi.spyOn(domTree, \"buildSessionDomIndex\").mockResolvedValue(idx);\n const a11ySpy = vi\n .spyOn(a11yTree, \"a11yForFrame\")\n .mockImplementation(async (_sess, frameId) => ({\n outline:\n frameId === \"frame-1\"\n ? \"[0-150] iframe host\"\n : \"[1-200] child subtree\",\n urlMap: { [`url-${frameId}`]: `https://${frameId}.test` },\n scopeApplied: false,\n }));\n\n const snapshot = await capture.captureHybridSnapshot(page, {\n includeIframes: false,\n });\n\n expect(a11ySpy).toHaveBeenCalledTimes(1);\n expect(session.callsFor(\"DOM.getFrameOwner\")).toHaveLength(0);\n expect(snapshot.perFrame?.map((pf) => pf.frameId)).toEqual([\"frame-1\"]);\n expect(snapshot.combinedXpathMap[\"1-201\"]).toBeUndefined();\n expect(snapshot.combinedTree).not.toContain(\"[1-200] child subtree\");\n });\n});\n"]}
|
|
@@ -16,7 +16,6 @@ export async function extract({ instruction, domElements, schema, llmClient, log
|
|
|
16
16
|
.describe("true if the goal is now accomplished. Use this conservatively, only when sure that the goal has been completed."),
|
|
17
17
|
});
|
|
18
18
|
const isUsingAnthropic = llmClient.type === "anthropic";
|
|
19
|
-
const isGPT5 = llmClient.modelName.includes("gpt-5"); // TODO: remove this as we update support for gpt-5 configuration options
|
|
20
19
|
const extractCallMessages = [
|
|
21
20
|
buildExtractSystemPrompt(isUsingAnthropic, userProvidedInstructions),
|
|
22
21
|
buildExtractUserPrompt(instruction, domElements, isUsingAnthropic),
|
|
@@ -39,7 +38,6 @@ export async function extract({ instruction, domElements, schema, llmClient, log
|
|
|
39
38
|
schema,
|
|
40
39
|
name: "Extraction",
|
|
41
40
|
},
|
|
42
|
-
temperature: isGPT5 ? 1 : 0.1,
|
|
43
41
|
top_p: 1,
|
|
44
42
|
frequency_penalty: 0,
|
|
45
43
|
presence_penalty: 0,
|
|
@@ -89,7 +87,6 @@ export async function extract({ instruction, domElements, schema, llmClient, log
|
|
|
89
87
|
name: "Metadata",
|
|
90
88
|
schema: metadataSchema,
|
|
91
89
|
},
|
|
92
|
-
temperature: isGPT5 ? 1 : 0.1,
|
|
93
90
|
top_p: 1,
|
|
94
91
|
frequency_penalty: 0,
|
|
95
92
|
presence_penalty: 0,
|
|
@@ -141,14 +138,13 @@ export async function extract({ instruction, domElements, schema, llmClient, log
|
|
|
141
138
|
};
|
|
142
139
|
}
|
|
143
140
|
export async function observe({ instruction, domElements, llmClient, userProvidedInstructions, logger, logInferenceToFile = false, supportedActions, variables, }) {
|
|
144
|
-
const isGPT5 = llmClient.modelName.includes("gpt-5"); // TODO: remove this as we update support for gpt-5 configuration options
|
|
145
141
|
const observeSchema = z.object({
|
|
146
142
|
elements: z
|
|
147
143
|
.array(z.object({
|
|
148
144
|
elementId: z
|
|
149
145
|
.string()
|
|
150
146
|
.regex(/^\d+-\d+$/)
|
|
151
|
-
.describe("the ID string associated with the element. Never include surrounding square brackets. This field must follow the format of 'number-number'."),
|
|
147
|
+
.describe("the exact ID string associated with the element. Never include surrounding square brackets. This field must follow the format of 'number-number'. For example, if the accessibility tree shows [0-18372], return '0-18372', not '18372'."),
|
|
152
148
|
description: z
|
|
153
149
|
.string()
|
|
154
150
|
.describe("a description of the accessible element and its purpose"),
|
|
@@ -185,7 +181,6 @@ export async function observe({ instruction, domElements, llmClient, userProvide
|
|
|
185
181
|
schema: observeSchema,
|
|
186
182
|
name: "Observation",
|
|
187
183
|
},
|
|
188
|
-
temperature: isGPT5 ? 1 : 0.1,
|
|
189
184
|
top_p: 1,
|
|
190
185
|
frequency_penalty: 0,
|
|
191
186
|
presence_penalty: 0,
|
|
@@ -237,7 +232,6 @@ export async function observe({ instruction, domElements, llmClient, userProvide
|
|
|
237
232
|
};
|
|
238
233
|
}
|
|
239
234
|
export async function act({ instruction, domElements, llmClient, userProvidedInstructions, logger, logInferenceToFile = false, }) {
|
|
240
|
-
const isGPT5 = llmClient.modelName.includes("gpt-5"); // TODO: remove this as we update support for gpt-5 configuration options
|
|
241
235
|
const actSchema = z.object({
|
|
242
236
|
action: z
|
|
243
237
|
.object({
|
|
@@ -259,7 +253,7 @@ export async function act({ instruction, domElements, llmClient, userProvidedIns
|
|
|
259
253
|
})
|
|
260
254
|
.nullable()
|
|
261
255
|
.describe("The element to act on. Return null if no element on the page matches the instruction — do NOT fabricate or guess an element, and never emit empty strings or placeholder values."),
|
|
262
|
-
twoStep: z.boolean()
|
|
256
|
+
twoStep: z.boolean(),
|
|
263
257
|
});
|
|
264
258
|
const messages = [
|
|
265
259
|
buildActSystemPrompt(userProvidedInstructions),
|
|
@@ -283,7 +277,6 @@ export async function act({ instruction, domElements, llmClient, userProvidedIns
|
|
|
283
277
|
schema: actSchema,
|
|
284
278
|
name: "act",
|
|
285
279
|
},
|
|
286
|
-
temperature: isGPT5 ? 1 : 0.1,
|
|
287
280
|
top_p: 1,
|
|
288
281
|
frequency_penalty: 0,
|
|
289
282
|
presence_penalty: 0,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inference.js","sourceRoot":"","sources":["../../../lib/inference.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from \"zod\";\nimport { LogLine } from \"./v3/types/public/logs.js\";\nimport { ChatMessage, LLMClient } from \"./v3/llm/LLMClient.js\";\nimport { getEnvTimeoutMs, withTimeout } from \"./v3/timeoutConfig.js\";\nimport {\n buildActSystemPrompt,\n buildExtractSystemPrompt,\n buildExtractUserPrompt,\n buildMetadataPrompt,\n buildMetadataSystemPrompt,\n buildObserveSystemPrompt,\n buildObserveUserMessage,\n} from \"./prompt.js\";\nimport { appendSummary, writeTimestampedTxtFile } from \"./inferenceLogUtils.js\";\nimport type {\n InferStagehandSchema,\n StagehandZodObject,\n} from \"./v3/zodCompat.js\";\nimport { SupportedUnderstudyAction } from \"./v3/types/private/handlers.js\";\nimport type { Variables } from \"./v3/types/public/agent.js\";\n\n// Re-export for backward compatibility\nexport type { LLMParsedResponse, LLMUsage } from \"./v3/llm/LLMClient.js\";\n\nfunction withLlmTimeout<T>(promise: Promise<T>, operation: string): Promise<T> {\n return withTimeout(\n promise,\n getEnvTimeoutMs(\"LLM_MAX_MS\"),\n `LLM ${operation}`,\n );\n}\n\nexport async function extract<T extends StagehandZodObject>({\n instruction,\n domElements,\n schema,\n llmClient,\n logger,\n userProvidedInstructions,\n logInferenceToFile = false,\n}: {\n instruction: string;\n domElements: string;\n schema: T;\n llmClient: LLMClient;\n userProvidedInstructions?: string;\n logger: (message: LogLine) => void;\n logInferenceToFile?: boolean;\n}) {\n const metadataSchema = z.object({\n progress: z\n .string()\n .describe(\n \"progress of what has been extracted so far, as concise as possible\",\n ),\n completed: z\n .boolean()\n .describe(\n \"true if the goal is now accomplished. Use this conservatively, only when sure that the goal has been completed.\",\n ),\n });\n\n type ExtractionResponse = InferStagehandSchema<T>;\n type MetadataResponse = z.infer<typeof metadataSchema>;\n\n const isUsingAnthropic = llmClient.type === \"anthropic\";\n const isGPT5 = llmClient.modelName.includes(\"gpt-5\"); // TODO: remove this as we update support for gpt-5 configuration options\n\n const extractCallMessages: ChatMessage[] = [\n buildExtractSystemPrompt(isUsingAnthropic, userProvidedInstructions),\n buildExtractUserPrompt(instruction, domElements, isUsingAnthropic),\n ];\n\n let extractCallFile = \"\";\n let extractCallTimestamp = \"\";\n if (logInferenceToFile) {\n const { fileName, timestamp } = writeTimestampedTxtFile(\n \"extract_summary\",\n \"extract_call\",\n {\n modelCall: \"extract\",\n messages: extractCallMessages,\n },\n );\n extractCallFile = fileName;\n extractCallTimestamp = timestamp;\n }\n\n const extractStartTime = Date.now();\n const extractionResponse = await withLlmTimeout(\n llmClient.createChatCompletion<ExtractionResponse>({\n options: {\n messages: extractCallMessages,\n response_model: {\n schema,\n name: \"Extraction\",\n },\n temperature: isGPT5 ? 1 : 0.1,\n top_p: 1,\n frequency_penalty: 0,\n presence_penalty: 0,\n },\n logger,\n }),\n \"extract\",\n );\n const extractEndTime = Date.now();\n\n const { data: extractedData, usage: extractUsage } = extractionResponse;\n\n let extractResponseFile: string;\n if (logInferenceToFile) {\n const { fileName } = writeTimestampedTxtFile(\n \"extract_summary\",\n \"extract_response\",\n {\n modelResponse: \"extract\",\n rawResponse: extractedData,\n },\n );\n extractResponseFile = fileName;\n\n appendSummary(\"extract\", {\n extract_inference_type: \"extract\",\n timestamp: extractCallTimestamp,\n LLM_input_file: extractCallFile,\n LLM_output_file: extractResponseFile,\n prompt_tokens: extractUsage?.prompt_tokens ?? 0,\n completion_tokens: extractUsage?.completion_tokens ?? 0,\n reasoning_tokens: extractUsage?.reasoning_tokens ?? 0,\n cached_input_tokens: extractUsage?.cached_input_tokens ?? 0,\n inference_time_ms: extractEndTime - extractStartTime,\n });\n }\n\n const metadataCallMessages: ChatMessage[] = [\n buildMetadataSystemPrompt(),\n buildMetadataPrompt(instruction, extractedData),\n ];\n\n let metadataCallFile = \"\";\n let metadataCallTimestamp = \"\";\n if (logInferenceToFile) {\n const { fileName, timestamp } = writeTimestampedTxtFile(\n \"extract_summary\",\n \"metadata_call\",\n {\n modelCall: \"metadata\",\n messages: metadataCallMessages,\n },\n );\n metadataCallFile = fileName;\n metadataCallTimestamp = timestamp;\n }\n\n const metadataStartTime = Date.now();\n const metadataResponse = await withLlmTimeout(\n llmClient.createChatCompletion<MetadataResponse>({\n options: {\n messages: metadataCallMessages,\n response_model: {\n name: \"Metadata\",\n schema: metadataSchema,\n },\n temperature: isGPT5 ? 1 : 0.1,\n top_p: 1,\n frequency_penalty: 0,\n presence_penalty: 0,\n },\n logger,\n }),\n \"extract metadata\",\n );\n const metadataEndTime = Date.now();\n\n const {\n data: {\n completed: metadataResponseCompleted,\n progress: metadataResponseProgress,\n },\n usage: metadataResponseUsage,\n } = metadataResponse;\n\n let metadataResponseFile: string;\n if (logInferenceToFile) {\n const { fileName } = writeTimestampedTxtFile(\n \"extract_summary\",\n \"metadata_response\",\n {\n modelResponse: \"metadata\",\n completed: metadataResponseCompleted,\n progress: metadataResponseProgress,\n },\n );\n metadataResponseFile = fileName;\n\n appendSummary(\"extract\", {\n extract_inference_type: \"metadata\",\n timestamp: metadataCallTimestamp,\n LLM_input_file: metadataCallFile,\n LLM_output_file: metadataResponseFile,\n prompt_tokens: metadataResponseUsage?.prompt_tokens ?? 0,\n completion_tokens: metadataResponseUsage?.completion_tokens ?? 0,\n reasoning_tokens: metadataResponseUsage?.reasoning_tokens ?? 0,\n cached_input_tokens: metadataResponseUsage?.cached_input_tokens ?? 0,\n inference_time_ms: metadataEndTime - metadataStartTime,\n });\n }\n\n const totalPromptTokens =\n (extractUsage?.prompt_tokens ?? 0) +\n (metadataResponseUsage?.prompt_tokens ?? 0);\n\n const totalCompletionTokens =\n (extractUsage?.completion_tokens ?? 0) +\n (metadataResponseUsage?.completion_tokens ?? 0);\n\n const totalInferenceTimeMs =\n extractEndTime - extractStartTime + (metadataEndTime - metadataStartTime);\n const totalReasoningTokens =\n (extractUsage?.reasoning_tokens ?? 0) +\n (metadataResponseUsage?.reasoning_tokens ?? 0);\n const totalCachedInputTokens =\n (extractUsage?.cached_input_tokens ?? 0) +\n (metadataResponseUsage?.cached_input_tokens ?? 0);\n\n return {\n ...extractedData,\n metadata: {\n completed: metadataResponseCompleted,\n progress: metadataResponseProgress,\n },\n prompt_tokens: totalPromptTokens,\n completion_tokens: totalCompletionTokens,\n reasoning_tokens: totalReasoningTokens,\n cached_input_tokens: totalCachedInputTokens,\n inference_time_ms: totalInferenceTimeMs,\n };\n}\n\nexport async function observe({\n instruction,\n domElements,\n llmClient,\n userProvidedInstructions,\n logger,\n logInferenceToFile = false,\n supportedActions,\n variables,\n}: {\n instruction: string;\n domElements: string;\n llmClient: LLMClient;\n userProvidedInstructions?: string;\n logger: (message: LogLine) => void;\n logInferenceToFile?: boolean;\n supportedActions?: string[];\n variables?: Variables;\n}) {\n const isGPT5 = llmClient.modelName.includes(\"gpt-5\"); // TODO: remove this as we update support for gpt-5 configuration options\n\n const observeSchema = z.object({\n elements: z\n .array(\n z.object({\n elementId: z\n .string()\n .regex(/^\\d+-\\d+$/)\n .describe(\n \"the ID string associated with the element. Never include surrounding square brackets. This field must follow the format of 'number-number'.\",\n ),\n description: z\n .string()\n .describe(\n \"a description of the accessible element and its purpose\",\n ),\n method: z\n .enum(\n // Use Object.values() for Zod v3 compatibility - z.enum() in v3 doesn't accept TypeScript enums directly\n Object.values(SupportedUnderstudyAction) as unknown as readonly [\n string,\n ...string[],\n ],\n )\n .describe(\n `the candidate method/action to interact with the element. Select one of the available Understudy interaction methods.`,\n ),\n arguments: z.array(\n z\n .string()\n .describe(\n \"the arguments to pass to the method. For example, for a click, the arguments are empty, but for a fill, the arguments are the value to fill in.\",\n ),\n ),\n }),\n )\n .describe(\"an array of accessible elements that match the instruction\"),\n });\n\n type ObserveResponse = z.infer<typeof observeSchema>;\n\n const messages: ChatMessage[] = [\n buildObserveSystemPrompt(\n userProvidedInstructions,\n supportedActions,\n variables,\n ),\n buildObserveUserMessage(instruction, domElements),\n ];\n\n let callTimestamp = \"\";\n let callFile = \"\";\n if (logInferenceToFile) {\n const { fileName, timestamp } = writeTimestampedTxtFile(\n `observe_summary`,\n `observe_call`,\n {\n modelCall: \"observe\",\n messages,\n },\n );\n callFile = fileName;\n callTimestamp = timestamp;\n }\n\n const start = Date.now();\n const rawResponse = await llmClient.createChatCompletion<ObserveResponse>({\n options: {\n messages,\n response_model: {\n schema: observeSchema,\n name: \"Observation\",\n },\n temperature: isGPT5 ? 1 : 0.1,\n top_p: 1,\n frequency_penalty: 0,\n presence_penalty: 0,\n },\n logger,\n });\n const end = Date.now();\n const usageTimeMs = end - start;\n\n const { data: observeData, usage: observeUsage } = rawResponse;\n const promptTokens = observeUsage?.prompt_tokens ?? 0;\n const completionTokens = observeUsage?.completion_tokens ?? 0;\n const reasoningTokens = observeUsage?.reasoning_tokens ?? 0;\n const cachedInputTokens = observeUsage?.cached_input_tokens ?? 0;\n\n let responseFile: string;\n if (logInferenceToFile) {\n const { fileName: responseFileName } = writeTimestampedTxtFile(\n `observe_summary`,\n `observe_response`,\n {\n modelResponse: \"observe\",\n rawResponse: observeData,\n },\n );\n responseFile = responseFileName;\n\n appendSummary(\"observe\", {\n [`observe_inference_type`]: \"observe\",\n timestamp: callTimestamp,\n LLM_input_file: callFile,\n LLM_output_file: responseFile,\n prompt_tokens: promptTokens,\n completion_tokens: completionTokens,\n reasoning_tokens: reasoningTokens,\n cached_input_tokens: cachedInputTokens,\n inference_time_ms: usageTimeMs,\n });\n }\n\n const parsedElements =\n observeData.elements?.map((el) => {\n const base = {\n elementId: el.elementId,\n description: String(el.description),\n method: String(el.method),\n arguments: el.arguments,\n };\n return base;\n }) ?? [];\n\n return {\n elements: parsedElements,\n prompt_tokens: promptTokens,\n completion_tokens: completionTokens,\n reasoning_tokens: reasoningTokens,\n cached_input_tokens: cachedInputTokens,\n inference_time_ms: usageTimeMs,\n };\n}\n\nexport async function act({\n instruction,\n domElements,\n llmClient,\n userProvidedInstructions,\n logger,\n logInferenceToFile = false,\n}: {\n instruction: string;\n domElements: string;\n llmClient: LLMClient;\n userProvidedInstructions?: string;\n logger: (message: LogLine) => void;\n logInferenceToFile?: boolean;\n}) {\n const isGPT5 = llmClient.modelName.includes(\"gpt-5\"); // TODO: remove this as we update support for gpt-5 configuration options\n\n const actSchema = z.object({\n action: z\n .object({\n elementId: z\n .string()\n .regex(/^\\d+-\\d+$/)\n .describe(\n \"the ID string associated with the element. Never include surrounding square brackets. This field must follow the format of 'number-number'. for example, '0-76' or '16-21'\",\n ),\n description: z\n .string()\n .describe(\"a description of the accessible element and its purpose\"),\n method: z\n .enum(\n // Use Object.values() for Zod v3 compatibility - z.enum() in v3 doesn't accept TypeScript enums directly\n Object.values(SupportedUnderstudyAction) as unknown as readonly [\n string,\n ...string[],\n ],\n )\n .describe(\n \"the candidate method/action to interact with the element. Select one of the available Understudy interaction methods.\",\n ),\n arguments: z.array(\n z\n .string()\n .describe(\n \"the arguments to pass to the method. For example, for a click, the arguments are empty, but for a fill, the arguments are the value to fill in.\",\n ),\n ),\n })\n .nullable()\n .describe(\n \"The element to act on. Return null if no element on the page matches the instruction — do NOT fabricate or guess an element, and never emit empty strings or placeholder values.\",\n ),\n twoStep: z.boolean().default(false),\n });\n\n type ActResponse = z.infer<typeof actSchema>;\n\n const messages: ChatMessage[] = [\n buildActSystemPrompt(userProvidedInstructions),\n buildObserveUserMessage(instruction, domElements),\n ];\n\n let callTimestamp = \"\";\n let callFile = \"\";\n if (logInferenceToFile) {\n const { fileName, timestamp } = writeTimestampedTxtFile(\n `act_summary`,\n `act_call`,\n {\n modelCall: \"act\",\n messages,\n },\n );\n callFile = fileName;\n callTimestamp = timestamp;\n }\n\n const start = Date.now();\n const rawResponse = await llmClient.createChatCompletion<ActResponse>({\n options: {\n messages,\n response_model: {\n schema: actSchema,\n name: \"act\",\n },\n temperature: isGPT5 ? 1 : 0.1,\n top_p: 1,\n frequency_penalty: 0,\n presence_penalty: 0,\n },\n logger,\n });\n const end = Date.now();\n const usageTimeMs = end - start;\n\n const { data: actData, usage: actUsage } = rawResponse;\n const promptTokens = actUsage?.prompt_tokens ?? 0;\n const completionTokens = actUsage?.completion_tokens ?? 0;\n const reasoningTokens = actUsage?.reasoning_tokens ?? 0;\n const cachedInputTokens = actUsage?.cached_input_tokens ?? 0;\n\n let responseFile: string;\n if (logInferenceToFile) {\n const { fileName: responseFileName } = writeTimestampedTxtFile(\n `act_summary`,\n `act_response`,\n {\n modelResponse: \"act\",\n rawResponse: actData,\n },\n );\n responseFile = responseFileName;\n\n appendSummary(\"act\", {\n [`act_inference_type`]: \"act\",\n timestamp: callTimestamp,\n LLM_input_file: callFile,\n LLM_output_file: responseFile,\n prompt_tokens: promptTokens,\n completion_tokens: completionTokens,\n reasoning_tokens: reasoningTokens,\n cached_input_tokens: cachedInputTokens,\n inference_time_ms: usageTimeMs,\n });\n }\n\n const parsedElement = actData.action\n ? {\n elementId: actData.action.elementId,\n description: String(actData.action.description),\n method: String(actData.action.method),\n arguments: actData.action.arguments,\n }\n : undefined;\n\n return {\n element: parsedElement,\n prompt_tokens: promptTokens,\n completion_tokens: completionTokens,\n reasoning_tokens: reasoningTokens,\n cached_input_tokens: cachedInputTokens,\n inference_time_ms: usageTimeMs,\n twoStep: actData.twoStep,\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"inference.js","sourceRoot":"","sources":["../../../lib/inference.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from \"zod\";\nimport { LogLine } from \"./v3/types/public/logs.js\";\nimport { ChatMessage, LLMClient } from \"./v3/llm/LLMClient.js\";\nimport { getEnvTimeoutMs, withTimeout } from \"./v3/timeoutConfig.js\";\nimport {\n buildActSystemPrompt,\n buildExtractSystemPrompt,\n buildExtractUserPrompt,\n buildMetadataPrompt,\n buildMetadataSystemPrompt,\n buildObserveSystemPrompt,\n buildObserveUserMessage,\n} from \"./prompt.js\";\nimport { appendSummary, writeTimestampedTxtFile } from \"./inferenceLogUtils.js\";\nimport type {\n InferStagehandSchema,\n StagehandZodObject,\n} from \"./v3/zodCompat.js\";\nimport { SupportedUnderstudyAction } from \"./v3/types/private/handlers.js\";\nimport type { Variables } from \"./v3/types/public/agent.js\";\n\n// Re-export for backward compatibility\nexport type { LLMParsedResponse, LLMUsage } from \"./v3/llm/LLMClient.js\";\n\nfunction withLlmTimeout<T>(promise: Promise<T>, operation: string): Promise<T> {\n return withTimeout(\n promise,\n getEnvTimeoutMs(\"LLM_MAX_MS\"),\n `LLM ${operation}`,\n );\n}\n\nexport async function extract<T extends StagehandZodObject>({\n instruction,\n domElements,\n schema,\n llmClient,\n logger,\n userProvidedInstructions,\n logInferenceToFile = false,\n}: {\n instruction: string;\n domElements: string;\n schema: T;\n llmClient: LLMClient;\n userProvidedInstructions?: string;\n logger: (message: LogLine) => void;\n logInferenceToFile?: boolean;\n}) {\n const metadataSchema = z.object({\n progress: z\n .string()\n .describe(\n \"progress of what has been extracted so far, as concise as possible\",\n ),\n completed: z\n .boolean()\n .describe(\n \"true if the goal is now accomplished. Use this conservatively, only when sure that the goal has been completed.\",\n ),\n });\n\n type ExtractionResponse = InferStagehandSchema<T>;\n type MetadataResponse = z.infer<typeof metadataSchema>;\n\n const isUsingAnthropic = llmClient.type === \"anthropic\";\n\n const extractCallMessages: ChatMessage[] = [\n buildExtractSystemPrompt(isUsingAnthropic, userProvidedInstructions),\n buildExtractUserPrompt(instruction, domElements, isUsingAnthropic),\n ];\n\n let extractCallFile = \"\";\n let extractCallTimestamp = \"\";\n if (logInferenceToFile) {\n const { fileName, timestamp } = writeTimestampedTxtFile(\n \"extract_summary\",\n \"extract_call\",\n {\n modelCall: \"extract\",\n messages: extractCallMessages,\n },\n );\n extractCallFile = fileName;\n extractCallTimestamp = timestamp;\n }\n\n const extractStartTime = Date.now();\n const extractionResponse = await withLlmTimeout(\n llmClient.createChatCompletion<ExtractionResponse>({\n options: {\n messages: extractCallMessages,\n response_model: {\n schema,\n name: \"Extraction\",\n },\n top_p: 1,\n frequency_penalty: 0,\n presence_penalty: 0,\n },\n logger,\n }),\n \"extract\",\n );\n const extractEndTime = Date.now();\n\n const { data: extractedData, usage: extractUsage } = extractionResponse;\n\n let extractResponseFile: string;\n if (logInferenceToFile) {\n const { fileName } = writeTimestampedTxtFile(\n \"extract_summary\",\n \"extract_response\",\n {\n modelResponse: \"extract\",\n rawResponse: extractedData,\n },\n );\n extractResponseFile = fileName;\n\n appendSummary(\"extract\", {\n extract_inference_type: \"extract\",\n timestamp: extractCallTimestamp,\n LLM_input_file: extractCallFile,\n LLM_output_file: extractResponseFile,\n prompt_tokens: extractUsage?.prompt_tokens ?? 0,\n completion_tokens: extractUsage?.completion_tokens ?? 0,\n reasoning_tokens: extractUsage?.reasoning_tokens ?? 0,\n cached_input_tokens: extractUsage?.cached_input_tokens ?? 0,\n inference_time_ms: extractEndTime - extractStartTime,\n });\n }\n\n const metadataCallMessages: ChatMessage[] = [\n buildMetadataSystemPrompt(),\n buildMetadataPrompt(instruction, extractedData),\n ];\n\n let metadataCallFile = \"\";\n let metadataCallTimestamp = \"\";\n if (logInferenceToFile) {\n const { fileName, timestamp } = writeTimestampedTxtFile(\n \"extract_summary\",\n \"metadata_call\",\n {\n modelCall: \"metadata\",\n messages: metadataCallMessages,\n },\n );\n metadataCallFile = fileName;\n metadataCallTimestamp = timestamp;\n }\n\n const metadataStartTime = Date.now();\n const metadataResponse = await withLlmTimeout(\n llmClient.createChatCompletion<MetadataResponse>({\n options: {\n messages: metadataCallMessages,\n response_model: {\n name: \"Metadata\",\n schema: metadataSchema,\n },\n top_p: 1,\n frequency_penalty: 0,\n presence_penalty: 0,\n },\n logger,\n }),\n \"extract metadata\",\n );\n const metadataEndTime = Date.now();\n\n const {\n data: {\n completed: metadataResponseCompleted,\n progress: metadataResponseProgress,\n },\n usage: metadataResponseUsage,\n } = metadataResponse;\n\n let metadataResponseFile: string;\n if (logInferenceToFile) {\n const { fileName } = writeTimestampedTxtFile(\n \"extract_summary\",\n \"metadata_response\",\n {\n modelResponse: \"metadata\",\n completed: metadataResponseCompleted,\n progress: metadataResponseProgress,\n },\n );\n metadataResponseFile = fileName;\n\n appendSummary(\"extract\", {\n extract_inference_type: \"metadata\",\n timestamp: metadataCallTimestamp,\n LLM_input_file: metadataCallFile,\n LLM_output_file: metadataResponseFile,\n prompt_tokens: metadataResponseUsage?.prompt_tokens ?? 0,\n completion_tokens: metadataResponseUsage?.completion_tokens ?? 0,\n reasoning_tokens: metadataResponseUsage?.reasoning_tokens ?? 0,\n cached_input_tokens: metadataResponseUsage?.cached_input_tokens ?? 0,\n inference_time_ms: metadataEndTime - metadataStartTime,\n });\n }\n\n const totalPromptTokens =\n (extractUsage?.prompt_tokens ?? 0) +\n (metadataResponseUsage?.prompt_tokens ?? 0);\n\n const totalCompletionTokens =\n (extractUsage?.completion_tokens ?? 0) +\n (metadataResponseUsage?.completion_tokens ?? 0);\n\n const totalInferenceTimeMs =\n extractEndTime - extractStartTime + (metadataEndTime - metadataStartTime);\n const totalReasoningTokens =\n (extractUsage?.reasoning_tokens ?? 0) +\n (metadataResponseUsage?.reasoning_tokens ?? 0);\n const totalCachedInputTokens =\n (extractUsage?.cached_input_tokens ?? 0) +\n (metadataResponseUsage?.cached_input_tokens ?? 0);\n\n return {\n ...extractedData,\n metadata: {\n completed: metadataResponseCompleted,\n progress: metadataResponseProgress,\n },\n prompt_tokens: totalPromptTokens,\n completion_tokens: totalCompletionTokens,\n reasoning_tokens: totalReasoningTokens,\n cached_input_tokens: totalCachedInputTokens,\n inference_time_ms: totalInferenceTimeMs,\n };\n}\n\nexport async function observe({\n instruction,\n domElements,\n llmClient,\n userProvidedInstructions,\n logger,\n logInferenceToFile = false,\n supportedActions,\n variables,\n}: {\n instruction: string;\n domElements: string;\n llmClient: LLMClient;\n userProvidedInstructions?: string;\n logger: (message: LogLine) => void;\n logInferenceToFile?: boolean;\n supportedActions?: string[];\n variables?: Variables;\n}) {\n const observeSchema = z.object({\n elements: z\n .array(\n z.object({\n elementId: z\n .string()\n .regex(/^\\d+-\\d+$/)\n .describe(\n \"the exact ID string associated with the element. Never include surrounding square brackets. This field must follow the format of 'number-number'. For example, if the accessibility tree shows [0-18372], return '0-18372', not '18372'.\",\n ),\n description: z\n .string()\n .describe(\n \"a description of the accessible element and its purpose\",\n ),\n method: z\n .enum(\n // Use Object.values() for Zod v3 compatibility - z.enum() in v3 doesn't accept TypeScript enums directly\n Object.values(SupportedUnderstudyAction) as unknown as readonly [\n string,\n ...string[],\n ],\n )\n .describe(\n `the candidate method/action to interact with the element. Select one of the available Understudy interaction methods.`,\n ),\n arguments: z.array(\n z\n .string()\n .describe(\n \"the arguments to pass to the method. For example, for a click, the arguments are empty, but for a fill, the arguments are the value to fill in.\",\n ),\n ),\n }),\n )\n .describe(\"an array of accessible elements that match the instruction\"),\n });\n\n type ObserveResponse = z.infer<typeof observeSchema>;\n\n const messages: ChatMessage[] = [\n buildObserveSystemPrompt(\n userProvidedInstructions,\n supportedActions,\n variables,\n ),\n buildObserveUserMessage(instruction, domElements),\n ];\n\n let callTimestamp = \"\";\n let callFile = \"\";\n if (logInferenceToFile) {\n const { fileName, timestamp } = writeTimestampedTxtFile(\n `observe_summary`,\n `observe_call`,\n {\n modelCall: \"observe\",\n messages,\n },\n );\n callFile = fileName;\n callTimestamp = timestamp;\n }\n\n const start = Date.now();\n const rawResponse = await llmClient.createChatCompletion<ObserveResponse>({\n options: {\n messages,\n response_model: {\n schema: observeSchema,\n name: \"Observation\",\n },\n top_p: 1,\n frequency_penalty: 0,\n presence_penalty: 0,\n },\n logger,\n });\n const end = Date.now();\n const usageTimeMs = end - start;\n\n const { data: observeData, usage: observeUsage } = rawResponse;\n const promptTokens = observeUsage?.prompt_tokens ?? 0;\n const completionTokens = observeUsage?.completion_tokens ?? 0;\n const reasoningTokens = observeUsage?.reasoning_tokens ?? 0;\n const cachedInputTokens = observeUsage?.cached_input_tokens ?? 0;\n\n let responseFile: string;\n if (logInferenceToFile) {\n const { fileName: responseFileName } = writeTimestampedTxtFile(\n `observe_summary`,\n `observe_response`,\n {\n modelResponse: \"observe\",\n rawResponse: observeData,\n },\n );\n responseFile = responseFileName;\n\n appendSummary(\"observe\", {\n [`observe_inference_type`]: \"observe\",\n timestamp: callTimestamp,\n LLM_input_file: callFile,\n LLM_output_file: responseFile,\n prompt_tokens: promptTokens,\n completion_tokens: completionTokens,\n reasoning_tokens: reasoningTokens,\n cached_input_tokens: cachedInputTokens,\n inference_time_ms: usageTimeMs,\n });\n }\n\n const parsedElements =\n observeData.elements?.map((el) => {\n const base = {\n elementId: el.elementId,\n description: String(el.description),\n method: String(el.method),\n arguments: el.arguments,\n };\n return base;\n }) ?? [];\n\n return {\n elements: parsedElements,\n prompt_tokens: promptTokens,\n completion_tokens: completionTokens,\n reasoning_tokens: reasoningTokens,\n cached_input_tokens: cachedInputTokens,\n inference_time_ms: usageTimeMs,\n };\n}\n\nexport async function act({\n instruction,\n domElements,\n llmClient,\n userProvidedInstructions,\n logger,\n logInferenceToFile = false,\n}: {\n instruction: string;\n domElements: string;\n llmClient: LLMClient;\n userProvidedInstructions?: string;\n logger: (message: LogLine) => void;\n logInferenceToFile?: boolean;\n}) {\n const actSchema = z.object({\n action: z\n .object({\n elementId: z\n .string()\n .regex(/^\\d+-\\d+$/)\n .describe(\n \"the ID string associated with the element. Never include surrounding square brackets. This field must follow the format of 'number-number'. for example, '0-76' or '16-21'\",\n ),\n description: z\n .string()\n .describe(\"a description of the accessible element and its purpose\"),\n method: z\n .enum(\n // Use Object.values() for Zod v3 compatibility - z.enum() in v3 doesn't accept TypeScript enums directly\n Object.values(SupportedUnderstudyAction) as unknown as readonly [\n string,\n ...string[],\n ],\n )\n .describe(\n \"the candidate method/action to interact with the element. Select one of the available Understudy interaction methods.\",\n ),\n arguments: z.array(\n z\n .string()\n .describe(\n \"the arguments to pass to the method. For example, for a click, the arguments are empty, but for a fill, the arguments are the value to fill in.\",\n ),\n ),\n })\n .nullable()\n .describe(\n \"The element to act on. Return null if no element on the page matches the instruction — do NOT fabricate or guess an element, and never emit empty strings or placeholder values.\",\n ),\n twoStep: z.boolean(),\n });\n\n type ActResponse = z.infer<typeof actSchema>;\n\n const messages: ChatMessage[] = [\n buildActSystemPrompt(userProvidedInstructions),\n buildObserveUserMessage(instruction, domElements),\n ];\n\n let callTimestamp = \"\";\n let callFile = \"\";\n if (logInferenceToFile) {\n const { fileName, timestamp } = writeTimestampedTxtFile(\n `act_summary`,\n `act_call`,\n {\n modelCall: \"act\",\n messages,\n },\n );\n callFile = fileName;\n callTimestamp = timestamp;\n }\n\n const start = Date.now();\n const rawResponse = await llmClient.createChatCompletion<ActResponse>({\n options: {\n messages,\n response_model: {\n schema: actSchema,\n name: \"act\",\n },\n top_p: 1,\n frequency_penalty: 0,\n presence_penalty: 0,\n },\n logger,\n });\n const end = Date.now();\n const usageTimeMs = end - start;\n\n const { data: actData, usage: actUsage } = rawResponse;\n const promptTokens = actUsage?.prompt_tokens ?? 0;\n const completionTokens = actUsage?.completion_tokens ?? 0;\n const reasoningTokens = actUsage?.reasoning_tokens ?? 0;\n const cachedInputTokens = actUsage?.cached_input_tokens ?? 0;\n\n let responseFile: string;\n if (logInferenceToFile) {\n const { fileName: responseFileName } = writeTimestampedTxtFile(\n `act_summary`,\n `act_response`,\n {\n modelResponse: \"act\",\n rawResponse: actData,\n },\n );\n responseFile = responseFileName;\n\n appendSummary(\"act\", {\n [`act_inference_type`]: \"act\",\n timestamp: callTimestamp,\n LLM_input_file: callFile,\n LLM_output_file: responseFile,\n prompt_tokens: promptTokens,\n completion_tokens: completionTokens,\n reasoning_tokens: reasoningTokens,\n cached_input_tokens: cachedInputTokens,\n inference_time_ms: usageTimeMs,\n });\n }\n\n const parsedElement = actData.action\n ? {\n elementId: actData.action.elementId,\n description: String(actData.action.description),\n method: String(actData.action.method),\n arguments: actData.action.arguments,\n }\n : undefined;\n\n return {\n element: parsedElement,\n prompt_tokens: promptTokens,\n completion_tokens: completionTokens,\n reasoning_tokens: reasoningTokens,\n cached_input_tokens: cachedInputTokens,\n inference_time_ms: usageTimeMs,\n twoStep: actData.twoStep,\n };\n}\n"]}
|
package/dist/esm/lib/prompt.js
CHANGED
|
@@ -93,7 +93,9 @@ You will be given:
|
|
|
93
93
|
2. a hierarchical accessibility tree showing the semantic structure of the page. The tree is a hybrid of the DOM and the accessibility tree.
|
|
94
94
|
|
|
95
95
|
Return an array of elements that match the instruction if they exist, otherwise return an empty array.
|
|
96
|
-
When returning elements, include the appropriate method from the supported actions list.${actionsString}${variablesString}. When choosing non-left click actions, provide right or middle as the argument
|
|
96
|
+
When returning elements, include the appropriate method from the supported actions list.${actionsString}${variablesString}. When choosing non-left click actions, provide right or middle as the argument.
|
|
97
|
+
|
|
98
|
+
Each element in the accessibility tree has an ID in square brackets, like [0-18372]. The ID has two parts: frame ordinal and backend node ID. Always copy the complete ID exactly as shown inside the brackets into elementId, including the frame ordinal and hyphen. For example, if the tree shows [0-18372], return elementId "0-18372"; never return only "18372".`;
|
|
97
99
|
const content = observeSystemPrompt.replace(/\s+/g, " ");
|
|
98
100
|
return {
|
|
99
101
|
role: "system",
|