@cortexkit/opencode-anthropic-auth 1.5.0 → 1.6.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/README.md CHANGED
@@ -19,8 +19,8 @@ This repo is a Bun workspace monorepo with two user-facing integrations and one
19
19
  | Primary Claude Pro/Max OAuth | OpenCode `/connect anthropic` | Pi `/login anthropic` |
20
20
  | Provider integration point | OpenCode plugin fetch/request transform | Pi `registerProvider("anthropic")` provider override |
21
21
  | Sidecar config | `~/.config/opencode/anthropic-auth.json` | `~/.pi/agent/anthropic-auth.json` |
22
- | Commands | `/claude-cache`, `/claude-cachekeep`, `/claude-routing`, `/claude-fast`, `/claude-quota`, `/claude-dump` | `/claude-cache`, `/claude-cachekeep`, `/claude-routing`, `/claude-fast`, `/claude-quota`, `/claude-dump` |
23
- | Fallback accounts, quota routing, relay, dumps, fast mode | Supported | Supported through the same shared core and Pi sidecar |
22
+ | Commands | `/claude-cache`, `/claude-cachekeep`, `/claude-routing`, `/claude-fast`, `/claude-quota`, `/claude-dump`, `/claude-killswitch` | `/claude-cache`, `/claude-cachekeep`, `/claude-routing`, `/claude-fast`, `/claude-quota`, `/claude-dump` |
23
+ | Fallback accounts, quota routing, killswitch, relay, dumps, fast mode | Supported | Supported through the same shared core and Pi sidecar |
24
24
 
25
25
  ## What CortexKit adds over the original plugin
26
26
 
@@ -31,6 +31,7 @@ This repo is a Bun workspace monorepo with two user-facing integrations and one
31
31
  - **Cache keepalive**: use `/claude-cachekeep HH-HH` to pre-warm hybrid cache anchors for active sessions before the 1-hour TTL expires.
32
32
  - **Fast mode toggle**: use `/claude-fast on|off` to request Anthropic fast mode for supported Opus models.
33
33
  - **Live quota visibility**: use `/claude-quota` to see main and fallback quota state, reset times, and refresh errors.
34
+ - **Killswitch**: per-account hard-block thresholds that stop requests before hitting Anthropic's rate limits, with synthetic 429 retry-after when all accounts are exhausted.
34
35
  - **User-owned Cloudflare relay**: optionally provision your own Worker relay to reduce repeated client upload bytes for large OpenCode or Pi requests.
35
36
  - **Claude-compatible request hardening**: final-body billing signing, safer token refresh persistence, replay-safe fallback retries, and subagent cache isolation.
36
37
 
@@ -171,7 +172,13 @@ Example:
171
172
  "five_hour": 10,
172
173
  "seven_day": 20
173
174
  },
174
- "failClosedOnUnknownQuota": true
175
+ "failClosedOnUnknownQuota": true,
176
+ "showToasts": false
177
+ },
178
+ "killswitch": {
179
+ "enabled": false,
180
+ "main": { "five_hour": 5, "seven_day": 10 },
181
+ "accounts": {}
175
182
  },
176
183
  "claudeCache": {
177
184
  "enabled": false,
@@ -199,7 +206,7 @@ Example:
199
206
  }
200
207
  ```
201
208
 
202
- The `routing` block controls `/claude-routing`, `claudeCache` controls `/claude-cache`, `cacheKeep` controls `/claude-cachekeep`, and `claudeFast` controls `/claude-fast`. The `main` field identifies OpenCode's primary auth entry; Pi keeps primary OAuth credentials in Pi's own credential store, but uses the same sidecar shape for CortexKit settings and fallback accounts.
209
+ The `routing` block controls `/claude-routing`, `claudeCache` controls `/claude-cache`, `cacheKeep` controls `/claude-cachekeep`, and `claudeFast` controls `/claude-fast`. Set `quota.showToasts` to `true` to opt into OpenCode quota toast notifications after quota refreshes. The `main` field identifies OpenCode's primary auth entry; Pi keeps primary OAuth credentials in Pi's own credential store, but uses the same sidecar shape for CortexKit settings and fallback accounts.
203
210
 
204
211
  ## Fallback accounts
205
212
 
@@ -264,6 +271,49 @@ In OpenCode, this includes the main Anthropic account and sidecar fallback accou
264
271
 
265
272
  Reset times are rendered as relative durations, such as `resets in 10m` or `resets in 1h 15m`.
266
273
 
274
+ ## Killswitch
275
+
276
+ The killswitch is a per-account hard-block that stops requests when remaining quota drops below configured thresholds, even if Anthropic's API would still accept them. Unlike `minimumRemaining` (which routes to fallback accounts), the killswitch removes accounts from the routing pool entirely.
277
+
278
+ Add a `killswitch` block to the sidecar config:
279
+
280
+ ```json
281
+ "killswitch": {
282
+ "enabled": true,
283
+ "main": {
284
+ "five_hour": 5,
285
+ "seven_day": 10
286
+ },
287
+ "accounts": {
288
+ "work-alt": {
289
+ "five_hour": 10,
290
+ "seven_day": 20
291
+ }
292
+ }
293
+ }
294
+ ```
295
+
296
+ Thresholds are remaining-percent values. With `five_hour: 5`, the account is killed when less than 5% of the 5-hour quota window remains. Accounts without an entry in `accounts` fall back to the `main` thresholds. The aliases `5h` and `1w` are also accepted.
297
+
298
+ Behavior:
299
+
300
+ - When an account is killed, it is skipped during routing. Surviving accounts are tried instead.
301
+ - When all accounts (main and all enabled fallbacks) are killed, the plugin returns a synthetic 429 response with a `retry-after` header set to the earliest quota reset time across all accounts.
302
+ - On the first request after restart, the plugin eagerly fetches main quota so the killswitch evaluates immediately.
303
+ - `/claude-quota` shows killswitch status and per-account killed/active state.
304
+
305
+ Manage the killswitch from inside OpenCode:
306
+
307
+ ```text
308
+ /claude-killswitch — show status and command cheatsheet
309
+ /claude-killswitch on — enable with current or default thresholds
310
+ /claude-killswitch off — disable
311
+ /claude-killswitch set all:5,10 — set all accounts to 5h≥5%, 1w≥10%
312
+ /claude-killswitch set main:3,8 work-alt:5,10 — per-account thresholds
313
+ ```
314
+
315
+ Changes made with `/claude-killswitch` are persisted to the sidecar config.
316
+
267
317
  ## Claude prompt cache control
268
318
 
269
319
  Both OpenCode and Pi packages add a slash command for Anthropic's 1-hour ephemeral prompt-cache TTL:
package/dist/cli.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import{m as y,n as w,p as l,q as u,qa as b,r as m,sa as k}from"./index-4wz5npbg.js";import{stdin as A,stdout as $}from"node:process";import{createInterface as R}from"node:readline/promises";function v(){return{version:1,main:{type:"opencode",provider:"anthropic"},fallbackOn:[401,403,429],refresh:{enabled:!0,intervalMinutes:10,refreshBeforeExpiryMinutes:240},quota:{enabled:!0,checkIntervalMinutes:5,minimumRemaining:{five_hour:10,seven_day:20},failClosedOnUnknownQuota:!0},accounts:[]}}function h(){console.log(`Usage:
2
+ import{Aa as k,m as y,n as w,p as l,q as u,r as m,ya as b}from"./index-zx0zb5c8.js";import{stdin as A,stdout as $}from"node:process";import{createInterface as R}from"node:readline/promises";function v(){return{version:1,main:{type:"opencode",provider:"anthropic"},fallbackOn:[401,403,429],refresh:{enabled:!0,intervalMinutes:10,refreshBeforeExpiryMinutes:240},quota:{enabled:!0,checkIntervalMinutes:5,minimumRemaining:{five_hour:10,seven_day:20},failClosedOnUnknownQuota:!0},accounts:[]}}function h(){console.log(`Usage:
3
3
  opencode-anthropic-auth login [label]
4
4
  opencode-anthropic-auth list
5
5
  opencode-anthropic-auth relay setup
@@ -0,0 +1,2 @@
1
+ import{mkdir as K,readFile as M,writeFile as O}from"node:fs/promises";import{tmpdir as P}from"node:os";import{dirname as Q,join as H}from"node:path";var W="OPENCODE_ANTHROPIC_AUTH_SIDEBAR_STATE_FILE",X=H(P(),"opencode-anthropic-auth"),Y=H(X,"sidebar-state.json");function J(){return process.env[W]||Y}var Z={main:{quota:null},fallbacks:[],activeId:void 0,route:"main",relay:null,fastMode:!1,lastUpdated:0};async function N(){try{let q=await M(J(),"utf8");return JSON.parse(q)}catch{return Z}}async function V(q){try{let z=J();await K(Q(z),{recursive:!0}),await O(z,JSON.stringify(q),"utf8")}catch{}}function g(q){let z=q.activeId;if(z&&z!=="main"){let C=q.fallbacks.find((G)=>G.enabled&&G.id===z);if(C)return{id:C.id,name:C.label??C.id,quota:C.quota}}return{id:"main",name:"main",quota:q.main.quota}}
2
+ export{J as Ga,Z as Ha,N as Ia,V as Ja,g as Ka};
@@ -0,0 +1,335 @@
1
+ var r="9d1c250a-e61b-44d9-88ed-5944d1962f5e",cf={console:"https://platform.claude.com/oauth/authorize",max:"https://claude.ai/oauth/authorize"},Sf="https://platform.claude.com/oauth/code/callback",Ff="https://platform.claude.com/v1/oauth/token",tf=["org:create_api_key","user:profile","user:inference","user:sessions:claude_code","user:mcp_servers","user:file_upload"],q$="mcp_";var sf="fast-mode-2026-02-01";function P$(f,_){let $=(f??"").split(",").map((m)=>m.trim()).filter(Boolean);return[...new Set([...$,..._])].join(",")}function T$(f){return typeof f==="string"&&(f.startsWith("claude-opus-4-6")||f.startsWith("claude-opus-4-7")||f.startsWith("claude-opus-4-8"))}var R$="You are OpenCode",w$="You are a Claude agent, built on Anthropic's Claude Agent SDK.",i$=["<use_parallel_tool_calls>","For maximum efficiency, whenever you perform multiple independent operations, invoke all relevant tools simultaneously rather than sequentially. Prioritize calling independent tools in parallel whenever possible. For example, when reading 3 known files, run 3 tool calls in parallel to read all 3 files into context at the same time. When running multiple independent read-only commands like `ls` or `list_dir`, run all of those commands in parallel. Err on the side of maximizing parallel tool calls for independent work rather than running too many tools sequentially.","","Do not parallelize tool calls when one call depends on the output of another call. If a tool call needs an ID, filename, search result, or any other value returned by a previous tool call, run the first call, wait for its result, then run the dependent call using the real returned value. Never invent placeholder IDs, guessed task IDs, or other guessed values for dependent tool calls just to place them in the same parallel block.","</use_parallel_tool_calls>"].join(`
2
+ `);var x="2.1.141",Gf="67b",rf="sdk-cli",of="0.94.0",af="v24.3.0",ef="claude-cli/2.1.141 (external, sdk-cli)",f0=["explicit","automatic","hybrid"],o="explicit",l$=["github.com/anomalyco/opencode","opencode.ai/docs"],k$=[{match:"if OpenCode honestly",replacement:"if the assistant honestly"},{match:"Here is some useful information about the environment you are running in:",replacement:"Environment context you are running in:"}];function _0(f){let _="";for(let $ of f)_+=String.fromCharCode($);return btoa(_).replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}async function $0(){let f=new Uint8Array(64);crypto.getRandomValues(f);let _=_0(f),$=await crypto.subtle.digest("SHA-256",new TextEncoder().encode(_));return{verifier:_,challenge:_0(new Uint8Array($)),method:"S256"}}function M1(f){if(!f)return;let _=Number(f);if(Number.isFinite(_)&&_>0)return Math.ceil(_);let $=Date.parse(f);if(Number.isFinite($)){let m=Math.ceil(($-Date.now())/1000);return m>0?m:void 0}return}class q extends Error{status;body;retryAfter;constructor(f,_,$){super(`Claude OAuth refresh failed: ${f} — ${_}`);this.status=f,this.body=_,this.name="ClaudeOAuthRefreshError",this.retryAfter=M1($??void 0)}}function U1(f){if(!(f instanceof Error))return!1;let _=f.code;return f.message.includes("fetch failed")||_==="ECONNRESET"||_==="ECONNREFUSED"||_==="ETIMEDOUT"||_==="UND_ERR_CONNECT_TIMEOUT"}async function m0(f){let _=f.fetchImpl??fetch,$=f.maxRetries??2,m=f.baseDelayMs??500;for(let D=0;D<=$;D++)try{if(D>0){let H=m*2**(D-1);await new Promise((U)=>setTimeout(U,H))}let E=await _(Ff,{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json","User-Agent":"axios/1.13.6"},body:JSON.stringify({grant_type:"refresh_token",refresh_token:f.refreshToken,client_id:r})});if(!E.ok){if(E.status>=500&&D<$){await E.body?.cancel().catch(()=>{});continue}let H=await E.text().catch(()=>"");throw new q(E.status,H,E.headers.get("retry-after"))}let C=await E.json(),b=f.now?.()??Date.now();return{access:C.access_token,refresh:C.refresh_token??f.refreshToken,expires:b+C.expires_in*1000,expiresIn:C.expires_in}}catch(E){if(E instanceof q)throw E;if(D<$&&U1(E))continue;throw E}throw Error("Token refresh exhausted all retries")}function K1(){return crypto.randomUUID().replace(/-/g,"")}function N1(f){let _=f.trim();try{let C=new URL(_),b=C.searchParams.get("code"),H=C.searchParams.get("state");if(b&&H)return{code:b,state:H}}catch{}let $=_.split("#");if($.length===2&&$[0]&&$[1])return{code:$[0],state:$[1]};let m=new URLSearchParams(_),D=m.get("code"),E=m.get("state");if(D&&E)return{code:D,state:E};return null}async function j1(f,_,$){let m=await fetch(Ff,{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json, text/plain, */*","User-Agent":"axios/1.13.6"},body:JSON.stringify({code:f.code,state:f.state,grant_type:"authorization_code",client_id:r,redirect_uri:$,code_verifier:_})});if(!m.ok)return{type:"failed"};let D=await m.json();return{type:"success",refresh:D.refresh_token,access:D.access_token,expires:Date.now()+D.expires_in*1000}}async function d$(f){let _=await $0(),$=K1(),m=new URL(cf[f],import.meta.url);return m.searchParams.set("code","true"),m.searchParams.set("client_id",r),m.searchParams.set("response_type","code"),m.searchParams.set("redirect_uri",Sf),m.searchParams.set("scope",tf.join(" ")),m.searchParams.set("code_challenge",_.challenge),m.searchParams.set("code_challenge_method","S256"),m.searchParams.set("state",$),{url:m.toString(),redirectUri:Sf,state:$,verifier:_.verifier}}async function n$(f,_,$,m){let D=N1(f);if(!D)return{type:"failed"};if(m&&D.state!==m)return{type:"failed"};return j1(D,_,$)}import*as D0 from"node:fs";import*as E0 from"node:os";import*as C0 from"node:path";var S1=C0.join(E0.tmpdir(),"opencode-anthropic-auth.log"),b0=!1,F1=500,G1=50,p=[],l=null;function Jf(){if(l)clearTimeout(l),l=null;if(p.length===0)return;let f=p.join("");p=[];try{D0.appendFileSync(S1,f)}catch{}}function J1(){if(l)return;l=setTimeout(()=>{l=null,Jf()},F1)}function O1(f){if(f===void 0)return"";if(f instanceof Error)return` ${f.message}${f.stack?`
3
+ ${f.stack}`:""}`;return` ${JSON.stringify(f)}`}function Q(f,_){if(b0)return;try{if(p.push(`[${new Date().toISOString()}] ${f}${O1(_)}
4
+ `),p.length>=G1)Jf();else J1()}catch{}}function j(f,_){Q(`[relay] ${f}`,_)}if(!b0)process.on("exit",Jf);import{createHash as F0,randomUUID as Bf}from"node:crypto";import{mkdir as z1,readFile as a,rename as W1,rm as H0,stat as B1,writeFile as Wf}from"node:fs/promises";import{homedir as V1}from"node:os";import{dirname as X1,join as e}from"node:path";var Z1=globalThis.setTimeout.bind(globalThis),Y1=globalThis.clearTimeout.bind(globalThis),L1="anthropic-auth.json",A1="https://api.anthropic.com/api/oauth/usage",Q1=[401,403,429],G0=240,h1=G0;var x1=300000,I1=3600000,q1=86400000,P1=60000,T1=900000,R1=300000,w1=5,M0={five_hour:0,seven_day:0},i1=!0,l1=60000,k1=60000,y1=600000,p1=1e4,u1=100;function v1(){if(process.env.OPENCODE_CONFIG_DIR?.trim())return process.env.OPENCODE_CONFIG_DIR.trim();return e(process.env.XDG_CONFIG_HOME||e(V1(),".config"),"opencode")}function W(){return process.env.OPENCODE_ANTHROPIC_AUTH_FILE?.trim()||e(v1(),L1)}function O(f){return f!=null&&typeof f==="object"&&!Array.isArray(f)}function d1(f){if(!O(f))return null;if(f.type!=="oauth")return null;if(typeof f.refresh!=="string"||!f.refresh.trim())return null;return{id:typeof f.id==="string"&&f.id.trim()?f.id.trim():Bf(),label:typeof f.label==="string"?f.label:void 0,type:"oauth",access:typeof f.access==="string"?f.access:void 0,refresh:f.refresh,expires:typeof f.expires==="number"?f.expires:void 0,enabled:typeof f.enabled==="boolean"?f.enabled:void 0,addedAt:typeof f.addedAt==="number"?f.addedAt:void 0,lastUsed:typeof f.lastUsed==="number"?f.lastUsed:void 0,lastRefreshedAt:typeof f.lastRefreshedAt==="number"?f.lastRefreshedAt:void 0,lastRefreshError:U0(f.lastRefreshError),lastQuotaRefreshError:U0(f.lastQuotaRefreshError),quota:n1(f.quota)}}function U0(f){if(!O(f))return;if(typeof f.message!=="string")return;let _=Number(f.checkedAt);if(!Number.isFinite(_))return;let $=Number(f.nextRetryAt),m=Number(f.retryCount);return{message:f.message,checkedAt:_,nextRetryAt:Number.isFinite($)?$:void 0,retryCount:Number.isFinite(m)?m:void 0,tokenHash:typeof f.tokenHash==="string"?f.tokenHash:void 0}}function n1(f){if(!O(f))return;let _={};for(let $ of["five_hour","seven_day"]){let m=f[$];if(!O(m))continue;let D=Number(m.usedPercent),E=Number(m.remainingPercent),C=Number(m.checkedAt);if(!Number.isFinite(D)||!Number.isFinite(E)||!Number.isFinite(C))continue;_[$]={usedPercent:D,remainingPercent:E,checkedAt:C,resetsAt:typeof m.resetsAt==="string"?m.resetsAt:void 0}}return Object.keys(_).length?_:void 0}function g1(f){if(!O(f)||!Array.isArray(f.accounts))return null;return{version:1,main:{type:"opencode",provider:"anthropic"},routing:O(f.routing)?f.routing:void 0,fallbackOn:Array.isArray(f.fallbackOn)?f.fallbackOn.filter((_)=>Number.isInteger(_)):void 0,refresh:O(f.refresh)?f.refresh:void 0,quota:O(f.quota)?f.quota:void 0,claudeCache:O(f.claudeCache)?f.claudeCache:void 0,dump:O(f.dump)?f.dump:void 0,claudeFast:O(f.claudeFast)?f.claudeFast:void 0,cacheKeep:O(f.cacheKeep)?f.cacheKeep:void 0,relay:O(f.relay)?f.relay:void 0,killswitch:O(f.killswitch)?f.killswitch:void 0,accounts:f.accounts.map(d1).filter((_)=>_!=null)}}async function L(f=W()){try{let _=await a(f,"utf8");return g1(JSON.parse(_))}catch(_){if(_.code==="ENOENT")return null;return null}}async function c1(f){try{let _=await a(f,"utf8"),$=JSON.parse(_);return O($)?$:{}}catch{return{}}}function t1(f){return Object.fromEntries(Object.entries(f).filter(([,_])=>_!==void 0))}async function A(f,_=W()){await z1(X1(_),{recursive:!0});let m={...await c1(_),...t1(f)},D=`${_}.${Bf()}.tmp`;await Wf(D,`${JSON.stringify(m,null,2)}
5
+ `,{encoding:"utf8",mode:384}),await W1(D,_)}async function Vf(f){let $=`${f.path??W()}.${f.name}.lock`,m=e($,"owner.json"),D=Bf(),E=f.now??Date.now,C=null,b=!1;async function H(){try{return JSON.parse(await a($,"utf8"))}catch(F){if(F.code!=="EISDIR")throw F;return JSON.parse(await a(m,"utf8"))}}async function U(){await Wf($,`${JSON.stringify({ownerId:D,expiresAt:E()+f.ttlMs})}
6
+ `,{encoding:"utf8",mode:384})}async function K(){try{return await Wf($,`${JSON.stringify({ownerId:D,expiresAt:E()+f.ttlMs})}
7
+ `,{encoding:"utf8",mode:384,flag:"wx"}),!0}catch(F){let G=F.code;if(G==="EEXIST"||G==="EISDIR")return!1;throw F}}function S(){if(!f.renew||b)return;let F=f.renewIntervalMs??Math.max(1000,Math.floor(f.ttlMs/3));if(C=Z1(()=>{(async()=>{try{let G=await H(),N=E();if(b||G?.ownerId!==D||Number(G?.expiresAt)<=N)return;await U(),S()}catch{}})()},F),"unref"in C)C.unref()}if(!await K()){try{let F=await H();if(Number(F?.expiresAt)>E())return null}catch{try{if((await B1($)).mtimeMs+f.ttlMs>Date.now())return null}catch{return null}}if(await H0($,{recursive:!0,force:!0}).catch(()=>{}),!await K())return null}return S(),{release:async()=>{if(b=!0,C)Y1(C),C=null;try{if((await H())?.ownerId!==D)return}catch{return}await H0($,{recursive:!0,force:!0}).catch(()=>{})}}}function _m(f){return f?.claudeCache?.enabled===!0}function s1(f){return typeof f==="string"&&f0.includes(f)?f:o}function r1(f){return s1(f?.claudeCache?.mode)}async function $m(f,_,$=W()){let m=await L($)??{version:1,main:{type:"opencode",provider:"anthropic"},accounts:[]};return m.claudeCache={...m.claudeCache??{},enabled:f,mode:_??r1(m)},await A(m,$),m}async function mm(f,_=W()){let $=await L(_)??{version:1,main:{type:"opencode",provider:"anthropic"},accounts:[]};return $.claudeCache={...$.claudeCache??{},enabled:$.claudeCache?.enabled===!0,mode:f},await A($,_),$}function Dm(f){return f?.dump?.enabled===!0}async function Em(f,_=W()){let $=await L(_)??{version:1,main:{type:"opencode",provider:"anthropic"},accounts:[]};return $.dump={...$.dump??{},enabled:f},await A($,_),$}function Cm(f){return f?.claudeFast?.enabled===!0}async function bm(f,_=W()){let $=await L(_)??{version:1,main:{type:"opencode",provider:"anthropic"},accounts:[]};return $.claudeFast={...$.claudeFast??{},enabled:f},await A($,_),$}async function Hm(f,_,$=W()){let m=await L($)??{version:1,main:{type:"opencode",provider:"anthropic"},accounts:[]};return m.cacheKeep={enabled:!0,startHour:f,endHour:_},await A(m,$),m}async function Mm(f,_=W()){let $=await L(_)??{version:1,main:{type:"opencode",provider:"anthropic"},accounts:[]};return $.cacheKeep={...$.cacheKeep??{},enabled:f},await A($,_),$}function o1(f){return f?.fallbackOn?.length?f.fallbackOn:Q1}function Um(f,_){return o1(_).includes(f)}function J0(f){let _=f?.quota?.minimumRemaining||{};return{five_hour:_.five_hour??_["5h"]??M0.five_hour,seven_day:_.seven_day??_["1w"]??M0.seven_day}}function v(f){return f?.quota?.enabled!==!1}function a1(f){return f?.refresh?.enabled!==!1}function e1(f){return Math.floor(Math.random()*Math.max(0,f))}function f_(f){let _=f?.refresh?.refreshBeforeExpiryMinutes??h1;return Math.max(G0,_)*60000}function O0(f){return F0("sha256").update(f).digest("hex")}function __(f){if(f instanceof q)return f.status===429||f.status>=500;if(!(f instanceof Error))return!1;return f.message.includes("fetch failed")||"code"in f&&(f.code==="ECONNRESET"||f.code==="ECONNREFUSED"||f.code==="ETIMEDOUT"||f.code==="UND_ERR_CONNECT_TIMEOUT")}function $_(f){let _=O0(f.refreshToken),m=(f.previous?.tokenHash===_?f.previous.retryCount??0:0)+1,D;if(f.error instanceof q&&f.error.retryAfter)D=f.error.retryAfter*1000;else if(__(f.error))D=Math.min(I1,x1*2**Math.min(m-1,6));else D=q1;return{message:d(f.error),checkedAt:f.now,nextRetryAt:f.now+D,retryCount:m,tokenHash:_}}function u(f,_,$){if(!f?.nextRetryAt||f.nextRetryAt<=$)return!1;if(!_)return!0;return f.tokenHash===O0(_)}function Of(f,_){return`Claude OAuth refresh is backed off for ${Math.max(1,Math.ceil(((f.nextRetryAt??_)-_)/1000))}s after: ${f.message}`}function ff(f){let $=(f.previous?.retryCount??0)+1,m=V0(f.error)?Math.min(T1,P1*2**Math.min($-1,6)):R1;return{message:d(f.error),checkedAt:f.now,nextRetryAt:f.now+m,retryCount:$}}function k(f,_){if(!f?.nextRetryAt||f.nextRetryAt<=_)return!1;return!0}function Km(f,_){return`Quota API backed off for ${Math.max(1,Math.ceil(((f.nextRetryAt??_)-_)/1000))}s after: ${f.message}`}function Z(f){let _=f?.quota?.checkIntervalMinutes??w1;return Math.max(1,_)*60000}function z0(f){if(!f?.quota?.mainQuota||!f.quota.mainQuotaCheckedAt)return null;return{quota:f.quota.mainQuota,checkedAt:f.quota.mainQuotaCheckedAt,tokenFingerprint:f.quota.mainQuotaToken}}function W0(f){let _=f?.quota?.refreshEveryNRequests;return typeof _==="number"&&Number.isFinite(_)&&_>0?Math.floor(_):0}function Xf(f){return f?.quota?.failClosedOnUnknownQuota??i1}function B0(f,_){if(!v(_))return!0;let $=J0(_);for(let m of["five_hour","seven_day"]){let D=f?.[m];if(!D)return!Xf(_);if(D.remainingPercent<$[m])return!1}return!0}var Y={five_hour:5,seven_day:10};function K0(f){return{five_hour:f?.five_hour??f?.["5h"]??Y.five_hour,seven_day:f?.seven_day??f?.["1w"]??Y.seven_day}}function m_(f){return f?.killswitch?.enabled===!0}function D_(f,_){if(!f?.killswitch)return Y;if(_&&f.killswitch.accounts?.[_])return K0(f.killswitch.accounts[_]);return K0(f.killswitch.main)}function Nm(f,_,$){if(!m_(_))return!0;let m=D_(_,$),D=!1;for(let E of["five_hour","seven_day"]){let C=f?.[E];if(!C){D=!0;continue}if(C.remainingPercent<m[E])return!1}if(D)return!Xf(_);return!0}function jm(f,_,$){let m=[],D=[f,..._.map((E)=>E.quota)];for(let E of D)for(let C of["five_hour","seven_day"]){let b=E?.[C]?.resetsAt;if(!b)continue;let H=Date.parse(b);if(Number.isFinite(H)&&H>$)m.push(H)}if(!m.length)return 300;return Math.max(1,Math.ceil((Math.min(...m)-$)/1000))+60}function Sm(f){return f?.killswitch??{enabled:!1}}async function Fm(f,_=W()){let $=await L(_)??{version:1,main:{type:"opencode",provider:"anthropic"},accounts:[]};return $.killswitch=f,await A($,_),$}function Zf(f,_,$){if(!v(_))return $+Z(_);let m=J0(_),D=[];for(let E of["five_hour","seven_day"]){let C=f?.[E];if(!C)return $+Z(_);if(C.remainingPercent>=m[E])continue;let b=C.resetsAt?Date.parse(C.resetsAt):Number.NaN;if(!Number.isFinite(b)||b<=$)return $+Z(_);D.push(b)}if(!D.length)return $+Z(_);return Math.min(...D)+60000}function P(f,_,$){return!f.access||!f.expires||f.expires-$<=f_(_)}function zf(f,_,$){if(!v(_))return!1;let m=Z(_);return["five_hour","seven_day"].some((D)=>{let E=f.quota?.[D];return!E||$-E.checkedAt>=m})}function E_(f,_){if(!f)return!1;if(!f.resetsAt)return!0;let $=Date.parse(f.resetsAt);return!Number.isFinite($)||$>_}function C_(f,_){return["five_hour","seven_day"].every(($)=>E_(f?.[$],_))}function V0(f){let _=d(f);if(/Claude quota check failed: (429|5\d\d)\b/.test(_))return!0;if(!(f instanceof Error))return!1;let $=f.code;return _.includes("fetch failed")||$==="ECONNRESET"||$==="ECONNREFUSED"||$==="ETIMEDOUT"||$==="UND_ERR_CONNECT_TIMEOUT"}function b_(f,_,$,m){return V0($)&&B0(f.quota,_)&&C_(f.quota,m)}function N0(f){if(!Number.isFinite(f))return 0;if(f<0)return 0;if(f>100)return 100;return f}function j0(f,_){if(typeof f?.utilization!=="number")return;let $=N0(f.utilization);return{usedPercent:$,remainingPercent:N0(100-$),resetsAt:f.resets_at,checkedAt:_}}async function _f(f){let $=await(f.fetchImpl??fetch)(A1,{method:"GET",headers:{Authorization:`Bearer ${f.accessToken}`,Accept:"application/json","Content-Type":"application/json","anthropic-beta":"oauth-2025-04-20","User-Agent":`claude-code/${x}`}});if(!$.ok){let E=await $.text().catch(()=>"");throw Error(`Claude quota check failed: ${$.status} — ${E}`)}let m=f.now?.()??Date.now(),D=await $.json();return{five_hour:j0(D.five_hour,m),seven_day:j0(D.seven_day,m)}}function X(f,_){let $=f.accounts.findIndex((m)=>m.id===_.id);if($>=0)f.accounts[$]=_}function d(f){return f instanceof Error?f.message:String(f)}function X0(f,_,$){f.lastRefreshError=$_({error:_,now:$,refreshToken:f.refresh,previous:f.lastRefreshError})}function S0(f,_,$){if(f.lastQuotaRefreshError=ff({error:_,now:$,previous:f.lastQuotaRefreshError}),_ instanceof q)X0(f,_,$)}function H_(f){return`fallback-oauth-refresh-${F0("sha256").update(f).digest("hex").slice(0,16)}`}class M_{now;fetchImpl;configPath;refreshPromises=new Map;refreshTimer=null;quotaTimer=null;quotaManager;onFallbackStorageChanged;constructor(f={}){this.now=f.now??Date.now,this.fetchImpl=f.fetchImpl??fetch,this.configPath=f.configPath??W(),this.quotaManager=f.quotaManager??null,this.onFallbackStorageChanged=f.onFallbackStorageChanged}seedFallbackQuota(f,_){if(!this.quotaManager)return;if(this.quotaManager.getFallback(f.id,f.access))return;if(!f.quota)return;let $=Math.max(f.quota.five_hour?.checkedAt??0,f.quota.seven_day?.checkedAt??0);if($<=0)return;let m=Z(_);this.quotaManager.setFallback(f.id,{quota:f.quota,refreshAfter:$+m,checkedAt:$},f.access)}async load(){return L(this.configPath)}async save(f){await A(f,this.configPath)}startBackgroundRefresh(){let f=async()=>{await this.refreshDueAccounts(),await this.refreshQuotaForDueAccounts()};if(f().catch(()=>{}),!this.refreshTimer){if(this.refreshTimer=setInterval(()=>{f().catch(()=>{})},l1+e1(k1)),"unref"in this.refreshTimer)this.refreshTimer.unref()}}stopBackgroundRefresh(){if(this.refreshTimer)clearInterval(this.refreshTimer);if(this.quotaTimer)clearInterval(this.quotaTimer);this.refreshTimer=null,this.quotaTimer=null}async getUsableFallbackAccounts(f){let _=f!==void 0?f:await this.load();if(!_)return[];let $=[],m=!1;for(let D of _.accounts){if(D.enabled===!1)continue;try{let E=D;if(P(E,_,this.now())){let b=E.lastRefreshError;if(b&&u(b,E.refresh,this.now()))throw Error(Of(b,this.now()));E=await this.refreshAccount(E,_),m=!0}if(this.seedFallbackQuota(E,_),(this.quotaManager?this.quotaManager.isFallbackStale(E.id,E.access):zf(E,_,this.now()))&&!k(E.lastQuotaRefreshError,this.now()))E=await this.refreshAccountQuota(E,_),m=!0;if(this.accountPassesQuotaPolicy(this.quotaPolicyAccount(E),_))$.push(E)}catch(E){if(b_(D,_,E,this.now()))Q("[refresh] fallback quota using cached quota after refresh error",{accountId:D.id,error:d(E)}),$.push(D);else if(!Xf(_))$.push(D)}}if(m)await this.save(_);return $}async markUsed(f){let _=await this.load();if(!_)return;let $=_.accounts.find((m)=>m.id===f.id);if(!$)return;$.lastUsed=this.now(),await this.save(_)}accountPassesQuotaPolicy(f,_){return B0(f.quota,_)}quotaPolicyAccount(f){if(!this.quotaManager)return f;let _=this.quotaManager.getFallback(f.id,f.access)?.quota;return _?{...f,quota:_}:f}async refreshDueAccounts(){let f=await this.load();if(!f||!a1(f))return;let _=!1;for(let $ of f.accounts){if($.enabled===!1)continue;if(!P($,f,this.now()))continue;if(u($.lastRefreshError,$.refresh,this.now()))continue;try{Q("[refresh] fallback oauth background due",{accountId:$.id,expiresInMs:$.expires?$.expires-this.now():void 0}),await this.refreshAccount($,f),_=!0}catch(m){Q("[refresh] fallback oauth background failed",{accountId:$.id,error:m instanceof Error?m.message:String(m)}),X0($,m,this.now()),X(f,$),_=!0}}if(_)await this.save(f)}async refreshQuotaForDueAccounts(){let f=await this.load();if(!f||!v(f))return;let _=!1;for(let $ of f.accounts){if($.enabled===!1)continue;let m=$;try{if(P(m,f,this.now())){if(u(m.lastRefreshError,m.refresh,this.now()))continue;m=await this.refreshAccount(m,f),_=!0}if(k(m.lastQuotaRefreshError,this.now()))continue;if(this.seedFallbackQuota(m,f),!(this.quotaManager?this.quotaManager.isFallbackStale(m.id,m.access):zf(m,f,this.now())))continue;await this.refreshAccountQuota(m,f),_=!0}catch(D){S0($,D,this.now()),X(f,$),_=!0}}if(_)await this.save(f),this.onFallbackStorageChanged?.()}async refreshQuotaForAllAccounts(f={}){let _=await this.load(),$=[];if(!_||!v(_))return{storage:_,errors:$};let m=f.force??!1,D=!1;for(let E of _.accounts){if(E.enabled===!1)continue;let C=E;try{if(P(C,_,this.now())){let b=C.lastRefreshError;if(b&&u(b,C.refresh,this.now()))throw Error(Of(b,this.now()));C=await this.refreshAccount(C,_),D=!0}if(!m&&!zf(C,_,this.now())){if(C.lastQuotaRefreshError)C.lastQuotaRefreshError=void 0,X(_,C),D=!0;continue}await this.refreshAccountQuota(C,_),D=!0}catch(b){S0(E,b,this.now()),X(_,E),D=!0,$.push({accountId:E.id,message:d(b)})}}if(D)await this.save(_);return{storage:_,errors:$}}async refreshAccount(f,_,$={}){let m=this.refreshPromises.get(f.id);if(m){let C=await m;return X(_,C),C}let D=this.refreshAccountNow(f,_,$).finally(()=>{this.refreshPromises.delete(f.id)});this.refreshPromises.set(f.id,D);let E=await D;return X(_,E),E}async waitForConcurrentFallbackRefresh(f,_,$,m){let D=Date.now()+p1;while(Date.now()<D){await new Promise((U)=>setTimeout(U,u1));let E=await this.load(),C=E?.accounts.find((U)=>U.id===f.id);if(!C)continue;if((C.access!==$.access||C.refresh!==$.refresh||(C.expires??0)>($.expires??0)+60000)&&(m.force||!P(C,E,this.now())))return X(_,C),Q("[refresh] fallback oauth joined concurrent refresh",{accountId:C.id,expiresInMs:C.expires?C.expires-this.now():void 0}),C;let H=C.lastRefreshError;if(H&&u(H,C.refresh,this.now()))throw X(_,C),Error(Of(H,this.now()))}return null}async refreshAccountNow(f,_,$){let m=await this.load(),D=m?.accounts.find((b)=>b.id===f.id);if(D&&!$.force&&!P(D,m,this.now()))return X(_,D),D;let E=D??f,C=await Vf({name:H_(E.id),ttlMs:y1,path:this.configPath,now:this.now,renew:!0});if(!C){Q("[refresh] fallback oauth refresh skipped file lock",{accountId:E.id});let b=await this.waitForConcurrentFallbackRefresh(f,_,E,$);if(b)return b;throw Error("Fallback OAuth refresh is already in progress")}try{if(m=await this.load(),D=m?.accounts.find((U)=>U.id===f.id),D&&!$.force&&!P(D,m,this.now()))return X(_,D),D;E=D??E;let b=E.refresh;Q("[refresh] fallback oauth refresh request start",{accountId:E.id,force:$.force===!0,expiresInMs:E.expires?E.expires-this.now():void 0});let H=await m0({refreshToken:b,fetchImpl:this.fetchImpl,now:this.now});return E.access=H.access,E.refresh=H.refresh,E.expires=H.expires,E.lastRefreshedAt=H.expires-H.expiresIn*1000,E.lastRefreshError=void 0,X(_,E),await this.save(_),Q("[refresh] fallback oauth refresh succeeded",{accountId:E.id,expiresInMs:E.expires?E.expires-this.now():void 0}),E}finally{await C.release()}}async refreshAccountQuota(f,_){let $=f;if(!$.access)throw Error(`Fallback account ${f.id} has no access token`);let m=(D)=>this.quotaManager?this.quotaManager.refreshFallback($.id,D):_f({accessToken:D,fetchImpl:this.fetchImpl,now:this.now});try{$.quota=await m($.access)}catch(D){if(!(D instanceof Error?D.message:String(D)).includes("Claude quota check failed: 401"))throw D;if($=await this.refreshAccount(f,_,{force:!0}),!$.access)throw D;$.quota=await m($.access)}if($.lastQuotaRefreshError=void 0,X(_,$),this.quotaManager&&$.quota){let D=this.now();this.quotaManager.setFallback($.id,{quota:$.quota,refreshAfter:D+Z(_),checkedAt:D},$.access)}return $}}var Om="claude-cache",Z0="## Claude Cache Status",U_="## Claude Cache Enabled",K_="## Claude Cache Disabled",N_="## Claude Cache Usage",j_="Usage: `/claude-cache`, `/claude-cache on`, `/claude-cache off`, or `/claude-cache mode explicit|automatic|hybrid`.",$f=!1,mf=o;function zm(){return $f}function Wm(){return mf}function Bm(f){$f=f.enabled,mf=f.mode}function S_(f){let _=f.trim().split(/\s+/).filter(Boolean);if(_.length===0)return{type:"status"};if(_.length===1&&_[0]==="on")return{type:"enable"};if(_.length===1&&_[0]==="off")return{type:"disable"};if(_.length===2&&_[0]==="mode"&&(_[1]==="explicit"||_[1]==="automatic"||_[1]==="hybrid"))return{type:"mode",mode:_[1]};return{type:"usage"}}function n(f){let _=f?.enabled??$f,$=f?.mode??mf;return[Z0,"",`- Enabled: ${_?"enabled":"disabled"}`,`- Mode: ${$}`,"- Persisted: ~/.config/opencode/anthropic-auth.json","- Scope: main sessions only; subagent sessions keep default ephemeral cache behavior","- Modes: explicit = existing OpenCode breakpoints; automatic = top-level cache_control only; hybrid = system + messages[0] + top-level cache_control","- TTL: 1h when enabled for main sessions; default ephemeral cache behavior otherwise"].join(`
8
+ `)}function Vm(f){let _=S_(f.argumentsText),$=f.enabled??$f,m=f.mode??mf;if(_.type==="status")return n({enabled:$,mode:m});if(_.type==="enable")return[U_,"",n({enabled:!0,mode:m})].join(`
9
+ `);if(_.type==="disable")return[K_,"",n({enabled:!1,mode:m})].join(`
10
+ `);if(_.type==="mode")return[Z0,"",`Mode updated to \`${_.mode}\`.`,"",n({enabled:$,mode:_.mode})].join(`
11
+ `);return[N_,"",j_,"",n({enabled:$,mode:m})].join(`
12
+ `)}import{randomBytes as F_,randomUUID as L0}from"node:crypto";var G_=1000,g=new Map;function Lf(f,_,$){if(!f.has(_)&&f.size>=G_){let m=f.keys().next().value;if(m!==void 0)f.delete(m)}f.set(_,$)}function A0(f){let _=f||"anonymous",$=g.get(_);if($)return $;let m={deviceId:F_(32).toString("hex"),sessionId:L0()};return Lf(g,_,m),m}var Yf=new Map;async function J_(f,_){if(!f.startsWith("sk-ant-oat"))return null;let $=new AbortController,m=setTimeout(()=>$.abort(),5000);try{let D=new URL("https://api.anthropic.com/api/claude_cli/bootstrap");if(D.searchParams.set("entrypoint",rf),_)D.searchParams.set("model",_);let E=await fetch(D,{method:"GET",headers:{accept:"application/json, text/plain, */*",authorization:`Bearer ${f}`,"content-type":"application/json","anthropic-beta":"oauth-2025-04-20","user-agent":`claude-code/${x}`},signal:$.signal});if(!E.ok)return null;let b=(await E.json().catch(()=>null))?.oauth_account?.account_uuid;return typeof b==="string"&&b?b:null}catch{return null}finally{clearTimeout(m)}}async function Lm(f,_){let $=A0(f);if(!f.startsWith("sk-ant-oat"))return $;let m=Yf.get(f);if(!m)m=J_(f,_),Yf.set(f,m);let D=await m;if(!D)return Yf.delete(f),$;let E=`account:${D}`,C=g.get(E);if(C)return Lf(g,f,C),C;return $.accountUuid=D,Lf(g,E,$),$}function T(f){return f!=null&&typeof f==="object"&&!Array.isArray(f)}function O_(f){if(!f.accountUuid)return null;return JSON.stringify({device_id:f.deviceId,account_uuid:f.accountUuid,session_id:f.sessionId})}function Am(f,_){let $=O_(_);if(!$){if(T(f.metadata))delete f.metadata.user_id;return!1}if(!T(f.metadata))f.metadata={};let m=f.metadata;if(T(m))m.user_id=$;return!0}var z_=["claude-code-20250219","oauth-2025-04-20","interleaved-thinking-2025-05-14","context-management-2025-06-27","prompt-caching-scope-2026-01-05","advisor-tool-2026-03-01","advanced-tool-use-2025-11-20","context-1m-2025-08-07","effort-2025-11-24","extended-cache-ttl-2025-04-11","cache-diagnosis-2026-04-07"],W_=["oauth-2025-04-20","interleaved-thinking-2025-05-14","context-management-2025-06-27","prompt-caching-scope-2026-01-05","advisor-tool-2026-03-01","structured-outputs-2025-12-15","cache-diagnosis-2026-04-07"],Y0=["oauth-2025-04-20","interleaved-thinking-2025-05-14","context-management-2025-06-27","prompt-caching-scope-2026-01-05","advisor-tool-2026-03-01","cache-diagnosis-2026-04-07"];function B_(f){return f.output_config?.format?.type==="json_schema"}function V_(f){return Array.isArray(f.tools)&&f.tools.length>0&&Array.isArray(f.system)&&T(f.thinking)&&T(f.context_management)&&T(f.output_config)&&T(f.diagnostics)}function X_(f,_=[]){let $=f?V_(f)?[...z_]:B_(f)?[...W_]:[...Y0]:[...Y0];if(f?.speed==="fast")$.push(sf);for(let m of _){let D=m.trim();if(D)$.push(D)}return[...new Set($)].join(",")}function Z_(){switch(process.platform){case"darwin":return"MacOS";case"win32":return"Windows";case"linux":return"Linux";case"freebsd":return"FreeBSD";default:return"Unknown"}}function Y_(){switch(process.arch){case"arm64":return"arm64";case"x64":return"x64";case"ia32":return"x32";default:return process.arch}}function Qm(f,_,$={}){let m=$.identity??A0(_),E=[...(f.get("anthropic-beta")??"").split(",").map((C)=>C.trim()).filter(Boolean),...$.extraBetas??[]];return f.set("accept","application/json"),f.set("authorization",`Bearer ${_}`),f.set("content-type","application/json"),f.set("user-agent",ef),f.set("anthropic-beta",X_($.body,E)),f.set("anthropic-dangerous-direct-browser-access","true"),f.set("anthropic-version","2023-06-01"),f.set("x-app","cli"),f.set("x-client-request-id",L0()),f.set("x-claude-code-session-id",m.sessionId),f.set("x-stainless-arch",Y_()),f.set("x-stainless-lang","js"),f.set("x-stainless-os",Z_()),f.set("x-stainless-package-version",of),f.set("x-stainless-retry-count","0"),f.set("x-stainless-runtime","node"),f.set("x-stainless-runtime-version",af),f.set("x-stainless-timeout","600"),f.delete("x-api-key"),f}var L_=["model","messages","system","tools","tool_choice","metadata","max_tokens","temperature","thinking","context_management","output_config","diagnostics","stream","speed"];function Q0(f){let _={};for(let $ of L_)if(Object.hasOwn(f,$))_[$]=f[$];for(let[$,m]of Object.entries(f))if(!Object.hasOwn(_,$))_[$]=m;return _}import{createHash as Q_}from"node:crypto";var A_=new Uint8Array([0,97,115,109,1,0,0,0,1,48,8,96,3,127,127,127,1,127,96,3,127,127,127,0,96,2,127,127,0,96,1,127,1,127,96,3,127,127,126,1,126,96,3,126,127,127,1,126,96,2,127,126,0,96,1,127,1,126,3,11,10,0,0,2,1,3,4,5,6,1,7,5,3,1,0,1,7,85,9,3,109,101,109,2,0,5,120,120,104,51,50,0,0,6,105,110,105,116,51,50,0,2,8,117,112,100,97,116,101,51,50,0,3,8,100,105,103,101,115,116,51,50,0,4,5,120,120,104,54,52,0,5,6,105,110,105,116,54,52,0,7,8,117,112,100,97,116,101,54,52,0,8,8,100,105,103,101,115,116,54,52,0,9,10,251,22,10,242,1,1,4,127,32,0,32,1,106,33,3,32,1,65,16,79,4,127,32,3,65,16,107,33,6,32,2,65,168,136,141,161,2,106,33,3,32,2,65,137,235,208,208,7,107,33,4,32,2,65,207,140,162,142,6,106,33,5,3,64,32,3,32,0,40,2,0,65,247,148,175,175,120,108,106,65,13,119,65,177,243,221,241,121,108,33,3,32,4,32,0,65,4,106,34,0,40,2,0,65,247,148,175,175,120,108,106,65,13,119,65,177,243,221,241,121,108,33,4,32,2,32,0,65,4,106,34,0,40,2,0,65,247,148,175,175,120,108,106,65,13,119,65,177,243,221,241,121,108,33,2,32,5,32,0,65,4,106,34,0,40,2,0,65,247,148,175,175,120,108,106,65,13,119,65,177,243,221,241,121,108,33,5,32,6,32,0,65,4,106,34,0,79,13,0,11,32,2,65,12,119,32,5,65,18,119,106,32,4,65,7,119,106,32,3,65,1,119,106,5,32,2,65,177,207,217,178,1,106,11,32,1,106,32,0,32,1,65,15,113,16,1,11,146,1,0,32,1,32,2,106,33,2,3,64,32,1,65,4,106,32,2,75,69,4,64,32,0,32,1,40,2,0,65,189,220,202,149,124,108,106,65,17,119,65,175,214,211,190,2,108,33,0,32,1,65,4,106,33,1,12,1,11,11,3,64,32,1,32,2,79,69,4,64,32,0,32,1,45,0,0,65,177,207,217,178,1,108,106,65,11,119,65,177,243,221,241,121,108,33,0,32,1,65,1,106,33,1,12,1,11,11,32,0,32,0,65,15,118,115,65,247,148,175,175,120,108,34,0,65,13,118,32,0,115,65,189,220,202,149,124,108,34,0,65,16,118,32,0,115,11,63,0,32,0,65,8,106,32,1,65,168,136,141,161,2,106,54,2,0,32,0,65,12,106,32,1,65,137,235,208,208,7,107,54,2,0,32,0,65,16,106,32,1,54,2,0,32,0,65,20,106,32,1,65,207,140,162,142,6,106,54,2,0,11,195,4,1,6,127,32,1,32,2,106,33,6,32,0,65,24,106,33,4,32,0,65,40,106,40,2,0,33,3,32,0,32,0,40,2,0,32,2,106,54,2,0,32,0,65,4,106,34,5,32,5,40,2,0,32,2,65,16,79,32,0,40,2,0,65,16,79,114,114,54,2,0,32,2,32,3,106,65,16,73,4,64,32,3,32,4,106,32,1,32,2,252,10,0,0,32,0,65,40,106,32,2,32,3,106,54,2,0,15,11,32,3,4,64,32,3,32,4,106,32,1,65,16,32,3,107,34,2,252,10,0,0,32,0,65,8,106,34,3,32,3,40,2,0,32,4,40,2,0,65,247,148,175,175,120,108,106,65,13,119,65,177,243,221,241,121,108,54,2,0,32,0,65,12,106,34,3,32,3,40,2,0,32,4,65,4,106,40,2,0,65,247,148,175,175,120,108,106,65,13,119,65,177,243,221,241,121,108,54,2,0,32,0,65,16,106,34,3,32,3,40,2,0,32,4,65,8,106,40,2,0,65,247,148,175,175,120,108,106,65,13,119,65,177,243,221,241,121,108,54,2,0,32,0,65,20,106,34,3,32,3,40,2,0,32,4,65,12,106,40,2,0,65,247,148,175,175,120,108,106,65,13,119,65,177,243,221,241,121,108,54,2,0,32,0,65,40,106,65,0,54,2,0,32,1,32,2,106,33,1,11,32,1,32,6,65,16,107,77,4,64,32,6,65,16,107,33,8,32,0,65,8,106,40,2,0,33,2,32,0,65,12,106,40,2,0,33,3,32,0,65,16,106,40,2,0,33,5,32,0,65,20,106,40,2,0,33,7,3,64,32,2,32,1,40,2,0,65,247,148,175,175,120,108,106,65,13,119,65,177,243,221,241,121,108,33,2,32,3,32,1,65,4,106,34,1,40,2,0,65,247,148,175,175,120,108,106,65,13,119,65,177,243,221,241,121,108,33,3,32,5,32,1,65,4,106,34,1,40,2,0,65,247,148,175,175,120,108,106,65,13,119,65,177,243,221,241,121,108,33,5,32,7,32,1,65,4,106,34,1,40,2,0,65,247,148,175,175,120,108,106,65,13,119,65,177,243,221,241,121,108,33,7,32,8,32,1,65,4,106,34,1,79,13,0,11,32,0,65,8,106,32,2,54,2,0,32,0,65,12,106,32,3,54,2,0,32,0,65,16,106,32,5,54,2,0,32,0,65,20,106,32,7,54,2,0,11,32,1,32,6,73,4,64,32,4,32,1,32,6,32,1,107,34,1,252,10,0,0,32,0,65,40,106,32,1,54,2,0,11,11,97,1,1,127,32,0,65,16,106,40,2,0,33,1,32,0,65,4,106,40,2,0,4,127,32,1,65,12,119,32,0,65,20,106,40,2,0,65,18,119,106,32,0,65,12,106,40,2,0,65,7,119,106,32,0,65,8,106,40,2,0,65,1,119,106,5,32,1,65,177,207,217,178,1,106,11,32,0,40,2,0,106,32,0,65,24,106,32,0,65,40,106,40,2,0,16,1,11,255,3,2,3,126,1,127,32,0,32,1,106,33,6,32,1,65,32,79,4,126,32,6,65,32,107,33,6,32,2,66,214,235,130,238,234,253,137,245,224,0,124,33,3,32,2,66,177,169,172,193,173,184,212,166,61,125,33,4,32,2,66,249,234,208,208,231,201,161,228,225,0,124,33,5,3,64,32,3,32,0,41,3,0,66,207,214,211,190,210,199,171,217,66,126,124,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,33,3,32,4,32,0,65,8,106,34,0,41,3,0,66,207,214,211,190,210,199,171,217,66,126,124,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,33,4,32,2,32,0,65,8,106,34,0,41,3,0,66,207,214,211,190,210,199,171,217,66,126,124,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,33,2,32,5,32,0,65,8,106,34,0,41,3,0,66,207,214,211,190,210,199,171,217,66,126,124,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,33,5,32,6,32,0,65,8,106,34,0,79,13,0,11,32,2,66,12,137,32,5,66,18,137,124,32,4,66,7,137,124,32,3,66,1,137,124,32,3,66,207,214,211,190,210,199,171,217,66,126,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,133,66,135,149,175,175,152,182,222,155,158,127,126,66,157,163,181,234,131,177,141,138,250,0,125,32,4,66,207,214,211,190,210,199,171,217,66,126,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,133,66,135,149,175,175,152,182,222,155,158,127,126,66,157,163,181,234,131,177,141,138,250,0,125,32,2,66,207,214,211,190,210,199,171,217,66,126,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,133,66,135,149,175,175,152,182,222,155,158,127,126,66,157,163,181,234,131,177,141,138,250,0,125,32,5,66,207,214,211,190,210,199,171,217,66,126,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,133,66,135,149,175,175,152,182,222,155,158,127,126,66,157,163,181,234,131,177,141,138,250,0,125,5,32,2,66,197,207,217,178,241,229,186,234,39,124,11,32,1,173,124,32,0,32,1,65,31,113,16,6,11,134,2,0,32,1,32,2,106,33,2,3,64,32,2,32,1,65,8,106,79,4,64,32,1,41,3,0,66,207,214,211,190,210,199,171,217,66,126,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,32,0,133,66,27,137,66,135,149,175,175,152,182,222,155,158,127,126,66,157,163,181,234,131,177,141,138,250,0,125,33,0,32,1,65,8,106,33,1,12,1,11,11,32,1,65,4,106,32,2,77,4,64,32,0,32,1,53,2,0,66,135,149,175,175,152,182,222,155,158,127,126,133,66,23,137,66,207,214,211,190,210,199,171,217,66,126,66,249,243,221,241,153,246,153,171,22,124,33,0,32,1,65,4,106,33,1,11,3,64,32,1,32,2,73,4,64,32,0,32,1,49,0,0,66,197,207,217,178,241,229,186,234,39,126,133,66,11,137,66,135,149,175,175,152,182,222,155,158,127,126,33,0,32,1,65,1,106,33,1,12,1,11,11,32,0,32,0,66,33,136,133,66,207,214,211,190,210,199,171,217,66,126,34,0,32,0,66,29,136,133,66,249,243,221,241,153,246,153,171,22,126,34,0,32,0,66,32,136,133,11,77,0,32,0,65,8,106,32,1,66,214,235,130,238,234,253,137,245,224,0,124,55,3,0,32,0,65,16,106,32,1,66,177,169,172,193,173,184,212,166,61,125,55,3,0,32,0,65,24,106,32,1,55,3,0,32,0,65,32,106,32,1,66,249,234,208,208,231,201,161,228,225,0,124,55,3,0,11,244,4,2,3,127,4,126,32,1,32,2,106,33,5,32,0,65,40,106,33,4,32,0,65,200,0,106,40,2,0,33,3,32,0,32,0,41,3,0,32,2,173,124,55,3,0,32,2,32,3,106,65,32,73,4,64,32,3,32,4,106,32,1,32,2,252,10,0,0,32,0,65,200,0,106,32,2,32,3,106,54,2,0,15,11,32,3,4,64,32,3,32,4,106,32,1,65,32,32,3,107,34,2,252,10,0,0,32,0,65,8,106,34,3,32,3,41,3,0,32,4,41,3,0,66,207,214,211,190,210,199,171,217,66,126,124,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,55,3,0,32,0,65,16,106,34,3,32,3,41,3,0,32,4,65,8,106,41,3,0,66,207,214,211,190,210,199,171,217,66,126,124,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,55,3,0,32,0,65,24,106,34,3,32,3,41,3,0,32,4,65,16,106,41,3,0,66,207,214,211,190,210,199,171,217,66,126,124,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,55,3,0,32,0,65,32,106,34,3,32,3,41,3,0,32,4,65,24,106,41,3,0,66,207,214,211,190,210,199,171,217,66,126,124,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,55,3,0,32,0,65,200,0,106,65,0,54,2,0,32,1,32,2,106,33,1,11,32,1,65,32,106,32,5,77,4,64,32,5,65,32,107,33,2,32,0,65,8,106,41,3,0,33,6,32,0,65,16,106,41,3,0,33,7,32,0,65,24,106,41,3,0,33,8,32,0,65,32,106,41,3,0,33,9,3,64,32,6,32,1,41,3,0,66,207,214,211,190,210,199,171,217,66,126,124,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,33,6,32,7,32,1,65,8,106,34,1,41,3,0,66,207,214,211,190,210,199,171,217,66,126,124,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,33,7,32,8,32,1,65,8,106,34,1,41,3,0,66,207,214,211,190,210,199,171,217,66,126,124,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,33,8,32,9,32,1,65,8,106,34,1,41,3,0,66,207,214,211,190,210,199,171,217,66,126,124,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,33,9,32,2,32,1,65,8,106,34,1,79,13,0,11,32,0,65,8,106,32,6,55,3,0,32,0,65,16,106,32,7,55,3,0,32,0,65,24,106,32,8,55,3,0,32,0,65,32,106,32,9,55,3,0,11,32,1,32,5,73,4,64,32,4,32,1,32,5,32,1,107,34,1,252,10,0,0,32,0,65,200,0,106,32,1,54,2,0,11,11,188,2,1,5,126,32,0,65,24,106,41,3,0,33,1,32,0,41,3,0,34,2,66,32,90,4,126,32,0,65,8,106,41,3,0,34,3,66,1,137,32,0,65,16,106,41,3,0,34,4,66,7,137,124,32,1,66,12,137,32,0,65,32,106,41,3,0,34,5,66,18,137,124,124,32,3,66,207,214,211,190,210,199,171,217,66,126,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,133,66,135,149,175,175,152,182,222,155,158,127,126,66,157,163,181,234,131,177,141,138,250,0,125,32,4,66,207,214,211,190,210,199,171,217,66,126,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,133,66,135,149,175,175,152,182,222,155,158,127,126,66,157,163,181,234,131,177,141,138,250,0,125,32,1,66,207,214,211,190,210,199,171,217,66,126,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,133,66,135,149,175,175,152,182,222,155,158,127,126,66,157,163,181,234,131,177,141,138,250,0,125,32,5,66,207,214,211,190,210,199,171,217,66,126,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,133,66,135,149,175,175,152,182,222,155,158,127,126,66,157,163,181,234,131,177,141,138,250,0,125,5,32,1,66,197,207,217,178,241,229,186,234,39,124,11,32,2,124,32,0,65,40,106,32,2,66,31,131,167,16,6,11]);async function h0(){return function(f){let{exports:{mem:_,xxh32:$,xxh64:m,init32:D,update32:E,digest32:C,init64:b,update64:H,digest64:U}}=f,K=new Uint8Array(_.buffer);function S(M,J){if(_.buffer.byteLength<M+J){let Nf=Math.ceil((M+J-_.buffer.byteLength)/65536);_.grow(Nf),K=new Uint8Array(_.buffer)}}function F(M,J,Nf,C1,b1,H1){S(M);let y=new Uint8Array(M);return K.set(y),Nf(0,J),y.set(K.subarray(0,M)),{update(i){let jf;return K.set(y),typeof i=="string"?(S(3*i.length,M),jf=V.encodeInto(i,K.subarray(M)).written):(S(i.byteLength,M),K.set(i,M),jf=i.byteLength),C1(0,M,jf),y.set(K.subarray(0,M)),this},digest:()=>(K.set(y),H1(b1(0)))}}function G(M){return M>>>0}let N=2n**64n-1n;function B(M){return M&N}let V=new TextEncoder,t=0,s=0n;function nf(M,J=t){return S(3*M.length,0),G($(0,V.encodeInto(M,K).written,J))}function gf(M,J=s){return S(3*M.length,0),B(m(0,V.encodeInto(M,K).written,J))}return{h32:nf,h32ToString:(M,J=t)=>nf(M,J).toString(16).padStart(8,"0"),h32Raw:(M,J=t)=>(S(M.byteLength,0),K.set(M),G($(0,M.byteLength,J))),create32:(M=t)=>F(48,M,D,E,C,G),h64:gf,h64ToString:(M,J=s)=>gf(M,J).toString(16).padStart(16,"0"),h64Raw:(M,J=s)=>(S(M.byteLength,0),K.set(M),B(m(0,M.byteLength,J))),create64:(M=s)=>F(88,M,b,H,U,B)}}((await WebAssembly.instantiate(A_)).instance)}var h_=0x6e52736ac806831en,x_="cch=00000;";var Qf=/("system":\[\{"type":"text","text":"x-anthropic-billing-header: cc_version=[^;"]+; cc_entrypoint=[^;"]+; )cch=([0-9a-f]{5});/,I_=/("system":\[\{"type":"text","text":"x-anthropic-billing-header: cc_version=[^;"]+; cc_entrypoint=[^;"]+; )cch=00000;/,x0=null,Af=null;async function q_(){if(Af)return;x0??=(async()=>{Af=(await h0()).h64Raw})(),await x0}async function P_(f){return await q_(),((Af?.(f,h_)??0n)&0xfffffn).toString(16).padStart(5,"0")}function T_(f){return f.replace(Qf,`$1${x_}`)}function I0(f){return Qf.exec(f)?.[2]??null}async function q0(f){if(!Qf.test(f))return f;let _=T_(f),$=await P_(new TextEncoder().encode(_));return _.replace(I_,`$1cch=${$};`)}function R_(f=x,_=new Date){if(f===x)return Gf;let $=_.toISOString().slice(0,10);return Q_("sha256").update(`${$}${f}`).digest("hex").slice(0,3)}function Tm(f,_=x,$,m=new Date){let D=R_(_,m);return`x-anthropic-billing-header: cc_version=${_}.${D}; cc_entrypoint=${$}; cch=00000;`}var lm="claude-cachekeep",P0=3600000,hf=300000,w_=60000,km="extended-cache-ttl-2025-04-11",i_="## Claude Cache Keep Status",l_="## Claude Cache Keep Enabled",k_="## Claude Cache Keep Disabled",y_="## Claude Cache Keep Usage",p_="Usage: `/claude-cachekeep`, `/claude-cachekeep off`, or `/claude-cachekeep HH-HH`.";function Ef(f){return String(f).padStart(2,"0")}function u_(f){let _=f.trim();if(!_)return{type:"status"};if(_==="off")return{type:"disable"};let $=/^(\d{1,2})-(\d{1,2})$/.exec(_);if(!$)return{type:"usage"};let m=Number($[1]),D=Number($[2]);if(!Number.isInteger(m)||!Number.isInteger(D)||m<0||m>23||D<0||D>23||m===D)return{type:"usage"};return{type:"window",startHour:m,endHour:D}}function If(f){let _=Number(f?.cacheKeep?.startHour),$=Number(f?.cacheKeep?.endHour);if(!Number.isInteger(_)||!Number.isInteger($)||_<0||_>23||$<0||$>23||_===$)return;return{startHour:_,endHour:$}}function w0(f){return f?.cacheKeep?.enabled===!0&&!!If(f)}function v_(f){return w0(f)&&f?.claudeCache?.enabled===!0&&f.claudeCache.mode==="hybrid"}function T0(f,_=new Date){if(!f)return!1;let $=_.getHours();if(f.startHour<f.endHour)return $>=f.startHour&&$<f.endHour;return $>=f.startHour||$<f.endHour}function R0(f=new Date){return`${f.getFullYear()}-${Ef(f.getMonth()+1)}-${Ef(f.getDate())}`}function xf(f,_=new Date){if(f&&f.startHour>f.endHour&&_.getHours()<f.endHour){let $=new Date(_);return $.setDate($.getDate()-1),R0($)}return R0(_)}function Df(f){let _=f.window?`${Ef(f.window.startHour)}-${Ef(f.window.endHour)}`:"not configured",$=[`Cache keep: ${f.enabled?"enabled":"disabled"}`,`Window: ${_}`,"Mode requirement: `/claude-cache mode hybrid` must be active."];if(typeof f.hybridActive==="boolean")$.push(`Hybrid active: ${f.hybridActive?"yes":"no"}`);if(typeof f.trackedSessions==="number")$.push(`Tracked sessions: ${f.trackedSessions}`);if(f.nextPrewarmAt)$.push(`Next prewarm: ${new Date(f.nextPrewarmAt).toLocaleString()}`);return $.join(`
13
+ `)}function ym(f){let _=u_(f.argumentsText),$={enabled:f.enabled??!1,window:f.window,trackedSessions:f.trackedSessions,nextPrewarmAt:f.nextPrewarmAt,hybridActive:f.hybridActive};if(_.type==="status")return[i_,"",Df($)].join(`
14
+ `);if(_.type==="disable")return[k_,"",Df({...$,enabled:!1})].join(`
15
+ `);if(_.type==="window")return[l_,"",Df({...$,enabled:!0,window:{startHour:_.startHour,endHour:_.endHour}})].join(`
16
+ `);return[y_,"",p_,"",Df($)].join(`
17
+ `)}function qf(f){if(!f||typeof f!=="object")return!1;if(Array.isArray(f))return f.some(qf);let _=f,$=_.cache_control;if($&&typeof $==="object"&&$.type==="ephemeral")return!0;return Object.values(_).some(qf)}async function d_(f){let _;try{_=JSON.parse(f)}catch{return{ok:!1,reason:"body is not valid JSON"}}if(!qf(_))return{ok:!1,reason:"body has no explicit cache breakpoints"};let $=structuredClone(_);if($.max_tokens=0,delete $.stream,$.thinking?.type==="enabled")delete $.thinking;if($.output_config?.format)delete $.output_config;let E=$.tool_choice;if(E?.type==="tool"||E?.type==="any")delete $.tool_choice;return{ok:!0,bodyText:await q0(JSON.stringify(Q0($)))}}class n_{options;targets=new Map;timer=null;constructor(f){this.options=f}start(){if(this.timer)return;if(this.timer=setInterval(()=>{this.tick().catch((f)=>{this.options.log?.("[cachekeep] tick failed",{error:f instanceof Error?f.message:String(f)})})},w_),"unref"in this.timer)this.timer.unref()}stop(){if(this.timer)clearInterval(this.timer);this.timer=null}stats(f,_=this.options.now?.()??Date.now()){let $=xf(f,new Date(_)),m=[...this.targets.values()].filter((E)=>E.dayKey===$),D=m.length?Math.min(...m.map((E)=>E.cacheExpiresAt-hf)):void 0;return{trackedSessions:m.length,nextPrewarmAt:D}}trackedCount(){return this.targets.size}track(f){if(!f.sessionId)return{tracked:!1,reason:"missing session id"};if(!w0(f.storage))return{tracked:!1,reason:"cachekeep disabled"};if(f.cacheMode!=="hybrid")return{tracked:!1,reason:"cache mode is not hybrid"};let _=this.options.now?.()??Date.now(),$=If(f.storage);if(!T0($,new Date(_)))return{tracked:!1,reason:"outside configured window"};let m={};return f.headers.forEach((D,E)=>{m[E]=D}),this.targets.set(f.sessionId,{id:f.sessionId,url:f.url,headers:m,bodyText:f.bodyText,cacheExpiresAt:_+P0,dayKey:xf($,new Date(_))}),this.start(),{tracked:!0}}async tick(){let f=await this.options.loadStorage(),_=If(f),$=this.options.now?.()??Date.now(),m=xf(_,new Date($));for(let[E,C]of this.targets)if(C.dayKey!==m)this.targets.delete(E);if(!this.targets.size){this.stop();return}if(!v_(f))return;if(!T0(_,new Date($)))return;let D=$+hf;for(let E of this.targets.values()){if(E.cacheExpiresAt>D)continue;await this.prewarm(E,$)}}async prewarm(f,_){let $=await d_(f.bodyText);if(!$.ok){this.options.log?.("[cachekeep] prewarm skipped",{session:f.id,reason:$.reason}),this.targets.delete(f.id);return}let m=this.options.fetchImpl??fetch,D={...f,bodyText:$.bodyText},E=this.options.prepareHeaders?await this.options.prepareHeaders(new Headers(f.headers),D):new Headers(f.headers);E.delete("content-length"),E.delete("transfer-encoding");let C=await m(f.url,{method:"POST",headers:E,body:$.bodyText});if(!C.ok){this.options.log?.("[cachekeep] prewarm failed",{session:f.id,status:C.status,body:await C.text().catch(()=>"")}),f.cacheExpiresAt=_+hf+300000;return}await C.body?.cancel().catch(()=>{}),f.cacheExpiresAt=_+P0,this.options.log?.("[cachekeep] prewarm succeeded",{session:f.id})}}import{createHash as g_}from"node:crypto";import{mkdir as c_,writeFile as Pf}from"node:fs/promises";import{tmpdir as t_}from"node:os";import{join as k0}from"node:path";var tm="claude-dump",s_="## Claude Dump Status",r_="## Claude Dump Enabled",o_="## Claude Dump Disabled",a_="## Claude Dump Usage",e_="Usage: `/claude-dump`, `/claude-dump on`, or `/claude-dump off`.",f$="OPENCODE_ANTHROPIC_AUTH_DUMP_DIR",_$=k0(t_(),"opencode-anthropic-auth-dumps"),bf=!1,i0=0;function sm(f){bf=f}function y0(){return process.env[f$]||_$}function $$(f){let _=f.trim().split(/\s+/).filter(Boolean);if(_.length===0)return{type:"status"};if(_.length===1&&_[0]==="on")return{type:"enable"};if(_.length===1&&_[0]==="off")return{type:"disable"};return{type:"usage"}}function Cf(f){let _=f?.enabled??bf;return[s_,"",`- Enabled: ${_?"enabled":"disabled"}`,`- Directory: ${y0()}`,"- Persisted: ~/.config/opencode/anthropic-auth.json","- Captures: final rewritten Anthropic body plus redacted relay payload metadata","- Warning: body dumps may contain prompt/session content; turn this off after debugging"].join(`
18
+ `)}function rm(f){let _=$$(f.argumentsText),$=f.enabled??bf;if(_.type==="status")return Cf({enabled:$});if(_.type==="enable")return[r_,"",Cf({enabled:!0})].join(`
19
+ `);if(_.type==="disable")return[o_,"",Cf({enabled:!1})].join(`
20
+ `);return[a_,"",e_,"",Cf({enabled:$})].join(`
21
+ `)}function l0(f){return f.length<=16?f:`${f.slice(0,12)}…`}function p0(f){return g_("sha256").update(f).digest("hex")}function m$(f){return I0(f)}function D$(f,_){if(f==null)return null;if(f===_)return{changed:!1,firstByte:-1,lastPreviousByte:-1,lastCurrentByte:-1,previousBytes:f.length,currentBytes:_.length};let $=0;while($<f.length&&$<_.length&&f[$]===_[$])$+=1;let m=f.length-1,D=_.length-1;while(m>=$&&D>=$&&f[m]===_[D])m-=1,D-=1;return{changed:!0,firstByte:$,lastPreviousByte:m,lastCurrentByte:D,changedPreviousBytes:m-$+1,changedCurrentBytes:D-$+1,previousBytes:f.length,currentBytes:_.length}}function E$(f){try{let _=JSON.parse(f);return _!=null&&typeof _==="object"&&!Array.isArray(_)?_:null}catch(_){return j(`dump body parse failed: ${_ instanceof Error?_.message:String(_)}`),null}}function Tf(f){return p0(JSON.stringify(f))}function C$(f){let _=E$(f);if(!_)return{parseable:!1};let $=Array.isArray(_.messages)?_.messages:[],m=Array.isArray(_.system)?_.system:[],D=$[0],E=$.slice(1);return{parseable:!0,model:typeof _.model==="string"?_.model:void 0,stream:_.stream,systemCount:m.length,messagesCount:$.length,systemHash:Tf(m),message0Hash:D===void 0?null:Tf(D),message0Bytes:D===void 0?0:JSON.stringify(D).length,messagesAfter0Hash:Tf(E),messagesAfter0Bytes:JSON.stringify(E).length,cch:m$(f)}}function Rf(f){if(Array.isArray(f))return f.map(Rf);if(f==null||typeof f!=="object")return f;let _={};for(let[$,m]of Object.entries(f)){let D=$.toLowerCase();if(D==="authorization"||D==="x-api-key"||D==="cookie"||D==="set-cookie"){_[$]="[redacted]";continue}_[$]=Rf(m)}return _}async function u0(f){if(!bf)return;i0+=1;let _=`${new Date().toISOString().replace(/[:.]/g,"-")}-${String(i0).padStart(5,"0")}-${f.transport}-p${f.protocol}-${f.mode}`,$=y0(),m=k0($,_);try{await c_($,{recursive:!0});let D={id:_,createdAt:new Date().toISOString(),session:l0(f.affinity),transport:f.transport,protocol:f.protocol,mode:f.mode,status:f.status,bodyBytes:f.bodyText.length,relayBytes:f.relayBytes,bodyHash:p0(f.bodyText),diff:D$(f.previousBodyText,f.bodyText),body:C$(f.bodyText),files:{body:`${m}.body.json`,relay:`${m}.relay.json`,metadata:`${m}.meta.json`}};await Promise.all([Pf(`${m}.body.json`,f.bodyText,"utf8"),Pf(`${m}.relay.json`,`${JSON.stringify(Rf(f.payload),null,2)}
22
+ `,"utf8"),Pf(`${m}.meta.json`,`${JSON.stringify(D,null,2)}
23
+ `,"utf8")]),j(`dumped request id=${_} session=${l0(f.affinity)} body=${m}.body.json meta=${m}.meta.json`)}catch(D){j(`dump failed: ${D instanceof Error?D.message:String(D)}`)}}var am="claude-fast";var Mf=!1;function em(){return Mf}function fD(f){Mf=f}function b$(f){let _=f.trim().split(/\s+/).filter(Boolean);if(_.length===0)return{type:"status"};if(_.length===1&&_[0]==="on")return{type:"enable"};if(_.length===1&&_[0]==="off")return{type:"disable"};return{type:"usage"}}function Hf(f){return["## Claude Fast Mode Status","",`- Enabled: ${f?.enabled??Mf?"enabled":"disabled"}`,"- Persisted: ~/.config/opencode/anthropic-auth.json","- Scope: adds Anthropic fast mode to supported Opus requests","- Supported models: claude-opus-4-6, claude-opus-4-7, and claude-opus-4-8",'- Request changes: adds `speed: "fast"` and the `fast-mode-2026-02-01` beta header',"- Note: fast and standard speeds do not share prompt-cache prefixes"].join(`
24
+ `)}function _D(f){let _=b$(f.argumentsText),$=f.enabled??Mf;if(_.type==="status")return Hf({enabled:$});if(_.type==="enable")return["## Claude Fast Mode Enabled","",Hf({enabled:!0})].join(`
25
+ `);if(_.type==="disable")return["## Claude Fast Mode Disabled","",Hf({enabled:!1})].join(`
26
+ `);return["## Claude Fast Mode Usage","","Usage: `/claude-fast`, `/claude-fast on`, or `/claude-fast off`.","",Hf({enabled:$})].join(`
27
+ `)}var c="claude-killswitch";function H$(f){let _=f.trim().split(/\s+/).filter(Boolean);if(_.length===0)return{type:"status"};if(_.length===1&&_[0]==="on")return{type:"on"};if(_.length===1&&_[0]==="off")return{type:"off"};if(_[0]==="set"){let $=[];for(let m=1;m<_.length;m++){let D=_[m]?.match(/^([^:]+):(\d+),(\d+)$/);if(!D)return{type:"usage"};let[,E,C,b]=D;$.push({account:E,fh:Number.parseInt(C,10),sd:Number.parseInt(b,10)})}if($.length===0)return{type:"usage"};return{type:"set",entries:$}}return{type:"usage"}}function Uf(f,_){let $=f.enabled===!0,m=["## Killswitch","",`Status: **${$?"ON":"OFF"}**`];if($){m.push(""),m.push("| Account | 5h threshold | 1w threshold |"),m.push("| ------- | ------------ | ------------ |");let D=f.main??{},E=D.five_hour??D["5h"]??Y.five_hour,C=D.seven_day??D["1w"]??Y.seven_day;m.push(`| main | ≥ ${E}% | ≥ ${C}% |`);for(let b of _){let H=f.accounts?.[b]??f.main??{},U=H.five_hour??H["5h"]??Y.five_hour,K=H.seven_day??H["1w"]??Y.seven_day;m.push(`| ${b} | ≥ ${U}% | ≥ ${K}% |`)}}return m.join(`
28
+ `)}var v0=["## Killswitch Commands","","```",`/${c} — show status`,`/${c} on — enable with current or default thresholds`,`/${c} off — disable`,`/${c} set all:5,10 — set all accounts to 5h≥5%, 1w≥10%`,`/${c} set main:3,8 work-alt:5,10 — per-account`,"```"].join(`
29
+ `);function DD(f){let _=H$(f.argumentsText);if(_.type==="status")return{text:`${Uf(f.config,f.accountIds)}
30
+
31
+ ${v0}`};if(_.type==="on"){let m={...f.config,enabled:!0,main:f.config.main??{five_hour:Y.five_hour,seven_day:Y.seven_day}};return{text:`## Killswitch Enabled
32
+
33
+ ${Uf(m,f.accountIds)}`,updatedConfig:m}}if(_.type==="off")return{text:"## Killswitch Disabled",updatedConfig:{...f.config,enabled:!1}};if(_.type==="set"){let m={...f.config.accounts??{}},D={...f.config,enabled:!0,accounts:m};for(let C of _.entries){let b={five_hour:C.fh,seven_day:C.sd};if(C.account==="main")D.main=b;else if(C.account==="all"){D.main=b;for(let H of f.accountIds)m[H]=b}else m[C.account]=b}return{text:`## Killswitch Updated
34
+
35
+ ${Uf(D,f.accountIds)}`,updatedConfig:D}}return{text:`${Uf(f.config,f.accountIds)}
36
+
37
+ ${v0}`}}import{createHash as M$}from"node:crypto";var U$=globalThis.setTimeout;function h(f){return M$("sha256").update(f).digest("hex").slice(0,16)}class R{main=null;mainTokenFp=null;fallbacks=new Map;fallbackTokenFps=new Map;inflightMain=null;inflightFallbacks=new Map;mainLastApiError=void 0;fallbackApiErrors=new Map;fallbackErrorTokenFps=new Map;apiGate=Promise.resolve();lastApiCallAt=0;storage;fetchImpl;now;onMainQuotaFetched;onApiError;constructor(f){this.storage=f.storage,this.fetchImpl=f.fetchImpl??fetch,this.now=f.now??Date.now,this.onMainQuotaFetched=f.onMainQuotaFetched,this.onApiError=f.onApiError;let _=z0(f.storage);if(_)this.main={quota:_.quota,refreshAfter:Zf(_.quota,f.storage,_.checkedAt),checkedAt:_.checkedAt},this.mainTokenFp=_.tokenFingerprint??null;let $=f.storage?.quota?.mainLastQuotaApiError;if($&&k($,this.now()))this.mainLastApiError=$}getMain(f){if(f&&this.main&&this.mainTokenFp&&this.mainTokenFp!==h(f))this.main=null,this.mainTokenFp=null;return this.main}getFallback(f,_){let $=this.fallbacks.get(f)??null;if(!_||!$)return $;if(this.fallbackTokenFps.get(f)!==h(_))return this.fallbacks.delete(f),this.fallbackTokenFps.delete(f),null;return $}getAllFallbacks(){return this.fallbacks}setMain(f,_){this.mainTokenFp=h(f),this.main=_}setFallback(f,_,$){if(this.fallbacks.set(f,_),$)this.fallbackTokenFps.set(f,h($));else this.fallbackTokenFps.delete(f)}async refreshMain(f){let _=h(f);if(this.mainTokenFp&&this.mainTokenFp!==_)this.main=null,this.mainTokenFp=null;if(this.inflightMain)return this.inflightMain;if(this.isBackedOff()){if(this.main)return this.main.quota;throw Error("Quota API rate-limited — try again later")}return this.inflightMain=this._fetchMain(f),this.inflightMain}async refreshFallback(f,_){let $=R.fallbackInflightKey(f,_),m=this.inflightFallbacks.get($);if(m)return m;if(this.isFallbackBackedOff(f,_)){let E=this.getFallback(f,_);if(E)return E.quota;throw Error("Quota API rate-limited — try again later")}let D=this._fetchFallback(f,_);return this.inflightFallbacks.set($,D),D}async refreshAllFallbacks(f){let _=this.now();for(let $ of f){if($.enabled===!1)continue;if(!$.access)continue;let m=this.getFallback($.id,$.access);if(m&&_<m.refreshAfter)continue;try{await this.refreshFallback($.id,$.access)}catch{}}}refreshMainInBackground(f){if(this.inflightMain)return;if(this.isBackedOff())return;this.refreshMain(f).catch(()=>{})}isMainStale(){if(!this.main)return!0;return this.now()>=this.main.refreshAfter}isFallbackStale(f,_){let $=this.getFallback(f,_);if(!$)return!0;return this.now()>=$.refreshAfter}shouldRefreshOnRequestCount(f){let _=W0(this.storage);if(_<=0)return!1;return f>0&&f%_===0}needsRefresh(f){return this.isMainStale()||this.shouldRefreshOnRequestCount(f)}updateStorage(f){this.storage=f}seedFallbacksFromAccounts(f){let _=Z(this.storage);for(let $ of f){if($.enabled===!1)continue;if(this.getFallback($.id,$.access))continue;if(!$.quota)continue;let m=Math.max($.quota.five_hour?.checkedAt??0,$.quota.seven_day?.checkedAt??0);if(m<=0)continue;this.setFallback($.id,{quota:$.quota,refreshAfter:m+_,checkedAt:m},$.access)}}isBackedOff(){return k(this.mainLastApiError,this.now())}isFallbackBackedOff(f,_){if(_){if(this.fallbackErrorTokenFps.get(f)!==h(_))return!1}return k(this.fallbackApiErrors.get(f),this.now())}getLastApiError(){return this.mainLastApiError}static API_CALL_GAP_MS=1000;static fallbackInflightKey(f,_){return JSON.stringify([f,h(_)])}_enqueueApiFetch(f){let _=async()=>{let m=this.now()-this.lastApiCallAt;if(m<R.API_CALL_GAP_MS)await new Promise((D)=>{let E=U$(D,R.API_CALL_GAP_MS-m);if(typeof E==="object"&&"unref"in E)E.unref()});return this.lastApiCallAt=this.now(),f()},$=this.apiGate.then(_,_);return this.apiGate=$.catch(()=>{}),$}async _fetchMain(f){return this._enqueueApiFetch(async()=>{try{if(this.isBackedOff()){if(this.main)return this.main.quota;throw Error("Quota API rate-limited — try again later")}let _=await Vf({name:"opencode-main-quota-refresh",ttlMs:30000});if(!_){if(this.main)return this.main.quota;throw Error("Quota refresh is already in progress")}try{let $=await _f({accessToken:f,fetchImpl:this.fetchImpl,now:this.now}),m=this.now();return this.mainTokenFp=h(f),this.main={quota:$,refreshAfter:Zf($,this.storage,m),checkedAt:m},this.mainLastApiError=void 0,this.onMainQuotaFetched?.($,m,this.mainTokenFp),$}catch($){throw this._handleMainFetchError($),$}finally{await _.release()}}finally{this.inflightMain=null}})}async _fetchFallback(f,_){return this._enqueueApiFetch(async()=>{try{if(this.isFallbackBackedOff(f,_)){let D=this.getFallback(f,_);if(D)return D.quota;throw Error("Quota API rate-limited — try again later")}let $=await _f({accessToken:_,fetchImpl:this.fetchImpl,now:this.now}),m=this.now();return this.setFallback(f,{quota:$,refreshAfter:m+Z(this.storage),checkedAt:m},_),this.fallbackApiErrors.delete(f),this.fallbackErrorTokenFps.delete(f),$}catch($){throw this._handleFallbackFetchError(f,_,$),$}finally{this.inflightFallbacks.delete(R.fallbackInflightKey(f,_))}})}static isAuthError(f){let _=f instanceof Error?f.message:String(f);return/quota check failed: 401\b/.test(_)}_handleMainFetchError(f){if(R.isAuthError(f))return;this.mainLastApiError=ff({error:f,now:this.now(),previous:this.mainLastApiError}),this.onApiError?.(this.mainLastApiError)}_handleFallbackFetchError(f,_,$){if(R.isAuthError($))return;let m=h(_),D=this.fallbackErrorTokenFps.get(f)===m?this.fallbackApiErrors.get(f):void 0;this.fallbackApiErrors.set(f,ff({error:$,now:this.now(),previous:D})),this.fallbackErrorTokenFps.set(f,m)}}var MD="claude-quota",d0={five_hour:"5h",seven_day:"1w"};function n0(f){return`${Math.round(f*10)/10}%`}function wf(f,_){let $=Math.max(0,_-f),m=Math.floor($/60000);if(m<1)return"just now";if(m===1)return"1m ago";if(m<60)return`${m}m ago`;let D=Math.floor(m/60),E=m%60;if(E===0)return`${D}h ago`;return`${D}h ${E}m ago`}function K$(f,_){let $=Date.parse(f);if(!Number.isFinite($))return f;let m=$-_;if(m<=0)return"now";let D=Math.max(1,Math.ceil(m/60000));if(D<60)return`in ${D}m`;let E=Math.floor(D/60),C=D%60;if(C===0)return`in ${E}h`;return`in ${E}h ${C}m`}function N$(f,_){if(!f)return"";return`, resets ${K$(f,_)}`}function g0(f,_,$){if(!_)return` - ${d0[f]}: unknown`;return[` - ${d0[f]}: ${n0(_.remainingPercent)} remaining`,` (${n0(_.usedPercent)} used`,`${N$(_.resetsAt,$)}, checked ${wf(_.checkedAt,$)})`].join("")}function j$(f){return f.label?.trim()||f.id}function S$(f){return f.lastQuotaRefreshError?.message??f.lastRefreshError?.message}function UD(f,_=new Map){if(!f?.accounts.length)return[];return f.accounts.map(($)=>{let m=_.get($.id)??S$($);return{name:j$($),role:"fallback",enabled:$.enabled!==!1,quota:$.quota,lastRefreshedAt:$.lastRefreshedAt,...m&&{error:m}}})}function KD(f){let _=f.now??Date.now(),$=["## Claude Quotas",""];if(f.refreshedAt)$.push(`Refreshed: ${wf(f.refreshedAt,_)}`,"");if(!f.accounts.length)return $.push("No Claude OAuth accounts found yet."),$.join(`
38
+ `);for(let m of f.accounts){let D=m.role==="main"?"main":"fallback",E=m.enabled===!1?" disabled":"";if($.push(`### ${m.name} (${D}${E})`),m.lastRefreshedAt)$.push(` - Last token refresh: ${wf(m.lastRefreshedAt,_)}`);if(m.error)$.push(` - Error: ${m.error}`);$.push(g0("five_hour",m.quota?.five_hour,_)),$.push(g0("seven_day",m.quota?.seven_day,_)),$.push("")}return $.join(`
39
+ `).trimEnd()}import{Buffer as _1}from"node:buffer";import{createHash as F$,randomBytes as G$}from"node:crypto";class kf extends Error{}var pf=new Map,c0=new Map,t0=new Set,s0=0;function lf(){return s0+=1,`req_${Date.now().toString(36)}_${s0.toString(36)}`}function Kf(f){if(t0.has(f))return;t0.add(f),j(f)}function JD(f){let _=f?.relay;if(!_)return Kf("disabled: no relay config found"),null;if(_.enabled!==!0)return Kf("disabled: relay.enabled is not true"),null;if(!_.url?.trim()||!_.token?.trim())return Kf("disabled: missing relay url or token"),null;let $=_.transport==="http"?"http":"websocket";return Kf(`configured transport=${$} protocol=${$==="websocket"?2:1} url=${_.url.trim()} fallbackToDirect=${_.fallbackToDirect!==!1}`),{enabled:!0,url:_.url.trim(),token:_.token.trim(),fallbackToDirect:_.fallbackToDirect!==!1,transport:$}}function OD(){return G$(32).toString("base64url")}function J$(f){return`sha256:${F$("sha256").update(f).digest("hex")}`}function r0(f,_){let $=0,m=Math.min(f.length,_.length);while($<m&&f.charCodeAt($)===_.charCodeAt($))$++;let D=f.length,E=_.length;while(D>$&&E>$&&f.charCodeAt(D-1)===_.charCodeAt(E-1))D--,E--;return{start:$,deleteCount:D-$,insert:_.slice($,E)}}function O$(f){return f.deleteCount===0&&f.insert.length===0}function o0(f){let _=f.match(/\bcch=([0-9a-f]{5});/),$=_?.[1];if(!$||_.index==null)return null;let m=_.index+4;return{start:m,end:m+$.length,token:$}}function z$(f,_,$,m){return`${f.slice(0,_)}${m}${f.slice($)}`}function $1(f,_){let $=o0(f),m=o0(_);if($&&m&&$.start===m.start&&$.end-$.start===m.end-m.start&&$.token!==m.token){let D={start:$.start,deleteCount:$.end-$.start,insert:m.token},E=z$(f,$.start,$.end,m.token),C=r0(E,_);return O$(C)?D:[D,C]}return r0(f,_)}function W$(f,_){if(typeof _!=="string")return!1;try{let $=f instanceof Request?new URL(f.url):new URL(f.toString());return $.pathname==="/v1/messages"||$.pathname==="/messages"}catch{return!1}}function B$(f){let _={};for(let[$,m]of f.entries()){if($==="x-session-affinity"||$==="x-opencode-session")continue;_[$]=m}return _}async function a0(f,_){return fetch(f.url,{method:"POST",headers:{"content-type":"application/json","x-relay-token":f.token},body:JSON.stringify(_)})}function z(f){return f.length>12?`${f.slice(0,12)}…`:f}function I(){return performance.now()}function w(f){return Math.round(f*10)/10}function V$(f){let{input:_,init:$,headers:m,bodyText:D,affinity:E,previous:C,nextHash:b}=f,H=_ instanceof Request?_.url:_.toString(),U={protocol:1,type:"request",affinity:E,upstream:{url:H,method:$?.method||(_ instanceof Request?_.method:"POST"),headers:B$(m)},next_hash:b};return C?{...U,mode:"patch",base_hash:C.hash,revision:C.revision+1,patch:$1(C.body,D)}:{...U,mode:"full_sync",revision:1,body:D}}function yf(f,_){return{protocol:f.protocol,type:"request",affinity:f.affinity,upstream:f.upstream,next_hash:f.next_hash,mode:"full_sync",revision:1,body:_}}function m1(f,_,$,m){pf.set(f,{body:_,hash:$,revision:m})}async function e0(f){let{config:_,payload:$,bodyText:m,fallback:D}=f,E=$,C=await a0(_,E);if(C.status===409&&E.mode==="patch")j(`state mismatch from relay session=${z(E.affinity)}; retrying full_sync`),await C.body?.cancel().catch(()=>{}),E=yf(E,m),C=await a0(_,E);if(!C.ok&&C.status>=500&&_.fallbackToDirect)return j(`relay returned ${C.status}; falling back direct session=${z(E.affinity)}`),await C.body?.cancel().catch(()=>{}),{response:await D(),payload:E,transport:"http",protocol:E.protocol,usedRelay:!1};return{response:C,payload:E,transport:"http",protocol:E.protocol,usedRelay:!0}}function X$(f,_){let $=new URL(f);return $.protocol=$.protocol==="http:"?"ws:":"wss:",$.pathname="/ws",$.searchParams.set("token",_),$.toString()}function Z$(f){return new Uint8Array(_1.from(f,"base64"))}function Y$(f){if(f instanceof Uint8Array)return f;if(f instanceof ArrayBuffer)return new Uint8Array(f);if(ArrayBuffer.isView(f))return new Uint8Array(f.buffer,f.byteOffset,f.byteLength);return new Uint8Array(_1.from(String(f)))}function L$(f){return JSON.parse(f)}function f1(f){let _=f,$=[`code=${_.code??"unknown"}`,`wasClean=${_.wasClean??"unknown"}`];if(_.reason)$.push(`reason=${JSON.stringify(_.reason)}`);return $.join(" ")}function A$(f){let _=f.message||"relay websocket error";return f.status?`relay websocket error ${f.status}: ${_}`:_}class D1{config;affinity;socket;connecting;queue=Promise.resolve();pending;serverState;constructor(f,_){this.config=f,this.affinity=_}send(f,_,$=!1){let m=I(),D=this.queue.catch(()=>{}).then(()=>this.startQueued(f,_,m,$)),E=D.then(async({response:C,getPayload:b})=>({response:await C,payload:b(),transport:"websocket",protocol:2,usedRelay:!0}));return this.queue=D.then(({done:C})=>C.catch(()=>{}),()=>{}),E}async startQueued(f,_,$,m){let D=I();await this.ensureConnected();let E=I(),C=pf.get(this.affinity),b=this.serverState?.hash,H={...f,protocol:2,id:lf()};if(H.mode==="patch"&&(!b||b!==H.base_hash))H.mode="full_sync",H.revision=(this.serverState?.revision??0)+1,delete H.base_hash,delete H.patch,H.body=_;if(H.mode==="patch"&&C)H.patch=$1(C.body,_);j(`perf websocket send_start session=${z(this.affinity)} request=${H.id} mode=${H.mode} queueMs=${w(E-$)} connectMs=${w(E-D)} bodyBytes=${_.length} relayBytes=${JSON.stringify(H).length}`);let U=H,K=this.sendPayload(H,_,m);K.done.catch(()=>{});let S=K.done,F=K.response.catch((N)=>{if(!(N instanceof kf)||H.mode!=="patch")throw N;let B=yf(H,_);B.protocol=2,B.id=lf(),B.revision=(this.serverState?.revision??0)+1,U=B;let V=this.sendPayload(B,_,m);return V.done.catch(()=>{}),S=V.done,V.response}),G=F.then(()=>S,()=>S.catch(()=>{}));return{response:F,done:G,getPayload:()=>U}}async ensureConnected(){if(this.socket?.readyState===WebSocket.OPEN&&this.serverState!==void 0)return;if(this.connecting)return await this.connecting;this.connecting=new Promise((f,_)=>{let $=X$(this.config.url,this.config.token),m=new URL($);m.searchParams.set("affinity",this.affinity);let D=new WebSocket(m.toString());this.socket=D,this.serverState=void 0;let E=setTimeout(()=>{D.close(),_(Error("relay websocket ready timed out"))},15000);D.addEventListener("message",(C)=>{try{if(typeof C.data!=="string"){this.handleBinaryChunk(C.data);return}let b=L$(C.data);if(b.type==="ready"){clearTimeout(E),this.serverState=b.state,f();return}this.handleMessage(b)}catch(b){clearTimeout(E),_(b),this.failPending(b),D.close()}}),D.addEventListener("error",()=>{clearTimeout(E);let C=Error("relay websocket error");_(C),this.failPending(C)}),D.addEventListener("close",(C)=>{if(clearTimeout(E),this.socket===D)this.socket=void 0,this.serverState=void 0,this.connecting=void 0;if(this.pending){if(this.pending.retryingBeforeResponse)return;let b=this.pending.responseStartedAt!=null,H=b?"closed after response_start before stream bytes":"closed before response";if(this.retryPendingBeforeResponse(this.pending,H,C))return;let U=Error(b?"relay websocket closed during response stream":"relay websocket closed before response");j(`websocket ${b?"closed during response stream":"closed before response without retry"} session=${z(this.affinity)} request=${this.pending.payload.id} chunks=${this.pending.streamChunkCount} bytes=${this.pending.streamByteCount} ${f1(C)}`),this.failPending(U)}})}).finally(()=>{this.connecting=void 0}),await this.connecting}sendPayload(f,_,$){let m=this.socket;if(!m||m.readyState!==WebSocket.OPEN)throw Error("relay websocket is not connected");let D=I(),E,C,b=new Promise((U,K)=>{E=U,C=K});return{response:new Promise((U,K)=>{let S={payload:f,bodyText:_,resolve:U,reject:K,streamDone:!1,accepted:!1,responseStarted:!1,resolveDone:E,rejectDone:C,sentAt:D,optimisticResponse:$,streamChunkCount:0,streamByteCount:0,retryAttempts:0,retryingBeforeResponse:!1};if(this.pending=S,this.resetPendingTimeout(S),m.send(JSON.stringify(f)),$)this.resolvePendingResponse(S,200,"OK",{"content-type":"text/event-stream","x-cortexkit-relay-optimistic":"true"})}),done:b}}resetPendingTimeout(f){clearTimeout(f.timeout),f.timeout=setTimeout(()=>{if(this.pending!==f)return;if(this.retryPendingBeforeResponse(f,"response timed out"))return;this.failPending(Error("relay websocket response timed out")),this.socket?.close()},45000)}retryPendingBeforeResponse(f,_,$){if(f.responseStartedAt!=null&&f.streamByteCount>0)return!1;if(f.streamDone)return!1;if(f.retryAttempts>=1)return!1;f.retryAttempts+=1,f.retryingBeforeResponse=!0,clearTimeout(f.timeout);let m=f.retryAttempts,D=f.payload.id;return j(`websocket ${_}; reconnecting and retrying full_sync session=${z(this.affinity)} request=${D} retry=${m} chunks=${f.streamChunkCount} bytes=${f.streamByteCount}${$?` ${f1($)}`:""}`),this.socket?.close(),this.socket=void 0,this.serverState=void 0,this.connecting=void 0,(async()=>{try{if(await this.ensureConnected(),this.pending!==f)return;let E=yf(f.payload,f.bodyText);E.protocol=2,E.id=lf(),E.revision=(this.serverState?.revision??0)+1,f.payload=E,f.accepted=!1,f.acceptedAt=void 0,f.responseStartedAt=void 0,f.sentAt=I(),f.retryingBeforeResponse=!1;let C=this.socket;if(!C||C.readyState!==WebSocket.OPEN)throw Error("relay websocket is not connected");this.resetPendingTimeout(f),j(`perf websocket retry_send session=${z(this.affinity)} request=${E.id} previous=${D} mode=full_sync retry=${m} bodyBytes=${f.bodyText.length} relayBytes=${JSON.stringify(E).length}`),C.send(JSON.stringify(E))}catch(E){if(f.retryingBeforeResponse=!1,this.pending===f)this.failPending(E)}})(),!0}enqueueStreamChunk(f,_){f.streamChunkCount+=1,f.streamByteCount+=_.byteLength,f.streamController?.enqueue(_)}handleBinaryChunk(f){let _=this.pending;if(!_?.responseStarted)return;this.enqueueStreamChunk(_,Y$(f))}resolvePendingResponse(f,_,$,m){if(f.responseStarted)return;f.responseStarted=!0;let D=new ReadableStream({start:(E)=>{f.streamController=E},cancel:()=>{this.socket?.close()}});f.resolve(new Response(D,{status:_,statusText:$,headers:m}))}handleMessage(f){if(f.type==="keepalive"){if(this.pending)this.resetPendingTimeout(this.pending);return}let _=this.pending;if(!_)return;if("id"in f&&f.id&&f.id!==_.payload.id)return;if(f.type==="accepted"){let $=I();_.accepted=!0,_.acceptedAt=$,j(`perf websocket accepted session=${z(this.affinity)} request=${_.payload.id} sentMs=${w($-_.sentAt)} mode=${_.payload.mode}`),this.serverState={hash:f.hash,revision:f.revision},m1(this.affinity,_.bodyText,f.hash,f.revision),this.resetPendingTimeout(_);return}if(f.type==="response_start"){let $=I();if(_.responseStartedAt=$,j(`perf websocket response_start session=${z(this.affinity)} request=${_.payload.id} sentMs=${w($-_.sentAt)} upstreamMs=${_.acceptedAt==null?"unknown":w($-_.acceptedAt)} status=${f.status}`),clearTimeout(_.timeout),this.resolvePendingResponse(_,f.status,f.statusText,f.headers),_.optimisticResponse&&f.status>=400)_.streamController?.enqueue(new TextEncoder().encode(`event: error
40
+ data: ${JSON.stringify({type:"error",error:{type:"relay_upstream_error",message:`Relay upstream returned HTTP ${f.status}`}})}
41
+
42
+ `)),this.finishPending();return}if(f.type==="chunk"){this.enqueueStreamChunk(_,Z$(f.base64));return}if(f.type==="done"){this.finishPending();return}if(f.type==="error"){if(_.optimisticResponse&&_.responseStartedAt!=null){j(`websocket relay error during optimistic response session=${z(this.affinity)} request=${_.payload.id} status=${f.status} message=${f.message||"unknown"} chunks=${_.streamChunkCount} bytes=${_.streamByteCount}`),_.streamController?.enqueue(new TextEncoder().encode(`event: error
43
+ data: ${JSON.stringify({type:"error",error:{type:"relay_error",message:f.message||"relay error"}})}
44
+
45
+ `)),this.finishPending(),this.socket?.close();return}if(f.status===409&&this.retryPendingBeforeResponse(_,f.message||"state mismatch"))return;let $=f.status===409?new kf(f.message||"state mismatch"):Error(A$(f));this.failPending($)}}finishPending(){let f=this.pending;if(!f)return;let _=I();if(j(`perf websocket done session=${z(this.affinity)} request=${f.payload.id} sentMs=${w(_-f.sentAt)} streamMs=${f.responseStartedAt==null?"unknown":w(_-f.responseStartedAt)} chunks=${f.streamChunkCount} bytes=${f.streamByteCount}`),clearTimeout(f.timeout),!f.streamDone)f.streamDone=!0,f.streamController?.close();f.resolveDone(),this.pending=void 0}failPending(f){let _=this.pending;if(!_)return;if(clearTimeout(_.timeout),this.pending=void 0,_.responseStarted)_.streamController?.error(f);else _.reject(f);_.rejectDone(f)}}function Q$(f,_){let $=c0.get(_);if($)return $;let m=new D1(f,_);return c0.set(_,m),m}async function zD(f){let{config:_,input:$,init:m,headers:D,body:E,fallback:C,affinity:b,optimisticResponse:H}=f;if(!_||!W$($,E))return C();let U=b||D.get("x-session-affinity")||D.get("x-opencode-session");if(!U)return j("skipping relay: missing x-session-affinity header"),C();let K=E,S=J$(K),F=pf.get(U),G=V$({input:$,init:m,headers:D,bodyText:K,affinity:U,previous:F,nextHash:S});try{let N;if(_.transport==="websocket")try{N=await Q$(_,U).send(G,K,H===!0)}catch(V){j(`websocket relay failed session=${z(U)}; trying http relay: ${V instanceof Error?V.message:String(V)}`),N=await e0({config:_,payload:G,bodyText:K,fallback:C})}else N=await e0({config:_,payload:G,bodyText:K,fallback:C});if(!N.usedRelay)return N.response;if(N.transport==="http")m1(U,K,N.payload.next_hash,N.payload.revision);let B=JSON.stringify(N.payload).length;return j(`used relay transport=${N.transport} protocol=${N.protocol} mode=${N.payload.mode} status=${N.response.status} session=${z(U)} bodyBytes=${K.length} relayBytes=${B}`),await u0({affinity:U,transport:N.transport,protocol:N.protocol,mode:N.payload.mode,status:N.response.status,bodyText:K,previousBodyText:F?.body,payload:N.payload,relayBytes:B}),N.response}catch(N){if(!_.fallbackToDirect)throw j(`relay failed session=${z(U)} and fallbackToDirect=false: ${N instanceof Error?N.message:String(N)}`),N;return j(`relay failed; falling back direct session=${z(U)}: ${N instanceof Error?N.message:String(N)}`),C()}}var WD=`
46
+ async function hashBody(body) {
47
+ const bytes = new TextEncoder().encode(body)
48
+ const digest = await crypto.subtle.digest('SHA-256', bytes)
49
+ const hex = [...new Uint8Array(digest)].map((b) => b.toString(16).padStart(2, '0')).join('')
50
+ return 'sha256:' + hex
51
+ }
52
+
53
+ function applyPatch(base, patch) {
54
+ return base.slice(0, patch.start) + patch.insert + base.slice(patch.start + patch.deleteCount)
55
+ }
56
+
57
+ function applyPatchSet(base, patch) {
58
+ if (!Array.isArray(patch)) return applyPatch(base, patch)
59
+ if (patch.length === 0) return base
60
+
61
+ let result = ''
62
+ let cursor = 0
63
+ for (const item of patch) {
64
+ if (item.start < cursor) return { error: 'overlapping patch', status: 400 }
65
+ result += base.slice(cursor, item.start)
66
+ result += item.insert
67
+ cursor = item.start + item.deleteCount
68
+ }
69
+ return result + base.slice(cursor)
70
+ }
71
+
72
+ async function readState(env, affinity) {
73
+ const raw = await env.RELAY_STATE.get('session:' + affinity)
74
+ return raw ? JSON.parse(raw) : null
75
+ }
76
+
77
+ async function writeState(env, affinity, state) {
78
+ await env.RELAY_STATE.put('session:' + affinity, JSON.stringify(state), { expirationTtl: 86400 })
79
+ }
80
+
81
+ async function resolveBody(env, payload) {
82
+ if (payload.mode === 'full_sync') return payload.body
83
+ if (payload.mode === 'patch') {
84
+ const state = await readState(env, payload.affinity)
85
+ if (!state || state.hash !== payload.base_hash) {
86
+ return { error: 'state mismatch', status: 409 }
87
+ }
88
+ return applyPatchSet(state.body, payload.patch)
89
+ }
90
+ return { error: 'unknown mode', status: 400 }
91
+ }
92
+
93
+ async function prepareUpstream(env, payload) {
94
+ if ((payload.protocol !== 1 && payload.protocol !== 2) || payload.type !== 'request' || !payload.affinity || !payload.upstream?.url || !payload.next_hash) {
95
+ return { error: 'invalid payload', status: 400 }
96
+ }
97
+
98
+ const body = await resolveBody(env, payload)
99
+ if (body && typeof body === 'object' && 'error' in body) return body
100
+
101
+ if (typeof body !== 'string' || (await hashBody(body)) !== payload.next_hash) {
102
+ return { error: 'hash mismatch', status: 409 }
103
+ }
104
+
105
+ const stateWrite = writeState(env, payload.affinity, { body, hash: payload.next_hash, revision: payload.revision }).catch(() => {})
106
+ console.log(JSON.stringify({
107
+ relay: 'opencode-anthropic-auth',
108
+ transport: 'relay',
109
+ mode: payload.mode,
110
+ revision: payload.revision,
111
+ affinity: String(payload.affinity).slice(0, 12),
112
+ bodyBytes: body.length,
113
+ }))
114
+
115
+ return { body, stateWrite }
116
+ }
117
+
118
+ function resolveBodyFromState(state, payload) {
119
+ if (payload.mode === 'full_sync') return payload.body
120
+ if (payload.mode === 'patch') {
121
+ if (!state || state.hash !== payload.base_hash) {
122
+ return { error: 'state mismatch', status: 409 }
123
+ }
124
+ return applyPatchSet(state.body, payload.patch)
125
+ }
126
+ return { error: 'unknown mode', status: 400 }
127
+ }
128
+
129
+ function deferWorkerTask(task) {
130
+ return new Promise((resolve) => setTimeout(resolve, 0)).then(task)
131
+ }
132
+
133
+ function checkpointWebSocketState(env, payload, body, nextState) {
134
+ return deferWorkerTask(async () => {
135
+ try {
136
+ if ((await hashBody(body)) !== payload.next_hash) {
137
+ throw new Error('hash mismatch')
138
+ }
139
+ await writeState(env, payload.affinity, nextState)
140
+ } catch (error) {
141
+ console.log(JSON.stringify({
142
+ relay: 'opencode-anthropic-auth',
143
+ transport: 'websocket',
144
+ event: 'checkpoint_write_failed',
145
+ affinity: String(payload.affinity).slice(0, 12),
146
+ message: error instanceof Error ? error.message : String(error),
147
+ }))
148
+ }
149
+ })
150
+ }
151
+
152
+ async function prepareWebSocketUpstream(env, state, payload) {
153
+ if (payload.protocol !== 2 || payload.type !== 'request' || !payload.id || !payload.affinity || !payload.upstream?.url || !payload.next_hash) {
154
+ return { error: 'invalid payload', status: 400 }
155
+ }
156
+
157
+ const body = resolveBodyFromState(state, payload)
158
+ if (body && typeof body === 'object' && 'error' in body) return body
159
+ if (typeof body !== 'string') return { error: 'invalid body', status: 400 }
160
+ if ((await hashBody(body)) !== payload.next_hash) {
161
+ return { error: 'hash mismatch', status: 409 }
162
+ }
163
+
164
+ const nextState = { body, hash: payload.next_hash, revision: payload.revision }
165
+ const checkpoint = checkpointWebSocketState(env, payload, body, nextState)
166
+ const logAccepted = () => console.log(JSON.stringify({
167
+ relay: 'opencode-anthropic-auth',
168
+ transport: 'websocket',
169
+ mode: payload.mode,
170
+ revision: payload.revision,
171
+ affinity: String(payload.affinity).slice(0, 12),
172
+ bodyBytes: body.length,
173
+ }))
174
+
175
+ return { body, state: nextState, checkpoint, logAccepted }
176
+ }
177
+
178
+ function headersToObject(headers) {
179
+ const result = {}
180
+ for (const [key, value] of headers.entries()) result[key] = value
181
+ return result
182
+ }
183
+
184
+ async function handleRelayPayload(env, payload) {
185
+ const prepared = await prepareUpstream(env, payload)
186
+ if (prepared.error) return prepared
187
+ const upstream = await fetch(payload.upstream.url, {
188
+ method: payload.upstream.method || 'POST',
189
+ headers: payload.upstream.headers,
190
+ body: prepared.body,
191
+ })
192
+ return { upstream, stateWrite: prepared.stateWrite }
193
+ }
194
+
195
+ async function handleWebSocket(socket, env, ctx, payload, getState, setState) {
196
+ const heartbeat = setInterval(() => {
197
+ try {
198
+ socket.send(JSON.stringify({ protocol: 2, type: 'keepalive' }))
199
+ } catch {
200
+ clearInterval(heartbeat)
201
+ }
202
+ }, 15000)
203
+ try {
204
+ const result = await prepareWebSocketUpstream(env, getState(), payload)
205
+ if (result.error) {
206
+ socket.send(JSON.stringify({ protocol: 2, type: 'error', id: payload.id, status: result.status, message: result.error }))
207
+ return
208
+ }
209
+
210
+ setState(result.state)
211
+ socket.send(JSON.stringify({ protocol: 2, type: 'accepted', id: payload.id, hash: result.state.hash, revision: result.state.revision }))
212
+ ctx?.waitUntil?.(deferWorkerTask(result.logAccepted))
213
+
214
+ const upstreamPromise = fetch(payload.upstream.url, {
215
+ method: payload.upstream.method || 'POST',
216
+ headers: payload.upstream.headers,
217
+ body: result.body,
218
+ })
219
+ ctx?.waitUntil?.(result.checkpoint)
220
+ const upstream = await upstreamPromise
221
+ socket.send(JSON.stringify({
222
+ protocol: 2,
223
+ type: 'response_start',
224
+ id: payload.id,
225
+ status: upstream.status,
226
+ statusText: upstream.statusText,
227
+ headers: headersToObject(upstream.headers),
228
+ }))
229
+
230
+ const reader = upstream.body?.getReader()
231
+ if (reader) {
232
+ while (true) {
233
+ const { done, value } = await reader.read()
234
+ if (done) break
235
+ socket.send(value)
236
+ }
237
+ }
238
+ socket.send(JSON.stringify({ protocol: 2, type: 'done', id: payload.id }))
239
+ } catch (error) {
240
+ socket.send(JSON.stringify({ protocol: 2, type: 'error', id: payload.id, status: 500, message: error instanceof Error ? error.message : String(error) }))
241
+ } finally {
242
+ clearInterval(heartbeat)
243
+ }
244
+ }
245
+
246
+ export default {
247
+ async fetch(request, env, ctx) {
248
+ if (request.headers.get('Upgrade') === 'websocket') {
249
+ const url = new URL(request.url)
250
+ const token = url.searchParams.get('token')
251
+ const affinity = url.searchParams.get('affinity')
252
+ if (token !== env.RELAY_TOKEN) return new Response('unauthorized', { status: 401 })
253
+ if (!affinity) return new Response('missing affinity', { status: 400 })
254
+ const pair = new WebSocketPair()
255
+ const client = pair[0]
256
+ const server = pair[1]
257
+ server.binaryType = 'arraybuffer'
258
+ let state = null
259
+ let ready = false
260
+ server.accept()
261
+ const loadState = readState(env, affinity).then((loadedState) => {
262
+ state = loadedState
263
+ ready = true
264
+ server.send(JSON.stringify({
265
+ protocol: 2,
266
+ type: 'ready',
267
+ state: state ? { hash: state.hash, revision: state.revision } : null,
268
+ }))
269
+ }).catch((error) => {
270
+ server.send(JSON.stringify({ protocol: 2, type: 'error', status: 500, message: error instanceof Error ? error.message : String(error) }))
271
+ server.close(1011, 'state load failed')
272
+ })
273
+ ctx?.waitUntil?.(loadState)
274
+ if (!ctx?.waitUntil) void loadState
275
+ let busy = false
276
+ server.addEventListener('message', (event) => {
277
+ if (!ready) {
278
+ server.send(JSON.stringify({ protocol: 2, type: 'error', status: 425, message: 'relay state is not ready' }))
279
+ return
280
+ }
281
+ if (busy) {
282
+ server.send(JSON.stringify({ protocol: 2, type: 'error', status: 429, message: 'request already in flight' }))
283
+ return
284
+ }
285
+ let payload
286
+ try {
287
+ payload = JSON.parse(event.data)
288
+ } catch {
289
+ server.send(JSON.stringify({ protocol: 2, type: 'error', status: 400, message: 'invalid JSON payload' }))
290
+ return
291
+ }
292
+ payload.affinity = affinity
293
+ busy = true
294
+ const run = handleWebSocket(server, env, ctx, payload, () => state, (nextState) => { state = nextState }).finally(() => { busy = false })
295
+ ctx?.waitUntil?.(run)
296
+ if (!ctx?.waitUntil) void run
297
+ })
298
+ return new Response(null, { status: 101, webSocket: client })
299
+ }
300
+
301
+ if (request.method === 'GET') {
302
+ return Response.json({ status: 'ok', transports: ['http', 'websocket'] })
303
+ }
304
+ if (request.method !== 'POST') return new Response('method not allowed', { status: 405 })
305
+ if (request.headers.get('x-relay-token') !== env.RELAY_TOKEN) {
306
+ return new Response('unauthorized', { status: 401 })
307
+ }
308
+
309
+ try {
310
+ const payload = await request.json()
311
+ const result = await handleRelayPayload(env, payload)
312
+ if (result.error) return Response.json({ error: result.error }, { status: result.status })
313
+
314
+ if (result.stateWrite) ctx.waitUntil(result.stateWrite)
315
+
316
+ const upstream = result.upstream
317
+ return new Response(upstream.body, {
318
+ status: upstream.status,
319
+ statusText: upstream.statusText,
320
+ headers: upstream.headers,
321
+ })
322
+ } catch (error) {
323
+ return Response.json(
324
+ { error: error instanceof Error ? error.message : 'internal relay error' },
325
+ { status: 502 },
326
+ )
327
+ }
328
+ },
329
+ }
330
+ `;var XD="claude-routing",vf=["main-first","fallback-first"],df="main-first",E1="Usage: `/claude-routing`, `/claude-routing main-first`, or `/claude-routing fallback-first`.";function h$(f){return typeof f==="string"&&vf.includes(f)?f:df}function ZD(f){return h$(f?.routing?.mode)}async function YD(f,_=W()){let $=await L(_)??{version:1,main:{type:"opencode",provider:"anthropic"},accounts:[]};return $.routing={...$.routing??{},mode:f},await A($,_),$}function x$(f){let _=f.trim().toLowerCase().split(/\s+/).filter(Boolean);if(_.length===0)return{type:"status"};if(_.length===1&&vf.includes(_[0]))return{type:"mode",mode:_[0]};if(_.length===2&&_[0]==="mode"&&vf.includes(_[1]))return{type:"mode",mode:_[1]};return{type:"usage"}}function I$(f){if(f==="fallback-first")return"Try usable fallback accounts before the main account. If no fallback succeeds, try the main account.";return"Try the main account first. Use fallback accounts only when quota policy or fallback errors require it."}function uf(f){let _=f?.mode??df;return["## Claude Routing Status","",`- Mode: \`${_}\``,`- Behavior: ${I$(_)}`,"",E1].join(`
331
+ `)}function LD(f){let _=x$(f.argumentsText),$=f.mode??df;if(_.type==="status")return uf({mode:$});if(_.type==="mode")return["## Claude Routing Updated","",`Mode updated to \`${_.mode}\`.`,"",...uf({mode:_.mode}).split(`
332
+ `).slice(2)].join(`
333
+ `);return["## Claude Routing Usage","",E1,"",...uf({mode:$}).split(`
334
+ `).slice(2)].join(`
335
+ `)}export{q$ as a,sf as b,P$ as c,T$ as d,R$ as e,w$ as f,i$ as g,rf as h,l$ as i,k$ as j,q as k,m0 as l,d$ as m,n$ as n,Q as o,W as p,L as q,A as r,Vf as s,_m as t,r1 as u,$m as v,mm as w,Dm as x,Em as y,Cm as z,bm as A,Hm as B,Mm as C,Um as D,O0 as E,$_ as F,u as G,Of as H,Km as I,B0 as J,m_ as K,Nm as L,jm as M,Sm as N,Fm as O,M_ as P,Om as Q,zm as R,Wm as S,Bm as T,S_ as U,Vm as V,q0 as W,Tm as X,Lm as Y,Am as Z,Qm as _,Q0 as $,lm as aa,km as ba,u_ as ca,If as da,w0 as ea,v_ as fa,ym as ga,n_ as ha,tm as ia,sm as ja,$$ as ka,rm as la,am as ma,em as na,fD as oa,b$ as pa,_D as qa,c as ra,DD as sa,R as ta,MD as ua,UD as va,KD as wa,JD as xa,OD as ya,zD as za,WD as Aa,XD as Ba,ZD as Ca,YD as Da,x$ as Ea,LD as Fa};