@cortexkit/opencode-antigravity-auth 1.1.0 → 2.0.0
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 +3790 -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 +18767 -13829
- 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/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 +35 -0
- package/dist/src/plugin/auth-loader.d.ts.map +1 -0
- package/dist/src/plugin/auth-loader.js +144 -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/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 +276 -0
- package/dist/src/plugin/command-data.d.ts.map +1 -0
- package/dist/src/plugin/command-data.js +325 -0
- package/dist/src/plugin/command-data.js.map +1 -0
- package/dist/src/plugin/commands.d.ts +151 -0
- package/dist/src/plugin/commands.d.ts.map +1 -0
- package/dist/src/plugin/commands.js +639 -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 +21 -2
- package/dist/src/plugin/config/schema.d.ts.map +1 -1
- package/dist/src/plugin/config/schema.js +85 -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 +3 -3
- package/dist/src/plugin/debug.d.ts.map +1 -1
- package/dist/src/plugin/debug.js +85 -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 +1387 -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 +23 -0
- package/dist/src/plugin/index.d.ts.map +1 -0
- package/dist/src/plugin/index.js +308 -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 +194 -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 +1284 -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 +97 -41
- package/dist/src/plugin/quota.d.ts.map +1 -1
- package/dist/src/plugin/quota.js +273 -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 +82 -31
- 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 +51 -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 +240 -0
- package/dist/src/sidebar-state.d.ts.map +1 -0
- package/dist/src/sidebar-state.js +520 -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 +497 -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 +662 -0
- package/dist/src/tui.js.map +1 -0
- package/package.json +46 -22
- package/src/plugin/command-data.ts +651 -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 +717 -0
- package/src/tui/command-dialogs.tsx +699 -0
- package/src/tui/entry.mjs +74 -0
- package/src/tui/file-logger.ts +145 -0
- package/src/tui-compiled/plugin/command-data.ts +651 -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 +717 -0
- package/src/tui-compiled/tui/command-dialogs.tsx +659 -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 +1150 -0
- package/src/tui-preferences.ts +416 -0
- package/src/tui.tsx +1117 -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
|
@@ -0,0 +1,1150 @@
|
|
|
1
|
+
import { memo as _$memo } from "opentui:runtime-module:%40opentui%2Fsolid";
|
|
2
|
+
import { createTextNode as _$createTextNode } from "opentui:runtime-module:%40opentui%2Fsolid";
|
|
3
|
+
import { createComponent as _$createComponent } from "opentui:runtime-module:%40opentui%2Fsolid";
|
|
4
|
+
import { effect as _$effect } from "opentui:runtime-module:%40opentui%2Fsolid";
|
|
5
|
+
import { insertNode as _$insertNode } from "opentui:runtime-module:%40opentui%2Fsolid";
|
|
6
|
+
import { insert as _$insert } from "opentui:runtime-module:%40opentui%2Fsolid";
|
|
7
|
+
import { setProp as _$setProp } from "opentui:runtime-module:%40opentui%2Fsolid";
|
|
8
|
+
import { createElement as _$createElement } from "opentui:runtime-module:%40opentui%2Fsolid";
|
|
9
|
+
/** @jsxImportSource @opentui/solid */
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Read-only OpenTUI sidebar for the Antigravity plugin.
|
|
13
|
+
*
|
|
14
|
+
* Mirrors the fleet sibling layout (see `anthropic-auth-live` /
|
|
15
|
+
* `openai-auth-live` `packages/opencode/src/tui.tsx`): a single bordered
|
|
16
|
+
* column with a labelled header badge, a Quota section that lists one
|
|
17
|
+
* `AccountBlock` per visible account, a Routing section that surfaces the
|
|
18
|
+
* most recent session route, and a Health section that only appears when
|
|
19
|
+
* something is wrong. The Antigravity data model is richer than the
|
|
20
|
+
* Claude/Codex one (per-account Claude + Gemini Pro + Gemini Flash quota
|
|
21
|
+
* groups, a health score, and per-session routing decisions), so the
|
|
22
|
+
* fleet components are adapted rather than copied verbatim:
|
|
23
|
+
*
|
|
24
|
+
* - `QuotaRow` reads `remainingPercent + resetAt` from the Antigravity
|
|
25
|
+
* `SidebarQuotaEntry` shape and colors via `quotaTone` (remaining
|
|
26
|
+
* threshold) instead of `usageTone` (used threshold).
|
|
27
|
+
* - `AccountBlock` derives its status word (`active` / `idle` /
|
|
28
|
+
* `cooling` / `off` / `blocked`) from the Antigravity account state and
|
|
29
|
+
* surfaces health as a muted secondary line rather than a top-level
|
|
30
|
+
* bar — fleet parity for "Quota first, health second".
|
|
31
|
+
* - `Routing` resolves to a single `Route` `StatRow` carrying the most
|
|
32
|
+
* recent `activeRouting` entry, since Antigravity does not maintain a
|
|
33
|
+
* per-session sidebar state alongside the slot-rendered tree.
|
|
34
|
+
*
|
|
35
|
+
* Hard rules for this file:
|
|
36
|
+
*
|
|
37
|
+
* - NO direct writes to the host terminal anywhere in the render path.
|
|
38
|
+
* The host terminal is the frame buffer; one stray byte corrupts every
|
|
39
|
+
* subsequent cell. Errors flow through `createTuiFileLogger()`.
|
|
40
|
+
* - NO imports from `./plugin/storage`, `./plugin/accounts`, OAuth code,
|
|
41
|
+
* or anything that touches tokens.
|
|
42
|
+
* - The component uses Solid's `onCleanup` to release the polling timer
|
|
43
|
+
* on unmount so a route change can never leak an interval.
|
|
44
|
+
*/
|
|
45
|
+
|
|
46
|
+
import { readFileSync } from "node:fs";
|
|
47
|
+
import { dirname, join } from "node:path";
|
|
48
|
+
import { fileURLToPath } from "node:url";
|
|
49
|
+
import { createSlot } from "opentui:runtime-module:%40opentui%2Fsolid";
|
|
50
|
+
import { createEffect, createSignal, For, onCleanup, onMount, Show } from "opentui:runtime-module:solid-js";
|
|
51
|
+
import { createRpcClient } from "./rpc/rpc-client";
|
|
52
|
+
import { getRpcDir } from "./rpc/rpc-dir";
|
|
53
|
+
import { readSidebarState } from "./sidebar-state";
|
|
54
|
+
import { openCommandDialog } from "./tui/command-dialogs";
|
|
55
|
+
import { createTuiFileLogger } from "./tui/file-logger";
|
|
56
|
+
import { computeEffectiveOrder, DEFAULT_PREFS, DEFAULT_SLOT_ORDER, PLUGIN_KEY, queueTuiPreferenceUpdate, readTuiPreferencesFile, resolveAntigravityAuthPrefs, watchTuiPreferences } from "./tui-preferences";
|
|
57
|
+
const ID = 'cortexkit.antigravity-auth';
|
|
58
|
+
const POLL_INTERVAL_MS = 2000;
|
|
59
|
+
const RPC_POLL_MS = 500;
|
|
60
|
+
const SINGLE_BORDER = {
|
|
61
|
+
type: 'single'
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
// Read package metadata from either the raw src/ entry or its generated
|
|
65
|
+
// src/tui-compiled/ counterpart. Avoid a JSON import because package.json sits
|
|
66
|
+
// outside the declaration build's rootDir.
|
|
67
|
+
const PLUGIN_VERSION = (() => {
|
|
68
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
69
|
+
for (const packageFile of [join(here, '..', 'package.json'), join(here, '..', '..', 'package.json')]) {
|
|
70
|
+
try {
|
|
71
|
+
const raw = readFileSync(packageFile, 'utf8');
|
|
72
|
+
const version = JSON.parse(raw).version;
|
|
73
|
+
if (version) return version;
|
|
74
|
+
} catch {
|
|
75
|
+
// Try the path for the other TUI entry layout.
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return '';
|
|
79
|
+
})();
|
|
80
|
+
// Module-scoped state — TEST ISOLATION CONTRACT:
|
|
81
|
+
//
|
|
82
|
+
// `rpcPollStarted`, notification cursor/deduplication state, `rpcInFlight`, and the lazy
|
|
83
|
+
// `sidebarController` below persist across tests via the cached ES
|
|
84
|
+
// module Bun loads once per `--isolate` file. Tests must NOT assert
|
|
85
|
+
// fresh-process behaviour from these variables — by the time the first
|
|
86
|
+
// `startRpcNotificationPolling` runs, all four carry stale values from
|
|
87
|
+
// prior tests in the same file. Test isolation comes from:
|
|
88
|
+
// 1. fresh-importing `tui.tsx` via a cache-busted dynamic `import`
|
|
89
|
+
// so the module re-evaluates with fresh module-scoped bindings, and
|
|
90
|
+
// 2. constructing a fresh `SidebarController` via
|
|
91
|
+
// `createSidebarController(prefs)` and passing it through
|
|
92
|
+
// `SidebarPanel.props.controller` — never through
|
|
93
|
+
// `getSidebarController()`, which lazily seeds the module-scoped
|
|
94
|
+
// singleton.
|
|
95
|
+
let rpcPollStarted = false;
|
|
96
|
+
const notificationCursorBySession = new Map();
|
|
97
|
+
const dispatchedNotificationIds = new Set();
|
|
98
|
+
let rpcInFlight = false;
|
|
99
|
+
const GLOBAL_NOTIFICATION_CURSOR = '__global__';
|
|
100
|
+
const MAX_NOTIFICATION_CURSORS = 256;
|
|
101
|
+
const QUOTA_LABELS = {
|
|
102
|
+
claude: 'Cl',
|
|
103
|
+
'gemini-pro': 'GP',
|
|
104
|
+
'gemini-flash': 'GF',
|
|
105
|
+
'gpt-oss': 'GPT'
|
|
106
|
+
};
|
|
107
|
+
const QUOTA_ORDER = ['claude', 'gemini-pro', 'gemini-flash', 'gpt-oss'];
|
|
108
|
+
|
|
109
|
+
// --- Theme tokens ----------------------------------------------------------
|
|
110
|
+
//
|
|
111
|
+
// The sidebar pulls its colors from the live host theme (`api.theme.current`
|
|
112
|
+
// — a Solid-friendly getter that re-emits when the user switches theme).
|
|
113
|
+
// Every render path resolves through `toneColor(theme, tone)` with a
|
|
114
|
+
// sibling-style `??` fallback chain, so the sidebar always tracks the
|
|
115
|
+
// active theme and never hardcodes an ANSI literal.
|
|
116
|
+
//
|
|
117
|
+
// `FALLBACK_THEME` is the safety net for tests and any future host that
|
|
118
|
+
// does not implement the theme surface. The fields the sidebar actually
|
|
119
|
+
// uses are populated; the rest of the TuiThemeCurrent fields are left
|
|
120
|
+
// undefined and the `??` chain in `toneColor` falls through cleanly.
|
|
121
|
+
|
|
122
|
+
const FALLBACK_THEME = {
|
|
123
|
+
primary: '#3b82f6',
|
|
124
|
+
secondary: '#a855f7',
|
|
125
|
+
accent: '#7c3aed',
|
|
126
|
+
error: '#ef4444',
|
|
127
|
+
warning: '#eab308',
|
|
128
|
+
success: '#22c55e',
|
|
129
|
+
info: '#0ea5e9',
|
|
130
|
+
text: '#e5e7eb',
|
|
131
|
+
textMuted: '#6b7280',
|
|
132
|
+
selectedListItemText: '#ffffff',
|
|
133
|
+
background: '#0b0d12',
|
|
134
|
+
backgroundPanel: '#11131a',
|
|
135
|
+
backgroundElement: '#1a1d27',
|
|
136
|
+
backgroundMenu: '#1a1d27',
|
|
137
|
+
border: '#2a2d3a',
|
|
138
|
+
borderActive: '#7c3aed',
|
|
139
|
+
borderSubtle: '#2a2d3a',
|
|
140
|
+
diffAdded: '#22c55e',
|
|
141
|
+
diffRemoved: '#ef4444',
|
|
142
|
+
diffContext: '#6b7280',
|
|
143
|
+
diffHunkHeader: '#7c3aed',
|
|
144
|
+
diffHighlightAdded: '#166534',
|
|
145
|
+
diffHighlightRemoved: '#7f1d1d',
|
|
146
|
+
diffAddedBg: '#0a1f12',
|
|
147
|
+
diffRemovedBg: '#1f0a0a',
|
|
148
|
+
diffContextBg: '#0b0d12',
|
|
149
|
+
diffLineNumber: '#4b5563',
|
|
150
|
+
diffAddedLineNumberBg: '#0a1f12',
|
|
151
|
+
diffRemovedLineNumberBg: '#1f0a0a',
|
|
152
|
+
markdownText: '#e5e7eb',
|
|
153
|
+
markdownHeading: '#7c3aed',
|
|
154
|
+
markdownLink: '#3b82f6',
|
|
155
|
+
markdownLinkText: '#60a5fa',
|
|
156
|
+
markdownCode: '#22c55e',
|
|
157
|
+
markdownBlockQuote: '#6b7280',
|
|
158
|
+
markdownEmph: '#eab308',
|
|
159
|
+
markdownStrong: '#7c3aed',
|
|
160
|
+
markdownHorizontalRule: '#2a2d3a',
|
|
161
|
+
markdownListItem: '#7c3aed',
|
|
162
|
+
markdownListEnumeration: '#a855f7',
|
|
163
|
+
markdownImage: '#3b82f6',
|
|
164
|
+
markdownImageText: '#60a5fa',
|
|
165
|
+
markdownCodeBlock: '#11131a',
|
|
166
|
+
syntaxComment: '#6b7280',
|
|
167
|
+
syntaxKeyword: '#a855f7',
|
|
168
|
+
syntaxFunction: '#3b82f6',
|
|
169
|
+
syntaxVariable: '#e5e7eb',
|
|
170
|
+
syntaxString: '#22c55e',
|
|
171
|
+
syntaxNumber: '#eab308',
|
|
172
|
+
syntaxType: '#7c3aed',
|
|
173
|
+
syntaxOperator: '#e5e7eb',
|
|
174
|
+
syntaxPunctuation: '#6b7280',
|
|
175
|
+
thinkingOpacity: 0.6
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
// Mirror the fleet siblings' tone chain: every tone falls through to a
|
|
179
|
+
// sibling token, so a sparse custom theme still renders readably.
|
|
180
|
+
function toneColor(theme, tone) {
|
|
181
|
+
switch (tone) {
|
|
182
|
+
case 'ok':
|
|
183
|
+
return theme.success ?? theme.accent;
|
|
184
|
+
case 'warn':
|
|
185
|
+
return theme.warning ?? theme.accent;
|
|
186
|
+
case 'err':
|
|
187
|
+
return theme.error ?? theme.accent;
|
|
188
|
+
case 'muted':
|
|
189
|
+
return theme.textMuted ?? theme.text;
|
|
190
|
+
case 'accent':
|
|
191
|
+
return theme.accent ?? theme.text;
|
|
192
|
+
default:
|
|
193
|
+
return theme.text;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
function quotaTone(usedPct, appearance) {
|
|
197
|
+
if (usedPct < appearance.warnThreshold) return 'ok';
|
|
198
|
+
if (usedPct < appearance.errorThreshold) return 'warn';
|
|
199
|
+
return 'err';
|
|
200
|
+
}
|
|
201
|
+
function quotaBarSegments(usedPct, appearance) {
|
|
202
|
+
const width = appearance.barWidth;
|
|
203
|
+
const usedCells = Math.max(0, Math.min(Math.round(usedPct / 100 * width), width));
|
|
204
|
+
const tone = quotaTone(usedPct, appearance);
|
|
205
|
+
return [{
|
|
206
|
+
text: appearance.barFilledChar.repeat(usedCells),
|
|
207
|
+
tone
|
|
208
|
+
}, {
|
|
209
|
+
text: appearance.barEmptyChar.repeat(width - usedCells),
|
|
210
|
+
tone
|
|
211
|
+
}].filter(segment => segment.text.length > 0);
|
|
212
|
+
}
|
|
213
|
+
const EMPTY_STATE = {
|
|
214
|
+
version: 1,
|
|
215
|
+
checkedAt: 0,
|
|
216
|
+
accounts: [],
|
|
217
|
+
activeRouting: {},
|
|
218
|
+
routingAuthoritative: false
|
|
219
|
+
};
|
|
220
|
+
function resolveLogger(logger) {
|
|
221
|
+
if (logger) return logger;
|
|
222
|
+
try {
|
|
223
|
+
return createTuiFileLogger();
|
|
224
|
+
} catch {
|
|
225
|
+
// Fall back to a stub that drops everything — the sidebar must still
|
|
226
|
+
// render even if file logging cannot be initialized.
|
|
227
|
+
return noopLogger();
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
function noopLogger() {
|
|
231
|
+
const drop = () => undefined;
|
|
232
|
+
return {
|
|
233
|
+
debug: drop,
|
|
234
|
+
info: drop,
|
|
235
|
+
warn: drop,
|
|
236
|
+
error: drop,
|
|
237
|
+
getLogPath: () => undefined
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// Module-scoped controller singleton, initialized at plugin startup. The
|
|
242
|
+
// watcher is intentionally never disposed — collapse/prefs state survives
|
|
243
|
+
// sidebar remounts (route changes) for the lifetime of the TUI process,
|
|
244
|
+
// mirroring the fleet siblings.
|
|
245
|
+
//
|
|
246
|
+
// TEST ISOLATION: this singleton, like `rpcPollStarted` above, persists
|
|
247
|
+
// across tests via the cached ES module. Tests construct a controller
|
|
248
|
+
// via `createSidebarController(prefs)` and pass it through
|
|
249
|
+
// `SidebarPanel.props.controller` — they MUST NOT rely on this lazy
|
|
250
|
+
// singleton for isolation. See the block above for the full contract.
|
|
251
|
+
let sidebarController = null;
|
|
252
|
+
|
|
253
|
+
// The TUI may unmount and remount sidebar_content when the user switches
|
|
254
|
+
// views. A remount re-runs the component body, so any signal created inside
|
|
255
|
+
// the component would reset to its seed. The controller lives in the plugin
|
|
256
|
+
// closure (process lifetime) and owns the durable prefs/collapse signals
|
|
257
|
+
// plus the single shared watcher subscription, so collapse and live pref
|
|
258
|
+
// reloads survive the remount.
|
|
259
|
+
//
|
|
260
|
+
// Exported so tests can construct a controller with a controlled initial
|
|
261
|
+
// prefs snapshot without touching the module-scoped singleton.
|
|
262
|
+
export function createSidebarController(initialPrefs) {
|
|
263
|
+
const [prefs, setPrefs] = createSignal(initialPrefs);
|
|
264
|
+
const seedCollapsed = initialPrefs.rememberCollapsed && initialPrefs.collapsed != null ? initialPrefs.collapsed : initialPrefs.startCollapsed;
|
|
265
|
+
const [collapsed, setCollapsed] = createSignal(seedCollapsed);
|
|
266
|
+
let lastPersistedCollapsed = initialPrefs.collapsed;
|
|
267
|
+
let lastApplied = JSON.stringify(initialPrefs);
|
|
268
|
+
|
|
269
|
+
// The watcher lives for the plugin/process lifetime — it is intentionally
|
|
270
|
+
// never disposed. Collapse guard mirrors the race-fix in toggleCollapsed:
|
|
271
|
+
// lastPersistedCollapsed is advanced only once our own write lands, so
|
|
272
|
+
// watcher echoes of the previous persisted value are rejected by the
|
|
273
|
+
// `!==` check and cannot revert a user click.
|
|
274
|
+
watchTuiPreferences(() => {
|
|
275
|
+
void (async () => {
|
|
276
|
+
const next = resolveAntigravityAuthPrefs(await readTuiPreferencesFile());
|
|
277
|
+
const serialized = JSON.stringify(next);
|
|
278
|
+
if (serialized === lastApplied) return;
|
|
279
|
+
lastApplied = serialized;
|
|
280
|
+
setPrefs(next);
|
|
281
|
+
if (next.rememberCollapsed && next.collapsed != null && next.collapsed !== lastPersistedCollapsed) {
|
|
282
|
+
lastPersistedCollapsed = next.collapsed;
|
|
283
|
+
setCollapsed(next.collapsed);
|
|
284
|
+
}
|
|
285
|
+
})();
|
|
286
|
+
});
|
|
287
|
+
function toggleCollapsed() {
|
|
288
|
+
const next = !collapsed();
|
|
289
|
+
setCollapsed(next);
|
|
290
|
+
if (prefs().rememberCollapsed) {
|
|
291
|
+
void queueTuiPreferenceUpdate(PLUGIN_KEY, ['collapsed'], next).then(() => {
|
|
292
|
+
lastPersistedCollapsed = next;
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
return {
|
|
297
|
+
prefs,
|
|
298
|
+
collapsed,
|
|
299
|
+
toggleCollapsed
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// Lazy module-scoped accessor used by the plugin entry. Tests should NOT go
|
|
304
|
+
// through this — they construct their own controller via createSidebarController
|
|
305
|
+
// and pass it via SidebarPanelProps.controller.
|
|
306
|
+
function getSidebarController() {
|
|
307
|
+
if (!sidebarController) {
|
|
308
|
+
sidebarController = createSidebarController(DEFAULT_PREFS);
|
|
309
|
+
}
|
|
310
|
+
return sidebarController;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// --- Shared helpers (fleet shape, antigravity data) ------------------------
|
|
314
|
+
|
|
315
|
+
function clamp(value, min, max) {
|
|
316
|
+
if (value < min) return min;
|
|
317
|
+
if (value > max) return max;
|
|
318
|
+
return value;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
// Render a "reset in Nm/Nh/NdNh" string from an epoch-ms reset time.
|
|
322
|
+
// Empty string when no resetAt is cached. The fleet's `formatResetIn`
|
|
323
|
+
// reads ISO strings; Antigravity persists resetAt as a numeric epoch, so
|
|
324
|
+
// the wrapper adapts to that without changing the shape of the output.
|
|
325
|
+
function formatResetIn(resetAt, now) {
|
|
326
|
+
if (!resetAt) return '';
|
|
327
|
+
const ms = resetAt - now();
|
|
328
|
+
if (ms <= 0) return 'now';
|
|
329
|
+
const mins = Math.floor(ms / 60_000);
|
|
330
|
+
if (mins < 60) return `${mins}m`;
|
|
331
|
+
const hrs = Math.floor(mins / 60);
|
|
332
|
+
if (hrs < 24) {
|
|
333
|
+
const rm = mins % 60;
|
|
334
|
+
return rm > 0 ? `${hrs}h${rm}m` : `${hrs}h`;
|
|
335
|
+
}
|
|
336
|
+
const days = Math.floor(hrs / 24);
|
|
337
|
+
const rh = hrs % 24;
|
|
338
|
+
return rh > 0 ? `${days}d${rh}h` : `${days}d`;
|
|
339
|
+
}
|
|
340
|
+
function formatError(value) {
|
|
341
|
+
if (value instanceof Error) return value.message;
|
|
342
|
+
try {
|
|
343
|
+
return JSON.stringify(value);
|
|
344
|
+
} catch {
|
|
345
|
+
return String(value);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// --- Fleet components (adapted to antigravity data) ------------------------
|
|
350
|
+
|
|
351
|
+
// Section header — fleet pattern: bold title, themed text color, top margin
|
|
352
|
+
// for vertical breathing room between sections.
|
|
353
|
+
function SectionHeader(props) {
|
|
354
|
+
return (() => {
|
|
355
|
+
var _el$ = _$createElement("box"),
|
|
356
|
+
_el$2 = _$createElement("text"),
|
|
357
|
+
_el$3 = _$createElement("b");
|
|
358
|
+
_$insertNode(_el$, _el$2);
|
|
359
|
+
_$setProp(_el$, "width", '100%');
|
|
360
|
+
_$setProp(_el$, "marginTop", 1);
|
|
361
|
+
_$insertNode(_el$2, _el$3);
|
|
362
|
+
_$insert(_el$3, () => props.title);
|
|
363
|
+
_$effect(_$p => _$setProp(_el$2, "fg", toneColor(props.theme(), 'text'), _$p));
|
|
364
|
+
return _el$;
|
|
365
|
+
})();
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// Fleet StatRow: muted label left, value (optionally tone-tinted, bold)
|
|
369
|
+
// right. Mirrors the layout the Claude/Codex sidebars use for routing
|
|
370
|
+
// rows, plan rows, and "resets N" rows.
|
|
371
|
+
function StatRow(props) {
|
|
372
|
+
return (() => {
|
|
373
|
+
var _el$4 = _$createElement("box"),
|
|
374
|
+
_el$5 = _$createElement("text"),
|
|
375
|
+
_el$6 = _$createElement("text"),
|
|
376
|
+
_el$7 = _$createElement("b");
|
|
377
|
+
_$insertNode(_el$4, _el$5);
|
|
378
|
+
_$insertNode(_el$4, _el$6);
|
|
379
|
+
_$setProp(_el$4, "width", '100%');
|
|
380
|
+
_$setProp(_el$4, "flexDirection", 'row');
|
|
381
|
+
_$setProp(_el$4, "justifyContent", 'space-between');
|
|
382
|
+
_$insert(_el$5, () => props.label);
|
|
383
|
+
_$insertNode(_el$6, _el$7);
|
|
384
|
+
_$insert(_el$7, () => props.value);
|
|
385
|
+
_$effect(_p$ => {
|
|
386
|
+
var _v$ = props.theme().textMuted,
|
|
387
|
+
_v$2 = toneColor(props.theme(), props.tone ?? 'text');
|
|
388
|
+
_v$ !== _p$.e && (_p$.e = _$setProp(_el$5, "fg", _v$, _p$.e));
|
|
389
|
+
_v$2 !== _p$.t && (_p$.t = _$setProp(_el$6, "fg", _v$2, _p$.t));
|
|
390
|
+
return _p$;
|
|
391
|
+
}, {
|
|
392
|
+
e: undefined,
|
|
393
|
+
t: undefined
|
|
394
|
+
});
|
|
395
|
+
return _el$4;
|
|
396
|
+
})();
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
// Fleet CollapsedRow: muted label left, caller-supplied value right. Used
|
|
400
|
+
// for the collapsed sidebar view; the Antigravity adapter renders one
|
|
401
|
+
// CollapsedRow per visible account (Claude's sibling collapses to a
|
|
402
|
+
// single primary-quota line, but Antigravity's multi-quota model fits a
|
|
403
|
+
// per-account row better when the sidebar is collapsed).
|
|
404
|
+
function CollapsedRow(props) {
|
|
405
|
+
return (() => {
|
|
406
|
+
var _el$8 = _$createElement("box"),
|
|
407
|
+
_el$9 = _$createElement("text");
|
|
408
|
+
_$insertNode(_el$8, _el$9);
|
|
409
|
+
_$setProp(_el$8, "width", '100%');
|
|
410
|
+
_$setProp(_el$8, "flexDirection", 'row');
|
|
411
|
+
_$setProp(_el$8, "justifyContent", 'space-between');
|
|
412
|
+
_$insert(_el$9, () => props.label);
|
|
413
|
+
_$insert(_el$8, () => props.children, null);
|
|
414
|
+
_$effect(_$p => _$setProp(_el$9, "fg", props.theme().textMuted, _$p));
|
|
415
|
+
return _el$8;
|
|
416
|
+
})();
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
// Fleet QuotaRow, adapted to Antigravity's `remainingPercent + resetAt`
|
|
420
|
+
// shape. The left group stacks label + bar + pct in fixed columns so
|
|
421
|
+
// bars line up across rows; the right group carries the reset countdown
|
|
422
|
+
// when the plugin has cached a reset time. Tone is read off the
|
|
423
|
+
// remaining percentage via the antigravity threshold rules — the fleet's
|
|
424
|
+
// `usageTone` would invert the polarity (healthy = high remaining vs
|
|
425
|
+
// healthy = low used), so we keep the antigravity-local `quotaTone`.
|
|
426
|
+
function QuotaRow(props) {
|
|
427
|
+
const used = () => props.entry ? 100 - clamp(props.entry.remainingPercent, 0, 100) : null;
|
|
428
|
+
const reset = () => props.entry ? formatResetIn(props.entry.resetAt, props.now) : '';
|
|
429
|
+
return _$createComponent(Show, {
|
|
430
|
+
get when() {
|
|
431
|
+
return used() != null;
|
|
432
|
+
},
|
|
433
|
+
get fallback() {
|
|
434
|
+
return (() => {
|
|
435
|
+
var _el$14 = _$createElement("box"),
|
|
436
|
+
_el$15 = _$createElement("text"),
|
|
437
|
+
_el$16 = _$createElement("text");
|
|
438
|
+
_$insertNode(_el$14, _el$15);
|
|
439
|
+
_$insertNode(_el$14, _el$16);
|
|
440
|
+
_$setProp(_el$14, "width", '100%');
|
|
441
|
+
_$setProp(_el$14, "flexDirection", 'row');
|
|
442
|
+
_$setProp(_el$14, "justifyContent", 'space-between');
|
|
443
|
+
_$insert(_el$15, () => props.label.padEnd(3));
|
|
444
|
+
_$insertNode(_el$16, _$createTextNode(`—`));
|
|
445
|
+
_$effect(_p$ => {
|
|
446
|
+
var _v$6 = props.theme().textMuted,
|
|
447
|
+
_v$7 = props.theme().textMuted;
|
|
448
|
+
_v$6 !== _p$.e && (_p$.e = _$setProp(_el$15, "fg", _v$6, _p$.e));
|
|
449
|
+
_v$7 !== _p$.t && (_p$.t = _$setProp(_el$16, "fg", _v$7, _p$.t));
|
|
450
|
+
return _p$;
|
|
451
|
+
}, {
|
|
452
|
+
e: undefined,
|
|
453
|
+
t: undefined
|
|
454
|
+
});
|
|
455
|
+
return _el$14;
|
|
456
|
+
})();
|
|
457
|
+
},
|
|
458
|
+
get children() {
|
|
459
|
+
var _el$0 = _$createElement("box"),
|
|
460
|
+
_el$1 = _$createElement("box"),
|
|
461
|
+
_el$10 = _$createElement("text"),
|
|
462
|
+
_el$11 = _$createElement("box"),
|
|
463
|
+
_el$12 = _$createElement("text");
|
|
464
|
+
_$insertNode(_el$0, _el$1);
|
|
465
|
+
_$setProp(_el$0, "width", '100%');
|
|
466
|
+
_$setProp(_el$0, "flexDirection", 'row');
|
|
467
|
+
_$setProp(_el$0, "justifyContent", 'space-between');
|
|
468
|
+
_$insertNode(_el$1, _el$10);
|
|
469
|
+
_$insertNode(_el$1, _el$11);
|
|
470
|
+
_$insertNode(_el$1, _el$12);
|
|
471
|
+
_$setProp(_el$1, "flexDirection", 'row');
|
|
472
|
+
_$setProp(_el$10, "width", 3);
|
|
473
|
+
_$setProp(_el$10, "flexShrink", 0);
|
|
474
|
+
_$insert(_el$10, () => props.label);
|
|
475
|
+
_$setProp(_el$11, "flexShrink", 0);
|
|
476
|
+
_$setProp(_el$11, "flexDirection", 'row');
|
|
477
|
+
_$insert(_el$11, _$createComponent(For, {
|
|
478
|
+
get each() {
|
|
479
|
+
return quotaBarSegments(used() ?? 0, props.appearance);
|
|
480
|
+
},
|
|
481
|
+
children: segment => (() => {
|
|
482
|
+
var _el$18 = _$createElement("text");
|
|
483
|
+
_$insert(_el$18, () => segment.text);
|
|
484
|
+
_$effect(_$p => _$setProp(_el$18, "fg", toneColor(props.theme(), segment.tone), _$p));
|
|
485
|
+
return _el$18;
|
|
486
|
+
})()
|
|
487
|
+
}));
|
|
488
|
+
_$insert(_el$12, () => ` ${String(Math.round(used() ?? 0)).padStart(3)}%`);
|
|
489
|
+
_$insert(_el$0, _$createComponent(Show, {
|
|
490
|
+
get when() {
|
|
491
|
+
return reset();
|
|
492
|
+
},
|
|
493
|
+
get children() {
|
|
494
|
+
var _el$13 = _$createElement("text");
|
|
495
|
+
_$insert(_el$13, reset);
|
|
496
|
+
_$effect(_$p => _$setProp(_el$13, "fg", props.theme().textMuted, _$p));
|
|
497
|
+
return _el$13;
|
|
498
|
+
}
|
|
499
|
+
}), null);
|
|
500
|
+
_$effect(_p$ => {
|
|
501
|
+
var _v$3 = props.theme().textMuted,
|
|
502
|
+
_v$4 = props.appearance.barWidth,
|
|
503
|
+
_v$5 = toneColor(props.theme(), quotaTone(used() ?? 0, props.appearance));
|
|
504
|
+
_v$3 !== _p$.e && (_p$.e = _$setProp(_el$10, "fg", _v$3, _p$.e));
|
|
505
|
+
_v$4 !== _p$.t && (_p$.t = _$setProp(_el$11, "width", _v$4, _p$.t));
|
|
506
|
+
_v$5 !== _p$.a && (_p$.a = _$setProp(_el$12, "fg", _v$5, _p$.a));
|
|
507
|
+
return _p$;
|
|
508
|
+
}, {
|
|
509
|
+
e: undefined,
|
|
510
|
+
t: undefined,
|
|
511
|
+
a: undefined
|
|
512
|
+
});
|
|
513
|
+
return _el$0;
|
|
514
|
+
}
|
|
515
|
+
});
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
// Fleet AccountBlock, adapted to Antigravity's per-account data. Header
|
|
519
|
+
// row is account label (left) + status word (right). The body renders one
|
|
520
|
+
// QuotaRow per present quota group in the fleet's stable order, then a
|
|
521
|
+
// muted secondary line with the account's health score and, when
|
|
522
|
+
// relevant, a cooldown countdown. Status word priorities (first match
|
|
523
|
+
// wins):
|
|
524
|
+
// - `off` when the account is disabled
|
|
525
|
+
// - `cooling` when cooldownUntil is still in the future
|
|
526
|
+
// - `active` when current === true
|
|
527
|
+
// - `idle` for the fallback (current === false) case
|
|
528
|
+
function AccountBlock(props) {
|
|
529
|
+
const active = () => props.active ?? props.account.current;
|
|
530
|
+
const statusWord = () => {
|
|
531
|
+
if (!props.account.enabled) return 'off';
|
|
532
|
+
const cd = props.account.cooldownUntil;
|
|
533
|
+
if (typeof cd === 'number' && cd > props.now()) return 'cooling';
|
|
534
|
+
return active() ? 'active' : 'idle';
|
|
535
|
+
};
|
|
536
|
+
const statusTone = () => {
|
|
537
|
+
if (!props.account.enabled) return 'muted';
|
|
538
|
+
const cd = props.account.cooldownUntil;
|
|
539
|
+
if (typeof cd === 'number' && cd > props.now()) return 'warn';
|
|
540
|
+
return active() ? 'ok' : 'muted';
|
|
541
|
+
};
|
|
542
|
+
const cooldownMs = () => {
|
|
543
|
+
const cd = props.account.cooldownUntil;
|
|
544
|
+
if (typeof cd !== 'number') return 0;
|
|
545
|
+
return Math.max(0, cd - props.now());
|
|
546
|
+
};
|
|
547
|
+
const healthText = () => {
|
|
548
|
+
const base = `health ${Math.round(clamp(props.account.health, 0, 100))}`;
|
|
549
|
+
return cooldownMs() > 0 ? `${base} · cooling ${formatWait(cooldownMs())}` : base;
|
|
550
|
+
};
|
|
551
|
+
return (() => {
|
|
552
|
+
var _el$19 = _$createElement("box"),
|
|
553
|
+
_el$20 = _$createElement("box"),
|
|
554
|
+
_el$21 = _$createElement("text"),
|
|
555
|
+
_el$22 = _$createElement("b"),
|
|
556
|
+
_el$23 = _$createElement("text"),
|
|
557
|
+
_el$24 = _$createElement("b"),
|
|
558
|
+
_el$25 = _$createElement("box"),
|
|
559
|
+
_el$26 = _$createElement("text");
|
|
560
|
+
_$insertNode(_el$19, _el$20);
|
|
561
|
+
_$insertNode(_el$19, _el$25);
|
|
562
|
+
_$setProp(_el$19, "width", '100%');
|
|
563
|
+
_$setProp(_el$19, "flexDirection", 'column');
|
|
564
|
+
_$insertNode(_el$20, _el$21);
|
|
565
|
+
_$insertNode(_el$20, _el$23);
|
|
566
|
+
_$setProp(_el$20, "width", '100%');
|
|
567
|
+
_$setProp(_el$20, "flexDirection", 'row');
|
|
568
|
+
_$setProp(_el$20, "justifyContent", 'space-between');
|
|
569
|
+
_$insertNode(_el$21, _el$22);
|
|
570
|
+
_$insert(_el$22, () => props.account.label);
|
|
571
|
+
_$insertNode(_el$23, _el$24);
|
|
572
|
+
_$insert(_el$24, statusWord);
|
|
573
|
+
_$insert(_el$19, _$createComponent(For, {
|
|
574
|
+
each: QUOTA_ORDER,
|
|
575
|
+
children: key => _$createComponent(QuotaRow, {
|
|
576
|
+
get theme() {
|
|
577
|
+
return props.theme;
|
|
578
|
+
},
|
|
579
|
+
get appearance() {
|
|
580
|
+
return props.appearance;
|
|
581
|
+
},
|
|
582
|
+
get label() {
|
|
583
|
+
return QUOTA_LABELS[key];
|
|
584
|
+
},
|
|
585
|
+
get entry() {
|
|
586
|
+
return props.account.quota[key];
|
|
587
|
+
},
|
|
588
|
+
get now() {
|
|
589
|
+
return props.now;
|
|
590
|
+
}
|
|
591
|
+
})
|
|
592
|
+
}), _el$25);
|
|
593
|
+
_$insertNode(_el$25, _el$26);
|
|
594
|
+
_$setProp(_el$25, "width", '100%');
|
|
595
|
+
_$setProp(_el$25, "flexDirection", 'row');
|
|
596
|
+
_$insert(_el$26, () => ` ${healthText()}`);
|
|
597
|
+
_$effect(_p$ => {
|
|
598
|
+
var _v$8 = props.marginTop ?? 0,
|
|
599
|
+
_v$9 = props.theme().text,
|
|
600
|
+
_v$0 = toneColor(props.theme(), statusTone()),
|
|
601
|
+
_v$1 = props.theme().textMuted;
|
|
602
|
+
_v$8 !== _p$.e && (_p$.e = _$setProp(_el$19, "marginTop", _v$8, _p$.e));
|
|
603
|
+
_v$9 !== _p$.t && (_p$.t = _$setProp(_el$21, "fg", _v$9, _p$.t));
|
|
604
|
+
_v$0 !== _p$.a && (_p$.a = _$setProp(_el$23, "fg", _v$0, _p$.a));
|
|
605
|
+
_v$1 !== _p$.o && (_p$.o = _$setProp(_el$26, "fg", _v$1, _p$.o));
|
|
606
|
+
return _p$;
|
|
607
|
+
}, {
|
|
608
|
+
e: undefined,
|
|
609
|
+
t: undefined,
|
|
610
|
+
a: undefined,
|
|
611
|
+
o: undefined
|
|
612
|
+
});
|
|
613
|
+
return _el$19;
|
|
614
|
+
})();
|
|
615
|
+
}
|
|
616
|
+
function formatWait(ms) {
|
|
617
|
+
const seconds = Math.ceil(ms / 1000);
|
|
618
|
+
if (seconds < 60) return `${seconds}s`;
|
|
619
|
+
const minutes = Math.floor(seconds / 60);
|
|
620
|
+
const remaining = seconds % 60;
|
|
621
|
+
return remaining > 0 ? `${minutes}m ${remaining}s` : `${minutes}m`;
|
|
622
|
+
}
|
|
623
|
+
export function resolveQuotaDialogActiveId(state, sessionId) {
|
|
624
|
+
return (sessionId ? state.activeRouting[sessionId]?.accountId : undefined) ?? state.accounts.find(account => account.current)?.id;
|
|
625
|
+
}
|
|
626
|
+
export function QuotaDialogContent(props) {
|
|
627
|
+
const prefs = props.controller.prefs;
|
|
628
|
+
const [state, setState] = createSignal(EMPTY_STATE);
|
|
629
|
+
const refresh = () => {
|
|
630
|
+
setState(readSidebarState());
|
|
631
|
+
};
|
|
632
|
+
createEffect(() => {
|
|
633
|
+
const timer = setInterval(refresh, prefs().pollMs);
|
|
634
|
+
onCleanup(() => clearInterval(timer));
|
|
635
|
+
});
|
|
636
|
+
setTimeout(refresh, 0);
|
|
637
|
+
const theme = () => props.api.theme.current;
|
|
638
|
+
const visibleAccounts = () => {
|
|
639
|
+
if (prefs().sections.fallbackAccounts) return state().accounts;
|
|
640
|
+
return state().accounts.filter(account => account.current);
|
|
641
|
+
};
|
|
642
|
+
const activeId = () => resolveQuotaDialogActiveId(state(), props.sessionId);
|
|
643
|
+
return (() => {
|
|
644
|
+
var _el$27 = _$createElement("box"),
|
|
645
|
+
_el$28 = _$createElement("box"),
|
|
646
|
+
_el$29 = _$createElement("box"),
|
|
647
|
+
_el$30 = _$createElement("text"),
|
|
648
|
+
_el$31 = _$createElement("b");
|
|
649
|
+
_$insertNode(_el$27, _el$28);
|
|
650
|
+
_$setProp(_el$27, "flexDirection", 'column');
|
|
651
|
+
_$setProp(_el$27, "padding", 2);
|
|
652
|
+
_$setProp(_el$27, "width", '100%');
|
|
653
|
+
_$setProp(_el$27, "alignItems", 'center');
|
|
654
|
+
_$insertNode(_el$28, _el$29);
|
|
655
|
+
_$setProp(_el$28, "flexDirection", 'column');
|
|
656
|
+
_$setProp(_el$28, "width", 58);
|
|
657
|
+
_$insertNode(_el$29, _el$30);
|
|
658
|
+
_$setProp(_el$29, "width", '100%');
|
|
659
|
+
_$setProp(_el$29, "justifyContent", 'center');
|
|
660
|
+
_$setProp(_el$29, "marginBottom", 1);
|
|
661
|
+
_$insertNode(_el$30, _el$31);
|
|
662
|
+
_$insertNode(_el$31, _$createTextNode(`Antigravity Quota`));
|
|
663
|
+
_$insert(_el$28, _$createComponent(For, {
|
|
664
|
+
get each() {
|
|
665
|
+
return visibleAccounts();
|
|
666
|
+
},
|
|
667
|
+
children: (account, index) => _$createComponent(AccountBlock, {
|
|
668
|
+
theme: theme,
|
|
669
|
+
get appearance() {
|
|
670
|
+
return prefs().appearance;
|
|
671
|
+
},
|
|
672
|
+
account: account,
|
|
673
|
+
get active() {
|
|
674
|
+
return activeId() === account.id;
|
|
675
|
+
},
|
|
676
|
+
now: () => Date.now(),
|
|
677
|
+
get marginTop() {
|
|
678
|
+
return index() === 0 ? 0 : 1;
|
|
679
|
+
}
|
|
680
|
+
})
|
|
681
|
+
}), null);
|
|
682
|
+
_$effect(_$p => _$setProp(_el$30, "fg", theme().text, _$p));
|
|
683
|
+
return _el$27;
|
|
684
|
+
})();
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
// --- SidebarPanel ----------------------------------------------------------
|
|
688
|
+
|
|
689
|
+
export function SidebarPanel(props) {
|
|
690
|
+
const logger = resolveLogger(props.logger);
|
|
691
|
+
const now = props.now ?? (() => Date.now());
|
|
692
|
+
const pollMs = props.pollIntervalMs ?? POLL_INTERVAL_MS;
|
|
693
|
+
const controller = props.controller ?? getSidebarController();
|
|
694
|
+
const collapsed = controller.collapsed;
|
|
695
|
+
const prefs = controller.prefs;
|
|
696
|
+
// Live host theme — falls back to a sensible dark palette when the host
|
|
697
|
+
// does not expose one. Solid tracks `theme()` so a theme switch re-renders
|
|
698
|
+
// every styled span/border without a manual subscription.
|
|
699
|
+
const theme = () => props.theme?.() ?? FALLBACK_THEME;
|
|
700
|
+
const [state, setState] = createSignal({
|
|
701
|
+
loaded: EMPTY_STATE,
|
|
702
|
+
lastReadAt: 0,
|
|
703
|
+
lastError: null
|
|
704
|
+
});
|
|
705
|
+
const refresh = () => {
|
|
706
|
+
try {
|
|
707
|
+
const loaded = readSidebarState(props.stateFile);
|
|
708
|
+
setState({
|
|
709
|
+
loaded,
|
|
710
|
+
lastReadAt: now(),
|
|
711
|
+
lastError: null
|
|
712
|
+
});
|
|
713
|
+
} catch (error) {
|
|
714
|
+
logger.warn('sidebar-poll-failed', {
|
|
715
|
+
error: formatError(error)
|
|
716
|
+
});
|
|
717
|
+
setState(prev => ({
|
|
718
|
+
...prev,
|
|
719
|
+
lastReadAt: now(),
|
|
720
|
+
lastError: formatError(error)
|
|
721
|
+
}));
|
|
722
|
+
}
|
|
723
|
+
};
|
|
724
|
+
onMount(() => {
|
|
725
|
+
refresh();
|
|
726
|
+
const interval = setInterval(refresh, pollMs);
|
|
727
|
+
onCleanup(() => clearInterval(interval));
|
|
728
|
+
});
|
|
729
|
+
const hasData = () => state().loaded.accounts.length > 0;
|
|
730
|
+
const backoffActive = () => {
|
|
731
|
+
const until = state().loaded.quotaBackoffUntil;
|
|
732
|
+
return typeof until === 'number' && until > now();
|
|
733
|
+
};
|
|
734
|
+
const lastError = () => state().lastError ?? state().loaded.lastError;
|
|
735
|
+
const degraded = () => backoffActive() || !!lastError();
|
|
736
|
+
// Honors sections.fallbackAccounts. Both the expanded (AccountBlock list)
|
|
737
|
+
// and the collapsed (CollapsedRow list) paths use the same filter so the
|
|
738
|
+
// user sees the same account set in either mode.
|
|
739
|
+
const visibleAccounts = () => {
|
|
740
|
+
const showFallback = prefs().sections.fallbackAccounts;
|
|
741
|
+
if (showFallback) return state().loaded.accounts;
|
|
742
|
+
return state().loaded.accounts.filter(account => account.current);
|
|
743
|
+
};
|
|
744
|
+
const currentRoute = () => {
|
|
745
|
+
const routes = state().loaded.activeRouting;
|
|
746
|
+
const entry = props.sessionId ? routes[props.sessionId] : Object.values(routes).sort((a, b) => b.updatedAt - a.updatedAt)[0];
|
|
747
|
+
if (!entry) return null;
|
|
748
|
+
return {
|
|
749
|
+
strategy: entry.strategy,
|
|
750
|
+
family: entry.modelFamily,
|
|
751
|
+
style: entry.headerStyle
|
|
752
|
+
};
|
|
753
|
+
};
|
|
754
|
+
|
|
755
|
+
// Header badge: ▼/▶ {label}. The fleet shows the version string on the
|
|
756
|
+
// right when no degraded state is present; the antigravity adapter keeps
|
|
757
|
+
// that right-alignment and surfaces `degraded` as a "LIMITED" badge
|
|
758
|
+
// instead of the "1/1 ready" count the previous revision rendered.
|
|
759
|
+
const headerLabel = () => {
|
|
760
|
+
const name = prefs().header.label;
|
|
761
|
+
return !hasData() ? name : collapsed() ? `\u25b6 ${name}` : `\u25bc ${name}`;
|
|
762
|
+
};
|
|
763
|
+
return (() => {
|
|
764
|
+
var _el$33 = _$createElement("box"),
|
|
765
|
+
_el$34 = _$createElement("box"),
|
|
766
|
+
_el$35 = _$createElement("box"),
|
|
767
|
+
_el$36 = _$createElement("text"),
|
|
768
|
+
_el$37 = _$createElement("b");
|
|
769
|
+
_$insertNode(_el$33, _el$34);
|
|
770
|
+
_$setProp(_el$33, "width", '100%');
|
|
771
|
+
_$setProp(_el$33, "flexDirection", 'column');
|
|
772
|
+
_$setProp(_el$33, "border", SINGLE_BORDER);
|
|
773
|
+
_$setProp(_el$33, "paddingTop", 1);
|
|
774
|
+
_$setProp(_el$33, "paddingBottom", 1);
|
|
775
|
+
_$setProp(_el$33, "paddingLeft", 1);
|
|
776
|
+
_$setProp(_el$33, "paddingRight", 1);
|
|
777
|
+
_$insertNode(_el$34, _el$35);
|
|
778
|
+
_$setProp(_el$34, "width", '100%');
|
|
779
|
+
_$setProp(_el$34, "flexDirection", 'row');
|
|
780
|
+
_$setProp(_el$34, "justifyContent", 'space-between');
|
|
781
|
+
_$setProp(_el$34, "alignItems", 'center');
|
|
782
|
+
_$setProp(_el$34, "onMouseDown", () => {
|
|
783
|
+
// Mirror the fleet guard: only toggle when there is data to expand
|
|
784
|
+
// into. Without this a click on the empty-awaiting header would just
|
|
785
|
+
// toggle the affordance for nothing.
|
|
786
|
+
if (hasData()) controller.toggleCollapsed();
|
|
787
|
+
});
|
|
788
|
+
_$insertNode(_el$35, _el$36);
|
|
789
|
+
_$setProp(_el$35, "paddingLeft", 1);
|
|
790
|
+
_$setProp(_el$35, "paddingRight", 1);
|
|
791
|
+
_$insertNode(_el$36, _el$37);
|
|
792
|
+
_$insert(_el$37, headerLabel);
|
|
793
|
+
_$insert(_el$34, _$createComponent(Show, {
|
|
794
|
+
get when() {
|
|
795
|
+
return degraded();
|
|
796
|
+
},
|
|
797
|
+
get fallback() {
|
|
798
|
+
return _$createComponent(Show, {
|
|
799
|
+
get when() {
|
|
800
|
+
return prefs().header.showVersion && PLUGIN_VERSION !== '';
|
|
801
|
+
},
|
|
802
|
+
get children() {
|
|
803
|
+
var _el$42 = _$createElement("text");
|
|
804
|
+
_$insert(_el$42, `v${PLUGIN_VERSION}`);
|
|
805
|
+
_$effect(_$p => _$setProp(_el$42, "fg", theme().textMuted, _$p));
|
|
806
|
+
return _el$42;
|
|
807
|
+
}
|
|
808
|
+
});
|
|
809
|
+
},
|
|
810
|
+
get children() {
|
|
811
|
+
var _el$38 = _$createElement("box"),
|
|
812
|
+
_el$39 = _$createElement("text"),
|
|
813
|
+
_el$40 = _$createElement("b");
|
|
814
|
+
_$insertNode(_el$38, _el$39);
|
|
815
|
+
_$setProp(_el$38, "paddingLeft", 1);
|
|
816
|
+
_$setProp(_el$38, "paddingRight", 1);
|
|
817
|
+
_$insertNode(_el$39, _el$40);
|
|
818
|
+
_$insertNode(_el$40, _$createTextNode(`LIMITED`));
|
|
819
|
+
_$effect(_p$ => {
|
|
820
|
+
var _v$10 = theme().warning,
|
|
821
|
+
_v$11 = theme().background;
|
|
822
|
+
_v$10 !== _p$.e && (_p$.e = _$setProp(_el$38, "backgroundColor", _v$10, _p$.e));
|
|
823
|
+
_v$11 !== _p$.t && (_p$.t = _$setProp(_el$39, "fg", _v$11, _p$.t));
|
|
824
|
+
return _p$;
|
|
825
|
+
}, {
|
|
826
|
+
e: undefined,
|
|
827
|
+
t: undefined
|
|
828
|
+
});
|
|
829
|
+
return _el$38;
|
|
830
|
+
}
|
|
831
|
+
}), null);
|
|
832
|
+
_$insert(_el$33, _$createComponent(Show, {
|
|
833
|
+
get when() {
|
|
834
|
+
return _$memo(() => !!collapsed())() && hasData();
|
|
835
|
+
},
|
|
836
|
+
get children() {
|
|
837
|
+
return (() => {
|
|
838
|
+
const account = () => visibleAccounts().find(entry => entry.current) ?? visibleAccounts()[0];
|
|
839
|
+
const used = () => {
|
|
840
|
+
const entry = account()?.quota.claude;
|
|
841
|
+
return entry ? 100 - clamp(entry.remainingPercent, 0, 100) : null;
|
|
842
|
+
};
|
|
843
|
+
const unavailable = () => {
|
|
844
|
+
const selected = account();
|
|
845
|
+
return selected != null && (!selected.enabled || selected.cooldownUntil != null && selected.cooldownUntil > now());
|
|
846
|
+
};
|
|
847
|
+
return _$createComponent(Show, {
|
|
848
|
+
get when() {
|
|
849
|
+
return account();
|
|
850
|
+
},
|
|
851
|
+
children: selected => _$createComponent(CollapsedRow, {
|
|
852
|
+
theme: theme,
|
|
853
|
+
get label() {
|
|
854
|
+
return selected().label;
|
|
855
|
+
},
|
|
856
|
+
get children() {
|
|
857
|
+
var _el$43 = _$createElement("box"),
|
|
858
|
+
_el$44 = _$createElement("text"),
|
|
859
|
+
_el$45 = _$createElement("b"),
|
|
860
|
+
_el$46 = _$createElement("text");
|
|
861
|
+
_$insertNode(_el$43, _el$44);
|
|
862
|
+
_$insertNode(_el$43, _el$46);
|
|
863
|
+
_$setProp(_el$43, "flexDirection", 'row');
|
|
864
|
+
_$insertNode(_el$44, _el$45);
|
|
865
|
+
_$insert(_el$45, (() => {
|
|
866
|
+
var _c$ = _$memo(() => used() == null);
|
|
867
|
+
return () => _c$() ? '—' : `Cl: ${Math.round(used() ?? 0)}%`;
|
|
868
|
+
})());
|
|
869
|
+
_$insert(_el$46, () => unavailable() ? ' ⊘' : ' ●');
|
|
870
|
+
_$effect(_p$ => {
|
|
871
|
+
var _v$15 = toneColor(theme(), used() == null ? 'muted' : quotaTone(used() ?? 0, prefs().appearance)),
|
|
872
|
+
_v$16 = toneColor(theme(), unavailable() ? 'err' : quotaTone(used() ?? 0, prefs().appearance));
|
|
873
|
+
_v$15 !== _p$.e && (_p$.e = _$setProp(_el$44, "fg", _v$15, _p$.e));
|
|
874
|
+
_v$16 !== _p$.t && (_p$.t = _$setProp(_el$46, "fg", _v$16, _p$.t));
|
|
875
|
+
return _p$;
|
|
876
|
+
}, {
|
|
877
|
+
e: undefined,
|
|
878
|
+
t: undefined
|
|
879
|
+
});
|
|
880
|
+
return _el$43;
|
|
881
|
+
}
|
|
882
|
+
})
|
|
883
|
+
});
|
|
884
|
+
})();
|
|
885
|
+
}
|
|
886
|
+
}), null);
|
|
887
|
+
_$insert(_el$33, _$createComponent(Show, {
|
|
888
|
+
get when() {
|
|
889
|
+
return !collapsed() || !hasData();
|
|
890
|
+
},
|
|
891
|
+
get children() {
|
|
892
|
+
return _$createComponent(Show, {
|
|
893
|
+
get when() {
|
|
894
|
+
return hasData();
|
|
895
|
+
},
|
|
896
|
+
get fallback() {
|
|
897
|
+
return (() => {
|
|
898
|
+
var _el$47 = _$createElement("box"),
|
|
899
|
+
_el$48 = _$createElement("text");
|
|
900
|
+
_$insertNode(_el$47, _el$48);
|
|
901
|
+
_$setProp(_el$47, "marginTop", 1);
|
|
902
|
+
_$setProp(_el$47, "width", '100%');
|
|
903
|
+
_$insertNode(_el$48, _$createTextNode(`Waiting for quota…`));
|
|
904
|
+
_$effect(_$p => _$setProp(_el$48, "fg", theme().textMuted, _$p));
|
|
905
|
+
return _el$47;
|
|
906
|
+
})();
|
|
907
|
+
},
|
|
908
|
+
get children() {
|
|
909
|
+
return [_$createComponent(Show, {
|
|
910
|
+
get when() {
|
|
911
|
+
return prefs().sections.quota;
|
|
912
|
+
},
|
|
913
|
+
get children() {
|
|
914
|
+
return [_$createComponent(SectionHeader, {
|
|
915
|
+
theme: theme,
|
|
916
|
+
title: "Quota"
|
|
917
|
+
}), _$createComponent(For, {
|
|
918
|
+
get each() {
|
|
919
|
+
return visibleAccounts();
|
|
920
|
+
},
|
|
921
|
+
children: (account, index) => _$createComponent(AccountBlock, {
|
|
922
|
+
theme: theme,
|
|
923
|
+
get appearance() {
|
|
924
|
+
return prefs().appearance;
|
|
925
|
+
},
|
|
926
|
+
account: account,
|
|
927
|
+
now: now,
|
|
928
|
+
get marginTop() {
|
|
929
|
+
return index() === 0 ? 0 : 1;
|
|
930
|
+
}
|
|
931
|
+
})
|
|
932
|
+
})];
|
|
933
|
+
}
|
|
934
|
+
}), _$createComponent(Show, {
|
|
935
|
+
get when() {
|
|
936
|
+
return prefs().sections.routing;
|
|
937
|
+
},
|
|
938
|
+
get children() {
|
|
939
|
+
return [_$createComponent(SectionHeader, {
|
|
940
|
+
theme: theme,
|
|
941
|
+
title: "Routing"
|
|
942
|
+
}), _$createComponent(Show, {
|
|
943
|
+
get when() {
|
|
944
|
+
return currentRoute();
|
|
945
|
+
},
|
|
946
|
+
get fallback() {
|
|
947
|
+
return _$createComponent(StatRow, {
|
|
948
|
+
theme: theme,
|
|
949
|
+
label: "Route",
|
|
950
|
+
value: "\u2014",
|
|
951
|
+
tone: "muted"
|
|
952
|
+
});
|
|
953
|
+
},
|
|
954
|
+
children: route => _$createComponent(StatRow, {
|
|
955
|
+
theme: theme,
|
|
956
|
+
label: "Route",
|
|
957
|
+
get value() {
|
|
958
|
+
return `${route().strategy ? `${route().strategy} · ` : ''}${route().family}: ${route().style}`;
|
|
959
|
+
},
|
|
960
|
+
tone: "accent"
|
|
961
|
+
})
|
|
962
|
+
})];
|
|
963
|
+
}
|
|
964
|
+
}), _$createComponent(Show, {
|
|
965
|
+
get when() {
|
|
966
|
+
return _$memo(() => !!degraded())() && prefs().sections.health;
|
|
967
|
+
},
|
|
968
|
+
get children() {
|
|
969
|
+
return [_$createComponent(SectionHeader, {
|
|
970
|
+
theme: theme,
|
|
971
|
+
title: "Health"
|
|
972
|
+
}), _$createComponent(Show, {
|
|
973
|
+
get when() {
|
|
974
|
+
return backoffActive();
|
|
975
|
+
},
|
|
976
|
+
get children() {
|
|
977
|
+
return _$createComponent(StatRow, {
|
|
978
|
+
theme: theme,
|
|
979
|
+
label: "Quota API",
|
|
980
|
+
get value() {
|
|
981
|
+
return `backoff ${formatResetIn(state().loaded.quotaBackoffUntil, now)}`;
|
|
982
|
+
},
|
|
983
|
+
tone: "warn"
|
|
984
|
+
});
|
|
985
|
+
}
|
|
986
|
+
}), _$createComponent(Show, {
|
|
987
|
+
get when() {
|
|
988
|
+
return lastError();
|
|
989
|
+
},
|
|
990
|
+
get children() {
|
|
991
|
+
return _$createComponent(StatRow, {
|
|
992
|
+
theme: theme,
|
|
993
|
+
label: "Last error",
|
|
994
|
+
get value() {
|
|
995
|
+
return lastError() ?? '';
|
|
996
|
+
},
|
|
997
|
+
tone: "err"
|
|
998
|
+
});
|
|
999
|
+
}
|
|
1000
|
+
})];
|
|
1001
|
+
}
|
|
1002
|
+
})];
|
|
1003
|
+
}
|
|
1004
|
+
});
|
|
1005
|
+
}
|
|
1006
|
+
}), null);
|
|
1007
|
+
_$effect(_p$ => {
|
|
1008
|
+
var _v$12 = theme().borderActive,
|
|
1009
|
+
_v$13 = theme().accent,
|
|
1010
|
+
_v$14 = theme().background;
|
|
1011
|
+
_v$12 !== _p$.e && (_p$.e = _$setProp(_el$33, "borderColor", _v$12, _p$.e));
|
|
1012
|
+
_v$13 !== _p$.t && (_p$.t = _$setProp(_el$35, "backgroundColor", _v$13, _p$.t));
|
|
1013
|
+
_v$14 !== _p$.a && (_p$.a = _$setProp(_el$36, "fg", _v$14, _p$.a));
|
|
1014
|
+
return _p$;
|
|
1015
|
+
}, {
|
|
1016
|
+
e: undefined,
|
|
1017
|
+
t: undefined,
|
|
1018
|
+
a: undefined
|
|
1019
|
+
});
|
|
1020
|
+
return _el$33;
|
|
1021
|
+
})();
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
/**
|
|
1025
|
+
* Solid slot registry binding exposed for hosts that want to mount the
|
|
1026
|
+
* sidebar inside their renderer. Hosts that already own a slot registry can
|
|
1027
|
+
* use `createSlot` directly; we re-export for convenience and to keep the
|
|
1028
|
+
* contract visible at the module entry point.
|
|
1029
|
+
*/
|
|
1030
|
+
export const sidebar_content = createSlot;
|
|
1031
|
+
export function startRpcNotificationPolling(options) {
|
|
1032
|
+
if (rpcPollStarted) return;
|
|
1033
|
+
rpcPollStarted = true;
|
|
1034
|
+
options.schedule(async () => {
|
|
1035
|
+
if (rpcInFlight) return;
|
|
1036
|
+
rpcInFlight = true;
|
|
1037
|
+
try {
|
|
1038
|
+
const sessionId = options.currentSessionId();
|
|
1039
|
+
const cursorKey = sessionId ?? GLOBAL_NOTIFICATION_CURSOR;
|
|
1040
|
+
let cursor = notificationCursorBySession.get(cursorKey) ?? 0;
|
|
1041
|
+
const notifications = await options.pending(cursor, sessionId);
|
|
1042
|
+
for (const notification of [...notifications].sort((a, b) => a.id - b.id)) {
|
|
1043
|
+
if (notification.id <= cursor) continue;
|
|
1044
|
+
cursor = Math.max(cursor, notification.id);
|
|
1045
|
+
if (dispatchedNotificationIds.has(notification.id)) continue;
|
|
1046
|
+
dispatchedNotificationIds.add(notification.id);
|
|
1047
|
+
if (dispatchedNotificationIds.size > 100) {
|
|
1048
|
+
const oldestId = dispatchedNotificationIds.values().next().value;
|
|
1049
|
+
if (oldestId !== undefined) dispatchedNotificationIds.delete(oldestId);
|
|
1050
|
+
}
|
|
1051
|
+
await options.dispatch(notification);
|
|
1052
|
+
}
|
|
1053
|
+
if (!notificationCursorBySession.has(cursorKey)) {
|
|
1054
|
+
while (notificationCursorBySession.size >= MAX_NOTIFICATION_CURSORS) {
|
|
1055
|
+
const oldest = notificationCursorBySession.keys().next().value;
|
|
1056
|
+
if (oldest === undefined) break;
|
|
1057
|
+
notificationCursorBySession.delete(oldest);
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1060
|
+
notificationCursorBySession.set(cursorKey, cursor);
|
|
1061
|
+
} catch (error) {
|
|
1062
|
+
// Surface the swallowed error through the file logger rather than
|
|
1063
|
+
// stdout/stderr (the host terminal is the frame buffer — any byte
|
|
1064
|
+
// written here corrupts every subsequent cell). Without this, a
|
|
1065
|
+
// transient RPC outage is invisible to operators. The catch stays
|
|
1066
|
+
// because one failed poll must never break the next — the scheduler
|
|
1067
|
+
// is a setInterval and a thrown error there would crash the
|
|
1068
|
+
// process.
|
|
1069
|
+
options.logger.warn('rpc-poll-failed', {
|
|
1070
|
+
error: error instanceof Error ? error.message : String(error)
|
|
1071
|
+
});
|
|
1072
|
+
} finally {
|
|
1073
|
+
rpcInFlight = false;
|
|
1074
|
+
}
|
|
1075
|
+
}, RPC_POLL_MS);
|
|
1076
|
+
}
|
|
1077
|
+
const tui = async api => {
|
|
1078
|
+
const logger = resolveLogger(undefined);
|
|
1079
|
+
const prefsRoot = await readTuiPreferencesFile();
|
|
1080
|
+
if (!sidebarController) {
|
|
1081
|
+
sidebarController = createSidebarController(resolveAntigravityAuthPrefs(prefsRoot));
|
|
1082
|
+
}
|
|
1083
|
+
const rpcClient = createRpcClient(getRpcDir(api.state.path.directory ?? ''), process.pid);
|
|
1084
|
+
startRpcNotificationPolling({
|
|
1085
|
+
pending: (lastReceivedId, sessionId) => rpcClient.pendingNotifications(lastReceivedId, sessionId),
|
|
1086
|
+
currentSessionId: () => {
|
|
1087
|
+
const current = api.route.current;
|
|
1088
|
+
const resolved = typeof current === 'function' ? current() : current;
|
|
1089
|
+
return resolved?.params?.sessionID;
|
|
1090
|
+
},
|
|
1091
|
+
dispatch: async notification => {
|
|
1092
|
+
logger.debug('rpc-notification-received', {
|
|
1093
|
+
command: notification.payload.command,
|
|
1094
|
+
id: notification.id,
|
|
1095
|
+
sessionId: notification.sessionId
|
|
1096
|
+
});
|
|
1097
|
+
// Call the imperative dispatcher directly — the prior
|
|
1098
|
+
// two-phase `collectDialogFlow` + `renderDialogFlow` is gone.
|
|
1099
|
+
// The dispatcher awaits `apply`, toasts the result, then clears
|
|
1100
|
+
// (or replaces for multi-step flows). The RPC `apply` accepts the
|
|
1101
|
+
// optional `timeoutMs` knob so account add / refresh can opt into
|
|
1102
|
+
// the 120s RPC timeout without the dialog layer having to know
|
|
1103
|
+
// about it.
|
|
1104
|
+
if (notification.payload.command === 'antigravity-quota') {
|
|
1105
|
+
api.ui.dialog.setSize('xlarge');
|
|
1106
|
+
api.ui.dialog.replace(() => _$createComponent(QuotaDialogContent, {
|
|
1107
|
+
api: api,
|
|
1108
|
+
get controller() {
|
|
1109
|
+
return getSidebarController();
|
|
1110
|
+
},
|
|
1111
|
+
get sessionId() {
|
|
1112
|
+
return notification.sessionId;
|
|
1113
|
+
}
|
|
1114
|
+
}));
|
|
1115
|
+
return;
|
|
1116
|
+
}
|
|
1117
|
+
openCommandDialog(api, notification.payload, (command, args, options) => rpcClient.apply({
|
|
1118
|
+
command,
|
|
1119
|
+
arguments: args,
|
|
1120
|
+
sessionId: notification.sessionId
|
|
1121
|
+
}, options));
|
|
1122
|
+
},
|
|
1123
|
+
schedule: (poll, intervalMs) => {
|
|
1124
|
+
setInterval(() => void poll(), intervalMs);
|
|
1125
|
+
},
|
|
1126
|
+
logger
|
|
1127
|
+
});
|
|
1128
|
+
|
|
1129
|
+
// The host supplies the live theme via `api.theme.current` — the slot
|
|
1130
|
+
// callback's closure captures `api` so the accessor always reads the
|
|
1131
|
+
// current theme. A Solid re-render follows whenever the user switches.
|
|
1132
|
+
const liveTheme = () => api.theme.current;
|
|
1133
|
+
api.slots.register({
|
|
1134
|
+
order: computeEffectiveOrder(prefsRoot, PLUGIN_KEY, DEFAULT_SLOT_ORDER),
|
|
1135
|
+
slots: {
|
|
1136
|
+
sidebar_content: (_context, {
|
|
1137
|
+
session_id: sessionId
|
|
1138
|
+
}) => _$createComponent(SidebarPanel, {
|
|
1139
|
+
logger: logger,
|
|
1140
|
+
theme: liveTheme,
|
|
1141
|
+
sessionId: sessionId
|
|
1142
|
+
})
|
|
1143
|
+
}
|
|
1144
|
+
});
|
|
1145
|
+
};
|
|
1146
|
+
const plugin = {
|
|
1147
|
+
id: ID,
|
|
1148
|
+
tui
|
|
1149
|
+
};
|
|
1150
|
+
export default plugin;
|