@cortexkit/opencode-antigravity-auth 3.0.5 → 3.0.6
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 +38 -352
- package/dist/cli.js +9199 -8799
- package/dist/cli.js.map +4 -4
- package/dist/cli.meta.json +1286 -1064
- package/dist/index.js +13641 -14559
- package/dist/index.js.map +4 -4
- package/dist/index.meta.json +1333 -1342
- package/dist/server.js +10618 -11080
- package/dist/server.js.map +4 -4
- package/dist/server.meta.json +1 -1
- package/dist/src/auth-method-labels.d.ts +3 -0
- package/dist/src/auth-method-labels.d.ts.map +1 -0
- package/dist/src/auth-method-labels.js +5 -0
- package/dist/src/auth-method-labels.js.map +1 -0
- package/dist/src/cli.d.ts +3 -1
- package/dist/src/cli.d.ts.map +1 -1
- package/dist/src/cli.js +98 -12
- package/dist/src/cli.js.map +1 -1
- package/dist/src/common-auth-embedded/claustrum/consumer.d.ts +33 -3
- package/dist/src/common-auth-embedded/claustrum/consumer.js +96 -1
- package/dist/src/common-auth-embedded/claustrum/custody.d.ts +4 -1
- package/dist/src/common-auth-embedded/claustrum/enrollment.d.ts +6 -1
- package/dist/src/common-auth-embedded/claustrum/enrollment.js +6 -1
- package/dist/src/common-auth-embedded/claustrum/index.d.ts +2 -1
- package/dist/src/common-auth-embedded/claustrum/index.js +5 -3
- package/dist/src/common-auth-embedded/claustrum/insula.d.ts +69 -0
- package/dist/src/common-auth-embedded/claustrum/insula.js +152 -0
- package/dist/src/common-auth-embedded/claustrum/roster.d.ts +13 -0
- package/dist/src/common-auth-embedded/claustrum/roster.js +33 -3
- package/dist/src/common-auth-embedded/fs/refresh-file-lock.js +20 -11
- package/dist/src/common-auth-embedded/quota/codec.d.ts +2 -0
- package/dist/src/common-auth-embedded/quota/codec.js +2 -1
- package/dist/src/common-auth-embedded/quota/format.d.ts +26 -0
- package/dist/src/common-auth-embedded/quota/format.js +78 -42
- package/dist/src/common-auth-embedded/quota/index.d.ts +4 -4
- package/dist/src/common-auth-embedded/quota/index.js +2 -2
- package/dist/src/common-auth-embedded/quota/map.d.ts +11 -0
- package/dist/src/common-auth-embedded/quota/map.js +36 -1
- package/dist/src/common-auth-embedded/quota/merge.d.ts +3 -1
- package/dist/src/common-auth-embedded/quota/merge.js +21 -5
- package/dist/src/common-auth-embedded/quota/projection.d.ts +2 -1
- package/dist/src/common-auth-embedded/quota/projection.js +3 -1
- package/dist/src/common-auth-embedded/setup/command-runner.js +49 -0
- package/dist/src/common-auth-embedded/setup/command.d.ts +3 -0
- package/dist/src/common-auth-embedded/setup/command.js +215 -0
- package/dist/src/common-auth-embedded/setup/config-write.js +60 -0
- package/dist/src/common-auth-embedded/setup/detect.d.ts +6 -0
- package/dist/src/common-auth-embedded/setup/detect.js +224 -0
- package/dist/src/common-auth-embedded/setup/enroll.js +70 -0
- package/dist/src/common-auth-embedded/setup/index.d.ts +5 -0
- package/dist/src/common-auth-embedded/setup/index.js +4 -0
- package/dist/src/common-auth-embedded/setup/paths.js +33 -0
- package/dist/src/common-auth-embedded/setup/process-fence.d.ts +43 -0
- package/dist/src/common-auth-embedded/setup/process-fence.js +270 -0
- package/dist/src/common-auth-embedded/setup/prompts.js +26 -0
- package/dist/src/common-auth-embedded/setup/register.d.ts +11 -0
- package/dist/src/common-auth-embedded/setup/register.js +130 -0
- package/dist/src/common-auth-embedded/setup/types.d.ts +136 -0
- package/dist/src/common-auth-embedded/source-output.json +228 -80
- package/dist/src/common-auth-embedded/store/schema.d.ts +2 -0
- package/dist/src/common-auth-embedded/store/schema.js +3 -2
- package/dist/src/ga/rpc/protocol.d.ts +4 -7
- package/dist/src/ga/rpc/protocol.d.ts.map +1 -1
- package/dist/src/ga/rpc/protocol.js +5 -13
- package/dist/src/ga/rpc/protocol.js.map +1 -1
- package/dist/src/ga/server/auth.d.ts +8 -3
- package/dist/src/ga/server/auth.d.ts.map +1 -1
- package/dist/src/ga/server/auth.js +25 -9
- package/dist/src/ga/server/auth.js.map +1 -1
- package/dist/src/ga/server/index.d.ts +39 -12
- package/dist/src/ga/server/index.d.ts.map +1 -1
- package/dist/src/ga/server/index.js +214 -53
- package/dist/src/ga/server/index.js.map +1 -1
- package/dist/src/ga/server/pool-login.d.ts +22 -0
- package/dist/src/ga/server/pool-login.d.ts.map +1 -0
- package/dist/src/ga/server/pool-login.js +150 -0
- package/dist/src/ga/server/pool-login.js.map +1 -0
- package/dist/src/ga/tui/host-ga.d.ts +2 -5
- package/dist/src/ga/tui/host-ga.d.ts.map +1 -1
- package/dist/src/ga/tui/host-ga.js +17 -49
- package/dist/src/ga/tui/host-ga.js.map +1 -1
- package/dist/src/plugin/accounts.d.ts +1 -1
- package/dist/src/plugin/accounts.d.ts.map +1 -1
- package/dist/src/plugin/accounts.js +1 -0
- package/dist/src/plugin/accounts.js.map +1 -1
- package/dist/src/plugin/background-vault-quota-refresh.d.ts +2 -0
- package/dist/src/plugin/background-vault-quota-refresh.d.ts.map +1 -1
- package/dist/src/plugin/background-vault-quota-refresh.js +125 -10
- package/dist/src/plugin/background-vault-quota-refresh.js.map +1 -1
- package/dist/src/plugin/command-apply.d.ts +2 -2
- package/dist/src/plugin/command-apply.d.ts.map +1 -1
- package/dist/src/plugin/command-apply.js +3 -10
- package/dist/src/plugin/command-apply.js.map +1 -1
- package/dist/src/plugin/commands.d.ts +1 -0
- package/dist/src/plugin/commands.d.ts.map +1 -1
- package/dist/src/plugin/commands.js +2 -2
- package/dist/src/plugin/commands.js.map +1 -1
- package/dist/src/plugin/config/operator-settings-schema.d.ts +0 -4
- package/dist/src/plugin/config/operator-settings-schema.d.ts.map +1 -1
- package/dist/src/plugin/config/operator-settings-schema.js +0 -5
- package/dist/src/plugin/config/operator-settings-schema.js.map +1 -1
- package/dist/src/plugin/config/schema.d.ts +0 -7
- package/dist/src/plugin/config/schema.d.ts.map +1 -1
- package/dist/src/plugin/config/schema.js +0 -43
- package/dist/src/plugin/config/schema.js.map +1 -1
- package/dist/src/plugin/config/writer.d.ts +1 -1
- package/dist/src/plugin/config/writer.js +1 -1
- package/dist/src/plugin/fetch/retry-state.d.ts +19 -3
- package/dist/src/plugin/fetch/retry-state.d.ts.map +1 -1
- package/dist/src/plugin/fetch/retry-state.js +0 -6
- package/dist/src/plugin/fetch/retry-state.js.map +1 -1
- package/dist/src/plugin/fetch-interceptor.d.ts.map +1 -1
- package/dist/src/plugin/fetch-interceptor.js +0 -3
- package/dist/src/plugin/fetch-interceptor.js.map +1 -1
- package/dist/src/plugin/fetch-routing.d.ts +0 -16
- package/dist/src/plugin/fetch-routing.d.ts.map +1 -1
- package/dist/src/plugin/fetch-routing.js +0 -49
- package/dist/src/plugin/fetch-routing.js.map +1 -1
- package/dist/src/plugin/ga-location-services.d.ts +14 -9
- package/dist/src/plugin/ga-location-services.d.ts.map +1 -1
- package/dist/src/plugin/ga-location-services.js +120 -40
- package/dist/src/plugin/ga-location-services.js.map +1 -1
- package/dist/src/plugin/google-origin.d.ts +7 -0
- package/dist/src/plugin/google-origin.d.ts.map +1 -0
- package/dist/src/plugin/google-origin.js +14 -0
- package/dist/src/plugin/google-origin.js.map +1 -0
- package/dist/src/plugin/index.d.ts.map +1 -1
- package/dist/src/plugin/index.js +15 -4
- package/dist/src/plugin/index.js.map +1 -1
- package/dist/src/plugin/oauth-methods.d.ts.map +1 -1
- package/dist/src/plugin/oauth-methods.js +0 -33
- package/dist/src/plugin/oauth-methods.js.map +1 -1
- package/dist/src/plugin/operator-settings.d.ts +1 -1
- package/dist/src/plugin/operator-settings.d.ts.map +1 -1
- package/dist/src/plugin/operator-settings.js +1 -8
- package/dist/src/plugin/operator-settings.js.map +1 -1
- package/dist/src/plugin/quota.d.ts +11 -7
- package/dist/src/plugin/quota.d.ts.map +1 -1
- package/dist/src/plugin/quota.js +128 -102
- package/dist/src/plugin/quota.js.map +1 -1
- package/dist/src/plugin/request.d.ts +5 -3
- package/dist/src/plugin/request.d.ts.map +1 -1
- package/dist/src/plugin/request.js +87 -168
- package/dist/src/plugin/request.js.map +1 -1
- package/dist/src/plugin/server.d.ts.map +1 -1
- package/dist/src/plugin/server.js +60 -53
- package/dist/src/plugin/server.js.map +1 -1
- package/dist/src/plugin/shared/advisory-repository.d.ts +20 -0
- package/dist/src/plugin/shared/advisory-repository.d.ts.map +1 -0
- package/dist/src/plugin/shared/advisory-repository.js +91 -0
- package/dist/src/plugin/shared/advisory-repository.js.map +1 -0
- package/dist/src/plugin/shared/request-services.d.ts +19 -25
- package/dist/src/plugin/shared/request-services.d.ts.map +1 -1
- package/dist/src/plugin/shared/request-services.js +105 -188
- package/dist/src/plugin/shared/request-services.js.map +1 -1
- package/dist/src/plugin/shared/runtime.js +4 -2
- package/dist/src/plugin/shared/runtime.js.map +1 -1
- package/dist/src/plugin/shared/vault-request-credentials.d.ts +4 -1
- package/dist/src/plugin/shared/vault-request-credentials.d.ts.map +1 -1
- package/dist/src/plugin/shared/vault-request-credentials.js +41 -7
- package/dist/src/plugin/shared/vault-request-credentials.js.map +1 -1
- package/dist/src/plugin/storage.d.ts +2 -2
- package/dist/src/plugin/storage.d.ts.map +1 -1
- package/dist/src/plugin/storage.js.map +1 -1
- package/dist/src/plugin/vault-custody.d.ts.map +1 -1
- package/dist/src/plugin/vault-custody.js +147 -35
- package/dist/src/plugin/vault-custody.js.map +1 -1
- package/dist/src/plugin/vault-quota-outcome.d.ts +19 -0
- package/dist/src/plugin/vault-quota-outcome.d.ts.map +1 -0
- package/dist/src/plugin/vault-quota-outcome.js +47 -0
- package/dist/src/plugin/vault-quota-outcome.js.map +1 -0
- package/dist/src/quota-presentation.d.ts +29 -1
- package/dist/src/quota-presentation.d.ts.map +1 -1
- package/dist/src/quota-presentation.js +52 -17
- package/dist/src/quota-presentation.js.map +1 -1
- package/dist/src/setup.d.ts +15 -0
- package/dist/src/setup.d.ts.map +1 -0
- package/dist/src/setup.js +320 -0
- package/dist/src/setup.js.map +1 -0
- package/dist/src/sidebar-projection.d.ts +1 -1
- package/dist/src/sidebar-projection.d.ts.map +1 -1
- package/dist/src/sidebar-state.d.ts +1 -1
- package/dist/src/sidebar-state.d.ts.map +1 -1
- package/dist/src/sidebar-state.js +19 -1
- package/dist/src/sidebar-state.js.map +1 -1
- package/dist/src/tui.d.ts.map +1 -1
- package/dist/src/tui.js +205 -110
- package/dist/src/tui.js.map +1 -1
- package/dist/tui-build-map.json +37 -37
- package/dist/tui-ga-build-map.json +33 -33
- package/dist/types/src/auth-method-labels.d.ts +3 -0
- package/dist/types/src/auth-method-labels.d.ts.map +1 -0
- package/dist/types/src/cli.d.ts +3 -1
- package/dist/types/src/cli.d.ts.map +1 -1
- package/dist/types/src/common-auth-embedded/auth-menu/terminal.d.ts +43 -0
- package/dist/types/src/common-auth-embedded/claustrum/consumer.d.ts +132 -0
- package/dist/types/src/common-auth-embedded/claustrum/custody.d.ts +178 -0
- package/dist/types/src/common-auth-embedded/claustrum/enrollment.d.ts +164 -0
- package/dist/types/src/common-auth-embedded/claustrum/errors.d.ts +16 -0
- package/dist/types/src/common-auth-embedded/claustrum/host-slot.d.ts +39 -0
- package/dist/types/src/common-auth-embedded/claustrum/index.d.ts +19 -0
- package/dist/types/src/common-auth-embedded/claustrum/insula.d.ts +69 -0
- package/dist/types/src/common-auth-embedded/claustrum/interlock.d.ts +27 -0
- package/dist/types/src/common-auth-embedded/claustrum/roster.d.ts +221 -0
- package/dist/types/src/common-auth-embedded/opencode2/errors.d.ts +25 -0
- package/dist/types/src/common-auth-embedded/opencode2/index.d.ts +8 -0
- package/dist/types/src/common-auth-embedded/opencode2/install.d.ts +55 -0
- package/dist/types/src/common-auth-embedded/opencode2/integration.d.ts +112 -0
- package/dist/types/src/common-auth-embedded/opencode2/sse.d.ts +12 -0
- package/dist/types/src/common-auth-embedded/opencode2/types.d.ts +413 -0
- package/dist/types/src/common-auth-embedded/quota/codec.d.ts +2 -0
- package/dist/types/src/common-auth-embedded/quota/format.d.ts +26 -0
- package/dist/types/src/common-auth-embedded/quota/index.d.ts +4 -4
- package/dist/types/src/common-auth-embedded/quota/map.d.ts +11 -0
- package/dist/types/src/common-auth-embedded/quota/merge.d.ts +3 -1
- package/dist/types/src/common-auth-embedded/quota/projection.d.ts +2 -1
- package/dist/types/src/common-auth-embedded/routing/admission.d.ts +93 -0
- package/dist/types/src/common-auth-embedded/routing/index.d.ts +8 -0
- package/dist/types/src/common-auth-embedded/routing/ordered.d.ts +47 -0
- package/dist/types/src/common-auth-embedded/routing/pins.d.ts +22 -0
- package/dist/types/src/common-auth-embedded/routing/sticky.d.ts +158 -0
- package/dist/types/src/common-auth-embedded/setup/command.d.ts +3 -0
- package/dist/types/src/common-auth-embedded/setup/detect.d.ts +6 -0
- package/dist/types/src/common-auth-embedded/setup/index.d.ts +5 -0
- package/dist/types/src/common-auth-embedded/setup/process-fence.d.ts +43 -0
- package/dist/types/src/common-auth-embedded/setup/register.d.ts +11 -0
- package/dist/types/src/common-auth-embedded/setup/types.d.ts +136 -0
- package/dist/types/src/common-auth-embedded/store/schema.d.ts +2 -0
- package/dist/types/src/ga/rpc/protocol.d.ts +4 -7
- package/dist/types/src/ga/rpc/protocol.d.ts.map +1 -1
- package/dist/types/src/ga/server/auth.d.ts +8 -3
- package/dist/types/src/ga/server/auth.d.ts.map +1 -1
- package/dist/types/src/ga/server/index.d.ts +39 -12
- package/dist/types/src/ga/server/index.d.ts.map +1 -1
- package/dist/types/src/ga/server/pool-login.d.ts +22 -0
- package/dist/types/src/ga/server/pool-login.d.ts.map +1 -0
- package/dist/types/src/plugin/accounts.d.ts +1 -1
- package/dist/types/src/plugin/accounts.d.ts.map +1 -1
- package/dist/types/src/plugin/background-vault-quota-refresh.d.ts +2 -0
- package/dist/types/src/plugin/background-vault-quota-refresh.d.ts.map +1 -1
- package/dist/types/src/plugin/command-apply.d.ts +2 -2
- package/dist/types/src/plugin/command-apply.d.ts.map +1 -1
- package/dist/types/src/plugin/commands.d.ts +1 -0
- package/dist/types/src/plugin/commands.d.ts.map +1 -1
- package/dist/types/src/plugin/config/operator-settings-schema.d.ts +0 -4
- package/dist/types/src/plugin/config/operator-settings-schema.d.ts.map +1 -1
- package/dist/types/src/plugin/config/schema.d.ts +0 -7
- package/dist/types/src/plugin/config/schema.d.ts.map +1 -1
- package/dist/types/src/plugin/config/writer.d.ts +1 -1
- package/dist/types/src/plugin/fetch/retry-state.d.ts +19 -3
- package/dist/types/src/plugin/fetch/retry-state.d.ts.map +1 -1
- package/dist/types/src/plugin/fetch-interceptor.d.ts.map +1 -1
- package/dist/types/src/plugin/fetch-routing.d.ts +0 -16
- package/dist/types/src/plugin/fetch-routing.d.ts.map +1 -1
- package/dist/types/src/plugin/ga-location-services.d.ts +14 -9
- package/dist/types/src/plugin/ga-location-services.d.ts.map +1 -1
- package/dist/types/src/plugin/google-origin.d.ts +7 -0
- package/dist/types/src/plugin/google-origin.d.ts.map +1 -0
- package/dist/types/src/plugin/index.d.ts.map +1 -1
- package/dist/types/src/plugin/oauth-methods.d.ts.map +1 -1
- package/dist/types/src/plugin/operator-settings.d.ts +1 -1
- package/dist/types/src/plugin/operator-settings.d.ts.map +1 -1
- package/dist/types/src/plugin/quota.d.ts +11 -7
- package/dist/types/src/plugin/quota.d.ts.map +1 -1
- package/dist/types/src/plugin/request.d.ts +5 -3
- package/dist/types/src/plugin/request.d.ts.map +1 -1
- package/dist/types/src/plugin/server.d.ts.map +1 -1
- package/dist/types/src/plugin/shared/advisory-repository.d.ts +20 -0
- package/dist/types/src/plugin/shared/advisory-repository.d.ts.map +1 -0
- package/dist/types/src/plugin/shared/request-services.d.ts +19 -25
- package/dist/types/src/plugin/shared/request-services.d.ts.map +1 -1
- package/dist/types/src/plugin/shared/vault-request-credentials.d.ts +4 -1
- package/dist/types/src/plugin/shared/vault-request-credentials.d.ts.map +1 -1
- package/dist/types/src/plugin/storage.d.ts +2 -2
- package/dist/types/src/plugin/storage.d.ts.map +1 -1
- package/dist/types/src/plugin/vault-custody.d.ts.map +1 -1
- package/dist/types/src/plugin/vault-quota-outcome.d.ts +19 -0
- package/dist/types/src/plugin/vault-quota-outcome.d.ts.map +1 -0
- package/dist/types/src/setup.d.ts +15 -0
- package/dist/types/src/setup.d.ts.map +1 -0
- package/dist/types/src/sidebar-state.d.ts +1 -1
- package/dist/types/src/sidebar-state.d.ts.map +1 -1
- package/package.json +5 -4
- package/src/common-auth-embedded/claustrum/consumer.d.ts +33 -3
- package/src/common-auth-embedded/claustrum/consumer.js +96 -1
- package/src/common-auth-embedded/claustrum/custody.d.ts +4 -1
- package/src/common-auth-embedded/claustrum/enrollment.d.ts +6 -1
- package/src/common-auth-embedded/claustrum/enrollment.js +6 -1
- package/src/common-auth-embedded/claustrum/index.d.ts +2 -1
- package/src/common-auth-embedded/claustrum/index.js +5 -3
- package/src/common-auth-embedded/claustrum/insula.d.ts +69 -0
- package/src/common-auth-embedded/claustrum/insula.js +152 -0
- package/src/common-auth-embedded/claustrum/roster.d.ts +13 -0
- package/src/common-auth-embedded/claustrum/roster.js +33 -3
- package/src/common-auth-embedded/fs/refresh-file-lock.js +20 -11
- package/src/common-auth-embedded/quota/codec.d.ts +2 -0
- package/src/common-auth-embedded/quota/codec.js +2 -1
- package/src/common-auth-embedded/quota/format.d.ts +26 -0
- package/src/common-auth-embedded/quota/format.js +78 -42
- package/src/common-auth-embedded/quota/index.d.ts +4 -4
- package/src/common-auth-embedded/quota/index.js +2 -2
- package/src/common-auth-embedded/quota/map.d.ts +11 -0
- package/src/common-auth-embedded/quota/map.js +36 -1
- package/src/common-auth-embedded/quota/merge.d.ts +3 -1
- package/src/common-auth-embedded/quota/merge.js +21 -5
- package/src/common-auth-embedded/quota/projection.d.ts +2 -1
- package/src/common-auth-embedded/quota/projection.js +3 -1
- package/src/common-auth-embedded/setup/command-runner.js +49 -0
- package/src/common-auth-embedded/setup/command.d.ts +3 -0
- package/src/common-auth-embedded/setup/command.js +215 -0
- package/src/common-auth-embedded/setup/config-write.js +60 -0
- package/src/common-auth-embedded/setup/detect.d.ts +6 -0
- package/src/common-auth-embedded/setup/detect.js +224 -0
- package/src/common-auth-embedded/setup/enroll.js +70 -0
- package/src/common-auth-embedded/setup/index.d.ts +5 -0
- package/src/common-auth-embedded/setup/index.js +4 -0
- package/src/common-auth-embedded/setup/paths.js +33 -0
- package/src/common-auth-embedded/setup/process-fence.d.ts +43 -0
- package/src/common-auth-embedded/setup/process-fence.js +270 -0
- package/src/common-auth-embedded/setup/prompts.js +26 -0
- package/src/common-auth-embedded/setup/register.d.ts +11 -0
- package/src/common-auth-embedded/setup/register.js +130 -0
- package/src/common-auth-embedded/setup/types.d.ts +136 -0
- package/src/common-auth-embedded/source-output.json +228 -80
- package/src/common-auth-embedded/store/schema.d.ts +2 -0
- package/src/common-auth-embedded/store/schema.js +3 -2
- package/src/sidebar-state.ts +19 -2
- package/src/tui-compiled/common-auth-embedded/quota/codec.js +2 -1
- package/src/tui-compiled/common-auth-embedded/quota/format.js +78 -42
- package/src/tui-compiled/common-auth-embedded/quota/index.js +2 -2
- package/src/tui-compiled/common-auth-embedded/quota/map.js +36 -1
- package/src/tui-compiled/common-auth-embedded/quota/merge.js +21 -5
- package/src/tui-compiled/common-auth-embedded/quota/projection.js +3 -1
- package/src/tui-compiled/quota-presentation.js +42 -9
- package/src/tui-compiled/sidebar-state.js +15 -1
- package/src/tui-compiled/tui.js +516 -334
- package/src/tui-ga-compiled/host-ga.js +11 -38
- package/src/tui-ga-compiled/shared/1ff34afa7c42d196-projection.js +3 -1
- package/src/tui-ga-compiled/shared/77138df80c7ae006-map.js +36 -1
- package/src/tui-ga-compiled/shared/98cc0c186c46c42d-quota-presentation.js +42 -9
- package/src/tui-ga-compiled/shared/aef2402f8fc342f0-format.js +78 -42
- package/src/tui-ga-compiled/shared/bf17cbee28e58197-index.js +2 -2
- package/src/tui-ga-compiled/shared/ca21dc417b36dc5d-codec.js +2 -1
- package/src/tui-ga-compiled/shared/ecc214300932dfb6-merge.js +21 -5
- package/src/tui-ga-raw/host-ga.tsx +31 -62
- package/src/tui-ga-raw/shared/1ff34afa7c42d196-projection.js +3 -1
- package/src/tui-ga-raw/shared/77138df80c7ae006-map.js +36 -1
- package/src/tui-ga-raw/shared/98cc0c186c46c42d-quota-presentation.js +42 -9
- package/src/tui-ga-raw/shared/aef2402f8fc342f0-format.js +78 -42
- package/src/tui-ga-raw/shared/bf17cbee28e58197-index.js +2 -2
- package/src/tui-ga-raw/shared/ca21dc417b36dc5d-codec.js +2 -1
- package/src/tui-ga-raw/shared/ecc214300932dfb6-merge.js +21 -5
- package/src/tui-raw/common-auth-embedded/quota/codec.js +2 -1
- package/src/tui-raw/common-auth-embedded/quota/format.js +78 -42
- package/src/tui-raw/common-auth-embedded/quota/index.js +2 -2
- package/src/tui-raw/common-auth-embedded/quota/map.js +36 -1
- package/src/tui-raw/common-auth-embedded/quota/merge.js +21 -5
- package/src/tui-raw/common-auth-embedded/quota/projection.js +3 -1
- package/src/tui-raw/quota-presentation.js +42 -9
- package/src/tui-raw/sidebar-state.js +15 -1
- package/src/tui-raw/tui.tsx +423 -218
- package/src/tui.tsx +423 -218
- package/dist/src/tui/vault-setup.d.ts +0 -98
- package/dist/src/tui/vault-setup.d.ts.map +0 -1
- package/dist/src/tui/vault-setup.js +0 -198
- package/dist/src/tui/vault-setup.js.map +0 -1
- package/dist/types/src/plugin/transform/model-resolver.d.ts +0 -2
- package/dist/types/src/plugin/transform/model-resolver.d.ts.map +0 -1
- package/dist/types/src/quota-presentation.d.ts +0 -18
- package/dist/types/src/quota-presentation.d.ts.map +0 -1
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type { ClaustrumClientOptions } from '@cortexkit/claustrum-client';
|
|
2
|
+
/** Insula's window fields are open: plugins choose which limits they understand. */
|
|
3
|
+
export interface InsulaUsageWindow {
|
|
4
|
+
usedPercent: number;
|
|
5
|
+
rawUsedPercent?: number;
|
|
6
|
+
resetsAt?: string;
|
|
7
|
+
windowMinutes?: number;
|
|
8
|
+
windowKind?: string;
|
|
9
|
+
[field: string]: unknown;
|
|
10
|
+
}
|
|
11
|
+
export interface InsulaUsageEntry {
|
|
12
|
+
provider: string;
|
|
13
|
+
account?: string;
|
|
14
|
+
fetchedAt?: string;
|
|
15
|
+
source?: string;
|
|
16
|
+
stale?: unknown;
|
|
17
|
+
errorClass?: unknown;
|
|
18
|
+
usage?: {
|
|
19
|
+
primary?: InsulaUsageWindow;
|
|
20
|
+
secondary?: InsulaUsageWindow;
|
|
21
|
+
tertiary?: InsulaUsageWindow;
|
|
22
|
+
extraRateWindows?: Array<{
|
|
23
|
+
id?: string;
|
|
24
|
+
title?: string;
|
|
25
|
+
window?: InsulaUsageWindow;
|
|
26
|
+
}>;
|
|
27
|
+
[field: string]: unknown;
|
|
28
|
+
};
|
|
29
|
+
[field: string]: unknown;
|
|
30
|
+
}
|
|
31
|
+
export interface InsulaQuotaContext {
|
|
32
|
+
/** Milliseconds since the epoch, parsed from the producer's fetchedAt. */
|
|
33
|
+
fetchedAt: number;
|
|
34
|
+
source?: string;
|
|
35
|
+
}
|
|
36
|
+
export interface InsulaQuotaOptions<Q> {
|
|
37
|
+
provider: 'codex' | 'claude' | 'antigravity';
|
|
38
|
+
/**
|
|
39
|
+
* Set every converted window's reading time to context.fetchedAt, not poll
|
|
40
|
+
* time. Return undefined for entries the plugin cannot use. Antigravity can
|
|
41
|
+
* receive its own sidebar reading back from insula: accept it only from the
|
|
42
|
+
* vault or when fetchedAt is newer than the plugin's last reading.
|
|
43
|
+
*/
|
|
44
|
+
normalize: (entry: InsulaUsageEntry, context: InsulaQuotaContext) => Q | undefined;
|
|
45
|
+
}
|
|
46
|
+
/** Optional transport for custom scoped clients; getUsage must not retry refusals. */
|
|
47
|
+
export interface InsulaUsageTransport {
|
|
48
|
+
connectionFile: string;
|
|
49
|
+
getUsage(): Promise<unknown>;
|
|
50
|
+
}
|
|
51
|
+
/** Constructing this transport opens no connection; getUsage opens one per call. */
|
|
52
|
+
export declare function insulaUsageTransport(options: ClaustrumClientOptions & {
|
|
53
|
+
connectionFile: string;
|
|
54
|
+
}): InsulaUsageTransport;
|
|
55
|
+
export declare class InsulaQuotaSource {
|
|
56
|
+
#private;
|
|
57
|
+
private readonly transport;
|
|
58
|
+
private readonly key;
|
|
59
|
+
constructor(transport: InsulaUsageTransport, key: string);
|
|
60
|
+
refresh(now: number): Promise<void>;
|
|
61
|
+
current(provider: string, accountId: string, now: number): {
|
|
62
|
+
entry: InsulaUsageEntry;
|
|
63
|
+
context: InsulaQuotaContext;
|
|
64
|
+
} | undefined;
|
|
65
|
+
}
|
|
66
|
+
export declare function acquireInsulaQuotaSource(transport: InsulaUsageTransport, tokenPath: string): {
|
|
67
|
+
source: InsulaQuotaSource;
|
|
68
|
+
release(): void;
|
|
69
|
+
};
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { resolve } from 'node:path';
|
|
2
|
+
import { storeIdentity } from '@cortexkit/claustrum-client';
|
|
3
|
+
// A static import: claustrum-client already loads subc-client whenever
|
|
4
|
+
// /claustrum is imported, so loading it lazily saves nothing, and a dynamic
|
|
5
|
+
// import makes bundlers emit a separate chunk that a running host loses when
|
|
6
|
+
// its dist folder is rebuilt underneath it.
|
|
7
|
+
import { SubcClient } from '@cortexkit/subc-client';
|
|
8
|
+
/** Constructing this transport opens no connection; getUsage opens one per call. */
|
|
9
|
+
export function insulaUsageTransport(options) {
|
|
10
|
+
const identity = options.identity ??
|
|
11
|
+
storeIdentity(options.projectRoot ?? process.cwd(), options.storagePath ?? process.cwd());
|
|
12
|
+
return {
|
|
13
|
+
connectionFile: options.connectionFile,
|
|
14
|
+
async getUsage() {
|
|
15
|
+
let client;
|
|
16
|
+
let expired = false;
|
|
17
|
+
let timer;
|
|
18
|
+
const timeout = new Promise((_resolve, reject) => {
|
|
19
|
+
timer = setTimeout(() => reject(new Error('insula usage timeout')), 3_000);
|
|
20
|
+
timer.unref?.();
|
|
21
|
+
});
|
|
22
|
+
const request = (async () => {
|
|
23
|
+
client = options.connector
|
|
24
|
+
? await options.connector({
|
|
25
|
+
connectionFile: options.connectionFile,
|
|
26
|
+
handshakeTimeoutMs: Math.min(options.handshakeTimeoutMs ?? 3_000, 3_000),
|
|
27
|
+
})
|
|
28
|
+
: await SubcClient.connect({
|
|
29
|
+
connectionFile: options.connectionFile,
|
|
30
|
+
handshakeTimeoutMs: Math.min(options.handshakeTimeoutMs ?? 3_000, 3_000),
|
|
31
|
+
});
|
|
32
|
+
// A slow connector may resolve after the whole-call deadline. It still
|
|
33
|
+
// owns a socket, which must not survive or open a route after fallback.
|
|
34
|
+
if (expired) {
|
|
35
|
+
client.close();
|
|
36
|
+
throw new Error('insula usage timeout');
|
|
37
|
+
}
|
|
38
|
+
// Managed call() retries warming routes. A single routeOpen/request
|
|
39
|
+
// instead lets the plugin fall back as soon as the daemon refuses.
|
|
40
|
+
const route = await client.routeOpen({ kind: 'management_surface', module_id: 'insula' }, identity);
|
|
41
|
+
return await client.request(route, { method: 'usage.get', params: {} });
|
|
42
|
+
})();
|
|
43
|
+
try {
|
|
44
|
+
return await Promise.race([request, timeout]);
|
|
45
|
+
}
|
|
46
|
+
finally {
|
|
47
|
+
expired = true;
|
|
48
|
+
clearTimeout(timer);
|
|
49
|
+
client?.close();
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
const MINUTE = 60_000;
|
|
55
|
+
const MAX_AGE = 4 * MINUTE;
|
|
56
|
+
const sources = new Map();
|
|
57
|
+
// Keep only the minute budget after the last owner closes, so project churn
|
|
58
|
+
// cannot reset the bound. Expired budgets are pruned on the next tick.
|
|
59
|
+
const attempts = new Map();
|
|
60
|
+
function record(value) {
|
|
61
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
62
|
+
}
|
|
63
|
+
export class InsulaQuotaSource {
|
|
64
|
+
transport;
|
|
65
|
+
key;
|
|
66
|
+
#entries = [];
|
|
67
|
+
#pending;
|
|
68
|
+
constructor(transport, key) {
|
|
69
|
+
this.transport = transport;
|
|
70
|
+
this.key = key;
|
|
71
|
+
}
|
|
72
|
+
refresh(now) {
|
|
73
|
+
if (this.#pending)
|
|
74
|
+
return this.#pending;
|
|
75
|
+
for (const [key, time] of attempts) {
|
|
76
|
+
if (now - time >= MINUTE)
|
|
77
|
+
attempts.delete(key);
|
|
78
|
+
}
|
|
79
|
+
const lastAttempt = attempts.get(this.key);
|
|
80
|
+
if (lastAttempt !== undefined && now - lastAttempt < MINUTE)
|
|
81
|
+
return Promise.resolve();
|
|
82
|
+
// Reserve the minute before I/O, so concurrent projects cannot each poll.
|
|
83
|
+
attempts.set(this.key, now);
|
|
84
|
+
this.#pending = (async () => {
|
|
85
|
+
try {
|
|
86
|
+
const reply = await this.transport.getUsage();
|
|
87
|
+
if (!record(reply) ||
|
|
88
|
+
!Array.isArray(reply.result) ||
|
|
89
|
+
reply.error !== undefined)
|
|
90
|
+
throw new Error('unavailable insula usage');
|
|
91
|
+
// Each response is a snapshot, not a delta. Missing accounts fall back;
|
|
92
|
+
// neither pending nor the entry count asserts provider completeness.
|
|
93
|
+
this.#entries = reply.result.filter((entry) => record(entry) && typeof entry.provider === 'string');
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
// Refusal is absence, even if the previous reading was still young.
|
|
97
|
+
this.#entries = [];
|
|
98
|
+
}
|
|
99
|
+
})().finally(() => {
|
|
100
|
+
this.#pending = undefined;
|
|
101
|
+
});
|
|
102
|
+
return this.#pending;
|
|
103
|
+
}
|
|
104
|
+
current(provider, accountId, now) {
|
|
105
|
+
for (const entry of this.#entries) {
|
|
106
|
+
if (entry.provider !== provider ||
|
|
107
|
+
typeof entry.account !== 'string' ||
|
|
108
|
+
entry.account.trim() !== accountId)
|
|
109
|
+
continue;
|
|
110
|
+
if (entry.stale !== undefined ||
|
|
111
|
+
entry.errorClass !== undefined ||
|
|
112
|
+
!record(entry.usage))
|
|
113
|
+
continue;
|
|
114
|
+
const fetchedAt = typeof entry.fetchedAt === 'string'
|
|
115
|
+
? Date.parse(entry.fetchedAt)
|
|
116
|
+
: Number.NaN;
|
|
117
|
+
if (!Number.isFinite(fetchedAt) || now - fetchedAt >= MAX_AGE)
|
|
118
|
+
continue;
|
|
119
|
+
return {
|
|
120
|
+
entry,
|
|
121
|
+
context: {
|
|
122
|
+
fetchedAt,
|
|
123
|
+
...(typeof entry.source === 'string' && { source: entry.source }),
|
|
124
|
+
},
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
return undefined;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
export function acquireInsulaQuotaSource(transport, tokenPath) {
|
|
131
|
+
const key = JSON.stringify([
|
|
132
|
+
resolve(transport.connectionFile),
|
|
133
|
+
resolve(tokenPath),
|
|
134
|
+
]);
|
|
135
|
+
let shared = sources.get(key);
|
|
136
|
+
if (!shared) {
|
|
137
|
+
shared = { source: new InsulaQuotaSource(transport, key), refs: 0 };
|
|
138
|
+
sources.set(key, shared);
|
|
139
|
+
}
|
|
140
|
+
shared.refs++;
|
|
141
|
+
let released = false;
|
|
142
|
+
return {
|
|
143
|
+
source: shared.source,
|
|
144
|
+
release() {
|
|
145
|
+
if (released)
|
|
146
|
+
return;
|
|
147
|
+
released = true;
|
|
148
|
+
if (--shared.refs === 0)
|
|
149
|
+
sources.delete(key);
|
|
150
|
+
},
|
|
151
|
+
};
|
|
152
|
+
}
|
|
@@ -133,6 +133,19 @@ export declare function recordVaultQuota(path: string, input: QuotaReceipt & {
|
|
|
133
133
|
routeId: string;
|
|
134
134
|
observation: QuotaObservation;
|
|
135
135
|
}): Promise<boolean>;
|
|
136
|
+
/**
|
|
137
|
+
* Merge a quota observation that belongs to an account rather than to a
|
|
138
|
+
* served credential, such as a background reading from insula. The write
|
|
139
|
+
* lands only while the row is still bound to that exact known account, so a
|
|
140
|
+
* reading taken before a replacement never reaches the successor. Unlike
|
|
141
|
+
* `recordVaultQuota` it never binds an account: a row without a known account
|
|
142
|
+
* is refused. Returns whether the observation was kept.
|
|
143
|
+
*/
|
|
144
|
+
export declare function recordVaultAccountQuota(path: string, input: {
|
|
145
|
+
routeId: string;
|
|
146
|
+
accountIdentity: string;
|
|
147
|
+
observation: QuotaObservation;
|
|
148
|
+
}): Promise<boolean>;
|
|
136
149
|
/**
|
|
137
150
|
* Discover and commit the roster. The lease covers the list call and the
|
|
138
151
|
* commit, not just the write: an opaque view cannot tell a delayed old reply
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
2
|
import { acquireRefreshFileLock, withLock, writeJsonAtomic, } from '../fs/index.js';
|
|
3
3
|
import { readPrivateText, windowsPrivateFiles } from '../fs/private-files.js';
|
|
4
|
-
import {
|
|
4
|
+
import { decodeQuotaMap, mergeQuotaObservation, } from '../quota/index.js';
|
|
5
5
|
import { ClaustrumConsumerError } from './errors.js';
|
|
6
6
|
import { acceptAccount, declineAccount, isDeclined, } from './interlock.js';
|
|
7
7
|
export const DEFAULT_ROUTE_PREFIX = 'vault:';
|
|
@@ -210,6 +210,7 @@ function optionalString(value) {
|
|
|
210
210
|
return value === undefined || typeof value === 'string';
|
|
211
211
|
}
|
|
212
212
|
function decodeRow(value) {
|
|
213
|
+
const quota = isRecord(value) ? decodeQuotaMap(value.quota) : undefined;
|
|
213
214
|
if (!isRecord(value) ||
|
|
214
215
|
typeof value.routeId !== 'string' ||
|
|
215
216
|
typeof value.credentialId !== 'string' ||
|
|
@@ -224,11 +225,14 @@ function decodeRow(value) {
|
|
|
224
225
|
(value.aliases !== undefined &&
|
|
225
226
|
(!Array.isArray(value.aliases) ||
|
|
226
227
|
!value.aliases.every((alias) => typeof alias === 'string'))) ||
|
|
227
|
-
(value.quota !== undefined &&
|
|
228
|
+
(value.quota !== undefined && quota === undefined) ||
|
|
228
229
|
(value.stale !== undefined && value.stale !== true) ||
|
|
229
230
|
(value.unclaimed !== undefined && value.unclaimed !== true))
|
|
230
231
|
return undefined;
|
|
231
|
-
return
|
|
232
|
+
return {
|
|
233
|
+
...value,
|
|
234
|
+
...(quota === undefined ? {} : { quota }),
|
|
235
|
+
};
|
|
232
236
|
}
|
|
233
237
|
const SKIPPED_REASONS = new Set([
|
|
234
238
|
'empty credential id',
|
|
@@ -435,6 +439,32 @@ export function recordVaultQuota(path, input) {
|
|
|
435
439
|
};
|
|
436
440
|
});
|
|
437
441
|
}
|
|
442
|
+
/**
|
|
443
|
+
* Merge a quota observation that belongs to an account rather than to a
|
|
444
|
+
* served credential, such as a background reading from insula. The write
|
|
445
|
+
* lands only while the row is still bound to that exact known account, so a
|
|
446
|
+
* reading taken before a replacement never reaches the successor. Unlike
|
|
447
|
+
* `recordVaultQuota` it never binds an account: a row without a known account
|
|
448
|
+
* is refused. Returns whether the observation was kept.
|
|
449
|
+
*/
|
|
450
|
+
export function recordVaultAccountQuota(path, input) {
|
|
451
|
+
return mutateVaultRoster(path, (current) => {
|
|
452
|
+
const row = current?.rows.find((entry) => entry.routeId === input.routeId);
|
|
453
|
+
if (!current ||
|
|
454
|
+
!row ||
|
|
455
|
+
row.accountIdentity === undefined ||
|
|
456
|
+
row.accountIdentity !== input.accountIdentity)
|
|
457
|
+
return { result: false };
|
|
458
|
+
const quota = mergeQuotaObservation(row.quota, input.observation);
|
|
459
|
+
return {
|
|
460
|
+
next: {
|
|
461
|
+
...current,
|
|
462
|
+
rows: current.rows.map((entry) => entry === row ? { ...entry, quota } : entry),
|
|
463
|
+
},
|
|
464
|
+
result: true,
|
|
465
|
+
};
|
|
466
|
+
});
|
|
467
|
+
}
|
|
438
468
|
/**
|
|
439
469
|
* Discover and commit the roster. The lease covers the list call and the
|
|
440
470
|
* commit, not just the write: an opaque view cannot tell a delayed old reply
|
|
@@ -1,8 +1,25 @@
|
|
|
1
1
|
import { randomUUID } from 'node:crypto';
|
|
2
|
-
import { mkdir, open, readFile, rename, rm, stat
|
|
2
|
+
import { mkdir, open, readFile, rename, rm, stat } from 'node:fs/promises';
|
|
3
3
|
import { dirname, join } from 'node:path';
|
|
4
4
|
import { createPrivateBytes, createPrivateDirectoryExclusive, ensurePrivateDirectory, PrivateFileError, privateOperation, readPrivateText, verifyPrivate, windowsPrivateFiles, writePrivateAtomic, } from './private-files.js';
|
|
5
5
|
import { LockOwnershipError, lockPathFor } from './with-lock.js';
|
|
6
|
+
/**
|
|
7
|
+
* Create a new owner-only file and write `text` into it, failing with EEXIST if
|
|
8
|
+
* the file already exists. Writing through the handle rather than path-based
|
|
9
|
+
* `writeFile(path, …, { flag: 'wx' })` matters: Bun's path form also truncates
|
|
10
|
+
* the file it has just created, and on some Linux filesystems (XFS under load)
|
|
11
|
+
* that redundant ftruncate stalls for hundreds of milliseconds, inside every
|
|
12
|
+
* lock acquisition.
|
|
13
|
+
*/
|
|
14
|
+
async function createExclusiveText(path, text) {
|
|
15
|
+
const handle = await open(path, 'wx', 0o600);
|
|
16
|
+
try {
|
|
17
|
+
await handle.writeFile(text, 'utf8');
|
|
18
|
+
}
|
|
19
|
+
finally {
|
|
20
|
+
await handle.close();
|
|
21
|
+
}
|
|
22
|
+
}
|
|
6
23
|
const setRefreshLockRenewalTimeout = globalThis.setTimeout.bind(globalThis);
|
|
7
24
|
const clearRefreshLockRenewalTimeout = globalThis.clearTimeout.bind(globalThis);
|
|
8
25
|
// A concurrent contender renaming the freshly-created eviction-marker directory
|
|
@@ -152,11 +169,7 @@ export async function acquireRefreshFileLock(options) {
|
|
|
152
169
|
if (windowsPrivateFiles)
|
|
153
170
|
await createPrivateBytes(lockPath, bytes);
|
|
154
171
|
else
|
|
155
|
-
await
|
|
156
|
-
encoding: 'utf8',
|
|
157
|
-
mode: 0o600,
|
|
158
|
-
flag: 'wx',
|
|
159
|
-
});
|
|
172
|
+
await createExclusiveText(lockPath, bytes);
|
|
160
173
|
}
|
|
161
174
|
async function leaseContention(error) {
|
|
162
175
|
const code = error.code;
|
|
@@ -304,11 +317,7 @@ export async function acquireRefreshFileLock(options) {
|
|
|
304
317
|
if (windowsPrivateFiles)
|
|
305
318
|
await createPrivateBytes(evictOwnerPath, bytes);
|
|
306
319
|
else
|
|
307
|
-
await
|
|
308
|
-
encoding: 'utf8',
|
|
309
|
-
mode: 0o600,
|
|
310
|
-
flag: 'wx',
|
|
311
|
-
});
|
|
320
|
+
await createExclusiveText(evictOwnerPath, bytes);
|
|
312
321
|
}
|
|
313
322
|
catch (error) {
|
|
314
323
|
// A competing contender can rename our just-created marker directory
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export interface QuotaCodec {
|
|
2
2
|
readonly validate: (value: unknown) => boolean;
|
|
3
|
+
/** Normalize persisted data before validation; older codecs may omit this. */
|
|
4
|
+
readonly decode?: (value: unknown) => unknown;
|
|
3
5
|
readonly merge: (stored: unknown, observation: unknown) => unknown;
|
|
4
6
|
}
|
|
5
7
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isQuotaMap } from './map.js';
|
|
1
|
+
import { decodeQuotaMap, isQuotaMap } from './map.js';
|
|
2
2
|
import { mergeQuotaObservation } from './merge.js';
|
|
3
3
|
/**
|
|
4
4
|
* The quota codec the account-pool store (the `/store` subpath) takes when it
|
|
@@ -8,5 +8,6 @@ import { mergeQuotaObservation } from './merge.js';
|
|
|
8
8
|
*/
|
|
9
9
|
export const quotaCodec = Object.freeze({
|
|
10
10
|
validate: isQuotaMap,
|
|
11
|
+
decode: decodeQuotaMap,
|
|
11
12
|
merge: mergeQuotaObservation,
|
|
12
13
|
});
|
|
@@ -21,6 +21,26 @@ export interface QuotaTextOptions {
|
|
|
21
21
|
/** Defaults to `QUOTA_STALE_AFTER_MS`. */
|
|
22
22
|
staleAfterMs?: number;
|
|
23
23
|
}
|
|
24
|
+
export interface QuotaWindowPart {
|
|
25
|
+
kind: 'window' | 'budget';
|
|
26
|
+
/** The display name of a quota window, or `credits` for the budget. */
|
|
27
|
+
name: string;
|
|
28
|
+
/** The shared figure wording, including `credits` for budget figures. */
|
|
29
|
+
figure: string;
|
|
30
|
+
/** The unrounded remaining percentage, clamped to 0–100, when known. */
|
|
31
|
+
remainingPercent?: number;
|
|
32
|
+
/** A bare relative reset span such as `4d`, only when the reset is future. */
|
|
33
|
+
resetIn?: string;
|
|
34
|
+
checkedAt: number;
|
|
35
|
+
/** Whether the reset followed this reading and has arrived by `now`. */
|
|
36
|
+
resetSinceReading: boolean;
|
|
37
|
+
}
|
|
38
|
+
export interface QuotaParts {
|
|
39
|
+
/** Reported windows in display order, followed by the budget when present. */
|
|
40
|
+
windows: QuotaWindowPart[];
|
|
41
|
+
/** The shared checked-age wording, present only when the reading is stale. */
|
|
42
|
+
age?: string;
|
|
43
|
+
}
|
|
24
44
|
/**
|
|
25
45
|
* The name a window is shown under. A general window (scope `all`) is named
|
|
26
46
|
* by its stored length; a model-scoped window keeps the label the plugin
|
|
@@ -29,6 +49,12 @@ export interface QuotaTextOptions {
|
|
|
29
49
|
* were recorded) falls back to its label.
|
|
30
50
|
*/
|
|
31
51
|
export declare function quotaWindowName(limit: Pick<ProjectedLimit, 'scope' | 'label' | 'windowMinutes'>): string;
|
|
52
|
+
/**
|
|
53
|
+
* Structured quota wording for layouts that need one row per window. The
|
|
54
|
+
* windows use the same filtering and order as `quotaTextParts`; future resets
|
|
55
|
+
* and the optional age keep the shared formatter's wording.
|
|
56
|
+
*/
|
|
57
|
+
export declare function quotaWindowParts(quota: ProjectedQuota | undefined, options: QuotaTextOptions): QuotaParts;
|
|
32
58
|
/**
|
|
33
59
|
* The pieces of a quota text, in order: one per reported window
|
|
34
60
|
* (`5h 58% left, resets 2h`), then the credit budget when there is one, then
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// The one quota wording every surface shows: the command menu's dialogs on
|
|
2
2
|
// OpenCode and Pi, the terminal auth menu, and the plugins' sidebars. Each of
|
|
3
|
-
// them calls `formatQuota`
|
|
4
|
-
//
|
|
3
|
+
// them calls `formatQuota`, `quotaTextParts`, or `quotaWindowParts`, so the
|
|
4
|
+
// wording cannot drift between plugins or between a dialog and a sidebar.
|
|
5
5
|
//
|
|
6
6
|
// The rules: a window is named by its length (`5h`, `7d`), or, for a window
|
|
7
7
|
// that binds only one model family, by the label the plugin stored it under.
|
|
@@ -22,18 +22,23 @@ export const NO_QUOTA_READING = 'no quota reading yet';
|
|
|
22
22
|
*/
|
|
23
23
|
export const NO_LIMITS_REPORTED = 'no limits reported';
|
|
24
24
|
/**
|
|
25
|
-
* A
|
|
26
|
-
*
|
|
27
|
-
*
|
|
25
|
+
* A time span in at most its two largest units: `45m`, `2h29m`, `5h`, `3d23h`,
|
|
26
|
+
* `7d`. Every unit is rounded down, so a reset is never shown later than it is;
|
|
27
|
+
* the one exception is a span under a minute, which reads `1m` rather than
|
|
28
|
+
* zero. A zero second unit is left out.
|
|
28
29
|
*/
|
|
29
30
|
function shortSpan(ms) {
|
|
30
|
-
const minutes = Math.max(1, Math.
|
|
31
|
+
const minutes = Math.max(1, Math.floor(ms / 60_000));
|
|
31
32
|
if (minutes < 60)
|
|
32
33
|
return `${minutes}m`;
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
if (minutes < 1440) {
|
|
35
|
+
const hours = Math.floor(minutes / 60);
|
|
36
|
+
const rest = minutes % 60;
|
|
37
|
+
return rest === 0 ? `${hours}h` : `${hours}h${rest}m`;
|
|
38
|
+
}
|
|
39
|
+
const days = Math.floor(minutes / 1440);
|
|
40
|
+
const hours = Math.floor((minutes % 1440) / 60);
|
|
41
|
+
return hours === 0 ? `${days}d` : `${days}d${hours}h`;
|
|
37
42
|
}
|
|
38
43
|
/** A stored window length in minutes as its exact name: `5h`, `7d`, `90m`. */
|
|
39
44
|
function lengthName(minutes) {
|
|
@@ -55,17 +60,20 @@ export function quotaWindowName(limit) {
|
|
|
55
60
|
return limit.label;
|
|
56
61
|
return lengthName(limit.windowMinutes);
|
|
57
62
|
}
|
|
63
|
+
function clampPercent(remaining) {
|
|
64
|
+
return Math.min(100, Math.max(0, remaining));
|
|
65
|
+
}
|
|
58
66
|
function percentLeft(remaining) {
|
|
59
|
-
return `${Math.round(
|
|
67
|
+
return `${Math.round(clampPercent(remaining))}% left`;
|
|
60
68
|
}
|
|
61
|
-
function
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
+
function resetDetails(resetsAt, checkedAt, now) {
|
|
70
|
+
const at = resetsAt === undefined ? Number.NaN : Date.parse(resetsAt);
|
|
71
|
+
return {
|
|
72
|
+
...(Number.isFinite(at) && at > now
|
|
73
|
+
? { resetIn: shortSpan(at - now) }
|
|
74
|
+
: {}),
|
|
75
|
+
resetSinceReading: Number.isFinite(at) && at > checkedAt && at <= now,
|
|
76
|
+
};
|
|
69
77
|
}
|
|
70
78
|
/** Shortest window first, so `5h` reads before `7d`; unknown lengths last. */
|
|
71
79
|
function displayOrder(left, right) {
|
|
@@ -85,42 +93,70 @@ function displayOrder(left, right) {
|
|
|
85
93
|
return left.label < right.label ? -1 : left.label > right.label ? 1 : 0;
|
|
86
94
|
}
|
|
87
95
|
/**
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
* was reported; `formatQuota` turns that into a sentence. A caller printing
|
|
92
|
-
* one line per window (the terminal auth menu) uses these directly.
|
|
96
|
+
* Structured quota wording for layouts that need one row per window. The
|
|
97
|
+
* windows use the same filtering and order as `quotaTextParts`; future resets
|
|
98
|
+
* and the optional age keep the shared formatter's wording.
|
|
93
99
|
*/
|
|
94
|
-
export function
|
|
100
|
+
export function quotaWindowParts(quota, options) {
|
|
95
101
|
if (!quota)
|
|
96
|
-
return [];
|
|
102
|
+
return { windows: [] };
|
|
97
103
|
const { now } = options;
|
|
98
|
-
const full = (options.form ?? 'full') === 'full';
|
|
99
|
-
const parts = [];
|
|
100
|
-
const times = [];
|
|
101
104
|
const readings = quota.limits
|
|
102
105
|
.filter((limit) => limit.kind === 'reading' && limit.remainingPercent !== undefined)
|
|
103
106
|
.sort(displayOrder);
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
107
|
+
const windows = readings.map((limit) => {
|
|
108
|
+
const remainingPercent = clampPercent(limit.remainingPercent ?? 0);
|
|
109
|
+
return {
|
|
110
|
+
kind: 'window',
|
|
111
|
+
name: quotaWindowName(limit),
|
|
112
|
+
figure: percentLeft(limit.remainingPercent ?? 0),
|
|
113
|
+
remainingPercent,
|
|
114
|
+
checkedAt: limit.checkedAt,
|
|
115
|
+
...resetDetails(limit.resetsAt, limit.checkedAt, now),
|
|
116
|
+
};
|
|
117
|
+
});
|
|
108
118
|
const budget = quota.budget;
|
|
109
119
|
if (budget) {
|
|
110
|
-
|
|
120
|
+
const remainingPercent = budget.remainingPercent;
|
|
111
121
|
const figure = budget.reached
|
|
112
122
|
? 'credits spent'
|
|
113
|
-
:
|
|
114
|
-
? `credits ${percentLeft(
|
|
123
|
+
: remainingPercent !== undefined
|
|
124
|
+
? `credits ${percentLeft(remainingPercent)}`
|
|
115
125
|
: 'credits available';
|
|
116
|
-
|
|
126
|
+
windows.push({
|
|
127
|
+
kind: 'budget',
|
|
128
|
+
name: 'credits',
|
|
129
|
+
figure,
|
|
130
|
+
...(remainingPercent === undefined
|
|
131
|
+
? {}
|
|
132
|
+
: { remainingPercent: clampPercent(remainingPercent) }),
|
|
133
|
+
checkedAt: budget.checkedAt,
|
|
134
|
+
...resetDetails(budget.resetsAt, budget.checkedAt, now),
|
|
135
|
+
});
|
|
117
136
|
}
|
|
118
|
-
if (
|
|
119
|
-
const age = now - Math.min(...
|
|
120
|
-
if (age > (options.staleAfterMs ?? QUOTA_STALE_AFTER_MS))
|
|
121
|
-
|
|
137
|
+
if (windows.length > 0) {
|
|
138
|
+
const age = now - Math.min(...windows.map((part) => part.checkedAt));
|
|
139
|
+
if (age > (options.staleAfterMs ?? QUOTA_STALE_AFTER_MS)) {
|
|
140
|
+
return { windows, age: `checked ${shortSpan(age)} ago` };
|
|
141
|
+
}
|
|
122
142
|
}
|
|
123
|
-
return
|
|
143
|
+
return { windows };
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* The pieces of a quota text, in order: one per reported window
|
|
147
|
+
* (`5h 58% left, resets 2h`), then the credit budget when there is one, then
|
|
148
|
+
* `checked 3h ago` when the oldest piece shown is stale. Empty when nothing
|
|
149
|
+
* was reported; `formatQuota` turns that into a sentence. A caller printing
|
|
150
|
+
* one line per window (the terminal auth menu) uses these directly.
|
|
151
|
+
*/
|
|
152
|
+
export function quotaTextParts(quota, options) {
|
|
153
|
+
const parts = quotaWindowParts(quota, options);
|
|
154
|
+
const full = (options.form ?? 'full') === 'full';
|
|
155
|
+
const text = parts.windows.map((part) => {
|
|
156
|
+
const reset = full && part.resetIn ? `, resets ${part.resetIn}` : '';
|
|
157
|
+
return `${part.kind === 'budget' ? '' : `${part.name} `}${part.figure}${reset}`;
|
|
158
|
+
});
|
|
159
|
+
return parts.age === undefined ? text : [...text, parts.age];
|
|
124
160
|
}
|
|
125
161
|
/**
|
|
126
162
|
* A row's quota as one line: `5h 58% left · 7d 90% left` in the compact
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
export type { QuotaCodec } from './codec.js';
|
|
2
2
|
export { quotaCodec } from './codec.js';
|
|
3
|
-
export type { QuotaTextForm, QuotaTextOptions } from './format.js';
|
|
4
|
-
export { formatQuota, NO_LIMITS_REPORTED, NO_QUOTA_READING, QUOTA_STALE_AFTER_MS, quotaTextParts, quotaWindowName, } from './format.js';
|
|
5
|
-
export type { CreditBudgetCleared, CreditBudgetEntry, CreditBudgetReading, QuotaAbsentEntry, QuotaEntry, QuotaMap, QuotaReadingEntry, QuotaRetiredEntry, } from './map.js';
|
|
6
|
-
export { ALL_SCOPE, DEFAULT_REQUIRED_LABELS, emptyQuotaMap, isQuotaMap, } from './map.js';
|
|
3
|
+
export type { QuotaParts, QuotaTextForm, QuotaTextOptions, QuotaWindowPart, } from './format.js';
|
|
4
|
+
export { formatQuota, NO_LIMITS_REPORTED, NO_QUOTA_READING, QUOTA_STALE_AFTER_MS, quotaTextParts, quotaWindowName, quotaWindowParts, } from './format.js';
|
|
5
|
+
export type { CreditBudgetCleared, CreditBudgetEntry, CreditBudgetReading, QuotaAbsentEntry, QuotaCounter, QuotaEntry, QuotaMap, QuotaReadingEntry, QuotaRetiredEntry, } from './map.js';
|
|
6
|
+
export { ALL_SCOPE, DEFAULT_REQUIRED_LABELS, decodeQuotaMap, emptyQuotaMap, isQuotaMap, } from './map.js';
|
|
7
7
|
export type { ObservedBudget, ObservedPair, ObservedReading, QuotaObservation, } from './merge.js';
|
|
8
8
|
export { isQuotaObservation, mergeQuotaObservation, QuotaCodecError, } from './merge.js';
|
|
9
9
|
export type { ExhaustionReset, ProjectedBudget, ProjectedLimit, ProjectedQuota, } from './projection.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { quotaCodec } from './codec.js';
|
|
2
|
-
export { formatQuota, NO_LIMITS_REPORTED, NO_QUOTA_READING, QUOTA_STALE_AFTER_MS, quotaTextParts, quotaWindowName, } from './format.js';
|
|
3
|
-
export { ALL_SCOPE, DEFAULT_REQUIRED_LABELS, emptyQuotaMap, isQuotaMap, } from './map.js';
|
|
2
|
+
export { formatQuota, NO_LIMITS_REPORTED, NO_QUOTA_READING, QUOTA_STALE_AFTER_MS, quotaTextParts, quotaWindowName, quotaWindowParts, } from './format.js';
|
|
3
|
+
export { ALL_SCOPE, DEFAULT_REQUIRED_LABELS, decodeQuotaMap, emptyQuotaMap, isQuotaMap, } from './map.js';
|
|
4
4
|
export { isQuotaObservation, mergeQuotaObservation, QuotaCodecError, } from './merge.js';
|
|
5
5
|
export { budgetExhaustedResetAt, futureResetAt, projectQuota, readsExhausted, } from './projection.js';
|
|
@@ -44,16 +44,27 @@ export interface CreditBudgetCleared {
|
|
|
44
44
|
checkedAt: number;
|
|
45
45
|
}
|
|
46
46
|
export type CreditBudgetEntry = CreditBudgetReading | CreditBudgetCleared;
|
|
47
|
+
export interface QuotaCounter {
|
|
48
|
+
value: number;
|
|
49
|
+
checkedAt: number;
|
|
50
|
+
}
|
|
47
51
|
export interface QuotaMap {
|
|
48
52
|
limits: QuotaEntry[];
|
|
49
53
|
/** Absent means no observation has reported on the budget yet. */
|
|
50
54
|
budget?: CreditBudgetEntry;
|
|
55
|
+
/** Provider-named counts, each with its own observation time. */
|
|
56
|
+
counters?: Record<string, QuotaCounter>;
|
|
51
57
|
}
|
|
52
58
|
export declare function emptyQuotaMap(): QuotaMap;
|
|
53
59
|
/** The time an entry speaks for: its reading, retirement or absence time. */
|
|
54
60
|
export declare function entryTime(entry: QuotaEntry): number;
|
|
55
61
|
export declare function limitKey(scope: string, label: string): string;
|
|
56
62
|
export declare function isCreditBudgetEntry(value: unknown): value is CreditBudgetEntry;
|
|
63
|
+
export declare function isQuotaCounters(value: unknown): value is Record<string, QuotaCounter>;
|
|
64
|
+
/** Keep usable counters without letting one malformed count hide a quota map. */
|
|
65
|
+
export declare function readQuotaCounters(value: unknown): Record<string, QuotaCounter> | undefined;
|
|
66
|
+
/** Decode persisted quota, dropping malformed counters but not limit evidence. */
|
|
67
|
+
export declare function decodeQuotaMap(value: unknown): QuotaMap | undefined;
|
|
57
68
|
/**
|
|
58
69
|
* True when `value` is a well-formed quota map. Unrecognised top-level keys
|
|
59
70
|
* are tolerated (and preserved by merge) so a newer writer's additions
|