@prestyj/core 5.11.0 → 5.13.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/dist/{chunk-WAG5K2MH.js → chunk-S6QBRJ4D.js} +448 -124
- package/dist/chunk-S6QBRJ4D.js.map +1 -0
- package/dist/index.cjs +469 -126
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +161 -13
- package/dist/index.d.ts +161 -13
- package/dist/index.js +31 -2
- package/dist/index.js.map +1 -1
- package/dist/model-registry.cjs +16 -43
- package/dist/model-registry.cjs.map +1 -1
- package/dist/model-registry.d.cts +5 -6
- package/dist/model-registry.d.ts +5 -6
- package/dist/model-registry.js +1 -1
- package/package.json +2 -2
- package/dist/chunk-WAG5K2MH.js.map +0 -1
package/dist/index.d.cts
CHANGED
|
@@ -12,7 +12,7 @@ declare function getNextThinkingLevel(provider: Provider, model: string, current
|
|
|
12
12
|
* and any other OpenAI-compatible server the user points us at.
|
|
13
13
|
*
|
|
14
14
|
* Everything rides the OpenAI-compatible `/v1` transport (see the `local`
|
|
15
|
-
* provider in
|
|
15
|
+
* provider in @prestyj/ai's stream.ts); the only per-server difference is where the
|
|
16
16
|
* *capabilities* come from, because `GET /v1/models` reports nothing useful:
|
|
17
17
|
*
|
|
18
18
|
* - Ollama → `POST /api/show` → `capabilities[]` + `model_info["<arch>.context_length"]`
|
|
@@ -185,7 +185,16 @@ interface OAuthCredentials {
|
|
|
185
185
|
}
|
|
186
186
|
interface OAuthLoginCallbacks {
|
|
187
187
|
onOpenUrl: (url: string) => void;
|
|
188
|
-
|
|
188
|
+
/**
|
|
189
|
+
* Collect a pasted authorization code or callback URL.
|
|
190
|
+
*
|
|
191
|
+
* `signal` aborts when the code already arrived another way (the local
|
|
192
|
+
* callback listener won the race) and the prompt should be torn down.
|
|
193
|
+
* Implementations may ignore it — an abandoned promise is simply never
|
|
194
|
+
* awaited — but a terminal prompt should honour it so the line does not
|
|
195
|
+
* linger after login already succeeded.
|
|
196
|
+
*/
|
|
197
|
+
onPromptCode: (message: string, signal?: AbortSignal) => Promise<string>;
|
|
189
198
|
onStatus: (message: string) => void;
|
|
190
199
|
}
|
|
191
200
|
|
|
@@ -195,6 +204,43 @@ interface OAuthLoginCallbacks {
|
|
|
195
204
|
* prefer OAuth for the logical `moonshot` provider.
|
|
196
205
|
*/
|
|
197
206
|
declare const MOONSHOT_OAUTH_KEY = "moonshot-oauth";
|
|
207
|
+
/**
|
|
208
|
+
* Storage key for Grok (xAI) subscription OAuth credentials. Kept distinct from
|
|
209
|
+
* the `xai` API-key entry for the same reason as Kimi's: a user may configure
|
|
210
|
+
* BOTH — a SuperGrok/X Premium subscription plus a metered console key — and we
|
|
211
|
+
* always prefer OAuth for the logical `xai` provider.
|
|
212
|
+
*/
|
|
213
|
+
declare const XAI_OAUTH_KEY = "xai-oauth";
|
|
214
|
+
/**
|
|
215
|
+
* A provider that can hold two credentials at once: a refreshable subscription
|
|
216
|
+
* OAuth token and a static API key. One policy governs all of them — see
|
|
217
|
+
* {@link DUAL_AUTH_PROVIDERS} — so adding a provider here is enough to give it
|
|
218
|
+
* OAuth-first resolution, usage-exhaustion fallback, per-method logout and the
|
|
219
|
+
* matching UI affordances.
|
|
220
|
+
*/
|
|
221
|
+
interface DualAuthProvider {
|
|
222
|
+
/** Logical provider id, which is also the API-key storage key. */
|
|
223
|
+
provider: string;
|
|
224
|
+
/** Storage key holding the OAuth credential. */
|
|
225
|
+
oauthKey: string;
|
|
226
|
+
/** Human label for the OAuth credential (log/UI wording). */
|
|
227
|
+
oauthLabel: string;
|
|
228
|
+
/** Human label for the API-key credential (log/UI wording). */
|
|
229
|
+
apiKeyLabel: string;
|
|
230
|
+
/** What the user should do to restore OAuth after it went invalid. */
|
|
231
|
+
restoreHint: string;
|
|
232
|
+
}
|
|
233
|
+
/** Dual-auth policy for a logical provider, or undefined if it has just one method. */
|
|
234
|
+
declare function dualAuthProvider(provider: string): DualAuthProvider | undefined;
|
|
235
|
+
/** Dual-auth policy keyed by the OAuth storage key (the reverse lookup). */
|
|
236
|
+
declare function dualAuthProviderByOAuthKey(storageKey: string): DualAuthProvider | undefined;
|
|
237
|
+
/** The OAuth storage key for a dual-auth provider, if it has one. */
|
|
238
|
+
declare function oauthStorageKey(provider: string): string | undefined;
|
|
239
|
+
/**
|
|
240
|
+
* Both storage keys a dual-auth provider may hold, in resolution order
|
|
241
|
+
* (OAuth first). Single-method providers yield just their own key.
|
|
242
|
+
*/
|
|
243
|
+
declare function providerStorageKeys(provider: string): string[];
|
|
198
244
|
/**
|
|
199
245
|
* Storage key for the Xiaomi API Credits credential (`https://api.xiaomimimo.com/v1`).
|
|
200
246
|
* Kept distinct from the `xiaomi` Token Plan entry (`token-plan-sgp.xiaomimimo.com`)
|
|
@@ -224,6 +270,16 @@ declare class AuthStorage {
|
|
|
224
270
|
private data;
|
|
225
271
|
private filePath;
|
|
226
272
|
private loaded;
|
|
273
|
+
/**
|
|
274
|
+
* mtime+size of the file as of the cached snapshot (`size: -1` = no file).
|
|
275
|
+
* auth.json is shared: the desktop app writes API keys and disconnects
|
|
276
|
+
* NATIVELY (so they work with no daemon running), and every window/process has
|
|
277
|
+
* its own AuthStorage. A load-once cache therefore goes stale — the sidecar
|
|
278
|
+
* would keep listing models for a provider just disconnected, and hide the
|
|
279
|
+
* ones just connected, until the daemon restarted.
|
|
280
|
+
*/
|
|
281
|
+
private snapshotMtimeMs;
|
|
282
|
+
private snapshotSize;
|
|
227
283
|
/** Per-provider lock to serialize concurrent refresh calls. */
|
|
228
284
|
private refreshLocks;
|
|
229
285
|
constructor(filePath?: string);
|
|
@@ -242,9 +298,9 @@ declare class AuthStorage {
|
|
|
242
298
|
*/
|
|
243
299
|
pickStorageKey(keys: string[]): Promise<string | undefined>;
|
|
244
300
|
/**
|
|
245
|
-
* True if the user has any usable auth for the logical provider. For
|
|
246
|
-
*
|
|
247
|
-
*
|
|
301
|
+
* True if the user has any usable auth for the logical provider. For a
|
|
302
|
+
* dual-auth provider (Kimi/Grok) either the OAuth credential or the API key
|
|
303
|
+
* satisfies it.
|
|
248
304
|
*/
|
|
249
305
|
hasProviderAuth(provider: string): Promise<boolean>;
|
|
250
306
|
/** Endpoint ids that currently have a `local:<id>` credential stored. */
|
|
@@ -259,16 +315,17 @@ declare class AuthStorage {
|
|
|
259
315
|
removeLocalEndpoint(endpointId: string): Promise<void>;
|
|
260
316
|
/**
|
|
261
317
|
* True if the active credential for `provider` is a static API key with no
|
|
262
|
-
* refresh mechanism. For
|
|
263
|
-
* credential is absent (a
|
|
318
|
+
* refresh mechanism. For a dual-auth provider this is only true when its OAuth
|
|
319
|
+
* credential is absent or sidelined (a live OAuth credential is refreshable).
|
|
264
320
|
*/
|
|
265
321
|
isStaticApiKey(provider: string): Promise<boolean>;
|
|
266
322
|
/**
|
|
267
323
|
* The base URL on the credential that is active right now, if any.
|
|
268
324
|
* Synchronous — call only after load()/resolveCredentials() populated the
|
|
269
|
-
* snapshot. For
|
|
270
|
-
*
|
|
271
|
-
* usage-exhausted with an
|
|
325
|
+
* snapshot. For a dual-auth provider this is the subscription endpoint (Kimi
|
|
326
|
+
* For Coding, the Grok CLI proxy) whenever the OAuth entry is the one
|
|
327
|
+
* resolveCredentials would serve (i.e. not currently usage-exhausted with an
|
|
328
|
+
* API key configured).
|
|
272
329
|
*/
|
|
273
330
|
getStoredBaseUrl(provider: string): string | undefined;
|
|
274
331
|
load(): Promise<void>;
|
|
@@ -279,6 +336,20 @@ declare class AuthStorage {
|
|
|
279
336
|
* writes API keys natively without going through this instance.
|
|
280
337
|
*/
|
|
281
338
|
reload(): Promise<void>;
|
|
339
|
+
/**
|
|
340
|
+
* Like {@link ensureLoaded}, but re-reads when the file changed since this
|
|
341
|
+
* snapshot — a cheap stat, not a re-parse. Used by the "what is connected?"
|
|
342
|
+
* readers, which must reflect writes made by another window, the CLI, or the
|
|
343
|
+
* desktop app's native (daemon-free) API-key and disconnect paths.
|
|
344
|
+
*
|
|
345
|
+
* Deliberately NOT used by {@link resolveCredentials}: that path compares the
|
|
346
|
+
* caller's snapshot against the latest file to detect a concurrent re-login,
|
|
347
|
+
* and silently refreshing this instance's view first would destroy the
|
|
348
|
+
* evidence that the token it just had rejected has already been replaced.
|
|
349
|
+
*/
|
|
350
|
+
private ensureFresh;
|
|
351
|
+
/** Record the file identity behind the current snapshot. */
|
|
352
|
+
private rememberSnapshot;
|
|
282
353
|
/**
|
|
283
354
|
* Apply one provider-scoped mutation to the latest on-disk snapshot.
|
|
284
355
|
* AuthStorage instances live in every app session/process, so writing this
|
|
@@ -296,7 +367,7 @@ declare class AuthStorage {
|
|
|
296
367
|
* `resetsAt` (unix SECONDS, from the provider's rate-limit response) or a
|
|
297
368
|
* 15-minute default when no reset time is known. While the mark is in the
|
|
298
369
|
* future, `resolveCredentials("moonshot")` serves the Moonshot API key
|
|
299
|
-
* instead of the
|
|
370
|
+
* instead of the subscription OAuth credential (when both are configured) — OAuth
|
|
300
371
|
* stays the preferred credential and is retried automatically once the mark
|
|
301
372
|
* lapses. Persisted to auth.json so a restart (or another ezcoder-app window)
|
|
302
373
|
* doesn't burn a request rediscovering the same exhausted window. No-op if
|
|
@@ -306,13 +377,27 @@ declare class AuthStorage {
|
|
|
306
377
|
clearAll(): Promise<void>;
|
|
307
378
|
/**
|
|
308
379
|
* Returns valid credentials, auto-refreshing if expired.
|
|
380
|
+
*
|
|
309
381
|
* If `forceRefresh` is true, refreshes even if the token hasn't expired
|
|
310
|
-
* (useful when the provider rejects a token with 401 before its stored
|
|
382
|
+
* (useful when the provider rejects a token with 401 before its stored
|
|
383
|
+
* expiry). Callers recovering from a rejection should also pass
|
|
384
|
+
* `rejectedToken` — see the stampede guard below.
|
|
385
|
+
*
|
|
311
386
|
* Throws if not logged in.
|
|
312
387
|
*/
|
|
313
388
|
resolveCredentials(provider: string, opts?: {
|
|
314
389
|
forceRefresh?: boolean;
|
|
315
390
|
storageKeys?: string[];
|
|
391
|
+
/**
|
|
392
|
+
* The access token the provider just rejected. Refreshing an OAuth grant
|
|
393
|
+
* invalidates the previous access token, so N processes sharing auth.json
|
|
394
|
+
* (app windows, CLI sessions, the usage poller) can otherwise revoke each
|
|
395
|
+
* other in a loop: each one force-refreshes on 401, and every refresh kills
|
|
396
|
+
* the token the others still hold. Naming the rejected token lets the
|
|
397
|
+
* refresh path tell "this credential is genuinely dead" from "someone else
|
|
398
|
+
* already rotated it" and simply adopt the newer on-disk credential.
|
|
399
|
+
*/
|
|
400
|
+
rejectedToken?: string;
|
|
316
401
|
}): Promise<OAuthCredentials>;
|
|
317
402
|
/**
|
|
318
403
|
* Returns a valid access token, auto-refreshing if expired.
|
|
@@ -417,6 +502,69 @@ declare function loginKimi(callbacks: OAuthLoginCallbacks): Promise<OAuthCredent
|
|
|
417
502
|
/** Exchange a refresh token for a fresh Kimi access token. */
|
|
418
503
|
declare function refreshKimiToken(refreshToken: string): Promise<OAuthCredentials>;
|
|
419
504
|
|
|
505
|
+
/**
|
|
506
|
+
* Grok (xAI) subscription OAuth — Device Authorization Grant (RFC 8628).
|
|
507
|
+
*
|
|
508
|
+
* Two form-encoded POST endpoints against xAI's OIDC issuer (`https://auth.x.ai`,
|
|
509
|
+
* advertised by its `/.well-known/openid-configuration`):
|
|
510
|
+
*
|
|
511
|
+
* - `/oauth2/device/code` (client_id + scope) → device + user code
|
|
512
|
+
* - `/oauth2/token` (grant_type=device_code) → poll until authorized
|
|
513
|
+
* - `/oauth2/token` (grant_type=refresh_token) → refresh access token
|
|
514
|
+
*
|
|
515
|
+
* Like Kimi (and unlike Anthropic/OpenAI/Gemini's browser-redirect PKCE) this is
|
|
516
|
+
* a device-code/poll flow: show a URL + code, the user authorizes in a browser on
|
|
517
|
+
* any device, we poll for the token. Deliberately chosen over the loopback PKCE
|
|
518
|
+
* variant because xAI pins the Grok-CLI client's redirect to
|
|
519
|
+
* `http://127.0.0.1:56121/callback` — a fixed port we cannot rebind if it's busy,
|
|
520
|
+
* and unreachable from a container/SSH session. Device code has neither problem.
|
|
521
|
+
*
|
|
522
|
+
* The issued token is used against the Grok CLI's chat proxy
|
|
523
|
+
* (`https://cli-chat-proxy.grok.com/v1`, distinct from the `api.x.ai` API-key
|
|
524
|
+
* endpoint) — that is the surface the `grok-cli:access` scope grants, and it
|
|
525
|
+
* bills against the user's SuperGrok / X Premium subscription instead of metered
|
|
526
|
+
* API credits. We persist that base URL on the credential so the runtime routes
|
|
527
|
+
* there automatically; `grokCliHeaders()` supplies the client identity the proxy
|
|
528
|
+
* requires (attached centrally in @prestyj/ai's `xai` transport).
|
|
529
|
+
*
|
|
530
|
+
* Caveats worth knowing, both observed in the wild and surfaced to users rather
|
|
531
|
+
* than hidden here:
|
|
532
|
+
* - The client id below is xAI's public Grok-CLI desktop client (no secret).
|
|
533
|
+
* Every third-party implementation reuses it; xAI has not published a
|
|
534
|
+
* partner-client program, so subscription OAuth is a best-effort path.
|
|
535
|
+
* - xAI gates proxy access by subscription tier. A perfectly valid login can
|
|
536
|
+
* still be refused at inference time, which is exactly why `xai` keeps its
|
|
537
|
+
* API-key method as a fallback (see AuthStorage's dual-auth resolution).
|
|
538
|
+
*/
|
|
539
|
+
|
|
540
|
+
/** Grok CLI chat-proxy base URL the issued OAuth token is used against. */
|
|
541
|
+
declare function grokCliBaseUrl(): string;
|
|
542
|
+
/**
|
|
543
|
+
* Headers the Grok CLI chat proxy requires on every model request. It serves
|
|
544
|
+
* only recognized Grok-CLI clients: without the token-auth marker and a client
|
|
545
|
+
* version it refuses the request. `modelId` populates the model-override header
|
|
546
|
+
* the proxy uses to route a request to the entitled model.
|
|
547
|
+
*
|
|
548
|
+
* Attach these ONLY to the proxy — the `api.x.ai` API-key path must not receive
|
|
549
|
+
* them (see {@link isGrokCliEndpoint}).
|
|
550
|
+
*/
|
|
551
|
+
declare function grokCliHeaders(modelId?: string): Record<string, string>;
|
|
552
|
+
/**
|
|
553
|
+
* True if `baseUrl` targets the Grok CLI chat proxy (the URL persisted on Grok
|
|
554
|
+
* OAuth credentials). Callers use this to decide whether to attach
|
|
555
|
+
* {@link grokCliHeaders} and whether a usage/permission rejection should fall
|
|
556
|
+
* back to the xAI API key.
|
|
557
|
+
*/
|
|
558
|
+
declare function isGrokCliEndpoint(baseUrl: string | undefined): boolean;
|
|
559
|
+
/**
|
|
560
|
+
* Drive the Grok device-code flow end-to-end. Shows the verification URL + user
|
|
561
|
+
* code via callbacks, opens the browser, and polls until the user authorizes or
|
|
562
|
+
* the device code expires (deadline set by the server).
|
|
563
|
+
*/
|
|
564
|
+
declare function loginXai(callbacks: OAuthLoginCallbacks): Promise<OAuthCredentials>;
|
|
565
|
+
/** Exchange a refresh token for a fresh Grok access token. */
|
|
566
|
+
declare function refreshXaiToken(refreshToken: string): Promise<OAuthCredentials>;
|
|
567
|
+
|
|
420
568
|
/**
|
|
421
569
|
* Minimal Telegram Bot API client using raw fetch().
|
|
422
570
|
* Supports long polling, markdown messages, inline keyboards, and message splitting.
|
|
@@ -590,4 +738,4 @@ interface AutoUpdater {
|
|
|
590
738
|
}
|
|
591
739
|
declare function createAutoUpdater(config: AutoUpdateConfig): AutoUpdater;
|
|
592
740
|
|
|
593
|
-
export { AuthStorage, type AutoUpdateConfig, type AutoUpdater, DEFAULT_LOCAL_ENDPOINTS, type DiscoverOptions, type DiscoveryResult, FALLBACK_CONTEXT_WINDOW, type InlineButton, LOCAL_API_KEY_PLACEHOLDER, LOCAL_AUTH_KEY_PREFIX, type LocalEndpoint, type LocalEndpointKind, type LocalEndpointProbe, type LocalModel, type LogLevel, MOONSHOT_OAUTH_KEY, ModelInfo, NotLoggedInError, type OAuthCredentials, type OAuthLoginCallbacks, type ProbeOptions, type ProgressCallback, SubscriptionUsageError, type SubscriptionUsageProvider, type SubscriptionUsageSnapshot, type SubscriptionUsageWindow, TelegramBot, type TelegramConfig, type TelegramMessage, type TelegramUpdate, type TelegramVoiceMessage, XIAOMI_CREDITS_KEY, clearLocalDiscoveryCache, closeLogger, createAutoUpdater, decodeOggOpus, discoverLocalModels, downmixToMono, endpointRoot, fetchSubscriptionUsage, findProbedModel, formatLocalModelId, generatePKCE, getClaudeCliUserAgent, getClaudeCodeVersion, getNextThinkingLevel, getSessionId, getSupportedThinkingLevels, isKimiCodingEndpoint, isLocalModelId, isLoggerOpen, isModelLoaded, isThinkingLevelSupported, kimiCodeBaseUrl, kimiCodingHeaders, localAuthStorageKey, log, loginAnthropic, loginGemini, loginKimi, loginOpenAI, openLog, parseLocalModelId, probeEndpoint, readStoredBaseUrlSync, refreshAnthropicToken, refreshGeminiToken, refreshKimiToken, refreshOpenAIToken, registerLogCleanup, resample, setProgressCallback, toModelInfo, transcribeVoice, withFileLock };
|
|
741
|
+
export { AuthStorage, type AutoUpdateConfig, type AutoUpdater, DEFAULT_LOCAL_ENDPOINTS, type DiscoverOptions, type DiscoveryResult, type DualAuthProvider, FALLBACK_CONTEXT_WINDOW, type InlineButton, LOCAL_API_KEY_PLACEHOLDER, LOCAL_AUTH_KEY_PREFIX, type LocalEndpoint, type LocalEndpointKind, type LocalEndpointProbe, type LocalModel, type LogLevel, MOONSHOT_OAUTH_KEY, ModelInfo, NotLoggedInError, type OAuthCredentials, type OAuthLoginCallbacks, type ProbeOptions, type ProgressCallback, SubscriptionUsageError, type SubscriptionUsageProvider, type SubscriptionUsageSnapshot, type SubscriptionUsageWindow, TelegramBot, type TelegramConfig, type TelegramMessage, type TelegramUpdate, type TelegramVoiceMessage, XAI_OAUTH_KEY, XIAOMI_CREDITS_KEY, clearLocalDiscoveryCache, closeLogger, createAutoUpdater, decodeOggOpus, discoverLocalModels, downmixToMono, dualAuthProvider, dualAuthProviderByOAuthKey, endpointRoot, fetchSubscriptionUsage, findProbedModel, formatLocalModelId, generatePKCE, getClaudeCliUserAgent, getClaudeCodeVersion, getNextThinkingLevel, getSessionId, getSupportedThinkingLevels, grokCliBaseUrl, grokCliHeaders, isGrokCliEndpoint, isKimiCodingEndpoint, isLocalModelId, isLoggerOpen, isModelLoaded, isThinkingLevelSupported, kimiCodeBaseUrl, kimiCodingHeaders, localAuthStorageKey, log, loginAnthropic, loginGemini, loginKimi, loginOpenAI, loginXai, oauthStorageKey, openLog, parseLocalModelId, probeEndpoint, providerStorageKeys, readStoredBaseUrlSync, refreshAnthropicToken, refreshGeminiToken, refreshKimiToken, refreshOpenAIToken, refreshXaiToken, registerLogCleanup, resample, setProgressCallback, toModelInfo, transcribeVoice, withFileLock };
|
package/dist/index.d.ts
CHANGED
|
@@ -12,7 +12,7 @@ declare function getNextThinkingLevel(provider: Provider, model: string, current
|
|
|
12
12
|
* and any other OpenAI-compatible server the user points us at.
|
|
13
13
|
*
|
|
14
14
|
* Everything rides the OpenAI-compatible `/v1` transport (see the `local`
|
|
15
|
-
* provider in
|
|
15
|
+
* provider in @prestyj/ai's stream.ts); the only per-server difference is where the
|
|
16
16
|
* *capabilities* come from, because `GET /v1/models` reports nothing useful:
|
|
17
17
|
*
|
|
18
18
|
* - Ollama → `POST /api/show` → `capabilities[]` + `model_info["<arch>.context_length"]`
|
|
@@ -185,7 +185,16 @@ interface OAuthCredentials {
|
|
|
185
185
|
}
|
|
186
186
|
interface OAuthLoginCallbacks {
|
|
187
187
|
onOpenUrl: (url: string) => void;
|
|
188
|
-
|
|
188
|
+
/**
|
|
189
|
+
* Collect a pasted authorization code or callback URL.
|
|
190
|
+
*
|
|
191
|
+
* `signal` aborts when the code already arrived another way (the local
|
|
192
|
+
* callback listener won the race) and the prompt should be torn down.
|
|
193
|
+
* Implementations may ignore it — an abandoned promise is simply never
|
|
194
|
+
* awaited — but a terminal prompt should honour it so the line does not
|
|
195
|
+
* linger after login already succeeded.
|
|
196
|
+
*/
|
|
197
|
+
onPromptCode: (message: string, signal?: AbortSignal) => Promise<string>;
|
|
189
198
|
onStatus: (message: string) => void;
|
|
190
199
|
}
|
|
191
200
|
|
|
@@ -195,6 +204,43 @@ interface OAuthLoginCallbacks {
|
|
|
195
204
|
* prefer OAuth for the logical `moonshot` provider.
|
|
196
205
|
*/
|
|
197
206
|
declare const MOONSHOT_OAUTH_KEY = "moonshot-oauth";
|
|
207
|
+
/**
|
|
208
|
+
* Storage key for Grok (xAI) subscription OAuth credentials. Kept distinct from
|
|
209
|
+
* the `xai` API-key entry for the same reason as Kimi's: a user may configure
|
|
210
|
+
* BOTH — a SuperGrok/X Premium subscription plus a metered console key — and we
|
|
211
|
+
* always prefer OAuth for the logical `xai` provider.
|
|
212
|
+
*/
|
|
213
|
+
declare const XAI_OAUTH_KEY = "xai-oauth";
|
|
214
|
+
/**
|
|
215
|
+
* A provider that can hold two credentials at once: a refreshable subscription
|
|
216
|
+
* OAuth token and a static API key. One policy governs all of them — see
|
|
217
|
+
* {@link DUAL_AUTH_PROVIDERS} — so adding a provider here is enough to give it
|
|
218
|
+
* OAuth-first resolution, usage-exhaustion fallback, per-method logout and the
|
|
219
|
+
* matching UI affordances.
|
|
220
|
+
*/
|
|
221
|
+
interface DualAuthProvider {
|
|
222
|
+
/** Logical provider id, which is also the API-key storage key. */
|
|
223
|
+
provider: string;
|
|
224
|
+
/** Storage key holding the OAuth credential. */
|
|
225
|
+
oauthKey: string;
|
|
226
|
+
/** Human label for the OAuth credential (log/UI wording). */
|
|
227
|
+
oauthLabel: string;
|
|
228
|
+
/** Human label for the API-key credential (log/UI wording). */
|
|
229
|
+
apiKeyLabel: string;
|
|
230
|
+
/** What the user should do to restore OAuth after it went invalid. */
|
|
231
|
+
restoreHint: string;
|
|
232
|
+
}
|
|
233
|
+
/** Dual-auth policy for a logical provider, or undefined if it has just one method. */
|
|
234
|
+
declare function dualAuthProvider(provider: string): DualAuthProvider | undefined;
|
|
235
|
+
/** Dual-auth policy keyed by the OAuth storage key (the reverse lookup). */
|
|
236
|
+
declare function dualAuthProviderByOAuthKey(storageKey: string): DualAuthProvider | undefined;
|
|
237
|
+
/** The OAuth storage key for a dual-auth provider, if it has one. */
|
|
238
|
+
declare function oauthStorageKey(provider: string): string | undefined;
|
|
239
|
+
/**
|
|
240
|
+
* Both storage keys a dual-auth provider may hold, in resolution order
|
|
241
|
+
* (OAuth first). Single-method providers yield just their own key.
|
|
242
|
+
*/
|
|
243
|
+
declare function providerStorageKeys(provider: string): string[];
|
|
198
244
|
/**
|
|
199
245
|
* Storage key for the Xiaomi API Credits credential (`https://api.xiaomimimo.com/v1`).
|
|
200
246
|
* Kept distinct from the `xiaomi` Token Plan entry (`token-plan-sgp.xiaomimimo.com`)
|
|
@@ -224,6 +270,16 @@ declare class AuthStorage {
|
|
|
224
270
|
private data;
|
|
225
271
|
private filePath;
|
|
226
272
|
private loaded;
|
|
273
|
+
/**
|
|
274
|
+
* mtime+size of the file as of the cached snapshot (`size: -1` = no file).
|
|
275
|
+
* auth.json is shared: the desktop app writes API keys and disconnects
|
|
276
|
+
* NATIVELY (so they work with no daemon running), and every window/process has
|
|
277
|
+
* its own AuthStorage. A load-once cache therefore goes stale — the sidecar
|
|
278
|
+
* would keep listing models for a provider just disconnected, and hide the
|
|
279
|
+
* ones just connected, until the daemon restarted.
|
|
280
|
+
*/
|
|
281
|
+
private snapshotMtimeMs;
|
|
282
|
+
private snapshotSize;
|
|
227
283
|
/** Per-provider lock to serialize concurrent refresh calls. */
|
|
228
284
|
private refreshLocks;
|
|
229
285
|
constructor(filePath?: string);
|
|
@@ -242,9 +298,9 @@ declare class AuthStorage {
|
|
|
242
298
|
*/
|
|
243
299
|
pickStorageKey(keys: string[]): Promise<string | undefined>;
|
|
244
300
|
/**
|
|
245
|
-
* True if the user has any usable auth for the logical provider. For
|
|
246
|
-
*
|
|
247
|
-
*
|
|
301
|
+
* True if the user has any usable auth for the logical provider. For a
|
|
302
|
+
* dual-auth provider (Kimi/Grok) either the OAuth credential or the API key
|
|
303
|
+
* satisfies it.
|
|
248
304
|
*/
|
|
249
305
|
hasProviderAuth(provider: string): Promise<boolean>;
|
|
250
306
|
/** Endpoint ids that currently have a `local:<id>` credential stored. */
|
|
@@ -259,16 +315,17 @@ declare class AuthStorage {
|
|
|
259
315
|
removeLocalEndpoint(endpointId: string): Promise<void>;
|
|
260
316
|
/**
|
|
261
317
|
* True if the active credential for `provider` is a static API key with no
|
|
262
|
-
* refresh mechanism. For
|
|
263
|
-
* credential is absent (a
|
|
318
|
+
* refresh mechanism. For a dual-auth provider this is only true when its OAuth
|
|
319
|
+
* credential is absent or sidelined (a live OAuth credential is refreshable).
|
|
264
320
|
*/
|
|
265
321
|
isStaticApiKey(provider: string): Promise<boolean>;
|
|
266
322
|
/**
|
|
267
323
|
* The base URL on the credential that is active right now, if any.
|
|
268
324
|
* Synchronous — call only after load()/resolveCredentials() populated the
|
|
269
|
-
* snapshot. For
|
|
270
|
-
*
|
|
271
|
-
* usage-exhausted with an
|
|
325
|
+
* snapshot. For a dual-auth provider this is the subscription endpoint (Kimi
|
|
326
|
+
* For Coding, the Grok CLI proxy) whenever the OAuth entry is the one
|
|
327
|
+
* resolveCredentials would serve (i.e. not currently usage-exhausted with an
|
|
328
|
+
* API key configured).
|
|
272
329
|
*/
|
|
273
330
|
getStoredBaseUrl(provider: string): string | undefined;
|
|
274
331
|
load(): Promise<void>;
|
|
@@ -279,6 +336,20 @@ declare class AuthStorage {
|
|
|
279
336
|
* writes API keys natively without going through this instance.
|
|
280
337
|
*/
|
|
281
338
|
reload(): Promise<void>;
|
|
339
|
+
/**
|
|
340
|
+
* Like {@link ensureLoaded}, but re-reads when the file changed since this
|
|
341
|
+
* snapshot — a cheap stat, not a re-parse. Used by the "what is connected?"
|
|
342
|
+
* readers, which must reflect writes made by another window, the CLI, or the
|
|
343
|
+
* desktop app's native (daemon-free) API-key and disconnect paths.
|
|
344
|
+
*
|
|
345
|
+
* Deliberately NOT used by {@link resolveCredentials}: that path compares the
|
|
346
|
+
* caller's snapshot against the latest file to detect a concurrent re-login,
|
|
347
|
+
* and silently refreshing this instance's view first would destroy the
|
|
348
|
+
* evidence that the token it just had rejected has already been replaced.
|
|
349
|
+
*/
|
|
350
|
+
private ensureFresh;
|
|
351
|
+
/** Record the file identity behind the current snapshot. */
|
|
352
|
+
private rememberSnapshot;
|
|
282
353
|
/**
|
|
283
354
|
* Apply one provider-scoped mutation to the latest on-disk snapshot.
|
|
284
355
|
* AuthStorage instances live in every app session/process, so writing this
|
|
@@ -296,7 +367,7 @@ declare class AuthStorage {
|
|
|
296
367
|
* `resetsAt` (unix SECONDS, from the provider's rate-limit response) or a
|
|
297
368
|
* 15-minute default when no reset time is known. While the mark is in the
|
|
298
369
|
* future, `resolveCredentials("moonshot")` serves the Moonshot API key
|
|
299
|
-
* instead of the
|
|
370
|
+
* instead of the subscription OAuth credential (when both are configured) — OAuth
|
|
300
371
|
* stays the preferred credential and is retried automatically once the mark
|
|
301
372
|
* lapses. Persisted to auth.json so a restart (or another ezcoder-app window)
|
|
302
373
|
* doesn't burn a request rediscovering the same exhausted window. No-op if
|
|
@@ -306,13 +377,27 @@ declare class AuthStorage {
|
|
|
306
377
|
clearAll(): Promise<void>;
|
|
307
378
|
/**
|
|
308
379
|
* Returns valid credentials, auto-refreshing if expired.
|
|
380
|
+
*
|
|
309
381
|
* If `forceRefresh` is true, refreshes even if the token hasn't expired
|
|
310
|
-
* (useful when the provider rejects a token with 401 before its stored
|
|
382
|
+
* (useful when the provider rejects a token with 401 before its stored
|
|
383
|
+
* expiry). Callers recovering from a rejection should also pass
|
|
384
|
+
* `rejectedToken` — see the stampede guard below.
|
|
385
|
+
*
|
|
311
386
|
* Throws if not logged in.
|
|
312
387
|
*/
|
|
313
388
|
resolveCredentials(provider: string, opts?: {
|
|
314
389
|
forceRefresh?: boolean;
|
|
315
390
|
storageKeys?: string[];
|
|
391
|
+
/**
|
|
392
|
+
* The access token the provider just rejected. Refreshing an OAuth grant
|
|
393
|
+
* invalidates the previous access token, so N processes sharing auth.json
|
|
394
|
+
* (app windows, CLI sessions, the usage poller) can otherwise revoke each
|
|
395
|
+
* other in a loop: each one force-refreshes on 401, and every refresh kills
|
|
396
|
+
* the token the others still hold. Naming the rejected token lets the
|
|
397
|
+
* refresh path tell "this credential is genuinely dead" from "someone else
|
|
398
|
+
* already rotated it" and simply adopt the newer on-disk credential.
|
|
399
|
+
*/
|
|
400
|
+
rejectedToken?: string;
|
|
316
401
|
}): Promise<OAuthCredentials>;
|
|
317
402
|
/**
|
|
318
403
|
* Returns a valid access token, auto-refreshing if expired.
|
|
@@ -417,6 +502,69 @@ declare function loginKimi(callbacks: OAuthLoginCallbacks): Promise<OAuthCredent
|
|
|
417
502
|
/** Exchange a refresh token for a fresh Kimi access token. */
|
|
418
503
|
declare function refreshKimiToken(refreshToken: string): Promise<OAuthCredentials>;
|
|
419
504
|
|
|
505
|
+
/**
|
|
506
|
+
* Grok (xAI) subscription OAuth — Device Authorization Grant (RFC 8628).
|
|
507
|
+
*
|
|
508
|
+
* Two form-encoded POST endpoints against xAI's OIDC issuer (`https://auth.x.ai`,
|
|
509
|
+
* advertised by its `/.well-known/openid-configuration`):
|
|
510
|
+
*
|
|
511
|
+
* - `/oauth2/device/code` (client_id + scope) → device + user code
|
|
512
|
+
* - `/oauth2/token` (grant_type=device_code) → poll until authorized
|
|
513
|
+
* - `/oauth2/token` (grant_type=refresh_token) → refresh access token
|
|
514
|
+
*
|
|
515
|
+
* Like Kimi (and unlike Anthropic/OpenAI/Gemini's browser-redirect PKCE) this is
|
|
516
|
+
* a device-code/poll flow: show a URL + code, the user authorizes in a browser on
|
|
517
|
+
* any device, we poll for the token. Deliberately chosen over the loopback PKCE
|
|
518
|
+
* variant because xAI pins the Grok-CLI client's redirect to
|
|
519
|
+
* `http://127.0.0.1:56121/callback` — a fixed port we cannot rebind if it's busy,
|
|
520
|
+
* and unreachable from a container/SSH session. Device code has neither problem.
|
|
521
|
+
*
|
|
522
|
+
* The issued token is used against the Grok CLI's chat proxy
|
|
523
|
+
* (`https://cli-chat-proxy.grok.com/v1`, distinct from the `api.x.ai` API-key
|
|
524
|
+
* endpoint) — that is the surface the `grok-cli:access` scope grants, and it
|
|
525
|
+
* bills against the user's SuperGrok / X Premium subscription instead of metered
|
|
526
|
+
* API credits. We persist that base URL on the credential so the runtime routes
|
|
527
|
+
* there automatically; `grokCliHeaders()` supplies the client identity the proxy
|
|
528
|
+
* requires (attached centrally in @prestyj/ai's `xai` transport).
|
|
529
|
+
*
|
|
530
|
+
* Caveats worth knowing, both observed in the wild and surfaced to users rather
|
|
531
|
+
* than hidden here:
|
|
532
|
+
* - The client id below is xAI's public Grok-CLI desktop client (no secret).
|
|
533
|
+
* Every third-party implementation reuses it; xAI has not published a
|
|
534
|
+
* partner-client program, so subscription OAuth is a best-effort path.
|
|
535
|
+
* - xAI gates proxy access by subscription tier. A perfectly valid login can
|
|
536
|
+
* still be refused at inference time, which is exactly why `xai` keeps its
|
|
537
|
+
* API-key method as a fallback (see AuthStorage's dual-auth resolution).
|
|
538
|
+
*/
|
|
539
|
+
|
|
540
|
+
/** Grok CLI chat-proxy base URL the issued OAuth token is used against. */
|
|
541
|
+
declare function grokCliBaseUrl(): string;
|
|
542
|
+
/**
|
|
543
|
+
* Headers the Grok CLI chat proxy requires on every model request. It serves
|
|
544
|
+
* only recognized Grok-CLI clients: without the token-auth marker and a client
|
|
545
|
+
* version it refuses the request. `modelId` populates the model-override header
|
|
546
|
+
* the proxy uses to route a request to the entitled model.
|
|
547
|
+
*
|
|
548
|
+
* Attach these ONLY to the proxy — the `api.x.ai` API-key path must not receive
|
|
549
|
+
* them (see {@link isGrokCliEndpoint}).
|
|
550
|
+
*/
|
|
551
|
+
declare function grokCliHeaders(modelId?: string): Record<string, string>;
|
|
552
|
+
/**
|
|
553
|
+
* True if `baseUrl` targets the Grok CLI chat proxy (the URL persisted on Grok
|
|
554
|
+
* OAuth credentials). Callers use this to decide whether to attach
|
|
555
|
+
* {@link grokCliHeaders} and whether a usage/permission rejection should fall
|
|
556
|
+
* back to the xAI API key.
|
|
557
|
+
*/
|
|
558
|
+
declare function isGrokCliEndpoint(baseUrl: string | undefined): boolean;
|
|
559
|
+
/**
|
|
560
|
+
* Drive the Grok device-code flow end-to-end. Shows the verification URL + user
|
|
561
|
+
* code via callbacks, opens the browser, and polls until the user authorizes or
|
|
562
|
+
* the device code expires (deadline set by the server).
|
|
563
|
+
*/
|
|
564
|
+
declare function loginXai(callbacks: OAuthLoginCallbacks): Promise<OAuthCredentials>;
|
|
565
|
+
/** Exchange a refresh token for a fresh Grok access token. */
|
|
566
|
+
declare function refreshXaiToken(refreshToken: string): Promise<OAuthCredentials>;
|
|
567
|
+
|
|
420
568
|
/**
|
|
421
569
|
* Minimal Telegram Bot API client using raw fetch().
|
|
422
570
|
* Supports long polling, markdown messages, inline keyboards, and message splitting.
|
|
@@ -590,4 +738,4 @@ interface AutoUpdater {
|
|
|
590
738
|
}
|
|
591
739
|
declare function createAutoUpdater(config: AutoUpdateConfig): AutoUpdater;
|
|
592
740
|
|
|
593
|
-
export { AuthStorage, type AutoUpdateConfig, type AutoUpdater, DEFAULT_LOCAL_ENDPOINTS, type DiscoverOptions, type DiscoveryResult, FALLBACK_CONTEXT_WINDOW, type InlineButton, LOCAL_API_KEY_PLACEHOLDER, LOCAL_AUTH_KEY_PREFIX, type LocalEndpoint, type LocalEndpointKind, type LocalEndpointProbe, type LocalModel, type LogLevel, MOONSHOT_OAUTH_KEY, ModelInfo, NotLoggedInError, type OAuthCredentials, type OAuthLoginCallbacks, type ProbeOptions, type ProgressCallback, SubscriptionUsageError, type SubscriptionUsageProvider, type SubscriptionUsageSnapshot, type SubscriptionUsageWindow, TelegramBot, type TelegramConfig, type TelegramMessage, type TelegramUpdate, type TelegramVoiceMessage, XIAOMI_CREDITS_KEY, clearLocalDiscoveryCache, closeLogger, createAutoUpdater, decodeOggOpus, discoverLocalModels, downmixToMono, endpointRoot, fetchSubscriptionUsage, findProbedModel, formatLocalModelId, generatePKCE, getClaudeCliUserAgent, getClaudeCodeVersion, getNextThinkingLevel, getSessionId, getSupportedThinkingLevels, isKimiCodingEndpoint, isLocalModelId, isLoggerOpen, isModelLoaded, isThinkingLevelSupported, kimiCodeBaseUrl, kimiCodingHeaders, localAuthStorageKey, log, loginAnthropic, loginGemini, loginKimi, loginOpenAI, openLog, parseLocalModelId, probeEndpoint, readStoredBaseUrlSync, refreshAnthropicToken, refreshGeminiToken, refreshKimiToken, refreshOpenAIToken, registerLogCleanup, resample, setProgressCallback, toModelInfo, transcribeVoice, withFileLock };
|
|
741
|
+
export { AuthStorage, type AutoUpdateConfig, type AutoUpdater, DEFAULT_LOCAL_ENDPOINTS, type DiscoverOptions, type DiscoveryResult, type DualAuthProvider, FALLBACK_CONTEXT_WINDOW, type InlineButton, LOCAL_API_KEY_PLACEHOLDER, LOCAL_AUTH_KEY_PREFIX, type LocalEndpoint, type LocalEndpointKind, type LocalEndpointProbe, type LocalModel, type LogLevel, MOONSHOT_OAUTH_KEY, ModelInfo, NotLoggedInError, type OAuthCredentials, type OAuthLoginCallbacks, type ProbeOptions, type ProgressCallback, SubscriptionUsageError, type SubscriptionUsageProvider, type SubscriptionUsageSnapshot, type SubscriptionUsageWindow, TelegramBot, type TelegramConfig, type TelegramMessage, type TelegramUpdate, type TelegramVoiceMessage, XAI_OAUTH_KEY, XIAOMI_CREDITS_KEY, clearLocalDiscoveryCache, closeLogger, createAutoUpdater, decodeOggOpus, discoverLocalModels, downmixToMono, dualAuthProvider, dualAuthProviderByOAuthKey, endpointRoot, fetchSubscriptionUsage, findProbedModel, formatLocalModelId, generatePKCE, getClaudeCliUserAgent, getClaudeCodeVersion, getNextThinkingLevel, getSessionId, getSupportedThinkingLevels, grokCliBaseUrl, grokCliHeaders, isGrokCliEndpoint, isKimiCodingEndpoint, isLocalModelId, isLoggerOpen, isModelLoaded, isThinkingLevelSupported, kimiCodeBaseUrl, kimiCodingHeaders, localAuthStorageKey, log, loginAnthropic, loginGemini, loginKimi, loginOpenAI, loginXai, oauthStorageKey, openLog, parseLocalModelId, probeEndpoint, providerStorageKeys, readStoredBaseUrlSync, refreshAnthropicToken, refreshGeminiToken, refreshKimiToken, refreshOpenAIToken, refreshXaiToken, registerLogCleanup, resample, setProgressCallback, toModelInfo, transcribeVoice, withFileLock };
|
package/dist/index.js
CHANGED
|
@@ -5,9 +5,12 @@ import {
|
|
|
5
5
|
MODELS,
|
|
6
6
|
MOONSHOT_OAUTH_KEY,
|
|
7
7
|
NotLoggedInError,
|
|
8
|
+
XAI_OAUTH_KEY,
|
|
8
9
|
XIAOMI_CREDITS_KEY,
|
|
9
10
|
clearRuntimeModels,
|
|
10
11
|
closeLogger,
|
|
12
|
+
dualAuthProvider,
|
|
13
|
+
dualAuthProviderByOAuthKey,
|
|
11
14
|
generatePKCE,
|
|
12
15
|
getAllModels,
|
|
13
16
|
getAuthStorageKey,
|
|
@@ -25,6 +28,9 @@ import {
|
|
|
25
28
|
getSummaryModel,
|
|
26
29
|
getToolResultCharLimit,
|
|
27
30
|
getVideoByteLimit,
|
|
31
|
+
grokCliBaseUrl,
|
|
32
|
+
grokCliHeaders,
|
|
33
|
+
isGrokCliEndpoint,
|
|
28
34
|
isKimiCodingEndpoint,
|
|
29
35
|
isLoggerOpen,
|
|
30
36
|
kimiCodeBaseUrl,
|
|
@@ -34,17 +40,21 @@ import {
|
|
|
34
40
|
loginGemini,
|
|
35
41
|
loginKimi,
|
|
36
42
|
loginOpenAI,
|
|
43
|
+
loginXai,
|
|
44
|
+
oauthStorageKey,
|
|
37
45
|
openLog,
|
|
46
|
+
providerStorageKeys,
|
|
38
47
|
readStoredBaseUrlSync,
|
|
39
48
|
refreshAnthropicToken,
|
|
40
49
|
refreshGeminiToken,
|
|
41
50
|
refreshKimiToken,
|
|
42
51
|
refreshOpenAIToken,
|
|
52
|
+
refreshXaiToken,
|
|
43
53
|
registerLogCleanup,
|
|
44
54
|
registerRuntimeModels,
|
|
45
55
|
usesOpenAICodexTransport,
|
|
46
56
|
withFileLock
|
|
47
|
-
} from "./chunk-
|
|
57
|
+
} from "./chunk-S6QBRJ4D.js";
|
|
48
58
|
import {
|
|
49
59
|
getAppPaths
|
|
50
60
|
} from "./chunk-CRU3SSNX.js";
|
|
@@ -75,6 +85,7 @@ var ANTHROPIC_ADAPTIVE_THINKING_LEVELS = [
|
|
|
75
85
|
"max"
|
|
76
86
|
];
|
|
77
87
|
var MOONSHOT_K3_THINKING_LEVELS = ["low", "high", "max"];
|
|
88
|
+
var GLM_THINKING_LEVELS = ["low", "medium", "high", "xhigh", "max"];
|
|
78
89
|
var LOCAL_THINKING_LEVELS = ["low", "medium", "high", "max"];
|
|
79
90
|
function isOpenAIGptModel(provider, model) {
|
|
80
91
|
return provider === "openai" && model.startsWith("gpt-");
|
|
@@ -88,6 +99,9 @@ function isXaiModel(provider) {
|
|
|
88
99
|
function isMoonshotK3Model(provider, model) {
|
|
89
100
|
return provider === "moonshot" && model === "kimi-k3";
|
|
90
101
|
}
|
|
102
|
+
function isGlmModel(provider) {
|
|
103
|
+
return provider === "glm";
|
|
104
|
+
}
|
|
91
105
|
function isAnthropicXhighModel(provider, model) {
|
|
92
106
|
return provider === "anthropic" && /opus-5|opus-4-8|opus-4-7/.test(model);
|
|
93
107
|
}
|
|
@@ -119,6 +133,11 @@ function getSupportedThinkingLevels(provider, model) {
|
|
|
119
133
|
return XAI_THINKING_LEVELS.slice(0, maxIndex2 + 1);
|
|
120
134
|
}
|
|
121
135
|
if (isMoonshotK3Model(provider, model)) return MOONSHOT_K3_THINKING_LEVELS;
|
|
136
|
+
if (isGlmModel(provider)) {
|
|
137
|
+
const maxIndex2 = GLM_THINKING_LEVELS.indexOf(maxLevel);
|
|
138
|
+
if (maxIndex2 === -1) return GLM_THINKING_LEVELS;
|
|
139
|
+
return GLM_THINKING_LEVELS.slice(0, maxIndex2 + 1);
|
|
140
|
+
}
|
|
122
141
|
if (!isOpenAIGptModel(provider, model)) return [maxLevel];
|
|
123
142
|
const levels = model.startsWith("gpt-5.6-") ? OPENAI_GPT_56_THINKING_LEVELS : OPENAI_GPT_THINKING_LEVELS;
|
|
124
143
|
const maxIndex = levels.indexOf(maxLevel);
|
|
@@ -130,7 +149,7 @@ function isThinkingLevelSupported(provider, model, level) {
|
|
|
130
149
|
}
|
|
131
150
|
function getNextThinkingLevel(provider, model, current) {
|
|
132
151
|
const supportedLevels = getSupportedThinkingLevels(provider, model);
|
|
133
|
-
const shouldCycleLevels = isOpenAIGptModel(provider, model) || isAnthropicAdaptiveModel(provider, model) || isSakanaModel(provider) || isXaiModel(provider) || isMoonshotK3Model(provider, model) || // Local servers take a real effort level, not just on/off: Ollama accepts
|
|
152
|
+
const shouldCycleLevels = isOpenAIGptModel(provider, model) || isAnthropicAdaptiveModel(provider, model) || isSakanaModel(provider) || isXaiModel(provider) || isMoonshotK3Model(provider, model) || isGlmModel(provider) || // Local servers take a real effort level, not just on/off: Ollama accepts
|
|
134
153
|
// low/medium/high on `reasoning_effort` (verified against 0.32) and the
|
|
135
154
|
// other OpenAI-compatible servers use the same three. A model that can't
|
|
136
155
|
// reason at all already has no supported levels, so it never gets here.
|
|
@@ -1117,6 +1136,7 @@ export {
|
|
|
1117
1136
|
NotLoggedInError,
|
|
1118
1137
|
SubscriptionUsageError,
|
|
1119
1138
|
TelegramBot,
|
|
1139
|
+
XAI_OAUTH_KEY,
|
|
1120
1140
|
XIAOMI_CREDITS_KEY,
|
|
1121
1141
|
clearLocalDiscoveryCache,
|
|
1122
1142
|
clearRuntimeModels,
|
|
@@ -1125,6 +1145,8 @@ export {
|
|
|
1125
1145
|
decodeOggOpus,
|
|
1126
1146
|
discoverLocalModels,
|
|
1127
1147
|
downmixToMono,
|
|
1148
|
+
dualAuthProvider,
|
|
1149
|
+
dualAuthProviderByOAuthKey,
|
|
1128
1150
|
endpointRoot,
|
|
1129
1151
|
fetchSubscriptionUsage,
|
|
1130
1152
|
findProbedModel,
|
|
@@ -1149,6 +1171,9 @@ export {
|
|
|
1149
1171
|
getSupportedThinkingLevels,
|
|
1150
1172
|
getToolResultCharLimit,
|
|
1151
1173
|
getVideoByteLimit,
|
|
1174
|
+
grokCliBaseUrl,
|
|
1175
|
+
grokCliHeaders,
|
|
1176
|
+
isGrokCliEndpoint,
|
|
1152
1177
|
isKimiCodingEndpoint,
|
|
1153
1178
|
isLocalModelId,
|
|
1154
1179
|
isLoggerOpen,
|
|
@@ -1162,14 +1187,18 @@ export {
|
|
|
1162
1187
|
loginGemini,
|
|
1163
1188
|
loginKimi,
|
|
1164
1189
|
loginOpenAI,
|
|
1190
|
+
loginXai,
|
|
1191
|
+
oauthStorageKey,
|
|
1165
1192
|
openLog,
|
|
1166
1193
|
parseLocalModelId,
|
|
1167
1194
|
probeEndpoint,
|
|
1195
|
+
providerStorageKeys,
|
|
1168
1196
|
readStoredBaseUrlSync,
|
|
1169
1197
|
refreshAnthropicToken,
|
|
1170
1198
|
refreshGeminiToken,
|
|
1171
1199
|
refreshKimiToken,
|
|
1172
1200
|
refreshOpenAIToken,
|
|
1201
|
+
refreshXaiToken,
|
|
1173
1202
|
registerLogCleanup,
|
|
1174
1203
|
registerRuntimeModels,
|
|
1175
1204
|
resample,
|