本次变更提示
近期同步提交中与请求流程相关:
3033afb fix(provider): normalize Mistral family tool call IDs — 影响 OpenAI-Compatible 协议 tool-call ID 规范化
5a8ee27 fix(provider): update muse-spark reasoning default — 影响特定模型请求 Body 构造
一、请求流程(时序)
sequenceDiagram
participant S as Session 层
participant P as LLMRequestPrep (session/llm/request.ts)
participant N as LLMNative (session/llm/native-request.ts)
participant R as LLMNativeRuntime (session/llm/native-runtime.ts)
participant C as LLMClient (llm/route/client.ts)
participant T as httpJson Transport (route/transport/http.ts)
participant E as RequestExecutor (route/executor.ts)
participant API as Provider HTTP API
S->>P: prepare(sessionID, messages, model)
Note over P: 构造 User-Agent、会话追踪 Header、plugin Header
P->>N: LLMNative.model() — api.npm → Provider Facade
N->>R: LLMNative.request() → LLMRequest
R->>C: llmClient.stream(LLMRequest)
C->>C: Protocol.body.from() — Provider 原生 Body
C->>T: httpJson.prepare(body)
Note over T: renderEndpoint() URL, Auth.apply() 注入鉴权 Header
T->>E: runtime.http.execute(httpRequest)
E->>API: POST(/messages / /chat/completions / converse-stream)
API-->>E: 200 + SSE stream
E-->>C: frames via Framing.sse
C-->>S: Stream LLMEvent(text-delta/tool-call/finish)
Loading
关键步骤
步骤
描述
关键文件/符号
1 Provider/Model 解析
api.npm 包名 → Provider Facade → Route
native-request.ts LLMNative.model()
2 会话 Header 构造
User-Agent、会话追踪、plugin 贡献 Header
request.ts LLMRequestPrep.prepare()
3 凭据获取
AuthOptions.bearer() 惰性解析 apiKey/env
route/auth-options.ts:47–55
4 Protocol Body
LLMRequest → Provider 原生 Body(Schema 验证+JSON 编码)
protocols/*.ts body.from()
5 URL 渲染
Endpoint.render() 静态/动态路径(Bedrock 含 modelId)
route/endpoint.ts
6 Auth 注入
Auth.apply() 注入鉴权 Header
route/auth.ts
7 HTTP 发送+重试
POST;读取 retry-after[-ms];最多重试 2 次
route/executor.ts
8 流解析
SSE/AWS event-stream → protocol.stream.step() → LLMEvent
route/framing.ts
二、请求 Header 明细
鉴权类 Header(按 Provider)
Provider
Header
取值来源
代码位置
Anthropic
x-api-key
options.apiKey → env ANTHROPIC_API_KEY
providers/anthropic.ts:13–18
Anthropic
anthropic-version
硬编码 "2023-06-01"
protocols/anthropic-messages.ts:852
OpenAI
Authorization
Bearer <key>;env OPENAI_API_KEY
providers/openai.ts:24
Azure OpenAI
api-key
options.apiKey;env AZURE_OPENAI_API_KEY
providers/azure.ts:65–72
Azure OpenAI
Authorization 移除
Auth.remove("authorization")
providers/azure.ts:10
Google Gemini
x-goog-api-key
options.apiKey;env GOOGLE_GENERATIVE_AI_API_KEY
providers/google.ts:13–17
GitHub Copilot
Authorization
Bearer <key>;无 env 回退
providers/github-copilot.ts:40,46
Bedrock API Key
Authorization
Bearer <key>
providers/amazon-bedrock.ts:29
Bedrock SigV4
Authorization
AWS4-HMAC-SHA256 Credential=...
protocols/utils/bedrock-auth.ts:20–45
Bedrock SigV4
x-amz-date
签名时间戳(AwsV4Signer 注入)
protocols/utils/bedrock-auth.ts
Bedrock SigV4
x-amz-security-token
STS sessionToken(可选)
protocols/utils/bedrock-auth.ts
OpenAI-Compatible
Authorization
Bearer <key>;无 env 回退
providers/openai-compatible.ts:29
会话追踪 Header(session/llm/request.ts:187–204)
条件
Header
取值来源
所有
User-Agent
opencode/<InstallationVersion>(line 18)
provider === "opencode"
x-opencode-project/session/request/client
实例/会话/用户/flags 值
非 opencode
x-session-affinity, X-Session-Id
sessionID
非 opencode(若有)
x-parent-session-id
parentSessionID
所有
model/plugin 级
model.headers.*;plugin chat.headers hook
HTTP 通用 Header
Header
值
来源
content-type
application/json
protocols/shared.ts ProviderShared.jsonPost()
三、鉴权机制
Auth 原语 (route/auth.ts):所有鉴权均为惰性 Effect,真正凭据在请求时才解析。
凭据优先级 (route/auth-options.ts:47–55):
显式 auth 对象
options.apiKey(内联/Redacted/Config)
Auth.config(envVar) — 环境变量回退
机制
Provider
实现
Auth.header("x-api-key")
Anthropic
providers/anthropic.ts
Auth.bearer()
OpenAI、Copilot、Compatible
route/auth.ts
Auth.header("api-key") + Auth.remove("authorization")
Azure
providers/azure.ts
Auth.header("x-goog-api-key")
Google
providers/google.ts
AWS SigV4 via aws4fetch.AwsV4Signer
Bedrock
protocols/utils/bedrock-auth.ts:20–45
自定义 OAuth fetch 注入
OpenAI OAuth
session/llm/native-runtime.ts:148–153
Bedrock SigV4 :用 accessKeyId + secretAccessKey + sessionToken 对 URL+Body+Headers 整体签名(service="bedrock"),签名前设 content-type: application/json(line 56)。
OAuth 交互流程 (provider/auth.ts):authorize() → plugin hook → 重定向;callback() 持久化 {type:"oauth", access, refresh, expires} 或 {type:"api", key}。
四、Endpoint / URL 构造
Provider
Default Base URL
Path
Anthropic
`(api.anthropic.com/redacted)
/messages
OpenAI Chat
`(api.openai.com/redacted)
/chat/completions
OpenAI Responses
`(api.openai.com/redacted)
/responses
Google Gemini
`(generativelanguage.googleapis.com/redacted)
/models/${modelId}:streamGenerateContent?alt=sse
Amazon Bedrock
(bedrockruntime/redacted)<region>.amazonaws.com
/model/${encodedModelId}/converse-stream
Azure OpenAI
https://<resourceName>.openai.azure.com/openai/v1
/responses 或 /chat/completions?api-version=<ver>
GitHub Copilot / Compatible
需外部配置(无默认)
/chat/completions
五、错误处理与重试(route/executor.ts)
最大重试次数 :2;初始延迟 :500 ms(含抖动);最大延迟 :10,000 ms
可重试状态码 :429、503、504、529
状态映射:401→Authentication(invalid);403→Authentication(insufficient-permissions);429(配额)→QuotaExceeded;429→RateLimit;400/404/422→InvalidRequest;5xx→ProviderInternal;内容政策→ContentPolicy
Secret 脱敏 :Header/query/Body 中匹配 authorization|api[-_]?key|token|secret|signature 的字段均被脱敏(executor.ts:48–54, 166–195)
六、关键代码位置索引
文件
核心符号
packages/opencode/src/session/llm/request.ts
LLMRequestPrep.prepare()
packages/opencode/src/session/llm/native-request.ts
LLMNative.model/request()
packages/opencode/src/session/llm/native-runtime.ts
LLMNativeRuntime.stream()
packages/opencode/src/provider/auth.ts
ProviderAuth.Service
packages/llm/src/route/client.ts
LLMClient.stream/generate/prepare()
packages/llm/src/route/auth.ts
Auth interface + constructors
packages/llm/src/route/auth-options.ts
AuthOptions.bearer()
packages/llm/src/route/executor.ts
RequestExecutor
packages/llm/src/route/transport/http.ts
httpJson
packages/llm/src/route/transport/websocket.ts
WebSocketTransport.json
packages/llm/src/route/endpoint.ts
Endpoint.path/render()
packages/llm/src/protocols/anthropic-messages.ts
AnthropicMessages.protocol
packages/llm/src/protocols/openai-chat.ts
OpenAIChat.protocol
packages/llm/src/protocols/openai-responses.ts
OpenAIResponses.protocol
packages/llm/src/protocols/bedrock-converse.ts
BedrockConverse.protocol
packages/llm/src/protocols/utils/bedrock-auth.ts
bedrockSigV4Auth()
packages/llm/src/providers/anthropic.ts
Anthropic.configure()
packages/llm/src/providers/openai.ts
OpenAI.configure()
packages/llm/src/providers/amazon-bedrock.ts
AmazonBedrock.configure()
packages/llm/src/providers/azure.ts
Azure.configure()
packages/llm/src/providers/github-copilot.ts
GitHubCopilot.configure()
packages/llm/src/providers/google.ts
Google.configure()
packages/llm/src/providers/openai-compatible.ts
OpenAICompatible.configure()
Generated by Daily Upstream Sync + Request-Flow Analysis · 116.2 AIC · ⌖ 9.59 AIC · ⊞ 5.9K · ◷
本次变更提示
近期同步提交中与请求流程相关:
3033afbfix(provider): normalize Mistral family tool call IDs — 影响 OpenAI-Compatible 协议 tool-call ID 规范化5a8ee27fix(provider): update muse-spark reasoning default — 影响特定模型请求 Body 构造一、请求流程(时序)
sequenceDiagram participant S as Session 层 participant P as LLMRequestPrep (session/llm/request.ts) participant N as LLMNative (session/llm/native-request.ts) participant R as LLMNativeRuntime (session/llm/native-runtime.ts) participant C as LLMClient (llm/route/client.ts) participant T as httpJson Transport (route/transport/http.ts) participant E as RequestExecutor (route/executor.ts) participant API as Provider HTTP API S->>P: prepare(sessionID, messages, model) Note over P: 构造 User-Agent、会话追踪 Header、plugin Header P->>N: LLMNative.model() — api.npm → Provider Facade N->>R: LLMNative.request() → LLMRequest R->>C: llmClient.stream(LLMRequest) C->>C: Protocol.body.from() — Provider 原生 Body C->>T: httpJson.prepare(body) Note over T: renderEndpoint() URL, Auth.apply() 注入鉴权 Header T->>E: runtime.http.execute(httpRequest) E->>API: POST(/messages / /chat/completions / converse-stream) API-->>E: 200 + SSE stream E-->>C: frames via Framing.sse C-->>S: Stream LLMEvent(text-delta/tool-call/finish)关键步骤
api.npm包名 → Provider Facade → Routenative-request.tsLLMNative.model()request.tsLLMRequestPrep.prepare()AuthOptions.bearer()惰性解析 apiKey/envroute/auth-options.ts:47–55protocols/*.tsbody.from()Endpoint.render()静态/动态路径(Bedrock 含 modelId)route/endpoint.tsAuth.apply()注入鉴权 Headerroute/auth.tsretry-after[-ms];最多重试 2 次route/executor.tsprotocol.stream.step()→ LLMEventroute/framing.ts二、请求 Header 明细
鉴权类 Header(按 Provider)
x-api-keyoptions.apiKey→ envANTHROPIC_API_KEYproviders/anthropic.ts:13–18anthropic-version"2023-06-01"protocols/anthropic-messages.ts:852AuthorizationBearer <key>;envOPENAI_API_KEYproviders/openai.ts:24api-keyoptions.apiKey;envAZURE_OPENAI_API_KEYproviders/azure.ts:65–72移除AuthorizationAuth.remove("authorization")providers/azure.ts:10x-goog-api-keyoptions.apiKey;envGOOGLE_GENERATIVE_AI_API_KEYproviders/google.ts:13–17AuthorizationBearer <key>;无 env 回退providers/github-copilot.ts:40,46AuthorizationBearer <key>providers/amazon-bedrock.ts:29AuthorizationAWS4-HMAC-SHA256 Credential=...protocols/utils/bedrock-auth.ts:20–45x-amz-dateprotocols/utils/bedrock-auth.tsx-amz-security-tokenprotocols/utils/bedrock-auth.tsAuthorizationBearer <key>;无 env 回退providers/openai-compatible.ts:29会话追踪 Header(
session/llm/request.ts:187–204)User-Agentopencode/<InstallationVersion>(line 18)provider === "opencode"x-opencode-project/session/request/clientx-session-affinity,X-Session-Idx-parent-session-idmodel.headers.*;pluginchat.headershookHTTP 通用 Header
content-typeapplication/jsonprotocols/shared.tsProviderShared.jsonPost()三、鉴权机制
Auth原语(route/auth.ts):所有鉴权均为惰性 Effect,真正凭据在请求时才解析。凭据优先级(
route/auth-options.ts:47–55):auth对象options.apiKey(内联/Redacted/Config)Auth.config(envVar)— 环境变量回退Auth.header("x-api-key")providers/anthropic.tsAuth.bearer()route/auth.tsAuth.header("api-key")+Auth.remove("authorization")providers/azure.tsAuth.header("x-goog-api-key")providers/google.tsaws4fetch.AwsV4Signerprotocols/utils/bedrock-auth.ts:20–45session/llm/native-runtime.ts:148–153Bedrock SigV4:用
accessKeyId + secretAccessKey + sessionToken对 URL+Body+Headers 整体签名(service="bedrock"),签名前设content-type: application/json(line 56)。OAuth 交互流程(
provider/auth.ts):authorize()→ plugin hook → 重定向;callback()持久化{type:"oauth", access, refresh, expires}或{type:"api", key}。四、Endpoint / URL 构造
/messages/chat/completions/responses/models/${modelId}:streamGenerateContent?alt=sse(bedrockruntime/redacted)<region>.amazonaws.com/model/${encodedModelId}/converse-streamhttps://<resourceName>.openai.azure.com/openai/v1/responses或/chat/completions?api-version=<ver>/chat/completions五、错误处理与重试(
route/executor.ts)Authentication(invalid);403→Authentication(insufficient-permissions);429(配额)→QuotaExceeded;429→RateLimit;400/404/422→InvalidRequest;5xx→ProviderInternal;内容政策→ContentPolicyauthorization|api[-_]?key|token|secret|signature的字段均被脱敏(executor.ts:48–54, 166–195)六、关键代码位置索引
packages/opencode/src/session/llm/request.tsLLMRequestPrep.prepare()packages/opencode/src/session/llm/native-request.tsLLMNative.model/request()packages/opencode/src/session/llm/native-runtime.tsLLMNativeRuntime.stream()packages/opencode/src/provider/auth.tsProviderAuth.Servicepackages/llm/src/route/client.tsLLMClient.stream/generate/prepare()packages/llm/src/route/auth.tsAuthinterface + constructorspackages/llm/src/route/auth-options.tsAuthOptions.bearer()packages/llm/src/route/executor.tsRequestExecutorpackages/llm/src/route/transport/http.tshttpJsonpackages/llm/src/route/transport/websocket.tsWebSocketTransport.jsonpackages/llm/src/route/endpoint.tsEndpoint.path/render()packages/llm/src/protocols/anthropic-messages.tsAnthropicMessages.protocolpackages/llm/src/protocols/openai-chat.tsOpenAIChat.protocolpackages/llm/src/protocols/openai-responses.tsOpenAIResponses.protocolpackages/llm/src/protocols/bedrock-converse.tsBedrockConverse.protocolpackages/llm/src/protocols/utils/bedrock-auth.tsbedrockSigV4Auth()packages/llm/src/providers/anthropic.tsAnthropic.configure()packages/llm/src/providers/openai.tsOpenAI.configure()packages/llm/src/providers/amazon-bedrock.tsAmazonBedrock.configure()packages/llm/src/providers/azure.tsAzure.configure()packages/llm/src/providers/github-copilot.tsGitHubCopilot.configure()packages/llm/src/providers/google.tsGoogle.configure()packages/llm/src/providers/openai-compatible.tsOpenAICompatible.configure()