@browserbasehq/orca 3.2.1-preview.2 → 3.4.0-preview-1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/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/dom/build/selectorRuntime.generated.d.ts +24 -0
- package/dist/cjs/lib/v3/dom/build/selectorRuntime.generated.js +31 -0
- package/dist/cjs/lib/v3/dom/build/selectorRuntime.generated.js.map +1 -0
- 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/observeHandler.js +2 -1
- package/dist/cjs/lib/v3/handlers/observeHandler.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 +2 -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 +7 -1
- package/dist/cjs/lib/v3/types/public/api.js +22 -2
- package/dist/cjs/lib/v3/types/public/api.js.map +1 -1
- package/dist/cjs/lib/v3/types/public/methods.d.ts +2 -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 +18 -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 +49 -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 +32 -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/cjs/tests/unit/timeout-handlers.test.js +36 -0
- package/dist/cjs/tests/unit/timeout-handlers.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/dom/build/selectorRuntime.generated.d.ts +24 -0
- package/dist/esm/lib/v3/dom/build/selectorRuntime.generated.js +28 -0
- package/dist/esm/lib/v3/dom/build/selectorRuntime.generated.js.map +1 -0
- 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/observeHandler.js +2 -1
- package/dist/esm/lib/v3/handlers/observeHandler.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 +2 -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 +7 -1
- package/dist/esm/lib/v3/types/public/api.js +22 -2
- package/dist/esm/lib/v3/types/public/api.js.map +1 -1
- package/dist/esm/lib/v3/types/public/methods.d.ts +2 -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 +18 -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 +49 -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 +32 -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/dist/esm/tests/unit/timeout-handlers.test.js +36 -0
- package/dist/esm/tests/unit/timeout-handlers.test.js.map +1 -1
- package/package.json +3 -3
- 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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-client-observe-variables.test.js","sourceRoot":"","sources":["../../../../tests/unit/api-client-observe-variables.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAClD,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAEzD,QAAQ,CAAC,2CAA2C,EAAE,GAAG,EAAE;IACzD,EAAE,CAAC,uDAAuD,EAAE,KAAK,IAAI,EAAE;QACrE,MAAM,MAAM,GAAG,IAAI,kBAAkB,CAAC;YACpC,MAAM,EAAE,SAAS;YACjB,MAAM,EAAE,EAAE,CAAC,EAAE,EAAE;SAChB,CAAC,CAAC;QACH,MAAM,WAAW,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC;YAC5C,OAAO,EAAE,IAAI;YACb,OAAO,EAAE,IAAI;YACb,iBAAiB,EAAE,OAAO;YAC1B,OAAO,EAAE,EAAE;SACZ,CAAC,CAAC;QAGD,MAGD,CAAC,OAAO,GAAG,WAAW,CAAC;QAExB,MAAM,MAAM,CAAC,GAAG,CAAC;YACf,KAAK,EAAE,sCAAsC;YAC7C,OAAO,EAAE;gBACP,SAAS,EAAE;oBACT,QAAQ,EAAE;wBACR,KAAK,EAAE,kBAAkB;wBACzB,WAAW,EAAE,iBAAiB;qBAC/B;oBACD,QAAQ,EAAE,QAAQ;iBACnB;aACF;SACF,CAAC,CAAC;QAEH,MAAM,CAAC,WAAW,CAAC,CAAC,oBAAoB,CAAC;YACvC,MAAM,EAAE,KAAK;YACb,IAAI,EAAE;gBACJ,KAAK,EAAE,sCAAsC;gBAC7C,OAAO,EAAE;oBACP,SAAS,EAAE;wBACT,QAAQ,EAAE;4BACR,KAAK,EAAE,kBAAkB;4BACzB,WAAW,EAAE,iBAAiB;yBAC/B;wBACD,QAAQ,EAAE,QAAQ;qBACnB;iBACF;gBACD,OAAO,EAAE,SAAS;aACnB;YACD,WAAW,EAAE,SAAS;SACvB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2DAA2D,EAAE,KAAK,IAAI,EAAE;QACzE,MAAM,MAAM,GAAG,IAAI,kBAAkB,CAAC;YACpC,MAAM,EAAE,SAAS;YACjB,MAAM,EAAE,EAAE,CAAC,EAAE,EAAE;SAChB,CAAC,CAAC;QACH,MAAM,WAAW,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAC;QAGhD,MAGD,CAAC,OAAO,GAAG,WAAW,CAAC;QAExB,MAAM,MAAM,CAAC,OAAO,CAAC;YACnB,WAAW,EAAE,mDAAmD;YAChE,OAAO,EAAE;gBACP,SAAS,EAAE;oBACT,QAAQ,EAAE;wBACR,KAAK,EAAE,kBAAkB;wBACzB,WAAW,EAAE,iBAAiB;qBAC/B;oBACD,QAAQ,EAAE,QAAQ;iBACnB;
|
|
1
|
+
{"version":3,"file":"api-client-observe-variables.test.js","sourceRoot":"","sources":["../../../../tests/unit/api-client-observe-variables.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, expect, it, vi } from \"vitest\";\nimport { StagehandAPIClient } from \"../../lib/v3/api.js\";\n\ndescribe(\"StagehandAPIClient variable serialization\", () => {\n it(\"preserves rich variables when sending the act request\", async () => {\n const client = new StagehandAPIClient({\n apiKey: \"bb-test\",\n logger: vi.fn(),\n });\n const executeMock = vi.fn().mockResolvedValue({\n success: true,\n message: \"ok\",\n actionDescription: \"typed\",\n actions: [],\n });\n\n (\n client as unknown as {\n execute: typeof executeMock;\n }\n ).execute = executeMock;\n\n await client.act({\n input: \"type %username% into the email field\",\n options: {\n variables: {\n username: {\n value: \"john@example.com\",\n description: \"The login email\",\n },\n password: \"secret\",\n },\n },\n });\n\n expect(executeMock).toHaveBeenCalledWith({\n method: \"act\",\n args: {\n input: \"type %username% into the email field\",\n options: {\n variables: {\n username: {\n value: \"john@example.com\",\n description: \"The login email\",\n },\n password: \"secret\",\n },\n },\n frameId: undefined,\n },\n serverCache: undefined,\n });\n });\n\n it(\"preserves rich variables when sending the observe request\", async () => {\n const client = new StagehandAPIClient({\n apiKey: \"bb-test\",\n logger: vi.fn(),\n });\n const executeMock = vi.fn().mockResolvedValue([]);\n\n (\n client as unknown as {\n execute: typeof executeMock;\n }\n ).execute = executeMock;\n\n await client.observe({\n instruction: \"find the field where %username% should be entered\",\n options: {\n variables: {\n username: {\n value: \"john@example.com\",\n description: \"The login email\",\n },\n password: \"secret\",\n },\n ignoreSelectors: [\".cookie-banner\"],\n },\n });\n\n expect(executeMock).toHaveBeenCalledWith({\n method: \"observe\",\n args: {\n instruction: \"find the field where %username% should be entered\",\n options: {\n variables: {\n username: {\n value: \"john@example.com\",\n description: \"The login email\",\n },\n password: \"secret\",\n },\n ignoreSelectors: [\".cookie-banner\"],\n },\n frameId: undefined,\n },\n serverCache: undefined,\n });\n });\n\n it(\"preserves rich variables when sending the agentExecute request\", async () => {\n const client = new StagehandAPIClient({\n apiKey: \"bb-test\",\n logger: vi.fn(),\n });\n const executeMock = vi.fn().mockResolvedValue({\n success: true,\n message: \"ok\",\n actions: [],\n completed: true,\n });\n\n (\n client as unknown as {\n execute: typeof executeMock;\n }\n ).execute = executeMock;\n\n await client.agentExecute(\n { mode: \"dom\" },\n {\n instruction: \"fill the form with %username% and %password%\",\n variables: {\n username: \"john@example.com\",\n password: {\n value: \"secret\",\n description: \"The login password\",\n },\n },\n },\n );\n\n expect(executeMock).toHaveBeenCalledWith({\n method: \"agentExecute\",\n args: {\n agentConfig: {\n systemPrompt: undefined,\n mode: \"dom\",\n cua: undefined,\n model: undefined,\n executionModel: undefined,\n },\n executeOptions: {\n instruction: \"fill the form with %username% and %password%\",\n variables: {\n username: \"john@example.com\",\n password: {\n value: \"secret\",\n description: \"The login password\",\n },\n },\n },\n frameId: undefined,\n shouldCache: undefined,\n },\n });\n });\n});\n"]}
|
|
@@ -25,9 +25,12 @@ describe("StagehandAPIClient - optional modelApiKey", () => {
|
|
|
25
25
|
}
|
|
26
26
|
beforeEach(() => {
|
|
27
27
|
originalFetch = globalThis.fetch;
|
|
28
|
+
logger.mockClear();
|
|
28
29
|
});
|
|
29
30
|
afterEach(() => {
|
|
30
31
|
globalThis.fetch = originalFetch;
|
|
32
|
+
delete process.env.STAGEHAND_BASE_URL;
|
|
33
|
+
delete process.env.STAGEHAND_API_URL;
|
|
31
34
|
vi.restoreAllMocks();
|
|
32
35
|
});
|
|
33
36
|
it("should NOT throw when modelApiKey is omitted", async () => {
|
|
@@ -89,5 +92,62 @@ describe("StagehandAPIClient - optional modelApiKey", () => {
|
|
|
89
92
|
const [, requestInit] = fetchSpy.mock.calls[0];
|
|
90
93
|
expect(requestInit.headers["x-model-api-key"]).toBeUndefined();
|
|
91
94
|
});
|
|
95
|
+
it("should use STAGEHAND_API_URL for the API base URL", async () => {
|
|
96
|
+
process.env.STAGEHAND_API_URL = "http://localhost:5000";
|
|
97
|
+
const fetchSpy = vi
|
|
98
|
+
.fn()
|
|
99
|
+
.mockResolvedValue(createSessionStartResponse("sess-api-url"));
|
|
100
|
+
globalThis.fetch = fetchSpy;
|
|
101
|
+
const client = new StagehandAPIClient({
|
|
102
|
+
apiKey: "test-api-key",
|
|
103
|
+
logger,
|
|
104
|
+
});
|
|
105
|
+
await client.init({
|
|
106
|
+
modelName: "openai/gpt-4.1-mini",
|
|
107
|
+
});
|
|
108
|
+
const [url] = fetchSpy.mock.calls[0];
|
|
109
|
+
expect(url.toString()).toBe("http://localhost:5000/v1/sessions/start");
|
|
110
|
+
});
|
|
111
|
+
it("should use STAGEHAND_BASE_URL as a legacy fallback", async () => {
|
|
112
|
+
process.env.STAGEHAND_BASE_URL = "http://localhost:5001";
|
|
113
|
+
const fetchSpy = vi
|
|
114
|
+
.fn()
|
|
115
|
+
.mockResolvedValue(createSessionStartResponse("sess-base-url"));
|
|
116
|
+
globalThis.fetch = fetchSpy;
|
|
117
|
+
const client = new StagehandAPIClient({
|
|
118
|
+
apiKey: "test-api-key",
|
|
119
|
+
logger,
|
|
120
|
+
});
|
|
121
|
+
await client.init({
|
|
122
|
+
modelName: "openai/gpt-4.1-mini",
|
|
123
|
+
});
|
|
124
|
+
const [url] = fetchSpy.mock.calls[0];
|
|
125
|
+
expect(url.toString()).toBe("http://localhost:5001/v1/sessions/start");
|
|
126
|
+
expect(logger).toHaveBeenCalledWith(expect.objectContaining({
|
|
127
|
+
category: "config",
|
|
128
|
+
message: "STAGEHAND_BASE_URL is deprecated. Use STAGEHAND_API_URL instead.",
|
|
129
|
+
level: 0,
|
|
130
|
+
}));
|
|
131
|
+
});
|
|
132
|
+
it("should prefer STAGEHAND_API_URL over STAGEHAND_BASE_URL", async () => {
|
|
133
|
+
process.env.STAGEHAND_BASE_URL = "http://localhost:5002";
|
|
134
|
+
process.env.STAGEHAND_API_URL = "http://localhost:5003";
|
|
135
|
+
const fetchSpy = vi
|
|
136
|
+
.fn()
|
|
137
|
+
.mockResolvedValue(createSessionStartResponse("sess-base-precedence"));
|
|
138
|
+
globalThis.fetch = fetchSpy;
|
|
139
|
+
const client = new StagehandAPIClient({
|
|
140
|
+
apiKey: "test-api-key",
|
|
141
|
+
logger,
|
|
142
|
+
});
|
|
143
|
+
await client.init({
|
|
144
|
+
modelName: "openai/gpt-4.1-mini",
|
|
145
|
+
});
|
|
146
|
+
const [url] = fetchSpy.mock.calls[0];
|
|
147
|
+
expect(url.toString()).toBe("http://localhost:5003/v1/sessions/start");
|
|
148
|
+
expect(logger).not.toHaveBeenCalledWith(expect.objectContaining({
|
|
149
|
+
message: "STAGEHAND_BASE_URL is deprecated. Use STAGEHAND_API_URL instead.",
|
|
150
|
+
}));
|
|
151
|
+
});
|
|
92
152
|
});
|
|
93
153
|
//# sourceMappingURL=api-optional-model-api-key.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-optional-model-api-key.test.js","sourceRoot":"","sources":["../../../../tests/unit/api-optional-model-api-key.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, expect, it, vi, beforeEach, afterEach } from \"vitest\";\nimport { StagehandAPIClient } from \"../../lib/v3/api\";\n\n/**\n * Tests that modelApiKey is optional when calling StagehandAPIClient.init().\n *\n * Previously, init() would throw \"modelApiKey is required\" if the key was not\n * provided. After the fix, sessions can be started without a model API key\n * (the server may provide its own key or the user may not need one).\n * When provided, the key should still be sent via the x-model-api-key header.\n */\ndescribe(\"StagehandAPIClient - optional modelApiKey\", () => {\n const logger = vi.fn();\n\n // We mock fetch to avoid real network calls; we just need to verify\n // that init() doesn't throw when modelApiKey is omitted and that\n // the header is conditionally included.\n let originalFetch: typeof globalThis.fetch;\n\n function createSessionStartResponse(sessionId: string) {\n return new Response(\n JSON.stringify({\n success: true,\n data: { sessionId, available: true },\n }),\n {\n status: 200,\n headers: { \"Content-Type\": \"application/json\" },\n },\n );\n }\n\n beforeEach(() => {\n originalFetch = globalThis.fetch;\n });\n\n afterEach(() => {\n globalThis.fetch = originalFetch;\n vi.restoreAllMocks();\n });\n\n it(\"should NOT throw when modelApiKey is omitted\", async () => {\n globalThis.fetch = vi\n .fn()\n .mockResolvedValue(createSessionStartResponse(\"sess-123\"));\n\n const client = new StagehandAPIClient({\n apiKey: \"test-api-key\",\n logger,\n });\n\n // Should not throw \"modelApiKey is required\"\n await expect(\n client.init({\n modelName: \"openai/gpt-4.1-mini\",\n }),\n ).resolves.toBeDefined();\n });\n\n it(\"should NOT throw when modelApiKey is undefined\", async () => {\n globalThis.fetch = vi\n .fn()\n .mockResolvedValue(createSessionStartResponse(\"sess-456\"));\n\n const client = new StagehandAPIClient({\n apiKey: \"test-api-key\",\n logger,\n });\n\n await expect(\n client.init({\n modelName: \"openai/gpt-4.1-mini\",\n modelApiKey: undefined,\n }),\n ).resolves.toBeDefined();\n });\n\n it(\"should send x-model-api-key header when modelApiKey IS provided\", async () => {\n const fetchSpy = vi\n .fn()\n .mockResolvedValue(createSessionStartResponse(\"sess-789\"));\n globalThis.fetch = fetchSpy;\n\n const client = new StagehandAPIClient({\n apiKey: \"test-api-key\",\n logger,\n });\n\n await client.init({\n modelName: \"openai/gpt-4.1-mini\",\n modelApiKey: \"my-model-key\",\n });\n\n // Verify the fetch was called with x-model-api-key header\n const [, requestInit] = fetchSpy.mock.calls[0];\n expect(requestInit.headers[\"x-model-api-key\"]).toBe(\"my-model-key\");\n });\n\n it(\"should NOT send x-model-api-key header when modelApiKey is omitted\", async () => {\n const fetchSpy = vi\n .fn()\n .mockResolvedValue(createSessionStartResponse(\"sess-012\"));\n globalThis.fetch = fetchSpy;\n\n const client = new StagehandAPIClient({\n apiKey: \"test-api-key\",\n logger,\n });\n\n await client.init({\n modelName: \"openai/gpt-4.1-mini\",\n });\n\n // Verify x-model-api-key header is NOT present\n const [, requestInit] = fetchSpy.mock.calls[0];\n expect(requestInit.headers[\"x-model-api-key\"]).toBeUndefined();\n });\n});\n"]}
|
|
1
|
+
{"version":3,"file":"api-optional-model-api-key.test.js","sourceRoot":"","sources":["../../../../tests/unit/api-optional-model-api-key.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, expect, it, vi, beforeEach, afterEach } from \"vitest\";\nimport { StagehandAPIClient } from \"../../lib/v3/api\";\n\n/**\n * Tests that modelApiKey is optional when calling StagehandAPIClient.init().\n *\n * Previously, init() would throw \"modelApiKey is required\" if the key was not\n * provided. After the fix, sessions can be started without a model API key\n * (the server may provide its own key or the user may not need one).\n * When provided, the key should still be sent via the x-model-api-key header.\n */\ndescribe(\"StagehandAPIClient - optional modelApiKey\", () => {\n const logger = vi.fn();\n\n // We mock fetch to avoid real network calls; we just need to verify\n // that init() doesn't throw when modelApiKey is omitted and that\n // the header is conditionally included.\n let originalFetch: typeof globalThis.fetch;\n\n function createSessionStartResponse(sessionId: string) {\n return new Response(\n JSON.stringify({\n success: true,\n data: { sessionId, available: true },\n }),\n {\n status: 200,\n headers: { \"Content-Type\": \"application/json\" },\n },\n );\n }\n\n beforeEach(() => {\n originalFetch = globalThis.fetch;\n logger.mockClear();\n });\n\n afterEach(() => {\n globalThis.fetch = originalFetch;\n delete process.env.STAGEHAND_BASE_URL;\n delete process.env.STAGEHAND_API_URL;\n vi.restoreAllMocks();\n });\n\n it(\"should NOT throw when modelApiKey is omitted\", async () => {\n globalThis.fetch = vi\n .fn()\n .mockResolvedValue(createSessionStartResponse(\"sess-123\"));\n\n const client = new StagehandAPIClient({\n apiKey: \"test-api-key\",\n logger,\n });\n\n // Should not throw \"modelApiKey is required\"\n await expect(\n client.init({\n modelName: \"openai/gpt-4.1-mini\",\n }),\n ).resolves.toBeDefined();\n });\n\n it(\"should NOT throw when modelApiKey is undefined\", async () => {\n globalThis.fetch = vi\n .fn()\n .mockResolvedValue(createSessionStartResponse(\"sess-456\"));\n\n const client = new StagehandAPIClient({\n apiKey: \"test-api-key\",\n logger,\n });\n\n await expect(\n client.init({\n modelName: \"openai/gpt-4.1-mini\",\n modelApiKey: undefined,\n }),\n ).resolves.toBeDefined();\n });\n\n it(\"should send x-model-api-key header when modelApiKey IS provided\", async () => {\n const fetchSpy = vi\n .fn()\n .mockResolvedValue(createSessionStartResponse(\"sess-789\"));\n globalThis.fetch = fetchSpy;\n\n const client = new StagehandAPIClient({\n apiKey: \"test-api-key\",\n logger,\n });\n\n await client.init({\n modelName: \"openai/gpt-4.1-mini\",\n modelApiKey: \"my-model-key\",\n });\n\n // Verify the fetch was called with x-model-api-key header\n const [, requestInit] = fetchSpy.mock.calls[0];\n expect(requestInit.headers[\"x-model-api-key\"]).toBe(\"my-model-key\");\n });\n\n it(\"should NOT send x-model-api-key header when modelApiKey is omitted\", async () => {\n const fetchSpy = vi\n .fn()\n .mockResolvedValue(createSessionStartResponse(\"sess-012\"));\n globalThis.fetch = fetchSpy;\n\n const client = new StagehandAPIClient({\n apiKey: \"test-api-key\",\n logger,\n });\n\n await client.init({\n modelName: \"openai/gpt-4.1-mini\",\n });\n\n // Verify x-model-api-key header is NOT present\n const [, requestInit] = fetchSpy.mock.calls[0];\n expect(requestInit.headers[\"x-model-api-key\"]).toBeUndefined();\n });\n\n it(\"should use STAGEHAND_API_URL for the API base URL\", async () => {\n process.env.STAGEHAND_API_URL = \"http://localhost:5000\";\n const fetchSpy = vi\n .fn()\n .mockResolvedValue(createSessionStartResponse(\"sess-api-url\"));\n globalThis.fetch = fetchSpy;\n\n const client = new StagehandAPIClient({\n apiKey: \"test-api-key\",\n logger,\n });\n\n await client.init({\n modelName: \"openai/gpt-4.1-mini\",\n });\n\n const [url] = fetchSpy.mock.calls[0];\n expect(url.toString()).toBe(\"http://localhost:5000/v1/sessions/start\");\n });\n\n it(\"should use STAGEHAND_BASE_URL as a legacy fallback\", async () => {\n process.env.STAGEHAND_BASE_URL = \"http://localhost:5001\";\n const fetchSpy = vi\n .fn()\n .mockResolvedValue(createSessionStartResponse(\"sess-base-url\"));\n globalThis.fetch = fetchSpy;\n\n const client = new StagehandAPIClient({\n apiKey: \"test-api-key\",\n logger,\n });\n\n await client.init({\n modelName: \"openai/gpt-4.1-mini\",\n });\n\n const [url] = fetchSpy.mock.calls[0];\n expect(url.toString()).toBe(\"http://localhost:5001/v1/sessions/start\");\n expect(logger).toHaveBeenCalledWith(\n expect.objectContaining({\n category: \"config\",\n message:\n \"STAGEHAND_BASE_URL is deprecated. Use STAGEHAND_API_URL instead.\",\n level: 0,\n }),\n );\n });\n\n it(\"should prefer STAGEHAND_API_URL over STAGEHAND_BASE_URL\", async () => {\n process.env.STAGEHAND_BASE_URL = \"http://localhost:5002\";\n process.env.STAGEHAND_API_URL = \"http://localhost:5003\";\n const fetchSpy = vi\n .fn()\n .mockResolvedValue(createSessionStartResponse(\"sess-base-precedence\"));\n globalThis.fetch = fetchSpy;\n\n const client = new StagehandAPIClient({\n apiKey: \"test-api-key\",\n logger,\n });\n\n await client.init({\n modelName: \"openai/gpt-4.1-mini\",\n });\n\n const [url] = fetchSpy.mock.calls[0];\n expect(url.toString()).toBe(\"http://localhost:5003/v1/sessions/start\");\n expect(logger).not.toHaveBeenCalledWith(\n expect.objectContaining({\n message:\n \"STAGEHAND_BASE_URL is deprecated. Use STAGEHAND_API_URL instead.\",\n }),\n );\n });\n});\n"]}
|
|
@@ -27,9 +27,41 @@ describe("API variable schemas", () => {
|
|
|
27
27
|
},
|
|
28
28
|
rememberMe: true,
|
|
29
29
|
},
|
|
30
|
+
ignoreSelectors: [".cookie-banner", "#sidebar-ads"],
|
|
30
31
|
},
|
|
31
32
|
});
|
|
32
33
|
expect(result.success).toBe(true);
|
|
34
|
+
if (!result.success)
|
|
35
|
+
throw result.error;
|
|
36
|
+
expect(result.data.options?.ignoreSelectors).toEqual([
|
|
37
|
+
".cookie-banner",
|
|
38
|
+
"#sidebar-ads",
|
|
39
|
+
]);
|
|
40
|
+
});
|
|
41
|
+
it("preserves variables for agent execute requests", () => {
|
|
42
|
+
const result = Api.AgentExecuteRequestSchema.safeParse({
|
|
43
|
+
agentConfig: { mode: "dom" },
|
|
44
|
+
executeOptions: {
|
|
45
|
+
instruction: "fill the form with %username% and %password%",
|
|
46
|
+
variables: {
|
|
47
|
+
username: "john@example.com",
|
|
48
|
+
password: {
|
|
49
|
+
value: "secret-password",
|
|
50
|
+
description: "The login password",
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
expect(result.success).toBe(true);
|
|
56
|
+
if (!result.success)
|
|
57
|
+
throw result.error;
|
|
58
|
+
expect(result.data.executeOptions.variables).toEqual({
|
|
59
|
+
username: "john@example.com",
|
|
60
|
+
password: {
|
|
61
|
+
value: "secret-password",
|
|
62
|
+
description: "The login password",
|
|
63
|
+
},
|
|
64
|
+
});
|
|
33
65
|
});
|
|
34
66
|
});
|
|
35
67
|
//# sourceMappingURL=api-variables-schema.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-variables-schema.test.js","sourceRoot":"","sources":["../../../../tests/unit/api-variables-schema.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,GAAG,EAAE,MAAM,oCAAoC,CAAC;AAEzD,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;IACpC,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QACjD,MAAM,MAAM,GAAG,GAAG,CAAC,gBAAgB,CAAC,SAAS,CAAC;YAC5C,KAAK,EAAE,sCAAsC;YAC7C,OAAO,EAAE;gBACP,SAAS,EAAE;oBACT,QAAQ,EAAE;wBACR,KAAK,EAAE,kBAAkB;wBACzB,WAAW,EAAE,iBAAiB;qBAC/B;oBACD,UAAU,EAAE,IAAI;iBACjB;aACF;SACF,CAAC,CAAC;QAEH,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACrD,MAAM,MAAM,GAAG,GAAG,CAAC,oBAAoB,CAAC,SAAS,CAAC;YAChD,WAAW,EAAE,mDAAmD;YAChE,OAAO,EAAE;gBACP,SAAS,EAAE;oBACT,QAAQ,EAAE;wBACR,KAAK,EAAE,kBAAkB;wBACzB,WAAW,EAAE,iBAAiB;qBAC/B;oBACD,UAAU,EAAE,IAAI;iBACjB;aACF;SACF,CAAC,CAAC;QAEH,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"api-variables-schema.test.js","sourceRoot":"","sources":["../../../../tests/unit/api-variables-schema.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,GAAG,EAAE,MAAM,oCAAoC,CAAC;AAEzD,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;IACpC,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QACjD,MAAM,MAAM,GAAG,GAAG,CAAC,gBAAgB,CAAC,SAAS,CAAC;YAC5C,KAAK,EAAE,sCAAsC;YAC7C,OAAO,EAAE;gBACP,SAAS,EAAE;oBACT,QAAQ,EAAE;wBACR,KAAK,EAAE,kBAAkB;wBACzB,WAAW,EAAE,iBAAiB;qBAC/B;oBACD,UAAU,EAAE,IAAI;iBACjB;aACF;SACF,CAAC,CAAC;QAEH,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACrD,MAAM,MAAM,GAAG,GAAG,CAAC,oBAAoB,CAAC,SAAS,CAAC;YAChD,WAAW,EAAE,mDAAmD;YAChE,OAAO,EAAE;gBACP,SAAS,EAAE;oBACT,QAAQ,EAAE;wBACR,KAAK,EAAE,kBAAkB;wBACzB,WAAW,EAAE,iBAAiB;qBAC/B;oBACD,UAAU,EAAE,IAAI;iBACjB;gBACD,eAAe,EAAE,CAAC,gBAAgB,EAAE,cAAc,CAAC;aACpD;SACF,CAAC,CAAC;QAEH,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClC,IAAI,CAAC,MAAM,CAAC,OAAO;YAAE,MAAM,MAAM,CAAC,KAAK,CAAC;QACxC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC,OAAO,CAAC;YACnD,gBAAgB;YAChB,cAAc;SACf,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE;QACxD,MAAM,MAAM,GAAG,GAAG,CAAC,yBAAyB,CAAC,SAAS,CAAC;YACrD,WAAW,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE;YAC5B,cAAc,EAAE;gBACd,WAAW,EAAE,8CAA8C;gBAC3D,SAAS,EAAE;oBACT,QAAQ,EAAE,kBAAkB;oBAC5B,QAAQ,EAAE;wBACR,KAAK,EAAE,iBAAiB;wBACxB,WAAW,EAAE,oBAAoB;qBAClC;iBACF;aACF;SACF,CAAC,CAAC;QAEH,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClC,IAAI,CAAC,MAAM,CAAC,OAAO;YAAE,MAAM,MAAM,CAAC,KAAK,CAAC;QACxC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC;YACnD,QAAQ,EAAE,kBAAkB;YAC5B,QAAQ,EAAE;gBACR,KAAK,EAAE,iBAAiB;gBACxB,WAAW,EAAE,oBAAoB;aAClC;SACF,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { describe, expect, it } from \"vitest\";\nimport { Api } from \"../../lib/v3/types/public/index.js\";\n\ndescribe(\"API variable schemas\", () => {\n it(\"accepts rich variables for act requests\", () => {\n const result = Api.ActRequestSchema.safeParse({\n input: \"type %username% into the email field\",\n options: {\n variables: {\n username: {\n value: \"john@example.com\",\n description: \"The login email\",\n },\n rememberMe: true,\n },\n },\n });\n\n expect(result.success).toBe(true);\n });\n\n it(\"accepts rich variables for observe requests\", () => {\n const result = Api.ObserveRequestSchema.safeParse({\n instruction: \"find the field where %username% should be entered\",\n options: {\n variables: {\n username: {\n value: \"john@example.com\",\n description: \"The login email\",\n },\n rememberMe: true,\n },\n ignoreSelectors: [\".cookie-banner\", \"#sidebar-ads\"],\n },\n });\n\n expect(result.success).toBe(true);\n if (!result.success) throw result.error;\n expect(result.data.options?.ignoreSelectors).toEqual([\n \".cookie-banner\",\n \"#sidebar-ads\",\n ]);\n });\n\n it(\"preserves variables for agent execute requests\", () => {\n const result = Api.AgentExecuteRequestSchema.safeParse({\n agentConfig: { mode: \"dom\" },\n executeOptions: {\n instruction: \"fill the form with %username% and %password%\",\n variables: {\n username: \"john@example.com\",\n password: {\n value: \"secret-password\",\n description: \"The login password\",\n },\n },\n },\n });\n\n expect(result.success).toBe(true);\n if (!result.success) throw result.error;\n expect(result.data.executeOptions.variables).toEqual({\n username: \"john@example.com\",\n password: {\n value: \"secret-password\",\n description: \"The login password\",\n },\n });\n });\n});\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { FrameRegistry } from "../../lib/v3/understudy/frameRegistry.js";
|
|
3
|
+
describe("FrameRegistry OOPIF adoption ordering", () => {
|
|
4
|
+
it("keeps child-session ownership when parent frameAttached arrives before child target adoption", () => {
|
|
5
|
+
const registry = new FrameRegistry("target-1", "root-frame");
|
|
6
|
+
registry.onFrameAttached("child-frame", "root-frame", "parent-session");
|
|
7
|
+
registry.adoptChildSession("child-session", "child-frame");
|
|
8
|
+
expect(registry.listAllFrames()).toEqual(["root-frame", "child-frame"]);
|
|
9
|
+
expect(registry.getParent("child-frame")).toBe("root-frame");
|
|
10
|
+
expect(registry.getOwnerSessionId("child-frame")).toBe("child-session");
|
|
11
|
+
expect(registry.framesForSession("parent-session")).toEqual([]);
|
|
12
|
+
expect(registry.framesForSession("child-session")).toEqual(["child-frame"]);
|
|
13
|
+
});
|
|
14
|
+
it("keeps child-session ownership when child target adoption is staged before parent frameAttached", () => {
|
|
15
|
+
const registry = new FrameRegistry("target-1", "root-frame");
|
|
16
|
+
registry.adoptChildSession("child-session", "child-frame");
|
|
17
|
+
registry.onFrameAttached("child-frame", "root-frame", "parent-session");
|
|
18
|
+
registry.adoptChildSession("child-session", "child-frame");
|
|
19
|
+
expect(registry.listAllFrames()).toEqual(["root-frame", "child-frame"]);
|
|
20
|
+
expect(registry.getParent("child-frame")).toBe("root-frame");
|
|
21
|
+
expect(registry.getOwnerSessionId("child-frame")).toBe("child-session");
|
|
22
|
+
expect(registry.framesForSession("parent-session")).toEqual([]);
|
|
23
|
+
expect(registry.framesForSession("child-session")).toEqual(["child-frame"]);
|
|
24
|
+
});
|
|
25
|
+
it("preserves the known parent edge when seeding an adopted OOPIF child frame tree", () => {
|
|
26
|
+
const registry = new FrameRegistry("target-1", "root-frame");
|
|
27
|
+
registry.onFrameAttached("child-frame", "root-frame", "parent-session");
|
|
28
|
+
registry.adoptChildSession("child-session", "child-frame");
|
|
29
|
+
registry.seedFromFrameTree("child-session", {
|
|
30
|
+
frame: {
|
|
31
|
+
id: "child-frame",
|
|
32
|
+
loaderId: "loader-1",
|
|
33
|
+
name: "payment-frame",
|
|
34
|
+
url: "https://js.stripe.com/v3/elements-inner-payment.html",
|
|
35
|
+
domainAndRegistry: "stripe.com",
|
|
36
|
+
securityOrigin: "https://js.stripe.com",
|
|
37
|
+
mimeType: "text/html",
|
|
38
|
+
secureContextType: "Secure",
|
|
39
|
+
crossOriginIsolatedContextType: "NotIsolated",
|
|
40
|
+
gatedAPIFeatures: [],
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
expect(registry.getParent("child-frame")).toBe("root-frame");
|
|
44
|
+
expect(registry.asProtocolFrameTree("root-frame")).toMatchObject({
|
|
45
|
+
frame: { id: "root-frame" },
|
|
46
|
+
childFrames: [
|
|
47
|
+
{
|
|
48
|
+
frame: {
|
|
49
|
+
id: "child-frame",
|
|
50
|
+
parentId: "root-frame",
|
|
51
|
+
url: "https://js.stripe.com/v3/elements-inner-payment.html",
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
],
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
//# sourceMappingURL=frame-registry-oopif-adoption.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frame-registry-oopif-adoption.test.js","sourceRoot":"","sources":["../../../../tests/unit/frame-registry-oopif-adoption.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, expect, it } from \"vitest\";\nimport type { Protocol } from \"devtools-protocol\";\n\nimport { FrameRegistry } from \"../../lib/v3/understudy/frameRegistry.js\";\n\ndescribe(\"FrameRegistry OOPIF adoption ordering\", () => {\n it(\"keeps child-session ownership when parent frameAttached arrives before child target adoption\", () => {\n const registry = new FrameRegistry(\"target-1\", \"root-frame\");\n\n registry.onFrameAttached(\"child-frame\", \"root-frame\", \"parent-session\");\n registry.adoptChildSession(\"child-session\", \"child-frame\");\n\n expect(registry.listAllFrames()).toEqual([\"root-frame\", \"child-frame\"]);\n expect(registry.getParent(\"child-frame\")).toBe(\"root-frame\");\n expect(registry.getOwnerSessionId(\"child-frame\")).toBe(\"child-session\");\n expect(registry.framesForSession(\"parent-session\")).toEqual([]);\n expect(registry.framesForSession(\"child-session\")).toEqual([\"child-frame\"]);\n });\n\n it(\"keeps child-session ownership when child target adoption is staged before parent frameAttached\", () => {\n const registry = new FrameRegistry(\"target-1\", \"root-frame\");\n\n registry.adoptChildSession(\"child-session\", \"child-frame\");\n registry.onFrameAttached(\"child-frame\", \"root-frame\", \"parent-session\");\n registry.adoptChildSession(\"child-session\", \"child-frame\");\n\n expect(registry.listAllFrames()).toEqual([\"root-frame\", \"child-frame\"]);\n expect(registry.getParent(\"child-frame\")).toBe(\"root-frame\");\n expect(registry.getOwnerSessionId(\"child-frame\")).toBe(\"child-session\");\n expect(registry.framesForSession(\"parent-session\")).toEqual([]);\n expect(registry.framesForSession(\"child-session\")).toEqual([\"child-frame\"]);\n });\n\n it(\"preserves the known parent edge when seeding an adopted OOPIF child frame tree\", () => {\n const registry = new FrameRegistry(\"target-1\", \"root-frame\");\n\n registry.onFrameAttached(\"child-frame\", \"root-frame\", \"parent-session\");\n registry.adoptChildSession(\"child-session\", \"child-frame\");\n registry.seedFromFrameTree(\"child-session\", {\n frame: {\n id: \"child-frame\",\n loaderId: \"loader-1\",\n name: \"payment-frame\",\n url: \"https://js.stripe.com/v3/elements-inner-payment.html\",\n domainAndRegistry: \"stripe.com\",\n securityOrigin: \"https://js.stripe.com\",\n mimeType: \"text/html\",\n secureContextType: \"Secure\",\n crossOriginIsolatedContextType: \"NotIsolated\",\n gatedAPIFeatures: [],\n },\n } satisfies Protocol.Page.FrameTree);\n\n expect(registry.getParent(\"child-frame\")).toBe(\"root-frame\");\n expect(registry.asProtocolFrameTree(\"root-frame\")).toMatchObject({\n frame: { id: \"root-frame\" },\n childFrames: [\n {\n frame: {\n id: \"child-frame\",\n parentId: \"root-frame\",\n url: \"https://js.stripe.com/v3/elements-inner-payment.html\",\n },\n },\n ],\n });\n });\n});\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { describe, expect, it, vi } from "vitest";
|
|
3
|
+
import { act, extract, observe } from "../../lib/inference.js";
|
|
4
|
+
function createLlmClient(responses) {
|
|
5
|
+
const calls = [];
|
|
6
|
+
const createChatCompletion = vi.fn(async (request) => {
|
|
7
|
+
calls.push(request);
|
|
8
|
+
const response = responses.shift();
|
|
9
|
+
if (!response) {
|
|
10
|
+
throw new Error("Unexpected LLM call");
|
|
11
|
+
}
|
|
12
|
+
return response;
|
|
13
|
+
});
|
|
14
|
+
const llmClient = {
|
|
15
|
+
type: "openai",
|
|
16
|
+
modelName: "openai/gpt-5",
|
|
17
|
+
createChatCompletion,
|
|
18
|
+
};
|
|
19
|
+
return { llmClient, calls };
|
|
20
|
+
}
|
|
21
|
+
describe("shared act/extract/observe inference temperature", () => {
|
|
22
|
+
it("does not pass temperature for either extract call", async () => {
|
|
23
|
+
const { llmClient, calls } = createLlmClient([
|
|
24
|
+
{ data: { answer: "42" } },
|
|
25
|
+
{ data: { completed: true, progress: "complete" } },
|
|
26
|
+
]);
|
|
27
|
+
await extract({
|
|
28
|
+
instruction: "extract the answer",
|
|
29
|
+
domElements: "body",
|
|
30
|
+
schema: z.object({ answer: z.string() }),
|
|
31
|
+
llmClient,
|
|
32
|
+
logger: vi.fn(),
|
|
33
|
+
});
|
|
34
|
+
expect(calls).toHaveLength(2);
|
|
35
|
+
expect(calls[0].options).not.toHaveProperty("temperature");
|
|
36
|
+
expect(calls[1].options).not.toHaveProperty("temperature");
|
|
37
|
+
});
|
|
38
|
+
it("does not pass temperature for observe", async () => {
|
|
39
|
+
const { llmClient, calls } = createLlmClient([{ data: { elements: [] } }]);
|
|
40
|
+
await observe({
|
|
41
|
+
instruction: "find buttons",
|
|
42
|
+
domElements: "body",
|
|
43
|
+
llmClient,
|
|
44
|
+
logger: vi.fn(),
|
|
45
|
+
});
|
|
46
|
+
expect(calls).toHaveLength(1);
|
|
47
|
+
expect(calls[0].options).not.toHaveProperty("temperature");
|
|
48
|
+
});
|
|
49
|
+
it("does not pass temperature for act", async () => {
|
|
50
|
+
const { llmClient, calls } = createLlmClient([
|
|
51
|
+
{ data: { action: null, twoStep: false } },
|
|
52
|
+
]);
|
|
53
|
+
await act({
|
|
54
|
+
instruction: "click the button",
|
|
55
|
+
domElements: "body",
|
|
56
|
+
llmClient,
|
|
57
|
+
logger: vi.fn(),
|
|
58
|
+
});
|
|
59
|
+
expect(calls).toHaveLength(1);
|
|
60
|
+
expect(calls[0].options).not.toHaveProperty("temperature");
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
//# sourceMappingURL=inference-temperature.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inference-temperature.test.js","sourceRoot":"","sources":["../../../../tests/unit/inference-temperature.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from \"zod\";\nimport { describe, expect, it, vi } from \"vitest\";\nimport { act, extract, observe } from \"../../lib/inference.js\";\nimport type {\n CreateChatCompletionOptions,\n LLMClient,\n} from \"../../lib/v3/llm/LLMClient.js\";\n\ntype QueuedResponse = {\n data: unknown;\n usage?: Record<string, number>;\n};\n\nfunction createLlmClient(responses: QueuedResponse[]) {\n const calls: CreateChatCompletionOptions[] = [];\n const createChatCompletion = vi.fn(\n async (request: CreateChatCompletionOptions) => {\n calls.push(request);\n const response = responses.shift();\n if (!response) {\n throw new Error(\"Unexpected LLM call\");\n }\n return response;\n },\n );\n\n const llmClient = {\n type: \"openai\",\n modelName: \"openai/gpt-5\",\n createChatCompletion,\n } as unknown as LLMClient;\n\n return { llmClient, calls };\n}\n\ndescribe(\"shared act/extract/observe inference temperature\", () => {\n it(\"does not pass temperature for either extract call\", async () => {\n const { llmClient, calls } = createLlmClient([\n { data: { answer: \"42\" } },\n { data: { completed: true, progress: \"complete\" } },\n ]);\n\n await extract({\n instruction: \"extract the answer\",\n domElements: \"body\",\n schema: z.object({ answer: z.string() }),\n llmClient,\n logger: vi.fn(),\n });\n\n expect(calls).toHaveLength(2);\n expect(calls[0].options).not.toHaveProperty(\"temperature\");\n expect(calls[1].options).not.toHaveProperty(\"temperature\");\n });\n\n it(\"does not pass temperature for observe\", async () => {\n const { llmClient, calls } = createLlmClient([{ data: { elements: [] } }]);\n\n await observe({\n instruction: \"find buttons\",\n domElements: \"body\",\n llmClient,\n logger: vi.fn(),\n });\n\n expect(calls).toHaveLength(1);\n expect(calls[0].options).not.toHaveProperty(\"temperature\");\n });\n\n it(\"does not pass temperature for act\", async () => {\n const { llmClient, calls } = createLlmClient([\n { data: { action: null, twoStep: false } },\n ]);\n\n await act({\n instruction: \"click the button\",\n domElements: \"body\",\n llmClient,\n logger: vi.fn(),\n });\n\n expect(calls).toHaveLength(1);\n expect(calls[0].options).not.toHaveProperty(\"temperature\");\n });\n});\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { CerebrasClient } from "../../lib/v3/llm/CerebrasClient.js";
|
|
3
|
+
import { GroqClient } from "../../lib/v3/llm/GroqClient.js";
|
|
4
|
+
function mockCompletionCreate() {
|
|
5
|
+
return vi.fn().mockResolvedValue({
|
|
6
|
+
id: "chatcmpl-test",
|
|
7
|
+
choices: [
|
|
8
|
+
{
|
|
9
|
+
message: {
|
|
10
|
+
role: "assistant",
|
|
11
|
+
content: "ok",
|
|
12
|
+
tool_calls: [],
|
|
13
|
+
},
|
|
14
|
+
finish_reason: "stop",
|
|
15
|
+
},
|
|
16
|
+
],
|
|
17
|
+
usage: {
|
|
18
|
+
prompt_tokens: 1,
|
|
19
|
+
completion_tokens: 1,
|
|
20
|
+
total_tokens: 2,
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
function installMockClient(client) {
|
|
25
|
+
const create = mockCompletionCreate();
|
|
26
|
+
client.client = {
|
|
27
|
+
chat: {
|
|
28
|
+
completions: {
|
|
29
|
+
create,
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
return create;
|
|
34
|
+
}
|
|
35
|
+
const logger = vi.fn();
|
|
36
|
+
describe.each([
|
|
37
|
+
[
|
|
38
|
+
"GroqClient",
|
|
39
|
+
() => new GroqClient({
|
|
40
|
+
modelName: "groq-test-model",
|
|
41
|
+
clientOptions: { apiKey: "test-key" },
|
|
42
|
+
logger,
|
|
43
|
+
}),
|
|
44
|
+
],
|
|
45
|
+
[
|
|
46
|
+
"CerebrasClient",
|
|
47
|
+
() => new CerebrasClient({
|
|
48
|
+
modelName: "cerebras-test-model",
|
|
49
|
+
clientOptions: { apiKey: "test-key" },
|
|
50
|
+
logger,
|
|
51
|
+
}),
|
|
52
|
+
],
|
|
53
|
+
])("%s temperature handling", (_name, createClient) => {
|
|
54
|
+
it("falls back to 0.7 when temperature is not provided", async () => {
|
|
55
|
+
const client = createClient();
|
|
56
|
+
const create = installMockClient(client);
|
|
57
|
+
await client.createChatCompletion({
|
|
58
|
+
options: {
|
|
59
|
+
messages: [{ role: "user", content: "hello" }],
|
|
60
|
+
},
|
|
61
|
+
logger,
|
|
62
|
+
});
|
|
63
|
+
expect(create).toHaveBeenCalledWith(expect.objectContaining({
|
|
64
|
+
temperature: 0.7,
|
|
65
|
+
}));
|
|
66
|
+
});
|
|
67
|
+
it("preserves explicit temperature zero", async () => {
|
|
68
|
+
const client = createClient();
|
|
69
|
+
const create = installMockClient(client);
|
|
70
|
+
await client.createChatCompletion({
|
|
71
|
+
options: {
|
|
72
|
+
messages: [{ role: "user", content: "hello" }],
|
|
73
|
+
temperature: 0,
|
|
74
|
+
},
|
|
75
|
+
logger,
|
|
76
|
+
});
|
|
77
|
+
expect(create).toHaveBeenCalledWith(expect.objectContaining({
|
|
78
|
+
temperature: 0,
|
|
79
|
+
}));
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
//# sourceMappingURL=openai-compatible-temperature.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai-compatible-temperature.test.js","sourceRoot":"","sources":["../../../../tests/unit/openai-compatible-temperature.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAe5D,SAAS,oBAAoB;IAC3B,OAAO,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC;QAC/B,EAAE,EAAE,eAAe;QACnB,OAAO,EAAE;YACP;gBACE,OAAO,EAAE;oBACP,IAAI,EAAE,WAAW;oBACjB,OAAO,EAAE,IAAI;oBACb,UAAU,EAAE,EAAE;iBACf;gBACD,aAAa,EAAE,MAAM;aACtB;SACF;QACD,KAAK,EAAE;YACL,aAAa,EAAE,CAAC;YAChB,iBAAiB,EAAE,CAAC;YACpB,YAAY,EAAE,CAAC;SAChB;KACF,CAAC,CAAC;AACL,CAAC;AAED,SAAS,iBAAiB,CAAC,MAAiB;IAC1C,MAAM,MAAM,GAAG,oBAAoB,EAAE,CAAC;IACrC,MAAiC,CAAC,MAAM,GAAG;QAC1C,IAAI,EAAE;YACJ,WAAW,EAAE;gBACX,MAAM;aACP;SACF;KACF,CAAC;IACF,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,MAAM,GAAG,EAAE,CAAC,EAAE,EAA8B,CAAC;AAEnD,QAAQ,CAAC,IAAI,CAAC;IACZ;QACE,YAAY;QACZ,GAAG,EAAE,CACH,IAAI,UAAU,CAAC;YACb,SAAS,EAAE,iBAAmC;YAC9C,aAAa,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE;YACrC,MAAM;SACP,CAAC;KACL;IACD;QACE,gBAAgB;QAChB,GAAG,EAAE,CACH,IAAI,cAAc,CAAC;YACjB,SAAS,EAAE,qBAAuC;YAClD,aAAa,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE;YACrC,MAAM;SACP,CAAC;KACL;CACF,CAAC,CAAC,yBAAyB,EAAE,CAAC,KAAK,EAAE,YAAY,EAAE,EAAE;IACpD,EAAE,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;QAClE,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;QAC9B,MAAM,MAAM,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;QAEzC,MAAM,MAAM,CAAC,oBAAoB,CAAC;YAChC,OAAO,EAAE;gBACP,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;aAC/C;YACD,MAAM;SACP,CAAC,CAAC;QAEH,MAAM,CAAC,MAAM,CAAC,CAAC,oBAAoB,CACjC,MAAM,CAAC,gBAAgB,CAAC;YACtB,WAAW,EAAE,GAAG;SACjB,CAAC,CACH,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qCAAqC,EAAE,KAAK,IAAI,EAAE;QACnD,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;QAC9B,MAAM,MAAM,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;QAEzC,MAAM,MAAM,CAAC,oBAAoB,CAAC;YAChC,OAAO,EAAE;gBACP,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;gBAC9C,WAAW,EAAE,CAAC;aACf;YACD,MAAM;SACP,CAAC,CAAC;QAEH,MAAM,CAAC,MAAM,CAAC,CAAC,oBAAoB,CACjC,MAAM,CAAC,gBAAgB,CAAC;YACtB,WAAW,EAAE,CAAC;SACf,CAAC,CACH,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { describe, expect, it, vi } from \"vitest\";\nimport { CerebrasClient } from \"../../lib/v3/llm/CerebrasClient.js\";\nimport { GroqClient } from \"../../lib/v3/llm/GroqClient.js\";\nimport type { LLMClient } from \"../../lib/v3/llm/LLMClient.js\";\nimport type { LogLine } from \"../../lib/v3/types/public/logs.js\";\nimport type { AvailableModel } from \"../../lib/v3/types/public/model.js\";\n\ntype OpenAICompatibleClient = LLMClient & {\n client: {\n chat: {\n completions: {\n create: ReturnType<typeof vi.fn>;\n };\n };\n };\n};\n\nfunction mockCompletionCreate() {\n return vi.fn().mockResolvedValue({\n id: \"chatcmpl-test\",\n choices: [\n {\n message: {\n role: \"assistant\",\n content: \"ok\",\n tool_calls: [],\n },\n finish_reason: \"stop\",\n },\n ],\n usage: {\n prompt_tokens: 1,\n completion_tokens: 1,\n total_tokens: 2,\n },\n });\n}\n\nfunction installMockClient(client: LLMClient) {\n const create = mockCompletionCreate();\n (client as OpenAICompatibleClient).client = {\n chat: {\n completions: {\n create,\n },\n },\n };\n return create;\n}\n\nconst logger = vi.fn<(message: LogLine) => void>();\n\ndescribe.each([\n [\n \"GroqClient\",\n () =>\n new GroqClient({\n modelName: \"groq-test-model\" as AvailableModel,\n clientOptions: { apiKey: \"test-key\" },\n logger,\n }),\n ],\n [\n \"CerebrasClient\",\n () =>\n new CerebrasClient({\n modelName: \"cerebras-test-model\" as AvailableModel,\n clientOptions: { apiKey: \"test-key\" },\n logger,\n }),\n ],\n])(\"%s temperature handling\", (_name, createClient) => {\n it(\"falls back to 0.7 when temperature is not provided\", async () => {\n const client = createClient();\n const create = installMockClient(client);\n\n await client.createChatCompletion({\n options: {\n messages: [{ role: \"user\", content: \"hello\" }],\n },\n logger,\n });\n\n expect(create).toHaveBeenCalledWith(\n expect.objectContaining({\n temperature: 0.7,\n }),\n );\n });\n\n it(\"preserves explicit temperature zero\", async () => {\n const client = createClient();\n const create = installMockClient(client);\n\n await client.createChatCompletion({\n options: {\n messages: [{ role: \"user\", content: \"hello\" }],\n temperature: 0,\n },\n logger,\n });\n\n expect(create).toHaveBeenCalledWith(\n expect.objectContaining({\n temperature: 0,\n }),\n );\n });\n});\n"]}
|
|
@@ -13,5 +13,11 @@ describe("buildObserveSystemPrompt", () => {
|
|
|
13
13
|
expect(prompt.content).toContain("Available variables: %username% (The login email), %password%");
|
|
14
14
|
expect(prompt.content).toContain("return the matching %variableName% placeholder");
|
|
15
15
|
});
|
|
16
|
+
it("instructs the model to copy complete bracketed element IDs", () => {
|
|
17
|
+
const prompt = buildObserveSystemPrompt(undefined, ["click"]);
|
|
18
|
+
expect(prompt.content).toContain("Always copy the complete ID exactly as shown inside the brackets into elementId");
|
|
19
|
+
expect(prompt.content).toContain('return elementId "0-18372"');
|
|
20
|
+
expect(prompt.content).toContain('never return only "18372"');
|
|
21
|
+
});
|
|
16
22
|
});
|
|
17
23
|
//# sourceMappingURL=prompt-observe-variables.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompt-observe-variables.test.js","sourceRoot":"","sources":["../../../../tests/unit/prompt-observe-variables.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAE/D,QAAQ,CAAC,0BAA0B,EAAE,GAAG,EAAE;IACxC,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACrD,MAAM,MAAM,GAAG,wBAAwB,CAAC,SAAS,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,EAAE;YACpE,QAAQ,EAAE;gBACR,KAAK,EAAE,kBAAkB;gBACzB,WAAW,EAAE,iBAAiB;aAC/B;YACD,QAAQ,EAAE,WAAW;SACtB,CAAC,CAAC;QAEH,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,gCAAgC,CAAC,CAAC;QACnE,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAC9B,+DAA+D,CAChE,CAAC;QACF,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAC9B,gDAAgD,CACjD,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { describe, expect, it } from \"vitest\";\nimport { buildObserveSystemPrompt } from \"../../lib/prompt.js\";\n\ndescribe(\"buildObserveSystemPrompt\", () => {\n it(\"includes variable descriptions when present\", () => {\n const prompt = buildObserveSystemPrompt(undefined, [\"click\", \"fill\"], {\n username: {\n value: \"john@example.com\",\n description: \"The login email\",\n },\n password: \"secret123\",\n });\n\n expect(prompt.content).toContain(\"Supported actions: click, fill\");\n expect(prompt.content).toContain(\n \"Available variables: %username% (The login email), %password%\",\n );\n expect(prompt.content).toContain(\n \"return the matching %variableName% placeholder\",\n );\n });\n});\n"]}
|
|
1
|
+
{"version":3,"file":"prompt-observe-variables.test.js","sourceRoot":"","sources":["../../../../tests/unit/prompt-observe-variables.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAE/D,QAAQ,CAAC,0BAA0B,EAAE,GAAG,EAAE;IACxC,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACrD,MAAM,MAAM,GAAG,wBAAwB,CAAC,SAAS,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,EAAE;YACpE,QAAQ,EAAE;gBACR,KAAK,EAAE,kBAAkB;gBACzB,WAAW,EAAE,iBAAiB;aAC/B;YACD,QAAQ,EAAE,WAAW;SACtB,CAAC,CAAC;QAEH,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,gCAAgC,CAAC,CAAC;QACnE,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAC9B,+DAA+D,CAChE,CAAC;QACF,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAC9B,gDAAgD,CACjD,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4DAA4D,EAAE,GAAG,EAAE;QACpE,MAAM,MAAM,GAAG,wBAAwB,CAAC,SAAS,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;QAE9D,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAC9B,iFAAiF,CAClF,CAAC;QACF,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,4BAA4B,CAAC,CAAC;QAC/D,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,2BAA2B,CAAC,CAAC;IAChE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { describe, expect, it } from \"vitest\";\nimport { buildObserveSystemPrompt } from \"../../lib/prompt.js\";\n\ndescribe(\"buildObserveSystemPrompt\", () => {\n it(\"includes variable descriptions when present\", () => {\n const prompt = buildObserveSystemPrompt(undefined, [\"click\", \"fill\"], {\n username: {\n value: \"john@example.com\",\n description: \"The login email\",\n },\n password: \"secret123\",\n });\n\n expect(prompt.content).toContain(\"Supported actions: click, fill\");\n expect(prompt.content).toContain(\n \"Available variables: %username% (The login email), %password%\",\n );\n expect(prompt.content).toContain(\n \"return the matching %variableName% placeholder\",\n );\n });\n\n it(\"instructs the model to copy complete bracketed element IDs\", () => {\n const prompt = buildObserveSystemPrompt(undefined, [\"click\"]);\n\n expect(prompt.content).toContain(\n \"Always copy the complete ID exactly as shown inside the brackets into elementId\",\n );\n expect(prompt.content).toContain('return elementId \"0-18372\"');\n expect(prompt.content).toContain('never return only \"18372\"');\n });\n});\n"]}
|
|
@@ -30,9 +30,12 @@ describe("LLM and Agents public API types", () => {
|
|
|
30
30
|
"openai/computer-use-preview",
|
|
31
31
|
"openai/computer-use-preview-2025-03-11",
|
|
32
32
|
"openai/gpt-5.4",
|
|
33
|
+
"openai/gpt-5.4-mini",
|
|
34
|
+
"openai/gpt-5.5",
|
|
33
35
|
"anthropic/claude-opus-4-5-20251101",
|
|
34
36
|
"anthropic/claude-opus-4-6",
|
|
35
37
|
"anthropic/claude-sonnet-4-6",
|
|
38
|
+
"anthropic/claude-haiku-4-5",
|
|
36
39
|
"anthropic/claude-haiku-4-5-20251001",
|
|
37
40
|
"anthropic/claude-sonnet-4-20250514",
|
|
38
41
|
"anthropic/claude-sonnet-4-5-20250929",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"llm-and-agents.test.js","sourceRoot":"","sources":["../../../../../tests/unit/public-api/llm-and-agents.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC5D,OAAO,KAAK,SAAS,MAAM,0BAA0B,CAAC;AAEtD,QAAQ,CAAC,iCAAiC,EAAE,GAAG,EAAE;IAC/C,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;QAClC,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;YAChD,MAAM,YAAY,GAAG;gBACnB,SAAS,EAAE,+BAA+B;gBAC1C,OAAO,EAAE,cAAc;gBACvB,QAAQ,EAAE,QAAQ;gBAClB,OAAO,EAAE;oBACP,iBAAiB,EAAE,MAAM;iBAC1B;aACqC,CAAC;YAEzC,KAAK,YAAY,CAAC;QACpB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,aAAa,EAAE,GAAG,EAAE;QAG3B,EAAE,CAAC,aAAa,EAAE,GAAG,EAAE;YACrB,MAAM,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,WAAW,EAAE,CAAC;QAC9C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,mBAAmB,EAAE,GAAG,EAAE;YAC3B,YAAY,EAAuB,CAAC,QAAQ,EAAuB,CAAC;QACtE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;YAG7C,YAAY,EAAwB,CAAC,aAAa,EAAK,CAAC;QAC1D,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;QACpC,MAAM,cAAc,GAAG;YACrB,6BAA6B;YAC7B,wCAAwC;YACxC,gBAAgB;YAChB,oCAAoC;YACpC,2BAA2B;YAC3B,6BAA6B;YAC7B,qCAAqC;YACrC,oCAAoC;YACpC,sCAAsC;YACtC,gDAAgD;YAChD,+BAA+B;YAC/B,6BAA6B;YAC7B,mBAAmB;SACX,CAAC;QAEX,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;YACtD,YAAY,EAA+B,CAAC,aAAa,EAEtD,CAAC;YACJ,KAAK,cAAc,CAAC,CAAC,iCAAiC;QACxD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;QAG7B,EAAE,CAAC,aAAa,EAAE,GAAG,EAAE;YACrB,MAAM,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC,WAAW,EAAE,CAAC;QAChD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,sBAAsB,EAAE,GAAG,EAAE;YAC9B,YAAY,EAAsC,CAAC,gBAAgB,CACjE,YAAY,CACb,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;YAC9C,YAAY,EAET,CAAC,aAAa,EAA0C,CAAC;QAC9D,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;QAGvC,EAAE,CAAC,qBAAqB,EAAE,GAAG,EAAE;YAC7B,YAAY,EAET,CAAC,QAAQ,EAAmC,CAAC;QAClD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;QAkB9B,EAAE,CAAC,oCAAoC,EAAE,GAAG,EAAE;YAC5C,YAAY,EAA0B,CAAC,QAAQ,EAAiB,CAAC;QACnE,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,aAAa,EAAE,GAAG,EAAE;QAI3B,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE;YAexD,YAAY,EAAmB,CAAC,QAAQ,EAAiB,CAAC;QAC5D,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,WAAW,EAAE,GAAG,EAAE;QAiCzB,EAAE,CAAC,oCAAoC,EAAE,GAAG,EAAE;YAC5C,YAAY,EAAqB,CAAC,QAAQ,EAAiB,CAAC;QAC9D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;YACzD,YAAY,EAET,CAAC,aAAa,EAAsB,CAAC;QAC1C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,uDAAuD,EAAE,GAAG,EAAE;YAC/D,YAAY,EAET,CAAC,gBAAgB,CAAC;gBACnB,OAAO,EAAE;oBACP,QAAQ,EAAE;wBACR;4BACE,IAAI,EAAE,MAAM;4BACZ,OAAO,EAAE,OAAO;yBACjB;qBACF;iBACF;gBACD,MAAM,EAAE,GAAG,EAAE,GAAE,CAAC;aACc,CAAC,CAAC;QACpC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,wDAAwD,EAAE,GAAG,EAAE;YAChE,MAAM,UAAU,GAAG,EAAkC,CAAC;YACtD,YAAY,EAET,CAAC,gBAAgB,CAAC;gBACnB,OAAO,EAAE;oBACP,QAAQ,EAAE;wBACR;4BACE,IAAI,EAAE,MAAM;4BACZ,OAAO,EAAE,cAAc;yBACxB;qBACF;oBACD,cAAc,EAAE;wBACd,IAAI,EAAE,WAAW;wBACjB,MAAM,EAAE,UAAU;qBACnB;iBACF;gBACD,MAAM,EAAE,GAAG,EAAE,GAAE,CAAC;aACmB,CAAC,CAAC;QACzC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;YAM3D,YAAY,EAET,CAAC,QAAQ,EAAqB,CAAC;QACpC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,wBAAwB,EAAE,GAAG,EAAE;YAChC,qFAAqF;YACrF,qDAAqD;YACrD,YAAY,EAAqC,CAAC,QAAQ,EAEvD,CAAC;YACJ,YAAY,EAAuC,CAAC,QAAQ,EAEzD,CAAC;YACJ,YAAY,EAAmC,CAAC,QAAQ,EAErD,CAAC;YACJ,YAAY,EAAqC,CAAC,QAAQ,EAEvD,CAAC;YACJ,YAAY,EAAsC,CAAC,QAAQ,EAExD,CAAC;YACJ,YAAY,EAA8B,CAAC,QAAQ,EAEhD,CAAC;YACJ,YAAY,EAAkC,CAAC,QAAQ,EAEpD,CAAC;YACJ,YAAY,EAAmC,CAAC,QAAQ,EAErD,CAAC;YACJ,YAAY,EAAuC,CAAC,QAAQ,EAEzD,CAAC;QACN,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;QAMvC,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;YAC1C,YAAY,EAET,CAAC,QAAQ,EAAmC,CAAC;QAClD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,UAAU,EAAE,GAAG,EAAE;QAyBxB,EAAE,CAAC,oCAAoC,EAAE,GAAG,EAAE;YAC5C,YAAY,EAAoB,CAAC,QAAQ,EAAiB,CAAC;QAC7D,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { describe, expect, expectTypeOf, it } from \"vitest\";\nimport * as Stagehand from \"@browserbasehq/stagehand\";\n\ndescribe(\"LLM and Agents public API types\", () => {\n describe(\"ModelConfiguration\", () => {\n it(\"accepts Vertex headers in model config\", () => {\n const googleConfig = {\n modelName: \"google/gemini-3-flash-preview\",\n project: \"test-project\",\n location: \"global\",\n headers: {\n \"X-Goog-Priority\": \"high\",\n },\n } satisfies Stagehand.ModelConfiguration;\n\n void googleConfig;\n });\n });\n\n describe(\"AISdkClient\", () => {\n type AISdkClientInstance = InstanceType<typeof Stagehand.AISdkClient>;\n\n it(\"is exported\", () => {\n expect(Stagehand.AISdkClient).toBeDefined();\n });\n\n it(\"extends LLMClient\", () => {\n expectTypeOf<AISdkClientInstance>().toExtend<Stagehand.LLMClient>();\n });\n\n it(\"constructor accepts model parameter\", () => {\n // AISdkClient constructor takes { model: LanguageModelV2 }\n type CtorParams = ConstructorParameters<typeof Stagehand.AISdkClient>;\n expectTypeOf<CtorParams[\"length\"]>().toEqualTypeOf<1>();\n });\n });\n\n describe(\"AVAILABLE_CUA_MODELS\", () => {\n const expectedModels = [\n \"openai/computer-use-preview\",\n \"openai/computer-use-preview-2025-03-11\",\n \"openai/gpt-5.4\",\n \"anthropic/claude-opus-4-5-20251101\",\n \"anthropic/claude-opus-4-6\",\n \"anthropic/claude-sonnet-4-6\",\n \"anthropic/claude-haiku-4-5-20251001\",\n \"anthropic/claude-sonnet-4-20250514\",\n \"anthropic/claude-sonnet-4-5-20250929\",\n \"google/gemini-2.5-computer-use-preview-10-2025\",\n \"google/gemini-3-flash-preview\",\n \"google/gemini-3-pro-preview\",\n \"microsoft/fara-7b\",\n ] as const;\n\n it(\"AvailableCuaModel matches the known literals\", () => {\n expectTypeOf<Stagehand.AvailableCuaModel>().toEqualTypeOf<\n (typeof expectedModels)[number]\n >();\n void expectedModels; // Mark as used to satisfy ESLint\n });\n });\n\n describe(\"AgentProvider\", () => {\n type AgentProviderInstance = InstanceType<typeof Stagehand.AgentProvider>;\n\n it(\"is exported\", () => {\n expect(Stagehand.AgentProvider).toBeDefined();\n });\n\n it(\"has getClient method\", () => {\n expectTypeOf<AgentProviderInstance[\"getClient\"]>().toBeCallableWith(\n \"test-model\",\n );\n });\n\n it(\"constructor accepts logger parameter\", () => {\n expectTypeOf<\n ConstructorParameters<typeof Stagehand.AgentProvider>\n >().toEqualTypeOf<[(message: Stagehand.LogLine) => void]>();\n });\n });\n\n describe(\"AnnotatedScreenshotText\", () => {\n type ExpectedAnnotatedScreenshotText = string;\n\n it(\"is a string literal\", () => {\n expectTypeOf<\n typeof Stagehand.AnnotatedScreenshotText\n >().toExtend<ExpectedAnnotatedScreenshotText>();\n });\n });\n\n describe(\"ConsoleMessage\", () => {\n type ExpectedShape = {\n type: () => string;\n text: () => string;\n args: () => unknown[];\n location: () => {\n url?: string;\n lineNumber?: number;\n columnNumber?: number;\n };\n page: () => unknown;\n timestamp: () => number | undefined;\n raw: () => unknown;\n toString: () => string;\n };\n\n type ConsoleMessageInstance = InstanceType<typeof Stagehand.ConsoleMessage>;\n\n it(\"has correct public interface shape\", () => {\n expectTypeOf<ConsoleMessageInstance>().toExtend<ExpectedShape>();\n });\n });\n\n describe(\"AgentClient\", () => {\n type AgentProviderInstance = InstanceType<typeof Stagehand.AgentProvider>;\n type GetClientReturn = ReturnType<AgentProviderInstance[\"getClient\"]>;\n\n it(\"getClient returns object with expected methods\", () => {\n type ExpectedShape = {\n execute: (\n options: Stagehand.AgentExecutionOptions,\n ) => Promise<Stagehand.AgentResult>;\n captureScreenshot: (\n options?: Record<string, unknown>,\n ) => Promise<unknown>;\n setViewport: (width: number, height: number) => void;\n setCurrentUrl: (url: string) => void;\n setScreenshotProvider: (provider: () => Promise<string>) => void;\n setActionHandler: (\n handler: (action: Stagehand.AgentAction) => Promise<void>,\n ) => void;\n };\n expectTypeOf<GetClientReturn>().toExtend<ExpectedShape>();\n });\n });\n\n describe(\"LLMClient\", () => {\n type ExpectedShape = {\n type: \"openai\" | \"anthropic\" | \"cerebras\" | \"groq\" | (string & {});\n modelName: Stagehand.AvailableModel | (string & {});\n hasVision: boolean;\n clientOptions: Stagehand.ClientOptions;\n userProvidedInstructions?: string;\n };\n\n type ExpectedCtorParams = [Stagehand.AvailableModel, string?];\n\n type ExpectedBasicOptions = {\n options: {\n messages: Array<{\n role: \"system\" | \"user\" | \"assistant\";\n content: string | Array<unknown>;\n }>;\n };\n logger: (message: unknown) => void;\n retries?: number;\n };\n\n type ExpectedWithResponseModel = ExpectedBasicOptions & {\n options: ExpectedBasicOptions[\"options\"] & {\n response_model: {\n name: string;\n schema: Stagehand.StagehandZodSchema;\n };\n };\n };\n\n type LLMClientInstance = InstanceType<typeof Stagehand.LLMClient>;\n\n it(\"has correct public interface shape\", () => {\n expectTypeOf<LLMClientInstance>().toExtend<ExpectedShape>();\n });\n\n it(\"constructor parameters match expected signature\", () => {\n expectTypeOf<\n ConstructorParameters<typeof Stagehand.LLMClient>\n >().toEqualTypeOf<ExpectedCtorParams>();\n });\n\n it(\"createChatCompletion can be called with basic options\", () => {\n expectTypeOf<\n LLMClientInstance[\"createChatCompletion\"]\n >().toBeCallableWith({\n options: {\n messages: [\n {\n role: \"user\",\n content: \"Hello\",\n },\n ],\n },\n logger: () => {},\n } satisfies ExpectedBasicOptions);\n });\n\n it(\"createChatCompletion can be called with response_model\", () => {\n const mockSchema = {} as Stagehand.StagehandZodSchema;\n expectTypeOf<\n LLMClientInstance[\"createChatCompletion\"]\n >().toBeCallableWith({\n options: {\n messages: [\n {\n role: \"user\",\n content: \"Extract data\",\n },\n ],\n response_model: {\n name: \"extracted\",\n schema: mockSchema,\n },\n },\n logger: () => {},\n } satisfies ExpectedWithResponseModel);\n });\n\n it(\"createChatCompletion supports generic return type\", () => {\n type Result = { custom: string };\n type ExpectedSignature = (\n options: Stagehand.CreateChatCompletionOptions,\n ) => Promise<Result>;\n\n expectTypeOf<\n LLMClientInstance[\"createChatCompletion\"]\n >().toExtend<ExpectedSignature>();\n });\n\n it(\"has additional methods\", () => {\n // These methods exist on LLMClient but have complex signatures from the 'ai' library\n // We verify they exist by checking they're functions\n expectTypeOf<LLMClientInstance[\"generateText\"]>().toExtend<\n (...args: unknown[]) => unknown\n >();\n expectTypeOf<LLMClientInstance[\"generateObject\"]>().toExtend<\n (...args: unknown[]) => unknown\n >();\n expectTypeOf<LLMClientInstance[\"streamText\"]>().toExtend<\n (...args: unknown[]) => unknown\n >();\n expectTypeOf<LLMClientInstance[\"streamObject\"]>().toExtend<\n (...args: unknown[]) => unknown\n >();\n expectTypeOf<LLMClientInstance[\"generateImage\"]>().toExtend<\n (...args: unknown[]) => unknown\n >();\n expectTypeOf<LLMClientInstance[\"embed\"]>().toExtend<\n (...args: unknown[]) => unknown\n >();\n expectTypeOf<LLMClientInstance[\"embedMany\"]>().toExtend<\n (...args: unknown[]) => unknown\n >();\n expectTypeOf<LLMClientInstance[\"transcribe\"]>().toExtend<\n (...args: unknown[]) => unknown\n >();\n expectTypeOf<LLMClientInstance[\"generateSpeech\"]>().toExtend<\n (...args: unknown[]) => unknown\n >();\n });\n });\n\n describe(\"modelToAgentProviderMap\", () => {\n type ExpectedModelToAgentProviderMap = Record<\n string,\n Stagehand.AgentProviderType\n >;\n\n it(\"only stores valid provider types\", () => {\n expectTypeOf<\n typeof Stagehand.modelToAgentProviderMap\n >().toExtend<ExpectedModelToAgentProviderMap>();\n });\n });\n\n describe(\"Response\", () => {\n type ExpectedShape = {\n url: () => string;\n status: () => number;\n statusText: () => string;\n ok: () => boolean;\n frame: () => unknown;\n fromServiceWorker: () => boolean;\n securityDetails: () => Promise<unknown>;\n serverAddr: () => Promise<unknown>;\n headers: () => Record<string, string>;\n allHeaders: () => Promise<Record<string, string>>;\n headerValue: (name: string) => Promise<string | null>;\n headerValues: (name: string) => Promise<string[]>;\n headersArray: () => Promise<Array<{ name: string; value: string }>>;\n body: () => Promise<Buffer>;\n text: () => Promise<string>;\n json: <T = unknown>() => Promise<T>;\n finished: () => Promise<null | Error>;\n markFinished: (error: Error | null) => void;\n applyExtraInfo: (info: unknown) => void;\n };\n\n type ResponseInstance = InstanceType<typeof Stagehand.Response>;\n\n it(\"has correct public interface shape\", () => {\n expectTypeOf<ResponseInstance>().toExtend<ExpectedShape>();\n });\n });\n});\n"]}
|
|
1
|
+
{"version":3,"file":"llm-and-agents.test.js","sourceRoot":"","sources":["../../../../../tests/unit/public-api/llm-and-agents.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, expect, expectTypeOf, it } from \"vitest\";\nimport * as Stagehand from \"@browserbasehq/stagehand\";\n\ndescribe(\"LLM and Agents public API types\", () => {\n describe(\"ModelConfiguration\", () => {\n it(\"accepts Vertex headers in model config\", () => {\n const googleConfig = {\n modelName: \"google/gemini-3-flash-preview\",\n project: \"test-project\",\n location: \"global\",\n headers: {\n \"X-Goog-Priority\": \"high\",\n },\n } satisfies Stagehand.ModelConfiguration;\n\n void googleConfig;\n });\n });\n\n describe(\"AISdkClient\", () => {\n type AISdkClientInstance = InstanceType<typeof Stagehand.AISdkClient>;\n\n it(\"is exported\", () => {\n expect(Stagehand.AISdkClient).toBeDefined();\n });\n\n it(\"extends LLMClient\", () => {\n expectTypeOf<AISdkClientInstance>().toExtend<Stagehand.LLMClient>();\n });\n\n it(\"constructor accepts model parameter\", () => {\n // AISdkClient constructor takes { model: LanguageModelV2 }\n type CtorParams = ConstructorParameters<typeof Stagehand.AISdkClient>;\n expectTypeOf<CtorParams[\"length\"]>().toEqualTypeOf<1>();\n });\n });\n\n describe(\"AVAILABLE_CUA_MODELS\", () => {\n const expectedModels = [\n \"openai/computer-use-preview\",\n \"openai/computer-use-preview-2025-03-11\",\n \"openai/gpt-5.4\",\n \"openai/gpt-5.4-mini\",\n \"openai/gpt-5.5\",\n \"anthropic/claude-opus-4-5-20251101\",\n \"anthropic/claude-opus-4-6\",\n \"anthropic/claude-sonnet-4-6\",\n \"anthropic/claude-haiku-4-5\",\n \"anthropic/claude-haiku-4-5-20251001\",\n \"anthropic/claude-sonnet-4-20250514\",\n \"anthropic/claude-sonnet-4-5-20250929\",\n \"google/gemini-2.5-computer-use-preview-10-2025\",\n \"google/gemini-3-flash-preview\",\n \"google/gemini-3-pro-preview\",\n \"microsoft/fara-7b\",\n ] as const;\n\n it(\"AvailableCuaModel matches the known literals\", () => {\n expectTypeOf<Stagehand.AvailableCuaModel>().toEqualTypeOf<\n (typeof expectedModels)[number]\n >();\n void expectedModels; // Mark as used to satisfy ESLint\n });\n });\n\n describe(\"AgentProvider\", () => {\n type AgentProviderInstance = InstanceType<typeof Stagehand.AgentProvider>;\n\n it(\"is exported\", () => {\n expect(Stagehand.AgentProvider).toBeDefined();\n });\n\n it(\"has getClient method\", () => {\n expectTypeOf<AgentProviderInstance[\"getClient\"]>().toBeCallableWith(\n \"test-model\",\n );\n });\n\n it(\"constructor accepts logger parameter\", () => {\n expectTypeOf<\n ConstructorParameters<typeof Stagehand.AgentProvider>\n >().toEqualTypeOf<[(message: Stagehand.LogLine) => void]>();\n });\n });\n\n describe(\"AnnotatedScreenshotText\", () => {\n type ExpectedAnnotatedScreenshotText = string;\n\n it(\"is a string literal\", () => {\n expectTypeOf<\n typeof Stagehand.AnnotatedScreenshotText\n >().toExtend<ExpectedAnnotatedScreenshotText>();\n });\n });\n\n describe(\"ConsoleMessage\", () => {\n type ExpectedShape = {\n type: () => string;\n text: () => string;\n args: () => unknown[];\n location: () => {\n url?: string;\n lineNumber?: number;\n columnNumber?: number;\n };\n page: () => unknown;\n timestamp: () => number | undefined;\n raw: () => unknown;\n toString: () => string;\n };\n\n type ConsoleMessageInstance = InstanceType<typeof Stagehand.ConsoleMessage>;\n\n it(\"has correct public interface shape\", () => {\n expectTypeOf<ConsoleMessageInstance>().toExtend<ExpectedShape>();\n });\n });\n\n describe(\"AgentClient\", () => {\n type AgentProviderInstance = InstanceType<typeof Stagehand.AgentProvider>;\n type GetClientReturn = ReturnType<AgentProviderInstance[\"getClient\"]>;\n\n it(\"getClient returns object with expected methods\", () => {\n type ExpectedShape = {\n execute: (\n options: Stagehand.AgentExecutionOptions,\n ) => Promise<Stagehand.AgentResult>;\n captureScreenshot: (\n options?: Record<string, unknown>,\n ) => Promise<unknown>;\n setViewport: (width: number, height: number) => void;\n setCurrentUrl: (url: string) => void;\n setScreenshotProvider: (provider: () => Promise<string>) => void;\n setActionHandler: (\n handler: (action: Stagehand.AgentAction) => Promise<void>,\n ) => void;\n };\n expectTypeOf<GetClientReturn>().toExtend<ExpectedShape>();\n });\n });\n\n describe(\"LLMClient\", () => {\n type ExpectedShape = {\n type: \"openai\" | \"anthropic\" | \"cerebras\" | \"groq\" | (string & {});\n modelName: Stagehand.AvailableModel | (string & {});\n hasVision: boolean;\n clientOptions: Stagehand.ClientOptions;\n userProvidedInstructions?: string;\n };\n\n type ExpectedCtorParams = [Stagehand.AvailableModel, string?];\n\n type ExpectedBasicOptions = {\n options: {\n messages: Array<{\n role: \"system\" | \"user\" | \"assistant\";\n content: string | Array<unknown>;\n }>;\n };\n logger: (message: unknown) => void;\n retries?: number;\n };\n\n type ExpectedWithResponseModel = ExpectedBasicOptions & {\n options: ExpectedBasicOptions[\"options\"] & {\n response_model: {\n name: string;\n schema: Stagehand.StagehandZodSchema;\n };\n };\n };\n\n type LLMClientInstance = InstanceType<typeof Stagehand.LLMClient>;\n\n it(\"has correct public interface shape\", () => {\n expectTypeOf<LLMClientInstance>().toExtend<ExpectedShape>();\n });\n\n it(\"constructor parameters match expected signature\", () => {\n expectTypeOf<\n ConstructorParameters<typeof Stagehand.LLMClient>\n >().toEqualTypeOf<ExpectedCtorParams>();\n });\n\n it(\"createChatCompletion can be called with basic options\", () => {\n expectTypeOf<\n LLMClientInstance[\"createChatCompletion\"]\n >().toBeCallableWith({\n options: {\n messages: [\n {\n role: \"user\",\n content: \"Hello\",\n },\n ],\n },\n logger: () => {},\n } satisfies ExpectedBasicOptions);\n });\n\n it(\"createChatCompletion can be called with response_model\", () => {\n const mockSchema = {} as Stagehand.StagehandZodSchema;\n expectTypeOf<\n LLMClientInstance[\"createChatCompletion\"]\n >().toBeCallableWith({\n options: {\n messages: [\n {\n role: \"user\",\n content: \"Extract data\",\n },\n ],\n response_model: {\n name: \"extracted\",\n schema: mockSchema,\n },\n },\n logger: () => {},\n } satisfies ExpectedWithResponseModel);\n });\n\n it(\"createChatCompletion supports generic return type\", () => {\n type Result = { custom: string };\n type ExpectedSignature = (\n options: Stagehand.CreateChatCompletionOptions,\n ) => Promise<Result>;\n\n expectTypeOf<\n LLMClientInstance[\"createChatCompletion\"]\n >().toExtend<ExpectedSignature>();\n });\n\n it(\"has additional methods\", () => {\n // These methods exist on LLMClient but have complex signatures from the 'ai' library\n // We verify they exist by checking they're functions\n expectTypeOf<LLMClientInstance[\"generateText\"]>().toExtend<\n (...args: unknown[]) => unknown\n >();\n expectTypeOf<LLMClientInstance[\"generateObject\"]>().toExtend<\n (...args: unknown[]) => unknown\n >();\n expectTypeOf<LLMClientInstance[\"streamText\"]>().toExtend<\n (...args: unknown[]) => unknown\n >();\n expectTypeOf<LLMClientInstance[\"streamObject\"]>().toExtend<\n (...args: unknown[]) => unknown\n >();\n expectTypeOf<LLMClientInstance[\"generateImage\"]>().toExtend<\n (...args: unknown[]) => unknown\n >();\n expectTypeOf<LLMClientInstance[\"embed\"]>().toExtend<\n (...args: unknown[]) => unknown\n >();\n expectTypeOf<LLMClientInstance[\"embedMany\"]>().toExtend<\n (...args: unknown[]) => unknown\n >();\n expectTypeOf<LLMClientInstance[\"transcribe\"]>().toExtend<\n (...args: unknown[]) => unknown\n >();\n expectTypeOf<LLMClientInstance[\"generateSpeech\"]>().toExtend<\n (...args: unknown[]) => unknown\n >();\n });\n });\n\n describe(\"modelToAgentProviderMap\", () => {\n type ExpectedModelToAgentProviderMap = Record<\n string,\n Stagehand.AgentProviderType\n >;\n\n it(\"only stores valid provider types\", () => {\n expectTypeOf<\n typeof Stagehand.modelToAgentProviderMap\n >().toExtend<ExpectedModelToAgentProviderMap>();\n });\n });\n\n describe(\"Response\", () => {\n type ExpectedShape = {\n url: () => string;\n status: () => number;\n statusText: () => string;\n ok: () => boolean;\n frame: () => unknown;\n fromServiceWorker: () => boolean;\n securityDetails: () => Promise<unknown>;\n serverAddr: () => Promise<unknown>;\n headers: () => Record<string, string>;\n allHeaders: () => Promise<Record<string, string>>;\n headerValue: (name: string) => Promise<string | null>;\n headerValues: (name: string) => Promise<string[]>;\n headersArray: () => Promise<Array<{ name: string; value: string }>>;\n body: () => Promise<Buffer>;\n text: () => Promise<string>;\n json: <T = unknown>() => Promise<T>;\n finished: () => Promise<null | Error>;\n markFinished: (error: Error | null) => void;\n applyExtraInfo: (info: unknown) => void;\n };\n\n type ResponseInstance = InstanceType<typeof Stagehand.Response>;\n\n it(\"has correct public interface shape\", () => {\n expectTypeOf<ResponseInstance>().toExtend<ExpectedShape>();\n });\n });\n});\n"]}
|