本次变更提示
近期同步的 20 条提交主要涉及 TUI 交互、子 Agent 嵌套深度限制和 UI 修复,不直接影响请求流程或 Header 构造 。
1. 请求流程
opencode 存在两条并行的 LLM 请求路径:
Native 路径 (@opencode/llm,Effect 体系):OpenAI、Anthropic、Bedrock、Google 等原生协议。
AI SDK 路径 (ai / @ai-sdk/*):GitHub Copilot、Azure、OpenRouter、xAI 等。
1.1 Native 路径时序(Mermaid)
sequenceDiagram
participant S as Session/prompt
participant NR as native-runtime.ts
participant NRQ as native-request.ts
participant LC as LLMClient (client.ts)
participant P as Protocol
participant HT as HttpTransport (http.ts)
participant Auth as Auth (auth.ts)
participant EX as RequestExecutor (executor.ts)
participant API as LLM Provider
S->>NR: stream(input)
NR->>NRQ: model() 按 api.npm 选 provider 工厂
NRQ->>NRQ: request() 构造 LLMRequest
NR->>LC: LLMClient.stream(request)
LC->>LC: compile() → resolveRequestOptions()
LC->>P: route.body.from(request) 构造请求体
LC->>HT: prepareTransport() → jsonRequestParts()
HT->>Auth: Auth.toEffect(auth)(authInput)
Auth-->>HT: 返回已鉴权 Headers
HT->>HT: ProviderShared.jsonPost() 设置 content-type
LC->>EX: execute(httpRequest)
EX->>EX: retryStatusFailures()(最多重试 2 次)
EX->>API: HTTP POST(SSE/JSON 流)
API-->>EX: 响应流
EX-->>LC: HttpClientResponse
LC->>P: streamPrepared() 解帧→解码 LLMEvent
LC-->>S: Stream<LLMEvent>
Loading
1.2 关键步骤
#
步骤
文件 / 函数
1
Session 调用 stream(input)
session/llm/native-runtime.ts
2
按 model.api.npm 分派 provider 工厂,构造 LLMRequest
session/llm/native-request.ts:model() L153-175
3
compile() 合并 route/model/request 三层默认值
llm/src/route/client.ts:compile
4
Protocol body.from(request) 构造 provider-native JSON 体
各协议文件
5
jsonRequestParts() 渲染 URL、合并静态 header、调用 Auth
llm/src/route/transport/http.ts:jsonRequestParts
6
ProviderShared.jsonPost() 强制设置 content-type: application/json
llm/src/protocols/shared.ts:322
7
遇到 429/503/504/529 按指数退避重试(最多 2 次)
llm/src/route/executor.ts:retryStatusFailures
8
响应经 Framing 解帧后由 Protocol 状态机解析为 LLMEvent
llm/src/route/client.ts:streamPrepared
2. 请求 Header 明细
通用(所有 Native 路径)
Header
取值来源
说明
content-type
shared.ts:322
application/json,jsonPost() 强制设置
Anthropic
Header
取值来源
说明
anthropic-version
anthropic-messages.ts:852 → "2023-06-01"
路由静态注入,每次请求携带
x-api-key
providers/anthropic.ts:17 → apiKey || ANTHROPIC_API_KEY
鉴权(非 Bearer 格式)
OpenAI / OpenAI-Compatible
Header
取值来源
说明
Authorization
auth-options.ts:bearer() → "Bearer <apiKey || OPENAI_API_KEY>"
标准 Bearer Token
Azure OpenAI
Header
取值来源
说明
api-key
providers/azure.ts:70 → apiKey || AZURE_OPENAI_API_KEY
Azure 专用(同时移除 Authorization)
URL 附加 ?api-version=<version> 查询参数。
Amazon Bedrock(SigV4)
Header
取值来源
说明
Authorization
bedrock-auth.ts:signRequest() → AwsV4Signer.sign()
AWS4-HMAC-SHA256 签名串
x-amz-date
AwsV4Signer 自动
UTC 时间戳
x-amz-security-token
AwsV4Signer(有 sessionToken 时)
STS 临时凭证令牌
若提供 apiKey 则退化为 Authorization: Bearer <apiKey>。
Google / Gemini
Header
取值来源
说明
x-goog-api-key
providers/google.ts:16 → apiKey || GOOGLE_GENERATIVE_AI_API_KEY
Google API Key
GitHub Copilot(AI SDK 路径)
Header
取值来源
说明
Authorization
core/github-copilot/copilot-provider.ts:62 → "Bearer <apiKey>"
OAuth Token 或 API Key
User-Agent 后缀
withUserAgentSuffix(..., "ai-sdk/openai-compatible/0.1.0")
SDK 版本标识
OpenRouter
Header
取值来源
说明
Authorization
providers/openrouter.ts → "Bearer <apiKey || OPENROUTER_API_KEY>"
Bearer Token
Cloudflare AI Gateway / Workers AI
Header
取值来源
说明
Authorization
providers/cloudflare.ts:45 → Bearer from CLOUDFLARE_API_TOKEN / CF_AIG_TOKEN(Gateway)或 CLOUDFLARE_API_KEY / CLOUDFLARE_WORKERS_AI_TOKEN(Workers AI)
Bearer Token
3. 鉴权机制
3.1 API Key
apiKey 参数优先 → 回退到 Auth.config("ENV_VAR")(读取环境变量)
→ Auth.header("x-api-key") Anthropic
→ Auth.bearer() OpenAI / OpenRouter 等
→ Auth.header("x-goog-api-key") Google
→ Auth.remove("authorization") + Auth.header("api-key") Azure
核心抽象:auth.ts:credential() / auth.ts:fromCredential() / auth-options.ts:bearer()。
3.2 AWS SigV4(Bedrock)
protocols/utils/bedrock-auth.ts:signRequest() 使用 aws4fetch 的 AwsV4Signer 对每请求签名。凭据在路由构造时静态注入;STS 凭据过期需调用方手动重建 model。
3.3 OAuth(GitHub Copilot 等)
packages/opencode/src/provider/auth.ts 管理 OAuth 流程(authorize() → callback() → 存储 { type: "oauth", access: "<token>" }),运行时以 Bearer Token 形式注入。
3.4 自定义 Auth
Auth.custom((input: AuthInput) => Effect.Effect<Headers, LLMError>) 允许完全自定义 header 注入,Bedrock SigV4 即此方式。
4. 关键代码位置索引
文件
说明
packages/llm/src/route/client.ts
核心路由、compile()、LLMClient
packages/llm/src/route/auth.ts
Auth/Credential 抽象,header 注入接口
packages/llm/src/route/auth-options.ts
AuthOptions.bearer() 标准 Bearer 解析
packages/llm/src/route/transport/http.ts
jsonRequestParts() URL/header/auth 组装
packages/llm/src/route/executor.ts
HTTP 执行、重试、错误分类、日志脱敏
packages/llm/src/protocols/shared.ts:320
jsonPost() → content-type: application/json
packages/llm/src/protocols/anthropic-messages.ts:852
anthropic-version: 2023-06-01
packages/llm/src/protocols/openai-chat.ts:497
OpenAI Chat 路由
packages/llm/src/protocols/openai-responses.ts:984
OpenAI Responses 路由
packages/llm/src/protocols/bedrock-converse.ts:658
Bedrock 路由,SigV4 auth
packages/llm/src/protocols/gemini.ts:500
Gemini 路由
packages/llm/src/protocols/utils/bedrock-auth.ts
AWS SigV4 实现(aws4fetch)
packages/llm/src/providers/anthropic.ts
x-api-key 注入
packages/llm/src/providers/azure.ts
api-key,移除 Authorization
packages/llm/src/providers/google.ts
x-goog-api-key
packages/llm/src/providers/amazon-bedrock.ts
SigV4 / Bearer 二选一
packages/llm/src/providers/github-copilot.ts
Copilot provider facade
packages/llm/src/providers/cloudflare.ts
Cloudflare AI Gateway / Workers AI
packages/opencode/src/session/llm/native-request.ts
model() 分派,request() 构造
packages/opencode/src/session/llm/native-runtime.ts
Native 路径入口
packages/opencode/src/provider/provider.ts
BUNDLED_PROVIDERS,AI SDK 工厂
packages/opencode/src/provider/auth.ts
OAuth 流程管理
packages/core/src/github-copilot/copilot-provider.ts:62
Copilot Authorization: Bearer
Generated by Daily Upstream Sync + Request-Flow Analysis · 152.6 AIC · ⌖ 7.06 AIC · ⊞ 5.9K · ◷
本次变更提示
近期同步的 20 条提交主要涉及 TUI 交互、子 Agent 嵌套深度限制和 UI 修复,不直接影响请求流程或 Header 构造。
1. 请求流程
opencode 存在两条并行的 LLM 请求路径:
@opencode/llm,Effect 体系):OpenAI、Anthropic、Bedrock、Google 等原生协议。ai/@ai-sdk/*):GitHub Copilot、Azure、OpenRouter、xAI 等。1.1 Native 路径时序(Mermaid)
sequenceDiagram participant S as Session/prompt participant NR as native-runtime.ts participant NRQ as native-request.ts participant LC as LLMClient (client.ts) participant P as Protocol participant HT as HttpTransport (http.ts) participant Auth as Auth (auth.ts) participant EX as RequestExecutor (executor.ts) participant API as LLM Provider S->>NR: stream(input) NR->>NRQ: model() 按 api.npm 选 provider 工厂 NRQ->>NRQ: request() 构造 LLMRequest NR->>LC: LLMClient.stream(request) LC->>LC: compile() → resolveRequestOptions() LC->>P: route.body.from(request) 构造请求体 LC->>HT: prepareTransport() → jsonRequestParts() HT->>Auth: Auth.toEffect(auth)(authInput) Auth-->>HT: 返回已鉴权 Headers HT->>HT: ProviderShared.jsonPost() 设置 content-type LC->>EX: execute(httpRequest) EX->>EX: retryStatusFailures()(最多重试 2 次) EX->>API: HTTP POST(SSE/JSON 流) API-->>EX: 响应流 EX-->>LC: HttpClientResponse LC->>P: streamPrepared() 解帧→解码 LLMEvent LC-->>S: Stream<LLMEvent>1.2 关键步骤
stream(input)session/llm/native-runtime.tsmodel.api.npm分派 provider 工厂,构造LLMRequestsession/llm/native-request.ts:model()L153-175compile()合并 route/model/request 三层默认值llm/src/route/client.ts:compilebody.from(request)构造 provider-native JSON 体jsonRequestParts()渲染 URL、合并静态 header、调用 Authllm/src/route/transport/http.ts:jsonRequestPartsProviderShared.jsonPost()强制设置content-type: application/jsonllm/src/protocols/shared.ts:322llm/src/route/executor.ts:retryStatusFailuresLLMEventllm/src/route/client.ts:streamPrepared2. 请求 Header 明细
通用(所有 Native 路径)
content-typeshared.ts:322application/json,jsonPost()强制设置Anthropic
anthropic-versionanthropic-messages.ts:852→"2023-06-01"x-api-keyproviders/anthropic.ts:17→apiKey || ANTHROPIC_API_KEYOpenAI / OpenAI-Compatible
Authorizationauth-options.ts:bearer()→"Bearer <apiKey || OPENAI_API_KEY>"Azure OpenAI
api-keyproviders/azure.ts:70→apiKey || AZURE_OPENAI_API_KEYAuthorization)URL 附加
?api-version=<version>查询参数。Amazon Bedrock(SigV4)
Authorizationbedrock-auth.ts:signRequest()→AwsV4Signer.sign()x-amz-dateAwsV4Signer自动x-amz-security-tokenAwsV4Signer(有 sessionToken 时)若提供
apiKey则退化为Authorization: Bearer <apiKey>。Google / Gemini
x-goog-api-keyproviders/google.ts:16→apiKey || GOOGLE_GENERATIVE_AI_API_KEYGitHub Copilot(AI SDK 路径)
Authorizationcore/github-copilot/copilot-provider.ts:62→"Bearer <apiKey>"withUserAgentSuffix(..., "ai-sdk/openai-compatible/0.1.0")OpenRouter
Authorizationproviders/openrouter.ts→"Bearer <apiKey || OPENROUTER_API_KEY>"Cloudflare AI Gateway / Workers AI
Authorizationproviders/cloudflare.ts:45→ Bearer fromCLOUDFLARE_API_TOKEN/CF_AIG_TOKEN(Gateway)或CLOUDFLARE_API_KEY/CLOUDFLARE_WORKERS_AI_TOKEN(Workers AI)3. 鉴权机制
3.1 API Key
核心抽象:
auth.ts:credential()/auth.ts:fromCredential()/auth-options.ts:bearer()。3.2 AWS SigV4(Bedrock)
protocols/utils/bedrock-auth.ts:signRequest()使用aws4fetch的AwsV4Signer对每请求签名。凭据在路由构造时静态注入;STS 凭据过期需调用方手动重建 model。3.3 OAuth(GitHub Copilot 等)
packages/opencode/src/provider/auth.ts管理 OAuth 流程(authorize()→callback()→ 存储{ type: "oauth", access: "<token>" }),运行时以 Bearer Token 形式注入。3.4 自定义 Auth
Auth.custom((input: AuthInput) => Effect.Effect<Headers, LLMError>)允许完全自定义 header 注入,Bedrock SigV4 即此方式。4. 关键代码位置索引
packages/llm/src/route/client.tscompile()、LLMClientpackages/llm/src/route/auth.tsAuth/Credential抽象,header 注入接口packages/llm/src/route/auth-options.tsAuthOptions.bearer()标准 Bearer 解析packages/llm/src/route/transport/http.tsjsonRequestParts()URL/header/auth 组装packages/llm/src/route/executor.tspackages/llm/src/protocols/shared.ts:320jsonPost()→content-type: application/jsonpackages/llm/src/protocols/anthropic-messages.ts:852anthropic-version: 2023-06-01packages/llm/src/protocols/openai-chat.ts:497packages/llm/src/protocols/openai-responses.ts:984packages/llm/src/protocols/bedrock-converse.ts:658packages/llm/src/protocols/gemini.ts:500packages/llm/src/protocols/utils/bedrock-auth.tsaws4fetch)packages/llm/src/providers/anthropic.tsx-api-key注入packages/llm/src/providers/azure.tsapi-key,移除Authorizationpackages/llm/src/providers/google.tsx-goog-api-keypackages/llm/src/providers/amazon-bedrock.tspackages/llm/src/providers/github-copilot.tspackages/llm/src/providers/cloudflare.tspackages/opencode/src/session/llm/native-request.tsmodel()分派,request()构造packages/opencode/src/session/llm/native-runtime.tspackages/opencode/src/provider/provider.tspackages/opencode/src/provider/auth.tspackages/core/src/github-copilot/copilot-provider.ts:62Authorization: Bearer