@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
package/dist/cli.js ADDED
@@ -0,0 +1,4017 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/cli.ts
4
+ import { execFile } from "node:child_process";
5
+ import { createInterface } from "node:readline/promises";
6
+ import { promisify } from "node:util";
7
+
8
+ // ../core/dist/account-storage.js
9
+ import { chmod, copyFile, mkdir as mkdir3, readFile as readFile2, unlink as unlink2 } from "node:fs/promises";
10
+
11
+ // ../core/dist/atomic-write.js
12
+ import { randomUUID } from "node:crypto";
13
+ import { mkdir, rename, rm, writeFile } from "node:fs/promises";
14
+ import { dirname } from "node:path";
15
+ async function writeJsonAtomic(path2, value) {
16
+ const serialized = `${JSON.stringify(value, null, 2)}
17
+ `;
18
+ const tempPath = `${path2}.${randomUUID()}.tmp`;
19
+ await mkdir(dirname(path2), { recursive: true });
20
+ let renamed = false;
21
+ try {
22
+ await writeFile(tempPath, serialized, {
23
+ encoding: "utf8",
24
+ mode: 384
25
+ });
26
+ await rename(tempPath, path2);
27
+ renamed = true;
28
+ } finally {
29
+ if (!renamed) {
30
+ await rm(tempPath, { force: true }).catch(() => {
31
+ });
32
+ }
33
+ }
34
+ }
35
+
36
+ // ../core/dist/file-lock.js
37
+ import { randomUUID as randomUUID2 } from "node:crypto";
38
+ import { mkdir as mkdir2, readFile, rename as rename2, rm as rm2, stat, unlink, writeFile as writeFile2 } from "node:fs/promises";
39
+ import { dirname as dirname2, join } from "node:path";
40
+ var RENEW_MIN_INTERVAL_MS = 1e3;
41
+ var MARKER_CLAIM_MAX_ATTEMPTS = 8;
42
+ var MARKER_CLAIM_BACKOFF_MS = 25;
43
+ var FileLockOwnershipError = class extends Error {
44
+ details;
45
+ constructor(message, details) {
46
+ super(message);
47
+ this.name = "FileLockOwnershipError";
48
+ this.details = details;
49
+ }
50
+ };
51
+ var MARKER_TTL_MS = 3e4;
52
+ async function readLockPayload(path2) {
53
+ try {
54
+ const text = await readFile(path2, "utf8");
55
+ const parsed = JSON.parse(text);
56
+ if (typeof parsed === "object" && parsed !== null && typeof parsed.ownerId === "string" && typeof parsed.expiresAt === "number") {
57
+ return parsed;
58
+ }
59
+ return null;
60
+ } catch {
61
+ return null;
62
+ }
63
+ }
64
+ async function readMarkerPayload(path2) {
65
+ try {
66
+ const text = await readFile(path2, "utf8");
67
+ const parsed = JSON.parse(text);
68
+ if (typeof parsed === "object" && parsed !== null && typeof parsed.ownerId === "string" && typeof parsed.pid === "number" && typeof parsed.createdAt === "number") {
69
+ return parsed;
70
+ }
71
+ return null;
72
+ } catch {
73
+ return null;
74
+ }
75
+ }
76
+ function isProcessAlive(pid) {
77
+ if (!Number.isInteger(pid) || pid <= 0)
78
+ return false;
79
+ try {
80
+ process.kill(pid, 0);
81
+ return true;
82
+ } catch (err) {
83
+ const code = err.code;
84
+ if (code === "ESRCH")
85
+ return false;
86
+ return true;
87
+ }
88
+ }
89
+ async function rmEvictingDir(evictingPath) {
90
+ await rm2(evictingPath, { force: true }).catch(() => {
91
+ });
92
+ await rm2(dirname2(evictingPath), { recursive: true, force: true }).catch(() => {
93
+ });
94
+ }
95
+ async function sleep(ms) {
96
+ await new Promise((resolve) => setTimeout(resolve, ms));
97
+ }
98
+ async function acquireFencedFileLock(options) {
99
+ const lockPath = `${options.path}.${options.name}.lock`;
100
+ const evictingDir = `${lockPath}.evicting`;
101
+ const evictingPath = join(evictingDir, "owner.json");
102
+ const ownerId = randomUUID2();
103
+ const now = options.now ?? Date.now;
104
+ const tryAcquire = async (expiresAt) => {
105
+ const payload = JSON.stringify({ ownerId, expiresAt });
106
+ try {
107
+ await mkdir2(dirname2(lockPath), { recursive: true });
108
+ await writeFile2(lockPath, payload, {
109
+ flag: "wx",
110
+ encoding: "utf8",
111
+ mode: 384
112
+ });
113
+ return buildLock(lockPath, evictingPath, ownerId, options, now);
114
+ } catch (err) {
115
+ if (err.code === "EEXIST") {
116
+ return null;
117
+ }
118
+ throw err;
119
+ }
120
+ };
121
+ for (; ; ) {
122
+ const firstTry = await tryAcquire(now() + options.ttlMs);
123
+ if (firstTry)
124
+ return firstTry;
125
+ const observed = await readLockPayload(lockPath);
126
+ const lockStats = await stat(lockPath).catch(() => null);
127
+ if (!lockStats)
128
+ continue;
129
+ const currentTime = now();
130
+ const looksLive = observed !== null && typeof observed.ownerId === "string" && observed.expiresAt > currentTime;
131
+ if (looksLive) {
132
+ return null;
133
+ }
134
+ const looksValid = observed !== null;
135
+ if (!looksValid) {
136
+ const ageMs = currentTime - lockStats.mtimeMs;
137
+ if (ageMs < options.ttlMs)
138
+ return null;
139
+ }
140
+ await options.onStep?.("stale-marker-stat");
141
+ let markerClaimed = false;
142
+ for (let attempt = 0; attempt < MARKER_CLAIM_MAX_ATTEMPTS; attempt++) {
143
+ try {
144
+ await mkdir2(evictingDir, { recursive: true, mode: 448 });
145
+ await writeFile2(evictingPath, JSON.stringify({
146
+ ownerId,
147
+ pid: process.pid,
148
+ createdAt: now()
149
+ }), {
150
+ flag: "wx",
151
+ encoding: "utf8",
152
+ mode: 384
153
+ });
154
+ markerClaimed = true;
155
+ break;
156
+ } catch (err) {
157
+ if (err.code !== "EEXIST")
158
+ throw err;
159
+ const existing = await readMarkerPayload(evictingPath);
160
+ if (existing) {
161
+ const ageMs = now() - existing.createdAt;
162
+ const deadPid = !isProcessAlive(existing.pid);
163
+ if (deadPid || ageMs > MARKER_TTL_MS) {
164
+ await rmEvictingDir(evictingPath);
165
+ continue;
166
+ }
167
+ }
168
+ await sleep(MARKER_CLAIM_BACKOFF_MS);
169
+ }
170
+ }
171
+ if (!markerClaimed) {
172
+ return null;
173
+ }
174
+ await options.onStep?.("stale-marker-claimed");
175
+ let markerPayload = await readMarkerPayload(evictingPath);
176
+ if (markerPayload?.ownerId !== ownerId)
177
+ continue;
178
+ const observedAgain = await readLockPayload(lockPath);
179
+ const refreshed = observedAgain !== null && observedAgain.ownerId !== ownerId && observedAgain.expiresAt > now();
180
+ if (refreshed) {
181
+ await rmEvictingDir(evictingPath);
182
+ return null;
183
+ }
184
+ await options.onStep?.("stale-lock-confirmed");
185
+ markerPayload = await readMarkerPayload(evictingPath);
186
+ if (markerPayload?.ownerId !== ownerId)
187
+ continue;
188
+ try {
189
+ await unlink(lockPath);
190
+ } catch (err) {
191
+ const code = err.code;
192
+ if (code !== "ENOENT") {
193
+ await rmEvictingDir(evictingPath);
194
+ continue;
195
+ }
196
+ }
197
+ await options.onStep?.("eviction-marker-acquired");
198
+ const reentry = await tryAcquire(now() + options.ttlMs);
199
+ if (reentry) {
200
+ await rmEvictingDir(evictingPath);
201
+ return reentry;
202
+ }
203
+ await rmEvictingDir(evictingPath);
204
+ }
205
+ }
206
+ function buildLock(lockPath, evictingPath, ownerId, options, now) {
207
+ let renewTimer = null;
208
+ let inFlightRenew = null;
209
+ let released = false;
210
+ let lost = false;
211
+ let lostResolve = null;
212
+ let lostPromise = new Promise((resolve) => {
213
+ lostResolve = resolve;
214
+ });
215
+ const markLost = () => {
216
+ if (lost)
217
+ return;
218
+ lost = true;
219
+ if (renewTimer !== null) {
220
+ clearInterval(renewTimer);
221
+ renewTimer = null;
222
+ }
223
+ const resolve = lostResolve;
224
+ lostResolve = null;
225
+ resolve?.();
226
+ };
227
+ const setupRenew = () => {
228
+ if (options.renew === false)
229
+ return;
230
+ const interval = options.renewIntervalMs ?? Math.max(RENEW_MIN_INTERVAL_MS, Math.floor(options.ttlMs / 3));
231
+ const renew = async () => {
232
+ if (released || lost)
233
+ return;
234
+ try {
235
+ const observed = await readLockPayload(lockPath);
236
+ if (released || lost)
237
+ return;
238
+ await options.onStep?.("renew-read");
239
+ if (released || lost)
240
+ return;
241
+ if (observed === null) {
242
+ markLost();
243
+ return;
244
+ }
245
+ if (observed.ownerId !== ownerId) {
246
+ markLost();
247
+ return;
248
+ }
249
+ if (observed.expiresAt > now()) {
250
+ if (released || lost)
251
+ return;
252
+ const tempPath = `${lockPath}.${ownerId}.tmp`;
253
+ let shouldCommit = false;
254
+ try {
255
+ await writeFile2(tempPath, JSON.stringify({
256
+ ownerId,
257
+ expiresAt: now() + options.ttlMs
258
+ }), { encoding: "utf8", mode: 384 });
259
+ if (released || lost) {
260
+ await unlink(tempPath).catch(() => {
261
+ });
262
+ return;
263
+ }
264
+ const currentObserved = await readLockPayload(lockPath);
265
+ if (released || lost) {
266
+ await unlink(tempPath).catch(() => {
267
+ });
268
+ return;
269
+ }
270
+ if (!currentObserved || currentObserved.ownerId !== ownerId) {
271
+ markLost();
272
+ await unlink(tempPath).catch(() => {
273
+ });
274
+ return;
275
+ }
276
+ shouldCommit = true;
277
+ await rename2(tempPath, lockPath);
278
+ await options.onStep?.("renew-committed");
279
+ if (released || lost)
280
+ return;
281
+ const committed = await readLockPayload(lockPath);
282
+ if (released || lost)
283
+ return;
284
+ if (!committed || committed.ownerId !== ownerId) {
285
+ markLost();
286
+ return;
287
+ }
288
+ } catch {
289
+ markLost();
290
+ if (!shouldCommit) {
291
+ await unlink(tempPath).catch(() => {
292
+ });
293
+ }
294
+ }
295
+ }
296
+ } catch {
297
+ }
298
+ };
299
+ const tick = () => {
300
+ if (released)
301
+ return;
302
+ if (inFlightRenew)
303
+ return;
304
+ inFlightRenew = renew().finally(() => {
305
+ inFlightRenew = null;
306
+ });
307
+ };
308
+ renewTimer = setInterval(tick, interval);
309
+ if (renewTimer && typeof renewTimer.unref === "function") {
310
+ ;
311
+ renewTimer.unref();
312
+ }
313
+ };
314
+ const release = async () => {
315
+ if (released)
316
+ return;
317
+ released = true;
318
+ if (renewTimer !== null) {
319
+ clearInterval(renewTimer);
320
+ renewTimer = null;
321
+ }
322
+ const pendingRenew = inFlightRenew;
323
+ inFlightRenew = null;
324
+ if (pendingRenew) {
325
+ try {
326
+ await pendingRenew;
327
+ } catch {
328
+ }
329
+ }
330
+ try {
331
+ const observed = await readLockPayload(lockPath);
332
+ if (!observed || observed.ownerId !== ownerId) {
333
+ await rmEvictingDir(evictingPath).catch(() => {
334
+ });
335
+ return;
336
+ }
337
+ try {
338
+ await unlink(lockPath);
339
+ } catch (err) {
340
+ if (err.code !== "ENOENT")
341
+ throw err;
342
+ }
343
+ await rmEvictingDir(evictingPath).catch(() => {
344
+ });
345
+ } finally {
346
+ markLost();
347
+ renewTimer = null;
348
+ inFlightRenew = null;
349
+ lostResolve = null;
350
+ lostPromise = null;
351
+ }
352
+ };
353
+ const assertOwned = async () => {
354
+ const observed = await readLockPayload(lockPath);
355
+ if (!observed || observed.ownerId !== ownerId) {
356
+ throw new FileLockOwnershipError(`file lock ${lockPath} is not owned by ${ownerId}`, {
357
+ path: lockPath,
358
+ expectedOwner: ownerId,
359
+ observedOwner: observed?.ownerId,
360
+ observedExpiresAt: observed?.expiresAt
361
+ });
362
+ }
363
+ if (observed.expiresAt <= now()) {
364
+ throw new FileLockOwnershipError(`file lock ${lockPath} has expired`, {
365
+ path: lockPath,
366
+ expectedOwner: ownerId,
367
+ observedOwner: observed.ownerId,
368
+ observedExpiresAt: observed.expiresAt
369
+ });
370
+ }
371
+ };
372
+ setupRenew();
373
+ return {
374
+ ownerId,
375
+ assertOwned,
376
+ release,
377
+ whenLost: () => lostPromise ?? Promise.resolve(),
378
+ hasLost: () => lost
379
+ };
380
+ }
381
+
382
+ // ../core/dist/logger.js
383
+ var ENV_CONSOLE_LOG = "ANTIGRAVITY_CORE_CONSOLE_LOG";
384
+ var _sink = null;
385
+ function isTruthyFlag(flag) {
386
+ return flag === "1" || flag?.toLowerCase() === "true";
387
+ }
388
+ function isConsoleLogEnabled() {
389
+ return isTruthyFlag(process.env[ENV_CONSOLE_LOG]);
390
+ }
391
+ function writeConsoleLog(level, ...args) {
392
+ switch (level) {
393
+ case "debug":
394
+ console.debug(...args);
395
+ break;
396
+ case "info":
397
+ console.info(...args);
398
+ break;
399
+ case "warn":
400
+ console.warn(...args);
401
+ break;
402
+ case "error":
403
+ console.error(...args);
404
+ break;
405
+ }
406
+ }
407
+ function createLogger(module) {
408
+ const service = `antigravity.${module}`;
409
+ const log8 = (level, message, extra) => {
410
+ if (_sink) {
411
+ try {
412
+ _sink({ service, level, message, extra });
413
+ } catch {
414
+ }
415
+ }
416
+ if (isConsoleLogEnabled()) {
417
+ const prefix = `[${service}]`;
418
+ const args = extra ? [prefix, message, extra] : [prefix, message];
419
+ writeConsoleLog(level, ...args);
420
+ }
421
+ };
422
+ return {
423
+ debug: (message, extra) => log8("debug", message, extra),
424
+ info: (message, extra) => log8("info", message, extra),
425
+ warn: (message, extra) => log8("warn", message, extra),
426
+ error: (message, extra) => log8("error", message, extra)
427
+ };
428
+ }
429
+
430
+ // ../core/dist/account-storage.js
431
+ var log = createLogger("account-storage");
432
+ var AccountStorageLockContentionError = class extends Error {
433
+ details;
434
+ constructor(message, details) {
435
+ super(message);
436
+ this.name = "AccountStorageLockContentionError";
437
+ this.details = details;
438
+ }
439
+ };
440
+ var AccountStorageUnreadableError = class extends Error {
441
+ details;
442
+ constructor(message, details) {
443
+ super(message);
444
+ this.name = "AccountStorageUnreadableError";
445
+ this.details = details;
446
+ }
447
+ };
448
+ var RETRY_DELAYS_MS = [100, 200, 400, 800, 1e3];
449
+ var DEFAULT_SLEEP = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
450
+ var DEFAULT_BUILD_BACKUP_PATH = (path2, now) => `${path2}.corrupt-${now.toISOString().replace(/[:.]/g, "-")}`;
451
+ async function ensureSecurePermissions(path2) {
452
+ try {
453
+ await chmod(path2, 384);
454
+ } catch {
455
+ }
456
+ }
457
+ async function backupCorruptFile(sourcePath, buildBackupPath, now) {
458
+ const backupPath = buildBackupPath(sourcePath, now);
459
+ if (!backupPath)
460
+ return null;
461
+ try {
462
+ await copyFile(sourcePath, backupPath);
463
+ await ensureSecurePermissions(backupPath);
464
+ return backupPath;
465
+ } catch (backupError) {
466
+ log.warn("Failed to back up corrupt account storage file", {
467
+ sourcePath,
468
+ backupPath,
469
+ error: String(backupError)
470
+ });
471
+ return null;
472
+ }
473
+ }
474
+ function deduplicateAccountsByEmail(accounts) {
475
+ const emailToNewestIndex = /* @__PURE__ */ new Map();
476
+ const indicesToKeep = /* @__PURE__ */ new Set();
477
+ for (let i = 0; i < accounts.length; i++) {
478
+ const acc = accounts[i];
479
+ if (!acc)
480
+ continue;
481
+ if (!acc.email) {
482
+ indicesToKeep.add(i);
483
+ continue;
484
+ }
485
+ const existingIndex = emailToNewestIndex.get(acc.email);
486
+ if (existingIndex === void 0) {
487
+ emailToNewestIndex.set(acc.email, i);
488
+ continue;
489
+ }
490
+ const existing = accounts[existingIndex];
491
+ if (!existing) {
492
+ emailToNewestIndex.set(acc.email, i);
493
+ continue;
494
+ }
495
+ const currLastUsed = acc.lastUsed || 0;
496
+ const existLastUsed = existing.lastUsed || 0;
497
+ const currAddedAt = acc.addedAt || 0;
498
+ const existAddedAt = existing.addedAt || 0;
499
+ const isNewer = currLastUsed > existLastUsed || currLastUsed === existLastUsed && currAddedAt > existAddedAt;
500
+ if (isNewer) {
501
+ emailToNewestIndex.set(acc.email, i);
502
+ }
503
+ }
504
+ for (const idx of emailToNewestIndex.values()) {
505
+ indicesToKeep.add(idx);
506
+ }
507
+ const result = [];
508
+ for (let i = 0; i < accounts.length; i++) {
509
+ if (indicesToKeep.has(i)) {
510
+ const acc = accounts[i];
511
+ if (acc) {
512
+ result.push(acc);
513
+ }
514
+ }
515
+ }
516
+ return result;
517
+ }
518
+ function migrateV1ToV2(v1) {
519
+ return {
520
+ version: 2,
521
+ accounts: v1.accounts.map((acc) => {
522
+ const rateLimitResetTimes = {};
523
+ if (acc.isRateLimited && acc.rateLimitResetTime && acc.rateLimitResetTime > Date.now()) {
524
+ rateLimitResetTimes.claude = acc.rateLimitResetTime;
525
+ rateLimitResetTimes.gemini = acc.rateLimitResetTime;
526
+ }
527
+ return {
528
+ email: acc.email,
529
+ refreshToken: acc.refreshToken,
530
+ projectId: acc.projectId,
531
+ managedProjectId: acc.managedProjectId,
532
+ addedAt: acc.addedAt,
533
+ lastUsed: acc.lastUsed,
534
+ lastSwitchReason: acc.lastSwitchReason,
535
+ rateLimitResetTimes: Object.keys(rateLimitResetTimes).length > 0 ? rateLimitResetTimes : void 0
536
+ };
537
+ }),
538
+ activeIndex: v1.activeIndex
539
+ };
540
+ }
541
+ function migrateV2ToV3(v2) {
542
+ return {
543
+ version: 3,
544
+ accounts: v2.accounts.map((acc) => {
545
+ const rateLimitResetTimes = {};
546
+ if (acc.rateLimitResetTimes?.claude && acc.rateLimitResetTimes.claude > Date.now()) {
547
+ rateLimitResetTimes.claude = acc.rateLimitResetTimes.claude;
548
+ }
549
+ if (acc.rateLimitResetTimes?.gemini && acc.rateLimitResetTimes.gemini > Date.now()) {
550
+ rateLimitResetTimes["gemini-antigravity"] = acc.rateLimitResetTimes.gemini;
551
+ }
552
+ return {
553
+ email: acc.email,
554
+ refreshToken: acc.refreshToken,
555
+ projectId: acc.projectId,
556
+ managedProjectId: acc.managedProjectId,
557
+ addedAt: acc.addedAt,
558
+ lastUsed: acc.lastUsed,
559
+ lastSwitchReason: acc.lastSwitchReason,
560
+ rateLimitResetTimes: Object.keys(rateLimitResetTimes).length > 0 ? rateLimitResetTimes : void 0
561
+ };
562
+ }),
563
+ activeIndex: v2.activeIndex
564
+ };
565
+ }
566
+ function migrateV3ToV4(v3) {
567
+ return {
568
+ version: 4,
569
+ accounts: v3.accounts.map((acc) => ({
570
+ ...acc,
571
+ fingerprint: void 0,
572
+ fingerprintHistory: void 0
573
+ })),
574
+ activeIndex: v3.activeIndex,
575
+ activeIndexByFamily: v3.activeIndexByFamily
576
+ };
577
+ }
578
+ function mergeAccountStorage(existing, incoming) {
579
+ const accountMap = /* @__PURE__ */ new Map();
580
+ for (const acc of existing.accounts) {
581
+ if (acc.refreshToken) {
582
+ accountMap.set(acc.refreshToken, acc);
583
+ }
584
+ }
585
+ for (const acc of incoming.accounts) {
586
+ if (!acc.refreshToken)
587
+ continue;
588
+ const existingAcc = accountMap.get(acc.refreshToken);
589
+ if (existingAcc) {
590
+ const eligibilitySource = (acc.eligibilityStateUpdatedAt ?? 0) >= (existingAcc.eligibilityStateUpdatedAt ?? 0) ? acc : existingAcc;
591
+ const merged = {
592
+ ...existingAcc,
593
+ ...acc,
594
+ projectId: acc.projectId ?? existingAcc.projectId,
595
+ managedProjectId: acc.managedProjectId ?? existingAcc.managedProjectId,
596
+ rateLimitResetTimes: {
597
+ ...existingAcc.rateLimitResetTimes,
598
+ ...acc.rateLimitResetTimes
599
+ },
600
+ lastUsed: Math.max(existingAcc.lastUsed || 0, acc.lastUsed || 0),
601
+ accountIneligible: eligibilitySource.accountIneligible,
602
+ accountIneligibleAt: eligibilitySource.accountIneligibleAt,
603
+ accountIneligibleReason: eligibilitySource.accountIneligibleReason,
604
+ eligibilityStateUpdatedAt: eligibilitySource.eligibilityStateUpdatedAt
605
+ };
606
+ if (merged.accountIneligible) {
607
+ merged.enabled = false;
608
+ }
609
+ accountMap.set(acc.refreshToken, merged);
610
+ } else {
611
+ accountMap.set(acc.refreshToken, acc);
612
+ }
613
+ }
614
+ return {
615
+ version: 4,
616
+ accounts: Array.from(accountMap.values()),
617
+ activeIndex: incoming.activeIndex,
618
+ activeIndexByFamily: incoming.activeIndexByFamily
619
+ };
620
+ }
621
+ async function readAndNormalizeV4(path2) {
622
+ let raw;
623
+ try {
624
+ raw = await readFile2(path2, "utf-8");
625
+ } catch (error) {
626
+ const code = error.code;
627
+ if (code === "ENOENT") {
628
+ return { state: "missing" };
629
+ }
630
+ return {
631
+ state: "unreadable",
632
+ reason: "io-error",
633
+ detail: `${code ?? "UNKNOWN"}: ${error.message ?? String(error)}`
634
+ };
635
+ }
636
+ let parsed;
637
+ try {
638
+ parsed = JSON.parse(raw);
639
+ } catch (parseError) {
640
+ return {
641
+ state: "unreadable",
642
+ reason: "malformed-json",
643
+ detail: parseError.message ?? String(parseError)
644
+ };
645
+ }
646
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
647
+ return {
648
+ state: "unreadable",
649
+ reason: "invalid-shape",
650
+ detail: "top-level value is not an object"
651
+ };
652
+ }
653
+ const candidate = parsed;
654
+ if (!Array.isArray(candidate.accounts)) {
655
+ return {
656
+ state: "unreadable",
657
+ reason: "invalid-shape",
658
+ detail: "`accounts` is missing or not an array"
659
+ };
660
+ }
661
+ const parsedVersion = candidate.version;
662
+ if (parsedVersion !== 1 && parsedVersion !== 2 && parsedVersion !== 3 && parsedVersion !== 4) {
663
+ return {
664
+ state: "unreadable",
665
+ reason: "unsupported-version",
666
+ detail: `unsupported version: ${String(parsedVersion)}`
667
+ };
668
+ }
669
+ let storage = null;
670
+ switch (parsedVersion) {
671
+ case 1:
672
+ storage = migrateV3ToV4(migrateV2ToV3(migrateV1ToV2(parsed)));
673
+ break;
674
+ case 2:
675
+ storage = migrateV3ToV4(migrateV2ToV3(parsed));
676
+ break;
677
+ case 3:
678
+ storage = migrateV3ToV4(parsed);
679
+ break;
680
+ case 4:
681
+ storage = parsed;
682
+ break;
683
+ }
684
+ if (!storage) {
685
+ return {
686
+ state: "unreadable",
687
+ reason: "unsupported-version",
688
+ detail: `unhandled version after switch: ${String(parsedVersion)}`
689
+ };
690
+ }
691
+ for (let i = 0; i < storage.accounts.length; i++) {
692
+ const detail = validateV4AccountRecord(storage.accounts[i], i);
693
+ if (detail !== null) {
694
+ return {
695
+ state: "unreadable",
696
+ reason: "invalid-shape",
697
+ detail
698
+ };
699
+ }
700
+ }
701
+ const deduplicatedAccounts = deduplicateAccountsByEmail(storage.accounts);
702
+ let activeIndex = typeof storage.activeIndex === "number" && Number.isFinite(storage.activeIndex) ? storage.activeIndex : 0;
703
+ if (deduplicatedAccounts.length > 0) {
704
+ activeIndex = Math.min(activeIndex, deduplicatedAccounts.length - 1);
705
+ activeIndex = Math.max(activeIndex, 0);
706
+ } else {
707
+ activeIndex = 0;
708
+ }
709
+ return {
710
+ state: "ok",
711
+ storage: {
712
+ version: 4,
713
+ accounts: deduplicatedAccounts,
714
+ activeIndex,
715
+ activeIndexByFamily: storage.activeIndexByFamily
716
+ }
717
+ };
718
+ }
719
+ function validateV4AccountRecord(record, index) {
720
+ if (record === null || typeof record !== "object" || Array.isArray(record)) {
721
+ return `accounts[${index}] is not an object`;
722
+ }
723
+ const acc = record;
724
+ if (typeof acc.refreshToken !== "string" || acc.refreshToken.length === 0) {
725
+ return `accounts[${index}].refreshToken is missing or not a non-empty string`;
726
+ }
727
+ if (typeof acc.addedAt !== "number" || !Number.isFinite(acc.addedAt)) {
728
+ return `accounts[${index}].addedAt is missing or not a finite number`;
729
+ }
730
+ if (typeof acc.lastUsed !== "number" || !Number.isFinite(acc.lastUsed)) {
731
+ return `accounts[${index}].lastUsed is missing or not a finite number`;
732
+ }
733
+ return null;
734
+ }
735
+ async function loadAccountStorage(path2) {
736
+ const buildBackupPath = DEFAULT_BUILD_BACKUP_PATH;
737
+ const now = () => /* @__PURE__ */ new Date();
738
+ await ensureSecurePermissions(path2);
739
+ const outcome = await readAndNormalizeV4(path2);
740
+ if (outcome.state === "missing") {
741
+ return null;
742
+ }
743
+ if (outcome.state === "unreadable") {
744
+ const backupPath = await backupCorruptFile(path2, buildBackupPath, now());
745
+ throw new AccountStorageUnreadableError(`Account storage at ${path2} is unreadable (${outcome.reason}: ${outcome.detail}).` + (backupPath ? ` A backup was written to ${backupPath}. The plugin will refuse to write until the file is removed or repaired.` : " A backup could not be written; the file has been left in place. The plugin will refuse to write until the file is removed or repaired."), {
746
+ path: path2,
747
+ reason: outcome.reason,
748
+ detail: outcome.detail,
749
+ backupPath
750
+ });
751
+ }
752
+ if (outcome.storage.version === 4) {
753
+ const onDiskVersion = await readVersionOnly(path2);
754
+ if (onDiskVersion !== null && onDiskVersion !== 4) {
755
+ try {
756
+ await saveAccountStorage(path2, outcome.storage);
757
+ log.info("Migration to v4 complete");
758
+ } catch (saveError) {
759
+ log.warn("Failed to persist migrated storage", {
760
+ error: String(saveError)
761
+ });
762
+ }
763
+ }
764
+ }
765
+ return outcome.storage;
766
+ }
767
+ async function readVersionOnly(path2) {
768
+ try {
769
+ const raw = await readFile2(path2, "utf-8");
770
+ const parsed = JSON.parse(raw);
771
+ return typeof parsed.version === "number" ? parsed.version : null;
772
+ } catch {
773
+ return null;
774
+ }
775
+ }
776
+ async function acquireWithRetry(path2, sleep2) {
777
+ for (let attempt = 0; attempt <= RETRY_DELAYS_MS.length; attempt++) {
778
+ const lock = await acquireFencedFileLock({
779
+ path: path2,
780
+ name: "accounts",
781
+ ttlMs: 1e4,
782
+ renew: true
783
+ });
784
+ if (lock) {
785
+ return lock;
786
+ }
787
+ if (attempt < RETRY_DELAYS_MS.length) {
788
+ const delay = RETRY_DELAYS_MS[attempt];
789
+ if (delay !== void 0) {
790
+ await sleep2(delay);
791
+ }
792
+ }
793
+ }
794
+ throw new AccountStorageLockContentionError(`account storage lock contention at ${path2} after ${RETRY_DELAYS_MS.length + 1} attempts`, {
795
+ path: path2,
796
+ attempts: RETRY_DELAYS_MS.length + 1
797
+ });
798
+ }
799
+ async function mutateAccountStorage(path2, mutate, options = {}) {
800
+ const sleep2 = options.sleep ?? DEFAULT_SLEEP;
801
+ const buildBackupPath = options.buildBackupPath ?? DEFAULT_BUILD_BACKUP_PATH;
802
+ const now = options.now ?? (() => /* @__PURE__ */ new Date());
803
+ const lock = await acquireWithRetry(path2, sleep2);
804
+ try {
805
+ const outcome = await readAndNormalizeV4(path2);
806
+ if (outcome.state === "unreadable") {
807
+ const backupPath = await backupCorruptFile(path2, buildBackupPath, now());
808
+ throw new AccountStorageUnreadableError(`Refusing to write: account storage at ${path2} is unreadable (${outcome.reason}: ${outcome.detail}).` + (backupPath ? ` A backup of the existing file was written to ${backupPath} and the on-disk file has been left untouched. Repair or remove the existing file before retrying.` : " A backup could not be written; the on-disk file has been left untouched. Repair or remove the existing file before retrying."), {
809
+ path: path2,
810
+ reason: outcome.reason,
811
+ detail: outcome.detail,
812
+ backupPath
813
+ });
814
+ }
815
+ const existing = outcome.state === "ok" ? outcome.storage : { version: 4, accounts: [], activeIndex: 0 };
816
+ const next = await mutate(existing);
817
+ const finalStorage = next ?? existing;
818
+ await lock.assertOwned();
819
+ await writeJsonAtomic(path2, finalStorage);
820
+ return finalStorage;
821
+ } finally {
822
+ try {
823
+ await lock.release();
824
+ } catch (releaseError) {
825
+ log.warn("Failed to release account storage lock", {
826
+ error: String(releaseError)
827
+ });
828
+ }
829
+ }
830
+ }
831
+ async function saveAccountStorage(path2, incoming) {
832
+ return mutateAccountStorage(path2, (current) => mergeAccountStorage(current, incoming));
833
+ }
834
+
835
+ // ../core/dist/auth.js
836
+ var ACCESS_TOKEN_EXPIRY_BUFFER_MS = 60 * 1e3;
837
+ function parseRefreshParts(refresh) {
838
+ const [refreshToken = "", projectId = "", managedProjectId = ""] = (refresh ?? "").split("|");
839
+ return {
840
+ refreshToken,
841
+ projectId: projectId || void 0,
842
+ managedProjectId: managedProjectId || void 0
843
+ };
844
+ }
845
+ function formatRefreshParts(parts) {
846
+ const projectSegment = parts.projectId ?? "";
847
+ const base = `${parts.refreshToken}|${projectSegment}`;
848
+ return parts.managedProjectId ? `${base}|${parts.managedProjectId}` : base;
849
+ }
850
+ function accessTokenExpired(auth) {
851
+ if (!auth.access || typeof auth.expires !== "number") {
852
+ return true;
853
+ }
854
+ return auth.expires <= Date.now() + ACCESS_TOKEN_EXPIRY_BUFFER_MS;
855
+ }
856
+ function calculateTokenExpiry(requestTimeMs, expiresInSeconds) {
857
+ const seconds = typeof expiresInSeconds === "number" ? expiresInSeconds : 3600;
858
+ if (Number.isNaN(seconds) || seconds <= 0) {
859
+ return requestTimeMs;
860
+ }
861
+ return requestTimeMs + seconds * 1e3;
862
+ }
863
+
864
+ // ../core/dist/fingerprint.js
865
+ var AGY_CLI_VERSION = "1.1.6";
866
+ function normalizeHarnessPlatform(platform = process.platform) {
867
+ return platform === "win32" ? "windows" : platform || "unknown";
868
+ }
869
+ function normalizeHarnessArch(arch = process.arch) {
870
+ switch (arch) {
871
+ case "x64":
872
+ return "amd64";
873
+ case "ia32":
874
+ return "386";
875
+ default:
876
+ return arch || "unknown";
877
+ }
878
+ }
879
+ function buildAntigravityHarnessUserAgent(version = AGY_CLI_VERSION, platform = process.platform, arch = process.arch, authMethod = "consumer") {
880
+ const osType = normalizeHarnessPlatform(platform);
881
+ const normalizedArch = normalizeHarnessArch(arch);
882
+ return `antigravity/cli/${version} (aidev_client; os_type=${osType}; arch=${normalizedArch}; auth_method=${authMethod})`;
883
+ }
884
+ function buildAntigravityHarnessLoadCodeAssistUserAgent(version = AGY_CLI_VERSION) {
885
+ return buildAntigravityHarnessUserAgent(version);
886
+ }
887
+ function buildAntigravityLoadCodeAssistMetadata() {
888
+ return { ideType: "ANTIGRAVITY" };
889
+ }
890
+ function buildAntigravityHarnessBootstrapHeaders(accessToken) {
891
+ return {
892
+ "User-Agent": buildAntigravityHarnessLoadCodeAssistUserAgent(),
893
+ Authorization: `Bearer ${accessToken}`,
894
+ "Content-Type": "application/json",
895
+ "Accept-Encoding": "gzip"
896
+ };
897
+ }
898
+
899
+ // ../core/dist/model-registry.js
900
+ var DEFAULT_MODALITIES = {
901
+ input: ["text", "image", "pdf"],
902
+ output: ["text"]
903
+ };
904
+ var MODEL_RELEASE_DATE = "";
905
+ var DEFAULT_COST = { input: 0, output: 0 };
906
+ var DEFAULT_OPTIONS = {};
907
+ function defineModel(id, model) {
908
+ return {
909
+ id,
910
+ release_date: MODEL_RELEASE_DATE,
911
+ attachment: model.modalities.input.some((modality) => modality !== "text"),
912
+ temperature: true,
913
+ tool_call: true,
914
+ cost: { ...DEFAULT_COST },
915
+ options: { ...DEFAULT_OPTIONS },
916
+ ...model
917
+ };
918
+ }
919
+ var ALL_MODEL_DEFINITIONS = {
920
+ "antigravity-gemini-3.1-pro": defineModel("antigravity-gemini-3.1-pro", {
921
+ name: "Gemini 3.1 Pro (Antigravity)",
922
+ reasoning: true,
923
+ limit: { context: 1048576, output: 65535 },
924
+ modalities: DEFAULT_MODALITIES,
925
+ variants: {
926
+ low: { thinkingLevel: "low" },
927
+ high: { thinkingLevel: "high" }
928
+ }
929
+ }),
930
+ "antigravity-gemini-3.6-flash": defineModel("antigravity-gemini-3.6-flash", {
931
+ name: "Gemini 3.6 Flash (Antigravity)",
932
+ reasoning: true,
933
+ limit: { context: 1048576, output: 65536 },
934
+ modalities: DEFAULT_MODALITIES,
935
+ variants: {
936
+ low: { thinkingLevel: "low" },
937
+ high: { thinkingLevel: "high" }
938
+ }
939
+ }),
940
+ "antigravity-gemini-3.5-flash": defineModel("antigravity-gemini-3.5-flash", {
941
+ name: "Gemini 3.5 Flash (Antigravity)",
942
+ reasoning: true,
943
+ limit: { context: 1048576, output: 65536 },
944
+ modalities: DEFAULT_MODALITIES,
945
+ variants: {
946
+ low: { thinkingLevel: "low" },
947
+ high: { thinkingLevel: "high" }
948
+ }
949
+ }),
950
+ "antigravity-claude-sonnet-4-6-thinking": defineModel("antigravity-claude-sonnet-4-6-thinking", {
951
+ name: "Claude Sonnet 4.6 Thinking (Antigravity)",
952
+ reasoning: true,
953
+ limit: { context: 25e4, output: 64e3 },
954
+ modalities: DEFAULT_MODALITIES,
955
+ variants: {
956
+ low: { disabled: true },
957
+ high: { disabled: true }
958
+ }
959
+ }),
960
+ "antigravity-claude-opus-4-6-thinking": defineModel("antigravity-claude-opus-4-6-thinking", {
961
+ name: "Claude Opus 4.6 Thinking (Antigravity)",
962
+ reasoning: true,
963
+ limit: { context: 25e4, output: 64e3 },
964
+ modalities: DEFAULT_MODALITIES,
965
+ variants: {
966
+ low: { disabled: true },
967
+ high: { disabled: true }
968
+ }
969
+ }),
970
+ "antigravity-gemini-3.1-flash-image": defineModel("antigravity-gemini-3.1-flash-image", {
971
+ name: "Gemini 3.1 Flash Image (Antigravity)",
972
+ reasoning: false,
973
+ limit: { context: 66e3, output: 33e3 },
974
+ modalities: {
975
+ input: ["text", "image"],
976
+ output: ["text", "image"]
977
+ }
978
+ }),
979
+ "antigravity-gpt-oss-120b-medium": defineModel("antigravity-gpt-oss-120b-medium", {
980
+ name: "GPT-OSS 120B Medium (Antigravity)",
981
+ reasoning: true,
982
+ limit: { context: 131072, output: 32768 },
983
+ modalities: DEFAULT_MODALITIES
984
+ }),
985
+ "gemini-2.5-flash": defineModel("gemini-2.5-flash", {
986
+ name: "Gemini 2.5 Flash (Gemini CLI)",
987
+ reasoning: true,
988
+ limit: { context: 1048576, output: 65536 },
989
+ modalities: DEFAULT_MODALITIES
990
+ }),
991
+ "gemini-2.5-pro": defineModel("gemini-2.5-pro", {
992
+ name: "Gemini 2.5 Pro (Gemini CLI)",
993
+ reasoning: true,
994
+ limit: { context: 1048576, output: 65536 },
995
+ modalities: DEFAULT_MODALITIES
996
+ }),
997
+ "gemini-3-flash-preview": defineModel("gemini-3-flash-preview", {
998
+ name: "Gemini 3 Flash Preview (Gemini CLI)",
999
+ reasoning: true,
1000
+ limit: { context: 1048576, output: 65536 },
1001
+ modalities: DEFAULT_MODALITIES
1002
+ }),
1003
+ "gemini-3.1-pro-preview": defineModel("gemini-3.1-pro-preview", {
1004
+ name: "Gemini 3.1 Pro Preview (Gemini CLI)",
1005
+ reasoning: true,
1006
+ limit: { context: 1048576, output: 65535 },
1007
+ modalities: DEFAULT_MODALITIES
1008
+ }),
1009
+ "gemini-3.5-flash-preview": defineModel("gemini-3.5-flash-preview", {
1010
+ name: "Gemini 3.5 Flash Preview (Gemini CLI)",
1011
+ reasoning: true,
1012
+ limit: { context: 1048576, output: 65536 },
1013
+ modalities: DEFAULT_MODALITIES
1014
+ }),
1015
+ "gemini-3.1-flash-image": defineModel("gemini-3.1-flash-image", {
1016
+ name: "Gemini 3.1 Flash Image (Gemini CLI)",
1017
+ reasoning: false,
1018
+ limit: { context: 66e3, output: 33e3 },
1019
+ modalities: {
1020
+ input: ["text", "image"],
1021
+ output: ["text", "image"]
1022
+ }
1023
+ }),
1024
+ "gemini-3.1-flash-image-preview": defineModel("gemini-3.1-flash-image-preview", {
1025
+ name: "Gemini 3.1 Flash Image Preview (Gemini CLI)",
1026
+ reasoning: false,
1027
+ limit: { context: 66e3, output: 33e3 },
1028
+ modalities: {
1029
+ input: ["text", "image"],
1030
+ output: ["text", "image"]
1031
+ }
1032
+ }),
1033
+ "gemini-3.1-pro-preview-customtools": defineModel("gemini-3.1-pro-preview-customtools", {
1034
+ name: "Gemini 3.1 Pro Preview Custom Tools (Gemini CLI)",
1035
+ reasoning: true,
1036
+ limit: { context: 1048576, output: 65535 },
1037
+ modalities: DEFAULT_MODALITIES
1038
+ })
1039
+ };
1040
+ var RESOLVER_ALIASES = {
1041
+ "gemini-3.1-pro-low": "gemini-3.1-pro",
1042
+ "gemini-3.1-pro-high": "gemini-3.1-pro",
1043
+ "gemini-3-flash-low": "gemini-3-flash",
1044
+ "gemini-3-flash-medium": "gemini-3-flash",
1045
+ "gemini-3-flash-high": "gemini-3-flash",
1046
+ "gemini-3.5-flash-low": "gemini-3.5-flash",
1047
+ "gemini-3.5-flash-medium": "gemini-3.5-flash",
1048
+ "gemini-3.5-flash-high": "gemini-3.5-flash",
1049
+ "gemini-3.6-flash-low": "gemini-3.6-flash",
1050
+ "gemini-3.6-flash-medium": "gemini-3.6-flash",
1051
+ "gemini-3.6-flash-high": "gemini-3.6-flash",
1052
+ "gemini-claude-opus-4-6-thinking-low": "claude-opus-4-6-thinking",
1053
+ "gemini-claude-opus-4-6-thinking-medium": "claude-opus-4-6-thinking",
1054
+ "gemini-claude-opus-4-6-thinking-high": "claude-opus-4-6-thinking",
1055
+ "gemini-claude-sonnet-4-6-thinking-low": "claude-sonnet-4-6",
1056
+ "gemini-claude-sonnet-4-6-thinking-medium": "claude-sonnet-4-6",
1057
+ "gemini-claude-sonnet-4-6-thinking-high": "claude-sonnet-4-6",
1058
+ "gemini-claude-sonnet-4-6": "claude-sonnet-4-6",
1059
+ "claude-sonnet-4-6-thinking": "claude-sonnet-4-6",
1060
+ "claude-sonnet-4-6-thinking-low": "claude-sonnet-4-6",
1061
+ "claude-sonnet-4-6-thinking-medium": "claude-sonnet-4-6",
1062
+ "claude-sonnet-4-6-thinking-high": "claude-sonnet-4-6",
1063
+ "gpt-oss-120b": "gpt-oss-120b-medium"
1064
+ };
1065
+ var QUOTA_GROUP_BY_MODEL_ID = {
1066
+ "claude-opus-4-6-thinking": "non-gemini",
1067
+ "claude-opus-4-6": "non-gemini",
1068
+ "claude-sonnet-4-6-thinking": "non-gemini",
1069
+ "claude-sonnet-4-6": "non-gemini",
1070
+ "gemini-pro-agent": "gemini",
1071
+ "gemini-3.1-pro": "gemini",
1072
+ "gemini-3.1-pro-low": "gemini",
1073
+ "gemini-3.1-pro-high": "gemini",
1074
+ "gemini-3-flash": "gemini",
1075
+ "gemini-3-flash-agent": "gemini",
1076
+ "gemini-3.5-flash-low": "gemini",
1077
+ "gemini-3.5-flash-extra-low": "gemini",
1078
+ "gemini-3.6-flash-low": "gemini",
1079
+ "gemini-3.6-flash-medium": "gemini",
1080
+ "gemini-3.6-flash-high": "gemini",
1081
+ "gemini-3.6-flash-tiered": "gemini",
1082
+ "gemini-3.1-flash-image": "gemini",
1083
+ "gpt-oss-120b": "non-gemini",
1084
+ "gpt-oss-120b-medium": "non-gemini"
1085
+ };
1086
+ var ANTIGRAVITY_OPENCODE_MODEL_IDS = [
1087
+ "antigravity-gemini-3.6-flash",
1088
+ "antigravity-gemini-3.5-flash",
1089
+ "antigravity-gemini-3.1-pro",
1090
+ "antigravity-claude-sonnet-4-6-thinking",
1091
+ "antigravity-claude-opus-4-6-thinking",
1092
+ "antigravity-gemini-3.1-flash-image",
1093
+ "antigravity-gpt-oss-120b-medium"
1094
+ ];
1095
+ function pickModelDefinitions(ids) {
1096
+ return Object.fromEntries(ids.map((id) => [id, ALL_MODEL_DEFINITIONS[id]]));
1097
+ }
1098
+ var OPENCODE_MODEL_DEFINITIONS = pickModelDefinitions(ANTIGRAVITY_OPENCODE_MODEL_IDS);
1099
+ function getResolverAliasMap() {
1100
+ return RESOLVER_ALIASES;
1101
+ }
1102
+ function getQuotaGroupForModel(modelId) {
1103
+ const normalized = modelId.toLowerCase();
1104
+ return QUOTA_GROUP_BY_MODEL_ID[normalized] ?? // Check Claude / GPT-OSS substrings BEFORE the `gemini` substring so
1105
+ // a `gemini-claude-*` alias (which is a Claude route exposed under
1106
+ // a `gemini-` namespace) attributes to the non-gemini pool rather
1107
+ // than the gemini pool. Substring matching is required because the
1108
+ // alias IDs start with `gemini-` but contain `claude`.
1109
+ (normalized.includes("claude") || normalized.includes("gpt-oss") ? "non-gemini" : normalized.startsWith("gemini") || normalized.startsWith("tab_") ? "gemini" : void 0);
1110
+ }
1111
+
1112
+ // ../core/dist/account-manager.js
1113
+ var ACCOUNT_SESSION_STATE_TTL_MS = 24 * 60 * 60 * 1e3;
1114
+
1115
+ // ../core/dist/agy-request-metadata.js
1116
+ var DEFAULT_SESSION_STATE_TTL_MS = 24 * 60 * 60 * 1e3;
1117
+
1118
+ // ../core/dist/agy-transport.js
1119
+ import { Buffer as Buffer2 } from "node:buffer";
1120
+ import * as net from "node:net";
1121
+ import { PassThrough, Readable, Transform } from "node:stream";
1122
+ import * as tls from "node:tls";
1123
+ import { createGunzip } from "node:zlib";
1124
+ var DEFAULT_HTTPS_PORT = 443;
1125
+ var DEFAULT_PROXY_PORT = 8080;
1126
+ var DEFAULT_AGY_RESPONSE_HEADER_TIMEOUT_MS = 18e4;
1127
+ var DEFAULT_AGY_IDLE_TIMEOUT_MS = 18e4;
1128
+ function headersToRecord(headers) {
1129
+ const result = {};
1130
+ if (!headers)
1131
+ return result;
1132
+ const normalized = new Headers(headers);
1133
+ normalized.forEach((value, key) => {
1134
+ result[key.toLowerCase()] = value;
1135
+ });
1136
+ return result;
1137
+ }
1138
+ function getHeader(headers, name) {
1139
+ return headers[name.toLowerCase()];
1140
+ }
1141
+ function bodyToBuffer(body) {
1142
+ if (body == null)
1143
+ return Buffer2.alloc(0);
1144
+ if (typeof body === "string")
1145
+ return Buffer2.from(body);
1146
+ if (body instanceof Uint8Array)
1147
+ return Buffer2.from(body);
1148
+ if (body instanceof ArrayBuffer)
1149
+ return Buffer2.from(body);
1150
+ throw new Error("agy transport only supports string/byte request bodies");
1151
+ }
1152
+ function shouldUseChunkedBody(url) {
1153
+ return url.pathname.includes(":streamGenerateContent");
1154
+ }
1155
+ function buildAgyCliHeaderPairs(url, init = {}) {
1156
+ const parsedUrl = new URL(url);
1157
+ const headers = headersToRecord(init.headers);
1158
+ const body = bodyToBuffer(init.body);
1159
+ const host = parsedUrl.port ? `${parsedUrl.hostname}:${parsedUrl.port}` : parsedUrl.hostname;
1160
+ const userAgent = getHeader(headers, "User-Agent") ?? buildAntigravityHarnessUserAgent();
1161
+ const authorization = getHeader(headers, "Authorization");
1162
+ const contentType = getHeader(headers, "Content-Type") ?? "application/json";
1163
+ const acceptEncoding = getHeader(headers, "Accept-Encoding") ?? "gzip";
1164
+ const chunked = shouldUseChunkedBody(parsedUrl);
1165
+ const pairs = [
1166
+ ["Host", host],
1167
+ ["User-Agent", userAgent]
1168
+ ];
1169
+ if (chunked) {
1170
+ pairs.push(["Transfer-Encoding", "chunked"]);
1171
+ } else {
1172
+ pairs.push(["Content-Length", String(body.byteLength)]);
1173
+ }
1174
+ if (authorization) {
1175
+ pairs.push(["Authorization", authorization]);
1176
+ }
1177
+ pairs.push(["Content-Type", contentType]);
1178
+ pairs.push(["Accept-Encoding", acceptEncoding]);
1179
+ return pairs;
1180
+ }
1181
+ function noProxyIncludes(hostname) {
1182
+ const raw = process.env.NO_PROXY || process.env.no_proxy || "";
1183
+ if (!raw)
1184
+ return false;
1185
+ const host = hostname.toLowerCase();
1186
+ return raw.split(",").map((entry) => entry.trim().toLowerCase()).some((entry) => {
1187
+ if (!entry)
1188
+ return false;
1189
+ if (entry === "*")
1190
+ return true;
1191
+ if (entry.startsWith("."))
1192
+ return host.endsWith(entry);
1193
+ return host === entry || host.endsWith(`.${entry}`);
1194
+ });
1195
+ }
1196
+ function getHttpsProxy(url) {
1197
+ if (url.protocol !== "https:" || noProxyIncludes(url.hostname))
1198
+ return void 0;
1199
+ const rawProxy = process.env.HTTPS_PROXY || process.env.https_proxy || process.env.ALL_PROXY || process.env.all_proxy;
1200
+ if (!rawProxy)
1201
+ return void 0;
1202
+ try {
1203
+ return new URL(rawProxy);
1204
+ } catch {
1205
+ return void 0;
1206
+ }
1207
+ }
1208
+ function waitForHead(socket, timeoutMs, onTimeout) {
1209
+ return new Promise((resolve, reject) => {
1210
+ let buffer = Buffer2.alloc(0);
1211
+ const timeout = setTimeout(() => {
1212
+ onTimeout();
1213
+ cleanup(() => reject(new Error(`Antigravity request timed out waiting for response headers after ${timeoutMs}ms`)));
1214
+ }, timeoutMs);
1215
+ const cleanup = (finish) => {
1216
+ socket.off("data", onData);
1217
+ socket.off("error", onError);
1218
+ clearTimeout(timeout);
1219
+ finish();
1220
+ };
1221
+ const onError = (error) => cleanup(() => reject(error));
1222
+ const onData = (chunk) => {
1223
+ buffer = Buffer2.concat([buffer, chunk]);
1224
+ const marker = buffer.indexOf("\r\n\r\n");
1225
+ if (marker === -1)
1226
+ return;
1227
+ const head = buffer.subarray(0, marker).toString("latin1");
1228
+ const leftover = buffer.subarray(marker + 4);
1229
+ cleanup(() => resolve({ head, leftover }));
1230
+ };
1231
+ socket.on("data", onData);
1232
+ socket.once("error", onError);
1233
+ });
1234
+ }
1235
+ async function connectViaProxy(proxyUrl, targetUrl, timeoutMs, onDebug) {
1236
+ const proxySocket = net.connect({
1237
+ host: proxyUrl.hostname,
1238
+ port: Number(proxyUrl.port || DEFAULT_PROXY_PORT)
1239
+ });
1240
+ await new Promise((resolve, reject) => {
1241
+ const timeout = setTimeout(() => {
1242
+ onDebug?.(`agy transport proxy connect timeout after ${timeoutMs}ms`);
1243
+ proxySocket.destroy();
1244
+ reject(new Error(`Antigravity request timed out connecting to HTTPS proxy after ${timeoutMs}ms`));
1245
+ }, timeoutMs);
1246
+ const cleanup = () => clearTimeout(timeout);
1247
+ proxySocket.once("connect", () => {
1248
+ cleanup();
1249
+ resolve();
1250
+ });
1251
+ proxySocket.once("error", (error) => {
1252
+ cleanup();
1253
+ reject(error);
1254
+ });
1255
+ });
1256
+ const targetHost = targetUrl.hostname;
1257
+ const targetPort = Number(targetUrl.port || DEFAULT_HTTPS_PORT);
1258
+ const auth = proxyUrl.username ? `Proxy-Authorization: Basic ${Buffer2.from(`${decodeURIComponent(proxyUrl.username)}:${decodeURIComponent(proxyUrl.password)}`).toString("base64")}\r
1259
+ ` : "";
1260
+ proxySocket.write(`CONNECT ${targetHost}:${targetPort} HTTP/1.1\r
1261
+ Host: ${targetHost}:${targetPort}\r
1262
+ ` + auth + "\r\n");
1263
+ const { head, leftover } = await waitForHead(proxySocket, timeoutMs, () => {
1264
+ onDebug?.(`agy transport proxy CONNECT response timeout after ${timeoutMs}ms`);
1265
+ proxySocket.destroy();
1266
+ });
1267
+ if (!/^HTTP\/1\.[01] 2\d\d\b/.test(head)) {
1268
+ proxySocket.destroy();
1269
+ throw new Error(`Proxy CONNECT failed: ${head.split("\r\n")[0] ?? "unknown"}`);
1270
+ }
1271
+ if (leftover.length > 0) {
1272
+ proxySocket.unshift(leftover);
1273
+ }
1274
+ return await new Promise((resolve, reject) => {
1275
+ const tlsSocket = tls.connect({
1276
+ socket: proxySocket,
1277
+ servername: targetHost
1278
+ });
1279
+ const timeout = setTimeout(() => {
1280
+ onDebug?.(`agy transport proxy TLS handshake timeout after ${timeoutMs}ms`);
1281
+ tlsSocket.destroy();
1282
+ reject(new Error(`Antigravity request timed out during proxy TLS handshake after ${timeoutMs}ms`));
1283
+ }, timeoutMs);
1284
+ const cleanup = () => clearTimeout(timeout);
1285
+ tlsSocket.once("secureConnect", () => {
1286
+ cleanup();
1287
+ resolve(tlsSocket);
1288
+ });
1289
+ tlsSocket.once("error", (error) => {
1290
+ cleanup();
1291
+ reject(error);
1292
+ });
1293
+ });
1294
+ }
1295
+ async function connectDirect(targetUrl, timeoutMs, onDebug) {
1296
+ return await new Promise((resolve, reject) => {
1297
+ const socket = tls.connect({
1298
+ host: targetUrl.hostname,
1299
+ port: Number(targetUrl.port || DEFAULT_HTTPS_PORT),
1300
+ servername: targetUrl.hostname
1301
+ });
1302
+ const timeout = setTimeout(() => {
1303
+ onDebug?.(`agy transport TLS connect timeout after ${timeoutMs}ms`);
1304
+ socket.destroy();
1305
+ reject(new Error(`Antigravity request timed out connecting after ${timeoutMs}ms`));
1306
+ }, timeoutMs);
1307
+ const cleanup = () => clearTimeout(timeout);
1308
+ socket.once("secureConnect", () => {
1309
+ cleanup();
1310
+ resolve(socket);
1311
+ });
1312
+ socket.once("error", (error) => {
1313
+ cleanup();
1314
+ reject(error);
1315
+ });
1316
+ });
1317
+ }
1318
+ async function connectTls(targetUrl, timeoutMs, onDebug) {
1319
+ const proxyUrl = getHttpsProxy(targetUrl);
1320
+ return proxyUrl ? await connectViaProxy(proxyUrl, targetUrl, timeoutMs, onDebug) : await connectDirect(targetUrl, timeoutMs, onDebug);
1321
+ }
1322
+ function serializeRequest(url, init, body) {
1323
+ const method = init.method ?? "POST";
1324
+ const path2 = `${url.pathname}${url.search}`;
1325
+ const headerLines = buildAgyCliHeaderPairs(url.toString(), init).map(([key, value]) => `${key}: ${value}`).join("\r\n");
1326
+ const head = Buffer2.from(`${method} ${path2} HTTP/1.1\r
1327
+ ${headerLines}\r
1328
+ \r
1329
+ `);
1330
+ if (body.byteLength === 0) {
1331
+ return head;
1332
+ }
1333
+ if (!shouldUseChunkedBody(url)) {
1334
+ return Buffer2.concat([head, body]);
1335
+ }
1336
+ return Buffer2.concat([
1337
+ head,
1338
+ Buffer2.from(`${body.byteLength.toString(16)}\r
1339
+ `),
1340
+ body,
1341
+ Buffer2.from("\r\n0\r\n\r\n")
1342
+ ]);
1343
+ }
1344
+ function parseResponseHead(head) {
1345
+ const lines = head.split("\r\n");
1346
+ const statusLine = lines.shift() ?? "";
1347
+ const match = /^HTTP\/1\.[01]\s+(\d{3})\s*(.*)$/.exec(statusLine);
1348
+ if (!match) {
1349
+ throw new Error(`Invalid HTTP response: ${statusLine}`);
1350
+ }
1351
+ const headers = new Headers();
1352
+ let chunked = false;
1353
+ let gzip = false;
1354
+ let contentLength;
1355
+ for (const line of lines) {
1356
+ const index = line.indexOf(":");
1357
+ if (index <= 0)
1358
+ continue;
1359
+ const key = line.slice(0, index);
1360
+ const value = line.slice(index + 1).trim();
1361
+ const lowerKey = key.toLowerCase();
1362
+ const lowerValue = value.toLowerCase();
1363
+ if (lowerKey === "transfer-encoding" && lowerValue.includes("chunked")) {
1364
+ chunked = true;
1365
+ continue;
1366
+ }
1367
+ if (lowerKey === "content-encoding" && lowerValue.includes("gzip")) {
1368
+ gzip = true;
1369
+ continue;
1370
+ }
1371
+ if (lowerKey === "content-length") {
1372
+ const parsed = Number.parseInt(value, 10);
1373
+ if (Number.isFinite(parsed) && parsed >= 0) {
1374
+ contentLength = parsed;
1375
+ }
1376
+ if (gzip)
1377
+ continue;
1378
+ }
1379
+ headers.append(key, value);
1380
+ }
1381
+ return {
1382
+ status: Number(match[1]),
1383
+ statusText: match[2] ?? "",
1384
+ headers,
1385
+ chunked,
1386
+ gzip,
1387
+ contentLength
1388
+ };
1389
+ }
1390
+ var ContentLengthStream = class extends Transform {
1391
+ remaining;
1392
+ constructor(contentLength) {
1393
+ super();
1394
+ this.remaining = contentLength;
1395
+ }
1396
+ _transform(chunk, _encoding, callback) {
1397
+ if (this.remaining <= 0) {
1398
+ callback();
1399
+ return;
1400
+ }
1401
+ if (chunk.length <= this.remaining) {
1402
+ this.remaining -= chunk.length;
1403
+ this.push(chunk);
1404
+ } else {
1405
+ this.push(chunk.subarray(0, this.remaining));
1406
+ this.remaining = 0;
1407
+ }
1408
+ if (this.remaining <= 0) {
1409
+ this.push(null);
1410
+ }
1411
+ callback();
1412
+ }
1413
+ };
1414
+ var ChunkedDecodeStream = class extends Transform {
1415
+ buffer = Buffer2.alloc(0);
1416
+ _transform(chunk, _encoding, callback) {
1417
+ this.buffer = Buffer2.concat([this.buffer, chunk]);
1418
+ try {
1419
+ this.flushAvailableChunks();
1420
+ callback();
1421
+ } catch (error) {
1422
+ callback(error instanceof Error ? error : new Error(String(error)));
1423
+ }
1424
+ }
1425
+ _flush(callback) {
1426
+ try {
1427
+ this.flushAvailableChunks();
1428
+ callback();
1429
+ } catch (error) {
1430
+ callback(error instanceof Error ? error : new Error(String(error)));
1431
+ }
1432
+ }
1433
+ flushAvailableChunks() {
1434
+ while (true) {
1435
+ const lineEnd = this.buffer.indexOf("\r\n");
1436
+ if (lineEnd === -1)
1437
+ return;
1438
+ const sizeLine = this.buffer.subarray(0, lineEnd).toString("latin1");
1439
+ const sizeText = sizeLine.split(";", 1)[0]?.trim() ?? "";
1440
+ const size = Number.parseInt(sizeText, 16);
1441
+ if (!Number.isFinite(size)) {
1442
+ throw new Error(`Invalid chunk size: ${sizeLine}`);
1443
+ }
1444
+ const chunkStart = lineEnd + 2;
1445
+ const chunkEnd = chunkStart + size;
1446
+ const nextOffset = chunkEnd + 2;
1447
+ if (this.buffer.length < nextOffset)
1448
+ return;
1449
+ if (size === 0) {
1450
+ this.buffer = Buffer2.alloc(0);
1451
+ this.push(null);
1452
+ return;
1453
+ }
1454
+ this.push(this.buffer.subarray(chunkStart, chunkEnd));
1455
+ this.buffer = this.buffer.subarray(nextOffset);
1456
+ }
1457
+ }
1458
+ };
1459
+ function buildResponseStream(socket, leftover, head, signal, idleTimeoutMs, onDebug) {
1460
+ const source = new PassThrough();
1461
+ if (leftover.length > 0) {
1462
+ source.write(leftover);
1463
+ }
1464
+ socket.pipe(source);
1465
+ let responseBody = source;
1466
+ if (head.chunked) {
1467
+ responseBody = responseBody.pipe(new ChunkedDecodeStream());
1468
+ } else if (typeof head.contentLength === "number") {
1469
+ responseBody = responseBody.pipe(new ContentLengthStream(head.contentLength));
1470
+ }
1471
+ if (head.gzip) {
1472
+ responseBody = responseBody.pipe(createGunzip());
1473
+ }
1474
+ let idleTimer;
1475
+ const clearIdle = () => {
1476
+ if (idleTimer) {
1477
+ clearTimeout(idleTimer);
1478
+ idleTimer = void 0;
1479
+ }
1480
+ };
1481
+ const armIdle = () => {
1482
+ if (!idleTimeoutMs || idleTimeoutMs <= 0)
1483
+ return;
1484
+ clearIdle();
1485
+ idleTimer = setTimeout(() => {
1486
+ onDebug?.(`agy transport idle timeout after ${idleTimeoutMs}ms with no body data`);
1487
+ socket.destroy(new Error(`Antigravity response stalled: no data for ${idleTimeoutMs}ms`));
1488
+ }, idleTimeoutMs);
1489
+ };
1490
+ socket.on("data", armIdle);
1491
+ armIdle();
1492
+ const abort = () => socket.destroy(new DOMException("The operation was aborted", "AbortError"));
1493
+ const cleanup = () => {
1494
+ clearIdle();
1495
+ socket.off("data", armIdle);
1496
+ signal?.removeEventListener("abort", abort);
1497
+ };
1498
+ if (signal?.aborted) {
1499
+ abort();
1500
+ } else {
1501
+ signal?.addEventListener("abort", abort, { once: true });
1502
+ }
1503
+ responseBody.once("end", () => {
1504
+ cleanup();
1505
+ socket.destroy();
1506
+ });
1507
+ responseBody.once("error", () => {
1508
+ cleanup();
1509
+ socket.destroy();
1510
+ });
1511
+ responseBody.once("close", cleanup);
1512
+ return Readable.toWeb(responseBody);
1513
+ }
1514
+ async function fetchWithAgyCliTransport(url, init = {}, options = {}) {
1515
+ const parsedUrl = new URL(url);
1516
+ if (parsedUrl.protocol !== "https:") {
1517
+ throw new Error(`agy transport only supports https URLs: ${url}`);
1518
+ }
1519
+ if (options.signal?.aborted) {
1520
+ throw new DOMException("The operation was aborted", "AbortError");
1521
+ }
1522
+ const body = bodyToBuffer(init.body);
1523
+ const requestBytes = serializeRequest(parsedUrl, init, body);
1524
+ const timeoutMs = options.timeoutMs ?? DEFAULT_AGY_RESPONSE_HEADER_TIMEOUT_MS;
1525
+ const idleTimeoutMs = options.idleTimeoutMs ?? DEFAULT_AGY_IDLE_TIMEOUT_MS;
1526
+ options.onDebug?.(`agy transport connecting to ${parsedUrl.hostname} with header timeout ${timeoutMs}ms`);
1527
+ const socket = await connectTlsWithAbort(parsedUrl, timeoutMs, options.signal, options.onDebug);
1528
+ const abort = () => {
1529
+ socket.destroy(new DOMException("The operation was aborted", "AbortError"));
1530
+ };
1531
+ try {
1532
+ options.signal?.addEventListener("abort", abort, { once: true });
1533
+ socket.write(requestBytes);
1534
+ options.onDebug?.(`agy transport request dispatched (${requestBytes.byteLength} bytes)`);
1535
+ const { head, leftover } = await waitForHead(socket, timeoutMs, () => {
1536
+ options.onDebug?.(`agy transport response header timeout after ${timeoutMs}ms`);
1537
+ socket.destroy();
1538
+ });
1539
+ const parsedHead = parseResponseHead(head);
1540
+ options.onDebug?.(`agy transport response headers received: ${parsedHead.status} ${parsedHead.statusText}`);
1541
+ const bodyStream = buildResponseStream(socket, leftover, parsedHead, options.signal, idleTimeoutMs, options.onDebug);
1542
+ return new Response(bodyStream, {
1543
+ status: parsedHead.status,
1544
+ statusText: parsedHead.statusText,
1545
+ headers: parsedHead.headers
1546
+ });
1547
+ } catch (error) {
1548
+ socket.destroy();
1549
+ throw error;
1550
+ } finally {
1551
+ options.signal?.removeEventListener("abort", abort);
1552
+ }
1553
+ }
1554
+ async function connectTlsWithAbort(targetUrl, timeoutMs, signal, onDebug) {
1555
+ if (!signal) {
1556
+ return connectTls(targetUrl, timeoutMs, onDebug);
1557
+ }
1558
+ const connectPromise = connectTls(targetUrl, timeoutMs, onDebug);
1559
+ let onAbort;
1560
+ const abortPromise = new Promise((_, reject) => {
1561
+ onAbort = () => reject(new DOMException("The operation was aborted", "AbortError"));
1562
+ signal.addEventListener("abort", onAbort, { once: true });
1563
+ });
1564
+ try {
1565
+ return await Promise.race([connectPromise, abortPromise]);
1566
+ } catch (error) {
1567
+ void connectPromise.then((socket) => socket.destroy()).catch(() => {
1568
+ });
1569
+ throw error;
1570
+ } finally {
1571
+ if (onAbort)
1572
+ signal.removeEventListener("abort", onAbort);
1573
+ }
1574
+ }
1575
+
1576
+ // ../core/dist/antigravity/oauth.js
1577
+ import { generatePKCE } from "@openauthjs/openauth/pkce";
1578
+
1579
+ // ../core/dist/constants.js
1580
+ var ANTIGRAVITY_CLIENT_ID = "1071006060591-tmhssin2h21lcre235vtolojh4g403ep.apps.googleusercontent.com";
1581
+ var ANTIGRAVITY_CLIENT_SECRET = "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";
1582
+ var ANTIGRAVITY_SCOPES = [
1583
+ "https://www.googleapis.com/auth/cloud-platform",
1584
+ "https://www.googleapis.com/auth/userinfo.email",
1585
+ "https://www.googleapis.com/auth/userinfo.profile",
1586
+ "https://www.googleapis.com/auth/cclog",
1587
+ "https://www.googleapis.com/auth/experimentsandconfigs"
1588
+ ];
1589
+ var ANTIGRAVITY_REDIRECT_URI = "http://localhost:51121/oauth-callback";
1590
+ var ANTIGRAVITY_ENDPOINT_DAILY = "https://daily-cloudcode-pa.googleapis.com";
1591
+ var ANTIGRAVITY_ENDPOINT_PROD = "https://cloudcode-pa.googleapis.com";
1592
+ var ANTIGRAVITY_ENDPOINT_FALLBACKS = [
1593
+ ANTIGRAVITY_ENDPOINT_DAILY,
1594
+ ANTIGRAVITY_ENDPOINT_PROD
1595
+ ];
1596
+ var ANTIGRAVITY_LOAD_ENDPOINTS = [
1597
+ ANTIGRAVITY_ENDPOINT_DAILY,
1598
+ ANTIGRAVITY_ENDPOINT_PROD
1599
+ ];
1600
+ var ANTIGRAVITY_DEFAULT_PROJECT_ID = "rising-fact-p41fc";
1601
+ var ANTIGRAVITY_VERSION_FALLBACK = "1.18.3";
1602
+ var ANTIGRAVITY_VERSION = ANTIGRAVITY_VERSION_FALLBACK;
1603
+ var ANTIGRAVITY_HEADERS = {
1604
+ "User-Agent": `Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Antigravity/${ANTIGRAVITY_VERSION} Chrome/138.0.7204.235 Electron/37.3.1 Safari/537.36`,
1605
+ "X-Goog-Api-Client": "google-cloud-sdk vscode_cloudshelleditor/0.1",
1606
+ "Client-Metadata": `{"ideType":"ANTIGRAVITY","platform":"${process.platform === "win32" ? "WINDOWS" : "MACOS"}","pluginType":"GEMINI"}`
1607
+ };
1608
+ var GEMINI_CLI_VERSION = "1.0.0";
1609
+ var GEMINI_CLI_DEFAULT_MODEL = "gemini-2.5-pro";
1610
+ function buildGeminiCliUserAgent(model) {
1611
+ const effectiveModel = model || GEMINI_CLI_DEFAULT_MODEL;
1612
+ const platform = process.platform || "darwin";
1613
+ const arch = process.arch || "arm64";
1614
+ return `GeminiCLI/${GEMINI_CLI_VERSION}/${effectiveModel} (${platform}; ${arch})`;
1615
+ }
1616
+ var GEMINI_CLI_HEADERS = {
1617
+ "User-Agent": "google-api-nodejs-client/9.15.1",
1618
+ "X-Goog-Api-Client": "gl-node/22.17.0",
1619
+ "Client-Metadata": "ideType=IDE_UNSPECIFIED,platform=PLATFORM_UNSPECIFIED,pluginType=GEMINI"
1620
+ };
1621
+ var ANTIGRAVITY_PROVIDER_ID = "google";
1622
+
1623
+ // ../core/dist/fetch-timeout.js
1624
+ var ACTIVE_FETCH_TIMEOUT_MS = 15e3;
1625
+ async function fetchWithActiveTimeout(input, init = {}, options = {}) {
1626
+ const fetchImpl = options.fetchImpl ?? globalThis.fetch;
1627
+ const timeoutMs = options.timeoutMs ?? ACTIVE_FETCH_TIMEOUT_MS;
1628
+ const timeoutSignal = AbortSignal.timeout(timeoutMs);
1629
+ const activeController = new AbortController();
1630
+ const onTimeoutAbort = () => activeController.abort(timeoutSignal.reason);
1631
+ if (timeoutSignal.aborted) {
1632
+ onTimeoutAbort();
1633
+ } else {
1634
+ timeoutSignal.addEventListener("abort", onTimeoutAbort, { once: true });
1635
+ }
1636
+ const composedSignal = init.signal ? AbortSignal.any([activeController.signal, init.signal]) : activeController.signal;
1637
+ try {
1638
+ return await fetchImpl(input, { ...init, signal: composedSignal });
1639
+ } finally {
1640
+ timeoutSignal.removeEventListener("abort", onTimeoutAbort);
1641
+ }
1642
+ }
1643
+
1644
+ // ../core/dist/antigravity/oauth.js
1645
+ var log2 = createLogger("oauth");
1646
+ function encodeState(payload) {
1647
+ return Buffer.from(JSON.stringify(payload), "utf8").toString("base64url");
1648
+ }
1649
+ function decodeState(state) {
1650
+ const normalized = state.replace(/-/g, "+").replace(/_/g, "/");
1651
+ const padded = normalized.padEnd(normalized.length + (4 - normalized.length % 4) % 4, "=");
1652
+ const json = Buffer.from(padded, "base64").toString("utf8");
1653
+ const parsed = JSON.parse(json);
1654
+ if (typeof parsed.verifier !== "string") {
1655
+ throw new Error("Missing PKCE verifier in state");
1656
+ }
1657
+ return {
1658
+ verifier: parsed.verifier,
1659
+ projectId: typeof parsed.projectId === "string" ? parsed.projectId : ""
1660
+ };
1661
+ }
1662
+ async function authorizeAntigravity(projectId = "") {
1663
+ const pkce = await generatePKCE();
1664
+ const url = new URL("https://accounts.google.com/o/oauth2/v2/auth");
1665
+ url.searchParams.set("client_id", ANTIGRAVITY_CLIENT_ID);
1666
+ url.searchParams.set("response_type", "code");
1667
+ url.searchParams.set("redirect_uri", ANTIGRAVITY_REDIRECT_URI);
1668
+ url.searchParams.set("scope", ANTIGRAVITY_SCOPES.join(" "));
1669
+ url.searchParams.set("code_challenge", pkce.challenge);
1670
+ url.searchParams.set("code_challenge_method", "S256");
1671
+ url.searchParams.set("state", encodeState({ verifier: pkce.verifier, projectId: projectId || "" }));
1672
+ url.searchParams.set("access_type", "offline");
1673
+ url.searchParams.set("prompt", "consent");
1674
+ return {
1675
+ url: url.toString(),
1676
+ verifier: pkce.verifier,
1677
+ projectId: projectId || ""
1678
+ };
1679
+ }
1680
+ async function fetchProjectID(accessToken) {
1681
+ const errors = [];
1682
+ const loadHeaders = buildAntigravityHarnessBootstrapHeaders(accessToken);
1683
+ const loadEndpoints = Array.from(/* @__PURE__ */ new Set([
1684
+ ...ANTIGRAVITY_LOAD_ENDPOINTS,
1685
+ ...ANTIGRAVITY_ENDPOINT_FALLBACKS
1686
+ ]));
1687
+ for (const baseEndpoint of loadEndpoints) {
1688
+ try {
1689
+ const url = `${baseEndpoint}/v1internal:loadCodeAssist`;
1690
+ const response = await fetchWithAgyCliTransport(url, {
1691
+ method: "POST",
1692
+ headers: loadHeaders,
1693
+ body: JSON.stringify({
1694
+ metadata: buildAntigravityLoadCodeAssistMetadata()
1695
+ })
1696
+ }, { timeoutMs: 1e4 });
1697
+ if (!response.ok) {
1698
+ const message = await response.text().catch(() => "");
1699
+ errors.push(`loadCodeAssist ${response.status} at ${baseEndpoint}${message ? `: ${message}` : ""}`);
1700
+ continue;
1701
+ }
1702
+ const data = await response.json();
1703
+ if (typeof data.cloudaicompanionProject === "string" && data.cloudaicompanionProject) {
1704
+ return data.cloudaicompanionProject;
1705
+ }
1706
+ if (data.cloudaicompanionProject && typeof data.cloudaicompanionProject.id === "string" && data.cloudaicompanionProject.id) {
1707
+ return data.cloudaicompanionProject.id;
1708
+ }
1709
+ errors.push(`loadCodeAssist missing project id at ${baseEndpoint}`);
1710
+ } catch (e) {
1711
+ errors.push(`loadCodeAssist error at ${baseEndpoint}: ${e instanceof Error ? e.message : String(e)}`);
1712
+ }
1713
+ }
1714
+ if (errors.length) {
1715
+ log2.warn("Failed to resolve Antigravity project via loadCodeAssist", {
1716
+ errors: errors.join("; ")
1717
+ });
1718
+ }
1719
+ return "";
1720
+ }
1721
+ async function exchangeAntigravity(code, state) {
1722
+ try {
1723
+ const { verifier, projectId } = decodeState(state);
1724
+ const startTime = Date.now();
1725
+ const tokenResponse = await fetchWithActiveTimeout("https://oauth2.googleapis.com/token", {
1726
+ method: "POST",
1727
+ headers: {
1728
+ "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",
1729
+ Accept: "*/*",
1730
+ "Accept-Encoding": "gzip, deflate, br",
1731
+ "User-Agent": GEMINI_CLI_HEADERS["User-Agent"]
1732
+ },
1733
+ body: new URLSearchParams({
1734
+ client_id: ANTIGRAVITY_CLIENT_ID,
1735
+ client_secret: ANTIGRAVITY_CLIENT_SECRET,
1736
+ code,
1737
+ grant_type: "authorization_code",
1738
+ redirect_uri: ANTIGRAVITY_REDIRECT_URI,
1739
+ code_verifier: verifier
1740
+ })
1741
+ });
1742
+ if (!tokenResponse.ok) {
1743
+ const errorText = await tokenResponse.text();
1744
+ return { type: "failed", error: errorText };
1745
+ }
1746
+ const tokenPayload = await tokenResponse.json();
1747
+ const userInfoResponse = await fetchWithActiveTimeout("https://www.googleapis.com/oauth2/v1/userinfo?alt=json", {
1748
+ headers: {
1749
+ Authorization: `Bearer ${tokenPayload.access_token}`,
1750
+ "User-Agent": GEMINI_CLI_HEADERS["User-Agent"]
1751
+ }
1752
+ });
1753
+ const userInfo = userInfoResponse.ok ? await userInfoResponse.json() : {};
1754
+ const refreshToken = tokenPayload.refresh_token;
1755
+ if (!refreshToken) {
1756
+ return { type: "failed", error: "Missing refresh token in response" };
1757
+ }
1758
+ let effectiveProjectId = projectId;
1759
+ if (!effectiveProjectId) {
1760
+ effectiveProjectId = await fetchProjectID(tokenPayload.access_token);
1761
+ }
1762
+ const storedRefresh = `${refreshToken}|${effectiveProjectId || ""}`;
1763
+ return {
1764
+ type: "success",
1765
+ refresh: storedRefresh,
1766
+ access: tokenPayload.access_token,
1767
+ expires: calculateTokenExpiry(startTime, tokenPayload.expires_in),
1768
+ email: userInfo.email,
1769
+ label: userInfo.name?.trim() || void 0,
1770
+ projectId: effectiveProjectId || ""
1771
+ };
1772
+ } catch (error) {
1773
+ return {
1774
+ type: "failed",
1775
+ error: error instanceof Error ? error.message : "Unknown error"
1776
+ };
1777
+ }
1778
+ }
1779
+
1780
+ // ../core/dist/project.js
1781
+ var log3 = createLogger("project");
1782
+ var PROJECT_CONTEXT_CACHE_TTL_MS = 30 * 60 * 1e3;
1783
+ var projectContextResultCache = /* @__PURE__ */ new Map();
1784
+ var projectContextPendingCache = /* @__PURE__ */ new Map();
1785
+ var provisionFailedKeys = /* @__PURE__ */ new Set();
1786
+ function buildBootstrapRequestBody(extra = {}) {
1787
+ return {
1788
+ ...extra,
1789
+ metadata: buildAntigravityLoadCodeAssistMetadata()
1790
+ };
1791
+ }
1792
+ function getDefaultTierId(allowedTiers) {
1793
+ if (!allowedTiers || allowedTiers.length === 0) {
1794
+ return void 0;
1795
+ }
1796
+ for (const tier of allowedTiers) {
1797
+ if (tier?.isDefault) {
1798
+ return tier.id;
1799
+ }
1800
+ }
1801
+ return allowedTiers[0]?.id;
1802
+ }
1803
+ function wait(ms) {
1804
+ return new Promise((resolve) => {
1805
+ setTimeout(resolve, ms);
1806
+ });
1807
+ }
1808
+ function extractManagedProjectId(payload) {
1809
+ if (!payload) {
1810
+ return void 0;
1811
+ }
1812
+ if (typeof payload.cloudaicompanionProject === "string") {
1813
+ return payload.cloudaicompanionProject;
1814
+ }
1815
+ if (payload.cloudaicompanionProject && typeof payload.cloudaicompanionProject.id === "string") {
1816
+ return payload.cloudaicompanionProject.id;
1817
+ }
1818
+ return void 0;
1819
+ }
1820
+ function getCacheKeyFromRefresh(refresh) {
1821
+ const packedRefresh = refresh?.trim();
1822
+ if (!packedRefresh)
1823
+ return void 0;
1824
+ return parseRefreshParts(packedRefresh).refreshToken.trim() || packedRefresh;
1825
+ }
1826
+ function getCacheKey(auth) {
1827
+ return getCacheKeyFromRefresh(auth.refresh);
1828
+ }
1829
+ function invalidateProjectContextCache(refresh) {
1830
+ if (!refresh) {
1831
+ projectContextPendingCache.clear();
1832
+ projectContextResultCache.clear();
1833
+ provisionFailedKeys.clear();
1834
+ return;
1835
+ }
1836
+ const cacheKey = getCacheKeyFromRefresh(refresh);
1837
+ if (!cacheKey)
1838
+ return;
1839
+ projectContextPendingCache.delete(cacheKey);
1840
+ projectContextResultCache.delete(cacheKey);
1841
+ provisionFailedKeys.delete(cacheKey);
1842
+ }
1843
+ async function loadManagedProject(accessToken, _projectId) {
1844
+ const requestBody = buildBootstrapRequestBody();
1845
+ const loadHeaders = buildAntigravityHarnessBootstrapHeaders(accessToken);
1846
+ const loadEndpoints = Array.from(/* @__PURE__ */ new Set([
1847
+ ...ANTIGRAVITY_LOAD_ENDPOINTS,
1848
+ ...ANTIGRAVITY_ENDPOINT_FALLBACKS
1849
+ ]));
1850
+ for (const baseEndpoint of loadEndpoints) {
1851
+ try {
1852
+ const response = await fetchWithAgyCliTransport(`${baseEndpoint}/v1internal:loadCodeAssist`, {
1853
+ method: "POST",
1854
+ headers: loadHeaders,
1855
+ body: JSON.stringify(requestBody)
1856
+ });
1857
+ if (!response.ok) {
1858
+ continue;
1859
+ }
1860
+ return await response.json();
1861
+ } catch (error) {
1862
+ log3.debug("Failed to load managed project", {
1863
+ endpoint: baseEndpoint,
1864
+ error: String(error)
1865
+ });
1866
+ }
1867
+ }
1868
+ return null;
1869
+ }
1870
+ async function onboardManagedProject(accessToken, tierId, projectId, attempts = 10, delayMs = 5e3) {
1871
+ const requestBody = { tierId };
1872
+ const onboardEndpoints = Array.from(/* @__PURE__ */ new Set([
1873
+ ANTIGRAVITY_ENDPOINT_PROD,
1874
+ ...ANTIGRAVITY_LOAD_ENDPOINTS,
1875
+ ...ANTIGRAVITY_ENDPOINT_FALLBACKS
1876
+ ]));
1877
+ for (const baseEndpoint of onboardEndpoints) {
1878
+ for (let attempt = 0; attempt < attempts; attempt += 1) {
1879
+ try {
1880
+ const response = await fetchWithAgyCliTransport(`${baseEndpoint}/v1internal:onboardUser`, {
1881
+ method: "POST",
1882
+ headers: buildAntigravityHarnessBootstrapHeaders(accessToken),
1883
+ body: JSON.stringify(requestBody)
1884
+ });
1885
+ if (!response.ok) {
1886
+ log3.debug("Onboard request failed", {
1887
+ endpoint: baseEndpoint,
1888
+ status: response.status,
1889
+ statusText: response.statusText
1890
+ });
1891
+ break;
1892
+ }
1893
+ const payload = await response.json();
1894
+ const managedProjectId = payload.response?.cloudaicompanionProject?.id;
1895
+ if (payload.done && managedProjectId) {
1896
+ return managedProjectId;
1897
+ }
1898
+ if (payload.done && projectId) {
1899
+ return projectId;
1900
+ }
1901
+ } catch (error) {
1902
+ log3.debug("Failed to onboard managed project", {
1903
+ endpoint: baseEndpoint,
1904
+ error: String(error)
1905
+ });
1906
+ break;
1907
+ }
1908
+ await wait(delayMs);
1909
+ }
1910
+ }
1911
+ return void 0;
1912
+ }
1913
+ async function ensureProjectContext(auth) {
1914
+ const accessToken = auth.access;
1915
+ if (!accessToken) {
1916
+ return { auth, effectiveProjectId: "" };
1917
+ }
1918
+ const cacheKey = getCacheKey(auth);
1919
+ if (cacheKey) {
1920
+ const cached = projectContextResultCache.get(cacheKey);
1921
+ if (cached && Date.now() - cached.cachedAt < PROJECT_CONTEXT_CACHE_TTL_MS) {
1922
+ return cached.result;
1923
+ }
1924
+ if (cached) {
1925
+ projectContextResultCache.delete(cacheKey);
1926
+ }
1927
+ const pending = projectContextPendingCache.get(cacheKey);
1928
+ if (pending) {
1929
+ return pending;
1930
+ }
1931
+ }
1932
+ const resolveContext = async () => {
1933
+ const parts = parseRefreshParts(auth.refresh);
1934
+ if (parts.managedProjectId) {
1935
+ return { auth, effectiveProjectId: parts.managedProjectId };
1936
+ }
1937
+ const fallbackProjectId = ANTIGRAVITY_DEFAULT_PROJECT_ID;
1938
+ if (cacheKey && provisionFailedKeys.has(cacheKey)) {
1939
+ const effectiveProjectId = parts.projectId || fallbackProjectId;
1940
+ return { auth, effectiveProjectId };
1941
+ }
1942
+ const persistManagedProject = async (managedProjectId, capturedTier) => {
1943
+ const updatedAuth = {
1944
+ ...auth,
1945
+ refresh: formatRefreshParts({
1946
+ refreshToken: parts.refreshToken,
1947
+ projectId: parts.projectId,
1948
+ managedProjectId
1949
+ })
1950
+ };
1951
+ return {
1952
+ auth: updatedAuth,
1953
+ effectiveProjectId: managedProjectId,
1954
+ capturedTier
1955
+ };
1956
+ };
1957
+ const loadPayload = await loadManagedProject(accessToken, parts.projectId ?? fallbackProjectId);
1958
+ const capturedTierId = loadPayload?.currentTier?.id;
1959
+ const paidTierId = typeof loadPayload?.paidTier === "string" ? loadPayload.paidTier : loadPayload?.paidTier?.id;
1960
+ const tierFromPayload = capturedTierId ? {
1961
+ id: capturedTierId,
1962
+ ...paidTierId ? { paidId: paidTierId } : {},
1963
+ capturedAt: Date.now()
1964
+ } : void 0;
1965
+ const resolvedManagedProjectId = extractManagedProjectId(loadPayload);
1966
+ if (resolvedManagedProjectId) {
1967
+ return persistManagedProject(resolvedManagedProjectId, tierFromPayload);
1968
+ }
1969
+ const tierId = getDefaultTierId(loadPayload?.allowedTiers) ?? "free-tier";
1970
+ log3.debug("Auto-provisioning managed project", {
1971
+ tierId,
1972
+ projectId: parts.projectId
1973
+ });
1974
+ const provisionedProjectId = await onboardManagedProject(accessToken, tierId, parts.projectId);
1975
+ if (provisionedProjectId) {
1976
+ log3.debug("Successfully provisioned managed project", {
1977
+ provisionedProjectId
1978
+ });
1979
+ return persistManagedProject(provisionedProjectId, tierFromPayload);
1980
+ }
1981
+ log3.warn("Failed to provision managed project - account may not work correctly", {
1982
+ hasProjectId: !!parts.projectId
1983
+ });
1984
+ if (cacheKey) {
1985
+ provisionFailedKeys.add(cacheKey);
1986
+ }
1987
+ if (parts.projectId) {
1988
+ return {
1989
+ auth,
1990
+ effectiveProjectId: parts.projectId,
1991
+ capturedTier: tierFromPayload
1992
+ };
1993
+ }
1994
+ return {
1995
+ auth,
1996
+ effectiveProjectId: fallbackProjectId,
1997
+ capturedTier: tierFromPayload
1998
+ };
1999
+ };
2000
+ if (!cacheKey) {
2001
+ return resolveContext();
2002
+ }
2003
+ const promise = resolveContext().then((result) => {
2004
+ const nextKey = getCacheKey(result.auth) ?? cacheKey;
2005
+ projectContextPendingCache.delete(cacheKey);
2006
+ projectContextResultCache.set(nextKey, { result, cachedAt: Date.now() });
2007
+ if (nextKey !== cacheKey) {
2008
+ projectContextResultCache.delete(cacheKey);
2009
+ }
2010
+ return result;
2011
+ }).catch((error) => {
2012
+ projectContextPendingCache.delete(cacheKey);
2013
+ throw error;
2014
+ });
2015
+ projectContextPendingCache.set(cacheKey, promise);
2016
+ return promise;
2017
+ }
2018
+
2019
+ // ../core/dist/quota-manager.js
2020
+ import { createHash } from "node:crypto";
2021
+ var log4 = createLogger("quota-manager");
2022
+ var QUOTA_MANAGER_DEFAULT_BASE_BACKOFF_MS = 3e4;
2023
+ var QUOTA_MANAGER_DEFAULT_MAX_BACKOFF_MS = 10 * 60 * 1e3;
2024
+ var QUOTA_MANAGER_DEFAULT_TIMEOUT_MS = 1e4;
2025
+ function defaultKeyOf(account) {
2026
+ if (account.email)
2027
+ return `e:${account.email.toLowerCase()}`;
2028
+ const token = account.refreshToken || "";
2029
+ return `t:${createHash("sha256").update(token).digest("hex").slice(0, 16)}`;
2030
+ }
2031
+ function createQuotaManager(options) {
2032
+ const now = options.now ?? (() => Date.now());
2033
+ const baseBackoffMs = options.baseBackoffMs ?? QUOTA_MANAGER_DEFAULT_BASE_BACKOFF_MS;
2034
+ const maxBackoffMs = options.maxBackoffMs ?? QUOTA_MANAGER_DEFAULT_MAX_BACKOFF_MS;
2035
+ const fetchTimeoutMs = options.fetchTimeoutMs ?? QUOTA_MANAGER_DEFAULT_TIMEOUT_MS;
2036
+ const state = /* @__PURE__ */ new Map();
2037
+ let disposed = false;
2038
+ const keyOf = (account) => options.keyOf(account);
2039
+ const recordSuccess = (key) => {
2040
+ const entry = state.get(key);
2041
+ if (!entry)
2042
+ return;
2043
+ entry.consecutiveFailures = 0;
2044
+ entry.backoffUntil = 0;
2045
+ };
2046
+ const recordFailure = (key) => {
2047
+ const current = now();
2048
+ const entry = state.get(key) ?? {
2049
+ consecutiveFailures: 0,
2050
+ backoffUntil: 0
2051
+ };
2052
+ const failures = entry.consecutiveFailures + 1;
2053
+ const backoffMs = Math.min(maxBackoffMs, baseBackoffMs * 2 ** (failures - 1));
2054
+ entry.consecutiveFailures = failures;
2055
+ entry.backoffUntil = current + backoffMs;
2056
+ state.set(key, entry);
2057
+ return { backoffMs, backoffUntil: entry.backoffUntil };
2058
+ };
2059
+ const cacheResult = (key, result) => {
2060
+ const entry = state.get(key) ?? {
2061
+ consecutiveFailures: 0,
2062
+ backoffUntil: 0
2063
+ };
2064
+ entry.cached = result;
2065
+ state.set(key, entry);
2066
+ };
2067
+ const buildDisabledResult = (account, index) => ({
2068
+ index,
2069
+ email: account.email,
2070
+ status: "disabled",
2071
+ disabled: true,
2072
+ quota: void 0,
2073
+ geminiCliQuota: void 0,
2074
+ updatedAccount: void 0
2075
+ });
2076
+ const buildSkippedResult = (account, index, backoffUntil) => {
2077
+ const cached = state.get(keyOf(account))?.cached;
2078
+ if (cached) {
2079
+ return { ...cached, index };
2080
+ }
2081
+ return {
2082
+ index,
2083
+ email: account.email,
2084
+ status: "error",
2085
+ error: `quota refresh skipped (backoff until ${new Date(backoffUntil).toISOString()})`
2086
+ };
2087
+ };
2088
+ const refreshAccount = async (account, refreshOptions) => {
2089
+ if (disposed) {
2090
+ return {
2091
+ index: refreshOptions.index,
2092
+ email: account.email,
2093
+ status: "error",
2094
+ error: "quota manager disposed"
2095
+ };
2096
+ }
2097
+ const { index, force = false } = refreshOptions;
2098
+ const key = keyOf(account);
2099
+ if (account.enabled === false) {
2100
+ const result = buildDisabledResult(account, index);
2101
+ cacheResult(key, result);
2102
+ return result;
2103
+ }
2104
+ const current = now();
2105
+ const entry = state.get(key);
2106
+ if (!force && entry && entry.backoffUntil > current) {
2107
+ return buildSkippedResult(account, index, entry.backoffUntil);
2108
+ }
2109
+ const inflight = entry?.inflight;
2110
+ if (inflight) {
2111
+ const cached = await inflight;
2112
+ return { ...cached, index };
2113
+ }
2114
+ const controller = new AbortController();
2115
+ const stored = state.get(key) ?? {
2116
+ consecutiveFailures: 0,
2117
+ backoffUntil: 0
2118
+ };
2119
+ stored.controller = controller;
2120
+ state.set(key, stored);
2121
+ const promise = (async () => {
2122
+ try {
2123
+ const signal = AbortSignal.timeout(fetchTimeoutMs);
2124
+ const composite = controller.signal.aborted ? controller.signal : AbortSignal.any([controller.signal, signal]);
2125
+ const result = await options.fetchAccountQuota(account, composite);
2126
+ if (controller.signal.aborted) {
2127
+ throw new Error("quota manager disposed mid-fetch");
2128
+ }
2129
+ const attributed = { ...result, index };
2130
+ cacheResult(key, attributed);
2131
+ if (result.status === "error") {
2132
+ const { backoffMs } = recordFailure(key);
2133
+ log4.debug("quota-refresh-failed", {
2134
+ key: hashKey(key),
2135
+ backoffMs,
2136
+ error: result.error ?? "attributed error result"
2137
+ });
2138
+ return attributed;
2139
+ }
2140
+ recordSuccess(key);
2141
+ return attributed;
2142
+ } catch (error) {
2143
+ const message = error instanceof Error ? error.message : String(error);
2144
+ if (disposed || controller.signal.aborted) {
2145
+ const failureResult2 = {
2146
+ index,
2147
+ email: account.email,
2148
+ status: "error",
2149
+ error: message
2150
+ };
2151
+ cacheResult(key, failureResult2);
2152
+ return failureResult2;
2153
+ }
2154
+ const { backoffMs } = recordFailure(key);
2155
+ log4.debug("quota-refresh-failed", {
2156
+ key: hashKey(key),
2157
+ backoffMs,
2158
+ error: message
2159
+ });
2160
+ const failureResult = {
2161
+ index,
2162
+ email: account.email,
2163
+ status: "error",
2164
+ error: message
2165
+ };
2166
+ cacheResult(key, failureResult);
2167
+ return failureResult;
2168
+ } finally {
2169
+ const finished = state.get(key);
2170
+ if (finished) {
2171
+ finished.inflight = void 0;
2172
+ finished.controller = void 0;
2173
+ state.set(key, finished);
2174
+ }
2175
+ }
2176
+ })();
2177
+ stored.inflight = promise;
2178
+ state.set(key, stored);
2179
+ return promise;
2180
+ };
2181
+ const refreshAccounts = async (accounts, refreshOptions) => {
2182
+ const results = [];
2183
+ for (const account of accounts) {
2184
+ const index = refreshOptions.indexFor(account);
2185
+ const result = await refreshAccount(account, {
2186
+ index,
2187
+ force: refreshOptions.force
2188
+ });
2189
+ results.push(result);
2190
+ }
2191
+ return results;
2192
+ };
2193
+ const getCached = (account) => {
2194
+ const entry = state.get(keyOf(account));
2195
+ return entry?.cached;
2196
+ };
2197
+ const getBackoffUntil = (account) => {
2198
+ return state.get(keyOf(account))?.backoffUntil ?? 0;
2199
+ };
2200
+ const hashedLogLabel = (prefix, account) => {
2201
+ const identity = typeof account === "string" ? account : keyOf(account);
2202
+ return `${prefix} ${hashKey(identity)}`;
2203
+ };
2204
+ const dispose = async () => {
2205
+ if (disposed)
2206
+ return;
2207
+ disposed = true;
2208
+ const pending = Array.from(state.values(), (entry) => entry.inflight).filter((promise) => promise != null);
2209
+ for (const [, entry] of state) {
2210
+ entry.controller?.abort();
2211
+ }
2212
+ if (pending.length > 0) {
2213
+ await Promise.allSettled(pending);
2214
+ }
2215
+ for (const [, entry] of state) {
2216
+ entry.inflight = void 0;
2217
+ }
2218
+ };
2219
+ return {
2220
+ refreshAccount,
2221
+ refreshAccounts,
2222
+ getCached,
2223
+ getBackoffUntil,
2224
+ hashedLogLabel,
2225
+ dispose,
2226
+ classifyQuotaGroup,
2227
+ aggregateQuota,
2228
+ aggregateGeminiCliQuota
2229
+ };
2230
+ }
2231
+ function hashKey(key) {
2232
+ return createHash("sha256").update(key).digest("hex").slice(0, 8);
2233
+ }
2234
+ function classifyQuotaGroup(modelName, displayName) {
2235
+ const registryGroup = getQuotaGroupForModel(modelName);
2236
+ if (registryGroup) {
2237
+ return registryGroup;
2238
+ }
2239
+ const combined = `${modelName} ${displayName ?? ""}`.toLowerCase();
2240
+ if (combined.includes("claude") || combined.includes("gpt-oss")) {
2241
+ return "non-gemini";
2242
+ }
2243
+ if (combined.includes("gemini")) {
2244
+ return "gemini";
2245
+ }
2246
+ return null;
2247
+ }
2248
+ function normalizeRemainingFraction(value) {
2249
+ if (typeof value !== "number" || !Number.isFinite(value)) {
2250
+ return 0;
2251
+ }
2252
+ if (value < 0)
2253
+ return 0;
2254
+ if (value > 1)
2255
+ return 1;
2256
+ return value;
2257
+ }
2258
+ function parseResetTime(resetTime) {
2259
+ if (!resetTime)
2260
+ return null;
2261
+ const timestamp = Date.parse(resetTime);
2262
+ if (!Number.isFinite(timestamp)) {
2263
+ return null;
2264
+ }
2265
+ return timestamp;
2266
+ }
2267
+ function aggregateQuota(models) {
2268
+ const groups = {};
2269
+ const perModel = [];
2270
+ if (!models) {
2271
+ return { groups, perModel, modelCount: 0 };
2272
+ }
2273
+ let totalCount = 0;
2274
+ for (const [modelName, entry] of Object.entries(models)) {
2275
+ const group = classifyQuotaGroup(modelName, entry.displayName ?? entry.modelName);
2276
+ const quotaInfo = entry.quotaInfo;
2277
+ const remainingFraction = quotaInfo ? normalizeRemainingFraction(quotaInfo.remainingFraction) : void 0;
2278
+ const resetTime = quotaInfo?.resetTime;
2279
+ const resetTimestamp = parseResetTime(resetTime);
2280
+ totalCount += 1;
2281
+ perModel.push({
2282
+ modelId: modelName,
2283
+ displayName: entry.displayName ?? entry.modelName,
2284
+ group,
2285
+ remainingFraction: remainingFraction ?? 0,
2286
+ resetTime
2287
+ });
2288
+ if (!group) {
2289
+ continue;
2290
+ }
2291
+ const existing = groups[group];
2292
+ const nextCount = (existing?.modelCount ?? 0) + 1;
2293
+ const nextRemaining = remainingFraction === void 0 ? existing?.remainingFraction : existing?.remainingFraction === void 0 ? remainingFraction : Math.min(existing.remainingFraction, remainingFraction);
2294
+ let nextResetTime = existing?.resetTime;
2295
+ if (resetTimestamp !== null) {
2296
+ if (!existing?.resetTime) {
2297
+ nextResetTime = resetTime;
2298
+ } else {
2299
+ const existingTimestamp = parseResetTime(existing.resetTime);
2300
+ if (existingTimestamp === null || resetTimestamp < existingTimestamp) {
2301
+ nextResetTime = resetTime;
2302
+ }
2303
+ }
2304
+ }
2305
+ groups[group] = {
2306
+ remainingFraction: nextRemaining,
2307
+ resetTime: nextResetTime,
2308
+ modelCount: nextCount
2309
+ };
2310
+ }
2311
+ perModel.sort((a, b) => a.modelId.localeCompare(b.modelId));
2312
+ return { groups, perModel, modelCount: totalCount };
2313
+ }
2314
+ function mostConstrainedWindow(windows) {
2315
+ if (windows.length === 0)
2316
+ return void 0;
2317
+ let best = windows[0];
2318
+ for (let i = 1; i < windows.length; i++) {
2319
+ if (windows[i].remainingFraction < best.remainingFraction) {
2320
+ best = windows[i];
2321
+ }
2322
+ }
2323
+ return {
2324
+ remainingFraction: best.remainingFraction,
2325
+ resetTime: best.resetTime
2326
+ };
2327
+ }
2328
+ function poolForBucketId(bucketId) {
2329
+ if (bucketId.startsWith("gemini-"))
2330
+ return "gemini";
2331
+ if (bucketId.startsWith("3p-"))
2332
+ return "non-gemini";
2333
+ return null;
2334
+ }
2335
+ function parseDescriptionModelCount(description) {
2336
+ const prefixMatch = description.match(/^[^:]+:\s*/);
2337
+ const payload = prefixMatch ? description.slice(prefixMatch[0].length) : description;
2338
+ if (!payload)
2339
+ return 0;
2340
+ const entries = payload.split(",").map((entry) => entry.trim()).filter((entry) => entry.length > 0);
2341
+ return entries.length;
2342
+ }
2343
+ function windowDurationMs(window) {
2344
+ switch (window) {
2345
+ case "5h":
2346
+ return 5 * 60 * 60 * 1e3;
2347
+ case "weekly":
2348
+ return 7 * 24 * 60 * 60 * 1e3;
2349
+ default:
2350
+ return Number.MAX_SAFE_INTEGER;
2351
+ }
2352
+ }
2353
+ function aggregateQuotaSummary(response) {
2354
+ const groups = {};
2355
+ let totalCount = 0;
2356
+ for (const group of response.groups) {
2357
+ const windows = [];
2358
+ for (const bucket of group.buckets) {
2359
+ const pool2 = poolForBucketId(bucket.bucketId);
2360
+ if (!pool2)
2361
+ continue;
2362
+ windows.push({
2363
+ window: bucket.window,
2364
+ remainingFraction: normalizeRemainingFraction(bucket.remainingFraction),
2365
+ resetTime: bucket.resetTime
2366
+ });
2367
+ }
2368
+ if (windows.length === 0)
2369
+ continue;
2370
+ windows.sort((a, b) => windowDurationMs(a.window) - windowDurationMs(b.window));
2371
+ const constrained = mostConstrainedWindow(windows);
2372
+ const recognizedBucket = group.buckets.find((bucket) => poolForBucketId(bucket.bucketId));
2373
+ if (!recognizedBucket)
2374
+ continue;
2375
+ const pool = poolForBucketId(recognizedBucket.bucketId);
2376
+ if (!pool || !constrained)
2377
+ continue;
2378
+ const modelCount = group.description ? parseDescriptionModelCount(group.description) : 0;
2379
+ groups[pool] = {
2380
+ remainingFraction: constrained.remainingFraction,
2381
+ resetTime: constrained.resetTime,
2382
+ modelCount,
2383
+ windows
2384
+ };
2385
+ totalCount += modelCount;
2386
+ }
2387
+ return { groups, modelCount: totalCount };
2388
+ }
2389
+ async function fetchQuotaSummary(options) {
2390
+ const timeoutMs = options.timeoutMs ?? QUOTA_MANAGER_DEFAULT_TIMEOUT_MS;
2391
+ const userAgent = options.userAgent ?? buildAntigravityHarnessUserAgent();
2392
+ const transport = options.fetchVia ?? defaultTransport;
2393
+ const errors = [];
2394
+ if (options.endpoints.length === 0) {
2395
+ throw new Error("No endpoints configured for fetchQuotaSummary");
2396
+ }
2397
+ const tryBody = async (endpoint, projectId) => {
2398
+ const body = { project: projectId };
2399
+ try {
2400
+ const response = await transport(`${endpoint}/v1internal:retrieveUserQuotaSummary`, {
2401
+ method: "POST",
2402
+ headers: {
2403
+ "User-Agent": userAgent,
2404
+ Authorization: `Bearer ${options.accessToken}`,
2405
+ "Content-Type": "application/json",
2406
+ "Accept-Encoding": "gzip"
2407
+ },
2408
+ body: JSON.stringify(body)
2409
+ }, { timeoutMs });
2410
+ if (response.ok) {
2411
+ return {
2412
+ ok: true,
2413
+ summary: await response.json()
2414
+ };
2415
+ }
2416
+ const status = response.status;
2417
+ if (status === 403) {
2418
+ errors.push(`retrieveUserQuotaSummary 403 at ${endpoint} (project=${projectId.slice(0, 12)}\u2026)`);
2419
+ return { ok: false, reason: "403" };
2420
+ }
2421
+ if (status === 429 || status >= 500) {
2422
+ const message2 = await response.text().catch(() => "");
2423
+ errors.push(`retrieveUserQuotaSummary ${status} at ${endpoint}${message2 ? `: ${message2.trim().slice(0, 200)}` : ""}`);
2424
+ return { ok: false, reason: "transient" };
2425
+ }
2426
+ const message = await response.text().catch(() => "");
2427
+ errors.push(`retrieveUserQuotaSummary ${status} at ${endpoint}${message ? `: ${message.trim().slice(0, 200)}` : ""}`);
2428
+ return { ok: false, reason: "transient" };
2429
+ } catch (error) {
2430
+ errors.push(`retrieveUserQuotaSummary network error at ${endpoint}: ${error instanceof Error ? error.message : String(error)}`);
2431
+ return { ok: false, reason: "transient" };
2432
+ }
2433
+ };
2434
+ const primary = options.managedProjectId ?? options.projectId;
2435
+ let primaryGot403 = false;
2436
+ if (primary) {
2437
+ for (const endpoint of options.endpoints) {
2438
+ const result = await tryBody(endpoint, primary);
2439
+ if (result.ok)
2440
+ return { summary: result.summary };
2441
+ if (result.reason === "403")
2442
+ primaryGot403 = true;
2443
+ }
2444
+ }
2445
+ const fallbackId = primaryGot403 && options.managedProjectId && options.projectId && options.managedProjectId !== options.projectId ? options.projectId : void 0;
2446
+ if (fallbackId) {
2447
+ for (const endpoint of options.endpoints) {
2448
+ const result = await tryBody(endpoint, fallbackId);
2449
+ if (result.ok)
2450
+ return { summary: result.summary };
2451
+ }
2452
+ }
2453
+ throw new Error(errors.join("; ") || "fetchQuotaSummary failed: no project ID available");
2454
+ }
2455
+ function aggregateGeminiCliQuota(response) {
2456
+ const models = [];
2457
+ if (!response.buckets || response.buckets.length === 0) {
2458
+ return { models };
2459
+ }
2460
+ for (const bucket of response.buckets) {
2461
+ if (!bucket.modelId) {
2462
+ continue;
2463
+ }
2464
+ const modelId = bucket.modelId;
2465
+ const isRelevantModel = modelId.startsWith("gemini-3-") || modelId.startsWith("gemini-3.") || modelId.startsWith("gemini-2.5-");
2466
+ if (!isRelevantModel) {
2467
+ continue;
2468
+ }
2469
+ models.push({
2470
+ modelId: bucket.modelId,
2471
+ remainingFraction: normalizeRemainingFraction(bucket.remainingFraction),
2472
+ resetTime: bucket.resetTime
2473
+ });
2474
+ }
2475
+ models.sort((a, b) => a.modelId.localeCompare(b.modelId));
2476
+ return { models };
2477
+ }
2478
+ async function fetchAvailableModels(options) {
2479
+ const timeoutMs = options.timeoutMs ?? QUOTA_MANAGER_DEFAULT_TIMEOUT_MS;
2480
+ const userAgent = options.userAgent ?? buildAntigravityHarnessUserAgent();
2481
+ const errors = [];
2482
+ const transport = options.fetchVia ?? defaultTransport;
2483
+ for (const endpoint of options.endpoints) {
2484
+ const body = options.projectId ? { project: options.projectId } : {};
2485
+ try {
2486
+ const response = await transport(`${endpoint}/v1internal:fetchAvailableModels`, {
2487
+ method: "POST",
2488
+ headers: {
2489
+ "User-Agent": userAgent,
2490
+ Authorization: `Bearer ${options.accessToken}`,
2491
+ "Content-Type": "application/json",
2492
+ "Accept-Encoding": "gzip"
2493
+ },
2494
+ body: JSON.stringify(body)
2495
+ }, { timeoutMs });
2496
+ if (response.ok) {
2497
+ return await response.json();
2498
+ }
2499
+ const status = response.status;
2500
+ if (status === 403 && options.projectId) {
2501
+ try {
2502
+ const retryResponse = await transport(`${endpoint}/v1internal:fetchAvailableModels`, {
2503
+ method: "POST",
2504
+ headers: {
2505
+ "User-Agent": userAgent,
2506
+ Authorization: `Bearer ${options.accessToken}`,
2507
+ "Content-Type": "application/json",
2508
+ "Accept-Encoding": "gzip"
2509
+ },
2510
+ body: JSON.stringify({})
2511
+ }, { timeoutMs });
2512
+ if (retryResponse.ok) {
2513
+ return await retryResponse.json();
2514
+ }
2515
+ } catch {
2516
+ }
2517
+ }
2518
+ if (status === 429 || status >= 500) {
2519
+ const message2 = await response.text().catch(() => "");
2520
+ const snippet2 = message2.trim().slice(0, 200);
2521
+ errors.push(`fetchAvailableModels ${status} at ${endpoint}${snippet2 ? `: ${snippet2}` : ""}`);
2522
+ continue;
2523
+ }
2524
+ const message = await response.text().catch(() => "");
2525
+ const snippet = message.trim().slice(0, 200);
2526
+ errors.push(`fetchAvailableModels ${status} at ${endpoint}${snippet ? `: ${snippet}` : ""}`);
2527
+ break;
2528
+ } catch (error) {
2529
+ errors.push(`fetchAvailableModels network error at ${endpoint}: ${error instanceof Error ? error.message : String(error)}`);
2530
+ }
2531
+ }
2532
+ throw new Error(errors.join("; ") || "fetchAvailableModels failed");
2533
+ }
2534
+ async function fetchGeminiCliQuota(options) {
2535
+ const timeoutMs = options.timeoutMs ?? QUOTA_MANAGER_DEFAULT_TIMEOUT_MS;
2536
+ const userAgent = options.userAgent ?? buildAntigravityHarnessUserAgent();
2537
+ const transport = options.fetchVia ?? defaultTransport;
2538
+ const errors = [];
2539
+ for (const endpoint of options.endpoints) {
2540
+ const body = options.projectId ? { project: options.projectId } : {};
2541
+ try {
2542
+ const response = await transport(`${endpoint}/v1internal:retrieveUserQuota`, {
2543
+ method: "POST",
2544
+ headers: {
2545
+ Authorization: `Bearer ${options.accessToken}`,
2546
+ "Content-Type": "application/json",
2547
+ "User-Agent": userAgent
2548
+ },
2549
+ body: JSON.stringify(body)
2550
+ }, { timeoutMs });
2551
+ if (response.ok) {
2552
+ return await response.json();
2553
+ }
2554
+ const status = response.status;
2555
+ if (status === 429 || status >= 500) {
2556
+ errors.push(`fetchGeminiCliQuota ${status} at ${endpoint}`);
2557
+ continue;
2558
+ }
2559
+ return { buckets: [] };
2560
+ } catch (error) {
2561
+ errors.push(error instanceof Error ? error.message : String(error));
2562
+ }
2563
+ }
2564
+ if (errors.length > 0) {
2565
+ throw new Error(errors.join("; ") || "fetchGeminiCliQuota failed");
2566
+ }
2567
+ return { buckets: [] };
2568
+ }
2569
+ async function defaultTransport(url, init, options) {
2570
+ return fetchWithActiveTimeout(url, init, { timeoutMs: options.timeoutMs });
2571
+ }
2572
+
2573
+ // ../core/dist/transform/model-resolver.js
2574
+ var MODEL_ALIASES = getResolverAliasMap();
2575
+
2576
+ // src/plugin/oauth-login.ts
2577
+ function expectedState(authorizationUrl) {
2578
+ try {
2579
+ return new URL(authorizationUrl).searchParams.get("state") ?? "";
2580
+ } catch {
2581
+ return "";
2582
+ }
2583
+ }
2584
+ function callbackParams(callbackUrl, expected) {
2585
+ const code = callbackUrl.searchParams.get("code");
2586
+ const state = callbackUrl.searchParams.get("state");
2587
+ if (!code || !state) throw new Error("Missing code or state in callback URL");
2588
+ if (expected && state !== expected) throw new Error("OAuth state mismatch");
2589
+ return { code, state };
2590
+ }
2591
+ async function performOAuthLogin(request, deps) {
2592
+ const listener = await deps.startListener();
2593
+ try {
2594
+ const authorization = await deps.authorize(request.projectId ?? "");
2595
+ if (!request.noBrowser && !request.isHeadless) {
2596
+ await deps.openBrowser(authorization.url);
2597
+ }
2598
+ const params = callbackParams(
2599
+ await listener.waitForCallback(),
2600
+ expectedState(authorization.url)
2601
+ );
2602
+ const result = await deps.exchange(params.code, params.state);
2603
+ if (result.type === "failed") throw new Error(result.error);
2604
+ await deps.upsert(result);
2605
+ request.accounts.push(result);
2606
+ return result;
2607
+ } finally {
2608
+ await listener.close().catch(() => {
2609
+ });
2610
+ }
2611
+ }
2612
+
2613
+ // src/plugin/storage.ts
2614
+ import {
2615
+ appendFileSync,
2616
+ copyFileSync,
2617
+ existsSync,
2618
+ promises as fs,
2619
+ mkdirSync as mkdirSync2,
2620
+ readFileSync,
2621
+ renameSync,
2622
+ unlinkSync as unlinkSync2,
2623
+ writeFileSync
2624
+ } from "node:fs";
2625
+ import { homedir as homedir2 } from "node:os";
2626
+ import { dirname as dirname3, join as join3 } from "node:path";
2627
+
2628
+ // src/plugin/debug.ts
2629
+ import {
2630
+ createWriteStream,
2631
+ mkdirSync,
2632
+ readdirSync,
2633
+ statSync,
2634
+ unlinkSync
2635
+ } from "node:fs";
2636
+ import { homedir } from "node:os";
2637
+ import { join as join2 } from "node:path";
2638
+ import { env } from "node:process";
2639
+
2640
+ // src/plugin/logging-utils.ts
2641
+ function isTruthyFlag2(flag) {
2642
+ return flag === "1" || flag?.toLowerCase() === "true";
2643
+ }
2644
+ function parseDebugLevel(flag) {
2645
+ const trimmed = flag.trim();
2646
+ if (trimmed === "2" || trimmed === "verbose") return 2;
2647
+ if (trimmed === "1" || trimmed === "true") return 1;
2648
+ return 0;
2649
+ }
2650
+ function deriveDebugPolicy(input) {
2651
+ const envDebugFlag = input.envDebugFlag ?? "";
2652
+ const debugLevel = input.configDebug ? envDebugFlag === "2" || envDebugFlag === "verbose" ? 2 : 1 : parseDebugLevel(envDebugFlag);
2653
+ const debugEnabled = debugLevel >= 1;
2654
+ const verboseEnabled = debugLevel >= 2;
2655
+ const debugTuiEnabled = debugEnabled && (input.configDebugTui || isTruthyFlag2(input.envDebugTuiFlag));
2656
+ return {
2657
+ debugLevel,
2658
+ debugEnabled,
2659
+ debugTuiEnabled,
2660
+ verboseEnabled
2661
+ };
2662
+ }
2663
+ function formatAccountLabel(email, accountIndex) {
2664
+ return email || `Account ${accountIndex + 1}`;
2665
+ }
2666
+ function writeConsoleLog2(level, ...args) {
2667
+ switch (level) {
2668
+ case "debug":
2669
+ console.debug(...args);
2670
+ break;
2671
+ case "info":
2672
+ console.info(...args);
2673
+ break;
2674
+ case "warn":
2675
+ console.warn(...args);
2676
+ break;
2677
+ case "error":
2678
+ console.error(...args);
2679
+ break;
2680
+ }
2681
+ }
2682
+
2683
+ // src/plugin/debug.ts
2684
+ var debugState = null;
2685
+ function getConfigDir() {
2686
+ const platform = process.platform;
2687
+ if (platform === "win32") {
2688
+ return join2(
2689
+ env.APPDATA || join2(homedir(), "AppData", "Roaming"),
2690
+ "opencode"
2691
+ );
2692
+ }
2693
+ const xdgConfig2 = env.XDG_CONFIG_HOME || join2(homedir(), ".config");
2694
+ return join2(xdgConfig2, "opencode");
2695
+ }
2696
+ function getLogsDir(customLogDir) {
2697
+ const logsDir = customLogDir || join2(getConfigDir(), "antigravity-logs");
2698
+ try {
2699
+ mkdirSync(logsDir, { recursive: true, mode: 448 });
2700
+ } catch {
2701
+ }
2702
+ return logsDir;
2703
+ }
2704
+ function createLogFilePath(customLogDir) {
2705
+ const logsDir = getLogsDir(customLogDir);
2706
+ cleanupOldLogs(logsDir, 25);
2707
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
2708
+ return join2(logsDir, `antigravity-debug-${timestamp}.log`);
2709
+ }
2710
+ function cleanupOldLogs(logsDir, maxFiles) {
2711
+ try {
2712
+ const files = readdirSync(logsDir).filter(
2713
+ (file) => file.startsWith("antigravity-debug-") && file.endsWith(".log")
2714
+ ).map((file) => join2(logsDir, file));
2715
+ if (files.length <= maxFiles) {
2716
+ return;
2717
+ }
2718
+ const sortedFiles = files.map((file) => ({
2719
+ file,
2720
+ mtime: statSync(file).mtimeMs
2721
+ })).sort((a, b) => b.mtime - a.mtime);
2722
+ for (let i = maxFiles; i < sortedFiles.length; i++) {
2723
+ try {
2724
+ unlinkSync(sortedFiles[i].file);
2725
+ } catch {
2726
+ }
2727
+ }
2728
+ } catch {
2729
+ }
2730
+ }
2731
+ function createLogWriter(filePath) {
2732
+ if (!filePath) {
2733
+ return { writer: () => {
2734
+ }, stream: null };
2735
+ }
2736
+ try {
2737
+ const stream = createWriteStream(filePath, { flags: "a", mode: 384 });
2738
+ stream.on("error", () => {
2739
+ });
2740
+ return {
2741
+ stream,
2742
+ writer: (line) => {
2743
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString();
2744
+ const formatted = `[${timestamp}] ${line}`;
2745
+ stream.write(`${formatted}
2746
+ `);
2747
+ }
2748
+ };
2749
+ } catch {
2750
+ return { writer: () => {
2751
+ }, stream: null };
2752
+ }
2753
+ }
2754
+ function getDebugState() {
2755
+ if (!debugState) {
2756
+ const { debugEnabled } = deriveDebugPolicy({
2757
+ configDebug: false,
2758
+ configDebugTui: false,
2759
+ envDebugFlag: env.OPENCODE_ANTIGRAVITY_DEBUG,
2760
+ envDebugTuiFlag: env.OPENCODE_ANTIGRAVITY_DEBUG_TUI
2761
+ });
2762
+ const debugTuiEnabled = isTruthyFlag2(env.OPENCODE_ANTIGRAVITY_DEBUG_TUI);
2763
+ const logFilePath = debugEnabled ? createLogFilePath() : void 0;
2764
+ const { writer: logWriter, stream: logStream } = createLogWriter(logFilePath);
2765
+ debugState = {
2766
+ debugEnabled,
2767
+ debugTuiEnabled,
2768
+ logFilePath,
2769
+ logWriter,
2770
+ logStream
2771
+ };
2772
+ }
2773
+ return debugState;
2774
+ }
2775
+ function isDebugTuiEnabled() {
2776
+ return getDebugState().debugTuiEnabled;
2777
+ }
2778
+ function logDebug(line) {
2779
+ getDebugState().logWriter(line);
2780
+ }
2781
+ function runWithDebugEnabled(action) {
2782
+ if (!getDebugState().debugEnabled) return;
2783
+ action();
2784
+ }
2785
+ function logQuotaStatus(accountEmail, accountIndex, quotaPercent, family) {
2786
+ runWithDebugEnabled(() => {
2787
+ const accountLabel = formatAccountLabel(accountEmail, accountIndex);
2788
+ const familyInfo = family ? ` family=${family}` : "";
2789
+ const status = quotaPercent <= 0 ? "EXHAUSTED" : quotaPercent < 20 ? "LOW" : "OK";
2790
+ logDebug(
2791
+ `[Quota] ${accountLabel} remaining=${quotaPercent.toFixed(1)}% status=${status}${familyInfo}`
2792
+ );
2793
+ });
2794
+ }
2795
+ function logQuotaFetch(event, accountCount, details) {
2796
+ runWithDebugEnabled(() => {
2797
+ const countInfo = accountCount !== void 0 ? ` accounts=${accountCount}` : "";
2798
+ const detailsInfo = details ? ` ${details}` : "";
2799
+ logDebug(`[QuotaFetch] ${event.toUpperCase()}${countInfo}${detailsInfo}`);
2800
+ });
2801
+ }
2802
+
2803
+ // src/plugin/logger.ts
2804
+ var ENV_CONSOLE_LOG2 = "OPENCODE_ANTIGRAVITY_CONSOLE_LOG";
2805
+ var LEVEL_PRIORITY = {
2806
+ debug: 0,
2807
+ info: 1,
2808
+ warn: 2,
2809
+ error: 3
2810
+ };
2811
+ var _client = null;
2812
+ var _configuredLevel = "debug";
2813
+ function shouldEmit(level) {
2814
+ return LEVEL_PRIORITY[level] >= LEVEL_PRIORITY[_configuredLevel];
2815
+ }
2816
+ function emitLog(service, level, message, extra) {
2817
+ if (!shouldEmit(level)) return;
2818
+ if (isDebugTuiEnabled()) {
2819
+ const app = _client?.app;
2820
+ if (app && typeof app.log === "function") {
2821
+ app.log({
2822
+ body: { service, level, message, extra }
2823
+ }).catch(() => {
2824
+ });
2825
+ }
2826
+ }
2827
+ if (isConsoleLogEnabled2()) {
2828
+ const prefix = `[${service}]`;
2829
+ const args = extra ? [prefix, message, extra] : [prefix, message];
2830
+ writeConsoleLog2(level, ...args);
2831
+ }
2832
+ }
2833
+ function isConsoleLogEnabled2() {
2834
+ return isTruthyFlag2(process.env[ENV_CONSOLE_LOG2]);
2835
+ }
2836
+ function createLogger2(module) {
2837
+ const service = `antigravity.${module}`;
2838
+ const log8 = (level, message, extra) => {
2839
+ emitLog(service, level, message, extra);
2840
+ };
2841
+ return {
2842
+ debug: (message, extra) => log8("debug", message, extra),
2843
+ info: (message, extra) => log8("info", message, extra),
2844
+ warn: (message, extra) => log8("warn", message, extra),
2845
+ error: (message, extra) => log8("error", message, extra)
2846
+ };
2847
+ }
2848
+
2849
+ // src/plugin/storage.ts
2850
+ var log5 = createLogger2("storage");
2851
+ var GITIGNORE_ENTRIES = [
2852
+ "antigravity-accounts.json",
2853
+ "antigravity-accounts.json.*.tmp",
2854
+ "antigravity-signature-cache.json",
2855
+ "antigravity-logs/"
2856
+ ];
2857
+ async function ensureGitignore(configDir) {
2858
+ const gitignorePath = join3(configDir, ".gitignore");
2859
+ try {
2860
+ let content;
2861
+ let existingLines = [];
2862
+ try {
2863
+ content = await fs.readFile(gitignorePath, "utf-8");
2864
+ existingLines = content.split("\n").map((line) => line.trim());
2865
+ } catch (error) {
2866
+ if (error.code !== "ENOENT") {
2867
+ return;
2868
+ }
2869
+ content = "";
2870
+ }
2871
+ const missingEntries = GITIGNORE_ENTRIES.filter(
2872
+ (entry) => !existingLines.includes(entry)
2873
+ );
2874
+ if (missingEntries.length === 0) {
2875
+ return;
2876
+ }
2877
+ if (content === "") {
2878
+ await fs.writeFile(
2879
+ gitignorePath,
2880
+ `${missingEntries.join("\n")}
2881
+ `,
2882
+ "utf-8"
2883
+ );
2884
+ log5.info("Created .gitignore in config directory");
2885
+ } else {
2886
+ const suffix = content.endsWith("\n") ? "" : "\n";
2887
+ await fs.appendFile(
2888
+ gitignorePath,
2889
+ `${suffix + missingEntries.join("\n")}
2890
+ `,
2891
+ "utf-8"
2892
+ );
2893
+ log5.info("Updated .gitignore with missing entries", {
2894
+ added: missingEntries
2895
+ });
2896
+ }
2897
+ } catch (error) {
2898
+ log5.warn("Failed to update .gitignore with account storage entries", {
2899
+ error: String(error)
2900
+ });
2901
+ }
2902
+ }
2903
+ function getLegacyWindowsConfigDir() {
2904
+ return join3(
2905
+ process.env.APPDATA || join3(homedir2(), "AppData", "Roaming"),
2906
+ "opencode"
2907
+ );
2908
+ }
2909
+ function getConfigDir2() {
2910
+ if (process.env.OPENCODE_CONFIG_DIR) {
2911
+ return process.env.OPENCODE_CONFIG_DIR;
2912
+ }
2913
+ const xdgConfig2 = process.env.XDG_CONFIG_HOME || join3(homedir2(), ".config");
2914
+ return join3(xdgConfig2, "opencode");
2915
+ }
2916
+ function migrateLegacyWindowsConfig() {
2917
+ if (process.platform !== "win32") {
2918
+ return false;
2919
+ }
2920
+ const newPath = join3(getConfigDir2(), "antigravity-accounts.json");
2921
+ const legacyPath = join3(
2922
+ getLegacyWindowsConfigDir(),
2923
+ "antigravity-accounts.json"
2924
+ );
2925
+ if (!existsSync(legacyPath) || existsSync(newPath)) {
2926
+ return false;
2927
+ }
2928
+ try {
2929
+ const newConfigDir = getConfigDir2();
2930
+ mkdirSync2(newConfigDir, { recursive: true });
2931
+ try {
2932
+ renameSync(legacyPath, newPath);
2933
+ log5.info("Migrated Windows config via rename", {
2934
+ from: legacyPath,
2935
+ to: newPath
2936
+ });
2937
+ } catch {
2938
+ copyFileSync(legacyPath, newPath);
2939
+ unlinkSync2(legacyPath);
2940
+ log5.info("Migrated Windows config via copy+delete", {
2941
+ from: legacyPath,
2942
+ to: newPath
2943
+ });
2944
+ }
2945
+ return true;
2946
+ } catch (error) {
2947
+ log5.warn("Failed to migrate legacy Windows config, will use legacy path", {
2948
+ legacyPath,
2949
+ newPath,
2950
+ error: String(error)
2951
+ });
2952
+ return false;
2953
+ }
2954
+ }
2955
+ function getStoragePathWithMigration() {
2956
+ const newPath = join3(getConfigDir2(), "antigravity-accounts.json");
2957
+ if (process.platform === "win32") {
2958
+ migrateLegacyWindowsConfig();
2959
+ if (!existsSync(newPath)) {
2960
+ const legacyPath = join3(
2961
+ getLegacyWindowsConfigDir(),
2962
+ "antigravity-accounts.json"
2963
+ );
2964
+ if (existsSync(legacyPath)) {
2965
+ log5.info("Using legacy Windows config path (migration failed)", {
2966
+ legacyPath,
2967
+ newPath
2968
+ });
2969
+ return legacyPath;
2970
+ }
2971
+ }
2972
+ }
2973
+ return newPath;
2974
+ }
2975
+ function getStoragePath() {
2976
+ return getStoragePathWithMigration();
2977
+ }
2978
+ async function loadAccounts() {
2979
+ const path2 = getStoragePath();
2980
+ await ensureGitignore(dirname3(path2));
2981
+ return loadAccountStorage(path2);
2982
+ }
2983
+
2984
+ // src/plugin/persist-account-pool.ts
2985
+ function clampInt(value, min, max) {
2986
+ if (!Number.isFinite(value)) {
2987
+ return min;
2988
+ }
2989
+ return Math.min(max, Math.max(min, Math.floor(value)));
2990
+ }
2991
+ function applyUpserts(current, results, replaceAll) {
2992
+ const now = Date.now();
2993
+ const accounts = replaceAll ? [] : [...current.accounts];
2994
+ const indexByRefreshToken = /* @__PURE__ */ new Map();
2995
+ const indexByEmail = /* @__PURE__ */ new Map();
2996
+ for (let i = 0; i < accounts.length; i++) {
2997
+ const acc = accounts[i];
2998
+ if (!acc) continue;
2999
+ if (acc.refreshToken) {
3000
+ indexByRefreshToken.set(acc.refreshToken, i);
3001
+ }
3002
+ if (acc.email) {
3003
+ indexByEmail.set(acc.email, i);
3004
+ }
3005
+ }
3006
+ for (const result of results) {
3007
+ const parts = parseRefreshParts(result.refresh);
3008
+ if (!parts.refreshToken) {
3009
+ continue;
3010
+ }
3011
+ const existingByEmail = result.email ? indexByEmail.get(result.email) : void 0;
3012
+ const existingByToken = indexByRefreshToken.get(parts.refreshToken);
3013
+ const existingIndex = existingByEmail ?? existingByToken;
3014
+ if (existingIndex === void 0) {
3015
+ const newIndex = accounts.length;
3016
+ indexByRefreshToken.set(parts.refreshToken, newIndex);
3017
+ if (result.email) {
3018
+ indexByEmail.set(result.email, newIndex);
3019
+ }
3020
+ accounts.push({
3021
+ email: result.email,
3022
+ label: result.label,
3023
+ refreshToken: parts.refreshToken,
3024
+ projectId: parts.projectId,
3025
+ managedProjectId: parts.managedProjectId,
3026
+ addedAt: now,
3027
+ lastUsed: now,
3028
+ enabled: true
3029
+ });
3030
+ continue;
3031
+ }
3032
+ const existing = accounts[existingIndex];
3033
+ if (!existing) continue;
3034
+ const oldToken = existing.refreshToken;
3035
+ accounts[existingIndex] = {
3036
+ ...existing,
3037
+ email: result.email ?? existing.email,
3038
+ label: result.label ?? existing.label,
3039
+ refreshToken: parts.refreshToken,
3040
+ projectId: parts.projectId ?? existing.projectId,
3041
+ managedProjectId: parts.managedProjectId ?? existing.managedProjectId,
3042
+ lastUsed: now
3043
+ };
3044
+ if (oldToken !== parts.refreshToken) {
3045
+ indexByRefreshToken.delete(oldToken);
3046
+ indexByRefreshToken.set(parts.refreshToken, existingIndex);
3047
+ }
3048
+ }
3049
+ if (accounts.length === 0) {
3050
+ return void 0;
3051
+ }
3052
+ const activeIndex = replaceAll ? 0 : typeof current.activeIndex === "number" && Number.isFinite(current.activeIndex) ? current.activeIndex : 0;
3053
+ const clamped = clampInt(activeIndex, 0, accounts.length - 1);
3054
+ return {
3055
+ version: 4,
3056
+ accounts,
3057
+ activeIndex: clamped,
3058
+ activeIndexByFamily: {
3059
+ claude: clamped,
3060
+ gemini: clamped
3061
+ }
3062
+ };
3063
+ }
3064
+ async function persistAccountPool(results, replaceAll = false) {
3065
+ if (results.length === 0) {
3066
+ return;
3067
+ }
3068
+ const path2 = getStoragePath();
3069
+ const emptyV4 = () => ({
3070
+ version: 4,
3071
+ accounts: [],
3072
+ activeIndex: 0
3073
+ });
3074
+ if (replaceAll) {
3075
+ await mutateAccountStorage(
3076
+ path2,
3077
+ () => applyUpserts(emptyV4(), results, true)
3078
+ );
3079
+ return;
3080
+ }
3081
+ await mutateAccountStorage(
3082
+ path2,
3083
+ (current) => applyUpserts(current, results, false)
3084
+ );
3085
+ }
3086
+
3087
+ // ../../node_modules/.bun/xdg-basedir@5.1.0/node_modules/xdg-basedir/index.js
3088
+ import os from "os";
3089
+ import path from "path";
3090
+ var homeDirectory = os.homedir();
3091
+ var { env: env2 } = process;
3092
+ var xdgData = env2.XDG_DATA_HOME || (homeDirectory ? path.join(homeDirectory, ".local", "share") : void 0);
3093
+ var xdgConfig = env2.XDG_CONFIG_HOME || (homeDirectory ? path.join(homeDirectory, ".config") : void 0);
3094
+ var xdgState = env2.XDG_STATE_HOME || (homeDirectory ? path.join(homeDirectory, ".local", "state") : void 0);
3095
+ var xdgCache = env2.XDG_CACHE_HOME || (homeDirectory ? path.join(homeDirectory, ".cache") : void 0);
3096
+ var xdgRuntime = env2.XDG_RUNTIME_DIR || void 0;
3097
+ var xdgDataDirectories = (env2.XDG_DATA_DIRS || "/usr/local/share/:/usr/share/").split(":");
3098
+ if (xdgData) {
3099
+ xdgDataDirectories.unshift(xdgData);
3100
+ }
3101
+ var xdgConfigDirectories = (env2.XDG_CONFIG_DIRS || "/etc/xdg").split(":");
3102
+ if (xdgConfig) {
3103
+ xdgConfigDirectories.unshift(xdgConfig);
3104
+ }
3105
+
3106
+ // src/sidebar-state.ts
3107
+ var ACTIVE_ROUTING_MAX_AGE_MS = 24 * 60 * 60 * 1e3;
3108
+ var sidebarWriteChain = Promise.resolve();
3109
+
3110
+ // src/plugin/cache.ts
3111
+ var authCache = /* @__PURE__ */ new Map();
3112
+ function normalizeRefreshKey(refresh) {
3113
+ const key = refresh?.trim();
3114
+ return key ? key : void 0;
3115
+ }
3116
+ function storeCachedAuth(auth) {
3117
+ const key = normalizeRefreshKey(auth.refresh);
3118
+ if (!key) {
3119
+ return;
3120
+ }
3121
+ authCache.set(key, auth);
3122
+ }
3123
+ function clearCachedAuth(refresh) {
3124
+ if (!refresh) {
3125
+ authCache.clear();
3126
+ return;
3127
+ }
3128
+ const key = normalizeRefreshKey(refresh);
3129
+ if (key) {
3130
+ authCache.delete(key);
3131
+ }
3132
+ }
3133
+ var SIGNATURE_CACHE_TTL_MS = 60 * 60 * 1e3;
3134
+
3135
+ // src/plugin/token.ts
3136
+ var log6 = createLogger2("token");
3137
+ function parseOAuthErrorPayload(text) {
3138
+ if (!text) {
3139
+ return {};
3140
+ }
3141
+ try {
3142
+ const payload = JSON.parse(text);
3143
+ if (!payload || typeof payload !== "object") {
3144
+ return { description: text };
3145
+ }
3146
+ let code;
3147
+ if (typeof payload.error === "string") {
3148
+ code = payload.error;
3149
+ } else if (payload.error && typeof payload.error === "object") {
3150
+ code = payload.error.status ?? payload.error.code;
3151
+ if (!payload.error_description && payload.error.message) {
3152
+ return { code, description: payload.error.message };
3153
+ }
3154
+ }
3155
+ const description = payload.error_description;
3156
+ if (description) {
3157
+ return { code, description };
3158
+ }
3159
+ if (payload.error && typeof payload.error === "object" && payload.error.message) {
3160
+ return { code, description: payload.error.message };
3161
+ }
3162
+ return { code };
3163
+ } catch {
3164
+ return { description: text };
3165
+ }
3166
+ }
3167
+ var AntigravityTokenRefreshError = class extends Error {
3168
+ code;
3169
+ description;
3170
+ status;
3171
+ statusText;
3172
+ constructor(options) {
3173
+ super(options.message);
3174
+ this.name = "AntigravityTokenRefreshError";
3175
+ this.code = options.code;
3176
+ this.description = options.description;
3177
+ this.status = options.status;
3178
+ this.statusText = options.statusText;
3179
+ }
3180
+ };
3181
+ async function refreshAccessToken(auth, _client2, _providerId) {
3182
+ const parts = parseRefreshParts(auth.refresh);
3183
+ if (!parts.refreshToken) {
3184
+ return void 0;
3185
+ }
3186
+ try {
3187
+ const startTime = Date.now();
3188
+ const response = await fetchWithActiveTimeout(
3189
+ "https://oauth2.googleapis.com/token",
3190
+ {
3191
+ method: "POST",
3192
+ headers: {
3193
+ "Content-Type": "application/x-www-form-urlencoded"
3194
+ },
3195
+ body: new URLSearchParams({
3196
+ grant_type: "refresh_token",
3197
+ refresh_token: parts.refreshToken,
3198
+ client_id: ANTIGRAVITY_CLIENT_ID,
3199
+ client_secret: ANTIGRAVITY_CLIENT_SECRET
3200
+ })
3201
+ }
3202
+ );
3203
+ if (!response.ok) {
3204
+ let errorText;
3205
+ try {
3206
+ errorText = await response.text();
3207
+ } catch {
3208
+ errorText = void 0;
3209
+ }
3210
+ const { code, description } = parseOAuthErrorPayload(errorText);
3211
+ const details = [code, description ?? errorText].filter(Boolean).join(": ");
3212
+ const baseMessage = `Antigravity token refresh failed (${response.status} ${response.statusText})`;
3213
+ const message = details ? `${baseMessage} - ${details}` : baseMessage;
3214
+ log6.warn("Token refresh failed", {
3215
+ status: response.status,
3216
+ code,
3217
+ details
3218
+ });
3219
+ if (code === "invalid_grant") {
3220
+ log6.warn(
3221
+ "Google revoked the stored refresh token - reauthentication required"
3222
+ );
3223
+ invalidateProjectContextCache(auth.refresh);
3224
+ clearCachedAuth(auth.refresh);
3225
+ }
3226
+ throw new AntigravityTokenRefreshError({
3227
+ message,
3228
+ code,
3229
+ description: description ?? errorText,
3230
+ status: response.status,
3231
+ statusText: response.statusText
3232
+ });
3233
+ }
3234
+ const payload = await response.json();
3235
+ const refreshedParts = {
3236
+ refreshToken: payload.refresh_token ?? parts.refreshToken,
3237
+ projectId: parts.projectId,
3238
+ managedProjectId: parts.managedProjectId
3239
+ };
3240
+ const updatedAuth = {
3241
+ ...auth,
3242
+ access: payload.access_token,
3243
+ expires: calculateTokenExpiry(startTime, payload.expires_in),
3244
+ refresh: formatRefreshParts(refreshedParts)
3245
+ };
3246
+ storeCachedAuth(updatedAuth);
3247
+ return updatedAuth;
3248
+ } catch (error) {
3249
+ if (error instanceof AntigravityTokenRefreshError) {
3250
+ throw error;
3251
+ }
3252
+ log6.error("Unexpected token refresh error", { error: String(error) });
3253
+ return void 0;
3254
+ }
3255
+ }
3256
+
3257
+ // src/plugin/quota.ts
3258
+ var log7 = createLogger2("quota");
3259
+ async function checkAccountsQuotaWith(accounts, fetchAccountQuota) {
3260
+ const manager = createQuotaManager({
3261
+ fetchAccountQuota,
3262
+ keyOf: defaultKeyOf
3263
+ });
3264
+ try {
3265
+ return await manager.refreshAccounts(accounts, {
3266
+ indexFor: (account) => accounts.indexOf(account),
3267
+ force: true
3268
+ });
3269
+ } finally {
3270
+ manager.dispose();
3271
+ }
3272
+ }
3273
+ async function checkAccountsQuotaStandalone(accounts, options) {
3274
+ if (!options.refresh) {
3275
+ return accounts.map((account, index) => ({
3276
+ index,
3277
+ email: account.email,
3278
+ status: account.enabled === false ? "disabled" : "ok",
3279
+ disabled: account.enabled === false,
3280
+ quota: {
3281
+ groups: account.cachedQuota ?? {},
3282
+ modelCount: Object.keys(account.cachedQuota ?? {}).length
3283
+ }
3284
+ }));
3285
+ }
3286
+ return checkAccountsQuotaWith(
3287
+ accounts,
3288
+ makeFetchAccountQuota(void 0, ANTIGRAVITY_PROVIDER_ID)
3289
+ );
3290
+ }
3291
+ async function fetchLegacyModelsFallback(options) {
3292
+ try {
3293
+ const modelsResponse = await fetchAvailableModels({
3294
+ accessToken: options.accessToken,
3295
+ projectId: options.projectId,
3296
+ endpoints: ANTIGRAVITY_ENDPOINT_FALLBACKS,
3297
+ userAgent: buildAntigravityHarnessUserAgent(),
3298
+ timeoutMs: 1e4,
3299
+ ...options.fetchVia ? { fetchVia: options.fetchVia } : {}
3300
+ });
3301
+ if (modelsResponse.models) {
3302
+ return aggregateQuota(modelsResponse.models);
3303
+ }
3304
+ return {
3305
+ groups: {},
3306
+ modelCount: 0,
3307
+ error: "Failed to fetch Antigravity quota (legacy fallback)"
3308
+ };
3309
+ } catch {
3310
+ return {
3311
+ groups: {},
3312
+ modelCount: 0,
3313
+ error: "Failed to fetch Antigravity quota"
3314
+ };
3315
+ }
3316
+ }
3317
+ function makeFetchAccountQuota(client, providerId, fetchVia) {
3318
+ return async (account, signal) => {
3319
+ const index = 0;
3320
+ const disabled = account.enabled === false;
3321
+ if (disabled) {
3322
+ return {
3323
+ index,
3324
+ email: account.email,
3325
+ status: "disabled",
3326
+ disabled: true
3327
+ };
3328
+ }
3329
+ if (signal.aborted) {
3330
+ return {
3331
+ index,
3332
+ email: account.email,
3333
+ status: "error",
3334
+ error: signal.reason instanceof Error ? signal.reason.message : "aborted"
3335
+ };
3336
+ }
3337
+ let auth = buildAuthFromAccount(account);
3338
+ let rotatedRefresh;
3339
+ try {
3340
+ if (accessTokenExpired(auth)) {
3341
+ const refreshed = await refreshAccessToken(
3342
+ auth,
3343
+ client,
3344
+ providerId
3345
+ );
3346
+ if (!refreshed) {
3347
+ throw new Error("Token refresh failed");
3348
+ }
3349
+ if (refreshed.refresh !== auth.refresh) {
3350
+ rotatedRefresh = refreshed.refresh;
3351
+ }
3352
+ auth = refreshed;
3353
+ }
3354
+ const projectContext = await ensureProjectContext(auth);
3355
+ auth = projectContext.auth;
3356
+ const updatedAccount = applyAccountUpdates(
3357
+ account,
3358
+ auth,
3359
+ projectContext.capturedTier
3360
+ );
3361
+ if (rotatedRefresh && client) {
3362
+ await persistRotatedRefresh(client, providerId, auth).catch(() => {
3363
+ });
3364
+ }
3365
+ let quotaResult;
3366
+ let fellBackToLegacy = false;
3367
+ const authParts = parseRefreshParts(auth.refresh);
3368
+ const managedProjectId = authParts.managedProjectId ?? account.managedProjectId;
3369
+ const fetchSummaryPayload = (async () => {
3370
+ try {
3371
+ const summaryResult = await fetchQuotaSummary({
3372
+ accessToken: auth.access ?? "",
3373
+ managedProjectId,
3374
+ projectId: projectContext.effectiveProjectId,
3375
+ endpoints: ANTIGRAVITY_ENDPOINT_FALLBACKS,
3376
+ userAgent: buildAntigravityHarnessUserAgent(),
3377
+ timeoutMs: 1e4,
3378
+ ...fetchVia ? { fetchVia } : {}
3379
+ });
3380
+ return {
3381
+ result: aggregateQuotaSummary(summaryResult.summary),
3382
+ fellBackToLegacy: summaryResult.fellBackToLegacy ?? false
3383
+ };
3384
+ } catch {
3385
+ return {
3386
+ result: await fetchLegacyModelsFallback({
3387
+ accessToken: auth.access ?? "",
3388
+ projectId: projectContext.effectiveProjectId,
3389
+ fetchVia
3390
+ }),
3391
+ fellBackToLegacy: true
3392
+ };
3393
+ }
3394
+ })();
3395
+ let geminiCliFetchError;
3396
+ const fetchGeminiCliPayload = fetchGeminiCliQuota({
3397
+ accessToken: auth.access ?? "",
3398
+ projectId: projectContext.effectiveProjectId,
3399
+ endpoints: ANTIGRAVITY_ENDPOINT_FALLBACKS,
3400
+ userAgent: buildGeminiCliUserAgent(),
3401
+ timeoutMs: 1e4,
3402
+ ...fetchVia ? { fetchVia } : {}
3403
+ }).catch((error) => {
3404
+ geminiCliFetchError = error instanceof Error ? error.message : String(error);
3405
+ log7.debug("fetchGeminiCliQuota failed", { error: geminiCliFetchError });
3406
+ return { buckets: void 0 };
3407
+ });
3408
+ const [summary, geminiCliResponse] = await Promise.all([
3409
+ fetchSummaryPayload,
3410
+ fetchGeminiCliPayload
3411
+ ]);
3412
+ quotaResult = summary.result;
3413
+ fellBackToLegacy = summary.fellBackToLegacy;
3414
+ const geminiCliQuotaResult = aggregateGeminiCliQuota(geminiCliResponse);
3415
+ const annotated = geminiCliResponse.buckets === void 0 || geminiCliResponse.buckets.length === 0 ? {
3416
+ ...geminiCliQuotaResult,
3417
+ error: (
3418
+ // A real fetch exception is a transient failure, not a
3419
+ // "no CLI configured" scenario — propagate the actual message.
3420
+ geminiCliFetchError ?? (geminiCliQuotaResult.models.length === 0 ? "No Gemini CLI quota available" : void 0)
3421
+ )
3422
+ } : geminiCliQuotaResult;
3423
+ for (const [family, groupQuota] of Object.entries(quotaResult.groups)) {
3424
+ const remainingPercent = (groupQuota.remainingFraction ?? 0) * 100;
3425
+ logQuotaStatus(account.email, index, remainingPercent, family);
3426
+ }
3427
+ const legacyTag = fellBackToLegacy ? " legacy=1" : "";
3428
+ logQuotaFetch("complete", 1, `ok=1 errors=0${legacyTag}`);
3429
+ return {
3430
+ index,
3431
+ email: account.email,
3432
+ status: "ok",
3433
+ disabled: false,
3434
+ quota: quotaResult,
3435
+ geminiCliQuota: annotated,
3436
+ updatedAccount
3437
+ };
3438
+ } catch (error) {
3439
+ logQuotaFetch(
3440
+ "error",
3441
+ void 0,
3442
+ `account=${account.email ?? index} error=${error instanceof Error ? error.message : String(error)}`
3443
+ );
3444
+ return {
3445
+ index,
3446
+ email: account.email,
3447
+ status: "error",
3448
+ error: error instanceof Error ? error.message : String(error),
3449
+ disabled: false
3450
+ };
3451
+ }
3452
+ };
3453
+ }
3454
+ function buildAuthFromAccount(account) {
3455
+ return {
3456
+ type: "oauth",
3457
+ refresh: formatRefreshParts({
3458
+ refreshToken: account.refreshToken,
3459
+ projectId: account.projectId,
3460
+ managedProjectId: account.managedProjectId
3461
+ }),
3462
+ access: void 0,
3463
+ expires: void 0
3464
+ };
3465
+ }
3466
+ function applyAccountUpdates(account, auth, capturedTier) {
3467
+ const parts = parseRefreshParts(auth.refresh);
3468
+ if (!parts.refreshToken) {
3469
+ return void 0;
3470
+ }
3471
+ const updated = {
3472
+ ...account,
3473
+ refreshToken: parts.refreshToken,
3474
+ projectId: parts.projectId ?? account.projectId,
3475
+ managedProjectId: parts.managedProjectId ?? account.managedProjectId,
3476
+ // Persist the captured tier alongside the project-context write. Only
3477
+ // present when the loadCodeAssist payload returned a non-empty currentTier.id.
3478
+ ...capturedTier ? {
3479
+ capturedTierId: capturedTier.id,
3480
+ ...capturedTier.paidId !== void 0 ? { capturedPaidTierId: capturedTier.paidId } : {},
3481
+ capturedTierAt: capturedTier.capturedAt
3482
+ } : {}
3483
+ };
3484
+ const changed = updated.refreshToken !== account.refreshToken || updated.projectId !== account.projectId || updated.managedProjectId !== account.managedProjectId || updated.capturedTierId !== account.capturedTierId || updated.capturedPaidTierId !== account.capturedPaidTierId || // capturedAt represents when the tier was LAST CONFIRMED, not when it
3485
+ // changed -- always update it on a successful observation so consumers
3486
+ // can gate staleness on that timestamp even when the id stays the same.
3487
+ capturedTier !== void 0 && updated.capturedTierAt !== account.capturedTierAt;
3488
+ return changed ? updated : void 0;
3489
+ }
3490
+ async function persistRotatedRefresh(client, providerId, auth) {
3491
+ await client.auth.set({
3492
+ path: { id: providerId },
3493
+ body: {
3494
+ type: "oauth",
3495
+ refresh: auth.refresh,
3496
+ access: auth.access ?? "",
3497
+ expires: auth.expires ?? 0
3498
+ }
3499
+ });
3500
+ }
3501
+
3502
+ // src/plugin/server.ts
3503
+ import { existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
3504
+ import { createServer } from "node:http";
3505
+ var redirectUri = new URL(ANTIGRAVITY_REDIRECT_URI);
3506
+ var callbackPath = redirectUri.pathname || "/";
3507
+ function isOrbStackDockerHost() {
3508
+ if (!existsSync2("/.dockerenv")) {
3509
+ return false;
3510
+ }
3511
+ try {
3512
+ if (existsSync2("/proc/version")) {
3513
+ const version = readFileSync2("/proc/version", "utf8").toLowerCase();
3514
+ if (version.includes("orbstack")) {
3515
+ return true;
3516
+ }
3517
+ }
3518
+ const hostname = process.env.HOSTNAME || "";
3519
+ if (hostname.startsWith("orbstack-") || hostname.endsWith(".orb") || hostname === "orbstack") {
3520
+ return true;
3521
+ }
3522
+ if (existsSync2("/etc/resolv.conf")) {
3523
+ const resolv = readFileSync2("/etc/resolv.conf", "utf8");
3524
+ if (resolv.includes("orb.local") || resolv.includes("orbstack")) {
3525
+ return true;
3526
+ }
3527
+ }
3528
+ if (process.platform === "linux" && existsSync2("/.dockerenv")) {
3529
+ if (existsSync2("/run/host-services")) {
3530
+ return true;
3531
+ }
3532
+ }
3533
+ } catch {
3534
+ }
3535
+ return false;
3536
+ }
3537
+ function isWSL() {
3538
+ if (process.platform !== "linux") return false;
3539
+ try {
3540
+ const release = readFileSync2("/proc/version", "utf8").toLowerCase();
3541
+ return release.includes("microsoft") || release.includes("wsl");
3542
+ } catch {
3543
+ return false;
3544
+ }
3545
+ }
3546
+ function isRemoteEnvironment() {
3547
+ if (process.env.SSH_CLIENT || process.env.SSH_TTY || process.env.SSH_CONNECTION) {
3548
+ return true;
3549
+ }
3550
+ if (process.env.REMOTE_CONTAINERS || process.env.CODESPACES) {
3551
+ return true;
3552
+ }
3553
+ return false;
3554
+ }
3555
+ function getBindAddress() {
3556
+ const envBind = process.env.OPENCODE_ANTIGRAVITY_OAUTH_BIND;
3557
+ if (envBind) {
3558
+ return envBind;
3559
+ }
3560
+ if (isOrbStackDockerHost()) {
3561
+ return "127.0.0.1";
3562
+ }
3563
+ if (isWSL() || isRemoteEnvironment()) {
3564
+ return "0.0.0.0";
3565
+ }
3566
+ return "127.0.0.1";
3567
+ }
3568
+ async function startOAuthListener({
3569
+ timeoutMs = 5 * 60 * 1e3
3570
+ } = {}) {
3571
+ const port = redirectUri.port ? Number.parseInt(redirectUri.port, 10) : redirectUri.protocol === "https:" ? 443 : 80;
3572
+ const origin = `${redirectUri.protocol}//${redirectUri.host}`;
3573
+ let settled = false;
3574
+ let resolveCallback;
3575
+ let rejectCallback;
3576
+ let timeoutHandle;
3577
+ const callbackPromise = new Promise((resolve, reject) => {
3578
+ resolveCallback = (url) => {
3579
+ if (settled) return;
3580
+ settled = true;
3581
+ if (timeoutHandle) clearTimeout(timeoutHandle);
3582
+ resolve(url);
3583
+ };
3584
+ rejectCallback = (error) => {
3585
+ if (settled) return;
3586
+ settled = true;
3587
+ if (timeoutHandle) clearTimeout(timeoutHandle);
3588
+ reject(error);
3589
+ };
3590
+ });
3591
+ const successResponse = `<!DOCTYPE html>
3592
+ <html lang="en">
3593
+ <head>
3594
+ <meta charset="utf-8" />
3595
+ <meta name="viewport" content="width=device-width, initial-scale=1">
3596
+ <title>Authentication Successful</title>
3597
+ <style>
3598
+ :root {
3599
+ --bg: #FAFAFA;
3600
+ --card-bg: #FFFFFF;
3601
+ --text-primary: #1F2937;
3602
+ --text-secondary: #6B7280;
3603
+ --accent: #2563EB;
3604
+ --success: #10B981;
3605
+ --border: #E5E7EB;
3606
+ }
3607
+ @media (prefers-color-scheme: dark) {
3608
+ :root {
3609
+ --bg: #111827;
3610
+ --card-bg: #1F2937;
3611
+ --text-primary: #F9FAFB;
3612
+ --text-secondary: #9CA3AF;
3613
+ --accent: #3B82F6;
3614
+ --success: #34D399;
3615
+ --border: #374151;
3616
+ }
3617
+ }
3618
+ body {
3619
+ margin: 0;
3620
+ min-height: 100vh;
3621
+ display: flex;
3622
+ align-items: center;
3623
+ justify-content: center;
3624
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
3625
+ background: var(--bg);
3626
+ color: var(--text-primary);
3627
+ padding: 1rem;
3628
+ }
3629
+ .card {
3630
+ background: var(--card-bg);
3631
+ border-radius: 16px;
3632
+ padding: 3rem 2rem;
3633
+ width: 100%;
3634
+ max-width: 400px;
3635
+ text-align: center;
3636
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
3637
+ border: 1px solid var(--border);
3638
+ }
3639
+ .icon-wrapper {
3640
+ width: 64px;
3641
+ height: 64px;
3642
+ background: rgba(16, 185, 129, 0.1);
3643
+ border-radius: 50%;
3644
+ display: flex;
3645
+ align-items: center;
3646
+ justify-content: center;
3647
+ margin: 0 auto 1.5rem;
3648
+ }
3649
+ .icon {
3650
+ width: 32px;
3651
+ height: 32px;
3652
+ color: var(--success);
3653
+ }
3654
+ h1 {
3655
+ font-size: 1.5rem;
3656
+ font-weight: 600;
3657
+ margin: 0 0 0.5rem;
3658
+ letter-spacing: -0.025em;
3659
+ }
3660
+ p {
3661
+ color: var(--text-secondary);
3662
+ font-size: 0.95rem;
3663
+ line-height: 1.5;
3664
+ margin: 0 0 2rem;
3665
+ }
3666
+ .btn {
3667
+ display: inline-flex;
3668
+ align-items: center;
3669
+ justify-content: center;
3670
+ background: var(--text-primary);
3671
+ color: var(--card-bg);
3672
+ font-weight: 500;
3673
+ padding: 0.75rem 1.5rem;
3674
+ border-radius: 8px;
3675
+ text-decoration: none;
3676
+ transition: opacity 0.2s;
3677
+ font-size: 0.95rem;
3678
+ border: none;
3679
+ cursor: pointer;
3680
+ width: 100%;
3681
+ box-sizing: border-box;
3682
+ }
3683
+ .btn:hover {
3684
+ opacity: 0.9;
3685
+ }
3686
+ .sub-text {
3687
+ margin-top: 1rem;
3688
+ font-size: 0.8rem;
3689
+ color: var(--text-secondary);
3690
+ }
3691
+ </style>
3692
+ </head>
3693
+ <body>
3694
+ <div class="card">
3695
+ <div class="icon-wrapper">
3696
+ <svg class="icon" fill="none" viewBox="0 0 24 24" stroke="currentColor">
3697
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2.5" d="M5 13l4 4L19 7" />
3698
+ </svg>
3699
+ </div>
3700
+ <h1>All set!</h1>
3701
+ <p>You've successfully authenticated with Antigravity. You can now return to Opencode.</p>
3702
+ <button class="btn" onclick="closeWindow()">Close this tab</button>
3703
+ <div class="sub-text">Usage Tip: Most browsers block auto-closing. If the button doesn't work, please close the tab manually.</div>
3704
+ </div>
3705
+ <script>
3706
+ function closeWindow() {
3707
+ window.close();
3708
+ // Fallback if window.close() is blocked
3709
+ document.querySelector('.btn').textContent = "Tab cannot be closed automatically";
3710
+ document.querySelector('.btn').style.opacity = "0.5";
3711
+ document.querySelector('.btn').style.cursor = "default";
3712
+ }
3713
+ </script>
3714
+ </body>
3715
+ </html>`;
3716
+ timeoutHandle = setTimeout(() => {
3717
+ rejectCallback(new Error("Timed out waiting for OAuth callback"));
3718
+ }, timeoutMs);
3719
+ timeoutHandle.unref?.();
3720
+ const server = createServer((request, response) => {
3721
+ if (!request.url) {
3722
+ response.writeHead(400, { "Content-Type": "text/plain" });
3723
+ response.end("Invalid request");
3724
+ return;
3725
+ }
3726
+ const url = new URL(request.url, origin);
3727
+ if (url.pathname !== callbackPath) {
3728
+ response.writeHead(404, { "Content-Type": "text/plain" });
3729
+ response.end("Not found");
3730
+ return;
3731
+ }
3732
+ response.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
3733
+ response.end(successResponse);
3734
+ resolveCallback(url);
3735
+ setImmediate(() => {
3736
+ server.close();
3737
+ });
3738
+ });
3739
+ const bindAddress = getBindAddress();
3740
+ await new Promise((resolve, reject) => {
3741
+ const handleError = (error) => {
3742
+ server.off("error", handleError);
3743
+ if (error.code === "EADDRINUSE") {
3744
+ reject(
3745
+ new Error(
3746
+ `Port ${port} is already in use. Another process is occupying this port. Please terminate the process or try again later.`
3747
+ )
3748
+ );
3749
+ return;
3750
+ }
3751
+ reject(error);
3752
+ };
3753
+ server.once("error", handleError);
3754
+ server.listen(port, bindAddress, () => {
3755
+ server.off("error", handleError);
3756
+ resolve();
3757
+ });
3758
+ });
3759
+ server.on("error", (error) => {
3760
+ rejectCallback(error instanceof Error ? error : new Error(String(error)));
3761
+ });
3762
+ return {
3763
+ waitForCallback: () => callbackPromise,
3764
+ close: () => new Promise((resolve, reject) => {
3765
+ server.close((error) => {
3766
+ if (error && error.code !== "ERR_SERVER_NOT_RUNNING") {
3767
+ reject(error);
3768
+ return;
3769
+ }
3770
+ if (!settled) {
3771
+ rejectCallback(new Error("OAuth listener closed before callback"));
3772
+ }
3773
+ resolve();
3774
+ });
3775
+ })
3776
+ };
3777
+ }
3778
+
3779
+ // src/cli.ts
3780
+ var HELP = `Usage: antigravity-auth <command> [options]
3781
+
3782
+ Commands:
3783
+ login [--project <id>] [--no-browser]
3784
+ list [--json]
3785
+ quota [--json] [--refresh]
3786
+
3787
+ Options:
3788
+ --help Show help
3789
+ `;
3790
+ function parseArgs(argv) {
3791
+ const [command, ...args] = argv;
3792
+ if (command === "--help") {
3793
+ return args.length === 0 ? { ok: true, value: { command: "help" } } : { ok: false, error: `Unknown argument: ${args[0]}` };
3794
+ }
3795
+ if (!command) return { ok: false, error: "Missing command" };
3796
+ if (command === "login") {
3797
+ let projectId;
3798
+ let noBrowser = false;
3799
+ for (let index = 0; index < args.length; index += 1) {
3800
+ const arg = args[index];
3801
+ if (arg === "--no-browser") {
3802
+ noBrowser = true;
3803
+ continue;
3804
+ }
3805
+ if (arg === "--project") {
3806
+ const value = args[index + 1];
3807
+ if (!value || value.startsWith("--")) {
3808
+ return { ok: false, error: "Missing value for --project" };
3809
+ }
3810
+ projectId = value;
3811
+ index += 1;
3812
+ continue;
3813
+ }
3814
+ return { ok: false, error: `Unknown option for login: ${arg}` };
3815
+ }
3816
+ return { ok: true, value: { command, projectId, noBrowser } };
3817
+ }
3818
+ if (command === "list") {
3819
+ let json = false;
3820
+ for (const arg of args) {
3821
+ if (arg === "--json") json = true;
3822
+ else return { ok: false, error: `Unknown option for list: ${arg}` };
3823
+ }
3824
+ return { ok: true, value: { command, json } };
3825
+ }
3826
+ if (command === "quota") {
3827
+ let json = false;
3828
+ let refresh = false;
3829
+ for (const arg of args) {
3830
+ if (arg === "--json") json = true;
3831
+ else if (arg === "--refresh") refresh = true;
3832
+ else return { ok: false, error: `Unknown option for quota: ${arg}` };
3833
+ }
3834
+ return { ok: true, value: { command, json, refresh } };
3835
+ }
3836
+ return { ok: false, error: `Unknown command: ${command}` };
3837
+ }
3838
+ function accountStatus(account) {
3839
+ if (account.enabled === false) return "disabled";
3840
+ if (account.accountIneligible) return "ineligible";
3841
+ if (account.verificationRequired) return "verification-required";
3842
+ return "active";
3843
+ }
3844
+ function accountSummary(storage) {
3845
+ return {
3846
+ accounts: (storage?.accounts ?? []).map((account, index) => ({
3847
+ index: index + 1,
3848
+ email: account.email ?? `Account ${index + 1}`,
3849
+ status: accountStatus(account)
3850
+ }))
3851
+ };
3852
+ }
3853
+ function formatTable(headers, rows) {
3854
+ const widths = headers.map(
3855
+ (header, column) => Math.max(header.length, ...rows.map((row) => row[column]?.length ?? 0))
3856
+ );
3857
+ const formatRow = (row) => row.map(
3858
+ (value, column) => column === row.length - 1 ? value : value.padEnd((widths[column] ?? value.length) + 2)
3859
+ ).join("");
3860
+ return `${[formatRow(headers), ...rows.map(formatRow)].join("\n")}
3861
+ `;
3862
+ }
3863
+ function quotaSummary(results) {
3864
+ return {
3865
+ accounts: results.map((result) => ({
3866
+ index: result.index + 1,
3867
+ email: result.email ?? `Account ${result.index + 1}`,
3868
+ status: result.status,
3869
+ ...result.error ? { error: result.error } : {},
3870
+ groups: Object.entries(result.quota?.groups ?? {}).map(
3871
+ ([name, group]) => ({
3872
+ name,
3873
+ ...typeof group.remainingFraction === "number" ? { remainingPercent: group.remainingFraction * 100 } : {},
3874
+ ...group.resetTime ? { resetTime: group.resetTime } : {}
3875
+ })
3876
+ )
3877
+ }))
3878
+ };
3879
+ }
3880
+ function formatQuotaTable(results) {
3881
+ const rows = [];
3882
+ for (const account of quotaSummary(results).accounts) {
3883
+ if (account.groups.length === 0) {
3884
+ rows.push([account.email, account.status, "-", "-", account.error ?? "-"]);
3885
+ continue;
3886
+ }
3887
+ for (const group of account.groups) {
3888
+ rows.push([
3889
+ account.email,
3890
+ account.status,
3891
+ group.name,
3892
+ group.remainingPercent === void 0 ? "-" : `${group.remainingPercent}%`,
3893
+ group.resetTime ?? "-"
3894
+ ]);
3895
+ }
3896
+ }
3897
+ return formatTable(["ACCOUNT", "STATUS", "GROUP", "REMAINING", "RESET"], rows);
3898
+ }
3899
+ async function runCli(argv, deps) {
3900
+ const parsed = parseArgs(argv);
3901
+ if (!parsed.ok) {
3902
+ deps.stderr.write(`${parsed.error}
3903
+ `);
3904
+ return 2;
3905
+ }
3906
+ if (parsed.value.command === "help") {
3907
+ deps.stdout.write(HELP);
3908
+ return 0;
3909
+ }
3910
+ try {
3911
+ if (parsed.value.command === "login") {
3912
+ const result = await deps.performLogin(
3913
+ {
3914
+ projectId: parsed.value.projectId,
3915
+ noBrowser: parsed.value.noBrowser,
3916
+ isHeadless: deps.isHeadless?.() ?? false,
3917
+ refreshAccountIndex: void 0,
3918
+ accounts: [],
3919
+ startFresh: true
3920
+ },
3921
+ deps.openBrowser
3922
+ );
3923
+ deps.stdout.write(
3924
+ `Authenticated ${result.email ?? "Antigravity account"}
3925
+ `
3926
+ );
3927
+ return 0;
3928
+ }
3929
+ const storage = await deps.loadAccounts();
3930
+ if (parsed.value.command === "list") {
3931
+ const summary = accountSummary(storage);
3932
+ deps.stdout.write(
3933
+ parsed.value.json ? `${JSON.stringify(summary)}
3934
+ ` : formatTable(
3935
+ ["INDEX", "EMAIL", "STATUS"],
3936
+ summary.accounts.map((account) => [
3937
+ String(account.index),
3938
+ account.email,
3939
+ account.status
3940
+ ])
3941
+ )
3942
+ );
3943
+ return 0;
3944
+ }
3945
+ const results = await deps.getQuota(storage?.accounts ?? [], {
3946
+ refresh: parsed.value.refresh
3947
+ });
3948
+ deps.stdout.write(
3949
+ parsed.value.json ? `${JSON.stringify(quotaSummary(results))}
3950
+ ` : formatQuotaTable(results)
3951
+ );
3952
+ return 0;
3953
+ } catch (error) {
3954
+ deps.stderr.write(
3955
+ `${error instanceof Error ? error.message : String(error)}
3956
+ `
3957
+ );
3958
+ return 1;
3959
+ }
3960
+ }
3961
+ var execFileAsync = promisify(execFile);
3962
+ async function openBrowserDefault(url) {
3963
+ if (process.platform === "win32") {
3964
+ await execFileAsync("cmd", ["/c", "start", "", url]);
3965
+ return;
3966
+ }
3967
+ await execFileAsync(process.platform === "darwin" ? "open" : "xdg-open", [
3968
+ url
3969
+ ]);
3970
+ }
3971
+ function createDefaultCliDependencies() {
3972
+ return {
3973
+ stdout: process.stdout,
3974
+ stderr: process.stderr,
3975
+ prompt: async (message) => {
3976
+ const readline = createInterface({
3977
+ input: process.stdin,
3978
+ output: process.stdout
3979
+ });
3980
+ try {
3981
+ return (await readline.question(message)).trim();
3982
+ } finally {
3983
+ readline.close();
3984
+ }
3985
+ },
3986
+ openBrowser: openBrowserDefault,
3987
+ isHeadless: () => Boolean(
3988
+ process.env.SSH_CONNECTION || process.env.SSH_CLIENT || process.env.SSH_TTY || process.env.OPENCODE_HEADLESS
3989
+ ),
3990
+ performLogin: async (request, openBrowser) => performOAuthLogin(request, {
3991
+ authorize: authorizeAntigravity,
3992
+ exchange: exchangeAntigravity,
3993
+ startListener: startOAuthListener,
3994
+ openBrowser,
3995
+ upsert: async (result) => {
3996
+ await persistAccountPool(
3997
+ [result],
3998
+ request.startFresh && request.accounts.length === 0
3999
+ );
4000
+ }
4001
+ }),
4002
+ loadAccounts,
4003
+ getQuota: (accounts, options) => checkAccountsQuotaStandalone(accounts, options)
4004
+ };
4005
+ }
4006
+ if (import.meta.main) {
4007
+ process.exitCode = await runCli(
4008
+ process.argv.slice(2),
4009
+ createDefaultCliDependencies()
4010
+ );
4011
+ }
4012
+ export {
4013
+ createDefaultCliDependencies,
4014
+ performOAuthLogin,
4015
+ runCli
4016
+ };
4017
+ //# sourceMappingURL=cli.js.map