@cortexkit/opencode-openai-auth 1.3.0 → 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/dist/bin.js +8 -8
- package/dist/{codex-request-B9D0e97Q.d.ts → codex-request-hw0XcldE.d.ts} +27 -27
- package/dist/index-1eq2s1cp.js +2 -0
- package/dist/{index-m3ctrabv.js → index-1tdnrt68.js} +1 -1
- package/dist/{index-8x1aj7q3.js → index-5230x6s8.js} +2 -2
- package/dist/{index-gn2b097f.js → index-ag04nyv7.js} +7 -7
- package/dist/index-brbqqer5.js +90 -0
- package/dist/{index-xwvze96g.js → index-d98f1xdp.js} +1 -1
- package/dist/index-jcyrm58f.js +65 -0
- package/dist/{index-2pgkrebq.js → index-rsvnabbe.js} +2 -2
- package/dist/{index-ftkhhr6d.js → index-s88n2bjn.js} +1 -1
- package/dist/{index-bc89akak.js → index-t5m0dhmq.js} +1 -1
- package/dist/index-vy729a0b.js +69 -0
- package/dist/index-wgwze391.js +2 -0
- package/dist/{index-tddr876f.js → index-yhw3hnsh.js} +2 -2
- package/dist/index.d.ts +11 -3
- package/dist/index.js +1 -1
- package/dist/{model-BdITTmeb.d.ts → model-DphbMQce.d.ts} +1 -1
- package/dist/{port-file-DbHIVC9a.d.ts → port-file-Cx-wwe5Q.d.ts} +1 -1
- package/dist/{protocol-MysYPAho.d.ts → protocol-CDqdjh74.d.ts} +1 -1
- package/dist/rpc/port-file.d.ts +1 -1
- package/dist/rpc/port-file.js +1 -1
- package/dist/rpc/protocol.d.ts +1 -1
- package/dist/rpc/protocol.js +1 -1
- package/dist/rpc/rpc-client.d.ts +3 -3
- package/dist/rpc/rpc-client.js +1 -1
- package/dist/rpc/rpc-dir.js +1 -1
- package/dist/{sidebar-state-CVSok7zv.d.ts → sidebar-state-pTd9gg9W.d.ts} +55 -7
- package/dist/sidebar-state.d.ts +2 -2
- package/dist/sidebar-state.js +1 -1
- package/dist/{token-z6qq7a1d.js → token-0z5g59p8.js} +1 -1
- package/dist/token-util-jf9g6stk.js +1 -0
- package/dist/tui-preferences.js +1 -1
- package/dist/tui.d.ts +30 -3
- package/dist/v2/server.d.ts +2 -2
- package/dist/v2/server.js +2 -2
- package/package.json +4 -4
- package/src/tui-compiled/raw/shared/0332701351b3eeec-format.js +50 -5
- package/src/tui-compiled/raw/shared/0f77ebc3c914c9c6-custody.js +70 -1
- package/src/tui-compiled/raw/shared/169b2b4bf30909bc-consumer.js +88 -61
- package/src/tui-compiled/raw/shared/2577ec69f9973ae9-quota-normalize.js +45 -1
- package/src/tui-compiled/raw/shared/30f5bc480f31f51c-roster.js +100 -43
- package/src/tui-compiled/raw/shared/39c3cb05738fcf6d-projection.js +3 -1
- package/src/tui-compiled/raw/shared/42ae93ab554fcec2-open-url.js +7 -9
- package/src/tui-compiled/raw/shared/4825e03209d6ae3e-with-lock.js +2 -0
- package/src/tui-compiled/raw/shared/4f36d333d081d040-merge.js +17 -3
- package/src/tui-compiled/raw/shared/81dddd203f1b92a3-quota-writer.js +253 -0
- package/src/tui-compiled/raw/shared/905bffc0220f43d0-map.js +31 -6
- package/src/tui-compiled/raw/shared/abd062d633e29fd2-pool-routing.js +116 -12
- package/src/tui-compiled/raw/shared/bfbdd0f9aae56b47-pool-quota.js +15 -3
- package/src/tui-compiled/raw/shared/d0f0b6be200311af-insula.js +64 -2
- package/src/tui-compiled/raw/shared/d5a8f1061ee2f114-index.js +2 -2
- package/src/tui-compiled/raw/shared/dbc61cd405941828-accounts.js +5 -4
- package/src/tui-compiled/raw/shared/dc9290c2a7552ba6-watch.js +2 -1
- package/src/tui-compiled/raw/shared/e8d3c8da776ef9cd-index.js +1 -0
- package/src/tui-compiled/raw/sidebar-state.js +32 -3
- package/src/tui-compiled/raw/tui/v2-dialog.js +2 -1
- package/src/tui-compiled/raw/tui.tsx +170 -26
- package/src/tui-compiled/runtime/shared/0332701351b3eeec-format.js +50 -5
- package/src/tui-compiled/runtime/shared/0f77ebc3c914c9c6-custody.js +70 -1
- package/src/tui-compiled/runtime/shared/169b2b4bf30909bc-consumer.js +88 -61
- package/src/tui-compiled/runtime/shared/2577ec69f9973ae9-quota-normalize.js +45 -1
- package/src/tui-compiled/runtime/shared/30f5bc480f31f51c-roster.js +100 -43
- package/src/tui-compiled/runtime/shared/39c3cb05738fcf6d-projection.js +3 -1
- package/src/tui-compiled/runtime/shared/42ae93ab554fcec2-open-url.js +7 -9
- package/src/tui-compiled/runtime/shared/4825e03209d6ae3e-with-lock.js +2 -0
- package/src/tui-compiled/runtime/shared/4f36d333d081d040-merge.js +17 -3
- package/src/tui-compiled/runtime/shared/81dddd203f1b92a3-quota-writer.js +253 -0
- package/src/tui-compiled/runtime/shared/905bffc0220f43d0-map.js +31 -6
- package/src/tui-compiled/runtime/shared/abd062d633e29fd2-pool-routing.js +116 -12
- package/src/tui-compiled/runtime/shared/bfbdd0f9aae56b47-pool-quota.js +15 -3
- package/src/tui-compiled/runtime/shared/d0f0b6be200311af-insula.js +64 -2
- package/src/tui-compiled/runtime/shared/d5a8f1061ee2f114-index.js +2 -2
- package/src/tui-compiled/runtime/shared/dbc61cd405941828-accounts.js +5 -4
- package/src/tui-compiled/runtime/shared/dc9290c2a7552ba6-watch.js +2 -1
- package/src/tui-compiled/runtime/shared/e8d3c8da776ef9cd-index.js +1 -0
- package/src/tui-compiled/runtime/sidebar-state.js +32 -3
- package/src/tui-compiled/runtime/tui/v2-dialog.js +2 -1
- package/src/tui-compiled/runtime/tui.js +350 -219
- package/dist/index-1mbgsxsr.js +0 -2
- package/dist/index-4v2fs42x.js +0 -65
- package/dist/index-ex6nx3mq.js +0 -2
- package/dist/index-psjyexj3.js +0 -69
- package/dist/index-tn8x5tz8.js +0 -90
- package/dist/token-util-cf0nyh7n.js +0 -1
package/dist/v2/server.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{c as
|
|
1
|
+
import{c as pZ}from"../index-1tdnrt68.js";import{$ as t$,A as U$,B as H$,C as fZ,D as vZ,E as W1,F as hZ,G as mZ,H as J$,I as HZ,J as NZ,K as gZ,L as lZ,M as w$,N as y$,O as S2,P as z$,S as a$,T as n$,aa as e$,d as C$,e as qZ,ea as uZ,f as B2,g as W2,h as b2,i as yZ,j as IZ,k as I2,ka as R1,l as Q2,la as A1,n as E1,o as O1,oa as cZ,p as _1,q as R2,r as T$,s as _$,t as M$,u as k$,v as b$,w as D$,x as c$,y as d$,z as D2}from"../index-jcyrm58f.js";import{Qa as h$,Xa as JZ,fb as f2,gb as AZ,hb as xZ,ib as SZ,kb as kZ,lb as m$,ub as bZ,va as RZ,vb as DZ,wb as wZ,xb as g$,ya as c1,za as d1}from"../index-vy729a0b.js";import{Nb as jZ,ac as VZ,bc as BZ,dc as WZ,hc as UZ}from"../index-1eq2s1cp.js";import{$d as K2,Fd as z2,Kd as u1,Md as W$,Nd as p1,Td as y2,Vc as q2,Wc as k2,Xc as EZ,_d as s$,ae as i1,be as a1,cd as B1,ce as n1,dd as h1,ed as m1,ee as o1,fd as g1,fe as r1,he as s1,ie as t1,je as e1,ke as $$,le as Z$,md as f$,sd as v$,ud as OZ,vd as r$,wd as l1,xc as v1}from"../index-brbqqer5.js";import{re as L$}from"../index-ag04nyv7.js";import{Ae as S$}from"../index-rsvnabbe.js";import"../index-yhw3hnsh.js";import{Ke as MZ,Me as G2}from"../index-wgwze391.js";import"../index-5230x6s8.js";import{gf as q$}from"../index-t5m0dhmq.js";import{kf as v2,lf as _Z}from"../index-d98f1xdp.js";import{AsyncLocalStorage as c0}from"node:async_hooks";import{randomUUID as d0}from"node:crypto";class o extends Error{kind;providerID;sessionID;requestKind;constructor($){super($.message??`${$.providerID} ${$.requestKind} request refused (${$.kind})`);this.name="OpenCode2AuthError",this.kind=$.kind,this.providerID=$.providerID,this.sessionID=$.sessionID,this.requestKind=$.requestKind}}function $2($){return`common-auth-placeholder.${$}`}function K1($){let Z=$2($.integrationID);return{type:"oauth",methodID:$.methodID,access:Z,refresh:Z,expires:$.now+31536000000,metadata:{["commonAuthPlaceholder"]:!0}}}function N2($,Z){if($?.type!=="oauth")return!1;let J=Z===void 0?void 0:$2(Z),z=(X)=>J===void 0?X.startsWith("common-auth-placeholder."):X===J;return z($.access)&&z($.refresh)}var L1="No browser sign-in: this connects the plugin to the accounts in its vault.";async function p2($,Z){let J=Z.now??Date.now,{integrationID:z}=Z,X=(H)=>K1({integrationID:z,methodID:H,now:J()}),Y=async(H,W)=>{return await Z.onLogin(H,{integrationID:z,methodID:W}),X(W)},N=(H)=>async(W)=>{let B=H.method.id,V=await H.authorize(W),K={url:V.url,instructions:V.instructions,...V.expiresAt===void 0?{}:{expiresAt:V.expiresAt}};if(V.mode==="auto")return{...K,mode:"auto",callback:V.callback.then((_)=>Y(_,B))};let x=V.callback;return{...K,mode:"code",callback:async(_)=>Y(await x(_),B)}};return $.integration.transform((H)=>{let W=Z.label===void 0?{}:{label:()=>Z.label};for(let K of Z.methods)H.method.update({integrationID:z,method:K.method,authorize:N(K),refresh:async(x)=>{if(!N2(x,z))throw Error("This login method refreshes only its pool placeholder; sign in again with the plugin's login method.");return X(x.methodID)},...W});let B=Z.vault;if(B===void 0)return;let V=B.method.id;H.method.update({integrationID:z,method:B.method,authorize:async()=>({url:"",instructions:B.instructions??L1,mode:"auto",callback:Promise.resolve().then(()=>B.activate({integrationID:z,methodID:V})).then(()=>X(V))}),refresh:async(K)=>{if(!N2(K,z)||K.methodID!==V)throw Error("This login method refreshes only its vault placeholder; choose the plugin's vault login method again.");return X(V)},...W})})}function dZ($){let Z=[],J;for(let z of $.split(/\r?\n/))if(z.startsWith("data:"))Z.push(z.slice(5).replace(/^ /,""));else if(z.startsWith("event:"))J=z.slice(6).trim();if(Z.length===0)return;return J===void 0?{data:Z.join(`
|
|
2
2
|
`)}:{event:J,data:Z.join(`
|
|
3
|
-
`)}}function c2($,Z){let J=new TextDecoder,z="",X=(F)=>{let H=cZ(F);if(!H)return;try{$(H)}catch(W){Z(W)}},Y=()=>{for(;;){let F=/\r?\n\r?\n/.exec(z);if(!F)return;let H=z.slice(0,F.index);z=z.slice(F.index+F[0].length),X(H)}};return new TransformStream({transform(F,H){H.enqueue(F),z+=J.decode(F,{stream:!0}),Y()},flush(){if(z+=J.decode(),Y(),z.trim()!=="")X(z);z=""}})}var C1=512,j2="x-common-auth-attempt",X2=($,Z)=>JSON.stringify([$,Z]),e=($)=>({providerID:$.model.providerID,modelID:$.model.id,sessionID:$.sessionID,agent:$.agent,kind:$.kind});function dZ($){let Z=$.headers;return typeof Z==="object"&&Z!==null}function iZ($,Z){let J=$.getReader();return new ReadableStream({async pull(z){let X;try{X=await J.read()}catch(Y){Z({reason:"failed",message:Y instanceof Error?Y.message:String(Y)}),z.error(Y);return}if(X.done)Z(),z.close();else z.enqueue(X.value)},async cancel(z){Z({reason:"cancelled",...z===void 0?{}:{message:String(z)}}),await J.cancel(z)}})}function d2($,Z){for(let[J,z]of Object.entries(Z)){let X=J.toLowerCase();for(let Y of Object.keys($))if(Y.toLowerCase()===X)delete $[Y];if(z!==null)$[J]=z}}function aZ($,Z){for(let[J,z]of Object.entries(Z))if(z===null)$.delete(J);else $.set(J,z)}async function i2($,Z,J={}){let{providerID:z}=Z,X=J.gateOnPlaceholder,Y=(G)=>X===void 0||X.credential(G)===t(z),F=J.logger,H=Math.max(1,J.maxRecords??C1),W=[...J.hostCredentials??[t(z)],...X?[t(z)]:[]].filter((G)=>G!==""),B=new Map,V=new WeakMap,L=new Map,x=new Set,T=new Map,v=!1,d=!1,S=new Map,y=0,a=!1,I=new Map,j=(G,Q)=>{try{F?.warn(G,Q)}catch{}},K=(G)=>G instanceof Error?G.message:String(G),R=async(G,Q)=>{let U=S.get(G);if(!U||U.size===0)return;await Promise.all([...U].map(async(P)=>{try{await P(Q)}catch(q){j("opencode2 auth listener threw; the request is unaffected",{event:G,error:K(q)})}}))},M=async(G,Q)=>{try{await Z.onAttemptEnd?.(G,Q)}catch(U){j("opencode2 auth onAttemptEnd threw; the request is unaffected",{attemptId:G.attemptId,error:K(U)})}},A=(G,Q)=>{if(G.ended||!G.attempt)return;let U={...G.status===void 0?{}:{status:G.status},outputStarted:G.outputStarted,...G.limit?{limit:G.limit.signal}:{},...Q?{error:Q}:{}};if(Q)G.endError=Q;G.ended=M(G.attempt,U)},N=(G,Q)=>A(G,{reason:"abandoned",message:Q}),_=(G)=>[...B.values()].filter((Q)=>Q.key===G),k=(G)=>_(G).at(-1),E=(G)=>{if(B.delete(G.id),!_(G.key).length)L.delete(G.key)},l=(G)=>{B.set(G.id,G);while(B.size>H){let Q=B.values().next().value;if(Q===void 0)break;N(Q,"dropped to keep the record bound"),E(Q)}},i=(G)=>G.accountId===void 0?void 0:{...G.scope,accountId:G.accountId},c=(G,Q)=>new n({kind:"no-account",providerID:z,sessionID:G.sessionID,requestKind:G.kind,...Q===void 0?{}:{message:Q}}),m=(G)=>{I.get(G)?.clear(),I.delete(G)},p=async(G,Q)=>{let U=()=>c(G,`${z} ${G.kind} request has no account: its auth selection was revoked by session forgetting or installation disposal`);if(a)throw U();let P=I.get(G.sessionID);if(!P)P=new Set,I.set(G.sessionID,P);let q={};P.add(q);let w=()=>{if(!P.has(q))throw U()};try{return await Q(w)}finally{if(P.delete(q),P.size===0&&I.get(G.sessionID)===P)I.delete(G.sessionID)}},b=(G,Q)=>{for(let[U,P]of Q)if(W.some((q)=>P.includes(q)))throw new n({kind:"host-credential-on-wire",providerID:z,sessionID:G.sessionID,requestKind:G.kind,message:`${z} ${G.kind} request still carries the host's placeholder credential in ${U}; the adapter's account headers must replace it`})},u=(G)=>{for(let Q of _(G))if(Q.ended||!Q.attempt)E(Q);else if(Q.transport==="ws"||Q.judged)N(Q,"a newer attempt of its session and kind began"),E(Q)},g=async(G,Q,U,P)=>{let q=X2(G.sessionID,G.kind),w=L.get(q);L.delete(q);let O=w?.accountId??k(q)?.accountId;u(q);let D={...G,...O===void 0?{}:{previousAccountId:O},...w?.rerouteFrom===void 0?{}:{rerouteFrom:w.rerouteFrom}},h=await Z.chooseAccount(D);U();let s={},F1;if(h!==void 0){let E2=await Z.accountHeaders({...G,accountId:h});if(U(),dZ(E2))s=E2.headers,F1=E2.attempt;else s=E2}let P1=`attempt-${++y}`,H2={id:P1,key:q,scope:G,accountId:h,headers:s,attempt:h===void 0?void 0:{...G,accountId:h,attemptId:P1,transport:P,data:F1},...P===void 0?{}:{transport:P},outputStarted:!1};if(l(H2),H2.attempt)R("select",{...G,accountId:H2.attempt.accountId,hook:Q,...D.previousAccountId===void 0?{}:{previousAccountId:D.previousAccountId},...D.rerouteFrom===void 0?{}:{rerouteFrom:D.rerouteFrom},handle:H2.attempt});return H2},z2=async(G,Q,U,P,q)=>{let w=X2(G.sessionID,G.kind),O=P===void 0?void 0:B.get(P);if(O?.key!==w)O=void 0;if(!O){if(O=k(w),_(w).filter((h)=>h.transport===void 0&&!h.ended).length>1&&!d)d=!0,j("opencode2 auth tied a send without its attempt mark to the newest of several waiting attempts",{sessionID:G.sessionID,kind:G.kind})}if(!O||O.transport!==void 0||O.ended)O=await g(G,Q,q,U);else if(O.transport=U,O.attempt)O.attempt.transport=U;if(U==="ws"){for(let D of _(w))if(D!==O&&D.transport==="ws")N(D,"a newer attempt of its session and kind went out over WebSocket")}return O},W2=async(G,Q)=>{try{return await Q()}catch(U){throw A(G,{reason:"failed",message:K(U)}),U}},M2=(G,Q)=>{let U=_(X2(G,Q)).filter((P)=>P.transport==="ws").at(-1);return U?.attempt!==void 0&&!U.ended?U:void 0},U2=(G,Q,U)=>{let P=i(G);if(!P||!G.attempt||G.limit)return;G.limit={signal:Q,delivered:R("limit",{...P,via:U,limit:Q,outputStarted:G.outputStarted,handle:G.attempt})}},Q2=(G,Q,U,P)=>{let q=i(G);if(!q||!G.attempt)return;R("quota",{...q,transport:Q,...P===void 0?{}:{status:P},quota:U,handle:G.attempt})},G2=(G,Q,U,P)=>{let q=G.attempt;if(!q)return;let w=Z.inspectEvent?.(P===void 0?{transport:Q,data:U,attempt:q}:{transport:Q,data:U,event:P,attempt:q});if(!w)return;if(w.quota!==void 0)Q2(G,Q,w.quota);if(w.outputStarted)G.outputStarted=!0;if(w.limit)U2(G,w.limit,Q);if(w.error!==void 0)A(G,{reason:"failed",message:w.error});else if(w.done)A(G)},m2=(G,Q)=>{let U=G.attempt;if(!U||Q.accountId===G.accountId)return;if(U.reboundFrom??=U.accountId,U.accountId=Q.accountId,"data"in Q)U.data=Q.data;G.accountId=Q.accountId},g2=(G)=>!G.attempt||G.endError!==void 0||G.status!==void 0&&G.status>=400,l2=(G)=>{let Q=[...B.values()].filter((D)=>D.scope.sessionID===G),U=Q.filter((D)=>D.limit&&!D.rerouted).at(-1);if(U)return U;let P=Q.filter((D)=>D.scope.kind==="primary"),q=P.length>0?P:Q;if(q.length<=1)return q[0];let w=q.filter((D)=>!D.judged&&g2(D)).at(-1);if(w)return w;let O=q.filter((D)=>D.attempt&&!D.ended);if(O.length>1)return"ambiguous";return O[0]??q.at(-1)},C={providerID:z},f=[];f.push(await $.session.hook("model.request",(G)=>{if(X)return;return p(e(G),async(Q)=>{let U=await g(e(G),"model.request",Q);if(Q(),U.accountId===void 0)throw c(U.scope);d2(G.headers,{...U.headers,[j2]:U.id})})},C)),f.push(await $.session.hook("http.request",(G)=>{if(X){let Q=Y(G.request.headers);if(T.set(G.sessionID,Q),!Q)return}return p(e(G),async(Q)=>{let U=G.request.headers.get(j2)??void 0,P=X?await g(e(G),"http.request",Q,"http"):await z2(e(G),"http.request","http",U,Q);Q();let q=i(P),w=P.attempt;if(!q||!w)throw c(P.scope);await W2(P,async()=>{let O=G.request;if(Z.rewriteRequest){if(U!==void 0){let s=new Headers(O.headers);s.delete(j2),O=new Request(O,{headers:s})}O=await Z.rewriteRequest({...q,request:O,attempt:w})??O,Q()}let D=new Headers(O.headers);D.delete(j2),aZ(D,P.headers),b(P.scope,D.entries());let h=new Request(O,{headers:D});V.set(h,P),G.request=h})})},C)),f.push(await $.session.hook("http.response",async(G)=>{let Q=V.get(G.request);if(!Q){if(X)return;if(!v)v=!0,j("opencode2 auth dropped an http.response whose request it did not produce",{sessionID:G.sessionID,kind:G.kind});return}let U=G.response;if(Z.answeredBy&&Q.attempt){let D=Q.attempt,h=await W2(Q,async()=>Z.answeredBy?.({request:G.request,response:U,attempt:D}));if(h)m2(Q,h)}let P=i(Q),q=Q.attempt;if(!P||!q)return;Q.status=U.status;let w=Z.quotaFromHeaders?.(U.headers,U.status,q);if(w!==void 0)Q2(Q,"http",w,U.status);if(!U.ok&&Z.limitFromResponse){let D=await Z.limitFromResponse({status:U.status,headers:U.headers,body:()=>U.clone().text(),attempt:q});if(D)U2(Q,D,"http")}if(!U.ok||!U.body)A(Q);let O=U;if(U.body&&(Z.inspectEvent||Z.onAttemptEnd)){let D=U.body;if(Z.inspectEvent)D=D.pipeThrough(c2((h)=>G2(Q,"http",h.data,h.event),(h)=>j("opencode2 auth event inspection threw",{error:K(h)})));O=new Response(iZ(D,(h)=>A(Q,h)),{status:U.status,statusText:U.statusText,headers:U.headers})}if(Z.rewriteResponse)O=await Z.rewriteResponse({...P,request:G.request,response:O,attempt:q})??O;if(O!==U)G.response=O},C)),f.push(await $.session.hook("experimental.ws.handshake",(G)=>{if(X){let Q=Y(new Headers(G.headers)),U=X2(G.sessionID,G.kind);if(T.set(G.sessionID,Q),x.delete(U),!Q)return}return p(e(G),async(Q)=>{let U;for(let O of Object.keys(G.headers)){if(O.toLowerCase()!==j2)continue;U??=G.headers[O],delete G.headers[O]}let P=X?await g(e(G),"experimental.ws.handshake",Q,"ws"):await z2(e(G),"experimental.ws.handshake","ws",U,Q);Q();let q=i(P),w=P.attempt;if(!q||!w)throw c(P.scope);await W2(P,async()=>{d2(G.headers,P.headers);let O=Z.rewriteHandshakeURL?.({...q,url:G.url,attempt:w});if(O!==void 0)G.url=O;if(b(P.scope,Object.entries(G.headers)),X)x.add(P.key)})})},C));let r=Z.rewriteWebSocketFrame?.bind(Z);if(r)f.push(await $.session.hook("experimental.ws.send",async(G)=>{let Q=e(G);if(X&&!x.has(X2(Q.sessionID,Q.kind)))return;let U=M2(Q.sessionID,Q.kind),P=await r({...Q,attempt:U?.attempt,frame:G.frame});if(P!==void 0)G.frame=P},C));f.push(await $.session.hook("experimental.ws.receive",(G)=>{if(X&&!x.has(X2(G.sessionID,G.kind)))return;let Q=M2(G.sessionID,G.kind);if(!Q)return;try{G2(Q,"ws",G.frame)}catch(U){j("opencode2 auth frame inspection threw",{error:K(U)})}},C)),f.push(await $.session.hook("retry",async(G)=>{if(X&&T.get(G.sessionID)!==!0)return;let Q=l2(G.sessionID);if(!Q)return;let U=G.decision;if(Q==="ambiguous"){await R("retry",{sessionID:G.sessionID,attempt:G.attempt,reason:"host-decides",hostDecision:U,decision:U});return}let P=Q;await p(P.scope,async(q)=>{P.judged=!0;let w=U,O,D,h=P.attempt;if(P.accountId===void 0||!h)w={retry:!1},O="no-account";else if(P.outputStarted)w={retry:!1},O="output-started";else{if(!P.limit){let s=Z.limitFromError?.(G.error,h);if(s)U2(P,s,"error")}if(P.ended)await P.ended,q();if(P.limit)await P.limit.delivered,q(),P.rerouted=!0,D={accountId:P.accountId,limit:P.limit.signal},w={retry:!0,delay:0},O="reroute";else O="host-decides"}if(G.decision=w,w.retry&&P.accountId!==void 0)L.set(P.key,{sessionID:P.scope.sessionID,accountId:P.accountId,...D===void 0?{}:{rerouteFrom:D}});await R("retry",{sessionID:G.sessionID,...P.accountId===void 0?{}:{accountId:P.accountId},kind:P.scope.kind,attempt:G.attempt,reason:O,hostDecision:U,decision:w,...h===void 0?{}:{handle:h}})})},C));let H1=(G)=>{m(G),T.delete(G);for(let Q of x)if(JSON.parse(Q)[0]===G)x.delete(Q);for(let Q of[...B.values()]){if(Q.scope.sessionID!==G)continue;N(Q,"its session was forgotten"),B.delete(Q.id)}for(let[Q,U]of L)if(U.sessionID===G)L.delete(Q)},u2=new AbortController,N1=$.event;if(N1)(async()=>{try{for await(let G of N1.subscribe({signal:u2.signal}))if(G.type==="session.deleted")H1(G.data.sessionID)}catch(G){if(!u2.signal.aborted)j("opencode2 auth stopped listening for session deletion",{error:K(G)})}})();return{on(G,Q){let U=S.get(G);if(!U)U=new Set,S.set(G,U);let P=Q;return U.add(P),()=>{U.delete(P)}},accountFor(G,Q){return k(X2(G,Q))?.accountId},forgetSession:H1,get size(){return B.size},async dispose(){if(a)return;a=!0;for(let G of I.keys())m(G);u2.abort();for(let G of B.values())N(G,"the installation was disposed");B.clear(),L.clear(),x.clear(),T.clear(),S.clear(),await Promise.all(f.map(async(G)=>{try{await G.dispose()}catch(Q){j("opencode2 auth hook did not dispose cleanly",{error:K(Q)})}}))}}}import{createHash as nZ}from"node:crypto";var oZ=1024,rZ=($)=>typeof $==="object"&&$!==null&&!Array.isArray($),T1=($)=>_1($,"user"),sZ=($)=>rZ($)&&($.role==="assistant"||typeof $.type==="string"&&$.type!=="message"&&$.type!=="configuration_update");function tZ($){return nZ("sha256").update(JSON.stringify($)).digest("hex")}class F2{runtime;maxSessions;#$=new Map;constructor($,Z=oZ){this.runtime=$;this.maxSessions=Z}advance($,Z,J=this.runtime){let z=this.#$.get($),X=Array.isArray(Z.input)?Z.input:[],Y=X.filter(T1),F=X.findLastIndex(T1),H=F<0?void 0:tZ(X[F]),W=typeof Z.previous_response_id==="string"&&Z.previous_response_id.length>0,B,V,L;if(W)B=Y.length>0,V=H??z?.fingerprint,L=z?.userCount===void 0?void 0:z.userCount+Y.length;else{V=H,L=Y.length;let T=F>=0&&F>X.findLastIndex(sZ),v=z!==void 0&&!z.completed&&z.fingerprint===V&&z.userCount===L;B=T&&!v}let x=B||!z?{turnID:(J?.uuid??Y2)(),turnStartedAt:(J?.now??Date.now)()}:{turnID:z.turnID,turnStartedAt:z.turnStartedAt};return this.#Z($,{...x,completed:!1,fingerprint:V,userCount:L}),x}completed($){let Z=this.#$.get($);if(Z)this.#Z($,{...Z,completed:!0})}get($){return this.#$.get($)}forget($){this.#$.delete($)}#Z($,Z){this.#$.delete($),this.#$.set($,Z);while(this.#$.size>this.maxSessions){let J=this.#$.keys().next().value;if(J===void 0)break;this.#$.delete(J)}}}function a2($,Z){return{threadID:$.threadID,windowID:$.windowID,turnID:Z.turnID,turnStartedAt:Z.turnStartedAt}}var M1=Symbol.for("@cortexkit/openai-auth/opencode2/codex-installation");function eZ(){let $=globalThis;return $[M1]??=crypto.randomUUID(),$[M1]}class P2{runtime;store;sessions;frameTurns;installationID;constructor($,Z,J){this.runtime=$;this.store=J;this.installationID=Z??eZ(),this.sessions=J?.sessions??new Map,this.frameTurns=J?.frameTurns??new F2}get($){let Z=this.runtime?.uuid??Y2;if(this.store)return this.store.get($,Z);let J=this.sessions.get($);if(!J){let z=Z();J={threadID:z,turnID:Z(),windowID:`${z}:0`},this.sessions.set($,J)}return J}advanceFrame($,Z){return this.frameTurns.advance($,Z,this.runtime)}frameReceived($,Z){if(!Z.includes("response.completed"))return;if(O2(Z)?.type==="response.completed")this.frameTurns.completed($)}forget($){if(this.store)this.store.delete($);else this.sessions.delete($),this.frameTurns.forget($)}}var n2={version:E1,"user-agent":O1,originator:"codex_exec"};var $0=1024,Z0=/(?:^|\/)gpt-6-(?:astra|sol|luna)$/i,A2=($)=>typeof $==="object"&&$!==null&&!Array.isArray($),x1=($)=>A2($)&&($.type==="message"||("role"in $))&&$.role==="user",S1=($)=>A2($)&&$.type==="configuration_update";class o2{http;#$=new Map;constructor($=new P2){this.http=$}apply($,Z,J){if(Z.kind!=="primary")return!1;let z=typeof $.model==="string"?$.model:"";if(!R1.has(z))return!1;if(Z0.test(z))return!1;let X=A2($.reasoning)?$.reasoning:void 0,Y=typeof X?.effort==="string"?X.effort:void 0;if(!Y)return!1;let F=this.#$.get(Z.sessionID);if(F===void 0)return this.#Z(Z.sessionID,Y),!1;if(Y===F)return!1;let H=Array.isArray($.input)?$.input:void 0;if(!H||H.length===0)return!1;let W=H.findLastIndex(x1);if(W<0){if(J==="http")return!1;return $.reasoning={...X,effort:F},!0}if($.reasoning={...X,effort:F},!S1(H[W-1]))H.splice(W,0,{type:"configuration_update",reasoning:{effort:Y}});return!0}forget($){this.#$.delete($),this.http.forget($)}#Z($,Z){this.#$.set($,Z);while(this.#$.size>$0){let J=this.#$.keys().next().value;if(J===void 0)break;this.#$.delete(J)}}}function O2($){try{let Z=JSON.parse($);return A2(Z)?Z:void 0}catch{return}}async function q1($,Z,J,z,X=J.http){if($.method.toUpperCase()!=="POST")return;if(!/\/responses\/?$/.test(new URL($.url).pathname))return;let Y=await $.clone().text(),F=O2(Y);if(F)delete F.max_output_tokens;let H=new Headers($.headers),W=R2({rewriteLite:A1,init:{body:F?JSON.stringify(F):$.body===null?void 0:Y},headers:H,metadata:X.get(Z.sessionID),installationID:X.installationID,runtime:X.runtime,websocket:!1,responsesLite:z,applyEffort:(B)=>{J.apply(B,Z,"http")}});return new Request($,{headers:H,body:W.init?.body})}function k1($,Z,J,z){let X=z.sessions.get($.sessionID),Y=z.frameTurns.get($.sessionID);if(!X||!Y)return;let F=a2(X,Y),H=new Headers({"content-type":"application/json"});for(let B of["chatgpt-account-id","x-opencode-parent-session-id","x-parent-session-id"]){let V=J.get(B);if(V!==null)H.set(B,V)}R2({init:{body:$.bodyText},headers:H,metadata:F,installationID:z.installationID,runtime:z.runtime,websocket:!1,skipTurnUpdate:!0,responsesLite:!1,rewriteLite:()=>{}});let W=new URL(Z);if(W.protocol==="wss:")W.protocol="https:";if(W.protocol==="ws:")W.protocol="http:";return new Request(W,{method:"POST",headers:H,body:$.bodyText})}function J0($,Z){if(JSON.stringify($)===JSON.stringify(Z))return!0;if(!Array.isArray($)||!Array.isArray(Z)||Z.length!==$.length+1)return!1;let J=Z.findIndex((z,X)=>JSON.stringify(z)!==JSON.stringify($[X]));return J>=0&&S1(Z[J])&&x1(Z[J+1])&&JSON.stringify(Z.slice(J+1))===JSON.stringify($.slice(J))}function b1($,Z,J){let z=O2($);if(z?.type!=="response.create")return;let X=J.http.advanceFrame(Z.sessionID,z),Y=J.http.get(Z.sessionID);delete z.max_output_tokens;let F=R2({rewriteLite:()=>{},init:{body:JSON.stringify(z)},headers:new Headers,metadata:a2(Y,X),installationID:J.http.installationID,runtime:J.http.runtime,websocket:!0,responsesLite:!1,applyEffort:(W)=>{J.apply(W,Z,"ws")}}),H=O2(String(F.init?.body));if(!H)return;if(!J0(z.input,H.input)){if("input"in z)H.input=z.input;else delete H.input;return JSON.stringify(H)}return String(F.init?.body)}function z0($){return $.replace(/\/responses\/?$/,"").replace(/\/$/,"")}function r2($,Z){let J=new URL($);if(J.origin!=="https://api.openai.com"&&J.origin!=="wss://api.openai.com"||!/\/responses\/?$/.test(J.pathname))return $;let z=new URL(`${z0(Z)}/responses`);if(z.search=J.search,J.protocol==="ws:"||J.protocol==="wss:")z.protocol=z.protocol==="https:"?"wss:":"ws:";return z.href}import{resolve as D1}from"node:path";var G0=1024;class x2{accounts=new Map;limit;constructor($=G0){this.limit=Math.max(1,$)}record($,Z){this.accounts.delete($),this.accounts.set($,Z);while(this.accounts.size>this.limit){let J=this.accounts.keys().next().value;if(J===void 0)break;this.accounts.delete(J)}}activeAccount($){return this.accounts.get($)}forget($){this.accounts.delete($)}get size(){return this.accounts.size}}var w1=Symbol.for("@cortexkit/openai-auth/opencode2-session-accounts"),y1=globalThis,s2=y1[w1]??new Map;y1[w1]=s2;function t2($){let Z=JSON.stringify([D1($.configPath),D1($.statePath)]),J=s2.get(Z);if(!J)J=new x2,s2.set(Z,J);return J}var o="openai",X0=60000,I1=1,Y0="request refused: no account with a usable credential",$2=($)=>typeof $==="object"&&$!==null&&!Array.isArray($);function Q0($){let Z=$2($)?$.counters:void 0,J=$2(Z)?Z.resetCredits:void 0,z=$2(J)?J.value:void 0;return typeof z==="number"&&Number.isFinite(z)?z:void 0}function e2($){try{return JSON.parse($)}catch{return}}function f1($){let Z=q2($);return Z?k2(Z):void 0}var j0=new Set(["usage_limit_reached","rate_limit_exceeded"]);function $1($,Z,J){return{reason:$.window,...J!==void 0?{status:J}:{},...$.resetAt!==void 0?{retryAfterMs:Math.max(0,$.resetAt-Z)}:{}}}function V0($,Z){let J=S2($);if(J){let Y=typeof $.status==="number"?$.status:void 0;return $1(J,Z,Y)}if($.type!=="response.failed"||!$2($.response))return;let z=$.response.failed;if($2(z)&&typeof z.rate_limit_reached_type==="string")return{reason:z.rate_limit_reached_type};let X=$.response.error;if($2(X)){let Y=typeof X.code==="string"?X.code:typeof X.type==="string"?X.type:void 0;if(Y&&j0.has(Y))return{reason:Y}}return}function B0($,Z){let J=e2($);if(!$2(J))return;let z=typeof J.type==="string"?J.type:void 0;if(z==="codex.rate_limits")return{quota:{snapshot:g1(J),complete:!0}};let X=V0(J,Z);if(X)return{limit:X};if(z===void 0||z==="error")return;return J$(z)?void 0:{outputStarted:!0}}function W0($){let Z=!1;for(let J of $.keys())if(J.toLowerCase().startsWith("x-codex-")){Z=!0;break}if(!Z)return;return{snapshot:h1($),complete:m1($)}}function U0($){let Z=$.get("retry-after");if(Z===null)return;let J=Number(Z);return Number.isFinite(J)&&J>=0?J*1000:void 0}function z$($){let{source:Z,pins:J}=$,z=$.now??Date.now,X=$.log,Y=$.vault,F=new o2($.codex),H=new Map,W=(j)=>`${j.sessionID}\x00${j.kind}\x00${j.accountId}`,B=new Map,V=$.sessionAccounts??new x2,L=(j,K,R)=>{let M=R?[]:Z$(Z.peek().rows,j,K,Y?.identities()??new Set),A=(Y?.routes()??[]).filter((N)=>N.kind==="oauth"&&u1(K2(N.quota),j,K));return[...M.map((N)=>({id:N.id,...N.identity!==void 0?{identity:N.identity}:{},quota:N.quota,row:N})),...A.map((N)=>({id:N.id,...N.identity!==void 0?{identity:N.identity}:{},quota:N.quota}))]},x=(j,K,R)=>{let M=n1(j,K,R),A=j.map((E)=>({id:E.id,kind:"oauth",...v1(E.quota)?{quota:E.quota}:{}})),N=j.flatMap((E)=>E.row?[E.row]:[]),_=new Set(j.filter((E)=>!E.row).map((E)=>E.id)),k=Z.rateLimitMarks(N);for(let E of _){let l=B.get(E);if(l===void 0)continue;if(l<=R)B.delete(E);else k.set(E,l)}return{rows:A,now:R,rateLimitMarks:k,refreshBackoff:Z.refreshBackoffFor(N),killswitch:M,requestPull:(E)=>_.has(E)?Y?.requestReading(E):Z.requestReading(E)}},T=(j,K,R,M,A)=>{let N=s1({...j,placement:o1(K),mainId:A});if(N.kind==="block"){X?.debug("pool admission refused the request",{reason:N.block.reason});return}let _=N.order.filter((k)=>!R.has(k));if(M!==void 0&&_.includes(M))return M;return _[0]},v=(j,K,R,M,A,N)=>{let _=new Map(K.map((b)=>[b.id,b.quota])),k={requestBytes:I1,reservePercent:(b)=>p1(R,b===i1?void 0:b),resetCredits:(b)=>Q0(_.get(b))},E=t1(j),l=(b,u)=>J.place({sessionId:M,requestBytes:I1,validPinnedAccountIds:j.rows.map((g)=>g.id).filter((g)=>!E.excluded.has(g)),excludeAccountIds:b,quotaCheckedAtByAccount:Object.fromEntries(j.rows.map((g)=>[g.id,E.projections.get(g.id)?.checkedAt])),wireAccountIdByAccount:Object.fromEntries(K.map((g)=>[g.id,g.identity])),select:(g)=>e1(j,k,new Set(b),g),persist:u}),i=[...A],c=l(i,N);if(!c)return;let m=c.accountId,p=$$(j,k,m);if(p.kind==="none")return;if(p.kind==="move"){let b=l([...i,m],N);if(b)return b.accountId;return p.reason==="killswitch"?void 0:m}if(p.kind==="detour")return l([...i,m],!1)?.accountId;return m},y={providerID:o,chooseAccount:async(j)=>{let K=await Y?.authority(),R=await $.storage(),M=K!==void 0&&K!=="local",A=()=>{throw new n({kind:"no-account",providerID:o,sessionID:j.sessionID,requestKind:j.kind,message:b2})};if(M)await $.awaitVaultRoster?.();else{if(!(await Z.current()).active){if(await $.slotPlaceholderWithoutMain?.())A();X?.warn("the account pool does not serve requests yet; refusing the request",{kind:j.kind});return}await Z.prepareTokens(Z.peek().rows,R)}let N=z(),_=L(R,N,M),k=r1(x(_.filter((u)=>u.id!==j.rerouteFrom?.accountId),R,N));if(k)await k,N=z(),_=L(R,N,M);let E=new Map(_.map((u)=>[u.id,u])),l=x(_,R,N),i=new Set(j.rerouteFrom?[j.rerouteFrom.accountId]:[]),c=R?.routing?.mode??"main-first",m=j.kind==="primary",p=new Set,b;for(;;){let u=new Set([...i,...p]);if(b=void 0,c==="sticky-balanced")b=v(l,_,R,j.sessionID,u,m&&p.size===0);if(b??=T(l,c,u,m?void 0:V.activeAccount(j.sessionID),M?c==="sticky-balanced"?null:a1(Y?.routes()??[]):void 0),b===void 0||p.has(b)){b=void 0;break}let g=E.get(b)?.row;if(g){if(Z.usableToken(g)!==void 0)break;X?.debug("pool row holds no usable token; choosing again",{accountId:b})}else{if(!Y)break;let z2=await Y.authorize(b);if(z2){H.set(W({...j,accountId:b}),z2);break}X?.debug("the vault refused to serve an account; choosing again",{accountId:b})}p.add(b)}if(b===void 0&&!M&&_.length===0&&await $.slotPlaceholderWithoutMain?.())A();if(b===void 0&&M&&Y&&(_.length===0||p.size>0)){let u=p.size>0?"vault-refused":d1(Y);throw X?.warn("vault mode: no vault account can serve; refusing the request",{cause:u}),new n({kind:"no-account",providerID:o,sessionID:j.sessionID,requestKind:j.kind,message:c1(u,Y.name)})}if(b!==void 0&&m)V.record(j.sessionID,b),$.onRoute?.(j.sessionID,b,c);return X?.debug("pool account chosen",{kind:j.kind,accountId:b,mode:c,...j.rerouteFrom?{rerouteFrom:j.rerouteFrom.accountId}:{}}),b},accountHeaders:async(j)=>{let{accountId:K}=j,R=()=>new n({kind:"no-account",providerID:o,sessionID:j.sessionID,requestKind:j.kind,message:Y0}),M=Y&&await Y.authority()!=="local"?void 0:Z.peek().rows.find((_)=>_.id===K);if(!M&&Y){let _=W(j),k=H.get(_)??await Y.authorize(K);if(H.delete(_),!k)throw X?.warn("the vault refused to serve an account; refusing the request",{accountId:K}),R();return{headers:{...n2,"session-id":j.sessionID,authorization:`Bearer ${k.accessToken}`,"chatgpt-account-id":k.accountIdentity??f1(k.accessToken)??null},attempt:{kind:"vault",routeId:K,receipt:k}}}let A=M?Z.usableToken(M):void 0;if(!M||!A)throw X?.warn("pool row holds no usable token; refusing the request",{accountId:K}),R();let N=M.identity??f1(A);return{headers:{...n2,"session-id":j.sessionID,authorization:`Bearer ${A}`,"chatgpt-account-id":N??null},attempt:{kind:"pool",token:A,credentialEpoch:M.credentialEpoch}}},async rewriteRequest({request:j,sessionID:K,kind:R}){let M=$.codexEndpoint?r2(j.url,$.codexEndpoint()):j.url,A=M===j.url?j:new Request(M,j);return await q1(A,{sessionID:K,kind:R},F,$.responsesLite?.()??!1)??A},rewriteHandshakeURL:({url:j})=>$.codexEndpoint?r2(j,$.codexEndpoint()):void 0,rewriteWebSocketFrame:({frame:j,sessionID:K,kind:R})=>b1(j,{sessionID:K,kind:R},F),quotaFromHeaders:(j)=>W0(j),async limitFromResponse({status:j,headers:K,body:R}){if(j<400)return;let M=e2(await R().catch(()=>"")),A=S2({...$2(M)?M:{},status:j});if(!A)return;let N=z(),_=$1(A,N,j);if(_.retryAfterMs!==void 0)return _;let k=U0(K);return k===void 0?_:{..._,retryAfterMs:k}},inspectEvent:({data:j})=>B0(j,z()),limitFromError(j){let K=e2(j.message),R=S2({...$2(K)?K:{},...j.status!==void 0?{status:j.status}:{}})??(j.message.includes("usage_limit_reached")?{window:"usage_limit_reached"}:void 0);return R?$1(R,z(),j.status):void 0},async onAttemptEnd(j,K){let R=j.data;if(R?.kind!=="vault"||K.status!==401)return;X?.warn("a vault account answered 401; reporting it to the vault",{accountId:j.accountId}),await Y?.reportFailure(R.receipt,401)}},a=(j,K,R)=>{let M=R.data;if(M?.kind==="vault"){Y?.recordSnapshot(j,K.snapshot,K.complete,M.receipt);return}if(M?.kind!=="pool")return;if(Z.peek().rows.find((N)=>N.id===j)?.credentialEpoch!==M.credentialEpoch){X?.debug("quota reading dropped: the row holds another credential",{accountId:j});return}Z.recordSnapshot(j,K.snapshot,M.token,K.complete)},I=(j,K,R)=>{let M=z(),A=R.data?.kind==="vault",N=A?Y?.routes().find((E)=>E.id===j)?.quota:Z.peek().rows.find((E)=>E.id===j)?.quota,_=l1(K2(N),K.reason,M,X0,K.retryAfterMs!==void 0?M+K.retryAfterMs:void 0);if(!A){Z.markRateLimited(j,_);return}let k=B.get(j);if(k===void 0||k<_)B.set(j,_)};return{adapter:y,attach(j){j.on("quota",(K)=>a(K.accountId,K.quota,K.handle)),j.on("limit",(K)=>{I(K.accountId,K.limit,K.handle),X?.debug("pool row refused the request",{accountId:K.accountId,via:K.via,reason:K.limit.reason,outputStarted:K.outputStarted})})},forgetSession(j){J.forget(j),V.forget(j),F.forget(j)},activeAccount:(j)=>V.activeAccount(j)}}import{resolve as V$}from"node:path";import{Buffer as H0}from"node:buffer";import{resolve as G$}from"node:path";function L2($){return H0.byteLength(JSON.stringify($))}function N0($){return $.reduce((Z,J)=>Z+L2(J),0)}function Z1($,Z){return 2+$+Math.max(0,Z-1)}function F0($){let{head:Z,pending:J}=$;return 10+$.fieldsBytes+1+(Z?22+Z.responseIDBytes+9+Z1(Z.inputBytes,Z.input.length)+1:0)+(J?20+Z1(J.inputBytes,J.input.length)+10+Z1(J.outputBytes,J.output.length)+(J.responseID===void 0?0:14+J.responseIDBytes)+1:0)}function X$($){try{let Z=JSON.parse($);if(Z&&typeof Z==="object"&&!Array.isArray(Z))return Z}catch{}return}class Y${enabled;caps=D2;entries=new Map;bytes=0;constructor($=!1){this.enabled=$}setEnabled($){if(this.enabled=$,!$)this.entries.clear(),this.bytes=0}send($,Z){if(!this.enabled)return;let J=X$(Z);if(J?.type!=="response.create")return;if(!Array.isArray(J.input)){this.forget($);return}let z=J.previous_response_id,X=this.entries.get($),Y=X?.head;if(z&&z!==Y?.responseID){this.forget($);return}let{type:F,previous_response_id:H,input:W,...B}=J;this.keep($,{fields:z&&X?X.fields:B,fieldsBytes:z&&X?X.fieldsBytes:L2(B),...z&&Y?{head:Y}:{},pending:{input:W,inputBytes:N0(W),output:[],outputBytes:0,responseIDBytes:0},bytes:0})}receive($,Z,J){if(!this.enabled||!Z.includes("response.created")&&!Z.includes("response.output_item.done")&&!Z.includes("response.completed"))return;let z=this.entries.get($);if(!z?.pending)return;let X=X$(Z);if(!X)return;let Y=z.pending,F=X.response;if(X.type==="response.created"&&typeof F?.id==="string")Y.responseID=F.id,Y.responseIDBytes=L2(F.id),this.keep($,z);else if(X.type==="response.output_item.done"&&X.item){if(typeof X.response_id==="string"&&Y.responseID!==void 0&&X.response_id!==Y.responseID)return;Y.output.push(X.item),Y.outputBytes+=L2(X.item),this.keep($,z)}else if(X.type==="response.completed"&&typeof F?.id==="string"){if(F.id===z.head?.responseID||Y.responseID!==void 0&&F.id!==Y.responseID)return;let H={responseID:F.id,responseIDBytes:Y.responseID===F.id?Y.responseIDBytes:L2(F.id),input:[...z.head?.input??[],...Y.input,...Y.output],inputBytes:(z.head?.inputBytes??0)+Y.inputBytes+Y.outputBytes},W={...z,head:H,pending:void 0};if(!this.keep($,W))return;J?.({sessionID:$,responseID:H.responseID,bodyText:this.body(z.fields,H)})}}replay($){let Z=this.entries.get($);if(!Z?.head)return;return this.entries.delete($),this.entries.set($,Z),this.body(Z.fields,Z.head)}forget($){let Z=this.entries.get($);if(Z)this.bytes-=Z.bytes;this.entries.delete($)}status(){return{bytes:this.bytes,sessions:[...this.entries].map(([$,Z])=>({sessionID:$,bytes:Z.bytes,responseID:Z.head?.responseID,pending:Z.pending!==void 0}))}}body($,Z){return JSON.stringify({...$,input:Z.input,stream:!0})}keep($,Z){let J=F0(Z);if(this.forget($),J>this.caps.maxBytes)return!1;Z.bytes=J,this.entries.set($,Z),this.bytes+=J;while(this.entries.size>this.caps.maxTargets||this.bytes>this.caps.maxBytes){let z=this.entries.keys().next().value;if(z===void 0)break;this.forget(z)}return this.entries.has($)}}var Q$=Symbol.for("@cortexkit/openai-auth/opencode2-frame-mirror"),j$=globalThis,J1=j$[Q$]??new Map;j$[Q$]=J1;function w2($){let Z=JSON.stringify([G$($.configPath),G$($.statePath)]),J=J1.get(Z);if(!J)J=new Y$,J1.set(Z,J);return J}var P0=5000,K0=["accept","originator","session-id","thread-id","user-agent","version","x-client-request-id","x-codex-beta-features","x-codex-turn-metadata","x-codex-window-id","x-openai-internal-codex-responses-lite","x-opencode-parent-session-id","x-parent-session-id"],L0=["x-opencode-parent-session-id","x-parent-session-id"];function H$($){let Z=B$($);return{enabled:Z?.enabled===!0,subagents:Z?.subagents===!0,sustain:Z?.sustain===!0,window:W$($?{...$,cachekeep:Z}:$)}}var N$=Symbol.for("@cortexkit/openai-auth/opencode2-cache-keep"),F$=globalThis,C2=F$[N$]??new Map;F$[N$]=C2;function C0($,Z){let J=[],z=()=>J.at(-1)?.location,X=()=>{let W=z();if(!W)throw Error("no location holds keep-warm");return W},Y=(W,B)=>{H.remove(W),z()?.log?.debug(`cachekeep dropped target (${B})`,{sessionKey:W})},F=async(W)=>{if(W.meta.credentialMode!=="local")throw Error("a target captured in vault mode is not warmed with a local credential");let B=W.accountId??"main",V=X(),L=await V.source.accessFor(B,await V.storage());if(!L)throw Error(`pool row ${B} has no usable token`);return{token:L.token,identity:L.row.identity}},H=U$({...D2,now:$.now,...$.setIntervalImpl?{setIntervalImpl:$.setIntervalImpl}:{},...$.clearIntervalImpl?{clearIntervalImpl:$.clearIntervalImpl}:{},codexResponsesUrl:$.codexResponsesUrl,fetchImpl:(W,B)=>X().fetch(W,B),logger:{debug:(W,B)=>z()?.log?.debug(W,B),warn:(W,B)=>z()?.log?.warn(W,B)},getWindow:()=>z()?.settings().window,getSustain:()=>z()?.settings().sustain===!0,resolveLocal:F,vault:{owns:(W)=>z()?.vault.owns(W)===!0,authority:()=>X().vault.authority(),send:async(W,B,V)=>{let L=X();if(await L.vault.authority()!=="vault")return;return L.vault.send(W,B,V)}},activeAccount:(W)=>{if(W===void 0)throw Error("target has no session");let B=z(),V=B?.settings();if(!B||!V?.enabled){Y(W,"keep-warm is off");return}if(!V.subagents&&H.status().targets.some((x)=>x.sessionKey===W&&x.isSubagent)){Y(W,"subagent warming is off");return}let L=B.accounts.activeAccount(W);if(L===void 0){Y(W,"no account recorded for the session");return}return L},verifyCredential:({target:W,mode:B,identity:V})=>{if(W.meta.credentialMode!==B)throw Error(`a target captured in ${W.meta.credentialMode??"an unknown"} mode is not warmed with a ${B} credential`);if(V!==W.meta.chatgptAccountId)throw Y(W.sessionKey,"the account signs in as another login now"),Error("the account signs in as another login now")}});return{manager:H,settings:Z,holders:J,joinTimeoutMs:$.joinTimeoutMs??P0}}function T0($){try{let Z=JSON.parse($),J=Array.isArray(Z.input)?Z.input.at(-1):void 0;if(J?.role!=="user")return!1;return(typeof J.content==="string"?J.content:Array.isArray(J.content)?J.content.map((X)=>typeof X?.text==="string"?X.text:"").join(""):"").startsWith("This is a keep-alive request.")}catch{return!1}}function _0($){let Z={};for(let J of K0){let z=$.get(J);if(z)Z[J]=z}return Z}function P$($,Z,J){let z=JSON.stringify([V$($.configPath),V$($.statePath)]),X=C2.get(z);if(!X)X=C0(J,Z.settings()),C2.set(z,X);let Y=X,F=w2($);F.setEnabled(Y.settings.enabled);let H={location:{...Z,settings:()=>Y.settings}};Y.holders.push(H);let W=!1,B=async(V)=>{try{let L=H.location.settings();if(W||!L.enabled)return;if(V.kind!=="primary"){if(V.kind==="generate"&&T0(await V.request.clone().text())){if(W)return;Y.manager.remove(V.sessionID)}return}let x=V.attempt.data,T=x?.kind==="pool"?"local":x?.kind==="vault"?"vault":void 0;if(!T)return;let v=V.request.headers,d=L0.some((a)=>v.has(a))||Z.parentOf!==void 0&&await Z.parentOf(V.sessionID)!==void 0;if(d&&!L.subagents)return;let S=await V.request.clone().text();if(W)return;let y=v.get("chatgpt-account-id")??void 0;Y.manager.track({sessionKey:V.sessionID,bodyText:S,accountId:V.attempt.accountId,isSubagent:d,meta:{replayHeaders:_0(v),...y?{chatgptAccountId:y}:{},routingSessionId:V.sessionID,url:V.request.url,credentialMode:T}})}catch(L){Z.log?.warn("cachekeep capture failed",{error:L instanceof Error?L.message:String(L)})}};return{manager:Y.manager,configure:(V)=>{Object.assign(Y.settings,V),F.setEnabled(Y.settings.enabled)},capture:B,forget:(V)=>Y.manager.remove(V),async release(){if(W)return;W=!0;let V=Y.holders.indexOf(H);if(V>=0)Y.holders.splice(V,1);if(Y.holders.length>0)return;if(C2.get(z)===Y)C2.delete(z);Y.manager.stop();let L;try{await Promise.race([Y.manager.tick().catch(()=>{}),new Promise((x)=>{L=setTimeout(x,Y.joinTimeoutMs),L.unref?.()})])}finally{clearTimeout(L)}}}}import{mkdirSync as M0}from"node:fs";import{dirname as E0,join as O0,resolve as R0}from"node:path";var A0="openai-auth-sessions-opencode2.json";function x0(){return O0(L$(),A0)}var S0="sessions",q0=1e4,k0=5000,b0=25;class M${path;options;sessions;frameTurns=new F2;#$=new Set;#Z=new Set;#J=Promise.resolve();#z=!1;constructor($,Z={}){this.path=$;this.options=Z;this.sessions=T$($,Z.uuid??Y2)}get($,Z=Y2){let J=this.sessions.get($);if(!J){let z=Z();J={threadID:z,turnID:Z(),windowID:`${z}:0`},this.sessions.set($,J),this.#Z.delete($),this.#$.add($),this.save()}return J}delete($){this.sessions.delete($),this.frameTurns.forget($),this.#$.delete($),this.#Z.add($),this.save()}save(){if(!this.#z)this.#z=!0,this.#J=this.#J.then(()=>{return this.#z=!1,this.#G()});return this.#J}settled(){return this.#J}async#G(){if(this.#$.size===0&&this.#Z.size===0)return;let $=[...this.#$].flatMap((z)=>{let X=this.sessions.get(z);return X?[[z,X]]:[]}),Z=[...this.#Z],J=null;try{if(M0(E0(this.path),{recursive:!0}),J=await this.#X(),!J)return;let z;try{z=C$(this.path)}catch{z=new Map}await this.options.afterRead?.();for(let X of Z)z.delete(X);for(let[X,Y]of $)z.set(X,Y.threadID);_$(this.path,z)}catch{return}finally{await J?.release().catch(()=>{})}for(let[z,X]of $)if(this.sessions.get(z)===X)this.#$.delete(z);for(let z of Z)if(!this.sessions.has(z))this.#Z.delete(z)}async#X(){let $=performance.now()+(this.options.lockWaitMs??k0);for(;;){let Z=await K$({name:S0,path:this.path,ttlMs:q0});if(Z||performance.now()>=$)return Z;await new Promise((J)=>setTimeout(J,b0))}}}var E$=Symbol.for("@cortexkit/openai-auth/opencode2-codex-sessions"),O$=globalThis,z1=O$[E$]??new Map;O$[E$]=z1;function R$($=x0()){let Z=R0($),J=z1.get(Z);if(!J)J=new M$(Z),z1.set(Z,J);return J}var A$=Symbol.for("cortexkit.openai-auth.v2.commands");function D0(){let $=globalThis;return $[A$]??={locations:new Map},$[A$]}async function y$($,Z){let J=D0(),z=$.location.directory,X={menu:Z,session:$.session},Y=await S$(z),F=await x$(D$,Y.dir,()=>w$({...Y,drain:k$,apply:(V)=>{let L=J.locations.get(z);if(!L)throw Error("The OpenAI menu location was closed");return L.menu.apply(V)}})),H=J.locations.get(z);J.locations.set(z,X),await H?.registration?.dispose(),J.command??={name:"openai",description:"OpenAI account menu",async execute(V){let L=J.locations.values().next().value?.session;if(!L)return;let x=await L.get({sessionID:V.sessionID}),T=J.locations.get(x.location.directory);if(!T||!b$(V.sessionID))return;let v=await T.menu.open(V.sessionID);q$(v,V.sessionID)}};let W=J.command;try{X.registration=await $.command.transform((V)=>{V.add(W)})}catch(V){if(J.locations.get(z)===X)J.locations.delete(z);throw await F.release(),V}let B=!1;return async()=>{if(B)return;if(B=!0,J.locations.get(z)===X)J.locations.delete(z);await F.release(),await X.registration?.dispose()}}var w0="openai-auth-pool-browser",y0="openai-auth-pool-headless",I0="openai-auth-vault",f0="Vault login requires this OpenCode host to be enrolled in the Claustrum vault. Connect to the vault or disconnect this host before trying again.";async function T2($){if(await $.authority()!=="local")throw Error("This host is connected to the credential vault or its enrollment is unreadable; the login was not stored. Disconnect this host from the vault to add a local login.")}function g$($){return{method:{id:I0,type:"oauth",label:"ChatGPT accounts in the vault"},async activate(){if(await I$($.paths,$.name)!=="vault")throw Error(f0)}}}function l$($){let Z=(J,z,X)=>({method:{id:J,type:"oauth",label:z},async authorize(){if($.vault)await T2($.vault);let Y=await $.beginLogin({version:$.version,headless:X});return{url:Y.url,instructions:Y.instructions,mode:"auto",callback:Y.completion}}});return[Z(w0,"ChatGPT (openai-auth pool, browser)",!1),Z(y0,"ChatGPT (openai-auth pool, headless)",!0)]}function G1($){let Z=(J)=>typeof J==="string"?J:"";return N2({type:"oauth",access:Z($.access),refresh:Z($.refresh)})||$.refresh===h$||f$($)}function v0($){if($.accountId)return $.accountId;let Z=$.access?q2($.access):void 0;return Z?k2(Z):void 0}async function u$($,Z,J,z={}){if(z.vault)await T2(z.vault);if(G1(J))throw Error("the credential is not a ChatGPT login (a placeholder or a tombstone); it was not stored");let X=v$($,{rowLocks:(T)=>m$(Z,T)}),Y=await X.read();if(Y.status!=="ready")throw Error(`the account pool cannot be read (${Y.status}); the login was not stored`);let F={type:"oauth",refresh:J.refresh,...J.access!==void 0?{access:J.access}:{},...J.expires!==void 0?{expires:J.expires}:{}},H=v0(J);if(z.vault)await T2(z.vault);let W=H!==void 0?{identity:H}:{};if(z.origin==="import"){let T=Y.rows.find((v)=>H!==void 0&&v.identity===H||v.credential?.type==="oauth"&&v.credential.refresh===J.refresh);if(T)return{id:T.id,operation:"kept"}}let B=Y.rows.filter((T)=>T.type==="oauth"&&!T.invalid),V=H?B.find((T)=>T.identity===H):void 0,L=Y.rows.find((T)=>T.id===y2);if(V)return{id:(await X.replace(V.id,F,W)).id,operation:"replaced"};if(!L){let T=await X.add({id:y2,credential:F,...W,...J.label!==void 0?{label:J.label}:{}});return{id:T.id,operation:T.outcome==="added-disabled"?"added-disabled":"added"}}if(!L.invalid&&!L.credential)return{id:(await X.replace(y2,F,W)).id,operation:"replaced"};let x=await X.add({id:J.id,credential:F,...W,...J.label!==void 0?{label:J.label}:{}});return{id:x.id,operation:x.outcome==="added-disabled"?"added-disabled":x.outcome==="rotated"?"replaced":"added"}}function h0($){let Z=$.itemId!==void 0;switch($.sectionId){case"accounts":return Z?["enable","disable","remove","move"].includes($.actionId):$.actionId==="add";case"routing":return!Z&&["order","mode"].includes($.actionId);case"quota":return $.actionId==="check";case"limits":return Z?$.actionId==="floors":$.actionId==="killswitch";case"session":return!Z&&$.actionId==="clear-pin";case"diagnostics":return!Z&&["logging","dump"].includes($.actionId);case"cache":return!Z&&["enabled","subagents","sustain","window"].includes($.actionId);case"reset":return Z&&["preview","spend","retry"].includes($.actionId);default:return!1}}function d$($){let Z={...$,allowAction:h0,unavailableSections:[]};return{open:(J)=>p$(Z,J),apply:(J)=>{let z=J!==null&&typeof J==="object"?J:{},X=z.values&&typeof z.values==="object"&&!Array.isArray(z.values)?Object.fromEntries(Object.entries(z.values).filter(([,Y])=>Y===null||["string","number","boolean"].includes(typeof Y))):void 0;return c$(Z,{command:"openai",sectionId:typeof z.sectionId==="string"?z.sectionId:"",actionId:typeof z.actionId==="string"?z.actionId:"",...X?{values:X}:{},...z.confirmed===!0?{confirmed:!0}:{},...typeof z.itemId==="string"?{itemId:z.itemId}:{},...typeof z.sessionId==="string"?{sessionId:z.sessionId}:{}})}}}function m0($){if(!i$($.modelID??$.id)){$.enabled=!1;return}let Z=a$($.id);if(Z)$.limit={...Z}}function n$($){return $.model.transform((Z)=>{for(let J of Z.list(o))Z.update(o,String(J.id),(z)=>m0(z))})}class X1{log;pending=new Map;requests=new Map;writing=new Set;constructor($){this.log=$}async safely($){let Z=(async()=>{try{await $()}catch{this.log.warn("request dump failed")}})();this.writing.add(Z);try{await Z}finally{this.writing.delete(Z)}}async captureHttp($,Z){await this.safely(async()=>{if(!V2().dump)return;let J={sessionID:Z.sessionID,accountId:Z.accountId,transport:"http",phase:"http",url:$.url,method:$.method,headers:new Headers($.headers),bodyText:await $.clone().text()};if(this.pending.set($,{attemptId:Z.attemptId,input:J}),this.requests.set(Z.attemptId,$),this.pending.size>512){let z=this.pending.keys().next().value;if(z)this.take(z)}})}take($){let Z=this.pending.get($);if(Z)this.pending.delete($),this.requests.delete(Z.attemptId);return Z?.input}async response($,Z){let J=this.take($);if(J)await this.safely(()=>I2({...J,status:Z}))}async end($,Z){if(Z.status!==void 0||!Z.error)return;let J=this.requests.get($.attemptId),z=J&&this.take(J);if(!z)return;let{reason:X,message:Y}=Z.error,F=Y?`${X}: ${Y}`:X;await this.safely(()=>I2({...z,error:f2(F,J?.headers.get("authorization")?.replace(/^Bearer /,""))}))}async frame($,Z){await this.safely(()=>I2({sessionID:Z.sessionID,accountId:Z.accountId,transport:"websocket",phase:"observed",bodyText:$}))}clear(){this.pending.clear(),this.requests.clear()}async settle(){await Promise.all(this.writing)}}class Y1{counts=new Map;record($,Z){let J=Z.resetCreditsApplicable;this.counts.set($.id,{credentialEpoch:$.credentialEpoch,identity:$.identity,applicable:typeof J==="number"&&Number.isFinite(J)?J:void 0})}applicable($){let Z=this.counts.get($.id);if(!Z||Z.credentialEpoch!==$.credentialEpoch||Z.identity!==$.identity)return;return Z.applicable}}function e$($){return async(Z)=>{let J=Z.credential;if(J.type!=="oauth"||!J.access)throw Error("the row holds no access token to poll with");let z=await o$({accessToken:J.access,fetchImpl:$.fetchImpl,now:$.now,...Z.identity?{accountId:Z.identity}:{},accountKey:Z.id,...$.logger?{logger:$.logger}:{}});return $.counts.record(Z,z),r$(z,$.now(),!0)}}function $Z($){let{source:Z,counts:J,now:z}=$,X=async(B)=>{let V=await Z.rowAccess(B,await $.storage());if(!V?.row)throw new s$("unknown_account",`${B==="main"?"Main":"Fallback"} account ${B} was not found.`);return t$(B,V)},Y=async(B)=>{if($.authority&&await $.authority()!=="local")return{account:B,ok:!1,error:"local accounts are not polled while this host is connected to the vault"};let[V]=await Z.pollRows(await $.storage(),{ids:[B]});if(!V)return{account:B,ok:!1,error:"targeted quota refresh returned no result"};return{account:V.id,ok:V.ok,...V.error!==void 0?{error:V.error}:{}}},F=(B)=>Z.peek().rows.find((V)=>V.id===B),H=(B)=>{let V=F(B);if(!V)return null;let L=K2(V.quota)??{},x=J.applicable(V),T=Math.max(0,...[L.primary?.checkedAt,L.secondary?.checkedAt].filter((v)=>typeof v==="number"));return{quota:{...L,...x!==void 0?{resetCreditsApplicable:x}:{}},checkedAt:T,refreshAfter:T,...V.identity!==void 0?{accountId:V.identity}:{}}};return{resolveResetTarget:X,refreshResetTargetQuota:Y,quotaManager:{isRateLimited:(B)=>{let V=F(B);if(!V)return!1;let L=Z.rateLimitMarks([V]).get(V.id);return L!==void 0&&L>z()},getMain:()=>H("main"),getFallback:(B)=>H(B)}}}import{resolve as JZ}from"node:path";var g0=1024;class Q1{pins=new Map;listeners=new Set;limit;constructor($=g0){this.limit=Math.max(1,$)}get($){return this.pins.get($)?.accountId}forget($){this.pins.delete($);for(let Z of this.listeners)Z($)}subscribe($){return this.listeners.add($),()=>{this.listeners.delete($)}}snapshot(){return new Map(this.pins)}get size(){return this.pins.size}set($,Z){this.pins.delete($),this.pins.set($,Z);for(let J of this.listeners)J($,Z);while(this.pins.size>this.limit){let J=this.pins.keys().next().value;if(J===void 0)break;this.forget(J)}}place($){return ZZ(this.pins,$,(Z,J)=>this.set(Z,J))}}var zZ=Symbol.for("@cortexkit/openai-auth/opencode2-pins"),GZ=globalThis,j1=GZ[zZ]??new Map;GZ[zZ]=j1;function XZ($){let Z=JSON.stringify([JZ($.configPath),JZ($.statePath)]),J=j1.get(Z);if(!J)J=new Q1,j1.set(Z,J);return J}import{statSync as l0}from"node:fs";import{resolve as u0}from"node:path";function NZ($){return $.map((Z)=>{try{let J=l0(Z);return`${J.ino}:${J.size}:${J.mtimeMs}:${J.ctimeMs}`}catch{return"?"}}).join("|")}function V1($){return NZ([$.vault.paths.tokenPath,$.vault.paths.statePath])}function YZ($){return NZ([$.paths.configPath,$.paths.statePath,$.vault.paths.rosterPath])+V1($)}class FZ{file;observationIntervalMs;producers=new Set;subscriptions=new Map;observations=new Map;chain=Promise.resolve();timer;constructor($,Z){this.file=$;this.observationIntervalMs=Z}add($){this.producers.add($),this.observations.set($,{stamp:YZ($),roster:$.vault.snapshot()});let Z=$.source.subscribe(()=>{this.publish($)}),J=this.subscriptions.get($.pins);if(!J){let z=new Set;J={producers:z,stop:$.pins.subscribe((X,Y)=>{let F=z.values().next().value;if(F)this.publish(F,{sessionId:X,pin:Y,accountId:Y?.accountId,route:"sticky-balanced"})})},this.subscriptions.set($.pins,J)}return J.producers.add($),this.timer??=setInterval(()=>{for(let z of this.producers){let X={stamp:YZ(z),roster:z.vault.snapshot()},Y=this.observations.get(z);if(X.stamp!==Y?.stamp||X.roster!==Y?.roster)this.observations.set(z,X),this.publish(z)}},this.observationIntervalMs),this.timer.unref?.(),()=>{if(Z(),this.producers.delete($),this.observations.delete($),J.producers.delete($),!J.producers.size)J.stop(),this.subscriptions.delete($.pins);if(!this.producers.size)clearInterval(this.timer),this.timer=void 0}}publish($,Z){return this.chain=this.chain.then(async()=>{if(!this.producers.has($))return;let z=await $.vault.authority()!=="local",X=V1($),Y=()=>this.producers.has($)&&$.vault.enrolled()===z&&V1($)===X,F=await Z2($.paths),H=z?UZ($.vault.snapshot()?.rows??[],new Set($.vault.routes().map((B)=>B.id)),F,Date.now()):HZ((await $.source.sidebarView()).rows,F,Date.now());if(await jZ(H,this.file,{canWrite:Y}),!Y()||!Z)return;let W=H.vaultAccounts??H.fallbacks;if(Z.accountId===void 0){await BZ(Z.sessionId,W,this.file,{canWrite:Y});return}if(Z.pin){let B=Date.now();await WZ({sessionId:Z.sessionId,assignment:{accountId:Z.pin.accountId,wireAccountId:Z.pin.wireIdentity,inputBytes:Z.pin.inputBytes??0,quotaCheckedAt:Z.pin.quotaCheckedAt,assignedAt:B,lastSeenAt:B},validPinnedAccountIds:[...z?[]:["main"],...W.filter((V)=>V.enabled).map((V)=>V.id)]},this.file)}await VZ({sessionId:Z.sessionId,activeId:Z.accountId,route:Z.route??H.route,updatedAt:Date.now()},W,this.file,{canWrite:Y})}).catch(()=>{J2("opencode2").warn("sidebar publication failed")}),this.chain}settled(){return this.chain}get empty(){return this.producers.size===0}}var PZ=Symbol.for("@cortexkit/openai-auth/opencode2-sidebar-publishers"),KZ=globalThis,_2=KZ[PZ]??new Map;KZ[PZ]=_2;function LZ($,Z=QZ(),J=2000){let z=u0(Z),X=_2.get(z);if(!X)X=new FZ(z,J),_2.set(z,X);let Y=X,F=Y.add($),H=!1;for(let[W,B]of $.pins.snapshot())Y.publish($,{sessionId:W,pin:B,accountId:B.accountId,route:"sticky-balanced"});return{publish:()=>Y.publish($),route:(W,B,V)=>{Y.publish($,{sessionId:W,accountId:B,route:V})},async release(){if(H)return;if(H=!0,F(),await Y.settled(),Y.empty&&_2.get(z)===Y)_2.delete(z)}}}var h2="cortexkit-openai-auth",d0=5000;async function CZ($,Z,J,z=new P2,X,Y,F){let H=new X1(J),W=new p0,B=new Map,V=new Map,L=(S)=>{V.delete(S);for(let y of B.keys())if(y.startsWith(`${S}:`))B.delete(y)},x=(S)=>{F?.(S.sessionID),Y?.send(S.sessionID,S.frame)},v=await i2({session:{hook:(S,y,a)=>$.session.hook(S,async(I)=>{let j=S==="http.request"?I:void 0,K=S==="experimental.ws.handshake"?I:void 0,M=(j?j.request.headers:K?new Headers(K.headers):void 0)?.get("authorization")===`Bearer ${t(Z.providerID)}`,A={};if(K)B.delete(`${K.sessionID}:${K.kind}`);try{await W.run(A,()=>y(I))}catch(N){if(M&&!(N instanceof n))throw RZ(N);throw N}if(j&&M&&A.attempt){let N=j.request.headers.get("thread-id");if(N)j.request.headers.set("session-id",N)}if(j&&M&&A.attempt)await H.captureHttp(j.request,A.attempt);if(j&&M&&A.attempt)await X?.({sessionID:j.sessionID,kind:j.kind,request:j.request,attempt:A.attempt});if(K&&M&&A.attempt)K.headers["session-id"]=z.get(K.sessionID).threadID;if(S==="experimental.ws.send"){let N=I,_=B.get(`${N.sessionID}:${N.kind}`);if(_)await H.frame(N.frame,_.attempt);if(_&&N.kind==="primary")x(N)}if(j||K){let N=j??K;if(!N)return;let k=(j?j.request.headers:new Headers(N.headers)).get("authorization")?.replace(/^Bearer /,"");if(M&&k)V.set(N.sessionID,k);else V.delete(N.sessionID);if(K){let E=`${K.sessionID}:${K.kind}`;if(M&&k&&A.attempt)B.set(E,{bearer:k,attempt:A.attempt,url:K.url,headers:new Headers(Object.entries(K.headers).filter(([l])=>["chatgpt-account-id","x-opencode-parent-session-id","x-parent-session-id"].includes(l.toLowerCase())))});else B.delete(E)}if(V.size>512){let E=V.keys().next().value;if(E)V.delete(E)}if(B.size>512){let E=B.keys().next().value;if(E)B.delete(E)}}else if(S==="experimental.ws.receive"){let N=I,_=B.get(`${N.sessionID}:${N.kind}`);if(_){if(z.frameReceived(N.sessionID,N.frame),N.kind==="primary"){let k;if(Y?.receive(N.sessionID,N.frame,(E)=>{k=E}),k)try{let E=k1(k,_.url,_.headers,z);if(E)await X?.({sessionID:N.sessionID,kind:"primary",request:E,attempt:_.attempt})}catch(E){J.warn("cachekeep WebSocket capture failed",{error:E instanceof Error?E.message:String(E)})}}N.frame=AZ(N.frame,_.bearer)}}else if(S==="retry"){let N=I,_=V.get(N.sessionID);if(_)Object.assign(N.error,{message:f2(N.error.message,_)})}},a)},event:{subscribe:(S)=>async function*(){for await(let y of $.event.subscribe(S)){if(y.type==="session.deleted")L(y.data.sessionID);yield y}}()}},{...Z,rewriteRequest:async(S)=>{let y=W.getStore();if(y)y.attempt=S.attempt;return Z.rewriteRequest?.(S)},rewriteHandshakeURL:(S)=>{let y=W.getStore();if(y)y.attempt=S.attempt;return Z.rewriteHandshakeURL?.(S)},onAttemptEnd:async(S,y)=>{await H.end(S,y),await Z.onAttemptEnd?.(S,y)},rewriteResponse:async(S)=>{await H.response(S.request,S.response.status);let y=await Z.rewriteResponse?.(S)??S.response;return xZ(y,S.request.headers.get("authorization")?.replace(/^Bearer /,""),"event-stream")}},{gateOnPlaceholder:{credential:(S)=>{let y=S.get("authorization");return y?.startsWith("Bearer ")?y.slice(7):void 0}},logger:{warn:(S,y)=>J.warn(S,{data:y})}}),d=v.dispose;return{...v,dispose:async()=>{V.clear(),B.clear(),await d(),await H.settle(),H.clear()}}}function U1($={}){return{id:h2,setup:(Z)=>i0(Z,$)}}async function i0($,Z={}){let G2=[];try{let J=J2("opencode2");let z=J2("quota");let X=Z.paths??(()=>qZ(SZ()));let Y=await Z2(X());let F=Y?.logging?.level;if(F&&typeof F==="string")_Z(F);let H=Z.fetch??fetch;let W=Z.now??Date.now;let B=Z.version??yZ;let V=Z.poolMigration??lZ;if(!V&&!B2(X().configPath)){J.info("openai-auth stands aside on OpenCode 2: this install has not moved into the account pool and the migration is switched off, so OpenCode 2 serves its own ChatGPT login");let C=(r)=>{throw new n({kind:"no-account",providerID:o,sessionID:r.sessionID,requestKind:r.kind,message:b2})},f=await CZ($,{providerID:o,chooseAccount:C,accountHeaders:C},J);return()=>f.dispose()}let L=Z.vault?.firstRosterWaitMs??fZ;let x=gZ({host:"opencode",stateDir:Z.vault?.stateDir??OZ(X().statePath),reservedRouteIds:()=>I.peek().rows.map((C)=>C.id),...Z.vault?.connectionFile?{connectionFile:Z.vault.connectionFile}:{},...Z.vault?.connectScoped?{connectScoped:Z.vault.connectScoped}:{},...Z.vault?.connectEnrollment?{connectEnrollment:Z.vault.connectEnrollment}:{},...Z.vault?.pollIntervalMs!==void 0?{pollIntervalMs:Z.vault.pollIntervalMs}:{},fetchImpl:()=>H},X());let T=x.vault;let v=!1;let d=!1;const S=v2(G2,{[Symbol.dispose](){if(!v)x.release()}},0);await T.authority();let y=x.firstRoster;let a=new Y1;let I=new vZ({paths:X,refreshProvider:async(C)=>{let f=await EZ({refreshToken:C.refresh,fetchImpl:H,now:W}),r=MZ({id_token:"",access_token:f.access,refresh_token:f.refresh});return{...f,...r?{identity:r}:{}}},pullQuota:e$({fetchImpl:H,now:W,counts:a,logger:z}),now:W,vaultIdentities:()=>T.identities(),vaultMode:()=>T.enrolled(),vaultAuthority:()=>T.authority(),vaultFirstRoster:y,vaultFirstRosterBackgroundWaitMs:L,log:J2("pool")});await I.load();let j=Z.heartbeat===!1?void 0:await mZ({version:B,logger:J2("heartbeat")});let K=Z.fence??(()=>wZ({currentVersion:B}));let R=Z.slot??uZ();let M=async()=>kZ(X(),await R.get({path:{id:"openai"}}));let A=!1;let N=V?hZ({paths:X,slot:R,version:B,fence:K,runDeps:{vaultServes:()=>T.serves()},paused:async()=>await T.authority()!=="local",migrate:async(C)=>{let f=await bZ(C);if(A=f.status==="refused",!d)await I.load();return f},adopt:async(C)=>{if(d)return{status:"retry",reason:"unsettled"};if(!await W1(y,L))return{status:"retry",reason:"vault-roster-pending"};if(d)return{status:"retry",reason:"unsettled"};let f=await DZ(C);if(!d)await I.load();return f}}):void 0;N?.start();x.start();let _=XZ(X());let k=LZ({paths:X(),source:I,pins:_,vault:T},Z.sidebarStateFile,Z.sidebarObservationIntervalMs);const E=v2(G2,{[Symbol.dispose](){if(!v)k.release()}},0);k.publish();let l=Z.codex??new P2(void 0,void 0,R$());let i=H$(Y);let c=w2(X());let m=P$(X(),{source:I,storage:()=>Z2(X()),vault:T,accounts:t2(X()),settings:()=>i,parentOf:async(C)=>(await $.session.get({sessionID:C}))?.parentID??void 0,fetch:H,log:J2("cachekeep")},{now:W,codexResponsesUrl:V2().codexApiEndpoint,...Z.cacheKeep});const p=v2(G2,{[Symbol.dispose](){if(!v)m.release()}},0);let b=z$({codex:l,onRoute:k.route,source:I,slotPlaceholderWithoutMain:M,storage:()=>Z2(X()),pins:_,sessionAccounts:t2(X()),vault:T,awaitVaultRoster:async()=>{await W1(T.awaitRequestRoster(),IZ)},responsesLite:()=>V2().responsesLite,codexEndpoint:()=>V2().codexApiEndpoint,now:W,log:J});let u=await CZ($,b.adapter,J,l,(C)=>m.capture(C),c,(C)=>m.forget(C));b.attach(u);let g=async(C)=>{if(await T2(T),B2(X().configPath))return;if(await N?.idle(),B2(X().configPath))return;if(A&&!G1(C)&&(await K()).open){await I.poolStore().initialize();return}throw Error("OpenAI accounts move to the shared account pool once every OpenCode process on this machine runs this version of openai-auth; the login was not stored. Update or close the older processes and sign in again.")};let z2=async(C)=>{await g(C);let f=await u$(I.poolStore(),X(),C,{vault:T});if(!B2(X().configPath))await N?.requestAdoption();await I.load(),J.info("ChatGPT login stored in the account pool",f)};let W2=await p2($,{integrationID:o,methods:l$({beginLogin:Z.beginLogin??B1,version:B,vault:T}),onLogin:(C)=>z2(C),label:"ChatGPT (openai-auth account pool)",vault:g$(T)});let M2=await n$($);if(Z.controlPlane&&(!$.command||!$.location))throw Error("OpenCode 2 control plane requires command and location APIs");let U2=$.command&&$.location?await y$({session:$.session,command:$.command,location:$.location},Z.controlPlane??d$({...$Z({source:I,storage:()=>Z2(X()),counts:a,now:W,authority:()=>T.authority()}),fetchImpl:H,now:W,randomUUID:c0,accountStoragePath:X().configPath,accountStatePath:X().statePath,packageVersion:B,loadAccounts:Z2,store:()=>I.poolStore(),migration:async()=>{if(B2(X().configPath))return{migrated:!0};let C=await K();return{migrated:!1,blockers:C.open?[]:C.blockers}},beginAccountLogin:Z.beginLogin??B1,refreshAllQuota:async()=>(await I.pollRows(await Z2(X()))).map((C)=>({...C,account:C.id})),getStickyRouting:async(C)=>_.get(C),cacheKeepManager:m.manager,setCacheKeepEnabled:(C)=>m.configure({enabled:C}),setCacheKeepSubagents:(C)=>m.configure({subagents:C}),setCacheKeepSustain:(C)=>m.configure({sustain:C}),setCacheKeepWindow:(C)=>m.configure({window:C}),afterWrite:()=>I.load(),refreshSidebar:()=>k.publish(),clearStickyRouting:async(C)=>{let f=_.get(C)!==void 0;return _.forget(C),f},vault:T})):void 0;let Q2=new AbortController;(async()=>{try{for await(let C of $.event.subscribe({signal:Q2.signal}))if(C.type==="session.deleted")b.forgetSession(C.data.sessionID),m.forget(C.data.sessionID),c.forget(C.data.sessionID)}catch(C){if(!Q2.signal.aborted)J.warn("stopped listening for session deletion",{error:C instanceof Error?C.message:String(C)})}})();v=!0;return async()=>{d=!0,Q2.abort();let C=m.release();await U2?.(),N?.dispose(),I.dispose(),await k.release(),await Promise.allSettled([u.dispose(),W2.dispose(),M2.dispose()]);let f;try{await Promise.race([Promise.all([N?.idle(),I.settled(),l.store?.settled(),C]),new Promise((r)=>{f=setTimeout(r,d0),f.unref?.()})])}finally{clearTimeout(f),x.release(),await j?.release()}}}catch(m2){var g2=m2,l2=1}finally{TZ(G2,g2,l2)}}var a0=U1(),F6={id:h2,setup:a0.setup,server:pZ.server};export{F6 as default,U1 as createOpenAIAuthPlugin,h2 as OPENAI_AUTH_PLUGIN_ID};
|
|
3
|
+
`)}}function c2($,Z){let J=new TextDecoder,z="",X=(N)=>{let H=dZ(N);if(!H)return;try{$(H)}catch(W){Z(W)}},Y=()=>{for(;;){let N=/\r?\n\r?\n/.exec(z);if(!N)return;let H=z.slice(0,N.index);z=z.slice(N.index+N[0].length),X(H)}};return new TransformStream({transform(N,H){H.enqueue(N),z+=J.decode(N,{stream:!0}),Y()},flush(){if(z+=J.decode(),Y(),z.trim()!=="")X(z);z=""}})}var C1=512,V2="x-common-auth-attempt",Y2=($,Z)=>JSON.stringify([$,Z]),Z2=($)=>({providerID:$.model.providerID,modelID:$.model.id,sessionID:$.sessionID,agent:$.agent,kind:$.kind});function iZ($){let Z=$.headers;return typeof Z==="object"&&Z!==null}function aZ($,Z){let J=$.getReader();return new ReadableStream({async pull(z){let X;try{X=await J.read()}catch(Y){Z({reason:"failed",message:Y instanceof Error?Y.message:String(Y)}),z.error(Y);return}if(X.done)Z(),z.close();else z.enqueue(X.value)},async cancel(z){Z({reason:"cancelled",...z===void 0?{}:{message:String(z)}}),await J.cancel(z)}})}function d2($,Z){for(let[J,z]of Object.entries(Z)){let X=J.toLowerCase();for(let Y of Object.keys($))if(Y.toLowerCase()===X)delete $[Y];if(z!==null)$[J]=z}}function nZ($,Z){for(let[J,z]of Object.entries(Z))if(z===null)$.delete(J);else $.set(J,z)}async function i2($,Z,J={}){let{providerID:z}=Z,X=J.gateOnPlaceholder,Y=(G)=>X===void 0||X.credential(G)===$2(z),N=J.logger,H=Math.max(1,J.maxRecords??C1),W=[...J.hostCredentials??[$2(z)],...X?[$2(z)]:[]].filter((G)=>G!==""),B=new Map,V=new WeakMap,K=new Map,x=new Set,_=new Map,h=!1,d=!1,S=new Map,y=0,n=!1,I=new Map,f=(G,Q)=>{try{N?.warn(G,Q)}catch{}},j=(G)=>G instanceof Error?G.message:String(G),T=async(G,Q)=>{let U=S.get(G);if(!U||U.size===0)return;await Promise.all([...U].map(async(F)=>{try{await F(Q)}catch(q){f("opencode2 auth listener threw; the request is unaffected",{event:G,error:j(q)})}}))},E=async(G,Q)=>{try{await Z.onAttemptEnd?.(G,Q)}catch(U){f("opencode2 auth onAttemptEnd threw; the request is unaffected",{attemptId:G.attemptId,error:j(U)})}},M=(G,Q)=>{if(G.ended||!G.attempt)return;let U={...G.status===void 0?{}:{status:G.status},outputStarted:G.outputStarted,...G.limit?{limit:G.limit.signal}:{},...Q?{error:Q}:{}};if(Q)G.endError=Q;G.ended=E(G.attempt,U)},P=(G,Q)=>M(G,{reason:"abandoned",message:Q}),L=(G)=>[...B.values()].filter((Q)=>Q.key===G),O=(G)=>L(G).at(-1),A=(G)=>{if(B.delete(G.id),!L(G.key).length)K.delete(G.key)},w=(G)=>{B.set(G.id,G);while(B.size>H){let Q=B.values().next().value;if(Q===void 0)break;P(Q,"dropped to keep the record bound"),A(Q)}},p=(G)=>G.accountId===void 0?void 0:{...G.scope,accountId:G.accountId},a=(G,Q)=>new o({kind:"no-account",providerID:z,sessionID:G.sessionID,requestKind:G.kind,...Q===void 0?{}:{message:Q}}),l=(G)=>{I.get(G)?.clear(),I.delete(G)},i=async(G,Q)=>{let U=()=>a(G,`${z} ${G.kind} request has no account: its auth selection was revoked by session forgetting or installation disposal`);if(n)throw U();let F=I.get(G.sessionID);if(!F)F=new Set,I.set(G.sessionID,F);let q={};F.add(q);let D=()=>{if(!F.has(q))throw U()};try{return await Q(D)}finally{if(F.delete(q),F.size===0&&I.get(G.sessionID)===F)I.delete(G.sessionID)}},c=(G,Q)=>{for(let[U,F]of Q)if(W.some((q)=>F.includes(q)))throw new o({kind:"host-credential-on-wire",providerID:z,sessionID:G.sessionID,requestKind:G.kind,message:`${z} ${G.kind} request still carries the host's placeholder credential in ${U}; the adapter's account headers must replace it`})},k=(G)=>{for(let Q of L(G))if(Q.ended||!Q.attempt)A(Q);else if(Q.transport==="ws"||Q.judged)P(Q,"a newer attempt of its session and kind began"),A(Q)},g=async(G,Q,U,F)=>{let q=Y2(G.sessionID,G.kind),D=K.get(q);K.delete(q);let R=D?.accountId??O(q)?.accountId;k(q);let b={...G,...R===void 0?{}:{previousAccountId:R},...D?.rerouteFrom===void 0?{}:{rerouteFrom:D.rerouteFrom}},m=await Z.chooseAccount(b);U();let e={},F1;if(m!==void 0){let E2=await Z.accountHeaders({...G,accountId:m});if(U(),iZ(E2))e=E2.headers,F1=E2.attempt;else e=E2}let P1=`attempt-${++y}`,H2={id:P1,key:q,scope:G,accountId:m,headers:e,attempt:m===void 0?void 0:{...G,accountId:m,attemptId:P1,transport:F,data:F1},...F===void 0?{}:{transport:F},outputStarted:!1};if(w(H2),H2.attempt)T("select",{...G,accountId:H2.attempt.accountId,hook:Q,...b.previousAccountId===void 0?{}:{previousAccountId:b.previousAccountId},...b.rerouteFrom===void 0?{}:{rerouteFrom:b.rerouteFrom},handle:H2.attempt});return H2},u=async(G,Q,U,F,q)=>{let D=Y2(G.sessionID,G.kind),R=F===void 0?void 0:B.get(F);if(R?.key!==D)R=void 0;if(!R){if(R=O(D),L(D).filter((m)=>m.transport===void 0&&!m.ended).length>1&&!d)d=!0,f("opencode2 auth tied a send without its attempt mark to the newest of several waiting attempts",{sessionID:G.sessionID,kind:G.kind})}if(!R||R.transport!==void 0||R.ended)R=await g(G,Q,q,U);else if(R.transport=U,R.attempt)R.attempt.transport=U;if(U==="ws"){for(let b of L(D))if(b!==R&&b.transport==="ws")P(b,"a newer attempt of its session and kind went out over WebSocket")}return R},s=async(G,Q)=>{try{return await Q()}catch(U){throw M(G,{reason:"failed",message:j(U)}),U}},M2=(G,Q)=>{let U=L(Y2(G,Q)).filter((F)=>F.transport==="ws").at(-1);return U?.attempt!==void 0&&!U.ended?U:void 0},U2=(G,Q,U)=>{let F=p(G);if(!F||!G.attempt||G.limit)return;G.limit={signal:Q,delivered:T("limit",{...F,via:U,limit:Q,outputStarted:G.outputStarted,handle:G.attempt})}},j2=(G,Q,U,F)=>{let q=p(G);if(!q||!G.attempt)return;T("quota",{...q,transport:Q,...F===void 0?{}:{status:F},quota:U,handle:G.attempt})},X2=(G,Q,U,F)=>{let q=G.attempt;if(!q)return;let D=Z.inspectEvent?.(F===void 0?{transport:Q,data:U,attempt:q}:{transport:Q,data:U,event:F,attempt:q});if(!D)return;if(D.quota!==void 0)j2(G,Q,D.quota);if(D.outputStarted)G.outputStarted=!0;if(D.limit)U2(G,D.limit,Q);if(D.error!==void 0)M(G,{reason:"failed",message:D.error});else if(D.done)M(G)},m2=(G,Q)=>{let U=G.attempt;if(!U||Q.accountId===G.accountId)return;if(U.reboundFrom??=U.accountId,U.accountId=Q.accountId,"data"in Q)U.data=Q.data;G.accountId=Q.accountId},g2=(G)=>!G.attempt||G.endError!==void 0||G.status!==void 0&&G.status>=400,l2=(G)=>{let Q=[...B.values()].filter((b)=>b.scope.sessionID===G),U=Q.filter((b)=>b.limit&&!b.rerouted).at(-1);if(U)return U;let F=Q.filter((b)=>b.scope.kind==="primary"),q=F.length>0?F:Q;if(q.length<=1)return q[0];let D=q.filter((b)=>!b.judged&&g2(b)).at(-1);if(D)return D;let R=q.filter((b)=>b.attempt&&!b.ended);if(R.length>1)return"ambiguous";return R[0]??q.at(-1)},C={providerID:z},v=[];v.push(await $.session.hook("model.request",(G)=>{if(X)return;return i(Z2(G),async(Q)=>{let U=await g(Z2(G),"model.request",Q);if(Q(),U.accountId===void 0)throw a(U.scope);d2(G.headers,{...U.headers,[V2]:U.id})})},C)),v.push(await $.session.hook("http.request",(G)=>{if(X){let Q=Y(G.request.headers);if(_.set(G.sessionID,Q),!Q)return}return i(Z2(G),async(Q)=>{let U=G.request.headers.get(V2)??void 0,F=X?await g(Z2(G),"http.request",Q,"http"):await u(Z2(G),"http.request","http",U,Q);Q();let q=p(F),D=F.attempt;if(!q||!D)throw a(F.scope);await s(F,async()=>{let R=G.request;if(Z.rewriteRequest){if(U!==void 0){let e=new Headers(R.headers);e.delete(V2),R=new Request(R,{headers:e})}R=await Z.rewriteRequest({...q,request:R,attempt:D})??R,Q()}let b=new Headers(R.headers);b.delete(V2),nZ(b,F.headers),c(F.scope,b.entries());let m=new Request(R,{headers:b});V.set(m,F),G.request=m})})},C)),v.push(await $.session.hook("http.response",async(G)=>{let Q=V.get(G.request);if(!Q){if(X)return;if(!h)h=!0,f("opencode2 auth dropped an http.response whose request it did not produce",{sessionID:G.sessionID,kind:G.kind});return}let U=G.response;if(Z.answeredBy&&Q.attempt){let b=Q.attempt,m=await s(Q,async()=>Z.answeredBy?.({request:G.request,response:U,attempt:b}));if(m)m2(Q,m)}let F=p(Q),q=Q.attempt;if(!F||!q)return;Q.status=U.status;let D=Z.quotaFromHeaders?.(U.headers,U.status,q);if(D!==void 0)j2(Q,"http",D,U.status);if(!U.ok&&Z.limitFromResponse){let b=await Z.limitFromResponse({status:U.status,headers:U.headers,body:()=>U.clone().text(),attempt:q});if(b)U2(Q,b,"http")}if(!U.ok||!U.body)M(Q);let R=U;if(U.body&&(Z.inspectEvent||Z.onAttemptEnd)){let b=U.body;if(Z.inspectEvent)b=b.pipeThrough(c2((m)=>X2(Q,"http",m.data,m.event),(m)=>f("opencode2 auth event inspection threw",{error:j(m)})));R=new Response(aZ(b,(m)=>M(Q,m)),{status:U.status,statusText:U.statusText,headers:U.headers})}if(Z.rewriteResponse)R=await Z.rewriteResponse({...F,request:G.request,response:R,attempt:q})??R;if(R!==U)G.response=R},C)),v.push(await $.session.hook("experimental.ws.handshake",(G)=>{if(X){let Q=Y(new Headers(G.headers)),U=Y2(G.sessionID,G.kind);if(_.set(G.sessionID,Q),x.delete(U),!Q)return}return i(Z2(G),async(Q)=>{let U;for(let R of Object.keys(G.headers)){if(R.toLowerCase()!==V2)continue;U??=G.headers[R],delete G.headers[R]}let F=X?await g(Z2(G),"experimental.ws.handshake",Q,"ws"):await u(Z2(G),"experimental.ws.handshake","ws",U,Q);Q();let q=p(F),D=F.attempt;if(!q||!D)throw a(F.scope);await s(F,async()=>{d2(G.headers,F.headers);let R=Z.rewriteHandshakeURL?.({...q,url:G.url,attempt:D});if(R!==void 0)G.url=R;if(c(F.scope,Object.entries(G.headers)),X)x.add(F.key)})})},C));let t=Z.rewriteWebSocketFrame?.bind(Z);if(t)v.push(await $.session.hook("experimental.ws.send",async(G)=>{let Q=Z2(G);if(X&&!x.has(Y2(Q.sessionID,Q.kind)))return;let U=M2(Q.sessionID,Q.kind),F=await t({...Q,attempt:U?.attempt,frame:G.frame});if(F!==void 0)G.frame=F},C));v.push(await $.session.hook("experimental.ws.receive",(G)=>{if(X&&!x.has(Y2(G.sessionID,G.kind)))return;let Q=M2(G.sessionID,G.kind);if(!Q)return;try{X2(Q,"ws",G.frame)}catch(U){f("opencode2 auth frame inspection threw",{error:j(U)})}},C)),v.push(await $.session.hook("retry",async(G)=>{if(X&&_.get(G.sessionID)!==!0)return;let Q=l2(G.sessionID);if(!Q)return;let U=G.decision;if(Q==="ambiguous"){await T("retry",{sessionID:G.sessionID,attempt:G.attempt,reason:"host-decides",hostDecision:U,decision:U});return}let F=Q;await i(F.scope,async(q)=>{F.judged=!0;let D=U,R,b,m=F.attempt;if(F.accountId===void 0||!m)D={retry:!1},R="no-account";else if(F.outputStarted)D={retry:!1},R="output-started";else{if(!F.limit){let e=Z.limitFromError?.(G.error,m);if(e)U2(F,e,"error")}if(F.ended)await F.ended,q();if(F.limit)await F.limit.delivered,q(),F.rerouted=!0,b={accountId:F.accountId,limit:F.limit.signal},D={retry:!0,delay:0},R="reroute";else R="host-decides"}if(G.decision=D,D.retry&&F.accountId!==void 0)K.set(F.key,{sessionID:F.scope.sessionID,accountId:F.accountId,...b===void 0?{}:{rerouteFrom:b}});await T("retry",{sessionID:G.sessionID,...F.accountId===void 0?{}:{accountId:F.accountId},kind:F.scope.kind,attempt:G.attempt,reason:R,hostDecision:U,decision:D,...m===void 0?{}:{handle:m}})})},C));let H1=(G)=>{l(G),_.delete(G);for(let Q of x)if(JSON.parse(Q)[0]===G)x.delete(Q);for(let Q of[...B.values()]){if(Q.scope.sessionID!==G)continue;P(Q,"its session was forgotten"),B.delete(Q.id)}for(let[Q,U]of K)if(U.sessionID===G)K.delete(Q)},u2=new AbortController,N1=$.event;if(N1)(async()=>{try{for await(let G of N1.subscribe({signal:u2.signal}))if(G.type==="session.deleted")H1(G.data.sessionID)}catch(G){if(!u2.signal.aborted)f("opencode2 auth stopped listening for session deletion",{error:j(G)})}})();return{on(G,Q){let U=S.get(G);if(!U)U=new Set,S.set(G,U);let F=Q;return U.add(F),()=>{U.delete(F)}},accountFor(G,Q){return O(Y2(G,Q))?.accountId},forgetSession:H1,get size(){return B.size},async dispose(){if(n)return;n=!0;for(let G of I.keys())l(G);u2.abort();for(let G of B.values())P(G,"the installation was disposed");B.clear(),K.clear(),x.clear(),_.clear(),S.clear(),await Promise.all(v.map(async(G)=>{try{await G.dispose()}catch(Q){f("opencode2 auth hook did not dispose cleanly",{error:j(Q)})}}))}}}import{createHash as oZ}from"node:crypto";var rZ=1024,sZ=($)=>typeof $==="object"&&$!==null&&!Array.isArray($),T1=($)=>_1($,"user"),tZ=($)=>sZ($)&&($.role==="assistant"||typeof $.type==="string"&&$.type!=="message"&&$.type!=="configuration_update");function eZ($){return oZ("sha256").update(JSON.stringify($)).digest("hex")}class F2{runtime;maxSessions;#$=new Map;constructor($,Z=rZ){this.runtime=$;this.maxSessions=Z}advance($,Z,J=this.runtime){let z=this.#$.get($),X=Array.isArray(Z.input)?Z.input:[],Y=X.filter(T1),N=X.findLastIndex(T1),H=N<0?void 0:eZ(X[N]),W=typeof Z.previous_response_id==="string"&&Z.previous_response_id.length>0,B,V,K;if(W)B=Y.length>0,V=H??z?.fingerprint,K=z?.userCount===void 0?void 0:z.userCount+Y.length;else{V=H,K=Y.length;let _=N>=0&&N>X.findLastIndex(tZ),h=z!==void 0&&!z.completed&&z.fingerprint===V&&z.userCount===K;B=_&&!h}let x=B||!z?{turnID:(J?.uuid??Q2)(),turnStartedAt:(J?.now??Date.now)()}:{turnID:z.turnID,turnStartedAt:z.turnStartedAt};return this.#Z($,{...x,completed:!1,fingerprint:V,userCount:K}),x}completed($){let Z=this.#$.get($);if(Z)this.#Z($,{...Z,completed:!0})}get($){return this.#$.get($)}forget($){this.#$.delete($)}#Z($,Z){this.#$.delete($),this.#$.set($,Z);while(this.#$.size>this.maxSessions){let J=this.#$.keys().next().value;if(J===void 0)break;this.#$.delete(J)}}}function a2($,Z){return{threadID:$.threadID,windowID:$.windowID,turnID:Z.turnID,turnStartedAt:Z.turnStartedAt}}var M1=Symbol.for("@cortexkit/openai-auth/opencode2/codex-installation");function $0(){let $=globalThis;return $[M1]??=crypto.randomUUID(),$[M1]}class P2{runtime;store;sessions;frameTurns;installationID;constructor($,Z,J){this.runtime=$;this.store=J;this.installationID=Z??$0(),this.sessions=J?.sessions??new Map,this.frameTurns=J?.frameTurns??new F2}get($){let Z=this.runtime?.uuid??Q2;if(this.store)return this.store.get($,Z);let J=this.sessions.get($);if(!J){let z=Z();J={threadID:z,turnID:Z(),windowID:`${z}:0`},this.sessions.set($,J)}return J}advanceFrame($,Z){return this.frameTurns.advance($,Z,this.runtime)}frameReceived($,Z){if(!Z.includes("response.completed"))return;if(O2(Z)?.type==="response.completed")this.frameTurns.completed($)}forget($){if(this.store)this.store.delete($);else this.sessions.delete($),this.frameTurns.forget($)}}var n2={version:E1,"user-agent":O1,originator:"codex_exec"};var Z0=1024,J0=/(?:^|\/)gpt-6-(?:astra|sol|luna)$/i,A2=($)=>typeof $==="object"&&$!==null&&!Array.isArray($),x1=($)=>A2($)&&($.type==="message"||("role"in $))&&$.role==="user",S1=($)=>A2($)&&$.type==="configuration_update";class o2{http;#$=new Map;constructor($=new P2){this.http=$}apply($,Z,J){if(Z.kind!=="primary")return!1;let z=typeof $.model==="string"?$.model:"";if(!R1.has(z))return!1;if(J0.test(z))return!1;let X=A2($.reasoning)?$.reasoning:void 0,Y=typeof X?.effort==="string"?X.effort:void 0;if(!Y)return!1;let N=this.#$.get(Z.sessionID);if(N===void 0)return this.#Z(Z.sessionID,Y),!1;if(Y===N)return!1;let H=Array.isArray($.input)?$.input:void 0;if(!H||H.length===0)return!1;let W=H.findLastIndex(x1);if(W<0){if(J==="http")return!1;return $.reasoning={...X,effort:N},!0}if($.reasoning={...X,effort:N},!S1(H[W-1]))H.splice(W,0,{type:"configuration_update",reasoning:{effort:Y}});return!0}forget($){this.#$.delete($),this.http.forget($)}#Z($,Z){this.#$.set($,Z);while(this.#$.size>Z0){let J=this.#$.keys().next().value;if(J===void 0)break;this.#$.delete(J)}}}function O2($){try{let Z=JSON.parse($);return A2(Z)?Z:void 0}catch{return}}async function q1($,Z,J,z,X=J.http){if($.method.toUpperCase()!=="POST")return;if(!/\/responses\/?$/.test(new URL($.url).pathname))return;let Y=await $.clone().text(),N=O2(Y);if(N)delete N.max_output_tokens;let H=new Headers($.headers),W=R2({rewriteLite:A1,init:{body:N?JSON.stringify(N):$.body===null?void 0:Y},headers:H,metadata:X.get(Z.sessionID),installationID:X.installationID,runtime:X.runtime,websocket:!1,responsesLite:z,applyEffort:(B)=>{J.apply(B,Z,"http")}});return new Request($,{headers:H,body:W.init?.body})}function k1($,Z,J,z){let X=z.sessions.get($.sessionID),Y=z.frameTurns.get($.sessionID);if(!X||!Y)return;let N=a2(X,Y),H=new Headers({"content-type":"application/json"});for(let B of["chatgpt-account-id","x-opencode-parent-session-id","x-parent-session-id"]){let V=J.get(B);if(V!==null)H.set(B,V)}R2({init:{body:$.bodyText},headers:H,metadata:N,installationID:z.installationID,runtime:z.runtime,websocket:!1,skipTurnUpdate:!0,responsesLite:!1,rewriteLite:()=>{}});let W=new URL(Z);if(W.protocol==="wss:")W.protocol="https:";if(W.protocol==="ws:")W.protocol="http:";return new Request(W,{method:"POST",headers:H,body:$.bodyText})}function z0($,Z){if(JSON.stringify($)===JSON.stringify(Z))return!0;if(!Array.isArray($)||!Array.isArray(Z)||Z.length!==$.length+1)return!1;let J=Z.findIndex((z,X)=>JSON.stringify(z)!==JSON.stringify($[X]));return J>=0&&S1(Z[J])&&x1(Z[J+1])&&JSON.stringify(Z.slice(J+1))===JSON.stringify($.slice(J))}function b1($,Z,J){let z=O2($);if(z?.type!=="response.create")return;let X=J.http.advanceFrame(Z.sessionID,z),Y=J.http.get(Z.sessionID);delete z.max_output_tokens;let N=R2({rewriteLite:()=>{},init:{body:JSON.stringify(z)},headers:new Headers,metadata:a2(Y,X),installationID:J.http.installationID,runtime:J.http.runtime,websocket:!0,responsesLite:!1,applyEffort:(W)=>{J.apply(W,Z,"ws")}}),H=O2(String(N.init?.body));if(!H)return;if(!z0(z.input,H.input)){if("input"in z)H.input=z.input;else delete H.input;return JSON.stringify(H)}return String(N.init?.body)}function G0($){return $.replace(/\/responses\/?$/,"").replace(/\/$/,"")}function r2($,Z){let J=new URL($);if(J.origin!=="https://api.openai.com"&&J.origin!=="wss://api.openai.com"||!/\/responses\/?$/.test(J.pathname))return $;let z=new URL(`${G0(Z)}/responses`);if(z.search=J.search,J.protocol==="ws:"||J.protocol==="wss:")z.protocol=z.protocol==="https:"?"wss:":"ws:";return z.href}import{resolve as D1}from"node:path";var X0=1024;class x2{accounts=new Map;limit;constructor($=X0){this.limit=Math.max(1,$)}record($,Z){this.accounts.delete($),this.accounts.set($,Z);while(this.accounts.size>this.limit){let J=this.accounts.keys().next().value;if(J===void 0)break;this.accounts.delete(J)}}activeAccount($){return this.accounts.get($)}forget($){this.accounts.delete($)}get size(){return this.accounts.size}}var w1=Symbol.for("@cortexkit/openai-auth/opencode2-session-accounts"),y1=globalThis,s2=y1[w1]??new Map;y1[w1]=s2;function t2($){let Z=JSON.stringify([D1($.configPath),D1($.statePath)]),J=s2.get(Z);if(!J)J=new x2,s2.set(Z,J);return J}var r="openai",Y0=60000,I1=1,Q0="request refused: no account with a usable credential",J2=($)=>typeof $==="object"&&$!==null&&!Array.isArray($);function j0($){let Z=J2($)?$.counters:void 0,J=J2(Z)?Z.resetCredits:void 0,z=J2(J)?J.value:void 0;return typeof z==="number"&&Number.isFinite(z)?z:void 0}function e2($){try{return JSON.parse($)}catch{return}}function f1($){let Z=q2($);return Z?k2(Z):void 0}var V0=new Set(["usage_limit_reached","rate_limit_exceeded"]);function $1($,Z,J){return{reason:$.window,...J!==void 0?{status:J}:{},...$.resetAt!==void 0?{retryAfterMs:Math.max(0,$.resetAt-Z)}:{}}}function B0($,Z){let J=S2($);if(J){let Y=typeof $.status==="number"?$.status:void 0;return $1(J,Z,Y)}if($.type!=="response.failed"||!J2($.response))return;let z=$.response.failed;if(J2(z)&&typeof z.rate_limit_reached_type==="string")return{reason:z.rate_limit_reached_type};let X=$.response.error;if(J2(X)){let Y=typeof X.code==="string"?X.code:typeof X.type==="string"?X.type:void 0;if(Y&&V0.has(Y))return{reason:Y}}return}function W0($,Z){let J=e2($);if(!J2(J))return;let z=typeof J.type==="string"?J.type:void 0;if(z==="codex.rate_limits")return{quota:{snapshot:g1(J),complete:!0}};let X=B0(J,Z);if(X)return{limit:X};if(z===void 0||z==="error")return;return z$(z)?void 0:{outputStarted:!0}}function U0($){let Z=!1;for(let J of $.keys())if(J.toLowerCase().startsWith("x-codex-")){Z=!0;break}if(!Z)return;return{snapshot:h1($),complete:m1($)}}function H0($){let Z=$.get("retry-after");if(Z===null)return;let J=Number(Z);return Number.isFinite(J)&&J>=0?J*1000:void 0}function G$($){let{source:Z,pins:J}=$,z=$.now??Date.now,X=$.log,Y=$.vault,N=new o2($.codex),H=new Map,W=(j)=>`${j.sessionID}\x00${j.kind}\x00${j.accountId}`,B=new Map,V=$.sessionAccounts??new x2,K=new s1,x=(j,T,E)=>{let M=E?[]:J$(Z.peek().rows,j,T,Y?.identities()??new Set),P=(Y?.routes()??[]).filter((L)=>L.kind==="oauth"&&u1(K2(L.quota),j,T));return[...M.map((L)=>({id:L.id,...L.identity!==void 0?{identity:L.identity}:{},quota:L.quota,row:L})),...P.map((L)=>({id:L.id,...L.identity!==void 0?{identity:L.identity}:{},quota:L.quota}))]},_=(j,T,E)=>{let M=n1(j,T,E),P=j.map((w)=>({id:w.id,kind:"oauth",...v1(w.quota)?{quota:w.quota}:{}})),L=j.flatMap((w)=>w.row?[w.row]:[]),O=new Set(j.filter((w)=>!w.row).map((w)=>w.id)),A=Z.rateLimitMarks(L);for(let w of O){let p=B.get(w);if(p===void 0)continue;if(p<=E)B.delete(w);else A.set(w,p)}return{rows:P,now:E,rateLimitMarks:A,refreshBackoff:Z.refreshBackoffFor(L),killswitch:M,requestPull:(w)=>O.has(w)?Y?.requestReading(w):Z.requestReading(w)}},h=(j,T,E,M,P)=>{let L=t1({...j,placement:o1(T),mainId:P});if(L.kind==="block"){X?.debug("pool admission refused the request",{reason:L.block.reason});return}let O=L.order.filter((A)=>!E.has(A));if(M!==void 0&&O.includes(M))return M;return O[0]},d=(j,T,E,M,P,L)=>{let O=new Map(T.map((k)=>[k.id,k.quota])),A={requestBytes:I1,reservePercent:(k)=>p1(E,k===i1?void 0:k),resetCredits:(k)=>j0(O.get(k))},w=e1(j),p=(k,g)=>J.place({sessionId:M,requestBytes:I1,validPinnedAccountIds:j.rows.map((u)=>u.id).filter((u)=>!w.excluded.has(u)),excludeAccountIds:k,quotaCheckedAtByAccount:Object.fromEntries(j.rows.map((u)=>[u.id,w.projections.get(u.id)?.checkedAt])),wireAccountIdByAccount:Object.fromEntries(T.map((u)=>[u.id,u.identity])),select:(u)=>$$(j,A,new Set(k),u),persist:g}),a=[...P],l=p(a,L);if(!l)return;let i=l.accountId,c=Z$(j,A,i);if(c.kind==="none")return;if(c.kind==="move"){let k=p([...a,i],L);if(k)return k.accountId;return c.reason==="killswitch"?void 0:i}if(c.kind==="detour")return p([...a,i],!1)?.accountId;return i},n={providerID:r,chooseAccount:async(j)=>{let T=await Y?.authority(),E=await $.storage(),M=T!==void 0&&T!=="local",P=()=>{throw new o({kind:"no-account",providerID:r,sessionID:j.sessionID,requestKind:j.kind,message:b2})};if(M)await $.awaitVaultRoster?.();else{if(!(await Z.current()).active){if(await $.slotPlaceholderWithoutMain?.())P();X?.warn("the account pool does not serve requests yet; refusing the request",{kind:j.kind});return}await Z.prepareTokens(Z.peek().rows,E)}let L=z(),O=x(E,L,M),A=r1(_(O.filter((g)=>g.id!==j.rerouteFrom?.accountId),E,L));if(A)await A,L=z(),O=x(E,L,M);let w=new Map(O.map((g)=>[g.id,g])),p=_(O,E,L),a=new Set(j.rerouteFrom?[j.rerouteFrom.accountId]:[]),l=E?.routing?.mode??"main-first",i=j.kind==="primary",c=new Set,k;for(;;){let g=new Set([...a,...c]);if(k=void 0,l==="sticky-balanced")k=d(p,O,E,j.sessionID,g,i&&c.size===0);if(k??=h(p,l,g,i?void 0:V.activeAccount(j.sessionID),M?l==="sticky-balanced"?null:a1(Y?.routes()??[]):void 0),k===void 0||c.has(k)){k=void 0;break}let u=w.get(k)?.row;if(u){if(Z.usableToken(u)!==void 0)break;X?.debug("pool row holds no usable token; choosing again",{accountId:k})}else{if(!Y)break;let s=await Y.authorize(k);if(s){H.set(W({...j,accountId:k}),s);break}X?.debug("the vault refused to serve an account; choosing again",{accountId:k})}c.add(k)}if(k===void 0&&!M&&O.length===0&&await $.slotPlaceholderWithoutMain?.())P();if(k===void 0&&M&&Y&&(O.length===0||c.size>0)){let g=c.size>0?"vault-refused":d1(Y);throw X?.warn("vault mode: no vault account can serve; refusing the request",{cause:g}),new o({kind:"no-account",providerID:r,sessionID:j.sessionID,requestKind:j.kind,message:c1(g,Y.name)})}if(k!==void 0&&i)V.record(j.sessionID,k),$.onRoute?.(j.sessionID,k,l);if(k!==void 0){let g=X?.info;K.served(p,k,X&&g?{info:(u,s)=>g.call(X,u,s)}:void 0)}return X?.debug("pool account chosen",{kind:j.kind,accountId:k,mode:l,...j.rerouteFrom?{rerouteFrom:j.rerouteFrom.accountId}:{}}),k},accountHeaders:async(j)=>{let{accountId:T}=j,E=()=>new o({kind:"no-account",providerID:r,sessionID:j.sessionID,requestKind:j.kind,message:Q0}),M=Y&&await Y.authority()!=="local"?void 0:Z.peek().rows.find((O)=>O.id===T);if(!M&&Y){let O=W(j),A=H.get(O)??await Y.authorize(T);if(H.delete(O),!A)throw X?.warn("the vault refused to serve an account; refusing the request",{accountId:T}),E();return{headers:{...n2,"session-id":j.sessionID,authorization:`Bearer ${A.accessToken}`,"chatgpt-account-id":A.accountIdentity??f1(A.accessToken)??null},attempt:{kind:"vault",routeId:T,receipt:A}}}let P=M?Z.usableToken(M):void 0;if(!M||!P)throw X?.warn("pool row holds no usable token; refusing the request",{accountId:T}),E();let L=M.identity??f1(P);return{headers:{...n2,"session-id":j.sessionID,authorization:`Bearer ${P}`,"chatgpt-account-id":L??null},attempt:{kind:"pool",token:P,credentialEpoch:M.credentialEpoch}}},async rewriteRequest({request:j,sessionID:T,kind:E}){let M=$.codexEndpoint?r2(j.url,$.codexEndpoint()):j.url,P=M===j.url?j:new Request(M,j);return await q1(P,{sessionID:T,kind:E},N,$.responsesLite?.()??!1)??P},rewriteHandshakeURL:({url:j})=>$.codexEndpoint?r2(j,$.codexEndpoint()):void 0,rewriteWebSocketFrame:({frame:j,sessionID:T,kind:E})=>b1(j,{sessionID:T,kind:E},N),quotaFromHeaders:(j)=>U0(j),async limitFromResponse({status:j,headers:T,body:E}){if(j<400)return;let M=e2(await E().catch(()=>"")),P=S2({...J2(M)?M:{},status:j});if(!P)return;let L=z(),O=$1(P,L,j);if(O.retryAfterMs!==void 0)return O;let A=H0(T);return A===void 0?O:{...O,retryAfterMs:A}},inspectEvent:({data:j})=>W0(j,z()),limitFromError(j){let T=e2(j.message),E=S2({...J2(T)?T:{},...j.status!==void 0?{status:j.status}:{}})??(j.message.includes("usage_limit_reached")?{window:"usage_limit_reached"}:void 0);return E?$1(E,z(),j.status):void 0},async onAttemptEnd(j,T){let E=j.data;if(E?.kind!=="vault"||T.status!==401)return;X?.warn("a vault account answered 401; reporting it to the vault",{accountId:j.accountId}),await Y?.reportFailure(E.receipt,401)}},I=(j,T,E)=>{let M=E.data;if(M?.kind==="vault"){Y?.recordSnapshot(j,T.snapshot,T.complete,M.receipt);return}if(M?.kind!=="pool")return;if(Z.peek().rows.find((L)=>L.id===j)?.credentialEpoch!==M.credentialEpoch){X?.debug("quota reading dropped: the row holds another credential",{accountId:j});return}Z.recordSnapshot(j,T.snapshot,M.token,T.complete)},f=(j,T,E)=>{let M=z(),P=E.data?.kind==="vault",L=P?Y?.routes().find((w)=>w.id===j)?.quota:Z.peek().rows.find((w)=>w.id===j)?.quota,O=l1(K2(L),T.reason,M,Y0,T.retryAfterMs!==void 0?M+T.retryAfterMs:void 0);if(!P){Z.markRateLimited(j,O);return}let A=B.get(j);if(A===void 0||A<O)B.set(j,O)};return{adapter:n,attach(j){j.on("quota",(T)=>I(T.accountId,T.quota,T.handle)),j.on("limit",(T)=>{f(T.accountId,T.limit,T.handle),X?.debug("pool row refused the request",{accountId:T.accountId,via:T.via,reason:T.limit.reason,outputStarted:T.outputStarted})})},forgetSession(j){J.forget(j),V.forget(j),N.forget(j)},activeAccount:(j)=>V.activeAccount(j)}}import{resolve as B$}from"node:path";import{Buffer as N0}from"node:buffer";import{resolve as X$}from"node:path";function L2($){return N0.byteLength(JSON.stringify($))}function F0($){return $.reduce((Z,J)=>Z+L2(J),0)}function Z1($,Z){return 2+$+Math.max(0,Z-1)}function P0($){let{head:Z,pending:J}=$;return 10+$.fieldsBytes+1+(Z?22+Z.responseIDBytes+9+Z1(Z.inputBytes,Z.input.length)+1:0)+(J?20+Z1(J.inputBytes,J.input.length)+10+Z1(J.outputBytes,J.output.length)+(J.responseID===void 0?0:14+J.responseIDBytes)+1:0)}function Y$($){try{let Z=JSON.parse($);if(Z&&typeof Z==="object"&&!Array.isArray(Z))return Z}catch{}return}class Q${enabled;caps=D2;entries=new Map;bytes=0;constructor($=!1){this.enabled=$}setEnabled($){if(this.enabled=$,!$)this.entries.clear(),this.bytes=0}send($,Z){if(!this.enabled)return;let J=Y$(Z);if(J?.type!=="response.create")return;if(!Array.isArray(J.input)){this.forget($);return}let z=J.previous_response_id,X=this.entries.get($),Y=X?.head;if(z&&z!==Y?.responseID){this.forget($);return}let{type:N,previous_response_id:H,input:W,...B}=J;this.keep($,{fields:z&&X?X.fields:B,fieldsBytes:z&&X?X.fieldsBytes:L2(B),...z&&Y?{head:Y}:{},pending:{input:W,inputBytes:F0(W),output:[],outputBytes:0,responseIDBytes:0},bytes:0})}receive($,Z,J){if(!this.enabled||!Z.includes("response.created")&&!Z.includes("response.output_item.done")&&!Z.includes("response.completed"))return;let z=this.entries.get($);if(!z?.pending)return;let X=Y$(Z);if(!X)return;let Y=z.pending,N=X.response;if(X.type==="response.created"&&typeof N?.id==="string")Y.responseID=N.id,Y.responseIDBytes=L2(N.id),this.keep($,z);else if(X.type==="response.output_item.done"&&X.item){if(typeof X.response_id==="string"&&Y.responseID!==void 0&&X.response_id!==Y.responseID)return;Y.output.push(X.item),Y.outputBytes+=L2(X.item),this.keep($,z)}else if(X.type==="response.completed"&&typeof N?.id==="string"){if(N.id===z.head?.responseID||Y.responseID!==void 0&&N.id!==Y.responseID)return;let H={responseID:N.id,responseIDBytes:Y.responseID===N.id?Y.responseIDBytes:L2(N.id),input:[...z.head?.input??[],...Y.input,...Y.output],inputBytes:(z.head?.inputBytes??0)+Y.inputBytes+Y.outputBytes},W={...z,head:H,pending:void 0};if(!this.keep($,W))return;J?.({sessionID:$,responseID:H.responseID,bodyText:this.body(z.fields,H)})}}replay($){let Z=this.entries.get($);if(!Z?.head)return;return this.entries.delete($),this.entries.set($,Z),this.body(Z.fields,Z.head)}forget($){let Z=this.entries.get($);if(Z)this.bytes-=Z.bytes;this.entries.delete($)}status(){return{bytes:this.bytes,sessions:[...this.entries].map(([$,Z])=>({sessionID:$,bytes:Z.bytes,responseID:Z.head?.responseID,pending:Z.pending!==void 0}))}}body($,Z){return JSON.stringify({...$,input:Z.input,stream:!0})}keep($,Z){let J=P0(Z);if(this.forget($),J>this.caps.maxBytes)return!1;Z.bytes=J,this.entries.set($,Z),this.bytes+=J;while(this.entries.size>this.caps.maxTargets||this.bytes>this.caps.maxBytes){let z=this.entries.keys().next().value;if(z===void 0)break;this.forget(z)}return this.entries.has($)}}var j$=Symbol.for("@cortexkit/openai-auth/opencode2-frame-mirror"),V$=globalThis,J1=V$[j$]??new Map;V$[j$]=J1;function w2($){let Z=JSON.stringify([X$($.configPath),X$($.statePath)]),J=J1.get(Z);if(!J)J=new Q$,J1.set(Z,J);return J}var K0=5000,L0=["accept","originator","session-id","thread-id","user-agent","version","x-client-request-id","x-codex-beta-features","x-codex-turn-metadata","x-codex-window-id","x-openai-internal-codex-responses-lite","x-opencode-parent-session-id","x-parent-session-id"],C0=["x-opencode-parent-session-id","x-parent-session-id"];function N$($){let Z=W$($);return{enabled:Z?.enabled===!0,subagents:Z?.subagents===!0,sustain:Z?.sustain===!0,window:U$($?{...$,cachekeep:Z}:$)}}var F$=Symbol.for("@cortexkit/openai-auth/opencode2-cache-keep"),P$=globalThis,C2=P$[F$]??new Map;P$[F$]=C2;function T0($,Z){let J=[],z=()=>J.at(-1)?.location,X=()=>{let W=z();if(!W)throw Error("no location holds keep-warm");return W},Y=(W,B)=>{H.remove(W),z()?.log?.debug(`cachekeep dropped target (${B})`,{sessionKey:W})},N=async(W)=>{if(W.meta.credentialMode!=="local")throw Error("a target captured in vault mode is not warmed with a local credential");let B=W.accountId??"main",V=X(),K=await V.source.accessFor(B,await V.storage());if(!K)throw Error(`pool row ${B} has no usable token`);return{token:K.token,identity:K.row.identity}},H=H$({...D2,now:$.now,...$.setIntervalImpl?{setIntervalImpl:$.setIntervalImpl}:{},...$.clearIntervalImpl?{clearIntervalImpl:$.clearIntervalImpl}:{},codexResponsesUrl:$.codexResponsesUrl,fetchImpl:(W,B)=>X().fetch(W,B),logger:{debug:(W,B)=>z()?.log?.debug(W,B),warn:(W,B)=>z()?.log?.warn(W,B)},getWindow:()=>z()?.settings().window,getSustain:()=>z()?.settings().sustain===!0,resolveLocal:N,vault:{owns:(W)=>z()?.vault.owns(W)===!0,authority:()=>X().vault.authority(),send:async(W,B,V)=>{let K=X();if(await K.vault.authority()!=="vault")return;return K.vault.send(W,B,V)}},activeAccount:(W)=>{if(W===void 0)throw Error("target has no session");let B=z(),V=B?.settings();if(!B||!V?.enabled){Y(W,"keep-warm is off");return}if(!V.subagents&&H.status().targets.some((x)=>x.sessionKey===W&&x.isSubagent)){Y(W,"subagent warming is off");return}let K=B.accounts.activeAccount(W);if(K===void 0){Y(W,"no account recorded for the session");return}return K},verifyCredential:({target:W,mode:B,identity:V})=>{if(W.meta.credentialMode!==B)throw Error(`a target captured in ${W.meta.credentialMode??"an unknown"} mode is not warmed with a ${B} credential`);if(V!==W.meta.chatgptAccountId)throw Y(W.sessionKey,"the account signs in as another login now"),Error("the account signs in as another login now")}});return{manager:H,settings:Z,holders:J,joinTimeoutMs:$.joinTimeoutMs??K0}}function _0($){try{let Z=JSON.parse($),J=Array.isArray(Z.input)?Z.input.at(-1):void 0;if(J?.role!=="user")return!1;return(typeof J.content==="string"?J.content:Array.isArray(J.content)?J.content.map((X)=>typeof X?.text==="string"?X.text:"").join(""):"").startsWith("This is a keep-alive request.")}catch{return!1}}function M0($){let Z={};for(let J of L0){let z=$.get(J);if(z)Z[J]=z}return Z}function K$($,Z,J){let z=JSON.stringify([B$($.configPath),B$($.statePath)]),X=C2.get(z);if(!X)X=T0(J,Z.settings()),C2.set(z,X);let Y=X,N=w2($);N.setEnabled(Y.settings.enabled);let H={location:{...Z,settings:()=>Y.settings}};Y.holders.push(H);let W=!1,B=async(V)=>{try{let K=H.location.settings();if(W||!K.enabled)return;if(V.kind!=="primary"){if(V.kind==="generate"&&_0(await V.request.clone().text())){if(W)return;Y.manager.remove(V.sessionID)}return}let x=V.attempt.data,_=x?.kind==="pool"?"local":x?.kind==="vault"?"vault":void 0;if(!_)return;let h=V.request.headers,d=C0.some((n)=>h.has(n))||Z.parentOf!==void 0&&await Z.parentOf(V.sessionID)!==void 0;if(d&&!K.subagents)return;let S=await V.request.clone().text();if(W)return;let y=h.get("chatgpt-account-id")??void 0;Y.manager.track({sessionKey:V.sessionID,bodyText:S,accountId:V.attempt.accountId,isSubagent:d,meta:{replayHeaders:M0(h),...y?{chatgptAccountId:y}:{},routingSessionId:V.sessionID,url:V.request.url,credentialMode:_}})}catch(K){Z.log?.warn("cachekeep capture failed",{error:K instanceof Error?K.message:String(K)})}};return{manager:Y.manager,configure:(V)=>{Object.assign(Y.settings,V),N.setEnabled(Y.settings.enabled)},capture:B,forget:(V)=>Y.manager.remove(V),async release(){if(W)return;W=!0;let V=Y.holders.indexOf(H);if(V>=0)Y.holders.splice(V,1);if(Y.holders.length>0)return;if(C2.get(z)===Y)C2.delete(z);Y.manager.stop();let K;try{await Promise.race([Y.manager.tick().catch(()=>{}),new Promise((x)=>{K=setTimeout(x,Y.joinTimeoutMs),K.unref?.()})])}finally{clearTimeout(K)}}}}import{mkdirSync as E0}from"node:fs";import{dirname as O0,join as R0,resolve as A0}from"node:path";var x0="openai-auth-sessions-opencode2.json";function S0(){return R0(C$(),x0)}var q0="sessions",k0=1e4,b0=5000,D0=25;class E${path;options;sessions;frameTurns=new F2;#$=new Set;#Z=new Set;#J=Promise.resolve();#z=!1;constructor($,Z={}){this.path=$;this.options=Z;this.sessions=_$($,Z.uuid??Q2)}get($,Z=Q2){let J=this.sessions.get($);if(!J){let z=Z();J={threadID:z,turnID:Z(),windowID:`${z}:0`},this.sessions.set($,J),this.#Z.delete($),this.#$.add($),this.save()}return J}delete($){this.sessions.delete($),this.frameTurns.forget($),this.#$.delete($),this.#Z.add($),this.save()}save(){if(!this.#z)this.#z=!0,this.#J=this.#J.then(()=>{return this.#z=!1,this.#G()});return this.#J}settled(){return this.#J}async#G(){if(this.#$.size===0&&this.#Z.size===0)return;let $=[...this.#$].flatMap((z)=>{let X=this.sessions.get(z);return X?[[z,X]]:[]}),Z=[...this.#Z],J=null;try{if(E0(O0(this.path),{recursive:!0}),J=await this.#X(),!J)return;let z;try{z=T$(this.path)}catch{z=new Map}await this.options.afterRead?.();for(let X of Z)z.delete(X);for(let[X,Y]of $)z.set(X,Y.threadID);M$(this.path,z)}catch{return}finally{await J?.release().catch(()=>{})}for(let[z,X]of $)if(this.sessions.get(z)===X)this.#$.delete(z);for(let z of Z)if(!this.sessions.has(z))this.#Z.delete(z)}async#X(){let $=performance.now()+(this.options.lockWaitMs??b0);for(;;){let Z=await L$({name:q0,path:this.path,ttlMs:k0});if(Z||performance.now()>=$)return Z;await new Promise((J)=>setTimeout(J,D0))}}}var O$=Symbol.for("@cortexkit/openai-auth/opencode2-codex-sessions"),R$=globalThis,z1=R$[O$]??new Map;R$[O$]=z1;function A$($=S0()){let Z=A0($),J=z1.get(Z);if(!J)J=new E$(Z),z1.set(Z,J);return J}var x$=Symbol.for("cortexkit.openai-auth.v2.commands");function w0(){let $=globalThis;return $[x$]??={locations:new Map},$[x$]}async function I$($,Z){let J=w0(),z=$.location.directory,X={menu:Z,session:$.session},Y=await q$(z),N=await S$(w$,Y.dir,()=>y$({...Y,drain:b$,apply:(V)=>{let K=J.locations.get(z);if(!K)throw Error("The OpenAI menu location was closed");return K.menu.apply(V)}})),H=J.locations.get(z);J.locations.set(z,X),await H?.registration?.dispose(),J.command??={name:"openai",description:"OpenAI account menu",async execute(V){let K=J.locations.values().next().value?.session;if(!K)return;let x=await K.get({sessionID:V.sessionID}),_=J.locations.get(x.location.directory);if(!_||!D$(V.sessionID))return;let h=await _.menu.open(V.sessionID);k$(h,V.sessionID)}};let W=J.command;try{X.registration=await $.command.transform((V)=>{V.add(W)})}catch(V){if(J.locations.get(z)===X)J.locations.delete(z);throw await N.release(),V}let B=!1;return async()=>{if(B)return;if(B=!0,J.locations.get(z)===X)J.locations.delete(z);await N.release(),await X.registration?.dispose()}}var y0="openai-auth-pool-browser",I0="openai-auth-pool-headless",f0="openai-auth-vault",v0="Vault login requires this OpenCode host to be enrolled in the Claustrum vault. Connect to the vault or disconnect this host before trying again.";async function T2($){if(await $.authority()!=="local")throw Error("This host is connected to the credential vault or its enrollment is unreadable; the login was not stored. Disconnect this host from the vault to add a local login.")}function l$($){return{method:{id:f0,type:"oauth",label:"ChatGPT accounts in the vault"},async activate(){if(await f$($.paths,$.name)!=="vault")throw Error(v0)}}}function u$($){let Z=(J,z,X)=>({method:{id:J,type:"oauth",label:z},async authorize(){if($.vault)await T2($.vault);let Y=await $.beginLogin({version:$.version,headless:X});return{url:Y.url,instructions:Y.instructions,mode:"auto",callback:Y.completion}}});return[Z(y0,"ChatGPT (openai-auth pool, browser)",!1),Z(I0,"ChatGPT (openai-auth pool, headless)",!0)]}function G1($){let Z=(J)=>typeof J==="string"?J:"";return N2({type:"oauth",access:Z($.access),refresh:Z($.refresh)})||$.refresh===m$||v$($)}function h0($){if($.accountId)return $.accountId;let Z=$.access?q2($.access):void 0;return Z?k2(Z):void 0}async function p$($,Z,J,z={}){if(z.vault)await T2(z.vault);if(G1(J))throw Error("the credential is not a ChatGPT login (a placeholder or a tombstone); it was not stored");let X=h$($,{rowLocks:(_)=>g$(Z,_)}),Y=await X.read();if(Y.status!=="ready")throw Error(`the account pool cannot be read (${Y.status}); the login was not stored`);let N={type:"oauth",refresh:J.refresh,...J.access!==void 0?{access:J.access}:{},...J.expires!==void 0?{expires:J.expires}:{}},H=h0(J);if(z.vault)await T2(z.vault);let W=H!==void 0?{identity:H}:{};if(z.origin==="import"){let _=Y.rows.find((h)=>H!==void 0&&h.identity===H||h.credential?.type==="oauth"&&h.credential.refresh===J.refresh);if(_)return{id:_.id,operation:"kept"}}let B=Y.rows.filter((_)=>_.type==="oauth"&&!_.invalid),V=H?B.find((_)=>_.identity===H):void 0,K=Y.rows.find((_)=>_.id===y2);if(V)return{id:(await X.replace(V.id,N,W)).id,operation:"replaced"};if(!K){let _=await X.add({id:y2,credential:N,...W,...J.label!==void 0?{label:J.label}:{}});return{id:_.id,operation:_.outcome==="added-disabled"?"added-disabled":"added"}}if(!K.invalid&&!K.credential)return{id:(await X.replace(y2,N,W)).id,operation:"replaced"};let x=await X.add({id:J.id,credential:N,...W,...J.label!==void 0?{label:J.label}:{}});return{id:x.id,operation:x.outcome==="added-disabled"?"added-disabled":x.outcome==="rotated"?"replaced":"added"}}function m0($){let Z=$.itemId!==void 0;switch($.sectionId){case"accounts":return Z?["enable","disable","remove","move"].includes($.actionId):$.actionId==="add";case"routing":return!Z&&["order","mode"].includes($.actionId);case"quota":return $.actionId==="check";case"limits":return Z?$.actionId==="floors":$.actionId==="killswitch";case"session":return!Z&&$.actionId==="clear-pin";case"diagnostics":return!Z&&["logging","dump"].includes($.actionId);case"cache":return!Z&&["enabled","subagents","sustain","window"].includes($.actionId);case"reset":return Z&&["preview","spend","retry"].includes($.actionId);default:return!1}}function i$($){let Z={...$,allowAction:m0,unavailableSections:[]};return{open:(J)=>c$(Z,J),apply:(J)=>{let z=J!==null&&typeof J==="object"?J:{},X=z.values&&typeof z.values==="object"&&!Array.isArray(z.values)?Object.fromEntries(Object.entries(z.values).filter(([,Y])=>Y===null||["string","number","boolean"].includes(typeof Y))):void 0;return d$(Z,{command:"openai",sectionId:typeof z.sectionId==="string"?z.sectionId:"",actionId:typeof z.actionId==="string"?z.actionId:"",...X?{values:X}:{},...z.confirmed===!0?{confirmed:!0}:{},...typeof z.itemId==="string"?{itemId:z.itemId}:{},...typeof z.sessionId==="string"?{sessionId:z.sessionId}:{}})}}}function g0($){if(!a$($.modelID??$.id)){$.enabled=!1;return}let Z=n$($.id);if(Z)$.limit={...Z}}function o$($){return $.model.transform((Z)=>{for(let J of Z.list(r))Z.update(r,String(J.id),(z)=>g0(z))})}class X1{log;pending=new Map;requests=new Map;writing=new Set;constructor($){this.log=$}async safely($){let Z=(async()=>{try{await $()}catch{this.log.warn("request dump failed")}})();this.writing.add(Z);try{await Z}finally{this.writing.delete(Z)}}async captureHttp($,Z){await this.safely(async()=>{if(!B2().dump)return;let J={sessionID:Z.sessionID,accountId:Z.accountId,transport:"http",phase:"http",url:$.url,method:$.method,headers:new Headers($.headers),bodyText:await $.clone().text()};if(this.pending.set($,{attemptId:Z.attemptId,input:J}),this.requests.set(Z.attemptId,$),this.pending.size>512){let z=this.pending.keys().next().value;if(z)this.take(z)}})}take($){let Z=this.pending.get($);if(Z)this.pending.delete($),this.requests.delete(Z.attemptId);return Z?.input}async response($,Z){let J=this.take($);if(J)await this.safely(()=>I2({...J,status:Z}))}async end($,Z){if(Z.status!==void 0||!Z.error)return;let J=this.requests.get($.attemptId),z=J&&this.take(J);if(!z)return;let{reason:X,message:Y}=Z.error,N=Y?`${X}: ${Y}`:X;await this.safely(()=>I2({...z,error:f2(N,J?.headers.get("authorization")?.replace(/^Bearer /,""))}))}async frame($,Z){await this.safely(()=>I2({sessionID:Z.sessionID,accountId:Z.accountId,transport:"websocket",phase:"observed",bodyText:$}))}clear(){this.pending.clear(),this.requests.clear()}async settle(){await Promise.all(this.writing)}}class Y1{counts=new Map;record($,Z){let J=Z.resetCreditsApplicable;this.counts.set($.id,{credentialEpoch:$.credentialEpoch,identity:$.identity,applicable:typeof J==="number"&&Number.isFinite(J)?J:void 0})}applicable($){let Z=this.counts.get($.id);if(!Z||Z.credentialEpoch!==$.credentialEpoch||Z.identity!==$.identity)return;return Z.applicable}}function $Z($){return async(Z)=>{let J=Z.credential;if(J.type!=="oauth"||!J.access)throw Error("the row holds no access token to poll with");let z=await r$({accessToken:J.access,fetchImpl:$.fetchImpl,now:$.now,...Z.identity?{accountId:Z.identity}:{},accountKey:Z.id,...$.logger?{logger:$.logger}:{}});return $.counts.record(Z,z),s$(z,$.now(),!0)}}function ZZ($){let{source:Z,counts:J,now:z}=$,X=async(B)=>{let V=await Z.rowAccess(B,await $.storage());if(!V?.row)throw new t$("unknown_account",`${B==="main"?"Main":"Fallback"} account ${B} was not found.`);return e$(B,V)},Y=async(B)=>{if($.authority&&await $.authority()!=="local")return{account:B,ok:!1,error:"local accounts are not polled while this host is connected to the vault"};let[V]=await Z.pollRows(await $.storage(),{ids:[B]});if(!V)return{account:B,ok:!1,error:"targeted quota refresh returned no result"};return{account:V.id,ok:V.ok,...V.error!==void 0?{error:V.error}:{}}},N=(B)=>Z.peek().rows.find((V)=>V.id===B),H=(B)=>{let V=N(B);if(!V)return null;let K=K2(V.quota)??{},x=J.applicable(V),_=Math.max(0,...[K.primary?.checkedAt,K.secondary?.checkedAt].filter((h)=>typeof h==="number"));return{quota:{...K,...x!==void 0?{resetCreditsApplicable:x}:{}},checkedAt:_,refreshAfter:_,...V.identity!==void 0?{accountId:V.identity}:{}}};return{resolveResetTarget:X,refreshResetTargetQuota:Y,quotaManager:{isRateLimited:(B)=>{let V=N(B);if(!V)return!1;let K=Z.rateLimitMarks([V]).get(V.id);return K!==void 0&&K>z()},getMain:()=>H("main"),getFallback:(B)=>H(B)}}}import{resolve as zZ}from"node:path";var l0=1024;class Q1{pins=new Map;listeners=new Set;limit;constructor($=l0){this.limit=Math.max(1,$)}get($){return this.pins.get($)?.accountId}forget($){this.pins.delete($);for(let Z of this.listeners)Z($)}subscribe($){return this.listeners.add($),()=>{this.listeners.delete($)}}snapshot(){return new Map(this.pins)}get size(){return this.pins.size}set($,Z){this.pins.delete($),this.pins.set($,Z);for(let J of this.listeners)J($,Z);while(this.pins.size>this.limit){let J=this.pins.keys().next().value;if(J===void 0)break;this.forget(J)}}place($){return JZ(this.pins,$,(Z,J)=>this.set(Z,J))}}var GZ=Symbol.for("@cortexkit/openai-auth/opencode2-pins"),XZ=globalThis,j1=XZ[GZ]??new Map;XZ[GZ]=j1;function YZ($){let Z=JSON.stringify([zZ($.configPath),zZ($.statePath)]),J=j1.get(Z);if(!J)J=new Q1,j1.set(Z,J);return J}import{statSync as u0}from"node:fs";import{resolve as p0}from"node:path";function FZ($){return $.map((Z)=>{try{let J=u0(Z);return`${J.ino}:${J.size}:${J.mtimeMs}:${J.ctimeMs}`}catch{return"?"}}).join("|")}function V1($){return FZ([$.vault.paths.tokenPath,$.vault.paths.statePath])}function QZ($){return FZ([$.paths.configPath,$.paths.statePath,$.vault.paths.rosterPath])+V1($)}class PZ{file;observationIntervalMs;producers=new Set;subscriptions=new Map;observations=new Map;chain=Promise.resolve();timer;constructor($,Z){this.file=$;this.observationIntervalMs=Z}add($){this.producers.add($),this.observations.set($,{stamp:QZ($),roster:$.vault.snapshot()});let Z=$.source.subscribe(()=>{this.publish($)}),J=this.subscriptions.get($.pins);if(!J){let z=new Set;J={producers:z,stop:$.pins.subscribe((X,Y)=>{let N=z.values().next().value;if(N)this.publish(N,{sessionId:X,pin:Y,accountId:Y?.accountId,route:"sticky-balanced"})})},this.subscriptions.set($.pins,J)}return J.producers.add($),this.timer??=setInterval(()=>{for(let z of this.producers){let X={stamp:QZ(z),roster:z.vault.snapshot()},Y=this.observations.get(z);if(X.stamp!==Y?.stamp||X.roster!==Y?.roster)this.observations.set(z,X),this.publish(z)}},this.observationIntervalMs),this.timer.unref?.(),()=>{if(Z(),this.producers.delete($),this.observations.delete($),J.producers.delete($),!J.producers.size)J.stop(),this.subscriptions.delete($.pins);if(!this.producers.size)clearInterval(this.timer),this.timer=void 0}}publish($,Z){return this.chain=this.chain.then(async()=>{if(!this.producers.has($))return;let z=await $.vault.authority()!=="local",X=V1($),Y=()=>this.producers.has($)&&$.vault.enrolled()===z&&V1($)===X,N=await z2($.paths),H=z?HZ($.vault.snapshot()?.rows??[],new Set($.vault.routes().map((B)=>B.id)),N,Date.now()):NZ((await $.source.sidebarView()).rows,N,Date.now());if(await VZ(H,this.file,{canWrite:Y}),!Y()||!Z)return;let W=H.vaultAccounts??H.fallbacks;if(Z.accountId===void 0){await WZ(Z.sessionId,W,this.file,{canWrite:Y});return}if(Z.pin){let B=Date.now();await UZ({sessionId:Z.sessionId,assignment:{accountId:Z.pin.accountId,wireAccountId:Z.pin.wireIdentity,inputBytes:Z.pin.inputBytes??0,quotaCheckedAt:Z.pin.quotaCheckedAt,assignedAt:B,lastSeenAt:B},validPinnedAccountIds:[...z?[]:["main"],...W.filter((V)=>V.enabled).map((V)=>V.id)]},this.file)}await BZ({sessionId:Z.sessionId,activeId:Z.accountId,route:Z.route??H.route,updatedAt:Date.now()},W,this.file,{canWrite:Y})}).catch(()=>{G2("opencode2").warn("sidebar publication failed")}),this.chain}settled(){return this.chain}get empty(){return this.producers.size===0}}var KZ=Symbol.for("@cortexkit/openai-auth/opencode2-sidebar-publishers"),LZ=globalThis,_2=LZ[KZ]??new Map;LZ[KZ]=_2;function CZ($,Z=jZ(),J=2000){let z=p0(Z),X=_2.get(z);if(!X)X=new PZ(z,J),_2.set(z,X);let Y=X,N=Y.add($),H=!1;for(let[W,B]of $.pins.snapshot())Y.publish($,{sessionId:W,pin:B,accountId:B.accountId,route:"sticky-balanced"});return{publish:()=>Y.publish($),route:(W,B,V)=>{Y.publish($,{sessionId:W,accountId:B,route:V})},async release(){if(H)return;if(H=!0,N(),await Y.settled(),Y.empty&&_2.get(z)===Y)_2.delete(z)}}}var h2="cortexkit-openai-auth",i0=5000;async function TZ($,Z,J,z=new P2,X,Y,N){let H=new X1(J),W=new c0,B=new Map,V=new Map,K=(S)=>{V.delete(S);for(let y of B.keys())if(y.startsWith(`${S}:`))B.delete(y)},x=(S)=>{N?.(S.sessionID),Y?.send(S.sessionID,S.frame)},h=await i2({session:{hook:(S,y,n)=>$.session.hook(S,async(I)=>{let f=S==="http.request"?I:void 0,j=S==="experimental.ws.handshake"?I:void 0,E=(f?f.request.headers:j?new Headers(j.headers):void 0)?.get("authorization")===`Bearer ${$2(Z.providerID)}`,M={};if(j)B.delete(`${j.sessionID}:${j.kind}`);try{await W.run(M,()=>y(I))}catch(P){if(E&&!(P instanceof o))throw AZ(P);throw P}if(f&&E&&M.attempt){let P=f.request.headers.get("thread-id");if(P)f.request.headers.set("session-id",P)}if(f&&E&&M.attempt)await H.captureHttp(f.request,M.attempt);if(f&&E&&M.attempt)await X?.({sessionID:f.sessionID,kind:f.kind,request:f.request,attempt:M.attempt});if(j&&E&&M.attempt)j.headers["session-id"]=z.get(j.sessionID).threadID;if(S==="experimental.ws.send"){let P=I,L=B.get(`${P.sessionID}:${P.kind}`);if(L)await H.frame(P.frame,L.attempt);if(L&&P.kind==="primary")x(P)}if(f||j){let P=f??j;if(!P)return;let O=(f?f.request.headers:new Headers(P.headers)).get("authorization")?.replace(/^Bearer /,"");if(E&&O)V.set(P.sessionID,O);else V.delete(P.sessionID);if(j){let A=`${j.sessionID}:${j.kind}`;if(E&&O&&M.attempt)B.set(A,{bearer:O,attempt:M.attempt,url:j.url,headers:new Headers(Object.entries(j.headers).filter(([w])=>["chatgpt-account-id","x-opencode-parent-session-id","x-parent-session-id"].includes(w.toLowerCase())))});else B.delete(A)}if(V.size>512){let A=V.keys().next().value;if(A)V.delete(A)}if(B.size>512){let A=B.keys().next().value;if(A)B.delete(A)}}else if(S==="experimental.ws.receive"){let P=I,L=B.get(`${P.sessionID}:${P.kind}`);if(L){if(z.frameReceived(P.sessionID,P.frame),P.kind==="primary"){let O;if(Y?.receive(P.sessionID,P.frame,(A)=>{O=A}),O)try{let A=k1(O,L.url,L.headers,z);if(A)await X?.({sessionID:P.sessionID,kind:"primary",request:A,attempt:L.attempt})}catch(A){J.warn("cachekeep WebSocket capture failed",{error:A instanceof Error?A.message:String(A)})}}P.frame=xZ(P.frame,L.bearer)}}else if(S==="retry"){let P=I,L=V.get(P.sessionID);if(L)Object.assign(P.error,{message:f2(P.error.message,L)})}},n)},event:{subscribe:(S)=>async function*(){for await(let y of $.event.subscribe(S)){if(y.type==="session.deleted")K(y.data.sessionID);yield y}}()}},{...Z,rewriteRequest:async(S)=>{let y=W.getStore();if(y)y.attempt=S.attempt;return Z.rewriteRequest?.(S)},rewriteHandshakeURL:(S)=>{let y=W.getStore();if(y)y.attempt=S.attempt;return Z.rewriteHandshakeURL?.(S)},onAttemptEnd:async(S,y)=>{await H.end(S,y),await Z.onAttemptEnd?.(S,y)},rewriteResponse:async(S)=>{await H.response(S.request,S.response.status);let y=await Z.rewriteResponse?.(S)??S.response;return SZ(y,S.request.headers.get("authorization")?.replace(/^Bearer /,""),"event-stream")}},{gateOnPlaceholder:{credential:(S)=>{let y=S.get("authorization");return y?.startsWith("Bearer ")?y.slice(7):void 0}},logger:{warn:(S,y)=>J.warn(S,{data:y})}}),d=h.dispose;return{...h,dispose:async()=>{V.clear(),B.clear(),await d(),await H.settle(),H.clear()}}}function U1($={}){return{id:h2,setup:(Z)=>a0(Z,$)}}async function a0($,Z={}){let X2=[];try{let J=G2("opencode2");let z=G2("quota");let X=Z.paths??(()=>kZ(qZ()));let Y=await z2(X());let N=Y?.logging?.level;if(N&&typeof N==="string")MZ(N);let H=Z.fetch??fetch;let W=Z.now??Date.now;let B=Z.version??IZ;let V=Z.poolMigration??uZ;if(!V&&!W2(X().configPath)){J.info("openai-auth stands aside on OpenCode 2: this install has not moved into the account pool and the migration is switched off, so OpenCode 2 serves its own ChatGPT login");let C=(t)=>{throw new o({kind:"no-account",providerID:r,sessionID:t.sessionID,requestKind:t.kind,message:b2})},v=await TZ($,{providerID:r,chooseAccount:C,accountHeaders:C},J);return()=>v.dispose()}let K=Z.vault?.firstRosterWaitMs??vZ;let x=lZ({host:"opencode",stateDir:Z.vault?.stateDir??RZ(X().statePath),reservedRouteIds:()=>I.peek().rows.map((C)=>C.id),...Z.vault?.connectionFile?{connectionFile:Z.vault.connectionFile}:{},...Z.vault?.connectScoped?{connectScoped:Z.vault.connectScoped}:{},...Z.vault?.connectEnrollment?{connectEnrollment:Z.vault.connectEnrollment}:{},...Z.vault?.pollIntervalMs!==void 0?{pollIntervalMs:Z.vault.pollIntervalMs}:{},fetchImpl:()=>H},X());let _=x.vault;let h=!1;let d=!1;const S=v2(X2,{[Symbol.dispose](){if(!h)x.release()}},0);await _.authority();let y=x.firstRoster;let n=new Y1;let I=new hZ({paths:X,refreshProvider:async(C)=>{let v=await OZ({refreshToken:C.refresh,fetchImpl:H,now:W}),t=EZ({id_token:"",access_token:v.access,refresh_token:v.refresh});return{...v,...t?{identity:t}:{}}},pullQuota:$Z({fetchImpl:H,now:W,counts:n,logger:z}),now:W,vaultIdentities:()=>_.identities(),vaultMode:()=>_.enrolled(),vaultAuthority:()=>_.authority(),vaultFirstRoster:y,vaultFirstRosterBackgroundWaitMs:K,log:G2("pool")});await I.load();let f=Z.heartbeat===!1?void 0:await gZ({version:B,logger:G2("heartbeat")});let j=Z.fence??(()=>yZ({currentVersion:B}));let T=Z.slot??pZ();let E=async()=>bZ(X(),await T.get({path:{id:"openai"}}));let M=!1;let P=V?mZ({paths:X,slot:T,version:B,fence:j,runDeps:{vaultServes:()=>_.serves()},paused:async()=>await _.authority()!=="local",migrate:async(C)=>{let v=await DZ(C);if(M=v.status==="refused",!d)await I.load();return v},adopt:async(C)=>{if(d)return{status:"retry",reason:"unsettled"};if(!await W1(y,K))return{status:"retry",reason:"vault-roster-pending"};if(d)return{status:"retry",reason:"unsettled"};let v=await wZ(C);if(!d)await I.load();return v}}):void 0;P?.start();x.start();let L=YZ(X());let O=CZ({paths:X(),source:I,pins:L,vault:_},Z.sidebarStateFile,Z.sidebarObservationIntervalMs);const A=v2(X2,{[Symbol.dispose](){if(!h)O.release()}},0);O.publish();let w=Z.codex??new P2(void 0,void 0,A$());let p=N$(Y);let a=w2(X());let l=K$(X(),{source:I,storage:()=>z2(X()),vault:_,accounts:t2(X()),settings:()=>p,parentOf:async(C)=>(await $.session.get({sessionID:C}))?.parentID??void 0,fetch:H,log:G2("cachekeep")},{now:W,codexResponsesUrl:B2().codexApiEndpoint,...Z.cacheKeep});const i=v2(X2,{[Symbol.dispose](){if(!h)l.release()}},0);let c=G$({codex:w,onRoute:O.route,source:I,slotPlaceholderWithoutMain:E,storage:()=>z2(X()),pins:L,sessionAccounts:t2(X()),vault:_,awaitVaultRoster:async()=>{await W1(_.awaitRequestRoster(),fZ)},responsesLite:()=>B2().responsesLite,codexEndpoint:()=>B2().codexApiEndpoint,now:W,log:J});let k=await TZ($,c.adapter,J,w,(C)=>l.capture(C),a,(C)=>l.forget(C));c.attach(k);let g=async(C)=>{if(await T2(_),W2(X().configPath))return;if(await P?.idle(),W2(X().configPath))return;if(M&&!G1(C)&&(await j()).open){await I.poolStore().initialize();return}throw Error("OpenAI accounts move to the shared account pool once every OpenCode process on this machine runs this version of openai-auth; the login was not stored. Update or close the older processes and sign in again.")};let u=async(C)=>{await g(C);let v=await p$(I.poolStore(),X(),C,{vault:_});if(!W2(X().configPath))await P?.requestAdoption();await I.load(),J.info("ChatGPT login stored in the account pool",v)};let s=await p2($,{integrationID:r,methods:u$({beginLogin:Z.beginLogin??B1,version:B,vault:_}),onLogin:(C)=>u(C),label:"ChatGPT (openai-auth account pool)",vault:l$(_)});let M2=await o$($);if(Z.controlPlane&&(!$.command||!$.location))throw Error("OpenCode 2 control plane requires command and location APIs");let U2=$.command&&$.location?await I$({session:$.session,command:$.command,location:$.location},Z.controlPlane??i$({...ZZ({source:I,storage:()=>z2(X()),counts:n,now:W,authority:()=>_.authority()}),fetchImpl:H,now:W,randomUUID:d0,accountStoragePath:X().configPath,accountStatePath:X().statePath,packageVersion:B,loadAccounts:z2,store:()=>I.poolStore(),migration:async()=>{if(W2(X().configPath))return{migrated:!0};let C=await j();return{migrated:!1,blockers:C.open?[]:C.blockers}},beginAccountLogin:Z.beginLogin??B1,refreshAllQuota:async()=>(await I.pollRows(await z2(X()))).map((C)=>({...C,account:C.id})),getStickyRouting:async(C)=>L.get(C),cacheKeepManager:l.manager,setCacheKeepEnabled:(C)=>l.configure({enabled:C}),setCacheKeepSubagents:(C)=>l.configure({subagents:C}),setCacheKeepSustain:(C)=>l.configure({sustain:C}),setCacheKeepWindow:(C)=>l.configure({window:C}),afterWrite:()=>I.load(),refreshSidebar:()=>O.publish(),clearStickyRouting:async(C)=>{let v=L.get(C)!==void 0;return L.forget(C),v},vault:_})):void 0;let j2=new AbortController;(async()=>{try{for await(let C of $.event.subscribe({signal:j2.signal}))if(C.type==="session.deleted")c.forgetSession(C.data.sessionID),l.forget(C.data.sessionID),a.forget(C.data.sessionID)}catch(C){if(!j2.signal.aborted)J.warn("stopped listening for session deletion",{error:C instanceof Error?C.message:String(C)})}})();h=!0;return async()=>{d=!0,j2.abort();let C=l.release();await U2?.(),P?.dispose(),I.dispose(),await O.release(),await Promise.allSettled([k.dispose(),s.dispose(),M2.dispose()]);let v;try{await Promise.race([Promise.all([P?.idle(),I.settled(),w.store?.settled(),C]),new Promise((t)=>{v=setTimeout(t,i0),v.unref?.()})])}finally{clearTimeout(v),x.release(),await f?.release()}}}catch(m2){var g2=m2,l2=1}finally{_Z(X2,g2,l2)}}var n0=U1(),P6={id:h2,setup:n0.setup,server:cZ.server};export{P6 as default,U1 as createOpenAIAuthPlugin,h2 as OPENAI_AUTH_PLUGIN_ID};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cortexkit/opencode-openai-auth",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -66,9 +66,9 @@
|
|
|
66
66
|
},
|
|
67
67
|
"devDependencies": {
|
|
68
68
|
"@ai-sdk/openai": "3.0.88",
|
|
69
|
-
"@cortexkit/common-auth": "^0.
|
|
69
|
+
"@cortexkit/common-auth": "^0.23.0",
|
|
70
70
|
"@cortexkit/openai-auth-core": "workspace:*",
|
|
71
|
-
"@opencode/plugin": "2.0.
|
|
71
|
+
"@opencode/plugin": "2.0.32"
|
|
72
72
|
},
|
|
73
73
|
"dependencies": {
|
|
74
74
|
"@cortexkit/claustrum-client": "^0.12.0",
|
|
@@ -76,7 +76,7 @@
|
|
|
76
76
|
"@cortexkit/subc-client": "^0.22.0",
|
|
77
77
|
"@opentui/core": ">=0.6.1",
|
|
78
78
|
"@opentui/solid": ">=0.6.1",
|
|
79
|
-
"ai": "^7.0.
|
|
79
|
+
"ai": "^7.0.143",
|
|
80
80
|
"jsonc-parser": "^3.3.1",
|
|
81
81
|
"solid-js": "1.9.12"
|
|
82
82
|
}
|
|
@@ -106,6 +106,25 @@ export function quotaWindowParts(quota, options) {
|
|
|
106
106
|
const parts = windows.map(({ part }) => part);
|
|
107
107
|
return age === undefined ? { windows: parts } : { windows: parts, age };
|
|
108
108
|
}
|
|
109
|
+
/**
|
|
110
|
+
* The narrow label of each scoped window part, as `narrowTextParts` names
|
|
111
|
+
* them: model short names are worked out over every model-scoped window in
|
|
112
|
+
* the reading, so two models never share a short name.
|
|
113
|
+
*/
|
|
114
|
+
function withShortNames(windows) {
|
|
115
|
+
const abbreviations = scopeAbbreviations(windows
|
|
116
|
+
.filter(({ part, scope }) => part.kind === 'window' && scope !== ALL_SCOPE)
|
|
117
|
+
.map(({ scope }) => scope));
|
|
118
|
+
for (const window of windows) {
|
|
119
|
+
window.part.short =
|
|
120
|
+
window.part.kind === 'budget'
|
|
121
|
+
? 'cr'
|
|
122
|
+
: window.scope === ALL_SCOPE
|
|
123
|
+
? window.part.name
|
|
124
|
+
: (abbreviations.get(window.scope) ?? window.scope);
|
|
125
|
+
}
|
|
126
|
+
return windows;
|
|
127
|
+
}
|
|
109
128
|
/**
|
|
110
129
|
* `quotaWindowParts` with each window's scope kept beside it. The narrow form
|
|
111
130
|
* needs the scope to name and pick model-scoped windows; the public parts do
|
|
@@ -128,6 +147,7 @@ function scopedWindowParts(quota, options) {
|
|
|
128
147
|
part: {
|
|
129
148
|
kind: 'window',
|
|
130
149
|
name: quotaWindowName(limit),
|
|
150
|
+
short: '',
|
|
131
151
|
figure: percentLeft(limit.remainingPercent ?? 0),
|
|
132
152
|
remainingPercent,
|
|
133
153
|
checkedAt: limit.checkedAt,
|
|
@@ -149,6 +169,7 @@ function scopedWindowParts(quota, options) {
|
|
|
149
169
|
part: {
|
|
150
170
|
kind: 'budget',
|
|
151
171
|
name: 'credits',
|
|
172
|
+
short: '',
|
|
152
173
|
figure,
|
|
153
174
|
...(remainingPercent === undefined
|
|
154
175
|
? {}
|
|
@@ -158,6 +179,7 @@ function scopedWindowParts(quota, options) {
|
|
|
158
179
|
},
|
|
159
180
|
});
|
|
160
181
|
}
|
|
182
|
+
withShortNames(windows);
|
|
161
183
|
if (windows.length > 0) {
|
|
162
184
|
const age = now - Math.min(...windows.map(({ part }) => part.checkedAt));
|
|
163
185
|
if (age > (options.staleAfterMs ?? QUOTA_STALE_AFTER_MS)) {
|
|
@@ -298,20 +320,21 @@ function narrowTextParts(quota, options) {
|
|
|
298
320
|
return grouped;
|
|
299
321
|
const general = windows.filter(({ part, scope }) => part.kind === 'window' && scope === ALL_SCOPE);
|
|
300
322
|
const scoped = windows.filter(({ part, scope }) => part.kind === 'window' && scope !== ALL_SCOPE);
|
|
301
|
-
const abbreviations = scopeAbbreviations(scoped.map(({ scope }) => scope));
|
|
302
323
|
// The items competing for the one slot after the account-wide windows, in
|
|
303
324
|
// tie-break order: scoped windows in display order, then the budget. A
|
|
304
325
|
// spent budget counts as 0% left; one without a percentage cannot compete.
|
|
326
|
+
// Their labels are the parts' short names, so the narrow line and a layout
|
|
327
|
+
// reading `short` always agree.
|
|
305
328
|
const budget = windows.find(({ part }) => part.kind === 'budget');
|
|
306
329
|
const budgetLeft = budget?.spent ? 0 : budget?.part.remainingPercent;
|
|
307
330
|
const extras = [
|
|
308
|
-
...scoped.map(({
|
|
309
|
-
label:
|
|
331
|
+
...scoped.map(({ part }) => ({
|
|
332
|
+
label: part.short,
|
|
310
333
|
remaining: part.remainingPercent ?? 0,
|
|
311
334
|
})),
|
|
312
|
-
...(budgetLeft === undefined
|
|
335
|
+
...(budgetLeft === undefined || budget === undefined
|
|
313
336
|
? []
|
|
314
|
-
: [{ label:
|
|
337
|
+
: [{ label: budget.part.short, remaining: budgetLeft }]),
|
|
315
338
|
];
|
|
316
339
|
// Strictly lower wins, so on a tie the earlier item keeps the slot.
|
|
317
340
|
const tightest = extras.reduce((best, item) => best === undefined || item.remaining < best.remaining ? item : best, undefined);
|
|
@@ -357,3 +380,25 @@ export function formatQuota(quota, options) {
|
|
|
357
380
|
? NO_LIMITS_REPORTED
|
|
358
381
|
: NO_QUOTA_READING;
|
|
359
382
|
}
|
|
383
|
+
/**
|
|
384
|
+
* Prepaid credits as one short value, worded as the official Codex client's
|
|
385
|
+
* status view words them: `Unlimited` for unlimited credits, `<n> credits`
|
|
386
|
+
* for a finite positive balance (rounded to a whole number), `Available` when
|
|
387
|
+
* the account has credits but no usable balance was reported, and undefined
|
|
388
|
+
* when the account has no credits (or `credits` is undefined), so a caller
|
|
389
|
+
* shows no credits row at all. Unlimited wins even when `hasCredits` is false.
|
|
390
|
+
* No other formatter adds this text; a caller that wants a credits row asks
|
|
391
|
+
* for it.
|
|
392
|
+
*/
|
|
393
|
+
export function quotaCreditsText(credits) {
|
|
394
|
+
if (credits === undefined)
|
|
395
|
+
return undefined;
|
|
396
|
+
if (credits.unlimited)
|
|
397
|
+
return 'Unlimited';
|
|
398
|
+
if (!credits.hasCredits)
|
|
399
|
+
return undefined;
|
|
400
|
+
const { balance } = credits;
|
|
401
|
+
return typeof balance === 'number' && Number.isFinite(balance) && balance > 0
|
|
402
|
+
? `${Math.round(balance)} credits`
|
|
403
|
+
: 'Available';
|
|
404
|
+
}
|
|
@@ -4,6 +4,7 @@ import { ClaustrumUnreachableError, classifyVaultFailure, } from "./94f53cfd572b
|
|
|
4
4
|
import { readClaustrumEnrollmentToken } from "./b9588ad4725c1d10-enrollment.js";
|
|
5
5
|
import { ClaustrumConsumerError } from "./ca0fccaba1d87af4-errors.js";
|
|
6
6
|
import { CUSTODY_PLACEHOLDER_PREFIX } from "./d9d2892a4c371301-host-slot.js";
|
|
7
|
+
import { ScopedRosterWatch, } from "./dc9290c2a7552ba6-watch.js";
|
|
7
8
|
/** Only a new version of the same account may replace an in-flight 401. */
|
|
8
9
|
export function isScopedCredentialRotation(served, current) {
|
|
9
10
|
return (current !== undefined &&
|
|
@@ -132,6 +133,9 @@ export class ClaustrumScopedCustody {
|
|
|
132
133
|
#lastProbeAt = -Infinity;
|
|
133
134
|
#probeDelay = 2_000;
|
|
134
135
|
#closed = false;
|
|
136
|
+
/** The view of the last successful `discover()`, for `watchRoster`. */
|
|
137
|
+
#discoveredView;
|
|
138
|
+
#watches = new Set();
|
|
135
139
|
constructor(options) {
|
|
136
140
|
const tokenPath = options.tokenPath;
|
|
137
141
|
if (options.readToken) {
|
|
@@ -197,7 +201,9 @@ export class ClaustrumScopedCustody {
|
|
|
197
201
|
this.#probing = true;
|
|
198
202
|
// Both triggers share list_scoped discovery, including its receipt-drop rules.
|
|
199
203
|
// Sends never await discovery or let idle backoff delay the next send probe.
|
|
200
|
-
|
|
204
|
+
// A probe commits no roster, so it is not the host's discovery and does
|
|
205
|
+
// not move the view a roster watch compares notices against.
|
|
206
|
+
void this.#list()
|
|
201
207
|
.catch(() => {
|
|
202
208
|
if (idle && this.#outage)
|
|
203
209
|
this.#probeDelay = Math.min(this.#probeDelay * 2, 30_000);
|
|
@@ -271,6 +277,11 @@ export class ClaustrumScopedCustody {
|
|
|
271
277
|
* skipped records: they simply are not this consumer's.
|
|
272
278
|
*/
|
|
273
279
|
async discover(signal) {
|
|
280
|
+
const inventory = await this.#list(signal);
|
|
281
|
+
this.#discoveredView = inventory.view;
|
|
282
|
+
return inventory;
|
|
283
|
+
}
|
|
284
|
+
async #list(signal) {
|
|
274
285
|
let inventory;
|
|
275
286
|
let token;
|
|
276
287
|
try {
|
|
@@ -567,6 +578,61 @@ export class ClaustrumScopedCustody {
|
|
|
567
578
|
throw error;
|
|
568
579
|
}
|
|
569
580
|
}
|
|
581
|
+
/**
|
|
582
|
+
* Watch this consumer's visible vault accounts instead of listing them on a
|
|
583
|
+
* short timer. Opens one `watchScoped` on this custody's client and calls
|
|
584
|
+
* `onView` when the host must run its discovery (see
|
|
585
|
+
* `ClaustrumRosterWatchOptions`). A claustrum-client without `watchScoped`
|
|
586
|
+
* (before 0.12.0) or a vault that answers `unknown_method` reports
|
|
587
|
+
* `fallback` and opens nothing. A watch that closes before any notice was
|
|
588
|
+
* never accepted: the client reads once to learn why, and the watch reports
|
|
589
|
+
* `fallback` and tries one new watch after `WATCH_RETRY_MS`, never in a
|
|
590
|
+
* loop. A watch that closes after notices is re-opened after
|
|
591
|
+
* `RESUBSCRIBE_BACKOFF_MS`, doubling per close in a row. A lost transport
|
|
592
|
+
* starts this custody's outage, exactly as an unreachable call does, and
|
|
593
|
+
* the first notice of a watch ends it. Timers are unreferenced; `close()`
|
|
594
|
+
* on the returned watch or on this custody stops it.
|
|
595
|
+
*
|
|
596
|
+
* The watch keeps no history, so the host still lists on a slow timer while
|
|
597
|
+
* the mode is `watching`: every `SAFETY_POLL_MS` (five minutes). In any
|
|
598
|
+
* other mode the host keeps its usual list timer.
|
|
599
|
+
*/
|
|
600
|
+
watchRoster(options) {
|
|
601
|
+
this.#check();
|
|
602
|
+
const watch = new ScopedRosterWatch({
|
|
603
|
+
client: this.#client,
|
|
604
|
+
enrollmentToken: () => this.#token(),
|
|
605
|
+
view: options.view ?? (() => this.#discoveredView),
|
|
606
|
+
discover: async (view) => {
|
|
607
|
+
await options.onView(view);
|
|
608
|
+
},
|
|
609
|
+
onRefused: (error) => {
|
|
610
|
+
// Apply a refused watch as discover() applies a refused account
|
|
611
|
+
// listing: every kept receipt is dropped.
|
|
612
|
+
this.listFailed(error);
|
|
613
|
+
options.onRefused?.(error);
|
|
614
|
+
},
|
|
615
|
+
onTransportLost: () => this.transportLost(),
|
|
616
|
+
onReachable: () => this.reachable(),
|
|
617
|
+
onError: options.onError,
|
|
618
|
+
onMode: options.onMode,
|
|
619
|
+
logger: this.#logger,
|
|
620
|
+
now: this.#now,
|
|
621
|
+
setTimeoutImpl: this.#setTimeout,
|
|
622
|
+
clearTimeoutImpl: this.#clearTimeout,
|
|
623
|
+
});
|
|
624
|
+
this.#watches.add(watch);
|
|
625
|
+
watch.start();
|
|
626
|
+
return {
|
|
627
|
+
get mode() {
|
|
628
|
+
return watch.mode;
|
|
629
|
+
},
|
|
630
|
+
close: () => {
|
|
631
|
+
this.#watches.delete(watch);
|
|
632
|
+
watch.stop();
|
|
633
|
+
},
|
|
634
|
+
};
|
|
635
|
+
}
|
|
570
636
|
close() {
|
|
571
637
|
if (this.#closed)
|
|
572
638
|
return;
|
|
@@ -574,6 +640,9 @@ export class ClaustrumScopedCustody {
|
|
|
574
640
|
if (this.#probeTimer)
|
|
575
641
|
this.#clearTimeout(this.#probeTimer);
|
|
576
642
|
this.#probeTimer = undefined;
|
|
643
|
+
for (const watch of this.#watches)
|
|
644
|
+
watch.stop();
|
|
645
|
+
this.#watches.clear();
|
|
577
646
|
this.#kept.clear();
|
|
578
647
|
this.#client.close();
|
|
579
648
|
}
|