dsh-subscriptions 0.2.0 → 0.2.3
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 +220 -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.d.ts +8 -4
- package/lib/auth/rpc.js +89 -25
- 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 +137 -34
- package/lib/client/SpeedSelect.d.ts +62 -14
- package/lib/client/SpeedSelect.js +261 -49
- package/lib/client/SubscriptionUsageBadge.d.ts +4 -10
- package/lib/client/SubscriptionUsageBadge.js +300 -112
- package/lib/client/SubscriptionsSection.d.ts +2 -0
- package/lib/client/SubscriptionsSection.js +265 -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 +22 -0
- package/lib/client/locales.js +73 -51
- package/lib/client/model-filter.d.ts +37 -0
- package/lib/client/model-filter.js +45 -0
- 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/usage-window-filter.d.ts +7 -0
- package/lib/client/usage-window-filter.js +12 -0
- package/lib/client.js +480 -136
- package/lib/client.js.map +1 -1
- package/lib/http.js +1 -1
- package/lib/index.d.ts +3 -3
- package/lib/index.js +167 -76
- package/lib/model-defaults.js +4 -2
- package/lib/provider-settings.d.ts +17 -0
- package/lib/provider-settings.js +79 -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 +151 -52
- 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 +27 -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
|
};
|
|
@@ -3834,7 +3834,13 @@ async function dispatch(controller, speed, modelDefaults, endpoint, payload, sig
|
|
|
3834
3834
|
accounts: [],
|
|
3835
3835
|
detail: error instanceof Error ? error.message : String(error)
|
|
3836
3836
|
}))]));
|
|
3837
|
-
return ok({ providers: Object.fromEntries(entries)
|
|
3837
|
+
return ok({ providers: Object.fromEntries(entries.map(([provider, status]) => {
|
|
3838
|
+
const visibleModels = providerSettings?.visibleModels?.(provider);
|
|
3839
|
+
return [provider, {
|
|
3840
|
+
...status,
|
|
3841
|
+
...visibleModels === void 0 ? {} : { visibleModels }
|
|
3842
|
+
}];
|
|
3843
|
+
})) });
|
|
3838
3844
|
}
|
|
3839
3845
|
case "login": {
|
|
3840
3846
|
const provider = readProvider(payload);
|
|
@@ -3931,7 +3937,7 @@ async function dispatch(controller, speed, modelDefaults, endpoint, payload, sig
|
|
|
3931
3937
|
return ok({ ok: true });
|
|
3932
3938
|
case "image": return ok(await controller.readImage(readImageRef(payload), signal));
|
|
3933
3939
|
case "video": return ok(await controller.readVideo(readVideoName(payload), signal));
|
|
3934
|
-
case "speed": return ok(await speed.speed(readSessionId(payload)));
|
|
3940
|
+
case "speed": return ok(await speed.speed(readSessionId(payload), payload.model === void 0 ? void 0 : readString(payload, "model")));
|
|
3935
3941
|
case "setSpeed":
|
|
3936
3942
|
await speed.setSpeed(readSessionId(payload), readSpeedTier(payload));
|
|
3937
3943
|
return ok({ ok: true });
|
|
@@ -6950,8 +6956,8 @@ async function postJson(url, apiKey, payload, options, signal) {
|
|
|
6950
6956
|
method: "POST",
|
|
6951
6957
|
headers: {
|
|
6952
6958
|
"content-type": "application/json",
|
|
6953
|
-
|
|
6954
|
-
|
|
6959
|
+
accept: "application/json",
|
|
6960
|
+
authorization: `Bearer ${apiKey}`,
|
|
6955
6961
|
...attributionHeaders()
|
|
6956
6962
|
},
|
|
6957
6963
|
body: JSON.stringify(payload),
|
|
@@ -8008,13 +8014,39 @@ async function readCatalogFile(path) {
|
|
|
8008
8014
|
return {};
|
|
8009
8015
|
}
|
|
8010
8016
|
}
|
|
8017
|
+
/**
|
|
8018
|
+
* Windows refuses to replace a file another handle holds open without
|
|
8019
|
+
* `FILE_SHARE_DELETE` (an indexer, antivirus scan, or a second dsh profile
|
|
8020
|
+
* reading the cache), surfacing as a transient `EPERM`/`EBUSY`/`EACCES` on
|
|
8021
|
+
* `rename` (V1ki/dsh-plugin-subscriptions#129). On Windows only, retry
|
|
8022
|
+
* briefly before giving the write up: on POSIX those codes are real
|
|
8023
|
+
* failures, so retrying would only delay surfacing them.
|
|
8024
|
+
*/
|
|
8025
|
+
const RENAME_RETRY_CODES = new Set([
|
|
8026
|
+
"EPERM",
|
|
8027
|
+
"EBUSY",
|
|
8028
|
+
"EACCES"
|
|
8029
|
+
]);
|
|
8030
|
+
const RENAME_RETRIES = 5;
|
|
8031
|
+
const RENAME_RETRY_DELAY_MS = 20;
|
|
8032
|
+
/** `rename` with a short bounded retry on Windows share-mode conflicts. */
|
|
8033
|
+
async function renameWithRetry(from, to) {
|
|
8034
|
+
for (let attempt = 0;; attempt++) try {
|
|
8035
|
+
await rename(from, to);
|
|
8036
|
+
return;
|
|
8037
|
+
} catch (error) {
|
|
8038
|
+
const code = error.code;
|
|
8039
|
+
if (process.platform !== "win32" || attempt >= RENAME_RETRIES || code === void 0 || !RENAME_RETRY_CODES.has(code)) throw error;
|
|
8040
|
+
await new Promise((resolve$2) => setTimeout(resolve$2, RENAME_RETRY_DELAY_MS * (attempt + 1)));
|
|
8041
|
+
}
|
|
8042
|
+
}
|
|
8011
8043
|
/** Persist the whole file atomically (tmp file + rename). */
|
|
8012
8044
|
async function writeCatalogFile(store, path) {
|
|
8013
8045
|
await mkdir(dirname(path), { recursive: true });
|
|
8014
8046
|
const tmp = `${path}.tmp-${process.pid}-${Math.random().toString(36).slice(2)}`;
|
|
8015
8047
|
try {
|
|
8016
8048
|
await writeFile(tmp, JSON.stringify(store, null, 2));
|
|
8017
|
-
await
|
|
8049
|
+
await renameWithRetry(tmp, path);
|
|
8018
8050
|
} catch (error) {
|
|
8019
8051
|
await rm(tmp, { force: true });
|
|
8020
8052
|
throw error;
|
|
@@ -8550,10 +8582,10 @@ async function fetchClaudeUsage(session, fetchFn = hostFetch, signal, cliVersion
|
|
|
8550
8582
|
const userAgent = claudeCliUserAgent(await cliVersion());
|
|
8551
8583
|
const init = {
|
|
8552
8584
|
headers: {
|
|
8553
|
-
|
|
8585
|
+
authorization: `Bearer ${session.accessToken}`,
|
|
8554
8586
|
"anthropic-beta": "oauth-2025-04-20",
|
|
8555
8587
|
"user-agent": userAgent,
|
|
8556
|
-
|
|
8588
|
+
accept: "application/json"
|
|
8557
8589
|
},
|
|
8558
8590
|
...signal === void 0 ? {} : { signal }
|
|
8559
8591
|
};
|
|
@@ -8625,11 +8657,11 @@ async function fetchClaudeModels(session, fetchFn = hostFetch, signal, cliVersio
|
|
|
8625
8657
|
const userAgent = claudeCliUserAgent(await cliVersion());
|
|
8626
8658
|
const response = await fetchFn(CLAUDE_MODELS_URL, {
|
|
8627
8659
|
headers: {
|
|
8628
|
-
|
|
8660
|
+
authorization: `Bearer ${session.accessToken}`,
|
|
8629
8661
|
"anthropic-version": "2023-06-01",
|
|
8630
8662
|
"user-agent": userAgent,
|
|
8631
8663
|
"anthropic-dangerous-direct-browser-access": "true",
|
|
8632
|
-
|
|
8664
|
+
accept: "application/json"
|
|
8633
8665
|
},
|
|
8634
8666
|
...signal === void 0 ? {} : { signal }
|
|
8635
8667
|
});
|
|
@@ -8697,8 +8729,9 @@ const CLAUDE_MODALITIES = ["text", "image"];
|
|
|
8697
8729
|
* @param effort - the reasoning effort, when the model advertises efforts.
|
|
8698
8730
|
* @param cacheTtl - lifetime of every cache breakpoint; defaults to five minutes.
|
|
8699
8731
|
* Requests that carry a `purpose` (compaction, session titles) always use five
|
|
8700
|
-
* minutes to preserve their existing auxiliary-request behavior
|
|
8701
|
-
*
|
|
8732
|
+
* minutes to preserve their existing auxiliary-request behavior — the override
|
|
8733
|
+
* changes the TTL for ordinary turns only, never the auxiliary floor. A
|
|
8734
|
+
* five-minute mark can still read an entry a one-hour mark wrote.
|
|
8702
8735
|
* @returns the JSON body to POST.
|
|
8703
8736
|
*/
|
|
8704
8737
|
function claudeRequestBody(options, messages, maxTokens, thinking, effort, cacheTtl) {
|
|
@@ -8913,18 +8946,18 @@ var ClaudeAdapter = class extends LlmAdapter {
|
|
|
8913
8946
|
}
|
|
8914
8947
|
const disc = await this.discovered(options.model);
|
|
8915
8948
|
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);
|
|
8949
|
+
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
8950
|
const cliVersion = await (this.options.resolveCliVersion ?? localClaudeCliVersion)();
|
|
8918
8951
|
return hostFetch(CLAUDE_API_URL, {
|
|
8919
8952
|
method: "POST",
|
|
8920
8953
|
headers: {
|
|
8921
|
-
|
|
8954
|
+
authorization: `Bearer ${session.accessToken}`,
|
|
8922
8955
|
"anthropic-version": "2023-06-01",
|
|
8923
8956
|
"anthropic-beta": CLAUDE_BETA_FLAGS,
|
|
8924
8957
|
"user-agent": claudeCliUserAgent(cliVersion),
|
|
8925
8958
|
"x-app": "cli",
|
|
8926
8959
|
"anthropic-dangerous-direct-browser-access": "true",
|
|
8927
|
-
|
|
8960
|
+
accept: "text/event-stream",
|
|
8928
8961
|
"content-type": "application/json"
|
|
8929
8962
|
},
|
|
8930
8963
|
body: JSON.stringify(body),
|
|
@@ -9653,10 +9686,10 @@ function codexUsageWindow(value, fallbackKind) {
|
|
|
9653
9686
|
async function fetchCodexUsage(session, fetchFn = hostFetch, signal) {
|
|
9654
9687
|
const response = await fetchFn(CODEX_USAGE_URL, {
|
|
9655
9688
|
headers: {
|
|
9656
|
-
|
|
9689
|
+
authorization: `Bearer ${session.accessToken}`,
|
|
9657
9690
|
"chatgpt-account-id": session.accountId,
|
|
9658
|
-
|
|
9659
|
-
|
|
9691
|
+
originator: "codex_cli_rs",
|
|
9692
|
+
accept: "application/json",
|
|
9660
9693
|
...attributionHeaders()
|
|
9661
9694
|
},
|
|
9662
9695
|
...signal === void 0 ? {} : { signal }
|
|
@@ -9707,10 +9740,10 @@ async function fetchCodexModels(session, fetchFn = hostFetch, signal, clientVers
|
|
|
9707
9740
|
const version = codexClientVersion(clientVersion);
|
|
9708
9741
|
const response = await fetchFn(`${CODEX_MODELS_URL}?client_version=${encodeURIComponent(version)}`, {
|
|
9709
9742
|
headers: {
|
|
9710
|
-
|
|
9743
|
+
authorization: `Bearer ${session.accessToken}`,
|
|
9711
9744
|
"chatgpt-account-id": session.accountId,
|
|
9712
|
-
|
|
9713
|
-
|
|
9745
|
+
originator: "codex_cli_rs",
|
|
9746
|
+
accept: "application/json",
|
|
9714
9747
|
...attributionHeaders()
|
|
9715
9748
|
},
|
|
9716
9749
|
...signal === void 0 ? {} : { signal }
|
|
@@ -10101,11 +10134,11 @@ var CodexAdapter = class extends LlmAdapter {
|
|
|
10101
10134
|
return hostFetch(CODEX_API_URL, {
|
|
10102
10135
|
method: "POST",
|
|
10103
10136
|
headers: {
|
|
10104
|
-
|
|
10137
|
+
authorization: `Bearer ${session.accessToken}`,
|
|
10105
10138
|
"chatgpt-account-id": session.accountId,
|
|
10106
|
-
|
|
10139
|
+
originator: "codex_cli_rs",
|
|
10107
10140
|
"session-id": deterministicSessionId(options.sessionId),
|
|
10108
|
-
|
|
10141
|
+
accept: "text/event-stream",
|
|
10109
10142
|
"content-type": "application/json",
|
|
10110
10143
|
...attributionHeaders()
|
|
10111
10144
|
},
|
|
@@ -10185,10 +10218,10 @@ var CodexWebSearchProvider = class {
|
|
|
10185
10218
|
response = await fetchFn(CODEX_SEARCH_URL, {
|
|
10186
10219
|
method: "POST",
|
|
10187
10220
|
headers: {
|
|
10188
|
-
|
|
10221
|
+
authorization: `Bearer ${session.accessToken}`,
|
|
10189
10222
|
"chatgpt-account-id": session.accountId,
|
|
10190
10223
|
"content-type": "application/json",
|
|
10191
|
-
|
|
10224
|
+
originator: "codex_cli_rs",
|
|
10192
10225
|
...attributionHeaders()
|
|
10193
10226
|
},
|
|
10194
10227
|
body: JSON.stringify(body),
|
|
@@ -10769,7 +10802,7 @@ var PoolAdapter = class extends LlmAdapter {
|
|
|
10769
10802
|
if (definition === void 0) throw new LlmError(`unknown pool model "${options.model}"`, "NO_ADAPTER");
|
|
10770
10803
|
const members = await this.concrete(definition.members);
|
|
10771
10804
|
const candidates = await this.select(options.model, members, options.sessionId);
|
|
10772
|
-
if (candidates.length === 0) throw this.
|
|
10805
|
+
if (candidates.length === 0) throw this.exhaustedWithWarn(options.model, members);
|
|
10773
10806
|
const failures = [];
|
|
10774
10807
|
for (const member of candidates) {
|
|
10775
10808
|
const adapter = this.options.adapters[member.provider];
|
|
@@ -10804,7 +10837,7 @@ var PoolAdapter = class extends LlmAdapter {
|
|
|
10804
10837
|
}
|
|
10805
10838
|
return;
|
|
10806
10839
|
}
|
|
10807
|
-
throw this.
|
|
10840
|
+
throw this.exhaustedWithWarn(options.model, members, failures);
|
|
10808
10841
|
}
|
|
10809
10842
|
/**
|
|
10810
10843
|
* Order the candidates for one request. Health filters both strategies;
|
|
@@ -10845,6 +10878,18 @@ var PoolAdapter = class extends LlmAdapter {
|
|
|
10845
10878
|
}
|
|
10846
10879
|
this.sticky.set(key, memberKey(member.provider, member.account, member.model));
|
|
10847
10880
|
}
|
|
10881
|
+
/**
|
|
10882
|
+
* Build the terminal exhaustion error and log it. Per-member failovers are
|
|
10883
|
+
* already warned above; without this line dsh.log shows the failover chain
|
|
10884
|
+
* but not the exhaustion that ends it. The message carries only the
|
|
10885
|
+
* LlmError's own sanitized text and code — raw provider payloads never
|
|
10886
|
+
* reach here (see the note in {@link exhausted}).
|
|
10887
|
+
*/
|
|
10888
|
+
exhaustedWithWarn(model, pool, failures = []) {
|
|
10889
|
+
const error = this.exhausted(model, pool, failures);
|
|
10890
|
+
this.options.onWarn(`pool "${model}": exhausted (${error.code}: ${error.message})`);
|
|
10891
|
+
return error;
|
|
10892
|
+
}
|
|
10848
10893
|
/** Report attempt failures or this pool's active cooldowns, never unrelated health records. */
|
|
10849
10894
|
exhausted(model, pool, failures = []) {
|
|
10850
10895
|
if (pool.length === 0) return new LlmError(`pool "${model}" has no usable member: no account could be resolved`, "NO_ADAPTER");
|
|
@@ -11647,9 +11692,9 @@ function grokResetsAt(value) {
|
|
|
11647
11692
|
async function fetchGrokUsage(session, fetchFn = hostFetch, signal) {
|
|
11648
11693
|
const response = await fetchFn(GROK_BILLING_URL, {
|
|
11649
11694
|
headers: {
|
|
11650
|
-
|
|
11695
|
+
authorization: `Bearer ${session.accessToken}`,
|
|
11651
11696
|
"x-xai-token-auth": "xai-grok-cli",
|
|
11652
|
-
|
|
11697
|
+
accept: "application/json",
|
|
11653
11698
|
...attributionHeaders()
|
|
11654
11699
|
},
|
|
11655
11700
|
...signal === void 0 ? {} : { signal }
|
|
@@ -11726,9 +11771,9 @@ function grokCliReasoning(entry) {
|
|
|
11726
11771
|
async function fetchGrokCliCatalog(session, fetchFn = hostFetch, signal) {
|
|
11727
11772
|
const response = await fetchFn(GROK_CLI_MODELS_URL, {
|
|
11728
11773
|
headers: {
|
|
11729
|
-
|
|
11774
|
+
authorization: `Bearer ${session.accessToken}`,
|
|
11730
11775
|
"x-xai-token-auth": "xai-grok-cli",
|
|
11731
|
-
|
|
11776
|
+
accept: "application/json",
|
|
11732
11777
|
...attributionHeaders()
|
|
11733
11778
|
},
|
|
11734
11779
|
...signal === void 0 ? {} : { signal }
|
|
@@ -11792,8 +11837,8 @@ async function fetchGrokModels(session, fetchFn = hostFetch, onWarn, previous, s
|
|
|
11792
11837
|
const previousById = previous === void 0 || previous.length === 0 ? void 0 : new Map(previous.map((model) => [model.id, model]));
|
|
11793
11838
|
const [response, cliCatalog] = await Promise.all([fetchFn(GROK_MODELS_URL, {
|
|
11794
11839
|
headers: {
|
|
11795
|
-
|
|
11796
|
-
|
|
11840
|
+
authorization: `Bearer ${session.accessToken}`,
|
|
11841
|
+
accept: "application/json",
|
|
11797
11842
|
...attributionHeaders()
|
|
11798
11843
|
},
|
|
11799
11844
|
...signal === void 0 ? {} : { signal }
|
|
@@ -12017,8 +12062,8 @@ var GrokAdapter = class extends LlmAdapter {
|
|
|
12017
12062
|
return hostFetch(GROK_API_URL, {
|
|
12018
12063
|
method: "POST",
|
|
12019
12064
|
headers: {
|
|
12020
|
-
|
|
12021
|
-
|
|
12065
|
+
authorization: `Bearer ${session.accessToken}`,
|
|
12066
|
+
accept: "text/event-stream",
|
|
12022
12067
|
"content-type": "application/json",
|
|
12023
12068
|
...attributionHeaders()
|
|
12024
12069
|
},
|
|
@@ -12131,8 +12176,8 @@ function copilotHeaders(hasVision = false, vscodeVersion = FALLBACK_VSCODE_VERSI
|
|
|
12131
12176
|
*/
|
|
12132
12177
|
async function exchangeCopilotToken(githubToken, fetchFn = hostFetch) {
|
|
12133
12178
|
const response = await fetchFn(COPILOT_TOKEN_URL, { headers: {
|
|
12134
|
-
|
|
12135
|
-
|
|
12179
|
+
authorization: `Bearer ${githubToken}`,
|
|
12180
|
+
accept: "application/json",
|
|
12136
12181
|
...copilotHeaders(false, await latestVsCodeVersion(fetchFn))
|
|
12137
12182
|
} });
|
|
12138
12183
|
if (!response.ok) throw await oauthEndpointError(response, "copilot");
|
|
@@ -12155,8 +12200,8 @@ async function completeCopilotLogin(githubToken, fetchFn = hostFetch) {
|
|
|
12155
12200
|
let account;
|
|
12156
12201
|
try {
|
|
12157
12202
|
const response = await fetchFn(GITHUB_USER_URL, { headers: {
|
|
12158
|
-
|
|
12159
|
-
|
|
12203
|
+
authorization: `Bearer ${githubToken}`,
|
|
12204
|
+
accept: "application/json",
|
|
12160
12205
|
"user-agent": "GitHubCopilotChat/0.35.0"
|
|
12161
12206
|
} });
|
|
12162
12207
|
if (response.ok) {
|
|
@@ -12240,8 +12285,8 @@ function copilotReasoning(entry) {
|
|
|
12240
12285
|
async function fetchCopilotModels(session, fetchFn = hostFetch, signal) {
|
|
12241
12286
|
const response = await fetchFn(COPILOT_MODELS_URL, {
|
|
12242
12287
|
headers: {
|
|
12243
|
-
|
|
12244
|
-
|
|
12288
|
+
authorization: `Bearer ${session.accessToken}`,
|
|
12289
|
+
accept: "application/json",
|
|
12245
12290
|
...copilotHeaders(false, await latestVsCodeVersion(fetchFn))
|
|
12246
12291
|
},
|
|
12247
12292
|
...signal === void 0 ? {} : { signal }
|
|
@@ -12757,8 +12802,8 @@ var CopilotAdapter = class CopilotAdapter extends LlmAdapter {
|
|
|
12757
12802
|
return hostFetch(wire === "responses" ? COPILOT_RESPONSES_URL : COPILOT_API_URL, {
|
|
12758
12803
|
method: "POST",
|
|
12759
12804
|
headers: {
|
|
12760
|
-
|
|
12761
|
-
|
|
12805
|
+
authorization: `Bearer ${session.accessToken}`,
|
|
12806
|
+
accept: "text/event-stream",
|
|
12762
12807
|
"content-type": "application/json",
|
|
12763
12808
|
...copilotHeaders(hasVision, await latestVsCodeVersion(this.options.fetchFn ?? hostFetch))
|
|
12764
12809
|
},
|
|
@@ -12999,9 +13044,17 @@ function toAntigravityTools(tools, model = "gemini") {
|
|
|
12999
13044
|
})) }];
|
|
13000
13045
|
}
|
|
13001
13046
|
const SKIP_THOUGHT_SIGNATURE_VALIDATOR = "skip_thought_signature_validator";
|
|
13002
|
-
/**
|
|
13047
|
+
/**
|
|
13048
|
+
* Whether this model validates thought signatures on replayed function calls.
|
|
13049
|
+
*
|
|
13050
|
+
* Gemini 3 and 4 require a signature on the first function call of each step;
|
|
13051
|
+
* foreign history uses the documented placeholder when no signature can be reused.
|
|
13052
|
+
* https://ai.google.dev/gemini-api/docs/generate-content/thought-signatures
|
|
13053
|
+
* Keep this scoped to these model families; future versions and unversioned aliases
|
|
13054
|
+
* need verification before enabling the same fallback.
|
|
13055
|
+
*/
|
|
13003
13056
|
function requiresThoughtSignatures(model) {
|
|
13004
|
-
return model !== void 0 && /^gemini-
|
|
13057
|
+
return model !== void 0 && /^gemini-[34](?:[.-]|$)/i.test(model.trim());
|
|
13005
13058
|
}
|
|
13006
13059
|
/**
|
|
13007
13060
|
* Convert resolved harness messages into Gemini contents. Function response
|
|
@@ -13432,7 +13485,7 @@ function antigravityFlow(oauth) {
|
|
|
13432
13485
|
/** Shared Antigravity API headers. */
|
|
13433
13486
|
function antigravityHeaders(accessToken, userAgent = ANTIGRAVITY_DEFAULT_USER_AGENT) {
|
|
13434
13487
|
return {
|
|
13435
|
-
|
|
13488
|
+
authorization: `Bearer ${accessToken}`,
|
|
13436
13489
|
"content-type": "application/json",
|
|
13437
13490
|
"user-agent": userAgent
|
|
13438
13491
|
};
|
|
@@ -13951,9 +14004,9 @@ function createXSearchTool(options) {
|
|
|
13951
14004
|
const response = await (options.fetchFn ?? hostFetch)(X_SEARCH_URL, {
|
|
13952
14005
|
method: "POST",
|
|
13953
14006
|
headers: {
|
|
13954
|
-
|
|
14007
|
+
authorization: `Bearer ${session.accessToken}`,
|
|
13955
14008
|
"content-type": "application/json",
|
|
13956
|
-
|
|
14009
|
+
accept: "application/json"
|
|
13957
14010
|
},
|
|
13958
14011
|
body: JSON.stringify({
|
|
13959
14012
|
model: X_SEARCH_MODEL,
|
|
@@ -14033,7 +14086,7 @@ const GROK_ASPECT_RATIOS = {
|
|
|
14033
14086
|
"1024x1024": "1:1",
|
|
14034
14087
|
"1024x1536": "2:3",
|
|
14035
14088
|
"1536x1024": "3:2",
|
|
14036
|
-
|
|
14089
|
+
auto: "auto"
|
|
14037
14090
|
};
|
|
14038
14091
|
/**
|
|
14039
14092
|
* Assemble the grok request body from the same tool arguments: `size` maps
|
|
@@ -14319,11 +14372,11 @@ function createImageGenerateTool(options) {
|
|
|
14319
14372
|
send: (session) => fetchFn(references === void 0 ? IMAGE_GENERATE_URL : IMAGE_EDIT_URL, {
|
|
14320
14373
|
method: "POST",
|
|
14321
14374
|
headers: {
|
|
14322
|
-
|
|
14375
|
+
authorization: `Bearer ${session.accessToken}`,
|
|
14323
14376
|
"chatgpt-account-id": session.accountId,
|
|
14324
|
-
|
|
14377
|
+
originator: "codex_cli_rs",
|
|
14325
14378
|
"content-type": "application/json",
|
|
14326
|
-
|
|
14379
|
+
accept: "application/json"
|
|
14327
14380
|
},
|
|
14328
14381
|
body: JSON.stringify({
|
|
14329
14382
|
...buildImageGenerateBody(args),
|
|
@@ -14341,9 +14394,9 @@ function createImageGenerateTool(options) {
|
|
|
14341
14394
|
send: (session) => fetchFn(references === void 0 ? GROK_IMAGE_GENERATE_URL : GROK_IMAGE_EDIT_URL, {
|
|
14342
14395
|
method: "POST",
|
|
14343
14396
|
headers: {
|
|
14344
|
-
|
|
14397
|
+
authorization: `Bearer ${session.accessToken}`,
|
|
14345
14398
|
"content-type": "application/json",
|
|
14346
|
-
|
|
14399
|
+
accept: "application/json"
|
|
14347
14400
|
},
|
|
14348
14401
|
body: JSON.stringify({
|
|
14349
14402
|
...buildGrokImageGenerateBody(args),
|
|
@@ -14602,8 +14655,8 @@ function createVideoGenerateTool(options) {
|
|
|
14602
14655
|
const session = await options.tokens.session();
|
|
14603
14656
|
const fetchFn = options.fetchFn ?? hostFetch;
|
|
14604
14657
|
const headers = {
|
|
14605
|
-
|
|
14606
|
-
|
|
14658
|
+
authorization: `Bearer ${session.accessToken}`,
|
|
14659
|
+
accept: "application/json"
|
|
14607
14660
|
};
|
|
14608
14661
|
const submit = await fetchFn(VIDEO_GENERATE_URL, {
|
|
14609
14662
|
method: "POST",
|
|
@@ -14705,6 +14758,20 @@ function validatePreferences(provider, input) {
|
|
|
14705
14758
|
result.contextWindows[model] = value;
|
|
14706
14759
|
}
|
|
14707
14760
|
}
|
|
14761
|
+
if (raw.promptCacheTtl !== void 0) {
|
|
14762
|
+
if (provider !== "claude") throw new Error("the prompt-cache TTL override is supported only for Claude");
|
|
14763
|
+
if (raw.promptCacheTtl !== "5m" && raw.promptCacheTtl !== "1h") throw new Error("promptCacheTtl must be \"5m\" or \"1h\"");
|
|
14764
|
+
result.promptCacheTtl = raw.promptCacheTtl;
|
|
14765
|
+
}
|
|
14766
|
+
if (raw.subagentSpeeds !== void 0) {
|
|
14767
|
+
if (provider !== "codex") throw new Error("subagent speeds are currently supported only for Codex");
|
|
14768
|
+
if (!raw.subagentSpeeds || typeof raw.subagentSpeeds !== "object" || Array.isArray(raw.subagentSpeeds)) throw new Error("subagent speeds must be a model-to-speed map");
|
|
14769
|
+
result.subagentSpeeds = Object.create(null);
|
|
14770
|
+
for (const [model, tier] of Object.entries(raw.subagentSpeeds)) {
|
|
14771
|
+
if (!model.trim() || tier !== "standard" && tier !== "fast") throw new Error("subagent speeds require a model id and either \"standard\" or \"fast\"");
|
|
14772
|
+
result.subagentSpeeds[model] = tier;
|
|
14773
|
+
}
|
|
14774
|
+
}
|
|
14708
14775
|
if (raw.tools !== void 0) {
|
|
14709
14776
|
if (!raw.tools || typeof raw.tools !== "object" || Array.isArray(raw.tools)) throw new Error("tools must be an object");
|
|
14710
14777
|
result.tools = {};
|
|
@@ -14753,6 +14820,19 @@ var ProviderSettingsStore = class {
|
|
|
14753
14820
|
const windows = this.current.providers[provider]?.contextWindows;
|
|
14754
14821
|
return windows && Object.hasOwn(windows, model) ? windows[model] : void 0;
|
|
14755
14822
|
}
|
|
14823
|
+
/** Read on every request so saved changes apply to the next subagent request. */
|
|
14824
|
+
subagentSpeed(model) {
|
|
14825
|
+
const speeds = this.current.providers.codex?.subagentSpeeds;
|
|
14826
|
+
return speeds && Object.hasOwn(speeds, model) ? speeds[model] : "standard";
|
|
14827
|
+
}
|
|
14828
|
+
/**
|
|
14829
|
+
* The Claude route's prompt-cache TTL override, read live so a saved change
|
|
14830
|
+
* takes effect from the next request without a restart. Absent means follow
|
|
14831
|
+
* the `claudePromptCacheTtl` config.
|
|
14832
|
+
*/
|
|
14833
|
+
promptCacheTtl() {
|
|
14834
|
+
return this.current.providers.claude?.promptCacheTtl;
|
|
14835
|
+
}
|
|
14756
14836
|
/** Creation-time policy survives restarts and never changes an existing session. */
|
|
14757
14837
|
toolEnabled(provider, tool, createdAt = Date.now()) {
|
|
14758
14838
|
let enabled = true;
|
|
@@ -15064,7 +15144,7 @@ var SubscriptionsAuthController = class {
|
|
|
15064
15144
|
* cannot be read off the flow manager.
|
|
15065
15145
|
*/
|
|
15066
15146
|
claims = /* @__PURE__ */ new Map();
|
|
15067
|
-
constructor(flows, deviceFlows, onAuthChanged, resolveAttachments, usageFetchers = {}, readClaudeCreds = readClaudeCodeCredentials, poolUsage = void 0, antigravityConfig = {}, clientVersions = {}, resetRedemption) {
|
|
15147
|
+
constructor(flows, deviceFlows, onAuthChanged, resolveAttachments, usageFetchers = {}, readClaudeCreds = readClaudeCodeCredentials, poolUsage = void 0, antigravityConfig = {}, clientVersions = {}, resetRedemption, onUsageForced) {
|
|
15068
15148
|
this.flows = flows;
|
|
15069
15149
|
this.deviceFlows = deviceFlows;
|
|
15070
15150
|
this.onAuthChanged = onAuthChanged;
|
|
@@ -15075,6 +15155,7 @@ var SubscriptionsAuthController = class {
|
|
|
15075
15155
|
this.antigravityConfig = antigravityConfig;
|
|
15076
15156
|
this.clientVersions = clientVersions;
|
|
15077
15157
|
this.resetRedemption = resetRedemption;
|
|
15158
|
+
this.onUsageForced = onUsageForced;
|
|
15078
15159
|
}
|
|
15079
15160
|
prepareReset(account, signal) {
|
|
15080
15161
|
if (!this.resetRedemption) throw new BadRequest("Reset redemption unavailable");
|
|
@@ -15085,6 +15166,7 @@ var SubscriptionsAuthController = class {
|
|
|
15085
15166
|
await this.resetRedemption.redeem(account, ticket, AbortSignal.any([signal, AbortSignal.timeout(2e4)]));
|
|
15086
15167
|
}
|
|
15087
15168
|
usage(provider, account, signal, force = false) {
|
|
15169
|
+
if (force) this.onUsageForced?.(provider, account);
|
|
15088
15170
|
const fetcher = this.usageFetchers[provider];
|
|
15089
15171
|
if (fetcher === void 0) return Promise.resolve({ supported: false });
|
|
15090
15172
|
if (this.poolUsage === void 0) return fetcher(account, signal);
|
|
@@ -15347,6 +15429,13 @@ function apply(ctx, config) {
|
|
|
15347
15429
|
let grokTokens;
|
|
15348
15430
|
const usageFetchers = {};
|
|
15349
15431
|
const speedBySession = /* @__PURE__ */ new Map();
|
|
15432
|
+
const selectedSpeed = (sessionId, model) => {
|
|
15433
|
+
const explicit = speedBySession.get(sessionId);
|
|
15434
|
+
if (explicit !== void 0) return explicit;
|
|
15435
|
+
const agent = ctx.get("agents")?.get(sessionId);
|
|
15436
|
+
if (model !== void 0 && agent?.session.header.origin === "subagent") return preferences.subagentSpeed(parseAccountModelId(model)?.model ?? model);
|
|
15437
|
+
return "standard";
|
|
15438
|
+
};
|
|
15350
15439
|
let codexAdapter;
|
|
15351
15440
|
let claudeAdapter;
|
|
15352
15441
|
let copilotAdapter;
|
|
@@ -15397,8 +15486,7 @@ function apply(ctx, config) {
|
|
|
15397
15486
|
};
|
|
15398
15487
|
}
|
|
15399
15488
|
};
|
|
15400
|
-
|
|
15401
|
-
adapter = new CodexAdapter({
|
|
15489
|
+
const adapter = new CodexAdapter({
|
|
15402
15490
|
...config.codexClientVersion === void 0 ? {} : { clientVersion: config.codexClientVersion },
|
|
15403
15491
|
resolveClientVersion: () => codexVersion.resolve(),
|
|
15404
15492
|
models: catalog.codex,
|
|
@@ -15413,7 +15501,7 @@ function apply(ctx, config) {
|
|
|
15413
15501
|
defaultEffortOf: (model) => defaultEffortOf("codex", model),
|
|
15414
15502
|
contextWindowOf: (model) => preferences.contextWindow(model),
|
|
15415
15503
|
pool: () => poolAdapter,
|
|
15416
|
-
speedFor: (sessionId, model) => sessionId !== void 0 &&
|
|
15504
|
+
speedFor: (sessionId, model) => sessionId !== void 0 && selectedSpeed(sessionId, model) === "fast" && adapter.supportsFastTier(model)
|
|
15417
15505
|
});
|
|
15418
15506
|
codexAdapter = adapter;
|
|
15419
15507
|
adapters.set("codex", adapter);
|
|
@@ -15449,6 +15537,7 @@ function apply(ctx, config) {
|
|
|
15449
15537
|
contextWindowOf: (model) => preferences.contextWindow(model, "claude"),
|
|
15450
15538
|
resolveCliVersion: () => claudeVersion.resolve(),
|
|
15451
15539
|
promptCacheTtl: claudePromptCacheTtl,
|
|
15540
|
+
promptCacheTtlOverride: () => preferences.promptCacheTtl(),
|
|
15452
15541
|
pool: () => poolAdapter
|
|
15453
15542
|
});
|
|
15454
15543
|
claudeAdapter = adapter;
|
|
@@ -15628,24 +15717,23 @@ function apply(ctx, config) {
|
|
|
15628
15717
|
adapter.listModels = async (route) => (await list(route)).filter((model) => preferences.visible(provider, model.id));
|
|
15629
15718
|
}
|
|
15630
15719
|
const speed = {
|
|
15631
|
-
async speed(sessionId) {
|
|
15720
|
+
async speed(sessionId, model) {
|
|
15632
15721
|
const fastModels = await codexAdapter?.fastCapableModels() ?? [];
|
|
15633
15722
|
const accountPreferences = preferences.get("codex").accounts;
|
|
15634
15723
|
for (const { key } of await codexTokens?.list() ?? []) {
|
|
15635
15724
|
if (!accountPreferences || !Object.hasOwn(accountPreferences, key) || accountPreferences[key].independentEntry !== true) continue;
|
|
15636
|
-
for (const model of [...fastModels]) {
|
|
15637
|
-
if (parseAccountModelId(model)) continue;
|
|
15638
|
-
if (await codexAdapter?.supportsFastTier(model, key)) fastModels.push(accountModelId(key, model));
|
|
15725
|
+
for (const model$1 of [...fastModels]) {
|
|
15726
|
+
if (parseAccountModelId(model$1)) continue;
|
|
15727
|
+
if (await codexAdapter?.supportsFastTier(model$1, key)) fastModels.push(accountModelId(key, model$1));
|
|
15639
15728
|
}
|
|
15640
15729
|
}
|
|
15641
15730
|
return {
|
|
15642
|
-
tier:
|
|
15731
|
+
tier: selectedSpeed(sessionId, model),
|
|
15643
15732
|
fastModels
|
|
15644
15733
|
};
|
|
15645
15734
|
},
|
|
15646
15735
|
async setSpeed(sessionId, tier) {
|
|
15647
|
-
|
|
15648
|
-
else speedBySession.set(sessionId, tier);
|
|
15736
|
+
speedBySession.set(sessionId, tier);
|
|
15649
15737
|
}
|
|
15650
15738
|
};
|
|
15651
15739
|
const modelDefaults = {
|
|
@@ -15661,7 +15749,7 @@ function apply(ctx, config) {
|
|
|
15661
15749
|
const catalog$1 = [];
|
|
15662
15750
|
for (const provider of PROVIDER_IDS) {
|
|
15663
15751
|
if (!visible.has(provider)) continue;
|
|
15664
|
-
let models
|
|
15752
|
+
let models;
|
|
15665
15753
|
try {
|
|
15666
15754
|
models = await ctx.llm.listModels(provider);
|
|
15667
15755
|
} catch {
|
|
@@ -15776,7 +15864,8 @@ function apply(ctx, config) {
|
|
|
15776
15864
|
source: "config"
|
|
15777
15865
|
}) } : {},
|
|
15778
15866
|
...providers.includes("claude") ? { claude: presentedVersion(claudeVersion) } : {}
|
|
15779
|
-
}, resetRedemption), speed, modelDefaults, {
|
|
15867
|
+
}, resetRedemption, (provider, account) => poolHealth?.clear(provider, account)), speed, modelDefaults, {
|
|
15868
|
+
visibleModels: (provider) => preferences.get(provider).visibleModels,
|
|
15780
15869
|
async get(provider, force) {
|
|
15781
15870
|
await loadModelDefaults();
|
|
15782
15871
|
const adapter = adapters.get(provider);
|
|
@@ -15795,6 +15884,7 @@ function apply(ctx, config) {
|
|
|
15795
15884
|
models: await withTimeout((signal) => adapter.listOwnModels(provider, account.key, signal), DISCOVERY_TIMEOUT_MS).catch(() => void 0)
|
|
15796
15885
|
})));
|
|
15797
15886
|
const tierIds = new Set((await poolAdapter?.modelsForProvider(provider).catch(() => []) ?? []).map((model) => model.id));
|
|
15887
|
+
const fastModels = new Set(provider === "codex" ? await codexAdapter?.fastCapableModels() ?? [] : []);
|
|
15798
15888
|
const rows = await Promise.all(models.map(async (model) => {
|
|
15799
15889
|
const contexts = [];
|
|
15800
15890
|
if (provider === "codex" && codexAdapter) {
|
|
@@ -15819,6 +15909,7 @@ function apply(ctx, config) {
|
|
|
15819
15909
|
name: name$1
|
|
15820
15910
|
})) ?? [],
|
|
15821
15911
|
configured: defaultEffortOf(provider, model.id),
|
|
15912
|
+
...provider === "codex" ? { fastTier: !tierIds.has(model.id) && fastModels.has(model.id) } : {},
|
|
15822
15913
|
...contexts.length ? {
|
|
15823
15914
|
defaultContextWindow: Math.min(...contexts.map((entry) => entry.default)),
|
|
15824
15915
|
maxContextWindow: Math.min(...contexts.map((entry) => entry.max))
|
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
|
}
|