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/provider-settings.js
CHANGED
|
@@ -16,11 +16,16 @@ export function validatePreferences(provider, input) {
|
|
|
16
16
|
const raw = input;
|
|
17
17
|
const result = {};
|
|
18
18
|
if (raw.accounts !== undefined) {
|
|
19
|
-
if (!raw.accounts ||
|
|
19
|
+
if (!raw.accounts ||
|
|
20
|
+
typeof raw.accounts !== 'object' ||
|
|
21
|
+
Array.isArray(raw.accounts))
|
|
20
22
|
throw new Error('accounts must be an account-to-preferences map');
|
|
21
23
|
result.accounts = Object.create(null);
|
|
22
24
|
for (const [key, value] of Object.entries(raw.accounts)) {
|
|
23
|
-
if (!key.trim() ||
|
|
25
|
+
if (!key.trim() ||
|
|
26
|
+
!value ||
|
|
27
|
+
typeof value !== 'object' ||
|
|
28
|
+
Array.isArray(value))
|
|
24
29
|
throw new Error('invalid account preferences');
|
|
25
30
|
const account = value;
|
|
26
31
|
const parsed = {};
|
|
@@ -37,7 +42,8 @@ export function validatePreferences(provider, input) {
|
|
|
37
42
|
}
|
|
38
43
|
}
|
|
39
44
|
if (account.poolModels !== undefined) {
|
|
40
|
-
if (!Array.isArray(account.poolModels) ||
|
|
45
|
+
if (!Array.isArray(account.poolModels) ||
|
|
46
|
+
account.poolModels.some((id) => typeof id !== 'string' || !id.trim()))
|
|
41
47
|
throw new Error('poolModels must be an array of model ids');
|
|
42
48
|
parsed.poolModels = [...new Set(account.poolModels)];
|
|
43
49
|
}
|
|
@@ -45,7 +51,8 @@ export function validatePreferences(provider, input) {
|
|
|
45
51
|
}
|
|
46
52
|
}
|
|
47
53
|
if (raw.visibleModels !== undefined) {
|
|
48
|
-
if (!Array.isArray(raw.visibleModels) ||
|
|
54
|
+
if (!Array.isArray(raw.visibleModels) ||
|
|
55
|
+
raw.visibleModels.some((id) => typeof id !== 'string' || !id.trim())) {
|
|
49
56
|
throw new Error('visibleModels must be an array of model ids');
|
|
50
57
|
}
|
|
51
58
|
result.visibleModels = [...new Set(raw.visibleModels)];
|
|
@@ -54,23 +61,37 @@ export function validatePreferences(provider, input) {
|
|
|
54
61
|
if (provider !== 'codex' && provider !== 'claude') {
|
|
55
62
|
throw new Error('context window overrides are supported only for Codex and Claude');
|
|
56
63
|
}
|
|
57
|
-
if (!raw.contextWindows ||
|
|
64
|
+
if (!raw.contextWindows ||
|
|
65
|
+
typeof raw.contextWindows !== 'object' ||
|
|
66
|
+
Array.isArray(raw.contextWindows)) {
|
|
58
67
|
throw new Error('contextWindows must be a model-to-token map');
|
|
59
68
|
}
|
|
60
69
|
result.contextWindows = Object.create(null);
|
|
61
70
|
for (const [model, value] of Object.entries(raw.contextWindows)) {
|
|
62
|
-
if (!model.trim() ||
|
|
71
|
+
if (!model.trim() ||
|
|
72
|
+
typeof value !== 'number' ||
|
|
73
|
+
!Number.isSafeInteger(value) ||
|
|
74
|
+
value <= 0) {
|
|
63
75
|
throw new Error('context windows must be positive safe integers');
|
|
64
76
|
}
|
|
65
77
|
result.contextWindows[model] = value;
|
|
66
78
|
}
|
|
67
79
|
}
|
|
80
|
+
if (raw.promptCacheTtl !== undefined) {
|
|
81
|
+
if (provider !== 'claude')
|
|
82
|
+
throw new Error('the prompt-cache TTL override is supported only for Claude');
|
|
83
|
+
if (raw.promptCacheTtl !== '5m' && raw.promptCacheTtl !== '1h') {
|
|
84
|
+
throw new Error('promptCacheTtl must be "5m" or "1h"');
|
|
85
|
+
}
|
|
86
|
+
result.promptCacheTtl = raw.promptCacheTtl;
|
|
87
|
+
}
|
|
68
88
|
if (raw.tools !== undefined) {
|
|
69
89
|
if (!raw.tools || typeof raw.tools !== 'object' || Array.isArray(raw.tools))
|
|
70
90
|
throw new Error('tools must be an object');
|
|
71
91
|
result.tools = {};
|
|
72
92
|
for (const [tool, enabled] of Object.entries(raw.tools)) {
|
|
73
|
-
if (!PROVIDER_TOOLS[provider].includes(tool) ||
|
|
93
|
+
if (!PROVIDER_TOOLS[provider].includes(tool) ||
|
|
94
|
+
typeof enabled !== 'boolean') {
|
|
74
95
|
throw new Error(`unsupported tool setting: ${provider}/${tool}`);
|
|
75
96
|
}
|
|
76
97
|
result.tools[tool] = enabled;
|
|
@@ -93,29 +114,44 @@ export class ProviderSettingsStore {
|
|
|
93
114
|
if (Object.hasOwn(raw.providers, provider))
|
|
94
115
|
this.current.providers[provider] = validatePreferences(provider, raw.providers[provider]);
|
|
95
116
|
}
|
|
96
|
-
this.current.toolHistory = raw.toolHistory
|
|
97
|
-
|
|
117
|
+
this.current.toolHistory = raw.toolHistory
|
|
118
|
+
.map((revision) => {
|
|
119
|
+
if (!PROVIDER_IDS.includes(revision.provider) ||
|
|
120
|
+
!Number.isSafeInteger(revision.at) ||
|
|
121
|
+
revision.at < 0)
|
|
98
122
|
throw new Error('invalid tool history');
|
|
99
|
-
const tools = validatePreferences(revision.provider, { tools: revision.tools })
|
|
123
|
+
const tools = validatePreferences(revision.provider, { tools: revision.tools })
|
|
124
|
+
.tools ?? {};
|
|
100
125
|
return { at: revision.at, provider: revision.provider, tools };
|
|
101
|
-
})
|
|
126
|
+
})
|
|
127
|
+
.sort((a, b) => a.at - b.at);
|
|
102
128
|
}
|
|
103
129
|
catch (error) {
|
|
104
130
|
if (error.code !== 'ENOENT')
|
|
105
|
-
throw new Error(`Cannot read provider settings at ${path}`, {
|
|
131
|
+
throw new Error(`Cannot read provider settings at ${path}`, {
|
|
132
|
+
cause: error,
|
|
133
|
+
});
|
|
106
134
|
}
|
|
107
135
|
}
|
|
108
136
|
get(provider) {
|
|
109
137
|
return structuredClone(this.current.providers[provider] ?? {});
|
|
110
138
|
}
|
|
111
139
|
visible(provider, model) {
|
|
112
|
-
return this.current.providers[provider]?.visibleModels?.includes(model) ?? true;
|
|
140
|
+
return (this.current.providers[provider]?.visibleModels?.includes(model) ?? true);
|
|
113
141
|
}
|
|
114
142
|
/** The user's local context-window override for one model; absent follows the provider. */
|
|
115
143
|
contextWindow(model, provider = 'codex') {
|
|
116
144
|
const windows = this.current.providers[provider]?.contextWindows;
|
|
117
145
|
return windows && Object.hasOwn(windows, model) ? windows[model] : undefined;
|
|
118
146
|
}
|
|
147
|
+
/**
|
|
148
|
+
* The Claude route's prompt-cache TTL override, read live so a saved change
|
|
149
|
+
* takes effect from the next request without a restart. Absent means follow
|
|
150
|
+
* the `claudePromptCacheTtl` config.
|
|
151
|
+
*/
|
|
152
|
+
promptCacheTtl() {
|
|
153
|
+
return this.current.providers.claude?.promptCacheTtl;
|
|
154
|
+
}
|
|
119
155
|
/** Creation-time policy survives restarts and never changes an existing session. */
|
|
120
156
|
toolEnabled(provider, tool, createdAt = Date.now()) {
|
|
121
157
|
let enabled = true;
|
|
@@ -133,13 +169,19 @@ export class ProviderSettingsStore {
|
|
|
133
169
|
const next = structuredClone(this.current);
|
|
134
170
|
const before = next.providers[provider]?.tools ?? {};
|
|
135
171
|
next.providers[provider] = preferences;
|
|
136
|
-
if (PROVIDER_TOOLS[provider].some(tool => (before[tool] !== false) !== (preferences.tools?.[tool] !== false))) {
|
|
137
|
-
next.toolHistory.push({
|
|
172
|
+
if (PROVIDER_TOOLS[provider].some((tool) => (before[tool] !== false) !== (preferences.tools?.[tool] !== false))) {
|
|
173
|
+
next.toolHistory.push({
|
|
174
|
+
at: Date.now(),
|
|
175
|
+
provider,
|
|
176
|
+
tools: preferences.tools ?? {},
|
|
177
|
+
});
|
|
138
178
|
}
|
|
139
179
|
await mkdir(dirname(this.path), { recursive: true });
|
|
140
180
|
const temporary = `${this.path}.${process.pid}.${Math.random().toString(36).slice(2)}.tmp`;
|
|
141
181
|
try {
|
|
142
|
-
await writeFile(temporary, JSON.stringify(next, null, 2), {
|
|
182
|
+
await writeFile(temporary, JSON.stringify(next, null, 2), {
|
|
183
|
+
mode: 0o600,
|
|
184
|
+
});
|
|
143
185
|
await rename(temporary, this.path);
|
|
144
186
|
}
|
|
145
187
|
finally {
|
|
@@ -24,7 +24,8 @@ export function parseAccountModelId(id) {
|
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
export function accountAllowsPool(preferences, model) {
|
|
27
|
-
return preferences?.poolEnabled !== false &&
|
|
27
|
+
return (preferences?.poolEnabled !== false &&
|
|
28
|
+
(preferences?.poolModels?.includes(model) ?? true));
|
|
28
29
|
}
|
|
29
30
|
/** Keeps the registered route separate from raw adapters and pool member seams. */
|
|
30
31
|
export class AccountPreferencesAdapter extends LlmAdapter {
|
|
@@ -35,20 +36,24 @@ export class AccountPreferencesAdapter extends LlmAdapter {
|
|
|
35
36
|
}
|
|
36
37
|
preference(account) {
|
|
37
38
|
const accounts = this.options.settings.get(this.options.provider).accounts;
|
|
38
|
-
return accounts && Object.hasOwn(accounts, account)
|
|
39
|
+
return accounts && Object.hasOwn(accounts, account)
|
|
40
|
+
? accounts[account]
|
|
41
|
+
: undefined;
|
|
39
42
|
}
|
|
40
43
|
async models(account) {
|
|
41
|
-
const models = await withTimeout(signal => this.options.adapter.listOwnModels(this.options.provider, account, signal), this.options.discoveryTimeoutMs ?? DISCOVERY_TIMEOUT_MS);
|
|
44
|
+
const models = await withTimeout((signal) => this.options.adapter.listOwnModels(this.options.provider, account, signal), this.options.discoveryTimeoutMs ?? DISCOVERY_TIMEOUT_MS);
|
|
42
45
|
if (models !== undefined)
|
|
43
46
|
return models;
|
|
44
47
|
// Discovery timed out: the catalog this account listed last time beats
|
|
45
48
|
// "no models", which would fail the turn with "No eligible account".
|
|
46
|
-
return await this.options.adapter.lastKnownOwnModels?.(this.options.provider, account) ?? [];
|
|
49
|
+
return ((await this.options.adapter.lastKnownOwnModels?.(this.options.provider, account)) ?? []);
|
|
47
50
|
}
|
|
48
51
|
async requireAccount(account, model, independent) {
|
|
49
|
-
if (!(await this.options.accounts()).some(entry => entry.key === account)
|
|
50
|
-
|
|
51
|
-
|
|
52
|
+
if (!(await this.options.accounts()).some((entry) => entry.key === account) ||
|
|
53
|
+
(independent
|
|
54
|
+
? this.preference(account)?.independentEntry !== true
|
|
55
|
+
: !accountAllowsPool(this.preference(account), model)) ||
|
|
56
|
+
!(await this.models(account)).some((entry) => entry.id === model)) {
|
|
52
57
|
throw new LlmError(`Account route unavailable: ${this.options.provider}/${account}/${model}`, 'NO_ADAPTER');
|
|
53
58
|
}
|
|
54
59
|
}
|
|
@@ -60,7 +65,9 @@ export class AccountPreferencesAdapter extends LlmAdapter {
|
|
|
60
65
|
await this.requireAccount(key, model, false);
|
|
61
66
|
return key;
|
|
62
67
|
}
|
|
63
|
-
catch {
|
|
68
|
+
catch {
|
|
69
|
+
/* unavailable catalog */
|
|
70
|
+
}
|
|
64
71
|
}
|
|
65
72
|
throw new LlmError(`No eligible account for ${this.options.provider}/${model}`, 'NO_ADAPTER');
|
|
66
73
|
}
|
|
@@ -76,7 +83,8 @@ export class AccountPreferencesAdapter extends LlmAdapter {
|
|
|
76
83
|
await this.requireAccount(key, model, false);
|
|
77
84
|
return key;
|
|
78
85
|
};
|
|
79
|
-
return new Proxy(raw, {
|
|
86
|
+
return new Proxy(raw, {
|
|
87
|
+
get: (target, property) => {
|
|
80
88
|
if (property === 'streamAccount')
|
|
81
89
|
return async function* (options, account) {
|
|
82
90
|
let key;
|
|
@@ -94,34 +102,51 @@ export class AccountPreferencesAdapter extends LlmAdapter {
|
|
|
94
102
|
return async (provider, model, account) => raw.resolveOwnModel(provider, model, await keyFor(account, model));
|
|
95
103
|
const value = Reflect.get(target, property);
|
|
96
104
|
return typeof value === 'function' ? value.bind(target) : value;
|
|
97
|
-
}
|
|
105
|
+
},
|
|
106
|
+
});
|
|
98
107
|
}
|
|
99
108
|
async listModels(provider) {
|
|
100
109
|
const result = new Map();
|
|
101
|
-
const catalogs = await Promise.all((await this.options.accounts()).map(async (account) => ({
|
|
110
|
+
const catalogs = await Promise.all((await this.options.accounts()).map(async (account) => ({
|
|
111
|
+
...account,
|
|
112
|
+
models: await this.models(account.key).catch(() => []),
|
|
113
|
+
})));
|
|
102
114
|
for (const { key, label, models } of catalogs) {
|
|
103
115
|
const preferences = this.preference(key);
|
|
104
116
|
for (const model of models) {
|
|
105
117
|
if (model.id.startsWith(ACCOUNT_MODEL_PREFIX))
|
|
106
118
|
continue;
|
|
107
|
-
if (accountAllowsPool(preferences, model.id) &&
|
|
119
|
+
if (accountAllowsPool(preferences, model.id) &&
|
|
120
|
+
this.options.settings.visible(this.options.provider, model.id) &&
|
|
121
|
+
!result.has(model.id))
|
|
108
122
|
result.set(model.id, model);
|
|
109
|
-
if (preferences?.independentEntry === true &&
|
|
123
|
+
if (preferences?.independentEntry === true &&
|
|
124
|
+
this.options.settings.visible(this.options.provider, model.id)) {
|
|
110
125
|
const id = accountModelId(key, model.id);
|
|
111
|
-
result.set(id, {
|
|
126
|
+
result.set(id, {
|
|
127
|
+
...model,
|
|
128
|
+
id,
|
|
129
|
+
name: `${preferences.alias || label} · ${model.name}`,
|
|
130
|
+
});
|
|
112
131
|
}
|
|
113
132
|
}
|
|
114
133
|
}
|
|
115
|
-
for (const model of await this.options
|
|
116
|
-
|
|
134
|
+
for (const model of (await this.options
|
|
135
|
+
.pool()
|
|
136
|
+
?.modelsForProvider(this.options.provider)) ?? []) {
|
|
137
|
+
if (model.id.startsWith(ACCOUNT_MODEL_PREFIX) ||
|
|
138
|
+
!this.options.settings.visible(this.options.provider, model.id))
|
|
117
139
|
continue;
|
|
118
140
|
try {
|
|
119
141
|
await this.options.pool().resolveModel(provider, model.id);
|
|
120
142
|
result.set(model.id, model);
|
|
121
143
|
}
|
|
122
|
-
catch {
|
|
144
|
+
catch {
|
|
145
|
+
/* excluded tier */
|
|
146
|
+
}
|
|
123
147
|
}
|
|
124
|
-
const priority = (model) => model.priority ??
|
|
148
|
+
const priority = (model) => model.priority ??
|
|
149
|
+
Number.MAX_SAFE_INTEGER;
|
|
125
150
|
return [...result.values()].sort((left, right) => priority(left) - priority(right));
|
|
126
151
|
}
|
|
127
152
|
async resolveModel(provider, id) {
|
|
@@ -129,11 +154,15 @@ export class AccountPreferencesAdapter extends LlmAdapter {
|
|
|
129
154
|
if (independent) {
|
|
130
155
|
await this.requireAccount(independent.account, independent.model, true);
|
|
131
156
|
const info = await this.options.adapter.resolveOwnModel(provider, independent.model, independent.account);
|
|
132
|
-
const label = (await this.options.accounts()).find(entry => entry.key === independent.account)?.label ?? independent.account;
|
|
133
|
-
return {
|
|
157
|
+
const label = (await this.options.accounts()).find((entry) => entry.key === independent.account)?.label ?? independent.account;
|
|
158
|
+
return {
|
|
159
|
+
...info,
|
|
160
|
+
id,
|
|
161
|
+
name: `${this.preference(independent.account)?.alias || label} · ${info.name}`,
|
|
162
|
+
};
|
|
134
163
|
}
|
|
135
164
|
const pool = this.options.pool();
|
|
136
|
-
if (pool && await pool.owns(this.options.provider, id))
|
|
165
|
+
if (pool && (await pool.owns(this.options.provider, id)))
|
|
137
166
|
return pool.resolveModel(provider, id);
|
|
138
167
|
return this.options.adapter.resolveOwnModel(provider, id, await this.fallback(id));
|
|
139
168
|
}
|
|
@@ -145,7 +174,7 @@ export class AccountPreferencesAdapter extends LlmAdapter {
|
|
|
145
174
|
return;
|
|
146
175
|
}
|
|
147
176
|
const pool = this.options.pool();
|
|
148
|
-
if (pool && await pool.owns(this.options.provider, options.model)) {
|
|
177
|
+
if (pool && (await pool.owns(this.options.provider, options.model))) {
|
|
149
178
|
yield* pool.stream(options);
|
|
150
179
|
return;
|
|
151
180
|
}
|
|
@@ -15,7 +15,9 @@ export { DISCOVERY_TIMEOUT_MS } from './common.js';
|
|
|
15
15
|
/** Catalog sort hint when the provider advertised one (Codex `priority`). */
|
|
16
16
|
function catalogPriority(model) {
|
|
17
17
|
const ranked = model;
|
|
18
|
-
return typeof ranked.priority === 'number'
|
|
18
|
+
return typeof ranked.priority === 'number'
|
|
19
|
+
? ranked.priority
|
|
20
|
+
: Number.MAX_SAFE_INTEGER;
|
|
19
21
|
}
|
|
20
22
|
/**
|
|
21
23
|
* Merge per-account catalogs, keeping the first occurrence of each model id.
|
|
@@ -31,7 +33,9 @@ export async function unionAccountCatalogs(accounts, listOne, options) {
|
|
|
31
33
|
try {
|
|
32
34
|
if (timeoutMs === undefined)
|
|
33
35
|
return await listOne(account, caller);
|
|
34
|
-
const models = await withTimeout(timeoutSignal => listOne(account, caller === undefined
|
|
36
|
+
const models = await withTimeout((timeoutSignal) => listOne(account, caller === undefined
|
|
37
|
+
? timeoutSignal
|
|
38
|
+
: AbortSignal.any([timeoutSignal, caller])), timeoutMs);
|
|
35
39
|
return models ?? [];
|
|
36
40
|
}
|
|
37
41
|
catch (error) {
|
|
@@ -63,10 +67,10 @@ export class AccountTokenManager {
|
|
|
63
67
|
const provider = options.provider;
|
|
64
68
|
this.io = options.io ?? {
|
|
65
69
|
list: () => listAccounts(provider),
|
|
66
|
-
get: account => getAccountSession(provider, account),
|
|
70
|
+
get: (account) => getAccountSession(provider, account),
|
|
67
71
|
save: (account, session) => saveAccountSession(provider, account, session),
|
|
68
|
-
remove: account => deleteAccountSession(provider, account),
|
|
69
|
-
resolve: account => resolveAccountKey(provider, account),
|
|
72
|
+
remove: (account) => deleteAccountSession(provider, account),
|
|
73
|
+
resolve: (account) => resolveAccountKey(provider, account),
|
|
70
74
|
};
|
|
71
75
|
}
|
|
72
76
|
/** The provider's accounts, default first (straight from the store). */
|
|
@@ -86,7 +90,7 @@ export class AccountTokenManager {
|
|
|
86
90
|
* @throws LlmError MISSING_CREDENTIAL when the account is not logged in.
|
|
87
91
|
*/
|
|
88
92
|
async session(account, forceRefresh = false) {
|
|
89
|
-
const requested = account ?? await this.defaultAccount();
|
|
93
|
+
const requested = account ?? (await this.defaultAccount());
|
|
90
94
|
if (requested === undefined)
|
|
91
95
|
throw this.missingCredential();
|
|
92
96
|
const key = await this.resolveAccount(requested);
|
|
@@ -128,7 +132,9 @@ export class AccountTokenManager {
|
|
|
128
132
|
}
|
|
129
133
|
},
|
|
130
134
|
remove: () => io.remove(boundAccount),
|
|
131
|
-
onRemoved: () => {
|
|
135
|
+
onRemoved: () => {
|
|
136
|
+
this.options.onAccountRemoved?.(boundAccount);
|
|
137
|
+
},
|
|
132
138
|
});
|
|
133
139
|
this.managers.set(account, manager);
|
|
134
140
|
}
|
|
@@ -136,7 +142,7 @@ export class AccountTokenManager {
|
|
|
136
142
|
}
|
|
137
143
|
/** The logged-out error, mirroring TokenManager's own message. */
|
|
138
144
|
missingCredential() {
|
|
139
|
-
return new LlmError(`dsh-subscriptions: not logged in to ${this.options.displayName}; `
|
|
140
|
-
|
|
145
|
+
return new LlmError(`dsh-subscriptions: not logged in to ${this.options.displayName}; ` +
|
|
146
|
+
'log in via Settings → Subscriptions in the dsh web app', 'MISSING_CREDENTIAL');
|
|
141
147
|
}
|
|
142
148
|
}
|
|
@@ -3,5 +3,5 @@
|
|
|
3
3
|
* These application constants are distinct from user access/refresh tokens.
|
|
4
4
|
* Source: https://github.com/Rahularya01/pi-antigravity/blob/697858cafcf1faddf2ae898d2f053b2ff26c05e6/src/auth/oauth.ts
|
|
5
5
|
*/
|
|
6
|
-
export const ANTIGRAVITY_DEFAULT_CLIENT_ID =
|
|
7
|
-
export const ANTIGRAVITY_DEFAULT_CLIENT_SECRET =
|
|
6
|
+
export const ANTIGRAVITY_DEFAULT_CLIENT_ID = '1071006060591-tmhssin2h21lcre235vtolojh4g403ep.apps.googleusercontent.com';
|
|
7
|
+
export const ANTIGRAVITY_DEFAULT_CLIENT_SECRET = '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';
|