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
|
@@ -3,15 +3,15 @@
|
|
|
3
3
|
* from Gemini CLI: it uses Antigravity OAuth scopes, project discovery, and
|
|
4
4
|
* the daily-cloudcode-pa v1internal request envelope.
|
|
5
5
|
*/
|
|
6
|
-
import { errorChain, EMPTY_RESPONSE_CODE, LlmAdapter, LlmError } from '@deepseek-ai/dsh-llm';
|
|
6
|
+
import { errorChain, EMPTY_RESPONSE_CODE, LlmAdapter, LlmError, } from '@deepseek-ai/dsh-llm';
|
|
7
7
|
import { resolveImages } from '../translate/resolved.js';
|
|
8
8
|
import { antigravityReasoning } from '../translate/antigravity-thinking.js';
|
|
9
9
|
import { parseAntigravityResponse, streamAntigravity, toAntigravityRequest, } from '../translate/antigravity.js';
|
|
10
10
|
import { httpLlmError, idleWatchdog, mapFetchFailure, mergeReasoning, ModelCatalogCache, discoverOrRetryAuth, isMissingOrInvalidCredential, parseProviderJson, oauthEndpointError, OAuthEndpointError, discoverAcrossAccounts, isDiscoveryAborted, } from './common.js';
|
|
11
11
|
import { hostFetch } from '../http.js';
|
|
12
|
-
import { ANTIGRAVITY_DEFAULT_CLIENT_ID, ANTIGRAVITY_DEFAULT_CLIENT_SECRET } from './antigravity-oauth-client.js';
|
|
13
|
-
import { AccountTokenManager, DISCOVERY_TIMEOUT_MS, unionAccountCatalogs } from './accounts.js';
|
|
14
|
-
import { DEFAULT_RATE_LIMIT_WAIT, DEFAULT_RETRY, subscriptionRetryPolicy } from './rate-limit.js';
|
|
12
|
+
import { ANTIGRAVITY_DEFAULT_CLIENT_ID, ANTIGRAVITY_DEFAULT_CLIENT_SECRET, } from './antigravity-oauth-client.js';
|
|
13
|
+
import { AccountTokenManager, DISCOVERY_TIMEOUT_MS, unionAccountCatalogs, } from './accounts.js';
|
|
14
|
+
import { DEFAULT_RATE_LIMIT_WAIT, DEFAULT_RETRY, subscriptionRetryPolicy, } from './rate-limit.js';
|
|
15
15
|
export const ANTIGRAVITY_AUTHORIZE_URL = 'https://accounts.google.com/o/oauth2/v2/auth';
|
|
16
16
|
export const ANTIGRAVITY_TOKEN_URL = 'https://oauth2.googleapis.com/token';
|
|
17
17
|
export const ANTIGRAVITY_USERINFO_URL = 'https://www.googleapis.com/oauth2/v2/userinfo';
|
|
@@ -40,24 +40,37 @@ export function resolveAntigravityOAuthConfig(config) {
|
|
|
40
40
|
const environmentSecret = process.env.ANTIGRAVITY_CLIENT_SECRET?.trim();
|
|
41
41
|
if (configuredId) {
|
|
42
42
|
// A custom PKCE-only client must never inherit a different client's secret.
|
|
43
|
-
return {
|
|
43
|
+
return {
|
|
44
|
+
clientId: configuredId,
|
|
45
|
+
...(configuredSecret ? { clientSecret: configuredSecret } : {}),
|
|
46
|
+
};
|
|
44
47
|
}
|
|
45
48
|
if (configuredSecret)
|
|
46
49
|
throw new Error('config.antigravity.clientSecret requires config.antigravity.clientId');
|
|
47
50
|
if (environmentId) {
|
|
48
|
-
return {
|
|
51
|
+
return {
|
|
52
|
+
clientId: environmentId,
|
|
53
|
+
...(environmentSecret ? { clientSecret: environmentSecret } : {}),
|
|
54
|
+
};
|
|
49
55
|
}
|
|
50
56
|
if (environmentSecret)
|
|
51
57
|
throw new Error('ANTIGRAVITY_CLIENT_SECRET requires ANTIGRAVITY_CLIENT_ID');
|
|
52
|
-
return {
|
|
58
|
+
return {
|
|
59
|
+
clientId: ANTIGRAVITY_DEFAULT_CLIENT_ID,
|
|
60
|
+
clientSecret: ANTIGRAVITY_DEFAULT_CLIENT_SECRET,
|
|
61
|
+
};
|
|
53
62
|
}
|
|
54
63
|
/** Normalize the configured API origin and reject paths/credentials. */
|
|
55
64
|
export function antigravityBaseURL(value) {
|
|
56
65
|
const parsed = new URL(value?.trim() || ANTIGRAVITY_DEFAULT_BASE_URL);
|
|
57
|
-
if (parsed.protocol !== 'https:' ||
|
|
66
|
+
if (parsed.protocol !== 'https:' ||
|
|
67
|
+
parsed.username.length > 0 ||
|
|
68
|
+
parsed.password.length > 0) {
|
|
58
69
|
throw new Error('config.antigravity.baseURL must be an HTTPS origin without credentials');
|
|
59
70
|
}
|
|
60
|
-
if (parsed.pathname !== '/' ||
|
|
71
|
+
if (parsed.pathname !== '/' ||
|
|
72
|
+
parsed.search.length > 0 ||
|
|
73
|
+
parsed.hash.length > 0) {
|
|
61
74
|
throw new Error('config.antigravity.baseURL must not contain a path, query, or fragment');
|
|
62
75
|
}
|
|
63
76
|
return parsed.origin;
|
|
@@ -79,7 +92,8 @@ async function fetchAntigravity(method, init, runtime, fetchFn) {
|
|
|
79
92
|
throw error;
|
|
80
93
|
continue;
|
|
81
94
|
}
|
|
82
|
-
if (index === endpoints.length - 1 ||
|
|
95
|
+
if (index === endpoints.length - 1 ||
|
|
96
|
+
![404, 502, 503, 504].includes(response.status))
|
|
83
97
|
return response;
|
|
84
98
|
await response.body?.cancel();
|
|
85
99
|
}
|
|
@@ -111,7 +125,7 @@ export function antigravityFlow(oauth) {
|
|
|
111
125
|
/** Shared Antigravity API headers. */
|
|
112
126
|
export function antigravityHeaders(accessToken, userAgent = ANTIGRAVITY_DEFAULT_USER_AGENT) {
|
|
113
127
|
return {
|
|
114
|
-
|
|
128
|
+
authorization: `Bearer ${accessToken}`,
|
|
115
129
|
'content-type': 'application/json',
|
|
116
130
|
'user-agent': userAgent,
|
|
117
131
|
};
|
|
@@ -122,7 +136,7 @@ async function callInternal(method, body, accessToken, runtime, fetchFn, signal)
|
|
|
122
136
|
method: 'POST',
|
|
123
137
|
headers: antigravityHeaders(accessToken, runtime.userAgent),
|
|
124
138
|
body: JSON.stringify(body),
|
|
125
|
-
...signal === undefined ? {} : { signal },
|
|
139
|
+
...(signal === undefined ? {} : { signal }),
|
|
126
140
|
}, runtime, fetchFn);
|
|
127
141
|
if (!response.ok)
|
|
128
142
|
throw await httpLlmError(response, `Antigravity ${method}`);
|
|
@@ -140,11 +154,15 @@ function projectIdOf(value) {
|
|
|
140
154
|
}
|
|
141
155
|
/** Read (and, when enabled, initialize) the Antigravity project/account. */
|
|
142
156
|
export async function discoverAntigravityAccount(accessToken, runtime = {}, fetchFn = hostFetch) {
|
|
143
|
-
const metadata = {
|
|
157
|
+
const metadata = {
|
|
158
|
+
ideType: 'ANTIGRAVITY',
|
|
159
|
+
platform: 'PLATFORM_UNSPECIFIED',
|
|
160
|
+
pluginType: 'GEMINI',
|
|
161
|
+
};
|
|
144
162
|
const load = await callInternal('loadCodeAssist', { metadata }, accessToken, runtime, fetchFn);
|
|
145
163
|
let projectId = projectIdOf(load.cloudaicompanionProject);
|
|
146
164
|
if (projectId === undefined && runtime.onboard !== false) {
|
|
147
|
-
const tierId = load.allowedTiers?.find(tier => tier.isDefault)?.id ?? 'LEGACY';
|
|
165
|
+
const tierId = load.allowedTiers?.find((tier) => tier.isDefault)?.id ?? 'LEGACY';
|
|
148
166
|
const onboardBody = { tierId, metadata };
|
|
149
167
|
for (let attempt = 0; attempt < 10; attempt++) {
|
|
150
168
|
const result = await callInternal('onboardUser', onboardBody, accessToken, runtime, fetchFn);
|
|
@@ -152,7 +170,7 @@ export async function discoverAntigravityAccount(accessToken, runtime = {}, fetc
|
|
|
152
170
|
projectId = projectIdOf(result.response?.cloudaicompanionProject);
|
|
153
171
|
break;
|
|
154
172
|
}
|
|
155
|
-
await new Promise(resolve => setTimeout(resolve, 1_000));
|
|
173
|
+
await new Promise((resolve) => setTimeout(resolve, 1_000));
|
|
156
174
|
}
|
|
157
175
|
}
|
|
158
176
|
if (projectId === undefined) {
|
|
@@ -161,10 +179,13 @@ export async function discoverAntigravityAccount(accessToken, runtime = {}, fetc
|
|
|
161
179
|
let account;
|
|
162
180
|
try {
|
|
163
181
|
const profileResponse = await fetchFn(ANTIGRAVITY_USERINFO_URL, {
|
|
164
|
-
headers: {
|
|
182
|
+
headers: {
|
|
183
|
+
authorization: `Bearer ${accessToken}`,
|
|
184
|
+
accept: 'application/json',
|
|
185
|
+
},
|
|
165
186
|
});
|
|
166
187
|
if (profileResponse.ok) {
|
|
167
|
-
const profile = await profileResponse.json();
|
|
188
|
+
const profile = (await profileResponse.json());
|
|
168
189
|
if (typeof profile.email === 'string' && profile.email.length > 0)
|
|
169
190
|
account = profile.email;
|
|
170
191
|
}
|
|
@@ -172,15 +193,19 @@ export async function discoverAntigravityAccount(accessToken, runtime = {}, fetc
|
|
|
172
193
|
catch {
|
|
173
194
|
// Identity is display-only; project discovery is the login boundary.
|
|
174
195
|
}
|
|
175
|
-
const plan = load.paidTier?.name ??
|
|
196
|
+
const plan = load.paidTier?.name ??
|
|
197
|
+
load.paidTier?.id ??
|
|
198
|
+
load.currentTier?.name ??
|
|
199
|
+
load.currentTier?.id;
|
|
176
200
|
return {
|
|
177
201
|
projectId,
|
|
178
|
-
...account === undefined ? {} : { account },
|
|
179
|
-
...typeof plan !== 'string' || plan.length === 0 ? {} : { plan },
|
|
202
|
+
...(account === undefined ? {} : { account }),
|
|
203
|
+
...(typeof plan !== 'string' || plan.length === 0 ? {} : { plan }),
|
|
180
204
|
};
|
|
181
205
|
}
|
|
182
206
|
function sessionFromTokens(tokens, account, fallback) {
|
|
183
|
-
if (typeof tokens.access_token !== 'string' ||
|
|
207
|
+
if (typeof tokens.access_token !== 'string' ||
|
|
208
|
+
tokens.access_token.length === 0) {
|
|
184
209
|
throw new Error('Antigravity token endpoint returned no access token');
|
|
185
210
|
}
|
|
186
211
|
const refreshToken = tokens.refresh_token ?? fallback?.refreshToken;
|
|
@@ -195,9 +220,9 @@ function sessionFromTokens(tokens, account, fallback) {
|
|
|
195
220
|
refreshToken,
|
|
196
221
|
expiresAt: Date.now() + tokens.expires_in * 1000,
|
|
197
222
|
projectId: account.projectId,
|
|
198
|
-
...tokens.scope === undefined ? {} : { scopes: tokens.scope },
|
|
199
|
-
...account.account === undefined ? {} : { account: account.account },
|
|
200
|
-
...account.plan === undefined ? {} : { plan: account.plan },
|
|
223
|
+
...(tokens.scope === undefined ? {} : { scopes: tokens.scope }),
|
|
224
|
+
...(account.account === undefined ? {} : { account: account.account }),
|
|
225
|
+
...(account.plan === undefined ? {} : { plan: account.plan }),
|
|
201
226
|
};
|
|
202
227
|
}
|
|
203
228
|
/** Exchange a Google OAuth authorization code and discover the Antigravity project. */
|
|
@@ -208,7 +233,9 @@ export async function exchangeAntigravityCode(code, verifier, redirectUri, oauth
|
|
|
208
233
|
redirect_uri: redirectUri,
|
|
209
234
|
client_id: oauth.clientId,
|
|
210
235
|
code_verifier: verifier,
|
|
211
|
-
...oauth.clientSecret === undefined
|
|
236
|
+
...(oauth.clientSecret === undefined
|
|
237
|
+
? {}
|
|
238
|
+
: { client_secret: oauth.clientSecret }),
|
|
212
239
|
});
|
|
213
240
|
const response = await fetchFn(ANTIGRAVITY_TOKEN_URL, {
|
|
214
241
|
method: 'POST',
|
|
@@ -217,7 +244,7 @@ export async function exchangeAntigravityCode(code, verifier, redirectUri, oauth
|
|
|
217
244
|
});
|
|
218
245
|
if (!response.ok)
|
|
219
246
|
throw await oauthEndpointError(response, 'Antigravity');
|
|
220
|
-
const tokens = await parseProviderJson(response, 'Antigravity token exchange');
|
|
247
|
+
const tokens = (await parseProviderJson(response, 'Antigravity token exchange'));
|
|
221
248
|
if (typeof tokens.access_token !== 'string')
|
|
222
249
|
throw new Error('Antigravity token endpoint returned no access token');
|
|
223
250
|
const account = await discoverAntigravityAccount(tokens.access_token, runtime, fetchFn);
|
|
@@ -229,7 +256,9 @@ export async function refreshAntigravity(session, oauth, fetchFn = hostFetch) {
|
|
|
229
256
|
grant_type: 'refresh_token',
|
|
230
257
|
refresh_token: session.refreshToken,
|
|
231
258
|
client_id: oauth.clientId,
|
|
232
|
-
...oauth.clientSecret === undefined
|
|
259
|
+
...(oauth.clientSecret === undefined
|
|
260
|
+
? {}
|
|
261
|
+
: { client_secret: oauth.clientSecret }),
|
|
233
262
|
});
|
|
234
263
|
const response = await fetchFn(ANTIGRAVITY_TOKEN_URL, {
|
|
235
264
|
method: 'POST',
|
|
@@ -238,17 +267,17 @@ export async function refreshAntigravity(session, oauth, fetchFn = hostFetch) {
|
|
|
238
267
|
});
|
|
239
268
|
if (!response.ok)
|
|
240
269
|
throw await oauthEndpointError(response, 'Antigravity');
|
|
241
|
-
return sessionFromTokens(await parseProviderJson(response, 'Antigravity token refresh'), {
|
|
270
|
+
return sessionFromTokens((await parseProviderJson(response, 'Antigravity token refresh')), {
|
|
242
271
|
projectId: session.projectId,
|
|
243
|
-
...session.account === undefined ? {} : { account: session.account },
|
|
244
|
-
...session.plan === undefined ? {} : { plan: session.plan },
|
|
272
|
+
...(session.account === undefined ? {} : { account: session.account }),
|
|
273
|
+
...(session.plan === undefined ? {} : { plan: session.plan }),
|
|
245
274
|
}, session);
|
|
246
275
|
}
|
|
247
276
|
/** Refresh failures that require a fresh Google consent grant. */
|
|
248
277
|
export function isAntigravityPermanentRefreshError(error) {
|
|
249
|
-
return error instanceof OAuthEndpointError
|
|
250
|
-
|
|
251
|
-
|
|
278
|
+
return (error instanceof OAuthEndpointError &&
|
|
279
|
+
(error.status === 400 || error.status === 401 || error.status === 403) &&
|
|
280
|
+
(error.oauthCode === 'invalid_grant' || error.status !== 400));
|
|
252
281
|
}
|
|
253
282
|
/** Fetch the authenticated account's live Antigravity model catalog. */
|
|
254
283
|
export async function fetchAntigravityModels(session, runtime = {}, fetchFn = hostFetch, signal) {
|
|
@@ -258,11 +287,22 @@ export async function fetchAntigravityModels(session, runtime = {}, fetchFn = ho
|
|
|
258
287
|
}
|
|
259
288
|
const models = Object.entries(payload.models).map(([id, model]) => ({
|
|
260
289
|
id,
|
|
261
|
-
name: model.displayName ??
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
290
|
+
name: model.displayName ??
|
|
291
|
+
id
|
|
292
|
+
.split('-')
|
|
293
|
+
.map((word) => word.length === 0 ? word : word[0].toUpperCase() + word.slice(1))
|
|
294
|
+
.join(' '),
|
|
295
|
+
...(model.description === undefined
|
|
296
|
+
? {}
|
|
297
|
+
: { description: model.description }),
|
|
298
|
+
contextWindow: model.inputTokenLimit ??
|
|
299
|
+
model.maxInputTokens ??
|
|
300
|
+
ANTIGRAVITY_CONTEXT_WINDOW,
|
|
301
|
+
...(typeof model.maxOutputTokens === 'number' &&
|
|
302
|
+
Number.isSafeInteger(model.maxOutputTokens) &&
|
|
303
|
+
model.maxOutputTokens > 0
|
|
304
|
+
? { maxOutputTokens: model.maxOutputTokens }
|
|
305
|
+
: {}),
|
|
266
306
|
inputModalities: ['text', 'image'],
|
|
267
307
|
}));
|
|
268
308
|
if (models.length === 0)
|
|
@@ -284,12 +324,16 @@ function usageWindow(kind, scope, quota) {
|
|
|
284
324
|
kind,
|
|
285
325
|
scope,
|
|
286
326
|
usedPercent: Math.max(0, Math.min(100, (1 - remaining) * 100)),
|
|
287
|
-
...resetsAt === undefined ? {} : { resetsAt },
|
|
327
|
+
...(resetsAt === undefined ? {} : { resetsAt }),
|
|
288
328
|
};
|
|
289
329
|
}
|
|
290
330
|
/** Fetch plan and per-model quota windows when the upstream exposes them. */
|
|
291
331
|
export async function fetchAntigravityUsage(session, runtime = {}, fetchFn = hostFetch, signal) {
|
|
292
|
-
const metadata = {
|
|
332
|
+
const metadata = {
|
|
333
|
+
ideType: 'ANTIGRAVITY',
|
|
334
|
+
platform: 'PLATFORM_UNSPECIFIED',
|
|
335
|
+
pluginType: 'GEMINI',
|
|
336
|
+
};
|
|
293
337
|
const [models, account] = await Promise.all([
|
|
294
338
|
callInternal('fetchAvailableModels', { project: session.projectId }, session.accessToken, runtime, fetchFn, signal),
|
|
295
339
|
callInternal('loadCodeAssist', { metadata }, session.accessToken, runtime, fetchFn, signal),
|
|
@@ -303,14 +347,19 @@ export async function fetchAntigravityUsage(session, runtime = {}, fetchFn = hos
|
|
|
303
347
|
if (weekly !== undefined)
|
|
304
348
|
windows.push(weekly);
|
|
305
349
|
}
|
|
306
|
-
const plan = account.paidTier?.name ??
|
|
307
|
-
|
|
350
|
+
const plan = account.paidTier?.name ??
|
|
351
|
+
account.paidTier?.id ??
|
|
352
|
+
account.currentTier?.name ??
|
|
353
|
+
account.currentTier?.id ??
|
|
354
|
+
session.plan;
|
|
308
355
|
const credits = account.paidTier?.availableCredits?.[0]?.creditAmount;
|
|
309
|
-
const displayPlan = credits === undefined
|
|
356
|
+
const displayPlan = credits === undefined
|
|
357
|
+
? plan
|
|
358
|
+
: `${plan ?? 'Antigravity'} · ${String(credits)} credits`;
|
|
310
359
|
return {
|
|
311
360
|
supported: true,
|
|
312
361
|
windows,
|
|
313
|
-
...displayPlan === undefined ? {} : { plan: displayPlan },
|
|
362
|
+
...(displayPlan === undefined ? {} : { plan: displayPlan }),
|
|
314
363
|
};
|
|
315
364
|
}
|
|
316
365
|
/** Forward one already-built payload to generateContent or streamGenerateContent. */
|
|
@@ -322,7 +371,7 @@ export async function requestAntigravityContent(session, payload, stream, runtim
|
|
|
322
371
|
accept: stream ? 'text/event-stream' : 'application/json',
|
|
323
372
|
},
|
|
324
373
|
body: JSON.stringify(payload),
|
|
325
|
-
...signal === undefined ? {} : { signal },
|
|
374
|
+
...(signal === undefined ? {} : { signal }),
|
|
326
375
|
}, runtime, fetchFn);
|
|
327
376
|
}
|
|
328
377
|
/** DSH provider adapter for the `antigravity` route. */
|
|
@@ -345,7 +394,9 @@ export class AntigravityAdapter extends LlmAdapter {
|
|
|
345
394
|
this.accountCatalogs.clear();
|
|
346
395
|
else
|
|
347
396
|
this.accountCatalogs.delete(account);
|
|
348
|
-
if (account === undefined ||
|
|
397
|
+
if (account === undefined ||
|
|
398
|
+
this.catalogOwner === account ||
|
|
399
|
+
this.catalogOwner === undefined) {
|
|
349
400
|
this.catalogOwner = undefined;
|
|
350
401
|
this.catalog.invalidate();
|
|
351
402
|
}
|
|
@@ -372,7 +423,7 @@ export class AntigravityAdapter extends LlmAdapter {
|
|
|
372
423
|
return subscriptionRetryPolicy(DEFAULT_RETRY, this.options.rateLimit ?? DEFAULT_RATE_LIMIT_WAIT, `antigravity: provider "${provider}" retryPolicy`);
|
|
373
424
|
}
|
|
374
425
|
staticModels(provider) {
|
|
375
|
-
return this.options.models.map(model => ({
|
|
426
|
+
return this.options.models.map((model) => ({
|
|
376
427
|
provider,
|
|
377
428
|
id: model.id,
|
|
378
429
|
name: model.name ?? model.id,
|
|
@@ -380,7 +431,9 @@ export class AntigravityAdapter extends LlmAdapter {
|
|
|
380
431
|
}));
|
|
381
432
|
}
|
|
382
433
|
fetchCatalog(account, signal) {
|
|
383
|
-
return this.options.tokens
|
|
434
|
+
return this.options.tokens
|
|
435
|
+
.session(account)
|
|
436
|
+
.then((session) => fetchAntigravityModels(session, this.options.runtime, this.options.fetchFn, signal));
|
|
384
437
|
}
|
|
385
438
|
async listModels(provider) {
|
|
386
439
|
const own = await this.listOwnModels(provider);
|
|
@@ -388,30 +441,35 @@ export class AntigravityAdapter extends LlmAdapter {
|
|
|
388
441
|
if (pool === undefined)
|
|
389
442
|
return own;
|
|
390
443
|
const extra = await pool.modelsForProvider(provider);
|
|
391
|
-
const seen = new Set(own.map(model => model.id));
|
|
444
|
+
const seen = new Set(own.map((model) => model.id));
|
|
392
445
|
// Account pools reuse the catalog row; only configured tiers are extra.
|
|
393
|
-
return [...own, ...extra.filter(model => !seen.has(model.id))];
|
|
446
|
+
return [...own, ...extra.filter((model) => !seen.has(model.id))];
|
|
394
447
|
}
|
|
395
448
|
/** The provider's own catalog: union of every account, or one account when named. */
|
|
396
449
|
async listOwnModels(provider, account, signal) {
|
|
397
450
|
if (account === undefined) {
|
|
398
|
-
const accounts = (await this.options.tokens.list()).map(entry => entry.key);
|
|
451
|
+
const accounts = (await this.options.tokens.list()).map((entry) => entry.key);
|
|
399
452
|
if (accounts.length === 0)
|
|
400
453
|
return [];
|
|
401
|
-
return unionAccountCatalogs(accounts, (key, accountSignal) => this.listOwnModels(provider, key, accountSignal), {
|
|
454
|
+
return unionAccountCatalogs(accounts, (key, accountSignal) => this.listOwnModels(provider, key, accountSignal), {
|
|
455
|
+
timeoutMs: DISCOVERY_TIMEOUT_MS,
|
|
456
|
+
...(signal === undefined ? {} : { signal }),
|
|
457
|
+
});
|
|
402
458
|
}
|
|
403
|
-
if (await this.options.tokens.peek(account) === undefined)
|
|
459
|
+
if ((await this.options.tokens.peek(account)) === undefined)
|
|
404
460
|
return [];
|
|
405
461
|
if (!this.options.discovery)
|
|
406
462
|
return this.staticModels(provider);
|
|
407
463
|
const catalog = await this.catalogFor(account);
|
|
408
464
|
try {
|
|
409
|
-
const models = await discoverOrRetryAuth(force => this.options.tokens.session(account, force), catalog, () => catalog.get(() => this.fetchCatalog(account, signal)));
|
|
410
|
-
return models.map(model => ({
|
|
465
|
+
const models = await discoverOrRetryAuth((force) => this.options.tokens.session(account, force), catalog, () => catalog.get(() => this.fetchCatalog(account, signal)));
|
|
466
|
+
return models.map((model) => ({
|
|
411
467
|
provider,
|
|
412
468
|
id: model.id,
|
|
413
469
|
name: model.name,
|
|
414
|
-
...model.description === undefined
|
|
470
|
+
...(model.description === undefined
|
|
471
|
+
? {}
|
|
472
|
+
: { description: model.description }),
|
|
415
473
|
inputModalities: model.inputModalities ?? ['text', 'image'],
|
|
416
474
|
}));
|
|
417
475
|
}
|
|
@@ -427,16 +485,19 @@ export class AntigravityAdapter extends LlmAdapter {
|
|
|
427
485
|
async discovered(model, account) {
|
|
428
486
|
if (!this.options.discovery)
|
|
429
487
|
return undefined;
|
|
430
|
-
const accounts = account === undefined
|
|
488
|
+
const accounts = account === undefined
|
|
489
|
+
? (await this.options.tokens.list()).map((entry) => entry.key)
|
|
490
|
+
: [account];
|
|
431
491
|
return discoverAcrossAccounts(accounts, async (key) => {
|
|
432
492
|
const catalog = await this.catalogFor(key);
|
|
433
493
|
const models = await catalog.resolve(() => this.fetchCatalog(key));
|
|
434
|
-
return models?.find(entry => entry.id === model);
|
|
494
|
+
return models?.find((entry) => entry.id === model);
|
|
435
495
|
});
|
|
436
496
|
}
|
|
437
497
|
async resolveModel(provider, model) {
|
|
438
498
|
const pool = this.options.pool?.();
|
|
439
|
-
if (pool !== undefined &&
|
|
499
|
+
if (pool !== undefined &&
|
|
500
|
+
(await pool.owns(provider, model))) {
|
|
440
501
|
return pool.resolveModel(provider, model);
|
|
441
502
|
}
|
|
442
503
|
return this.resolveOwnModel(provider, model);
|
|
@@ -444,26 +505,36 @@ export class AntigravityAdapter extends LlmAdapter {
|
|
|
444
505
|
/** Capability resolution of the provider's own models (the pool resolves members here). */
|
|
445
506
|
async resolveOwnModel(provider, model, account) {
|
|
446
507
|
const discovered = await this.discovered(model, account);
|
|
447
|
-
const configured = this.options.models.find(entry => entry.id === model);
|
|
508
|
+
const configured = this.options.models.find((entry) => entry.id === model);
|
|
448
509
|
const reasoning = mergeReasoning(this.options.defaultEffortOf?.(model), antigravityReasoning(model));
|
|
449
510
|
const outputLimit = discovered?.maxOutputTokens;
|
|
450
511
|
const preferredMaxTokens = configured?.maxTokens ?? outputLimit ?? ANTIGRAVITY_DEFAULT_MAX_TOKENS;
|
|
451
512
|
// Configuration may lower the default, but must not exceed a known server cap.
|
|
452
|
-
const defaultMaxTokens = outputLimit === undefined
|
|
513
|
+
const defaultMaxTokens = outputLimit === undefined
|
|
514
|
+
? preferredMaxTokens
|
|
515
|
+
: Math.min(preferredMaxTokens, outputLimit);
|
|
453
516
|
return {
|
|
454
517
|
provider,
|
|
455
518
|
id: model,
|
|
456
519
|
name: discovered?.name ?? configured?.name ?? model,
|
|
457
|
-
...discovered?.description === undefined
|
|
458
|
-
|
|
459
|
-
|
|
520
|
+
...(discovered?.description === undefined
|
|
521
|
+
? {}
|
|
522
|
+
: { description: discovered.description }),
|
|
523
|
+
inputModalities: discovered?.inputModalities ??
|
|
524
|
+
configured?.inputModalities ?? ['text', 'image'],
|
|
525
|
+
context: {
|
|
526
|
+
contextWindow: discovered?.contextWindow ??
|
|
527
|
+
configured?.contextWindow ??
|
|
528
|
+
ANTIGRAVITY_CONTEXT_WINDOW,
|
|
529
|
+
},
|
|
460
530
|
defaultMaxTokens,
|
|
461
|
-
...reasoning === undefined ? {} : { reasoning },
|
|
531
|
+
...(reasoning === undefined ? {} : { reasoning }),
|
|
462
532
|
};
|
|
463
533
|
}
|
|
464
534
|
async *stream(options) {
|
|
465
535
|
const pool = this.options.pool?.();
|
|
466
|
-
if (pool !== undefined &&
|
|
536
|
+
if (pool !== undefined &&
|
|
537
|
+
(await pool.owns(options.provider, options.model))) {
|
|
467
538
|
yield* pool.stream(options);
|
|
468
539
|
return;
|
|
469
540
|
}
|
|
@@ -491,7 +562,9 @@ export class AntigravityAdapter extends LlmAdapter {
|
|
|
491
562
|
if (response.body === null) {
|
|
492
563
|
throw new LlmError('Antigravity API returned no response body', EMPTY_RESPONSE_CODE);
|
|
493
564
|
}
|
|
494
|
-
yield* streamAntigravity(response.body, () => {
|
|
565
|
+
yield* streamAntigravity(response.body, () => {
|
|
566
|
+
watchdog.pulse();
|
|
567
|
+
});
|
|
495
568
|
}
|
|
496
569
|
catch (error) {
|
|
497
570
|
throw mapFetchFailure('Antigravity API', error, watchdog, options.signal);
|
|
@@ -507,6 +580,6 @@ export class AntigravityAdapter extends LlmAdapter {
|
|
|
507
580
|
const response = await requestAntigravityContent(session, toAntigravityRequest(options, messages, session.projectId), false, this.options.runtime, this.options.fetchFn, options.signal);
|
|
508
581
|
if (!response.ok)
|
|
509
582
|
throw await httpLlmError(response, 'Antigravity API');
|
|
510
|
-
return parseAntigravityResponse(await parseProviderJson(response, 'Antigravity generateContent'));
|
|
583
|
+
return parseAntigravityResponse((await parseProviderJson(response, 'Antigravity generateContent')));
|
|
511
584
|
}
|
|
512
585
|
}
|