@cortexkit/opencode-openai-auth 1.2.0 → 1.3.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 +2 -2
- package/dist/{codex-request-CjXETpTA.d.ts → codex-request-B9D0e97Q.d.ts} +145 -28
- package/dist/{index-ehjj89rx.js → index-1mbgsxsr.js} +1 -1
- package/dist/{index-htvcmtcx.js → index-2pgkrebq.js} +1 -1
- package/dist/{index-rwbrhkse.js → index-4v2fs42x.js} +1 -1
- package/dist/index-8x1aj7q3.js +2 -0
- package/dist/{index-6n4pnfkg.js → index-ex6nx3mq.js} +1 -1
- package/dist/{index-qxbchh2d.js → index-gn2b097f.js} +1 -1
- package/dist/{index-qp5hdpw8.js → index-m3ctrabv.js} +1 -1
- package/dist/{index-03em8hv1.js → index-psjyexj3.js} +15 -15
- package/dist/{index-ffg0sgg5.js → index-tddr876f.js} +1 -1
- package/dist/index-tn8x5tz8.js +90 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/{model-CQcw10oW.d.ts → model-BdITTmeb.d.ts} +1 -1
- package/dist/{port-file-BDJnzgHH.d.ts → port-file-DbHIVC9a.d.ts} +1 -1
- package/dist/{protocol-C-kagE6O.d.ts → protocol-MysYPAho.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/{sidebar-state-BfQ4mpZO.d.ts → sidebar-state-CVSok7zv.d.ts} +20 -4
- package/dist/sidebar-state.d.ts +1 -1
- package/dist/sidebar-state.js +1 -1
- package/dist/tui-preferences.js +1 -1
- package/dist/tui.d.ts +2 -2
- package/dist/v2/server.d.ts +2 -2
- package/dist/v2/server.js +1 -1
- package/package.json +4 -4
- package/src/tui-compiled/raw/shared/0332701351b3eeec-format.js +69 -1
- package/src/tui-compiled/raw/shared/0f77ebc3c914c9c6-custody.js +225 -16
- package/src/tui-compiled/raw/shared/169b2b4bf30909bc-consumer.js +130 -5
- package/src/tui-compiled/raw/shared/375d9cca2def037d-private-files.js +10 -2
- package/src/tui-compiled/raw/shared/94f53cfd572ba4bb-availability.js +106 -0
- package/src/tui-compiled/raw/shared/d0f0b6be200311af-insula.js +286 -21
- package/src/tui-compiled/raw/shared/dc9290c2a7552ba6-watch.js +253 -0
- package/src/tui-compiled/raw/shared/e8d3c8da776ef9cd-index.js +4 -1
- package/src/tui-compiled/runtime/shared/0332701351b3eeec-format.js +69 -1
- package/src/tui-compiled/runtime/shared/0f77ebc3c914c9c6-custody.js +225 -16
- package/src/tui-compiled/runtime/shared/169b2b4bf30909bc-consumer.js +130 -5
- package/src/tui-compiled/runtime/shared/375d9cca2def037d-private-files.js +10 -2
- package/src/tui-compiled/runtime/shared/94f53cfd572ba4bb-availability.js +106 -0
- package/src/tui-compiled/runtime/shared/d0f0b6be200311af-insula.js +286 -21
- package/src/tui-compiled/runtime/shared/dc9290c2a7552ba6-watch.js +253 -0
- package/src/tui-compiled/runtime/shared/e8d3c8da776ef9cd-index.js +4 -1
- package/dist/index-f21addzm.js +0 -90
- package/dist/index-r2s51ac1.js +0 -2
package/dist/sidebar-state.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{$b as w,Fb as a,Gb as b,Hb as c,Ib as d,Jb as e,Kb as f,Lb as g,Mb as h,Nb as i,Ob as j,Pb as k,Qb as l,Rb as m,Sb as n,Tb as o,Ub as p,Vb as q,Wb as r,Xb as s,Yb as t,Zb as u,_b as v,ac as x,bc as y,cc as z,dc as A,ec as B,fc as C,gc as D,hc as E,ic as F,jc as G,kc as H,lc as I,mc as J,nc as K,oc as L,pc as M,qc as N,rc as O,sc as P,tc as Q,uc as R}from"./index-
|
|
1
|
+
import{$b as w,Fb as a,Gb as b,Hb as c,Ib as d,Jb as e,Kb as f,Lb as g,Mb as h,Nb as i,Ob as j,Pb as k,Qb as l,Rb as m,Sb as n,Tb as o,Ub as p,Vb as q,Wb as r,Xb as s,Yb as t,Zb as u,_b as v,ac as x,bc as y,cc as z,dc as A,ec as B,fc as C,gc as D,hc as E,ic as F,jc as G,kc as H,lc as I,mc as J,nc as K,oc as L,pc as M,qc as N,rc as O,sc as P,tc as Q,uc as R}from"./index-ex6nx3mq.js";import"./index-tn8x5tz8.js";import"./index-gn2b097f.js";import"./index-1mbgsxsr.js";import"./index-8x1aj7q3.js";import"./index-xwvze96g.js";export{w as upsertSidebarActiveRouting,n as spendControlExhaustedResetAt,M as sidebarQuotaProjection,G as settleWithinBudget,u as setSidebarState,v as setSidebarMachineState,x as setSidebarLegacyRouting,c as setLegacySidebarStateFileForTest,A as resolveSidebarStickyAssignment,q as resolveSessionStickyAccount,r as resolveSessionSidebarRouting,L as resolveActiveAccount,y as removeSidebarActiveRouting,I as rememberStickyPin,t as pruneStickyAssignments,s as pruneActiveRouting,B as planSidebarStickyAssignmentFromSnapshot,z as planSidebarStickyAssignment,C as persistSidebarStickyAssignment,i as normalizeSidebarState,m as isUsableRoutingEntry,p as isQuotaExhausted,f as hashSidebarSessionId,g as getSidebarStateFile,j as getSidebarState,b as getPresentQuotaWindows,N as getCollapsedQuotaSummary,O as getCollapsedAccountLines,a as formatWindowLabel,Q as fitCollapsedLabel,o as exhaustedQuotaResetAt,E as drainSidebarWrites,P as displayWidth,H as createSidebarStateCache,K as createSidebarBookkeepingQueue,R as computeQuotaPacing,D as clearSidebarStickyAssignment,J as applyStickyPinOverlay,e as STICKY_ASSIGNMENT_MAX_ENTRIES,d as STICKY_ASSIGNMENT_MAX_AGE_MS,F as HOT_PATH_READ_BUDGET_MS,h as DEFAULT_SIDEBAR_STATE,l as ACTIVE_ROUTING_MAX_ENTRIES,k as ACTIVE_ROUTING_MAX_AGE_MS};
|
package/dist/tui-preferences.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{je as h,pe as u,qe as P}from"./index-
|
|
1
|
+
import{je as h,pe as u,qe as P}from"./index-gn2b097f.js";import{Pe as M,Qe as R,Ve as S}from"./index-8x1aj7q3.js";import"./index-xwvze96g.js";import{mkdir as Yq,writeFile as Vq}from"node:fs/promises";import{homedir as Wq}from"node:os";import{dirname as Dq,join as b}from"node:path";import{applyEdits as t,modify as r,parse as e}from"jsonc-parser";function qq(z){return z!==null&&typeof z==="object"&&!Array.isArray(z)}async function k(z){try{let q=[],H=e(await S(z,M),q,{allowTrailingComma:!0});return q.length===0&&qq(H)?H:{}}catch(q){if(q instanceof R&&q.code!=="ENOENT")throw q;return{}}}var zq=`// Shared preferences for TUI plugins.
|
|
2
2
|
// Plugins update individual keys in place and preserve comments.
|
|
3
3
|
{}
|
|
4
4
|
`;function g(z){let{file:q,pluginKey:H,beforeCommit:Q}=z,$={...P.preferences,timeoutMs:z.timeoutMs??P.preferences.timeoutMs},Z=Promise.resolve();async function X(U,j){await u(q,$,async(K)=>{let J;try{J=await S(q,M)}catch(G){if(G.code!=="ENOENT")throw G;J=""}if(J.trim()==="")J=zq;let B=t(J,r(J,[H,...U],j,{formattingOptions:{insertSpaces:!0,tabSize:2}}));await h(q,B,{serialize:(G)=>String(G),beforeRename:async()=>{await Q?.(),await K.assertOwned()}})})}return{queueTuiPreferenceUpdate(U,j){let K=[...U],J=structuredClone(j),B=Z.then(()=>X(K,J));return Z=B.catch(()=>{}),B}}}import{readFileSync as Hq,realpathSync as Qq,statSync as Xq,watch as Zq}from"node:fs";import{readFile as $q,stat as Bq}from"node:fs/promises";import{basename as p,dirname as s,join as Gq,resolve as Jq}from"node:path";import{clearTimeout as w,setTimeout as c}from"node:timers";function n(z){let q=Jq(z);if(M)return q;try{return Qq(q)}catch{let H=s(q);return H===q?q:Gq(n(H),p(q))}}function d(z){return z&&`${z.dev}:${z.ino}:${z.mtimeMs}:${z.size}`}function T(z,q,H={}){let Q=globalThis,$=Symbol.for("cortexkit.common-auth.tui-prefs.watchers.v1"),Z=Q[$]??new Map;Q[$]=Z;let X=n(z),U=Z.get(X);if(U)return U.subscribe(q);let j=p(X),K=M?(Y)=>S(Y):H.fs?.readFile??((Y)=>$q(Y,"utf8")),J=H.fs?.stat??Bq,B=null,G=null,x=null,C=null;if(!M)try{let Y=d((H.fs?.statSync??Xq)(X));C=(H.fs?.readFileSync??((V)=>Hq(V,"utf8")))(X),x=Y}catch{}let N=!1,L=new Set,E=Promise.resolve(),v=(Y)=>{return E=E.then(async()=>{if(N)return;let V=d(await J(X).catch(()=>null));if(!Y&&V===x)return;if(V===null){x=null;return}let I=await K(X).catch((W)=>{if(W instanceof R&&W.code!=="ENOENT")if(H.onError)H.onError(W);else process.emitWarning(W.message,W.name);return null});if(N)return;if(I===null)return;if(x=V,I===C)return;C=I;for(let W of[...L]){if(!L.has(W))continue;try{W.notify()}catch{}}}),E},i=()=>{if(N)return;if(B)w(B);B=c(()=>{B=null,v(!0)},150)},O=null;try{O=(H.watchDirectory??Zq)(s(X),(Y,V)=>{let I=V?.toString(),W=I===j||I?.startsWith(`${j}.`)&&I.endsWith(".tmp");if(I!=null&&!W)return;i()}),O.on("error",()=>{O?.close(),O=null})}catch{}let f=()=>{if(N||G)return;G=c(()=>{if(G=null,N)return;v(!1).finally(f)},1000),G.unref()},F={subscribe:(Y)=>{let V={notify:Y};return L.add(V),()=>{if(!L.delete(V)||L.size>0)return;if(N=!0,B)w(B);if(G)w(G);if(O?.close(),Z.get(X)===F)Z.delete(X)}}};return Z.set(X,F),f(),F.subscribe(q)}var Uq="OPENCODE_TUI_PREFERENCES_FILE",Iq="tui-preferences.jsonc";function m(){let z=process.env[Uq];if(z)return z;let q=process.env.OPENCODE_CONFIG_DIR||b(process.env.XDG_CONFIG_HOME||b(Wq(),".config"),"opencode");return b(q,Iq)}function _(z){return typeof z==="object"&&z!==null&&!Array.isArray(z)}function dq(){return k(m())}var Mq="openai-auth",Aq=160,l={forceToTop:!1,order:Aq,startCollapsed:!1,rememberCollapsed:!0,collapsed:null,pollMs:1500,refreshDebounceMs:200,header:{label:"OPENAI",showVersion:!0},sections:{quota:!0,fallbackAccounts:!0,routing:!0,health:!0,pacing:!0},appearance:{barWidth:10,barFilledChar:"█",barEmptyChar:"░",warnThreshold:50,errorThreshold:80}};function D(z,q){return typeof z==="boolean"?z:q}function A(z,q,H,Q){if(typeof z!=="number"||!Number.isFinite(z))return q;return Math.min(Math.max(Math.round(z),H),Q)}function jq(z,q,H){if(typeof z!=="string"||z.length===0)return q;return z.slice(0,H)}function o(z,q){if(typeof z!=="string")return q;return[...z][0]??q}function pq(z){let q=z[Mq];if(!_(q))return structuredClone(l);let H=l,Q=_(q.header)?q.header:{},$=_(q.sections)?q.sections:{},Z=_(q.appearance)?q.appearance:{},X=A(Z.warnThreshold,H.appearance.warnThreshold,0,99),U=Math.max(A(Z.errorThreshold,H.appearance.errorThreshold,0,100),Math.min(X+1,100));return{forceToTop:D(q.forceToTop,H.forceToTop),order:A(q.order,H.order,-1e4,1e4),startCollapsed:D(q.startCollapsed,H.startCollapsed),rememberCollapsed:D(q.rememberCollapsed,H.rememberCollapsed),collapsed:typeof q.collapsed==="boolean"?q.collapsed:null,pollMs:A(q.pollMs,H.pollMs,500,30000),refreshDebounceMs:A(q.refreshDebounceMs,H.refreshDebounceMs,50,5000),header:{label:jq(Q.label,H.header.label,20),showVersion:D(Q.showVersion,H.header.showVersion)},sections:{quota:D($.quota,H.sections.quota),fallbackAccounts:D($.fallbackAccounts,H.sections.fallbackAccounts),routing:D($.routing,H.sections.routing),health:D($.health,H.sections.health),pacing:D($.pacing,H.sections.pacing)},appearance:{barWidth:A(Z.barWidth,H.appearance.barWidth,4,40),barFilledChar:o(Z.barFilledChar,H.appearance.barFilledChar),barEmptyChar:o(Z.barEmptyChar,H.appearance.barEmptyChar),warnThreshold:X,errorThreshold:U}}}var Nq=-1e5;function sq(z,q,H){let Q=z[q];if(!_(Q))return H;if(Q.forceToTop===!0)return Nq+Object.keys(z).indexOf(q);return A(Q.order,H,-1e4,1e4)}var Kq=`// Shared preferences for opencode TUI plugins.
|
package/dist/tui.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { C as SpendControlReading, d as QuotaWindow, r as AccountQuota, u as QuotaPacing, x as SidebarState } from "./sidebar-state-
|
|
2
|
-
import { i as OpenDialogPayload, n as ApplyResult, t as ApplyRequest } from "./protocol-
|
|
1
|
+
import { C as SpendControlReading, d as QuotaWindow, r as AccountQuota, u as QuotaPacing, x as SidebarState } from "./sidebar-state-CVSok7zv.js";
|
|
2
|
+
import { i as OpenDialogPayload, n as ApplyResult, t as ApplyRequest } from "./protocol-MysYPAho.js";
|
|
3
3
|
import { Plugin } from "@opencode/plugin/tui";
|
|
4
4
|
import { TuiPluginModule } from "@opencode-ai/plugin/tui";
|
|
5
5
|
import { JSX } from "solid-js";
|
package/dist/v2/server.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { h as BeginAccountLoginResult, i as CodexSessionMetadata, m as BeginAccountLoginOptions, o as PoolLifecycleDeps, p as OpenAiVaultOptions, r as CodexRequestRuntime, s as HostSlotAdapter, x as AccountPaths } from "../codex-request-
|
|
2
|
-
import { i as OpenDialogPayload, n as ApplyResult } from "../protocol-
|
|
1
|
+
import { h as BeginAccountLoginResult, i as CodexSessionMetadata, m as BeginAccountLoginOptions, o as PoolLifecycleDeps, p as OpenAiVaultOptions, r as CodexRequestRuntime, s as HostSlotAdapter, x as AccountPaths } from "../codex-request-B9D0e97Q.js";
|
|
2
|
+
import { i as OpenDialogPayload, n as ApplyResult } from "../protocol-MysYPAho.js";
|
|
3
3
|
import { Plugin } from "@opencode/plugin";
|
|
4
4
|
import "@opencode/plugin/promise/session";
|
|
5
5
|
import "@opencode/plugin/promise/integration";
|
package/dist/v2/server.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{c as uZ}from"../index-
|
|
1
|
+
import{c as uZ}from"../index-m3ctrabv.js";import{$ as s$,A as W$,B as U$,C as IZ,D as fZ,E as W1,F as vZ,G as hZ,H as Z$,I as UZ,J as HZ,K as mZ,L as gZ,M as D$,N as w$,O as S2,P as J$,S as i$,T as a$,aa as t$,d as L$,e as SZ,ea as lZ,f as V2,g as B2,h as b2,i as wZ,j as yZ,k as I2,ka as R1,l as Y2,la as A1,n as E1,o as O1,oa as pZ,p as _1,q as R2,r as C$,s as T$,t as _$,u as q$,v as k$,w as b$,x as p$,y as c$,z as D2}from"../index-4v2fs42x.js";import{Qa as v$,Xa as ZZ,fb as f2,gb as RZ,hb as AZ,ib as xZ,kb as qZ,lb as h$,ub as kZ,va as OZ,vb as bZ,wb as DZ,xb as m$,ya as c1,za as d1}from"../index-psjyexj3.js";import{$b as VZ,Lb as QZ,_b as jZ,bc as BZ,fc as WZ}from"../index-ex6nx3mq.js";import{$c as B1,$d as n1,Cd as Z2,Hd as u1,Jd as B$,Kd as p1,Qd as y2,Sc as q2,Tc as k2,Uc as MZ,Xd as r$,Yd as K2,Zd as i1,_d as a1,ad as h1,bd as m1,be as o1,cd as g1,ce as r1,de as s1,ee as t1,fe as e1,ge as $$,jd as I$,pd as f$,rd as EZ,sd as o$,td as l1,vc as v1}from"../index-tn8x5tz8.js";import{me as K$}from"../index-gn2b097f.js";import{ve as x$}from"../index-2pgkrebq.js";import"../index-tddr876f.js";import{Fe as _Z,He as J2}from"../index-1mbgsxsr.js";import"../index-8x1aj7q3.js";import{bf as S$}from"../index-bc89akak.js";import{ff as v2,gf as TZ}from"../index-xwvze96g.js";import{AsyncLocalStorage as p0}from"node:async_hooks";import{randomUUID as c0}from"node:crypto";class n 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 t($){return`common-auth-placeholder.${$}`}function K1($){let Z=t($.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:t(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)},F=(H)=>async(W)=>{let B=H.method.id,V=await H.authorize(W),L={url:V.url,instructions:V.instructions,...V.expiresAt===void 0?{}:{expiresAt:V.expiresAt}};if(V.mode==="auto")return{...L,mode:"auto",callback:V.callback.then((T)=>Y(T,B))};let x=V.callback;return{...L,mode:"code",callback:async(T)=>Y(await x(T),B)}};return $.integration.transform((H)=>{let W=Z.label===void 0?{}:{label:()=>Z.label};for(let L of Z.methods)H.method.update({integrationID:z,method:L.method,authorize:F(L),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(L)=>{if(!N2(L,z)||L.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 cZ($){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
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};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cortexkit/opencode-openai-auth",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -66,14 +66,14 @@
|
|
|
66
66
|
},
|
|
67
67
|
"devDependencies": {
|
|
68
68
|
"@ai-sdk/openai": "3.0.88",
|
|
69
|
-
"@cortexkit/common-auth": "^0.
|
|
69
|
+
"@cortexkit/common-auth": "^0.21.0",
|
|
70
70
|
"@cortexkit/openai-auth-core": "workspace:*",
|
|
71
71
|
"@opencode/plugin": "2.0.27"
|
|
72
72
|
},
|
|
73
73
|
"dependencies": {
|
|
74
|
-
"@cortexkit/claustrum-client": "^0.
|
|
74
|
+
"@cortexkit/claustrum-client": "^0.12.0",
|
|
75
75
|
"@cortexkit/private-files": "^0.2.1",
|
|
76
|
-
"@cortexkit/subc-client": "^0.
|
|
76
|
+
"@cortexkit/subc-client": "^0.22.0",
|
|
77
77
|
"@opentui/core": ">=0.6.1",
|
|
78
78
|
"@opentui/solid": ">=0.6.1",
|
|
79
79
|
"ai": "^7.0.137",
|
|
@@ -122,6 +122,9 @@ function scopedWindowParts(quota, options) {
|
|
|
122
122
|
const remainingPercent = clampPercent(limit.remainingPercent ?? 0);
|
|
123
123
|
return {
|
|
124
124
|
scope: limit.scope,
|
|
125
|
+
...(limit.windowMinutes === undefined
|
|
126
|
+
? {}
|
|
127
|
+
: { windowMinutes: limit.windowMinutes }),
|
|
125
128
|
part: {
|
|
126
129
|
kind: 'window',
|
|
127
130
|
name: quotaWindowName(limit),
|
|
@@ -212,6 +215,66 @@ function scopeAbbreviations(scopes) {
|
|
|
212
215
|
}
|
|
213
216
|
return new Map(scopes.map((scope) => [scope, short(scopeDisplayName(scope))]));
|
|
214
217
|
}
|
|
218
|
+
/** The most groups a grouped narrow line shows. */
|
|
219
|
+
const NARROW_GROUP_LIMIT = 2;
|
|
220
|
+
/**
|
|
221
|
+
* The names the groups read under in the narrow line, one per listed group:
|
|
222
|
+
* each label's short name, derived exactly as a model window's is (`Gemini`
|
|
223
|
+
* → `Ge`, `Other models` → `Ot`, colliding names extended until they
|
|
224
|
+
* differ), computed over every listed group so a group keeps its name
|
|
225
|
+
* whichever groups show. A blank label falls back to the group's scope.
|
|
226
|
+
*/
|
|
227
|
+
function groupShortNames(groups) {
|
|
228
|
+
const labels = groups.map((group) => group.label.trim() || group.scope);
|
|
229
|
+
const short = scopeAbbreviations(labels);
|
|
230
|
+
return labels.map((label) => short.get(label) ?? label);
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* The narrow line of a reading whose windows belong to named groups and that
|
|
234
|
+
* has no account-wide window: for each group, its tightest window as
|
|
235
|
+
* `Ge 7d 62%`, with ` left` once at the end. The tightest window is the
|
|
236
|
+
* one with least left, compared before rounding; on a tie the first in
|
|
237
|
+
* display order (the shorter window) wins. At most two groups show: the two
|
|
238
|
+
* with least left, earlier-listed first on a tie, and always in the order
|
|
239
|
+
* the reading lists them, so the line does not reorder as the figures move.
|
|
240
|
+
* A group with no reported window is skipped. Windows outside the listed
|
|
241
|
+
* groups and the credit budget are left out. Undefined when the rule does
|
|
242
|
+
* not apply, so the caller uses the ordinary narrow rule.
|
|
243
|
+
*/
|
|
244
|
+
function groupedNarrowPieces(groups, windows) {
|
|
245
|
+
if (!groups || groups.length === 0)
|
|
246
|
+
return undefined;
|
|
247
|
+
const reported = windows.filter(({ part }) => part.kind === 'window');
|
|
248
|
+
if (reported.some(({ scope }) => scope === ALL_SCOPE))
|
|
249
|
+
return undefined;
|
|
250
|
+
const candidates = groups.flatMap((group, listed) => {
|
|
251
|
+
const inGroup = reported.filter(({ scope }) => scope === group.scope);
|
|
252
|
+
// `windows` is already in display order, and strictly lower wins, so on
|
|
253
|
+
// a tie the shorter window keeps the place.
|
|
254
|
+
const groupTightest = inGroup.reduce((least, window) => least === undefined ||
|
|
255
|
+
(window.part.remainingPercent ?? 0) < (least.part.remainingPercent ?? 0)
|
|
256
|
+
? window
|
|
257
|
+
: least, undefined);
|
|
258
|
+
return groupTightest ? [{ group, listed, window: groupTightest }] : [];
|
|
259
|
+
});
|
|
260
|
+
if (candidates.length === 0)
|
|
261
|
+
return undefined;
|
|
262
|
+
const names = groupShortNames(groups);
|
|
263
|
+
const left = (candidate) => candidate.window.part.remainingPercent ?? 0;
|
|
264
|
+
const shown = [...candidates]
|
|
265
|
+
.sort((a, b) => left(a) - left(b) || a.listed - b.listed)
|
|
266
|
+
.slice(0, NARROW_GROUP_LIMIT)
|
|
267
|
+
.sort((a, b) => a.listed - b.listed);
|
|
268
|
+
return shown.map((candidate, index) => {
|
|
269
|
+
const { windowMinutes } = candidate.window;
|
|
270
|
+
const piece = [
|
|
271
|
+
names[candidate.listed] ?? candidate.group.scope,
|
|
272
|
+
...(windowMinutes === undefined ? [] : [lengthName(windowMinutes)]),
|
|
273
|
+
`${wholePercent(left(candidate))}%`,
|
|
274
|
+
].join(' ');
|
|
275
|
+
return index === shown.length - 1 ? `${piece} left` : piece;
|
|
276
|
+
});
|
|
277
|
+
}
|
|
215
278
|
/**
|
|
216
279
|
* The narrow form's pieces: every account-wide window as `5h 92%`, then at
|
|
217
280
|
* most one more item, with ` left` added once to the last piece. That item is
|
|
@@ -224,10 +287,15 @@ function scopeAbbreviations(scopes) {
|
|
|
224
287
|
* be chosen; when nothing at all is shown it keeps its compact wording
|
|
225
288
|
* (`credits available`). No age is added; `isQuotaStale` says whether the
|
|
226
289
|
* reading is stale. A window whose reset arrived after the reading keeps its
|
|
227
|
-
* figure, as in the other forms.
|
|
290
|
+
* figure, as in the other forms. A reading that lists named groups and has no
|
|
291
|
+
* account-wide window reads one item per group instead (see
|
|
292
|
+
* `groupedNarrowPieces`).
|
|
228
293
|
*/
|
|
229
294
|
function narrowTextParts(quota, options) {
|
|
230
295
|
const { windows } = scopedWindowParts(quota, options);
|
|
296
|
+
const grouped = groupedNarrowPieces(quota?.groups, windows);
|
|
297
|
+
if (grouped)
|
|
298
|
+
return grouped;
|
|
231
299
|
const general = windows.filter(({ part, scope }) => part.kind === 'window' && scope === ALL_SCOPE);
|
|
232
300
|
const scoped = windows.filter(({ part, scope }) => part.kind === 'window' && scope !== ALL_SCOPE);
|
|
233
301
|
const abbreviations = scopeAbbreviations(scoped.map(({ scope }) => scope));
|