@cortexkit/opencode-anthropic-auth 2.4.0 → 2.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/effort-history.d.ts +15 -2
- package/dist/{index-46e2gk3c.js → index-12km9x91.js} +2 -2
- package/dist/{index-dpnhamzw.js → index-a1k6z503.js} +1 -1
- package/dist/index-xarkyfqd.js +45 -0
- package/dist/index.js +1 -1
- package/dist/sidebar-state.d.ts +7 -4
- package/dist/sidebar-state.js +1 -1
- package/dist/transform.d.ts +1 -0
- package/dist/v2/server.js +1 -1
- package/dist/v2/tui.js +1 -1
- package/package.json +5 -5
- package/src/sidebar-state.ts +22 -6
- package/src/tui/claude-sidebar.tsx +7 -2
- package/src/tui-compiled/sidebar-state.ts +22 -6
- package/src/tui-compiled/tui/claude-sidebar.tsx +6 -3
- package/dist/index-32m0nard.js +0 -43
package/dist/v2/server.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{a as d2,b as B1,c as z1,d as R$,e as S$,f as p2,g as A2,h as q$,i as A$,j as x$,k as K1,l as k$,m as b$,n as w$,o as D$,p as J$,q as F1}from"../index-
|
|
1
|
+
import{a as d2,b as B1,c as z1,d as R$,e as S$,f as p2,g as A2,h as q$,i as A$,j as x$,k as K1,l as k$,m as b$,n as w$,o as D$,p as J$,q as F1}from"../index-xarkyfqd.js";import"../index-sg0knfec.js";import"../index-hc7bm3yf.js";import{v as N1}from"../index-a1k6z503.js";import{w as c2,x as i2,z as _1}from"../index-m4dazzyf.js";import"../index-naff9h33.js";import{J as e$}from"../index-12km9x91.js";import"../index-gvswxab8.js";import"../index-71temqvq.js";import{acquireNativeAccountRuntime as jZ,authorize as QZ,createNativeUi as WZ,disconnectNativeVaultForHost as BZ,exchange as UZ,isDumpPersistentlyEnabled as zZ,logger as H1,openCodeHolderKind as KZ,readNativeEnrollmentMode as MZ,registerNativePoolHolder as HZ,resolveNativePoolPaths as _Z,setDumpEnabled as NZ}from"@cortexkit/anthropic-auth-core";class x2 extends Error{kind;providerID;sessionID;requestKind;constructor(X){super(X.message??`${X.providerID} ${X.requestKind} request refused (${X.kind})`);this.name="OpenCode2AuthError",this.kind=X.kind,this.providerID=X.providerID,this.sessionID=X.sessionID,this.requestKind=X.requestKind}}function O2(X){return`common-auth-placeholder.${X}`}function K$(X){let Z=O2(X.integrationID);return{type:"oauth",methodID:X.methodID,access:Z,refresh:Z,expires:X.now+31536000000,metadata:{["commonAuthPlaceholder"]:!0}}}function t2(X,Z){if(X?.type!=="oauth")return!1;let z=Z===void 0?void 0:O2(Z),W=(F)=>z===void 0?F.startsWith("common-auth-placeholder."):F===z;return W(X.access)&&W(X.refresh)}var M$="No browser sign-in: this connects the plugin to the accounts in its vault.";async function e2(X,Z){let z=Z.now??Date.now,{integrationID:W}=Z,F=(T)=>K$({integrationID:W,methodID:T,now:z()}),L=async(T,K)=>{return await Z.onLogin(T,{integrationID:W,methodID:K}),F(K)},C=(T)=>async(K)=>{let Y=T.method.id,U=await T.authorize(K),H={url:U.url,instructions:U.instructions,...U.expiresAt===void 0?{}:{expiresAt:U.expiresAt}};if(U.mode==="auto")return{...H,mode:"auto",callback:U.callback.then((P)=>L(P,Y))};let V=U.callback;return{...H,mode:"code",callback:async(P)=>L(await V(P),Y)}};return X.integration.transform((T)=>{let K=Z.label===void 0?{}:{label:()=>Z.label};for(let H of Z.methods)T.method.update({integrationID:W,method:H.method,authorize:C(H),refresh:async(V)=>{if(!t2(V,W))throw Error("This login method refreshes only its pool placeholder; sign in again with the plugin's login method.");return F(V.methodID)},...K});let Y=Z.vault;if(Y===void 0)return;let U=Y.method.id;T.method.update({integrationID:W,method:Y.method,authorize:async()=>({url:"",instructions:Y.instructions??M$,mode:"auto",callback:Promise.resolve().then(()=>Y.activate({integrationID:W,methodID:U})).then(()=>F(U))}),refresh:async(H)=>{if(!t2(H,W)||H.methodID!==U)throw Error("This login method refreshes only its vault placeholder; choose the plugin's vault login method again.");return F(U)},...K})})}function T1(X){let Z=[],z;for(let W of X.split(/\r?\n/))if(W.startsWith("data:"))Z.push(W.slice(5).replace(/^ /,""));else if(W.startsWith("event:"))z=W.slice(6).trim();if(Z.length===0)return;return z===void 0?{data:Z.join(`
|
|
2
2
|
`)}:{event:z,data:Z.join(`
|
|
3
3
|
`)}}function $$(X,Z){let z=new TextDecoder,W="",F=(C)=>{let T=T1(C);if(!T)return;try{X(T)}catch(K){Z(K)}},L=()=>{for(;;){let C=/\r?\n\r?\n/.exec(W);if(!C)return;let T=W.slice(0,C.index);W=W.slice(C.index+C[0].length),F(T)}};return new TransformStream({transform(C,T){T.enqueue(C),W+=z.decode(C,{stream:!0}),L()},flush(){if(W+=z.decode(),L(),W.trim()!=="")F(W);W=""}})}var H$=512,_$=1200000,k2="x-common-auth-attempt",S2=(X,Z)=>JSON.stringify([X,Z]),N2=(X)=>({providerID:X.model.providerID,modelID:X.model.id,sessionID:X.sessionID,agent:X.agent,kind:X.kind});function P1(X){let Z=X.headers;return typeof Z==="object"&&Z!==null}function C1(X,Z){let z=X.getReader();return new ReadableStream({async pull(W){let F;try{F=await z.read()}catch(L){Z({reason:"failed",message:L instanceof Error?L.message:String(L)}),W.error(L);return}if(F.done)Z(),W.close();else W.enqueue(F.value)},async cancel(W){Z({reason:"cancelled",...W===void 0?{}:{message:String(W)}}),await z.cancel(W)}})}function m2(X,Z){for(let[z,W]of Object.entries(Z)){let F=z.toLowerCase();for(let L of Object.keys(X))if(L.toLowerCase()===F)delete X[L];if(W!==null)X[z]=W}}function O1(X,Z){for(let[z,W]of Object.entries(Z))if(W===null)X.delete(z);else X.set(z,W)}async function X$(X,Z,z={}){let{providerID:W}=Z,F=z.gateOnPlaceholder,L=($)=>F===void 0||F.credential($)===O2(W),C=z.logger,T=Math.max(1,z.maxRecords??H$),K=[...z.hostCredentials??[O2(W)],...F?[O2(W)]:[]].filter(($)=>$!==""),Y=new Map,U=new WeakMap,H=new Map,V=0,P=new Set,x=new Map,q=new Map,f=($)=>{let G=q.get($);return G?.ownedSeen===!0&&G.foreignSeen},c=($,G)=>{x.set($,G);let _=q.get($)??{ownedSeen:!1,foreignSeen:!1};if(G)_.ownedSeen=!0;else _.foreignSeen=!0;q.set($,_)},D=($,G)=>{let _=F?.refuseMisplaced,S=_?[...G].filter(([,u])=>u.includes(O2(W))):[],O=L(G)&&(!_||S.length>0);if(_){if(S.length>0&&(S.length!==1||!O))throw c($.sessionID,!1),new x2({kind:"placement-refused",providerID:W,sessionID:$.sessionID,requestKind:$.kind,message:_(S[0]?.[0]??"")})}return c($.sessionID,O),O},r=!1,$2=!1,a=new Map,H2=0,n=!1,J=new Map,j=($,G)=>{try{C?.warn($,G)}catch{}},B=($)=>$ instanceof Error?$.message:String($),E=new Map,k=($,G)=>{let _=(E.get($)??Promise.resolve()).then(G),S=_.then(()=>{},()=>{});return E.set($,S),S.then(()=>{if(E.get($)===S)E.delete($)}),_},I=($,G)=>{let _=E.get($);return _?_.then(()=>I($,G)):G()},h=async($)=>{try{await Z.dropChoice?.({...$.input,accountId:$.accountId})}catch(G){j("opencode2 auth dropChoice threw; the request is unaffected",{sessionID:$.input.sessionID,error:B(G)})}},i=($)=>{let G=H.get($);if(H.delete($),G?.next){let _=G.next;k(G.sessionID,()=>h(_))}},p=async($,G)=>{let _=a.get($);if(!_||_.size===0)return;await Promise.all([..._].map(async(S)=>{try{await S(G)}catch(O){j("opencode2 auth listener threw; the request is unaffected",{event:$,error:B(O)})}}))},J2=async($,G)=>{try{await Z.onAttemptEnd?.($,G)}catch(_){j("opencode2 auth onAttemptEnd threw; the request is unaffected",{attemptId:$.attemptId,error:B(_)})}},g=($,G)=>{if($.ended||!$.attempt)return;let _={...$.status===void 0?{}:{status:$.status},outputStarted:$.outputStarted,...$.limit?{limit:$.limit.signal}:{},...G?{error:G}:{}};if(G)$.endError=G;$.ended=J2($.attempt,_)},m=($,G)=>g($,{reason:"abandoned",message:G}),l=($)=>[...Y.values()].filter((G)=>G.key===$),z2=($)=>l($).at(-1),P2=($)=>{if(Y.delete($.id),H.get($.key)?.attemptId===$.id||!l($.key).length)i($.key)},t=($)=>{Y.set($.id,$);while(Y.size>T){let G=Y.values().next().value;if(G===void 0)break;m(G,"dropped to keep the record bound"),P2(G)}},j2=($)=>$.accountId===void 0?void 0:{...$.scope,accountId:$.accountId},Q=($,G)=>new x2({kind:"no-account",providerID:W,sessionID:$.sessionID,requestKind:$.kind,...G===void 0?{}:{message:G}}),N=($)=>{J.get($)?.clear(),J.delete($)},M=async($,G)=>{let _=()=>Q($,`${W} ${$.kind} request has no account: its auth selection was revoked by session forgetting or installation disposal`);if(n)throw _();let S=J.get($.sessionID);if(!S)S=new Set,J.set($.sessionID,S);let O={};S.add(O);let u=()=>{if(!S.has(O))throw _()};try{return await G(u)}finally{if(S.delete(O),S.size===0&&J.get($.sessionID)===S)J.delete($.sessionID)}},A=($,G)=>{for(let[_,S]of G)if(K.some((O)=>S.includes(O)))throw new x2({kind:"host-credential-on-wire",providerID:W,sessionID:$.sessionID,requestKind:$.kind,message:`${W} ${$.kind} request still carries the host's placeholder credential in ${_}; the adapter's account headers must replace it`})},R=($)=>{for(let G of l($))if(G.ended||!G.attempt)P2(G);else if(G.transport==="ws"||G.judged)m(G,"a newer attempt of its session and kind began"),P2(G)},w=async($,G,_,S)=>{let O=S2($.sessionID,$.kind),{input:u,accountId:b}=await I($.sessionID,async()=>{_();let W2=H.get(O);H.delete(O);let L2=W2?.accountId??z2(O)?.accountId;R(O);let F2=W2?.next,U2=F2!==void 0&&F2.input.modelID===$.modelID&&F2.input.agent===$.agent,y2={...$,phase:"request",...L2===void 0?{}:{previousAccountId:L2},...W2?.rerouteFrom?{rerouteFrom:W2.rerouteFrom}:{}};if(F2&&!U2)await k($.sessionID,()=>h(F2)),_();let C2=U2?F2.accountId:await Z.chooseAccount(y2);return{input:y2,accountId:typeof C2==="string"?C2:void 0}});_();let v={},Z2;if(b!==void 0){let W2=await Z.accountHeaders({...$,accountId:b});if(_(),P1(W2))v=W2.headers,Z2=W2.attempt;else v=W2}let E2=`attempt-${++H2}`,_2={id:E2,key:O,scope:$,accountId:b,headers:v,attempt:b===void 0?void 0:{...$,accountId:b,attemptId:E2,transport:S,data:Z2},...S===void 0?{}:{transport:S},outputStarted:!1};if(t(_2),_2.attempt)p("select",{...$,accountId:_2.attempt.accountId,hook:G,...u.previousAccountId===void 0?{}:{previousAccountId:u.previousAccountId},...u.rerouteFrom===void 0?{}:{rerouteFrom:u.rerouteFrom},handle:_2.attempt});return _2},y=async($,G,_,S,O)=>{let u=S2($.sessionID,$.kind),b=S===void 0?void 0:Y.get(S);if(b?.key!==u)b=void 0;if(!b){if(b=z2(u),l(u).filter((Z2)=>Z2.transport===void 0&&!Z2.ended).length>1&&!$2)$2=!0,j("opencode2 auth tied a send without its attempt mark to the newest of several waiting attempts",{sessionID:$.sessionID,kind:$.kind})}if(!b||b.transport!==void 0||b.ended)b=await w($,G,O,_);else if(b.transport=_,b.attempt)b.attempt.transport=_;if(_==="ws"){for(let v of l(u))if(v!==b&&v.transport==="ws")m(v,"a newer attempt of its session and kind went out over WebSocket")}return b},s=async($,G)=>{try{return await G()}catch(_){throw g($,{reason:"failed",message:B(_)}),_}},d=($,G)=>{let _=l(S2($,G)).filter((S)=>S.transport==="ws").at(-1);return _?.attempt!==void 0&&!_.ended?_:void 0},Y2=($,G,_)=>{let S=j2($);if(!S||!$.attempt||$.limit)return;$.limit={signal:G,delivered:p("limit",{...S,via:_,limit:G,outputStarted:$.outputStarted,handle:$.attempt})}},Q2=($,G,_,S)=>{let O=j2($);if(!O||!$.attempt)return;p("quota",{...O,transport:G,...S===void 0?{}:{status:S},quota:_,handle:$.attempt})},B2=($,G,_,S)=>{let O=$.attempt;if(!O)return;let u=Z.inspectEvent?.(S===void 0?{transport:G,data:_,attempt:O}:{transport:G,data:_,event:S,attempt:O});if(!u)return;if(u.quota!==void 0)Q2($,G,u.quota);if(u.outputStarted)$.outputStarted=!0;if(u.limit)Y2($,u.limit,G);if(u.error!==void 0)g($,{reason:"failed",message:u.error});else if(u.done)g($)},T2=($,G)=>{let _=$.attempt;if(!_||G.accountId===$.accountId)return;if(_.reboundFrom??=_.accountId,_.accountId=G.accountId,"data"in G)_.data=G.data;$.accountId=G.accountId},X2=($)=>!$.attempt||$.endError!==void 0||$.status!==void 0&&$.status>=400,e=($)=>{let G=[...Y.values()].filter((v)=>v.scope.sessionID===$),_=G.filter((v)=>v.limit&&!v.rerouted).at(-1);if(_)return _;let S=G.filter((v)=>v.scope.kind==="primary"),O=S.length>0?S:G;if(O.length<=1)return O[0];let u=O.filter((v)=>!v.judged&&X2(v)).at(-1);if(u)return u;let b=O.filter((v)=>v.attempt&&!v.ended);if(b.length>1)return"ambiguous";return b[0]??O.at(-1)},G2={providerID:W},V2=[];V2.push(await X.session.hook("model.request",($)=>{if(F)return;return M(N2($),async(G)=>{let _=await w(N2($),"model.request",G);if(G(),_.accountId===void 0)throw Q(_.scope);m2($.headers,{..._.headers,[k2]:_.id})})},G2)),V2.push(await X.session.hook("http.request",($)=>{if(F){if(!D(N2($),$.request.headers))return}return M(N2($),async(G)=>{let _=$.request.headers.get(k2)??void 0,S=F?await w(N2($),"http.request",G,"http"):await y(N2($),"http.request","http",_,G);G();let O=j2(S),u=S.attempt;if(!O||!u)throw Q(S.scope);await s(S,async()=>{let b=$.request;if(Z.rewriteRequest){if(_!==void 0){let E2=new Headers(b.headers);E2.delete(k2),b=new Request(b,{headers:E2})}b=await Z.rewriteRequest({...O,request:b,attempt:u})??b,G()}let v=new Headers(b.headers);v.delete(k2),O1(v,S.headers),A(S.scope,v.entries());let Z2=new Request(b,{headers:v});U.set(Z2,S),$.request=Z2})})},G2)),V2.push(await X.session.hook("http.response",async($)=>{let G=U.get($.request);if(!G){if(F)return;if(!r)r=!0,j("opencode2 auth dropped an http.response whose request it did not produce",{sessionID:$.sessionID,kind:$.kind});return}let _=$.response;if(Z.answeredBy&&G.attempt){let v=G.attempt,Z2=await s(G,async()=>Z.answeredBy?.({request:$.request,response:_,attempt:v}));if(Z2)T2(G,Z2)}let S=j2(G),O=G.attempt;if(!S||!O)return;G.status=_.status;let u=Z.quotaFromHeaders?.(_.headers,_.status,O);if(u!==void 0)Q2(G,"http",u,_.status);if(!_.ok&&Z.limitFromResponse){let v=await Z.limitFromResponse({status:_.status,headers:_.headers,body:()=>_.clone().text(),attempt:O});if(v)Y2(G,v,"http")}if(!_.ok||!_.body)g(G);let b=_;if(_.body&&(Z.inspectEvent||Z.onAttemptEnd)){let v=_.body;if(Z.inspectEvent)v=v.pipeThrough($$((Z2)=>B2(G,"http",Z2.data,Z2.event),(Z2)=>j("opencode2 auth event inspection threw",{error:B(Z2)})));b=new Response(C1(v,(Z2)=>g(G,Z2)),{status:_.status,statusText:_.statusText,headers:_.headers})}if(Z.rewriteResponse)b=await Z.rewriteResponse({...S,request:$.request,response:b,attempt:O})??b;if(b!==_)$.response=b},G2)),V2.push(await X.session.hook("experimental.ws.handshake",($)=>{if(F){let G=S2($.sessionID,$.kind);if(P.delete(G),!D(N2($),new Headers($.headers)))return}return M(N2($),async(G)=>{let _;for(let b of Object.keys($.headers)){if(b.toLowerCase()!==k2)continue;_??=$.headers[b],delete $.headers[b]}let S=F?await w(N2($),"experimental.ws.handshake",G,"ws"):await y(N2($),"experimental.ws.handshake","ws",_,G);G();let O=j2(S),u=S.attempt;if(!O||!u)throw Q(S.scope);await s(S,async()=>{if(!F?.refuseMisplaced)m2($.headers,S.headers);let b=Z.rewriteHandshakeURL?.({...O,url:$.url,attempt:u});if(b!==void 0)$.url=b;if(F?.refuseMisplaced)m2($.headers,S.headers);if(A(S.scope,Object.entries($.headers)),F)P.add(S.key)})})},G2));let o=Z.rewriteWebSocketFrame?.bind(Z);if(o)V2.push(await X.session.hook("experimental.ws.send",async($)=>{let G=N2($);if(F&&!P.has(S2(G.sessionID,G.kind)))return;let _=d(G.sessionID,G.kind),S=await o({...G,attempt:_?.attempt,frame:$.frame});if(S!==void 0)$.frame=S},G2));V2.push(await X.session.hook("experimental.ws.receive",($)=>{if(F&&!P.has(S2($.sessionID,$.kind)))return;let G=d($.sessionID,$.kind);if(!G)return;try{B2(G,"ws",$.frame)}catch(_){j("opencode2 auth frame inspection threw",{error:B(_)})}},G2)),V2.push(await X.session.hook("retry",async($)=>{if(F&&x.get($.sessionID)!==!0)return;let G=$.decision,_=()=>p("retry",{sessionID:$.sessionID,attempt:$.attempt,reason:"host-decides",hostDecision:G,decision:G});if(f($.sessionID)){await _();return}let S=e($.sessionID);if(!S)return;if(S==="ambiguous"){await p("retry",{sessionID:$.sessionID,attempt:$.attempt,reason:"host-decides",hostDecision:G,decision:G});return}let O=S;await M(O.scope,async(u)=>{let b=u;if(f($.sessionID)){await _();return}O.judged=!0;let v=O.attempt;if(v&&!O.outputStarted){if(!O.limit){let _2=Z.limitFromError?.($.error,v);if(_2)Y2(O,_2,"error")}if(O.ended)await O.ended;if(O.limit)await O.limit.delivered}b();let{decision:Z2,reason:E2}=await k(O.scope.sessionID,async()=>{if(b(),f($.sessionID))return{decision:G,reason:"host-decides"};let _2=H.get(O.key);if(H.delete(O.key),_2?.next)await h(_2.next);if(b(),f($.sessionID))return{decision:G,reason:"host-decides"};let W2=G,L2,F2,U2;if(O.accountId===void 0||!v)W2={retry:!1},L2="no-account";else if(O.outputStarted)W2={retry:!1},L2="output-started";else if(O.limit){let y2={accountId:O.accountId,limit:O.limit.signal},C2,s2={...O.scope,phase:"retry",previousAccountId:O.accountId,rerouteFrom:y2};try{C2=await Z.chooseAccount(s2)}catch(a2){j("opencode2 auth chooseAccount threw while the retry hook looked for another account; the host decides the retry",{sessionID:O.scope.sessionID,error:B(a2)})}let R2=typeof C2==="object"?C2.hold:void 0,h2=typeof C2==="string"?C2:R2?O.accountId:void 0;if(h2!==void 0)U2={accountId:h2,input:s2};try{b()}catch(a2){if(U2)await h(U2);throw a2}if(f($.sessionID)){if(U2)await h(U2);return{decision:G,reason:"host-decides"}}if(R2&&Number.isFinite(R2.delayMs)&&R2.delayMs>=0)W2={retry:!0,delay:Math.min(R2.delayMs,_$)},L2="hold";else if(!R2&&h2!==void 0&&h2!==O.accountId)O.rerouted=!0,F2=y2,W2={retry:!0,delay:0},L2="reroute";else{if(R2&&U2)await h(U2),U2=void 0;L2="host-decides-last-account"}}else L2="host-decides";if($.decision=W2,W2.retry&&O.accountId!==void 0&&Y.has(O.id))H.set(O.key,{attemptId:O.id,sessionID:O.scope.sessionID,order:++V,accountId:O.accountId,...F2===void 0?{}:{rerouteFrom:F2},...U2===void 0?{}:{next:U2}});else if(U2)await h(U2);return{decision:W2,reason:L2}});b(),await p("retry",{sessionID:$.sessionID,...O.accountId===void 0?{}:{accountId:O.accountId},kind:O.scope.kind,attempt:$.attempt,reason:E2,hostDecision:G,decision:Z2,...v===void 0?{}:{handle:v}})})},G2));let M2=($)=>{if(N($),x.delete($),!q.get($)?.foreignSeen)q.delete($);for(let G of P)if(JSON.parse(G)[0]===$)P.delete(G);for(let G of[...Y.values()]){if(G.scope.sessionID!==$)continue;m(G,"its session was forgotten"),Y.delete(G.id)}for(let[G,_]of H)if(_.sessionID===$)i(G)},K2=new AbortController,g2=X.event;if(g2)(async()=>{try{for await(let $ of g2.subscribe({signal:K2.signal}))if($.type==="session.deleted")M2($.data.sessionID);else if($.type==="session.status"&&$.data.status.type==="idle"){let G=$.data.sessionID,_=++V;k(G,async()=>{for(let[S,O]of H)if(O.sessionID===G&&O.order<_){if(H.delete(S),O.next)await h(O.next)}})}}catch($){if(!K2.signal.aborted)j("opencode2 auth stopped listening for session deletion",{error:B($)})}})();return{on($,G){let _=a.get($);if(!_)_=new Set,a.set($,_);let S=G;return _.add(S),()=>{_.delete(S)}},accountFor($,G){return z2(S2($,G))?.accountId},forgetSession:M2,get size(){return Y.size},async dispose(){if(n)return;n=!0;for(let $ of J.keys())N($);K2.abort();for(let $ of Y.values())m($,"the installation was disposed");Y.clear();for(let $ of H.keys())i($);P.clear(),x.clear(),q.clear(),a.clear(),await Promise.all(E.values()),await Promise.all(V2.map(async($)=>{try{await $.dispose()}catch(G){j("opencode2 auth hook did not dispose cleanly",{error:B(G)})}}))}}}import{CacheKeepManager as $X,CacheKeepSessionRegistry as XX,getDefaultCacheKeepRegistryDirectory as ZX,isCacheKeepActiveNow as g$,isCacheKeepHybridActive as G$,isCacheKeepSubagentsEnabled as V$,logger as h$}from"@cortexkit/anthropic-auth-core";import{createHash as E1}from"node:crypto";import{AnthropicOAuthOriginError as R1,applyCustomHeaders as S1,assertNotCustodyTombstone as q1,classifyGzipRejection as A1,createProviderErrorRedactor as N$,createProviderErrorResponseScope as L$,decideRequestGzip as x1,dumpDirectRequest as F$,dumpRelayRequest as T$,dumpResponseArtifact as l2,encodeGzipRequestBody as k1,getAccountStoragePath as b1,getRequestGzipLatch as w1,getRequestGzipLatchPath as D1,isDumpEnabled as y1,mergeAnthropicBetas as I1,remapModelId as P$,remapRequestBodyModel as f1,setDumpEnabled as C$,stateRefusalCause as v1,stripEmptyTrailingAssistantMessages as g1,TrailingAssistantHistoryError as h1}from"@cortexkit/anthropic-auth-core";var b2="anthropic",y$="x-common-auth-attempt",m1=["x-session-affinity","x-opencode-session","x-parent-session-id",R$,d2,A2,y$],u2=new Set(["authorization","x-api-key"]),l1="physical send before a response",u1="Claude pool login is selected but no native account is usable. Complete offline migration or repair the pool and its quota policy before retrying.",d1=512,p1=5000,c1=500,O$=new Set(["invalid_request_error","authentication_error","billing_error","permission_error","not_found_error","request_too_large","rate_limit_error","timeout_error","api_error","overloaded_error"]);class I$ extends Error{sessionID;requestKind;kind="no-account";providerID=b2;constructor(X,Z){super(u1);this.sessionID=X;this.requestKind=Z;this.name="NativeAnthropicNoAccountError"}}class Y$ extends Error{sessionID;requestKind;kind="session-forgotten";providerID=b2;constructor(X,Z){super("request refused: its session was closed while it was being prepared");this.sessionID=X;this.requestKind=Z;this.name="NativeAnthropicRevokedError"}}class w2 extends Error{kind="unsupported-transport";providerID=b2;constructor(){super("request refused: WebSocket relay is not supported on OpenCode 2; select HTTP relay or direct transport");this.name="NativeAnthropicTransportRefusal"}}class f$ extends Error{kind="local-invalid-request";status=400;check;constructor(X){super(X.message,{cause:X});this.name="NativeAnthropicLocalRefusal",this.check=X.check}}class v$ extends Error{kind="state-relocated";providerID=b2;constructor(X){super(X.message,{cause:X});this.name="NativeAnthropicStateRefusal"}}function i1(X){let Z=v1(X);return Z?new v$(Z):void 0}var q2=(X)=>typeof X==="object"&&X!==null&&!Array.isArray(X);function I2(X){try{return JSON.parse(X)}catch{return}}function Z$(X){let Z={};for(let[z,W]of Object.entries(X??{}))Z[z.toLowerCase()]=W;return Z}function E$(X){let Z={};for(let z of m1){let W=X.get(z);if(W!==null&&z!==y$)Z[z]=W;X.delete(z)}return Z}function o1(X){try{return new URL(X).pathname.endsWith("/messages")}catch{return!1}}function r1(X){return X instanceof h1||X instanceof S$||X instanceof R1?new f$(X):void 0}function n1(X,Z){let z=[];if(X.oauth)z.push(X.oauth.accessToken);for(let[W,F]of Object.entries(X.apiHeaders??{})){if(F===null||!u2.has(W))continue;z.push(F.replace(/^Bearer\s+/i,""))}for(let W of u2){let F=Z.get(W);if(F!==null)z.push(F.replace(/^Bearer\s+/i,""))}if(X.dispatch?.kind==="http-relay")z.push(X.dispatch.token);return[...new Set(z.filter(Boolean))]}var s1=new Set(["oauth-2025-04-20","claude-code-20250219",x$]);function a1(X){let Z=X.split(",").map((z)=>z.trim()).filter((z)=>z&&!s1.has(z));return I1(null,Z)}function t1(X){let Z=I2(X);if(!q2(Z))return X;let z=g1(Z.messages),W=Object.hasOwn(Z,"fallbacks"),{droppedMarkers:F}=k$(Z,!1),L=W&&!Object.hasOwn(Z,"fallbacks"),C=f1(Z);return z>0||F>0||L||C?JSON.stringify(Z):X}async function e1(X,Z){if(!(X instanceof Promise))return"settled";let z;try{return await Promise.race([X.then(()=>"settled"),new Promise((W)=>{z=setTimeout(()=>W("timed-out"),Z)})])}finally{if(z!==void 0)clearTimeout(z)}}function D2(X){let{source:Z,log:z}=X,W=Math.max(1,X.maxPendingSends??d1),F=X.attemptEndTimeoutMs??p1,L=X.requestGzipLatch??w1(D1(b1())),C=new WeakSet,T=new Map,K=new WeakMap,Y=new WeakMap,U=new WeakMap,H=new Map,V=new WeakMap,P=N$([]);P.dispose();let x=(Q)=>(Q&&H.get(Q)?.redactor)??P,q=(Q)=>{let N=H.get(Q);if(!N)return;H.delete(Q),N.redactor.dispose(),N.scope.dispose()},f=(Q,N,M,A)=>{let R=n1(N,A),w=L$(R,M);c.set(Q,M),H.set(Q,{sessionID:N.sessionID,redactor:N$(R),scope:w}),w.settled.then(()=>q(Q));while(H.size>W){let y=H.keys().next().value;if(y===void 0)break;q(y)}},c=new WeakMap,D=(Q,N)=>{let M=Q?c.get(Q):void 0;if(!M||!N.ok)return P.redactResponse(N);let A=L$([],M),R=A.redactResponse(N);return A.dispose(),R},r=(Q,N)=>{let M=Q?H.get(Q)?.scope:void 0;if(!M)return D(Q,N);try{return M.redactResponse(N)}catch{return D(Q,N)}},$2=!1,a=new Map,H2=new WeakMap,n=new WeakMap,J=new WeakMap,j=(Q)=>Q.agent==="cachekeep"||Q.agent==="prime",B=async()=>{try{if(Z.isDumpEnabled)return await Z.isDumpEnabled()}catch{return!1}try{return y1()}catch{return!1}},E=(Q)=>{a.delete(Q)},k=new WeakMap,I=(Q,N)=>{if(Q&&!N.ok)k.set(N.headers,Q);return N},h=(Q,N)=>{if(N.dispatch!=="http-relay")return!0;let M=/^req_[A-Za-z0-9_-]+$/.test(Q.get("request-id")??"");return Y.set(N,M),M},i=(Q)=>new I$(Q.sessionID,Q.kind),p=new Map,J2=async(Q,N)=>{if($2)throw new Y$(Q.sessionID,Q.kind);let M={revoked:!1},A=p.get(Q.sessionID);if(!A)A=new Set,p.set(Q.sessionID,A);A.add(M);let R=()=>{if($2||M.revoked)throw new Y$(Q.sessionID,Q.kind)};try{let w=await N(R);return R(),w}finally{let w=p.get(Q.sessionID);if(w?.delete(M)&&w.size===0)p.delete(Q.sessionID)}},g=(Q,N)=>{T.set(Q,N);while(T.size>W){let M=T.keys().next().value;if(M===void 0)break;T.delete(M),z?.warn("dropped the oldest pending Anthropic send to stay bounded",{bound:W})}},m=(Q,N)=>({providerID:Q.providerID,modelID:Q.modelID,sessionID:Q.sessionID,agent:Q.agent,kind:Q.kind,accountId:Q.accountId,attemptId:Q.attemptId,transport:Q.transport,route:N.route,provenance:N.provenance,dispatch:N.dispatch}),l=(Q)=>J2(Q,async(N)=>{let{accountId:M,...A}=Q,R;try{R=await Z.authorizeAccount(A,M)}catch(w){let y=i1(w);if(y)throw z?.warn("refused an Anthropic request: its account state was moved or could not be recorded",{error:y.cause instanceof Error?y.cause.name:""}),y;throw w}return N(),z2(A,R)}),z2=(Q,N)=>{if(!N)throw i(Q);if(N.dispatch?.kind==="websocket-relay")throw new w2;let M=N.dispatch?.kind==="http-relay"?"http-relay":"direct",A=N.dispatch?.kind==="http-relay"?{authorization:null,"x-api-key":null,"x-relay-token":N.dispatch.token}:void 0;if(N.route==="oauth"){if(!N.accessToken)throw i(Q);q1(N.accessToken,b2);let y=Object.freeze({route:"oauth",provenance:N.provenance,dispatch:M});g(y,{sessionID:Q.sessionID,oauth:{accessToken:N.accessToken,...N.identity?{identity:N.identity}:{}},dispatch:N.dispatch,oauthHeaders:N.headers});let s=Z$(N.headers);for(let d of u2)delete s[d];return delete s["anthropic-beta"],{headers:A??{...s,"x-api-key":null,authorization:`Bearer ${N.accessToken}`},attempt:y}}let R={authorization:null,"x-api-key":null,...Z$(N.headers)};if(!R.authorization&&!R["x-api-key"])throw i(Q);let w=Object.freeze({route:"api",provenance:N.provenance,dispatch:M});return g(w,{sessionID:Q.sessionID,...N.baseURL?{baseURL:N.baseURL}:{},dispatch:N.dispatch,apiHeaders:R}),{headers:A??R,attempt:w}},P2=(Q)=>J2(Q,(N)=>t(Q,N)),t=async(Q,N)=>{let{request:M,attempt:A}=Q,R=A.data,w=R?T.get(R):void 0;if(R)T.delete(R);if(!R||!w||R.route==="oauth"&&!w.oauth)throw i(Q);let y=new Headers(M.headers);S1(y);let s=E$(y),d=M.body===null?void 0:await M.text();N();let Y2=d!==void 0&&o1(M.url),Q2=w$(M.url,w.baseURL!==void 0?{baseURL:w.baseURL}:{}).url?.toString()??M.url;try{if(R.route==="oauth"&&w.oauth){q$(Q2);let{accessToken:X2,identity:e}=w.oauth;for(let[V2,o]of Object.entries(Z$(w.oauthHeaders))){if(u2.has(V2))continue;if(o===null)y.delete(V2);else y.set(V2,o)}let G2=null;if(d!==void 0&&Y2){let V2={...m(A,R),modelID:(()=>{let K2=I2(d);return P$(q2(K2)&&typeof K2.model==="string"?K2.model:Q.modelID)})(),route:"oauth",correlation:s},o=await Z.requestOptions?.(V2)??{};N(),d=await D$(d,{...o,...e?{identity:e}:{},sessionId:Q.sessionID,onToolNameMap:(K2)=>U.set(R,K2)});let M2=I2(d);G2=q2(M2)?M2:null}b$(y,X2,{body:G2,...e?{identity:e}:{},requestClass:A$(A.agent)?"auxiliary":"main"})}else{if(d!==void 0&&Y2)d=t1(d);y.delete("authorization"),y.delete("x-api-key");for(let[e,G2]of Object.entries(w.apiHeaders??{}))if(G2===null)y.delete(e);else y.set(e,G2);if(d!==void 0&&Y2&&!y.has("content-type"))y.set("content-type","application/json");let X2=y.get("anthropic-beta");if(X2!==null){let e=a1(X2);if(e)y.set("anthropic-beta",e);else y.delete("anthropic-beta")}}}catch(X2){let e=r1(X2);if(!e)throw X2;throw K.set(R,e.check),z?.warn("refused an Anthropic request locally; nothing was sent",{check:e.check}),e}let B2=d!==void 0?I2(d):void 0;if(await Z.admitRequest?.({...m(A,R),modelID:P$(q2(B2)&&typeof B2.model==="string"?B2.model:Q.modelID)}),E$(y),d!==void 0)y.delete("content-length");if(N(),f(R,w,q2(B2)&&B2.stream===!0?"event-stream":"http",y),R.route==="oauth"&&Y2&&d!==void 0)await Z.onRequestPrepared?.({...m(A,R),url:Q2,bodyText:d}),N();if(w.dispatch?.kind==="http-relay"){let X2=d??"";y.delete("x-relay-token");let e={protocol:1,type:"request",affinity:Q.sessionID,upstream:{url:Q2,method:M.method,headers:Object.fromEntries(y)},mode:"full_sync",revision:1,body:X2,next_hash:`sha256:${E1("sha256").update(X2).digest("hex")}`};if(Y2&&d!==void 0&&!j(A)){let G2=s[A2]==="1"?"start":void 0,V2=JSON.stringify(e);a.set(R,{affinity:Q.sessionID,route:Q.accountId,bodyText:X2,url:Q2,method:M.method,headers:new Headers(y),dispatch:"http-relay",relayUrl:w.dispatch.url,envelope:e,relayBytes:V2.length,...G2?{tag:G2}:{}})}else E(R);return new Request(w.dispatch.url,{method:"POST",headers:{"content-type":"application/json","x-relay-token":w.dispatch.token},redirect:"error",signal:M.signal,body:JSON.stringify(e)})}let T2=d;if(R.route==="oauth"&&Y2&&d!==void 0){let X2=await x1({url:Q2,body:d,latch:L});if(N(),X2.gzip)T2=await k1(d),y.set("content-encoding","gzip"),C.add(R),N()}if(Y2&&d!==void 0&&!j(A)){let X2=s[A2]==="1"?"start":void 0;a.set(R,{affinity:Q.sessionID,route:Q.accountId,bodyText:d,url:Q2,method:M.method,headers:new Headers(y),dispatch:"direct",...X2?{tag:X2}:{}})}else E(R);return new Request(Q2,{method:M.method,headers:y,redirect:R.route==="oauth"?"error":M.redirect,signal:M.signal,...T2!==void 0?{body:T2}:{}})};return{adapter:{providerID:b2,chooseAccount:(Q)=>J2(Q,async()=>{let N=await Z.chooseAccount(Q);if(typeof N==="object"&&Q.phase==="retry")return N;if(typeof N!=="string"||!N)throw i(Q);return N}),dropChoice:(Q)=>Z.dropChoice?.(Q),accountHeaders:l,rewriteRequest:P2,rewriteHandshakeURL(){throw new w2},async rewriteResponse({response:Q,attempt:N}){let M=N.data;if(M&&!h(Q.headers,M)){if(M)E(M);if(Q.status===401)return q(M),Q.body?.cancel().catch(()=>{}),Response.json({type:"error",error:{type:"api_error",message:"Relay authentication failed before Anthropic received the request"}},{status:502});return r(M,Q)}if(M&&C.has(M))C.delete(M),A1(Q).then((o)=>{if(!o)return;L.latchProcess(),z?.warn("gzipped request body rejected; later requests go uncompressed",{kind:o,status:Q.status})},()=>{});let A=null,R=M?a.get(M):void 0;if(M&&R){let o=!1;try{o=await B()}catch{o=!1}if(!o)E(M);else{try{C$(!0)}catch{}try{if(R.dispatch==="http-relay")A=await T$({affinity:R.affinity,transport:"http",protocol:1,mode:"full_sync",status:Q.status,bodyText:R.bodyText,payload:R.envelope??{},relayBytes:R.relayBytes??0,...R.tag?{tag:R.tag}:{}});else A=await F$({affinity:R.affinity,route:R.route,status:Q.status,bodyText:R.bodyText,url:R.url,method:R.method,headers:R.headers,...R.tag?{tag:R.tag}:{}})}catch{A=null}if(E(M),A){H2.set(M,A);try{await l2(A,{status:Q.status,message:null,complete:!1})}catch{}J.set(M,Promise.resolve())}}}let w=r(M,Q);if(M?.route!=="oauth"||!w.body)return I(M,w);let y={...m(N,M),status:Q.status},s=Z.responseOptions?.(y)??{},d=(Q.headers.get("content-type")??"").includes("application/json"),Y2={...s,toolNameMap:M?U.get(M):void 0,onToolNameRefusal:()=>{if(!M)return;K.set(M,"response_tool_names"),q(M)},laneStartOAuthServed:!0,...d?{responseMode:"json"}:{}};if(!M||!A)return I(M,J$(w,Y2));let Q2=A,B2=Q.status,T2=(o)=>{let K2=(J.get(M)??Promise.resolve()).then(()=>o().then(()=>{return})).catch(()=>{return});J.set(M,K2)},X2=s.onMessageStart,e=s.onMessageDelta,G2=s.onMessageResponse,V2=s.onStreamEnd;return I(M,J$(w,{...Y2,onMessageStart:(o)=>{try{X2?.(o)}catch{}try{n.set(M,{...o}),T2(()=>l2(Q2,{status:B2,message:o,complete:!1}))}catch{}},onMessageDelta:(o)=>{try{e?.(o)}catch{}try{let M2=n.get(M)??{},K2=M2.usage&&typeof M2.usage==="object"&&!Array.isArray(M2.usage)?M2.usage:{},g2={...M2,...o.usage?{usage:{...K2,...o.usage}}:{},...o.stopReason?{stop_reason:o.stopReason}:{}};T2(()=>l2(Q2,{status:B2,message:g2,complete:!0}))}catch{}},onMessageResponse:(o)=>{try{G2?.(o)}catch{}try{T2(()=>l2(Q2,{status:B2,message:o,complete:!0}))}catch{}},onStreamEnd:async()=>{try{await V2?.()}catch{}try{await(J.get(M)??Promise.resolve())}catch{}}}))},quotaFromHeaders(Q,N,M){let A=M.data;if(!A||!h(Q,A))return;return Z.quotaFromHeaders?.(Q,{...m(M,A),status:N})},async limitFromResponse({status:Q,headers:N,body:M,attempt:A}){let R=A.data;if(!R||K.get(R)==="response_tool_names")return;if(!h(N,R))return Z.limitFromRelayFailure?.({...m(A,R),status:Q});if(V.set(R,`provider responded with HTTP ${Q}`),!Z.limitFromResponse)return;let w=k.get(N)===R,y=x(R);return Z.limitFromResponse({...m(A,R),status:Q,headers:N,body:async()=>w?await M():y.redactText(await M())})},inspectEvent({data:Q,event:N,attempt:M}){if(M.data&&K.get(M.data)==="response_tool_names")return;let A=I2(Q);if(!q2(A))return;let R=typeof A.type==="string"?A.type:N;if(R==="content_block_start"||R==="content_block_delta")return{outputStarted:!0};if(R==="message_stop")return{done:!0};if(R!=="error")return;let w=M.data,y=x(w),s=q2(A.error)?A.error:{},d=typeof s.type!=="string"?void 0:O$.has(s.type)?s.type:y.redactText(s.type),Y2=typeof s.message==="string"?y.redactText(s.message):void 0;if(w?.dispatch==="http-relay"&&Y.get(w)===!1)return;let Q2=w?Z.limitFromStreamError?.({...m(M,w),errorType:d,message:Y2}):void 0,B2={error:[d??"error",Y2].filter(Boolean).join(": ").slice(0,c1),...Q2?{limit:Q2}:{}};if(w&&B2.error)V.set(w,B2.error);return B2},limitFromError(Q,N){let M=N.data;if(!M||K.has(M))return;let A={type:O$.has(Q.type)?Q.type:"provider_error",message:V.get(M)??"provider request failed",...Q.status!==void 0?{status:Q.status}:{}};if(q(M),M.dispatch==="http-relay"&&Y.get(M)===!1)return;return Z.limitFromHostError?.(A,m(N,M))},async onAttemptEnd(Q,N){let M=Q.data;if(!M)return;T.delete(M);let A=a.get(M);if(A){E(M);try{if(await B()){try{C$(!0)}catch{}try{if(A.dispatch==="http-relay"){if(N.status!==void 0)await T$({affinity:A.affinity,transport:"http",protocol:1,mode:"full_sync",status:N.status,bodyText:A.bodyText,payload:A.envelope??{},relayBytes:A.relayBytes??0,...A.tag?{tag:A.tag}:{}})}else await F$({affinity:A.affinity,route:A.route,status:N.status,error:N.status===void 0?l1:void 0,bodyText:A.bodyText,url:A.url,method:A.method,headers:A.headers,...A.tag?{tag:A.tag}:{}})}catch{}}}catch{}}let R=N.error?.reason;if(R==="cancelled"||R==="abandoned"||R===void 0&&(N.status===void 0||N.status<400))q(M);let w=K.get(M),{status:y,...s}=N,d=Z.onAttemptEnd?.(m(Q,M),{...s,...y!==void 0&&(M.dispatch!=="http-relay"||Y.get(M)===!0)?{status:y}:{},...w!==void 0?{localRefusal:{check:w}}:{}});if(await e1(d,F)==="timed-out")z?.warn("the account source did not finish recording a send",{timeoutMs:F})}},dispose(){$2=!0;for(let[Q,N]of p){for(let M of N)M.revoked=!0;Z.forgetSession?.(Q)}p.clear(),T.clear(),a.clear();for(let Q of[...H.keys()])q(Q)},forgetSession(Q){for(let N of p.get(Q)??[])N.revoked=!0;p.delete(Q);for(let[N,M]of T)if(M.sessionID===Q)T.delete(N);for(let[N,M]of[...H])if(M.sessionID===Q)q(N);for(let[N,M]of[...a])if(M.affinity===Q)a.delete(N);Z.forgetSession?.(Q)},get pendingSendCount(){return T.size},get heldCredentialCount(){let Q=0;for(let N of T.values())if(N.oauth)Q++;return Q},get heldRedactorCount(){return H.size},get operationsInProgress(){let Q=0;for(let N of p.values())Q+=N.size;return Q}}}function f2(X){return JSON.stringify([X.source,X.accountIdentity,X.credentialId,X.binding?.storageId,X.binding?.rowId,X.binding?.credentialEpoch])}var m$=Symbol.for("cortexkit.anthropic-auth.opencode2.cachekeep.v1");function l$(){let X=globalThis;return X[m$]??=new Map,X[m$]}function JX(X,Z){let z=new Map,W=new Map,F=new XX({directory:Z.registryDirectory||process.env.OPENCODE_ANTHROPIC_AUTH_CACHEKEEP_REGISTRY_DIR||ZX("opencode"),now:Z.now}),L=()=>{let V;for(let P of W.values())V=P;return V},C=Z.setIntervalImpl??globalThis.setInterval,T=new $X({loadStorage:async()=>{let V=L();return V?V.loadStorage():null},now:Z.now,setIntervalImpl:(V,P)=>C(()=>{let x=T.tick();return H.ticking=x.catch(()=>{h$.warn("cachekeep","tick failed")}),H.ticking},P),clearIntervalImpl:Z.clearIntervalImpl,onTrackedSessionsChanged:(V)=>F.publish(W.size===0?[]:V),prepareHeaders(V,P,x){let q=L();if(!q)return;return z.set(x.id,{target:P,attempt:x,lease:q}),new Headers({"x-native-cachekeep-attempt":String(x.id)})},fetchImpl:async(V,P)=>{let x=new Request(V,P),q=Number(x.headers.get("x-native-cachekeep-attempt")),f=z.get(q);if(z.delete(q),!f||f.lease.stopped)throw Error("CacheKeep attempt is unavailable");let c=f.lease.send(f.target,x,f.attempt.signal),D=c.then(()=>{},()=>{});return f.lease.inflight.add(D),D.then(()=>f.lease.inflight.delete(D)),c},onComplete:({attempt:V})=>{z.delete(V.id)}}),K,Y=()=>{if(K!==void 0)clearTimeout(K);K=void 0},U=()=>{if(Y(),W.size>0)return;let V=T.dropExpiredTargets();if(V===void 0){let x=l$();if(x.get(X)===H)x.delete(X);return}let P=Z.now?.()??Date.now();if(K=setTimeout(U,Math.max(0,V-P)),typeof K==="object"&&"unref"in K)K.unref()},H={manager:T,registry:F,prepared:z,leases:W,nextGeneration:0,retain(){T.stop(),z.clear(),U()},adopt(){if(Y(),T.dropExpiredTargets()===void 0)return;T.start(),F.publish(T.trackedSessions()).catch(()=>{h$.warn("cachekeep","failed to publish tracked sessions")})}};return H}function u$(X){let{runtime:Z,source:z}=X,W=new AbortController,F=l$(),L=F.get(X.storageId)??JX(X.storageId,X);F.set(X.storageId,L);let{manager:C,registry:T}=L,K=async(V,P,x)=>{let q=x?AbortSignal.any([W.signal,x]):W.signal;q.throwIfAborted();let f=JSON.parse(await P.text()),c={providerID:"anthropic",modelID:f.model,sessionID:`oc2-cachekeep:${V.id}`,agent:"cachekeep",kind:"generate"},D=D2({source:{...z,onRequestPrepared:void 0,responseOptions:void 0,async requestOptions(n){return{...await z.requestOptions?.(n),laneStart:!1,billingLineage:void 0,cacheDiagnosticsPreviousMessageId:void 0}},async authorizeAccount(n,J){let j=await Z.read();q.throwIfAborted();let B=j.accounts.find((k)=>k.id===J);if(B?.type!=="oauth"||f2(B)!==V.oauthAccountIdentity||V.isSubagent&&!V$(j.policyStorage)||!G$(j.policyStorage)||!g$(j.policyStorage,new Date(X.now?.()??Date.now())))return;let E=await z.authorizeAccount(n,J);if(E?.provenance.kind==="local"&&f2({...B,binding:E.provenance.subject.binding,accountIdentity:E.provenance.subject.binding.identity})!==V.oauthAccountIdentity)return;if(E?.provenance.kind==="vault"&&E.provenance.credentialId!==B.credentialId)return;return E},async admitRequest(n){await z.admitRequest?.(n);let J=await Z.read(),j=J.accounts.find((B)=>B.id===n.accountId);if(q.throwIfAborted(),!j||f2(j)!==V.oauthAccountIdentity||V.isSubagent&&!V$(J.policyStorage)||!G$(J.policyStorage)||!g$(J.policyStorage,new Date(X.now?.()??Date.now())))throw Error("CacheKeep policy changed before dispatch")}}}),r,$2,a=!1,H2=()=>D.forgetSession(c.sessionID);q.addEventListener("abort",H2,{once:!0});try{let n=(await Z.read()).accounts.find((I)=>f2(I)===V.oauthAccountIdentity)?.id;if(!n)throw Error("CacheKeep account is unavailable");let J=await D.adapter.accountHeaders({...c,accountId:n});if(!("headers"in J)||typeof J.headers!=="object"||J.headers===null||typeof J.attempt!=="object"||J.attempt===null||J.attempt.route!=="oauth")throw Error("CacheKeep authorization refused");r={...c,accountId:n,attemptId:crypto.randomUUID(),transport:"http",data:J.attempt};let j=await D.adapter.rewriteRequest?.({...c,accountId:n,attempt:r,request:new Request(V.url,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(f),signal:q})});if(!j)throw Error("CacheKeep rewrite refused");q.throwIfAborted();let B=await(X.fetch??fetch)(j),E=await D.adapter.rewriteResponse?.({...c,accountId:n,attempt:r,request:j,response:B});if(!E)throw Error("CacheKeep response rewrite refused");if($2=E.status,D.adapter.quotaFromHeaders?.(E.headers,E.status,r),!E.ok)await D.adapter.limitFromResponse?.({status:$2,headers:E.headers,body:()=>E.clone().text(),attempt:r});let k=await E.arrayBuffer();return a=!0,new Response(k,{status:$2,headers:E.headers})}catch{throw Error("Native CacheKeep was not completed")}finally{q.removeEventListener("abort",H2);try{if(r)await D.adapter.onAttemptEnd?.(r,{status:$2,outputStarted:!1,...a?{}:{error:{reason:"cancelled"}}})}finally{D.dispose(),z.forgetSession?.(c.sessionID)}}},Y={generation:L.nextGeneration++,stopped:!1,loadStorage:async()=>(await Z.read()).policyStorage,send:K,inflight:new Set},U=L.leases.size===0;if(L.leases.set(Y.generation,Y),U)L.adopt();let H;return{async track(V){if(Y.stopped||V.route!=="oauth"||V.agent==="cachekeep"||V.agent==="prime"||V.kind!=="primary")return;let P=await Z.read();if(Y.stopped||!G$(P.policyStorage))return;let x=!1;try{x=await X.isSubagent?.(V.sessionID)??!1}catch{return}if(Y.stopped||x&&!V$(P.policyStorage))return;let q=P.accounts.find((f)=>f.id===V.accountId);if(!q?.accountIdentity)return;if(V.provenance.kind==="local"&&JSON.stringify(q.binding)!==JSON.stringify(V.provenance.subject.binding))return;if(V.provenance.kind==="vault"&&q.credentialId!==V.provenance.credentialId)return;C.track({sessionId:V.sessionID,url:V.url,headers:new Headers,bodyText:V.bodyText,storage:P.policyStorage,cacheMode:"hybrid",oauthAccountId:V.accountId,oauthAccountIdentity:f2(q),isSubagent:x}),await T.publish(C.trackedSessions())},registry:T,dispose(){if(H)return H;Y.stopped=!0,W.abort();for(let[P,x]of L.prepared)if(x.lease===Y)L.prepared.delete(P);let V=L.leases.delete(Y.generation)&&L.leases.size===0;if(V)L.retain();return H=(async()=>{try{if(V)await L.ticking;await Promise.all(Y.inflight)}finally{if(V&&L.leases.size===0)await T.dispose()}})(),H}}}async function d$(X,Z,z){let W=D2(Z),F=[],L=async(V,P,x)=>{let q=await X.session.hook(V,P,x);return F.push(q),q},C=new AbortController,T;try{T=await X$({session:{hook:L},event:X.event},W.adapter,{logger:Z.log,gateOnPlaceholder:z})}catch(V){throw W.dispose(),await Promise.allSettled(F.map((P)=>P.dispose())),V}let K=(V)=>{W.forgetSession(V),T.forgetSession(V)},Y=X.event,U=Y?(async()=>{try{for await(let V of Y.subscribe({signal:C.signal}))if(V.type==="session.deleted")K(V.data.sessionID)}catch(V){if(!C.signal.aborted)Z.log?.warn("stopped listening for session deletion",{error:V instanceof Error?V.name:"unknown"})}})():Promise.resolve(),H;return{installation:T,forgetSession:K,dispose(){if(H)return H;return W.dispose(),C.abort(),H=(async()=>{await T.dispose(),await U})(),H}}}import{effectiveRelayTransport as p$,getQuotaCheckIntervalMs as YX,logger as GX,nativeAccountCanServe as VX,oauthProfileIsFresh as jX,quotaSnapshotCheckedAt as QX}from"@cortexkit/anthropic-auth-core";function c$(X,Z){let z=new AbortController,W,F=!1,L=async()=>{let K=await X.read();if(z.signal.throwIfAborted(),K.policyStorage.relay?.enabled===!0&&p$(K.policyStorage.relay.transport,K.policyStorage.relay.url)==="websocket")return;let Y=K,U=YX(Y.policyStorage);for(let H of Y.accounts){if(z.signal.aborted)return;if(!VX(H)||H.type!=="oauth")continue;if(Y.policyStorage.quota?.enabled!==!1&&Date.now()-QX(H.quota)>=U)await X.fetchQuota(H.id,Z,z.signal,void 0,"background").catch(()=>{});if(!jX(H.profile)&&!z.signal.aborted)await X.fetchProfile(H.id,Z,z.signal).catch(()=>{})}},C=()=>{if(F||W)return W;return W=L().catch(()=>{if(!z.signal.aborted)GX.debug("opencode2","native background readings did not complete")}).finally(()=>{W=void 0}),W},T=X.vault.watch({intervalMs:60000,onRefresh:C,shouldRefresh:async()=>{let K=await X.read();return K.policyStorage.relay?.enabled!==!0||p$(K.policyStorage.relay.transport,K.policyStorage.relay.url)==="http"}});return T.ready.catch(()=>{}),{async dispose(){F=!0,T.close(),z.abort(),await W}}}import{authorize as TX,buildCacheKeepStatusSummary as PX,buildClaudeQuotaSummary as CX,buildPrimeAccountStatuses as OX,buildPrimeStatusSummary as EX,CLAUSTRUM_OPENCODE_ENROLLMENT_NAME as RX,exchange as SX,formatNativeAccountState as qX,formatOAuthAccountTier as AX,getCacheKeepWindow as xX,getHostClaustrumEnrollmentPaths as kX,isCacheKeepAlways as bX,isCacheKeepHybridActive as wX,isCacheKeepPersistentlyEnabled as DX,nativeAccountCanServe as yX,resetClaustrumEnrollmentState as IX,setDumpEnabled as fX}from"@cortexkit/anthropic-auth-core";import{buildPrimeAccountStatuses as WX,effectiveRelayStatus as BX,formatNativeAccountState as UX,formatOAuthAccountTier as i$,getCacheKeepWindow as zX,getRoutingMode as KX,isCacheKeepAlways as MX,isCacheKeepHybridActive as HX,isPermanentRefreshError as _X,isPrimePersistentlyEnabled as NX,nativeAccountCanServe as n$,refreshBackoffActive as o$}from"@cortexkit/anthropic-auth-core";var r$=(X)=>n$(X)&&X.state!=="unsupported-access"?void 0:UX(X)||void 0,LX=(X)=>{if(X.source!=="vault")return"off";if(X.state==="needs_reauth")return"on-vault-reauth";return n$(X)?"on-vault-served":"on-cold"},FX=(X,Z)=>typeof X==="number"&&X>Z;function s$(X,Z){let{now:z}=Z,W=X.policyStorage,F=X.accounts.filter((U)=>U.type==="oauth"),L=F.find((U)=>U.id==="main"),C=L?r$(L):void 0,T=L?.lastQuotaRefreshError?.nextRetryAt,K=L?.lastRefreshError,Y=zX(W);return{main:{quota:L?.quota??null,enabled:L?.enabled,tierLabel:i$(L?.profile),quotaBackedOff:FX(T,z),quotaBackoffUntil:T,refreshBackedOff:o$(K,L?.accountIdentity,z,void 0),refreshBackoffUntil:K?.nextRetryAt,stateLine:C,quotaDated:Boolean(C)},fallbacks:F.filter((U)=>U.id!=="main"&&(U.enabled||U.source==="vault")).map((U)=>{let H=r$(U),V=LX(U);return{id:U.id,label:U.label,quota:U.quota??null,enabled:U.enabled,tierLabel:i$(U.profile),needsReauth:_X(U.lastRefreshError)&&o$(U.lastRefreshError,U.accountIdentity,z,void 0),...V==="on-vault-reauth"?{vaultReauth:!0}:{},...V==="on-vault-served"?{vaultServed:!0}:{},...V!=="off"?{custodyState:V}:{},stateLine:H,quotaDated:Boolean(H)}}),...Z.activeId!==void 0&&{activeId:Z.activeId},route:KX(W),relay:BX(W.relay),fastMode:W.claudeFast?.enabled===!0,cacheKeep:{enabled:HX(W),...MX(W)?{window:"always"}:Y&&{window:`${Y.startHour}-${Y.endHour}`},trackedSessions:Z.trackedSessions},prime:NX(W)?{enabled:!0,accounts:WX(W,{now:z})}:void 0,lastUpdated:z}}var j$=(X)=>X!==null&&typeof X==="object"&&!Array.isArray(X)?X:{},a$=`For first-time model access, connect Anthropic with "${i2}".
|
|
4
4
|
Run: opencode auth login anthropic --method ${c2}`,t$=(X)=>X.mode==="local"&&!X.accounts.some((Z)=>Z.id==="main"),vX=(X)=>{let Z=X.id==="main"?"main":"fallback",z=`${X.enabled?"enabled":"disabled"}, ${X.type}, ${X.source}${X.state?`, ${qX(X)}`:""}`;if(X.label)return`${X.label} [${Z}]: ${z}
|
package/dist/v2/tui.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{u as q}from"../index-
|
|
1
|
+
import{u as q}from"../index-a1k6z503.js";import"../index-12km9x91.js";import"../index-71temqvq.js";var N="Open this link in your browser and sign in. Then choose Finish OAuth sign-in in the Accounts menu and paste the code Claude shows you.";async function g(D,M={}){let B=D.client.rpc(q),Z=!0,V=!1,Y=new AbortController,$=()=>{let j=D.ui.router.current();return j.type==="session"?j.sessionID:void 0};function C(j){return new Promise((Q)=>{let z="",J=!1,G=D.keymap.mode.push("cortexkit-protected-entry"),X=(H,W=!0)=>{if(J)return;J=!0,D.renderer.keyInput.off("keypress",O),D.renderer.keyInput.off("paste",P),Y.signal.removeEventListener("abort",K),G();let F=H?z:void 0;if(z="",W)D.ui.dialog.clear();Q(F)},K=()=>X(!1),O=(H)=>{if(H.preventDefault(),H.stopPropagation(),H.name==="escape"||H.ctrl&&H.name==="c")return X(!1);if(H.name==="return"||H.name==="enter")return X(!0);if(H.name==="backspace"){z=Array.from(z).slice(0,-1).join("");return}if(!H.ctrl&&!H.meta&&!H.option&&Array.from(H.sequence).every((W)=>W.charCodeAt(0)>=32&&W.charCodeAt(0)!==127))z=(z+H.sequence).slice(0,4096)},P=(H)=>{H.preventDefault(),H.stopPropagation(),z=(z+Array.from(new TextDecoder().decode(H.bytes)).filter((W)=>W.charCodeAt(0)>=32&&W.charCodeAt(0)!==127).join("")).slice(0,4096)};if(D.renderer.keyInput.prependListener("keypress",O),D.renderer.keyInput.prependListener("paste",P),Y.signal.addEventListener("abort",K,{once:!0}),D.ui.dialog.alert({title:j,message:"Type or paste the value. Input is hidden. Enter accepts; Escape cancels."}).then(()=>X(!1,!1),()=>X(!1,!1)),Y.signal.aborted)K()})}async function E(j){let Q={};for(let z of j.knobs){if(!Z)return;if(z.kind==="choice"){let J=await D.ui.dialog.select({title:z.label,options:z.choices.map((G)=>({title:G.label,value:G.value})),current:z.value});if(J===void 0)return;Q[z.id]=J}else if(z.kind==="toggle"){let J=await D.ui.dialog.select({title:z.label,options:[{title:"On",value:!0},{title:"Off",value:!1}],current:z.value});if(J===void 0)return;Q[z.id]=J}else{let J=z.kind==="text"&&z.masked?await C(z.label):await D.ui.dialog.prompt({title:z.label,value:z.value===void 0?void 0:String(z.value),placeholder:z.kind==="text"?z.placeholder:void 0});if(J===void 0)return;Q[z.id]=J===""&&!z.required?null:z.kind==="number"?Number(J):J}}return Q}async function A(j){if(M.showSignInLink)try{await M.showSignInLink(D,j,Y.signal);return}catch{}await D.ui.dialog.alert({title:"Claude sign-in",message:`${N}
|
|
2
2
|
|
|
3
3
|
${j}
|
|
4
4
|
`})}async function T(j,Q){let z=`${Q.title} status`;if(M.showStatus)try{await M.showStatus(D,{title:z,lines:Q.lines,...Q.slot==="quota"&&{readQuota:(J)=>B.sidebar({sessionId:j},{signal:J,location:D.location})}},Y.signal);return}catch{}await D.ui.dialog.alert({title:z,message:Q.lines.join(`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cortexkit/opencode-anthropic-auth",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -77,18 +77,18 @@
|
|
|
77
77
|
},
|
|
78
78
|
"dependencies": {
|
|
79
79
|
"@clack/prompts": "^1.6.0",
|
|
80
|
-
"@cortexkit/anthropic-auth-core": "2.4.
|
|
80
|
+
"@cortexkit/anthropic-auth-core": "2.4.1",
|
|
81
81
|
"@cortexkit/claustrum-client": "0.12.0",
|
|
82
82
|
"@cortexkit/private-files": "0.2.1",
|
|
83
83
|
"@cortexkit/subc-client": "^0.22.0",
|
|
84
|
-
"@opentui/core": "0.
|
|
85
|
-
"@opentui/solid": "0.
|
|
84
|
+
"@opentui/core": "0.7.0",
|
|
85
|
+
"@opentui/solid": "0.7.0",
|
|
86
86
|
"jsonc-parser": "^3.3.1",
|
|
87
87
|
"solid-js": "1.9.12",
|
|
88
88
|
"xxhash-wasm": "^1.1.0"
|
|
89
89
|
},
|
|
90
90
|
"devDependencies": {
|
|
91
91
|
"@ai-sdk/anthropic": "4.0.82",
|
|
92
|
-
"@opencode/plugin": "2.0
|
|
92
|
+
"@opencode/plugin": "2.2.0"
|
|
93
93
|
}
|
|
94
94
|
}
|
package/src/sidebar-state.ts
CHANGED
|
@@ -1053,20 +1053,36 @@ export function fitQuotaRow(input: {
|
|
|
1053
1053
|
/**
|
|
1054
1054
|
* The pacing subline for a window that is off pace: `deficit 12% · out in
|
|
1055
1055
|
* 1d23h` for a deficit that runs out before the reset, otherwise the delta
|
|
1056
|
-
* and `lasts to reset` (`reserve 4% · lasts to reset`).
|
|
1057
|
-
*
|
|
1058
|
-
*
|
|
1056
|
+
* and `lasts to reset` (`reserve 4% · lasts to reset`). A window already at
|
|
1057
|
+
* 0% left is used up until its reset (`used up · resets in 2h10m`, with no
|
|
1058
|
+
* deficit percentage and no `out in` clause). A runout under a minute away
|
|
1059
|
+
* reads `out in <1m`, never `out in now`. When the line is wider than `width`
|
|
1060
|
+
* cells it is cut to fit and ends in `…` rather than wrapping. Null when
|
|
1061
|
+
* there is no pacing or the window is on pace.
|
|
1059
1062
|
*/
|
|
1060
1063
|
export function fitPaceLine(
|
|
1061
1064
|
pacing: QuotaPacing | null,
|
|
1062
1065
|
width: number | undefined,
|
|
1063
1066
|
runsOutIn: string | undefined,
|
|
1067
|
+
resetIn?: string | undefined,
|
|
1068
|
+
remainingPercent?: number | undefined,
|
|
1064
1069
|
): string | null {
|
|
1065
1070
|
if (!pacing || pacing.state === 'on-pace') return null
|
|
1071
|
+
// An exhausted window reports its deficit as a large percentage with a
|
|
1072
|
+
// runout of `now`, which reads as broken wording. The percentage no longer
|
|
1073
|
+
// means anything once nothing is left, so the line names the state instead.
|
|
1074
|
+
const exhausted = remainingPercent !== undefined && remainingPercent <= 0
|
|
1075
|
+
// A projected runout under a minute away is not `now` while quota remains.
|
|
1076
|
+
const normalizedRunsOutIn =
|
|
1077
|
+
runsOutIn === 'now' || runsOutIn === '0m' ? '<1m' : runsOutIn
|
|
1066
1078
|
const head = `${pacing.state} ${Math.round(Math.abs(pacing.deltaPercent))}%`
|
|
1067
|
-
const line =
|
|
1068
|
-
?
|
|
1069
|
-
|
|
1079
|
+
const line = exhausted
|
|
1080
|
+
? resetIn
|
|
1081
|
+
? `used up \u00b7 resets in ${resetIn}`
|
|
1082
|
+
: 'used up'
|
|
1083
|
+
: normalizedRunsOutIn
|
|
1084
|
+
? `${head} \u00b7 out in ${normalizedRunsOutIn}`
|
|
1085
|
+
: `${head} \u00b7 lasts to reset`
|
|
1070
1086
|
if (width === undefined || Bun.stringWidth(line) <= width) return line
|
|
1071
1087
|
if (width <= 0) return ''
|
|
1072
1088
|
let cut = ''
|
|
@@ -172,7 +172,9 @@ function quotaBarSegments(
|
|
|
172
172
|
function formatResetIn(resetsAt: string | undefined, now: number): string {
|
|
173
173
|
if (!resetsAt) return ''
|
|
174
174
|
const ms = new Date(resetsAt).getTime() - now
|
|
175
|
-
|
|
175
|
+
// A pacing runout under a minute away is not `now` while quota remains;
|
|
176
|
+
// the exhausted window never reaches this formatter with an `out in` line.
|
|
177
|
+
if (ms < 60_000) return '<1m'
|
|
176
178
|
const mins = Math.floor(ms / 60_000)
|
|
177
179
|
if (mins < 60) return `${mins}m`
|
|
178
180
|
const hrs = Math.floor(mins / 60)
|
|
@@ -318,7 +320,8 @@ function Cell(props: { fg: SidebarColor; text: string }) {
|
|
|
318
320
|
// instead of letting it wrap. When pacing data is present, the bar gains a
|
|
319
321
|
// pace segment and an off-pace window adds a one-line subline under the bar
|
|
320
322
|
// with the reserve/deficit delta and either the projected runout or
|
|
321
|
-
// `lasts to reset
|
|
323
|
+
// `lasts to reset`; a window already at 0% left names itself used up until
|
|
324
|
+
// its reset instead.
|
|
322
325
|
function QuotaRow(props: {
|
|
323
326
|
theme: SidebarTheme
|
|
324
327
|
appearance: AppearancePrefs
|
|
@@ -354,6 +357,8 @@ function QuotaRow(props: {
|
|
|
354
357
|
props.pacing?.runsOutAt
|
|
355
358
|
? formatResetIn(props.pacing.runsOutAt, props.now)
|
|
356
359
|
: undefined,
|
|
360
|
+
props.part?.resetIn,
|
|
361
|
+
props.part?.remainingPercent,
|
|
357
362
|
)
|
|
358
363
|
return (
|
|
359
364
|
<Show
|
|
@@ -1053,20 +1053,36 @@ export function fitQuotaRow(input: {
|
|
|
1053
1053
|
/**
|
|
1054
1054
|
* The pacing subline for a window that is off pace: `deficit 12% · out in
|
|
1055
1055
|
* 1d23h` for a deficit that runs out before the reset, otherwise the delta
|
|
1056
|
-
* and `lasts to reset` (`reserve 4% · lasts to reset`).
|
|
1057
|
-
*
|
|
1058
|
-
*
|
|
1056
|
+
* and `lasts to reset` (`reserve 4% · lasts to reset`). A window already at
|
|
1057
|
+
* 0% left is used up until its reset (`used up · resets in 2h10m`, with no
|
|
1058
|
+
* deficit percentage and no `out in` clause). A runout under a minute away
|
|
1059
|
+
* reads `out in <1m`, never `out in now`. When the line is wider than `width`
|
|
1060
|
+
* cells it is cut to fit and ends in `…` rather than wrapping. Null when
|
|
1061
|
+
* there is no pacing or the window is on pace.
|
|
1059
1062
|
*/
|
|
1060
1063
|
export function fitPaceLine(
|
|
1061
1064
|
pacing: QuotaPacing | null,
|
|
1062
1065
|
width: number | undefined,
|
|
1063
1066
|
runsOutIn: string | undefined,
|
|
1067
|
+
resetIn?: string | undefined,
|
|
1068
|
+
remainingPercent?: number | undefined,
|
|
1064
1069
|
): string | null {
|
|
1065
1070
|
if (!pacing || pacing.state === 'on-pace') return null
|
|
1071
|
+
// An exhausted window reports its deficit as a large percentage with a
|
|
1072
|
+
// runout of `now`, which reads as broken wording. The percentage no longer
|
|
1073
|
+
// means anything once nothing is left, so the line names the state instead.
|
|
1074
|
+
const exhausted = remainingPercent !== undefined && remainingPercent <= 0
|
|
1075
|
+
// A projected runout under a minute away is not `now` while quota remains.
|
|
1076
|
+
const normalizedRunsOutIn =
|
|
1077
|
+
runsOutIn === 'now' || runsOutIn === '0m' ? '<1m' : runsOutIn
|
|
1066
1078
|
const head = `${pacing.state} ${Math.round(Math.abs(pacing.deltaPercent))}%`
|
|
1067
|
-
const line =
|
|
1068
|
-
?
|
|
1069
|
-
|
|
1079
|
+
const line = exhausted
|
|
1080
|
+
? resetIn
|
|
1081
|
+
? `used up \u00b7 resets in ${resetIn}`
|
|
1082
|
+
: 'used up'
|
|
1083
|
+
: normalizedRunsOutIn
|
|
1084
|
+
? `${head} \u00b7 out in ${normalizedRunsOutIn}`
|
|
1085
|
+
: `${head} \u00b7 lasts to reset`
|
|
1070
1086
|
if (width === undefined || Bun.stringWidth(line) <= width) return line
|
|
1071
1087
|
if (width <= 0) return ''
|
|
1072
1088
|
let cut = ''
|
|
@@ -110,7 +110,9 @@ function quotaBarSegments(usedPct, appearance, pacing, width) {
|
|
|
110
110
|
function formatResetIn(resetsAt, now) {
|
|
111
111
|
if (!resetsAt) return '';
|
|
112
112
|
const ms = new Date(resetsAt).getTime() - now;
|
|
113
|
-
|
|
113
|
+
// A pacing runout under a minute away is not `now` while quota remains;
|
|
114
|
+
// the exhausted window never reaches this formatter with an `out in` line.
|
|
115
|
+
if (ms < 60_000) return '<1m';
|
|
114
116
|
const mins = Math.floor(ms / 60_000);
|
|
115
117
|
if (mins < 60) return `${mins}m`;
|
|
116
118
|
const hrs = Math.floor(mins / 60);
|
|
@@ -303,7 +305,8 @@ function Cell(props) {
|
|
|
303
305
|
// instead of letting it wrap. When pacing data is present, the bar gains a
|
|
304
306
|
// pace segment and an off-pace window adds a one-line subline under the bar
|
|
305
307
|
// with the reserve/deficit delta and either the projected runout or
|
|
306
|
-
// `lasts to reset
|
|
308
|
+
// `lasts to reset`; a window already at 0% left names itself used up until
|
|
309
|
+
// its reset instead.
|
|
307
310
|
function QuotaRow(props) {
|
|
308
311
|
const used = () => props.usedPercent ?? 0;
|
|
309
312
|
const labelCell = () => `${props.label}${' '.repeat(Math.max(0, props.labelWidth - Bun.stringWidth(props.label)))} `;
|
|
@@ -315,7 +318,7 @@ function QuotaRow(props) {
|
|
|
315
318
|
figure: figure(),
|
|
316
319
|
reset: props.part?.resetIn
|
|
317
320
|
});
|
|
318
|
-
const paceLine = () => fitPaceLine(props.pacing, props.width === undefined ? undefined : props.width - props.labelWidth - 1, props.pacing?.runsOutAt ? formatResetIn(props.pacing.runsOutAt, props.now) : undefined);
|
|
321
|
+
const paceLine = () => fitPaceLine(props.pacing, props.width === undefined ? undefined : props.width - props.labelWidth - 1, props.pacing?.runsOutAt ? formatResetIn(props.pacing.runsOutAt, props.now) : undefined, props.part?.resetIn, props.part?.remainingPercent);
|
|
319
322
|
return _$createComponent(Show, {
|
|
320
323
|
get when() {
|
|
321
324
|
return props.part;
|