dsh-subscriptions 0.2.2 → 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 +21 -13
- package/lib/auth/rpc.d.ts +8 -4
- package/lib/auth/rpc.js +15 -2
- package/lib/client/ProviderModelEditor.js +59 -37
- package/lib/client/SpeedSelect.js +13 -12
- package/lib/client/SubscriptionsSection.d.ts +2 -0
- package/lib/client/SubscriptionsSection.js +10 -3
- package/lib/client/locales.d.ts +12 -0
- package/lib/client/locales.js +14 -2
- package/lib/client/model-filter.d.ts +37 -0
- package/lib/client/model-filter.js +45 -0
- package/lib/client/usage-window-filter.d.ts +7 -0
- package/lib/client/usage-window-filter.js +12 -0
- package/lib/client.js +199 -95
- package/lib/client.js.map +1 -1
- package/lib/index.js +49 -12
- package/lib/provider-settings.d.ts +5 -0
- package/lib/provider-settings.js +21 -0
- package/lib/translate/antigravity.js +10 -2
- package/package.json +2 -1
package/lib/index.js
CHANGED
|
@@ -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 });
|
|
@@ -13038,9 +13044,17 @@ function toAntigravityTools(tools, model = "gemini") {
|
|
|
13038
13044
|
})) }];
|
|
13039
13045
|
}
|
|
13040
13046
|
const SKIP_THOUGHT_SIGNATURE_VALIDATOR = "skip_thought_signature_validator";
|
|
13041
|
-
/**
|
|
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
|
+
*/
|
|
13042
13056
|
function requiresThoughtSignatures(model) {
|
|
13043
|
-
return model !== void 0 && /^gemini-
|
|
13057
|
+
return model !== void 0 && /^gemini-[34](?:[.-]|$)/i.test(model.trim());
|
|
13044
13058
|
}
|
|
13045
13059
|
/**
|
|
13046
13060
|
* Convert resolved harness messages into Gemini contents. Function response
|
|
@@ -14749,6 +14763,15 @@ function validatePreferences(provider, input) {
|
|
|
14749
14763
|
if (raw.promptCacheTtl !== "5m" && raw.promptCacheTtl !== "1h") throw new Error("promptCacheTtl must be \"5m\" or \"1h\"");
|
|
14750
14764
|
result.promptCacheTtl = raw.promptCacheTtl;
|
|
14751
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
|
+
}
|
|
14752
14775
|
if (raw.tools !== void 0) {
|
|
14753
14776
|
if (!raw.tools || typeof raw.tools !== "object" || Array.isArray(raw.tools)) throw new Error("tools must be an object");
|
|
14754
14777
|
result.tools = {};
|
|
@@ -14797,6 +14820,11 @@ var ProviderSettingsStore = class {
|
|
|
14797
14820
|
const windows = this.current.providers[provider]?.contextWindows;
|
|
14798
14821
|
return windows && Object.hasOwn(windows, model) ? windows[model] : void 0;
|
|
14799
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
|
+
}
|
|
14800
14828
|
/**
|
|
14801
14829
|
* The Claude route's prompt-cache TTL override, read live so a saved change
|
|
14802
14830
|
* takes effect from the next request without a restart. Absent means follow
|
|
@@ -15401,6 +15429,13 @@ function apply(ctx, config) {
|
|
|
15401
15429
|
let grokTokens;
|
|
15402
15430
|
const usageFetchers = {};
|
|
15403
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
|
+
};
|
|
15404
15439
|
let codexAdapter;
|
|
15405
15440
|
let claudeAdapter;
|
|
15406
15441
|
let copilotAdapter;
|
|
@@ -15466,7 +15501,7 @@ function apply(ctx, config) {
|
|
|
15466
15501
|
defaultEffortOf: (model) => defaultEffortOf("codex", model),
|
|
15467
15502
|
contextWindowOf: (model) => preferences.contextWindow(model),
|
|
15468
15503
|
pool: () => poolAdapter,
|
|
15469
|
-
speedFor: (sessionId, model) => sessionId !== void 0 &&
|
|
15504
|
+
speedFor: (sessionId, model) => sessionId !== void 0 && selectedSpeed(sessionId, model) === "fast" && adapter.supportsFastTier(model)
|
|
15470
15505
|
});
|
|
15471
15506
|
codexAdapter = adapter;
|
|
15472
15507
|
adapters.set("codex", adapter);
|
|
@@ -15682,24 +15717,23 @@ function apply(ctx, config) {
|
|
|
15682
15717
|
adapter.listModels = async (route) => (await list(route)).filter((model) => preferences.visible(provider, model.id));
|
|
15683
15718
|
}
|
|
15684
15719
|
const speed = {
|
|
15685
|
-
async speed(sessionId) {
|
|
15720
|
+
async speed(sessionId, model) {
|
|
15686
15721
|
const fastModels = await codexAdapter?.fastCapableModels() ?? [];
|
|
15687
15722
|
const accountPreferences = preferences.get("codex").accounts;
|
|
15688
15723
|
for (const { key } of await codexTokens?.list() ?? []) {
|
|
15689
15724
|
if (!accountPreferences || !Object.hasOwn(accountPreferences, key) || accountPreferences[key].independentEntry !== true) continue;
|
|
15690
|
-
for (const model of [...fastModels]) {
|
|
15691
|
-
if (parseAccountModelId(model)) continue;
|
|
15692
|
-
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));
|
|
15693
15728
|
}
|
|
15694
15729
|
}
|
|
15695
15730
|
return {
|
|
15696
|
-
tier:
|
|
15731
|
+
tier: selectedSpeed(sessionId, model),
|
|
15697
15732
|
fastModels
|
|
15698
15733
|
};
|
|
15699
15734
|
},
|
|
15700
15735
|
async setSpeed(sessionId, tier) {
|
|
15701
|
-
|
|
15702
|
-
else speedBySession.set(sessionId, tier);
|
|
15736
|
+
speedBySession.set(sessionId, tier);
|
|
15703
15737
|
}
|
|
15704
15738
|
};
|
|
15705
15739
|
const modelDefaults = {
|
|
@@ -15831,6 +15865,7 @@ function apply(ctx, config) {
|
|
|
15831
15865
|
}) } : {},
|
|
15832
15866
|
...providers.includes("claude") ? { claude: presentedVersion(claudeVersion) } : {}
|
|
15833
15867
|
}, resetRedemption, (provider, account) => poolHealth?.clear(provider, account)), speed, modelDefaults, {
|
|
15868
|
+
visibleModels: (provider) => preferences.get(provider).visibleModels,
|
|
15834
15869
|
async get(provider, force) {
|
|
15835
15870
|
await loadModelDefaults();
|
|
15836
15871
|
const adapter = adapters.get(provider);
|
|
@@ -15849,6 +15884,7 @@ function apply(ctx, config) {
|
|
|
15849
15884
|
models: await withTimeout((signal) => adapter.listOwnModels(provider, account.key, signal), DISCOVERY_TIMEOUT_MS).catch(() => void 0)
|
|
15850
15885
|
})));
|
|
15851
15886
|
const tierIds = new Set((await poolAdapter?.modelsForProvider(provider).catch(() => []) ?? []).map((model) => model.id));
|
|
15887
|
+
const fastModels = new Set(provider === "codex" ? await codexAdapter?.fastCapableModels() ?? [] : []);
|
|
15852
15888
|
const rows = await Promise.all(models.map(async (model) => {
|
|
15853
15889
|
const contexts = [];
|
|
15854
15890
|
if (provider === "codex" && codexAdapter) {
|
|
@@ -15873,6 +15909,7 @@ function apply(ctx, config) {
|
|
|
15873
15909
|
name: name$1
|
|
15874
15910
|
})) ?? [],
|
|
15875
15911
|
configured: defaultEffortOf(provider, model.id),
|
|
15912
|
+
...provider === "codex" ? { fastTier: !tierIds.has(model.id) && fastModels.has(model.id) } : {},
|
|
15876
15913
|
...contexts.length ? {
|
|
15877
15914
|
defaultContextWindow: Math.min(...contexts.map((entry) => entry.default)),
|
|
15878
15915
|
maxContextWindow: Math.min(...contexts.map((entry) => entry.max))
|
|
@@ -8,6 +8,7 @@ export declare const PROVIDER_TOOLS: {
|
|
|
8
8
|
readonly antigravity: readonly [];
|
|
9
9
|
};
|
|
10
10
|
export type SubscriptionTool = 'image_generate' | 'video_generate' | 'x_search' | 'web_search';
|
|
11
|
+
export type SubagentSpeedTier = 'standard' | 'fast';
|
|
11
12
|
export interface AccountPreferences {
|
|
12
13
|
alias?: string;
|
|
13
14
|
/** Absent means included. */
|
|
@@ -22,6 +23,8 @@ export interface ProviderPreferences {
|
|
|
22
23
|
/** Absent follows discovery; an explicit selection hides newly discovered models. */
|
|
23
24
|
visibleModels?: string[];
|
|
24
25
|
contextWindows?: Record<string, number>;
|
|
26
|
+
/** Codex only: per-model defaults for subagents, independent of main-session speed. */
|
|
27
|
+
subagentSpeeds?: Record<string, SubagentSpeedTier>;
|
|
25
28
|
tools?: Partial<Record<SubscriptionTool, boolean>>;
|
|
26
29
|
/**
|
|
27
30
|
* Claude only: overrides the `claudePromptCacheTtl` plugin config for this
|
|
@@ -40,6 +43,8 @@ export declare class ProviderSettingsStore {
|
|
|
40
43
|
visible(provider: ProviderId, model: string): boolean;
|
|
41
44
|
/** The user's local context-window override for one model; absent follows the provider. */
|
|
42
45
|
contextWindow(model: string, provider?: ProviderId): number | undefined;
|
|
46
|
+
/** Read on every request so saved changes apply to the next subagent request. */
|
|
47
|
+
subagentSpeed(model: string): SubagentSpeedTier;
|
|
43
48
|
/**
|
|
44
49
|
* The Claude route's prompt-cache TTL override, read live so a saved change
|
|
45
50
|
* takes effect from the next request without a restart. Absent means follow
|
package/lib/provider-settings.js
CHANGED
|
@@ -85,6 +85,22 @@ export function validatePreferences(provider, input) {
|
|
|
85
85
|
}
|
|
86
86
|
result.promptCacheTtl = raw.promptCacheTtl;
|
|
87
87
|
}
|
|
88
|
+
if (raw.subagentSpeeds !== undefined) {
|
|
89
|
+
if (provider !== 'codex')
|
|
90
|
+
throw new Error('subagent speeds are currently supported only for Codex');
|
|
91
|
+
if (!raw.subagentSpeeds ||
|
|
92
|
+
typeof raw.subagentSpeeds !== 'object' ||
|
|
93
|
+
Array.isArray(raw.subagentSpeeds)) {
|
|
94
|
+
throw new Error('subagent speeds must be a model-to-speed map');
|
|
95
|
+
}
|
|
96
|
+
result.subagentSpeeds = Object.create(null);
|
|
97
|
+
for (const [model, tier] of Object.entries(raw.subagentSpeeds)) {
|
|
98
|
+
if (!model.trim() || (tier !== 'standard' && tier !== 'fast')) {
|
|
99
|
+
throw new Error('subagent speeds require a model id and either "standard" or "fast"');
|
|
100
|
+
}
|
|
101
|
+
result.subagentSpeeds[model] = tier;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
88
104
|
if (raw.tools !== undefined) {
|
|
89
105
|
if (!raw.tools || typeof raw.tools !== 'object' || Array.isArray(raw.tools))
|
|
90
106
|
throw new Error('tools must be an object');
|
|
@@ -144,6 +160,11 @@ export class ProviderSettingsStore {
|
|
|
144
160
|
const windows = this.current.providers[provider]?.contextWindows;
|
|
145
161
|
return windows && Object.hasOwn(windows, model) ? windows[model] : undefined;
|
|
146
162
|
}
|
|
163
|
+
/** Read on every request so saved changes apply to the next subagent request. */
|
|
164
|
+
subagentSpeed(model) {
|
|
165
|
+
const speeds = this.current.providers.codex?.subagentSpeeds;
|
|
166
|
+
return speeds && Object.hasOwn(speeds, model) ? speeds[model] : 'standard';
|
|
167
|
+
}
|
|
147
168
|
/**
|
|
148
169
|
* The Claude route's prompt-cache TTL override, read live so a saved change
|
|
149
170
|
* takes effect from the next request without a restart. Absent means follow
|
|
@@ -88,9 +88,17 @@ export function toAntigravityTools(tools, model = 'gemini') {
|
|
|
88
88
|
];
|
|
89
89
|
}
|
|
90
90
|
const SKIP_THOUGHT_SIGNATURE_VALIDATOR = 'skip_thought_signature_validator';
|
|
91
|
-
/**
|
|
91
|
+
/**
|
|
92
|
+
* Whether this model validates thought signatures on replayed function calls.
|
|
93
|
+
*
|
|
94
|
+
* Gemini 3 and 4 require a signature on the first function call of each step;
|
|
95
|
+
* foreign history uses the documented placeholder when no signature can be reused.
|
|
96
|
+
* https://ai.google.dev/gemini-api/docs/generate-content/thought-signatures
|
|
97
|
+
* Keep this scoped to these model families; future versions and unversioned aliases
|
|
98
|
+
* need verification before enabling the same fallback.
|
|
99
|
+
*/
|
|
92
100
|
function requiresThoughtSignatures(model) {
|
|
93
|
-
return model !== undefined && /^gemini-
|
|
101
|
+
return model !== undefined && /^gemini-[34](?:[.-]|$)/i.test(model.trim());
|
|
94
102
|
}
|
|
95
103
|
/**
|
|
96
104
|
* Convert resolved harness messages into Gemini contents. Function response
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-subscriptions",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"description": "Unified subscription providers and usage dashboard for DeepSeek Harness",
|
|
5
5
|
"icon": "./icon.svg",
|
|
6
6
|
"license": "MIT",
|
|
@@ -90,6 +90,7 @@
|
|
|
90
90
|
},
|
|
91
91
|
"devDependencies": {
|
|
92
92
|
"@deepseek-ai/cordis": "4.0.4",
|
|
93
|
+
"@deepseek-ai/dsh-agent": "0.1.7-rc.2",
|
|
93
94
|
"@deepseek-ai/dsh-api-remotes": "0.1.7-rc.2",
|
|
94
95
|
"@deepseek-ai/dsh-attachment": "0.1.7-rc.2",
|
|
95
96
|
"@deepseek-ai/dsh-client-connection": "0.1.7-rc.2",
|