@bitkyc08/opencodex 2.89.0 → 2.90.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. package/gui/dist/assets/App-DgxkE6Md.js +58 -0
  2. package/gui/dist/assets/{Tray-7z1COnmz.js → Tray-DbTNc_88.js} +1 -1
  3. package/gui/dist/assets/{index-uchD-ngf.js → index-TmaHa54u.js} +5 -5
  4. package/gui/dist/assets/quota-summary-B16x5DZZ.js +1 -0
  5. package/gui/dist/index.html +1 -1
  6. package/package.json +2 -2
  7. package/src/adapters/base.ts +4 -0
  8. package/src/adapters/claude-cli/adapter.ts +13 -7
  9. package/src/adapters/claude-cli/usage-admission.ts +14 -2
  10. package/src/adapters/coding-agent/turn.ts +14 -4
  11. package/src/adapters/cursor/protobuf-request.ts +3 -0
  12. package/src/adapters/google-progress-history.ts +19 -1
  13. package/src/adapters/google.ts +28 -9
  14. package/src/adapters/image.ts +5 -3
  15. package/src/adapters/input-media-guard.ts +5 -2
  16. package/src/adapters/kiro-refusal.ts +41 -1
  17. package/src/adapters/ollama-native.ts +1 -0
  18. package/src/adapters/openai-chat/messages.ts +34 -4
  19. package/src/adapters/openai-chat/passthrough.ts +37 -4
  20. package/src/adapters/openai-chat/reasoning-replay.ts +98 -13
  21. package/src/adapters/openai-chat/serialized-tool-call-content.ts +95 -134
  22. package/src/adapters/openai-chat/serialized-tool-call-markup.ts +108 -0
  23. package/src/adapters/openai-chat/standalone-bare-tool-calls.ts +136 -0
  24. package/src/adapters/openai-chat.ts +7 -6
  25. package/src/adapters/openai-responses/opengateway-input.ts +139 -0
  26. package/src/adapters/openai-responses/passthrough.ts +5 -1
  27. package/src/adapters/openai-responses/transport.ts +13 -1
  28. package/src/claude/desktop-3p-library.ts +43 -3
  29. package/src/claude/desktop-3p.ts +20 -10
  30. package/src/claude/desktop-picker-profile.ts +18 -9
  31. package/src/claude/desktop-remote-store-io.ts +2 -2
  32. package/src/cli/ensure-desktop-cold-start.ts +2 -2
  33. package/src/codex/account-lifecycle.ts +19 -6
  34. package/src/codex/account-store.ts +27 -8
  35. package/src/codex/account-usability.ts +4 -1
  36. package/src/codex/auth-api/account-list.ts +10 -5
  37. package/src/codex/auth-api/account-pause-group.ts +2 -22
  38. package/src/codex/auth-api/login-collision.ts +59 -0
  39. package/src/codex/auth-api/login-flow.ts +12 -7
  40. package/src/codex/auth-api/pool-mode-gate.ts +81 -13
  41. package/src/codex/auth-collision.ts +31 -4
  42. package/src/codex/auth-context.ts +48 -6
  43. package/src/codex/cli-update-plan.ts +18 -3
  44. package/src/codex/collision-identity.ts +78 -0
  45. package/src/codex/main-account-hard-lock.ts +14 -0
  46. package/src/codex/routing/cooldown-math.ts +5 -0
  47. package/src/codex/routing/failure-window.ts +61 -9
  48. package/src/codex/routing.ts +4 -3
  49. package/src/codex/shim-diagnostics.ts +2 -1
  50. package/src/codex/shim-fingerprint.ts +11 -2
  51. package/src/codex/shim-templates.ts +16 -5
  52. package/src/codex/shim-windows-refresh.ts +224 -0
  53. package/src/codex/shim.ts +45 -21
  54. package/src/combos/failover.ts +8 -1
  55. package/src/config/provider-validation.ts +7 -2
  56. package/src/generated/compatibility-version.json +168 -108
  57. package/src/generated/model-metadata.ts +1 -1
  58. package/src/images/loop.ts +2 -2
  59. package/src/lib/bun-transpiler-cache-scope.mjs +31 -17
  60. package/src/lib/provider-admission-wait.ts +14 -0
  61. package/src/lib/service-secrets.ts +37 -2
  62. package/src/lib/translator-budget.ts +1 -1
  63. package/src/lib/upstream-retry.ts +15 -0
  64. package/src/oauth/account-import/google-antigravity-adapter.ts +38 -2
  65. package/src/oauth/account-import/parser.ts +15 -2
  66. package/src/oauth/account-import/types.ts +7 -0
  67. package/src/oauth/chatgpt-shared.ts +10 -1
  68. package/src/oauth/dsh.ts +45 -2
  69. package/src/oauth/kiro.ts +44 -1
  70. package/src/oauth/login-flow-state.ts +11 -2
  71. package/src/providers/claude-cli-usage.ts +20 -5
  72. package/src/providers/initial-model-selection.ts +2 -2
  73. package/src/providers/key-failover.ts +10 -2
  74. package/src/providers/key-store.ts +8 -3
  75. package/src/providers/mistral-transport.ts +207 -0
  76. package/src/providers/openai-sidecar.ts +5 -0
  77. package/src/providers/quota/anthropic-account-quota.ts +18 -6
  78. package/src/providers/quota/antigravity.ts +6 -2
  79. package/src/providers/quota/failure-codes.ts +18 -0
  80. package/src/providers/quota/vendor-probes-oauth.ts +12 -3
  81. package/src/providers/quota-routing-cache.ts +1 -1
  82. package/src/providers/quota.ts +5 -1
  83. package/src/providers/registry/entries-extended.ts +6 -1
  84. package/src/providers/routed-config.ts +1 -1
  85. package/src/providers/xai-transport.ts +2 -1
  86. package/src/responses/audio.ts +46 -0
  87. package/src/responses/input-media.ts +37 -15
  88. package/src/responses/parser-content.ts +22 -27
  89. package/src/responses/reasoning-retention.ts +218 -11
  90. package/src/responses/schema.ts +3 -4
  91. package/src/responses/web-search-replay.ts +11 -2
  92. package/src/server/chat-native.ts +8 -7
  93. package/src/server/index/serve-options.ts +8 -2
  94. package/src/server/index/websocket-handler.ts +10 -0
  95. package/src/server/lifecycle.ts +17 -1
  96. package/src/server/management/oauth-account-routes.ts +2 -1
  97. package/src/server/messages-native.ts +11 -0
  98. package/src/server/request-log.ts +16 -7
  99. package/src/server/responses/adapter-continuation.ts +2 -2
  100. package/src/server/responses/adapter-dispatch.ts +2 -2
  101. package/src/server/responses/codex-ws-exchange.ts +3 -0
  102. package/src/server/responses/codex-ws-metadata.ts +44 -0
  103. package/src/server/responses/codex-ws-session.ts +21 -1
  104. package/src/server/responses/combo-stream-preflight.ts +7 -2
  105. package/src/server/responses/compact.ts +2 -0
  106. package/src/server/responses/core-auth.ts +20 -0
  107. package/src/server/responses/core-codex-account.ts +21 -14
  108. package/src/server/responses/core-combo.ts +3 -0
  109. package/src/server/responses/core-opaque-recovery.ts +20 -11
  110. package/src/server/responses/deepseek-image-files.ts +121 -0
  111. package/src/server/responses/empty-completion-guard.ts +8 -0
  112. package/src/server/responses/fetch-helpers.ts +30 -10
  113. package/src/server/responses/input-admission.ts +6 -2
  114. package/src/server/responses/main-hard-lock-routing.ts +33 -8
  115. package/src/server/responses/opengateway-completion-guard.ts +232 -0
  116. package/src/server/responses/passthrough-completion.ts +41 -0
  117. package/src/server/responses/passthrough-delivery.ts +2 -0
  118. package/src/server/responses/passthrough-dispatch.ts +13 -13
  119. package/src/server/responses/passthrough-key-rotation.ts +40 -0
  120. package/src/server/responses/reasoning-archive-error.ts +21 -0
  121. package/src/server/responses/request-prepare.ts +11 -1
  122. package/src/server/responses/request-transport.ts +61 -3
  123. package/src/service/orchestration.ts +17 -0
  124. package/src/types/provider.ts +2 -0
  125. package/src/types/request.ts +16 -1
  126. package/src/types.ts +1 -0
  127. package/src/web-search/loop.ts +2 -2
  128. package/gui/dist/assets/App-BnRSujOq.js +0 -58
  129. package/gui/dist/assets/quota-summary-BY_10IEz.js +0 -1
@@ -53,7 +53,7 @@ const DATA: Record<string, readonly Row[]> = {
53
53
  "moonshot": [["kimi-k2.5",262144,65536,"text,image",1,null,0,0,0,0]],
54
54
  "openai": [["codex-mini-latest",200000,100000,"text",1,null,1.5,6,0.375,0],["gpt-4",8192,8192,"text",0,null,30,60,0,0],["gpt-4-turbo",128000,4096,"text,image",0,null,10,30,0,0],["gpt-4.1",1047576,32768,"text,image",0,null,2,8,0.5,0],["gpt-4.1-mini",1047576,32768,"text,image",0,null,0.4,1.6,0.1,0],["gpt-4.1-nano",1047576,32768,"text,image",0,null,0.1,0.4,0.025,0],["gpt-4o",128000,16384,"text,image",0,null,2.5,10,1.25,0],["gpt-4o-2024-05-13",128000,4096,"text,image",0,null,5,15,0,0],["gpt-4o-2024-08-06",128000,16384,"text,image",0,null,2.5,10,1.25,0],["gpt-4o-2024-11-20",128000,16384,"text,image",0,null,2.5,10,1.25,0],["gpt-4o-mini",128000,16384,"text,image",0,null,0.15,0.6,0.075,0],["gpt-5",400000,128000,"text,image",1,null,1.25,10,0.125,0],["gpt-5-chat-latest",128000,16384,"text,image",0,null,1.25,10,0.125,0],["gpt-5-codex",272000,128000,"text,image",1,null,1.25,10,0.125,0],["gpt-5-mini",400000,128000,"text,image",1,null,0.25,2,0.025,0],["gpt-5-nano",400000,128000,"text,image",1,null,0.05,0.4,0.005,0],["gpt-5-pro",400000,272000,"text,image",1,null,15,120,0,0],["gpt-5.1",400000,128000,"text,image",1,null,1.25,10,0.125,0],["gpt-5.1-chat-latest",128000,16384,"text,image",1,null,1.25,10,0.125,0],["gpt-5.1-codex",272000,128000,"text,image",1,null,1.25,10,0.125,0],["gpt-5.1-codex-max",272000,128000,"text,image",1,null,1.25,10,0.125,0],["gpt-5.1-codex-mini",272000,128000,"text,image",1,null,0.25,2,0.025,0],["gpt-5.2",400000,128000,"text,image",1,null,1.75,14,0.175,0],["gpt-5.2-chat-latest",128000,16384,"text,image",1,null,1.75,14,0.175,0],["gpt-5.2-codex",272000,128000,"text,image",1,null,1.75,14,0.175,0],["gpt-5.2-pro",400000,128000,"text,image",1,null,21,168,0,0],["gpt-5.3-chat-latest",128000,16384,"text,image",0,null,1.75,14,0.175,0],["gpt-5.3-codex",272000,128000,"text,image",1,null,1.75,14,0.175,0],["gpt-5.3-codex-spark",128000,32000,"text,image",1,null,1.75,14,0.175,0],["gpt-5.4",1050000,128000,"text,image",1,null,2.5,15,0.25,0],["gpt-5.4-mini",400000,128000,"text,image",1,null,0.75,4.5,0.075,0],["gpt-5.4-nano",400000,128000,"text,image",1,null,0.2,1.25,0.02,0],["gpt-5.4-pro",1050000,128000,"text,image",1,null,30,180,0,0],["gpt-5.5",1050000,128000,"text,image",1,null,5,30,0.5,0],["gpt-5.5-pro",1050000,128000,"text,image",1,null,30,180,0,0],["gpt-5.6",1050000,128000,"text,image",1,null,5,30,0.5,6.25],["gpt-5.6-luna",1050000,128000,"text,image",1,null,0.2,1.2,0.02,0.25],["gpt-5.6-sol",1050000,128000,"text,image",1,null,5,30,0.5,6.25],["gpt-5.6-terra",1050000,128000,"text,image",1,null,2,12,0.2,2.5],["gpt-6-astra",1050000,128000,"text,image",1,null,10,50,1,12.5],["gpt-6-luna",1050000,128000,"text,image",1,null,0.1,0.5,0.01,0.125],["gpt-6-sol",1050000,128000,"text,image",1,null,2,10,0.2,2.5],["gpt-6.1-sol",1050000,128000,"text,image",1,null,2,10,0.1,2.5],["gpt-realtime-2.1",128000,32000,"text,image",1,null,4,24,0.4,0],["o1",200000,100000,"text,image",1,null,15,60,7.5,0],["o1-pro",200000,100000,"text,image",1,null,150,600,0,0],["o3",200000,100000,"text,image",1,null,2,8,0.5,0],["o3-deep-research",200000,100000,"text,image",1,null,10,40,2.5,0],["o3-mini",200000,100000,"text",1,null,1.1,4.4,0.55,0],["o3-pro",200000,100000,"text,image",1,null,20,80,0,0],["o4-mini",200000,100000,"text,image",1,null,1.1,4.4,0.275,0],["o4-mini-deep-research",200000,100000,"text,image",1,null,2,8,0.5,0]],
55
55
  "openai-codex": [["codex-auto-review",1000000,128000,"text,image",1,null,0,0,0,0],["gpt-5",400000,128000,"text,image",1,null,1.25,10,0.125,0],["gpt-5-codex",272000,128000,"text,image",1,null,1.25,10,0.125,0],["gpt-5-codex-mini",272000,128000,"text,image",1,null,0,0,0,0],["gpt-5.1",400000,128000,"text,image",1,null,1.25,10,0.13,0],["gpt-5.1-codex",272000,128000,"text,image",1,null,1.25,10,0.125,0],["gpt-5.1-codex-max",272000,128000,"text,image",1,null,1.25,10,0.125,0],["gpt-5.1-codex-mini",272000,128000,"text,image",1,null,0.25,2,0.025,0],["gpt-5.2",272000,128000,"text,image",1,null,1.75,14,0.175,0],["gpt-5.2-codex",272000,128000,"text,image",1,null,1.75,14,0.175,0],["gpt-5.3-codex",272000,128000,"text,image",1,null,1.75,14,0.175,0],["gpt-5.3-codex-spark",128000,128000,"text",1,null,1.75,14,0.175,0],["gpt-5.4",1000000,128000,"text,image",1,null,2.5,15,0.25,0],["gpt-5.4-mini",272000,128000,"text,image",1,null,0.75,4.5,0.075,0],["gpt-5.4-nano",272000,128000,"text,image",1,null,0.2,1.25,0.02,0],["gpt-5.5",272000,128000,"text,image",1,null,5,30,0.5,0],["gpt-5.6-luna",373000,128000,"text,image",1,null,0.2,1.2,0.02,0.25],["gpt-5.6-sol",373000,128000,"text,image",1,null,5,30,0.5,6.25],["gpt-5.6-terra",373000,128000,"text,image",1,null,2,12,0.2,2.5],["gpt-6-luna",373000,128000,"text,image",1,null,0.1,0.5,0.01,0.125],["gpt-6-sol",373000,128000,"text,image",1,null,2,10,0.2,2.5],["gpt-6.1-sol",373000,128000,"text,image",1,null,2,10,0.1,2.5]],
56
- "opencode-go": [["claude-haiku-5-5",1000000,128000,"text,image",1,null,0.1,0.5,0.01,0.125],["deepseek-v4-flash",1000000,384000,"text",1,null,0.14,0.28,0.0028,0],["deepseek-v4-pro",1000000,384000,"text",1,null,1.74,3.48,0.0145,0],["glm-5",204800,131072,"text",1,null,1,3.2,0.2,0],["glm-5.1",200000,131072,"text",1,null,1.4,4.4,0.26,0],["glm-5.2",1000000,131072,"text",1,null,1.4,4.4,0.26,0],["glm-5.3",1000000,131072,"text",1,null,1.4,4.4,0.26,0],["glm-5.3-flash",1000000,131072,"text,image",1],["gpt-5.6-luna",1050000,128000,"text,image",1],["grok-4.5",500000,500000,"text,image",1,null,2,6,0.5,0],["grok-4.6",500000,500000,"text,image",1,null,2,6,0.5,0],["grok-4.7",500000,500000,"text,image",1,null,2,6,0.5,0],["hy3",256000,64000,"text",1,null,0.14,0.58,0.035,0],["hy4-preview",1024000,64000,"text",1],["kimi-k2.5",262144,262144,"text,image",1,null,0.3,1.9,0,0],["kimi-k2.6",262144,262144,"text,image",1,null,0.95,4,0.2,0],["kimi-k2.7-code",262144,262144,"text,image",1,null,0.95,4,0.19,0],["kimi-k3",1048576,131072,"text,image",1,null,3,15,0.3,0],["longcat-2.0",1000000,131072,"text",1],["mimo-v2-omni",262144,131072,"text,image",1,null,0.4,2,0.08,0],["mimo-v2-pro",1048576,131072,"text",1,null,1,3,0.2,0],["mimo-v2.5",1048576,131072,"text,image",1,null,0.14,0.28,0.0028,0],["mimo-v2.5-pro",1048576,131072,"text",1,null,1.74,3.48,0.0145,0],["mimo-v2.6-flash",1048576,131072,"text",1,null,0.14,0.28,0.0028,0],["mimo-v2.6-pro",1048576,131072,"text",1,null,0.435,0.87,0.003625,0],["minimax-m2.5",204800,131072,"text",1,null,0.3,1.2,0.06,0.375],["minimax-m2.7",204800,131072,"text",1,null,0.3,1.2,0.06,0.375],["minimax-m3",512000,128000,"text,image",1,null,0.3,1.2,0.06,0],["muse-spark-1.2-contributor",1048576,131072,"text,image",1],["muse-spark-1.3-contributor",1048576,131072,"text,image",1],["omen-alpha",500000,128000,"text,image",1],["ox-alpha-free",1000000,131072,"text,image",1],["qwen3.5-plus",1000000,65536,"text,image",1,null,0.4,2.4,0,0],["qwen3.6-plus",1000000,65536,"text,image",1,null,2,6,0.2,2.5],["qwen3.7-max",1000000,65536,"text",1,null,2.5,7.5,0.5,3.125],["qwen3.7-plus",1000000,64000,"text,image",1,null,1.2,4.8,0.12,1.5],["qwen3.8-flash",1000000,131072,"text,image",1],["qwen3.8-max",1000000,131072,"text,image",1],["union-alpha",262144,131072,"text,image",1]],
56
+ "opencode-go": [["beam-free",1000000,131072,"text,image",1],["claude-haiku-5-5",1000000,128000,"text,image",1,null,0.1,0.5,0.01,0.125],["deepseek-v4-flash",1000000,384000,"text",1,null,0.14,0.28,0.0028,0],["deepseek-v4-pro",1000000,384000,"text",1,null,1.74,3.48,0.0145,0],["deepseek-v4.1-flash",1048576,384000,"text",1],["gemini-4-argon-contributor",1048576,65536,"text,image",1],["glm-5",204800,131072,"text",1,null,1,3.2,0.2,0],["glm-5.1",200000,131072,"text",1,null,1.4,4.4,0.26,0],["glm-5.2",1000000,131072,"text",1,null,1.4,4.4,0.26,0],["glm-5.3",1000000,131072,"text",1,null,1.4,4.4,0.26,0],["glm-5.3-flash",1000000,131072,"text,image",1],["gpt-5.6-luna",1050000,128000,"text,image",1],["gpt-6-luna",1050000,128000,"text,image",1],["grok-4.5",500000,500000,"text,image",1,null,2,6,0.5,0],["grok-4.6",500000,500000,"text,image",1,null,2,6,0.5,0],["grok-4.7",500000,500000,"text,image",1,null,2,6,0.5,0],["hy3",256000,64000,"text",1,null,0.14,0.58,0.035,0],["hy4-preview",1024000,64000,"text",1],["kimi-k2.5",262144,262144,"text,image",1,null,0.3,1.9,0,0],["kimi-k2.6",262144,262144,"text,image",1,null,0.95,4,0.2,0],["kimi-k2.7-code",262144,262144,"text,image",1,null,0.95,4,0.19,0],["kimi-k3",1048576,131072,"text,image",1,null,3,15,0.3,0],["longcat-2.0",1000000,131072,"text",1],["longcat-2.5-preview-free",1000000,131072,"text,image",1],["mimo-v2-omni",262144,131072,"text,image",1,null,0.4,2,0.08,0],["mimo-v2-pro",1048576,131072,"text",1,null,1,3,0.2,0],["mimo-v2.5",1048576,131072,"text,image",1,null,0.14,0.28,0.0028,0],["mimo-v2.5-pro",1048576,131072,"text",1,null,1.74,3.48,0.0145,0],["mimo-v2.6-flash",1048576,131072,"text",1,null,0.14,0.28,0.0028,0],["mimo-v2.6-pro",1048576,131072,"text",1,null,0.435,0.87,0.003625,0],["minimax-m2.5",204800,131072,"text",1,null,0.3,1.2,0.06,0.375],["minimax-m2.7",204800,131072,"text",1,null,0.3,1.2,0.06,0.375],["minimax-m3",512000,128000,"text,image",1,null,0.3,1.2,0.06,0],["muse-spark-1.2-contributor",1048576,131072,"text,image",1],["muse-spark-1.3-contributor",1048576,131072,"text,image",1],["omen-alpha",500000,128000,"text,image",1],["ox-alpha-free",1000000,131072,"text,image",1],["qwen3.5-plus",1000000,65536,"text,image",1,null,0.4,2.4,0,0],["qwen3.6-plus",1000000,65536,"text,image",1,null,2,6,0.2,2.5],["qwen3.7-max",1000000,65536,"text",1,null,2.5,7.5,0.5,3.125],["qwen3.7-plus",1000000,64000,"text,image",1,null,1.2,4.8,0.12,1.5],["qwen3.8-flash",1000000,131072,"text,image",1],["qwen3.8-max",1000000,131072,"text,image",1],["space-bunny",1000000,131072,"text,image",1],["step-5-preview",256000,64000,"text,image",1],["union-alpha",262144,131072,"text,image",1]],
57
57
  "openrouter": [["~anthropic/claude-fable-latest",1000000,128000,"text,image",1,null,10,50,1,12.5],["~anthropic/claude-haiku-latest",200000,64000,"text,image",1,null,1,5,0.09999999999999999,1.25],["~anthropic/claude-opus-latest",1000000,128000,"text,image",1,null,5,25,0.5,6.25],["~anthropic/claude-sonnet-latest",1000000,128000,"text,image",1,null,2,10,0.19999999999999998,2.5],["~google/gemini-flash-latest",1048576,65536,"text,image",1,null,1.5,7.5,0.15,0.08333333333333334],["~google/gemini-pro-latest",1048576,65536,"text,image",1,null,2,12,0.19999999999999998,0.375],["~moonshotai/kimi-latest",1048576,8888,"text,image",1,null,3,15,0.3,0],["~openai/gpt-latest",1050000,128000,"text,image",1,null,5,30,0.5,6.25],["~openai/gpt-mini-latest",400000,128000,"text,image",1,null,0.75,4.5,0.075,0],["~x-ai/grok-latest",500000,8888,"text,image",1,null,2,6,0.3,0],["ai21/jamba-large-1.7",256000,4096,"text",0,null,2,8,0,0],["aion-labs/aion-2.0",131072,32768,"text",1,null,0.7999999999999999,1.5999999999999999,0.19999999999999998,0],["aion-labs/aion-3.0",131072,32768,"text",1,null,3,6,0.75,0],["aion-labs/aion-3.0-mini",131072,32768,"text",1,null,0.7,1.4,0.18,0],["alibaba/tongyi-deepresearch-30b-a3b",131072,131072,"text",1,null,0.09,0.44999999999999996,0.09,0],["allenai/olmo-3.1-32b-instruct",65536,16384,"text",0,null,0.19999999999999998,0.6,0,0],["amazon/nova-2-lite-v1",1000000,65535,"text,image",1,null,0.3,2.5,0,0],["amazon/nova-lite-v1",300000,5120,"text,image",0,null,0.06,0.24,0,0],["amazon/nova-micro-v1",128000,5120,"text",0,null,0.035,0.14,0,0],["amazon/nova-premier-v1",1000000,32000,"text,image",0,null,2.5,12.5,0.625,0],["amazon/nova-pro-v1",300000,5120,"text,image",0,null,0.7999999999999999,3.1999999999999997,0,0],["anthropic/claude-3-haiku",200000,4096,"text,image",0,null,0.25,1.25,0.03,0.3],["anthropic/claude-3.5-haiku",200000,8192,"text,image",0,null,0.7999999999999999,4,0.08,1],["anthropic/claude-3.5-sonnet",200000,8192,"text,image",0,null,6,30,0.6,7.5],["anthropic/claude-3.7-sonnet",200000,128000,"text,image",1,null,3,15,0.3,3.75],["anthropic/claude-3.7-sonnet:thinking",200000,64000,"text,image",1,null,3,15,0.3,3.75],["anthropic/claude-fable-5",1000000,128000,"text,image",1,null,10,50,1,12.5],["anthropic/claude-haiku-4.5",200000,64000,"text,image",0,null,1,5,0.09999999999999999,1.25],["anthropic/claude-haiku-5.5",1000000,128000,"text,image",1,null,0.1,0.5,0.01,0.125],["anthropic/claude-opus-4",200000,32000,"text,image",1,null,15,75,1.5,18.75],["anthropic/claude-opus-4.1",200000,32000,"text,image",1,null,15,75,1.5,18.75],["anthropic/claude-opus-4.5",200000,64000,"text,image",1,null,5,25,0.5,6.25],["anthropic/claude-opus-4.6",1000000,128000,"text,image",1,null,5,25,0.5,6.25],["anthropic/claude-opus-4.6-fast",1000000,128000,"text,image",1,null,30,150,3,37.5],["anthropic/claude-opus-4.7",1000000,128000,"text,image",1,null,5,25,0.5,6.25],["anthropic/claude-opus-4.7-fast",1000000,128000,"text,image",1,null,30,150,3,37.5],["anthropic/claude-opus-4.8",1000000,128000,"text,image",1,null,5,25,0.5,6.25],["anthropic/claude-opus-4.8-fast",1000000,128000,"text,image",1,null,10,50,1,12.5],["anthropic/claude-opus-5",1000000,128000,"text,image",1,null,5,25,0.5,6.25],["anthropic/claude-opus-5-fast",1000000,128000,"text,image",1,null,10,50,1,12.5],["anthropic/claude-opus-5.5",1000000,128000,"text,image",1,null,4,20,0.2,5],["anthropic/claude-opus-5.5-fast",1000000,128000,"text,image",1,null,8,40,0.4,10],["anthropic/claude-sonnet-4",1000000,64000,"text,image",1,null,3,15,0.3,3.75],["anthropic/claude-sonnet-4.5",1000000,64000,"text,image",1,null,3,15,0.3,3.75],["anthropic/claude-sonnet-4.6",1000000,128000,"text,image",1,null,3,15,0.3,3.75],["anthropic/claude-sonnet-5",1000000,128000,"text,image",1,null,2,10,0.19999999999999998,2.5],["anthropic/claude-sonnet-5.5",1000000,128000,"text,image",1,null,2,10,0.1,2.5],["arcee-ai/trinity-large-preview",131000,8888,"text",0,null,0.15,0.44999999999999996,0,0],["arcee-ai/trinity-large-preview:free",131000,8888,"text",0,null,0,0,0,0],["arcee-ai/trinity-large-thinking",262144,262144,"text",1,null,0.22,0.85,0.06,0],["arcee-ai/trinity-large-thinking:free",262144,80000,"text",1,null,0,0,0,0],["arcee-ai/trinity-mini",131072,131072,"text",1,null,0.045,0.15,0,0],["arcee-ai/trinity-mini:free",131072,8888,"text",1,null,0,0,0,0],["arcee-ai/virtuoso-large",131072,64000,"text",0,null,0.75,1.2,0,0],["auto",2000000,30000,"text,image",1,null,0,0,0,0],["baidu/cobuddy:free",131072,65536,"text",1,null,0,0,0,0],["baidu/ernie-4.5-21b-a3b",131072,8000,"text",0,null,0.07,0.28,0,0],["baidu/ernie-4.5-vl-28b-a3b",131072,8000,"text,image",1,null,0.14,0.56,0,0],["bytedance-seed/seed-1.6",262144,32768,"text,image",1,null,0.25,2,0,0],["bytedance-seed/seed-1.6-flash",262144,32768,"text,image",1,null,0.075,0.3,0,0],["bytedance-seed/seed-2.0-lite",262144,131072,"text,image",1,null,0.25,2,0,0],["bytedance-seed/seed-2.0-mini",262144,131072,"text,image",1,null,0.09999999999999999,0.39999999999999997,0,0],["cohere/command-r-08-2024",128000,4000,"text",0,null,0.15,0.6,0,0],["cohere/command-r-plus-08-2024",128000,4000,"text",0,null,2.5,10,0,0],["cohere/north-mini-code:free",256000,64000,"text",1,null,0,0,0,0],["deepseek/deepseek-chat",163840,16000,"text",0,null,0.20020000000000002,0.8000999999999999,0.15,0],["deepseek/deepseek-chat-v3-0324",163840,65536,"text",1,null,0.27,1.12,0.135,0],["deepseek/deepseek-chat-v3.1",163840,32768,"text",1,null,0.25,0.95,0.13,0],["deepseek/deepseek-r1",163840,16000,"text",1,null,0.7,2.5,0,0],["deepseek/deepseek-r1-0528",163840,32768,"text",1,null,0.5,2.1500000000000004,0.35,0],["deepseek/deepseek-v3.1-terminus",163840,32768,"text",1,null,0.27,1,0.135,0],["deepseek/deepseek-v3.1-terminus:exacto",163840,8888,"text",1,null,0.21,0.7899999999999999,0.16799999999999998,0],["deepseek/deepseek-v3.2",163840,65536,"text",1,null,0.26899999999999996,0.39999999999999997,0.13449999999999998,0],["deepseek/deepseek-v3.2-exp",163840,65536,"text",1,null,0.27,0.41,0,0],["deepseek/deepseek-v4-flash",1048576,384000,"text",1,null,0.09380000000000001,0.18760000000000002,0.01876,0],["deepseek/deepseek-v4-flash:free",1048576,384000,"text",1,null,0,0,0,0],["deepseek/deepseek-v4-pro",1048576,384000,"text",1,null,0.435,0.87,0.003625,0],["essentialai/rnj-1-instruct",32768,8888,"text",0,null,0.15,0.15,0,0],["google/gemini-2.0-flash-001",1048576,8192,"text,image",0,null,0.09999999999999999,0.39999999999999997,0.024999999999999998,0.08333333333333334],["google/gemini-2.0-flash-lite-001",1048576,8192,"text,image",0,null,0.075,0.3,0,0],["google/gemini-2.5-flash",1048576,65535,"text,image",1,null,0.3,2.5,0.03,0.08333333333333334],["google/gemini-2.5-flash-lite",1048576,65535,"text,image",0,null,0.09999999999999999,0.39999999999999997,0.01,0.08333333333333334],["google/gemini-2.5-flash-lite-preview-09-2025",1048576,65535,"text,image",1,null,0.09999999999999999,0.39999999999999997,0.01,0.08333333333333334],["google/gemini-2.5-flash-preview-09-2025",1048576,65536,"text,image",1,null,0.3,2.5,0.03,0.08333333333333334],["google/gemini-2.5-pro",1048576,65536,"text,image",1,null,1.25,10,0.125,0.375],["google/gemini-2.5-pro-preview",1048576,65536,"text,image",1,null,1.25,10,0.125,0.375],["google/gemini-2.5-pro-preview-05-06",1048576,65535,"text,image",1,null,1.25,10,0.125,0.375],["google/gemini-3-flash-preview",1048576,65535,"text,image",1,null,0.5,3,0.049999999999999996,0.08333333333333334],["google/gemini-3-pro-image",131072,32768,"text,image",1,null,2,12,0.19999999999999998,0.375],["google/gemini-3-pro-preview",1048000,64000,"text,image",1,null,2,12,0.19999999999999998,0.375],["google/gemini-3.1-flash-lite",1048576,65536,"text,image",1,null,0.25,1.5,0.024999999999999998,0.08333333333333334],["google/gemini-3.1-flash-lite-preview",1048576,65536,"text,image",0,null,0.25,1.5,0.024999999999999998,0.08333333333333334],["google/gemini-3.1-pro-preview",1048576,65536,"text,image",1,null,2,12,0.19999999999999998,0.375],["google/gemini-3.1-pro-preview-customtools",1048576,65536,"text,image",1,null,2,12,0.19999999999999998,0.375],["google/gemini-3.5-flash",1048576,65536,"text,image",1,null,1.5,9,0.15,0.08333333333333334],["google/gemini-3.5-flash-lite",1048576,65536,"text,image",1,null,0.3,2.5,0.03,0.08333333333333334],["google/gemini-3.6-flash",1048576,65536,"text,image",1,null,1.5,7.5,0.15,0.08333333333333334],["google/gemma-3-12b-it",131072,16384,"text,image",0,null,0.049999999999999996,0.15,0,0],["google/gemma-3-27b-it",262144,131072,"text,image",1,null,0.08,0.44999999999999996,0.04,0],["google/gemma-3-27b-it:free",131072,8192,"text,image",0,null,0,0,0,0],["google/gemma-4-26b-a4b-it",262144,262144,"text,image",1,null,0.12,0.35,0.049999999999999996,0],["google/gemma-4-26b-a4b-it:free",262144,32768,"text,image",1,null,0,0,0,0],["google/gemma-4-31b-it",262144,262144,"text,image",1,null,0.14,0.39999999999999997,0.09,0],["google/gemma-4-31b-it:free",262144,32768,"text,image",1,null,0,0,0,0],["ibm-granite/granite-4.1-8b",131072,131072,"text",0,null,0.049999999999999996,0.09999999999999999,0.049999999999999996,0],["inception/mercury",128000,32000,"text",0,null,0.25,0.75,0.024999999999999998,0],["inception/mercury-2",128000,50000,"text",1,null,0.25,0.75,0.024999999999999998,0],["inception/mercury-coder",128000,32000,"text",0,null,0.25,0.75,0.024999999999999998,0],["inclusionai/ling-2.6-1t",262144,32768,"text",0,null,0.075,0.625,0.015,0],["inclusionai/ling-2.6-1t:free",262144,32768,"text",0,null,0,0,0,0],["inclusionai/ling-2.6-flash",262144,32768,"text",0,null,0.01,0.03,0.002,0],["inclusionai/ling-2.6-flash:free",262144,32768,"text",0,null,0,0,0,0],["inclusionai/ling-3.0-flash:free",262144,32768,"text",1,null,0,0,0,0],["inclusionai/ring-2.6-1t",262144,65536,"text",1,null,0.075,0.625,0.015,0],["inclusionai/ring-2.6-1t:free",262144,65536,"text",1,null,0,0,0,0],["kwaipilot/kat-coder-air-v2.5",256000,80000,"text",0,null,0.15,0.6,0.03,0],["kwaipilot/kat-coder-pro",256000,128000,"text",0,null,0.207,0.828,0.0414,0],["kwaipilot/kat-coder-pro-v2",262144,80000,"text",0,null,0.3,1.2,0.06,0],["kwaipilot/kat-coder-pro-v2.5",256000,80000,"text",0,null,0.74,2.96,0.15,0],["liquid/lfm-2.5-1.2b-thinking:free",32768,8888,"text",1,null,0,0,0,0],["meituan/longcat-2.0",1048756,262144,"text",1,null,0.3,1.2,0.006,0],["meituan/longcat-flash-chat",131072,131072,"text",0,null,0.19999999999999998,0.7999999999999999,0.19999999999999998,0],["meta-llama/llama-3-8b-instruct",8192,16384,"text",0,null,0.03,0.04,0,0],["meta-llama/llama-3.1-405b-instruct",131000,8888,"text",0,null,4,4,0,0],["meta-llama/llama-3.1-70b-instruct",131072,16384,"text",0,null,0.39999999999999997,0.39999999999999997,0,0],["meta-llama/llama-3.1-8b-instruct",131072,131072,"text",0,null,0.049999999999999996,0.08,0.024999999999999998,0],["meta-llama/llama-3.3-70b-instruct",131072,128000,"text",0,null,0.13,0.39999999999999997,0,0],["meta-llama/llama-3.3-70b-instruct:free",131072,8888,"text",0,null,0,0,0,0],["meta-llama/llama-4-maverick",1048576,16384,"text,image",0,null,0.19999999999999998,0.7999999999999999,0,0],["meta-llama/llama-4-scout",1310720,16384,"text,image",0,null,0.09999999999999999,0.3,0,0],["meta/muse-spark-1.1",1048576,8888,"text,image",1,null,1.25,4.25,0.15,0],["minimax/minimax-m1",1000000,40000,"text",1,null,0.55,2.2,0,0],["minimax/minimax-m2",204800,131072,"text",1,null,0.255,1.02,0.03,0],["minimax/minimax-m2.1",204800,131072,"text",1,null,0.3,1.2,0.03,0],["minimax/minimax-m2.5",204800,196608,"text",1,null,0.15,0.8999999999999999,0.049999999999999996,0],["minimax/minimax-m2.5:free",262144,8192,"text",1,null,0,0,0,0],["minimax/minimax-m2.7",204800,131072,"text",1,null,0.25,1,0.049999999999999996,0],["minimax/minimax-m3",1048576,512000,"text,image",1,null,0.3,1.2,0.06,0],["mistralai/codestral-2508",256000,8888,"text",0,null,0.3,0.8999999999999999,0.03,0],["mistralai/devstral-2512",262144,8888,"text",0,null,0.39999999999999997,2,0.04,0],["mistralai/devstral-medium",131072,8888,"text",0,null,0.39999999999999997,2,0.04,0],["mistralai/devstral-small",131072,8888,"text",0,null,0.09999999999999999,0.3,0.01,0],["mistralai/ministral-14b-2512",262144,8888,"text,image",0,null,0.19999999999999998,0.19999999999999998,0.02,0],["mistralai/ministral-3b-2512",131072,8888,"text,image",0,null,0.09999999999999999,0.09999999999999999,0.01,0],["mistralai/ministral-8b-2512",262144,8888,"text,image",0,null,0.15,0.15,0.015,0],["mistralai/mistral-large",128000,8888,"text",0,null,2,6,0.19999999999999998,0],["mistralai/mistral-large-2407",131072,8888,"text",0,null,2,6,0.19999999999999998,0],["mistralai/mistral-large-2411",131072,8888,"text",0,null,2,6,0.19999999999999998,0],["mistralai/mistral-large-2512",262144,8888,"text,image",0,null,0.5,1.5,0.049999999999999996,0],["mistralai/mistral-medium-3",131072,8888,"text,image",0,null,0.39999999999999997,2,0.04,0],["mistralai/mistral-medium-3-5",262144,8888,"text,image",1,null,1.5,7.5,0,0],["mistralai/mistral-medium-3.1",131072,8888,"text,image",0,null,0.39999999999999997,2,0.04,0],["mistralai/mistral-nemo",131072,16384,"text",0,null,0.019000000000000003,0.03,0,0],["mistralai/mistral-saba",32768,8888,"text",0,null,0.19999999999999998,0.6,0.02,0],["mistralai/mistral-small-24b-instruct-2501",32768,16384,"text",0,null,0.049999999999999996,0.08,0,0],["mistralai/mistral-small-2603",262144,8888,"text,image",1,null,0.15,0.6,0.015,0],["mistralai/mistral-small-3.1-24b-instruct",131072,131072,"text,image",0,null,0.03,0.11,0.015,0],["mistralai/mistral-small-3.1-24b-instruct:free",128000,8888,"text,image",0,null,0,0,0,0],["mistralai/mistral-small-3.2-24b-instruct",256000,8888,"text,image",0,null,0.09999999999999999,0.3,0.01,0],["mistralai/mistral-small-creative",32768,8888,"text",0,null,0.09999999999999999,0.3,0.01,0],["mistralai/mixtral-8x22b-instruct",65536,13108,"text",0,null,2,6,0.19999999999999998,0],["mistralai/mixtral-8x7b-instruct",32768,16384,"text",0,null,0.54,0.54,0,0],["mistralai/pixtral-large-2411",131072,8888,"text,image",0,null,2,6,0.19999999999999998,0],["mistralai/voxtral-small-24b-2507",32000,8888,"text",0,null,0.09999999999999999,0.3,0.01,0],["moonshotai/kimi-k2",131072,100352,"text",0,null,0.5700000000000001,2.3,0,0],["moonshotai/kimi-k2-0905",262144,100352,"text",0,null,0.6,2.5,0.15,0],["moonshotai/kimi-k2-0905:exacto",262144,8888,"text",0,null,0.6,2.5,0,0],["moonshotai/kimi-k2-thinking",262144,100352,"text",1,null,0.6,2.5,0.15,0],["moonshotai/kimi-k2.5",262144,262144,"text,image",1,null,0.5700000000000001,2.8499999999999996,0.095,0],["moonshotai/kimi-k2.6",262144,262144,"text,image",1,null,0.646,2.7199999999999998,0.1088,0],["moonshotai/kimi-k2.6:free",262144,8888,"text,image",1,null,0,0,0,0],["moonshotai/kimi-k2.7-code",262144,262144,"text,image",1,null,0.78,3.5,0.15,0],["moonshotai/kimi-k3",1048576,131072,"text,image",1,null,3,15,0.3,0],["nex-agi/deepseek-v3.1-nex-n1",131072,163840,"text",0,null,0.135,0.5,0,0],["nex-agi/nex-n2-mini",262144,262144,"text,image",1,null,0.024999999999999998,0.09999999999999999,0.0025,0],["nex-agi/nex-n2-pro",262144,262144,"text,image",1,null,0.25,1,0.024999999999999998,0],["nex-agi/nex-n2-pro:free",262144,262144,"text,image",1,null,0,0,0,0],["nousresearch/deephermes-3-mistral-24b-preview",32768,32768,"text",1,null,0.02,0.09999999999999999,0.01,0],["nousresearch/hermes-4-70b",131072,131072,"text",1,null,0.11,0.38,0.055,0],["nvidia/llama-3.1-nemotron-70b-instruct",131072,16384,"text",0,null,1.2,1.2,0,0],["nvidia/llama-3.3-nemotron-super-49b-v1.5",131072,16384,"text",1,null,0.39999999999999997,0.39999999999999997,0,0],["nvidia/nemotron-3-nano-30b-a3b",262144,228000,"text",1,null,0.049999999999999996,0.19999999999999998,0,0],["nvidia/nemotron-3-nano-30b-a3b:free",256000,8888,"text",1,null,0,0,0,0],["nvidia/nemotron-3-nano-omni-30b-a3b-reasoning:free",256000,65536,"text,image",1,null,0,0,0,0],["nvidia/nemotron-3-super-120b-a12b",1000000,16384,"text",1,null,0.08499999999999999,0.39999999999999997,0.09999999999999999,0],["nvidia/nemotron-3-super-120b-a12b:free",262144,262144,"text",1,null,0,0,0,0],["nvidia/nemotron-3-ultra-550b-a55b",512288,65536,"text",1,null,0.6,3.5999999999999996,0.19999999999999998,0],["nvidia/nemotron-3-ultra-550b-a55b:free",1000000,65536,"text",1,null,0,0,0,0],["nvidia/nemotron-nano-12b-v2-vl:free",128000,128000,"text,image",1,null,0,0,0,0],["nvidia/nemotron-nano-9b-v2",131072,16384,"text",1,null,0.04,0.16,0,0],["nvidia/nemotron-nano-9b-v2:free",128000,8888,"text",1,null,0,0,0,0],["openai/gpt-3.5-turbo",16385,4096,"text",0,null,0.5,1.5,0,0],["openai/gpt-3.5-turbo-0613",4095,4096,"text",0,null,1,2,0,0],["openai/gpt-3.5-turbo-16k",16385,4096,"text",0,null,3,4,0,0],["openai/gpt-4",8191,8192,"text",0,null,30,60,0,0],["openai/gpt-4-0314",8191,4096,"text",0,null,30,60,0,0],["openai/gpt-4-1106-preview",128000,4096,"text",0,null,10,30,0,0],["openai/gpt-4-turbo",128000,4096,"text,image",0,null,10,30,0,0],["openai/gpt-4-turbo-preview",128000,4096,"text",0,null,10,30,0,0],["openai/gpt-4.1",1047576,32768,"text,image",0,null,2,8,0.5,0],["openai/gpt-4.1-mini",1047576,32768,"text,image",0,null,0.39999999999999997,1.5999999999999999,0.09999999999999999,0],["openai/gpt-4.1-nano",1047576,32768,"text,image",0,null,0.09999999999999999,0.39999999999999997,0.024999999999999998,0],["openai/gpt-4o",128000,16384,"text,image",0,null,2.5,10,1.25,0],["openai/gpt-4o-2024-05-13",128000,4096,"text,image",0,null,5,15,0,0],["openai/gpt-4o-2024-08-06",128000,16384,"text,image",0,null,2.5,10,1.25,0],["openai/gpt-4o-2024-11-20",128000,16384,"text,image",0,null,2.5,10,1.25,0],["openai/gpt-4o-audio-preview",128000,16384,"text",0,null,2.5,10,0,0],["openai/gpt-4o-mini",128000,16384,"text,image",0,null,0.15,0.6,0.075,0],["openai/gpt-4o-mini-2024-07-18",128000,16384,"text,image",0,null,0.15,0.6,0.075,0],["openai/gpt-4o:extended",128000,64000,"text,image",0,null,6,18,0,0],["openai/gpt-5",400000,128000,"text,image",1,null,1.25,10,0.125,0],["openai/gpt-5-codex",272000,128000,"text,image",1,null,1.25,10,0.125,0],["openai/gpt-5-image",400000,128000,"text,image",1,null,10,10,1.25,0],["openai/gpt-5-image-mini",400000,128000,"text,image",1,null,2.5,2,0.25,0],["openai/gpt-5-mini",400000,128000,"text,image",1,null,0.25,2,0.024999999999999998,0],["openai/gpt-5-nano",400000,128000,"text,image",1,null,0.049999999999999996,0.39999999999999997,0.005,0],["openai/gpt-5-pro",400000,128000,"text,image",1,null,15,120,0,0],["openai/gpt-5.1",400000,128000,"text,image",1,null,1.25,10,0.125,0],["openai/gpt-5.1-chat",128000,16384,"text,image",0,null,1.25,10,0.125,0],["openai/gpt-5.1-codex",272000,128000,"text,image",1,null,1.25,10,0.125,0],["openai/gpt-5.1-codex-max",272000,128000,"text,image",1,null,1.25,10,0.125,0],["openai/gpt-5.1-codex-mini",272000,100000,"text,image",1,null,0.25,2,0.024999999999999998,0],["openai/gpt-5.2",400000,128000,"text,image",1,null,1.75,14,0.175,0],["openai/gpt-5.2-chat",128000,16384,"text,image",0,null,1.75,14,0.175,0],["openai/gpt-5.2-codex",272000,128000,"text,image",1,null,1.75,14,0.175,0],["openai/gpt-5.2-pro",400000,128000,"text,image",1,null,21,168,0,0],["openai/gpt-5.3-chat",128000,16384,"text",0,null,1.75,14,0.175,0],["openai/gpt-5.3-codex",272000,128000,"text,image",1,null,1.75,14,0.175,0],["openai/gpt-5.4",1050000,128000,"text,image",1,null,2.5,15,0.25,0],["openai/gpt-5.4-mini",400000,128000,"text",0,null,0.75,4.5,0.075,0],["openai/gpt-5.4-nano",400000,128000,"text",0,null,0.19999999999999998,1.25,0.02,0],["openai/gpt-5.4-pro",1050000,128000,"text,image",1,null,30,180,0,0],["openai/gpt-5.5",1050000,128000,"text,image",1,null,5,30,0.5,0],["openai/gpt-5.5-pro",1050000,128000,"text,image",1,null,30,180,0,0],["openai/gpt-5.6-luna",373000,128000,"text,image",1,null,1,6,0.09999999999999999,1.25],["openai/gpt-5.6-luna-pro",373000,128000,"text,image",1,null,1,6,0.09999999999999999,1.25],["openai/gpt-5.6-sol",373000,128000,"text,image",1,null,5,30,0.5,6.25],["openai/gpt-5.6-sol-pro",373000,128000,"text,image",1,null,5,30,0.5,6.25],["openai/gpt-5.6-terra",373000,128000,"text,image",1,null,2.5,15,0.25,3.125],["openai/gpt-5.6-terra-pro",373000,128000,"text,image",1,null,2.5,15,0.25,3.125],["openai/gpt-6-luna",373000,128000,"text,image",1,null,0.1,0.5,0.01,0.125],["openai/gpt-6-sol",373000,128000,"text,image",1,null,2,10,0.2,2.5],["openai/gpt-6.1-sol",373000,128000,"text,image",1,null,2,10,0.1,2.5],["openai/gpt-audio",128000,16384,"text",0,null,2.5,10,0,0],["openai/gpt-audio-mini",128000,16384,"text",0,null,0.6,2.4,0,0],["openai/gpt-chat-latest",400000,128000,"text,image",0,null,5,30,0.5,0],["openai/gpt-oss-120b",131072,131072,"text",1,null,0.037,0.16999999999999998,0,0],["openai/gpt-oss-120b:exacto",131072,8888,"text",1,null,0.039,0.19,0,0],["openai/gpt-oss-120b:free",131072,131072,"text",1,null,0,0,0,0],["openai/gpt-oss-20b",131072,131072,"text",1,null,0.03,0.13,0.03,0],["openai/gpt-oss-20b:free",131072,32768,"text",1,null,0,0,0,0],["openai/gpt-oss-safeguard-20b",131072,65536,"text",1,null,0.075,0.3,0.0375,0],["openai/o1",200000,100000,"text,image",1,null,15,60,7.5,0],["openai/o3",200000,100000,"text,image",1,null,2,8,0.5,0],["openai/o3-deep-research",200000,100000,"text,image",1,null,10,40,2.5,0],["openai/o3-mini",200000,100000,"text",1,null,1.1,4.4,0.55,0],["openai/o3-mini-high",200000,100000,"text",1,null,1.1,4.4,0.55,0],["openai/o3-pro",200000,100000,"text,image",1,null,20,80,0,0],["openai/o4-mini",200000,100000,"text,image",1,null,1.1,4.4,0.275,0],["openai/o4-mini-deep-research",200000,100000,"text,image",1,null,2,8,0.5,0],["openai/o4-mini-high",200000,100000,"text,image",1,null,1.1,4.4,0.275,0],["openrouter/aurora-alpha",128000,50000,"text",1,null,0,0,0,0],["openrouter/auto",2000000,8888,"text,image",1,null,-1000000,-1000000,0,0],["openrouter/auto-beta",2000000,8888,"text,image",1,null,-1000000,-1000000,0,0],["openrouter/elephant-alpha",262144,32768,"text",0,null,0,0,0,0],["openrouter/free",200000,8888,"text,image",1,null,0,0,0,0],["openrouter/healer-alpha",262144,32000,"text,image",1,null,0,0,0,0],["openrouter/hunter-alpha",1048576,32000,"text",1,null,0,0,0,0],["openrouter/owl-alpha",1048756,262144,"text",0,null,0,0,0,0],["poolside/laguna-m.1",262144,32768,"text",1,null,0.19999999999999998,0.39999999999999997,0.09999999999999999,0],["poolside/laguna-m.1:free",262144,32768,"text",1,null,0,0,0,0],["poolside/laguna-s-2.1",1048576,131072,"text",1,null,0.09999999999999999,0.19999999999999998,0.01,0],["poolside/laguna-s-2.1:free",262144,32768,"text",1,null,0,0,0,0],["poolside/laguna-xs-2.1",262144,32768,"text",1,null,0.06,0.12,0.03,0],["poolside/laguna-xs-2.1:free",262144,32768,"text",1,null,0,0,0,0],["poolside/laguna-xs.2",262144,32768,"text",1,null,0.09999999999999999,0.19999999999999998,0.049999999999999996,0],["poolside/laguna-xs.2:free",262144,32768,"text",1,null,0,0,0,0],["prime-intellect/intellect-3",131072,131072,"text",1,null,0.19999999999999998,1.1,0,0],["qwen/qwen-2.5-72b-instruct",32768,16384,"text",0,null,0.36,0.39999999999999997,0,0],["qwen/qwen-2.5-7b-instruct",32768,32768,"text",0,null,0.04,0.09999999999999999,0,0],["qwen/qwen-max",32768,8192,"text",0,null,1.04,4.16,0.20800000000000002,0],["qwen/qwen-plus",1000000,32768,"text",0,null,0.26,0.78,0.052000000000000005,0.325],["qwen/qwen-plus-2025-07-28",1000000,32768,"text",0,null,0.26,0.78,0,0.325],["qwen/qwen-plus-2025-07-28:thinking",1000000,32768,"text",1,null,0.26,0.78,0,0.325],["qwen/qwen-turbo",131072,8192,"text",0,null,0.0325,0.13,0.006500000000000001,0],["qwen/qwen-vl-max",131072,32768,"text,image",0,null,0.52,2.08,0,0],["qwen/qwen3-14b",131072,8192,"text",1,null,0.22749999999999998,0.9099999999999999,0,0],["qwen/qwen3-235b-a22b",131072,8192,"text",1,null,0.45499999999999996,1.8199999999999998,0,0],["qwen/qwen3-235b-a22b-2507",262144,16384,"text",1,null,0.09,0.55,0,0],["qwen/qwen3-235b-a22b-thinking-2507",262144,32768,"text",1,null,0.3,3,0.09999999999999999,0],["qwen/qwen3-30b-a3b",131072,8192,"text",1,null,0.13,0.52,0,0],["qwen/qwen3-30b-a3b-instruct-2507",262144,32000,"text",0,null,0.04815,0.19305,0,0],["qwen/qwen3-30b-a3b-thinking-2507",81920,32768,"text",1,null,0.13,1.56,0.08,0],["qwen/qwen3-32b",131072,16384,"text",1,null,0.08,0.28,0.04,0],["qwen/qwen3-4b",131072,8192,"text",1,null,0.0715,0.273,0,0],["qwen/qwen3-4b:free",40960,8888,"text",1,null,0,0,0,0],["qwen/qwen3-8b",131072,8192,"text",1,null,0.117,0.45499999999999996,0.049999999999999996,0],["qwen/qwen3-coder",262144,65536,"text",0,null,0.3,1,0.09999999999999999,0],["qwen/qwen3-coder-30b-a3b-instruct",262144,32768,"text",0,null,0.07,0.27,0,0],["qwen/qwen3-coder-flash",1000000,65536,"text",0,null,0.195,0.975,0.039,0.24375],["qwen/qwen3-coder-next",262144,262144,"text",0,null,0.11,0.7999999999999999,0.07,0],["qwen/qwen3-coder-plus",1000000,65536,"text",0,null,0.65,3.25,0.13,0.8125],["qwen/qwen3-coder:exacto",262144,65536,"text",0,null,0.22,1.7999999999999998,0.022,0],["qwen/qwen3-coder:free",1048576,262000,"text",0,null,0,0,0,0],["qwen/qwen3-max",262144,32768,"text",1,null,0.78,3.9,0.156,0.975],["qwen/qwen3-max-thinking",262144,32768,"text",1,null,0.78,3.9,0,0],["qwen/qwen3-next-80b-a3b-instruct",262144,262144,"text",0,null,0.09999999999999999,1.1,0.07,0],["qwen/qwen3-next-80b-a3b-instruct:free",262144,8888,"text",0,null,0,0,0,0],["qwen/qwen3-next-80b-a3b-thinking",262144,32768,"text",1,null,0.0975,0.78,0,0],["qwen/qwen3-vl-235b-a22b-instruct",262144,32768,"text,image",0,null,0.21,1.9,0.09999999999999999,0],["qwen/qwen3-vl-235b-a22b-thinking",131072,32768,"text,image",1,null,0.26,2.6,0,0],["qwen/qwen3-vl-30b-a3b-instruct",262144,16384,"text,image",0,null,0.15,0.6,0,0],["qwen/qwen3-vl-30b-a3b-thinking",262144,32768,"text,image",1,null,0.13,1.56,0,0],["qwen/qwen3-vl-32b-instruct",131072,32768,"text,image",0,null,0.10400000000000001,0.41600000000000004,0,0],["qwen/qwen3-vl-8b-instruct",262144,32768,"text,image",0,null,0.117,0.45499999999999996,0,0],["qwen/qwen3-vl-8b-thinking",131072,32768,"text,image",1,null,0.117,1.365,0,0],["qwen/qwen3.5-122b-a10b",262144,65536,"text,image",1,null,0.26,2.08,0,0],["qwen/qwen3.5-27b",262144,65536,"text,image",1,null,0.195,1.56,0,0],["qwen/qwen3.5-35b-a3b",262144,262144,"text,image",1,null,0.14,1,0.049999999999999996,0],["qwen/qwen3.5-397b-a17b",262144,65536,"text,image",1,null,0.39,2.34,0.111,0],["qwen/qwen3.5-9b",262144,262144,"text,image",1,null,0.09999999999999999,0.15,0,0],["qwen/qwen3.5-flash-02-23",1000000,65536,"text,image",1,null,0.065,0.26,0,0.08125],["qwen/qwen3.5-plus-02-15",1000000,65536,"text,image",1,null,0.26,1.56,0,0.325],["qwen/qwen3.5-plus-20260420",1000000,65536,"text,image",1,null,0.3,1.7999999999999998,0,0.375],["qwen/qwen3.6-27b",262144,131072,"text,image",1,null,0.28900000000000003,2.4,0.15,0],["qwen/qwen3.6-35b-a3b",262144,262144,"text,image",1,null,0.14,1,0.049999999999999996,0],["qwen/qwen3.6-flash",1000000,65536,"text,image",1,null,0.1875,1.125,0,0.234375],["qwen/qwen3.6-max-preview",262144,65536,"text",1,null,1.04,6.24,0,1.3],["qwen/qwen3.6-plus",1000000,65536,"text",1,null,0.325,1.95,0,0.40625],["qwen/qwen3.6-plus-preview:free",1000000,32000,"text",1,null,0,0,0,0],["qwen/qwen3.6-plus:free",1000000,65536,"text,image",1,null,0,0,0,0],["qwen/qwen3.7-max",1000000,65536,"text",1,null,1.475,4.425,0.295,1.84375],["qwen/qwen3.7-plus",1000000,65536,"text,image",1,null,0.32,1.28,0.064,0.39999999999999997],["qwen/qwq-32b",131072,131072,"text",1,null,0.15,0.58,0,0],["reka/reka-edge",16384,16384,"text,image",0,null,0.09999999999999999,0.09999999999999999,0,0],["rekaai/reka-edge",16384,16384,"text,image",0,null,0.09999999999999999,0.09999999999999999,0,0],["relace/relace-search",256000,128000,"text",0,null,1,3,0,0],["sakana/fugu-ultra",1000000,128000,"text,image",1,null,5,30,0.5,0],["sao10k/l3-euryale-70b",8192,8192,"text",0,null,1.48,1.48,0,0],["sao10k/l3.1-euryale-70b",131072,16384,"text",0,null,0.85,0.85,0,0],["stepfun/step-3.5-flash",262144,65536,"text",0,null,0.09999999999999999,0.3,0.02,0],["stepfun/step-3.5-flash:free",256000,256000,"text",1,null,0,0,0,0],["stepfun/step-3.7-flash",262144,256000,"text,image",1,null,0.19999999999999998,1.15,0.04,0],["tencent/hy3",262144,128000,"text",1,null,0.13199999999999998,0.5279999999999999,0.032999999999999995,0],["tencent/hy3-preview",262144,64000,"text",1,null,0.063,0.21,0.020999999999999998,0],["tencent/hy3-preview:free",262144,262144,"text",1,null,0,0,0,0],["tencent/hy3:free",262144,262144,"text",1,null,0,0,0,0],["thedrummer/rocinante-12b",32768,32768,"text",0,null,0.16999999999999998,0.43,0,0],["thedrummer/unslopnemo-12b",32768,32768,"text",0,null,0.39999999999999997,0.39999999999999997,0,0],["thinkingmachines/inkling",1048576,8888,"text,image",1,null,1,4.05,0.16999999999999998,0],["tngtech/deepseek-r1t2-chimera",163840,163840,"text",1,null,0.3,1.1,0.15,0],["tngtech/tng-r1t-chimera",163840,65536,"text",1,null,0.25,0.85,0.125,0],["upstage/solar-pro-3",128000,8888,"text",1,null,0.15,0.6,0.015,0],["upstage/solar-pro-3:free",128000,8888,"text",1,null,0,0,0,0],["x-ai/grok-3",131072,8888,"text",0,null,3,15,0.75,0],["x-ai/grok-3-beta",131072,8888,"text",0,null,3,15,0.75,0],["x-ai/grok-3-mini",131072,8888,"text",1,null,0.3,0.5,0.075,0],["x-ai/grok-3-mini-beta",131072,8888,"text",1,null,0.3,0.5,0.075,0],["x-ai/grok-4",256000,64000,"text,image",1,null,3,15,0.75,0],["x-ai/grok-4-fast",2000000,30000,"text,image",1,null,0.19999999999999998,0.5,0.049999999999999996,0],["x-ai/grok-4.1-fast",2000000,30000,"text,image",1,null,0.19999999999999998,0.5,0.049999999999999996,0],["x-ai/grok-4.20",2000000,8888,"text,image",1,null,1.25,2.5,0.19999999999999998,0],["x-ai/grok-4.20-beta",2000000,8888,"text,image",1,null,2,6,0.19999999999999998,0],["x-ai/grok-4.3",1000000,1000000,"text,image",1,null,1.25,2.5,0.19999999999999998,0],["x-ai/grok-4.5",500000,500000,"text,image",1,null,2,6,0.3,0],["x-ai/grok-4.6",500000,500000,"text,image",1,null,2,6,0.3,0],["x-ai/grok-4.7",500000,450000,"text,image",1,null,1.6,4.8,0.4,0],["x-ai/grok-build-0.1",256000,256000,"text,image",1,null,1,2,0.19999999999999998,0],["x-ai/grok-code-fast-1",256000,10000,"text",1,null,0.19999999999999998,1.5,0.02,0],["xiaomi/mimo-v2-flash",262144,65536,"text",1,null,0.09999999999999999,0.3,0.01,0],["xiaomi/mimo-v2-omni",262144,65536,"text,image",1,null,0.39999999999999997,2,0.08,0],["xiaomi/mimo-v2-pro",1048576,131072,"text",1,null,1,3,0.19999999999999998,0],["xiaomi/mimo-v2.5",1050000,131072,"text,image",1,null,0.14,0.28,0.0028,0],["xiaomi/mimo-v2.5-pro",1050000,131072,"text",1,null,0.435,0.87,0.0036,0],["xiaomi/mimo-v2.6-flash",1048576,131072,"text,image",1,null,0.14,0.28,0.0028,0],["xiaomi/mimo-v2.6-pro",1048576,131072,"text,image",1,null,0.435,0.87,0.0036,0],["xiaomi/mimo-v2.6-pro-ultraspeed",1048576,131072,"text,image",1,null,4.35,8.7,0.036,0],["z-ai/glm-4-32b",128000,8888,"text",0,null,0.09999999999999999,0.09999999999999999,0,0],["z-ai/glm-4.5",131072,98304,"text",1,null,0.6,2.2,0.11,0],["z-ai/glm-4.5-air",131072,98304,"text",1,null,0.13,0.85,0.024999999999999998,0],["z-ai/glm-4.5-air:free",131072,96000,"text",1,null,0,0,0,0],["z-ai/glm-4.5v",65536,16384,"text,image",1,null,0.6,1.7999999999999998,0.11,0],["z-ai/glm-4.6",204800,131072,"text",1,null,0.5,2,0.09999999999999999,0],["z-ai/glm-4.6:exacto",204800,131072,"text",1,null,0.44,1.76,0.11,0],["z-ai/glm-4.6v",131072,32768,"text,image",1,null,0.3,0.8999999999999999,0.055,0],["z-ai/glm-4.7",204800,131072,"text",1,null,0.39999999999999997,1.75,0.08,0],["z-ai/glm-4.7-flash",202752,16384,"text",1,null,0.06,0.39999999999999997,0.01,0],["z-ai/glm-5",204800,131072,"text",1,null,0.95,2.5500000000000003,0.19999999999999998,0],["z-ai/glm-5-turbo",202752,131072,"text",1,null,1.2,4,0.24,0],["z-ai/glm-5.1",204800,128000,"text",1,null,0.966,3.036,0.1794,0],["z-ai/glm-5.2",1048576,131072,"text",1,null,0.707,2.222,0.1313,0],["z-ai/glm-5.3",1048576,131072,"text",1,null,0.707,2.222,0.1313,0],["z-ai/glm-5v-turbo",202752,131072,"text,image",1,null,1.2,4,0.24,0]],
58
58
  "xai": [["grok-2",131072,8192,"text",0,null,2,10,2,0],["grok-2-1212",131072,8192,"text",0,null,2,10,2,0],["grok-2-latest",131072,8192,"text",0,null,2,10,2,0],["grok-2-vision",8192,4096,"text,image",0,null,2,10,2,0],["grok-2-vision-1212",8192,4096,"text,image",0,null,2,10,2,0],["grok-2-vision-latest",8192,4096,"text,image",0,null,2,10,2,0],["grok-3",131072,8192,"text",0,null,3,15,0.75,0],["grok-3-fast",131072,8192,"text",0,null,5,25,1.25,0],["grok-3-fast-latest",131072,8192,"text",0,null,5,25,1.25,0],["grok-3-latest",131072,8192,"text",0,null,3,15,0.75,0],["grok-3-mini",131072,8192,"text",1,null,0.3,0.5,0.075,0],["grok-3-mini-fast",131072,8192,"text",1,null,0.6,4,0.15,0],["grok-3-mini-fast-latest",131072,8192,"text",1,null,0.6,4,0.15,0],["grok-3-mini-latest",131072,8192,"text",1,null,0.3,0.5,0.075,0],["grok-4",256000,64000,"text",1,null,3,15,0.75,0],["grok-4-1-fast",2000000,30000,"text,image",1,null,0.2,0.5,0.05,0],["grok-4-1-fast-non-reasoning",2000000,30000,"text,image",0,null,0.2,0.5,0.05,0],["grok-4-fast",2000000,30000,"text,image",1,null,0.2,0.5,0.05,0],["grok-4-fast-non-reasoning",2000000,30000,"text,image",0,null,0.2,0.5,0.05,0],["grok-4.20-0309-non-reasoning",1000000,30000,"text,image",0,null,1.25,2.5,0.2,0],["grok-4.20-0309-reasoning",1000000,30000,"text,image",1,null,1.25,2.5,0.2,0],["grok-4.20-beta-latest-non-reasoning",2000000,30000,"text,image",0,null,2,6,0.2,0],["grok-4.20-beta-latest-reasoning",2000000,30000,"text,image",1,null,2,6,0.2,0],["grok-4.20-multi-agent-0309",1000000,30000,"text,image",1,null,1.25,2.5,0.2,0],["grok-4.20-multi-agent-beta-latest",2000000,30000,"text,image",1,null,2,6,0.2,0],["grok-4.3",1000000,30000,"text,image",1,null,1.25,2.5,0.2,0],["grok-4.5",500000,500000,"text,image",1,null,2,6,0.3,0],["grok-4.6",500000,500000,"text,image",1,null,2,6,0.3,0],["grok-4.7",500000,500000,"text,image",1,null,2,6,0.5,0],["grok-beta",131072,4096,"text",0,null,5,15,5,0],["grok-build-0.1",256000,256000,"text,image",1,null,1,2,0.2,0],["grok-code-fast-1",256000,10000,"text",1,null,0.2,1.5,0.02,0],["grok-composer-2.5-fast",200000,64000,"text",1,null,0,0,0,0],["grok-vision-beta",8192,4096,"text,image",0,null,5,15,5,0]],
59
59
  "xiaomi": [["mimo-v2-flash",262144,65536,"text",1,null,0.14,0.28,0.0028,0],["mimo-v2-omni",262144,131072,"text,image",1,null,0.14,0.28,0.0028,0],["mimo-v2-pro",1048576,131072,"text",1,null,0.435,0.87,0.0036,0],["mimo-v2.5",1048576,131072,"text,image",1,null,0.14,0.28,0.0028,0],["mimo-v2.5-pro",1048576,131072,"text",1,null,0.435,0.87,0.0036,0],["mimo-v2.5-pro-ultraspeed",1048576,131072,"text",1,null,1.305,2.61,0.0108,0],["mimo-v2.6-flash",1048576,131072,"text,image",1,null,0.14,0.28,0.0028,0],["mimo-v2.6-pro",1048576,131072,"text,image",1,null,0.435,0.87,0.0036,0],["mimo-v2.6-pro-ultraspeed",1048576,131072,"text,image",1,null,4.35,8.7,0.036,0]],
@@ -26,7 +26,7 @@ import { bridgeToResponsesSSE } from "../bridge";
26
26
  import { isTerminalRefusalIncomplete } from "../bridge/terminal-refusal";
27
27
  import { clearableDeadline, idleDeadline } from "../lib/abort";
28
28
  import { readBoundedResponseBody } from "../lib/bounded-body";
29
- import { applyUpstreamRecoveryInit, fetchWithResetRetry, prepareSameTarget429Wait, isNonReplayableResponse, SendBudgetExhaustedError } from "../lib/upstream-retry";
29
+ import { applyUpstreamRecoveryInit, fetchWithResetRetry, prepareSameTarget429Wait, isNonReplayableResponse, isSameTargetRetryHold, SendBudgetExhaustedError } from "../lib/upstream-retry";
30
30
  import { rateLimitRetryDelayMs } from "../providers/key-failover";
31
31
  import { releaseProviderRequestSlot, RequestPacingQueueOverloadError, sendTrackingRequestSlot, type ProviderRequestSlot } from "../providers/request-pacing";
32
32
  import {
@@ -713,7 +713,7 @@ export async function runWithImageBridge(deps: ImageBridgeDeps): Promise<Respons
713
713
  // Same-target 429 wait-and-retry (opt-in `retryOn429`) BEFORE key rotation: a primary-key
714
714
  // rate-limit blip replays on the SAME key; rotation only runs after attempts exhaust.
715
715
  while (
716
- prepared.response.status === 429
716
+ prepared.response.status === 429 && !isSameTargetRetryHold(prepared.response)
717
717
  && rateLimitRetryPolicy !== null
718
718
  && rateLimitRetries < rateLimitRetryPolicy.attempts
719
719
  ) {
@@ -10,30 +10,39 @@
10
10
  * and every launcher spawn re-transpiled its whole CLI graph from nothing.
11
11
  *
12
12
  * A per-version subdirectory keeps each runtime's entries stable. Bun creates the directory.
13
+ *
14
+ * The scoped directory is always beneath the configured path: `bun-<version>` is appended as a
15
+ * new leaf, and a basename is never treated as a reason to rewrite the path to its parent. A
16
+ * configured `.../bun-9.9.9` is an ordinary directory that gains a child — the operator's
17
+ * parent is not handed to another version. Only when the path's own final segment is exactly
18
+ * `bun-<version>` of the runtime being started is it kept unchanged, so a launcher started
19
+ * from a launched process reaches the same warm directory. A chain that changes versions
20
+ * therefore nests inward — `cache/bun-A` started on B yields `cache/bun-A/bun-B` — while an
21
+ * independent launch configured with the original base still lands one level down.
13
22
  * A disabled cache ("0" or empty), an unset one, or an unknown version is left as given.
14
23
  * Windows environment names are case-insensitive (Bun's lookup too) while this object is not,
15
24
  * so on win32 every spelling of the name is matched and replaced by one scoped entry.
16
- * A cache that is already scoped (a launcher started from a launched process) is re-scoped in
17
- * place, never nested, so the same runtime keeps reaching the same warm directory.
18
25
  */
19
26
  export const TRANSPILER_CACHE_ENV = "BUN_RUNTIME_TRANSPILER_CACHE_PATH";
20
27
 
21
28
  // Semver core, optional prerelease and build metadata (findPathBun accepts `+build`). The
22
29
  // alphabet has no separator, drive colon or NUL, so the segment cannot leave the cache.
23
30
  const VERSION = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;
24
- const SCOPED_TAIL = /^(.*?)([\\/]*)(bun-[^\\/]+)[\\/]*$/;
25
31
  const DRIVE = /^[A-Za-z]:$/;
32
+ const WIN_TAIL = /^(?:.*[\\/])?([^\\/]+)[\\/]*$/;
33
+ const POSIX_TAIL = /^(?:.*\/)?([^/]+)\/*$/;
26
34
 
27
- /** The directory a scoped cache lives in, or null when the path is not a bun-<version> scope. */
28
- function scopeParent(cache) {
29
- const tail = SCOPED_TAIL.exec(cache);
30
- if (!tail || !validVersion(tail[3].slice(4))) return null;
31
- const [, prefix, separator] = tail;
32
- // Without a separator the segment must start the path ("bun-1.4.2") or follow a drive
33
- // ("C:bun-1.4.2", drive-relative); "xbun-1.4.2" is an ordinary directory name.
34
- if (separator === "") return prefix === "" ? "." : DRIVE.test(prefix) ? prefix : null;
35
- // At a filesystem or drive root ("/", "C:\\") keep one separator: a bare "C:" is drive-relative.
36
- return prefix === "" || DRIVE.test(prefix) ? prefix + separator[0] : prefix;
35
+ /**
36
+ * The path's final segment the way the running platform parses it — "/" and "\\" separate on
37
+ * Windows while "/" alone does on POSIX, where a backslash is an ordinary character. A bare
38
+ * drive-letter prefix is a boundary, so "C:bun-1.4.3" is the drive-relative leaf "bun-1.4.3".
39
+ * A bare root has no segment and returns null.
40
+ */
41
+ function leaf(cache, isWindows) {
42
+ const tail = (isWindows ? WIN_TAIL : POSIX_TAIL).exec(cache);
43
+ if (!tail) return null;
44
+ const name = tail[1];
45
+ return isWindows && name.length > 2 && DRIVE.test(name.slice(0, 2)) ? name.slice(2) : name;
37
46
  }
38
47
 
39
48
  /** @param {unknown} version */
@@ -57,12 +66,17 @@ export function scopeTranspilerCacheToRuntime(env, runtimeVersion, join, platfor
57
66
  const cache = name === undefined ? undefined : env[name];
58
67
  if (typeof cache !== "string" || cache === "" || cache === "0") return env;
59
68
  if (!validVersion(runtimeVersion)) return env;
60
- const base = scopeParent(cache) ?? cache;
69
+ const segment = `bun-${runtimeVersion}`;
70
+ const isWindows = platform === "win32";
71
+ const current = leaf(cache, isWindows);
72
+ // The filesystems that fold the environment name's case fold the leaf's too.
73
+ const alreadyScoped = current !== null
74
+ && (isWindows ? current.toLowerCase() === segment.toLowerCase() : current === segment);
61
75
  const scoped = { ...env };
62
76
  for (const variant of names) delete scoped[variant];
63
- const segment = `bun-${runtimeVersion}`;
64
- // join("C:", x) yields "C:\\x"; a drive-relative parent must stay drive-relative.
65
- scoped[TRANSPILER_CACHE_ENV] = DRIVE.test(base) ? base + segment : join(base, segment);
77
+ // join("C:", x) yields "C:\\x"; a drive-relative path must stay drive-relative.
78
+ scoped[TRANSPILER_CACHE_ENV] = alreadyScoped ? cache
79
+ : DRIVE.test(cache) ? cache + segment : join(cache, segment);
66
80
  return scoped;
67
81
  }
68
82
 
@@ -0,0 +1,14 @@
1
+ /** Internal RequestInit metadata; never serialized into headers or upstream JSON. */
2
+ export const PROVIDER_HEADER_DEADLINE = Symbol("provider-header-deadline");
3
+ export type ProviderHeaderDeadline = { clientSignal: AbortSignal; pause(): void; resume(): void };
4
+
5
+ /** A local admission queue waits on client cancellation, outside the upstream header timer. */
6
+ export async function waitOutsideProviderHeaderDeadline<T>(
7
+ init: RequestInit | undefined,
8
+ wait: (signal?: AbortSignal) => Promise<T>,
9
+ ): Promise<T> {
10
+ const deadline = (init as (RequestInit & { [PROVIDER_HEADER_DEADLINE]?: ProviderHeaderDeadline }) | undefined)?.[PROVIDER_HEADER_DEADLINE];
11
+ deadline?.pause();
12
+ try { return await wait(deadline?.clientSignal ?? init?.signal ?? undefined); }
13
+ finally { deadline?.resume(); }
14
+ }
@@ -268,19 +268,54 @@ export function removeServiceApiTokenFileIfOwned(
268
268
  * token file into the environment). Pure: returns the token or null — the CALLER
269
269
  * assigns it to process.env.OPENCODEX_API_AUTH_TOKEN. Loads only when the env token
270
270
  * is empty and OCX_API_TOKEN_FILE names a readable file.
271
+ *
272
+ * OCX_API_TOKEN_FILE is inherited from the environment, so the path is untrusted: the read
273
+ * goes through one no-follow, nonblocking descriptor, accepts only a regular file of at most
274
+ * MAX_SERVICE_API_TOKEN_BYTES, and returns only a single-line printable token. Anything else
275
+ * (a FIFO, device, symlink, oversized or multi-line file) loads nothing.
271
276
  */
272
277
  export function loadServiceTokenFromFile(env: Record<string, string | undefined>): string | null {
273
278
  if (env.OPENCODEX_API_AUTH_TOKEN?.trim()) return null;
274
279
  const file = env.OCX_API_TOKEN_FILE?.trim();
275
280
  if (!file) return null;
281
+ const flags = process.platform === "win32"
282
+ ? constants.O_RDONLY
283
+ : constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK;
284
+ let fd: number | undefined;
276
285
  try {
277
- const token = readFileSync(file, "utf8").trim();
278
- return token || null;
286
+ // Windows has no O_NOFOLLOW: refuse a link up front, then bind the opened descriptor to the
287
+ // entry by identity so a link swapped in between lstat and open is still refused.
288
+ const entry = process.platform === "win32" ? lstatSync(file, { bigint: true }) : undefined;
289
+ if (entry?.isSymbolicLink()) return null;
290
+ fd = openSync(file, flags);
291
+ const stat = fstatSync(fd, { bigint: true });
292
+ if (!stat.isFile() || stat.size > BigInt(MAX_SERVICE_API_TOKEN_BYTES)) return null;
293
+ if (entry) {
294
+ const after = lstatSync(file, { bigint: true });
295
+ if (after.isSymbolicLink() || after.dev !== stat.dev || after.ino !== stat.ino || entry.ino !== stat.ino || entry.dev !== stat.dev) return null;
296
+ }
297
+ const buffer = Buffer.alloc(MAX_SERVICE_API_TOKEN_BYTES + 1);
298
+ let length = 0;
299
+ while (length < buffer.length) {
300
+ const count = readSync(fd, buffer, length, buffer.length - length, null);
301
+ if (count === 0) break;
302
+ length += count;
303
+ }
304
+ if (length > MAX_SERVICE_API_TOKEN_BYTES) return null;
305
+ const token = buffer.subarray(0, length).toString("utf8").trim();
306
+ return SERVICE_TOKEN_FILE_SHAPE.test(token) ? token : null;
279
307
  } catch {
280
308
  return null;
309
+ } finally {
310
+ if (fd !== undefined) {
311
+ try { closeSync(fd); } catch { /* already closed */ }
312
+ }
281
313
  }
282
314
  }
283
315
 
316
+ /** One line of printable, non-space ASCII: never JSON with newlines, binary, or a second line. */
317
+ const SERVICE_TOKEN_FILE_SHAPE = /^[\x21-\x7e]{1,4096}$/;
318
+
284
319
  /**
285
320
  * The data-plane token a boot should export, or null when the environment already has one
286
321
  * (or there is nothing to export).
@@ -23,7 +23,7 @@ export type TranslatorBufferKind =
23
23
  | "cursor_kv"
24
24
  | "request_copies";
25
25
 
26
- export type ExternallyCappedKind = "passthrough_serialization" | "mcp_payload";
26
+ export type ExternallyCappedKind = "passthrough_serialization" | "mcp_payload" | "provider_image_upload";
27
27
 
28
28
  export class TranslatorBudgetExceededError extends Error {
29
29
  readonly code = "translation_buffer_limit";
@@ -34,6 +34,20 @@ export function markResponseNonReplayable(response: Response): void {
34
34
  nonReplayableResponses.add(response);
35
35
  }
36
36
 
37
+ /**
38
+ * A server-instructed wait longer than the retry budget: same-target 429 replay loops stop and
39
+ * return the original response, while key rotation and ordinary error delivery are unaffected.
40
+ */
41
+ const sameTargetRetryHolds = new WeakSet<Response>();
42
+
43
+ export function markSameTargetRetryHold(response: Response): void {
44
+ sameTargetRetryHolds.add(response);
45
+ }
46
+
47
+ export function isSameTargetRetryHold(response: Response): boolean {
48
+ return sameTargetRetryHolds.has(response);
49
+ }
50
+
37
51
  export function isNonReplayableResponse(response: Response): boolean {
38
52
  return nonReplayableResponses.has(response);
39
53
  }
@@ -144,6 +158,7 @@ export function retainReplayRefusal<T extends Response>(response: T): T {
144
158
 
145
159
  /** Carry the verdict from a response onto the one that replaces it. */
146
160
  export function carryReplayRefusal<T extends Response>(source: Response, rewrapped: T): T {
161
+ if (sameTargetRetryHolds.has(source)) sameTargetRetryHolds.add(rewrapped);
147
162
  return isReplayRefusalResponse(source) ? retainReplayRefusal(rewrapped) : rewrapped;
148
163
  }
149
164
 
@@ -1,6 +1,7 @@
1
1
  import { validateAntigravityImportCredential } from "../google-antigravity";
2
2
  import { upsertCredentialByIdentity } from "../store";
3
3
  import type { OAuthCredentials } from "../types";
4
+ import { probeAntigravityUsageQuota } from "../../providers/quota/antigravity";
4
5
  import {
5
6
  ACCOUNT_IMPORT_FORMAT,
6
7
  ACCOUNT_IMPORT_MAX_EMAIL_LENGTH,
@@ -14,6 +15,26 @@ import {
14
15
  export interface AntigravityImportAdapterDeps {
15
16
  validate(refreshToken: string, signal?: AbortSignal): Promise<ValidatedAntigravityCredential>;
16
17
  upsert(credential: OAuthCredentials): Promise<"inserted" | "updated">;
18
+ /**
19
+ * Prove that the freshly validated account token can use an operator-supplied project.
20
+ * Without this owner a fallback project is never admitted.
21
+ */
22
+ verifyProject?(accessToken: string, projectId: string, signal?: AbortSignal): Promise<boolean>;
23
+ }
24
+
25
+ /**
26
+ * The account-bound admission probe for a fallback project: the same Cloud Code Assist quota
27
+ * probe the account pool runs, authenticated with this account's own access token against the
28
+ * named project. Only a parsed quota answer admits it; denial, rate limiting, transport failure
29
+ * or an unusable body all keep the record out.
30
+ */
31
+ export async function verifyAntigravityImportProject(accessToken: string, projectId: string, signal?: AbortSignal): Promise<boolean> {
32
+ if (signal?.aborted) return false;
33
+ try {
34
+ return (await probeAntigravityUsageQuota(accessToken, projectId, signal)).kind === "available" && !signal?.aborted;
35
+ } catch {
36
+ return false;
37
+ }
17
38
  }
18
39
 
19
40
  function safeProviderEmail(value: unknown): string | null {
@@ -32,6 +53,7 @@ export function createAntigravityAccountImportAdapter(
32
53
  deps: AntigravityImportAdapterDeps = {
33
54
  validate: validateAntigravityImportCredential,
34
55
  upsert: credential => upsertCredentialByIdentity(ACCOUNT_IMPORT_PROVIDER, credential),
56
+ verifyProject: verifyAntigravityImportProject,
35
57
  },
36
58
  ): AccountImportAdapter {
37
59
  return {
@@ -52,15 +74,29 @@ export function createAntigravityAccountImportAdapter(
52
74
  const providerEmail = safeProviderEmail(credential.email);
53
75
  if (!providerEmail) return { status: "failed", code: "credential_rejected" };
54
76
  if (providerEmail !== record.email) return { status: "failed", code: "identity_mismatch" };
55
- if (typeof credential.projectId !== "string" || credential.projectId.length === 0) {
56
- return { status: "failed", code: "missing_project" };
77
+ // Automatic discovery wins: a discovered project is used as-is and the record's project_id
78
+ // is ignored. The record's project is a fallback only, admitted after an account-bound probe.
79
+ let projectId = typeof credential.projectId === "string" && credential.projectId.length > 0
80
+ ? credential.projectId
81
+ : undefined;
82
+ if (!projectId && record.projectId && deps.verifyProject) {
83
+ let admitted = false;
84
+ try {
85
+ admitted = await deps.verifyProject(credential.access, record.projectId, signal);
86
+ } catch {
87
+ admitted = false;
88
+ }
89
+ throwIfAccountImportAborted(signal);
90
+ if (admitted) projectId = record.projectId;
57
91
  }
92
+ if (!projectId) return { status: "failed", code: "missing_project" };
58
93
 
59
94
  throwIfAccountImportAborted(signal);
60
95
  try {
61
96
  const disposition = await deps.upsert({
62
97
  ...credential,
63
98
  email: providerEmail,
99
+ projectId,
64
100
  source: "credential-file",
65
101
  });
66
102
  return disposition === "updated"
@@ -1,13 +1,17 @@
1
1
  import {
2
2
  ACCOUNT_IMPORT_MAX_BYTES,
3
3
  ACCOUNT_IMPORT_MAX_EMAIL_LENGTH,
4
+ ACCOUNT_IMPORT_MAX_PROJECT_ID_LENGTH,
4
5
  ACCOUNT_IMPORT_MAX_RECORDS,
5
6
  ACCOUNT_IMPORT_MAX_REFRESH_TOKEN_BYTES,
6
7
  type ParsedCockpitRecord,
7
8
  } from "./types";
8
9
 
9
10
  const encoder = new TextEncoder();
10
- const ALLOWED_RECORD_KEYS = new Set(["email", "refresh_token", "tags", "notes"]);
11
+ const ALLOWED_RECORD_KEYS = new Set(["email", "refresh_token", "project_id", "tags", "notes"]);
12
+ // Google Cloud project id grammar: a lowercase letter, then lowercase letters, digits or hyphens,
13
+ // not ending in a hyphen. Exact match only — no trimming, so whitespace or controls are rejected.
14
+ const PROJECT_ID_SHAPE = /^[a-z][a-z0-9-]*[a-z0-9]$/;
11
15
 
12
16
  export type CockpitDocumentParseResult =
13
17
  | { ok: true; records: ParsedCockpitRecord[] }
@@ -50,10 +54,18 @@ function validMetadata(record: Record<string, unknown>): boolean {
50
54
  return record.notes === undefined || typeof record.notes === "string";
51
55
  }
52
56
 
57
+ function validProjectId(value: unknown): value is string | undefined {
58
+ if (value === undefined) return true;
59
+ return typeof value === "string"
60
+ && value.length >= 6
61
+ && value.length <= ACCOUNT_IMPORT_MAX_PROJECT_ID_LENGTH
62
+ && PROJECT_ID_SHAPE.test(value);
63
+ }
64
+
53
65
  function parseRecord(value: unknown, index: number): ParsedCockpitRecord {
54
66
  if (!isPlainRecord(value)) return { index, code: "invalid_record" };
55
67
  if (Object.keys(value).some(key => !ALLOWED_RECORD_KEYS.has(key))) return { index, code: "invalid_record" };
56
- if (!validEmail(value.email) || !validRefreshToken(value.refresh_token) || !validMetadata(value)) {
68
+ if (!validEmail(value.email) || !validRefreshToken(value.refresh_token) || !validProjectId(value.project_id) || !validMetadata(value)) {
57
69
  return { index, code: "invalid_record" };
58
70
  }
59
71
  return {
@@ -61,6 +73,7 @@ function parseRecord(value: unknown, index: number): ParsedCockpitRecord {
61
73
  record: {
62
74
  email: value.email.toLowerCase(),
63
75
  refreshToken: value.refresh_token,
76
+ ...(typeof value.project_id === "string" ? { projectId: value.project_id } : {}),
64
77
  },
65
78
  };
66
79
  }
@@ -11,6 +11,8 @@ export const ACCOUNT_IMPORT_MAX_REQUEST_BYTES = ACCOUNT_IMPORT_MAX_BYTES + 1024;
11
11
  export const ACCOUNT_IMPORT_DEADLINE_MS = 600_000;
12
12
  export const ACCOUNT_IMPORT_MAX_RECORDS = 25;
13
13
  export const ACCOUNT_IMPORT_MAX_EMAIL_LENGTH = 254;
14
+ /** Google Cloud project ids are 6–30 characters; anything longer cannot name a project. */
15
+ export const ACCOUNT_IMPORT_MAX_PROJECT_ID_LENGTH = 30;
14
16
  export const ACCOUNT_IMPORT_MAX_REFRESH_TOKEN_BYTES = 16 * 1024;
15
17
 
16
18
  export type AccountImportStatus = "imported" | "updated" | "failed" | "unsupported";
@@ -65,6 +67,11 @@ export function throwIfAccountImportAborted(signal?: AbortSignal): void {
65
67
  export interface CockpitAccountRecord {
66
68
  email: string;
67
69
  refreshToken: string;
70
+ /**
71
+ * Operator-supplied Cloud Code Assist project, used only when automatic discovery finds none
72
+ * and only after the account's own token proves it can use that project.
73
+ */
74
+ projectId?: string;
68
75
  }
69
76
 
70
77
  export type ParsedCockpitRecord =
@@ -46,7 +46,16 @@ export function extractEmail(idToken?: string, accessToken?: string): string | u
46
46
  if (!token) continue;
47
47
  const payload = decodeJwtPayload(token);
48
48
  if (!payload) continue;
49
- if (typeof payload.email === "string") return payload.email.toLowerCase();
49
+ if (typeof payload.email === "string" && payload.email.trim()) {
50
+ return payload.email.trim().toLowerCase();
51
+ }
52
+ const profile = payload["https://api.openai.com/profile"];
53
+ if (profile && typeof profile === "object" && !Array.isArray(profile)) {
54
+ const email = (profile as Record<string, unknown>).email;
55
+ if (typeof email === "string" && email.trim()) {
56
+ return email.trim().toLowerCase();
57
+ }
58
+ }
50
59
  }
51
60
  return undefined;
52
61
  }
package/src/oauth/dsh.ts CHANGED
@@ -9,6 +9,7 @@
9
9
  */
10
10
 
11
11
  import type { OAuthController, OAuthCredentials } from "./types";
12
+ import { readBoundedResponseBody } from "../lib/bounded-body";
12
13
  import { homedir } from "node:os";
13
14
  import { join } from "node:path";
14
15
  import { existsSync, readFileSync } from "node:fs";
@@ -16,6 +17,20 @@ import { existsSync, readFileSync } from "node:fs";
16
17
  export const DSH_PLATFORM_ORIGIN = "https://platform.deepseek.com";
17
18
  export const DSH_INFERENCE_ORIGIN = "https://api.deepseek.com/anthropic";
18
19
 
20
+ /**
21
+ * Byte ceiling for the profile document returned by /auth-api/v0/users/current.
22
+ *
23
+ * A legitimate profile is a small fixed-shape JSON object (code, data.biz_code,
24
+ * biz_data.id/email/id_profile{name,picture}) well under a few KiB; 64 KiB matches
25
+ * the shared bounded-body ceiling and still leaves orders of magnitude of
26
+ * headroom. Anything larger is rejected before parsing so a hostile or broken
27
+ * upstream cannot turn an import validation into unbounded memory work.
28
+ */
29
+ export const DSH_PROFILE_MAX_BYTES = 64 * 1024;
30
+
31
+ /** Wall-clock budget for the profile request and its body read, in milliseconds. */
32
+ const DSH_PROFILE_FETCH_TIMEOUT_MS = 10_000;
33
+
19
34
  export interface DshAccountDetectionResult {
20
35
  detected: boolean;
21
36
  token?: string;
@@ -80,7 +95,7 @@ export async function validateDshAccountToken(
80
95
  signal?: AbortSignal,
81
96
  ): Promise<DshValidatedAccountIdentity> {
82
97
  try {
83
- const timeoutSignal = AbortSignal.timeout(10_000);
98
+ const timeoutSignal = AbortSignal.timeout(DSH_PROFILE_FETCH_TIMEOUT_MS);
84
99
  const combinedSignal = signal ? AbortSignal.any([signal, timeoutSignal]) : timeoutSignal;
85
100
  const response = await fetch(`${DSH_PLATFORM_ORIGIN}/auth-api/v0/users/current`, {
86
101
  method: "GET",
@@ -99,7 +114,35 @@ export async function validateDshAccountToken(
99
114
  return { valid: false, error: `Platform returned HTTP ${response.status}` };
100
115
  }
101
116
 
102
- const body = (await response.json()) as {
117
+ // A declared length past the cap is rejected without touching the stream.
118
+ const declaredLength = Number(response.headers.get("content-length"));
119
+ if (Number.isFinite(declaredLength) && declaredLength > DSH_PROFILE_MAX_BYTES) {
120
+ try {
121
+ void response.body?.cancel(
122
+ new DOMException("DSH profile response is too large", "QuotaExceededError"),
123
+ ).catch(() => undefined);
124
+ } catch {
125
+ // Best-effort cancellation only.
126
+ }
127
+ return { valid: false, error: "PROFILE_VALIDATION_FAILED" };
128
+ }
129
+
130
+ // Missing or understated Content-Length still meets the cap on the decoded
131
+ // stream itself: once an over-limit byte is observed the retained buffer is
132
+ // discarded and cancellation is requested on the body. Malformed UTF-8 fails
133
+ // closed so a replacement character can never alter the authoritative ID.
134
+ const bounded = await readBoundedResponseBody(response, {
135
+ signal: combinedSignal,
136
+ maxBytes: DSH_PROFILE_MAX_BYTES,
137
+ totalTimeoutMs: DSH_PROFILE_FETCH_TIMEOUT_MS,
138
+ inactivityTimeoutMs: DSH_PROFILE_FETCH_TIMEOUT_MS,
139
+ fatalUtf8: true,
140
+ });
141
+ if (bounded.oversized || bounded.truncated || !bounded.displaySafe) {
142
+ return { valid: false, error: "PROFILE_VALIDATION_FAILED" };
143
+ }
144
+
145
+ const body = JSON.parse(bounded.text) as {
103
146
  code?: number;
104
147
  data?: {
105
148
  biz_code?: number;