shariq-pi-extensions 0.2.3 → 0.2.5
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/docs/EXTENSIONS.md +1 -1
- package/extensions/antigravity-provider/README.md +4 -5
- package/extensions/antigravity-provider/antigravity/accounts.ts +88 -9
- package/extensions/antigravity-provider/antigravity/dashboard.ts +22 -8
- package/extensions/antigravity-provider/antigravity/models.ts +0 -66
- package/extensions/antigravity-provider/antigravity/oauth.ts +21 -1
- package/extensions/antigravity-provider/antigravity/quotas.ts +3 -1
- package/extensions/subagents/index.ts +1 -1
- package/extensions/subagents/src/backends/pi.ts +8 -3
- package/extensions/subagents/src/domain.ts +2 -2
- package/package.json +1 -1
package/docs/EXTENSIONS.md
CHANGED
|
@@ -6,7 +6,7 @@ Last verified: 2026-08-20
|
|
|
6
6
|
|
|
7
7
|
### [Antigravity Provider](../extensions/antigravity-provider/README.md)
|
|
8
8
|
|
|
9
|
-
Registers the `antigravity` provider and `/login antigravity` flow for
|
|
9
|
+
Registers the `antigravity` provider and `/login antigravity` flow for the latest Gemini Flash, Gemini Pro, Claude Sonnet, and Claude Opus families. Repeating login adds or updates accounts in the secure `<agent-dir>/antigravity/accounts.json` pool. Requests use quota-aware least-recently-used balancing, rotate before streaming on account-specific auth/rate/quota/capacity failures, honor known reset times, and refresh stored OAuth tokens. `/antigravity` shows account state plus the shared five-hour and weekly limits for the Gemini and Claude pools and can enable or disable accounts; `/antigravity.doctor` reports sanitized provider and rotation diagnostics.
|
|
10
10
|
|
|
11
11
|
### [Cursor provider](../extensions/cursor-provider/README.md)
|
|
12
12
|
|
|
@@ -8,19 +8,18 @@ Local persistent Pi provider for Google Antigravity-compatible models.
|
|
|
8
8
|
- Account and quota dashboard: `/antigravity`
|
|
9
9
|
- Doctor command: `/antigravity.doctor`
|
|
10
10
|
|
|
11
|
-
The provider includes an IPv4 OAuth token-exchange fallback for Node environments where the default request fails. Its
|
|
11
|
+
The provider includes an IPv4 OAuth token-exchange fallback for Node environments where the default request fails. Its curated catalog follows current Antigravity model identifiers and runtime behavior.
|
|
12
12
|
|
|
13
13
|
Successful logins are added to `<agent-dir>/antigravity/accounts.json`, written with owner-only permissions. Existing Pi OAuth credentials are migrated into that pool without exposing token values. Requests select the least recently used eligible account, skip disabled/cooling/exhausted accounts, refresh expiring OAuth tokens, and rotate to another account when an auth, rate, quota, or capacity failure occurs before response streaming begins. Cached per-model remaining quota and reset times guide selection; `/antigravity` refreshes the authoritative catalog and can reversibly enable or disable accounts.
|
|
14
14
|
|
|
15
15
|
Current public model IDs:
|
|
16
16
|
- `antigravity/gemini-3.7-flash`
|
|
17
|
-
- `antigravity/gemini-3.6-flash`
|
|
18
|
-
- `antigravity/gemini-3.5-flash`
|
|
19
17
|
- `antigravity/gemini-3.1-pro`
|
|
20
18
|
- `antigravity/claude-sonnet-4-6`
|
|
21
19
|
- `antigravity/claude-opus-4-6`
|
|
22
|
-
- `antigravity/gpt-oss-120b`
|
|
23
20
|
|
|
24
|
-
|
|
21
|
+
The provider intentionally exposes only the latest Gemini Flash and Pro generations and the latest Claude Sonnet and Opus family. `/antigravity` shows the shared five-hour and weekly limits for the Gemini and Claude pools instead of listing every upstream runtime variant.
|
|
22
|
+
|
|
23
|
+
Pi's thinking selector is normalized to Antigravity's runtime IDs: Gemini 3.7 Flash clamps `off`/`minimal` to `low` and `xhigh`/`max` to `high`; Gemini 3.1 Pro clamps to its `low`/`high` pair; Claude models use their fixed-thinking runtime regardless of the selected Pi level.
|
|
25
24
|
|
|
26
25
|
The provider id intentionally remains `antigravity`; existing `~/.pi/agent/auth.json` credentials continue to work without moving secret values. After updating `agy`, compare `agy models` with `antigravity/models.ts` before changing this deterministic catalog.
|
|
@@ -14,11 +14,13 @@ const CAPACITY_COOLDOWN_MS = 60 * 1_000;
|
|
|
14
14
|
const REFRESH_SKEW_MS = 60 * 1_000;
|
|
15
15
|
|
|
16
16
|
export type AntigravityQuotaGroup = "gemini" | "non-gemini";
|
|
17
|
+
export type AntigravityQuotaWindow = "five-hour" | "weekly";
|
|
17
18
|
|
|
18
19
|
export interface AntigravityQuotaEntry {
|
|
19
20
|
modelId: string;
|
|
20
21
|
displayName?: string;
|
|
21
22
|
group: AntigravityQuotaGroup;
|
|
23
|
+
window?: AntigravityQuotaWindow;
|
|
22
24
|
remainingFraction: number;
|
|
23
25
|
resetTime?: string;
|
|
24
26
|
}
|
|
@@ -78,6 +80,7 @@ function normalizeAccount(value: unknown): AntigravityAccount | undefined {
|
|
|
78
80
|
modelId: entry.modelId,
|
|
79
81
|
displayName: typeof entry.displayName === "string" ? entry.displayName : undefined,
|
|
80
82
|
group: entry.group,
|
|
83
|
+
window: entry.window === "five-hour" || entry.window === "weekly" ? entry.window : undefined,
|
|
81
84
|
remainingFraction: Math.max(0, Math.min(1, remainingFraction)),
|
|
82
85
|
resetTime: typeof entry.resetTime === "string" ? entry.resetTime : undefined,
|
|
83
86
|
}];
|
|
@@ -281,7 +284,74 @@ export function updateAntigravityAccountQuota(id: string, quota: AntigravityQuot
|
|
|
281
284
|
}
|
|
282
285
|
|
|
283
286
|
export function parseAntigravityQuota(value: unknown): AntigravityQuotaEntry[] {
|
|
284
|
-
const
|
|
287
|
+
const findGroups = (node: unknown): unknown[] | undefined => {
|
|
288
|
+
if (!node || typeof node !== "object") return undefined;
|
|
289
|
+
if (Array.isArray(node)) {
|
|
290
|
+
for (const item of node) {
|
|
291
|
+
const found = findGroups(item);
|
|
292
|
+
if (found) return found;
|
|
293
|
+
}
|
|
294
|
+
return undefined;
|
|
295
|
+
}
|
|
296
|
+
const raw = node as Record<string, unknown>;
|
|
297
|
+
if (Array.isArray(raw.groups)) return raw.groups;
|
|
298
|
+
for (const child of Object.values(raw)) {
|
|
299
|
+
const found = findGroups(child);
|
|
300
|
+
if (found) return found;
|
|
301
|
+
}
|
|
302
|
+
return undefined;
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
const summaryEntries: AntigravityQuotaEntry[] = [];
|
|
306
|
+
for (const groupValue of findGroups(value) ?? []) {
|
|
307
|
+
if (!groupValue || typeof groupValue !== "object") continue;
|
|
308
|
+
const group = groupValue as Record<string, unknown>;
|
|
309
|
+
const groupLabel = [group.displayName, group.name, group.id].find((item): item is string => typeof item === "string") ?? "";
|
|
310
|
+
const quotaGroup: AntigravityQuotaGroup | undefined = /gemini/i.test(groupLabel)
|
|
311
|
+
? "gemini"
|
|
312
|
+
: /claude|third.party|3p|gpt/i.test(groupLabel)
|
|
313
|
+
? "non-gemini"
|
|
314
|
+
: undefined;
|
|
315
|
+
if (!quotaGroup || !Array.isArray(group.buckets)) continue;
|
|
316
|
+
for (const bucketValue of group.buckets) {
|
|
317
|
+
if (!bucketValue || typeof bucketValue !== "object") continue;
|
|
318
|
+
const bucket = bucketValue as Record<string, unknown>;
|
|
319
|
+
const remaining = bucket.remaining && typeof bucket.remaining === "object"
|
|
320
|
+
? bucket.remaining as Record<string, unknown>
|
|
321
|
+
: undefined;
|
|
322
|
+
const remainingFraction = finiteNumber(bucket.remainingFraction) ?? finiteNumber(remaining?.remainingFraction);
|
|
323
|
+
const windowLabel = [bucket.window, bucket.bucketId, bucket.displayName].find((item): item is string => typeof item === "string") ?? "";
|
|
324
|
+
const window: AntigravityQuotaWindow | undefined = /week/i.test(windowLabel)
|
|
325
|
+
? "weekly"
|
|
326
|
+
: /5h|five.?hour/i.test(windowLabel)
|
|
327
|
+
? "five-hour"
|
|
328
|
+
: undefined;
|
|
329
|
+
if (remainingFraction === undefined || !window) continue;
|
|
330
|
+
summaryEntries.push({
|
|
331
|
+
modelId: typeof bucket.bucketId === "string" ? bucket.bucketId : `${quotaGroup}-${window}`,
|
|
332
|
+
displayName: window === "weekly" ? "Weekly" : "5-Hour",
|
|
333
|
+
group: quotaGroup,
|
|
334
|
+
window,
|
|
335
|
+
remainingFraction: Math.max(0, Math.min(1, remainingFraction)),
|
|
336
|
+
resetTime: typeof bucket.resetTime === "string"
|
|
337
|
+
? bucket.resetTime
|
|
338
|
+
: typeof remaining?.resetTime === "string"
|
|
339
|
+
? remaining.resetTime
|
|
340
|
+
: undefined,
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
if (summaryEntries.length) return summaryEntries;
|
|
345
|
+
|
|
346
|
+
const supportedRuntimeIds = new Set(
|
|
347
|
+
Object.entries(ANTIGRAVITY_ROUTING).flatMap(([modelId, routing]) => [
|
|
348
|
+
modelId,
|
|
349
|
+
routing.off,
|
|
350
|
+
routing.defaultRequestId,
|
|
351
|
+
...Object.values(routing.routing ?? {}),
|
|
352
|
+
]).filter((item): item is string => typeof item === "string"),
|
|
353
|
+
);
|
|
354
|
+
const modelEntries: AntigravityQuotaEntry[] = [];
|
|
285
355
|
const seen = new Set<string>();
|
|
286
356
|
const visit = (node: unknown, keyHint?: string) => {
|
|
287
357
|
if (!node || typeof node !== "object") return;
|
|
@@ -291,17 +361,17 @@ export function parseAntigravityQuota(value: unknown): AntigravityQuotaEntry[] {
|
|
|
291
361
|
}
|
|
292
362
|
const raw = node as Record<string, unknown>;
|
|
293
363
|
const quota = raw.quotaInfo && typeof raw.quotaInfo === "object" ? raw.quotaInfo as Record<string, unknown> : raw;
|
|
294
|
-
const
|
|
295
|
-
const modelId = [raw.modelId, raw.id, raw.name, raw.model, keyHint].find((item): item is string => typeof item === "string"
|
|
296
|
-
if (modelId &&
|
|
364
|
+
const remainingFraction = finiteNumber(quota.remainingFraction);
|
|
365
|
+
const modelId = [raw.modelId, raw.id, raw.name, raw.model, keyHint].find((item): item is string => typeof item === "string");
|
|
366
|
+
if (modelId && remainingFraction !== undefined) {
|
|
297
367
|
const normalized = modelId.replace(/^models\//, "");
|
|
298
|
-
if (!seen.has(normalized)) {
|
|
368
|
+
if (supportedRuntimeIds.has(normalized) && !seen.has(normalized)) {
|
|
299
369
|
seen.add(normalized);
|
|
300
|
-
|
|
370
|
+
modelEntries.push({
|
|
301
371
|
modelId: normalized,
|
|
302
|
-
displayName: typeof raw.displayName === "string" ? raw.displayName : typeof raw.label === "string" ? raw.label : undefined,
|
|
303
372
|
group: normalized.startsWith("gemini-") ? "gemini" : "non-gemini",
|
|
304
|
-
|
|
373
|
+
window: "five-hour",
|
|
374
|
+
remainingFraction: Math.max(0, Math.min(1, remainingFraction)),
|
|
305
375
|
resetTime: typeof quota.resetTime === "string" ? quota.resetTime : undefined,
|
|
306
376
|
});
|
|
307
377
|
}
|
|
@@ -311,7 +381,16 @@ export function parseAntigravityQuota(value: unknown): AntigravityQuotaEntry[] {
|
|
|
311
381
|
}
|
|
312
382
|
};
|
|
313
383
|
visit(value);
|
|
314
|
-
|
|
384
|
+
|
|
385
|
+
return (["gemini", "non-gemini"] as const).flatMap((group) => {
|
|
386
|
+
const entries = modelEntries.filter((entry) => entry.group === group).sort((left, right) => left.remainingFraction - right.remainingFraction);
|
|
387
|
+
const mostConstrained = entries[0];
|
|
388
|
+
return mostConstrained ? [{
|
|
389
|
+
...mostConstrained,
|
|
390
|
+
modelId: group === "gemini" ? "gemini-5h" : "claude-5h",
|
|
391
|
+
displayName: "5-Hour",
|
|
392
|
+
}] : [];
|
|
393
|
+
});
|
|
315
394
|
}
|
|
316
395
|
|
|
317
396
|
const refreshes = new Map<string, Promise<AntigravityAccount>>();
|
|
@@ -29,7 +29,22 @@ function until(timestamp: number | string | undefined) {
|
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
function groupQuota(quota: AntigravityQuotaEntry[] | undefined, group: "gemini" | "non-gemini") {
|
|
32
|
-
|
|
32
|
+
const byWindow = new Map<"five-hour" | "weekly", AntigravityQuotaEntry>();
|
|
33
|
+
for (const entry of (quota ?? []).filter((candidate) => candidate.group === group)) {
|
|
34
|
+
const window = entry.window ?? "five-hour";
|
|
35
|
+
const existing = byWindow.get(window);
|
|
36
|
+
if (!existing || entry.remainingFraction < existing.remainingFraction) {
|
|
37
|
+
byWindow.set(window, {
|
|
38
|
+
...entry,
|
|
39
|
+
window,
|
|
40
|
+
displayName: window === "weekly" ? "Weekly" : "5-Hour",
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return (["five-hour", "weekly"] as const).flatMap((window) => {
|
|
45
|
+
const entry = byWindow.get(window);
|
|
46
|
+
return entry ? [entry] : [];
|
|
47
|
+
});
|
|
33
48
|
}
|
|
34
49
|
|
|
35
50
|
function accountState(account: AntigravityAccountStatus) {
|
|
@@ -50,8 +65,7 @@ function stateColor(state: string) {
|
|
|
50
65
|
|
|
51
66
|
function compactGroup(label: string, entries: AntigravityQuotaEntry[]) {
|
|
52
67
|
if (!entries.length) return `${label}: unavailable`;
|
|
53
|
-
|
|
54
|
-
return `${label}: ${remaining(worst.remainingFraction)} remaining${worst.resetTime ? ` · resets ${until(worst.resetTime)}` : ""}`;
|
|
68
|
+
return `${label}: ${entries.map((entry) => `${entry.displayName} ${remaining(entry.remainingFraction)}${entry.resetTime ? ` · resets ${until(entry.resetTime)}` : ""}`).join(" · ")}`;
|
|
55
69
|
}
|
|
56
70
|
|
|
57
71
|
export class AntigravityDashboard implements Component {
|
|
@@ -159,7 +173,7 @@ export class AntigravityDashboard implements Component {
|
|
|
159
173
|
const lines = width >= 64
|
|
160
174
|
? [joinSides(title, `${right} `, width)]
|
|
161
175
|
: [truncateToWidth(title, width, ""), truncateToWidth(` ${right}`, width, "")];
|
|
162
|
-
lines.push(frameTop(this.theme, width, `ACCOUNTS ${accounts.length} ·
|
|
176
|
+
lines.push(frameTop(this.theme, width, `ACCOUNTS ${accounts.length} · 5-HOUR + WEEKLY LIMITS REMAINING`));
|
|
163
177
|
const inner = Math.max(1, width - 2);
|
|
164
178
|
if (width >= 104 && selected) {
|
|
165
179
|
const leftWidth = Math.max(46, Math.floor((inner - 1) * 0.45));
|
|
@@ -195,7 +209,7 @@ export class AntigravityDashboard implements Component {
|
|
|
195
209
|
lines.push(selected ? this.theme.bg("selectedBg", padLine(first, width)) : first);
|
|
196
210
|
if (!compact) {
|
|
197
211
|
lines.push(` ${this.theme.fg("muted", compactGroup("Gemini", groupQuota(account.quota, "gemini")))}`);
|
|
198
|
-
lines.push(` ${this.theme.fg("muted", compactGroup("Claude
|
|
212
|
+
lines.push(` ${this.theme.fg("muted", compactGroup("Claude", groupQuota(account.quota, "non-gemini")))}`);
|
|
199
213
|
lines.push("");
|
|
200
214
|
}
|
|
201
215
|
}
|
|
@@ -211,8 +225,8 @@ export class AntigravityDashboard implements Component {
|
|
|
211
225
|
if (account.cooldownUntil && account.cooldownUntil > Date.now()) lines.push(` ${this.theme.fg("warning", `${account.cooldownReason || "rotation"} cooldown · ${until(account.cooldownUntil)}`)}`);
|
|
212
226
|
if (account.quotaError) lines.push(` ${this.theme.fg("error", oneLine(account.quotaError))}`);
|
|
213
227
|
if (account.lastError) lines.push(` ${this.theme.fg("warning", oneLine(account.lastError))}`);
|
|
214
|
-
lines.push("", ...this.renderQuotaGroup("Gemini", groupQuota(account.quota, "gemini"), width));
|
|
215
|
-
lines.push("", ...this.renderQuotaGroup("Claude
|
|
228
|
+
lines.push("", ...this.renderQuotaGroup("Gemini models", groupQuota(account.quota, "gemini"), width));
|
|
229
|
+
lines.push("", ...this.renderQuotaGroup("Claude models", groupQuota(account.quota, "non-gemini"), width));
|
|
216
230
|
if (account.lastUsedAt) lines.push("", ` ${this.theme.fg("muted", "LAST USED")} ${this.theme.fg("text", new Date(account.lastUsedAt).toLocaleString())}`);
|
|
217
231
|
return lines.slice(0, height);
|
|
218
232
|
}
|
|
@@ -221,7 +235,7 @@ export class AntigravityDashboard implements Component {
|
|
|
221
235
|
const lines = [` ${this.theme.fg("accent", this.theme.bold(`${name.toUpperCase()} · REMAINING`))}`];
|
|
222
236
|
if (!entries.length) return [...lines, ` ${this.theme.fg("muted", "Unavailable")}`];
|
|
223
237
|
const meterWidth = Math.max(10, width - 29);
|
|
224
|
-
for (const entry of entries
|
|
238
|
+
for (const entry of entries) {
|
|
225
239
|
const percent = entry.remainingFraction * 100;
|
|
226
240
|
const color = percent <= 0 ? "error" : percent <= 15 ? "warning" : "active";
|
|
227
241
|
const label = oneLine(entry.displayName || entry.modelId).slice(0, 16).padEnd(16);
|
|
@@ -59,42 +59,6 @@ export const ANTIGRAVITY_ROUTING: Record<string, AntigravityRouting> = {
|
|
|
59
59
|
},
|
|
60
60
|
defaultRequestId: "gemini-3.7-flash-low",
|
|
61
61
|
},
|
|
62
|
-
"gemini-3.6-flash": {
|
|
63
|
-
off: "gemini-3.6-flash-low",
|
|
64
|
-
routing: {
|
|
65
|
-
minimal: "gemini-3.6-flash-low",
|
|
66
|
-
low: "gemini-3.6-flash-low",
|
|
67
|
-
medium: "gemini-3.6-flash-medium",
|
|
68
|
-
high: "gemini-3.6-flash-high",
|
|
69
|
-
xhigh: "gemini-3.6-flash-high",
|
|
70
|
-
max: "gemini-3.6-flash-high",
|
|
71
|
-
},
|
|
72
|
-
defaultRequestId: "gemini-3.6-flash-low",
|
|
73
|
-
},
|
|
74
|
-
"gemini-3.5-flash": {
|
|
75
|
-
off: "gemini-3.5-flash-extra-low",
|
|
76
|
-
routing: {
|
|
77
|
-
minimal: "gemini-3.5-flash-extra-low",
|
|
78
|
-
low: "gemini-3.5-flash-extra-low",
|
|
79
|
-
medium: "gemini-3.5-flash-low",
|
|
80
|
-
high: "gemini-3-flash-agent",
|
|
81
|
-
xhigh: "gemini-3-flash-agent",
|
|
82
|
-
max: "gemini-3-flash-agent",
|
|
83
|
-
},
|
|
84
|
-
defaultRequestId: "gemini-3.5-flash-low",
|
|
85
|
-
},
|
|
86
|
-
"gpt-oss-120b": {
|
|
87
|
-
off: "gpt-oss-120b-medium",
|
|
88
|
-
routing: {
|
|
89
|
-
minimal: "gpt-oss-120b-medium",
|
|
90
|
-
low: "gpt-oss-120b-medium",
|
|
91
|
-
medium: "gpt-oss-120b-medium",
|
|
92
|
-
high: "gpt-oss-120b-medium",
|
|
93
|
-
xhigh: "gpt-oss-120b-medium",
|
|
94
|
-
max: "gpt-oss-120b-medium",
|
|
95
|
-
},
|
|
96
|
-
defaultRequestId: "gpt-oss-120b-medium",
|
|
97
|
-
},
|
|
98
62
|
};
|
|
99
63
|
|
|
100
64
|
export const ANTIGRAVITY_MODELS: ProviderModelConfig[] = [
|
|
@@ -138,36 +102,6 @@ export const ANTIGRAVITY_MODELS: ProviderModelConfig[] = [
|
|
|
138
102
|
contextWindow: 1048576,
|
|
139
103
|
maxTokens: 65536,
|
|
140
104
|
},
|
|
141
|
-
{
|
|
142
|
-
id: "gemini-3.6-flash",
|
|
143
|
-
name: "Gemini 3.6 Flash (Antigravity)",
|
|
144
|
-
reasoning: true,
|
|
145
|
-
thinkingLevelMap: { off: null, minimal: "LOW", low: "LOW", medium: "MEDIUM", high: "HIGH", xhigh: "HIGH", max: "HIGH" } as any,
|
|
146
|
-
input: ["text", "image"],
|
|
147
|
-
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
148
|
-
contextWindow: 1048576,
|
|
149
|
-
maxTokens: 65536,
|
|
150
|
-
},
|
|
151
|
-
{
|
|
152
|
-
id: "gemini-3.5-flash",
|
|
153
|
-
name: "Gemini 3.5 Flash (Antigravity)",
|
|
154
|
-
reasoning: true,
|
|
155
|
-
thinkingLevelMap: { off: null, minimal: "LOW", low: "LOW", medium: "MEDIUM", high: "HIGH", xhigh: "HIGH", max: "HIGH" } as any,
|
|
156
|
-
input: ["text", "image"],
|
|
157
|
-
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
158
|
-
contextWindow: 1048576,
|
|
159
|
-
maxTokens: 65536,
|
|
160
|
-
},
|
|
161
|
-
{
|
|
162
|
-
id: "gpt-oss-120b",
|
|
163
|
-
name: "GPT-OSS 120B (Antigravity)",
|
|
164
|
-
reasoning: true,
|
|
165
|
-
thinkingLevelMap: { off: null, minimal: "MEDIUM", low: "MEDIUM", medium: "MEDIUM", high: "MEDIUM", xhigh: "MEDIUM", max: "MEDIUM" } as any,
|
|
166
|
-
input: ["text"],
|
|
167
|
-
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
168
|
-
contextWindow: 131072,
|
|
169
|
-
maxTokens: 32768,
|
|
170
|
-
},
|
|
171
105
|
];
|
|
172
106
|
|
|
173
107
|
export function getAntigravityRequestModelId(modelId: string, effort: string | undefined): string {
|
|
@@ -322,8 +322,28 @@ function findDynamicModel(value: any, requestedId: string): DynamicModelInfo | u
|
|
|
322
322
|
|
|
323
323
|
export async function fetchAntigravityQuotaCatalog(token: string, projectId: string, signal?: AbortSignal): Promise<unknown> {
|
|
324
324
|
let lastFailure = "Antigravity quota catalog is unavailable.";
|
|
325
|
-
const bodies = [{}, { cloudaicompanionProject: projectId }, { project: projectId }];
|
|
326
325
|
for (const endpoint of endpointCandidates()) {
|
|
326
|
+
try {
|
|
327
|
+
const res = await fetch(`${endpoint}/v1internal:retrieveUserQuotaSummary`, {
|
|
328
|
+
method: "POST",
|
|
329
|
+
headers: antigravityHeaders(token),
|
|
330
|
+
body: "{}",
|
|
331
|
+
signal: boundedFetchSignal(signal),
|
|
332
|
+
});
|
|
333
|
+
lastStatus = res.status;
|
|
334
|
+
lastEndpoint = endpoint;
|
|
335
|
+
if (res.ok) {
|
|
336
|
+
const summary = await res.json() as { groups?: unknown[] };
|
|
337
|
+
if (Array.isArray(summary.groups) && summary.groups.length) return summary;
|
|
338
|
+
}
|
|
339
|
+
else lastFailure = `HTTP ${res.status}: ${jsonOrTextError(await res.text())}`;
|
|
340
|
+
} catch (error) {
|
|
341
|
+
if (signal?.aborted) throw error;
|
|
342
|
+
lastFailure = safeError(error);
|
|
343
|
+
lastError = lastFailure;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
const bodies = [{}, { cloudaicompanionProject: projectId }, { project: projectId }];
|
|
327
347
|
for (const candidateBody of bodies) {
|
|
328
348
|
try {
|
|
329
349
|
const res = await fetch(`${endpoint}/v1internal:fetchAvailableModels`, {
|
|
@@ -20,7 +20,9 @@ export function refreshAntigravityQuotas(options: { force?: boolean; signal?: Ab
|
|
|
20
20
|
const accounts = antigravityAccountStatuses(now);
|
|
21
21
|
for (const account of accounts) {
|
|
22
22
|
if (account.disabled) continue;
|
|
23
|
-
|
|
23
|
+
const hasBothWindows = account.quota?.some((entry) => entry.window === "five-hour") &&
|
|
24
|
+
account.quota.some((entry) => entry.window === "weekly");
|
|
25
|
+
if (!options.force && hasBothWindows && account.quotaUpdatedAt && now - account.quotaUpdatedAt < ANTIGRAVITY_QUOTA_TTL_MS) continue;
|
|
24
26
|
try {
|
|
25
27
|
const resolved = await resolveAntigravityAccount(account, refreshAntigravityToken, now);
|
|
26
28
|
const catalog = await fetchAntigravityQuotaCatalog(resolved.access, resolved.projectId, options.signal);
|
|
@@ -480,7 +480,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
480
480
|
childCwd: cwd,
|
|
481
481
|
parentTrusted: ctx.isProjectTrusted(),
|
|
482
482
|
}),
|
|
483
|
-
inheritedModel: ctx.model
|
|
483
|
+
inheritedModel: ctx.model ?? undefined,
|
|
484
484
|
inheritedThinkingLevel: pi.getThinkingLevel(),
|
|
485
485
|
inheritedMessages,
|
|
486
486
|
parentSessionFile: ctx.sessionManager.getSessionFile(),
|
|
@@ -186,14 +186,17 @@ function createParentBridgeTools(task: SpawnTask): ToolDefinition[] {
|
|
|
186
186
|
* then must be unambiguous across providers. No hint inherits the parent
|
|
187
187
|
* model; with nothing to inherit, the SDK default applies.
|
|
188
188
|
*/
|
|
189
|
-
function resolvePiModel(
|
|
189
|
+
export function resolvePiModel(
|
|
190
190
|
registry: ModelRegistry,
|
|
191
191
|
hint: string | undefined,
|
|
192
|
-
inherited:
|
|
192
|
+
inherited: Model<any> | undefined,
|
|
193
193
|
): Model<any> | undefined {
|
|
194
194
|
if (!hint) {
|
|
195
195
|
if (!inherited) return undefined;
|
|
196
|
-
return registry.find(inherited.provider, inherited.id) ??
|
|
196
|
+
return registry.find(inherited.provider, inherited.id) ?? inherited;
|
|
197
|
+
}
|
|
198
|
+
if (inherited?.id === hint) {
|
|
199
|
+
return registry.find(inherited.provider, hint) ?? inherited;
|
|
197
200
|
}
|
|
198
201
|
const slash = hint.indexOf("/");
|
|
199
202
|
if (slash > 0) {
|
|
@@ -201,11 +204,13 @@ function resolvePiModel(
|
|
|
201
204
|
const id = hint.slice(slash + 1);
|
|
202
205
|
const found = registry.find(provider, id);
|
|
203
206
|
if (found) return found;
|
|
207
|
+
if (inherited?.provider === provider && inherited.id === id) return inherited;
|
|
204
208
|
throw new Error(`Unknown model "${hint}".`);
|
|
205
209
|
}
|
|
206
210
|
if (inherited) {
|
|
207
211
|
const found = registry.find(inherited.provider, hint);
|
|
208
212
|
if (found) return found;
|
|
213
|
+
if (inherited.id === hint) return inherited;
|
|
209
214
|
}
|
|
210
215
|
const matches = registry.getAll().filter((m) => m.id === hint);
|
|
211
216
|
if (matches.length === 1) return matches[0];
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* `SubagentEvent` union.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import type { Message } from "@earendil-works/pi-ai";
|
|
9
|
+
import type { Message, Model } from "@earendil-works/pi-ai";
|
|
10
10
|
import type { ModelRegistry } from "@earendil-works/pi-coding-agent";
|
|
11
11
|
import { Data } from "effect";
|
|
12
12
|
import type { CapabilityMode, IsolationMode } from "./config.ts";
|
|
@@ -50,7 +50,7 @@ export interface ParentContext {
|
|
|
50
50
|
/** In-process bridge used by child-only message_parent/ask_parent tools. */
|
|
51
51
|
readonly bridge?: ParentBridge;
|
|
52
52
|
/** Parent pi model, for the pi backend's "inherit" default. */
|
|
53
|
-
readonly inheritedModel?:
|
|
53
|
+
readonly inheritedModel?: Model<any>;
|
|
54
54
|
readonly inheritedThinkingLevel?: string;
|
|
55
55
|
/** Parent model registry; required by the pi backend to resolve models. */
|
|
56
56
|
readonly modelRegistry?: ModelRegistry;
|