9router 0.3.47 → 0.3.49

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.
Files changed (347) hide show
  1. package/app/.next/BUILD_ID +1 -1
  2. package/app/.next/app-path-routes-manifest.json +42 -42
  3. package/app/.next/build-manifest.json +2 -2
  4. package/app/.next/server/app/(dashboard)/dashboard/cli-tools/page_client-reference-manifest.js +1 -1
  5. package/app/.next/server/app/(dashboard)/dashboard/combos/page_client-reference-manifest.js +1 -1
  6. package/app/.next/server/app/(dashboard)/dashboard/console-log/page_client-reference-manifest.js +1 -1
  7. package/app/.next/server/app/(dashboard)/dashboard/endpoint/page_client-reference-manifest.js +1 -1
  8. package/app/.next/server/app/(dashboard)/dashboard/mitm/page_client-reference-manifest.js +1 -1
  9. package/app/.next/server/app/(dashboard)/dashboard/page_client-reference-manifest.js +1 -1
  10. package/app/.next/server/app/(dashboard)/dashboard/profile/page_client-reference-manifest.js +1 -1
  11. package/app/.next/server/app/(dashboard)/dashboard/providers/[id]/page_client-reference-manifest.js +1 -1
  12. package/app/.next/server/app/(dashboard)/dashboard/providers/new/page_client-reference-manifest.js +1 -1
  13. package/app/.next/server/app/(dashboard)/dashboard/providers/page_client-reference-manifest.js +1 -1
  14. package/app/.next/server/app/(dashboard)/dashboard/proxy-pools/page_client-reference-manifest.js +1 -1
  15. package/app/.next/server/app/(dashboard)/dashboard/quota/page_client-reference-manifest.js +1 -1
  16. package/app/.next/server/app/(dashboard)/dashboard/translator/page_client-reference-manifest.js +1 -1
  17. package/app/.next/server/app/(dashboard)/dashboard/usage/page_client-reference-manifest.js +1 -1
  18. package/app/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  19. package/app/.next/server/app/_global-error.html +2 -2
  20. package/app/.next/server/app/_global-error.rsc +1 -1
  21. package/app/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  22. package/app/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  23. package/app/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  24. package/app/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  25. package/app/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  26. package/app/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  27. package/app/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  28. package/app/.next/server/app/_not-found.html +1 -1
  29. package/app/.next/server/app/_not-found.rsc +3 -3
  30. package/app/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  31. package/app/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  32. package/app/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  33. package/app/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  34. package/app/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  35. package/app/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  36. package/app/.next/server/app/api/auth/login/route_client-reference-manifest.js +1 -1
  37. package/app/.next/server/app/api/auth/logout/route_client-reference-manifest.js +1 -1
  38. package/app/.next/server/app/api/cli-tools/antigravity-mitm/alias/route_client-reference-manifest.js +1 -1
  39. package/app/.next/server/app/api/cli-tools/antigravity-mitm/route_client-reference-manifest.js +1 -1
  40. package/app/.next/server/app/api/cli-tools/claude-settings/route_client-reference-manifest.js +1 -1
  41. package/app/.next/server/app/api/cli-tools/codex-settings/route_client-reference-manifest.js +1 -1
  42. package/app/.next/server/app/api/cli-tools/copilot-settings/route_client-reference-manifest.js +1 -1
  43. package/app/.next/server/app/api/cli-tools/droid-settings/route_client-reference-manifest.js +1 -1
  44. package/app/.next/server/app/api/cli-tools/openclaw-settings/route_client-reference-manifest.js +1 -1
  45. package/app/.next/server/app/api/cli-tools/opencode-settings/route_client-reference-manifest.js +1 -1
  46. package/app/.next/server/app/api/cloud/auth/route_client-reference-manifest.js +1 -1
  47. package/app/.next/server/app/api/cloud/credentials/update/route_client-reference-manifest.js +1 -1
  48. package/app/.next/server/app/api/cloud/model/resolve/route_client-reference-manifest.js +1 -1
  49. package/app/.next/server/app/api/cloud/models/alias/route_client-reference-manifest.js +1 -1
  50. package/app/.next/server/app/api/combos/[id]/route_client-reference-manifest.js +1 -1
  51. package/app/.next/server/app/api/combos/route_client-reference-manifest.js +1 -1
  52. package/app/.next/server/app/api/init/route_client-reference-manifest.js +1 -1
  53. package/app/.next/server/app/api/keys/[id]/route_client-reference-manifest.js +1 -1
  54. package/app/.next/server/app/api/keys/route_client-reference-manifest.js +1 -1
  55. package/app/.next/server/app/api/locale/route_client-reference-manifest.js +1 -1
  56. package/app/.next/server/app/api/models/alias/route_client-reference-manifest.js +1 -1
  57. package/app/.next/server/app/api/models/route.js +1 -1
  58. package/app/.next/server/app/api/models/route_client-reference-manifest.js +1 -1
  59. package/app/.next/server/app/api/models/test/route_client-reference-manifest.js +1 -1
  60. package/app/.next/server/app/api/oauth/[provider]/[action]/route_client-reference-manifest.js +1 -1
  61. package/app/.next/server/app/api/oauth/cursor/auto-import/route.js +2 -2
  62. package/app/.next/server/app/api/oauth/cursor/auto-import/route.js.nft.json +1 -1
  63. package/app/.next/server/app/api/oauth/cursor/auto-import/route_client-reference-manifest.js +1 -1
  64. package/app/.next/server/app/api/oauth/cursor/import/route_client-reference-manifest.js +1 -1
  65. package/app/.next/server/app/api/oauth/iflow/cookie/route_client-reference-manifest.js +1 -1
  66. package/app/.next/server/app/api/oauth/kiro/auto-import/route_client-reference-manifest.js +1 -1
  67. package/app/.next/server/app/api/oauth/kiro/import/route_client-reference-manifest.js +1 -1
  68. package/app/.next/server/app/api/oauth/kiro/social-authorize/route_client-reference-manifest.js +1 -1
  69. package/app/.next/server/app/api/oauth/kiro/social-exchange/route_client-reference-manifest.js +1 -1
  70. package/app/.next/server/app/api/pricing/route_client-reference-manifest.js +1 -1
  71. package/app/.next/server/app/api/provider-nodes/[id]/route_client-reference-manifest.js +1 -1
  72. package/app/.next/server/app/api/provider-nodes/route_client-reference-manifest.js +1 -1
  73. package/app/.next/server/app/api/provider-nodes/validate/route_client-reference-manifest.js +1 -1
  74. package/app/.next/server/app/api/providers/[id]/models/route_client-reference-manifest.js +1 -1
  75. package/app/.next/server/app/api/providers/[id]/route_client-reference-manifest.js +1 -1
  76. package/app/.next/server/app/api/providers/[id]/test/route_client-reference-manifest.js +1 -1
  77. package/app/.next/server/app/api/providers/[id]/test-models/route_client-reference-manifest.js +1 -1
  78. package/app/.next/server/app/api/providers/client/route_client-reference-manifest.js +1 -1
  79. package/app/.next/server/app/api/providers/route.js +1 -1
  80. package/app/.next/server/app/api/providers/route_client-reference-manifest.js +1 -1
  81. package/app/.next/server/app/api/providers/test-batch/route_client-reference-manifest.js +1 -1
  82. package/app/.next/server/app/api/providers/validate/route_client-reference-manifest.js +1 -1
  83. package/app/.next/server/app/api/proxy-pools/[id]/route_client-reference-manifest.js +1 -1
  84. package/app/.next/server/app/api/proxy-pools/[id]/test/route_client-reference-manifest.js +1 -1
  85. package/app/.next/server/app/api/proxy-pools/route_client-reference-manifest.js +1 -1
  86. package/app/.next/server/app/api/settings/database/route_client-reference-manifest.js +1 -1
  87. package/app/.next/server/app/api/settings/proxy-test/route_client-reference-manifest.js +1 -1
  88. package/app/.next/server/app/api/settings/require-login/route_client-reference-manifest.js +1 -1
  89. package/app/.next/server/app/api/settings/route_client-reference-manifest.js +1 -1
  90. package/app/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  91. package/app/.next/server/app/api/tags/route_client-reference-manifest.js +1 -1
  92. package/app/.next/server/app/api/translator/console-logs/route.js +1 -1
  93. package/app/.next/server/app/api/translator/console-logs/route_client-reference-manifest.js +1 -1
  94. package/app/.next/server/app/api/translator/console-logs/stream/route.js +1 -1
  95. package/app/.next/server/app/api/translator/console-logs/stream/route_client-reference-manifest.js +1 -1
  96. package/app/.next/server/app/api/translator/load/route_client-reference-manifest.js +1 -1
  97. package/app/.next/server/app/api/translator/save/route_client-reference-manifest.js +1 -1
  98. package/app/.next/server/app/api/translator/send/route_client-reference-manifest.js +1 -1
  99. package/app/.next/server/app/api/translator/translate/route_client-reference-manifest.js +1 -1
  100. package/app/.next/server/app/api/tunnel/disable/route.js +1 -1
  101. package/app/.next/server/app/api/tunnel/disable/route_client-reference-manifest.js +1 -1
  102. package/app/.next/server/app/api/tunnel/enable/route.js +1 -1
  103. package/app/.next/server/app/api/tunnel/enable/route_client-reference-manifest.js +1 -1
  104. package/app/.next/server/app/api/tunnel/status/route.js +1 -1
  105. package/app/.next/server/app/api/tunnel/status/route_client-reference-manifest.js +1 -1
  106. package/app/.next/server/app/api/usage/[connectionId]/route.js +1 -1
  107. package/app/.next/server/app/api/usage/[connectionId]/route_client-reference-manifest.js +1 -1
  108. package/app/.next/server/app/api/usage/chart/route_client-reference-manifest.js +1 -1
  109. package/app/.next/server/app/api/usage/history/route_client-reference-manifest.js +1 -1
  110. package/app/.next/server/app/api/usage/providers/route.js +1 -1
  111. package/app/.next/server/app/api/usage/providers/route_client-reference-manifest.js +1 -1
  112. package/app/.next/server/app/api/usage/request-details/route_client-reference-manifest.js +1 -1
  113. package/app/.next/server/app/api/usage/request-logs/route_client-reference-manifest.js +1 -1
  114. package/app/.next/server/app/api/usage/stats/route_client-reference-manifest.js +1 -1
  115. package/app/.next/server/app/api/usage/stream/route.js +1 -1
  116. package/app/.next/server/app/api/usage/stream/route_client-reference-manifest.js +1 -1
  117. package/app/.next/server/app/api/v1/api/chat/route.js +1 -1
  118. package/app/.next/server/app/api/v1/api/chat/route_client-reference-manifest.js +1 -1
  119. package/app/.next/server/app/api/v1/chat/completions/route.js +1 -1
  120. package/app/.next/server/app/api/v1/chat/completions/route_client-reference-manifest.js +1 -1
  121. package/app/.next/server/app/api/v1/embeddings/route.js +1 -1
  122. package/app/.next/server/app/api/v1/embeddings/route_client-reference-manifest.js +1 -1
  123. package/app/.next/server/app/api/v1/messages/count_tokens/route_client-reference-manifest.js +1 -1
  124. package/app/.next/server/app/api/v1/messages/route.js +1 -1
  125. package/app/.next/server/app/api/v1/messages/route_client-reference-manifest.js +1 -1
  126. package/app/.next/server/app/api/v1/models/route_client-reference-manifest.js +1 -1
  127. package/app/.next/server/app/api/v1/responses/route.js +1 -1
  128. package/app/.next/server/app/api/v1/responses/route_client-reference-manifest.js +1 -1
  129. package/app/.next/server/app/api/v1/route_client-reference-manifest.js +1 -1
  130. package/app/.next/server/app/api/v1beta/models/[...path]/route.js +1 -1
  131. package/app/.next/server/app/api/v1beta/models/[...path]/route_client-reference-manifest.js +1 -1
  132. package/app/.next/server/app/api/v1beta/models/route_client-reference-manifest.js +1 -1
  133. package/app/.next/server/app/api/version/route.js +1 -1
  134. package/app/.next/server/app/api/version/route_client-reference-manifest.js +1 -1
  135. package/app/.next/server/app/callback/page_client-reference-manifest.js +1 -1
  136. package/app/.next/server/app/callback.html +1 -1
  137. package/app/.next/server/app/callback.rsc +3 -3
  138. package/app/.next/server/app/callback.segments/_full.segment.rsc +3 -3
  139. package/app/.next/server/app/callback.segments/_head.segment.rsc +1 -1
  140. package/app/.next/server/app/callback.segments/_index.segment.rsc +3 -3
  141. package/app/.next/server/app/callback.segments/_tree.segment.rsc +1 -1
  142. package/app/.next/server/app/callback.segments/callback/__PAGE__.segment.rsc +1 -1
  143. package/app/.next/server/app/callback.segments/callback.segment.rsc +1 -1
  144. package/app/.next/server/app/dashboard/cli-tools.html +1 -1
  145. package/app/.next/server/app/dashboard/cli-tools.rsc +5 -5
  146. package/app/.next/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk/dashboard/cli-tools/__PAGE__.segment.rsc +2 -2
  147. package/app/.next/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk/dashboard/cli-tools.segment.rsc +1 -1
  148. package/app/.next/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  149. package/app/.next/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  150. package/app/.next/server/app/dashboard/cli-tools.segments/_full.segment.rsc +5 -5
  151. package/app/.next/server/app/dashboard/cli-tools.segments/_head.segment.rsc +1 -1
  152. package/app/.next/server/app/dashboard/cli-tools.segments/_index.segment.rsc +3 -3
  153. package/app/.next/server/app/dashboard/cli-tools.segments/_tree.segment.rsc +1 -1
  154. package/app/.next/server/app/dashboard/combos.html +1 -1
  155. package/app/.next/server/app/dashboard/combos.rsc +5 -5
  156. package/app/.next/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk/dashboard/combos/__PAGE__.segment.rsc +2 -2
  157. package/app/.next/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk/dashboard/combos.segment.rsc +1 -1
  158. package/app/.next/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  159. package/app/.next/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  160. package/app/.next/server/app/dashboard/combos.segments/_full.segment.rsc +5 -5
  161. package/app/.next/server/app/dashboard/combos.segments/_head.segment.rsc +1 -1
  162. package/app/.next/server/app/dashboard/combos.segments/_index.segment.rsc +3 -3
  163. package/app/.next/server/app/dashboard/combos.segments/_tree.segment.rsc +1 -1
  164. package/app/.next/server/app/dashboard/endpoint.html +1 -1
  165. package/app/.next/server/app/dashboard/endpoint.rsc +5 -5
  166. package/app/.next/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk/dashboard/endpoint/__PAGE__.segment.rsc +2 -2
  167. package/app/.next/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk/dashboard/endpoint.segment.rsc +1 -1
  168. package/app/.next/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  169. package/app/.next/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  170. package/app/.next/server/app/dashboard/endpoint.segments/_full.segment.rsc +5 -5
  171. package/app/.next/server/app/dashboard/endpoint.segments/_head.segment.rsc +1 -1
  172. package/app/.next/server/app/dashboard/endpoint.segments/_index.segment.rsc +3 -3
  173. package/app/.next/server/app/dashboard/endpoint.segments/_tree.segment.rsc +1 -1
  174. package/app/.next/server/app/dashboard/mitm.html +1 -1
  175. package/app/.next/server/app/dashboard/mitm.rsc +5 -5
  176. package/app/.next/server/app/dashboard/mitm.segments/!KGRhc2hib2FyZCk/dashboard/mitm/__PAGE__.segment.rsc +2 -2
  177. package/app/.next/server/app/dashboard/mitm.segments/!KGRhc2hib2FyZCk/dashboard/mitm.segment.rsc +1 -1
  178. package/app/.next/server/app/dashboard/mitm.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  179. package/app/.next/server/app/dashboard/mitm.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  180. package/app/.next/server/app/dashboard/mitm.segments/_full.segment.rsc +5 -5
  181. package/app/.next/server/app/dashboard/mitm.segments/_head.segment.rsc +1 -1
  182. package/app/.next/server/app/dashboard/mitm.segments/_index.segment.rsc +3 -3
  183. package/app/.next/server/app/dashboard/mitm.segments/_tree.segment.rsc +1 -1
  184. package/app/.next/server/app/dashboard/profile.html +1 -1
  185. package/app/.next/server/app/dashboard/profile.rsc +5 -5
  186. package/app/.next/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk/dashboard/profile/__PAGE__.segment.rsc +2 -2
  187. package/app/.next/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk/dashboard/profile.segment.rsc +1 -1
  188. package/app/.next/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  189. package/app/.next/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  190. package/app/.next/server/app/dashboard/profile.segments/_full.segment.rsc +5 -5
  191. package/app/.next/server/app/dashboard/profile.segments/_head.segment.rsc +1 -1
  192. package/app/.next/server/app/dashboard/profile.segments/_index.segment.rsc +3 -3
  193. package/app/.next/server/app/dashboard/profile.segments/_tree.segment.rsc +1 -1
  194. package/app/.next/server/app/dashboard/providers/new.html +1 -1
  195. package/app/.next/server/app/dashboard/providers/new.rsc +5 -5
  196. package/app/.next/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard/providers/new/__PAGE__.segment.rsc +2 -2
  197. package/app/.next/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard/providers/new.segment.rsc +1 -1
  198. package/app/.next/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard/providers.segment.rsc +1 -1
  199. package/app/.next/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  200. package/app/.next/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  201. package/app/.next/server/app/dashboard/providers/new.segments/_full.segment.rsc +5 -5
  202. package/app/.next/server/app/dashboard/providers/new.segments/_head.segment.rsc +1 -1
  203. package/app/.next/server/app/dashboard/providers/new.segments/_index.segment.rsc +3 -3
  204. package/app/.next/server/app/dashboard/providers/new.segments/_tree.segment.rsc +1 -1
  205. package/app/.next/server/app/dashboard/providers.html +1 -1
  206. package/app/.next/server/app/dashboard/providers.rsc +5 -5
  207. package/app/.next/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk/dashboard/providers/__PAGE__.segment.rsc +2 -2
  208. package/app/.next/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk/dashboard/providers.segment.rsc +1 -1
  209. package/app/.next/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  210. package/app/.next/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  211. package/app/.next/server/app/dashboard/providers.segments/_full.segment.rsc +5 -5
  212. package/app/.next/server/app/dashboard/providers.segments/_head.segment.rsc +1 -1
  213. package/app/.next/server/app/dashboard/providers.segments/_index.segment.rsc +3 -3
  214. package/app/.next/server/app/dashboard/providers.segments/_tree.segment.rsc +1 -1
  215. package/app/.next/server/app/dashboard/proxy-pools.html +1 -1
  216. package/app/.next/server/app/dashboard/proxy-pools.rsc +5 -5
  217. package/app/.next/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk/dashboard/proxy-pools/__PAGE__.segment.rsc +2 -2
  218. package/app/.next/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk/dashboard/proxy-pools.segment.rsc +1 -1
  219. package/app/.next/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  220. package/app/.next/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  221. package/app/.next/server/app/dashboard/proxy-pools.segments/_full.segment.rsc +5 -5
  222. package/app/.next/server/app/dashboard/proxy-pools.segments/_head.segment.rsc +1 -1
  223. package/app/.next/server/app/dashboard/proxy-pools.segments/_index.segment.rsc +3 -3
  224. package/app/.next/server/app/dashboard/proxy-pools.segments/_tree.segment.rsc +1 -1
  225. package/app/.next/server/app/dashboard/quota.html +2 -2
  226. package/app/.next/server/app/dashboard/quota.rsc +4 -4
  227. package/app/.next/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk/dashboard/quota/__PAGE__.segment.rsc +1 -1
  228. package/app/.next/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk/dashboard/quota.segment.rsc +1 -1
  229. package/app/.next/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  230. package/app/.next/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  231. package/app/.next/server/app/dashboard/quota.segments/_full.segment.rsc +4 -4
  232. package/app/.next/server/app/dashboard/quota.segments/_head.segment.rsc +1 -1
  233. package/app/.next/server/app/dashboard/quota.segments/_index.segment.rsc +3 -3
  234. package/app/.next/server/app/dashboard/quota.segments/_tree.segment.rsc +1 -1
  235. package/app/.next/server/app/dashboard/settings/pricing/page_client-reference-manifest.js +1 -1
  236. package/app/.next/server/app/dashboard/settings/pricing.html +1 -1
  237. package/app/.next/server/app/dashboard/settings/pricing.rsc +3 -3
  238. package/app/.next/server/app/dashboard/settings/pricing.segments/_full.segment.rsc +3 -3
  239. package/app/.next/server/app/dashboard/settings/pricing.segments/_head.segment.rsc +1 -1
  240. package/app/.next/server/app/dashboard/settings/pricing.segments/_index.segment.rsc +3 -3
  241. package/app/.next/server/app/dashboard/settings/pricing.segments/_tree.segment.rsc +1 -1
  242. package/app/.next/server/app/dashboard/settings/pricing.segments/dashboard/settings/pricing/__PAGE__.segment.rsc +1 -1
  243. package/app/.next/server/app/dashboard/settings/pricing.segments/dashboard/settings/pricing.segment.rsc +1 -1
  244. package/app/.next/server/app/dashboard/settings/pricing.segments/dashboard/settings.segment.rsc +1 -1
  245. package/app/.next/server/app/dashboard/settings/pricing.segments/dashboard.segment.rsc +1 -1
  246. package/app/.next/server/app/dashboard/translator.html +1 -1
  247. package/app/.next/server/app/dashboard/translator.rsc +5 -5
  248. package/app/.next/server/app/dashboard/translator.segments/!KGRhc2hib2FyZCk/dashboard/translator/__PAGE__.segment.rsc +2 -2
  249. package/app/.next/server/app/dashboard/translator.segments/!KGRhc2hib2FyZCk/dashboard/translator.segment.rsc +1 -1
  250. package/app/.next/server/app/dashboard/translator.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  251. package/app/.next/server/app/dashboard/translator.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  252. package/app/.next/server/app/dashboard/translator.segments/_full.segment.rsc +5 -5
  253. package/app/.next/server/app/dashboard/translator.segments/_head.segment.rsc +1 -1
  254. package/app/.next/server/app/dashboard/translator.segments/_index.segment.rsc +3 -3
  255. package/app/.next/server/app/dashboard/translator.segments/_tree.segment.rsc +1 -1
  256. package/app/.next/server/app/dashboard/usage.html +1 -1
  257. package/app/.next/server/app/dashboard/usage.rsc +5 -5
  258. package/app/.next/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk/dashboard/usage/__PAGE__.segment.rsc +2 -2
  259. package/app/.next/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk/dashboard/usage.segment.rsc +1 -1
  260. package/app/.next/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  261. package/app/.next/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  262. package/app/.next/server/app/dashboard/usage.segments/_full.segment.rsc +5 -5
  263. package/app/.next/server/app/dashboard/usage.segments/_head.segment.rsc +1 -1
  264. package/app/.next/server/app/dashboard/usage.segments/_index.segment.rsc +3 -3
  265. package/app/.next/server/app/dashboard/usage.segments/_tree.segment.rsc +1 -1
  266. package/app/.next/server/app/dashboard.html +1 -1
  267. package/app/.next/server/app/dashboard.rsc +5 -5
  268. package/app/.next/server/app/dashboard.segments/!KGRhc2hib2FyZCk/dashboard/__PAGE__.segment.rsc +2 -2
  269. package/app/.next/server/app/dashboard.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  270. package/app/.next/server/app/dashboard.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  271. package/app/.next/server/app/dashboard.segments/_full.segment.rsc +5 -5
  272. package/app/.next/server/app/dashboard.segments/_head.segment.rsc +1 -1
  273. package/app/.next/server/app/dashboard.segments/_index.segment.rsc +3 -3
  274. package/app/.next/server/app/dashboard.segments/_tree.segment.rsc +1 -1
  275. package/app/.next/server/app/index.html +1 -1
  276. package/app/.next/server/app/index.rsc +3 -3
  277. package/app/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  278. package/app/.next/server/app/index.segments/_full.segment.rsc +3 -3
  279. package/app/.next/server/app/index.segments/_head.segment.rsc +1 -1
  280. package/app/.next/server/app/index.segments/_index.segment.rsc +3 -3
  281. package/app/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  282. package/app/.next/server/app/landing/page_client-reference-manifest.js +1 -1
  283. package/app/.next/server/app/landing.html +1 -1
  284. package/app/.next/server/app/landing.rsc +3 -3
  285. package/app/.next/server/app/landing.segments/_full.segment.rsc +3 -3
  286. package/app/.next/server/app/landing.segments/_head.segment.rsc +1 -1
  287. package/app/.next/server/app/landing.segments/_index.segment.rsc +3 -3
  288. package/app/.next/server/app/landing.segments/_tree.segment.rsc +1 -1
  289. package/app/.next/server/app/landing.segments/landing/__PAGE__.segment.rsc +1 -1
  290. package/app/.next/server/app/landing.segments/landing.segment.rsc +1 -1
  291. package/app/.next/server/app/login/page_client-reference-manifest.js +1 -1
  292. package/app/.next/server/app/login.html +1 -1
  293. package/app/.next/server/app/login.rsc +4 -4
  294. package/app/.next/server/app/login.segments/_full.segment.rsc +4 -4
  295. package/app/.next/server/app/login.segments/_head.segment.rsc +1 -1
  296. package/app/.next/server/app/login.segments/_index.segment.rsc +3 -3
  297. package/app/.next/server/app/login.segments/_tree.segment.rsc +1 -1
  298. package/app/.next/server/app/login.segments/login/__PAGE__.segment.rsc +2 -2
  299. package/app/.next/server/app/login.segments/login.segment.rsc +1 -1
  300. package/app/.next/server/app/manifest.webmanifest/route_client-reference-manifest.js +1 -1
  301. package/app/.next/server/app/page_client-reference-manifest.js +1 -1
  302. package/app/.next/server/app-paths-manifest.json +42 -42
  303. package/app/.next/server/chunks/1114.js +1 -1
  304. package/app/.next/server/chunks/1424.js +1 -1
  305. package/app/.next/server/chunks/289.js +1 -1
  306. package/app/.next/server/chunks/318.js +6 -6
  307. package/app/.next/server/chunks/4989.js +2 -2
  308. package/app/.next/server/chunks/5297.js +1 -1
  309. package/app/.next/server/chunks/6182.js +4 -4
  310. package/app/.next/server/chunks/8590.js +1 -1
  311. package/app/.next/server/chunks/8895.js +3 -3
  312. package/app/.next/server/chunks/9201.js +1 -1
  313. package/app/.next/server/chunks/9609.js +1 -1
  314. package/app/.next/server/pages/404.html +1 -1
  315. package/app/.next/server/pages/500.html +2 -2
  316. package/app/.next/server/server-reference-manifest.js +1 -1
  317. package/app/.next/server/server-reference-manifest.json +1 -1
  318. package/app/.next/static/chunks/{5497-80f3e016aa6ffe90.js → 5497-612d09a8bc2fb0ac.js} +1 -1
  319. package/app/.next/static/chunks/{619-4c970716a5102dc3.js → 619-c4c101a6a78feeb4.js} +1 -1
  320. package/app/.next/static/chunks/app/{layout-3d619e2f57919f2c.js → layout-facb48b90c716570.js} +1 -1
  321. package/app/node_modules/better-sqlite3/build/Release/better_sqlite3.node +0 -0
  322. package/app/node_modules/better-sqlite3/lib/database.js +90 -0
  323. package/app/node_modules/better-sqlite3/lib/index.js +3 -0
  324. package/app/node_modules/better-sqlite3/lib/methods/aggregate.js +43 -0
  325. package/app/node_modules/better-sqlite3/lib/methods/backup.js +67 -0
  326. package/app/node_modules/better-sqlite3/lib/methods/function.js +31 -0
  327. package/app/node_modules/better-sqlite3/lib/methods/inspect.js +7 -0
  328. package/app/node_modules/better-sqlite3/lib/methods/pragma.js +12 -0
  329. package/app/node_modules/better-sqlite3/lib/methods/serialize.js +16 -0
  330. package/app/node_modules/better-sqlite3/lib/methods/table.js +189 -0
  331. package/app/node_modules/better-sqlite3/lib/methods/transaction.js +78 -0
  332. package/app/node_modules/better-sqlite3/lib/methods/wrappers.js +54 -0
  333. package/app/node_modules/better-sqlite3/lib/sqlite-error.js +20 -0
  334. package/app/node_modules/better-sqlite3/lib/util.js +12 -0
  335. package/app/node_modules/better-sqlite3/package.json +59 -0
  336. package/app/node_modules/bindings/bindings.js +221 -0
  337. package/app/node_modules/bindings/package.json +28 -0
  338. package/app/node_modules/file-uri-to-path/index.js +66 -0
  339. package/app/node_modules/file-uri-to-path/package.json +32 -0
  340. package/app/package.json +2 -1
  341. package/app/src/mitm/manager.js +59 -0
  342. package/app/src/mitm/server.js +1 -1
  343. package/app/src/mitm/server2.js +890 -0
  344. package/cli.js +97 -56
  345. package/package.json +1 -1
  346. /package/app/.next/static/{cc9J-XDw_OEWOXEASQdi9 → I7Z75b-mEq-yr9pvEanD-}/_buildManifest.js +0 -0
  347. /package/app/.next/static/{cc9J-XDw_OEWOXEASQdi9 → I7Z75b-mEq-yr9pvEanD-}/_ssgManifest.js +0 -0
@@ -0,0 +1,890 @@
1
+ const https = require("https");
2
+ const fs = require("fs");
3
+ const path = require("path");
4
+ const dns = require("dns");
5
+ const { promisify } = require("util");
6
+ const Database = require("better-sqlite3");
7
+
8
+ const CURSOR_GLOBAL_DB = path.join(
9
+ process.env.HOME,
10
+ "Library/Application Support/Cursor/User/globalStorage/state.vscdb"
11
+ );
12
+
13
+ // Read full conversation from Cursor global DB
14
+ function readConversationFromDb(conversationId) {
15
+ try {
16
+ const db = new Database(CURSOR_GLOBAL_DB, { readonly: true, fileMustExist: true });
17
+ const stmt = db.prepare("SELECT value FROM cursorDiskKV WHERE key=?");
18
+
19
+ const row = stmt.get(`composerData:${conversationId}`);
20
+ if (!row) { db.close(); return null; }
21
+
22
+ const composer = JSON.parse(row.value);
23
+ const headers = composer.fullConversationHeadersOnly || [];
24
+ const name = composer.name || "";
25
+
26
+ const messages = [];
27
+ for (const h of headers) {
28
+ const brow = stmt.get(`bubbleId:${conversationId}:${h.bubbleId}`);
29
+ if (!brow) continue;
30
+ const bubble = JSON.parse(brow.value);
31
+ const role = h.type === 1 ? "user" : "assistant";
32
+ const text = (bubble.text || "").trim();
33
+ const ts = bubble.createdAt || null;
34
+
35
+ // Tool call bubble (no text but has toolFormerData)
36
+ const tool = bubble.toolFormerData && bubble.toolFormerData.name
37
+ ? { name: bubble.toolFormerData.name, args: bubble.toolFormerData.rawArgs || null, status: bubble.toolFormerData.status || null }
38
+ : null;
39
+
40
+ if (!text && !tool) continue;
41
+ messages.push({ role, text: text || null, tool, ts });
42
+ }
43
+
44
+ db.close();
45
+ return { name, totalMessages: headers.length, messages };
46
+ } catch (e) {
47
+ return { error: e.message };
48
+ }
49
+ }
50
+
51
+ const INTERNAL_REQUEST_HEADER = { name: "x-request-source", value: "local" };
52
+
53
+ // All intercepted domains across all tools
54
+ const TARGET_HOSTS = [
55
+ "daily-cloudcode-pa.googleapis.com",
56
+ "cloudcode-pa.googleapis.com",
57
+ "api.individual.githubcopilot.com",
58
+ ];
59
+
60
+ const LOCAL_PORT = 443;
61
+ const ROUTER_URL = "http://localhost:20128/v1/chat/completions";
62
+ const API_KEY = process.env.ROUTER_API_KEY;
63
+ const { DATA_DIR, MITM_DIR } = require("./paths");
64
+ const DB_FILE = path.join(DATA_DIR, "db.json");
65
+
66
+ const ENABLE_FILE_LOG = false;
67
+ const CURSOR_LOG_DIR = path.join(__dirname, "../../logs/cursor");
68
+ if (!fs.existsSync(CURSOR_LOG_DIR)) fs.mkdirSync(CURSOR_LOG_DIR, { recursive: true });
69
+ const CURSOR_JSONL = path.join(CURSOR_LOG_DIR, "cursor_messages.jsonl");
70
+
71
+ const CURSOR_ENDPOINTS = [
72
+ "/agent.v1.AgentService/RunPoll",
73
+ "/aiserver.v1.BidiService/BidiAppend",
74
+ "/agent.v1.AgentService/Run",
75
+ "/agent.v1.AgentService/RunSSE",
76
+ ];
77
+
78
+ /**
79
+ * Decode Connect-RPC frame: [1 byte flags][4 bytes length][protobuf body]
80
+ * Then walk raw protobuf fields and extract readable strings/numbers.
81
+ */
82
+ function decodeConnectFrame(buf) {
83
+ if (!buf || buf.length < 5) return null;
84
+ const msgLen = buf.readUInt32BE(1);
85
+ if (buf.length < 5 + msgLen) return null;
86
+ return decodeProtoRaw(buf.slice(5, 5 + msgLen));
87
+ }
88
+
89
+ function decodeProtoRaw(buf, depth = 0) {
90
+ if (depth > 6) return {};
91
+ const result = {};
92
+ let offset = 0;
93
+ try {
94
+ while (offset < buf.length) {
95
+ const tag = readVarint(buf, offset);
96
+ if (!tag) break;
97
+ offset += tag.bytes;
98
+ const fieldNum = tag.value >> 3;
99
+ const wireType = tag.value & 0x7;
100
+
101
+ if (wireType === 0) {
102
+ // varint
103
+ const v = readVarint(buf, offset);
104
+ if (!v) break;
105
+ offset += v.bytes;
106
+ result[`f${fieldNum}`] = v.value;
107
+ } else if (wireType === 2) {
108
+ // length-delimited: string, bytes, or nested message
109
+ const lenV = readVarint(buf, offset);
110
+ if (!lenV) break;
111
+ offset += lenV.bytes;
112
+ const data = buf.slice(offset, offset + lenV.value);
113
+ offset += lenV.value;
114
+ // Try as UTF-8 string first
115
+ const str = data.toString("utf8");
116
+ const isPrintable = /^[\x20-\x7E\n\r\t]*$/.test(str) && str.length > 0;
117
+ if (isPrintable) {
118
+ result[`f${fieldNum}`] = str;
119
+ } else if (data.length > 0 && data.length < 4096) {
120
+ // Try nested decode
121
+ const nested = decodeProtoRaw(data, depth + 1);
122
+ result[`f${fieldNum}`] = Object.keys(nested).length ? nested : data.toString("hex").substring(0, 64);
123
+ }
124
+ } else if (wireType === 5) {
125
+ offset += 4;
126
+ } else if (wireType === 1) {
127
+ offset += 8;
128
+ } else {
129
+ break;
130
+ }
131
+ }
132
+ } catch { /* best effort */ }
133
+ return result;
134
+ }
135
+
136
+ function readVarint(buf, offset) {
137
+ let value = 0, shift = 0, bytes = 0;
138
+ while (offset + bytes < buf.length) {
139
+ const b = buf[offset + bytes++];
140
+ value |= (b & 0x7f) << shift;
141
+ shift += 7;
142
+ if (!(b & 0x80)) return { value, bytes };
143
+ if (shift >= 28) break;
144
+ }
145
+ return null;
146
+ }
147
+
148
+ const zlib = require("zlib");
149
+
150
+ /**
151
+ * Deep decode protobuf buffer — returns structured object.
152
+ * Tries to interpret each length-delimited field as:
153
+ * 1. UTF-8 string (if fully printable)
154
+ * 2. Nested proto message (recursive)
155
+ * 3. Hex string fallback
156
+ */
157
+ function deepDecodeProto(buf, depth = 0) {
158
+ if (depth > 10 || buf.length === 0) return null;
159
+ const result = {};
160
+ let off = 0;
161
+ try {
162
+ while (off < buf.length) {
163
+ // Read varint tag
164
+ let tag = 0, shift = 0;
165
+ while (off < buf.length) {
166
+ const b = buf[off++];
167
+ tag |= (b & 0x7f) << shift;
168
+ shift += 7;
169
+ if (!(b & 0x80)) break;
170
+ if (shift > 28) break;
171
+ }
172
+ if (tag === 0) break;
173
+ const field = tag >> 3;
174
+ const wire = tag & 7;
175
+ const key = `f${field}`;
176
+
177
+ if (wire === 0) {
178
+ // varint
179
+ let v = 0, s = 0;
180
+ while (off < buf.length) {
181
+ const b = buf[off++];
182
+ v |= (b & 0x7f) << s;
183
+ s += 7;
184
+ if (!(b & 0x80)) break;
185
+ }
186
+ result[key] = v;
187
+ } else if (wire === 2) {
188
+ // length-delimited
189
+ let len = 0, s = 0;
190
+ while (off < buf.length) {
191
+ const b = buf[off++];
192
+ len |= (b & 0x7f) << s;
193
+ s += 7;
194
+ if (!(b & 0x80)) break;
195
+ }
196
+ if (off + len > buf.length || len < 0) break;
197
+ const data = buf.slice(off, off + len);
198
+ off += len;
199
+
200
+ if (len === 0) {
201
+ result[key] = "";
202
+ continue;
203
+ }
204
+
205
+ // Try UTF-8 string
206
+ const str = data.toString("utf8");
207
+ const isPrintable = str.length > 0 && !/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/.test(str);
208
+ if (isPrintable) {
209
+ // Accumulate repeated fields as array
210
+ if (key in result) {
211
+ result[key] = [].concat(result[key], str);
212
+ } else {
213
+ result[key] = str;
214
+ }
215
+ continue;
216
+ }
217
+
218
+ // Try nested proto
219
+ if (len >= 2 && len <= 500000) {
220
+ const nested = deepDecodeProto(data, depth + 1);
221
+ if (nested && Object.keys(nested).length > 0) {
222
+ if (key in result) {
223
+ result[key] = [].concat(result[key], [nested]);
224
+ } else {
225
+ result[key] = nested;
226
+ }
227
+ continue;
228
+ }
229
+ }
230
+
231
+ // Fallback: hex (truncate at 64 bytes)
232
+ result[key] = data.slice(0, 64).toString("hex");
233
+ } else if (wire === 5) {
234
+ off += 4;
235
+ } else if (wire === 1) {
236
+ off += 8;
237
+ } else {
238
+ break;
239
+ }
240
+ }
241
+ } catch { /* best effort */ }
242
+ return result;
243
+ }
244
+
245
+ // ── Proto helpers ──────────────────────────────────────────────
246
+ function protoReadVarint(buf, off) {
247
+ let v = 0, shift = 0;
248
+ while (off < buf.length) {
249
+ const b = buf[off++];
250
+ v |= (b & 0x7f) << shift;
251
+ shift += 7;
252
+ if (!(b & 0x80)) return { v, off };
253
+ if (shift > 49) break;
254
+ }
255
+ return null;
256
+ }
257
+
258
+ function protoWalkFields(buf) {
259
+ const fields = [];
260
+ let off = 0;
261
+ while (off < buf.length) {
262
+ const t = protoReadVarint(buf, off);
263
+ if (!t || t.v === 0) break;
264
+ off = t.off;
265
+ const field = t.v >> 3, wire = t.v & 7;
266
+ if (wire === 0) {
267
+ const r = protoReadVarint(buf, off);
268
+ if (!r) break;
269
+ off = r.off;
270
+ fields.push({ field, wire, value: r.v });
271
+ } else if (wire === 2) {
272
+ const r = protoReadVarint(buf, off);
273
+ if (!r) break;
274
+ off = r.off;
275
+ if (off + r.v > buf.length) break;
276
+ fields.push({ field, wire, data: buf.slice(off, off + r.v) });
277
+ off += r.v;
278
+ } else if (wire === 5) { off += 4; }
279
+ else if (wire === 1) { off += 8; }
280
+ else break;
281
+ }
282
+ return fields;
283
+ }
284
+
285
+ function protoStr(buf) {
286
+ if (!buf || buf.length === 0) return null;
287
+ const s = buf.toString("utf8");
288
+ return /[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/.test(s) ? null : s;
289
+ }
290
+
291
+ // ── Schema-aware decoders ──────────────────────────────────────
292
+
293
+ // BidiAppendRequest: f1=data(hex-encoded AgentClientMessage), f2=requestId{f1=uuid}, f3=seqno
294
+ function decodeBidiAppend(buf) {
295
+ const fields = protoWalkFields(buf);
296
+ const result = {};
297
+ for (const f of fields) {
298
+ if (f.field === 1 && f.data) {
299
+ // f1.data is ASCII hex string → decode to actual proto bytes
300
+ try {
301
+ const hexStr = f.data.toString("utf8");
302
+ const protoBytes = Buffer.from(hexStr, "hex");
303
+ result.agentMsg = decodeAgentClientMsg(protoBytes);
304
+ } catch { result.agentMsg = { type: "hex_decode_error" }; }
305
+ } else if (f.field === 2 && f.data) {
306
+ const inner = protoWalkFields(f.data);
307
+ const id = inner.find(x => x.field === 1 && x.data);
308
+ result.requestId = id ? protoStr(id.data) : null;
309
+ } else if (f.field === 3) result.seqno = f.value;
310
+ }
311
+ return result;
312
+ }
313
+
314
+ // AgentClientMessage oneof: f1=AgentRunRequest, f2=ExecClientMessage, f3=KvClientMessage, f4=ConversationAction, f5=ExecClientControlMessage, f6=InteractionResponse, f7=ClientHeartbeat
315
+ function decodeAgentClientMsg(buf) {
316
+ const fields = protoWalkFields(buf);
317
+ for (const f of fields) {
318
+ // f7=ClientHeartbeat: wire-type 2 but empty (len=0), data is Buffer(0)
319
+ if (f.field === 7) return { type: "ClientHeartbeat" };
320
+ if (f.data === undefined || f.data === null) continue;
321
+ if (f.field === 1 && f.data.length > 0) return { type: "AgentRunRequest", ...decodeAgentRunRequest(f.data) };
322
+ if (f.field === 2 && f.data.length > 0) return { type: "ExecClientMessage", ...decodeExecClientMessage(f.data) };
323
+ if (f.field === 3) return { type: "KvClientMessage" };
324
+ if (f.field === 4 && f.data.length > 0) return { type: "ConversationAction", ...decodeConversationAction(f.data) };
325
+ if (f.field === 5) return { type: "ExecClientControlMessage" };
326
+ if (f.field === 6) return { type: "InteractionResponse" };
327
+ }
328
+ return { type: "unknown" };
329
+ }
330
+
331
+ // AgentRunRequest: f1=conversation_state, f2=action, f3=model_details, f4=mcp_tools, f5=conversation_id, f6=mcp_file_system_options, f7=skill_options
332
+ function decodeAgentRunRequest(buf) {
333
+ const fields = protoWalkFields(buf);
334
+ const result = {};
335
+
336
+ for (const f of fields) {
337
+ if (f.field === 1 && f.data) result.state = decodeConversationState(f.data);
338
+ if (f.field === 2 && f.data) result.action = decodeConversationAction(f.data);
339
+ if (f.field === 3 && f.data) result.model = decodeModelDetails(f.data);
340
+ if (f.field === 4 && f.data) result.mcpTools = decodeMcpTools(f.data);
341
+ if (f.field === 5 && f.data) result.conversationId = protoStr(f.data);
342
+ }
343
+ return result;
344
+ }
345
+
346
+ // McpTools: f1=repeated McpDescriptor (f1=serverName, f2=repeated tools)
347
+ function decodeMcpTools(buf) {
348
+ const fields = protoWalkFields(buf);
349
+ const descriptors = [];
350
+ for (const f of fields) {
351
+ if (f.field === 1 && f.data) {
352
+ const inner = protoWalkFields(f.data);
353
+ const name = inner.find(x => x.field === 1 && x.data);
354
+ const tools = inner.filter(x => x.field === 2 && x.data).map(t => {
355
+ const tf = protoWalkFields(t.data);
356
+ const tname = tf.find(x => x.field === 1 && x.data);
357
+ return tname ? protoStr(tname.data) : null;
358
+ }).filter(Boolean);
359
+ descriptors.push({ server: name ? protoStr(name.data) : null, tools });
360
+ }
361
+ }
362
+ return descriptors;
363
+ }
364
+
365
+ // ExecClientMessage: f1=id(uint32), f2=shellResult, f3=writeResult, etc.
366
+ function decodeExecClientMessage(buf) {
367
+ const fields = protoWalkFields(buf);
368
+ const result = { id: null, execId: null, resultType: "unknown" };
369
+ for (const f of fields) {
370
+ if (f.field === 1 && f.value !== undefined) result.id = f.value;
371
+ if (f.field === 15 && f.data) result.execId = protoStr(f.data);
372
+ // Detect result type by field number (oneof)
373
+ const resultTypes = { 2: "shellResult", 3: "writeResult", 4: "deleteResult", 5: "grepResult", 7: "readResult", 8: "lsResult", 9: "diagnosticsResult", 10: "requestContextResult", 11: "mcpResult", 14: "shellStream", 16: "backgroundShellSpawnResult" };
374
+ if (f.data && resultTypes[f.field]) result.resultType = resultTypes[f.field];
375
+ }
376
+ return result;
377
+ }
378
+
379
+ // ModelDetails — scan all string fields
380
+ function decodeModelDetails(buf) {
381
+ const fields = protoWalkFields(buf);
382
+ const result = {};
383
+ for (const f of fields) {
384
+ if (f.data) {
385
+ const s = protoStr(f.data);
386
+ if (s && s.length > 0) result[`f${f.field}`] = s;
387
+ } else if (f.value !== undefined) {
388
+ result[`f${f.field}`] = f.value;
389
+ }
390
+ }
391
+ return result;
392
+ }
393
+
394
+ // ConversationAction: f1=StartChatAction → f1=userMsg{f1=text,f2=uuid,f8=lexical}, f2=history{f2=contextFiles,f7=tools}
395
+ function decodeConversationAction(buf) {
396
+ const result = {};
397
+ const topFields = protoWalkFields(buf);
398
+
399
+ // action.f1 = StartChatAction wrapper
400
+ const f1 = topFields.find(f => f.field === 1 && f.data && f.data.length > 0);
401
+ if (!f1) {
402
+ // No StartChatAction — show which fields are present for debugging
403
+ const presentFields = topFields.map(f => `f${f.field}`);
404
+ if (presentFields.length > 0) result._fields = presentFields;
405
+ return result;
406
+ }
407
+ const f1Fields = protoWalkFields(f1.data);
408
+
409
+ // ── User message: action.f1.f1 ──────────────────────────────
410
+ const f1f1 = f1Fields.find(f => f.field === 1 && f.data);
411
+ if (f1f1) {
412
+ for (const f of protoWalkFields(f1f1.data)) {
413
+ if (!f.data) continue;
414
+ const s = protoStr(f.data);
415
+ if (f.field === 1 && s) result.text = s;
416
+ if (f.field === 2 && s) result.messageId = s;
417
+ if (f.field === 8 && s) {
418
+ try {
419
+ const lex = JSON.parse(s);
420
+ const texts = [];
421
+ function extractLexText(node) {
422
+ if (node?.text) texts.push(node.text);
423
+ (node?.children || []).forEach(extractLexText);
424
+ }
425
+ extractLexText(lex?.root);
426
+ result.textFull = texts.join("");
427
+ } catch { result.lexical = s.substring(0, 300); }
428
+ }
429
+ }
430
+ }
431
+
432
+ // ── Conversation history: action.f1.f2 ──────────────────────
433
+ const f1f2 = f1Fields.find(f => f.field === 2 && f.data);
434
+ if (f1f2) {
435
+ const histFields = protoWalkFields(f1f2.data);
436
+
437
+ // f2 repeated = context files (rules, open files...)
438
+ result.contextFiles = histFields
439
+ .filter(f => f.field === 2 && f.data)
440
+ .map(t => {
441
+ const tf = protoWalkFields(t.data);
442
+ const name = tf.find(f => f.field === 1 && f.data);
443
+ const content = tf.find(f => f.field === 2 && f.data);
444
+ return {
445
+ path: name ? protoStr(name.data) : null,
446
+ content: content ? protoStr(content.data)?.substring(0, 500) : null,
447
+ };
448
+ })
449
+ .filter(x => x.path);
450
+
451
+ // f7 repeated = MCP tools
452
+ result.tools = histFields
453
+ .filter(f => f.field === 7 && f.data)
454
+ .map(t => {
455
+ const tf = protoWalkFields(t.data);
456
+ const name = tf.find(f => f.field === 1 && f.data);
457
+ const desc = tf.find(f => f.field === 2 && f.data);
458
+ return {
459
+ name: name ? protoStr(name.data) : null,
460
+ description: desc ? protoStr(desc.data) : null,
461
+ };
462
+ })
463
+ .filter(x => x.name);
464
+
465
+ }
466
+
467
+ return result;
468
+ }
469
+
470
+ /**
471
+ * Recursively decode any proto buffer into a plain JS object for debugging.
472
+ * Each field: try UTF-8 string → nested proto → hex fallback.
473
+ * Repeated fields become arrays.
474
+ */
475
+ function protoTreeToObj(buf, depth = 0) {
476
+ if (depth > 12 || !buf || buf.length === 0) return null;
477
+ const result = {};
478
+ const fields = protoWalkFields(buf);
479
+ for (const f of fields) {
480
+ const key = `f${f.field}`;
481
+ let val;
482
+ if (f.data !== undefined) {
483
+ const s = protoStr(f.data);
484
+ if (s !== null) {
485
+ // Detect hex-encoded proto (BidiAppend.data field)
486
+ if (/^[0-9a-f]{20,}$/i.test(s)) {
487
+ try {
488
+ const dec = protoTreeToObj(Buffer.from(s, "hex"), depth + 1);
489
+ val = (dec && Object.keys(dec).length > 0) ? dec : s;
490
+ } catch { val = s; }
491
+ } else {
492
+ try { val = JSON.parse(s); } catch { val = s; }
493
+ }
494
+ } else if (f.data.length > 0) {
495
+ const nested = protoTreeToObj(f.data, depth + 1);
496
+ val = (nested && Object.keys(nested).length > 0)
497
+ ? nested
498
+ : f.data.toString("hex");
499
+ } else {
500
+ val = "";
501
+ }
502
+ } else {
503
+ val = f.value;
504
+ }
505
+ // Accumulate repeated fields as array
506
+ if (key in result) {
507
+ result[key] = [].concat(result[key], [val]);
508
+ } else {
509
+ result[key] = val;
510
+ }
511
+ }
512
+ return result;
513
+ }
514
+
515
+ // ConversationStateStructure: f1=root_prompt_messages_json(encrypted bytes), f3=todos, f8=turns, f10=mode
516
+ function decodeConversationState(buf) {
517
+ const fields = protoWalkFields(buf);
518
+ const turns = [], todos = [];
519
+ let mode = null, messageCount = 0;
520
+ for (const f of fields) {
521
+ if (f.field === 10 && f.value !== undefined) {
522
+ const modes = ["unspecified", "agent", "ask", "plan", "debug", "triage"];
523
+ mode = modes[f.value] || `mode_${f.value}`;
524
+ }
525
+ if (!f.data) continue;
526
+ if (f.field === 1) {
527
+ // Encrypted bytes — just count, cannot decode
528
+ messageCount++;
529
+ } else if (f.field === 8) {
530
+ // f8 = repeated bytes (ConversationTurn OR encrypted blob)
531
+ // Encrypted turns: binary blobs that don't parse as valid proto strings
532
+ if (f.data.length === 32) continue; // 32-byte encrypted blob
533
+ const inner = protoWalkFields(f.data);
534
+ const strs = inner.filter(x => x.data).map(x => protoStr(x.data)).filter(s => s && s.length > 3);
535
+ if (strs.length) turns.push(strs.slice(0, 3));
536
+ } else if (f.field === 3) {
537
+ // f3 = repeated bytes (TodoItem OR encrypted blob)
538
+ // Encrypted: 32-byte binary (shows as 64-char hex in protoStr-reject path)
539
+ // TodoItem: f1=id(str), f2=content(str), f3=status(varint)
540
+ if (f.data.length === 32) {
541
+ // 32 bytes = encrypted blob, skip
542
+ continue;
543
+ }
544
+ const inner = protoWalkFields(f.data);
545
+ const id = inner.find(x => x.field === 1 && x.data);
546
+ const content = inner.find(x => x.field === 2 && x.data);
547
+ const status = inner.find(x => x.field === 3 && x.value !== undefined);
548
+ const idStr = id ? protoStr(id.data) : null;
549
+ const contentStr = content ? protoStr(content.data) : null;
550
+ // If neither id nor content is readable string, it's encrypted
551
+ if (!idStr && !contentStr) continue;
552
+ const statusMap = ["unspecified", "pending", "in_progress", "completed", "cancelled"];
553
+ todos.push({
554
+ id: idStr,
555
+ content: contentStr,
556
+ status: status ? (statusMap[status.value] || `status_${status.value}`) : null,
557
+ });
558
+ }
559
+ }
560
+ return { mode, messageCount, turns: turns.slice(0, 5), todos: todos.slice(0, 20) };
561
+ }
562
+
563
+ // ── Save per-chat JSON file ────────────────────────────────────
564
+ function saveCursorLogFull(url, headers, buf) {
565
+ try {
566
+ if (buf.length < 5) return;
567
+
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
+ const isGzip = buf[0] === 0x1f && buf[1] === 0x8b;
575
+ if (isGzip) {
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
+ }
581
+
582
+ const endpoint = isBidiAppend ? "BidiAppend" : "RunPoll";
583
+ let decoded = {};
584
+ let userMessage = null;
585
+
586
+ if (isBidiAppend) {
587
+ decoded = decodeBidiAppend(raw);
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
+ }
602
+
603
+ // Fetch conversation history from local Cursor DB when AgentRunRequest detected
604
+ const conversationId = decoded?.agentMsg?.conversationId || null;
605
+ let conversation = null;
606
+ if (conversationId && decoded?.agentMsg?.type === "AgentRunRequest") {
607
+ conversation = readConversationFromDb(conversationId);
608
+ }
609
+
610
+ const ts = new Date().toISOString().replace(/[:.]/g, "-");
611
+ const base = path.join(CURSOR_LOG_DIR, `${ts}_${endpoint}`);
612
+
613
+ // _chat.json — structured decoded
614
+ fs.writeFileSync(`${base}_chat.json`, JSON.stringify({
615
+ ts: new Date().toISOString(),
616
+ endpoint,
617
+ version: headers["x-cursor-client-version"] || null,
618
+ encoding: isGzip ? "gzip" : "raw",
619
+ sizeIn: buf.length,
620
+ sizeRaw: raw.length,
621
+ userMessage,
622
+ decoded,
623
+ conversation,
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)";
631
+ const convName = conversation?.name ? ` | conv="${conversation.name}" (${conversation.totalMessages} msgs)` : "";
632
+ console.log(`[CURSOR] ${endpoint} | type=${agentType} | msg=${userMessage || "(none)"}${convName} | ${isGzip ? "gzip" : "raw"} ${buf.length}B`);
633
+ } catch (e) {
634
+ console.error(`[CURSOR] decode error: ${e.message}`);
635
+ }
636
+ }
637
+
638
+ if (!API_KEY) {
639
+ console.error("❌ ROUTER_API_KEY required");
640
+ process.exit(1);
641
+ }
642
+
643
+ const { getCertForDomain } = require("./cert/generate");
644
+
645
+ // Certificate cache for performance
646
+ const certCache = new Map();
647
+
648
+ // SNI callback for dynamic certificate generation
649
+ function sniCallback(servername, cb) {
650
+ try {
651
+ // Check cache first
652
+ if (certCache.has(servername)) {
653
+ const cached = certCache.get(servername);
654
+ return cb(null, cached);
655
+ }
656
+
657
+ // Generate new cert for this domain
658
+ const certData = getCertForDomain(servername);
659
+ if (!certData) {
660
+ return cb(new Error(`Failed to generate cert for ${servername}`));
661
+ }
662
+
663
+ // Create secure context
664
+ const ctx = require("tls").createSecureContext({
665
+ key: certData.key,
666
+ cert: certData.cert
667
+ });
668
+
669
+ // Cache it
670
+ certCache.set(servername, ctx);
671
+ console.log(`✅ Generated cert for: ${servername}`);
672
+
673
+ cb(null, ctx);
674
+ } catch (error) {
675
+ console.error(`❌ SNI error for ${servername}:`, error.message);
676
+ cb(error);
677
+ }
678
+ }
679
+
680
+ // Load Root CA for default context
681
+ const certDir = MITM_DIR;
682
+ const rootCAKeyPath = path.join(certDir, "rootCA.key");
683
+ const rootCACertPath = path.join(certDir, "rootCA.crt");
684
+
685
+ let sslOptions;
686
+ try {
687
+ sslOptions = {
688
+ key: fs.readFileSync(rootCAKeyPath),
689
+ cert: fs.readFileSync(rootCACertPath),
690
+ SNICallback: sniCallback
691
+ };
692
+ } catch (e) {
693
+ console.error(`❌ Root CA not found in ${certDir}: ${e.message}`);
694
+ process.exit(1);
695
+ }
696
+
697
+ // Antigravity: Gemini generateContent endpoints
698
+ const ANTIGRAVITY_URL_PATTERNS = [":generateContent", ":streamGenerateContent"];
699
+ // Copilot: OpenAI-compatible + Anthropic endpoints
700
+ const COPILOT_URL_PATTERNS = ["/chat/completions", "/v1/messages", "/responses"];
701
+
702
+ const LOG_DIR = path.join(__dirname, "../../logs/mitm");
703
+ if (ENABLE_FILE_LOG && !fs.existsSync(LOG_DIR)) fs.mkdirSync(LOG_DIR, { recursive: true });
704
+
705
+ function saveRequestLog(url, bodyBuffer) {
706
+ if (!ENABLE_FILE_LOG) return;
707
+ try {
708
+ const ts = new Date().toISOString().replace(/[:.]/g, "-");
709
+ const urlSlug = url.replace(/[^a-zA-Z0-9]/g, "_").substring(0, 60);
710
+ const filePath = path.join(LOG_DIR, `${ts}_${urlSlug}.json`);
711
+ const body = JSON.parse(bodyBuffer.toString());
712
+ fs.writeFileSync(filePath, JSON.stringify(body, null, 2));
713
+ } catch { /* ignore */ }
714
+ }
715
+
716
+ const cachedTargetIPs = {};
717
+ async function resolveTargetIP(hostname) {
718
+ if (cachedTargetIPs[hostname]) return cachedTargetIPs[hostname];
719
+ const resolver = new dns.Resolver();
720
+ resolver.setServers(["8.8.8.8"]);
721
+ const resolve4 = promisify(resolver.resolve4.bind(resolver));
722
+ const addresses = await resolve4(hostname);
723
+ cachedTargetIPs[hostname] = addresses[0];
724
+ return cachedTargetIPs[hostname];
725
+ }
726
+
727
+ function collectBodyRaw(req) {
728
+ return new Promise((resolve, reject) => {
729
+ const chunks = [];
730
+ req.on("data", chunk => chunks.push(chunk));
731
+ req.on("end", () => resolve(Buffer.concat(chunks)));
732
+ req.on("error", reject);
733
+ });
734
+ }
735
+
736
+ // Extract model from URL path (Gemini) or body (OpenAI/Anthropic)
737
+ function extractModel(url, body) {
738
+ const urlMatch = url.match(/\/models\/([^/:]+)/);
739
+ if (urlMatch) return urlMatch[1];
740
+ try { return JSON.parse(body.toString()).model || null; } catch { return null; }
741
+ }
742
+
743
+ function getMappedModel(tool, model) {
744
+ if (!model) return null;
745
+ try {
746
+ if (!fs.existsSync(DB_FILE)) return null;
747
+ const db = JSON.parse(fs.readFileSync(DB_FILE, "utf-8"));
748
+ return db.mitmAlias?.[tool]?.[model] || null;
749
+ } catch {
750
+ return null;
751
+ }
752
+ }
753
+
754
+ /**
755
+ * Determine which tool this request belongs to based on hostname
756
+ */
757
+ function getToolForHost(host) {
758
+ const h = (host || "").split(":")[0];
759
+ if (h === "api.individual.githubcopilot.com") return "copilot";
760
+ if (h === "daily-cloudcode-pa.googleapis.com" || h === "cloudcode-pa.googleapis.com") return "antigravity";
761
+ return null;
762
+ }
763
+
764
+ async function passthrough(req, res, bodyBuffer) {
765
+ const targetHost = (req.headers.host || TARGET_HOSTS[0]).split(":")[0];
766
+ const targetIP = await resolveTargetIP(targetHost);
767
+
768
+ const forwardReq = https.request({
769
+ hostname: targetIP,
770
+ port: 443,
771
+ path: req.url,
772
+ method: req.method,
773
+ headers: { ...req.headers, host: targetHost },
774
+ servername: targetHost,
775
+ rejectUnauthorized: false
776
+ }, (forwardRes) => {
777
+ res.writeHead(forwardRes.statusCode, forwardRes.headers);
778
+ forwardRes.pipe(res);
779
+ });
780
+
781
+ forwardReq.on("error", (err) => {
782
+ console.error(`❌ Passthrough error: ${err.message}`);
783
+ if (!res.headersSent) res.writeHead(502);
784
+ res.end("Bad Gateway");
785
+ });
786
+
787
+ if (bodyBuffer.length > 0) forwardReq.write(bodyBuffer);
788
+ forwardReq.end();
789
+ }
790
+
791
+ async function intercept(req, res, bodyBuffer, mappedModel) {
792
+ try {
793
+ const body = JSON.parse(bodyBuffer.toString());
794
+ body.model = mappedModel;
795
+
796
+ const response = await fetch(ROUTER_URL, {
797
+ method: "POST",
798
+ headers: {
799
+ "Content-Type": "application/json",
800
+ "Authorization": `Bearer ${API_KEY}`
801
+ },
802
+ body: JSON.stringify(body)
803
+ });
804
+
805
+ if (!response.ok) {
806
+ const errText = await response.text().catch(() => "");
807
+ throw new Error(`9Router ${response.status}: ${errText}`);
808
+ }
809
+
810
+ const ct = response.headers.get("content-type") || "application/json";
811
+ const resHeaders = { "Content-Type": ct, "Cache-Control": "no-cache", "Connection": "keep-alive" };
812
+ if (ct.includes("text/event-stream")) resHeaders["X-Accel-Buffering"] = "no";
813
+ res.writeHead(200, resHeaders);
814
+
815
+ const reader = response.body.getReader();
816
+ const decoder = new TextDecoder();
817
+ while (true) {
818
+ const { done, value } = await reader.read();
819
+ if (done) { res.end(); break; }
820
+ res.write(decoder.decode(value, { stream: true }));
821
+ }
822
+ } catch (error) {
823
+ console.error(`❌ ${error.message}`);
824
+ if (!res.headersSent) res.writeHead(500, { "Content-Type": "application/json" });
825
+ res.end(JSON.stringify({ error: { message: error.message, type: "mitm_error" } }));
826
+ }
827
+ }
828
+
829
+ const server = https.createServer(sslOptions, async (req, res) => {
830
+ if (req.url === "/_mitm_health") {
831
+ res.writeHead(200, { "Content-Type": "application/json" });
832
+ res.end(JSON.stringify({ ok: true, pid: process.pid }));
833
+ return;
834
+ }
835
+
836
+ console.log(`[MITM] ${req.method} https://${req.headers.host}${req.url}`);
837
+
838
+ const bodyBuffer = await collectBodyRaw(req);
839
+ if (bodyBuffer.length > 0) saveRequestLog(req.url, bodyBuffer);
840
+
841
+ // Decode and log Cursor protobuf endpoints
842
+ if (CURSOR_ENDPOINTS.some(e => req.url.includes(e))) {
843
+ saveCursorLogFull(req.url, req.headers, bodyBuffer);
844
+ }
845
+
846
+ // Anti-loop: requests originating from 9Router bypass interception
847
+ if (req.headers[INTERNAL_REQUEST_HEADER.name] === INTERNAL_REQUEST_HEADER.value) {
848
+ return passthrough(req, res, bodyBuffer);
849
+ }
850
+
851
+ const tool = getToolForHost(req.headers.host);
852
+ if (!tool) return passthrough(req, res, bodyBuffer);
853
+
854
+ // Check if this URL should be intercepted based on tool
855
+ const isChat = tool === "antigravity"
856
+ ? ANTIGRAVITY_URL_PATTERNS.some(p => req.url.includes(p))
857
+ : COPILOT_URL_PATTERNS.some(p => req.url.includes(p));
858
+
859
+ if (!isChat) return passthrough(req, res, bodyBuffer);
860
+
861
+ const model = extractModel(req.url, bodyBuffer);
862
+ console.log("Extracted model:", model)
863
+ const mappedModel = getMappedModel(tool, model);
864
+
865
+ if (!mappedModel) return passthrough(req, res, bodyBuffer);
866
+
867
+ return intercept(req, res, bodyBuffer, mappedModel);
868
+ });
869
+
870
+ server.listen(LOCAL_PORT, () => {
871
+ console.log(`🚀 MITM ready on :${LOCAL_PORT}`);
872
+ });
873
+
874
+ server.on("error", (error) => {
875
+ if (error.code === "EADDRINUSE") {
876
+ console.error(`❌ Port ${LOCAL_PORT} already in use`);
877
+ } else if (error.code === "EACCES") {
878
+ console.error(`❌ Permission denied for port ${LOCAL_PORT}`);
879
+ } else {
880
+ console.error(`❌ ${error.message}`);
881
+ }
882
+ process.exit(1);
883
+ });
884
+
885
+ const shutdown = () => { server.close(() => process.exit(0)); };
886
+ process.on("SIGTERM", shutdown);
887
+ process.on("SIGINT", shutdown);
888
+ if (process.platform === "win32") {
889
+ process.on("SIGBREAK", shutdown);
890
+ }