pi-provider-antigravity 0.16.0 → 0.17.0
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/dist/index.js +272 -173
- package/dist/index.js.map +3 -3
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -1,77 +1,25 @@
|
|
|
1
1
|
// src/auth.ts
|
|
2
2
|
import { createHash, randomBytes } from "node:crypto";
|
|
3
3
|
|
|
4
|
-
// src/
|
|
5
|
-
var DEFAULT_ENDPOINT = "https://daily-cloudcode-pa.googleapis.com";
|
|
6
|
-
var DEFAULT_USER_AGENT = "antigravity/cli/1.2.7 (aidev_client; os_type=linux; arch=amd64; cl=984112147; auth_method=consumer)";
|
|
4
|
+
// src/constants.ts
|
|
7
5
|
var PROVIDER_ID = "antigravity";
|
|
8
|
-
var
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
super(`Antigravity request to ${path2} failed (${status}): ${errorBody}`);
|
|
14
|
-
this.name = "AntigravityHttpError";
|
|
15
|
-
this.status = status;
|
|
16
|
-
this.path = path2;
|
|
17
|
-
this.errorBody = errorBody;
|
|
18
|
-
}
|
|
19
|
-
};
|
|
20
|
-
function resolveToken(auth) {
|
|
21
|
-
if (typeof auth === "string") return auth;
|
|
22
|
-
if (auth && typeof auth.token === "string") return auth.token;
|
|
23
|
-
throw new Error("Invalid auth parameter: missing token string");
|
|
24
|
-
}
|
|
25
|
-
async function postAntigravityRaw({
|
|
26
|
-
auth,
|
|
27
|
-
path: path2,
|
|
28
|
-
endpoint = DEFAULT_ENDPOINT,
|
|
29
|
-
headers,
|
|
30
|
-
body,
|
|
31
|
-
signal
|
|
32
|
-
}) {
|
|
33
|
-
const token = resolveToken(auth);
|
|
34
|
-
return fetch(`${endpoint}/${path2}`, {
|
|
35
|
-
method: "POST",
|
|
36
|
-
headers: { ...buildAntigravityHeaders(token), ...headers },
|
|
37
|
-
body: JSON.stringify(body),
|
|
38
|
-
signal
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
async function postAntigravityJson(params) {
|
|
42
|
-
const res = await postAntigravityRaw(params);
|
|
43
|
-
if (!res.ok) {
|
|
44
|
-
const errText = await res.text();
|
|
45
|
-
throw new AntigravityHttpError(res.status, params.path, errText);
|
|
46
|
-
}
|
|
47
|
-
return await res.json();
|
|
48
|
-
}
|
|
49
|
-
async function postAntigravityStream(params) {
|
|
50
|
-
const res = await postAntigravityRaw(params);
|
|
51
|
-
if (!res.ok) {
|
|
52
|
-
const errText = await res.text();
|
|
53
|
-
throw new AntigravityHttpError(res.status, params.path, errText);
|
|
54
|
-
}
|
|
55
|
-
if (!res.body) {
|
|
56
|
-
throw new Error(`No response stream received from Antigravity for ${params.path}.`);
|
|
57
|
-
}
|
|
58
|
-
return { response: res, stream: res.body };
|
|
59
|
-
}
|
|
60
|
-
function buildAntigravityHeaders(token, userAgent = DEFAULT_USER_AGENT) {
|
|
61
|
-
return {
|
|
62
|
-
Host: "daily-cloudcode-pa.googleapis.com",
|
|
63
|
-
"User-Agent": userAgent,
|
|
64
|
-
"Content-Type": "application/json",
|
|
65
|
-
Authorization: `Bearer ${token}`
|
|
66
|
-
};
|
|
67
|
-
}
|
|
6
|
+
var PROVIDER_NAME = "Antigravity";
|
|
7
|
+
var DEFAULT_HOST = "daily-cloudcode-pa.googleapis.com";
|
|
8
|
+
var DEFAULT_ENDPOINT = `https://${DEFAULT_HOST}`;
|
|
9
|
+
var DEFAULT_USER_AGENT = "antigravity/cli/1.2.9 (aidev_client; os_type=linux; arch=amd64; cl=986394137; auth_method=consumer)";
|
|
10
|
+
var FALLBACK_PROJECT_ID = "aicode-consumers";
|
|
68
11
|
|
|
69
12
|
// src/auth.ts
|
|
13
|
+
var AntigravityAuthError = class extends Error {
|
|
14
|
+
constructor(message = NOT_LOGGED_IN) {
|
|
15
|
+
super(message);
|
|
16
|
+
this.name = "AntigravityAuthError";
|
|
17
|
+
}
|
|
18
|
+
};
|
|
70
19
|
var REDIRECT_URI = "https://antigravity.google/oauth-callback";
|
|
71
20
|
var AUTH_URL = "https://accounts.google.com/o/oauth2/auth";
|
|
72
21
|
var TOKEN_URL = "https://oauth2.googleapis.com/token";
|
|
73
22
|
var OAUTH_CALLBACK_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
74
|
-
var FALLBACK_PROJECT_ID = "aicode-consumers";
|
|
75
23
|
var SCOPES = [
|
|
76
24
|
"https://www.googleapis.com/auth/cloud-platform",
|
|
77
25
|
"https://www.googleapis.com/auth/userinfo.email",
|
|
@@ -112,14 +60,22 @@ function generatePKCE() {
|
|
|
112
60
|
}
|
|
113
61
|
async function fetchProjectId(token, signal) {
|
|
114
62
|
try {
|
|
115
|
-
const
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
63
|
+
const res = await fetch(`${DEFAULT_ENDPOINT}/v1internal:loadCodeAssist`, {
|
|
64
|
+
method: "POST",
|
|
65
|
+
headers: {
|
|
66
|
+
Host: DEFAULT_HOST,
|
|
67
|
+
"User-Agent": DEFAULT_USER_AGENT,
|
|
68
|
+
"Content-Type": "application/json",
|
|
69
|
+
Authorization: `Bearer ${token}`
|
|
70
|
+
},
|
|
71
|
+
body: JSON.stringify({ metadata: { ideType: "ANTIGRAVITY" } }),
|
|
119
72
|
signal
|
|
120
73
|
});
|
|
121
|
-
if (
|
|
122
|
-
|
|
74
|
+
if (res.ok) {
|
|
75
|
+
const data = await res.json();
|
|
76
|
+
if (data.cloudaicompanionProject) {
|
|
77
|
+
return data.cloudaicompanionProject;
|
|
78
|
+
}
|
|
123
79
|
}
|
|
124
80
|
} catch (err) {
|
|
125
81
|
if (signal?.aborted) throw err;
|
|
@@ -262,7 +218,7 @@ var NOT_LOGGED_IN = "Not logged in. Run /login antigravity first.";
|
|
|
262
218
|
async function requireCredentials(source, errorMessage = NOT_LOGGED_IN) {
|
|
263
219
|
const creds = await resolveCredentials(source);
|
|
264
220
|
if (!creds) {
|
|
265
|
-
throw new
|
|
221
|
+
throw new AntigravityAuthError(errorMessage);
|
|
266
222
|
}
|
|
267
223
|
return creds;
|
|
268
224
|
}
|
|
@@ -277,20 +233,158 @@ function parseStoredCredentials(rawApiKey) {
|
|
|
277
233
|
return { token: rawApiKey, projectId: FALLBACK_PROJECT_ID };
|
|
278
234
|
}
|
|
279
235
|
|
|
236
|
+
// src/protocol.ts
|
|
237
|
+
var AntigravityHttpError = class extends Error {
|
|
238
|
+
status;
|
|
239
|
+
path;
|
|
240
|
+
errorBody;
|
|
241
|
+
constructor(status, path2, errorBody) {
|
|
242
|
+
super(`Antigravity request to ${path2} failed (${status}): ${errorBody}`);
|
|
243
|
+
this.name = "AntigravityHttpError";
|
|
244
|
+
this.status = status;
|
|
245
|
+
this.path = path2;
|
|
246
|
+
this.errorBody = errorBody;
|
|
247
|
+
}
|
|
248
|
+
};
|
|
249
|
+
function resolveToken(auth) {
|
|
250
|
+
if (typeof auth === "string") return auth;
|
|
251
|
+
if (auth && typeof auth.token === "string") return auth.token;
|
|
252
|
+
throw new Error("Invalid auth parameter: missing token string");
|
|
253
|
+
}
|
|
254
|
+
async function postAntigravityRaw({
|
|
255
|
+
auth,
|
|
256
|
+
path: path2,
|
|
257
|
+
endpoint = DEFAULT_ENDPOINT,
|
|
258
|
+
headers,
|
|
259
|
+
body,
|
|
260
|
+
signal
|
|
261
|
+
}) {
|
|
262
|
+
const token = resolveToken(auth);
|
|
263
|
+
return fetch(`${endpoint}/${path2}`, {
|
|
264
|
+
method: "POST",
|
|
265
|
+
headers: { ...buildAntigravityHeaders(token), ...headers },
|
|
266
|
+
body: JSON.stringify(body),
|
|
267
|
+
signal
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
async function postAntigravityJson(params) {
|
|
271
|
+
const res = await postAntigravityRaw(params);
|
|
272
|
+
if (!res.ok) {
|
|
273
|
+
const errText = await res.text();
|
|
274
|
+
throw new AntigravityHttpError(res.status, params.path, errText);
|
|
275
|
+
}
|
|
276
|
+
return await res.json();
|
|
277
|
+
}
|
|
278
|
+
async function postAntigravityStream(params) {
|
|
279
|
+
const res = await postAntigravityRaw(params);
|
|
280
|
+
if (!res.ok) {
|
|
281
|
+
const errText = await res.text();
|
|
282
|
+
throw new AntigravityHttpError(res.status, params.path, errText);
|
|
283
|
+
}
|
|
284
|
+
if (!res.body) {
|
|
285
|
+
throw new Error(`No response stream received from Antigravity for ${params.path}.`);
|
|
286
|
+
}
|
|
287
|
+
return { response: res, stream: res.body };
|
|
288
|
+
}
|
|
289
|
+
function buildAntigravityHeaders(token, userAgent = DEFAULT_USER_AGENT) {
|
|
290
|
+
return {
|
|
291
|
+
Host: DEFAULT_HOST,
|
|
292
|
+
"User-Agent": userAgent,
|
|
293
|
+
"Content-Type": "application/json",
|
|
294
|
+
Authorization: `Bearer ${token}`
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
function createAntigravityClient(options) {
|
|
298
|
+
const endpoint = options?.endpoint || DEFAULT_ENDPOINT;
|
|
299
|
+
const userAgent = options?.userAgent || DEFAULT_USER_AGENT;
|
|
300
|
+
return {
|
|
301
|
+
endpoint,
|
|
302
|
+
userAgent,
|
|
303
|
+
async fetchAvailableModels(source, signal) {
|
|
304
|
+
const creds = await requireCredentials(source);
|
|
305
|
+
return postAntigravityJson({
|
|
306
|
+
auth: creds.token,
|
|
307
|
+
endpoint,
|
|
308
|
+
path: "v1internal:fetchAvailableModels",
|
|
309
|
+
body: { project: creds.projectId },
|
|
310
|
+
signal
|
|
311
|
+
});
|
|
312
|
+
},
|
|
313
|
+
async retrieveQuotaSummary(source, signal) {
|
|
314
|
+
const creds = await resolveCredentials(source);
|
|
315
|
+
if (!creds) return void 0;
|
|
316
|
+
return postAntigravityJson({
|
|
317
|
+
auth: creds.token,
|
|
318
|
+
endpoint,
|
|
319
|
+
path: "v1internal:retrieveUserQuotaSummary",
|
|
320
|
+
body: { project: creds.projectId },
|
|
321
|
+
signal
|
|
322
|
+
});
|
|
323
|
+
},
|
|
324
|
+
async streamGenerateContent(params) {
|
|
325
|
+
const creds = await requireCredentials(params.source);
|
|
326
|
+
return postAntigravityStream({
|
|
327
|
+
auth: creds.token,
|
|
328
|
+
endpoint: params.endpoint || endpoint,
|
|
329
|
+
path: "v1internal:streamGenerateContent?alt=sse",
|
|
330
|
+
headers: params.headers,
|
|
331
|
+
body: params.body,
|
|
332
|
+
signal: params.signal
|
|
333
|
+
});
|
|
334
|
+
},
|
|
335
|
+
async postJson(source, path2, body = {}, signal, headers) {
|
|
336
|
+
const creds = await requireCredentials(source);
|
|
337
|
+
const effectiveBody = body && typeof body === "object" && !Array.isArray(body) ? { project: creds.projectId, ...body } : body;
|
|
338
|
+
return postAntigravityJson({
|
|
339
|
+
auth: creds.token,
|
|
340
|
+
endpoint,
|
|
341
|
+
path: path2,
|
|
342
|
+
body: effectiveBody,
|
|
343
|
+
headers,
|
|
344
|
+
signal
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
var defaultAntigravityClient = createAntigravityClient();
|
|
350
|
+
|
|
280
351
|
// src/model-identity.ts
|
|
281
|
-
function
|
|
352
|
+
function getModelProfile(modelId) {
|
|
282
353
|
const bare = ((modelId || "").split("/").pop() || "").toLowerCase();
|
|
283
|
-
|
|
284
|
-
if (bare.startsWith("
|
|
285
|
-
if (bare.startsWith("
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
const
|
|
292
|
-
|
|
293
|
-
|
|
354
|
+
let family = "unknown";
|
|
355
|
+
if (bare.startsWith("gemini-")) family = "gemini";
|
|
356
|
+
else if (bare.startsWith("claude-")) family = "claude";
|
|
357
|
+
else if (bare.startsWith("gpt-")) family = "gpt";
|
|
358
|
+
const isGemini = family === "gemini";
|
|
359
|
+
const isClaude = family === "claude";
|
|
360
|
+
const isGpt = family === "gpt";
|
|
361
|
+
const isNonGemini = family !== "gemini";
|
|
362
|
+
const quotaPoolKind = isClaude || isGpt ? "3p" : "gemini";
|
|
363
|
+
const replaysReasoningHistory = family !== "gpt";
|
|
364
|
+
const isFlash = bare.includes("flash");
|
|
365
|
+
const defaultContextWindow = isFlash ? 1048576 : isClaude ? 25e4 : isGpt ? 128e3 : 1048576;
|
|
366
|
+
const defaultMaxOutputTokens = isClaude ? 64e3 : isGpt ? 32768 : 65536;
|
|
367
|
+
const promptCache = isClaude ? { short: 300, long: 3600 } : { short: 300 };
|
|
368
|
+
return {
|
|
369
|
+
id: modelId,
|
|
370
|
+
family,
|
|
371
|
+
isGemini,
|
|
372
|
+
isClaude,
|
|
373
|
+
isGpt,
|
|
374
|
+
isNonGemini,
|
|
375
|
+
quotaPoolKind,
|
|
376
|
+
replaysReasoningHistory,
|
|
377
|
+
defaultContextWindow,
|
|
378
|
+
defaultMaxOutputTokens,
|
|
379
|
+
promptCache,
|
|
380
|
+
isReplayCompatible(candidateModel) {
|
|
381
|
+
if (!candidateModel || !modelId) return true;
|
|
382
|
+
if (candidateModel === modelId) return true;
|
|
383
|
+
const other = getModelProfile(candidateModel);
|
|
384
|
+
if (other.family !== "unknown" && other.family === family) return true;
|
|
385
|
+
return false;
|
|
386
|
+
}
|
|
387
|
+
};
|
|
294
388
|
}
|
|
295
389
|
|
|
296
390
|
// src/model-catalog.ts
|
|
@@ -432,13 +526,8 @@ function parseAvailableModels(data) {
|
|
|
432
526
|
...Object.keys(deprecated).length > 0 ? { deprecated } : {}
|
|
433
527
|
};
|
|
434
528
|
}
|
|
435
|
-
async function fetchAvailableModelsCatalog(
|
|
436
|
-
const json = await
|
|
437
|
-
auth: token,
|
|
438
|
-
path: "v1internal:fetchAvailableModels",
|
|
439
|
-
body: { project: projectId },
|
|
440
|
-
signal
|
|
441
|
-
});
|
|
529
|
+
async function fetchAvailableModelsCatalog(source, signal, client = defaultAntigravityClient) {
|
|
530
|
+
const json = await client.fetchAvailableModels(source, signal);
|
|
442
531
|
return parseAvailableModels(json);
|
|
443
532
|
}
|
|
444
533
|
function toPersistedSnapshot(snapshot) {
|
|
@@ -509,13 +598,13 @@ function resolveModelPlan(publicModelId, effort, snapshot) {
|
|
|
509
598
|
`Unknown model "${runtimeModelId}". Run /antigravity refresh, then pick a current model.`
|
|
510
599
|
);
|
|
511
600
|
}
|
|
512
|
-
const
|
|
601
|
+
const profile = getModelProfile(runtimeModelId);
|
|
513
602
|
return {
|
|
514
603
|
runtimeModelId,
|
|
515
604
|
modelEnum,
|
|
516
605
|
thinkingConfig: resolveThinkingConfig(runtimeModelId, snapshot),
|
|
517
|
-
isNonGemini:
|
|
518
|
-
isClaude:
|
|
606
|
+
isNonGemini: profile.isNonGemini,
|
|
607
|
+
isClaude: profile.isClaude
|
|
519
608
|
};
|
|
520
609
|
}
|
|
521
610
|
function estimateModelCost(_baseId) {
|
|
@@ -544,13 +633,9 @@ function synthesizeDynamicModel(baseId, items) {
|
|
|
544
633
|
...hasVariant(tierSpellings("medium")) ? {} : { medium: null },
|
|
545
634
|
...hasVariant(tierSpellings("high")) || items.some((it) => it.id === baseId) ? {} : { high: null }
|
|
546
635
|
};
|
|
547
|
-
const
|
|
548
|
-
const
|
|
549
|
-
const
|
|
550
|
-
const isGpt = family === "gpt";
|
|
551
|
-
const defaultContext = isFlash ? 1048576 : isClaude ? 25e4 : isGpt ? 128e3 : 1048576;
|
|
552
|
-
const defaultMaxOutput = isClaude ? 64e3 : isGpt ? 32768 : 65536;
|
|
553
|
-
const promptCache = isClaude ? { short: 300, long: 3600 } : { short: 300 };
|
|
636
|
+
const profile = getModelProfile(baseId);
|
|
637
|
+
const defaultContext = profile.defaultContextWindow;
|
|
638
|
+
const defaultMaxOutput = profile.defaultMaxOutputTokens;
|
|
554
639
|
return {
|
|
555
640
|
id: baseId,
|
|
556
641
|
name: formatModelDisplayName(baseId, repItem?.displayName),
|
|
@@ -561,7 +646,7 @@ function synthesizeDynamicModel(baseId, items) {
|
|
|
561
646
|
thinkingLevelMap,
|
|
562
647
|
input: repItem?.supportsImages ? ["text", "image"] : ["text"],
|
|
563
648
|
cost: estimateModelCost(baseId),
|
|
564
|
-
promptCache,
|
|
649
|
+
promptCache: profile.promptCache,
|
|
565
650
|
contextWindow: repItem?.maxTokens || defaultContext,
|
|
566
651
|
maxTokens: repItem?.maxOutputTokens || defaultMaxOutput
|
|
567
652
|
};
|
|
@@ -639,7 +724,8 @@ function formatModelsList(catalog) {
|
|
|
639
724
|
}
|
|
640
725
|
return lines.join("\n");
|
|
641
726
|
}
|
|
642
|
-
function createModelCatalog() {
|
|
727
|
+
function createModelCatalog(deps) {
|
|
728
|
+
const client = deps?.client ?? defaultAntigravityClient;
|
|
643
729
|
let generation = { snapshot: EMPTY_SNAPSHOT(), version: 0 };
|
|
644
730
|
const record = (catalogOrRaw) => {
|
|
645
731
|
let catalog;
|
|
@@ -678,9 +764,7 @@ function createModelCatalog() {
|
|
|
678
764
|
const storedModels = () => [...context.stored?.models ?? []];
|
|
679
765
|
if (!context.allowNetwork) return storedModels();
|
|
680
766
|
try {
|
|
681
|
-
const
|
|
682
|
-
if (!creds) return storedModels();
|
|
683
|
-
const catalog = await fetchAvailableModelsCatalog(creds, creds.projectId, context.signal);
|
|
767
|
+
const catalog = await fetchAvailableModelsCatalog(context, context.signal, client);
|
|
684
768
|
record(catalog);
|
|
685
769
|
const dynamicModels = buildDynamicPublicModels(catalog);
|
|
686
770
|
if (context.publish) {
|
|
@@ -1030,8 +1114,8 @@ function isGeminiQuotaGroup(group) {
|
|
|
1030
1114
|
}
|
|
1031
1115
|
function selectQuotaGroup(groups, modelId) {
|
|
1032
1116
|
if (groups.length === 0) return void 0;
|
|
1033
|
-
const
|
|
1034
|
-
if (
|
|
1117
|
+
const profile = getModelProfile(modelId);
|
|
1118
|
+
if (profile.quotaPoolKind === "3p") {
|
|
1035
1119
|
const found = groups.find((g) => !isGeminiQuotaGroup(g));
|
|
1036
1120
|
if (found) return found;
|
|
1037
1121
|
}
|
|
@@ -1237,17 +1321,21 @@ var QuotaStatusCoordinator = class {
|
|
|
1237
1321
|
lastPairs;
|
|
1238
1322
|
store;
|
|
1239
1323
|
fetchSummaryOverride;
|
|
1324
|
+
client;
|
|
1240
1325
|
nowFn;
|
|
1241
1326
|
constructor(depsOrStoreOrFile) {
|
|
1242
1327
|
if (typeof depsOrStoreOrFile === "string" || !depsOrStoreOrFile) {
|
|
1243
1328
|
this.store = fileQuotaStatusStore(depsOrStoreOrFile || defaultConfigFile());
|
|
1329
|
+
this.client = defaultAntigravityClient;
|
|
1244
1330
|
this.nowFn = Date.now;
|
|
1245
1331
|
} else if ("loadMode" in depsOrStoreOrFile) {
|
|
1246
1332
|
this.store = depsOrStoreOrFile;
|
|
1333
|
+
this.client = defaultAntigravityClient;
|
|
1247
1334
|
this.nowFn = Date.now;
|
|
1248
1335
|
} else {
|
|
1249
1336
|
this.store = depsOrStoreOrFile.store ?? fileQuotaStatusStore(depsOrStoreOrFile.configFile || defaultConfigFile());
|
|
1250
1337
|
this.fetchSummaryOverride = depsOrStoreOrFile.fetchQuotaSummary;
|
|
1338
|
+
this.client = depsOrStoreOrFile.client ?? defaultAntigravityClient;
|
|
1251
1339
|
this.nowFn = depsOrStoreOrFile.now ?? Date.now;
|
|
1252
1340
|
}
|
|
1253
1341
|
this.weeklyTo5hRatio = DEFAULT_WEEKLY_TO_5H_RATIO;
|
|
@@ -1260,6 +1348,26 @@ var QuotaStatusCoordinator = class {
|
|
|
1260
1348
|
mode() {
|
|
1261
1349
|
return this.store.loadMode();
|
|
1262
1350
|
}
|
|
1351
|
+
bind(pi) {
|
|
1352
|
+
if (typeof pi?.on !== "function") return;
|
|
1353
|
+
pi.on("session_start", async (_event, ctx) => {
|
|
1354
|
+
await this.refreshAndPaint(ctx);
|
|
1355
|
+
});
|
|
1356
|
+
pi.on("model_select", async (event, ctx) => {
|
|
1357
|
+
const modelCtx = {
|
|
1358
|
+
ui: ctx.ui,
|
|
1359
|
+
modelRegistry: ctx.modelRegistry,
|
|
1360
|
+
model: event.model || ctx.model
|
|
1361
|
+
};
|
|
1362
|
+
await this.refreshAndPaint(modelCtx);
|
|
1363
|
+
});
|
|
1364
|
+
pi.on("agent_settled", async (_event, ctx) => {
|
|
1365
|
+
await this.refreshAndPaint(ctx);
|
|
1366
|
+
});
|
|
1367
|
+
}
|
|
1368
|
+
formatUsage(ctx) {
|
|
1369
|
+
return this.inspectUsage(ctx);
|
|
1370
|
+
}
|
|
1263
1371
|
footerFor(modelId, mode = "smart") {
|
|
1264
1372
|
return FOOTER_MODES[mode]?.render(this.summary, modelId, this.weeklyTo5hRatio, void 0, this.nowFn).plain;
|
|
1265
1373
|
}
|
|
@@ -1328,18 +1436,13 @@ var QuotaStatusCoordinator = class {
|
|
|
1328
1436
|
}
|
|
1329
1437
|
async fetch(ctx, signal) {
|
|
1330
1438
|
try {
|
|
1331
|
-
const creds = await resolveCredentials(ctx);
|
|
1332
|
-
if (!creds) return void 0;
|
|
1333
1439
|
let rawSummary;
|
|
1334
1440
|
if (this.fetchSummaryOverride) {
|
|
1441
|
+
const creds = await resolveCredentials(ctx);
|
|
1442
|
+
if (!creds) return void 0;
|
|
1335
1443
|
rawSummary = await this.fetchSummaryOverride(creds.token, signal);
|
|
1336
1444
|
} else {
|
|
1337
|
-
rawSummary = await
|
|
1338
|
-
auth: creds,
|
|
1339
|
-
path: "v1internal:retrieveUserQuotaSummary",
|
|
1340
|
-
body: { project: creds.projectId },
|
|
1341
|
-
signal
|
|
1342
|
-
});
|
|
1445
|
+
rawSummary = await this.client.retrieveQuotaSummary(ctx, signal);
|
|
1343
1446
|
}
|
|
1344
1447
|
if (!rawSummary) return void 0;
|
|
1345
1448
|
const summary = rawSummary.groups ? parseQuotaSummary(rawSummary) : rawSummary;
|
|
@@ -1516,8 +1619,9 @@ function convertTools(tools) {
|
|
|
1516
1619
|
function translateTurnTrace(conversation, runtimeModelId) {
|
|
1517
1620
|
const contents = [];
|
|
1518
1621
|
const messages = conversation || [];
|
|
1519
|
-
const
|
|
1520
|
-
const
|
|
1622
|
+
const runtimeProfile = getModelProfile(runtimeModelId);
|
|
1623
|
+
const isGeminiRequest = runtimeProfile.isGemini;
|
|
1624
|
+
const isGptRequest = runtimeProfile.isGpt;
|
|
1521
1625
|
for (const msg of messages) {
|
|
1522
1626
|
if (msg.role === "user") {
|
|
1523
1627
|
const parts = [];
|
|
@@ -1545,7 +1649,7 @@ function translateTurnTrace(conversation, runtimeModelId) {
|
|
|
1545
1649
|
continue;
|
|
1546
1650
|
}
|
|
1547
1651
|
const isSameProvider = !msg.provider || msg.provider === PROVIDER_ID;
|
|
1548
|
-
const isSameModel =
|
|
1652
|
+
const isSameModel = runtimeProfile.isReplayCompatible(msg.model);
|
|
1549
1653
|
const isSameProviderAndModel = isSameProvider && isSameModel;
|
|
1550
1654
|
const parts = [];
|
|
1551
1655
|
let pendingThinkingSig;
|
|
@@ -1984,7 +2088,7 @@ async function consumeAntigravityStream(streamBody, output, stream, model, signa
|
|
|
1984
2088
|
reader.releaseLock();
|
|
1985
2089
|
}
|
|
1986
2090
|
}
|
|
1987
|
-
function streamAntigravity(model, context, options, catalog) {
|
|
2091
|
+
function streamAntigravity(model, context, options, catalog, client = defaultAntigravityClient) {
|
|
1988
2092
|
const stream = createAssistantMessageEventStream();
|
|
1989
2093
|
(async () => {
|
|
1990
2094
|
const output = {
|
|
@@ -2038,10 +2142,9 @@ function streamAntigravity(model, context, options, catalog) {
|
|
|
2038
2142
|
if (typeof v === "string") mergedHeaders[k] = v;
|
|
2039
2143
|
}
|
|
2040
2144
|
}
|
|
2041
|
-
const { response, stream: streamBody } = await
|
|
2042
|
-
|
|
2145
|
+
const { response, stream: streamBody } = await client.streamGenerateContent({
|
|
2146
|
+
source: options,
|
|
2043
2147
|
endpoint,
|
|
2044
|
-
path: "v1internal:streamGenerateContent?alt=sse",
|
|
2045
2148
|
headers: mergedHeaders,
|
|
2046
2149
|
body: requestBody,
|
|
2047
2150
|
signal: options?.signal
|
|
@@ -2140,7 +2243,7 @@ ${sourceLines.join("\n")}`;
|
|
|
2140
2243
|
completedAt
|
|
2141
2244
|
};
|
|
2142
2245
|
}
|
|
2143
|
-
async function performWebSearch(
|
|
2246
|
+
async function performWebSearch(source, options, client = defaultAntigravityClient) {
|
|
2144
2247
|
const createdAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
2145
2248
|
let effectiveQuery = options.query.trim();
|
|
2146
2249
|
if (options.domain && options.domain.trim()) {
|
|
@@ -2150,7 +2253,6 @@ async function performWebSearch(creds, options) {
|
|
|
2150
2253
|
}
|
|
2151
2254
|
}
|
|
2152
2255
|
const reqBody = {
|
|
2153
|
-
project: creds.projectId || FALLBACK_PROJECT_ID,
|
|
2154
2256
|
request: {
|
|
2155
2257
|
contents: [
|
|
2156
2258
|
{
|
|
@@ -2181,12 +2283,12 @@ async function performWebSearch(creds, options) {
|
|
|
2181
2283
|
userAgent: "antigravity",
|
|
2182
2284
|
requestType: "web_search"
|
|
2183
2285
|
};
|
|
2184
|
-
const resp = await
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2286
|
+
const resp = await client.postJson(
|
|
2287
|
+
source,
|
|
2288
|
+
"v1internal:generateContent",
|
|
2289
|
+
reqBody,
|
|
2290
|
+
options.signal
|
|
2291
|
+
);
|
|
2190
2292
|
const completedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
2191
2293
|
const candidate = resp.response?.candidates?.[0];
|
|
2192
2294
|
const rawText = candidate?.content?.parts?.filter((p) => typeof p.text === "string").map((p) => p.text).join("") || "";
|
|
@@ -2220,15 +2322,8 @@ function registerWebSearchTool(pi) {
|
|
|
2220
2322
|
)
|
|
2221
2323
|
}),
|
|
2222
2324
|
async execute(_toolCallId, params, signal, _onUpdate, ctx) {
|
|
2223
|
-
const creds = await resolveCredentials(ctx);
|
|
2224
|
-
if (!creds) {
|
|
2225
|
-
return {
|
|
2226
|
-
content: [{ type: "text", text: `Error: ${NOT_LOGGED_IN}` }],
|
|
2227
|
-
details: { error: "not_logged_in" }
|
|
2228
|
-
};
|
|
2229
|
-
}
|
|
2230
2325
|
try {
|
|
2231
|
-
const result = await performWebSearch(
|
|
2326
|
+
const result = await performWebSearch(ctx, {
|
|
2232
2327
|
query: params.query,
|
|
2233
2328
|
domain: params.domain,
|
|
2234
2329
|
signal
|
|
@@ -2241,6 +2336,12 @@ function registerWebSearchTool(pi) {
|
|
|
2241
2336
|
}
|
|
2242
2337
|
};
|
|
2243
2338
|
} catch (err) {
|
|
2339
|
+
if (err instanceof AntigravityAuthError) {
|
|
2340
|
+
return {
|
|
2341
|
+
content: [{ type: "text", text: `Error: ${NOT_LOGGED_IN}` }],
|
|
2342
|
+
details: { error: "not_logged_in" }
|
|
2343
|
+
};
|
|
2344
|
+
}
|
|
2244
2345
|
return {
|
|
2245
2346
|
content: [{ type: "text", text: `Search failed: ${err.message}` }],
|
|
2246
2347
|
details: { error: err.message }
|
|
@@ -2250,11 +2351,6 @@ function registerWebSearchTool(pi) {
|
|
|
2250
2351
|
});
|
|
2251
2352
|
}
|
|
2252
2353
|
async function executeWebSearchCommand(ctx, query) {
|
|
2253
|
-
const creds = await resolveCredentials(ctx);
|
|
2254
|
-
if (!creds) {
|
|
2255
|
-
notifyUser(ctx, NOT_LOGGED_IN, "warning");
|
|
2256
|
-
return;
|
|
2257
|
-
}
|
|
2258
2354
|
const trimmedQuery = (query || "").trim();
|
|
2259
2355
|
if (!trimmedQuery) {
|
|
2260
2356
|
notifyUser(ctx, "Usage: /antigravity websearch <query>", "warning");
|
|
@@ -2262,12 +2358,16 @@ async function executeWebSearchCommand(ctx, query) {
|
|
|
2262
2358
|
}
|
|
2263
2359
|
try {
|
|
2264
2360
|
if (ctx.hasUI) ctx.ui.notify(`Searching: "${trimmedQuery}"\u2026`, "info");
|
|
2265
|
-
const result = await performWebSearch(
|
|
2361
|
+
const result = await performWebSearch(ctx, {
|
|
2266
2362
|
query: trimmedQuery,
|
|
2267
2363
|
signal: ctx.signal
|
|
2268
2364
|
});
|
|
2269
2365
|
notifyUser(ctx, result.formattedOutput);
|
|
2270
2366
|
} catch (err) {
|
|
2367
|
+
if (err instanceof AntigravityAuthError) {
|
|
2368
|
+
notifyUser(ctx, NOT_LOGGED_IN, "warning");
|
|
2369
|
+
return;
|
|
2370
|
+
}
|
|
2271
2371
|
notifyUser(ctx, `Search failed: ${err.message}`, "error");
|
|
2272
2372
|
}
|
|
2273
2373
|
}
|
|
@@ -2386,7 +2486,7 @@ async function runUsageSubcommand(ctx, quotaStatus) {
|
|
|
2386
2486
|
}
|
|
2387
2487
|
try {
|
|
2388
2488
|
if (ctx.hasUI) ctx.ui.notify("Fetching quota summary\u2026", "info");
|
|
2389
|
-
const text = await quotaStatus.
|
|
2489
|
+
const text = await quotaStatus.formatUsage(ctx);
|
|
2390
2490
|
emitOutput(ctx, text);
|
|
2391
2491
|
} catch (err) {
|
|
2392
2492
|
emitOutput(ctx, `Failed to fetch usage: ${err.message}`, "error");
|
|
@@ -2417,24 +2517,36 @@ function runLoginSubcommand(ctx) {
|
|
|
2417
2517
|
emitOutput(ctx, "Please run /login antigravity to authenticate.");
|
|
2418
2518
|
}
|
|
2419
2519
|
}
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2520
|
+
function createAntigravityCommands(deps) {
|
|
2521
|
+
return {
|
|
2522
|
+
async handle(args, ctx) {
|
|
2523
|
+
const raw = (args || "").trim();
|
|
2524
|
+
const parts = raw.split(/\s+/).filter(Boolean);
|
|
2525
|
+
const sub = parseAntigravitySubcommand(parts[0] || "");
|
|
2526
|
+
const subArgs = raw.slice(parts[0]?.length || 0).trim();
|
|
2527
|
+
const cmd = SUBCOMMANDS.find((c) => c.name === sub);
|
|
2528
|
+
if (cmd) {
|
|
2529
|
+
await cmd.run({
|
|
2530
|
+
ctx,
|
|
2531
|
+
quotaStatus: deps.quotaStatus,
|
|
2532
|
+
catalog: deps.catalog,
|
|
2533
|
+
subArgs
|
|
2534
|
+
});
|
|
2535
|
+
return;
|
|
2536
|
+
}
|
|
2537
|
+
emitOutput(ctx, USAGE_TEXT);
|
|
2538
|
+
},
|
|
2539
|
+
complete(prefix) {
|
|
2540
|
+
return completeSubcommands(prefix);
|
|
2541
|
+
}
|
|
2542
|
+
};
|
|
2431
2543
|
}
|
|
2432
2544
|
|
|
2433
2545
|
// src/index.ts
|
|
2434
|
-
var PROVIDER_NAME = "Antigravity";
|
|
2435
2546
|
function index_default(pi) {
|
|
2436
2547
|
const quotaStatus = createQuotaStatus();
|
|
2437
2548
|
const catalog = createModelCatalog();
|
|
2549
|
+
const commands = createAntigravityCommands({ quotaStatus, catalog });
|
|
2438
2550
|
pi.registerProvider(PROVIDER_ID, {
|
|
2439
2551
|
name: PROVIDER_NAME,
|
|
2440
2552
|
baseUrl: DEFAULT_ENDPOINT,
|
|
@@ -2453,26 +2565,13 @@ function index_default(pi) {
|
|
|
2453
2565
|
});
|
|
2454
2566
|
pi.registerCommand("antigravity", {
|
|
2455
2567
|
description: "Antigravity quota, models and settings",
|
|
2456
|
-
getArgumentCompletions: (prefix) =>
|
|
2568
|
+
getArgumentCompletions: (prefix) => commands.complete(prefix),
|
|
2457
2569
|
handler: async (args, ctx) => {
|
|
2458
|
-
await
|
|
2570
|
+
await commands.handle(args, ctx);
|
|
2459
2571
|
}
|
|
2460
2572
|
});
|
|
2461
2573
|
registerWebSearchTool(pi);
|
|
2462
|
-
|
|
2463
|
-
await quotaStatus.refreshAndPaint(ctx);
|
|
2464
|
-
});
|
|
2465
|
-
pi.on("model_select", async (event, ctx) => {
|
|
2466
|
-
const modelCtx = {
|
|
2467
|
-
ui: ctx.ui,
|
|
2468
|
-
modelRegistry: ctx.modelRegistry,
|
|
2469
|
-
model: event.model || ctx.model
|
|
2470
|
-
};
|
|
2471
|
-
await quotaStatus.refreshAndPaint(modelCtx);
|
|
2472
|
-
});
|
|
2473
|
-
pi.on("agent_settled", async (_event, ctx) => {
|
|
2474
|
-
await quotaStatus.refreshAndPaint(ctx);
|
|
2475
|
-
});
|
|
2574
|
+
quotaStatus.bind(pi);
|
|
2476
2575
|
}
|
|
2477
2576
|
export {
|
|
2478
2577
|
PROVIDER_ID,
|