dsh-subscriptions 0.2.0 → 0.2.2
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 +212 -180
- package/lib/auth/claude-code-creds.js +31 -9
- package/lib/auth/device-flow.js +16 -9
- package/lib/auth/oauth-flow.js +13 -10
- package/lib/auth/rpc.js +74 -23
- package/lib/auth/store.js +80 -31
- package/lib/client/CursorCard.d.ts +1 -1
- package/lib/client/CursorCard.js +50 -16
- package/lib/client/ExternalUsageCards.d.ts +1 -1
- package/lib/client/ExternalUsageCards.js +37 -16
- package/lib/client/ImageGallery.d.ts +2 -2
- package/lib/client/ImageGallery.js +92 -33
- package/lib/client/ImageGenerateToolview.js +50 -14
- package/lib/client/OllamaCard.d.ts +1 -1
- package/lib/client/OllamaCard.js +26 -8
- package/lib/client/OllamaSettingsManager.js +113 -30
- package/lib/client/ProviderAccountManager.d.ts +1 -1
- package/lib/client/ProviderAccountManager.js +164 -49
- package/lib/client/ProviderModelEditor.js +107 -26
- package/lib/client/SpeedSelect.d.ts +62 -14
- package/lib/client/SpeedSelect.js +257 -46
- package/lib/client/SubscriptionUsageBadge.d.ts +4 -10
- package/lib/client/SubscriptionUsageBadge.js +300 -112
- package/lib/client/SubscriptionsSection.js +258 -85
- package/lib/client/UsageBadgeDisplaySetting.js +35 -12
- package/lib/client/UsageMeter.d.ts +1 -1
- package/lib/client/UsageMeter.js +62 -24
- package/lib/client/VideoGenerateToolview.js +69 -17
- package/lib/client/account-preferences.d.ts +8 -0
- package/lib/client/account-preferences.js +20 -5
- package/lib/client/host-contract.d.ts +11 -2
- package/lib/client/host-contract.js +20 -3
- package/lib/client/index.d.ts +5 -5
- package/lib/client/index.js +34 -12
- package/lib/client/locales.d.ts +10 -0
- package/lib/client/locales.js +61 -51
- package/lib/client/ollama-draft.js +21 -12
- package/lib/client/reset-action.js +6 -4
- package/lib/client/reset-credits-view.d.ts +1 -1
- package/lib/client/reset-credits-view.js +66 -17
- package/lib/client/subscription-card-styles.js +94 -24
- package/lib/client/usage-color-preferences.js +4 -2
- package/lib/client/usage-pace.js +30 -12
- package/lib/client.js +287 -47
- package/lib/client.js.map +1 -1
- package/lib/http.js +1 -1
- package/lib/index.d.ts +3 -3
- package/lib/index.js +118 -64
- package/lib/model-defaults.js +4 -2
- package/lib/provider-settings.d.ts +12 -0
- package/lib/provider-settings.js +58 -16
- package/lib/providers/account-preferences.js +51 -22
- package/lib/providers/accounts.js +15 -9
- package/lib/providers/antigravity-oauth-client.js +2 -2
- package/lib/providers/antigravity.js +141 -68
- package/lib/providers/catalog-store.js +120 -41
- package/lib/providers/claude-cli-version.js +3 -3
- package/lib/providers/claude.d.ts +9 -2
- package/lib/providers/claude.js +153 -90
- package/lib/providers/codex-client-version.js +3 -3
- package/lib/providers/codex-search.js +40 -13
- package/lib/providers/codex.js +196 -112
- package/lib/providers/common.js +71 -39
- package/lib/providers/copilot.js +143 -82
- package/lib/providers/cursor-adapter.js +42 -18
- package/lib/providers/cursor-auth.d.ts +1 -1
- package/lib/providers/cursor-auth.js +69 -24
- package/lib/providers/cursor-model-settings.js +14 -5
- package/lib/providers/cursor-usage.js +27 -13
- package/lib/providers/external-usage-controller.js +14 -5
- package/lib/providers/external-usage.js +59 -23
- package/lib/providers/grok.js +152 -89
- package/lib/providers/image-pool.js +29 -11
- package/lib/providers/minimax-usage.js +31 -11
- package/lib/providers/npm-cli-version.js +10 -3
- package/lib/providers/ollama-settings.js +24 -8
- package/lib/providers/ollama-web.js +29 -11
- package/lib/providers/ollama.js +129 -66
- package/lib/providers/pool-family.js +11 -3
- package/lib/providers/pool-health.js +28 -8
- package/lib/providers/pool-usage.js +16 -9
- package/lib/providers/pool.d.ts +8 -0
- package/lib/providers/pool.js +81 -42
- package/lib/providers/rate-limit.js +8 -2
- package/lib/providers/replay.js +40 -17
- package/lib/providers/reset-redemption.js +18 -6
- package/lib/tools/image-generate.js +123 -65
- package/lib/tools/registration.js +5 -2
- package/lib/tools/video-generate.js +51 -31
- package/lib/tools/x-search.js +50 -22
- package/lib/translate/anthropic.js +85 -37
- package/lib/translate/antigravity-schema.js +71 -28
- package/lib/translate/antigravity-thinking.js +22 -9
- package/lib/translate/antigravity.js +141 -50
- package/lib/translate/chat-completions.js +67 -23
- package/lib/translate/resolved.js +55 -21
- package/lib/translate/responses.js +69 -29
- package/lib/translate/sse.js +4 -1
- package/package.json +26 -4
package/lib/http.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Host-managed network routing for subscription requests. */
|
|
2
|
-
import { getDefaultAutoSelectFamilyAttemptTimeout, setDefaultAutoSelectFamilyAttemptTimeout } from 'node:net';
|
|
2
|
+
import { getDefaultAutoSelectFamilyAttemptTimeout, setDefaultAutoSelectFamilyAttemptTimeout, } from 'node:net';
|
|
3
3
|
/** Keep a sufficient per-address connection budget on high-latency networks. */
|
|
4
4
|
export const MIN_CONNECT_ATTEMPT_TIMEOUT_MS = 1500;
|
|
5
5
|
export function ensureConnectAttemptTimeout(minMs = MIN_CONNECT_ATTEMPT_TIMEOUT_MS) {
|
package/lib/index.d.ts
CHANGED
|
@@ -13,13 +13,13 @@ import type { ModelEntry } from './providers/common.js';
|
|
|
13
13
|
import type { RateLimitConfig } from './providers/rate-limit.js';
|
|
14
14
|
import type { PromptCacheTtl } from './translate/anthropic.js';
|
|
15
15
|
import type { CliVersion, NpmCliVersionCache } from './providers/npm-cli-version.js';
|
|
16
|
-
export type { AccountPreferences, ProviderPreferences } from './provider-settings.js';
|
|
16
|
+
export type { AccountPreferences, ProviderPreferences, } from './provider-settings.js';
|
|
17
17
|
import type { PoolMemberRef } from './providers/pool-family.js';
|
|
18
18
|
import type { AntigravityRuntimeConfig } from './providers/antigravity.js';
|
|
19
|
-
export type { ModelEntry, ProviderUsage, UsageWindow } from './providers/common.js';
|
|
19
|
+
export type { ModelEntry, ProviderUsage, UsageWindow, } from './providers/common.js';
|
|
20
20
|
export type { RateLimitConfig, RateLimitWait } from './providers/rate-limit.js';
|
|
21
21
|
export type { ProviderStatus } from './auth/rpc.js';
|
|
22
|
-
export type { AntigravitySession, ClaudeSession, CodexSession, CopilotSession, GrokSession, ProviderId } from './auth/store.js';
|
|
22
|
+
export type { AntigravitySession, ClaudeSession, CodexSession, CopilotSession, GrokSession, ProviderId, } from './auth/store.js';
|
|
23
23
|
export declare const name = "dsh-subscriptions";
|
|
24
24
|
export declare const inject: string[];
|
|
25
25
|
/** Default maximum provider idle time while one stream read is outstanding. */
|
package/lib/index.js
CHANGED
|
@@ -1205,7 +1205,7 @@ var DeviceFlowManager = class {
|
|
|
1205
1205
|
const response = await fetchFn(spec.deviceCodeUrl, {
|
|
1206
1206
|
method: "POST",
|
|
1207
1207
|
headers: {
|
|
1208
|
-
|
|
1208
|
+
accept: "application/json",
|
|
1209
1209
|
"content-type": "application/x-www-form-urlencoded"
|
|
1210
1210
|
},
|
|
1211
1211
|
body: new URLSearchParams({
|
|
@@ -1244,7 +1244,7 @@ var DeviceFlowManager = class {
|
|
|
1244
1244
|
const pollResponse = await fetchFn(spec.tokenUrl, {
|
|
1245
1245
|
method: "POST",
|
|
1246
1246
|
headers: {
|
|
1247
|
-
|
|
1247
|
+
accept: "application/json",
|
|
1248
1248
|
"content-type": "application/x-www-form-urlencoded"
|
|
1249
1249
|
},
|
|
1250
1250
|
body: new URLSearchParams({
|
|
@@ -3064,8 +3064,8 @@ function withoutImages(messages) {
|
|
|
3064
3064
|
}
|
|
3065
3065
|
function discoveryHeaders(apiKey) {
|
|
3066
3066
|
return {
|
|
3067
|
-
|
|
3068
|
-
...apiKey === void 0 ? {} : {
|
|
3067
|
+
accept: "application/json",
|
|
3068
|
+
...apiKey === void 0 ? {} : { authorization: `Bearer ${apiKey}` },
|
|
3069
3069
|
...attributionHeaders()
|
|
3070
3070
|
};
|
|
3071
3071
|
}
|
|
@@ -3340,8 +3340,8 @@ var OllamaAdapter = class extends LlmAdapter {
|
|
|
3340
3340
|
const response = await (this.options.fetchFn ?? hostFetch)(`${chatBase}/chat/completions`, {
|
|
3341
3341
|
method: "POST",
|
|
3342
3342
|
headers: {
|
|
3343
|
-
|
|
3344
|
-
|
|
3343
|
+
authorization: `Bearer ${apiKey}`,
|
|
3344
|
+
accept: "text/event-stream",
|
|
3345
3345
|
"content-type": "application/json",
|
|
3346
3346
|
...attributionHeaders()
|
|
3347
3347
|
},
|
|
@@ -3377,7 +3377,7 @@ function valueOf(value) {
|
|
|
3377
3377
|
const DEFAULT_REFS = {
|
|
3378
3378
|
"opencode-go": "OPENCODE_GO_API_KEY",
|
|
3379
3379
|
"kimi-code": "KIMI_CODING_API_KEY",
|
|
3380
|
-
|
|
3380
|
+
minimax: "MINIMAX_API_KEY",
|
|
3381
3381
|
"minimax-cn": "MINIMAX_CN_API_KEY",
|
|
3382
3382
|
"ollama-cloud": DEFAULT_OLLAMA_API_KEY_REF
|
|
3383
3383
|
};
|
|
@@ -6950,8 +6950,8 @@ async function postJson(url, apiKey, payload, options, signal) {
|
|
|
6950
6950
|
method: "POST",
|
|
6951
6951
|
headers: {
|
|
6952
6952
|
"content-type": "application/json",
|
|
6953
|
-
|
|
6954
|
-
|
|
6953
|
+
accept: "application/json",
|
|
6954
|
+
authorization: `Bearer ${apiKey}`,
|
|
6955
6955
|
...attributionHeaders()
|
|
6956
6956
|
},
|
|
6957
6957
|
body: JSON.stringify(payload),
|
|
@@ -8008,13 +8008,39 @@ async function readCatalogFile(path) {
|
|
|
8008
8008
|
return {};
|
|
8009
8009
|
}
|
|
8010
8010
|
}
|
|
8011
|
+
/**
|
|
8012
|
+
* Windows refuses to replace a file another handle holds open without
|
|
8013
|
+
* `FILE_SHARE_DELETE` (an indexer, antivirus scan, or a second dsh profile
|
|
8014
|
+
* reading the cache), surfacing as a transient `EPERM`/`EBUSY`/`EACCES` on
|
|
8015
|
+
* `rename` (V1ki/dsh-plugin-subscriptions#129). On Windows only, retry
|
|
8016
|
+
* briefly before giving the write up: on POSIX those codes are real
|
|
8017
|
+
* failures, so retrying would only delay surfacing them.
|
|
8018
|
+
*/
|
|
8019
|
+
const RENAME_RETRY_CODES = new Set([
|
|
8020
|
+
"EPERM",
|
|
8021
|
+
"EBUSY",
|
|
8022
|
+
"EACCES"
|
|
8023
|
+
]);
|
|
8024
|
+
const RENAME_RETRIES = 5;
|
|
8025
|
+
const RENAME_RETRY_DELAY_MS = 20;
|
|
8026
|
+
/** `rename` with a short bounded retry on Windows share-mode conflicts. */
|
|
8027
|
+
async function renameWithRetry(from, to) {
|
|
8028
|
+
for (let attempt = 0;; attempt++) try {
|
|
8029
|
+
await rename(from, to);
|
|
8030
|
+
return;
|
|
8031
|
+
} catch (error) {
|
|
8032
|
+
const code = error.code;
|
|
8033
|
+
if (process.platform !== "win32" || attempt >= RENAME_RETRIES || code === void 0 || !RENAME_RETRY_CODES.has(code)) throw error;
|
|
8034
|
+
await new Promise((resolve$2) => setTimeout(resolve$2, RENAME_RETRY_DELAY_MS * (attempt + 1)));
|
|
8035
|
+
}
|
|
8036
|
+
}
|
|
8011
8037
|
/** Persist the whole file atomically (tmp file + rename). */
|
|
8012
8038
|
async function writeCatalogFile(store, path) {
|
|
8013
8039
|
await mkdir(dirname(path), { recursive: true });
|
|
8014
8040
|
const tmp = `${path}.tmp-${process.pid}-${Math.random().toString(36).slice(2)}`;
|
|
8015
8041
|
try {
|
|
8016
8042
|
await writeFile(tmp, JSON.stringify(store, null, 2));
|
|
8017
|
-
await
|
|
8043
|
+
await renameWithRetry(tmp, path);
|
|
8018
8044
|
} catch (error) {
|
|
8019
8045
|
await rm(tmp, { force: true });
|
|
8020
8046
|
throw error;
|
|
@@ -8550,10 +8576,10 @@ async function fetchClaudeUsage(session, fetchFn = hostFetch, signal, cliVersion
|
|
|
8550
8576
|
const userAgent = claudeCliUserAgent(await cliVersion());
|
|
8551
8577
|
const init = {
|
|
8552
8578
|
headers: {
|
|
8553
|
-
|
|
8579
|
+
authorization: `Bearer ${session.accessToken}`,
|
|
8554
8580
|
"anthropic-beta": "oauth-2025-04-20",
|
|
8555
8581
|
"user-agent": userAgent,
|
|
8556
|
-
|
|
8582
|
+
accept: "application/json"
|
|
8557
8583
|
},
|
|
8558
8584
|
...signal === void 0 ? {} : { signal }
|
|
8559
8585
|
};
|
|
@@ -8625,11 +8651,11 @@ async function fetchClaudeModels(session, fetchFn = hostFetch, signal, cliVersio
|
|
|
8625
8651
|
const userAgent = claudeCliUserAgent(await cliVersion());
|
|
8626
8652
|
const response = await fetchFn(CLAUDE_MODELS_URL, {
|
|
8627
8653
|
headers: {
|
|
8628
|
-
|
|
8654
|
+
authorization: `Bearer ${session.accessToken}`,
|
|
8629
8655
|
"anthropic-version": "2023-06-01",
|
|
8630
8656
|
"user-agent": userAgent,
|
|
8631
8657
|
"anthropic-dangerous-direct-browser-access": "true",
|
|
8632
|
-
|
|
8658
|
+
accept: "application/json"
|
|
8633
8659
|
},
|
|
8634
8660
|
...signal === void 0 ? {} : { signal }
|
|
8635
8661
|
});
|
|
@@ -8697,8 +8723,9 @@ const CLAUDE_MODALITIES = ["text", "image"];
|
|
|
8697
8723
|
* @param effort - the reasoning effort, when the model advertises efforts.
|
|
8698
8724
|
* @param cacheTtl - lifetime of every cache breakpoint; defaults to five minutes.
|
|
8699
8725
|
* Requests that carry a `purpose` (compaction, session titles) always use five
|
|
8700
|
-
* minutes to preserve their existing auxiliary-request behavior
|
|
8701
|
-
*
|
|
8726
|
+
* minutes to preserve their existing auxiliary-request behavior — the override
|
|
8727
|
+
* changes the TTL for ordinary turns only, never the auxiliary floor. A
|
|
8728
|
+
* five-minute mark can still read an entry a one-hour mark wrote.
|
|
8702
8729
|
* @returns the JSON body to POST.
|
|
8703
8730
|
*/
|
|
8704
8731
|
function claudeRequestBody(options, messages, maxTokens, thinking, effort, cacheTtl) {
|
|
@@ -8913,18 +8940,18 @@ var ClaudeAdapter = class extends LlmAdapter {
|
|
|
8913
8940
|
}
|
|
8914
8941
|
const disc = await this.discovered(options.model);
|
|
8915
8942
|
const maxTokens = options.maxTokens ?? claudeMaxTokens(this.options.models.find((entry) => entry.id === options.model), disc);
|
|
8916
|
-
const body = claudeRequestBody(options, messages, maxTokens, this.thinkingParam(disc?.thinkingType, maxTokens), options.reasoningEffort !== void 0 && disc?.reasoning !== void 0 ? String(options.reasoningEffort) : void 0, this.options.promptCacheTtl);
|
|
8943
|
+
const body = claudeRequestBody(options, messages, maxTokens, this.thinkingParam(disc?.thinkingType, maxTokens), options.reasoningEffort !== void 0 && disc?.reasoning !== void 0 ? String(options.reasoningEffort) : void 0, this.options.promptCacheTtlOverride?.() ?? this.options.promptCacheTtl);
|
|
8917
8944
|
const cliVersion = await (this.options.resolveCliVersion ?? localClaudeCliVersion)();
|
|
8918
8945
|
return hostFetch(CLAUDE_API_URL, {
|
|
8919
8946
|
method: "POST",
|
|
8920
8947
|
headers: {
|
|
8921
|
-
|
|
8948
|
+
authorization: `Bearer ${session.accessToken}`,
|
|
8922
8949
|
"anthropic-version": "2023-06-01",
|
|
8923
8950
|
"anthropic-beta": CLAUDE_BETA_FLAGS,
|
|
8924
8951
|
"user-agent": claudeCliUserAgent(cliVersion),
|
|
8925
8952
|
"x-app": "cli",
|
|
8926
8953
|
"anthropic-dangerous-direct-browser-access": "true",
|
|
8927
|
-
|
|
8954
|
+
accept: "text/event-stream",
|
|
8928
8955
|
"content-type": "application/json"
|
|
8929
8956
|
},
|
|
8930
8957
|
body: JSON.stringify(body),
|
|
@@ -9653,10 +9680,10 @@ function codexUsageWindow(value, fallbackKind) {
|
|
|
9653
9680
|
async function fetchCodexUsage(session, fetchFn = hostFetch, signal) {
|
|
9654
9681
|
const response = await fetchFn(CODEX_USAGE_URL, {
|
|
9655
9682
|
headers: {
|
|
9656
|
-
|
|
9683
|
+
authorization: `Bearer ${session.accessToken}`,
|
|
9657
9684
|
"chatgpt-account-id": session.accountId,
|
|
9658
|
-
|
|
9659
|
-
|
|
9685
|
+
originator: "codex_cli_rs",
|
|
9686
|
+
accept: "application/json",
|
|
9660
9687
|
...attributionHeaders()
|
|
9661
9688
|
},
|
|
9662
9689
|
...signal === void 0 ? {} : { signal }
|
|
@@ -9707,10 +9734,10 @@ async function fetchCodexModels(session, fetchFn = hostFetch, signal, clientVers
|
|
|
9707
9734
|
const version = codexClientVersion(clientVersion);
|
|
9708
9735
|
const response = await fetchFn(`${CODEX_MODELS_URL}?client_version=${encodeURIComponent(version)}`, {
|
|
9709
9736
|
headers: {
|
|
9710
|
-
|
|
9737
|
+
authorization: `Bearer ${session.accessToken}`,
|
|
9711
9738
|
"chatgpt-account-id": session.accountId,
|
|
9712
|
-
|
|
9713
|
-
|
|
9739
|
+
originator: "codex_cli_rs",
|
|
9740
|
+
accept: "application/json",
|
|
9714
9741
|
...attributionHeaders()
|
|
9715
9742
|
},
|
|
9716
9743
|
...signal === void 0 ? {} : { signal }
|
|
@@ -10101,11 +10128,11 @@ var CodexAdapter = class extends LlmAdapter {
|
|
|
10101
10128
|
return hostFetch(CODEX_API_URL, {
|
|
10102
10129
|
method: "POST",
|
|
10103
10130
|
headers: {
|
|
10104
|
-
|
|
10131
|
+
authorization: `Bearer ${session.accessToken}`,
|
|
10105
10132
|
"chatgpt-account-id": session.accountId,
|
|
10106
|
-
|
|
10133
|
+
originator: "codex_cli_rs",
|
|
10107
10134
|
"session-id": deterministicSessionId(options.sessionId),
|
|
10108
|
-
|
|
10135
|
+
accept: "text/event-stream",
|
|
10109
10136
|
"content-type": "application/json",
|
|
10110
10137
|
...attributionHeaders()
|
|
10111
10138
|
},
|
|
@@ -10185,10 +10212,10 @@ var CodexWebSearchProvider = class {
|
|
|
10185
10212
|
response = await fetchFn(CODEX_SEARCH_URL, {
|
|
10186
10213
|
method: "POST",
|
|
10187
10214
|
headers: {
|
|
10188
|
-
|
|
10215
|
+
authorization: `Bearer ${session.accessToken}`,
|
|
10189
10216
|
"chatgpt-account-id": session.accountId,
|
|
10190
10217
|
"content-type": "application/json",
|
|
10191
|
-
|
|
10218
|
+
originator: "codex_cli_rs",
|
|
10192
10219
|
...attributionHeaders()
|
|
10193
10220
|
},
|
|
10194
10221
|
body: JSON.stringify(body),
|
|
@@ -10769,7 +10796,7 @@ var PoolAdapter = class extends LlmAdapter {
|
|
|
10769
10796
|
if (definition === void 0) throw new LlmError(`unknown pool model "${options.model}"`, "NO_ADAPTER");
|
|
10770
10797
|
const members = await this.concrete(definition.members);
|
|
10771
10798
|
const candidates = await this.select(options.model, members, options.sessionId);
|
|
10772
|
-
if (candidates.length === 0) throw this.
|
|
10799
|
+
if (candidates.length === 0) throw this.exhaustedWithWarn(options.model, members);
|
|
10773
10800
|
const failures = [];
|
|
10774
10801
|
for (const member of candidates) {
|
|
10775
10802
|
const adapter = this.options.adapters[member.provider];
|
|
@@ -10804,7 +10831,7 @@ var PoolAdapter = class extends LlmAdapter {
|
|
|
10804
10831
|
}
|
|
10805
10832
|
return;
|
|
10806
10833
|
}
|
|
10807
|
-
throw this.
|
|
10834
|
+
throw this.exhaustedWithWarn(options.model, members, failures);
|
|
10808
10835
|
}
|
|
10809
10836
|
/**
|
|
10810
10837
|
* Order the candidates for one request. Health filters both strategies;
|
|
@@ -10845,6 +10872,18 @@ var PoolAdapter = class extends LlmAdapter {
|
|
|
10845
10872
|
}
|
|
10846
10873
|
this.sticky.set(key, memberKey(member.provider, member.account, member.model));
|
|
10847
10874
|
}
|
|
10875
|
+
/**
|
|
10876
|
+
* Build the terminal exhaustion error and log it. Per-member failovers are
|
|
10877
|
+
* already warned above; without this line dsh.log shows the failover chain
|
|
10878
|
+
* but not the exhaustion that ends it. The message carries only the
|
|
10879
|
+
* LlmError's own sanitized text and code — raw provider payloads never
|
|
10880
|
+
* reach here (see the note in {@link exhausted}).
|
|
10881
|
+
*/
|
|
10882
|
+
exhaustedWithWarn(model, pool, failures = []) {
|
|
10883
|
+
const error = this.exhausted(model, pool, failures);
|
|
10884
|
+
this.options.onWarn(`pool "${model}": exhausted (${error.code}: ${error.message})`);
|
|
10885
|
+
return error;
|
|
10886
|
+
}
|
|
10848
10887
|
/** Report attempt failures or this pool's active cooldowns, never unrelated health records. */
|
|
10849
10888
|
exhausted(model, pool, failures = []) {
|
|
10850
10889
|
if (pool.length === 0) return new LlmError(`pool "${model}" has no usable member: no account could be resolved`, "NO_ADAPTER");
|
|
@@ -11647,9 +11686,9 @@ function grokResetsAt(value) {
|
|
|
11647
11686
|
async function fetchGrokUsage(session, fetchFn = hostFetch, signal) {
|
|
11648
11687
|
const response = await fetchFn(GROK_BILLING_URL, {
|
|
11649
11688
|
headers: {
|
|
11650
|
-
|
|
11689
|
+
authorization: `Bearer ${session.accessToken}`,
|
|
11651
11690
|
"x-xai-token-auth": "xai-grok-cli",
|
|
11652
|
-
|
|
11691
|
+
accept: "application/json",
|
|
11653
11692
|
...attributionHeaders()
|
|
11654
11693
|
},
|
|
11655
11694
|
...signal === void 0 ? {} : { signal }
|
|
@@ -11726,9 +11765,9 @@ function grokCliReasoning(entry) {
|
|
|
11726
11765
|
async function fetchGrokCliCatalog(session, fetchFn = hostFetch, signal) {
|
|
11727
11766
|
const response = await fetchFn(GROK_CLI_MODELS_URL, {
|
|
11728
11767
|
headers: {
|
|
11729
|
-
|
|
11768
|
+
authorization: `Bearer ${session.accessToken}`,
|
|
11730
11769
|
"x-xai-token-auth": "xai-grok-cli",
|
|
11731
|
-
|
|
11770
|
+
accept: "application/json",
|
|
11732
11771
|
...attributionHeaders()
|
|
11733
11772
|
},
|
|
11734
11773
|
...signal === void 0 ? {} : { signal }
|
|
@@ -11792,8 +11831,8 @@ async function fetchGrokModels(session, fetchFn = hostFetch, onWarn, previous, s
|
|
|
11792
11831
|
const previousById = previous === void 0 || previous.length === 0 ? void 0 : new Map(previous.map((model) => [model.id, model]));
|
|
11793
11832
|
const [response, cliCatalog] = await Promise.all([fetchFn(GROK_MODELS_URL, {
|
|
11794
11833
|
headers: {
|
|
11795
|
-
|
|
11796
|
-
|
|
11834
|
+
authorization: `Bearer ${session.accessToken}`,
|
|
11835
|
+
accept: "application/json",
|
|
11797
11836
|
...attributionHeaders()
|
|
11798
11837
|
},
|
|
11799
11838
|
...signal === void 0 ? {} : { signal }
|
|
@@ -12017,8 +12056,8 @@ var GrokAdapter = class extends LlmAdapter {
|
|
|
12017
12056
|
return hostFetch(GROK_API_URL, {
|
|
12018
12057
|
method: "POST",
|
|
12019
12058
|
headers: {
|
|
12020
|
-
|
|
12021
|
-
|
|
12059
|
+
authorization: `Bearer ${session.accessToken}`,
|
|
12060
|
+
accept: "text/event-stream",
|
|
12022
12061
|
"content-type": "application/json",
|
|
12023
12062
|
...attributionHeaders()
|
|
12024
12063
|
},
|
|
@@ -12131,8 +12170,8 @@ function copilotHeaders(hasVision = false, vscodeVersion = FALLBACK_VSCODE_VERSI
|
|
|
12131
12170
|
*/
|
|
12132
12171
|
async function exchangeCopilotToken(githubToken, fetchFn = hostFetch) {
|
|
12133
12172
|
const response = await fetchFn(COPILOT_TOKEN_URL, { headers: {
|
|
12134
|
-
|
|
12135
|
-
|
|
12173
|
+
authorization: `Bearer ${githubToken}`,
|
|
12174
|
+
accept: "application/json",
|
|
12136
12175
|
...copilotHeaders(false, await latestVsCodeVersion(fetchFn))
|
|
12137
12176
|
} });
|
|
12138
12177
|
if (!response.ok) throw await oauthEndpointError(response, "copilot");
|
|
@@ -12155,8 +12194,8 @@ async function completeCopilotLogin(githubToken, fetchFn = hostFetch) {
|
|
|
12155
12194
|
let account;
|
|
12156
12195
|
try {
|
|
12157
12196
|
const response = await fetchFn(GITHUB_USER_URL, { headers: {
|
|
12158
|
-
|
|
12159
|
-
|
|
12197
|
+
authorization: `Bearer ${githubToken}`,
|
|
12198
|
+
accept: "application/json",
|
|
12160
12199
|
"user-agent": "GitHubCopilotChat/0.35.0"
|
|
12161
12200
|
} });
|
|
12162
12201
|
if (response.ok) {
|
|
@@ -12240,8 +12279,8 @@ function copilotReasoning(entry) {
|
|
|
12240
12279
|
async function fetchCopilotModels(session, fetchFn = hostFetch, signal) {
|
|
12241
12280
|
const response = await fetchFn(COPILOT_MODELS_URL, {
|
|
12242
12281
|
headers: {
|
|
12243
|
-
|
|
12244
|
-
|
|
12282
|
+
authorization: `Bearer ${session.accessToken}`,
|
|
12283
|
+
accept: "application/json",
|
|
12245
12284
|
...copilotHeaders(false, await latestVsCodeVersion(fetchFn))
|
|
12246
12285
|
},
|
|
12247
12286
|
...signal === void 0 ? {} : { signal }
|
|
@@ -12757,8 +12796,8 @@ var CopilotAdapter = class CopilotAdapter extends LlmAdapter {
|
|
|
12757
12796
|
return hostFetch(wire === "responses" ? COPILOT_RESPONSES_URL : COPILOT_API_URL, {
|
|
12758
12797
|
method: "POST",
|
|
12759
12798
|
headers: {
|
|
12760
|
-
|
|
12761
|
-
|
|
12799
|
+
authorization: `Bearer ${session.accessToken}`,
|
|
12800
|
+
accept: "text/event-stream",
|
|
12762
12801
|
"content-type": "application/json",
|
|
12763
12802
|
...copilotHeaders(hasVision, await latestVsCodeVersion(this.options.fetchFn ?? hostFetch))
|
|
12764
12803
|
},
|
|
@@ -13432,7 +13471,7 @@ function antigravityFlow(oauth) {
|
|
|
13432
13471
|
/** Shared Antigravity API headers. */
|
|
13433
13472
|
function antigravityHeaders(accessToken, userAgent = ANTIGRAVITY_DEFAULT_USER_AGENT) {
|
|
13434
13473
|
return {
|
|
13435
|
-
|
|
13474
|
+
authorization: `Bearer ${accessToken}`,
|
|
13436
13475
|
"content-type": "application/json",
|
|
13437
13476
|
"user-agent": userAgent
|
|
13438
13477
|
};
|
|
@@ -13951,9 +13990,9 @@ function createXSearchTool(options) {
|
|
|
13951
13990
|
const response = await (options.fetchFn ?? hostFetch)(X_SEARCH_URL, {
|
|
13952
13991
|
method: "POST",
|
|
13953
13992
|
headers: {
|
|
13954
|
-
|
|
13993
|
+
authorization: `Bearer ${session.accessToken}`,
|
|
13955
13994
|
"content-type": "application/json",
|
|
13956
|
-
|
|
13995
|
+
accept: "application/json"
|
|
13957
13996
|
},
|
|
13958
13997
|
body: JSON.stringify({
|
|
13959
13998
|
model: X_SEARCH_MODEL,
|
|
@@ -14033,7 +14072,7 @@ const GROK_ASPECT_RATIOS = {
|
|
|
14033
14072
|
"1024x1024": "1:1",
|
|
14034
14073
|
"1024x1536": "2:3",
|
|
14035
14074
|
"1536x1024": "3:2",
|
|
14036
|
-
|
|
14075
|
+
auto: "auto"
|
|
14037
14076
|
};
|
|
14038
14077
|
/**
|
|
14039
14078
|
* Assemble the grok request body from the same tool arguments: `size` maps
|
|
@@ -14319,11 +14358,11 @@ function createImageGenerateTool(options) {
|
|
|
14319
14358
|
send: (session) => fetchFn(references === void 0 ? IMAGE_GENERATE_URL : IMAGE_EDIT_URL, {
|
|
14320
14359
|
method: "POST",
|
|
14321
14360
|
headers: {
|
|
14322
|
-
|
|
14361
|
+
authorization: `Bearer ${session.accessToken}`,
|
|
14323
14362
|
"chatgpt-account-id": session.accountId,
|
|
14324
|
-
|
|
14363
|
+
originator: "codex_cli_rs",
|
|
14325
14364
|
"content-type": "application/json",
|
|
14326
|
-
|
|
14365
|
+
accept: "application/json"
|
|
14327
14366
|
},
|
|
14328
14367
|
body: JSON.stringify({
|
|
14329
14368
|
...buildImageGenerateBody(args),
|
|
@@ -14341,9 +14380,9 @@ function createImageGenerateTool(options) {
|
|
|
14341
14380
|
send: (session) => fetchFn(references === void 0 ? GROK_IMAGE_GENERATE_URL : GROK_IMAGE_EDIT_URL, {
|
|
14342
14381
|
method: "POST",
|
|
14343
14382
|
headers: {
|
|
14344
|
-
|
|
14383
|
+
authorization: `Bearer ${session.accessToken}`,
|
|
14345
14384
|
"content-type": "application/json",
|
|
14346
|
-
|
|
14385
|
+
accept: "application/json"
|
|
14347
14386
|
},
|
|
14348
14387
|
body: JSON.stringify({
|
|
14349
14388
|
...buildGrokImageGenerateBody(args),
|
|
@@ -14602,8 +14641,8 @@ function createVideoGenerateTool(options) {
|
|
|
14602
14641
|
const session = await options.tokens.session();
|
|
14603
14642
|
const fetchFn = options.fetchFn ?? hostFetch;
|
|
14604
14643
|
const headers = {
|
|
14605
|
-
|
|
14606
|
-
|
|
14644
|
+
authorization: `Bearer ${session.accessToken}`,
|
|
14645
|
+
accept: "application/json"
|
|
14607
14646
|
};
|
|
14608
14647
|
const submit = await fetchFn(VIDEO_GENERATE_URL, {
|
|
14609
14648
|
method: "POST",
|
|
@@ -14705,6 +14744,11 @@ function validatePreferences(provider, input) {
|
|
|
14705
14744
|
result.contextWindows[model] = value;
|
|
14706
14745
|
}
|
|
14707
14746
|
}
|
|
14747
|
+
if (raw.promptCacheTtl !== void 0) {
|
|
14748
|
+
if (provider !== "claude") throw new Error("the prompt-cache TTL override is supported only for Claude");
|
|
14749
|
+
if (raw.promptCacheTtl !== "5m" && raw.promptCacheTtl !== "1h") throw new Error("promptCacheTtl must be \"5m\" or \"1h\"");
|
|
14750
|
+
result.promptCacheTtl = raw.promptCacheTtl;
|
|
14751
|
+
}
|
|
14708
14752
|
if (raw.tools !== void 0) {
|
|
14709
14753
|
if (!raw.tools || typeof raw.tools !== "object" || Array.isArray(raw.tools)) throw new Error("tools must be an object");
|
|
14710
14754
|
result.tools = {};
|
|
@@ -14753,6 +14797,14 @@ var ProviderSettingsStore = class {
|
|
|
14753
14797
|
const windows = this.current.providers[provider]?.contextWindows;
|
|
14754
14798
|
return windows && Object.hasOwn(windows, model) ? windows[model] : void 0;
|
|
14755
14799
|
}
|
|
14800
|
+
/**
|
|
14801
|
+
* The Claude route's prompt-cache TTL override, read live so a saved change
|
|
14802
|
+
* takes effect from the next request without a restart. Absent means follow
|
|
14803
|
+
* the `claudePromptCacheTtl` config.
|
|
14804
|
+
*/
|
|
14805
|
+
promptCacheTtl() {
|
|
14806
|
+
return this.current.providers.claude?.promptCacheTtl;
|
|
14807
|
+
}
|
|
14756
14808
|
/** Creation-time policy survives restarts and never changes an existing session. */
|
|
14757
14809
|
toolEnabled(provider, tool, createdAt = Date.now()) {
|
|
14758
14810
|
let enabled = true;
|
|
@@ -15064,7 +15116,7 @@ var SubscriptionsAuthController = class {
|
|
|
15064
15116
|
* cannot be read off the flow manager.
|
|
15065
15117
|
*/
|
|
15066
15118
|
claims = /* @__PURE__ */ new Map();
|
|
15067
|
-
constructor(flows, deviceFlows, onAuthChanged, resolveAttachments, usageFetchers = {}, readClaudeCreds = readClaudeCodeCredentials, poolUsage = void 0, antigravityConfig = {}, clientVersions = {}, resetRedemption) {
|
|
15119
|
+
constructor(flows, deviceFlows, onAuthChanged, resolveAttachments, usageFetchers = {}, readClaudeCreds = readClaudeCodeCredentials, poolUsage = void 0, antigravityConfig = {}, clientVersions = {}, resetRedemption, onUsageForced) {
|
|
15068
15120
|
this.flows = flows;
|
|
15069
15121
|
this.deviceFlows = deviceFlows;
|
|
15070
15122
|
this.onAuthChanged = onAuthChanged;
|
|
@@ -15075,6 +15127,7 @@ var SubscriptionsAuthController = class {
|
|
|
15075
15127
|
this.antigravityConfig = antigravityConfig;
|
|
15076
15128
|
this.clientVersions = clientVersions;
|
|
15077
15129
|
this.resetRedemption = resetRedemption;
|
|
15130
|
+
this.onUsageForced = onUsageForced;
|
|
15078
15131
|
}
|
|
15079
15132
|
prepareReset(account, signal) {
|
|
15080
15133
|
if (!this.resetRedemption) throw new BadRequest("Reset redemption unavailable");
|
|
@@ -15085,6 +15138,7 @@ var SubscriptionsAuthController = class {
|
|
|
15085
15138
|
await this.resetRedemption.redeem(account, ticket, AbortSignal.any([signal, AbortSignal.timeout(2e4)]));
|
|
15086
15139
|
}
|
|
15087
15140
|
usage(provider, account, signal, force = false) {
|
|
15141
|
+
if (force) this.onUsageForced?.(provider, account);
|
|
15088
15142
|
const fetcher = this.usageFetchers[provider];
|
|
15089
15143
|
if (fetcher === void 0) return Promise.resolve({ supported: false });
|
|
15090
15144
|
if (this.poolUsage === void 0) return fetcher(account, signal);
|
|
@@ -15397,8 +15451,7 @@ function apply(ctx, config) {
|
|
|
15397
15451
|
};
|
|
15398
15452
|
}
|
|
15399
15453
|
};
|
|
15400
|
-
|
|
15401
|
-
adapter = new CodexAdapter({
|
|
15454
|
+
const adapter = new CodexAdapter({
|
|
15402
15455
|
...config.codexClientVersion === void 0 ? {} : { clientVersion: config.codexClientVersion },
|
|
15403
15456
|
resolveClientVersion: () => codexVersion.resolve(),
|
|
15404
15457
|
models: catalog.codex,
|
|
@@ -15449,6 +15502,7 @@ function apply(ctx, config) {
|
|
|
15449
15502
|
contextWindowOf: (model) => preferences.contextWindow(model, "claude"),
|
|
15450
15503
|
resolveCliVersion: () => claudeVersion.resolve(),
|
|
15451
15504
|
promptCacheTtl: claudePromptCacheTtl,
|
|
15505
|
+
promptCacheTtlOverride: () => preferences.promptCacheTtl(),
|
|
15452
15506
|
pool: () => poolAdapter
|
|
15453
15507
|
});
|
|
15454
15508
|
claudeAdapter = adapter;
|
|
@@ -15661,7 +15715,7 @@ function apply(ctx, config) {
|
|
|
15661
15715
|
const catalog$1 = [];
|
|
15662
15716
|
for (const provider of PROVIDER_IDS) {
|
|
15663
15717
|
if (!visible.has(provider)) continue;
|
|
15664
|
-
let models
|
|
15718
|
+
let models;
|
|
15665
15719
|
try {
|
|
15666
15720
|
models = await ctx.llm.listModels(provider);
|
|
15667
15721
|
} catch {
|
|
@@ -15776,7 +15830,7 @@ function apply(ctx, config) {
|
|
|
15776
15830
|
source: "config"
|
|
15777
15831
|
}) } : {},
|
|
15778
15832
|
...providers.includes("claude") ? { claude: presentedVersion(claudeVersion) } : {}
|
|
15779
|
-
}, resetRedemption), speed, modelDefaults, {
|
|
15833
|
+
}, resetRedemption, (provider, account) => poolHealth?.clear(provider, account)), speed, modelDefaults, {
|
|
15780
15834
|
async get(provider, force) {
|
|
15781
15835
|
await loadModelDefaults();
|
|
15782
15836
|
const adapter = adapters.get(provider);
|
package/lib/model-defaults.js
CHANGED
|
@@ -163,7 +163,9 @@ export function defaultEffortOf(provider, model) {
|
|
|
163
163
|
// plain index would inherit from Object.prototype for names like
|
|
164
164
|
// `toString`, handing a *function* to mergeReasoning (which then throws and
|
|
165
165
|
// breaks that model's resolution).
|
|
166
|
-
return Object.prototype.hasOwnProperty.call(section, model)
|
|
166
|
+
return Object.prototype.hasOwnProperty.call(section, model)
|
|
167
|
+
? section[model]
|
|
168
|
+
: undefined;
|
|
167
169
|
}
|
|
168
170
|
/**
|
|
169
171
|
* Detached snapshot for store assertions in tests; no production RPC uses it.
|
|
@@ -193,7 +195,7 @@ export function setDefaultEffort(provider, model, effort) {
|
|
|
193
195
|
// shared chain.
|
|
194
196
|
const run = writeChain.then(async () => {
|
|
195
197
|
await ensureReady();
|
|
196
|
-
const section = { ...sectionOf(current, provider) ?? {} };
|
|
198
|
+
const section = { ...(sectionOf(current, provider) ?? {}) };
|
|
197
199
|
if (effort === undefined) {
|
|
198
200
|
delete section[model];
|
|
199
201
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type ProviderId } from './auth/store.js';
|
|
2
|
+
import type { PromptCacheTtl } from './translate/anthropic.js';
|
|
2
3
|
export declare const PROVIDER_TOOLS: {
|
|
3
4
|
readonly codex: readonly ["image_generate", "web_search"];
|
|
4
5
|
readonly claude: readonly [];
|
|
@@ -22,6 +23,11 @@ export interface ProviderPreferences {
|
|
|
22
23
|
visibleModels?: string[];
|
|
23
24
|
contextWindows?: Record<string, number>;
|
|
24
25
|
tools?: Partial<Record<SubscriptionTool, boolean>>;
|
|
26
|
+
/**
|
|
27
|
+
* Claude only: overrides the `claudePromptCacheTtl` plugin config for this
|
|
28
|
+
* route. Absent follows the configured TTL.
|
|
29
|
+
*/
|
|
30
|
+
promptCacheTtl?: PromptCacheTtl;
|
|
25
31
|
}
|
|
26
32
|
export declare function validatePreferences(provider: ProviderId, input: unknown): ProviderPreferences;
|
|
27
33
|
/** Durable user preferences, independent of expiring discovery caches. */
|
|
@@ -34,6 +40,12 @@ export declare class ProviderSettingsStore {
|
|
|
34
40
|
visible(provider: ProviderId, model: string): boolean;
|
|
35
41
|
/** The user's local context-window override for one model; absent follows the provider. */
|
|
36
42
|
contextWindow(model: string, provider?: ProviderId): number | undefined;
|
|
43
|
+
/**
|
|
44
|
+
* The Claude route's prompt-cache TTL override, read live so a saved change
|
|
45
|
+
* takes effect from the next request without a restart. Absent means follow
|
|
46
|
+
* the `claudePromptCacheTtl` config.
|
|
47
|
+
*/
|
|
48
|
+
promptCacheTtl(): PromptCacheTtl | undefined;
|
|
37
49
|
/** Creation-time policy survives restarts and never changes an existing session. */
|
|
38
50
|
toolEnabled(provider: ProviderId, tool: SubscriptionTool, createdAt?: number): boolean;
|
|
39
51
|
set(provider: ProviderId, input: unknown): Promise<void>;
|