@jsonstudio/rcc 0.90.323 → 0.90.352

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 (258) hide show
  1. package/README.md +16 -16
  2. package/dist/build-info.js +2 -2
  3. package/dist/cli/commands/camoufox.js +2 -2
  4. package/dist/cli/commands/camoufox.js.map +1 -1
  5. package/dist/cli/commands/clean.js +4 -3
  6. package/dist/cli/commands/clean.js.map +1 -1
  7. package/dist/cli/commands/config.js +2 -1
  8. package/dist/cli/commands/config.js.map +1 -1
  9. package/dist/cli/commands/env.js +2 -1
  10. package/dist/cli/commands/env.js.map +1 -1
  11. package/dist/cli/commands/init/basic.js +2 -1
  12. package/dist/cli/commands/init/basic.js.map +1 -1
  13. package/dist/cli/commands/init.js +4 -3
  14. package/dist/cli/commands/init.js.map +1 -1
  15. package/dist/cli/commands/launcher-kernel.js +23 -13
  16. package/dist/cli/commands/launcher-kernel.js.map +1 -1
  17. package/dist/cli/commands/port.js +1 -1
  18. package/dist/cli/commands/port.js.map +1 -1
  19. package/dist/cli/commands/restart.js +3 -2
  20. package/dist/cli/commands/restart.js.map +1 -1
  21. package/dist/cli/commands/start.js +4 -3
  22. package/dist/cli/commands/start.js.map +1 -1
  23. package/dist/cli/commands/stop.js +3 -2
  24. package/dist/cli/commands/stop.js.map +1 -1
  25. package/dist/cli/config/bundled-docs.js +2 -6
  26. package/dist/cli/config/bundled-docs.js.map +1 -1
  27. package/dist/cli/config/init-config.d.ts +1 -0
  28. package/dist/cli/config/init-config.js +6 -3
  29. package/dist/cli/config/init-config.js.map +1 -1
  30. package/dist/cli/config/init-provider-catalog.js +4 -4
  31. package/dist/cli/config/init-provider-catalog.js.map +1 -1
  32. package/dist/cli/config/precommand-default-script.js +3 -9
  33. package/dist/cli/config/precommand-default-script.js.map +1 -1
  34. package/dist/cli/guardian/paths.js +2 -3
  35. package/dist/cli/guardian/paths.js.map +1 -1
  36. package/dist/cli.js +10 -2
  37. package/dist/cli.js.map +1 -1
  38. package/dist/commands/camoufox-fp.js +2 -3
  39. package/dist/commands/camoufox-fp.js.map +1 -1
  40. package/dist/commands/migrate-user-config.d.ts +6 -0
  41. package/dist/commands/migrate-user-config.js +53 -0
  42. package/dist/commands/migrate-user-config.js.map +1 -0
  43. package/dist/commands/provider-update.js +9 -9
  44. package/dist/commands/provider-update.js.map +1 -1
  45. package/dist/commands/quota-daemon.js +3 -3
  46. package/dist/commands/quota-daemon.js.map +1 -1
  47. package/dist/commands/quota-status.js +2 -2
  48. package/dist/commands/quota-status.js.map +1 -1
  49. package/dist/commands/token-daemon.js +2 -2
  50. package/dist/commands/token-daemon.js.map +1 -1
  51. package/dist/commands/validate.js +2 -3
  52. package/dist/commands/validate.js.map +1 -1
  53. package/dist/config/auth-file-resolver.js +2 -2
  54. package/dist/config/auth-file-resolver.js.map +1 -1
  55. package/dist/config/provider-v2-loader.js +9 -6
  56. package/dist/config/provider-v2-loader.js.map +1 -1
  57. package/dist/config/routecodex-config-loader.js +2 -2
  58. package/dist/config/routecodex-config-loader.js.map +1 -1
  59. package/dist/config/unified-config-paths.js +11 -9
  60. package/dist/config/unified-config-paths.js.map +1 -1
  61. package/dist/config/user-config-migration.d.ts +42 -0
  62. package/dist/config/user-config-migration.js +188 -0
  63. package/dist/config/user-config-migration.js.map +1 -0
  64. package/dist/config/user-data-paths.d.ts +59 -0
  65. package/dist/config/user-data-paths.js +174 -0
  66. package/dist/config/user-data-paths.js.map +1 -0
  67. package/dist/config/virtual-router-builder.d.ts +1 -1
  68. package/dist/config/virtual-router-builder.js +1 -1
  69. package/dist/docs/daemon-admin-ui.html +9 -9
  70. package/dist/index.js +7 -5
  71. package/dist/index.js.map +1 -1
  72. package/dist/manager/modules/health/index.js +2 -2
  73. package/dist/manager/modules/health/index.js.map +1 -1
  74. package/dist/manager/modules/quota/antigravity-quota-persistence.d.ts +2 -1
  75. package/dist/manager/modules/quota/antigravity-quota-persistence.js +11 -22
  76. package/dist/manager/modules/quota/antigravity-quota-persistence.js.map +1 -1
  77. package/dist/manager/quota/provider-quota-store.js +11 -4
  78. package/dist/manager/quota/provider-quota-store.js.map +1 -1
  79. package/dist/modules/config/pipeline-config-path.js +3 -3
  80. package/dist/modules/config/pipeline-config-path.js.map +1 -1
  81. package/dist/providers/auth/antigravity-fingerprint.js +2 -3
  82. package/dist/providers/auth/antigravity-fingerprint.js.map +1 -1
  83. package/dist/providers/auth/antigravity-reauth-state.js +2 -3
  84. package/dist/providers/auth/antigravity-reauth-state.js.map +1 -1
  85. package/dist/providers/auth/antigravity-user-agent.js +2 -2
  86. package/dist/providers/auth/antigravity-user-agent.js.map +1 -1
  87. package/dist/providers/auth/antigravity-warmup.js +2 -3
  88. package/dist/providers/auth/antigravity-warmup.js.map +1 -1
  89. package/dist/providers/auth/deepseek-account-auth.js +4 -3
  90. package/dist/providers/auth/deepseek-account-auth.js.map +1 -1
  91. package/dist/providers/auth/deepseek-account-token-acquirer.js +3 -2
  92. package/dist/providers/auth/deepseek-account-token-acquirer.js.map +1 -1
  93. package/dist/providers/auth/oauth-auth.js +2 -3
  94. package/dist/providers/auth/oauth-auth.js.map +1 -1
  95. package/dist/providers/auth/oauth-lifecycle/path-resolver.js +6 -7
  96. package/dist/providers/auth/oauth-lifecycle/path-resolver.js.map +1 -1
  97. package/dist/providers/auth/oauth-lifecycle.js +4 -4
  98. package/dist/providers/auth/oauth-lifecycle.js.map +1 -1
  99. package/dist/providers/auth/oauth-repair-cooldown.js +2 -3
  100. package/dist/providers/auth/oauth-repair-cooldown.js.map +1 -1
  101. package/dist/providers/auth/token-scanner/index.js +2 -3
  102. package/dist/providers/auth/token-scanner/index.js.map +1 -1
  103. package/dist/providers/auth/token-storage/token-file-resolver.js +8 -7
  104. package/dist/providers/auth/token-storage/token-file-resolver.js.map +1 -1
  105. package/dist/providers/auth/tokenfile-auth.js +5 -6
  106. package/dist/providers/auth/tokenfile-auth.js.map +1 -1
  107. package/dist/providers/core/config/camoufox-launcher.js +3 -4
  108. package/dist/providers/core/config/camoufox-launcher.js.map +1 -1
  109. package/dist/providers/core/config/provider-oauth-configs.js +2 -2
  110. package/dist/providers/core/config/provider-oauth-configs.js.map +1 -1
  111. package/dist/providers/core/hooks/hooks-integration.js +1 -1
  112. package/dist/providers/core/hooks/hooks-integration.js.map +1 -1
  113. package/dist/providers/core/runtime/deepseek-http-provider.js +2 -1
  114. package/dist/providers/core/runtime/deepseek-http-provider.js.map +1 -1
  115. package/dist/providers/core/utils/snapshot-writer.js +2 -1
  116. package/dist/providers/core/utils/snapshot-writer.js.map +1 -1
  117. package/dist/server/handlers/config-admin-handler.d.ts +1 -1
  118. package/dist/server/handlers/config-admin-handler.js +6 -6
  119. package/dist/server/handlers/config-admin-handler.js.map +1 -1
  120. package/dist/server/runtime/http-server/daemon-admin/auth-store.js +2 -2
  121. package/dist/server/runtime/http-server/daemon-admin/auth-store.js.map +1 -1
  122. package/dist/server/runtime/http-server/daemon-admin/control-handler.js +3 -3
  123. package/dist/server/runtime/http-server/daemon-admin/control-handler.js.map +1 -1
  124. package/dist/server/runtime/http-server/daemon-admin/credentials-handler.js +2 -2
  125. package/dist/server/runtime/http-server/daemon-admin/credentials-handler.js.map +1 -1
  126. package/dist/server/runtime/http-server/daemon-admin/providers-handler-routing-utils.js +5 -4
  127. package/dist/server/runtime/http-server/daemon-admin/providers-handler-routing-utils.js.map +1 -1
  128. package/dist/server/runtime/http-server/daemon-admin/providers-handler.js +3 -3
  129. package/dist/server/runtime/http-server/daemon-admin/providers-handler.js.map +1 -1
  130. package/dist/server/runtime/http-server/http-server-bootstrap.js +2 -3
  131. package/dist/server/runtime/http-server/http-server-bootstrap.js.map +1 -1
  132. package/dist/server/runtime/http-server/request-executor.js +0 -49
  133. package/dist/server/runtime/http-server/request-executor.js.map +1 -1
  134. package/dist/server/runtime/http-server/routes.js +1 -1
  135. package/dist/server/runtime/http-server/routes.js.map +1 -1
  136. package/dist/server/runtime/http-server/servertool-admin-state.js +2 -2
  137. package/dist/server/runtime/http-server/servertool-admin-state.js.map +1 -1
  138. package/dist/server/runtime/http-server/session-dir.js +6 -12
  139. package/dist/server/runtime/http-server/session-dir.js.map +1 -1
  140. package/dist/server/runtime/http-server/stats-manager.js +2 -1
  141. package/dist/server/runtime/http-server/stats-manager.js.map +1 -1
  142. package/dist/server/utils/non-blocking-error-logger.js +2 -1
  143. package/dist/server/utils/non-blocking-error-logger.js.map +1 -1
  144. package/dist/token-daemon/history-store.js +2 -1
  145. package/dist/token-daemon/history-store.js.map +1 -1
  146. package/dist/token-daemon/leader-lock.js +2 -2
  147. package/dist/token-daemon/leader-lock.js.map +1 -1
  148. package/dist/token-daemon/quota-auth-issue.js +2 -4
  149. package/dist/token-daemon/quota-auth-issue.js.map +1 -1
  150. package/dist/token-daemon/server-utils.js +3 -4
  151. package/dist/token-daemon/server-utils.js.map +1 -1
  152. package/dist/token-daemon/token-daemon.js +6 -6
  153. package/dist/token-daemon/token-daemon.js.map +1 -1
  154. package/dist/token-daemon/token-utils.js +2 -1
  155. package/dist/token-daemon/token-utils.js.map +1 -1
  156. package/dist/token-portal/fingerprint-summary.js +2 -3
  157. package/dist/token-portal/fingerprint-summary.js.map +1 -1
  158. package/dist/token-portal/local-token-portal.js +1 -1
  159. package/dist/token-portal/local-token-portal.js.map +1 -1
  160. package/dist/utils/daemon-stop-intent.js +2 -2
  161. package/dist/utils/daemon-stop-intent.js.map +1 -1
  162. package/dist/utils/errorsamples.js +3 -1
  163. package/dist/utils/errorsamples.js.map +1 -1
  164. package/dist/utils/llms-engine-shadow.js +2 -2
  165. package/dist/utils/llms-engine-shadow.js.map +1 -1
  166. package/dist/utils/managed-server-pids.js +2 -2
  167. package/dist/utils/managed-server-pids.js.map +1 -1
  168. package/dist/utils/process-lifecycle-logger.js +2 -1
  169. package/dist/utils/process-lifecycle-logger.js.map +1 -1
  170. package/dist/utils/runtime-exit-forensics.js +2 -2
  171. package/dist/utils/runtime-exit-forensics.js.map +1 -1
  172. package/dist/utils/snapshot-writer.js +2 -1
  173. package/dist/utils/snapshot-writer.js.map +1 -1
  174. package/docs/CODEX_AND_CLAUDE_CODE.md +1 -1
  175. package/docs/CONFIG_ARCHITECTURE.md +7 -7
  176. package/docs/DAEMON_CONTROL_PLANE.md +2 -2
  177. package/docs/INSTALLATION_AND_QUICKSTART.md +2 -2
  178. package/docs/INSTRUCTION_MARKUP.md +2 -2
  179. package/docs/OAUTH.md +6 -6
  180. package/docs/PORTS.md +1 -1
  181. package/docs/PROVIDERS_BUILTIN.md +2 -2
  182. package/docs/QUOTA_MANAGER_V3.md +2 -2
  183. package/docs/ROUTING_POLICY_SCHEMA.md +1 -1
  184. package/docs/SERVERTOOL_CLOCK_DESIGN.md +1 -1
  185. package/docs/SERVERTOOL_PRE_COMMAND_HOOKS.md +4 -4
  186. package/docs/anthropic-request-golden-samples.md +4 -4
  187. package/docs/chat-glm-500-analysis.md +2 -2
  188. package/docs/chat-request-golden-samples.md +4 -4
  189. package/docs/codex-samples-replay.md +3 -3
  190. package/docs/daemon-admin-api-design.md +2 -2
  191. package/docs/daemon-admin-ui.html +9 -9
  192. package/docs/design/servertool-stopmessage-lifecycle.md +5 -0
  193. package/docs/golden-ci-library.md +8 -8
  194. package/docs/monitoring/Design.md +2 -2
  195. package/docs/multi-token-auth-guide.md +6 -6
  196. package/docs/oauth-authentication-guide.md +1 -1
  197. package/docs/oauth-iflow-implementation.md +2 -2
  198. package/docs/pipeline-routing-report.md +1 -1
  199. package/docs/plans/manager-daemon/PLAN.md +1 -1
  200. package/docs/plans/provider-config-v2-plan.md +8 -8
  201. package/docs/plans/provider-runtime-manager-plan.md +4 -4
  202. package/docs/provider-analysis.md +5 -5
  203. package/docs/provider-quota-design.md +2 -2
  204. package/docs/providers/antigravity-fingerprint-ua-warmup.md +5 -5
  205. package/docs/providers/antigravity-gemini-provider-compat.md +3 -3
  206. package/docs/providers/deepseek-web-provider-design.md +1 -1
  207. package/docs/providers/gemini-provider.md +1 -1
  208. package/docs/providers/provider-composite-testing.md +2 -2
  209. package/docs/providers/tabglm-claude-code-compat.md +1 -1
  210. package/docs/replay-evidence-iflow-400.txt +3 -3
  211. package/docs/reports/routing-classification-report.json +6 -6
  212. package/docs/reports/routing-classification-report.md +6 -6
  213. package/docs/reports/thinking-keywords-report.json +6 -6
  214. package/docs/responses/README.md +5 -5
  215. package/docs/responses-generic-provider.md +1 -1
  216. package/docs/responses-passthrough-provider-design.md +7 -7
  217. package/docs/routing-instructions.md +1 -1
  218. package/docs/token-daemon-preview.html +3 -3
  219. package/docs/token-refresh-daemon-plan.md +7 -7
  220. package/docs/verification/modelscope-verify.md +2 -2
  221. package/docs/verified-configs/README.md +2 -2
  222. package/docs/verified-configs/v0.45.0/README.md +5 -5
  223. package/docs/verified-configs/v0.45.0/merged-config.5521.json +3 -3
  224. package/docs/verified-configs/v0.45.0/merged-config.qwen-5522.json +3 -3
  225. package/package.json +2 -2
  226. package/scripts/anthropic-four-config-e2e.mjs +5 -5
  227. package/scripts/anthropic-toolcall.mjs +1 -1
  228. package/scripts/batch-toolcall-report.mjs +1 -1
  229. package/scripts/claude-e2e-listdir-all.sh +1 -1
  230. package/scripts/claude-e2e-listdir-per-config.sh +4 -4
  231. package/scripts/clean-safe.mjs +1 -1
  232. package/scripts/cleanup-beads-oversized-notes.mjs +182 -0
  233. package/scripts/config-core-compare.ts +1 -1
  234. package/scripts/glm1210-curl-test.sh +1 -1
  235. package/scripts/install-release.sh +1 -1
  236. package/scripts/mock-provider/capture-from-configs.mjs +1 -1
  237. package/scripts/outbound-network-toolcall.mjs +2 -2
  238. package/scripts/outbound-regression-codex-samples.mjs +1 -1
  239. package/scripts/provider-v2-smoke.mjs +3 -3
  240. package/scripts/replay-recorded-toolcall.mjs +1 -2
  241. package/scripts/responses-fai-capture.mjs +1 -1
  242. package/scripts/responses-sse-capture.mjs +1 -1
  243. package/scripts/responses-sse-proxy.mjs +1 -1
  244. package/scripts/responses-sse-replay-golden.mjs +252 -111
  245. package/scripts/run-bg.sh +1 -1
  246. package/scripts/run-fg-gtimeout.sh +1 -1
  247. package/scripts/tests/antigravity-codex-sample-pipeline-compare.mjs +1 -1
  248. package/scripts/tests/antigravity-gemini-dryrun-compare.mjs +1 -1
  249. package/scripts/tests/responses-provider-dry-run.mjs +1 -1
  250. package/scripts/tests/virtual-router-health.mjs +1 -1
  251. package/scripts/update-models.mjs +2 -2
  252. package/scripts/v2-simple-monitor.mjs +1 -1
  253. package/scripts/verify-e2e-gemini-followup-sample.mjs +1 -1
  254. package/scripts/verify-e2e-toolcall.mjs +2 -2
  255. package/scripts/verify-health.mjs +2 -2
  256. package/scripts/verify-sse-loop.mjs +1 -1
  257. package/scripts/virtual-router-dryrun.mjs +2 -2
  258. package/scripts/virtual-router-shadow-v2-real.mjs +3 -3
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  // One-click outbound network toolcall tests against openai-compatible providers.
3
- // Reads provider configs under ~/.routecodex/provider/*/config*.json
3
+ // Reads provider configs under ~/.rcc/provider/*/config*.json
4
4
  // Sends a function-calling prompt and reports whether a functionCall/tool_calls is returned.
5
5
 
6
6
  import fs from 'fs';
@@ -8,7 +8,7 @@ import path from 'path';
8
8
  import os from 'os';
9
9
  import { ProviderFactory } from '../dist/providers/core/runtime/provider-factory.js';
10
10
 
11
- const root = path.join(os.homedir(), '.routecodex', 'provider');
11
+ const root = path.join(os.homedir(), '.rcc', 'provider');
12
12
  const MAX_PROVIDERS = parseInt(process.env.RCC_NET_MAX_PROVIDERS || '5', 10);
13
13
  // Per-provider rate limit: default 3 req/min (can override by RCC_NET_RATE_MAX_PER_MINUTE)
14
14
  const RATE_MAX_PER_MIN = parseInt(process.env.RCC_NET_RATE_MAX_PER_MINUTE || '3', 10);
@@ -12,7 +12,7 @@ import { ProviderFactory } from '../dist/providers/core/runtime/provider-factory
12
12
  const CODEx_DIR = path.join(os.homedir(), '.routecodex', 'codex-samples', 'openai-chat');
13
13
  const RESPONSES_SAMPLE_DIR = path.join(os.homedir(), '.routecodex', 'codex-samples', 'openai-responses');
14
14
  const TARGET_TOOL_NAME = (process.env.RCC_REG_TOOL_NAME || 'add').toLowerCase();
15
- const PROVIDER_DIR = path.join(os.homedir(), '.routecodex', 'provider');
15
+ const PROVIDER_DIR = path.join(os.homedir(), '.rcc', 'provider');
16
16
  const MAX_PER_PROVIDER_PER_MIN = parseInt(process.env.RCC_NET_RATE_MAX_PER_MINUTE || '3', 10);
17
17
  const RATE_DISABLED = (process.env.RCC_NET_RATE_DISABLED || '0') === '1';
18
18
  const TARGET_PROTOCOLS = new Set(
@@ -6,10 +6,10 @@ import path from 'path';
6
6
 
7
7
  function readJson(p){ try { return JSON.parse(fs.readFileSync(p,'utf-8')); } catch { return null; } }
8
8
  function loadUserConfig(){
9
- const explicit = process.env.ROUTECODEX_CONFIG_PATH;
9
+ const explicit = process.env.ROUTECODEX_CONFIG_PATH || process.env.RCC_CONFIG_PATH || process.env.ROUTECODEX_CONFIG || process.env.RCC_CONFIG;
10
10
  const candidate = explicit && explicit.trim()
11
11
  ? path.resolve(explicit.trim())
12
- : path.join(os.homedir(), '.routecodex', 'config.json');
12
+ : path.join(os.homedir(), '.rcc', 'config.json');
13
13
  return readJson(candidate);
14
14
  }
15
15
 
@@ -18,7 +18,7 @@ const providers = cfg?.virtualrouter?.providers || {};
18
18
  const entries = Object.entries(providers);
19
19
  const glmEntry = entries.find(([id]) => id.includes('glm')) || entries[0];
20
20
  if (!glmEntry) {
21
- console.error('no provider definition found in ~/.routecodex/config.json');
21
+ console.error('no provider definition found in ~/.rcc/config.json');
22
22
  process.exit(2);
23
23
  }
24
24
  const [providerId, providerConfig] = glmEntry;
@@ -41,7 +41,7 @@ async function sleep(ms) { await new Promise(r => setTimeout(r, ms)); }
41
41
  async function getPortFromConfig() {
42
42
  try {
43
43
  const envPath = process.env.ROUTECODEX_CONFIG_PATH || process.env.ROUTECODEX_CONFIG || '';
44
- const candidate = envPath || path.join(os.homedir(), '.routecodex', 'config.json');
44
+ const candidate = envPath || path.join(os.homedir(), '.rcc', 'config.json');
45
45
  if (fsSync.existsSync(candidate)) {
46
46
  const cfg = await readJson(candidate);
47
47
  const p = (cfg && cfg.httpserver && typeof cfg.httpserver.port === 'number') ? cfg.httpserver.port : cfg.port;
@@ -227,4 +227,3 @@ async function main() {
227
227
  }
228
228
 
229
229
  main().catch(err => { console.error(err); process.exit(1); });
230
-
@@ -7,7 +7,7 @@ import path from 'path';
7
7
  import { pathToFileURL } from 'url';
8
8
 
9
9
  const PROVIDER_ID = process.env.RCC_RESP_PROV || 'fai';
10
- const PROVIDER_DIR = path.join(os.homedir(), '.routecodex', 'provider');
10
+ const PROVIDER_DIR = path.join(os.homedir(), '.rcc', 'provider');
11
11
  const OUT_DIR = path.join(os.homedir(), '.routecodex', 'golden_samples', 'provider_golden_samples', 'responses', PROVIDER_ID);
12
12
 
13
13
  function ensureDir(p) { fs.mkdirSync(p, { recursive: true }); }
@@ -10,7 +10,7 @@ import OpenAI from 'openai';
10
10
  const BASEDIR = process.cwd();
11
11
  const CODEx_DIR = path.join(os.homedir(), '.routecodex', 'codex-samples', 'openai-chat');
12
12
  const RESP_SAMPLE_DIR = path.join(os.homedir(), '.routecodex', 'codex-samples', 'openai-responses');
13
- const PROVIDER_DIR = path.join(os.homedir(), '.routecodex', 'provider');
13
+ const PROVIDER_DIR = path.join(os.homedir(), '.rcc', 'provider');
14
14
  const OUT_DIR = path.join(os.homedir(), '.routecodex', 'logs', 'responses-sse');
15
15
 
16
16
  function ensureDir(p) { fs.mkdirSync(p, { recursive: true }); }
@@ -17,7 +17,7 @@ const replayLog = process.env.RCC_RESP_REPLAY_LOG || getArg('--replay');
17
17
  const port = Number(getArg('--port') || DEFAULT_PORT);
18
18
  const host = getArg('--host') || DEFAULT_HOST;
19
19
 
20
- const PROVIDER_ROOT = path.join(os.homedir(), '.routecodex', 'provider');
20
+ const PROVIDER_ROOT = path.join(os.homedir(), '.rcc', 'provider');
21
21
  const CAPTURE_ROOT = path.join(os.homedir(), '.routecodex', 'codex-samples', 'openai-responses', 'sse-proxy');
22
22
 
23
23
  function getArg(flag) {
@@ -1,138 +1,279 @@
1
1
  #!/usr/bin/env node
2
- // Replay a Responses golden provider-request sample to a live provider and aggregate SSE → JSON → Chat.
3
- // Usage:
4
- // RCC_RESP_PROV=<providerId> node scripts/responses-sse-replay-golden.mjs
2
+ // Server-side replay for codex-samples /v1/responses requests.
3
+ // This script intentionally replays through RouteCodex HTTP server instead of calling provider URLs directly.
4
+ //
5
5
  // Env:
6
- // RCC_RESP_PROV: fc|c4m|fai (default fc)
7
- // RCC_RESP_PICK: substring to pick a specific sample file
6
+ // RCC_REPLAY_BASE server base URL (default http://127.0.0.1:5555)
7
+ // RCC_REPLAY_KEY x-routecodex-api-key (default routecodex-test)
8
+ // RCC_RESP_PROVIDER provider directory filter (optional)
9
+ // RCC_RESP_PICK request-id/path substring filter (optional)
10
+ // RCC_RESP_REQ exact request directory name, e.g. req_1773310208018_9b3ec605 (optional)
11
+ //
12
+ // Output:
13
+ // ~/.routecodex/logs/responses-sse/server-replay_<timestamp>.{request,response,sse,json,chat}.*
8
14
 
9
- import fs from 'fs';
10
- import os from 'os';
11
- import path from 'path';
12
- import { pathToFileURL } from 'url';
15
+ import fs from 'node:fs';
16
+ import os from 'node:os';
17
+ import path from 'node:path';
18
+ import { pathToFileURL } from 'node:url';
13
19
 
14
- const PROVIDER_DIR = path.join(os.homedir(), '.routecodex', 'provider');
15
- const SAMPLES_DIR = path.join(os.homedir(), '.routecodex', 'codex-samples', 'openai-responses');
20
+ const DEFAULT_BASE = process.env.RCC_REPLAY_BASE || 'http://127.0.0.1:5555';
21
+ const DEFAULT_KEY =
22
+ process.env.RCC_REPLAY_KEY ||
23
+ process.env.ROUTECODEX_HTTP_APIKEY ||
24
+ process.env.ROUTECODEX_API_KEY ||
25
+ 'routecodex-test';
26
+ const FILTER_PROVIDER = (process.env.RCC_RESP_PROVIDER || '').trim();
27
+ const FILTER_PICK = (process.env.RCC_RESP_PICK || '').trim();
28
+ const FILTER_REQ = (process.env.RCC_RESP_REQ || '').trim();
29
+ const SAMPLES_ROOT = path.join(os.homedir(), '.routecodex', 'codex-samples', 'openai-responses');
16
30
  const OUT_DIR = path.join(os.homedir(), '.routecodex', 'logs', 'responses-sse');
17
31
 
18
- function ensureDir(p) { fs.mkdirSync(p, { recursive: true }); }
19
- function nowStamp() { return new Date().toISOString().replace(/[:.]/g, '-'); }
32
+ function nowStamp() {
33
+ return new Date().toISOString().replace(/[:.]/g, '-');
34
+ }
35
+
36
+ function ensureDir(p) {
37
+ fs.mkdirSync(p, { recursive: true });
38
+ }
39
+
40
+ function readJson(p) {
41
+ return JSON.parse(fs.readFileSync(p, 'utf-8'));
42
+ }
43
+
44
+ async function healthCheck(baseUrl) {
45
+ try {
46
+ const res = await fetch(`${baseUrl.replace(/\/$/, '')}/health`, { method: 'GET' });
47
+ return res.ok;
48
+ } catch {
49
+ return false;
50
+ }
51
+ }
20
52
 
21
- function findProviderConfig(providerId) {
22
- const dir = path.join(PROVIDER_DIR, providerId);
23
- const candidates = ['config.v1.json', 'config.json'];
24
- for (const name of candidates) {
25
- const p = path.join(dir, name);
26
- if (fs.existsSync(p)) {
27
- return JSON.parse(fs.readFileSync(p, 'utf-8'));
53
+ function findClientRequestFiles(root) {
54
+ const result = [];
55
+ if (!fs.existsSync(root)) {
56
+ return result;
57
+ }
58
+ const providerDirs = fs.readdirSync(root, { withFileTypes: true }).filter((d) => d.isDirectory());
59
+ for (const providerDir of providerDirs) {
60
+ if (FILTER_PROVIDER && !providerDir.name.includes(FILTER_PROVIDER)) {
61
+ continue;
62
+ }
63
+ const providerPath = path.join(root, providerDir.name);
64
+ const reqDirs = fs.readdirSync(providerPath, { withFileTypes: true }).filter((d) => d.isDirectory());
65
+ for (const reqDir of reqDirs) {
66
+ if (FILTER_REQ && reqDir.name !== FILTER_REQ) {
67
+ continue;
68
+ }
69
+ if (FILTER_PICK && !reqDir.name.includes(FILTER_PICK) && !providerDir.name.includes(FILTER_PICK)) {
70
+ continue;
71
+ }
72
+ const clientReq = path.join(providerPath, reqDir.name, 'client-request.json');
73
+ if (!fs.existsSync(clientReq)) {
74
+ continue;
75
+ }
76
+ const stat = fs.statSync(clientReq);
77
+ result.push({
78
+ provider: providerDir.name,
79
+ requestId: reqDir.name,
80
+ file: clientReq,
81
+ mtimeMs: stat.mtimeMs
82
+ });
28
83
  }
29
84
  }
30
- throw new Error(`No provider config for ${providerId}`);
85
+ result.sort((a, b) => b.mtimeMs - a.mtimeMs);
86
+ return result;
31
87
  }
32
88
 
33
- function extractProviderEntry(doc, providerId) {
34
- const pipelines = doc?.pipeline_assembler?.config?.pipelines || [];
35
- for (const p of pipelines) {
36
- const prov = p?.modules?.provider;
37
- if (!prov?.config) continue;
38
- const pid = prov.config.providerId || path.basename(path.dirname(p?.__file || ''));
39
- if (pid === providerId) return prov.config;
40
- }
41
- // fallback v1
42
- const providers = doc?.virtualrouter?.providers || {};
43
- return Object.values(providers)[0] || null;
89
+ function extractRequestBody(doc) {
90
+ if (doc && typeof doc === 'object') {
91
+ if (doc.body && typeof doc.body === 'object' && !Array.isArray(doc.body)) {
92
+ if (doc.body.body && typeof doc.body.body === 'object' && !Array.isArray(doc.body.body)) {
93
+ return doc.body.body;
94
+ }
95
+ return doc.body;
96
+ }
97
+ if (doc.data && typeof doc.data === 'object' && !Array.isArray(doc.data)) {
98
+ const data = doc.data;
99
+ if (data.body && typeof data.body === 'object' && !Array.isArray(data.body)) {
100
+ if (data.body.body && typeof data.body.body === 'object' && !Array.isArray(data.body.body)) {
101
+ return data.body.body;
102
+ }
103
+ return data.body;
104
+ }
105
+ }
106
+ }
107
+ return undefined;
44
108
  }
45
109
 
46
- function listGoldenRequests() {
47
- if (!fs.existsSync(SAMPLES_DIR)) return [];
48
- return fs.readdirSync(SAMPLES_DIR).filter(n => n.endsWith('_provider-request.json'));
110
+ function extractEntryEndpoint(doc) {
111
+ const endpoint = doc?.meta?.entryEndpoint;
112
+ if (typeof endpoint === 'string' && endpoint.trim().length) {
113
+ return endpoint.trim();
114
+ }
115
+ return '/v1/responses';
49
116
  }
50
117
 
51
- function pickGoldenForBaseUrl(files, baseUrl, pickHint) {
52
- const want = String(baseUrl || '').replace(/\/$/, '');
53
- const host = want.split('://')[1] || want; // naive
54
- let matches = files.filter(f => {
55
- try {
56
- const obj = JSON.parse(fs.readFileSync(path.join(SAMPLES_DIR, f), 'utf-8'));
57
- const url = obj?.data?.url || obj?.url || '';
58
- return typeof url === 'string' && url.includes(host);
59
- } catch { return false; }
60
- });
61
- if (pickHint) matches = matches.filter(f => f.includes(pickHint));
62
- if (!matches.length) matches = files; // fallback to any
63
- // prefer ones containing input[] and tools
64
- matches.sort((a, b) => {
65
- const aa = fs.readFileSync(path.join(SAMPLES_DIR, a), "utf-8");
66
- const bb = fs.readFileSync(path.join(SAMPLES_DIR, b), "utf-8");
67
- const sa = (aa.includes("\"input\"") ? 10 : 0) + (aa.includes("\"tools\"") ? 2 : 0) + (aa.includes("function_call_arguments") ? 1 : 0);
68
- const sb = (bb.includes("\"input\"") ? 10 : 0) + (bb.includes("\"tools\"") ? 2 : 0) + (bb.includes("function_call_arguments") ? 1 : 0);
69
- return sb - sa;
70
- });
71
- return matches[0] || null;
118
+ function extractStreamFlag(doc, body) {
119
+ if (typeof body?.stream === 'boolean') {
120
+ return body.stream;
121
+ }
122
+ if (typeof doc?.meta?.stream === 'boolean') {
123
+ return doc.meta.stream;
124
+ }
125
+ return true;
126
+ }
127
+
128
+ async function readSseFrames(stream) {
129
+ const reader = stream?.getReader?.();
130
+ if (!reader) {
131
+ return [];
132
+ }
133
+ const decoder = new TextDecoder();
134
+ let buffer = '';
135
+ const frames = [];
136
+ while (true) {
137
+ const { value, done } = await reader.read();
138
+ if (done) {
139
+ break;
140
+ }
141
+ buffer += decoder.decode(value, { stream: true });
142
+ let idx = buffer.indexOf('\n\n');
143
+ while (idx >= 0) {
144
+ const frame = buffer.slice(0, idx).trim();
145
+ buffer = buffer.slice(idx + 2);
146
+ if (frame.length) {
147
+ frames.push(frame);
148
+ }
149
+ idx = buffer.indexOf('\n\n');
150
+ }
151
+ }
152
+ buffer += decoder.decode(new Uint8Array(), { stream: false });
153
+ if (buffer.trim().length) {
154
+ frames.push(buffer.trim());
155
+ }
156
+ return frames;
157
+ }
158
+
159
+ async function convertSseFramesToJson(frames, requestId, model) {
160
+ try {
161
+ const convPath = pathToFileURL(path.join(process.cwd(), 'sharedmodule/llmswitch-core/dist/sse/sse-to-json/index.js')).href;
162
+ const bridgePath = pathToFileURL(path.join(process.cwd(), 'sharedmodule/llmswitch-core/dist/conversion/responses/responses-openai-bridge.js')).href;
163
+ const { ResponsesSseToJsonConverter } = await import(convPath);
164
+ const { buildChatResponseFromResponses } = await import(bridgePath);
165
+ const converter = new ResponsesSseToJsonConverter();
166
+ async function* toChunks() {
167
+ for (const frame of frames) {
168
+ yield `${frame}\n\n`;
169
+ }
170
+ }
171
+ const json = await converter.convertSseToJson(toChunks(), {
172
+ requestId,
173
+ model: typeof model === 'string' && model.length ? model : 'unknown'
174
+ });
175
+ const chat = buildChatResponseFromResponses(json);
176
+ return { json, chat };
177
+ } catch {
178
+ return { json: null, chat: null };
179
+ }
72
180
  }
73
181
 
74
182
  async function main() {
75
- const providerId = process.env.RCC_RESP_PROV || 'fc';
76
- const pickHint = process.env.RCC_RESP_PICK || '';
77
- const cfgDoc = findProviderConfig(providerId);
78
- const prov = extractProviderEntry(cfgDoc, providerId);
79
- if (!prov) throw new Error('provider entry missing');
80
- const baseUrl = String(prov.baseUrl || prov.baseURL || '').replace(/\/$/, '');
81
- const endpoint = String(prov.endpoint || '/responses');
82
- const apiKey = prov.auth?.apiKey || cfgDoc?.keyVault?.[providerId]?.key1?.value;
83
- if (!apiKey) throw new Error('no apikey');
84
-
85
- const files = listGoldenRequests();
86
- if (!files.length) throw new Error('no responses golden requests');
87
- const chosen = pickGoldenForBaseUrl(files, baseUrl, pickHint);
88
- if (!chosen) throw new Error('no suitable golden request');
89
- const sample = JSON.parse(fs.readFileSync(path.join(SAMPLES_DIR, chosen), 'utf-8'));
90
- const body = sample?.data?.body || sample?.body || sample?.data || sample;
91
- if (!body || typeof body !== 'object') throw new Error('invalid golden body');
92
- // Override model if provider specifies one
93
- const model = prov.model || prov.modelId || prov.defaultModel || body.model;
94
- body.model = model;
95
- body.stream = true;
96
-
97
- const httpPath = pathToFileURL(path.join(process.cwd(), 'dist/providers/core/utils/http-client.js')).href;
98
- const { HttpClient } = await import(httpPath);
99
- const convPath = pathToFileURL(path.join(process.cwd(), 'sharedmodule/llmswitch-core/dist/sse/sse-to-json/index.js')).href;
100
- const bridgePath = pathToFileURL(path.join(process.cwd(), 'sharedmodule/llmswitch-core/dist/conversion/responses/responses-openai-bridge.js')).href;
101
- const { ResponsesSseToJsonConverter } = await import(convPath);
102
- const { buildChatResponseFromResponses } = await import(bridgePath);
183
+ const baseUrl = DEFAULT_BASE.replace(/\/$/, '');
184
+ const healthy = await healthCheck(baseUrl);
185
+ if (!healthy) {
186
+ throw new Error(`routecodex server not healthy: ${baseUrl}/health`);
187
+ }
188
+
189
+ const candidates = findClientRequestFiles(SAMPLES_ROOT);
190
+ if (!candidates.length) {
191
+ throw new Error(`no client-request samples found under ${SAMPLES_ROOT}`);
192
+ }
193
+ const picked = candidates[0];
194
+ const sample = readJson(picked.file);
195
+ const body = extractRequestBody(sample);
196
+ if (!body || typeof body !== 'object' || Array.isArray(body)) {
197
+ throw new Error(`invalid sample request body: ${picked.file}`);
198
+ }
199
+
200
+ const endpoint = extractEntryEndpoint(sample);
201
+ const wantsStream = extractStreamFlag(sample, body);
202
+ const requestBody = { ...body, stream: wantsStream };
203
+ const targetUrl = `${baseUrl}${endpoint.startsWith('/') ? endpoint : `/${endpoint}`}`;
204
+
205
+ ensureDir(OUT_DIR);
206
+ const runBase = path.join(OUT_DIR, `server-replay_${nowStamp()}`);
207
+ const requestOut = `${runBase}.request.json`;
208
+ const metaOut = `${runBase}.response.meta.json`;
209
+ const sseOut = `${runBase}.response.sse.log`;
210
+ const sseNdjsonOut = `${runBase}.response.sse.ndjson`;
211
+ const jsonOut = `${runBase}.response.json`;
212
+ const chatOut = `${runBase}.chat.json`;
103
213
 
104
214
  const headers = {
105
215
  'Content-Type': 'application/json',
216
+ 'Accept': wantsStream ? 'text/event-stream' : 'application/json',
106
217
  'OpenAI-Beta': 'responses-2024-12-17',
107
- 'Authorization': `Bearer ${apiKey}`
218
+ 'x-routecodex-api-key': DEFAULT_KEY
108
219
  };
109
220
 
110
- ensureDir(OUT_DIR);
111
- const base = path.join(OUT_DIR, `${providerId}_replay_${nowStamp()}`);
112
- const sseLog = `${base}.sse.log`;
113
- const jsonOut = `${base}.json`;
114
- const chatOut = `${base}.chat.json`;
115
- fs.writeFileSync(`${base}.request.json`, JSON.stringify({ url: baseUrl+endpoint, headers, body }, null, 2));
116
-
117
- const client = new HttpClient({ baseUrl, timeout: 300000 });
118
- const stream = await client.postStream(endpoint, body, { ...headers, Accept: 'text/event-stream' });
119
- const conv = new ResponsesSseToJsonConverter();
120
- const json = await conv.convertSseToJson(stream, {
121
- requestId: path.basename(base),
122
- model: String(body.model||'unknown'),
123
- onEvent: (evt) => {
124
- try {
125
- fs.appendFileSync(sseLog, `event: ${evt.type}\n`);
126
- fs.appendFileSync(sseLog, `data: ${JSON.stringify(evt.data)}\n\n`);
127
- } catch {}
128
- }
221
+ fs.writeFileSync(requestOut, JSON.stringify({
222
+ targetUrl,
223
+ endpoint,
224
+ sample: picked,
225
+ headers: { ...headers, 'x-routecodex-api-key': '***' },
226
+ body: requestBody
227
+ }, null, 2));
228
+
229
+ const res = await fetch(targetUrl, {
230
+ method: 'POST',
231
+ headers,
232
+ body: JSON.stringify(requestBody)
129
233
  });
130
- fs.writeFileSync(jsonOut, JSON.stringify(json, null, 2));
131
- const chat = buildChatResponseFromResponses(json);
132
- fs.writeFileSync(chatOut, JSON.stringify(chat, null, 2));
133
- const tc = chat?.choices?.[0]?.message?.tool_calls || [];
134
- const ok = Array.isArray(tc) && tc.length > 0;
135
- console.log('[responses-sse-replay-golden] provider=%s sample=%s tool_calls=%s out=%s', providerId, chosen, ok ? tc.length : 0, chatOut);
234
+ fs.writeFileSync(metaOut, JSON.stringify({
235
+ status: res.status,
236
+ statusText: res.statusText,
237
+ headers: Object.fromEntries(res.headers.entries())
238
+ }, null, 2));
239
+ if (!res.ok) {
240
+ const text = await res.text();
241
+ fs.writeFileSync(`${runBase}.response.error.txt`, text, 'utf-8');
242
+ throw new Error(`HTTP ${res.status}: ${text.slice(0, 500)}`);
243
+ }
244
+
245
+ if (!wantsStream) {
246
+ const json = await res.json();
247
+ fs.writeFileSync(jsonOut, JSON.stringify(json, null, 2));
248
+ console.log('[responses-sse-replay-golden] mode=json sample=%s out=%s', picked.file, jsonOut);
249
+ return;
250
+ }
251
+
252
+ const frames = await readSseFrames(res.body);
253
+ fs.writeFileSync(sseOut, frames.map((frame) => `${frame}\n\n`).join(''), 'utf-8');
254
+ fs.writeFileSync(sseNdjsonOut, frames.join('\n'), 'utf-8');
255
+ const converted = await convertSseFramesToJson(
256
+ frames,
257
+ picked.requestId,
258
+ typeof (requestBody).model === 'string' ? (requestBody).model : undefined
259
+ );
260
+ if (converted.json) {
261
+ fs.writeFileSync(jsonOut, JSON.stringify(converted.json, null, 2));
262
+ }
263
+ if (converted.chat) {
264
+ fs.writeFileSync(chatOut, JSON.stringify(converted.chat, null, 2));
265
+ }
266
+ console.log(
267
+ '[responses-sse-replay-golden] mode=sse sample=%s frames=%d sse=%s json=%s chat=%s',
268
+ picked.file,
269
+ frames.length,
270
+ sseOut,
271
+ converted.json ? jsonOut : '(skip)',
272
+ converted.chat ? chatOut : '(skip)'
273
+ );
136
274
  }
137
275
 
138
- main().catch(e => { console.error(e); process.exit(1); });
276
+ main().catch((err) => {
277
+ console.error('[responses-sse-replay-golden] failed:', err?.message || String(err));
278
+ process.exit(1);
279
+ });
package/scripts/run-bg.sh CHANGED
@@ -44,7 +44,7 @@ detect_port() {
44
44
  local p="${TARGET_PORT:-}"
45
45
  if [[ -n "$p" ]]; then echo "$p"; return; fi
46
46
  if [[ -n "${ROUTECODEX_PORT:-}" ]]; then echo "${ROUTECODEX_PORT}"; return; fi
47
- local cfg="$HOME/.routecodex/config.json"
47
+ local cfg="$HOME/.rcc/config.json"
48
48
  if command -v jq >/dev/null 2>&1 && [[ -f "$cfg" ]]; then
49
49
  p=$(jq -r '.port // empty' "$cfg" 2>/dev/null || true)
50
50
  if [[ -n "$p" && "$p" =~ ^[0-9]+$ ]]; then echo "$p"; return; fi
@@ -38,7 +38,7 @@ detect_port() {
38
38
  local p="${TARGET_PORT:-}"
39
39
  if [[ -n "$p" ]]; then echo "$p"; return; fi
40
40
  if [[ -n "${ROUTECODEX_PORT:-}" ]]; then echo "${ROUTECODEX_PORT}"; return; fi
41
- local cfg="$HOME/.routecodex/config.json"
41
+ local cfg="$HOME/.rcc/config.json"
42
42
  if command -v jq >/dev/null 2>&1 && [[ -f "$cfg" ]]; then
43
43
  p=$(jq -r '.port // empty' "$cfg" 2>/dev/null || true)
44
44
  if [[ -n "$p" && "$p" =~ ^[0-9]+$ ]]; then echo "$p"; return; fi
@@ -180,7 +180,7 @@ async function main() {
180
180
  const samplePath = args.sample || args._[0];
181
181
  if (!samplePath) throw new Error('Missing --sample <file.json>');
182
182
 
183
- const configPath = args.config || path.join(os.homedir(), '.routecodex', 'config.json');
183
+ const configPath = args.config || path.join(os.homedir(), '.rcc', 'config.json');
184
184
  const outDir = args.out || path.join(process.cwd(), 'test-results', 'antigravity-pipeline-compare');
185
185
  fs.mkdirSync(outDir, { recursive: true });
186
186
 
@@ -85,7 +85,7 @@ async function main() {
85
85
  const baselinePath = args.baseline || args._[1];
86
86
  if (!baselinePath) throw new Error('Missing --baseline <provider-request.json>');
87
87
 
88
- const configPath = args.config || path.join(os.homedir(), '.routecodex', 'config.json');
88
+ const configPath = args.config || path.join(os.homedir(), '.rcc', 'config.json');
89
89
  const outDir = args.out || path.join(process.cwd(), 'test-results', 'antigravity-gemini-dryrun');
90
90
  fs.mkdirSync(outDir, { recursive: true });
91
91
 
@@ -21,7 +21,7 @@ function usage(err) {
21
21
  }
22
22
 
23
23
  const args = process.argv.slice(2);
24
- const configPath = args[0] || path.join(process.env.HOME || '~', '.routecodex', 'provider', 'c4m', 'config.v1.json');
24
+ const configPath = args[0] || path.join(process.env.HOME || '~', '.rcc', 'provider', 'c4m', 'config.v1.json');
25
25
  if (!fs.existsSync(configPath)) usage(`Config file not found: ${configPath}`);
26
26
  const providerTarget = args[1] || 'c4m.gpt-5.1';
27
27
  const [providerId, modelId = 'gpt-5.1'] = providerTarget.split('.');
@@ -360,7 +360,7 @@ async function scenarioRealConfig(configPath) {
360
360
  async function main() {
361
361
  const args = parseArgs(process.argv.slice(2));
362
362
  if (args.help) {
363
- console.log('Usage: node scripts/tests/virtual-router-health.mjs [--out summary.json] [--config ~/.routecodex/config.json]');
363
+ console.log('Usage: node scripts/tests/virtual-router-health.mjs [--out summary.json] [--config ~/.rcc/config.json]');
364
364
  return;
365
365
  }
366
366
 
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
3
  * Update provider models from /v1/models endpoint and write into the user's
4
- * RouteCodex config (defaults to ~/.routecodex/config.json).
4
+ * RouteCodex config (defaults to ~/.rcc/config.json).
5
5
  *
6
6
  * Usage:
7
7
  * node scripts/update-models.mjs --provider qwen-provider [--write] [--config path]
@@ -27,7 +27,7 @@ function expandHome(p){ return p && p.startsWith('~/')? p.replace(/^~\//, `${pro
27
27
 
28
28
  function resolveConfigPath(explicit){
29
29
  const envPath = process.env.ROUTECODEX_CONFIG_PATH || process.env.ROUTECODEX_CONFIG;
30
- const fallback = path.join(process.env.HOME || '', '.routecodex', 'config.json');
30
+ const fallback = path.join(process.env.HOME || '', '.rcc', 'config.json');
31
31
  const candidate = expandHome(explicit || envPath || fallback);
32
32
  if (!candidate) {
33
33
  throw new Error('Unable to resolve configuration path');
@@ -149,7 +149,7 @@ const debugLogsCount = fs.existsSync(debugLogsDir)
149
149
 
150
150
  if (debugLogsCount > 0) {
151
151
  console.log('✅ 流水线系统活跃');
152
- console.log('💡 建议使用: routecodex start --config ~/.routecodex/config.json (默认监听 5555 端口)');
152
+ console.log('💡 建议使用: routecodex start --config ~/.rcc/config.json (默认监听 5555 端口)');
153
153
  } else {
154
154
  console.log('⚠️ 流水线系统可能未启动');
155
155
  console.log('💡 建议检查 5555 端口上的 RouteCodex 服务是否已启动(routecodex start)');
@@ -24,7 +24,7 @@ const VERIFY_BASE = process.env.ROUTECODEX_VERIFY_BASE_URL || `http://127.0.0.1:
24
24
  const VERIFY_CONFIG =
25
25
  process.env.ROUTECODEX_VERIFY_CONFIG ||
26
26
  process.env.ROUTECODEX_CONFIG_PATH ||
27
- `${process.env.HOME || ''}/.routecodex/config.json`;
27
+ `${process.env.HOME || ''}/.rcc/config.json`;
28
28
 
29
29
  const DEFAULT_SAMPLE = path.join(
30
30
  os.homedir(),
@@ -16,11 +16,11 @@ const VERIFY_BASE = process.env.ROUTECODEX_VERIFY_BASE_URL || `http://127.0.0.1:
16
16
  const EXPLICIT_VERIFY_CONFIG = String(
17
17
  process.env.ROUTECODEX_VERIFY_CONFIG || process.env.ROUTECODEX_CONFIG_PATH || ''
18
18
  ).trim();
19
- const DEFAULT_USER_CONFIG = `${process.env.HOME || ''}/.routecodex/config.json`;
19
+ const DEFAULT_USER_CONFIG = `${process.env.HOME || ''}/.rcc/config.json`;
20
20
  const USE_USER_CONFIG = String(process.env.ROUTECODEX_VERIFY_USE_USER_CONFIG || '').trim() === '1';
21
21
  const GEMINI_CLI_CONFIG =
22
22
  process.env.ROUTECODEX_VERIFY_GEMINI_CLI_CONFIG ||
23
- `${process.env.HOME || ''}/.routecodex/provider/gemini-cli/config.v1.json`;
23
+ `${process.env.HOME || ''}/.rcc/provider/gemini-cli/config.v1.json`;
24
24
 
25
25
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
26
26
  const DEFAULT_AGENTS_PATH = path.resolve(__dirname, '..', 'AGENTS.md');
@@ -55,8 +55,8 @@ async function waitForHealth() {
55
55
  async function resolveTestModel() {
56
56
  const home = os.homedir();
57
57
  const candidates = [
58
- path.join(home, '.routecodex', 'config', 'generated', `virtual-router-config.${port}.generated.json`),
59
- path.join(home, '.routecodex', 'config', 'generated', 'virtual-router-config.generated.json'),
58
+ path.join(home, '.rcc', 'config', 'generated', `virtual-router-config.${port}.generated.json`),
59
+ path.join(home, '.rcc', 'config', 'generated', 'virtual-router-config.generated.json'),
60
60
  ];
61
61
  for (const file of candidates) {
62
62
  try {
@@ -42,7 +42,7 @@ function resolveSecretValue(value) {
42
42
  }
43
43
 
44
44
  function loadProviderEntry(providerId) {
45
- const providerRoot = path.join(os.homedir(), '.routecodex', 'provider', providerId);
45
+ const providerRoot = path.join(os.homedir(), '.rcc', 'provider', providerId);
46
46
  for (const name of PROVIDER_CONFIG_FILES) {
47
47
  const full = path.join(providerRoot, name);
48
48
  if (!fs.existsSync(full)) continue;