codexsdk

package module
v0.0.0-...-3e9e0df Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 15, 2026 License: GPL-3.0, LGPL-3.0 Imports: 20 Imported by: 0

README

codex-sdk

A Go client library for the OpenAI Responses protocol targeting the Codex upstream, in both WebSocket and HTTP forms, exposed through a single raw-byte channel API.

Features

  • Responses WebSocket: dial, raw frame send/receive (text and binary passthrough), heartbeat keepalive, close-code passthrough.
  • Responses HTTP: request construction, non-streaming responses, streaming SSE event-frame extraction.
  • Image generation: GenerateImage (non-streaming, direct images endpoint) and GenerateImageStream (synthesized streaming with keepalive and image_generation.completed events).
  • Search: HTTPClient.Search against the /alpha/search endpoint.
  • Unified client: all endpoints go through HTTPClient methods (Do / Stream / Responses / GenerateImage / Search), with endpoints derived from the base URL.
  • Authentication: static PAT, OAuth with refresh callback, and OAuthWithRotation (rotating state machine with single-flight refresh, fatal-account detection, and 401 auto-rotation).
  • Fingerprint alignment: headers, send-frame top-level key whitelist, and client_metadata assembly aligned with the real Codex client.
  • Zero protocol parsing: the SDK delivers complete raw bytes; type/usage/ event semantics and business logic live in the gateway (go-proxy-mini).

Installation

go get github.com/is7Qin/codex-sdk

Quick Start

package main

import (
	"context"
	"fmt"

	codexsdk "github.com/is7Qin/codex-sdk"
)

func main() {
	ctx := context.Background()

	// OAuth with a rotation state machine (recommended).
	auth := codexsdk.OAuthWithRotation("refresh-token",
		codexsdk.WithOnTokenRotated(func(at, rt string) {
			// Persist the rotated tokens.
		}),
	)

	client := codexsdk.NewHTTPClient(auth)

	// Search (endpoint derived from the base URL).
	payload := []byte(`{"query":"example"}`)
	resp, err := client.Search(ctx, payload)
	if err != nil {
		panic(err)
	}
	fmt.Println(resp.StatusCode, string(resp.Raw))
}

For the full API reference, see the package documentation in doc.go.

License

Dual-licensed under LGPL-3.0 (open source) or a commercial license (LICENSE.commercial) for closed-source distribution of modified versions. Copyright (c) 2026 is7Qin.

Documentation

Overview

Package codexsdk 提供面向 Codex 上游的 OpenAI Responses 客户端库(WS + HTTP 双形态), 单一 raw 字节通道 API 面。

边界

本库只负责协议 / 传输 / 鉴权 / 伪装:

  • Responses WebSocket:Dial / 帧字节收发(文本与二进制帧原样透传)/ 心跳保活 / 关闭码透传(Close(status, reason),急断 CloseNow)
  • Responses HTTP:POST 请求构造 / 非流式响应 / 流式 SSE 事件帧提取
  • 生图(HTTPClient 方法):GenerateImage 非流式直连 images 端点 (generations/edits、JSON 非流式——上游无流式路径;输入图 Raw 字节 → data URL 直嵌、usage image_tokens 提取;端点默认 DefaultImagesURL 与 DefaultResponsesURL 同源派生,WithBaseURL 覆盖值 = 完整 generations 端点直用;传输层复用 Do:401 轮转 / 判死分类 / 错误透传零新增); GenerateImageStream 合成流式(内部调 GenerateImage,等待期间每 60s 合成 keepalive 事件——CF 524 免疫;成功后每张图合成一个 image_generation.completed 事件回调——usage 仅最后一个携带;错误原样 透传、无 partial_image 合成、无会话维持)
  • 上游 URL 内置维护:默认 DefaultResponsesURL(完整 responses 端点直用, 不再拼 /responses);WS 由该端点派生(http→ws / https→wss 换 scheme, path/query 保留,对齐真实客户端 provider.rs:92-103);WithBaseURL 覆盖 (覆盖值按完整端点语义直用)、WithQuery 追加 query(HTTP/WS 双形态)
  • 升级与请求鉴权注入(PAT 静态 / OAuth 刷新回调 / OAuthWithRotation 轮转 状态机,Auth 接口):401 自动轮转(判死分类 + 单飞 refresh + 重试一次, WS 升级 401 自动重连一次并带 DialError.Refreshed 标记)、RT 判死码集 / token 端点 401 / 账号禁用类 → 账号级终止(导出错误类型 errors.As 区分, OnAuthFatal 通知),Invalidate() / Fatal(err) 显式入口(网关解析 WS 判死 事件帧时调用)
  • 伪装层(真实 codex 客户端形态对齐,对照见 IMPERSONATION.md):默认 codex-tui UA/originator(0.147.0 + Ubuntu 指纹,用户拍板默认)、beta 头(现役唯一 2026-02-06)、头常量导出、 Send 帧顶层 key 白名单过滤(18 字段)、client_metadata 组装(WS 帧面 8 key 恒发:installation_id/session_id/thread_id/turn_id/window_id/ turn-metadata/traceparent/tracestate;HTTP 体面恒 4 key + turn_id + 条件键,不含 trace/turn-state,见 injectResponsesClientMetadata)、 透传(HTTP 头 WithHeader / WS client_metadata 任意键 WithClientMetadata,只透传不解析——如 responses-lite 标记 HeaderResponsesLite / MetaResponsesLiteKey)、会话标识握手头(WithSession)、 x-codex-turn-state(WS:升级响应头签发 → 帧内 client_metadata 回传; HTTP:仅响应侧捕获,请求不带头)、每帧新 trace 与 turn_id(UUIDv7)

SDK 零协议解析:type / usage / 事件构造与业务语义(计费、透传编排、failover、 会话粘性、内容审核)全部在网关侧(go-proxy-mini)——网关在 SDK 交付的完整 字节上自行解析。不做事件层、不做模式枚举、不做任何业务钩子。

OAuthWithRotation 边界:refresh 轮转协议 / 响应解析 / 判死分类 / 退避重试 属鉴权面,SDK 自包含("零协议解析"纪律指 responses 业务协议——type/usage/ 事件构造/计费语义不解析,鉴权错误分类不在此列)。RefreshResponse 仅非空覆盖 (缺 refresh_token 保留旧 rt,回调与后续 refresh 均用保留值);refresh 退避 SDK 自有默认(base 200ms / cap 30s / 上限 3 次,WithBackoff 可调);token 端点 401 无条件判死、RT 判死码 10 个(大小写不敏感)、账号禁用类(400 org disabled / KYC / 402)、AT 401 判死码(token_invalidated / token_revoked / detail:"Unauthorized")→ OnAuthFatal 一次性 + Fatal 态;网络/5xx/429/其他 非 2xx 退避重试,耗尽 → RefreshError(非 fatal,下次可再试)。空 refreshToken 构造 panic(构造器返回 Auth 接口无 error 通道,签名约束下唯一选择)。 refresh 请求走 http.DefaultClient(env override 换端点),不受 WithTransport / WithTimeout 影响。

性能语义(性能优先:懒构建 + 热路径低分配)

  • 无全局可变状态:连接/客户端均按需构建,心跳 goroutine 仅连接存活期间存在
  • WS 帧收发零额外分配:Send 直传帧字节(零拷贝);Recv 返回 coder/websocket 每次 Read 独立分配的读缓冲(跨次调用有效,无需拷贝即可保留)
  • 伪装层默认开启(白名单过滤 + client_metadata 注入 + 每帧 trace/turn_id), Send 的 JSON 组装开销仅在开启时发生;WithPayloadFiltering(false) / WithTraceAuto(false) / WithTurnAuto(false) 且无任何注入时回到 零拷贝零分配快速路径
  • 常驻读循环是硬性要求:Ping 与心跳依赖 Recv 处理 pong 控制帧 (coder/websocket:Ping 必须与 Reader 并发,否则等不到 pong); 网关透传编排天然常驻 Recv 循环,满足该前提
  • HTTP 流式解析零拷贝:bufio.Scanner 复用缓冲 + 行切片提取 data: 帧内容, 回调内的原始字节引用 scanner 缓冲(仅在回调执行期间有效)
  • HTTP 客户端懒构建:NewHTTPClient 零开销,首次 Do/Stream 才创建 http.Client (连接池复用;WithTransport 可注入自定义 RoundTripper)

上游协议与参考

目标协议为 OpenAI Responses WebSocket(现役唯一 beta:responses_websockets= 2026-02-06,仅 WS 握手注入;HTTP 默认不发 OpenAI-Beta,需要时 WithHeader 显式注入)。真实客户端行为对齐:WS 握手与 HTTP 请求均不发 trace 头(trace 只进每帧 client_metadata,每帧新值);session-id/thread-id/x-client-request-id/ x-codex-window-id 会话级握手头;x-codex-turn-state 是双面机制(真实源码 行号实证,防未来误删 WS 帧注入):

  • HTTP 面:真实客户端请求头携带 x-codex-turn-state(client.rs:1202 build_responses_headers(..., Some(&self.turn_state)));本 SDK HTTP 路径 不发送该头——仅响应侧捕获 + HTTPResponse.TurnState / TurnState() 暴露, 同轮回传由网关转发层(c3api)实现
  • WS 面:帧 metadata 恒带(TurnState 非空时)——真实发送路径 client.rs:1626-1631(stream_responses_websocket)在 build_ws_client_metadata (:779-792,辅助函数本身无 turn-state)之后显式追加 client_metadata.insert(X_CODEX_TURN_STATE_HEADER, ...),流入 ResponseCreateWsRequest.client_metadata(:1702-1711 帧体携带);SDK 帧注入 (client.go:548 prepareFrame)逐点一致:升级响应头签发 → 帧内回传 (Client.TurnState 缓存 + 网关 SetTurnState("") 清除,跨轮不得回传)。

responses-lite 非独立端点:与 /responses 同端点同事件集, 仅 internal 标记区分——HTTP 头 x-openai-internal-codex-responses-lite(WithHeader 透传)与 WS client_metadata 键 ws_request_header_x_openai_internal_codex_responses_lite (WithClientMetadata 透传),SDK 只透传不解析。 传输常量对齐参考实现:16MiB ReadLimit(coder 默认 32KB 过小)、 CompressionContextTakeover 压缩、WS 层 ping 心跳(30s 间隔 + 2s 超时)、 data: SSE 行提取与 [DONE] 终止、response.create 18 字段白名单、 client_metadata 恒发 8 key 集合(session_id/thread_id/turn_id 为 snake_case, trace 的 metadata key 名与头名不同)。HTTP /responses 面注入(Stream 发送前统一执行)恒 4 key(x-codex-installation-id/session_id/thread_id/ x-codex-window-id)+ 恒带 turn_id + 条件键(x-openai-subagent/ x-codex-parent-thread-id/parent_turn_id/x-codex-turn-metadata)——不含 trace/turn-state(trace 仅 WS 帧面;turn-state 的请求头属 HTTP 头面)。

依赖:github.com/coder/websocket(纯标准库实现,无 CGO)+ github.com/tidwall/gjson / github.com/tidwall/sjson(raw JSON 修补)。

Index

Constants

View Source
const (
	// RefreshTokenURL 是 OpenAI OAuth refresh_token 端点。
	// 环境变量 CODEX_REFRESH_TOKEN_URL_OVERRIDE 可覆盖(同名对齐真实客户端)。
	RefreshTokenURL = "https://auth.openai.com/oauth/token"
	// RevokeTokenURL 是 OAuth revoke 端点(真实客户端同名常量;SDK 暂未使用)。
	RevokeTokenURL = "https://auth.openai.com/oauth/revoke"
)

OAuth 轮转常量(对齐真实 codex 客户端 login/src/auth/manager.rs:192-198)。

View Source
const (
	StatusNormalClosure   = coderws.StatusNormalClosure
	StatusGoingAway       = coderws.StatusGoingAway
	StatusProtocolError   = coderws.StatusProtocolError
	StatusPolicyViolation = coderws.StatusPolicyViolation
	StatusMessageTooBig   = coderws.StatusMessageTooBig
	StatusAbnormalClosure = coderws.StatusAbnormalClosure
	StatusInternalError   = coderws.StatusInternalError
)
View Source
const (
	HeaderSessionID       = "session-id"
	HeaderThreadID        = "thread-id"
	HeaderClientRequestID = "x-client-request-id"
	HeaderInstallationID  = "x-codex-installation-id"
	HeaderWindowID        = "x-codex-window-id"
	HeaderParentThreadID  = "x-codex-parent-thread-id"
	HeaderBetaFeatures    = "x-codex-beta-features"
	HeaderTurnState       = "x-codex-turn-state"
	HeaderTurnMetadata    = "x-codex-turn-metadata"
	HeaderSubagent        = "x-openai-subagent"
	HeaderMemgenRequest   = "x-openai-memgen-request"
	HeaderOAIAAttestation = "x-oai-attestation"
	HeaderTraceparent     = "traceparent"
	HeaderTracestate      = "tracestate"
	// HeaderResponsesLite 是 responses-lite internal 标记头(值 "true";
	// 仅 gpt-5.6-sol/terra/luna 等 lite 模型触发):HTTP 请求以
	// WithHeader 透传,SDK 只透传不解析(lite 触发与请求体形态由网关决定)。
	HeaderResponsesLite = "x-openai-internal-codex-responses-lite"
)

Codex 请求头名常量(对齐真实 codex 客户端头名,供调用方组装请求头)。

View Source
const (
	// ImageStreamEventCompleted 对齐上游 image_generation_call 会话 item 的
	// completed 终态(每张图一个)。
	ImageStreamEventCompleted = "image_generation.completed"
	// ImageStreamEventKeepalive 保活事件(等待期间每 60s 一个;B64JSON/Usage
	// 恒 nil)——网关收到首个事件即发 SSE 响应头,keepalive 保证 120s 响应头
	// 超时门槛内必有字节流(CF 524 免疫)。
	ImageStreamEventKeepalive = "keepalive"
)

ImageStreamEvent 事件类型常量(GenerateImageStream 合成事件)。

View Source
const DefaultBetaWS = "2026-02-06"

DefaultBetaWS 是现役唯一的 Responses WS beta 值(真实源码全仓库唯一常量; 2026-02-04 为旧值、无真实来源),仅 WS 握手注入。

View Source
const DefaultCodexUserAgent = "codex-tui/0.147.0 (Ubuntu 24.4.0; x86_64) xterm-256color (codex-tui; 0.147.0)"

DefaultCodexUserAgent 默认 codex UA(用户拍板:codex-tui/0.147.0 + Ubuntu 指纹;真实形态 "{originator}/{version} ({os} {os_version}; {arch}) {terminal} ({originator}; {version})"——UA 前缀与 originator 保持一致)。 WithHeader("User-Agent", ...) 可覆盖。

View Source
const DefaultImagesURL = "https://chatgpt.com/backend-api/codex/images/generations"

DefaultImagesURL 是内置默认上游 images generations 完整端点 (与 DefaultResponsesURL 同源派生:chatgpt.com/backend-api/codex + /images/generations;实证见 .superpowers/sdd/sdk-image-gen-v1v3-validation.md V2:codex-api/src/endpoint/images.rs:33-54 + model-provider-info/src/lib.rs:243-257)。 WithBaseURL 可覆盖(覆盖值同样按完整 generations 端点语义直用)。

View Source
const DefaultOriginator = "codex-tui"

DefaultOriginator 默认 originator 头值(用户拍板:codex-tui; 首方值集合:codex_cli_rs / codex-tui / codex_vscode / codex_exec)。 WithHeader("Originator", ...) 可覆盖。

View Source
const DefaultResponsesURL = "https://chatgpt.com/backend-api/codex/responses"

DefaultResponsesURL 是内置默认上游 responses 完整端点(用户拍板 2026-08-12: SDK 内维护请求 url,网关不传 url;完整端点直用,SDK 不再拼 /responses)。 WS 由该端点派生(http→ws / https→wss 换 scheme,path/query 保留)。 WithBaseURL 可覆盖。

View Source
const DefaultSearchURL = "https://chatgpt.com/backend-api/codex/alpha/search"

DefaultSearchURL 是默认上游 search 完整端点形态(与 DefaultResponsesURL 同源派生:末尾 /responses 路径段 → /alpha/search——chatgpt.com 登录模式 base=https://chatgpt.com/backend-api/codex → .../codex/alpha/search)。 实证出处:codex-rs codex-api/src/endpoint/search.rs:32-34 path 常量 "alpha/search"(无前导 /v1)+ provider.rs:50-59 {base_url}/{path} 拼接 (/v1 来自 base_url)+ lib.rs:37,243-257;API key 模式派生形态 = https://api.openai.com/v1/alpha/search 一并成立。非流式、请求/响应体 opaque(SDK 零解析——alpha 端点实验性,上游变更网关免疫)。 本常量在派生路径下仅文档/测试引用:默认 c.baseURL=DefaultResponsesURL → Search 方法内 searchEndpointFrom 派生结果即本值。

View Source
const HTTPBetaResponsesV1 = "responses=v1"

HTTPBetaResponsesV1 是 Responses HTTP 的 OpenAI-Beta 参考值。 真实客户端 HTTP /responses 路径不发 OpenAI-Beta——SDK 默认同样不发, 需要时调用方以 WithHeader("OpenAI-Beta", ...) 显式注入。

View Source
const (

	// MetaResponsesLiteKey 是 responses-lite 的 client_metadata 键(值 "true";
	// 服务端约定把 ws_request_header_ 前缀键还原为请求头,与 HeaderResponsesLite
	// 同一标记)。以 WithClientMetadata 透传,SDK 只透传不解析。
	MetaResponsesLiteKey = "ws_request_header_x_openai_internal_codex_responses_lite"
)

client_metadata 内的 key 名(对齐真实 client_metadata(): session_id/thread_id/turn_id 为 snake_case 且与头名不同; x-codex-turn-state 的 metadata key 名即头名)。

Variables

View Source
var CodexPayloadFields = []string{
	"type", "model", "instructions", "previous_response_id", "input",
	"tools", "tool_choice", "parallel_tool_calls", "reasoning",
	"store", "stream", "stream_options", "include", "service_tier",
	"prompt_cache_key", "text", "generate", "client_metadata",
}

CodexPayloadFields 是 response.create 顶层 key 白名单(18 字段 + type, 对齐真实 ResponseCreateWsRequest——真实存在 stream_options)。 只读,勿修改。

View Source
var ErrEmptyFrame = errors.New("codexsdk: 帧经白名单过滤后为空")

ErrEmptyFrame 是帧经白名单过滤后无任何白名单字段时返回的错误 (空结果帧不入网)。

View Source
var ErrMessageTooBig = coderws.ErrMessageTooBig

ErrMessageTooBig 单帧超过 ReadLimit(透传 coder/websocket)。

Functions

func FilterCodexPayload

func FilterCodexPayload(raw []byte) ([]byte, error)

FilterCodexPayload 顶层 key 白名单过滤(纯函数):删除不在 CodexPayloadFields 中的顶层 key,白名单字段的值原样搬移(gjson raw, 值内容零解析,只动顶层不深入嵌套)。

空输入/非法 JSON 原样返回;无需删除时零拷贝返回原字节; 过滤后无任何白名单字段时返回 ErrEmptyFrame。

func NewUUIDv7

func NewUUIDv7() string

NewUUIDv7 生成 UUIDv7(RFC 9562:48bit 毫秒时间戳 + 版本 7 + 变体 10 + 随机数),对齐真实 codex 客户端的 session_id / thread_id / turn_id 取值。

Types

type AccountDisabledError

type AccountDisabledError struct {
	StatusCode int
	Detail     string // 判死依据(错误码或 message 文案)
	Raw        []byte // 响应体(诊断用)
}

AccountDisabledError 是账号/组织禁用错误(账号级终止): 400 + "organization has been disabled" / "identity verification is required" (KYC),或 402(deactivated_workspace / payment required,402 泛化判死)。

func (*AccountDisabledError) Error

func (e *AccountDisabledError) Error() string

type Auth

type Auth interface {
	// Authorization 返回 Authorization 请求头值(如 "Bearer xxx")。
	// 每次建连/请求调用一次;OAuth 场景的 token 刷新逻辑由调用方在
	// tokenProvider 内实现(网关侧接 OAuth 刷新后在此注入)。
	Authorization(ctx context.Context) (string, error)

	// Invalidate 显式失效:标记当前 access token 失效,下次 Authorization
	// 前刷新。OAuthWithRotation 实现为置空 at 缓存;PAT / oauthAuth
	// 无轮转状态,实现为 no-op。
	Invalidate()

	// Fatal 终止:置账号级终止状态,后续 Authorization 恒返回该错误。
	// 网关解析到 WS 判死错误事件(token_invalidated 等业务事件帧)时调用
	// (唯一跨边界点:SDK 不解析业务事件帧)。PAT / oauthAuth 实现为 no-op。
	Fatal(err error)
}

Auth 抽象上游鉴权:向 WS 升级请求 / HTTP 请求注入 Authorization 头。

实现为零分配值类型(PAT / OAuth 均为小型结构体),由 SDK 在 Dial / Do / Stream 时各调用一次取头值。

func OAuth

func OAuth(tokenProvider func(ctx context.Context) (string, error)) Auth

OAuth 构造动态令牌鉴权:每次建连/请求前调用 tokenProvider 取最新 token (返回裸 token,SDK 补 "Bearer " 前缀),刷新与缓存逻辑由调用方实现。

func OAuthWithRotation

func OAuthWithRotation(refreshToken string, opts ...OAuthOption) Auth

OAuthWithRotation 构造 OAuth 轮转鉴权:SDK 内部维护 refresh_token 轮转协议 (refresh 请求 / oauth 响应解析 / rt 轮换 / 判死分类 / 指数退避),调用方只 提供 refresh_token 材料,经 WithOnTokenRotated 接收新 at+rt、经 WithOnAuthFatal 接收账号级终止通知。

refreshToken 必传——空值构造 panic(构造器返回 Auth 接口无 error 通道, panic 是签名约束下唯一选择,防空 rt 永久失败);WithInitialAccessToken 可预置初始 at(传了直接用、401/失效才轮转,不传则首请求前先用 rt 换取)。 构造器直接返回 Auth 接口(具体类型不外露,防 copylocks:接口拷贝共享同一 装箱数据,单飞锁随指针共享);多 client 共享同一 Auth 时状态天然共享 (并发 401 单飞恰一次 refresh)。

refresh 请求走 http.DefaultClient(env override CODEX_REFRESH_TOKEN_URL_OVERRIDE 换端点)——不受 SDK WithTransport / WithTimeout 影响(传输层注入不做, 观测/代理需求以 env override 或自定义 RoundTripper 换 DefaultClient 实现)。

与 OAuth(tokenProvider) 低层回调的关系:后者保留(自定义 token 源), 前者覆盖 RT 轮转协议面。PAT(token) 无轮转语义,不受影响。

func PAT

func PAT(token string) Auth

PAT 构造静态 PAT 鉴权:Authorization: Bearer <token>。

type AuthPermanentlyRevokedError

type AuthPermanentlyRevokedError struct {
	Code string // 判死依据(token_invalidated / token_revoked / unauthorized)
	Raw  []byte // 401 响应体(诊断用)
}

AuthPermanentlyRevokedError 是 AT 路径判死错误:HTTP 401 响应体 error.code/error.type ∈ {token_invalidated, token_revoked}(token 永久作废, 非过期),或顶层 detail == "Unauthorized"(ChatGPT 内部 API 风格, token 完全无效)。匹配大小写不敏感。

func (*AuthPermanentlyRevokedError) Error

type CallbackDeliveryError

type CallbackDeliveryError struct {
	Attempts int   // 连续失败次数(达阈值)
	Err      error // 最后一次回调失败的原因
}

CallbackDeliveryError 是 OnTokenRotated 回调连续失败达阈值(D4, WithTokenRotatedRetry 可配,默认 3)触发的账号级终止错误——网关无法持久化 新令牌(at/rt 落库中断)。errors.As 可与协议级判死类型(RefreshOAuthError / AccountDisabledError / AuthPermanentlyRevokedError)区分。

func (*CallbackDeliveryError) Error

func (e *CallbackDeliveryError) Error() string

func (*CallbackDeliveryError) Unwrap

func (e *CallbackDeliveryError) Unwrap() error

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client 是 Responses WebSocket 连接(Dial 创建)。

并发语义:至多一个 goroutine 同时执行 Recv;Send / Ping 内部串行化 (coder/websocket 禁止并发写)。连接建立后的帧收发路径零额外分配。

常驻读循环是硬性要求:Ping 与心跳依赖 Recv 处理 pong 控制帧 (coder/websocket:Ping 必须与 Reader 并发,否则等不到 pong)—— 网关透传编排天然常驻 Recv 循环,满足该前提。

func Dial

func Dial(ctx context.Context, auth Auth, opts ...Option) (*Client, error)

Dial 建立到内置上游的 Responses WebSocket 连接:URL 由 SDK 维护—— 默认 DefaultResponsesURL 派生(http→ws / https→wss 换 scheme,path/query 保留,对齐真实客户端 provider.rs:92-103),WithBaseURL / WithQuery 可覆盖 与追加(query 与 WithBaseURL 同用时拼接到覆盖 URL)。

auth 注入升级请求的 Authorization 头(PAT 静态 / OAuth 每次升级取新 token)。

WS 升级 401 自动轮转(OAuthWithRotation 专属):DialError{401}(升级无 响应体不可判死)→ SDK 内单飞 refresh → 自动重连一次;仍 401 → 返回 DialError 且 Refreshed=true(网关据此知道已轮转过)。PAT/oauthAuth 不轮转 (401 直接返回 DialError,现状保持);refresh 失败(fatal / RefreshError) 经本方法透传,不被 DialError 包层吞掉(errors.As 可区分)。

连接建立后启动心跳:每 pingInterval 发送 WS 层 ping(默认 30s)。心跳依赖 调用方的常驻 Recv 循环处理 pong(见 Client 并发语义)。心跳失败视为连接 已死:立即 CloseNow 解除阻塞中的 Recv(返回网络错误),网关据此触发重连。

func (*Client) Close

func (c *Client) Close(status StatusCode, reason string) error

Close 发起关闭握手(关闭码透传,如 StatusNormalClosure;reason ≤125 字节)。 注意:关闭握手可能阻塞最多 ~10s(coder 写关闭帧 5s + 等对端关闭帧 5s), 等不起时用 CloseNow。停用心跳。重复调用返回首次结果(幂等; 对端已断开时返回 nil)。

func (*Client) CloseNow

func (c *Client) CloseNow()

CloseNow 立即断开连接(跳过关闭握手,不等待对端),用于等不起 Close 阻塞的 场景——如网关快速 failover、心跳死亡兜底。幂等;与 Close 互斥,先调用者生效。

func (*Client) Ping

func (c *Client) Ping(ctx context.Context) error

Ping 发送 WS 层 ping 并等待 pong(对端库自动回 pong;ctx 控制等待上限)。 注意:pong 由常驻 Recv 循环处理——Ping 必须在调用方同时执行 Recv 时使用。

func (*Client) Recv

func (c *Client) Recv(ctx context.Context) ([]byte, error)

Recv 读取下一帧字节(文本/二进制帧原样透传,不区分帧类型不做解析)。

data 为 coder/websocket 每次 Read 独立分配的缓冲,跨次调用有效。 对端关闭/网络断开/超 ReadLimit 时返回错误(如 coder/websocket.CloseError、 ErrMessageTooBig,网关自行分类处置)。

func (*Client) Send

func (c *Client) Send(ctx context.Context, frame []byte) error

Send 发送一帧字节(文本帧)。

伪装层默认生效(Options 可关):白名单过滤(FilterCodexPayload,过滤后为空 返回 ErrEmptyFrame 不入网)+ client_metadata 组装(CodexMeta 静态值 / trace / turn_metadata;浅合并,帧内已存在的 key 不覆盖)。 关闭过滤且无任何注入时为零拷贝零分配快速路径;Write 同步消费—— Send 返回前不得复用 frame。

func (*Client) SetTurnState

func (c *Client) SetTurnState(state string)

SetTurnState 设置 x-codex-turn-state 回传值(服务端签发 → 后续 Send 帧 client_metadata 自动回传)。轮结束时传空串清除——跨轮不得回传。 网关也可在别处观测到该值时显式设置。

func (*Client) TurnState

func (c *Client) TurnState() string

TurnState 返回当前缓存的 x-codex-turn-state(Dial 时自动捕获握手响应头)。

type CodexMeta

type CodexMeta struct {
	InstallationID string // metadata "x-codex-installation-id"(UUIDv4,账号级持久)
	SessionID      string // metadata "session_id"(UUIDv7,会话级)
	ThreadID       string // metadata "thread_id"(UUIDv7,线程级)
	TurnID         string // metadata "turn_id"(UUIDv7;为空时 SDK 每轮自动生成)
	WindowID       string // metadata "x-codex-window-id"({thread_id}:{n})
	Subagent       string // metadata "x-openai-subagent"(条件)
	ParentThreadID string // metadata "x-codex-parent-thread-id"(条件;续接/子代理)
	ParentTurnID   string // metadata "parent_turn_id"(条件;续接/子代理)
	TurnMetadata   string // metadata "x-codex-turn-metadata"
	Traceparent    string // metadata "ws_request_header_traceparent"(为空时自动生成)
	Tracestate     string // metadata "ws_request_header_tracestate"
}

CodexMeta 是 client_metadata 静态载体(值由调用方提供,SDK 只组装不生成; trace 与 turn_id 另有自动机制,见 WithTraceContext / WithTurnAuto, 也可用本结构静态注入。优先级:帧内已存在 > CodexMeta > WithSession > 自动机制)。

type CompressionMode

type CompressionMode int

CompressionMode 是消息压缩模式(默认不压缩:性能优先,LLM 流式小消息 压缩收益低、耗 CPU)。

const (
	CompressionDisabled CompressionMode = iota
	// CompressionNoContextTakeover 逐消息独立压缩(无上下文延续)。
	CompressionNoContextTakeover
	// CompressionContextTakeover 跨消息复用压缩上下文(压缩率更高)。
	CompressionContextTakeover
)

type DialError

type DialError struct {
	StatusCode int
	Err        error
	// Refreshed 表示 SDK 已尝试过 OAuth 轮转刷新后仍失败(WS 升级 401 →
	// 单飞 refresh → 自动重连一次仍失败)。网关据此知道已轮转过,避免
	// 与 SDK 各自轮转造成双份刷新。仅 401 路径可置 true;PAT/oauthAuth
	// 不轮转,恒为 false。
	Refreshed bool
}

DialError 携带 WS 升级失败信息(HTTP 状态码 + 底层错误), 网关据此区分鉴权失败(401/403)与可重试的传输失败。

func (*DialError) Error

func (e *DialError) Error() string

func (*DialError) Unwrap

func (e *DialError) Unwrap() error

type HTTPClient

type HTTPClient struct {
	// contains filtered or unexported fields
}

HTTPClient 是统一端点方法 HTTP 客户端(懒构建:NewHTTPClient 零开销, 首次 Do/Stream 才创建 http.Client,连接池复用)。端点方法族: Do/Stream(构造期 URL 固定)、GenerateImage / Search(方法内由 baseURL 派生端点)、Responses(合成非流式)。

x-codex-turn-state 仅响应侧(真实 codex 客户端行为):响应头/SSE 中的 turn-state 自动捕获,经 TurnState() / HTTPResponse.TurnState 暴露给网关; HTTP 请求不携带 x-codex-turn-state 头(头回传仅 WS 路径,见 Client)。

func NewHTTPClient

func NewHTTPClient(auth Auth, opts ...Option) *HTTPClient

NewHTTPClient 创建 Responses HTTP 客户端(端点方法族客户端——search 端点无独立构造器,经 Search 方法由 baseURL 尾段派生)。上游 URL 由 SDK 内置维护:默认 DefaultResponsesURL(完整 responses 端点,不再自动拼接 /responses),WithBaseURL 可覆盖(覆盖值同样按完整端点语义直用——传 https://selfhost/v1 将打 /v1 而非 /v1/responses,与旧版 baseURL 语义 不同,显式行为变更;自建上游请传完整 responses 端点 URL)。WithQuery 注入的 query 参数拼接到最终 URL。

func (*HTTPClient) CloseIdleConnections

func (c *HTTPClient) CloseIdleConnections()

CloseIdleConnections 关闭底层空闲连接(懒构建未使用时为零开销调用; 与首个请求并发调用安全——内部加锁)。

func (*HTTPClient) Do

func (c *HTTPClient) Do(ctx context.Context, payload []byte) (*HTTPResponse, error)

Do 发送 POST <responses 端点> 请求(端点方法族成员——search 端点经 Search 方法派生;payload 为完整 JSON 请求体,调用方决定 stream 等字段), 原样返回非流式响应。非 2xx 返回 *HTTPError。

401 自动轮转(OAuthWithRotation 专属):每次 401 先做判死分类(响应体 error_code/error_type/detail,大小写不敏感)——判死码 → Fatal 态 + 返回 *AuthPermanentlyRevokedError(不重试);非判死 → 单飞 refresh → 自动重试一次;二次 401 同样过判死分类后原样返回。PAT/oauthAuth 不轮转 (401 原样返回 HTTPError,现状保持)。fatal 类错误(refresh 路径 RefreshOAuthError / AccountDisabledError 等)经本方法透传,不被 HTTPError 包层吞掉(errors.As 可区分)。

func (*HTTPClient) GenerateImage

func (c *HTTPClient) GenerateImage(ctx context.Context, p *ImageGenParams) (*ImageResponse, error)

GenerateImage 非流式生图(codex 凭据直连 images 端点):POST {imagesBase}/images/generations|edits(JSON 非流式——上游无流式路径, 流式语义见 GenerateImageStream——合成 completed 事件包装本方法)。 edits 由 Images 非空判定;输入图 Raw 字节经 data URL 直嵌 (MIME 魔数检测 PNG/JPEG,默认 image/png——codex-rs 恒 PNG 先例)。

端点:默认 DefaultImagesURL(与 DefaultResponsesURL 同源派生); WithBaseURL 覆盖值 = 完整 generations 端点直用(与既有 HTTPClient 语义 一致);edits = 端点尾段 /images/generations → /images/edits 派生。

传输层复用 Do:鉴权头注入 / 懒构建 / 401 判死分类 + 单飞 refresh + 自动 重试一次 / fatal 类错误透传(不被 HTTPError 吞掉,errors.As 可区分)/ 非 2xx 返回 *HTTPError 原样交付(403 = 账号无生图权限,网关透传映射)。 请求头与 HTTPClient 既有默认一致(Authorization + Content-Type: application/json + codex UA/Originator);不发 OpenAI-Beta 与 x-codex-image-turn-id(实证不需要,不影响功能;需要时 WithHeader 注入)。 turn-state 不捕获(doURL 路径无捕获调用——对齐 Search 方法语义, 响应头 turn-state 不读取;网关不消费)。

func (*HTTPClient) GenerateImageStream

func (c *HTTPClient) GenerateImageStream(ctx context.Context, p *ImageGenParams, fn func(ImageStreamEvent) error) error

GenerateImageStream 流式语义(合成——上游 images 端点无流式路径):内部调 非流式 GenerateImage,等待期间(请求发出后、响应返回前)每 60s 回调一次 keepalive 事件(网关收到首个事件即发 SSE 响应头——keepalive 保证 120s 响应头超时门槛内必有字节流,CF 524 免疫);响应返回后停 ticker,为每张图 合成一个 "image_generation.completed" 事件回调(B64JSON 各自;Usage 仅 最后一个事件携带——对齐上游 completed 事件语义)→ 结束(发完即止, 无会话维持)。

回调式对齐既有 Stream 风格:fn 返回错误立即终止并透传该错误(keepalive 回调错误取消在途请求且优先返回)。错误路径同 GenerateImage:生成失败 → completed 回调不调用、错误原样透传(HTTPError / 鉴权 fatal 五类 / refresh 失败均不包装)。Data 为空 → 无 completed 事件直接返回。无 partial_image 合成(无 wire 来源)。

func (*HTTPClient) Responses

func (c *HTTPClient) Responses(ctx context.Context, payload []byte) (*HTTPResponse, error)

Responses 合成非流式 responses 调用:内部无条件覆盖 stream:true(上游硬性 要求——payload 任意 stream 值(含显式 false)均覆盖为 true,非流式语义由 聚合保证),SSE 事件流聚合重组为完整响应体返回。 注入机制:sjson.SetBytes 同款(对齐 injectClientMetadataKeys 先例——非法 JSON payload 放弃注入保持原样,上游 400 透传);client_metadata 注入 (恒 4 key + turn_id + 条件键,对齐真实 client_metadata()—— responses_metadata.rs:255-288)在 Stream 发送前统一执行 (injectResponsesClientMetadata——非流式聚合与流式路径同一注入点)。 与 Do 的区别:Do 是通用非流式 POST(对 codex responses 端点 400 不可用); 本方法走 Stream 合成——网关以非流式语义消费(一次性响应)。 返回 HTTPResponse{StatusCode, Raw, TurnState}(与 Do 同形态;TurnState 读 c.TurnState()——Stream 内部已捕获(http.go captureTurnState),非 2xx 路径 本就为空)。 错误透传同 Stream(HTTPError 信封 / fatal 五类 / 401 判死轮转)。

func (*HTTPClient) Search

func (c *HTTPClient) Search(ctx context.Context, payload []byte) (*HTTPResponse, error)

Search 非流式搜索(codex 凭据直连 alpha/search 端点):POST {searchEndpoint},请求/响应体 opaque(SDK 零解析——alpha 端点实验性, 上游变更网关免疫;HTTPResponse.Raw 原样交付)。

端点:由 c.baseURL(responses 完整端点)尾段派生——默认 DefaultResponsesURL → DefaultSearchURL;WithBaseURL 覆盖值同样按 responses 端点语义派生(网关 cred.BaseURL 直传即用;URL 派生逻辑留 SDK——网关零拼装)。

传输层复用 doURL:鉴权头注入 / 懒构建 / 401 判死分类 + 单飞 refresh + 自动重试一次 / fatal 类错误透传(不被 HTTPError 吞掉,errors.As 可区分)/ 非 2xx 返回 *HTTPError 原样交付。请求头与 HTTPClient 既有默认一致 (Authorization + Content-Type: application/json + codex UA/Originator); 不发 OpenAI-Beta 与 x-codex-turn-metadata(网关不转发,与 resp HTTP 路径 现状一致;需要时 WithHeader 注入)。 turn-state 不捕获(对齐 GenerateImage——doURL 路径不捕获, HTTPResponse.TurnState 恒空,网关不消费)。

func (*HTTPClient) Stream

func (c *HTTPClient) Stream(ctx context.Context, payload []byte, fn func(raw []byte) error) error

Stream 发送 POST 请求并提取 SSE 事件帧:逐 data: 行交付原始字节(零拷贝 行切片——回调内的字节引用 scanner 复用缓冲,仅在回调执行期间有效; 跨回调保留需自行拷贝),[DONE] 标记流正常终止。

发送前统一注入 client_metadata(对齐真实 codex client_metadata()—— responses_metadata.rs:255-288;见 injectResponsesClientMetadata)。 Responses 内部调 Stream 走同一注入点,避免两路径重复;Do 是通用非流式 POST 不注入(GenerateImage/Search 各自端点不受影响)。

fn 返回错误立即终止读取并透传该错误。非 2xx 返回 *HTTPError; 401 自动轮转语义同 Do。

func (*HTTPClient) TurnState

func (c *HTTPClient) TurnState() string

TurnState 返回最近一次响应捕获的 x-codex-turn-state(仅响应侧暴露—— HTTP 请求不携带该头,头回传仅 WS 路径)。

type HTTPError

type HTTPError struct {
	StatusCode int
	Raw        []byte
}

HTTPError 是上游非 2xx 响应(状态码 + 错误体原样交付,error 信封由网关解析)。

func (*HTTPError) Error

func (e *HTTPError) Error() string

type HTTPResponse

type HTTPResponse struct {
	StatusCode int
	Raw        []byte // 完整响应体
	TurnState  string // 响应头 x-codex-turn-state(服务端签发,仅响应侧暴露)
}

HTTPResponse 是 HTTP 非流式响应(原样交付,不做字段解析——字段由网关 在完整字节上自行解析;Do / Search 方法共用)。

type Image

type Image struct {
	B64JSON *string `json:"b64_json"`
}

Image 是单张生成结果(实证:b64_json 为原始 PNG base64,无 data URL 前缀)。

type ImageGenParams

type ImageGenParams struct {
	Model      string  // 生图模型(gpt-image-2 等;必填)
	Prompt     string  // 必填
	N          *int    // nil = 不发 n 字段(上游默认 1;codex 客户端恒 None,SDK 按需透传)
	Size       *string // nil = 不发 size 字段(上游默认 "auto")
	Quality    *string // nil = 不发 quality 字段(上游默认 "auto");枚举 low|medium|high|auto
	Background *string // nil = 不发 background 字段(上游默认 "auto");枚举 transparent|opaque|auto
	// edits 专属:
	Images []ImageRef // 输入图片(≤5,codex-rs MAX_EDIT_IMAGES);generations 恒空
}

ImageGenParams 生图参数(generations/edits 共参;网关从 HTTP 请求 JSON body / multipart form 解析后传入——SDK 不做 HTTP 协议解析)。 参数集 = codex-rs 实证收敛(prompt/model/size/quality/background/n); moderation/output_format/output_compression/partial_images/style 零实证——不映射。

type ImageRef

type ImageRef struct {
	ImageURL *string // 完整 URL 或 base64 data URL(优先于 Raw)
	Raw      []byte  // 原始文件字节 → SDK 内部转 data URL(into_data_url 同款)
}

ImageRef 是 edits 单张输入图(两者取一;generations 不使用)。

type ImageResponse

type ImageResponse struct {
	Created      int64       `json:"created"`
	Background   *string     `json:"background"`
	Data         []Image     `json:"data"`
	OutputFormat *string     `json:"output_format"`
	Quality      *string     `json:"quality"`
	Size         *string     `json:"size"`
	Usage        *ImageUsage `json:"usage"` // 上游未提供 → nil(网关 per-image 分量兜底)
}

ImageResponse 是标准 ImagesResponse(对齐上游 images 端点响应)—— 网关直接据此计费(data 长 = 张数、usage 提取 image_tokens)与序列化转发。 与 API-key 直连响应同一口径(网关统一计费逻辑)。

type ImageStreamEvent

type ImageStreamEvent struct {
	Type    string      // "image_generation.completed" | "keepalive"
	B64JSON *string     // completed:原始 PNG base64(无 data URL 前缀);keepalive 恒 nil
	Usage   *ImageUsage // 仅最后一个 completed 事件携带;keepalive 恒 nil
}

ImageStreamEvent 是 GenerateImageStream 的合成流式事件(用户裁决:codex 专属合成归 SDK,网关统一透传)。completed:每张图一个(带 b64_json; usage 仅最后一个事件携带——对齐上游 completed 事件语义);keepalive: 等待期间保活(B64JSON/Usage 恒 nil)。partial_image 不合成——无 wire 来源。

type ImageUsage

type ImageUsage struct {
	InputTokens       int64 `json:"input_tokens"`
	InputImageTokens  int64 `json:"input_image_tokens"` // input_tokens_details.image_tokens
	OutputTokens      int64 `json:"output_tokens"`
	OutputImageTokens int64 `json:"output_image_tokens"` // output_tokens_details.image_tokens
}

ImageUsage 是生图 token 用量(由上游嵌套 input/output_tokens_details. image_tokens 提取为平铺四字段,与网关 API-key 直连同一计费口径)。

type OAuthOption

type OAuthOption func(*oauthConfig)

OAuthOption 配置 OAuthWithRotation。

func WithBackoff

func WithBackoff(cap time.Duration, maxAttempts int) OAuthOption

WithBackoff 设置 refresh 退避:cap 为延迟封顶(默认 30s;0 表示不封顶), maxAttempts 为总尝试次数上限(默认 3;<=0 关闭重试,单次尝试后即返回)。 base 固定 200ms(指数翻倍)。

func WithInitialAccessToken

func WithInitialAccessToken(at string) OAuthOption

WithInitialAccessToken 预置初始 access token(裸 token):传了直接用, 401/失效才轮转;不传则首请求前先用 refresh_token 换取。

func WithOnAuthFatal

func WithOnAuthFatal(fn func(err error)) OAuthOption

WithOnAuthFatal 设置账号级终止回调(至多一次):SDK 判定账号级不可重试 (RT 判死码 / token 端点 401 / 账号禁用 / 回调连续失败达阈值)时通知网关 标记账号失效。网关自行调用 Auth.Fatal 的显式终止不触发本回调。

func WithOnTokenRotated

func WithOnTokenRotated(fn func(at, rt string)) OAuthOption

WithOnTokenRotated 设置轮转回调:每次 refresh 成功产出新 at+rt 时同步调用 (成功投递时每轮转至多一次;回调在单飞内执行,阻塞并发等待者——应快速 返回,本地 upsert 毫秒级)。rt 为 SDK 内存有效值——响应缺 refresh_token 时保留旧 rt,回调收到该保留值(网关盲写 upsert 不落空,幂等)。回调失败 (panic)不阻塞请求:本次 at 放行,下次 refresh 前重试投递,连续失败达 WithTokenRotatedRetry 阈值 → OnAuthFatal(CallbackDeliveryError)。

func WithRefreshTimeout

func WithRefreshTimeout(d time.Duration) OAuthOption

WithRefreshTimeout 设置单次 refresh 超时(默认 10s)。超时/取消不污染单飞 ——等待者收到错误,下次可重试。

func WithTokenRotatedRetry

func WithTokenRotatedRetry(max int) OAuthOption

WithTokenRotatedRetry 设置 OnTokenRotated 回调失败重试阈值(默认 3): 连续失败达阈值 → OnAuthFatal。

type Option

type Option func(*options)

Option 配置 Dial / NewHTTPClient。

func WithBaseURL

func WithBaseURL(u string) Option

WithBaseURL 覆盖内置上游 URL(默认 DefaultResponsesURL)——覆盖值按完整 端点语义直用:SDK 不再自动拼接 /responses(与旧版 baseURL 参数语义不同, 显式行为变更——自建上游传 https://selfhost/v1 将打 /v1 而非 /v1/responses,避免静默 404 请传完整端点)。HTTP 与 WS(Dial 由该值派生 scheme)双形态生效;Search 方法由该值尾段派生 search 端点。

func WithBeta

func WithBeta(version string) Option

WithBeta 设置 Responses WS 的 beta 版本(默认 DefaultBetaWS=2026-02-06, 现役唯一真实值),注入 "OpenAI-Beta: responses_websockets=<version>"。 仅作用于 WS 握手——HTTP 默认不发 OpenAI-Beta, 需要时以 WithHeader("OpenAI-Beta", ...) 显式注入。

func WithClientMetadata

func WithClientMetadata(key, value string) Option

WithClientMetadata 注入 client_metadata 任意键值(透传面:SDK 只透传不解析, 键名由调用方自定或引用 Meta* 常量,如 MetaResponsesLiteKey="true")。 与其余注入同优先级——帧内已存在的 key 不覆盖;多次调用为多键注入。 仅作用于 WS——HTTP 无 client_metadata,对应请求头透传用 WithHeader。

func WithCodexMeta

func WithCodexMeta(meta CodexMeta) Option

WithCodexMeta 设置 client_metadata 静态载体(值由调用方提供, SDK 只组装不生成;帧内已存在的 key 不覆盖)。

func WithCompression

func WithCompression(mode CompressionMode) Option

WithCompression 设置 WS 压缩模式(默认 CompressionDisabled)。

func WithHeader

func WithHeader(key, value string) Option

WithHeader 注入附加请求头(WS 升级 / HTTP 请求通用),覆盖默认头 (如 WithHeader("User-Agent", ...) 覆盖默认 codex UA);同名多次调用为扩展。

func WithMaxLineSize

func WithMaxLineSize(n int) Option

WithMaxLineSize 设置 HTTP SSE 单行上限(默认 16MiB)。

func WithPayloadFiltering

func WithPayloadFiltering(enabled bool) Option

WithPayloadFiltering 开关 Send 帧的顶层 key 白名单过滤(默认开; 关闭后帧原样直写,零分配快速路径)。

func WithPingInterval

func WithPingInterval(d time.Duration) Option

WithPingInterval 设置 WS 心跳间隔(默认 30s;0 或负值禁用心跳)。

func WithQuery

func WithQuery(key, value string) Option

WithQuery 注入 URL query 参数(HTTP 请求与 WS 升级 URL 双形态生效; 与 WithBaseURL 同用时拼接到覆盖 URL;base URL 自带 query 时追加而非覆盖)。 保留面非对齐面——真实客户端 Responses 本无 query 版本参数 (IMPERSONATION.md:130),本选项为既有调用方注入能力(beta 等)的延续。

func WithReadLimit

func WithReadLimit(n int64) Option

WithReadLimit 设置 WS 单帧最大字节数(默认 16MiB;-1 表示不设限)。

func WithSession

func WithSession(s Session) Option

WithSession 设置会话级标识(真实客户端 WS 握手恒带 x-client-request-id / session-id / thread-id / x-codex-window-id): 注入握手头,并补齐帧内 client_metadata 的 session_id / thread_id / x-codex-window-id(CodexMeta 中同 key 优先)。会话内稳定。

func WithTimeout

func WithTimeout(d time.Duration) Option

WithTimeout 设置 HTTP 客户端总超时(http.Client.Timeout;默认 0 不设限)。

func WithTraceAuto

func WithTraceAuto(enabled bool) Option

WithTraceAuto 开关每帧 trace 自动生成(默认开:每个 Send 帧生成新的 W3C traceparent 并注入 client_metadata,与真实客户端每请求新 span 一致)。 仅作用于 WS。

func WithTraceContext

func WithTraceContext(tc TraceContext) Option

WithTraceContext 注入外部 trace context(每帧注入 Send 帧 client_metadata 的 trace key;禁用自动生成)。仅作用于 WS—— 真实客户端握手头与 HTTP 请求均不发 trace。

func WithTransport

func WithTransport(rt http.RoundTripper) Option

WithTransport 注入 HTTP 传输层(自定义 RoundTripper,如代理);默认使用 http.DefaultTransport(连接池复用)。

func WithTurnAuto

func WithTurnAuto(enabled bool) Option

WithTurnAuto 开关 turn_id 自动生成(默认开:每个 Send 帧生成新的 UUIDv7 注入 client_metadata.turn_id;CodexMeta.TurnID 静态值优先)。 关闭后(且无静态值)帧内不带 turn_id。

func WithTurnMetadata

func WithTurnMetadata(provider func(turn uint64) string) Option

WithTurnMetadata 设置 turn_metadata 内容提供回调:每次 Send 计一轮 turn (从 1 起自增),以当前 turn 序号调用回调,返回值(协议约定格式的字符串, 可为空=不注入)组装进 client_metadata."x-codex-turn-metadata"。 优先级:帧内已存在 > CodexMeta.TurnMetadata > 本回调。

type RefreshError

type RefreshError struct {
	Attempts int   // 已尝试次数(耗尽时 = 上限)
	Err      error // 最后一次尝试的错误
}

RefreshError 是 refresh 可重试类失败(网络错误 / 5xx / 429 / RT 端点其他 非 2xx / 响应缺 access_token)——非 fatal,下次调用可再试,不触发 OnAuthFatal。指数退避耗尽后返回。

func (*RefreshError) Error

func (e *RefreshError) Error() string

func (*RefreshError) Unwrap

func (e *RefreshError) Unwrap() error

type RefreshOAuthError

type RefreshOAuthError struct {
	Code string // 响应体 error.code;端点 401 无错误码时为 "unauthorized"
	Raw  []byte // 响应体(诊断用)
}

RefreshOAuthError 是 refresh 端点判死错误(RT 路径账号级终止,需重新授权)。 触发:响应体错误码 ∈ RT 判死码集(invalid_grant / invalid_refresh_token / refresh_token_expired / refresh_token_reused / refresh_token_invalidated / app_session_terminated / token_expired / invalid_client / unauthorized_client / access_denied,大小写不敏感),或 token 端点响应状态 401(无条件判死,无论错误码——对齐 codex manager.rs:1537-1538)。

func (*RefreshOAuthError) Error

func (e *RefreshOAuthError) Error() string

type Session

type Session struct {
	SessionID       string // 头 session-id / metadata session_id
	ThreadID        string // 头 thread-id / metadata thread_id
	WindowID        string // 头 x-codex-window-id / metadata x-codex-window-id({thread_id}:{n},n 自 0 起)
	ClientRequestID string // 头 x-client-request-id(空则用 ThreadID)
}

Session 是会话级标识(真实 codex 客户端 WS 握手恒带 x-client-request-id / session-id / thread-id / x-codex-window-id)。 会话内稳定,新会话换新值(UUIDv7,见 NewUUIDv7)。WithSession 注入 握手头,并补齐帧内 client_metadata 的 session_id / thread_id / x-codex-window-id(CodexMeta 中同 key 优先)。

type StatusCode

type StatusCode = coderws.StatusCode

StatusCode 是 WebSocket 关闭码(透传 coder/websocket.StatusCode), Close 关闭码透传 API。

type TraceContext

type TraceContext struct {
	Traceparent string // 如 "00-<32位hex trace id>-<16位hex parent id>-01"
	Tracestate  string // 可为空(调用方可补充 vendor 数据)
}

TraceContext 是 W3C trace context(仅注入 WS 帧内 client_metadata—— 真实客户端 WS 握手与 HTTP 请求均不发 trace 头)。

func NewTraceContext

func NewTraceContext() TraceContext

NewTraceContext 生成新的 W3C trace context(每次调用新链路 id,crypto/rand)。

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL