constants.go 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. // Package claude provides constants and helpers for Claude API integration.
  2. package claude
  3. // Claude Code 客户端相关常量
  4. // Beta header 常量
  5. //
  6. // 这里的常量对齐真实 Claude Code CLI 的最新流量(截至 2026-04)。
  7. // 选型参考:与 Parrot (src/transform/cc_mimicry.py) 的 BETAS 保持一致,
  8. // 原因:Anthropic 上游会基于 anthropic-beta 的完整集合判定请求来源;
  9. // 缺少任何"官方 Claude Code 请求才会带"的 beta,都会被降级到第三方额度,
  10. // 对应报错:`Third-party apps now draw from your extra usage, not your plan limits.`
  11. const (
  12. BetaOAuth = "oauth-2025-04-20"
  13. BetaClaudeCode = "claude-code-20250219"
  14. BetaInterleavedThinking = "interleaved-thinking-2025-05-14"
  15. BetaFineGrainedToolStreaming = "fine-grained-tool-streaming-2025-05-14"
  16. BetaTokenCounting = "token-counting-2024-11-01"
  17. BetaContext1M = "context-1m-2025-08-07"
  18. BetaFastMode = "fast-mode-2026-02-01"
  19. // 新增(对齐官方 CLI 2.1.9x 以来的流量)
  20. BetaPromptCachingScope = "prompt-caching-scope-2026-01-05"
  21. BetaEffort = "effort-2025-11-24"
  22. BetaRedactThinking = "redact-thinking-2026-02-12"
  23. BetaContextManagement = "context-management-2025-06-27"
  24. BetaThinkingBindingControls = "thinking-binding-controls-2026-08-01"
  25. BetaExtendedCacheTTL = "extended-cache-ttl-2025-04-11"
  26. // server-side refusal fallback beta 字段族(beta Messages API 专有)。
  27. // 客户端(Claude Code / SDK / OpenCode 等)会默认透传 body.fallbacks /
  28. // body.fallback_credit_token,上游仅在 anthropic-beta 携带对应 token 时接受;
  29. // 缺 token 时 Pydantic 拒收:"fallbacks: Extra inputs are not permitted"。
  30. // 仅用于 sanitize 的条件判断(strip-or-keep),禁止加入
  31. // FullClaudeCodeMimicryBetas / DefaultBetaHeader / APIKeyBetaHeader /
  32. // Bedrock 白名单:server-side fallback 会换模型、改计费,不能默认打开。
  33. BetaServerSideFallback = "server-side-fallback-2026-07-01"
  34. BetaFallbackCredit = "fallback-credit-2026-07-01"
  35. BetaFallbackCreditLegacy = "fallback-credit-2026-06-01"
  36. )
  37. // DroppedBetas 是转发时需要从 anthropic-beta header 中移除的 beta token 列表。
  38. // 这些 token 是客户端特有的,不应透传给上游 API。
  39. var DroppedBetas = []string{}
  40. // DefaultBetaHeader Claude Code 客户端默认的 anthropic-beta header
  41. const DefaultBetaHeader = BetaClaudeCode + "," + BetaOAuth + "," + BetaInterleavedThinking + "," + BetaFineGrainedToolStreaming
  42. // MessageBetaHeaderNoTools /v1/messages 在无工具时的 beta header
  43. //
  44. // NOTE: Claude Code OAuth credentials are scoped to Claude Code. When we "mimic"
  45. // Claude Code for non-Claude-Code clients, we must include the claude-code beta
  46. // even if the request doesn't use tools, otherwise upstream may reject the
  47. // request as a non-Claude-Code API request.
  48. const MessageBetaHeaderNoTools = BetaClaudeCode + "," + BetaOAuth + "," + BetaInterleavedThinking
  49. // MessageBetaHeaderWithTools /v1/messages 在有工具时的 beta header
  50. const MessageBetaHeaderWithTools = BetaClaudeCode + "," + BetaOAuth + "," + BetaInterleavedThinking
  51. // CountTokensBetaHeader count_tokens 请求使用的 anthropic-beta header
  52. const CountTokensBetaHeader = BetaClaudeCode + "," + BetaOAuth + "," + BetaInterleavedThinking + "," + BetaTokenCounting
  53. // HaikuBetaHeader Haiku 模型在 OAuth 真实客户端透传路径上的默认 anthropic-beta header。
  54. // OAuth mimic 路径统一使用 FullClaudeCodeMimicryBetas。
  55. const HaikuBetaHeader = BetaOAuth + "," + BetaInterleavedThinking
  56. // APIKeyBetaHeader API-key 账号建议使用的 anthropic-beta header(不包含 oauth)
  57. const APIKeyBetaHeader = BetaClaudeCode + "," + BetaInterleavedThinking + "," + BetaFineGrainedToolStreaming
  58. // APIKeyHaikuBetaHeader Haiku 模型在 API-key 账号下使用的 anthropic-beta header(不包含 oauth / claude-code)
  59. const APIKeyHaikuBetaHeader = BetaInterleavedThinking
  60. // DefaultCacheControlTTL 是网关代理为自己生成的 cache_control 块默认使用的 ttl。
  61. // 真实 Claude Code CLI 当前使用 "1h",但本仓策略是"客户端透传 ttl 优先;
  62. // 客户端缺省时统一使用 5m",这样既不浪费 1h 缓存额度,也保留客户端自定义能力。
  63. const DefaultCacheControlTTL = "5m"
  64. // CLICurrentVersion 是内置的 Claude Code CLI 伪装版本号基线(三段 semver)。
  65. // 用于 billing attribution block 中的 cc_version=X.Y.Z.{fp} 前缀以及 fingerprint 计算。
  66. // 必须与 DefaultHeaders["User-Agent"] 中的版本号严格一致;不一致会被 Anthropic 判第三方。
  67. //
  68. // ⚠️ 读取实际生效的版本号请用 CLIVersion(),它会叠加 SUB2API_CLAUDE_CLI_VERSION 覆盖。
  69. // 直接引用本常量只在"表达内置基线"时才正确(例如覆盖值的下限校验)。
  70. const CLICurrentVersion = "2.1.258"
  71. // FullClaudeCodeMimicryBetas 返回最"像"真实 Claude Code CLI 的完整 beta 列表,
  72. // 用于 OAuth 账号伪装成 Claude Code 时使用。
  73. // 顺序与真实 CLI 抓包一致。
  74. //
  75. // 使用建议:
  76. // - OAuth mimic:所有模型(包括 Haiku)都使用这整份列表。
  77. // - OAuth 真实客户端透传:保留客户端 beta;未提供时使用模型对应默认值。
  78. // - API-key 账号:不要使用本函数,参见 APIKeyBetaHeader。
  79. // - 不默认加入 redact-thinking,避免上游抹除 thinking 内容;客户端显式传入时由合并逻辑保留。
  80. func FullClaudeCodeMimicryBetas() []string {
  81. return []string{
  82. BetaClaudeCode,
  83. BetaOAuth,
  84. BetaInterleavedThinking,
  85. BetaPromptCachingScope,
  86. BetaEffort,
  87. BetaContextManagement,
  88. BetaThinkingBindingControls,
  89. BetaExtendedCacheTTL,
  90. }
  91. }
  92. // DefaultHeaders 是 Claude Code 客户端默认请求头。
  93. var DefaultHeaders = map[string]string{
  94. // Keep these in sync with recent Claude CLI traffic to reduce the chance
  95. // that Claude Code-scoped OAuth credentials are rejected as "non-CLI" usage.
  96. // 版本参考:对齐 Parrot (src/transform/cc_mimicry.py:49) 的 CLI_USER_AGENT。
  97. "User-Agent": "claude-cli/" + CLIVersion() + " (external, cli)",
  98. "X-Stainless-Lang": "js",
  99. "X-Stainless-Package-Version": "0.94.0",
  100. "X-Stainless-OS": "Linux",
  101. "X-Stainless-Arch": "arm64",
  102. "X-Stainless-Runtime": "node",
  103. "X-Stainless-Runtime-Version": "v24.3.0",
  104. "X-Stainless-Retry-Count": "0",
  105. "X-Stainless-Timeout": "600",
  106. "X-App": "cli",
  107. "Anthropic-Dangerous-Direct-Browser-Access": "true",
  108. }
  109. // Model 表示一个 Claude 模型
  110. type Model struct {
  111. ID string `json:"id"`
  112. Type string `json:"type"`
  113. DisplayName string `json:"display_name"`
  114. CreatedAt string `json:"created_at"`
  115. }
  116. // DefaultModels Claude Code 客户端支持的默认模型列表
  117. var DefaultModels = []Model{
  118. {
  119. ID: "claude-fable-5-1",
  120. Type: "model",
  121. DisplayName: "Claude Fable 5.1",
  122. CreatedAt: "2026-09-01T00:00:00Z",
  123. },
  124. {
  125. ID: "claude-fable-5",
  126. Type: "model",
  127. DisplayName: "Claude Fable 5",
  128. CreatedAt: "2026-06-09T00:00:00Z",
  129. },
  130. {
  131. ID: "claude-opus-4-5-20251101",
  132. Type: "model",
  133. DisplayName: "Claude Opus 4.5",
  134. CreatedAt: "2025-11-01T00:00:00Z",
  135. },
  136. {
  137. ID: "claude-opus-4-6",
  138. Type: "model",
  139. DisplayName: "Claude Opus 4.6",
  140. CreatedAt: "2026-02-06T00:00:00Z",
  141. },
  142. {
  143. ID: "claude-opus-4-7",
  144. Type: "model",
  145. DisplayName: "Claude Opus 4.7",
  146. CreatedAt: "2026-04-17T00:00:00Z",
  147. },
  148. {
  149. ID: "claude-opus-4-8",
  150. Type: "model",
  151. DisplayName: "Claude Opus 4.8",
  152. CreatedAt: "2026-05-29T00:00:00Z",
  153. },
  154. {
  155. ID: "claude-opus-5",
  156. Type: "model",
  157. DisplayName: "Claude Opus 5",
  158. CreatedAt: "2026-07-25T00:00:00Z",
  159. },
  160. {
  161. ID: "claude-sonnet-5",
  162. Type: "model",
  163. DisplayName: "Claude Sonnet 5",
  164. CreatedAt: "2026-07-01T00:00:00Z",
  165. },
  166. {
  167. ID: "claude-sonnet-4-6",
  168. Type: "model",
  169. DisplayName: "Claude Sonnet 4.6",
  170. CreatedAt: "2026-02-18T00:00:00Z",
  171. },
  172. {
  173. ID: "claude-sonnet-4-5-20250929",
  174. Type: "model",
  175. DisplayName: "Claude Sonnet 4.5",
  176. CreatedAt: "2025-09-29T00:00:00Z",
  177. },
  178. {
  179. ID: "claude-haiku-4-5-20251001",
  180. Type: "model",
  181. DisplayName: "Claude Haiku 4.5",
  182. CreatedAt: "2025-10-01T00:00:00Z",
  183. },
  184. }
  185. // DefaultModelIDs 返回默认模型的 ID 列表
  186. func DefaultModelIDs() []string {
  187. ids := make([]string, len(DefaultModels))
  188. for i, m := range DefaultModels {
  189. ids[i] = m.ID
  190. }
  191. return ids
  192. }
  193. // DefaultTestModel 测试时使用的默认模型
  194. const DefaultTestModel = "claude-sonnet-4-5-20250929"
  195. // ModelIDOverrides Claude OAuth 请求需要的模型 ID 映射
  196. var ModelIDOverrides = map[string]string{
  197. "claude-sonnet-4-5": "claude-sonnet-4-5-20250929",
  198. "claude-opus-4-5": "claude-opus-4-5-20251101",
  199. "claude-haiku-4-5": "claude-haiku-4-5-20251001",
  200. }
  201. // ModelIDReverseOverrides 用于将上游模型 ID 还原为短名
  202. var ModelIDReverseOverrides = map[string]string{
  203. "claude-sonnet-4-5-20250929": "claude-sonnet-4-5",
  204. "claude-opus-4-5-20251101": "claude-opus-4-5",
  205. "claude-haiku-4-5-20251001": "claude-haiku-4-5",
  206. }
  207. // NormalizeModelID 根据 Claude OAuth 规则映射模型
  208. func NormalizeModelID(id string) string {
  209. if id == "" {
  210. return id
  211. }
  212. if mapped, ok := ModelIDOverrides[id]; ok {
  213. return mapped
  214. }
  215. return id
  216. }
  217. // DenormalizeModelID 将上游模型 ID 转换为短名
  218. func DenormalizeModelID(id string) string {
  219. if id == "" {
  220. return id
  221. }
  222. if mapped, ok := ModelIDReverseOverrides[id]; ok {
  223. return mapped
  224. }
  225. return id
  226. }