@cortexkit/opencode-openai-auth 0.3.0 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +5 -4
- package/dist/core/accounts.d.ts +9 -4
- package/dist/core/oauth.d.ts +5 -1
- package/dist/core/quota-manager.d.ts +2 -1
- package/dist/core/refresh-file-lock.d.ts +1 -0
- package/dist/{index-vj00ztg7.js → index-53j7bdev.js} +1 -1
- package/dist/{index-nngfcx1x.js → index-7w467pz8.js} +1 -1
- package/dist/{index-r68prrfg.js → index-899gpxdd.js} +1 -1
- package/dist/index-d9hq0tmc.js +2 -0
- package/dist/{index-qqrj9za2.js → index-gwmhhrrc.js} +1 -1
- package/dist/index-jn8xd8fy.js +3 -0
- package/dist/index-qp2nja20.js +2 -0
- package/dist/index-z21wp7ac.js +92 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +59 -59
- package/dist/logger.d.ts +1 -0
- package/dist/prompt-context.d.ts +19 -0
- package/dist/quota-normalize-dxftsgep.js +1 -0
- package/dist/rpc/port-file.js +1 -1
- package/dist/rpc/rpc-client.js +1 -1
- package/dist/rpc/rpc-dir.js +1 -1
- package/dist/sidebar-state.js +1 -1
- package/dist/{token-c1q4pea2.js → token-28n5g707.js} +1 -1
- package/dist/token-util-gmr2b13z.js +1 -0
- package/dist/tui-preferences.js +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/ws-pool.d.ts +7 -4
- package/package.json +1 -1
- package/src/logger.ts +26 -5
- package/dist/index-1gjhrsep.js +0 -2
- package/dist/index-5j7p33r8.js +0 -2
- package/dist/index-88b7ha2h.js +0 -3
- package/dist/index-pyyjg54f.js +0 -92
- package/dist/quota-normalize-s1bctr9a.js +0 -1
- package/dist/token-util-ff59e4fw.js +0 -1
package/dist/cli.js
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{
|
|
2
|
+
import{E as q,I as B,J as V,q as Y,x as Z,y as $}from"./index-z21wp7ac.js";import"./index-jn8xd8fy.js";import{ja as X}from"./index-53j7bdev.js";import{execFileSync as E}from"node:child_process";function Q(C,H=process.platform,D=E){try{if(H==="win32"){D("cmd",["/c","start","",C],{stdio:"ignore",timeout:3000});return}D(H==="darwin"?"open":"xdg-open",[C],{stdio:"ignore",timeout:3000})}catch{}}function T(){console.log(`Usage:
|
|
3
3
|
npx @cortexkit/opencode-openai-auth login [--label <name>] [--headless]
|
|
4
4
|
npx @cortexkit/opencode-openai-auth list
|
|
5
5
|
npx @cortexkit/opencode-openai-auth remove <id>
|
|
6
6
|
|
|
7
7
|
Fallback accounts are stored in:
|
|
8
|
-
${
|
|
8
|
+
${q()}`)}function P(C){let H=[],D={};for(let M=0;M<C.length;M++){let j=C[M];if(!j)continue;if(j.startsWith("--")){let G=j.slice(2),z=C[M+1];if(z&&!z.startsWith("--"))D[G]=z,M++;else D[G]=!0}else H.push(j)}return{positional:H,flags:D}}async function R(){let{positional:C,flags:H}=P(process.argv.slice(2)),[D,...M]=C;if(!D||D==="help")T(),process.exit(0);switch(D){case"login":{let j=typeof H.label==="string"?H.label:void 0,G=Boolean(H.headless);try{Y(j)}catch(K){console.error(`
|
|
9
|
+
Error: ${K instanceof Error?K.message:String(K)}`),process.exit(1)}let{url:z,instructions:J,completion:O}=await $({label:j,headless:G});if(console.log(`
|
|
9
10
|
Open this URL in your browser and complete sign-in:
|
|
10
11
|
`),console.log(`${z}
|
|
11
12
|
`),J)console.log(`${J}
|
|
12
|
-
`);Q(z);let
|
|
13
|
+
`);Q(z);let N=await O,W=!1;if(await V((K)=>{if(N.accountId&&K.mainAccountId&&N.accountId===K.mainAccountId)return W=!0,K;return Z(K.accounts,N),K}),W)console.error(`
|
|
13
14
|
Error: that account is already your main (same ChatGPT account).`),console.error("A self-fallback would retry on the account that just returned 429."),process.exit(1);if(console.log(`
|
|
14
|
-
✓ Added account ${
|
|
15
|
+
✓ Added account ${N.id}`),N.label)console.log(` Label: ${N.label}`);break}case"list":{let j=await B();if(!j||j.accounts.length===0)console.log("No fallback accounts configured.");else for(let G of j.accounts){let z=G.label,J=[` ${G.id}`];if(z)J.push(`(${z})`);J.push(G.enabled!==!1?"[enabled]":"[disabled]"),console.log(J.join(" "))}break}case"remove":{let j=M[0];if(!j)console.error("Error: remove requires an account ID."),T(),process.exit(1);let G=!1;if(await V((z)=>{let J=z.accounts.findIndex((O)=>O.id===j);if(J===-1)return z;return G=!0,z.accounts.splice(J,1),z}),!G)console.error(`No account with id "${j}".`),process.exit(1);console.log(`Removed account ${j}.`);break}default:console.error(`Unknown command: ${D}`),T(),process.exit(1)}}if(X.main==X.module)R().catch((C)=>{console.error(C instanceof Error?C.message:String(C)),process.exit(1)});export{Q as openBrowserForLogin};
|
package/dist/core/accounts.d.ts
CHANGED
|
@@ -142,6 +142,10 @@ export type AccountRefreshError = {
|
|
|
142
142
|
accountId: string;
|
|
143
143
|
message: string;
|
|
144
144
|
};
|
|
145
|
+
export declare class AccountRemovedDuringRefreshError extends Error {
|
|
146
|
+
readonly code = "ACCOUNT_REMOVED_DURING_REFRESH";
|
|
147
|
+
constructor(accountId: string);
|
|
148
|
+
}
|
|
145
149
|
export declare const DEFAULT_KILLSWITCH_THRESHOLDS: {
|
|
146
150
|
primary: number;
|
|
147
151
|
secondary: number;
|
|
@@ -167,9 +171,9 @@ export declare function saveAccounts(storage: AccountStorage, path?: string): Pr
|
|
|
167
171
|
export declare function mutateAccounts(mutate: (current: AccountStorage) => AccountStorage | undefined, path?: string): Promise<AccountStorage>;
|
|
168
172
|
export declare function saveAccountState(storage: AccountStorage, path?: string, scope?: AccountStateSaveScope): Promise<void>;
|
|
169
173
|
export declare function shouldFallbackStatus(status: number, storage: AccountStorage | null): boolean;
|
|
170
|
-
export declare function quotaSnapshotPassesPolicy(quota: OAuthQuotaSnapshot | undefined, storage: AccountStorage | null): boolean;
|
|
174
|
+
export declare function quotaSnapshotPassesPolicy(quota: OAuthQuotaSnapshot | undefined, storage: AccountStorage | null, now?: number): boolean;
|
|
171
175
|
export declare function isKillswitchEnabled(storage: AccountStorage | null): boolean;
|
|
172
|
-
export declare function killswitchPassesPolicy(quota: OAuthQuotaSnapshot | undefined, storage: AccountStorage | null, accountId?: string): boolean;
|
|
176
|
+
export declare function killswitchPassesPolicy(quota: OAuthQuotaSnapshot | undefined, storage: AccountStorage | null, accountId?: string, now?: number): boolean;
|
|
173
177
|
export declare function killswitchRetryAfterSeconds(mainQuota: OAuthQuotaSnapshot | undefined, fallbackAccounts: Array<{
|
|
174
178
|
quota?: OAuthQuotaSnapshot;
|
|
175
179
|
}>, now: number): number;
|
|
@@ -177,7 +181,7 @@ export declare function killswitchRetryAfterSeconds(mainQuota: OAuthQuotaSnapsho
|
|
|
177
181
|
* Migrate an existing single-slot token into the multi-account store.
|
|
178
182
|
*
|
|
179
183
|
* Reads the existing token via the caller-provided `getAuth` (the ONLY
|
|
180
|
-
* read path — there is no `client.auth.get`).
|
|
184
|
+
* read path — there is no `client.auth.get`). If a token exists and the
|
|
181
185
|
* config file is NOT yet an account store (content discriminator), seeds
|
|
182
186
|
* it as the primary OAuth account.
|
|
183
187
|
*
|
|
@@ -186,7 +190,8 @@ export declare function killswitchRetryAfterSeconds(mainQuota: OAuthQuotaSnapsho
|
|
|
186
190
|
*
|
|
187
191
|
* Tolerates expired/revoked tokens (migrates them; refresh handles validity).
|
|
188
192
|
*
|
|
189
|
-
* Guards against first-run races with
|
|
193
|
+
* Guards against first-run races with the same save-lock order used by
|
|
194
|
+
* structural account mutations.
|
|
190
195
|
*/
|
|
191
196
|
export declare function migrateIfNeeded(existingToken: {
|
|
192
197
|
type: 'oauth';
|
package/dist/core/oauth.d.ts
CHANGED
|
@@ -2,7 +2,9 @@ export declare const CLIENT_ID = "app_EMoamEEZ73f0CkXaXp7hrann";
|
|
|
2
2
|
export declare const ISSUER = "https://auth.openai.com";
|
|
3
3
|
export declare const OAUTH_PORT = 1455;
|
|
4
4
|
export declare const OAUTH_POLLING_SAFETY_MARGIN_MS = 3000;
|
|
5
|
-
export declare const USER_AGENT = "cortexkit-opencode-openai-auth/0.3.
|
|
5
|
+
export declare const USER_AGENT = "cortexkit-opencode-openai-auth/0.3.2";
|
|
6
|
+
export declare const RESERVED_ACCOUNT_ID = "main";
|
|
7
|
+
export declare const RESERVED_ACCOUNT_ID_ERROR = "\"main\" is a reserved account id; choose a different label.";
|
|
6
8
|
export interface PkceCodes {
|
|
7
9
|
verifier: string;
|
|
8
10
|
challenge: string;
|
|
@@ -28,6 +30,8 @@ export interface TokenResponse {
|
|
|
28
30
|
expires_in?: number;
|
|
29
31
|
}
|
|
30
32
|
export declare function extractAccountId(tokens: TokenResponse): string | undefined;
|
|
33
|
+
export declare function isReservedAccountId(value: string | undefined): boolean;
|
|
34
|
+
export declare function assertFallbackAccountIdAllowed<T extends string | undefined>(value: T): T;
|
|
31
35
|
export declare function buildAuthorizeUrl(redirectUri: string, pkce: PkceCodes, state: string): string;
|
|
32
36
|
export declare function exchangeCodeForTokens(code: string, redirectUri: string, pkce: PkceCodes): Promise<TokenResponse>;
|
|
33
37
|
export declare function escapeHtml(value: string): string;
|
|
@@ -8,9 +8,10 @@
|
|
|
8
8
|
* Adapted from anthropic-auth — provider-specific quota fetch injected via
|
|
9
9
|
* fetchQuotaFn instead of hard-importing fetchOAuthQuotaSnapshot.
|
|
10
10
|
*/
|
|
11
|
-
import type { AccountOperationError, AccountStorage, OAuthAccount, OAuthQuotaSnapshot } from './accounts.ts';
|
|
11
|
+
import type { AccountOperationError, AccountQuotaWindow, AccountStorage, OAuthAccount, OAuthQuotaSnapshot } from './accounts.ts';
|
|
12
12
|
import type { ProviderQuotaFn } from './provider.ts';
|
|
13
13
|
export type { ProviderQuotaFn };
|
|
14
|
+
export declare function quotaWindowResetIsPast(window: AccountQuotaWindow | undefined, now: number): boolean;
|
|
14
15
|
/**
|
|
15
16
|
* Stable, non-reversible fingerprint of an access token. Used to detect a
|
|
16
17
|
* main-account switch so a different account's persisted/cached quota is never
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export declare const ACCOUNT_FILE_NAME = "openai-auth.json";
|
|
2
2
|
export declare const ACCOUNT_STATE_FILE_NAME = "openai-auth-state.json";
|
|
3
|
+
export declare function isLostMarkerRaceError(error: unknown): boolean;
|
|
3
4
|
export declare function getAccountStoragePath(): string;
|
|
4
5
|
export declare function getAccountStatePath(configPath?: string): string;
|
|
5
6
|
export declare function acquireRefreshFileLock(options: {
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import{createRequire as s}from"node:module";var j=Object.create;var{getPrototypeOf:k,defineProperty:f,getOwnPropertyNames:l}=Object;var m=Object.prototype.hasOwnProperty;function n(a){return this[a]}var o,p,t=(a,b,c)=>{var g=a!=null&&typeof a==="object";if(g){var h=b?o??=new WeakMap:p??=new WeakMap,i=h.get(a);if(i)return i}c=a!=null?j(k(a)):{};let d=b||!a||!a.__esModule?f(c,"default",{value:a,enumerable:!0}):c;for(let e of l(a))if(!m.call(d,e))f(d,e,{get:n.bind(a,e),enumerable:!0});if(g)h.set(a,d);return d};var u=(a,b)=>()=>(b||a((b={exports:{}}).exports,b),b.exports);var q=(a)=>a;function r(a,b){this[a]=q.bind(null,b)}var v=(a,b)=>{for(var c in b)f(a,c,{get:b[c],enumerable:!0,configurable:!0,set:r.bind(b,c)})};var x=s(import.meta.url);
|
|
2
|
-
export{t as
|
|
2
|
+
export{t as ga,u as ha,v as ia,x as ja};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import{mkdir as u,readdir as l,readFile as c,rename as p,unlink as m,writeFile as d}from"node:fs/promises";import{join as a}from"node:path";function f(t){try{return process.kill(t,0),!0}catch(r){return r.code==="EPERM"}}async function b(t,r){await u(t,{recursive:!0});let s={...r,startedAt:Date.now()},e=a(t,`port-${r.pid}.json`),i=`${e}.${process.pid}.tmp`;return await d(i,JSON.stringify(s),{encoding:"utf8",mode:384}),await p(i,e),e}async function h(t,r){let s;try{s=await l(t)}catch{return null}let e=[];for(let n of s){if(!n.startsWith("port-")||!n.endsWith(".json"))continue;try{let o=JSON.parse(await c(a(t,n),"utf8"));if(Number.isFinite(o.port))if(f(o.pid))e.push(o);else m(a(t,n)).catch(()=>{})}catch{}}if(e.length===0)return null;let i=r!==void 0&&r>=1?e.filter((n)=>n.pid===r):[];return(i.length>0?i:e).sort((n,o)=>o.startedAt-n.startedAt)[0]??null}
|
|
2
|
-
export{b as
|
|
2
|
+
export{b as ca,h as da};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{ha as Y,ja as K}from"./index-53j7bdev.js";var V=Y((rz,O)=>{var{defineProperty:J,getOwnPropertyDescriptor:r,getOwnPropertyNames:t}=Object,e=Object.prototype.hasOwnProperty,o=(z,B)=>{for(var F in B)J(z,F,{get:B[F],enumerable:!0})},zz=(z,B,F,H)=>{if(B&&typeof B==="object"||typeof B==="function"){for(let G of t(B))if(!e.call(z,G)&&G!==F)J(z,G,{get:()=>B[G],enumerable:!(H=r(B,G))||H.enumerable})}return z},Bz=(z)=>zz(J({},"__esModule",{value:!0}),z),M={};o(M,{VercelOidcTokenError:()=>j});O.exports=Bz(M);class j extends Error{constructor(z,B){super(z);this.name="VercelOidcTokenError",this.cause=B}toString(){if(this.cause)return`${this.name}: ${this.message}: ${this.cause}`;return`${this.name}: ${this.message}`}}});var C=Y((tz,x)=>{var{create:Fz,defineProperty:v,getOwnPropertyDescriptor:Gz,getOwnPropertyNames:Hz,getPrototypeOf:Kz}=Object,Qz=Object.prototype.hasOwnProperty,Wz=(z,B)=>{for(var F in B)v(z,F,{get:B[F],enumerable:!0})},S=(z,B,F,H)=>{if(B&&typeof B==="object"||typeof B==="function"){for(let G of Hz(B))if(!Qz.call(z,G)&&G!==F)v(z,G,{get:()=>B[G],enumerable:!(H=Gz(B,G))||H.enumerable})}return z},N=(z,B,F)=>(F=z!=null?Fz(Kz(z)):{},S(B||!z||!z.__esModule?v(F,"default",{value:z,enumerable:!0}):F,z)),Xz=(z)=>S(v({},"__esModule",{value:!0}),z),E={};Wz(E,{findRootDir:()=>$z,getUserDataDir:()=>qz});x.exports=Xz(E);var Z=N(K("path")),Yz=N(K("fs")),A=N(K("os")),Zz=V();function $z(){try{let z=process.cwd();while(z!==Z.default.dirname(z)){let B=Z.default.join(z,".vercel");if(Yz.default.existsSync(B))return z;z=Z.default.dirname(z)}}catch(z){throw new Zz.VercelOidcTokenError("Token refresh only supported in node server environments")}return null}function qz(){if(process.env.XDG_DATA_HOME)return process.env.XDG_DATA_HOME;switch(A.default.platform()){case"darwin":return Z.default.join(A.default.homedir(),"Library/Application Support");case"linux":return Z.default.join(A.default.homedir(),".local/share");case"win32":if(process.env.LOCALAPPDATA)return process.env.LOCALAPPDATA;return null;default:return null}}});var c=Y((ez,g)=>{var{create:vz,defineProperty:b,getOwnPropertyDescriptor:bz,getOwnPropertyNames:Uz,getPrototypeOf:Lz}=Object,Jz=Object.prototype.hasOwnProperty,Vz=(z,B)=>{for(var F in B)b(z,F,{get:B[F],enumerable:!0})},y=(z,B,F,H)=>{if(B&&typeof B==="object"||typeof B==="function"){for(let G of Uz(B))if(!Jz.call(z,G)&&G!==F)b(z,G,{get:()=>B[G],enumerable:!(H=bz(B,G))||H.enumerable})}return z},u=(z,B,F)=>(F=z!=null?vz(Lz(z)):{},y(B||!z||!z.__esModule?b(F,"default",{value:z,enumerable:!0}):F,z)),Az=(z)=>y(b({},"__esModule",{value:!0}),z),P={};Vz(P,{isValidAccessToken:()=>wz,readAuthConfig:()=>Rz,writeAuthConfig:()=>Iz});g.exports=Az(P);var $=u(K("fs")),l=u(K("path")),Nz=k();function h(){let z=(0,Nz.getVercelDataDir)();if(!z)throw Error(`Unable to find Vercel CLI data directory. Your platform: ${process.platform}. Supported: darwin, linux, win32.`);return l.join(z,"auth.json")}function Rz(){try{let z=h();if(!$.existsSync(z))return null;let B=$.readFileSync(z,"utf8");if(!B)return null;return JSON.parse(B)}catch(z){return null}}function Iz(z){let B=h(),F=l.dirname(B);if(!$.existsSync(F))$.mkdirSync(F,{mode:504,recursive:!0});$.writeFileSync(B,JSON.stringify(z,null,2),{mode:384})}function wz(z){if(!z.token)return!1;if(typeof z.expiresAt!=="number")return!0;let B=Math.floor(Date.now()/1000);return z.expiresAt>=B}});var p=Y((oz,d)=>{var{defineProperty:w,getOwnPropertyDescriptor:Dz,getOwnPropertyNames:Tz}=Object,Mz=Object.prototype.hasOwnProperty,jz=(z,B)=>{for(var F in B)w(z,F,{get:B[F],enumerable:!0})},Oz=(z,B,F,H)=>{if(B&&typeof B==="object"||typeof B==="function"){for(let G of Tz(B))if(!Mz.call(z,G)&&G!==F)w(z,G,{get:()=>B[G],enumerable:!(H=Dz(B,G))||H.enumerable})}return z},Sz=(z)=>Oz(w({},"__esModule",{value:!0}),z),i={};jz(i,{processTokenResponse:()=>uz,refreshTokenRequest:()=>yz});d.exports=Sz(i);var R=K("os"),Ez="https://vercel.com",xz="cl_HYyOPBNtFMfHhaUn9L4QPfTZz6TP47bp",f=`@vercel/oidc node-${process.version} ${(0,R.platform)()} (${(0,R.arch)()}) ${(0,R.hostname)()}`,I=null;async function Cz(){if(I)return I;let z=`${Ez}/.well-known/openid-configuration`,B=await fetch(z,{headers:{"user-agent":f}});if(!B.ok)throw Error("Failed to discover OAuth endpoints");let F=await B.json();if(!F||typeof F.token_endpoint!=="string")throw Error("Invalid OAuth discovery response");let H=F.token_endpoint;return I=H,H}async function yz(z){let B=await Cz();return await fetch(B,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded","user-agent":f},body:new URLSearchParams({client_id:xz,grant_type:"refresh_token",...z})})}async function uz(z){let B=await z.json();if(!z.ok){let F=typeof B==="object"&&B&&"error"in B?String(B.error):"Token refresh failed";return[Error(F)]}if(typeof B!=="object"||B===null)return[Error("Invalid token response")];if(typeof B.access_token!=="string")return[Error("Missing access_token in response")];if(B.token_type!=="Bearer")return[Error("Invalid token_type in response")];if(typeof B.expires_in!=="number")return[Error("Missing expires_in in response")];return[null,B]}});var k=Y((zB,n)=>{var{create:Pz,defineProperty:U,getOwnPropertyDescriptor:lz,getOwnPropertyNames:hz,getPrototypeOf:gz}=Object,cz=Object.prototype.hasOwnProperty,kz=(z,B)=>{for(var F in B)U(z,F,{get:B[F],enumerable:!0})},a=(z,B,F,H)=>{if(B&&typeof B==="object"||typeof B==="function"){for(let G of hz(B))if(!cz.call(z,G)&&G!==F)U(z,G,{get:()=>B[G],enumerable:!(H=lz(B,G))||H.enumerable})}return z},_=(z,B,F)=>(F=z!=null?Pz(gz(z)):{},a(B||!z||!z.__esModule?U(F,"default",{value:z,enumerable:!0}):F,z)),iz=(z)=>a(U({},"__esModule",{value:!0}),z),m={};kz(m,{assertVercelOidcTokenResponse:()=>D,findProjectInfo:()=>sz,getTokenPayload:()=>mz,getVercelCliToken:()=>dz,getVercelDataDir:()=>fz,getVercelOidcToken:()=>pz,isExpired:()=>nz,loadToken:()=>_z,saveToken:()=>az});n.exports=iz(m);var q=_(K("path")),Q=_(K("fs")),X=V(),L=C(),W=c(),s=p();function fz(){let B=(0,L.getUserDataDir)();if(!B)return null;return q.join(B,"com.vercel.cli")}async function dz(){let z=(0,W.readAuthConfig)();if(!z)return null;if((0,W.isValidAccessToken)(z))return z.token||null;if(!z.refreshToken)return(0,W.writeAuthConfig)({}),null;try{let B=await(0,s.refreshTokenRequest)({refresh_token:z.refreshToken}),[F,H]=await(0,s.processTokenResponse)(B);if(F||!H)return(0,W.writeAuthConfig)({}),null;let G={token:H.access_token,expiresAt:Math.floor(Date.now()/1000)+H.expires_in};if(H.refresh_token)G.refreshToken=H.refresh_token;return(0,W.writeAuthConfig)(G),G.token??null}catch(B){return(0,W.writeAuthConfig)({}),null}}async function pz(z,B,F){let H=`https://api.vercel.com/v1/projects/${B}/token?source=vercel-oidc-refresh${F?`&teamId=${F}`:""}`,G=await fetch(H,{method:"POST",headers:{Authorization:`Bearer ${z}`}});if(!G.ok)throw new X.VercelOidcTokenError(`Failed to refresh OIDC token: ${G.statusText}`);let T=await G.json();return D(T),T}function D(z){if(!z||typeof z!=="object")throw TypeError("Vercel OIDC token is malformed. Expected an object. Please run `vc env pull` and try again");if(!("token"in z)||typeof z.token!=="string")throw TypeError("Vercel OIDC token is malformed. Expected a string-valued token property. Please run `vc env pull` and try again")}function sz(){let z=(0,L.findRootDir)();if(!z)throw new X.VercelOidcTokenError("Unable to find project root directory. Have you linked your project with `vc link?`");let B=q.join(z,".vercel","project.json");if(!Q.existsSync(B))throw new X.VercelOidcTokenError("project.json not found, have you linked your project with `vc link?`");let F=JSON.parse(Q.readFileSync(B,"utf8"));if(typeof F.projectId!=="string"&&typeof F.orgId!=="string")throw TypeError("Expected a string-valued projectId property. Try running `vc link` to re-link your project.");return{projectId:F.projectId,teamId:F.orgId}}function az(z,B){let F=(0,L.getUserDataDir)();if(!F)throw new X.VercelOidcTokenError("Unable to find user data directory. Please reach out to Vercel support.");let H=q.join(F,"com.vercel.token",`${B}.json`),G=JSON.stringify(z);Q.mkdirSync(q.dirname(H),{mode:504,recursive:!0}),Q.writeFileSync(H,G),Q.chmodSync(H,432);return}function _z(z){let B=(0,L.getUserDataDir)();if(!B)throw new X.VercelOidcTokenError("Unable to find user data directory. Please reach out to Vercel support.");let F=q.join(B,"com.vercel.token",`${z}.json`);if(!Q.existsSync(F))return null;let H=JSON.parse(Q.readFileSync(F,"utf8"));return D(H),H}function mz(z){let B=z.split(".");if(B.length!==3)throw new X.VercelOidcTokenError("Invalid token. Please run `vc env pull` and try again");let F=B[1].replace(/-/g,"+").replace(/_/g,"/"),H=F.padEnd(F.length+(4-F.length%4)%4,"=");return JSON.parse(Buffer.from(H,"base64").toString("utf8"))}function nz(z){return z.exp*1000<Date.now()}});
|
|
2
2
|
export{V as a,k as b};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
function A(b){if(b==null||b==="")return;let g=typeof b==="number"?b:Number(b);if(Number.isFinite(g)){let q=g<100000000000?g*1000:g,B=new Date(q);return Number.isNaN(B.getTime())?void 0:B.toISOString()}let z=new Date(b);return Number.isNaN(z.getTime())?void 0:z.toISOString()}function C(b,g){let z=b.get(g);if(z===null||z.trim()==="")return;let q=Number(z);if(!Number.isFinite(q)||q<0||q>100)return;return{usedPercent:q,remainingPercent:100-q,resetsAt:A(b.get(`${g.slice(0,-13)}-reset-at`)??void 0),checkedAt:Date.now()}}function G(b){let g={},z=C(b,"x-codex-primary-used-percent");if(z)g.primary=z;let q=C(b,"x-codex-secondary-used-percent");if(q)g.secondary=q;return g}function D(b){if(!b)return;if(!Number.isFinite(b.used_percent)||b.used_percent<0||b.used_percent>100)return;return{usedPercent:b.used_percent,remainingPercent:100-b.used_percent,resetsAt:A(b.reset_at),checkedAt:Date.now()}}function J(b){let g={},z=D(b.rate_limits?.primary);if(z)g.primary=z;let q=D(b.rate_limits?.secondary);if(q)g.secondary=q;return g}function E(b){if(!b)return;if(!Number.isFinite(b.used_percent)||b.used_percent<0||b.used_percent>100)return;return{usedPercent:b.used_percent,remainingPercent:100-b.used_percent,resetsAt:A(b.reset_at),checkedAt:Date.now()}}function K(b){let g={},z=E(b.rate_limit?.primary_window);if(z)g.primary=z;let q=E(b.rate_limit?.secondary_window);if(q)g.secondary=q;return g}
|
|
2
|
+
export{A as c,G as d,J as e,K as f};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createHash as z}from"node:crypto";import{homedir as A,tmpdir as K}from"node:os";import{join as q,resolve as B}from"node:path";var F="OPENCODE_OPENAI_AUTH_RPC_DIR";function M(f){let k=process.env[F]?.trim();if(k)return B(f,k);let w=z("sha256").update(f).digest("hex").slice(0,16),x=process.env.XDG_STATE_HOME||q(A(),".local","state");return q(x,"cortexkit","openai-auth","rpc",w)}export{K as
|
|
1
|
+
import{createHash as z}from"node:crypto";import{homedir as A,tmpdir as K}from"node:os";import{join as q,resolve as B}from"node:path";var F="OPENCODE_OPENAI_AUTH_RPC_DIR";function M(f){let k=process.env[F]?.trim();if(k)return B(f,k);let w=z("sha256").update(f).digest("hex").slice(0,16),x=process.env.XDG_STATE_HOME||q(A(),".local","state");return q(x,"cortexkit","openai-auth","rpc",w)}export{K as ea,M as fa};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import{appendFileSync as Y,chmodSync as w,existsSync as B,renameSync as N,statSync as C}from"node:fs";import{tmpdir as F}from"node:os";import{join as x}from"node:path";var $={error:0,warn:1,info:2,debug:3,trace:4},A=!1,D=5242880;function X(){return process.env.OPENCODE_OPENAI_AUTH_LOG_FILE??x(F(),"opencode-openai-auth.log")}var G;function k(q){if(q===void 0||q in $)G=q}function I(){if(G)return G;let q=process.env.OPENCODE_OPENAI_AUTH_LOG_LEVEL;if(q&&q in $)return q;return"info"}var K=/^(authorization|x-api-key|cookie|set-cookie|refresh|access|token)$/i;function b(q){if(K.test(q))return!0;let H=q.toLowerCase().replace(/[-_]/g,"");if(H==="chatgptaccountid")return!0;if(H.includes("apikey"))return!0;if(H.endsWith("secret")||H.endsWith("password"))return!0;if(H.endsWith("token")&&!H.endsWith("tokens"))return!0;return!1}var L=/\b(Bearer\s+[\w.-]+|sk-[\w-]+|eyJ[\w.-]+)\b/g;function P(q){return M(q,new WeakSet)}function M(q,H){if(typeof q==="string")return q.replace(L,"***REDACTED***");if(Array.isArray(q)){if(H.has(q))return"[Circular]";H.add(q);let J=q.map((Q)=>M(Q,H));return H.delete(q),J}if(q&&typeof q==="object"){if(H.has(q))return"[Circular]";H.add(q);let J={};for(let[Q,j]of Object.entries(q))J[Q]=b(Q)?"***REDACTED***":M(j,H);return H.delete(q),J}return q}var Z=[],z,_=3;function U(q){try{w(q,384)}catch{}}function g(){try{let q=X();if(!(B(q)&&C(q).size>D))return;for(let J=_-1;J>=1;J--)if(B(`${q}.${J}`)){let Q=`${q}.${J+1}`;N(`${q}.${J}`,Q),U(Q)}let H=`${q}.1`;N(q,H),U(H)}catch{}}function V(){if(!Z.length)return;let q=Z.join("");Z=[];try{g();let H=X();if(B(H))U(H);Y(H,q,{encoding:"utf8",mode:384})}catch{}}function O(){if(!z)z=setTimeout(()=>{z=void 0,V()},500)}if(!A)process.on("exit",V);function p(q){try{return` ${JSON.stringify(P(q))}`}catch{return" [unserializable]"}}function W(q,H,J,Q){if($[H]>$[I()])return;let j=`[${new Date().toISOString()}] ${H.toUpperCase()} [${q}] ${J}`+(Q===void 0?"":p(Q))+`
|
|
2
|
+
`;if(Z.push(j),Z.length>=50)V();else O()}function y(q){return{error:(H,J)=>W(q,"error",H,J),warn:(H,J)=>W(q,"warn",H,J),info:(H,J)=>W(q,"info",H,J),debug:(H,J)=>W(q,"debug",H,J),trace:(H,J)=>W(q,"trace",H,J)}}
|
|
3
|
+
export{k as $,P as aa,y as ba};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{ba as v}from"./index-jn8xd8fy.js";import{randomUUID as O}from"node:crypto";import{mkdir as N,readFile as C,rename as g,rm as h,writeFile as k}from"node:fs/promises";import{tmpdir as L}from"node:os";import{dirname as D,join as R}from"node:path";var F=v("sidebar"),M="OPENCODE_OPENAI_AUTH_SIDEBAR_STATE_FILE",I=R(L(),"opencode-openai-auth"),f=R(I,"sidebar-state.json");function W(){return process.env[M]||f}var B={main:{quota:null,killed:!1},fallbacks:[],activeId:void 0,route:"main",lastUpdated:0};function b(K){if(K===null||typeof K!=="object"||Array.isArray(K))return B;let x=K,J=x.main,Q;if(J!==null&&typeof J==="object"&&!Array.isArray(J)){let H=J;Q={quota:"quota"in H?H.quota:null,killed:typeof H.killed==="boolean"?H.killed:!1,...typeof H.quotaBackedOff==="boolean"?{quotaBackedOff:H.quotaBackedOff}:{},...typeof H.quotaBackoffUntil==="number"?{quotaBackoffUntil:H.quotaBackoffUntil}:{},...typeof H.refreshBackedOff==="boolean"?{refreshBackedOff:H.refreshBackedOff}:{},...typeof H.refreshBackoffUntil==="number"?{refreshBackoffUntil:H.refreshBackoffUntil}:{}}}else Q={quota:null,killed:!1};let Y=x.fallbacks,X=Array.isArray(Y)?Y.filter((H)=>H!==null&&typeof H==="object"&&!Array.isArray(H)&&typeof H.id==="string").map((H)=>({id:H.id,label:typeof H.label==="string"?H.label:void 0,quota:"quota"in H?H.quota:null,killed:typeof H.killed==="boolean"?H.killed:!1,enabled:typeof H.enabled==="boolean"?H.enabled:!0})):[],Z=typeof x.activeId==="string"?x.activeId:void 0,V=typeof x.route==="string"?x.route:B.route,$=typeof x.lastUpdated==="number"?x.lastUpdated:0,j=typeof x.planType==="string"?x.planType:void 0,z=typeof x.credits==="number"?x.credits:void 0;return{main:Q,fallbacks:X,activeId:Z,route:V,lastUpdated:$,...j!==void 0?{planType:j}:{},...z!==void 0?{credits:z}:{}}}async function A(){try{let K=await C(W(),"utf8");return b(JSON.parse(K))}catch{return B}}var G=Promise.resolve();function m(K,x=W()){return G=G.then(()=>U(K,x)).catch(()=>{}),G}async function U(K,x){let J=`${x}.${O()}.tmp`;try{await N(D(x),{recursive:!0}),await k(J,JSON.stringify(K),"utf8"),await g(J,x)}catch(Q){await h(J,{force:!0}).catch(()=>{}),F.warn("sidebar write failed",{pid:process.pid,error:Q instanceof Error?Q.message:String(Q)})}}function w(){return G}function c(K){let x=K.activeId;if(x&&x!=="main"){let J=K.fallbacks.find((Q)=>Q.enabled&&Q.id===x);if(J)return{id:J.id,name:J.label??J.id,quota:J.quota,killed:J.killed}}return{id:"main",name:"main",quota:K.main.quota,killed:K.main.killed}}function l(K){let x=K?.primary?.usedPercent??null,J=K?.secondary?.usedPercent??null;if(x==null&&J==null)return{primaryUsedPercent:x,secondaryUsedPercent:J,text:null};return{primaryUsedPercent:x,secondaryUsedPercent:J,text:`5h: ${x==null?"—":`${Math.round(x)}%`} 7d: ${J==null?"—":`${Math.round(J)}%`}`}}var o=18000000,d=604800000,_=300000,y=0.01,S=1;function s(K,x,J){if(!K.resetsAt)return null;let Q=new Date(K.resetsAt).getTime();if(!Number.isFinite(Q))return null;let Y=Q-x,X=J-Y;if(X<_)return null;if(X<x*y)return null;if(X>=x)return null;let Z=K.usedPercent,V=Math.min(Math.max(X/x*100,0),100),$=Z-V,j=Math.abs($)<S?"on-pace":$>0?"deficit":"reserve",z=null;if(Z>0){let H=X*100/Z,q=Y+H;if(q<Q)z=new Date(q).toISOString()}return{pacePercent:V,deltaPercent:$,state:j,runsOutAt:z}}
|
|
2
|
+
export{W as Q,B as R,b as S,A as T,m as U,w as V,c as W,l as X,o as Y,d as Z,s as _};
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import{ba as d0}from"./index-jn8xd8fy.js";import{ja as M2}from"./index-53j7bdev.js";import{createHash as t0}from"node:crypto";var e0=86400000,B2=300000,Z2=3600000,$2=60000,z2=900000,W2=300000;function W0(B){return B instanceof Error?B.message:String(B)}function X2(B){let Z=B?.status;if(typeof Z==="number")return Z===429||Z>=500;if(!(B instanceof Error))return!1;return B.message.includes("fetch failed")||"code"in B&&(B.code==="ECONNRESET"||B.code==="ECONNREFUSED"||B.code==="ETIMEDOUT"||B.code==="UND_ERR_CONNECT_TIMEOUT")}function X0(B){let Z=W0(B),$=B?.status;if(typeof $==="number")return $===429||$>=500;if(!(B instanceof Error))return!1;let z=B.code;return Z.includes("fetch failed")||z==="ECONNRESET"||z==="ECONNREFUSED"||z==="ETIMEDOUT"||z==="UND_ERR_CONNECT_TIMEOUT"}function q0(B){return t0("sha256").update(B).digest("hex")}function C0(B){let Z=q0(B.refreshToken),z=(B.previous?.tokenHash===Z?B.previous.retryCount??0:0)+1,X,W=B.error?.retryAfter;if(typeof W==="number"&&W>0)X=W*1000;else if(X2(B.error))X=Math.min(Z2,B2*2**Math.min(z-1,6));else X=e0;return{message:W0(B.error),checkedAt:B.now,nextRetryAt:B.now+X,retryCount:z,tokenHash:Z}}function q(B,Z,$){if(!B?.nextRetryAt||B.nextRetryAt<=$)return!1;if(!Z)return!0;return B.tokenHash===q0(Z)}function n(B,Z){return`Codex OAuth refresh is backed off for ${Math.max(1,Math.ceil(((B.nextRetryAt??Z)-Z)/1000))}s after: ${B.message}`}function v(B){let $=(B.previous?.retryCount??0)+1,z,X=B.error?.retryAfter;if(typeof X==="number"&&X>0)z=X*1000;else if(X0(B.error))z=Math.min(z2,$2*2**Math.min($-1,6));else z=W2;return{message:W0(B.error),checkedAt:B.now,nextRetryAt:B.now+z,retryCount:$}}function A(B,Z){if(!B?.nextRetryAt||B.nextRetryAt<=Z)return!1;return!0}function G0(B){if(!B)return;let Z=Number(B);if(Number.isFinite(Z)&&Z>0)return Math.ceil(Z);let $=Date.parse(B);if(Number.isFinite($)){let z=Math.ceil(($-Date.now())/1000);return z>0?z:void 0}return}import{createServer as G2}from"node:http";import{setTimeout as K2}from"node:timers/promises";var R0="0.3.2";var o="app_EMoamEEZ73f0CkXaXp7hrann",S="https://auth.openai.com",p=1455,Y2=3000,E0=`cortexkit-opencode-openai-auth/${R0}`,I0="main",J2=`"${I0}" is a reserved account id; choose a different label.`;function x0(B){let Z=new Uint8Array(B),$=String.fromCharCode(...Z);return btoa($).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}async function H2(){let Z=Array.from(crypto.getRandomValues(new Uint8Array(43))).map((z)=>"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~"[z%66]).join(""),$=x0(await crypto.subtle.digest("SHA-256",new TextEncoder().encode(Z)));return{verifier:Z,challenge:$}}function S0(B){if(B.length>16384)return;let Z=B.split(".");if(Z.length!==3)return;let $=Z[1];if(!$||$.length>8192)return;try{return JSON.parse(Buffer.from($,"base64url").toString())}catch{return}}function y0(B){let Z=B.chatgpt_account_id;if(typeof Z==="string"&&Z.length>0)return Z;let $=B["https://api.openai.com/auth"];if($&&typeof $==="object"&&!Array.isArray($)&&typeof $.chatgpt_account_id==="string"&&$.chatgpt_account_id.length>0)return $.chatgpt_account_id;let z=B.organizations;if(Array.isArray(z)){let X=z[0];if(X&&typeof X==="object"&&!Array.isArray(X)&&typeof X.id==="string"&&X.id.length>0)return X.id}return}function a(B){if(B.id_token){let Z=S0(B.id_token),$=Z&&y0(Z);if($)return $}if(B.access_token){let Z=S0(B.access_token);return Z?y0(Z):void 0}return}function j2(B){return typeof B==="string"&&B.toLowerCase()===I0}function K0(B){if(j2(B))throw Error(J2);return B}function Q2(B,Z,$){let z=new URLSearchParams({response_type:"code",client_id:o,redirect_uri:B,scope:"openid profile email offline_access",code_challenge:Z.challenge,code_challenge_method:"S256",id_token_add_organizations:"true",codex_cli_simplified_flow:"true",state:$,originator:"opencode"});return`${S}/oauth/authorize?${z.toString()}`}async function V2(B,Z,$){let z=await fetch(`${S}/oauth/token`,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({grant_type:"authorization_code",code:B,redirect_uri:Z,client_id:o,code_verifier:$.verifier}).toString()});if(!z.ok)throw Error(`Token exchange failed: ${z.status}`);return await z.json()}function N2(B){return B.replaceAll("&","&").replaceAll("<","<").replaceAll(">",">").replaceAll('"',""").replaceAll("'","'")}var L2=`<!doctype html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<title>CortexKit OpenAI Auth - Authorization Successful</title>
|
|
5
|
+
<style>
|
|
6
|
+
body {
|
|
7
|
+
font-family:
|
|
8
|
+
system-ui,
|
|
9
|
+
-apple-system,
|
|
10
|
+
sans-serif;
|
|
11
|
+
display: flex;
|
|
12
|
+
justify-content: center;
|
|
13
|
+
align-items: center;
|
|
14
|
+
height: 100vh;
|
|
15
|
+
margin: 0;
|
|
16
|
+
background: #131010;
|
|
17
|
+
color: #f1ecec;
|
|
18
|
+
}
|
|
19
|
+
.container {
|
|
20
|
+
text-align: center;
|
|
21
|
+
padding: 2rem;
|
|
22
|
+
}
|
|
23
|
+
h1 {
|
|
24
|
+
color: #f1ecec;
|
|
25
|
+
margin-bottom: 1rem;
|
|
26
|
+
}
|
|
27
|
+
p {
|
|
28
|
+
color: #b7b1b1;
|
|
29
|
+
}
|
|
30
|
+
</style>
|
|
31
|
+
</head>
|
|
32
|
+
<body>
|
|
33
|
+
<div class="container">
|
|
34
|
+
<h1>Authorization Successful</h1>
|
|
35
|
+
<p>You can close this window and return to OpenCode.</p>
|
|
36
|
+
</div>
|
|
37
|
+
<script>
|
|
38
|
+
setTimeout(() => window.close(), 2000)
|
|
39
|
+
</script>
|
|
40
|
+
</body>
|
|
41
|
+
</html>`,c=(B)=>`<!doctype html>
|
|
42
|
+
<html>
|
|
43
|
+
<head>
|
|
44
|
+
<title>CortexKit OpenAI Auth - Authorization Failed</title>
|
|
45
|
+
<style>
|
|
46
|
+
body {
|
|
47
|
+
font-family:
|
|
48
|
+
system-ui,
|
|
49
|
+
-apple-system,
|
|
50
|
+
sans-serif;
|
|
51
|
+
display: flex;
|
|
52
|
+
justify-content: center;
|
|
53
|
+
align-items: center;
|
|
54
|
+
height: 100vh;
|
|
55
|
+
margin: 0;
|
|
56
|
+
background: #131010;
|
|
57
|
+
color: #f1ecec;
|
|
58
|
+
}
|
|
59
|
+
.container {
|
|
60
|
+
text-align: center;
|
|
61
|
+
padding: 2rem;
|
|
62
|
+
}
|
|
63
|
+
h1 {
|
|
64
|
+
color: #fc533a;
|
|
65
|
+
margin-bottom: 1rem;
|
|
66
|
+
}
|
|
67
|
+
p {
|
|
68
|
+
color: #b7b1b1;
|
|
69
|
+
}
|
|
70
|
+
.error {
|
|
71
|
+
color: #ff917b;
|
|
72
|
+
font-family: monospace;
|
|
73
|
+
margin-top: 1rem;
|
|
74
|
+
padding: 1rem;
|
|
75
|
+
background: #3c140d;
|
|
76
|
+
border-radius: 0.5rem;
|
|
77
|
+
}
|
|
78
|
+
</style>
|
|
79
|
+
</head>
|
|
80
|
+
<body>
|
|
81
|
+
<div class="container">
|
|
82
|
+
<h1>Authorization Failed</h1>
|
|
83
|
+
<p>An error occurred during authorization.</p>
|
|
84
|
+
<div class="error">${N2(B)}</div>
|
|
85
|
+
</div>
|
|
86
|
+
</body>
|
|
87
|
+
</html>`,d,l,O=new Map;function C(){return O.size}function y(B){if(O.delete(B),C()===0)R()}async function b2(){let B=`http://localhost:${p}/auth/callback`;if(d)return{port:p,redirectUri:B};if(l)return l;l=(async()=>{let Z=G2(($,z)=>{let X=new URL($.url||"/",`http://127.0.0.1:${p}`);if(X.pathname==="/auth/callback"){let W=X.searchParams.get("code"),G=X.searchParams.get("state"),K=X.searchParams.get("error"),Y=X.searchParams.get("error_description");if(K){let H=Y||K;if(G){let V=O.get(G);if(V)V.reject(Error(H)),y(G);else if(C()===0)R()}else if(C()===0)R();z.writeHead(200,{"Content-Type":"text/html"}),z.end(c(H));return}if(!G){if(C()===0)R();z.writeHead(400,{"Content-Type":"text/html"}),z.end(c("Missing state parameter"));return}if(!W){if(C()===0)R();z.writeHead(400,{"Content-Type":"text/html"}),z.end(c("Missing authorization code"));return}let J=O.get(G);if(!J){if(C()===0)R();z.writeHead(400,{"Content-Type":"text/html"}),z.end(c("Unknown state — authorization may have expired"));return}y(G),V2(W,B,J.pkce).then((H)=>J.resolve(H)).catch((H)=>J.reject(H)),z.writeHead(200,{"Content-Type":"text/html"}),z.end(L2);return}if(X.pathname==="/cancel"){let W=X.searchParams.get("state"),G=W?[W]:[...O.keys()];z.writeHead(200),z.end("Login cancelled");for(let K of G){let Y=O.get(K);if(!Y)continue;Y.reject(Error("Login cancelled")),y(K)}if(C()===0)R();return}z.writeHead(404),z.end("Not found")});return await new Promise(($,z)=>{Z.once("error",z),Z.listen(p,"127.0.0.1",()=>{Z.off("error",z),$()})}),d=Z,{port:p,redirectUri:B}})();try{return await l}finally{l=void 0}}function R(){if(d){let B=d;d=void 0,B.close(()=>{}),B.closeIdleConnections?.(),setTimeout(()=>{B.closeAllConnections?.()},25).unref?.()}}function D2(B,Z,$=300000,z){return new Promise((X,W)=>{if(z?.aborted){y(Z),W(Error("Login cancelled"));return}let G=setTimeout(()=>{if(O.get(Z))y(Z),W(Error("OAuth callback timeout — authorization took too long"))},$),K=()=>{if(clearTimeout(G),O.get(Z))y(Z),W(Error("Login cancelled"))};if(z)z.addEventListener("abort",K);O.set(Z,{pkce:B,state:Z,resolve:(Y)=>{if(clearTimeout(G),z)z.removeEventListener("abort",K);X(Y)},reject:(Y)=>{if(clearTimeout(G),z)z.removeEventListener("abort",K);W(Y)}})})}async function F2(){let B=await fetch(`${S}/api/accounts/deviceauth/usercode`,{method:"POST",headers:{"Content-Type":"application/json","User-Agent":E0},body:JSON.stringify({client_id:o})});if(!B.ok)throw Error("Failed to initiate device authorization");let Z=await B.json();return{deviceData:Z,url:`${S}/codex/device`,instructions:`Enter code: ${Z.user_code}`}}async function O2(B,Z){let $=Math.max(parseInt(B.interval,10)||5,1)*1000,z=typeof B.expires_in==="number"?B.expires_in:parseInt(B.expires_in||"",10),X=!Number.isNaN(z)&&z>0?z*1000:900000,W=Date.now();while(!0){if(Z?.aborted)throw Error("Device authorization cancelled");if(Date.now()-W>X)throw Error("Device authorization expired");let G=await fetch(`${S}/api/accounts/deviceauth/token`,{method:"POST",headers:{"Content-Type":"application/json","User-Agent":E0},body:JSON.stringify({device_auth_id:B.device_auth_id,user_code:B.user_code})});if(G.ok){let J=await G.json(),H=await fetch(`${S}/oauth/token`,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({grant_type:"authorization_code",code:J.authorization_code,redirect_uri:`${S}/deviceauth/callback`,client_id:o,code_verifier:J.code_verifier}).toString()});if(!H.ok)throw Error(`Token exchange failed: ${H.status}`);return await H.json()}if(G.status!==403&&G.status!==404)throw Error(`Device authorization failed: ${G.status}`);let K=X-(Date.now()-W);if(K<=0)throw Error("Device authorization expired");let Y=Math.min($+Y2,K);try{await K2(Y,void 0,{signal:Z})}catch(J){if(J instanceof Error&&J.name==="AbortError")throw Error("Device authorization cancelled");throw J}}}function c3(B,Z){let $=-1;if(Z.accountId)$=B.findIndex((z)=>z.accountId&&z.accountId===Z.accountId);if($<0)$=B.findIndex((z)=>z.id===Z.id);if($<0&&Z.label&&!Z.accountId)$=B.findIndex((z)=>z.label===Z.label);if($>=0)return B[$]={...B[$],...Z,addedAt:B[$]?.addedAt??Z.addedAt},$;return B.push(Z),B.length-1}async function a3(B={}){let{label:Z,headless:$=!1,signal:z}=B;if(K0(Z),$){let{deviceData:J,url:H,instructions:V}=await F2(),D=(async()=>{let Q=await O2(J,z),N=Date.now(),_=a(Q);return{id:K0(Z||_||crypto.randomUUID()),label:Z||void 0,type:"oauth",access:Q.access_token,refresh:Q.refresh_token,expires:N+(Q.expires_in??3600)*1000,enabled:!0,addedAt:N,lastUsed:N,lastRefreshedAt:N,accountId:_}})();return{url:H,instructions:V,completion:D}}let{redirectUri:X}=await b2(),W=await H2(),G=x0(crypto.getRandomValues(new Uint8Array(32)).buffer),K=Q2(X,W,G),Y=(async()=>{try{if(z?.aborted)throw Error("Login cancelled");let J=await D2(W,G,void 0,z),H=Date.now(),V=a(J);return{id:K0(Z||V||crypto.randomUUID()),label:Z||void 0,type:"oauth",access:J.access_token,refresh:J.refresh_token,expires:H+(J.expires_in??3600)*1000,enabled:!0,addedAt:H,lastUsed:H,lastRefreshedAt:H,accountId:V}}finally{y(G)}})();return{url:K,instructions:"Complete authorization in your browser. This window will close automatically.",completion:Y}}var t="primary",e="secondary",P2="app_EMoamEEZ73f0CkXaXp7hrann",U2="https://auth.openai.com";async function e3(B){let Z=await B.fetchImpl(`${U2}/oauth/token`,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({grant_type:"refresh_token",refresh_token:B.refreshToken,client_id:P2}).toString()});if(!Z.ok){let z=G0(Z.headers.get("retry-after"));throw Object.assign(Error(`Token refresh failed: ${Z.status}`),{status:Z.status,retryAfter:z,isRefreshError:!0})}let $=await Z.json();if(!$||typeof $.access_token!=="string"||!$.access_token||typeof $.refresh_token!=="string"||!$.refresh_token||typeof $.expires_in!=="number")throw Object.assign(Error("Token refresh failed: malformed response"),{status:Z.status,isRefreshError:!0});return{access:$.access_token,refresh:$.refresh_token,expires:B.now()+$.expires_in*1000,expiresIn:$.expires_in}}var _2="https://chatgpt.com/backend-api/wham/usage";async function BB(B){let Z=await B.fetchImpl(_2,{headers:{authorization:`Bearer ${B.accessToken}`,"chatgpt-account-id":B.accountId??"","oai-client-platform":"web","oai-client-version":"0","x-openai-target-path":"/backend-api/wham/usage"}});if(!Z.ok){let z=G0(Z.headers.get("retry-after"));throw Object.assign(Error(`wham usage check failed: ${Z.status}`),{status:Z.status,retryAfter:z})}let{normalizeWham:$}=await import("./quota-normalize-dxftsgep.js");return $(await Z.json())}import{randomUUID as Y0}from"node:crypto";import{mkdir as q2,readFile as J0,rename as C2,rm as g,stat as A0,writeFile as H0}from"node:fs/promises";import{homedir as R2}from"node:os";import{dirname as GB,join as i}from"node:path";var S2=globalThis.setTimeout.bind(globalThis),y2=globalThis.clearTimeout.bind(globalThis),E2="openai-auth.json";function I2(){if(process.env.OPENCODE_CONFIG_DIR?.trim())return process.env.OPENCODE_CONFIG_DIR.trim();return i(process.env.XDG_CONFIG_HOME||i(R2(),".config"),"opencode")}function x2(B){let Z=B?.code;return Z==="ENOENT"||Z==="EINVAL"||Z==="ENOTDIR"}function A2(){return process.env.OPENCODE_OPENAI_AUTH_FILE?.trim()||i(I2(),E2)}async function T(B){let $=`${B.path??A2()}.${B.name}.lock`,z=i($,"owner.json"),X=Y0(),W=B.now??Date.now,G=null,K=!1;async function Y(){try{return JSON.parse(await J0($,"utf8"))}catch(Q){if(Q.code!=="EISDIR")throw Q;return JSON.parse(await J0(z,"utf8"))}}async function J(){await H0($,`${JSON.stringify({ownerId:X,expiresAt:W()+B.ttlMs})}
|
|
88
|
+
`,{encoding:"utf8",mode:384})}async function H(){try{return await H0($,`${JSON.stringify({ownerId:X,expiresAt:W()+B.ttlMs})}
|
|
89
|
+
`,{encoding:"utf8",mode:384,flag:"wx"}),!0}catch(Q){let N=Q.code;if(N==="EEXIST"||N==="EISDIR")return!1;throw Q}}function V(){if(!B.renew||K)return;let Q=B.renewIntervalMs??Math.max(1000,Math.floor(B.ttlMs/3));if(G=S2(()=>{(async()=>{try{let N=await Y(),_=W();if(K||N?.ownerId!==X||Number(N?.expiresAt)<=_)return;await J(),V()}catch{}})()},Q),"unref"in G)G.unref()}let D=await H();if(!D){let Q=`${$}.evicting`,N=i(Q,"owner.json"),_=Y0(),p3=5000,l3=8;async function r(){await new Promise((F)=>setTimeout(F,Math.floor(Math.random()*4)))}async function O0(){try{let F=await Y();return Number(F?.expiresAt)>W()}catch{try{return(await A0($)).mtimeMs+B.ttlMs>W()}catch{return!1}}}async function k(){try{return JSON.parse(await J0(N,"utf8"))?.ownerId===_}catch{return!1}}async function o0(){await q2(Q);try{await H0(N,`${JSON.stringify({ownerId:_,createdAt:W()})}
|
|
90
|
+
`,{encoding:"utf8",mode:384,flag:"wx"})}catch(F){if(x2(F))return!1;throw await M0(),F}return await B.onStep?.("eviction-marker-acquired"),!0}async function M0(){if(await k())await g(Q,{recursive:!0,force:!0}).catch(()=>{})}for(let F=0;F<8;F++){if(D=await H(),D)break;if(await O0())return null;try{if(!await o0()){await r();continue}}catch(P0){if(P0.code!=="EEXIST")throw P0;let U0;try{U0=await A0(Q)}catch(h){if(h.code==="ENOENT"){await r();continue}throw h}if(U0.mtimeMs+5000>W())return null;await B.onStep?.("stale-marker-stat");let _0=`${Q}.${Y0()}`;try{await C2(Q,_0)}catch(h){if(h.code==="ENOENT"){await r();continue}throw h}await B.onStep?.("stale-marker-claimed"),await g(_0,{recursive:!0,force:!0}).catch(()=>{}),await r();continue}try{if(await O0())return null;if(!await k())return null;if(await B.onStep?.("stale-lock-confirmed"),!await k())return null;if(await g($,{recursive:!0,force:!0}).catch(()=>{}),!await k())return null;if(D=await H(),!D)return null;if(!await k())return await g($,{recursive:!0,force:!0}).catch(()=>{}),D=!1,null;break}finally{await M0()}}}if(!D)return null;return V(),{release:async()=>{if(K=!0,G)y2(G),G=null;try{if((await Y())?.ownerId!==X)return}catch{return}await g($,{recursive:!0,force:!0}).catch(()=>{})}}}import{createHash as T2}from"node:crypto";var f2=globalThis.setTimeout,m2=5;function f(B){let Z=B?.quota?.checkIntervalMinutes??m2;return Math.max(1,Z)*60000}function w2(B){return B?.quota?.enabled!==!1}function j0(B,Z){if(!B?.resetsAt)return!1;let $=Date.parse(B.resetsAt);return Number.isFinite($)&&$<=Z}function k2(B){let Z=B?.quota?.minimumRemaining||{};return{primary:Z.primary??Z["5h"]??15,secondary:Z.secondary??Z["1w"]??10}}function T0(B,Z,$){if(!w2(Z))return $+f(Z);let z=k2(Z),X=[];for(let W of["primary","secondary"]){let G=B?.[W];if(!G)return $+f(Z);if(G.remainingPercent>=z[W])continue;let K=G.resetsAt?Date.parse(G.resetsAt):Number.NaN;if(!Number.isFinite(K)||K<=$)return $+f(Z);X.push(K)}if(!X.length)return $+f(Z);return Math.min(...X)+60000}function h2(B){if(!B?.quota?.mainQuota||!B.quota.mainQuotaCheckedAt)return null;return{quota:B.quota.mainQuota,checkedAt:B.quota.mainQuotaCheckedAt,tokenFingerprint:B.quota.mainQuotaToken}}function v2(B){let Z=B?.quota?.refreshEveryNRequests;return typeof Z==="number"&&Number.isFinite(Z)&&Z>0?Math.floor(Z):0}function b(B){return T2("sha256").update(B).digest("hex").slice(0,16)}class M{main=null;mainTokenFp=null;mainQuotaAccountId=null;fallbacks=new Map;fallbackTokenFps=new Map;inflightMain=null;inflightMainFp=null;inflightFallbacks=new Map;mainLastApiError=void 0;fallbackApiErrors=new Map;fallbackErrorTokenFps=new Map;apiGate=Promise.resolve();lastApiCallAt=0;storage;fetchImpl;now;fetchQuotaFn;onMainQuotaFetched;onApiError;constructor(B){this.storage=B.storage,this.fetchImpl=B.fetchImpl??fetch,this.now=B.now??Date.now,this.fetchQuotaFn=B.fetchQuotaFn,this.onMainQuotaFetched=B.onMainQuotaFetched,this.onApiError=B.onApiError,this.seedMainFromStorage(B.storage),this.seedMainBackoffFromStorage(B.storage)}getMain(B){if(B&&this.main&&this.mainTokenFp&&this.mainTokenFp!==b(B))this.main=null,this.mainTokenFp=null;return this.main}getFallback(B,Z){let $=this.fallbacks.get(B)??null;if(!Z||!$)return $;if(this.fallbackTokenFps.get(B)!==b(Z))return this.fallbacks.delete(B),this.fallbackTokenFps.delete(B),null;return $}getAllFallbacks(){return this.fallbacks}setMain(B,Z,$){if(!f0(Z.quota))return;if(this.mainTokenFp=b(B),$)this.mainQuotaAccountId=$;this.main=Z}peekMainForPolicy(B){if(B&&this.mainQuotaAccountId&&this.mainQuotaAccountId!==B)return null;return this.main}peekFallbackForPolicy(B){return this.fallbacks.get(B)??null}setFallback(B,Z,$){if(!f0(Z.quota))return;if(this.fallbacks.set(B,Z),$)this.fallbackTokenFps.set(B,b($));else this.fallbackTokenFps.delete(B)}async refreshMain(B){let Z=b(B);if(this.mainTokenFp&&this.mainTokenFp!==Z)this.main=null,this.mainTokenFp=null;if(this.inflightMain&&this.inflightMainFp===Z)return this.inflightMain;if(this.isBackedOff()){if(this.main)return this.main.quota;throw Error("Quota API rate-limited — try again later")}return this.inflightMainFp=Z,this.inflightMain=this._fetchMain(B),this.inflightMain}async refreshFallback(B,Z){let $=M.fallbackInflightKey(B,Z),z=this.inflightFallbacks.get($);if(z)return z;if(this.isFallbackBackedOff(B,Z)){let W=this.getFallback(B,Z);if(W)return W.quota;throw Error("Quota API rate-limited — try again later")}let X=this._fetchFallback(B,Z);return this.inflightFallbacks.set($,X),X}async refreshAllFallbacks(B){let Z=this.now();for(let $ of B){if($.enabled===!1)continue;if(!$.access)continue;let z=this.getFallback($.id,$.access);if(z&&Z<z.refreshAfter)continue;try{await this.refreshFallback($.id,$.access)}catch{}}}refreshMainInBackground(B){let Z=b(B);if(this.inflightMain&&this.inflightMainFp===Z)return;if(this.isBackedOff())return;this.refreshMain(B).catch(()=>{})}isMainStale(){if(!this.main)return!0;return this.now()>=this.main.refreshAfter}isFallbackStale(B,Z){let $=this.getFallback(B,Z);if(!$)return!0;return this.now()>=$.refreshAfter}shouldRefreshOnRequestCount(B){let Z=v2(this.storage);if(Z<=0)return!1;return B>0&&B%Z===0}needsRefresh(B){return this.isMainStale()||this.shouldRefreshOnRequestCount(B)}updateStorage(B){this.storage=B,this.seedMainFromStorage(B),this.seedMainBackoffFromStorage(B)}seedMainFromStorage(B,Z){let $=h2(B);if(!$)return;let z=Z?b(Z):null;if(z&&$.tokenFingerprint&&$.tokenFingerprint!==z)return;let X={quota:$.quota,refreshAfter:T0($.quota,B,$.checkedAt),checkedAt:$.checkedAt};if(this.main&&this.main.checkedAt>=X.checkedAt&&(!z||!this.mainTokenFp||this.mainTokenFp===z))return;if(this.main=X,this.mainTokenFp=$.tokenFingerprint??null,B?.mainAccountId)this.mainQuotaAccountId=B.mainAccountId}seedMainBackoffFromStorage(B){let Z=B?.quota?.mainLastQuotaApiError;this.mainLastApiError=Z&&A(Z,this.now())?Z:void 0}seedFallbacksFromAccounts(B){let Z=f(this.storage);for(let $ of B){if($.enabled===!1)continue;if(!$.quota)continue;let z=Math.max($.quota.primary?.checkedAt??0,$.quota.secondary?.checkedAt??0);if(z<=0)continue;let X=this.getFallback($.id,$.access);if(X&&X.checkedAt>=z)continue;this.setFallback($.id,{quota:$.quota,refreshAfter:z+Z,checkedAt:z},$.access)}}isBackedOff(){return A(this.mainLastApiError,this.now())}isFallbackBackedOff(B,Z){if(Z){if(this.fallbackErrorTokenFps.get(B)!==b(Z))return!1}return A(this.fallbackApiErrors.get(B),this.now())}getLastApiError(){return this.mainLastApiError}static API_CALL_GAP_MS=1000;static fallbackInflightKey(B,Z){return JSON.stringify([B,b(Z)])}static quotaLockName(B){return`opencode-fallback-quota-refresh-${B.replace(/[^a-zA-Z0-9._-]+/g,"-")||"account"}`}_enqueueApiFetch(B){let Z=async()=>{let z=this.now()-this.lastApiCallAt;if(z<M.API_CALL_GAP_MS)await new Promise((X)=>{let W=f2(X,M.API_CALL_GAP_MS-z);if(typeof W==="object"&&"unref"in W)W.unref()});return this.lastApiCallAt=this.now(),B()},$=this.apiGate.then(Z,Z);return this.apiGate=$.catch(()=>{}),$}async _fetchMain(B){let Z=b(B);return this._enqueueApiFetch(async()=>{try{if(this.isBackedOff()){if(this.main)return this.main.quota;throw Error("Quota API rate-limited — try again later")}let $=await T({name:"opencode-main-quota-refresh",ttlMs:30000});if(!$){let z=this.main;if(z&&this.now()<z.refreshAfter)return z.quota;throw Error("Quota refresh is already in progress")}try{let z=this.now(),X=await this._fetchQuota(B),W=this.now();return this.mainTokenFp=b(B),this.main={quota:X,refreshAfter:T0(X,this.storage,W),checkedAt:W},this.mainLastApiError=void 0,this.onMainQuotaFetched?.(X,W,this.mainTokenFp,z),X}catch(z){throw this._handleMainFetchError(z),z}finally{await $.release()}}finally{if(this.inflightMainFp===Z)this.inflightMain=null,this.inflightMainFp=null}})}async _fetchFallback(B,Z){return this._enqueueApiFetch(async()=>{try{if(this.isFallbackBackedOff(B,Z)){let z=this.getFallback(B,Z);if(z)return z.quota;throw Error("Quota API rate-limited — try again later")}let $=await T({name:M.quotaLockName(B),ttlMs:30000});if(!$){let z=this.getFallback(B,Z);if(z&&this.now()<z.refreshAfter)return z.quota;throw Error("Quota refresh is already in progress")}try{let z=await this._fetchQuota(Z),X=this.now();return this.setFallback(B,{quota:z,refreshAfter:X+f(this.storage),checkedAt:X},Z),this.fallbackApiErrors.delete(B),this.fallbackErrorTokenFps.delete(B),z}finally{await $.release()}}catch($){throw this._handleFallbackFetchError(B,Z,$),$}finally{this.inflightFallbacks.delete(M.fallbackInflightKey(B,Z))}})}async _fetchQuota(B){if(!this.fetchQuotaFn)throw Error("Quota fetch not available — no fetchQuotaFn injected (push-only mode)");return this.fetchQuotaFn({accessToken:B,fetchImpl:this.fetchImpl,now:this.now})}static isAuthError(B){return B?.status===401}_handleMainFetchError(B){if(M.isAuthError(B))return;this.mainLastApiError=v({error:B,now:this.now(),previous:this.mainLastApiError}),this.onApiError?.(this.mainLastApiError)}_handleFallbackFetchError(B,Z,$){if(M.isAuthError($))return;let z=b(Z),X=this.fallbackErrorTokenFps.get(B)===z?this.fallbackApiErrors.get(B):void 0;this.fallbackApiErrors.set(B,v({error:$,now:this.now(),previous:X})),this.fallbackErrorTokenFps.set(B,z)}}function f0(B){for(let Z of Object.keys(B))return!0;return!1}import{createHash as s2,randomUUID as r2}from"node:crypto";import{homedir as n2}from"node:os";import{dirname as c2,join as B0}from"node:path";import{setTimeout as a2}from"node:timers/promises";import{randomUUID as p2}from"node:crypto";import{mkdir as l2,rename as d2,rm as g2,writeFile as i2}from"node:fs/promises";import{dirname as u2}from"node:path";async function m(B,Z){await l2(u2(B),{recursive:!0});let $=`${B}.${p2()}.tmp`;await i2($,`${JSON.stringify(Z,null,2)}
|
|
91
|
+
`,{encoding:"utf8",mode:384});try{await d2($,B)}catch(z){throw await g2($,{force:!0}).catch(()=>{}),z}}import{readFile as K3}from"node:fs/promises";var E=d0("refresh"),m0=1e4,o2=50,g0="openai-auth.json",t2="openai-auth-state.json";function e2(){if(process.env.OPENCODE_CONFIG_DIR?.trim())return process.env.OPENCODE_CONFIG_DIR.trim();return B0(process.env.XDG_CONFIG_HOME||B0(n2(),".config"),"opencode")}function w(){return process.env.OPENCODE_OPENAI_AUTH_FILE?.trim()||B0(e2(),g0)}function z0(B=w()){let Z=process.env.OPENCODE_OPENAI_AUTH_STATE_FILE?.trim();if(Z)return Z;return B3(B)}function B3(B){return B.endsWith(g0)?B0(c2(B),t2):`${B}.state.json`}function P(B){return B.type==="oauth"}function Z3(B){let Z=B?.trim();if(!Z)return!1;try{let $=new URL(Z);return($.protocol==="http:"||$.protocol==="https:")&&!$.username&&!$.password}catch{return!1}}function SB(B){return B.costZeroing?.enabled!==!1}class Z0 extends Error{code="ACCOUNT_REMOVED_DURING_REFRESH";constructor(B){super(`Fallback account ${B} was removed before refresh`);this.name="AccountRemovedDuringRefreshError"}}var $3=[401,403,429],w0={primary:0,secondary:0},z3=!1,N0={primary:5,secondary:10};function j(B){return B!=null&&typeof B==="object"&&!Array.isArray(B)}function W3(B){return B instanceof Z0||j(B)&&B.name==="AccountRemovedDuringRefreshError"&&B.code==="ACCOUNT_REMOVED_DURING_REFRESH"}function k0(B){return{id:typeof B.id==="string"&&B.id.trim()?B.id.trim():r2(),label:typeof B.label==="string"?B.label:void 0,enabled:typeof B.enabled==="boolean"?B.enabled:void 0,addedAt:typeof B.addedAt==="number"?B.addedAt:void 0,lastUsed:typeof B.lastUsed==="number"?B.lastUsed:void 0,accountId:typeof B.accountId==="string"?B.accountId:void 0}}function h0(B){if(!j(B))return;if(typeof B.message!=="string")return;let Z=Number(B.checkedAt);if(!Number.isFinite(Z))return;let $=Number(B.nextRetryAt),z=Number(B.retryCount);return{message:B.message,checkedAt:Z,nextRetryAt:Number.isFinite($)?$:void 0,retryCount:Number.isFinite(z)?z:void 0,tokenHash:typeof B.tokenHash==="string"?B.tokenHash:void 0}}function X3(B){if(!j(B))return;let Z={};for(let $ of["primary","secondary"]){let z=B[$];if(!j(z))continue;let X=Number(z.usedPercent),W=Number(z.remainingPercent),G=Number(z.checkedAt);if(!Number.isFinite(X)||!Number.isFinite(W)||!Number.isFinite(G))continue;Z[$]={usedPercent:X,remainingPercent:W,checkedAt:G,resetsAt:typeof z.resetsAt==="string"?z.resetsAt:void 0}}return Object.keys(Z).length?Z:void 0}function G3(B){if(!j(B))return null;if(B.type==="api"){let Z=typeof B.baseURL==="string"?B.baseURL.trim():"",$=typeof B.apiKey==="string"?B.apiKey.trim():"";if(!Z3(Z))return null;let z=B.authHeader==="x-api-key"?"x-api-key":"authorization-bearer";return{...k0(B),type:"api",apiKey:$||void 0,baseURL:Z,authHeader:z}}if(B.type!=="oauth")return null;if(typeof B.refresh!=="string"||!B.refresh.trim())return null;return{...k0(B),type:"oauth",access:typeof B.access==="string"?B.access:void 0,refresh:B.refresh,expires:typeof B.expires==="number"?B.expires:void 0,lastRefreshedAt:typeof B.lastRefreshedAt==="number"?B.lastRefreshedAt:void 0,lastRefreshError:h0(B.lastRefreshError),lastQuotaRefreshError:h0(B.lastQuotaRefreshError),quota:X3(B.quota)}}function i0(B){if(!j(B)||!Array.isArray(B.accounts))return null;return{version:1,main:{type:"opencode",provider:"openai"},routing:j(B.routing)?B.routing:void 0,fallbackOn:Array.isArray(B.fallbackOn)?B.fallbackOn.filter((Z)=>Number.isInteger(Z)):void 0,refresh:j(B.refresh)?B.refresh:void 0,quota:j(B.quota)?B.quota:void 0,dump:j(B.dump)?B.dump:void 0,costZeroing:j(B.costZeroing)?B.costZeroing:void 0,killswitch:j(B.killswitch)?B.killswitch:void 0,logging:j(B.logging)?B.logging:void 0,cachekeep:j(B.cachekeep)?B.cachekeep:void 0,mainAccountId:typeof B.mainAccountId==="string"?B.mainAccountId:void 0,accounts:B.accounts.map(G3).filter((Z)=>Z!=null)}}async function x(B){try{return{exists:!0,value:JSON.parse(await K3(B,"utf8"))}}catch(Z){if(Z.code==="ENOENT")return{exists:!1,value:null};throw Z}}function U(B){return Object.fromEntries(Object.entries(B).filter(([,Z])=>Z!==void 0))}async function Y3(B){let Z;try{Z=(await x(B)).value}catch{return null}if(!j(Z)||!Array.isArray(Z.accounts))return null;let $=new Set;for(let z of Z.accounts)if(j(z)&&typeof z.id==="string")$.add(z.id);return $}function u0(B,Z){if(!j(B))return B;let $=j(Z)?Z:{},z=j($.main)?$.main:void 0,X=j($.accounts)?$.accounts:{},W=j(B.quota)?B.quota:{},G=j(B.refresh)?B.refresh:{},K=z??W,Y=z??G,H=Array.isArray(B.accounts)?B.accounts.map((V)=>{if(!j(V))return V;let D=typeof V.id==="string"&&j(X[V.id])?X[V.id]:{};return{...V,...D}}):void 0;return s0({...B,refresh:U({...G,mainLastRefreshError:Y.lastRefreshError,mainRefreshLeaseId:Y.refreshLeaseId,mainRefreshLeaseUntil:Y.refreshLeaseUntil,mainRefreshLeaseTokenHash:Y.refreshLeaseTokenHash}),quota:U({...W,mainQuota:K.quota,mainQuotaCheckedAt:K.quotaCheckedAt,mainQuotaToken:K.quotaToken,mainLastQuotaApiError:K.lastQuotaApiError}),accounts:H})}async function J3(B=w()){let Z=await x(B);if(!Z.exists)return null;let $=await x(z0(B));return i0(u0(Z.value,$.value))}function s0(B){return Object.fromEntries(Object.entries(B).filter(([,Z])=>Z!==void 0))}function H3(B){return U({id:B.id,label:B.label,type:B.type,enabled:B.enabled,addedAt:B.addedAt,accountId:B.accountId,baseURL:B.type==="api"?B.baseURL:void 0,authHeader:B.type==="api"?B.authHeader:void 0})}function r0(B){if(B.type==="api")return U({apiKey:B.apiKey,lastUsed:B.lastUsed});return U({access:B.access,refresh:B.refresh,expires:B.expires,lastUsed:B.lastUsed,lastRefreshedAt:B.lastRefreshedAt,lastRefreshError:B.lastRefreshError,lastQuotaRefreshError:B.lastQuotaRefreshError,quota:B.quota})}function $0(B){return Math.max(B?.primary?.checkedAt??0,B?.secondary?.checkedAt??0)}function u(B,Z,$){if($ in Z)B[$]=Z[$];else delete B[$]}function j3(B,Z){return B.access===Z.access&&B.refresh===Z.refresh&&B.expires===Z.expires&&B.lastRefreshedAt===Z.lastRefreshedAt}function Q3(B,Z){if(!j3(B,Z))return Z;if(!("lastRefreshError"in Z))return B;if(!("lastRefreshError"in B))return Z;return(Z.lastRefreshError?.checkedAt??0)>(B.lastRefreshError?.checkedAt??0)?Z:B}function V3(B,Z,$){let z=Z.lastRefreshedAt??0,X=$.lastRefreshedAt??0,W=Z.expires??0,G=$.expires??0,K=X>z?$:z>X?Z:G>W?$:W>G?Z:Q3(Z,$);u(B,K,"access"),u(B,K,"refresh"),u(B,K,"expires"),u(B,K,"lastRefreshedAt"),u(B,K,"lastRefreshError")}function N3(B,Z){if(!j(B))return Z;let $=B,z=$0($.quota),X=$0(Z.quota),W=z>X,G=W?{...$,...Z,quota:$.quota,lastQuotaRefreshError:$.lastQuotaRefreshError}:{...$,...Z};if(!W&&!("lastQuotaRefreshError"in Z))delete G.lastQuotaRefreshError;if(!("lastRefreshError"in Z))delete G.lastRefreshError;if(typeof $.lastUsed==="number"&&(typeof Z.lastUsed!=="number"||$.lastUsed>Z.lastUsed))G.lastUsed=$.lastUsed;return V3(G,$,Z),G}function n0(B){let Z=B.refresh?U({enabled:B.refresh.enabled,intervalMinutes:B.refresh.intervalMinutes,refreshBeforeExpiryMinutes:B.refresh.refreshBeforeExpiryMinutes}):void 0,$=B.quota?U({enabled:B.quota.enabled,checkIntervalMinutes:B.quota.checkIntervalMinutes,refreshEveryNRequests:B.quota.refreshEveryNRequests,minimumRemaining:B.quota.minimumRemaining,failClosedOnUnknownQuota:B.quota.failClosedOnUnknownQuota,showToasts:B.quota.showToasts}):void 0;return s0({version:1,main:B.main,routing:B.routing,fallbackOn:B.fallbackOn,refresh:Z,quota:$,dump:B.dump,costZeroing:B.costZeroing,killswitch:B.killswitch,logging:B.logging,cachekeep:B.cachekeep,mainAccountId:B.mainAccountId,accounts:B.accounts.map(H3)})}async function s(B){let Z=Date.now()+m0;while(Date.now()<=Z){let $=await T({name:"save",ttlMs:m0,path:B});if($)return $;let z=Z-Date.now();if(z<=0)break;await a2(Math.min(o2,z))}throw Error(`Timed out acquiring account store lock for ${B}; refusing to overwrite newer account data`)}function c0(B){let Z=Object.fromEntries(B.accounts.map(($)=>[$.id,r0($)]));return{version:1,main:U({quota:B.quota?.mainQuota,quotaCheckedAt:B.quota?.mainQuotaCheckedAt,quotaToken:B.quota?.mainQuotaToken,lastQuotaApiError:B.quota?.mainLastQuotaApiError,lastRefreshError:B.refresh?.mainLastRefreshError,refreshLeaseId:B.refresh?.mainRefreshLeaseId,refreshLeaseUntil:B.refresh?.mainRefreshLeaseUntil,refreshLeaseTokenHash:B.refresh?.mainRefreshLeaseTokenHash}),accounts:Z}}async function EB(B,Z=w()){let $=z0(Z),z=await s(Z);try{let X=await s($);try{let W=await x(Z),G=await x($),K=(W.exists?i0(u0(W.value,G.value)):null)??L3(),Y=B(K)??K,H={...j(W.value)?W.value:{},...n0(Y)};return await m(Z,H),await m($,c0(Y)),Y}finally{await X.release()}}finally{await z.release()}}function L3(){return{version:1,main:{type:"opencode",provider:"openai"},accounts:[]}}function b3(B,Z){B.main=B.main??{};let $=typeof B.main.quotaCheckedAt==="number"?B.main.quotaCheckedAt:$0(B.main.quota),z=typeof Z.quota?.mainQuotaCheckedAt==="number"?Z.quota.mainQuotaCheckedAt:$0(Z.quota?.mainQuota);if($>z)return;B.main.quota=Z.quota?.mainQuota,B.main.quotaCheckedAt=Z.quota?.mainQuotaCheckedAt,B.main.quotaToken=Z.quota?.mainQuotaToken,B.main.lastQuotaApiError=Z.quota?.mainLastQuotaApiError}function D3(B,Z){B.main=B.main??{},B.main.lastRefreshError=Z.refresh?.mainLastRefreshError,B.main.refreshLeaseId=Z.refresh?.mainRefreshLeaseId,B.main.refreshLeaseUntil=Z.refresh?.mainRefreshLeaseUntil,B.main.refreshLeaseTokenHash=Z.refresh?.mainRefreshLeaseTokenHash}function L0(B){if(Array.isArray(B))return B.map(L0);if(!j(B))return B;return Object.fromEntries(Object.entries(B).filter(([,Z])=>Z!==void 0).map(([Z,$])=>[Z,L0($)]))}async function F3(B,Z=w(),$={mainQuota:!0,mainRefresh:!0,accounts:!0}){let z=z0(Z),X=await s(z);try{let W=(await x(z)).value,G=j(W)?{...W,version:1}:{version:1};if($.mainQuota)b3(G,B);if($.mainRefresh)D3(G,B);if($.accounts){let K=$.accounts===!0?null:new Set($.accounts),Y=await Y3(Z);G.accounts={...j(G.accounts)?G.accounts:{}};for(let J of B.accounts){if(K&&!K.has(J.id))continue;if(Y&&!Y.has(J.id))continue;G.accounts[J.id]=N3(G.accounts[J.id],r0(J))}if(K){for(let J of K)if(!B.accounts.some((H)=>H.id===J))delete G.accounts[J]}if(Y){for(let J of Object.keys(G.accounts))if(!Y.has(J))delete G.accounts[J]}}await m(z,L0(G))}finally{await X.release()}}function O3(B){return B?.fallbackOn?.length?B.fallbackOn:$3}function IB(B,Z){return O3(Z).includes(B)}function M3(B){let Z=B?.quota?.minimumRemaining||{};return{primary:Z.primary??Z["5h"]??w0.primary,secondary:Z.secondary??Z["1w"]??w0.secondary}}function b0(B){return B?.quota?.enabled!==!1}function F0(B){return B?.quota?.failClosedOnUnknownQuota??z3}function a0(B,Z,$=Date.now()){if(!b0(Z))return!0;let z=M3(Z);for(let X of["primary","secondary"]){let W=B?.[X];if(!W||j0(W,$))return!F0(Z);if(W.remainingPercent<z[X])return!1}return!0}function P3(B){return B?.killswitch?.enabled===!0}function v0(B){return{primary:B?.primary??B?.["5h"]??N0.primary,secondary:B?.secondary??B?.["1w"]??N0.secondary}}function U3(B,Z){if(!B?.killswitch)return N0;if(Z&&B.killswitch.accounts?.[Z])return v0(B.killswitch.accounts[Z]);return v0(B.killswitch.main)}function xB(B,Z,$,z=Date.now()){if(!P3(Z))return!0;let X=U3(Z,$),W=!1;for(let G of["primary","secondary"]){let K=B?.[G];if(!K||j0(K,z)){W=!0;continue}if(K.remainingPercent<X[G])return!1}if(W)return!F0(Z);return!0}function AB(B,Z,$){let z=[],X=[B,...Z.map((G)=>G.quota)];for(let G of X)for(let K of["primary","secondary"]){let Y=G?.[K]?.resetsAt;if(!Y)continue;let J=Date.parse(Y);if(Number.isFinite(J)&&J>$)z.push(J)}if(z.length===0)return 300;let W=Math.min(...z);return Math.max(1,Math.ceil((W-$)/1000))}function _3(B){return typeof B.version==="number"&&Array.isArray(B.accounts)}async function TB(B,Z=w()){let $=z0(Z),z=await s(Z);try{let X=await s($);try{let W=await x(Z);if(W.exists&&j(W.value)){if(_3(W.value))return}if(!B)return;let G={version:1,main:{type:"opencode",provider:"openai"},accounts:[]};if(B.access){let J=a({id_token:"",access_token:B.access,refresh_token:B.refresh});if(J)G.mainAccountId=J}let Y={...W.exists&&j(W.value)?W.value:{},...n0(G)};await m(Z,Y),await m($,c0(G))}finally{await X.release()}}finally{await z.release()}}function q3(B){return B?.refresh?.enabled!==!1}function C3(B){return(B?.refresh?.refreshBeforeExpiryMinutes??240)*60000}function R3(B){return Math.floor(Math.random()*(B+1))}function I(B,Z,$){return!B.access||!B.expires||B.expires-$<=C3(Z)}function S3(B,Z){return Boolean(B.access&&typeof B.expires==="number"&&B.expires>Z)}function y3(B,Z){return Boolean(B.mainAccountId&&Z.accountId&&Z.accountId===B.mainAccountId)}function L(B,Z){let $=B.accounts.findIndex((z)=>z.id===Z.id);if($!==-1)B.accounts[$]=Z}function Q0(B){return B instanceof Error?B.message:String(B)}function D0(B,Z,$){B.lastRefreshError=C0({error:Z,now:$,refreshToken:B.refresh,previous:B.lastRefreshError})}function V0(B,Z,$){if(B.lastQuotaRefreshError=v({error:Z,now:$,previous:B.lastQuotaRefreshError}),Z?.isRefreshError===!0)D0(B,Z,$)}function E3(B){return`fallback-oauth-refresh-${s2("sha256").update(B).digest("base64url").slice(0,16)}`}function p0(B,Z){if(!B)return!1;if(!B.resetsAt)return!0;let $=Date.parse(B.resetsAt);return Number.isFinite($)?$>Z:!0}function I3(B,Z){if(!B)return!1;return p0(B[t],Z)||p0(B[e],Z)}function x3(B,Z,$){if(!B)return!1;let z=Z?.quota?.checkIntervalMinutes??5,X=Math.max(1,z)*60000,W=Math.max(B[t]?.checkedAt??0,B[e]?.checkedAt??0);return $-W<X}function l0(B,Z,$){return!x3(B.quota,Z,$)}function A3(B,Z,$,z){return X0($)&&a0(B.quota,Z,z)&&I3(B.quota,z)}function T3(B){let Z=B?.quota?.checkIntervalMinutes??5;return Math.max(1,Z)*60000}var f3=60000,m3=60000,w3=600000,k3=1e4,h3=100;var fB=globalThis.setTimeout.bind(globalThis),mB=globalThis.clearTimeout.bind(globalThis);class v3{now;fetchImpl;configPath;refreshPromises=new Map;refreshTimer=null;quotaTimer=null;quotaManager;onFallbackStorageChanged;options;constructor(B={}){this.options=B,this.now=B.now??Date.now,this.fetchImpl=B.fetchImpl??fetch,this.configPath=B.configPath??w(),this.quotaManager=B.quotaManager??null,this.onFallbackStorageChanged=B.onFallbackStorageChanged}seedFallbackQuota(B,Z){if(!this.quotaManager)return;if(!B.quota)return;let $=Math.max(B.quota[t]?.checkedAt??0,B.quota[e]?.checkedAt??0);if($<=0)return;let z=this.quotaManager.getFallback(B.id,B.access);if(z&&z.checkedAt>=$)return;this.quotaManager.setFallback(B.id,{quota:B.quota,refreshAfter:$+T3(Z),checkedAt:$},B.access)}async load(){return J3(this.configPath)}async save(B,Z){await F3(B,this.configPath,{accounts:Z??!0})}startBackgroundRefresh(){let B=async()=>{if(await this.refreshDueAccounts(),this.options.fetchQuotaFn)await this.refreshQuotaForDueAccounts()};if(B().catch(()=>{}),!this.refreshTimer){if(this.refreshTimer=setInterval(()=>{B().catch(()=>{})},f3+R3(m3)),"unref"in this.refreshTimer)this.refreshTimer.unref()}}stopBackgroundRefresh(){if(this.refreshTimer)clearInterval(this.refreshTimer);if(this.quotaTimer)clearInterval(this.quotaTimer);this.refreshTimer=null,this.quotaTimer=null}async getUsableFallbackAccounts(B){let Z=B!==void 0?B:await this.load();if(!Z)return[];let $=[],z=!1;for(let X of Z.accounts){if(X.enabled===!1||!P(X))continue;if(y3(Z,X))continue;let W=!1,G=X;try{if(I(G,Z,this.now())){let K=G.lastRefreshError;if(K&&q(K,G.refresh,this.now()))throw W=!0,Error(n(K,this.now()));try{G=await this.refreshAccount(G,Z),z=!0}catch(Y){if(W3(Y))continue;W=!0;let J=Z.accounts.find((H)=>H.id===X.id&&P(H));if(J&&!q(J.lastRefreshError,J.refresh,this.now()))D0(J,Y,this.now()),L(Z,J),z=!0;throw Y}}if(this.seedFallbackQuota(G,Z),this.accountPassesQuotaPolicy(this.quotaPolicyAccount(G),Z))$.push(G)}catch(K){let Y=S3(G,this.now());if(W){if(!Y)continue}else if(!Y)continue;if(A3(G,Z,K,this.now()))E.debug("fallback quota using cached quota after refresh error",{pid:process.pid,accountId:G.id,error:Q0(K)}),$.push(G);else if(!F0(Z))$.push(G)}}if(z)await this.save(Z);return $}async markUsed(B){let Z=await this.load();if(!Z)return;let $=Z.accounts.find((z)=>z.id===B.id);if(!$)return;$.lastUsed=this.now(),await this.save(Z)}accountPassesQuotaPolicy(B,Z){return a0(B.quota,Z,this.now())}quotaPolicyAccount(B){if(!this.quotaManager)return B;let Z=this.quotaManager.getFallback(B.id,B.access)?.quota;return Z?{...B,quota:Z}:B}async refreshDueAccounts(){let B=await this.load();if(!B||!q3(B))return;let Z=!1;for(let $ of B.accounts){if($.enabled===!1||!P($))continue;if(!I($,B,this.now()))continue;if(q($.lastRefreshError,$.refresh,this.now()))continue;try{E.debug("fallback oauth background due",{pid:process.pid,accountId:$.id,expiresInMs:$.expires?$.expires-this.now():void 0}),await this.refreshAccount($,B),Z=!0}catch(z){E.warn("fallback oauth background failed",{pid:process.pid,accountId:$.id,error:Q0(z)}),D0($,z,this.now()),L(B,$),Z=!0}}if(Z)await this.save(B)}async refreshQuotaForDueAccounts(){let B=await this.load();if(!B||!b0(B))return;if(!this.options.fetchQuotaFn)return;let Z=!1;for(let $ of B.accounts){if($.enabled===!1||!P($))continue;let z=$;try{if(I(z,B,this.now())){if(q(z.lastRefreshError,z.refresh,this.now()))continue;z=await this.refreshAccount(z,B),Z=!0}if(A(z.lastQuotaRefreshError,this.now()))continue;if(this.seedFallbackQuota(z,B),!(this.quotaManager?this.quotaManager.isFallbackStale(z.id,z.access):l0(z,B,this.now())))continue;await this.refreshAccountQuota(z,B),Z=!0}catch(X){V0($,X,this.now()),L(B,$),Z=!0}}if(Z)await this.save(B),this.onFallbackStorageChanged?.()}async refreshQuotaForAllAccounts(B={}){let Z=await this.load(),$=[];if(!Z||!b0(Z))return{storage:Z,errors:$};if(!this.options.fetchQuotaFn)return{storage:Z,errors:$};let z=B.force??!1,X=!1;for(let W of Z.accounts){if(W.enabled===!1||!P(W))continue;let G=W;try{if(I(G,Z,this.now())){let K=G.lastRefreshError;if(K&&q(K,G.refresh,this.now()))throw Error(n(K,this.now()));G=await this.refreshAccount(G,Z),X=!0}if(!z&&!l0(G,Z,this.now())){if(G.lastQuotaRefreshError)G.lastQuotaRefreshError=void 0,L(Z,G),X=!0;continue}await this.refreshAccountQuota(G,Z),X=!0}catch(K){V0(W,K,this.now()),L(Z,W),X=!0,$.push({accountId:W.id,message:Q0(K)})}}if(X)await this.save(Z);return{storage:Z,errors:$}}async refreshAccount(B,Z,$={}){let z=this.refreshPromises.get(B.id);if(z){let G=await z;return L(Z,G),G}let X=this.refreshAccountNow(B,Z,$).finally(()=>{this.refreshPromises.delete(B.id)});this.refreshPromises.set(B.id,X);let W=await X;return L(Z,W),W}async waitForConcurrentFallbackRefresh(B,Z,$,z){let X=Date.now()+k3;while(Date.now()<X){await new Promise((J)=>setTimeout(J,h3));let W=await this.load(),G=W?.accounts.find((J)=>J.id===B.id&&P(J));if(!G)continue;if((G.access!==$.access||G.refresh!==$.refresh||(G.expires??0)>($.expires??0)+60000)&&(z.force||!I(G,W,this.now())))return L(Z,G),E.debug("fallback oauth joined concurrent refresh",{pid:process.pid,accountId:G.id,expiresInMs:G.expires?G.expires-this.now():void 0}),G;let Y=G.lastRefreshError;if(Y&&q(Y,G.refresh,this.now()))throw L(Z,G),Error(n(Y,this.now()))}return null}async refreshAccountNow(B,Z,$){let z=await this.load(),X=z?.accounts.find((K)=>K.id===B.id&&P(K));if(X&&!$.force&&!I(X,z,this.now()))return L(Z,X),X;let W=X??B,G=await T({name:E3(W.id),ttlMs:w3,path:this.configPath,now:this.now,renew:!0});if(!G){E.debug("fallback oauth refresh skipped file lock",{pid:process.pid,accountId:W.id});let K=await this.waitForConcurrentFallbackRefresh(B,Z,W,$);if(K)return K;throw Error("Fallback OAuth refresh is already in progress")}try{if(z=await this.load(),X=z?.accounts.find((H)=>H.id===B.id&&P(H)),X&&!$.force&&!I(X,z,this.now()))return L(Z,X),X;if(!X)throw new Z0(B.id);W=X;let K=this.options.refreshFn??(async()=>{throw Error("No refreshFn injected into FallbackAccountManager")});E.debug("fallback oauth refresh request start",{pid:process.pid,accountId:W.id,force:$.force===!0,expiresInMs:W.expires?W.expires-this.now():void 0});let Y=await K({refreshToken:W.refresh,fetchImpl:this.fetchImpl,now:this.now});if(W.access=Y.access,W.refresh=Y.refresh,W.expires=Y.expires,W.lastRefreshedAt=Y.expires-Y.expiresIn*1000,W.lastRefreshError=void 0,L(Z,W),await this.save(Z),!(await this.load())?.accounts.some((H)=>H.id===B.id))throw new Z0(B.id);return E.debug("fallback oauth refresh succeeded",{pid:process.pid,accountId:W.id,expiresInMs:W.expires?W.expires-this.now():void 0}),W}finally{await G.release()}}async refreshAccountQuota(B,Z){let $=B;if(!$.access)throw Error(`Fallback account ${B.id} has no access token`);if(!this.options.fetchQuotaFn)throw Error("No fetchQuotaFn injected — wham/usage supplement is disabled");let z=this.options.fetchQuotaFn??(async()=>{throw Error("No fetchQuotaFn injected — wham/usage supplement is disabled")}),X=(W)=>this.quotaManager?this.quotaManager.refreshFallback($.id,W):z({accessToken:W,fetchImpl:this.fetchImpl,now:this.now});try{if(!$.access)throw Error(`Fallback account ${B.id} has no access token`);let W=await X($.access);$.quota=W,$.lastQuotaRefreshError=void 0,L(Z,$),await this.save(Z)}catch(W){throw V0(B,W,this.now()),L(Z,B),W}}}
|
|
92
|
+
export{q0 as g,C0 as h,q as i,n as j,E0 as k,x0 as l,H2 as m,S0 as n,y0 as o,a as p,K0 as q,Q2 as r,y as s,b2 as t,D2 as u,F2 as v,O2 as w,c3 as x,a3 as y,e3 as z,BB as A,T as B,j0 as C,M as D,w as E,P as F,SB as G,N0 as H,J3 as I,EB as J,IB as K,P3 as L,xB as M,AB as N,TB as O,v3 as P};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import type { Hooks, Plugin, PluginInput } from '@opencode-ai/plugin';
|
|
2
2
|
import { type FallbackAccount, type OAuthAccount } from './core/accounts';
|
|
3
|
+
export declare const MAIN_REFRESH_LOCK_TTL_MS: number;
|
|
4
|
+
export declare const MAIN_REFRESH_LEASE_TTL_MS = 90000;
|
|
5
|
+
export declare class AuthPersistError extends Error {
|
|
6
|
+
readonly code = "OPENAI_AUTH_PERSIST_FAILED";
|
|
7
|
+
constructor(cause: unknown);
|
|
8
|
+
}
|
|
3
9
|
export { extractAccountIdFromClaims, type IdTokenClaims, parseJwtClaims, } from './core/oauth';
|
|
4
10
|
interface CodexAuthPluginOptions {
|
|
5
11
|
issuer?: string;
|