近期变更
近期同步 upstream 的相关提交(不影响 Header 结构,主要是请求体构造层面):
20589d6 fix(provider): preserve Mistral reasoning history
fada1a5 fix(provider): serialize Mistral prompt cache keys
542ba88 fix(provider): select prompt cache keys by SDK
一、请求流程
分层架构
会话编排层 :opencode/src/session/llm.ts — 决定走 Native runtime 还是 AI SDK path
降级适配层 :session/llm/native-request.ts — ModelMessage[] → LLMRequest
核心执行层 :@opencode-ai/llm(packages/llm/src/)
请求时序
sequenceDiagram
participant Session as session/llm.ts
participant LLMClient as route/client.ts (LLMClient)
participant Protocol as Protocol.body.from
participant Transport as HttpTransport
participant Auth as Auth.apply
participant Executor as RequestExecutor
participant Provider as LLM Provider
Session->>LLMClient: LLMClient.stream(llmRequest)
LLMClient->>LLMClient: compile() — 合并 route/model/request defaults + applyCachePolicy
LLMClient->>Protocol: route.body.from(resolved) — 构造 provider-native body
LLMClient->>Transport: route.prepareTransport(body, resolved)
Transport->>Transport: renderEndpoint() — 拼接 URL(含 query params)
Transport->>Auth: Auth.apply({ request, url, body, headers })
Auth-->>Transport: 注入鉴权 Header
Transport->>Executor: RequestExecutor.execute(httpClientRequest)
Executor->>Provider: POST endpoint (SSE / AWS event-stream)
Provider-->>Executor: 200 流式响应
Executor-->>LLMClient: Stream<LLMEvent>(Framing → Protocol.stream.step 解析)
Loading
Header 注入顺序
jsonRequestParts() [transport/http.ts]
1. Headers.fromInput({ ...route.headers(request), ...request.http.headers })
2. Auth.toEffect(auth)({ request, url, body, headers }) ← 注入凭据 Header
3. ProviderShared.jsonPost(...) ← 追加 content-type: application/json
错误重试(route/executor.ts:retryStatusFailures)
状态码 429/503/504/529 自动重试,最多 2 次,尊重 retry-after / retry-after-ms 响应头。
二、请求 Header 明细
Anthropic(protocols/anthropic-messages.ts:845)
Header
取值来源
说明
content-type
protocols/shared.ts:jsonPost:322
application/json
anthropic-version
anthropic-messages.ts:852 headers:()=>({...})
固定 2023-06-01
x-api-key
providers/anthropic.ts:auth()→Auth.header("x-api-key")
优先 apiKey,回退 ANTHROPIC_API_KEY
anthropic-beta
opencode/provider/provider.ts:175
按模型注入,如 interleaved-thinking-2025-05-14
anthropic-beta
opencode/provider/provider.ts:622
context-1m-2025-08-07(超长上下文)
OpenAI(protocols/openai-responses.ts:984 / openai-chat.ts:497)
Header
取值来源
说明
content-type
protocols/shared.ts:jsonPost
application/json
authorization
providers/openai.ts→AuthOptions.bearer
Bearer <key>,回退 OPENAI_API_KEY
OpenAI 兼容(DeepSeek、Mistral、TogetherAI 等)
Header
取值来源
说明
content-type
protocols/shared.ts:jsonPost
application/json
authorization
各 provider configuredRoute→AuthOptions.bearer(options,"<PROVIDER>_API_KEY")
Bearer <key>
Google Gemini(protocols/gemini.ts:500)
Header
取值来源
说明
content-type
protocols/shared.ts:jsonPost
application/json
x-goog-api-key
providers/google.ts:auth()→Auth.header("x-goog-api-key")
回退 GOOGLE_GENERATIVE_AI_API_KEY
模型 ID 嵌入 URL 路径:/models/${model.id}:streamGenerateContent?alt=sse
Amazon Bedrock — SigV4(protocols/bedrock-converse.ts:658)
Header
取值来源
说明
content-type
protocols/utils/bedrock-auth.ts:signRequest
参与 SigV4 规范化
x-amz-date
bedrock-auth.ts→AwsV4Signer.sign()
UTC 时间戳
x-amz-security-token
bedrock-auth.ts→AwsV4Signer.sign()(STS)
STS 会话令牌
authorization
bedrock-auth.ts→AwsV4Signer.sign()
AWS4-HMAC-SHA256 Credential=.../bedrock/...
有 apiKey 时改用 Auth.bearer(apiKey) Bearer 模式(providers/amazon-bedrock.ts)
Azure OpenAI(providers/azure.ts)
Header
取值来源
说明
content-type
protocols/shared.ts:jsonPost
application/json
api-key
providers/azure.ts:auth():67→Auth.remove("authorization").andThen(Auth.header("api-key"))
先移除 Bearer authorization,注入 api-key,回退 AZURE_OPENAI_API_KEY
api-version 通过 URL query 参数(非 Header)
GitHub Copilot(providers/github-copilot.ts)
Header
取值来源
说明
content-type
protocols/shared.ts:jsonPost
application/json
authorization
providers/github-copilot.ts→AuthOptions.bearer
OAuth2 token(plugin/github-copilot/copilot.ts 刷新)
anthropic-beta
plugin/github-copilot/copilot.ts:369
interleaved-thinking-2025-05-14
OpenRouter(providers/openrouter.ts)
Header
取值来源
说明
content-type
protocols/shared.ts:jsonPost
application/json
authorization
providers/openrouter.ts→AuthOptions.bearer
Bearer <key>,回退 OPENROUTER_API_KEY
HTTP-Referer
opencode/provider/provider.ts:461
`(opencode.ai/redacted)
X-Title
opencode/provider/provider.ts:462
opencode
GitLab AI Gateway(opencode/provider/provider.ts:gitlab)
Header
取值来源
说明
authorization
provider.ts:538
Bearer (token)(OAuth / GITLAB_TOKEN)
User-Agent
provider.ts:aiGatewayHeaders
opencode/\$\{ver} gitlab-ai-provider/\$\{ver} (\$\{os})
anthropic-beta
provider.ts:622 / core/plugin/provider/gitlab.ts:23
context-1m-2025-08-07
三、鉴权机制
Provider
方式
核心代码
Anthropic
API Key Header
providers/anthropic.ts:auth()→Auth.optional(key).orElse(Auth.config("ANTHROPIC_API_KEY")).pipe(Auth.header("x-api-key"))
OpenAI
Bearer
providers/openai.ts→AuthOptions.bearer(options,"OPENAI_API_KEY")
OpenAI-兼容
Bearer
各 provider configuredRoute→AuthOptions.bearer(options,"(ENV)")
Google Gemini
API Key Header
providers/google.ts:auth()→Auth.header("x-goog-api-key")
Amazon Bedrock
AWS SigV4
protocols/utils/bedrock-auth.ts:sigV4(),用 aws4fetch 库签名
Azure OpenAI
api-key Header
providers/azure.ts:67→Auth.remove("authorization").andThen(Auth.header("api-key"))
GitHub Copilot
OAuth Bearer
plugin/github-copilot/copilot.ts OAuth2 刷新
OpenRouter
Bearer
providers/openrouter.ts→AuthOptions.bearer
GitLab
OAuth Bearer/PAT
provider.ts:538 fetch 拦截注入
Auth 模块 (packages/llm/src/route/auth.ts)核心 API:
Auth.bearer(src) — Authorization: Bearer (value)
Auth.header(name, src) — 任意 Header 名
Auth.config(envVar) — Effect Config 读环境变量,缺失抛 AuthenticationReason
Auth.remove(name) — 删除 Header(Azure 用于替换 authorization)
Auth.custom(fn) — 完全自定义(Bedrock SigV4)
credential.orElse(that) — 链式回退
四、关键代码位置
文件
说明
packages/llm/src/route/client.ts
Route.make, compile(), resolveRequestOptions()
packages/llm/src/route/auth.ts
所有 Auth 构造函数
packages/llm/src/route/transport/http.ts
jsonRequestParts(), httpJson()
packages/llm/src/route/executor.ts
RequestExecutor, 重试, 速率限制解析
packages/llm/src/protocols/anthropic-messages.ts:845
Anthropic 路由,anthropic-version
packages/llm/src/protocols/openai-responses.ts:984
OpenAI Responses 路由
packages/llm/src/protocols/gemini.ts:500
Gemini 路由
packages/llm/src/protocols/bedrock-converse.ts:658
Bedrock 路由
packages/llm/src/protocols/utils/bedrock-auth.ts
SigV4 实现
packages/llm/src/protocols/shared.ts:322
jsonPost() 注入 content-type
packages/llm/src/providers/azure.ts:67
Azure api-key 替换 authorization
packages/opencode/src/session/llm.ts
会话编排,runtime 选择
packages/opencode/src/session/llm/native-request.ts
ModelMessage → LLMRequest
packages/opencode/src/provider/provider.ts:175,461,538,622
anthropic-beta, OpenRouter HTTP-Referer, GitLab User-Agent
Generated by Daily Upstream Sync + Request-Flow Analysis · 138.1 AIC · ⌖ 9.51 AIC · ⊞ 5.9K · ◷
近期变更
近期同步 upstream 的相关提交(不影响 Header 结构,主要是请求体构造层面):
20589d6fix(provider): preserve Mistral reasoning historyfada1a5fix(provider): serialize Mistral prompt cache keys542ba88fix(provider): select prompt cache keys by SDK一、请求流程
分层架构
opencode/src/session/llm.ts— 决定走 Native runtime 还是 AI SDK pathsession/llm/native-request.ts— ModelMessage[] → LLMRequest@opencode-ai/llm(packages/llm/src/)请求时序
sequenceDiagram participant Session as session/llm.ts participant LLMClient as route/client.ts (LLMClient) participant Protocol as Protocol.body.from participant Transport as HttpTransport participant Auth as Auth.apply participant Executor as RequestExecutor participant Provider as LLM Provider Session->>LLMClient: LLMClient.stream(llmRequest) LLMClient->>LLMClient: compile() — 合并 route/model/request defaults + applyCachePolicy LLMClient->>Protocol: route.body.from(resolved) — 构造 provider-native body LLMClient->>Transport: route.prepareTransport(body, resolved) Transport->>Transport: renderEndpoint() — 拼接 URL(含 query params) Transport->>Auth: Auth.apply({ request, url, body, headers }) Auth-->>Transport: 注入鉴权 Header Transport->>Executor: RequestExecutor.execute(httpClientRequest) Executor->>Provider: POST endpoint (SSE / AWS event-stream) Provider-->>Executor: 200 流式响应 Executor-->>LLMClient: Stream<LLMEvent>(Framing → Protocol.stream.step 解析)Header 注入顺序
错误重试(
route/executor.ts:retryStatusFailures)状态码 429/503/504/529 自动重试,最多 2 次,尊重
retry-after/retry-after-ms响应头。二、请求 Header 明细
Anthropic(
protocols/anthropic-messages.ts:845)content-typeprotocols/shared.ts:jsonPost:322application/jsonanthropic-versionanthropic-messages.ts:852 headers:()=>({...})2023-06-01x-api-keyproviders/anthropic.ts:auth()→Auth.header("x-api-key")apiKey,回退ANTHROPIC_API_KEYanthropic-betaopencode/provider/provider.ts:175interleaved-thinking-2025-05-14anthropic-betaopencode/provider/provider.ts:622context-1m-2025-08-07(超长上下文)OpenAI(
protocols/openai-responses.ts:984/openai-chat.ts:497)content-typeprotocols/shared.ts:jsonPostapplication/jsonauthorizationproviders/openai.ts→AuthOptions.bearerBearer <key>,回退OPENAI_API_KEYOpenAI 兼容(DeepSeek、Mistral、TogetherAI 等)
content-typeprotocols/shared.ts:jsonPostapplication/jsonauthorizationconfiguredRoute→AuthOptions.bearer(options,"<PROVIDER>_API_KEY")Bearer <key>Google Gemini(
protocols/gemini.ts:500)content-typeprotocols/shared.ts:jsonPostapplication/jsonx-goog-api-keyproviders/google.ts:auth()→Auth.header("x-goog-api-key")GOOGLE_GENERATIVE_AI_API_KEYAmazon Bedrock — SigV4(
protocols/bedrock-converse.ts:658)content-typeprotocols/utils/bedrock-auth.ts:signRequestx-amz-datebedrock-auth.ts→AwsV4Signer.sign()x-amz-security-tokenbedrock-auth.ts→AwsV4Signer.sign()(STS)authorizationbedrock-auth.ts→AwsV4Signer.sign()AWS4-HMAC-SHA256 Credential=.../bedrock/...Azure OpenAI(
providers/azure.ts)content-typeprotocols/shared.ts:jsonPostapplication/jsonapi-keyproviders/azure.ts:auth():67→Auth.remove("authorization").andThen(Auth.header("api-key"))api-key,回退AZURE_OPENAI_API_KEYGitHub Copilot(
providers/github-copilot.ts)content-typeprotocols/shared.ts:jsonPostapplication/jsonauthorizationproviders/github-copilot.ts→AuthOptions.bearerplugin/github-copilot/copilot.ts刷新)anthropic-betaplugin/github-copilot/copilot.ts:369interleaved-thinking-2025-05-14OpenRouter(
providers/openrouter.ts)content-typeprotocols/shared.ts:jsonPostapplication/jsonauthorizationproviders/openrouter.ts→AuthOptions.bearerBearer <key>,回退OPENROUTER_API_KEYHTTP-Refereropencode/provider/provider.ts:461X-Titleopencode/provider/provider.ts:462opencodeGitLab AI Gateway(
opencode/provider/provider.ts:gitlab)authorizationprovider.ts:538Bearer (token)(OAuth / GITLAB_TOKEN)User-Agentprovider.ts:aiGatewayHeadersopencode/\$\{ver} gitlab-ai-provider/\$\{ver} (\$\{os})anthropic-betaprovider.ts:622/core/plugin/provider/gitlab.ts:23context-1m-2025-08-07三、鉴权机制
providers/anthropic.ts:auth()→Auth.optional(key).orElse(Auth.config("ANTHROPIC_API_KEY")).pipe(Auth.header("x-api-key"))providers/openai.ts→AuthOptions.bearer(options,"OPENAI_API_KEY")configuredRoute→AuthOptions.bearer(options,"(ENV)")providers/google.ts:auth()→Auth.header("x-goog-api-key")protocols/utils/bedrock-auth.ts:sigV4(),用aws4fetch库签名providers/azure.ts:67→Auth.remove("authorization").andThen(Auth.header("api-key"))plugin/github-copilot/copilot.tsOAuth2 刷新providers/openrouter.ts→AuthOptions.bearerprovider.ts:538fetch 拦截注入Auth 模块(
packages/llm/src/route/auth.ts)核心 API:Auth.bearer(src)—Authorization: Bearer (value)Auth.header(name, src)— 任意 Header 名Auth.config(envVar)— Effect Config 读环境变量,缺失抛AuthenticationReasonAuth.remove(name)— 删除 Header(Azure 用于替换 authorization)Auth.custom(fn)— 完全自定义(Bedrock SigV4)credential.orElse(that)— 链式回退四、关键代码位置
packages/llm/src/route/client.tsRoute.make,compile(),resolveRequestOptions()packages/llm/src/route/auth.tspackages/llm/src/route/transport/http.tsjsonRequestParts(),httpJson()packages/llm/src/route/executor.tsRequestExecutor, 重试, 速率限制解析packages/llm/src/protocols/anthropic-messages.ts:845anthropic-versionpackages/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.tspackages/llm/src/protocols/shared.ts:322jsonPost()注入content-typepackages/llm/src/providers/azure.ts:67api-key替换authorizationpackages/opencode/src/session/llm.tspackages/opencode/src/session/llm/native-request.tspackages/opencode/src/provider/provider.ts:175,461,538,622