@cortexkit/opencode-openai-auth 0.7.2 → 0.8.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.
Files changed (114) hide show
  1. package/README.md +9 -5
  2. package/dist/{index-9jpc8yct.js → index-02h7g5f9.js} +1 -1
  3. package/dist/index-2xppkvkx.js +2 -0
  4. package/dist/index-3w4vmckx.js +2 -0
  5. package/dist/{index-zxqb5ydj.js → index-507jh8bv.js} +1 -1
  6. package/dist/{index-zg1x8sty.js → index-944gsj1s.js} +1 -1
  7. package/dist/index-nshbgkz1.js +198 -0
  8. package/dist/{index-87145jkw.js → index-xyg86jgt.js} +1 -1
  9. package/dist/index.d.ts +381 -35
  10. package/dist/index.js +66 -161
  11. package/dist/protocol-Cv9ZmU0p.d.ts +24 -0
  12. package/dist/quota-normalize-wap0rne8.js +1 -0
  13. package/dist/rpc/port-file.d.ts +11 -9
  14. package/dist/rpc/port-file.js +1 -1
  15. package/dist/rpc/protocol.d.ts +2 -21
  16. package/dist/rpc/rpc-client.d.ts +6 -4
  17. package/dist/rpc/rpc-client.js +1 -1
  18. package/dist/rpc/rpc-dir.d.ts +7 -5
  19. package/dist/rpc/rpc-dir.js +1 -1
  20. package/dist/sidebar-state.d.ts +84 -83
  21. package/dist/sidebar-state.js +1 -1
  22. package/dist/{token-bvp0y166.js → token-jdvpwk60.js} +1 -1
  23. package/dist/token-util-zzm7paz9.js +1 -0
  24. package/dist/tui-preferences.d.ts +27 -26
  25. package/dist/tui-preferences.js +1 -1
  26. package/dist/tui.d.ts +18 -17
  27. package/package.json +7 -14
  28. package/src/tui/entry.mjs +2 -2
  29. package/src/tui-compiled/{core/account-paths.ts → raw/core-account-paths.ts} +29 -18
  30. package/src/tui-compiled/raw/logger.ts +53 -0
  31. package/src/tui-compiled/{rpc/port-file.ts → raw/rpc-port-file.ts} +1 -1
  32. package/src/tui-compiled/raw/rpc-protocol.ts +12 -0
  33. package/src/{rpc/rpc-client.ts → tui-compiled/raw/rpc-rpc-client.ts} +2 -2
  34. package/src/{sidebar-state.ts → tui-compiled/raw/sidebar-state.ts} +2 -2
  35. package/src/{tui/command-dialogs.tsx → tui-compiled/raw/tui-command-dialogs.tsx} +5 -5
  36. package/src/{tui.tsx → tui-compiled/raw/tui.tsx} +11 -10
  37. package/src/{core/account-paths.ts → tui-compiled/runtime/core-account-paths.ts} +29 -18
  38. package/src/tui-compiled/runtime/logger.ts +53 -0
  39. package/src/{rpc/port-file.ts → tui-compiled/runtime/rpc-port-file.ts} +1 -1
  40. package/src/tui-compiled/runtime/rpc-protocol.ts +12 -0
  41. package/src/tui-compiled/{rpc/rpc-client.ts → runtime/rpc-rpc-client.ts} +2 -2
  42. package/src/tui-compiled/{sidebar-state.ts → runtime/sidebar-state.ts} +2 -2
  43. package/src/tui-compiled/{tui/command-dialogs.tsx → runtime/tui-command-dialogs.tsx} +3 -4
  44. package/src/tui-compiled/{tui.tsx → runtime/tui.tsx} +10 -10
  45. package/src/tui-compiled/shared/internal.ts +6 -0
  46. package/src/{logger.ts → tui-compiled/shared/logger.ts} +82 -21
  47. package/src/tui-compiled/shared/paths.ts +33 -0
  48. package/src/{core → tui-compiled/shared}/refresh-file-lock.ts +7 -4
  49. package/dist/cli.d.ts +0 -2
  50. package/dist/cli.js +0 -15
  51. package/dist/codex-http.d.ts +0 -3
  52. package/dist/commands.d.ts +0 -88
  53. package/dist/config.d.ts +0 -47
  54. package/dist/core/account-paths.d.ts +0 -25
  55. package/dist/core/accounts.d.ts +0 -330
  56. package/dist/core/atomic-write.d.ts +0 -1
  57. package/dist/core/background-quota-refresh.d.ts +0 -46
  58. package/dist/core/backoff.d.ts +0 -53
  59. package/dist/core/cachekeep.d.ts +0 -118
  60. package/dist/core/oauth.d.ts +0 -138
  61. package/dist/core/provider.d.ts +0 -70
  62. package/dist/core/quota-manager.d.ts +0 -192
  63. package/dist/core/refresh-all-quota.d.ts +0 -86
  64. package/dist/core/refresh-file-lock.d.ts +0 -12
  65. package/dist/core/reset-credits.d.ts +0 -116
  66. package/dist/core/sticky-routing.d.ts +0 -43
  67. package/dist/dump.d.ts +0 -20
  68. package/dist/hosted-web-search.d.ts +0 -5
  69. package/dist/index-8f1200qx.js +0 -6
  70. package/dist/index-cfjed1st.js +0 -89
  71. package/dist/index-nrvjr97q.js +0 -3
  72. package/dist/index-qaggaze1.js +0 -2
  73. package/dist/index-sdcpzbnk.js +0 -2
  74. package/dist/logger.d.ts +0 -22
  75. package/dist/model-costs.d.ts +0 -29
  76. package/dist/prompt-context.d.ts +0 -19
  77. package/dist/quota-normalize-dvwtmy7f.js +0 -1
  78. package/dist/quota-normalize.d.ts +0 -43
  79. package/dist/raw-ws-bun.d.ts +0 -40
  80. package/dist/raw-ws-node.d.ts +0 -37
  81. package/dist/raw-ws-upgrade.d.ts +0 -2
  82. package/dist/raw-ws.d.ts +0 -3
  83. package/dist/response-stream-error.d.ts +0 -12
  84. package/dist/rpc/notifications.d.ts +0 -5
  85. package/dist/rpc/rpc-server.d.ts +0 -17
  86. package/dist/token-util-jcj7k7pa.js +0 -1
  87. package/dist/tui/command-dialogs.d.ts +0 -21
  88. package/dist/util/error.d.ts +0 -1
  89. package/dist/util/open-url.d.ts +0 -6
  90. package/dist/util/proxy-env.d.ts +0 -4
  91. package/dist/util/record.d.ts +0 -1
  92. package/dist/util/stable-json.d.ts +0 -1
  93. package/dist/util/uuid-v7.d.ts +0 -1
  94. package/dist/version.d.ts +0 -1
  95. package/dist/ws-pool.d.ts +0 -57
  96. package/dist/ws.d.ts +0 -71
  97. package/src/rpc/notifications.ts +0 -54
  98. package/src/rpc/protocol.ts +0 -33
  99. package/src/rpc/rpc-server.ts +0 -172
  100. package/src/tui-compiled/core/refresh-file-lock.ts +0 -381
  101. package/src/tui-compiled/logger.ts +0 -196
  102. package/src/tui-compiled/rpc/protocol.ts +0 -33
  103. package/src/util/error.ts +0 -9
  104. package/src/util/open-url.ts +0 -30
  105. package/src/util/proxy-env.ts +0 -42
  106. package/src/util/record.ts +0 -3
  107. package/src/util/stable-json.ts +0 -15
  108. package/src/util/uuid-v7.ts +0 -18
  109. /package/src/{rpc/rpc-dir.ts → tui-compiled/raw/rpc-rpc-dir.ts} +0 -0
  110. /package/src/tui-compiled/{tui-preferences.ts → raw/tui-preferences.ts} +0 -0
  111. /package/src/tui-compiled/{rpc/rpc-dir.ts → runtime/rpc-rpc-dir.ts} +0 -0
  112. /package/src/{tui-preferences.ts → tui-compiled/runtime/tui-preferences.ts} +0 -0
  113. /package/src/tui-compiled/{util → shared/util}/error.ts +0 -0
  114. /package/src/tui-compiled/{util → shared/util}/open-url.ts +0 -0
@@ -1,116 +0,0 @@
1
- import { type loadAccounts, type mutateAccounts, type OAuthQuotaSnapshot, type ResetAccountState, type ResetInFlight } from './accounts.ts';
2
- export interface ResetCredit {
3
- id: string;
4
- status: string;
5
- grantedAt?: string;
6
- expiresAt: string;
7
- resetType?: string;
8
- isSupportedByPlan: boolean;
9
- }
10
- export interface ResetCreditList {
11
- credits: ResetCredit[];
12
- availableCount?: number;
13
- }
14
- export type ResetConsumeKind = 'reset' | 'already_redeemed' | 'nothing_to_reset' | 'no_credit' | 'http_error' | 'ambiguous';
15
- export interface ResetConsumeOutcome {
16
- kind: ResetConsumeKind;
17
- raw: unknown;
18
- status?: number;
19
- }
20
- export type ResetPrecondition = {
21
- ok: true;
22
- } | {
23
- ok: false;
24
- reason: 'not exhausted';
25
- };
26
- export interface ResetStateDeps {
27
- configPath: string;
28
- mutateAccountsFn: typeof mutateAccounts;
29
- loadAccountsFn: typeof loadAccounts;
30
- now: () => number;
31
- randomUUID: () => string;
32
- }
33
- export interface ResetResolvedTarget {
34
- accountKey: string;
35
- label: string;
36
- accessToken: string;
37
- chatgptAccountId?: string;
38
- }
39
- export interface RunResetCreditDeps extends ResetStateDeps {
40
- fetchImpl: typeof fetch;
41
- resolveTarget(accountKey: string): Promise<ResetResolvedTarget>;
42
- fetchUsage(target: ResetResolvedTarget): Promise<OAuthQuotaSnapshot>;
43
- hasActiveRateLimitMark(accountKey: string): boolean;
44
- }
45
- export interface RunResetCreditInput {
46
- accountKey: string;
47
- expectedChatgptAccountId: string;
48
- retry: boolean;
49
- }
50
- export type ResetRedemptionErrorKind = 'invalid_account_key' | 'identity_mismatch' | 'cooldown_active' | 'expired_unreconciled' | 'retry_without_inflight' | 'not_exhausted' | 'no_eligible_credit';
51
- export declare class ResetRedemptionError extends Error {
52
- readonly kind: ResetRedemptionErrorKind;
53
- readonly cooldownUntil?: number;
54
- constructor(kind: ResetRedemptionErrorKind, message: string, cooldownUntil?: number);
55
- }
56
- export interface ResetLocalAmbiguousOutcome {
57
- kind: 'ambiguous_local';
58
- raw: {
59
- reason: 'corrupt_in_flight';
60
- };
61
- }
62
- export type ResetRedemptionOutcome = ResetConsumeOutcome | ResetLocalAmbiguousOutcome;
63
- export type ResetSelectedCredit = ResetCredit | {
64
- id: string;
65
- };
66
- export interface RunResetCreditResult {
67
- target: ResetResolvedTarget;
68
- selectedCredit: ResetSelectedCredit | undefined;
69
- beforeState: ResetAccountState | undefined;
70
- outcome: ResetRedemptionOutcome;
71
- retrySafety: string;
72
- finalizeStateWriteFailed?: boolean;
73
- }
74
- interface ResetClaim {
75
- inFlight: ResetInFlight;
76
- selectedCredit: ResetSelectedCredit;
77
- }
78
- type ResetStateDecision = {
79
- kind: 'fresh';
80
- beforeState: ResetAccountState | undefined;
81
- } | {
82
- kind: 'claim';
83
- beforeState: ResetAccountState | undefined;
84
- claim: ResetClaim;
85
- } | {
86
- kind: 'expired_unreconciled';
87
- beforeState: ResetAccountState | undefined;
88
- claim: ResetClaim;
89
- } | {
90
- kind: 'cooldown';
91
- beforeState: ResetAccountState | undefined;
92
- cooldownUntil: number;
93
- } | {
94
- kind: 'corrupt';
95
- beforeState: ResetAccountState | undefined;
96
- };
97
- export type ResetCreditErrorKind = 'http_error' | 'invalid_response';
98
- export declare class ResetCreditError extends Error {
99
- readonly kind: ResetCreditErrorKind;
100
- readonly status?: number;
101
- constructor(kind: ResetCreditErrorKind, message: string, status?: number);
102
- }
103
- export declare function claimResetAttempt(deps: ResetStateDeps, accountKey: string, credits: readonly ResetCredit[]): Promise<ResetStateDecision>;
104
- export declare function finalizeResetAttempt(deps: ResetStateDeps, accountKey: string, completing: ResetInFlight, outcome: ResetConsumeOutcome): Promise<void>;
105
- export declare function resetWindowIsExhausted(window: {
106
- usedPercent: number;
107
- resetsAt?: string;
108
- } | undefined, now: number): boolean;
109
- export declare function evaluateResetPrecondition(quota: OAuthQuotaSnapshot, hasActiveRateLimitMark: boolean, now: number): ResetPrecondition;
110
- export declare function listResetCredits(fetchImpl: typeof fetch, token: string, accountId?: string): Promise<ResetCreditList>;
111
- export declare function selectCreditToSpend(credits: readonly ResetCredit[]): ResetCredit | undefined;
112
- export declare function isResetCreditEligible(credit: ResetCredit): boolean;
113
- export declare function countEligibleResetCredits(credits: readonly ResetCredit[]): number;
114
- export declare function consumeResetCredit(fetchImpl: typeof fetch, token: string, accountId: string | undefined, creditId: string, redeemRequestId: string): Promise<ResetConsumeOutcome>;
115
- export declare function runResetCreditRedemption(deps: RunResetCreditDeps, input: RunResetCreditInput): Promise<RunResetCreditResult>;
116
- export {};
@@ -1,43 +0,0 @@
1
- import { type AccountQuota, type QuotaWindow, type QuotaWindowKey } from '../sidebar-state';
2
- export declare const QUOTA_STALENESS_MS: number;
3
- export declare const MIN_RESET_HOURS: number;
4
- export declare const MIN_WEIGHT = 0.000001;
5
- export declare function snapshotCheckedAt(quota: AccountQuota | null | undefined, entryCheckedAt?: number): number | undefined;
6
- export type StickyBreakDecision = {
7
- action: 'retain';
8
- reason: 'unknown' | 'stale' | 'healthy' | 'transient';
9
- } | {
10
- action: 'migrate';
11
- reason: 'exhausted' | 'permanent' | 'killswitch';
12
- windowKey?: QuotaWindowKey;
13
- resetsAt?: string;
14
- };
15
- export declare function decideStickyBreak(input: {
16
- quota: AccountQuota | null | undefined;
17
- quotaCheckedAt?: number;
18
- status?: number;
19
- now: number;
20
- killswitchPasses?: boolean;
21
- }): StickyBreakDecision;
22
- export declare function sustainableWindowWeight(window: Pick<QuotaWindow, 'remainingPercent' | 'resetsAt'>, reservePercent: number, now: number): number;
23
- export interface StickySelectionCandidate {
24
- accountId: string;
25
- quota: AccountQuota | null | undefined;
26
- quotaCheckedAt?: number;
27
- reservePercent: Record<QuotaWindowKey, number>;
28
- configuredOrder: number;
29
- resetCreditsApplicable?: number;
30
- killswitchPasses?: boolean;
31
- }
32
- export interface StickySelectionInput {
33
- candidates: readonly StickySelectionCandidate[];
34
- pendingBytes: ReadonlyMap<string, number>;
35
- requestBytes: number;
36
- now: number;
37
- onEmptyWeightedSet?: () => void;
38
- }
39
- export declare function selectStickyCandidate(input: StickySelectionInput): {
40
- accountId: string;
41
- quotaCheckedAt?: number;
42
- source: 'weighted' | 'mode-fallback';
43
- } | undefined;
package/dist/dump.d.ts DELETED
@@ -1,20 +0,0 @@
1
- export declare const DUMP_SESSION_HEADER = "x-cortexkit-openai-auth-dump-session";
2
- type DumpHeaders = ConstructorParameters<typeof Headers>[0];
3
- type DumpTransport = 'http' | 'websocket';
4
- declare const DUMP_PHASES: readonly ['http', 'prewarm', 'main'];
5
- type DumpPhase = (typeof DUMP_PHASES)[number];
6
- export declare function dumpCodexRequest(input: {
7
- sessionID?: string | null;
8
- transport: DumpTransport;
9
- phase: DumpPhase;
10
- bodyText: string;
11
- accountId?: string;
12
- url?: string;
13
- method?: string;
14
- headers?: DumpHeaders;
15
- status?: number;
16
- error?: string;
17
- }): Promise<void>;
18
- export declare function dumpDiagnostic(event: Record<string, unknown>): Promise<void>;
19
- export declare function resetDumpStateForTest(): void;
20
- export {};
@@ -1,5 +0,0 @@
1
- import { type ToolDefinition } from '@opencode-ai/plugin';
2
- export declare const HostedWebSearchTool: ToolDefinition;
3
- export declare function translateHostedWebSearchEvent(event: Record<string, unknown>): Record<string, unknown> | undefined;
4
- export declare function translateHostedWebSearchResponse(response: Response): Response;
5
- export declare function rewriteHostedWebSearchReplay(body: Record<string, unknown>): boolean;
@@ -1,6 +0,0 @@
1
- import{realpathSync as k}from"node:fs";import{homedir as i}from"node:os";import{basename as P,dirname as m,join as D,resolve as w}from"node:path";var d="openai-auth.json",r="openai-auth-state.json";function t(){if(process.env.OPENCODE_CONFIG_DIR?.trim())return process.env.OPENCODE_CONFIG_DIR.trim();return D(process.env.XDG_CONFIG_HOME||D(i(),".config"),"opencode")}function C(){return process.env.OPENCODE_OPENAI_AUTH_FILE?.trim()||D(t(),d)}function e(B){return P(B)===d?D(m(B),r):`${B}.state.json`}function q(B,Q){let J=w(B);return Q==="win32"||Q==="darwin"?J.toLowerCase():J}function f(B){try{return k.native(B)}catch{try{return D(k.native(m(B)),P(B))}catch{return}}}function o(B,Q,J=process.platform){if(q(B,J)===q(Q,J))return!0;let j=f(B),W=f(Q);return j!==void 0&&W!==void 0&&q(j,J)===q(W,J)}function ZB(B=C()){let Q=process.env.OPENCODE_OPENAI_AUTH_STATE_FILE?.trim();if(Q){if(o(B,Q))throw Error(`OPENCODE_OPENAI_AUTH_STATE_FILE resolves to the config path (${w(B)}). Set OPENCODE_OPENAI_AUTH_STATE_FILE to a different file.`);return Q}return e(B)}import{randomUUID as y}from"node:crypto";import{mkdir as h,readFile as F,rename as BB,rm as x,stat as l,writeFile as L}from"node:fs/promises";import{dirname as GB,join as p}from"node:path";var HB=globalThis.setTimeout.bind(globalThis),JB=globalThis.clearTimeout.bind(globalThis);function KB(B){let Q=B?.code;return Q==="ENOENT"||Q==="EINVAL"||Q==="ENOTDIR"}async function DB(B){let J=`${B.path??C()}.${B.name}.lock`,j=p(J,"owner.json"),W=y(),Z=B.now??Date.now,X=null,$=!1,N=null,z=`${J}.evicting`,A=p(z,"owner.json"),I=y(),c=5000,O=8;async function b(){try{return JSON.parse(await F(J,"utf8"))}catch(G){if(G.code!=="EISDIR")throw G;return JSON.parse(await F(j,"utf8"))}}async function s(){await L(J,`${JSON.stringify({ownerId:W,expiresAt:Z()+B.ttlMs})}
2
- `,{encoding:"utf8",mode:384})}async function _(){try{return await L(J,`${JSON.stringify({ownerId:W,expiresAt:Z()+B.ttlMs})}
3
- `,{encoding:"utf8",mode:384,flag:"wx"}),!0}catch(G){let H=G.code;if(H==="EEXIST"||H==="EISDIR")return!1;if(H==="ENOENT"){await h(GB(J),{recursive:!0});try{return await L(J,`${JSON.stringify({ownerId:W,expiresAt:Z()+B.ttlMs})}
4
- `,{encoding:"utf8",mode:384,flag:"wx"}),!0}catch(K){let R=K.code;if(R==="EEXIST"||R==="EISDIR")return!1;throw K}}throw G}}async function U(){await new Promise((G)=>setTimeout(G,Math.floor(Math.random()*4)))}async function T(){try{let G=await b();return Number(G?.expiresAt)>Z()}catch{try{return(await l(J)).mtimeMs+B.ttlMs>Z()}catch{return!1}}}async function Y(){try{return JSON.parse(await F(A,"utf8"))?.ownerId===I}catch{return!1}}async function S(){if(await Y())await x(z,{recursive:!0,force:!0}).catch(()=>{})}async function M(){await h(z);try{await L(A,`${JSON.stringify({ownerId:I,createdAt:Z()})}
5
- `,{encoding:"utf8",mode:384,flag:"wx"})}catch(G){if(KB(G))return!1;throw await S(),G}if(B.onStep)await B.onStep("eviction-marker-acquired");return!0}async function g(){let G;try{G=await l(z)}catch(K){if(K.code==="ENOENT")return"missing";throw K}if(G.mtimeMs+c>Z())return"fresh";if(B.onStep)await B.onStep("stale-marker-stat");let H=`${z}.${y()}`;try{await BB(z,H)}catch(K){if(K.code==="ENOENT")return"missing";throw K}if(B.onStep)await B.onStep("stale-marker-claimed");return await x(H,{recursive:!0,force:!0}).catch(()=>{}),"recovered"}async function E(G){try{if(!await M())return!1}catch(H){if(H.code==="EEXIST")return!1;throw H}try{await G()}finally{await S()}return!0}async function a(){for(let G=0;G<O;G++){if(B.onStep)await B.onStep("relinquish-read");let H;try{H=await b()}catch{return}if(H?.ownerId!==W)return;try{await x(J,{recursive:!0,force:!0});return}catch{await U()}}}function u(){if(!B.renew||$)return;let G=B.renewIntervalMs??Math.max(1000,Math.floor(B.ttlMs/3));if(X=HB(()=>{let H=(async()=>{let K=!$;try{if(!await E(async()=>{let v=await b(),n=Z();if($||v?.ownerId!==W){K=!1;return}if(Number(v?.expiresAt)<=n){K=!1;return}if(B.onStep)await B.onStep("renewal-owner-confirmed");if($){K=!1;return}if(!await Y())return;if(B.onStep)await B.onStep("renewal-write-fenced");if($){K=!1;return}if(!await Y())return;if(B.onStep)await B.onStep("renewal-write-ready");if(await s(),!await Y()){K=!1,await a();return}})&&B.onStep)await B.onStep("renewal-marker-unavailable")}catch{}finally{if(B.onStep)try{await B.onStep("renewal-finished")}catch{}if(K&&!$)u()}})();N=H,H.finally(()=>{if(N===H)N=null})},G),"unref"in X)X.unref()}let V=await _();if(!V)for(let G=0;G<O;G++){if(V=await _(),V)break;if(await T())return null;try{if(!await M()){await U();continue}}catch(H){if(H.code!=="EEXIST")throw H;if(await g()==="fresh")return null;await U();continue}try{if(await T())return null;if(!await Y())return null;if(B.onStep)await B.onStep("stale-lock-confirmed");if(!await Y())return null;if(await x(J,{recursive:!0,force:!0}).catch(()=>{}),!await Y())return null;if(V=await _(),!V)return null;if(!await Y())return await x(J,{recursive:!0,force:!0}).catch(()=>{}),V=!1,null;break}finally{await S()}}if(!V)return null;return u(),{release:async()=>{if($=!0,X)JB(X),X=null;await N;for(let G=0;G<O;G++){try{if(await E(async()=>{if((await b())?.ownerId!==W)return;if(B.onStep)await B.onStep("release-owner-confirmed");if(!await Y())return;await x(J,{recursive:!0,force:!0}).catch(()=>{})}))return;await g()}catch{return}await U()}}}}
6
- export{C as ua,ZB as va,DB as wa};
@@ -1,89 +0,0 @@
1
- import{ua as I,va as u,wa as A}from"./index-8f1200qx.js";import{Da as v}from"./index-nrvjr97q.js";import{Ka as Q2}from"./index-zxqb5ydj.js";import{createHash as i0}from"node:crypto";var u0=86400000,s0=300000,r0=3600000,n0=60000,c0=900000,o0=300000;function $0(B){return B instanceof Error?B.message:String(B)}function a0(B){let Z=B?.status;if(typeof Z==="number")return Z===429||Z>=500;if(!(B instanceof Error))return!1;return B.name==="AbortError"||B.name==="TimeoutError"||B.message.includes("fetch failed")||"code"in B&&(B.code==="ECONNRESET"||B.code==="ECONNREFUSED"||B.code==="ETIMEDOUT"||B.code==="UND_ERR_CONNECT_TIMEOUT")}function W0(B){let Z=$0(B),$=B?.status;if(typeof $==="number")return $===429||$>=500;if(!(B instanceof Error))return!1;let W=B.code;return B.name==="AbortError"||B.name==="TimeoutError"||Z.includes("fetch failed")||W==="ECONNRESET"||W==="ECONNREFUSED"||W==="ETIMEDOUT"||W==="UND_ERR_CONNECT_TIMEOUT"}function L0(B){return i0("sha256").update(B).digest("hex")}function F0(B){let Z=L0(B.refreshToken),W=(B.previous?.tokenHash===Z?B.previous.retryCount??0:0)+1,X,z=B.error?.retryAfter;if(typeof z==="number"&&z>0)X=z*1000;else if(a0(B.error))X=Math.min(r0,s0*2**Math.min(W-1,6));else X=u0;return{message:$0(B.error),checkedAt:B.now,nextRetryAt:B.now+X,retryCount:W,tokenHash:Z}}function _(B,Z,$){if(!B?.nextRetryAt||B.nextRetryAt<=$)return!1;if(!Z)return!0;return B.tokenHash===L0(Z)}function r(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 m(B){let $=(B.previous?.retryCount??0)+1,W,X=B.error?.retryAfter;if(typeof X==="number"&&X>0)W=X*1000;else if(W0(B.error))W=Math.min(c0,n0*2**Math.min($-1,6));else W=o0;return{message:$0(B.error),checkedAt:B.now,nextRetryAt:B.now+W,retryCount:$}}function x(B,Z){if(!B?.nextRetryAt||B.nextRetryAt<=Z)return!1;return!0}function X0(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 W=Math.ceil(($-Date.now())/1000);return W>0?W:void 0}return}import{createServer as t0}from"node:http";import{setTimeout as e0}from"node:timers/promises";var O0="0.7.2";var o="app_EMoamEEZ73f0CkXaXp7hrann",S="https://auth.openai.com",k=1455,B2=3000,D0=`cortexkit-opencode-openai-auth/${O0}`,U0="main",Z2=`"${U0}" is a reserved account id; choose a different label.`;function M0(B){let Z=new Uint8Array(B),$=String.fromCharCode(...Z);return btoa($).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}async function $2(){let Z=Array.from(crypto.getRandomValues(new Uint8Array(43))).map((W)=>"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~"[W%66]).join(""),$=M0(await crypto.subtle.digest("SHA-256",new TextEncoder().encode(Z)));return{verifier:Z,challenge:$}}function V0(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 b0(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 W=B.organizations;if(Array.isArray(W)){let X=W[0];if(X&&typeof X==="object"&&!Array.isArray(X)&&typeof X.id==="string"&&X.id.length>0)return X.id}return}function c(B){if(B.id_token){let Z=V0(B.id_token),$=Z&&b0(Z);if($)return $}if(B.access_token){let Z=V0(B.access_token);return Z?b0(Z):void 0}return}function W2(B){return typeof B==="string"&&B.toLowerCase()===U0}function G0(B){if(W2(B))throw Error(Z2);return B}function X2(B,Z,$){let W=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?${W.toString()}`}async function G2(B,Z,$){let W=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(!W.ok)throw Error(`Token exchange failed: ${W.status}`);return await W.json()}function z2(B){return B.replaceAll("&","&amp;").replaceAll("<","&lt;").replaceAll(">","&gt;").replaceAll('"',"&quot;").replaceAll("'","&#39;")}var K2=`<!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>`,n=(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">${z2(B)}</div>
85
- </div>
86
- </body>
87
- </html>`,w,h,V=new Map;function q(){return V.size}function E(B){if(V.delete(B),q()===0)C()}async function Y2(){let B=`http://localhost:${k}/auth/callback`;if(w)return{port:k,redirectUri:B};if(h)return h;h=(async()=>{let Z=t0(($,W)=>{let X=new URL($.url||"/",`http://127.0.0.1:${k}`);if(X.pathname==="/auth/callback"){let z=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 Q=V.get(G);if(Q)Q.reject(Error(H)),E(G);else if(q()===0)C()}else if(q()===0)C();W.writeHead(200,{"Content-Type":"text/html"}),W.end(n(H));return}if(!G){if(q()===0)C();W.writeHead(400,{"Content-Type":"text/html"}),W.end(n("Missing state parameter"));return}if(!z){if(q()===0)C();W.writeHead(400,{"Content-Type":"text/html"}),W.end(n("Missing authorization code"));return}let j=V.get(G);if(!j){if(q()===0)C();W.writeHead(400,{"Content-Type":"text/html"}),W.end(n("Unknown state — authorization may have expired"));return}E(G),G2(z,B,j.pkce).then((H)=>j.resolve(H)).catch((H)=>j.reject(H)),W.writeHead(200,{"Content-Type":"text/html"}),W.end(K2);return}if(X.pathname==="/cancel"){let z=X.searchParams.get("state"),G=z?[z]:[...V.keys()];W.writeHead(200),W.end("Login cancelled");for(let K of G){let Y=V.get(K);if(!Y)continue;Y.reject(Error("Login cancelled")),E(K)}if(q()===0)C();return}W.writeHead(404),W.end("Not found")});return await new Promise(($,W)=>{Z.once("error",W),Z.listen(k,"127.0.0.1",()=>{Z.off("error",W),$()})}),w=Z,{port:k,redirectUri:B}})();try{return await h}finally{h=void 0}}function C(){if(w){let B=w;w=void 0,B.close(()=>{}),B.closeIdleConnections?.(),setTimeout(()=>{B.closeAllConnections?.()},25).unref?.()}}function j2(B,Z,$=300000,W){return new Promise((X,z)=>{if(W?.aborted){E(Z),z(Error("Login cancelled"));return}let G=setTimeout(()=>{if(V.get(Z))E(Z),z(Error("OAuth callback timeout — authorization took too long"))},$),K=()=>{if(clearTimeout(G),V.get(Z))E(Z),z(Error("Login cancelled"))};if(W)W.addEventListener("abort",K);V.set(Z,{pkce:B,state:Z,resolve:(Y)=>{if(clearTimeout(G),W)W.removeEventListener("abort",K);X(Y)},reject:(Y)=>{if(clearTimeout(G),W)W.removeEventListener("abort",K);z(Y)}})})}async function J2(){let B=await fetch(`${S}/api/accounts/deviceauth/usercode`,{method:"POST",headers:{"Content-Type":"application/json","User-Agent":D0},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 H2(B,Z){let $=Math.max(parseInt(B.interval,10)||5,1)*1000,W=typeof B.expires_in==="number"?B.expires_in:parseInt(B.expires_in||"",10),X=!Number.isNaN(W)&&W>0?W*1000:900000,z=Date.now();while(!0){if(Z?.aborted)throw Error("Device authorization cancelled");if(Date.now()-z>X)throw Error("Device authorization expired");let G=await fetch(`${S}/api/accounts/deviceauth/token`,{method:"POST",headers:{"Content-Type":"application/json","User-Agent":D0},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()-z);if(K<=0)throw Error("Device authorization expired");let Y=Math.min($+B2,K);try{await e0(Y,void 0,{signal:Z})}catch(j){if(j instanceof Error&&j.name==="AbortError")throw Error("Device authorization cancelled");throw j}}}function xB(B,Z){let $=-1;if(Z.accountId)$=B.findIndex((W)=>W.accountId&&W.accountId===Z.accountId);if($<0)$=B.findIndex((W)=>W.id===Z.id);if($<0&&Z.label&&!Z.accountId)$=B.findIndex((W)=>W.label===Z.label);if($>=0)return B[$]={...B[$],...Z,addedAt:B[$]?.addedAt??Z.addedAt},$;return B.push(Z),B.length-1}async function AB(B={}){let{label:Z,headless:$=!1,signal:W}=B;if(G0(Z),$){let{deviceData:j,url:H,instructions:Q}=await J2(),b=(async()=>{let N=await H2(j,W),F=Date.now(),s=c(N);return{id:G0(Z||s||crypto.randomUUID()),label:Z||void 0,type:"oauth",access:N.access_token,refresh:N.refresh_token,expires:F+(N.expires_in??3600)*1000,enabled:!0,addedAt:F,lastUsed:F,lastRefreshedAt:F,accountId:s}})();return{url:H,instructions:Q,completion:b}}let{redirectUri:X}=await Y2(),z=await $2(),G=M0(crypto.getRandomValues(new Uint8Array(32)).buffer),K=X2(X,z,G),Y=(async()=>{try{if(W?.aborted)throw Error("Login cancelled");let j=await j2(z,G,void 0,W),H=Date.now(),Q=c(j);return{id:G0(Z||Q||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:Q}}finally{E(G)}})();return{url:K,instructions:"Complete authorization in your browser. This window will close automatically.",completion:Y}}function _0(B){if(B instanceof Error)return B.message;if(typeof B==="string")return B;try{return JSON.stringify(B)}catch{return String(B)}}var N2=v("quota"),z0="primary",K0="secondary",P2="app_EMoamEEZ73f0CkXaXp7hrann",L2="https://auth.openai.com";async function wB(B){let Z=await B.fetchImpl(`${L2}/oauth/token`,{method:"POST",signal:AbortSignal.timeout(15000),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 X=X0(Z.headers.get("retry-after"));throw Object.assign(Error(`Token refresh failed: ${Z.status}`),{status:Z.status,retryAfter:X,isRefreshError:!0})}let $=await Z.json();if(!$||typeof $.access_token!=="string"||!$.access_token||typeof $.expires_in!=="number")throw Object.assign(Error("Token refresh failed: malformed response"),{status:Z.status,isRefreshError:!0});if($.refresh_token!==void 0&&typeof $.refresh_token!=="string")throw Object.assign(Error("Token refresh failed: malformed response"),{status:Z.status,isRefreshError:!0});let W=typeof $.refresh_token==="string"&&$.refresh_token?$.refresh_token:B.refreshToken;return{access:$.access_token,refresh:W,expires:B.now()+$.expires_in*1000,expiresIn:$.expires_in}}var F2="https://chatgpt.com/backend-api/wham/usage";async function vB(B){let Z=B.logger??N2,$=B.accountKey??"unknown",W=Date.now();Z.debug("wham usage fetch started",{pid:process.pid,accountId:$});try{let X=await B.fetchImpl(F2,{signal:AbortSignal.timeout(15000),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(!X.ok){let K=X0(X.headers.get("retry-after"));throw Object.assign(Error(`wham usage check failed: ${X.status}`),{status:X.status,retryAfter:K})}let{normalizeWham:z}=await import("./quota-normalize-dvwtmy7f.js"),G=z(await X.json());return Z.debug("wham usage fetch succeeded",{pid:process.pid,accountId:$,status:X.status,elapsedMs:Date.now()-W}),G}catch(X){throw Z.warn("wham usage fetch failed",{pid:process.pid,accountId:$,status:typeof X?.status==="number"?X.status:"error",elapsedMs:Date.now()-W,error:_0(X)}),X}}import{createHash as O2}from"node:crypto";var V2=globalThis.setTimeout,b2=5;function p(B){let Z=B?.quota?.checkIntervalMinutes??b2;return Math.max(1,Z)*60000}function D2(B){return B?.quota?.enabled!==!1}function a(B,Z){if(!B?.resetsAt)return!1;let $=Date.parse(B.resetsAt);return Number.isFinite($)&&$<=Z}function uB(B,Z,$,W,X){if(X!==void 0&&Number.isFinite(X)&&X>$)return X;let z=Z===z0?B?.primary:Z===K0?B?.secondary:void 0,G=z?.resetsAt?Date.parse(z.resetsAt):NaN;if(Number.isFinite(G)&&G>$)return G;return $+W}function U2(B){let Z=B?.quota?.minimumRemaining||{};return{primary:Z.primary??Z["5h"]??15,secondary:Z.secondary??Z["1w"]??10}}function q0(B,Z,$){if(!D2(Z))return $+p(Z);let W=U2(Z),X=[];for(let z of["primary","secondary"]){let G=B?.[z];if(!G)continue;if(G.remainingPercent>=W[z])continue;let K=G.resetsAt?Date.parse(G.resetsAt):Number.NaN;if(!Number.isFinite(K)||K<=$)return $+p(Z);X.push(K)}if(!X.length)return $+p(Z);return Math.min(...X)+60000}function M2(B){if(!B?.quota?.mainQuota||!B.quota.mainQuotaCheckedAt)return null;return{quota:B.quota.mainQuota,checkedAt:B.quota.mainQuotaCheckedAt,tokenFingerprint:B.quota.mainQuotaToken}}function _2(B){let Z=B?.quota?.refreshEveryNRequests;return typeof Z==="number"&&Number.isFinite(Z)&&Z>0?Math.floor(Z):0}function L(B){return O2("sha256").update(B).digest("hex").slice(0,16)}class D{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;rateLimitedUntilMap=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!==L(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)!==L(Z))return this.fallbacks.delete(B),this.fallbackTokenFps.delete(B),null;return $}getAllFallbacks(){return this.fallbacks}setMain(B,Z,$,W=!1){if(!W&&!C0(Z.quota))return;if(this.mainTokenFp=L(B),$&&this.mainQuotaAccountId&&this.mainQuotaAccountId!==$)this.clearRateLimited("main");if($)this.mainQuotaAccountId=$;if(this.main=Z,Y0(Z.quota))this.clearRateLimited("main")}peekMainForPolicy(B){if(B&&this.mainQuotaAccountId&&this.mainQuotaAccountId!==B)return null;return this.main}peekFallbackForPolicy(B,Z){let $=this.fallbacks.get(B)??null;if(Z&&$?.accountId&&$.accountId!==Z)return null;return $}setFallback(B,Z,$,W=!1,X){if(!W&&!C0(Z.quota))return;let z=this.fallbacks.get(B)?.accountId;if(X&&z&&X!==z)this.clearRateLimited(B);let G=X??z;if(this.fallbacks.set(B,{...Z,accountId:G}),$)this.fallbackTokenFps.set(B,L($));else this.fallbackTokenFps.delete(B);if(Y0(Z.quota))this.clearRateLimited(B)}markRateLimited(B,Z){let $=this.rateLimitedUntilMap.get(B);if($!==void 0&&$>Z)return;this.rateLimitedUntilMap.set(B,Z)}isRateLimited(B){let Z=this.rateLimitedUntilMap.get(B);return Z!==void 0&&this.now()<Z}rateLimitedUntil(B){return this.rateLimitedUntilMap.get(B)}clearRateLimited(B){this.rateLimitedUntilMap.delete(B)}async refreshMain(B){let Z=L(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 $=D.fallbackInflightKey(B,Z),W=this.inflightFallbacks.get($);if(W)return W;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 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 W=this.getFallback($.id,$.access);if(W&&Z<W.refreshAfter)continue;try{await this.refreshFallback($.id,$.access)}catch{}}}refreshMainInBackground(B){let Z=L(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=_2(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 $=M2(B);if(!$)return;let W=Z?L(Z):null;if(W&&$.tokenFingerprint&&$.tokenFingerprint!==W)return;let X={quota:$.quota,refreshAfter:q0($.quota,B,$.checkedAt),checkedAt:$.checkedAt};if(this.main&&this.main.checkedAt>=X.checkedAt&&(!W||!this.mainTokenFp||this.mainTokenFp===W))return;if(this.main=X,this.mainTokenFp=$.tokenFingerprint??null,B?.mainAccountId){if(this.mainQuotaAccountId&&this.mainQuotaAccountId!==B.mainAccountId)this.clearRateLimited("main");this.mainQuotaAccountId=B.mainAccountId}}seedMainBackoffFromStorage(B){let Z=B?.quota?.mainLastQuotaApiError;this.mainLastApiError=Z&&x(Z,this.now())?Z:void 0}seedFallbacksFromAccounts(B){let Z=p(this.storage);for(let $ of B){if($.enabled===!1)continue;if(!$.quota)continue;let W=Math.max($.quota.primary?.checkedAt??0,$.quota.secondary?.checkedAt??0);if(W<=0)continue;let X=this.getFallback($.id,$.access);if(X&&X.checkedAt>=W)continue;this.setFallback($.id,{quota:$.quota,refreshAfter:W+Z,checkedAt:W},$.access,!1,$.accountId)}}isBackedOff(){return x(this.mainLastApiError,this.now())}isFallbackBackedOff(B,Z){if(Z){if(this.fallbackErrorTokenFps.get(B)!==L(Z))return!1}return x(this.fallbackApiErrors.get(B),this.now())}getLastApiError(){return this.mainLastApiError}static API_CALL_GAP_MS=1000;static fallbackInflightKey(B,Z){return JSON.stringify([B,L(Z)])}static quotaLockName(B){return`opencode-fallback-quota-refresh-${B.replace(/[^a-zA-Z0-9._-]+/g,"-")||"account"}`}_enqueueApiFetch(B){let Z=async()=>{let W=this.now()-this.lastApiCallAt;if(W<D.API_CALL_GAP_MS)await new Promise((X)=>{let z=V2(X,D.API_CALL_GAP_MS-W);if(typeof z==="object"&&"unref"in z)z.unref()});return this.lastApiCallAt=this.now(),B()},$=this.apiGate.then(Z,Z);return this.apiGate=$.catch(()=>{}),$}async _fetchMain(B){let Z=L(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 A({name:"opencode-main-quota-refresh",ttlMs:30000});if(!$){let W=this.main;if(W&&this.now()<W.refreshAfter)return W.quota;throw Error("Quota refresh is already in progress")}try{let W=this.now(),X=await this._fetchQuota(B),z=this.now();if(this.mainTokenFp=L(B),this.main={quota:X,refreshAfter:q0(X,this.storage,z),checkedAt:z},Y0(X))this.clearRateLimited("main");return this.mainLastApiError=void 0,this.onMainQuotaFetched?.(X,z,this.mainTokenFp,W),X}catch(W){throw this._handleMainFetchError(W),W}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 W=this.getFallback(B,Z);if(W)return W.quota;throw Error("Quota API rate-limited — try again later")}let $=await A({name:D.quotaLockName(B),ttlMs:30000});if(!$){let W=this.getFallback(B,Z);if(W&&this.now()<W.refreshAfter)return W.quota;throw Error("Quota refresh is already in progress")}try{let W=await this._fetchQuota(Z),X=this.now();return this.setFallback(B,{quota:W,refreshAfter:X+p(this.storage),checkedAt:X},Z,!0),this.fallbackApiErrors.delete(B),this.fallbackErrorTokenFps.delete(B),W}finally{await $.release()}}catch($){throw this._handleFallbackFetchError(B,Z,$),$}finally{this.inflightFallbacks.delete(D.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(D.isAuthError(B))return;this.mainLastApiError=m({error:B,now:this.now(),previous:this.mainLastApiError}),this.onApiError?.(this.mainLastApiError)}_handleFallbackFetchError(B,Z,$){if(D.isAuthError($))return;let W=L(Z),X=this.fallbackErrorTokenFps.get(B)===W?this.fallbackApiErrors.get(B):void 0;this.fallbackApiErrors.set(B,m({error:$,now:this.now(),previous:X})),this.fallbackErrorTokenFps.set(B,W)}}function C0(B){return Boolean(B.primary||B.secondary)}function Y0(B){let{primary:Z,secondary:$}=B;if(!Z&&!$)return!1;if(Z&&Z.usedPercent>=100)return!1;if($&&$.usedPercent>=100)return!1;return!0}import{createHash as T2,randomUUID as x2}from"node:crypto";import{setTimeout as A2}from"node:timers/promises";import{randomUUID as q2}from"node:crypto";import{mkdir as C2,rename as S2,rm as E2,writeFile as R2}from"node:fs/promises";import{dirname as y2}from"node:path";async function f(B,Z){await C2(y2(B),{recursive:!0});let $=`${B}.${q2()}.tmp`;await R2($,`${JSON.stringify(Z,null,2)}
88
- `,{encoding:"utf8",mode:384});try{await S2($,B)}catch(W){throw await E2($,{force:!0}).catch(()=>{}),W}}import{readFile as i2}from"node:fs/promises";var R=v("refresh"),t=v("accounts"),f2=1e4,I2=15000,j0=50;function U(B){return B.type==="oauth"}function m2(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 JZ(B){return B.costZeroing?.enabled!==!1}class e extends Error{code="ACCOUNT_REMOVED_DURING_REFRESH";constructor(B){super(`Fallback account ${B} was removed before refresh`);this.name="AccountRemovedDuringRefreshError"}}var k2=[401,403,429],S0={primary:0,secondary:0},h2=!1,H0={primary:5,secondary:10};function J(B){return B!=null&&typeof B==="object"&&!Array.isArray(B)}var w2=new Set(["__proto__","constructor","prototype"]);function v2(B){return B.length>0&&!w2.has(B)}function p2(B){return B instanceof e||J(B)&&B.name==="AccountRemovedDuringRefreshError"&&B.code==="ACCOUNT_REMOVED_DURING_REFRESH"}function E0(B){return{id:typeof B.id==="string"&&B.id.trim()?B.id.trim():x2(),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 R0(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),W=Number(B.retryCount);return{message:B.message,checkedAt:Z,nextRetryAt:Number.isFinite($)?$:void 0,retryCount:Number.isFinite(W)?W:void 0,tokenHash:typeof B.tokenHash==="string"?B.tokenHash:void 0}}function l2(B){if(!J(B))return;let Z={};for(let $ of["primary","secondary"]){let W=B[$];if(!J(W))continue;let X=Number(W.usedPercent),z=Number(W.remainingPercent),G=Number(W.checkedAt);if(!Number.isFinite(X)||!Number.isFinite(z)||!Number.isFinite(G))continue;let K=typeof W.windowMinutes==="number"?W.windowMinutes:Number.NaN;Z[$]={usedPercent:X,remainingPercent:z,checkedAt:G,resetsAt:typeof W.resetsAt==="string"?W.resetsAt:void 0,...Number.isFinite(K)&&K>0?{windowMinutes:K}:{}}}for(let $ of["resetCreditsAvailable","resetCreditsApplicable"]){let W=typeof B[$]==="number"?B[$]:Number.NaN;if(Number.isFinite(W)&&W>=0)Z[$]=W}return Object.keys(Z).length?Z:void 0}function g2(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(!m2(Z))return null;let W=B.authHeader==="x-api-key"?"x-api-key":"authorization-bearer";return{...E0(B),type:"api",apiKey:$||void 0,baseURL:Z,authHeader:W}}if(B.type!=="oauth")return null;if(typeof B.refresh!=="string"||!B.refresh.trim())return null;return{...E0(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:R0(B.lastRefreshError),lastQuotaRefreshError:R0(B.lastQuotaRefreshError),quota:l2(B.quota)}}function d2(B){if(!J(B))return;let Z=Object.create(null);for(let[$,W]of Object.entries(B)){if(!v2($)||!J(W))continue;let X={};if(J(W.inFlight))X.inFlight={...W.inFlight};if(J(W.lastOutcome)&&typeof W.lastOutcome.code==="string"&&W.lastOutcome.code.length>0&&typeof W.lastOutcome.at==="number"&&Number.isFinite(W.lastOutcome.at))X.lastOutcome={code:W.lastOutcome.code,at:W.lastOutcome.at,...J(W.lastOutcome.previousOutcome)&&typeof W.lastOutcome.previousOutcome.code==="string"&&W.lastOutcome.previousOutcome.code.length>0&&typeof W.lastOutcome.previousOutcome.at==="number"&&Number.isFinite(W.lastOutcome.previousOutcome.at)?{previousOutcome:{code:W.lastOutcome.previousOutcome.code,at:W.lastOutcome.previousOutcome.at}}:{}};if(typeof W.cooldownUntil==="number"&&Number.isFinite(W.cooldownUntil))X.cooldownUntil=W.cooldownUntil;if(Object.keys(X).length>0)Z[$]=X}return Object.keys(Z).length>0?Z:void 0}var y0=new Set;function f0(B){if(B.length===0)return;let Z=JSON.stringify([...B].sort());if(y0.has(Z))return;y0.add(Z),t.warn("account load-dropped, preserved on disk",{droppedIds:B})}function I0(B){if(!J(B)||!Array.isArray(B.accounts))return null;let Z=B.accounts,$=Z.map(g2).filter((W)=>W!=null);if($.length<Z.length){let W=new Set;for(let G of Z)if(J(G)&&typeof G.id==="string"&&G.id.trim())W.add(G.id.trim());let X=new Set($.map((G)=>G.id)),z=[];for(let G of W)if(!X.has(G))z.push(G);f0(z)}return{version:1,main:{type:"opencode",provider:"openai"},routing:J(B.routing)?B.routing:void 0,fallbackOn:Array.isArray(B.fallbackOn)?B.fallbackOn.filter((W)=>Number.isInteger(W)):void 0,refresh:J(B.refresh)?B.refresh:void 0,quota:J(B.quota)?B.quota:void 0,reset:d2(B.reset),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:$}}async function T(B){try{return{exists:!0,value:JSON.parse(await i2(B,"utf8"))}}catch(Z){if(Z.code==="ENOENT")return{exists:!1,value:null};throw Z}}function M(B){return Object.fromEntries(Object.entries(B).filter(([,Z])=>Z!==void 0))}async function u2(B){let Z;try{Z=(await T(B)).value}catch{return null}if(!J(Z)||!Array.isArray(Z.accounts))return null;let $=new Set;for(let W of Z.accounts){if(!J(W))continue;if(typeof W.id!=="string")continue;let X=W.id.trim();if(!X)continue;$.add(X)}return $}function m0(B,Z){if(!J(B))return B;let $=J(Z)?Z:{},W=J($.main)?$.main:void 0,X=J($.accounts)?$.accounts:{},z=J(B.quota)?B.quota:{},G=J(B.refresh)?B.refresh:{},K=W??z,Y=W??G,H=Array.isArray(B.accounts)?B.accounts.map((Q)=>{if(!J(Q))return Q;let b=typeof Q.id==="string"&&J(X[Q.id])?X[Q.id]:{};return{...Q,...b}}):void 0;return k0({...B,refresh:M({...G,mainLastRefreshError:Y.lastRefreshError,mainRefreshLeaseId:Y.refreshLeaseId,mainRefreshLeaseUntil:Y.refreshLeaseUntil,mainRefreshLeaseTokenHash:Y.refreshLeaseTokenHash}),quota:M({...z,mainQuota:K.quota,mainQuotaCheckedAt:K.quotaCheckedAt,mainQuotaToken:K.quotaToken,mainLastQuotaApiError:K.lastQuotaApiError}),accounts:H})}async function s2(B=I()){let Z=await T(B);if(!Z.exists)return null;let $=await T(u(B));return I0(m0(Z.value,$.value))}function k0(B){return Object.fromEntries(Object.entries(B).filter(([,Z])=>Z!==void 0))}function r2(B){return M({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 h0(B){if(B.type==="api")return M({apiKey:B.apiKey,lastUsed:B.lastUsed});return M({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 B0(B){return Math.max(B?.primary?.checkedAt??0,B?.secondary?.checkedAt??0)}function l(B,Z,$){if($ in Z)B[$]=Z[$];else delete B[$]}function n2(B,Z){return B.access===Z.access&&B.refresh===Z.refresh&&B.expires===Z.expires&&B.lastRefreshedAt===Z.lastRefreshedAt}function c2(B,Z){if(!n2(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 o2(B,Z,$){let W=Z.lastRefreshedAt??0,X=$.lastRefreshedAt??0,z=Z.expires??0,G=$.expires??0,K=X>W?$:W>X?Z:G>z?$:z>G?Z:c2(Z,$);l(B,K,"access"),l(B,K,"refresh"),l(B,K,"expires"),l(B,K,"lastRefreshedAt"),l(B,K,"lastRefreshError")}function a2(B,Z){if(!J(B))return Z;let $=B,W=B0($.quota),X=B0(Z.quota),z=W>X,G=z?{...$,...Z,quota:$.quota,lastQuotaRefreshError:$.lastQuotaRefreshError}:{...$,...Z};if(!z&&!("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 o2(G,$,Z),G}function w0(B){let Z=B.refresh?M({enabled:B.refresh.enabled,intervalMinutes:B.refresh.intervalMinutes,refreshBeforeExpiryMinutes:B.refresh.refreshBeforeExpiryMinutes}):void 0,$=B.quota?M({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 k0({version:1,main:B.main,routing:B.routing,fallbackOn:B.fallbackOn,refresh:Z,quota:$,reset:B.reset,dump:B.dump,costZeroing:B.costZeroing,killswitch:B.killswitch,logging:B.logging,cachekeep:B.cachekeep,mainAccountId:B.mainAccountId,accounts:B.accounts.map(r2)})}async function d(B){let Z=Date.now(),$=Z+I2,W=0;while(Date.now()<=$){W++;let G=await A({name:"save",ttlMs:f2,path:B});if(G)return G;let K=$-Date.now();if(K<=0)break;await A2(Math.min(j0+d0(j0),K))}let X=Date.now()-Z,z=Math.round(X/Math.max(1,W));throw Error(`Timed out after ${X}ms waiting for the account store lock on ${B} (${W} attempts, ~${z}ms apart; retry interval is ${j0}ms). A gap near the retry interval means lock contention; a much larger one means this process's event loop was saturated and the wait expired without getting scheduled.`)}function v0(B){let Z=Object.fromEntries(B.accounts.map(($)=>[$.id,h0($)]));return{version:1,main:M({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}}function t2(B){if(!J(B)||!Array.isArray(B.accounts))return null;let Z=new Set;for(let $ of B.accounts){if(!J($))continue;if(typeof $.id!=="string")continue;let W=$.id.trim();if(!W)continue;Z.add(W)}return Z}function e2(B,Z,$,W){if(!J(B)||!Array.isArray(B.accounts))return{preservedRawEntries:[],preservedIds:[]};let X=[],z=[];for(let G of Z){if($.has(G))continue;if(W.has(G))continue;let K=B.accounts.find((Y)=>J(Y)&&typeof Y.id==="string"&&Y.id.trim()===G);if(!K)continue;X.push(K),z.push(G)}return{preservedRawEntries:X,preservedIds:z}}function BB(B){if(!Array.isArray(B))return[];let Z=[];for(let $ of B){if(!J($))continue;if(typeof $.id!=="string")continue;Z.push($.id)}return Z}function ZB(B,Z,$){let W=t2(B);if(W===null)return[];let{preservedRawEntries:X,preservedIds:z}=e2(B,W,Z,$);return f0(z),X}async function QZ(B,Z=I(),$={}){let W=u(Z),X=await d(Z);try{let z=await d(W);try{let G=await T(Z),K=await T(W),Y=(G.exists?I0(m0(G.value,K.value)):null)??$B(),j=new Set(Y.accounts.map((O)=>O.id)),H=B(Y)??Y,Q=new Set($.allowDrop??[]),b=ZB(G.value,j,Q),N=w0(H),F=new Set((Array.isArray(N.accounts)?N.accounts:[]).map((O)=>J(O)&&typeof O.id==="string"?O.id.trim():"").filter(Boolean)),s=b.filter((O)=>{if(!J(O))return!1;if(typeof O.id!=="string")return!1;return!F.has(O.id.trim())}),Z0={...J(G.value)?G.value:{},...N,accounts:[...Array.isArray(N.accounts)?N.accounts:[],...s]};return await f(Z,Z0),await f(W,v0(H)),t.debug("account config written",{accountCount:Z0.accounts.length,accountIds:BB(Z0.accounts)}),H}finally{await z.release()}}finally{await X.release()}}function $B(){return{version:1,main:{type:"opencode",provider:"openai"},accounts:[]}}function WB(B,Z){B.main=B.main??{};let $=typeof B.main.quotaCheckedAt==="number"?B.main.quotaCheckedAt:B0(B.main.quota),W=typeof Z.quota?.mainQuotaCheckedAt==="number"?Z.quota.mainQuotaCheckedAt:B0(Z.quota?.mainQuota);if($>W)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 XB(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 Q0(B){if(Array.isArray(B))return B.map(Q0);if(!J(B))return B;return Object.fromEntries(Object.entries(B).filter(([,Z])=>Z!==void 0).map(([Z,$])=>[Z,Q0($)]))}async function GB(B,Z=I(),$={mainQuota:!0,mainRefresh:!0,accounts:!0}){let W=u(Z),X=await d(W);try{let z=(await T(W)).value,G=J(z)?{...z,version:1}:{version:1};if($.mainQuota)WB(G,B);if($.mainRefresh)XB(G,B);if($.accounts){let K=$.accounts===!0?null:new Set($.accounts),Y=await u2(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]=a2(G.accounts[j.id],h0(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 f(W,Q0(G))}finally{await X.release()}}function zB(B){return B?.fallbackOn?.length?B.fallbackOn:k2}function NZ(B,Z){return zB(Z).includes(B)}function KB(B){let Z=B?.quota?.minimumRemaining||{};return{primary:Z.primary??Z["5h"]??S0.primary,secondary:Z.secondary??Z["1w"]??S0.secondary}}function N0(B){return B?.quota?.enabled!==!1}function i(B){return B?.quota?.failClosedOnUnknownQuota??h2}function p0(B,Z,$=Date.now()){if(!N0(Z))return!0;if(!B)return!i(Z);let W=KB(Z),X=i(Z);for(let z of["primary","secondary"]){let G=B[z];if(!G)continue;if(a(G,$)){if(X)return!1;continue}if(G.remainingPercent<W[z])return!1}return!0}function l0(B){return B?.killswitch?.enabled===!0}function T0(B){return{primary:B?.primary??B?.["5h"]??H0.primary,secondary:B?.secondary??B?.["1w"]??H0.secondary}}function g0(B,Z){if(!B?.killswitch)return H0;if(Z&&B.killswitch.accounts?.[Z])return T0(B.killswitch.accounts[Z]);return T0(B.killswitch.main)}function PZ(B,Z,$,W=Date.now()){if(!l0(Z))return!0;if(!B)return!i(Z);let X=g0(Z,$),z=i(Z);for(let G of["primary","secondary"]){let K=B[G];if(!K)continue;if(a(K,W)){if(z)return!1;continue}if(K.remainingPercent<X[G])return!1}return!0}function LZ(B,Z,$,W){if(!l0(W))return 300;let X=[],z=[{accountId:void 0,quota:B},...Z];for(let{accountId:K,quota:Y}of z){if(!Y)continue;let j=g0(W,K),H=[],Q=!1;for(let b of["primary","secondary"]){let N=Y[b];if(!N||a(N,$))continue;if(N.remainingPercent>=j[b])continue;let F=N.resetsAt?Date.parse(N.resetsAt):NaN;if(!Number.isFinite(F)||F<=$){Q=!0;break}H.push(F)}if(Q||H.length===0)continue;X.push(Math.max(...H))}if(X.length===0)return 300;let G=Math.min(...X);return Math.max(1,Math.ceil((G-$)/1000))}function YB(B){return typeof B.version==="number"&&Array.isArray(B.accounts)}async function FZ(B,Z=I()){let $=u(Z),W=await d(Z);try{let X=await d($);try{let z=await T(Z);if(z.exists&&J(z.value)){if(YB(z.value))return}if(!B)return;let G={version:1,main:{type:"opencode",provider:"openai"},accounts:[]};if(B.access){let j=c({id_token:"",access_token:B.access,refresh_token:B.refresh});if(j)G.mainAccountId=j}let Y={...z.exists&&J(z.value)?z.value:{},...w0(G)};await f(Z,Y),await f($,v0(G))}finally{await X.release()}}finally{await W.release()}}function jB(B){return B?.refresh?.enabled!==!1}function JB(B){return(B?.refresh?.refreshBeforeExpiryMinutes??240)*60000}function d0(B){return Math.floor(Math.random()*(B+1))}function y(B,Z,$){return!B.access||!B.expires||B.expires-$<=JB(Z)}function HB(B,Z){return Boolean(B.access&&typeof B.expires==="number"&&B.expires>Z)}function QB(B,Z){return Boolean(B.mainAccountId&&Z.accountId&&Z.accountId===B.mainAccountId)}function P(B,Z){let $=B.accounts.findIndex((W)=>W.id===Z.id);if($!==-1)B.accounts[$]=Z}function g(B){return B instanceof Error?B.message:String(B)}function P0(B,Z,$){B.lastRefreshError=F0({error:Z,now:$,refreshToken:B.refresh,previous:B.lastRefreshError})}function J0(B,Z,$){if(B.lastQuotaRefreshError=m({error:Z,now:$,previous:B.lastQuotaRefreshError}),Z?.isRefreshError===!0)P0(B,Z,$)}function NB(B){return`fallback-oauth-refresh-${T2("sha256").update(B).digest("base64url").slice(0,16)}`}function x0(B,Z){if(!B)return!1;if(!B.resetsAt)return!0;let $=Date.parse(B.resetsAt);return Number.isFinite($)?$>Z:!0}function PB(B,Z){if(!B)return!1;return x0(B.primary,Z)||x0(B.secondary,Z)}function LB(B,Z,$){if(!B)return!1;let W=Z?.quota?.checkIntervalMinutes??5,X=Math.max(1,W)*60000,z=Math.max(B.primary?.checkedAt??0,B.secondary?.checkedAt??0);return $-z<X}function A0(B,Z,$){return!LB(B.quota,Z,$)}function FB(B,Z,$,W){return W0($)&&p0(B.quota,Z,W)&&PB(B.quota,W)}function OB(B){let Z=B?.quota?.checkIntervalMinutes??5;return Math.max(1,Z)*60000}var VB=60000,bB=60000,DB=600000,UB=1e4,MB=100;var OZ=globalThis.setTimeout.bind(globalThis),VZ=globalThis.clearTimeout.bind(globalThis);class _B{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??I(),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.primary?.checkedAt??0,B.quota.secondary?.checkedAt??0);if($<=0)return;let W=this.quotaManager.getFallback(B.id,B.access);if(W&&W.checkedAt>=$)return;this.quotaManager.setFallback(B.id,{quota:B.quota,refreshAfter:$+OB(Z),checkedAt:$},B.access,!1,B.accountId)}async load(){return s2(this.configPath)}async save(B,Z){await GB(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(()=>{})},VB+d0(bB)),"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 $=[],W=!1;for(let X of Z.accounts){if(X.enabled===!1||!U(X))continue;if(QB(Z,X))continue;let z=!1,G=X;try{if(y(G,Z,this.now())){let K=G.lastRefreshError;if(K&&_(K,G.refresh,this.now()))throw z=!0,Error(r(K,this.now()));try{G=await this.refreshAccount(G,Z),W=!0}catch(Y){if(p2(Y))continue;z=!0;let j=Z.accounts.find((H)=>H.id===X.id&&U(H));if(j&&!_(j.lastRefreshError,j.refresh,this.now()))P0(j,Y,this.now()),P(Z,j),W=!0;throw Y}}if(this.seedFallbackQuota(G,Z),this.accountPassesQuotaPolicy(this.quotaPolicyAccount(G),Z))$.push(G)}catch(K){let Y=HB(G,this.now());if(z){if(!Y)continue}else if(!Y)continue;if(FB(G,Z,K,this.now()))R.debug("fallback quota using cached quota after refresh error",{pid:process.pid,accountId:G.id,error:g(K)}),$.push(G);else if(!i(Z))$.push(G)}}if(W)try{await this.save(Z)}catch(X){t.warn("fallback selection bookkeeping not persisted",{pid:process.pid,error:g(X)})}return $}async markUsed(B){try{let Z=await this.load();if(!Z)return;let $=Z.accounts.find((W)=>W.id===B.id);if(!$)return;$.lastUsed=this.now(),await this.save(Z,[$.id])}catch(Z){t.warn("lastUsed stamp not persisted",{pid:process.pid,accountId:B.id,error:g(Z)})}}accountPassesQuotaPolicy(B,Z){return p0(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||!jB(B))return;let Z=!1;for(let $ of B.accounts){if($.enabled===!1||!U($))continue;if(!y($,B,this.now()))continue;if(_($.lastRefreshError,$.refresh,this.now()))continue;try{R.debug("fallback oauth background due",{pid:process.pid,accountId:$.id,expiresInMs:$.expires?$.expires-this.now():void 0}),await this.refreshAccount($,B),Z=!0}catch(W){R.warn("fallback oauth background failed",{pid:process.pid,accountId:$.id,error:g(W)}),P0($,W,this.now()),P(B,$),Z=!0}}if(Z)await this.save(B)}async refreshQuotaForDueAccounts(){let B=await this.load();if(!B||!N0(B))return;if(!this.options.fetchQuotaFn)return;let Z=!1;for(let $ of B.accounts){if($.enabled===!1||!U($))continue;let W=$;try{if(y(W,B,this.now())){if(_(W.lastRefreshError,W.refresh,this.now()))continue;W=await this.refreshAccount(W,B),Z=!0}if(x(W.lastQuotaRefreshError,this.now()))continue;if(this.seedFallbackQuota(W,B),!(this.quotaManager?this.quotaManager.isFallbackStale(W.id,W.access):A0(W,B,this.now())))continue;await this.refreshAccountQuota(W,B),Z=!0}catch(X){J0($,X,this.now()),P(B,$),Z=!0}}if(Z)await this.save(B),this.onFallbackStorageChanged?.()}async refreshQuotaForAllAccounts(B={}){let Z=await this.load(),$=[];if(!Z||!N0(Z))return{storage:Z,errors:$};if(!this.options.fetchQuotaFn)return{storage:Z,errors:$};let W=B.force??!1,X=!1;for(let z of Z.accounts){if(z.enabled===!1||!U(z))continue;let G=z;try{if(y(G,Z,this.now())){let K=G.lastRefreshError;if(K&&_(K,G.refresh,this.now()))throw Error(r(K,this.now()));G=await this.refreshAccount(G,Z),X=!0}if(!W&&!A0(G,Z,this.now())){if(G.lastQuotaRefreshError)G.lastQuotaRefreshError=void 0,P(Z,G),X=!0;continue}await this.refreshAccountQuota(G,Z),X=!0}catch(K){J0(z,K,this.now()),P(Z,z),X=!0,$.push({accountId:z.id,message:g(K)})}}if(X)await this.save(Z);return{storage:Z,errors:$}}async refreshAccount(B,Z,$={}){let W=this.refreshPromises.get(B.id);if(W){let G=await W;return P(Z,G),G}let X=this.refreshAccountNow(B,Z,$).finally(()=>{this.refreshPromises.delete(B.id)});this.refreshPromises.set(B.id,X);let z=await X;return P(Z,z),z}async waitForConcurrentFallbackRefresh(B,Z,$,W){let X=Date.now()+UB;while(Date.now()<X){await new Promise((j)=>setTimeout(j,MB));let z=await this.load(),G=z?.accounts.find((j)=>j.id===B.id&&U(j));if(!G)continue;if((G.access!==$.access||G.refresh!==$.refresh||(G.expires??0)>($.expires??0)+60000)&&(W.force||!y(G,z,this.now())))return P(Z,G),R.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&&_(Y,G.refresh,this.now()))throw P(Z,G),Error(r(Y,this.now()))}return null}async refreshAccountNow(B,Z,$){let W=await this.load(),X=W?.accounts.find((K)=>K.id===B.id&&U(K));if(X&&!$.force&&!y(X,W,this.now()))return P(Z,X),X;let z=X??B,G=await A({name:NB(z.id),ttlMs:DB,path:this.configPath,now:this.now,renew:!0});if(!G){R.debug("fallback oauth refresh skipped file lock",{pid:process.pid,accountId:z.id});let K=await this.waitForConcurrentFallbackRefresh(B,Z,z,$);if(K)return K;throw Error("Fallback OAuth refresh is already in progress")}try{if(W=await this.load(),X=W?.accounts.find((H)=>H.id===B.id&&U(H)),X&&!$.force&&!y(X,W,this.now()))return P(Z,X),X;if(!X)throw new e(B.id);z=X;let K=this.options.refreshFn??(async()=>{throw Error("No refreshFn injected into FallbackAccountManager")});R.debug("fallback oauth refresh request start",{pid:process.pid,accountId:z.id,force:$.force===!0,expiresInMs:z.expires?z.expires-this.now():void 0});let Y=await K({refreshToken:z.refresh,fetchImpl:this.fetchImpl,now:this.now});if(z.access=Y.access,z.refresh=Y.refresh,z.expires=Y.expires,z.lastRefreshedAt=Y.expires-Y.expiresIn*1000,z.lastRefreshError=void 0,P(Z,z),await this.save(Z),!(await this.load())?.accounts.some((H)=>H.id===B.id))throw new e(B.id);return R.debug("fallback oauth refresh succeeded",{pid:process.pid,accountId:z.id,expiresInMs:z.expires?z.expires-this.now():void 0}),z}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 W=this.options.fetchQuotaFn??(async()=>{throw Error("No fetchQuotaFn injected — wham/usage supplement is disabled")}),X=(z)=>this.quotaManager?this.quotaManager.refreshFallback($.id,z):W({accessToken:z,fetchImpl:this.fetchImpl,now:this.now});try{if(!$.access)throw Error(`Fallback account ${B.id} has no access token`);let z=await X($.access);$.quota=z,$.lastQuotaRefreshError=void 0,P(Z,$),await this.save(Z)}catch(z){throw J0(B,z,this.now()),P(Z,B),z}}}
89
- export{L0 as h,F0 as i,_ as j,r as k,D0 as l,M0 as m,$2 as n,V0 as o,b0 as p,c as q,G0 as r,X2 as s,E as t,Y2 as u,j2 as v,J2 as w,H2 as x,xB as y,AB as z,_0 as A,wB as B,vB as C,uB as D,D as E,U as F,JZ as G,H0 as H,v2 as I,u2 as J,s2 as K,QZ as L,NZ as M,l0 as N,g0 as O,PZ as P,LZ as Q,FZ as R,_B as S};
@@ -1,3 +0,0 @@
1
- import{appendFileSync as D,chmodSync as F,existsSync as B,renameSync as X,statSync as N}from"node:fs";import{tmpdir as P}from"node:os";import{join as K}from"node:path";var j={error:0,warn:1,info:2,debug:3,trace:4},w=!1,A=5242880;function Y(){return process.env.OPENCODE_OPENAI_AUTH_LOG_FILE??K(P(),"opencode-openai-auth.log")}var J;function S(q){if(q===void 0||q in j)J=q}function L(){if(J)return J;let q=process.env.OPENCODE_OPENAI_AUTH_LOG_LEVEL;if(q&&q in j)return q;return"info"}var I=/^(authorization|x-api-key|cookie|set-cookie|refresh|access|token)$/i;function _(q){if(I.test(q))return!0;let G=q.toLowerCase().replace(/[-_]/g,"");if(G==="chatgptaccountid")return!0;if(G.includes("apikey"))return!0;if(G.endsWith("secret")||G.endsWith("password"))return!0;if(G.endsWith("token")&&!G.endsWith("tokens"))return!0;return!1}var x=/\b(Bearer\s+[\w.-]+|sk-[\w-]+|eyJ[\w.-]+)\b/g;function O(q){return C(q,new WeakSet)}function y(q){return M(q,new WeakSet)}function M(q,G){if(typeof q==="string")return q.replace(x,"***REDACTED***");if(Array.isArray(q)){if(G.has(q))return"[Circular]";G.add(q);let H=q.map((Q)=>M(Q,G));return G.delete(q),H}if(q&&typeof q==="object"){if(G.has(q))return"[Circular]";G.add(q);let H={};for(let[Q,W]of Object.entries(q))H[Q]=M(W,G);return G.delete(q),H}return q}function C(q,G){if(typeof q==="string")return q.replace(x,"***REDACTED***");if(Array.isArray(q)){if(G.has(q))return"[Circular]";G.add(q);let H=q.map((Q)=>C(Q,G));return G.delete(q),H}if(q&&typeof q==="object"){if(G.has(q))return"[Circular]";G.add(q);let H={};for(let[Q,W]of Object.entries(q))H[Q]=_(Q)?"***REDACTED***":C(W,G);return G.delete(q),H}return q}var $=[],z,T=3;function U(q){try{F(q,384)}catch{}}function b(){try{let q=Y();if(!(B(q)&&N(q).size>A))return;for(let H=T-1;H>=1;H--)if(B(`${q}.${H}`)){let Q=`${q}.${H+1}`;X(`${q}.${H}`,Q),U(Q)}let G=`${q}.1`;X(q,G),U(G)}catch{}}function V(){if(!$.length)return;let q=$.join("");$=[];try{b();let G=Y();if(B(G))U(G);D(G,q,{encoding:"utf8",mode:384})}catch{}}function R(){if(!z)z=setTimeout(()=>{z=void 0,V()},500)}if(!w)process.on("exit",V);function p(q){try{return` ${JSON.stringify(O(q))}`}catch{return" [unserializable]"}}function Z(q,G,H,Q){if(j[G]>j[L()])return;let W=`[${new Date().toISOString()}] ${G.toUpperCase()} [${q}] ${H}`+(Q===void 0?"":p(Q))+`
2
- `;if($.push(W),$.length>=50)V();else R()}function f(q){return{error:(G,H)=>Z(q,"error",G,H),warn:(G,H)=>Z(q,"warn",G,H),info:(G,H)=>Z(q,"info",G,H),debug:(G,H)=>Z(q,"debug",G,H),trace:(G,H)=>Z(q,"trace",G,H)}}
3
- export{S as Aa,O as Ba,y as Ca,f as Da};
@@ -1,2 +0,0 @@
1
- import{Da as _}from"./index-nrvjr97q.js";import{chmod as L,mkdir as M,readdir as W,readFile as $,rename as R,rmdir as S,unlink as X,writeFile as U}from"node:fs/promises";import{join as N,resolve as Y}from"node:path";var A=_("rpc");function E(q){try{return process.kill(q,0),!0}catch(H){return H.code==="EPERM"}}function C(q){return/^(?:openai-auth-)?[0-9a-f]{16}$/.test(q)}function O(q){return q!==null&&typeof q==="object"&&!Array.isArray(q)&&typeof q.pid==="number"&&Number.isFinite(q.pid)&&typeof q.port==="number"&&Number.isFinite(q.port)}async function Z(q){A.debug("rpc corrupt port file",{pid:process.pid,portFile:q}),await X(q).catch(()=>{})}async function w(q,H,I={}){let J=async()=>{if(await M(q,{recursive:!0,mode:I.secureDir?448:void 0}),I.secureDir)await L(q,448);await I.beforeWrite?.();let z={...H,startedAt:Date.now()},K=N(q,`port-${H.pid}.json`),B=`${K}.${process.pid}.tmp`;return await U(B,JSON.stringify(z),{encoding:"utf8",mode:384}),await R(B,K),K};try{return await J()}catch(z){if(z.code==="ENOENT")return await J();throw z}}async function x(q,H){let I;try{I=await W(q,{withFileTypes:!0})}catch(z){if(z.code==="ENOENT")return;throw z}let J=Y(H);for(let z of I){if(!z.isDirectory()||!C(z.name))continue;let K=N(q,z.name),B;try{B=await W(K)}catch(G){if(G.code==="ENOENT")continue;throw G}for(let G of B){if(!G.startsWith("port-")||!G.endsWith(".json"))continue;let Q=N(K,G),T;try{T=await $(Q,"utf8")}catch{continue}if(T===void 0)continue;let V;try{V=JSON.parse(T)}catch{await Z(Q);continue}if(!O(V)){await Z(Q);continue}if(!E(V.pid))await X(Q).catch(()=>{})}if(Y(K)!==J)await S(K).catch(()=>{})}}async function y(q,H){let I;try{I=await W(q)}catch{return null}let J=[];for(let B of I){if(!B.startsWith("port-")||!B.endsWith(".json"))continue;try{let G=JSON.parse(await $(N(q,B),"utf8"));if(Number.isFinite(G.port))if(E(G.pid))J.push(G);else X(N(q,B)).catch(()=>{})}catch{}}if(J.length===0)return null;let z=H!==void 0&&H>=1?J.filter((B)=>B.pid===H):[];return(z.length>0?z:J).sort((B,G)=>G.startedAt-B.startedAt)[0]??null}
2
- export{w as xa,x as ya,y as za};
@@ -1,2 +0,0 @@
1
- import{wa as l}from"./index-8f1200qx.js";import{Da as d}from"./index-nrvjr97q.js";import{createHash as $j,randomUUID as Vj}from"node:crypto";import{chmod as Xj,mkdir as Kj,readFile as c,rename as Yj,rm as Gj,writeFile as Lj}from"node:fs/promises";import{tmpdir as zj}from"node:os";import{dirname as Dj,join as o}from"node:path";var r=["primary","secondary"],u={primary:300,secondary:10080};function E(j){return Number.isInteger(j)?String(j):String(Math.round(j*10)/10)}function Jj(j,J){let Z=j!==void 0&&Number.isFinite(j)&&j>0?j:u[J];if(Z<60)return`${E(Z)}m`;if(Z<1440)return`${E(Z/60)}h`;return`${E(Z/1440)}d`}function Zj(j){if(!j)return[];let J=[];for(let Z of r){let $=j[Z];if(!$)continue;let V=$.windowMinutes,X=V!==void 0&&Number.isFinite(V)&&V>0?V:u[Z];J.push({key:Z,label:Jj(X,Z),window:$,windowMs:X*60000})}return J}var M=d("sidebar"),Oj="OPENCODE_OPENAI_AUTH_SIDEBAR_STATE_FILE",Bj=o(zj(),"opencode-openai-auth"),a=o(Bj,"sidebar-state.json"),Tj=/^[a-f0-9]{64}$/,b=604800000,Uj=256,i=3600000;function R(j){return $j("sha256").update(j).digest("hex")}function Qj(j){return typeof j==="number"&&Number.isFinite(j)&&j>=0?j:void 0}function y(j){let J=Qj(j);return J!==void 0?{resetCredits:J}:{}}function Nj(j){if(j===null||typeof j!=="object"||Array.isArray(j))return;let J={};for(let[Z,$]of Object.entries(j)){if($===null||typeof $!=="object"||Array.isArray($))continue;let V=$;if(typeof V.activeId!=="string"||typeof V.route!=="string"||typeof V.updatedAt!=="number"||!Number.isFinite(V.updatedAt))continue;J[Z]={activeId:V.activeId,route:V.route,updatedAt:V.updatedAt}}return Object.keys(J).length>0?J:void 0}function _j(j){if(j===null||typeof j!=="object"||Array.isArray(j))return;let J={};for(let[Z,$]of Object.entries(j)){if(!Tj.test(Z)||$===null||typeof $!=="object"||Array.isArray($))continue;let V=$;if(typeof V.accountId!=="string"||V.accountId.length===0||typeof V.assignedAt!=="number"||!Number.isFinite(V.assignedAt)||V.assignedAt<0||typeof V.lastSeenAt!=="number"||!Number.isFinite(V.lastSeenAt)||V.lastSeenAt<0||typeof V.inputBytes!=="number"||!Number.isFinite(V.inputBytes)||V.inputBytes<0)continue;let X=V.quotaCheckedAt;if(X!==void 0&&(typeof X!=="number"||!Number.isFinite(X)||X<0))continue;let K=V.wireAccountId;J[Z]={accountId:V.accountId,assignedAt:V.assignedAt,lastSeenAt:V.lastSeenAt,inputBytes:V.inputBytes,...X===void 0?{}:{quotaCheckedAt:X},...typeof K==="string"?{wireAccountId:K}:{}}}return Object.keys(J).length>0?J:void 0}function T(){return process.env[Oj]||a}var Q={main:{quota:null,killed:!1},fallbacks:[],activeId:void 0,route:"main",lastUpdated:0};function x(j){if(j===null||typeof j!=="object"||Array.isArray(j))return Q;let J=j,Z=J.main,$;if(Z!==null&&typeof Z==="object"&&!Array.isArray(Z)){let Y=Z;$={quota:"quota"in Y?Y.quota:null,killed:typeof Y.killed==="boolean"?Y.killed:!1,...typeof Y.mainAccountId==="string"?{mainAccountId:Y.mainAccountId}:{},...typeof Y.quotaBackedOff==="boolean"?{quotaBackedOff:Y.quotaBackedOff}:{},...typeof Y.quotaBackoffUntil==="number"?{quotaBackoffUntil:Y.quotaBackoffUntil}:{},...typeof Y.refreshBackedOff==="boolean"?{refreshBackedOff:Y.refreshBackedOff}:{},...typeof Y.refreshBackoffUntil==="number"?{refreshBackoffUntil:Y.refreshBackoffUntil}:{},...y(Y.resetCredits)}}else $={quota:null,killed:!1};let V=J.fallbacks,X=Array.isArray(V)?V.filter((Y)=>Y!==null&&typeof Y==="object"&&!Array.isArray(Y)&&typeof Y.id==="string").map((Y)=>({id:Y.id,label:typeof Y.label==="string"?Y.label:void 0,...typeof Y.accountId==="string"?{accountId:Y.accountId}:{},quota:"quota"in Y?Y.quota:null,killed:typeof Y.killed==="boolean"?Y.killed:!1,enabled:typeof Y.enabled==="boolean"?Y.enabled:!0,...y(Y.resetCredits)})):[],K=typeof J.activeId==="string"?J.activeId:void 0,G=typeof J.route==="string"?J.route:Q.route,L=typeof J.lastUpdated==="number"?J.lastUpdated:0,z=typeof J.planType==="string"?J.planType:void 0,O=typeof J.credits==="number"?J.credits:void 0,D=Nj(J.activeRouting),B=_j(J.stickyAssignments);return{main:$,fallbacks:X,activeId:K,route:G,lastUpdated:L,...D!==void 0?{activeRouting:D}:{},...B!==void 0?{stickyAssignments:B}:{},...z!==void 0?{planType:z}:{},...O!==void 0?{credits:O}:{}}}async function wj(j=T()){try{let J=await c(j,"utf8");return x(JSON.parse(J))}catch{return Q}}var Pj=3600000,f=128;function s(j,J,Z=Date.now()){if(!(j.updatedAt>=Z-Pj&&j.updatedAt<=Z))return!1;if(J===void 0)return!0;return j.activeId==="main"||J.some((V)=>V.enabled!==!1&&V.killed!==!0&&V.id===j.activeId)}function Fj(j,J=Date.now()){let Z;for(let $ of r){let V=j?.[$];if(typeof V?.resetsAt!=="string"||!Number.isFinite(V.usedPercent)||V.usedPercent<100)continue;let X=Date.parse(V.resetsAt);if(!Number.isFinite(X)||X<=J)continue;if(!Z||X<Z.resetAtMs)Z={resetsAt:V.resetsAt,resetAtMs:X}}return Z}function _(j,J=Date.now()){return Fj(j,J)!==void 0}function Rj(j,J,Z=Date.now()){if(!J||j.route!=="sticky-balanced")return;let $=j.stickyAssignments?.[R(J)];if(!$||$.lastSeenAt<Z-b)return;if($.accountId==="main")return j.main?.killed||_(j.main?.quota,Z)?void 0:"main";let V=j.fallbacks?.find((X)=>X.id===$.accountId);if(!V||V.enabled===!1||V.killed===!0||_(V.quota,Z))return;return V.id}function mj(j,J,Z=Date.now()){if(!J)return{activeId:j.activeId??"main",route:j.route};let $=J?j.activeRouting?.[J]:void 0,V=$?.activeId==="main"?j.main.quota:j.fallbacks.find((L)=>L.id===$?.activeId)?.quota;if($&&s($,j.fallbacks,Z)&&!_(V,Z))return{activeId:$.activeId,route:$.route};let X=Rj(j,J,Z);if(X)return{activeId:X,route:j.route};let K=j.fallbacks.filter((L)=>L.enabled&&!L.killed),G=K.find((L)=>!_(L.quota,Z))??K[0];return{activeId:j.route==="fallback-first"&&G?G.id:"main",route:j.route}}function n(j,J,Z=Date.now(),$){if(!j)return;let V=Object.entries(j).filter(([K,G])=>K!==$&&s(G,J,Z)),X=V.length<=f?V:V.sort((K,G)=>G[1].updatedAt-K[1].updatedAt).slice(0,f);return X.length>0?Object.fromEntries(X):void 0}function W(j,J,Z=Date.now(),$){if(!j)return;let V=0,X=0,K=0,G=[];for(let[z,O]of Object.entries(j)){if(z===$){K+=1;continue}if(O.lastSeenAt<Z-b){X+=1;continue}if(J!==void 0&&!J.has(O.accountId)){V+=1;continue}G.push([z,O])}let L=V+X+K;if(L>0)M.debug("pruned sticky assignments",{pid:process.pid,removed:L,reasons:{"account-not-in-roster":V,expired:X,"explicit-removal":K}});return G.length>0?Object.fromEntries(G):void 0}function Wj(j,J){let Z=Object.keys(j).length-Uj;if(Z<=0)return j;let $=new Set(Object.entries(j).filter(([V])=>V!==J).sort(([V,X],[K,G])=>X.lastSeenAt-G.lastSeenAt||V.localeCompare(K)).slice(0,Z).map(([V])=>V));return Object.fromEntries(Object.entries(j).filter(([V])=>!$.has(V)))}function Ej(j,J){if(j===J)return!0;if(!j||!J)return!1;let Z=Object.entries(j);if(Z.length!==Object.keys(J).length)return!1;return Z.every(([$,V])=>Object.is(J[$],V))}function k(j,J,Z,$){return j!==void 0&&J.has(j.accountId)&&!Z.has(j.accountId)&&j.lastSeenAt>=$-b}function A(j,J,Z,$){return J>j.inputBytes||Z-j.lastSeenAt>=i||j.wireAccountId===void 0&&$!==void 0}function p(j,J){return typeof j.wireAccountId==="string"&&typeof J==="string"&&j.wireAccountId!==J}function Cj(j){let J=new Map(j),Z={get size(){return J.size},has:($)=>J.has($),get:($)=>J.get($),entries:()=>J.entries(),keys:()=>J.keys(),values:()=>J.values(),forEach:($,V)=>{J.forEach((X,K)=>{$.call(V,X,K,Z)})},[Symbol.iterator]:()=>J[Symbol.iterator]()};return Object.freeze(Z)}function Hj(j,J,Z){let $=new Map;for(let[V,X]of Object.entries(j??{})){if(V===Z)continue;if(X.quotaCheckedAt!==J[X.accountId])continue;$.set(X.accountId,($.get(X.accountId)??0)+X.inputBytes)}return Cj($)}function v(j){if(j===void 0)return;return new Set(["main",...j.filter((J)=>J.enabled!==!1&&J.killed!==!0).map((J)=>J.id)])}var C=Promise.resolve(),qj=3,Mj=1e4,bj=15000;function U(j){let J=C.then(j);return C=J.catch(()=>{}),J}function gj(j,J=T()){return U(()=>q(j,J))}async function t(j){try{return e(await H(j))}catch{return Q}}async function H(j){try{return await c(j,"utf8")}catch(J){if(J.code==="ENOENT")return"";throw J}}function e(j){if(j==="")return Q;try{return x(JSON.parse(j))}catch{return Q}}async function xj(j){await jj(j);let J=Date.now()+bj;while(Date.now()<=J){let Z=await l({name:"sidebar-write",path:j,ttlMs:Mj,renew:!0});if(Z)return Z;await new Promise(($)=>setTimeout($,10))}throw Error("Timed out waiting for the sidebar state write lock")}async function jj(j){let J=Dj(j);if(await Kj(J,{recursive:!0,mode:448}),j!==a)return;await Xj(J,448).catch((Z)=>{M.warn("sidebar directory permission remediation failed",{pid:process.pid,error:Z instanceof Error?Z.message:String(Z)})})}async function N(j,J,Z){let $=await xj(j);try{for(let K=0;K<qj;K+=1){let G=await H(j),L=J(e(G));if(!L)return;if(K===0)await Z?.beforeRecheck?.();if(await H(j)!==G)continue;await q(L,j);return}let V=await t(j),X=J(V);if(X)await q(X,j)}finally{await $.release()}}function P(j){let J;for(let Z of[j?.primary?.checkedAt,j?.secondary?.checkedAt,j?.checkedAt])if(typeof Z==="number"&&Number.isFinite(Z))J=J===void 0?Z:Math.max(J,Z);return J}function h(j,J){let Z=P(j),$=P(J);if($!==void 0&&(Z===void 0||$>Z))return J;return j}function w(j,J){return j!==void 0&&J!==void 0&&j===J}function F(j,J){let Z=j?.checkedAt;if(typeof Z==="number"&&Number.isFinite(Z))return Z;if(typeof J==="number"&&Number.isFinite(J))return J;return}function m(j,J,Z,$,V){if(j&&J){let X=F(j,$),K=F(J,V);if(K!==void 0&&(X===void 0||K>X))return J;return j}return Z?J:j}function g(j,J){if(!j)return J;if(!J)return j;let Z=P(j),$=P(J),V=$!==void 0&&(Z===void 0||$>Z),X=m(j.primary,J.primary,V,j.checkedAt,J.checkedAt),K=m(j.secondary,J.secondary,V,j.checkedAt,J.checkedAt),G;for(let L of[F(X),F(K)])if(L!==void 0)G=G===void 0?L:Math.max(G,L);return{...j,primary:X,secondary:K,checkedAt:G??j.checkedAt}}function dj(j,J=T(),Z){return U(async()=>{await N(J,($)=>{let V=new Map($.fallbacks.map((z)=>[z.id,z])),X=w(j.main.mainAccountId,$.main.mainAccountId),K=X?g(j.main.quota,$.main.quota):h(j.main.quota,$.main.quota),G=Date.now(),L=W($.stickyAssignments,v(j.fallbacks),G);return{...$,...j,main:{...j.main,quota:K,mainAccountId:X?j.main.mainAccountId:K===$.main.quota&&K!==j.main.quota?$.main.mainAccountId:j.main.mainAccountId},fallbacks:j.fallbacks.map((z)=>{let O=V.get(z.id),D=w(z.accountId,O?.accountId),B=D?g(z.quota,O?.quota??null):h(z.quota,O?.quota??null);return{...z,quota:B,accountId:D?z.accountId:B===O?.quota&&B!==z.quota?O?.accountId:z.accountId}}),activeId:$.activeId,activeRouting:$.activeRouting,stickyAssignments:L,lastUpdated:Math.max(G,$.lastUpdated+1)}},Z)})}function lj(j,J,Z=T(),$){return U(async()=>{await N(Z,(V)=>{let X=n({...V.activeRouting,[j.sessionId]:{activeId:j.activeId,route:j.route,updatedAt:j.updatedAt}},J,Date.now()),K=W(V.stickyAssignments,v(J),Date.now());return{...V,activeId:j.activeId,route:j.route,activeRouting:X,stickyAssignments:K,lastUpdated:Math.max(Date.now(),V.lastUpdated+1)}},$)})}function rj(j,J=T()){return U(async()=>{await N(J,(Z)=>({...Z,activeId:j.activeId,route:j.route,lastUpdated:Math.max(Date.now(),Z.lastUpdated+1)}))})}function uj(j,J,Z=T(),$){return U(async()=>{await N(Z,(V)=>{let X=Date.now(),K=n(V.activeRouting,J,X,j),G=W(V.stickyAssignments,v(J),X,R(j));return{...V,activeRouting:K,stickyAssignments:G,lastUpdated:Math.max(Date.now(),V.lastUpdated+1)}},$)})}async function cj(j,J=T(),Z){let $=R(j.sessionId),V=new Set(j.validPinnedAccountIds),X=new Set(j.excludeAccountIds),K=(await t(J)).stickyAssignments?.[$];if(k(K,V,X,j.now)&&!p(K,j.wireAccountIdByAccount?.[K.accountId])&&!A(K,j.requestBytes,j.now,j.wireAccountIdByAccount?.[K.accountId]))return K;let G;return await U(async()=>{await N(J,(L)=>{let z=W(L.stickyAssignments,V,j.now),O=!Ej(L.stickyAssignments,z),D=z?.[$],B=D!==void 0&&p(D,j.wireAccountIdByAccount?.[D.accountId]);if(k(D,V,X,j.now)&&!B){let I=A(D,j.requestBytes,j.now,j.wireAccountIdByAccount?.[D.accountId]),S=I?{...D,inputBytes:Math.max(D.inputBytes,j.requestBytes),...D.wireAccountId===void 0&&j.wireAccountIdByAccount?.[D.accountId]!==void 0?{wireAccountId:j.wireAccountIdByAccount?.[D.accountId]}:{},...j.now-D.lastSeenAt>=i?{lastSeenAt:j.now}:{}}:D;if(G=S,!O&&!I)return;return{...L,stickyAssignments:{...z,[$]:S},lastUpdated:Math.max(j.now,L.lastUpdated+1)}}let Y=j.choose(Hj(z,j.quotaCheckedAtByAccount,B?$:void 0));if(!Y){if(G=void 0,!O)return;return{...L,stickyAssignments:z,lastUpdated:Math.max(j.now,L.lastUpdated+1)}}return G={accountId:Y.accountId,assignedAt:j.now,lastSeenAt:j.now,inputBytes:j.requestBytes,...Y.quotaCheckedAt===void 0?{}:{quotaCheckedAt:Y.quotaCheckedAt},...j.wireAccountIdByAccount?.[Y.accountId]===void 0?{}:{wireAccountId:j.wireAccountIdByAccount?.[Y.accountId]}},{...L,stickyAssignments:Wj({...z,[$]:G},$),lastUpdated:Math.max(j.now,L.lastUpdated+1)}},Z)}),G}async function oj(j,J=T()){let Z=R(j),$=!1;return await U(async()=>{await N(J,(V)=>{let X=V.stickyAssignments;if(X?.[Z]===void 0){$=!1;return}$=!0;let{[Z]:K,...G}=X;return{...V,...Object.keys(G).length>0?{stickyAssignments:G}:{stickyAssignments:void 0},lastUpdated:Math.max(Date.now(),V.lastUpdated+1)}})}),$}async function q(j,J){let Z=`${J}.${Vj()}.tmp`;try{await jj(J),await Lj(Z,JSON.stringify(x(j)),{encoding:"utf8",mode:384}),await Yj(Z,J)}catch($){throw await Gj(Z,{force:!0}).catch(()=>{}),M.warn("sidebar write failed",{pid:process.pid,error:$ instanceof Error?$.message:String($)}),$}}function aj(){return C}function ij(j){let J=j.activeId;if(J&&J!=="main"){let Z=j.fallbacks.find(($)=>$.enabled&&$.id===J);if(Z)return{id:Z.id,name:Z.label??Z.id,quota:Z.quota,killed:Z.killed}}return{id:"main",name:"main",quota:j.main.quota,killed:j.main.killed}}function sj(j){let J=j?.primary?.usedPercent??null,Z=j?.secondary?.usedPercent??null,$=Zj(j);return{primaryUsedPercent:J,secondaryUsedPercent:Z,text:$.length===0?null:$.map(({label:V,window:X})=>`${V}: ${Math.round(X.usedPercent)}%`).join(" ")}}var vj=300000,Ij=0.01,Sj=1;function nj(j,J,Z){if(!j.resetsAt)return null;let $=new Date(j.resetsAt).getTime();if(!Number.isFinite($))return null;let V=$-J,X=Z-V;if(X<vj)return null;if(X<J*Ij)return null;if(X>=J)return null;let K=j.usedPercent,G=Math.min(Math.max(X/J*100,0),100),L=K-G,z=Math.abs(L)<Sj?"on-pace":L>0?"deficit":"reserve",O=null;if(K>0){let D=X*100/K,B=V+D;if(B<$)O=new Date(B).toISOString()}return{pacePercent:G,deltaPercent:L,state:z,runsOutAt:O}}
2
- export{Jj as T,Zj as U,b as V,Uj as W,R as X,T as Y,Q as Z,x as _,wj as $,Pj as aa,f as ba,s as ca,Fj as da,_ as ea,Rj as fa,mj as ga,n as ha,W as ia,gj as ja,dj as ka,lj as la,rj as ma,uj as na,cj as oa,oj as pa,aj as qa,ij as ra,sj as sa,nj as ta};
package/dist/logger.d.ts DELETED
@@ -1,22 +0,0 @@
1
- type Level = 'error' | 'warn' | 'info' | 'debug' | 'trace';
2
- export declare function setLogLevel(l: Level | undefined): void;
3
- export declare function redact(value: unknown): unknown;
4
- /**
5
- * Scrub credential-shaped strings without redacting by key name.
6
- *
7
- * For regions where a key names a piece of data rather than holding a secret —
8
- * a JSON Schema property called `api_key` describes an argument, it does not
9
- * carry one — replacing the node by name destroys the structure while removing
10
- * nothing sensitive. A credential pasted into a description is still caught,
11
- * because that is a string.
12
- */
13
- export declare function redactStrings(value: unknown): unknown;
14
- export declare function createLogger(channel: string): {
15
- error: (m: string, d?: unknown) => void;
16
- warn: (m: string, d?: unknown) => void;
17
- info: (m: string, d?: unknown) => void;
18
- debug: (m: string, d?: unknown) => void;
19
- trace: (m: string, d?: unknown) => void;
20
- };
21
- export declare function flushForTest(): Promise<void>;
22
- export {};
@@ -1,29 +0,0 @@
1
- type CacheCost = {
2
- read: number;
3
- write: number;
4
- };
5
- type TierCost = {
6
- input: number;
7
- output: number;
8
- cache: CacheCost;
9
- tier: {
10
- type: 'context';
11
- size: number;
12
- };
13
- };
14
- export type ModelCost = {
15
- input: number;
16
- output: number;
17
- cache: CacheCost;
18
- tiers?: TierCost[];
19
- experimentalOver200K?: {
20
- input: number;
21
- output: number;
22
- cache: CacheCost;
23
- };
24
- };
25
- export declare function toSdkCost(raw: unknown): ModelCost | null;
26
- export declare function loadModelsDevCosts(): Promise<Record<string, ModelCost> | null>;
27
- /** Test-only: drop the memoized catalog so a later load re-reads its source. */
28
- export declare function resetModelCostsForTest(): void;
29
- export {};
@@ -1,19 +0,0 @@
1
- /**
2
- * Resolve prompt context for synthetic OpenCode user messages.
3
- *
4
- * OpenCode records even ignored/noReply prompt messages as user messages. If a
5
- * plugin sends one (e.g. a hidden /openai-* command reply) without the previous
6
- * model/variant, OpenCode's next real prompt can inherit the synthetic message's
7
- * default model/variant and silently change the model, usage, or cache
8
- * attribution. Resolve the most recent assistant context and pass it through on
9
- * hidden command replies so the user's selected model and reasoning variant are kept.
10
- */
11
- export interface ResolvedPromptContext {
12
- agent?: string;
13
- model?: {
14
- providerID: string;
15
- modelID: string;
16
- };
17
- variant?: string;
18
- }
19
- export declare function resolvePromptContext(client: unknown, sessionId: string): Promise<ResolvedPromptContext | null>;
@@ -1 +0,0 @@
1
- import{c as a,d as b,e as c,f as d,g as e}from"./index-87145jkw.js";import"./index-zxqb5ydj.js";export{a as toResetIso,d as normalizeWsFrame,e as normalizeWham,b as normalizeQuotaHeaders,c as isCompleteQuotaHeaderFrame};
@@ -1,43 +0,0 @@
1
- import type { OAuthQuotaSnapshot } from './core/accounts.ts';
2
- export declare function toResetIso(raw: string | number | undefined): string | undefined;
3
- export declare function normalizeQuotaHeaders(h: Headers): OAuthQuotaSnapshot;
4
- /**
5
- * A complete frame has at least one syntactically valid used-percent header
6
- * and no malformed used-percent headers. Explicit retired-slot markers count
7
- * as valid even though normalization omits them from the snapshot.
8
- */
9
- export declare function isCompleteQuotaHeaderFrame(h: Headers): boolean;
10
- interface WsRateLimitWindow {
11
- used_percent: number;
12
- window_minutes: number;
13
- reset_at?: string | number;
14
- }
15
- interface WsRateLimits {
16
- primary?: WsRateLimitWindow | null;
17
- secondary?: WsRateLimitWindow | null;
18
- }
19
- interface WsRateLimitsFrame {
20
- type: string;
21
- rate_limits: WsRateLimits;
22
- plan_type?: string;
23
- }
24
- export declare function normalizeWsFrame(event: WsRateLimitsFrame): OAuthQuotaSnapshot;
25
- interface WhamRateLimitWindow {
26
- used_percent: number;
27
- limit_window_seconds: number;
28
- reset_at?: string | number;
29
- }
30
- interface WhamRateLimits {
31
- primary_window?: WhamRateLimitWindow | null;
32
- secondary_window?: WhamRateLimitWindow | null;
33
- }
34
- interface WhamUsageResponse {
35
- plan_type?: string;
36
- rate_limit: WhamRateLimits;
37
- rate_limit_reset_credits?: {
38
- available_count?: number;
39
- applicable_available_count?: number;
40
- } | null;
41
- }
42
- export declare function normalizeWham(json: WhamUsageResponse): OAuthQuotaSnapshot;
43
- export {};
@@ -1,40 +0,0 @@
1
- type Listener = (event: unknown) => void;
2
- export declare class RawWebSocket {
3
- url: string;
4
- readyState: number;
5
- private socket;
6
- private readonly sessionID;
7
- private listeners;
8
- private rxBuffer;
9
- private handshakeDone;
10
- private upgradeFailureEmitted;
11
- private expectedAccept;
12
- private fragOpcode;
13
- private fragChunks;
14
- private writeQueue;
15
- constructor(url: string, headers: Record<string, string>, options?: {
16
- sessionID?: string;
17
- });
18
- addEventListener(type: string, fn: Listener, _opts?: {
19
- once?: boolean;
20
- }): void;
21
- removeEventListener(type: string, fn: Listener): void;
22
- /** Close code and reason from the peer's close frame, if one arrived. */
23
- private peerClose;
24
- private closeEmitted;
25
- /** Emit at most one close event, so the first reported code is the one kept. */
26
- private emitClose;
27
- private emit;
28
- private connect;
29
- private onData;
30
- private emitRejectedUpgrade;
31
- private drainFrames;
32
- private handleFrame;
33
- send(data: string): void;
34
- private writeFrame;
35
- private enqueueWrite;
36
- private flushWrites;
37
- close(): void;
38
- private log;
39
- }
40
- export {};