@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.
- package/gui/dist/assets/App-DgxkE6Md.js +58 -0
- package/gui/dist/assets/{Tray-7z1COnmz.js → Tray-DbTNc_88.js} +1 -1
- package/gui/dist/assets/{index-uchD-ngf.js → index-TmaHa54u.js} +5 -5
- package/gui/dist/assets/quota-summary-B16x5DZZ.js +1 -0
- package/gui/dist/index.html +1 -1
- package/package.json +2 -2
- package/src/adapters/base.ts +4 -0
- package/src/adapters/claude-cli/adapter.ts +13 -7
- package/src/adapters/claude-cli/usage-admission.ts +14 -2
- package/src/adapters/coding-agent/turn.ts +14 -4
- package/src/adapters/cursor/protobuf-request.ts +3 -0
- package/src/adapters/google-progress-history.ts +19 -1
- package/src/adapters/google.ts +28 -9
- package/src/adapters/image.ts +5 -3
- package/src/adapters/input-media-guard.ts +5 -2
- package/src/adapters/kiro-refusal.ts +41 -1
- package/src/adapters/ollama-native.ts +1 -0
- package/src/adapters/openai-chat/messages.ts +34 -4
- package/src/adapters/openai-chat/passthrough.ts +37 -4
- package/src/adapters/openai-chat/reasoning-replay.ts +98 -13
- package/src/adapters/openai-chat/serialized-tool-call-content.ts +95 -134
- package/src/adapters/openai-chat/serialized-tool-call-markup.ts +108 -0
- package/src/adapters/openai-chat/standalone-bare-tool-calls.ts +136 -0
- package/src/adapters/openai-chat.ts +7 -6
- package/src/adapters/openai-responses/opengateway-input.ts +139 -0
- package/src/adapters/openai-responses/passthrough.ts +5 -1
- package/src/adapters/openai-responses/transport.ts +13 -1
- package/src/claude/desktop-3p-library.ts +43 -3
- package/src/claude/desktop-3p.ts +20 -10
- package/src/claude/desktop-picker-profile.ts +18 -9
- package/src/claude/desktop-remote-store-io.ts +2 -2
- package/src/cli/ensure-desktop-cold-start.ts +2 -2
- package/src/codex/account-lifecycle.ts +19 -6
- package/src/codex/account-store.ts +27 -8
- package/src/codex/account-usability.ts +4 -1
- package/src/codex/auth-api/account-list.ts +10 -5
- package/src/codex/auth-api/account-pause-group.ts +2 -22
- package/src/codex/auth-api/login-collision.ts +59 -0
- package/src/codex/auth-api/login-flow.ts +12 -7
- package/src/codex/auth-api/pool-mode-gate.ts +81 -13
- package/src/codex/auth-collision.ts +31 -4
- package/src/codex/auth-context.ts +48 -6
- package/src/codex/cli-update-plan.ts +18 -3
- package/src/codex/collision-identity.ts +78 -0
- package/src/codex/main-account-hard-lock.ts +14 -0
- package/src/codex/routing/cooldown-math.ts +5 -0
- package/src/codex/routing/failure-window.ts +61 -9
- package/src/codex/routing.ts +4 -3
- package/src/codex/shim-diagnostics.ts +2 -1
- package/src/codex/shim-fingerprint.ts +11 -2
- package/src/codex/shim-templates.ts +16 -5
- package/src/codex/shim-windows-refresh.ts +224 -0
- package/src/codex/shim.ts +45 -21
- package/src/combos/failover.ts +8 -1
- package/src/config/provider-validation.ts +7 -2
- package/src/generated/compatibility-version.json +168 -108
- package/src/generated/model-metadata.ts +1 -1
- package/src/images/loop.ts +2 -2
- package/src/lib/bun-transpiler-cache-scope.mjs +31 -17
- package/src/lib/provider-admission-wait.ts +14 -0
- package/src/lib/service-secrets.ts +37 -2
- package/src/lib/translator-budget.ts +1 -1
- package/src/lib/upstream-retry.ts +15 -0
- package/src/oauth/account-import/google-antigravity-adapter.ts +38 -2
- package/src/oauth/account-import/parser.ts +15 -2
- package/src/oauth/account-import/types.ts +7 -0
- package/src/oauth/chatgpt-shared.ts +10 -1
- package/src/oauth/dsh.ts +45 -2
- package/src/oauth/kiro.ts +44 -1
- package/src/oauth/login-flow-state.ts +11 -2
- package/src/providers/claude-cli-usage.ts +20 -5
- package/src/providers/initial-model-selection.ts +2 -2
- package/src/providers/key-failover.ts +10 -2
- package/src/providers/key-store.ts +8 -3
- package/src/providers/mistral-transport.ts +207 -0
- package/src/providers/openai-sidecar.ts +5 -0
- package/src/providers/quota/anthropic-account-quota.ts +18 -6
- package/src/providers/quota/antigravity.ts +6 -2
- package/src/providers/quota/failure-codes.ts +18 -0
- package/src/providers/quota/vendor-probes-oauth.ts +12 -3
- package/src/providers/quota-routing-cache.ts +1 -1
- package/src/providers/quota.ts +5 -1
- package/src/providers/registry/entries-extended.ts +6 -1
- package/src/providers/routed-config.ts +1 -1
- package/src/providers/xai-transport.ts +2 -1
- package/src/responses/audio.ts +46 -0
- package/src/responses/input-media.ts +37 -15
- package/src/responses/parser-content.ts +22 -27
- package/src/responses/reasoning-retention.ts +218 -11
- package/src/responses/schema.ts +3 -4
- package/src/responses/web-search-replay.ts +11 -2
- package/src/server/chat-native.ts +8 -7
- package/src/server/index/serve-options.ts +8 -2
- package/src/server/index/websocket-handler.ts +10 -0
- package/src/server/lifecycle.ts +17 -1
- package/src/server/management/oauth-account-routes.ts +2 -1
- package/src/server/messages-native.ts +11 -0
- package/src/server/request-log.ts +16 -7
- package/src/server/responses/adapter-continuation.ts +2 -2
- package/src/server/responses/adapter-dispatch.ts +2 -2
- package/src/server/responses/codex-ws-exchange.ts +3 -0
- package/src/server/responses/codex-ws-metadata.ts +44 -0
- package/src/server/responses/codex-ws-session.ts +21 -1
- package/src/server/responses/combo-stream-preflight.ts +7 -2
- package/src/server/responses/compact.ts +2 -0
- package/src/server/responses/core-auth.ts +20 -0
- package/src/server/responses/core-codex-account.ts +21 -14
- package/src/server/responses/core-combo.ts +3 -0
- package/src/server/responses/core-opaque-recovery.ts +20 -11
- package/src/server/responses/deepseek-image-files.ts +121 -0
- package/src/server/responses/empty-completion-guard.ts +8 -0
- package/src/server/responses/fetch-helpers.ts +30 -10
- package/src/server/responses/input-admission.ts +6 -2
- package/src/server/responses/main-hard-lock-routing.ts +33 -8
- package/src/server/responses/opengateway-completion-guard.ts +232 -0
- package/src/server/responses/passthrough-completion.ts +41 -0
- package/src/server/responses/passthrough-delivery.ts +2 -0
- package/src/server/responses/passthrough-dispatch.ts +13 -13
- package/src/server/responses/passthrough-key-rotation.ts +40 -0
- package/src/server/responses/reasoning-archive-error.ts +21 -0
- package/src/server/responses/request-prepare.ts +11 -1
- package/src/server/responses/request-transport.ts +61 -3
- package/src/service/orchestration.ts +17 -0
- package/src/types/provider.ts +2 -0
- package/src/types/request.ts +16 -1
- package/src/types.ts +1 -0
- package/src/web-search/loop.ts +2 -2
- package/gui/dist/assets/App-BnRSujOq.js +0 -58
- 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};
|
package/gui/dist/index.html
CHANGED
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
document.documentElement.lang = langMap[locale];
|
|
37
37
|
})();
|
|
38
38
|
</script>
|
|
39
|
-
<script type="module" crossorigin src="/assets/index-
|
|
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.
|
|
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.
|
|
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"
|
package/src/adapters/base.ts
CHANGED
|
@@ -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(
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
package/src/adapters/google.ts
CHANGED
|
@@ -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)
|
|
563
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
}
|
package/src/adapters/image.ts
CHANGED
|
@@ -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
|
-
//
|
|
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"
|
|
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
|
|
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
|
-
|
|
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.
|
|
31
|
-
*
|
|
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
|
}
|