Repository navigation
feat(ai): apiKey: false for keyless providers - #60770
Conversation
There was a problem hiding this comment.
Looks sound. apiKey: false goes through the new shared AuthOptions.apiKey helper. I copied the new keyless test onto the base branch: its four apiKey: false cases fail there (only the omitted-key case passes), and all five pass with this change. The full packages/ai suite passes (2000 pass), and typecheck:tsc is clean in ai and core. No hand-written Auth.optional key lookups remain outside the helper. Vertex and Bedrock keep their own auth, and their types still reject false. The Cloudflare gateway order (gatewayApiKey first, then apiKey) and Azure's removal of authorization both behave correctly.
Public API (@opencode/ai, backwards compatible): apiKey now also accepts false (string → string | false on provider Config/Settings, and on OptionalApiKeyAuth/RequiredApiKeyAuth). AuthOptions.apiKey(options, envVars, apply) and the AuthOptions.ApiKey type are new. AuthOptions.bearer keeps its signature. Existing callers are unaffected.
No blocking concerns.
Related: #42790
Problem
A provider that needs no key (a local server, a gateway that authenticates by header) had no way to say so. Leaving the key out failed with
Missing auth credential: apiKey, and passingapiKey: falsecrashed.Change
apiKey: falsemeans "no key on purpose": no env lookup, no auth header from the package, no error. Omitted or""keeps today's behavior.AuthOptions.apiKey(options, envVars, apply) // new shared helper; bearer() wraps it auth override? -> use it + apiKey === false -> Auth.none else -> apiKey ?? env vars, rendered by applyCovered: every provider on the shared helper (OpenAI, OpenAI-compatible chat/responses, xAI, Groq, DeepSeek, OpenRouter, Vercel AI Gateway, Cloudflare Workers AI, Mistral, Cohere, Alibaba, Moonshot, MiniMax, Z.ai, Meta, Venice, etc.), plus Anthropic and Anthropic-compatible (
x-api-key), Google (x-goog-api-key), Azure (api-key), Cloudflare AI Gateway, ElevenLabs, Deepgram and AssemblyAI. Image, decision and other media routes reuse the same auth, so they honor it too.Out of scope
apiKey: false.Verification
test/keyless-auth.test.tsagainst a localBun.servestub: omitted key still errors;apiKey: falsesucceeds with noAuthorization(chat + image) and nox-api-key(Anthropic); custom header is the only one sent.test/auth-options.types.ts.bun testin packages/ai (2000 pass),bun typecheck+typecheck:tscin ai and core,bun run check.Added by the opencode bot (AI-generated).
Related: #42790
Public API: @opencode/ai: provider apiKey options accept
false; adds AuthOptions.apiKey helper and AuthOptions.ApiKey type (backwards compatible)