diff --git a/.changeset/shiny-ladybugs-shave.md b/.changeset/shiny-ladybugs-shave.md new file mode 100644 index 00000000..f95423fd --- /dev/null +++ b/.changeset/shiny-ladybugs-shave.md @@ -0,0 +1,5 @@ +--- +"@browserbasehq/stagehand": patch +--- + +Added example implementation of the Vercel AI SDK as an LLMClient diff --git a/examples/ai_sdk_example.ts b/examples/ai_sdk_example.ts new file mode 100644 index 00000000..ef6037dc --- /dev/null +++ b/examples/ai_sdk_example.ts @@ -0,0 +1,40 @@ +import { google } from "@ai-sdk/google"; +import { z } from "zod"; +import { Stagehand } from "../lib"; +import { AISdkClient } from "./external_clients/aisdk"; +import StagehandConfig from "./stagehand.config"; + +async function example() { + const stagehand = new Stagehand({ + ...StagehandConfig, + llmClient: new AISdkClient({ + model: google("gemini-1.5-flash-latest"), + }), + }); + + await stagehand.init(); + await stagehand.page.goto("https://news.ycombinator.com"); + + const headlines = await stagehand.page.extract({ + instruction: "Extract only 3 stories from the Hacker News homepage.", + schema: z.object({ + stories: z + .array( + z.object({ + title: z.string(), + url: z.string(), + points: z.number(), + }), + ) + .length(3), + }), + }); + + console.log(headlines); + + await stagehand.close(); +} + +(async () => { + await example(); +})(); diff --git a/examples/external_clients/aisdk.ts b/examples/external_clients/aisdk.ts new file mode 100644 index 00000000..83e35cc1 --- /dev/null +++ b/examples/external_clients/aisdk.ts @@ -0,0 +1,112 @@ +import { + CoreAssistantMessage, + CoreMessage, + CoreSystemMessage, + CoreTool, + CoreUserMessage, + generateObject, + generateText, + ImagePart, + LanguageModel, + TextPart, +} from "ai"; +import { ChatCompletion } from "openai/resources/chat/completions"; +import { + CreateChatCompletionOptions, + LLMClient, +} from "../../lib/llm/LLMClient"; +import { AvailableModel } from "../../types/model"; + +export class AISdkClient extends LLMClient { + public type = "aisdk" as const; + private model: LanguageModel; + + constructor({ model }: { model: LanguageModel }) { + super(model.modelId as AvailableModel); + this.model = model; + } + + async createChatCompletion({ + options, + }: CreateChatCompletionOptions): Promise { + const formattedMessages: CoreMessage[] = options.messages.map((message) => { + if (Array.isArray(message.content)) { + if (message.role === "system") { + const systemMessage: CoreSystemMessage = { + role: "system", + content: message.content + .map((c) => ("text" in c ? c.text : "")) + .join("\n"), + }; + return systemMessage; + } + + const contentParts = message.content.map((content) => { + if ("image_url" in content) { + const imageContent: ImagePart = { + type: "image", + image: content.image_url.url, + }; + return imageContent; + } else { + const textContent: TextPart = { + type: "text", + text: content.text, + }; + return textContent; + } + }); + + if (message.role === "user") { + const userMessage: CoreUserMessage = { + role: "user", + content: contentParts, + }; + return userMessage; + } else { + const textOnlyParts = contentParts.map((part) => ({ + type: "text" as const, + text: part.type === "image" ? "[Image]" : part.text, + })); + const assistantMessage: CoreAssistantMessage = { + role: "assistant", + content: textOnlyParts, + }; + return assistantMessage; + } + } + + return { + role: message.role, + content: message.content, + }; + }); + + if (options.response_model) { + const response = await generateObject({ + model: this.model, + messages: formattedMessages, + schema: options.response_model.schema, + }); + + return response.object; + } + + const tools: Record = {}; + + for (const rawTool of options.tools) { + tools[rawTool.name] = { + description: rawTool.description, + parameters: rawTool.parameters, + }; + } + + const response = await generateText({ + model: this.model, + messages: formattedMessages, + tools, + }); + + return response as T; + } +} diff --git a/lib/index.ts b/lib/index.ts index 18997a91..cceb4d7c 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -372,6 +372,7 @@ export class Stagehand { this.llmClient = undefined; } } + this.domSettleTimeoutMs = domSettleTimeoutMs ?? 30_000; this.headless = headless ?? false; this.browserbaseSessionCreateParams = browserbaseSessionCreateParams; diff --git a/package-lock.json b/package-lock.json index 47f40009..da63850a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,20 +1,23 @@ { "name": "@browserbasehq/stagehand", - "version": "1.7.0", + "version": "1.8.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@browserbasehq/stagehand", - "version": "1.7.0", + "version": "1.8.0", "license": "MIT", "dependencies": { "@anthropic-ai/sdk": "^0.27.3", "@browserbasehq/sdk": "^2.0.0", "sharp": "^0.33.5", + "ws": "^8.18.0", "zod-to-json-schema": "^3.23.5" }, "devDependencies": { + "@ai-sdk/google": "^1.0.13", + "@ai-sdk/openai": "^1.0.14", "@changesets/changelog-github": "^0.5.0", "@changesets/cli": "^2.27.9", "@eslint/js": "^9.16.0", @@ -24,6 +27,7 @@ "@types/node": "^20.11.30", "@types/ws": "^8.5.13", "adm-zip": "^0.5.16", + "ai": "^4.0.26", "autoevals": "^0.0.64", "braintrust": "^0.0.171", "cheerio": "^1.0.0", @@ -48,6 +52,134 @@ "zod": "^3.23.8" } }, + "node_modules/@ai-sdk/google": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/@ai-sdk/google/-/google-1.0.13.tgz", + "integrity": "sha512-L4ej4rd3JpHp0QVqlgr383EedwQXu9tJ3hmJl793Lt8zMLgY+VKZE816v/bz0R3zCyTtiUrxR+LDhbSMuPV7eQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@ai-sdk/provider": "1.0.4", + "@ai-sdk/provider-utils": "2.0.6" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "zod": "^3.0.0" + } + }, + "node_modules/@ai-sdk/google/node_modules/@ai-sdk/provider": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-1.0.4.tgz", + "integrity": "sha512-lJi5zwDosvvZER3e/pB8lj1MN3o3S7zJliQq56BRr4e9V3fcRyFtwP0JRxaRS5vHYX3OJ154VezVoQNrk0eaKw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "json-schema": "^0.4.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@ai-sdk/google/node_modules/@ai-sdk/provider-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-2.0.6.tgz", + "integrity": "sha512-nB0rPwIBSCk0UkfdkprAxQ45ZjfKlk+Ts5zvIBQkJ5SnTCL9meg6bW65aomQrxhdvtqZML2jjaWTI8/l6AIVlQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@ai-sdk/provider": "1.0.4", + "eventsource-parser": "^3.0.0", + "nanoid": "^3.3.8", + "secure-json-parse": "^2.7.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "zod": "^3.0.0" + }, + "peerDependenciesMeta": { + "zod": { + "optional": true + } + } + }, + "node_modules/@ai-sdk/google/node_modules/eventsource-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.0.tgz", + "integrity": "sha512-T1C0XCUimhxVQzW4zFipdx0SficT651NnkR0ZSH3yQwh+mFMdLfgjABVi4YtMTtaL4s168593DaoaRLMqryavA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@ai-sdk/openai": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/@ai-sdk/openai/-/openai-1.0.14.tgz", + "integrity": "sha512-uyOkQNtYsHr4qyV7y0rmMAtdW4LTJoThYo1qXcvQa30RDh/MyvLEOjKYX181Siyp8LcTqYvwf6Tt+eckdVTTug==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@ai-sdk/provider": "1.0.4", + "@ai-sdk/provider-utils": "2.0.6" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "zod": "^3.0.0" + } + }, + "node_modules/@ai-sdk/openai/node_modules/@ai-sdk/provider": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-1.0.4.tgz", + "integrity": "sha512-lJi5zwDosvvZER3e/pB8lj1MN3o3S7zJliQq56BRr4e9V3fcRyFtwP0JRxaRS5vHYX3OJ154VezVoQNrk0eaKw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "json-schema": "^0.4.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@ai-sdk/openai/node_modules/@ai-sdk/provider-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-2.0.6.tgz", + "integrity": "sha512-nB0rPwIBSCk0UkfdkprAxQ45ZjfKlk+Ts5zvIBQkJ5SnTCL9meg6bW65aomQrxhdvtqZML2jjaWTI8/l6AIVlQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@ai-sdk/provider": "1.0.4", + "eventsource-parser": "^3.0.0", + "nanoid": "^3.3.8", + "secure-json-parse": "^2.7.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "zod": "^3.0.0" + }, + "peerDependenciesMeta": { + "zod": { + "optional": true + } + } + }, + "node_modules/@ai-sdk/openai/node_modules/eventsource-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.0.tgz", + "integrity": "sha512-T1C0XCUimhxVQzW4zFipdx0SficT651NnkR0ZSH3yQwh+mFMdLfgjABVi4YtMTtaL4s168593DaoaRLMqryavA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@ai-sdk/provider": { "version": "0.0.11", "resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-0.0.11.tgz", @@ -62,15 +194,15 @@ } }, "node_modules/@ai-sdk/provider-utils": { - "version": "1.0.22", - "resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-1.0.22.tgz", - "integrity": "sha512-YHK2rpj++wnLVc9vPGzGFP3Pjeld2MwhKinetA0zKXOoHAT/Jit5O8kZsxcSlJPu9wvcGT1UGZEjZrtO7PfFOQ==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-2.0.5.tgz", + "integrity": "sha512-2M7vLhYN0ThGjNlzow7oO/lsL+DyMxvGMIYmVQvEYaCWhDzxH5dOp78VNjJIVwHzVLMbBDigX3rJuzAs853idw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@ai-sdk/provider": "0.0.26", - "eventsource-parser": "^1.1.2", - "nanoid": "^3.3.7", + "@ai-sdk/provider": "1.0.3", + "eventsource-parser": "^3.0.0", + "nanoid": "^3.3.8", "secure-json-parse": "^2.7.0" }, "engines": { @@ -86,9 +218,9 @@ } }, "node_modules/@ai-sdk/provider-utils/node_modules/@ai-sdk/provider": { - "version": "0.0.26", - "resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-0.0.26.tgz", - "integrity": "sha512-dQkfBDs2lTYpKM8389oopPdQgIU007GQyCbuPPrV+K6MtSII3HBfE0stUIMXUb44L+LK1t6GXPP7wjSzjO6uKg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-1.0.3.tgz", + "integrity": "sha512-WiuJEpHTrltOIzv3x2wx4gwksAHW0h6nK3SoDzjqCOJLu/2OJ1yASESTIX+f07ChFykHElVoP80Ol/fe9dw6tQ==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -98,15 +230,25 @@ "node": ">=18" } }, + "node_modules/@ai-sdk/provider-utils/node_modules/eventsource-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.0.tgz", + "integrity": "sha512-T1C0XCUimhxVQzW4zFipdx0SficT651NnkR0ZSH3yQwh+mFMdLfgjABVi4YtMTtaL4s168593DaoaRLMqryavA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@ai-sdk/react": { - "version": "0.0.70", - "resolved": "https://registry.npmjs.org/@ai-sdk/react/-/react-0.0.70.tgz", - "integrity": "sha512-GnwbtjW4/4z7MleLiW+TOZC2M29eCg1tOUpuEiYFMmFNZK8mkrqM0PFZMo6UsYeUYMWqEOOcPOU9OQVJMJh7IQ==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@ai-sdk/react/-/react-1.0.7.tgz", + "integrity": "sha512-j2/of4iCNq+r2Bjx0O9vdRhn5C/02t2Esenis71YtnsoynPz74eQlJ3N0RYYPheThiJes50yHdfdVdH9ulxs1A==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@ai-sdk/provider-utils": "1.0.22", - "@ai-sdk/ui-utils": "0.0.50", + "@ai-sdk/provider-utils": "2.0.5", + "@ai-sdk/ui-utils": "1.0.6", "swr": "^2.2.5", "throttleit": "2.1.0" }, @@ -148,6 +290,68 @@ } } }, + "node_modules/@ai-sdk/solid/node_modules/@ai-sdk/provider": { + "version": "0.0.26", + "resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-0.0.26.tgz", + "integrity": "sha512-dQkfBDs2lTYpKM8389oopPdQgIU007GQyCbuPPrV+K6MtSII3HBfE0stUIMXUb44L+LK1t6GXPP7wjSzjO6uKg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "json-schema": "^0.4.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@ai-sdk/solid/node_modules/@ai-sdk/provider-utils": { + "version": "1.0.22", + "resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-1.0.22.tgz", + "integrity": "sha512-YHK2rpj++wnLVc9vPGzGFP3Pjeld2MwhKinetA0zKXOoHAT/Jit5O8kZsxcSlJPu9wvcGT1UGZEjZrtO7PfFOQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@ai-sdk/provider": "0.0.26", + "eventsource-parser": "^1.1.2", + "nanoid": "^3.3.7", + "secure-json-parse": "^2.7.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "zod": "^3.0.0" + }, + "peerDependenciesMeta": { + "zod": { + "optional": true + } + } + }, + "node_modules/@ai-sdk/solid/node_modules/@ai-sdk/ui-utils": { + "version": "0.0.50", + "resolved": "https://registry.npmjs.org/@ai-sdk/ui-utils/-/ui-utils-0.0.50.tgz", + "integrity": "sha512-Z5QYJVW+5XpSaJ4jYCCAVG7zIAuKOOdikhgpksneNmKvx61ACFaf98pmOd+xnjahl0pIlc/QIe6O4yVaJ1sEaw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@ai-sdk/provider": "0.0.26", + "@ai-sdk/provider-utils": "1.0.22", + "json-schema": "^0.4.0", + "secure-json-parse": "^2.7.0", + "zod-to-json-schema": "^3.23.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "zod": "^3.0.0" + }, + "peerDependenciesMeta": { + "zod": { + "optional": true + } + } + }, "node_modules/@ai-sdk/svelte": { "version": "0.0.57", "resolved": "https://registry.npmjs.org/@ai-sdk/svelte/-/svelte-0.0.57.tgz", @@ -171,7 +375,44 @@ } } }, - "node_modules/@ai-sdk/ui-utils": { + "node_modules/@ai-sdk/svelte/node_modules/@ai-sdk/provider": { + "version": "0.0.26", + "resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-0.0.26.tgz", + "integrity": "sha512-dQkfBDs2lTYpKM8389oopPdQgIU007GQyCbuPPrV+K6MtSII3HBfE0stUIMXUb44L+LK1t6GXPP7wjSzjO6uKg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "json-schema": "^0.4.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@ai-sdk/svelte/node_modules/@ai-sdk/provider-utils": { + "version": "1.0.22", + "resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-1.0.22.tgz", + "integrity": "sha512-YHK2rpj++wnLVc9vPGzGFP3Pjeld2MwhKinetA0zKXOoHAT/Jit5O8kZsxcSlJPu9wvcGT1UGZEjZrtO7PfFOQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@ai-sdk/provider": "0.0.26", + "eventsource-parser": "^1.1.2", + "nanoid": "^3.3.7", + "secure-json-parse": "^2.7.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "zod": "^3.0.0" + }, + "peerDependenciesMeta": { + "zod": { + "optional": true + } + } + }, + "node_modules/@ai-sdk/svelte/node_modules/@ai-sdk/ui-utils": { "version": "0.0.50", "resolved": "https://registry.npmjs.org/@ai-sdk/ui-utils/-/ui-utils-0.0.50.tgz", "integrity": "sha512-Z5QYJVW+5XpSaJ4jYCCAVG7zIAuKOOdikhgpksneNmKvx61ACFaf98pmOd+xnjahl0pIlc/QIe6O4yVaJ1sEaw==", @@ -196,38 +437,123 @@ } } }, - "node_modules/@ai-sdk/ui-utils/node_modules/@ai-sdk/provider": { - "version": "0.0.26", - "resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-0.0.26.tgz", - "integrity": "sha512-dQkfBDs2lTYpKM8389oopPdQgIU007GQyCbuPPrV+K6MtSII3HBfE0stUIMXUb44L+LK1t6GXPP7wjSzjO6uKg==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "json-schema": "^0.4.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@ai-sdk/vue": { - "version": "0.0.59", - "resolved": "https://registry.npmjs.org/@ai-sdk/vue/-/vue-0.0.59.tgz", - "integrity": "sha512-+ofYlnqdc8c4F6tM0IKF0+7NagZRAiqBJpGDJ+6EYhDW8FHLUP/JFBgu32SjxSxC6IKFZxEnl68ZoP/Z38EMlw==", + "node_modules/@ai-sdk/ui-utils": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@ai-sdk/ui-utils/-/ui-utils-1.0.6.tgz", + "integrity": "sha512-ZP6Vjj+VCnSPBIAvWAdKj2olQONJ/f4aZpkVCGkzprdhv8TjHwB6CTlXFS3zypuEGy4asg84dc1dvXKooQXFvg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@ai-sdk/provider": "1.0.3", + "@ai-sdk/provider-utils": "2.0.5", + "zod-to-json-schema": "^3.23.5" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "zod": "^3.0.0" + }, + "peerDependenciesMeta": { + "zod": { + "optional": true + } + } + }, + "node_modules/@ai-sdk/ui-utils/node_modules/@ai-sdk/provider": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-1.0.3.tgz", + "integrity": "sha512-WiuJEpHTrltOIzv3x2wx4gwksAHW0h6nK3SoDzjqCOJLu/2OJ1yASESTIX+f07ChFykHElVoP80Ol/fe9dw6tQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "json-schema": "^0.4.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@ai-sdk/vue": { + "version": "0.0.59", + "resolved": "https://registry.npmjs.org/@ai-sdk/vue/-/vue-0.0.59.tgz", + "integrity": "sha512-+ofYlnqdc8c4F6tM0IKF0+7NagZRAiqBJpGDJ+6EYhDW8FHLUP/JFBgu32SjxSxC6IKFZxEnl68ZoP/Z38EMlw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@ai-sdk/provider-utils": "1.0.22", + "@ai-sdk/ui-utils": "0.0.50", + "swrv": "^1.0.4" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "vue": "^3.3.4" + }, + "peerDependenciesMeta": { + "vue": { + "optional": true + } + } + }, + "node_modules/@ai-sdk/vue/node_modules/@ai-sdk/provider": { + "version": "0.0.26", + "resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-0.0.26.tgz", + "integrity": "sha512-dQkfBDs2lTYpKM8389oopPdQgIU007GQyCbuPPrV+K6MtSII3HBfE0stUIMXUb44L+LK1t6GXPP7wjSzjO6uKg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "json-schema": "^0.4.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@ai-sdk/vue/node_modules/@ai-sdk/provider-utils": { + "version": "1.0.22", + "resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-1.0.22.tgz", + "integrity": "sha512-YHK2rpj++wnLVc9vPGzGFP3Pjeld2MwhKinetA0zKXOoHAT/Jit5O8kZsxcSlJPu9wvcGT1UGZEjZrtO7PfFOQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@ai-sdk/provider": "0.0.26", + "eventsource-parser": "^1.1.2", + "nanoid": "^3.3.7", + "secure-json-parse": "^2.7.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "zod": "^3.0.0" + }, + "peerDependenciesMeta": { + "zod": { + "optional": true + } + } + }, + "node_modules/@ai-sdk/vue/node_modules/@ai-sdk/ui-utils": { + "version": "0.0.50", + "resolved": "https://registry.npmjs.org/@ai-sdk/ui-utils/-/ui-utils-0.0.50.tgz", + "integrity": "sha512-Z5QYJVW+5XpSaJ4jYCCAVG7zIAuKOOdikhgpksneNmKvx61ACFaf98pmOd+xnjahl0pIlc/QIe6O4yVaJ1sEaw==", "dev": true, "license": "Apache-2.0", "dependencies": { + "@ai-sdk/provider": "0.0.26", "@ai-sdk/provider-utils": "1.0.22", - "@ai-sdk/ui-utils": "0.0.50", - "swrv": "^1.0.4" + "json-schema": "^0.4.0", + "secure-json-parse": "^2.7.0", + "zod-to-json-schema": "^3.23.3" }, "engines": { "node": ">=18" }, "peerDependencies": { - "vue": "^3.3.4" + "zod": "^3.0.0" }, "peerDependenciesMeta": { - "vue": { + "zod": { "optional": true } } @@ -2882,58 +3208,40 @@ } }, "node_modules/ai": { - "version": "3.4.33", - "resolved": "https://registry.npmjs.org/ai/-/ai-3.4.33.tgz", - "integrity": "sha512-plBlrVZKwPoRTmM8+D1sJac9Bq8eaa2jiZlHLZIWekKWI1yMWYZvCCEezY9ASPwRhULYDJB2VhKOBUUeg3S5JQ==", + "version": "4.0.26", + "resolved": "https://registry.npmjs.org/ai/-/ai-4.0.26.tgz", + "integrity": "sha512-IDnSkiH0C+s+9jfKA5M8vO6PO279b5N/OtkbIy4gYtajLT5i52OobssG6LdZExZQxlYgBvXvTl3YskKJE/kD8Q==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@ai-sdk/provider": "0.0.26", - "@ai-sdk/provider-utils": "1.0.22", - "@ai-sdk/react": "0.0.70", - "@ai-sdk/solid": "0.0.54", - "@ai-sdk/svelte": "0.0.57", - "@ai-sdk/ui-utils": "0.0.50", - "@ai-sdk/vue": "0.0.59", + "@ai-sdk/provider": "1.0.3", + "@ai-sdk/provider-utils": "2.0.5", + "@ai-sdk/react": "1.0.7", + "@ai-sdk/ui-utils": "1.0.6", "@opentelemetry/api": "1.9.0", - "eventsource-parser": "1.1.2", - "json-schema": "^0.4.0", "jsondiffpatch": "0.6.0", - "secure-json-parse": "^2.7.0", - "zod-to-json-schema": "^3.23.3" + "zod-to-json-schema": "^3.23.5" }, "engines": { "node": ">=18" }, "peerDependencies": { - "openai": "^4.42.0", "react": "^18 || ^19 || ^19.0.0-rc", - "sswr": "^2.1.0", - "svelte": "^3.0.0 || ^4.0.0 || ^5.0.0", "zod": "^3.0.0" }, "peerDependenciesMeta": { - "openai": { - "optional": true - }, "react": { "optional": true }, - "sswr": { - "optional": true - }, - "svelte": { - "optional": true - }, "zod": { "optional": true } } }, "node_modules/ai/node_modules/@ai-sdk/provider": { - "version": "0.0.26", - "resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-0.0.26.tgz", - "integrity": "sha512-dQkfBDs2lTYpKM8389oopPdQgIU007GQyCbuPPrV+K6MtSII3HBfE0stUIMXUb44L+LK1t6GXPP7wjSzjO6uKg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-1.0.3.tgz", + "integrity": "sha512-WiuJEpHTrltOIzv3x2wx4gwksAHW0h6nK3SoDzjqCOJLu/2OJ1yASESTIX+f07ChFykHElVoP80Ol/fe9dw6tQ==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -3295,6 +3603,109 @@ "zod": "^3.0.0" } }, + "node_modules/braintrust/node_modules/@ai-sdk/provider-utils": { + "version": "1.0.22", + "resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-1.0.22.tgz", + "integrity": "sha512-YHK2rpj++wnLVc9vPGzGFP3Pjeld2MwhKinetA0zKXOoHAT/Jit5O8kZsxcSlJPu9wvcGT1UGZEjZrtO7PfFOQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@ai-sdk/provider": "0.0.26", + "eventsource-parser": "^1.1.2", + "nanoid": "^3.3.7", + "secure-json-parse": "^2.7.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "zod": "^3.0.0" + }, + "peerDependenciesMeta": { + "zod": { + "optional": true + } + } + }, + "node_modules/braintrust/node_modules/@ai-sdk/provider-utils/node_modules/@ai-sdk/provider": { + "version": "0.0.26", + "resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-0.0.26.tgz", + "integrity": "sha512-dQkfBDs2lTYpKM8389oopPdQgIU007GQyCbuPPrV+K6MtSII3HBfE0stUIMXUb44L+LK1t6GXPP7wjSzjO6uKg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "json-schema": "^0.4.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/braintrust/node_modules/@ai-sdk/react": { + "version": "0.0.70", + "resolved": "https://registry.npmjs.org/@ai-sdk/react/-/react-0.0.70.tgz", + "integrity": "sha512-GnwbtjW4/4z7MleLiW+TOZC2M29eCg1tOUpuEiYFMmFNZK8mkrqM0PFZMo6UsYeUYMWqEOOcPOU9OQVJMJh7IQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@ai-sdk/provider-utils": "1.0.22", + "@ai-sdk/ui-utils": "0.0.50", + "swr": "^2.2.5", + "throttleit": "2.1.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "react": "^18 || ^19 || ^19.0.0-rc", + "zod": "^3.0.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "zod": { + "optional": true + } + } + }, + "node_modules/braintrust/node_modules/@ai-sdk/ui-utils": { + "version": "0.0.50", + "resolved": "https://registry.npmjs.org/@ai-sdk/ui-utils/-/ui-utils-0.0.50.tgz", + "integrity": "sha512-Z5QYJVW+5XpSaJ4jYCCAVG7zIAuKOOdikhgpksneNmKvx61ACFaf98pmOd+xnjahl0pIlc/QIe6O4yVaJ1sEaw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@ai-sdk/provider": "0.0.26", + "@ai-sdk/provider-utils": "1.0.22", + "json-schema": "^0.4.0", + "secure-json-parse": "^2.7.0", + "zod-to-json-schema": "^3.23.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "zod": "^3.0.0" + }, + "peerDependenciesMeta": { + "zod": { + "optional": true + } + } + }, + "node_modules/braintrust/node_modules/@ai-sdk/ui-utils/node_modules/@ai-sdk/provider": { + "version": "0.0.26", + "resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-0.0.26.tgz", + "integrity": "sha512-dQkfBDs2lTYpKM8389oopPdQgIU007GQyCbuPPrV+K6MtSII3HBfE0stUIMXUb44L+LK1t6GXPP7wjSzjO6uKg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "json-schema": "^0.4.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/braintrust/node_modules/@braintrust/core": { "version": "0.0.67", "resolved": "https://registry.npmjs.org/@braintrust/core/-/core-0.0.67.tgz", @@ -3681,6 +4092,68 @@ "node": ">=12" } }, + "node_modules/braintrust/node_modules/ai": { + "version": "3.4.33", + "resolved": "https://registry.npmjs.org/ai/-/ai-3.4.33.tgz", + "integrity": "sha512-plBlrVZKwPoRTmM8+D1sJac9Bq8eaa2jiZlHLZIWekKWI1yMWYZvCCEezY9ASPwRhULYDJB2VhKOBUUeg3S5JQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@ai-sdk/provider": "0.0.26", + "@ai-sdk/provider-utils": "1.0.22", + "@ai-sdk/react": "0.0.70", + "@ai-sdk/solid": "0.0.54", + "@ai-sdk/svelte": "0.0.57", + "@ai-sdk/ui-utils": "0.0.50", + "@ai-sdk/vue": "0.0.59", + "@opentelemetry/api": "1.9.0", + "eventsource-parser": "1.1.2", + "json-schema": "^0.4.0", + "jsondiffpatch": "0.6.0", + "secure-json-parse": "^2.7.0", + "zod-to-json-schema": "^3.23.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "openai": "^4.42.0", + "react": "^18 || ^19 || ^19.0.0-rc", + "sswr": "^2.1.0", + "svelte": "^3.0.0 || ^4.0.0 || ^5.0.0", + "zod": "^3.0.0" + }, + "peerDependenciesMeta": { + "openai": { + "optional": true + }, + "react": { + "optional": true + }, + "sswr": { + "optional": true + }, + "svelte": { + "optional": true + }, + "zod": { + "optional": true + } + } + }, + "node_modules/braintrust/node_modules/ai/node_modules/@ai-sdk/provider": { + "version": "0.0.26", + "resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-0.0.26.tgz", + "integrity": "sha512-dQkfBDs2lTYpKM8389oopPdQgIU007GQyCbuPPrV+K6MtSII3HBfE0stUIMXUb44L+LK1t6GXPP7wjSzjO6uKg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "json-schema": "^0.4.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/braintrust/node_modules/esbuild": { "version": "0.18.20", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", @@ -3962,12 +4435,16 @@ "node": ">=4" } }, - "node_modules/client-only": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", - "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6" + } }, "node_modules/color": { "version": "4.2.3", @@ -4293,6 +4770,16 @@ "node": ">= 0.8" } }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/destroy": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", @@ -4832,15 +5319,14 @@ } }, "node_modules/esrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/esrap/-/esrap-1.2.3.tgz", - "integrity": "sha512-ZlQmCCK+n7SGoqo7DnfKaP1sJZa49P01/dXzmjCASSo04p72w8EksT2NMK8CEX8DhKsfJXANioIw8VyHNsBfvQ==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/esrap/-/esrap-1.3.2.tgz", + "integrity": "sha512-C4PXusxYhFT98GjLSmb20k9PREuUdporer50dhzGuJu9IJXktbMddVCMLAERl5dAHyAi73GWWCE4FVHGP1794g==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@jridgewell/sourcemap-codec": "^1.4.15", - "@types/estree": "^1.0.1" + "@jridgewell/sourcemap-codec": "^1.4.15" } }, "node_modules/esrecurse": { @@ -5753,14 +6239,6 @@ "node": ">=0.10.0" } }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true, - "license": "MIT", - "peer": true - }, "node_modules/js-yaml": { "version": "3.14.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", @@ -5963,20 +6441,6 @@ "dev": true, "license": "MIT" }, - "node_modules/loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" - }, - "bin": { - "loose-envify": "cli.js" - } - }, "node_modules/lru-cache": { "version": "10.4.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", @@ -5985,9 +6449,9 @@ "license": "ISC" }, "node_modules/magic-string": { - "version": "0.30.14", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.14.tgz", - "integrity": "sha512-5c99P1WKTed11ZC0HMJOj6CDIue6F8ySu+bJL+85q1zBEIY8IklrJ1eiKC2NDRh3Ct3FcvmJPyQHb9erXMTJNw==", + "version": "0.30.17", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", "dev": true, "license": "MIT", "peer": true, @@ -6969,15 +7433,12 @@ } }, "node_modules/react": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", - "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/react/-/react-19.0.0.tgz", + "integrity": "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==", "dev": true, "license": "MIT", "peer": true, - "dependencies": { - "loose-envify": "^1.1.0" - }, "engines": { "node": ">=0.10.0" } @@ -7641,9 +8102,9 @@ } }, "node_modules/svelte": { - "version": "5.10.0", - "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.10.0.tgz", - "integrity": "sha512-jGJFpB9amHLLQZBbAuQ6csH7WlTvGx4cO4wSSNcgGcx9vDGMTCZzTREf6/wKhVUQDoK+GapgvLQPZHa3e9MOAA==", + "version": "5.16.1", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.16.1.tgz", + "integrity": "sha512-FsA1OjAKMAFSDob6j/Tv2ZV9rY4SeqPd1WXQlQkFkePAozSHLp6tbkU9qa1xJ+uTRzMSM2Vx3USdsYZBXd3H3g==", "dev": true, "license": "MIT", "peer": true, @@ -7655,8 +8116,9 @@ "acorn-typescript": "^1.4.13", "aria-query": "^5.3.1", "axobject-query": "^4.1.0", + "clsx": "^2.1.1", "esm-env": "^1.2.1", - "esrap": "^1.2.3", + "esrap": "^1.3.2", "is-reference": "^3.0.3", "locate-character": "^3.0.0", "magic-string": "^0.30.11", @@ -7667,17 +8129,17 @@ } }, "node_modules/swr": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/swr/-/swr-2.2.5.tgz", - "integrity": "sha512-QtxqyclFeAsxEUeZIYmsaQ0UjimSq1RZ9Un7I68/0ClKK/U3LoyQunwkQfJZr2fc22DfIXLNDc2wFyTEikCUpg==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/swr/-/swr-2.3.0.tgz", + "integrity": "sha512-NyZ76wA4yElZWBHzSgEJc28a0u6QZvhb6w0azeL2k7+Q1gAzVK+IqQYXhVOC/mzi+HZIozrZvBVeSeOZNR2bqA==", "dev": true, "license": "MIT", "dependencies": { - "client-only": "^0.0.1", - "use-sync-external-store": "^1.2.0" + "dequal": "^2.0.3", + "use-sync-external-store": "^1.4.0" }, "peerDependencies": { - "react": "^16.11.0 || ^17.0.0 || ^18.0.0" + "react": "^16.11.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "node_modules/swrev": { diff --git a/package.json b/package.json index 9bd4f4ab..e5a5ebfa 100644 --- a/package.json +++ b/package.json @@ -6,11 +6,12 @@ "module": "./dist/index.js", "types": "./dist/index.d.ts", "scripts": { - "popup": "npm run build-dom-scripts && tsx examples/popup.ts", "2048": "npm run build-dom-scripts && tsx examples/2048.ts", + "popup": "npm run build-dom-scripts && tsx examples/popup.ts", "example": "npm run build-dom-scripts && tsx examples/example.ts", "debug-url": "npm run build-dom-scripts && tsx examples/debugUrl.ts", "external-client": "npm run build-dom-scripts && tsx examples/external_client.ts", + "ai-sdk-client": "npm run build-dom-scripts && tsx examples/ai_sdk_example.ts", "format": "prettier --write .", "prettier": "prettier --check .", "prettier:fix": "prettier --write .", @@ -35,6 +36,8 @@ "author": "Browserbase", "license": "MIT", "devDependencies": { + "@ai-sdk/google": "^1.0.13", + "@ai-sdk/openai": "^1.0.14", "@changesets/changelog-github": "^0.5.0", "@changesets/cli": "^2.27.9", "@eslint/js": "^9.16.0", @@ -44,6 +47,7 @@ "@types/node": "^20.11.30", "@types/ws": "^8.5.13", "adm-zip": "^0.5.16", + "ai": "^4.0.26", "autoevals": "^0.0.64", "braintrust": "^0.0.171", "cheerio": "^1.0.0",