diff --git a/.changeset/aisdk-allow-system-in-messages.md b/.changeset/aisdk-allow-system-in-messages.md new file mode 100644 index 000000000..faff01006 --- /dev/null +++ b/.changeset/aisdk-allow-system-in-messages.md @@ -0,0 +1,7 @@ +--- +"@browserbasehq/stagehand": patch +--- + +Silence the AI SDK "System messages in the prompt or messages fields can be a security risk" warning emitted on every hybrid/DOM `agent.execute()` call. + +The agent loop intentionally supplies its system prompt as a system-role message (rather than the top-level `system` param) so it can carry Anthropic ephemeral cache-control via `providerOptions`. AI SDK v5 warns whenever it sees a system message inside `messages`, since it can't tell a trusted system prompt from untrusted input. Because the prompt is Stagehand's own, we now pass `allowSystemInMessages: true` to the `generateText`/`streamText` calls, which keeps prompt caching intact and removes the noisy warning. Bumps the `ai` floor to `^5.0.185`, where this option is available. diff --git a/packages/core/lib/v3/handlers/v3AgentHandler.ts b/packages/core/lib/v3/handlers/v3AgentHandler.ts index e85acf78c..3d19745f3 100644 --- a/packages/core/lib/v3/handlers/v3AgentHandler.ts +++ b/packages/core/lib/v3/handlers/v3AgentHandler.ts @@ -458,6 +458,7 @@ export class V3AgentHandler { const result = await this.llmClient.generateText({ model: wrappedModel, messages: prependSystemMessage(systemPrompt, messages), + allowSystemInMessages: true, tools: allTools, stopWhen: (result) => this.handleStop(result, maxSteps), toolChoice: "auto", @@ -616,6 +617,7 @@ export class V3AgentHandler { streamResult = this.llmClient.streamText({ model: wrappedModel, messages: prependSystemMessage(systemPrompt, messages), + allowSystemInMessages: true, tools: allTools, stopWhen: (result) => this.handleStop(result, maxSteps), toolChoice: "auto", diff --git a/packages/core/lib/v3/llm/LLMProvider.ts b/packages/core/lib/v3/llm/LLMProvider.ts index a3d9ae582..4f10e31f5 100644 --- a/packages/core/lib/v3/llm/LLMProvider.ts +++ b/packages/core/lib/v3/llm/LLMProvider.ts @@ -1,4 +1,7 @@ -import type { LanguageModelV2Middleware } from "@ai-sdk/provider"; +import type { + LanguageModelV2, + LanguageModelV2Middleware, +} from "@ai-sdk/provider"; import { UnsupportedAISDKModelProviderError, UnsupportedModelError, @@ -156,7 +159,7 @@ export function getAISDKLanguageModel( subModelName: string, clientOptions?: ClientOptions, middleware?: LanguageModelV2Middleware, -) { +): LanguageModelV2 { const aiSdkClientOptions = toAISDKClientOptions(subProvider, clientOptions); const hasValidOptions = aiSdkClientOptions && diff --git a/packages/core/package.json b/packages/core/package.json index 9e55fe0df..73ec2fd9c 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -89,7 +89,7 @@ "@browserbasehq/sdk": "^2.10.0", "@google/genai": "^1.22.0", "@modelcontextprotocol/sdk": "^1.29.0", - "ai": "^5.0.133", + "ai": "^5.0.185", "devtools-protocol": "^0.0.1642743", "fetch-cookie": "^3.1.0", "openai": "^4.104.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ad9fd6318..eb8c07ac8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -187,8 +187,8 @@ importers: specifier: ^1.29.0 version: 1.29.0(@cfworker/json-schema@4.1.1)(zod@4.2.1) ai: - specifier: ^5.0.133 - version: 5.0.133(zod@4.2.1) + specifier: ^5.0.185 + version: 5.0.209(zod@4.2.1) devtools-protocol: specifier: ^0.0.1642743 version: 0.0.1642743 @@ -514,6 +514,12 @@ packages: peerDependencies: zod: ^3.25.76 || ^4.1.8 + '@ai-sdk/gateway@2.0.108': + resolution: {integrity: sha512-86SG+gvko20aD6aM2Z4Mx8rEJYHpC2E2QrrEQzerXkEtruMWJCKwFfeaOKDLn8axN18Lln+HvYbS6cOiRA1J0g==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + '@ai-sdk/gateway@2.0.39': resolution: {integrity: sha512-ULnefGmRHG0/tRrf+dtDwgQYAttGi/TR0FmASAzTs1dtpeZp4Xoh1VyWrX3Z1bM3WDs9RM3ZeSE77kQT/jbfjw==} engines: {node: '>=18'} @@ -604,6 +610,12 @@ packages: peerDependencies: zod: ^3.25.76 || ^4.1.8 + '@ai-sdk/provider-utils@3.0.28': + resolution: {integrity: sha512-bXlX1WX7E50a2N+AJW+1a/x63m52aPhm+6xYe5THxWrx9vW9NR7E2Ay+1G1ndlCdMdYKo2Fnsd7kBhuyQPaphw==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + '@ai-sdk/provider@1.1.3': resolution: {integrity: sha512-qZMxYJ0qqX/RfnuIaab+zp8UAeJn/ygXXAffR5I4N0n1IrvA6qBsjc8hXLmBiMV2zoXlifkacF7sEFnYnjBcqg==} engines: {node: '>=18'} @@ -2930,6 +2942,12 @@ packages: peerDependencies: zod: ^3.25.76 || ^4.1.8 + ai@5.0.209: + resolution: {integrity: sha512-M5iPINrFG/7fJamY4ibnuj+/1e8g3zMJj7f0EEoq25LTlgmqJqeVsRz2u7x7X4E+KvJuOWIJFAcwHVb6Nr9UfA==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + ajv-draft-04@1.0.0: resolution: {integrity: sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==} peerDependencies: @@ -7582,6 +7600,13 @@ snapshots: zod: 4.2.1 optional: true + '@ai-sdk/gateway@2.0.108(zod@4.2.1)': + dependencies: + '@ai-sdk/provider': 2.0.3 + '@ai-sdk/provider-utils': 3.0.28(zod@4.2.1) + '@vercel/oidc': 3.1.0 + zod: 4.2.1 + '@ai-sdk/gateway@2.0.39(zod@4.2.1)': dependencies: '@ai-sdk/provider': 2.0.1 @@ -7696,6 +7721,13 @@ snapshots: zod: 4.2.1 optional: true + '@ai-sdk/provider-utils@3.0.28(zod@4.2.1)': + dependencies: + '@ai-sdk/provider': 2.0.3 + '@standard-schema/spec': 1.1.0 + eventsource-parser: 3.1.0 + zod: 4.2.1 + '@ai-sdk/provider@1.1.3': dependencies: json-schema: 0.4.0 @@ -7712,7 +7744,6 @@ snapshots: '@ai-sdk/provider@2.0.3': dependencies: json-schema: 0.4.0 - optional: true '@ai-sdk/togetherai@1.0.23(zod@4.2.1)': dependencies: @@ -10765,6 +10796,14 @@ snapshots: '@opentelemetry/api': 1.9.0 zod: 4.2.1 + ai@5.0.209(zod@4.2.1): + dependencies: + '@ai-sdk/gateway': 2.0.108(zod@4.2.1) + '@ai-sdk/provider': 2.0.3 + '@ai-sdk/provider-utils': 3.0.28(zod@4.2.1) + '@opentelemetry/api': 1.9.0 + zod: 4.2.1 + ajv-draft-04@1.0.0(ajv@8.20.0): optionalDependencies: ajv: 8.20.0 @@ -12076,8 +12115,7 @@ snapshots: eventsource-parser@3.0.6: {} - eventsource-parser@3.1.0: - optional: true + eventsource-parser@3.1.0: {} eventsource@3.0.7: dependencies: