@expiren/opencode-antigravity-auth 1.6.15 → 1.6.18
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 +583 -68
- package/dist/index.js.map +7 -1
- package/dist/src/constants.d.ts +13 -0
- package/dist/src/constants.d.ts.map +1 -1
- package/dist/src/constants.js +19 -1
- package/dist/src/constants.js.map +1 -1
- package/dist/src/plugin/auth-doctor.d.ts +30 -0
- package/dist/src/plugin/auth-doctor.d.ts.map +1 -0
- package/dist/src/plugin/auth-doctor.js +144 -0
- package/dist/src/plugin/auth-doctor.js.map +1 -0
- package/dist/src/plugin/auth-drift.d.ts +13 -0
- package/dist/src/plugin/auth-drift.d.ts.map +1 -0
- package/dist/src/plugin/auth-drift.js +70 -0
- package/dist/src/plugin/auth-drift.js.map +1 -0
- package/dist/src/plugin/cli.d.ts +11 -2
- package/dist/src/plugin/cli.d.ts.map +1 -1
- package/dist/src/plugin/cli.js +31 -3
- package/dist/src/plugin/cli.js.map +1 -1
- package/dist/src/plugin/config/models.d.ts +2 -32
- package/dist/src/plugin/config/models.d.ts.map +1 -1
- package/dist/src/plugin/config/models.js +1 -122
- package/dist/src/plugin/config/models.js.map +1 -1
- package/dist/src/plugin/config/schema.js +2 -2
- package/dist/src/plugin/config/schema.js.map +1 -1
- package/dist/src/plugin/model-registry.d.ts +46 -0
- package/dist/src/plugin/model-registry.d.ts.map +1 -0
- package/dist/src/plugin/model-registry.js +180 -0
- package/dist/src/plugin/model-registry.js.map +1 -0
- package/dist/src/plugin/quota.d.ts +1 -0
- package/dist/src/plugin/quota.d.ts.map +1 -1
- package/dist/src/plugin/quota.js +8 -5
- package/dist/src/plugin/quota.js.map +1 -1
- package/dist/src/plugin/request.d.ts.map +1 -1
- package/dist/src/plugin/request.js +8 -5
- package/dist/src/plugin/request.js.map +1 -1
- package/dist/src/plugin/transform/model-resolver.d.ts.map +1 -1
- package/dist/src/plugin/transform/model-resolver.js +4 -26
- package/dist/src/plugin/transform/model-resolver.js.map +1 -1
- package/dist/src/plugin/ui/auth-menu.d.ts +25 -1
- package/dist/src/plugin/ui/auth-menu.d.ts.map +1 -1
- package/dist/src/plugin/ui/auth-menu.js +64 -13
- package/dist/src/plugin/ui/auth-menu.js.map +1 -1
- package/dist/src/plugin/ui/quota-status.d.ts +67 -0
- package/dist/src/plugin/ui/quota-status.d.ts.map +1 -0
- package/dist/src/plugin/ui/quota-status.js +194 -0
- package/dist/src/plugin/ui/quota-status.js.map +1 -0
- package/dist/src/plugin/version.d.ts +8 -1
- package/dist/src/plugin/version.d.ts.map +1 -1
- package/dist/src/plugin/version.js +8 -1
- package/dist/src/plugin/version.js.map +1 -1
- package/dist/src/plugin.d.ts.map +1 -1
- package/dist/src/plugin.js +66 -5
- package/dist/src/plugin.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -66,6 +66,14 @@ var ANTIGRAVITY_HEADERS = {
|
|
|
66
66
|
"X-Goog-Api-Client": "google-cloud-sdk vscode_cloudshelleditor/0.1",
|
|
67
67
|
"Client-Metadata": `{"ideType":"ANTIGRAVITY","platform":"${process.platform === "win32" ? "WINDOWS" : "MACOS"}","pluginType":"GEMINI"}`
|
|
68
68
|
};
|
|
69
|
+
var GEMINI_CLI_VERSION = "1.0.0";
|
|
70
|
+
var GEMINI_CLI_DEFAULT_MODEL = "gemini-2.5-pro";
|
|
71
|
+
function buildGeminiCliUserAgent(model) {
|
|
72
|
+
const effectiveModel = model || GEMINI_CLI_DEFAULT_MODEL;
|
|
73
|
+
const platform = process.platform || "darwin";
|
|
74
|
+
const arch = process.arch || "arm64";
|
|
75
|
+
return `GeminiCLI/${GEMINI_CLI_VERSION}/${effectiveModel} (${platform}; ${arch})`;
|
|
76
|
+
}
|
|
69
77
|
var GEMINI_CLI_HEADERS = {
|
|
70
78
|
"User-Agent": "google-api-nodejs-client/9.15.1",
|
|
71
79
|
"X-Goog-Api-Client": "gl-node/22.17.0",
|
|
@@ -83,7 +91,7 @@ function randomFrom(arr) {
|
|
|
83
91
|
function getRandomizedHeaders(style, model) {
|
|
84
92
|
if (style === "gemini-cli") {
|
|
85
93
|
return {
|
|
86
|
-
"User-Agent":
|
|
94
|
+
"User-Agent": buildGeminiCliUserAgent(model),
|
|
87
95
|
"X-Goog-Api-Client": GEMINI_CLI_HEADERS["X-Goog-Api-Client"],
|
|
88
96
|
"Client-Metadata": GEMINI_CLI_HEADERS["Client-Metadata"]
|
|
89
97
|
};
|
|
@@ -1574,6 +1582,129 @@ async function confirm(message, defaultYes = false) {
|
|
|
1574
1582
|
return result ?? false;
|
|
1575
1583
|
}
|
|
1576
1584
|
|
|
1585
|
+
// src/plugin/ui/quota-status.ts
|
|
1586
|
+
function formatWaitDuration(ms) {
|
|
1587
|
+
if (ms < 1e3) return `${ms}ms`;
|
|
1588
|
+
const seconds = Math.ceil(ms / 1e3);
|
|
1589
|
+
if (seconds < 60) return `${seconds}s`;
|
|
1590
|
+
const minutes = Math.floor(seconds / 60);
|
|
1591
|
+
const remainingSeconds = seconds % 60;
|
|
1592
|
+
if (minutes < 60) {
|
|
1593
|
+
return remainingSeconds > 0 ? `${minutes}m ${remainingSeconds}s` : `${minutes}m`;
|
|
1594
|
+
}
|
|
1595
|
+
const hours = Math.floor(minutes / 60);
|
|
1596
|
+
const remainingMinutes = minutes % 60;
|
|
1597
|
+
return remainingMinutes > 0 ? `${hours}h ${remainingMinutes}m` : `${hours}h`;
|
|
1598
|
+
}
|
|
1599
|
+
function classifyGroupStatus(group) {
|
|
1600
|
+
if (!group) {
|
|
1601
|
+
return { label: "READY" };
|
|
1602
|
+
}
|
|
1603
|
+
const remaining = group.remainingFraction;
|
|
1604
|
+
if (typeof remaining !== "number" || !Number.isFinite(remaining)) {
|
|
1605
|
+
return { label: "READY" };
|
|
1606
|
+
}
|
|
1607
|
+
if (remaining <= 0) {
|
|
1608
|
+
const waitMs = parseResetTimeToMs(group.resetTime);
|
|
1609
|
+
if (waitMs !== null && waitMs > 0) {
|
|
1610
|
+
return { label: "EXHAUSTED", waitMs };
|
|
1611
|
+
}
|
|
1612
|
+
return { label: "EXHAUSTED" };
|
|
1613
|
+
}
|
|
1614
|
+
if (remaining < 0.2) {
|
|
1615
|
+
return { label: "LOW" };
|
|
1616
|
+
}
|
|
1617
|
+
return { label: "READY" };
|
|
1618
|
+
}
|
|
1619
|
+
function parseResetTimeToMs(resetTime) {
|
|
1620
|
+
if (!resetTime) return null;
|
|
1621
|
+
const timestamp = Date.parse(resetTime);
|
|
1622
|
+
if (!Number.isFinite(timestamp)) return null;
|
|
1623
|
+
const ms = timestamp - Date.now();
|
|
1624
|
+
return ms > 0 ? ms : null;
|
|
1625
|
+
}
|
|
1626
|
+
function buildCooldownStatus(cooldownMs, reason) {
|
|
1627
|
+
return {
|
|
1628
|
+
label: "COOLDOWN",
|
|
1629
|
+
waitMs: cooldownMs > 0 ? cooldownMs : void 0,
|
|
1630
|
+
cooldownReason: reason
|
|
1631
|
+
};
|
|
1632
|
+
}
|
|
1633
|
+
function formatQuotaStatusBadge(status) {
|
|
1634
|
+
switch (status.label) {
|
|
1635
|
+
case "READY":
|
|
1636
|
+
return `${ANSI.green}[READY]${ANSI.reset}`;
|
|
1637
|
+
case "LOW":
|
|
1638
|
+
return `${ANSI.yellow}[LOW]${ANSI.reset}`;
|
|
1639
|
+
case "WAIT": {
|
|
1640
|
+
const suffix = status.waitMs ? ` ${formatWaitDuration(status.waitMs)}` : "";
|
|
1641
|
+
return `${ANSI.yellow}[WAIT${suffix}]${ANSI.reset}`;
|
|
1642
|
+
}
|
|
1643
|
+
case "EXHAUSTED": {
|
|
1644
|
+
const suffix = status.waitMs ? ` resets in ${formatWaitDuration(status.waitMs)}` : "";
|
|
1645
|
+
return `${ANSI.red}[EXHAUSTED${suffix}]${ANSI.reset}`;
|
|
1646
|
+
}
|
|
1647
|
+
case "COOLDOWN": {
|
|
1648
|
+
const parts = ["COOLDOWN"];
|
|
1649
|
+
if (status.cooldownReason) {
|
|
1650
|
+
parts.push(status.cooldownReason);
|
|
1651
|
+
}
|
|
1652
|
+
if (status.waitMs) {
|
|
1653
|
+
parts.push(formatWaitDuration(status.waitMs));
|
|
1654
|
+
}
|
|
1655
|
+
return `${ANSI.red}[${parts.join(" ")}]${ANSI.reset}`;
|
|
1656
|
+
}
|
|
1657
|
+
}
|
|
1658
|
+
}
|
|
1659
|
+
function formatQuotaStatusPlain(status) {
|
|
1660
|
+
switch (status.label) {
|
|
1661
|
+
case "READY":
|
|
1662
|
+
return "READY";
|
|
1663
|
+
case "LOW":
|
|
1664
|
+
return "LOW";
|
|
1665
|
+
case "WAIT": {
|
|
1666
|
+
const suffix = status.waitMs ? ` ${formatWaitDuration(status.waitMs)}` : "";
|
|
1667
|
+
return `WAIT${suffix}`;
|
|
1668
|
+
}
|
|
1669
|
+
case "EXHAUSTED": {
|
|
1670
|
+
const suffix = status.waitMs ? ` resets in ${formatWaitDuration(status.waitMs)}` : "";
|
|
1671
|
+
return `EXHAUSTED${suffix}`;
|
|
1672
|
+
}
|
|
1673
|
+
case "COOLDOWN": {
|
|
1674
|
+
const parts = ["COOLDOWN"];
|
|
1675
|
+
if (status.cooldownReason) {
|
|
1676
|
+
parts.push(status.cooldownReason);
|
|
1677
|
+
}
|
|
1678
|
+
if (status.waitMs) {
|
|
1679
|
+
parts.push(formatWaitDuration(status.waitMs));
|
|
1680
|
+
}
|
|
1681
|
+
return parts.join(" ");
|
|
1682
|
+
}
|
|
1683
|
+
}
|
|
1684
|
+
}
|
|
1685
|
+
function formatCachedQuotaWithStatus(cachedQuota) {
|
|
1686
|
+
if (!cachedQuota) {
|
|
1687
|
+
return void 0;
|
|
1688
|
+
}
|
|
1689
|
+
const entries = [
|
|
1690
|
+
{ key: "claude", label: "Claude" },
|
|
1691
|
+
{ key: "gemini-pro", label: "Gemini Pro" },
|
|
1692
|
+
{ key: "gemini-flash", label: "Gemini Flash" }
|
|
1693
|
+
].flatMap(({ key, label }) => {
|
|
1694
|
+
const value = cachedQuota[key]?.remainingFraction;
|
|
1695
|
+
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
1696
|
+
return [];
|
|
1697
|
+
}
|
|
1698
|
+
const pct = Math.round(Math.max(0, Math.min(1, value)) * 100);
|
|
1699
|
+
const status = classifyGroupStatus(cachedQuota[key]);
|
|
1700
|
+
if (status.label === "READY") {
|
|
1701
|
+
return [`${label} ${pct}%`];
|
|
1702
|
+
}
|
|
1703
|
+
return [`${label} ${formatQuotaStatusPlain(status)} ${pct}%`];
|
|
1704
|
+
});
|
|
1705
|
+
return entries.length > 0 ? entries.join(", ") : void 0;
|
|
1706
|
+
}
|
|
1707
|
+
|
|
1577
1708
|
// src/plugin/ui/auth-menu.ts
|
|
1578
1709
|
function formatRelativeTime(timestamp) {
|
|
1579
1710
|
if (!timestamp) return "never";
|
|
@@ -1588,16 +1719,20 @@ function formatDate(timestamp) {
|
|
|
1588
1719
|
if (!timestamp) return "unknown";
|
|
1589
1720
|
return new Date(timestamp).toLocaleDateString();
|
|
1590
1721
|
}
|
|
1591
|
-
function getStatusBadge(status) {
|
|
1722
|
+
function getStatusBadge(status, account) {
|
|
1723
|
+
if (account?.cooldownMs !== void 0 && account.cooldownMs > 0) {
|
|
1724
|
+
const cooldownStatus = buildCooldownStatus(account.cooldownMs, account.cooldownReason);
|
|
1725
|
+
return ` ${formatQuotaStatusBadge(cooldownStatus)}`;
|
|
1726
|
+
}
|
|
1592
1727
|
switch (status) {
|
|
1593
1728
|
case "active":
|
|
1594
|
-
return
|
|
1729
|
+
return ` ${ANSI.green}[active]${ANSI.reset}`;
|
|
1595
1730
|
case "rate-limited":
|
|
1596
|
-
return
|
|
1731
|
+
return ` ${ANSI.yellow}[rate-limited]${ANSI.reset}`;
|
|
1597
1732
|
case "expired":
|
|
1598
|
-
return
|
|
1733
|
+
return ` ${ANSI.red}[expired]${ANSI.reset}`;
|
|
1599
1734
|
case "verification-required":
|
|
1600
|
-
return
|
|
1735
|
+
return ` ${ANSI.red}[needs verification]${ANSI.reset}`;
|
|
1601
1736
|
default:
|
|
1602
1737
|
return "";
|
|
1603
1738
|
}
|
|
@@ -1606,22 +1741,25 @@ async function showAuthMenu(accounts) {
|
|
|
1606
1741
|
const items = [
|
|
1607
1742
|
{ label: "Actions", value: { type: "cancel" }, kind: "heading" },
|
|
1608
1743
|
{ label: "Add account", value: { type: "add" }, color: "cyan" },
|
|
1744
|
+
{ label: "Auth current", value: { type: "current" }, color: "cyan" },
|
|
1609
1745
|
{ label: "Check quotas", value: { type: "check" }, color: "cyan" },
|
|
1746
|
+
{ label: "Repair auth", value: { type: "repair" }, color: "yellow" },
|
|
1747
|
+
{ label: "Auth doctor", value: { type: "doctor" }, color: "cyan" },
|
|
1610
1748
|
{ label: "Verify one account", value: { type: "verify" }, color: "cyan" },
|
|
1611
1749
|
{ label: "Verify all accounts", value: { type: "verify-all" }, color: "cyan" },
|
|
1612
1750
|
{ label: "Configure models in opencode.json", value: { type: "configure-models" }, color: "cyan" },
|
|
1613
1751
|
{ label: "", value: { type: "cancel" }, separator: true },
|
|
1614
1752
|
{ label: "Accounts", value: { type: "cancel" }, kind: "heading" },
|
|
1615
1753
|
...accounts.map((account) => {
|
|
1616
|
-
const statusBadge = getStatusBadge(account.status);
|
|
1754
|
+
const statusBadge = getStatusBadge(account.status, account);
|
|
1617
1755
|
const currentBadge = account.isCurrentAccount ? ` ${ANSI.cyan}[current]${ANSI.reset}` : "";
|
|
1618
1756
|
const disabledBadge = account.enabled === false ? ` ${ANSI.red}[disabled]${ANSI.reset}` : "";
|
|
1619
1757
|
const baseLabel = account.email || `Account ${account.index + 1}`;
|
|
1620
1758
|
const numbered = `${account.index + 1}. ${baseLabel}`;
|
|
1621
|
-
const fullLabel = `${numbered}${currentBadge}${statusBadge
|
|
1759
|
+
const fullLabel = `${numbered}${currentBadge}${statusBadge}${disabledBadge}`;
|
|
1622
1760
|
return {
|
|
1623
1761
|
label: fullLabel,
|
|
1624
|
-
hint: account.lastUsed ? `used ${formatRelativeTime(account.lastUsed)}` : "",
|
|
1762
|
+
hint: account.quotaSummary ?? (account.lastUsed ? `used ${formatRelativeTime(account.lastUsed)}` : ""),
|
|
1625
1763
|
value: { type: "select-account", account }
|
|
1626
1764
|
};
|
|
1627
1765
|
}),
|
|
@@ -1643,23 +1781,69 @@ async function showAuthMenu(accounts) {
|
|
|
1643
1781
|
return result;
|
|
1644
1782
|
}
|
|
1645
1783
|
}
|
|
1784
|
+
function formatFingerprintReason(reason) {
|
|
1785
|
+
switch (reason) {
|
|
1786
|
+
case "initial":
|
|
1787
|
+
return "initial";
|
|
1788
|
+
case "regenerated":
|
|
1789
|
+
return "regenerated";
|
|
1790
|
+
case "restored":
|
|
1791
|
+
return "restored";
|
|
1792
|
+
}
|
|
1793
|
+
}
|
|
1794
|
+
async function showFingerprintHistory(history, accountLabel) {
|
|
1795
|
+
const items = [
|
|
1796
|
+
{ label: "Back", value: null },
|
|
1797
|
+
{ label: "", value: null, separator: true },
|
|
1798
|
+
{ label: "Fingerprint history", value: null, kind: "heading" },
|
|
1799
|
+
...history.map((entry, index) => {
|
|
1800
|
+
const deviceShort = entry.deviceId.slice(0, 8);
|
|
1801
|
+
const reasonBadge = `${ANSI.dim}[${formatFingerprintReason(entry.reason)}]${ANSI.reset}`;
|
|
1802
|
+
const label = `${index + 1}. ${deviceShort}... ${reasonBadge}`;
|
|
1803
|
+
const hint = formatRelativeTime(entry.timestamp);
|
|
1804
|
+
return {
|
|
1805
|
+
label,
|
|
1806
|
+
hint,
|
|
1807
|
+
value: index,
|
|
1808
|
+
color: "cyan"
|
|
1809
|
+
};
|
|
1810
|
+
})
|
|
1811
|
+
];
|
|
1812
|
+
const result = await select(items, {
|
|
1813
|
+
message: `Restore fingerprint \u2014 ${accountLabel}`,
|
|
1814
|
+
subtitle: "Select a previous fingerprint to restore",
|
|
1815
|
+
clearScreen: true
|
|
1816
|
+
});
|
|
1817
|
+
return result ?? null;
|
|
1818
|
+
}
|
|
1646
1819
|
async function showAccountDetails(account) {
|
|
1647
1820
|
const label = account.email || `Account ${account.index + 1}`;
|
|
1648
|
-
const badge = getStatusBadge(account.status);
|
|
1821
|
+
const badge = getStatusBadge(account.status, account);
|
|
1649
1822
|
const disabledBadge = account.enabled === false ? ` ${ANSI.red}[disabled]${ANSI.reset}` : "";
|
|
1650
|
-
const header = `${label}${badge
|
|
1823
|
+
const header = `${label}${badge}${disabledBadge}`;
|
|
1651
1824
|
const subtitleParts = [
|
|
1652
1825
|
`Added: ${formatDate(account.addedAt)}`,
|
|
1653
1826
|
`Last used: ${formatRelativeTime(account.lastUsed)}`
|
|
1654
1827
|
];
|
|
1828
|
+
const hasHistory = (account.fingerprintHistory?.length ?? 0) > 0;
|
|
1655
1829
|
while (true) {
|
|
1656
|
-
const
|
|
1830
|
+
const menuItems = [
|
|
1657
1831
|
{ label: "Back", value: "back" },
|
|
1658
1832
|
{ label: "Verify account access", value: "verify", color: "cyan" },
|
|
1659
1833
|
{ label: account.enabled === false ? "Enable account" : "Disable account", value: "toggle", color: account.enabled === false ? "green" : "yellow" },
|
|
1660
|
-
{ label: "Refresh token", value: "refresh", color: "cyan" }
|
|
1834
|
+
{ label: "Refresh token", value: "refresh", color: "cyan" }
|
|
1835
|
+
];
|
|
1836
|
+
if (hasHistory) {
|
|
1837
|
+
menuItems.push({
|
|
1838
|
+
label: `Restore fingerprint (${account.fingerprintHistory.length} saved)`,
|
|
1839
|
+
value: "restore-fingerprint",
|
|
1840
|
+
color: "cyan"
|
|
1841
|
+
});
|
|
1842
|
+
}
|
|
1843
|
+
menuItems.push(
|
|
1661
1844
|
{ label: "Delete this account", value: "delete", color: "red" }
|
|
1662
|
-
|
|
1845
|
+
);
|
|
1846
|
+
const result = await select(menuItems, {
|
|
1663
1847
|
message: header,
|
|
1664
1848
|
subtitle: subtitleParts.join(" | "),
|
|
1665
1849
|
clearScreen: true
|
|
@@ -1681,12 +1865,14 @@ import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync
|
|
|
1681
1865
|
import { join as join3, dirname as dirname2 } from "node:path";
|
|
1682
1866
|
import { homedir as homedir3 } from "node:os";
|
|
1683
1867
|
|
|
1684
|
-
// src/plugin/
|
|
1868
|
+
// src/plugin/model-registry.ts
|
|
1685
1869
|
var DEFAULT_MODALITIES = {
|
|
1686
1870
|
input: ["text", "image", "pdf"],
|
|
1687
1871
|
output: ["text"]
|
|
1688
1872
|
};
|
|
1689
1873
|
var MODEL_RELEASE_DATE = "";
|
|
1874
|
+
var DEFAULT_COST = { input: 0, output: 0 };
|
|
1875
|
+
var DEFAULT_OPTIONS = {};
|
|
1690
1876
|
function defineModel(id, model) {
|
|
1691
1877
|
return {
|
|
1692
1878
|
id,
|
|
@@ -1694,10 +1880,12 @@ function defineModel(id, model) {
|
|
|
1694
1880
|
attachment: model.modalities.input.some((modality) => modality !== "text"),
|
|
1695
1881
|
temperature: true,
|
|
1696
1882
|
tool_call: true,
|
|
1883
|
+
cost: { ...DEFAULT_COST },
|
|
1884
|
+
options: { ...DEFAULT_OPTIONS },
|
|
1697
1885
|
...model
|
|
1698
1886
|
};
|
|
1699
1887
|
}
|
|
1700
|
-
var
|
|
1888
|
+
var PUBLIC_MODEL_DEFINITIONS = {
|
|
1701
1889
|
"antigravity-gemini-3.1-pro": defineModel("antigravity-gemini-3.1-pro", {
|
|
1702
1890
|
name: "Gemini 3.1 Pro (Antigravity)",
|
|
1703
1891
|
reasoning: true,
|
|
@@ -1789,15 +1977,6 @@ var OPENCODE_MODEL_DEFINITIONS = {
|
|
|
1789
1977
|
output: ["text", "image"]
|
|
1790
1978
|
}
|
|
1791
1979
|
}),
|
|
1792
|
-
"gemini-3-pro-image-preview": defineModel("gemini-3-pro-image-preview", {
|
|
1793
|
-
name: "Gemini 3 Pro Image Preview (Gemini CLI)",
|
|
1794
|
-
reasoning: false,
|
|
1795
|
-
limit: { context: 66e3, output: 33e3 },
|
|
1796
|
-
modalities: {
|
|
1797
|
-
input: ["text", "image"],
|
|
1798
|
-
output: ["text", "image"]
|
|
1799
|
-
}
|
|
1800
|
-
}),
|
|
1801
1980
|
"gemini-3.1-pro-preview-customtools": defineModel("gemini-3.1-pro-preview-customtools", {
|
|
1802
1981
|
name: "Gemini 3.1 Pro Preview Custom Tools (Gemini CLI)",
|
|
1803
1982
|
reasoning: true,
|
|
@@ -1805,6 +1984,63 @@ var OPENCODE_MODEL_DEFINITIONS = {
|
|
|
1805
1984
|
modalities: DEFAULT_MODALITIES
|
|
1806
1985
|
})
|
|
1807
1986
|
};
|
|
1987
|
+
var RESOLVER_ALIASES = {
|
|
1988
|
+
"gemini-3.1-pro-low": "gemini-3.1-pro",
|
|
1989
|
+
"gemini-3.1-pro-high": "gemini-3.1-pro",
|
|
1990
|
+
"gemini-3-flash-low": "gemini-3-flash",
|
|
1991
|
+
"gemini-3-flash-medium": "gemini-3-flash",
|
|
1992
|
+
"gemini-3-flash-high": "gemini-3-flash",
|
|
1993
|
+
"gemini-3.5-flash-low": "gemini-3.5-flash",
|
|
1994
|
+
"gemini-3.5-flash-medium": "gemini-3.5-flash",
|
|
1995
|
+
"gemini-3.5-flash-high": "gemini-3.5-flash",
|
|
1996
|
+
"gemini-claude-opus-4-6-thinking-low": "claude-opus-4-6-thinking",
|
|
1997
|
+
"gemini-claude-opus-4-6-thinking-medium": "claude-opus-4-6-thinking",
|
|
1998
|
+
"gemini-claude-opus-4-6-thinking-high": "claude-opus-4-6-thinking",
|
|
1999
|
+
"gemini-claude-sonnet-4-6-thinking-low": "claude-sonnet-4-6-thinking",
|
|
2000
|
+
"gemini-claude-sonnet-4-6-thinking-medium": "claude-sonnet-4-6-thinking",
|
|
2001
|
+
"gemini-claude-sonnet-4-6-thinking-high": "claude-sonnet-4-6-thinking",
|
|
2002
|
+
"gemini-claude-sonnet-4-6": "claude-sonnet-4-6-thinking"
|
|
2003
|
+
};
|
|
2004
|
+
var GEMINI_35_FLASH_ROUTES = {
|
|
2005
|
+
antigravity: {
|
|
2006
|
+
defaultModel: "gemini-3-flash-agent",
|
|
2007
|
+
byTier: {
|
|
2008
|
+
low: "gemini-3.5-flash-low",
|
|
2009
|
+
medium: "gemini-3.5-flash-low",
|
|
2010
|
+
high: "gemini-3-flash-agent"
|
|
2011
|
+
}
|
|
2012
|
+
},
|
|
2013
|
+
geminiCliFallbackModel: "gemini-3-flash-preview"
|
|
2014
|
+
};
|
|
2015
|
+
var QUOTA_GROUP_BY_MODEL_ID = {
|
|
2016
|
+
"claude-opus-4-6-thinking": "claude",
|
|
2017
|
+
"claude-opus-4-6": "claude",
|
|
2018
|
+
"claude-sonnet-4-6-thinking": "claude",
|
|
2019
|
+
"claude-sonnet-4-6": "claude",
|
|
2020
|
+
"gemini-pro-agent": "gemini-pro",
|
|
2021
|
+
"gemini-3.1-pro": "gemini-pro",
|
|
2022
|
+
"gemini-3.1-pro-low": "gemini-pro",
|
|
2023
|
+
"gemini-3.1-pro-high": "gemini-pro",
|
|
2024
|
+
"gemini-3-flash": "gemini-flash",
|
|
2025
|
+
"gemini-3-flash-agent": "gemini-flash",
|
|
2026
|
+
"gemini-3.5-flash-low": "gemini-flash"
|
|
2027
|
+
};
|
|
2028
|
+
var OPENCODE_MODEL_DEFINITIONS = PUBLIC_MODEL_DEFINITIONS;
|
|
2029
|
+
function getResolverAliasMap() {
|
|
2030
|
+
return RESOLVER_ALIASES;
|
|
2031
|
+
}
|
|
2032
|
+
function getGemini35FlashAntigravityModel(tier) {
|
|
2033
|
+
if (!tier) {
|
|
2034
|
+
return GEMINI_35_FLASH_ROUTES.antigravity.defaultModel;
|
|
2035
|
+
}
|
|
2036
|
+
return GEMINI_35_FLASH_ROUTES.antigravity.byTier[tier] ?? GEMINI_35_FLASH_ROUTES.antigravity.defaultModel;
|
|
2037
|
+
}
|
|
2038
|
+
function getGemini35FlashGeminiCliFallbackModel() {
|
|
2039
|
+
return GEMINI_35_FLASH_ROUTES.geminiCliFallbackModel;
|
|
2040
|
+
}
|
|
2041
|
+
function getQuotaGroupForModel(modelId) {
|
|
2042
|
+
return QUOTA_GROUP_BY_MODEL_ID[modelId.toLowerCase()];
|
|
2043
|
+
}
|
|
1808
2044
|
|
|
1809
2045
|
// src/plugin/config/updater.ts
|
|
1810
2046
|
var PLUGIN_NAME = "@expiren/opencode-antigravity-auth@latest";
|
|
@@ -1915,7 +2151,7 @@ ${existingAccounts.length} account(s) saved:`);
|
|
|
1915
2151
|
}
|
|
1916
2152
|
console.log("");
|
|
1917
2153
|
while (true) {
|
|
1918
|
-
const answer = await rl.question("(a)dd new, (f)resh start, (c)heck quotas, (v)erify account, (va) verify all? [a/f/c/v/va]: ");
|
|
2154
|
+
const answer = await rl.question("(a)dd new, (f)resh start, (c)heck quotas, auth (d)octor, (v)erify account, (va) verify all? [a/f/c/d/v/va]: ");
|
|
1919
2155
|
const normalized = answer.trim().toLowerCase();
|
|
1920
2156
|
if (normalized === "a" || normalized === "add") {
|
|
1921
2157
|
return { mode: "add" };
|
|
@@ -1926,13 +2162,16 @@ ${existingAccounts.length} account(s) saved:`);
|
|
|
1926
2162
|
if (normalized === "c" || normalized === "check") {
|
|
1927
2163
|
return { mode: "check" };
|
|
1928
2164
|
}
|
|
2165
|
+
if (normalized === "d" || normalized === "doctor" || normalized === "auth-doctor") {
|
|
2166
|
+
return { mode: "doctor" };
|
|
2167
|
+
}
|
|
1929
2168
|
if (normalized === "v" || normalized === "verify") {
|
|
1930
2169
|
return { mode: "verify" };
|
|
1931
2170
|
}
|
|
1932
2171
|
if (normalized === "va" || normalized === "verify-all" || normalized === "all") {
|
|
1933
2172
|
return { mode: "verify-all", verifyAll: true };
|
|
1934
2173
|
}
|
|
1935
|
-
console.log("Please enter 'a', 'f', 'c', 'v', or 'va'.");
|
|
2174
|
+
console.log("Please enter 'a', 'f', 'c', 'd', 'v', or 'va'.");
|
|
1936
2175
|
}
|
|
1937
2176
|
} finally {
|
|
1938
2177
|
rl.close();
|
|
@@ -1949,7 +2188,12 @@ async function promptLoginMode(existingAccounts) {
|
|
|
1949
2188
|
lastUsed: acc.lastUsed,
|
|
1950
2189
|
status: acc.status,
|
|
1951
2190
|
isCurrentAccount: acc.isCurrentAccount,
|
|
1952
|
-
enabled: acc.enabled
|
|
2191
|
+
enabled: acc.enabled,
|
|
2192
|
+
quotaSummary: acc.quotaSummary,
|
|
2193
|
+
cooldownMs: acc.cooldownMs,
|
|
2194
|
+
cooldownReason: acc.cooldownReason,
|
|
2195
|
+
cachedQuota: acc.cachedQuota,
|
|
2196
|
+
fingerprintHistory: acc.fingerprintHistory
|
|
1953
2197
|
}));
|
|
1954
2198
|
console.log("");
|
|
1955
2199
|
while (true) {
|
|
@@ -1959,6 +2203,12 @@ async function promptLoginMode(existingAccounts) {
|
|
|
1959
2203
|
return { mode: "add" };
|
|
1960
2204
|
case "check":
|
|
1961
2205
|
return { mode: "check" };
|
|
2206
|
+
case "doctor":
|
|
2207
|
+
return { mode: "doctor" };
|
|
2208
|
+
case "repair":
|
|
2209
|
+
return { mode: "repair" };
|
|
2210
|
+
case "current":
|
|
2211
|
+
return { mode: "current" };
|
|
1962
2212
|
case "verify":
|
|
1963
2213
|
return { mode: "verify" };
|
|
1964
2214
|
case "verify-all":
|
|
@@ -1977,6 +2227,18 @@ async function promptLoginMode(existingAccounts) {
|
|
|
1977
2227
|
if (accountAction === "verify") {
|
|
1978
2228
|
return { mode: "verify", verifyAccountIndex: action.account.index };
|
|
1979
2229
|
}
|
|
2230
|
+
if (accountAction === "restore-fingerprint") {
|
|
2231
|
+
const history = action.account.fingerprintHistory;
|
|
2232
|
+
if (!history || history.length === 0) continue;
|
|
2233
|
+
const accountLabel = action.account.email || `Account ${action.account.index + 1}`;
|
|
2234
|
+
const historyIndex = await showFingerprintHistory(history, accountLabel);
|
|
2235
|
+
if (historyIndex === null) continue;
|
|
2236
|
+
return {
|
|
2237
|
+
mode: "restore-fingerprint",
|
|
2238
|
+
restoreFingerprintAccountIndex: action.account.index,
|
|
2239
|
+
restoreFingerprintHistoryIndex: historyIndex
|
|
2240
|
+
};
|
|
2241
|
+
}
|
|
1980
2242
|
continue;
|
|
1981
2243
|
}
|
|
1982
2244
|
case "delete-all":
|
|
@@ -2759,9 +3021,9 @@ var AntigravityConfigSchema = z2.object({
|
|
|
2759
3021
|
* When false: Only shows toast notification, user must manually continue.
|
|
2760
3022
|
* When true: Automatically sends "continue" to resume the session.
|
|
2761
3023
|
*
|
|
2762
|
-
* @default
|
|
3024
|
+
* @default true
|
|
2763
3025
|
*/
|
|
2764
|
-
auto_resume: z2.boolean().default(
|
|
3026
|
+
auto_resume: z2.boolean().default(true),
|
|
2765
3027
|
/**
|
|
2766
3028
|
* Custom text to send when auto-resuming after recovery.
|
|
2767
3029
|
* Only used when auto_resume is enabled.
|
|
@@ -5771,31 +6033,7 @@ var THINKING_TIER_BUDGETS = {
|
|
|
5771
6033
|
"gemini-2.5-flash": { low: 6144, medium: 12288, high: 24576 },
|
|
5772
6034
|
default: { low: 4096, medium: 8192, high: 16384 }
|
|
5773
6035
|
};
|
|
5774
|
-
var MODEL_ALIASES =
|
|
5775
|
-
// Gemini 3.x variants - for Gemini CLI only (tier stripped, thinkingLevel used)
|
|
5776
|
-
// For Antigravity, these are bypassed and full model name is kept
|
|
5777
|
-
"gemini-3.1-pro-low": "gemini-3.1-pro",
|
|
5778
|
-
"gemini-3.1-pro-high": "gemini-3.1-pro",
|
|
5779
|
-
"gemini-3-flash-low": "gemini-3-flash",
|
|
5780
|
-
"gemini-3-flash-medium": "gemini-3-flash",
|
|
5781
|
-
"gemini-3-flash-high": "gemini-3-flash",
|
|
5782
|
-
// Gemini 3.5 Flash variants
|
|
5783
|
-
"gemini-3.5-flash-low": "gemini-3.5-flash",
|
|
5784
|
-
"gemini-3.5-flash-medium": "gemini-3.5-flash",
|
|
5785
|
-
"gemini-3.5-flash-high": "gemini-3.5-flash",
|
|
5786
|
-
// Claude proxy names (gemini- prefix for compatibility)
|
|
5787
|
-
"gemini-claude-opus-4-6-thinking-low": "claude-opus-4-6-thinking",
|
|
5788
|
-
"gemini-claude-opus-4-6-thinking-medium": "claude-opus-4-6-thinking",
|
|
5789
|
-
"gemini-claude-opus-4-6-thinking-high": "claude-opus-4-6-thinking",
|
|
5790
|
-
"gemini-claude-sonnet-4-6-thinking-low": "claude-sonnet-4-6-thinking",
|
|
5791
|
-
"gemini-claude-sonnet-4-6-thinking-medium": "claude-sonnet-4-6-thinking",
|
|
5792
|
-
"gemini-claude-sonnet-4-6-thinking-high": "claude-sonnet-4-6-thinking",
|
|
5793
|
-
"gemini-claude-sonnet-4-6": "claude-sonnet-4-6-thinking"
|
|
5794
|
-
// Image generation models
|
|
5795
|
-
// gemini-3.1-flash-image (Nano Banana 2) - available via Antigravity API and Gemini CLI
|
|
5796
|
-
// gemini-2.5-flash-image (Nano Banana) - NOT supported by Antigravity, only Google AI API
|
|
5797
|
-
// Reference: Antigravity-Manager/src-tauri/src/proxy/common/model_mapping.rs
|
|
5798
|
-
};
|
|
6036
|
+
var MODEL_ALIASES = getResolverAliasMap();
|
|
5799
6037
|
var TIER_REGEX = /-(minimal|low|medium|high)$/;
|
|
5800
6038
|
var QUOTA_PREFIX_REGEX = /^antigravity-/i;
|
|
5801
6039
|
var GEMINI_3_PRO_REGEX = /^gemini-3(?:\.\d+)?-pro/i;
|
|
@@ -5838,7 +6076,7 @@ function isGemini35FlashModel(model) {
|
|
|
5838
6076
|
return /^gemini-3\.5-flash/i.test(model);
|
|
5839
6077
|
}
|
|
5840
6078
|
function resolveGemini35FlashAntigravityModel(tier) {
|
|
5841
|
-
return tier
|
|
6079
|
+
return getGemini35FlashAntigravityModel(tier);
|
|
5842
6080
|
}
|
|
5843
6081
|
function resolveModelWithTier(requestedModel, options = {}) {
|
|
5844
6082
|
const isAntigravity = QUOTA_PREFIX_REGEX.test(requestedModel);
|
|
@@ -5965,7 +6203,7 @@ function resolveModelForHeaderStyle(requestedModel, headerStyle) {
|
|
|
5965
6203
|
const hasPreviewSuffix = /-preview($|-)/i.test(transformedModel);
|
|
5966
6204
|
const isGemini35Flash = isGemini35FlashModel(transformedModel);
|
|
5967
6205
|
if (isGemini35Flash) {
|
|
5968
|
-
transformedModel =
|
|
6206
|
+
transformedModel = getGemini35FlashGeminiCliFallbackModel();
|
|
5969
6207
|
} else if (!hasPreviewSuffix) {
|
|
5970
6208
|
transformedModel = `${transformedModel}-preview`;
|
|
5971
6209
|
}
|
|
@@ -7548,9 +7786,10 @@ function prepareAntigravityRequest(input2, init, accessToken, projectId, endpoin
|
|
|
7548
7786
|
const fingerprintHeaders = buildFingerprintHeaders(fingerprint);
|
|
7549
7787
|
headers.set("User-Agent", fingerprintHeaders["User-Agent"] || selectedHeaders["User-Agent"]);
|
|
7550
7788
|
} else {
|
|
7551
|
-
|
|
7552
|
-
headers.set("
|
|
7553
|
-
headers.set("Client
|
|
7789
|
+
const geminiCliHeaders = getRandomizedHeaders("gemini-cli", requestedModel);
|
|
7790
|
+
headers.set("User-Agent", geminiCliHeaders["User-Agent"]);
|
|
7791
|
+
if (geminiCliHeaders["X-Goog-Api-Client"]) headers.set("X-Goog-Api-Client", geminiCliHeaders["X-Goog-Api-Client"]);
|
|
7792
|
+
if (geminiCliHeaders["Client-Metadata"]) headers.set("Client-Metadata", geminiCliHeaders["Client-Metadata"]);
|
|
7554
7793
|
}
|
|
7555
7794
|
return {
|
|
7556
7795
|
request: transformedUrl,
|
|
@@ -9690,6 +9929,219 @@ async function showLocalDevToast(client, version) {
|
|
|
9690
9929
|
logAutoUpdate(`Local dev toast shown: v${version}`);
|
|
9691
9930
|
}
|
|
9692
9931
|
|
|
9932
|
+
// src/plugin/auth-drift.ts
|
|
9933
|
+
function isAccountEnabled(account) {
|
|
9934
|
+
return account.enabled !== false;
|
|
9935
|
+
}
|
|
9936
|
+
function selectRestorableAccount(storage) {
|
|
9937
|
+
if (!storage || storage.accounts.length === 0) {
|
|
9938
|
+
return void 0;
|
|
9939
|
+
}
|
|
9940
|
+
const activeAccount = storage.accounts[storage.activeIndex];
|
|
9941
|
+
if (activeAccount && isAccountEnabled(activeAccount)) {
|
|
9942
|
+
return activeAccount;
|
|
9943
|
+
}
|
|
9944
|
+
return storage.accounts.find(isAccountEnabled);
|
|
9945
|
+
}
|
|
9946
|
+
function buildAuthFromStoredAccount(account) {
|
|
9947
|
+
return {
|
|
9948
|
+
type: "oauth",
|
|
9949
|
+
refresh: formatRefreshParts({
|
|
9950
|
+
refreshToken: account.refreshToken,
|
|
9951
|
+
projectId: account.projectId,
|
|
9952
|
+
managedProjectId: account.managedProjectId
|
|
9953
|
+
}),
|
|
9954
|
+
access: "",
|
|
9955
|
+
expires: 0
|
|
9956
|
+
};
|
|
9957
|
+
}
|
|
9958
|
+
function detectAuthStorageDrift(auth, storage) {
|
|
9959
|
+
if (!storage || storage.accounts.length === 0) {
|
|
9960
|
+
return {
|
|
9961
|
+
status: "unavailable",
|
|
9962
|
+
reason: "no-account-storage"
|
|
9963
|
+
};
|
|
9964
|
+
}
|
|
9965
|
+
const restorableAccount = selectRestorableAccount(storage);
|
|
9966
|
+
if (!restorableAccount) {
|
|
9967
|
+
return {
|
|
9968
|
+
status: "unavailable",
|
|
9969
|
+
reason: "no-enabled-accounts"
|
|
9970
|
+
};
|
|
9971
|
+
}
|
|
9972
|
+
if (!auth) {
|
|
9973
|
+
return {
|
|
9974
|
+
status: "restorable",
|
|
9975
|
+
reason: "missing-opencode-auth",
|
|
9976
|
+
account: restorableAccount
|
|
9977
|
+
};
|
|
9978
|
+
}
|
|
9979
|
+
if (!isOAuthAuth(auth)) {
|
|
9980
|
+
return {
|
|
9981
|
+
status: "restorable",
|
|
9982
|
+
reason: "non-oauth-opencode-auth",
|
|
9983
|
+
account: restorableAccount
|
|
9984
|
+
};
|
|
9985
|
+
}
|
|
9986
|
+
const authRefreshToken = parseRefreshParts(auth.refresh).refreshToken;
|
|
9987
|
+
const matchedAccount = storage.accounts.find((account) => account.refreshToken === authRefreshToken);
|
|
9988
|
+
if (matchedAccount) {
|
|
9989
|
+
return {
|
|
9990
|
+
status: "healthy",
|
|
9991
|
+
reason: "auth-matches-storage",
|
|
9992
|
+
account: matchedAccount
|
|
9993
|
+
};
|
|
9994
|
+
}
|
|
9995
|
+
return {
|
|
9996
|
+
status: "drifted",
|
|
9997
|
+
reason: "refresh-token-not-in-storage",
|
|
9998
|
+
account: restorableAccount
|
|
9999
|
+
};
|
|
10000
|
+
}
|
|
10001
|
+
|
|
10002
|
+
// src/plugin/auth-doctor.ts
|
|
10003
|
+
function isEnabled(account) {
|
|
10004
|
+
return account.enabled !== false;
|
|
10005
|
+
}
|
|
10006
|
+
function statusFromFindings(findings) {
|
|
10007
|
+
if (findings.some((finding) => finding.repair && finding.severity === "error")) {
|
|
10008
|
+
return "repairable";
|
|
10009
|
+
}
|
|
10010
|
+
if (findings.some((finding) => finding.severity === "error")) {
|
|
10011
|
+
return "error";
|
|
10012
|
+
}
|
|
10013
|
+
if (findings.some((finding) => finding.severity === "warning")) {
|
|
10014
|
+
return "warning";
|
|
10015
|
+
}
|
|
10016
|
+
return "ok";
|
|
10017
|
+
}
|
|
10018
|
+
function summaryFromStatus(status) {
|
|
10019
|
+
switch (status) {
|
|
10020
|
+
case "ok":
|
|
10021
|
+
return "OpenCode auth and Antigravity account storage are in sync.";
|
|
10022
|
+
case "repairable":
|
|
10023
|
+
return "Auth drift detected. One or more safe repairs are available.";
|
|
10024
|
+
case "warning":
|
|
10025
|
+
return "Auth is usable, but one or more accounts need attention.";
|
|
10026
|
+
case "error":
|
|
10027
|
+
return "Auth state is not usable and no safe automatic repair is available.";
|
|
10028
|
+
}
|
|
10029
|
+
}
|
|
10030
|
+
function createAuthDoctorReport(input2) {
|
|
10031
|
+
const findings = [];
|
|
10032
|
+
const drift = detectAuthStorageDrift(input2.auth, input2.storage);
|
|
10033
|
+
switch (drift.reason) {
|
|
10034
|
+
case "auth-matches-storage":
|
|
10035
|
+
findings.push({
|
|
10036
|
+
code: "auth-matches-storage",
|
|
10037
|
+
severity: "info",
|
|
10038
|
+
message: "OpenCode OAuth refresh token exists in Antigravity account storage.",
|
|
10039
|
+
accountEmail: drift.account?.email
|
|
10040
|
+
});
|
|
10041
|
+
break;
|
|
10042
|
+
case "missing-opencode-auth":
|
|
10043
|
+
findings.push({
|
|
10044
|
+
code: "missing-opencode-auth",
|
|
10045
|
+
severity: "error",
|
|
10046
|
+
message: "OpenCode auth.json has no Google OAuth entry, but Antigravity account storage has a restorable account.",
|
|
10047
|
+
repair: "restore-opencode-auth",
|
|
10048
|
+
accountEmail: drift.account?.email
|
|
10049
|
+
});
|
|
10050
|
+
break;
|
|
10051
|
+
case "non-oauth-opencode-auth":
|
|
10052
|
+
findings.push({
|
|
10053
|
+
code: "non-oauth-opencode-auth",
|
|
10054
|
+
severity: "error",
|
|
10055
|
+
message: "OpenCode Google auth is not OAuth, but Antigravity account storage has a restorable OAuth account.",
|
|
10056
|
+
repair: "restore-opencode-auth",
|
|
10057
|
+
accountEmail: drift.account?.email
|
|
10058
|
+
});
|
|
10059
|
+
break;
|
|
10060
|
+
case "refresh-token-not-in-storage":
|
|
10061
|
+
findings.push({
|
|
10062
|
+
code: "refresh-token-not-in-storage",
|
|
10063
|
+
severity: "error",
|
|
10064
|
+
message: "OpenCode Google OAuth refresh token does not match any stored Antigravity account.",
|
|
10065
|
+
repair: "restore-opencode-auth",
|
|
10066
|
+
accountEmail: drift.account?.email
|
|
10067
|
+
});
|
|
10068
|
+
break;
|
|
10069
|
+
case "no-account-storage":
|
|
10070
|
+
findings.push({
|
|
10071
|
+
code: "no-account-storage",
|
|
10072
|
+
severity: "error",
|
|
10073
|
+
message: "No Antigravity account storage was found."
|
|
10074
|
+
});
|
|
10075
|
+
break;
|
|
10076
|
+
case "no-enabled-accounts":
|
|
10077
|
+
findings.push({
|
|
10078
|
+
code: "no-enabled-accounts",
|
|
10079
|
+
severity: "error",
|
|
10080
|
+
message: "Antigravity account storage exists, but all accounts are disabled."
|
|
10081
|
+
});
|
|
10082
|
+
break;
|
|
10083
|
+
}
|
|
10084
|
+
const storage = input2.storage;
|
|
10085
|
+
if (storage && storage.accounts.length > 0) {
|
|
10086
|
+
if (!Number.isInteger(storage.activeIndex) || storage.activeIndex < 0 || storage.activeIndex >= storage.accounts.length) {
|
|
10087
|
+
findings.push({
|
|
10088
|
+
code: "active-index-out-of-range",
|
|
10089
|
+
severity: "error",
|
|
10090
|
+
message: `Active account index ${storage.activeIndex} is outside the stored account range.`,
|
|
10091
|
+
repair: "clamp-active-index"
|
|
10092
|
+
});
|
|
10093
|
+
} else {
|
|
10094
|
+
const activeAccount = storage.accounts[storage.activeIndex];
|
|
10095
|
+
if (activeAccount && !isEnabled(activeAccount) && storage.accounts.some(isEnabled)) {
|
|
10096
|
+
findings.push({
|
|
10097
|
+
code: "active-account-disabled",
|
|
10098
|
+
severity: "error",
|
|
10099
|
+
message: "The active account is disabled while another enabled account is available.",
|
|
10100
|
+
repair: "select-enabled-account",
|
|
10101
|
+
accountEmail: activeAccount.email
|
|
10102
|
+
});
|
|
10103
|
+
}
|
|
10104
|
+
}
|
|
10105
|
+
for (const account of storage.accounts) {
|
|
10106
|
+
if (account.verificationRequired) {
|
|
10107
|
+
findings.push({
|
|
10108
|
+
code: "verification-required",
|
|
10109
|
+
severity: "warning",
|
|
10110
|
+
message: account.verificationRequiredReason ?? "Account requires Google verification before it can be used.",
|
|
10111
|
+
repair: "verify-account",
|
|
10112
|
+
accountEmail: account.email
|
|
10113
|
+
});
|
|
10114
|
+
}
|
|
10115
|
+
}
|
|
10116
|
+
}
|
|
10117
|
+
const status = statusFromFindings(findings);
|
|
10118
|
+
return {
|
|
10119
|
+
status,
|
|
10120
|
+
summary: summaryFromStatus(status),
|
|
10121
|
+
findings,
|
|
10122
|
+
runtime: input2.runtime
|
|
10123
|
+
};
|
|
10124
|
+
}
|
|
10125
|
+
function formatAuthDoctorReport(report) {
|
|
10126
|
+
const lines = [
|
|
10127
|
+
"Antigravity auth doctor",
|
|
10128
|
+
`Status: ${report.status}`,
|
|
10129
|
+
report.summary,
|
|
10130
|
+
""
|
|
10131
|
+
];
|
|
10132
|
+
if (report.runtime) {
|
|
10133
|
+
lines.push(`Antigravity version: ${report.runtime.antigravityVersion} (${report.runtime.antigravityVersionSource})`);
|
|
10134
|
+
lines.push("");
|
|
10135
|
+
}
|
|
10136
|
+
for (const finding of report.findings) {
|
|
10137
|
+
const repair = finding.repair ? ` | repair: ${finding.repair}` : "";
|
|
10138
|
+
const account = finding.accountEmail ? ` | account: ${finding.accountEmail}` : "";
|
|
10139
|
+
lines.push(`- [${finding.severity}] ${finding.code}${account}${repair}`);
|
|
10140
|
+
lines.push(` ${finding.message}`);
|
|
10141
|
+
}
|
|
10142
|
+
return lines.join("\n");
|
|
10143
|
+
}
|
|
10144
|
+
|
|
9693
10145
|
// src/plugin/quota.ts
|
|
9694
10146
|
var FETCH_TIMEOUT_MS2 = 1e4;
|
|
9695
10147
|
function buildAuthFromAccount(account) {
|
|
@@ -9721,6 +10173,10 @@ function parseResetTime(resetTime) {
|
|
|
9721
10173
|
return timestamp;
|
|
9722
10174
|
}
|
|
9723
10175
|
function classifyQuotaGroup(modelName, displayName) {
|
|
10176
|
+
const registryGroup = getQuotaGroupForModel(modelName);
|
|
10177
|
+
if (registryGroup) {
|
|
10178
|
+
return registryGroup;
|
|
10179
|
+
}
|
|
9724
10180
|
const combined = `${modelName} ${displayName ?? ""}`.toLowerCase();
|
|
9725
10181
|
if (combined.includes("claude")) {
|
|
9726
10182
|
return "claude";
|
|
@@ -9805,9 +10261,7 @@ async function fetchAvailableModels(accessToken, projectId) {
|
|
|
9805
10261
|
}
|
|
9806
10262
|
async function fetchGeminiCliQuota(accessToken, projectId) {
|
|
9807
10263
|
const endpoint = ANTIGRAVITY_ENDPOINT_PROD;
|
|
9808
|
-
const
|
|
9809
|
-
const arch = process.arch || "arm64";
|
|
9810
|
-
const geminiCliUserAgent = `GeminiCLI/1.0.0/gemini-2.5-pro (${platform}; ${arch})`;
|
|
10264
|
+
const geminiCliUserAgent = buildGeminiCliUserAgent();
|
|
9811
10265
|
const body = projectId ? { project: projectId } : {};
|
|
9812
10266
|
try {
|
|
9813
10267
|
const response = await fetchWithTimeout2(`${endpoint}/v1internal:retrieveUserQuota`, {
|
|
@@ -10139,6 +10593,7 @@ var CHANGELOG_URL = "https://antigravity.google/changelog";
|
|
|
10139
10593
|
var FETCH_TIMEOUT_MS3 = 5e3;
|
|
10140
10594
|
var CHANGELOG_SCAN_CHARS = 5e3;
|
|
10141
10595
|
var VERSION_REGEX = /\d+\.\d+\.\d+/;
|
|
10596
|
+
var lastResolution = null;
|
|
10142
10597
|
function parseVersion(text) {
|
|
10143
10598
|
const match = text.match(VERSION_REGEX);
|
|
10144
10599
|
return match ? match[0] : null;
|
|
@@ -10158,6 +10613,9 @@ async function tryFetchVersion(url, maxChars) {
|
|
|
10158
10613
|
clearTimeout(timeout);
|
|
10159
10614
|
}
|
|
10160
10615
|
}
|
|
10616
|
+
function getAntigravityVersionResolution() {
|
|
10617
|
+
return lastResolution ?? { version: getAntigravityVersion(), source: "fallback" };
|
|
10618
|
+
}
|
|
10161
10619
|
async function initAntigravityVersion() {
|
|
10162
10620
|
const log11 = createLogger("version");
|
|
10163
10621
|
const fallback = getAntigravityVersion();
|
|
@@ -10174,7 +10632,8 @@ async function initAntigravityVersion() {
|
|
|
10174
10632
|
source = "fallback";
|
|
10175
10633
|
setAntigravityVersion(fallback);
|
|
10176
10634
|
log11.info("version-fetch-failed", { fallback });
|
|
10177
|
-
|
|
10635
|
+
lastResolution = { version: fallback, source };
|
|
10636
|
+
return lastResolution;
|
|
10178
10637
|
}
|
|
10179
10638
|
}
|
|
10180
10639
|
if (version !== fallback) {
|
|
@@ -10183,6 +10642,8 @@ async function initAntigravityVersion() {
|
|
|
10183
10642
|
log11.debug("version-unchanged", { version, source });
|
|
10184
10643
|
}
|
|
10185
10644
|
setAntigravityVersion(version);
|
|
10645
|
+
lastResolution = { version, source };
|
|
10646
|
+
return lastResolution;
|
|
10186
10647
|
}
|
|
10187
10648
|
|
|
10188
10649
|
// src/plugin/search.ts
|
|
@@ -10975,6 +11436,13 @@ function buildAuthSuccessFromStoredAccount(account) {
|
|
|
10975
11436
|
projectId: account.projectId ?? ""
|
|
10976
11437
|
};
|
|
10977
11438
|
}
|
|
11439
|
+
function formatCachedQuotaSummary(account) {
|
|
11440
|
+
const quota = account.cachedQuota;
|
|
11441
|
+
if (!quota) {
|
|
11442
|
+
return void 0;
|
|
11443
|
+
}
|
|
11444
|
+
return formatCachedQuotaWithStatus(quota);
|
|
11445
|
+
}
|
|
10978
11446
|
function retryAfterMsFromResponse(response, defaultRetryMs = 6e4) {
|
|
10979
11447
|
const retryAfterMsHeader = response.headers.get("retry-after-ms");
|
|
10980
11448
|
if (retryAfterMsHeader) {
|
|
@@ -11326,7 +11794,33 @@ var createAntigravityPlugin = (providerId) => async ({ client, directory }) => {
|
|
|
11326
11794
|
provider: providerId,
|
|
11327
11795
|
loader: async (getAuth, provider) => {
|
|
11328
11796
|
cachedGetAuth = getAuth;
|
|
11329
|
-
|
|
11797
|
+
let auth = await getAuth();
|
|
11798
|
+
if (!isOAuthAuth(auth)) {
|
|
11799
|
+
const storedAccounts2 = await loadAccounts();
|
|
11800
|
+
const drift = detectAuthStorageDrift(auth, storedAccounts2);
|
|
11801
|
+
if (drift.status === "restorable" && drift.account) {
|
|
11802
|
+
auth = buildAuthFromStoredAccount(drift.account);
|
|
11803
|
+
try {
|
|
11804
|
+
await client.auth.set({
|
|
11805
|
+
path: { id: providerId },
|
|
11806
|
+
body: {
|
|
11807
|
+
type: "oauth",
|
|
11808
|
+
refresh: auth.refresh,
|
|
11809
|
+
access: auth.access ?? "",
|
|
11810
|
+
expires: auth.expires ?? 0
|
|
11811
|
+
}
|
|
11812
|
+
});
|
|
11813
|
+
log10.info("Restored Antigravity OAuth auth from account storage", {
|
|
11814
|
+
reason: drift.reason,
|
|
11815
|
+
email: drift.account.email
|
|
11816
|
+
});
|
|
11817
|
+
} catch (storeError) {
|
|
11818
|
+
log10.warn("Failed to restore Antigravity OAuth auth from account storage", {
|
|
11819
|
+
error: String(storeError)
|
|
11820
|
+
});
|
|
11821
|
+
}
|
|
11822
|
+
}
|
|
11823
|
+
}
|
|
11330
11824
|
if (!isOAuthAuth(auth)) {
|
|
11331
11825
|
try {
|
|
11332
11826
|
await clearAccounts();
|
|
@@ -12234,7 +12728,8 @@ Alternatively, you can:
|
|
|
12234
12728
|
lastUsed: acc.lastUsed,
|
|
12235
12729
|
status,
|
|
12236
12730
|
isCurrentAccount: idx === (existingStorage2.activeIndex ?? 0),
|
|
12237
|
-
enabled: acc.enabled !== false
|
|
12731
|
+
enabled: acc.enabled !== false,
|
|
12732
|
+
quotaSummary: formatCachedQuotaSummary(acc)
|
|
12238
12733
|
};
|
|
12239
12734
|
});
|
|
12240
12735
|
menuResult = await promptLoginMode(existingAccounts);
|
|
@@ -12303,8 +12798,10 @@ Alternatively, you can:
|
|
|
12303
12798
|
const connector = isLast ? "\u2514\u2500" : "\u251C\u2500";
|
|
12304
12799
|
const bar = createProgressBar(model.remainingFraction);
|
|
12305
12800
|
const reset = formatReset(model.resetTime);
|
|
12801
|
+
const status = classifyGroupStatus({ remainingFraction: model.remainingFraction, resetTime: model.resetTime, modelCount: 1 });
|
|
12802
|
+
const badge = formatQuotaStatusBadge(status);
|
|
12306
12803
|
const modelName = model.modelId.padEnd(29);
|
|
12307
|
-
console.log(` \u2502 ${connector} ${modelName} ${bar}${reset}`);
|
|
12804
|
+
console.log(` \u2502 ${connector} ${modelName} ${bar} ${badge}${reset}`);
|
|
12308
12805
|
});
|
|
12309
12806
|
}
|
|
12310
12807
|
const hasAntigravity = res.quota && Object.keys(res.quota.groups).length > 0;
|
|
@@ -12325,8 +12822,10 @@ Alternatively, you can:
|
|
|
12325
12822
|
const connector = isLast ? "\u2514\u2500" : "\u251C\u2500";
|
|
12326
12823
|
const bar = createProgressBar(g.data.remainingFraction);
|
|
12327
12824
|
const reset = formatReset(g.data.resetTime);
|
|
12825
|
+
const status = classifyGroupStatus(g.data);
|
|
12826
|
+
const badge = formatQuotaStatusBadge(status);
|
|
12328
12827
|
const modelName = g.name.padEnd(29);
|
|
12329
|
-
console.log(` ${connector} ${modelName} ${bar}${reset}`);
|
|
12828
|
+
console.log(` ${connector} ${modelName} ${bar} ${badge}${reset}`);
|
|
12330
12829
|
});
|
|
12331
12830
|
}
|
|
12332
12831
|
console.log("");
|
|
@@ -12353,6 +12852,22 @@ Alternatively, you can:
|
|
|
12353
12852
|
console.log("");
|
|
12354
12853
|
continue;
|
|
12355
12854
|
}
|
|
12855
|
+
if (menuResult.mode === "doctor") {
|
|
12856
|
+
const auth = cachedGetAuth ? await cachedGetAuth().catch(() => void 0) : void 0;
|
|
12857
|
+
const versionResolution = getAntigravityVersionResolution();
|
|
12858
|
+
const report = createAuthDoctorReport({
|
|
12859
|
+
auth,
|
|
12860
|
+
storage: existingStorage2,
|
|
12861
|
+
runtime: {
|
|
12862
|
+
antigravityVersion: versionResolution.version,
|
|
12863
|
+
antigravityVersionSource: versionResolution.source
|
|
12864
|
+
}
|
|
12865
|
+
});
|
|
12866
|
+
console.log(`
|
|
12867
|
+
${formatAuthDoctorReport(report)}
|
|
12868
|
+
`);
|
|
12869
|
+
continue;
|
|
12870
|
+
}
|
|
12356
12871
|
if (menuResult.mode === "manage") {
|
|
12357
12872
|
if (menuResult.toggleAccountIndex !== void 0) {
|
|
12358
12873
|
const acc = existingStorage2.accounts[menuResult.toggleAccountIndex];
|