opencode-antigravity-auth 1.2.1 → 1.2.3

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.
@@ -1,8 +1,15 @@
1
+ import type { HeaderStyle } from "../constants";
1
2
  export type ModelFamily = "claude" | "gemini";
3
+ export type { HeaderStyle };
2
4
  export interface RateLimitState {
3
5
  claude?: number;
4
6
  gemini?: number;
5
7
  }
8
+ export interface RateLimitStateV3 {
9
+ claude?: number;
10
+ "gemini-antigravity"?: number;
11
+ "gemini-cli"?: number;
12
+ }
6
13
  export interface AccountMetadataV1 {
7
14
  email?: string;
8
15
  refreshToken: string;
@@ -34,8 +41,28 @@ export interface AccountStorage {
34
41
  accounts: AccountMetadata[];
35
42
  activeIndex: number;
36
43
  }
44
+ export interface AccountMetadataV3 {
45
+ email?: string;
46
+ refreshToken: string;
47
+ projectId?: string;
48
+ managedProjectId?: string;
49
+ addedAt: number;
50
+ lastUsed: number;
51
+ lastSwitchReason?: "rate-limit" | "initial" | "rotation";
52
+ rateLimitResetTimes?: RateLimitStateV3;
53
+ }
54
+ export interface AccountStorageV3 {
55
+ version: 3;
56
+ accounts: AccountMetadataV3[];
57
+ activeIndex: number;
58
+ activeIndexByFamily?: {
59
+ claude?: number;
60
+ gemini?: number;
61
+ };
62
+ }
37
63
  export declare function getStoragePath(): string;
38
- export declare function loadAccounts(): Promise<AccountStorage | null>;
39
- export declare function saveAccounts(storage: AccountStorage): Promise<void>;
64
+ export declare function migrateV2ToV3(v2: AccountStorage): AccountStorageV3;
65
+ export declare function loadAccounts(): Promise<AccountStorageV3 | null>;
66
+ export declare function saveAccounts(storage: AccountStorageV3): Promise<void>;
40
67
  export declare function clearAccounts(): Promise<void>;
41
68
  //# sourceMappingURL=storage.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../../src/plugin/storage.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAE9C,MAAM,WAAW,cAAc;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,gBAAgB,CAAC,EAAE,YAAY,GAAG,SAAS,GAAG,UAAU,CAAC;CAC1D;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,CAAC,CAAC;IACX,QAAQ,EAAE,iBAAiB,EAAE,CAAC;IAC9B,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,CAAC,EAAE,YAAY,GAAG,SAAS,GAAG,UAAU,CAAC;IACzD,mBAAmB,CAAC,EAAE,cAAc,CAAC;CACtC;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,CAAC,CAAC;IACX,QAAQ,EAAE,eAAe,EAAE,CAAC;IAC5B,WAAW,EAAE,MAAM,CAAC;CACrB;AAcD,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AA0BD,wBAAsB,YAAY,IAAI,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAgDnE;AAED,wBAAsB,YAAY,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAMzE;AAED,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAUnD"}
1
+ {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../../src/plugin/storage.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAC9C,YAAY,EAAE,WAAW,EAAE,CAAC;AAE5B,MAAM,WAAW,cAAc;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,gBAAgB,CAAC,EAAE,YAAY,GAAG,SAAS,GAAG,UAAU,CAAC;CAC1D;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,CAAC,CAAC;IACX,QAAQ,EAAE,iBAAiB,EAAE,CAAC;IAC9B,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,CAAC,EAAE,YAAY,GAAG,SAAS,GAAG,UAAU,CAAC;IACzD,mBAAmB,CAAC,EAAE,cAAc,CAAC;CACtC;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,CAAC,CAAC;IACX,QAAQ,EAAE,eAAe,EAAE,CAAC;IAC5B,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,CAAC,EAAE,YAAY,GAAG,SAAS,GAAG,UAAU,CAAC;IACzD,mBAAmB,CAAC,EAAE,gBAAgB,CAAC;CACxC;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,CAAC,CAAC;IACX,QAAQ,EAAE,iBAAiB,EAAE,CAAC;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,mBAAmB,CAAC,EAAE;QACpB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;CACH;AAcD,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AA0BD,wBAAgB,aAAa,CAAC,EAAE,EAAE,cAAc,GAAG,gBAAgB,CAwBlE;AAED,wBAAsB,YAAY,IAAI,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CA0DrE;AAED,wBAAsB,YAAY,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAM3E;AAED,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAUnD"}
@@ -35,6 +35,31 @@ function migrateV1ToV2(v1) {
35
35
  activeIndex: v1.activeIndex,
36
36
  };
37
37
  }
38
+ export function migrateV2ToV3(v2) {
39
+ return {
40
+ version: 3,
41
+ accounts: v2.accounts.map((acc) => {
42
+ const rateLimitResetTimes = {};
43
+ if (acc.rateLimitResetTimes?.claude && acc.rateLimitResetTimes.claude > Date.now()) {
44
+ rateLimitResetTimes.claude = acc.rateLimitResetTimes.claude;
45
+ }
46
+ if (acc.rateLimitResetTimes?.gemini && acc.rateLimitResetTimes.gemini > Date.now()) {
47
+ rateLimitResetTimes["gemini-antigravity"] = acc.rateLimitResetTimes.gemini;
48
+ }
49
+ return {
50
+ email: acc.email,
51
+ refreshToken: acc.refreshToken,
52
+ projectId: acc.projectId,
53
+ managedProjectId: acc.managedProjectId,
54
+ addedAt: acc.addedAt,
55
+ lastUsed: acc.lastUsed,
56
+ lastSwitchReason: acc.lastSwitchReason,
57
+ rateLimitResetTimes: Object.keys(rateLimitResetTimes).length > 0 ? rateLimitResetTimes : undefined,
58
+ };
59
+ }),
60
+ activeIndex: v2.activeIndex,
61
+ };
62
+ }
38
63
  export async function loadAccounts() {
39
64
  try {
40
65
  const path = getStoragePath();
@@ -46,17 +71,29 @@ export async function loadAccounts() {
46
71
  }
47
72
  let storage;
48
73
  if (data.version === 1) {
49
- console.info("[opencode-antigravity-auth] Migrating account storage from v1 to v2");
50
- storage = migrateV1ToV2(data);
74
+ console.info("[opencode-antigravity-auth] Migrating account storage from v1 to v3");
75
+ const v2 = migrateV1ToV2(data);
76
+ storage = migrateV2ToV3(v2);
51
77
  try {
52
78
  await saveAccounts(storage);
53
- console.info("[opencode-antigravity-auth] Migration to v2 complete");
79
+ console.info("[opencode-antigravity-auth] Migration to v3 complete");
54
80
  }
55
81
  catch (saveError) {
56
82
  console.warn("[opencode-antigravity-auth] Failed to persist migrated storage:", saveError);
57
83
  }
58
84
  }
59
85
  else if (data.version === 2) {
86
+ console.info("[opencode-antigravity-auth] Migrating account storage from v2 to v3");
87
+ storage = migrateV2ToV3(data);
88
+ try {
89
+ await saveAccounts(storage);
90
+ console.info("[opencode-antigravity-auth] Migration to v3 complete");
91
+ }
92
+ catch (saveError) {
93
+ console.warn("[opencode-antigravity-auth] Failed to persist migrated storage:", saveError);
94
+ }
95
+ }
96
+ else if (data.version === 3) {
60
97
  storage = data;
61
98
  }
62
99
  else {
@@ -1 +1 @@
1
- {"version":3,"file":"storage.js","sourceRoot":"","sources":["../../../src/plugin/storage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AA8ClC,SAAS,YAAY;IACnB,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;IAClC,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;QACzB,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,SAAS,CAAC,EAAE,UAAU,CAAC,CAAC;IACxF,CAAC;IAED,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,CAAC,CAAC;IAC5E,OAAO,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;AACrC,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,OAAO,IAAI,CAAC,YAAY,EAAE,EAAE,2BAA2B,CAAC,CAAC;AAC3D,CAAC;AAED,SAAS,aAAa,CAAC,EAAoB;IACzC,OAAO;QACL,OAAO,EAAE,CAAC;QACV,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;YAChC,MAAM,mBAAmB,GAAmB,EAAE,CAAC;YAC/C,IAAI,GAAG,CAAC,aAAa,IAAI,GAAG,CAAC,kBAAkB,IAAI,GAAG,CAAC,kBAAkB,GAAG,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;gBACvF,mBAAmB,CAAC,MAAM,GAAG,GAAG,CAAC,kBAAkB,CAAC;gBACpD,mBAAmB,CAAC,MAAM,GAAG,GAAG,CAAC,kBAAkB,CAAC;YACtD,CAAC;YACD,OAAO;gBACL,KAAK,EAAE,GAAG,CAAC,KAAK;gBAChB,YAAY,EAAE,GAAG,CAAC,YAAY;gBAC9B,SAAS,EAAE,GAAG,CAAC,SAAS;gBACxB,gBAAgB,EAAE,GAAG,CAAC,gBAAgB;gBACtC,OAAO,EAAE,GAAG,CAAC,OAAO;gBACpB,QAAQ,EAAE,GAAG,CAAC,QAAQ;gBACtB,gBAAgB,EAAE,GAAG,CAAC,gBAAgB;gBACtC,mBAAmB,EAAE,MAAM,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,SAAS;aACnG,CAAC;QACJ,CAAC,CAAC;QACF,WAAW,EAAE,EAAE,CAAC,WAAW;KAC5B,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,cAAc,EAAE,CAAC;QAC9B,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACjD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAsB,CAAC;QAEtD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;YAClC,OAAO,CAAC,IAAI,CAAC,8DAA8D,CAAC,CAAC;YAC7E,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,OAAuB,CAAC;QAE5B,IAAI,IAAI,CAAC,OAAO,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO,CAAC,IAAI,CAAC,qEAAqE,CAAC,CAAC;YACpF,OAAO,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;YAC9B,IAAI,CAAC;gBACH,MAAM,YAAY,CAAC,OAAO,CAAC,CAAC;gBAC5B,OAAO,CAAC,IAAI,CAAC,sDAAsD,CAAC,CAAC;YACvE,CAAC;YAAC,OAAO,SAAS,EAAE,CAAC;gBACnB,OAAO,CAAC,IAAI,CAAC,iEAAiE,EAAE,SAAS,CAAC,CAAC;YAC7F,CAAC;QACH,CAAC;aAAM,IAAI,IAAI,CAAC,OAAO,KAAK,CAAC,EAAE,CAAC;YAC9B,OAAO,GAAG,IAAI,CAAC;QACjB,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,IAAI,CAAC,+DAA+D,EAAE;gBAC5E,OAAO,EAAG,IAA8B,CAAC,OAAO;aACjD,CAAC,CAAC;YACH,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,OAAO,OAAO,CAAC,WAAW,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,CAAC;YACtF,OAAO,CAAC,WAAW,GAAG,CAAC,CAAC;QAC1B,CAAC;QAED,IAAI,OAAO,CAAC,WAAW,GAAG,CAAC,IAAI,OAAO,CAAC,WAAW,IAAI,OAAO,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;YAC9E,OAAO,CAAC,WAAW,GAAG,CAAC,CAAC;QAC1B,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,GAAI,KAA+B,CAAC,IAAI,CAAC;QACnD,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;YACtB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,CAAC,KAAK,CAAC,6DAA6D,EAAE,KAAK,CAAC,CAAC;QACpF,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,OAAuB;IACxD,MAAM,IAAI,GAAG,cAAc,EAAE,CAAC;IAC9B,MAAM,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAEnD,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IACjD,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;AAC7C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,cAAc,EAAE,CAAC;QAC9B,MAAM,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,GAAI,KAA+B,CAAC,IAAI,CAAC;QACnD,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;YACtB,OAAO,CAAC,KAAK,CAAC,8DAA8D,EAAE,KAAK,CAAC,CAAC;QACvF,CAAC;IACH,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"storage.js","sourceRoot":"","sources":["../../../src/plugin/storage.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/plugin.ts"],"names":[],"mappings":"AA6BA,OAAO,KAAK,EAGV,aAAa,EACb,YAAY,EAGb,MAAM,gBAAgB,CAAC;AA+WxB;;GAEG;AACH,eAAO,MAAM,uBAAuB,GAAI,YAAY,MAAM,MACxD,uBAAuB,aAAa,KACnC,OAAO,CAAC,YAAY,CA63BtB,CAAC;AAEF,eAAO,MAAM,yBAAyB,0BAh4Bb,aAAa,KACnC,OAAO,CAAC,YAAY,CA+3BkE,CAAC;AAC1F,eAAO,MAAM,iBAAiB,0BAj4BL,aAAa,KACnC,OAAO,CAAC,YAAY,CAg4BmC,CAAC"}
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/plugin.ts"],"names":[],"mappings":"AA6BA,OAAO,KAAK,EAGV,aAAa,EACb,YAAY,EAGb,MAAM,gBAAgB,CAAC;AA8YxB;;GAEG;AACH,eAAO,MAAM,uBAAuB,GAAI,YAAY,MAAM,MACxD,uBAAuB,aAAa,KACnC,OAAO,CAAC,YAAY,CA47BtB,CAAC;AAEF,eAAO,MAAM,yBAAyB,0BA/7Bb,aAAa,KACnC,OAAO,CAAC,YAAY,CA87BkE,CAAC;AAC1F,eAAO,MAAM,iBAAiB,0BAh8BL,aAAa,KACnC,OAAO,CAAC,YAAY,CA+7BmC,CAAC"}
@@ -156,9 +156,13 @@ async function persistAccountPool(results, replaceAll = false) {
156
156
  ? 0
157
157
  : (typeof stored?.activeIndex === "number" && Number.isFinite(stored.activeIndex) ? stored.activeIndex : 0);
158
158
  await saveAccounts({
159
- version: 2,
159
+ version: 3,
160
160
  accounts,
161
161
  activeIndex: clampInt(activeIndex, 0, accounts.length - 1),
162
+ activeIndexByFamily: {
163
+ claude: clampInt(activeIndex, 0, accounts.length - 1),
164
+ gemini: clampInt(activeIndex, 0, accounts.length - 1),
165
+ },
162
166
  });
163
167
  }
164
168
  function retryAfterMsFromResponse(response) {
@@ -302,6 +306,26 @@ function getRateLimitBackoff(accountIndex, serverRetryAfterMs) {
302
306
  function resetRateLimitState(accountIndex) {
303
307
  rateLimitStateByAccount.delete(accountIndex);
304
308
  }
309
+ // Track consecutive non-429 failures per account to prevent infinite loops
310
+ const accountFailureState = new Map();
311
+ const MAX_CONSECUTIVE_FAILURES = 5;
312
+ const FAILURE_COOLDOWN_MS = 30_000; // 30 seconds cooldown after max failures
313
+ const FAILURE_STATE_RESET_MS = 120_000; // Reset failure count after 2 minutes of no failures
314
+ function trackAccountFailure(accountIndex) {
315
+ const now = Date.now();
316
+ const previous = accountFailureState.get(accountIndex);
317
+ // Reset if last failure was more than 2 minutes ago
318
+ const failures = previous && (now - previous.lastFailureAt < FAILURE_STATE_RESET_MS)
319
+ ? previous.consecutiveFailures + 1
320
+ : 1;
321
+ accountFailureState.set(accountIndex, { consecutiveFailures: failures, lastFailureAt: now });
322
+ const shouldCooldown = failures >= MAX_CONSECUTIVE_FAILURES;
323
+ const cooldownMs = shouldCooldown ? FAILURE_COOLDOWN_MS : 0;
324
+ return { failures, shouldCooldown, cooldownMs };
325
+ }
326
+ function resetAccountFailureState(accountIndex) {
327
+ accountFailureState.delete(accountIndex);
328
+ }
305
329
  /**
306
330
  * Sleep for a given number of milliseconds, respecting an abort signal.
307
331
  */
@@ -500,9 +524,15 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
500
524
  try {
501
525
  const refreshed = await refreshAccessToken(authRecord, client, providerId);
502
526
  if (!refreshed) {
527
+ const { failures, shouldCooldown, cooldownMs } = trackAccountFailure(account.index);
503
528
  lastError = new Error("Antigravity token refresh failed");
529
+ if (shouldCooldown) {
530
+ accountManager.markRateLimited(account, cooldownMs, family, "antigravity");
531
+ pushDebug(`token-refresh-failed: cooldown ${cooldownMs}ms after ${failures} failures`);
532
+ }
504
533
  continue;
505
534
  }
535
+ resetAccountFailureState(account.index);
506
536
  accountManager.updateFromAuth(account, refreshed);
507
537
  authRecord = refreshed;
508
538
  try {
@@ -539,7 +569,12 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
539
569
  lastError = error;
540
570
  continue;
541
571
  }
572
+ const { failures, shouldCooldown, cooldownMs } = trackAccountFailure(account.index);
542
573
  lastError = error instanceof Error ? error : new Error(String(error));
574
+ if (shouldCooldown) {
575
+ accountManager.markRateLimited(account, cooldownMs, family, "antigravity");
576
+ pushDebug(`token-refresh-error: cooldown ${cooldownMs}ms after ${failures} failures`);
577
+ }
543
578
  continue;
544
579
  }
545
580
  }
@@ -551,9 +586,15 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
551
586
  let projectContext;
552
587
  try {
553
588
  projectContext = await ensureProjectContext(authRecord);
589
+ resetAccountFailureState(account.index);
554
590
  }
555
591
  catch (error) {
592
+ const { failures, shouldCooldown, cooldownMs } = trackAccountFailure(account.index);
556
593
  lastError = error instanceof Error ? error : new Error(String(error));
594
+ if (shouldCooldown) {
595
+ accountManager.markRateLimited(account, cooldownMs, family, "antigravity");
596
+ pushDebug(`project-context-error: cooldown ${cooldownMs}ms after ${failures} failures`);
597
+ }
557
598
  continue;
558
599
  }
559
600
  if (projectContext.auth !== authRecord) {
@@ -607,75 +648,152 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
607
648
  pushDebug(`thinking-warmup: failed ${error instanceof Error ? error.message : String(error)}`);
608
649
  }
609
650
  };
610
- // Try endpoint fallbacks
651
+ // Try endpoint fallbacks with header style fallback for Gemini
611
652
  let shouldSwitchAccount = false;
612
- for (let i = 0; i < ANTIGRAVITY_ENDPOINT_FALLBACKS.length; i++) {
613
- const currentEndpoint = ANTIGRAVITY_ENDPOINT_FALLBACKS[i];
614
- try {
615
- const prepared = prepareAntigravityRequest(input, init, accessToken, projectContext.effectiveProjectId, currentEndpoint);
616
- const originalUrl = toUrlString(input);
617
- const resolvedUrl = toUrlString(prepared.request);
618
- pushDebug(`endpoint=${currentEndpoint}`);
619
- pushDebug(`resolved=${resolvedUrl}`);
620
- const debugContext = startAntigravityDebugRequest({
621
- originalUrl,
622
- resolvedUrl,
623
- method: prepared.init.method,
624
- headers: prepared.init.headers,
625
- body: prepared.init.body,
626
- streaming: prepared.streaming,
627
- projectId: projectContext.effectiveProjectId,
628
- });
629
- await runThinkingWarmup(prepared, projectContext.effectiveProjectId);
630
- const response = await fetch(prepared.request, prepared.init);
631
- pushDebug(`status=${response.status} ${response.statusText}`);
632
- // Handle 429 rate limit with improved logic
633
- if (response.status === 429) {
634
- const headerRetryMs = retryAfterMsFromResponse(response);
635
- const bodyInfo = await extractRetryInfoFromBody(response);
636
- const serverRetryMs = bodyInfo.retryDelayMs ?? headerRetryMs;
637
- const { attempt, delayMs } = getRateLimitBackoff(account.index, serverRetryMs);
638
- const waitTimeFormatted = formatWaitTime(delayMs);
639
- const isCapacityExhausted = bodyInfo.reason === "MODEL_CAPACITY_EXHAUSTED" ||
640
- (typeof bodyInfo.message === "string" && bodyInfo.message.toLowerCase().includes("no capacity"));
641
- pushDebug(`429 idx=${account.index} email=${account.email ?? ""} family=${family} delayMs=${delayMs} attempt=${attempt}`);
642
- if (bodyInfo.message) {
643
- pushDebug(`429 message=${bodyInfo.message}`);
644
- }
645
- if (bodyInfo.quotaResetTime) {
646
- pushDebug(`429 quotaResetTime=${bodyInfo.quotaResetTime}`);
647
- }
648
- if (bodyInfo.reason) {
649
- pushDebug(`429 reason=${bodyInfo.reason}`);
650
- }
651
- logRateLimitEvent(account.index, account.email, family, response.status, delayMs, bodyInfo);
652
- await logResponseBody(debugContext, response, 429);
653
- if (isCapacityExhausted) {
654
- accountManager.markRateLimited(account, delayMs, family);
655
- await showToast(`Model capacity exhausted for ${family}. Retrying in ${waitTimeFormatted} (attempt ${attempt})...`, "warning");
656
- await sleep(delayMs, abortSignal);
657
- continue;
658
- }
659
- const accountLabel = account.email || `Account ${account.index + 1}`;
660
- // Short retry: if delay is small, just wait and retry same account
661
- if (delayMs <= SHORT_RETRY_THRESHOLD_MS) {
662
- await showToast(`Rate limited. Retrying in ${waitTimeFormatted} (attempt ${attempt})...`, "warning");
663
- await sleep(delayMs, abortSignal);
664
- continue;
665
- }
666
- // Mark account as rate-limited for this family
667
- accountManager.markRateLimited(account, delayMs, family);
668
- try {
669
- await accountManager.saveToDisk();
653
+ // For Gemini models, we can try both header styles (antigravity first, then gemini-cli)
654
+ // For Claude models, only antigravity headers work
655
+ const headerStyles = family === "gemini"
656
+ ? ["antigravity", "gemini-cli"]
657
+ : ["antigravity"];
658
+ let currentHeaderStyleIndex = 0;
659
+ // Find first non-rate-limited header style for this account
660
+ while (currentHeaderStyleIndex < headerStyles.length) {
661
+ const hs = headerStyles[currentHeaderStyleIndex];
662
+ if (hs && !accountManager.isRateLimitedForHeaderStyle(account, family, hs)) {
663
+ break;
664
+ }
665
+ currentHeaderStyleIndex++;
666
+ }
667
+ // If all header styles are rate-limited for this account, switch account
668
+ if (currentHeaderStyleIndex >= headerStyles.length) {
669
+ shouldSwitchAccount = true;
670
+ }
671
+ headerStyleLoop: while (!shouldSwitchAccount && currentHeaderStyleIndex < headerStyles.length) {
672
+ const currentHeaderStyle = headerStyles[currentHeaderStyleIndex];
673
+ pushDebug(`headerStyle=${currentHeaderStyle}`);
674
+ for (let i = 0; i < ANTIGRAVITY_ENDPOINT_FALLBACKS.length; i++) {
675
+ const currentEndpoint = ANTIGRAVITY_ENDPOINT_FALLBACKS[i];
676
+ try {
677
+ const prepared = prepareAntigravityRequest(input, init, accessToken, projectContext.effectiveProjectId, currentEndpoint, currentHeaderStyle);
678
+ const originalUrl = toUrlString(input);
679
+ const resolvedUrl = toUrlString(prepared.request);
680
+ pushDebug(`endpoint=${currentEndpoint}`);
681
+ pushDebug(`resolved=${resolvedUrl}`);
682
+ const debugContext = startAntigravityDebugRequest({
683
+ originalUrl,
684
+ resolvedUrl,
685
+ method: prepared.init.method,
686
+ headers: prepared.init.headers,
687
+ body: prepared.init.body,
688
+ streaming: prepared.streaming,
689
+ projectId: projectContext.effectiveProjectId,
690
+ });
691
+ await runThinkingWarmup(prepared, projectContext.effectiveProjectId);
692
+ const response = await fetch(prepared.request, prepared.init);
693
+ pushDebug(`status=${response.status} ${response.statusText}`);
694
+ // Handle 429 rate limit with improved logic
695
+ if (response.status === 429) {
696
+ const headerRetryMs = retryAfterMsFromResponse(response);
697
+ const bodyInfo = await extractRetryInfoFromBody(response);
698
+ const serverRetryMs = bodyInfo.retryDelayMs ?? headerRetryMs;
699
+ const { attempt, delayMs } = getRateLimitBackoff(account.index, serverRetryMs);
700
+ const waitTimeFormatted = formatWaitTime(delayMs);
701
+ const isCapacityExhausted = bodyInfo.reason === "MODEL_CAPACITY_EXHAUSTED" ||
702
+ (typeof bodyInfo.message === "string" && bodyInfo.message.toLowerCase().includes("no capacity"));
703
+ pushDebug(`429 idx=${account.index} email=${account.email ?? ""} family=${family} delayMs=${delayMs} attempt=${attempt}`);
704
+ if (bodyInfo.message) {
705
+ pushDebug(`429 message=${bodyInfo.message}`);
706
+ }
707
+ if (bodyInfo.quotaResetTime) {
708
+ pushDebug(`429 quotaResetTime=${bodyInfo.quotaResetTime}`);
709
+ }
710
+ if (bodyInfo.reason) {
711
+ pushDebug(`429 reason=${bodyInfo.reason}`);
712
+ }
713
+ logRateLimitEvent(account.index, account.email, family, response.status, delayMs, bodyInfo);
714
+ await logResponseBody(debugContext, response, 429);
715
+ if (isCapacityExhausted) {
716
+ accountManager.markRateLimited(account, delayMs, family, currentHeaderStyle);
717
+ await showToast(`Model capacity exhausted for ${family}. Retrying in ${waitTimeFormatted} (attempt ${attempt})...`, "warning");
718
+ await sleep(delayMs, abortSignal);
719
+ continue;
720
+ }
721
+ const accountLabel = account.email || `Account ${account.index + 1}`;
722
+ // Short retry: if delay is small, just wait and retry same account
723
+ if (delayMs <= SHORT_RETRY_THRESHOLD_MS) {
724
+ await showToast(`Rate limited. Retrying in ${waitTimeFormatted} (attempt ${attempt})...`, "warning");
725
+ await sleep(delayMs, abortSignal);
726
+ continue;
727
+ }
728
+ // Mark this header style as rate-limited for this account
729
+ accountManager.markRateLimited(account, delayMs, family, currentHeaderStyle);
730
+ try {
731
+ await accountManager.saveToDisk();
732
+ }
733
+ catch (error) {
734
+ console.error("[opencode-antigravity-auth] Failed to persist rate-limit state:", error);
735
+ }
736
+ // For Gemini, try next header style before switching accounts
737
+ if (family === "gemini" && currentHeaderStyleIndex < headerStyles.length - 1) {
738
+ const nextHeaderStyle = headerStyles[currentHeaderStyleIndex + 1];
739
+ await showToast(`Rate limited on ${currentHeaderStyle} quota. Trying ${nextHeaderStyle} quota...`, "warning");
740
+ currentHeaderStyleIndex++;
741
+ continue headerStyleLoop;
742
+ }
743
+ if (accountCount > 1) {
744
+ const quotaMsg = bodyInfo.quotaResetTime
745
+ ? ` (quota resets ${bodyInfo.quotaResetTime})`
746
+ : ` (retry in ${waitTimeFormatted})`;
747
+ await showToast(`Rate limited on ${accountLabel}${quotaMsg}. Switching...`, "warning");
748
+ lastFailure = {
749
+ response,
750
+ streaming: prepared.streaming,
751
+ debugContext,
752
+ requestedModel: prepared.requestedModel,
753
+ projectId: prepared.projectId,
754
+ endpoint: prepared.endpoint,
755
+ effectiveModel: prepared.effectiveModel,
756
+ sessionId: prepared.sessionId,
757
+ toolDebugMissing: prepared.toolDebugMissing,
758
+ toolDebugSummary: prepared.toolDebugSummary,
759
+ toolDebugPayload: prepared.toolDebugPayload,
760
+ };
761
+ shouldSwitchAccount = true;
762
+ break;
763
+ }
764
+ else {
765
+ const quotaMsg = bodyInfo.quotaResetTime
766
+ ? `Quota resets ${bodyInfo.quotaResetTime}`
767
+ : `Waiting ${waitTimeFormatted}`;
768
+ await showToast(`Rate limited. ${quotaMsg} (attempt ${attempt})...`, "warning");
769
+ lastFailure = {
770
+ response,
771
+ streaming: prepared.streaming,
772
+ debugContext,
773
+ requestedModel: prepared.requestedModel,
774
+ projectId: prepared.projectId,
775
+ endpoint: prepared.endpoint,
776
+ effectiveModel: prepared.effectiveModel,
777
+ sessionId: prepared.sessionId,
778
+ toolDebugMissing: prepared.toolDebugMissing,
779
+ toolDebugSummary: prepared.toolDebugSummary,
780
+ toolDebugPayload: prepared.toolDebugPayload,
781
+ };
782
+ await sleep(delayMs, abortSignal);
783
+ shouldSwitchAccount = true;
784
+ break;
785
+ }
670
786
  }
671
- catch (error) {
672
- console.error("[opencode-antigravity-auth] Failed to persist rate-limit state:", error);
787
+ // Success - reset rate limit backoff state
788
+ resetRateLimitState(account.index);
789
+ resetAccountFailureState(account.index);
790
+ const shouldRetryEndpoint = (response.status === 403 ||
791
+ response.status === 404 ||
792
+ response.status >= 500);
793
+ if (shouldRetryEndpoint) {
794
+ await logResponseBody(debugContext, response, response.status);
673
795
  }
674
- if (accountCount > 1) {
675
- const quotaMsg = bodyInfo.quotaResetTime
676
- ? ` (quota resets ${bodyInfo.quotaResetTime})`
677
- : ` (retry in ${waitTimeFormatted})`;
678
- await showToast(`Rate limited on ${accountLabel}${quotaMsg}. Switching...`, "warning");
796
+ if (shouldRetryEndpoint && i < ANTIGRAVITY_ENDPOINT_FALLBACKS.length - 1) {
679
797
  lastFailure = {
680
798
  response,
681
799
  streaming: prepared.streaming,
@@ -689,76 +807,34 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
689
807
  toolDebugSummary: prepared.toolDebugSummary,
690
808
  toolDebugPayload: prepared.toolDebugPayload,
691
809
  };
692
- shouldSwitchAccount = true;
693
- break;
810
+ continue;
694
811
  }
695
- else {
696
- const quotaMsg = bodyInfo.quotaResetTime
697
- ? `Quota resets ${bodyInfo.quotaResetTime}`
698
- : `Waiting ${waitTimeFormatted}`;
699
- await showToast(`Rate limited. ${quotaMsg} (attempt ${attempt})...`, "warning");
700
- lastFailure = {
701
- response,
702
- streaming: prepared.streaming,
703
- debugContext,
704
- requestedModel: prepared.requestedModel,
705
- projectId: prepared.projectId,
706
- endpoint: prepared.endpoint,
707
- effectiveModel: prepared.effectiveModel,
708
- sessionId: prepared.sessionId,
709
- toolDebugMissing: prepared.toolDebugMissing,
710
- toolDebugSummary: prepared.toolDebugSummary,
711
- toolDebugPayload: prepared.toolDebugPayload,
712
- };
713
- await sleep(delayMs, abortSignal);
714
- shouldSwitchAccount = true;
715
- break;
812
+ // Success or non-retryable error - return the response
813
+ logAntigravityDebugResponse(debugContext, response, {
814
+ note: response.ok ? "Success" : `Error ${response.status}`,
815
+ });
816
+ if (!response.ok) {
817
+ await logResponseBody(debugContext, response, response.status);
716
818
  }
819
+ return transformAntigravityResponse(response, prepared.streaming, debugContext, prepared.requestedModel, prepared.projectId, prepared.endpoint, prepared.effectiveModel, prepared.sessionId, prepared.toolDebugMissing, prepared.toolDebugSummary, prepared.toolDebugPayload, debugLines);
717
820
  }
718
- // Success - reset rate limit backoff state
719
- resetRateLimitState(account.index);
720
- const shouldRetryEndpoint = (response.status === 403 ||
721
- response.status === 404 ||
722
- response.status >= 500);
723
- if (shouldRetryEndpoint) {
724
- await logResponseBody(debugContext, response, response.status);
725
- }
726
- if (shouldRetryEndpoint && i < ANTIGRAVITY_ENDPOINT_FALLBACKS.length - 1) {
727
- lastFailure = {
728
- response,
729
- streaming: prepared.streaming,
730
- debugContext,
731
- requestedModel: prepared.requestedModel,
732
- projectId: prepared.projectId,
733
- endpoint: prepared.endpoint,
734
- effectiveModel: prepared.effectiveModel,
735
- sessionId: prepared.sessionId,
736
- toolDebugMissing: prepared.toolDebugMissing,
737
- toolDebugSummary: prepared.toolDebugSummary,
738
- toolDebugPayload: prepared.toolDebugPayload,
739
- };
740
- continue;
741
- }
742
- // Success or non-retryable error - return the response
743
- logAntigravityDebugResponse(debugContext, response, {
744
- note: response.ok ? "Success" : `Error ${response.status}`,
745
- });
746
- if (!response.ok) {
747
- await logResponseBody(debugContext, response, response.status);
748
- }
749
- return transformAntigravityResponse(response, prepared.streaming, debugContext, prepared.requestedModel, prepared.projectId, prepared.endpoint, prepared.effectiveModel, prepared.sessionId, prepared.toolDebugMissing, prepared.toolDebugSummary, prepared.toolDebugPayload, debugLines);
750
- }
751
- catch (error) {
752
- if (i < ANTIGRAVITY_ENDPOINT_FALLBACKS.length - 1) {
821
+ catch (error) {
822
+ if (i < ANTIGRAVITY_ENDPOINT_FALLBACKS.length - 1) {
823
+ lastError = error instanceof Error ? error : new Error(String(error));
824
+ continue;
825
+ }
826
+ // All endpoints failed for this account - track failure and try next account
827
+ const { failures, shouldCooldown, cooldownMs } = trackAccountFailure(account.index);
753
828
  lastError = error instanceof Error ? error : new Error(String(error));
754
- continue;
829
+ if (shouldCooldown) {
830
+ accountManager.markRateLimited(account, cooldownMs, family, currentHeaderStyle);
831
+ pushDebug(`endpoint-error: cooldown ${cooldownMs}ms after ${failures} failures`);
832
+ }
833
+ shouldSwitchAccount = true;
834
+ break;
755
835
  }
756
- // All endpoints failed for this account - try next account
757
- lastError = error instanceof Error ? error : new Error(String(error));
758
- shouldSwitchAccount = true;
759
- break;
760
836
  }
761
- }
837
+ } // end headerStyleLoop
762
838
  if (shouldSwitchAccount) {
763
839
  continue;
764
840
  }