@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.
- package/README.md +225 -569
- package/dist/cli.js +4017 -0
- package/dist/cli.js.map +7 -0
- package/dist/index.d.ts +1 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +20742 -14586
- package/dist/index.js.map +4 -4
- package/dist/src/antigravity/oauth.d.ts +1 -1
- package/dist/src/antigravity/oauth.js +1 -1
- package/dist/src/cli.d.ts +21 -0
- package/dist/src/cli.d.ts.map +1 -0
- package/dist/src/cli.js +237 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/constants.d.ts +1 -1
- package/dist/src/constants.js +1 -1
- package/dist/src/hooks/auto-update-checker/cache.d.ts.map +1 -1
- package/dist/src/hooks/auto-update-checker/cache.js +13 -13
- package/dist/src/hooks/auto-update-checker/cache.js.map +1 -1
- package/dist/src/hooks/auto-update-checker/checker.d.ts +1 -1
- package/dist/src/hooks/auto-update-checker/checker.d.ts.map +1 -1
- package/dist/src/hooks/auto-update-checker/checker.js +75 -51
- package/dist/src/hooks/auto-update-checker/checker.js.map +1 -1
- package/dist/src/hooks/auto-update-checker/constants.d.ts.map +1 -1
- package/dist/src/hooks/auto-update-checker/constants.js +12 -12
- package/dist/src/hooks/auto-update-checker/constants.js.map +1 -1
- package/dist/src/hooks/auto-update-checker/index.d.ts +6 -6
- package/dist/src/hooks/auto-update-checker/index.d.ts.map +1 -1
- package/dist/src/hooks/auto-update-checker/index.js +17 -17
- package/dist/src/hooks/auto-update-checker/index.js.map +1 -1
- package/dist/src/hooks/auto-update-checker/logging.js +2 -2
- package/dist/src/hooks/auto-update-checker/logging.js.map +1 -1
- package/dist/src/hooks/auto-update-checker/types.d.ts.map +1 -1
- package/dist/src/plugin/account-access.d.ts +99 -0
- package/dist/src/plugin/account-access.d.ts.map +1 -0
- package/dist/src/plugin/account-access.js +480 -0
- package/dist/src/plugin/account-access.js.map +1 -0
- package/dist/src/plugin/account-command-oauth.d.ts +34 -0
- package/dist/src/plugin/account-command-oauth.d.ts.map +1 -0
- package/dist/src/plugin/account-command-oauth.js +156 -0
- package/dist/src/plugin/account-command-oauth.js.map +1 -0
- package/dist/src/plugin/accounts.d.ts +7 -256
- package/dist/src/plugin/accounts.d.ts.map +1 -1
- package/dist/src/plugin/accounts.js +31 -1367
- package/dist/src/plugin/accounts.js.map +1 -1
- package/dist/src/plugin/agy-request-metadata.d.ts +1 -1
- package/dist/src/plugin/agy-request-metadata.js +1 -1
- package/dist/src/plugin/agy-transport.d.ts +1 -1
- package/dist/src/plugin/agy-transport.js +1 -1
- package/dist/src/plugin/auth-doctor.d.ts +6 -6
- package/dist/src/plugin/auth-doctor.d.ts.map +1 -1
- package/dist/src/plugin/auth-doctor.js +74 -66
- package/dist/src/plugin/auth-doctor.js.map +1 -1
- package/dist/src/plugin/auth-drift.d.ts +4 -4
- package/dist/src/plugin/auth-drift.d.ts.map +1 -1
- package/dist/src/plugin/auth-drift.js +15 -15
- package/dist/src/plugin/auth-drift.js.map +1 -1
- package/dist/src/plugin/auth-loader.d.ts +50 -0
- package/dist/src/plugin/auth-loader.d.ts.map +1 -0
- package/dist/src/plugin/auth-loader.js +225 -0
- package/dist/src/plugin/auth-loader.js.map +1 -0
- package/dist/src/plugin/auth.d.ts +1 -1
- package/dist/src/plugin/auth.js +1 -1
- package/dist/src/plugin/background-quota-refresh.d.ts +146 -0
- package/dist/src/plugin/background-quota-refresh.d.ts.map +1 -0
- package/dist/src/plugin/background-quota-refresh.js +347 -0
- package/dist/src/plugin/background-quota-refresh.js.map +1 -0
- package/dist/src/plugin/cache/index.d.ts +1 -1
- package/dist/src/plugin/cache/index.d.ts.map +1 -1
- package/dist/src/plugin/cache/index.js +1 -1
- package/dist/src/plugin/cache/index.js.map +1 -1
- package/dist/src/plugin/cache/signature-cache.d.ts +1 -1
- package/dist/src/plugin/cache/signature-cache.d.ts.map +1 -1
- package/dist/src/plugin/cache/signature-cache.js +23 -24
- package/dist/src/plugin/cache/signature-cache.js.map +1 -1
- package/dist/src/plugin/cache.d.ts +6 -5
- package/dist/src/plugin/cache.d.ts.map +1 -1
- package/dist/src/plugin/cache.js +21 -7
- package/dist/src/plugin/cache.js.map +1 -1
- package/dist/src/plugin/catalog.d.ts +23 -0
- package/dist/src/plugin/catalog.d.ts.map +1 -0
- package/dist/src/plugin/catalog.js +60 -0
- package/dist/src/plugin/catalog.js.map +1 -0
- package/dist/src/plugin/cli.d.ts +7 -7
- package/dist/src/plugin/cli.d.ts.map +1 -1
- package/dist/src/plugin/cli.js +62 -55
- package/dist/src/plugin/cli.js.map +1 -1
- package/dist/src/plugin/command-data.d.ts +329 -0
- package/dist/src/plugin/command-data.d.ts.map +1 -0
- package/dist/src/plugin/command-data.js +517 -0
- package/dist/src/plugin/command-data.js.map +1 -0
- package/dist/src/plugin/commands.d.ts +154 -0
- package/dist/src/plugin/commands.d.ts.map +1 -0
- package/dist/src/plugin/commands.js +746 -0
- package/dist/src/plugin/commands.js.map +1 -0
- package/dist/src/plugin/config/index.d.ts +2 -2
- package/dist/src/plugin/config/index.d.ts.map +1 -1
- package/dist/src/plugin/config/index.js +2 -2
- package/dist/src/plugin/config/index.js.map +1 -1
- package/dist/src/plugin/config/loader.d.ts +1 -1
- package/dist/src/plugin/config/loader.d.ts.map +1 -1
- package/dist/src/plugin/config/loader.js +18 -16
- package/dist/src/plugin/config/loader.js.map +1 -1
- package/dist/src/plugin/config/models.d.ts +2 -2
- package/dist/src/plugin/config/models.d.ts.map +1 -1
- package/dist/src/plugin/config/models.js +1 -1
- package/dist/src/plugin/config/models.js.map +1 -1
- package/dist/src/plugin/config/operator-settings-schema.d.ts +29 -0
- package/dist/src/plugin/config/operator-settings-schema.d.ts.map +1 -0
- package/dist/src/plugin/config/operator-settings-schema.js +28 -0
- package/dist/src/plugin/config/operator-settings-schema.js.map +1 -0
- package/dist/src/plugin/config/schema.d.ts +23 -2
- package/dist/src/plugin/config/schema.d.ts.map +1 -1
- package/dist/src/plugin/config/schema.js +109 -25
- package/dist/src/plugin/config/schema.js.map +1 -1
- package/dist/src/plugin/config/updater.d.ts.map +1 -1
- package/dist/src/plugin/config/updater.js +15 -15
- package/dist/src/plugin/config/updater.js.map +1 -1
- package/dist/src/plugin/config/writer.d.ts +34 -0
- package/dist/src/plugin/config/writer.d.ts.map +1 -0
- package/dist/src/plugin/config/writer.js +81 -0
- package/dist/src/plugin/config/writer.js.map +1 -0
- package/dist/src/plugin/core/streaming/index.d.ts +1 -1
- package/dist/src/plugin/core/streaming/index.d.ts.map +1 -1
- package/dist/src/plugin/core/streaming/index.js +1 -1
- package/dist/src/plugin/core/streaming/index.js.map +1 -1
- package/dist/src/plugin/core/streaming/transformer.d.ts.map +1 -1
- package/dist/src/plugin/core/streaming/transformer.js +85 -44
- package/dist/src/plugin/core/streaming/transformer.js.map +1 -1
- package/dist/src/plugin/core/streaming/types.d.ts.map +1 -1
- package/dist/src/plugin/debug.d.ts +10 -3
- package/dist/src/plugin/debug.d.ts.map +1 -1
- package/dist/src/plugin/debug.js +110 -47
- package/dist/src/plugin/debug.js.map +1 -1
- package/dist/src/plugin/dependencies.d.ts +129 -0
- package/dist/src/plugin/dependencies.d.ts.map +1 -0
- package/dist/src/plugin/dependencies.js +107 -0
- package/dist/src/plugin/dependencies.js.map +1 -0
- package/dist/src/plugin/errors.d.ts +27 -0
- package/dist/src/plugin/errors.d.ts.map +1 -1
- package/dist/src/plugin/errors.js +29 -3
- package/dist/src/plugin/errors.js.map +1 -1
- package/dist/src/plugin/event-handler.d.ts +53 -0
- package/dist/src/plugin/event-handler.d.ts.map +1 -0
- package/dist/src/plugin/event-handler.js +101 -0
- package/dist/src/plugin/event-handler.js.map +1 -0
- package/dist/src/plugin/fetch/retry-state.d.ts +61 -0
- package/dist/src/plugin/fetch/retry-state.d.ts.map +1 -0
- package/dist/src/plugin/fetch/retry-state.js +248 -0
- package/dist/src/plugin/fetch/retry-state.js.map +1 -0
- package/dist/src/plugin/fetch/warmup.d.ts +30 -0
- package/dist/src/plugin/fetch/warmup.d.ts.map +1 -0
- package/dist/src/plugin/fetch/warmup.js +76 -0
- package/dist/src/plugin/fetch/warmup.js.map +1 -0
- package/dist/src/plugin/fetch-interceptor.d.ts +59 -0
- package/dist/src/plugin/fetch-interceptor.d.ts.map +1 -0
- package/dist/src/plugin/fetch-interceptor.js +1399 -0
- package/dist/src/plugin/fetch-interceptor.js.map +1 -0
- package/dist/src/plugin/fetch-routing.d.ts +26 -0
- package/dist/src/plugin/fetch-routing.d.ts.map +1 -0
- package/dist/src/plugin/fetch-routing.js +99 -0
- package/dist/src/plugin/fetch-routing.js.map +1 -0
- package/dist/src/plugin/fingerprint.d.ts +1 -1
- package/dist/src/plugin/fingerprint.js +1 -1
- package/dist/src/plugin/gemini-dump.d.ts +5 -5
- package/dist/src/plugin/gemini-dump.d.ts.map +1 -1
- package/dist/src/plugin/gemini-dump.js +109 -55
- package/dist/src/plugin/gemini-dump.js.map +1 -1
- package/dist/src/plugin/google-search-tool.d.ts +9 -0
- package/dist/src/plugin/google-search-tool.d.ts.map +1 -0
- package/dist/src/plugin/google-search-tool.js +56 -0
- package/dist/src/plugin/google-search-tool.js.map +1 -0
- package/dist/src/plugin/image-saver.d.ts.map +1 -1
- package/dist/src/plugin/image-saver.js +16 -16
- package/dist/src/plugin/image-saver.js.map +1 -1
- package/dist/src/plugin/index.d.ts +30 -0
- package/dist/src/plugin/index.d.ts.map +1 -0
- package/dist/src/plugin/index.js +411 -0
- package/dist/src/plugin/index.js.map +1 -0
- package/dist/src/plugin/killswitch.d.ts +94 -0
- package/dist/src/plugin/killswitch.d.ts.map +1 -0
- package/dist/src/plugin/killswitch.js +197 -0
- package/dist/src/plugin/killswitch.js.map +1 -0
- package/dist/src/plugin/lifecycle.d.ts +40 -0
- package/dist/src/plugin/lifecycle.d.ts.map +1 -0
- package/dist/src/plugin/lifecycle.js +73 -0
- package/dist/src/plugin/lifecycle.js.map +1 -0
- package/dist/src/plugin/logger.d.ts +10 -1
- package/dist/src/plugin/logger.d.ts.map +1 -1
- package/dist/src/plugin/logger.js +38 -12
- package/dist/src/plugin/logger.js.map +1 -1
- package/dist/src/plugin/logging-utils.d.ts +35 -1
- package/dist/src/plugin/logging-utils.d.ts.map +1 -1
- package/dist/src/plugin/logging-utils.js +98 -15
- package/dist/src/plugin/logging-utils.js.map +1 -1
- package/dist/src/plugin/model-registry.d.ts +1 -1
- package/dist/src/plugin/model-registry.js +1 -1
- package/dist/src/plugin/oauth-login.d.ts +22 -0
- package/dist/src/plugin/oauth-login.d.ts.map +1 -0
- package/dist/src/plugin/oauth-login.js +37 -0
- package/dist/src/plugin/oauth-login.js.map +1 -0
- package/dist/src/plugin/oauth-methods.d.ts +42 -0
- package/dist/src/plugin/oauth-methods.d.ts.map +1 -0
- package/dist/src/plugin/oauth-methods.js +1276 -0
- package/dist/src/plugin/oauth-methods.js.map +1 -0
- package/dist/src/plugin/operator-settings.d.ts +40 -0
- package/dist/src/plugin/operator-settings.d.ts.map +1 -0
- package/dist/src/plugin/operator-settings.js +148 -0
- package/dist/src/plugin/operator-settings.js.map +1 -0
- package/dist/src/plugin/persist-account-pool.d.ts +37 -0
- package/dist/src/plugin/persist-account-pool.d.ts.map +1 -0
- package/dist/src/plugin/persist-account-pool.js +142 -0
- package/dist/src/plugin/persist-account-pool.js.map +1 -0
- package/dist/src/plugin/project.d.ts +1 -1
- package/dist/src/plugin/project.js +1 -1
- package/dist/src/plugin/prompt-context.d.ts.map +1 -1
- package/dist/src/plugin/prompt-context.js +11 -11
- package/dist/src/plugin/prompt-context.js.map +1 -1
- package/dist/src/plugin/quota.d.ts +138 -41
- package/dist/src/plugin/quota.d.ts.map +1 -1
- package/dist/src/plugin/quota.js +417 -285
- package/dist/src/plugin/quota.js.map +1 -1
- package/dist/src/plugin/recovery/constants.d.ts.map +1 -1
- package/dist/src/plugin/recovery/constants.js +24 -15
- package/dist/src/plugin/recovery/constants.js.map +1 -1
- package/dist/src/plugin/recovery/index.d.ts +3 -3
- package/dist/src/plugin/recovery/index.d.ts.map +1 -1
- package/dist/src/plugin/recovery/index.js +3 -3
- package/dist/src/plugin/recovery/index.js.map +1 -1
- package/dist/src/plugin/recovery/storage.d.ts +1 -1
- package/dist/src/plugin/recovery/storage.d.ts.map +1 -1
- package/dist/src/plugin/recovery/storage.js +31 -39
- package/dist/src/plugin/recovery/storage.js.map +1 -1
- package/dist/src/plugin/recovery/types.d.ts +12 -12
- package/dist/src/plugin/recovery/types.d.ts.map +1 -1
- package/dist/src/plugin/recovery.d.ts +3 -3
- package/dist/src/plugin/recovery.d.ts.map +1 -1
- package/dist/src/plugin/recovery.js +62 -58
- package/dist/src/plugin/recovery.js.map +1 -1
- package/dist/src/plugin/refresh-queue.d.ts +5 -2
- package/dist/src/plugin/refresh-queue.d.ts.map +1 -1
- package/dist/src/plugin/refresh-queue.js +37 -15
- package/dist/src/plugin/refresh-queue.js.map +1 -1
- package/dist/src/plugin/request-helpers.d.ts +1 -1
- package/dist/src/plugin/request-helpers.d.ts.map +1 -1
- package/dist/src/plugin/request-helpers.js +451 -352
- package/dist/src/plugin/request-helpers.js.map +1 -1
- package/dist/src/plugin/request.d.ts +7 -7
- package/dist/src/plugin/request.d.ts.map +1 -1
- package/dist/src/plugin/request.js +622 -384
- package/dist/src/plugin/request.js.map +1 -1
- package/dist/src/plugin/rotation.d.ts +1 -168
- package/dist/src/plugin/rotation.d.ts.map +1 -1
- package/dist/src/plugin/rotation.js +1 -327
- package/dist/src/plugin/rotation.js.map +1 -1
- package/dist/src/plugin/search.d.ts.map +1 -1
- package/dist/src/plugin/search.js +39 -35
- package/dist/src/plugin/search.js.map +1 -1
- package/dist/src/plugin/server.d.ts +1 -1
- package/dist/src/plugin/server.d.ts.map +1 -1
- package/dist/src/plugin/server.js +42 -37
- package/dist/src/plugin/server.js.map +1 -1
- package/dist/src/plugin/session-context.d.ts +2 -1
- package/dist/src/plugin/session-context.d.ts.map +1 -1
- package/dist/src/plugin/session-context.js +11 -7
- package/dist/src/plugin/session-context.js.map +1 -1
- package/dist/src/plugin/storage.d.ts +59 -120
- package/dist/src/plugin/storage.d.ts.map +1 -1
- package/dist/src/plugin/storage.js +140 -485
- package/dist/src/plugin/storage.js.map +1 -1
- package/dist/src/plugin/stores/signature-store.d.ts.map +1 -1
- package/dist/src/plugin/stores/signature-store.js.map +1 -1
- package/dist/src/plugin/thinking-recovery.d.ts.map +1 -1
- package/dist/src/plugin/thinking-recovery.js +35 -33
- package/dist/src/plugin/thinking-recovery.js.map +1 -1
- package/dist/src/plugin/token.d.ts +2 -2
- package/dist/src/plugin/token.d.ts.map +1 -1
- package/dist/src/plugin/token.js +30 -21
- package/dist/src/plugin/token.js.map +1 -1
- package/dist/src/plugin/transform/cross-model-sanitizer.d.ts +1 -1
- package/dist/src/plugin/transform/cross-model-sanitizer.js +1 -1
- package/dist/src/plugin/transform/index.d.ts +1 -1
- package/dist/src/plugin/transform/index.js +1 -1
- package/dist/src/plugin/transform/model-resolver.d.ts +1 -1
- package/dist/src/plugin/transform/model-resolver.js +1 -1
- package/dist/src/plugin/transform/types.d.ts +1 -1
- package/dist/src/plugin/transform/types.js +1 -1
- package/dist/src/plugin/types.d.ts +25 -69
- package/dist/src/plugin/types.d.ts.map +1 -1
- package/dist/src/plugin/ui/ansi.d.ts.map +1 -1
- package/dist/src/plugin/ui/ansi.js.map +1 -1
- package/dist/src/plugin/ui/auth-menu.d.ts +1 -1
- package/dist/src/plugin/ui/auth-menu.d.ts.map +1 -1
- package/dist/src/plugin/ui/auth-menu.js +84 -35
- package/dist/src/plugin/ui/auth-menu.js.map +1 -1
- package/dist/src/plugin/ui/confirm.d.ts.map +1 -1
- package/dist/src/plugin/ui/confirm.js.map +1 -1
- package/dist/src/plugin/ui/model-status.d.ts +3 -3
- package/dist/src/plugin/ui/model-status.d.ts.map +1 -1
- package/dist/src/plugin/ui/model-status.js +3 -3
- package/dist/src/plugin/ui/model-status.js.map +1 -1
- package/dist/src/plugin/ui/quota-status.d.ts +4 -4
- package/dist/src/plugin/ui/quota-status.d.ts.map +1 -1
- package/dist/src/plugin/ui/quota-status.js +49 -49
- package/dist/src/plugin/ui/quota-status.js.map +1 -1
- package/dist/src/plugin/ui/select.d.ts.map +1 -1
- package/dist/src/plugin/ui/select.js +22 -12
- package/dist/src/plugin/ui/select.js.map +1 -1
- package/dist/src/plugin/version.d.ts +1 -1
- package/dist/src/plugin/version.js +1 -1
- package/dist/src/rpc/notifications.d.ts +6 -0
- package/dist/src/rpc/notifications.d.ts.map +1 -0
- package/dist/src/rpc/notifications.js +46 -0
- package/dist/src/rpc/notifications.js.map +1 -0
- package/dist/src/rpc/port-file.d.ts +13 -0
- package/dist/src/rpc/port-file.d.ts.map +1 -0
- package/dist/src/rpc/port-file.js +109 -0
- package/dist/src/rpc/port-file.js.map +1 -0
- package/dist/src/rpc/protocol.d.ts +22 -0
- package/dist/src/rpc/protocol.d.ts.map +1 -0
- package/dist/src/rpc/protocol.js +1 -0
- package/dist/src/rpc/protocol.js.map +1 -0
- package/dist/src/rpc/rpc-client.d.ts +10 -0
- package/dist/src/rpc/rpc-client.d.ts.map +1 -0
- package/dist/src/rpc/rpc-client.js +58 -0
- package/dist/src/rpc/rpc-client.js.map +1 -0
- package/dist/src/rpc/rpc-dir.d.ts +4 -0
- package/dist/src/rpc/rpc-dir.d.ts.map +1 -0
- package/dist/src/rpc/rpc-dir.js +19 -0
- package/dist/src/rpc/rpc-dir.js.map +1 -0
- package/dist/src/rpc/rpc-server.d.ts +13 -0
- package/dist/src/rpc/rpc-server.d.ts.map +1 -0
- package/dist/src/rpc/rpc-server.js +231 -0
- package/dist/src/rpc/rpc-server.js.map +1 -0
- package/dist/src/sidebar-state.d.ts +357 -0
- package/dist/src/sidebar-state.d.ts.map +1 -0
- package/dist/src/sidebar-state.js +680 -0
- package/dist/src/sidebar-state.js.map +1 -0
- package/dist/src/tui/command-dialogs.d.ts +61 -0
- package/dist/src/tui/command-dialogs.d.ts.map +1 -0
- package/dist/src/tui/command-dialogs.js +595 -0
- package/dist/src/tui/command-dialogs.js.map +1 -0
- package/dist/src/tui/file-logger.d.ts +41 -0
- package/dist/src/tui/file-logger.d.ts.map +1 -0
- package/dist/src/tui/file-logger.js +114 -0
- package/dist/src/tui/file-logger.js.map +1 -0
- package/dist/src/tui-preferences.d.ts +40 -0
- package/dist/src/tui-preferences.d.ts.map +1 -0
- package/dist/src/tui-preferences.js +328 -0
- package/dist/src/tui-preferences.js.map +1 -0
- package/dist/src/tui.d.ts +68 -0
- package/dist/src/tui.d.ts.map +1 -0
- package/dist/src/tui.js +697 -0
- package/dist/src/tui.js.map +1 -0
- package/package.json +46 -22
- package/src/plugin/command-data.ts +931 -0
- package/src/rpc/port-file.ts +143 -0
- package/src/rpc/protocol.ts +31 -0
- package/src/rpc/rpc-client.ts +102 -0
- package/src/rpc/rpc-dir.ts +24 -0
- package/src/sidebar-state.ts +991 -0
- package/src/tui/command-dialogs.tsx +832 -0
- package/src/tui/entry.mjs +74 -0
- package/src/tui/file-logger.ts +145 -0
- package/src/tui-compiled/plugin/command-data.ts +931 -0
- package/src/tui-compiled/rpc/port-file.ts +143 -0
- package/src/tui-compiled/rpc/protocol.ts +31 -0
- package/src/tui-compiled/rpc/rpc-client.ts +102 -0
- package/src/tui-compiled/rpc/rpc-dir.ts +24 -0
- package/src/tui-compiled/sidebar-state.ts +991 -0
- package/src/tui-compiled/tui/command-dialogs.tsx +779 -0
- package/src/tui-compiled/tui/file-logger.ts +145 -0
- package/src/tui-compiled/tui-preferences.ts +416 -0
- package/src/tui-compiled/tui.tsx +1193 -0
- package/src/tui-preferences.ts +416 -0
- package/src/tui.tsx +1171 -0
- package/dist/src/plugin.d.ts +0 -48
- package/dist/src/plugin.d.ts.map +0 -1
- package/dist/src/plugin.js +0 -3311
- package/dist/src/plugin.js.map +0 -1
|
@@ -1,38 +1,53 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Host-path adapter for account storage.
|
|
3
|
+
*
|
|
4
|
+
* Resolves the on-disk path for the OpenCode config directory, handles
|
|
5
|
+
* the legacy Windows migration, and keeps the .gitignore in sync. All
|
|
6
|
+
* data operations are delegated to `@cortexkit/antigravity-auth-core`'s
|
|
7
|
+
* lock-held account-storage engine.
|
|
8
|
+
*
|
|
9
|
+
* The split keeps this module harness-specific (it knows about
|
|
10
|
+
* `OPENCODE_CONFIG_DIR`, `%APPDATA%`, and OpenCode-specific gitignore
|
|
11
|
+
* entries) while the schema, migrations, and lock semantics live in
|
|
12
|
+
* core.
|
|
13
|
+
*/
|
|
14
|
+
import { appendFileSync, copyFileSync, existsSync, promises as fs, mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync, } from 'node:fs';
|
|
15
|
+
import { homedir } from 'node:os';
|
|
16
|
+
import { dirname, join } from 'node:path';
|
|
17
|
+
import { AccountStorageUnreadableError, clearAccountStorage as coreClearAccountStorage, deduplicateAccountsByEmail as coreDeduplicateAccountsByEmail, loadAccountStorage as coreLoadAccountStorage, mergeAccountStorage as coreMergeAccountStorage, migrateV2ToV3 as coreMigrateV2ToV3, mutateAccountStorage as coreMutateAccountStorage, saveAccountStorage as coreSaveAccountStorage, saveAccountStorageReplace as coreSaveAccountStorageReplace, } from '@cortexkit/antigravity-auth-core';
|
|
18
|
+
import { createLogger } from './logger';
|
|
19
|
+
const log = createLogger('storage');
|
|
20
|
+
/**
|
|
21
|
+
* Re-export the typed unreadable-storage error so consumers can
|
|
22
|
+
* `instanceof`-check without pulling core into their own dependency
|
|
23
|
+
* graph. When the on-disk accounts file exists but cannot be parsed
|
|
24
|
+
* as a valid v4 (corrupt JSON, schema mismatch, unknown version, or
|
|
25
|
+
* an I/O error other than ENOENT), every read/write here throws this
|
|
26
|
+
* — never silently overwrites the user's data.
|
|
27
|
+
*/
|
|
28
|
+
export { AccountStorageUnreadableError };
|
|
29
|
+
/**
|
|
30
|
+
* Backward-compat re-exports for harnesses still importing
|
|
31
|
+
* `deduplicateAccountsByEmail` / `mergeAccountStorage` / `migrateV2ToV3`
|
|
32
|
+
* from `./storage`. The definitions live in core; the adapter exposes
|
|
33
|
+
* them so legacy test files compile without modification.
|
|
34
|
+
*/
|
|
35
|
+
export const deduplicateAccountsByEmail = coreDeduplicateAccountsByEmail;
|
|
36
|
+
export const mergeAccountStorage = coreMergeAccountStorage;
|
|
37
|
+
export const migrateV2ToV3 = coreMigrateV2ToV3;
|
|
38
|
+
export const mutateAccountStorage = coreMutateAccountStorage;
|
|
26
39
|
/**
|
|
27
40
|
* Files/directories that should be gitignored in the config directory.
|
|
28
41
|
* These contain sensitive data or machine-specific state.
|
|
29
42
|
*/
|
|
43
|
+
// NOTE: deliberately no ".gitignore" self-ignore entry — users who track their
|
|
44
|
+
// config dir as a git repo (with .gitignore committed) get endless working-tree
|
|
45
|
+
// drift from re-appending it, and for a tracked file the entry is a no-op anyway.
|
|
30
46
|
export const GITIGNORE_ENTRIES = [
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
"antigravity-logs/",
|
|
47
|
+
'antigravity-accounts.json',
|
|
48
|
+
'antigravity-accounts.json.*.tmp',
|
|
49
|
+
'antigravity-signature-cache.json',
|
|
50
|
+
'antigravity-logs/',
|
|
36
51
|
];
|
|
37
52
|
/**
|
|
38
53
|
* Ensures a .gitignore file exists in the config directory with entries
|
|
@@ -40,38 +55,38 @@ export const GITIGNORE_ENTRIES = [
|
|
|
40
55
|
* entries if it already exists.
|
|
41
56
|
*/
|
|
42
57
|
export async function ensureGitignore(configDir) {
|
|
43
|
-
const gitignorePath = join(configDir,
|
|
58
|
+
const gitignorePath = join(configDir, '.gitignore');
|
|
44
59
|
try {
|
|
45
60
|
let content;
|
|
46
61
|
let existingLines = [];
|
|
47
62
|
try {
|
|
48
|
-
content = await fs.readFile(gitignorePath,
|
|
49
|
-
existingLines = content.split(
|
|
63
|
+
content = await fs.readFile(gitignorePath, 'utf-8');
|
|
64
|
+
existingLines = content.split('\n').map((line) => line.trim());
|
|
50
65
|
}
|
|
51
66
|
catch (error) {
|
|
52
|
-
if (error.code !==
|
|
67
|
+
if (error.code !== 'ENOENT') {
|
|
53
68
|
return;
|
|
54
69
|
}
|
|
55
|
-
content =
|
|
70
|
+
content = '';
|
|
56
71
|
}
|
|
57
72
|
const missingEntries = GITIGNORE_ENTRIES.filter((entry) => !existingLines.includes(entry));
|
|
58
73
|
if (missingEntries.length === 0) {
|
|
59
74
|
return;
|
|
60
75
|
}
|
|
61
|
-
if (content ===
|
|
62
|
-
await fs.writeFile(gitignorePath, missingEntries.join(
|
|
63
|
-
log.info(
|
|
76
|
+
if (content === '') {
|
|
77
|
+
await fs.writeFile(gitignorePath, `${missingEntries.join('\n')}\n`, 'utf-8');
|
|
78
|
+
log.info('Created .gitignore in config directory');
|
|
64
79
|
}
|
|
65
80
|
else {
|
|
66
|
-
const suffix = content.endsWith(
|
|
67
|
-
await fs.appendFile(gitignorePath, suffix + missingEntries.join(
|
|
68
|
-
log.info(
|
|
81
|
+
const suffix = content.endsWith('\n') ? '' : '\n';
|
|
82
|
+
await fs.appendFile(gitignorePath, `${suffix + missingEntries.join('\n')}\n`, 'utf-8');
|
|
83
|
+
log.info('Updated .gitignore with missing entries', {
|
|
69
84
|
added: missingEntries,
|
|
70
85
|
});
|
|
71
86
|
}
|
|
72
87
|
}
|
|
73
88
|
catch (error) {
|
|
74
|
-
log.warn(
|
|
89
|
+
log.warn('Failed to update .gitignore with account storage entries', {
|
|
75
90
|
error: String(error),
|
|
76
91
|
});
|
|
77
92
|
}
|
|
@@ -80,35 +95,35 @@ export async function ensureGitignore(configDir) {
|
|
|
80
95
|
* Synchronous version of ensureGitignore for use in sync code paths.
|
|
81
96
|
*/
|
|
82
97
|
export function ensureGitignoreSync(configDir) {
|
|
83
|
-
const gitignorePath = join(configDir,
|
|
98
|
+
const gitignorePath = join(configDir, '.gitignore');
|
|
84
99
|
try {
|
|
85
100
|
let content;
|
|
86
101
|
let existingLines = [];
|
|
87
102
|
if (existsSync(gitignorePath)) {
|
|
88
|
-
content = readFileSync(gitignorePath,
|
|
89
|
-
existingLines = content.split(
|
|
103
|
+
content = readFileSync(gitignorePath, 'utf-8');
|
|
104
|
+
existingLines = content.split('\n').map((line) => line.trim());
|
|
90
105
|
}
|
|
91
106
|
else {
|
|
92
|
-
content =
|
|
107
|
+
content = '';
|
|
93
108
|
}
|
|
94
109
|
const missingEntries = GITIGNORE_ENTRIES.filter((entry) => !existingLines.includes(entry));
|
|
95
110
|
if (missingEntries.length === 0) {
|
|
96
111
|
return;
|
|
97
112
|
}
|
|
98
|
-
if (content ===
|
|
99
|
-
writeFileSync(gitignorePath, missingEntries.join(
|
|
100
|
-
log.info(
|
|
113
|
+
if (content === '') {
|
|
114
|
+
writeFileSync(gitignorePath, `${missingEntries.join('\n')}\n`, 'utf-8');
|
|
115
|
+
log.info('Created .gitignore in config directory');
|
|
101
116
|
}
|
|
102
117
|
else {
|
|
103
|
-
const suffix = content.endsWith(
|
|
104
|
-
appendFileSync(gitignorePath, suffix + missingEntries.join(
|
|
105
|
-
log.info(
|
|
118
|
+
const suffix = content.endsWith('\n') ? '' : '\n';
|
|
119
|
+
appendFileSync(gitignorePath, `${suffix + missingEntries.join('\n')}\n`, 'utf-8');
|
|
120
|
+
log.info('Updated .gitignore with missing entries', {
|
|
106
121
|
added: missingEntries,
|
|
107
122
|
});
|
|
108
123
|
}
|
|
109
124
|
}
|
|
110
125
|
catch (error) {
|
|
111
|
-
log.warn(
|
|
126
|
+
log.warn('Failed to update .gitignore with account storage entries', {
|
|
112
127
|
error: String(error),
|
|
113
128
|
});
|
|
114
129
|
}
|
|
@@ -118,7 +133,7 @@ export function ensureGitignoreSync(configDir) {
|
|
|
118
133
|
* Used for migration from older plugin versions.
|
|
119
134
|
*/
|
|
120
135
|
function getLegacyWindowsConfigDir() {
|
|
121
|
-
return join(process.env.APPDATA || join(homedir(),
|
|
136
|
+
return join(process.env.APPDATA || join(homedir(), 'AppData', 'Roaming'), 'opencode');
|
|
122
137
|
}
|
|
123
138
|
/**
|
|
124
139
|
* Gets the config directory path, with the following precedence:
|
|
@@ -128,13 +143,11 @@ function getLegacyWindowsConfigDir() {
|
|
|
128
143
|
* On Windows, also checks for legacy %APPDATA%\opencode path for migration.
|
|
129
144
|
*/
|
|
130
145
|
function getConfigDir() {
|
|
131
|
-
// 1. Check for explicit override via env var
|
|
132
146
|
if (process.env.OPENCODE_CONFIG_DIR) {
|
|
133
147
|
return process.env.OPENCODE_CONFIG_DIR;
|
|
134
148
|
}
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
return join(xdgConfig, "opencode");
|
|
149
|
+
const xdgConfig = process.env.XDG_CONFIG_HOME || join(homedir(), '.config');
|
|
150
|
+
return join(xdgConfig, 'opencode');
|
|
138
151
|
}
|
|
139
152
|
/**
|
|
140
153
|
* Migrates config from legacy Windows location to the new path.
|
|
@@ -142,34 +155,36 @@ function getConfigDir() {
|
|
|
142
155
|
* Returns true if migration was performed.
|
|
143
156
|
*/
|
|
144
157
|
function migrateLegacyWindowsConfig() {
|
|
145
|
-
if (process.platform !==
|
|
158
|
+
if (process.platform !== 'win32') {
|
|
146
159
|
return false;
|
|
147
160
|
}
|
|
148
|
-
const newPath = join(getConfigDir(),
|
|
149
|
-
const legacyPath = join(getLegacyWindowsConfigDir(),
|
|
150
|
-
// Only migrate if legacy exists and new doesn't
|
|
161
|
+
const newPath = join(getConfigDir(), 'antigravity-accounts.json');
|
|
162
|
+
const legacyPath = join(getLegacyWindowsConfigDir(), 'antigravity-accounts.json');
|
|
151
163
|
if (!existsSync(legacyPath) || existsSync(newPath)) {
|
|
152
164
|
return false;
|
|
153
165
|
}
|
|
154
166
|
try {
|
|
155
|
-
// Ensure new config directory exists
|
|
156
167
|
const newConfigDir = getConfigDir();
|
|
157
168
|
mkdirSync(newConfigDir, { recursive: true });
|
|
158
|
-
// Try rename first (atomic, but fails across filesystems)
|
|
159
169
|
try {
|
|
160
170
|
renameSync(legacyPath, newPath);
|
|
161
|
-
log.info(
|
|
171
|
+
log.info('Migrated Windows config via rename', {
|
|
172
|
+
from: legacyPath,
|
|
173
|
+
to: newPath,
|
|
174
|
+
});
|
|
162
175
|
}
|
|
163
176
|
catch {
|
|
164
|
-
// Fallback: copy then delete (for cross-filesystem moves)
|
|
165
177
|
copyFileSync(legacyPath, newPath);
|
|
166
178
|
unlinkSync(legacyPath);
|
|
167
|
-
log.info(
|
|
179
|
+
log.info('Migrated Windows config via copy+delete', {
|
|
180
|
+
from: legacyPath,
|
|
181
|
+
to: newPath,
|
|
182
|
+
});
|
|
168
183
|
}
|
|
169
184
|
return true;
|
|
170
185
|
}
|
|
171
186
|
catch (error) {
|
|
172
|
-
log.warn(
|
|
187
|
+
log.warn('Failed to migrate legacy Windows config, will use legacy path', {
|
|
173
188
|
legacyPath,
|
|
174
189
|
newPath,
|
|
175
190
|
error: String(error),
|
|
@@ -182,15 +197,13 @@ function migrateLegacyWindowsConfig() {
|
|
|
182
197
|
* On Windows, attempts to move legacy config to new path for alignment.
|
|
183
198
|
*/
|
|
184
199
|
function getStoragePathWithMigration() {
|
|
185
|
-
const newPath = join(getConfigDir(),
|
|
186
|
-
|
|
187
|
-
if (process.platform === "win32") {
|
|
200
|
+
const newPath = join(getConfigDir(), 'antigravity-accounts.json');
|
|
201
|
+
if (process.platform === 'win32') {
|
|
188
202
|
migrateLegacyWindowsConfig();
|
|
189
|
-
// If migration failed and legacy still exists, fall back to it
|
|
190
203
|
if (!existsSync(newPath)) {
|
|
191
|
-
const legacyPath = join(getLegacyWindowsConfigDir(),
|
|
204
|
+
const legacyPath = join(getLegacyWindowsConfigDir(), 'antigravity-accounts.json');
|
|
192
205
|
if (existsSync(legacyPath)) {
|
|
193
|
-
log.info(
|
|
206
|
+
log.info('Using legacy Windows config path (migration failed)', {
|
|
194
207
|
legacyPath,
|
|
195
208
|
newPath,
|
|
196
209
|
});
|
|
@@ -207,443 +220,85 @@ export function getStoragePath() {
|
|
|
207
220
|
* Gets the config directory path. Exported for use by other modules.
|
|
208
221
|
*/
|
|
209
222
|
export { getConfigDir };
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
},
|
|
218
|
-
};
|
|
219
|
-
/**
|
|
220
|
-
* Ensures the file has secure permissions (0600) on POSIX systems.
|
|
221
|
-
* This is a best-effort operation and ignores errors on Windows/unsupported FS.
|
|
222
|
-
*/
|
|
223
|
-
async function ensureSecurePermissions(path) {
|
|
224
|
-
try {
|
|
225
|
-
await fs.chmod(path, 0o600);
|
|
226
|
-
}
|
|
227
|
-
catch {
|
|
228
|
-
// Ignore errors (e.g. Windows, file doesn't exist, FS doesn't support chmod)
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
async function ensureFileExists(path) {
|
|
232
|
-
try {
|
|
233
|
-
await fs.access(path);
|
|
234
|
-
}
|
|
235
|
-
catch {
|
|
236
|
-
await fs.mkdir(dirname(path), { recursive: true });
|
|
237
|
-
await fs.writeFile(path, JSON.stringify({ version: 4, accounts: [], activeIndex: 0 }, null, 2), { encoding: "utf-8", mode: 0o600 });
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
async function withFileLock(path, fn) {
|
|
241
|
-
await ensureFileExists(path);
|
|
242
|
-
let release = null;
|
|
243
|
-
try {
|
|
244
|
-
release = await lockfile.lock(path, LOCK_OPTIONS);
|
|
245
|
-
return await fn();
|
|
246
|
-
}
|
|
247
|
-
finally {
|
|
248
|
-
if (release) {
|
|
249
|
-
try {
|
|
250
|
-
await release();
|
|
251
|
-
}
|
|
252
|
-
catch (unlockError) {
|
|
253
|
-
log.warn("Failed to release lock", { error: String(unlockError) });
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
export function mergeAccountStorage(existing, incoming) {
|
|
259
|
-
const accountMap = new Map();
|
|
260
|
-
for (const acc of existing.accounts) {
|
|
261
|
-
if (acc.refreshToken) {
|
|
262
|
-
accountMap.set(acc.refreshToken, acc);
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
for (const acc of incoming.accounts) {
|
|
266
|
-
if (acc.refreshToken) {
|
|
267
|
-
const existingAcc = accountMap.get(acc.refreshToken);
|
|
268
|
-
if (existingAcc) {
|
|
269
|
-
const eligibilitySource = (acc.eligibilityStateUpdatedAt ?? 0) >= (existingAcc.eligibilityStateUpdatedAt ?? 0)
|
|
270
|
-
? acc
|
|
271
|
-
: existingAcc;
|
|
272
|
-
const merged = {
|
|
273
|
-
...existingAcc,
|
|
274
|
-
...acc,
|
|
275
|
-
// Preserve manually configured projectId/managedProjectId if not in incoming
|
|
276
|
-
projectId: acc.projectId ?? existingAcc.projectId,
|
|
277
|
-
managedProjectId: acc.managedProjectId ?? existingAcc.managedProjectId,
|
|
278
|
-
rateLimitResetTimes: {
|
|
279
|
-
...existingAcc.rateLimitResetTimes,
|
|
280
|
-
...acc.rateLimitResetTimes,
|
|
281
|
-
},
|
|
282
|
-
lastUsed: Math.max(existingAcc.lastUsed || 0, acc.lastUsed || 0),
|
|
283
|
-
accountIneligible: eligibilitySource.accountIneligible,
|
|
284
|
-
accountIneligibleAt: eligibilitySource.accountIneligibleAt,
|
|
285
|
-
accountIneligibleReason: eligibilitySource.accountIneligibleReason,
|
|
286
|
-
eligibilityStateUpdatedAt: eligibilitySource.eligibilityStateUpdatedAt,
|
|
287
|
-
};
|
|
288
|
-
if (merged.accountIneligible) {
|
|
289
|
-
merged.enabled = false;
|
|
290
|
-
}
|
|
291
|
-
accountMap.set(acc.refreshToken, merged);
|
|
292
|
-
}
|
|
293
|
-
else {
|
|
294
|
-
accountMap.set(acc.refreshToken, acc);
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
return {
|
|
299
|
-
version: 4,
|
|
300
|
-
accounts: Array.from(accountMap.values()),
|
|
301
|
-
activeIndex: incoming.activeIndex,
|
|
302
|
-
activeIndexByFamily: incoming.activeIndexByFamily,
|
|
303
|
-
};
|
|
304
|
-
}
|
|
305
|
-
export function deduplicateAccountsByEmail(accounts) {
|
|
306
|
-
const emailToNewestIndex = new Map();
|
|
307
|
-
const indicesToKeep = new Set();
|
|
308
|
-
// First pass: find the newest account for each email (by lastUsed, then addedAt)
|
|
309
|
-
for (let i = 0; i < accounts.length; i++) {
|
|
310
|
-
const acc = accounts[i];
|
|
311
|
-
if (!acc)
|
|
312
|
-
continue;
|
|
313
|
-
if (!acc.email) {
|
|
314
|
-
// No email - keep this account (can't deduplicate without email)
|
|
315
|
-
indicesToKeep.add(i);
|
|
316
|
-
continue;
|
|
317
|
-
}
|
|
318
|
-
const existingIndex = emailToNewestIndex.get(acc.email);
|
|
319
|
-
if (existingIndex === undefined) {
|
|
320
|
-
emailToNewestIndex.set(acc.email, i);
|
|
321
|
-
continue;
|
|
322
|
-
}
|
|
323
|
-
// Compare to find which is newer
|
|
324
|
-
const existing = accounts[existingIndex];
|
|
325
|
-
if (!existing) {
|
|
326
|
-
emailToNewestIndex.set(acc.email, i);
|
|
327
|
-
continue;
|
|
328
|
-
}
|
|
329
|
-
// Prefer higher lastUsed, then higher addedAt
|
|
330
|
-
// Compare fields separately to avoid integer overflow with large timestamps
|
|
331
|
-
const currLastUsed = acc.lastUsed || 0;
|
|
332
|
-
const existLastUsed = existing.lastUsed || 0;
|
|
333
|
-
const currAddedAt = acc.addedAt || 0;
|
|
334
|
-
const existAddedAt = existing.addedAt || 0;
|
|
335
|
-
const isNewer = currLastUsed > existLastUsed ||
|
|
336
|
-
(currLastUsed === existLastUsed && currAddedAt > existAddedAt);
|
|
337
|
-
if (isNewer) {
|
|
338
|
-
emailToNewestIndex.set(acc.email, i);
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
// Add all the newest email-based indices to the keep set
|
|
342
|
-
for (const idx of emailToNewestIndex.values()) {
|
|
343
|
-
indicesToKeep.add(idx);
|
|
344
|
-
}
|
|
345
|
-
// Build the deduplicated list, preserving original order for kept items
|
|
346
|
-
const result = [];
|
|
347
|
-
for (let i = 0; i < accounts.length; i++) {
|
|
348
|
-
if (indicesToKeep.has(i)) {
|
|
349
|
-
const acc = accounts[i];
|
|
350
|
-
if (acc) {
|
|
351
|
-
result.push(acc);
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
return result;
|
|
356
|
-
}
|
|
357
|
-
function migrateV1ToV2(v1) {
|
|
358
|
-
return {
|
|
359
|
-
version: 2,
|
|
360
|
-
accounts: v1.accounts.map((acc) => {
|
|
361
|
-
const rateLimitResetTimes = {};
|
|
362
|
-
if (acc.isRateLimited &&
|
|
363
|
-
acc.rateLimitResetTime &&
|
|
364
|
-
acc.rateLimitResetTime > Date.now()) {
|
|
365
|
-
rateLimitResetTimes.claude = acc.rateLimitResetTime;
|
|
366
|
-
rateLimitResetTimes.gemini = acc.rateLimitResetTime;
|
|
367
|
-
}
|
|
368
|
-
return {
|
|
369
|
-
email: acc.email,
|
|
370
|
-
refreshToken: acc.refreshToken,
|
|
371
|
-
projectId: acc.projectId,
|
|
372
|
-
managedProjectId: acc.managedProjectId,
|
|
373
|
-
addedAt: acc.addedAt,
|
|
374
|
-
lastUsed: acc.lastUsed,
|
|
375
|
-
lastSwitchReason: acc.lastSwitchReason,
|
|
376
|
-
rateLimitResetTimes: Object.keys(rateLimitResetTimes).length > 0
|
|
377
|
-
? rateLimitResetTimes
|
|
378
|
-
: undefined,
|
|
379
|
-
};
|
|
380
|
-
}),
|
|
381
|
-
activeIndex: v1.activeIndex,
|
|
382
|
-
};
|
|
383
|
-
}
|
|
384
|
-
export function migrateV2ToV3(v2) {
|
|
385
|
-
return {
|
|
386
|
-
version: 3,
|
|
387
|
-
accounts: v2.accounts.map((acc) => {
|
|
388
|
-
const rateLimitResetTimes = {};
|
|
389
|
-
if (acc.rateLimitResetTimes?.claude &&
|
|
390
|
-
acc.rateLimitResetTimes.claude > Date.now()) {
|
|
391
|
-
rateLimitResetTimes.claude = acc.rateLimitResetTimes.claude;
|
|
392
|
-
}
|
|
393
|
-
if (acc.rateLimitResetTimes?.gemini &&
|
|
394
|
-
acc.rateLimitResetTimes.gemini > Date.now()) {
|
|
395
|
-
rateLimitResetTimes["gemini-antigravity"] =
|
|
396
|
-
acc.rateLimitResetTimes.gemini;
|
|
397
|
-
}
|
|
398
|
-
return {
|
|
399
|
-
email: acc.email,
|
|
400
|
-
refreshToken: acc.refreshToken,
|
|
401
|
-
projectId: acc.projectId,
|
|
402
|
-
managedProjectId: acc.managedProjectId,
|
|
403
|
-
addedAt: acc.addedAt,
|
|
404
|
-
lastUsed: acc.lastUsed,
|
|
405
|
-
lastSwitchReason: acc.lastSwitchReason,
|
|
406
|
-
rateLimitResetTimes: Object.keys(rateLimitResetTimes).length > 0
|
|
407
|
-
? rateLimitResetTimes
|
|
408
|
-
: undefined,
|
|
409
|
-
};
|
|
410
|
-
}),
|
|
411
|
-
activeIndex: v2.activeIndex,
|
|
412
|
-
};
|
|
413
|
-
}
|
|
414
|
-
export function migrateV3ToV4(v3) {
|
|
415
|
-
return {
|
|
416
|
-
version: 4,
|
|
417
|
-
accounts: v3.accounts.map((acc) => ({
|
|
418
|
-
...acc,
|
|
419
|
-
fingerprint: undefined,
|
|
420
|
-
fingerprintHistory: undefined,
|
|
421
|
-
})),
|
|
422
|
-
activeIndex: v3.activeIndex,
|
|
423
|
-
activeIndexByFamily: v3.activeIndexByFamily,
|
|
424
|
-
};
|
|
425
|
-
}
|
|
223
|
+
// ============================================================================
|
|
224
|
+
// Host path delegation. Each of these resolves the on-disk path via the
|
|
225
|
+
// adapter above and hands it to the core lock-held engine. Callers that
|
|
226
|
+
// want to run their own mutator (e.g. persist-account-pool) should
|
|
227
|
+
// import from `@cortexkit/antigravity-auth-core` directly and pass
|
|
228
|
+
// `getStoragePath()` as the path argument.
|
|
229
|
+
// ============================================================================
|
|
426
230
|
export async function loadAccounts() {
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
await ensureSecurePermissions(path);
|
|
431
|
-
const content = await fs.readFile(path, "utf-8");
|
|
432
|
-
const data = JSON.parse(content);
|
|
433
|
-
if (!Array.isArray(data.accounts)) {
|
|
434
|
-
log.warn("Invalid storage format, ignoring");
|
|
435
|
-
return null;
|
|
436
|
-
}
|
|
437
|
-
let storage;
|
|
438
|
-
if (data.version === 1) {
|
|
439
|
-
log.info("Migrating account storage from v1 to v4");
|
|
440
|
-
const v2 = migrateV1ToV2(data);
|
|
441
|
-
const v3 = migrateV2ToV3(v2);
|
|
442
|
-
storage = migrateV3ToV4(v3);
|
|
443
|
-
try {
|
|
444
|
-
await saveAccounts(storage);
|
|
445
|
-
log.info("Migration to v4 complete");
|
|
446
|
-
}
|
|
447
|
-
catch (saveError) {
|
|
448
|
-
log.warn("Failed to persist migrated storage", {
|
|
449
|
-
error: String(saveError),
|
|
450
|
-
});
|
|
451
|
-
}
|
|
452
|
-
}
|
|
453
|
-
else if (data.version === 2) {
|
|
454
|
-
log.info("Migrating account storage from v2 to v4");
|
|
455
|
-
const v3 = migrateV2ToV3(data);
|
|
456
|
-
storage = migrateV3ToV4(v3);
|
|
457
|
-
try {
|
|
458
|
-
await saveAccounts(storage);
|
|
459
|
-
log.info("Migration to v4 complete");
|
|
460
|
-
}
|
|
461
|
-
catch (saveError) {
|
|
462
|
-
log.warn("Failed to persist migrated storage", {
|
|
463
|
-
error: String(saveError),
|
|
464
|
-
});
|
|
465
|
-
}
|
|
466
|
-
}
|
|
467
|
-
else if (data.version === 3) {
|
|
468
|
-
log.info("Migrating account storage from v3 to v4");
|
|
469
|
-
storage = migrateV3ToV4(data);
|
|
470
|
-
try {
|
|
471
|
-
await saveAccounts(storage);
|
|
472
|
-
log.info("Migration to v4 complete");
|
|
473
|
-
}
|
|
474
|
-
catch (saveError) {
|
|
475
|
-
log.warn("Failed to persist migrated storage", {
|
|
476
|
-
error: String(saveError),
|
|
477
|
-
});
|
|
478
|
-
}
|
|
479
|
-
}
|
|
480
|
-
else if (data.version === 4) {
|
|
481
|
-
storage = data;
|
|
482
|
-
}
|
|
483
|
-
else {
|
|
484
|
-
log.warn("Unknown storage version, ignoring", {
|
|
485
|
-
version: data.version,
|
|
486
|
-
});
|
|
487
|
-
return null;
|
|
488
|
-
}
|
|
489
|
-
// Validate accounts have required fields
|
|
490
|
-
const validAccounts = storage.accounts.filter((a) => {
|
|
491
|
-
return (!!a &&
|
|
492
|
-
typeof a === "object" &&
|
|
493
|
-
typeof a.refreshToken === "string");
|
|
494
|
-
});
|
|
495
|
-
// Deduplicate accounts by email (keeps newest entry for each email)
|
|
496
|
-
const deduplicatedAccounts = deduplicateAccountsByEmail(validAccounts);
|
|
497
|
-
// Clamp activeIndex to valid range after deduplication
|
|
498
|
-
let activeIndex = typeof storage.activeIndex === "number" &&
|
|
499
|
-
Number.isFinite(storage.activeIndex)
|
|
500
|
-
? storage.activeIndex
|
|
501
|
-
: 0;
|
|
502
|
-
if (deduplicatedAccounts.length > 0) {
|
|
503
|
-
activeIndex = Math.min(activeIndex, deduplicatedAccounts.length - 1);
|
|
504
|
-
activeIndex = Math.max(activeIndex, 0);
|
|
505
|
-
}
|
|
506
|
-
else {
|
|
507
|
-
activeIndex = 0;
|
|
508
|
-
}
|
|
509
|
-
return {
|
|
510
|
-
version: 4,
|
|
511
|
-
accounts: deduplicatedAccounts,
|
|
512
|
-
activeIndex,
|
|
513
|
-
activeIndexByFamily: storage.activeIndexByFamily,
|
|
514
|
-
};
|
|
515
|
-
}
|
|
516
|
-
catch (error) {
|
|
517
|
-
const code = error.code;
|
|
518
|
-
if (code === "ENOENT") {
|
|
519
|
-
return null;
|
|
520
|
-
}
|
|
521
|
-
log.error("Failed to load account storage", { error: String(error) });
|
|
522
|
-
return null;
|
|
523
|
-
}
|
|
231
|
+
const path = getStoragePath();
|
|
232
|
+
await ensureGitignore(dirname(path));
|
|
233
|
+
return coreLoadAccountStorage(path);
|
|
524
234
|
}
|
|
525
235
|
/**
|
|
526
|
-
*
|
|
527
|
-
*
|
|
528
|
-
*
|
|
529
|
-
* Falls back to copyFile + unlink if all rename attempts fail.
|
|
236
|
+
* Merge `storage` into the persisted pool. Use this for non-destructive
|
|
237
|
+
* writes (quota cache, eligibility, last-used) so concurrent writers
|
|
238
|
+
* do not silently drop each other's data.
|
|
530
239
|
*/
|
|
531
|
-
async function atomicWriteFile(targetPath, content) {
|
|
532
|
-
const tempPath = `${targetPath}.${randomBytes(6).toString("hex")}.tmp`;
|
|
533
|
-
await fs.writeFile(tempPath, content, { encoding: "utf-8", mode: 0o600 });
|
|
534
|
-
const RETRY_DELAYS = [50, 100, 200];
|
|
535
|
-
let lastError;
|
|
536
|
-
for (let attempt = 0; attempt <= RETRY_DELAYS.length; attempt++) {
|
|
537
|
-
try {
|
|
538
|
-
await fs.rename(tempPath, targetPath);
|
|
539
|
-
return;
|
|
540
|
-
}
|
|
541
|
-
catch (error) {
|
|
542
|
-
lastError = error;
|
|
543
|
-
const code = error.code;
|
|
544
|
-
if (code !== "EPERM" && code !== "EACCES") {
|
|
545
|
-
break; // Non-transient error, skip retries
|
|
546
|
-
}
|
|
547
|
-
if (attempt < RETRY_DELAYS.length) {
|
|
548
|
-
await new Promise((r) => setTimeout(r, RETRY_DELAYS[attempt]));
|
|
549
|
-
}
|
|
550
|
-
}
|
|
551
|
-
}
|
|
552
|
-
// All rename attempts failed — fall back to copy + delete
|
|
553
|
-
try {
|
|
554
|
-
await fs.copyFile(tempPath, targetPath);
|
|
555
|
-
try {
|
|
556
|
-
await fs.unlink(tempPath);
|
|
557
|
-
}
|
|
558
|
-
catch {
|
|
559
|
-
// Ignore temp cleanup errors
|
|
560
|
-
}
|
|
561
|
-
}
|
|
562
|
-
catch {
|
|
563
|
-
// Copy also failed — clean up temp and throw original rename error
|
|
564
|
-
try {
|
|
565
|
-
await fs.unlink(tempPath);
|
|
566
|
-
}
|
|
567
|
-
catch {
|
|
568
|
-
// Ignore cleanup errors
|
|
569
|
-
}
|
|
570
|
-
throw lastError;
|
|
571
|
-
}
|
|
572
|
-
}
|
|
573
240
|
export async function saveAccounts(storage) {
|
|
574
241
|
const path = getStoragePath();
|
|
575
242
|
const configDir = dirname(path);
|
|
576
243
|
await fs.mkdir(configDir, { recursive: true });
|
|
577
244
|
await ensureGitignore(configDir);
|
|
578
|
-
await
|
|
579
|
-
const existing = await loadAccountsUnsafe();
|
|
580
|
-
const merged = existing ? mergeAccountStorage(existing, storage) : storage;
|
|
581
|
-
const content = JSON.stringify(merged, null, 2);
|
|
582
|
-
await atomicWriteFile(path, content);
|
|
583
|
-
});
|
|
245
|
+
await coreSaveAccountStorage(path, storage);
|
|
584
246
|
}
|
|
585
247
|
/**
|
|
586
248
|
* Save accounts storage by replacing the entire file (no merge).
|
|
587
|
-
*
|
|
588
|
-
*
|
|
249
|
+
* Required for destructive operations like delete where the next-state
|
|
250
|
+
* must replace — never be merged with — what is on disk.
|
|
589
251
|
*/
|
|
590
252
|
export async function saveAccountsReplace(storage) {
|
|
591
253
|
const path = getStoragePath();
|
|
592
254
|
const configDir = dirname(path);
|
|
593
255
|
await fs.mkdir(configDir, { recursive: true });
|
|
594
256
|
await ensureGitignore(configDir);
|
|
595
|
-
await
|
|
596
|
-
const content = JSON.stringify(storage, null, 2);
|
|
597
|
-
await atomicWriteFile(path, content);
|
|
598
|
-
});
|
|
599
|
-
}
|
|
600
|
-
async function loadAccountsUnsafe() {
|
|
601
|
-
try {
|
|
602
|
-
const path = getStoragePath();
|
|
603
|
-
// Ensure permissions are correct on load (fixes existing files)
|
|
604
|
-
await ensureSecurePermissions(path);
|
|
605
|
-
const content = await fs.readFile(path, "utf-8");
|
|
606
|
-
const parsed = JSON.parse(content);
|
|
607
|
-
if (parsed.version === 1) {
|
|
608
|
-
return migrateV3ToV4(migrateV2ToV3(migrateV1ToV2(parsed)));
|
|
609
|
-
}
|
|
610
|
-
if (parsed.version === 2) {
|
|
611
|
-
return migrateV3ToV4(migrateV2ToV3(parsed));
|
|
612
|
-
}
|
|
613
|
-
if (parsed.version === 3) {
|
|
614
|
-
return migrateV3ToV4(parsed);
|
|
615
|
-
}
|
|
616
|
-
return {
|
|
617
|
-
...parsed,
|
|
618
|
-
accounts: deduplicateAccountsByEmail(parsed.accounts),
|
|
619
|
-
};
|
|
620
|
-
}
|
|
621
|
-
catch (error) {
|
|
622
|
-
const code = error.code;
|
|
623
|
-
if (code === "ENOENT") {
|
|
624
|
-
return null;
|
|
625
|
-
}
|
|
626
|
-
log.error("Failed to load account storage (file exists but unreadable)", {
|
|
627
|
-
error: String(error),
|
|
628
|
-
code: code ?? "unknown",
|
|
629
|
-
});
|
|
630
|
-
return null;
|
|
631
|
-
}
|
|
257
|
+
await coreSaveAccountStorageReplace(path, storage);
|
|
632
258
|
}
|
|
633
259
|
export async function clearAccounts() {
|
|
634
260
|
const path = getStoragePath();
|
|
635
261
|
try {
|
|
636
|
-
|
|
637
|
-
// back in between (which would resurrect a just-cleared pool).
|
|
638
|
-
await withFileLock(path, async () => {
|
|
639
|
-
await fs.unlink(path);
|
|
640
|
-
});
|
|
262
|
+
await coreClearAccountStorage(path);
|
|
641
263
|
}
|
|
642
264
|
catch (error) {
|
|
643
265
|
const code = error.code;
|
|
644
|
-
if (code !==
|
|
645
|
-
log.error(
|
|
266
|
+
if (code !== 'ENOENT') {
|
|
267
|
+
log.error('Failed to clear account storage', { error: String(error) });
|
|
646
268
|
}
|
|
647
269
|
}
|
|
648
270
|
}
|
|
271
|
+
/**
|
|
272
|
+
* Locate a stored account by its refresh token under the lock-held
|
|
273
|
+
* mutator and apply `mutate(account)`. Returns the (possibly mutated)
|
|
274
|
+
* account, or `undefined` when the token no longer matches any stored
|
|
275
|
+
* account. Concurrent writers that add/remove accounts will not
|
|
276
|
+
* disturb the lookup — the read happens while the lock is held.
|
|
277
|
+
*
|
|
278
|
+
* `mutate` may mutate `account` in place and return `true` to commit
|
|
279
|
+
* the change; returning `false` is treated as "no change" and skips
|
|
280
|
+
* the write.
|
|
281
|
+
*/
|
|
282
|
+
export async function mutateAccountByRefreshToken(refreshToken, mutate) {
|
|
283
|
+
const path = getStoragePath();
|
|
284
|
+
const configDir = dirname(path);
|
|
285
|
+
await fs.mkdir(configDir, { recursive: true });
|
|
286
|
+
await ensureGitignore(configDir);
|
|
287
|
+
let result;
|
|
288
|
+
await coreMutateAccountStorage(path, (current) => {
|
|
289
|
+
const idx = current.accounts.findIndex((acc) => acc.refreshToken === refreshToken);
|
|
290
|
+
if (idx === -1)
|
|
291
|
+
return current;
|
|
292
|
+
const target = current.accounts[idx];
|
|
293
|
+
if (!target)
|
|
294
|
+
return current;
|
|
295
|
+
const changed = mutate(target);
|
|
296
|
+
if (!changed)
|
|
297
|
+
return current;
|
|
298
|
+
result = target;
|
|
299
|
+
current.accounts[idx] = target;
|
|
300
|
+
return current;
|
|
301
|
+
});
|
|
302
|
+
return result;
|
|
303
|
+
}
|
|
649
304
|
//# sourceMappingURL=storage.js.map
|