近期相关变更
fix(provider): restore Azure Cognitive Services endpoints (#37340) — 修复 Azure 端点配置
chore: generate — SDK 代码重新生成(含 provider 配置更新)
1. 请求流程
架构概览
OpenCode 的 LLM 请求分两条路径:
AI SDK 路径(默认) :通过 @ai-sdk/* npm 包发送请求
Native Route 路径 :仅 OpenAI、Anthropic、opencode 自有 provider 可用,直接使用 packages/llm 的 LLMClient
路径选择在 native-runtime.ts:status() 中判断。
关键步骤
sequenceDiagram
participant Session
participant LLMRequestPrep as session/llm/request.ts
participant NativeRuntime as native-runtime.ts
participant LLMClient as route/client.ts
participant Auth as route/auth.ts
participant Executor as route/executor.ts
participant Provider as LLM Provider
Session->>LLMRequestPrep: prepare() — 构造 headers/params
LLMRequestPrep-->>Session: Prepared{headers, messages, tools...}
Session->>NativeRuntime: stream()/generateText
NativeRuntime->>LLMClient: LLMClient.stream(request)
LLMClient->>LLMClient: compile() → route.body.from() 构造 body
LLMClient->>Auth: route.prepareTransport() → Auth.apply() 注入鉴权 header
Auth-->>LLMClient: Headers (Authorization/x-api-key/SigV4...)
LLMClient->>Executor: RequestExecutor.execute(httpRequest)
Executor->>Provider: POST JSON + headers
Provider-->>Executor: SSE / Event-stream
Executor->>Executor: retryStatusFailures() 自动重试
Executor-->>LLMClient: Stream<LLMEvent>
Loading
#
环节
关键文件 & 函数
1
请求构造
session/llm/request.ts → LLMRequestPrep.prepare()
2
凭据获取
provider/auth.ts → ProviderAuth.Service (OAuth/API key)
3
路径选择
native-runtime.ts → status()
4
消息降格
native-request.ts → LLMNative.from() (AI SDK → LLMRequest)
5
Body 构造
route/client.ts → compile() → route.body.from()
6
Body 验证
route/client.ts → ProviderShared.validateWith()
7
Header 组装
route/transport/http.ts → jsonRequestParts()
8
鉴权注入
route/auth.ts → Auth.apply()
9
HTTP 构造
protocols/shared.ts:322 → jsonPost() 设置 content-type
10
发送&重试
route/executor.ts → retryStatusFailures() (最多 2 次)
11
流解析
各 Protocol 的 stream.step() → LLMEvent[]
2. 请求 Header 明细
通用 Headers
Header
取值来源
说明
content-type
protocols/shared.ts:322
固定 application/json
User-Agent
session/llm/request.ts:21
opencode/<version>
x-session-affinity
session/llm/request.ts:197
会话亲和性路由
X-Session-Id
session/llm/request.ts:198
会话 ID
Anthropic
Header
取值来源
说明
x-api-key
providers/anthropic.ts:14 → Auth.header("x-api-key")
API key;env 回退 ANTHROPIC_API_KEY
anthropic-version
protocols/anthropic-messages.ts:852
固定 2023-06-01
content-type
protocols/shared.ts:322
application/json
OpenAI / OpenAI Compatible
Header
取值来源
说明
Authorization
providers/openai.ts:20 → AuthOptions.bearer()
Bearer <key>;env 回退 OPENAI_API_KEY
content-type
protocols/shared.ts:322
application/json
Azure OpenAI
Header
取值来源
说明
api-key
providers/azure.ts:72 → Auth.header("api-key")
Azure API key;env 回退 AZURE_OPENAI_API_KEY
Authorization
providers/azure.ts:10 → Auth.remove("authorization")
主动移除 ,避免与 api-key 冲突
api-version(URL 参数)
providers/azure.ts:33,81
URL 查询参数,默认 v1
Amazon Bedrock(SigV4)
Header
取值来源
说明
Authorization
protocols/utils/bedrock-auth.ts:27 → AwsV4Signer.sign()
AWS SigV4 签名
x-amz-date
protocols/utils/bedrock-auth.ts → AwsV4Signer.sign()
SigV4 时间戳
x-amz-security-token
protocols/utils/bedrock-auth.ts
STS 临时 token(有 sessionToken 时)
content-type
protocols/utils/bedrock-auth.ts:40
签名前设置,纳入签名范围
Bedrock 也支持 Bearer API key(providers/amazon-bedrock.ts 传入 apiKey 时)。
Google Gemini
Header
取值来源
说明
x-goog-api-key
providers/google.ts:17 → Auth.header("x-goog-api-key")
Google API key;env 回退 GOOGLE_GENERATIVE_AI_API_KEY
URL 动态嵌入模型 ID:/models/${model.id}:streamGenerateContent?alt=sse(protocols/gemini.ts:505)
GitHub Copilot
Header
取值来源
说明
Authorization
providers/github-copilot.ts:40,46 → AuthOptions.bearer()
Bearer <token>;无默认 env var,baseURL 必须外部配置
opencode 自有 Provider
Header
取值来源
说明
x-opencode-project
session/llm/request.ts:190
项目 ID
x-opencode-session
session/llm/request.ts:191
会话 ID
x-opencode-request
session/llm/request.ts:192
请求 ID
x-opencode-client
session/llm/request.ts:193
客户端类型
3. 鉴权机制
Provider
机制
实现位置
Anthropic
x-api-key: <key>
providers/anthropic.ts:14
OpenAI / Compatible
Authorization: Bearer <key>
route/auth-options.ts:bearer()
Azure
api-key: <key>(移除 Authorization)
providers/azure.ts:68-76
Bedrock
AWS SigV4(AwsV4Signer)
protocols/utils/bedrock-auth.ts:sigV4()
Google Gemini
x-goog-api-key: <key>
providers/google.ts:17
GitHub Copilot
Authorization: Bearer <OAuth token>
providers/github-copilot.ts:40
OpenRouter
Authorization: Bearer <key>
providers/openrouter.ts
凭据解析链 (route/auth-options.ts:bearer()):
显式传入 auth → 显式传入 apiKey → Config.redacted(ENV_VAR_NAME) → MissingCredentialError
4. 关键代码位置索引
文件
作用
packages/llm/src/route/client.ts
Route.make() / LLMClient / compile()
packages/llm/src/route/auth.ts
Auth 抽象(bearer/header/custom)
packages/llm/src/route/auth-options.ts
AuthOptions.bearer() 标准解析链
packages/llm/src/route/executor.ts
HTTP 发送 / 错误分类 / 指数退避重试
packages/llm/src/route/transport/http.ts
jsonRequestParts() / httpJson()
packages/llm/src/protocols/shared.ts:322
jsonPost() — 设置 content-type
packages/llm/src/protocols/anthropic-messages.ts:845
Anthropic 路由(anthropic-version header)
packages/llm/src/protocols/openai-chat.ts:497
OpenAI Chat Completions 路由
packages/llm/src/protocols/openai-responses.ts:984
OpenAI Responses API 路由
packages/llm/src/protocols/gemini.ts:500
Gemini 路由(URL 嵌入模型 ID)
packages/llm/src/protocols/bedrock-converse.ts:658
Bedrock Converse 路由
packages/llm/src/protocols/utils/bedrock-auth.ts
AWS SigV4 签名(AwsV4Signer)
packages/opencode/src/session/llm/request.ts
session 级 headers 构造
packages/opencode/src/session/llm/native-request.ts
AI SDK → LLMRequest 降格
packages/opencode/src/session/llm/native-runtime.ts
Native 路径选择与执行
packages/opencode/src/provider/auth.ts
OAuth / API key 凭据管理
5. 重试策略
最大重试 :2 次(executor.ts:MAX_RETRIES)
可重试状态码 :429、503、504、529
退避策略 :优先 retry-after-ms/retry-after header,否则指数退避(基础 500ms,上限 10s,±20% 抖动)
Generated by Daily Upstream Sync + Request-Flow Analysis · 96 AIC · ⌖ 7.04 AIC · ⊞ 5.9K · ◷
近期相关变更
fix(provider): restore Azure Cognitive Services endpoints (#37340)— 修复 Azure 端点配置chore: generate— SDK 代码重新生成(含 provider 配置更新)1. 请求流程
架构概览
OpenCode 的 LLM 请求分两条路径:
@ai-sdk/*npm 包发送请求packages/llm的LLMClient路径选择在
native-runtime.ts:status()中判断。关键步骤
sequenceDiagram participant Session participant LLMRequestPrep as session/llm/request.ts participant NativeRuntime as native-runtime.ts participant LLMClient as route/client.ts participant Auth as route/auth.ts participant Executor as route/executor.ts participant Provider as LLM Provider Session->>LLMRequestPrep: prepare() — 构造 headers/params LLMRequestPrep-->>Session: Prepared{headers, messages, tools...} Session->>NativeRuntime: stream()/generateText NativeRuntime->>LLMClient: LLMClient.stream(request) LLMClient->>LLMClient: compile() → route.body.from() 构造 body LLMClient->>Auth: route.prepareTransport() → Auth.apply() 注入鉴权 header Auth-->>LLMClient: Headers (Authorization/x-api-key/SigV4...) LLMClient->>Executor: RequestExecutor.execute(httpRequest) Executor->>Provider: POST JSON + headers Provider-->>Executor: SSE / Event-stream Executor->>Executor: retryStatusFailures() 自动重试 Executor-->>LLMClient: Stream<LLMEvent>session/llm/request.ts→LLMRequestPrep.prepare()provider/auth.ts→ProviderAuth.Service(OAuth/API key)native-runtime.ts→status()native-request.ts→LLMNative.from()(AI SDK → LLMRequest)route/client.ts→compile()→route.body.from()route/client.ts→ProviderShared.validateWith()route/transport/http.ts→jsonRequestParts()route/auth.ts→Auth.apply()protocols/shared.ts:322→jsonPost()设置 content-typeroute/executor.ts→retryStatusFailures()(最多 2 次)stream.step()→ LLMEvent[]2. 请求 Header 明细
通用 Headers
content-typeprotocols/shared.ts:322application/jsonUser-Agentsession/llm/request.ts:21opencode/<version>x-session-affinitysession/llm/request.ts:197X-Session-Idsession/llm/request.ts:198Anthropic
x-api-keyproviders/anthropic.ts:14→Auth.header("x-api-key")ANTHROPIC_API_KEYanthropic-versionprotocols/anthropic-messages.ts:8522023-06-01content-typeprotocols/shared.ts:322application/jsonOpenAI / OpenAI Compatible
Authorizationproviders/openai.ts:20→AuthOptions.bearer()Bearer <key>;env 回退OPENAI_API_KEYcontent-typeprotocols/shared.ts:322application/jsonAzure OpenAI
api-keyproviders/azure.ts:72→Auth.header("api-key")AZURE_OPENAI_API_KEYAuthorizationproviders/azure.ts:10→Auth.remove("authorization")api-key冲突api-version(URL 参数)providers/azure.ts:33,81v1Amazon Bedrock(SigV4)
Authorizationprotocols/utils/bedrock-auth.ts:27→AwsV4Signer.sign()x-amz-dateprotocols/utils/bedrock-auth.ts→AwsV4Signer.sign()x-amz-security-tokenprotocols/utils/bedrock-auth.tscontent-typeprotocols/utils/bedrock-auth.ts:40Google Gemini
x-goog-api-keyproviders/google.ts:17→Auth.header("x-goog-api-key")GOOGLE_GENERATIVE_AI_API_KEYGitHub Copilot
Authorizationproviders/github-copilot.ts:40,46→AuthOptions.bearer()Bearer <token>;无默认 env var,baseURL 必须外部配置opencode 自有 Provider
x-opencode-projectsession/llm/request.ts:190x-opencode-sessionsession/llm/request.ts:191x-opencode-requestsession/llm/request.ts:192x-opencode-clientsession/llm/request.ts:1933. 鉴权机制
x-api-key: <key>providers/anthropic.ts:14Authorization: Bearer <key>route/auth-options.ts:bearer()api-key: <key>(移除 Authorization)providers/azure.ts:68-76AwsV4Signer)protocols/utils/bedrock-auth.ts:sigV4()x-goog-api-key: <key>providers/google.ts:17Authorization: Bearer <OAuth token>providers/github-copilot.ts:40Authorization: Bearer <key>providers/openrouter.ts凭据解析链(
route/auth-options.ts:bearer()):4. 关键代码位置索引
packages/llm/src/route/client.tsRoute.make()/LLMClient/compile()packages/llm/src/route/auth.tspackages/llm/src/route/auth-options.tsAuthOptions.bearer()标准解析链packages/llm/src/route/executor.tspackages/llm/src/route/transport/http.tsjsonRequestParts()/httpJson()packages/llm/src/protocols/shared.ts:322jsonPost()— 设置 content-typepackages/llm/src/protocols/anthropic-messages.ts:845packages/llm/src/protocols/openai-chat.ts:497packages/llm/src/protocols/openai-responses.ts:984packages/llm/src/protocols/gemini.ts:500packages/llm/src/protocols/bedrock-converse.ts:658packages/llm/src/protocols/utils/bedrock-auth.tsAwsV4Signer)packages/opencode/src/session/llm/request.tspackages/opencode/src/session/llm/native-request.tspackages/opencode/src/session/llm/native-runtime.tspackages/opencode/src/provider/auth.ts5. 重试策略
executor.ts:MAX_RETRIES)429、503、504、529retry-after-ms/retry-afterheader,否则指数退避(基础 500ms,上限 10s,±20% 抖动)