@expiren/opencode-antigravity-auth 1.6.17 → 1.6.19
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 +600 -81
- package/dist/index.js.map +4 -4
- 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 +12 -2
- package/dist/src/plugin/cli.d.ts.map +1 -1
- package/dist/src/plugin/cli.js +36 -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 -113
- 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 +9 -9
- package/dist/src/plugin/request.js.map +1 -1
- package/dist/src/plugin/transform/claude.d.ts +1 -0
- package/dist/src/plugin/transform/claude.d.ts.map +1 -1
- package/dist/src/plugin/transform/claude.js +13 -0
- package/dist/src/plugin/transform/claude.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 +72 -16
- package/dist/src/plugin/ui/auth-menu.js.map +1 -1
- package/dist/src/plugin/ui/model-status.d.ts +28 -0
- package/dist/src/plugin/ui/model-status.d.ts.map +1 -0
- package/dist/src/plugin/ui/model-status.js +80 -0
- package/dist/src/plugin/ui/model-status.js.map +1 -0
- 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,78 @@ 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
|
|
1657
|
-
{ label: "Back", value: "back" }
|
|
1830
|
+
const menuItems = [
|
|
1831
|
+
{ label: "Back", value: "back" }
|
|
1832
|
+
];
|
|
1833
|
+
if (!account.isCurrentAccount) {
|
|
1834
|
+
menuItems.push({
|
|
1835
|
+
label: "Switch to this account",
|
|
1836
|
+
value: "switch-account",
|
|
1837
|
+
color: "green"
|
|
1838
|
+
});
|
|
1839
|
+
}
|
|
1840
|
+
menuItems.push(
|
|
1658
1841
|
{ label: "Verify account access", value: "verify", color: "cyan" },
|
|
1659
1842
|
{ label: account.enabled === false ? "Enable account" : "Disable account", value: "toggle", color: account.enabled === false ? "green" : "yellow" },
|
|
1660
|
-
{ label: "Refresh token", value: "refresh", color: "cyan" }
|
|
1843
|
+
{ label: "Refresh token", value: "refresh", color: "cyan" }
|
|
1844
|
+
);
|
|
1845
|
+
if (hasHistory) {
|
|
1846
|
+
menuItems.push({
|
|
1847
|
+
label: `Restore fingerprint (${account.fingerprintHistory.length} saved)`,
|
|
1848
|
+
value: "restore-fingerprint",
|
|
1849
|
+
color: "cyan"
|
|
1850
|
+
});
|
|
1851
|
+
}
|
|
1852
|
+
menuItems.push(
|
|
1661
1853
|
{ label: "Delete this account", value: "delete", color: "red" }
|
|
1662
|
-
|
|
1854
|
+
);
|
|
1855
|
+
const result = await select(menuItems, {
|
|
1663
1856
|
message: header,
|
|
1664
1857
|
subtitle: subtitleParts.join(" | "),
|
|
1665
1858
|
clearScreen: true
|
|
@@ -1681,12 +1874,14 @@ import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync
|
|
|
1681
1874
|
import { join as join3, dirname as dirname2 } from "node:path";
|
|
1682
1875
|
import { homedir as homedir3 } from "node:os";
|
|
1683
1876
|
|
|
1684
|
-
// src/plugin/
|
|
1877
|
+
// src/plugin/model-registry.ts
|
|
1685
1878
|
var DEFAULT_MODALITIES = {
|
|
1686
1879
|
input: ["text", "image", "pdf"],
|
|
1687
1880
|
output: ["text"]
|
|
1688
1881
|
};
|
|
1689
1882
|
var MODEL_RELEASE_DATE = "";
|
|
1883
|
+
var DEFAULT_COST = { input: 0, output: 0 };
|
|
1884
|
+
var DEFAULT_OPTIONS = {};
|
|
1690
1885
|
function defineModel(id, model) {
|
|
1691
1886
|
return {
|
|
1692
1887
|
id,
|
|
@@ -1694,10 +1889,12 @@ function defineModel(id, model) {
|
|
|
1694
1889
|
attachment: model.modalities.input.some((modality) => modality !== "text"),
|
|
1695
1890
|
temperature: true,
|
|
1696
1891
|
tool_call: true,
|
|
1892
|
+
cost: { ...DEFAULT_COST },
|
|
1893
|
+
options: { ...DEFAULT_OPTIONS },
|
|
1697
1894
|
...model
|
|
1698
1895
|
};
|
|
1699
1896
|
}
|
|
1700
|
-
var
|
|
1897
|
+
var PUBLIC_MODEL_DEFINITIONS = {
|
|
1701
1898
|
"antigravity-gemini-3.1-pro": defineModel("antigravity-gemini-3.1-pro", {
|
|
1702
1899
|
name: "Gemini 3.1 Pro (Antigravity)",
|
|
1703
1900
|
reasoning: true,
|
|
@@ -1796,6 +1993,63 @@ var OPENCODE_MODEL_DEFINITIONS = {
|
|
|
1796
1993
|
modalities: DEFAULT_MODALITIES
|
|
1797
1994
|
})
|
|
1798
1995
|
};
|
|
1996
|
+
var RESOLVER_ALIASES = {
|
|
1997
|
+
"gemini-3.1-pro-low": "gemini-3.1-pro",
|
|
1998
|
+
"gemini-3.1-pro-high": "gemini-3.1-pro",
|
|
1999
|
+
"gemini-3-flash-low": "gemini-3-flash",
|
|
2000
|
+
"gemini-3-flash-medium": "gemini-3-flash",
|
|
2001
|
+
"gemini-3-flash-high": "gemini-3-flash",
|
|
2002
|
+
"gemini-3.5-flash-low": "gemini-3.5-flash",
|
|
2003
|
+
"gemini-3.5-flash-medium": "gemini-3.5-flash",
|
|
2004
|
+
"gemini-3.5-flash-high": "gemini-3.5-flash",
|
|
2005
|
+
"gemini-claude-opus-4-6-thinking-low": "claude-opus-4-6-thinking",
|
|
2006
|
+
"gemini-claude-opus-4-6-thinking-medium": "claude-opus-4-6-thinking",
|
|
2007
|
+
"gemini-claude-opus-4-6-thinking-high": "claude-opus-4-6-thinking",
|
|
2008
|
+
"gemini-claude-sonnet-4-6-thinking-low": "claude-sonnet-4-6-thinking",
|
|
2009
|
+
"gemini-claude-sonnet-4-6-thinking-medium": "claude-sonnet-4-6-thinking",
|
|
2010
|
+
"gemini-claude-sonnet-4-6-thinking-high": "claude-sonnet-4-6-thinking",
|
|
2011
|
+
"gemini-claude-sonnet-4-6": "claude-sonnet-4-6-thinking"
|
|
2012
|
+
};
|
|
2013
|
+
var GEMINI_35_FLASH_ROUTES = {
|
|
2014
|
+
antigravity: {
|
|
2015
|
+
defaultModel: "gemini-3-flash-agent",
|
|
2016
|
+
byTier: {
|
|
2017
|
+
low: "gemini-3.5-flash-low",
|
|
2018
|
+
medium: "gemini-3.5-flash-low",
|
|
2019
|
+
high: "gemini-3-flash-agent"
|
|
2020
|
+
}
|
|
2021
|
+
},
|
|
2022
|
+
geminiCliFallbackModel: "gemini-3-flash-preview"
|
|
2023
|
+
};
|
|
2024
|
+
var QUOTA_GROUP_BY_MODEL_ID = {
|
|
2025
|
+
"claude-opus-4-6-thinking": "claude",
|
|
2026
|
+
"claude-opus-4-6": "claude",
|
|
2027
|
+
"claude-sonnet-4-6-thinking": "claude",
|
|
2028
|
+
"claude-sonnet-4-6": "claude",
|
|
2029
|
+
"gemini-pro-agent": "gemini-pro",
|
|
2030
|
+
"gemini-3.1-pro": "gemini-pro",
|
|
2031
|
+
"gemini-3.1-pro-low": "gemini-pro",
|
|
2032
|
+
"gemini-3.1-pro-high": "gemini-pro",
|
|
2033
|
+
"gemini-3-flash": "gemini-flash",
|
|
2034
|
+
"gemini-3-flash-agent": "gemini-flash",
|
|
2035
|
+
"gemini-3.5-flash-low": "gemini-flash"
|
|
2036
|
+
};
|
|
2037
|
+
var OPENCODE_MODEL_DEFINITIONS = PUBLIC_MODEL_DEFINITIONS;
|
|
2038
|
+
function getResolverAliasMap() {
|
|
2039
|
+
return RESOLVER_ALIASES;
|
|
2040
|
+
}
|
|
2041
|
+
function getGemini35FlashAntigravityModel(tier) {
|
|
2042
|
+
if (!tier) {
|
|
2043
|
+
return GEMINI_35_FLASH_ROUTES.antigravity.defaultModel;
|
|
2044
|
+
}
|
|
2045
|
+
return GEMINI_35_FLASH_ROUTES.antigravity.byTier[tier] ?? GEMINI_35_FLASH_ROUTES.antigravity.defaultModel;
|
|
2046
|
+
}
|
|
2047
|
+
function getGemini35FlashGeminiCliFallbackModel() {
|
|
2048
|
+
return GEMINI_35_FLASH_ROUTES.geminiCliFallbackModel;
|
|
2049
|
+
}
|
|
2050
|
+
function getQuotaGroupForModel(modelId) {
|
|
2051
|
+
return QUOTA_GROUP_BY_MODEL_ID[modelId.toLowerCase()];
|
|
2052
|
+
}
|
|
1799
2053
|
|
|
1800
2054
|
// src/plugin/config/updater.ts
|
|
1801
2055
|
var PLUGIN_NAME = "@expiren/opencode-antigravity-auth@latest";
|
|
@@ -1906,7 +2160,7 @@ ${existingAccounts.length} account(s) saved:`);
|
|
|
1906
2160
|
}
|
|
1907
2161
|
console.log("");
|
|
1908
2162
|
while (true) {
|
|
1909
|
-
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]: ");
|
|
2163
|
+
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]: ");
|
|
1910
2164
|
const normalized = answer.trim().toLowerCase();
|
|
1911
2165
|
if (normalized === "a" || normalized === "add") {
|
|
1912
2166
|
return { mode: "add" };
|
|
@@ -1917,13 +2171,16 @@ ${existingAccounts.length} account(s) saved:`);
|
|
|
1917
2171
|
if (normalized === "c" || normalized === "check") {
|
|
1918
2172
|
return { mode: "check" };
|
|
1919
2173
|
}
|
|
2174
|
+
if (normalized === "d" || normalized === "doctor" || normalized === "auth-doctor") {
|
|
2175
|
+
return { mode: "doctor" };
|
|
2176
|
+
}
|
|
1920
2177
|
if (normalized === "v" || normalized === "verify") {
|
|
1921
2178
|
return { mode: "verify" };
|
|
1922
2179
|
}
|
|
1923
2180
|
if (normalized === "va" || normalized === "verify-all" || normalized === "all") {
|
|
1924
2181
|
return { mode: "verify-all", verifyAll: true };
|
|
1925
2182
|
}
|
|
1926
|
-
console.log("Please enter 'a', 'f', 'c', 'v', or 'va'.");
|
|
2183
|
+
console.log("Please enter 'a', 'f', 'c', 'd', 'v', or 'va'.");
|
|
1927
2184
|
}
|
|
1928
2185
|
} finally {
|
|
1929
2186
|
rl.close();
|
|
@@ -1940,7 +2197,12 @@ async function promptLoginMode(existingAccounts) {
|
|
|
1940
2197
|
lastUsed: acc.lastUsed,
|
|
1941
2198
|
status: acc.status,
|
|
1942
2199
|
isCurrentAccount: acc.isCurrentAccount,
|
|
1943
|
-
enabled: acc.enabled
|
|
2200
|
+
enabled: acc.enabled,
|
|
2201
|
+
quotaSummary: acc.quotaSummary,
|
|
2202
|
+
cooldownMs: acc.cooldownMs,
|
|
2203
|
+
cooldownReason: acc.cooldownReason,
|
|
2204
|
+
cachedQuota: acc.cachedQuota,
|
|
2205
|
+
fingerprintHistory: acc.fingerprintHistory
|
|
1944
2206
|
}));
|
|
1945
2207
|
console.log("");
|
|
1946
2208
|
while (true) {
|
|
@@ -1950,6 +2212,12 @@ async function promptLoginMode(existingAccounts) {
|
|
|
1950
2212
|
return { mode: "add" };
|
|
1951
2213
|
case "check":
|
|
1952
2214
|
return { mode: "check" };
|
|
2215
|
+
case "doctor":
|
|
2216
|
+
return { mode: "doctor" };
|
|
2217
|
+
case "repair":
|
|
2218
|
+
return { mode: "repair" };
|
|
2219
|
+
case "current":
|
|
2220
|
+
return { mode: "current" };
|
|
1953
2221
|
case "verify":
|
|
1954
2222
|
return { mode: "verify" };
|
|
1955
2223
|
case "verify-all":
|
|
@@ -1968,6 +2236,25 @@ async function promptLoginMode(existingAccounts) {
|
|
|
1968
2236
|
if (accountAction === "verify") {
|
|
1969
2237
|
return { mode: "verify", verifyAccountIndex: action.account.index };
|
|
1970
2238
|
}
|
|
2239
|
+
if (accountAction === "switch-account") {
|
|
2240
|
+
const accountLabel = action.account.email || `Account ${action.account.index + 1}`;
|
|
2241
|
+
console.log(`
|
|
2242
|
+
\u2713 Switched to ${accountLabel}. Restart OpenCode for changes to take effect.
|
|
2243
|
+
`);
|
|
2244
|
+
return { mode: "switch-account", switchAccountIndex: action.account.index };
|
|
2245
|
+
}
|
|
2246
|
+
if (accountAction === "restore-fingerprint") {
|
|
2247
|
+
const history = action.account.fingerprintHistory;
|
|
2248
|
+
if (!history || history.length === 0) continue;
|
|
2249
|
+
const accountLabel = action.account.email || `Account ${action.account.index + 1}`;
|
|
2250
|
+
const historyIndex = await showFingerprintHistory(history, accountLabel);
|
|
2251
|
+
if (historyIndex === null) continue;
|
|
2252
|
+
return {
|
|
2253
|
+
mode: "restore-fingerprint",
|
|
2254
|
+
restoreFingerprintAccountIndex: action.account.index,
|
|
2255
|
+
restoreFingerprintHistoryIndex: historyIndex
|
|
2256
|
+
};
|
|
2257
|
+
}
|
|
1971
2258
|
continue;
|
|
1972
2259
|
}
|
|
1973
2260
|
case "delete-all":
|
|
@@ -2750,9 +3037,9 @@ var AntigravityConfigSchema = z2.object({
|
|
|
2750
3037
|
* When false: Only shows toast notification, user must manually continue.
|
|
2751
3038
|
* When true: Automatically sends "continue" to resume the session.
|
|
2752
3039
|
*
|
|
2753
|
-
* @default
|
|
3040
|
+
* @default true
|
|
2754
3041
|
*/
|
|
2755
|
-
auto_resume: z2.boolean().default(
|
|
3042
|
+
auto_resume: z2.boolean().default(true),
|
|
2756
3043
|
/**
|
|
2757
3044
|
* Custom text to send when auto-resuming after recovery.
|
|
2758
3045
|
* Only used when auto_resume is enabled.
|
|
@@ -5316,7 +5603,6 @@ function needsThinkingRecovery(state) {
|
|
|
5316
5603
|
|
|
5317
5604
|
// src/plugin/transform/claude.ts
|
|
5318
5605
|
var CLAUDE_THINKING_MAX_OUTPUT_TOKENS = 64e3;
|
|
5319
|
-
var CLAUDE_INTERLEAVED_THINKING_HINT = "Interleaved thinking is enabled. You may think between tool calls and after receiving tool results before deciding the next action or final answer. Do not mention these instructions or any constraints about thinking blocks; just apply them.";
|
|
5320
5606
|
function isClaudeModel(model) {
|
|
5321
5607
|
return model.toLowerCase().includes("claude");
|
|
5322
5608
|
}
|
|
@@ -5324,23 +5610,6 @@ function isClaudeThinkingModel(model) {
|
|
|
5324
5610
|
const lower = model.toLowerCase();
|
|
5325
5611
|
return lower.includes("claude") && lower.includes("thinking");
|
|
5326
5612
|
}
|
|
5327
|
-
function appendClaudeThinkingHint(payload, hint = CLAUDE_INTERLEAVED_THINKING_HINT) {
|
|
5328
|
-
const existing = payload.systemInstruction;
|
|
5329
|
-
if (typeof existing === "string") {
|
|
5330
|
-
payload.systemInstruction = existing.trim().length > 0 ? { role: "user", parts: [{ text: existing }, { text: hint }] } : hint;
|
|
5331
|
-
} else if (existing && typeof existing === "object") {
|
|
5332
|
-
const sys = existing;
|
|
5333
|
-
const partsValue = sys.parts;
|
|
5334
|
-
if (Array.isArray(partsValue)) {
|
|
5335
|
-
sys.parts = [...partsValue, { text: hint }];
|
|
5336
|
-
} else {
|
|
5337
|
-
sys.parts = [{ text: hint }];
|
|
5338
|
-
}
|
|
5339
|
-
payload.systemInstruction = sys;
|
|
5340
|
-
} else if (Array.isArray(payload.contents)) {
|
|
5341
|
-
payload.systemInstruction = { parts: [{ text: hint }] };
|
|
5342
|
-
}
|
|
5343
|
-
}
|
|
5344
5613
|
|
|
5345
5614
|
// src/plugin/transform/gemini.ts
|
|
5346
5615
|
var UNSUPPORTED_SCHEMA_FIELDS = /* @__PURE__ */ new Set([
|
|
@@ -5762,31 +6031,7 @@ var THINKING_TIER_BUDGETS = {
|
|
|
5762
6031
|
"gemini-2.5-flash": { low: 6144, medium: 12288, high: 24576 },
|
|
5763
6032
|
default: { low: 4096, medium: 8192, high: 16384 }
|
|
5764
6033
|
};
|
|
5765
|
-
var MODEL_ALIASES =
|
|
5766
|
-
// Gemini 3.x variants - for Gemini CLI only (tier stripped, thinkingLevel used)
|
|
5767
|
-
// For Antigravity, these are bypassed and full model name is kept
|
|
5768
|
-
"gemini-3.1-pro-low": "gemini-3.1-pro",
|
|
5769
|
-
"gemini-3.1-pro-high": "gemini-3.1-pro",
|
|
5770
|
-
"gemini-3-flash-low": "gemini-3-flash",
|
|
5771
|
-
"gemini-3-flash-medium": "gemini-3-flash",
|
|
5772
|
-
"gemini-3-flash-high": "gemini-3-flash",
|
|
5773
|
-
// Gemini 3.5 Flash variants
|
|
5774
|
-
"gemini-3.5-flash-low": "gemini-3.5-flash",
|
|
5775
|
-
"gemini-3.5-flash-medium": "gemini-3.5-flash",
|
|
5776
|
-
"gemini-3.5-flash-high": "gemini-3.5-flash",
|
|
5777
|
-
// Claude proxy names (gemini- prefix for compatibility)
|
|
5778
|
-
"gemini-claude-opus-4-6-thinking-low": "claude-opus-4-6-thinking",
|
|
5779
|
-
"gemini-claude-opus-4-6-thinking-medium": "claude-opus-4-6-thinking",
|
|
5780
|
-
"gemini-claude-opus-4-6-thinking-high": "claude-opus-4-6-thinking",
|
|
5781
|
-
"gemini-claude-sonnet-4-6-thinking-low": "claude-sonnet-4-6-thinking",
|
|
5782
|
-
"gemini-claude-sonnet-4-6-thinking-medium": "claude-sonnet-4-6-thinking",
|
|
5783
|
-
"gemini-claude-sonnet-4-6-thinking-high": "claude-sonnet-4-6-thinking",
|
|
5784
|
-
"gemini-claude-sonnet-4-6": "claude-sonnet-4-6-thinking"
|
|
5785
|
-
// Image generation models
|
|
5786
|
-
// gemini-3.1-flash-image (Nano Banana 2) - available via Antigravity API and Gemini CLI
|
|
5787
|
-
// gemini-2.5-flash-image (Nano Banana) - NOT supported by Antigravity, only Google AI API
|
|
5788
|
-
// Reference: Antigravity-Manager/src-tauri/src/proxy/common/model_mapping.rs
|
|
5789
|
-
};
|
|
6034
|
+
var MODEL_ALIASES = getResolverAliasMap();
|
|
5790
6035
|
var TIER_REGEX = /-(minimal|low|medium|high)$/;
|
|
5791
6036
|
var QUOTA_PREFIX_REGEX = /^antigravity-/i;
|
|
5792
6037
|
var GEMINI_3_PRO_REGEX = /^gemini-3(?:\.\d+)?-pro/i;
|
|
@@ -5829,7 +6074,7 @@ function isGemini35FlashModel(model) {
|
|
|
5829
6074
|
return /^gemini-3\.5-flash/i.test(model);
|
|
5830
6075
|
}
|
|
5831
6076
|
function resolveGemini35FlashAntigravityModel(tier) {
|
|
5832
|
-
return tier
|
|
6077
|
+
return getGemini35FlashAntigravityModel(tier);
|
|
5833
6078
|
}
|
|
5834
6079
|
function resolveModelWithTier(requestedModel, options = {}) {
|
|
5835
6080
|
const isAntigravity = QUOTA_PREFIX_REGEX.test(requestedModel);
|
|
@@ -5956,7 +6201,7 @@ function resolveModelForHeaderStyle(requestedModel, headerStyle) {
|
|
|
5956
6201
|
const hasPreviewSuffix = /-preview($|-)/i.test(transformedModel);
|
|
5957
6202
|
const isGemini35Flash = isGemini35FlashModel(transformedModel);
|
|
5958
6203
|
if (isGemini35Flash) {
|
|
5959
|
-
transformedModel =
|
|
6204
|
+
transformedModel = getGemini35FlashGeminiCliFallbackModel();
|
|
5960
6205
|
} else if (!hasPreviewSuffix) {
|
|
5961
6206
|
transformedModel = `${transformedModel}-preview`;
|
|
5962
6207
|
}
|
|
@@ -7291,9 +7536,6 @@ function prepareAntigravityRequest(input2, init, accessToken, projectId, endpoin
|
|
|
7291
7536
|
requestPayload.systemInstruction = requestPayload.system_instruction;
|
|
7292
7537
|
delete requestPayload.system_instruction;
|
|
7293
7538
|
}
|
|
7294
|
-
if (isClaudeThinking && Array.isArray(requestPayload.tools) && requestPayload.tools.length > 0) {
|
|
7295
|
-
appendClaudeThinkingHint(requestPayload);
|
|
7296
|
-
}
|
|
7297
7539
|
const cachedContentFromExtra = typeof requestPayload.extra_body === "object" && requestPayload.extra_body ? requestPayload.extra_body.cached_content ?? requestPayload.extra_body.cachedContent : void 0;
|
|
7298
7540
|
const cachedContent = requestPayload.cached_content ?? requestPayload.cachedContent ?? cachedContentFromExtra;
|
|
7299
7541
|
if (cachedContent) {
|
|
@@ -7539,9 +7781,10 @@ function prepareAntigravityRequest(input2, init, accessToken, projectId, endpoin
|
|
|
7539
7781
|
const fingerprintHeaders = buildFingerprintHeaders(fingerprint);
|
|
7540
7782
|
headers.set("User-Agent", fingerprintHeaders["User-Agent"] || selectedHeaders["User-Agent"]);
|
|
7541
7783
|
} else {
|
|
7542
|
-
|
|
7543
|
-
headers.set("
|
|
7544
|
-
headers.set("Client
|
|
7784
|
+
const geminiCliHeaders = getRandomizedHeaders("gemini-cli", requestedModel);
|
|
7785
|
+
headers.set("User-Agent", geminiCliHeaders["User-Agent"]);
|
|
7786
|
+
if (geminiCliHeaders["X-Goog-Api-Client"]) headers.set("X-Goog-Api-Client", geminiCliHeaders["X-Goog-Api-Client"]);
|
|
7787
|
+
if (geminiCliHeaders["Client-Metadata"]) headers.set("Client-Metadata", geminiCliHeaders["Client-Metadata"]);
|
|
7545
7788
|
}
|
|
7546
7789
|
return {
|
|
7547
7790
|
request: transformedUrl,
|
|
@@ -9681,6 +9924,219 @@ async function showLocalDevToast(client, version) {
|
|
|
9681
9924
|
logAutoUpdate(`Local dev toast shown: v${version}`);
|
|
9682
9925
|
}
|
|
9683
9926
|
|
|
9927
|
+
// src/plugin/auth-drift.ts
|
|
9928
|
+
function isAccountEnabled(account) {
|
|
9929
|
+
return account.enabled !== false;
|
|
9930
|
+
}
|
|
9931
|
+
function selectRestorableAccount(storage) {
|
|
9932
|
+
if (!storage || storage.accounts.length === 0) {
|
|
9933
|
+
return void 0;
|
|
9934
|
+
}
|
|
9935
|
+
const activeAccount = storage.accounts[storage.activeIndex];
|
|
9936
|
+
if (activeAccount && isAccountEnabled(activeAccount)) {
|
|
9937
|
+
return activeAccount;
|
|
9938
|
+
}
|
|
9939
|
+
return storage.accounts.find(isAccountEnabled);
|
|
9940
|
+
}
|
|
9941
|
+
function buildAuthFromStoredAccount(account) {
|
|
9942
|
+
return {
|
|
9943
|
+
type: "oauth",
|
|
9944
|
+
refresh: formatRefreshParts({
|
|
9945
|
+
refreshToken: account.refreshToken,
|
|
9946
|
+
projectId: account.projectId,
|
|
9947
|
+
managedProjectId: account.managedProjectId
|
|
9948
|
+
}),
|
|
9949
|
+
access: "",
|
|
9950
|
+
expires: 0
|
|
9951
|
+
};
|
|
9952
|
+
}
|
|
9953
|
+
function detectAuthStorageDrift(auth, storage) {
|
|
9954
|
+
if (!storage || storage.accounts.length === 0) {
|
|
9955
|
+
return {
|
|
9956
|
+
status: "unavailable",
|
|
9957
|
+
reason: "no-account-storage"
|
|
9958
|
+
};
|
|
9959
|
+
}
|
|
9960
|
+
const restorableAccount = selectRestorableAccount(storage);
|
|
9961
|
+
if (!restorableAccount) {
|
|
9962
|
+
return {
|
|
9963
|
+
status: "unavailable",
|
|
9964
|
+
reason: "no-enabled-accounts"
|
|
9965
|
+
};
|
|
9966
|
+
}
|
|
9967
|
+
if (!auth) {
|
|
9968
|
+
return {
|
|
9969
|
+
status: "restorable",
|
|
9970
|
+
reason: "missing-opencode-auth",
|
|
9971
|
+
account: restorableAccount
|
|
9972
|
+
};
|
|
9973
|
+
}
|
|
9974
|
+
if (!isOAuthAuth(auth)) {
|
|
9975
|
+
return {
|
|
9976
|
+
status: "restorable",
|
|
9977
|
+
reason: "non-oauth-opencode-auth",
|
|
9978
|
+
account: restorableAccount
|
|
9979
|
+
};
|
|
9980
|
+
}
|
|
9981
|
+
const authRefreshToken = parseRefreshParts(auth.refresh).refreshToken;
|
|
9982
|
+
const matchedAccount = storage.accounts.find((account) => account.refreshToken === authRefreshToken);
|
|
9983
|
+
if (matchedAccount) {
|
|
9984
|
+
return {
|
|
9985
|
+
status: "healthy",
|
|
9986
|
+
reason: "auth-matches-storage",
|
|
9987
|
+
account: matchedAccount
|
|
9988
|
+
};
|
|
9989
|
+
}
|
|
9990
|
+
return {
|
|
9991
|
+
status: "drifted",
|
|
9992
|
+
reason: "refresh-token-not-in-storage",
|
|
9993
|
+
account: restorableAccount
|
|
9994
|
+
};
|
|
9995
|
+
}
|
|
9996
|
+
|
|
9997
|
+
// src/plugin/auth-doctor.ts
|
|
9998
|
+
function isEnabled(account) {
|
|
9999
|
+
return account.enabled !== false;
|
|
10000
|
+
}
|
|
10001
|
+
function statusFromFindings(findings) {
|
|
10002
|
+
if (findings.some((finding) => finding.repair && finding.severity === "error")) {
|
|
10003
|
+
return "repairable";
|
|
10004
|
+
}
|
|
10005
|
+
if (findings.some((finding) => finding.severity === "error")) {
|
|
10006
|
+
return "error";
|
|
10007
|
+
}
|
|
10008
|
+
if (findings.some((finding) => finding.severity === "warning")) {
|
|
10009
|
+
return "warning";
|
|
10010
|
+
}
|
|
10011
|
+
return "ok";
|
|
10012
|
+
}
|
|
10013
|
+
function summaryFromStatus(status) {
|
|
10014
|
+
switch (status) {
|
|
10015
|
+
case "ok":
|
|
10016
|
+
return "OpenCode auth and Antigravity account storage are in sync.";
|
|
10017
|
+
case "repairable":
|
|
10018
|
+
return "Auth drift detected. One or more safe repairs are available.";
|
|
10019
|
+
case "warning":
|
|
10020
|
+
return "Auth is usable, but one or more accounts need attention.";
|
|
10021
|
+
case "error":
|
|
10022
|
+
return "Auth state is not usable and no safe automatic repair is available.";
|
|
10023
|
+
}
|
|
10024
|
+
}
|
|
10025
|
+
function createAuthDoctorReport(input2) {
|
|
10026
|
+
const findings = [];
|
|
10027
|
+
const drift = detectAuthStorageDrift(input2.auth, input2.storage);
|
|
10028
|
+
switch (drift.reason) {
|
|
10029
|
+
case "auth-matches-storage":
|
|
10030
|
+
findings.push({
|
|
10031
|
+
code: "auth-matches-storage",
|
|
10032
|
+
severity: "info",
|
|
10033
|
+
message: "OpenCode OAuth refresh token exists in Antigravity account storage.",
|
|
10034
|
+
accountEmail: drift.account?.email
|
|
10035
|
+
});
|
|
10036
|
+
break;
|
|
10037
|
+
case "missing-opencode-auth":
|
|
10038
|
+
findings.push({
|
|
10039
|
+
code: "missing-opencode-auth",
|
|
10040
|
+
severity: "error",
|
|
10041
|
+
message: "OpenCode auth.json has no Google OAuth entry, but Antigravity account storage has a restorable account.",
|
|
10042
|
+
repair: "restore-opencode-auth",
|
|
10043
|
+
accountEmail: drift.account?.email
|
|
10044
|
+
});
|
|
10045
|
+
break;
|
|
10046
|
+
case "non-oauth-opencode-auth":
|
|
10047
|
+
findings.push({
|
|
10048
|
+
code: "non-oauth-opencode-auth",
|
|
10049
|
+
severity: "error",
|
|
10050
|
+
message: "OpenCode Google auth is not OAuth, but Antigravity account storage has a restorable OAuth account.",
|
|
10051
|
+
repair: "restore-opencode-auth",
|
|
10052
|
+
accountEmail: drift.account?.email
|
|
10053
|
+
});
|
|
10054
|
+
break;
|
|
10055
|
+
case "refresh-token-not-in-storage":
|
|
10056
|
+
findings.push({
|
|
10057
|
+
code: "refresh-token-not-in-storage",
|
|
10058
|
+
severity: "error",
|
|
10059
|
+
message: "OpenCode Google OAuth refresh token does not match any stored Antigravity account.",
|
|
10060
|
+
repair: "restore-opencode-auth",
|
|
10061
|
+
accountEmail: drift.account?.email
|
|
10062
|
+
});
|
|
10063
|
+
break;
|
|
10064
|
+
case "no-account-storage":
|
|
10065
|
+
findings.push({
|
|
10066
|
+
code: "no-account-storage",
|
|
10067
|
+
severity: "error",
|
|
10068
|
+
message: "No Antigravity account storage was found."
|
|
10069
|
+
});
|
|
10070
|
+
break;
|
|
10071
|
+
case "no-enabled-accounts":
|
|
10072
|
+
findings.push({
|
|
10073
|
+
code: "no-enabled-accounts",
|
|
10074
|
+
severity: "error",
|
|
10075
|
+
message: "Antigravity account storage exists, but all accounts are disabled."
|
|
10076
|
+
});
|
|
10077
|
+
break;
|
|
10078
|
+
}
|
|
10079
|
+
const storage = input2.storage;
|
|
10080
|
+
if (storage && storage.accounts.length > 0) {
|
|
10081
|
+
if (!Number.isInteger(storage.activeIndex) || storage.activeIndex < 0 || storage.activeIndex >= storage.accounts.length) {
|
|
10082
|
+
findings.push({
|
|
10083
|
+
code: "active-index-out-of-range",
|
|
10084
|
+
severity: "error",
|
|
10085
|
+
message: `Active account index ${storage.activeIndex} is outside the stored account range.`,
|
|
10086
|
+
repair: "clamp-active-index"
|
|
10087
|
+
});
|
|
10088
|
+
} else {
|
|
10089
|
+
const activeAccount = storage.accounts[storage.activeIndex];
|
|
10090
|
+
if (activeAccount && !isEnabled(activeAccount) && storage.accounts.some(isEnabled)) {
|
|
10091
|
+
findings.push({
|
|
10092
|
+
code: "active-account-disabled",
|
|
10093
|
+
severity: "error",
|
|
10094
|
+
message: "The active account is disabled while another enabled account is available.",
|
|
10095
|
+
repair: "select-enabled-account",
|
|
10096
|
+
accountEmail: activeAccount.email
|
|
10097
|
+
});
|
|
10098
|
+
}
|
|
10099
|
+
}
|
|
10100
|
+
for (const account of storage.accounts) {
|
|
10101
|
+
if (account.verificationRequired) {
|
|
10102
|
+
findings.push({
|
|
10103
|
+
code: "verification-required",
|
|
10104
|
+
severity: "warning",
|
|
10105
|
+
message: account.verificationRequiredReason ?? "Account requires Google verification before it can be used.",
|
|
10106
|
+
repair: "verify-account",
|
|
10107
|
+
accountEmail: account.email
|
|
10108
|
+
});
|
|
10109
|
+
}
|
|
10110
|
+
}
|
|
10111
|
+
}
|
|
10112
|
+
const status = statusFromFindings(findings);
|
|
10113
|
+
return {
|
|
10114
|
+
status,
|
|
10115
|
+
summary: summaryFromStatus(status),
|
|
10116
|
+
findings,
|
|
10117
|
+
runtime: input2.runtime
|
|
10118
|
+
};
|
|
10119
|
+
}
|
|
10120
|
+
function formatAuthDoctorReport(report) {
|
|
10121
|
+
const lines = [
|
|
10122
|
+
"Antigravity auth doctor",
|
|
10123
|
+
`Status: ${report.status}`,
|
|
10124
|
+
report.summary,
|
|
10125
|
+
""
|
|
10126
|
+
];
|
|
10127
|
+
if (report.runtime) {
|
|
10128
|
+
lines.push(`Antigravity version: ${report.runtime.antigravityVersion} (${report.runtime.antigravityVersionSource})`);
|
|
10129
|
+
lines.push("");
|
|
10130
|
+
}
|
|
10131
|
+
for (const finding of report.findings) {
|
|
10132
|
+
const repair = finding.repair ? ` | repair: ${finding.repair}` : "";
|
|
10133
|
+
const account = finding.accountEmail ? ` | account: ${finding.accountEmail}` : "";
|
|
10134
|
+
lines.push(`- [${finding.severity}] ${finding.code}${account}${repair}`);
|
|
10135
|
+
lines.push(` ${finding.message}`);
|
|
10136
|
+
}
|
|
10137
|
+
return lines.join("\n");
|
|
10138
|
+
}
|
|
10139
|
+
|
|
9684
10140
|
// src/plugin/quota.ts
|
|
9685
10141
|
var FETCH_TIMEOUT_MS2 = 1e4;
|
|
9686
10142
|
function buildAuthFromAccount(account) {
|
|
@@ -9712,6 +10168,10 @@ function parseResetTime(resetTime) {
|
|
|
9712
10168
|
return timestamp;
|
|
9713
10169
|
}
|
|
9714
10170
|
function classifyQuotaGroup(modelName, displayName) {
|
|
10171
|
+
const registryGroup = getQuotaGroupForModel(modelName);
|
|
10172
|
+
if (registryGroup) {
|
|
10173
|
+
return registryGroup;
|
|
10174
|
+
}
|
|
9715
10175
|
const combined = `${modelName} ${displayName ?? ""}`.toLowerCase();
|
|
9716
10176
|
if (combined.includes("claude")) {
|
|
9717
10177
|
return "claude";
|
|
@@ -9796,9 +10256,7 @@ async function fetchAvailableModels(accessToken, projectId) {
|
|
|
9796
10256
|
}
|
|
9797
10257
|
async function fetchGeminiCliQuota(accessToken, projectId) {
|
|
9798
10258
|
const endpoint = ANTIGRAVITY_ENDPOINT_PROD;
|
|
9799
|
-
const
|
|
9800
|
-
const arch = process.arch || "arm64";
|
|
9801
|
-
const geminiCliUserAgent = `GeminiCLI/1.0.0/gemini-2.5-pro (${platform}; ${arch})`;
|
|
10259
|
+
const geminiCliUserAgent = buildGeminiCliUserAgent();
|
|
9802
10260
|
const body = projectId ? { project: projectId } : {};
|
|
9803
10261
|
try {
|
|
9804
10262
|
const response = await fetchWithTimeout2(`${endpoint}/v1internal:retrieveUserQuota`, {
|
|
@@ -10130,6 +10588,7 @@ var CHANGELOG_URL = "https://antigravity.google/changelog";
|
|
|
10130
10588
|
var FETCH_TIMEOUT_MS3 = 5e3;
|
|
10131
10589
|
var CHANGELOG_SCAN_CHARS = 5e3;
|
|
10132
10590
|
var VERSION_REGEX = /\d+\.\d+\.\d+/;
|
|
10591
|
+
var lastResolution = null;
|
|
10133
10592
|
function parseVersion(text) {
|
|
10134
10593
|
const match = text.match(VERSION_REGEX);
|
|
10135
10594
|
return match ? match[0] : null;
|
|
@@ -10149,6 +10608,9 @@ async function tryFetchVersion(url, maxChars) {
|
|
|
10149
10608
|
clearTimeout(timeout);
|
|
10150
10609
|
}
|
|
10151
10610
|
}
|
|
10611
|
+
function getAntigravityVersionResolution() {
|
|
10612
|
+
return lastResolution ?? { version: getAntigravityVersion(), source: "fallback" };
|
|
10613
|
+
}
|
|
10152
10614
|
async function initAntigravityVersion() {
|
|
10153
10615
|
const log11 = createLogger("version");
|
|
10154
10616
|
const fallback = getAntigravityVersion();
|
|
@@ -10165,7 +10627,8 @@ async function initAntigravityVersion() {
|
|
|
10165
10627
|
source = "fallback";
|
|
10166
10628
|
setAntigravityVersion(fallback);
|
|
10167
10629
|
log11.info("version-fetch-failed", { fallback });
|
|
10168
|
-
|
|
10630
|
+
lastResolution = { version: fallback, source };
|
|
10631
|
+
return lastResolution;
|
|
10169
10632
|
}
|
|
10170
10633
|
}
|
|
10171
10634
|
if (version !== fallback) {
|
|
@@ -10174,6 +10637,8 @@ async function initAntigravityVersion() {
|
|
|
10174
10637
|
log11.debug("version-unchanged", { version, source });
|
|
10175
10638
|
}
|
|
10176
10639
|
setAntigravityVersion(version);
|
|
10640
|
+
lastResolution = { version, source };
|
|
10641
|
+
return lastResolution;
|
|
10177
10642
|
}
|
|
10178
10643
|
|
|
10179
10644
|
// src/plugin/search.ts
|
|
@@ -10966,6 +11431,13 @@ function buildAuthSuccessFromStoredAccount(account) {
|
|
|
10966
11431
|
projectId: account.projectId ?? ""
|
|
10967
11432
|
};
|
|
10968
11433
|
}
|
|
11434
|
+
function formatCachedQuotaSummary(account) {
|
|
11435
|
+
const quota = account.cachedQuota;
|
|
11436
|
+
if (!quota) {
|
|
11437
|
+
return void 0;
|
|
11438
|
+
}
|
|
11439
|
+
return formatCachedQuotaWithStatus(quota);
|
|
11440
|
+
}
|
|
10969
11441
|
function retryAfterMsFromResponse(response, defaultRetryMs = 6e4) {
|
|
10970
11442
|
const retryAfterMsHeader = response.headers.get("retry-after-ms");
|
|
10971
11443
|
if (retryAfterMsHeader) {
|
|
@@ -11317,7 +11789,33 @@ var createAntigravityPlugin = (providerId) => async ({ client, directory }) => {
|
|
|
11317
11789
|
provider: providerId,
|
|
11318
11790
|
loader: async (getAuth, provider) => {
|
|
11319
11791
|
cachedGetAuth = getAuth;
|
|
11320
|
-
|
|
11792
|
+
let auth = await getAuth();
|
|
11793
|
+
if (!isOAuthAuth(auth)) {
|
|
11794
|
+
const storedAccounts2 = await loadAccounts();
|
|
11795
|
+
const drift = detectAuthStorageDrift(auth, storedAccounts2);
|
|
11796
|
+
if (drift.status === "restorable" && drift.account) {
|
|
11797
|
+
auth = buildAuthFromStoredAccount(drift.account);
|
|
11798
|
+
try {
|
|
11799
|
+
await client.auth.set({
|
|
11800
|
+
path: { id: providerId },
|
|
11801
|
+
body: {
|
|
11802
|
+
type: "oauth",
|
|
11803
|
+
refresh: auth.refresh,
|
|
11804
|
+
access: auth.access ?? "",
|
|
11805
|
+
expires: auth.expires ?? 0
|
|
11806
|
+
}
|
|
11807
|
+
});
|
|
11808
|
+
log10.info("Restored Antigravity OAuth auth from account storage", {
|
|
11809
|
+
reason: drift.reason,
|
|
11810
|
+
email: drift.account.email
|
|
11811
|
+
});
|
|
11812
|
+
} catch (storeError) {
|
|
11813
|
+
log10.warn("Failed to restore Antigravity OAuth auth from account storage", {
|
|
11814
|
+
error: String(storeError)
|
|
11815
|
+
});
|
|
11816
|
+
}
|
|
11817
|
+
}
|
|
11818
|
+
}
|
|
11321
11819
|
if (!isOAuthAuth(auth)) {
|
|
11322
11820
|
try {
|
|
11323
11821
|
await clearAccounts();
|
|
@@ -12225,7 +12723,8 @@ Alternatively, you can:
|
|
|
12225
12723
|
lastUsed: acc.lastUsed,
|
|
12226
12724
|
status,
|
|
12227
12725
|
isCurrentAccount: idx === (existingStorage2.activeIndex ?? 0),
|
|
12228
|
-
enabled: acc.enabled !== false
|
|
12726
|
+
enabled: acc.enabled !== false,
|
|
12727
|
+
quotaSummary: formatCachedQuotaSummary(acc)
|
|
12229
12728
|
};
|
|
12230
12729
|
});
|
|
12231
12730
|
menuResult = await promptLoginMode(existingAccounts);
|
|
@@ -12294,8 +12793,10 @@ Alternatively, you can:
|
|
|
12294
12793
|
const connector = isLast ? "\u2514\u2500" : "\u251C\u2500";
|
|
12295
12794
|
const bar = createProgressBar(model.remainingFraction);
|
|
12296
12795
|
const reset = formatReset(model.resetTime);
|
|
12796
|
+
const status = classifyGroupStatus({ remainingFraction: model.remainingFraction, resetTime: model.resetTime, modelCount: 1 });
|
|
12797
|
+
const badge = formatQuotaStatusBadge(status);
|
|
12297
12798
|
const modelName = model.modelId.padEnd(29);
|
|
12298
|
-
console.log(` \u2502 ${connector} ${modelName} ${bar}${reset}`);
|
|
12799
|
+
console.log(` \u2502 ${connector} ${modelName} ${bar} ${badge}${reset}`);
|
|
12299
12800
|
});
|
|
12300
12801
|
}
|
|
12301
12802
|
const hasAntigravity = res.quota && Object.keys(res.quota.groups).length > 0;
|
|
@@ -12316,8 +12817,10 @@ Alternatively, you can:
|
|
|
12316
12817
|
const connector = isLast ? "\u2514\u2500" : "\u251C\u2500";
|
|
12317
12818
|
const bar = createProgressBar(g.data.remainingFraction);
|
|
12318
12819
|
const reset = formatReset(g.data.resetTime);
|
|
12820
|
+
const status = classifyGroupStatus(g.data);
|
|
12821
|
+
const badge = formatQuotaStatusBadge(status);
|
|
12319
12822
|
const modelName = g.name.padEnd(29);
|
|
12320
|
-
console.log(` ${connector} ${modelName} ${bar}${reset}`);
|
|
12823
|
+
console.log(` ${connector} ${modelName} ${bar} ${badge}${reset}`);
|
|
12321
12824
|
});
|
|
12322
12825
|
}
|
|
12323
12826
|
console.log("");
|
|
@@ -12344,6 +12847,22 @@ Alternatively, you can:
|
|
|
12344
12847
|
console.log("");
|
|
12345
12848
|
continue;
|
|
12346
12849
|
}
|
|
12850
|
+
if (menuResult.mode === "doctor") {
|
|
12851
|
+
const auth = cachedGetAuth ? await cachedGetAuth().catch(() => void 0) : void 0;
|
|
12852
|
+
const versionResolution = getAntigravityVersionResolution();
|
|
12853
|
+
const report = createAuthDoctorReport({
|
|
12854
|
+
auth,
|
|
12855
|
+
storage: existingStorage2,
|
|
12856
|
+
runtime: {
|
|
12857
|
+
antigravityVersion: versionResolution.version,
|
|
12858
|
+
antigravityVersionSource: versionResolution.source
|
|
12859
|
+
}
|
|
12860
|
+
});
|
|
12861
|
+
console.log(`
|
|
12862
|
+
${formatAuthDoctorReport(report)}
|
|
12863
|
+
`);
|
|
12864
|
+
continue;
|
|
12865
|
+
}
|
|
12347
12866
|
if (menuResult.mode === "manage") {
|
|
12348
12867
|
if (menuResult.toggleAccountIndex !== void 0) {
|
|
12349
12868
|
const acc = existingStorage2.accounts[menuResult.toggleAccountIndex];
|