@cortexkit/opencode-antigravity-auth 1.1.0 → 2.0.1

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 (379) hide show
  1. package/README.md +225 -569
  2. package/dist/cli.js +4017 -0
  3. package/dist/cli.js.map +7 -0
  4. package/dist/index.d.ts +1 -3
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +20742 -14586
  7. package/dist/index.js.map +4 -4
  8. package/dist/src/antigravity/oauth.d.ts +1 -1
  9. package/dist/src/antigravity/oauth.js +1 -1
  10. package/dist/src/cli.d.ts +21 -0
  11. package/dist/src/cli.d.ts.map +1 -0
  12. package/dist/src/cli.js +237 -0
  13. package/dist/src/cli.js.map +1 -0
  14. package/dist/src/constants.d.ts +1 -1
  15. package/dist/src/constants.js +1 -1
  16. package/dist/src/hooks/auto-update-checker/cache.d.ts.map +1 -1
  17. package/dist/src/hooks/auto-update-checker/cache.js +13 -13
  18. package/dist/src/hooks/auto-update-checker/cache.js.map +1 -1
  19. package/dist/src/hooks/auto-update-checker/checker.d.ts +1 -1
  20. package/dist/src/hooks/auto-update-checker/checker.d.ts.map +1 -1
  21. package/dist/src/hooks/auto-update-checker/checker.js +75 -51
  22. package/dist/src/hooks/auto-update-checker/checker.js.map +1 -1
  23. package/dist/src/hooks/auto-update-checker/constants.d.ts.map +1 -1
  24. package/dist/src/hooks/auto-update-checker/constants.js +12 -12
  25. package/dist/src/hooks/auto-update-checker/constants.js.map +1 -1
  26. package/dist/src/hooks/auto-update-checker/index.d.ts +6 -6
  27. package/dist/src/hooks/auto-update-checker/index.d.ts.map +1 -1
  28. package/dist/src/hooks/auto-update-checker/index.js +17 -17
  29. package/dist/src/hooks/auto-update-checker/index.js.map +1 -1
  30. package/dist/src/hooks/auto-update-checker/logging.js +2 -2
  31. package/dist/src/hooks/auto-update-checker/logging.js.map +1 -1
  32. package/dist/src/hooks/auto-update-checker/types.d.ts.map +1 -1
  33. package/dist/src/plugin/account-access.d.ts +99 -0
  34. package/dist/src/plugin/account-access.d.ts.map +1 -0
  35. package/dist/src/plugin/account-access.js +480 -0
  36. package/dist/src/plugin/account-access.js.map +1 -0
  37. package/dist/src/plugin/account-command-oauth.d.ts +34 -0
  38. package/dist/src/plugin/account-command-oauth.d.ts.map +1 -0
  39. package/dist/src/plugin/account-command-oauth.js +156 -0
  40. package/dist/src/plugin/account-command-oauth.js.map +1 -0
  41. package/dist/src/plugin/accounts.d.ts +7 -256
  42. package/dist/src/plugin/accounts.d.ts.map +1 -1
  43. package/dist/src/plugin/accounts.js +31 -1367
  44. package/dist/src/plugin/accounts.js.map +1 -1
  45. package/dist/src/plugin/agy-request-metadata.d.ts +1 -1
  46. package/dist/src/plugin/agy-request-metadata.js +1 -1
  47. package/dist/src/plugin/agy-transport.d.ts +1 -1
  48. package/dist/src/plugin/agy-transport.js +1 -1
  49. package/dist/src/plugin/auth-doctor.d.ts +6 -6
  50. package/dist/src/plugin/auth-doctor.d.ts.map +1 -1
  51. package/dist/src/plugin/auth-doctor.js +74 -66
  52. package/dist/src/plugin/auth-doctor.js.map +1 -1
  53. package/dist/src/plugin/auth-drift.d.ts +4 -4
  54. package/dist/src/plugin/auth-drift.d.ts.map +1 -1
  55. package/dist/src/plugin/auth-drift.js +15 -15
  56. package/dist/src/plugin/auth-drift.js.map +1 -1
  57. package/dist/src/plugin/auth-loader.d.ts +50 -0
  58. package/dist/src/plugin/auth-loader.d.ts.map +1 -0
  59. package/dist/src/plugin/auth-loader.js +225 -0
  60. package/dist/src/plugin/auth-loader.js.map +1 -0
  61. package/dist/src/plugin/auth.d.ts +1 -1
  62. package/dist/src/plugin/auth.js +1 -1
  63. package/dist/src/plugin/background-quota-refresh.d.ts +146 -0
  64. package/dist/src/plugin/background-quota-refresh.d.ts.map +1 -0
  65. package/dist/src/plugin/background-quota-refresh.js +347 -0
  66. package/dist/src/plugin/background-quota-refresh.js.map +1 -0
  67. package/dist/src/plugin/cache/index.d.ts +1 -1
  68. package/dist/src/plugin/cache/index.d.ts.map +1 -1
  69. package/dist/src/plugin/cache/index.js +1 -1
  70. package/dist/src/plugin/cache/index.js.map +1 -1
  71. package/dist/src/plugin/cache/signature-cache.d.ts +1 -1
  72. package/dist/src/plugin/cache/signature-cache.d.ts.map +1 -1
  73. package/dist/src/plugin/cache/signature-cache.js +23 -24
  74. package/dist/src/plugin/cache/signature-cache.js.map +1 -1
  75. package/dist/src/plugin/cache.d.ts +6 -5
  76. package/dist/src/plugin/cache.d.ts.map +1 -1
  77. package/dist/src/plugin/cache.js +21 -7
  78. package/dist/src/plugin/cache.js.map +1 -1
  79. package/dist/src/plugin/catalog.d.ts +23 -0
  80. package/dist/src/plugin/catalog.d.ts.map +1 -0
  81. package/dist/src/plugin/catalog.js +60 -0
  82. package/dist/src/plugin/catalog.js.map +1 -0
  83. package/dist/src/plugin/cli.d.ts +7 -7
  84. package/dist/src/plugin/cli.d.ts.map +1 -1
  85. package/dist/src/plugin/cli.js +62 -55
  86. package/dist/src/plugin/cli.js.map +1 -1
  87. package/dist/src/plugin/command-data.d.ts +329 -0
  88. package/dist/src/plugin/command-data.d.ts.map +1 -0
  89. package/dist/src/plugin/command-data.js +517 -0
  90. package/dist/src/plugin/command-data.js.map +1 -0
  91. package/dist/src/plugin/commands.d.ts +154 -0
  92. package/dist/src/plugin/commands.d.ts.map +1 -0
  93. package/dist/src/plugin/commands.js +746 -0
  94. package/dist/src/plugin/commands.js.map +1 -0
  95. package/dist/src/plugin/config/index.d.ts +2 -2
  96. package/dist/src/plugin/config/index.d.ts.map +1 -1
  97. package/dist/src/plugin/config/index.js +2 -2
  98. package/dist/src/plugin/config/index.js.map +1 -1
  99. package/dist/src/plugin/config/loader.d.ts +1 -1
  100. package/dist/src/plugin/config/loader.d.ts.map +1 -1
  101. package/dist/src/plugin/config/loader.js +18 -16
  102. package/dist/src/plugin/config/loader.js.map +1 -1
  103. package/dist/src/plugin/config/models.d.ts +2 -2
  104. package/dist/src/plugin/config/models.d.ts.map +1 -1
  105. package/dist/src/plugin/config/models.js +1 -1
  106. package/dist/src/plugin/config/models.js.map +1 -1
  107. package/dist/src/plugin/config/operator-settings-schema.d.ts +29 -0
  108. package/dist/src/plugin/config/operator-settings-schema.d.ts.map +1 -0
  109. package/dist/src/plugin/config/operator-settings-schema.js +28 -0
  110. package/dist/src/plugin/config/operator-settings-schema.js.map +1 -0
  111. package/dist/src/plugin/config/schema.d.ts +23 -2
  112. package/dist/src/plugin/config/schema.d.ts.map +1 -1
  113. package/dist/src/plugin/config/schema.js +109 -25
  114. package/dist/src/plugin/config/schema.js.map +1 -1
  115. package/dist/src/plugin/config/updater.d.ts.map +1 -1
  116. package/dist/src/plugin/config/updater.js +15 -15
  117. package/dist/src/plugin/config/updater.js.map +1 -1
  118. package/dist/src/plugin/config/writer.d.ts +34 -0
  119. package/dist/src/plugin/config/writer.d.ts.map +1 -0
  120. package/dist/src/plugin/config/writer.js +81 -0
  121. package/dist/src/plugin/config/writer.js.map +1 -0
  122. package/dist/src/plugin/core/streaming/index.d.ts +1 -1
  123. package/dist/src/plugin/core/streaming/index.d.ts.map +1 -1
  124. package/dist/src/plugin/core/streaming/index.js +1 -1
  125. package/dist/src/plugin/core/streaming/index.js.map +1 -1
  126. package/dist/src/plugin/core/streaming/transformer.d.ts.map +1 -1
  127. package/dist/src/plugin/core/streaming/transformer.js +85 -44
  128. package/dist/src/plugin/core/streaming/transformer.js.map +1 -1
  129. package/dist/src/plugin/core/streaming/types.d.ts.map +1 -1
  130. package/dist/src/plugin/debug.d.ts +10 -3
  131. package/dist/src/plugin/debug.d.ts.map +1 -1
  132. package/dist/src/plugin/debug.js +110 -47
  133. package/dist/src/plugin/debug.js.map +1 -1
  134. package/dist/src/plugin/dependencies.d.ts +129 -0
  135. package/dist/src/plugin/dependencies.d.ts.map +1 -0
  136. package/dist/src/plugin/dependencies.js +107 -0
  137. package/dist/src/plugin/dependencies.js.map +1 -0
  138. package/dist/src/plugin/errors.d.ts +27 -0
  139. package/dist/src/plugin/errors.d.ts.map +1 -1
  140. package/dist/src/plugin/errors.js +29 -3
  141. package/dist/src/plugin/errors.js.map +1 -1
  142. package/dist/src/plugin/event-handler.d.ts +53 -0
  143. package/dist/src/plugin/event-handler.d.ts.map +1 -0
  144. package/dist/src/plugin/event-handler.js +101 -0
  145. package/dist/src/plugin/event-handler.js.map +1 -0
  146. package/dist/src/plugin/fetch/retry-state.d.ts +61 -0
  147. package/dist/src/plugin/fetch/retry-state.d.ts.map +1 -0
  148. package/dist/src/plugin/fetch/retry-state.js +248 -0
  149. package/dist/src/plugin/fetch/retry-state.js.map +1 -0
  150. package/dist/src/plugin/fetch/warmup.d.ts +30 -0
  151. package/dist/src/plugin/fetch/warmup.d.ts.map +1 -0
  152. package/dist/src/plugin/fetch/warmup.js +76 -0
  153. package/dist/src/plugin/fetch/warmup.js.map +1 -0
  154. package/dist/src/plugin/fetch-interceptor.d.ts +59 -0
  155. package/dist/src/plugin/fetch-interceptor.d.ts.map +1 -0
  156. package/dist/src/plugin/fetch-interceptor.js +1399 -0
  157. package/dist/src/plugin/fetch-interceptor.js.map +1 -0
  158. package/dist/src/plugin/fetch-routing.d.ts +26 -0
  159. package/dist/src/plugin/fetch-routing.d.ts.map +1 -0
  160. package/dist/src/plugin/fetch-routing.js +99 -0
  161. package/dist/src/plugin/fetch-routing.js.map +1 -0
  162. package/dist/src/plugin/fingerprint.d.ts +1 -1
  163. package/dist/src/plugin/fingerprint.js +1 -1
  164. package/dist/src/plugin/gemini-dump.d.ts +5 -5
  165. package/dist/src/plugin/gemini-dump.d.ts.map +1 -1
  166. package/dist/src/plugin/gemini-dump.js +109 -55
  167. package/dist/src/plugin/gemini-dump.js.map +1 -1
  168. package/dist/src/plugin/google-search-tool.d.ts +9 -0
  169. package/dist/src/plugin/google-search-tool.d.ts.map +1 -0
  170. package/dist/src/plugin/google-search-tool.js +56 -0
  171. package/dist/src/plugin/google-search-tool.js.map +1 -0
  172. package/dist/src/plugin/image-saver.d.ts.map +1 -1
  173. package/dist/src/plugin/image-saver.js +16 -16
  174. package/dist/src/plugin/image-saver.js.map +1 -1
  175. package/dist/src/plugin/index.d.ts +30 -0
  176. package/dist/src/plugin/index.d.ts.map +1 -0
  177. package/dist/src/plugin/index.js +411 -0
  178. package/dist/src/plugin/index.js.map +1 -0
  179. package/dist/src/plugin/killswitch.d.ts +94 -0
  180. package/dist/src/plugin/killswitch.d.ts.map +1 -0
  181. package/dist/src/plugin/killswitch.js +197 -0
  182. package/dist/src/plugin/killswitch.js.map +1 -0
  183. package/dist/src/plugin/lifecycle.d.ts +40 -0
  184. package/dist/src/plugin/lifecycle.d.ts.map +1 -0
  185. package/dist/src/plugin/lifecycle.js +73 -0
  186. package/dist/src/plugin/lifecycle.js.map +1 -0
  187. package/dist/src/plugin/logger.d.ts +10 -1
  188. package/dist/src/plugin/logger.d.ts.map +1 -1
  189. package/dist/src/plugin/logger.js +38 -12
  190. package/dist/src/plugin/logger.js.map +1 -1
  191. package/dist/src/plugin/logging-utils.d.ts +35 -1
  192. package/dist/src/plugin/logging-utils.d.ts.map +1 -1
  193. package/dist/src/plugin/logging-utils.js +98 -15
  194. package/dist/src/plugin/logging-utils.js.map +1 -1
  195. package/dist/src/plugin/model-registry.d.ts +1 -1
  196. package/dist/src/plugin/model-registry.js +1 -1
  197. package/dist/src/plugin/oauth-login.d.ts +22 -0
  198. package/dist/src/plugin/oauth-login.d.ts.map +1 -0
  199. package/dist/src/plugin/oauth-login.js +37 -0
  200. package/dist/src/plugin/oauth-login.js.map +1 -0
  201. package/dist/src/plugin/oauth-methods.d.ts +42 -0
  202. package/dist/src/plugin/oauth-methods.d.ts.map +1 -0
  203. package/dist/src/plugin/oauth-methods.js +1276 -0
  204. package/dist/src/plugin/oauth-methods.js.map +1 -0
  205. package/dist/src/plugin/operator-settings.d.ts +40 -0
  206. package/dist/src/plugin/operator-settings.d.ts.map +1 -0
  207. package/dist/src/plugin/operator-settings.js +148 -0
  208. package/dist/src/plugin/operator-settings.js.map +1 -0
  209. package/dist/src/plugin/persist-account-pool.d.ts +37 -0
  210. package/dist/src/plugin/persist-account-pool.d.ts.map +1 -0
  211. package/dist/src/plugin/persist-account-pool.js +142 -0
  212. package/dist/src/plugin/persist-account-pool.js.map +1 -0
  213. package/dist/src/plugin/project.d.ts +1 -1
  214. package/dist/src/plugin/project.js +1 -1
  215. package/dist/src/plugin/prompt-context.d.ts.map +1 -1
  216. package/dist/src/plugin/prompt-context.js +11 -11
  217. package/dist/src/plugin/prompt-context.js.map +1 -1
  218. package/dist/src/plugin/quota.d.ts +138 -41
  219. package/dist/src/plugin/quota.d.ts.map +1 -1
  220. package/dist/src/plugin/quota.js +417 -285
  221. package/dist/src/plugin/quota.js.map +1 -1
  222. package/dist/src/plugin/recovery/constants.d.ts.map +1 -1
  223. package/dist/src/plugin/recovery/constants.js +24 -15
  224. package/dist/src/plugin/recovery/constants.js.map +1 -1
  225. package/dist/src/plugin/recovery/index.d.ts +3 -3
  226. package/dist/src/plugin/recovery/index.d.ts.map +1 -1
  227. package/dist/src/plugin/recovery/index.js +3 -3
  228. package/dist/src/plugin/recovery/index.js.map +1 -1
  229. package/dist/src/plugin/recovery/storage.d.ts +1 -1
  230. package/dist/src/plugin/recovery/storage.d.ts.map +1 -1
  231. package/dist/src/plugin/recovery/storage.js +31 -39
  232. package/dist/src/plugin/recovery/storage.js.map +1 -1
  233. package/dist/src/plugin/recovery/types.d.ts +12 -12
  234. package/dist/src/plugin/recovery/types.d.ts.map +1 -1
  235. package/dist/src/plugin/recovery.d.ts +3 -3
  236. package/dist/src/plugin/recovery.d.ts.map +1 -1
  237. package/dist/src/plugin/recovery.js +62 -58
  238. package/dist/src/plugin/recovery.js.map +1 -1
  239. package/dist/src/plugin/refresh-queue.d.ts +5 -2
  240. package/dist/src/plugin/refresh-queue.d.ts.map +1 -1
  241. package/dist/src/plugin/refresh-queue.js +37 -15
  242. package/dist/src/plugin/refresh-queue.js.map +1 -1
  243. package/dist/src/plugin/request-helpers.d.ts +1 -1
  244. package/dist/src/plugin/request-helpers.d.ts.map +1 -1
  245. package/dist/src/plugin/request-helpers.js +451 -352
  246. package/dist/src/plugin/request-helpers.js.map +1 -1
  247. package/dist/src/plugin/request.d.ts +7 -7
  248. package/dist/src/plugin/request.d.ts.map +1 -1
  249. package/dist/src/plugin/request.js +622 -384
  250. package/dist/src/plugin/request.js.map +1 -1
  251. package/dist/src/plugin/rotation.d.ts +1 -168
  252. package/dist/src/plugin/rotation.d.ts.map +1 -1
  253. package/dist/src/plugin/rotation.js +1 -327
  254. package/dist/src/plugin/rotation.js.map +1 -1
  255. package/dist/src/plugin/search.d.ts.map +1 -1
  256. package/dist/src/plugin/search.js +39 -35
  257. package/dist/src/plugin/search.js.map +1 -1
  258. package/dist/src/plugin/server.d.ts +1 -1
  259. package/dist/src/plugin/server.d.ts.map +1 -1
  260. package/dist/src/plugin/server.js +42 -37
  261. package/dist/src/plugin/server.js.map +1 -1
  262. package/dist/src/plugin/session-context.d.ts +2 -1
  263. package/dist/src/plugin/session-context.d.ts.map +1 -1
  264. package/dist/src/plugin/session-context.js +11 -7
  265. package/dist/src/plugin/session-context.js.map +1 -1
  266. package/dist/src/plugin/storage.d.ts +59 -120
  267. package/dist/src/plugin/storage.d.ts.map +1 -1
  268. package/dist/src/plugin/storage.js +140 -485
  269. package/dist/src/plugin/storage.js.map +1 -1
  270. package/dist/src/plugin/stores/signature-store.d.ts.map +1 -1
  271. package/dist/src/plugin/stores/signature-store.js.map +1 -1
  272. package/dist/src/plugin/thinking-recovery.d.ts.map +1 -1
  273. package/dist/src/plugin/thinking-recovery.js +35 -33
  274. package/dist/src/plugin/thinking-recovery.js.map +1 -1
  275. package/dist/src/plugin/token.d.ts +2 -2
  276. package/dist/src/plugin/token.d.ts.map +1 -1
  277. package/dist/src/plugin/token.js +30 -21
  278. package/dist/src/plugin/token.js.map +1 -1
  279. package/dist/src/plugin/transform/cross-model-sanitizer.d.ts +1 -1
  280. package/dist/src/plugin/transform/cross-model-sanitizer.js +1 -1
  281. package/dist/src/plugin/transform/index.d.ts +1 -1
  282. package/dist/src/plugin/transform/index.js +1 -1
  283. package/dist/src/plugin/transform/model-resolver.d.ts +1 -1
  284. package/dist/src/plugin/transform/model-resolver.js +1 -1
  285. package/dist/src/plugin/transform/types.d.ts +1 -1
  286. package/dist/src/plugin/transform/types.js +1 -1
  287. package/dist/src/plugin/types.d.ts +25 -69
  288. package/dist/src/plugin/types.d.ts.map +1 -1
  289. package/dist/src/plugin/ui/ansi.d.ts.map +1 -1
  290. package/dist/src/plugin/ui/ansi.js.map +1 -1
  291. package/dist/src/plugin/ui/auth-menu.d.ts +1 -1
  292. package/dist/src/plugin/ui/auth-menu.d.ts.map +1 -1
  293. package/dist/src/plugin/ui/auth-menu.js +84 -35
  294. package/dist/src/plugin/ui/auth-menu.js.map +1 -1
  295. package/dist/src/plugin/ui/confirm.d.ts.map +1 -1
  296. package/dist/src/plugin/ui/confirm.js.map +1 -1
  297. package/dist/src/plugin/ui/model-status.d.ts +3 -3
  298. package/dist/src/plugin/ui/model-status.d.ts.map +1 -1
  299. package/dist/src/plugin/ui/model-status.js +3 -3
  300. package/dist/src/plugin/ui/model-status.js.map +1 -1
  301. package/dist/src/plugin/ui/quota-status.d.ts +4 -4
  302. package/dist/src/plugin/ui/quota-status.d.ts.map +1 -1
  303. package/dist/src/plugin/ui/quota-status.js +49 -49
  304. package/dist/src/plugin/ui/quota-status.js.map +1 -1
  305. package/dist/src/plugin/ui/select.d.ts.map +1 -1
  306. package/dist/src/plugin/ui/select.js +22 -12
  307. package/dist/src/plugin/ui/select.js.map +1 -1
  308. package/dist/src/plugin/version.d.ts +1 -1
  309. package/dist/src/plugin/version.js +1 -1
  310. package/dist/src/rpc/notifications.d.ts +6 -0
  311. package/dist/src/rpc/notifications.d.ts.map +1 -0
  312. package/dist/src/rpc/notifications.js +46 -0
  313. package/dist/src/rpc/notifications.js.map +1 -0
  314. package/dist/src/rpc/port-file.d.ts +13 -0
  315. package/dist/src/rpc/port-file.d.ts.map +1 -0
  316. package/dist/src/rpc/port-file.js +109 -0
  317. package/dist/src/rpc/port-file.js.map +1 -0
  318. package/dist/src/rpc/protocol.d.ts +22 -0
  319. package/dist/src/rpc/protocol.d.ts.map +1 -0
  320. package/dist/src/rpc/protocol.js +1 -0
  321. package/dist/src/rpc/protocol.js.map +1 -0
  322. package/dist/src/rpc/rpc-client.d.ts +10 -0
  323. package/dist/src/rpc/rpc-client.d.ts.map +1 -0
  324. package/dist/src/rpc/rpc-client.js +58 -0
  325. package/dist/src/rpc/rpc-client.js.map +1 -0
  326. package/dist/src/rpc/rpc-dir.d.ts +4 -0
  327. package/dist/src/rpc/rpc-dir.d.ts.map +1 -0
  328. package/dist/src/rpc/rpc-dir.js +19 -0
  329. package/dist/src/rpc/rpc-dir.js.map +1 -0
  330. package/dist/src/rpc/rpc-server.d.ts +13 -0
  331. package/dist/src/rpc/rpc-server.d.ts.map +1 -0
  332. package/dist/src/rpc/rpc-server.js +231 -0
  333. package/dist/src/rpc/rpc-server.js.map +1 -0
  334. package/dist/src/sidebar-state.d.ts +357 -0
  335. package/dist/src/sidebar-state.d.ts.map +1 -0
  336. package/dist/src/sidebar-state.js +680 -0
  337. package/dist/src/sidebar-state.js.map +1 -0
  338. package/dist/src/tui/command-dialogs.d.ts +61 -0
  339. package/dist/src/tui/command-dialogs.d.ts.map +1 -0
  340. package/dist/src/tui/command-dialogs.js +595 -0
  341. package/dist/src/tui/command-dialogs.js.map +1 -0
  342. package/dist/src/tui/file-logger.d.ts +41 -0
  343. package/dist/src/tui/file-logger.d.ts.map +1 -0
  344. package/dist/src/tui/file-logger.js +114 -0
  345. package/dist/src/tui/file-logger.js.map +1 -0
  346. package/dist/src/tui-preferences.d.ts +40 -0
  347. package/dist/src/tui-preferences.d.ts.map +1 -0
  348. package/dist/src/tui-preferences.js +328 -0
  349. package/dist/src/tui-preferences.js.map +1 -0
  350. package/dist/src/tui.d.ts +68 -0
  351. package/dist/src/tui.d.ts.map +1 -0
  352. package/dist/src/tui.js +697 -0
  353. package/dist/src/tui.js.map +1 -0
  354. package/package.json +46 -22
  355. package/src/plugin/command-data.ts +931 -0
  356. package/src/rpc/port-file.ts +143 -0
  357. package/src/rpc/protocol.ts +31 -0
  358. package/src/rpc/rpc-client.ts +102 -0
  359. package/src/rpc/rpc-dir.ts +24 -0
  360. package/src/sidebar-state.ts +991 -0
  361. package/src/tui/command-dialogs.tsx +832 -0
  362. package/src/tui/entry.mjs +74 -0
  363. package/src/tui/file-logger.ts +145 -0
  364. package/src/tui-compiled/plugin/command-data.ts +931 -0
  365. package/src/tui-compiled/rpc/port-file.ts +143 -0
  366. package/src/tui-compiled/rpc/protocol.ts +31 -0
  367. package/src/tui-compiled/rpc/rpc-client.ts +102 -0
  368. package/src/tui-compiled/rpc/rpc-dir.ts +24 -0
  369. package/src/tui-compiled/sidebar-state.ts +991 -0
  370. package/src/tui-compiled/tui/command-dialogs.tsx +779 -0
  371. package/src/tui-compiled/tui/file-logger.ts +145 -0
  372. package/src/tui-compiled/tui-preferences.ts +416 -0
  373. package/src/tui-compiled/tui.tsx +1193 -0
  374. package/src/tui-preferences.ts +416 -0
  375. package/src/tui.tsx +1171 -0
  376. package/dist/src/plugin.d.ts +0 -48
  377. package/dist/src/plugin.d.ts.map +0 -1
  378. package/dist/src/plugin.js +0 -3311
  379. package/dist/src/plugin.js.map +0 -1
@@ -1,251 +1,382 @@
1
- import { ANTIGRAVITY_ENDPOINT_FALLBACKS, ANTIGRAVITY_PROVIDER_ID, buildGeminiCliUserAgent, } from "../constants";
2
- import { fetchWithAgyCliTransport } from "./agy-transport";
3
- import { accessTokenExpired, formatRefreshParts, parseRefreshParts } from "./auth";
4
- import { buildAntigravityHarnessUserAgent } from "./fingerprint";
5
- import { logQuotaFetch, logQuotaStatus } from "./debug";
6
- import { ensureProjectContext } from "./project";
7
- import { getQuotaGroupForModel } from "./model-registry";
8
- import { refreshAccessToken } from "./token";
9
- import { getModelFamily } from "./transform/model-resolver";
10
- const FETCH_TIMEOUT_MS = 10000;
11
- function buildAuthFromAccount(account) {
1
+ /**
2
+ * OpenCode adapter for the harness-agnostic quota manager.
3
+ *
4
+ * Re-exports the core `QuotaManager` types and helpers so call sites in
5
+ * `plugin.ts` and other modules don't need to switch imports. Also wires up
6
+ * the host-specific fetch callback that handles:
7
+ * 1. Token refresh via the existing `refreshAccessToken` path.
8
+ * 2. Persisting rotated refresh tokens via `client.auth.set` (matching
9
+ * legacy behavior).
10
+ * 3. Resolving project context via `ensureProjectContext`.
11
+ *
12
+ * The legacy `checkAccountsQuota(accounts, client, providerId)` export is
13
+ * retained as a compatibility wrapper that creates a short-lived manager
14
+ * with `force: true` — manual quota screens must always refresh, even if
15
+ * the background manager has backed off.
16
+ */
17
+ import { aggregateGeminiCliQuota, aggregateQuota, aggregateQuotaSummary, createQuotaManager, defaultKeyOf, fetchAvailableModels, fetchGeminiCliQuota, fetchQuotaSummary, getHealthTracker, } from '@cortexkit/antigravity-auth-core';
18
+ import { ANTIGRAVITY_ENDPOINT_FALLBACKS, ANTIGRAVITY_PROVIDER_ID, buildGeminiCliUserAgent, } from '../constants';
19
+ import { buildSidebarMachineStateFromAccounts, isAccountCurrent, setSidebarMachineState, } from '../sidebar-state';
20
+ import { accessTokenExpired, formatRefreshParts, parseRefreshParts, } from './auth';
21
+ import { logQuotaFetch, logQuotaStatus } from './debug';
22
+ import { buildAntigravityHarnessUserAgent } from './fingerprint';
23
+ import { createLogger } from './logger';
24
+ import { ensureProjectContext, loadManagedProject } from './project';
25
+ import { refreshAccessToken } from './token';
26
+ // Re-export the public surface so existing imports from `./quota` keep working.
27
+ const log = createLogger('quota');
28
+ export { classifyQuotaGroup, createQuotaManager, defaultKeyOf, } from '@cortexkit/antigravity-auth-core';
29
+ /**
30
+ * Build an OpenCode-wired quota manager.
31
+ *
32
+ * The returned manager owns its cache, in-flight dedupe, and backoff state.
33
+ * Register its `dispose()` with `PluginLifecycle` so refreshes abort on plugin
34
+ * shutdown.
35
+ *
36
+ * The wrapper observes `refreshAccount` / `refreshAccounts` and pushes a
37
+ * redacted sidebar snapshot after every refresh (success or backoff) so
38
+ * the TUI's next poll renders the freshest cached quota. The snapshot is
39
+ * sourced from the live AccountManager view (`getAccountsForSidebar`) so
40
+ * it carries the just-updated percentages; before bootstrapping it is a
41
+ * no-op.
42
+ */
43
+ export function createOpenCodeQuotaManager(client, providerId = ANTIGRAVITY_PROVIDER_ID, options = {}) {
44
+ const fetchAccountQuota = makeFetchAccountQuota(client, providerId, options.fetchVia);
45
+ const manager = createQuotaManager({
46
+ fetchAccountQuota,
47
+ keyOf: options.keyOf ?? defaultKeyOf,
48
+ baseBackoffMs: options.baseBackoffMs,
49
+ maxBackoffMs: options.maxBackoffMs,
50
+ fetchTimeoutMs: options.fetchTimeoutMs,
51
+ });
52
+ const originalRefreshAccount = manager.refreshAccount;
53
+ const originalRefreshAccounts = manager.refreshAccounts;
54
+ const getAccountsForSidebar = options.getAccountsForSidebar;
55
+ const getActiveIndexByFamily = options.getActiveIndexByFamily;
56
+ let disposed = false;
57
+ const inFlight = new Set();
58
+ const pushAfterRefresh = async (account) => {
59
+ if (!getAccountsForSidebar)
60
+ return;
61
+ await pushSidebarQuotaSnapshot(getAccountsForSidebar, manager.getBackoffUntil(account), getActiveIndexByFamily).catch(() => {
62
+ // Sidebar persistence remains best-effort when lock contention
63
+ // outlives its retry budget.
64
+ });
65
+ };
66
+ const track = (operation) => {
67
+ inFlight.add(operation);
68
+ void operation.then(() => inFlight.delete(operation), () => inFlight.delete(operation));
69
+ return operation;
70
+ };
71
+ const dispose = async () => {
72
+ if (disposed)
73
+ return;
74
+ disposed = true;
75
+ await manager.dispose();
76
+ await Promise.allSettled(inFlight);
77
+ };
12
78
  return {
13
- type: "oauth",
14
- refresh: formatRefreshParts({
15
- refreshToken: account.refreshToken,
16
- projectId: account.projectId,
17
- managedProjectId: account.managedProjectId,
18
- }),
19
- access: undefined,
20
- expires: undefined,
79
+ ...manager,
80
+ async refreshAccount(account, refreshOptions) {
81
+ const shouldPush = !disposed;
82
+ return track((async () => {
83
+ const result = await originalRefreshAccount(account, refreshOptions);
84
+ if (shouldPush)
85
+ await pushAfterRefresh(account);
86
+ return result;
87
+ })());
88
+ },
89
+ async refreshAccounts(accounts, refreshOptions) {
90
+ const shouldPush = !disposed;
91
+ return track((async () => {
92
+ const results = await originalRefreshAccounts(accounts, refreshOptions);
93
+ // Push one snapshot per batch — the AccountManager's view is updated
94
+ // by the caller (oauth-methods / fetch-interceptor) BEFORE we read
95
+ // here, so a single post-batch snapshot captures the full diff.
96
+ const lastAccount = accounts[accounts.length - 1];
97
+ if (shouldPush && lastAccount)
98
+ await pushAfterRefresh(lastAccount);
99
+ return results;
100
+ })());
101
+ },
102
+ dispose,
21
103
  };
22
104
  }
23
- function normalizeRemainingFraction(value) {
24
- // If value is missing or invalid, treat as exhausted (0%)
25
- if (typeof value !== "number" || !Number.isFinite(value)) {
26
- return 0;
105
+ /**
106
+ * Compatibility wrapper used by code paths that want a one-shot check across
107
+ * the full account pool with no shared cache.
108
+ *
109
+ * Equivalent to spinning up a short-lived manager with `force: true` so
110
+ * manual quota dialogs always reflect the latest data even if the background
111
+ * manager has backed off.
112
+ */
113
+ export async function checkAccountsQuotaWith(accounts, fetchAccountQuota) {
114
+ const manager = createQuotaManager({
115
+ fetchAccountQuota,
116
+ keyOf: defaultKeyOf,
117
+ });
118
+ try {
119
+ return await manager.refreshAccounts(accounts, {
120
+ indexFor: (account) => accounts.indexOf(account),
121
+ force: true,
122
+ });
27
123
  }
28
- if (value < 0)
29
- return 0;
30
- if (value > 1)
31
- return 1;
32
- return value;
33
- }
34
- function parseResetTime(resetTime) {
35
- if (!resetTime)
36
- return null;
37
- const timestamp = Date.parse(resetTime);
38
- if (!Number.isFinite(timestamp)) {
39
- return null;
124
+ finally {
125
+ manager.dispose();
40
126
  }
41
- return timestamp;
42
127
  }
43
- export function classifyQuotaGroup(modelName, displayName) {
44
- const registryGroup = getQuotaGroupForModel(modelName);
45
- if (registryGroup) {
46
- return registryGroup;
128
+ export async function checkAccountsQuotaStandalone(accounts, options) {
129
+ if (!options.refresh) {
130
+ return accounts.map((account, index) => ({
131
+ index,
132
+ email: account.email,
133
+ status: account.enabled === false ? 'disabled' : 'ok',
134
+ disabled: account.enabled === false,
135
+ quota: {
136
+ groups: account.cachedQuota ?? {},
137
+ modelCount: Object.keys(account.cachedQuota ?? {}).length,
138
+ },
139
+ }));
47
140
  }
48
- const combined = `${modelName} ${displayName ?? ""}`.toLowerCase();
49
- if (combined.includes("claude")) {
50
- return "claude";
141
+ return checkAccountsQuotaWith(accounts, makeFetchAccountQuota(undefined, ANTIGRAVITY_PROVIDER_ID));
142
+ }
143
+ export async function checkAccountsQuota(accounts, client, providerId = ANTIGRAVITY_PROVIDER_ID) {
144
+ return checkAccountsQuotaWith(accounts, makeFetchAccountQuota(client, providerId));
145
+ }
146
+ /**
147
+ * Push a quota refresh into the sidebar. Called by every quota refresh
148
+ * call site (manual `/antigravity-quota`, the `check` menu action, and the
149
+ * background refresh in `fetch-interceptor`) AFTER the results have been
150
+ * folded back into the AccountManager's cached quota. The function reads
151
+ * the live account snapshot through `getAccounts` so the redacted entry
152
+ * carries the just-refreshed percentages — not the previous tick's stale
153
+ * numbers and not `undefined`.
154
+ *
155
+ * The mapping is deliberately tolerant: if `getAccounts` returns `null`
156
+ * (e.g. before the plugin has finished bootstrapping) the call is a no-op.
157
+ * On lock contention the error is logged-and-swallowed so a quota dialog
158
+ * never fails just because the sidebar file is busy.
159
+ */
160
+ export async function pushSidebarQuotaSnapshot(getAccounts, backoffUntil = 0, getActiveIndexByFamily) {
161
+ const accounts = getAccounts();
162
+ if (!accounts || accounts.length === 0)
163
+ return;
164
+ const activeByFamily = getActiveIndexByFamily?.() ?? null;
165
+ try {
166
+ await setSidebarMachineState(buildSidebarMachineStateFromAccounts(accounts.map((entry) => ({
167
+ index: entry.index,
168
+ label: entry.label,
169
+ enabled: entry.enabled,
170
+ current: activeByFamily
171
+ ? isAccountCurrent(entry.index, activeByFamily)
172
+ : false,
173
+ coolingDownUntil: entry.coolingDownUntil,
174
+ cachedQuota: entry.cachedQuota,
175
+ cachedQuotaAccountId: entry.cachedQuotaAccountId,
176
+ currentQuotaAccountId: entry.currentQuotaAccountId,
177
+ healthScore: getHealthTracker().getScore(entry.index),
178
+ tier: entry.tier,
179
+ })), {
180
+ checkedAt: Date.now(),
181
+ quotaBackoffUntil: backoffUntil > 0 ? backoffUntil : undefined,
182
+ }));
51
183
  }
52
- const isGemini3 = combined.includes("gemini-3") || combined.includes("gemini 3");
53
- if (!isGemini3) {
54
- return null;
184
+ catch (error) {
185
+ log.debug('sidebar-quota-write-failed', { error: String(error) });
55
186
  }
56
- const family = getModelFamily(modelName);
57
- return family === "gemini-flash" ? "gemini-flash" : "gemini-pro";
58
187
  }
59
- function aggregateQuota(models) {
60
- const groups = {};
61
- const perModel = [];
62
- if (!models) {
63
- return { groups, perModel, modelCount: 0 };
64
- }
65
- let totalCount = 0;
66
- for (const [modelName, entry] of Object.entries(models)) {
67
- const group = classifyQuotaGroup(modelName, entry.displayName ?? entry.modelName);
68
- const quotaInfo = entry.quotaInfo;
69
- const remainingFraction = quotaInfo
70
- ? normalizeRemainingFraction(quotaInfo.remainingFraction)
71
- : undefined;
72
- const resetTime = quotaInfo?.resetTime;
73
- const resetTimestamp = parseResetTime(resetTime);
74
- totalCount += 1;
75
- // Always preserve per-model data regardless of group classification
76
- perModel.push({
77
- modelId: modelName,
78
- displayName: entry.displayName ?? entry.modelName,
79
- group,
80
- remainingFraction: remainingFraction ?? 0,
81
- resetTime,
188
+ /**
189
+ * Legacy fallback: fetchAvailableModels → aggregateQuota. Used when
190
+ * `fetchQuotaSummary` rejects (network, 403, etc.). Extracted so the
191
+ * concurrent fetch path can reuse the same fallback logic without
192
+ * duplicating the catch chain.
193
+ */
194
+ async function fetchLegacyModelsFallback(options) {
195
+ try {
196
+ const modelsResponse = await fetchAvailableModels({
197
+ accessToken: options.accessToken,
198
+ projectId: options.projectId,
199
+ endpoints: ANTIGRAVITY_ENDPOINT_FALLBACKS,
200
+ userAgent: buildAntigravityHarnessUserAgent(),
201
+ timeoutMs: 10_000,
202
+ ...(options.fetchVia ? { fetchVia: options.fetchVia } : {}),
82
203
  });
83
- if (!group) {
84
- continue;
204
+ if (modelsResponse.models) {
205
+ return aggregateQuota(modelsResponse.models);
85
206
  }
86
- const existing = groups[group];
87
- const nextCount = (existing?.modelCount ?? 0) + 1;
88
- const nextRemaining = remainingFraction === undefined
89
- ? existing?.remainingFraction
90
- : existing?.remainingFraction === undefined
91
- ? remainingFraction
92
- : Math.min(existing.remainingFraction, remainingFraction);
93
- let nextResetTime = existing?.resetTime;
94
- if (resetTimestamp !== null) {
95
- if (!existing?.resetTime) {
96
- nextResetTime = resetTime;
97
- }
98
- else {
99
- const existingTimestamp = parseResetTime(existing.resetTime);
100
- if (existingTimestamp === null || resetTimestamp < existingTimestamp) {
101
- nextResetTime = resetTime;
102
- }
103
- }
104
- }
105
- groups[group] = {
106
- remainingFraction: nextRemaining,
107
- resetTime: nextResetTime,
108
- modelCount: nextCount,
207
+ return {
208
+ groups: {},
209
+ modelCount: 0,
210
+ error: 'Failed to fetch Antigravity quota (legacy fallback)',
109
211
  };
110
212
  }
111
- // Sort per-model entries by model ID for consistent display
112
- perModel.sort((a, b) => a.modelId.localeCompare(b.modelId));
113
- return { groups, perModel, modelCount: totalCount };
114
- }
115
- async function fetchWithTimeout(url, options, timeoutMs = FETCH_TIMEOUT_MS) {
116
- const controller = new AbortController();
117
- const timeout = setTimeout(() => controller.abort(), timeoutMs);
118
- try {
119
- return await fetch(url, { ...options, signal: controller.signal });
120
- }
121
- finally {
122
- clearTimeout(timeout);
213
+ catch {
214
+ return {
215
+ groups: {},
216
+ modelCount: 0,
217
+ error: 'Failed to fetch Antigravity quota',
218
+ };
123
219
  }
124
220
  }
125
- async function fetchAvailableModels(accessToken, projectId) {
126
- const quotaUserAgent = buildAntigravityHarnessUserAgent();
127
- const errors = [];
128
- for (const endpoint of ANTIGRAVITY_ENDPOINT_FALLBACKS) {
129
- const body = projectId ? { project: projectId } : {};
221
+ function makeFetchAccountQuota(client, providerId, fetchVia) {
222
+ return async (account, signal) => {
223
+ const index = 0;
224
+ const disabled = account.enabled === false;
225
+ if (disabled) {
226
+ return {
227
+ index,
228
+ email: account.email,
229
+ status: 'disabled',
230
+ disabled: true,
231
+ };
232
+ }
233
+ if (signal.aborted) {
234
+ return {
235
+ index,
236
+ email: account.email,
237
+ status: 'error',
238
+ error: signal.reason instanceof Error ? signal.reason.message : 'aborted',
239
+ };
240
+ }
241
+ let auth = buildAuthFromAccount(account);
242
+ let rotatedRefresh;
130
243
  try {
131
- const response = await fetchWithAgyCliTransport(`${endpoint}/v1internal:fetchAvailableModels`, {
132
- method: "POST",
133
- headers: {
134
- "User-Agent": quotaUserAgent,
135
- Authorization: `Bearer ${accessToken}`,
136
- "Content-Type": "application/json",
137
- "Accept-Encoding": "gzip",
138
- },
139
- body: JSON.stringify(body),
140
- }, { timeoutMs: FETCH_TIMEOUT_MS });
141
- if (response.ok) {
142
- return (await response.json());
244
+ if (accessTokenExpired(auth)) {
245
+ const refreshed = await refreshAccessToken(auth, client, providerId);
246
+ if (!refreshed) {
247
+ throw new Error('Token refresh failed');
248
+ }
249
+ if (refreshed.refresh !== auth.refresh) {
250
+ rotatedRefresh = refreshed.refresh;
251
+ }
252
+ auth = refreshed;
143
253
  }
144
- const status = response.status;
145
- // 403: retry once without project (like AntigravityManager)
146
- if (status === 403 && projectId) {
254
+ const projectContext = await ensureProjectContext(auth);
255
+ auth = projectContext.auth;
256
+ const updatedAccount = applyAccountUpdates(account, auth, projectContext.capturedTier);
257
+ if (rotatedRefresh && client) {
258
+ await persistRotatedRefresh(client, providerId, auth).catch(() => { });
259
+ }
260
+ let quotaResult;
261
+ let fellBackToLegacy = false;
262
+ const authParts = parseRefreshParts(auth.refresh);
263
+ // Bare refresh tokens have no packed project IDs — fall back to the
264
+ // account record. The real managedProjectId lives on the persisted
265
+ // account, not in the packed refresh string.
266
+ const managedProjectId = authParts.managedProjectId ?? account.managedProjectId;
267
+ // Two independent payload contracts: the windowed summary
268
+ // (with legacy fallback) and the gemini-CLI quota. They share
269
+ // access + project but target different endpoints, so the
270
+ // two 10s timeouts ran back-to-back for ~20s per account on
271
+ // modal open. Run them concurrently; either rejection is
272
+ // handled by its own branch and the result is still merged.
273
+ const fetchSummaryPayload = (async () => {
147
274
  try {
148
- const retryResponse = await fetchWithAgyCliTransport(`${endpoint}/v1internal:fetchAvailableModels`, {
149
- method: "POST",
150
- headers: {
151
- "User-Agent": quotaUserAgent,
152
- Authorization: `Bearer ${accessToken}`,
153
- "Content-Type": "application/json",
154
- "Accept-Encoding": "gzip",
155
- },
156
- body: JSON.stringify({}),
157
- }, { timeoutMs: FETCH_TIMEOUT_MS });
158
- if (retryResponse.ok) {
159
- return (await retryResponse.json());
160
- }
275
+ const summaryResult = await fetchQuotaSummary({
276
+ accessToken: auth.access ?? '',
277
+ managedProjectId,
278
+ projectId: projectContext.effectiveProjectId,
279
+ endpoints: ANTIGRAVITY_ENDPOINT_FALLBACKS,
280
+ userAgent: buildAntigravityHarnessUserAgent(),
281
+ timeoutMs: 10_000,
282
+ ...(fetchVia ? { fetchVia } : {}),
283
+ });
284
+ return {
285
+ result: aggregateQuotaSummary(summaryResult.summary),
286
+ fellBackToLegacy: summaryResult.fellBackToLegacy ?? false,
287
+ };
161
288
  }
162
289
  catch {
163
- // Fall through to next endpoint
290
+ return {
291
+ result: await fetchLegacyModelsFallback({
292
+ accessToken: auth.access ?? '',
293
+ projectId: projectContext.effectiveProjectId,
294
+ fetchVia,
295
+ }),
296
+ fellBackToLegacy: true,
297
+ };
164
298
  }
165
- }
166
- // 429/5xx: fall through to next endpoint
167
- if (status === 429 || status >= 500) {
168
- const message = await response.text().catch(() => "");
169
- const snippet = message.trim().slice(0, 200);
170
- errors.push(`fetchAvailableModels ${status} at ${endpoint}${snippet ? `: ${snippet}` : ""}`);
171
- continue;
172
- }
173
- // Other errors (4xx): don't retry on different endpoint
174
- const message = await response.text().catch(() => "");
175
- const snippet = message.trim().slice(0, 200);
176
- errors.push(`fetchAvailableModels ${status} at ${endpoint}${snippet ? `: ${snippet}` : ""}`);
177
- break;
178
- }
179
- catch (error) {
180
- // Network error or timeout: fall through to next endpoint
181
- errors.push(`fetchAvailableModels network error at ${endpoint}: ${error instanceof Error ? error.message : String(error)}`);
182
- continue;
183
- }
184
- }
185
- throw new Error(errors.join("; ") || "fetchAvailableModels failed");
186
- }
187
- async function fetchGeminiCliQuota(accessToken, projectId) {
188
- // Use Gemini CLI user-agent to get CLI quota buckets (not Antigravity buckets)
189
- const geminiCliUserAgent = buildGeminiCliUserAgent();
190
- for (const endpoint of ANTIGRAVITY_ENDPOINT_FALLBACKS) {
191
- const body = projectId ? { project: projectId } : {};
192
- try {
193
- const response = await fetchWithTimeout(`${endpoint}/v1internal:retrieveUserQuota`, {
194
- method: "POST",
195
- headers: {
196
- Authorization: `Bearer ${accessToken}`,
197
- "Content-Type": "application/json",
198
- "User-Agent": geminiCliUserAgent,
199
- },
200
- body: JSON.stringify(body),
299
+ })();
300
+ // CLI fetch is independent of the summary fetch. A CLI failure must
301
+ // NOT kill the summary result, but it also must not be laundered into
302
+ // "No Gemini CLI quota available" (a permanent-looking status) when
303
+ // the real cause is a transient network error. Capture the error
304
+ // message separately so the annotated result can carry it.
305
+ let geminiCliFetchError;
306
+ const fetchGeminiCliPayload = fetchGeminiCliQuota({
307
+ accessToken: auth.access ?? '',
308
+ projectId: projectContext.effectiveProjectId,
309
+ endpoints: ANTIGRAVITY_ENDPOINT_FALLBACKS,
310
+ userAgent: buildGeminiCliUserAgent(),
311
+ timeoutMs: 10_000,
312
+ ...(fetchVia ? { fetchVia } : {}),
313
+ }).catch((error) => {
314
+ geminiCliFetchError =
315
+ error instanceof Error ? error.message : String(error);
316
+ log.debug('fetchGeminiCliQuota failed', { error: geminiCliFetchError });
317
+ return { buckets: undefined };
201
318
  });
202
- if (response.ok) {
203
- return (await response.json());
204
- }
205
- const status = response.status;
206
- // 429/5xx: fall through to next endpoint
207
- if (status === 429 || status >= 500) {
208
- continue;
319
+ const [summary, geminiCliResponse] = await Promise.all([
320
+ fetchSummaryPayload,
321
+ fetchGeminiCliPayload,
322
+ ]);
323
+ quotaResult = summary.result;
324
+ fellBackToLegacy = summary.fellBackToLegacy;
325
+ const geminiCliQuotaResult = aggregateGeminiCliQuota(geminiCliResponse);
326
+ const annotated = geminiCliResponse.buckets === undefined ||
327
+ geminiCliResponse.buckets.length === 0
328
+ ? {
329
+ ...geminiCliQuotaResult,
330
+ error:
331
+ // A real fetch exception is a transient failure, not a
332
+ // "no CLI configured" scenario — propagate the actual message.
333
+ geminiCliFetchError ??
334
+ (geminiCliQuotaResult.models.length === 0
335
+ ? 'No Gemini CLI quota available'
336
+ : undefined),
337
+ }
338
+ : geminiCliQuotaResult;
339
+ for (const [family, groupQuota] of Object.entries(quotaResult.groups)) {
340
+ const remainingPercent = (groupQuota.remainingFraction ?? 0) * 100;
341
+ logQuotaStatus(account.email, index, remainingPercent, family);
209
342
  }
210
- // Other errors: don't retry on different endpoint
211
- return { buckets: [] };
343
+ const legacyTag = fellBackToLegacy ? ' legacy=1' : '';
344
+ logQuotaFetch('complete', 1, `ok=1 errors=0${legacyTag}`);
345
+ return {
346
+ index,
347
+ email: account.email,
348
+ status: 'ok',
349
+ disabled: false,
350
+ quota: quotaResult,
351
+ geminiCliQuota: annotated,
352
+ updatedAccount,
353
+ };
212
354
  }
213
- catch {
214
- // Network error or timeout: fall through to next endpoint
215
- continue;
355
+ catch (error) {
356
+ logQuotaFetch('error', undefined, `account=${account.email ?? index} error=${error instanceof Error ? error.message : String(error)}`);
357
+ return {
358
+ index,
359
+ email: account.email,
360
+ status: 'error',
361
+ error: error instanceof Error ? error.message : String(error),
362
+ disabled: false,
363
+ };
216
364
  }
217
- }
218
- // All endpoints failed
219
- return { buckets: [] };
365
+ };
220
366
  }
221
- function aggregateGeminiCliQuota(response) {
222
- const models = [];
223
- if (!response.buckets || response.buckets.length === 0) {
224
- return { models };
225
- }
226
- for (const bucket of response.buckets) {
227
- if (!bucket.modelId) {
228
- continue;
229
- }
230
- // Filter to relevant Gemini CLI quota models (premium tier)
231
- const modelId = bucket.modelId;
232
- const isRelevantModel = modelId.startsWith("gemini-3-") ||
233
- modelId.startsWith("gemini-3.") ||
234
- modelId.startsWith("gemini-2.5-");
235
- if (!isRelevantModel) {
236
- continue;
237
- }
238
- models.push({
239
- modelId: bucket.modelId,
240
- remainingFraction: normalizeRemainingFraction(bucket.remainingFraction),
241
- resetTime: bucket.resetTime,
242
- });
243
- }
244
- // Sort by model ID for consistent display
245
- models.sort((a, b) => a.modelId.localeCompare(b.modelId));
246
- return { models };
367
+ function buildAuthFromAccount(account) {
368
+ return {
369
+ type: 'oauth',
370
+ refresh: formatRefreshParts({
371
+ refreshToken: account.refreshToken,
372
+ projectId: account.projectId,
373
+ managedProjectId: account.managedProjectId,
374
+ }),
375
+ access: undefined,
376
+ expires: undefined,
377
+ };
247
378
  }
248
- function applyAccountUpdates(account, auth) {
379
+ function applyAccountUpdates(account, auth, capturedTier) {
249
380
  const parts = parseRefreshParts(auth.refresh);
250
381
  if (!parts.refreshToken) {
251
382
  return undefined;
@@ -255,82 +386,83 @@ function applyAccountUpdates(account, auth) {
255
386
  refreshToken: parts.refreshToken,
256
387
  projectId: parts.projectId ?? account.projectId,
257
388
  managedProjectId: parts.managedProjectId ?? account.managedProjectId,
389
+ // Persist the captured tier alongside the project-context write. Only
390
+ // present when the loadCodeAssist payload returned a non-empty currentTier.id.
391
+ ...(capturedTier
392
+ ? {
393
+ capturedTierId: capturedTier.id,
394
+ ...(capturedTier.paidId !== undefined
395
+ ? { capturedPaidTierId: capturedTier.paidId }
396
+ : {}),
397
+ capturedTierAt: capturedTier.capturedAt,
398
+ }
399
+ : {}),
258
400
  };
259
401
  const changed = updated.refreshToken !== account.refreshToken ||
260
402
  updated.projectId !== account.projectId ||
261
- updated.managedProjectId !== account.managedProjectId;
403
+ updated.managedProjectId !== account.managedProjectId ||
404
+ updated.capturedTierId !== account.capturedTierId ||
405
+ updated.capturedPaidTierId !== account.capturedPaidTierId ||
406
+ // capturedAt represents when the tier was LAST CONFIRMED, not when it
407
+ // changed -- always update it on a successful observation so consumers
408
+ // can gate staleness on that timestamp even when the id stays the same.
409
+ (capturedTier !== undefined &&
410
+ updated.capturedTierAt !== account.capturedTierAt);
262
411
  return changed ? updated : undefined;
263
412
  }
264
- export async function checkAccountsQuota(accounts, client, providerId = ANTIGRAVITY_PROVIDER_ID) {
265
- const results = [];
266
- logQuotaFetch("start", accounts.length);
267
- for (const [index, account] of accounts.entries()) {
268
- const disabled = account.enabled === false;
269
- let auth = buildAuthFromAccount(account);
413
+ async function persistRotatedRefresh(client, providerId, auth) {
414
+ await client.auth.set({
415
+ path: { id: providerId },
416
+ body: {
417
+ type: 'oauth',
418
+ refresh: auth.refresh,
419
+ access: auth.access ?? '',
420
+ expires: auth.expires ?? 0,
421
+ },
422
+ });
423
+ }
424
+ /**
425
+ * Build a per-account tier-loader callback for the background poller.
426
+ *
427
+ * Calls `loadManagedProject` (loadCodeAssist) directly, bypassing the
428
+ * `ensureProjectContext` cache that fast-paths on `managedProjectId` and
429
+ * never returns a tier for existing accounts. One call per account per 24 h.
430
+ *
431
+ * Uses the same token-refresh infrastructure as `makeFetchAccountQuota` so
432
+ * an expired access token does not silently fail the tier lookup.
433
+ *
434
+ * `loadManagedProject` uses the production TLS transport (`fetchWithAgyCliTransport`)
435
+ * and is not interceptable via `fetchVia` -- the same design constraint applies to
436
+ * `ensureProjectContext`. Tier lookup is best-effort; any failure resolves `null`.
437
+ */
438
+ export function makeTierLoader(client, providerId) {
439
+ return async (account) => {
270
440
  try {
441
+ let auth = buildAuthFromAccount(account);
271
442
  if (accessTokenExpired(auth)) {
272
443
  const refreshed = await refreshAccessToken(auth, client, providerId);
273
- if (!refreshed) {
274
- throw new Error("Token refresh failed");
275
- }
444
+ if (!refreshed)
445
+ return null;
276
446
  auth = refreshed;
277
447
  }
278
- const projectContext = await ensureProjectContext(auth);
279
- auth = projectContext.auth;
280
- const updatedAccount = applyAccountUpdates(account, auth);
281
- let quotaResult;
282
- let geminiCliQuotaResult;
283
- // Fetch both Antigravity and Gemini CLI quotas in parallel
284
- const [antigravityResponse, geminiCliResponse] = await Promise.all([
285
- fetchAvailableModels(auth.access ?? "", projectContext.effectiveProjectId)
286
- .catch((error) => ({ models: undefined })),
287
- fetchGeminiCliQuota(auth.access ?? "", projectContext.effectiveProjectId),
288
- ]);
289
- // Process Antigravity quota
290
- if (antigravityResponse.models === undefined) {
291
- quotaResult = {
292
- groups: {},
293
- modelCount: 0,
294
- error: "Failed to fetch Antigravity quota",
295
- };
296
- }
297
- else {
298
- quotaResult = aggregateQuota(antigravityResponse.models);
299
- }
300
- // Process Gemini CLI quota
301
- geminiCliQuotaResult = aggregateGeminiCliQuota(geminiCliResponse);
302
- if (geminiCliResponse.buckets === undefined || geminiCliResponse.buckets.length === 0) {
303
- geminiCliQuotaResult.error = geminiCliQuotaResult.models.length === 0
304
- ? "No Gemini CLI quota available"
305
- : undefined;
306
- }
307
- results.push({
308
- index,
309
- email: account.email,
310
- status: "ok",
311
- disabled,
312
- quota: quotaResult,
313
- geminiCliQuota: geminiCliQuotaResult,
314
- updatedAccount,
315
- });
316
- // Log quota status for each family
317
- for (const [family, groupQuota] of Object.entries(quotaResult.groups)) {
318
- const remainingPercent = (groupQuota.remainingFraction ?? 0) * 100;
319
- logQuotaStatus(account.email, index, remainingPercent, family);
320
- }
448
+ const accessToken = auth.access;
449
+ if (!accessToken)
450
+ return null;
451
+ const payload = await loadManagedProject(accessToken);
452
+ if (!payload?.currentTier?.id)
453
+ return null;
454
+ const paidTierId = typeof payload.paidTier === 'string'
455
+ ? payload.paidTier
456
+ : payload.paidTier?.id;
457
+ return {
458
+ id: payload.currentTier.id,
459
+ ...(paidTierId ? { paidId: paidTierId } : {}),
460
+ capturedAt: Date.now(),
461
+ };
321
462
  }
322
- catch (error) {
323
- results.push({
324
- index,
325
- email: account.email,
326
- status: "error",
327
- disabled,
328
- error: error instanceof Error ? error.message : String(error),
329
- });
330
- logQuotaFetch("error", undefined, `account=${account.email ?? index} error=${error instanceof Error ? error.message : String(error)}`);
463
+ catch {
464
+ return null;
331
465
  }
332
- }
333
- logQuotaFetch("complete", accounts.length, `ok=${results.filter(r => r.status === "ok").length} errors=${results.filter(r => r.status === "error").length}`);
334
- return results;
466
+ };
335
467
  }
336
468
  //# sourceMappingURL=quota.js.map