@jheavenknows/bluerouter 5.5.34 → 5.5.36
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/app/.next-cli-build/BUILD_ID +1 -1
- package/app/.next-cli-build/app-path-routes-manifest.json +24 -24
- package/app/.next-cli-build/build-manifest.json +2 -2
- package/app/.next-cli-build/prerender-manifest.json +3 -3
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/ai-power-index/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/analytics/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/api-keys/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/audit-proxy/page.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/audit-proxy/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/basic-chat/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/cli-tools/[toolId]/page.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/cli-tools/[toolId]/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/cli-tools/model-profiles/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/cli-tools/page.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/cli-tools/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/cluster/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/combos/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/console-log/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/endpoint/page.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/endpoint/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/logs/console/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/logs/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/media-providers/[kind]/[id]/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/media-providers/[kind]/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/media-providers/combo/[id]/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/media-providers/web/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/page.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/personal/page.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/personal/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/personalcloudcombo/page.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/personalcloudcombo/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/personalcloudprovider/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/personalcloudprovidermonitor/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/personalquota/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/profile/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/prompt-logs/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/provider-health/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/providers/[id]/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/providers/embedding/[id]/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/providers/embedding/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/providers/image/[id]/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/providers/image/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/providers/image-to-text/[id]/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/providers/image-to-text/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/providers/new/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/providers/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/providers/stt/[id]/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/providers/stt/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/providers/tts/[id]/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/providers/tts/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/providers/web/[kind]/[id]/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/providers/web/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/proxy-pools/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/quota/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/resource-monitor/page.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/resource-monitor/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/settings/pricing/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/skills/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/token-saver/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/translator/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/usage/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/_global-error.html +1 -1
- package/app/.next-cli-build/server/app/_global-error.rsc +1 -1
- package/app/.next-cli-build/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/_not-found.html +1 -1
- package/app/.next-cli-build/server/app/_not-found.rsc +5 -5
- package/app/.next-cli-build/server/app/_not-found.segments/_full.segment.rsc +5 -5
- package/app/.next-cli-build/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +5 -5
- package/app/.next-cli-build/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/api/audit-proxy/ca/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/audit-proxy/me/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/audit-proxy/root-ca/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/audit-proxy/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/audit-proxy/users/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/auth/ldap/test/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/auth/ldap/users/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/auth/login/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/auth/logout/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/auth/oidc/callback/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/auth/oidc/start/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/auth/oidc/test/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/auth/status/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/auth/view-mode/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/branding/[asset]/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/branding/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/branding/upload/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/cli-model-profiles/cloud-models/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/cli-model-profiles/model-catalog/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/cli-model-profiles/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/cli-tools/all-statuses/route.js +4 -4
- package/app/.next-cli-build/server/app/api/cli-tools/all-statuses/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/cli-tools/claude-settings/route.js +2 -2
- package/app/.next-cli-build/server/app/api/cli-tools/cline-settings/route.js +1 -1
- package/app/.next-cli-build/server/app/api/cli-tools/codex-settings/route.js +1 -1
- package/app/.next-cli-build/server/app/api/cli-tools/copilot-settings/route.js +2 -2
- package/app/.next-cli-build/server/app/api/cli-tools/copilot-settings/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/cli-tools/cowork-mcp-registry/route.js +1 -1
- package/app/.next-cli-build/server/app/api/cli-tools/cowork-mcp-tools/route.js +1 -1
- package/app/.next-cli-build/server/app/api/cli-tools/cowork-settings/route.js +1 -1
- package/app/.next-cli-build/server/app/api/cli-tools/cowork-settings/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/cli-tools/deepseek-tui-settings/route.js +2 -2
- package/app/.next-cli-build/server/app/api/cli-tools/droid-settings/route.js +2 -2
- package/app/.next-cli-build/server/app/api/cli-tools/hermes-settings/route.js +2 -2
- package/app/.next-cli-build/server/app/api/cli-tools/jcode-settings/route.js +2 -2
- package/app/.next-cli-build/server/app/api/cli-tools/kilo-settings/route.js +2 -2
- package/app/.next-cli-build/server/app/api/cli-tools/openclaw-settings/route.js +2 -2
- package/app/.next-cli-build/server/app/api/cli-tools/opencode-settings/route.js +1 -1
- package/app/.next-cli-build/server/app/api/cli-tools/qwen-settings/route.js +1 -1
- package/app/.next-cli-build/server/app/api/cluster/config/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/cluster/heartbeat/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/cluster/peers/[id]/command/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/cluster/peers/[id]/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/cluster/peers/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/cluster/snapshot/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/cluster/sync/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/cluster/test/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/codex-catalog/download/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/codex-catalog/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/codex-catalog/upload/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/combos/[id]/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/combos/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/dashboard/ai-power-index/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/dashboard/analytics/ai-models/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/dashboard/analytics/analyze/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/dashboard/analytics/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/dashboard/combos/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/dashboard/endpoint/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/dashboard/prompt-logs/[id]/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/dashboard/prompt-logs/options/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/dashboard/prompt-logs/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/dashboard/token-saver/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/keys/[id]/caveman-test/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/keys/[id]/rotate/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/keys/[id]/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/keys/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/mcp/[plugin]/message/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/mcp/[plugin]/sse/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/media-providers/tts/deepgram/voices/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/media-providers/tts/elevenlabs/voices/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/media-providers/tts/inworld/voices/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/media-providers/tts/minimax/voices/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/models/alias/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/models/availability/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/models/custom/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/models/disabled/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/models/route.js +1 -1
- package/app/.next-cli-build/server/app/api/models/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/models/test/route.js +1 -1
- package/app/.next-cli-build/server/app/api/models/test/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/oauth/[provider]/[action]/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/oauth/codex/import-token/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/oauth/cursor/auto-import/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/oauth/cursor/import/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/oauth/gitlab/pat/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/oauth/grok-cli/device-code/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/oauth/grok-cli/poll/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/oauth/iflow/cookie/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/oauth/kiro/import/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/oauth/kiro/social-exchange/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/personal-cloud-combos/[id]/api-key-models/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/personal-cloud-combos/[id]/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/personal-cloud-combos/route.js +1 -1
- package/app/.next-cli-build/server/app/api/personal-cloud-combos/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/personal-cloud-providers/[id]/api-key-models/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/personal-cloud-providers/[id]/import-models/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/personal-cloud-providers/[id]/models/[...routeModel]/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/personal-cloud-providers/[id]/move/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/personal-cloud-providers/[id]/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/personal-cloud-providers/[id]/usage/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/personal-cloud-providers/account-emails/route.js +2 -2
- package/app/.next-cli-build/server/app/api/personal-cloud-providers/account-emails/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/personal-cloud-providers/account-policy/route.js +1 -1
- package/app/.next-cli-build/server/app/api/personal-cloud-providers/account-policy/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/personal-cloud-providers/client/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/personal-cloud-providers/monitor/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/personal-cloud-providers/pending-accounts/route.js +2 -2
- package/app/.next-cli-build/server/app/api/personal-cloud-providers/pending-accounts/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/personal-cloud-providers/permissions/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/personal-cloud-providers/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/personal-cloud-providers/routing/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/personal-cloud-providers/shares/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/personal-cloud-providers/visibility/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/personal-oauth-email/verify/route.js +2 -2
- package/app/.next-cli-build/server/app/api/personal-oauth-email/verify/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/pricing/catalog/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/pricing/recalculate/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/pricing/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/provider-health/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/provider-nodes/[id]/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/provider-nodes/combo-references/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/provider-nodes/custom-embedding/manage/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/provider-nodes/openai-compatible/manage/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/provider-nodes/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/providers/[id]/models/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/providers/[id]/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/providers/[id]/test/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/providers/[id]/test-models/route.js +1 -1
- package/app/.next-cli-build/server/app/api/providers/[id]/test-models/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/providers/client/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/providers/route.js +1 -1
- package/app/.next-cli-build/server/app/api/providers/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/providers/test-batch/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/providers/validate/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/proxy-pools/[id]/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/proxy-pools/[id]/test/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/proxy-pools/cloudflare-deploy/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/proxy-pools/deno-deploy/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/proxy-pools/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/proxy-pools/vercel-deploy/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/resource-monitor/[id]/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/resource-monitor/ai-models/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/resource-monitor/analyze/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/resource-monitor/history/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/resource-monitor/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/settings/database/export/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/settings/database/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/settings/prompt-log-db/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/settings/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/settings/smtp/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/translator/console-logs/route.js +1 -1
- package/app/.next-cli-build/server/app/api/translator/console-logs/stream/route.js +1 -1
- package/app/.next-cli-build/server/app/api/translator/send/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/translator/translate/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/usage/[connectionId]/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/usage/chart/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/usage/history/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/usage/logs/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/usage/providers/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/usage/request-details/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/usage/request-logs/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/usage/stats/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/usage/stream/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/v1/api/chat/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/v1/audio/speech/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/v1/audio/transcriptions/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/v1/chat/completions/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/v1/embeddings/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/v1/images/generations/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/v1/messages/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/v1/models/[kind]/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/v1/models/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/v1/rate-limits/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/v1/responses/compact/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/v1/responses/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/v1/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/v1/search/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/v1/web/fetch/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/v1beta/models/[...path]/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/v1beta/models/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/version/shutdown/route.js +1 -1
- package/app/.next-cli-build/server/app/api/version/shutdown/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/version/update/route.js +1 -1
- package/app/.next-cli-build/server/app/api/version/update/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/callback/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/callback.html +1 -1
- package/app/.next-cli-build/server/app/callback.rsc +5 -5
- package/app/.next-cli-build/server/app/callback.segments/_full.segment.rsc +5 -5
- package/app/.next-cli-build/server/app/callback.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/callback.segments/callback/__PAGE__.segment.rsc +5 -5
- package/app/.next-cli-build/server/app/dashboard/ai-power-index.html +1 -1
- package/app/.next-cli-build/server/app/dashboard/ai-power-index.rsc +6 -6
- package/app/.next-cli-build/server/app/dashboard/ai-power-index.segments/!KGRhc2hib2FyZCk/dashboard/ai-power-index/__PAGE__.segment.rsc +6 -6
- package/app/.next-cli-build/server/app/dashboard/ai-power-index.segments/_full.segment.rsc +6 -6
- package/app/.next-cli-build/server/app/dashboard/ai-power-index.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/api-keys.html +1 -1
- package/app/.next-cli-build/server/app/dashboard/api-keys.rsc +9 -9
- package/app/.next-cli-build/server/app/dashboard/api-keys.segments/!KGRhc2hib2FyZCk/dashboard/api-keys/__PAGE__.segment.rsc +9 -9
- package/app/.next-cli-build/server/app/dashboard/api-keys.segments/_full.segment.rsc +9 -9
- package/app/.next-cli-build/server/app/dashboard/api-keys.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/basic-chat.html +1 -1
- package/app/.next-cli-build/server/app/dashboard/basic-chat.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/basic-chat.segments/!KGRhc2hib2FyZCk/dashboard/basic-chat/__PAGE__.segment.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/basic-chat.segments/_full.segment.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/basic-chat.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/cli-tools/model-profiles.html +1 -1
- package/app/.next-cli-build/server/app/dashboard/cli-tools/model-profiles.rsc +8 -8
- package/app/.next-cli-build/server/app/dashboard/cli-tools/model-profiles.segments/!KGRhc2hib2FyZCk/dashboard/cli-tools/model-profiles/__PAGE__.segment.rsc +8 -8
- package/app/.next-cli-build/server/app/dashboard/cli-tools/model-profiles.segments/_full.segment.rsc +8 -8
- package/app/.next-cli-build/server/app/dashboard/cli-tools/model-profiles.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/cli-tools.html +1 -1
- package/app/.next-cli-build/server/app/dashboard/cli-tools.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk/dashboard/cli-tools/__PAGE__.segment.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/cli-tools.segments/_full.segment.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/cli-tools.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/cluster.html +1 -1
- package/app/.next-cli-build/server/app/dashboard/cluster.rsc +6 -6
- package/app/.next-cli-build/server/app/dashboard/cluster.segments/!KGRhc2hib2FyZCk/dashboard/cluster/__PAGE__.segment.rsc +6 -6
- package/app/.next-cli-build/server/app/dashboard/cluster.segments/_full.segment.rsc +6 -6
- package/app/.next-cli-build/server/app/dashboard/cluster.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/combos.html +1 -1
- package/app/.next-cli-build/server/app/dashboard/combos.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk/dashboard/combos/__PAGE__.segment.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/combos.segments/_full.segment.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/combos.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/endpoint.html +1 -1
- package/app/.next-cli-build/server/app/dashboard/endpoint.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk/dashboard/endpoint/__PAGE__.segment.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/endpoint.segments/_full.segment.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/endpoint.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/logs.html +1 -1
- package/app/.next-cli-build/server/app/dashboard/logs.rsc +6 -6
- package/app/.next-cli-build/server/app/dashboard/logs.segments/!KGRhc2hib2FyZCk/dashboard/logs/__PAGE__.segment.rsc +6 -6
- package/app/.next-cli-build/server/app/dashboard/logs.segments/_full.segment.rsc +6 -6
- package/app/.next-cli-build/server/app/dashboard/logs.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/media-providers/web.html +1 -1
- package/app/.next-cli-build/server/app/dashboard/media-providers/web.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/media-providers/web.segments/!KGRhc2hib2FyZCk/dashboard/media-providers/web/__PAGE__.segment.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/media-providers/web.segments/_full.segment.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/media-providers/web.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/personal.html +1 -1
- package/app/.next-cli-build/server/app/dashboard/personal.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/personal.segments/!KGRhc2hib2FyZCk/dashboard/personal/__PAGE__.segment.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/personal.segments/_full.segment.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/personal.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/profile.html +1 -1
- package/app/.next-cli-build/server/app/dashboard/profile.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk/dashboard/profile/__PAGE__.segment.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/profile.segments/_full.segment.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/profile.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/prompt-logs.html +1 -1
- package/app/.next-cli-build/server/app/dashboard/prompt-logs.rsc +6 -6
- package/app/.next-cli-build/server/app/dashboard/prompt-logs.segments/!KGRhc2hib2FyZCk/dashboard/prompt-logs/__PAGE__.segment.rsc +6 -6
- package/app/.next-cli-build/server/app/dashboard/prompt-logs.segments/_full.segment.rsc +6 -6
- package/app/.next-cli-build/server/app/dashboard/prompt-logs.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/provider-health.html +1 -1
- package/app/.next-cli-build/server/app/dashboard/provider-health.rsc +6 -6
- package/app/.next-cli-build/server/app/dashboard/provider-health.segments/!KGRhc2hib2FyZCk/dashboard/provider-health/__PAGE__.segment.rsc +6 -6
- package/app/.next-cli-build/server/app/dashboard/provider-health.segments/_full.segment.rsc +6 -6
- package/app/.next-cli-build/server/app/dashboard/provider-health.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/providers/embedding.html +1 -1
- package/app/.next-cli-build/server/app/dashboard/providers/embedding.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/providers/embedding.segments/!KGRhc2hib2FyZCk/dashboard/providers/embedding/__PAGE__.segment.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/providers/embedding.segments/_full.segment.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/providers/embedding.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/providers/image-to-text.html +1 -1
- package/app/.next-cli-build/server/app/dashboard/providers/image-to-text.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/providers/image-to-text.segments/!KGRhc2hib2FyZCk/dashboard/providers/image-to-text/__PAGE__.segment.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/providers/image-to-text.segments/_full.segment.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/providers/image-to-text.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/providers/image.html +1 -1
- package/app/.next-cli-build/server/app/dashboard/providers/image.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/providers/image.segments/!KGRhc2hib2FyZCk/dashboard/providers/image/__PAGE__.segment.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/providers/image.segments/_full.segment.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/providers/image.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/providers/new.html +1 -1
- package/app/.next-cli-build/server/app/dashboard/providers/new.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard/providers/new/__PAGE__.segment.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/providers/new.segments/_full.segment.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/providers/new.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/providers/stt.html +1 -1
- package/app/.next-cli-build/server/app/dashboard/providers/stt.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/providers/stt.segments/!KGRhc2hib2FyZCk/dashboard/providers/stt/__PAGE__.segment.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/providers/stt.segments/_full.segment.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/providers/stt.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/providers/tts.html +1 -1
- package/app/.next-cli-build/server/app/dashboard/providers/tts.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/providers/tts.segments/!KGRhc2hib2FyZCk/dashboard/providers/tts/__PAGE__.segment.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/providers/tts.segments/_full.segment.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/providers/tts.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/providers/web.html +1 -1
- package/app/.next-cli-build/server/app/dashboard/providers/web.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/providers/web.segments/!KGRhc2hib2FyZCk/dashboard/providers/web/__PAGE__.segment.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/providers/web.segments/_full.segment.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/providers/web.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/providers.html +1 -1
- package/app/.next-cli-build/server/app/dashboard/providers.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk/dashboard/providers/__PAGE__.segment.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/providers.segments/_full.segment.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/providers.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/proxy-pools.html +1 -1
- package/app/.next-cli-build/server/app/dashboard/proxy-pools.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk/dashboard/proxy-pools/__PAGE__.segment.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/proxy-pools.segments/_full.segment.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/proxy-pools.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/quota.html +1 -1
- package/app/.next-cli-build/server/app/dashboard/quota.rsc +8 -8
- package/app/.next-cli-build/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk/dashboard/quota/__PAGE__.segment.rsc +8 -8
- package/app/.next-cli-build/server/app/dashboard/quota.segments/_full.segment.rsc +8 -8
- package/app/.next-cli-build/server/app/dashboard/quota.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/resource-monitor.html +1 -1
- package/app/.next-cli-build/server/app/dashboard/resource-monitor.rsc +6 -6
- package/app/.next-cli-build/server/app/dashboard/resource-monitor.segments/!KGRhc2hib2FyZCk/dashboard/resource-monitor/__PAGE__.segment.rsc +6 -6
- package/app/.next-cli-build/server/app/dashboard/resource-monitor.segments/_full.segment.rsc +6 -6
- package/app/.next-cli-build/server/app/dashboard/resource-monitor.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/settings/pricing.html +1 -1
- package/app/.next-cli-build/server/app/dashboard/settings/pricing.rsc +6 -6
- package/app/.next-cli-build/server/app/dashboard/settings/pricing.segments/!KGRhc2hib2FyZCk/dashboard/settings/pricing/__PAGE__.segment.rsc +6 -6
- package/app/.next-cli-build/server/app/dashboard/settings/pricing.segments/_full.segment.rsc +6 -6
- package/app/.next-cli-build/server/app/dashboard/settings/pricing.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/skills.html +1 -1
- package/app/.next-cli-build/server/app/dashboard/skills.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/skills.segments/!KGRhc2hib2FyZCk/dashboard/skills/__PAGE__.segment.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/skills.segments/_full.segment.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/skills.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/token-saver.html +1 -1
- package/app/.next-cli-build/server/app/dashboard/token-saver.rsc +6 -6
- package/app/.next-cli-build/server/app/dashboard/token-saver.segments/!KGRhc2hib2FyZCk/dashboard/token-saver/__PAGE__.segment.rsc +6 -6
- package/app/.next-cli-build/server/app/dashboard/token-saver.segments/_full.segment.rsc +6 -6
- package/app/.next-cli-build/server/app/dashboard/token-saver.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/translator.html +1 -1
- package/app/.next-cli-build/server/app/dashboard/translator.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/translator.segments/!KGRhc2hib2FyZCk/dashboard/translator/__PAGE__.segment.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/translator.segments/_full.segment.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/translator.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/usage.html +1 -1
- package/app/.next-cli-build/server/app/dashboard/usage.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk/dashboard/usage/__PAGE__.segment.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/usage.segments/_full.segment.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/usage.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard.html +1 -1
- package/app/.next-cli-build/server/app/dashboard.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard.segments/!KGRhc2hib2FyZCk/dashboard/__PAGE__.segment.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard.segments/_full.segment.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/index.html +1 -1
- package/app/.next-cli-build/server/app/index.rsc +5 -5
- package/app/.next-cli-build/server/app/index.segments/__PAGE__.segment.rsc +5 -5
- package/app/.next-cli-build/server/app/index.segments/_full.segment.rsc +5 -5
- package/app/.next-cli-build/server/app/index.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/landing/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/landing.html +1 -1
- package/app/.next-cli-build/server/app/landing.rsc +5 -5
- package/app/.next-cli-build/server/app/landing.segments/_full.segment.rsc +5 -5
- package/app/.next-cli-build/server/app/landing.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/landing.segments/landing/__PAGE__.segment.rsc +5 -5
- package/app/.next-cli-build/server/app/login/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/login.html +1 -1
- package/app/.next-cli-build/server/app/login.rsc +6 -6
- package/app/.next-cli-build/server/app/login.segments/_full.segment.rsc +6 -6
- package/app/.next-cli-build/server/app/login.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/login.segments/login/__PAGE__.segment.rsc +6 -6
- package/app/.next-cli-build/server/app/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app-paths-manifest.json +24 -24
- package/app/.next-cli-build/server/chunks/2428.js +1 -1
- package/app/.next-cli-build/server/chunks/2867.js +1 -1
- package/app/.next-cli-build/server/chunks/3399.js +1 -1
- package/app/.next-cli-build/server/chunks/4003.js +1 -1
- package/app/.next-cli-build/server/chunks/4746.js +1 -1
- package/app/.next-cli-build/server/chunks/4778.js +1 -1
- package/app/.next-cli-build/server/chunks/6236.js +1 -1
- package/app/.next-cli-build/server/chunks/6811.js +1 -1
- package/app/.next-cli-build/server/chunks/6992.js +1 -1
- package/app/.next-cli-build/server/chunks/7126.js +1 -1
- package/app/.next-cli-build/server/chunks/8946.js +2 -2
- package/app/.next-cli-build/server/chunks/9037.js +2 -2
- package/app/.next-cli-build/server/chunks/9489.js +1 -1
- package/app/.next-cli-build/server/middleware-build-manifest.js +1 -1
- package/app/.next-cli-build/server/pages/404.html +1 -1
- package/app/.next-cli-build/server/pages/500.html +1 -1
- package/app/.next-cli-build/server/server-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/server-reference-manifest.json +1 -1
- package/app/.next-cli-build/static/chunks/{5263-ce3eee6759a72d58.js → 5263-703b00aba6c5bb1f.js} +1 -1
- package/app/.next-cli-build/static/chunks/912-18e8c0b298d404a0.js +1 -0
- package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/personal/page-5241ac88a293c965.js +1 -0
- package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/personalcloudcombo/page-899a8a75058f3959.js +1 -0
- package/app/cli/.build-home/AppData/Roaming/bluerouter/db/backups/{upgrade-5.5.28-to-5.5.29-5.5.29-20260924-103755 → upgrade-5.5.33-to-5.5.34-5.5.34-20260924-180218}/data.sqlite +0 -0
- package/app/cli/.build-home/AppData/Roaming/bluerouter/db/data.sqlite-shm +0 -0
- package/app/cli/.build-home/AppData/Roaming/bluerouter/db/data.sqlite-wal +0 -0
- package/app/package.json +1 -1
- package/package.json +1 -1
- package/app/.next-cli-build/static/chunks/912-a978dfe116157ecf.js +0 -1
- package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/personal/page-34f2672c5f3185e1.js +0 -1
- package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/personalcloudcombo/page-49b624ecbe4f4e3f.js +0 -1
- /package/app/.next-cli-build/static/{6c055jLT98rCMNi9NWSBj → xOi7_D4lBYmsajJ_tW7MH}/_buildManifest.js +0 -0
- /package/app/.next-cli-build/static/{6c055jLT98rCMNi9NWSBj → xOi7_D4lBYmsajJ_tW7MH}/_ssgManifest.js +0 -0
- /package/app/cli/.build-home/AppData/Roaming/bluerouter/db/backups/{upgrade-5.5.29-to-5.5.30-5.5.30-20260924-104020 → upgrade-5.5.32-to-5.5.33-5.5.33-20260924-173620}/data.sqlite +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[3674],{17:(e,t,s)=>{"use strict";s.d(t,{A:()=>c});var r=s(95155),n=s(98500),a=s.n(n),i=s(14051),l=s.n(i),d=s(31474);function c({tabs:e,activeId:t,onChange:s,className:n=""}){return(0,r.jsx)("div",{className:(0,d.cn)("mb-5 overflow-x-auto border-b border-border",n),children:(0,r.jsx)("div",{className:"flex min-w-max items-center gap-1",children:e.map(e=>{let n=e.id===t,i=(0,d.cn)("inline-flex items-center gap-2 border-b-2 px-4 py-3 text-sm font-semibold transition-colors",n?"border-primary text-primary":"border-transparent text-text-muted hover:border-border-strong hover:text-text-main"),l=(0,r.jsxs)(r.Fragment,{children:[e.icon?(0,r.jsx)("span",{className:"material-symbols-outlined text-[18px]",children:e.icon}):null,(0,r.jsx)("span",{children:e.label})]});return e.href?(0,r.jsx)(a(),{href:e.href,className:i,"aria-current":n?"page":void 0,children:l},e.id):(0,r.jsx)("button",{type:"button",onClick:()=>s?.(e.id),className:i,"aria-pressed":n,children:l},e.id)})})})}c.propTypes={tabs:l().arrayOf(l().shape({id:l().string.isRequired,label:l().string.isRequired,icon:l().string,href:l().string})).isRequired,activeId:l().string.isRequired,onChange:l().func,className:l().string}},12749:(e,t,s)=>{"use strict";s.r(t),s.d(t,{default:()=>D});var r=s(95155),n=s(12115),a=s(25086),i=s(94027),l=s(17),d=s(17173),c=s(6945),o=s(35497),m=s(57250),x=s(31458);function h(e){return String(e||"").trim().toLowerCase()}function u(){let{isAdmin:e}=(0,i.s)(),[t,s]=(0,n.useState)([]),[a,l]=(0,n.useState)({}),[d,c]=(0,n.useState)({}),[u,p]=(0,n.useState)(""),[g,b]=(0,n.useState)({}),[f,j]=(0,n.useState)(""),[v,y]=(0,n.useState)({}),[N,w]=(0,n.useState)(3),[k,C]=(0,n.useState)("3"),[S,A]=(0,n.useState)(!0),[E,$]=(0,n.useState)(!1),[P,T]=(0,n.useState)(!1),[O,K]=(0,n.useState)(""),[U,G]=(0,n.useState)(""),[q,I]=(0,n.useState)(""),[z,L]=(0,n.useState)(""),[D,M]=(0,n.useState)(null),[H,_]=(0,n.useState)(!1),[B,R]=(0,n.useState)(!1),[F,Z]=(0,n.useState)(!1),J=(0,n.useCallback)(e=>{l(e.permissions||{}),c(e.connectionsByUser||{}),"number"==typeof e.globalConnectionsPerProviderLimit&&e.globalConnectionsPerProviderLimit>0&&(w(e.globalConnectionsPerProviderLimit),C(String(e.globalConnectionsPerProviderLimit))),e.connectionsPerProviderLimitOverrides&&"object"==typeof e.connectionsPerProviderLimitOverrides&&y(e.connectionsPerProviderLimitOverrides)},[]),X=(0,n.useCallback)(async()=>{if(e){A(!0),G("");try{let[e,t]=await Promise.all([fetch("/api/personal-cloud-providers",{cache:"no-store"}),fetch("/api/personal-cloud-providers/permissions",{cache:"no-store"})]),r=await e.json().catch(()=>({})),n=await t.json().catch(()=>({}));if(!e.ok)throw Error(r.error||"Kh\xf4ng tải được personal OAuth providers");if(!t.ok)throw Error(n.error||"Kh\xf4ng tải được quyền OAuth");s(Array.isArray(r.providers)?r.providers:[]),J(n)}catch(e){G(e?.message||"Kh\xf4ng tải được cấu h\xecnh OAuth access")}finally{A(!1)}}},[J,e]);(0,n.useEffect)(()=>{X()},[X]);let V=(0,n.useRef)(0),Q=(0,n.useCallback)(async e=>{let t=e.trim();if(!t)return;let s=++V.current;_(!0);try{let e=await fetch(`/api/personal-cloud-providers/permissions?search=${encodeURIComponent(t)}`,{cache:"no-store"}),r=await e.json().catch(()=>({}));if(s!==V.current)return;if(!e.ok)throw Error(r.error||"Kh\xf4ng t\xecm được t\xe0i khoản");M(Array.isArray(r.accounts)?r.accounts:[]),R(!!r.accountsTruncated)}catch(e){if(s!==V.current)return;M([]),G(e?.message||"Kh\xf4ng t\xecm được t\xe0i khoản")}finally{s===V.current&&_(!1)}},[]);(0,n.useEffect)(()=>{if(!e)return;if(!z.trim()){M(null),R(!1),_(!1);return}let t=setTimeout(()=>Q(z),300);return()=>clearTimeout(t)},[z,e,Q]),(0,n.useEffect)(()=>{let e=h(u),s=a[e]||{},r={};for(let e of t)r[e.id]=!0===s[e.id];b(r);let n=v[e];j(n>0?String(n):"")},[u,a,t,v]);let W=(0,n.useMemo)(()=>Array.from(new Set([...Object.keys(a||{}),...Object.keys(d||{})])).map(e=>{let s=a[e]||{},r=d[e]||{},n=t.filter(e=>s?.[e.id]===!0),i=t.some(e=>Number(r[e.id]||0)>0);return{userId:e,providerState:s,connectionsByProvider:r,enabledProviders:n,hasAnyConnection:i}}).filter(e=>e.enabledProviders.length>0||e.hasAnyConnection).sort((e,t)=>e.userId.localeCompare(t.userId)),[d,a,t]),Y=null!==D,ee=(0,n.useMemo)(()=>Y?D.map(e=>{let s=e.providerState||{},r=e.connectionsByProvider||{},n=t.filter(e=>s?.[e.id]===!0),a=t.some(e=>Number(r[e.id]||0)>0);return{userId:e.userId,displayName:e.displayName,email:e.email,providerState:s,connectionsByProvider:r,enabledProviders:n,hasAnyConnection:a}}).sort((e,t)=>e.userId.localeCompare(t.userId)):W,[Y,D,W,t]),et=(0,n.useMemo)(()=>{let e=0,s=0,r=0,n=new Map(t.map(e=>[e.id,{grantedUsers:0,connections:0}]));for(let a of W){for(let s of t){let t=Number(a.connectionsByProvider?.[s.id]||0);e+=t;let r=n.get(s.id);a.providerState?.[s.id]===!0?(r.grantedUsers+=1,r.connections+=t):t>0&&(r.connections+=t)}a.enabledProviders.length>0&&!a.hasAnyConnection&&(s+=1),0===a.enabledProviders.length&&a.hasAnyConnection&&(r+=1)}return{totalUsers:W.length,totalConnections:e,grantedNoConnection:s,connectionNoGrant:r,perProvider:t.map(e=>({provider:e,...n.get(e.id)}))}},[W,t]),es=async()=>{let e,t=h(u);if(!t)return void G("Nhập username/email cần cấp quyền.");let s=String(f||"").trim();if(""===s)e=null;else{let t=Number.parseInt(s,10);if(!Number.isFinite(t)||t<=0)return void G("Per-user override phải l\xe0 số nguy\xean dương hoặc bỏ trống.");e=t}$(!0),G(""),I("");try{let s=await fetch("/api/personal-cloud-providers/permissions",{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify({userId:t,providers:g,connectionsPerProviderLimit:e})}),r=await s.json().catch(()=>({}));if(!s.ok)throw Error(r.error||"Kh\xf4ng lưu được quyền OAuth");J(r);let n=r.user?.id||t;p(n),I(`Đ\xe3 lưu quyền OAuth cho ${n}.`),Z(!1),z.trim()&&Q(z)}catch(e){G(e?.message||"Kh\xf4ng lưu được quyền OAuth")}finally{$(!1)}},er=async()=>{let e=Number.parseInt(k,10);if(!Number.isFinite(e)||e<=0)return void G("Global limit phải l\xe0 số nguy\xean dương.");T(!0),G(""),I("");try{let t=await fetch("/api/personal-cloud-providers/permissions",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({globalConnectionsPerProviderLimit:e})}),s=await t.json().catch(()=>({}));if(!t.ok)throw Error(s.error||"Kh\xf4ng lưu được global limit");J(s),I(`Đ\xe3 đặt global limit = ${e} account / provider / user.`)}catch(e){G(e?.message||"Kh\xf4ng lưu được global limit")}finally{T(!1)}},en=async e=>{let t=h(e);if(t){$(!0),G(""),I("");try{let e=await fetch(`/api/personal-cloud-providers/permissions?userId=${encodeURIComponent(t)}`,{method:"DELETE"}),s=await e.json().catch(()=>({}));if(!e.ok)throw Error(s.error||"Kh\xf4ng thu hồi được quyền OAuth");J(s),h(u)===t&&p("");let r=s.disconnectSummary||{},n=Number(r.manualActionRequired)||0;I(`Đ\xe3 x\xf3a ${r.deletedCount||0} OAuth connection của ${t}; ${r.upstreamRevokedCount||0} token đ\xe3 revoke upstream.${n>0?` ${n} connection cần thu hồi thủ c\xf4ng tại provider.`:""}`),K(""),z.trim()&&Q(z)}catch(e){G(e?.message||"Kh\xf4ng thu hồi được quyền OAuth")}finally{$(!1)}}};if(!e)return null;let ea=W.find(e=>e.userId===h(O)),ei=t.reduce((e,t)=>e+Number(ea?.connectionsByProvider?.[t.id]||0),0);return(0,r.jsxs)("div",{className:"space-y-5",children:[(0,r.jsxs)("div",{className:"rounded-2xl border border-border bg-surface/50 p-4",children:[(0,r.jsx)("h1",{className:"text-xl font-semibold text-text-main",children:"Admin: OAuth provider access"}),(0,r.jsx)("p",{className:"mt-1 text-sm text-text-muted",children:"Quản l\xfd provider n\xe0o user được ph\xe9p d\xf9ng, giới hạn số account OAuth c\xe1 nh\xe2n v\xe0 thu hồi to\xe0n bộ quyền/token khi cần. C\xe1c thao t\xe1c trong tab n\xe0y chỉ d\xe0nh cho admin."})]}),(0,r.jsx)(x.default,{}),U?(0,r.jsx)("div",{className:"rounded-xl border border-red-500/30 bg-red-500/10 px-4 py-3 text-sm text-red-700 dark:text-red-300",children:U}):null,q?(0,r.jsx)("div",{className:"rounded-xl border border-green-500/30 bg-green-500/10 px-4 py-3 text-sm text-green-700 dark:text-green-300",children:q}):null,(0,r.jsxs)(o.Zp,{className:"space-y-4",children:[(0,r.jsxs)("div",{className:"flex flex-col gap-2 md:flex-row md:items-center md:justify-between",children:[(0,r.jsxs)("div",{children:[(0,r.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"Access policy"}),(0,r.jsx)("p",{className:"text-sm text-text-muted",children:"Default l\xe0 kh\xf4ng c\xf3 quyền. Tắt provider giữ nguy\xean connection/token để c\xf3 thể bật lại; Revoke all sẽ thử revoke upstream rồi x\xf3a connection/token local."})]}),(0,r.jsx)(o.$n,{variant:"outline",size:"sm",onClick:X,loading:S,icon:"refresh",children:"Refresh"})]}),(0,r.jsxs)("div",{className:"rounded-2xl border border-border bg-surface p-4",children:[(0,r.jsx)("div",{className:"text-sm font-medium",children:"Global limit — số account OAuth c\xe1 nh\xe2n / provider / user thường"}),(0,r.jsx)("p",{className:"mt-1 text-xs text-text-muted",children:"\xc1p dụng cho user kh\xf4ng c\xf3 per-user override. Admin kh\xf4ng bị chặn bởi limit n\xe0y."}),(0,r.jsxs)("div",{className:"mt-3 flex flex-col gap-2 sm:flex-row sm:items-end",children:[(0,r.jsx)(o.pd,{type:"number",min:1,value:k,onChange:e=>C(e.target.value),className:"sm:w-48"}),(0,r.jsx)(o.$n,{onClick:er,loading:P,disabled:P||Number.parseInt(k,10)===N,children:"Lưu global"}),(0,r.jsxs)("span",{className:"text-xs text-text-muted",children:["Đang lưu: ",N]})]})]}),(0,r.jsxs)("div",{className:"border-t border-border pt-4",children:[(0,r.jsxs)("div",{className:"mb-3",children:[(0,r.jsx)("h3",{className:"font-semibold text-text-main",children:"Granted OAuth Access"}),(0,r.jsx)("p",{className:"text-xs text-text-muted",children:"T\xecm một t\xe0i khoản (username/email) để xem v\xe0 chỉnh quyền — kể cả t\xe0i khoản chưa được cấp quyền g\xec. Kh\xf4ng t\xecm kiếm th\xec hiển thị c\xe1c t\xe0i khoản đang c\xf3 quyền hoặc c\xf2n OAuth connection."})]}),S?(0,r.jsx)("div",{className:"rounded-2xl border border-dashed border-border p-6 text-center text-sm text-text-muted",children:"Đang tải quyền..."}):(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)("div",{className:"mb-4 grid grid-cols-1 gap-3 sm:grid-cols-2 md:grid-cols-4",children:[(0,r.jsxs)("div",{className:"rounded-2xl border border-border bg-surface p-4",children:[(0,r.jsx)("div",{className:"text-xs font-semibold uppercase text-text-muted",children:"Tổng user"}),(0,r.jsx)("div",{className:"mt-1 text-2xl font-bold text-text-main",children:et.totalUsers})]}),(0,r.jsxs)("div",{className:"rounded-2xl border border-border bg-surface p-4",children:[(0,r.jsx)("div",{className:"text-xs font-semibold uppercase text-text-muted",children:"Tổng OAuth connection"}),(0,r.jsx)("div",{className:"mt-1 text-2xl font-bold text-text-main",children:et.totalConnections})]}),(0,r.jsxs)("div",{className:"rounded-2xl border border-border bg-surface p-4",children:[(0,r.jsx)("div",{className:"text-xs font-semibold uppercase text-text-muted",children:"Cấp quyền, chưa connect"}),(0,r.jsx)("div",{className:"mt-1 text-2xl font-bold text-text-main",children:et.grantedNoConnection})]}),(0,r.jsxs)("div",{className:"rounded-2xl border border-border bg-surface p-4",children:[(0,r.jsx)("div",{className:"text-xs font-semibold uppercase text-text-muted",children:"C\xf2n connection, đ\xe3 thu hồi quyền"}),(0,r.jsx)("div",{className:"mt-1 text-2xl font-bold text-text-main",children:et.connectionNoGrant})]})]}),et.perProvider.some(e=>e.grantedUsers>0||e.connections>0)?(0,r.jsxs)("div",{className:"mb-4 rounded-2xl border border-border bg-surface p-4",children:[(0,r.jsx)("div",{className:"text-sm font-medium text-text-main",children:"Breakdown theo provider"}),(0,r.jsx)("div",{className:"mt-3 space-y-2",children:et.perProvider.map(({provider:e,grantedUsers:t,connections:s})=>(0,r.jsxs)("div",{className:"flex items-center justify-between gap-3 text-sm",children:[(0,r.jsxs)("div",{className:"flex items-center gap-2",children:[(0,r.jsx)(m.A,{src:`/providers/${e.id}.png`,alt:e.name,size:16,className:"max-h-[16px] max-w-[16px] rounded object-contain",fallbackText:e.id.slice(0,2).toUpperCase(),fallbackColor:e.color||"#64748b"}),(0,r.jsx)("span",{className:"text-text-main",children:e.name})]}),(0,r.jsxs)("div",{className:"flex items-center gap-3 text-xs text-text-muted",children:[(0,r.jsxs)("span",{children:[t," user được cấp quyền"]}),(0,r.jsxs)("span",{children:[s," connection"]})]})]},e.id))})]}):null,(0,r.jsx)("div",{className:"mb-4",children:(0,r.jsx)(o.pd,{label:"T\xecm t\xe0i khoản",value:z,onChange:e=>L(e.target.value),placeholder:"Nhập username hoặc email, vd: anh-tct hoặc anh-tct@fujinet.net",hint:H?"Đang t\xecm…":void 0})}),Y&&H&&0===ee.length?(0,r.jsx)("div",{className:"rounded-2xl border border-dashed border-border p-6 text-center text-sm text-text-muted",children:"Đang t\xecm t\xe0i khoản..."}):Y&&0===ee.length?(0,r.jsxs)("div",{className:"rounded-2xl border border-dashed border-border p-6 text-center text-sm text-text-muted",children:['Kh\xf4ng t\xecm thấy t\xe0i khoản n\xe0o khớp với "',z.trim(),'".']}):Y||0!==W.length?(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)("div",{className:"overflow-x-auto rounded-2xl border border-border",children:(0,r.jsxs)("table",{className:"min-w-full divide-y divide-border text-sm",children:[(0,r.jsx)("thead",{className:"bg-surface/80 text-left text-xs uppercase tracking-wide text-text-muted",children:(0,r.jsxs)("tr",{children:[(0,r.jsx)("th",{className:"px-4 py-3 font-medium",children:"User"}),t.map(e=>(0,r.jsx)("th",{className:"px-4 py-3 font-medium",children:e.name},e.id)),(0,r.jsx)("th",{className:"px-4 py-3 font-medium",children:"Limit / provider"}),(0,r.jsx)("th",{className:"px-4 py-3 text-right font-medium",children:"Actions"})]})}),(0,r.jsx)("tbody",{className:"divide-y divide-border bg-background",children:ee.map(e=>(0,r.jsxs)("tr",{className:"hover:bg-surface/50",children:[(0,r.jsxs)("td",{className:"px-4 py-4",children:[(0,r.jsx)("div",{className:"break-all font-mono text-text-main",children:e.userId}),e.displayName||e.email?(0,r.jsx)("div",{className:"mt-0.5 text-xs text-text-muted",children:[e.displayName,e.email].filter(Boolean).join(" \xb7 ")}):null]}),t.map(t=>{let s=!0===e.providerState[t.id],n=Number(e.connectionsByProvider?.[t.id]||0);return(0,r.jsx)("td",{className:"px-4 py-4",children:(0,r.jsxs)("div",{className:"flex items-center gap-1.5",children:[(0,r.jsx)(o.Ex,{variant:s?"success":"default",size:"sm",children:s?"ON":"OFF"}),n>0?(0,r.jsxs)("span",{className:"inline-flex items-center gap-0.5",title:`User đ\xe3 add ${n} ${t.name} account`,children:[(0,r.jsx)(m.A,{src:`/providers/${t.id}.png`,alt:t.name,size:16,className:"max-h-[16px] max-w-[16px] rounded object-contain",fallbackText:t.id.slice(0,2).toUpperCase(),fallbackColor:t.color||"#64748b"}),n>1?(0,r.jsxs)("span",{className:"text-[10px] font-semibold text-text-muted",children:["\xd7",n]}):null]}):null]})},t.id)}),(0,r.jsx)("td",{className:"px-4 py-4 text-xs",children:v[e.userId]>0?(0,r.jsxs)("span",{className:"inline-flex items-center gap-1",children:[(0,r.jsx)(o.Ex,{variant:"warning",size:"sm",children:"Override"}),(0,r.jsx)("span",{className:"font-mono",children:v[e.userId]})]}):(0,r.jsxs)("span",{className:"text-text-muted",children:["Global \xb7 ",N]})}),(0,r.jsx)("td",{className:"px-4 py-4",children:(0,r.jsxs)("div",{className:"flex flex-wrap justify-end gap-2",children:[(0,r.jsx)(o.$n,{variant:"outline",size:"sm",onClick:()=>(e=>{let s=h(e);p(s);let r=a[s]||{},n={};for(let e of t)n[e.id]=!0===r[e.id];b(n),G(""),I(""),Z(!0)})(e.userId),children:"Edit"}),e.enabledProviders.length>0||e.hasAnyConnection?(0,r.jsx)(o.$n,{variant:"danger",size:"sm",loading:E&&O===e.userId,onClick:()=>K(e.userId),children:"Revoke all & delete"}):null]})})]},e.userId))})]})}),Y&&B?(0,r.jsxs)("p",{className:"mt-2 text-xs text-text-muted",children:["Chỉ hiển thị ",ee.length," kết quả đầu, thu hẹp từ kh\xf3a t\xecm kiếm để ch\xednh x\xe1c hơn."]}):null]}):(0,r.jsx)("div",{className:"rounded-2xl border border-dashed border-border p-6 text-center text-sm text-text-muted",children:"Chưa c\xf3 user n\xe0o được cấp quyền OAuth provider. D\xf9ng \xf4 t\xecm kiếm ở tr\xean để cấp quyền cho một t\xe0i khoản."})]})]})]}),O?(0,r.jsx)(o.aF,{isOpen:!0,onClose:()=>K(""),title:"Thu hồi to\xe0n bộ quyền OAuth",size:"lg",busy:E,closeOnOverlay:!E,footer:(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(o.$n,{variant:"ghost",onClick:()=>K(""),disabled:E,children:"Hủy"}),(0,r.jsx)(o.$n,{variant:"danger",icon:"delete_forever",loading:E,onClick:()=>en(O),children:"Thu hồi v\xe0 x\xf3a to\xe0n bộ"})]}),children:(0,r.jsxs)("div",{className:"space-y-4",children:[(0,r.jsxs)("div",{className:"rounded-2xl border border-red-500/30 bg-red-500/10 p-4",children:[(0,r.jsx)("div",{className:"text-sm font-medium text-red-700 dark:text-red-300",children:"H\xe0nh động nguy hiểm, kh\xf4ng thể ho\xe0n t\xe1c"}),(0,r.jsx)("div",{className:"mt-1 break-all text-lg font-semibold text-text-main",children:O}),(0,r.jsx)("p",{className:"mt-2 text-sm text-text-muted",children:"To\xe0n bộ quyền OAuth provider v\xe0 connection/token local của user n\xe0y sẽ bị x\xf3a; gateway sẽ thử revoke upstream trước."})]}),(0,r.jsxs)("div",{className:"flex items-center justify-between rounded-xl border border-border bg-surface p-3 text-sm",children:[(0,r.jsx)("span",{className:"text-text-muted",children:"Connection t\xecm thấy"}),(0,r.jsx)(o.Ex,{variant:ei>0?"warning":"default",size:"sm",children:ei})]}),ea?(0,r.jsx)("div",{className:"flex flex-wrap gap-2",children:t.map(e=>{let t=Number(ea.connectionsByProvider?.[e.id]||0);return t>0?(0,r.jsxs)("span",{className:"inline-flex items-center gap-1.5 rounded-full border border-border bg-background px-2.5 py-1 text-xs text-text-muted",children:[(0,r.jsx)(m.A,{src:`/providers/${e.id}.png`,alt:e.name,size:16,className:"max-h-[16px] max-w-[16px] rounded object-contain",fallbackText:e.id.slice(0,2).toUpperCase()}),e.name," \xd7",t]},e.id):null})}):null]})}):null,F?(0,r.jsx)(o.aF,{isOpen:!0,onClose:()=>Z(!1),title:"Chỉnh quyền OAuth provider",size:"lg",busy:E,closeOnOverlay:!E,footer:(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(o.$n,{variant:"ghost",onClick:()=>Z(!1),disabled:E,children:"Hủy"}),(0,r.jsx)(o.$n,{onClick:es,loading:E,icon:"save",children:"Save permissions"})]}),children:(0,r.jsxs)("div",{className:"space-y-4",children:[(0,r.jsx)(o.pd,{label:"User ID / Email",value:u,disabled:!0}),(0,r.jsx)("div",{className:"grid gap-3 sm:grid-cols-2",children:t.map(e=>(0,r.jsx)("div",{className:"rounded-2xl border border-border bg-surface p-4",children:(0,r.jsx)(o.lM,{checked:!0===g[e.id],onChange:t=>b(s=>({...s,[e.id]:t})),label:e.name,description:g[e.id]?"User được ph\xe9p add account":"User chưa được cấp quyền"})},e.id))}),(0,r.jsxs)("div",{className:"rounded-2xl border border-border bg-surface p-4",children:[(0,r.jsx)("div",{className:"text-sm font-medium",children:"Per-user override — account / provider"}),(0,r.jsxs)("p",{className:"mt-1 text-xs text-text-muted",children:["Ghi đ\xe8 global cho ",(0,r.jsx)("span",{className:"font-mono",children:h(u)||"user đang chọn"}),". Để trống để d\xf9ng global (",N,")."]}),(0,r.jsx)("div",{className:"mt-3 max-w-xs",children:(0,r.jsx)(o.pd,{type:"number",min:1,value:f,onChange:e=>j(e.target.value),placeholder:`Để trống = d\xf9ng global (${N})`})})]})]})}):null]})}let p="/api/settings/smtp",g=[{value:"starttls",label:"STARTTLS (587)"},{value:"ssl",label:"SSL/TLS (465)"},{value:"none",label:"Kh\xf4ng m\xe3 ho\xe1 (25)"}],b={starttls:"587",ssl:"465",none:"25"};function f(e={}){return{host:e.host||"",port:e.port?String(e.port):"587",security:e.security||"starttls",username:e.username||"",password:"",fromEmail:e.fromEmail||"",fromName:e.fromName||"BlueRouter",allowInvalidCert:!0===e.allowInvalidCert,publicBaseUrl:e.publicBaseUrl||""}}function j(e){return{...e,port:Number.parseInt(e.port,10)||void 0}}function v({defaultTestRecipient:e=""}){let[t,s]=(0,n.useState)(null),[a,i]=(0,n.useState)(f()),[l,d]=(0,n.useState)(e),[c,m]=(0,n.useState)(!0),[x,h]=(0,n.useState)(!1),[u,y]=(0,n.useState)(!1),[N,w]=(0,n.useState)(""),[k,C]=(0,n.useState)(""),S=(0,n.useCallback)(e=>{s(e||null),i(f(e||{}))},[]),A=(0,n.useCallback)(async()=>{m(!0),w("");try{let e=await fetch(p,{cache:"no-store"}),t=await e.json().catch(()=>({}));if(!e.ok)throw Error(t.error||"Kh\xf4ng tải được SMTP settings");S(t.smtp)}catch(e){w(e?.message||"Kh\xf4ng tải được SMTP settings")}finally{m(!1)}},[S]);(0,n.useEffect)(()=>{A()},[A]),(0,n.useEffect)(()=>{!l&&e&&d(e)},[e,l]);let E=e=>t=>i(s=>({...s,[e]:t.target.value})),$=async()=>{h(!0),w(""),C("");try{let e=await fetch(p,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(j(a))}),t=await e.json().catch(()=>({}));if(!e.ok)throw Error(t.error||"Kh\xf4ng lưu được SMTP settings");S(t.smtp),C("Đ\xe3 lưu SMTP settings.")}catch(e){w(e?.message||"Kh\xf4ng lưu được SMTP settings")}finally{h(!1)}},P=async()=>{h(!0),w(""),C("");try{let e=await fetch(p,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({...j(a),password:"",clearPassword:!0})}),t=await e.json().catch(()=>({}));if(!e.ok)throw Error(t.error||"Kh\xf4ng xo\xe1 được password");S(t.smtp),C("Đ\xe3 xo\xe1 SMTP password.")}catch(e){w(e?.message||"Kh\xf4ng xo\xe1 được password")}finally{h(!1)}},T=async()=>{y(!0),w(""),C("");try{let e=await fetch(p,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({to:l.trim(),settings:j(a)})}),t=await e.json().catch(()=>({}));if(!e.ok)throw Error(t.error||"Gửi mail test thất bại");C(`Đ\xe3 gửi mail test tới ${l.trim()}.${t.response?` Server: ${t.response}`:""}`)}catch(e){w(e?.message||"Gửi mail test thất bại")}finally{y(!1)}};return(0,r.jsxs)(o.Zp,{className:"space-y-4",children:[(0,r.jsxs)("div",{className:"flex flex-col gap-2 md:flex-row md:items-center md:justify-between",children:[(0,r.jsxs)("div",{children:[(0,r.jsxs)("div",{className:"flex items-center gap-2",children:[(0,r.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"SMTP settings"}),t?(0,r.jsx)(o.Ex,{variant:t.configured?"success":"warning",size:"sm",children:t.configured?"Đ\xe3 cấu h\xecnh":"Chưa cấu h\xecnh"}):null]}),(0,r.jsx)("p",{className:"text-sm text-text-muted",children:"D\xf9ng để gửi email x\xe1c thực khi user add account ngo\xe0i domain được ph\xe9p. Password được m\xe3 ho\xe1 khi lưu."})]}),(0,r.jsx)(o.$n,{variant:"outline",size:"sm",onClick:A,loading:c,icon:"refresh",children:"Refresh"})]}),N?(0,r.jsx)("div",{className:"rounded-xl border border-red-500/30 bg-red-500/10 px-4 py-3 text-sm text-red-700 dark:text-red-300",children:N}):null,k?(0,r.jsx)("div",{className:"rounded-xl border border-green-500/30 bg-green-500/10 px-4 py-3 text-sm text-green-700 dark:text-green-300",children:k}):null,c?(0,r.jsx)("div",{className:"rounded-2xl border border-dashed border-border p-6 text-center text-sm text-text-muted",children:"Đang tải SMTP settings..."}):(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)("div",{className:"grid gap-3 md:grid-cols-[minmax(0,2fr)_minmax(0,1fr)_minmax(0,1fr)]",children:[(0,r.jsx)(o.pd,{label:"SMTP host",value:a.host,onChange:E("host"),placeholder:"vd: smtp.fujinet.net"}),(0,r.jsx)(o.l6,{label:"Bảo mật",value:a.security,onChange:e=>{let t=e.target.value;i(e=>({...e,security:t,port:Object.values(b).includes(e.port)?b[t]:e.port}))},options:g}),(0,r.jsx)(o.pd,{label:"Port",type:"number",min:1,max:65535,value:a.port,onChange:E("port")})]}),(0,r.jsxs)("div",{className:"grid gap-3 md:grid-cols-2",children:[(0,r.jsx)(o.pd,{label:"Username",value:a.username,onChange:E("username"),placeholder:"Để trống nếu SMTP kh\xf4ng cần auth",autoComplete:"off"}),(0,r.jsx)(o.pd,{label:"Password",type:"password",value:a.password,onChange:E("password"),placeholder:t?.hasPassword?"•••••••• (đ\xe3 lưu — để trống để giữ nguy\xean)":"Nhập password",autoComplete:"new-password",hint:t?.hasPassword?"Đ\xe3 c\xf3 password được lưu.":void 0})]}),(0,r.jsxs)("div",{className:"grid gap-3 md:grid-cols-3",children:[(0,r.jsx)(o.pd,{label:"From email",value:a.fromEmail,onChange:E("fromEmail"),placeholder:"vd: bluerouter@fujinet.net"}),(0,r.jsx)(o.pd,{label:"From name",value:a.fromName,onChange:E("fromName"),placeholder:"BlueRouter"}),(0,r.jsx)(o.pd,{label:"Public URL (hostname trong link)",value:a.publicBaseUrl,onChange:E("publicBaseUrl"),placeholder:"vd: https://router.fujinet.net",hint:a.publicBaseUrl.trim()?void 0:"Để trống = lấy BASE_URL / host của request."})]}),(0,r.jsx)("div",{className:"rounded-2xl border border-border bg-surface p-4",children:(0,r.jsx)(o.lM,{checked:a.allowInvalidCert,onChange:e=>i(t=>({...t,allowInvalidCert:e})),label:"Bỏ qua kiểm tra chứng chỉ TLS",description:"Chỉ bật khi SMTP nội bộ d\xf9ng chứng chỉ self-signed."})}),(0,r.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,r.jsx)(o.$n,{onClick:$,loading:x,disabled:x||u,icon:"save",children:"Lưu SMTP"}),t?.hasPassword?(0,r.jsx)(o.$n,{variant:"ghost",onClick:P,disabled:x||u,icon:"key_off",children:"Xo\xe1 password"}):null]}),(0,r.jsxs)("div",{className:"border-t border-border pt-4",children:[(0,r.jsx)("div",{className:"text-sm font-medium text-text-main",children:"Gửi mail test"}),(0,r.jsx)("p",{className:"mt-1 text-xs text-text-muted",children:"Test với th\xf4ng tin đang nhập ở tr\xean (chưa cần lưu)."}),(0,r.jsxs)("div",{className:"mt-3 flex flex-col gap-2 sm:flex-row sm:items-end",children:[(0,r.jsx)(o.pd,{value:l,onChange:e=>d(e.target.value),onKeyDown:e=>{"Enter"===e.key&&l.trim()&&T()},placeholder:"Email nhận test",className:"sm:w-96"}),(0,r.jsx)(o.$n,{variant:"outline",onClick:T,loading:u,disabled:u||x||!l.trim()||!a.host.trim(),icon:"send",children:"Gửi test"})]})]})]})]})}let y="/api/personal-cloud-providers/account-policy",N={domain:"Domain",email:"Allowlist","not-enforced":"Kh\xf4ng \xe1p dụng",disabled:"Policy tắt","missing-email":"Thiếu email","github-account":"GitHub allowlist","missing-identity":"Thiếu GitHub id","not-listed":"Chưa được ph\xe9p"};function w(e){return String(e||"").split(/[\s,;]+/).map(e=>e.trim().toLowerCase()).filter(Boolean)}function k(e){return`${e.email}|${e.ownerUser||""}`}function C(e){return`${e.githubUserId}|${e.ownerUser||""}`}function S(e){if(!e)return"";let t=new Date(e);return Number.isNaN(t.getTime())?"":t.toLocaleString("vi-VN")}function A(){let{isAdmin:e}=(0,i.s)(),[t,s]=(0,n.useState)(null),[a,l]=(0,n.useState)([]),[d,c]=(0,n.useState)([]),[x,h]=(0,n.useState)(0),[u,p]=(0,n.useState)(!0),[g,b]=(0,n.useState)(!1),[f,j]=(0,n.useState)(""),[A,E]=(0,n.useState)(""),[$,P]=(0,n.useState)(""),[T,O]=(0,n.useState)(""),[K,U]=(0,n.useState)(""),[G,q]=(0,n.useState)(""),[I,z]=(0,n.useState)(""),[L,D]=(0,n.useState)(""),[M,H]=(0,n.useState)(""),[_,B]=(0,n.useState)(""),[R,F]=(0,n.useState)(!1),Z=(0,n.useCallback)(e=>{s(e.policy||null),l(Array.isArray(e.providers)?e.providers:[]),c(Array.isArray(e.connections)?e.connections:[]),h(Number(e.pendingImportCount)||0)},[]),J=(0,n.useCallback)(async()=>{if(e){p(!0),j("");try{let e=await fetch(y,{cache:"no-store"}),t=await e.json().catch(()=>({}));if(!e.ok)throw Error(t.error||"Kh\xf4ng tải được account policy");Z(t)}catch(e){j(e?.message||"Kh\xf4ng tải được account policy")}finally{p(!1)}}},[Z,e]);(0,n.useEffect)(()=>{J()},[J]);let X=async(e,t,s)=>{b(!0),j(""),E("");try{let r=await fetch(y,{method:e,headers:{"Content-Type":"application/json"},body:JSON.stringify(t)}),n=await r.json().catch(()=>({}));if(!r.ok)throw Error(n.error||"Kh\xf4ng lưu được account policy");return Z(n),E("function"==typeof s?s(n):s),!0}catch(e){return j(e?.message||"Kh\xf4ng lưu được account policy"),!1}finally{b(!1)}},V=(e,s)=>X("PUT",{enabled:t.enabled,allowedDomains:t.allowedDomains,allowedEmails:t.allowedEmails,allowedGithubAccounts:t.allowedGithubAccounts||[],enforcedProviders:Object.fromEntries(a.map(e=>[e.id,e.enforced])),...e},s),Q=async()=>{let e=w($).map(e=>e.replace(/^@+/,"")),s=e.filter(e=>!t.allowedDomains.includes(e));0===s.length?j(e.length?"Domain đ\xe3 c\xf3 trong danh s\xe1ch.":"Nhập domain cần th\xeam, vd: fujinet.net"):await V({allowedDomains:[...t.allowedDomains,...s]},`Đ\xe3 th\xeam domain: ${s.join(", ")}.`)&&P("")},W=async()=>{let e=w(T),s=G.trim().toLowerCase(),r=new Set(t.allowedEmails.map(k)),n=Array.from(new Set(e)).filter(e=>!r.has(k({email:e,ownerUser:s})));if(0===n.length)return void j(e.length?"Email đ\xe3 c\xf3 trong danh s\xe1ch.":"Nhập email cần cho ph\xe9p.");let a=K.trim();await V({allowedEmails:[...t.allowedEmails,...n.map(e=>({email:e,note:a,ownerUser:s}))]},`Đ\xe3 cho ph\xe9p ${n.length} email${s?` cho user ${s}`:" cho mọi user"}.`)&&(O(""),U(""),q(""))},Y=(e,s)=>V({allowedEmails:t.allowedEmails.map(t=>k(t)===k(e)?{...t,status:s,verifiedAt:"verified"===s?new Date().toISOString():null}:t)},"verified"===s?`Đ\xe3 đ\xe1nh dấu ${e.email} l\xe0 đ\xe3 x\xe1c thực.`:`Đ\xe3 chuyển ${e.email} sang chưa x\xe1c thực — user cần x\xe1c thực lại qua mail.`),ee=async()=>{let e=Array.from(new Set(w(I).map(e=>e.replace(/^@+/,""))));if(0===e.length)return void j("Nhập GitHub login hoặc id cần cho ph\xe9p.");let s=L.trim().toLowerCase(),r=M.trim();await V({allowedGithubAccounts:[...t.allowedGithubAccounts||[],...e.map(e=>({login:e,ownerUser:s,note:r}))]},`Đ\xe3 cho ph\xe9p ${e.length} GitHub account${s?` cho user ${s}`:" cho mọi user"}.`)&&(z(""),D(""),H(""))},et=(0,n.useMemo)(()=>{let e=_.trim().toLowerCase(),s=t?.allowedEmails||[];return e?s.filter(t=>[t.email,t.note,t.addedBy,t.ownerUser].some(t=>String(t||"").toLowerCase().includes(e))):s},[_,t]),es=(0,n.useMemo)(()=>d.filter(e=>!e.allowed),[d]),er=R?d:es,en=(0,n.useMemo)(()=>new Map(a.map(e=>[e.id,e])),[a]);if(!e)return null;let ea=(e,t=16)=>{let s=en.get(e)||{id:e,name:e};return(0,r.jsx)(m.A,{src:`/providers/${s.id}.png`,alt:s.name,size:t,className:t>16?"max-h-[20px] max-w-[20px] rounded object-contain":"max-h-[16px] max-w-[16px] rounded object-contain",fallbackText:String(s.id).slice(0,2).toUpperCase(),fallbackColor:s.color||"#64748b"})};return(0,r.jsxs)("div",{className:"space-y-5",children:[(0,r.jsxs)("div",{className:"rounded-2xl border border-border bg-surface/50 p-4",children:[(0,r.jsx)("h1",{className:"text-xl font-semibold text-text-main",children:"Admin: Account allowlist"}),(0,r.jsx)("p",{className:"mt-1 text-sm text-text-muted",children:"Giới hạn account upstream n\xe0o được add v\xe0o Personal OAuth. Account c\xf3 email thuộc domain được ph\xe9p lu\xf4n được add (khi user đ\xe3 được cấp quyền provider); account kh\xe1c phải c\xf3 trong danh s\xe1ch email do admin thiết lập."})]}),f?(0,r.jsx)("div",{className:"rounded-xl border border-red-500/30 bg-red-500/10 px-4 py-3 text-sm text-red-700 dark:text-red-300",children:f}):null,A?(0,r.jsx)("div",{className:"rounded-xl border border-green-500/30 bg-green-500/10 px-4 py-3 text-sm text-green-700 dark:text-green-300",children:A}):null,u||!t?(0,r.jsx)("div",{className:"rounded-2xl border border-dashed border-border p-6 text-center text-sm text-text-muted",children:"Đang tải account policy..."}):(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)(o.Zp,{className:"space-y-4",children:[(0,r.jsxs)("div",{className:"flex flex-col gap-2 md:flex-row md:items-center md:justify-between",children:[(0,r.jsxs)("div",{children:[(0,r.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"Account policy"}),(0,r.jsx)("p",{className:"text-sm text-text-muted",children:"\xc1p dụng khi user add account mới hoặc reauth. Connection đang chạy kh\xf4ng bị ngắt khi đổi policy."})]}),(0,r.jsx)(o.$n,{variant:"outline",size:"sm",onClick:J,loading:u,icon:"refresh",children:"Refresh"})]}),(0,r.jsx)("div",{className:"rounded-2xl border border-border bg-surface p-4",children:(0,r.jsx)(o.lM,{checked:t.enabled,disabled:g,onChange:e=>V({enabled:e},e?"Đ\xe3 bật account policy.":"Đ\xe3 tắt account policy — mọi account đều được add."),label:"Bật kiểm tra account email",description:t.enabled?"Chỉ domain / email được ph\xe9p mới add được":"Đang tắt: mọi account đều được add"})}),(0,r.jsxs)("div",{className:"grid grid-cols-1 gap-3 sm:grid-cols-2 md:grid-cols-4",children:[(0,r.jsxs)("div",{className:"rounded-2xl border border-border bg-surface p-4",children:[(0,r.jsx)("div",{className:"text-xs font-semibold uppercase text-text-muted",children:"Domain được ph\xe9p"}),(0,r.jsx)("div",{className:"mt-1 text-2xl font-bold text-text-main",children:t.allowedDomains.length})]}),(0,r.jsxs)("div",{className:"rounded-2xl border border-border bg-surface p-4",children:[(0,r.jsx)("div",{className:"text-xs font-semibold uppercase text-text-muted",children:"Email / GitHub ngoại lệ"}),(0,r.jsx)("div",{className:"mt-1 text-2xl font-bold text-text-main",children:t.allowedEmails.length+(t.allowedGithubAccounts||[]).length})]}),(0,r.jsxs)("div",{className:"rounded-2xl border border-border bg-surface p-4",children:[(0,r.jsx)("div",{className:"text-xs font-semibold uppercase text-text-muted",children:"Connection hiện c\xf3"}),(0,r.jsx)("div",{className:"mt-1 text-2xl font-bold text-text-main",children:d.length})]}),(0,r.jsxs)("div",{className:"rounded-2xl border border-border bg-surface p-4",children:[(0,r.jsx)("div",{className:"text-xs font-semibold uppercase text-text-muted",children:"Sẽ bị chặn khi reauth"}),(0,r.jsx)("div",{className:`mt-1 text-2xl font-bold ${es.length>0?"text-red-600 dark:text-red-400":"text-text-main"}`,children:es.length})]})]})]}),(0,r.jsxs)(o.Zp,{className:"space-y-4",children:[(0,r.jsxs)("div",{children:[(0,r.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"Domain được ph\xe9p"}),(0,r.jsx)("p",{className:"text-sm text-text-muted",children:"Account c\xf3 email thuộc c\xe1c domain n\xe0y lu\xf4n được add. Chỉ khớp ch\xednh x\xe1c domain (kh\xf4ng gồm subdomain)."})]}),(0,r.jsx)("div",{className:"flex flex-wrap gap-2",children:0===t.allowedDomains.length?(0,r.jsx)("span",{className:"text-sm text-text-muted",children:"Chưa c\xf3 domain n\xe0o — mọi account đều phải nằm trong danh s\xe1ch email."}):t.allowedDomains.map(e=>(0,r.jsxs)("span",{className:"inline-flex items-center gap-1.5 rounded-full border border-border bg-background px-3 py-1 text-sm text-text-main",children:[(0,r.jsxs)("span",{className:"font-mono",children:["@",e]}),(0,r.jsx)("button",{type:"button",className:"material-symbols-outlined text-[16px] text-text-muted hover:text-red-500 disabled:opacity-50",onClick:()=>V({allowedDomains:t.allowedDomains.filter(t=>t!==e)},`Đ\xe3 x\xf3a domain ${e}.`),disabled:g,"aria-label":`X\xf3a domain ${e}`,title:"X\xf3a domain",children:"close"})]},e))}),(0,r.jsxs)("div",{className:"flex flex-col gap-2 sm:flex-row sm:items-end",children:[(0,r.jsx)(o.pd,{label:"Th\xeam domain",value:$,onChange:e=>P(e.target.value),onKeyDown:e=>{"Enter"===e.key&&Q()},placeholder:"vd: fujinet.net, partner.com",className:"sm:w-96"}),(0,r.jsx)(o.$n,{onClick:Q,loading:g,disabled:g||!$.trim(),icon:"add",children:"Th\xeam"})]})]}),(0,r.jsxs)(o.Zp,{className:"space-y-4",children:[(0,r.jsxs)("div",{children:[(0,r.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"Provider \xe1p dụng"}),(0,r.jsx)("p",{className:"text-sm text-text-muted",children:"Provider tắt ở đ\xe2y sẽ kh\xf4ng kiểm tra. Kiro lấy email qua API usage của Kiro. GitHub kh\xf4ng trả email n\xean được kiểm tra theo danh s\xe1ch GitHub account b\xean dưới, mặc định tắt."})]}),(0,r.jsx)("div",{className:"grid gap-3 sm:grid-cols-2 lg:grid-cols-3",children:a.map(e=>(0,r.jsxs)("div",{className:"flex items-start gap-3 rounded-2xl border border-border bg-surface p-4",children:[(0,r.jsx)("div",{className:"pt-0.5",children:ea(e.id,20)}),(0,r.jsx)(o.lM,{checked:e.enforced,disabled:g||!t.enabled,onChange:t=>{let s;return s=e.id,V({enforcedProviders:Object.fromEntries(a.map(e=>[e.id,e.id===s?t:e.enforced]))},`${t?"Đ\xe3 \xe1p dụng":"Đ\xe3 bỏ \xe1p dụng"} policy cho ${a.find(e=>e.id===s)?.name||s}.`)},label:e.name,description:e.enforced?"Kiểm tra domain / email":"Kh\xf4ng kiểm tra"})]},e.id))})]}),(0,r.jsxs)(o.Zp,{className:"space-y-4",children:[(0,r.jsxs)("div",{className:"flex flex-col gap-2 md:flex-row md:items-start md:justify-between",children:[(0,r.jsxs)("div",{children:[(0,r.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"Email được ph\xe9p (ngoại lệ)"}),(0,r.jsx)("p",{className:"text-sm text-text-muted",children:'Account ngo\xe0i domain được ph\xe9p phải c\xf3 trong danh s\xe1ch n\xe0y v\xe0 ở trạng th\xe1i đ\xe3 x\xe1c thực — email "Chưa x\xe1c thực" vẫn được giữ trong danh s\xe1ch nhưng user phải bấm link trong mail mới d\xf9ng được. Email gắn với một user chỉ user đ\xf3 được add; để trống User để cho mọi user. User cũng c\xf3 thể tự th\xeam email của m\xecnh bằng c\xe1ch x\xe1c thực qua mail.'})]}),(0,r.jsxs)("div",{className:"flex flex-wrap gap-2",children:[t.allowedEmails.some(e=>"unverified"!==e.status)?(0,r.jsx)(o.$n,{variant:"ghost",size:"sm",icon:"unpublished",onClick:()=>V({allowedEmails:t.allowedEmails.map(e=>({...e,status:"unverified",verifiedAt:null}))},`Đ\xe3 chuyển ${t.allowedEmails.length} email sang chưa x\xe1c thực.`),loading:g,disabled:g,children:"Tất cả → chưa x\xe1c thực"}):null,(0,r.jsxs)(o.$n,{variant:"outline",size:"sm",icon:"download",onClick:()=>X("POST",{action:"import-existing"},e=>e.importedCount>0?`Đ\xe3 import ${e.importedCount} email từ connection hiện c\xf3.`:"Kh\xf4ng c\xf3 email mới cần import."),loading:g,disabled:g,children:["Import từ connection hiện c\xf3",x>0?` (${x})`:""]})]})]}),(0,r.jsxs)("div",{className:"grid gap-2 md:grid-cols-[minmax(0,2fr)_minmax(0,1fr)_minmax(0,1fr)_auto] md:items-end",children:[(0,r.jsx)(o.pd,{label:"Email",value:T,onChange:e=>O(e.target.value),onKeyDown:e=>{"Enter"===e.key&&W()},placeholder:"vd: someone@gmail.com, other@partner.com"}),(0,r.jsx)(o.pd,{label:"Chỉ cho user (tuỳ chọn)",value:G,onChange:e=>q(e.target.value),onKeyDown:e=>{"Enter"===e.key&&W()},placeholder:"vd: anh-tct — trống = mọi user"}),(0,r.jsx)(o.pd,{label:"Ghi ch\xfa",value:K,onChange:e=>U(e.target.value),onKeyDown:e=>{"Enter"===e.key&&W()},placeholder:"vd: account c\xe1 nh\xe2n của anh-tct"}),(0,r.jsx)(o.$n,{onClick:W,loading:g,disabled:g||!T.trim(),icon:"person_add",children:"Cho ph\xe9p"})]}),t.allowedEmails.length>0?(0,r.jsx)(o.pd,{value:_,onChange:e=>B(e.target.value),placeholder:"Lọc theo email, ghi ch\xfa, người th\xeam..."}):null,0===t.allowedEmails.length?(0,r.jsx)("div",{className:"rounded-2xl border border-dashed border-border p-6 text-center text-sm text-text-muted",children:"Chưa c\xf3 email ngoại lệ n\xe0o."}):0===et.length?(0,r.jsxs)("div",{className:"rounded-2xl border border-dashed border-border p-6 text-center text-sm text-text-muted",children:['Kh\xf4ng c\xf3 email n\xe0o khớp với "',_.trim(),'".']}):(0,r.jsx)("div",{className:"overflow-x-auto rounded-2xl border border-border",children:(0,r.jsxs)("table",{className:"min-w-full divide-y divide-border text-sm",children:[(0,r.jsx)("thead",{className:"bg-surface/80 text-left text-xs uppercase tracking-wide text-text-muted",children:(0,r.jsxs)("tr",{children:[(0,r.jsx)("th",{className:"px-4 py-3 font-medium",children:"Email"}),(0,r.jsx)("th",{className:"px-4 py-3 font-medium",children:"User"}),(0,r.jsx)("th",{className:"px-4 py-3 font-medium",children:"Ghi ch\xfa"}),(0,r.jsx)("th",{className:"px-4 py-3 font-medium",children:"Th\xeam bởi"}),(0,r.jsx)("th",{className:"px-4 py-3 text-right font-medium",children:"Actions"})]})}),(0,r.jsx)("tbody",{className:"divide-y divide-border bg-background",children:et.map(e=>(0,r.jsxs)("tr",{className:"hover:bg-surface/50",children:[(0,r.jsxs)("td",{className:"px-4 py-3 break-all font-mono text-text-main",children:[e.email,"unverified"===e.status?(0,r.jsx)(o.Ex,{variant:"warning",size:"sm",className:"ml-2",children:"Chưa x\xe1c thực"}):(0,r.jsx)(o.Ex,{variant:"success",size:"sm",className:"ml-2",children:e.verifiedAt?"Đ\xe3 x\xe1c thực":"Được ph\xe9p"})]}),(0,r.jsx)("td",{className:"px-4 py-3 text-xs",children:e.ownerUser?(0,r.jsx)("span",{className:"font-mono text-text-main",children:e.ownerUser}):(0,r.jsx)(o.Ex,{variant:"info",size:"sm",children:"Mọi user"})}),(0,r.jsx)("td",{className:"px-4 py-3 text-xs text-text-muted",children:e.note||"—"}),(0,r.jsxs)("td",{className:"px-4 py-3 text-xs text-text-muted",children:[(0,r.jsx)("div",{children:e.addedBy||"—"}),e.addedAt?(0,r.jsx)("div",{className:"mt-0.5",children:S(e.addedAt)}):null]}),(0,r.jsx)("td",{className:"px-4 py-3",children:(0,r.jsx)("div",{className:"flex justify-end",children:(0,r.jsxs)("div",{className:"flex flex-wrap justify-end gap-2",children:["unverified"===e.status?(0,r.jsx)(o.$n,{variant:"outline",size:"sm",icon:"verified",onClick:()=>Y(e,"verified"),disabled:g,children:"Đ\xe1nh dấu đ\xe3 x\xe1c thực"}):(0,r.jsx)(o.$n,{variant:"ghost",size:"sm",icon:"unpublished",onClick:()=>Y(e,"unverified"),disabled:g,children:"Chuyển chưa x\xe1c thực"}),(0,r.jsx)(o.$n,{variant:"outline",size:"sm",icon:"delete",onClick:()=>V({allowedEmails:t.allowedEmails.filter(t=>k(t)!==k(e))},`Đ\xe3 x\xf3a ${e.email}${e.ownerUser?` (${e.ownerUser})`:""} khỏi danh s\xe1ch.`),disabled:g,children:"X\xf3a"})]})})})]},k(e)))})]})})]}),(0,r.jsxs)(o.Zp,{className:"space-y-4",children:[(0,r.jsxs)("div",{children:[(0,r.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"GitHub account được ph\xe9p"}),(0,r.jsx)("p",{className:"text-sm text-text-muted",children:"GitHub Copilot kh\xf4ng cho đọc email n\xean account GitHub được so theo id (kh\xf4ng đổi kể cả khi user đổi t\xean). Chỉ c\xf3 hiệu lực khi GitHub được bật ở mục Provider \xe1p dụng. Nhập login hoặc id, c\xe1ch nhau bởi dấu phẩy."})]}),(0,r.jsxs)("div",{className:"grid gap-2 md:grid-cols-[minmax(0,2fr)_minmax(0,1fr)_minmax(0,1fr)_auto] md:items-end",children:[(0,r.jsx)(o.pd,{label:"GitHub login / id",value:I,onChange:e=>z(e.target.value),onKeyDown:e=>{"Enter"===e.key&&ee()},placeholder:"vd: octocat, 34310938"}),(0,r.jsx)(o.pd,{label:"Chỉ cho user (tuỳ chọn)",value:L,onChange:e=>D(e.target.value),onKeyDown:e=>{"Enter"===e.key&&ee()},placeholder:"trống = mọi user"}),(0,r.jsx)(o.pd,{label:"Ghi ch\xfa",value:M,onChange:e=>H(e.target.value),onKeyDown:e=>{"Enter"===e.key&&ee()},placeholder:"tuỳ chọn"}),(0,r.jsx)(o.$n,{onClick:ee,loading:g,disabled:g||!I.trim(),icon:"person_add",children:"Cho ph\xe9p"})]}),0===(t.allowedGithubAccounts||[]).length?(0,r.jsx)("div",{className:"rounded-2xl border border-dashed border-border p-6 text-center text-sm text-text-muted",children:"Chưa c\xf3 GitHub account n\xe0o."}):(0,r.jsx)("div",{className:"overflow-x-auto rounded-2xl border border-border",children:(0,r.jsxs)("table",{className:"min-w-full divide-y divide-border text-sm",children:[(0,r.jsx)("thead",{className:"bg-surface/80 text-left text-xs uppercase tracking-wide text-text-muted",children:(0,r.jsxs)("tr",{children:[(0,r.jsx)("th",{className:"px-4 py-3 font-medium",children:"GitHub account"}),(0,r.jsx)("th",{className:"px-4 py-3 font-medium",children:"User"}),(0,r.jsx)("th",{className:"px-4 py-3 font-medium",children:"Ghi ch\xfa"}),(0,r.jsx)("th",{className:"px-4 py-3 font-medium",children:"Th\xeam bởi"}),(0,r.jsx)("th",{className:"px-4 py-3 text-right font-medium",children:"Actions"})]})}),(0,r.jsx)("tbody",{className:"divide-y divide-border bg-background",children:t.allowedGithubAccounts.map(e=>(0,r.jsxs)("tr",{className:"hover:bg-surface/50",children:[(0,r.jsxs)("td",{className:"px-4 py-3",children:[(0,r.jsxs)("div",{className:"flex items-center gap-2",children:[ea("github"),(0,r.jsx)("span",{className:"font-mono text-text-main",children:e.login||"—"})]}),(0,r.jsxs)("div",{className:"mt-0.5 font-mono text-xs text-text-muted",children:["id ",e.githubUserId]})]}),(0,r.jsx)("td",{className:"px-4 py-3 text-xs",children:e.ownerUser?(0,r.jsx)("span",{className:"font-mono text-text-main",children:e.ownerUser}):(0,r.jsx)(o.Ex,{variant:"info",size:"sm",children:"Mọi user"})}),(0,r.jsx)("td",{className:"px-4 py-3 text-xs text-text-muted",children:e.note||"—"}),(0,r.jsxs)("td",{className:"px-4 py-3 text-xs text-text-muted",children:[(0,r.jsx)("div",{children:e.addedBy||"—"}),e.addedAt?(0,r.jsx)("div",{className:"mt-0.5",children:S(e.addedAt)}):null]}),(0,r.jsx)("td",{className:"px-4 py-3",children:(0,r.jsx)("div",{className:"flex justify-end",children:(0,r.jsx)(o.$n,{variant:"outline",size:"sm",icon:"delete",onClick:()=>V({allowedGithubAccounts:(t.allowedGithubAccounts||[]).filter(t=>C(t)!==C(e))},`Đ\xe3 x\xf3a GitHub account ${e.login||e.githubUserId} khỏi danh s\xe1ch.`),disabled:g,children:"X\xf3a"})})})]},C(e)))})]})})]}),(0,r.jsx)(v,{}),(0,r.jsxs)(o.Zp,{className:"space-y-4",children:[(0,r.jsxs)("div",{className:"flex flex-col gap-2 md:flex-row md:items-center md:justify-between",children:[(0,r.jsxs)("div",{children:[(0,r.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"Kiểm tra connection hiện c\xf3"}),(0,r.jsx)("p",{className:"text-sm text-text-muted",children:"Kết quả nếu c\xe1c personal connection hiện c\xf3 được add / reauth lại với policy hiện tại."})]}),(0,r.jsx)(o.lM,{size:"sm",checked:R,onChange:F,label:"Hiện tất cả"})]}),0===er.length?(0,r.jsx)("div",{className:"rounded-2xl border border-dashed border-border p-6 text-center text-sm text-text-muted",children:R?"Chưa c\xf3 personal connection n\xe0o.":"Kh\xf4ng c\xf3 connection n\xe0o bị chặn bởi policy hiện tại."}):(0,r.jsx)("div",{className:"overflow-x-auto rounded-2xl border border-border",children:(0,r.jsxs)("table",{className:"min-w-full divide-y divide-border text-sm",children:[(0,r.jsx)("thead",{className:"bg-surface/80 text-left text-xs uppercase tracking-wide text-text-muted",children:(0,r.jsxs)("tr",{children:[(0,r.jsx)("th",{className:"px-4 py-3 font-medium",children:"User"}),(0,r.jsx)("th",{className:"px-4 py-3 font-medium",children:"Provider"}),(0,r.jsx)("th",{className:"px-4 py-3 font-medium",children:"Account"}),(0,r.jsx)("th",{className:"px-4 py-3 font-medium",children:"Kết quả"})]})}),(0,r.jsx)("tbody",{className:"divide-y divide-border bg-background",children:er.map(e=>(0,r.jsxs)("tr",{className:"hover:bg-surface/50",children:[(0,r.jsx)("td",{className:"px-4 py-3 break-all font-mono text-text-main",children:e.ownerUser||"—"}),(0,r.jsx)("td",{className:"px-4 py-3",children:(0,r.jsxs)("div",{className:"flex items-center gap-2",children:[ea(e.provider),(0,r.jsx)("span",{className:"text-text-main",children:en.get(e.provider)?.name||e.provider}),e.isActive?null:(0,r.jsx)(o.Ex,{size:"sm",children:"Inactive"})]})}),(0,r.jsx)("td",{className:"px-4 py-3 break-all font-mono text-xs text-text-muted",children:e.email||(e.githubLogin?`github: ${e.githubLogin}`:"—")}),(0,r.jsx)("td",{className:"px-4 py-3",children:(0,r.jsx)(o.Ex,{variant:e.allowed?"success":"error",size:"sm",children:N[e.reason]||e.reason})})]},e.id))})]})})]})]})]})}var E=s(43503),$=s(78867),P=s(67673),T=s(14796),O=s.n(T),K=s(36236);let U="/api/personal-cloud-providers/account-emails",G="/api/personal-cloud-providers/pending-accounts",q={ok:e=>({type:"success",text:`Đ\xe3 x\xe1c thực ${e||"email"}. Quay lại m\xe0n h\xecnh add account v\xe0 bấm "T\xf4i đ\xe3 x\xe1c thực" (hoặc bấm ở mục "Account đang chờ x\xe1c thực" b\xean dưới) để ho\xe0n tất.`}),expired:e=>({type:"error",text:`Link x\xe1c thực${e?` cho ${e}`:""} đ\xe3 hết hạn. Gửi lại email x\xe1c thực b\xean dưới.`}),invalid:()=>({type:"error",text:"Link x\xe1c thực kh\xf4ng hợp lệ hoặc đ\xe3 được d\xf9ng."}),error:()=>({type:"error",text:"Kh\xf4ng x\xe1c thực được email, vui l\xf2ng thử lại."})};function I(e){if(!e)return"";let t=new Date(e);return Number.isNaN(t.getTime())?"":t.toLocaleString("vi-VN")}function z(){let[e,t]=(0,n.useState)(null),[s,a]=(0,n.useState)([]),[i,l]=(0,n.useState)(!0),[d,c]=(0,n.useState)(!1),[m,x]=(0,n.useState)(""),[h,u]=(0,n.useState)(""),p=(0,n.useCallback)(async()=>{try{let e=await fetch(G,{cache:"no-store"}),t=await e.json().catch(()=>({}));e.ok&&a(Array.isArray(t.pending)?t.pending:[])}catch{}},[]),g=(0,n.useCallback)(async()=>{l(!0);try{let e=await fetch(U,{cache:"no-store"}),s=await e.json().catch(()=>({}));if(!e.ok)throw Error(s.error||"Kh\xf4ng tải được danh s\xe1ch email");t(s),p()}catch(e){x(e?.message||"Kh\xf4ng tải được danh s\xe1ch email")}finally{l(!1)}},[p]);(0,n.useEffect)(()=>{g()},[g]);let b=async e=>{x("");try{let t=await fetch(`${G}?id=${encodeURIComponent(e)}`,{method:"DELETE"}),s=await t.json().catch(()=>({}));if(!t.ok)throw Error(s.error||"Kh\xf4ng huỷ được");a(Array.isArray(s.pending)?s.pending:[])}catch(e){x(e?.message||"Kh\xf4ng huỷ được")}},f=e=>{u(`Đ\xe3 add account ${e?.email||""} v\xe0o Personal OAuth.`),setTimeout(()=>window.location.reload(),800)};(0,n.useEffect)(()=>{let e=new URL(window.location.href),t=e.searchParams.get("emailVerify");if(!t)return;let s=(q[t]||q.error)(e.searchParams.get("email")||"");"success"===s.type?u(s.text):x(s.text),e.searchParams.delete("emailVerify"),e.searchParams.delete("email"),window.history.replaceState(null,"",`${e.pathname}${e.search}${e.hash}`)},[]);let j=async(e,{query:s="",body:r}={},n)=>{c(!0),x(""),u("");try{let a=await fetch(`${U}${s}`,{method:e,headers:r?{"Content-Type":"application/json"}:void 0,body:r?JSON.stringify(r):void 0}),i=await a.json().catch(()=>({}));if(!a.ok)throw Error(i.error||"Thao t\xe1c thất bại");return t(i),u(n),!0}catch(e){return x(e?.message||"Thao t\xe1c thất bại"),!1}finally{c(!1)}},v=async e=>{let t=String(e||"").trim().toLowerCase();t&&await j("POST",{body:{email:t}},`Đ\xe3 gửi email x\xe1c thực tới ${t}. Mở hộp thư v\xe0 bấm link để ho\xe0n tất.`)},y=e=>j("DELETE",{query:`?email=${encodeURIComponent(e)}`},`Đ\xe3 xo\xe1 ${e}.`);if(i&&!e||!e||!e.policyEnabled)return null;let N=e.allowedDomains||[],w=e.verified||[],k=e.pending||[],C=(e.unverified||[]).filter(e=>!k.some(t=>t.email===e.email));return m||h||0!==s.length||0!==w.length||0!==k.length||0!==C.length?(0,r.jsxs)(o.Zp,{className:"mb-5 space-y-4",children:[(0,r.jsxs)("div",{children:[(0,r.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"Email account ngo\xe0i domain"}),(0,r.jsxs)("p",{className:"text-sm text-text-muted",children:[N.length>0?(0,r.jsxs)(r.Fragment,{children:["Account c\xf3 email ",(0,r.jsx)("span",{className:"font-mono",children:N.map(e=>`@${e}`).join(", ")})," được add trực tiếp. "]}):null,'Account d\xf9ng email kh\xe1c (vd: Gmail) cần x\xe1c thực qua mail: khi add account hệ thống tự gửi mail x\xe1c thực, với account đ\xe3 add th\xec bấm "X\xe1c thực" ở danh s\xe1ch account b\xean dưới. Email đ\xe3 x\xe1c thực chỉ \xe1p dụng cho t\xe0i khoản của bạn.']})]}),m?(0,r.jsx)("div",{className:"rounded-xl border border-red-500/30 bg-red-500/10 px-4 py-3 text-sm text-red-700 dark:text-red-300",children:m}):null,h?(0,r.jsx)("div",{className:"rounded-xl border border-green-500/30 bg-green-500/10 px-4 py-3 text-sm text-green-700 dark:text-green-300",children:h}):null,s.length>0?(0,r.jsxs)("div",{className:"space-y-3",children:[(0,r.jsx)("div",{className:"text-sm font-medium text-text-main",children:"Account đang chờ x\xe1c thực email"}),s.map(e=>(0,r.jsxs)("div",{className:"rounded-2xl border border-yellow-500/30 bg-yellow-500/5 p-4",children:[(0,r.jsxs)("div",{className:"mb-2 flex flex-wrap items-center gap-2 text-sm",children:[(0,r.jsx)(o.Ex,{variant:"warning",size:"sm",children:e.provider}),(0,r.jsx)("span",{className:"break-all font-mono text-text-main",children:e.email}),(0,r.jsxs)("span",{className:"text-xs text-text-muted",children:["giữ đến ",I(e.expiresAt)]})]}),(0,r.jsx)(K.A,{compact:!0,pendingAccount:e,message:`Mở mail gửi tới ${e.email}, bấm link x\xe1c thực, rồi bấm "T\xf4i đ\xe3 x\xe1c thực" để ho\xe0n tất add account.`,onVerified:f,onClose:()=>b(e.id)})]},e.id))]}):null,e.smtpConfigured?null:(0,r.jsx)("div",{className:"rounded-xl border border-yellow-500/30 bg-yellow-500/10 px-4 py-3 text-sm text-yellow-800 dark:text-yellow-300",children:"Hệ thống chưa cấu h\xecnh gửi mail. Li\xean hệ admin để được th\xeam email v\xe0o danh s\xe1ch cho ph\xe9p."}),w.length>0||k.length>0||C.length>0?(0,r.jsx)("div",{className:"overflow-x-auto rounded-2xl border border-border",children:(0,r.jsxs)("table",{className:"min-w-full divide-y divide-border text-sm",children:[(0,r.jsx)("thead",{className:"bg-surface/80 text-left text-xs uppercase tracking-wide text-text-muted",children:(0,r.jsxs)("tr",{children:[(0,r.jsx)("th",{className:"px-4 py-3 font-medium",children:"Email"}),(0,r.jsx)("th",{className:"px-4 py-3 font-medium",children:"Trạng th\xe1i"}),(0,r.jsx)("th",{className:"px-4 py-3 text-right font-medium",children:"Actions"})]})}),(0,r.jsxs)("tbody",{className:"divide-y divide-border bg-background",children:[w.map(e=>(0,r.jsxs)("tr",{className:"hover:bg-surface/50",children:[(0,r.jsx)("td",{className:"px-4 py-3 break-all font-mono text-text-main",children:e.email}),(0,r.jsxs)("td",{className:"px-4 py-3 text-xs text-text-muted",children:[(0,r.jsx)(o.Ex,{variant:"success",size:"sm",children:"Đ\xe3 cho ph\xe9p"}),(0,r.jsx)("span",{className:"ml-2",children:I(e.verifiedAt||e.addedAt)})]}),(0,r.jsx)("td",{className:"px-4 py-3",children:(0,r.jsx)("div",{className:"flex justify-end",children:(0,r.jsx)(o.$n,{variant:"outline",size:"sm",icon:"delete",onClick:()=>y(e.email),disabled:d,children:"Xo\xe1"})})})]},`verified:${e.email}`)),C.map(t=>(0,r.jsxs)("tr",{className:"hover:bg-surface/50",children:[(0,r.jsx)("td",{className:"px-4 py-3 break-all font-mono text-text-main",children:t.email}),(0,r.jsxs)("td",{className:"px-4 py-3 text-xs text-text-muted",children:[(0,r.jsx)(o.Ex,{variant:"warning",size:"sm",children:"Chưa x\xe1c thực"}),(0,r.jsx)("span",{className:"ml-2",children:"cần x\xe1c thực lại để d\xf9ng"})]}),(0,r.jsx)("td",{className:"px-4 py-3",children:(0,r.jsx)("div",{className:"flex justify-end",children:e.smtpConfigured?(0,r.jsx)(o.$n,{variant:"outline",size:"sm",icon:"mark_email_unread",onClick:()=>v(t.email),disabled:d,children:"Gửi email x\xe1c thực"}):null})})]},`unverified:${t.email}`)),k.filter(e=>!w.some(t=>t.email===e.email)).map(t=>(0,r.jsxs)("tr",{className:"hover:bg-surface/50",children:[(0,r.jsx)("td",{className:"px-4 py-3 break-all font-mono text-text-main",children:t.email}),(0,r.jsxs)("td",{className:"px-4 py-3 text-xs text-text-muted",children:[(0,r.jsx)(o.Ex,{variant:"warning",size:"sm",children:"Chờ x\xe1c thực"}),(0,r.jsxs)("span",{className:"ml-2",children:["hết hạn ",I(t.expiresAt)]})]}),(0,r.jsx)("td",{className:"px-4 py-3",children:(0,r.jsxs)("div",{className:"flex justify-end gap-2",children:[e.smtpConfigured?(0,r.jsx)(o.$n,{variant:"outline",size:"sm",icon:"send",onClick:()=>v(t.email),disabled:d,children:"Gửi lại"}):null,(0,r.jsx)(o.$n,{variant:"ghost",size:"sm",icon:"close",onClick:()=>y(t.email),disabled:d,children:"Huỷ"})]})})]},`pending:${t.email}`))]})]})}):null]}):null}function L(){let e=(0,n.useRef)(null);return(0,n.useLayoutEffect)(()=>{let t=e.current;if(!t)return;let s=null,r=()=>{let e=Array.from(t.querySelectorAll("h2")).find(e=>e.textContent?.trim()==="Admin: OAuth provider access"),r=e?.closest(".bg-surface.border.border-border");r&&r!==s&&(s&&s.style.removeProperty("display"),(s=r).style.setProperty("display","none"))};r();let n=new MutationObserver(r);return n.observe(t,{childList:!0,subtree:!0}),()=>{n.disconnect(),s&&s.style.removeProperty("display")}},[]),(0,r.jsxs)("div",{ref:e,className:O().page,children:[(0,r.jsx)(z,{}),(0,r.jsx)(E.default,{}),(0,r.jsx)(P.default,{}),(0,r.jsx)($.default,{})]})}function D(){let{isAdmin:e}=(0,i.s)(),[t,s]=(0,n.useState)("oauth"),o=(0,n.useMemo)(()=>[{id:"oauth",label:"Personal OAuth",icon:"cloud_sync"},...e?[{id:"monitor",label:"OAuth Monitor",icon:"manage_accounts"}]:[],{id:"quota",label:"Personal Quota",icon:"data_usage"},...e?[{id:"admin-access",label:"Admin: OAuth Access",icon:"admin_panel_settings"}]:[],...e?[{id:"admin-accounts",label:"Admin: Account Allowlist",icon:"verified_user"}]:[]],[e]),m=o.some(e=>e.id===t)?t:"oauth";return(0,r.jsxs)("div",{className:"min-w-0",children:[(0,r.jsx)(l.A,{tabs:o,activeId:m,onChange:s}),"oauth"===m?(0,r.jsx)(L,{}):null,"monitor"===m&&e?(0,r.jsx)(d.default,{}):null,"quota"===m?(0,r.jsx)(n.Suspense,{fallback:(0,r.jsx)(a.CardSkeleton,{}),children:(0,r.jsx)(c.default,{})}):null,"admin-access"===m&&e?(0,r.jsx)(u,{}):null,"admin-accounts"===m&&e?(0,r.jsx)(A,{}):null]})}},31458:(e,t,s)=>{"use strict";s.d(t,{default:()=>d});var r=s(95155),n=s(12115),a=s(35497),i=s(57250),l=s(94027);function d(){let{isAdmin:e}=(0,l.s)(),[t,s]=(0,n.useState)([]),[d,c]=(0,n.useState)(!1),[o,m]=(0,n.useState)(""),[x,h]=(0,n.useState)(""),[u,p]=(0,n.useState)(""),g=(0,n.useCallback)(async()=>{if(e){c(!0),h("");try{let e=await fetch("/api/personal-cloud-providers/visibility",{cache:"no-store"}),t=await e.json().catch(()=>({}));if(!e.ok)throw Error(t.error||"Kh\xf4ng tải được trạng th\xe1i Show/Hide provider");s(Array.isArray(t.providers)?t.providers:[])}catch(e){h(e?.message||"Kh\xf4ng tải được trạng th\xe1i Show/Hide provider")}finally{c(!1)}}},[e]);if((0,n.useEffect)(()=>{g()},[g]),!e)return null;let b=async(e,t)=>{m(e.id),h(""),p("");try{let r=await fetch("/api/personal-cloud-providers/visibility",{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify({providerId:e.id,visible:t})}),n=await r.json().catch(()=>({}));if(!r.ok)throw Error(n.error||"Kh\xf4ng cập nhật được visibility provider");s(Array.isArray(n.providers)?n.providers:[]),p(`${e.name}: ${t?"đ\xe3 Show cho user":"đ\xe3 Hide khỏi user"}.`)}catch(e){h(e?.message||"Kh\xf4ng cập nhật được visibility provider")}finally{m("")}};return(0,r.jsxs)("div",{className:"rounded-2xl border border-border bg-surface/50 p-4",children:[(0,r.jsxs)("div",{className:"flex flex-col gap-2 sm:flex-row sm:items-start sm:justify-between",children:[(0,r.jsxs)("div",{children:[(0,r.jsx)("div",{className:"font-semibold text-text-main",children:"Admin: Show / Hide Personal Cloud Providers"}),(0,r.jsx)("div",{className:"mt-1 text-xs text-text-muted",children:"Chỉ điều khiển provider c\xf3 xuất hiện tr\xean giao diện của user hay kh\xf4ng. Kh\xf4ng đổi quyền OAuth, kh\xf4ng deactivate connection, kh\xf4ng x\xf3a token, kh\xf4ng đổi API key/routing v\xe0 kh\xf4ng ảnh hưởng sử dụng thực tế."})]}),(0,r.jsx)(a.$n,{size:"sm",variant:"outline",onClick:g,loading:d,icon:"refresh",children:"Refresh"})]}),x?(0,r.jsx)("div",{className:"mt-3 rounded-xl border border-red-500/30 bg-red-500/10 px-3 py-2 text-xs text-red-700 dark:text-red-300",children:x}):null,u?(0,r.jsx)("div",{className:"mt-3 rounded-xl border border-green-500/30 bg-green-500/10 px-3 py-2 text-xs text-green-700 dark:text-green-300",children:u}):null,(0,r.jsx)("div",{className:"mt-4 grid gap-3 md:grid-cols-2 xl:grid-cols-4",children:t.map(e=>{let t=!1!==e.visible,s=o===e.id;return(0,r.jsxs)("div",{className:"flex items-center justify-between gap-3 rounded-xl border border-border bg-background p-3",children:[(0,r.jsxs)("div",{className:"flex min-w-0 items-center gap-3",children:[(0,r.jsx)(i.A,{src:`/providers/${e.id}.png`,alt:e.name,size:30,className:"max-h-[30px] max-w-[30px] rounded object-contain",fallbackText:e.id.slice(0,2).toUpperCase(),fallbackColor:e.color||"#64748b"}),(0,r.jsxs)("div",{className:"min-w-0",children:[(0,r.jsx)("div",{className:"truncate text-sm font-medium text-text-main",children:e.name}),(0,r.jsx)(a.Ex,{variant:t?"success":"default",size:"sm",children:t?"Shown":"Hidden"})]})]}),(0,r.jsx)(a.$n,{size:"sm",variant:t?"outline":"secondary",disabled:s,loading:s,icon:t?"visibility_off":"visibility",onClick:()=>b(e,!t),children:t?"Hide":"Show"})]},e.id)})})]})}},96928:(e,t,s)=>{Promise.resolve().then(s.bind(s,12749))}},e=>{e.O(0,[6373,3862,8500,9893,9959,7050,2218,5263,7033,5497,7413,912,6945,7173,8441,3794,7358],()=>e(e.s=96928)),_N_E=e.O()}]);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[823],{10332:(e,t,r)=>{Promise.resolve().then(r.bind(r,49711))},14051:(e,t,r)=>{e.exports=r(34701)()},31474:(e,t,r)=>{"use strict";function s(...e){return e.filter(Boolean).join(" ").replace(/\s+/g," ").trim()}r.d(t,{cn:()=>s})},34701:(e,t,r)=>{"use strict";var s=r(82114);function a(){}function o(){}o.resetWarningCache=a,e.exports=function(){function e(e,t,r,a,o,l){if(l!==s){var n=Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw n.name="Invariant Violation",n}}function t(){return e}e.isRequired=e;var r={array:e,bigint:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,elementType:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t,checkPropTypes:o,resetWarningCache:a};return r.PropTypes=r,r}},46442:(e,t,r)=>{"use strict";r.d(t,{j:()=>l,t:()=>n});var s=r(95155),a=r(12115);let o=(0,a.createContext)(null);function l({resolver:e,children:t}){return(0,s.jsx)(o.Provider,{value:"function"==typeof e?e:null,children:t})}function n(){return(0,a.useContext)(o)}},49711:(e,t,r)=>{"use strict";r.d(t,{default:()=>b});var s=r(95155),a=r(12115),o=r(84588),l=r(57250),n=r(81127),d=r(92542);let i=[{id:"fallback",label:"Fallback (priority order)",icon:"swap_vert"},{id:"round-robin",label:"Round Robin",icon:"sync"}],c={fallback:"Fallback (priority order)","round-robin":"Round Robin",sticky:"Sticky","least-latency":"Least latency",p2c:"Power of two choices"};function m(e){return c[e]||e||"fallback"}function x(e){return String(e||"").trim().toLowerCase()}function u(){return{id:null,name:"",strategy:"fallback",models:[]}}function b(){let[e,t]=(0,a.useState)([]),[r,c]=(0,a.useState)([]),[b,p]=(0,a.useState)([]),[h,g]=(0,a.useState)(!0),[f,y]=(0,a.useState)(""),[v,j]=(0,a.useState)(!1),[N,k]=(0,a.useState)(""),[w,C]=(0,a.useState)(null),[A,S]=(0,a.useState)(u()),[_,P]=(0,a.useState)(""),[M,T]=(0,a.useState)(!1),[E,I]=(0,a.useState)(""),[O,F]=(0,a.useState)(""),[R,$]=(0,a.useState)(""),[L,D]=(0,a.useState)("all"),[U,z]=(0,a.useState)(null),[q,K]=(0,a.useState)([]),[B,W]=(0,a.useState)(!1),[H,J]=(0,a.useState)(""),[G,V]=(0,a.useState)(!1),[X,Y]=(0,a.useState)(""),[Q,Z]=(0,a.useState)(""),ee=(0,a.useCallback)(async()=>{g(!0),y("");try{let[e,r]=await Promise.all([fetch("/api/personal-cloud-providers",{cache:"no-store"}),fetch("/api/personal-cloud-combos?scope=all",{cache:"no-store"})]),s=await e.json().catch(()=>({})),a=await r.json().catch(()=>({}));if(!e.ok)throw Error(s.error||"Failed to load personal connections");if(!r.ok)throw Error(a.error||"Failed to load cloud combos");t(Array.isArray(s.connections)?s.connections:[]),c(Array.isArray(a.combos)?a.combos:[]),p(Array.isArray(a.localDefaultModels)?a.localDefaultModels:[]),P(a.userId||""),T("all"===a.scope)}catch(e){y(e.message||"Failed to load cloud combos")}finally{g(!1)}},[]);(0,a.useEffect)(()=>{ee()},[ee]);let et=async e=>{z(e),J(""),Y(""),Z(""),W(!0);try{let e=await fetch("/api/keys?pageSize=100&status=active",{cache:"no-store"}),t=await e.json().catch(()=>({}));if(!e.ok)throw Error(t.error||"Failed to load API keys");K(Array.isArray(t.keys)?t.keys:[])}catch(e){Y(e.message||"Failed to load API keys"),K([])}finally{W(!1)}};function er(){z(null),J(""),Y(""),Z("")}async function es(){if(U&&H){V(!0),Y("");try{let e=await fetch(`/api/personal-cloud-combos/${encodeURIComponent(U.id)}/api-key-models`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiKeyId:H})}),t=await e.json().catch(()=>({}));if(!e.ok)throw Error(t.error||"Failed to add combo to API key");Z(`Đ\xe3 th\xeam "${U.name}" v\xe0o API key ${t.key?.name||""}.`)}catch(e){Y(e.message||"Failed to add combo to API key")}finally{V(!1)}}}let ea=(0,a.useMemo)(()=>{let t=new Set,r=[];for(let s of e)if(!1!==s.isActive){for(let e of Array.isArray(s?.importedModels)&&s.importedModels.length>0?s.importedModels:Array.isArray(s?.availableModels)?s.availableModels:[])!e?.routeModel||t.has(e.routeModel)||(t.add(e.routeModel),r.push({provider:s.provider,connectionLabel:s.name||s.email||s.provider,model:e}))}return r},[e]),eo=(0,a.useMemo)(()=>new Set(b),[b]),el=(0,a.useMemo)(()=>new Set(ea.map(e=>e.model.routeModel)),[ea]),en=(0,a.useCallback)(e=>!eo.has(e)&&!el.has(e),[eo,el]),ed=x(_),ei=(0,a.useCallback)(e=>!M||!!ed&&x(e?.ownerUser)===ed,[M,ed]),ec=(0,a.useMemo)(()=>{let e=new Set;for(let t of r){let r=String(t.ownerUser||"").trim();r&&e.add(r)}return[...e].sort((e,t)=>e.localeCompare(t))},[r]),em=(0,a.useMemo)(()=>[...new Set(r.map(e=>e.strategy||"fallback"))].sort((e,t)=>m(e).localeCompare(m(t))),[r]),ex=!!E.trim()||!!O||!!R||"all"!==L,eu=(0,a.useMemo)(()=>{if(!M)return r;let e=E.trim().toLowerCase();return r.filter(t=>(!O||x(t.ownerUser)===x(O))&&(!R||(t.strategy||"fallback")===R)&&("active"!==L||!1!==t.isActive)&&("inactive"!==L||!1===t.isActive)&&(!e||[t.ownerUser,t.name,t.id,...t.models||[]].join(" ").toLowerCase().includes(e)))},[r,M,E,O,R,L]);function eb(){C(null),S(u()),k("")}function ep(e){S(t=>{let r=t.models.includes(e);return{...t,models:r?t.models.filter(t=>t!==e):[...t.models,e]}})}function eh(e,t){S(r=>{let s=[...r.models],a=e+t;return a<0||a>=s.length?r:([s[e],s[a]]=[s[a],s[e]],{...r,models:s})})}async function eg(){k("");let e=A.name.trim();if(!e)return void k("Name is required");if(0===A.models.length)return void k("Select at least one model");j(!0);try{let t="new"===w,r=t?"/api/personal-cloud-combos":`/api/personal-cloud-combos/${encodeURIComponent(A.id)}`,s=await fetch(r,{method:t?"POST":"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:e,strategy:A.strategy,models:A.models})}),a=await s.json().catch(()=>({}));if(!s.ok){let e=Array.isArray(a.invalidModels)&&a.invalidModels.length>0?`: ${a.invalidModels.join(", ")}`:"";throw Error((a.error||"Failed to save combo")+e)}await ee(),eb()}catch(e){k(e.message||"Failed to save combo")}finally{j(!1)}}async function ef(e){if(window.confirm(`Delete cloud combo "${e.name}"? This cannot be undone.`))try{let t=await fetch(`/api/personal-cloud-combos/${encodeURIComponent(e.id)}`,{method:"DELETE"}),r=await t.json().catch(()=>({}));if(!t.ok)throw Error(r.error||"Failed to delete combo");await ee()}catch(e){y(e.message||"Failed to delete combo")}}return h?(0,s.jsx)("div",{className:"rounded-2xl border border-border bg-surface p-4 text-sm text-text-muted",children:"Loading cloud combos…"}):(0,s.jsxs)("div",{className:"space-y-5",children:[(0,s.jsxs)("section",{className:"space-y-2",children:[(0,s.jsxs)("div",{className:"flex flex-wrap items-start justify-between gap-3",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("h2",{className:"text-base font-semibold text-text-main",children:"Cloud Combos"}),(0,s.jsx)("p",{className:"mt-1 max-w-2xl text-xs leading-5 text-text-muted",children:"Tạo combo (fallback / round-robin) gồm c\xe1c model từ ch\xednh c\xe1c t\xe0i khoản OAuth c\xe1 nh\xe2n của bạn (Claude, Codex/OpenAI, Grok, Kiro...) v\xe0/hoặc local model lấy từ Default models của admin. Kh\xf4ng c\xf3 sampling override."}),M&&(0,s.jsxs)("p",{className:"mt-1.5 inline-flex items-center gap-1.5 rounded-lg border border-primary/30 bg-primary/5 px-2 py-1 text-[11px] text-primary",children:[(0,s.jsx)("span",{className:"material-symbols-outlined text-[14px]",children:"admin_panel_settings"}),"Chế độ admin: đang xem ",r.length," combo của to\xe0n hệ thống (",ec.length," người d\xf9ng). Combo của người kh\xe1c chỉ xem, kh\xf4ng sửa được."]})]}),null===w&&(0,s.jsxs)("button",{type:"button",onClick:function(){S(u()),k(""),C("new")},className:"inline-flex items-center gap-1.5 rounded-lg border border-border bg-background px-3 py-1.5 text-xs font-medium text-text-main transition hover:border-primary/30 hover:bg-surface",children:[(0,s.jsx)("span",{className:"material-symbols-outlined text-[16px]",children:"add"}),"New combo"]})]}),f&&(0,s.jsx)("div",{className:"rounded-lg border border-red-500/20 bg-red-500/5 p-3 text-xs text-red-600",children:f}),M&&r.length>0&&(0,s.jsxs)("div",{className:"grid gap-2 md:grid-cols-[minmax(0,1fr)_auto_auto_auto]",children:[(0,s.jsx)("input",{type:"text",value:E,onChange:e=>I(e.target.value),placeholder:"T\xecm theo owner, t\xean combo, model id...",className:"h-9 w-full rounded-lg border border-border bg-background px-3 text-xs text-text-main outline-none focus:border-primary"}),(0,s.jsxs)("select",{value:O,onChange:e=>F(e.target.value),className:"h-9 rounded-lg border border-border bg-background px-2 text-xs text-text-main outline-none focus:border-primary",children:[(0,s.jsx)("option",{value:"",children:"Tất cả owner"}),ec.map(e=>(0,s.jsx)("option",{value:e,children:e},e))]}),(0,s.jsxs)("select",{value:R,onChange:e=>$(e.target.value),className:"h-9 rounded-lg border border-border bg-background px-2 text-xs text-text-main outline-none focus:border-primary",children:[(0,s.jsx)("option",{value:"",children:"Tất cả strategy"}),em.map(e=>(0,s.jsx)("option",{value:e,children:m(e)},e))]}),(0,s.jsxs)("select",{value:L,onChange:e=>D(e.target.value),className:"h-9 rounded-lg border border-border bg-background px-2 text-xs text-text-main outline-none focus:border-primary",children:[(0,s.jsx)("option",{value:"all",children:"Tất cả trạng th\xe1i"}),(0,s.jsx)("option",{value:"active",children:"Đang hoạt động"}),(0,s.jsx)("option",{value:"inactive",children:"Cần xử l\xfd"})]})]}),M&&ex&&(0,s.jsxs)("div",{className:"flex items-center gap-2 text-[11px] text-text-muted",children:[(0,s.jsxs)("span",{children:["Hiện ",eu.length,"/",r.length," combo"]}),(0,s.jsx)("button",{type:"button",onClick:function(){I(""),F(""),$(""),D("all")},className:"text-primary hover:underline",children:"Xo\xe1 bộ lọc"})]})]}),null!==w&&(0,s.jsxs)(o.default,{className:"space-y-4",children:[(0,s.jsxs)("div",{className:"grid gap-3 sm:grid-cols-2",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("label",{className:"mb-1 block text-xs font-medium text-text-muted",children:"Name"}),(0,s.jsx)("input",{type:"text",value:A.name,onChange:e=>S(t=>({...t,name:e.target.value})),placeholder:"my-claude-fallback",className:"w-full rounded-lg border border-border bg-background px-3 py-2 text-sm text-text-main"})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)("label",{className:"mb-1 block text-xs font-medium text-text-muted",children:"Strategy"}),(0,s.jsx)("div",{className:"flex gap-2",children:i.map(e=>(0,s.jsxs)("button",{type:"button",onClick:()=>S(t=>({...t,strategy:e.id})),className:`inline-flex flex-1 items-center justify-center gap-1.5 rounded-lg border px-3 py-2 text-xs font-medium transition ${A.strategy===e.id?"border-primary/40 bg-primary/10 text-primary":"border-border bg-background text-text-main hover:border-primary/30"}`,children:[(0,s.jsx)("span",{className:"material-symbols-outlined text-[16px]",children:e.icon}),e.label]},e.id))})]})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)("div",{className:"mb-2 text-xs font-medium text-text-muted",children:"Models in this combo (order = fallback priority)"}),0===A.models.length?(0,s.jsx)("div",{className:"rounded-lg border border-dashed border-border p-3 text-xs text-text-muted",children:"Chưa chọn model n\xe0o."}):(0,s.jsx)("div",{className:"space-y-1.5",children:A.models.map((e,t)=>(0,s.jsxs)("div",{className:"flex items-center gap-2 rounded-lg border border-border bg-background px-3 py-1.5",children:[(0,s.jsx)("span",{className:"min-w-0 flex-1 truncate text-xs font-mono text-text-main",children:e}),eo.has(e)&&(0,s.jsx)("span",{className:"rounded bg-sky-500/10 px-1.5 py-0.5 text-[10px] font-medium text-sky-600",children:"Local"}),en(e)&&(0,s.jsx)("span",{className:"rounded bg-amber-500/10 px-1.5 py-0.5 text-[10px] font-medium text-amber-600",title:"Kh\xf4ng c\xf2n trong Default models / OAuth của bạn — h\xe3y xo\xe1 trước khi lưu",children:"Kh\xf4ng c\xf2n khả dụng"}),(0,s.jsx)("button",{type:"button",onClick:()=>eh(t,-1),disabled:0===t,className:"text-text-muted hover:text-text-main disabled:opacity-30",children:(0,s.jsx)("span",{className:"material-symbols-outlined text-[16px]",children:"arrow_upward"})}),(0,s.jsx)("button",{type:"button",onClick:()=>eh(t,1),disabled:t===A.models.length-1,className:"text-text-muted hover:text-text-main disabled:opacity-30",children:(0,s.jsx)("span",{className:"material-symbols-outlined text-[16px]",children:"arrow_downward"})}),(0,s.jsx)("button",{type:"button",onClick:()=>{S(t=>({...t,models:t.models.filter(t=>t!==e)}))},className:"text-red-500 hover:text-red-600",children:(0,s.jsx)("span",{className:"material-symbols-outlined text-[16px]",children:"close"})})]},e))})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)("div",{className:"mb-2 text-xs font-medium text-text-muted",children:"Model của bạn (chỉ hiện model từ OAuth connection đang active của bạn)"}),0===ea.length?(0,s.jsx)("div",{className:"rounded-lg border border-dashed border-border p-3 text-xs text-text-muted",children:"Bạn chưa c\xf3 personal OAuth connection n\xe0o đang active. Kết nối t\xe0i khoản ở tab Personal OAuth trước."}):(0,s.jsx)("div",{className:"grid max-h-64 gap-1.5 overflow-y-auto rounded-lg border border-border p-2 sm:grid-cols-2",children:ea.map(({provider:e,connectionLabel:t,model:r})=>{let a=A.models.includes(r.routeModel),o="review"===r.quotaFamily,n=o?r.name.replace(/ Review$/,""):r.name;return(0,s.jsxs)("label",{className:"flex cursor-pointer items-center gap-2 rounded-lg px-2 py-1.5 text-xs hover:bg-surface-2/50",children:[(0,s.jsx)("input",{type:"checkbox",checked:a,onChange:()=>ep(r.routeModel),className:"shrink-0"}),(0,s.jsx)(l.A,{src:`/providers/${e}.png`,alt:e,size:18,className:"shrink-0 rounded object-contain",fallbackText:String(e||"?").slice(0,2).toUpperCase()}),(0,s.jsxs)("span",{className:"min-w-0 flex-1 truncate",children:[(0,s.jsxs)("span",{className:"block truncate",children:[(0,s.jsx)("span",{className:"font-medium text-text-main",children:n}),o&&(0,s.jsx)("span",{className:"ml-1 rounded bg-amber-500/10 px-1 py-0.5 text-[10px] font-medium text-amber-600",children:"Review quota"}),(0,s.jsxs)("span",{className:"ml-1 text-text-muted",children:["\xb7 ",t]})]}),(0,s.jsx)("span",{className:"block truncate font-mono text-[10px] text-text-muted/70",children:r.routeModel})]})]},`${t}:${r.routeModel}`)})})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)("div",{className:"mb-2 text-xs font-medium text-text-muted",children:"Local models (từ Default models cho API key do admin cấu h\xecnh)"}),0===b.length?(0,s.jsx)("div",{className:"rounded-lg border border-dashed border-border p-3 text-xs text-text-muted",children:"Admin chưa cấu h\xecnh Default model local n\xe0o (Default models ở /dashboard/api-keys)."}):(0,s.jsx)("div",{className:"grid max-h-48 gap-1.5 overflow-y-auto rounded-lg border border-border p-2 sm:grid-cols-2",children:b.map(e=>(0,s.jsxs)("label",{className:"flex cursor-pointer items-center gap-2 rounded-lg px-2 py-1.5 text-xs hover:bg-surface-2/50",children:[(0,s.jsx)("input",{type:"checkbox",checked:A.models.includes(e),onChange:()=>ep(e),className:"shrink-0"}),(0,s.jsx)("span",{className:"material-symbols-outlined shrink-0 text-[16px] text-sky-600",children:"dns"}),(0,s.jsx)("span",{className:"min-w-0 flex-1 truncate font-mono text-text-main",children:e})]},e))}),(0,s.jsx)("p",{className:"mt-1.5 text-[11px] leading-4 text-text-muted",children:"Local model chạy bằng pool hệ thống, kh\xf4ng phải t\xe0i khoản OAuth của bạn. Trộn với model cloud: thứ tự tr\xean l\xe0 thứ tự fallback; nếu admin gỡ model khỏi Default models th\xec combo sẽ bỏ qua model đ\xf3."})]}),N&&(0,s.jsx)("div",{className:"rounded-lg border border-red-500/20 bg-red-500/5 p-2.5 text-xs text-red-600",children:N}),(0,s.jsxs)("div",{className:"flex justify-end gap-2",children:[(0,s.jsx)("button",{type:"button",onClick:eb,className:"rounded-lg border border-border bg-background px-3 py-1.5 text-xs font-medium text-text-main hover:bg-surface",children:"Cancel"}),(0,s.jsx)("button",{type:"button",onClick:eg,disabled:v,className:"rounded-lg border border-primary/40 bg-primary/10 px-3 py-1.5 text-xs font-medium text-primary hover:bg-primary/20 disabled:opacity-50",children:v?"Saving…":"new"===w?"Create combo":"Save changes"})]})]}),(0,s.jsxs)("div",{className:"grid gap-3 xl:grid-cols-2",children:[0===r.length&&null===w?(0,s.jsx)("div",{className:"col-span-full rounded-2xl border border-dashed border-border p-6 text-center text-sm text-text-muted",children:M?"Chưa c\xf3 ai tạo cloud combo n\xe0o.":"Bạn chưa c\xf3 cloud combo n\xe0o."}):null,r.length>0&&0===eu.length?(0,s.jsx)("div",{className:"col-span-full rounded-2xl border border-dashed border-border p-6 text-center text-sm text-text-muted",children:"Kh\xf4ng c\xf3 combo n\xe0o khớp bộ lọc."}):null,eu.map(e=>(0,s.jsxs)(o.default,{className:"space-y-3",children:[(0,s.jsxs)("div",{className:"flex flex-wrap items-start justify-between gap-2",children:[(0,s.jsxs)("div",{className:"min-w-0",children:[(0,s.jsxs)("div",{className:"flex items-center gap-2",children:[(0,s.jsx)("div",{className:"truncate text-sm font-semibold text-text-main",children:e.name}),!1===e.isActive&&(0,s.jsx)("span",{className:"rounded-full border border-amber-500/30 bg-amber-500/10 px-2 py-0.5 text-[10px] font-semibold text-amber-600",children:"No models left — needs attention"})]}),(0,s.jsxs)("div",{className:"mt-1 text-xs text-text-muted",children:[m(e.strategy)," \xb7 ",e.models?.length||0," model(s)"]}),M&&(0,s.jsxs)("div",{className:"mt-1 flex items-center gap-1 text-[11px] text-text-muted",children:[(0,s.jsx)("span",{className:"material-symbols-outlined text-[14px]",children:"person"}),(0,s.jsx)("span",{className:"truncate",children:e.ownerUser||"—"})]})]}),ei(e)?(0,s.jsxs)("div",{className:"flex items-center gap-1",children:[(0,s.jsxs)("button",{type:"button",onClick:()=>et(e),className:"inline-flex items-center gap-1 rounded-lg border border-primary/30 bg-primary/5 px-2 py-1.5 text-[11px] font-medium text-primary hover:bg-primary/10",children:[(0,s.jsx)("span",{className:"material-symbols-outlined text-[16px]",children:"vpn_key"}),"Add this combo to API key"]}),(0,s.jsx)("button",{type:"button",onClick:()=>{S({id:e.id,name:e.name,strategy:e.strategy||"fallback",models:[...e.models||[]]}),k(""),C(e.id)},className:"rounded-lg border border-border bg-background p-1.5 text-text-muted hover:text-text-main",children:(0,s.jsx)("span",{className:"material-symbols-outlined text-[16px]",children:"edit"})}),(0,s.jsx)("button",{type:"button",onClick:()=>ef(e),className:"rounded-lg border border-border bg-background p-1.5 text-red-500 hover:bg-red-500/5",children:(0,s.jsx)("span",{className:"material-symbols-outlined text-[16px]",children:"delete"})})]}):(0,s.jsxs)("span",{className:"inline-flex shrink-0 items-center gap-1 rounded-full border border-border bg-background px-2 py-0.5 text-[10px] font-medium text-text-muted",children:[(0,s.jsx)("span",{className:"material-symbols-outlined text-[13px]",children:"lock"}),"Chỉ xem"]})]}),(0,s.jsxs)("div",{className:"flex items-center gap-2 rounded-lg border border-border bg-background px-2.5 py-1.5",children:[(0,s.jsx)("span",{className:"text-[10px] uppercase tracking-wide text-text-muted",children:"model id để gọi API"}),(0,s.jsx)("code",{className:"min-w-0 flex-1 truncate text-xs text-text-main",children:e.id}),(0,s.jsx)("button",{type:"button",onClick:()=>(function(e){try{navigator.clipboard?.writeText(e)}catch{}})(e.id),className:"text-text-muted hover:text-text-main",children:(0,s.jsx)("span",{className:"material-symbols-outlined text-[16px]",children:"content_copy"})})]}),(0,s.jsx)("div",{className:"flex flex-wrap gap-1.5",children:(e.models||[]).map(e=>(0,s.jsxs)("span",{className:"rounded-full border border-border bg-background px-2 py-0.5 text-[11px] font-mono text-text-muted",children:[eo.has(e)?(0,s.jsx)("span",{className:"mr-1 text-sky-600",children:"local"}):null,e]},e))})]},e.id))]}),(0,s.jsx)(n.default,{isOpen:!!U,onClose:er,title:`Add "${U?.name||""}" to API key`,footer:(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(d.default,{variant:"ghost",onClick:er,disabled:G,children:"Cancel"}),(0,s.jsx)(d.default,{onClick:es,loading:G,disabled:!H,children:"Add to key"})]}),children:(0,s.jsxs)("div",{className:"space-y-3",children:[(0,s.jsxs)("p",{className:"text-sm text-text-muted",children:["Th\xeam model id ",(0,s.jsx)("code",{className:"font-mono text-text-main",children:U?.id})," v\xe0o ",(0,s.jsx)("code",{children:"allowedModels"})," của API key đ\xe3 chọn (chỉ hiện API key của ch\xednh bạn)."]}),(0,s.jsx)("p",{className:"rounded-lg border border-primary/20 bg-primary/5 p-2.5 text-xs text-text-muted",children:"Chỉ cần cấp quyền combo: API key d\xf9ng được combo n\xe0y m\xe0 kh\xf4ng cần cấp quyền ri\xeang cho từng model b\xean trong."}),(0,s.jsxs)("label",{className:"block text-sm",children:[(0,s.jsx)("span",{className:"mb-1 block font-medium text-text-main",children:"API key"}),(0,s.jsxs)("select",{value:H,onChange:e=>J(e.target.value),className:"h-10 w-full rounded-xl border border-border bg-background px-3 text-sm text-text-main outline-none focus:border-primary",disabled:B,children:[(0,s.jsx)("option",{value:"",children:B?"Đang tải API keys...":"Chọn API key"}),q.map(e=>(0,s.jsx)("option",{value:e.id,children:e.name||e.id},e.id))]})]}),B||0!==q.length?null:(0,s.jsx)("div",{className:"rounded-xl border border-amber-500/30 bg-amber-500/10 p-3 text-xs text-amber-700",children:"Bạn chưa c\xf3 API key active n\xe0o. Tạo API key ở /dashboard/api-keys trước."}),X&&(0,s.jsx)("div",{className:"rounded-lg border border-red-500/20 bg-red-500/5 p-2.5 text-xs text-red-600",children:X}),Q&&(0,s.jsx)("div",{className:"rounded-lg border border-green-500/20 bg-green-500/5 p-2.5 text-xs text-green-600",children:Q})]})})]})}},57250:(e,t,r)=>{"use strict";r.d(t,{A:()=>n});var s=r(95155),a=r(12115),o=r(14051),l=r.n(o);function n({src:e,alt:t,size:r=32,className:o="",fallbackText:l="?",fallbackColor:d}){let[i,c]=(0,a.useState)(!1);return!e||i?(0,s.jsx)("span",{className:`inline-flex items-center justify-center font-bold rounded-lg ${o}`.trim(),style:{width:r,height:r,color:d,fontSize:Math.max(10,Math.floor(.38*r))},children:l}):(0,s.jsx)("img",{src:e,alt:t,width:r,height:r,className:o,onError:()=>c(!0)})}n.propTypes={src:l().string,alt:l().string,size:l().number,className:l().string,fallbackText:l().string,fallbackColor:l().string}},81127:(e,t,r)=>{"use strict";r.d(t,{ConfirmModal:()=>b,default:()=>u});var s=r(95155),a=r(12115),o=r(31474),l=r(92542),n=r(97677),d=r(46442);let i=[],c="";function m(){1===i.length?(c=document.body.style.overflow,document.body.style.overflow="hidden"):0===i.length&&(document.body.style.overflow=c)}function x(e,t){return!!e&&Object.prototype.hasOwnProperty.call(e,t)}function u({isOpen:e,onClose:t,title:r,children:l,footer:c,size:b="md",closeOnOverlay:p=!0,showTrafficLights:h=!0,busy:g=!1,className:f}){let y=(0,a.useRef)({onClose:t,busy:g}),v=(0,d.t)(),j=v?.({title:r,children:l,footer:c,size:b,className:f})||null,N=x(j,"children")?j.children:l,k=x(j,"footer")?j.footer:c,w=j?.size||b,C=(0,o.cn)(f,j?.className);y.current.onClose=t,y.current.busy=g;let A={sm:"max-w-sm",md:"max-w-md",lg:"max-w-lg",xl:"max-w-xl",full:"max-w-4xl"};return((0,a.useEffect)(()=>{if(!e)return;let t=y.current;i.push(t),m();let r=e=>{if("Escape"!==e.key)return;let r=i[i.length-1];r!==t||r.busy||(e.preventDefault(),r.onClose())};return document.addEventListener("keydown",r),()=>{document.removeEventListener("keydown",r);let e=i.indexOf(t);-1!==e&&i.splice(e,1),m()}},[e]),e)?(0,s.jsxs)("div",{className:"fixed inset-0 z-50 flex items-center justify-center p-4",children:[(0,s.jsx)("div",{className:"absolute inset-0 bg-black/50 backdrop-blur-[2px] fade-in",onClick:p&&!g?t:void 0}),(0,s.jsxs)("div",{className:(0,o.cn)("relative w-full bg-surface","border border-border-subtle","rounded-[14px] shadow-[var(--shadow-elev)]","fade-in",A[w]||A.md,C),children:[(r||h)&&(0,s.jsxs)("div",{className:"flex items-center justify-between p-2 border-b border-border-subtle",children:[(0,s.jsxs)("div",{className:"flex items-center",children:[h&&(0,s.jsxs)("div",{className:"hidden md:flex items-center gap-2 mr-4 ml-2",children:[(0,s.jsx)(n.default,{text:"Close",position:"top",color:"#FF5F56",children:(0,s.jsx)("button",{onClick:t,disabled:g,"aria-label":"Close",title:"Close",className:"w-4 h-4 rounded-full bg-[#FF5F56] hover:brightness-90 transition-all cursor-pointer flex items-center justify-center group/dot disabled:cursor-not-allowed disabled:opacity-50",children:(0,s.jsx)("span",{className:"text-[9px] font-bold text-white opacity-0 group-hover/dot:opacity-100 transition-opacity leading-none",children:"✕"})})}),(0,s.jsx)("div",{className:"w-4 h-4 rounded-full bg-[#3a3a3a]/20 dark:bg-white/15 cursor-not-allowed"}),(0,s.jsx)("div",{className:"w-4 h-4 rounded-full bg-[#3a3a3a]/20 dark:bg-white/15 cursor-not-allowed"})]}),r&&(0,s.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:r})]}),(0,s.jsx)("button",{onClick:t,disabled:g,"aria-label":"Close",className:"md:hidden p-1.5 rounded-[10px] text-text-muted hover:bg-surface-2 hover:text-text-main transition-colors disabled:cursor-not-allowed disabled:opacity-50",children:(0,s.jsx)("span",{className:"material-symbols-outlined text-[20px]",children:"close"})})]}),(0,s.jsx)("div",{className:"p-6 max-h-[calc(85vh-100px)] overflow-y-auto custom-scrollbar",children:N}),k&&(0,s.jsx)("div",{className:"flex items-center justify-end gap-3 p-6 border-t border-border-subtle",children:k})]})]}):null}function b({isOpen:e,onClose:t,onConfirm:r,title:a="Confirm",message:o,confirmText:n="Confirm",cancelText:d="Cancel",variant:i="danger",loading:c=!1}){return(0,s.jsx)(u,{isOpen:e,onClose:t,title:a,size:"sm",busy:c,footer:(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(l.default,{variant:"ghost",onClick:t,disabled:c,children:d}),(0,s.jsx)(l.default,{variant:i,onClick:r,loading:c,children:n})]}),children:(0,s.jsx)("p",{className:"text-text-muted",children:o})})}},82114:e=>{"use strict";e.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"},84588:(e,t,r)=>{"use strict";r.d(t,{default:()=>o});var s=r(95155),a=r(31474);function o({children:e,title:t,subtitle:r,icon:l,action:n,padding:d="md",hover:i=!1,elev:c=!1,className:m,...x}){return(0,s.jsxs)("div",{className:(0,a.cn)("bg-surface border border-border",c?"rounded-[14px] shadow-[var(--shadow-elev)]":"rounded-[14px] shadow-[0_1px_2px_rgba(15,23,42,0.045),0_12px_28px_-26px_rgba(37,99,235,0.38)]",i&&"hover:shadow-[var(--shadow-warm)] hover:border-brand-500/40 transition-all cursor-pointer",{none:"",xs:"p-3",sm:"p-4",md:"p-5",lg:"p-6"}[d],m),...x,children:[(t||n)&&(0,s.jsxs)("div",{className:"flex items-center justify-between mb-4",children:[(0,s.jsxs)("div",{className:"flex items-center gap-3",children:[l&&(0,s.jsx)("div",{className:"p-2 rounded-[10px] bg-bg-alt border border-border-subtle text-text-muted",children:(0,s.jsx)("span",{className:"material-symbols-outlined text-[20px]",children:l})}),(0,s.jsxs)("div",{children:[t&&(0,s.jsx)("h3",{className:"text-text-main font-semibold",children:t}),r&&(0,s.jsx)("p",{className:"text-sm text-text-muted",children:r})]})]}),n]}),e]})}o.Section=function({children:e,className:t,...r}){return(0,s.jsx)("div",{className:(0,a.cn)("p-4 rounded-[10px]","bg-bg-alt border border-border",t),...r,children:e})},o.Row=function({children:e,className:t,...r}){return(0,s.jsx)("div",{className:(0,a.cn)("p-3 -mx-3 px-3 transition-colors","border-b border-border-subtle last:border-b-0","hover:bg-surface-2/50",t),...r,children:e})},o.ListItem=function({children:e,actions:t,className:r,...o}){return(0,s.jsxs)("div",{className:(0,a.cn)("group flex items-center justify-between p-3 -mx-3 px-3","border-b border-border-subtle last:border-b-0","hover:bg-surface-2/50 transition-colors",r),...o,children:[(0,s.jsx)("div",{className:"flex-1 min-w-0",children:e}),t&&(0,s.jsx)("div",{className:"flex items-center gap-1 opacity-0 group-hover:opacity-100 transition-opacity",children:t})]})}},92542:(e,t,r)=>{"use strict";r.d(t,{default:()=>n});var s=r(95155),a=r(31474);let o={primary:"bg-brand-500 hover:bg-brand-600 text-white shadow-sm disabled:bg-surface-3 disabled:text-text-muted",secondary:"bg-surface-2 hover:bg-surface-3 text-text-main border border-border disabled:opacity-50",outline:"border border-border text-text-main hover:bg-surface-2 hover:border-brand-500/40",ghost:"text-text-muted hover:bg-surface-2 hover:text-text-main",danger:"bg-red-500 hover:bg-red-600 text-white shadow-sm disabled:bg-surface-3 disabled:text-text-muted",success:"bg-green-600 hover:bg-green-700 text-white shadow-sm disabled:bg-surface-3 disabled:text-text-muted"},l={sm:"h-7 px-3 text-xs rounded-[8px]",md:"h-9 px-4 text-sm rounded-[10px]",lg:"h-11 px-6 text-sm rounded-[10px]"};function n({children:e,variant:t="primary",size:r="md",icon:d,iconRight:i,disabled:c=!1,loading:m=!1,fullWidth:x=!1,className:u,...b}){return(0,s.jsxs)("button",{className:(0,a.cn)("inline-flex items-center justify-center gap-2 font-semibold transition-all duration-150 ease-out cursor-pointer","active:scale-[0.97] disabled:opacity-50 disabled:cursor-not-allowed disabled:active:scale-100",o[t],l[r],x&&"w-full",u),disabled:c||m,...b,children:[m?(0,s.jsx)("span",{className:"material-symbols-outlined animate-spin text-[18px]",children:"progress_activity"}):d?(0,s.jsx)("span",{className:"material-symbols-outlined text-[18px]",children:d}):null,e,i&&!m&&(0,s.jsx)("span",{className:"material-symbols-outlined text-[18px]",children:i})]})}},97677:(e,t,r)=>{"use strict";r.d(t,{default:()=>a});var s=r(95155);function a({text:e,children:t,position:r="top",color:o}){let l=o?"":"bg-gray-900";return(0,s.jsxs)("div",{className:"relative inline-flex group",children:[t,(0,s.jsx)("div",{className:`pointer-events-none absolute ${{top:"bottom-full left-1/2 -translate-x-1/2 mb-1.5",bottom:"top-full left-1/2 -translate-x-1/2 mt-1.5",left:"right-full top-1/2 -translate-y-1/2 mr-1.5",right:"left-full top-1/2 -translate-y-1/2 ml-1.5"}[r]} z-50 w-max max-w-56 rounded px-2 py-1 text-[11px] leading-snug ${l} text-white opacity-0 group-hover:opacity-100 transition-opacity duration-150 whitespace-normal`,style:o?{backgroundColor:o}:{},children:e})]})}}},e=>{e.O(0,[8441,3794,7358],()=>e(e.s=10332)),_N_E=e.O()}]);
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/app/package.json
CHANGED
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[912],{14796:e=>{e.exports={page:"PersonalCloudProviderPage_page__WEiqp"}},29991:e=>{e.exports={shell:"PersonalCloudProviderShares_shell__US6gE",section:"PersonalCloudProviderShares_section__OHcNf",sharedSection:"PersonalCloudProviderShares_sharedSection___aHlv",sectionHeader:"PersonalCloudProviderShares_sectionHeader__vLKx5",eyebrow:"PersonalCloudProviderShares_eyebrow__ouAqZ",title:"PersonalCloudProviderShares_title__y8xC6",description:"PersonalCloudProviderShares_description__xqUNc",lockPill:"PersonalCloudProviderShares_lockPill__cRApp",readOnlyBadge:"PersonalCloudProviderShares_readOnlyBadge__vVzHd",activeBadge:"PersonalCloudProviderShares_activeBadge__1BOdA",inactiveBadge:"PersonalCloudProviderShares_inactiveBadge__3EO5q",accountGrid:"PersonalCloudProviderShares_accountGrid__CDIR9",accountCard:"PersonalCloudProviderShares_accountCard__BIwC5",readOnlyCard:"PersonalCloudProviderShares_readOnlyCard___k8Zg",accountIdentity:"PersonalCloudProviderShares_accountIdentity__wihlv",providerIconWrap:"PersonalCloudProviderShares_providerIconWrap__ahFle",providerIcon:"PersonalCloudProviderShares_providerIcon__73NZX",modalProviderIcon:"PersonalCloudProviderShares_modalProviderIcon__EIGx8",accountText:"PersonalCloudProviderShares_accountText__zeFWz",accountTopLine:"PersonalCloudProviderShares_accountTopLine__PhQY9",accountMeta:"PersonalCloudProviderShares_accountMeta__sndtV",modalAccountMeta:"PersonalCloudProviderShares_modalAccountMeta__9lzRs",inputHelp:"PersonalCloudProviderShares_inputHelp__KDqPa",viewerRole:"PersonalCloudProviderShares_viewerRole__2RT5B",noEditHint:"PersonalCloudProviderShares_noEditHint__5jcuv",emptyState:"PersonalCloudProviderShares_emptyState__7iKlL",viewerEmpty:"PersonalCloudProviderShares_viewerEmpty__I5ePR",errorBox:"PersonalCloudProviderShares_errorBox__Y7BnC",loadingLine:"PersonalCloudProviderShares_loadingLine__5dZ2T",loadingLineShort:"PersonalCloudProviderShares_loadingLineShort__CMied",pulse:"PersonalCloudProviderShares_pulse__hN35n",modalBody:"PersonalCloudProviderShares_modalBody__Yp6fA",modalAccount:"PersonalCloudProviderShares_modalAccount__8zW4q",modalAccountLabel:"PersonalCloudProviderShares_modalAccountLabel__zSz8C",readOnlyNotice:"PersonalCloudProviderShares_readOnlyNotice__O4gsg",shareForm:"PersonalCloudProviderShares_shareForm__p4mTP",inputLabel:"PersonalCloudProviderShares_inputLabel__5hRNA",inputRow:"PersonalCloudProviderShares_inputRow__5Yzd4",shareInput:"PersonalCloudProviderShares_shareInput__RfEew",viewerBlock:"PersonalCloudProviderShares_viewerBlock__OWaSu",viewerHeading:"PersonalCloudProviderShares_viewerHeading__sDj0L",viewerList:"PersonalCloudProviderShares_viewerList__gHcbG",viewerRow:"PersonalCloudProviderShares_viewerRow__OlmjU",viewerIdentity:"PersonalCloudProviderShares_viewerIdentity__HBkDt",avatar:"PersonalCloudProviderShares_avatar__acZLv",viewerName:"PersonalCloudProviderShares_viewerName__9tkp7",removeButton:"PersonalCloudProviderShares_removeButton__GpaF6"}},43503:(e,t,r)=>{"use strict";r.d(t,{default:()=>h});var n=r(95155),s=r(12115),a=r(35497),i=r(57250),l=r(52679);function o(e,t){return t.find(t=>t.id===e)?.name||e}function d(e){return String(e||"").trim().toLowerCase()}function c(e){return Array.from(new Set((Array.isArray(e)?e:[]).map(e=>String(e||"").trim()).filter(Boolean)))}function m(e){return Array.isArray(e?.importedModels)?e.importedModels:[]}function h(){let[e,t]=(0,s.useState)(!0),[r,h]=(0,s.useState)(!1),[x,u]=(0,s.useState)(""),[p,v]=(0,s.useState)(""),[g,b]=(0,s.useState)(""),[f,y]=(0,s.useState)(!1),[j,N]=(0,s.useState)([]),[k,w]=(0,s.useState)([]),[C,S]=(0,s.useState)(null),[P,A]=(0,s.useState)(null),[I,_]=(0,s.useState)(null),[O,$]=(0,s.useState)(null),[M,E]=(0,s.useState)(""),[T,R]=(0,s.useState)(null),[L,q]=(0,s.useState)([]),[U,B]=(0,s.useState)(!1),[K,z]=(0,s.useState)(""),[F,H]=(0,s.useState)([]),[D,G]=(0,s.useState)(!1),[W,Z]=(0,s.useState)(!1),[J,V]=(0,s.useState)({}),[X,Y]=(0,s.useState)({}),[Q,ee]=(0,s.useState)(""),[et,er]=(0,s.useState)({}),[en,es]=(0,s.useState)(""),[ea,ei]=(0,s.useState)(""),[el,eo]=(0,s.useState)(3),[ed,ec]=(0,s.useState)("3"),[em,eh]=(0,s.useState)(!1),[ex,eu]=(0,s.useState)({}),[ep,ev]=(0,s.useState)(null),[eg,eb]=(0,s.useState)({}),[ef,ey]=(0,s.useState)(""),[ej,eN]=(0,s.useState)(""),[ek,ew]=(0,s.useState)({}),[eC,eS]=(0,s.useState)({}),[eP,eA]=(0,s.useState)(""),[eI,e_]=(0,s.useState)(!1),[eO,e$]=(0,s.useState)(!0),[eM,eE]=(0,s.useState)(null),eT=(0,s.useCallback)(async()=>{t(!0),u("");try{let e=await fetch("/api/personal-cloud-providers",{cache:"no-store"}),t=await e.json().catch(()=>({}));if(!e.ok)throw Error(t.error||"Kh\xf4ng tải được personal cloud providers");b(t.userId||""),y(!0===t.isAdmin),N(t.providers||[]),w(t.connections||[]),e$(!1!==t.globalRtkEnabled),"number"==typeof t.connectionsPerProviderLimit&&t.connectionsPerProviderLimit>0&&eE(t.connectionsPerProviderLimit),ew(t.routing||{}),eS(e=>{let r={...e};for(let[e,n]of Object.entries(t.routing||{}))r[e]={...n};return r}),ee(e=>e||t.userId||"")}catch(e){u(e.message||"Kh\xf4ng tải được personal cloud providers")}finally{t(!1)}},[]),eR=(0,s.useCallback)(e=>{V(e.permissions||{}),Y(e.connectionsByUser||{}),"number"==typeof e.globalConnectionsPerProviderLimit&&e.globalConnectionsPerProviderLimit>0&&(eo(e.globalConnectionsPerProviderLimit),ec(String(e.globalConnectionsPerProviderLimit))),e.connectionsPerProviderLimitOverrides&&"object"==typeof e.connectionsPerProviderLimitOverrides&&eu(e.connectionsPerProviderLimitOverrides)},[]),eL=(0,s.useCallback)(async()=>{if(f){Z(!0);try{let e=await fetch("/api/personal-cloud-providers/permissions",{cache:"no-store"}),t=await e.json().catch(()=>({}));if(!e.ok)throw Error(t.error||"Kh\xf4ng tải được quyền OAuth");eR(t)}catch(e){u(e.message||"Kh\xf4ng tải được quyền OAuth")}finally{Z(!1)}}},[f,eR]);(0,s.useEffect)(()=>{eT()},[eT]),(0,s.useEffect)(()=>{f&&eL()},[f,eL]),(0,s.useEffect)(()=>{let e=()=>{eT()};return window.addEventListener("personal-cloud-refresh",e),()=>window.removeEventListener("personal-cloud-refresh",e)},[eT]),(0,s.useEffect)(()=>{let e=d(Q),t=J[e]||{},r={};for(let e of j)r[e.id]=!0===t[e.id];er(r);let n=ex[e];es(n>0?String(n):"")},[Q,J,j,ex]);let eq=(0,s.useMemo)(()=>{let e=d(T?.ownerUser||g);return e?L.filter(t=>d(t.ownerUser||t.createdByUser||g)===e):[]},[L,T,g]),eU=(0,s.useMemo)(()=>L.find(e=>e.id===K)||null,[L,K]);(0,s.useEffect)(()=>{T&&H(function(e,t){let r=m(e);if(!t)return[];let n=c(t.allowedModels);if(0===n.length)return r.map(e=>e.routeModel).filter(Boolean);let s=new Set(n),a=(0,l.wG)(e?.provider);return r.filter(e=>s.has(e.routeModel)||s.has(`${a}/${e.id}`)).map(e=>e.routeModel).filter(Boolean)}(T,eU))},[T,eU]);let eB=(0,s.useMemo)(()=>{let e=new Map;for(let t of L){let r=String(t.id||"").slice(0,8);e.set(t.id,`${t.name||"API key"}${r?` \xb7 ${r}`:""}`)}return e},[L]),eK=(0,s.useMemo)(()=>{if(!T||!K)return null;let e=k.find(e=>e.id===T.id)||T,t=e.routeApiKeyId||"";if(!t||t===K)return null;let r=d(e.ownerUser||g),n=k.filter(t=>t.id!==e.id&&t.provider===e.provider&&!1!==t.isActive&&d(t.ownerUser||g)===r&&(!t.routeApiKeyId||t.routeApiKeyId===K));return{boundLabel:eB.get(t)||"API key kh\xe1c",alternativesCount:n.length}},[T,K,k,g,eB]),ez=(0,s.useMemo)(()=>Array.from(new Set([...Object.keys(J||{}),...Object.keys(X||{})])).map(e=>{let t=J[e]||{},r=X[e]||{},n=j.filter(e=>t?.[e.id]===!0),s=j.some(e=>(r[e.id]||0)>0);return{userId:e,providerState:t,connectionsByProvider:r,enabledProviders:n,hasAnyConnection:s}}).filter(e=>e.enabledProviders.length>0||e.hasAnyConnection).sort((e,t)=>e.userId.localeCompare(t.userId)),[J,X,j]),eF=async()=>{let e=!!P;S(null),A(null),v(e?"Đ\xe3 reauth th\xe0nh c\xf4ng. Token mới đ\xe3 ghi đ\xe8 l\xean account, t\xean/routing/priority giữ nguy\xean.":"OAuth account đ\xe3 được th\xeam. Model sẽ được import tự động nếu provider hỗ trợ."),await eT()},eH=async(e,t)=>{u(""),v("");try{let r=await fetch(`/api/personal-cloud-providers/${encodeURIComponent(e)}`,{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)}),n=await r.json().catch(()=>({}));if(!r.ok)throw Error(n.error||"Kh\xf4ng cập nhật được connection");await eT()}catch(e){u(e.message||"Kh\xf4ng cập nhật được connection")}},eD=async e=>{u(""),v(""),E(e.id);try{let t=await fetch(`/api/personal-cloud-providers/${encodeURIComponent(e.id)}/import-models`,{method:"POST"}),r=await t.json().catch(()=>({}));if(!t.ok)throw Error(r.error||"Kh\xf4ng import được model");w(t=>t.map(t=>t.id===e.id?{...t,availableModels:r.models||[],importedModels:r.importedModels||[],modelImport:r.modelImport||t.modelImport}:t)),ev(t=>t?.id===e.id?{...t,availableModels:r.models||[],importedModels:r.importedModels||[],modelImport:r.modelImport||t.modelImport}:t);let n=r.modelImport?.source==="provider"?"provider":"catalog fallback";v(`Đ\xe3 cập nhật ${r.models?.length||0} model từ ${n}.`)}catch(e){u(e.message||"Kh\xf4ng import được model")}finally{E("")}},eG=(0,s.useCallback)(async()=>{let e=d(g);if(e){B(!0);try{let t=`&ownerUser=${encodeURIComponent(e)}`,r=await fetch(`/api/keys?pageSize=100&status=active${t}`,{cache:"no-store"}),n=await r.json().catch(()=>({}));if(!r.ok)throw Error(n.error||"Kh\xf4ng tải được API keys");q(Array.isArray(n.keys)?n.keys:[])}catch(e){u(e.message||"Kh\xf4ng tải được API keys")}finally{B(!1)}}},[g]),eW=async e=>{B(!0);try{let t=d(e?.ownerUser||g),r=t?`&ownerUser=${encodeURIComponent(t)}`:"",n=await fetch(`/api/keys?pageSize=100&status=active${r}`,{cache:"no-store"}),s=await n.json().catch(()=>({}));if(!n.ok)throw Error(s.error||"Kh\xf4ng tải được API keys");let a=Array.isArray(s.keys)?s.keys:[];q(a);let i=d(s.userId),l=a.find(e=>d(e.ownerUser||e.createdByUser||i)===t);z(e=>e&&a.some(t=>t.id===e)?e:l?.id||"")}catch(e){u(e.message||"Kh\xf4ng tải được API keys")}finally{B(!1)}};(0,s.useEffect)(()=>{g&&eG()},[g,eG]);let eZ=async e=>{u(""),v(""),R(e),H([]),z(e?.routeApiKeyId||""),await eW(e)},eJ=async()=>{if(!T)return;if(!K)return void u("Chọn API key cần th\xeam model.");let e=c(F);G(!0),u(""),v("");try{let t=await fetch(`/api/personal-cloud-providers/${encodeURIComponent(T.id)}/api-key-models`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiKeyId:K,models:e})}),r=await t.json().catch(()=>({}));if(!t.ok)throw Error(r.error||"Kh\xf4ng cập nhật được model cho API key");let n=r.key;n?.id&&q(e=>e.map(e=>e.id===n.id?{...e,allowedModels:n.allowedModels}:e)),R(null),v(`Đ\xe3 cập nhật API key ${n?.name||""}: cấp th\xeam ${r.addedModels?.length||0}, thu hồi ${r.removedModels?.length||0} model.`)}catch(e){u(e.message||"Kh\xf4ng th\xeam được model v\xe0o API key")}finally{G(!1)}},eV=async()=>{if(O){u(""),v("");try{let e=await fetch(`/api/personal-cloud-providers/${encodeURIComponent(O.id)}`,{method:"DELETE"}),t=await e.json().catch(()=>({}));if(!e.ok)throw Error(t.error||"Kh\xf4ng x\xf3a được connection");v(function(e,t="OAuth connection"){let r=e?.revocation||{};return!0===r.upstreamRevoked?`Đ\xe3 revoke token tại provider v\xe0 x\xf3a ${t} khỏi gateway.`:"unsupported"===r.status?`Đ\xe3 x\xf3a token v\xe0 ${t} khỏi gateway. Provider chưa hỗ trợ revoke tự động; h\xe3y thu hồi thủ c\xf4ng trong phần Security/Connected Apps của provider.`:`Đ\xe3 x\xf3a token v\xe0 ${t} khỏi gateway, nhưng kh\xf4ng x\xe1c nhận được revoke tại provider (${r.error||"unknown error"}). H\xe3y thu hồi thủ c\xf4ng trong phần Security/Connected Apps.`}(t.disconnect,O.name||O.id)),$(null),await eT()}catch(e){u(e.message||"Kh\xf4ng x\xf3a được connection")}}},eX=async(e,t)=>{if(e?.id&&t?.routeModel){u(""),ey(t.routeModel),eb(e=>({...e,[t.routeModel]:{...e[t.routeModel]||{},loading:!0}}));try{let r=`/api/personal-cloud-providers/${encodeURIComponent(e.id)}/models/${t.routeModel.split("/").map(encodeURIComponent).join("/")}`,n=await fetch(r,{method:"POST"}),s=await n.json().catch(()=>({})),a={ok:s?.ok===!0,status:s?.status||n.status,text:s?.text||"",error:s?.error||(n.ok?"":"Test failed"),latencyMs:s?.latencyMs||0};eb(e=>({...e,[t.routeModel]:a}))}catch(e){eb(r=>({...r,[t.routeModel]:{ok:!1,error:e.message||"Test failed"}}))}finally{ey("")}}},eY=async(e,t)=>{if(e?.id&&t?.routeModel&&window.confirm(`X\xf3a model ${t.routeModel} khỏi connection ${e.name||e.id}?`)){u(""),v(""),eN(t.routeModel);try{let r=`/api/personal-cloud-providers/${encodeURIComponent(e.id)}/models/${t.routeModel.split("/").map(encodeURIComponent).join("/")}`,n=await fetch(r,{method:"DELETE"}),s=await n.json().catch(()=>({}));if(!n.ok)throw Error(s?.error||"Kh\xf4ng x\xf3a được model");(e=>{if(!e?.connectionId&&!e?.id)return;let t=e.connectionId||e.id;w(r=>r.map(r=>r.id===t?{...r,importedModels:Array.isArray(e.importedModels)?e.importedModels:r.importedModels,availableModels:Array.isArray(e.models)?e.models:Array.isArray(e.availableModels)?e.availableModels:r.availableModels,modelImport:e.modelImport||r.modelImport}:r)),ev(r=>r?.id===t?{...r,importedModels:Array.isArray(e.importedModels)?e.importedModels:r.importedModels,availableModels:Array.isArray(e.models)?e.models:Array.isArray(e.availableModels)?e.availableModels:r.availableModels,modelImport:e.modelImport||r.modelImport}:r)})(s),eb(e=>{let r={...e};return delete r[t.routeModel],r}),v(`Đ\xe3 x\xf3a model ${t.routeModel}.`)}catch(e){u(e.message||"Kh\xf4ng x\xf3a được model")}finally{eN("")}}},eQ=(e,t)=>{eS(r=>{let n={...r[e]||{},...t};for(let e of Object.keys(n))(""===n[e]||void 0===n[e])&&delete n[e];return{...r,[e]:n}})},e0=async e=>{u(""),v(""),eA(e);try{let t=eC[e]||{},r={providerId:e,override:{fallbackStrategy:t.fallbackStrategy||"",stickyRoundRobinLimit:t.stickyRoundRobinLimit,stickyScope:t.stickyScope||"",stickyTtlMinutes:t.stickyTtlMinutes,stickyFallbackToClientIp:t.stickyFallbackToClientIp,stickyRebindOnFailure:t.stickyRebindOnFailure,stickyRebindFailureThreshold:t.stickyRebindFailureThreshold}},n=await fetch("/api/personal-cloud-providers/routing",{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify(r)}),s=await n.json().catch(()=>({}));if(!n.ok)throw Error(s?.error||"Kh\xf4ng lưu được routing");ew(s.routing||{}),v(`Đ\xe3 cập nhật routing cho ${e}.`)}catch(e){u(e.message||"Kh\xf4ng lưu được routing")}finally{eA("")}},e3=async e=>{u(""),v(""),eA(e);try{let t=await fetch(`/api/personal-cloud-providers/routing?providerId=${encodeURIComponent(e)}`,{method:"DELETE"}),r=await t.json().catch(()=>({}));if(!t.ok)throw Error(r?.error||"Kh\xf4ng reset được routing");ew(r.routing||{}),eS(t=>{let r={...t};return delete r[e],r}),v(`Đ\xe3 reset ${e} về ch\xednh s\xe1ch mặc định.`)}catch(e){u(e.message||"Kh\xf4ng reset được routing")}finally{eA("")}},e1=async()=>{let e,t=d(Q);if(!t)return void u("Nhập username/email cần cấp quyền.");let r=String(en||"").trim();if(""===r)e=null;else{let t=Number.parseInt(r,10);if(!Number.isFinite(t)||t<=0)return void u("Per-user override giới hạn phải l\xe0 số nguy\xean dương hoặc bỏ trống.");e=t}h(!0),u(""),v("");try{let r=await fetch("/api/personal-cloud-providers/permissions",{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify({userId:t,providers:et,connectionsPerProviderLimit:e})}),n=await r.json().catch(()=>({}));if(!r.ok)throw Error(n.error||"Kh\xf4ng lưu được quyền OAuth");eR(n);let s=n.user?.id||t;s!==t&&ee(s),v(`Đ\xe3 lưu quyền OAuth cho ${s}.`),await eT()}catch(e){u(e.message||"Kh\xf4ng lưu được quyền OAuth")}finally{h(!1)}},e2=async()=>{let e=Number.parseInt(ed,10);if(!Number.isFinite(e)||e<=0)return void u("Global limit phải l\xe0 số nguy\xean dương.");eh(!0),u(""),v("");try{let t=await fetch("/api/personal-cloud-providers/permissions",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({globalConnectionsPerProviderLimit:e})}),r=await t.json().catch(()=>({}));if(!t.ok)throw Error(r.error||"Kh\xf4ng lưu được global limit");eR(r),v(`Đ\xe3 đặt global limit = ${e} account / provider / user.`)}catch(e){u(e.message||"Kh\xf4ng lưu được global limit")}finally{eh(!1)}},e4=async e=>{let t=d(e);if(t){h(!0),u(""),v("");try{let e=await fetch(`/api/personal-cloud-providers/permissions?userId=${encodeURIComponent(t)}`,{method:"DELETE"}),r=await e.json().catch(()=>({}));if(!e.ok)throw Error(r.error||"Kh\xf4ng thu hồi được quyền OAuth");eR(r),d(Q)===t&&ee("");let n=r.disconnectSummary||{},s=Number(n.manualActionRequired)||0;v(`Đ\xe3 x\xf3a ${n.deletedCount||0} OAuth connection của ${t} khỏi gateway; ${n.upstreamRevokedCount||0} token đ\xe3 được revoke tại provider.${s>0?` ${s} connection cần kiểm tra/thu hồi thủ c\xf4ng tại provider.`:""}`),ei(""),await eT()}catch(e){u(e.message||"Kh\xf4ng thu hồi được quyền OAuth")}finally{h(!1)}}},e5=C?function(e={}){return{id:e.id,name:e.name||e.id,icon:e.icon||"cloud",color:e.color||"#64748b",website:e.website||"",notice:e.notice||null,deprecationNotice:e.deprecationNotice||"",serviceKinds:e.serviceKinds||["llm"]}}(C):null,e6=f?j:j.filter(e=>e.enabled),e7=m(T),e8=T?.modelImport||{},e9=m(ep),te=ez.find(e=>e.userId===d(ea)),tt=j.reduce((e,t)=>e+Number(te?.connectionsByProvider?.[t.id]||0),0);return(0,n.jsxs)("div",{className:"space-y-6",children:[(0,n.jsx)("div",{children:(0,n.jsxs)("div",{className:"flex flex-col gap-3 md:flex-row md:items-start md:justify-between",children:[(0,n.jsxs)("div",{children:[(0,n.jsx)("h1",{className:"text-2xl font-semibold text-text-main",children:"Personal Cloud Providers"}),(0,n.jsx)("p",{className:"mt-1 text-sm text-text-muted",children:"Kết nối OAuth c\xe1 nh\xe2n cho Claude Code, OpenAI Codex v\xe0 Antigravity. Account c\xe1 nh\xe2n chỉ owner v\xe0 quản trị vi\xean c\xf3 thẩm quyền nh\xecn thấy; chỉ API key của owner được d\xf9ng. Tắt Active chỉ tạm ngưng v\xe0 vẫn giữ token. Reauth cho ph\xe9p OAuth lại đ\xfang account đ\xf3 khi token hết hạn — ghi đ\xe8 token mới, giữ nguy\xean t\xean/routing/priority (khỏi phải revoke rồi add lại). Delete sẽ thử revoke tại provider rồi x\xf3a token/connection local. Cột RTK cho ph\xe9p override ri\xeang từng account (Lu\xf4n ON / Lu\xf4n OFF) bất kể cấu h\xecnh RTK global ở /dashboard/endpoint đang on hay off — để trống th\xec theo global."})]}),(0,n.jsxs)("div",{className:"rounded-2xl border border-border bg-surface px-4 py-3 text-sm",children:[(0,n.jsx)("div",{className:"text-xs uppercase tracking-wide text-text-muted",children:"Current user"}),(0,n.jsx)("div",{className:"mt-1 break-all font-mono text-text-main",children:g||"—"}),f||null===eM?null:(0,n.jsxs)("div",{className:"mt-2 border-t border-border pt-2 text-xs text-text-muted",children:["Giới hạn: ",(0,n.jsx)("span",{className:"font-semibold text-text-main",children:eM})," account / provider"]})]})]})}),x?(0,n.jsx)("div",{className:"rounded-2xl border border-red-500/30 bg-red-500/10 px-4 py-3 text-sm text-red-700 dark:text-red-300",children:x}):null,p?(0,n.jsx)("div",{className:"rounded-2xl border border-green-500/30 bg-green-500/10 px-4 py-3 text-sm text-green-700 dark:text-green-300",children:p}):null,(0,n.jsx)("div",{className:"grid gap-4 lg:grid-cols-3",children:0===j.length?(0,n.jsx)("div",{className:"rounded-2xl border border-dashed border-border p-8 text-center text-sm text-text-muted lg:col-span-3",children:"Admin chưa cấp quyền personal OAuth provider n\xe0o cho user n\xe0y."}):j.map(e=>{let t=k.filter(t=>t.provider===e.id).length,r=!f&&null!==eM&&e.enabled,s=r&&t>=eM;return(0,n.jsxs)(a.Zp,{className:"space-y-4",children:[(0,n.jsxs)("div",{className:"flex items-start gap-3",children:[(0,n.jsx)("span",{className:"inline-flex size-10 shrink-0 items-center justify-center rounded-xl",style:{backgroundColor:`${e.color||"#64748b"}22`},children:(0,n.jsx)(i.A,{src:`/providers/${e.id}.png`,alt:e.name,size:34,className:"max-h-[34px] max-w-[34px] rounded-lg object-contain",fallbackText:e.id.slice(0,2).toUpperCase(),fallbackColor:e.color||"#64748b"})}),(0,n.jsxs)("div",{className:"min-w-0 flex-1",children:[(0,n.jsxs)("div",{className:"flex flex-wrap items-center gap-2",children:[(0,n.jsx)("h2",{className:"font-semibold text-text-main",children:e.name}),e.enabled?(0,n.jsx)(a.Ex,{variant:"success",size:"sm",children:"Enabled"}):(0,n.jsx)(a.Ex,{variant:"warning",size:"sm",children:"Locked"}),r?(0,n.jsxs)(a.Ex,{variant:s?"error":"default",size:"sm",title:"Số account OAuth c\xe1 nh\xe2n bạn c\xf3 thể add cho provider n\xe0y",children:[t,"/",eM]}):null]}),(0,n.jsx)("p",{className:"mt-1 text-xs text-text-muted",children:e.enabled?"Được admin cấp quyền, c\xf3 thể add OAuth account c\xe1 nh\xe2n.":"Admin chưa cấp quyền cho user n\xe0y."})]})]}),e.deprecationNotice?(0,n.jsx)("p",{className:"rounded-xl border border-amber-500/30 bg-amber-500/10 p-3 text-xs text-amber-700 dark:text-amber-300",children:e.deprecationNotice}):null,(0,n.jsx)(a.$n,{fullWidth:!0,disabled:!e.enabled||s,onClick:()=>{e.enabled&&_(e)},icon:"add_link",children:s?`Đ\xe3 đạt giới hạn ${eM} account`:`Add ${e.name} account`})]},e.id)})}),(0,n.jsxs)(a.Zp,{className:"space-y-4",children:[(0,n.jsxs)("div",{className:"flex flex-col gap-2 md:flex-row md:items-center md:justify-between",children:[(0,n.jsxs)("div",{children:[(0,n.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"My personal accounts"}),(0,n.jsx)("p",{className:"text-sm text-text-muted",children:"OAuth xong sẽ tự import model nếu provider hỗ trợ. Nếu kh\xf4ng gọi được endpoint model, hệ thống d\xf9ng catalog fallback để user vẫn chọn được model."})]}),(0,n.jsx)(a.$n,{variant:"outline",size:"sm",onClick:eT,loading:e,icon:"refresh",children:"Refresh"})]}),e?(0,n.jsx)("div",{className:"rounded-2xl border border-dashed border-border p-8 text-center text-sm text-text-muted",children:"Đang tải..."}):0===k.length?(0,n.jsx)("div",{className:"rounded-2xl border border-dashed border-border p-8 text-center text-sm text-text-muted",children:"Chưa c\xf3 personal OAuth account n\xe0o."}):(0,n.jsx)("div",{className:"overflow-x-auto rounded-2xl border border-border",children:(0,n.jsxs)("table",{className:"min-w-full divide-y divide-border text-sm",children:[(0,n.jsx)("thead",{className:"bg-surface/80 text-left text-xs uppercase tracking-wide text-text-muted",children:(0,n.jsxs)("tr",{children:[(0,n.jsx)("th",{className:"px-4 py-3 font-medium",children:"Connection"}),(0,n.jsx)("th",{className:"px-4 py-3 font-medium",children:"Provider"}),(0,n.jsx)("th",{className:"px-4 py-3 font-medium",children:"Account"}),(0,n.jsx)("th",{className:"px-4 py-3 font-medium",children:"Models"}),(0,n.jsx)("th",{className:"px-4 py-3 font-medium",children:"Created"}),(0,n.jsx)("th",{className:"px-4 py-3 font-medium",children:"API key routing"}),(0,n.jsx)("th",{className:"px-4 py-3 font-medium",title:"Tắt = tạm ngưng sử dụng, token vẫn được giữ",children:"Active (tạm ngưng)"}),(0,n.jsx)("th",{className:"px-4 py-3 font-medium",children:(0,n.jsxs)("span",{className:"inline-flex items-center gap-1.5",children:["RTK (Token Savings)",(0,n.jsxs)(a.Ex,{variant:eO?"success":"default",size:"sm",className:"normal-case",children:["Global: ",eO?"ON":"OFF"]}),(0,n.jsx)("button",{type:"button",onClick:()=>e_(!0),title:"RTK l\xe0 g\xec? Bấm để xem giải th\xedch",className:"inline-flex size-4 shrink-0 items-center justify-center rounded-full border border-border text-[10px] font-bold normal-case text-text-muted transition-colors hover:border-brand-500 hover:text-brand-600",children:"?"})]})}),(0,n.jsx)("th",{className:"px-4 py-3 text-right font-medium",children:"Actions"})]})}),(0,n.jsx)("tbody",{className:"divide-y divide-border bg-background",children:k.map(e=>{let t=Array.isArray(e?.availableModels)?e.availableModels:[],r=e.modelImport||{};return(0,n.jsxs)("tr",{className:"align-top hover:bg-surface/50",children:[(0,n.jsxs)("td",{className:"px-4 py-4",children:[(0,n.jsx)("div",{className:"font-medium text-text-main",children:e.name||e.id}),(0,n.jsx)("div",{className:"mt-1 font-mono text-xs text-text-muted",children:e.id})]}),(0,n.jsx)("td",{className:"px-4 py-4",children:(0,n.jsxs)("div",{className:"flex items-center gap-2",children:[(0,n.jsx)(i.A,{src:`/providers/${e.provider}.png`,alt:e.provider,size:24,className:"max-h-[24px] max-w-[24px] rounded object-contain",fallbackText:e.provider.slice(0,2).toUpperCase()}),(0,n.jsx)("span",{children:o(e.provider,j)})]})}),(0,n.jsxs)("td",{className:"px-4 py-4",children:[(0,n.jsx)("div",{className:"break-all text-text-main",children:function(e={}){let t=e.providerSpecificData&&"object"==typeof e.providerSpecificData?e.providerSpecificData:{};return e.email||t.email||t.preferredUsername||t.githubEmail||t.githubLogin||e.displayName||t.sub||t.accountId||t.claudeAccountId||t.chatgptAccountId||"—"}(e)}),(0,n.jsxs)("div",{className:"mt-1 break-all text-xs text-text-muted",children:["Owner: ",e.ownerUser||g||"—"]})]}),(0,n.jsxs)("td",{className:"px-4 py-4",children:[(0,n.jsxs)("div",{className:"flex flex-wrap items-center gap-2",children:[function(e={}){return"provider"===(e.source||"catalog")?(0,n.jsx)(a.Ex,{variant:"success",size:"sm",children:"Imported"}):(0,n.jsx)(a.Ex,{variant:"warning",size:"sm",children:"Catalog"})}(r),(0,n.jsxs)("span",{className:"text-xs text-text-muted",children:[t.length," model(s)"]})]}),r.warning?(0,n.jsx)("div",{className:"mt-1 max-w-[320px] truncate text-xs text-amber-600 dark:text-amber-300",title:r.warning,children:r.warning}):null,t.length>0?(0,n.jsxs)("div",{className:"mt-2 flex max-w-[360px] flex-wrap gap-1",children:[t.slice(0,4).map(e=>(0,n.jsx)("span",{className:"rounded-full border border-border bg-surface px-2 py-0.5 font-mono text-[11px] text-text-muted",children:e.routeModel},e.routeModel)),t.length>4?(0,n.jsxs)("span",{className:"rounded-full border border-border bg-surface px-2 py-0.5 text-[11px] text-text-muted",children:["+",t.length-4]}):null]}):null]}),(0,n.jsx)("td",{className:"px-4 py-4 text-xs text-text-muted",children:function(e){if(!e)return"—";try{return new Intl.DateTimeFormat("vi-VN",{dateStyle:"short",timeStyle:"short"}).format(new Date(e))}catch{return e}}(e.createdAt)}),(0,n.jsx)("td",{className:"px-4 py-4",children:(0,n.jsxs)("div",{className:"min-w-[220px] space-y-1",children:[(0,n.jsxs)("select",{value:e.routeApiKeyId||"",onChange:t=>eH(e.id,{routeApiKeyId:t.target.value||null}),disabled:U||d(e.ownerUser||g)!==d(g),className:"h-9 w-full rounded-xl border border-border bg-background px-2 text-xs text-text-main outline-none focus:border-brand-500 disabled:opacity-60",children:[(0,n.jsx)("option",{value:"",children:"Shared across my API keys"}),L.filter(t=>d(t.ownerUser||t.createdByUser||g)===d(e.ownerUser||g)).map(e=>(0,n.jsx)("option",{value:e.id,children:e.name||e.id},e.id))]}),(0,n.jsx)("div",{className:"text-[11px] text-text-muted",children:e.routeApiKeyId?`Only ${eB.get(e.routeApiKeyId)||"selected API key"} can use this account.`:"Unassigned accounts remain shared fallback for your eligible API keys."})]})}),(0,n.jsx)("td",{className:"px-4 py-4",children:(0,n.jsx)(a.lM,{checked:!1!==e.isActive,onChange:t=>eH(e.id,{isActive:t})})}),(0,n.jsx)("td",{className:"px-4 py-4",children:(0,n.jsxs)("select",{value:!0===e.rtkEnabled?"on":!1===e.rtkEnabled?"off":"inherit",onChange:t=>{let r=t.target.value;eH(e.id,{rtkEnabled:"inherit"===r?null:"on"===r})},className:"h-9 w-full min-w-[140px] rounded-xl border border-border bg-background px-2 text-xs text-text-main outline-none focus:border-brand-500",children:[(0,n.jsx)("option",{value:"inherit",children:"Theo global"}),(0,n.jsx)("option",{value:"on",children:"Lu\xf4n ON"}),(0,n.jsx)("option",{value:"off",children:"Lu\xf4n OFF"})]})}),(0,n.jsx)("td",{className:"px-4 py-4",children:(0,n.jsxs)("div",{className:"flex flex-wrap justify-end gap-2",children:[(0,n.jsx)(a.$n,{variant:"outline",size:"sm",loading:M===e.id,onClick:()=>eD(e),children:"Import models"}),(0,n.jsx)(a.$n,{variant:"outline",size:"sm",disabled:0===m(e).length,onClick:()=>{u(""),v(""),ev(e),eb({}),ey(""),eN("")},children:"Manage models"}),(0,n.jsx)(a.$n,{variant:"secondary",size:"sm",disabled:0===m(e).length,onClick:()=>eZ(e),children:"Add models to API key"}),(0,n.jsx)(a.$n,{variant:"outline",size:"sm",onClick:()=>{let t;return t=window.prompt("T\xean connection mới",e.name||""),void(t?.trim()&&eH(e.id,{name:t.trim()}))},children:"Rename"}),(0,n.jsx)(a.$n,{variant:"outline",size:"sm",icon:"autorenew",title:"OAuth lại account n\xe0y khi token hết hạn — token mới sẽ ghi đ\xe8, giữ nguy\xean t\xean/routing/priority",onClick:()=>{let t;!(t=j.find(t=>t.id===e.provider))?u("Provider kh\xf4ng c\xf2n khả dụng, kh\xf4ng thể reauth."):(u(""),v(""),A(e),S(t))},children:"Reauth"}),(0,n.jsx)(a.$n,{variant:"danger",size:"sm",onClick:()=>$(e),children:"Revoke & delete"})]})})]},e.id)})})]})})]}),(0,n.jsxs)(a.Zp,{className:"space-y-4",children:[(0,n.jsxs)("div",{children:[(0,n.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"Routing strategy"}),(0,n.jsxs)("p",{className:"text-sm text-text-muted",children:["Khi bạn c\xf3 nhiều personal account cho c\xf9ng provider, đ\xe2y l\xe0 ch\xednh s\xe1ch chọn account cho từng request. Để trống = kế thừa ch\xednh s\xe1ch của admin ở ",(0,n.jsx)("span",{className:"font-mono",children:"/dashboard/providers/<provider>"}),"."]})]}),(0,n.jsx)("div",{className:"grid gap-4 lg:grid-cols-3",children:0===e6.length?(0,n.jsx)("div",{className:"rounded-2xl border border-dashed border-border p-6 text-center text-sm text-text-muted lg:col-span-3",children:"Bạn chưa được cấp quyền provider n\xe0o, n\xean chưa cần thiết lập routing."}):e6.map(e=>{let t=eC[e.id]||{},r=ek[e.id]||null,s=!r,i=t.fallbackStrategy||"",l="round-robin"===i,o=eP===e.id;return(0,n.jsxs)("div",{className:"rounded-2xl border border-border bg-surface p-4 space-y-3",children:[(0,n.jsxs)("div",{className:"flex items-center justify-between gap-2",children:[(0,n.jsxs)("div",{className:"min-w-0",children:[(0,n.jsx)("div",{className:"font-semibold text-text-main",children:e.name}),(0,n.jsx)("div",{className:"text-xs text-text-muted",children:s?"Đang kế thừa policy global":`Override active: ${r.fallbackStrategy||"inherit"}`})]}),s?(0,n.jsx)(a.Ex,{variant:"default",size:"sm",children:"Inherit"}):(0,n.jsx)(a.Ex,{variant:"success",size:"sm",children:"Override"})]}),(0,n.jsxs)("label",{className:"block text-sm",children:[(0,n.jsx)("span",{className:"mb-1 block font-medium text-text-main",children:"Strategy"}),(0,n.jsxs)("select",{value:i,onChange:t=>eQ(e.id,{fallbackStrategy:t.target.value}),className:"h-10 w-full rounded-xl border border-border bg-background px-3 text-sm text-text-main outline-none focus:border-brand-500",disabled:o,children:[(0,n.jsx)("option",{value:"",children:"Inherit (use global)"}),(0,n.jsx)("option",{value:"fill-first",children:"fill-first — chạy hết account 1 mới sang account 2"}),(0,n.jsx)("option",{value:"round-robin",children:"round-robin — lu\xe2n phi\xean theo sticky limit"}),(0,n.jsx)("option",{value:"least-latency",children:"least-latency — chọn account nhanh nhất"}),(0,n.jsx)("option",{value:"p2c",children:"p2c — power-of-two-choices"})]})]}),l?(0,n.jsxs)("div",{className:"space-y-2 rounded-xl border border-border/50 bg-background/50 p-3",children:[(0,n.jsx)("div",{className:"text-xs text-text-muted",children:"Round-robin sticky params (để trống = d\xf9ng gi\xe1 trị global)"}),(0,n.jsxs)("label",{className:"block text-xs",children:[(0,n.jsx)("span",{className:"mb-1 block text-text-muted",children:"Sticky limit (số request li\xean tiếp trước khi rotate)"}),(0,n.jsx)(a.pd,{type:"number",min:1,value:t.stickyRoundRobinLimit??"",onChange:t=>eQ(e.id,{stickyRoundRobinLimit:t.target.value?Number(t.target.value):void 0}),placeholder:"v\xed dụ 3",disabled:o})]}),(0,n.jsxs)("label",{className:"block text-xs",children:[(0,n.jsx)("span",{className:"mb-1 block text-text-muted",children:"Sticky scope"}),(0,n.jsxs)("select",{value:t.stickyScope||"",onChange:t=>eQ(e.id,{stickyScope:t.target.value}),className:"h-9 w-full rounded-xl border border-border bg-background px-3 text-xs text-text-main outline-none focus:border-brand-500",disabled:o,children:[(0,n.jsx)("option",{value:"",children:"(inherit)"}),(0,n.jsx)("option",{value:"global",children:"global — rotate cho mọi request"}),(0,n.jsx)("option",{value:"client_ip",children:"client_ip — sticky theo IP"}),(0,n.jsx)("option",{value:"client_session",children:"client_session — sticky theo CLI session"})]})]}),(0,n.jsxs)("label",{className:"block text-xs",children:[(0,n.jsx)("span",{className:"mb-1 block text-text-muted",children:"Sticky TTL (ph\xfat)"}),(0,n.jsx)(a.pd,{type:"number",min:1,value:t.stickyTtlMinutes??"",onChange:t=>eQ(e.id,{stickyTtlMinutes:t.target.value?Number(t.target.value):void 0}),placeholder:"v\xed dụ 120",disabled:o})]})]}):null,(0,n.jsxs)("div",{className:"flex flex-wrap gap-2 pt-1",children:[(0,n.jsx)(a.$n,{size:"sm",loading:o,onClick:()=>e0(e.id),children:"Save"}),(0,n.jsx)(a.$n,{size:"sm",variant:"ghost",disabled:o||s,onClick:()=>e3(e.id),children:"Reset to inherit"})]})]},e.id)})})]}),f?(0,n.jsxs)(a.Zp,{className:"space-y-4",children:[(0,n.jsxs)("div",{children:[(0,n.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"Admin: OAuth provider access"}),(0,n.jsx)("p",{className:"text-sm text-text-muted",children:"Default l\xe0 kh\xf4ng c\xf3 quyền. Tắt provider chỉ tạm ngưng connection v\xe0 giữ token để c\xf3 thể bật lại. N\xfat Revoke all sẽ thử revoke upstream rồi x\xf3a to\xe0n bộ connection/token local của user."})]}),(0,n.jsxs)("div",{className:"rounded-2xl border border-border bg-surface p-4",children:[(0,n.jsx)("div",{className:"text-sm font-medium",children:"Global limit — số account OAuth c\xe1 nh\xe2n / provider / user thường"}),(0,n.jsx)("p",{className:"mt-1 text-xs text-text-muted",children:"\xc1p dụng cho user kh\xf4ng c\xf3 per-user override. Admin kh\xf4ng bị chặn bởi limit n\xe0y."}),(0,n.jsxs)("div",{className:"mt-3 flex flex-col gap-2 sm:flex-row sm:items-end",children:[(0,n.jsx)(a.pd,{type:"number",min:1,value:ed,onChange:e=>ec(e.target.value),className:"sm:w-48"}),(0,n.jsx)(a.$n,{onClick:e2,loading:em,disabled:em||Number.parseInt(ed,10)===el,children:"Lưu global"}),(0,n.jsxs)("span",{className:"text-xs text-text-muted",children:["Đang lưu: ",el]})]})]}),(0,n.jsxs)("div",{className:"grid gap-3 md:grid-cols-[minmax(0,1fr)_auto] md:items-end",children:[(0,n.jsx)(a.pd,{label:"User ID / Email",value:Q,onChange:e=>ee(e.target.value),placeholder:"anh-tct hoặc anh-tct@fujinet.net"}),(0,n.jsx)(a.$n,{onClick:e1,loading:r,icon:"save",children:"Save permissions"})]}),(0,n.jsx)("div",{className:"grid gap-3 md:grid-cols-3",children:j.map(e=>(0,n.jsx)("div",{className:"rounded-2xl border border-border bg-surface p-4",children:(0,n.jsx)(a.lM,{checked:!0===et[e.id],onChange:t=>er(r=>({...r,[e.id]:t})),label:e.name,description:et[e.id]?"User được ph\xe9p add account":"User chưa được cấp quyền"})},e.id))}),(0,n.jsxs)("div",{className:"rounded-2xl border border-border bg-surface p-4",children:[(0,n.jsx)("div",{className:"text-sm font-medium",children:"Per-user override — account / provider"}),(0,n.jsxs)("p",{className:"mt-1 text-xs text-text-muted",children:["Ghi đ\xe8 global cho ",(0,n.jsx)("span",{className:"font-mono",children:d(Q)||"user đang chọn"}),". Để trống rồi Save permissions để bỏ override v\xe0 quay lại global (",el,")."]}),(0,n.jsx)("div",{className:"mt-3 max-w-xs",children:(0,n.jsx)(a.pd,{type:"number",min:1,value:en,onChange:e=>es(e.target.value),placeholder:`Để trống = d\xf9ng global (${el})`})})]}),(0,n.jsxs)("div",{className:"border-t border-border pt-4",children:[(0,n.jsxs)("div",{className:"mb-3 flex flex-col gap-2 md:flex-row md:items-center md:justify-between",children:[(0,n.jsxs)("div",{children:[(0,n.jsx)("h3",{className:"font-semibold text-text-main",children:"Granted OAuth Access"}),(0,n.jsx)("p",{className:"text-xs text-text-muted",children:"Danh s\xe1ch user hiện đang được cấp quyền add personal OAuth account."})]}),(0,n.jsx)(a.$n,{variant:"outline",size:"sm",onClick:eL,loading:W,icon:"refresh",children:"Refresh list"})]}),W?(0,n.jsx)("div",{className:"rounded-2xl border border-dashed border-border p-6 text-center text-sm text-text-muted",children:"Đang tải quyền..."}):0===ez.length?(0,n.jsx)("div",{className:"rounded-2xl border border-dashed border-border p-6 text-center text-sm text-text-muted",children:"Chưa c\xf3 user n\xe0o được cấp quyền OAuth provider."}):(0,n.jsx)("div",{className:"overflow-x-auto rounded-2xl border border-border",children:(0,n.jsxs)("table",{className:"min-w-full divide-y divide-border text-sm",children:[(0,n.jsx)("thead",{className:"bg-surface/80 text-left text-xs uppercase tracking-wide text-text-muted",children:(0,n.jsxs)("tr",{children:[(0,n.jsx)("th",{className:"px-4 py-3 font-medium",children:"User"}),j.map(e=>(0,n.jsx)("th",{className:"px-4 py-3 font-medium",children:e.name},e.id)),(0,n.jsx)("th",{className:"px-4 py-3 font-medium",title:"Số account OAuth tối đa cho mỗi provider m\xe0 user được add",children:"Limit / provider"}),(0,n.jsx)("th",{className:"px-4 py-3 text-right font-medium",children:"Actions"})]})}),(0,n.jsx)("tbody",{className:"divide-y divide-border bg-background",children:ez.map(e=>(0,n.jsxs)("tr",{className:"hover:bg-surface/50",children:[(0,n.jsxs)("td",{className:"px-4 py-4",children:[(0,n.jsx)("div",{className:"break-all font-mono text-text-main",children:e.userId}),d(Q)===e.userId?(0,n.jsx)("div",{className:"mt-1 text-xs text-brand-600 dark:text-brand-300",children:"Đang edit ở form ph\xeda tr\xean"}):null]}),j.map(t=>{let r=!0===e.providerState[t.id],s=e.connectionsByProvider?.[t.id]||0,l=s>0;return(0,n.jsx)("td",{className:"px-4 py-4",children:(0,n.jsxs)("div",{className:"flex items-center gap-1.5",children:[r?(0,n.jsx)(a.Ex,{variant:"success",size:"sm",children:"ON"}):(0,n.jsx)(a.Ex,{variant:"default",size:"sm",children:"OFF"}),l?(0,n.jsxs)("span",{className:"inline-flex items-center gap-0.5",title:`User đ\xe3 add ${s} ${t.name} account${s>1?"s":""}`,children:[(0,n.jsx)(i.A,{src:`/providers/${t.id}.png`,alt:t.name,size:16,className:"max-h-[16px] max-w-[16px] rounded object-contain",fallbackText:t.id.slice(0,2).toUpperCase(),fallbackColor:t.color||"#64748b"}),s>1?(0,n.jsxs)("span",{className:"text-[10px] font-semibold text-text-muted",children:["\xd7",s]}):null]}):null]})},t.id)}),(0,n.jsx)("td",{className:"px-4 py-4 text-xs",children:ex[e.userId]>0?(0,n.jsxs)("span",{className:"inline-flex items-center gap-1",children:[(0,n.jsx)(a.Ex,{variant:"warning",size:"sm",children:"Override"}),(0,n.jsx)("span",{className:"font-mono",children:ex[e.userId]})]}):(0,n.jsxs)("span",{className:"text-text-muted",children:["Global \xb7 ",el]})}),(0,n.jsx)("td",{className:"px-4 py-4",children:(0,n.jsxs)("div",{className:"flex flex-wrap justify-end gap-2",children:[(0,n.jsx)(a.$n,{variant:"outline",size:"sm",onClick:()=>(e=>{let t=d(e);ee(t);let r=J[t]||{},n={};for(let e of j)n[e.id]=!0===r[e.id];er(n)})(e.userId),children:"Edit"}),(0,n.jsx)(a.$n,{variant:"danger",size:"sm",loading:r&&ea===e.userId,onClick:()=>ei(e.userId),children:"Revoke all & delete"})]})})]},e.userId))})]})})]})]}):null,T?(0,n.jsx)(a.aF,{isOpen:!!T,onClose:()=>R(null),title:"Add models to API key",size:"full",footer:(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(a.$n,{variant:"ghost",onClick:()=>R(null),disabled:D,children:"Cancel"}),(0,n.jsx)(a.$n,{onClick:eJ,loading:D,disabled:!K,children:"Save"})]}),children:(0,n.jsxs)("div",{className:"space-y-4",children:[(0,n.jsxs)("div",{className:"rounded-2xl border border-border bg-surface p-4 text-sm",children:[(0,n.jsx)("div",{className:"font-semibold text-text-main",children:T.name||T.id}),(0,n.jsxs)("div",{className:"mt-1 text-text-muted",children:[o(T.provider,j)," \xb7 ",e7.length," imported model(s)"]}),e8.warning?(0,n.jsx)("div",{className:"mt-2 text-xs text-amber-600 dark:text-amber-300",children:e8.warning}):null,0===e7.length?(0,n.jsx)("div",{className:"mt-2 rounded-xl border border-amber-500/30 bg-amber-500/10 p-3 text-xs text-amber-700 dark:text-amber-300",children:'Chưa import được model n\xe0o từ provider. Bấm "Import models" tr\xean d\xf2ng connection trước khi g\xe1n v\xe0o API key.'}):null]}),(0,n.jsxs)("label",{className:"block text-sm",children:[(0,n.jsx)("span",{className:"mb-1 block font-medium text-text-main",children:"API key"}),(0,n.jsxs)("select",{value:K,onChange:e=>z(e.target.value),className:"h-10 w-full rounded-xl border border-border bg-background px-3 text-sm text-text-main outline-none focus:border-brand-500",disabled:U,children:[(0,n.jsx)("option",{value:"",children:U?"Đang tải API keys...":"Chọn API key"}),eq.map(e=>(0,n.jsxs)("option",{value:e.id,children:[e.name," \xb7 ",e.ownerUser||g]},e.id))]})]}),eK?(0,n.jsxs)("div",{className:"rounded-xl border border-amber-500/30 bg-amber-500/10 p-3 text-sm text-amber-700 dark:text-amber-300",children:["Account n\xe0y đang được g\xe1n ri\xeang cho ",(0,n.jsx)("span",{className:"font-semibold",children:eK.boundLabel})," (API key routing). API key đang chọn vẫn được cấp quyền model, nhưng request của n\xf3 sẽ ",(0,n.jsx)("span",{className:"font-semibold",children:"kh\xf4ng"})," route qua account n\xe0y.",eK.alternativesCount>0?` Request sẽ chạy qua ${eK.alternativesCount} account ${o(T.provider,j)} kh\xe1c m\xe0 key n\xe0y được d\xf9ng.`:` Hiện kh\xf4ng c\xf3 account ${o(T.provider,j)} n\xe0o kh\xe1c m\xe0 key n\xe0y được d\xf9ng, n\xean request sẽ lỗi "No credentials" d\xf9 đ\xe3 c\xf3 quyền model.`]}):null,0!==eq.length||U?null:(0,n.jsx)("div",{className:"rounded-xl border border-amber-500/30 bg-amber-500/10 p-3 text-sm text-amber-700 dark:text-amber-300",children:"User n\xe0y chưa c\xf3 API key active để th\xeam model."}),(0,n.jsxs)("div",{className:"flex items-center justify-between gap-2",children:[(0,n.jsxs)("div",{children:[(0,n.jsx)("h3",{className:"font-semibold text-text-main",children:"Models"}),(0,n.jsx)("p",{className:"text-xs text-text-muted",children:"Model đ\xe3 tick = API key đang được ph\xe9p d\xf9ng. Tick để cấp quyền, bỏ tick để thu hồi. Request sẽ route qua personal OAuth account của owner."}),eU&&0===c(eU.allowedModels).length?(0,n.jsx)("p",{className:"mt-1 text-xs text-amber-600 dark:text-amber-300",children:"API key n\xe0y đang full access (kh\xf4ng giới hạn model). Bấm Save sẽ giới hạn key chỉ c\xf2n c\xe1c model được tick."}):null]}),(0,n.jsxs)("div",{className:"flex gap-2",children:[(0,n.jsx)(a.$n,{variant:"outline",size:"sm",onClick:()=>H(e7.map(e=>e.routeModel).filter(Boolean)),children:"Select all"}),(0,n.jsx)(a.$n,{variant:"ghost",size:"sm",onClick:()=>H([]),children:"Clear"})]})]}),(0,n.jsx)("div",{className:"grid gap-2 md:grid-cols-2",children:e7.map(e=>(0,n.jsxs)("label",{className:"flex cursor-pointer items-start gap-3 rounded-xl border border-border bg-background p-3 hover:bg-surface",children:[(0,n.jsx)("input",{type:"checkbox",className:"mt-1",checked:F.includes(e.routeModel),onChange:()=>{var t;return t=e.routeModel,void H(e=>e.includes(t)?e.filter(e=>e!==t):[...e,t])}}),(0,n.jsxs)("span",{className:"min-w-0 flex-1",children:[(0,n.jsx)("span",{className:"block font-medium text-text-main",children:e.name||e.id}),(0,n.jsx)("span",{className:"mt-1 block break-all font-mono text-xs text-text-muted",children:e.routeModel}),e.type&&"llm"!==e.type?(0,n.jsx)("span",{className:"mt-2 inline-flex rounded-full bg-surface px-2 py-0.5 text-[11px] text-text-muted",children:e.type}):null]})]},e.routeModel))})]})}):null,ep?(0,n.jsx)(a.aF,{isOpen:!!ep,onClose:()=>ev(null),title:"Manage imported models",size:"full",footer:(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(a.$n,{variant:"ghost",onClick:()=>ev(null),children:"Close"}),(0,n.jsx)(a.$n,{variant:"outline",loading:M===ep.id,onClick:()=>eD(ep),icon:"refresh",children:"Re-import from provider"})]}),children:(0,n.jsxs)("div",{className:"space-y-4",children:[(0,n.jsxs)("div",{className:"rounded-2xl border border-border bg-surface p-4 text-sm",children:[(0,n.jsx)("div",{className:"font-semibold text-text-main",children:ep.name||ep.id}),(0,n.jsxs)("div",{className:"mt-1 text-text-muted",children:[o(ep.provider,j)," \xb7 ",e9.length," imported model(s)"]}),(0,n.jsx)("div",{className:"mt-2 text-xs text-text-muted",children:'Test gửi 1 prompt "Say hello in five words" qua ch\xednh OAuth account của bạn, qua đ\xfang proxy của connection. X\xf3a model sẽ bỏ n\xf3 khỏi list importable; c\xe1c API key đ\xe3 gắn model n\xe0y kh\xf4ng bị thay đổi (request đến model đ\xf3 sẽ do provider ph\xeda tr\xean quyết định chấp nhận hay kh\xf4ng).'})]}),0===e9.length?(0,n.jsx)("div",{className:"rounded-2xl border border-dashed border-border p-8 text-center text-sm text-text-muted",children:'Chưa c\xf3 model n\xe0o được import. Bấm "Re-import from provider".'}):(0,n.jsx)("div",{className:"overflow-x-auto rounded-2xl border border-border",children:(0,n.jsxs)("table",{className:"min-w-full divide-y divide-border text-sm",children:[(0,n.jsx)("thead",{className:"bg-surface/80 text-left text-xs uppercase tracking-wide text-text-muted",children:(0,n.jsxs)("tr",{children:[(0,n.jsx)("th",{className:"px-4 py-3 font-medium",children:"Model"}),(0,n.jsx)("th",{className:"px-4 py-3 font-medium",children:"Route ID"}),(0,n.jsx)("th",{className:"px-4 py-3 font-medium",children:"Test result"}),(0,n.jsx)("th",{className:"px-4 py-3 text-right font-medium",children:"Actions"})]})}),(0,n.jsx)("tbody",{className:"divide-y divide-border bg-background",children:e9.map(e=>{let t=eg[e.routeModel],r=ef===e.routeModel,s=ej===e.routeModel;return(0,n.jsxs)("tr",{className:"align-top",children:[(0,n.jsxs)("td",{className:"px-4 py-3",children:[(0,n.jsx)("div",{className:"font-medium text-text-main",children:e.name||e.id}),e.type&&"llm"!==e.type?(0,n.jsx)("div",{className:"mt-1 text-xs text-text-muted",children:e.type}):null]}),(0,n.jsx)("td",{className:"px-4 py-3 font-mono text-xs text-text-muted break-all",children:e.routeModel}),(0,n.jsx)("td",{className:"px-4 py-3 text-xs",children:r?(0,n.jsx)("span",{className:"text-text-muted",children:"Đang test..."}):t?t.ok?(0,n.jsxs)("div",{className:"space-y-1",children:[(0,n.jsxs)("div",{className:"text-green-700 dark:text-green-300",children:["OK \xb7 ",t.latencyMs||0,"ms"]}),(0,n.jsx)("div",{className:"break-all text-text-muted",children:(t.text||"").slice(0,200)})]}):(0,n.jsxs)("div",{className:"space-y-1",children:[(0,n.jsxs)("div",{className:"text-red-700 dark:text-red-300",children:["FAIL \xb7 status ",t.status||"?"]}),(0,n.jsx)("div",{className:"break-all text-text-muted",children:(t.error||"").slice(0,200)})]}):(0,n.jsx)("span",{className:"text-text-muted",children:"—"})}),(0,n.jsx)("td",{className:"px-4 py-3",children:(0,n.jsxs)("div",{className:"flex flex-wrap justify-end gap-2",children:[(0,n.jsx)(a.$n,{variant:"outline",size:"sm",loading:r,disabled:s,onClick:()=>eX(ep,e),children:"Say hello"}),(0,n.jsx)(a.$n,{variant:"danger",size:"sm",loading:s,disabled:r,onClick:()=>eY(ep,e),children:"Delete"})]})})]},e.routeModel)})})]})})]})}):null,eI?(0,n.jsx)(a.aF,{isOpen:eI,onClose:()=>e_(!1),title:"RTK (Token Savings) l\xe0 g\xec?",size:"xl",footer:(0,n.jsx)(a.$n,{onClick:()=>e_(!1),children:"Đ\xe3 hiểu"}),children:(0,n.jsxs)("div",{className:"space-y-5 text-sm text-text-main",children:[(0,n.jsxs)("div",{className:"flex items-center gap-2 rounded-xl border border-border bg-surface px-3 py-2",children:[(0,n.jsx)("span",{className:"text-xs text-text-muted",children:"Global RTK hiện đang:"}),(0,n.jsx)(a.Ex,{variant:eO?"success":"default",size:"sm",children:eO?"ON":"OFF"}),(0,n.jsx)("span",{className:"text-xs text-text-muted",children:'— \xe1p dụng cho mọi account chọn "Theo global"'})]}),(0,n.jsx)("p",{className:"text-text-muted",children:"RTK l\xe0 bộ lọc n\xe9n output của tool (Bash, Grep, Glob, Read...) ngay trong request trước khi gửi l\xean model, gi\xfap giảm số token phải gửi m\xe0 kh\xf4ng l\xe0m mất th\xf4ng tin quan trọng — chỉ t\xe1c động tới phần tool output, kh\xf4ng đụng v\xe0o nội dung chat."}),(0,n.jsxs)("div",{children:[(0,n.jsx)("h3",{className:"mb-2 font-semibold text-text-main",children:"Hoạt động ra sao với CLI tool"}),(0,n.jsx)("p",{className:"text-text-muted",children:"Mỗi khi Claude Code / Codex CLI / OpenCode... gọi tool v\xe0 nhận lại output, RTK tự nhận diện định dạng quen thuộc rồi r\xfat gọn theo đ\xfang cấu tr\xfac của n\xf3:"}),(0,n.jsxs)("ul",{className:"mt-2 list-disc space-y-1 pl-5 text-text-muted",children:[(0,n.jsxs)("li",{children:[(0,n.jsx)("span",{className:"font-mono text-text-main",children:"git diff"})," — giữ v\xe0i d\xf2ng context quanh thay đổi, cắt phần hunk qu\xe1 d\xe0i"]}),(0,n.jsxs)("li",{children:[(0,n.jsx)("span",{className:"font-mono text-text-main",children:"git status"})," / ",(0,n.jsx)("span",{className:"font-mono text-text-main",children:"git log"})," — gom gọn danh s\xe1ch file thay đổi, danh s\xe1ch commit"]}),(0,n.jsxs)("li",{children:[(0,n.jsx)("span",{className:"font-mono text-text-main",children:"grep"})," / ",(0,n.jsx)("span",{className:"font-mono text-text-main",children:"find"})," — giới hạn số match hiển thị mỗi file/thư mục"]}),(0,n.jsxs)("li",{children:[(0,n.jsx)("span",{className:"font-mono text-text-main",children:"ls -la"})," / ",(0,n.jsx)("span",{className:"font-mono text-text-main",children:"tree"})," — t\xf3m tắt theo loại file, cắt c\xe2y thư mục qu\xe1 s\xe2u"]}),(0,n.jsx)("li",{children:"Build log (npm/yarn/cargo...) — chỉ giữ d\xf2ng quan trọng (lỗi, kết quả build)"}),(0,n.jsx)("li",{children:"Output d\xe0i chung kh\xf4ng r\xf5 định dạng — fallback dedup d\xf2ng lặp hoặc smart-truncate (giữ đầu + cuối)"})]})]}),(0,n.jsxs)("div",{children:[(0,n.jsx)("h3",{className:"mb-2 font-semibold text-text-main",children:"Hiệu quả thực tế"}),(0,n.jsx)("div",{className:"overflow-x-auto rounded-xl border border-border",children:(0,n.jsxs)("table",{className:"min-w-full text-xs",children:[(0,n.jsx)("thead",{className:"bg-surface/80 text-left uppercase tracking-wide text-text-muted",children:(0,n.jsxs)("tr",{children:[(0,n.jsx)("th",{className:"px-3 py-2 font-medium",children:"Loại output"}),(0,n.jsx)("th",{className:"px-3 py-2 font-medium",children:"Trước"}),(0,n.jsx)("th",{className:"px-3 py-2 font-medium",children:"Sau"}),(0,n.jsx)("th",{className:"px-3 py-2 font-medium",children:"Tiết kiệm"})]})}),(0,n.jsxs)("tbody",{className:"divide-y divide-border",children:[(0,n.jsxs)("tr",{children:[(0,n.jsx)("td",{className:"px-3 py-2 font-mono",children:"git diff"}),(0,n.jsx)("td",{className:"px-3 py-2",children:"7384B"}),(0,n.jsx)("td",{className:"px-3 py-2",children:"3894B"}),(0,n.jsx)("td",{className:"px-3 py-2 text-green-600 dark:text-green-400",children:"47.3%"})]}),(0,n.jsxs)("tr",{children:[(0,n.jsx)("td",{className:"px-3 py-2 font-mono",children:"grep -n"}),(0,n.jsx)("td",{className:"px-3 py-2",children:"3723B"}),(0,n.jsx)("td",{className:"px-3 py-2",children:"1447B"}),(0,n.jsx)("td",{className:"px-3 py-2 text-green-600 dark:text-green-400",children:"61.1%"})]}),(0,n.jsxs)("tr",{children:[(0,n.jsx)("td",{className:"px-3 py-2 font-mono",children:"find"}),(0,n.jsx)("td",{className:"px-3 py-2",children:"729B"}),(0,n.jsx)("td",{className:"px-3 py-2",children:"264B"}),(0,n.jsx)("td",{className:"px-3 py-2 text-green-600 dark:text-green-400",children:"63.8%"})]})]})]})})]}),(0,n.jsxs)("div",{children:[(0,n.jsx)("h3",{className:"mb-2 font-semibold text-text-main",children:"Khi n\xe0o KH\xd4NG bị n\xe9n"}),(0,n.jsxs)("ul",{className:"list-disc space-y-1 pl-5 text-text-muted",children:[(0,n.jsx)("li",{children:"Chat thường kh\xf4ng gọi tool — kh\xf4ng c\xf3 g\xec để n\xe9n"}),(0,n.jsx)("li",{children:"Output nhỏ hơn 500B — kh\xf4ng đ\xe1ng n\xe9n"}),(0,n.jsxs)("li",{children:["Output b\xe1o lỗi (",(0,n.jsx)("span",{className:"font-mono text-text-main",children:"is_error"}),") — lu\xf4n giữ nguy\xean để debug"]}),(0,n.jsx)("li",{children:"Output lớn hơn 10MB — bỏ qua để tr\xe1nh tốn CPU xử l\xfd"})]})]}),(0,n.jsxs)("div",{children:[(0,n.jsx)("h3",{className:"mb-2 font-semibold text-text-main",children:"Global vs từng account"}),(0,n.jsxs)("p",{className:"text-text-muted",children:["Dropdown RTK ở bảng tr\xean cho ph\xe9p override ri\xeang từng account:",(0,n.jsx)("span",{className:"font-semibold text-text-main",children:" Theo global"})," (mặc định, d\xf9ng đ\xfang setting global),",(0,n.jsx)("span",{className:"font-semibold text-text-main",children:" Lu\xf4n ON"})," hoặc",(0,n.jsx)("span",{className:"font-semibold text-text-main",children:" Lu\xf4n OFF"})," — override lu\xf4n thắng global theo cả 2 chiều, n\xean c\xf3 thể để global OFF v\xe0 chỉ bật cho account d\xf9ng CLI tool, hoặc ngược lại."]})]})]})}):null,(0,n.jsx)(a.v9,{isOpen:!!I,provider:I,onAccept:()=>{_(null),I&&S(I)},onCancel:()=>{_(null)}}),e5?(0,n.jsx)(a.LF,{isOpen:!!C,provider:C.id,providerInfo:e5,connectionScope:"personal",reauthConnectionId:P?.id||"",onSuccess:eF,onClose:()=>{S(null),A(null)}}):null,O?(0,n.jsx)(a.uo,{isOpen:!!O,onClose:()=>$(null),onConfirm:eV,title:"Revoke and delete personal account",message:`Gateway sẽ thử revoke token của ${O.name||O.id} tại provider, sau đ\xf3 x\xf3a token v\xe0 connection local. ${"claude"===O.provider?"Claude chưa c\xf3 endpoint revoke tự động được c\xf4ng bố; bạn c\xf3 thể cần thu hồi thủ c\xf4ng trong t\xe0i khoản Claude.":"Nếu provider kh\xf4ng x\xe1c nhận revoke, hệ thống sẽ th\xf4ng b\xe1o để bạn thu hồi thủ c\xf4ng."}`,confirmText:"Revoke & delete",cancelText:"Cancel",variant:"danger"}):null,ea?(0,n.jsx)(a.aF,{isOpen:!!ea,onClose:()=>ei(""),title:"Thu hồi to\xe0n bộ quyền OAuth",size:"lg",busy:r,closeOnOverlay:!r,footer:(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(a.$n,{variant:"ghost",onClick:()=>ei(""),disabled:r,children:"Hủy"}),(0,n.jsx)(a.$n,{variant:"danger",icon:"delete_forever",loading:r,onClick:()=>e4(ea),children:"Thu hồi v\xe0 x\xf3a to\xe0n bộ"})]}),children:(0,n.jsxs)("div",{className:"space-y-5",children:[(0,n.jsxs)("div",{className:"flex items-start gap-4 rounded-2xl border border-red-500/30 bg-gradient-to-br from-red-500/15 to-orange-500/5 p-4",children:[(0,n.jsx)("div",{className:"flex size-12 shrink-0 items-center justify-center rounded-2xl bg-red-500 text-white shadow-lg shadow-red-500/20",children:(0,n.jsx)("span",{className:"material-symbols-outlined text-[28px]",children:"warning"})}),(0,n.jsxs)("div",{className:"min-w-0",children:[(0,n.jsx)("div",{className:"text-sm font-medium text-red-700 dark:text-red-300",children:"H\xe0nh động nguy hiểm, kh\xf4ng thể ho\xe0n t\xe1c"}),(0,n.jsx)("div",{className:"mt-1 break-all text-lg font-semibold text-text-main",children:ea}),(0,n.jsxs)("p",{className:"mt-2 text-sm leading-6 text-text-muted",children:["Thu hồi to\xe0n bộ quyền OAuth provider của ",(0,n.jsx)("span",{className:"font-semibold text-text-main",children:ea}),"? OAuth account của user n\xe0y sẽ bị ",(0,n.jsx)("span",{className:"font-semibold text-red-600 dark:text-red-300",children:"X\xd3A HẲN"})," khỏi gateway."]})]})]}),(0,n.jsx)("div",{className:"grid gap-3 sm:grid-cols-3",children:[["key_off","Token OAuth","Thử revoke upstream rồi x\xf3a token local"],["deployed_code","Model đ\xe3 import","X\xf3a dữ liệu model của connection"],["vpn_key_off","API key đ\xe3 g\xe1n","Gỡ model tương ứng khỏi API key"]].map(([e,t,r])=>(0,n.jsxs)("div",{className:"rounded-2xl border border-border bg-background p-4",children:[(0,n.jsx)("span",{className:"material-symbols-outlined text-[22px] text-red-500",children:e}),(0,n.jsx)("div",{className:"mt-2 text-sm font-semibold text-text-main",children:t}),(0,n.jsx)("div",{className:"mt-1 text-xs leading-5 text-text-muted",children:r})]},t))}),(0,n.jsxs)("div",{className:"rounded-2xl border border-border bg-surface/70 p-4",children:[(0,n.jsxs)("div",{className:"flex items-center justify-between gap-3",children:[(0,n.jsx)("span",{className:"text-sm text-text-muted",children:"Connection t\xecm thấy"}),(0,n.jsx)(a.Ex,{variant:tt>0?"warning":"default",size:"sm",children:tt})]}),te?(0,n.jsx)("div",{className:"mt-3 flex flex-wrap gap-2",children:j.map(e=>{let t=Number(te.connectionsByProvider?.[e.id]||0);return t>0?(0,n.jsxs)("span",{className:"inline-flex items-center gap-1.5 rounded-full border border-border bg-background px-2.5 py-1 text-xs text-text-muted",children:[(0,n.jsx)(i.A,{src:`/providers/${e.id}.png`,alt:e.name,size:16,className:"max-h-[16px] max-w-[16px] rounded object-contain",fallbackText:e.id.slice(0,2).toUpperCase()}),e.name," \xd7",t]},e.id):null})}):null]}),(0,n.jsx)("p",{className:"text-xs leading-5 text-text-muted",children:"Nếu provider kh\xf4ng hỗ trợ revoke tự động hoặc kh\xf4ng phản hồi, gateway vẫn x\xf3a token local v\xe0 sẽ th\xf4ng b\xe1o để quản trị vi\xean thu hồi thủ c\xf4ng trong Security/Connected Apps của provider."})]})}):null]})}},67673:(e,t,r)=>{"use strict";r.d(t,{default:()=>h});var n=r(12115);let s="data-personal-order-enhanced";function a(e){return String(e?.textContent||"").trim()}function i(e){let t=Array.from(e.querySelectorAll("thead th"));return{headers:t,connectionIndex:t.findIndex(e=>"Connection"===a(e)),providerIndex:t.findIndex(e=>"Provider"===a(e)),createdIndex:t.findIndex(e=>"Created"===a(e)),orderIndex:t.findIndex(e=>"Order"===a(e))}}function l(e){return a(e?.querySelector(".font-mono"))}function o({direction:e,disabled:t,position:r,total:n}){let s=document.createElement("button");s.type="button",s.dataset.personalMove=e,s.disabled=t;let a=r&&n?` (đang ở vị tr\xed ${r}/${n})`:"";s.title="up"===e?`Move up — đẩy account n\xe0y l\xean tr\xean to\xe0n danh s\xe1ch${a}`:`Move down — đẩy account n\xe0y xuống dưới to\xe0n danh s\xe1ch${a}`,s.setAttribute("aria-label",s.title),s.className="inline-flex size-8 items-center justify-center rounded-lg border border-border bg-background text-text-main transition hover:border-brand-500 hover:bg-brand-500/10 hover:text-brand-600 disabled:cursor-not-allowed disabled:opacity-30";let i="up"===e?"arrow_upward":"arrow_downward";return s.innerHTML=`<span class="material-symbols-outlined text-[20px] font-bold" style="font-variation-settings: 'FILL' 1, 'wght' 700, 'GRAD' 200, 'opsz' 24;">${i}</span>`,s}function d(e,t){let r=Array.from(e.querySelectorAll("tbody tr")).filter(e=>!!l(Array.from(e.children)[t.connectionIndex])),n=r.length;r.forEach((e,r)=>{let s,i=Array.from(e.children),d=i[t.connectionIndex],c=i[t.providerIndex],m=l(d),h=a(c);e.dataset.connectionId=m,h&&(e.dataset.providerLabel=h);let x=e.querySelector("td[data-personal-order-cell]");x||((x=document.createElement("td")).dataset.personalOrderCell="true",x.className="px-4 py-4 align-middle",d?.insertAdjacentElement("afterend",x));let u=document.createElement("div");u.className="flex items-center justify-center gap-2",u.title="Thứ tự \xe1p dụng to\xe0n cục cho mọi personal account của bạn";let p=r+1;u.append(o({direction:"up",disabled:0===r,position:p,total:n}),((s=document.createElement("span")).dataset.personalOrderBadge="true",s.className="inline-flex min-w-[2rem] items-center justify-center rounded-full border border-border bg-surface px-2 py-0.5 text-[11px] font-semibold tabular-nums text-text-muted",s.textContent=n>0?`${p}/${n}`:String(p),s.title=`Vị tr\xed ${p} tr\xean tổng ${n} account`,s),o({direction:"down",disabled:r===n-1,position:p,total:n})),x.replaceChildren(u)})}let c=!1;async function m(e){if(c)return;let t=e.closest("tr"),r=t?.dataset.connectionId,n=e.dataset.personalMove;if(!r||"up"!==n&&"down"!==n)return;let s=t.parentElement,a=s?.closest("table");if(!s||!a)return;let l=Array.from(s.children).filter(e=>"TR"===e.tagName),o=l.indexOf(t),m="up"===n?o-1:o+1;if(o<0||m<0||m>=l.length)return;let h=l[m],x=()=>{"up"===n?s.insertBefore(h,t):s.insertBefore(t,h)};c=!0,Array.from(a.querySelectorAll("button[data-personal-move]")).forEach(e=>{e.disabled=!0}),"up"===n?s.insertBefore(t,h):s.insertBefore(h,t);let u=i(a);d(a,u);try{let e=await fetch(`/api/personal-cloud-providers/${encodeURIComponent(r)}/move`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({direction:n})}),t=await e.json().catch(()=>({}));if(!e.ok)throw Error(t.error||"Kh\xf4ng đổi được thứ tự account");if(!1===t.moved){x(),d(a,u);return}window.dispatchEvent(new CustomEvent("personal-cloud-refresh"))}catch(e){x(),d(a,u),window.alert(e.message||"Kh\xf4ng đổi được thứ tự account")}finally{c=!1}}function h(){return(0,n.useEffect)(()=>{let e=0,t=()=>{e||(e=window.requestAnimationFrame(()=>{e=0,function(e){if(!e)return;let t=i(e);if(t.connectionIndex<0||t.providerIndex<0)return;let r=Array.from(e.querySelectorAll("tbody tr"));if(!("true"===e.getAttribute(s)&&t.createdIndex<0&&t.orderIndex>=0&&r.every(e=>e.querySelector("td[data-personal-order-cell]")))){if(t.createdIndex>=0){let e=t.headers[t.createdIndex];r.forEach(e=>{let r=Array.from(e.children),n=r[t.connectionIndex],s=r[t.createdIndex],i=a(s);n&&i&&(n.title=`Created: ${i}`,n.classList.add("cursor-help")),s?.remove()}),e?.remove()}if(!((t=i(e)).connectionIndex<0)&&!(t.providerIndex<0)){if(t.orderIndex<0){let r=document.createElement("th");r.className="px-4 py-3 font-medium text-center",r.textContent="Order",r.title="Thứ tự ưu ti\xean to\xe0n cục — sắp xếp giữa mọi provider, kh\xf4ng giới hạn trong c\xf9ng provider",t.headers[t.connectionIndex]?.insertAdjacentElement("afterend",r),t=i(e)}d(e,t),e.setAttribute(s,"true")}}}(Array.from(document.querySelectorAll("table")).find(e=>{let t=Array.from(e.querySelectorAll("thead th")).map(a);return t.includes("Connection")&&t.includes("Provider")&&t.includes("Account")&&t.includes("Models")&&t.includes("API key routing")&&t.includes("Actions")})||null)}))};t();let r=new MutationObserver(t);r.observe(document.body,{childList:!0,subtree:!0});let n=e=>{let t=e.target?.closest?.("button[data-personal-move]");t&&m(t)};return document.addEventListener("click",n),()=>{r.disconnect(),e&&window.cancelAnimationFrame(e),document.removeEventListener("click",n)}},[]),null}},78867:(e,t,r)=>{"use strict";r.d(t,{default:()=>m});var n=r(95155),s=r(12115),a=r(35497),i=r(57250),l=r(29991),o=r.n(l);function d(e={}){let t=e.providerSpecificData||{};return e.email||t.githubEmail||t.username||e.displayName||e.name||t.accountId||e.id}function c(e){let t=String(e||"Personal OAuth");return t.charAt(0).toUpperCase()+t.slice(1)}function m(){let[e,t]=(0,s.useState)([]),[r,l]=(0,s.useState)([]),[m,h]=(0,s.useState)(!0),[x,u]=(0,s.useState)(""),[p,v]=(0,s.useState)(""),[g,b]=(0,s.useState)(""),[f,y]=(0,s.useState)(!1),[j,N]=(0,s.useState)(""),k=(0,s.useCallback)(async()=>{h(!0),u("");try{let e=await fetch("/api/personal-cloud-providers/shares",{cache:"no-store"}),r=await e.json().catch(()=>({}));if(!e.ok)throw Error(r.error||"Failed to load sharing settings");t(Array.isArray(r.ownedConnections)?r.ownedConnections:[]),l(Array.isArray(r.sharedWithMe)?r.sharedWithMe:[])}catch(e){u(e.message||"Failed to load sharing settings")}finally{h(!1)}},[]);(0,s.useEffect)(()=>{k()},[k]);let w=(0,s.useMemo)(()=>e.find(e=>e.id===p)||null,[e,p]),C=(0,s.useCallback)(e=>{t(t=>t.map(t=>t.id===e.id?e:t))},[]),S=(0,s.useCallback)(async e=>{e.preventDefault();let t=g.trim().toLowerCase();if(w&&t&&!f){if(t.includes("@"))return void N("Nhập username đăng nhập dashboard, kh\xf4ng d\xf9ng email.");y(!0),N("");try{let e=await fetch("/api/personal-cloud-providers/shares",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({connectionId:w.id,userId:t})}),r=await e.json().catch(()=>({}));if(!e.ok)throw Error(r.error||"Unable to share this account");r.connection&&C(r.connection),b("")}catch(e){N(e.message||"Unable to share this account")}finally{y(!1)}}},[f,w,C,g]),P=(0,s.useCallback)(async e=>{if(w&&!f){y(!0),N("");try{let t=await fetch("/api/personal-cloud-providers/shares",{method:"DELETE",headers:{"Content-Type":"application/json"},body:JSON.stringify({connectionId:w.id,userId:e})}),r=await t.json().catch(()=>({}));if(!t.ok)throw Error(r.error||"Unable to remove viewer");r.connection&&C(r.connection)}catch(e){N(e.message||"Unable to remove viewer")}finally{y(!1)}}},[f,w,C]),A=(0,s.useCallback)(e=>{v(e),b(""),N("")},[]),I=(0,s.useCallback)(()=>{f||(v(""),b(""),N(""))},[f]);return m?(0,n.jsxs)("section",{className:o().section,children:[(0,n.jsx)("div",{className:o().loadingLine}),(0,n.jsx)("div",{className:o().loadingLineShort})]}):(0,n.jsxs)("div",{className:o().shell,children:[(0,n.jsxs)("section",{className:o().section,children:[(0,n.jsxs)("div",{className:o().sectionHeader,children:[(0,n.jsxs)("div",{children:[(0,n.jsx)("div",{className:o().eyebrow,children:"Read-only quota sharing"}),(0,n.jsx)("h2",{className:o().title,children:"Share Personal OAuth monitoring"}),(0,n.jsx)("p",{className:o().description,children:"Give another dashboard user visibility into account status and quota only. Shared users cannot edit, disable, delete, import models, or change routing."})]}),(0,n.jsxs)("div",{className:o().lockPill,children:[(0,n.jsx)("span",{className:"material-symbols-outlined",children:"visibility"}),"View only"]})]}),x?(0,n.jsx)("div",{className:o().errorBox,children:x}):null,0===e.length?(0,n.jsx)("div",{className:o().emptyState,children:"Add a Personal OAuth account above first. It will appear here and can then be shared with viewers."}):(0,n.jsx)("div",{className:o().accountGrid,children:e.map(e=>{let t=e.sharedWith?.length||0;return(0,n.jsxs)("article",{className:o().accountCard,children:[(0,n.jsxs)("div",{className:o().accountIdentity,children:[(0,n.jsx)("span",{className:o().providerIconWrap,children:(0,n.jsx)(i.A,{src:`/providers/${e.provider}.png`,alt:e.provider,size:30,className:o().providerIcon,fallbackText:String(e.provider||"?").slice(0,2).toUpperCase()})}),(0,n.jsxs)("div",{className:o().accountText,children:[(0,n.jsxs)("div",{className:o().accountTopLine,children:[(0,n.jsx)("strong",{children:d(e)}),(0,n.jsx)("span",{className:e.isActive?o().activeBadge:o().inactiveBadge,children:e.isActive?"Active":"Off"})]}),(0,n.jsxs)("div",{className:o().accountMeta,children:[c(e.provider)," \xb7 ",0===t?"Not shared":`${t} viewer${1===t?"":"s"}`]})]})]}),(0,n.jsxs)(a.$n,{variant:"secondary",size:"sm",onClick:()=>A(e.id),children:[(0,n.jsx)("span",{className:"material-symbols-outlined text-[18px]",children:"person_add"}),"Share"]})]},e.id)})})]}),r.length>0?(0,n.jsxs)("section",{className:`${o().section} ${o().sharedSection}`,children:[(0,n.jsxs)("div",{className:o().sectionHeader,children:[(0,n.jsxs)("div",{children:[(0,n.jsx)("div",{className:o().eyebrow,children:"Shared with me"}),(0,n.jsx)("h2",{className:o().title,children:"Read-only Personal OAuth accounts"}),(0,n.jsx)("p",{className:o().description,children:"These accounts are owned by other users. You can inspect their status here and quota on Personal Quota, but you cannot change anything."})]}),(0,n.jsxs)("div",{className:o().lockPill,children:[(0,n.jsx)("span",{className:"material-symbols-outlined",children:"lock"}),"Read only"]})]}),(0,n.jsx)("div",{className:o().accountGrid,children:r.map(e=>(0,n.jsxs)("article",{className:`${o().accountCard} ${o().readOnlyCard}`,children:[(0,n.jsxs)("div",{className:o().accountIdentity,children:[(0,n.jsx)("span",{className:o().providerIconWrap,children:(0,n.jsx)(i.A,{src:`/providers/${e.provider}.png`,alt:e.provider,size:30,className:o().providerIcon,fallbackText:String(e.provider||"?").slice(0,2).toUpperCase()})}),(0,n.jsxs)("div",{className:o().accountText,children:[(0,n.jsxs)("div",{className:o().accountTopLine,children:[(0,n.jsx)("strong",{children:d(e)}),(0,n.jsx)("span",{className:o().readOnlyBadge,children:"Shared \xb7 Read only"})]}),(0,n.jsxs)("div",{className:o().accountMeta,children:[c(e.provider)," \xb7 Owner: ",e.ownerUser||"Unknown"]})]})]}),(0,n.jsx)("span",{className:o().noEditHint,children:"No edit access"})]},e.id))})]}):null,w?(0,n.jsx)(a.aF,{isOpen:!!w,onClose:I,title:"Share quota monitoring",size:"lg",children:(0,n.jsxs)("div",{className:o().modalBody,children:[(0,n.jsxs)("div",{className:o().modalAccount,children:[(0,n.jsx)(i.A,{src:`/providers/${w.provider}.png`,alt:w.provider,size:34,className:o().modalProviderIcon,fallbackText:String(w.provider||"?").slice(0,2).toUpperCase()}),(0,n.jsxs)("div",{children:[(0,n.jsx)("div",{className:o().modalAccountLabel,children:d(w)}),(0,n.jsx)("div",{className:o().modalAccountMeta,children:c(w.provider)})]})]}),(0,n.jsxs)("div",{className:o().readOnlyNotice,children:[(0,n.jsx)("span",{className:"material-symbols-outlined",children:"verified_user"}),(0,n.jsxs)("div",{children:[(0,n.jsx)("strong",{children:"Viewer permission only"}),(0,n.jsx)("p",{children:"Shared users can view this account on Personal OAuth and Personal Quota. All write actions remain owner-only on the server."})]})]}),(0,n.jsxs)("form",{className:o().shareForm,onSubmit:S,children:[(0,n.jsx)("label",{className:o().inputLabel,htmlFor:"personal-oauth-share-user",children:"Username"}),(0,n.jsxs)("div",{className:o().inputRow,children:[(0,n.jsx)("input",{id:"personal-oauth-share-user",className:o().shareInput,value:g,onChange:e=>b(e.target.value),placeholder:"Nhập username",autoComplete:"off",disabled:f}),(0,n.jsx)(a.$n,{type:"submit",disabled:!g.trim()||f,loading:f,children:"Share"})]}),(0,n.jsx)("p",{className:o().inputHelp,children:"Nhập username đăng nhập dashboard của người đ\xf3."})]}),j?(0,n.jsx)("div",{className:o().errorBox,children:j}):null,(0,n.jsxs)("div",{className:o().viewerBlock,children:[(0,n.jsxs)("div",{className:o().viewerHeading,children:[(0,n.jsx)("span",{children:"People with access"}),(0,n.jsx)("span",{children:w.sharedWith?.length||0})]}),0===(w.sharedWith?.length||0)?(0,n.jsx)("div",{className:o().viewerEmpty,children:"No viewers yet."}):(0,n.jsx)("div",{className:o().viewerList,children:w.sharedWith.map(e=>(0,n.jsxs)("div",{className:o().viewerRow,children:[(0,n.jsxs)("div",{className:o().viewerIdentity,children:[(0,n.jsx)("span",{className:o().avatar,children:e.slice(0,1).toUpperCase()}),(0,n.jsxs)("div",{children:[(0,n.jsx)("div",{className:o().viewerName,children:e}),(0,n.jsx)("div",{className:o().viewerRole,children:"Viewer \xb7 read only"})]})]}),(0,n.jsx)("button",{type:"button",className:o().removeButton,onClick:()=>P(e),disabled:f,children:"Remove"})]},e))})]})]})}):null]})}}}]);
|