@cortexkit/opencode-anthropic-auth 1.2.5 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -6
- package/dist/cli.js +1 -1
- package/dist/index-75s94xp3.js +325 -0
- package/dist/index.js +3 -3
- package/package.json +2 -2
- package/dist/index-5by638vz.js +0 -318
package/README.md
CHANGED
|
@@ -19,12 +19,13 @@ This repo is a Bun workspace monorepo with two user-facing integrations and one
|
|
|
19
19
|
| Primary Claude Pro/Max OAuth | OpenCode `/connect anthropic` | Pi `/login anthropic` |
|
|
20
20
|
| Provider integration point | OpenCode plugin fetch/request transform | Pi `registerProvider("anthropic")` provider override |
|
|
21
21
|
| Sidecar config | `~/.config/opencode/anthropic-auth.json` | `~/.pi/agent/anthropic-auth.json` |
|
|
22
|
-
| Commands | `/claude-cache`, `/claude-cachekeep`, `/claude-fast`, `/claude-quota`, `/claude-dump` | `/claude-cache`, `/claude-cachekeep`, `/claude-fast`, `/claude-quota`, `/claude-dump` |
|
|
22
|
+
| Commands | `/claude-cache`, `/claude-cachekeep`, `/claude-routing`, `/claude-fast`, `/claude-quota`, `/claude-dump` | `/claude-cache`, `/claude-cachekeep`, `/claude-routing`, `/claude-fast`, `/claude-quota`, `/claude-dump` |
|
|
23
23
|
| Fallback accounts, quota routing, relay, dumps, fast mode | Supported | Supported through the same shared core and Pi sidecar |
|
|
24
24
|
|
|
25
25
|
## What CortexKit adds over the original plugin
|
|
26
26
|
|
|
27
27
|
- **Fallback Claude accounts**: keep each agent's normal Anthropic login as the primary account, then route to ordered fallback OAuth accounts on auth/quota/rate-limit failures.
|
|
28
|
+
- **Routing mode toggle**: use `/claude-routing fallback-first` to prefer sidecar fallback accounts before the main account.
|
|
28
29
|
- **Quota-aware routing**: skip main or fallback accounts when their 5-hour or 7-day Claude quota falls below your configured minimum.
|
|
29
30
|
- **Persistent Claude cache controls**: manage Anthropic 1-hour prompt caching from `/claude-cache` with explicit, automatic, or hybrid modes.
|
|
30
31
|
- **Cache keepalive**: use `/claude-cachekeep HH-HH` to pre-warm hybrid cache anchors for active sessions before the 1-hour TTL expires.
|
|
@@ -155,6 +156,9 @@ Example:
|
|
|
155
156
|
"version": 1,
|
|
156
157
|
"main": { "type": "opencode", "provider": "anthropic" },
|
|
157
158
|
"fallbackOn": [401, 403, 429],
|
|
159
|
+
"routing": {
|
|
160
|
+
"mode": "main-first"
|
|
161
|
+
},
|
|
158
162
|
"refresh": {
|
|
159
163
|
"enabled": true,
|
|
160
164
|
"intervalMinutes": 10,
|
|
@@ -195,11 +199,13 @@ Example:
|
|
|
195
199
|
}
|
|
196
200
|
```
|
|
197
201
|
|
|
198
|
-
The `
|
|
202
|
+
The `routing` block controls `/claude-routing`, `claudeCache` controls `/claude-cache`, `cacheKeep` controls `/claude-cachekeep`, and `claudeFast` controls `/claude-fast`. The `main` field identifies OpenCode's primary auth entry; Pi keeps primary OAuth credentials in Pi's own credential store, but uses the same sidecar shape for CortexKit settings and fallback accounts.
|
|
199
203
|
|
|
200
204
|
## Fallback accounts
|
|
201
205
|
|
|
202
|
-
Fallback accounts are separate Claude OAuth accounts managed by this plugin.
|
|
206
|
+
Fallback accounts are separate Claude OAuth accounts managed by this plugin. By default, the main account is tried first unless quota policy says it is currently unusable. Fallbacks are then tried in sidecar order when the primary request returns a configured fallback status.
|
|
207
|
+
|
|
208
|
+
Use `/claude-routing fallback-first` to prefer usable fallback accounts before the main account. Use `/claude-routing main-first` to restore the default. The command persists `routing.mode` and takes effect on the next request without restarting.
|
|
203
209
|
|
|
204
210
|
Default fallback statuses:
|
|
205
211
|
|
|
@@ -277,7 +283,7 @@ Modes:
|
|
|
277
283
|
|
|
278
284
|
- `explicit` keeps OpenCode's explicit cache breakpoints and adds `ttl: "1h"` to them.
|
|
279
285
|
- `automatic` removes block-level cache controls and sends a top-level `cache_control` object.
|
|
280
|
-
- `hybrid` (recommended) removes top-level automatic caching and uses explicit anchors on the last stable system block, the
|
|
286
|
+
- `hybrid` (recommended) removes top-level automatic caching and uses explicit anchors on the first two messages plus a moving latest-user boundary. It keeps the last stable system block in normal turns, and uses that slot for the previous user boundary when a tool-heavy step would exceed Anthropic's 20-block lookback.
|
|
281
287
|
|
|
282
288
|
In OpenCode, subagent requests do not receive 1-hour TTL caching. The plugin detects child sessions through OpenCode's `x-parent-session-id` header, strips that internal header before forwarding to Anthropic, and leaves default ephemeral caching in place for those requests.
|
|
283
289
|
|
|
@@ -307,7 +313,7 @@ Both OpenCode and Pi packages can persistently request Anthropic fast mode for s
|
|
|
307
313
|
/claude-fast off
|
|
308
314
|
```
|
|
309
315
|
|
|
310
|
-
When enabled, supported requests add `speed: "fast"` to the Anthropic JSON body and include the `fast-mode-2026-02-01` beta header. Unsupported models are left at standard speed. Anthropic currently documents fast mode for `claude-opus-4-6` and `claude-opus-4-
|
|
316
|
+
When enabled, supported requests add `speed: "fast"` to the Anthropic JSON body and include the `fast-mode-2026-02-01` beta header. Unsupported models are left at standard speed. Anthropic currently documents fast mode for `claude-opus-4-6`, `claude-opus-4-7`, and `claude-opus-4-8`.
|
|
311
317
|
|
|
312
318
|
Fast and standard speeds do not share prompt-cache prefixes, so switching this setting can cause cache misses.
|
|
313
319
|
|
|
@@ -334,7 +340,7 @@ bun run analyze:cache -- --days 7 --json
|
|
|
334
340
|
bun run analyze:cache -- --db ~/.local/share/opencode/opencode.db --days 30
|
|
335
341
|
```
|
|
336
342
|
|
|
337
|
-
The script reads OpenCode usage data from `~/.local/share/opencode/opencode.db` by default. It uses recorded prompt, cache-read, cache-write, and output tokens, then estimates counterfactual 5-minute and no-cache costs from the same turns. The default 5-minute expiry threshold is 5 minutes; override it with `--idle-threshold-min <minutes>` if needed.
|
|
343
|
+
The script reads OpenCode usage data from `~/.local/share/opencode/opencode.db` by default. It uses recorded prompt, cache-read, cache-write, and output tokens, then estimates counterfactual 5-minute and no-cache costs from the same turns. Its pricing table includes Claude Opus 4.5 through 4.8. The default 5-minute expiry threshold is 5 minutes; override it with `--idle-threshold-min <minutes>` if needed.
|
|
338
344
|
|
|
339
345
|
This analyzer is OpenCode-specific because it reads OpenCode's local message database.
|
|
340
346
|
|
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{
|
|
2
|
+
import{m as y,n as w,p as l,q as u,r as m,sa as b,ua as k}from"./index-75s94xp3.js";import{stdin as A,stdout as $}from"node:process";import{createInterface as R}from"node:readline/promises";function v(){return{version:1,main:{type:"opencode",provider:"anthropic"},fallbackOn:[401,403,429],refresh:{enabled:!0,intervalMinutes:10,refreshBeforeExpiryMinutes:240},quota:{enabled:!0,checkIntervalMinutes:5,minimumRemaining:{five_hour:10,seven_day:20},failClosedOnUnknownQuota:!0},accounts:[]}}function h(){console.log(`Usage:
|
|
3
3
|
opencode-anthropic-auth login [label]
|
|
4
4
|
opencode-anthropic-auth list
|
|
5
5
|
opencode-anthropic-auth relay setup
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
var d="9d1c250a-e61b-44d9-88ed-5944d1962f5e",Rf={console:"https://platform.claude.com/oauth/authorize",max:"https://claude.ai/oauth/authorize"},Cf="https://platform.claude.com/oauth/code/callback",Mf="https://platform.claude.com/v1/oauth/token",kf=["org:create_api_key","user:profile","user:inference","user:sessions:claude_code","user:mcp_servers","user:file_upload"],S_="mcp_";var wf="fast-mode-2026-02-01";function U_(f,m){let _=(f??"").split(",").map(($)=>$.trim()).filter(Boolean);return[...new Set([..._,...m])].join(",")}function b_(f){return typeof f==="string"&&(f.startsWith("claude-opus-4-6")||f.startsWith("claude-opus-4-7")||f.startsWith("claude-opus-4-8"))}var N_="You are OpenCode",j_="You are a Claude agent, built on Anthropic's Claude Agent SDK.",K_=["<use_parallel_tool_calls>","For maximum efficiency, whenever you perform multiple independent operations, invoke all relevant tools simultaneously rather than sequentially. Prioritize calling tools in parallel whenever possible. For example, when reading 3 files, run 3 tool calls in parallel to read all 3 files into context at the same time. When running multiple read-only commands like `ls` or `list_dir`, always run all of the commands in parallel. Err on the side of maximizing parallel tool calls rather than running too many tools sequentially.","</use_parallel_tool_calls>"].join(`
|
|
2
|
+
`);var X="2.1.141",Hf="67b",uf="sdk-cli",nf="0.94.0",cf="v24.3.0",lf="claude-cli/2.1.141 (external, sdk-cli)",pf=["explicit","automatic","hybrid"],v="explicit",I_=["github.com/anomalyco/opencode","opencode.ai/docs"],G_=[{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 yf(f){let m="";for(let _ of f)m+=String.fromCharCode(_);return btoa(m).replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}async function df(){let f=new Uint8Array(64);crypto.getRandomValues(f);let m=yf(f),_=await crypto.subtle.digest("SHA-256",new TextEncoder().encode(m));return{verifier:m,challenge:yf(new Uint8Array(_)),method:"S256"}}function g0(f){if(!f)return;let m=Number(f);if(Number.isFinite(m)&&m>0)return Math.ceil(m);let _=Date.parse(f);if(Number.isFinite(_)){let $=Math.ceil((_-Date.now())/1000);return $>0?$:void 0}return}class T extends Error{status;body;retryAfter;constructor(f,m,_){super(`Claude OAuth refresh failed: ${f} — ${m}`);this.status=f,this.body=m,this.name="ClaudeOAuthRefreshError",this.retryAfter=g0(_??void 0)}}function s0(f){if(!(f instanceof Error))return!1;let m=f.code;return f.message.includes("fetch failed")||m==="ECONNRESET"||m==="ECONNREFUSED"||m==="ETIMEDOUT"||m==="UND_ERR_CONNECT_TIMEOUT"}async function vf(f){let m=f.fetchImpl??fetch,_=f.maxRetries??2,$=f.baseDelayMs??500;for(let D=0;D<=_;D++)try{if(D>0){let H=$*2**(D-1);await new Promise((U)=>setTimeout(U,H))}let E=await m(Mf,{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json","User-Agent":"axios/1.13.6"},body:JSON.stringify({grant_type:"refresh_token",refresh_token:f.refreshToken,client_id:d})});if(!E.ok){if(E.status>=500&&D<_){await E.body?.cancel().catch(()=>{});continue}let H=await E.text().catch(()=>"");throw new T(E.status,H,E.headers.get("retry-after"))}let C=await E.json(),M=f.now?.()??Date.now();return{access:C.access_token,refresh:C.refresh_token??f.refreshToken,expires:M+C.expires_in*1000,expiresIn:C.expires_in}}catch(E){if(E instanceof T)throw E;if(D<_&&s0(E))continue;throw E}throw Error("Token refresh exhausted all retries")}function r0(){return crypto.randomUUID().replace(/-/g,"")}function o0(f){let m=f.trim();try{let C=new URL(m),M=C.searchParams.get("code"),H=C.searchParams.get("state");if(M&&H)return{code:M,state:H}}catch{}let _=m.split("#");if(_.length===2&&_[0]&&_[1])return{code:_[0],state:_[1]};let $=new URLSearchParams(m),D=$.get("code"),E=$.get("state");if(D&&E)return{code:D,state:E};return null}async function a0(f,m,_){let $=await fetch(Mf,{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json, text/plain, */*","User-Agent":"axios/1.13.6"},body:JSON.stringify({code:f.code,state:f.state,grant_type:"authorization_code",client_id:d,redirect_uri:_,code_verifier:m})});if(!$.ok)return{type:"failed"};let D=await $.json();return{type:"success",refresh:D.refresh_token,access:D.access_token,expires:Date.now()+D.expires_in*1000}}async function z_(f){let m=await df(),_=r0(),$=new URL(Rf[f],import.meta.url);return $.searchParams.set("code","true"),$.searchParams.set("client_id",d),$.searchParams.set("response_type","code"),$.searchParams.set("redirect_uri",Cf),$.searchParams.set("scope",kf.join(" ")),$.searchParams.set("code_challenge",m.challenge),$.searchParams.set("code_challenge_method","S256"),$.searchParams.set("state",_),{url:$.toString(),redirectUri:Cf,state:_,verifier:m.verifier}}async function B_(f,m,_,$){let D=o0(f);if(!D)return{type:"failed"};if($&&D.state!==$)return{type:"failed"};return a0(D,m,_)}import*as tf from"node:fs";import*as gf from"node:os";import*as sf from"node:path";var e0=sf.join(gf.tmpdir(),"opencode-anthropic-auth.log"),rf=!1,f1=500,m1=50,i=[],P=null;function Ff(){if(P)clearTimeout(P),P=null;if(i.length===0)return;let f=i.join("");i=[];try{tf.appendFileSync(e0,f)}catch{}}function _1(){if(P)return;P=setTimeout(()=>{P=null,Ff()},f1)}function $1(f){if(f===void 0)return"";if(f instanceof Error)return` ${f.message}${f.stack?`
|
|
3
|
+
${f.stack}`:""}`;return` ${JSON.stringify(f)}`}function L(f,m){if(rf)return;try{if(i.push(`[${new Date().toISOString()}] ${f}${$1(m)}
|
|
4
|
+
`),i.length>=m1)Ff();else _1()}catch{}}function K(f,m){L(`[relay] ${f}`,m)}if(!rf)process.on("exit",Ff);import{createHash as D0,randomUUID as Nf}from"node:crypto";import{mkdir as D1,readFile as t,rename as E1,rm as of,stat as C1,writeFile as bf}from"node:fs/promises";import{homedir as M1}from"node:os";import{dirname as H1,join as g}from"node:path";var F1=globalThis.setTimeout.bind(globalThis),S1=globalThis.clearTimeout.bind(globalThis),U1="anthropic-auth.json",b1="https://api.anthropic.com/api/oauth/usage",N1=[401,403,429],E0=240,j1=E0;var K1=300000,I1=3600000,G1=86400000,J1=5,af={five_hour:0,seven_day:0},O1=!0,A1=60000,W1=60000,z1=600000,B1=1e4,L1=100;function V1(){if(process.env.OPENCODE_CONFIG_DIR?.trim())return process.env.OPENCODE_CONFIG_DIR.trim();return g(process.env.XDG_CONFIG_HOME||g(M1(),".config"),"opencode")}function B(){return process.env.OPENCODE_ANTHROPIC_AUTH_FILE?.trim()||g(V1(),U1)}function J(f){return f!=null&&typeof f==="object"&&!Array.isArray(f)}function Q1(f){if(!J(f))return null;if(f.type!=="oauth")return null;if(typeof f.refresh!=="string"||!f.refresh.trim())return null;return{id:typeof f.id==="string"&&f.id.trim()?f.id.trim():Nf(),label:typeof f.label==="string"?f.label:void 0,type:"oauth",access:typeof f.access==="string"?f.access:void 0,refresh:f.refresh,expires:typeof f.expires==="number"?f.expires:void 0,enabled:typeof f.enabled==="boolean"?f.enabled:void 0,addedAt:typeof f.addedAt==="number"?f.addedAt:void 0,lastUsed:typeof f.lastUsed==="number"?f.lastUsed:void 0,lastRefreshedAt:typeof f.lastRefreshedAt==="number"?f.lastRefreshedAt:void 0,lastRefreshError:ef(f.lastRefreshError),lastQuotaRefreshError:ef(f.lastQuotaRefreshError),quota:X1(f.quota)}}function ef(f){if(!J(f))return;if(typeof f.message!=="string")return;let m=Number(f.checkedAt);if(!Number.isFinite(m))return;let _=Number(f.nextRetryAt),$=Number(f.retryCount);return{message:f.message,checkedAt:m,nextRetryAt:Number.isFinite(_)?_:void 0,retryCount:Number.isFinite($)?$:void 0,tokenHash:typeof f.tokenHash==="string"?f.tokenHash:void 0}}function X1(f){if(!J(f))return;let m={};for(let _ of["five_hour","seven_day"]){let $=f[_];if(!J($))continue;let D=Number($.usedPercent),E=Number($.remainingPercent),C=Number($.checkedAt);if(!Number.isFinite(D)||!Number.isFinite(E)||!Number.isFinite(C))continue;m[_]={usedPercent:D,remainingPercent:E,checkedAt:C,resetsAt:typeof $.resetsAt==="string"?$.resetsAt:void 0}}return Object.keys(m).length?m:void 0}function Z1(f){if(!J(f)||!Array.isArray(f.accounts))return null;return{version:1,main:{type:"opencode",provider:"anthropic"},routing:J(f.routing)?f.routing:void 0,fallbackOn:Array.isArray(f.fallbackOn)?f.fallbackOn.filter((m)=>Number.isInteger(m)):void 0,refresh:J(f.refresh)?f.refresh:void 0,quota:J(f.quota)?f.quota:void 0,claudeCache:J(f.claudeCache)?f.claudeCache:void 0,dump:J(f.dump)?f.dump:void 0,claudeFast:J(f.claudeFast)?f.claudeFast:void 0,cacheKeep:J(f.cacheKeep)?f.cacheKeep:void 0,relay:J(f.relay)?f.relay:void 0,accounts:f.accounts.map(Q1).filter((m)=>m!=null)}}async function V(f=B()){try{let m=await t(f,"utf8");return Z1(JSON.parse(m))}catch(m){if(m.code==="ENOENT")return null;return null}}async function T1(f){try{let m=await t(f,"utf8"),_=JSON.parse(m);return J(_)?_:{}}catch{return{}}}function Y1(f){return Object.fromEntries(Object.entries(f).filter(([,m])=>m!==void 0))}async function Q(f,m=B()){await D1(H1(m),{recursive:!0});let $={...await T1(m),...Y1(f)},D=`${m}.${Nf()}.tmp`;await bf(D,`${JSON.stringify($,null,2)}
|
|
5
|
+
`,{encoding:"utf8",mode:384}),await E1(D,m)}async function h1(f){let _=`${f.path??B()}.${f.name}.lock`,$=g(_,"owner.json"),D=Nf(),E=f.now??Date.now,C=null,M=!1;async function H(){try{return JSON.parse(await t(_,"utf8"))}catch(j){if(j.code!=="EISDIR")throw j;return JSON.parse(await t($,"utf8"))}}async function U(){await bf(_,`${JSON.stringify({ownerId:D,expiresAt:E()+f.ttlMs})}
|
|
6
|
+
`,{encoding:"utf8",mode:384})}async function b(){try{return await bf(_,`${JSON.stringify({ownerId:D,expiresAt:E()+f.ttlMs})}
|
|
7
|
+
`,{encoding:"utf8",mode:384,flag:"wx"}),!0}catch(j){let I=j.code;if(I==="EEXIST"||I==="EISDIR")return!1;throw j}}function N(){if(!f.renew||M)return;let j=f.renewIntervalMs??Math.max(1000,Math.floor(f.ttlMs/3));if(C=F1(()=>{(async()=>{try{let I=await H(),S=E();if(M||I?.ownerId!==D||Number(I?.expiresAt)<=S)return;await U(),N()}catch{}})()},j),"unref"in C)C.unref()}if(!await b()){try{let j=await H();if(Number(j?.expiresAt)>E())return null}catch{try{if((await C1(_)).mtimeMs+f.ttlMs>Date.now())return null}catch{return null}}if(await of(_,{recursive:!0,force:!0}).catch(()=>{}),!await b())return null}return N(),{release:async()=>{if(M=!0,C)S1(C),C=null;try{if((await H())?.ownerId!==D)return}catch{return}await of(_,{recursive:!0,force:!0}).catch(()=>{})}}}function x_(f){return f?.claudeCache?.enabled===!0}function q1(f){return typeof f==="string"&&pf.includes(f)?f:v}function x1(f){return q1(f?.claudeCache?.mode)}async function P_(f,m,_=B()){let $=await V(_)??{version:1,main:{type:"opencode",provider:"anthropic"},accounts:[]};return $.claudeCache={...$.claudeCache??{},enabled:f,mode:m??x1($)},await Q($,_),$}async function R_(f,m=B()){let _=await V(m)??{version:1,main:{type:"opencode",provider:"anthropic"},accounts:[]};return _.claudeCache={..._.claudeCache??{},enabled:_.claudeCache?.enabled===!0,mode:f},await Q(_,m),_}function i_(f){return f?.dump?.enabled===!0}async function k_(f,m=B()){let _=await V(m)??{version:1,main:{type:"opencode",provider:"anthropic"},accounts:[]};return _.dump={..._.dump??{},enabled:f},await Q(_,m),_}function w_(f){return f?.claudeFast?.enabled===!0}async function u_(f,m=B()){let _=await V(m)??{version:1,main:{type:"opencode",provider:"anthropic"},accounts:[]};return _.claudeFast={..._.claudeFast??{},enabled:f},await Q(_,m),_}async function n_(f,m,_=B()){let $=await V(_)??{version:1,main:{type:"opencode",provider:"anthropic"},accounts:[]};return $.cacheKeep={enabled:!0,startHour:f,endHour:m},await Q($,_),$}async function c_(f,m=B()){let _=await V(m)??{version:1,main:{type:"opencode",provider:"anthropic"},accounts:[]};return _.cacheKeep={..._.cacheKeep??{},enabled:f},await Q(_,m),_}function P1(f){return f?.fallbackOn?.length?f.fallbackOn:N1}function l_(f,m){return P1(m).includes(f)}function C0(f){let m=f?.quota?.minimumRemaining||{};return{five_hour:m.five_hour??m["5h"]??af.five_hour,seven_day:m.seven_day??m["1w"]??af.seven_day}}function u(f){return f?.quota?.enabled!==!1}function R1(f){return f?.refresh?.enabled!==!1}function i1(f){return Math.floor(Math.random()*Math.max(0,f))}function k1(f){let m=f?.refresh?.refreshBeforeExpiryMinutes??j1;return Math.max(E0,m)*60000}function M0(f){return D0("sha256").update(f).digest("hex")}function w1(f){if(f instanceof T)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 u1(f){let m=M0(f.refreshToken),$=(f.previous?.tokenHash===m?f.previous.retryCount??0:0)+1,D;if(f.error instanceof T&&f.error.retryAfter)D=f.error.retryAfter*1000;else if(w1(f.error))D=Math.min(I1,K1*2**Math.min($-1,6));else D=G1;return{message:n(f.error),checkedAt:f.now,nextRetryAt:f.now+D,retryCount:$,tokenHash:m}}function k(f,m,_){if(!f?.nextRetryAt||f.nextRetryAt<=_)return!1;if(!m)return!0;return f.tokenHash===M0(m)}function Sf(f,m){return`Claude OAuth refresh is backed off for ${Math.max(1,Math.ceil(((f.nextRetryAt??m)-m)/1000))}s after: ${f.message}`}function w(f){let m=f?.quota?.checkIntervalMinutes??J1;return Math.max(1,m)*60000}function H0(f){return f?.quota?.failClosedOnUnknownQuota??O1}function F0(f,m){if(!u(m))return!0;let _=C0(m);for(let $ of["five_hour","seven_day"]){let D=f?.[$];if(!D)return!H0(m);if(D.remainingPercent<_[$])return!1}return!0}function p_(f,m,_){if(!u(m))return _+w(m);let $=C0(m),D=[];for(let E of["five_hour","seven_day"]){let C=f?.[E];if(!C)return _+w(m);if(C.remainingPercent>=$[E])continue;let M=C.resetsAt?Date.parse(C.resetsAt):Number.NaN;if(!Number.isFinite(M)||M<=_)return _+w(m);D.push(M)}if(!D.length)return _+w(m);return Math.min(...D)+60000}function Y(f,m,_){return!f.access||!f.expires||f.expires-_<=k1(m)}function Uf(f,m,_){if(!u(m))return!1;let $=w(m);return["five_hour","seven_day"].some((D)=>{let E=f.quota?.[D];return!E||_-E.checkedAt>=$})}function n1(f,m){if(!f)return!1;if(!f.resetsAt)return!0;let _=Date.parse(f.resetsAt);return!Number.isFinite(_)||_>m}function c1(f,m){return["five_hour","seven_day"].every((_)=>n1(f?.[_],m))}function l1(f){let m=n(f);if(/Claude quota check failed: (429|5\d\d)\b/.test(m))return!0;if(!(f instanceof Error))return!1;let _=f.code;return m.includes("fetch failed")||_==="ECONNRESET"||_==="ECONNREFUSED"||_==="ETIMEDOUT"||_==="UND_ERR_CONNECT_TIMEOUT"}function p1(f,m,_,$){return l1(_)&&F0(f.quota,m)&&c1(f.quota,$)}function f0(f){if(!Number.isFinite(f))return 0;if(f<0)return 0;if(f>100)return 100;return f}function m0(f,m){if(typeof f?.utilization!=="number")return;let _=f0(f.utilization);return{usedPercent:_,remainingPercent:f0(100-_),resetsAt:f.resets_at,checkedAt:m}}async function _0(f){let _=await(f.fetchImpl??fetch)(b1,{method:"GET",headers:{Authorization:`Bearer ${f.accessToken}`,Accept:"application/json","Content-Type":"application/json","anthropic-beta":"oauth-2025-04-20","User-Agent":`claude-code/${X}`}});if(!_.ok){let E=await _.text().catch(()=>"");throw Error(`Claude quota check failed: ${_.status} — ${E}`)}let $=f.now?.()??Date.now(),D=await _.json();return{five_hour:m0(D.five_hour,$),seven_day:m0(D.seven_day,$)}}function z(f,m){let _=f.accounts.findIndex(($)=>$.id===m.id);if(_>=0)f.accounts[_]=m}function n(f){return f instanceof Error?f.message:String(f)}function S0(f,m,_){f.lastRefreshError=u1({error:m,now:_,refreshToken:f.refresh,previous:f.lastRefreshError})}function $0(f,m,_){if(f.lastQuotaRefreshError={message:n(m),checkedAt:_},m instanceof T)S0(f,m,_)}function y1(f){return`fallback-oauth-refresh-${D0("sha256").update(f).digest("hex").slice(0,16)}`}class d1{now;fetchImpl;configPath;refreshPromises=new Map;refreshTimer=null;quotaTimer=null;constructor(f={}){this.now=f.now??Date.now,this.fetchImpl=f.fetchImpl??fetch,this.configPath=f.configPath??B()}async load(){return V(this.configPath)}async save(f){await Q(f,this.configPath)}startBackgroundRefresh(){let f=async()=>{await this.refreshDueAccounts(),await this.refreshQuotaForDueAccounts()};if(f().catch(()=>{}),!this.refreshTimer){if(this.refreshTimer=setInterval(()=>{f().catch(()=>{})},A1+i1(W1)),"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 m=f!==void 0?f:await this.load();if(!m)return[];let _=[],$=!1;for(let D of m.accounts){if(D.enabled===!1)continue;try{let E=D;if(Y(E,m,this.now())){let C=E.lastRefreshError;if(C&&k(C,E.refresh,this.now()))throw Error(Sf(C,this.now()));E=await this.refreshAccount(E,m),$=!0}if(Uf(E,m,this.now()))E=await this.refreshAccountQuota(E,m),$=!0;if(this.accountPassesQuotaPolicy(E,m))_.push(E)}catch(E){if(p1(D,m,E,this.now()))L("[refresh] fallback quota using cached quota after refresh error",{accountId:D.id,error:n(E)}),_.push(D);else if(!H0(m))_.push(D)}}if($)await this.save(m);return _}async markUsed(f){let m=await this.load();if(!m)return;let _=m.accounts.find(($)=>$.id===f.id);if(!_)return;_.lastUsed=this.now(),await this.save(m)}accountPassesQuotaPolicy(f,m){return F0(f.quota,m)}async refreshDueAccounts(){let f=await this.load();if(!f||!R1(f))return;let m=!1;for(let _ of f.accounts){if(_.enabled===!1)continue;if(!Y(_,f,this.now()))continue;if(k(_.lastRefreshError,_.refresh,this.now())){L("[refresh] fallback oauth skipped backoff",{accountId:_.id,nextRetryAt:_.lastRefreshError?.nextRetryAt,retryCount:_.lastRefreshError?.retryCount});continue}try{L("[refresh] fallback oauth background due",{accountId:_.id,expiresInMs:_.expires?_.expires-this.now():void 0}),await this.refreshAccount(_,f),m=!0}catch($){L("[refresh] fallback oauth background failed",{accountId:_.id,error:$ instanceof Error?$.message:String($)}),S0(_,$,this.now()),z(f,_),m=!0}}if(m)await this.save(f)}async refreshQuotaForDueAccounts(){let f=await this.load();if(!f||!u(f))return;let m=!1;for(let _ of f.accounts){if(_.enabled===!1)continue;let $=_;try{if(Y($,f,this.now())){if(k($.lastRefreshError,$.refresh,this.now()))continue;$=await this.refreshAccount($,f),m=!0}if(!Uf($,f,this.now()))continue;await this.refreshAccountQuota($,f),m=!0}catch(D){$0(_,D,this.now()),z(f,_),m=!0}}if(m)await this.save(f)}async refreshQuotaForAllAccounts(){let f=await this.load(),m=[];if(!f||!u(f))return{storage:f,errors:m};let _=!1;for(let $ of f.accounts){if($.enabled===!1)continue;let D=$;try{if(Y(D,f,this.now())){let E=D.lastRefreshError;if(E&&k(E,D.refresh,this.now()))throw Error(Sf(E,this.now()));D=await this.refreshAccount(D,f),_=!0}if(!Uf(D,f,this.now())){if(D.lastQuotaRefreshError)D.lastQuotaRefreshError=void 0,z(f,D),_=!0;continue}await this.refreshAccountQuota(D,f),_=!0}catch(E){$0($,E,this.now()),z(f,$),_=!0,m.push({accountId:$.id,message:n(E)})}}if(_)await this.save(f);return{storage:f,errors:m}}async refreshAccount(f,m,_={}){let $=this.refreshPromises.get(f.id);if($){let C=await $;return z(m,C),C}let D=this.refreshAccountNow(f,m,_).finally(()=>{this.refreshPromises.delete(f.id)});this.refreshPromises.set(f.id,D);let E=await D;return z(m,E),E}async waitForConcurrentFallbackRefresh(f,m,_,$){let D=Date.now()+B1;while(Date.now()<D){await new Promise((U)=>setTimeout(U,L1));let E=await this.load(),C=E?.accounts.find((U)=>U.id===f.id);if(!C)continue;if((C.access!==_.access||C.refresh!==_.refresh||(C.expires??0)>(_.expires??0)+60000)&&($.force||!Y(C,E,this.now())))return z(m,C),L("[refresh] fallback oauth joined concurrent refresh",{accountId:C.id,expiresInMs:C.expires?C.expires-this.now():void 0}),C;let H=C.lastRefreshError;if(H&&k(H,C.refresh,this.now()))throw z(m,C),Error(Sf(H,this.now()))}return null}async refreshAccountNow(f,m,_){let $=await this.load(),D=$?.accounts.find((M)=>M.id===f.id);if(D&&!_.force&&!Y(D,$,this.now()))return z(m,D),D;let E=D??f,C=await h1({name:y1(E.id),ttlMs:z1,path:this.configPath,now:this.now,renew:!0});if(!C){L("[refresh] fallback oauth refresh skipped file lock",{accountId:E.id});let M=await this.waitForConcurrentFallbackRefresh(f,m,E,_);if(M)return M;throw Error("Fallback OAuth refresh is already in progress")}try{if($=await this.load(),D=$?.accounts.find((U)=>U.id===f.id),D&&!_.force&&!Y(D,$,this.now()))return z(m,D),D;E=D??E;let M=E.refresh;L("[refresh] fallback oauth refresh request start",{accountId:E.id,force:_.force===!0,expiresInMs:E.expires?E.expires-this.now():void 0});let H=await vf({refreshToken:M,fetchImpl:this.fetchImpl,now:this.now});return E.access=H.access,E.refresh=H.refresh,E.expires=H.expires,E.lastRefreshedAt=H.expires-H.expiresIn*1000,E.lastRefreshError=void 0,z(m,E),await this.save(m),L("[refresh] fallback oauth refresh succeeded",{accountId:E.id,expiresInMs:E.expires?E.expires-this.now():void 0}),E}finally{await C.release()}}async refreshAccountQuota(f,m){let _=f;if(!_.access)throw Error(`Fallback account ${f.id} has no access token`);try{_.quota=await _0({accessToken:_.access,fetchImpl:this.fetchImpl,now:this.now})}catch($){if(!($ instanceof Error?$.message:String($)).includes("Claude quota check failed: 401"))throw $;if(_=await this.refreshAccount(f,m,{force:!0}),!_.access)throw $;_.quota=await _0({accessToken:_.access,fetchImpl:this.fetchImpl,now:this.now})}return _.lastQuotaRefreshError=void 0,z(m,_),_}}var v_="claude-cache",U0="## Claude Cache Status",v1="## Claude Cache Enabled",t1="## Claude Cache Disabled",g1="## Claude Cache Usage",s1="Usage: `/claude-cache`, `/claude-cache on`, `/claude-cache off`, or `/claude-cache mode explicit|automatic|hybrid`.",s=!1,r=v;function t_(){return s}function g_(){return r}function s_(f){s=f.enabled,r=f.mode}function r1(f){let m=f.trim().split(/\s+/).filter(Boolean);if(m.length===0)return{type:"status"};if(m.length===1&&m[0]==="on")return{type:"enable"};if(m.length===1&&m[0]==="off")return{type:"disable"};if(m.length===2&&m[0]==="mode"&&(m[1]==="explicit"||m[1]==="automatic"||m[1]==="hybrid"))return{type:"mode",mode:m[1]};return{type:"usage"}}function c(f){let m=f?.enabled??s,_=f?.mode??r;return[U0,"",`- Enabled: ${m?"enabled":"disabled"}`,`- Mode: ${_}`,"- Persisted: ~/.config/opencode/anthropic-auth.json","- Scope: main sessions only; subagent sessions keep default ephemeral cache behavior","- Modes: explicit = existing OpenCode breakpoints; automatic = top-level cache_control only; hybrid = system + messages[0] + top-level cache_control","- TTL: 1h when enabled for main sessions; default ephemeral cache behavior otherwise"].join(`
|
|
8
|
+
`)}function r_(f){let m=r1(f.argumentsText),_=f.enabled??s,$=f.mode??r;if(m.type==="status")return c({enabled:_,mode:$});if(m.type==="enable")return[v1,"",c({enabled:!0,mode:$})].join(`
|
|
9
|
+
`);if(m.type==="disable")return[t1,"",c({enabled:!1,mode:$})].join(`
|
|
10
|
+
`);if(m.type==="mode")return[U0,"",`Mode updated to \`${m.mode}\`.`,"",c({enabled:_,mode:m.mode})].join(`
|
|
11
|
+
`);return[g1,"",s1,"",c({enabled:_,mode:$})].join(`
|
|
12
|
+
`)}import{randomBytes as o1,randomUUID as N0}from"node:crypto";var a1=1000,l=new Map;function Kf(f,m,_){if(!f.has(m)&&f.size>=a1){let $=f.keys().next().value;if($!==void 0)f.delete($)}f.set(m,_)}function j0(f){let m=f||"anonymous",_=l.get(m);if(_)return _;let $={deviceId:o1(32).toString("hex"),sessionId:N0()};return Kf(l,m,$),$}var jf=new Map;async function e1(f,m){if(!f.startsWith("sk-ant-oat"))return null;let _=new AbortController,$=setTimeout(()=>_.abort(),5000);try{let D=new URL("https://api.anthropic.com/api/claude_cli/bootstrap");if(D.searchParams.set("entrypoint",uf),m)D.searchParams.set("model",m);let E=await fetch(D,{method:"GET",headers:{accept:"application/json, text/plain, */*",authorization:`Bearer ${f}`,"content-type":"application/json","anthropic-beta":"oauth-2025-04-20","user-agent":`claude-code/${X}`},signal:_.signal});if(!E.ok)return null;let M=(await E.json().catch(()=>null))?.oauth_account?.account_uuid;return typeof M==="string"&&M?M:null}catch{return null}finally{clearTimeout($)}}async function f$(f,m){let _=j0(f);if(!f.startsWith("sk-ant-oat"))return _;let $=jf.get(f);if(!$)$=e1(f,m),jf.set(f,$);let D=await $;if(!D)return jf.delete(f),_;let E=`account:${D}`,C=l.get(E);if(C)return Kf(l,f,C),C;return _.accountUuid=D,Kf(l,E,_),_}function h(f){return f!=null&&typeof f==="object"&&!Array.isArray(f)}function fm(f){if(!f.accountUuid)return null;return JSON.stringify({device_id:f.deviceId,account_uuid:f.accountUuid,session_id:f.sessionId})}function m$(f,m){let _=fm(m);if(!_){if(h(f.metadata))delete f.metadata.user_id;return!1}if(!h(f.metadata))f.metadata={};let $=f.metadata;if(h($))$.user_id=_;return!0}var mm=["claude-code-20250219","oauth-2025-04-20","interleaved-thinking-2025-05-14","context-management-2025-06-27","prompt-caching-scope-2026-01-05","advisor-tool-2026-03-01","advanced-tool-use-2025-11-20","context-1m-2025-08-07","effort-2025-11-24","extended-cache-ttl-2025-04-11","cache-diagnosis-2026-04-07"],_m=["oauth-2025-04-20","interleaved-thinking-2025-05-14","context-management-2025-06-27","prompt-caching-scope-2026-01-05","advisor-tool-2026-03-01","structured-outputs-2025-12-15","cache-diagnosis-2026-04-07"],b0=["oauth-2025-04-20","interleaved-thinking-2025-05-14","context-management-2025-06-27","prompt-caching-scope-2026-01-05","advisor-tool-2026-03-01","cache-diagnosis-2026-04-07"];function $m(f){return f.output_config?.format?.type==="json_schema"}function Dm(f){return Array.isArray(f.tools)&&f.tools.length>0&&Array.isArray(f.system)&&h(f.thinking)&&h(f.context_management)&&h(f.output_config)&&h(f.diagnostics)}function Em(f,m=[]){let _=f?Dm(f)?[...mm]:$m(f)?[..._m]:[...b0]:[...b0];if(f?.speed==="fast")_.push(wf);for(let $ of m){let D=$.trim();if(D)_.push(D)}return[...new Set(_)].join(",")}function Cm(){switch(process.platform){case"darwin":return"MacOS";case"win32":return"Windows";case"linux":return"Linux";case"freebsd":return"FreeBSD";default:return"Unknown"}}function Mm(){switch(process.arch){case"arm64":return"arm64";case"x64":return"x64";case"ia32":return"x32";default:return process.arch}}function _$(f,m,_={}){let $=_.identity??j0(m),E=[...(f.get("anthropic-beta")??"").split(",").map((C)=>C.trim()).filter(Boolean),..._.extraBetas??[]];return f.set("accept","application/json"),f.set("authorization",`Bearer ${m}`),f.set("content-type","application/json"),f.set("user-agent",lf),f.set("anthropic-beta",Em(_.body,E)),f.set("anthropic-dangerous-direct-browser-access","true"),f.set("anthropic-version","2023-06-01"),f.set("x-app","cli"),f.set("x-client-request-id",N0()),f.set("x-claude-code-session-id",$.sessionId),f.set("x-stainless-arch",Mm()),f.set("x-stainless-lang","js"),f.set("x-stainless-os",Cm()),f.set("x-stainless-package-version",nf),f.set("x-stainless-retry-count","0"),f.set("x-stainless-runtime","node"),f.set("x-stainless-runtime-version",cf),f.set("x-stainless-timeout","600"),f.delete("x-api-key"),f}var Hm=["model","messages","system","tools","tool_choice","metadata","max_tokens","temperature","thinking","context_management","output_config","diagnostics","stream","speed"];function K0(f){let m={};for(let _ of Hm)if(Object.hasOwn(f,_))m[_]=f[_];for(let[_,$]of Object.entries(f))if(!Object.hasOwn(m,_))m[_]=$;return m}import{createHash as Sm}from"node:crypto";var Fm=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 I0(){return function(f){let{exports:{mem:m,xxh32:_,xxh64:$,init32:D,update32:E,digest32:C,init64:M,update64:H,digest64:U}}=f,b=new Uint8Array(m.buffer);function N(F,G){if(m.buffer.byteLength<F+G){let Df=Math.ceil((F+G-m.buffer.byteLength)/65536);m.grow(Df),b=new Uint8Array(m.buffer)}}function j(F,G,Df,d0,v0,t0){N(F);let R=new Uint8Array(F);return b.set(R),Df(0,G),R.set(b.subarray(0,F)),{update(x){let Ef;return b.set(R),typeof x=="string"?(N(3*x.length,F),Ef=W.encodeInto(x,b.subarray(F)).written):(N(x.byteLength,F),b.set(x,F),Ef=x.byteLength),d0(0,F,Ef),R.set(b.subarray(0,F)),this},digest:()=>(b.set(R),t0(v0(0)))}}function I(F){return F>>>0}let S=2n**64n-1n;function A(F){return F&S}let W=new TextEncoder,p=0,y=0n;function xf(F,G=p){return N(3*F.length,0),I(_(0,W.encodeInto(F,b).written,G))}function Pf(F,G=y){return N(3*F.length,0),A($(0,W.encodeInto(F,b).written,G))}return{h32:xf,h32ToString:(F,G=p)=>xf(F,G).toString(16).padStart(8,"0"),h32Raw:(F,G=p)=>(N(F.byteLength,0),b.set(F),I(_(0,F.byteLength,G))),create32:(F=p)=>j(48,F,D,E,C,I),h64:Pf,h64ToString:(F,G=y)=>Pf(F,G).toString(16).padStart(16,"0"),h64Raw:(F,G=y)=>(N(F.byteLength,0),b.set(F),A($(0,F.byteLength,G))),create64:(F=y)=>j(88,F,M,H,U,A)}}((await WebAssembly.instantiate(Fm)).instance)}var Um=0x6e52736ac806831en,bm="cch=00000;";var Gf=/("system":\[\{"type":"text","text":"x-anthropic-billing-header: cc_version=[^;"]+; cc_entrypoint=[^;"]+; )cch=([0-9a-f]{5});/,Nm=/("system":\[\{"type":"text","text":"x-anthropic-billing-header: cc_version=[^;"]+; cc_entrypoint=[^;"]+; )cch=00000;/,G0=null,If=null;async function jm(){if(If)return;G0??=(async()=>{If=(await I0()).h64Raw})(),await G0}async function Km(f){return await jm(),((If?.(f,Um)??0n)&0xfffffn).toString(16).padStart(5,"0")}function Im(f){return f.replace(Gf,`$1${bm}`)}function J0(f){return Gf.exec(f)?.[2]??null}async function O0(f){if(!Gf.test(f))return f;let m=Im(f),_=await Km(new TextEncoder().encode(m));return m.replace(Nm,`$1cch=${_};`)}function Gm(f=X,m=new Date){if(f===X)return Hf;let _=m.toISOString().slice(0,10);return Sm("sha256").update(`${_}${f}`).digest("hex").slice(0,3)}function H$(f,m=X,_,$=new Date){let D=Gm(m,$);return`x-anthropic-billing-header: cc_version=${m}.${D}; cc_entrypoint=${_}; cch=00000;`}var b$="claude-cachekeep",A0=3600000,Jf=300000,Jm=60000,N$="extended-cache-ttl-2025-04-11",Om="## Claude Cache Keep Status",Am="## Claude Cache Keep Enabled",Wm="## Claude Cache Keep Disabled",zm="## Claude Cache Keep Usage",Bm="Usage: `/claude-cachekeep`, `/claude-cachekeep off`, or `/claude-cachekeep HH-HH`.";function a(f){return String(f).padStart(2,"0")}function Lm(f){let m=f.trim();if(!m)return{type:"status"};if(m==="off")return{type:"disable"};let _=/^(\d{1,2})-(\d{1,2})$/.exec(m);if(!_)return{type:"usage"};let $=Number(_[1]),D=Number(_[2]);if(!Number.isInteger($)||!Number.isInteger(D)||$<0||$>23||D<0||D>23||$===D)return{type:"usage"};return{type:"window",startHour:$,endHour:D}}function Af(f){let m=Number(f?.cacheKeep?.startHour),_=Number(f?.cacheKeep?.endHour);if(!Number.isInteger(m)||!Number.isInteger(_)||m<0||m>23||_<0||_>23||m===_)return;return{startHour:m,endHour:_}}function B0(f){return f?.cacheKeep?.enabled===!0&&!!Af(f)}function Vm(f){return B0(f)&&f?.claudeCache?.enabled===!0&&f.claudeCache.mode==="hybrid"}function W0(f,m=new Date){if(!f)return!1;let _=m.getHours();if(f.startHour<f.endHour)return _>=f.startHour&&_<f.endHour;return _>=f.startHour||_<f.endHour}function z0(f=new Date){return`${f.getFullYear()}-${a(f.getMonth()+1)}-${a(f.getDate())}`}function Of(f,m=new Date){if(f&&f.startHour>f.endHour&&m.getHours()<f.endHour){let _=new Date(m);return _.setDate(_.getDate()-1),z0(_)}return z0(m)}function o(f){let m=f.window?`${a(f.window.startHour)}-${a(f.window.endHour)}`:"not configured",_=[`Cache keep: ${f.enabled?"enabled":"disabled"}`,`Window: ${m}`,"Mode requirement: `/claude-cache mode hybrid` must be active."];if(typeof f.hybridActive==="boolean")_.push(`Hybrid active: ${f.hybridActive?"yes":"no"}`);if(typeof f.trackedSessions==="number")_.push(`Tracked sessions: ${f.trackedSessions}`);if(f.nextPrewarmAt)_.push(`Next prewarm: ${new Date(f.nextPrewarmAt).toLocaleString()}`);return _.join(`
|
|
13
|
+
`)}function j$(f){let m=Lm(f.argumentsText),_={enabled:f.enabled??!1,window:f.window,trackedSessions:f.trackedSessions,nextPrewarmAt:f.nextPrewarmAt,hybridActive:f.hybridActive};if(m.type==="status")return[Om,"",o(_)].join(`
|
|
14
|
+
`);if(m.type==="disable")return[Wm,"",o({..._,enabled:!1})].join(`
|
|
15
|
+
`);if(m.type==="window")return[Am,"",o({..._,enabled:!0,window:{startHour:m.startHour,endHour:m.endHour}})].join(`
|
|
16
|
+
`);return[zm,"",Bm,"",o(_)].join(`
|
|
17
|
+
`)}function Wf(f){if(!f||typeof f!=="object")return!1;if(Array.isArray(f))return f.some(Wf);let m=f,_=m.cache_control;if(_&&typeof _==="object"&&_.type==="ephemeral")return!0;return Object.values(m).some(Wf)}async function Qm(f){let m;try{m=JSON.parse(f)}catch{return{ok:!1,reason:"body is not valid JSON"}}if(!Wf(m))return{ok:!1,reason:"body has no explicit cache breakpoints"};let _=structuredClone(m);if(_.max_tokens=0,delete _.stream,_.thinking?.type==="enabled")delete _.thinking;if(_.output_config?.format)delete _.output_config;let E=_.tool_choice;if(E?.type==="tool"||E?.type==="any")delete _.tool_choice;return{ok:!0,bodyText:await O0(JSON.stringify(K0(_)))}}class Xm{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)})})},Jm),"unref"in this.timer)this.timer.unref()}stop(){if(this.timer)clearInterval(this.timer);this.timer=null}stats(f,m=this.options.now?.()??Date.now()){let _=Of(f,new Date(m)),$=[...this.targets.values()].filter((E)=>E.dayKey===_),D=$.length?Math.min(...$.map((E)=>E.cacheExpiresAt-Jf)):void 0;return{trackedSessions:$.length,nextPrewarmAt:D}}track(f){if(!f.sessionId)return{tracked:!1,reason:"missing session id"};if(!B0(f.storage))return{tracked:!1,reason:"cachekeep disabled"};if(f.cacheMode!=="hybrid")return{tracked:!1,reason:"cache mode is not hybrid"};let m=this.options.now?.()??Date.now(),_=Af(f.storage);if(!W0(_,new Date(m)))return{tracked:!1,reason:"outside configured window"};let $={};return f.headers.forEach((D,E)=>{$[E]=D}),this.targets.set(f.sessionId,{id:f.sessionId,url:f.url,headers:$,bodyText:f.bodyText,cacheExpiresAt:m+A0,dayKey:Of(_,new Date(m))}),this.start(),{tracked:!0}}async tick(){let f=await this.options.loadStorage(),m=Af(f),_=this.options.now?.()??Date.now(),$=Of(m,new Date(_));for(let[E,C]of this.targets)if(C.dayKey!==$)this.targets.delete(E);if(!this.targets.size){this.stop();return}if(!Vm(f))return;if(!W0(m,new Date(_)))return;let D=_+Jf;for(let E of this.targets.values()){if(E.cacheExpiresAt>D)continue;await this.prewarm(E,_)}}async prewarm(f,m){let _=await Qm(f.bodyText);if(!_.ok){this.options.log?.("[cachekeep] prewarm skipped",{session:f.id,reason:_.reason}),this.targets.delete(f.id);return}let $=this.options.fetchImpl??fetch,D={...f,bodyText:_.bodyText},E=this.options.prepareHeaders?await this.options.prepareHeaders(new Headers(f.headers),D):new Headers(f.headers);E.delete("content-length"),E.delete("transfer-encoding");let C=await $(f.url,{method:"POST",headers:E,body:_.bodyText});if(!C.ok){this.options.log?.("[cachekeep] prewarm failed",{session:f.id,status:C.status,body:await C.text().catch(()=>"")}),f.cacheExpiresAt=m+Jf+300000;return}await C.body?.cancel().catch(()=>{}),f.cacheExpiresAt=m+A0,this.options.log?.("[cachekeep] prewarm succeeded",{session:f.id})}}import{createHash as Zm}from"node:crypto";import{mkdir as Tm,writeFile as zf}from"node:fs/promises";import{tmpdir as Ym}from"node:os";import{join as Q0}from"node:path";var z$="claude-dump",hm="## Claude Dump Status",qm="## Claude Dump Enabled",xm="## Claude Dump Disabled",Pm="## Claude Dump Usage",Rm="Usage: `/claude-dump`, `/claude-dump on`, or `/claude-dump off`.",im="OPENCODE_ANTHROPIC_AUTH_DUMP_DIR",km=Q0(Ym(),"opencode-anthropic-auth-dumps"),ff=!1,L0=0;function B$(f){ff=f}function X0(){return process.env[im]||km}function wm(f){let m=f.trim().split(/\s+/).filter(Boolean);if(m.length===0)return{type:"status"};if(m.length===1&&m[0]==="on")return{type:"enable"};if(m.length===1&&m[0]==="off")return{type:"disable"};return{type:"usage"}}function e(f){let m=f?.enabled??ff;return[hm,"",`- Enabled: ${m?"enabled":"disabled"}`,`- Directory: ${X0()}`,"- Persisted: ~/.config/opencode/anthropic-auth.json","- Captures: final rewritten Anthropic body plus redacted relay payload metadata","- Warning: body dumps may contain prompt/session content; turn this off after debugging"].join(`
|
|
18
|
+
`)}function L$(f){let m=wm(f.argumentsText),_=f.enabled??ff;if(m.type==="status")return e({enabled:_});if(m.type==="enable")return[qm,"",e({enabled:!0})].join(`
|
|
19
|
+
`);if(m.type==="disable")return[xm,"",e({enabled:!1})].join(`
|
|
20
|
+
`);return[Pm,"",Rm,"",e({enabled:_})].join(`
|
|
21
|
+
`)}function V0(f){return f.length<=16?f:`${f.slice(0,12)}…`}function Z0(f){return Zm("sha256").update(f).digest("hex")}function um(f){return J0(f)}function nm(f,m){if(f==null)return null;if(f===m)return{changed:!1,firstByte:-1,lastPreviousByte:-1,lastCurrentByte:-1,previousBytes:f.length,currentBytes:m.length};let _=0;while(_<f.length&&_<m.length&&f[_]===m[_])_+=1;let $=f.length-1,D=m.length-1;while($>=_&&D>=_&&f[$]===m[D])$-=1,D-=1;return{changed:!0,firstByte:_,lastPreviousByte:$,lastCurrentByte:D,changedPreviousBytes:$-_+1,changedCurrentBytes:D-_+1,previousBytes:f.length,currentBytes:m.length}}function cm(f){try{let m=JSON.parse(f);return m!=null&&typeof m==="object"&&!Array.isArray(m)?m:null}catch(m){return K(`dump body parse failed: ${m instanceof Error?m.message:String(m)}`),null}}function Bf(f){return Z0(JSON.stringify(f))}function lm(f){let m=cm(f);if(!m)return{parseable:!1};let _=Array.isArray(m.messages)?m.messages:[],$=Array.isArray(m.system)?m.system:[],D=_[0],E=_.slice(1);return{parseable:!0,model:typeof m.model==="string"?m.model:void 0,stream:m.stream,systemCount:$.length,messagesCount:_.length,systemHash:Bf($),message0Hash:D===void 0?null:Bf(D),message0Bytes:D===void 0?0:JSON.stringify(D).length,messagesAfter0Hash:Bf(E),messagesAfter0Bytes:JSON.stringify(E).length,cch:um(f)}}function Lf(f){if(Array.isArray(f))return f.map(Lf);if(f==null||typeof f!=="object")return f;let m={};for(let[_,$]of Object.entries(f)){let D=_.toLowerCase();if(D==="authorization"||D==="x-api-key"||D==="cookie"||D==="set-cookie"){m[_]="[redacted]";continue}m[_]=Lf($)}return m}async function T0(f){if(!ff)return;L0+=1;let m=`${new Date().toISOString().replace(/[:.]/g,"-")}-${String(L0).padStart(5,"0")}-${f.transport}-p${f.protocol}-${f.mode}`,_=X0(),$=Q0(_,m);try{await Tm(_,{recursive:!0});let D={id:m,createdAt:new Date().toISOString(),session:V0(f.affinity),transport:f.transport,protocol:f.protocol,mode:f.mode,status:f.status,bodyBytes:f.bodyText.length,relayBytes:f.relayBytes,bodyHash:Z0(f.bodyText),diff:nm(f.previousBodyText,f.bodyText),body:lm(f.bodyText),files:{body:`${$}.body.json`,relay:`${$}.relay.json`,metadata:`${$}.meta.json`}};await Promise.all([zf(`${$}.body.json`,f.bodyText,"utf8"),zf(`${$}.relay.json`,`${JSON.stringify(Lf(f.payload),null,2)}
|
|
22
|
+
`,"utf8"),zf(`${$}.meta.json`,`${JSON.stringify(D,null,2)}
|
|
23
|
+
`,"utf8")]),K(`dumped request id=${m} session=${V0(f.affinity)} body=${$}.body.json meta=${$}.meta.json`)}catch(D){K(`dump failed: ${D instanceof Error?D.message:String(D)}`)}}var Q$="claude-fast";var _f=!1;function X$(){return _f}function Z$(f){_f=f}function pm(f){let m=f.trim().split(/\s+/).filter(Boolean);if(m.length===0)return{type:"status"};if(m.length===1&&m[0]==="on")return{type:"enable"};if(m.length===1&&m[0]==="off")return{type:"disable"};return{type:"usage"}}function mf(f){return["## Claude Fast Mode Status","",`- Enabled: ${f?.enabled??_f?"enabled":"disabled"}`,"- Persisted: ~/.config/opencode/anthropic-auth.json","- Scope: adds Anthropic fast mode to supported Opus requests","- Supported models: claude-opus-4-6, claude-opus-4-7, and claude-opus-4-8",'- Request changes: adds `speed: "fast"` and the `fast-mode-2026-02-01` beta header',"- Note: fast and standard speeds do not share prompt-cache prefixes"].join(`
|
|
24
|
+
`)}function T$(f){let m=pm(f.argumentsText),_=f.enabled??_f;if(m.type==="status")return mf({enabled:_});if(m.type==="enable")return["## Claude Fast Mode Enabled","",mf({enabled:!0})].join(`
|
|
25
|
+
`);if(m.type==="disable")return["## Claude Fast Mode Disabled","",mf({enabled:!1})].join(`
|
|
26
|
+
`);return["## Claude Fast Mode Usage","","Usage: `/claude-fast`, `/claude-fast on`, or `/claude-fast off`.","",mf({enabled:_})].join(`
|
|
27
|
+
`)}var h$="claude-quota",Y0={five_hour:"5h",seven_day:"1w"};function h0(f){return`${Math.round(f*10)/10}%`}function Vf(f,m){let _=Math.max(0,m-f),$=Math.floor(_/60000);if($<1)return"just now";if($===1)return"1m ago";if($<60)return`${$}m ago`;let D=Math.floor($/60),E=$%60;if(E===0)return`${D}h ago`;return`${D}h ${E}m ago`}function ym(f,m){let _=Date.parse(f);if(!Number.isFinite(_))return f;let $=_-m;if($<=0)return"now";let D=Math.max(1,Math.ceil($/60000));if(D<60)return`in ${D}m`;let E=Math.floor(D/60),C=D%60;if(C===0)return`in ${E}h`;return`in ${E}h ${C}m`}function dm(f,m){if(!f)return"";return`, resets ${ym(f,m)}`}function q0(f,m,_){if(!m)return` - ${Y0[f]}: unknown`;return[` - ${Y0[f]}: ${h0(m.remainingPercent)} remaining`,` (${h0(m.usedPercent)} used`,`${dm(m.resetsAt,_)}, checked ${Vf(m.checkedAt,_)})`].join("")}function vm(f){return f.label?.trim()||f.id}function tm(f){return f.lastQuotaRefreshError?.message??f.lastRefreshError?.message}function q$(f,m=new Map){if(!f?.accounts.length)return[];return f.accounts.map((_)=>{let $=m.get(_.id)??tm(_);return{name:vm(_),role:"fallback",enabled:_.enabled!==!1,quota:_.quota,lastRefreshedAt:_.lastRefreshedAt,...$&&{error:$}}})}function x$(f){let m=f.now??Date.now(),_=["## Claude Quotas",""];if(f.refreshedAt)_.push(`Refreshed: ${Vf(f.refreshedAt,m)}`,"");if(!f.accounts.length)return _.push("No Claude OAuth accounts found yet."),_.join(`
|
|
28
|
+
`);for(let $ of f.accounts){let D=$.role==="main"?"main":"fallback",E=$.enabled===!1?" disabled":"";if(_.push(`### ${$.name} (${D}${E})`),$.lastRefreshedAt)_.push(` - Last token refresh: ${Vf($.lastRefreshedAt,m)}`);if($.error)_.push(` - Error: ${$.error}`);_.push(q0("five_hour",$.quota?.five_hour,m)),_.push(q0("seven_day",$.quota?.seven_day,m)),_.push("")}return _.join(`
|
|
29
|
+
`).trimEnd()}import{Buffer as n0}from"node:buffer";import{createHash as gm,randomBytes as sm}from"node:crypto";class Xf extends Error{}var Tf=new Map,x0=new Map,P0=new Set,R0=0;function Qf(){return R0+=1,`req_${Date.now().toString(36)}_${R0.toString(36)}`}function $f(f){if(P0.has(f))return;P0.add(f),K(f)}function u$(f){let m=f?.relay;if(!m)return $f("disabled: no relay config found"),null;if(m.enabled!==!0)return $f("disabled: relay.enabled is not true"),null;if(!m.url?.trim()||!m.token?.trim())return $f("disabled: missing relay url or token"),null;let _=m.transport==="http"?"http":"websocket";return $f(`configured transport=${_} protocol=${_==="websocket"?2:1} url=${m.url.trim()} fallbackToDirect=${m.fallbackToDirect!==!1}`),{enabled:!0,url:m.url.trim(),token:m.token.trim(),fallbackToDirect:m.fallbackToDirect!==!1,transport:_}}function n$(){return sm(32).toString("base64url")}function rm(f){return`sha256:${gm("sha256").update(f).digest("hex")}`}function i0(f,m){let _=0,$=Math.min(f.length,m.length);while(_<$&&f.charCodeAt(_)===m.charCodeAt(_))_++;let D=f.length,E=m.length;while(D>_&&E>_&&f.charCodeAt(D-1)===m.charCodeAt(E-1))D--,E--;return{start:_,deleteCount:D-_,insert:m.slice(_,E)}}function om(f){return f.deleteCount===0&&f.insert.length===0}function k0(f){let m=f.match(/\bcch=([0-9a-f]{5});/),_=m?.[1];if(!_||m.index==null)return null;let $=m.index+4;return{start:$,end:$+_.length,token:_}}function am(f,m,_,$){return`${f.slice(0,m)}${$}${f.slice(_)}`}function c0(f,m){let _=k0(f),$=k0(m);if(_&&$&&_.start===$.start&&_.end-_.start===$.end-$.start&&_.token!==$.token){let D={start:_.start,deleteCount:_.end-_.start,insert:$.token},E=am(f,_.start,_.end,$.token),C=i0(E,m);return om(C)?D:[D,C]}return i0(f,m)}function em(f,m){if(typeof m!=="string")return!1;try{let _=f instanceof Request?new URL(f.url):new URL(f.toString());return _.pathname==="/v1/messages"||_.pathname==="/messages"}catch{return!1}}function f_(f){let m={};for(let[_,$]of f.entries()){if(_==="x-session-affinity"||_==="x-opencode-session")continue;m[_]=$}return m}async function w0(f,m){return fetch(f.url,{method:"POST",headers:{"content-type":"application/json","x-relay-token":f.token},body:JSON.stringify(m)})}function O(f){return f.length>12?`${f.slice(0,12)}…`:f}function Z(){return performance.now()}function q(f){return Math.round(f*10)/10}function m_(f){let{input:m,init:_,headers:$,bodyText:D,affinity:E,previous:C,nextHash:M}=f,H=m instanceof Request?m.url:m.toString(),U={protocol:1,type:"request",affinity:E,upstream:{url:H,method:_?.method||(m instanceof Request?m.method:"POST"),headers:f_($)},next_hash:M};return C?{...U,mode:"patch",base_hash:C.hash,revision:C.revision+1,patch:c0(C.body,D)}:{...U,mode:"full_sync",revision:1,body:D}}function Zf(f,m){return{protocol:f.protocol,type:"request",affinity:f.affinity,upstream:f.upstream,next_hash:f.next_hash,mode:"full_sync",revision:1,body:m}}function l0(f,m,_,$){Tf.set(f,{body:m,hash:_,revision:$})}async function u0(f){let{config:m,payload:_,bodyText:$,fallback:D}=f,E=_,C=await w0(m,E);if(C.status===409&&E.mode==="patch")K(`state mismatch from relay session=${O(E.affinity)}; retrying full_sync`),await C.body?.cancel().catch(()=>{}),E=Zf(E,$),C=await w0(m,E);if(!C.ok&&C.status>=500&&m.fallbackToDirect)return K(`relay returned ${C.status}; falling back direct session=${O(E.affinity)}`),await C.body?.cancel().catch(()=>{}),{response:await D(),payload:E,transport:"http",protocol:E.protocol,usedRelay:!1};return{response:C,payload:E,transport:"http",protocol:E.protocol,usedRelay:!0}}function __(f,m){let _=new URL(f);return _.protocol=_.protocol==="http:"?"ws:":"wss:",_.pathname="/ws",_.searchParams.set("token",m),_.toString()}function $_(f){return new Uint8Array(n0.from(f,"base64"))}function D_(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(n0.from(String(f)))}function E_(f){return JSON.parse(f)}class p0{config;affinity;socket;connecting;queue=Promise.resolve();pending;serverState;constructor(f,m){this.config=f,this.affinity=m}send(f,m,_=!1){let $=Z(),D=this.queue.catch(()=>{}).then(()=>this.startQueued(f,m,$,_)),E=D.then(async({response:C,getPayload:M})=>({response:await C,payload:M(),transport:"websocket",protocol:2,usedRelay:!0}));return this.queue=D.then(({done:C})=>C.catch(()=>{}),()=>{}),E}async startQueued(f,m,_,$){let D=Z();await this.ensureConnected();let E=Z(),C=Tf.get(this.affinity),M=this.serverState?.hash,H={...f,protocol:2,id:Qf()};if(H.mode==="patch"&&(!M||M!==H.base_hash))H.mode="full_sync",H.revision=(this.serverState?.revision??0)+1,delete H.base_hash,delete H.patch,H.body=m;if(H.mode==="patch"&&C)H.patch=c0(C.body,m);K(`perf websocket send_start session=${O(this.affinity)} request=${H.id} mode=${H.mode} queueMs=${q(E-_)} connectMs=${q(E-D)} bodyBytes=${m.length} relayBytes=${JSON.stringify(H).length}`);let U=H,b=this.sendPayload(H,m,$);b.done.catch(()=>{});let N=b.done,j=b.response.catch((S)=>{if(!(S instanceof Xf)||H.mode!=="patch")throw S;let A=Zf(H,m);A.protocol=2,A.id=Qf(),A.revision=(this.serverState?.revision??0)+1,U=A;let W=this.sendPayload(A,m,$);return W.done.catch(()=>{}),N=W.done,W.response}),I=j.then(()=>N,()=>N.catch(()=>{}));return{response:j,done:I,getPayload:()=>U}}async ensureConnected(){if(this.socket?.readyState===WebSocket.OPEN&&this.serverState!==void 0)return;if(this.connecting)return await this.connecting;this.connecting=new Promise((f,m)=>{let _=__(this.config.url,this.config.token),$=new URL(_);$.searchParams.set("affinity",this.affinity);let D=new WebSocket($.toString());this.socket=D,this.serverState=void 0;let E=setTimeout(()=>{D.close(),m(Error("relay websocket ready timed out"))},15000);D.addEventListener("message",(C)=>{try{if(typeof C.data!=="string"){this.handleBinaryChunk(C.data);return}let M=E_(C.data);if(M.type==="ready"){clearTimeout(E),this.serverState=M.state,f();return}this.handleMessage(M)}catch(M){clearTimeout(E),m(M),this.failPending(M),D.close()}}),D.addEventListener("error",()=>{clearTimeout(E);let C=Error("relay websocket error");m(C),this.failPending(C)}),D.addEventListener("close",()=>{if(clearTimeout(E),this.socket===D)this.socket=void 0,this.serverState=void 0,this.connecting=void 0;if(this.pending){if(this.pending.retryingBeforeResponse)return;if(this.retryPendingBeforeResponse(this.pending,"closed before response"))return;let C=Error("relay websocket closed before response");this.failPending(C)}})}).finally(()=>{this.connecting=void 0}),await this.connecting}sendPayload(f,m,_){let $=this.socket;if(!$||$.readyState!==WebSocket.OPEN)throw Error("relay websocket is not connected");let D=Z(),E,C,M=new Promise((U,b)=>{E=U,C=b});return{response:new Promise((U,b)=>{let N={payload:f,bodyText:m,resolve:U,reject:b,streamDone:!1,accepted:!1,responseStarted:!1,resolveDone:E,rejectDone:C,sentAt:D,optimisticResponse:_,retryAttempts:0,retryingBeforeResponse:!1};if(this.pending=N,this.resetPendingTimeout(N),$.send(JSON.stringify(f)),_)this.resolvePendingResponse(N,200,"OK",{"content-type":"text/event-stream","x-cortexkit-relay-optimistic":"true"})}),done:M}}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,m){if(f.responseStartedAt!=null)return!1;if(f.streamDone)return!1;if(f.retryAttempts>=1)return!1;f.retryAttempts+=1,f.retryingBeforeResponse=!0,clearTimeout(f.timeout);let _=f.retryAttempts,$=f.payload.id;return K(`websocket ${m}; reconnecting and retrying full_sync session=${O(this.affinity)} request=${$} retry=${_}`),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 D=Zf(f.payload,f.bodyText);D.protocol=2,D.id=Qf(),D.revision=(this.serverState?.revision??0)+1,f.payload=D,f.accepted=!1,f.acceptedAt=void 0,f.responseStartedAt=void 0,f.sentAt=Z(),f.retryingBeforeResponse=!1;let E=this.socket;if(!E||E.readyState!==WebSocket.OPEN)throw Error("relay websocket is not connected");this.resetPendingTimeout(f),K(`perf websocket retry_send session=${O(this.affinity)} request=${D.id} previous=${$} mode=full_sync retry=${_} bodyBytes=${f.bodyText.length} relayBytes=${JSON.stringify(D).length}`),E.send(JSON.stringify(D))}catch(D){if(f.retryingBeforeResponse=!1,this.pending===f)this.failPending(D)}})(),!0}handleBinaryChunk(f){let m=this.pending;if(!m?.responseStarted)return;m.streamController?.enqueue(D_(f))}resolvePendingResponse(f,m,_,$){if(f.responseStarted)return;f.responseStarted=!0;let D=new ReadableStream({start:(E)=>{f.streamController=E},cancel:()=>{this.socket?.close()}});f.resolve(new Response(D,{status:m,statusText:_,headers:$}))}handleMessage(f){if(f.type==="keepalive"){if(this.pending)this.resetPendingTimeout(this.pending);return}let m=this.pending;if(!m)return;if("id"in f&&f.id&&f.id!==m.payload.id)return;if(f.type==="accepted"){let _=Z();m.accepted=!0,m.acceptedAt=_,K(`perf websocket accepted session=${O(this.affinity)} request=${m.payload.id} sentMs=${q(_-m.sentAt)} mode=${m.payload.mode}`),this.serverState={hash:f.hash,revision:f.revision},l0(this.affinity,m.bodyText,f.hash,f.revision),this.resetPendingTimeout(m);return}if(f.type==="response_start"){let _=Z();if(m.responseStartedAt=_,K(`perf websocket response_start session=${O(this.affinity)} request=${m.payload.id} sentMs=${q(_-m.sentAt)} upstreamMs=${m.acceptedAt==null?"unknown":q(_-m.acceptedAt)} status=${f.status}`),clearTimeout(m.timeout),this.resolvePendingResponse(m,f.status,f.statusText,f.headers),m.optimisticResponse&&f.status>=400)m.streamController?.enqueue(new TextEncoder().encode(`event: error
|
|
30
|
+
data: ${JSON.stringify({type:"error",error:{type:"relay_upstream_error",message:`Relay upstream returned HTTP ${f.status}`}})}
|
|
31
|
+
|
|
32
|
+
`)),this.finishPending();return}if(f.type==="chunk"){m.streamController?.enqueue($_(f.base64));return}if(f.type==="done"){this.finishPending();return}if(f.type==="error"){if(m.optimisticResponse&&m.responseStartedAt!=null){K(`websocket relay error during optimistic response session=${O(this.affinity)} request=${m.payload.id} status=${f.status} message=${f.message||"unknown"}`),m.streamController?.enqueue(new TextEncoder().encode(`event: error
|
|
33
|
+
data: ${JSON.stringify({type:"error",error:{type:"relay_error",message:f.message||"relay error"}})}
|
|
34
|
+
|
|
35
|
+
`)),this.finishPending(),this.socket?.close();return}if(f.status===409&&this.retryPendingBeforeResponse(m,f.message||"state mismatch"))return;let _=f.status===409?new Xf(f.message||"state mismatch"):Error(f.message||"relay websocket error");this.failPending(_)}}finishPending(){let f=this.pending;if(!f)return;let m=Z();if(K(`perf websocket done session=${O(this.affinity)} request=${f.payload.id} sentMs=${q(m-f.sentAt)} streamMs=${f.responseStartedAt==null?"unknown":q(m-f.responseStartedAt)}`),clearTimeout(f.timeout),!f.streamDone)f.streamDone=!0,f.streamController?.close();f.resolveDone(),this.pending=void 0}failPending(f){let m=this.pending;if(!m)return;if(clearTimeout(m.timeout),this.pending=void 0,m.responseStarted)m.streamController?.error(f);else m.reject(f);m.rejectDone(f)}}function C_(f,m){let _=x0.get(m);if(_)return _;let $=new p0(f,m);return x0.set(m,$),$}async function c$(f){let{config:m,input:_,init:$,headers:D,body:E,fallback:C,affinity:M,optimisticResponse:H}=f;if(!m||!em(_,E))return C();let U=M||D.get("x-session-affinity")||D.get("x-opencode-session");if(!U)return K("skipping relay: missing x-session-affinity header"),C();let b=E,N=rm(b),j=Tf.get(U),I=m_({input:_,init:$,headers:D,bodyText:b,affinity:U,previous:j,nextHash:N});try{let S;if(m.transport==="websocket")try{S=await C_(m,U).send(I,b,H===!0)}catch(W){K(`websocket relay failed session=${O(U)}; trying http relay: ${W instanceof Error?W.message:String(W)}`),S=await u0({config:m,payload:I,bodyText:b,fallback:C})}else S=await u0({config:m,payload:I,bodyText:b,fallback:C});if(!S.usedRelay)return S.response;if(S.transport==="http")l0(U,b,S.payload.next_hash,S.payload.revision);let A=JSON.stringify(S.payload).length;return K(`used relay transport=${S.transport} protocol=${S.protocol} mode=${S.payload.mode} status=${S.response.status} session=${O(U)} bodyBytes=${b.length} relayBytes=${A}`),await T0({affinity:U,transport:S.transport,protocol:S.protocol,mode:S.payload.mode,status:S.response.status,bodyText:b,previousBodyText:j?.body,payload:S.payload,relayBytes:A}),S.response}catch(S){if(!m.fallbackToDirect)throw K(`relay failed session=${O(U)} and fallbackToDirect=false: ${S instanceof Error?S.message:String(S)}`),S;return K(`relay failed; falling back direct session=${O(U)}: ${S instanceof Error?S.message:String(S)}`),C()}}var l$=`
|
|
36
|
+
async function hashBody(body) {
|
|
37
|
+
const bytes = new TextEncoder().encode(body)
|
|
38
|
+
const digest = await crypto.subtle.digest('SHA-256', bytes)
|
|
39
|
+
const hex = [...new Uint8Array(digest)].map((b) => b.toString(16).padStart(2, '0')).join('')
|
|
40
|
+
return 'sha256:' + hex
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function applyPatch(base, patch) {
|
|
44
|
+
return base.slice(0, patch.start) + patch.insert + base.slice(patch.start + patch.deleteCount)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function applyPatchSet(base, patch) {
|
|
48
|
+
if (!Array.isArray(patch)) return applyPatch(base, patch)
|
|
49
|
+
if (patch.length === 0) return base
|
|
50
|
+
|
|
51
|
+
let result = ''
|
|
52
|
+
let cursor = 0
|
|
53
|
+
for (const item of patch) {
|
|
54
|
+
if (item.start < cursor) return { error: 'overlapping patch', status: 400 }
|
|
55
|
+
result += base.slice(cursor, item.start)
|
|
56
|
+
result += item.insert
|
|
57
|
+
cursor = item.start + item.deleteCount
|
|
58
|
+
}
|
|
59
|
+
return result + base.slice(cursor)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async function readState(env, affinity) {
|
|
63
|
+
const raw = await env.RELAY_STATE.get('session:' + affinity)
|
|
64
|
+
return raw ? JSON.parse(raw) : null
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async function writeState(env, affinity, state) {
|
|
68
|
+
await env.RELAY_STATE.put('session:' + affinity, JSON.stringify(state), { expirationTtl: 86400 })
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async function resolveBody(env, payload) {
|
|
72
|
+
if (payload.mode === 'full_sync') return payload.body
|
|
73
|
+
if (payload.mode === 'patch') {
|
|
74
|
+
const state = await readState(env, payload.affinity)
|
|
75
|
+
if (!state || state.hash !== payload.base_hash) {
|
|
76
|
+
return { error: 'state mismatch', status: 409 }
|
|
77
|
+
}
|
|
78
|
+
return applyPatchSet(state.body, payload.patch)
|
|
79
|
+
}
|
|
80
|
+
return { error: 'unknown mode', status: 400 }
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
async function prepareUpstream(env, payload) {
|
|
84
|
+
if ((payload.protocol !== 1 && payload.protocol !== 2) || payload.type !== 'request' || !payload.affinity || !payload.upstream?.url || !payload.next_hash) {
|
|
85
|
+
return { error: 'invalid payload', status: 400 }
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const body = await resolveBody(env, payload)
|
|
89
|
+
if (body && typeof body === 'object' && 'error' in body) return body
|
|
90
|
+
|
|
91
|
+
if (typeof body !== 'string' || (await hashBody(body)) !== payload.next_hash) {
|
|
92
|
+
return { error: 'hash mismatch', status: 409 }
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const stateWrite = writeState(env, payload.affinity, { body, hash: payload.next_hash, revision: payload.revision }).catch(() => {})
|
|
96
|
+
console.log(JSON.stringify({
|
|
97
|
+
relay: 'opencode-anthropic-auth',
|
|
98
|
+
transport: 'relay',
|
|
99
|
+
mode: payload.mode,
|
|
100
|
+
revision: payload.revision,
|
|
101
|
+
affinity: String(payload.affinity).slice(0, 12),
|
|
102
|
+
bodyBytes: body.length,
|
|
103
|
+
}))
|
|
104
|
+
|
|
105
|
+
return { body, stateWrite }
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function resolveBodyFromState(state, payload) {
|
|
109
|
+
if (payload.mode === 'full_sync') return payload.body
|
|
110
|
+
if (payload.mode === 'patch') {
|
|
111
|
+
if (!state || state.hash !== payload.base_hash) {
|
|
112
|
+
return { error: 'state mismatch', status: 409 }
|
|
113
|
+
}
|
|
114
|
+
return applyPatchSet(state.body, payload.patch)
|
|
115
|
+
}
|
|
116
|
+
return { error: 'unknown mode', status: 400 }
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function deferWorkerTask(task) {
|
|
120
|
+
return new Promise((resolve) => setTimeout(resolve, 0)).then(task)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function checkpointWebSocketState(env, payload, body, nextState) {
|
|
124
|
+
return deferWorkerTask(async () => {
|
|
125
|
+
try {
|
|
126
|
+
if ((await hashBody(body)) !== payload.next_hash) {
|
|
127
|
+
throw new Error('hash mismatch')
|
|
128
|
+
}
|
|
129
|
+
await writeState(env, payload.affinity, nextState)
|
|
130
|
+
} catch (error) {
|
|
131
|
+
console.log(JSON.stringify({
|
|
132
|
+
relay: 'opencode-anthropic-auth',
|
|
133
|
+
transport: 'websocket',
|
|
134
|
+
event: 'checkpoint_write_failed',
|
|
135
|
+
affinity: String(payload.affinity).slice(0, 12),
|
|
136
|
+
message: error instanceof Error ? error.message : String(error),
|
|
137
|
+
}))
|
|
138
|
+
}
|
|
139
|
+
})
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
async function prepareWebSocketUpstream(env, state, payload) {
|
|
143
|
+
if (payload.protocol !== 2 || payload.type !== 'request' || !payload.id || !payload.affinity || !payload.upstream?.url || !payload.next_hash) {
|
|
144
|
+
return { error: 'invalid payload', status: 400 }
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const body = resolveBodyFromState(state, payload)
|
|
148
|
+
if (body && typeof body === 'object' && 'error' in body) return body
|
|
149
|
+
if (typeof body !== 'string') return { error: 'invalid body', status: 400 }
|
|
150
|
+
if ((await hashBody(body)) !== payload.next_hash) {
|
|
151
|
+
return { error: 'hash mismatch', status: 409 }
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const nextState = { body, hash: payload.next_hash, revision: payload.revision }
|
|
155
|
+
const checkpoint = checkpointWebSocketState(env, payload, body, nextState)
|
|
156
|
+
const logAccepted = () => console.log(JSON.stringify({
|
|
157
|
+
relay: 'opencode-anthropic-auth',
|
|
158
|
+
transport: 'websocket',
|
|
159
|
+
mode: payload.mode,
|
|
160
|
+
revision: payload.revision,
|
|
161
|
+
affinity: String(payload.affinity).slice(0, 12),
|
|
162
|
+
bodyBytes: body.length,
|
|
163
|
+
}))
|
|
164
|
+
|
|
165
|
+
return { body, state: nextState, checkpoint, logAccepted }
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function headersToObject(headers) {
|
|
169
|
+
const result = {}
|
|
170
|
+
for (const [key, value] of headers.entries()) result[key] = value
|
|
171
|
+
return result
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
async function handleRelayPayload(env, payload) {
|
|
175
|
+
const prepared = await prepareUpstream(env, payload)
|
|
176
|
+
if (prepared.error) return prepared
|
|
177
|
+
const upstream = await fetch(payload.upstream.url, {
|
|
178
|
+
method: payload.upstream.method || 'POST',
|
|
179
|
+
headers: payload.upstream.headers,
|
|
180
|
+
body: prepared.body,
|
|
181
|
+
})
|
|
182
|
+
return { upstream, stateWrite: prepared.stateWrite }
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
async function handleWebSocket(socket, env, ctx, payload, getState, setState) {
|
|
186
|
+
const heartbeat = setInterval(() => {
|
|
187
|
+
try {
|
|
188
|
+
socket.send(JSON.stringify({ protocol: 2, type: 'keepalive' }))
|
|
189
|
+
} catch {
|
|
190
|
+
clearInterval(heartbeat)
|
|
191
|
+
}
|
|
192
|
+
}, 15000)
|
|
193
|
+
try {
|
|
194
|
+
const result = await prepareWebSocketUpstream(env, getState(), payload)
|
|
195
|
+
if (result.error) {
|
|
196
|
+
socket.send(JSON.stringify({ protocol: 2, type: 'error', id: payload.id, status: result.status, message: result.error }))
|
|
197
|
+
return
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
setState(result.state)
|
|
201
|
+
socket.send(JSON.stringify({ protocol: 2, type: 'accepted', id: payload.id, hash: result.state.hash, revision: result.state.revision }))
|
|
202
|
+
ctx?.waitUntil?.(deferWorkerTask(result.logAccepted))
|
|
203
|
+
|
|
204
|
+
const upstreamPromise = fetch(payload.upstream.url, {
|
|
205
|
+
method: payload.upstream.method || 'POST',
|
|
206
|
+
headers: payload.upstream.headers,
|
|
207
|
+
body: result.body,
|
|
208
|
+
})
|
|
209
|
+
ctx?.waitUntil?.(result.checkpoint)
|
|
210
|
+
const upstream = await upstreamPromise
|
|
211
|
+
socket.send(JSON.stringify({
|
|
212
|
+
protocol: 2,
|
|
213
|
+
type: 'response_start',
|
|
214
|
+
id: payload.id,
|
|
215
|
+
status: upstream.status,
|
|
216
|
+
statusText: upstream.statusText,
|
|
217
|
+
headers: headersToObject(upstream.headers),
|
|
218
|
+
}))
|
|
219
|
+
|
|
220
|
+
const reader = upstream.body?.getReader()
|
|
221
|
+
if (reader) {
|
|
222
|
+
while (true) {
|
|
223
|
+
const { done, value } = await reader.read()
|
|
224
|
+
if (done) break
|
|
225
|
+
socket.send(value)
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
socket.send(JSON.stringify({ protocol: 2, type: 'done', id: payload.id }))
|
|
229
|
+
} catch (error) {
|
|
230
|
+
socket.send(JSON.stringify({ protocol: 2, type: 'error', id: payload.id, status: 500, message: error instanceof Error ? error.message : String(error) }))
|
|
231
|
+
} finally {
|
|
232
|
+
clearInterval(heartbeat)
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
export default {
|
|
237
|
+
async fetch(request, env, ctx) {
|
|
238
|
+
if (request.headers.get('Upgrade') === 'websocket') {
|
|
239
|
+
const url = new URL(request.url)
|
|
240
|
+
const token = url.searchParams.get('token')
|
|
241
|
+
const affinity = url.searchParams.get('affinity')
|
|
242
|
+
if (token !== env.RELAY_TOKEN) return new Response('unauthorized', { status: 401 })
|
|
243
|
+
if (!affinity) return new Response('missing affinity', { status: 400 })
|
|
244
|
+
const pair = new WebSocketPair()
|
|
245
|
+
const client = pair[0]
|
|
246
|
+
const server = pair[1]
|
|
247
|
+
server.binaryType = 'arraybuffer'
|
|
248
|
+
let state = null
|
|
249
|
+
let ready = false
|
|
250
|
+
server.accept()
|
|
251
|
+
const loadState = readState(env, affinity).then((loadedState) => {
|
|
252
|
+
state = loadedState
|
|
253
|
+
ready = true
|
|
254
|
+
server.send(JSON.stringify({
|
|
255
|
+
protocol: 2,
|
|
256
|
+
type: 'ready',
|
|
257
|
+
state: state ? { hash: state.hash, revision: state.revision } : null,
|
|
258
|
+
}))
|
|
259
|
+
}).catch((error) => {
|
|
260
|
+
server.send(JSON.stringify({ protocol: 2, type: 'error', status: 500, message: error instanceof Error ? error.message : String(error) }))
|
|
261
|
+
server.close(1011, 'state load failed')
|
|
262
|
+
})
|
|
263
|
+
ctx?.waitUntil?.(loadState)
|
|
264
|
+
if (!ctx?.waitUntil) void loadState
|
|
265
|
+
let busy = false
|
|
266
|
+
server.addEventListener('message', (event) => {
|
|
267
|
+
if (!ready) {
|
|
268
|
+
server.send(JSON.stringify({ protocol: 2, type: 'error', status: 425, message: 'relay state is not ready' }))
|
|
269
|
+
return
|
|
270
|
+
}
|
|
271
|
+
if (busy) {
|
|
272
|
+
server.send(JSON.stringify({ protocol: 2, type: 'error', status: 429, message: 'request already in flight' }))
|
|
273
|
+
return
|
|
274
|
+
}
|
|
275
|
+
let payload
|
|
276
|
+
try {
|
|
277
|
+
payload = JSON.parse(event.data)
|
|
278
|
+
} catch {
|
|
279
|
+
server.send(JSON.stringify({ protocol: 2, type: 'error', status: 400, message: 'invalid JSON payload' }))
|
|
280
|
+
return
|
|
281
|
+
}
|
|
282
|
+
payload.affinity = affinity
|
|
283
|
+
busy = true
|
|
284
|
+
const run = handleWebSocket(server, env, ctx, payload, () => state, (nextState) => { state = nextState }).finally(() => { busy = false })
|
|
285
|
+
ctx?.waitUntil?.(run)
|
|
286
|
+
if (!ctx?.waitUntil) void run
|
|
287
|
+
})
|
|
288
|
+
return new Response(null, { status: 101, webSocket: client })
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
if (request.method === 'GET') {
|
|
292
|
+
return Response.json({ status: 'ok', transports: ['http', 'websocket'] })
|
|
293
|
+
}
|
|
294
|
+
if (request.method !== 'POST') return new Response('method not allowed', { status: 405 })
|
|
295
|
+
if (request.headers.get('x-relay-token') !== env.RELAY_TOKEN) {
|
|
296
|
+
return new Response('unauthorized', { status: 401 })
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
try {
|
|
300
|
+
const payload = await request.json()
|
|
301
|
+
const result = await handleRelayPayload(env, payload)
|
|
302
|
+
if (result.error) return Response.json({ error: result.error }, { status: result.status })
|
|
303
|
+
|
|
304
|
+
if (result.stateWrite) ctx.waitUntil(result.stateWrite)
|
|
305
|
+
|
|
306
|
+
const upstream = result.upstream
|
|
307
|
+
return new Response(upstream.body, {
|
|
308
|
+
status: upstream.status,
|
|
309
|
+
statusText: upstream.statusText,
|
|
310
|
+
headers: upstream.headers,
|
|
311
|
+
})
|
|
312
|
+
} catch (error) {
|
|
313
|
+
return Response.json(
|
|
314
|
+
{ error: error instanceof Error ? error.message : 'internal relay error' },
|
|
315
|
+
{ status: 502 },
|
|
316
|
+
)
|
|
317
|
+
}
|
|
318
|
+
},
|
|
319
|
+
}
|
|
320
|
+
`;var d$="claude-routing",hf=["main-first","fallback-first"],qf="main-first",y0="Usage: `/claude-routing`, `/claude-routing main-first`, or `/claude-routing fallback-first`.";function M_(f){return typeof f==="string"&&hf.includes(f)?f:qf}function v$(f){return M_(f?.routing?.mode)}async function t$(f,m=B()){let _=await V(m)??{version:1,main:{type:"opencode",provider:"anthropic"},accounts:[]};return _.routing={..._.routing??{},mode:f},await Q(_,m),_}function H_(f){let m=f.trim().toLowerCase().split(/\s+/).filter(Boolean);if(m.length===0)return{type:"status"};if(m.length===1&&hf.includes(m[0]))return{type:"mode",mode:m[0]};if(m.length===2&&m[0]==="mode"&&hf.includes(m[1]))return{type:"mode",mode:m[1]};return{type:"usage"}}function F_(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 Yf(f){let m=f?.mode??qf;return["## Claude Routing Status","",`- Mode: \`${m}\``,`- Behavior: ${F_(m)}`,"",y0].join(`
|
|
321
|
+
`)}function g$(f){let m=H_(f.argumentsText),_=f.mode??qf;if(m.type==="status")return Yf({mode:_});if(m.type==="mode")return["## Claude Routing Updated","",`Mode updated to \`${m.mode}\`.`,"",...Yf({mode:m.mode}).split(`
|
|
322
|
+
`).slice(2)].join(`
|
|
323
|
+
`);return["## Claude Routing Usage","",y0,"",...Yf({mode:_}).split(`
|
|
324
|
+
`).slice(2)].join(`
|
|
325
|
+
`)}export{S_ as a,wf as b,U_ as c,b_ as d,N_ as e,j_ as f,K_ as g,uf as h,I_ as i,G_ as j,T as k,vf as l,z_ as m,B_ as n,L as o,B as p,V as q,Q as r,h1 as s,x_ as t,x1 as u,P_ as v,R_ as w,i_ as x,k_ as y,w_ as z,u_ as A,n_ as B,c_ as C,l_ as D,M0 as E,u1 as F,k as G,Sf as H,w as I,F0 as J,p_ as K,_0 as L,d1 as M,v_ as N,t_ as O,g_ as P,s_ as Q,r1 as R,r_ as S,O0 as T,H$ as U,f$ as V,m$ as W,_$ as X,K0 as Y,b$ as Z,N$ as _,Lm as $,Af as aa,B0 as ba,Vm as ca,j$ as da,Xm as ea,z$ as fa,B$ as ga,wm as ha,L$ as ia,Q$ as ja,X$ as ka,Z$ as la,pm as ma,T$ as na,h$ as oa,q$ as pa,x$ as qa,u$ as ra,n$ as sa,c$ as ta,l$ as ua,d$ as va,v$ as wa,t$ as xa,H_ as ya,g$ as za};
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import{$ as
|
|
1
|
+
import{$ as A1,A as v1,B as U1,C as x1,D as S0,E as D0,F as q1,G as n,H as E0,I as H1,J as T0,K as S1,L as R0,M as E1,N as V0,O as K0,P as X0,Q as c,R as T1,S as W0,T as $1,U as G1,V as A0,W as D1,X as V1,Y as K1,Z as Y0,_ as R1,a as r0,aa as C1,b as s0,ba as f1,c as j0,ca as y1,d as J0,da as k1,e as e0,ea as g1,f as l,fa as P0,g as N1,ga as w0,h as j1,ha as m1,i as J1,ia as C0,j as Z1,ja as z0,k as F0,ka as b1,l as L1,la as I0,m as v0,ma as h1,n as U0,na as f0,o as H,oa as Q0,pa as u1,q as T,qa as d1,r as x0,ra as i1,s as _1,t as $0,ta as l1,u as G0,v as M1,va as O0,w as B1,wa as y0,x as q0,xa as p1,y as F1,ya as n1,z as H0,za as k0}from"./index-75s94xp3.js";import{randomUUID as Fj}from"node:crypto";function b(j){return typeof j==="object"&&j!==null}function Vj(j){if(Array.isArray(j))return j;if(b(j)&&Array.isArray(j.data))return j.data;return[]}function Kj(j){if(!b(j)||!b(j.info))return;return typeof j.info.role==="string"?j.info.role:void 0}function d0(j){if(!b(j)||!b(j.info))return null;let J=j.info,Z=b(J.model)?J.model:void 0,G=typeof J.agent==="string"?J.agent:void 0,V=typeof Z?.providerID==="string"?Z.providerID:typeof J.providerID==="string"?J.providerID:void 0,K=typeof Z?.modelID==="string"?Z.modelID:typeof J.modelID==="string"?J.modelID:void 0,_=typeof Z?.variant==="string"?Z.variant:typeof J.variant==="string"?J.variant:void 0;if(!G&&(!V||!K)&&!_)return null;let C={};if(G)C.agent=G;if(V&&K)C.model={providerID:V,modelID:K};if(_)C.variant=_;return C}function i0(j,J){return{agent:j.agent??J.agent,model:j.model??J.model,variant:j.variant??J.variant}}function l0(j){return Boolean(j.agent&&j.model&&j.variant)}async function p0(j,J){if(!j||!J)return null;let Z=j;if(typeof Z.session?.messages!=="function")return null;let G=[];try{G=Vj(await Promise.resolve(Z.session.messages({path:{id:J},query:{limit:100}})))}catch{return null}if(G.length===0)return null;let V={};for(let K=G.length-1;K>=0;K--){if(Kj(G[K])!=="assistant")continue;let _=d0(G[K]);if(!_)continue;if(V=i0(V,_),l0(V))return V}for(let K=G.length-1;K>=0;K--){let _=d0(G[K]);if(!_)continue;if(V=i0(V,_),l0(V))return V}if(!V.agent&&!V.model&&!V.variant)return null;return V}function n0(j){return`${r0}${j.charAt(0).toUpperCase()}${j.slice(1)}`}function Xj(j){if(j==="StructuredOutput")return j;return`${j.charAt(0).toLowerCase()}${j.slice(1)}`}function X1(j,J){let Z=new Headers;if(j instanceof Request)j.headers.forEach((V,K)=>{Z.set(K,V)});let G=J?.headers;if(G){if(G instanceof Headers)G.forEach((V,K)=>{Z.set(K,V)});else if(Array.isArray(G))for(let V of G){let[K,_]=V;if(typeof _<"u")Z.set(K,String(_))}else for(let[V,K]of Object.entries(G))if(typeof K<"u")Z.set(V,String(K))}return Z}function B0(j){return j.set("anthropic-beta",j0(j.get("anthropic-beta"),[s0])),j}function p(j,J,Z={}){return V1(j,J,Z)}function Wj(j){if(j.tools&&Array.isArray(j.tools))j.tools=j.tools.map((J)=>({...J,name:J.name?n0(J.name):J.name}));if(j.messages&&Array.isArray(j.messages))j.messages=j.messages.map((J)=>{if(J.content&&Array.isArray(J.content))J.content=J.content.map((Z)=>{if(Z.type==="tool_use"&&Z.name)return{...Z,name:n0(Z.name)};return Z});return J});return JSON.stringify(K1(j))}function M0(j){return j.replace(/"name"\s*:\s*"mcp_([^"]+)"/g,(J,Z)=>`"name": "${Xj(Z)}"`)}function c0(j,J=!1){if(J)return{ready:M0(j),pending:""};let Z=j.length,G='"name"',V=Math.max(0,j.length-G.length+1);for(let _=V;_<j.length;_++)if(G.startsWith(j.slice(_))){Z=Math.min(Z,_);break}let K=j.lastIndexOf(G);if(K!==-1){let _=j.slice(K);if(/^"name"\s*(?::\s*(?:"[^"]*)?)?$/.test(_))Z=Math.min(Z,K)}if(Z<j.length)return{ready:M0(j.slice(0,Z)),pending:j.slice(Z)};return{ready:M0(j),pending:""}}function W1(){if(!process.env.ANTHROPIC_BASE_URL?.trim())return!1;let j=process.env.ANTHROPIC_INSECURE?.trim();return j==="1"||j==="true"}function Yj(){let j=process.env.ANTHROPIC_BASE_URL?.trim();if(!j)return null;try{let J=new URL(j);if(J.protocol!=="http:"&&J.protocol!=="https:"||J.username||J.password)return null;return J}catch{return null}}function Y1(j){let J=null;try{if(typeof j==="string"||j instanceof URL)J=new URL(j.toString());else if(j instanceof Request)J=new URL(j.url)}catch{J=null}if(!J)return{input:j,url:null};let Z=J.href,G=Yj();if(G)J.protocol=G.protocol,J.host=G.host;if(J.pathname==="/v1/messages"&&!J.searchParams.has("beta"))J.searchParams.set("beta","true");if(J.href===Z)return{input:j,url:J};return{input:j instanceof Request?new Request(J.toString(),j):J,url:J}}function a(j){let G=j.split(/\n\n+/).filter((V)=>{if(V.includes(e0))return!1;for(let K of J1)if(V.includes(K))return!1;return!0}).join(`
|
|
2
2
|
|
|
3
|
-
`);for(let D of s0)$=$.replace(D.match,D.replacement);return $.trim()}function C(j){return j!=null&&typeof j==="object"&&!Array.isArray(j)}function Zj(j){let J={type:"text",text:d};if(j==null)return[J];if(typeof j==="string"){let $=a(j);if($===d)return[J];return[J,{type:"text",text:$}]}if(C(j)){let $=typeof j.type==="string"?j.type:"text",D=typeof j.text==="string"?j.text:"";return[J,{...j,type:$,text:a(D)}]}if(!Array.isArray(j))return[J];let K=j.map(($)=>{if(typeof $==="string")return{type:"text",text:a($)};if(C($)&&$.type==="text"&&typeof $.text==="string")return{...$,type:"text",text:a($.text)};return{type:"text",text:String($)}});if(K[0]?.text===d)return K;return[J,...K]}var V1={type:"ephemeral",ttl:"1h"};function $j(j){if(C(j.cache_control))return j.cache_control;if(C(j.cacheControl))return j.cacheControl;return null}function s(j,J){if(!C(j))return!1;return delete j.cacheControl,j.cache_control=J?{...V1}:{type:"ephemeral"},!0}function n0(j){if(!C(j))return;delete j.cache_control,delete j.cacheControl}function Gj(j){if(Array.isArray(j))return j;if(typeof j==="string")return[{type:"text",text:j}];return null}function r(j,J){if(!C(j))return;let K=$j(j);if(!K||K.type!=="ephemeral")return;if(J)K.ttl="1h";else delete K.ttl}function p0(j,J){if(Array.isArray(j.system))for(let K of j.system)r(K,J);else r(j.system,J);if(!Array.isArray(j.messages))return;for(let K of j.messages)if(r(K,J),C(K)&&Array.isArray(K.content))for(let $ of K.content)r($,J)}function Dj(j,J){if(Array.isArray(j.system))for(let K of j.system)J(K);else J(j.system);if(!Array.isArray(j.messages))return;for(let K of j.messages)if(J(K),C(K)&&Array.isArray(K.content))for(let $ of K.content)J($)}function P1(j){n0(j),Dj(j,n0)}function Vj(j){P1(j),j.cache_control={...V1}}function L0(j){if(!C(j))return!1;let J=Gj(j.content);if(!J?.length)return s(j,!0);j.content=J;let K=[...J].reverse().find(($)=>C($)&&$.type!=="thinking");return s(K??j,!0)}function Pj(j){if(P1(j),Array.isArray(j.system)){let K=j.system.findIndex((V)=>C(V)&&V.text===d),$=j.system.slice(K>=0?K+1:0).filter(C),D=$[$.length-1];s(D,!0)}else s(j.system,!0);if(!Array.isArray(j.messages))return;L0(j.messages[0]),L0(j.messages[1]);let J=j.messages.length-2;if(J>1)L0(j.messages[J])}function Xj(j,J){if(!J.enabled){p0(j,!1),delete j.cache_control,delete j.cacheControl;return}if(J.mode==="automatic"){Vj(j);return}if(J.mode==="hybrid"){Pj(j);return}p0(j,!0),delete j.cacheControl}async function X1(j,J={}){try{let K=JSON.parse(j),$=Array.isArray(K.messages)&&K.messages.some((D)=>D.role==="user")?j1(K.messages,void 0,a0):null;if(K.system=Zj(K.system),$&&Array.isArray(K.system))K.system.unshift({type:"text",text:$});if(Xj(K,{enabled:J.cache1hEnabled??!1,mode:J.cache1hMode??"explicit"}),J.fastModeEnabled&&j0(K.model))K.speed="fast";else if(K.speed==="fast")delete K.speed;if(J.identity)J1(K,J.identity);return await e0(Jj(K))}catch{return j}}function _0(j){if(!j.body)return j;let J=j.body.getReader(),K=new TextDecoder,$=new TextEncoder,D="",V=new ReadableStream({async pull(B){let{done:E,value:y}=await J.read();if(E){let u=i0(`${D}${K.decode()}`,!0);if(u.ready)B.enqueue($.encode(u.ready));B.close();return}let O0=D+K.decode(y,{stream:!0}),h=i0(O0);if(D=h.pending,h.ready)B.enqueue($.encode(h.ready))}});return new Response(V,{status:j.status,statusText:j.statusText,headers:j.headers})}var Yj="__OPENCODE_ANTHROPIC_AUTH_COMMAND_HANDLED__",wj=60000,zj=60000,Ij=5000,W1=200,h1=240,Oj=h1,Qj=1,Y1=!1;function I0(){return process.env.OPENCODE_ANTHROPIC_AUTH_PERF==="1"}function M(){return performance.now()}function S(j){return Math.round(j*10)/10}function w1(j){return Math.floor(Math.random()*Math.max(0,j))}function Lj(){if(Y1||!1||!I0())return;Y1=!0;let j=100,J=250,K=M()+j;setInterval(()=>{let $=M(),D=$-K;if(K=$+j,D<J)return;U("[perf] opencode event_loop_lag",{lagMs:S(D),thresholdMs:J})},j).unref?.()}function Nj(j){let J=M(),K={requestId:String(Qj++),start:J,last:J,mark($,D){let V=M();if(I0())U("[perf] opencode request stage",{requestId:K.requestId,stage:$,deltaMs:S(V-K.last),totalMs:S(V-K.start),...D});K.last=V},done($,D){let V=M();if(I0())U("[perf] opencode request done",{requestId:K.requestId,stage:$,deltaMs:S(V-K.last),totalMs:S(V-K.start),...D});K.last=V}};if(I0())U("[perf] opencode request start",{requestId:K.requestId,...j});return K}async function i(j,J,K){let $=j.client.session,D=await d0(j.client,J),V={path:{id:J},body:{noReply:!0,parts:[{type:"text",text:K,ignored:!0}]}};if(D?.agent)V.body.agent=D.agent;if(D?.model)V.body.model=D.model;if(D?.variant)V.body.variant=D.variant;if(typeof $?.promptAsync==="function"){await $.promptAsync(V);return}if(typeof $?.prompt==="function"){await Promise.resolve($.prompt(V));return}throw Error("OpenCode session prompt API is unavailable for ignored replies.")}function n(){throw Error(Yj)}var qj=async(j)=>{Lj();let{client:J}=j,K=new U1;K.startBackgroundRefresh();let $=null,D=new R1({loadStorage:()=>A(),prepareHeaders:async(Z,Q)=>{if(!E)return Z;let W=await E();if(W.type!=="oauth")return Z;if(!W.access||W.expires&&W.expires<Date.now()){if(!$)return Z;W.access=await $()}if(!W.access)return Z;try{let N=JSON.parse(Q.bodyText),x=await E0(W.access,typeof N.model==="string"?N.model:void 0);if(Z.delete("anthropic-beta"),l(Z,W.access,{body:N,identity:x}),Z.set("anthropic-beta",e(Z.get("anthropic-beta"),[H1])),N.speed==="fast")N0(Z)}catch{l(Z,W.access)}return Z},log:U}),V=await A(),B=b1(V);c({enabled:J0(V),mode:K0(V)}),W0(U0(V)),w0(x0(V));let E=null,y=null;function O0(Z){let Q=Z?.refresh?.refreshBeforeExpiryMinutes??Oj;return Math.max(h1,Q)*60000}function h(Z){return Z?.refresh?.enabled!==!1}async function u(Z){if(!Z)return;let Q=await A(),W=Q?.refresh?.mainLastRefreshError;if(!Q?.refresh||!W?.tokenHash)return;let N=Z0(Z);if(W.tokenHash===N)return;if(W.nextRetryAt&&W.nextRetryAt>Date.now()){U("[refresh] opencode main oauth keeping backoff despite token rotation",{nextRetryAt:W.nextRetryAt,retryCount:W.retryCount,remainingMs:W.nextRetryAt-Date.now()});return}Q.refresh.mainLastRefreshError=void 0,await v0(Q),U("[refresh] opencode main oauth cleared stale backoff after token rotation",{previousCheckedAt:W.checkedAt,previousNextRetryAt:W.nextRetryAt,previousRetryCount:W.retryCount})}async function u1(){let Z=[];if(E)try{let N=await E();if(N.type==="oauth"&&N.access)Z.push({name:"OpenCode anthropic",role:"main",quota:await A0({accessToken:N.access})});else if(N.type==="oauth")Z.push({name:"OpenCode anthropic",role:"main",error:"missing access token; send a request first or reconnect auth"})}catch(N){Z.push({name:"OpenCode anthropic",role:"main",error:N instanceof Error?N.message:String(N)})}let{storage:Q,errors:W}=await K.refreshQuotaForAllAccounts();if(Z.push(...k1(Q,new Map(W.map((N)=>[N.accountId,N.message])))),!E)Z.unshift({name:"OpenCode anthropic",role:"main",error:"auth loader has not run yet; send a request first"});return g1({accounts:Z,refreshedAt:Date.now()})}async function d1(Z){let Q=x1(Z);if(Q.type==="enable"||Q.type==="disable"){let f=Q.type==="enable",k=await O1(f),g=K0(k);return c({enabled:f,mode:g}),V0({argumentsText:Z,enabled:f,mode:g})}if(Q.type==="mode"){let f=await Q1(Q.mode),k=J0(f);return c({enabled:k,mode:Q.mode}),V0({argumentsText:Z,enabled:k,mode:Q.mode})}let W=await A(),N=J0(W),x=K0(W);return c({enabled:N,mode:x}),V0({argumentsText:Z,enabled:N,mode:x})}async function l1(Z){let Q=q1(Z),W=await A();if(Q.type==="window")W=await _1(Q.startHour,Q.endHour);else if(Q.type==="disable")W=await F1(!1);let N=S1(W),x=D.stats(N);return C1({argumentsText:Z,enabled:A1(W),window:N,hybridActive:E1(W),trackedSessions:x.trackedSessions,nextPrewarmAt:x.nextPrewarmAt})}async function i1(Z){let Q=T1(Z);if(Q.type==="enable"||Q.type==="disable"){let x=Q.type==="enable";return await L1(x),W0(x),C0({argumentsText:Z,enabled:x})}let W=await A(),N=U0(W);return W0(N),C0({argumentsText:Z,enabled:N})}async function n1(Z){let Q=y1(Z);if(Q.type==="enable"||Q.type==="disable"){let x=Q.type==="enable";return await N1(x),w0(x),R0({argumentsText:Z,enabled:x})}let W=await A(),N=x0(W);return w0(N),R0({argumentsText:Z,enabled:N})}return{config:async(Z)=>{Z.command={...Z.command??{},[$0]:{template:$0,description:"Show or toggle 1-hour Anthropic ephemeral prompt cache TTL."},[P0]:{template:P0,description:"Keep hybrid Claude cache warm for recently used sessions during a local time window."},[z0]:{template:z0,description:"Show current Claude OAuth quota usage for all accounts."},[X0]:{template:X0,description:"Show or toggle Anthropic request dump capture for debugging."},[Y0]:{template:Y0,description:"Show or toggle Anthropic fast mode for supported Opus models."}}},"command.execute.before":async(Z)=>{if(Z.command===$0)await i(j,Z.sessionID,await d1(Z.arguments)),n();if(Z.command===P0)await i(j,Z.sessionID,await l1(Z.arguments)),n();if(Z.command===z0)await i(j,Z.sessionID,await u1()),n();if(Z.command===X0)await i(j,Z.sessionID,await i1(Z.arguments)),n();if(Z.command===Y0)await i(j,Z.sessionID,await n1(Z.arguments)),n()},auth:{provider:"anthropic",async loader(Z,Q){if(E=Z,(await Z()).type==="oauth"){let p1=function(){if(y)clearInterval(y),y=null;let P=async()=>{try{let X=await A();if(!h(X))return;let z=await Z();if(z.type!=="oauth")return;if(await u(z.refresh),!z.expires)return;let I=z.expires-Date.now(),v=O0(X);if(I>v)return;if(U("[refresh] opencode main oauth background due",{expiresInMs:I,refreshBeforeMs:v}),z.refresh&&p(X?.refresh?.mainLastRefreshError,z.refresh,Date.now())){U("[refresh] opencode main oauth background skipped backoff",{nextRetryAt:X?.refresh?.mainLastRefreshError?.nextRetryAt,retryCount:X?.refresh?.mainLastRefreshError?.retryCount,expiresInMs:I});return}if(z.refresh&&X?.refresh?.mainRefreshLeaseUntil&&X.refresh.mainRefreshLeaseUntil>Date.now()&&X.refresh.mainRefreshLeaseTokenHash===Z0(z.refresh))return;await g();let O=await Z();U("[refresh] opencode main oauth refreshed in background",{newExpiresInMs:O.expires?O.expires-Date.now():void 0})}catch(X){U("[refresh] opencode main oauth refresh failed",{message:X instanceof Error?X.message:String(X)})}};if(y=setInterval(()=>{P()},wj+w1(zj)),"unref"in y)y.unref()},T0=function(P,X){if(P instanceof Request&&P.body)return!1;return X==null||typeof X==="string"},c1=function(P){return P.has("x-parent-session-id")},f0=function(P){return P.includes("rate_limit_error")||/exceed your account'?s rate limit/i.test(P)},o1=function(P){return P?.quota?.enabled===!0},t1=function(P,X){let z=Date.now();if(f||z<k)return;f=g0(P,X).catch((I)=>{throw k=z+M1(X),I}).finally(()=>{f=null}),f.catch(()=>{})};for(let P of Object.values(Q.models))P.cost={input:0,output:0,cache:{read:0,write:0}};let N=null,x=null,f=null,k=0;async function g(){if(!N)N=(async()=>{let z=null,I=null,v=null;async function O(L){let Y=await A()??{version:1,main:{type:"opencode",provider:"anthropic"},accounts:[]};Y.refresh=Y.refresh??{},L(Y),await v0(Y)}async function F(L){let Y=Date.now()+Ij;while(Date.now()<Y){await new Promise((w)=>setTimeout(w,W1+w1(W1)));let G=await Z();if(G.type!=="oauth"||!G.access)continue;if((G.access!==L.access||G.refresh!==L.refresh||(G.expires??0)>(L.expires??0)+60000)&&(!G.expires||G.expires>Date.now()))return U("[refresh] opencode main oauth joined concurrent refresh",{expiresInMs:G.expires?G.expires-Date.now():void 0}),G.access}return null}for(let L=0;L<=2;L++){let Y=null;try{if(L>0){let H=500*2**(L-1);await new Promise((o)=>setTimeout(o,H))}if(Y=await Z(),!Y.refresh)throw Error("Token refresh failed: missing refresh token");let G=await A(),_=Z0(Y.refresh),w=G?.refresh?.mainLastRefreshError;if(U("[refresh] opencode main oauth refresh check",{attempt:L,expiresInMs:Y.expires?Y.expires-Date.now():void 0,hasBackoff:Boolean(w),backoffActive:w?p(w,Y.refresh,Date.now()):!1,retryCount:w?.retryCount,nextRetryAt:w?.nextRetryAt}),w&&p(w,Y.refresh,Date.now()))throw U("[refresh] opencode main oauth refresh skipped backoff",{nextRetryAt:w.nextRetryAt,retryCount:w.retryCount}),Error(q0(w,Date.now()));if(G?.refresh?.mainRefreshLeaseUntil&&G.refresh.mainRefreshLeaseUntil>Date.now()&&G.refresh.mainRefreshLeaseTokenHash===_){U("[refresh] opencode main oauth refresh skipped lease",{leaseUntil:G.refresh.mainRefreshLeaseUntil});let H=await F(Y);if(H)return H;throw Error("Claude OAuth refresh is already in progress")}let q=await I1({name:"opencode-main-oauth-refresh",ttlMs:120000});if(!q){U("[refresh] opencode main oauth refresh skipped file lock");let H=await F(Y);if(H)return H;throw Error("Claude OAuth refresh is already in progress")}v=q.release,z=Wj(),I=_,await O((H)=>{H.refresh=H.refresh??{},H.refresh.mainRefreshLeaseId=z??void 0,H.refresh.mainRefreshLeaseUntil=Date.now()+120000,H.refresh.mainRefreshLeaseTokenHash=_});let R=await A();if(U("[refresh] opencode main oauth refresh lease acquired",{attempt:L,leaseUntil:Date.now()+120000}),R?.refresh?.mainRefreshLeaseId!==z||R.refresh.mainRefreshLeaseTokenHash!==_)throw Error("Claude OAuth refresh is already in progress");U("[refresh] opencode main oauth refresh request start",{attempt:L});let T=await z1({refreshToken:Y.refresh,maxRetries:0});return await J.auth.set({path:{id:"anthropic"},body:{type:"oauth",refresh:T.refresh,access:T.access,expires:T.expires}}),await O((H)=>{if(!H?.refresh)return;if(H.refresh.mainLastRefreshError=void 0,H.refresh.mainRefreshLeaseId===z)H.refresh.mainRefreshLeaseId=void 0,H.refresh.mainRefreshLeaseUntil=void 0,H.refresh.mainRefreshLeaseTokenHash=void 0}),U("[refresh] opencode main oauth refresh succeeded",{attempt:L,expiresInMs:T.expires-Date.now()}),T.access}catch(G){let _=G instanceof Error&&(G.message.includes("fetch failed")||("code"in G)&&(G.code==="ECONNRESET"||G.code==="ECONNREFUSED"||G.code==="ETIMEDOUT"||G.code==="UND_ERR_CONNECT_TIMEOUT"));if(L<2&&(_||G instanceof F0&&G.status>=500))continue;U("[refresh] opencode main oauth refresh attempt failed",{attempt:L,error:G instanceof Error?G.message:String(G),transient:_});let w=Y?.refresh;if(w&&G instanceof F0)await O((q)=>{q.refresh=q.refresh??{},q.refresh.mainLastRefreshError=B1({error:G,now:Date.now(),refreshToken:w,previous:q.refresh.mainLastRefreshError})});throw G}finally{if(z)await O((G)=>{if(!G?.refresh)return;if(G.refresh.mainRefreshLeaseId===z&&G.refresh.mainRefreshLeaseTokenHash===I)G.refresh.mainRefreshLeaseId=void 0,G.refresh.mainRefreshLeaseUntil=void 0,G.refresh.mainRefreshLeaseTokenHash=void 0}).catch(()=>{});await v?.().catch(()=>{})}}throw Error("Token refresh exhausted all retries")})().finally(()=>{N=null});return N}$=g,p1();async function y0(P,X){if(!P.body||P.status!==200)return X?.mark("inspect_stream_skip",{status:P.status}),{response:P,rateLimited:!1};if(P.headers.get("x-cortexkit-relay-optimistic")==="true")return X?.mark("inspect_stream_skip",{status:P.status,reason:"optimistic_relay"}),{response:P,rateLimited:!1};let z=M(),I=P.body.getReader(),v=[],O=new TextDecoder,F="",L=0;while(!F.includes(`
|
|
3
|
+
`);for(let V of Z1)G=G.replace(V.match,V.replacement);return G.trim()}function R(j){return j!=null&&typeof j==="object"&&!Array.isArray(j)}function Pj(j){let J={type:"text",text:l};if(j==null)return[J];if(typeof j==="string"){let G=a(j);if(G===l)return[J];return[J,{type:"text",text:G}]}if(R(j)){let G=typeof j.type==="string"?j.type:"text",V=typeof j.text==="string"?j.text:"";return[J,{...j,type:G,text:a(V)}]}if(!Array.isArray(j))return[J];let Z=j.map((G)=>{if(typeof G==="string")return{type:"text",text:a(G)};if(R(G)&&G.type==="text"&&typeof G.text==="string")return{...G,type:"text",text:a(G.text)};return{type:"text",text:String(G)}});if(Z[0]?.text===l)return Z;return[J,...Z]}var P1={type:"ephemeral",ttl:"1h"},wj=20;function zj(j){if(R(j.cache_control))return j.cache_control;if(R(j.cacheControl))return j.cacheControl;return null}function e(j,J){if(!R(j))return!1;return delete j.cacheControl,j.cache_control=J?{...P1}:{type:"ephemeral"},!0}function o0(j){if(!R(j))return;delete j.cache_control,delete j.cacheControl}function Ij(j){if(Array.isArray(j))return j;if(typeof j==="string")return[{type:"text",text:j}];return null}function r(j,J){if(!R(j))return;let Z=zj(j);if(Z?.type!=="ephemeral")return;if(J)Z.ttl="1h";else delete Z.ttl}function t0(j,J){if(Array.isArray(j.system))for(let Z of j.system)r(Z,J);else r(j.system,J);if(!Array.isArray(j.messages))return;for(let Z of j.messages)if(r(Z,J),R(Z)&&Array.isArray(Z.content))for(let G of Z.content)r(G,J)}function Qj(j,J){if(Array.isArray(j.system))for(let Z of j.system)J(Z);else J(j.system);if(!Array.isArray(j.messages))return;for(let Z of j.messages)if(J(Z),R(Z)&&Array.isArray(Z.content))for(let G of Z.content)J(G)}function w1(j){o0(j),Qj(j,o0)}function Oj(j){w1(j),j.cache_control={...P1}}function s(j){if(!R(j))return!1;let J=Ij(j.content);if(!J?.length)return e(j,!0);j.content=J;let Z=[...J].reverse().find((G)=>R(G)&&G.type!=="thinking");return e(Z??j,!0)}function Nj(j){if(!R(j))return 0;let J=j.content;if(Array.isArray(J))return J.length;if(J==null)return 0;return 1}function Lj(j){let J=[],Z=0;return j.forEach((G,V)=>{let K=Nj(G);if(R(G)&&G.role==="user"&&K>0)J.push({index:V,blockPosition:Z+K-1});Z+=K}),J}function _j(j){let J=Lj(j),Z=[...J].reverse().find((_)=>_.index>1);if(!Z)return{latest:void 0,bridge:void 0};let G=[...J].reverse().find((_)=>_.index<Z.index),V=G?Z.blockPosition-G.blockPosition+1:0,K=G&&G.index>1&&V>wj?G:void 0;return{latest:Z,bridge:K}}function a0(j){if(Array.isArray(j.system)){let J=j.system.findIndex((V)=>R(V)&&V.text===l),Z=j.system.slice(J>=0?J+1:0).filter(R),G=Z[Z.length-1];e(G,!0)}else e(j.system,!0)}function Mj(j){if(w1(j),!Array.isArray(j.messages)){a0(j);return}let{latest:J,bridge:Z}=_j(j.messages);if(!Z)a0(j);if(s(j.messages[0]),s(j.messages[1]),Z)s(j.messages[Z.index]);if(J)s(j.messages[J.index])}function Bj(j,J){if(!J.enabled){t0(j,!1),delete j.cache_control,delete j.cacheControl;return}if(J.mode==="automatic"){Oj(j);return}if(J.mode==="hybrid"){Mj(j);return}t0(j,!0),delete j.cacheControl}async function z1(j,J={}){try{let Z=JSON.parse(j),G=Array.isArray(Z.messages)&&Z.messages.some((V)=>V.role==="user")?G1(Z.messages,void 0,j1):null;if(Z.system=Pj(Z.system),G&&Array.isArray(Z.system))Z.system.unshift({type:"text",text:G});if(Bj(Z,{enabled:J.cache1hEnabled??!1,mode:J.cache1hMode??"explicit"}),J.fastModeEnabled&&J0(Z.model))Z.speed="fast";else if(Z.speed==="fast")delete Z.speed;if(J.identity)D1(Z,J.identity);return await $1(Wj(Z))}catch{return j}}function Z0(j){if(!j.body)return j;let J=j.body.getReader(),Z=new TextDecoder,G=new TextEncoder,V="",K=new ReadableStream({async pull(_){let{done:C,value:y}=await J.read();if(C){let i=c0(`${V}${Z.decode()}`,!0);if(i.ready)_.enqueue(G.encode(i.ready));_.close();return}let L0=V+Z.decode(y,{stream:!0}),d=c0(L0);if(V=d.pending,d.ready)_.enqueue(G.encode(d.ready))}});return new Response(K,{status:j.status,statusText:j.statusText,headers:j.headers})}var vj="__OPENCODE_ANTHROPIC_AUTH_COMMAND_HANDLED__",Uj=60000,xj=60000,qj=5000,I1=200,c1=240,Hj=c1,Sj=1,Q1=!1;function N0(){return process.env.OPENCODE_ANTHROPIC_AUTH_PERF==="1"}function B(){return performance.now()}function E(j){return Math.round(j*10)/10}function O1(j){return Math.floor(Math.random()*Math.max(0,j))}function Ej(){if(Q1||!1||!N0())return;Q1=!0;let j=100,J=250,Z=B()+j;setInterval(()=>{let G=B(),V=G-Z;if(Z=G+j,V<J)return;H("[perf] opencode event_loop_lag",{lagMs:E(V),thresholdMs:J})},j).unref?.()}function Tj(j){let J=B(),Z={requestId:String(Sj++),start:J,last:J,mark(G,V){let K=B();if(N0())H("[perf] opencode request stage",{requestId:Z.requestId,stage:G,deltaMs:E(K-Z.last),totalMs:E(K-Z.start),...V});Z.last=K},done(G,V){let K=B();if(N0())H("[perf] opencode request done",{requestId:Z.requestId,stage:G,deltaMs:E(K-Z.last),totalMs:E(K-Z.start),...V});Z.last=K}};if(N0())H("[perf] opencode request start",{requestId:Z.requestId,...j});return Z}async function h(j,J,Z){let G=j.client.session,V=await p0(j.client,J),K={path:{id:J},body:{noReply:!0,parts:[{type:"text",text:Z,ignored:!0}]}};if(V?.agent)K.body.agent=V.agent;if(V?.model)K.body.model=V.model;if(V?.variant)K.body.variant=V.variant;if(typeof G?.promptAsync==="function"){await G.promptAsync(K);return}if(typeof G?.prompt==="function"){await Promise.resolve(G.prompt(K));return}throw Error("OpenCode session prompt API is unavailable for ignored replies.")}function u(){throw Error(vj)}function Rj(j){if(j.sessionID==null)return!1;let J=j.model;return J?.providerID==="anthropic"||J?.api?.npm==="@ai-sdk/anthropic"||J?.api?.npm==="@ai-sdk/google-vertex/anthropic"}function Aj(j){if(j.some((J)=>J.includes("<use_parallel_tool_calls>")))return!1;return j.push(N1),!0}var uj=async(j)=>{Ej();let{client:J}=j,Z=new E1;Z.startBackgroundRefresh();let G=null,V=new g1({loadStorage:()=>T(),prepareHeaders:async($,Y)=>{if(!C)return $;let w=await C();if(w.type!=="oauth")return $;if(!w.access||w.expires&&w.expires<Date.now()){if(!G)return $;w.access=await G()}if(!w.access)return $;try{let N=JSON.parse(Y.bodyText),S=await A0(w.access,typeof N.model==="string"?N.model:void 0);if($.delete("anthropic-beta"),p($,w.access,{body:N,identity:S}),$.set("anthropic-beta",j0($.get("anthropic-beta"),[R1])),N.speed==="fast")B0($)}catch{p($,w.access)}return $},log:H}),K=await T(),_=i1(K);c({enabled:$0(K),mode:G0(K)}),w0(q0(K)),I0(H0(K));let C=null,y=null;function L0($){let Y=$?.refresh?.refreshBeforeExpiryMinutes??Hj;return Math.max(c1,Y)*60000}function d($){return $?.refresh?.enabled!==!1}async function i($){if(!$)return;let Y=await T(),w=Y?.refresh?.mainLastRefreshError;if(!Y?.refresh||!w?.tokenHash)return;let N=D0($);if(w.tokenHash===N)return;if(w.nextRetryAt&&w.nextRetryAt>Date.now()){H("[refresh] opencode main oauth keeping backoff despite token rotation",{nextRetryAt:w.nextRetryAt,retryCount:w.retryCount,remainingMs:w.nextRetryAt-Date.now()});return}Y.refresh.mainLastRefreshError=void 0,await x0(Y),H("[refresh] opencode main oauth cleared stale backoff after token rotation",{previousCheckedAt:w.checkedAt,previousNextRetryAt:w.nextRetryAt,previousRetryCount:w.retryCount})}async function o1(){let $=[];if(C)try{let N=await C();if(N.type==="oauth"&&N.access)$.push({name:"OpenCode anthropic",role:"main",quota:await R0({accessToken:N.access})});else if(N.type==="oauth")$.push({name:"OpenCode anthropic",role:"main",error:"missing access token; send a request first or reconnect auth"})}catch(N){$.push({name:"OpenCode anthropic",role:"main",error:N instanceof Error?N.message:String(N)})}let{storage:Y,errors:w}=await Z.refreshQuotaForAllAccounts();if($.push(...u1(Y,new Map(w.map((N)=>[N.accountId,N.message])))),!C)$.unshift({name:"OpenCode anthropic",role:"main",error:"auth loader has not run yet; send a request first"});return d1({accounts:$,refreshedAt:Date.now()})}async function t1($){let Y=T1($);if(Y.type==="enable"||Y.type==="disable"){let f=Y.type==="enable",k=await M1(f),g=G0(k);return c({enabled:f,mode:g}),W0({argumentsText:$,enabled:f,mode:g})}if(Y.type==="mode"){let f=await B1(Y.mode),k=$0(f);return c({enabled:k,mode:Y.mode}),W0({argumentsText:$,enabled:k,mode:Y.mode})}let w=await T(),N=$0(w),S=G0(w);return c({enabled:N,mode:S}),W0({argumentsText:$,enabled:N,mode:S})}async function a1($){let Y=A1($),w=await T();if(Y.type==="window")w=await U1(Y.startHour,Y.endHour);else if(Y.type==="disable")w=await x1(!1);let N=C1(w),S=V.stats(N);return k1({argumentsText:$,enabled:f1(w),window:N,hybridActive:y1(w),trackedSessions:S.trackedSessions,nextPrewarmAt:S.nextPrewarmAt})}async function r1($){let Y=m1($);if(Y.type==="enable"||Y.type==="disable"){let S=Y.type==="enable";return await F1(S),w0(S),C0({argumentsText:$,enabled:S})}let w=await T(),N=q0(w);return w0(N),C0({argumentsText:$,enabled:N})}async function s1($){let Y=h1($);if(Y.type==="enable"||Y.type==="disable"){let S=Y.type==="enable";return await v1(S),I0(S),f0({argumentsText:$,enabled:S})}let w=await T(),N=H0(w);return I0(N),f0({argumentsText:$,enabled:N})}async function e1($){let Y=n1($);if(Y.type==="mode")return await p1(Y.mode),k0({argumentsText:$,mode:Y.mode});let w=await T();return k0({argumentsText:$,mode:y0(w)})}return{config:async($)=>{$.command={...$.command??{},[V0]:{template:V0,description:"Show or toggle 1-hour Anthropic ephemeral prompt cache TTL."},[Y0]:{template:Y0,description:"Keep hybrid Claude cache warm for recently used sessions during a local time window."},[Q0]:{template:Q0,description:"Show current Claude OAuth quota usage for all accounts."},[P0]:{template:P0,description:"Show or toggle Anthropic request dump capture for debugging."},[z0]:{template:z0,description:"Show or toggle Anthropic fast mode for supported Opus models."},[O0]:{template:O0,description:"Show or change Claude account routing between main-first and fallback-first."}}},"experimental.chat.system.transform":async($,Y)=>{if(!Rj($))return;Aj(Y.system)},"command.execute.before":async($)=>{if($.command===V0)await h(j,$.sessionID,await t1($.arguments)),u();if($.command===Y0)await h(j,$.sessionID,await a1($.arguments)),u();if($.command===Q0)await h(j,$.sessionID,await o1()),u();if($.command===P0)await h(j,$.sessionID,await r1($.arguments)),u();if($.command===z0)await h(j,$.sessionID,await s1($.arguments)),u();if($.command===O0)await h(j,$.sessionID,await e1($.arguments)),u()},auth:{provider:"anthropic",async loader($,Y){if(C=$,(await $()).type==="oauth"){let jj=function(){if(y)clearInterval(y),y=null;let X=async()=>{try{let W=await T();if(!d(W))return;let I=await $();if(I.type!=="oauth")return;if(await i(I.refresh),!I.expires)return;let P=I.expires-Date.now(),q=L0(W);if(P>q)return;if(H("[refresh] opencode main oauth background due",{expiresInMs:P,refreshBeforeMs:q}),I.refresh&&n(W?.refresh?.mainLastRefreshError,I.refresh,Date.now())){H("[refresh] opencode main oauth background skipped backoff",{nextRetryAt:W?.refresh?.mainLastRefreshError?.nextRetryAt,retryCount:W?.refresh?.mainLastRefreshError?.retryCount,expiresInMs:P});return}if(I.refresh&&W?.refresh?.mainRefreshLeaseUntil&&W.refresh.mainRefreshLeaseUntil>Date.now()&&W.refresh.mainRefreshLeaseTokenHash===D0(I.refresh))return;await g();let Q=await $();H("[refresh] opencode main oauth refreshed in background",{newExpiresInMs:Q.expires?Q.expires-Date.now():void 0})}catch(W){H("[refresh] opencode main oauth refresh failed",{message:W instanceof Error?W.message:String(W)})}};if(y=setInterval(()=>{X()},Uj+O1(xj)),"unref"in y)y.unref()},g0=function(X,W){if(X instanceof Request&&X.body)return!1;return W==null||typeof W==="string"},Jj=function(X){return X.has("x-parent-session-id")},m0=function(X){return X.includes("rate_limit_error")||/exceed your account'?s rate limit/i.test(X)},Zj=function(X){return X?.quota?.enabled===!0},$j=function(X,W){let I=Date.now();if(f||I<k)return;f=u0(X,W).catch((P)=>{throw k=I+H1(W),P}).finally(()=>{f=null}),f.catch(()=>{})};for(let X of Object.values(Y.models))X.cost={input:0,output:0,cache:{read:0,write:0}};let N=null,S=null,f=null,k=0;async function g(){if(!N)N=(async()=>{let I=null,P=null,q=null;async function Q(z){let O=await T()??{version:1,main:{type:"opencode",provider:"anthropic"},accounts:[]};O.refresh=O.refresh??{},z(O),await x0(O)}async function v(z){let O=Date.now()+qj;while(Date.now()<O){await new Promise((M)=>setTimeout(M,I1+O1(I1)));let D=await $();if(D.type!=="oauth"||!D.access)continue;if((D.access!==z.access||D.refresh!==z.refresh||(D.expires??0)>(z.expires??0)+60000)&&(!D.expires||D.expires>Date.now()))return H("[refresh] opencode main oauth joined concurrent refresh",{expiresInMs:D.expires?D.expires-Date.now():void 0}),D.access}return null}for(let z=0;z<=2;z++){let O=null;try{if(z>0){let U=500*2**(z-1);await new Promise((o)=>setTimeout(o,U))}if(O=await $(),!O.refresh)throw Error("Token refresh failed: missing refresh token");let D=await T(),F=D0(O.refresh),M=D?.refresh?.mainLastRefreshError;if(H("[refresh] opencode main oauth refresh check",{attempt:z,expiresInMs:O.expires?O.expires-Date.now():void 0,hasBackoff:Boolean(M),backoffActive:M?n(M,O.refresh,Date.now()):!1,retryCount:M?.retryCount,nextRetryAt:M?.nextRetryAt}),M&&n(M,O.refresh,Date.now()))throw H("[refresh] opencode main oauth refresh skipped backoff",{nextRetryAt:M.nextRetryAt,retryCount:M.retryCount}),Error(E0(M,Date.now()));if(D?.refresh?.mainRefreshLeaseUntil&&D.refresh.mainRefreshLeaseUntil>Date.now()&&D.refresh.mainRefreshLeaseTokenHash===F){H("[refresh] opencode main oauth refresh skipped lease",{leaseUntil:D.refresh.mainRefreshLeaseUntil});let U=await v(O);if(U)return U;throw Error("Claude OAuth refresh is already in progress")}let L=await _1({name:"opencode-main-oauth-refresh",ttlMs:120000,renew:!0});if(!L){H("[refresh] opencode main oauth refresh skipped file lock");let U=await v(O);if(U)return U;throw Error("Claude OAuth refresh is already in progress")}q=L.release,I=Fj(),P=F,await Q((U)=>{U.refresh=U.refresh??{},U.refresh.mainRefreshLeaseId=I??void 0,U.refresh.mainRefreshLeaseUntil=Date.now()+120000,U.refresh.mainRefreshLeaseTokenHash=F});let x=await T();if(H("[refresh] opencode main oauth refresh lease acquired",{attempt:z,leaseUntil:Date.now()+120000}),x?.refresh?.mainRefreshLeaseId!==I||x.refresh.mainRefreshLeaseTokenHash!==F)throw Error("Claude OAuth refresh is already in progress");H("[refresh] opencode main oauth refresh request start",{attempt:z});let A=await L1({refreshToken:O.refresh,maxRetries:0});return await J.auth.set({path:{id:"anthropic"},body:{type:"oauth",refresh:A.refresh,access:A.access,expires:A.expires}}),await Q((U)=>{if(!U?.refresh)return;if(U.refresh.mainLastRefreshError=void 0,U.refresh.mainRefreshLeaseId===I)U.refresh.mainRefreshLeaseId=void 0,U.refresh.mainRefreshLeaseUntil=void 0,U.refresh.mainRefreshLeaseTokenHash=void 0}),H("[refresh] opencode main oauth refresh succeeded",{attempt:z,expiresInMs:A.expires-Date.now()}),A.access}catch(D){let F=D instanceof Error&&(D.message.includes("fetch failed")||("code"in D)&&(D.code==="ECONNRESET"||D.code==="ECONNREFUSED"||D.code==="ETIMEDOUT"||D.code==="UND_ERR_CONNECT_TIMEOUT"));if(z<2&&(F||D instanceof F0&&D.status>=500))continue;H("[refresh] opencode main oauth refresh attempt failed",{attempt:z,error:D instanceof Error?D.message:String(D),transient:F});let M=O?.refresh;if(M&&D instanceof F0)await Q((L)=>{L.refresh=L.refresh??{},L.refresh.mainLastRefreshError=q1({error:D,now:Date.now(),refreshToken:M,previous:L.refresh.mainLastRefreshError})});throw D}finally{if(I)await Q((D)=>{if(!D?.refresh)return;if(D.refresh.mainRefreshLeaseId===I&&D.refresh.mainRefreshLeaseTokenHash===P)D.refresh.mainRefreshLeaseId=void 0,D.refresh.mainRefreshLeaseUntil=void 0,D.refresh.mainRefreshLeaseTokenHash=void 0}).catch(()=>{});await q?.().catch(()=>{})}}throw Error("Token refresh exhausted all retries")})().finally(()=>{N=null});return N}G=g,jj();async function b0(X,W){if(!X.body||X.status!==200)return W?.mark("inspect_stream_skip",{status:X.status}),{response:X,rateLimited:!1};if(X.headers.get("x-cortexkit-relay-optimistic")==="true")return W?.mark("inspect_stream_skip",{status:X.status,reason:"optimistic_relay"}),{response:X,rateLimited:!1};let I=B(),P=X.body.getReader(),q=[],Q=new TextDecoder,v="",z=0;while(!v.includes(`
|
|
4
4
|
|
|
5
|
-
`)&&
|
|
5
|
+
`)&&v.length<65536){let{done:D,value:F}=await P.read();if(D)break;if(q.push(F),z+=F.byteLength,v+=Q.decode(F,{stream:!0}),m0(v))break}if(m0(v))return await P.cancel().catch(()=>{}),W?.mark("inspect_stream_first_event",{ms:E(B()-I),bytes:z,rateLimited:!0}),{response:X,rateLimited:!0};let O=new ReadableStream({start(D){for(let F of q)D.enqueue(F)},async pull(D){let{done:F,value:M}=await P.read();if(F){D.close();return}D.enqueue(M)},cancel(D){return P.cancel(D)}});return W?.mark("inspect_stream_first_event",{ms:E(B()-I),bytes:z,rateLimited:!1}),{response:new Response(O,{status:X.status,statusText:X.statusText,headers:X.headers}),rateLimited:!1}}async function h0(X,W,I,P,q="unknown"){let Q=B(),v=X1(X,W),z=v.get("x-session-affinity")||v.get("x-opencode-session"),O=Jj(v);v.delete("x-parent-session-id"),v.delete("x-session-affinity"),v.delete("x-opencode-session");let D=W?.body,F;if(D&&typeof D==="string")try{let m=JSON.parse(D);if(typeof m.model==="string")F=m.model}catch{}let M=await A0(I,F),L=typeof D==="string"?D.length:void 0;if(D&&typeof D==="string"){let m=B(),t=(()=>{if(!b1())return!1;try{return J0(JSON.parse(D).model)}catch{return!1}})();D=await z1(D,{cache1hEnabled:!O&&K0(),cache1hMode:X0(),fastModeEnabled:t,identity:M});try{p(v,I,{body:JSON.parse(D),identity:M})}catch{p(v,I,{identity:M})}if(t)B0(v);P?.mark("rewrite_body",{route:q,ms:E(B()-m),originalBytes:L,rewrittenBytes:D.length,cacheEnabled:!O&&K0(),cacheMode:X0(),fastModeEnabled:t,subagent:O})}let x=Y1(X);if(q==="main"&&typeof D==="string"&&!O&&K0()&&X0()==="hybrid"){let m=await T();if((await V.track({sessionId:z,url:x.url?.toString()??x.input.toString(),headers:v,bodyText:D,storage:m,cacheMode:"hybrid"})).tracked)P?.mark("cachekeep_track",{session:z})}let A=()=>fetch(x.input,{...W,body:D,headers:v,...W1()&&{tls:{rejectUnauthorized:!1}}}),U=B(),o=await l1({config:_,input:x.input,init:W,headers:v,body:D,fallback:A,affinity:z,optimisticResponse:_?.transport==="websocket"});return P?.mark("send_headers_received",{route:q,ms:E(B()-U),status:o.status,relayConfigured:_!=null,totalSendWithAccessMs:E(B()-Q)}),o}async function u0(X,W){let I=Date.now(),P=await R0({accessToken:X});return S={accessToken:X,refreshAfter:S1(P,W,I),quota:P},P}async function Gj(X,W){let I=Date.now();if(S?.accessToken!==X)return await u0(X,W);if(I>=S.refreshAfter)$j(X,W);return S.quota}async function _0(X,W,I,P,q,Q,v){if(!I.length)return q??null;let z=v?.returnLastOnExhausted??!0;await q?.body?.cancel().catch(()=>{});let O=q??null;for(let[D,F]of I.entries()){let M=F.access;if(!M)continue;let L=await h0(X,W,M,Q,`fallback_${D}`);O=L;let x=S0(L.status,P);if(!x){let A=await b0(L,Q);L=A.response,O=L,x=A.rateLimited}if(!x)return await Z.markUsed(F),L;if(D<I.length-1||!z)await L.body?.cancel().catch(()=>{})}return z?O:null}async function Dj(X,W,I,P,q,Q){if(!g0(X,W?.body))return I;let v=B(),z=Q??await T();q?.mark("fallback_load_storage",{ms:E(B()-v),cached:!!Q});let O=I,D=S0(O.status,z);if(!D){let M=await b0(O,q);O=M.response,D=M.rateLimited}if(!D)return O;let F=P;if(!F){let M=B();F=await Z.getUsableFallbackAccounts(),q?.mark("fallback_get_accounts",{ms:E(B()-M),accounts:F.length})}return await _0(X,W,F,z,O,q)??O}return{apiKey:"",async fetch(X,W){let I=W?.body,P=Tj({bodyBytes:typeof I==="string"?I.length:void 0,relayConfigured:_!=null}),q=B(),Q=await $();if(P.mark("get_auth",{ms:E(B()-q),authType:Q.type,hasAccess:Boolean(Q.access)}),Q.type!=="oauth"){let L=await fetch(X,W);return P.done("non_oauth_passthrough",{status:L.status}),L}await i(Q.refresh);let v=B(),z=await T();P.mark("load_storage",{ms:E(B()-v)});let O=g0(X,W?.body),D;if(O&&y0(z)==="fallback-first")try{let L=B();D=await Z.getUsableFallbackAccounts(z),P.mark("fallback_first_get_accounts",{ms:E(B()-L),accounts:D.length});let x=await _0(X,W,D,z,void 0,P,{returnLastOnExhausted:!1});if(x)return P.done("return_fallback_first",{status:x.status}),Z0(x);D=[]}catch(L){P.mark("fallback_first_error",{error:L instanceof Error?L.message:String(L)})}if(!Q.access||!Q.expires||Q.expires<Date.now()){let x=(await T())?.refresh?.mainLastRefreshError;if(Q.refresh&&x&&n(x,Q.refresh,Date.now()))throw H("[refresh] opencode main oauth request skipped backoff",{nextRetryAt:x.nextRetryAt,retryCount:x.retryCount,expiresInMs:Q.expires?Q.expires-Date.now():void 0}),Error(E0(x,Date.now()));H("[refresh] opencode main oauth refresh required for request",{hasAccess:Boolean(Q.access),expiresInMs:Q.expires?Q.expires-Date.now():void 0,expiredAgoMs:Q.expires&&Q.expires<Date.now()?Date.now()-Q.expires:void 0});let A=B();Q.access=await g(),P.mark("refresh_main_access",{ms:E(B()-A)})}if(!Q.access)throw P.done("missing_access_error"),Error("OAuth access token is missing after refresh");if(O&&Zj(z))try{let L=B(),x=await Gj(Q.access,z);if(P.mark("main_quota_for_routing",{ms:E(B()-L),passes:T0(x,z)}),!T0(x,z)){let A=B();D=await Z.getUsableFallbackAccounts(),P.mark("preselect_fallback_accounts",{ms:E(B()-A),accounts:D.length});let U=await _0(X,W,D,z,void 0,P);if(U)return P.done("return_preselected_fallback",{status:U.status}),Z0(U)}}catch(L){P.mark("main_quota_for_routing_error",{error:L instanceof Error?L.message:String(L)})}let F=await h0(X,W,Q.access,P,"main"),M=await Dj(X,W,F,D,P,z);return P.done("return_response",{status:M.status}),Z0(M)}}}return{}},methods:[{label:"Claude Pro/Max",type:"oauth",authorize:async()=>{let $=await v0("max");return{url:$.url,instructions:"Paste the authorization code here:",method:"code",callback:async(Y)=>{return U0(Y,$.verifier,$.redirectUri,$.state)}}}},{label:"Create an API Key",type:"oauth",authorize:async()=>{let $=await v0("console");return{url:$.url,instructions:"Paste the authorization code here:",method:"code",callback:async(Y)=>{let w=await U0(Y,$.verifier,$.redirectUri,$.state);if(w.type==="failed")return w;return{type:"success",key:(await fetch("https://api.anthropic.com/api/oauth/claude_cli/create_api_key",{method:"POST",headers:{"Content-Type":"application/json",authorization:`Bearer ${w.access}`}}).then((S)=>S.json())).raw_key}}}}},{provider:"anthropic",label:"Manually enter API Key",type:"api"}]}}};export{uj as AnthropicAuthPlugin};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cortexkit/opencode-anthropic-auth",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -41,6 +41,6 @@
|
|
|
41
41
|
"@opencode-ai/plugin": "*"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@cortexkit/anthropic-auth-core": "1.
|
|
44
|
+
"@cortexkit/anthropic-auth-core": "1.4.0"
|
|
45
45
|
}
|
|
46
46
|
}
|
package/dist/index-5by638vz.js
DELETED
|
@@ -1,318 +0,0 @@
|
|
|
1
|
-
var v="9d1c250a-e61b-44d9-88ed-5944d1962f5e",qf={console:"https://platform.claude.com/oauth/authorize",max:"https://claude.ai/oauth/authorize"},Hf="https://platform.claude.com/oauth/code/callback",Ff="https://platform.claude.com/v1/oauth/token",Pf=["org:create_api_key","user:profile","user:inference","user:sessions:claude_code","user:mcp_servers","user:file_upload"],t_="mcp_";var xf="fast-mode-2026-02-01";function r_(f,_){let $=(f??"").split(",").map((m)=>m.trim()).filter(Boolean);return[...new Set([...$,..._])].join(",")}function o_(f){return typeof f==="string"&&(f.startsWith("claude-opus-4-6")||f.startsWith("claude-opus-4-7"))}var a_="You are OpenCode",e_="You are a Claude agent, built on Anthropic's Claude Agent SDK.";var A="2.1.141",Mf="67b",wf="sdk-cli",Rf="0.94.0",kf="v24.3.0",lf="claude-cli/2.1.141 (external, sdk-cli)",uf=["explicit","automatic","hybrid"],d="explicit",f$=["github.com/anomalyco/opencode","opencode.ai/docs"],_$=[{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 yf(f){let _="";for(let $ of f)_+=String.fromCharCode($);return btoa(_).replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}async function nf(){let f=new Uint8Array(64);crypto.getRandomValues(f);let _=yf(f),$=await crypto.subtle.digest("SHA-256",new TextEncoder().encode(_));return{verifier:_,challenge:yf(new Uint8Array($)),method:"S256"}}function p0(f){if(!f)return;let _=Number(f);if(Number.isFinite(_)&&_>0)return Math.ceil(_);let $=Date.parse(f);if(Number.isFinite($)){let m=Math.ceil(($-Date.now())/1000);return m>0?m:void 0}return}class X extends Error{status;body;retryAfter;constructor(f,_,$){super(`Claude OAuth refresh failed: ${f} — ${_}`);this.status=f,this.body=_,this.name="ClaudeOAuthRefreshError",this.retryAfter=p0($??void 0)}}function c0(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 pf(f){let _=f.fetchImpl??fetch,$=f.maxRetries??2,m=f.baseDelayMs??500;for(let E=0;E<=$;E++)try{if(E>0){let H=m*2**(E-1);await new Promise((K)=>setTimeout(K,H))}let D=await _(Ff,{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json","User-Agent":"axios/1.13.6"},body:JSON.stringify({grant_type:"refresh_token",refresh_token:f.refreshToken,client_id:v})});if(!D.ok){if(D.status>=500&&E<$){await D.body?.cancel().catch(()=>{});continue}let H=await D.text().catch(()=>"");throw new X(D.status,H,D.headers.get("retry-after"))}let C=await D.json(),F=f.now?.()??Date.now();return{access:C.access_token,refresh:C.refresh_token??f.refreshToken,expires:F+C.expires_in*1000,expiresIn:C.expires_in}}catch(D){if(D instanceof X)throw D;if(E<$&&c0(D))continue;throw D}throw Error("Token refresh exhausted all retries")}function v0(){return crypto.randomUUID().replace(/-/g,"")}function d0(f){let _=f.trim();try{let C=new URL(_),F=C.searchParams.get("code"),H=C.searchParams.get("state");if(F&&H)return{code:F,state:H}}catch{}let $=_.split("#");if($.length===2&&$[0]&&$[1])return{code:$[0],state:$[1]};let m=new URLSearchParams(_),E=m.get("code"),D=m.get("state");if(E&&D)return{code:E,state:D};return null}async function g0(f,_,$){let m=await fetch(Ff,{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json, text/plain, */*","User-Agent":"axios/1.13.6"},body:JSON.stringify({code:f.code,state:f.state,grant_type:"authorization_code",client_id:v,redirect_uri:$,code_verifier:_})});if(!m.ok)return{type:"failed"};let E=await m.json();return{type:"success",refresh:E.refresh_token,access:E.access_token,expires:Date.now()+E.expires_in*1000}}async function C$(f){let _=await nf(),$=v0(),m=new URL(qf[f],import.meta.url);return m.searchParams.set("code","true"),m.searchParams.set("client_id",v),m.searchParams.set("response_type","code"),m.searchParams.set("redirect_uri",Hf),m.searchParams.set("scope",Pf.join(" ")),m.searchParams.set("code_challenge",_.challenge),m.searchParams.set("code_challenge_method","S256"),m.searchParams.set("state",$),{url:m.toString(),redirectUri:Hf,state:$,verifier:_.verifier}}async function H$(f,_,$,m){let E=d0(f);if(!E)return{type:"failed"};if(m&&E.state!==m)return{type:"failed"};return g0(E,_,$)}import*as cf from"node:fs";import*as vf from"node:os";import*as df from"node:path";var s0=df.join(vf.tmpdir(),"opencode-anthropic-auth.log"),gf=!1,t0=500,r0=50,R=[],x=null;function Kf(){if(x)clearTimeout(x),x=null;if(R.length===0)return;let f=R.join("");R=[];try{cf.appendFileSync(s0,f)}catch{}}function o0(){if(x)return;x=setTimeout(()=>{x=null,Kf()},t0)}function a0(f){if(f===void 0)return"";if(f instanceof Error)return` ${f.message}${f.stack?`
|
|
2
|
-
${f.stack}`:""}`;return` ${JSON.stringify(f)}`}function z(f,_){if(gf)return;try{if(R.push(`[${new Date().toISOString()}] ${f}${a0(_)}
|
|
3
|
-
`),R.length>=r0)Kf();else o0()}catch{}}function b(f,_){z(`[relay] ${f}`,_)}if(!gf)process.on("exit",Kf);import{createHash as _0,randomUUID as bf}from"node:crypto";import{mkdir as e0,readFile as g,rename as f1,rm as sf,stat as _1,writeFile as $0}from"node:fs/promises";import{homedir as $1}from"node:os";import{dirname as m1,join as s}from"node:path";var E1="anthropic-auth.json",D1="https://api.anthropic.com/api/oauth/usage",C1=[401,403,429],m0=240,H1=m0;var F1=300000,M1=3600000,K1=86400000,N1=5,tf={five_hour:0,seven_day:0},S1=!0,b1=60000,j1=60000,I1=120000,J1=1e4,G1=100;function B1(){if(process.env.OPENCODE_CONFIG_DIR?.trim())return process.env.OPENCODE_CONFIG_DIR.trim();return s(process.env.XDG_CONFIG_HOME||s($1(),".config"),"opencode")}function L(){return process.env.OPENCODE_ANTHROPIC_AUTH_FILE?.trim()||s(B1(),E1)}function J(f){return f!=null&&typeof f==="object"&&!Array.isArray(f)}function W1(f){if(!J(f))return null;if(f.type!=="oauth")return null;if(typeof f.refresh!=="string"||!f.refresh.trim())return null;return{id:typeof f.id==="string"&&f.id.trim()?f.id.trim():bf(),label:typeof f.label==="string"?f.label:void 0,type:"oauth",access:typeof f.access==="string"?f.access:void 0,refresh:f.refresh,expires:typeof f.expires==="number"?f.expires:void 0,enabled:typeof f.enabled==="boolean"?f.enabled:void 0,addedAt:typeof f.addedAt==="number"?f.addedAt:void 0,lastUsed:typeof f.lastUsed==="number"?f.lastUsed:void 0,lastRefreshedAt:typeof f.lastRefreshedAt==="number"?f.lastRefreshedAt:void 0,lastRefreshError:rf(f.lastRefreshError),lastQuotaRefreshError:rf(f.lastQuotaRefreshError),quota:U1(f.quota)}}function rf(f){if(!J(f))return;if(typeof f.message!=="string")return;let _=Number(f.checkedAt);if(!Number.isFinite(_))return;let $=Number(f.nextRetryAt),m=Number(f.retryCount);return{message:f.message,checkedAt:_,nextRetryAt:Number.isFinite($)?$:void 0,retryCount:Number.isFinite(m)?m:void 0,tokenHash:typeof f.tokenHash==="string"?f.tokenHash:void 0}}function U1(f){if(!J(f))return;let _={};for(let $ of["five_hour","seven_day"]){let m=f[$];if(!J(m))continue;let E=Number(m.usedPercent),D=Number(m.remainingPercent),C=Number(m.checkedAt);if(!Number.isFinite(E)||!Number.isFinite(D)||!Number.isFinite(C))continue;_[$]={usedPercent:E,remainingPercent:D,checkedAt:C,resetsAt:typeof m.resetsAt==="string"?m.resetsAt:void 0}}return Object.keys(_).length?_:void 0}function z1(f){if(!J(f)||!Array.isArray(f.accounts))return null;return{version:1,main:{type:"opencode",provider:"anthropic"},fallbackOn:Array.isArray(f.fallbackOn)?f.fallbackOn.filter((_)=>Number.isInteger(_)):void 0,refresh:J(f.refresh)?f.refresh:void 0,quota:J(f.quota)?f.quota:void 0,claudeCache:J(f.claudeCache)?f.claudeCache:void 0,dump:J(f.dump)?f.dump:void 0,claudeFast:J(f.claudeFast)?f.claudeFast:void 0,cacheKeep:J(f.cacheKeep)?f.cacheKeep:void 0,relay:J(f.relay)?f.relay:void 0,accounts:f.accounts.map(W1).filter((_)=>_!=null)}}async function V(f=L()){try{let _=await g(f,"utf8");return z1(JSON.parse(_))}catch(_){if(_.code==="ENOENT")return null;return null}}async function L1(f){try{let _=await g(f,"utf8"),$=JSON.parse(_);return J($)?$:{}}catch{return{}}}function Q1(f){return Object.fromEntries(Object.entries(f).filter(([,_])=>_!==void 0))}async function O(f,_=L()){await e0(m1(_),{recursive:!0});let m={...await L1(_),...Q1(f)},E=`${_}.${bf()}.tmp`;await $0(E,`${JSON.stringify(m,null,2)}
|
|
4
|
-
`,{encoding:"utf8",mode:384}),await f1(E,_)}async function T1(f){let $=`${f.path??L()}.${f.name}.lock`,m=s($,"owner.json"),E=bf(),D=f.now??Date.now;async function C(){try{return JSON.parse(await g($,"utf8"))}catch(H){if(H.code!=="EISDIR")throw H;return JSON.parse(await g(m,"utf8"))}}async function F(){try{return await $0($,`${JSON.stringify({ownerId:E,expiresAt:D()+f.ttlMs})}
|
|
5
|
-
`,{encoding:"utf8",mode:384,flag:"wx"}),!0}catch(H){let K=H.code;if(K==="EEXIST"||K==="EISDIR")return!1;throw H}}if(!await F()){try{let H=await C();if(Number(H?.expiresAt)>D())return null}catch{try{if((await _1($)).mtimeMs+f.ttlMs>Date.now())return null}catch{return null}}if(await sf($,{recursive:!0,force:!0}).catch(()=>{}),!await F())return null}return{release:async()=>{try{if((await C())?.ownerId!==E)return}catch{return}await sf($,{recursive:!0,force:!0}).catch(()=>{})}}}function G$(f){return f?.claudeCache?.enabled===!0}function A1(f){return typeof f==="string"&&uf.includes(f)?f:d}function Z1(f){return A1(f?.claudeCache?.mode)}async function B$(f,_,$=L()){let m=await V($)??{version:1,main:{type:"opencode",provider:"anthropic"},accounts:[]};return m.claudeCache={...m.claudeCache??{},enabled:f,mode:_??Z1(m)},await O(m,$),m}async function W$(f,_=L()){let $=await V(_)??{version:1,main:{type:"opencode",provider:"anthropic"},accounts:[]};return $.claudeCache={...$.claudeCache??{},enabled:$.claudeCache?.enabled===!0,mode:f},await O($,_),$}function U$(f){return f?.dump?.enabled===!0}async function z$(f,_=L()){let $=await V(_)??{version:1,main:{type:"opencode",provider:"anthropic"},accounts:[]};return $.dump={...$.dump??{},enabled:f},await O($,_),$}function L$(f){return f?.claudeFast?.enabled===!0}async function Q$(f,_=L()){let $=await V(_)??{version:1,main:{type:"opencode",provider:"anthropic"},accounts:[]};return $.claudeFast={...$.claudeFast??{},enabled:f},await O($,_),$}async function T$(f,_,$=L()){let m=await V($)??{version:1,main:{type:"opencode",provider:"anthropic"},accounts:[]};return m.cacheKeep={enabled:!0,startHour:f,endHour:_},await O(m,$),m}async function A$(f,_=L()){let $=await V(_)??{version:1,main:{type:"opencode",provider:"anthropic"},accounts:[]};return $.cacheKeep={...$.cacheKeep??{},enabled:f},await O($,_),$}function X1(f){return f?.fallbackOn?.length?f.fallbackOn:C1}function Z$(f,_){return X1(_).includes(f)}function E0(f){let _=f?.quota?.minimumRemaining||{};return{five_hour:_.five_hour??_["5h"]??tf.five_hour,seven_day:_.seven_day??_["1w"]??tf.seven_day}}function l(f){return f?.quota?.enabled!==!1}function Y1(f){return f?.refresh?.enabled!==!1}function V1(f){return Math.floor(Math.random()*Math.max(0,f))}function O1(f){let _=f?.refresh?.refreshBeforeExpiryMinutes??H1;return Math.max(m0,_)*60000}function D0(f){return _0("sha256").update(f).digest("hex")}function h1(f){if(f instanceof X)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 q1(f){let _=D0(f.refreshToken),m=(f.previous?.tokenHash===_?f.previous.retryCount??0:0)+1,E;if(f.error instanceof X&&f.error.retryAfter)E=f.error.retryAfter*1000;else if(h1(f.error))E=Math.min(M1,F1*2**Math.min(m-1,6));else E=K1;return{message:u(f.error),checkedAt:f.now,nextRetryAt:f.now+E,retryCount:m,tokenHash:_}}function k(f,_,$){if(!f?.nextRetryAt||f.nextRetryAt<=$)return!1;if(!_)return!0;return f.tokenHash===D0(_)}function Nf(f,_){return`Claude OAuth refresh is backed off for ${Math.max(1,Math.ceil(((f.nextRetryAt??_)-_)/1000))}s after: ${f.message}`}function i(f){let _=f?.quota?.checkIntervalMinutes??N1;return Math.max(1,_)*60000}function C0(f){return f?.quota?.failClosedOnUnknownQuota??S1}function H0(f,_){if(!l(_))return!0;let $=E0(_);for(let m of["five_hour","seven_day"]){let E=f?.[m];if(!E)return!C0(_);if(E.remainingPercent<$[m])return!1}return!0}function X$(f,_,$){if(!l(_))return $+i(_);let m=E0(_),E=[];for(let D of["five_hour","seven_day"]){let C=f?.[D];if(!C)return $+i(_);if(C.remainingPercent>=m[D])continue;let F=C.resetsAt?Date.parse(C.resetsAt):Number.NaN;if(!Number.isFinite(F)||F<=$)return $+i(_);E.push(F)}if(!E.length)return $+i(_);return Math.min(...E)+60000}function Y(f,_,$){return!f.access||!f.expires||f.expires-$<=O1(_)}function Sf(f,_,$){if(!l(_))return!1;let m=i(_);return["five_hour","seven_day"].some((E)=>{let D=f.quota?.[E];return!D||$-D.checkedAt>=m})}function P1(f,_){if(!f)return!1;if(!f.resetsAt)return!0;let $=Date.parse(f.resetsAt);return!Number.isFinite($)||$>_}function x1(f,_){return["five_hour","seven_day"].every(($)=>P1(f?.[$],_))}function w1(f){let _=u(f);if(/Claude quota check failed: (429|5\d\d)\b/.test(_))return!0;if(!(f instanceof Error))return!1;let $=f.code;return _.includes("fetch failed")||$==="ECONNRESET"||$==="ECONNREFUSED"||$==="ETIMEDOUT"||$==="UND_ERR_CONNECT_TIMEOUT"}function R1(f,_,$,m){return w1($)&&H0(f.quota,_)&&x1(f.quota,m)}function of(f){if(!Number.isFinite(f))return 0;if(f<0)return 0;if(f>100)return 100;return f}function af(f,_){if(typeof f?.utilization!=="number")return;let $=of(f.utilization);return{usedPercent:$,remainingPercent:of(100-$),resetsAt:f.resets_at,checkedAt:_}}async function ef(f){let $=await(f.fetchImpl??fetch)(D1,{method:"GET",headers:{Authorization:`Bearer ${f.accessToken}`,Accept:"application/json","Content-Type":"application/json","anthropic-beta":"oauth-2025-04-20","User-Agent":`claude-code/${A}`}});if(!$.ok){let D=await $.text().catch(()=>"");throw Error(`Claude quota check failed: ${$.status} — ${D}`)}let m=f.now?.()??Date.now(),E=await $.json();return{five_hour:af(E.five_hour,m),seven_day:af(E.seven_day,m)}}function U(f,_){let $=f.accounts.findIndex((m)=>m.id===_.id);if($>=0)f.accounts[$]=_}function u(f){return f instanceof Error?f.message:String(f)}function F0(f,_,$){f.lastRefreshError=q1({error:_,now:$,refreshToken:f.refresh,previous:f.lastRefreshError})}function f0(f,_,$){if(f.lastQuotaRefreshError={message:u(_),checkedAt:$},_ instanceof X)F0(f,_,$)}function k1(f){return`fallback-oauth-refresh-${_0("sha256").update(f).digest("hex").slice(0,16)}`}class i1{now;fetchImpl;configPath;refreshPromises=new Map;refreshTimer=null;quotaTimer=null;constructor(f={}){this.now=f.now??Date.now,this.fetchImpl=f.fetchImpl??fetch,this.configPath=f.configPath??L()}async load(){return V(this.configPath)}async save(f){await O(f,this.configPath)}startBackgroundRefresh(){let f=async()=>{await this.refreshDueAccounts(),await this.refreshQuotaForDueAccounts()};if(f().catch(()=>{}),!this.refreshTimer){if(this.refreshTimer=setInterval(()=>{f().catch(()=>{})},b1+V1(j1)),"unref"in this.refreshTimer)this.refreshTimer.unref()}}stopBackgroundRefresh(){if(this.refreshTimer)clearInterval(this.refreshTimer);if(this.quotaTimer)clearInterval(this.quotaTimer);this.refreshTimer=null,this.quotaTimer=null}async getUsableFallbackAccounts(f){let _=f!==void 0?f:await this.load();if(!_)return[];let $=[],m=!1;for(let E of _.accounts){if(E.enabled===!1)continue;try{let D=E;if(Y(D,_,this.now())){let C=D.lastRefreshError;if(C&&k(C,D.refresh,this.now()))throw Error(Nf(C,this.now()));D=await this.refreshAccount(D,_),m=!0}if(Sf(D,_,this.now()))D=await this.refreshAccountQuota(D,_),m=!0;if(this.accountPassesQuotaPolicy(D,_))$.push(D)}catch(D){if(R1(E,_,D,this.now()))z("[refresh] fallback quota using cached quota after refresh error",{accountId:E.id,error:u(D)}),$.push(E);else if(!C0(_))$.push(E)}}if(m)await this.save(_);return $}async markUsed(f){let _=await this.load();if(!_)return;let $=_.accounts.find((m)=>m.id===f.id);if(!$)return;$.lastUsed=this.now(),await this.save(_)}accountPassesQuotaPolicy(f,_){return H0(f.quota,_)}async refreshDueAccounts(){let f=await this.load();if(!f||!Y1(f))return;let _=!1;for(let $ of f.accounts){if($.enabled===!1)continue;if(!Y($,f,this.now()))continue;if(k($.lastRefreshError,$.refresh,this.now())){z("[refresh] fallback oauth skipped backoff",{accountId:$.id,nextRetryAt:$.lastRefreshError?.nextRetryAt,retryCount:$.lastRefreshError?.retryCount});continue}try{z("[refresh] fallback oauth background due",{accountId:$.id,expiresInMs:$.expires?$.expires-this.now():void 0}),await this.refreshAccount($,f),_=!0}catch(m){z("[refresh] fallback oauth background failed",{accountId:$.id,error:m instanceof Error?m.message:String(m)}),F0($,m,this.now()),U(f,$),_=!0}}if(_)await this.save(f)}async refreshQuotaForDueAccounts(){let f=await this.load();if(!f||!l(f))return;let _=!1;for(let $ of f.accounts){if($.enabled===!1)continue;let m=$;try{if(Y(m,f,this.now())){if(k(m.lastRefreshError,m.refresh,this.now()))continue;m=await this.refreshAccount(m,f),_=!0}if(!Sf(m,f,this.now()))continue;await this.refreshAccountQuota(m,f),_=!0}catch(E){f0($,E,this.now()),U(f,$),_=!0}}if(_)await this.save(f)}async refreshQuotaForAllAccounts(){let f=await this.load(),_=[];if(!f||!l(f))return{storage:f,errors:_};let $=!1;for(let m of f.accounts){if(m.enabled===!1)continue;let E=m;try{if(Y(E,f,this.now())){let D=E.lastRefreshError;if(D&&k(D,E.refresh,this.now()))throw Error(Nf(D,this.now()));E=await this.refreshAccount(E,f),$=!0}if(!Sf(E,f,this.now())){if(E.lastQuotaRefreshError)E.lastQuotaRefreshError=void 0,U(f,E),$=!0;continue}await this.refreshAccountQuota(E,f),$=!0}catch(D){f0(m,D,this.now()),U(f,m),$=!0,_.push({accountId:m.id,message:u(D)})}}if($)await this.save(f);return{storage:f,errors:_}}async refreshAccount(f,_,$={}){let m=this.refreshPromises.get(f.id);if(m){let C=await m;return U(_,C),C}let E=this.refreshAccountNow(f,_,$).finally(()=>{this.refreshPromises.delete(f.id)});this.refreshPromises.set(f.id,E);let D=await E;return U(_,D),D}async waitForConcurrentFallbackRefresh(f,_,$,m){let E=Date.now()+J1;while(Date.now()<E){await new Promise((K)=>setTimeout(K,G1));let D=await this.load(),C=D?.accounts.find((K)=>K.id===f.id);if(!C)continue;if((C.access!==$.access||C.refresh!==$.refresh||(C.expires??0)>($.expires??0)+60000)&&(m.force||!Y(C,D,this.now())))return U(_,C),z("[refresh] fallback oauth joined concurrent refresh",{accountId:C.id,expiresInMs:C.expires?C.expires-this.now():void 0}),C;let H=C.lastRefreshError;if(H&&k(H,C.refresh,this.now()))throw U(_,C),Error(Nf(H,this.now()))}return null}async refreshAccountNow(f,_,$){let m=await this.load(),E=m?.accounts.find((F)=>F.id===f.id);if(E&&!$.force&&!Y(E,m,this.now()))return U(_,E),E;let D=E??f,C=await T1({name:k1(D.id),ttlMs:I1,path:this.configPath,now:this.now});if(!C){z("[refresh] fallback oauth refresh skipped file lock",{accountId:D.id});let F=await this.waitForConcurrentFallbackRefresh(f,_,D,$);if(F)return F;throw Error("Fallback OAuth refresh is already in progress")}try{if(m=await this.load(),E=m?.accounts.find((K)=>K.id===f.id),E&&!$.force&&!Y(E,m,this.now()))return U(_,E),E;D=E??D;let F=D.refresh;z("[refresh] fallback oauth refresh request start",{accountId:D.id,force:$.force===!0,expiresInMs:D.expires?D.expires-this.now():void 0});let H=await pf({refreshToken:F,fetchImpl:this.fetchImpl,now:this.now});return D.access=H.access,D.refresh=H.refresh,D.expires=H.expires,D.lastRefreshedAt=H.expires-H.expiresIn*1000,D.lastRefreshError=void 0,U(_,D),await this.save(_),z("[refresh] fallback oauth refresh succeeded",{accountId:D.id,expiresInMs:D.expires?D.expires-this.now():void 0}),D}finally{await C.release()}}async refreshAccountQuota(f,_){let $=f;if(!$.access)throw Error(`Fallback account ${f.id} has no access token`);try{$.quota=await ef({accessToken:$.access,fetchImpl:this.fetchImpl,now:this.now})}catch(m){if(!(m instanceof Error?m.message:String(m)).includes("Claude quota check failed: 401"))throw m;if($=await this.refreshAccount(f,_,{force:!0}),!$.access)throw m;$.quota=await ef({accessToken:$.access,fetchImpl:this.fetchImpl,now:this.now})}return $.lastQuotaRefreshError=void 0,U(_,$),$}}var O$="claude-cache",M0="## Claude Cache Status",l1="## Claude Cache Enabled",u1="## Claude Cache Disabled",y1="## Claude Cache Usage",n1="Usage: `/claude-cache`, `/claude-cache on`, `/claude-cache off`, or `/claude-cache mode explicit|automatic|hybrid`.",t=!1,r=d;function h$(){return t}function q$(){return r}function P$(f){t=f.enabled,r=f.mode}function p1(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 y(f){let _=f?.enabled??t,$=f?.mode??r;return[M0,"",`- Enabled: ${_?"enabled":"disabled"}`,`- Mode: ${$}`,"- Persisted: ~/.config/opencode/anthropic-auth.json","- Scope: main sessions only; subagent sessions keep default ephemeral cache behavior","- Modes: explicit = existing OpenCode breakpoints; automatic = top-level cache_control only; hybrid = system + messages[0] + top-level cache_control","- TTL: 1h when enabled for main sessions; default ephemeral cache behavior otherwise"].join(`
|
|
6
|
-
`)}function x$(f){let _=p1(f.argumentsText),$=f.enabled??t,m=f.mode??r;if(_.type==="status")return y({enabled:$,mode:m});if(_.type==="enable")return[l1,"",y({enabled:!0,mode:m})].join(`
|
|
7
|
-
`);if(_.type==="disable")return[u1,"",y({enabled:!1,mode:m})].join(`
|
|
8
|
-
`);if(_.type==="mode")return[M0,"",`Mode updated to \`${_.mode}\`.`,"",y({enabled:$,mode:_.mode})].join(`
|
|
9
|
-
`);return[y1,"",n1,"",y({enabled:$,mode:m})].join(`
|
|
10
|
-
`)}import{randomBytes as c1,randomUUID as N0}from"node:crypto";var v1=1000,n=new Map;function If(f,_,$){if(!f.has(_)&&f.size>=v1){let m=f.keys().next().value;if(m!==void 0)f.delete(m)}f.set(_,$)}function S0(f){let _=f||"anonymous",$=n.get(_);if($)return $;let m={deviceId:c1(32).toString("hex"),sessionId:N0()};return If(n,_,m),m}var jf=new Map;async function d1(f,_){if(!f.startsWith("sk-ant-oat"))return null;let $=new AbortController,m=setTimeout(()=>$.abort(),5000);try{let E=new URL("https://api.anthropic.com/api/claude_cli/bootstrap");if(E.searchParams.set("entrypoint",wf),_)E.searchParams.set("model",_);let D=await fetch(E,{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/${A}`},signal:$.signal});if(!D.ok)return null;let F=(await D.json().catch(()=>null))?.oauth_account?.account_uuid;return typeof F==="string"&&F?F:null}catch{return null}finally{clearTimeout(m)}}async function i$(f,_){let $=S0(f);if(!f.startsWith("sk-ant-oat"))return $;let m=jf.get(f);if(!m)m=d1(f,_),jf.set(f,m);let E=await m;if(!E)return jf.delete(f),$;let D=`account:${E}`,C=n.get(D);if(C)return If(n,f,C),C;return $.accountUuid=E,If(n,D,$),$}function h(f){return f!=null&&typeof f==="object"&&!Array.isArray(f)}function g1(f){if(!f.accountUuid)return null;return JSON.stringify({device_id:f.deviceId,account_uuid:f.accountUuid,session_id:f.sessionId})}function l$(f,_){let $=g1(_);if(!$){if(h(f.metadata))delete f.metadata.user_id;return!1}if(!h(f.metadata))f.metadata={};let m=f.metadata;if(h(m))m.user_id=$;return!0}var s1=["claude-code-20250219","oauth-2025-04-20","interleaved-thinking-2025-05-14","context-management-2025-06-27","prompt-caching-scope-2026-01-05","advisor-tool-2026-03-01","advanced-tool-use-2025-11-20","context-1m-2025-08-07","effort-2025-11-24","extended-cache-ttl-2025-04-11","cache-diagnosis-2026-04-07"],t1=["oauth-2025-04-20","interleaved-thinking-2025-05-14","context-management-2025-06-27","prompt-caching-scope-2026-01-05","advisor-tool-2026-03-01","structured-outputs-2025-12-15","cache-diagnosis-2026-04-07"],K0=["oauth-2025-04-20","interleaved-thinking-2025-05-14","context-management-2025-06-27","prompt-caching-scope-2026-01-05","advisor-tool-2026-03-01","cache-diagnosis-2026-04-07"];function r1(f){return f.output_config?.format?.type==="json_schema"}function o1(f){return Array.isArray(f.tools)&&f.tools.length>0&&Array.isArray(f.system)&&h(f.thinking)&&h(f.context_management)&&h(f.output_config)&&h(f.diagnostics)}function a1(f,_=[]){let $=f?o1(f)?[...s1]:r1(f)?[...t1]:[...K0]:[...K0];if(f?.speed==="fast")$.push(xf);for(let m of _){let E=m.trim();if(E)$.push(E)}return[...new Set($)].join(",")}function e1(){switch(process.platform){case"darwin":return"MacOS";case"win32":return"Windows";case"linux":return"Linux";case"freebsd":return"FreeBSD";default:return"Unknown"}}function f_(){switch(process.arch){case"arm64":return"arm64";case"x64":return"x64";case"ia32":return"x32";default:return process.arch}}function u$(f,_,$={}){let m=$.identity??S0(_),D=[...(f.get("anthropic-beta")??"").split(",").map((C)=>C.trim()).filter(Boolean),...$.extraBetas??[]];return f.set("accept","application/json"),f.set("authorization",`Bearer ${_}`),f.set("content-type","application/json"),f.set("user-agent",lf),f.set("anthropic-beta",a1($.body,D)),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",N0()),f.set("x-claude-code-session-id",m.sessionId),f.set("x-stainless-arch",f_()),f.set("x-stainless-lang","js"),f.set("x-stainless-os",e1()),f.set("x-stainless-package-version",Rf),f.set("x-stainless-retry-count","0"),f.set("x-stainless-runtime","node"),f.set("x-stainless-runtime-version",kf),f.set("x-stainless-timeout","600"),f.delete("x-api-key"),f}var __=["model","messages","system","tools","tool_choice","metadata","max_tokens","temperature","thinking","context_management","output_config","diagnostics","stream","speed"];function b0(f){let _={};for(let $ of __)if(Object.hasOwn(f,$))_[$]=f[$];for(let[$,m]of Object.entries(f))if(!Object.hasOwn(_,$))_[$]=m;return _}import{createHash as m_}from"node:crypto";var $_=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 j0(){return function(f){let{exports:{mem:_,xxh32:$,xxh64:m,init32:E,update32:D,digest32:C,init64:F,update64:H,digest64:K}}=f,S=new Uint8Array(_.buffer);function j(M,I){if(_.buffer.byteLength<M+I){let Df=Math.ceil((M+I-_.buffer.byteLength)/65536);_.grow(Df),S=new Uint8Array(_.buffer)}}function T(M,I,Df,u0,y0,n0){j(M);let w=new Uint8Array(M);return S.set(w),Df(0,I),w.set(S.subarray(0,M)),{update(P){let Cf;return S.set(w),typeof P=="string"?(j(3*P.length,M),Cf=W.encodeInto(P,S.subarray(M)).written):(j(P.byteLength,M),S.set(P,M),Cf=P.byteLength),u0(0,M,Cf),w.set(S.subarray(0,M)),this},digest:()=>(S.set(w),n0(y0(0)))}}function Q(M){return M>>>0}let N=2n**64n-1n;function B(M){return M&N}let W=new TextEncoder,p=0,c=0n;function Of(M,I=p){return j(3*M.length,0),Q($(0,W.encodeInto(M,S).written,I))}function hf(M,I=c){return j(3*M.length,0),B(m(0,W.encodeInto(M,S).written,I))}return{h32:Of,h32ToString:(M,I=p)=>Of(M,I).toString(16).padStart(8,"0"),h32Raw:(M,I=p)=>(j(M.byteLength,0),S.set(M),Q($(0,M.byteLength,I))),create32:(M=p)=>T(48,M,E,D,C,Q),h64:hf,h64ToString:(M,I=c)=>hf(M,I).toString(16).padStart(16,"0"),h64Raw:(M,I=c)=>(j(M.byteLength,0),S.set(M),B(m(0,M.byteLength,I))),create64:(M=c)=>T(88,M,F,H,K,B)}}((await WebAssembly.instantiate($_)).instance)}var E_=0x6e52736ac806831en,o=/\bcch=([0-9a-f]{5});/,I0=null,Jf=null;async function D_(){if(Jf)return;I0??=(async()=>{Jf=(await j0()).h64Raw})(),await I0}async function C_(f){return await D_(),((Jf?.(f,E_)??0n)&0xfffffn).toString(16).padStart(5,"0")}async function J0(f){if(!o.test(f))return f;let _=await C_(new TextEncoder().encode(f));return f.replace(o,`cch=${_};`)}function H_(f=A,_=new Date){if(f===A)return Mf;let $=_.toISOString().slice(0,10);return m_("sha256").update(`${$}${f}`).digest("hex").slice(0,3)}function d$(f,_=A,$,m=new Date){let E=H_(_,m);return`x-anthropic-billing-header: cc_version=${_}.${E}; cc_entrypoint=${$}; cch=00000;`}var r$="claude-cachekeep",G0=3600000,Gf=300000,F_=60000,o$="extended-cache-ttl-2025-04-11",M_="## Claude Cache Keep Status",K_="## Claude Cache Keep Enabled",N_="## Claude Cache Keep Disabled",S_="## Claude Cache Keep Usage",b_="Usage: `/claude-cachekeep`, `/claude-cachekeep off`, or `/claude-cachekeep HH-HH`.";function e(f){return String(f).padStart(2,"0")}function j_(f){let _=f.trim();if(!_)return{type:"status"};if(_==="off")return{type:"disable"};let $=/^(\d{1,2})-(\d{1,2})$/.exec(_);if(!$)return{type:"usage"};let m=Number($[1]),E=Number($[2]);if(!Number.isInteger(m)||!Number.isInteger(E)||m<0||m>23||E<0||E>23||m===E)return{type:"usage"};return{type:"window",startHour:m,endHour:E}}function Wf(f){let _=Number(f?.cacheKeep?.startHour),$=Number(f?.cacheKeep?.endHour);if(!Number.isInteger(_)||!Number.isInteger($)||_<0||_>23||$<0||$>23||_===$)return;return{startHour:_,endHour:$}}function U0(f){return f?.cacheKeep?.enabled===!0&&!!Wf(f)}function I_(f){return U0(f)&&f?.claudeCache?.enabled===!0&&f.claudeCache.mode==="hybrid"}function B0(f,_=new Date){if(!f)return!1;let $=_.getHours();if(f.startHour<f.endHour)return $>=f.startHour&&$<f.endHour;return $>=f.startHour||$<f.endHour}function W0(f=new Date){return`${f.getFullYear()}-${e(f.getMonth()+1)}-${e(f.getDate())}`}function Bf(f,_=new Date){if(f&&f.startHour>f.endHour&&_.getHours()<f.endHour){let $=new Date(_);return $.setDate($.getDate()-1),W0($)}return W0(_)}function a(f){let _=f.window?`${e(f.window.startHour)}-${e(f.window.endHour)}`:"not configured",$=[`Cache keep: ${f.enabled?"enabled":"disabled"}`,`Window: ${_}`,"Mode requirement: `/claude-cache mode hybrid` must be active."];if(typeof f.hybridActive==="boolean")$.push(`Hybrid active: ${f.hybridActive?"yes":"no"}`);if(typeof f.trackedSessions==="number")$.push(`Tracked sessions: ${f.trackedSessions}`);if(f.nextPrewarmAt)$.push(`Next prewarm: ${new Date(f.nextPrewarmAt).toLocaleString()}`);return $.join(`
|
|
11
|
-
`)}function a$(f){let _=j_(f.argumentsText),$={enabled:f.enabled??!1,window:f.window,trackedSessions:f.trackedSessions,nextPrewarmAt:f.nextPrewarmAt,hybridActive:f.hybridActive};if(_.type==="status")return[M_,"",a($)].join(`
|
|
12
|
-
`);if(_.type==="disable")return[N_,"",a({...$,enabled:!1})].join(`
|
|
13
|
-
`);if(_.type==="window")return[K_,"",a({...$,enabled:!0,window:{startHour:_.startHour,endHour:_.endHour}})].join(`
|
|
14
|
-
`);return[S_,"",b_,"",a($)].join(`
|
|
15
|
-
`)}function Uf(f){if(!f||typeof f!=="object")return!1;if(Array.isArray(f))return f.some(Uf);let _=f,$=_.cache_control;if($&&typeof $==="object"&&$.type==="ephemeral")return!0;return Object.values(_).some(Uf)}async function J_(f){let _;try{_=JSON.parse(f)}catch{return{ok:!1,reason:"body is not valid JSON"}}if(!Uf(_))return{ok:!1,reason:"body has no explicit cache breakpoints"};let $=structuredClone(_);if($.max_tokens=0,delete $.stream,$.thinking?.type==="enabled")delete $.thinking;if($.output_config?.format)delete $.output_config;let D=$.tool_choice;if(D?.type==="tool"||D?.type==="any")delete $.tool_choice;let C=JSON.stringify(b0($)).replace(o,"cch=00000;");return{ok:!0,bodyText:await J0(C)}}class G_{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)})})},F_),"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 $=Bf(f,new Date(_)),m=[...this.targets.values()].filter((D)=>D.dayKey===$),E=m.length?Math.min(...m.map((D)=>D.cacheExpiresAt-Gf)):void 0;return{trackedSessions:m.length,nextPrewarmAt:E}}track(f){if(!f.sessionId)return{tracked:!1,reason:"missing session id"};if(!U0(f.storage))return{tracked:!1,reason:"cachekeep disabled"};if(f.cacheMode!=="hybrid")return{tracked:!1,reason:"cache mode is not hybrid"};let _=this.options.now?.()??Date.now(),$=Wf(f.storage);if(!B0($,new Date(_)))return{tracked:!1,reason:"outside configured window"};let m={};return f.headers.forEach((E,D)=>{m[D]=E}),this.targets.set(f.sessionId,{id:f.sessionId,url:f.url,headers:m,bodyText:f.bodyText,cacheExpiresAt:_+G0,dayKey:Bf($,new Date(_))}),this.start(),{tracked:!0}}async tick(){let f=await this.options.loadStorage(),_=Wf(f),$=this.options.now?.()??Date.now(),m=Bf(_,new Date($));for(let[D,C]of this.targets)if(C.dayKey!==m)this.targets.delete(D);if(!this.targets.size){this.stop();return}if(!I_(f))return;if(!B0(_,new Date($)))return;let E=$+Gf;for(let D of this.targets.values()){if(D.cacheExpiresAt>E)continue;await this.prewarm(D,$)}}async prewarm(f,_){let $=await J_(f.bodyText);if(!$.ok){this.options.log?.("[cachekeep] prewarm skipped",{session:f.id,reason:$.reason}),this.targets.delete(f.id);return}let m=this.options.fetchImpl??fetch,E={...f,bodyText:$.bodyText},D=this.options.prepareHeaders?await this.options.prepareHeaders(new Headers(f.headers),E):new Headers(f.headers);D.delete("content-length"),D.delete("transfer-encoding");let C=await m(f.url,{method:"POST",headers:D,body:$.bodyText});if(!C.ok){this.options.log?.("[cachekeep] prewarm failed",{session:f.id,status:C.status,body:await C.text().catch(()=>"")}),f.cacheExpiresAt=_+Gf+300000;return}await C.body?.cancel().catch(()=>{}),f.cacheExpiresAt=_+G0,this.options.log?.("[cachekeep] prewarm succeeded",{session:f.id})}}import{createHash as B_}from"node:crypto";import{mkdir as W_,writeFile as zf}from"node:fs/promises";import{tmpdir as U_}from"node:os";import{join as Q0}from"node:path";var Dm="claude-dump",z_="## Claude Dump Status",L_="## Claude Dump Enabled",Q_="## Claude Dump Disabled",T_="## Claude Dump Usage",A_="Usage: `/claude-dump`, `/claude-dump on`, or `/claude-dump off`.",Qf=Q0(U_(),"opencode-anthropic-auth-dumps"),_f=!1,z0=0;function Cm(f){_f=f}function Z_(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 ff(f){let _=f?.enabled??_f;return[z_,"",`- Enabled: ${_?"enabled":"disabled"}`,`- Directory: ${Qf}`,"- Persisted: ~/.config/opencode/anthropic-auth.json","- Captures: final rewritten Anthropic body plus redacted relay payload metadata","- Warning: body dumps may contain prompt/session content; turn this off after debugging"].join(`
|
|
16
|
-
`)}function Hm(f){let _=Z_(f.argumentsText),$=f.enabled??_f;if(_.type==="status")return ff({enabled:$});if(_.type==="enable")return[L_,"",ff({enabled:!0})].join(`
|
|
17
|
-
`);if(_.type==="disable")return[Q_,"",ff({enabled:!1})].join(`
|
|
18
|
-
`);return[T_,"",A_,"",ff({enabled:$})].join(`
|
|
19
|
-
`)}function L0(f){return f.length<=16?f:`${f.slice(0,12)}…`}function T0(f){return B_("sha256").update(f).digest("hex")}function X_(f){return f.match(/\bcch=([0-9a-f]{5});/)?.[1]??null}function Y_(f,_){if(f==null)return null;if(f===_)return{changed:!1,firstByte:-1,lastPreviousByte:-1,lastCurrentByte:-1,previousBytes:f.length,currentBytes:_.length};let $=0;while($<f.length&&$<_.length&&f[$]===_[$])$+=1;let m=f.length-1,E=_.length-1;while(m>=$&&E>=$&&f[m]===_[E])m-=1,E-=1;return{changed:!0,firstByte:$,lastPreviousByte:m,lastCurrentByte:E,changedPreviousBytes:m-$+1,changedCurrentBytes:E-$+1,previousBytes:f.length,currentBytes:_.length}}function V_(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 Lf(f){return T0(JSON.stringify(f))}function O_(f){let _=V_(f);if(!_)return{parseable:!1};let $=Array.isArray(_.messages)?_.messages:[],m=Array.isArray(_.system)?_.system:[],E=$[0],D=$.slice(1);return{parseable:!0,model:typeof _.model==="string"?_.model:void 0,stream:_.stream,systemCount:m.length,messagesCount:$.length,systemHash:Lf(m),message0Hash:E===void 0?null:Lf(E),message0Bytes:E===void 0?0:JSON.stringify(E).length,messagesAfter0Hash:Lf(D),messagesAfter0Bytes:JSON.stringify(D).length,cch:X_(f)}}function Tf(f){if(Array.isArray(f))return f.map(Tf);if(f==null||typeof f!=="object")return f;let _={};for(let[$,m]of Object.entries(f)){let E=$.toLowerCase();if(E==="authorization"||E==="x-api-key"||E==="cookie"||E==="set-cookie"){_[$]="[redacted]";continue}_[$]=Tf(m)}return _}async function A0(f){if(!_f)return;z0+=1;let _=`${new Date().toISOString().replace(/[:.]/g,"-")}-${String(z0).padStart(5,"0")}-${f.transport}-p${f.protocol}-${f.mode}`,$=Q0(Qf,_);try{await W_(Qf,{recursive:!0});let m={id:_,createdAt:new Date().toISOString(),session:L0(f.affinity),transport:f.transport,protocol:f.protocol,mode:f.mode,status:f.status,bodyBytes:f.bodyText.length,relayBytes:f.relayBytes,bodyHash:T0(f.bodyText),diff:Y_(f.previousBodyText,f.bodyText),body:O_(f.bodyText),files:{body:`${$}.body.json`,relay:`${$}.relay.json`,metadata:`${$}.meta.json`}};await Promise.all([zf(`${$}.body.json`,f.bodyText,"utf8"),zf(`${$}.relay.json`,`${JSON.stringify(Tf(f.payload),null,2)}
|
|
20
|
-
`,"utf8"),zf(`${$}.meta.json`,`${JSON.stringify(m,null,2)}
|
|
21
|
-
`,"utf8")]),b(`dumped request id=${_} session=${L0(f.affinity)} body=${$}.body.json meta=${$}.meta.json`)}catch(m){b(`dump failed: ${m instanceof Error?m.message:String(m)}`)}}var Mm="claude-fast";var mf=!1;function Km(){return mf}function Nm(f){mf=f}function h_(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 $f(f){return["## Claude Fast Mode Status","",`- Enabled: ${f?.enabled??mf?"enabled":"disabled"}`,"- Persisted: ~/.config/opencode/anthropic-auth.json","- Scope: adds Anthropic fast mode to supported Opus requests","- Supported models: claude-opus-4-6 and claude-opus-4-7",'- 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(`
|
|
22
|
-
`)}function Sm(f){let _=h_(f.argumentsText),$=f.enabled??mf;if(_.type==="status")return $f({enabled:$});if(_.type==="enable")return["## Claude Fast Mode Enabled","",$f({enabled:!0})].join(`
|
|
23
|
-
`);if(_.type==="disable")return["## Claude Fast Mode Disabled","",$f({enabled:!1})].join(`
|
|
24
|
-
`);return["## Claude Fast Mode Usage","","Usage: `/claude-fast`, `/claude-fast on`, or `/claude-fast off`.","",$f({enabled:$})].join(`
|
|
25
|
-
`)}var jm="claude-quota",Z0={five_hour:"5h",seven_day:"1w"};function X0(f){return`${Math.round(f*10)/10}%`}function Af(f,_){let $=Math.max(0,_-f),m=Math.floor($/60000);if(m<1)return"just now";if(m===1)return"1m ago";if(m<60)return`${m}m ago`;let E=Math.floor(m/60),D=m%60;if(D===0)return`${E}h ago`;return`${E}h ${D}m ago`}function q_(f,_){let $=Date.parse(f);if(!Number.isFinite($))return f;let m=$-_;if(m<=0)return"now";let E=Math.max(1,Math.ceil(m/60000));if(E<60)return`in ${E}m`;let D=Math.floor(E/60),C=E%60;if(C===0)return`in ${D}h`;return`in ${D}h ${C}m`}function P_(f,_){if(!f)return"";return`, resets ${q_(f,_)}`}function Y0(f,_,$){if(!_)return` - ${Z0[f]}: unknown`;return[` - ${Z0[f]}: ${X0(_.remainingPercent)} remaining`,` (${X0(_.usedPercent)} used`,`${P_(_.resetsAt,$)}, checked ${Af(_.checkedAt,$)})`].join("")}function x_(f){return f.label?.trim()||f.id}function w_(f){return f.lastQuotaRefreshError?.message??f.lastRefreshError?.message}function Im(f,_=new Map){if(!f?.accounts.length)return[];return f.accounts.map(($)=>{let m=_.get($.id)??w_($);return{name:x_($),role:"fallback",enabled:$.enabled!==!1,quota:$.quota,lastRefreshedAt:$.lastRefreshedAt,...m&&{error:m}}})}function Jm(f){let _=f.now??Date.now(),$=["## Claude Quotas",""];if(f.refreshedAt)$.push(`Refreshed: ${Af(f.refreshedAt,_)}`,"");if(!f.accounts.length)return $.push("No Claude OAuth accounts found yet."),$.join(`
|
|
26
|
-
`);for(let m of f.accounts){let E=m.role==="main"?"main":"fallback",D=m.enabled===!1?" disabled":"";if($.push(`### ${m.name} (${E}${D})`),m.lastRefreshedAt)$.push(` - Last token refresh: ${Af(m.lastRefreshedAt,_)}`);if(m.error)$.push(` - Error: ${m.error}`);$.push(Y0("five_hour",m.quota?.five_hour,_)),$.push(Y0("seven_day",m.quota?.seven_day,_)),$.push("")}return $.join(`
|
|
27
|
-
`).trimEnd()}import{Buffer as R0}from"node:buffer";import{createHash as R_,randomBytes as k_}from"node:crypto";class Xf extends Error{}var Vf=new Map,V0=new Map,O0=new Set,h0=0;function Zf(){return h0+=1,`req_${Date.now().toString(36)}_${h0.toString(36)}`}function Ef(f){if(O0.has(f))return;O0.add(f),b(f)}function Lm(f){let _=f?.relay;if(!_)return Ef("disabled: no relay config found"),null;if(_.enabled!==!0)return Ef("disabled: relay.enabled is not true"),null;if(!_.url?.trim()||!_.token?.trim())return Ef("disabled: missing relay url or token"),null;let $=_.transport==="http"?"http":"websocket";return Ef(`configured transport=${$} protocol=${$==="websocket"?2:1} url=${_.url.trim()} fallbackToDirect=${_.fallbackToDirect!==!1}`),{enabled:!0,url:_.url.trim(),token:_.token.trim(),fallbackToDirect:_.fallbackToDirect!==!1,transport:$}}function Qm(){return k_(32).toString("base64url")}function i_(f){return`sha256:${R_("sha256").update(f).digest("hex")}`}function q0(f,_){let $=0,m=Math.min(f.length,_.length);while($<m&&f.charCodeAt($)===_.charCodeAt($))$++;let E=f.length,D=_.length;while(E>$&&D>$&&f.charCodeAt(E-1)===_.charCodeAt(D-1))E--,D--;return{start:$,deleteCount:E-$,insert:_.slice($,D)}}function l_(f){return f.deleteCount===0&&f.insert.length===0}function P0(f){let _=f.match(/\bcch=([0-9a-f]{5});/),$=_?.[1];if(!$||_.index==null)return null;let m=_.index+4;return{start:m,end:m+$.length,token:$}}function u_(f,_,$,m){return`${f.slice(0,_)}${m}${f.slice($)}`}function k0(f,_){let $=P0(f),m=P0(_);if($&&m&&$.start===m.start&&$.end-$.start===m.end-m.start&&$.token!==m.token){let E={start:$.start,deleteCount:$.end-$.start,insert:m.token},D=u_(f,$.start,$.end,m.token),C=q0(D,_);return l_(C)?E:[E,C]}return q0(f,_)}function y_(f,_){if(typeof _!=="string")return!1;try{let $=f instanceof Request?new URL(f.url):new URL(f.toString());return $.pathname==="/v1/messages"||$.pathname==="/messages"}catch{return!1}}function n_(f){let _={};for(let[$,m]of f.entries()){if($==="x-session-affinity"||$==="x-opencode-session")continue;_[$]=m}return _}async function x0(f,_){return fetch(f.url,{method:"POST",headers:{"content-type":"application/json","x-relay-token":f.token},body:JSON.stringify(_)})}function G(f){return f.length>12?`${f.slice(0,12)}…`:f}function Z(){return performance.now()}function q(f){return Math.round(f*10)/10}function p_(f){let{input:_,init:$,headers:m,bodyText:E,affinity:D,previous:C,nextHash:F}=f,H=_ instanceof Request?_.url:_.toString(),K={protocol:1,type:"request",affinity:D,upstream:{url:H,method:$?.method||(_ instanceof Request?_.method:"POST"),headers:n_(m)},next_hash:F};return C?{...K,mode:"patch",base_hash:C.hash,revision:C.revision+1,patch:k0(C.body,E)}:{...K,mode:"full_sync",revision:1,body:E}}function Yf(f,_){return{protocol:f.protocol,type:"request",affinity:f.affinity,upstream:f.upstream,next_hash:f.next_hash,mode:"full_sync",revision:1,body:_}}function i0(f,_,$,m){Vf.set(f,{body:_,hash:$,revision:m})}async function w0(f){let{config:_,payload:$,bodyText:m,fallback:E}=f,D=$,C=await x0(_,D);if(C.status===409&&D.mode==="patch")b(`state mismatch from relay session=${G(D.affinity)}; retrying full_sync`),await C.body?.cancel().catch(()=>{}),D=Yf(D,m),C=await x0(_,D);if(!C.ok&&C.status>=500&&_.fallbackToDirect)return b(`relay returned ${C.status}; falling back direct session=${G(D.affinity)}`),await C.body?.cancel().catch(()=>{}),{response:await E(),payload:D,transport:"http",protocol:D.protocol,usedRelay:!1};return{response:C,payload:D,transport:"http",protocol:D.protocol,usedRelay:!0}}function c_(f,_){let $=new URL(f);return $.protocol=$.protocol==="http:"?"ws:":"wss:",$.pathname="/ws",$.searchParams.set("token",_),$.toString()}function v_(f){return new Uint8Array(R0.from(f,"base64"))}function d_(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(R0.from(String(f)))}function g_(f){return JSON.parse(f)}class l0{config;affinity;socket;connecting;queue=Promise.resolve();pending;serverState;constructor(f,_){this.config=f,this.affinity=_}send(f,_,$=!1){let m=Z(),E=this.queue.catch(()=>{}).then(()=>this.startQueued(f,_,m,$)),D=E.then(async({response:C,getPayload:F})=>({response:await C,payload:F(),transport:"websocket",protocol:2,usedRelay:!0}));return this.queue=E.then(({done:C})=>C.catch(()=>{}),()=>{}),D}async startQueued(f,_,$,m){let E=Z();await this.ensureConnected();let D=Z(),C=Vf.get(this.affinity),F=this.serverState?.hash,H={...f,protocol:2,id:Zf()};if(H.mode==="patch"&&(!F||F!==H.base_hash))H.mode="full_sync",H.revision=(this.serverState?.revision??0)+1,delete H.base_hash,delete H.patch,H.body=_;if(H.mode==="patch"&&C)H.patch=k0(C.body,_);b(`perf websocket send_start session=${G(this.affinity)} request=${H.id} mode=${H.mode} queueMs=${q(D-$)} connectMs=${q(D-E)} bodyBytes=${_.length} relayBytes=${JSON.stringify(H).length}`);let K=H,S=this.sendPayload(H,_,m);S.done.catch(()=>{});let j=S.done,T=S.response.catch((N)=>{if(!(N instanceof Xf)||H.mode!=="patch")throw N;let B=Yf(H,_);B.protocol=2,B.id=Zf(),B.revision=(this.serverState?.revision??0)+1,K=B;let W=this.sendPayload(B,_,m);return W.done.catch(()=>{}),j=W.done,W.response}),Q=T.then(()=>j,()=>j.catch(()=>{}));return{response:T,done:Q,getPayload:()=>K}}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 $=c_(this.config.url,this.config.token),m=new URL($);m.searchParams.set("affinity",this.affinity);let E=new WebSocket(m.toString());this.socket=E,this.serverState=void 0;let D=setTimeout(()=>{E.close(),_(Error("relay websocket ready timed out"))},15000);E.addEventListener("message",(C)=>{try{if(typeof C.data!=="string"){this.handleBinaryChunk(C.data);return}let F=g_(C.data);if(F.type==="ready"){clearTimeout(D),this.serverState=F.state,f();return}this.handleMessage(F)}catch(F){clearTimeout(D),_(F),this.failPending(F),E.close()}}),E.addEventListener("error",()=>{clearTimeout(D);let C=Error("relay websocket error");_(C),this.failPending(C)}),E.addEventListener("close",()=>{if(clearTimeout(D),this.socket===E)this.socket=void 0,this.serverState=void 0,this.connecting=void 0;if(this.pending){if(this.pending.retryingBeforeResponse)return;if(this.retryPendingBeforeResponse(this.pending,"closed before response"))return;let C=Error("relay websocket closed before response");this.failPending(C)}})}).finally(()=>{this.connecting=void 0}),await this.connecting}sendPayload(f,_,$){let m=this.socket;if(!m||m.readyState!==WebSocket.OPEN)throw Error("relay websocket is not connected");let E=Z(),D,C,F=new Promise((K,S)=>{D=K,C=S});return{response:new Promise((K,S)=>{let j={payload:f,bodyText:_,resolve:K,reject:S,streamDone:!1,accepted:!1,responseStarted:!1,resolveDone:D,rejectDone:C,sentAt:E,optimisticResponse:$,retryAttempts:0,retryingBeforeResponse:!1};if(this.pending=j,this.resetPendingTimeout(j),m.send(JSON.stringify(f)),$)this.resolvePendingResponse(j,200,"OK",{"content-type":"text/event-stream","x-cortexkit-relay-optimistic":"true"})}),done:F}}resetPendingTimeout(f){clearTimeout(f.timeout),f.timeout=setTimeout(()=>{if(this.pending!==f)return;if(this.retryPendingBeforeResponse(f,"response timed out"))return;this.failPending(Error("relay websocket response timed out")),this.socket?.close()},45000)}retryPendingBeforeResponse(f,_){if(f.responseStartedAt!=null)return!1;if(f.streamDone)return!1;if(f.retryAttempts>=1)return!1;f.retryAttempts+=1,f.retryingBeforeResponse=!0,clearTimeout(f.timeout);let $=f.retryAttempts,m=f.payload.id;return b(`websocket ${_}; reconnecting and retrying full_sync session=${G(this.affinity)} request=${m} retry=${$}`),this.socket?.close(),this.socket=void 0,this.serverState=void 0,this.connecting=void 0,(async()=>{try{if(await this.ensureConnected(),this.pending!==f)return;let E=Yf(f.payload,f.bodyText);E.protocol=2,E.id=Zf(),E.revision=(this.serverState?.revision??0)+1,f.payload=E,f.accepted=!1,f.acceptedAt=void 0,f.responseStartedAt=void 0,f.sentAt=Z(),f.retryingBeforeResponse=!1;let D=this.socket;if(!D||D.readyState!==WebSocket.OPEN)throw Error("relay websocket is not connected");this.resetPendingTimeout(f),b(`perf websocket retry_send session=${G(this.affinity)} request=${E.id} previous=${m} mode=full_sync retry=${$} bodyBytes=${f.bodyText.length} relayBytes=${JSON.stringify(E).length}`),D.send(JSON.stringify(E))}catch(E){if(f.retryingBeforeResponse=!1,this.pending===f)this.failPending(E)}})(),!0}handleBinaryChunk(f){let _=this.pending;if(!_?.responseStarted)return;_.streamController?.enqueue(d_(f))}resolvePendingResponse(f,_,$,m){if(f.responseStarted)return;f.responseStarted=!0;let E=new ReadableStream({start:(D)=>{f.streamController=D},cancel:()=>{this.socket?.close()}});f.resolve(new Response(E,{status:_,statusText:$,headers:m}))}handleMessage(f){if(f.type==="keepalive"){if(this.pending)this.resetPendingTimeout(this.pending);return}let _=this.pending;if(!_)return;if("id"in f&&f.id&&f.id!==_.payload.id)return;if(f.type==="accepted"){let $=Z();_.accepted=!0,_.acceptedAt=$,b(`perf websocket accepted session=${G(this.affinity)} request=${_.payload.id} sentMs=${q($-_.sentAt)} mode=${_.payload.mode}`),this.serverState={hash:f.hash,revision:f.revision},i0(this.affinity,_.bodyText,f.hash,f.revision),this.resetPendingTimeout(_);return}if(f.type==="response_start"){let $=Z();if(_.responseStartedAt=$,b(`perf websocket response_start session=${G(this.affinity)} request=${_.payload.id} sentMs=${q($-_.sentAt)} upstreamMs=${_.acceptedAt==null?"unknown":q($-_.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
|
|
28
|
-
data: ${JSON.stringify({type:"error",error:{type:"relay_upstream_error",message:`Relay upstream returned HTTP ${f.status}`}})}
|
|
29
|
-
|
|
30
|
-
`)),this.finishPending();return}if(f.type==="chunk"){_.streamController?.enqueue(v_(f.base64));return}if(f.type==="done"){this.finishPending();return}if(f.type==="error"){if(_.optimisticResponse&&_.responseStartedAt!=null){b(`websocket relay error during optimistic response session=${G(this.affinity)} request=${_.payload.id} status=${f.status} message=${f.message||"unknown"}`),_.streamController?.enqueue(new TextEncoder().encode(`event: error
|
|
31
|
-
data: ${JSON.stringify({type:"error",error:{type:"relay_error",message:f.message||"relay error"}})}
|
|
32
|
-
|
|
33
|
-
`)),this.finishPending(),this.socket?.close();return}if(f.status===409&&this.retryPendingBeforeResponse(_,f.message||"state mismatch"))return;let $=f.status===409?new Xf(f.message||"state mismatch"):Error(f.message||"relay websocket error");this.failPending($)}}finishPending(){let f=this.pending;if(!f)return;let _=Z();if(b(`perf websocket done session=${G(this.affinity)} request=${f.payload.id} sentMs=${q(_-f.sentAt)} streamMs=${f.responseStartedAt==null?"unknown":q(_-f.responseStartedAt)}`),clearTimeout(f.timeout),!f.streamDone)f.streamDone=!0,f.streamController?.close();f.resolveDone(),this.pending=void 0}failPending(f){let _=this.pending;if(!_)return;if(clearTimeout(_.timeout),this.pending=void 0,_.responseStarted)_.streamController?.error(f);else _.reject(f);_.rejectDone(f)}}function s_(f,_){let $=V0.get(_);if($)return $;let m=new l0(f,_);return V0.set(_,m),m}async function Tm(f){let{config:_,input:$,init:m,headers:E,body:D,fallback:C,affinity:F,optimisticResponse:H}=f;if(!_||!y_($,D))return C();let K=F||E.get("x-session-affinity")||E.get("x-opencode-session");if(!K)return b("skipping relay: missing x-session-affinity header"),C();let S=D,j=i_(S),T=Vf.get(K),Q=p_({input:$,init:m,headers:E,bodyText:S,affinity:K,previous:T,nextHash:j});try{let N;if(_.transport==="websocket")try{N=await s_(_,K).send(Q,S,H===!0)}catch(W){b(`websocket relay failed session=${G(K)}; trying http relay: ${W instanceof Error?W.message:String(W)}`),N=await w0({config:_,payload:Q,bodyText:S,fallback:C})}else N=await w0({config:_,payload:Q,bodyText:S,fallback:C});if(!N.usedRelay)return N.response;if(N.transport==="http")i0(K,S,N.payload.next_hash,N.payload.revision);let B=JSON.stringify(N.payload).length;return b(`used relay transport=${N.transport} protocol=${N.protocol} mode=${N.payload.mode} status=${N.response.status} session=${G(K)} bodyBytes=${S.length} relayBytes=${B}`),await A0({affinity:K,transport:N.transport,protocol:N.protocol,mode:N.payload.mode,status:N.response.status,bodyText:S,previousBodyText:T?.body,payload:N.payload,relayBytes:B}),N.response}catch(N){if(!_.fallbackToDirect)throw b(`relay failed session=${G(K)} and fallbackToDirect=false: ${N instanceof Error?N.message:String(N)}`),N;return b(`relay failed; falling back direct session=${G(K)}: ${N instanceof Error?N.message:String(N)}`),C()}}var Am=`
|
|
34
|
-
async function hashBody(body) {
|
|
35
|
-
const bytes = new TextEncoder().encode(body)
|
|
36
|
-
const digest = await crypto.subtle.digest('SHA-256', bytes)
|
|
37
|
-
const hex = [...new Uint8Array(digest)].map((b) => b.toString(16).padStart(2, '0')).join('')
|
|
38
|
-
return 'sha256:' + hex
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
function applyPatch(base, patch) {
|
|
42
|
-
return base.slice(0, patch.start) + patch.insert + base.slice(patch.start + patch.deleteCount)
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
function applyPatchSet(base, patch) {
|
|
46
|
-
if (!Array.isArray(patch)) return applyPatch(base, patch)
|
|
47
|
-
if (patch.length === 0) return base
|
|
48
|
-
|
|
49
|
-
let result = ''
|
|
50
|
-
let cursor = 0
|
|
51
|
-
for (const item of patch) {
|
|
52
|
-
if (item.start < cursor) return { error: 'overlapping patch', status: 400 }
|
|
53
|
-
result += base.slice(cursor, item.start)
|
|
54
|
-
result += item.insert
|
|
55
|
-
cursor = item.start + item.deleteCount
|
|
56
|
-
}
|
|
57
|
-
return result + base.slice(cursor)
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
async function readState(env, affinity) {
|
|
61
|
-
const raw = await env.RELAY_STATE.get('session:' + affinity)
|
|
62
|
-
return raw ? JSON.parse(raw) : null
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
async function writeState(env, affinity, state) {
|
|
66
|
-
await env.RELAY_STATE.put('session:' + affinity, JSON.stringify(state), { expirationTtl: 86400 })
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
async function resolveBody(env, payload) {
|
|
70
|
-
if (payload.mode === 'full_sync') return payload.body
|
|
71
|
-
if (payload.mode === 'patch') {
|
|
72
|
-
const state = await readState(env, payload.affinity)
|
|
73
|
-
if (!state || state.hash !== payload.base_hash) {
|
|
74
|
-
return { error: 'state mismatch', status: 409 }
|
|
75
|
-
}
|
|
76
|
-
return applyPatchSet(state.body, payload.patch)
|
|
77
|
-
}
|
|
78
|
-
return { error: 'unknown mode', status: 400 }
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
async function prepareUpstream(env, payload) {
|
|
82
|
-
if ((payload.protocol !== 1 && payload.protocol !== 2) || payload.type !== 'request' || !payload.affinity || !payload.upstream?.url || !payload.next_hash) {
|
|
83
|
-
return { error: 'invalid payload', status: 400 }
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
const body = await resolveBody(env, payload)
|
|
87
|
-
if (body && typeof body === 'object' && 'error' in body) return body
|
|
88
|
-
|
|
89
|
-
if (typeof body !== 'string' || (await hashBody(body)) !== payload.next_hash) {
|
|
90
|
-
return { error: 'hash mismatch', status: 409 }
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
const stateWrite = writeState(env, payload.affinity, { body, hash: payload.next_hash, revision: payload.revision }).catch(() => {})
|
|
94
|
-
console.log(JSON.stringify({
|
|
95
|
-
relay: 'opencode-anthropic-auth',
|
|
96
|
-
transport: 'relay',
|
|
97
|
-
mode: payload.mode,
|
|
98
|
-
revision: payload.revision,
|
|
99
|
-
affinity: String(payload.affinity).slice(0, 12),
|
|
100
|
-
bodyBytes: body.length,
|
|
101
|
-
}))
|
|
102
|
-
|
|
103
|
-
return { body, stateWrite }
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
function resolveBodyFromState(state, payload) {
|
|
107
|
-
if (payload.mode === 'full_sync') return payload.body
|
|
108
|
-
if (payload.mode === 'patch') {
|
|
109
|
-
if (!state || state.hash !== payload.base_hash) {
|
|
110
|
-
return { error: 'state mismatch', status: 409 }
|
|
111
|
-
}
|
|
112
|
-
return applyPatchSet(state.body, payload.patch)
|
|
113
|
-
}
|
|
114
|
-
return { error: 'unknown mode', status: 400 }
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
function deferWorkerTask(task) {
|
|
118
|
-
return new Promise((resolve) => setTimeout(resolve, 0)).then(task)
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
function checkpointWebSocketState(env, payload, body, nextState) {
|
|
122
|
-
return deferWorkerTask(async () => {
|
|
123
|
-
try {
|
|
124
|
-
if ((await hashBody(body)) !== payload.next_hash) {
|
|
125
|
-
throw new Error('hash mismatch')
|
|
126
|
-
}
|
|
127
|
-
await writeState(env, payload.affinity, nextState)
|
|
128
|
-
} catch (error) {
|
|
129
|
-
console.log(JSON.stringify({
|
|
130
|
-
relay: 'opencode-anthropic-auth',
|
|
131
|
-
transport: 'websocket',
|
|
132
|
-
event: 'checkpoint_write_failed',
|
|
133
|
-
affinity: String(payload.affinity).slice(0, 12),
|
|
134
|
-
message: error instanceof Error ? error.message : String(error),
|
|
135
|
-
}))
|
|
136
|
-
}
|
|
137
|
-
})
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
async function prepareWebSocketUpstream(env, state, payload) {
|
|
141
|
-
if (payload.protocol !== 2 || payload.type !== 'request' || !payload.id || !payload.affinity || !payload.upstream?.url || !payload.next_hash) {
|
|
142
|
-
return { error: 'invalid payload', status: 400 }
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
const body = resolveBodyFromState(state, payload)
|
|
146
|
-
if (body && typeof body === 'object' && 'error' in body) return body
|
|
147
|
-
if (typeof body !== 'string') return { error: 'invalid body', status: 400 }
|
|
148
|
-
if ((await hashBody(body)) !== payload.next_hash) {
|
|
149
|
-
return { error: 'hash mismatch', status: 409 }
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
const nextState = { body, hash: payload.next_hash, revision: payload.revision }
|
|
153
|
-
const checkpoint = checkpointWebSocketState(env, payload, body, nextState)
|
|
154
|
-
const logAccepted = () => console.log(JSON.stringify({
|
|
155
|
-
relay: 'opencode-anthropic-auth',
|
|
156
|
-
transport: 'websocket',
|
|
157
|
-
mode: payload.mode,
|
|
158
|
-
revision: payload.revision,
|
|
159
|
-
affinity: String(payload.affinity).slice(0, 12),
|
|
160
|
-
bodyBytes: body.length,
|
|
161
|
-
}))
|
|
162
|
-
|
|
163
|
-
return { body, state: nextState, checkpoint, logAccepted }
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
function headersToObject(headers) {
|
|
167
|
-
const result = {}
|
|
168
|
-
for (const [key, value] of headers.entries()) result[key] = value
|
|
169
|
-
return result
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
async function handleRelayPayload(env, payload) {
|
|
173
|
-
const prepared = await prepareUpstream(env, payload)
|
|
174
|
-
if (prepared.error) return prepared
|
|
175
|
-
const upstream = await fetch(payload.upstream.url, {
|
|
176
|
-
method: payload.upstream.method || 'POST',
|
|
177
|
-
headers: payload.upstream.headers,
|
|
178
|
-
body: prepared.body,
|
|
179
|
-
})
|
|
180
|
-
return { upstream, stateWrite: prepared.stateWrite }
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
async function handleWebSocket(socket, env, ctx, payload, getState, setState) {
|
|
184
|
-
const heartbeat = setInterval(() => {
|
|
185
|
-
try {
|
|
186
|
-
socket.send(JSON.stringify({ protocol: 2, type: 'keepalive' }))
|
|
187
|
-
} catch {
|
|
188
|
-
clearInterval(heartbeat)
|
|
189
|
-
}
|
|
190
|
-
}, 15000)
|
|
191
|
-
try {
|
|
192
|
-
const result = await prepareWebSocketUpstream(env, getState(), payload)
|
|
193
|
-
if (result.error) {
|
|
194
|
-
socket.send(JSON.stringify({ protocol: 2, type: 'error', id: payload.id, status: result.status, message: result.error }))
|
|
195
|
-
return
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
setState(result.state)
|
|
199
|
-
socket.send(JSON.stringify({ protocol: 2, type: 'accepted', id: payload.id, hash: result.state.hash, revision: result.state.revision }))
|
|
200
|
-
ctx?.waitUntil?.(deferWorkerTask(result.logAccepted))
|
|
201
|
-
|
|
202
|
-
const upstreamPromise = fetch(payload.upstream.url, {
|
|
203
|
-
method: payload.upstream.method || 'POST',
|
|
204
|
-
headers: payload.upstream.headers,
|
|
205
|
-
body: result.body,
|
|
206
|
-
})
|
|
207
|
-
ctx?.waitUntil?.(result.checkpoint)
|
|
208
|
-
const upstream = await upstreamPromise
|
|
209
|
-
socket.send(JSON.stringify({
|
|
210
|
-
protocol: 2,
|
|
211
|
-
type: 'response_start',
|
|
212
|
-
id: payload.id,
|
|
213
|
-
status: upstream.status,
|
|
214
|
-
statusText: upstream.statusText,
|
|
215
|
-
headers: headersToObject(upstream.headers),
|
|
216
|
-
}))
|
|
217
|
-
|
|
218
|
-
const reader = upstream.body?.getReader()
|
|
219
|
-
if (reader) {
|
|
220
|
-
while (true) {
|
|
221
|
-
const { done, value } = await reader.read()
|
|
222
|
-
if (done) break
|
|
223
|
-
socket.send(value)
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
socket.send(JSON.stringify({ protocol: 2, type: 'done', id: payload.id }))
|
|
227
|
-
} catch (error) {
|
|
228
|
-
socket.send(JSON.stringify({ protocol: 2, type: 'error', id: payload.id, status: 500, message: error instanceof Error ? error.message : String(error) }))
|
|
229
|
-
} finally {
|
|
230
|
-
clearInterval(heartbeat)
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
export default {
|
|
235
|
-
async fetch(request, env, ctx) {
|
|
236
|
-
if (request.headers.get('Upgrade') === 'websocket') {
|
|
237
|
-
const url = new URL(request.url)
|
|
238
|
-
const token = url.searchParams.get('token')
|
|
239
|
-
const affinity = url.searchParams.get('affinity')
|
|
240
|
-
if (token !== env.RELAY_TOKEN) return new Response('unauthorized', { status: 401 })
|
|
241
|
-
if (!affinity) return new Response('missing affinity', { status: 400 })
|
|
242
|
-
const pair = new WebSocketPair()
|
|
243
|
-
const client = pair[0]
|
|
244
|
-
const server = pair[1]
|
|
245
|
-
server.binaryType = 'arraybuffer'
|
|
246
|
-
let state = null
|
|
247
|
-
let ready = false
|
|
248
|
-
server.accept()
|
|
249
|
-
const loadState = readState(env, affinity).then((loadedState) => {
|
|
250
|
-
state = loadedState
|
|
251
|
-
ready = true
|
|
252
|
-
server.send(JSON.stringify({
|
|
253
|
-
protocol: 2,
|
|
254
|
-
type: 'ready',
|
|
255
|
-
state: state ? { hash: state.hash, revision: state.revision } : null,
|
|
256
|
-
}))
|
|
257
|
-
}).catch((error) => {
|
|
258
|
-
server.send(JSON.stringify({ protocol: 2, type: 'error', status: 500, message: error instanceof Error ? error.message : String(error) }))
|
|
259
|
-
server.close(1011, 'state load failed')
|
|
260
|
-
})
|
|
261
|
-
ctx?.waitUntil?.(loadState)
|
|
262
|
-
if (!ctx?.waitUntil) void loadState
|
|
263
|
-
let busy = false
|
|
264
|
-
server.addEventListener('message', (event) => {
|
|
265
|
-
if (!ready) {
|
|
266
|
-
server.send(JSON.stringify({ protocol: 2, type: 'error', status: 425, message: 'relay state is not ready' }))
|
|
267
|
-
return
|
|
268
|
-
}
|
|
269
|
-
if (busy) {
|
|
270
|
-
server.send(JSON.stringify({ protocol: 2, type: 'error', status: 429, message: 'request already in flight' }))
|
|
271
|
-
return
|
|
272
|
-
}
|
|
273
|
-
let payload
|
|
274
|
-
try {
|
|
275
|
-
payload = JSON.parse(event.data)
|
|
276
|
-
} catch {
|
|
277
|
-
server.send(JSON.stringify({ protocol: 2, type: 'error', status: 400, message: 'invalid JSON payload' }))
|
|
278
|
-
return
|
|
279
|
-
}
|
|
280
|
-
payload.affinity = affinity
|
|
281
|
-
busy = true
|
|
282
|
-
const run = handleWebSocket(server, env, ctx, payload, () => state, (nextState) => { state = nextState }).finally(() => { busy = false })
|
|
283
|
-
ctx?.waitUntil?.(run)
|
|
284
|
-
if (!ctx?.waitUntil) void run
|
|
285
|
-
})
|
|
286
|
-
return new Response(null, { status: 101, webSocket: client })
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
if (request.method === 'GET') {
|
|
290
|
-
return Response.json({ status: 'ok', transports: ['http', 'websocket'] })
|
|
291
|
-
}
|
|
292
|
-
if (request.method !== 'POST') return new Response('method not allowed', { status: 405 })
|
|
293
|
-
if (request.headers.get('x-relay-token') !== env.RELAY_TOKEN) {
|
|
294
|
-
return new Response('unauthorized', { status: 401 })
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
try {
|
|
298
|
-
const payload = await request.json()
|
|
299
|
-
const result = await handleRelayPayload(env, payload)
|
|
300
|
-
if (result.error) return Response.json({ error: result.error }, { status: result.status })
|
|
301
|
-
|
|
302
|
-
if (result.stateWrite) ctx.waitUntil(result.stateWrite)
|
|
303
|
-
|
|
304
|
-
const upstream = result.upstream
|
|
305
|
-
return new Response(upstream.body, {
|
|
306
|
-
status: upstream.status,
|
|
307
|
-
statusText: upstream.statusText,
|
|
308
|
-
headers: upstream.headers,
|
|
309
|
-
})
|
|
310
|
-
} catch (error) {
|
|
311
|
-
return Response.json(
|
|
312
|
-
{ error: error instanceof Error ? error.message : 'internal relay error' },
|
|
313
|
-
{ status: 502 },
|
|
314
|
-
)
|
|
315
|
-
}
|
|
316
|
-
},
|
|
317
|
-
}
|
|
318
|
-
`;export{t_ as a,xf as b,r_ as c,o_ as d,a_ as e,e_ as f,wf as g,f$ as h,_$ as i,X as j,pf as k,C$ as l,H$ as m,z as n,L as o,V as p,O as q,T1 as r,G$ as s,Z1 as t,B$ as u,W$ as v,U$ as w,z$ as x,L$ as y,Q$ as z,T$ as A,A$ as B,Z$ as C,D0 as D,q1 as E,k as F,Nf as G,i as H,H0 as I,X$ as J,ef as K,i1 as L,O$ as M,h$ as N,q$ as O,P$ as P,p1 as Q,x$ as R,J0 as S,d$ as T,i$ as U,l$ as V,u$ as W,b0 as X,r$ as Y,o$ as Z,j_ as _,Wf as $,U0 as aa,I_ as ba,a$ as ca,G_ as da,Dm as ea,Cm as fa,Z_ as ga,Hm as ha,Mm as ia,Km as ja,Nm as ka,h_ as la,Sm as ma,jm as na,Im as oa,Jm as pa,Lm as qa,Qm as ra,Tm as sa,Am as ta};
|