9router 0.3.51 → 0.3.52
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/BUILD_ID +1 -1
- package/app/.next/app-path-routes-manifest.json +35 -35
- package/app/.next/build-manifest.json +2 -2
- package/app/.next/prerender-manifest.json +3 -3
- package/app/.next/server/app/(dashboard)/dashboard/cli-tools/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/combos/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/console-log/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/endpoint/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/mitm/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/profile/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/providers/[id]/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/providers/new/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/providers/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/proxy-pools/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/quota/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/translator/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/usage/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/_global-error.html +2 -2
- package/app/.next/server/app/_global-error.rsc +1 -1
- package/app/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/app/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/app/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/app/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/app/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/app/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/app/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/_not-found.html +1 -1
- package/app/.next/server/app/_not-found.rsc +3 -3
- package/app/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
- package/app/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/app/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
- package/app/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/app/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/app/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/app/.next/server/app/api/auth/login/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/auth/logout/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/cli-tools/antigravity-mitm/alias/route.js +2 -2
- package/app/.next/server/app/api/cli-tools/antigravity-mitm/alias/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/cli-tools/antigravity-mitm/route.js +1 -1
- package/app/.next/server/app/api/cli-tools/antigravity-mitm/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/cli-tools/claude-settings/route.js +2 -2
- package/app/.next/server/app/api/cli-tools/claude-settings/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/cli-tools/codex-settings/route.js +1 -1
- package/app/.next/server/app/api/cli-tools/codex-settings/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/cli-tools/copilot-settings/route.js +2 -2
- package/app/.next/server/app/api/cli-tools/copilot-settings/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/cli-tools/droid-settings/route.js +2 -2
- package/app/.next/server/app/api/cli-tools/droid-settings/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/cli-tools/openclaw-settings/route.js +2 -2
- package/app/.next/server/app/api/cli-tools/openclaw-settings/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/cli-tools/opencode-settings/route.js +1 -1
- package/app/.next/server/app/api/cli-tools/opencode-settings/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/cloud/auth/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/cloud/credentials/update/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/cloud/model/resolve/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/cloud/models/alias/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/combos/[id]/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/combos/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/init/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/keys/[id]/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/keys/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/locale/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/models/alias/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/models/route.js +1 -1
- package/app/.next/server/app/api/models/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/models/test/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/oauth/[provider]/[action]/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/oauth/cursor/auto-import/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/oauth/cursor/import/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/oauth/iflow/cookie/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/oauth/kiro/auto-import/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/oauth/kiro/import/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/oauth/kiro/social-authorize/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/oauth/kiro/social-exchange/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/pricing/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/provider-nodes/[id]/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/provider-nodes/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/provider-nodes/validate/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/providers/[id]/models/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/providers/[id]/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/providers/[id]/test/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/providers/[id]/test-models/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/providers/client/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/providers/route.js +1 -1
- package/app/.next/server/app/api/providers/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/providers/test-batch/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/providers/validate/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/proxy-pools/[id]/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/proxy-pools/[id]/test/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/proxy-pools/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/settings/database/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/settings/proxy-test/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/settings/require-login/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/settings/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/tags/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/translator/console-logs/route.js +1 -1
- package/app/.next/server/app/api/translator/console-logs/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/translator/console-logs/stream/route.js +1 -1
- package/app/.next/server/app/api/translator/console-logs/stream/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/translator/load/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/translator/save/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/translator/send/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/translator/translate/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/tunnel/disable/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/tunnel/enable/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/tunnel/status/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/usage/[connectionId]/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/usage/chart/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/usage/history/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/usage/providers/route.js +1 -1
- package/app/.next/server/app/api/usage/providers/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/usage/request-details/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/usage/request-logs/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/usage/stats/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/usage/stream/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/v1/api/chat/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/v1/chat/completions/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/v1/embeddings/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/v1/messages/count_tokens/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/v1/messages/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/v1/models/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/v1/responses/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/v1/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/v1beta/models/[...path]/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/v1beta/models/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/version/route.js +1 -1
- package/app/.next/server/app/api/version/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/callback/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/callback.html +1 -1
- package/app/.next/server/app/callback.rsc +3 -3
- package/app/.next/server/app/callback.segments/_full.segment.rsc +3 -3
- package/app/.next/server/app/callback.segments/_head.segment.rsc +1 -1
- package/app/.next/server/app/callback.segments/_index.segment.rsc +3 -3
- package/app/.next/server/app/callback.segments/_tree.segment.rsc +1 -1
- package/app/.next/server/app/callback.segments/callback/__PAGE__.segment.rsc +1 -1
- package/app/.next/server/app/callback.segments/callback.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/cli-tools.html +1 -1
- package/app/.next/server/app/dashboard/cli-tools.rsc +5 -5
- package/app/.next/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk/dashboard/cli-tools/__PAGE__.segment.rsc +2 -2
- package/app/.next/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk/dashboard/cli-tools.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/app/.next/server/app/dashboard/cli-tools.segments/_full.segment.rsc +5 -5
- package/app/.next/server/app/dashboard/cli-tools.segments/_head.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/cli-tools.segments/_index.segment.rsc +3 -3
- package/app/.next/server/app/dashboard/cli-tools.segments/_tree.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/combos.html +1 -1
- package/app/.next/server/app/dashboard/combos.rsc +5 -5
- package/app/.next/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk/dashboard/combos/__PAGE__.segment.rsc +2 -2
- package/app/.next/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk/dashboard/combos.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/app/.next/server/app/dashboard/combos.segments/_full.segment.rsc +5 -5
- package/app/.next/server/app/dashboard/combos.segments/_head.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/combos.segments/_index.segment.rsc +3 -3
- package/app/.next/server/app/dashboard/combos.segments/_tree.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/endpoint.html +1 -1
- package/app/.next/server/app/dashboard/endpoint.rsc +5 -5
- package/app/.next/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk/dashboard/endpoint/__PAGE__.segment.rsc +2 -2
- package/app/.next/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk/dashboard/endpoint.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/app/.next/server/app/dashboard/endpoint.segments/_full.segment.rsc +5 -5
- package/app/.next/server/app/dashboard/endpoint.segments/_head.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/endpoint.segments/_index.segment.rsc +3 -3
- package/app/.next/server/app/dashboard/endpoint.segments/_tree.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/mitm.html +1 -1
- package/app/.next/server/app/dashboard/mitm.rsc +5 -5
- package/app/.next/server/app/dashboard/mitm.segments/!KGRhc2hib2FyZCk/dashboard/mitm/__PAGE__.segment.rsc +2 -2
- package/app/.next/server/app/dashboard/mitm.segments/!KGRhc2hib2FyZCk/dashboard/mitm.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/mitm.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/mitm.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/app/.next/server/app/dashboard/mitm.segments/_full.segment.rsc +5 -5
- package/app/.next/server/app/dashboard/mitm.segments/_head.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/mitm.segments/_index.segment.rsc +3 -3
- package/app/.next/server/app/dashboard/mitm.segments/_tree.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/profile.html +1 -1
- package/app/.next/server/app/dashboard/profile.rsc +5 -5
- package/app/.next/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk/dashboard/profile/__PAGE__.segment.rsc +2 -2
- package/app/.next/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk/dashboard/profile.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/app/.next/server/app/dashboard/profile.segments/_full.segment.rsc +5 -5
- package/app/.next/server/app/dashboard/profile.segments/_head.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/profile.segments/_index.segment.rsc +3 -3
- package/app/.next/server/app/dashboard/profile.segments/_tree.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/providers/new.html +1 -1
- package/app/.next/server/app/dashboard/providers/new.rsc +5 -5
- package/app/.next/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard/providers/new/__PAGE__.segment.rsc +2 -2
- package/app/.next/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard/providers/new.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard/providers.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/app/.next/server/app/dashboard/providers/new.segments/_full.segment.rsc +5 -5
- package/app/.next/server/app/dashboard/providers/new.segments/_head.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/providers/new.segments/_index.segment.rsc +3 -3
- package/app/.next/server/app/dashboard/providers/new.segments/_tree.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/providers.html +1 -1
- package/app/.next/server/app/dashboard/providers.rsc +5 -5
- package/app/.next/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk/dashboard/providers/__PAGE__.segment.rsc +2 -2
- package/app/.next/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk/dashboard/providers.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/app/.next/server/app/dashboard/providers.segments/_full.segment.rsc +5 -5
- package/app/.next/server/app/dashboard/providers.segments/_head.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/providers.segments/_index.segment.rsc +3 -3
- package/app/.next/server/app/dashboard/providers.segments/_tree.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/proxy-pools.html +1 -1
- package/app/.next/server/app/dashboard/proxy-pools.rsc +5 -5
- package/app/.next/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk/dashboard/proxy-pools/__PAGE__.segment.rsc +2 -2
- package/app/.next/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk/dashboard/proxy-pools.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/app/.next/server/app/dashboard/proxy-pools.segments/_full.segment.rsc +5 -5
- package/app/.next/server/app/dashboard/proxy-pools.segments/_head.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/proxy-pools.segments/_index.segment.rsc +3 -3
- package/app/.next/server/app/dashboard/proxy-pools.segments/_tree.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/quota.html +2 -2
- package/app/.next/server/app/dashboard/quota.rsc +4 -4
- package/app/.next/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk/dashboard/quota/__PAGE__.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk/dashboard/quota.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/app/.next/server/app/dashboard/quota.segments/_full.segment.rsc +4 -4
- package/app/.next/server/app/dashboard/quota.segments/_head.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/quota.segments/_index.segment.rsc +3 -3
- package/app/.next/server/app/dashboard/quota.segments/_tree.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/settings/pricing/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/dashboard/settings/pricing.html +1 -1
- package/app/.next/server/app/dashboard/settings/pricing.rsc +3 -3
- package/app/.next/server/app/dashboard/settings/pricing.segments/_full.segment.rsc +3 -3
- package/app/.next/server/app/dashboard/settings/pricing.segments/_head.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/settings/pricing.segments/_index.segment.rsc +3 -3
- package/app/.next/server/app/dashboard/settings/pricing.segments/_tree.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/settings/pricing.segments/dashboard/settings/pricing/__PAGE__.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/settings/pricing.segments/dashboard/settings/pricing.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/settings/pricing.segments/dashboard/settings.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/settings/pricing.segments/dashboard.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/translator.html +1 -1
- package/app/.next/server/app/dashboard/translator.rsc +5 -5
- package/app/.next/server/app/dashboard/translator.segments/!KGRhc2hib2FyZCk/dashboard/translator/__PAGE__.segment.rsc +2 -2
- package/app/.next/server/app/dashboard/translator.segments/!KGRhc2hib2FyZCk/dashboard/translator.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/translator.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/translator.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/app/.next/server/app/dashboard/translator.segments/_full.segment.rsc +5 -5
- package/app/.next/server/app/dashboard/translator.segments/_head.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/translator.segments/_index.segment.rsc +3 -3
- package/app/.next/server/app/dashboard/translator.segments/_tree.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/usage.html +1 -1
- package/app/.next/server/app/dashboard/usage.rsc +5 -5
- package/app/.next/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk/dashboard/usage/__PAGE__.segment.rsc +2 -2
- package/app/.next/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk/dashboard/usage.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/app/.next/server/app/dashboard/usage.segments/_full.segment.rsc +5 -5
- package/app/.next/server/app/dashboard/usage.segments/_head.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/usage.segments/_index.segment.rsc +3 -3
- package/app/.next/server/app/dashboard/usage.segments/_tree.segment.rsc +1 -1
- package/app/.next/server/app/dashboard.html +1 -1
- package/app/.next/server/app/dashboard.rsc +5 -5
- package/app/.next/server/app/dashboard.segments/!KGRhc2hib2FyZCk/dashboard/__PAGE__.segment.rsc +2 -2
- package/app/.next/server/app/dashboard.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/app/.next/server/app/dashboard.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/app/.next/server/app/dashboard.segments/_full.segment.rsc +5 -5
- package/app/.next/server/app/dashboard.segments/_head.segment.rsc +1 -1
- package/app/.next/server/app/dashboard.segments/_index.segment.rsc +3 -3
- package/app/.next/server/app/dashboard.segments/_tree.segment.rsc +1 -1
- package/app/.next/server/app/index.html +1 -1
- package/app/.next/server/app/index.rsc +3 -3
- package/app/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/app/.next/server/app/index.segments/_full.segment.rsc +3 -3
- package/app/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/app/.next/server/app/index.segments/_index.segment.rsc +3 -3
- package/app/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/app/.next/server/app/landing/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/landing.html +1 -1
- package/app/.next/server/app/landing.rsc +3 -3
- package/app/.next/server/app/landing.segments/_full.segment.rsc +3 -3
- package/app/.next/server/app/landing.segments/_head.segment.rsc +1 -1
- package/app/.next/server/app/landing.segments/_index.segment.rsc +3 -3
- package/app/.next/server/app/landing.segments/_tree.segment.rsc +1 -1
- package/app/.next/server/app/landing.segments/landing/__PAGE__.segment.rsc +1 -1
- package/app/.next/server/app/landing.segments/landing.segment.rsc +1 -1
- package/app/.next/server/app/login/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/login.html +1 -1
- package/app/.next/server/app/login.rsc +4 -4
- package/app/.next/server/app/login.segments/_full.segment.rsc +4 -4
- package/app/.next/server/app/login.segments/_head.segment.rsc +1 -1
- package/app/.next/server/app/login.segments/_index.segment.rsc +3 -3
- package/app/.next/server/app/login.segments/_tree.segment.rsc +1 -1
- package/app/.next/server/app/login.segments/login/__PAGE__.segment.rsc +2 -2
- package/app/.next/server/app/login.segments/login.segment.rsc +1 -1
- package/app/.next/server/app/manifest.webmanifest/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app-paths-manifest.json +35 -35
- package/app/.next/server/chunks/1114.js +1 -1
- package/app/.next/server/chunks/1424.js +1 -1
- package/app/.next/server/chunks/318.js +1 -1
- package/app/.next/server/chunks/4989.js +1 -1
- package/app/.next/server/chunks/6182.js +1 -1
- package/app/.next/server/chunks/649.js +1 -1
- package/app/.next/server/chunks/9201.js +1 -1
- package/app/.next/server/pages/404.html +1 -1
- package/app/.next/server/pages/500.html +2 -2
- package/app/.next/server/server-reference-manifest.js +1 -1
- package/app/.next/server/server-reference-manifest.json +1 -1
- package/app/.next/static/chunks/{5497-2ffdc00508844dd5.js → 5497-d8f3c314a3499978.js} +1 -1
- package/app/.next/static/chunks/{9242-911fd2719103a7fa.js → 9242-3fb6423adcc6e277.js} +1 -1
- package/app/.next/static/chunks/app/{layout-f3021d4efcb79499.js → layout-de7fd6e41a79bed7.js} +1 -1
- package/app/package.json +1 -1
- package/app/src/mitm/cert/install.js +4 -2
- package/app/src/mitm/server.js +40 -23
- package/app/src/mitm/server2.js +266 -57
- package/package.json +1 -1
- /package/app/.next/static/{T7L0jvobZfRknPKh4v85- → I0MjnG4BJTOdnQP-tVU65}/_buildManifest.js +0 -0
- /package/app/.next/static/{T7L0jvobZfRknPKh4v85- → I0MjnG4BJTOdnQP-tVU65}/_ssgManifest.js +0 -0
|
@@ -74,9 +74,11 @@ async function installCert(sudoPassword, certPath) {
|
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
async function installCertMac(sudoPassword, certPath) {
|
|
77
|
-
|
|
77
|
+
// Remove all old certs with same name first to avoid duplicate/stale cert conflict
|
|
78
|
+
const deleteOld = `security delete-certificate -c "9Router MITM Root CA" /Library/Keychains/System.keychain 2>/dev/null || true`;
|
|
79
|
+
const install = `security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain "${certPath}"`;
|
|
78
80
|
try {
|
|
79
|
-
await execWithPassword(
|
|
81
|
+
await execWithPassword(`${deleteOld} && ${install}`, sudoPassword);
|
|
80
82
|
console.log(`✅ Installed certificate to system keychain: ${certPath}`);
|
|
81
83
|
} catch (error) {
|
|
82
84
|
const msg = error.message?.includes("canceled") ? "User canceled authorization" : "Certificate install failed";
|
package/app/src/mitm/server.js
CHANGED
|
@@ -4,6 +4,9 @@ const path = require("path");
|
|
|
4
4
|
const dns = require("dns");
|
|
5
5
|
const { promisify } = require("util");
|
|
6
6
|
|
|
7
|
+
// Allow self-signed certs from MITM root CA when fetching external hosts
|
|
8
|
+
|
|
9
|
+
|
|
7
10
|
const INTERNAL_REQUEST_HEADER = { name: "x-request-source", value: "local" };
|
|
8
11
|
|
|
9
12
|
// All intercepted domains across all tools
|
|
@@ -198,6 +201,13 @@ async function intercept(req, res, bodyBuffer, mappedModel) {
|
|
|
198
201
|
if (ct.includes("text/event-stream")) resHeaders["X-Accel-Buffering"] = "no";
|
|
199
202
|
res.writeHead(200, resHeaders);
|
|
200
203
|
|
|
204
|
+
// Guard: some responses have no body (e.g. errors, empty replies)
|
|
205
|
+
if (!response.body) {
|
|
206
|
+
const text = await response.text().catch(() => "");
|
|
207
|
+
res.end(text);
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
|
|
201
211
|
const reader = response.body.getReader();
|
|
202
212
|
const decoder = new TextDecoder();
|
|
203
213
|
while (true) {
|
|
@@ -213,37 +223,44 @@ async function intercept(req, res, bodyBuffer, mappedModel) {
|
|
|
213
223
|
}
|
|
214
224
|
|
|
215
225
|
const server = https.createServer(sslOptions, async (req, res) => {
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
226
|
+
// Top-level catch to prevent uncaughtException from crashing the server
|
|
227
|
+
try {
|
|
228
|
+
if (req.url === "/_mitm_health") {
|
|
229
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
230
|
+
res.end(JSON.stringify({ ok: true, pid: process.pid }));
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
221
233
|
|
|
222
|
-
|
|
223
|
-
|
|
234
|
+
const bodyBuffer = await collectBodyRaw(req);
|
|
235
|
+
if (bodyBuffer.length > 0) saveRequestLog(req.url, bodyBuffer);
|
|
224
236
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
237
|
+
// Anti-loop: requests originating from 9Router bypass interception
|
|
238
|
+
if (req.headers[INTERNAL_REQUEST_HEADER.name] === INTERNAL_REQUEST_HEADER.value) {
|
|
239
|
+
return passthrough(req, res, bodyBuffer);
|
|
240
|
+
}
|
|
229
241
|
|
|
230
|
-
|
|
231
|
-
|
|
242
|
+
const tool = getToolForHost(req.headers.host);
|
|
243
|
+
if (!tool) return passthrough(req, res, bodyBuffer);
|
|
232
244
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
245
|
+
// Check if this URL should be intercepted based on tool
|
|
246
|
+
const isChat = tool === "antigravity"
|
|
247
|
+
? ANTIGRAVITY_URL_PATTERNS.some(p => req.url.includes(p))
|
|
248
|
+
: COPILOT_URL_PATTERNS.some(p => req.url.includes(p));
|
|
237
249
|
|
|
238
|
-
|
|
250
|
+
if (!isChat) return passthrough(req, res, bodyBuffer);
|
|
239
251
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
252
|
+
const model = extractModel(req.url, bodyBuffer);
|
|
253
|
+
console.log("Extracted model:", model);
|
|
254
|
+
const mappedModel = getMappedModel(tool, model);
|
|
243
255
|
|
|
244
|
-
|
|
256
|
+
if (!mappedModel) return passthrough(req, res, bodyBuffer);
|
|
245
257
|
|
|
246
|
-
|
|
258
|
+
return intercept(req, res, bodyBuffer, mappedModel);
|
|
259
|
+
} catch (err) {
|
|
260
|
+
console.error(`❌ Unhandled request error: ${err.message}`);
|
|
261
|
+
if (!res.headersSent) res.writeHead(500, { "Content-Type": "application/json" });
|
|
262
|
+
res.end(JSON.stringify({ error: { message: err.message, type: "mitm_error" } }));
|
|
263
|
+
}
|
|
247
264
|
});
|
|
248
265
|
|
|
249
266
|
server.listen(LOCAL_PORT, () => {
|
package/app/src/mitm/server2.js
CHANGED
|
@@ -75,6 +75,14 @@ const CURSOR_ENDPOINTS = [
|
|
|
75
75
|
"/agent.v1.AgentService/RunSSE",
|
|
76
76
|
];
|
|
77
77
|
|
|
78
|
+
// Mock rules: if last user message contains key → reply with value
|
|
79
|
+
const MOCK_RULES = {
|
|
80
|
+
"aaa": "bbb",
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
// conversationId → mock reply (set when AgentRunRequest matches a rule)
|
|
84
|
+
const mockPending = new Map();
|
|
85
|
+
|
|
78
86
|
/**
|
|
79
87
|
* Decode Connect-RPC frame: [1 byte flags][4 bytes length][protobuf body]
|
|
80
88
|
* Then walk raw protobuf fields and extract readable strings/numbers.
|
|
@@ -561,75 +569,57 @@ function decodeConversationState(buf) {
|
|
|
561
569
|
}
|
|
562
570
|
|
|
563
571
|
// ── Save per-chat JSON file ────────────────────────────────────
|
|
572
|
+
// Only logs AgentRunRequest and ExecClientMessage — skips noise (RunPoll, KvClientMessage, ClientHeartbeat...)
|
|
564
573
|
function saveCursorLogFull(url, headers, buf) {
|
|
565
574
|
try {
|
|
566
575
|
if (buf.length < 5) return;
|
|
576
|
+
if (!url.includes("BidiAppend")) return;
|
|
567
577
|
|
|
568
|
-
const isBidiAppend = url.includes("BidiAppend");
|
|
569
|
-
const isRunPoll = url.includes("RunPoll");
|
|
570
|
-
if (!isBidiAppend && !isRunPoll) return;
|
|
571
|
-
|
|
572
|
-
// Decompress if gzip, otherwise use raw
|
|
573
|
-
let raw;
|
|
574
578
|
const isGzip = buf[0] === 0x1f && buf[1] === 0x8b;
|
|
575
|
-
|
|
576
|
-
raw = zlib.gunzipSync(buf);
|
|
577
|
-
} else {
|
|
578
|
-
// Try strip Connect-RPC envelope if present (flag byte + 4-byte length)
|
|
579
|
-
raw = (buf[0] === 0x00 || buf[0] === 0x01) ? buf.slice(5) : buf;
|
|
580
|
-
}
|
|
579
|
+
const raw = isGzip ? zlib.gunzipSync(buf) : (buf[0] === 0x00 || buf[0] === 0x01 ? buf.slice(5) : buf);
|
|
581
580
|
|
|
582
|
-
const
|
|
583
|
-
|
|
584
|
-
let userMessage = null;
|
|
581
|
+
const decoded = decodeBidiAppend(raw);
|
|
582
|
+
const msgType = decoded?.agentMsg?.type;
|
|
585
583
|
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
const action = decoded?.agentMsg?.action || {};
|
|
589
|
-
userMessage = action.textFull || action.text || null;
|
|
590
|
-
} else {
|
|
591
|
-
// RunPoll: BidiPollRequest — f1=requestId{f1=uuid}, f2=startRequest
|
|
592
|
-
const fields = protoWalkFields(raw);
|
|
593
|
-
for (const f of fields) {
|
|
594
|
-
if (f.field === 1 && f.data) {
|
|
595
|
-
const inner = protoWalkFields(f.data);
|
|
596
|
-
const id = inner.find(x => x.field === 1 && x.data);
|
|
597
|
-
decoded.requestId = id ? protoStr(id.data) : null;
|
|
598
|
-
}
|
|
599
|
-
if (f.field === 2) decoded.startRequest = f.value === 1;
|
|
600
|
-
}
|
|
601
|
-
}
|
|
584
|
+
// Only log meaningful message types
|
|
585
|
+
if (msgType !== "AgentRunRequest" && msgType !== "ExecClientMessage") return;
|
|
602
586
|
|
|
603
|
-
|
|
587
|
+
const action = decoded?.agentMsg?.action || {};
|
|
588
|
+
const userMessage = action.textFull || action.text || null;
|
|
589
|
+
|
|
590
|
+
// Fetch full conversation from DB for AgentRunRequest
|
|
604
591
|
const conversationId = decoded?.agentMsg?.conversationId || null;
|
|
605
592
|
let conversation = null;
|
|
606
|
-
if (conversationId &&
|
|
593
|
+
if (conversationId && msgType === "AgentRunRequest") {
|
|
607
594
|
conversation = readConversationFromDb(conversationId);
|
|
595
|
+
|
|
596
|
+
// Check MOCK_RULES against last user message
|
|
597
|
+
const lastMsg = userMessage || "";
|
|
598
|
+
for (const [keyword, reply] of Object.entries(MOCK_RULES)) {
|
|
599
|
+
if (lastMsg.toLowerCase().includes(keyword.toLowerCase())) {
|
|
600
|
+
mockPending.set(conversationId, reply);
|
|
601
|
+
console.log(`[MOCK] Triggered rule "${keyword}" → "${reply}" for conv=${conversationId}`);
|
|
602
|
+
break;
|
|
603
|
+
}
|
|
604
|
+
}
|
|
608
605
|
}
|
|
609
606
|
|
|
610
607
|
const ts = new Date().toISOString().replace(/[:.]/g, "-");
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
}, null, 2));
|
|
625
|
-
|
|
626
|
-
// _decoded.json — full proto tree, no filtering
|
|
627
|
-
const tree = protoTreeToObj(raw);
|
|
628
|
-
fs.writeFileSync(`${base}_decoded.json`, JSON.stringify(tree, null, 2));
|
|
629
|
-
|
|
630
|
-
const agentType = decoded?.agentMsg?.type || decoded?.requestId || "(none)";
|
|
608
|
+
fs.writeFileSync(
|
|
609
|
+
path.join(CURSOR_LOG_DIR, `${ts}_${msgType}_chat.json`),
|
|
610
|
+
JSON.stringify({
|
|
611
|
+
ts: new Date().toISOString(),
|
|
612
|
+
type: msgType,
|
|
613
|
+
version: headers["x-cursor-client-version"] || null,
|
|
614
|
+
sizeIn: buf.length,
|
|
615
|
+
userMessage,
|
|
616
|
+
decoded,
|
|
617
|
+
conversation,
|
|
618
|
+
}, null, 2)
|
|
619
|
+
);
|
|
620
|
+
|
|
631
621
|
const convName = conversation?.name ? ` | conv="${conversation.name}" (${conversation.totalMessages} msgs)` : "";
|
|
632
|
-
console.log(`[CURSOR] ${
|
|
622
|
+
console.log(`[CURSOR] ${msgType} | msg=${userMessage || "(none)"}${convName} | ${buf.length}B`);
|
|
633
623
|
} catch (e) {
|
|
634
624
|
console.error(`[CURSOR] decode error: ${e.message}`);
|
|
635
625
|
}
|
|
@@ -761,7 +751,93 @@ function getToolForHost(host) {
|
|
|
761
751
|
return null;
|
|
762
752
|
}
|
|
763
753
|
|
|
764
|
-
|
|
754
|
+
/**
|
|
755
|
+
* Encode a single protobuf length-delimited field: (fieldNum << 3 | wireType) + varint(len) + bytes
|
|
756
|
+
* wireType 2 = length-delimited, wireType 0 = varint
|
|
757
|
+
*/
|
|
758
|
+
function protoEncodeField(fieldNum, wireType, data) {
|
|
759
|
+
const tag = (fieldNum << 3) | wireType;
|
|
760
|
+
const tagBuf = encodeVarint(tag);
|
|
761
|
+
if (wireType === 2) {
|
|
762
|
+
const lenBuf = encodeVarint(data.length);
|
|
763
|
+
return Buffer.concat([tagBuf, lenBuf, data]);
|
|
764
|
+
}
|
|
765
|
+
// wireType 0: data is already a varint buffer
|
|
766
|
+
return Buffer.concat([tagBuf, data]);
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
function encodeVarint(n) {
|
|
770
|
+
const bufs = [];
|
|
771
|
+
while (n > 0x7f) {
|
|
772
|
+
bufs.push((n & 0x7f) | 0x80);
|
|
773
|
+
n >>>= 7;
|
|
774
|
+
}
|
|
775
|
+
bufs.push(n & 0x7f);
|
|
776
|
+
return Buffer.from(bufs);
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
/**
|
|
780
|
+
* Build a Connect-RPC streaming frame: [flags=0][4-byte big-endian length][body]
|
|
781
|
+
*/
|
|
782
|
+
function buildConnectFrame(body) {
|
|
783
|
+
const lenBuf = Buffer.alloc(4);
|
|
784
|
+
lenBuf.writeUInt32BE(body.length, 0);
|
|
785
|
+
return Buffer.concat([Buffer.from([0x00]), lenBuf, body]);
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
/**
|
|
789
|
+
* Build one gzip-compressed Connect-RPC data frame containing a BidiPollResponse.
|
|
790
|
+
* BidiPollResponse: f1=seqno(varint), f2=data(hex string of AgentServerMessage)
|
|
791
|
+
* AgentServerMessage.f1 = InteractionUpdate.f1 = TextDeltaUpdate.f1 = text
|
|
792
|
+
*/
|
|
793
|
+
function buildFakePollFrame(text, seqno) {
|
|
794
|
+
const zlib = require("zlib");
|
|
795
|
+
|
|
796
|
+
// TextDeltaUpdate { f1: text }
|
|
797
|
+
const textDelta = protoEncodeField(1, 2, Buffer.from(text, "utf8"));
|
|
798
|
+
// InteractionUpdate { f1: TextDeltaUpdate }
|
|
799
|
+
const interactionUpdate = protoEncodeField(1, 2, textDelta);
|
|
800
|
+
// AgentServerMessage { f1: InteractionUpdate }
|
|
801
|
+
const agentMsg = protoEncodeField(1, 2, interactionUpdate);
|
|
802
|
+
|
|
803
|
+
// BidiPollResponse { f1: seqno, f2: hex(agentMsg) }
|
|
804
|
+
let pollResp = protoEncodeField(1, 0, encodeVarint(seqno));
|
|
805
|
+
pollResp = Buffer.concat([pollResp, protoEncodeField(2, 2, Buffer.from(agentMsg.toString("hex"), "utf8"))]);
|
|
806
|
+
|
|
807
|
+
// Gzip compress (flags=1)
|
|
808
|
+
const compressed = zlib.gzipSync(pollResp);
|
|
809
|
+
const lenBuf = Buffer.alloc(4);
|
|
810
|
+
lenBuf.writeUInt32BE(compressed.length, 0);
|
|
811
|
+
return Buffer.concat([Buffer.from([0x01]), lenBuf, compressed]);
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
/**
|
|
815
|
+
* Build Connect-RPC end-of-stream trailer frame: flags=0x02, body={}
|
|
816
|
+
*/
|
|
817
|
+
function buildTrailerFrame() {
|
|
818
|
+
const body = Buffer.from("{}", "utf8");
|
|
819
|
+
const lenBuf = Buffer.alloc(4);
|
|
820
|
+
lenBuf.writeUInt32BE(body.length, 0);
|
|
821
|
+
return Buffer.concat([Buffer.from([0x02]), lenBuf, body]);
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
/**
|
|
825
|
+
* Send fake RunPoll response matching real Cursor server format
|
|
826
|
+
*/
|
|
827
|
+
function sendMockResponse(res, replyText) {
|
|
828
|
+
res.writeHead(200, {
|
|
829
|
+
"content-type": "application/connect+proto",
|
|
830
|
+
"transfer-encoding": "chunked",
|
|
831
|
+
});
|
|
832
|
+
|
|
833
|
+
// Send text as single frame + trailer
|
|
834
|
+
res.write(buildFakePollFrame(replyText, 1));
|
|
835
|
+
res.write(buildTrailerFrame());
|
|
836
|
+
res.end();
|
|
837
|
+
console.log(`[MOCK] RunPoll → "${replyText}"`);
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
async function passthrough(req, res, bodyBuffer, captureFile = null) {
|
|
765
841
|
const targetHost = (req.headers.host || TARGET_HOSTS[0]).split(":")[0];
|
|
766
842
|
const targetIP = await resolveTargetIP(targetHost);
|
|
767
843
|
|
|
@@ -774,8 +850,121 @@ async function passthrough(req, res, bodyBuffer) {
|
|
|
774
850
|
servername: targetHost,
|
|
775
851
|
rejectUnauthorized: false
|
|
776
852
|
}, (forwardRes) => {
|
|
853
|
+
// Log headers + first frame raw bytes of first RunPoll response for mock calibration
|
|
854
|
+
if (req.url.includes("RunPoll") && !passthrough._loggedRunPollHeaders) {
|
|
855
|
+
passthrough._loggedRunPollHeaders = true;
|
|
856
|
+
console.log("[DBG] RunPoll headers:", JSON.stringify(forwardRes.headers));
|
|
857
|
+
const origWrite = res.write.bind(res);
|
|
858
|
+
let logged = false;
|
|
859
|
+
res.write = function(chunk) {
|
|
860
|
+
if (!logged) {
|
|
861
|
+
logged = true;
|
|
862
|
+
console.log("[DBG] RunPoll first chunk hex:", Buffer.isBuffer(chunk) ? chunk.slice(0, 80).toString("hex") : Buffer.from(chunk).slice(0, 80).toString("hex"));
|
|
863
|
+
}
|
|
864
|
+
return origWrite(chunk);
|
|
865
|
+
};
|
|
866
|
+
}
|
|
777
867
|
res.writeHead(forwardRes.statusCode, forwardRes.headers);
|
|
778
|
-
|
|
868
|
+
|
|
869
|
+
if (!captureFile) {
|
|
870
|
+
forwardRes.pipe(res);
|
|
871
|
+
return;
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
// Tee response: forward to client AND decode+save to file
|
|
875
|
+
const chunks = [];
|
|
876
|
+
forwardRes.on("data", chunk => {
|
|
877
|
+
chunks.push(chunk);
|
|
878
|
+
res.write(chunk);
|
|
879
|
+
});
|
|
880
|
+
forwardRes.on("end", () => {
|
|
881
|
+
res.end();
|
|
882
|
+
try {
|
|
883
|
+
const raw = Buffer.concat(chunks);
|
|
884
|
+
// Save first RunPoll raw that has text (frames > 20)
|
|
885
|
+
if (req.url.includes("RunPoll") && !passthrough._savedTextRaw && frameCount > 20) {
|
|
886
|
+
passthrough._savedTextRaw = true;
|
|
887
|
+
fs.writeFileSync(path.join(CURSOR_LOG_DIR, "_runpoll_text_raw.hex"), raw.toString("hex"));
|
|
888
|
+
console.log("[DBG] RunPoll TEXT raw saved, len=", raw.length, "frames=", frameCount);
|
|
889
|
+
}
|
|
890
|
+
// Decode Connect-RPC streaming frames: each frame = [1B flags][4B len][proto body]
|
|
891
|
+
const textChunks = [];
|
|
892
|
+
const toolCalls = [];
|
|
893
|
+
let frameCount = 0;
|
|
894
|
+
let offset = 0;
|
|
895
|
+
|
|
896
|
+
while (offset + 5 <= raw.length) {
|
|
897
|
+
const flags = raw[offset];
|
|
898
|
+
const msgLen = raw.readUInt32BE(offset + 1);
|
|
899
|
+
if (offset + 5 + msgLen > raw.length) break;
|
|
900
|
+
let body = raw.slice(offset + 5, offset + 5 + msgLen);
|
|
901
|
+
offset += 5 + msgLen;
|
|
902
|
+
frameCount++;
|
|
903
|
+
|
|
904
|
+
// Decompress gzip frame (flags=1)
|
|
905
|
+
if (flags === 1) {
|
|
906
|
+
try { body = zlib.gunzipSync(body); } catch { continue; }
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
// BidiPollResponse: f1=seqno(varint), f2=data(hex-encoded AgentServerMessage)
|
|
910
|
+
const pollFields = protoWalkFields(body);
|
|
911
|
+
const dataField = pollFields.find(f => f.field === 2 && f.data);
|
|
912
|
+
if (!dataField) continue;
|
|
913
|
+
|
|
914
|
+
// f2.data is ASCII hex string → decode to actual AgentServerMessage bytes
|
|
915
|
+
const hexStr = dataField.data.toString("utf8");
|
|
916
|
+
if (!/^[0-9a-f]+$/i.test(hexStr)) continue;
|
|
917
|
+
const agentMsg = Buffer.from(hexStr, "hex");
|
|
918
|
+
|
|
919
|
+
// AgentServerMessage: f1=InteractionUpdate, f2=ExecServerMessage
|
|
920
|
+
const agentFields = protoWalkFields(agentMsg);
|
|
921
|
+
|
|
922
|
+
// f1 = InteractionUpdate → f1=TextDeltaUpdate.f1=text
|
|
923
|
+
const interactionUpdate = agentFields.find(f => f.field === 1 && f.data);
|
|
924
|
+
if (interactionUpdate) {
|
|
925
|
+
const iuFields = protoWalkFields(interactionUpdate.data);
|
|
926
|
+
const textDelta = iuFields.find(f => f.field === 1 && f.data);
|
|
927
|
+
if (textDelta) {
|
|
928
|
+
const tdFields = protoWalkFields(textDelta.data);
|
|
929
|
+
const textField = tdFields.find(f => f.field === 1 && f.data);
|
|
930
|
+
if (textField) {
|
|
931
|
+
const text = textField.data.toString("utf8");
|
|
932
|
+
if (text.length > 0) textChunks.push(text);
|
|
933
|
+
}
|
|
934
|
+
}
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
// f2 = ExecServerMessage → decode tool call
|
|
938
|
+
// ExecServerMessage: f1=id(varint), f15=exec_id(str), f2=shell, f3=write, f4=delete, f5=grep, f7=read, f8=ls
|
|
939
|
+
const execMsg = agentFields.find(f => f.field === 2 && f.data);
|
|
940
|
+
if (execMsg) {
|
|
941
|
+
const execFields = protoWalkFields(execMsg.data);
|
|
942
|
+
const toolFieldMap = { 2: "shell", 3: "write", 4: "delete", 5: "grep", 7: "read", 8: "ls", 11: "mcp", 14: "shell_stream", 20: "fetch" };
|
|
943
|
+
const toolField = execFields.find(f => toolFieldMap[f.field] && f.data);
|
|
944
|
+
if (toolField) {
|
|
945
|
+
const toolName = toolFieldMap[toolField.field];
|
|
946
|
+
// Extract first string field as main arg (command/path)
|
|
947
|
+
const argFields = protoWalkFields(toolField.data);
|
|
948
|
+
const mainArg = argFields.find(f => f.field === 1 && f.data);
|
|
949
|
+
const arg = mainArg ? mainArg.data.toString("utf8") : null;
|
|
950
|
+
toolCalls.push({ tool: toolName, arg });
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
const assembled = textChunks.length > 0 ? textChunks.join("") : null;
|
|
956
|
+
// Only save file if there's actual content
|
|
957
|
+
if (assembled || toolCalls.length > 0) {
|
|
958
|
+
const entry = { ts: new Date().toISOString(), frames: frameCount };
|
|
959
|
+
if (assembled) entry.text = assembled;
|
|
960
|
+
if (toolCalls.length > 0) entry.tools = toolCalls;
|
|
961
|
+
fs.writeFileSync(captureFile, JSON.stringify(entry, null, 2));
|
|
962
|
+
const toolSummary = toolCalls.map(t => `${t.tool}(${(t.arg || "").slice(0, 40)})`).join(", ");
|
|
963
|
+
const preview = assembled ? `"${assembled.slice(0, 80)}"` : "";
|
|
964
|
+
console.log(`[CURSOR] RunPoll ← ${preview}${toolSummary ? ` [${toolSummary}]` : ""}`);
|
|
965
|
+
}
|
|
966
|
+
} catch { /* ignore */ }
|
|
967
|
+
});
|
|
779
968
|
});
|
|
780
969
|
|
|
781
970
|
forwardReq.on("error", (err) => {
|
|
@@ -838,11 +1027,31 @@ const server = https.createServer(sslOptions, async (req, res) => {
|
|
|
838
1027
|
const bodyBuffer = await collectBodyRaw(req);
|
|
839
1028
|
if (bodyBuffer.length > 0) saveRequestLog(req.url, bodyBuffer);
|
|
840
1029
|
|
|
841
|
-
// Decode and log Cursor protobuf endpoints
|
|
1030
|
+
// Decode and log Cursor protobuf request endpoints
|
|
842
1031
|
if (CURSOR_ENDPOINTS.some(e => req.url.includes(e))) {
|
|
843
1032
|
saveCursorLogFull(req.url, req.headers, bodyBuffer);
|
|
844
1033
|
}
|
|
845
1034
|
|
|
1035
|
+
// Capture response of RunPoll (server streams BidiPollResponse chunks back)
|
|
1036
|
+
const isRunPoll = req.url.includes("RunPoll");
|
|
1037
|
+
if (isRunPoll) {
|
|
1038
|
+
// Check if there's a mock rule pending for this conversation
|
|
1039
|
+
// Extract conversationId from BidiPollRequest.f1 (BidiRequestId) → need to check mockPending
|
|
1040
|
+
// Simple approach: check all pending mocks and reply for any RunPoll within same session
|
|
1041
|
+
// Since mockPending is keyed by conversationId and RunPoll doesn't carry it directly,
|
|
1042
|
+
// we intercept the first RunPoll after a matching AgentRunRequest by checking pendingQueue
|
|
1043
|
+
if (mockPending.size > 0) {
|
|
1044
|
+
// Pick the first pending mock (FIFO) — matches the most recent matching conversation
|
|
1045
|
+
const [convId, replyText] = mockPending.entries().next().value;
|
|
1046
|
+
mockPending.delete(convId);
|
|
1047
|
+
return sendMockResponse(res, replyText);
|
|
1048
|
+
}
|
|
1049
|
+
|
|
1050
|
+
const ts = new Date().toISOString().replace(/[:.]/g, "-");
|
|
1051
|
+
const captureFile = path.join(CURSOR_LOG_DIR, `${ts}_RunPoll_response.json`);
|
|
1052
|
+
return passthrough(req, res, bodyBuffer, captureFile);
|
|
1053
|
+
}
|
|
1054
|
+
|
|
846
1055
|
// Anti-loop: requests originating from 9Router bypass interception
|
|
847
1056
|
if (req.headers[INTERNAL_REQUEST_HEADER.name] === INTERNAL_REQUEST_HEADER.value) {
|
|
848
1057
|
return passthrough(req, res, bodyBuffer);
|
package/package.json
CHANGED
|
File without changes
|
|
File without changes
|