@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.
Files changed (62) hide show
  1. package/dist/index.js +600 -81
  2. package/dist/index.js.map +4 -4
  3. package/dist/src/constants.d.ts +13 -0
  4. package/dist/src/constants.d.ts.map +1 -1
  5. package/dist/src/constants.js +19 -1
  6. package/dist/src/constants.js.map +1 -1
  7. package/dist/src/plugin/auth-doctor.d.ts +30 -0
  8. package/dist/src/plugin/auth-doctor.d.ts.map +1 -0
  9. package/dist/src/plugin/auth-doctor.js +144 -0
  10. package/dist/src/plugin/auth-doctor.js.map +1 -0
  11. package/dist/src/plugin/auth-drift.d.ts +13 -0
  12. package/dist/src/plugin/auth-drift.d.ts.map +1 -0
  13. package/dist/src/plugin/auth-drift.js +70 -0
  14. package/dist/src/plugin/auth-drift.js.map +1 -0
  15. package/dist/src/plugin/cli.d.ts +12 -2
  16. package/dist/src/plugin/cli.d.ts.map +1 -1
  17. package/dist/src/plugin/cli.js +36 -3
  18. package/dist/src/plugin/cli.js.map +1 -1
  19. package/dist/src/plugin/config/models.d.ts +2 -32
  20. package/dist/src/plugin/config/models.d.ts.map +1 -1
  21. package/dist/src/plugin/config/models.js +1 -113
  22. package/dist/src/plugin/config/models.js.map +1 -1
  23. package/dist/src/plugin/config/schema.js +2 -2
  24. package/dist/src/plugin/config/schema.js.map +1 -1
  25. package/dist/src/plugin/model-registry.d.ts +46 -0
  26. package/dist/src/plugin/model-registry.d.ts.map +1 -0
  27. package/dist/src/plugin/model-registry.js +180 -0
  28. package/dist/src/plugin/model-registry.js.map +1 -0
  29. package/dist/src/plugin/quota.d.ts +1 -0
  30. package/dist/src/plugin/quota.d.ts.map +1 -1
  31. package/dist/src/plugin/quota.js +8 -5
  32. package/dist/src/plugin/quota.js.map +1 -1
  33. package/dist/src/plugin/request.d.ts.map +1 -1
  34. package/dist/src/plugin/request.js +9 -9
  35. package/dist/src/plugin/request.js.map +1 -1
  36. package/dist/src/plugin/transform/claude.d.ts +1 -0
  37. package/dist/src/plugin/transform/claude.d.ts.map +1 -1
  38. package/dist/src/plugin/transform/claude.js +13 -0
  39. package/dist/src/plugin/transform/claude.js.map +1 -1
  40. package/dist/src/plugin/transform/model-resolver.d.ts.map +1 -1
  41. package/dist/src/plugin/transform/model-resolver.js +4 -26
  42. package/dist/src/plugin/transform/model-resolver.js.map +1 -1
  43. package/dist/src/plugin/ui/auth-menu.d.ts +25 -1
  44. package/dist/src/plugin/ui/auth-menu.d.ts.map +1 -1
  45. package/dist/src/plugin/ui/auth-menu.js +72 -16
  46. package/dist/src/plugin/ui/auth-menu.js.map +1 -1
  47. package/dist/src/plugin/ui/model-status.d.ts +28 -0
  48. package/dist/src/plugin/ui/model-status.d.ts.map +1 -0
  49. package/dist/src/plugin/ui/model-status.js +80 -0
  50. package/dist/src/plugin/ui/model-status.js.map +1 -0
  51. package/dist/src/plugin/ui/quota-status.d.ts +67 -0
  52. package/dist/src/plugin/ui/quota-status.d.ts.map +1 -0
  53. package/dist/src/plugin/ui/quota-status.js +194 -0
  54. package/dist/src/plugin/ui/quota-status.js.map +1 -0
  55. package/dist/src/plugin/version.d.ts +8 -1
  56. package/dist/src/plugin/version.d.ts.map +1 -1
  57. package/dist/src/plugin/version.js +8 -1
  58. package/dist/src/plugin/version.js.map +1 -1
  59. package/dist/src/plugin.d.ts.map +1 -1
  60. package/dist/src/plugin.js +66 -5
  61. package/dist/src/plugin.js.map +1 -1
  62. 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": GEMINI_CLI_HEADERS["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 `${ANSI.green}[active]${ANSI.reset}`;
1729
+ return ` ${ANSI.green}[active]${ANSI.reset}`;
1595
1730
  case "rate-limited":
1596
- return `${ANSI.yellow}[rate-limited]${ANSI.reset}`;
1731
+ return ` ${ANSI.yellow}[rate-limited]${ANSI.reset}`;
1597
1732
  case "expired":
1598
- return `${ANSI.red}[expired]${ANSI.reset}`;
1733
+ return ` ${ANSI.red}[expired]${ANSI.reset}`;
1599
1734
  case "verification-required":
1600
- return `${ANSI.red}[needs verification]${ANSI.reset}`;
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 ? " " + statusBadge : ""}${disabledBadge}`;
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 ? " " + badge : ""}${disabledBadge}`;
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 result = await select([
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/config/models.ts
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 OPENCODE_MODEL_DEFINITIONS = {
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 false
3040
+ * @default true
2754
3041
  */
2755
- auto_resume: z2.boolean().default(false),
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 === "low" || tier === "medium" ? "gemini-3.5-flash-low" : "gemini-3-flash-agent";
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 = "gemini-3-flash-preview";
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
- headers.set("User-Agent", GEMINI_CLI_HEADERS["User-Agent"]);
7543
- headers.set("X-Goog-Api-Client", GEMINI_CLI_HEADERS["X-Goog-Api-Client"]);
7544
- headers.set("Client-Metadata", GEMINI_CLI_HEADERS["Client-Metadata"]);
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 platform = process.platform || "darwin";
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
- return;
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
- const auth = await getAuth();
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];