@cortexkit/opencode-anthropic-auth 1.9.3 → 1.10.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/dist/cli.js +1 -1
- package/dist/index-3ynbghx3.js +1 -0
- package/dist/index-fvzta6xw.js +410 -0
- package/dist/index-jb14nj5c.js +2 -0
- package/dist/{index-agh52sak.js → index-p8j7mmfc.js} +1 -1
- package/dist/index.js +10 -9
- package/dist/rpc/notifications.d.ts +5 -0
- package/dist/rpc/port-file.d.ts +12 -0
- package/dist/rpc/port-file.js +1 -0
- package/dist/rpc/protocol.d.ts +20 -0
- package/dist/rpc/protocol.js +0 -0
- package/dist/rpc/rpc-client.d.ts +6 -0
- package/dist/rpc/rpc-client.js +1 -0
- package/dist/rpc/rpc-dir.d.ts +3 -0
- package/dist/rpc/rpc-dir.js +1 -0
- package/dist/rpc/rpc-server.d.ts +13 -0
- package/dist/sidebar-state.js +1 -1
- package/dist/tui/command-dialogs.d.ts +8 -0
- package/dist/tui-preferences.js +1 -1
- package/package.json +5 -3
- package/src/rpc/notifications.ts +54 -0
- package/src/rpc/port-file.ts +64 -0
- package/src/rpc/protocol.ts +31 -0
- package/src/rpc/rpc-client.ts +55 -0
- package/src/rpc/rpc-dir.ts +19 -0
- package/src/rpc/rpc-server.ts +121 -0
- package/src/tui/command-dialogs.tsx +229 -0
- package/src/tui.tsx +105 -1
- package/dist/index-68qrf9fn.js +0 -410
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{Oa as I,Qa as $,m as w,n as k,p as A,r as R,t as d,u as l,v as p}from"./index-
|
|
2
|
+
import{Oa as I,Qa as $,m as w,n as k,p as A,r as R,t as d,u as l,v as p}from"./index-fvzta6xw.js";import"./index-p8j7mmfc.js";import{stdin as E,stdout as U}from"node:process";import{createInterface as _}from"node:readline/promises";function g(){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 y(){console.log(`Usage:
|
|
3
3
|
opencode-anthropic-auth login [label]
|
|
4
4
|
opencode-anthropic-auth api add [label]
|
|
5
5
|
opencode-anthropic-auth list
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{createHash as z}from"node:crypto";import{homedir as F,tmpdir as L}from"node:os";import{join as k}from"node:path";var G="OPENCODE_ANTHROPIC_AUTH_RPC_DIR";function Q(q){let g=process.env[G]?.trim();if(g)return g;let w=z("sha256").update(q).digest("hex").slice(0,16),x=process.env.XDG_STATE_HOME||k(F(),".local","state");return k(x,"cortexkit","anthropic-auth","rpc",w)}export{L as fb,Q as gb};
|
|
@@ -0,0 +1,410 @@
|
|
|
1
|
+
var Lf="9d1c250a-e61b-44d9-88ed-5944d1962f5e",C_={console:"https://platform.claude.com/oauth/authorize",max:"https://claude.com/cai/oauth/authorize"},hf="https://platform.claude.com/oauth/code/callback",Vf="https://platform.claude.com/v1/oauth/token",If="axios/1.15.2",L_=["org:create_api_key","user:profile","user:inference","user:sessions:claude_code","user:mcp_servers","user:file_upload"],O_="user:profile user:inference user:sessions:claude_code user:mcp_servers user:file_upload",WE="mcp_";var U_="fast-mode-2026-02-01";function YE(f,_){let D=(f??"").split(",").map((E)=>E.trim()).filter(Boolean);return[...new Set([...D,..._])].join(",")}function XE(f){return typeof f==="string"&&(f.startsWith("claude-opus-4-6")||f.startsWith("claude-opus-4-7")||f.startsWith("claude-opus-4-8"))}var ZE="You are OpenCode",hE="You are Claude Code, Anthropic's official CLI for Claude.",VE=["<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 R="2.1.177",Qf="3bf",H_="cli",b_="0.94.0",N_="v24.3.0",S_="claude-cli/2.1.177 (external, cli)",B_=["explicit","automatic","hybrid"],Of="explicit",IE=["github.com/anomalyco/opencode","opencode.ai/docs"],QE=[{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 A_(f){let _="";for(let D of f)_+=String.fromCharCode(D);return btoa(_).replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}async function K_(){let f=new Uint8Array(64);crypto.getRandomValues(f);let _=A_(f),D=await crypto.subtle.digest("SHA-256",new TextEncoder().encode(_));return{verifier:_,challenge:A_(new Uint8Array(D)),method:"S256"}}function q0(f){if(!f)return;let _=Number(f);if(Number.isFinite(_)&&_>0)return Math.ceil(_);let D=Date.parse(f);if(Number.isFinite(D)){let E=Math.ceil((D-Date.now())/1000);return E>0?E:void 0}return}class y extends Error{status;body;retryAfter;constructor(f,_,D){super(`Claude OAuth refresh failed: ${f} — ${_}`);this.status=f,this.body=_,this.name="ClaudeOAuthRefreshError",this.retryAfter=q0(D??void 0)}}function x0(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 F_(f){let _=f.fetchImpl??fetch,D=f.maxRetries??2,E=f.baseDelayMs??500;for(let $=0;$<=D;$++)try{if($>0){let L=E*2**($-1);await new Promise((O)=>setTimeout(O,L))}let m=await _(Vf,{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json, text/plain, */*","User-Agent":If},body:JSON.stringify({grant_type:"refresh_token",refresh_token:f.refreshToken,client_id:Lf,scope:O_})});if(!m.ok){if(m.status>=500&&$<D){await m.body?.cancel().catch(()=>{});continue}let L=await m.text().catch(()=>"");throw new y(m.status,L,m.headers.get("retry-after"))}let M=await m.json(),C=f.now?.()??Date.now();return{access:M.access_token,refresh:M.refresh_token??f.refreshToken,expires:C+M.expires_in*1000,expiresIn:M.expires_in}}catch(m){if(m instanceof y)throw m;if($<D&&x0(m))continue;throw m}throw Error("Token refresh exhausted all retries")}function P0(){return crypto.randomUUID().replace(/-/g,"")}function R0(f){let _=f.trim();try{let M=new URL(_),C=M.searchParams.get("code"),L=M.searchParams.get("state");if(C&&L)return{code:C,state:L}}catch{}let D=_.split("#");if(D.length===2&&D[0]&&D[1])return{code:D[0],state:D[1]};let E=new URLSearchParams(_),$=E.get("code"),m=E.get("state");if($&&m)return{code:$,state:m};return null}async function T0(f,_,D){let E=await fetch(Vf,{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json, text/plain, */*","User-Agent":If},body:JSON.stringify({code:f.code,state:f.state,grant_type:"authorization_code",client_id:Lf,redirect_uri:D,code_verifier:_})});if(!E.ok)return{type:"failed"};let $=await E.json();return{type:"success",refresh:$.refresh_token,access:$.access_token,expires:Date.now()+$.expires_in*1000}}async function TE(f){let _=await K_(),D=P0(),E=new URL(C_[f],import.meta.url);return E.searchParams.set("code","true"),E.searchParams.set("client_id",Lf),E.searchParams.set("response_type","code"),E.searchParams.set("redirect_uri",hf),E.searchParams.set("scope",L_.join(" ")),E.searchParams.set("code_challenge",_.challenge),E.searchParams.set("code_challenge_method","S256"),E.searchParams.set("state",D),{url:E.toString(),redirectUri:hf,state:D,verifier:_.verifier}}async function wE(f,_,D,E){let $=R0(f);if(!$)return{type:"failed"};if(E&&$.state!==E)return{type:"failed"};return T0($,_,D)}import*as j_ from"node:fs";import*as z_ from"node:os";import*as G_ from"node:path";var w0=G_.join(z_.tmpdir(),"opencode-anthropic-auth.log"),J_=!1,y0=500,l0=50,o=[],n=null;function qf(){if(n)clearTimeout(n),n=null;if(o.length===0)return;let f=o.join("");o=[];try{j_.appendFileSync(w0,f)}catch{}}function i0(){if(n)return;n=setTimeout(()=>{n=null,qf()},y0)}function k0(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(J_)return;try{if(o.push(`[${new Date().toISOString()}] ${f}${k0(_)}
|
|
4
|
+
`),o.length>=l0)qf();else i0()}catch{}}function B(f,_){Q(`[relay] ${f}`,_)}if(!J_)process.on("exit",qf);import{createHash as q_,randomUUID as lf}from"node:crypto";import{mkdir as p0,readFile as Rf,rename as d0,rm as W_,stat as v0,writeFile as Tf}from"node:fs/promises";import{homedir as u0}from"node:os";import{dirname as x_,join as a}from"node:path";var r0=globalThis.setTimeout.bind(globalThis),n0=globalThis.clearTimeout.bind(globalThis),P_="anthropic-auth.json",g0="anthropic-auth-state.json",s0="https://api.anthropic.com/api/oauth/usage";function X(f){return f.type==="oauth"}function nE(f){return f.type==="api"}function c0(f){let _=f?.trim();if(!_)return!1;try{let D=new URL(_);return(D.protocol==="http:"||D.protocol==="https:")&&!D.username&&!D.password}catch{return!1}}function gE(f){return f.costZeroing?.enabled!==!1}var t0=[401,403,429],R_=240,o0=R_;var e0=300000,a0=3600000,fD=86400000,_D=60000,DD=900000,ED=300000,$D=5,Y_={five_hour:0,seven_day:0},mD=!0,MD=60000,CD=60000,LD=600000,OD=1e4,UD=100;function HD(){if(process.env.OPENCODE_CONFIG_DIR?.trim())return process.env.OPENCODE_CONFIG_DIR.trim();return a(process.env.XDG_CONFIG_HOME||a(u0(),".config"),"opencode")}function G(){return process.env.OPENCODE_ANTHROPIC_AUTH_FILE?.trim()||a(HD(),P_)}function kf(f=G()){let _=process.env.OPENCODE_ANTHROPIC_AUTH_STATE_FILE?.trim();if(_)return _;return f.endsWith(P_)?a(x_(f),g0):`${f}.state.json`}function N(f){return f!=null&&typeof f==="object"&&!Array.isArray(f)}function X_(f){return{id:typeof f.id==="string"&&f.id.trim()?f.id.trim():lf(),label:typeof f.label==="string"?f.label: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}}function bD(f){if(!N(f))return null;if(f.type==="api"){let _=typeof f.baseURL==="string"?f.baseURL.trim():"",D=typeof f.apiKey==="string"?f.apiKey.trim():"";if(!c0(_))return null;let E=f.authHeader==="x-api-key"?"x-api-key":"authorization-bearer";return{...X_(f),type:"api",apiKey:D||void 0,baseURL:_,authHeader:E}}if(f.type!=="oauth")return null;if(typeof f.refresh!=="string"||!f.refresh.trim())return null;return{...X_(f),type:"oauth",access:typeof f.access==="string"?f.access:void 0,refresh:f.refresh,expires:typeof f.expires==="number"?f.expires:void 0,lastRefreshedAt:typeof f.lastRefreshedAt==="number"?f.lastRefreshedAt:void 0,lastRefreshError:Z_(f.lastRefreshError),lastQuotaRefreshError:Z_(f.lastQuotaRefreshError),quota:ND(f.quota)}}function Z_(f){if(!N(f))return;if(typeof f.message!=="string")return;let _=Number(f.checkedAt);if(!Number.isFinite(_))return;let D=Number(f.nextRetryAt),E=Number(f.retryCount);return{message:f.message,checkedAt:_,nextRetryAt:Number.isFinite(D)?D:void 0,retryCount:Number.isFinite(E)?E:void 0,tokenHash:typeof f.tokenHash==="string"?f.tokenHash:void 0}}function ND(f){if(!N(f))return;let _={};for(let D of["five_hour","seven_day"]){let E=f[D];if(!N(E))continue;let $=Number(E.usedPercent),m=Number(E.remainingPercent),M=Number(E.checkedAt);if(!Number.isFinite($)||!Number.isFinite(m)||!Number.isFinite(M))continue;_[D]={usedPercent:$,remainingPercent:m,checkedAt:M,resetsAt:typeof E.resetsAt==="string"?E.resetsAt:void 0}}return Object.keys(_).length?_:void 0}function SD(f){if(!N(f)||!Array.isArray(f.accounts))return null;return{version:1,main:{type:"opencode",provider:"anthropic"},routing:N(f.routing)?f.routing:void 0,fallbackOn:Array.isArray(f.fallbackOn)?f.fallbackOn.filter((_)=>Number.isInteger(_)):void 0,refresh:N(f.refresh)?f.refresh:void 0,quota:N(f.quota)?f.quota:void 0,claudeCache:N(f.claudeCache)?f.claudeCache:void 0,dump:N(f.dump)?f.dump:void 0,claudeFast:N(f.claudeFast)?f.claudeFast:void 0,costZeroing:N(f.costZeroing)?f.costZeroing:void 0,cacheKeep:N(f.cacheKeep)?f.cacheKeep:void 0,relay:N(f.relay)?f.relay:void 0,killswitch:N(f.killswitch)?f.killswitch:void 0,accounts:f.accounts.map(bD).filter((_)=>_!=null)}}async function Uf(f){try{return{exists:!0,value:JSON.parse(await Rf(f,"utf8"))}}catch(_){if(_.code==="ENOENT")return{exists:!1,value:null};return{exists:!1,value:null}}}function T(f){return Object.fromEntries(Object.entries(f).filter(([,_])=>_!==void 0))}function BD(f,_){if(!N(f))return f;let D=N(_)?_:{},E=N(D.main)?D.main:void 0,$=N(D.accounts)?D.accounts:{},m=N(f.quota)?f.quota:{},M=N(f.refresh)?f.refresh:{},C=E??m,L=E??M,O=Array.isArray(f.accounts)?f.accounts.map((U)=>{if(!N(U))return U;let S=typeof U.id==="string"&&N($[U.id])?$[U.id]:{};return{...U,...S}}):[];return{...f,refresh:T({...M,mainLastRefreshError:L.lastRefreshError,mainRefreshLeaseId:L.refreshLeaseId,mainRefreshLeaseUntil:L.refreshLeaseUntil,mainRefreshLeaseTokenHash:L.refreshLeaseTokenHash}),quota:T({...m,mainQuota:C.quota,mainQuotaCheckedAt:C.quotaCheckedAt,mainQuotaToken:C.quotaToken,mainLastQuotaApiError:C.lastQuotaApiError}),accounts:O}}async function V(f=G()){let _=await Uf(f);if(!_.exists)return null;let D=await Uf(kf(f));return SD(BD(_.value,D.value))}async function AD(f){let _=await Uf(f);return N(_.value)?_.value:{}}function KD(f){return Object.fromEntries(Object.entries(f).filter(([,_])=>_!==void 0))}function FD(f){return T({id:f.id,label:f.label,type:f.type,enabled:f.enabled,addedAt:f.addedAt,baseURL:f.type==="api"?f.baseURL:void 0,authHeader:f.type==="api"?f.authHeader:void 0})}function T_(f){if(f.type==="api")return T({apiKey:f.apiKey,lastUsed:f.lastUsed});return T({access:f.access,refresh:f.refresh,expires:f.expires,lastUsed:f.lastUsed,lastRefreshedAt:f.lastRefreshedAt,lastRefreshError:f.lastRefreshError,lastQuotaRefreshError:f.lastQuotaRefreshError,quota:f.quota})}function ff(f){return Math.max(f?.five_hour?.checkedAt??0,f?.seven_day?.checkedAt??0)}function jD(f,_){if(!N(f))return _;let D=f,E=ff(D.quota),$=ff(_.quota);if(E>$){let M=Boolean(D.access&&_.access&&D.access!==_.access),C=D.lastRefreshedAt??0,L=_.lastRefreshedAt??0;if(M&&L<=C){let O={...D};if(typeof _.lastUsed==="number"&&(typeof D.lastUsed!=="number"||_.lastUsed>D.lastUsed))O.lastUsed=_.lastUsed;return O}return{...D,..._,quota:D.quota,lastQuotaRefreshError:D.lastQuotaRefreshError}}let m={...D,..._};if(!("lastQuotaRefreshError"in _))delete m.lastQuotaRefreshError;if(!("lastRefreshError"in _))delete m.lastRefreshError;return m}function zD(f){let _=f.refresh?T({enabled:f.refresh.enabled,intervalMinutes:f.refresh.intervalMinutes,refreshBeforeExpiryMinutes:f.refresh.refreshBeforeExpiryMinutes}):void 0,D=f.quota?T({enabled:f.quota.enabled,checkIntervalMinutes:f.quota.checkIntervalMinutes,refreshEveryNRequests:f.quota.refreshEveryNRequests,minimumRemaining:f.quota.minimumRemaining,failClosedOnUnknownQuota:f.quota.failClosedOnUnknownQuota,showToasts:f.quota.showToasts}):void 0;return KD({version:1,main:f.main,routing:f.routing,fallbackOn:f.fallbackOn,refresh:_,quota:D,claudeCache:f.claudeCache,dump:f.dump,claudeFast:f.claudeFast,costZeroing:f.costZeroing,cacheKeep:f.cacheKeep,relay:f.relay,killswitch:f.killswitch,accounts:f.accounts.map(FD)})}function GD(f){let _=Object.fromEntries(f.accounts.map((D)=>[D.id,T_(D)]));return{version:1,main:T({quota:f.quota?.mainQuota,quotaCheckedAt:f.quota?.mainQuotaCheckedAt,quotaToken:f.quota?.mainQuotaToken,lastQuotaApiError:f.quota?.mainLastQuotaApiError,lastRefreshError:f.refresh?.mainLastRefreshError,refreshLeaseId:f.refresh?.mainRefreshLeaseId,refreshLeaseUntil:f.refresh?.mainRefreshLeaseUntil,refreshLeaseTokenHash:f.refresh?.mainRefreshLeaseTokenHash}),accounts:_}}async function wf(f,_){await p0(x_(f),{recursive:!0});let D=`${f}.${lf()}.tmp`;await Tf(D,`${JSON.stringify(_,null,2)}
|
|
5
|
+
`,{encoding:"utf8",mode:384}),await d0(D,f)}async function q(f,_=G()){let E={...await AD(_),...zD(f)};await wf(_,E),await wf(kf(_),GD(f))}function JD(f,_){f.main=f.main??{};let D=typeof f.main.quotaCheckedAt==="number"?f.main.quotaCheckedAt:ff(f.main.quota),E=typeof _.quota?.mainQuotaCheckedAt==="number"?_.quota.mainQuotaCheckedAt:ff(_.quota?.mainQuota);if(D>E)return;f.main.quota=_.quota?.mainQuota,f.main.quotaCheckedAt=_.quota?.mainQuotaCheckedAt,f.main.quotaToken=_.quota?.mainQuotaToken,f.main.lastQuotaApiError=_.quota?.mainLastQuotaApiError}function WD(f,_){f.main=f.main??{},f.main.lastRefreshError=_.refresh?.mainLastRefreshError,f.main.refreshLeaseId=_.refresh?.mainRefreshLeaseId,f.main.refreshLeaseUntil=_.refresh?.mainRefreshLeaseUntil,f.main.refreshLeaseTokenHash=_.refresh?.mainRefreshLeaseTokenHash}function yf(f){if(Array.isArray(f))return f.map(yf);if(!N(f))return f;return Object.fromEntries(Object.entries(f).filter(([,_])=>_!==void 0).map(([_,D])=>[_,yf(D)]))}async function YD(f,_=G(),D={mainQuota:!0,mainRefresh:!0,accounts:!0}){let E=kf(_),$=(await Uf(E)).value,m=N($)?{...$,version:1}:{version:1};if(D.mainQuota)JD(m,f);if(D.mainRefresh)WD(m,f);if(D.accounts){let M=D.accounts===!0?null:new Set(D.accounts);m.accounts={...N(m.accounts)?m.accounts:{}};for(let C of f.accounts){if(M&&!M.has(C.id))continue;m.accounts[C.id]=jD(m.accounts[C.id],T_(C))}if(M){for(let C of M)if(!f.accounts.some((L)=>L.id===C))delete m.accounts[C]}}await wf(E,yf(m))}async function Hf(f){let D=`${f.path??G()}.${f.name}.lock`,E=a(D,"owner.json"),$=lf(),m=f.now??Date.now,M=null,C=!1;async function L(){try{return JSON.parse(await Rf(D,"utf8"))}catch(F){if(F.code!=="EISDIR")throw F;return JSON.parse(await Rf(E,"utf8"))}}async function O(){await Tf(D,`${JSON.stringify({ownerId:$,expiresAt:m()+f.ttlMs})}
|
|
6
|
+
`,{encoding:"utf8",mode:384})}async function U(){try{return await Tf(D,`${JSON.stringify({ownerId:$,expiresAt:m()+f.ttlMs})}
|
|
7
|
+
`,{encoding:"utf8",mode:384,flag:"wx"}),!0}catch(F){let j=F.code;if(j==="EEXIST"||j==="EISDIR")return!1;throw F}}function S(){if(!f.renew||C)return;let F=f.renewIntervalMs??Math.max(1000,Math.floor(f.ttlMs/3));if(M=r0(()=>{(async()=>{try{let j=await L(),P=m();if(C||j?.ownerId!==$||Number(j?.expiresAt)<=P)return;await O(),S()}catch{}})()},F),"unref"in M)M.unref()}if(!await U()){try{let F=await L();if(Number(F?.expiresAt)>m())return null}catch{try{if((await v0(D)).mtimeMs+f.ttlMs>Date.now())return null}catch{return null}}if(await W_(D,{recursive:!0,force:!0}).catch(()=>{}),!await U())return null}return S(),{release:async()=>{if(C=!0,M)n0(M),M=null;try{if((await L())?.ownerId!==$)return}catch{return}await W_(D,{recursive:!0,force:!0}).catch(()=>{})}}}function sE(f){return f?.claudeCache?.enabled===!0}function XD(f){return typeof f==="string"&&B_.includes(f)?f:Of}function ZD(f){return XD(f?.claudeCache?.mode)}async function cE(f,_,D=G()){let E=await V(D)??{version:1,main:{type:"opencode",provider:"anthropic"},accounts:[]};return E.claudeCache={...E.claudeCache??{},enabled:f,mode:_??ZD(E)},await q(E,D),E}async function tE(f,_=G()){let D=await V(_)??{version:1,main:{type:"opencode",provider:"anthropic"},accounts:[]};return D.claudeCache={...D.claudeCache??{},enabled:D.claudeCache?.enabled===!0,mode:f},await q(D,_),D}function oE(f){return f?.dump?.enabled===!0}async function eE(f,_=G()){let D=await V(_)??{version:1,main:{type:"opencode",provider:"anthropic"},accounts:[]};return D.dump={...D.dump??{},enabled:f},await q(D,_),D}function aE(f){return f?.claudeFast?.enabled===!0}async function f$(f,_=G()){let D=await V(_)??{version:1,main:{type:"opencode",provider:"anthropic"},accounts:[]};return D.claudeFast={...D.claudeFast??{},enabled:f},await q(D,_),D}async function _$(f,_,D=G()){let E=await V(D)??{version:1,main:{type:"opencode",provider:"anthropic"},accounts:[]};return E.cacheKeep={enabled:!0,startHour:f,endHour:_},await q(E,D),E}async function D$(f,_=G()){let D=await V(_)??{version:1,main:{type:"opencode",provider:"anthropic"},accounts:[]};return D.cacheKeep={...D.cacheKeep??{},enabled:f},await q(D,_),D}function hD(f){return f?.fallbackOn?.length?f.fallbackOn:t0}function E$(f,_){return hD(_).includes(f)}function w_(f){let _=f?.quota?.minimumRemaining||{};return{five_hour:_.five_hour??_["5h"]??Y_.five_hour,seven_day:_.seven_day??_["1w"]??Y_.seven_day}}function _f(f){return f?.quota?.enabled!==!1}function VD(f){return f?.refresh?.enabled!==!1}function ID(f){return Math.floor(Math.random()*Math.max(0,f))}function QD(f){let _=f?.refresh?.refreshBeforeExpiryMinutes??o0;return Math.max(R_,_)*60000}function y_(f){return q_("sha256").update(f).digest("hex")}function qD(f){if(f instanceof y)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 xD(f){let _=y_(f.refreshToken),E=(f.previous?.tokenHash===_?f.previous.retryCount??0:0)+1,$;if(f.error instanceof y&&f.error.retryAfter)$=f.error.retryAfter*1000;else if(qD(f.error))$=Math.min(a0,e0*2**Math.min(E-1,6));else $=fD;return{message:Df(f.error),checkedAt:f.now,nextRetryAt:f.now+$,retryCount:E,tokenHash:_}}function e(f,_,D){if(!f?.nextRetryAt||f.nextRetryAt<=D)return!1;if(!_)return!0;return f.tokenHash===y_(_)}function xf(f,_){return`Claude OAuth refresh is backed off for ${Math.max(1,Math.ceil(((f.nextRetryAt??_)-_)/1000))}s after: ${f.message}`}function bf(f){let D=(f.previous?.retryCount??0)+1,E=d_(f.error)?Math.min(DD,_D*2**Math.min(D-1,6)):ED;return{message:Df(f.error),checkedAt:f.now,nextRetryAt:f.now+E,retryCount:D}}function g(f,_){if(!f?.nextRetryAt||f.nextRetryAt<=_)return!1;return!0}function $$(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??$D;return Math.max(1,_)*60000}function l_(f){if(!f?.quota?.mainQuota||!f.quota.mainQuotaCheckedAt)return null;return{quota:f.quota.mainQuota,checkedAt:f.quota.mainQuotaCheckedAt,tokenFingerprint:f.quota.mainQuotaToken}}function i_(f){let _=f?.quota?.refreshEveryNRequests;return typeof _==="number"&&Number.isFinite(_)&&_>0?Math.floor(_):0}function pf(f){return f?.quota?.failClosedOnUnknownQuota??mD}function k_(f,_){if(!_f(_))return!0;let D=w_(_);for(let E of["five_hour","seven_day"]){let $=f?.[E];if(!$)return!pf(_);if($.remainingPercent<D[E])return!1}return!0}var h={five_hour:5,seven_day:10};function h_(f){return{five_hour:f?.five_hour??f?.["5h"]??h.five_hour,seven_day:f?.seven_day??f?.["1w"]??h.seven_day}}function PD(f){return f?.killswitch?.enabled===!0}function RD(f,_){if(!f?.killswitch)return h;if(_&&f.killswitch.accounts?.[_])return h_(f.killswitch.accounts[_]);return h_(f.killswitch.main)}function m$(f,_,D){if(!PD(_))return!0;let E=RD(_,D),$=!1;for(let m of["five_hour","seven_day"]){let M=f?.[m];if(!M){$=!0;continue}if(M.remainingPercent<E[m])return!1}if($)return!pf(_);return!0}function M$(f,_,D){let E=[],$=[f,..._.map((m)=>m.quota)];for(let m of $)for(let M of["five_hour","seven_day"]){let C=m?.[M]?.resetsAt;if(!C)continue;let L=Date.parse(C);if(Number.isFinite(L)&&L>D)E.push(L)}if(!E.length)return 300;return Math.max(1,Math.ceil((Math.min(...E)-D)/1000))+60}function C$(f){return f?.killswitch??{enabled:!1}}async function L$(f,_=G()){let D=await V(_)??{version:1,main:{type:"opencode",provider:"anthropic"},accounts:[]};return D.killswitch=f,await q(D,_),D}function df(f,_,D){if(!_f(_))return D+Z(_);let E=w_(_),$=[];for(let m of["five_hour","seven_day"]){let M=f?.[m];if(!M)return D+Z(_);if(M.remainingPercent>=E[m])continue;let C=M.resetsAt?Date.parse(M.resetsAt):Number.NaN;if(!Number.isFinite(C)||C<=D)return D+Z(_);$.push(C)}if(!$.length)return D+Z(_);return Math.min(...$)+60000}function l(f,_,D){return!f.access||!f.expires||f.expires-D<=QD(_)}function p_(f,_,D){if(!_f(_))return!0;let E=Z(_);return["five_hour","seven_day"].every(($)=>{let m=f?.[$];return Boolean(m&&D-m.checkedAt<E)})}function Pf(f,_,D){return!p_(f.quota,_,D)}function TD(f,_){if(!f)return!1;if(!f.resetsAt)return!0;let D=Date.parse(f.resetsAt);return!Number.isFinite(D)||D>_}function wD(f,_){return["five_hour","seven_day"].every((D)=>TD(f?.[D],_))}function d_(f){let _=Df(f);if(/Claude quota check failed: (429|5\d\d)\b/.test(_))return!0;if(!(f instanceof Error))return!1;let D=f.code;return _.includes("fetch failed")||D==="ECONNRESET"||D==="ECONNREFUSED"||D==="ETIMEDOUT"||D==="UND_ERR_CONNECT_TIMEOUT"}function yD(f,_,D,E){return d_(D)&&k_(f.quota,_)&&wD(f.quota,E)}function V_(f){if(!Number.isFinite(f))return 0;if(f<0)return 0;if(f>100)return 100;return f}function I_(f,_){if(typeof f?.utilization!=="number")return;let D=V_(f.utilization);return{usedPercent:D,remainingPercent:V_(100-D),resetsAt:f.resets_at,checkedAt:_}}async function Nf(f){let D=await(f.fetchImpl??fetch)(s0,{method:"GET",headers:{Authorization:`Bearer ${f.accessToken}`,Accept:"application/json","Content-Type":"application/json","anthropic-beta":"oauth-2025-04-20","User-Agent":`claude-code/${R}`}});if(!D.ok){let m=await D.text().catch(()=>"");throw Error(`Claude quota check failed: ${D.status} — ${m}`)}let E=f.now?.()??Date.now(),$=await D.json();return{five_hour:I_($.five_hour,E),seven_day:I_($.seven_day,E)}}function W(f,_){let D=f.accounts.findIndex((E)=>E.id===_.id);if(D>=0)f.accounts[D]=_}function Df(f){return f instanceof Error?f.message:String(f)}function v_(f,_,D){f.lastRefreshError=xD({error:_,now:D,refreshToken:f.refresh,previous:f.lastRefreshError})}function Q_(f,_,D){if(f.lastQuotaRefreshError=bf({error:_,now:D,previous:f.lastQuotaRefreshError}),_ instanceof y)v_(f,_,D)}function lD(f){return`fallback-oauth-refresh-${q_("sha256").update(f).digest("hex").slice(0,16)}`}class iD{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??G(),this.quotaManager=f.quotaManager??null,this.onFallbackStorageChanged=f.onFallbackStorageChanged}seedFallbackQuota(f,_){if(!this.quotaManager)return;if(!f.quota)return;let D=Math.max(f.quota.five_hour?.checkedAt??0,f.quota.seven_day?.checkedAt??0);if(D<=0)return;let E=this.quotaManager.getFallback(f.id,f.access);if(E&&E.checkedAt>=D)return;let $=Z(_);this.quotaManager.setFallback(f.id,{quota:f.quota,refreshAfter:D+$,checkedAt:D},f.access)}async load(){return V(this.configPath)}async save(f,_){await YD(f,this.configPath,{accounts:_??!0})}startBackgroundRefresh(){let f=async()=>{await this.refreshDueAccounts(),await this.refreshQuotaForDueAccounts()};if(f().catch(()=>{}),!this.refreshTimer){if(this.refreshTimer=setInterval(()=>{f().catch(()=>{})},MD+ID(CD)),"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 D=[],E=!1;for(let $ of _.accounts){if($.enabled===!1||!X($))continue;try{let m=$;if(l(m,_,this.now())){let C=m.lastRefreshError;if(C&&e(C,m.refresh,this.now()))throw Error(xf(C,this.now()));m=await this.refreshAccount(m,_),E=!0}if(this.seedFallbackQuota(m,_),(this.quotaManager?this.quotaManager.isFallbackStale(m.id,m.access):Pf(m,_,this.now()))&&!g(m.lastQuotaRefreshError,this.now()))m=await this.refreshAccountQuota(m,_),E=!0;if(this.accountPassesQuotaPolicy(this.quotaPolicyAccount(m),_))D.push(m)}catch(m){if(yD($,_,m,this.now()))Q("[refresh] fallback quota using cached quota after refresh error",{accountId:$.id,error:Df(m)}),D.push($);else if(!pf(_))D.push($)}}if(E)await this.save(_);return D}async markUsed(f){let _=await this.load();if(!_)return;let D=_.accounts.find((E)=>E.id===f.id);if(!D)return;D.lastUsed=this.now(),await this.save(_)}accountPassesQuotaPolicy(f,_){return k_(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||!VD(f))return;let _=!1;for(let D of f.accounts){if(D.enabled===!1||!X(D))continue;if(!l(D,f,this.now()))continue;if(e(D.lastRefreshError,D.refresh,this.now()))continue;try{Q("[refresh] fallback oauth background due",{accountId:D.id,expiresInMs:D.expires?D.expires-this.now():void 0}),await this.refreshAccount(D,f),_=!0}catch(E){Q("[refresh] fallback oauth background failed",{accountId:D.id,error:E instanceof Error?E.message:String(E)}),v_(D,E,this.now()),W(f,D),_=!0}}if(_)await this.save(f)}async refreshQuotaForDueAccounts(){let f=await this.load();if(!f||!_f(f))return;let _=!1;for(let D of f.accounts){if(D.enabled===!1||!X(D))continue;let E=D;try{if(l(E,f,this.now())){if(e(E.lastRefreshError,E.refresh,this.now()))continue;E=await this.refreshAccount(E,f),_=!0}if(g(E.lastQuotaRefreshError,this.now()))continue;if(this.seedFallbackQuota(E,f),!(this.quotaManager?this.quotaManager.isFallbackStale(E.id,E.access):Pf(E,f,this.now())))continue;await this.refreshAccountQuota(E,f),_=!0}catch($){Q_(D,$,this.now()),W(f,D),_=!0}}if(_)await this.save(f),this.onFallbackStorageChanged?.()}async refreshQuotaForAllAccounts(f={}){let _=await this.load(),D=[];if(!_||!_f(_))return{storage:_,errors:D};let E=f.force??!1,$=!1;for(let m of _.accounts){if(m.enabled===!1||!X(m))continue;let M=m;try{if(l(M,_,this.now())){let C=M.lastRefreshError;if(C&&e(C,M.refresh,this.now()))throw Error(xf(C,this.now()));M=await this.refreshAccount(M,_),$=!0}if(!E&&!Pf(M,_,this.now())){if(M.lastQuotaRefreshError)M.lastQuotaRefreshError=void 0,W(_,M),$=!0;continue}await this.refreshAccountQuota(M,_),$=!0}catch(C){Q_(m,C,this.now()),W(_,m),$=!0,D.push({accountId:m.id,message:Df(C)})}}if($)await this.save(_);return{storage:_,errors:D}}async refreshAccount(f,_,D={}){let E=this.refreshPromises.get(f.id);if(E){let M=await E;return W(_,M),M}let $=this.refreshAccountNow(f,_,D).finally(()=>{this.refreshPromises.delete(f.id)});this.refreshPromises.set(f.id,$);let m=await $;return W(_,m),m}async waitForConcurrentFallbackRefresh(f,_,D,E){let $=Date.now()+OD;while(Date.now()<$){await new Promise((O)=>setTimeout(O,UD));let m=await this.load(),M=m?.accounts.find((O)=>O.id===f.id&&X(O));if(!M)continue;if((M.access!==D.access||M.refresh!==D.refresh||(M.expires??0)>(D.expires??0)+60000)&&(E.force||!l(M,m,this.now())))return W(_,M),Q("[refresh] fallback oauth joined concurrent refresh",{accountId:M.id,expiresInMs:M.expires?M.expires-this.now():void 0}),M;let L=M.lastRefreshError;if(L&&e(L,M.refresh,this.now()))throw W(_,M),Error(xf(L,this.now()))}return null}async refreshAccountNow(f,_,D){let E=await this.load(),$=E?.accounts.find((C)=>C.id===f.id&&X(C));if($&&!D.force&&!l($,E,this.now()))return W(_,$),$;let m=$??f,M=await Hf({name:lD(m.id),ttlMs:LD,path:this.configPath,now:this.now,renew:!0});if(!M){Q("[refresh] fallback oauth refresh skipped file lock",{accountId:m.id});let C=await this.waitForConcurrentFallbackRefresh(f,_,m,D);if(C)return C;throw Error("Fallback OAuth refresh is already in progress")}try{if(E=await this.load(),$=E?.accounts.find((O)=>O.id===f.id&&X(O)),$&&!D.force&&!l($,E,this.now()))return W(_,$),$;m=$??m;let C=m.refresh;Q("[refresh] fallback oauth refresh request start",{accountId:m.id,force:D.force===!0,expiresInMs:m.expires?m.expires-this.now():void 0});let L=await F_({refreshToken:C,fetchImpl:this.fetchImpl,now:this.now});return m.access=L.access,m.refresh=L.refresh,m.expires=L.expires,m.lastRefreshedAt=L.expires-L.expiresIn*1000,m.lastRefreshError=void 0,W(_,m),await this.save(_),Q("[refresh] fallback oauth refresh succeeded",{accountId:m.id,expiresInMs:m.expires?m.expires-this.now():void 0}),m}finally{await M.release()}}async refreshAccountQuota(f,_){let D=f;if(!D.access)throw Error(`Fallback account ${f.id} has no access token`);let E=(C)=>this.quotaManager?this.quotaManager.refreshFallback(D.id,C):Nf({accessToken:C,fetchImpl:this.fetchImpl,now:this.now}),$=this.now();try{D.quota=await E(D.access)}catch(C){if(!(C instanceof Error?C.message:String(C)).includes("Claude quota check failed: 401"))throw C;if(D=await this.refreshAccount(f,_,{force:!0}),!D.access)throw C;D.quota=await E(D.access)}let m=await this.load(),M=m?.accounts.find((C)=>C.id===D.id&&X(C));if(m&&M&&M.access!==D.access)return this.seedFallbackQuota(M,m),W(_,M),M;if(m&&M?.access===D.access&&M.quota&&ff(M.quota)>=$&&p_(M.quota,m,this.now()))return this.seedFallbackQuota(M,m),W(_,M),M;if(D.lastQuotaRefreshError=void 0,W(_,D),this.quotaManager&&D.quota){let C=this.now();this.quotaManager.setFallback(D.id,{quota:D.quota,refreshAfter:C+Z(_),checkedAt:C},D.access)}return D}}var H$="claude-cache",u_="## Claude Cache Status",kD="## Claude Cache Enabled",pD="## Claude Cache Disabled",dD="## Claude Cache Usage",vD="Usage: `/claude-cache`, `/claude-cache on`, `/claude-cache off`, or `/claude-cache mode explicit|automatic|hybrid`.",Sf=!1,Bf=Of;function b$(){return Sf}function N$(){return Bf}function S$(f){Sf=f.enabled,Bf=f.mode}function uD(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 Ef(f){let _=f?.enabled??Sf,D=f?.mode??Bf;return[u_,"",`- Enabled: ${_?"enabled":"disabled"}`,`- Mode: ${D}`,"- 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 B$(f){let _=uD(f.argumentsText),D=f.enabled??Sf,E=f.mode??Bf;if(_.type==="status")return Ef({enabled:D,mode:E});if(_.type==="enable")return[kD,"",Ef({enabled:!0,mode:E})].join(`
|
|
9
|
+
`);if(_.type==="disable")return[pD,"",Ef({enabled:!1,mode:E})].join(`
|
|
10
|
+
`);if(_.type==="mode")return[u_,"",`Mode updated to \`${_.mode}\`.`,"",Ef({enabled:D,mode:_.mode})].join(`
|
|
11
|
+
`);return[dD,"",vD,"",Ef({enabled:D,mode:E})].join(`
|
|
12
|
+
`)}import{randomBytes as rD,randomUUID as g_}from"node:crypto";var nD=1000,i=new Map;function $f(f,_,D){if(!f.has(_)&&f.size>=nD){let E=f.keys().next().value;if(E!==void 0)f.delete(E)}f.set(_,D)}function s_(f){let _=f||"anonymous",D=i.get(_);if(D)return D;let E={deviceId:rD(32).toString("hex"),sessionId:g_()};return $f(i,_,E),E}var gD=86400000,sD=300000,vf=new Map,r_=new Map;async function cD(f,_){if(!f.startsWith("sk-ant-oat"))return null;let D=new AbortController,E=setTimeout(()=>D.abort(),5000);try{let $=new URL("https://api.anthropic.com/api/claude_cli/bootstrap");if($.searchParams.set("entrypoint",H_),_)$.searchParams.set("model",_);let m=await fetch($,{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/${R}`},signal:D.signal});if(!m.ok)return null;let C=(await m.json().catch(()=>null))?.oauth_account?.account_uuid;return typeof C==="string"&&C?C:null}catch{return null}finally{clearTimeout(E)}}async function j$(f,_){let D=s_(f);if(!f.startsWith("sk-ant-oat"))return D;let E=Date.now(),$=r_.get(f);if($&&$.expiresAt>E){if(!$.accountUuid)return D;let O=`account:${$.accountUuid}`,U=i.get(O);if(U)return $f(i,f,U),U}let m=vf.get(f);if(!m)m=cD(f,_),vf.set(f,m);let M=await m.finally(()=>{vf.delete(f)});if($f(r_,f,{accountUuid:M,expiresAt:E+(M?gD:sD)}),!M)return D;let C=`account:${M}`,L=i.get(C);if(L)return $f(i,f,L),L;return D.accountUuid=M,$f(i,C,D),D}function k(f){return f!=null&&typeof f==="object"&&!Array.isArray(f)}function tD(f){if(!f.accountUuid)return null;return JSON.stringify({device_id:f.deviceId,account_uuid:f.accountUuid,session_id:f.sessionId})}function z$(f,_){let D=tD(_);if(!D){if(k(f.metadata))delete f.metadata.user_id;return!1}if(!k(f.metadata))f.metadata={};let E=f.metadata;if(k(E))E.user_id=D;return!0}var oD=["oauth-2025-04-20","interleaved-thinking-2025-05-14","thinking-token-count-2026-05-13","context-management-2025-06-27","prompt-caching-scope-2026-01-05","claude-code-20250219","advisor-tool-2026-03-01","advanced-tool-use-2025-11-20","extended-cache-ttl-2025-04-11","cache-diagnosis-2026-04-07"],eD=["oauth-2025-04-20","interleaved-thinking-2025-05-14","thinking-token-count-2026-05-13","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"],n_=["oauth-2025-04-20","interleaved-thinking-2025-05-14","thinking-token-count-2026-05-13","context-management-2025-06-27","prompt-caching-scope-2026-01-05","advisor-tool-2026-03-01","advanced-tool-use-2025-11-20","extended-cache-ttl-2025-04-11","cache-diagnosis-2026-04-07"];function aD(f){return f.output_config?.format?.type==="json_schema"}function f1(f){return Array.isArray(f.tools)&&f.tools.length>0&&Array.isArray(f.system)&&k(f.thinking)&&k(f.context_management)&&k(f.output_config)&&k(f.diagnostics)}function _1(f,_=[]){let D=f?f1(f)?[...oD]:aD(f)?[...eD]:[...n_]:[...n_];if(f?.speed==="fast")D.push(U_);for(let E of _){let $=E.trim();if($)D.push($)}return[...new Set(D)].join(",")}function D1(){switch(process.platform){case"darwin":return"MacOS";case"win32":return"Windows";case"linux":return"Linux";case"freebsd":return"FreeBSD";default:return"Unknown"}}function E1(){switch(process.arch){case"arm64":return"arm64";case"x64":return"x64";case"ia32":return"x32";default:return process.arch}}function G$(f,_,D={}){let E=D.identity??s_(_),m=[...(f.get("anthropic-beta")??"").split(",").map((M)=>M.trim()).filter(Boolean),...D.extraBetas??[]];return f.set("accept","application/json"),f.set("authorization",`Bearer ${_}`),f.set("content-type","application/json"),f.set("user-agent",S_),f.set("anthropic-beta",_1(D.body,m)),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",g_()),f.set("x-claude-code-session-id",E.sessionId),f.set("x-stainless-arch",E1()),f.set("x-stainless-lang","js"),f.set("x-stainless-os",D1()),f.set("x-stainless-package-version",b_),f.set("x-stainless-retry-count","0"),f.set("x-stainless-runtime","node"),f.set("x-stainless-runtime-version",N_),f.set("x-stainless-timeout","600"),f.delete("x-api-key"),f}var $1=["model","messages","system","tools","tool_choice","metadata","max_tokens","temperature","thinking","context_management","output_config","diagnostics","stream","speed"];function c_(f){let _={};for(let D of $1)if(Object.hasOwn(f,D))_[D]=f[D];for(let[D,E]of Object.entries(f))if(!Object.hasOwn(_,D))_[D]=E;return _}import{createHash as M1}from"node:crypto";var m1=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 t_(){return function(f){let{exports:{mem:_,xxh32:D,xxh64:E,init32:$,update32:m,digest32:M,init64:C,update64:L,digest64:O}}=f,U=new Uint8Array(_.buffer);function S(H,z){if(_.buffer.byteLength<H+z){let Xf=Math.ceil((H+z-_.buffer.byteLength)/65536);_.grow(Xf),U=new Uint8Array(_.buffer)}}function F(H,z,Xf,V0,I0,Q0){S(H);let t=new Uint8Array(H);return U.set(t),Xf(0,z),t.set(U.subarray(0,H)),{update(r){let Zf;return U.set(t),typeof r=="string"?(S(3*r.length,H),Zf=b.encodeInto(r,U.subarray(H)).written):(S(r.byteLength,H),U.set(r,H),Zf=r.byteLength),V0(0,H,Zf),t.set(U.subarray(0,H)),this},digest:()=>(U.set(t),Q0(I0(0)))}}function j(H){return H>>>0}let P=2n**64n-1n;function J(H){return H&P}let b=new TextEncoder,d=0,v=0n;function u(H,z=d){return S(3*H.length,0),j(D(0,b.encodeInto(H,U).written,z))}function Cf(H,z=v){return S(3*H.length,0),J(E(0,b.encodeInto(H,U).written,z))}return{h32:u,h32ToString:(H,z=d)=>u(H,z).toString(16).padStart(8,"0"),h32Raw:(H,z=d)=>(S(H.byteLength,0),U.set(H),j(D(0,H.byteLength,z))),create32:(H=d)=>F(48,H,$,m,M,j),h64:Cf,h64ToString:(H,z=v)=>Cf(H,z).toString(16).padStart(16,"0"),h64Raw:(H,z=v)=>(S(H.byteLength,0),U.set(H),J(E(0,H.byteLength,z))),create64:(H=v)=>F(88,H,C,L,O,J)}}((await WebAssembly.instantiate(m1)).instance)}var C1=0x6e52736ac806831en,L1="cch=00000;";var rf=/("system":\[\{"type":"text","text":"x-anthropic-billing-header: cc_version=[^;"]+; cc_entrypoint=[^;"]+; )cch=([0-9a-f]{5});/,O1=/("system":\[\{"type":"text","text":"x-anthropic-billing-header: cc_version=[^;"]+; cc_entrypoint=[^;"]+; )cch=00000;/,o_=null,uf=null;async function U1(){if(uf)return;o_??=(async()=>{uf=(await t_()).h64Raw})(),await o_}async function H1(f){return await U1(),((uf?.(f,C1)??0n)&0xfffffn).toString(16).padStart(5,"0")}function b1(f){return f.replace(rf,`$1${L1}`)}function e_(f){return rf.exec(f)?.[2]??null}async function a_(f){if(!rf.test(f))return f;let _=b1(f),D=await H1(new TextEncoder().encode(_));return _.replace(O1,`$1cch=${D};`)}function N1(f=R,_=new Date){if(f===R)return Qf;return M1("sha256").update(f).digest("hex").slice(0,3)}function h$(f,_=R,D,E=new Date){let $=N1(_,E);return`x-anthropic-billing-header: cc_version=${_}.${$}; cc_entrypoint=${D}; cch=00000;`}var q$="claude-cachekeep",sf=3600000,nf=300000,S1=60000,x$="extended-cache-ttl-2025-04-11",B1=32,f0=16777216,A1=2*sf,K1="## Claude Cache Keep Status",F1="## Claude Cache Keep Enabled",j1="## Claude Cache Keep Disabled",z1="## Claude Cache Keep Usage",G1="Usage: `/claude-cachekeep`, `/claude-cachekeep off`, or `/claude-cachekeep HH-HH`.";function Kf(f){return String(f).padStart(2,"0")}function J1(f){let _=f.trim();if(!_)return{type:"status"};if(_==="off")return{type:"disable"};let D=/^(\d{1,2})-(\d{1,2})$/.exec(_);if(!D)return{type:"usage"};let E=Number(D[1]),$=Number(D[2]);if(!Number.isInteger(E)||!Number.isInteger($)||E<0||E>23||$<0||$>23||E===$)return{type:"usage"};return{type:"window",startHour:E,endHour:$}}function cf(f){let _=Number(f?.cacheKeep?.startHour),D=Number(f?.cacheKeep?.endHour);if(!Number.isInteger(_)||!Number.isInteger(D)||_<0||_>23||D<0||D>23||_===D)return;return{startHour:_,endHour:D}}function E0(f){return f?.cacheKeep?.enabled===!0&&!!cf(f)}function W1(f){return E0(f)&&f?.claudeCache?.enabled===!0&&f.claudeCache.mode==="hybrid"}function _0(f,_=new Date){if(!f)return!1;let D=_.getHours();if(f.startHour<f.endHour)return D>=f.startHour&&D<f.endHour;return D>=f.startHour||D<f.endHour}function D0(f=new Date){return`${f.getFullYear()}-${Kf(f.getMonth()+1)}-${Kf(f.getDate())}`}function gf(f,_=new Date){if(f&&f.startHour>f.endHour&&_.getHours()<f.endHour){let D=new Date(_);return D.setDate(D.getDate()-1),D0(D)}return D0(_)}function Af(f){let _=f.window?`${Kf(f.window.startHour)}-${Kf(f.window.endHour)}`:"not configured",D=[`Cache keep: ${f.enabled?"enabled":"disabled"}`,`Window: ${_}`,"Mode requirement: `/claude-cache mode hybrid` must be active."];if(typeof f.hybridActive==="boolean")D.push(`Hybrid active: ${f.hybridActive?"yes":"no"}`);if(typeof f.trackedSessions==="number")D.push(`Tracked sessions: ${f.trackedSessions}`);if(f.nextPrewarmAt)D.push(`Next prewarm: ${new Date(f.nextPrewarmAt).toLocaleString()}`);return D.join(`
|
|
13
|
+
`)}function P$(f){let _=J1(f.argumentsText),D={enabled:f.enabled??!1,window:f.window,trackedSessions:f.trackedSessions,nextPrewarmAt:f.nextPrewarmAt,hybridActive:f.hybridActive};if(_.type==="status")return[K1,"",Af(D)].join(`
|
|
14
|
+
`);if(_.type==="disable")return[j1,"",Af({...D,enabled:!1})].join(`
|
|
15
|
+
`);if(_.type==="window")return[F1,"",Af({...D,enabled:!0,window:{startHour:_.startHour,endHour:_.endHour}})].join(`
|
|
16
|
+
`);return[z1,"",G1,"",Af(D)].join(`
|
|
17
|
+
`)}function tf(f){if(!f||typeof f!=="object")return!1;if(Array.isArray(f))return f.some(tf);let _=f,D=_.cache_control;if(D&&typeof D==="object"&&D.type==="ephemeral")return!0;return Object.values(_).some(tf)}async function Y1(f){let _;try{_=JSON.parse(f)}catch{return{ok:!1,reason:"body is not valid JSON"}}if(!tf(_))return{ok:!1,reason:"body has no explicit cache breakpoints"};let D=structuredClone(_);if(D.max_tokens=0,delete D.stream,D.thinking?.type==="enabled")delete D.thinking;if(D.output_config?.format)delete D.output_config;let m=D.tool_choice;if(m?.type==="tool"||m?.type==="any")delete D.tool_choice;return{ok:!0,bodyText:await a_(JSON.stringify(c_(D)))}}class X1{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)})})},S1),"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 D=gf(f,new Date(_)),E=[...this.targets.values()].filter((m)=>m.dayKey===D),$=E.length?Math.min(...E.map((m)=>m.cacheExpiresAt-nf)):void 0;return{trackedSessions:E.length,nextPrewarmAt:$}}trackedCount(){return this.targets.size}totalBodyBytes(){return[...this.targets.values()].reduce((f,_)=>f+_.bodyText.length,0)}evictOldestTarget(){let f=this.targets.keys().next().value;if(f!==void 0)this.targets.delete(f)}pruneTargets(f,_){for(let[D,E]of this.targets){if(_&&E.dayKey!==_){this.targets.delete(D);continue}if(f-E.cacheExpiresAt>A1)this.targets.delete(D)}while(this.targets.size>B1)this.evictOldestTarget();while(this.totalBodyBytes()>f0){let D=this.targets.size;if(this.evictOldestTarget(),this.targets.size===D)break}}track(f){if(!f.sessionId)return{tracked:!1,reason:"missing session id"};if(!E0(f.storage))return{tracked:!1,reason:"cachekeep disabled"};if(f.cacheMode!=="hybrid")return{tracked:!1,reason:"cache mode is not hybrid"};if(f.bodyText.length>f0)return{tracked:!1,reason:"body exceeds cachekeep memory budget"};let _=this.options.now?.()??Date.now(),D=cf(f.storage);if(!_0(D,new Date(_)))return{tracked:!1,reason:"outside configured window"};let E=gf(D,new Date(_));if(this.pruneTargets(_,E),this.targets.has(f.sessionId))this.targets.delete(f.sessionId);let $={};return f.headers.forEach((m,M)=>{$[M]=m}),this.targets.set(f.sessionId,{id:f.sessionId,url:f.url,headers:$,bodyText:f.bodyText,cacheExpiresAt:_+sf,dayKey:E}),this.pruneTargets(_,E),this.start(),{tracked:!0}}async tick(){let f=await this.options.loadStorage(),_=cf(f),D=this.options.now?.()??Date.now(),E=gf(_,new Date(D));if(this.pruneTargets(D,E),!this.targets.size){this.stop();return}if(!W1(f))return;if(!_0(_,new Date(D)))return;let $=D+nf;for(let m of this.targets.values()){if(m.cacheExpiresAt>$)continue;await this.prewarm(m,D)}}async prewarm(f,_){let D=await Y1(f.bodyText);if(!D.ok){this.options.log?.("[cachekeep] prewarm skipped",{session:f.id,reason:D.reason}),this.targets.delete(f.id);return}let E=this.options.fetchImpl??fetch,$={...f,bodyText:D.bodyText},m=this.options.prepareHeaders?await this.options.prepareHeaders(new Headers(f.headers),$):new Headers(f.headers);m.delete("content-length"),m.delete("transfer-encoding");let M=await E(f.url,{method:"POST",headers:m,body:D.bodyText});if(!M.ok){this.options.log?.("[cachekeep] prewarm failed",{session:f.id,status:M.status,body:await M.text().catch(()=>"")}),f.cacheExpiresAt=_+nf+300000;return}await M.body?.cancel().catch(()=>{}),f.cacheExpiresAt=_+sf,this.options.log?.("[cachekeep] prewarm succeeded",{session:f.id})}}import{createHash as Z1}from"node:crypto";import{mkdir as h1,writeFile as Ff}from"node:fs/promises";import{tmpdir as V1}from"node:os";import{join as M0}from"node:path";var p$="claude-dump",I1="## Claude Dump Status",Q1="## Claude Dump Enabled",q1="## Claude Dump Disabled",x1="## Claude Dump Usage",P1="Usage: `/claude-dump`, `/claude-dump on`, or `/claude-dump off`.",R1="OPENCODE_ANTHROPIC_AUTH_DUMP_DIR",T1=M0(V1(),"opencode-anthropic-auth-dumps"),mf=!1,$0=0,w1=100,s=new Map;function d$(f){mf=f}function C0(){return process.env[R1]||T1}function y1(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 jf(f){let _=f?.enabled??mf;return[I1,"",`- Enabled: ${_?"enabled":"disabled"}`,`- Directory: ${C0()}`,"- Persisted: ~/.config/opencode/anthropic-auth.json","- Captures: final rewritten Anthropic body in direct and relay modes; request/relay metadata is redacted","- Warning: body dumps may contain prompt/session content; turn this off after debugging"].join(`
|
|
18
|
+
`)}function v$(f){let _=y1(f.argumentsText),D=f.enabled??mf;if(_.type==="status")return jf({enabled:D});if(_.type==="enable")return[Q1,"",jf({enabled:!0})].join(`
|
|
19
|
+
`);if(_.type==="disable")return[q1,"",jf({enabled:!1})].join(`
|
|
20
|
+
`);return[x1,"",P1,"",jf({enabled:D})].join(`
|
|
21
|
+
`)}function m0(f){return f.length<=16?f:`${f.slice(0,12)}…`}function L0(f){let _=f.trim().replace(/[^a-zA-Z0-9._-]+/g,"-").replace(/^-+|-+$/g,"");if(!_)return"session-unknown";return _.length<=80?_:_.slice(0,80)}function l1(f){if(f.transport!=="direct")return`${f.transport}-p${f.protocol}-${f.mode}`;return`direct${f.route?`-${L0(f.route)}`:""}`}function i1(f){let _=f.affinity?.trim();if(_)return`session:${_}`;return`request:${f.route??"direct"}:${f.url??""}`}function k1(f,_){if(!s.has(f))while(s.size>=w1){let D=s.keys().next().value;if(D===void 0)break;s.delete(D)}s.set(f,_)}function p1(f){if(f==null)return;return Object.fromEntries(new Headers(f).entries())}function O0(f){return Z1("sha256").update(f).digest("hex")}function d1(f){return e_(f)}function v1(f,_){if(f==null)return null;if(f===_)return{changed:!1,firstByte:-1,lastPreviousByte:-1,lastCurrentByte:-1,previousBytes:f.length,currentBytes:_.length};let D=0;while(D<f.length&&D<_.length&&f[D]===_[D])D+=1;let E=f.length-1,$=_.length-1;while(E>=D&&$>=D&&f[E]===_[$])E-=1,$-=1;return{changed:!0,firstByte:D,lastPreviousByte:E,lastCurrentByte:$,changedPreviousBytes:E-D+1,changedCurrentBytes:$-D+1,previousBytes:f.length,currentBytes:_.length}}function u1(f){try{let _=JSON.parse(f);return _!=null&&typeof _==="object"&&!Array.isArray(_)?_:null}catch(_){return B(`dump body parse failed: ${_ instanceof Error?_.message:String(_)}`),null}}function of(f){return O0(JSON.stringify(f))}function r1(f){let _=u1(f);if(!_)return{parseable:!1};let D=Array.isArray(_.messages)?_.messages:[],E=Array.isArray(_.system)?_.system:[],$=D[0],m=D.slice(1);return{parseable:!0,model:typeof _.model==="string"?_.model:void 0,stream:_.stream,systemCount:E.length,messagesCount:D.length,systemHash:of(E),message0Hash:$===void 0?null:of($),message0Bytes:$===void 0?0:JSON.stringify($).length,messagesAfter0Hash:of(m),messagesAfter0Bytes:JSON.stringify(m).length,cch:d1(f)}}function zf(f){if(Array.isArray(f))return f.map(zf);if(f==null||typeof f!=="object")return f;let _={};for(let[D,E]of Object.entries(f)){let $=D.toLowerCase();if($==="authorization"||$==="x-api-key"||$==="cookie"||$==="set-cookie"){_[D]="[redacted]";continue}_[D]=zf(E)}return _}async function U0(f){if(!mf)return;$0+=1;let _=f.affinity?.trim()||"session-unknown",D=`${new Date().toISOString().replace(/[:.]/g,"-")}-${String($0).padStart(5,"0")}-${L0(_)}-${l1(f)}`,E=C0(),$=M0(E,D),m={body:`${$}.body.json`,metadata:`${$}.meta.json`};if(f.payload!==void 0)m.relay=`${$}.relay.json`;if(f.request!==void 0)m.request=`${$}.request.json`;try{await h1(E,{recursive:!0});let M={id:D,createdAt:new Date().toISOString(),session:m0(_),transport:f.transport,protocol:f.protocol,mode:f.mode,route:f.route,status:f.status,error:f.error,bodyBytes:f.bodyText.length,relayBytes:f.relayBytes,bodyHash:O0(f.bodyText),diff:v1(f.previousBodyText,f.bodyText),body:r1(f.bodyText),files:m},C=[Ff(m.body,f.bodyText,"utf8"),Ff(m.metadata,`${JSON.stringify(M,null,2)}
|
|
22
|
+
`,"utf8")];if(f.payload!==void 0&&m.relay)C.push(Ff(m.relay,`${JSON.stringify(zf(f.payload),null,2)}
|
|
23
|
+
`,"utf8"));if(f.request!==void 0&&m.request)C.push(Ff(m.request,`${JSON.stringify(zf({...f.request,headers:p1(f.request.headers)}),null,2)}
|
|
24
|
+
`,"utf8"));await Promise.all(C),B(`dumped request id=${D} session=${m0(_)} body=${m.body} meta=${m.metadata}`)}catch(M){B(`dump failed: ${M instanceof Error?M.message:String(M)}`)}}async function u$(f){if(!mf)return;let _=i1(f),D=s.get(_);await U0({affinity:f.affinity,transport:"direct",route:f.route,status:f.status,error:f.error,bodyText:f.bodyText,previousBodyText:D,request:{url:f.url,method:f.method,headers:f.headers}}),k1(_,f.bodyText)}async function H0(f){await U0({affinity:f.affinity,transport:f.transport,protocol:f.protocol,mode:f.mode,status:f.status,bodyText:f.bodyText,previousBodyText:f.previousBodyText,payload:f.payload,relayBytes:f.relayBytes})}var n$="claude-fast";var Jf=!1;function g$(){return Jf}function s$(f){Jf=f}function n1(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 Gf(f){return["## Claude Fast Mode Status","",`- Enabled: ${f?.enabled??Jf?"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(`
|
|
25
|
+
`)}function c$(f){let _=n1(f.argumentsText),D=f.enabled??Jf;if(_.type==="status")return Gf({enabled:D});if(_.type==="enable")return["## Claude Fast Mode Enabled","",Gf({enabled:!0})].join(`
|
|
26
|
+
`);if(_.type==="disable")return["## Claude Fast Mode Disabled","",Gf({enabled:!1})].join(`
|
|
27
|
+
`);return["## Claude Fast Mode Usage","","Usage: `/claude-fast`, `/claude-fast on`, or `/claude-fast off`.","",Gf({enabled:D})].join(`
|
|
28
|
+
`)}var Mf="claude-killswitch";function g1(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 D=[];for(let E=1;E<_.length;E++){let $=_[E]?.match(/^([^:]+):(\d+),(\d+)$/);if(!$)return{type:"usage"};let[,m,M,C]=$;D.push({account:m,fh:Number.parseInt(M,10),sd:Number.parseInt(C,10)})}if(D.length===0)return{type:"usage"};return{type:"set",entries:D}}return{type:"usage"}}function Wf(f,_){let D=f.enabled===!0,E=["## Killswitch","",`Status: **${D?"ON":"OFF"}**`];if(D){E.push(""),E.push("| Account | 5h threshold | 1w threshold |"),E.push("| ------- | ------------ | ------------ |");let $=f.main??{},m=$.five_hour??$["5h"]??h.five_hour,M=$.seven_day??$["1w"]??h.seven_day;E.push(`| main | ≥ ${m}% | ≥ ${M}% |`);for(let C of _){let L=f.accounts?.[C]??f.main??{},O=L.five_hour??L["5h"]??h.five_hour,U=L.seven_day??L["1w"]??h.seven_day;E.push(`| ${C} | ≥ ${O}% | ≥ ${U}% |`)}}return E.join(`
|
|
29
|
+
`)}var b0=["## Killswitch Commands","","```",`/${Mf} — show status`,`/${Mf} on — enable with current or default thresholds`,`/${Mf} off — disable`,`/${Mf} set all:5,10 — set all accounts to 5h≥5%, 1w≥10%`,`/${Mf} set main:3,8 work-alt:5,10 — per-account`,"```"].join(`
|
|
30
|
+
`);function e$(f){let _=g1(f.argumentsText);if(_.type==="status")return{text:`${Wf(f.config,f.accountIds)}
|
|
31
|
+
|
|
32
|
+
${b0}`};if(_.type==="on"){let E={...f.config,enabled:!0,main:f.config.main??{five_hour:h.five_hour,seven_day:h.seven_day}};return{text:`## Killswitch Enabled
|
|
33
|
+
|
|
34
|
+
${Wf(E,f.accountIds)}`,updatedConfig:E}}if(_.type==="off")return{text:"## Killswitch Disabled",updatedConfig:{...f.config,enabled:!1}};if(_.type==="set"){let E={...f.config.accounts??{}},$={...f.config,enabled:!0,accounts:E};for(let M of _.entries){let C={five_hour:M.fh,seven_day:M.sd};if(M.account==="main")$.main=C;else if(M.account==="all"){$.main=C;for(let L of f.accountIds)E[L]=C}else E[M.account]=C}return{text:`## Killswitch Updated
|
|
35
|
+
|
|
36
|
+
${Wf($,f.accountIds)}`,updatedConfig:$}}return{text:`${Wf(f.config,f.accountIds)}
|
|
37
|
+
|
|
38
|
+
${b0}`}}var s1=["claude-fable-5","claude-mythos-5"],fm={type:"adaptive",display:"summarized"},_m={input:10,output:50,cacheRead:1,cacheWrite5m:12.5,cacheWrite1h:20},Dm=1e6,Em=128000,$m="2026-06-09",mm={["claude-fable-5"]:{id:"claude-fable-5",name:"Claude Fable 5"},["claude-mythos-5"]:{id:"claude-mythos-5",name:"Claude Mythos 5",limited:!0}};function Mm(f){return typeof f==="string"&&s1.some((_)=>f===_||f.startsWith(`${_}-`))}function Cm(f){if(typeof f!=="string")return!1;if(f.startsWith("gAAAA"))return!0;if(!f.startsWith("{"))return!1;try{let _=JSON.parse(f);return _.type==="reasoning"&&typeof _.id==="string"&&_.id.startsWith("rs_")&&typeof _.encrypted_content==="string"&&_.encrypted_content.startsWith("gAAAA")}catch{return!1}}import{createHash as c1}from"node:crypto";var t1=globalThis.setTimeout;function I(f){return c1("sha256").update(f).digest("hex").slice(0,16)}class w{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,this.seedMainFromStorage(f.storage),this.seedMainBackoffFromStorage(f.storage)}getMain(f){if(f&&this.main&&this.mainTokenFp&&this.mainTokenFp!==I(f))this.main=null,this.mainTokenFp=null;return this.main}getFallback(f,_){let D=this.fallbacks.get(f)??null;if(!_||!D)return D;if(this.fallbackTokenFps.get(f)!==I(_))return this.fallbacks.delete(f),this.fallbackTokenFps.delete(f),null;return D}getAllFallbacks(){return this.fallbacks}setMain(f,_){this.mainTokenFp=I(f),this.main=_}setFallback(f,_,D){if(this.fallbacks.set(f,_),D)this.fallbackTokenFps.set(f,I(D));else this.fallbackTokenFps.delete(f)}async refreshMain(f){let _=I(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 D=w.fallbackInflightKey(f,_),E=this.inflightFallbacks.get(D);if(E)return E;if(this.isFallbackBackedOff(f,_)){let m=this.getFallback(f,_);if(m)return m.quota;throw Error("Quota API rate-limited — try again later")}let $=this._fetchFallback(f,_);return this.inflightFallbacks.set(D,$),$}async refreshAllFallbacks(f){let _=this.now();for(let D of f){if(D.enabled===!1)continue;if(!D.access)continue;let E=this.getFallback(D.id,D.access);if(E&&_<E.refreshAfter)continue;try{await this.refreshFallback(D.id,D.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 D=this.getFallback(f,_);if(!D)return!0;return this.now()>=D.refreshAfter}shouldRefreshOnRequestCount(f){let _=i_(this.storage);if(_<=0)return!1;return f>0&&f%_===0}needsRefresh(f){return this.isMainStale()||this.shouldRefreshOnRequestCount(f)}updateStorage(f){this.storage=f,this.seedMainFromStorage(f),this.seedMainBackoffFromStorage(f)}seedMainFromStorage(f,_){let D=l_(f);if(!D)return;let E=_?I(_):null;if(E&&D.tokenFingerprint&&D.tokenFingerprint!==E)return;let $={quota:D.quota,refreshAfter:df(D.quota,f,D.checkedAt),checkedAt:D.checkedAt};if(this.main&&this.main.checkedAt>=$.checkedAt&&(!E||!this.mainTokenFp||this.mainTokenFp===E))return;this.main=$,this.mainTokenFp=D.tokenFingerprint??null}seedMainBackoffFromStorage(f){let _=f?.quota?.mainLastQuotaApiError;this.mainLastApiError=_&&g(_,this.now())?_:void 0}seedFallbacksFromAccounts(f){let _=Z(this.storage);for(let D of f){if(D.enabled===!1)continue;if(!D.quota)continue;let E=Math.max(D.quota.five_hour?.checkedAt??0,D.quota.seven_day?.checkedAt??0);if(E<=0)continue;let $=this.getFallback(D.id,D.access);if($&&$.checkedAt>=E)continue;this.setFallback(D.id,{quota:D.quota,refreshAfter:E+_,checkedAt:E},D.access)}}isBackedOff(){return g(this.mainLastApiError,this.now())}isFallbackBackedOff(f,_){if(_){if(this.fallbackErrorTokenFps.get(f)!==I(_))return!1}return g(this.fallbackApiErrors.get(f),this.now())}getLastApiError(){return this.mainLastApiError}static API_CALL_GAP_MS=1000;static fallbackInflightKey(f,_){return JSON.stringify([f,I(_)])}static quotaLockName(f){return`opencode-fallback-quota-refresh-${f.replace(/[^a-zA-Z0-9._-]+/g,"-")||"account"}`}_enqueueApiFetch(f){let _=async()=>{let E=this.now()-this.lastApiCallAt;if(E<w.API_CALL_GAP_MS)await new Promise(($)=>{let m=t1($,w.API_CALL_GAP_MS-E);if(typeof m==="object"&&"unref"in m)m.unref()});return this.lastApiCallAt=this.now(),f()},D=this.apiGate.then(_,_);return this.apiGate=D.catch(()=>{}),D}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 Hf({name:"opencode-main-quota-refresh",ttlMs:30000});if(!_){let D=this.main;if(D&&this.now()<D.refreshAfter)return D.quota;throw Error("Quota refresh is already in progress")}try{let D=this.now(),E=await Nf({accessToken:f,fetchImpl:this.fetchImpl,now:this.now}),$=this.now();return this.mainTokenFp=I(f),this.main={quota:E,refreshAfter:df(E,this.storage,$),checkedAt:$},this.mainLastApiError=void 0,this.onMainQuotaFetched?.(E,$,this.mainTokenFp,D),E}catch(D){throw this._handleMainFetchError(D),D}finally{await _.release()}}finally{this.inflightMain=null}})}async _fetchFallback(f,_){return this._enqueueApiFetch(async()=>{try{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=await Hf({name:w.quotaLockName(f),ttlMs:30000});if(!D){let E=this.getFallback(f,_);if(E&&this.now()<E.refreshAfter)return E.quota;throw Error("Quota refresh is already in progress")}try{let E=await Nf({accessToken:_,fetchImpl:this.fetchImpl,now:this.now}),$=this.now();return this.setFallback(f,{quota:E,refreshAfter:$+Z(this.storage),checkedAt:$},_),this.fallbackApiErrors.delete(f),this.fallbackErrorTokenFps.delete(f),E}finally{await D.release()}}catch(D){throw this._handleFallbackFetchError(f,_,D),D}finally{this.inflightFallbacks.delete(w.fallbackInflightKey(f,_))}})}static isAuthError(f){let _=f instanceof Error?f.message:String(f);return/quota check failed: 401\b/.test(_)}_handleMainFetchError(f){if(w.isAuthError(f))return;this.mainLastApiError=bf({error:f,now:this.now(),previous:this.mainLastApiError}),this.onApiError?.(this.mainLastApiError)}_handleFallbackFetchError(f,_,D){if(w.isAuthError(D))return;let E=I(_),$=this.fallbackErrorTokenFps.get(f)===E?this.fallbackApiErrors.get(f):void 0;this.fallbackApiErrors.set(f,bf({error:D,now:this.now(),previous:$})),this.fallbackErrorTokenFps.set(f,E)}}var Nm="claude-quota",N0={five_hour:"5h",seven_day:"1w"};function S0(f){return`${Math.round(f*10)/10}%`}function ef(f,_){let D=Math.max(0,_-f),E=Math.floor(D/60000);if(E<1)return"just now";if(E===1)return"1m ago";if(E<60)return`${E}m ago`;let $=Math.floor(E/60),m=E%60;if(m===0)return`${$}h ago`;return`${$}h ${m}m ago`}function o1(f,_){let D=Date.parse(f);if(!Number.isFinite(D))return f;let E=D-_;if(E<=0)return"now";let $=Math.max(1,Math.ceil(E/60000));if($<60)return`in ${$}m`;let m=Math.floor($/60),M=$%60;if(M===0)return`in ${m}h`;return`in ${m}h ${M}m`}function e1(f,_){if(!f)return"";return`, resets ${o1(f,_)}`}function B0(f,_,D){if(!_)return` - ${N0[f]}: unknown`;return[` - ${N0[f]}: ${S0(_.remainingPercent)} remaining`,` (${S0(_.usedPercent)} used`,`${e1(_.resetsAt,D)}, checked ${ef(_.checkedAt,D)})`].join("")}function a1(f){return f.label?.trim()||f.id}function fE(f){return f.lastQuotaRefreshError?.message??f.lastRefreshError?.message}function Sm(f,_=new Map){if(!f?.accounts.length)return[];return f.accounts.filter(X).map((D)=>{let E=_.get(D.id)??fE(D);return{name:a1(D),role:"fallback",enabled:D.enabled!==!1,quota:D.quota,lastRefreshedAt:D.lastRefreshedAt,...E&&{error:E}}})}function Bm(f){let _=f.now??Date.now(),D=["## Claude Quotas",""];if(f.refreshedAt)D.push(`Refreshed: ${ef(f.refreshedAt,_)}`,"");if(!f.accounts.length)return D.push("No Claude OAuth accounts found yet."),D.join(`
|
|
39
|
+
`);for(let E of f.accounts){let $=E.role==="main"?"main":"fallback",m=E.enabled===!1?" disabled":"";if(D.push(`### ${E.name} (${$}${m})`),E.lastRefreshedAt)D.push(` - Last token refresh: ${ef(E.lastRefreshedAt,_)}`);if(E.error)D.push(` - Error: ${E.error}`);D.push(B0("five_hour",E.quota?.five_hour,_)),D.push(B0("seven_day",E.quota?.seven_day,_)),D.push("")}return D.join(`
|
|
40
|
+
`).trimEnd()}import{Buffer as W0}from"node:buffer";import{createHash as _E,randomBytes as DE}from"node:crypto";class f_ extends Error{}class __ extends Error{code="ECONNRESET";syscall="websocket";closeCode;closeReason;wasClean;constructor(f,_){super(f);this.name="RelayWebSocketConnectionResetError",this.closeCode=_?.code,this.closeReason=_?.reason,this.wasClean=_?.wasClean}}var x=new Map,p=new Map,A0=new Set,EE=7200000,$E=1800000,mE=128,ME=32,K0=0;function af(){return K0+=1,`req_${Date.now().toString(36)}_${K0.toString(36)}`}function Yf(f){if(A0.has(f))return;A0.add(f),B(f)}function Gm(f){let _=f?.relay;if(!_)return Yf("disabled: no relay config found"),null;if(_.enabled!==!0)return Yf("disabled: relay.enabled is not true"),null;if(!_.url?.trim()||!_.token?.trim())return Yf("disabled: missing relay url or token"),null;let D=_.transport==="http"?"http":"websocket";return Yf(`configured transport=${D} protocol=${D==="websocket"?2:1} url=${_.url.trim()} fallbackToDirect=${_.fallbackToDirect!==!1}`),{enabled:!0,url:_.url.trim(),token:_.token.trim(),fallbackToDirect:_.fallbackToDirect!==!1,transport:D}}function Jm(){return DE(32).toString("base64url")}function CE(f){return`sha256:${_E("sha256").update(f).digest("hex")}`}function F0(f,_){let D=0,E=Math.min(f.length,_.length);while(D<E&&f.charCodeAt(D)===_.charCodeAt(D))D++;let $=f.length,m=_.length;while($>D&&m>D&&f.charCodeAt($-1)===_.charCodeAt(m-1))$--,m--;return{start:D,deleteCount:$-D,insert:_.slice(D,m)}}function LE(f){return f.deleteCount===0&&f.insert.length===0}function j0(f){let _=f.match(/\bcch=([0-9a-f]{5});/),D=_?.[1];if(!D||_.index==null)return null;let E=_.index+4;return{start:E,end:E+D.length,token:D}}function OE(f,_,D,E){return`${f.slice(0,_)}${E}${f.slice(D)}`}function Y0(f,_){let D=j0(f),E=j0(_);if(D&&E&&D.start===E.start&&D.end-D.start===E.end-E.start&&D.token!==E.token){let $={start:D.start,deleteCount:D.end-D.start,insert:E.token},m=OE(f,D.start,D.end,E.token),M=F0(m,_);return LE(M)?$:[$,M]}return F0(f,_)}function UE(f,_){if(typeof _!=="string")return!1;try{let D=f instanceof Request?new URL(f.url):new URL(f.toString());return D.pathname==="/v1/messages"||D.pathname==="/messages"}catch{return!1}}function HE(f){let _={};for(let[D,E]of f.entries()){if(D==="x-session-affinity"||D==="x-opencode-session")continue;_[D]=E}return _}async function z0(f,_,D){let E=A(),$=JSON.stringify(_);return c("http_payload_stringify",{session:K(_.affinity),ms:Y(A()-E),relayBytes:$.length,mode:_.mode}),fetch(f.url,{method:"POST",headers:{"content-type":"application/json","x-relay-token":f.token},body:$,signal:D??void 0})}function K(f){return f.length>12?`${f.slice(0,12)}…`:f}function A(){return performance.now()}function Y(f){return Math.round(f*10)/10}function bE(){return process.env.OPENCODE_ANTHROPIC_AUTH_PERF==="1"}function c(f,_){if(!bE())return;B(`[perf] relay ${f} ${JSON.stringify(_)}`)}function NE(f){let{input:_,init:D,headers:E,bodyText:$,affinity:m,previous:M,nextHash:C}=f,L=_ instanceof Request?_.url:_.toString(),O={protocol:1,type:"request",affinity:m,upstream:{url:L,method:D?.method||(_ instanceof Request?_.method:"POST"),headers:HE(E)},next_hash:C};return M?{...O,mode:"patch",base_hash:M.hash,revision:M.revision+1,patch:Y0(M.body,$)}:{...O,mode:"full_sync",revision:1,body:$}}function D_(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 X0(f,_,D,E){let $=Date.now();x.delete(f),x.set(f,{body:_,hash:D,revision:E,updatedAt:$}),E_($)}async function G0(f){let{config:_,payload:D,bodyText:E,fallback:$,signal:m}=f,M=D,C=await z0(_,M,m);if(C.status===409&&M.mode==="patch")B(`state mismatch from relay session=${K(M.affinity)}; retrying full_sync`),await C.body?.cancel().catch(()=>{}),M=D_(M,E),C=await z0(_,M,m);if(!C.ok&&C.status>=500&&_.fallbackToDirect)return B(`relay returned ${C.status}; falling back direct session=${K(M.affinity)}`),await C.body?.cancel().catch(()=>{}),{response:await $(),payload:M,transport:"http",protocol:M.protocol,usedRelay:!1};return{response:C,payload:M,transport:"http",protocol:M.protocol,usedRelay:!0}}function SE(f,_){let D=new URL(f);return D.protocol=D.protocol==="http:"?"ws:":"wss:",D.pathname="/ws",D.searchParams.set("token",_),D.toString()}function BE(f){return new Uint8Array(W0.from(f,"base64"))}function AE(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(W0.from(String(f)))}function KE(f){return JSON.parse(f)}function J0(f){let _=f,D=[`code=${_.code??"unknown"}`,`wasClean=${_.wasClean??"unknown"}`];if(_.reason)D.push(`reason=${JSON.stringify(_.reason)}`);return D.join(" ")}function FE(f){let _=f.message||"relay websocket error";return f.status?`relay websocket error ${f.status}: ${_}`:_}class Z0{config;affinity;socket;connecting;queue=Promise.resolve();pending;serverState;lastUsedAt=Date.now();constructor(f,_){this.config=f,this.affinity=_}touch(f=Date.now()){this.lastUsedAt=f}canEvict(f=Date.now()){return!this.pending&&!this.connecting&&f-this.lastUsedAt>$E}dispose(){this.socket?.close(),this.socket=void 0,this.serverState=void 0,this.connecting=void 0}send(f,_,D=!1){this.touch();let E=A(),$=this.queue.catch(()=>{}).then(()=>this.startQueued(f,_,E,D)),m=$.then(async({response:M,getPayload:C})=>({response:await M,payload:C(),transport:"websocket",protocol:2,usedRelay:!0}));return this.queue=$.then(({done:M})=>M.catch(()=>{}),()=>{}),m}async startQueued(f,_,D,E){let $=A();await this.ensureConnected();let m=A(),M=x.get(this.affinity),C=this.serverState?.hash,L={...f,protocol:2,id:af()};if(L.mode==="patch"&&(!C||C!==L.base_hash))L.mode="full_sync",L.revision=(this.serverState?.revision??0)+1,delete L.base_hash,delete L.patch,L.body=_;if(L.mode==="patch"&&M)L.patch=Y0(M.body,_);B(`perf websocket send_start session=${K(this.affinity)} request=${L.id} mode=${L.mode} queueMs=${Y(m-D)} connectMs=${Y(m-$)} bodyBytes=${_.length} relayBytes=${JSON.stringify(L).length}`);let O=L,U=this.sendPayload(L,_,E);U.done.catch(()=>{});let S=U.done,F=U.response.catch((P)=>{if(!(P instanceof f_)||L.mode!=="patch")throw P;let J=D_(L,_);J.protocol=2,J.id=af(),J.revision=(this.serverState?.revision??0)+1,O=J;let b=this.sendPayload(J,_,E);return b.done.catch(()=>{}),S=b.done,b.response}),j=F.then(()=>S,()=>S.catch(()=>{}));return{response:F,done:j,getPayload:()=>O}}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 D=SE(this.config.url,this.config.token),E=new URL(D);E.searchParams.set("affinity",this.affinity);let $=new WebSocket(E.toString());this.socket=$,this.serverState=void 0;let m=setTimeout(()=>{$.close(),_(Error("relay websocket ready timed out"))},15000);$.addEventListener("message",(M)=>{try{if(typeof M.data!=="string"){this.handleBinaryChunk(M.data);return}let C=KE(M.data);if(C.type==="ready"){clearTimeout(m),this.serverState=C.state,f();return}this.handleMessage(C)}catch(C){clearTimeout(m),_(C),this.failPending(C),$.close()}}),$.addEventListener("error",()=>{clearTimeout(m);let M=new __("relay websocket error");_(M),this.failPending(M)}),$.addEventListener("close",(M)=>{if(clearTimeout(m),this.socket===$)this.socket=void 0,this.serverState=void 0,this.connecting=void 0;if(this.pending){if(this.pending.retryingBeforeResponse)return;let C=this.pending.responseStartedAt!=null,L=C?"closed after response_start before stream bytes":"closed before response";if(this.retryPendingBeforeResponse(this.pending,L,M))return;let O=C?new __("relay websocket closed during response stream",M):Error("relay websocket closed before response");B(`websocket ${C?"closed during response stream":"closed before response without retry"} session=${K(this.affinity)} request=${this.pending.payload.id} chunks=${this.pending.streamChunkCount} bytes=${this.pending.streamByteCount} ${J0(M)}`),this.failPending(O)}})}).finally(()=>{this.connecting=void 0}),await this.connecting}sendPayload(f,_,D){let E=this.socket;if(!E||E.readyState!==WebSocket.OPEN)throw Error("relay websocket is not connected");let $=A(),m,M,C=new Promise((O,U)=>{m=O,M=U});return{response:new Promise((O,U)=>{let S={payload:f,bodyText:_,resolve:O,reject:U,streamDone:!1,accepted:!1,responseStarted:!1,resolveDone:m,rejectDone:M,sentAt:$,optimisticResponse:D,streamChunkCount:0,streamByteCount:0,retryAttempts:0,retryingBeforeResponse:!1};if(this.pending=S,this.resetPendingTimeout(S),E.send(JSON.stringify(f)),D)this.resolvePendingResponse(S,200,"OK",{"content-type":"text/event-stream","x-cortexkit-relay-optimistic":"true"})}),done:C}}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,_,D){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 E=f.retryAttempts,$=f.payload.id;return B(`websocket ${_}; reconnecting and retrying full_sync session=${K(this.affinity)} request=${$} retry=${E} chunks=${f.streamChunkCount} bytes=${f.streamByteCount}${D?` ${J0(D)}`:""}`),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 m=D_(f.payload,f.bodyText);m.protocol=2,m.id=af(),m.revision=(this.serverState?.revision??0)+1,f.payload=m,f.accepted=!1,f.acceptedAt=void 0,f.responseStartedAt=void 0,f.sentAt=A(),f.retryingBeforeResponse=!1;let M=this.socket;if(!M||M.readyState!==WebSocket.OPEN)throw Error("relay websocket is not connected");this.resetPendingTimeout(f),B(`perf websocket retry_send session=${K(this.affinity)} request=${m.id} previous=${$} mode=full_sync retry=${E} bodyBytes=${f.bodyText.length} relayBytes=${JSON.stringify(m).length}`),M.send(JSON.stringify(m))}catch(m){if(f.retryingBeforeResponse=!1,this.pending===f)this.failPending(m)}})(),!0}enqueueStreamChunk(f,_){f.streamChunkCount+=1,f.streamByteCount+=_.byteLength,f.streamController?.enqueue(_)}handleBinaryChunk(f){let _=this.pending;if(!_?.responseStarted)return;this.enqueueStreamChunk(_,AE(f))}resolvePendingResponse(f,_,D,E){if(f.responseStarted)return;f.responseStarted=!0;let $=new ReadableStream({start:(m)=>{f.streamController=m},cancel:()=>{this.socket?.close()}});f.resolve(new Response($,{status:_,statusText:D,headers:E}))}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 D=A();_.accepted=!0,_.acceptedAt=D,B(`perf websocket accepted session=${K(this.affinity)} request=${_.payload.id} sentMs=${Y(D-_.sentAt)} mode=${_.payload.mode}`),this.serverState={hash:f.hash,revision:f.revision},X0(this.affinity,_.bodyText,f.hash,f.revision),this.resetPendingTimeout(_);return}if(f.type==="response_start"){let D=A();if(_.responseStartedAt=D,B(`perf websocket response_start session=${K(this.affinity)} request=${_.payload.id} sentMs=${Y(D-_.sentAt)} upstreamMs=${_.acceptedAt==null?"unknown":Y(D-_.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
|
|
41
|
+
data: ${JSON.stringify({type:"error",error:{type:"relay_upstream_error",message:`Relay upstream returned HTTP ${f.status}`}})}
|
|
42
|
+
|
|
43
|
+
`)),this.finishPending();return}if(f.type==="chunk"){this.enqueueStreamChunk(_,BE(f.base64));return}if(f.type==="done"){this.finishPending(f);return}if(f.type==="error"){if(_.optimisticResponse&&_.responseStartedAt!=null){B(`websocket relay error during optimistic response session=${K(this.affinity)} request=${_.payload.id} status=${f.status} message=${f.message||"unknown"} chunks=${_.streamChunkCount} bytes=${_.streamByteCount}`),_.streamController?.enqueue(new TextEncoder().encode(`event: error
|
|
44
|
+
data: ${JSON.stringify({type:"error",error:{type:"relay_error",message:f.message||"relay error"}})}
|
|
45
|
+
|
|
46
|
+
`)),this.finishPending(),this.socket?.close();return}if(f.status===409&&this.retryPendingBeforeResponse(_,f.message||"state mismatch"))return;let D=f.status===409?new f_(f.message||"state mismatch"):Error(FE(f));this.failPending(D)}}finishPending(f){let _=this.pending;if(!_)return;let D=A(),E=f&&"frames"in f?` upstreamChunks=${f.upstreamChunks??"unknown"} upstreamBytes=${f.upstreamBytes??"unknown"} frames=${f.frames} frameBytes=${f.frameBytes??"unknown"}`:"";if(B(`perf websocket done session=${K(this.affinity)} request=${_.payload.id} sentMs=${Y(D-_.sentAt)} streamMs=${_.responseStartedAt==null?"unknown":Y(D-_.responseStartedAt)} chunks=${_.streamChunkCount} bytes=${_.streamByteCount}${E}`),clearTimeout(_.timeout),!_.streamDone)_.streamDone=!0,_.streamController?.close();_.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 E_(f=Date.now()){for(let[_,D]of x)if(f-D.updatedAt>EE)x.delete(_);while(x.size>mE){let _=x.keys().next().value;if(_===void 0)break;x.delete(_)}for(let[_,D]of p)if(D.canEvict(f))D.dispose(),p.delete(_);while(p.size>ME){let _=!1;for(let[D,E]of p){if(!E.canEvict(f))continue;E.dispose(),p.delete(D),_=!0;break}if(!_)break}}function jE(f,_){E_();let D=p.get(_);if(D)return D.touch(),D;let E=new Z0(f,_);return p.set(_,E),E_(),E}async function Wm(f){let{config:_,input:D,init:E,headers:$,body:m,fallback:M,affinity:C,optimisticResponse:L}=f;if(!_||!UE(D,m))return M();let O=C||$.get("x-session-affinity")||$.get("x-opencode-session");if(!O)return B("skipping relay: missing x-session-affinity header"),M();let U=m,S=A(),F=CE(U);c("hash_body",{session:K(O),ms:Y(A()-S),bodyBytes:U.length});let j=x.get(O),P=A(),J=NE({input:D,init:E,headers:$,bodyText:U,affinity:O,previous:j,nextHash:F});c("create_payload",{session:K(O),ms:Y(A()-P),mode:J.mode,bodyBytes:U.length,previousBytes:j?.body.length});try{let b,d=A();if(_.transport==="websocket")try{b=await jE(_,O).send(J,U,L===!0)}catch(H){B(`websocket relay failed session=${K(O)}; trying http relay: ${H instanceof Error?H.message:String(H)}`),b=await G0({config:_,payload:J,bodyText:U,fallback:M,signal:E?.signal})}else b=await G0({config:_,payload:J,bodyText:U,fallback:M,signal:E?.signal});if(c("send",{session:K(O),ms:Y(A()-d),transport:b.transport,protocol:b.protocol,mode:b.payload.mode,status:b.response.status,usedRelay:b.usedRelay}),!b.usedRelay)return b.response;if(b.transport==="http")X0(O,U,b.payload.next_hash,b.payload.revision);let v=A(),u=JSON.stringify(b.payload).length;c("payload_stringify",{session:K(O),ms:Y(A()-v),relayBytes:u}),B(`used relay transport=${b.transport} protocol=${b.protocol} mode=${b.payload.mode} status=${b.response.status} session=${K(O)} bodyBytes=${U.length} relayBytes=${u}`);let Cf=A();return await H0({affinity:O,transport:b.transport,protocol:b.protocol,mode:b.payload.mode,status:b.response.status,bodyText:U,previousBodyText:j?.body,payload:b.payload,relayBytes:u}),c("dump",{session:K(O),ms:Y(A()-Cf),enabled:!0}),b.response}catch(b){if(!_.fallbackToDirect)throw B(`relay failed session=${K(O)} and fallbackToDirect=false: ${b instanceof Error?b.message:String(b)}`),b;return B(`relay failed; falling back direct session=${K(O)}: ${b instanceof Error?b.message:String(b)}`),M()}}var Ym=`
|
|
47
|
+
async function hashBody(body) {
|
|
48
|
+
const bytes = new TextEncoder().encode(body)
|
|
49
|
+
const digest = await crypto.subtle.digest('SHA-256', bytes)
|
|
50
|
+
const hex = [...new Uint8Array(digest)].map((b) => b.toString(16).padStart(2, '0')).join('')
|
|
51
|
+
return 'sha256:' + hex
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function applyPatch(base, patch) {
|
|
55
|
+
return base.slice(0, patch.start) + patch.insert + base.slice(patch.start + patch.deleteCount)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function applyPatchSet(base, patch) {
|
|
59
|
+
if (!Array.isArray(patch)) return applyPatch(base, patch)
|
|
60
|
+
if (patch.length === 0) return base
|
|
61
|
+
|
|
62
|
+
let result = ''
|
|
63
|
+
let cursor = 0
|
|
64
|
+
for (const item of patch) {
|
|
65
|
+
if (item.start < cursor) return { error: 'overlapping patch', status: 400 }
|
|
66
|
+
result += base.slice(cursor, item.start)
|
|
67
|
+
result += item.insert
|
|
68
|
+
cursor = item.start + item.deleteCount
|
|
69
|
+
}
|
|
70
|
+
return result + base.slice(cursor)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
async function readState(env, affinity) {
|
|
74
|
+
const raw = await env.RELAY_STATE.get('session:' + affinity)
|
|
75
|
+
return raw ? JSON.parse(raw) : null
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async function writeState(env, affinity, state) {
|
|
79
|
+
await env.RELAY_STATE.put('session:' + affinity, JSON.stringify(state), { expirationTtl: 86400 })
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async function resolveBody(env, payload) {
|
|
83
|
+
if (payload.mode === 'full_sync') return payload.body
|
|
84
|
+
if (payload.mode === 'patch') {
|
|
85
|
+
const state = await readState(env, payload.affinity)
|
|
86
|
+
if (!state || state.hash !== payload.base_hash) {
|
|
87
|
+
return { error: 'state mismatch', status: 409 }
|
|
88
|
+
}
|
|
89
|
+
return applyPatchSet(state.body, payload.patch)
|
|
90
|
+
}
|
|
91
|
+
return { error: 'unknown mode', status: 400 }
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async function prepareUpstream(env, payload) {
|
|
95
|
+
if ((payload.protocol !== 1 && payload.protocol !== 2) || payload.type !== 'request' || !payload.affinity || !payload.upstream?.url || !payload.next_hash) {
|
|
96
|
+
return { error: 'invalid payload', status: 400 }
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const body = await resolveBody(env, payload)
|
|
100
|
+
if (body && typeof body === 'object' && 'error' in body) return body
|
|
101
|
+
|
|
102
|
+
if (typeof body !== 'string' || (await hashBody(body)) !== payload.next_hash) {
|
|
103
|
+
return { error: 'hash mismatch', status: 409 }
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const stateWrite = writeState(env, payload.affinity, { body, hash: payload.next_hash, revision: payload.revision }).catch(() => {})
|
|
107
|
+
console.log(JSON.stringify({
|
|
108
|
+
relay: 'opencode-anthropic-auth',
|
|
109
|
+
transport: 'relay',
|
|
110
|
+
mode: payload.mode,
|
|
111
|
+
revision: payload.revision,
|
|
112
|
+
affinity: String(payload.affinity).slice(0, 12),
|
|
113
|
+
bodyBytes: body.length,
|
|
114
|
+
}))
|
|
115
|
+
|
|
116
|
+
return { body, stateWrite }
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function resolveBodyFromState(state, payload) {
|
|
120
|
+
if (payload.mode === 'full_sync') return payload.body
|
|
121
|
+
if (payload.mode === 'patch') {
|
|
122
|
+
if (!state || state.hash !== payload.base_hash) {
|
|
123
|
+
return { error: 'state mismatch', status: 409 }
|
|
124
|
+
}
|
|
125
|
+
return applyPatchSet(state.body, payload.patch)
|
|
126
|
+
}
|
|
127
|
+
return { error: 'unknown mode', status: 400 }
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function deferWorkerTask(task) {
|
|
131
|
+
return new Promise((resolve) => setTimeout(resolve, 0)).then(task)
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const WEBSOCKET_STREAM_FLUSH_BYTES = 1024
|
|
135
|
+
const WEBSOCKET_STREAM_FLUSH_MS = 20
|
|
136
|
+
|
|
137
|
+
function createWebSocketStreamCoalescer(socket, options = {}) {
|
|
138
|
+
const flushBytes = options.flushBytes || WEBSOCKET_STREAM_FLUSH_BYTES
|
|
139
|
+
const flushMs = options.flushMs ?? WEBSOCKET_STREAM_FLUSH_MS
|
|
140
|
+
let chunks = []
|
|
141
|
+
let byteLength = 0
|
|
142
|
+
let flushTimer = null
|
|
143
|
+
const stats = {
|
|
144
|
+
upstreamChunks: 0,
|
|
145
|
+
upstreamBytes: 0,
|
|
146
|
+
frames: 0,
|
|
147
|
+
frameBytes: 0,
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const clearFlushTimer = () => {
|
|
151
|
+
if (flushTimer === null) return
|
|
152
|
+
clearTimeout(flushTimer)
|
|
153
|
+
flushTimer = null
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const mergeChunks = () => {
|
|
157
|
+
if (chunks.length === 1) return chunks[0]
|
|
158
|
+
const frame = new Uint8Array(byteLength)
|
|
159
|
+
let offset = 0
|
|
160
|
+
for (const chunk of chunks) {
|
|
161
|
+
frame.set(chunk, offset)
|
|
162
|
+
offset += chunk.byteLength
|
|
163
|
+
}
|
|
164
|
+
return frame
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const flush = () => {
|
|
168
|
+
clearFlushTimer()
|
|
169
|
+
if (byteLength === 0) return
|
|
170
|
+
const frame = mergeChunks()
|
|
171
|
+
chunks = []
|
|
172
|
+
byteLength = 0
|
|
173
|
+
socket.send(frame)
|
|
174
|
+
stats.frames += 1
|
|
175
|
+
stats.frameBytes += frame.byteLength
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const scheduleFlush = () => {
|
|
179
|
+
if (flushTimer !== null) return
|
|
180
|
+
flushTimer = setTimeout(flush, flushMs)
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return {
|
|
184
|
+
push(value) {
|
|
185
|
+
const chunk = value instanceof Uint8Array ? value : new Uint8Array(value)
|
|
186
|
+
if (chunk.byteLength === 0) return
|
|
187
|
+
stats.upstreamChunks += 1
|
|
188
|
+
stats.upstreamBytes += chunk.byteLength
|
|
189
|
+
chunks.push(chunk)
|
|
190
|
+
byteLength += chunk.byteLength
|
|
191
|
+
if (byteLength >= flushBytes) flush()
|
|
192
|
+
else scheduleFlush()
|
|
193
|
+
},
|
|
194
|
+
flush,
|
|
195
|
+
stats() {
|
|
196
|
+
return { ...stats, pendingBytes: byteLength }
|
|
197
|
+
},
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function checkpointWebSocketState(env, payload, body, nextState) {
|
|
202
|
+
return deferWorkerTask(async () => {
|
|
203
|
+
try {
|
|
204
|
+
if ((await hashBody(body)) !== payload.next_hash) {
|
|
205
|
+
throw new Error('hash mismatch')
|
|
206
|
+
}
|
|
207
|
+
await writeState(env, payload.affinity, nextState)
|
|
208
|
+
} catch (error) {
|
|
209
|
+
console.log(JSON.stringify({
|
|
210
|
+
relay: 'opencode-anthropic-auth',
|
|
211
|
+
transport: 'websocket',
|
|
212
|
+
event: 'checkpoint_write_failed',
|
|
213
|
+
affinity: String(payload.affinity).slice(0, 12),
|
|
214
|
+
message: error instanceof Error ? error.message : String(error),
|
|
215
|
+
}))
|
|
216
|
+
}
|
|
217
|
+
})
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
async function prepareWebSocketUpstream(env, state, payload) {
|
|
221
|
+
if (payload.protocol !== 2 || payload.type !== 'request' || !payload.id || !payload.affinity || !payload.upstream?.url || !payload.next_hash) {
|
|
222
|
+
return { error: 'invalid payload', status: 400 }
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const body = resolveBodyFromState(state, payload)
|
|
226
|
+
if (body && typeof body === 'object' && 'error' in body) return body
|
|
227
|
+
if (typeof body !== 'string') return { error: 'invalid body', status: 400 }
|
|
228
|
+
if ((await hashBody(body)) !== payload.next_hash) {
|
|
229
|
+
return { error: 'hash mismatch', status: 409 }
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
const nextState = { body, hash: payload.next_hash, revision: payload.revision }
|
|
233
|
+
const checkpoint = checkpointWebSocketState(env, payload, body, nextState)
|
|
234
|
+
const logAccepted = () => console.log(JSON.stringify({
|
|
235
|
+
relay: 'opencode-anthropic-auth',
|
|
236
|
+
transport: 'websocket',
|
|
237
|
+
mode: payload.mode,
|
|
238
|
+
revision: payload.revision,
|
|
239
|
+
affinity: String(payload.affinity).slice(0, 12),
|
|
240
|
+
bodyBytes: body.length,
|
|
241
|
+
}))
|
|
242
|
+
|
|
243
|
+
return { body, state: nextState, checkpoint, logAccepted }
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
function headersToObject(headers) {
|
|
247
|
+
const result = {}
|
|
248
|
+
for (const [key, value] of headers.entries()) result[key] = value
|
|
249
|
+
return result
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
async function handleRelayPayload(env, payload) {
|
|
253
|
+
const prepared = await prepareUpstream(env, payload)
|
|
254
|
+
if (prepared.error) return prepared
|
|
255
|
+
const upstream = await fetch(payload.upstream.url, {
|
|
256
|
+
method: payload.upstream.method || 'POST',
|
|
257
|
+
headers: payload.upstream.headers,
|
|
258
|
+
body: prepared.body,
|
|
259
|
+
})
|
|
260
|
+
return { upstream, stateWrite: prepared.stateWrite }
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
async function handleWebSocket(socket, env, ctx, payload, getState, setState) {
|
|
264
|
+
const heartbeat = setInterval(() => {
|
|
265
|
+
try {
|
|
266
|
+
socket.send(JSON.stringify({ protocol: 2, type: 'keepalive' }))
|
|
267
|
+
} catch {
|
|
268
|
+
clearInterval(heartbeat)
|
|
269
|
+
}
|
|
270
|
+
}, 15000)
|
|
271
|
+
let streamCoalescer = null
|
|
272
|
+
try {
|
|
273
|
+
const result = await prepareWebSocketUpstream(env, getState(), payload)
|
|
274
|
+
if (result.error) {
|
|
275
|
+
socket.send(JSON.stringify({ protocol: 2, type: 'error', id: payload.id, status: result.status, message: result.error }))
|
|
276
|
+
return
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
setState(result.state)
|
|
280
|
+
socket.send(JSON.stringify({ protocol: 2, type: 'accepted', id: payload.id, hash: result.state.hash, revision: result.state.revision }))
|
|
281
|
+
ctx?.waitUntil?.(deferWorkerTask(result.logAccepted))
|
|
282
|
+
|
|
283
|
+
const upstreamPromise = fetch(payload.upstream.url, {
|
|
284
|
+
method: payload.upstream.method || 'POST',
|
|
285
|
+
headers: payload.upstream.headers,
|
|
286
|
+
body: result.body,
|
|
287
|
+
})
|
|
288
|
+
ctx?.waitUntil?.(result.checkpoint)
|
|
289
|
+
const upstream = await upstreamPromise
|
|
290
|
+
socket.send(JSON.stringify({
|
|
291
|
+
protocol: 2,
|
|
292
|
+
type: 'response_start',
|
|
293
|
+
id: payload.id,
|
|
294
|
+
status: upstream.status,
|
|
295
|
+
statusText: upstream.statusText,
|
|
296
|
+
headers: headersToObject(upstream.headers),
|
|
297
|
+
}))
|
|
298
|
+
|
|
299
|
+
const reader = upstream.body?.getReader()
|
|
300
|
+
if (reader) {
|
|
301
|
+
streamCoalescer = createWebSocketStreamCoalescer(socket)
|
|
302
|
+
while (true) {
|
|
303
|
+
const { done, value } = await reader.read()
|
|
304
|
+
if (done) break
|
|
305
|
+
streamCoalescer.push(value)
|
|
306
|
+
}
|
|
307
|
+
streamCoalescer.flush()
|
|
308
|
+
}
|
|
309
|
+
const stats = streamCoalescer?.stats?.() || {}
|
|
310
|
+
socket.send(JSON.stringify({ protocol: 2, type: 'done', id: payload.id, ...stats }))
|
|
311
|
+
} catch (error) {
|
|
312
|
+
try {
|
|
313
|
+
streamCoalescer?.flush?.()
|
|
314
|
+
} catch {}
|
|
315
|
+
socket.send(JSON.stringify({ protocol: 2, type: 'error', id: payload.id, status: 500, message: error instanceof Error ? error.message : String(error) }))
|
|
316
|
+
} finally {
|
|
317
|
+
clearInterval(heartbeat)
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
export default {
|
|
322
|
+
async fetch(request, env, ctx) {
|
|
323
|
+
if (request.headers.get('Upgrade') === 'websocket') {
|
|
324
|
+
const url = new URL(request.url)
|
|
325
|
+
const token = url.searchParams.get('token')
|
|
326
|
+
const affinity = url.searchParams.get('affinity')
|
|
327
|
+
if (token !== env.RELAY_TOKEN) return new Response('unauthorized', { status: 401 })
|
|
328
|
+
if (!affinity) return new Response('missing affinity', { status: 400 })
|
|
329
|
+
const pair = new WebSocketPair()
|
|
330
|
+
const client = pair[0]
|
|
331
|
+
const server = pair[1]
|
|
332
|
+
server.binaryType = 'arraybuffer'
|
|
333
|
+
let state = null
|
|
334
|
+
let ready = false
|
|
335
|
+
server.accept()
|
|
336
|
+
const loadState = readState(env, affinity).then((loadedState) => {
|
|
337
|
+
state = loadedState
|
|
338
|
+
ready = true
|
|
339
|
+
server.send(JSON.stringify({
|
|
340
|
+
protocol: 2,
|
|
341
|
+
type: 'ready',
|
|
342
|
+
state: state ? { hash: state.hash, revision: state.revision } : null,
|
|
343
|
+
}))
|
|
344
|
+
}).catch((error) => {
|
|
345
|
+
server.send(JSON.stringify({ protocol: 2, type: 'error', status: 500, message: error instanceof Error ? error.message : String(error) }))
|
|
346
|
+
server.close(1011, 'state load failed')
|
|
347
|
+
})
|
|
348
|
+
ctx?.waitUntil?.(loadState)
|
|
349
|
+
if (!ctx?.waitUntil) void loadState
|
|
350
|
+
let busy = false
|
|
351
|
+
server.addEventListener('message', (event) => {
|
|
352
|
+
if (!ready) {
|
|
353
|
+
server.send(JSON.stringify({ protocol: 2, type: 'error', status: 425, message: 'relay state is not ready' }))
|
|
354
|
+
return
|
|
355
|
+
}
|
|
356
|
+
if (busy) {
|
|
357
|
+
server.send(JSON.stringify({ protocol: 2, type: 'error', status: 429, message: 'request already in flight' }))
|
|
358
|
+
return
|
|
359
|
+
}
|
|
360
|
+
let payload
|
|
361
|
+
try {
|
|
362
|
+
payload = JSON.parse(event.data)
|
|
363
|
+
} catch {
|
|
364
|
+
server.send(JSON.stringify({ protocol: 2, type: 'error', status: 400, message: 'invalid JSON payload' }))
|
|
365
|
+
return
|
|
366
|
+
}
|
|
367
|
+
payload.affinity = affinity
|
|
368
|
+
busy = true
|
|
369
|
+
const run = handleWebSocket(server, env, ctx, payload, () => state, (nextState) => { state = nextState }).finally(() => { busy = false })
|
|
370
|
+
ctx?.waitUntil?.(run)
|
|
371
|
+
if (!ctx?.waitUntil) void run
|
|
372
|
+
})
|
|
373
|
+
return new Response(null, { status: 101, webSocket: client })
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
if (request.method === 'GET') {
|
|
377
|
+
return Response.json({ status: 'ok', transports: ['http', 'websocket'] })
|
|
378
|
+
}
|
|
379
|
+
if (request.method !== 'POST') return new Response('method not allowed', { status: 405 })
|
|
380
|
+
if (request.headers.get('x-relay-token') !== env.RELAY_TOKEN) {
|
|
381
|
+
return new Response('unauthorized', { status: 401 })
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
try {
|
|
385
|
+
const payload = await request.json()
|
|
386
|
+
const result = await handleRelayPayload(env, payload)
|
|
387
|
+
if (result.error) return Response.json({ error: result.error }, { status: result.status })
|
|
388
|
+
|
|
389
|
+
if (result.stateWrite) ctx.waitUntil(result.stateWrite)
|
|
390
|
+
|
|
391
|
+
const upstream = result.upstream
|
|
392
|
+
return new Response(upstream.body, {
|
|
393
|
+
status: upstream.status,
|
|
394
|
+
statusText: upstream.statusText,
|
|
395
|
+
headers: upstream.headers,
|
|
396
|
+
})
|
|
397
|
+
} catch (error) {
|
|
398
|
+
return Response.json(
|
|
399
|
+
{ error: error instanceof Error ? error.message : 'internal relay error' },
|
|
400
|
+
{ status: 502 },
|
|
401
|
+
)
|
|
402
|
+
}
|
|
403
|
+
},
|
|
404
|
+
}
|
|
405
|
+
`;var hm="claude-routing",m_=["main-first","fallback-first"],M_="main-first",h0="Usage: `/claude-routing`, `/claude-routing main-first`, or `/claude-routing fallback-first`.";function zE(f){return typeof f==="string"&&m_.includes(f)?f:M_}function Vm(f){return zE(f?.routing?.mode)}async function Im(f,_=G()){let D=await V(_)??{version:1,main:{type:"opencode",provider:"anthropic"},accounts:[]};return D.routing={...D.routing??{},mode:f},await q(D,_),D}function GE(f){let _=f.trim().toLowerCase().split(/\s+/).filter(Boolean);if(_.length===0)return{type:"status"};if(_.length===1&&m_.includes(_[0]))return{type:"mode",mode:_[0]};if(_.length===2&&_[0]==="mode"&&m_.includes(_[1]))return{type:"mode",mode:_[1]};return{type:"usage"}}function JE(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 $_(f){let _=f?.mode??M_;return["## Claude Routing Status","",`- Mode: \`${_}\``,`- Behavior: ${JE(_)}`,"",h0].join(`
|
|
406
|
+
`)}function Qm(f){let _=GE(f.argumentsText),D=f.mode??M_;if(_.type==="status")return $_({mode:D});if(_.type==="mode")return["## Claude Routing Updated","",`Mode updated to \`${_.mode}\`.`,"",...$_({mode:_.mode}).split(`
|
|
407
|
+
`).slice(2)].join(`
|
|
408
|
+
`);return["## Claude Routing Usage","",h0,"",...$_({mode:D}).split(`
|
|
409
|
+
`).slice(2)].join(`
|
|
410
|
+
`)}export{WE as a,U_ as b,YE as c,XE as d,ZE as e,hE as f,VE as g,H_ as h,IE as i,QE as j,y as k,F_ as l,TE as m,wE as n,Q as o,X as p,nE as q,c0 as r,gE as s,G as t,V as u,q as v,YD as w,Hf as x,sE as y,ZD as z,cE as A,tE as B,oE as C,eE as D,aE as E,f$ as F,_$ as G,D$ as H,E$ as I,y_ as J,xD as K,e as L,xf as M,$$ as N,l_ as O,k_ as P,PD as Q,m$ as R,M$ as S,C$ as T,L$ as U,df as V,iD as W,H$ as X,b$ as Y,N$ as Z,S$ as _,uD as $,B$ as aa,a_ as ba,h$ as ca,j$ as da,z$ as ea,G$ as fa,c_ as ga,q$ as ha,x$ as ia,J1 as ja,cf as ka,E0 as la,W1 as ma,P$ as na,X1 as oa,p$ as pa,d$ as qa,y1 as ra,v$ as sa,u$ as ta,n$ as ua,g$ as va,s$ as wa,n1 as xa,c$ as ya,Mf as za,e$ as Aa,fm as Ba,_m as Ca,Dm as Da,Em as Ea,$m as Fa,mm as Ga,Mm as Ha,Cm as Ia,w as Ja,Nm as Ka,Sm as La,Bm as Ma,Gm as Na,Jm as Oa,Wm as Pa,Ym as Qa,hm as Ra,Vm as Sa,Im as Ta,GE as Ua,Qm as Va};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{mkdir as s,readdir as a,readFile as u,rename as c,unlink as l,writeFile as p}from"node:fs/promises";import{join as o}from"node:path";function m(r){try{return process.kill(r,0),!0}catch(n){return n.code==="EPERM"}}async function g(r,n){await s(r,{recursive:!0});let i={...n,startedAt:Date.now()},t=o(r,`port-${n.pid}.json`),e=`${t}.${process.pid}.tmp`;return await p(e,JSON.stringify(i),{encoding:"utf8",mode:384}),await c(e,t),t}async function y(r){let n;try{n=await a(r)}catch{return null}let i=[];for(let t of n){if(!t.startsWith("port-")||!t.endsWith(".json"))continue;try{let e=JSON.parse(await u(o(r,t),"utf8"));if(Number.isFinite(e.port))if(m(e.pid))i.push(e);else l(o(r,t)).catch(()=>{})}catch{}}if(i.length===0)return null;return i.sort((t,e)=>e.startedAt-t.startedAt)[0]??null}
|
|
2
|
+
export{g as db,y as eb};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import{createRequire as q}from"node:module";var j=Object.create;var{getPrototypeOf:k,defineProperty:i,getOwnPropertyNames:l}=Object;var m=Object.prototype.hasOwnProperty;function n(a){return this[a]}var o,p,r=(a,b,d)=>{var f=a!=null&&typeof a==="object";if(f){var g=b?o??=new WeakMap:p??=new WeakMap,h=g.get(a);if(h)return h}d=a!=null?j(k(a)):{};let c=b||!a||!a.__esModule?i(d,"default",{value:a,enumerable:!0}):d;for(let e of l(a))if(!m.call(c,e))i(c,e,{get:n.bind(a,e),enumerable:!0});if(f)g.set(a,c);return c};var s=(a,b)=>()=>(b||a((b={exports:{}}).exports,b),b.exports);var u=q(import.meta.url);
|
|
2
|
-
export{r as
|
|
2
|
+
export{r as hb,s as ib,u as jb};
|