dsh-subscriptions 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +129 -0
- package/cordis.patch.yml +12 -0
- package/lib/auth/claude-code-creds.d.ts +23 -0
- package/lib/auth/claude-code-creds.js +172 -0
- package/lib/auth/device-flow.d.ts +55 -0
- package/lib/auth/device-flow.js +177 -0
- package/lib/auth/jwt.d.ts +10 -0
- package/lib/auth/jwt.js +25 -0
- package/lib/auth/oauth-flow.d.ts +91 -0
- package/lib/auth/oauth-flow.js +227 -0
- package/lib/auth/pkce.d.ts +31 -0
- package/lib/auth/pkce.js +35 -0
- package/lib/auth/rpc.d.ts +209 -0
- package/lib/auth/rpc.js +386 -0
- package/lib/auth/store.d.ts +196 -0
- package/lib/auth/store.js +468 -0
- package/lib/client/CursorCard.d.ts +9 -0
- package/lib/client/CursorCard.js +113 -0
- package/lib/client/ExternalUsageCards.d.ts +9 -0
- package/lib/client/ExternalUsageCards.js +72 -0
- package/lib/client/ImageGallery.d.ts +54 -0
- package/lib/client/ImageGallery.js +112 -0
- package/lib/client/ImageGenerateToolview.d.ts +48 -0
- package/lib/client/ImageGenerateToolview.js +133 -0
- package/lib/client/ProviderAccountManager.d.ts +13 -0
- package/lib/client/ProviderAccountManager.js +147 -0
- package/lib/client/ProviderModelEditor.d.ts +39 -0
- package/lib/client/ProviderModelEditor.js +107 -0
- package/lib/client/SpeedSelect.d.ts +71 -0
- package/lib/client/SpeedSelect.js +177 -0
- package/lib/client/SubscriptionUsageBadge.d.ts +116 -0
- package/lib/client/SubscriptionUsageBadge.js +543 -0
- package/lib/client/SubscriptionsSection.d.ts +140 -0
- package/lib/client/SubscriptionsSection.js +544 -0
- package/lib/client/UsageBadgeDisplaySetting.d.ts +7 -0
- package/lib/client/UsageBadgeDisplaySetting.js +36 -0
- package/lib/client/VideoGenerateToolview.d.ts +42 -0
- package/lib/client/VideoGenerateToolview.js +175 -0
- package/lib/client/account-preferences.d.ts +24 -0
- package/lib/client/account-preferences.js +21 -0
- package/lib/client/fast-command.d.ts +2 -0
- package/lib/client/fast-command.js +4 -0
- package/lib/client/host-contract.d.ts +90 -0
- package/lib/client/host-contract.js +101 -0
- package/lib/client/host-icons.d.ts +24 -0
- package/lib/client/host-icons.js +21 -0
- package/lib/client/index.d.ts +27 -0
- package/lib/client/index.js +136 -0
- package/lib/client/locales.d.ts +297 -0
- package/lib/client/locales.js +295 -0
- package/lib/client/subscription-card-styles.d.ts +3 -0
- package/lib/client/subscription-card-styles.js +53 -0
- package/lib/client/subscriptions-rpc.d.ts +14 -0
- package/lib/client/subscriptions-rpc.js +34 -0
- package/lib/client/usage-badge-preferences.d.ts +11 -0
- package/lib/client/usage-badge-preferences.js +41 -0
- package/lib/client.js +4472 -0
- package/lib/client.js.map +1 -0
- package/lib/compat.d.ts +36 -0
- package/lib/compat.js +20 -0
- package/lib/http.d.ts +6 -0
- package/lib/http.js +15 -0
- package/lib/index.d.ts +80 -0
- package/lib/index.js +14018 -0
- package/lib/model-defaults.d.ts +23 -0
- package/lib/model-defaults.js +237 -0
- package/lib/provider-settings.d.ts +39 -0
- package/lib/provider-settings.js +151 -0
- package/lib/providers/account-preferences.d.ts +41 -0
- package/lib/providers/account-preferences.js +153 -0
- package/lib/providers/accounts.d.ts +112 -0
- package/lib/providers/accounts.js +142 -0
- package/lib/providers/antigravity-oauth-client.d.ts +7 -0
- package/lib/providers/antigravity-oauth-client.js +7 -0
- package/lib/providers/antigravity.d.ts +110 -0
- package/lib/providers/antigravity.js +516 -0
- package/lib/providers/catalog-store.d.ts +48 -0
- package/lib/providers/catalog-store.js +243 -0
- package/lib/providers/claude-cli-version.d.ts +15 -0
- package/lib/providers/claude-cli-version.js +24 -0
- package/lib/providers/claude.d.ts +181 -0
- package/lib/providers/claude.js +680 -0
- package/lib/providers/codex-client-version.d.ts +8 -0
- package/lib/providers/codex-client-version.js +17 -0
- package/lib/providers/codex-search.d.ts +29 -0
- package/lib/providers/codex-search.js +198 -0
- package/lib/providers/codex.d.ts +229 -0
- package/lib/providers/codex.js +821 -0
- package/lib/providers/common.d.ts +389 -0
- package/lib/providers/common.js +656 -0
- package/lib/providers/copilot.d.ts +344 -0
- package/lib/providers/copilot.js +888 -0
- package/lib/providers/cursor-adapter.d.ts +15 -0
- package/lib/providers/cursor-adapter.js +39 -0
- package/lib/providers/cursor-auth.d.ts +43 -0
- package/lib/providers/cursor-auth.js +169 -0
- package/lib/providers/cursor-model-settings.d.ts +15 -0
- package/lib/providers/cursor-model-settings.js +51 -0
- package/lib/providers/cursor-usage.d.ts +9 -0
- package/lib/providers/cursor-usage.js +112 -0
- package/lib/providers/external-usage-controller.d.ts +19 -0
- package/lib/providers/external-usage-controller.js +32 -0
- package/lib/providers/external-usage.d.ts +8 -0
- package/lib/providers/external-usage.js +82 -0
- package/lib/providers/grok.d.ts +205 -0
- package/lib/providers/grok.js +713 -0
- package/lib/providers/image-pool.d.ts +30 -0
- package/lib/providers/image-pool.js +89 -0
- package/lib/providers/npm-cli-version.d.ts +56 -0
- package/lib/providers/npm-cli-version.js +98 -0
- package/lib/providers/pool-family.d.ts +56 -0
- package/lib/providers/pool-family.js +45 -0
- package/lib/providers/pool-health.d.ts +74 -0
- package/lib/providers/pool-health.js +150 -0
- package/lib/providers/pool-usage.d.ts +86 -0
- package/lib/providers/pool-usage.js +223 -0
- package/lib/providers/pool.d.ts +108 -0
- package/lib/providers/pool.js +368 -0
- package/lib/providers/rate-limit.d.ts +192 -0
- package/lib/providers/rate-limit.js +338 -0
- package/lib/tools/image-generate.d.ts +128 -0
- package/lib/tools/image-generate.js +438 -0
- package/lib/tools/registration.d.ts +15 -0
- package/lib/tools/registration.js +24 -0
- package/lib/tools/video-generate.d.ts +89 -0
- package/lib/tools/video-generate.js +257 -0
- package/lib/tools/x-search.d.ts +58 -0
- package/lib/tools/x-search.js +197 -0
- package/lib/translate/anthropic.d.ts +161 -0
- package/lib/translate/anthropic.js +515 -0
- package/lib/translate/antigravity-schema.d.ts +4 -0
- package/lib/translate/antigravity-schema.js +145 -0
- package/lib/translate/antigravity-thinking.d.ts +5 -0
- package/lib/translate/antigravity-thinking.js +44 -0
- package/lib/translate/antigravity.d.ts +114 -0
- package/lib/translate/antigravity.js +366 -0
- package/lib/translate/chat-completions.d.ts +120 -0
- package/lib/translate/chat-completions.js +382 -0
- package/lib/translate/resolved.d.ts +80 -0
- package/lib/translate/resolved.js +118 -0
- package/lib/translate/responses.d.ts +179 -0
- package/lib/translate/responses.js +408 -0
- package/lib/translate/sse.d.ts +21 -0
- package/lib/translate/sse.js +56 -0
- package/package.json +114 -0
- package/vendor/cursor/LICENSE +21 -0
- package/vendor/cursor/index.d.ts +18 -0
- package/vendor/cursor/index.js +3574 -0
- package/vendor/cursor/proto.js +254 -0
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plumbing shared by the subscription adapters: HTTP error mapping, a
|
|
3
|
+
* stream idle watchdog, fetch failure classification, OAuth endpoint errors,
|
|
4
|
+
* and the per-provider {@link TokenManager} that owns session freshness.
|
|
5
|
+
* Concurrent refreshes for one provider coalesce behind a single in-flight
|
|
6
|
+
* promise (`inflight`), so a rotating refresh token is never spent twice.
|
|
7
|
+
*/
|
|
8
|
+
import { LlmError, ReasoningEffortId } from '@deepseek-ai/dsh-llm';
|
|
9
|
+
import type { RateLimitResetReader } from './rate-limit.js';
|
|
10
|
+
/** One configured model catalog entry. */
|
|
11
|
+
export interface ModelEntry {
|
|
12
|
+
/** Wire model id; must be non-empty. */
|
|
13
|
+
id: string;
|
|
14
|
+
/** Selector label; defaults to the id. */
|
|
15
|
+
name?: string;
|
|
16
|
+
/** Known combined request/response context capacity. */
|
|
17
|
+
contextWindow?: number;
|
|
18
|
+
/** Per-request output cap for this model. */
|
|
19
|
+
maxTokens?: number;
|
|
20
|
+
/** Accepted request modalities; when set, wins over the provider default. */
|
|
21
|
+
inputModalities?: ('text' | 'image')[];
|
|
22
|
+
/**
|
|
23
|
+
* Force this model's upstream protocol. Only the copilot adapter consumes
|
|
24
|
+
* the semantics; the union is inlined here to avoid a circular import of
|
|
25
|
+
* the copilot module's `CopilotWire`.
|
|
26
|
+
*/
|
|
27
|
+
wire?: 'chat-completions' | 'responses';
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Validate a configured model catalog (mirrors llm-deepseek's resolveModels).
|
|
31
|
+
* @param models - raw configured entries.
|
|
32
|
+
* @param label - diagnostic prefix naming the provider.
|
|
33
|
+
* @returns the validated entries.
|
|
34
|
+
*/
|
|
35
|
+
export declare function validateModels(models: readonly ModelEntry[], label: string): ModelEntry[];
|
|
36
|
+
/** Optional per-call hooks {@link httpLlmError} uses to read a rate-limit window. */
|
|
37
|
+
export interface HttpLlmErrorOptions {
|
|
38
|
+
/**
|
|
39
|
+
* The calling provider's reader for the instant its rate-limit window
|
|
40
|
+
* reopens. Consulted on a 429 only, and there ahead of the generic
|
|
41
|
+
* `retry-after` header, because a provider's own field names the window while
|
|
42
|
+
* `retry-after` often names a short backoff.
|
|
43
|
+
*/
|
|
44
|
+
rateLimitReset?: RateLimitResetReader;
|
|
45
|
+
/** Diagnostic sink for a 429 that disclosed no reset instant this code recognizes. */
|
|
46
|
+
onWarn?: (message: string) => void;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Build an LlmError from a non-2xx provider response, mapping the status to a
|
|
50
|
+
* stable code and, for a rate-limited request, the disclosed reset instant to
|
|
51
|
+
* the `providerRetryAfterMs` the retry plugin waits out.
|
|
52
|
+
*
|
|
53
|
+
* A 429 classifies as `RATE_LIMIT` on the strength of the status alone, ahead
|
|
54
|
+
* of the quota-wording check. On these routes there is no terminal quota to
|
|
55
|
+
* distinguish: a subscription has no balance to top up, only a window that
|
|
56
|
+
* reopens, and providers announce an exhausted window with wording
|
|
57
|
+
* (`usage_limit_reached`) the shared classifier reads as permanent.
|
|
58
|
+
* @param response - the failed response.
|
|
59
|
+
* @param label - diagnostic prefix naming the provider API.
|
|
60
|
+
* @param options - the calling provider's rate-limit reader and warning sink.
|
|
61
|
+
* @returns the classified error.
|
|
62
|
+
*/
|
|
63
|
+
export declare function httpLlmError(response: Response, label: string, options?: HttpLlmErrorOptions): Promise<LlmError>;
|
|
64
|
+
/** An idle watchdog: aborts its signal when no SSE activity arrives within the timeout. */
|
|
65
|
+
export interface IdleWatchdog {
|
|
66
|
+
/** Signal to pass to fetch and body reads; aborts on caller cancel or idle expiry. */
|
|
67
|
+
readonly signal: AbortSignal;
|
|
68
|
+
/** Reset the idle timer (call on every received SSE event). */
|
|
69
|
+
pulse(): void;
|
|
70
|
+
/** Stop the timer and detach from the caller signal. */
|
|
71
|
+
stop(): void;
|
|
72
|
+
/** Whether the last abort came from idle expiry rather than caller cancellation. */
|
|
73
|
+
timedOut(): boolean;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Create an idle watchdog chained to the caller's signal.
|
|
77
|
+
* @param caller - the request's own abort signal, when present.
|
|
78
|
+
* @param timeoutMs - maximum idle interval while a stream read is outstanding.
|
|
79
|
+
* @returns the watchdog; always {@link IdleWatchdog.stop} it when the stream ends.
|
|
80
|
+
*/
|
|
81
|
+
export declare function idleWatchdog(caller: AbortSignal | undefined, timeoutMs: number): IdleWatchdog;
|
|
82
|
+
/**
|
|
83
|
+
* Classify a thrown fetch failure. Caller cancellation maps to ABORTED, idle
|
|
84
|
+
* expiry to TIMEOUT, and everything else (DNS, TLS, refused connection) to
|
|
85
|
+
* TRANSPORT with the cause chained.
|
|
86
|
+
* @param label - diagnostic prefix naming the provider API.
|
|
87
|
+
* @param error - the thrown value.
|
|
88
|
+
* @param watchdog - the request's idle watchdog.
|
|
89
|
+
* @param caller - the request's own abort signal, when present.
|
|
90
|
+
* @returns the classified error.
|
|
91
|
+
*/
|
|
92
|
+
export declare function mapFetchFailure(label: string, error: unknown, watchdog: IdleWatchdog, caller: AbortSignal | undefined): LlmError;
|
|
93
|
+
/** OAuth token-endpoint failure carrying the provider's `error` code when it sent one. */
|
|
94
|
+
export declare class OAuthEndpointError extends Error {
|
|
95
|
+
/** HTTP status of the token endpoint response. */
|
|
96
|
+
readonly status: number;
|
|
97
|
+
/** The provider's OAuth `error` code (e.g. `invalid_grant`), when present. */
|
|
98
|
+
readonly oauthCode: string | undefined;
|
|
99
|
+
/**
|
|
100
|
+
* The endpoint's `retry-after`, in ms, when it sent one. Usage/models
|
|
101
|
+
* endpoints reuse this error type and can rate-limit progressively (each
|
|
102
|
+
* hit within the window extends the next one), so a caller retrying on a
|
|
103
|
+
* fixed schedule instead of honoring this can keep an account locked out
|
|
104
|
+
* indefinitely.
|
|
105
|
+
*/
|
|
106
|
+
readonly retryAfterMs: number | undefined;
|
|
107
|
+
constructor(message: string, status: number, oauthCode?: string, retryAfterMs?: number);
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Read an OAuth JSON error body into an {@link OAuthEndpointError}. Two body
|
|
111
|
+
* shapes are understood: RFC 6749 (`{ error: "invalid_grant", error_description }`)
|
|
112
|
+
* and the OpenAI API envelope the auth.openai.com token endpoint now answers
|
|
113
|
+
* with (`{ error: { code: "refresh_token_reused", message } }`). The code
|
|
114
|
+
* must land in `oauthCode` either way — the permanent-failure classifiers
|
|
115
|
+
* key on it, and an unrecognized shape would keep a dead login forever.
|
|
116
|
+
* @param response - the failed token-endpoint response.
|
|
117
|
+
* @param label - diagnostic prefix naming the provider.
|
|
118
|
+
* @returns the error to throw.
|
|
119
|
+
*/
|
|
120
|
+
export declare function oauthEndpointError(response: Response, label: string): Promise<OAuthEndpointError>;
|
|
121
|
+
/** A session fresh enough to serve a request without a refresh. */
|
|
122
|
+
interface TimedSession {
|
|
123
|
+
accessToken: string;
|
|
124
|
+
refreshToken: string;
|
|
125
|
+
expiresAt: number;
|
|
126
|
+
}
|
|
127
|
+
/** Provider hooks the token manager needs. */
|
|
128
|
+
export interface TokenManagerOptions<S extends TimedSession> {
|
|
129
|
+
/** Human-readable provider name for error messages. */
|
|
130
|
+
displayName: string;
|
|
131
|
+
/** Refresh this long before `expiresAt`. */
|
|
132
|
+
preemptMs: number;
|
|
133
|
+
load(): Promise<S | undefined>;
|
|
134
|
+
save(session: S): Promise<void>;
|
|
135
|
+
remove(): Promise<void>;
|
|
136
|
+
/** Perform the provider's refresh-token grant. */
|
|
137
|
+
refresh(session: S): Promise<S>;
|
|
138
|
+
/** Whether a refresh failure is permanent (re-login required). */
|
|
139
|
+
isPermanent(error: unknown): boolean;
|
|
140
|
+
/** Called after a permanent refresh failure deleted the stored session. */
|
|
141
|
+
onRemoved?(): void;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Per-provider session freshness: loads the stored session, refreshes
|
|
145
|
+
* proactively inside the preempt window or on demand after a 401, and
|
|
146
|
+
* coalesces concurrent refreshes behind one in-flight promise. Permanent
|
|
147
|
+
* refresh failures delete the stored session and surface INVALID_CREDENTIAL
|
|
148
|
+
* with a re-login hint; transient failures fall back to a still-valid token.
|
|
149
|
+
*/
|
|
150
|
+
export declare class TokenManager<S extends TimedSession> {
|
|
151
|
+
private readonly options;
|
|
152
|
+
private inflight;
|
|
153
|
+
/** The session whose refresh token the in-flight refresh is spending. */
|
|
154
|
+
private attempted;
|
|
155
|
+
constructor(options: TokenManagerOptions<S>);
|
|
156
|
+
/**
|
|
157
|
+
* Read the stored session without any refresh side effect. Catalog queries
|
|
158
|
+
* (`listModels`) use this to decide whether the provider is logged in.
|
|
159
|
+
* @returns the stored session, or `undefined` when logged out.
|
|
160
|
+
*/
|
|
161
|
+
peek(): Promise<S | undefined>;
|
|
162
|
+
/**
|
|
163
|
+
* Whether a session is currently stored (cheap; never refreshes).
|
|
164
|
+
* @returns true when logged in.
|
|
165
|
+
*/
|
|
166
|
+
hasSession(): Promise<boolean>;
|
|
167
|
+
/**
|
|
168
|
+
* Resolve a usable session, refreshing proactively or on demand.
|
|
169
|
+
* @param forceRefresh - refresh regardless of expiry (used after a 401).
|
|
170
|
+
* @returns the persisted session to send.
|
|
171
|
+
* @throws LlmError MISSING_CREDENTIAL when logged out, INVALID_CREDENTIAL
|
|
172
|
+
* when the refresh grant is permanently rejected.
|
|
173
|
+
*/
|
|
174
|
+
session(forceRefresh?: boolean): Promise<S>;
|
|
175
|
+
private doRefresh;
|
|
176
|
+
}
|
|
177
|
+
/** Fetch signature adapters accept for discovery calls (injectable for tests). */
|
|
178
|
+
export type FetchFn = typeof fetch;
|
|
179
|
+
/** Bound on one account catalog fetch or usage poll — a hang must not block the picker. */
|
|
180
|
+
export declare const DISCOVERY_TIMEOUT_MS = 10000;
|
|
181
|
+
/**
|
|
182
|
+
* Run `work` with an aborting signal. Resolves undefined when the timeout
|
|
183
|
+
* fires (the fetch is aborted); other failures propagate.
|
|
184
|
+
*/
|
|
185
|
+
export declare function withTimeout<T>(work: (signal: AbortSignal) => Promise<T>, timeoutMs: number): Promise<T | undefined>;
|
|
186
|
+
/** One rate-limit window reported by a provider's usage endpoint. */
|
|
187
|
+
export interface UsageWindow {
|
|
188
|
+
/** Window kind: `session` for the short rolling window, `weekly` for the 7-day one. */
|
|
189
|
+
kind: 'session' | 'weekly' | 'other';
|
|
190
|
+
/** Model scope for model-specific windows (e.g. `Opus`), when the provider names one. */
|
|
191
|
+
scope?: string;
|
|
192
|
+
/** Percent of the window already consumed (0–100). */
|
|
193
|
+
usedPercent: number;
|
|
194
|
+
/** Epoch milliseconds at which the window resets, when the provider discloses it. */
|
|
195
|
+
resetsAt?: number;
|
|
196
|
+
}
|
|
197
|
+
/** Subscription usage of one provider, as served by the `usage` RPC endpoint. */
|
|
198
|
+
export interface ProviderUsage {
|
|
199
|
+
/** False when the provider has no usage endpoint (grok); windows are absent then. */
|
|
200
|
+
supported: boolean;
|
|
201
|
+
/** Usage windows in display order. */
|
|
202
|
+
windows?: UsageWindow[];
|
|
203
|
+
/** Plan name the usage endpoint reported, when present. */
|
|
204
|
+
plan?: string;
|
|
205
|
+
}
|
|
206
|
+
/** One model discovered from a provider's live model-list endpoint. */
|
|
207
|
+
export interface DiscoveredModel {
|
|
208
|
+
/** Account-specific server-advertised ceiling for local context overrides. */
|
|
209
|
+
maxContextWindow?: number;
|
|
210
|
+
/** Wire model id. */
|
|
211
|
+
id: string;
|
|
212
|
+
/** Human-readable display name. */
|
|
213
|
+
name: string;
|
|
214
|
+
description?: string;
|
|
215
|
+
/** Advertised combined context capacity in tokens. */
|
|
216
|
+
contextWindow?: number;
|
|
217
|
+
/** Server-advertised per-request output token ceiling, when disclosed. */
|
|
218
|
+
maxOutputTokens?: number;
|
|
219
|
+
/** Provider sort hint; lower sorts earlier. */
|
|
220
|
+
priority?: number;
|
|
221
|
+
/** Advertised reasoning efforts, when the provider discloses them. */
|
|
222
|
+
reasoning?: {
|
|
223
|
+
efforts: {
|
|
224
|
+
id: ReasoningEffortId;
|
|
225
|
+
name: string;
|
|
226
|
+
description?: string;
|
|
227
|
+
}[];
|
|
228
|
+
defaultEffort?: ReasoningEffortId;
|
|
229
|
+
};
|
|
230
|
+
/** Accepted request modalities the endpoint advertised (e.g. Copilot's vision support flag). */
|
|
231
|
+
inputModalities?: ('text' | 'image')[];
|
|
232
|
+
/** Claude-specific: which extended-thinking wire shape this model accepts. */
|
|
233
|
+
thinkingType?: 'enabled' | 'adaptive';
|
|
234
|
+
/** Codex-specific: the catalog advertises a fast (priority) service tier. */
|
|
235
|
+
fastTier?: boolean;
|
|
236
|
+
/** Copilot-specific: which upstream protocol the model's endpoints speak. */
|
|
237
|
+
copilotWire?: 'chat-completions' | 'responses';
|
|
238
|
+
/**
|
|
239
|
+
* Copilot-specific: the catalog also lists `/responses` for this model
|
|
240
|
+
* (dual-protocol entries, e.g. gpt-5.4), so a chat-wire request may reroute
|
|
241
|
+
* there when it combines function tools with a reasoning effort.
|
|
242
|
+
*/
|
|
243
|
+
copilotResponses?: boolean;
|
|
244
|
+
}
|
|
245
|
+
/** Display name for a wire reasoning-effort identifier. */
|
|
246
|
+
export declare function effortDisplayName(effort: string): string;
|
|
247
|
+
/** The reasoning-block shape every caller passes to {@link mergeReasoning}. */
|
|
248
|
+
export interface ReasoningBlock {
|
|
249
|
+
efforts: readonly {
|
|
250
|
+
id: ReasoningEffortId;
|
|
251
|
+
name: string;
|
|
252
|
+
description?: string;
|
|
253
|
+
}[];
|
|
254
|
+
defaultEffort?: ReasoningEffortId;
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Fold a configured per-model default effort into a reasoning block, keeping
|
|
258
|
+
* the DSH runtime invariant `defaultEffort ∈ efforts` (the runtime rejects an
|
|
259
|
+
* unknown default with `INVALID_MODEL_REASONING`).
|
|
260
|
+
*
|
|
261
|
+
* A configured level the base set does not advertise is *dropped*, not
|
|
262
|
+
* appended: for claude/grok/copilot the base is the provider's live catalog,
|
|
263
|
+
* i.e. the truth about what the model accepts, so honouring a stale override
|
|
264
|
+
* would put an unsupported effort on every single request instead of letting
|
|
265
|
+
* the harness reject it before provider I/O. The override then simply falls
|
|
266
|
+
* back to the provider's own default until the user picks a level the catalog
|
|
267
|
+
* still lists.
|
|
268
|
+
*
|
|
269
|
+
* `extendable` opts into the opposite rule for a base that is a *built-in
|
|
270
|
+
* fallback* rather than discovered truth (codex, whose static effort list is
|
|
271
|
+
* known to trail the backend): there, appending the configured level is how a
|
|
272
|
+
* newly shipped tier becomes selectable at all.
|
|
273
|
+
* @param configuredDefault - the user-configured default effort id, or undefined.
|
|
274
|
+
* @param base - the discovered/built-in reasoning block, or undefined.
|
|
275
|
+
* @param options - `extendable` marks the base as a fallback that may be extended.
|
|
276
|
+
* @returns the merged block, or undefined when neither side contributes one.
|
|
277
|
+
*/
|
|
278
|
+
export declare function mergeReasoning(configuredDefault: string | undefined, base: ReasoningBlock | undefined, options?: {
|
|
279
|
+
extendable?: boolean;
|
|
280
|
+
}): DiscoveredModel['reasoning'] | undefined;
|
|
281
|
+
/**
|
|
282
|
+
* First account catalog that lists `model` (callers pass default-first).
|
|
283
|
+
* One failing lookup sits that account out so a sibling's metadata still
|
|
284
|
+
* resolves — the same isolation as the picker catalog union.
|
|
285
|
+
*/
|
|
286
|
+
export declare function discoverAcrossAccounts(accounts: readonly string[], lookup: (account: string) => Promise<DiscoveredModel | undefined>): Promise<DiscoveredModel | undefined>;
|
|
287
|
+
/** How long a discovered catalog is trusted before re-fetching. */
|
|
288
|
+
export declare const DISCOVERY_TTL_MS: number;
|
|
289
|
+
/** A durable snapshot of one provider's discovered catalog. */
|
|
290
|
+
export interface CatalogSnapshot {
|
|
291
|
+
/** Epoch milliseconds of the successful fetch that produced it. */
|
|
292
|
+
at: number;
|
|
293
|
+
models: DiscoveredModel[];
|
|
294
|
+
}
|
|
295
|
+
/** The durable half of a {@link ModelCatalogCache} (the models.json store). */
|
|
296
|
+
export interface CatalogPersistence {
|
|
297
|
+
/** The last persisted snapshot, or undefined when absent or unusable. */
|
|
298
|
+
load(): Promise<CatalogSnapshot | undefined>;
|
|
299
|
+
/** Persist a fresh snapshot (write-through after every successful fetch). */
|
|
300
|
+
save(snapshot: CatalogSnapshot): Promise<void>;
|
|
301
|
+
/** Drop the persisted snapshot (a 401 proved the credential changed). */
|
|
302
|
+
clear(): Promise<void>;
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Cache for one provider's discovered model catalog. The TTL only decides
|
|
306
|
+
* when to REFRESH; it never makes the cache forget: capability metadata
|
|
307
|
+
* (reasoning efforts) must stay stable for a session that selected an effort,
|
|
308
|
+
* or mid-conversation calls fail UNSUPPORTED_REASONING_EFFORT the moment the
|
|
309
|
+
* cache goes stale. `listModels` awaits freshness via {@link get};
|
|
310
|
+
* `resolveModel` uses {@link resolve}, which serves the last-known catalog
|
|
311
|
+
* while a stale entry refreshes in the background, and only awaits the fetch
|
|
312
|
+
* when nothing is known yet. An optional {@link CatalogPersistence} seeds the
|
|
313
|
+
* last-known state across restarts and receives every successful fetch. A 401
|
|
314
|
+
* that still fails after a forced token refresh must call {@link invalidate}.
|
|
315
|
+
*/
|
|
316
|
+
export declare class ModelCatalogCache {
|
|
317
|
+
private readonly persistence?;
|
|
318
|
+
private readonly ttlMs;
|
|
319
|
+
private entry;
|
|
320
|
+
private inflight;
|
|
321
|
+
/** Settles once the persisted snapshot (when any) has been considered. */
|
|
322
|
+
private seeded;
|
|
323
|
+
/** Set by {@link invalidate} so an in-flight disk read cannot resurrect dropped state. */
|
|
324
|
+
private seedDisabled;
|
|
325
|
+
/** Bumped by {@link invalidate} so a loser in-flight fetch cannot write back. */
|
|
326
|
+
private generation;
|
|
327
|
+
constructor(persistence?: CatalogPersistence | undefined, ttlMs?: number);
|
|
328
|
+
/**
|
|
329
|
+
* The cached catalog when fresh, without fetching.
|
|
330
|
+
* @returns the cached models, or `undefined` when absent or stale.
|
|
331
|
+
*/
|
|
332
|
+
cached(): readonly DiscoveredModel[] | undefined;
|
|
333
|
+
/**
|
|
334
|
+
* The last successfully fetched catalog, ignoring TTL. Used to carry
|
|
335
|
+
* capability metadata forward when a later fetch cannot re-enrich.
|
|
336
|
+
* @returns the last-known models, or `undefined` when nothing has been stored.
|
|
337
|
+
*/
|
|
338
|
+
lastKnown(): readonly DiscoveredModel[] | undefined;
|
|
339
|
+
/** Load the persisted snapshot once; a fetch or invalidate that landed first wins. */
|
|
340
|
+
private ensureSeeded;
|
|
341
|
+
/** Run (or join) the single in-flight fetch, updating memory and disk on success. */
|
|
342
|
+
private refresh;
|
|
343
|
+
/**
|
|
344
|
+
* Return the cached catalog when fresh, otherwise fetch and cache it.
|
|
345
|
+
* @param fetcher - performs the provider's model-list request.
|
|
346
|
+
* @returns the discovered models.
|
|
347
|
+
* @throws the fetcher's failure (the `listModels` caller warns and falls back).
|
|
348
|
+
*/
|
|
349
|
+
get(fetcher: () => Promise<DiscoveredModel[]>): Promise<readonly DiscoveredModel[]>;
|
|
350
|
+
/**
|
|
351
|
+
* The models for capability resolution. A fresh cache answers directly; a
|
|
352
|
+
* stale one answers immediately from the last-known catalog while a
|
|
353
|
+
* background refresh runs (a mid-conversation `resolveModel` must neither
|
|
354
|
+
* block on nor fail with the network); a cold cache awaits one fetch.
|
|
355
|
+
* @param fetcher - performs the provider's model-list request.
|
|
356
|
+
* @returns the models, or `undefined` when nothing is known (the caller
|
|
357
|
+
* falls back to its static metadata). Never throws.
|
|
358
|
+
*/
|
|
359
|
+
resolve(fetcher: () => Promise<DiscoveredModel[]>): Promise<readonly DiscoveredModel[] | undefined>;
|
|
360
|
+
/** Drop the cached catalog (e.g. after a 401 proved the credential changed). */
|
|
361
|
+
invalidate(): void;
|
|
362
|
+
}
|
|
363
|
+
/** Whether discovery failed because the stored login is gone. */
|
|
364
|
+
export declare function isMissingOrInvalidCredential(error: unknown): boolean;
|
|
365
|
+
/** Whether discovery stopped because the caller cancelled or the timeout fired. */
|
|
366
|
+
export declare function isDiscoveryAborted(error: unknown, signal?: AbortSignal): boolean;
|
|
367
|
+
/**
|
|
368
|
+
* Whether discovery failed because the access token was rejected. After
|
|
369
|
+
* {@link discoverOrRetryAuth} this means the token was rejected AGAIN right
|
|
370
|
+
* after a forced refresh: the login is dead server-side (revoked) even though
|
|
371
|
+
* the refresh grant still answers, so the store keeps the session.
|
|
372
|
+
*/
|
|
373
|
+
export declare function isDiscoveryAuthFailure(error: unknown): boolean;
|
|
374
|
+
/**
|
|
375
|
+
* Run a catalog fetch, retrying once after a forced token refresh when the
|
|
376
|
+
* first attempt is a 401/AUTH. Only {@link ModelCatalogCache.invalidate}s
|
|
377
|
+
* when the retry is also an auth failure, so a refresh race cannot erase
|
|
378
|
+
* last-known capability metadata.
|
|
379
|
+
*/
|
|
380
|
+
export declare function discoverOrRetryAuth<T>(session: (forceRefresh?: boolean) => Promise<unknown>, catalog: ModelCatalogCache, run: () => Promise<T>): Promise<T>;
|
|
381
|
+
/**
|
|
382
|
+
* Keep Codex's session header stable for a supplied, non-empty session ID.
|
|
383
|
+
* Existing UUIDs are preserved; other IDs use a SHA-256-derived UUIDv8 (a
|
|
384
|
+
* custom deterministic layout). UUID formatting is a client convention,
|
|
385
|
+
* not a claim about gateway validation or guaranteed prompt-cache hits.
|
|
386
|
+
* Missing and empty IDs have no session identity and receive a fresh UUIDv4.
|
|
387
|
+
*/
|
|
388
|
+
export declare function deterministicSessionId(sessionId?: string): string;
|
|
389
|
+
export {};
|