@cortexkit/opencode-openai-auth 0.8.0 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/{index-3w4vmckx.js → index-4effjmr6.js} +2 -2
- package/dist/{index-507jh8bv.js → index-9ehhb051.js} +1 -1
- package/dist/index-g3hsdjh4.js +2 -0
- package/dist/index-hh52v8sb.js +2 -0
- package/dist/{index-944gsj1s.js → index-jwn4r3sw.js} +1 -1
- package/dist/{index-02h7g5f9.js → index-sdt2d2ra.js} +1 -1
- package/dist/index-sq36b120.js +211 -0
- package/dist/index.d.ts +172 -341
- package/dist/index.js +65 -65
- package/dist/internal-BTndPmW2.d.ts +914 -0
- package/dist/quota-normalize-08hpp51v.js +1 -0
- package/dist/rpc/port-file.js +1 -1
- package/dist/rpc/protocol.d.ts +1 -1
- package/dist/rpc/rpc-client.d.ts +2 -1
- package/dist/rpc/rpc-client.js +1 -1
- package/dist/rpc/rpc-dir.js +1 -1
- package/dist/sidebar-state-CoKYKcLn.d.ts +220 -0
- package/dist/sidebar-state.d.ts +2 -172
- package/dist/sidebar-state.js +1 -1
- package/dist/{token-jdvpwk60.js → token-9823y0pc.js} +1 -1
- package/dist/token-util-ypgz7rge.js +1 -0
- package/dist/tui-preferences.js +1 -1
- package/dist/tui.d.ts +27 -5
- package/package.json +3 -2
- package/src/tui-compiled/raw/core-custody-state.ts +243 -0
- package/src/tui-compiled/raw/sidebar-state.ts +168 -12
- package/src/tui-compiled/raw/tui-command-dialogs.tsx +89 -39
- package/src/tui-compiled/raw/tui.tsx +138 -18
- package/src/tui-compiled/runtime/core-custody-state.ts +243 -0
- package/src/tui-compiled/runtime/sidebar-state.ts +168 -12
- package/src/tui-compiled/runtime/tui-command-dialogs.tsx +70 -33
- package/src/tui-compiled/runtime/tui.tsx +241 -143
- package/src/tui-compiled/shared/logger.ts +9 -2
- package/dist/index-2xppkvkx.js +0 -2
- package/dist/index-nshbgkz1.js +0 -198
- package/dist/index-xyg86jgt.js +0 -2
- package/dist/protocol-Cv9ZmU0p.d.ts +0 -24
- package/dist/quota-normalize-wap0rne8.js +0 -1
- package/dist/token-util-zzm7paz9.js +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,355 +1,150 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { C as CustodyManifestIo, E as detectClaustrumConnection, S as acquireRefreshFileLock, T as QuotaManager, _ as loadAccounts, b as ClaustrumCredentialCache, c as IdTokenClaims, d as parseJwtClaims, f as AccountStorage, g as OAuthQuotaSnapshot, h as OAuthAccount, l as TokenResponse, m as FallbackAccount, n as ResetTargetIdentity, p as AccountStoreTransaction, t as CommandContext, u as extractAccountIdFromClaims, v as mutateAccounts, w as CustodyManifestReadResult, x as resolveFallbackAccess, y as withAccountStoreTransaction } from "./internal-BTndPmW2.js";
|
|
2
|
+
import { Q as VaultCustodyState, Z as CustodyInertReason, b as SidebarState, m as SidebarAccountCustody, v as SidebarMachineState } from "./sidebar-state-CoKYKcLn.js";
|
|
2
3
|
import { Hooks, Plugin, PluginInput } from "@opencode-ai/plugin";
|
|
3
|
-
//#region
|
|
4
|
-
|
|
5
|
-
type ProviderQuotaFn = (input: {
|
|
6
|
-
accessToken: string;
|
|
7
|
-
fetchImpl: typeof fetch;
|
|
8
|
-
now: () => number;
|
|
9
|
-
}) => Promise<OAuthQuotaSnapshot>;
|
|
4
|
+
//#region src/core/custody-manifest.d.ts
|
|
5
|
+
declare function readCustodyManifest(path?: string, io?: CustodyManifestIo): Promise<CustodyManifestReadResult>;
|
|
10
6
|
//#endregion
|
|
11
|
-
//#region
|
|
12
|
-
type
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
7
|
+
//#region src/core/custody-transition.d.ts
|
|
8
|
+
type TransitionOutcome = 'ready' | 'tombstoned' | Extract<CustodyInertReason, 'new-local-family-under-claustrum' | 'vault-cold' | 'vault-reauth' | 'identity-mismatch' | 'no-handle'> | 'torn-read-deferred' | `aborted:${string}`;
|
|
9
|
+
type TransitionResult = {
|
|
10
|
+
status: 'completed' | 'incomplete' | 'aborted';
|
|
11
|
+
outcomes: Record<string, TransitionOutcome>;
|
|
12
|
+
reason?: string;
|
|
17
13
|
};
|
|
18
|
-
type
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Account config file this manager's cross-process refresh locks are named
|
|
23
|
-
* after. Host-resolved and required, so two hosts pointing at different
|
|
24
|
-
* stores never contend on one another's lock.
|
|
25
|
-
*/
|
|
26
|
-
configPath: string;
|
|
27
|
-
now?: () => number;
|
|
28
|
-
/** Injected quota-fetch function — replaces the hard-imported Anthropic fetchOAuthQuotaSnapshot */
|
|
29
|
-
fetchQuotaFn?: ProviderQuotaFn;
|
|
30
|
-
onMainQuotaFetched?: (quota: OAuthQuotaSnapshot, checkedAt: number, fingerprint: string, fetchStartedAt: number) => void;
|
|
31
|
-
onApiError?: (error: AccountOperationError) => void;
|
|
14
|
+
type CustodyHostAuth = EnterClaustrumModeDeps['auth'];
|
|
15
|
+
type Release = {
|
|
16
|
+
release(): Promise<void>;
|
|
32
17
|
};
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
* it is dropped and null is returned so the caller refetches.
|
|
68
|
-
*/
|
|
69
|
-
getFallback(accountId: string, accessToken?: string): QuotaEntry | null;
|
|
70
|
-
getAllFallbacks(): Map<string, QuotaEntry>;
|
|
71
|
-
setMain(accessToken: string, entry: QuotaEntry, accountId?: string, completeSnapshot?: boolean): void;
|
|
72
|
-
/**
|
|
73
|
-
* Non-invalidating read of the cached main quota for POLICY decisions
|
|
74
|
-
* (killswitch). Unlike getMain(token), a token mismatch does NOT drop the
|
|
75
|
-
* cache — an access-token refresh is a same-account event and must not turn a
|
|
76
|
-
* known-exhausted account into "unknown" (which would fail open and spend).
|
|
77
|
-
*
|
|
78
|
-
* Pass the live ChatGPT accountId to still drop on a genuine account SWITCH:
|
|
79
|
-
* if the cached entry's account identity is known and differs, return null so
|
|
80
|
-
* the killswitch treats it as unknown rather than judging account A by account
|
|
81
|
-
* B's quota. When identity is unknown on either side, the cached snapshot is
|
|
82
|
-
* returned (best-effort) — the same fail-open-on-unknown stance as elsewhere.
|
|
83
|
-
*/
|
|
84
|
-
peekMainForPolicy(accountId?: string): QuotaEntry | null;
|
|
85
|
-
/**
|
|
86
|
-
* Non-invalidating read of a cached fallback quota for POLICY decisions
|
|
87
|
-
* (killswitch, admission). Keyed by the stable internal account id, so a
|
|
88
|
-
* token refresh for the same account does not drop it (getFallback(id, token)
|
|
89
|
-
* would).
|
|
90
|
-
*
|
|
91
|
-
* Pass the live ChatGPT identity to still drop on a genuine re-login: if the
|
|
92
|
-
* cached entry's identity is known and differs, return null so the previous
|
|
93
|
-
* identity's (possibly exhausted) quota is never judged against its
|
|
94
|
-
* replacement. Unknown on either side fails open, matching peekMainForPolicy.
|
|
95
|
-
*/
|
|
96
|
-
peekFallbackForPolicy(accountId: string, identity?: string): QuotaEntry | null;
|
|
97
|
-
setFallback(accountId: string, entry: QuotaEntry, accessToken?: string, completeSnapshot?: boolean, identity?: string): void;
|
|
98
|
-
/**
|
|
99
|
-
* Mark accountId ('main' or a fallback id) rate-limited until resetAtMs.
|
|
100
|
-
* Keeps the LATER reset: skips only when an existing mark is strictly
|
|
101
|
-
* later than resetAtMs, so an equal-reset re-mark still applies (idempotent)
|
|
102
|
-
* instead of being silently dropped by a stale `>=` comparison.
|
|
103
|
-
*/
|
|
104
|
-
markRateLimited(accountId: string, resetAtMs: number): void;
|
|
105
|
-
/** True iff accountId has a mark whose reset has not yet passed. */
|
|
106
|
-
isRateLimited(accountId: string): boolean;
|
|
107
|
-
/**
|
|
108
|
-
* Raw stored reset for accountId's mark, or undefined if none. Unlike
|
|
109
|
-
* isRateLimited, this does NOT apply read-time expiry — callers on the
|
|
110
|
-
* block path already know the mark is live (isRateLimited just returned
|
|
111
|
-
* true) and want its exact reset estimate for a Retry-After computation.
|
|
112
|
-
*/
|
|
113
|
-
rateLimitedUntil(accountId: string): number | undefined;
|
|
114
|
-
/** Explicit early clear — read-time expiry in isRateLimited is primary. */
|
|
115
|
-
clearRateLimited(accountId: string): void;
|
|
116
|
-
refreshMain(accessToken: string): Promise<OAuthQuotaSnapshot>;
|
|
117
|
-
refreshFallback(accountId: string, accessToken: string): Promise<OAuthQuotaSnapshot>;
|
|
118
|
-
refreshAllFallbacks(accounts: OAuthAccount[]): Promise<void>;
|
|
119
|
-
/**
|
|
120
|
-
* Fire-and-forget refresh. Does not await, swallows errors.
|
|
121
|
-
*/
|
|
122
|
-
refreshMainInBackground(accessToken: string): void;
|
|
123
|
-
isMainStale(): boolean;
|
|
124
|
-
isFallbackStale(accountId: string, accessToken?: string): boolean;
|
|
125
|
-
shouldRefreshOnRequestCount(requestCount: number): boolean;
|
|
126
|
-
/**
|
|
127
|
-
* Combined check: should a refresh happen right now?
|
|
128
|
-
* True if main is stale by time OR triggered by request count.
|
|
129
|
-
*/
|
|
130
|
-
needsRefresh(requestCount: number): boolean;
|
|
131
|
-
updateStorage(storage: AccountStorage | null): void;
|
|
132
|
-
/**
|
|
133
|
-
* Seed/update the main quota cache from persisted state. This is deliberately
|
|
134
|
-
* callable after every disk load so another plugin process's fresh quota write
|
|
135
|
-
* can stop this process from showing "checking…" or making a redundant quota
|
|
136
|
-
* API call.
|
|
137
|
-
*/
|
|
138
|
-
seedMainFromStorage(storage: AccountStorage | null, accessToken?: string): void;
|
|
139
|
-
private seedMainBackoffFromStorage;
|
|
140
|
-
/**
|
|
141
|
-
* Seed fallback cache entries from persisted account.quota data.
|
|
142
|
-
* Updates older in-memory entries so a fresh quota write from another plugin
|
|
143
|
-
* process prevents redundant checks and stale sidebar writes.
|
|
144
|
-
*/
|
|
145
|
-
seedFallbacksFromAccounts(accounts: OAuthAccount[]): void;
|
|
146
|
-
/**
|
|
147
|
-
* Whether the MAIN quota API is currently in backoff. Scoped to the main
|
|
148
|
-
* account — a fallback account's 429 never reports here.
|
|
149
|
-
*/
|
|
150
|
-
isBackedOff(): boolean;
|
|
151
|
-
/**
|
|
152
|
-
* Whether a specific fallback account's quota API is in backoff.
|
|
153
|
-
*/
|
|
154
|
-
isFallbackBackedOff(accountId: string, accessToken?: string): boolean;
|
|
155
|
-
getLastApiError(): AccountOperationError | undefined;
|
|
156
|
-
/** Minimum gap between consecutive quota API calls (ms). */
|
|
157
|
-
private static readonly API_CALL_GAP_MS;
|
|
158
|
-
private static fallbackInflightKey;
|
|
159
|
-
private static quotaLockName;
|
|
160
|
-
/**
|
|
161
|
-
* Serialize API calls through a shared gate so only one
|
|
162
|
-
* quota API request runs at a time, with a minimum gap
|
|
163
|
-
* between calls. Prevents concurrent and rapid-fire calls
|
|
164
|
-
* from triggering rate limits.
|
|
165
|
-
*/
|
|
166
|
-
private _enqueueApiFetch;
|
|
167
|
-
private _fetchMain;
|
|
168
|
-
private _fetchFallback;
|
|
169
|
-
/** Route through injected fetchQuotaFn, or throw if unset. */
|
|
170
|
-
private _fetchQuota;
|
|
171
|
-
private static isAuthError;
|
|
172
|
-
/** Main quota failure: arms main-only backoff and persists via onApiError. */
|
|
173
|
-
private _handleMainFetchError;
|
|
174
|
-
/**
|
|
175
|
-
* Fallback quota failure: arms backoff for THIS account only. Never touches
|
|
176
|
-
* main backoff state and never calls onApiError (which persists the main
|
|
177
|
-
* quota error) — the per-account error is recorded by the caller via the
|
|
178
|
-
* account's lastQuotaRefreshError.
|
|
179
|
-
*/
|
|
180
|
-
private _handleFallbackFetchError;
|
|
181
|
-
}
|
|
182
|
-
//#endregion
|
|
183
|
-
//#region ../core/dist/paths.d.ts
|
|
184
|
-
/**
|
|
185
|
-
* The config file and the runtime-state file a store operation reads and writes.
|
|
186
|
-
*
|
|
187
|
-
* Both are required. A store function never derives one from the other, because
|
|
188
|
-
* a host may point its state file somewhere the derivation would not reach and
|
|
189
|
-
* a silently derived path would lock one file while writing another.
|
|
190
|
-
*/
|
|
191
|
-
interface AccountPaths {
|
|
192
|
-
configPath: string;
|
|
193
|
-
statePath: string;
|
|
194
|
-
}
|
|
195
|
-
//#endregion
|
|
196
|
-
//#region ../core/dist/accounts.d.ts
|
|
197
|
-
type AccountQuotaWindow = {
|
|
198
|
-
usedPercent: number;
|
|
199
|
-
remainingPercent: number;
|
|
200
|
-
resetsAt?: string;
|
|
201
|
-
checkedAt: number;
|
|
202
|
-
windowMinutes?: number;
|
|
203
|
-
};
|
|
204
|
-
interface OAuthQuotaSnapshot {
|
|
205
|
-
primary?: AccountQuotaWindow;
|
|
206
|
-
secondary?: AccountQuotaWindow;
|
|
207
|
-
resetCreditsAvailable?: number;
|
|
208
|
-
resetCreditsApplicable?: number;
|
|
209
|
-
}
|
|
210
|
-
type AccountBase = {
|
|
211
|
-
id: string;
|
|
212
|
-
label?: string;
|
|
213
|
-
enabled?: boolean;
|
|
214
|
-
addedAt?: number;
|
|
215
|
-
lastUsed?: number;
|
|
216
|
-
/** Stable ChatGPT account identifier extracted from the OAuth token claims. */
|
|
217
|
-
accountId?: string;
|
|
218
|
-
};
|
|
219
|
-
type AccountOperationError = {
|
|
220
|
-
message: string;
|
|
221
|
-
checkedAt: number;
|
|
222
|
-
nextRetryAt?: number;
|
|
223
|
-
retryCount?: number;
|
|
224
|
-
tokenHash?: string;
|
|
18
|
+
type EnterClaustrumModeDeps = {
|
|
19
|
+
accountIds: readonly string[];
|
|
20
|
+
acquireLock(options: {
|
|
21
|
+
name: string;
|
|
22
|
+
renew: boolean;
|
|
23
|
+
}): Promise<Release | null>;
|
|
24
|
+
withStoreTransaction(action: (transaction: AccountStoreTransaction) => Promise<TransitionResult>): Promise<TransitionResult>;
|
|
25
|
+
readManifest(): Promise<CustodyManifestReadResult>;
|
|
26
|
+
preflight(input: {
|
|
27
|
+
id: string;
|
|
28
|
+
accountId?: string;
|
|
29
|
+
handle: string;
|
|
30
|
+
}): Promise<Exclude<TransitionOutcome, `aborted:${string}` | 'tombstoned' | 'new-local-family-under-claustrum' | 'torn-read-deferred'>>;
|
|
31
|
+
auth: {
|
|
32
|
+
all(): Promise<Record<string, unknown>>;
|
|
33
|
+
get(input: {
|
|
34
|
+
path: {
|
|
35
|
+
id: string;
|
|
36
|
+
};
|
|
37
|
+
}): Promise<unknown>;
|
|
38
|
+
set(input: {
|
|
39
|
+
path: {
|
|
40
|
+
id: string;
|
|
41
|
+
};
|
|
42
|
+
body: {
|
|
43
|
+
type: 'oauth';
|
|
44
|
+
access: string;
|
|
45
|
+
refresh: string;
|
|
46
|
+
expires: number;
|
|
47
|
+
};
|
|
48
|
+
}): Promise<unknown>;
|
|
49
|
+
};
|
|
50
|
+
onStep?(step: string): void | Promise<void>;
|
|
51
|
+
warn?(message: string): void;
|
|
225
52
|
};
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
lastQuotaRefreshError?: AccountOperationError;
|
|
234
|
-
quota?: OAuthQuotaSnapshot;
|
|
53
|
+
//#endregion
|
|
54
|
+
//#region src/core/custody-runtime.d.ts
|
|
55
|
+
type RuntimeLogger = {
|
|
56
|
+
info: (message: string, meta?: Record<string, unknown>) => void;
|
|
57
|
+
warn: (message: string, meta?: Record<string, unknown>) => void;
|
|
58
|
+
debug: (message: string, meta?: Record<string, unknown>) => void;
|
|
59
|
+
error: (message: string, meta?: Record<string, unknown>) => void;
|
|
235
60
|
};
|
|
236
|
-
type
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
61
|
+
type CustodyRuntimeOptions = {
|
|
62
|
+
/** Storage snapshot at loader time — used for the boot sweep pass. */
|
|
63
|
+
storage: AccountStorage | null;
|
|
64
|
+
configPath: string;
|
|
65
|
+
manifestPath?: string;
|
|
66
|
+
/** Test seam: the vendored detector. Production passes the real function. */
|
|
67
|
+
detectClaustrumConnection?: typeof detectClaustrumConnection;
|
|
68
|
+
/** Test seam: transport factory passed to `ClaustrumCredentialCache`. */
|
|
69
|
+
cacheConnector?: (options: {
|
|
70
|
+
connectionFile: string;
|
|
71
|
+
handshakeTimeoutMs?: number;
|
|
72
|
+
}) => Promise<ClaustrumCacheTransportLike>;
|
|
73
|
+
loadAccounts: typeof loadAccounts;
|
|
74
|
+
mutateAccounts: typeof mutateAccounts;
|
|
75
|
+
withAccountStoreTransaction: typeof withAccountStoreTransaction;
|
|
76
|
+
readCustodyManifest: typeof readCustodyManifest;
|
|
77
|
+
acquireRefreshFileLock: typeof acquireRefreshFileLock;
|
|
78
|
+
auth?: CustodyHostAuth;
|
|
79
|
+
resolveFallbackVaultState?: (input: {
|
|
80
|
+
accountId: string;
|
|
81
|
+
handle: string;
|
|
82
|
+
}) => Promise<VaultCustodyState>;
|
|
83
|
+
now?: () => number;
|
|
84
|
+
setIntervalFn?: (callback: () => void, intervalMs: number) => ReturnType<typeof setInterval>;
|
|
85
|
+
clearIntervalFn?: (handle: ReturnType<typeof setInterval>) => void;
|
|
86
|
+
onReconcileStep?: (step: 'discovery-lock-acquired' | 'enabled-manifest-join', accountId?: string) => void | Promise<void>;
|
|
87
|
+
logger: RuntimeLogger;
|
|
241
88
|
};
|
|
242
|
-
type
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
89
|
+
type ClaustrumCacheTransportLike = {
|
|
90
|
+
getCredential(handle: string, minTtlMs?: number): Promise<{
|
|
91
|
+
material: string;
|
|
92
|
+
recordVersion: number;
|
|
93
|
+
expiresAtMs: number | null;
|
|
94
|
+
accountId?: string;
|
|
95
|
+
}>;
|
|
96
|
+
statusCredential(handle: string): Promise<{
|
|
97
|
+
ready: boolean;
|
|
98
|
+
lastErrorCode: string | null;
|
|
99
|
+
leaseHeld: boolean;
|
|
100
|
+
recordVersion: number;
|
|
101
|
+
}>;
|
|
102
|
+
reportAuthFailure(params: {
|
|
103
|
+
handle: string;
|
|
104
|
+
providerStatus: number;
|
|
105
|
+
recordVersion: number;
|
|
106
|
+
reporterSource: 'direct' | 'relay_status_field' | 'relay_message_parse';
|
|
107
|
+
}): Promise<void>;
|
|
108
|
+
close(): void;
|
|
249
109
|
};
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
type AccountStorage = {
|
|
270
|
-
version: 1;
|
|
271
|
-
main?: {
|
|
272
|
-
type: 'opencode';
|
|
273
|
-
provider: 'openai';
|
|
274
|
-
};
|
|
275
|
-
routing?: {
|
|
276
|
-
mode?: RoutingMode;
|
|
277
|
-
};
|
|
278
|
-
fallbackOn?: number[];
|
|
279
|
-
refresh?: {
|
|
280
|
-
enabled?: boolean;
|
|
281
|
-
intervalMinutes?: number;
|
|
282
|
-
refreshBeforeExpiryMinutes?: number;
|
|
283
|
-
mainLastRefreshError?: AccountOperationError;
|
|
284
|
-
mainRefreshLeaseId?: string;
|
|
285
|
-
mainRefreshLeaseUntil?: number;
|
|
286
|
-
mainRefreshLeaseTokenHash?: string;
|
|
287
|
-
};
|
|
288
|
-
quota?: {
|
|
289
|
-
enabled?: boolean;
|
|
290
|
-
checkIntervalMinutes?: number;
|
|
291
|
-
refreshEveryNRequests?: number;
|
|
292
|
-
minimumRemaining?: Partial<Record<QuotaWindowName | '5h' | '1w', number>>;
|
|
293
|
-
failClosedOnUnknownQuota?: boolean;
|
|
294
|
-
showToasts?: boolean;
|
|
295
|
-
mainQuota?: OAuthQuotaSnapshot;
|
|
296
|
-
mainQuotaCheckedAt?: number;
|
|
297
|
-
mainQuotaToken?: string;
|
|
298
|
-
mainLastQuotaApiError?: AccountOperationError;
|
|
299
|
-
};
|
|
300
|
-
reset?: ResetStateByAccount;
|
|
301
|
-
dump?: {
|
|
302
|
-
enabled?: boolean;
|
|
303
|
-
};
|
|
304
|
-
costZeroing?: {
|
|
305
|
-
enabled?: boolean;
|
|
306
|
-
};
|
|
307
|
-
killswitch?: KillswitchConfig;
|
|
308
|
-
logging?: {
|
|
309
|
-
level?: string;
|
|
310
|
-
};
|
|
311
|
-
cachekeep?: {
|
|
312
|
-
enabled?: boolean;
|
|
313
|
-
subagents?: boolean;
|
|
314
|
-
sustain?: boolean;
|
|
315
|
-
/** Clock-hour window start (0-23, inclusive) — keeps cachekeep idle warming
|
|
316
|
-
* inside `[startHour, endHour)` local hours. Omit to warm unconditionally. */
|
|
317
|
-
startHour?: number;
|
|
318
|
-
/** Clock-hour window end (0-23, exclusive) — must differ from startHour
|
|
319
|
-
* to be honored; an unset or equal hour falls back to "always warm". */
|
|
320
|
-
endHour?: number;
|
|
321
|
-
};
|
|
322
|
-
/** Stable ChatGPT account identifier of the main account (extracted from OAuth token). */
|
|
323
|
-
mainAccountId?: string;
|
|
324
|
-
accounts: FallbackAccount[];
|
|
110
|
+
type CustodyRuntime = {
|
|
111
|
+
/** Run the initial completion sweep. Resolves BEFORE the background refresh is armed. */
|
|
112
|
+
boot(): Promise<void>;
|
|
113
|
+
/** Clear the timer and close the cache + transport. Idempotent. */
|
|
114
|
+
dispose(): void;
|
|
115
|
+
/** Force one tick pass (used by the timer and tests). */
|
|
116
|
+
runTick(): Promise<void>;
|
|
117
|
+
/** Sync projection read for the sidebar writer. */
|
|
118
|
+
getCustodyProjection(account: OAuthAccount, now: number): SidebarAccountCustody | undefined;
|
|
119
|
+
/** Whether the custody runtime is enabled for this process. */
|
|
120
|
+
isEnabled(): boolean;
|
|
121
|
+
/** Cache handle (undefined when custody is disabled). */
|
|
122
|
+
getCache(): ClaustrumCredentialCache | undefined;
|
|
123
|
+
/** Connect the cache on demand and return it. */
|
|
124
|
+
ensureCache(): Promise<ClaustrumCredentialCache | undefined>;
|
|
125
|
+
/** Transport handle (undefined when custody is disabled). */
|
|
126
|
+
getTransport(): ClaustrumCacheTransportLike | undefined;
|
|
127
|
+
/** True if the detection step produced an `available` connection file. */
|
|
128
|
+
wasDetected(): boolean;
|
|
325
129
|
};
|
|
326
|
-
declare function
|
|
327
|
-
|
|
328
|
-
//#region ../core/dist/oauth.d.ts
|
|
329
|
-
interface IdTokenClaims {
|
|
330
|
-
chatgpt_account_id?: string;
|
|
331
|
-
email?: string;
|
|
332
|
-
organizations?: Array<{
|
|
333
|
-
id: string;
|
|
334
|
-
}>;
|
|
335
|
-
'https://api.openai.com/auth'?: {
|
|
336
|
-
chatgpt_account_id?: string;
|
|
337
|
-
};
|
|
338
|
-
}
|
|
339
|
-
export declare function parseJwtClaims(token: string): IdTokenClaims | undefined;
|
|
340
|
-
export declare function extractAccountIdFromClaims(claims: IdTokenClaims): string | undefined;
|
|
341
|
-
//#endregion
|
|
342
|
-
//#region ../core/dist/commands.d.ts
|
|
343
|
-
interface ResetTargetIdentity {
|
|
344
|
-
accountKey: string;
|
|
345
|
-
label: string;
|
|
346
|
-
accessToken: string;
|
|
347
|
-
chatgptAccountId?: string;
|
|
348
|
-
}
|
|
130
|
+
export declare function __createCustodyRuntimeForTest(options: CustodyRuntimeOptions): CustodyRuntime;
|
|
131
|
+
export declare function __resetSweepFailureLogDedupeForTest(): void;
|
|
349
132
|
//#endregion
|
|
350
133
|
//#region src/index.d.ts
|
|
134
|
+
/**
|
|
135
|
+
* Surfaced when a request would go to the wire with no credential.
|
|
136
|
+
*
|
|
137
|
+
* Fixed text on purpose. The host decides retries by matching this string
|
|
138
|
+
* (opencode v1.18.30, session/retry.ts), so no account label, provider wording
|
|
139
|
+
* or number may reach it - an operator-chosen id like `acct-429` would read as
|
|
140
|
+
* retryable and hide a local defect behind a retry loop. Details go to the
|
|
141
|
+
* transport log.
|
|
142
|
+
*/
|
|
143
|
+
export declare const EMPTY_BEARER_MESSAGE = "Refusing to send a request with no access token. This is a defect in the plugin, not a problem with the provider or the account; the transport log names the account and the path that produced it.";
|
|
144
|
+
export declare const getMainRefreshLockName: () => string;
|
|
351
145
|
export declare const MAIN_REFRESH_LOCK_TTL_MS: number;
|
|
352
146
|
export declare const MAIN_REFRESH_LEASE_TTL_MS = 90000;
|
|
147
|
+
export declare function __resetBootQuotaSeedForTest(): void;
|
|
353
148
|
export declare class AuthPersistError extends Error {
|
|
354
149
|
readonly code = "OPENAI_AUTH_PERSIST_FAILED";
|
|
355
150
|
constructor(cause: unknown);
|
|
@@ -376,6 +171,13 @@ interface ResetTargetResolverDeps {
|
|
|
376
171
|
accountStoragePath: string;
|
|
377
172
|
accountStatePath: string;
|
|
378
173
|
now: () => number;
|
|
174
|
+
isFallbackRefreshInert?: (account: OAuthAccount, storage: AccountStorage) => Promise<boolean>;
|
|
175
|
+
resolveFallbackAccess?: (account: OAuthAccount, storage: AccountStorage) => ReturnType<typeof resolveFallbackAccess>;
|
|
176
|
+
reportAuthFailure?: (params: {
|
|
177
|
+
handle: string;
|
|
178
|
+
providerStatus: number;
|
|
179
|
+
recordVersion: number;
|
|
180
|
+
}) => Promise<void>;
|
|
379
181
|
}
|
|
380
182
|
export declare function createResetTargetResolver(deps: ResetTargetResolverDeps): (accountKey: string) => Promise<ResetTargetIdentity>;
|
|
381
183
|
export declare function buildResetRedemptionDeps(): {
|
|
@@ -388,10 +190,39 @@ interface CodexAuthPluginOptions {
|
|
|
388
190
|
codexApiEndpoint?: string;
|
|
389
191
|
experimentalWebSockets?: boolean;
|
|
390
192
|
responsesLite?: boolean;
|
|
193
|
+
custody?: {
|
|
194
|
+
/** Test seam: the transport backing the loader-owned runtime. */
|
|
195
|
+
transport: ClaustrumCacheTransportLike;
|
|
196
|
+
/** Test seam: override the connection-file detection result. */
|
|
197
|
+
detection?: 'available' | 'absent';
|
|
198
|
+
/** Test seam: observes the loader-owned runtime for explicit ticks. */
|
|
199
|
+
onRuntime?: (runtime: CustodyRuntime) => void;
|
|
200
|
+
/** Test seam: controls the runtime clock for expiry-bound scenarios. */
|
|
201
|
+
now?: () => number;
|
|
202
|
+
/** Test seam: controls bounded host-write observation without real timers. */
|
|
203
|
+
sleep?: (ms: number) => Promise<void>;
|
|
204
|
+
/** Test seam: observes a host-write observation deadline warning. */
|
|
205
|
+
warn?: (message: string) => void;
|
|
206
|
+
/** Test seam: observes the account lock around custody binding checks. */
|
|
207
|
+
withFallbackAccountLock?: CommandContext['withFallbackAccountLock'];
|
|
208
|
+
/** Test seam: replaces external OAuth I/O while preserving the hook callback. */
|
|
209
|
+
authorize?: {
|
|
210
|
+
browser?: () => Promise<{
|
|
211
|
+
url: string;
|
|
212
|
+
tokens: Promise<TokenResponse>;
|
|
213
|
+
cleanup?: () => void;
|
|
214
|
+
}>;
|
|
215
|
+
headless?: () => Promise<{
|
|
216
|
+
url: string;
|
|
217
|
+
instructions: string;
|
|
218
|
+
tokens: Promise<TokenResponse>;
|
|
219
|
+
}>;
|
|
220
|
+
};
|
|
221
|
+
};
|
|
391
222
|
}
|
|
392
223
|
export declare function findCachekeepFallbackAccount(accounts: FallbackAccount[], accountId: string): OAuthAccount | undefined;
|
|
393
224
|
export declare function mergePushedQuotaMetadata(incoming: OAuthQuotaSnapshot, previous: OAuthQuotaSnapshot | undefined): OAuthQuotaSnapshot;
|
|
394
|
-
export declare function buildSidebarMachineState(qm: QuotaManager, store: AccountStorage, now?: number, mainAccountIdentity?: string | undefined): SidebarMachineState;
|
|
225
|
+
export declare function buildSidebarMachineState(qm: QuotaManager, store: AccountStorage, now?: number, mainAccountIdentity?: string | undefined, projectCustody?: (account: FallbackAccount, now: number) => SidebarAccountCustody | undefined): SidebarMachineState;
|
|
395
226
|
export declare function buildSidebarState(qm: QuotaManager, store: AccountStorage, activeId: string, now?: number): SidebarState;
|
|
396
227
|
export declare function resolveSidebarSessionId(headers: Headers): string | undefined;
|
|
397
228
|
export declare function CodexAuthPlugin(input: PluginInput, options?: CodexAuthPluginOptions): Promise<Hooks>;
|
|
@@ -401,4 +232,4 @@ declare const _default: {
|
|
|
401
232
|
server: Plugin;
|
|
402
233
|
};
|
|
403
234
|
//#endregion
|
|
404
|
-
export { type IdTokenClaims, _default as default };
|
|
235
|
+
export { type ClaustrumCacheTransportLike, type CustodyRuntime, type CustodyRuntimeOptions, type IdTokenClaims, _default as default, extractAccountIdFromClaims, parseJwtClaims };
|