diff --git a/.changeset/orcarouter-provider.md b/.changeset/orcarouter-provider.md new file mode 100644 index 0000000000..ce056bdffc --- /dev/null +++ b/.changeset/orcarouter-provider.md @@ -0,0 +1,9 @@ +--- +"@browserbasehq/stagehand": minor +"@browserbasehq/stagehand-extension": minor +"@browserbasehq/stagehand-protocol": minor +"@browserbasehq/stagehand-python": minor +"@browserbasehq/stagehand-go": minor +--- + +feat(providers): add OrcaRouter as a first-class model provider diff --git a/.env.example b/.env.example index a402c75d66..edcd0c2461 100644 --- a/.env.example +++ b/.env.example @@ -1,5 +1,9 @@ OPENAI_API_KEY="" BROWSERBASE_API_KEY="" +# OrcaRouter (OpenAI-compatible gateway): https://www.orcarouter.ai +# Use model names like "orcarouter/auto" with an ORCAROUTER_API_KEY. +# ORCAROUTER_API_KEY="sk-orca-..." + # Optional: set this only if Chrome cannot be detected automatically. # CHROME_PATH="" diff --git a/packages/docs/v4/configuration/models.mdx b/packages/docs/v4/configuration/models.mdx index 4a6cb4bb82..79348ddf7c 100644 --- a/packages/docs/v4/configuration/models.mdx +++ b/packages/docs/v4/configuration/models.mdx @@ -328,7 +328,7 @@ defer func() { err = errors.Join(err, client.Close(ctx)) }() -Model names for the providers below carry a `provider/` prefix, and the provider must be one of the five. Stagehand ships a list of known model IDs per provider and validates the full name when you call `Stagehand.create()` or pass a per-call override, so a name it does not recognize fails before any request reaches the provider. Upgrade the SDK to pick up newly released models. The prefix is never optional: to reach an Azure OpenAI deployment, a self-hosted model, or anything else outside those five providers, use the [bring-your-own-LLM callback](#custom-models). +Model names for the providers below carry a `provider/` prefix, and the provider must be one of the first-class providers listed on this page. Stagehand ships a list of known model IDs per provider and validates the full name when you call `Stagehand.create()` or pass a per-call override, so a name it does not recognize fails before any request reaches the provider. Upgrade the SDK to pick up newly released models. The prefix is never optional: to reach an Azure OpenAI deployment, a self-hosted model, or anything else outside those first-class providers, use the [bring-your-own-LLM callback](#custom-models). @@ -668,6 +668,74 @@ Commonly used: `cerebras/gpt-oss-120b`, `cerebras/qwen-3-235b-a22b-instruct-2507 [View all supported Cerebras models →](https://inference-docs.cerebras.ai/models/overview) + + + + +```typescript +import { browserbase, Stagehand } from "@browserbasehq/stagehand"; + +const stagehand = await Stagehand.create({ + browser: await browserbase.launch({ apiKey: process.env.BROWSERBASE_API_KEY }), + model: { + modelName: "orcarouter/auto", + apiKey: process.env.ORCAROUTER_API_KEY, + }, +}); +``` + + + +```python +import os + +from stagehand import Stagehand, browserbase + +browser = await browserbase.launch(api_key=os.environ["BROWSERBASE_API_KEY"]) + +stagehand = await Stagehand.create( + browser=browser, + model="orcarouter/auto", + model_api_key=os.environ["ORCAROUTER_API_KEY"], +) +``` + + + +```go +apiKey := os.Getenv("BROWSERBASE_API_KEY") +modelAPIKey := os.Getenv("ORCAROUTER_API_KEY") +model := stagehand.ModelConfig{ + ModelName: "orcarouter/auto", + APIKey: &modelAPIKey, +} + +browser, err := stagehand.LaunchBrowserbase(ctx, stagehand.BrowserbaseLaunchOptions{ + APIKey: apiKey, +}) +if err != nil { + return err +} + +client, err := stagehand.Create(ctx, stagehand.CreateOptions{ + Browser: browser, + Model: &model, +}) +if err != nil { + return err +} +defer func() { err = errors.Join(err, client.Close(ctx)) }() +``` + + + +[OrcaRouter](https://www.orcarouter.ai) is an OpenAI-compatible gateway that fronts hundreds of frontier and open-weight models behind a single `sk-orca-` key. Use a gateway routing alias like `orcarouter/auto` or a vendor-prefixed model like `orcarouter/deepseek/deepseek-v4-pro`. It also runs gateway-level, zero-trust security for AI agents on the same endpoint — screening every prompt/response and governing every tool call on a default-deny basis, with no application code changes. + +Commonly used: `orcarouter/auto`, `orcarouter/fusion`, `orcarouter/fusion-flash`, `orcarouter/fusion-mini`, `orcarouter/deepseek/deepseek-v4-pro`. + +[View all supported OrcaRouter models →](https://www.orcarouter.ai) + + --- @@ -1570,7 +1638,7 @@ defer func() { err = errors.Join(err, client.Close(ctx)) }() -There is no base URL option. A model configuration always names one of the five supported providers, so Azure OpenAI deployments, self-hosted models, and any other custom endpoint go through the [bring-your-own-LLM callback](#custom-models) instead, where you own the client, the transport, and the credentials. +There is no base URL option. A model configuration always names one of the first-class providers, so Azure OpenAI deployments, self-hosted models, and any other custom endpoint go through the [bring-your-own-LLM callback](#custom-models) instead, where you own the client, the transport, and the credentials. --- @@ -1746,6 +1814,7 @@ You pinned a `model` but gave it no `apiKey`, and the browser is not a Browserba | OpenAI | `OPENAI_API_KEY` | | Groq | `GROQ_API_KEY` | | Cerebras | `CEREBRAS_API_KEY` | +| OrcaRouter | `ORCAROUTER_API_KEY` | | Bring your own LLM | None; your callback owns its credentials | @@ -1756,7 +1825,7 @@ You pinned a `model` but gave it no `apiKey`, and the browser is not a Browserba **Solutions:** - Use the `provider/model` format: `openai/gpt-5`. The prefix is required; bare model names are rejected -- Use one of the five supported providers: `openai`, `anthropic`, `google`, `groq`, `cerebras` +- Use one of the first-class providers: `openai`, `anthropic`, `google`, `groq`, `cerebras`, `orcarouter` - Check the model ID against the lists on this page. Stagehand validates the whole name, so a typo fails at `Stagehand.create()` rather than on the first inference - Upgrade the SDK if the model shipped after your installed version - For a provider outside that list, use the [bring-your-own-LLM callback](#custom-models) diff --git a/packages/evals/initStagehand.ts b/packages/evals/initStagehand.ts index dd7d60faa5..cd143063ff 100644 --- a/packages/evals/initStagehand.ts +++ b/packages/evals/initStagehand.ts @@ -35,6 +35,7 @@ const PROVIDER_API_KEY_ENV: Record = { google: ["GOOGLE_GENERATIVE_AI_API_KEY", "GEMINI_API_KEY"], groq: ["GROQ_API_KEY"], cerebras: ["CEREBRAS_API_KEY"], + orcarouter: ["ORCAROUTER_API_KEY"], }; type StagehandLogEvent = Parameters>[0]; diff --git a/packages/evals/tests/tui/welcomeStatus.test.ts b/packages/evals/tests/tui/welcomeStatus.test.ts index b94a58b328..e8d2f90e55 100644 --- a/packages/evals/tests/tui/welcomeStatus.test.ts +++ b/packages/evals/tests/tui/welcomeStatus.test.ts @@ -16,6 +16,7 @@ const PROVIDER_KEYS = [ "BB_API_KEY", "BB_PROJECT_ID", "BRAINTRUST_API_KEY", + "ORCAROUTER_API_KEY", ]; const savedEnv: Record = {}; @@ -160,6 +161,12 @@ describe("hasZeroProviderKeys", () => { __resetPackageEnvCacheForTests(); expect(hasZeroProviderKeys(snapshotEnv())).toBe(false); }); + + it("false with only OrcaRouter set", () => { + process.env.ORCAROUTER_API_KEY = "sk-orca-test"; + __resetPackageEnvCacheForTests(); + expect(hasZeroProviderKeys(snapshotEnv())).toBe(false); + }); }); describe("renderInlineWarning", () => { diff --git a/packages/evals/tui/welcomeStatus.ts b/packages/evals/tui/welcomeStatus.ts index 1e49466778..16bfad501d 100644 --- a/packages/evals/tui/welcomeStatus.ts +++ b/packages/evals/tui/welcomeStatus.ts @@ -45,6 +45,7 @@ export type EnvSnapshot = { google: GoogleKeyEntry; browserbase: BrowserbaseKeyEntry; braintrust: ProviderKeyEntry; + orcarouter: ProviderKeyEntry; }; // --------------------------------------------------------------------------- @@ -166,6 +167,7 @@ export function snapshotEnv(): EnvSnapshot { google: googleEntry(), browserbase: browserbaseEntry(), braintrust: providerEntry("BRAINTRUST_API_KEY"), + orcarouter: providerEntry("ORCAROUTER_API_KEY"), }; } @@ -177,7 +179,10 @@ export function snapshotEnv(): EnvSnapshot { export function hasZeroProviderKeys(s: EnvSnapshot): boolean { return ( - s.openai.state === "missing" && s.anthropic.state === "missing" && s.google.state === "missing" + s.openai.state === "missing" && + s.anthropic.state === "missing" && + s.google.state === "missing" && + s.orcarouter.state === "missing" ); } diff --git a/packages/extension/llm/LLMProvider.ts b/packages/extension/llm/LLMProvider.ts index 34d1214eca..684383f0e3 100644 --- a/packages/extension/llm/LLMProvider.ts +++ b/packages/extension/llm/LLMProvider.ts @@ -21,6 +21,15 @@ const AISDKProviderFactories: Record = { google: createGoogleGenerativeAI as AISDKProviderFactory, groq: createGroq as AISDKProviderFactory, cerebras: createCerebras as AISDKProviderFactory, + // OrcaRouter is an OpenAI-compatible gateway; the createOpenAI factory talks + // to it once baseURL points at the gateway. + orcarouter: createOpenAI as AISDKProviderFactory, +}; + +// Default base URL for each OpenAI-compatible gateway provider, applied when the +// caller does not set one explicitly. +const DEFAULT_BASE_URL: Partial> = { + orcarouter: "https://api.orcarouter.ai/v1", }; type AISDKProviderClientOptions = ClientOptions & Record; @@ -30,7 +39,7 @@ function parseClientOptions(clientOptions?: ClientOptions): ClientOptions { } export function toAISDKClientOptions( - _subProvider: ModelProvider, + subProvider: ModelProvider, clientOptions?: ClientOptions, ): AISDKProviderClientOptions | undefined { const { auth, providerOptions: _providerOptions, ...rest } = parseClientOptions(clientOptions); @@ -41,6 +50,12 @@ export function toAISDKClientOptions( ...apiKeyOption, }; + // OpenAI-compatible gateways route through the Responses API; give them a + // sensible base URL when the caller did not pin one. + if (DEFAULT_BASE_URL[subProvider] && !options.baseURL) { + options.baseURL = DEFAULT_BASE_URL[subProvider]; + } + return Object.values(options).some((value) => value !== undefined && value !== null) ? options : undefined; @@ -63,7 +78,12 @@ export function getAISDKLanguageModel( const model = subProvider === "openai" ? (provider as ReturnType).responses(subModelName) - : provider(subModelName); + : subProvider === "orcarouter" + ? // OrcaRouter routes on the full gateway-qualified model name + // (`orcarouter/fusion`, `orcarouter/deepseek/deepseek-v4-pro`), so + // send the complete model name rather than the stripped suffix. + (provider as ReturnType).responses(`orcarouter/${subModelName}`) + : provider(subModelName); if (middleware) { return wrapLanguageModel({ model: model as never, middleware }); diff --git a/packages/extension/llm/aiSdkClient.ts b/packages/extension/llm/aiSdkClient.ts index 720884301b..5a6d839b04 100644 --- a/packages/extension/llm/aiSdkClient.ts +++ b/packages/extension/llm/aiSdkClient.ts @@ -17,6 +17,7 @@ import { LLMGenerateResultSchema, ModelProviderSchema, OpenAIModelIdSchema, + OrcaRouterModelNameSchema, } from "../../protocol/schemas.js"; import type { LLMGenerateParams, LLMGenerateResult, ModelConfig } from "../../protocol/types.js"; @@ -163,6 +164,18 @@ export function createAiSdkLanguageModel( return createGroq(connection)(GroqModelIdSchema.parse(modelId)); case "cerebras": return createCerebras(connection)(CerebrasModelIdSchema.parse(modelId)); + case "orcarouter": { + const orcaRouter = createOpenAI({ + ...connection, + baseURL: "https://api.orcarouter.ai/v1", + }); + // OrcaRouter routes on the full gateway-qualified model name + // (`orcarouter/fusion`), so re-attach the provider prefix. + const orcaRouterModelName = OrcaRouterModelNameSchema.parse(config.modelName); + return params?.stopSequences?.length + ? orcaRouter.chat(orcaRouterModelName) + : orcaRouter.responses(orcaRouterModelName); + } } } diff --git a/packages/extension/llm/aisdk.ts b/packages/extension/llm/aisdk.ts index 50a78c215e..2f978c0855 100644 --- a/packages/extension/llm/aisdk.ts +++ b/packages/extension/llm/aisdk.ts @@ -191,6 +191,14 @@ export class AISdkClient extends LLMClient { strictJsonSchema: true, }; break; + case "orcarouter": + // OrcaRouter is an OpenAI-compatible gateway served through the + // createOpenAI factory, so its provider options ride under the openai + // key and the Responses API applies strict JSON schema. + providerOptions.openai = { + strictJsonSchema: true, + }; + break; case "mistral": providerOptions.mistral = { structuredOutputs: true, diff --git a/packages/extension/tests/ai-sdk-client.test.ts b/packages/extension/tests/ai-sdk-client.test.ts index b5590d80a4..14a3da7e6b 100644 --- a/packages/extension/tests/ai-sdk-client.test.ts +++ b/packages/extension/tests/ai-sdk-client.test.ts @@ -47,6 +47,12 @@ describe("AI SDK language models", () => { modelId: "gpt-oss-120b", provider: "cerebras.chat", }, + { + name: "OrcaRouter", + modelName: "orcarouter/auto" as const, + modelId: "orcarouter/auto", + provider: "openai.responses", + }, ])("creates a direct $name model from its validated configuration", (testCase) => { const model = createAiSdkLanguageModel({ modelName: testCase.modelName, @@ -75,6 +81,21 @@ describe("AI SDK language models", () => { }); }); + it("uses Chat Completions for OrcaRouter requests with stop sequences", () => { + const model = createAiSdkLanguageModel( + { + modelName: "orcarouter/fusion", + apiKey: "provider-secret", + }, + { stopSequences: ["STOP"] }, + ); + + expect(model).toMatchObject({ + provider: "openai.chat", + modelId: "orcarouter/fusion", + }); + }); + it("routes a configured provider model through the AI SDK client", async () => { vi.mocked(generateText).mockResolvedValue({ text: "Four", diff --git a/packages/extension/tests/model-resolution.test.ts b/packages/extension/tests/model-resolution.test.ts index 56ae23d69a..ddc8bfb942 100644 --- a/packages/extension/tests/model-resolution.test.ts +++ b/packages/extension/tests/model-resolution.test.ts @@ -7,6 +7,7 @@ import { ModelConfigSchema, ModelNameSchema, OpenAIModelIdSchema, + OrcaRouterModelIdSchema, } from "../../protocol/schemas.js"; import type { StagehandInitParams, StagehandResultMetadata } from "../../protocol/types.js"; import { createStagehandController } from "../controllers/stagehandController.js"; @@ -64,6 +65,7 @@ describe("model configuration", () => { ["google", GoogleModelIdSchema.options], ["groq", GroqModelIdSchema.options], ["cerebras", CerebrasModelIdSchema.options], + ["orcarouter", OrcaRouterModelIdSchema.options], ] as const; for (const [provider, modelIds] of providers) { @@ -77,6 +79,11 @@ describe("model configuration", () => { expect(ModelNameSchema.safeParse("groq/openai/gpt-oss-120b").success).toBe(true); }); + it("accepts an OrcaRouter gateway alias and a vendor-prefixed model", () => { + expect(ModelNameSchema.safeParse("orcarouter/auto").success).toBe(true); + expect(ModelNameSchema.safeParse("orcarouter/deepseek/deepseek-v4-pro").success).toBe(true); + }); + it("rejects a model from an unsupported provider", () => { expect(ModelNameSchema.safeParse("bedrock/anthropic.claude-sonnet-v1:0").success).toBe(false); }); diff --git a/packages/integrations/core/src/facade/config.ts b/packages/integrations/core/src/facade/config.ts index 14c5ab9a57..d0ba6c5b91 100644 --- a/packages/integrations/core/src/facade/config.ts +++ b/packages/integrations/core/src/facade/config.ts @@ -109,6 +109,8 @@ function providerApiKey(provider: string | undefined, env: NodeJS.ProcessEnv): s return nonEmpty(env.GROQ_API_KEY); case "cerebras": return nonEmpty(env.CEREBRAS_API_KEY); + case "orcarouter": + return nonEmpty(env.ORCAROUTER_API_KEY); default: return undefined; } diff --git a/packages/integrations/core/tests/facade-contract.test.ts b/packages/integrations/core/tests/facade-contract.test.ts index 20bc0829db..38df274b33 100644 --- a/packages/integrations/core/tests/facade-contract.test.ts +++ b/packages/integrations/core/tests/facade-contract.test.ts @@ -104,4 +104,25 @@ describe("Stagehand facade contract", () => { }).success, ).toBe(false); }); + + it("resolves an OrcaRouter model key from STAGEHAND_MODEL_NAME", () => { + const config = stagehandFacadeConfigFromEnv({ + BROWSERBASE_API_KEY: "bb-test", + STAGEHAND_MODEL_NAME: "orcarouter/auto", + ORCAROUTER_API_KEY: "sk-orca-test", + }); + expect(config.stagehand.model).toMatchObject({ + modelName: "orcarouter/auto", + apiKey: "sk-orca-test", + }); + }); + + it("rejects an unsupported OrcaRouter model name", () => { + expect(() => + stagehandFacadeConfigFromEnv({ + BROWSERBASE_API_KEY: "bb-test", + STAGEHAND_MODEL_NAME: "orcarouter/not-a-real-model", + }), + ).toThrow(/Unsupported STAGEHAND_MODEL_NAME/); + }); }); diff --git a/packages/protocol/schemas.ts b/packages/protocol/schemas.ts index d528aaf320..a08ac734eb 100644 --- a/packages/protocol/schemas.ts +++ b/packages/protocol/schemas.ts @@ -179,8 +179,38 @@ export const CerebrasModelIdSchema = z ]) .meta({ id: "CerebrasModelId" }); +// OrcaRouter is an OpenAI-compatible gateway that fronts hundreds of models +// (frontier + open weights) behind a single `sk-orca-` key. The gateway's own +// routing aliases live under the `orcarouter/` prefix; upstream models exposed +// by https://api.orcarouter.ai/v1/models are addressable by their vendor name. +// Like Groq, model IDs may themselves contain slashes, so `orcarouter/auto` +// and `orcarouter/deepseek/deepseek-v4-pro` are both valid full model names. +export const OrcaRouterModelIdSchema = z + .enum([ + "auto", + "free", + "fusion", + "fusion-flash", + "fusion-mini", + "open-code", + "code-review", + "deepseek/deepseek-v4-flash", + "deepseek/deepseek-v4-pro", + "openai/gpt-5.6-luna", + "openai/gpt-5.6-sol", + "openai/gpt-5.6-terra", + "anthropic/claude-sonnet-5", + "anthropic/claude-fable-5", + "anthropic/claude-haiku-4.5", + "google/gemini-3.1-flash-lite", + "google/gemini-3.6-flash", + "qwen/qwen3.6-flash", + "qwen/qwen3.8-27b", + ]) + .meta({ id: "OrcaRouterModelId" }); + export const ModelProviderSchema = z - .enum(["openai", "anthropic", "google", "groq", "cerebras"]) + .enum(["openai", "anthropic", "google", "groq", "cerebras", "orcarouter"]) .meta({ id: "ModelProvider" }); export const OpenAIModelNameSchema = z @@ -198,6 +228,9 @@ export const GroqModelNameSchema = z export const CerebrasModelNameSchema = z .templateLiteral(["cerebras/", CerebrasModelIdSchema]) .meta({ id: "CerebrasModelName" }); +export const OrcaRouterModelNameSchema = z + .templateLiteral(["orcarouter/", OrcaRouterModelIdSchema]) + .meta({ id: "OrcaRouterModelName" }); export const ModelNameSchema = z .union([ @@ -206,6 +239,7 @@ export const ModelNameSchema = z GoogleModelNameSchema, GroqModelNameSchema, CerebrasModelNameSchema, + OrcaRouterModelNameSchema, ]) .meta({ id: "ModelName", diff --git a/packages/protocol/stagehand.v4.json b/packages/protocol/stagehand.v4.json index 277938c331..23d0f8d085 100644 --- a/packages/protocol/stagehand.v4.json +++ b/packages/protocol/stagehand.v4.json @@ -1300,6 +1300,10 @@ "type": "string", "pattern": "^cerebras\\/(llama3\\.1-8b|gpt-oss-120b|qwen-3-235b-a22b-instruct-2507|qwen-3-235b-a22b-thinking-2507|zai-glm-4\\.6|zai-glm-4\\.7)$" }, + "OrcaRouterModelName": { + "type": "string", + "pattern": "^orcarouter\\/(auto|free|fusion|fusion-flash|fusion-mini|open-code|code-review|deepseek\\/deepseek-v4-flash|deepseek\\/deepseek-v4-pro|openai\\/gpt-5\\.6-luna|openai\\/gpt-5\\.6-sol|openai\\/gpt-5\\.6-terra|anthropic\\/claude-sonnet-5|anthropic\\/claude-fable-5|anthropic\\/claude-haiku-4\\.5|google\\/gemini-3\\.1-flash-lite|google\\/gemini-3\\.6-flash|qwen\\/qwen3\\.6-flash|qwen\\/qwen3\\.8-27b)$" + }, "ModelName": { "anyOf": [ { @@ -1316,6 +1320,9 @@ }, { "$ref": "#/$defs/CerebrasModelName" + }, + { + "$ref": "#/$defs/OrcaRouterModelName" } ], "description": "An explicitly supported model name with its provider prefix" diff --git a/packages/protocol/types.ts b/packages/protocol/types.ts index a03658f7a2..ac53692926 100644 --- a/packages/protocol/types.ts +++ b/packages/protocol/types.ts @@ -218,6 +218,8 @@ import type { ThinkingEffortSchema, OpenAIModelIdSchema, OpenAIModelNameSchema, + OrcaRouterModelIdSchema, + OrcaRouterModelNameSchema, VariablePrimitiveSchema, VariablesSchema, VariableValueSchema, @@ -256,11 +258,13 @@ export type AnthropicModelId = z.infer; export type GoogleModelId = z.infer; export type GroqModelId = z.infer; export type CerebrasModelId = z.infer; +export type OrcaRouterModelId = z.infer; export type OpenAIModelName = z.infer; export type AnthropicModelName = z.infer; export type GoogleModelName = z.infer; export type GroqModelName = z.infer; export type CerebrasModelName = z.infer; +export type OrcaRouterModelName = z.infer; export type ModelConfig = z.infer; export type ModelName = z.infer; export type ModelProvider = z.infer; diff --git a/packages/sdk-go/internal/extensionassets/stagehand-extension.zip b/packages/sdk-go/internal/extensionassets/stagehand-extension.zip index c4f5890ddf..4615afc69d 100644 Binary files a/packages/sdk-go/internal/extensionassets/stagehand-extension.zip and b/packages/sdk-go/internal/extensionassets/stagehand-extension.zip differ diff --git a/packages/sdk-go/models.gen.go b/packages/sdk-go/models.gen.go index b1996ca9e4..65d2878721 100644 --- a/packages/sdk-go/models.gen.go +++ b/packages/sdk-go/models.gen.go @@ -1196,6 +1196,8 @@ type ObserveResult struct { type OpenAIModelName string +type OrcaRouterModelName string + type PageAddInitScriptParams struct { // PageID corresponds to the JSON schema field "page_id". PageID string `json:"page_id"` @@ -2549,6 +2551,9 @@ type generatedModelCatalog struct { // OpenAIModelName corresponds to the JSON schema field "OpenAIModelName". OpenAIModelName *OpenAIModelName `json:"OpenAIModelName,omitempty,omitzero"` + // OrcaRouterModelName corresponds to the JSON schema field "OrcaRouterModelName". + OrcaRouterModelName *OrcaRouterModelName `json:"OrcaRouterModelName,omitempty,omitzero"` + // PageAddInitScriptParams corresponds to the JSON schema field // "PageAddInitScriptParams". PageAddInitScriptParams *PageAddInitScriptParams `json:"PageAddInitScriptParams,omitempty,omitzero"` diff --git a/packages/sdk-python/src/stagehand/_generated/input_types.py b/packages/sdk-python/src/stagehand/_generated/input_types.py index f3cbb05be2..af273c6a9b 100644 --- a/packages/sdk-python/src/stagehand/_generated/input_types.py +++ b/packages/sdk-python/src/stagehand/_generated/input_types.py @@ -652,7 +652,10 @@ class NavigationServerAddr(TypedDict): OpenAIModelName: TypeAlias = str -ModelName: TypeAlias = OpenAIModelName | AnthropicModelName | GoogleModelName | GroqModelName | CerebrasModelName +OrcaRouterModelName: TypeAlias = str + + +ModelName: TypeAlias = OpenAIModelName | AnthropicModelName | GoogleModelName | GroqModelName | CerebrasModelName | OrcaRouterModelName class ModelConfig(TypedDict): diff --git a/packages/sdk-python/src/stagehand/_generated/models.py b/packages/sdk-python/src/stagehand/_generated/models.py index b0a81ef0c2..e4d669ce20 100644 --- a/packages/sdk-python/src/stagehand/_generated/models.py +++ b/packages/sdk-python/src/stagehand/_generated/models.py @@ -1446,13 +1446,6 @@ class OpenAIModelName(RootModel[StrictStr]): ] -class ModelName( - RootModel[Union[OpenAIModelName, AnthropicModelName, GoogleModelName, GroqModelName, CerebrasModelName]] -): - root: Union[OpenAIModelName, AnthropicModelName, GoogleModelName, GroqModelName, CerebrasModelName] - """An explicitly supported model name with its provider prefix""" - - class OperatingSystem(StrEnum): android = "android" ios = "ios" @@ -1461,6 +1454,22 @@ class OperatingSystem(StrEnum): windows = "windows" +class OrcaRouterModelName(RootModel[StrictStr]): + root: Annotated[ + StrictStr, + Field( + pattern="^orcarouter\\/(auto|free|fusion|fusion-flash|fusion-mini|open-code|code-review|deepseek\\/deepseek-v4-flash|deepseek\\/deepseek-v4-pro|openai\\/gpt-5\\.6-luna|openai\\/gpt-5\\.6-sol|openai\\/gpt-5\\.6-terra|anthropic\\/claude-sonnet-5|anthropic\\/claude-fable-5|anthropic\\/claude-haiku-4\\.5|google\\/gemini-3\\.1-flash-lite|google\\/gemini-3\\.6-flash|qwen\\/qwen3\\.6-flash|qwen\\/qwen3\\.8-27b)$" + ), + ] + + +class ModelName( + RootModel[Union[OpenAIModelName, AnthropicModelName, GoogleModelName, GroqModelName, CerebrasModelName, OrcaRouterModelName]] +): + root: Union[OpenAIModelName, AnthropicModelName, GoogleModelName, GroqModelName, CerebrasModelName, OrcaRouterModelName] + """An explicitly supported model name with its provider prefix""" + + class Os(StrEnum): windows = "windows" mac = "mac"