@jsonstudio/rcc 0.89.683 → 0.89.912

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 (215) hide show
  1. package/README.md +44 -0
  2. package/dist/build-info.js +2 -2
  3. package/dist/cli.js +164 -116
  4. package/dist/cli.js.map +1 -1
  5. package/dist/client/anthropic/anthropic-protocol-client.js +42 -1
  6. package/dist/client/anthropic/anthropic-protocol-client.js.map +1 -1
  7. package/dist/client/gemini-cli/gemini-cli-protocol-client.js +4 -1
  8. package/dist/client/gemini-cli/gemini-cli-protocol-client.js.map +1 -1
  9. package/dist/commands/camoufox-backfill.d.ts +2 -0
  10. package/dist/commands/camoufox-backfill.js +33 -0
  11. package/dist/commands/camoufox-backfill.js.map +1 -0
  12. package/dist/commands/camoufox-fp.d.ts +2 -0
  13. package/dist/commands/camoufox-fp.js +86 -0
  14. package/dist/commands/camoufox-fp.js.map +1 -0
  15. package/dist/commands/oauth.d.ts +2 -0
  16. package/dist/commands/oauth.js +170 -0
  17. package/dist/commands/oauth.js.map +1 -0
  18. package/dist/commands/provider-update.js +439 -2
  19. package/dist/commands/provider-update.js.map +1 -1
  20. package/dist/commands/quota-status.d.ts +2 -0
  21. package/dist/commands/quota-status.js +80 -0
  22. package/dist/commands/quota-status.js.map +1 -0
  23. package/dist/commands/token-daemon.js +12 -1
  24. package/dist/commands/token-daemon.js.map +1 -1
  25. package/dist/config/provider-v2-loader.d.ts +16 -0
  26. package/dist/config/provider-v2-loader.js +84 -0
  27. package/dist/config/provider-v2-loader.js.map +1 -0
  28. package/dist/config/routecodex-config-loader.js +27 -4
  29. package/dist/config/routecodex-config-loader.js.map +1 -1
  30. package/dist/config/system-prompts/codex-cli.txt +1 -0
  31. package/dist/config/virtual-router-builder.d.ts +9 -0
  32. package/dist/config/virtual-router-builder.js +34 -0
  33. package/dist/config/virtual-router-builder.js.map +1 -0
  34. package/dist/config/virtual-router-types.d.ts +25 -0
  35. package/dist/config/virtual-router-types.js +30 -0
  36. package/dist/config/virtual-router-types.js.map +1 -0
  37. package/dist/manager/index.d.ts +10 -0
  38. package/dist/manager/index.js +27 -0
  39. package/dist/manager/index.js.map +1 -0
  40. package/dist/manager/modules/health/index.d.ts +22 -0
  41. package/dist/manager/modules/health/index.js +82 -0
  42. package/dist/manager/modules/health/index.js.map +1 -0
  43. package/dist/manager/modules/quota/index.d.ts +57 -0
  44. package/dist/manager/modules/quota/index.js +426 -0
  45. package/dist/manager/modules/quota/index.js.map +1 -0
  46. package/dist/manager/modules/routing/index.d.ts +17 -0
  47. package/dist/manager/modules/routing/index.js +61 -0
  48. package/dist/manager/modules/routing/index.js.map +1 -0
  49. package/dist/manager/modules/token/index.d.ts +10 -0
  50. package/dist/manager/modules/token/index.js +58 -0
  51. package/dist/manager/modules/token/index.js.map +1 -0
  52. package/dist/manager/storage/base-store.d.ts +6 -0
  53. package/dist/manager/storage/base-store.js +2 -0
  54. package/dist/manager/storage/base-store.js.map +1 -0
  55. package/dist/manager/storage/file-store.d.ts +25 -0
  56. package/dist/manager/storage/file-store.js +117 -0
  57. package/dist/manager/storage/file-store.js.map +1 -0
  58. package/dist/manager/types.d.ts +9 -0
  59. package/dist/manager/types.js +2 -0
  60. package/dist/manager/types.js.map +1 -0
  61. package/dist/message-center/index.d.ts +5 -0
  62. package/dist/message-center/index.js +6 -0
  63. package/dist/message-center/index.js.map +1 -0
  64. package/dist/message-center/message-center.d.ts +93 -0
  65. package/dist/message-center/message-center.js +189 -0
  66. package/dist/message-center/message-center.js.map +1 -0
  67. package/dist/providers/auth/antigravity-userinfo-helper.d.ts +2 -0
  68. package/dist/providers/auth/antigravity-userinfo-helper.js +102 -0
  69. package/dist/providers/auth/antigravity-userinfo-helper.js.map +1 -1
  70. package/dist/providers/auth/iflow-cookie-auth.d.ts +27 -0
  71. package/dist/providers/auth/iflow-cookie-auth.js +209 -0
  72. package/dist/providers/auth/iflow-cookie-auth.js.map +1 -0
  73. package/dist/providers/auth/oauth-lifecycle.js +29 -22
  74. package/dist/providers/auth/oauth-lifecycle.js.map +1 -1
  75. package/dist/providers/auth/token-scanner/index.js +16 -1
  76. package/dist/providers/auth/token-scanner/index.js.map +1 -1
  77. package/dist/providers/core/config/camoufox-launcher.d.ts +16 -0
  78. package/dist/providers/core/config/camoufox-launcher.js +314 -0
  79. package/dist/providers/core/config/camoufox-launcher.js.map +1 -0
  80. package/dist/providers/core/config/oauth-flows.d.ts +9 -0
  81. package/dist/providers/core/config/oauth-flows.js +50 -19
  82. package/dist/providers/core/config/oauth-flows.js.map +1 -1
  83. package/dist/providers/core/config/provider-oauth-configs.d.ts +6 -0
  84. package/dist/providers/core/config/provider-oauth-configs.js +12 -0
  85. package/dist/providers/core/config/provider-oauth-configs.js.map +1 -1
  86. package/dist/providers/core/config/service-profiles.js +26 -3
  87. package/dist/providers/core/config/service-profiles.js.map +1 -1
  88. package/dist/providers/core/runtime/antigravity-quota-client.d.ts +10 -0
  89. package/dist/providers/core/runtime/antigravity-quota-client.js +88 -0
  90. package/dist/providers/core/runtime/antigravity-quota-client.js.map +1 -0
  91. package/dist/providers/core/runtime/base-provider.d.ts +2 -1
  92. package/dist/providers/core/runtime/base-provider.js +93 -34
  93. package/dist/providers/core/runtime/base-provider.js.map +1 -1
  94. package/dist/providers/core/runtime/gemini-cli-http-provider.js +42 -10
  95. package/dist/providers/core/runtime/gemini-cli-http-provider.js.map +1 -1
  96. package/dist/providers/core/runtime/http-request-executor.js +24 -0
  97. package/dist/providers/core/runtime/http-request-executor.js.map +1 -1
  98. package/dist/providers/core/runtime/http-transport-provider.d.ts +0 -3
  99. package/dist/providers/core/runtime/http-transport-provider.js +32 -136
  100. package/dist/providers/core/runtime/http-transport-provider.js.map +1 -1
  101. package/dist/providers/core/runtime/provider-error-classifier.js +18 -10
  102. package/dist/providers/core/runtime/provider-error-classifier.js.map +1 -1
  103. package/dist/providers/core/runtime/rate-limit-manager.d.ts +6 -0
  104. package/dist/providers/core/runtime/rate-limit-manager.js +23 -0
  105. package/dist/providers/core/runtime/rate-limit-manager.js.map +1 -1
  106. package/dist/providers/core/runtime/responses-provider.js +17 -19
  107. package/dist/providers/core/runtime/responses-provider.js.map +1 -1
  108. package/dist/providers/core/strategies/oauth-auth-code-flow.d.ts +1 -0
  109. package/dist/providers/core/strategies/oauth-auth-code-flow.js +3 -2
  110. package/dist/providers/core/strategies/oauth-auth-code-flow.js.map +1 -1
  111. package/dist/providers/core/strategies/oauth-device-flow.d.ts +1 -0
  112. package/dist/providers/core/strategies/oauth-device-flow.js +3 -2
  113. package/dist/providers/core/strategies/oauth-device-flow.js.map +1 -1
  114. package/dist/providers/core/strategies/oauth-hybrid-flow.d.ts +1 -0
  115. package/dist/providers/core/strategies/oauth-hybrid-flow.js +3 -2
  116. package/dist/providers/core/strategies/oauth-hybrid-flow.js.map +1 -1
  117. package/dist/providers/core/utils/http-client.js +43 -1
  118. package/dist/providers/core/utils/http-client.js.map +1 -1
  119. package/dist/providers/mock/mock-provider-runtime.js +4 -4
  120. package/dist/providers/mock/mock-provider-runtime.js.map +1 -1
  121. package/dist/providers/profile/provider-profile-loader.js +13 -1
  122. package/dist/providers/profile/provider-profile-loader.js.map +1 -1
  123. package/dist/providers/profile/provider-profile.d.ts +5 -0
  124. package/dist/scripts/camoufox/gen-fingerprint-env.py +171 -0
  125. package/dist/scripts/camoufox/launch-auth.mjs +617 -0
  126. package/dist/server/runtime/http-server/daemon-admin/credentials-handler.d.ts +3 -0
  127. package/dist/server/runtime/http-server/daemon-admin/credentials-handler.js +138 -0
  128. package/dist/server/runtime/http-server/daemon-admin/credentials-handler.js.map +1 -0
  129. package/dist/server/runtime/http-server/daemon-admin/providers-handler.d.ts +3 -0
  130. package/dist/server/runtime/http-server/daemon-admin/providers-handler.js +166 -0
  131. package/dist/server/runtime/http-server/daemon-admin/providers-handler.js.map +1 -0
  132. package/dist/server/runtime/http-server/daemon-admin/quota-handler.d.ts +3 -0
  133. package/dist/server/runtime/http-server/daemon-admin/quota-handler.js +109 -0
  134. package/dist/server/runtime/http-server/daemon-admin/quota-handler.js.map +1 -0
  135. package/dist/server/runtime/http-server/daemon-admin/status-handler.d.ts +3 -0
  136. package/dist/server/runtime/http-server/daemon-admin/status-handler.js +43 -0
  137. package/dist/server/runtime/http-server/daemon-admin/status-handler.js.map +1 -0
  138. package/dist/server/runtime/http-server/daemon-admin-routes.d.ts +19 -0
  139. package/dist/server/runtime/http-server/daemon-admin-routes.js +27 -0
  140. package/dist/server/runtime/http-server/daemon-admin-routes.js.map +1 -0
  141. package/dist/server/runtime/http-server/executor-provider.d.ts +1 -0
  142. package/dist/server/runtime/http-server/executor-provider.js +26 -0
  143. package/dist/server/runtime/http-server/executor-provider.js.map +1 -1
  144. package/dist/server/runtime/http-server/executor-response.d.ts +16 -0
  145. package/dist/server/runtime/http-server/executor-response.js +164 -0
  146. package/dist/server/runtime/http-server/executor-response.js.map +1 -0
  147. package/dist/server/runtime/http-server/index.d.ts +6 -0
  148. package/dist/server/runtime/http-server/index.js +121 -53
  149. package/dist/server/runtime/http-server/index.js.map +1 -1
  150. package/dist/server/runtime/http-server/request-executor.d.ts +3 -0
  151. package/dist/server/runtime/http-server/request-executor.js +73 -21
  152. package/dist/server/runtime/http-server/request-executor.js.map +1 -1
  153. package/dist/server/runtime/http-server/routes.d.ts +5 -0
  154. package/dist/server/runtime/http-server/routes.js +45 -1
  155. package/dist/server/runtime/http-server/routes.js.map +1 -1
  156. package/dist/server/runtime/http-server/types.d.ts +1 -0
  157. package/dist/server/utils/client-connection-state.d.ts +8 -0
  158. package/dist/server/utils/client-connection-state.js +52 -0
  159. package/dist/server/utils/client-connection-state.js.map +1 -0
  160. package/dist/server/utils/request-id-manager.js +21 -3
  161. package/dist/server/utils/request-id-manager.js.map +1 -1
  162. package/dist/token-daemon/history-store.d.ts +2 -0
  163. package/dist/token-daemon/history-store.js +6 -2
  164. package/dist/token-daemon/history-store.js.map +1 -1
  165. package/dist/token-daemon/index.js +36 -5
  166. package/dist/token-daemon/index.js.map +1 -1
  167. package/dist/token-daemon/leader-lock.d.ts +11 -0
  168. package/dist/token-daemon/leader-lock.js +79 -0
  169. package/dist/token-daemon/leader-lock.js.map +1 -0
  170. package/dist/token-daemon/message-bus-integrator.d.ts +98 -0
  171. package/dist/token-daemon/message-bus-integrator.js +144 -0
  172. package/dist/token-daemon/message-bus-integrator.js.map +1 -0
  173. package/dist/token-daemon/provider-registry.d.ts +22 -0
  174. package/dist/token-daemon/provider-registry.js +201 -0
  175. package/dist/token-daemon/provider-registry.js.map +1 -0
  176. package/dist/token-daemon/token-daemon.d.ts +8 -0
  177. package/dist/token-daemon/token-daemon.js +196 -11
  178. package/dist/token-daemon/token-daemon.js.map +1 -1
  179. package/dist/token-portal/local-token-portal.d.ts +1 -0
  180. package/dist/token-portal/local-token-portal.js +18 -0
  181. package/dist/token-portal/local-token-portal.js.map +1 -1
  182. package/dist/token-portal/render.js +1 -0
  183. package/dist/token-portal/render.js.map +1 -1
  184. package/dist/tools/error-log.d.ts +31 -0
  185. package/dist/tools/error-log.js +117 -0
  186. package/dist/tools/error-log.js.map +1 -0
  187. package/dist/tools/stats-request-events.d.ts +2 -0
  188. package/dist/tools/stats-request-events.js +16 -0
  189. package/dist/tools/stats-request-events.js.map +1 -0
  190. package/dist/tools/stats-usage.d.ts +31 -0
  191. package/dist/tools/stats-usage.js +206 -0
  192. package/dist/tools/stats-usage.js.map +1 -0
  193. package/package.json +9 -4
  194. package/scripts/analyze-codex-error-failures.mjs +111 -0
  195. package/scripts/analyze-usage-estimate.mjs +240 -0
  196. package/scripts/camoufox/gen-fingerprint-env.py +171 -0
  197. package/scripts/camoufox/launch-auth.mjs +617 -0
  198. package/scripts/classify-codex-samples.mjs +251 -0
  199. package/scripts/cleanup-codex-error-samples.mjs +88 -0
  200. package/scripts/compare-codex-rccx.mjs +268 -0
  201. package/scripts/copy-compat-assets.mjs +18 -0
  202. package/scripts/install-release.sh +1 -1
  203. package/scripts/local-replay-openai-response.mjs +1 -2
  204. package/scripts/pack-mode.mjs +16 -6
  205. package/scripts/replay-codex-sample.mjs +24 -2
  206. package/scripts/responses-compare-server.mjs +119 -0
  207. package/scripts/tests/apply-patch-loop.mjs +266 -7
  208. package/scripts/tests/exec-command-loop.mjs +165 -0
  209. package/scripts/tool-classification-report.ts +281 -0
  210. package/scripts/verification/samples/openai-chat-list-local-files.json +1 -1
  211. package/scripts/verify-apply-patch.mjs +28 -17
  212. package/scripts/verify-codex-error-samples.mjs +102 -0
  213. package/scripts/verify-e2e-toolcall.mjs +71 -4
  214. package/scripts/virtual-router-shadow-v2-real.mjs +143 -0
  215. package/scripts/virtual-router-shadow-v2.mjs +122 -0
@@ -0,0 +1,143 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Virtual Router v1/v2 shadow comparison against real user config.
5
+ *
6
+ * - 读取当前用户配置(~/.routecodex/config.json 或 env 指定路径);
7
+ * - 使用 buildVirtualRouterInputFromUserConfig 生成 v1 视图;
8
+ * - 使用 buildVirtualRouterInputV2 生成 v2 视图(从 ~/.routecodex/provider 加载 provider v2);
9
+ * - 对比 providers / routing 结构并打印差异摘要。
10
+ *
11
+ * 依赖前提:dist/ 已通过 `npm run build` 或等价 tsc 编译生成。
12
+ */
13
+
14
+ import fs from 'node:fs/promises';
15
+ import os from 'node:os';
16
+ import path from 'node:path';
17
+ import { fileURLToPath } from 'node:url';
18
+
19
+ async function resolveConfigPath() {
20
+ const explicit = process.env.ROUTECODEX_CONFIG || process.env.RCC_CONFIG;
21
+ if (explicit && explicit.trim()) {
22
+ return path.resolve(explicit.trim());
23
+ }
24
+ return path.join(os.homedir(), '.routecodex', 'config.json');
25
+ }
26
+
27
+ async function loadUserConfig() {
28
+ const configPath = await resolveConfigPath();
29
+ const raw = await fs.readFile(configPath, 'utf8');
30
+ const parsed = raw.trim() ? JSON.parse(raw) : {};
31
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
32
+ return {};
33
+ }
34
+ return parsed;
35
+ }
36
+
37
+ function normalizeKeys(obj) {
38
+ if (!obj || typeof obj !== 'object' || Array.isArray(obj)) return {};
39
+ return Object.fromEntries(Object.entries(obj).filter(([k]) => typeof k === 'string'));
40
+ }
41
+
42
+ function diffKeys(a, b) {
43
+ const aKeys = new Set(Object.keys(a));
44
+ const bKeys = new Set(Object.keys(b));
45
+ const onlyA = [...aKeys].filter((k) => !bKeys.has(k));
46
+ const onlyB = [...bKeys].filter((k) => !aKeys.has(k));
47
+ return { onlyA, onlyB };
48
+ }
49
+
50
+ async function main() {
51
+ const __filename = fileURLToPath(import.meta.url);
52
+ const __dirname = path.dirname(__filename);
53
+
54
+ let buildVirtualRouterInputFromUserConfig;
55
+ let buildVirtualRouterInputV2;
56
+ try {
57
+ ({ buildVirtualRouterInputFromUserConfig } = await import(
58
+ path.join(__dirname, '../dist/config/virtual-router-types.js')
59
+ ));
60
+ ({ buildVirtualRouterInputV2 } = await import(
61
+ path.join(__dirname, '../dist/config/virtual-router-builder.js')
62
+ ));
63
+ } catch (error) {
64
+ // eslint-disable-next-line no-console
65
+ console.error(
66
+ '[virtual-router-shadow-v2-real] Failed to load dist modules. Please run `npm run build` or tsc first.',
67
+ error instanceof Error ? error.message : String(error)
68
+ );
69
+ process.exitCode = 1;
70
+ return;
71
+ }
72
+
73
+ let userConfig;
74
+ try {
75
+ userConfig = await loadUserConfig();
76
+ } catch (error) {
77
+ // eslint-disable-next-line no-console
78
+ console.error(
79
+ '[virtual-router-shadow-v2-real] Failed to load user config:',
80
+ error instanceof Error ? error.message : String(error)
81
+ );
82
+ process.exitCode = 1;
83
+ return;
84
+ }
85
+
86
+ const v1Input = buildVirtualRouterInputFromUserConfig(userConfig);
87
+ const v2Input = await buildVirtualRouterInputV2(userConfig);
88
+
89
+ const v1Providers = normalizeKeys(v1Input.providers || {});
90
+ const v2Providers = normalizeKeys(v2Input.providers || {});
91
+
92
+ // eslint-disable-next-line no-console
93
+ console.log('[virtual-router-shadow-v2-real] v1 provider keys:', Object.keys(v1Providers));
94
+ // eslint-disable-next-line no-console
95
+ console.log('[virtual-router-shadow-v2-real] v2 provider keys:', Object.keys(v2Providers));
96
+
97
+ const providerKeyDiff = diffKeys(v1Providers, v2Providers);
98
+ const providersEqual =
99
+ providerKeyDiff.onlyA.length === 0 && providerKeyDiff.onlyB.length === 0;
100
+
101
+ // eslint-disable-next-line no-console
102
+ console.log('[virtual-router-shadow-v2-real] providers key diff:', providerKeyDiff);
103
+
104
+ let providerPayloadEqual = providersEqual;
105
+ if (providersEqual) {
106
+ for (const key of Object.keys(v1Providers)) {
107
+ const a = v1Providers[key];
108
+ const b = v2Providers[key];
109
+ if (JSON.stringify(a) !== JSON.stringify(b)) {
110
+ providerPayloadEqual = false;
111
+ // eslint-disable-next-line no-console
112
+ console.log(
113
+ `[virtual-router-shadow-v2-real] provider payload mismatch for "${key}" (showing v1/v2 JSON):`
114
+ );
115
+ // eslint-disable-next-line no-console
116
+ console.log('v1:', JSON.stringify(a, null, 2));
117
+ // eslint-disable-next-line no-console
118
+ console.log('v2:', JSON.stringify(b, null, 2));
119
+ break;
120
+ }
121
+ }
122
+ }
123
+
124
+ const routingEqual = JSON.stringify(v1Input.routing || {}) === JSON.stringify(v2Input.routing || {});
125
+
126
+ // eslint-disable-next-line no-console
127
+ console.log('[virtual-router-shadow-v2-real] providers keys equal:', providersEqual);
128
+ // eslint-disable-next-line no-console
129
+ console.log('[virtual-router-shadow-v2-real] providers payload equal:', providerPayloadEqual);
130
+ // eslint-disable-next-line no-console
131
+ console.log('[virtual-router-shadow-v2-real] routing equal:', routingEqual);
132
+
133
+ if (!providersEqual || !providerPayloadEqual || !routingEqual) {
134
+ process.exitCode = 1;
135
+ }
136
+ }
137
+
138
+ main().catch((error) => {
139
+ // eslint-disable-next-line no-console
140
+ console.error('[virtual-router-shadow-v2-real] failed:', error);
141
+ process.exit(1);
142
+ });
143
+
@@ -0,0 +1,122 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Virtual Router v1/v2 shadow comparison script.
5
+ *
6
+ * 构造一个简化的 userConfig + 临时 provider-root:
7
+ * - 使用 buildVirtualRouterInputFromUserConfig 生成 v1 视图;
8
+ * - 使用 buildVirtualRouterInputV2 生成 v2 视图;
9
+ * 然后比较 providers / routing 结构是否一致。
10
+ *
11
+ * 依赖前提:dist/ 已通过 `npm run build` 生成。
12
+ */
13
+
14
+ import fs from 'node:fs/promises';
15
+ import os from 'node:os';
16
+ import path from 'node:path';
17
+ import { fileURLToPath } from 'node:url';
18
+
19
+ async function main() {
20
+ const __filename = fileURLToPath(import.meta.url);
21
+ const __dirname = path.dirname(__filename);
22
+
23
+ // 尝试从 dist 导入构建函数
24
+ let buildVirtualRouterInputFromUserConfig;
25
+ let buildVirtualRouterInputV2;
26
+ try {
27
+ // eslint-disable-next-line import/no-dynamic-require
28
+ ({ buildVirtualRouterInputFromUserConfig } = await import(
29
+ path.join(__dirname, '../dist/config/virtual-router-types.js')
30
+ ));
31
+ // eslint-disable-next-line import/no-dynamic-require
32
+ ({ buildVirtualRouterInputV2 } = await import(
33
+ path.join(__dirname, '../dist/config/virtual-router-builder.js')
34
+ ));
35
+ } catch (error) {
36
+ // eslint-disable-next-line no-console
37
+ console.error(
38
+ '[virtual-router-shadow-v2] Failed to load dist modules. Please run `npm run build` first.',
39
+ error instanceof Error ? error.message : String(error)
40
+ );
41
+ process.exitCode = 1;
42
+ return;
43
+ }
44
+
45
+ // 构造简化 userConfig(v1 风格:virtualrouter.providers + routing)
46
+ const userConfig = {
47
+ virtualrouter: {
48
+ providers: {
49
+ demo: {
50
+ type: 'mock-provider',
51
+ baseURL: 'https://demo.example.com',
52
+ models: {
53
+ 'mock-1': { maxTokens: 1024 }
54
+ }
55
+ }
56
+ },
57
+ routing: {
58
+ default: [
59
+ {
60
+ id: 'primary',
61
+ targets: ['demo.mock-1']
62
+ }
63
+ ]
64
+ }
65
+ }
66
+ };
67
+
68
+ // 构造临时 provider-root,并写入 v2 风格配置
69
+ const tempRoot = await fs.mkdtemp(path.join(os.tmpdir(), 'vr-shadow-v2-'));
70
+ const providerDir = path.join(tempRoot, 'demo');
71
+ await fs.mkdir(providerDir, { recursive: true });
72
+ const v2Payload = {
73
+ version: '2.0.0',
74
+ providerId: 'demo',
75
+ provider: userConfig.virtualrouter.providers.demo
76
+ };
77
+ await fs.writeFile(
78
+ path.join(providerDir, 'config.v2.json'),
79
+ `${JSON.stringify(v2Payload, null, 2)}\n`,
80
+ 'utf8'
81
+ );
82
+
83
+ // 构建 v1/v2 视图
84
+ const v1Input = buildVirtualRouterInputFromUserConfig(userConfig);
85
+ const v2Input = await buildVirtualRouterInputV2(userConfig, tempRoot);
86
+
87
+ // 比较 providers
88
+ const v1Providers = Object.keys(v1Input.providers || {});
89
+ const v2Providers = Object.keys(v2Input.providers || {});
90
+
91
+ // eslint-disable-next-line no-console
92
+ console.log('[virtual-router-shadow-v2] v1 providers:', v1Providers);
93
+ // eslint-disable-next-line no-console
94
+ console.log('[virtual-router-shadow-v2] v2 providers:', v2Providers);
95
+
96
+ const providersEqual =
97
+ v1Providers.length === v2Providers.length &&
98
+ v1Providers.every((id) => v2Providers.includes(id)) &&
99
+ v1Providers.every((id) => {
100
+ const v1 = v1Input.providers[id];
101
+ const v2 = v2Input.providers[id];
102
+ return JSON.stringify(v1) === JSON.stringify(v2);
103
+ });
104
+
105
+ // 比较 routing
106
+ const routingEqual = JSON.stringify(v1Input.routing) === JSON.stringify(v2Input.routing);
107
+
108
+ // eslint-disable-next-line no-console
109
+ console.log('[virtual-router-shadow-v2] providers equal:', providersEqual);
110
+ // eslint-disable-next-line no-console
111
+ console.log('[virtual-router-shadow-v2] routing equal:', routingEqual);
112
+
113
+ if (!providersEqual || !routingEqual) {
114
+ process.exitCode = 1;
115
+ }
116
+ }
117
+
118
+ main().catch((error) => {
119
+ // eslint-disable-next-line no-console
120
+ console.error('[virtual-router-shadow-v2] failed:', error);
121
+ process.exit(1);
122
+ });