zevairouter 1.0.147 → 1.0.148
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/CHANGELOG.md +12 -0
- package/cli/app/.next-cli-build/BUILD_ID +1 -1
- package/cli/app/.next-cli-build/app-path-routes-manifest.json +10 -10
- package/cli/app/.next-cli-build/build-manifest.json +2 -2
- package/cli/app/.next-cli-build/server/app/(dashboard)/dashboard/automation/page_client-reference-manifest.js +1 -1
- package/cli/app/.next-cli-build/server/app/(dashboard)/dashboard/basic-chat/page_client-reference-manifest.js +1 -1
- package/cli/app/.next-cli-build/server/app/(dashboard)/dashboard/cli-tools/[toolId]/page_client-reference-manifest.js +1 -1
- package/cli/app/.next-cli-build/server/app/(dashboard)/dashboard/cli-tools/page_client-reference-manifest.js +1 -1
- package/cli/app/.next-cli-build/server/app/(dashboard)/dashboard/combos/page_client-reference-manifest.js +1 -1
- package/cli/app/.next-cli-build/server/app/(dashboard)/dashboard/console-log/page_client-reference-manifest.js +1 -1
- package/cli/app/.next-cli-build/server/app/(dashboard)/dashboard/context/page_client-reference-manifest.js +1 -1
- package/cli/app/.next-cli-build/server/app/(dashboard)/dashboard/endpoint/page_client-reference-manifest.js +1 -1
- package/cli/app/.next-cli-build/server/app/(dashboard)/dashboard/media-providers/[kind]/[id]/page_client-reference-manifest.js +1 -1
- package/cli/app/.next-cli-build/server/app/(dashboard)/dashboard/media-providers/[kind]/page_client-reference-manifest.js +1 -1
- package/cli/app/.next-cli-build/server/app/(dashboard)/dashboard/media-providers/combo/[id]/page_client-reference-manifest.js +1 -1
- package/cli/app/.next-cli-build/server/app/(dashboard)/dashboard/media-providers/web/page_client-reference-manifest.js +1 -1
- package/cli/app/.next-cli-build/server/app/(dashboard)/dashboard/mitm/page_client-reference-manifest.js +1 -1
- package/cli/app/.next-cli-build/server/app/(dashboard)/dashboard/page_client-reference-manifest.js +1 -1
- package/cli/app/.next-cli-build/server/app/(dashboard)/dashboard/playground/page_client-reference-manifest.js +1 -1
- package/cli/app/.next-cli-build/server/app/(dashboard)/dashboard/profile/page_client-reference-manifest.js +1 -1
- package/cli/app/.next-cli-build/server/app/(dashboard)/dashboard/providers/[id]/page_client-reference-manifest.js +1 -1
- package/cli/app/.next-cli-build/server/app/(dashboard)/dashboard/providers/new/page_client-reference-manifest.js +1 -1
- package/cli/app/.next-cli-build/server/app/(dashboard)/dashboard/providers/page_client-reference-manifest.js +1 -1
- package/cli/app/.next-cli-build/server/app/(dashboard)/dashboard/proxy-pools/page_client-reference-manifest.js +1 -1
- package/cli/app/.next-cli-build/server/app/(dashboard)/dashboard/pxpipe/page_client-reference-manifest.js +1 -1
- package/cli/app/.next-cli-build/server/app/(dashboard)/dashboard/quota/page_client-reference-manifest.js +1 -1
- package/cli/app/.next-cli-build/server/app/(dashboard)/dashboard/terminal/page_client-reference-manifest.js +1 -1
- package/cli/app/.next-cli-build/server/app/(dashboard)/dashboard/token-saver/page_client-reference-manifest.js +1 -1
- package/cli/app/.next-cli-build/server/app/(dashboard)/dashboard/translator/page_client-reference-manifest.js +1 -1
- package/cli/app/.next-cli-build/server/app/(dashboard)/dashboard/usage/page_client-reference-manifest.js +1 -1
- package/cli/app/.next-cli-build/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/cli/app/.next-cli-build/server/app/_global-error.html +1 -1
- package/cli/app/.next-cli-build/server/app/_global-error.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/cli/app/.next-cli-build/server/app/_not-found.html +1 -1
- package/cli/app/.next-cli-build/server/app/_not-found.rsc +3 -3
- package/cli/app/.next-cli-build/server/app/_not-found.segments/_full.segment.rsc +3 -3
- package/cli/app/.next-cli-build/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/_not-found.segments/_index.segment.rsc +3 -3
- package/cli/app/.next-cli-build/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/api/models/route.js +1 -1
- package/cli/app/.next-cli-build/server/app/api/providers/route.js +1 -1
- package/cli/app/.next-cli-build/server/app/api/providers/validate/route.js +1 -1
- package/cli/app/.next-cli-build/server/app/api/translator/console-logs/route.js +1 -1
- package/cli/app/.next-cli-build/server/app/api/translator/console-logs/stream/route.js +1 -1
- package/cli/app/.next-cli-build/server/app/api/version/route.js +1 -1
- package/cli/app/.next-cli-build/server/app/api/version/shutdown/route.js +1 -1
- package/cli/app/.next-cli-build/server/app/api/version/update/route.js +1 -1
- package/cli/app/.next-cli-build/server/app/callback/page_client-reference-manifest.js +1 -1
- package/cli/app/.next-cli-build/server/app/callback.html +1 -1
- package/cli/app/.next-cli-build/server/app/callback.rsc +3 -3
- package/cli/app/.next-cli-build/server/app/callback.segments/_full.segment.rsc +3 -3
- package/cli/app/.next-cli-build/server/app/callback.segments/_head.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/callback.segments/_index.segment.rsc +3 -3
- package/cli/app/.next-cli-build/server/app/callback.segments/_tree.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/callback.segments/callback/__PAGE__.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/callback.segments/callback.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/automation.html +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/automation.rsc +5 -5
- package/cli/app/.next-cli-build/server/app/dashboard/automation.segments/!KGRhc2hib2FyZCk/dashboard/automation/__PAGE__.segment.rsc +2 -2
- package/cli/app/.next-cli-build/server/app/dashboard/automation.segments/!KGRhc2hib2FyZCk/dashboard/automation.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/automation.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/automation.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/cli/app/.next-cli-build/server/app/dashboard/automation.segments/_full.segment.rsc +5 -5
- package/cli/app/.next-cli-build/server/app/dashboard/automation.segments/_head.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/automation.segments/_index.segment.rsc +3 -3
- package/cli/app/.next-cli-build/server/app/dashboard/automation.segments/_tree.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/basic-chat.html +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/basic-chat.rsc +5 -5
- package/cli/app/.next-cli-build/server/app/dashboard/basic-chat.segments/!KGRhc2hib2FyZCk/dashboard/basic-chat/__PAGE__.segment.rsc +2 -2
- package/cli/app/.next-cli-build/server/app/dashboard/basic-chat.segments/!KGRhc2hib2FyZCk/dashboard/basic-chat.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/basic-chat.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/basic-chat.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/cli/app/.next-cli-build/server/app/dashboard/basic-chat.segments/_full.segment.rsc +5 -5
- package/cli/app/.next-cli-build/server/app/dashboard/basic-chat.segments/_head.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/basic-chat.segments/_index.segment.rsc +3 -3
- package/cli/app/.next-cli-build/server/app/dashboard/basic-chat.segments/_tree.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/cli-tools.html +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/cli-tools.rsc +5 -5
- package/cli/app/.next-cli-build/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk/dashboard/cli-tools/__PAGE__.segment.rsc +2 -2
- package/cli/app/.next-cli-build/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk/dashboard/cli-tools.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/cli/app/.next-cli-build/server/app/dashboard/cli-tools.segments/_full.segment.rsc +5 -5
- package/cli/app/.next-cli-build/server/app/dashboard/cli-tools.segments/_head.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/cli-tools.segments/_index.segment.rsc +3 -3
- package/cli/app/.next-cli-build/server/app/dashboard/cli-tools.segments/_tree.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/combos.html +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/combos.rsc +5 -5
- package/cli/app/.next-cli-build/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk/dashboard/combos/__PAGE__.segment.rsc +2 -2
- package/cli/app/.next-cli-build/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk/dashboard/combos.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/cli/app/.next-cli-build/server/app/dashboard/combos.segments/_full.segment.rsc +5 -5
- package/cli/app/.next-cli-build/server/app/dashboard/combos.segments/_head.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/combos.segments/_index.segment.rsc +3 -3
- package/cli/app/.next-cli-build/server/app/dashboard/combos.segments/_tree.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/context.html +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/context.rsc +5 -5
- package/cli/app/.next-cli-build/server/app/dashboard/context.segments/!KGRhc2hib2FyZCk/dashboard/context/__PAGE__.segment.rsc +2 -2
- package/cli/app/.next-cli-build/server/app/dashboard/context.segments/!KGRhc2hib2FyZCk/dashboard/context.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/context.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/context.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/cli/app/.next-cli-build/server/app/dashboard/context.segments/_full.segment.rsc +5 -5
- package/cli/app/.next-cli-build/server/app/dashboard/context.segments/_head.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/context.segments/_index.segment.rsc +3 -3
- package/cli/app/.next-cli-build/server/app/dashboard/context.segments/_tree.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/endpoint.html +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/endpoint.rsc +5 -5
- package/cli/app/.next-cli-build/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk/dashboard/endpoint/__PAGE__.segment.rsc +2 -2
- package/cli/app/.next-cli-build/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk/dashboard/endpoint.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/cli/app/.next-cli-build/server/app/dashboard/endpoint.segments/_full.segment.rsc +5 -5
- package/cli/app/.next-cli-build/server/app/dashboard/endpoint.segments/_head.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/endpoint.segments/_index.segment.rsc +3 -3
- package/cli/app/.next-cli-build/server/app/dashboard/endpoint.segments/_tree.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/media-providers/web.html +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/media-providers/web.rsc +5 -5
- package/cli/app/.next-cli-build/server/app/dashboard/media-providers/web.segments/!KGRhc2hib2FyZCk/dashboard/media-providers/web/__PAGE__.segment.rsc +2 -2
- package/cli/app/.next-cli-build/server/app/dashboard/media-providers/web.segments/!KGRhc2hib2FyZCk/dashboard/media-providers/web.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/media-providers/web.segments/!KGRhc2hib2FyZCk/dashboard/media-providers.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/media-providers/web.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/media-providers/web.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/cli/app/.next-cli-build/server/app/dashboard/media-providers/web.segments/_full.segment.rsc +5 -5
- package/cli/app/.next-cli-build/server/app/dashboard/media-providers/web.segments/_head.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/media-providers/web.segments/_index.segment.rsc +3 -3
- package/cli/app/.next-cli-build/server/app/dashboard/media-providers/web.segments/_tree.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/mitm.html +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/mitm.rsc +5 -5
- package/cli/app/.next-cli-build/server/app/dashboard/mitm.segments/!KGRhc2hib2FyZCk/dashboard/mitm/__PAGE__.segment.rsc +2 -2
- package/cli/app/.next-cli-build/server/app/dashboard/mitm.segments/!KGRhc2hib2FyZCk/dashboard/mitm.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/mitm.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/mitm.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/cli/app/.next-cli-build/server/app/dashboard/mitm.segments/_full.segment.rsc +5 -5
- package/cli/app/.next-cli-build/server/app/dashboard/mitm.segments/_head.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/mitm.segments/_index.segment.rsc +3 -3
- package/cli/app/.next-cli-build/server/app/dashboard/mitm.segments/_tree.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/playground.html +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/playground.rsc +5 -5
- package/cli/app/.next-cli-build/server/app/dashboard/playground.segments/!KGRhc2hib2FyZCk/dashboard/playground/__PAGE__.segment.rsc +2 -2
- package/cli/app/.next-cli-build/server/app/dashboard/playground.segments/!KGRhc2hib2FyZCk/dashboard/playground.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/playground.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/playground.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/cli/app/.next-cli-build/server/app/dashboard/playground.segments/_full.segment.rsc +5 -5
- package/cli/app/.next-cli-build/server/app/dashboard/playground.segments/_head.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/playground.segments/_index.segment.rsc +3 -3
- package/cli/app/.next-cli-build/server/app/dashboard/playground.segments/_tree.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/profile.html +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/profile.rsc +5 -5
- package/cli/app/.next-cli-build/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk/dashboard/profile/__PAGE__.segment.rsc +2 -2
- package/cli/app/.next-cli-build/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk/dashboard/profile.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/cli/app/.next-cli-build/server/app/dashboard/profile.segments/_full.segment.rsc +5 -5
- package/cli/app/.next-cli-build/server/app/dashboard/profile.segments/_head.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/profile.segments/_index.segment.rsc +3 -3
- package/cli/app/.next-cli-build/server/app/dashboard/profile.segments/_tree.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/providers/new.html +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/providers/new.rsc +5 -5
- package/cli/app/.next-cli-build/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard/providers/new/__PAGE__.segment.rsc +2 -2
- package/cli/app/.next-cli-build/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard/providers/new.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard/providers.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/cli/app/.next-cli-build/server/app/dashboard/providers/new.segments/_full.segment.rsc +5 -5
- package/cli/app/.next-cli-build/server/app/dashboard/providers/new.segments/_head.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/providers/new.segments/_index.segment.rsc +3 -3
- package/cli/app/.next-cli-build/server/app/dashboard/providers/new.segments/_tree.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/providers.html +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/providers.rsc +5 -5
- package/cli/app/.next-cli-build/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk/dashboard/providers/__PAGE__.segment.rsc +2 -2
- package/cli/app/.next-cli-build/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk/dashboard/providers.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/cli/app/.next-cli-build/server/app/dashboard/providers.segments/_full.segment.rsc +5 -5
- package/cli/app/.next-cli-build/server/app/dashboard/providers.segments/_head.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/providers.segments/_index.segment.rsc +3 -3
- package/cli/app/.next-cli-build/server/app/dashboard/providers.segments/_tree.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/proxy-pools.html +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/proxy-pools.rsc +5 -5
- package/cli/app/.next-cli-build/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk/dashboard/proxy-pools/__PAGE__.segment.rsc +2 -2
- package/cli/app/.next-cli-build/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk/dashboard/proxy-pools.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/cli/app/.next-cli-build/server/app/dashboard/proxy-pools.segments/_full.segment.rsc +5 -5
- package/cli/app/.next-cli-build/server/app/dashboard/proxy-pools.segments/_head.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/proxy-pools.segments/_index.segment.rsc +3 -3
- package/cli/app/.next-cli-build/server/app/dashboard/proxy-pools.segments/_tree.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/pxpipe.html +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/pxpipe.rsc +5 -5
- package/cli/app/.next-cli-build/server/app/dashboard/pxpipe.segments/!KGRhc2hib2FyZCk/dashboard/pxpipe/__PAGE__.segment.rsc +2 -2
- package/cli/app/.next-cli-build/server/app/dashboard/pxpipe.segments/!KGRhc2hib2FyZCk/dashboard/pxpipe.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/pxpipe.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/pxpipe.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/cli/app/.next-cli-build/server/app/dashboard/pxpipe.segments/_full.segment.rsc +5 -5
- package/cli/app/.next-cli-build/server/app/dashboard/pxpipe.segments/_head.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/pxpipe.segments/_index.segment.rsc +3 -3
- package/cli/app/.next-cli-build/server/app/dashboard/pxpipe.segments/_tree.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/quota.html +2 -2
- package/cli/app/.next-cli-build/server/app/dashboard/quota.rsc +6 -6
- package/cli/app/.next-cli-build/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk/dashboard/quota/__PAGE__.segment.rsc +3 -3
- package/cli/app/.next-cli-build/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk/dashboard/quota.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/cli/app/.next-cli-build/server/app/dashboard/quota.segments/_full.segment.rsc +6 -6
- package/cli/app/.next-cli-build/server/app/dashboard/quota.segments/_head.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/quota.segments/_index.segment.rsc +3 -3
- package/cli/app/.next-cli-build/server/app/dashboard/quota.segments/_tree.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/settings/pricing/page_client-reference-manifest.js +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/settings/pricing.html +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/settings/pricing.rsc +3 -3
- package/cli/app/.next-cli-build/server/app/dashboard/settings/pricing.segments/_full.segment.rsc +3 -3
- package/cli/app/.next-cli-build/server/app/dashboard/settings/pricing.segments/_head.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/settings/pricing.segments/_index.segment.rsc +3 -3
- package/cli/app/.next-cli-build/server/app/dashboard/settings/pricing.segments/_tree.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/settings/pricing.segments/dashboard/settings/pricing/__PAGE__.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/settings/pricing.segments/dashboard/settings/pricing.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/settings/pricing.segments/dashboard/settings.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/settings/pricing.segments/dashboard.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/token-saver.html +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/token-saver.rsc +5 -5
- package/cli/app/.next-cli-build/server/app/dashboard/token-saver.segments/!KGRhc2hib2FyZCk/dashboard/token-saver/__PAGE__.segment.rsc +2 -2
- package/cli/app/.next-cli-build/server/app/dashboard/token-saver.segments/!KGRhc2hib2FyZCk/dashboard/token-saver.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/token-saver.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/token-saver.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/cli/app/.next-cli-build/server/app/dashboard/token-saver.segments/_full.segment.rsc +5 -5
- package/cli/app/.next-cli-build/server/app/dashboard/token-saver.segments/_head.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/token-saver.segments/_index.segment.rsc +3 -3
- package/cli/app/.next-cli-build/server/app/dashboard/token-saver.segments/_tree.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/translator.html +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/translator.rsc +5 -5
- package/cli/app/.next-cli-build/server/app/dashboard/translator.segments/!KGRhc2hib2FyZCk/dashboard/translator/__PAGE__.segment.rsc +2 -2
- package/cli/app/.next-cli-build/server/app/dashboard/translator.segments/!KGRhc2hib2FyZCk/dashboard/translator.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/translator.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/translator.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/cli/app/.next-cli-build/server/app/dashboard/translator.segments/_full.segment.rsc +5 -5
- package/cli/app/.next-cli-build/server/app/dashboard/translator.segments/_head.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/translator.segments/_index.segment.rsc +3 -3
- package/cli/app/.next-cli-build/server/app/dashboard/translator.segments/_tree.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/usage.html +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/usage.rsc +5 -5
- package/cli/app/.next-cli-build/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk/dashboard/usage/__PAGE__.segment.rsc +2 -2
- package/cli/app/.next-cli-build/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk/dashboard/usage.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/cli/app/.next-cli-build/server/app/dashboard/usage.segments/_full.segment.rsc +5 -5
- package/cli/app/.next-cli-build/server/app/dashboard/usage.segments/_head.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard/usage.segments/_index.segment.rsc +3 -3
- package/cli/app/.next-cli-build/server/app/dashboard/usage.segments/_tree.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard.html +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard.rsc +5 -5
- package/cli/app/.next-cli-build/server/app/dashboard.segments/!KGRhc2hib2FyZCk/dashboard/__PAGE__.segment.rsc +2 -2
- package/cli/app/.next-cli-build/server/app/dashboard.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/cli/app/.next-cli-build/server/app/dashboard.segments/_full.segment.rsc +5 -5
- package/cli/app/.next-cli-build/server/app/dashboard.segments/_head.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/dashboard.segments/_index.segment.rsc +3 -3
- package/cli/app/.next-cli-build/server/app/dashboard.segments/_tree.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/index.html +1 -1
- package/cli/app/.next-cli-build/server/app/index.rsc +3 -3
- package/cli/app/.next-cli-build/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/index.segments/_full.segment.rsc +3 -3
- package/cli/app/.next-cli-build/server/app/index.segments/_head.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/index.segments/_index.segment.rsc +3 -3
- package/cli/app/.next-cli-build/server/app/index.segments/_tree.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/landing/page_client-reference-manifest.js +1 -1
- package/cli/app/.next-cli-build/server/app/landing.html +1 -1
- package/cli/app/.next-cli-build/server/app/landing.rsc +4 -4
- package/cli/app/.next-cli-build/server/app/landing.segments/_full.segment.rsc +4 -4
- package/cli/app/.next-cli-build/server/app/landing.segments/_head.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/landing.segments/_index.segment.rsc +3 -3
- package/cli/app/.next-cli-build/server/app/landing.segments/_tree.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/landing.segments/landing/__PAGE__.segment.rsc +2 -2
- package/cli/app/.next-cli-build/server/app/landing.segments/landing.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/login/page_client-reference-manifest.js +1 -1
- package/cli/app/.next-cli-build/server/app/login.html +1 -1
- package/cli/app/.next-cli-build/server/app/login.rsc +4 -4
- package/cli/app/.next-cli-build/server/app/login.segments/_full.segment.rsc +4 -4
- package/cli/app/.next-cli-build/server/app/login.segments/_head.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/login.segments/_index.segment.rsc +3 -3
- package/cli/app/.next-cli-build/server/app/login.segments/_tree.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/login.segments/login/__PAGE__.segment.rsc +2 -2
- package/cli/app/.next-cli-build/server/app/login.segments/login.segment.rsc +1 -1
- package/cli/app/.next-cli-build/server/app/page_client-reference-manifest.js +1 -1
- package/cli/app/.next-cli-build/server/app-paths-manifest.json +10 -10
- package/cli/app/.next-cli-build/server/chunks/3155.js +1 -1
- package/cli/app/.next-cli-build/server/chunks/4566.js +1 -1
- package/cli/app/.next-cli-build/server/chunks/4746.js +1 -1
- package/cli/app/.next-cli-build/server/chunks/5307.js +1 -1
- package/cli/app/.next-cli-build/server/chunks/5949.js +3 -3
- package/cli/app/.next-cli-build/server/chunks/8306.js +1 -1
- package/cli/app/.next-cli-build/server/chunks/8371.js +1 -1
- package/cli/app/.next-cli-build/server/chunks/9621.js +1 -1
- package/cli/app/.next-cli-build/server/middleware-build-manifest.js +1 -1
- package/cli/app/.next-cli-build/server/pages/404.html +1 -1
- package/cli/app/.next-cli-build/server/pages/500.html +1 -1
- package/cli/app/.next-cli-build/static/chunks/{620-375754e53341e85b.js → 620-16902cd352ef1d97.js} +1 -1
- package/cli/app/CHANGELOG.md +12 -0
- package/cli/app/cli/hooks/cloakbrowserRuntime.js +111 -4
- package/cli/app/package.json +1 -1
- package/cli/hooks/cloakbrowserRuntime.js +111 -4
- package/cli/package.json +1 -1
- package/package.json +1 -1
- package/src/lib/oauth/services/bulkImportBrowserEngine.js +36 -0
- package/src/lib/oauth/services/codebuddyCnBulkImportManager.js +469 -172
- package/src/lib/oauth/services/codebuddyCnPhoneAutomation.js +16 -2
- package/src/lib/oauth/services/kiroBulkImportManager.js +7 -1
- /package/cli/app/.next-cli-build/static/{y-U4C09T7DItXT7CZZV41 → kmlfntQuBCJ_ni8__OiKd}/_buildManifest.js +0 -0
- /package/cli/app/.next-cli-build/static/{y-U4C09T7DItXT7CZZV41 → kmlfntQuBCJ_ni8__OiKd}/_ssgManifest.js +0 -0
|
@@ -64,12 +64,25 @@ const CODEBUDDY_CN_POLL_TIMEOUT_MS = 15 * 60_000;
|
|
|
64
64
|
// input phone, click send code takes ~15-20s before SMS is actually requested).
|
|
65
65
|
const CODEBUDDY_CN_SMS_TIMEOUT_MS = 90_000;
|
|
66
66
|
|
|
67
|
-
// Hard wall-clock
|
|
68
|
-
//
|
|
67
|
+
// Hard wall-clock for phone registration (nav + form + SMS). Console/API work
|
|
68
|
+
// has separate bounded operations below.
|
|
69
69
|
const CODEBUDDY_CN_ACCOUNT_HARD_TIMEOUT_MS = Number.parseInt(
|
|
70
70
|
process.env.ZEVAI_CN_ACCOUNT_TIMEOUT_MS || "",
|
|
71
71
|
10,
|
|
72
|
-
) ||
|
|
72
|
+
) || 5 * 60_000;
|
|
73
|
+
|
|
74
|
+
const CODEBUDDY_CN_BROWSER_LAUNCH_TIMEOUT_MS = 90_000;
|
|
75
|
+
const CODEBUDDY_CN_CONTEXT_TIMEOUT_MS = 30_000;
|
|
76
|
+
const CODEBUDDY_CN_CONSOLE_NAV_TIMEOUT_MS = 18_000;
|
|
77
|
+
const CODEBUDDY_CN_CONSOLE_PROBE_TIMEOUT_MS = 10_000;
|
|
78
|
+
const CODEBUDDY_CN_API_KEY_REQUEST_TIMEOUT_MS = 60_000;
|
|
79
|
+
const CODEBUDDY_CN_OIDC_MAX_ATTEMPTS = 6;
|
|
80
|
+
const CODEBUDDY_CN_API_REHANDOFF_ROUNDS = 2;
|
|
81
|
+
const CODEBUDDY_CN_MANUAL_TIMEOUT_MS = 8 * 60_000;
|
|
82
|
+
const CODEBUDDY_CN_LOW_MEM_MANUAL_TIMEOUT_MS = 3 * 60_000;
|
|
83
|
+
const CODEBUDDY_CN_RESOURCE_CLOSE_TIMEOUT_MS = 5_000;
|
|
84
|
+
const CODEBUDDY_CN_FIVESIM_SETTLE_TIMEOUT_MS = 12_000;
|
|
85
|
+
const CODEBUDDY_CN_API_KEY_OUTCOME_UNKNOWN = "CN_API_KEY_OUTCOME_UNKNOWN";
|
|
73
86
|
|
|
74
87
|
// Supported 5sim regions
|
|
75
88
|
const SUPPORTED_REGIONS = new Set(["hongkong", "china", "any"]);
|
|
@@ -113,6 +126,83 @@ function clampCnConcurrency(value) {
|
|
|
113
126
|
return Math.min(hardMax, Math.max(CODEBUDDY_CN_MIN_CONCURRENCY, parsed));
|
|
114
127
|
}
|
|
115
128
|
|
|
129
|
+
async function withTimeoutCleanup(
|
|
130
|
+
task,
|
|
131
|
+
{
|
|
132
|
+
timeoutMs,
|
|
133
|
+
message,
|
|
134
|
+
code,
|
|
135
|
+
onTimeout,
|
|
136
|
+
onLateResolve,
|
|
137
|
+
},
|
|
138
|
+
) {
|
|
139
|
+
const operation = Promise.resolve(task);
|
|
140
|
+
let timer = null;
|
|
141
|
+
let timedOut = false;
|
|
142
|
+
const timeout = new Promise((_, reject) => {
|
|
143
|
+
timer = setTimeout(() => {
|
|
144
|
+
timedOut = true;
|
|
145
|
+
try {
|
|
146
|
+
if (typeof onTimeout === "function") onTimeout();
|
|
147
|
+
} catch {
|
|
148
|
+
// Timeout reporting must not be replaced by cleanup callback failures.
|
|
149
|
+
}
|
|
150
|
+
reject(Object.assign(new Error(message), { code }));
|
|
151
|
+
}, timeoutMs);
|
|
152
|
+
if (typeof timer.unref === "function") timer.unref();
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
try {
|
|
156
|
+
return await Promise.race([operation, timeout]);
|
|
157
|
+
} finally {
|
|
158
|
+
if (timer) clearTimeout(timer);
|
|
159
|
+
if (timedOut && typeof onLateResolve === "function") {
|
|
160
|
+
void operation.then(onLateResolve).catch(() => null);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function isLoginHtmlProbe(probe) {
|
|
166
|
+
const raw = `${probe?.text || ""} ${probe?.data?._raw || ""}`;
|
|
167
|
+
return probe?.data?._notJson === true
|
|
168
|
+
|| /<!doctype html|<html|login-pf|\/auth\/realms\//i.test(raw);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
async function closeResourceBounded(resource) {
|
|
172
|
+
if (!resource || typeof resource.close !== "function") return true;
|
|
173
|
+
try {
|
|
174
|
+
await withTimeoutCleanup(Promise.resolve().then(() => resource.close()), {
|
|
175
|
+
timeoutMs: CODEBUDDY_CN_RESOURCE_CLOSE_TIMEOUT_MS,
|
|
176
|
+
message: `Browser resource close timed out after ${CODEBUDDY_CN_RESOURCE_CLOSE_TIMEOUT_MS / 1000}s`,
|
|
177
|
+
code: "CN_RESOURCE_CLOSE_TIMEOUT",
|
|
178
|
+
});
|
|
179
|
+
return true;
|
|
180
|
+
} catch {
|
|
181
|
+
return false;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
async function closeContextOrBrowser(context, job) {
|
|
186
|
+
if (await closeResourceBounded(context)) return;
|
|
187
|
+
if (!job?.browser) return;
|
|
188
|
+
const browser = job.browser;
|
|
189
|
+
job.browser = null;
|
|
190
|
+
await forceCloseBrowser(browser).catch(() => null);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
async function settleFiveSimOrder(operation) {
|
|
194
|
+
try {
|
|
195
|
+
return await withTimeoutCleanup(Promise.resolve().then(operation), {
|
|
196
|
+
timeoutMs: CODEBUDDY_CN_FIVESIM_SETTLE_TIMEOUT_MS,
|
|
197
|
+
message: `5sim order settlement timed out after ${CODEBUDDY_CN_FIVESIM_SETTLE_TIMEOUT_MS / 1000}s`,
|
|
198
|
+
code: "CN_FIVESIM_SETTLE_TIMEOUT",
|
|
199
|
+
});
|
|
200
|
+
} catch {
|
|
201
|
+
// Finish/cancel/ban are best-effort and must not hold the browser worker.
|
|
202
|
+
return false;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
116
206
|
/**
|
|
117
207
|
* Save a CodeBuddy CN provider connection to the database.
|
|
118
208
|
*/
|
|
@@ -165,7 +255,10 @@ export class CodeBuddyCnBulkImportManager extends KiroBulkImportManager {
|
|
|
165
255
|
// CloakBrowser-only: proxy on launch + geoip. Headed by default (Turnstile/Tencent).
|
|
166
256
|
// Override: ZEVAI_CN_HEADLESS=0|1
|
|
167
257
|
const cnBrowserLauncher = browserLauncher || (async (job) => {
|
|
168
|
-
const {
|
|
258
|
+
const {
|
|
259
|
+
forceCloseBrowser,
|
|
260
|
+
launchBulkImportBrowser,
|
|
261
|
+
} = await import("./bulkImportBrowserEngine.js");
|
|
169
262
|
const proxyUrl = Array.isArray(job?.proxyUrls) && job.proxyUrls.length
|
|
170
263
|
? job.proxyUrls[0]
|
|
171
264
|
: null;
|
|
@@ -173,12 +266,18 @@ export class CodeBuddyCnBulkImportManager extends KiroBulkImportManager {
|
|
|
173
266
|
let headless = false;
|
|
174
267
|
if (envHeadless === "0" || envHeadless === "false") headless = false;
|
|
175
268
|
if (envHeadless === "1" || envHeadless === "true") headless = true;
|
|
176
|
-
|
|
269
|
+
const launchTask = launchBulkImportBrowser({
|
|
177
270
|
engine: job?.engine || "cloakbrowser",
|
|
178
271
|
proxyUrl,
|
|
179
272
|
headless,
|
|
180
273
|
windowSize: { width: 1280, height: 900 },
|
|
181
274
|
});
|
|
275
|
+
return withTimeoutCleanup(launchTask, {
|
|
276
|
+
timeoutMs: CODEBUDDY_CN_BROWSER_LAUNCH_TIMEOUT_MS,
|
|
277
|
+
message: `CloakBrowser launch timed out after ${CODEBUDDY_CN_BROWSER_LAUNCH_TIMEOUT_MS / 1000}s`,
|
|
278
|
+
code: "CN_BROWSER_LAUNCH_TIMEOUT",
|
|
279
|
+
onLateResolve: (browser) => forceCloseBrowser(browser),
|
|
280
|
+
});
|
|
182
281
|
});
|
|
183
282
|
super({ browserLauncher: cnBrowserLauncher, storageName });
|
|
184
283
|
this.requestDeviceCode = requestDeviceCodeFn;
|
|
@@ -358,10 +457,17 @@ export class CodeBuddyCnBulkImportManager extends KiroBulkImportManager {
|
|
|
358
457
|
// cause of 账号访问受限 right after OTP). Per-account fingerprint seed —
|
|
359
458
|
// sticky residential IP alone still clusters if every session shares HW.
|
|
360
459
|
if (!account.fingerprintSeed) account.fingerprintSeed = randomUUID();
|
|
361
|
-
const
|
|
460
|
+
const contextTask = createFreshContext(job.browser, account.proxyUrl, {
|
|
362
461
|
profile: "codebuddy-cn",
|
|
363
462
|
region: job.region || "hongkong",
|
|
364
463
|
fingerprintSeed: account.fingerprintSeed,
|
|
464
|
+
lowMemory: isLowMemHost(),
|
|
465
|
+
});
|
|
466
|
+
const freshContext = await withTimeoutCleanup(contextTask, {
|
|
467
|
+
timeoutMs: CODEBUDDY_CN_CONTEXT_TIMEOUT_MS,
|
|
468
|
+
message: `Browser context creation timed out after ${CODEBUDDY_CN_CONTEXT_TIMEOUT_MS / 1000}s`,
|
|
469
|
+
code: "CN_CONTEXT_TIMEOUT",
|
|
470
|
+
onLateResolve: (session) => Promise.resolve(session?.context?.close?.()).catch(() => null),
|
|
365
471
|
});
|
|
366
472
|
context = freshContext.context;
|
|
367
473
|
const page = freshContext.page;
|
|
@@ -481,13 +587,13 @@ export class CodeBuddyCnBulkImportManager extends KiroBulkImportManager {
|
|
|
481
587
|
// Only touch 5sim if we actually bought a number (order is deferred until form ready)
|
|
482
588
|
if (fiveSimClient && fiveSimOrderId) {
|
|
483
589
|
if (smsReceived) {
|
|
484
|
-
await fiveSimClient.finishOrder(fiveSimOrderId);
|
|
590
|
+
await settleFiveSimOrder(() => fiveSimClient.finishOrder(fiveSimOrderId));
|
|
485
591
|
} else {
|
|
486
|
-
await fiveSimClient.cancelOrder(fiveSimOrderId);
|
|
592
|
+
await settleFiveSimOrder(() => fiveSimClient.cancelOrder(fiveSimOrderId));
|
|
487
593
|
}
|
|
488
594
|
}
|
|
489
595
|
account.runtimeSession = null;
|
|
490
|
-
await context
|
|
596
|
+
await closeContextOrBrowser(context, job);
|
|
491
597
|
await this.persistJobSnapshot(job, { forcePreview: true });
|
|
492
598
|
return;
|
|
493
599
|
}
|
|
@@ -510,19 +616,23 @@ export class CodeBuddyCnBulkImportManager extends KiroBulkImportManager {
|
|
|
510
616
|
// 5sim hygiene on error
|
|
511
617
|
if (fiveSimClient && fiveSimOrderId) {
|
|
512
618
|
if (smsReceived) {
|
|
513
|
-
await fiveSimClient.finishOrder(fiveSimOrderId);
|
|
619
|
+
await settleFiveSimOrder(() => fiveSimClient.finishOrder(fiveSimOrderId));
|
|
514
620
|
} else if (isSmsTimeout) {
|
|
515
|
-
// BAN: number
|
|
516
|
-
await fiveSimClient.banOrder(fiveSimOrderId);
|
|
621
|
+
// BAN: number did not receive CodeBuddy SMS within the OTP window.
|
|
622
|
+
await settleFiveSimOrder(() => fiveSimClient.banOrder(fiveSimOrderId));
|
|
517
623
|
} else {
|
|
518
|
-
await fiveSimClient.cancelOrder(fiveSimOrderId);
|
|
624
|
+
await settleFiveSimOrder(() => fiveSimClient.cancelOrder(fiveSimOrderId));
|
|
519
625
|
}
|
|
520
626
|
}
|
|
521
627
|
account.runtimeSession = null;
|
|
522
|
-
|
|
628
|
+
await closeContextOrBrowser(context, job);
|
|
523
629
|
// Hard timeout / blackhole nav: kill the shared browser so the worker unblocks
|
|
524
630
|
// and Chromium cannot pin 100% CPU on a 2GB VPS until reboot.
|
|
525
|
-
if (
|
|
631
|
+
if (
|
|
632
|
+
error?.code === "CN_ACCOUNT_HARD_TIMEOUT"
|
|
633
|
+
|| error?.code === "CN_CONTEXT_TIMEOUT"
|
|
634
|
+
|| job.cancelRequested
|
|
635
|
+
) {
|
|
526
636
|
if (job.browser) {
|
|
527
637
|
const b = job.browser;
|
|
528
638
|
job.browser = null;
|
|
@@ -592,34 +702,55 @@ export class CodeBuddyCnBulkImportManager extends KiroBulkImportManager {
|
|
|
592
702
|
|| names.has("qcmainCSRFToken")
|
|
593
703
|
|| names.has("x_host_key_access");
|
|
594
704
|
|
|
595
|
-
const probeConsoleAccounts = async () =>
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
const
|
|
599
|
-
const base = host.endsWith("codebuddy.cn")
|
|
600
|
-
? `${window.location.origin}`
|
|
601
|
-
: "https://www.codebuddy.cn";
|
|
602
|
-
const res = await fetch(`${base}/console/accounts`, {
|
|
603
|
-
credentials: "include",
|
|
604
|
-
headers: {
|
|
605
|
-
Accept: "application/json, text/plain, */*",
|
|
606
|
-
"x-requested-with": "XMLHttpRequest",
|
|
607
|
-
"X-Domain": "www.codebuddy.cn",
|
|
608
|
-
"X-Product": "SaaS",
|
|
609
|
-
},
|
|
610
|
-
});
|
|
611
|
-
const text = await res.text().catch(() => "");
|
|
612
|
-
let data = null;
|
|
705
|
+
const probeConsoleAccounts = async () => {
|
|
706
|
+
const probeTask = page.evaluate(async ({ timeoutMs }) => {
|
|
707
|
+
const controller = new AbortController();
|
|
708
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
613
709
|
try {
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
710
|
+
// Relative /console/accounts fails on Tencent/Keycloak login hosts.
|
|
711
|
+
const host = window.location.hostname || "www.codebuddy.cn";
|
|
712
|
+
const base = host === "www.codebuddy.cn"
|
|
713
|
+
? `${window.location.origin}`
|
|
714
|
+
: "https://www.codebuddy.cn";
|
|
715
|
+
const res = await fetch(`${base}/console/accounts`, {
|
|
716
|
+
credentials: "include",
|
|
717
|
+
signal: controller.signal,
|
|
718
|
+
headers: {
|
|
719
|
+
Accept: "application/json, text/plain, */*",
|
|
720
|
+
"x-requested-with": "XMLHttpRequest",
|
|
721
|
+
"X-Domain": "www.codebuddy.cn",
|
|
722
|
+
"X-Product": "SaaS",
|
|
723
|
+
},
|
|
724
|
+
});
|
|
725
|
+
const text = await res.text().catch(() => "");
|
|
726
|
+
let data = null;
|
|
727
|
+
try {
|
|
728
|
+
data = text ? JSON.parse(text) : null;
|
|
729
|
+
} catch {
|
|
730
|
+
data = { _raw: String(text || "").slice(0, 240), _notJson: true };
|
|
731
|
+
}
|
|
732
|
+
return { status: res.status, data, text: String(text || "").slice(0, 240) };
|
|
733
|
+
} catch (error) {
|
|
734
|
+
return {
|
|
735
|
+
status: 0,
|
|
736
|
+
timedOut: error?.name === "AbortError",
|
|
737
|
+
error: error?.message || String(error),
|
|
738
|
+
};
|
|
739
|
+
} finally {
|
|
740
|
+
clearTimeout(timer);
|
|
617
741
|
}
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
742
|
+
}, { timeoutMs: CODEBUDDY_CN_CONSOLE_PROBE_TIMEOUT_MS });
|
|
743
|
+
|
|
744
|
+
return withTimeoutCleanup(probeTask, {
|
|
745
|
+
timeoutMs: CODEBUDDY_CN_CONSOLE_PROBE_TIMEOUT_MS,
|
|
746
|
+
message: `Console account probe timed out after ${CODEBUDDY_CN_CONSOLE_PROBE_TIMEOUT_MS / 1000}s`,
|
|
747
|
+
code: "CN_CONSOLE_PROBE_TIMEOUT",
|
|
748
|
+
}).catch((error) => ({
|
|
749
|
+
status: 0,
|
|
750
|
+
timedOut: error?.code === "CN_CONSOLE_PROBE_TIMEOUT",
|
|
751
|
+
error: error?.message || String(error),
|
|
752
|
+
}));
|
|
753
|
+
};
|
|
623
754
|
|
|
624
755
|
const extractAccountList = (probe) => {
|
|
625
756
|
const d = probe?.data;
|
|
@@ -642,35 +773,52 @@ export class CodeBuddyCnBulkImportManager extends KiroBulkImportManager {
|
|
|
642
773
|
return [];
|
|
643
774
|
};
|
|
644
775
|
|
|
645
|
-
//
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
(
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
776
|
+
// A committed response is enough to start session probes. Waiting for the
|
|
777
|
+
// full SPA DOM is expensive and frequently stalls on small VPS hosts.
|
|
778
|
+
const waitAfterNav = async (timeoutMs = 2_500) => {
|
|
779
|
+
let settled = false;
|
|
780
|
+
let timer = null;
|
|
781
|
+
try {
|
|
782
|
+
await Promise.race([
|
|
783
|
+
page.waitForLoadState("domcontentloaded", { timeout: timeoutMs }).catch(() => null),
|
|
784
|
+
waitUntil(async () => {
|
|
785
|
+
if (settled) return true;
|
|
786
|
+
const snap = await cookieSnapshot();
|
|
787
|
+
return hasStrongKeycloak(snap.names);
|
|
788
|
+
}, { timeout: timeoutMs, interval: 200 }),
|
|
789
|
+
new Promise((resolve) => {
|
|
790
|
+
timer = setTimeout(resolve, timeoutMs);
|
|
791
|
+
}),
|
|
792
|
+
]);
|
|
793
|
+
} finally {
|
|
794
|
+
settled = true;
|
|
795
|
+
if (timer) clearTimeout(timer);
|
|
796
|
+
}
|
|
797
|
+
};
|
|
798
|
+
|
|
799
|
+
const navigateConsole = async (path) => {
|
|
800
|
+
const startedAt = Date.now();
|
|
801
|
+
try {
|
|
802
|
+
await page.goto(path, {
|
|
803
|
+
waitUntil: "commit",
|
|
804
|
+
timeout: CODEBUDDY_CN_CONSOLE_NAV_TIMEOUT_MS,
|
|
805
|
+
});
|
|
806
|
+
const remainingMs = CODEBUDDY_CN_CONSOLE_NAV_TIMEOUT_MS - (Date.now() - startedAt);
|
|
807
|
+
if (remainingMs > 0) await waitAfterNav(Math.min(2_500, remainingMs));
|
|
808
|
+
return true;
|
|
809
|
+
} catch {
|
|
810
|
+
return false;
|
|
811
|
+
}
|
|
662
812
|
};
|
|
663
813
|
|
|
664
814
|
// Navigate sequence to finish OIDC handoff when only AUTH_SESSION_ID is present.
|
|
665
|
-
//
|
|
815
|
+
// Never revisit /login here: it can wipe a valid partial OIDC session.
|
|
666
816
|
const oIDCNudgePaths = [
|
|
667
817
|
"https://www.codebuddy.cn/",
|
|
668
818
|
"https://www.codebuddy.cn/console",
|
|
669
819
|
"https://www.codebuddy.cn/console/",
|
|
670
820
|
"https://www.codebuddy.cn/profile",
|
|
671
821
|
"https://www.codebuddy.cn/profile/keys",
|
|
672
|
-
// only if still empty after console probes
|
|
673
|
-
"https://www.codebuddy.cn/login/",
|
|
674
822
|
];
|
|
675
823
|
|
|
676
824
|
let accountList = [];
|
|
@@ -678,9 +826,8 @@ export class CodeBuddyCnBulkImportManager extends KiroBulkImportManager {
|
|
|
678
826
|
let sessionReady = false;
|
|
679
827
|
let lastPayloadSnippet = "";
|
|
680
828
|
|
|
681
|
-
// Event-driven OIDC settle:
|
|
682
|
-
|
|
683
|
-
for (let attempt = 0; attempt < OIDC_MAX_ATTEMPTS; attempt += 1) {
|
|
829
|
+
// Event-driven OIDC settle: bounded attempts and no blind multi-second sleeps.
|
|
830
|
+
for (let attempt = 0; attempt < CODEBUDDY_CN_OIDC_MAX_ATTEMPTS; attempt += 1) {
|
|
684
831
|
if (job.cancelRequested) {
|
|
685
832
|
throw new Error("Job cancelled while establishing session");
|
|
686
833
|
}
|
|
@@ -697,31 +844,32 @@ export class CodeBuddyCnBulkImportManager extends KiroBulkImportManager {
|
|
|
697
844
|
this.setAccountStep(
|
|
698
845
|
account,
|
|
699
846
|
"waiting_session",
|
|
700
|
-
`OIDC handoff ${attempt + 1}/${
|
|
847
|
+
`OIDC handoff ${attempt + 1}/${CODEBUDDY_CN_OIDC_MAX_ATTEMPTS} → ${path.replace("https://www.codebuddy.cn", "")} (${strong ? "KEYCLOAK" : soft ? "soft-session" : "weak"})`,
|
|
701
848
|
);
|
|
702
849
|
await this.persistJobSnapshot(job, { forcePreview: false });
|
|
703
|
-
await
|
|
704
|
-
await waitAfterNav();
|
|
850
|
+
await navigateConsole(path);
|
|
705
851
|
} else {
|
|
706
852
|
// Soft session present — short yield then re-probe (no blind multi-second sleep).
|
|
707
853
|
await new Promise((r) => setTimeout(r, 300));
|
|
708
854
|
}
|
|
709
855
|
|
|
710
856
|
// Prefer landing on console for the API probe (absolute host)
|
|
711
|
-
const onCodebuddy =
|
|
712
|
-
if (!onCodebuddy
|
|
713
|
-
await
|
|
714
|
-
waitUntil: "domcontentloaded",
|
|
715
|
-
timeout: 25_000,
|
|
716
|
-
}).catch(() => null);
|
|
717
|
-
await waitAfterNav();
|
|
857
|
+
const onCodebuddy = /^https:\/\/www\.codebuddy\.cn(?:[/:]|$)/i.test(page.url?.() || "");
|
|
858
|
+
if (!onCodebuddy) {
|
|
859
|
+
await navigateConsole("https://www.codebuddy.cn/console");
|
|
718
860
|
}
|
|
719
861
|
|
|
720
862
|
accountsProbe = await probeConsoleAccounts();
|
|
721
863
|
accountList = extractAccountList(accountsProbe);
|
|
722
864
|
lastPayloadSnippet = JSON.stringify(accountsProbe?.data ?? accountsProbe?.text ?? null).slice(0, 180);
|
|
865
|
+
const loginHtml = isLoginHtmlProbe(accountsProbe);
|
|
723
866
|
|
|
724
|
-
if (
|
|
867
|
+
if (
|
|
868
|
+
accountsProbe?.status === 200
|
|
869
|
+
&& !loginHtml
|
|
870
|
+
&& Array.isArray(accountList)
|
|
871
|
+
&& accountList.length > 0
|
|
872
|
+
) {
|
|
725
873
|
sessionReady = true;
|
|
726
874
|
this.setAccountStep(
|
|
727
875
|
account,
|
|
@@ -737,9 +885,11 @@ export class CodeBuddyCnBulkImportManager extends KiroBulkImportManager {
|
|
|
737
885
|
if (
|
|
738
886
|
soft
|
|
739
887
|
&& accountsProbe?.status === 200
|
|
888
|
+
&& !loginHtml
|
|
889
|
+
&& accountsProbe?.data?._notJson !== true
|
|
740
890
|
&& Array.isArray(accountList)
|
|
741
891
|
&& accountList.length === 0
|
|
742
|
-
&& attempt >=
|
|
892
|
+
&& attempt >= 3
|
|
743
893
|
) {
|
|
744
894
|
this.setAccountStep(
|
|
745
895
|
account,
|
|
@@ -754,7 +904,7 @@ export class CodeBuddyCnBulkImportManager extends KiroBulkImportManager {
|
|
|
754
904
|
this.setAccountStep(
|
|
755
905
|
account,
|
|
756
906
|
"resolving_enterprise",
|
|
757
|
-
`Console not ready (HTTP ${accountsProbe?.status || 0}, accounts=${accountList.length}) — ${attempt + 1}/${
|
|
907
|
+
`Console not ready (HTTP ${accountsProbe?.status || 0}, accounts=${accountList.length}${loginHtml ? ", login HTML" : ""}) — ${attempt + 1}/${CODEBUDDY_CN_OIDC_MAX_ATTEMPTS} body=${lastPayloadSnippet.slice(0, 80)}`,
|
|
758
908
|
);
|
|
759
909
|
await this.persistJobSnapshot(job, { forcePreview: false });
|
|
760
910
|
}
|
|
@@ -780,82 +930,150 @@ export class CodeBuddyCnBulkImportManager extends KiroBulkImportManager {
|
|
|
780
930
|
this.setAccountStep(account, "creating_api_key", `Creating API key (enterprise=${userEnterpriseId}, accounts=${accountList.length})`);
|
|
781
931
|
await this.persistJobSnapshot(job, { forcePreview: true });
|
|
782
932
|
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
Accept: "application/json, text/plain, */*",
|
|
794
|
-
"x-requested-with": "XMLHttpRequest",
|
|
795
|
-
"X-Domain": "www.codebuddy.cn",
|
|
796
|
-
"X-Product": "SaaS",
|
|
797
|
-
},
|
|
798
|
-
body: JSON.stringify({
|
|
799
|
-
name: `zevai-router-${Date.now()}`,
|
|
800
|
-
expire_in_days: 365,
|
|
801
|
-
user_enterprise_id: entId,
|
|
802
|
-
}),
|
|
803
|
-
});
|
|
804
|
-
const text = await res.text().catch(() => "");
|
|
805
|
-
let data = null;
|
|
933
|
+
// Keep one name for every safe retry in this capture attempt. A timed-out
|
|
934
|
+
// POST has an unknown outcome and must never be sent again automatically.
|
|
935
|
+
const apiKeyName = `zevai-router-${account.workerId || "account"}-${Date.now()}`;
|
|
936
|
+
const createKeyOnPage = async (enterpriseId) => page.evaluate(async ({
|
|
937
|
+
enterpriseId: entId,
|
|
938
|
+
keyName,
|
|
939
|
+
timeoutMs,
|
|
940
|
+
}) => {
|
|
941
|
+
const controller = new AbortController();
|
|
942
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
806
943
|
try {
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
944
|
+
const host = window.location.hostname || "www.codebuddy.cn";
|
|
945
|
+
const base = host === "www.codebuddy.cn"
|
|
946
|
+
? window.location.origin
|
|
947
|
+
: "https://www.codebuddy.cn";
|
|
948
|
+
const res = await fetch(`${base}/console/api/client/v1/api-keys`, {
|
|
949
|
+
method: "POST",
|
|
950
|
+
credentials: "include",
|
|
951
|
+
signal: controller.signal,
|
|
952
|
+
headers: {
|
|
953
|
+
"Content-Type": "application/json",
|
|
954
|
+
Accept: "application/json, text/plain, */*",
|
|
955
|
+
"x-requested-with": "XMLHttpRequest",
|
|
956
|
+
"X-Domain": "www.codebuddy.cn",
|
|
957
|
+
"X-Product": "SaaS",
|
|
958
|
+
},
|
|
959
|
+
body: JSON.stringify({
|
|
960
|
+
name: keyName,
|
|
961
|
+
expire_in_days: 365,
|
|
962
|
+
user_enterprise_id: entId,
|
|
963
|
+
}),
|
|
964
|
+
});
|
|
965
|
+
const text = await res.text().catch(() => "");
|
|
966
|
+
let data = null;
|
|
967
|
+
try {
|
|
968
|
+
data = text ? JSON.parse(text) : null;
|
|
969
|
+
} catch {
|
|
970
|
+
data = { _raw: String(text || "").slice(0, 200) };
|
|
971
|
+
}
|
|
972
|
+
return { ok: res.ok, status: res.status, data };
|
|
973
|
+
} catch (error) {
|
|
974
|
+
// Fetch/network failures after a POST starts are ambiguous: the server
|
|
975
|
+
// may have created the key even if the browser lost the response.
|
|
976
|
+
return {
|
|
977
|
+
ok: false,
|
|
978
|
+
status: 0,
|
|
979
|
+
outcomeUnknown: true,
|
|
980
|
+
timedOut: error?.name === "AbortError",
|
|
981
|
+
error: error?.message || String(error),
|
|
982
|
+
};
|
|
983
|
+
} finally {
|
|
984
|
+
clearTimeout(timer);
|
|
985
|
+
}
|
|
986
|
+
}, {
|
|
987
|
+
enterpriseId,
|
|
988
|
+
keyName: apiKeyName,
|
|
989
|
+
timeoutMs: CODEBUDDY_CN_API_KEY_REQUEST_TIMEOUT_MS,
|
|
990
|
+
});
|
|
991
|
+
|
|
992
|
+
const requestApiKey = async (enterpriseId, label) => {
|
|
993
|
+
const startedAt = Date.now();
|
|
994
|
+
let heartbeatPromise = null;
|
|
995
|
+
const heartbeat = setInterval(() => {
|
|
996
|
+
if (heartbeatPromise) return;
|
|
997
|
+
const elapsedSeconds = Math.max(5, Math.round((Date.now() - startedAt) / 1000));
|
|
998
|
+
this.setAccountStep(
|
|
999
|
+
account,
|
|
1000
|
+
"creating_api_key",
|
|
1001
|
+
`${label} — waiting for CodeBuddy (${elapsedSeconds}s)`,
|
|
1002
|
+
);
|
|
1003
|
+
heartbeatPromise = this.persistJobSnapshot(job, { forcePreview: false })
|
|
1004
|
+
.catch(() => null)
|
|
1005
|
+
.finally(() => {
|
|
1006
|
+
heartbeatPromise = null;
|
|
1007
|
+
});
|
|
1008
|
+
}, 5_000);
|
|
1009
|
+
if (typeof heartbeat.unref === "function") heartbeat.unref();
|
|
1010
|
+
|
|
1011
|
+
let result;
|
|
1012
|
+
try {
|
|
1013
|
+
result = await withTimeoutCleanup(createKeyOnPage(enterpriseId), {
|
|
1014
|
+
timeoutMs: CODEBUDDY_CN_API_KEY_REQUEST_TIMEOUT_MS,
|
|
1015
|
+
message: `API key request timed out after ${CODEBUDDY_CN_API_KEY_REQUEST_TIMEOUT_MS / 1000}s; creation outcome is unknown`,
|
|
1016
|
+
code: CODEBUDDY_CN_API_KEY_OUTCOME_UNKNOWN,
|
|
1017
|
+
});
|
|
1018
|
+
} catch (error) {
|
|
1019
|
+
if (error?.code === CODEBUDDY_CN_API_KEY_OUTCOME_UNKNOWN) throw error;
|
|
1020
|
+
throw Object.assign(
|
|
1021
|
+
new Error(`API key request lost its response; creation outcome is unknown: ${error?.message || String(error)}`),
|
|
1022
|
+
{ code: CODEBUDDY_CN_API_KEY_OUTCOME_UNKNOWN },
|
|
1023
|
+
);
|
|
1024
|
+
} finally {
|
|
1025
|
+
clearInterval(heartbeat);
|
|
1026
|
+
if (heartbeatPromise) await heartbeatPromise.catch(() => null);
|
|
810
1027
|
}
|
|
811
|
-
|
|
812
|
-
|
|
1028
|
+
|
|
1029
|
+
if (result?.outcomeUnknown) {
|
|
1030
|
+
const reason = result.timedOut
|
|
1031
|
+
? `timed out after ${CODEBUDDY_CN_API_KEY_REQUEST_TIMEOUT_MS / 1000}s`
|
|
1032
|
+
: `lost its response (${result.error || "network error"})`;
|
|
1033
|
+
throw Object.assign(
|
|
1034
|
+
new Error(`API key request ${reason}; creation outcome is unknown`),
|
|
1035
|
+
{ code: CODEBUDDY_CN_API_KEY_OUTCOME_UNKNOWN },
|
|
1036
|
+
);
|
|
1037
|
+
}
|
|
1038
|
+
return result;
|
|
1039
|
+
};
|
|
813
1040
|
|
|
814
1041
|
// Always open keys page first (SPA hydrates CSRF / host-key there).
|
|
815
|
-
await
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
1042
|
+
const keysPageReady = await navigateConsole("https://www.codebuddy.cn/profile/keys");
|
|
1043
|
+
if (!keysPageReady) {
|
|
1044
|
+
throw Object.assign(
|
|
1045
|
+
new Error(`Keys page navigation timed out after ${CODEBUDDY_CN_CONSOLE_NAV_TIMEOUT_MS / 1000}s`),
|
|
1046
|
+
{ code: "CN_CONSOLE_NAV_TIMEOUT" },
|
|
1047
|
+
);
|
|
1048
|
+
}
|
|
820
1049
|
|
|
821
|
-
let apiKeyResult = await
|
|
1050
|
+
let apiKeyResult = await requestApiKey(userEnterpriseId, "Creating API key");
|
|
822
1051
|
|
|
823
|
-
//
|
|
1052
|
+
// A confirmed 400 can safely retry with the personal enterprise id. Do
|
|
1053
|
+
// not retry 5xx/network failures because the POST outcome is ambiguous.
|
|
824
1054
|
if (
|
|
825
|
-
|
|
1055
|
+
apiKeyResult?.status === 400
|
|
826
1056
|
&& userEnterpriseId !== PERSONAL_ENTERPRISE_ID
|
|
827
1057
|
) {
|
|
828
1058
|
this.setAccountStep(account, "retrying_api_key", "Retrying with personal-edition enterprise id");
|
|
829
1059
|
await this.persistJobSnapshot(job, { forcePreview: false });
|
|
830
|
-
apiKeyResult = await
|
|
831
|
-
}
|
|
832
|
-
|
|
833
|
-
// Retry from console root if keys page POST failed.
|
|
834
|
-
if (!apiKeyResult || !apiKeyResult.ok) {
|
|
835
|
-
this.setAccountStep(account, "retrying_api_key", "Retrying API key from /console");
|
|
836
|
-
await this.persistJobSnapshot(job, { forcePreview: true });
|
|
837
|
-
await page.goto("https://www.codebuddy.cn/console", {
|
|
838
|
-
waitUntil: "domcontentloaded",
|
|
839
|
-
timeout: 45_000,
|
|
840
|
-
}).catch(() => null);
|
|
841
|
-
await waitAfterNav();
|
|
842
|
-
await page.goto("https://www.codebuddy.cn/profile/keys", {
|
|
843
|
-
waitUntil: "domcontentloaded",
|
|
844
|
-
timeout: 45_000,
|
|
845
|
-
}).catch(() => null);
|
|
846
|
-
await waitAfterNav();
|
|
847
|
-
apiKeyResult = await createKeyOnPage(PERSONAL_ENTERPRISE_ID).catch(() => null);
|
|
1060
|
+
apiKeyResult = await requestApiKey(PERSONAL_ENTERPRISE_ID, "Retrying personal API key");
|
|
848
1061
|
}
|
|
849
1062
|
|
|
850
1063
|
// Retry loop on 401/403 — openresty edge blocks create-key when Keycloak
|
|
851
1064
|
// cookies are half-synced (common on slow proxies). Nudge OIDC handoff,
|
|
852
|
-
// wait for strong session, then retry
|
|
853
|
-
const isAuthBlocked = (
|
|
854
|
-
|
|
1065
|
+
// wait for strong session, then retry with a strict round cap.
|
|
1066
|
+
const isAuthBlocked = (result) =>
|
|
1067
|
+
result?.ok === false && (result.status === 401 || result.status === 403);
|
|
1068
|
+
for (
|
|
1069
|
+
let round = 1;
|
|
1070
|
+
round <= CODEBUDDY_CN_API_REHANDOFF_ROUNDS && isAuthBlocked(apiKeyResult);
|
|
1071
|
+
round += 1
|
|
1072
|
+
) {
|
|
855
1073
|
this.setAccountStep(
|
|
856
1074
|
account,
|
|
857
1075
|
"retrying_api_key",
|
|
858
|
-
`API key 401/403 — OIDC re-handoff round ${round}
|
|
1076
|
+
`API key 401/403 — OIDC re-handoff round ${round}/${CODEBUDDY_CN_API_REHANDOFF_ROUNDS} (waiting strong session)`,
|
|
859
1077
|
);
|
|
860
1078
|
await this.persistJobSnapshot(job, { forcePreview: true });
|
|
861
1079
|
for (const path of [
|
|
@@ -863,15 +1081,17 @@ export class CodeBuddyCnBulkImportManager extends KiroBulkImportManager {
|
|
|
863
1081
|
"https://www.codebuddy.cn/console",
|
|
864
1082
|
"https://www.codebuddy.cn/profile/keys",
|
|
865
1083
|
]) {
|
|
866
|
-
await
|
|
867
|
-
await waitAfterNav();
|
|
1084
|
+
await navigateConsole(path);
|
|
868
1085
|
}
|
|
869
1086
|
// Wait for strong Keycloak cookie — openresty accepts api-keys only after full session.
|
|
870
1087
|
await waitUntil(async () => {
|
|
871
1088
|
const snap = await cookieSnapshot();
|
|
872
1089
|
return hasStrongKeycloak(snap.names);
|
|
873
1090
|
}, { timeout: 8_000 * round, interval: 300 }).catch(() => null);
|
|
874
|
-
apiKeyResult = await
|
|
1091
|
+
apiKeyResult = await requestApiKey(
|
|
1092
|
+
PERSONAL_ENTERPRISE_ID,
|
|
1093
|
+
`Retrying API key after OIDC handoff ${round}/${CODEBUDDY_CN_API_REHANDOFF_ROUNDS}`,
|
|
1094
|
+
);
|
|
875
1095
|
}
|
|
876
1096
|
|
|
877
1097
|
const businessCode = apiKeyResult?.data?.code;
|
|
@@ -904,8 +1124,9 @@ export class CodeBuddyCnBulkImportManager extends KiroBulkImportManager {
|
|
|
904
1124
|
apiKeyResult.data.secret;
|
|
905
1125
|
|
|
906
1126
|
if (!apiKey || typeof apiKey !== "string") {
|
|
907
|
-
throw
|
|
908
|
-
`API key response did not contain a key field: ${JSON.stringify(apiKeyResult.data).slice(0, 300)}
|
|
1127
|
+
throw Object.assign(
|
|
1128
|
+
new Error(`API key response did not contain a key field; creation outcome is unknown: ${JSON.stringify(apiKeyResult.data).slice(0, 300)}`),
|
|
1129
|
+
{ code: CODEBUDDY_CN_API_KEY_OUTCOME_UNKNOWN },
|
|
909
1130
|
);
|
|
910
1131
|
}
|
|
911
1132
|
|
|
@@ -925,7 +1146,7 @@ export class CodeBuddyCnBulkImportManager extends KiroBulkImportManager {
|
|
|
925
1146
|
});
|
|
926
1147
|
|
|
927
1148
|
// Step 10: Finish 5sim order + finalize
|
|
928
|
-
await fiveSimClient.finishOrder(fiveSimOrderId);
|
|
1149
|
+
await settleFiveSimOrder(() => fiveSimClient.finishOrder(fiveSimOrderId));
|
|
929
1150
|
|
|
930
1151
|
this.finalizeAccount(account, "success", {
|
|
931
1152
|
connectionId: connection.id,
|
|
@@ -933,21 +1154,35 @@ export class CodeBuddyCnBulkImportManager extends KiroBulkImportManager {
|
|
|
933
1154
|
message: `CodeBuddy CN connection saved (phone: ${account.phone})`,
|
|
934
1155
|
});
|
|
935
1156
|
account.runtimeSession = null;
|
|
936
|
-
await context
|
|
1157
|
+
await closeContextOrBrowser(context, job);
|
|
937
1158
|
await this.persistJobSnapshot(job, { forcePreview: true });
|
|
938
1159
|
} catch (error) {
|
|
939
1160
|
// If API key capture fails after registration, the account is registered
|
|
940
1161
|
// but we don't have a key. Surface as needs_manual so the operator can
|
|
941
1162
|
// create the key manually in the opened browser — number is NOT re-bought.
|
|
1163
|
+
const outcomeUnknown = error?.code === CODEBUDDY_CN_API_KEY_OUTCOME_UNKNOWN;
|
|
1164
|
+
const failureMessage = outcomeUnknown
|
|
1165
|
+
? `${error.message}. Check the CodeBuddy keys page before creating another key.`
|
|
1166
|
+
: error.message;
|
|
942
1167
|
this.finalizeAccount(account, "needs_manual", {
|
|
943
|
-
error: `Registration succeeded but API key capture failed: ${
|
|
944
|
-
step: "awaiting_manual",
|
|
945
|
-
message:
|
|
1168
|
+
error: `Registration succeeded but API key capture failed: ${failureMessage}`,
|
|
1169
|
+
step: outcomeUnknown ? "api_key_outcome_unknown" : "awaiting_manual",
|
|
1170
|
+
message: outcomeUnknown
|
|
1171
|
+
? `Registration done; API key request outcome is unknown. Check existing keys before retrying.`
|
|
1172
|
+
: `Registration done, API key capture failed: ${error.message}`,
|
|
946
1173
|
});
|
|
947
1174
|
// The 5sim order was successful (SMS received) — finish it (no re-order)
|
|
948
|
-
await fiveSimClient.finishOrder(fiveSimOrderId)
|
|
1175
|
+
await settleFiveSimOrder(() => fiveSimClient.finishOrder(fiveSimOrderId));
|
|
949
1176
|
await this.persistJobSnapshot(job, { forcePreview: true });
|
|
950
1177
|
|
|
1178
|
+
if (outcomeUnknown) {
|
|
1179
|
+
// Closing the page aborts any late browser work. Automatic/manual POST
|
|
1180
|
+
// retries are intentionally disabled because the key may already exist.
|
|
1181
|
+
account.runtimeSession = null;
|
|
1182
|
+
await closeContextOrBrowser(context, job);
|
|
1183
|
+
return;
|
|
1184
|
+
}
|
|
1185
|
+
|
|
951
1186
|
// Start manual followup for API key capture (reuse same browser session)
|
|
952
1187
|
await this.runCnManualFollowup(job, account, account.workerId, context, page, fiveSimClient, fiveSimOrderId);
|
|
953
1188
|
}
|
|
@@ -963,18 +1198,21 @@ export class CodeBuddyCnBulkImportManager extends KiroBulkImportManager {
|
|
|
963
1198
|
const ms = account.manualSession;
|
|
964
1199
|
const ctx = ms?.context || context;
|
|
965
1200
|
const headed = ms?.headedBrowser || null;
|
|
966
|
-
|
|
967
|
-
if (headed) await headed
|
|
1201
|
+
await closeContextOrBrowser(ctx, job);
|
|
1202
|
+
if (headed) await forceCloseBrowser(headed).catch(() => null);
|
|
968
1203
|
};
|
|
969
1204
|
|
|
970
1205
|
try {
|
|
971
1206
|
this.setAccountStep(account, "manual_waiting", "Waiting for operator to complete in headed browser");
|
|
972
1207
|
await this.persistJobSnapshot(job, { forcePreview: true });
|
|
973
1208
|
|
|
974
|
-
// Wait
|
|
975
|
-
|
|
976
|
-
|
|
1209
|
+
// Wait up to 3 minutes on low-memory hosts, otherwise 8 minutes.
|
|
1210
|
+
const manualTimeoutMs = isLowMemHost()
|
|
1211
|
+
? CODEBUDDY_CN_LOW_MEM_MANUAL_TIMEOUT_MS
|
|
1212
|
+
: CODEBUDDY_CN_MANUAL_TIMEOUT_MS;
|
|
1213
|
+
const deadline = Date.now() + manualTimeoutMs;
|
|
977
1214
|
let apiKey = null;
|
|
1215
|
+
const manualApiKeyName = `zevai-router-manual-${account.workerId || "account"}-${Date.now()}`;
|
|
978
1216
|
|
|
979
1217
|
while (Date.now() < deadline && !job.cancelRequested) {
|
|
980
1218
|
await new Promise((r) => setTimeout(r, 10_000)); // Check every 10s
|
|
@@ -985,28 +1223,60 @@ export class CodeBuddyCnBulkImportManager extends KiroBulkImportManager {
|
|
|
985
1223
|
if (!currentUrl.includes("codebuddy.cn")) continue;
|
|
986
1224
|
|
|
987
1225
|
// Try to create an API key via the console API (include enterprise id)
|
|
988
|
-
const result = await page.evaluate(async () => {
|
|
989
|
-
const
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1226
|
+
const result = await withTimeoutCleanup(page.evaluate(async ({ keyName, timeoutMs }) => {
|
|
1227
|
+
const controller = new AbortController();
|
|
1228
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
1229
|
+
try {
|
|
1230
|
+
const host = window.location.hostname || "www.codebuddy.cn";
|
|
1231
|
+
const base = host === "www.codebuddy.cn"
|
|
1232
|
+
? window.location.origin
|
|
1233
|
+
: "https://www.codebuddy.cn";
|
|
1234
|
+
const res = await fetch(`${base}/console/api/client/v1/api-keys`, {
|
|
1235
|
+
method: "POST",
|
|
1236
|
+
headers: {
|
|
1237
|
+
"Content-Type": "application/json",
|
|
1238
|
+
Accept: "application/json, text/plain, */*",
|
|
1239
|
+
"x-requested-with": "XMLHttpRequest",
|
|
1240
|
+
"X-Domain": "www.codebuddy.cn",
|
|
1241
|
+
"X-Product": "SaaS",
|
|
1242
|
+
},
|
|
1243
|
+
credentials: "include",
|
|
1244
|
+
signal: controller.signal,
|
|
1245
|
+
body: JSON.stringify({
|
|
1246
|
+
name: keyName,
|
|
1247
|
+
expire_in_days: 365,
|
|
1248
|
+
user_enterprise_id: "personal-edition-user-id",
|
|
1249
|
+
}),
|
|
1250
|
+
});
|
|
1251
|
+
const data = await res.json().catch(() => null);
|
|
1252
|
+
return { ok: res.ok, status: res.status, data };
|
|
1253
|
+
} catch (error) {
|
|
1254
|
+
return {
|
|
1255
|
+
ok: false,
|
|
1256
|
+
status: 0,
|
|
1257
|
+
outcomeUnknown: true,
|
|
1258
|
+
error: error?.message || String(error),
|
|
1259
|
+
};
|
|
1260
|
+
} finally {
|
|
1261
|
+
clearTimeout(timer);
|
|
1262
|
+
}
|
|
1263
|
+
}, {
|
|
1264
|
+
keyName: manualApiKeyName,
|
|
1265
|
+
timeoutMs: CODEBUDDY_CN_API_KEY_REQUEST_TIMEOUT_MS,
|
|
1266
|
+
}), {
|
|
1267
|
+
timeoutMs: CODEBUDDY_CN_API_KEY_REQUEST_TIMEOUT_MS,
|
|
1268
|
+
message: "Manual API key request timed out; creation outcome is unknown",
|
|
1269
|
+
code: CODEBUDDY_CN_API_KEY_OUTCOME_UNKNOWN,
|
|
1007
1270
|
});
|
|
1008
1271
|
|
|
1009
|
-
if (result?.
|
|
1272
|
+
if (result?.outcomeUnknown) {
|
|
1273
|
+
throw Object.assign(
|
|
1274
|
+
new Error(`Manual API key request lost its response; creation outcome is unknown: ${result.error || "network error"}`),
|
|
1275
|
+
{ code: CODEBUDDY_CN_API_KEY_OUTCOME_UNKNOWN },
|
|
1276
|
+
);
|
|
1277
|
+
}
|
|
1278
|
+
|
|
1279
|
+
if (result?.ok) {
|
|
1010
1280
|
const payload = result.data?.data || result.data;
|
|
1011
1281
|
apiKey =
|
|
1012
1282
|
payload?.apiKey ||
|
|
@@ -1016,8 +1286,13 @@ export class CodeBuddyCnBulkImportManager extends KiroBulkImportManager {
|
|
|
1016
1286
|
payload?.api_key ||
|
|
1017
1287
|
(typeof payload === "string" ? payload : null);
|
|
1018
1288
|
if (apiKey && typeof apiKey === "string") break;
|
|
1289
|
+
throw Object.assign(
|
|
1290
|
+
new Error("Manual API key response was successful but did not contain the key; creation outcome is unknown"),
|
|
1291
|
+
{ code: CODEBUDDY_CN_API_KEY_OUTCOME_UNKNOWN },
|
|
1292
|
+
);
|
|
1019
1293
|
}
|
|
1020
|
-
} catch {
|
|
1294
|
+
} catch (error) {
|
|
1295
|
+
if (error?.code === CODEBUDDY_CN_API_KEY_OUTCOME_UNKNOWN) throw error;
|
|
1021
1296
|
// Operator might still be completing — keep waiting
|
|
1022
1297
|
}
|
|
1023
1298
|
}
|
|
@@ -1061,6 +1336,12 @@ export class CodeBuddyCnBulkImportManager extends KiroBulkImportManager {
|
|
|
1061
1336
|
step: "cancelled",
|
|
1062
1337
|
message: "Job cancelled while waiting for manual completion",
|
|
1063
1338
|
});
|
|
1339
|
+
} else if (error?.code === CODEBUDDY_CN_API_KEY_OUTCOME_UNKNOWN) {
|
|
1340
|
+
this.finalizeAccount(account, "needs_manual", {
|
|
1341
|
+
error: `${error.message}. Check existing CodeBuddy keys before retrying.`,
|
|
1342
|
+
step: "api_key_outcome_unknown",
|
|
1343
|
+
message: "Manual API key request outcome is unknown; automatic retries stopped",
|
|
1344
|
+
});
|
|
1064
1345
|
} else {
|
|
1065
1346
|
this.finalizeAccount(account, "failed", {
|
|
1066
1347
|
error: error.message || "Manual assist flow failed",
|
|
@@ -1244,4 +1525,20 @@ export const __test__ = {
|
|
|
1244
1525
|
sanitizeCnJob,
|
|
1245
1526
|
defaultPhoneFormatter,
|
|
1246
1527
|
defaultSaveCodeBuddyCnConnection,
|
|
1528
|
+
isLoginHtmlProbe,
|
|
1529
|
+
withTimeoutCleanup,
|
|
1530
|
+
AUTOMATION_LIMITS: {
|
|
1531
|
+
registrationHardTimeoutMs: CODEBUDDY_CN_ACCOUNT_HARD_TIMEOUT_MS,
|
|
1532
|
+
browserLaunchTimeoutMs: CODEBUDDY_CN_BROWSER_LAUNCH_TIMEOUT_MS,
|
|
1533
|
+
contextTimeoutMs: CODEBUDDY_CN_CONTEXT_TIMEOUT_MS,
|
|
1534
|
+
consoleNavTimeoutMs: CODEBUDDY_CN_CONSOLE_NAV_TIMEOUT_MS,
|
|
1535
|
+
consoleProbeTimeoutMs: CODEBUDDY_CN_CONSOLE_PROBE_TIMEOUT_MS,
|
|
1536
|
+
apiKeyRequestTimeoutMs: CODEBUDDY_CN_API_KEY_REQUEST_TIMEOUT_MS,
|
|
1537
|
+
oidcMaxAttempts: CODEBUDDY_CN_OIDC_MAX_ATTEMPTS,
|
|
1538
|
+
apiRehandoffRounds: CODEBUDDY_CN_API_REHANDOFF_ROUNDS,
|
|
1539
|
+
manualTimeoutMs: CODEBUDDY_CN_MANUAL_TIMEOUT_MS,
|
|
1540
|
+
lowMemoryManualTimeoutMs: CODEBUDDY_CN_LOW_MEM_MANUAL_TIMEOUT_MS,
|
|
1541
|
+
resourceCloseTimeoutMs: CODEBUDDY_CN_RESOURCE_CLOSE_TIMEOUT_MS,
|
|
1542
|
+
fiveSimSettleTimeoutMs: CODEBUDDY_CN_FIVESIM_SETTLE_TIMEOUT_MS,
|
|
1543
|
+
},
|
|
1247
1544
|
};
|