@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
@@ -0,0 +1 @@
1
+ import{n as e,w as t,y as n}from"./index-TmaHa54u.js";var r=e(),i=e=>({viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:2,strokeLinecap:`round`,strokeLinejoin:`round`,...e}),a=e=>(0,r.jsxs)(`svg`,{...i(e),children:[(0,r.jsx)(`rect`,{x:`3`,y:`3`,width:`7`,height:`7`,rx:`1.5`}),(0,r.jsx)(`rect`,{x:`14`,y:`3`,width:`7`,height:`7`,rx:`1.5`}),(0,r.jsx)(`rect`,{x:`3`,y:`14`,width:`7`,height:`7`,rx:`1.5`}),(0,r.jsx)(`rect`,{x:`14`,y:`14`,width:`7`,height:`7`,rx:`1.5`})]}),o=e=>(0,r.jsxs)(`svg`,{...i(e),children:[(0,r.jsx)(`rect`,{x:`3`,y:`4`,width:`18`,height:`7`,rx:`2`}),(0,r.jsx)(`rect`,{x:`3`,y:`13`,width:`18`,height:`7`,rx:`2`}),(0,r.jsx)(`path`,{d:`M7 7.5h.01M7 16.5h.01`})]}),s=e=>(0,r.jsxs)(`svg`,{...i(e),children:[(0,r.jsx)(`path`,{d:`M12 2 4 6v6l8 4 8-4V6l-8-4Z`}),(0,r.jsx)(`path`,{d:`m4 6 8 4 8-4M12 10v8`})]}),c=e=>(0,r.jsxs)(`svg`,{...i(e),children:[(0,r.jsx)(`rect`,{x:`4`,y:`8`,width:`16`,height:`11`,rx:`3`}),(0,r.jsx)(`path`,{d:`M12 8V4M8 2h8`}),(0,r.jsx)(`circle`,{cx:`9`,cy:`13`,r:`1`}),(0,r.jsx)(`circle`,{cx:`15`,cy:`13`,r:`1`})]}),l=e=>(0,r.jsx)(`svg`,{...i(e),children:(0,r.jsx)(`path`,{d:`M8 6h13M8 12h13M8 18h13M3 6h.01M3 12h.01M3 18h.01`})}),u=e=>(0,r.jsx)(`svg`,{...i(e),children:(0,r.jsx)(`path`,{d:`M4 6h16M4 12h16M4 18h16`})}),d=e=>(0,r.jsxs)(`svg`,{...i(e),children:[(0,r.jsx)(`rect`,{x:`3`,y:`4`,width:`18`,height:`16`,rx:`2`}),(0,r.jsx)(`path`,{d:`M9 4v16`})]}),f=e=>(0,r.jsxs)(`svg`,{...i(e),children:[(0,r.jsx)(`path`,{d:`m4 17 6-5-6-5`}),(0,r.jsx)(`path`,{d:`M12 19h8`})]}),p=e=>(0,r.jsx)(`svg`,{...i(e),children:(0,r.jsx)(`path`,{d:`M22 12h-4l-3 9L9 3l-3 9H2`})}),m=e=>(0,r.jsxs)(`svg`,{...i(e),children:[(0,r.jsx)(`path`,{d:`M22 12H2`}),(0,r.jsx)(`path`,{d:`M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11Z`}),(0,r.jsx)(`path`,{d:`M6 16h.01M10 16h.01`})]}),h=e=>(0,r.jsx)(`svg`,{...i(e),children:(0,r.jsx)(`path`,{d:`m20 6-11 11-5-5`})}),g=e=>(0,r.jsx)(`svg`,{...i(e),children:(0,r.jsx)(`path`,{d:`M18 6 6 18M6 6l12 12`})}),ee=e=>(0,r.jsx)(`svg`,{...i(e),children:(0,r.jsx)(`path`,{d:`M12 5v14M5 12h14`})}),_=e=>(0,r.jsx)(`svg`,{...i(e),children:(0,r.jsx)(`path`,{d:`M5 12h14`})}),te=e=>(0,r.jsx)(`svg`,{...i(e),children:(0,r.jsx)(`path`,{d:`M21 12a9 9 0 0 1-9 9 9.8 9.8 0 0 1-6.7-2.7L3 16M3 21v-5h5M3 12a9 9 0 0 1 9-9 9.8 9.8 0 0 1 6.7 2.7L21 8M21 3v5h-5`})}),ne=e=>(0,r.jsx)(`svg`,{...i(e),children:(0,r.jsx)(`path`,{d:`M8 5v14M16 5v14`})}),re=e=>(0,r.jsx)(`svg`,{...i(e),children:(0,r.jsx)(`path`,{d:`m7 4 13 8-13 8Z`})}),ie=e=>(0,r.jsx)(`svg`,{...i(e),children:(0,r.jsx)(`path`,{d:`M3 6h18M8 6V4h8v2M19 6l-1 14H6L5 6`})}),ae=e=>(0,r.jsx)(`svg`,{...i(e),children:(0,r.jsx)(`path`,{d:`m3 3 18 18M10.6 10.6a2 2 0 0 0 2.8 2.8M9.9 4.2A10.8 10.8 0 0 1 12 4c5 0 9 4 10 8a12.7 12.7 0 0 1-2 4.1M6.6 6.6A12.4 12.4 0 0 0 2 12c1 4 5 8 10 8 1.5 0 2.9-.4 4.1-1`})}),oe=e=>(0,r.jsxs)(`svg`,{...i(e),children:[(0,r.jsx)(`path`,{d:`M12 20h9`}),(0,r.jsx)(`path`,{d:`M16.5 3.5a2.1 2.1 0 0 1 3 3L7 19l-4 1 1-4Z`})]}),se=e=>(0,r.jsxs)(`svg`,{...i(e),children:[(0,r.jsx)(`path`,{d:`M10.3 3.7 1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.7a2 2 0 0 0-3.4 0Z`}),(0,r.jsx)(`path`,{d:`M12 9v4M12 17h.01`})]}),ce=e=>(0,r.jsxs)(`svg`,{...i(e),children:[(0,r.jsx)(`circle`,{cx:`12`,cy:`12`,r:`10`}),(0,r.jsx)(`path`,{d:`M12 16v-4M12 8h.01`})]}),le=e=>(0,r.jsxs)(`svg`,{...i(e),children:[(0,r.jsx)(`circle`,{cx:`11`,cy:`11`,r:`7`}),(0,r.jsx)(`path`,{d:`m21 21-4.3-4.3`})]}),ue=e=>(0,r.jsx)(`svg`,{...i(e),children:(0,r.jsx)(`path`,{d:`M12 19V5M5 12l7-7 7 7`})}),de=e=>(0,r.jsx)(`svg`,{...i(e),children:(0,r.jsx)(`path`,{d:`M12 5v14M19 12l-7 7-7-7`})}),fe=e=>(0,r.jsx)(`svg`,{...i(e),children:(0,r.jsx)(`path`,{d:`M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4M7 10l5 5 5-5M12 15V3`})}),pe=e=>(0,r.jsx)(`svg`,{...i(e),children:(0,r.jsx)(`path`,{d:`m9 18 6-6-6-6`})}),me=e=>(0,r.jsx)(`svg`,{...i(e),children:(0,r.jsx)(`path`,{d:`M9 19c-5 1.5-5-2.5-7-3m14 6v-3.9a3.4 3.4 0 0 0-.9-2.6c3-.3 6.2-1.5 6.2-6.7A5.2 5.2 0 0 0 20 4.8 4.9 4.9 0 0 0 19.9 1S18.7.6 16 2.5a13.4 13.4 0 0 0-7 0C6.3.6 5.1 1 5.1 1A4.9 4.9 0 0 0 5 4.8a5.2 5.2 0 0 0-1.4 3.7c0 5.1 3.1 6.4 6.1 6.7a3.4 3.4 0 0 0-.9 2.5V22`})}),he=e=>(0,r.jsxs)(`svg`,{...i(e),children:[(0,r.jsx)(`path`,{d:`M18.4 5.6a9 9 0 1 1-12.8 0`}),(0,r.jsx)(`path`,{d:`M12 2v10`})]}),ge=e=>(0,r.jsx)(`svg`,{...i(e),children:(0,r.jsx)(`path`,{d:`M15 3h6v6M10 14 21 3M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6`})}),_e=e=>(0,r.jsxs)(`svg`,{...i(e),children:[(0,r.jsx)(`circle`,{cx:`7.5`,cy:`15.5`,r:`4.5`}),(0,r.jsx)(`path`,{d:`m10.7 12.3 9.6-9.6M16 7l3 3M14 9l2 2`})]}),ve=e=>(0,r.jsx)(`svg`,{viewBox:`0 0 32 32`,fill:`none`,stroke:`currentColor`,strokeWidth:2.484,strokeLinecap:`round`,...e,children:(0,r.jsx)(`path`,{d:`M22.356 19.797H17.17M9.662 12.29l1.979 3.576a.511.511 0 0 1-.005.504l-1.974 3.409M30.758 16c0 8.15-6.607 14.758-14.758 14.758-8.15 0-14.758-6.607-14.758-14.758C1.242 7.85 7.85 1.242 16 1.242c8.15 0 14.758 6.608 14.758 14.758Z`})}),ye=e=>(0,r.jsxs)(`svg`,{...i(e),children:[(0,r.jsx)(`rect`,{x:`4`,y:`11`,width:`16`,height:`10`,rx:`2`}),(0,r.jsx)(`path`,{d:`M8 11V7a4 4 0 0 1 8 0v4`})]}),be=e=>(0,r.jsxs)(`svg`,{...i(e),children:[(0,r.jsx)(`path`,{d:`M2 9a3 3 0 0 1 0 6v2a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-2a3 3 0 0 1 0-6V7a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2Z`}),(0,r.jsx)(`path`,{d:`M13 5v2`}),(0,r.jsx)(`path`,{d:`M13 17v2`}),(0,r.jsx)(`path`,{d:`M13 11v2`})]}),xe=e=>(0,r.jsx)(`svg`,{...i(e),children:(0,r.jsx)(`path`,{d:`M9 17H7A5 5 0 0 1 7 7h2M15 7h2a5 5 0 0 1 0 10h-2M8 12h8`})}),Se=e=>(0,r.jsxs)(`svg`,{...i(e),children:[(0,r.jsx)(`circle`,{cx:`12`,cy:`12`,r:`4`}),(0,r.jsx)(`path`,{d:`M12 2v2M12 20v2M4.9 4.9l1.4 1.4M17.7 17.7l1.4 1.4M2 12h2M20 12h2M4.9 19.1l1.4-1.4M17.7 6.3l1.4-1.4`})]}),Ce=e=>(0,r.jsx)(`svg`,{...i(e),children:(0,r.jsx)(`path`,{d:`M21 12.8A9 9 0 1 1 11.2 3 7 7 0 0 0 21 12.8Z`})}),we=e=>(0,r.jsxs)(`svg`,{...i(e),children:[(0,r.jsx)(`rect`,{x:`2`,y:`3`,width:`20`,height:`14`,rx:`2`}),(0,r.jsx)(`path`,{d:`M8 21h8M12 17v4`})]}),Te=e=>(0,r.jsxs)(`svg`,{...i(e),children:[(0,r.jsx)(`circle`,{cx:`12`,cy:`12`,r:`9`}),(0,r.jsx)(`path`,{d:`M3 12h18M12 3a14 14 0 0 1 0 18M12 3a14 14 0 0 0 0 18`})]}),Ee=e=>(0,r.jsxs)(`svg`,{...i(e),children:[(0,r.jsx)(`path`,{d:`m18 14 4 4-4 4`}),(0,r.jsx)(`path`,{d:`m18 2 4 4-4 4`}),(0,r.jsx)(`path`,{d:`M2 18h1.973a4 4 0 0 0 3.3-1.7l5.454-8.6a4 4 0 0 1 3.3-1.7H22`}),(0,r.jsx)(`path`,{d:`M2 6h1.972a4 4 0 0 1 3.6 2.2`}),(0,r.jsx)(`path`,{d:`M22 18h-6.041a4 4 0 0 1-3.3-1.8l-.359-.45`})]}),De=e=>(0,r.jsxs)(`svg`,{...i(e),children:[(0,r.jsx)(`circle`,{cx:`9`,cy:`6`,r:`1`,fill:`currentColor`,stroke:`none`}),(0,r.jsx)(`circle`,{cx:`15`,cy:`6`,r:`1`,fill:`currentColor`,stroke:`none`}),(0,r.jsx)(`circle`,{cx:`9`,cy:`12`,r:`1`,fill:`currentColor`,stroke:`none`}),(0,r.jsx)(`circle`,{cx:`15`,cy:`12`,r:`1`,fill:`currentColor`,stroke:`none`}),(0,r.jsx)(`circle`,{cx:`9`,cy:`18`,r:`1`,fill:`currentColor`,stroke:`none`}),(0,r.jsx)(`circle`,{cx:`15`,cy:`18`,r:`1`,fill:`currentColor`,stroke:`none`})]}),v=e=>(0,r.jsx)(`svg`,{...i(e),children:(0,r.jsx)(`path`,{d:`m12 2 3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z`})}),Oe=e=>(0,r.jsx)(`svg`,{...i(e),children:(0,r.jsx)(`path`,{d:`M4 5h16l-6 7v5l-4 2v-7L4 5z`})}),y={anthropic:`claude-color.svg`,anthropic2:`claude-green.svg`,"anthropic-apikey":`claude-color.svg`,"claude-cli":`claude-color.svg`,"azure-openai":`openai.svg`,chatgpt:`openai.svg`,"cloudflare-ai-gateway":`cloudflare-ai-gateway-color.svg`,"cloudflare-workers-ai":`cloudflare-ai-gateway-color.svg`,cline:`cline-color.svg`,"cline-pass":`cline-color.svg`,"command-code":`commandcode-color.svg`,commandcode:`commandcode-color.svg`,cursor:`cursor-color.svg`,deepseek:`deepseek-color.svg`,"dsh-account":`deepseek-color.svg`,devin:`devin.svg`,firepass:`firepass-color.svg`,fireworks:`fireworks-color.svg`,github:`github-copilot-color.svg`,"github-copilot":`copilot-color.svg`,"gitlab-duo":`gitlab-duo-color.svg`,google:`gemini-color.svg`,"google-antigravity":`antigravity-color.svg`,"google-vertex":`gemini-color.svg`,groq:`groq-color.svg`,huggingface:`huggingface-color.svg`,kimi:`kimi-color.svg`,"kimi-code":`kimi-color.svg`,"kimi-responses":`kimi-color.svg`,kiro:`kiro-color.svg`,"lm-studio":`lm-studio-color.svg`,"meta-model":`meta.svg`,"meta-muse":`meta.svg`,mistral:`mistral-color.svg`,minimax:`minimax.svg`,"minimax-cn":`minimax.svg`,moonshot:`moonshot-color.svg`,nvidia:`nvidia-color.svg`,ollama:`ollama-color.svg`,"ollama-cloud":`ollama-color.svg`,openai:`openai.svg`,"openai-apikey":`openai.svg`,"opencode-free":`opencode.svg`,"opencode-go":`opencode.svg`,"opencode-zen":`opencode.svg`,openrouter:`openrouter-color.svg`,opengateway:`opengateway.svg`,opper:`opper.svg`,qianfan:`qianfan-color.svg`,qoder:`qoder.svg`,"qoder-cn":`qoder.svg`,alibaba:`alibaba-color.svg`,"alibaba-token-plan":`alibaba-color.svg`,"alibaba-token-plan-intl":`alibaba-color.svg`,baseten:`baseten.svg`,bizrouter:`bizrouter.svg`,cerebras:`cerebras.svg`,crusoe:`crusoe.svg`,deepinfra:`deepinfra.svg`,digitalocean:`digitalocean.svg`,featherless:`featherless.svg`,hyperbolic:`hyperbolic.svg`,kilo:`kilo.svg`,nanogpt:`nanogpt.svg`,nebius:`nebius.svg`,neuralwatt:`neuralwatt.svg`,nous:`nous.svg`,novita:`novita.svg`,orcarouter:`orcarouter.svg`,"orcarouter-oauth":`orcarouter.svg`,packycode:`packycode.svg`,tokenlab:`tokenlab.svg`,parallel:`parallel.svg`,sambanova:`sambanova.svg`,scaleway:`scaleway.svg`,stepfun:`stepfun-color.svg`,siliconflow:`siliconflow.svg`,synthetic:`synthetic.svg`,together:`together.svg`,umans:`umans.svg`,venice:`venice.svg`,vultr:`vultr.svg`,litellm:`litellm.svg`,zenmux:`zenmux.svg`,zai:`zai.svg`,"zhipu-bigmodel":`zai.svg`,"zhipu-bigmodel-coding":`zai.svg`,"qwen-cloud":`qwen-portal-color.svg`,"vercel-ai-gateway":`vercel-ai-gateway-color.svg`,vllm:`vllm-color.svg`,xai:`grok.svg`,"mimo-free":`xiaomi-color.svg`,mimo:`xiaomi-color.svg`,xiaomi:`xiaomi-color.svg`,"xiaomi-mimo":`xiaomi-color.svg`},b={anthropic:`Anthropic Claude`,"anthropic-apikey":`Anthropic Claude`,chatgpt:`ChatGPT`,openai:`OpenAI (Codex login)`,"openai-apikey":`OpenAI API`,"azure-openai":`Azure OpenAI`,"cloudflare-ai-gateway":`Cloudflare AI Gateway`,"cloudflare-workers-ai":`Cloudflare Workers AI`,cline:`Cline`,"cline-pass":`ClinePass`,nvidia:`NVIDIA NIM`,ollama:`Ollama`,"ollama-cloud":`Ollama Cloud`,xai:`xAI Grok`,"mimo-free":`MiMo Free`,xiaomi:`Xiaomi`,cursor:`Cursor`,deepseek:`DeepSeek`,zed:`Zed`,"dsh-account":`DeepSeek Account (DSH)`,devin:`Devin`,github:`GitHub`,"github-copilot":`GitHub Copilot`,"gitlab-duo":`GitLab Duo`,openrouter:`OpenRouter`,opengateway:`OpenGateway`,opper:`Opper`,"opencode-go":`OpenCode Go`,"opencode-free":`OpenCode Free`,"opencode-zen":`OpenCode Zen`,orcarouter:`OrcaRouter - API`,"orcarouter-oauth":`OrcaRouter - Auth`,packycode:`PackyCode`,tokenlab:`TokenLab`,mistral:`Mistral`,groq:`Groq`,"meta-model":`Meta Model API`,"meta-muse":`Muse Code`,alibaba:`Alibaba Coding Plan`,"alibaba-token-plan":`Alibaba Token Plan`,"alibaba-token-plan-intl":`Alibaba Token Plan (Intl)`,kimi:`Kimi`,"kimi-code":`Kimi`,"kimi-responses":`Kimi`,moonshot:`Moonshot`,google:`Google`,"google-vertex":`Google Vertex`,"lm-studio":`LM Studio`,huggingface:`Hugging Face`,"qwen-cloud":`Qwen Cloud`,siliconflow:`SiliconFlow`,stepfun:`StepFun`,"tencent-coding-plan":`Tencent Cloud Coding Plan`,codebuddy:`CodeBuddy`,"codebuddy-cn":`CodeBuddy CN`,qoder:`Qoder`,"qoder-cn":`Qoder CN`,"vercel-ai-gateway":`Vercel AI Gateway`,vllm:`vLLM`,litellm:`LiteLLM`},x={anthropic2:`provider.name.anthropic2`,"command-code":`provider.name.commandCodeAuth`,commandcode:`provider.name.commandCodeApi`,orcarouter:`provider.name.orcaRouterApi`,"orcarouter-oauth":`provider.name.orcaRouterAuth`,volcengine:`provider.name.volcengine`,"volcengine-coding-plan":`provider.name.volcengineCodingPlan`,"volcengine-agent-plan":`provider.name.volcengineAgentPlan`},ke=new Set([...Object.keys(b),...Object.keys(x)]);function Ae(e){let t=e.toLowerCase();return Object.hasOwn(y,t)?y[t]:void 0}function je(e,t){let n=Ae(e);return n?`/provider-icons/${n}`:void 0}var Me=new Set([`cerebras.svg`,`deepinfra.svg`,`neuralwatt.svg`,`nous.svg`,`novita.svg`,`packycode.svg`,`tokenlab.svg`,`opper.svg`,`opengateway.svg`,`siliconflow.svg`,`synthetic.svg`,`zenmux.svg`,`grok.svg`,`kimi-color.svg`,`ollama-color.svg`,`opencode.svg`,`vercel-ai-gateway-color.svg`]),Ne=new Set([`baseten.svg`,`kilo.svg`,`sambanova.svg`,`venice.svg`,`zai.svg`]),Pe=new Set([`bizrouter.svg`,`featherless.svg`,`hyperbolic.svg`,`nebius.svg`,`parallel.svg`,`umans.svg`]);function Fe(e){if(!e)return`image`;let t=e.split(`/`).pop()??``;return Me.has(t)?`mask`:Ne.has(t)?`plate`:Pe.has(t)?`dark-plate`:`image`}function S(e,t){let n=e.toLowerCase(),r=Object.hasOwn(x,n)?x[n]:void 0;return r?t(r):(Object.hasOwn(b,n)?b[n]:void 0)||(e===n&&/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(e)?e.split(`-`).map(e=>e&&e[0].toUpperCase()+e.slice(1)).join(` `):e)}function Ie(e){return ke.has(e.toLowerCase())}function Le(e){return e===`command-code`?`commandcode-auth`:e===`commandcode`?`commandcode-api`:e}function Re(e,t){let n=e.indexOf(`/`);if(n<=0)return e;let r=e.slice(0,n),i=e.slice(n+1);if(r===`command-code`||r===`commandcode`){let e=i.match(/^([a-z0-9]+)-([a-z0-9]+(?:-[a-z0-9]+)+)$/i);return e&&i.startsWith(`${e[1]}-${e[1]}-`)&&(i=i.slice(e[1].length+1)),`${r===`command-code`?`commandcode-auth`:`commandcode-api`}/${i}`}return e}var ze={ko:[{v:0x2386f26fc10000,s:`경`},{v:0xe8d4a51000,s:`조`},{v:1e8,s:`억`},{v:1e4,s:`만`}],zh:[{v:0x2386f26fc10000,s:`京`},{v:0xe8d4a51000,s:`兆`},{v:1e8,s:`亿`},{v:1e4,s:`万`}],"zh-TW":[{v:0x2386f26fc10000,s:`京`},{v:0xe8d4a51000,s:`兆`},{v:1e8,s:`億`},{v:1e4,s:`萬`}]};function C(e){return e.replace(/\.0+$/,``).replace(/(\.\d*?)0+$/,`$1`)}function Be(e,t){let n=ze[t];if(n){for(let t of n)if(e>=t.v)return`${C((e/t.v).toFixed(1))}${t.s}`;return String(e)}return e<1e4?String(e):e<1e6?`${C((e/1e3).toFixed(1))}K`:e<1e9?`${C((e/1e6).toFixed(1))}M`:e<0xe8d4a51000?`${C((e/1e9).toFixed(1))}B`:`${C((e/0xe8d4a51000).toFixed(1))}T`}var Ve=new Set([`claude-cli`]),He=`anthropic-apikey`;function w(e){return Ve.has((e.adapter??``).trim())}var T=`https://chatgpt.com/backend-api/codex`,Ue=`openai`;function E(e){try{let t=new URL(e.trim());if(t.username||t.password||t.search||t.hash)return;let n=t.pathname.replace(/\/+$/,``);return`${t.origin}${n}`}catch{return}}var We=new URL(T).protocol;function D(e,...t){return`${We}//${e}/${t.join(`/`)}`}var Ge={"cline-pass":{adapter:`openai-chat`,baseUrl:D(`api.cline.bot`,`api`,`v1`)},"mimo-free":{adapter:`mimo-free`,baseUrl:D(`api.xiaomimimo.com`,`api`,`free-ai`,`openai`,`chat`)}};function Ke(e,t){let n=Ge[e];return!n||t.adapter!==n.adapter||E(t.baseUrl)!==E(n.baseUrl)}function O(e){try{let t=new URL(e).hostname.replace(/^\[|\]$/g,``).toLowerCase();return t===`localhost`||t===`127.0.0.1`||t===`::1`}catch{return!1}}function k(e){return e.keyOptional===!0||w(e)||e.authMode===`oauth`||e.authMode===`forward`||e.authMode===`local`||O(e.baseUrl)||e.hasApiKey===!0}function A(e){return e.adapter===`openai-responses`&&e.authMode===`forward`&&E(e.baseUrl)===T}function j(e,t){return e===Ue&&A(t)}function M(e){return w(e)?!1:e.freeTier===!0||e.keyOptional===!0||e.authMode===`local`||O(e.baseUrl)}function N(e,t){return j(e,t)?`accounts`:M(t)?`free`:`paid`}function qe(e,t){let n=[...e],r=(e,t)=>e.name.localeCompare(t.name,void 0,{sensitivity:`base`}),i=e=>e.tier??N(e.name,e);switch(t){case`az`:return n.sort(r);case`za`:return n.sort((e,t)=>r(t,e));case`free-paid`:return n.sort((e,t)=>(i(e)===`free`?0:1)-(i(t)===`free`?0:1)||r(e,t));case`paid-free`:return n.sort((e,t)=>+(i(e)===`free`)-(i(t)===`free`)||r(e,t));case`accounts-first`:return n.sort((e,t)=>{let n=e=>{let t=i(e);return t===`accounts`?0:t===`free`?1:2};return n(e)-n(t)||r(e,t)});default:return n}}function Je(e){let t=[],n=[],r=[];for(let[i,a]of Object.entries(e))a.disabled?r.push({name:i,...a}):k(a)?t.push({name:i,...a,tier:N(i,a)}):n.push({name:i,...a});return{ready:t,needsSetup:n,disabled:r}}function Ye(e,t){let n=new Set(Object.entries(t).filter(([,e])=>e).map(([e])=>e));if(n.size===0)return e;let r=e=>e.map(e=>n.has(e.name)?{...e,activeNeedsReauth:!0}:e);return{ready:r(e.ready),needsSetup:r(e.needsSetup),disabled:e.disabled}}function P(e){return e.disabled?`disabled`:`activeNeedsReauth`in e&&e.activeNeedsReauth?`needs-setup`:k(e)?`ready`:`needs-setup`}function Xe(e){let t=e.openai,n=e.chatgpt;if(!t||!n||!j(`openai`,t)||!A(n))return e;let r={...e};return delete r.chatgpt,r}function F(e){return e.authMode===`local`||O(e.baseUrl)}var Ze=[`ollama`,`vllm`,`lm-studio`,`lmstudio`,`litellm`,`localai`];function Qe(e){let t=(e.authMode??``).toLowerCase();if(t===`oauth`||t===`forward`)return`login`;if(F(e))return`local`;let n=`${e.name??``} ${e.adapter} ${e.baseUrl}`.toLowerCase();return Ze.some(e=>n.includes(e))?`selfHosted`:`cloud`}function I(e,t){if(!e||typeof e!=`object`||Array.isArray(e))return null;let n=e;if(typeof n.updatedAt!=`number`||!Number.isFinite(n.updatedAt))return null;let r=n.observed===!0;return!r&&t-n.updatedAt>=18e5||!(`quota`in n)||n.label!==void 0&&typeof n.label!=`string`||n.source!==void 0&&typeof n.source!=`string`?null:{...typeof n.label==`string`?{label:n.label}:{},...typeof n.source==`string`?{source:n.source}:{},updatedAt:n.updatedAt,quota:n.quota,...r?{observed:!0}:{},...n.aggregation===void 0?{}:{aggregation:n.aggregation}}}function $e(e,t=Date.now()){if(!e||typeof e!=`object`||Array.isArray(e))return null;let n={};for(let[r,i]of Object.entries(e)){let e=I(i,t);r.trim()&&e&&(n[r]=e)}return n}function et(e,t=Date.now()){if(!Array.isArray(e))return{};let n={};for(let r of e){if(!r||typeof r!=`object`||Array.isArray(r))continue;let e=r.provider,i=I(r,t);typeof e==`string`&&e.trim()&&i&&(n[e]=i)}return n}function tt(e){return e?.observed===!0&&typeof e.updatedAt==`number`?e.updatedAt:void 0}var L=e=>typeof e==`number`&&Number.isFinite(e)?e:void 0,nt=e=>{let t=L(e);if(t===void 0)return;let n=t>1e10?t:t*1e3;return Number.isFinite(new Date(n).getTime())?t:void 0};function R(e,t){if(!e||typeof e!=`object`||Array.isArray(e))return null;let n=e,r=Array.isArray(n.customWindows)?n.customWindows.flatMap(e=>{if(!e||typeof e!=`object`)return[];let t=e;return typeof t.label!=`string`||L(t.percent)===void 0?[]:[{label:t.label,percent:t.percent,...L(t.resetAt)===void 0?{}:{resetAt:t.resetAt},...typeof t.modelId==`string`&&t.modelId.length<=128?{modelId:t.modelId}:{}}]}):[],i=n.creditsUsd&&typeof n.creditsUsd==`object`&&!Array.isArray(n.creditsUsd)?n.creditsUsd:null,a=L(i?.used),o=L(i?.limit),s=L(i?.remaining),c=L(i?.percent),l=nt(i?.expiresAt),u=a!==void 0&&o!==void 0&&s!==void 0&&c!==void 0?{used:a,limit:o,remaining:s,percent:c,...l===void 0?{}:{expiresAt:l},...typeof i?.unlimited==`boolean`?{unlimited:i.unlimited}:{}}:void 0,d={...L(n.fiveHourPercent)===void 0?{}:{fiveHourPercent:n.fiveHourPercent},...L(n.fiveHourResetAt)===void 0?{}:{fiveHourResetAt:n.fiveHourResetAt},...L(n.weeklyPercent)===void 0?{}:{weeklyPercent:n.weeklyPercent},...L(n.weeklyResetAt)===void 0?{}:{weeklyResetAt:n.weeklyResetAt},...L(n.monthlyPercent)===void 0?{}:{monthlyPercent:n.monthlyPercent},...L(n.monthlyResetAt)===void 0?{}:{monthlyResetAt:n.monthlyResetAt},...r.length>0?{customWindows:r}:{},...u?{creditsUsd:u}:{},updatedAt:L(n.updatedAt)??t??Date.now()};return d.fiveHourPercent!==void 0||d.weeklyPercent!==void 0||d.monthlyPercent!==void 0||(d.customWindows?.length??0)>0||d.creditsUsd!==void 0?d:null}function z(e){return R(e?.quota,e?.updatedAt)}function rt(e){if(!e)return;if(e.aggregation===void 0)return e;let t=V(e)?.currentAccount?.quota??null;return{...e,aggregation:void 0,quota:t,updatedAt:t?.updatedAt}}function B(e){if(!e||typeof e!=`object`||Array.isArray(e))return;let t=e,n=L(t.usedPercent);if(n!==void 0)return{usedPercent:n,...typeof t.incomplete==`boolean`?{incomplete:t.incomplete}:{},...L(t.excludedAccounts)===void 0?{}:{excludedAccounts:t.excludedAccounts},...L(t.nextRecoveryAt)===void 0?{}:{nextRecoveryAt:t.nextRecoveryAt},...L(t.nextRecoveryPercent)===void 0?{}:{nextRecoveryPercent:t.nextRecoveryPercent}}}function V(e){let t=e?.aggregation;if(!t||typeof t!=`object`||Array.isArray(t))return null;let n=t;if(n.kind!==`capacity-weighted-v1`||n.scope!==`routable-known`)return null;let r=L(n.excludedAccounts),i=L(n.unknownPlanAccounts);if(r===void 0||i===void 0||typeof n.incomplete!=`boolean`)return null;let a=n.currentAccount&&typeof n.currentAccount==`object`&&!Array.isArray(n.currentAccount)?n.currentAccount:null,o=Array.isArray(n.customWindows)?n.customWindows.flatMap(e=>{if(!e||typeof e!=`object`||Array.isArray(e))return[];let t=e,n=B(t);return typeof t.label==`string`&&n?[{label:t.label,...n}]:[]}):[],s=B(n.fiveHour),c=B(n.weekly),l=B(n.monthly),u=!!s||!!c||!!l||o.length>0;return{presentation:n.presentation===`aggregate`||n.presentation===`effective-account-fallback`||n.presentation===`coverage-only`?n.presentation:u?`aggregate`:`coverage-only`,incomplete:n.incomplete,excludedAccounts:r,unknownPlanAccounts:i,partialWindowAccounts:L(n.partialWindowAccounts)??0,...s?{fiveHour:s}:{},...c?{weekly:c}:{},...l?{monthly:l}:{},...o.length>0?{customWindows:o}:{},...a?{currentAccount:{...typeof a.plan==`string`||a.plan===null?{plan:a.plan}:{},quota:R(a.quota)}}:{}}}function it(e){if(!e?.trim())return``;let[t,n]=e.split(`:`,2);return n?`${t} · ${n.replace(/-/g,` `)}`:e}function at(e,t){let n=P(e);return n===`disabled`?t(`prov.disabledBadge`):n===`ready`?t(`pws.status.ready`):`activeNeedsReauth`in e&&e.activeNeedsReauth?t(`pws.status.needsAttention`):t(`pws.status.needsSetup`)}function ot(e,t){if(w(e))return t(`modal.badge.subscriptionCli`);switch(e.authMode){case`oauth`:return t(`modal.badge.oauth`);case`forward`:return t(`pws.auth.chatgptPassthrough`);case`local`:return t(`modal.badge.local`);case`key`:return t(`modal.badge.apiKey`);default:return e.authMode??(e.keyOptional?t(`pws.auth.noKey`):t(`modal.badge.apiKey`))}}function st(e){let t=P(e);return t===`disabled`?`providers-workspace-rail-status providers-workspace-rail-status--inactive`:t===`ready`?`providers-workspace-rail-status providers-workspace-rail-status--active`:`providers-workspace-rail-status providers-workspace-rail-status--warning`}function H({name:e,adapter:n,baseUrl:i,cls:a}){let o=t(),s=je(e,{adapter:n,baseUrl:i}),c=Fe(s),l=c===`plate`?`${a} provider-icon--plate`:c===`dark-plate`?`${a} provider-icon--plate-dark`:a;return(0,r.jsx)(`span`,{className:l,children:s&&c===`mask`?(0,r.jsx)(`span`,{className:`provider-icon-mask`,style:{maskImage:`url(${s})`,WebkitMaskImage:`url(${s})`},"aria-hidden":`true`}):s?(0,r.jsx)(`img`,{src:s,alt:``,"aria-hidden":`true`}):(0,r.jsx)(ct,{name:e,label:S(e,o)})})}function ct({name:e,label:t}){let n=[...e].reduce((e,t)=>e+t.charCodeAt(0),0)%360,i=(t.trim()[0]??e[0]??`?`).toUpperCase();return(0,r.jsx)(`span`,{className:`provider-icon-fallback`,style:{background:`hsl(${n} 55% 90%)`,color:`hsl(${n} 65% 32%)`},"aria-hidden":`true`,children:i})}function lt({item:e,selected:n,tabbable:i,modelCount:a,isDefault:o,showConfigId:s,onClick:c,onFocus:l}){let u=t(),d=M(e),f=F(e),p=at(e,u),m=S(e.name,u),h=s?`${m} (${e.name})`:m,g=`${o?u(`pws.rail.suffixDefault`):``}${f?u(`pws.rail.suffixLocal`):d?u(`pws.rail.suffixFree`):``}`,ee=a!==void 0&&a>0?a===1?u(`pws.modelCountOne`):u(`pws.modelCount`,{count:a}):``,_=[s?e.name:``,ee].filter(Boolean).join(` · `);return(0,r.jsxs)(`button`,{type:`button`,className:`providers-workspace-rail-row${n?` providers-workspace-rail-row--selected`:``}`,onClick:c,role:`option`,"aria-selected":n,tabIndex:i?0:-1,"aria-label":u(`pws.rail.selectAria`,{name:h,status:p,suffix:g}),title:h,onFocus:l,children:[(0,r.jsx)(H,{name:e.name,adapter:e.adapter,baseUrl:e.baseUrl,cls:`providers-workspace-rail-icon`}),(0,r.jsxs)(`span`,{className:`providers-workspace-rail-copy`,children:[(0,r.jsxs)(`span`,{className:`providers-workspace-rail-primary`,children:[(0,r.jsx)(`span`,{className:`providers-workspace-rail-name-label`,title:m,children:m}),f?(0,r.jsx)(`span`,{className:`pwi-rail-badge pwi-rail-badge--local`,title:u(`pws.localTitle`),children:u(`modal.badge.local`)}):d?(0,r.jsx)(`span`,{className:`pwi-rail-badge pwi-rail-badge--free`,title:u(`pws.freeTitle`),children:u(`modal.badge.free`)}):null]}),(0,r.jsx)(`span`,{className:`providers-workspace-rail-secondary`,title:_||void 0,children:_||`\xA0`})]}),(0,r.jsxs)(`span`,{className:`providers-workspace-rail-trail`,children:[o&&(0,r.jsx)(`span`,{className:`pwi-default-star`,title:u(`prov.defaultBadge`),"aria-label":u(`prov.defaultBadge`),children:(0,r.jsx)(v,{width:17,height:17,"aria-hidden":`true`})}),(0,r.jsx)(`span`,{className:st(e),title:p,"aria-hidden":`true`})]})]})}var ut=1e10;function dt(e){return e<ut?e*1e3:e}function ft(e,t){let n=e=>typeof e==`number`&&Number.isFinite(e);if(!n(e.shortPercent)||e.shortPercent<100)return!1;let r=e.shortResetAt;if(!n(r)||r<=0){let r=e.shortObservedAt;if(!n(r))return!1;let i=t-r;return i>=0&&i<=3e5}return dt(r)>t}function pt(e){return{fiveHourAvailable:e?.shortWindowSeconds===18e3&&typeof e.shortResetAt==`number`,weeklyAvailable:typeof e?.weeklyResetAt==`number`}}function U(e){let t=e?.trim().toLowerCase();return t===`go`||t===`free`}function W(e,t){if(!e)return null;let n=e.shortPercent===void 0&&e.shortResetAt===void 0?e:{...e,fiveHourPercent:e.fiveHourPercent??e.shortPercent,fiveHourResetAt:e.fiveHourResetAt??e.shortResetAt};return U(t)?{...n.monthlyPercent===void 0?{}:{monthlyPercent:n.monthlyPercent},...n.monthlyResetAt===void 0?{}:{monthlyResetAt:n.monthlyResetAt},...n.creditsUsd===void 0?{}:{creditsUsd:n.creditsUsd},...n.resetCredits===void 0?{}:{resetCredits:n.resetCredits},updatedAt:n.updatedAt}:n}function mt(e,t,n=Date.now()){if(!e)return null;let r=e=>typeof e==`number`&&Number.isFinite(e),i=r(e.fiveHourPercent)?e.fiveHourPercent:r(e.shortPercent)?e.shortPercent:void 0,a=(U(t)?[e.monthlyPercent]:[e.weeklyPercent,e.monthlyPercent]).filter(r);if(a.length===0)return ft({...r(i)?{shortPercent:i}:{},...r(e.fiveHourResetAt??e.shortResetAt)?{shortResetAt:e.fiveHourResetAt??e.shortResetAt}:{},...r(e.shortObservedAt)?{shortObservedAt:e.shortObservedAt}:{}},n)?100:null;let o=r(i)?[...a,i]:a;return o.length?Math.max(...o):null}function ht(e){let t=new URLSearchParams({hours:String(e.chartHours),bucketMinutes:String(e.bucketMinutes),metric:e.tokenMetric,aggregation:e.aggregation,grouping:e.chartGrouping});e.models?.length&&t.set(`models`,e.models.join(`,`));for(let n of e.hiddenProviders)t.append(`hiddenProvider`,n);return t}function G(e){return Array.isArray(e)&&e.length<=100&&e.every(e=>typeof e==`string`)?JSON.stringify([...new Set(e)].sort()):void 0}function gt(e,t){let n=new Set(t.hiddenProviders),r=e.availableModels.filter(e=>!n.has(e.slice(0,e.indexOf(`/`))));if(t.models?.length===0)return{...e,series:[],availableModels:r};let i=t.models===null?null:new Set(t.models),a=i!==null||n.size>0,o=e.appliedFilters,s=!!o&&G(o.hiddenProviders)===G(t.hiddenProviders)&&(t.models===null?o.models===null:G(o.models)===G(t.models)),c=e.series.filter(e=>e.id===`other`&&e.provider===``?!a||s:!n.has(e.provider)&&(i===null||i.has(`${e.provider}/${e.model}`)||i.has(e.model)));return{...e,series:c,availableModels:r,truncated:e.truncated||(a||o!==void 0)&&!s}}var _t={6:15,24:60,72:180,168:360};function vt(e){return _t[e]}function K(e){if(e<1e3)return String(Math.round(e));let t=[[0xe8d4a51000,`T`],[1e9,`B`],[1e6,`M`],[1e3,`K`]];for(let n=0;n<t.length;n+=1){let[r,i]=t[n];if(e>=r){let a=Math.round(e/r);if(a>=1e3&&n>0){let[r,i]=t[n-1];return`${Math.round(e/r)}${i}`}return`${a}${i}`}}return String(Math.round(e))}function yt(e,t){let n=new Map;for(let r of e){let e=r.includes(`/`)?r.slice(0,r.indexOf(`/`)):r,i=n.get(e)??{provider:e,models:[],total:0},a=t.get(r)??0;i.models.push({id:r,total:a}),i.total+=a,n.set(e,i)}return Array.from(n.values()).map(e=>({...e,models:e.models.toSorted((e,t)=>t.total-e.total||e.id.localeCompare(t.id))})).toSorted((e,t)=>t.total-e.total||e.provider.localeCompare(t.provider))}function bt(e,t,n,r){let i=new Set(t),a=new Set((e??t).filter(e=>i.has(e)));for(let e of n)r?a.add(e):a.delete(e);return t.length>0&&t.every(e=>a.has(e))?null:t.filter(e=>a.has(e))}function xt(e,t=[]){let n={...e};if(typeof n.menuBarTemplate==`string`&&n.menuBarTemplate.trim()===``&&(n.menuBarTemplate=null),n.models!==void 0&&t.length>0){let e=n.models??[],r=new Set(e);e.length===t.length&&t.every(e=>r.has(e))&&(n.models=null)}return n}function St(e,t,n,r,i=8){let a=Math.max(0,t-i*2),o=Math.max(0,n-i*2),s=Math.max(r,1),c=Math.max(e.length-1,1);return e.map((e,t)=>`${i+a*t/c},${i+o*(1-Math.max(0,e)/s)}`).join(` `)}function Ct(e,t,n,r,i=8){let a=e[0]?.points.length??0;if(a===0)return[];let o=Math.max(0,t-i*2),s=Math.max(0,n-i*2),c=Math.max(r,1),l=Math.min(3,o/Math.max(a*8,1)),u=Math.max(0,o/a-l),d=[];for(let t=0;t<a;t+=1){let n=0;for(let r=0;r<e.length;r+=1){let f=s*Math.max(0,e[r]?.points[t]??0)/c;f>0&&d.push({x:i+o/a*t+l/2,y:i+s-n-f,width:u,height:f,seriesIndex:r,bucketIndex:t}),n+=f}}return d}var q=[`#0A84FF`,`#FF9F0A`,`#30D158`,`#BF5AF2`,`#FF453A`,`#64D2FF`],wt=640,Tt=160,J=28;function Et(e,t){return Math.max(...t===`stackedBar`?Array.from({length:e.buckets},(t,n)=>e.series.reduce((e,t)=>e+(t.points[n]??0),0)):e.series.flatMap(e=>e.points),0)}function Dt(e,t){let n=new Intl.DateTimeFormat(t,{month:`short`,day:`numeric`}),r=Math.max(1,Math.floor((e.buckets-1)/3));return[0,1,2,3].map(t=>{let i=Math.min(e.buckets-1,t*r);return n.format(new Date((e.start+i*e.bucketSeconds)*1e3))})}function Ot({timeline:e,chartStyle:t,hours:n,loading:i,error:a,onRetry:o,locale:s,t:c}){if(i)return(0,r.jsx)(`div`,{className:`usage-companion-chart-skeleton`,"aria-busy":`true`,"aria-label":c(`usage.companion.loading`)});if(a)return(0,r.jsxs)(`div`,{className:`usage-companion-chart-state`,role:`alert`,children:[(0,r.jsx)(`span`,{children:c(`usage.companion.timelineUnavailable`)}),(0,r.jsx)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,onClick:o,children:c(`common.retry`)})]});if(!e||e.series.length===0)return(0,r.jsx)(`div`,{className:`usage-companion-chart-state`,children:c(`usage.companion.empty`,{hours:e?.buckets?Math.round(e.buckets*e.bucketSeconds/3600):n})});let l=Et(e,t),u=Dt(e,s),d=J,f=u.map((e,t)=>(0,r.jsx)(`text`,{x:J+584*t/3,y:156,textAnchor:t===0?`start`:t===3?`end`:`middle`,className:`usage-companion-axis-label`,children:e},`${e}-${t}`)),p=t===`line`?e.series.map((e,t)=>(0,r.jsx)(`polyline`,{points:St(e.points,584,104,l,0),transform:`translate(${J},${J})`,fill:`none`,stroke:q[t%q.length],strokeWidth:`2`,strokeLinejoin:`round`,strokeLinecap:`round`},e.id)):Ct(e.series,584,104,l,0).map(e=>(0,r.jsx)(`rect`,{x:J+e.x,y:J+e.y,width:e.width,height:e.height,fill:q[e.seriesIndex%q.length],rx:`1`},`${e.bucketIndex}-${e.seriesIndex}`));return(0,r.jsxs)(`div`,{className:`usage-companion-chart`,children:[(0,r.jsxs)(`svg`,{viewBox:`0 0 ${wt} ${Tt}`,role:`img`,"aria-label":c(`usage.companion.chartLabel`),children:[(0,r.jsx)(`line`,{x1:J,y1:d,x2:J,y2:132,className:`usage-companion-axis`}),(0,r.jsx)(`line`,{x1:J,y1:132,x2:612,y2:132,className:`usage-companion-axis`}),(0,r.jsx)(`text`,{x:24,y:32,textAnchor:`end`,className:`usage-companion-axis-label`,children:K(l)}),p,f]}),(0,r.jsx)(`div`,{className:`usage-companion-legend`,children:e.series.map((e,t)=>(0,r.jsxs)(`span`,{className:`usage-companion-legend-item`,children:[(0,r.jsx)(`span`,{className:`usage-companion-swatch`,style:{background:q[t%q.length]},"aria-hidden":`true`}),(0,r.jsx)(`span`,{children:e.id})]},e.id))}),e.truncated&&(0,r.jsx)(`p`,{className:`muted text-caption`,children:c(`usage.companion.olderRecordsSkipped`)})]})}var Y=e=>typeof e==`number`&&Number.isFinite(e)&&e>=0,X=e=>typeof e==`object`&&e&&!Array.isArray(e)?e:{};function kt(e){return Object.entries(X(X(e).providers)).flatMap(([e,t])=>{let n=X(t);return n.disabled===!0?[]:e===`openai`?[{name:e,path:`/api/codex-auth/accounts`,switchKind:`codex`}]:n.authMode===`oauth`?[{name:e,path:`/api/oauth/accounts?${new URLSearchParams({provider:e,quota:`1`})}`,switchKind:`oauth`}]:n.hasApiKey===!0&&n.authMode!==`forward`?[{name:e,path:`/api/providers/keys?${new URLSearchParams({name:e,quota:`1`})}`,switchKind:`apiKey`}]:[{name:e,path:null,switchKind:null}]})}function At(e,t,n){return t===`codex`?{path:`/api/codex-auth/active`,body:{accountId:n}}:t===`oauth`?{path:`/api/oauth/accounts/active`,body:{provider:e,accountId:n}}:{path:`/api/providers/keys/active`,body:{name:e,id:n}}}function jt(e,t){return t?{switchState:`active`}:X(e.mainAccountHardLock).state===`blocked`?{switchState:`blocked`,blockedReason:`mainHardLock`}:e.paused===!0?{switchState:`blocked`,blockedReason:`paused`}:X(e.health).reason===`validation_pending`?{switchState:`blocked`,blockedReason:`validationPending`}:{switchState:`available`}}function Mt(e,t){let n=[`go`,`free`].includes((t??``).trim().toLowerCase()),r=e.fiveHourPercent??e.shortPercent;return(n?[e.monthlyPercent,r]:[e.weeklyPercent,e.monthlyPercent,r]).some(e=>typeof e==`number`&&Number.isFinite(e)&&e>=100)}function Nt(e){let t=X(e),n=t.accounts??t.keys;if(!Array.isArray(n))throw Error(`Invalid account roster`);return n.map(e=>{let n=X(e);if(typeof n.id!=`string`)throw Error(`Invalid account identifier`);let r=typeof n.email==`string`?Pt(n.email):void 0,i=[n.alias,n.label,r,n.logLabel,n.id].find(e=>typeof e==`string`&&e.length),a=n.quotaUnavailable===!0||n.quotaMode===`unsupported`||!n.quota?null:X(n.quota),o=typeof n.plan==`string`?n.plan:void 0,s=t.activeAccountId??t.activeId??t.activeCodexAccountId,c=typeof s==`string`?s===n.id:n.active===!0;return{id:n.id,label:i,email:r,plan:o,unavailable:n.quotaUnavailable===!0,active:c,...jt(n,c),exhausted:a!==null&&Mt(X(n.quota),o),status:typeof X(n.health).status==`string`?X(n.health).status:void 0,quotaFailure:typeof n.quotaFailure==`string`?n.quotaFailure:void 0,quota:W(a,o)}})}function Z(e){if(!Y(e)||e===0)return null;let t=e<0xe8d4a51000?e*1e3:e;return Number.isFinite(new Date(t).getTime())?t:null}function Pt(e){let[t,n]=e.split(`@`);if(!n)return`•••`;let r=n.includes(`.`)?n.slice(n.lastIndexOf(`.`)):``;return`${t?.slice(0,1)||`•`}•••@${n.slice(0,1)}•••${r}`}function Ft(e,t,n=Date.now()){let r=Z(e);if(r===null||r<=n)return{text:`—`};let i=Math.ceil((r-n)/6e4),a=(e,n)=>new Intl.NumberFormat(t,{style:`unit`,unit:n,unitDisplay:`narrow`}).format(e);return{text:i<60?a(i,`minute`):i<1440?`${a(Math.floor(i/60),`hour`)} ${a(i%60,`minute`)}`:i<10080?`${a(Math.floor(i/1440),`day`)} ${a(Math.floor(i%1440/60),`hour`)}`:new Intl.DateTimeFormat(t,{month:`short`,day:`numeric`}).format(r),exact:new Date(r).toLocaleString(t)}}function It(e){if(!e)return[];let t=[{id:`quota.fiveHourLimit`,key:`quota.fiveHourLimit`,percent:e.fiveHourPercent??e.shortPercent,reset:e.fiveHourResetAt??e.shortResetAt},{id:`quota.weeklyLimit`,key:`quota.weeklyLimit`,percent:e.weeklyPercent,reset:e.weeklyResetAt},{id:`quota.monthlyLimit`,key:`quota.monthlyLimit`,percent:e.monthlyPercent,reset:e.monthlyResetAt},...Array.isArray(e.customWindows)?e.customWindows.filter(e=>e&&typeof e.label==`string`).map(e=>({id:e.label,label:e.label,modelId:e.modelId,percent:e.percent,reset:e.resetAt})):[]].filter(e=>Y(e.percent)||Z(e.reset)!==null),n=new Map;return t.map(e=>{let t=n.get(e.id)??0;return n.set(e.id,t+1),t===0?e:{...e,id:`${e.id}#${t}`}})}function Lt(e,t){let n=new Set(t.hiddenProviders),r=t.models===null?null:new Set(t.models),i=e.models.filter(e=>!n.has(e.provider)&&(r===null||r.has(`${e.provider}/${e.model}`)||r.has(e.model)));if(t.models===null&&t.hiddenProviders.length===0)return{...e,models:i};if(t.models?.length!==0&&e.models.some(e=>!e.provider||!e.model||e.provider===`other`&&e.model===`other`))return{...e,models:i.filter(e=>e.provider!==`other`||e.model!==`other`),summary:{},usageIncomplete:!0};let a={};for(let e of[`requests`,`totalTokens`,`inputTokens`,`outputTokens`,`cachedInputTokens`,`cacheReadInputTokens`,`estimatedCostUsd`,`measuredRequests`,`pricedRequests`])i.length&&i.every(t=>Y(t[e]))&&(a[e]=i.reduce((t,n)=>t+n[e],0));return{...e,models:i,summary:a}}function Rt(e){let t={...e};if((e.requests??0)>0&&(e.measuredRequests===0||e.coverageRatio===0))for(let e of[`totalTokens`,`inputTokens`,`outputTokens`,`cachedInputTokens`,`cacheReadInputTokens`])delete t[e];return(e.requests??0)>0&&e.pricedRequests===0&&delete t.estimatedCostUsd,t}async function zt(e,t){let r=n(2e4),i=()=>r.controller.abort();t.aborted&&i(),t.addEventListener(`abort`,i,{once:!0});try{let t=await fetch(e,{signal:r.signal,cache:`no-store`});if(!t.ok)throw Error(String(t.status));let n=await t.json();if(r.signal.aborted)throw Error(`Tray request cancelled`);return n}finally{r.clear(),t.removeEventListener(`abort`,i)}}function Bt(e){let t=X(e);if(t.error||!t.summary||typeof t.summary!=`object`||Array.isArray(t.summary)||!Array.isArray(t.models))throw Error(`Invalid usage`);return t}var Q=e=>typeof e==`number`&&Number.isFinite(e);function $(e){return Q(e)?e>=90?`critical`:e>=70?`warn`:`normal`:`normal`}function Vt(e){return Q(e)?`${Math.floor(e)}%`:`-`}var Ht=[`quota.weeklyLimit`,`quota.monthlyLimit`,`quota.fiveHourLimit`];function Ut(e){let t=It(e).map(e=>{let t=Q(e.percent)?e.percent:void 0,n=Z(e.reset),r=`modelId`in e?e.modelId:void 0;return{id:e.id,...r===void 0?{}:{modelId:r},...`key`in e&&e.key?{labelKey:e.key}:{},...`label`in e&&typeof e.label==`string`?{label:e.label}:{},...t===void 0?{}:{percent:t},...n===null?{}:{resetAt:n},severity:r===void 0?$(t):`normal`}}),n=e.creditsUsd;if(n&&n.unlimited!==!0&&Q(n.percent)){let e=Z(n.expiresAt);t.push({id:`quotaSummary.credits`,labelKey:`quotaSummary.credits`,percent:n.percent,...e===null?{}:{resetAt:e},severity:$(n.percent)})}return t}function Wt(e){let t=e.filter(e=>e.modelId===void 0&&e.percent!==void 0),n=new Map(t.map(e=>[e.id,e]));for(let e of Ht){let t=n.get(e);if(t)return t}return t[0]}function Gt(e,t){let n=[];for(let[r,i]of Object.entries(e)){let e=z(i);if(!e)continue;let a=Ut(e),o=Wt(a);o&&n.push({provider:r,label:i.label?.trim()||t(r),headline:o,windows:a,...Q(i.updatedAt)?{updatedAt:i.updatedAt}:{},observed:i.observed===!0,severity:o.severity})}return n}export{p as $,rt as A,ee as At,Xe as B,ie as Bt,W as C,_ as Ct,ot as D,ne as Dt,lt as E,d as Et,F,Ee as Ft,qe as G,M as H,Qe as I,v as It,Be as J,He as K,Ye as L,Se as Lt,$e as M,te as Mt,et as N,le as Nt,z as O,oe as Ot,tt as P,o as Pt,Le as Q,P as R,f as Rt,mt as S,u as St,H as T,Ce as Tt,Ke as U,j as V,g as Vt,N as W,S as X,Re as Y,Ie as Z,gt as _,ce as _t,zt as a,h as at,yt as b,l as bt,Rt as c,fe as ct,kt as d,Oe as dt,se as et,It as f,me as ft,xt as g,m as gt,vt as h,De as ht,At as i,s as it,it as j,he as jt,V as k,re as kt,Nt as l,ge as lt,Ot as m,a as mt,Vt as n,ue as nt,Lt as o,pe as ot,Ft as p,Te as pt,w as q,$ as r,c as rt,Y as s,ve as st,Gt as t,de as tt,Bt as u,ae as ut,ht as v,_e as vt,pt as w,we as wt,bt as x,ye as xt,K as y,xe as yt,Je as z,be as zt};
@@ -36,7 +36,7 @@
36
36
  document.documentElement.lang = langMap[locale];
37
37
  })();
38
38
  </script>
39
- <script type="module" crossorigin src="/assets/index-uchD-ngf.js"></script>
39
+ <script type="module" crossorigin src="/assets/index-TmaHa54u.js"></script>
40
40
  <link rel="stylesheet" crossorigin href="/assets/index-DPeB9HpV.css">
41
41
  </head>
42
42
  <body>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bitkyc08/opencodex",
3
- "version": "2.89.0",
3
+ "version": "2.90.0",
4
4
  "description": "Universal provider proxy for OpenAI Codex & Claude Code — use any LLM with Codex CLI/App/SDK and Claude Code",
5
5
  "type": "module",
6
6
  "main": "./bin/package-main.mjs",
@@ -80,7 +80,7 @@
80
80
  },
81
81
  "dependencies": {
82
82
  "@bufbuild/protobuf": "^2.14.0",
83
- "@modelcontextprotocol/sdk": "^1.30.0",
83
+ "@modelcontextprotocol/sdk": "^1.32.1",
84
84
  "@napi-rs/keyring": "1.3.0",
85
85
  "bun": "1.4.2",
86
86
  "zod": "4.4.3"
@@ -14,6 +14,8 @@ export interface IncomingMeta {
14
14
  abortSignal?: AbortSignal;
15
15
  /** Lease acquired before the response is committed; the physical send transfers it to its body. */
16
16
  pacingSlot?: ProviderRequestSlot;
17
+ /** Internal queued rebuild already owns the outer provider fetch admission. */
18
+ dispatchPacingHeld?: boolean;
17
19
  /** Combo children must surface a pre-output refusal so the selector can try the next target. */
18
20
  comboAttempt?: boolean;
19
21
  /**
@@ -127,6 +129,8 @@ export interface AdapterRequest {
127
129
  method: string;
128
130
  headers: Record<string, string>;
129
131
  body: string;
132
+ /** Exact final wire model, captured before serialization for model-scoped transport gates. */
133
+ outboundModelId?: string;
130
134
  /** Final upstream wire names of custom tools lowered to functions while building this request. */
131
135
  convertedRoutedCustomToolNames?: ReadonlySet<string>;
132
136
  /** Native custom-tool wire names authorized for representation-only response repair. */
@@ -15,7 +15,7 @@ import {
15
15
  CODEBUDDY_TOOL_LIMITS,
16
16
  } from "../codebuddy/tool-bridge";
17
17
  import { CLAUDE_CLI_PROFILES, type ClaudeCliProfile } from "./profiles";
18
- import { checkClaudeUsageAdmission, recordClaudeUsageRefusal, type ClaudeAdmission } from "./usage-admission";
18
+ import { checkClaudeUsageAdmission, containsClaudeResetClock, recordClaudeUsageRefusal, type ClaudeAdmission } from "./usage-admission";
19
19
  import { buildStableClaudeConversationInput, CLAUDE_REPLAY_SYSTEM_PROMPT, stableClaudeToolBridge } from "./stable-replay";
20
20
 
21
21
  // The coding-agent bridge is protocol-level infrastructure shared with CodeBuddy. Its MCP server
@@ -286,12 +286,18 @@ export function createClaudeCliAdapter(provider: OcxProviderConfig, deps: Claude
286
286
  provider,
287
287
  parsed,
288
288
  incoming,
289
- emit: withClaudeLoginHint(event => {
290
- if (event.type === "error") {
291
- void Promise.resolve((deps.usageRefusal ?? recordClaudeUsageRefusal)(event.message)).catch(() => {});
292
- }
293
- emit(event);
294
- }),
289
+ emit: withClaudeLoginHint(emit),
290
+ onCliOutputError: message => {
291
+ // The model id is caller input that reaches the CLI verbatim, and the CLI may reflect it
292
+ // inside its own error wording. When the model id itself carries the reset-clock
293
+ // phrase the refusal parser honors, a parsed reset cannot be attributed to the
294
+ // account — it may be the model string echoed back rather than a limit Claude
295
+ // reported — so this turn's output records nothing. The error still reaches the
296
+ // client and limits the preflight already knows still gate; a genuine limit seen
297
+ // only on such a turn is delivered but deliberately not cached.
298
+ if (containsClaudeResetClock(parsed.modelId)) return;
299
+ void Promise.resolve().then(() => (deps.usageRefusal ?? recordClaudeUsageRefusal)(message)).catch(() => {});
300
+ },
295
301
  ...(toolBridge ? { toolBridge } : {}),
296
302
  conversationInput: buildStableClaudeConversationInput,
297
303
  buildArgs: (profile, req, prov) => buildArgs(profile as ClaudeCliProfile, req, prov, promptFile),
@@ -188,11 +188,23 @@ export function claudeUsagePreflight(model: string): Promise<ClaudeAdmission> {
188
188
  return (preflightOverride ?? checkClaudeUsageAdmission)(model);
189
189
  }
190
190
 
191
+ // Claude prints "resets 3pm (Europe/Paris)" or "resets 3:30pm (...)"; minutes are optional.
192
+ const CLAUDE_RESET_CLOCK = /resets?\s+(?:at\s+)?(\d{1,2})(?::(\d{2}))?\s*(am|pm)\s*\(([^)]+)\)/i;
193
+
194
+ /**
195
+ * Whether text carries the reset-clock wording the refusal parser honors. The check is lexical
196
+ * only — no "limit" keyword and no clock resolution against the current time — because the phrase
197
+ * matters wherever it appears: a caller-controlled model id can carry the clock while the CLI's
198
+ * own error wording supplies the limit keyword around it.
199
+ */
200
+ export function containsClaudeResetClock(text: string): boolean {
201
+ return CLAUDE_RESET_CLOCK.test(text);
202
+ }
203
+
191
204
  /** Parse Claude's explicit next-clock reset, including its IANA timezone. */
192
205
  export function parseClaudeReset(message: string, now = Date.now()): number | undefined {
193
206
  if (!/hit.*limit|usage limit|rate limit/i.test(message)) return;
194
- // Claude prints "resets 3pm (Europe/Paris)" or "resets 3:30pm (...)"; minutes are optional.
195
- const match = /resets?\s+(?:at\s+)?(\d{1,2})(?::(\d{2}))?\s*(am|pm)\s*\(([^)]+)\)/i.exec(message);
207
+ const match = CLAUDE_RESET_CLOCK.exec(message);
196
208
  if (!match) return;
197
209
  const hour = Number(match[1]); const minute = Number(match[2] ?? 0);
198
210
  if (hour < 1 || hour > 12 || minute > 59) return;
@@ -121,6 +121,8 @@ export interface CodingAgentTurnInput {
121
121
  parsed: OcxParsedRequest;
122
122
  incoming: IncomingMeta;
123
123
  emit: (event: AdapterEvent) => void;
124
+ /** Observes accepted CLI result/stderr failures, before client-side error decoration. */
125
+ onCliOutputError?: (message: string) => void;
124
126
  /** Family-specific headless argument builder (tools disabled, model, reasoning, system prompt). */
125
127
  buildArgs: (profile: CodingAgentProviderProfile, parsed: OcxParsedRequest, provider: OcxProviderConfig) => string[];
126
128
  /** Family-specific scoped env builder (credential + region switch on top of baseScopedEnv). */
@@ -368,11 +370,18 @@ export async function runCodingAgentTurn(input: CodingAgentTurnInput): Promise<v
368
370
  });
369
371
 
370
372
  let terminalEmitted = false;
371
- const emitOnce = (event: AdapterEvent): void => {
373
+ const emitOnce = (event: AdapterEvent, cliOutputError?: string): void => {
372
374
  if (event.type === "done" || event.type === "error" || event.type === "incomplete") {
373
375
  if (terminalEmitted) return;
374
376
  terminalEmitted = true;
375
377
  }
378
+ if (event.type === "error" && cliOutputError !== undefined) {
379
+ try {
380
+ input.onCliOutputError?.(cliOutputError);
381
+ } catch {
382
+ // An observer failure must never drop the client's terminal event or turn it into a rejection.
383
+ }
384
+ }
376
385
  emit(event);
377
386
  };
378
387
 
@@ -648,7 +657,8 @@ export async function runCodingAgentTurn(input: CodingAgentTurnInput): Promise<v
648
657
  }
649
658
  emitOnce(event.type === "error"
650
659
  ? { ...event, message: redactSecrets(event.message, profile.tokenEnv, apiKey) }
651
- : event);
660
+ : event, event.type === "error" && message.type === "result"
661
+ ? redactSecrets(event.message, profile.tokenEnv, apiKey) : undefined);
652
662
  }
653
663
  if (failClosed) break;
654
664
  const sawToolTurnStop = sawSelectedToolTurnStop();
@@ -762,7 +772,7 @@ export async function runCodingAgentTurn(input: CodingAgentTurnInput): Promise<v
762
772
  };
763
773
  emitOnce(input.classifyFailure
764
774
  ? input.classifyFailure({ source: "process-exit", exitCode: child.exitCode, stderr, error, profile })
765
- : error);
775
+ : error, stderr || undefined);
766
776
  } else if (toolBridge && deferredResultDone !== undefined && !sawSelectedToolTurnStop()) {
767
777
  emitOnce({
768
778
  type: "error",
@@ -783,7 +793,7 @@ export async function runCodingAgentTurn(input: CodingAgentTurnInput): Promise<v
783
793
  errorType: "upstream_error",
784
794
  code: "protocol_error",
785
795
  retryable: false,
786
- });
796
+ }, stderr || undefined);
787
797
  }
788
798
  }
789
799
  } finally {
@@ -869,6 +869,9 @@ function decodeResultParts(message: OcxToolResultMessage): DecodedResultPart[] |
869
869
  // Without this the document falls through to decodeInlineImage(part.imageUrl) below and is
870
870
  // treated as an image it is not.
871
871
  if (part.type === "document") return { kind: "text", text: part.text };
872
+ // The translated-adapter guard rejects audio before this wire; retain its marker if this
873
+ // decoder is ever called directly.
874
+ if (part.type === "audio") return { kind: "text", text: part.text };
872
875
  const decoded = decodeInlineImage(part.imageUrl);
873
876
  return decoded ? { kind: "image", ...decoded } : { kind: "undecodable" };
874
877
  });
@@ -27,6 +27,7 @@ const SENTENCE_END = /[.!?]["'\u201D\u2019)\]*_`]*(?=\s|$)|[\u3002\uFF01\uFF1F\u
27
27
 
28
28
  /** A boundary that only closes a leading list marker ("1.", "a.") or a common abbreviation ("e.g."). */
29
29
  const NOT_A_SENTENCE = /^(?:\d{1,3}|[a-z])\.$|(?:^|\s)(?:e\.g|i\.e|etc|vs)\.$/i;
30
+ const WHITESPACE = /\s/;
30
31
 
31
32
  /** Whether replayed progress text for this model is trimmed to its lead sentence. */
32
33
  export function trimsGeminiProgressHistory(modelId: string): boolean {
@@ -42,9 +43,26 @@ export function geminiProgressLead(text: string): string | undefined {
42
43
  if (trimmed.length === 0) return undefined;
43
44
  SENTENCE_END.lastIndex = 0;
44
45
  let end = trimmed.length;
46
+ let checked = 0;
47
+ let contentEnd = 0;
45
48
  for (let match = SENTENCE_END.exec(trimmed); match; match = SENTENCE_END.exec(trimmed)) {
46
49
  const boundary = match.index + match[0].length;
47
- if (!NOT_A_SENTENCE.test(trimmed.slice(0, boundary).trim())) { end = boundary; break; }
50
+ // Only a newline boundary can end in whitespace. Scan its new interval once; repeated
51
+ // blank lines retain the previous content end without rescanning the preceding text.
52
+ if (match[0] === "\n") {
53
+ for (let index = checked; index < boundary; index++) {
54
+ if (!WHITESPACE.test(trimmed[index])) contentEnd = index + 1;
55
+ }
56
+ } else {
57
+ contentEnd = boundary;
58
+ }
59
+ checked = boundary;
60
+ // The longest exception is four characters plus its preceding whitespace. The list
61
+ // marker alternative is anchored to the whole prefix, so allow it only at the start.
62
+ const start = Math.max(0, contentEnd - 5);
63
+ const suffix = trimmed.slice(start, contentEnd);
64
+ const exception = NOT_A_SENTENCE.exec(suffix);
65
+ if (!exception || (exception.index === 0 && start > 0 && !/^\s/.test(suffix))) { end = boundary; break; }
48
66
  }
49
67
  const lead = trimmed.slice(0, end).trim();
50
68
  // A code-fence opener is not a sentence; replaying it alone would leave an unclosed fence.
@@ -378,6 +378,7 @@ function messagesToGeminiFormat(
378
378
  stripRejectedClaudeSdkParagraph = false,
379
379
  isCloudCodeAssist = false,
380
380
  nestToolResultImages = false,
381
+ toolResponseImagesLast = false,
381
382
  ): { systemInstruction?: unknown; contents: unknown[]; replayedCallIds: string[] } {
382
383
  // Neutralize Codex's GPT-5 identity line (Gemini/Antigravity share this path) so a routed model
383
384
  // never misreports as GPT-5/OpenAI, and never leaks the proxy identity upstream.
@@ -557,11 +558,17 @@ function messagesToGeminiFormat(
557
558
  }
558
559
 
559
560
  const responseParts: unknown[] = [];
561
+ const trailingImages: unknown[] = [];
560
562
  for (const call of toolCalls) {
561
563
  const result = resultsById.get(call.wireCallId);
562
- if (result) responseParts.push(...geminiToolResultParts(result, call.wireName, call.wireCallId, nestToolResultImages));
563
- else responseParts.push(geminiMissingToolResultPart(call.wireName, call.wireCallId));
564
+ if (result) {
565
+ const [response, ...images] = geminiToolResultParts(result, call.wireName, call.wireCallId, nestToolResultImages);
566
+ responseParts.push(response);
567
+ (toolResponseImagesLast ? trailingImages : responseParts).push(...images);
568
+ } else responseParts.push(geminiMissingToolResultPart(call.wireName, call.wireCallId));
564
569
  }
570
+ // CCA Claude misses later responses when image siblings interrupt the response batch.
571
+ responseParts.push(...trailingImages);
565
572
  const orphanParts = orphanResults.flatMap(geminiOrphanToolResultParts);
566
573
  contents.push({ role: "user", parts: responseParts });
567
574
  // Orphan images cannot share Argon's response batch or claim another call's ownership.
@@ -1026,7 +1033,14 @@ export function createGoogleAdapter(provider: OcxProviderConfig): ProviderAdapte
1026
1033
  : provider.googleMode === "vertex" || openCodeZenGeminiEndpoint(provider, parsed.modelId) !== undefined
1027
1034
  ? parsed.modelId
1028
1035
  : resolveDirectGeminiWireModelId(parsed.modelId, provider.directGeminiWireRenames !== false);
1029
- returnsThoughtSummaries = provider.googleMode === "cloud-code-assist"
1036
+ const configuredEfforts = configuredReasoningEfforts(provider, parsed.modelId);
1037
+ const thinkingEligible = provider.googleMode !== "cloud-code-assist"
1038
+ && !isImageCapableModel(parsed.modelId)
1039
+ && (configuredEfforts !== undefined
1040
+ ? configuredEfforts.length > 0
1041
+ : (provider.googleMode !== "vertex"
1042
+ && (parsed.modelId === "gemini-3.5-flash" || parsed.modelId === "gemini-3.6-flash")));
1043
+ returnsThoughtSummaries = (provider.googleMode === "cloud-code-assist" || (thinkingEligible && provider.showThinkingSummary === true))
1030
1044
  && /^gemini-/.test(routedModelId) && !isImageCapableModel(parsed.modelId);
1031
1045
  // AI Studio's `-tiered` spelling is wire-only; CCA aliases may migrate to another generation.
1032
1046
  const identityModelId = provider.googleMode === "cloud-code-assist" ? routedModelId : parsed.modelId;
@@ -1039,6 +1053,7 @@ export function createGoogleAdapter(provider: OcxProviderConfig): ProviderAdapte
1039
1053
  stripRejectedClaudeSdkParagraph,
1040
1054
  isCloudCodeAssist,
1041
1055
  provider.googleMode === "vertex" && parsed.modelId === "gemini-4-argon",
1056
+ isCloudCodeAssist && /^claude-/i.test(routedModelId),
1042
1057
  );
1043
1058
  lastInjectedCallIds = [...replayedCallIds];
1044
1059
  lastReasoningReplayScope = parsed._reasoningReplayScope;
@@ -1065,15 +1080,19 @@ export function createGoogleAdapter(provider: OcxProviderConfig): ProviderAdapte
1065
1080
  // current behavior; Vertex participates only through an explicitly configured ladder (the
1066
1081
  // seed google-vertex entry ships none). Image models are excluded — thinkingConfig would
1067
1082
  // suppress the responseModalities fallback below. CCA maps effort on its envelope path.
1068
- const thinkingEligible = provider.googleMode !== "cloud-code-assist"
1069
- && !isImageCapableModel(parsed.modelId)
1070
- && (configuredReasoningEfforts(provider, parsed.modelId) !== undefined
1071
- || (provider.googleMode !== "vertex"
1072
- && (parsed.modelId === "gemini-3.5-flash" || parsed.modelId === "gemini-3.6-flash")));
1073
1083
  const thinkingLevel = thinkingEligible
1074
1084
  ? mapReasoningEffort(provider, parsed.modelId, parsed.options.reasoning)
1075
1085
  : undefined;
1076
- if (thinkingLevel) generationConfig.thinkingConfig = { thinkingLevel };
1086
+ const includeThoughts = thinkingEligible
1087
+ && provider.showThinkingSummary === true
1088
+ && parsed.options.hideThinkingSummary !== true
1089
+ && /^gemini-/.test(routedModelId);
1090
+ if (thinkingLevel || includeThoughts) {
1091
+ generationConfig.thinkingConfig = {
1092
+ ...(thinkingLevel ? { thinkingLevel } : {}),
1093
+ ...(includeThoughts ? { includeThoughts: true } : {}),
1094
+ };
1095
+ }
1077
1096
  if (!generationConfig.thinkingConfig && isImageCapableModel(parsed.modelId)) {
1078
1097
  generationConfig.responseModalities = ["TEXT", "IMAGE"];
1079
1098
  }
@@ -18,9 +18,11 @@ export function parseDataUrl(url: string): { mediaType: string; base64: string }
18
18
  */
19
19
  export function contentPartsToText(content: string | OcxContentPart[]): string {
20
20
  if (typeof content === "string") return content;
21
- // A document carries its own marker, so this wire states the attachment instead of
22
- // mislabelling it as a video.
21
+ // Documents and audio carry their own markers, so this wire states the attachment instead
22
+ // of mislabelling it as a video.
23
23
  const text = content.map(p =>
24
- p.type === "text" || p.type === "document" ? p.text : p.type === "image" ? "[image]" : "[video]").join("");
24
+ p.type === "text" || p.type === "document" || p.type === "audio"
25
+ ? p.text
26
+ : p.type === "image" ? "[image]" : "[video]").join("");
25
27
  return text || "[image]";
26
28
  }
@@ -10,7 +10,8 @@ import type { OcxParsedRequest } from "../types";
10
10
  * out because it uses the original body rather than the lossy normalized content.
11
11
  *
12
12
  * Two of the three checks are wire-scoped, and that is the point. A constraint the normalized
13
- * request CAN carry — a caller restriction on a tool, an attached document's bytes — still has
13
+ * request CAN carry — a caller restriction on a tool, an attached document's bytes, or inline
14
+ * audio in the translated Chat content model — still has
14
15
  * to reach a wire that can express it. Leaving that to each adapter means an adapter that never
15
16
  * learned about the carrier rebuilds without it and answers normally, so the allowlist in
16
17
  * `declaration-carrier.ts` is default-deny and this is the one place every registered adapter
@@ -18,7 +19,9 @@ import type { OcxParsedRequest } from "../types";
18
19
  */
19
20
  export function withInputMediaGuard<T extends ProviderAdapter>(adapter: T, wire: AdapterWire): T {
20
21
  const refusal = (parsed: OcxParsedRequest): string | undefined => {
21
- const kind = untranslatedResponsesInputMedia(parsed._rawBody);
22
+ // Chat Completions has a native input_audio user-content part. The adapter promotes
23
+ // tool-result audio into a follow-up user message, so these blocks no longer lose bytes.
24
+ const kind = untranslatedResponsesInputMedia(parsed._rawBody, { allowAudio: wire === "openai-chat" });
22
25
  return kind ? untranslatedInputMediaMessage(kind) : unrepresentableDeclaration(parsed, wire);
23
26
  };
24
27
  const build = adapter.buildRequest.bind(adapter);
@@ -1,8 +1,13 @@
1
1
  /** Account-scoped Kiro refusals. Unknown data never convicts an account. */
2
2
  import { BOUNDED_BODY_MAX_BYTES } from "../lib/bounded-body";
3
- export type KiroRefusalKind = "rate" | "monthly_quota" | "suspended" | "other";
3
+ export type KiroRefusalKind = "rate" | "monthly_quota" | "suspended" | "profile" | "other";
4
4
  export interface KiroRefusal { kind: KiroRefusalKind; resetAt?: number }
5
5
 
6
+ /** The vendor's own name for the body validator that rejects a request for this identity. */
7
+ const VALIDATION_EXCEPTION = "ValidationException";
8
+ /** Kiro's wording for that rejection; the code alone is also what a genuinely bad payload gets. */
9
+ const IMPROPER_REQUEST_WORD = /improperly formed request/i;
10
+
6
11
  const SUSPENSION_WORDS = [
7
12
  "temporarily suspended", "temporarily is suspended",
8
13
  "locked your account", "locked it as a",
@@ -22,9 +27,44 @@ export function classifyKiroRefusal(status: number, bodyText: string): KiroRefus
22
27
  } catch { /* Unrecognised bodies cannot establish an account verdict. */ }
23
28
  if ((status === 400 || status === 429) && reason === "MONTHLY_REQUEST_COUNT")
24
29
  return { kind: "monthly_quota" };
30
+ // A 400 whose own validator calls the body improperly formed is not proof that the request is
31
+ // impossible: Kiro answers this shape when the identity a request was routed under cannot serve
32
+ // it. Treating it as `other` leaves the account selected and the same 400 reaches the client.
33
+ // Both vendor tokens are required, so a bad payload or a caller echoing one token stays terminal.
34
+ if (status === 400 && typeof message === "string" && IMPROPER_REQUEST_WORD.test(message)
35
+ && (reason === VALIDATION_EXCEPTION || message.includes(VALIDATION_EXCEPTION)))
36
+ return { kind: "profile" };
25
37
  if (status === 403 && (reason === "TEMPORARILY_SUSPENDED"
26
38
  || (typeof message === "string" && SUSPENSION_WORDS.some(word => message.toLowerCase().includes(word)))))
27
39
  return { kind: "suspended" };
28
40
  if (status === 429) return { kind: "rate" };
29
41
  return { kind: "other" };
30
42
  }
43
+
44
+ /** The adapter's own prefix for a normalized 400 (`normalizedKiroErrorMessage` in kiro-errors.ts). */
45
+ const KIRO_INVALID_REQUEST_PREFIX = "Kiro invalid request: ";
46
+
47
+ /**
48
+ * The same verdict at the combo layer. There the text is either the adapter's normalized message
49
+ * ("Kiro invalid request: ValidationException: Improperly formed request", what a combo child's
50
+ * failure carries) or a raw JSON body, each possibly behind the "Provider error 400: " frame.
51
+ * JSON goes through the parsed `reason`/`message` rules of `classifyKiroRefusal` (tokens in
52
+ * unrelated fields never count); prose counts only behind the adapter's own prefix. Callers must
53
+ * also know the failed target is a Kiro adapter.
54
+ */
55
+ export function isKiroAccountProfileRefusal(status: number, bodyText: string): boolean {
56
+ if (status !== 400 || Buffer.byteLength(bodyText, "utf8") > BOUNDED_BODY_MAX_BYTES) return false;
57
+ const text = bodyText.replace(/^Provider error \d{3}: /, "");
58
+ if (text.startsWith(KIRO_INVALID_REQUEST_PREFIX)) {
59
+ const detail = text.slice(KIRO_INVALID_REQUEST_PREFIX.length);
60
+ return detail.includes(VALIDATION_EXCEPTION) && IMPROPER_REQUEST_WORD.test(detail);
61
+ }
62
+ try {
63
+ const row: unknown = JSON.parse(text);
64
+ if (!row || typeof row !== "object" || Array.isArray(row)) return false;
65
+ const envelope = (row as Record<string, unknown>).error;
66
+ const body = envelope && typeof envelope === "object" && !Array.isArray(envelope) ? envelope : row;
67
+ const { reason, message } = body as Record<string, unknown>;
68
+ return classifyKiroRefusal(400, JSON.stringify({ reason, message })).kind === "profile";
69
+ } catch { return false; }
70
+ }
@@ -290,6 +290,7 @@ function contentToNative(
290
290
  text += part.text;
291
291
  continue;
292
292
  }
293
+ if (part.type === "audio") throw new Error(`ollama-native cannot send audio content in ${label}`);
293
294
  // Ollama's native /api/chat message shape carries `images: string[]` and has no video
294
295
  // counterpart, so a video part is refused rather than silently dropped or mis-sent as an image.
295
296
  if (part.type === "video") throw new Error(`ollama-native cannot send video content in ${label}`);
@@ -27,8 +27,8 @@ const VIDEO_UNSUPPORTED_MARKER = "[video omitted: the translated Chat route has
27
27
  /**
28
28
  * Chat-completions image_url parts for images carried inside a tool result (issue #888). role:"tool"
29
29
  * content is text-only on every chat provider, so these ride in a follow-up user message instead of
30
- * being flattened to the "[image]" marker the model can't actually see. Data URLs and remote https
31
- * URLs are both valid in image_url.url, unlike Gemini inline_data which needs base64.
30
+ * being flattened to the "[image]" marker the model can't actually see. The same follow-up carries
31
+ * inline audio as input_audio, which is also user-content-only on this wire.
32
32
  */
33
33
  export function toolResultTextForWire(content: string | OcxContentPart[], annotateEmpty = false): string {
34
34
  // An empty content array is a present-but-empty result; `contentPartsToText` would
@@ -63,6 +63,14 @@ export function toolResultImageChatParts(content: string | OcxContentPart[]): un
63
63
  return parts;
64
64
  }
65
65
 
66
+ /** Chat input_audio parts for audio carried inside a tool result. */
67
+ export function toolResultAudioChatParts(content: string | OcxContentPart[]): unknown[] {
68
+ if (typeof content === "string") return [];
69
+ return content
70
+ .filter((p): p is Extract<OcxContentPart, { type: "audio" }> => p.type === "audio")
71
+ .map(p => ({ type: "input_audio", input_audio: { data: p.data, format: p.format } }));
72
+ }
73
+
66
74
  /**
67
75
  * Whether this wire serializes a replayed thinking block for the given model.
68
76
  *
@@ -98,6 +106,7 @@ export function messagesToChatFormat(parsed: OcxParsedRequest, provider: OcxProv
98
106
  let pendingToolCalls: PendingToolCall[] = [];
99
107
  let deferredBarrierMessages: unknown[] = [];
100
108
  let pendingToolResultImageParts: unknown[] = [];
109
+ let pendingToolResultAudioParts: unknown[] = [];
101
110
  let mintedIdSeq = 0;
102
111
  const seenWireCallIds = new Set<string>();
103
112
 
@@ -128,6 +137,18 @@ export function messagesToChatFormat(parsed: OcxParsedRequest, provider: OcxProv
128
137
  pendingToolResultImageParts = [];
129
138
  };
130
139
 
140
+ const flushToolResultAudio = (): void => {
141
+ if (pendingToolResultAudioParts.length === 0) return;
142
+ out.push({
143
+ role: "user",
144
+ content: [
145
+ { type: "text", text: "[ocx] audio output from the preceding tool result(s):" },
146
+ ...pendingToolResultAudioParts,
147
+ ],
148
+ });
149
+ pendingToolResultAudioParts = [];
150
+ };
151
+
131
152
  const flushPendingToolCalls = (): void => {
132
153
  if (pendingToolCalls.length === 0) return;
133
154
  for (const call of pendingToolCalls) {
@@ -139,6 +160,7 @@ export function messagesToChatFormat(parsed: OcxParsedRequest, provider: OcxProv
139
160
  }
140
161
  pendingToolCalls = [];
141
162
  flushToolResultImages();
163
+ flushToolResultAudio();
142
164
  releaseDeferredBarriers();
143
165
  };
144
166
 
@@ -185,9 +207,10 @@ export function messagesToChatFormat(parsed: OcxParsedRequest, provider: OcxProv
185
207
  case "developer": {
186
208
  const parts = typeof msg.content === "string" ? undefined : msg.content as OcxContentPart[];
187
209
  const hasImages = parts?.some(p => p.type === "image") ?? false;
210
+ const hasAudio = parts?.some(p => p.type === "audio") ?? false;
188
211
  // A document has a structured counterpart on this wire, so it needs the parts array for
189
212
  // the same reason an image does: flattening it to a string would drop the bytes.
190
- const hasStructured = hasImages || (parts?.some(p => p.type === "document") ?? false);
213
+ const hasStructured = hasImages || hasAudio || (parts?.some(p => p.type === "document") ?? false);
191
214
  let chatMsg: Record<string, unknown>;
192
215
  if (msg.role === "developer" && !hasStructured) {
193
216
  const text = typeof msg.content === "string"
@@ -219,6 +242,9 @@ export function messagesToChatFormat(parsed: OcxParsedRequest, provider: OcxProv
219
242
  if (p.type === "image") {
220
243
  return { type: "image_url", image_url: { url: p.imageUrl, ...(p.detail ? { detail: p.detail } : {}) } };
221
244
  }
245
+ if (p.type === "audio") {
246
+ return { type: "input_audio", input_audio: { data: p.data, format: p.format } };
247
+ }
222
248
  // Chat Completions carries an attached document as a file part with inline bytes,
223
249
  // the direct counterpart of the Anthropic document block the caller sent.
224
250
  if (p.type === "document") {
@@ -240,7 +266,7 @@ export function messagesToChatFormat(parsed: OcxParsedRequest, provider: OcxProv
240
266
  // this wire. One carrying only a document has no such precedent, and demoting it would
241
267
  // undo the role this adapter just finished preserving.
242
268
  chatMsg = {
243
- role: msg.role === "developer" && !hasImages ? developerWireRole : "user",
269
+ role: msg.role === "developer" && !hasImages && !hasAudio ? developerWireRole : "user",
244
270
  content: chatParts,
245
271
  };
246
272
  }
@@ -330,9 +356,11 @@ export function messagesToChatFormat(parsed: OcxParsedRequest, provider: OcxProv
330
356
  content: toolResultTextForWire(msg.content, provider.annotateEmptyToolOutputs === true),
331
357
  });
332
358
  pendingToolResultImageParts.push(...toolResultImageChatParts(msg.content));
359
+ pendingToolResultAudioParts.push(...toolResultAudioChatParts(msg.content));
333
360
  pendingToolCalls.splice(matchIdx, 1);
334
361
  if (pendingToolCalls.length === 0) {
335
362
  flushToolResultImages();
363
+ flushToolResultAudio();
336
364
  releaseDeferredBarriers();
337
365
  }
338
366
  } else {
@@ -380,7 +408,9 @@ export function messagesToChatFormat(parsed: OcxParsedRequest, provider: OcxProv
380
408
  content: toolResultTextForWire(msg.content, provider.annotateEmptyToolOutputs === true),
381
409
  });
382
410
  pendingToolResultImageParts.push(...toolResultImageChatParts(msg.content));
411
+ pendingToolResultAudioParts.push(...toolResultAudioChatParts(msg.content));
383
412
  flushToolResultImages();
413
+ flushToolResultAudio();
384
414
  }
385
415
  break;
386
416
  }