@cortexkit/opencode-openai-auth 0.7.2 → 0.9.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 (118) hide show
  1. package/README.md +9 -5
  2. package/dist/index-301y4qa1.js +2 -0
  3. package/dist/index-338z7171.js +211 -0
  4. package/dist/index-5y4vzdf8.js +2 -0
  5. package/dist/{index-zxqb5ydj.js → index-9ehhb051.js} +1 -1
  6. package/dist/{index-zg1x8sty.js → index-jwn4r3sw.js} +1 -1
  7. package/dist/{index-9jpc8yct.js → index-sdt2d2ra.js} +1 -1
  8. package/dist/index-w42s0g6m.js +2 -0
  9. package/dist/index.d.ts +213 -36
  10. package/dist/index.js +59 -154
  11. package/dist/internal-Y7QNVDJT.d.ts +908 -0
  12. package/dist/quota-normalize-3qffywcm.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 +7 -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-B98sERYt.d.ts +219 -0
  21. package/dist/sidebar-state.d.ts +2 -171
  22. package/dist/sidebar-state.js +1 -1
  23. package/dist/{token-bvp0y166.js → token-9823y0pc.js} +1 -1
  24. package/dist/token-util-ypgz7rge.js +1 -0
  25. package/dist/tui-preferences.d.ts +27 -26
  26. package/dist/tui-preferences.js +1 -1
  27. package/dist/tui.d.ts +42 -19
  28. package/package.json +8 -14
  29. package/src/tui/entry.mjs +2 -2
  30. package/src/tui-compiled/{core/account-paths.ts → raw/core-account-paths.ts} +29 -18
  31. package/src/tui-compiled/raw/core-custody-state.ts +243 -0
  32. package/src/tui-compiled/raw/logger.ts +53 -0
  33. package/src/tui-compiled/{rpc/port-file.ts → raw/rpc-port-file.ts} +1 -1
  34. package/src/tui-compiled/raw/rpc-protocol.ts +12 -0
  35. package/src/{rpc/rpc-client.ts → tui-compiled/raw/rpc-rpc-client.ts} +2 -2
  36. package/src/{sidebar-state.ts → tui-compiled/raw/sidebar-state.ts} +142 -13
  37. package/src/{tui/command-dialogs.tsx → tui-compiled/raw/tui-command-dialogs.tsx} +94 -44
  38. package/src/{tui.tsx → tui-compiled/raw/tui.tsx} +149 -28
  39. package/src/{core/account-paths.ts → tui-compiled/runtime/core-account-paths.ts} +29 -18
  40. package/src/tui-compiled/runtime/core-custody-state.ts +243 -0
  41. package/src/tui-compiled/runtime/logger.ts +53 -0
  42. package/src/{rpc/port-file.ts → tui-compiled/runtime/rpc-port-file.ts} +1 -1
  43. package/src/tui-compiled/runtime/rpc-protocol.ts +12 -0
  44. package/src/tui-compiled/{rpc/rpc-client.ts → runtime/rpc-rpc-client.ts} +2 -2
  45. package/src/tui-compiled/{sidebar-state.ts → runtime/sidebar-state.ts} +142 -13
  46. package/src/tui-compiled/{tui/command-dialogs.tsx → runtime/tui-command-dialogs.tsx} +73 -37
  47. package/src/tui-compiled/{tui.tsx → runtime/tui.tsx} +251 -153
  48. package/src/tui-compiled/shared/internal.ts +6 -0
  49. package/src/{logger.ts → tui-compiled/shared/logger.ts} +91 -23
  50. package/src/tui-compiled/shared/paths.ts +33 -0
  51. package/src/{core → tui-compiled/shared}/refresh-file-lock.ts +7 -4
  52. package/dist/cli.d.ts +0 -2
  53. package/dist/cli.js +0 -15
  54. package/dist/codex-http.d.ts +0 -3
  55. package/dist/commands.d.ts +0 -88
  56. package/dist/config.d.ts +0 -47
  57. package/dist/core/account-paths.d.ts +0 -25
  58. package/dist/core/accounts.d.ts +0 -330
  59. package/dist/core/atomic-write.d.ts +0 -1
  60. package/dist/core/background-quota-refresh.d.ts +0 -46
  61. package/dist/core/backoff.d.ts +0 -53
  62. package/dist/core/cachekeep.d.ts +0 -118
  63. package/dist/core/oauth.d.ts +0 -138
  64. package/dist/core/provider.d.ts +0 -70
  65. package/dist/core/quota-manager.d.ts +0 -192
  66. package/dist/core/refresh-all-quota.d.ts +0 -86
  67. package/dist/core/refresh-file-lock.d.ts +0 -12
  68. package/dist/core/reset-credits.d.ts +0 -116
  69. package/dist/core/sticky-routing.d.ts +0 -43
  70. package/dist/dump.d.ts +0 -20
  71. package/dist/hosted-web-search.d.ts +0 -5
  72. package/dist/index-87145jkw.js +0 -2
  73. package/dist/index-8f1200qx.js +0 -6
  74. package/dist/index-cfjed1st.js +0 -89
  75. package/dist/index-nrvjr97q.js +0 -3
  76. package/dist/index-qaggaze1.js +0 -2
  77. package/dist/index-sdcpzbnk.js +0 -2
  78. package/dist/logger.d.ts +0 -22
  79. package/dist/model-costs.d.ts +0 -29
  80. package/dist/prompt-context.d.ts +0 -19
  81. package/dist/quota-normalize-dvwtmy7f.js +0 -1
  82. package/dist/quota-normalize.d.ts +0 -43
  83. package/dist/raw-ws-bun.d.ts +0 -40
  84. package/dist/raw-ws-node.d.ts +0 -37
  85. package/dist/raw-ws-upgrade.d.ts +0 -2
  86. package/dist/raw-ws.d.ts +0 -3
  87. package/dist/response-stream-error.d.ts +0 -12
  88. package/dist/rpc/notifications.d.ts +0 -5
  89. package/dist/rpc/rpc-server.d.ts +0 -17
  90. package/dist/token-util-jcj7k7pa.js +0 -1
  91. package/dist/tui/command-dialogs.d.ts +0 -21
  92. package/dist/util/error.d.ts +0 -1
  93. package/dist/util/open-url.d.ts +0 -6
  94. package/dist/util/proxy-env.d.ts +0 -4
  95. package/dist/util/record.d.ts +0 -1
  96. package/dist/util/stable-json.d.ts +0 -1
  97. package/dist/util/uuid-v7.d.ts +0 -1
  98. package/dist/version.d.ts +0 -1
  99. package/dist/ws-pool.d.ts +0 -57
  100. package/dist/ws.d.ts +0 -71
  101. package/src/rpc/notifications.ts +0 -54
  102. package/src/rpc/protocol.ts +0 -33
  103. package/src/rpc/rpc-server.ts +0 -172
  104. package/src/tui-compiled/core/refresh-file-lock.ts +0 -381
  105. package/src/tui-compiled/logger.ts +0 -196
  106. package/src/tui-compiled/rpc/protocol.ts +0 -33
  107. package/src/util/error.ts +0 -9
  108. package/src/util/open-url.ts +0 -30
  109. package/src/util/proxy-env.ts +0 -42
  110. package/src/util/record.ts +0 -3
  111. package/src/util/stable-json.ts +0 -15
  112. package/src/util/uuid-v7.ts +0 -18
  113. /package/src/{rpc/rpc-dir.ts → tui-compiled/raw/rpc-rpc-dir.ts} +0 -0
  114. /package/src/tui-compiled/{tui-preferences.ts → raw/tui-preferences.ts} +0 -0
  115. /package/src/tui-compiled/{rpc/rpc-dir.ts → runtime/rpc-rpc-dir.ts} +0 -0
  116. /package/src/{tui-preferences.ts → tui-compiled/runtime/tui-preferences.ts} +0 -0
  117. /package/src/tui-compiled/{util → shared/util}/error.ts +0 -0
  118. /package/src/tui-compiled/{util → shared/util}/open-url.ts +0 -0
@@ -1,330 +0,0 @@
1
- import { ACCOUNT_FILE_NAME, ACCOUNT_STATE_FILE_NAME, deriveStatePath, getAccountStatePath, getAccountStoragePath } from './account-paths';
2
- import type { ProviderQuotaFn, ProviderRefreshFn, QuotaWindowName } from './provider.ts';
3
- import { PRIMARY, SECONDARY } from './provider.ts';
4
- export { ACCOUNT_FILE_NAME, ACCOUNT_STATE_FILE_NAME, deriveStatePath, getAccountStatePath, getAccountStoragePath, };
5
- export type { QuotaWindowName };
6
- export { PRIMARY, SECONDARY };
7
- export type AccountQuotaWindow = {
8
- usedPercent: number;
9
- remainingPercent: number;
10
- resetsAt?: string;
11
- checkedAt: number;
12
- windowMinutes?: number;
13
- };
14
- export interface OAuthQuotaSnapshot {
15
- primary?: AccountQuotaWindow;
16
- secondary?: AccountQuotaWindow;
17
- resetCreditsAvailable?: number;
18
- resetCreditsApplicable?: number;
19
- }
20
- export type AccountBase = {
21
- id: string;
22
- label?: string;
23
- enabled?: boolean;
24
- addedAt?: number;
25
- lastUsed?: number;
26
- /** Stable ChatGPT account identifier extracted from the OAuth token claims. */
27
- accountId?: string;
28
- };
29
- export type AccountOperationError = {
30
- message: string;
31
- checkedAt: number;
32
- nextRetryAt?: number;
33
- retryCount?: number;
34
- tokenHash?: string;
35
- };
36
- export type OAuthAccount = AccountBase & {
37
- type: 'oauth';
38
- access?: string;
39
- refresh: string;
40
- expires?: number;
41
- lastRefreshedAt?: number;
42
- lastRefreshError?: AccountOperationError;
43
- lastQuotaRefreshError?: AccountOperationError;
44
- quota?: OAuthQuotaSnapshot;
45
- };
46
- export type ApiKeyAccount = AccountBase & {
47
- type: 'api';
48
- apiKey?: string;
49
- baseURL: string;
50
- authHeader?: 'authorization-bearer' | 'x-api-key';
51
- };
52
- export type FallbackAccount = OAuthAccount | ApiKeyAccount;
53
- export declare function isOAuthAccount(account: FallbackAccount): account is OAuthAccount;
54
- export declare function isApiKeyAccount(account: FallbackAccount): account is ApiKeyAccount;
55
- export declare function isValidApiBaseURL(value: string | undefined): boolean;
56
- export type RoutingMode = 'main-first' | 'fallback-first' | 'sticky-balanced';
57
- export type KillswitchThresholds = Partial<Record<QuotaWindowName | '5h' | '1w', number>>;
58
- export type KillswitchConfig = {
59
- enabled?: boolean;
60
- main?: KillswitchThresholds;
61
- accounts?: Record<string, KillswitchThresholds>;
62
- };
63
- export interface ResetInFlight {
64
- redeemRequestId: string;
65
- creditId: string;
66
- startedAt: number;
67
- }
68
- export interface ResetLastOutcome {
69
- code: string;
70
- at: number;
71
- previousOutcome?: {
72
- code: string;
73
- at: number;
74
- };
75
- }
76
- export interface ResetAccountState {
77
- inFlight?: ResetInFlight | Record<string, unknown>;
78
- lastOutcome?: ResetLastOutcome;
79
- cooldownUntil?: number;
80
- }
81
- export type ResetStateByAccount = Record<string, ResetAccountState>;
82
- export type AccountStorage = {
83
- version: 1;
84
- main?: {
85
- type: 'opencode';
86
- provider: 'openai';
87
- };
88
- routing?: {
89
- mode?: RoutingMode;
90
- };
91
- fallbackOn?: number[];
92
- refresh?: {
93
- enabled?: boolean;
94
- intervalMinutes?: number;
95
- refreshBeforeExpiryMinutes?: number;
96
- mainLastRefreshError?: AccountOperationError;
97
- mainRefreshLeaseId?: string;
98
- mainRefreshLeaseUntil?: number;
99
- mainRefreshLeaseTokenHash?: string;
100
- };
101
- quota?: {
102
- enabled?: boolean;
103
- checkIntervalMinutes?: number;
104
- refreshEveryNRequests?: number;
105
- minimumRemaining?: Partial<Record<QuotaWindowName | '5h' | '1w', number>>;
106
- failClosedOnUnknownQuota?: boolean;
107
- showToasts?: boolean;
108
- mainQuota?: OAuthQuotaSnapshot;
109
- mainQuotaCheckedAt?: number;
110
- mainQuotaToken?: string;
111
- mainLastQuotaApiError?: AccountOperationError;
112
- };
113
- reset?: ResetStateByAccount;
114
- dump?: {
115
- enabled?: boolean;
116
- };
117
- costZeroing?: {
118
- enabled?: boolean;
119
- };
120
- killswitch?: KillswitchConfig;
121
- logging?: {
122
- level?: string;
123
- };
124
- cachekeep?: {
125
- enabled?: boolean;
126
- subagents?: boolean;
127
- sustain?: boolean;
128
- /** Clock-hour window start (0-23, inclusive) — keeps cachekeep idle warming
129
- * inside `[startHour, endHour)` local hours. Omit to warm unconditionally. */
130
- startHour?: number;
131
- /** Clock-hour window end (0-23, exclusive) — must differ from startHour
132
- * to be honored; an unset or equal hour falls back to "always warm". */
133
- endHour?: number;
134
- };
135
- /** Stable ChatGPT account identifier of the main account (extracted from OAuth token). */
136
- mainAccountId?: string;
137
- accounts: FallbackAccount[];
138
- };
139
- export declare function isCostZeroingEnabled(storage: Pick<AccountStorage, 'costZeroing'>): boolean;
140
- export type AccountRuntimeEntry = Partial<Pick<OAuthAccount, 'access' | 'refresh' | 'expires' | 'lastUsed' | 'lastRefreshedAt' | 'lastRefreshError' | 'lastQuotaRefreshError' | 'quota'> & Pick<ApiKeyAccount, 'apiKey' | 'lastUsed'>>;
141
- export type AccountRuntimeState = {
142
- version: 1;
143
- main?: {
144
- quota?: OAuthQuotaSnapshot;
145
- quotaCheckedAt?: number;
146
- quotaToken?: string;
147
- lastQuotaApiError?: AccountOperationError;
148
- lastRefreshError?: AccountOperationError;
149
- refreshLeaseId?: string;
150
- refreshLeaseUntil?: number;
151
- refreshLeaseTokenHash?: string;
152
- };
153
- accounts?: Record<string, AccountRuntimeEntry>;
154
- };
155
- export type AccountStateSaveScope = {
156
- mainQuota?: boolean;
157
- mainRefresh?: boolean;
158
- accounts?: true | string[];
159
- };
160
- export type AccountManagerOptions = {
161
- now?: () => number;
162
- fetchImpl?: typeof fetch;
163
- configPath?: string;
164
- onFallbackStorageChanged?: () => void;
165
- /** Provider token-refresh function (constructor-injected). */
166
- refreshFn?: ProviderRefreshFn;
167
- /** Provider quota-fetch function (constructor-injected, OPTIONAL wham/usage supplement). */
168
- fetchQuotaFn?: ProviderQuotaFn;
169
- /** QuotaManager instance for unified cache (constructor-injected). */
170
- quotaManager?: import('./quota-manager.ts').QuotaManager;
171
- };
172
- export type AccountRefreshError = {
173
- accountId: string;
174
- message: string;
175
- };
176
- export declare class AccountRemovedDuringRefreshError extends Error {
177
- readonly code = "ACCOUNT_REMOVED_DURING_REFRESH";
178
- constructor(accountId: string);
179
- }
180
- export declare const DEFAULT_KILLSWITCH_THRESHOLDS: {
181
- primary: number;
182
- secondary: number;
183
- };
184
- export declare function isSafeResetAccountKey(accountKey: string): boolean;
185
- /**
186
- * The set of account ids present in the CONFIG file (the authoritative account
187
- * roster). Returns null when the config is absent or unreadable/malformed, so
188
- * callers can fall back to non-pruning behavior rather than risk wiping live
189
- * state. The config never holds secrets (see accountConfig), so reading it here
190
- * is safe. Reads are lock-free but the file is written atomically, so a
191
- * concurrent write is seen as either the complete old or complete new file.
192
- *
193
- * Trims and skips blank ids per the rule in collectConfigRosterIds above.
194
- */
195
- export declare function readConfigRosterIds(path: string): Promise<Set<string> | null>;
196
- export declare function loadAccounts(path?: string): Promise<AccountStorage | null>;
197
- export declare function saveAccounts(storage: AccountStorage, path?: string): Promise<void>;
198
- /**
199
- * Read-modify-write the account store atomically under the save lock.
200
- *
201
- * Unlike saveAccounts (which UNION-merges the incoming accounts with the latest
202
- * on-disk set so concurrent ADDS from another process are never lost), this
203
- * reads the freshest state under the lock and writes the mutator's result
204
- * AUTHORITATIVELY — no union. That is required for structural edits (remove,
205
- * reorder): a union cannot express a deletion (the removed id reappears from
206
- * `latest`) or a reordering (the union is seeded latest-first). Because the
207
- * mutator runs against freshly-read state under the lock, an add committed by a
208
- * concurrent process is still visible to it and preserved.
209
- *
210
- * The mutator may edit `current` in place and return it, or return a new
211
- * storage object. Returning undefined means "no change" and still rewrites the
212
- * freshly-read state (a harmless idempotent write).
213
- *
214
- * Load-time drop preservation: if normalizeAccount (called inside
215
- * normalizeStorage) rejects an account whose id IS in the raw config roster,
216
- * the previous behavior would erase that id silently on the next write. This
217
- * function now carries the dropped raw entry through to the written config
218
- * verbatim, so the on-disk state always matches the operator's intent (an
219
- * account they added, even if temporarily un-loadable, stays in their list
220
- * until they deliberately remove it).
221
- *
222
- * Removal seam: when the caller knows they are removing an id (e.g. the CLI
223
- * `remove` command) and that id may be load-dropped — in which case the
224
- * mutator cannot find it in `current.accounts` to splice it — the caller can
225
- * pass `options.allowDrop: [id]`. Ids in `allowDrop` are NOT preserved; the
226
- * mutator's splice still no-ops on a dropped id, but the absence of
227
- * preservation completes the removal end-to-end.
228
- */
229
- export declare function mutateAccounts(mutate: (current: AccountStorage) => AccountStorage | undefined, path?: string, options?: {
230
- allowDrop?: readonly string[];
231
- }): Promise<AccountStorage>;
232
- export declare function saveAccountState(storage: AccountStorage, path?: string, scope?: AccountStateSaveScope): Promise<void>;
233
- export declare function shouldFallbackStatus(status: number, storage: AccountStorage | null): boolean;
234
- export declare function quotaSnapshotPassesPolicy(quota: OAuthQuotaSnapshot | undefined, storage: AccountStorage | null, now?: number): boolean;
235
- export declare function isKillswitchEnabled(storage: AccountStorage | null): boolean;
236
- export declare function getKillswitchThresholdsForAccount(storage: AccountStorage | null, accountId?: string): {
237
- primary: number;
238
- secondary: number;
239
- };
240
- export declare function killswitchPassesPolicy(quota: OAuthQuotaSnapshot | undefined, storage: AccountStorage | null, accountId?: string, now?: number): boolean;
241
- export declare function killswitchRetryAfterSeconds(mainQuota: OAuthQuotaSnapshot | undefined, fallbackAccounts: Array<{
242
- accountId: string;
243
- quota?: OAuthQuotaSnapshot;
244
- }>, now: number, storage: AccountStorage | null): number;
245
- /**
246
- * Migrate an existing single-slot token into the multi-account store.
247
- *
248
- * Reads the existing token via the caller-provided `getAuth` (the ONLY
249
- * read path — there is no `client.auth.get`). If a token exists and the
250
- * config file is NOT yet an account store (content discriminator), seeds
251
- * it as the primary OAuth account.
252
- *
253
- * Idempotent: a second run is a no-op because the content discriminator
254
- * will already match.
255
- *
256
- * Tolerates expired/revoked tokens (migrates them; refresh handles validity).
257
- *
258
- * Guards against first-run races with the same save-lock order used by
259
- * structural account mutations.
260
- */
261
- export declare function migrateIfNeeded(existingToken: {
262
- type: 'oauth';
263
- access: string;
264
- refresh: string;
265
- expires: number;
266
- } | undefined, path?: string): Promise<void>;
267
- export declare function getQuotaCheckIntervalMs(storage: AccountStorage | null): number;
268
- export declare function getRefreshIntervalMs(storage: AccountStorage | null): number;
269
- export declare class FallbackAccountManager {
270
- private readonly now;
271
- private readonly fetchImpl;
272
- private readonly configPath;
273
- private readonly refreshPromises;
274
- private refreshTimer;
275
- private quotaTimer;
276
- readonly quotaManager: import('./quota-manager.ts').QuotaManager | null;
277
- private readonly onFallbackStorageChanged;
278
- private readonly options;
279
- constructor(options?: AccountManagerOptions);
280
- /**
281
- * Seed QuotaManager from persisted account.quota if no cache entry exists
282
- * yet. Prevents unnecessary API calls when the on-disk snapshot is fresh.
283
- */
284
- private seedFallbackQuota;
285
- load(): Promise<AccountStorage | null>;
286
- save(storage: AccountStorage, accountIds?: string[]): Promise<void>;
287
- startBackgroundRefresh(): void;
288
- stopBackgroundRefresh(): void;
289
- getUsableFallbackAccounts(existingStorage?: AccountStorage | null): Promise<OAuthAccount[]>;
290
- /**
291
- * Stamp `lastUsed` on a served account.
292
- *
293
- * This runs on the request path after a response is already in hand, and
294
- * `lastUsed` is telemetry: nothing reads it to make a routing, quota, or
295
- * killswitch decision. The WHOLE operation is therefore best-effort, read
296
- * included — loadAccounts deliberately rethrows anything that is not ENOENT so
297
- * corruption surfaces to callers that must act on it, and a store lock shared
298
- * by every session in the host process can legitimately time out under a burst
299
- * of concurrent turns. Neither may reach this caller: it would discard a
300
- * successful, already-billed provider response to record a timestamp. Losing
301
- * the stamp costs nothing a later turn cannot redo.
302
- *
303
- * Contrast refreshAccount, whose save persists rotated tokens and MUST
304
- * propagate: dropping it silently would strand a refresh and invalidate the
305
- * account's credentials.
306
- */
307
- markUsed(account: FallbackAccount): Promise<void>;
308
- accountPassesQuotaPolicy(account: OAuthAccount, storage: AccountStorage | null): boolean;
309
- /**
310
- * Return the account with its quota overlaid from the unified QuotaManager
311
- * cache (token-bound) when available, so quota-policy decisions use the same
312
- * source of truth as the staleness check. Falls back to the stored
313
- * account.quota when no manager is wired or the cache has no entry.
314
- */
315
- private quotaPolicyAccount;
316
- refreshDueAccounts(): Promise<void>;
317
- refreshQuotaForDueAccounts(): Promise<void>;
318
- refreshQuotaForAllAccounts(options?: {
319
- force?: boolean;
320
- }): Promise<{
321
- storage: AccountStorage | null;
322
- errors: AccountRefreshError[];
323
- }>;
324
- refreshAccount(account: OAuthAccount, storage: AccountStorage, options?: {
325
- force?: boolean;
326
- }): Promise<OAuthAccount>;
327
- private waitForConcurrentFallbackRefresh;
328
- private refreshAccountNow;
329
- refreshAccountQuota(account: OAuthAccount, storage: AccountStorage): Promise<void>;
330
- }
@@ -1 +0,0 @@
1
- export declare function writeJsonAtomic(path: string, value: unknown): Promise<void>;
@@ -1,46 +0,0 @@
1
- import { type RefreshAllQuotaDeps, type RefreshAllQuotaResult } from './refresh-all-quota';
2
- export declare const BACKGROUND_QUOTA_REFRESH_INTERVAL_MS: number;
3
- export declare const BACKGROUND_QUOTA_REFRESH_JITTER_MS = 30000;
4
- export declare const BACKGROUND_QUOTA_FRESHNESS_MS: number;
5
- export declare const BACKGROUND_QUOTA_REFRESH_LOCK_NAME = "bg-quota-refresh";
6
- export declare const BACKGROUND_QUOTA_REFRESH_LOCK_TTL_MS = 120000;
7
- type TimerHandle = ReturnType<typeof setInterval>;
8
- interface BackgroundQuotaRefreshOptions {
9
- setIntervalFn?: (callback: () => void, intervalMs: number) => TimerHandle;
10
- clearIntervalFn?: (timer: TimerHandle) => void;
11
- random?: () => number;
12
- onError?: (error: unknown) => void;
13
- }
14
- type RefreshAllQuotaFn = (deps: RefreshAllQuotaDeps) => Promise<RefreshAllQuotaResult[]>;
15
- type BackgroundLockHandle = {
16
- release: () => Promise<void>;
17
- };
18
- export type BackgroundLockAcquirer = () => Promise<BackgroundLockHandle | null>;
19
- /**
20
- * Acquire the cross-process lock that serializes the background refresh.
21
- * `renew` re-arms the TTL on an interval until release(), so a serial pass that
22
- * outlasts the TTL (a fleet of accounts each costing a token refresh plus a
23
- * wham fetch) never lets the lock expire mid-run — an expiry would let a second
24
- * process start a concurrent refresh. Overrides exist so tests can drive the
25
- * renewal with a mock clock and a fast interval.
26
- */
27
- export declare function acquireBackgroundRefreshLock(configPath: string, overrides?: {
28
- now?: () => number;
29
- renewIntervalMs?: number;
30
- }): Promise<BackgroundLockHandle | null>;
31
- export declare function refreshQuotaInBackground(deps: RefreshAllQuotaDeps, refreshFn?: RefreshAllQuotaFn, acquireLock?: BackgroundLockAcquirer): Promise<RefreshAllQuotaResult[]>;
32
- export declare class BackgroundQuotaRefresh {
33
- private readonly setIntervalFn;
34
- private readonly clearIntervalFn;
35
- private readonly random;
36
- private onError;
37
- private run;
38
- private timer;
39
- private tickPromise;
40
- private stopped;
41
- constructor(options?: BackgroundQuotaRefreshOptions);
42
- start(run: () => Promise<void>, onError?: ((error: unknown) => void) | undefined): void;
43
- stop(): void;
44
- isStopped(): boolean;
45
- }
46
- export {};
@@ -1,53 +0,0 @@
1
- export declare const NON_TRANSIENT_REFRESH_RETRY_DELAY_MS: number;
2
- export declare function isTransientRefreshError(error: unknown): boolean;
3
- export declare function isTransientQuotaError(error: unknown): boolean;
4
- export declare function hashRefreshToken(refreshToken: string): string;
5
- export declare function buildRefreshOperationError(input: {
6
- error: unknown;
7
- now: number;
8
- refreshToken: string;
9
- previous?: {
10
- message: string;
11
- checkedAt: number;
12
- nextRetryAt?: number;
13
- retryCount?: number;
14
- tokenHash?: string;
15
- };
16
- }): {
17
- message: string;
18
- checkedAt: number;
19
- nextRetryAt: number;
20
- retryCount: number;
21
- tokenHash: string;
22
- };
23
- export declare function refreshBackoffActive(error: {
24
- nextRetryAt?: number;
25
- tokenHash?: string;
26
- } | undefined, refreshToken: string | undefined, now: number): boolean;
27
- export declare function formatRefreshBackoffMessage(error: {
28
- message: string;
29
- nextRetryAt?: number;
30
- }, now: number): string;
31
- export declare function buildQuotaOperationError(input: {
32
- error: unknown;
33
- now: number;
34
- previous?: {
35
- message: string;
36
- checkedAt: number;
37
- nextRetryAt?: number;
38
- retryCount?: number;
39
- };
40
- }): {
41
- message: string;
42
- checkedAt: number;
43
- nextRetryAt: number;
44
- retryCount: number;
45
- };
46
- export declare function quotaBackoffActive(error: {
47
- nextRetryAt?: number;
48
- } | undefined, now: number): boolean;
49
- export declare function formatQuotaBackoffMessage(error: {
50
- message: string;
51
- nextRetryAt?: number;
52
- }, now: number): string;
53
- export declare function parseRetryAfter(value: string | undefined | null): number | undefined;
@@ -1,118 +0,0 @@
1
- import type { AccountStorage } from './accounts.ts';
2
- export type CacheKeepWindow = {
3
- startHour: number;
4
- endHour: number;
5
- };
6
- export interface Target {
7
- bodyText: string;
8
- accountId: string | undefined;
9
- chatgptAccountId?: string;
10
- route: 'main';
11
- cacheExpiresAt: number;
12
- ttlMs: number;
13
- warmCount: number;
14
- lastRealRequestAt: number;
15
- lastWarmedAt?: number;
16
- backoffUntil?: number;
17
- replayHeaders: Record<string, string>;
18
- isSubagent?: boolean;
19
- is56: boolean;
20
- }
21
- export interface CacheKeepManagerOptions {
22
- fetchImpl: typeof fetch;
23
- getMainToken: () => Promise<string>;
24
- refreshFallback: (accountId: string) => Promise<string>;
25
- codexResponsesUrl: string;
26
- logger: {
27
- info: (msg: string, data?: unknown) => void;
28
- warn: (msg: string, data?: unknown) => void;
29
- debug: (msg: string, data?: unknown) => void;
30
- error: (msg: string, data?: unknown) => void;
31
- };
32
- now: () => number;
33
- ttlMs?: number;
34
- leadMs?: number;
35
- maxDurationMs?: number;
36
- maxIdleWarmMs?: number;
37
- maxSubagentIdleMs?: number;
38
- tickIntervalMs?: number;
39
- maxTargets?: number;
40
- maxBytes?: number;
41
- /** Returns the configured clock-hour window; undefined means always warm. */
42
- getWindow?: () => CacheKeepWindow | undefined;
43
- /** Returns whether main-agent targets bypass only the idle warm cap. */
44
- getSustain?: () => boolean;
45
- }
46
- export interface CacheKeepStatus {
47
- running: boolean;
48
- tracked: number;
49
- generatedAt: number;
50
- startedAt: number | null;
51
- maxIdleWarmMs: number;
52
- maxSubagentIdleMs: number;
53
- ttlMs: number;
54
- leadMs: number;
55
- sustain: boolean;
56
- window?: CacheKeepWindow;
57
- targets: Array<{
58
- sessionKey: string;
59
- accountId: string | undefined;
60
- route: 'main';
61
- cacheExpiresAt: number;
62
- lastRealRequestAt: number;
63
- lastWarmedAt?: number;
64
- backoffUntil?: number;
65
- bodyBytes: number;
66
- }>;
67
- }
68
- export interface KeepwarmCapture {
69
- sessionKey: string;
70
- bodyText: string;
71
- replayHeaders: Record<string, string>;
72
- isSubagent: boolean;
73
- }
74
- export declare function buildKeepwarmCapture(input: {
75
- enabled: boolean;
76
- includeSubagents: boolean;
77
- headers: Headers;
78
- body: unknown;
79
- }): KeepwarmCapture | undefined;
80
- export declare function getCacheKeepWindow(storage: AccountStorage | null): CacheKeepWindow | undefined;
81
- export declare function isWithinCacheKeepWindow(window: CacheKeepWindow | undefined, now?: Date): boolean;
82
- export declare function buildKeepwarmBody(bodyText: string): string;
83
- export declare function ttlForModel(bodyText: string, defaultTtlMs: number): number;
84
- export declare class CacheKeepManager {
85
- private readonly targets;
86
- private readonly fetchImpl;
87
- private readonly getMainToken;
88
- private readonly refreshFallback;
89
- private readonly codexResponsesUrl;
90
- private readonly log;
91
- private readonly now;
92
- private readonly ttlMs;
93
- private readonly leadMs;
94
- private readonly maxIdleWarmMs;
95
- private readonly maxSubagentIdleMs;
96
- private readonly tickIntervalMs;
97
- private readonly maxTargets;
98
- private readonly maxBytes;
99
- private readonly getWindow?;
100
- private readonly getSustain?;
101
- private timer;
102
- private startedAt;
103
- private totalBytes;
104
- private tickInFlight;
105
- private disposed;
106
- private abortController;
107
- private logPayload;
108
- constructor(options: CacheKeepManagerOptions);
109
- track(sessionKey: string, bodyText: string, accountId: string | undefined, chatgptAccountId?: string, replayHeaders?: Record<string, string>, isSubagent?: boolean): void;
110
- private isGpt56Subagent;
111
- private pruneStale;
112
- start(): void;
113
- stop(): void;
114
- remove(sessionKey: string): void;
115
- status(): CacheKeepStatus;
116
- tick(): Promise<void>;
117
- private prewarm;
118
- }
@@ -1,138 +0,0 @@
1
- export declare const CLIENT_ID = "app_EMoamEEZ73f0CkXaXp7hrann";
2
- export declare const ISSUER = "https://auth.openai.com";
3
- export declare const OAUTH_PORT = 1455;
4
- export declare const OAUTH_POLLING_SAFETY_MARGIN_MS = 3000;
5
- export declare const USER_AGENT = "cortexkit-opencode-openai-auth/0.7.2";
6
- export declare const RESERVED_ACCOUNT_ID = "main";
7
- export declare const RESERVED_ACCOUNT_ID_ERROR = "\"main\" is a reserved account id; choose a different label.";
8
- export interface PkceCodes {
9
- verifier: string;
10
- challenge: string;
11
- }
12
- export declare function base64UrlEncode(buffer: ArrayBuffer): string;
13
- export declare function generatePKCE(): Promise<PkceCodes>;
14
- export interface IdTokenClaims {
15
- chatgpt_account_id?: string;
16
- email?: string;
17
- organizations?: Array<{
18
- id: string;
19
- }>;
20
- 'https://api.openai.com/auth'?: {
21
- chatgpt_account_id?: string;
22
- };
23
- }
24
- export declare function parseJwtClaims(token: string): IdTokenClaims | undefined;
25
- export declare function extractAccountIdFromClaims(claims: IdTokenClaims): string | undefined;
26
- export interface TokenResponse {
27
- id_token: string;
28
- access_token: string;
29
- refresh_token: string;
30
- expires_in?: number;
31
- }
32
- export declare function extractAccountId(tokens: TokenResponse): string | undefined;
33
- export declare function isReservedAccountId(value: string | undefined): boolean;
34
- export declare function assertFallbackAccountIdAllowed<T extends string | undefined>(value: T): T;
35
- export declare function buildAuthorizeUrl(redirectUri: string, pkce: PkceCodes, state: string): string;
36
- export declare function exchangeCodeForTokens(code: string, redirectUri: string, pkce: PkceCodes): Promise<TokenResponse>;
37
- export declare function escapeHtml(value: string): string;
38
- export declare const HTML_SUCCESS = "<!doctype html>\n<html>\n <head>\n <title>CortexKit OpenAI Auth - Authorization Successful</title>\n <style>\n body {\n font-family:\n system-ui,\n -apple-system,\n sans-serif;\n display: flex;\n justify-content: center;\n align-items: center;\n height: 100vh;\n margin: 0;\n background: #131010;\n color: #f1ecec;\n }\n .container {\n text-align: center;\n padding: 2rem;\n }\n h1 {\n color: #f1ecec;\n margin-bottom: 1rem;\n }\n p {\n color: #b7b1b1;\n }\n </style>\n </head>\n <body>\n <div class=\"container\">\n <h1>Authorization Successful</h1>\n <p>You can close this window and return to OpenCode.</p>\n </div>\n <script>\n setTimeout(() => window.close(), 2000)\n </script>\n </body>\n</html>";
39
- export declare const HTML_ERROR: (error: string) => string;
40
- export interface PendingOAuth {
41
- pkce: PkceCodes;
42
- state: string;
43
- resolve: (tokens: TokenResponse) => void;
44
- reject: (error: Error) => void;
45
- }
46
- export declare function flowCleanup(state: string): void;
47
- export declare function startOAuthServer(): Promise<{
48
- port: number;
49
- redirectUri: string;
50
- }>;
51
- export declare function stopOAuthServer(): void;
52
- export declare function resetOAuthStateForTest(): void;
53
- export declare function waitForOAuthCallback(pkce: PkceCodes, state: string, timeoutMs?: number, signal?: AbortSignal): Promise<TokenResponse>;
54
- export interface DeviceAuthInit {
55
- device_auth_id: string;
56
- user_code: string;
57
- interval: string;
58
- expires_in?: number | string;
59
- }
60
- export declare function beginDeviceAuth(): Promise<{
61
- deviceData: DeviceAuthInit;
62
- url: string;
63
- instructions: string;
64
- }>;
65
- export declare function completeDeviceAuth(deviceData: DeviceAuthInit, signal?: AbortSignal): Promise<TokenResponse>;
66
- /**
67
- * Minimal shape of a fallback OAuth account for ingestion. Matches the
68
- * fields used by upsertAccount and beginAccountLogin, compatible with
69
- * the full OAuthAccount type in accounts.ts.
70
- */
71
- export interface IngestAccount {
72
- id: string;
73
- label?: string;
74
- type: 'oauth';
75
- access?: string;
76
- refresh: string;
77
- expires?: number;
78
- enabled: boolean;
79
- addedAt: number;
80
- lastUsed: number;
81
- /**
82
- * When the token was obtained. Stamped at login so a freshly added account
83
- * carries a refresh marker — without it, the runtime-state merge cannot tell a
84
- * rotated token from a stale one (both default to 0) and a concurrent stale
85
- * save could roll the token back.
86
- */
87
- lastRefreshedAt?: number;
88
- /** Stable ChatGPT account identifier from the OAuth token claims. */
89
- accountId?: string;
90
- }
91
- export interface AccountStorageLike {
92
- version: 1;
93
- mainAccountId?: string;
94
- accounts: IngestAccount[];
95
- }
96
- /**
97
- * Dedup by stable accountId first (strongest signal — same ChatGPT account
98
- * added twice with different labels must merge), then by id, then by label.
99
- * If found, merge-update preserving addedAt. Otherwise push.
100
- * Re-running `add --label work` is idempotent.
101
- *
102
- * Accepts the accounts array directly (not the whole storage object) to
103
- * avoid coupling to any particular storage shape.
104
- */
105
- export declare function upsertAccount<T extends {
106
- id: string;
107
- label?: string;
108
- accountId?: string;
109
- addedAt?: number;
110
- }>(accounts: T[], account: T): number;
111
- export interface BeginAccountLoginOptions {
112
- label?: string;
113
- headless?: boolean;
114
- signal?: AbortSignal;
115
- }
116
- export interface BeginAccountLoginResult {
117
- url: string;
118
- instructions: string;
119
- /** Resolves after the user completes the OAuth flow with a ready-to-ingest account. */
120
- completion: Promise<IngestAccount>;
121
- }
122
- /**
123
- * Split-return OAuth flow entry point.
124
- *
125
- * Browser flow (default):
126
- * 1. Start OAuth server, generate PKCE, build authorize URL
127
- * 2. Return { url, instructions, completion } — url is ready immediately
128
- * 3. completion resolves after browser callback + token exchange
129
- *
130
- * Headless flow:
131
- * 1. Begin device auth
132
- * 2. Return { url, instructions, completion }
133
- * 3. completion polls device endpoint + exchanges for tokens
134
- *
135
- * The split return allows the TUI command to show the URL before the
136
- * (potentially 30-60s) wait, avoiding a deadlock.
137
- */
138
- export declare function beginAccountLogin(opts?: BeginAccountLoginOptions): Promise<BeginAccountLoginResult>;