opencode-antigravity-auth-tweaked 1.7.3 → 1.7.4

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.
@@ -15,7 +15,7 @@ import { startOAuthListener } from "./plugin/server";
15
15
  import { clearAccounts, loadAccounts, saveAccounts, saveAccountsReplace } from "./plugin/storage";
16
16
  import { AccountManager, parseRateLimitReason, calculateBackoffMs, computeSoftQuotaCacheTtlMs } from "./plugin/accounts";
17
17
  import { createAutoUpdateCheckerHook } from "./hooks/auto-update-checker";
18
- import { loadConfig, initRuntimeConfig } from "./plugin/config";
18
+ import { loadConfig, initRuntimeConfig, wasConfigCreated, getUserConfigPath } from "./plugin/config";
19
19
  import { createSessionRecoveryHook, getRecoverySuccessToast } from "./plugin/recovery";
20
20
  import { checkAccountsQuota } from "./plugin/quota";
21
21
  import { initDiskSignatureCache } from "./plugin/cache";
@@ -26,6 +26,7 @@ import { getConcurrencyTracker } from "./plugin/concurrency";
26
26
  import { getSessionAccountManager } from "./plugin/sessions";
27
27
  import { initAntigravityVersion } from "./plugin/version";
28
28
  import { executeSearch } from "./plugin/search";
29
+ import { initToastService, toast, setChildSession } from "./plugin/ui/toast";
29
30
  const MAX_OAUTH_ACCOUNTS = 10;
30
31
  const MAX_WARMUP_SESSIONS = 1000;
31
32
  const MAX_WARMUP_RETRIES = 2;
@@ -52,10 +53,6 @@ function preparedRequestSessionId(input) {
52
53
  }
53
54
  const warmupAttemptedSessionIds = new Set();
54
55
  const warmupSucceededSessionIds = new Set();
55
- // Track if this plugin instance is running in a child session (subagent, background task)
56
- // Used to filter toasts based on toast_scope config
57
- let isChildSession = false;
58
- let childSessionParentID = undefined;
59
56
  const log = createLogger("plugin");
60
57
  // Module-level toast debounce to persist across requests (fixes toast spam)
61
58
  const rateLimitToastCooldowns = new Map();
@@ -1020,6 +1017,14 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
1020
1017
  initializeDebug(config);
1021
1018
  // Initialize structured logger for TUI integration
1022
1019
  initLogger(client);
1020
+ // Initialize toast service for user-facing notifications
1021
+ initToastService(client, config);
1022
+ if (wasConfigCreated()) {
1023
+ toast.info("Created default configuration", {
1024
+ title: "Antigravity",
1025
+ message: `Config created at ${getUserConfigPath()}`,
1026
+ });
1027
+ }
1023
1028
  // Fetch latest Antigravity version from remote API (non-blocking, falls back to hardcoded)
1024
1029
  await initAntigravityVersion();
1025
1030
  // Initialize health tracker for hybrid strategy
@@ -1062,14 +1067,12 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
1062
1067
  if (input.event.type === "session.created") {
1063
1068
  const props = input.event.properties;
1064
1069
  if (props?.info?.parentID) {
1065
- isChildSession = true;
1066
- childSessionParentID = props.info.parentID;
1070
+ setChildSession(true);
1067
1071
  log.debug("child-session-detected", { parentID: props.info.parentID });
1068
1072
  }
1069
1073
  else {
1070
1074
  // Reset for root sessions - important when plugin instance is reused
1071
- isChildSession = false;
1072
- childSessionParentID = undefined;
1075
+ setChildSession(false);
1073
1076
  log.debug("root-session-detected", {});
1074
1077
  }
1075
1078
  }
@@ -1099,16 +1102,9 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
1099
1102
  }).catch(() => { });
1100
1103
  // Show success toast (respects toast_scope for child sessions)
1101
1104
  const successToast = getRecoverySuccessToast();
1102
- log.debug("recovery-toast", { ...successToast, isChildSession, toastScope: config.toast_scope });
1103
- if (!(config.toast_scope === "root_only" && isChildSession)) {
1104
- await client.tui.showToast({
1105
- body: {
1106
- title: successToast.title,
1107
- message: successToast.message,
1108
- variant: "success",
1109
- },
1110
- }).catch(() => { });
1111
- }
1105
+ toast.success(successToast.message, {
1106
+ title: successToast.title,
1107
+ });
1112
1108
  }
1113
1109
  }
1114
1110
  }
@@ -1197,14 +1193,7 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
1197
1193
  if (isDebugEnabled()) {
1198
1194
  const logPath = getLogFilePath();
1199
1195
  if (logPath) {
1200
- try {
1201
- await client.tui.showToast({
1202
- body: { message: `Debug log: ${logPath}`, variant: "info" },
1203
- });
1204
- }
1205
- catch {
1206
- // TUI may not be available
1207
- }
1196
+ toast.info(`Debug log: ${logPath}`, { title: "Antigravity" });
1208
1197
  }
1209
1198
  }
1210
1199
  if (provider.models) {
@@ -1250,32 +1239,10 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
1250
1239
  // This ensures we wait and retry when all accounts are rate-limited
1251
1240
  const quietMode = config.quiet_mode;
1252
1241
  const toastScope = config.toast_scope;
1253
- // Helper to show toast without blocking on abort (respects quiet_mode and toast_scope)
1242
+ // Helper to show toast without blocking on abort (respects quiet_mode and toast_scope via ToastService)
1254
1243
  const showToast = async (message, variant) => {
1255
- // Always log to debug regardless of toast filtering
1256
- log.debug("toast", { message, variant, isChildSession, toastScope });
1257
- if (quietMode)
1258
- return;
1259
- if (abortSignal?.aborted)
1260
- return;
1261
- // Filter toasts for child sessions when toast_scope is "root_only"
1262
- if (toastScope === "root_only" && isChildSession) {
1263
- log.debug("toast-suppressed-child-session", { message, variant, parentID: childSessionParentID });
1264
- return;
1265
- }
1266
- if (variant === "warning" && message.toLowerCase().includes("rate")) {
1267
- if (!shouldShowRateLimitToast(message)) {
1268
- return;
1269
- }
1270
- }
1271
- try {
1272
- await client.tui.showToast({
1273
- body: { message, variant },
1274
- });
1275
- }
1276
- catch {
1277
- // TUI may not be available
1278
- }
1244
+ // ToastService handles quiet_mode, toast_scope, and isChildSession
1245
+ await toast.info(message, { variant, signal: abortSignal });
1279
1246
  };
1280
1247
  const hasOtherAccountWithAntigravity = (currentAccount) => {
1281
1248
  if (family !== "gemini")
@@ -1311,7 +1278,7 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
1311
1278
  const maxWaitMs = (config.max_rate_limit_wait_seconds ?? 300) * 1000;
1312
1279
  if (softQuotaWaitMs === null || (maxWaitMs > 0 && softQuotaWaitMs > maxWaitMs)) {
1313
1280
  const waitTimeFormatted = softQuotaWaitMs ? formatWaitTime(softQuotaWaitMs) : "unknown";
1314
- await showToast(`All accounts over ${threshold}% quota threshold. Resets in ${waitTimeFormatted}.`, "error");
1281
+ await toast.info(`All accounts over ${threshold}% quota threshold. Resets in ${waitTimeFormatted}.`, { variant: "error" });
1315
1282
  throw new Error(`Quota protection: All ${accountCount} account(s) are over ${threshold}% usage for ${family}. ` +
1316
1283
  `Quota resets in ${waitTimeFormatted}. ` +
1317
1284
  `Add more accounts, wait for quota reset, or set soft_quota_threshold_percent: 100 to disable.`);
@@ -1409,6 +1376,10 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
1409
1376
  const removed = accountManager.removeAccount(account);
1410
1377
  if (removed) {
1411
1378
  log.warn("Removed revoked account from pool - reauthenticate via `opencode auth login`");
1379
+ toast.warn(`Session revoked for ${account.email || "account"} - please login again`, {
1380
+ title: "Antigravity",
1381
+ force: true,
1382
+ });
1412
1383
  try {
1413
1384
  await accountManager.saveToDisk();
1414
1385
  }
@@ -1549,7 +1520,7 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
1549
1520
  alternateStyle,
1550
1521
  });
1551
1522
  if (fallbackStyle) {
1552
- await showToast(`Antigravity quota exhausted on all accounts. Using Gemini CLI quota.`, "warning");
1523
+ await toast.info(`Antigravity quota exhausted on all accounts. Using Gemini CLI quota.`, { variant: "warning" });
1553
1524
  headerStyle = fallbackStyle;
1554
1525
  pushDebug(`all-accounts antigravity exhausted, quota fallback: ${headerStyle}`);
1555
1526
  }
@@ -1569,7 +1540,7 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
1569
1540
  if (fallbackStyle) {
1570
1541
  const quotaName = headerStyle === "gemini-cli" ? "Gemini CLI" : "Antigravity";
1571
1542
  const altQuotaName = fallbackStyle === "gemini-cli" ? "Gemini CLI" : "Antigravity";
1572
- await showToast(`${quotaName} quota exhausted, using ${altQuotaName} quota`, "warning");
1543
+ await toast.info(`${quotaName} quota exhausted, using ${altQuotaName} quota`, { variant: "warning" });
1573
1544
  headerStyle = fallbackStyle;
1574
1545
  pushDebug(`quota fallback: ${headerStyle}`);
1575
1546
  }
@@ -1784,7 +1755,7 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
1784
1755
  });
1785
1756
  if (fallbackStyle) {
1786
1757
  const safeModelName = model || "this model";
1787
- await showToast(`Antigravity quota exhausted for ${safeModelName}. Switching to Gemini CLI quota...`, "warning");
1758
+ await toast.info(`Antigravity quota exhausted for ${safeModelName}. Switching to Gemini CLI quota...`, { variant: "warning" });
1788
1759
  headerStyle = fallbackStyle;
1789
1760
  pushDebug(`quota fallback: ${headerStyle}`);
1790
1761
  continue;
@@ -1801,7 +1772,7 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
1801
1772
  });
1802
1773
  if (fallbackStyle) {
1803
1774
  const safeModelName = model || "this model";
1804
- await showToast(`Gemini CLI quota exhausted for ${safeModelName}. Switching to Antigravity quota...`, "warning");
1775
+ await toast.info(`Gemini CLI quota exhausted for ${safeModelName}. Switching to Antigravity quota...`, { variant: "warning" });
1805
1776
  headerStyle = fallbackStyle;
1806
1777
  pushDebug(`quota fallback: ${headerStyle}`);
1807
1778
  continue;
@@ -1843,7 +1814,7 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
1843
1814
  accountManager.markRateLimited(account, cooldownMs, family, headerStyle, model);
1844
1815
  const label = account.email || `Account ${account.index + 1}`;
1845
1816
  if (accountManager.shouldShowAccountToast(account.index, 60000)) {
1846
- await showToast(`⚠ ${label} needs verification. Run 'opencode auth login' and use Verify accounts.`, "warning");
1817
+ await toast.info(`⚠ ${label} needs verification. Run 'opencode auth login' and use Verify accounts.`, { variant: "warning" });
1847
1818
  accountManager.markToastShown(account.index);
1848
1819
  }
1849
1820
  pushDebug(`verification-required: disabled account ${account.index}`);
@@ -1881,7 +1852,7 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
1881
1852
  const cloned = response.clone();
1882
1853
  const bodyText = await cloned.text();
1883
1854
  if (bodyText.includes("Prompt is too long") || bodyText.includes("prompt_too_long")) {
1884
- await showToast("Context too long - use /compact to reduce size", "warning");
1855
+ await toast.info("Context too long - use /compact to reduce size", { variant: "warning" });
1885
1856
  const errorMessage = `[Antigravity Error] Context is too long for this model.\n\nPlease use /compact to reduce context size, then retry your request.\n\nAlternatively, you can:\n- Use /clear to start fresh\n- Use /undo to remove recent messages\n- Switch to a model with larger context window`;
1886
1857
  return createSyntheticErrorResponse(errorMessage, prepared.requestedModel);
1887
1858
  }
@@ -1903,7 +1874,7 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
1903
1874
  emptyResponseAttempts.set(emptyAttemptKey, currentAttempts);
1904
1875
  pushDebug(`empty-response: attempt ${currentAttempts}/${maxAttempts}`);
1905
1876
  if (currentAttempts < maxAttempts) {
1906
- await showToast(`Empty response received. Retrying (${currentAttempts}/${maxAttempts})...`, "warning");
1877
+ await toast.info(`Empty response received. Retrying (${currentAttempts}/${maxAttempts})...`, { variant: "warning" });
1907
1878
  await sleep(retryDelayMs, abortSignal);
1908
1879
  continue; // Retry the endpoint loop
1909
1880
  }
@@ -1920,10 +1891,10 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
1920
1891
  const contextError = transformedResponse.headers.get("x-antigravity-context-error");
1921
1892
  if (contextError) {
1922
1893
  if (contextError === "prompt_too_long") {
1923
- await showToast("Context too long - use /compact to reduce size, or trim your request", "warning");
1894
+ await toast.info("Context too long - use /compact to reduce size, or trim your request", { variant: "warning" });
1924
1895
  }
1925
1896
  else if (contextError === "tool_pairing") {
1926
- await showToast("Tool call/result mismatch - use /compact to fix, or /undo last message", "warning");
1897
+ await toast.info("Tool call/result mismatch - use /compact to fix, or /undo last message", { variant: "warning" });
1927
1898
  }
1928
1899
  }
1929
1900
  return transformedResponse;
@@ -2511,16 +2482,7 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
2511
2482
  break;
2512
2483
  }
2513
2484
  accounts.push(result);
2514
- try {
2515
- await client.tui.showToast({
2516
- body: {
2517
- message: `Account ${accounts.length} authenticated${result.email ? ` (${result.email})` : ""}`,
2518
- variant: "success",
2519
- },
2520
- });
2521
- }
2522
- catch {
2523
- }
2485
+ toast.success(`Account ${accounts.length} authenticated${result.email ? ` (${result.email})` : ""}`);
2524
2486
  try {
2525
2487
  if (refreshAccountIndex !== undefined) {
2526
2488
  const currentStorage = await loadAccounts();
@@ -2666,16 +2628,7 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
2666
2628
  const toastMessage = existingCount > 0
2667
2629
  ? `Added account${result.email ? ` (${result.email})` : ""} - ${newTotal} total`
2668
2630
  : `Authenticated${result.email ? ` (${result.email})` : ""}`;
2669
- try {
2670
- await client.tui.showToast({
2671
- body: {
2672
- message: toastMessage,
2673
- variant: "success",
2674
- },
2675
- });
2676
- }
2677
- catch {
2678
- }
2631
+ toast.success(toastMessage);
2679
2632
  }
2680
2633
  return result;
2681
2634
  }
@@ -2718,17 +2671,7 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
2718
2671
  const toastMessage = existingCount > 0
2719
2672
  ? `Added account${result.email ? ` (${result.email})` : ""} - ${newTotal} total`
2720
2673
  : `Authenticated${result.email ? ` (${result.email})` : ""}`;
2721
- try {
2722
- await client.tui.showToast({
2723
- body: {
2724
- message: toastMessage,
2725
- variant: "success",
2726
- },
2727
- });
2728
- }
2729
- catch {
2730
- // TUI may not be available
2731
- }
2674
+ toast.success(toastMessage);
2732
2675
  }
2733
2676
  return result;
2734
2677
  },