n9router 0.3.93 → 0.3.95
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/.next/standalone/.next/BUILD_ID +1 -1
- package/.next/standalone/.next/build-manifest.json +3 -3
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/basic-chat/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/basic-chat/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/cli-tools/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/cli-tools/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/combos/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/combos/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/console-log/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/console-log/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/endpoint/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/endpoint/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/mitm/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/mitm/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/profile/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/profile/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/providers/[id]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/providers/[id]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/providers/new/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/providers/new/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/providers/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/providers/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/proxy-pools/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/proxy-pools/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/quota/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/quota/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/translator/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/translator/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/usage/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/dashboard/usage/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_global-error.html +1 -1
- package/.next/standalone/.next/server/app/_global-error.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_not-found.html +1 -1
- package/.next/standalone/.next/server/app/_not-found.rsc +10 -10
- package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +10 -10
- package/.next/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +5 -5
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/api/antigravity-tools/import/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/antigravity-tools/import-refresh-tokens/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/login/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/cli-tools/antigravity-mitm/alias/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/cli-tools/antigravity-mitm/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/cloud/auth/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/cloud/credentials/update/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/cloud/model/resolve/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/cloud/models/alias/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/combos/[id]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/combos/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/init/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/internal/request-detail/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/internal/usage/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/keys/[id]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/keys/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/models/alias/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/models/availability/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/models/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/models/test/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/oauth/[provider]/[action]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/oauth/cursor/import/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/oauth/gitlab/pat/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/oauth/iflow/cookie/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/oauth/kiro/import/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/oauth/kiro/social-exchange/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/pricing/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/provider-nodes/[id]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/provider-nodes/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/providers/[id]/models/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/providers/[id]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/providers/[id]/test/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/providers/[id]/test-models/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/providers/client/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/providers/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/providers/test-batch/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/providers/validate/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/proxy-pools/[id]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/proxy-pools/[id]/test/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/proxy-pools/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/settings/database/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/settings/require-login/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/settings/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/translator/send/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/translator/translate/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/tunnel/disable/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/tunnel/enable/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/tunnel/status/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/usage/[connectionId]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/usage/chart/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/usage/history/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/usage/logs/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/usage/providers/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/usage/request-details/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/usage/request-logs/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/usage/stats/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/usage/stream/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/v1/api/chat/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/v1/chat/completions/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/v1/embeddings/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/v1/messages/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/v1/models/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/v1/responses/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/v1beta/models/[...path]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/callback/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/callback/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/callback.html +1 -1
- package/.next/standalone/.next/server/app/callback.rsc +12 -12
- package/.next/standalone/.next/server/app/callback.segments/_full.segment.rsc +12 -12
- package/.next/standalone/.next/server/app/callback.segments/_head.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/callback.segments/_index.segment.rsc +5 -5
- package/.next/standalone/.next/server/app/callback.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/callback.segments/callback/__PAGE__.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/callback.segments/callback.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/dashboard/basic-chat.html +1 -1
- package/.next/standalone/.next/server/app/dashboard/basic-chat.rsc +12 -12
- package/.next/standalone/.next/server/app/dashboard/basic-chat.segments/!KGRhc2hib2FyZCk/dashboard/basic-chat/__PAGE__.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/dashboard/basic-chat.segments/!KGRhc2hib2FyZCk/dashboard/basic-chat.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/dashboard/basic-chat.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/dashboard/basic-chat.segments/!KGRhc2hib2FyZCk.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/dashboard/basic-chat.segments/_full.segment.rsc +12 -12
- package/.next/standalone/.next/server/app/dashboard/basic-chat.segments/_head.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/dashboard/basic-chat.segments/_index.segment.rsc +5 -5
- package/.next/standalone/.next/server/app/dashboard/basic-chat.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/cli-tools.html +1 -1
- package/.next/standalone/.next/server/app/dashboard/cli-tools.rsc +12 -12
- package/.next/standalone/.next/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk/dashboard/cli-tools/__PAGE__.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk/dashboard/cli-tools.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/dashboard/cli-tools.segments/_full.segment.rsc +12 -12
- package/.next/standalone/.next/server/app/dashboard/cli-tools.segments/_head.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/dashboard/cli-tools.segments/_index.segment.rsc +5 -5
- package/.next/standalone/.next/server/app/dashboard/cli-tools.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/combos.html +1 -1
- package/.next/standalone/.next/server/app/dashboard/combos.rsc +13 -13
- package/.next/standalone/.next/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk/dashboard/combos/__PAGE__.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk/dashboard/combos.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/dashboard/combos.segments/_full.segment.rsc +13 -13
- package/.next/standalone/.next/server/app/dashboard/combos.segments/_head.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/dashboard/combos.segments/_index.segment.rsc +5 -5
- package/.next/standalone/.next/server/app/dashboard/combos.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/endpoint.html +1 -1
- package/.next/standalone/.next/server/app/dashboard/endpoint.rsc +12 -12
- package/.next/standalone/.next/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk/dashboard/endpoint/__PAGE__.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk/dashboard/endpoint.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/dashboard/endpoint.segments/_full.segment.rsc +12 -12
- package/.next/standalone/.next/server/app/dashboard/endpoint.segments/_head.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/dashboard/endpoint.segments/_index.segment.rsc +5 -5
- package/.next/standalone/.next/server/app/dashboard/endpoint.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/mitm.html +1 -1
- package/.next/standalone/.next/server/app/dashboard/mitm.rsc +12 -12
- package/.next/standalone/.next/server/app/dashboard/mitm.segments/!KGRhc2hib2FyZCk/dashboard/mitm/__PAGE__.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/dashboard/mitm.segments/!KGRhc2hib2FyZCk/dashboard/mitm.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/dashboard/mitm.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/dashboard/mitm.segments/!KGRhc2hib2FyZCk.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/dashboard/mitm.segments/_full.segment.rsc +12 -12
- package/.next/standalone/.next/server/app/dashboard/mitm.segments/_head.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/dashboard/mitm.segments/_index.segment.rsc +5 -5
- package/.next/standalone/.next/server/app/dashboard/mitm.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/profile.html +1 -1
- package/.next/standalone/.next/server/app/dashboard/profile.rsc +13 -13
- package/.next/standalone/.next/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk/dashboard/profile/__PAGE__.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk/dashboard/profile.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/dashboard/profile.segments/_full.segment.rsc +13 -13
- package/.next/standalone/.next/server/app/dashboard/profile.segments/_head.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/dashboard/profile.segments/_index.segment.rsc +5 -5
- package/.next/standalone/.next/server/app/dashboard/profile.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/providers/new.html +1 -1
- package/.next/standalone/.next/server/app/dashboard/providers/new.rsc +13 -13
- package/.next/standalone/.next/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard/providers/new/__PAGE__.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard/providers/new.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard/providers.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/dashboard/providers/new.segments/_full.segment.rsc +13 -13
- package/.next/standalone/.next/server/app/dashboard/providers/new.segments/_head.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/dashboard/providers/new.segments/_index.segment.rsc +5 -5
- package/.next/standalone/.next/server/app/dashboard/providers/new.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/providers.html +1 -1
- package/.next/standalone/.next/server/app/dashboard/providers.rsc +13 -13
- package/.next/standalone/.next/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk/dashboard/providers/__PAGE__.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk/dashboard/providers.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/dashboard/providers.segments/_full.segment.rsc +13 -13
- package/.next/standalone/.next/server/app/dashboard/providers.segments/_head.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/dashboard/providers.segments/_index.segment.rsc +5 -5
- package/.next/standalone/.next/server/app/dashboard/providers.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/proxy-pools.html +1 -1
- package/.next/standalone/.next/server/app/dashboard/proxy-pools.rsc +13 -13
- package/.next/standalone/.next/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk/dashboard/proxy-pools/__PAGE__.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk/dashboard/proxy-pools.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/dashboard/proxy-pools.segments/_full.segment.rsc +13 -13
- package/.next/standalone/.next/server/app/dashboard/proxy-pools.segments/_head.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/dashboard/proxy-pools.segments/_index.segment.rsc +5 -5
- package/.next/standalone/.next/server/app/dashboard/proxy-pools.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/quota.html +2 -2
- package/.next/standalone/.next/server/app/dashboard/quota.rsc +13 -13
- package/.next/standalone/.next/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk/dashboard/quota/__PAGE__.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk/dashboard/quota.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/dashboard/quota.segments/_full.segment.rsc +13 -13
- package/.next/standalone/.next/server/app/dashboard/quota.segments/_head.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/dashboard/quota.segments/_index.segment.rsc +5 -5
- package/.next/standalone/.next/server/app/dashboard/quota.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/settings/pricing/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/dashboard/settings/pricing/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/dashboard/settings/pricing.html +1 -1
- package/.next/standalone/.next/server/app/dashboard/settings/pricing.rsc +12 -12
- package/.next/standalone/.next/server/app/dashboard/settings/pricing.segments/_full.segment.rsc +12 -12
- package/.next/standalone/.next/server/app/dashboard/settings/pricing.segments/_head.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/dashboard/settings/pricing.segments/_index.segment.rsc +5 -5
- package/.next/standalone/.next/server/app/dashboard/settings/pricing.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/settings/pricing.segments/dashboard/settings/pricing/__PAGE__.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/dashboard/settings/pricing.segments/dashboard/settings/pricing.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/dashboard/settings/pricing.segments/dashboard/settings.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/dashboard/settings/pricing.segments/dashboard.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/dashboard/translator.html +1 -1
- package/.next/standalone/.next/server/app/dashboard/translator.rsc +13 -13
- package/.next/standalone/.next/server/app/dashboard/translator.segments/!KGRhc2hib2FyZCk/dashboard/translator/__PAGE__.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/dashboard/translator.segments/!KGRhc2hib2FyZCk/dashboard/translator.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/dashboard/translator.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/dashboard/translator.segments/!KGRhc2hib2FyZCk.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/dashboard/translator.segments/_full.segment.rsc +13 -13
- package/.next/standalone/.next/server/app/dashboard/translator.segments/_head.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/dashboard/translator.segments/_index.segment.rsc +5 -5
- package/.next/standalone/.next/server/app/dashboard/translator.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard/usage.html +1 -1
- package/.next/standalone/.next/server/app/dashboard/usage.rsc +13 -13
- package/.next/standalone/.next/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk/dashboard/usage/__PAGE__.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk/dashboard/usage.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/dashboard/usage.segments/_full.segment.rsc +13 -13
- package/.next/standalone/.next/server/app/dashboard/usage.segments/_head.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/dashboard/usage.segments/_index.segment.rsc +5 -5
- package/.next/standalone/.next/server/app/dashboard/usage.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/dashboard.html +1 -1
- package/.next/standalone/.next/server/app/dashboard.rsc +12 -12
- package/.next/standalone/.next/server/app/dashboard.segments/!KGRhc2hib2FyZCk/dashboard/__PAGE__.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/dashboard.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/dashboard.segments/!KGRhc2hib2FyZCk.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/dashboard.segments/_full.segment.rsc +12 -12
- package/.next/standalone/.next/server/app/dashboard.segments/_head.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/dashboard.segments/_index.segment.rsc +5 -5
- package/.next/standalone/.next/server/app/dashboard.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/index.html +1 -1
- package/.next/standalone/.next/server/app/index.rsc +10 -10
- package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +10 -10
- package/.next/standalone/.next/server/app/index.segments/_head.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/index.segments/_index.segment.rsc +5 -5
- package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/landing/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/landing/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/landing.html +1 -1
- package/.next/standalone/.next/server/app/landing.rsc +12 -12
- package/.next/standalone/.next/server/app/landing.segments/_full.segment.rsc +12 -12
- package/.next/standalone/.next/server/app/landing.segments/_head.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/landing.segments/_index.segment.rsc +5 -5
- package/.next/standalone/.next/server/app/landing.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/landing.segments/landing/__PAGE__.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/landing.segments/landing.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/login/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/login/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/login.html +1 -1
- package/.next/standalone/.next/server/app/login.rsc +12 -12
- package/.next/standalone/.next/server/app/login.segments/_full.segment.rsc +12 -12
- package/.next/standalone/.next/server/app/login.segments/_head.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/login.segments/_index.segment.rsc +5 -5
- package/.next/standalone/.next/server/app/login.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/login.segments/login/__PAGE__.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/login.segments/login.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0.yvcis._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0148t9m._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0b802lh._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0kpc-o6._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0lc~.sk._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0lp_pm5._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0pwrfp1._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0uw3x8s._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0y.reft._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0y5ae.7._.js +1 -1
- package/.next/standalone/.next/server/chunks/_0__-aqg._.js +1 -1
- package/.next/standalone/.next/server/chunks/_0_ovl1h._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/src_0_xhepz._.js +1 -1
- package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
- package/.next/standalone/.next/server/pages/404.html +1 -1
- package/.next/standalone/.next/server/pages/500.html +1 -1
- package/.next/{static/chunks/0deg-_syv13xx.js → standalone/.next/static/chunks/11q6656-lc_oz.js} +1 -1
- package/.next/standalone/mitm/server.js +168 -113
- package/.next/standalone/mitm/tokenPool.js +168 -20
- package/.next/standalone/package-lock.json +2 -2
- package/.next/standalone/package.json +1 -1
- package/.next/standalone/plans/tauri-app/01-scope-and-architecture.md +218 -0
- package/.next/standalone/plans/tauri-app/02-backend-plan.md +237 -0
- package/.next/standalone/plans/tauri-app/03-tauri-native-plan.md +194 -0
- package/.next/standalone/plans/tauri-app/04-react-ui-plan.md +155 -0
- package/.next/standalone/plans/tauri-app/05-delivery-phases.md +171 -0
- package/.next/standalone/plans/tauri-app/README.md +87 -0
- package/.next/standalone/src/mitm/server.js +168 -113
- package/.next/standalone/src/mitm/tokenPool.js +168 -20
- package/.next/{standalone/.next/static/chunks/0deg-_syv13xx.js → static/chunks/11q6656-lc_oz.js} +1 -1
- package/package.json +1 -1
- /package/.next/standalone/.next/static/{b_Drjo0YdAiFCInKT62q9 → 03mW5vaG0Fogum-tDkkOQ}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{b_Drjo0YdAiFCInKT62q9 → 03mW5vaG0Fogum-tDkkOQ}/_clientMiddlewareManifest.js +0 -0
- /package/.next/standalone/.next/static/{b_Drjo0YdAiFCInKT62q9 → 03mW5vaG0Fogum-tDkkOQ}/_ssgManifest.js +0 -0
- /package/.next/static/{b_Drjo0YdAiFCInKT62q9 → 03mW5vaG0Fogum-tDkkOQ}/_buildManifest.js +0 -0
- /package/.next/static/{b_Drjo0YdAiFCInKT62q9 → 03mW5vaG0Fogum-tDkkOQ}/_clientMiddlewareManifest.js +0 -0
- /package/.next/static/{b_Drjo0YdAiFCInKT62q9 → 03mW5vaG0Fogum-tDkkOQ}/_ssgManifest.js +0 -0
|
@@ -14,9 +14,11 @@ const DB_FILE = path.join(DATA_DIR, "db.json");
|
|
|
14
14
|
const TOKEN_EXPIRY_BUFFER_MS = 5 * 60 * 1000; // refresh 5min before expiry
|
|
15
15
|
const ROUTER_PORT = process.env.PORT || 20128;
|
|
16
16
|
const DEFAULT_COOLDOWN_MS = 5 * 60 * 1000;
|
|
17
|
+
const DEFAULT_AUTH_COOLDOWN_MS = 10 * 60 * 1000;
|
|
17
18
|
|
|
18
19
|
// ── In-memory state ──────────────────────────────────────────
|
|
19
|
-
const cooldownMap = {}; // { [connectionId]: expiresTimestamp }
|
|
20
|
+
const cooldownMap = {}; // { [connectionId]: expiresTimestamp } quota/general cooldown
|
|
21
|
+
const authCooldownMap = {}; // { [connectionId]: expiresTimestamp } invalid_token/auth cooldown
|
|
20
22
|
const modelCooldownMap = {}; // { [connectionId]: { [model]: expiresTimestamp } }
|
|
21
23
|
const rrState = {}; // { [provider]: roundRobinIndex }
|
|
22
24
|
|
|
@@ -28,13 +30,33 @@ function setCooldown(connId, durationMs) {
|
|
|
28
30
|
log(`⏸ [token-pool] cooldown: ${connId.slice(0, 8)}… for ${Math.ceil(ms / 60000)}m`);
|
|
29
31
|
}
|
|
30
32
|
|
|
31
|
-
function
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
function setAuthCooldown(connId, durationMs) {
|
|
34
|
+
const ms = durationMs || DEFAULT_AUTH_COOLDOWN_MS;
|
|
35
|
+
authCooldownMap[connId] = Date.now() + ms;
|
|
36
|
+
log(`🔒 [token-pool] auth-cooldown: ${connId.slice(0, 8)}… for ${Math.ceil(ms / 60000)}m`);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function getMapExpiry(map, connId) {
|
|
40
|
+
if (!map[connId]) return 0;
|
|
41
|
+
if (Date.now() > map[connId]) {
|
|
42
|
+
delete map[connId];
|
|
43
|
+
return 0;
|
|
36
44
|
}
|
|
37
|
-
return
|
|
45
|
+
return map[connId];
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function getCooldownState(connId) {
|
|
49
|
+
const authExpiry = getMapExpiry(authCooldownMap, connId);
|
|
50
|
+
if (authExpiry) return { type: "auth", expiresAt: authExpiry };
|
|
51
|
+
|
|
52
|
+
const quotaExpiry = getMapExpiry(cooldownMap, connId);
|
|
53
|
+
if (quotaExpiry) return { type: "quota", expiresAt: quotaExpiry };
|
|
54
|
+
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function isInCooldown(connId) {
|
|
59
|
+
return !!getCooldownState(connId);
|
|
38
60
|
}
|
|
39
61
|
|
|
40
62
|
// ── Per-model cooldown management ────────────────────────────
|
|
@@ -110,6 +132,90 @@ function getActiveConnections(provider) {
|
|
|
110
132
|
} catch { return []; }
|
|
111
133
|
}
|
|
112
134
|
|
|
135
|
+
function getTokenSwapAvailabilitySummary(provider, model) {
|
|
136
|
+
try {
|
|
137
|
+
if (!fs.existsSync(DB_FILE)) {
|
|
138
|
+
return {
|
|
139
|
+
total: 0,
|
|
140
|
+
eligible: 0,
|
|
141
|
+
skipped: 0,
|
|
142
|
+
reasons: {},
|
|
143
|
+
summaryText: "0/0 account(s) eligible"
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const db = JSON.parse(fs.readFileSync(DB_FILE, "utf-8"));
|
|
148
|
+
const connections = (db.providerConnections || []).filter(c => c.provider === provider);
|
|
149
|
+
const now = Date.now();
|
|
150
|
+
const strategy = getTokenSwapStrategy();
|
|
151
|
+
const reasons = {
|
|
152
|
+
inactive: 0,
|
|
153
|
+
noToken: 0,
|
|
154
|
+
expiredNoRefresh: 0,
|
|
155
|
+
quotaCooldown: 0,
|
|
156
|
+
authCooldown: 0,
|
|
157
|
+
modelCooldown: 0,
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
let eligible = 0;
|
|
161
|
+
|
|
162
|
+
for (const connection of connections) {
|
|
163
|
+
if (connection.isActive === false) {
|
|
164
|
+
reasons.inactive += 1;
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
if (!connection.accessToken) {
|
|
168
|
+
reasons.noToken += 1;
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
if (connection.expiresAt && new Date(connection.expiresAt).getTime() < now && !connection.refreshToken) {
|
|
172
|
+
reasons.expiredNoRefresh += 1;
|
|
173
|
+
continue;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const cooldownState = getCooldownState(connection.id);
|
|
177
|
+
if (cooldownState?.type === "auth") {
|
|
178
|
+
reasons.authCooldown += 1;
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
if (cooldownState?.type === "quota") {
|
|
182
|
+
reasons.quotaCooldown += 1;
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
if (strategy === "sticky" && model && isModelExhausted(connection.id, model)) {
|
|
187
|
+
reasons.modelCooldown += 1;
|
|
188
|
+
continue;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
eligible += 1;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const skipped = connections.length - eligible;
|
|
195
|
+
const reasonParts = [];
|
|
196
|
+
if (reasons.quotaCooldown) reasonParts.push(`${reasons.quotaCooldown} quota cooldown`);
|
|
197
|
+
if (reasons.authCooldown) reasonParts.push(`${reasons.authCooldown} auth cooldown`);
|
|
198
|
+
if (reasons.modelCooldown) reasonParts.push(`${reasons.modelCooldown} model cooldown`);
|
|
199
|
+
if (reasons.inactive) reasonParts.push(`${reasons.inactive} inactive`);
|
|
200
|
+
if (reasons.noToken) reasonParts.push(`${reasons.noToken} missing token`);
|
|
201
|
+
if (reasons.expiredNoRefresh) reasonParts.push(`${reasons.expiredNoRefresh} expired-no-refresh`);
|
|
202
|
+
|
|
203
|
+
const summaryText = skipped > 0
|
|
204
|
+
? `${eligible}/${connections.length} account(s) eligible, skipped ${skipped} (${reasonParts.join(", ")})`
|
|
205
|
+
: `${eligible}/${connections.length} account(s) eligible`;
|
|
206
|
+
|
|
207
|
+
return { total: connections.length, eligible, skipped, reasons, summaryText };
|
|
208
|
+
} catch {
|
|
209
|
+
return {
|
|
210
|
+
total: 0,
|
|
211
|
+
eligible: 0,
|
|
212
|
+
skipped: 0,
|
|
213
|
+
reasons: {},
|
|
214
|
+
summaryText: "0/0 account(s) eligible"
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
113
219
|
function getConnectionById(connId) {
|
|
114
220
|
try {
|
|
115
221
|
if (!fs.existsSync(DB_FILE)) return null;
|
|
@@ -287,41 +393,82 @@ function markAccountUsed(connId) {
|
|
|
287
393
|
// checks expiry, refreshes token automatically, then returns the
|
|
288
394
|
// latest persisted connection snapshot for the current request.
|
|
289
395
|
|
|
290
|
-
async function
|
|
291
|
-
if (!connection?.expiresAt || !connection?.refreshToken) return connection;
|
|
292
|
-
const expiresAt = new Date(connection.expiresAt).getTime();
|
|
293
|
-
if (Date.now() + TOKEN_EXPIRY_BUFFER_MS < expiresAt) return connection;
|
|
294
|
-
|
|
295
|
-
log(`🔄 [token-pool] near-expiry refresh → ${getConnectionLabel(connection).slice(0, 20)}`);
|
|
396
|
+
async function runConnectionTest(connection) {
|
|
296
397
|
return await new Promise((resolve) => {
|
|
398
|
+
if (!connection?.id) {
|
|
399
|
+
resolve({ connection, refreshed: false, valid: false });
|
|
400
|
+
return;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
let responseBody = "";
|
|
404
|
+
|
|
297
405
|
try {
|
|
298
406
|
const req = http.request(
|
|
299
407
|
{ hostname: "127.0.0.1", port: ROUTER_PORT, path: `/api/providers/${connection.id}/test`, method: "POST" },
|
|
300
408
|
(res) => {
|
|
301
|
-
res.on("data", () => {
|
|
409
|
+
res.on("data", (chunk) => {
|
|
410
|
+
responseBody += chunk.toString();
|
|
411
|
+
});
|
|
302
412
|
res.on("end", () => {
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
413
|
+
let payload = {};
|
|
414
|
+
try {
|
|
415
|
+
payload = JSON.parse(responseBody || "{}");
|
|
416
|
+
} catch {
|
|
417
|
+
payload = {};
|
|
306
418
|
}
|
|
307
|
-
|
|
419
|
+
|
|
420
|
+
const refreshedConnection = getConnectionById(connection.id);
|
|
421
|
+
const tokenChanged = !!(refreshedConnection?.accessToken && refreshedConnection.accessToken !== connection.accessToken);
|
|
422
|
+
resolve({
|
|
423
|
+
connection: refreshedConnection || connection,
|
|
424
|
+
refreshed: !!payload.refreshed || tokenChanged,
|
|
425
|
+
valid: !!payload.valid,
|
|
426
|
+
});
|
|
308
427
|
});
|
|
309
428
|
}
|
|
310
429
|
);
|
|
311
|
-
req.on("error", () => resolve(connection));
|
|
430
|
+
req.on("error", () => resolve({ connection, refreshed: false, valid: false }));
|
|
312
431
|
req.end();
|
|
313
432
|
} catch {
|
|
314
|
-
resolve(connection);
|
|
433
|
+
resolve({ connection, refreshed: false, valid: false });
|
|
315
434
|
}
|
|
316
435
|
});
|
|
317
436
|
}
|
|
318
437
|
|
|
438
|
+
async function triggerRefreshIfNeeded(connection) {
|
|
439
|
+
if (!connection?.expiresAt || !connection?.refreshToken) return connection;
|
|
440
|
+
const expiresAt = new Date(connection.expiresAt).getTime();
|
|
441
|
+
if (Date.now() + TOKEN_EXPIRY_BUFFER_MS < expiresAt) return connection;
|
|
442
|
+
|
|
443
|
+
log(`🔄 [token-pool] near-expiry refresh → ${getConnectionLabel(connection).slice(0, 20)}`);
|
|
444
|
+
const result = await runConnectionTest(connection);
|
|
445
|
+
if (result.refreshed) {
|
|
446
|
+
log(`♻️ [token-pool] refreshed token applied → ${getConnectionLabel(connection).slice(0, 20)}`);
|
|
447
|
+
}
|
|
448
|
+
return result.connection || connection;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
async function forceRefreshConnection(connection) {
|
|
452
|
+
if (!connection?.refreshToken) {
|
|
453
|
+
return { connection, refreshed: false, valid: false };
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
log(`🔄 [token-pool] auth refresh → ${getConnectionLabel(connection).slice(0, 20)}`);
|
|
457
|
+
const result = await runConnectionTest(connection);
|
|
458
|
+
if (result.refreshed) {
|
|
459
|
+
log(`♻️ [token-pool] refreshed token applied → ${getConnectionLabel(connection).slice(0, 20)}`);
|
|
460
|
+
}
|
|
461
|
+
return result;
|
|
462
|
+
}
|
|
463
|
+
|
|
319
464
|
module.exports = {
|
|
320
465
|
isTokenSwapEnabled,
|
|
321
466
|
getNextConnection,
|
|
322
467
|
getAllActiveConnections,
|
|
323
468
|
triggerRefreshIfNeeded,
|
|
469
|
+
forceRefreshConnection,
|
|
324
470
|
setCooldown,
|
|
471
|
+
setAuthCooldown,
|
|
325
472
|
setModelCooldown,
|
|
326
473
|
isModelExhausted,
|
|
327
474
|
getTokenSwapStrategy,
|
|
@@ -329,4 +476,5 @@ module.exports = {
|
|
|
329
476
|
markAccountUsed,
|
|
330
477
|
getConnectionLabel,
|
|
331
478
|
maskEmail,
|
|
479
|
+
getTokenSwapAvailabilitySummary,
|
|
332
480
|
};
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "n9router",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.95",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "n9router",
|
|
9
|
-
"version": "0.3.
|
|
9
|
+
"version": "0.3.95",
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@monaco-editor/react": "^4.7.0",
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
# Scope And Architecture
|
|
2
|
+
|
|
3
|
+
## Scope
|
|
4
|
+
|
|
5
|
+
### In scope
|
|
6
|
+
|
|
7
|
+
- Antigravity OAuth and account import
|
|
8
|
+
- project ID fetch/onboarding if needed by account validation or usage flows
|
|
9
|
+
- MITM HTTPS server for Antigravity domains
|
|
10
|
+
- DNS/hosts enable-disable for Antigravity
|
|
11
|
+
- root certificate generation and trust flow
|
|
12
|
+
- token swap across Antigravity accounts
|
|
13
|
+
- usage persistence, logs, request detail capture
|
|
14
|
+
- desktop-first UI for operating the above
|
|
15
|
+
- cross-platform support for macOS, Windows, and Linux
|
|
16
|
+
|
|
17
|
+
### Out of scope
|
|
18
|
+
|
|
19
|
+
- generic AI router
|
|
20
|
+
- upstream model aliasing outside MITM use case
|
|
21
|
+
- generic provider CRUD for all existing providers
|
|
22
|
+
- all `src/app/api/v1/*` compatibility APIs
|
|
23
|
+
- cloud deployment and Workers support
|
|
24
|
+
|
|
25
|
+
## Existing code to reuse
|
|
26
|
+
|
|
27
|
+
### Core logic to preserve
|
|
28
|
+
|
|
29
|
+
- Antigravity OAuth flow:
|
|
30
|
+
- `src/lib/oauth/services/antigravity.js`
|
|
31
|
+
- MITM server:
|
|
32
|
+
- `src/mitm/server.js`
|
|
33
|
+
- `src/mitm/handlers/antigravity.js`
|
|
34
|
+
- `src/mitm/config.js`
|
|
35
|
+
- token swap:
|
|
36
|
+
- `src/mitm/tokenPool.js`
|
|
37
|
+
- usage capture:
|
|
38
|
+
- `src/mitm/usageTracker.js`
|
|
39
|
+
- `src/lib/usageDb.js`
|
|
40
|
+
- settings and account persistence:
|
|
41
|
+
- `src/lib/localDb.js`
|
|
42
|
+
- DNS and cert operations:
|
|
43
|
+
- `src/mitm/dns/dnsConfig.js`
|
|
44
|
+
- `src/mitm/cert/*`
|
|
45
|
+
- `src/mitm/manager.js`
|
|
46
|
+
- account import from local Antigravity install:
|
|
47
|
+
- `src/app/api/antigravity-tools/import/route.js`
|
|
48
|
+
|
|
49
|
+
### UI logic to mine and adapt
|
|
50
|
+
|
|
51
|
+
- `src/app/(dashboard)/dashboard/mitm/MitmPageClient.js`
|
|
52
|
+
- `src/app/(dashboard)/dashboard/usage/page.js`
|
|
53
|
+
- `src/app/(dashboard)/dashboard/usage/components/RequestDetailsTab.js`
|
|
54
|
+
- `src/app/(dashboard)/dashboard/usage/components/OverviewCards.js`
|
|
55
|
+
- `src/shared/constants/cliTools.js`
|
|
56
|
+
|
|
57
|
+
## Target workspace layout
|
|
58
|
+
|
|
59
|
+
```text
|
|
60
|
+
apps/
|
|
61
|
+
desktop-shell/ # Tauri
|
|
62
|
+
desktop-ui/ # React SPA
|
|
63
|
+
desktop-backend/ # Express service
|
|
64
|
+
packages/
|
|
65
|
+
desktop-shared/ # API contracts, DTOs, constants
|
|
66
|
+
plans/
|
|
67
|
+
tauri-app/
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Runtime boundaries
|
|
71
|
+
|
|
72
|
+
### Tauri Rust owns
|
|
73
|
+
|
|
74
|
+
- secure credential storage integration
|
|
75
|
+
- privileged actions
|
|
76
|
+
- backend process supervision
|
|
77
|
+
- MITM sidecar process supervision if separate from backend
|
|
78
|
+
- app data dir resolution
|
|
79
|
+
- native menu, tray, startup behavior
|
|
80
|
+
- platform adaptation for macOS, Windows, and Linux behaviors
|
|
81
|
+
|
|
82
|
+
### Express backend owns
|
|
83
|
+
|
|
84
|
+
- account storage
|
|
85
|
+
- OAuth callback server or callback handling
|
|
86
|
+
- account import and validation
|
|
87
|
+
- MITM routing logic
|
|
88
|
+
- token swap state machine
|
|
89
|
+
- usage writes and reads
|
|
90
|
+
- internal APIs called by usage observer
|
|
91
|
+
|
|
92
|
+
### React UI owns
|
|
93
|
+
|
|
94
|
+
- control plane only
|
|
95
|
+
- polling/subscribing to backend status
|
|
96
|
+
- visualization of pool state and usage data
|
|
97
|
+
- no direct filesystem or privileged OS operations
|
|
98
|
+
|
|
99
|
+
## Critical design decisions
|
|
100
|
+
|
|
101
|
+
### 1. Keep MITM logic in JS for v1
|
|
102
|
+
|
|
103
|
+
Reason:
|
|
104
|
+
|
|
105
|
+
- existing behavior is already implemented
|
|
106
|
+
- request interception and stream parsing are sensitive
|
|
107
|
+
- product value comes from shipping the desktop app, not from rewriting stable logic
|
|
108
|
+
|
|
109
|
+
### 2. Move OS privilege work out of Node
|
|
110
|
+
|
|
111
|
+
Reason:
|
|
112
|
+
|
|
113
|
+
- current Node code handles passwords and host mutations directly
|
|
114
|
+
- desktop app should centralize privileged operations in Tauri
|
|
115
|
+
- Tauri offers a cleaner UX for elevation prompts and secret handling
|
|
116
|
+
|
|
117
|
+
### 3. Keep JSON persistence first
|
|
118
|
+
|
|
119
|
+
Reason:
|
|
120
|
+
|
|
121
|
+
- current code already uses `db.json`, `usage.json`, and `log.txt`
|
|
122
|
+
- enough for a desktop MVP
|
|
123
|
+
- storage migration to SQLite is a separate concern and should not block v1
|
|
124
|
+
|
|
125
|
+
### 4. Design for cross-platform from day one
|
|
126
|
+
|
|
127
|
+
Reason:
|
|
128
|
+
|
|
129
|
+
- DNS and certificate flows are different on each OS
|
|
130
|
+
- port 443 and elevation behavior differ across OSes
|
|
131
|
+
- retrofitting Windows and Linux after a macOS-first implementation will create avoidable rework
|
|
132
|
+
|
|
133
|
+
## Platform support requirements
|
|
134
|
+
|
|
135
|
+
### Shared
|
|
136
|
+
|
|
137
|
+
- same user-facing feature set on macOS, Windows, and Linux
|
|
138
|
+
- same backend API contract across all OSes
|
|
139
|
+
- same persistence format across all OSes
|
|
140
|
+
- same token swap semantics across all OSes
|
|
141
|
+
|
|
142
|
+
### macOS
|
|
143
|
+
|
|
144
|
+
- support hosts-file mutation
|
|
145
|
+
- support certificate trust flow
|
|
146
|
+
- support DNS cache flush
|
|
147
|
+
|
|
148
|
+
### Windows
|
|
149
|
+
|
|
150
|
+
- support hosts-file mutation under elevated privileges
|
|
151
|
+
- support certificate trust flow using Windows certificate store
|
|
152
|
+
- support UAC-based elevation flow without requiring terminal usage
|
|
153
|
+
|
|
154
|
+
### Linux
|
|
155
|
+
|
|
156
|
+
- support hosts-file mutation on major desktop distros
|
|
157
|
+
- support root certificate installation at least for the app-documented path
|
|
158
|
+
- support DNS cache flush with distro-safe fallbacks
|
|
159
|
+
- gracefully handle environments without `sudo`
|
|
160
|
+
|
|
161
|
+
## Architecture diagram
|
|
162
|
+
|
|
163
|
+
```mermaid
|
|
164
|
+
flowchart LR
|
|
165
|
+
UI["React Desktop UI"] --> API["Local Express Backend"]
|
|
166
|
+
UI --> TAURI["Tauri Commands"]
|
|
167
|
+
TAURI --> OS["OS Cert / DNS / Secure Store"]
|
|
168
|
+
TAURI --> API
|
|
169
|
+
API --> DB["db.json / usage.json / log.txt"]
|
|
170
|
+
API --> MITM["MITM HTTPS Server"]
|
|
171
|
+
MITM --> AG["Antigravity Domains"]
|
|
172
|
+
MITM --> API
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## MVP feature map
|
|
176
|
+
|
|
177
|
+
### Accounts
|
|
178
|
+
|
|
179
|
+
- list accounts
|
|
180
|
+
- connect via browser OAuth
|
|
181
|
+
- import from `~/.antigravity_tools`
|
|
182
|
+
- enable/disable account
|
|
183
|
+
- show token expiry and refresh availability
|
|
184
|
+
|
|
185
|
+
### MITM
|
|
186
|
+
|
|
187
|
+
- cert exists
|
|
188
|
+
- cert trusted
|
|
189
|
+
- server running
|
|
190
|
+
- DNS active
|
|
191
|
+
- health status
|
|
192
|
+
- start/stop controls
|
|
193
|
+
- platform-specific remediation text when a native action fails
|
|
194
|
+
|
|
195
|
+
### Token swap
|
|
196
|
+
|
|
197
|
+
- enable/disable
|
|
198
|
+
- strategy selection
|
|
199
|
+
- account pool table
|
|
200
|
+
- cooldown visibility
|
|
201
|
+
- auth failure visibility
|
|
202
|
+
- last-used rotation indicator
|
|
203
|
+
|
|
204
|
+
### Usage analyst
|
|
205
|
+
|
|
206
|
+
- totals
|
|
207
|
+
- recent requests
|
|
208
|
+
- token totals
|
|
209
|
+
- estimated cost
|
|
210
|
+
- request details drawer
|
|
211
|
+
- account-level and model-level filtering
|
|
212
|
+
|
|
213
|
+
## Cross-platform acceptance criteria
|
|
214
|
+
|
|
215
|
+
- the app can be packaged and launched on macOS, Windows, and Linux
|
|
216
|
+
- backend startup path is identical from the UI perspective on all OSes
|
|
217
|
+
- cert/DNS/MITM state is surfaced consistently on all OSes
|
|
218
|
+
- platform-specific failure messages are understandable and actionable
|