@jsonstudio/rcc 0.90.252 → 0.90.323

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 (95) hide show
  1. package/config/providers/ali-coding-plan.json +73 -0
  2. package/dist/build-info.js +2 -2
  3. package/dist/cli/commands/launcher-kernel.js +21 -5
  4. package/dist/cli/commands/launcher-kernel.js.map +1 -1
  5. package/dist/cli/commands/session-admin.js +46 -8
  6. package/dist/cli/commands/session-admin.js.map +1 -1
  7. package/dist/cli/commands/session-inject.js +43 -4
  8. package/dist/cli/commands/session-inject.js.map +1 -1
  9. package/dist/config/unified-config-paths.js +22 -2
  10. package/dist/config/unified-config-paths.js.map +1 -1
  11. package/dist/daemon-admin-ui/assets/index-Bnx13Byl.js +15 -0
  12. package/dist/daemon-admin-ui/index.html +1 -1
  13. package/dist/index.js +59 -8
  14. package/dist/index.js.map +1 -1
  15. package/dist/manager/quota/provider-quota-center.js +33 -25
  16. package/dist/manager/quota/provider-quota-center.js.map +1 -1
  17. package/dist/modules/llmswitch/bridge/index.d.ts +1 -1
  18. package/dist/modules/llmswitch/bridge/index.js +1 -1
  19. package/dist/modules/llmswitch/bridge/index.js.map +1 -1
  20. package/dist/modules/llmswitch/bridge/native-exports.d.ts +1 -0
  21. package/dist/modules/llmswitch/bridge/native-exports.js +27 -0
  22. package/dist/modules/llmswitch/bridge/native-exports.js.map +1 -1
  23. package/dist/modules/llmswitch/bridge/snapshot-recorder.js +95 -24
  24. package/dist/modules/llmswitch/bridge/snapshot-recorder.js.map +1 -1
  25. package/dist/modules/llmswitch/bridge/state-integrations.d.ts +18 -0
  26. package/dist/modules/llmswitch/bridge/state-integrations.js +28 -0
  27. package/dist/modules/llmswitch/bridge/state-integrations.js.map +1 -1
  28. package/dist/modules/llmswitch/bridge.d.ts +2 -2
  29. package/dist/modules/llmswitch/bridge.js +2 -2
  30. package/dist/modules/llmswitch/bridge.js.map +1 -1
  31. package/dist/modules/pipeline/utils/colored-logger.d.ts +1 -0
  32. package/dist/modules/pipeline/utils/colored-logger.js +13 -9
  33. package/dist/modules/pipeline/utils/colored-logger.js.map +1 -1
  34. package/dist/providers/profile/families/anthropic-profile.js +32 -0
  35. package/dist/providers/profile/families/anthropic-profile.js.map +1 -1
  36. package/dist/server/handlers/handler-response-utils.js +9 -4
  37. package/dist/server/handlers/handler-response-utils.js.map +1 -1
  38. package/dist/server/runtime/http-server/clock-runtime-hooks.d.ts +2 -0
  39. package/dist/server/runtime/http-server/clock-runtime-hooks.js +91 -0
  40. package/dist/server/runtime/http-server/clock-runtime-hooks.js.map +1 -0
  41. package/dist/server/runtime/http-server/daemon-admin/auth-handler.js +51 -13
  42. package/dist/server/runtime/http-server/daemon-admin/auth-handler.js.map +1 -1
  43. package/dist/server/runtime/http-server/daemon-admin/auth-store.d.ts +1 -9
  44. package/dist/server/runtime/http-server/daemon-admin/auth-store.js +0 -16
  45. package/dist/server/runtime/http-server/daemon-admin/auth-store.js.map +1 -1
  46. package/dist/server/runtime/http-server/daemon-admin-routes.d.ts +2 -0
  47. package/dist/server/runtime/http-server/daemon-admin-routes.js +11 -8
  48. package/dist/server/runtime/http-server/daemon-admin-routes.js.map +1 -1
  49. package/dist/server/runtime/http-server/executor/client-injection-flow.js +9 -1
  50. package/dist/server/runtime/http-server/executor/client-injection-flow.js.map +1 -1
  51. package/dist/server/runtime/http-server/executor/provider-response-converter.js +119 -26
  52. package/dist/server/runtime/http-server/executor/provider-response-converter.js.map +1 -1
  53. package/dist/server/runtime/http-server/executor/request-retry-helpers.d.ts +1 -0
  54. package/dist/server/runtime/http-server/executor/request-retry-helpers.js +26 -0
  55. package/dist/server/runtime/http-server/executor/request-retry-helpers.js.map +1 -1
  56. package/dist/server/runtime/http-server/http-server-lifecycle.js +2 -0
  57. package/dist/server/runtime/http-server/http-server-lifecycle.js.map +1 -1
  58. package/dist/server/runtime/http-server/http-server-runtime-setup.js +2 -0
  59. package/dist/server/runtime/http-server/http-server-runtime-setup.js.map +1 -1
  60. package/dist/server/runtime/http-server/http-server-session-daemon.js +9 -299
  61. package/dist/server/runtime/http-server/http-server-session-daemon.js.map +1 -1
  62. package/dist/server/runtime/http-server/middleware.d.ts +7 -0
  63. package/dist/server/runtime/http-server/middleware.js +1 -1
  64. package/dist/server/runtime/http-server/middleware.js.map +1 -1
  65. package/dist/server/runtime/http-server/request-executor.js +36 -2
  66. package/dist/server/runtime/http-server/request-executor.js.map +1 -1
  67. package/dist/server/runtime/http-server/routes.js +9 -2
  68. package/dist/server/runtime/http-server/routes.js.map +1 -1
  69. package/dist/server/runtime/http-server/servertool-admin-state.d.ts +1 -0
  70. package/dist/server/runtime/http-server/servertool-admin-state.js +5 -0
  71. package/dist/server/runtime/http-server/servertool-admin-state.js.map +1 -1
  72. package/dist/server/runtime/http-server/session-client-route-utils.d.ts +1 -0
  73. package/dist/server/runtime/http-server/session-client-route-utils.js +49 -4
  74. package/dist/server/runtime/http-server/session-client-route-utils.js.map +1 -1
  75. package/dist/server/runtime/http-server/session-client-routes.d.ts +5 -1
  76. package/dist/server/runtime/http-server/session-client-routes.js +60 -30
  77. package/dist/server/runtime/http-server/session-client-routes.js.map +1 -1
  78. package/dist/server/runtime/http-server/stats-manager.js +2 -2
  79. package/dist/server/runtime/http-server/stats-manager.js.map +1 -1
  80. package/dist/server/utils/request-log-color.js +10 -3
  81. package/dist/server/utils/request-log-color.js.map +1 -1
  82. package/dist/server/utils/stage-logger.js +71 -9
  83. package/dist/server/utils/stage-logger.js.map +1 -1
  84. package/dist/utils/session-log-color.js +31 -5
  85. package/dist/utils/session-log-color.js.map +1 -1
  86. package/package.json +3 -2
  87. package/scripts/build-core.mjs +2 -7
  88. package/scripts/ensure-llmswitch-mode.mjs +7 -1
  89. package/scripts/pack-mode.mjs +14 -1
  90. package/scripts/pack-rcc.mjs +9 -4
  91. package/scripts/publish-rcc.mjs +8 -3
  92. package/scripts/vendor-core.mjs +12 -7
  93. package/dist/daemon-admin-ui/assets/index-C8vP_c5E.js +0 -15
  94. package/docs/rccx-wasm-migration.md +0 -74
  95. package/scripts/compare-codex-rccx.mjs +0 -326
@@ -1,74 +0,0 @@
1
- # rccx wasm 接入说明(Host 视角)
2
-
3
- ## 三条 CLI 路线的角色划分
4
-
5
- - `routecodex`(dev CLI)
6
- - 面向本地开发与调试,始终使用仓库下的 `sharedmodule/llmswitch-core` 源码。
7
- - 通过 `npm run llmswitch:link` / `npm run config:use-local` 把本地 llmswitch-core 链接到 `node_modules/@jsonstudio/llms`。
8
- - `rcc`(release CLI)
9
- - 发布到 npm 的正式包:`@jsonstudio/rcc`。
10
- - 由 `npm run publish:rcc` 生成 tarball 并 `npm publish`,构建时依赖 npm 上的 `@jsonstudio/llms`(TS 实现)。
11
- - `rccx`(wasm CLI,实验/内部使用)
12
- - 使用 `@jsonstudio/llms-wasm`(wasm 引擎)作为 llms 核心实现。
13
- - 通过 npm alias 保持 Host import 形状不变:源码仍然 `import ... from '@jsonstudio/llms'`,但在 rccx 包内该依赖会被重写为 `@jsonstudio/llms-wasm`。
14
-
15
- > 约束:按照 `AGENTS.md`,正式发布渠道仍然只使用 `@jsonstudio/rcc`;`routecodex` 和 `rccx` 保持在本地/内部使用范围内。
16
-
17
- ## 依赖与打包策略
18
-
19
- - 根 `package.json` 继续声明:
20
- - `@jsonstudio/llms`: `^0.6.x`(供 routecodex / rcc 构建使用)。
21
- - `scripts/pack-mode.mjs` 在打包 rccx 时(`--name @jsonstudio/rccx --bin rccx`)会:
22
- - 将 `package.json.name` 设置为 `@jsonstudio/rccx`,`bin` 设置为 `{ "rccx": "dist/cli.js" }`。
23
- - 清空 `bundledDependencies` / `bundleDependencies`,改为普通 `dependencies`。
24
- - 在 `dependencies` 中应用 alias:
25
- - 移除原有的 `@jsonstudio/llms` 直连依赖;
26
- - 增加:
27
- - `"@jsonstudio/llms": "npm:@jsonstudio/llms-wasm@^0.1.0"`
28
- - `"@jsonstudio/llms-wasm": "^0.1.0"`
29
- - 这样,安装 `@jsonstudio/rccx` 时,`require('@jsonstudio/llms')` 实际会加载 wasm 版本实现。
30
-
31
- > 注意:`pack-mode.mjs` 只在打包阶段临时修改 `package.json`,打包完成后会恢复原始文件。
32
-
33
- ## 构建 rccx(本地)
34
-
35
- 1. 确保本机已经有可用的 `@jsonstudio/llms-wasm`:
36
- - 要么从 `sharedmodule/llms-wasm` 构建并发布到私有 npm;
37
- - 要么通过本地 tarball 安装到全局/工程级 npm registry(版本号需满足 `^0.1.0`)。
38
- 2. 在 routecodex 仓库根目录执行:
39
- ```bash
40
- npm run build:rccx
41
- ```
42
- - 这会先执行 `npm run build:min`(使用当前 BUILD_MODE 构建 dist);
43
- - 然后调用:
44
- ```bash
45
- node scripts/pack-mode.mjs --name @jsonstudio/rccx --bin rccx
46
- ```
47
- - 完成后仓库根目录会出现一个 `jsonstudio-rccx-<version>.tgz`。
48
- 3. 在目标环境中安装 rccx:
49
- ```bash
50
- npm install -g ./jsonstudio-rccx-<version>.tgz
51
- ```
52
-
53
- ## 运行与行为确认
54
-
55
- - `rccx` CLI 行为与 `routecodex` / `rcc` 相同:
56
- - `rccx start` 启动同一套 HTTP server,端口仍由 RouteCodex 配置决定(默认 5555)。
57
- - `rccx code` / `rccx config` 等子命令全部复用现有 CLI 逻辑。
58
- - 不同点只在于 llms 实现:
59
- - `rcc` 使用 npm 上的 `@jsonstudio/llms`(TS 实现);
60
- - `rccx` 使用 npm 上的 `@jsonstudio/llms-wasm`(wasm 引擎,通过 alias 暴露为 `@jsonstudio/llms`)。
61
-
62
- ## 黑盒对比建议(可选)
63
-
64
- 为确保 wasm 版本行为与 TS 版本一致,建议在同一份 RouteCodex 配置下做一轮回放对比:
65
-
66
- - 启动两个实例:
67
- - `routecodex`(或 `rcc`)使用 TS 版 llms;
68
- - `rccx` 使用 wasm 版 llms。
69
- - 对同一组请求(尤其是 sticky / health / 429 / series cooldown / Gemini compat 等场景):
70
- - 比较日志中的 `virtual-router-hit` / `providerKey` / sticky 选择与健康状态;
71
- - 确认两侧路由决策与工具调用行为一致。
72
-
73
- 后续每次升级 `@jsonstudio/llms` / `@jsonstudio/llms-wasm` 时,可以复用这一套回放作为回归校验。
74
-
@@ -1,326 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * 黑盒对比:使用 codex-samples 中的一条样本,
4
- * 分别通过 RouteCodex(dev) 和 rccx(wasm 引擎) 重放,
5
- * 然后对比 HTTP 元数据和基础响应结构。
6
- *
7
- * 前提:
8
- * - 已经有 RouteCodex 服务在某个端口运行(默认 http://127.0.0.1:5555);
9
- * - 已经有 rccx 服务在另一个端口运行(默认 http://127.0.0.1:5556);
10
- * - codex 样本是由 RouteCodex 捕获的 client-request JSON(~/.routecodex/codex-samples/...)。
11
- *
12
- * 使用方式(示例):
13
- * node scripts/compare-codex-rccx.mjs \\
14
- * --sample ~/.routecodex/codex-samples/openai-responses/xxx_client-request.json \\
15
- * --route-base http://127.0.0.1:5555 \\
16
- * --rccx-base http://127.0.0.1:5556
17
- *
18
- * 脚本会调用 scripts/replay-codex-sample.mjs 对同一条样本重放两次:
19
- * - label=routecodex,base = --route-base;
20
- * - label=rccx, base = --rccx-base;
21
- *
22
- * 然后读取各自 runs/<requestId>/<label>/response.* 进行对比。
23
- */
24
-
25
- import fs from 'node:fs';
26
- import os from 'node:os';
27
- import path from 'node:path';
28
- import { spawn } from 'node:child_process';
29
- import { writeErrorSampleJson } from './lib/errorsamples.mjs';
30
-
31
- const DEFAULT_ROUTE_BASE = process.env.ROUTECODEX_BASE || 'http://127.0.0.1:5555';
32
- const DEFAULT_RCCX_BASE = process.env.RCCX_BASE || 'http://127.0.0.1:5556';
33
- const DEFAULT_API_KEY = process.env.ROUTECODEX_API_KEY || 'routecodex-test';
34
-
35
- function usage() {
36
- console.log(`Usage:
37
- node scripts/compare-codex-rccx.mjs --sample <file> [--route-base URL] [--rccx-base URL] [--key TOKEN]
38
-
39
- Environment:
40
- ROUTECODEX_BASE 默认 RouteCodex 基础 URL (默认 ${DEFAULT_ROUTE_BASE})
41
- RCCX_BASE 默认 rccx 基础 URL (默认 ${DEFAULT_RCCX_BASE})
42
- ROUTECODEX_API_KEY 默认 API key (默认 ${DEFAULT_API_KEY})
43
- `);
44
- }
45
-
46
- function parseArgs() {
47
- const args = process.argv.slice(2);
48
- const opts = {
49
- routeBase: DEFAULT_ROUTE_BASE,
50
- rccxBase: DEFAULT_RCCX_BASE,
51
- key: DEFAULT_API_KEY,
52
- routeLabel: 'routecodex',
53
- rccxLabel: 'rccx'
54
- };
55
- for (let i = 0; i < args.length; i += 1) {
56
- const a = args[i];
57
- if (a === '--sample') opts.sample = args[++i];
58
- else if (a === '--route-base') opts.routeBase = args[++i];
59
- else if (a === '--rccx-base') opts.rccxBase = args[++i];
60
- else if (a === '--key') opts.key = args[++i];
61
- else if (a === '--route-label') opts.routeLabel = args[++i];
62
- else if (a === '--rccx-label') opts.rccxLabel = args[++i];
63
- else if (a === '--help' || a === '-h') {
64
- usage();
65
- process.exit(0);
66
- } else {
67
- console.error(`Unknown arg: ${a}`);
68
- usage();
69
- process.exit(1);
70
- }
71
- }
72
- if (!opts.sample) {
73
- usage();
74
- process.exit(1);
75
- }
76
- return opts;
77
- }
78
-
79
- function readJson(file) {
80
- return JSON.parse(fs.readFileSync(file, 'utf8'));
81
- }
82
-
83
- function computeRequestId(sample) {
84
- return (
85
- sample?.requestId ||
86
- sample?.data?.meta?.requestId ||
87
- sample?.meta?.requestId ||
88
- `sample_${Date.now()}`
89
- );
90
- }
91
-
92
- function computeRunDir(samplePath, requestId, label) {
93
- const baseDir = path.dirname(path.resolve(samplePath));
94
- return path.join(baseDir, 'runs', requestId, label);
95
- }
96
-
97
- function runReplay({ base, label, samplePath, key }) {
98
- return new Promise((resolve, reject) => {
99
- const args = [
100
- 'scripts/replay-codex-sample.mjs',
101
- '--sample',
102
- samplePath,
103
- '--label',
104
- label,
105
- '--base',
106
- base,
107
- '--key',
108
- key
109
- ];
110
- const repoRoot = path.resolve(path.dirname(new URL(import.meta.url).pathname), '..');
111
- const child = spawn(process.execPath, args, {
112
- cwd: repoRoot,
113
- stdio: 'inherit'
114
- });
115
- child.on('exit', (code) => {
116
- if (code === 0) resolve();
117
- else reject(new Error(`replay-codex-sample failed for label=${label} (exit ${code})`));
118
- });
119
- child.on('error', (err) => reject(err));
120
- });
121
- }
122
-
123
- function loadRunResult(runDir) {
124
- const metaPath = path.join(runDir, 'response.meta.json');
125
- if (!fs.existsSync(metaPath)) {
126
- return { error: `missing response.meta.json in ${runDir}` };
127
- }
128
- const meta = readJson(metaPath);
129
-
130
- const jsonPath = path.join(runDir, 'response.json');
131
- const errorPath = path.join(runDir, 'response.error.txt');
132
- const ssePath = path.join(runDir, 'response.sse.ndjson');
133
-
134
- let bodyKind = 'none';
135
- let bodySample = null;
136
-
137
- if (fs.existsSync(jsonPath)) {
138
- bodyKind = 'json';
139
- try {
140
- bodySample = readJson(jsonPath);
141
- } catch {
142
- bodySample = null;
143
- }
144
- } else if (fs.existsSync(errorPath)) {
145
- bodyKind = 'error-text';
146
- try {
147
- const txt = fs.readFileSync(errorPath, 'utf8');
148
- bodySample = txt.slice(0, 1024);
149
- } catch {
150
- bodySample = null;
151
- }
152
- } else if (fs.existsSync(ssePath)) {
153
- bodyKind = 'sse';
154
- try {
155
- const txt = fs.readFileSync(ssePath, 'utf8');
156
- const lines = txt.split('\n').filter(Boolean);
157
- bodySample = lines.slice(0, 5);
158
- } catch {
159
- bodySample = null;
160
- }
161
- }
162
-
163
- return { meta, bodyKind, bodySample };
164
- }
165
-
166
- function stableSubset(meta) {
167
- if (!meta || typeof meta !== 'object') return null;
168
- return {
169
- status: meta.status,
170
- statusText: meta.statusText,
171
- endpoint: meta.endpoint,
172
- targetUrl: meta.targetUrl,
173
- wantsSse: meta.wantsSse,
174
- contentType: meta.headers && meta.headers['content-type'],
175
- routeHint:
176
- (meta.headers && (meta.headers['x-route-hint'] || meta.headers['X-Route-Hint'])) || undefined
177
- };
178
- }
179
-
180
- function stableStringify(value) {
181
- return JSON.stringify(
182
- value,
183
- (key, val) => {
184
- if (val && typeof val === 'object' && !Array.isArray(val)) {
185
- const out = {};
186
- for (const k of Object.keys(val).sort()) {
187
- out[k] = val[k];
188
- }
189
- return out;
190
- }
191
- return val;
192
- }
193
- );
194
- }
195
-
196
- async function main() {
197
- const opts = parseArgs();
198
- const samplePath = path.resolve(opts.sample);
199
- const sample = readJson(samplePath);
200
- const requestId = computeRequestId(sample);
201
-
202
- console.log(
203
- `[compare-codex-rccx] sample=${samplePath} requestId=${requestId} routeBase=${opts.routeBase} rccxBase=${opts.rccxBase}`
204
- );
205
-
206
- // RouteCodex 路径
207
- console.log('[compare-codex-rccx] ▶ routecodex replay...');
208
- await runReplay({
209
- base: opts.routeBase,
210
- label: opts.routeLabel,
211
- samplePath,
212
- key: opts.key
213
- });
214
- const routeRunDir = computeRunDir(samplePath, requestId, opts.routeLabel);
215
- const routeResult = loadRunResult(routeRunDir);
216
-
217
- // rccx 路径
218
- console.log('[compare-codex-rccx] ▶ rccx replay...');
219
- await runReplay({
220
- base: opts.rccxBase,
221
- label: opts.rccxLabel,
222
- samplePath,
223
- key: opts.key
224
- });
225
- const rccxRunDir = computeRunDir(samplePath, requestId, opts.rccxLabel);
226
- const rccxResult = loadRunResult(rccxRunDir);
227
-
228
- if (routeResult.error || rccxResult.error) {
229
- console.error('[compare-codex-rccx] ❌ missing run artifacts:', {
230
- routeRunDir,
231
- routeError: routeResult.error || null,
232
- rccxRunDir,
233
- rccxError: rccxResult.error || null
234
- });
235
- try {
236
- const file = await writeErrorSampleJson({
237
- group: 'compare-codex-rccx',
238
- kind: 'missing-artifacts',
239
- payload: {
240
- kind: 'compare-codex-rccx-missing-artifacts',
241
- stamp: new Date().toISOString(),
242
- samplePath,
243
- requestId,
244
- routeBase: opts.routeBase,
245
- rccxBase: opts.rccxBase,
246
- routeLabel: opts.routeLabel,
247
- rccxLabel: opts.rccxLabel,
248
- routeRunDir,
249
- rccxRunDir,
250
- routeError: routeResult.error || null,
251
- rccxError: rccxResult.error || null
252
- }
253
- });
254
- console.error(`[compare-codex-rccx] wrote errorsample: ${file}`);
255
- } catch (err) {
256
- console.error('[compare-codex-rccx] failed to write errorsample:', err);
257
- }
258
- process.exitCode = 1;
259
- return;
260
- }
261
-
262
- const routeMeta = stableSubset(routeResult.meta);
263
- const rccxMeta = stableSubset(rccxResult.meta);
264
-
265
- const metaEqual = stableStringify(routeMeta) === stableStringify(rccxMeta);
266
- const bodyKindEqual = routeResult.bodyKind === rccxResult.bodyKind;
267
-
268
- console.log('[compare-codex-rccx] routecodex.meta =', routeMeta);
269
- console.log('[compare-codex-rccx] rccx.meta =', rccxMeta);
270
- console.log('[compare-codex-rccx] routecodex.bodyKind =', routeResult.bodyKind);
271
- console.log('[compare-codex-rccx] rccx.bodyKind =', rccxResult.bodyKind);
272
-
273
- if (!metaEqual || !bodyKindEqual) {
274
- console.log('[compare-codex-rccx] ❌ mismatch detected between RouteCodex and rccx');
275
- console.log('[compare-codex-rccx] routecodex runDir =', routeRunDir);
276
- console.log('[compare-codex-rccx] rccx runDir =', rccxRunDir);
277
- // 为了调试 429 / 系列冷却问题,额外打印一小段 body 样本。
278
- console.log('[compare-codex-rccx] routecodex.bodySample =', routeResult.bodySample);
279
- console.log('[compare-codex-rccx] rccx.bodySample =', rccxResult.bodySample);
280
- try {
281
- const file = await writeErrorSampleJson({
282
- group: 'compare-codex-rccx',
283
- kind: 'mismatch',
284
- payload: {
285
- kind: 'compare-codex-rccx-mismatch',
286
- stamp: new Date().toISOString(),
287
- samplePath,
288
- requestId,
289
- routeBase: opts.routeBase,
290
- rccxBase: opts.rccxBase,
291
- routeLabel: opts.routeLabel,
292
- rccxLabel: opts.rccxLabel,
293
- routeRunDir,
294
- rccxRunDir,
295
- routeMeta,
296
- rccxMeta,
297
- routeBodyKind: routeResult.bodyKind,
298
- rccxBodyKind: rccxResult.bodyKind,
299
- routeBodySample: routeResult.bodySample,
300
- rccxBodySample: rccxResult.bodySample
301
- }
302
- });
303
- console.error(`[compare-codex-rccx] wrote errorsample: ${file}`);
304
- } catch (err) {
305
- console.error('[compare-codex-rccx] failed to write errorsample:', err);
306
- }
307
- process.exitCode = 1;
308
- return;
309
- }
310
-
311
- console.log('[compare-codex-rccx] ✅ meta/bodyKind aligned for this sample');
312
- console.log('[compare-codex-rccx] routecodex runDir =', routeRunDir);
313
- console.log('[compare-codex-rccx] rccx runDir =', rccxRunDir);
314
- }
315
-
316
- main().catch((err) => {
317
- console.error('[compare-codex-rccx] fatal error:', err);
318
- try {
319
- const root = path.join(os.homedir(), '.routecodex', 'errorsamples', 'compare-codex-rccx');
320
- const file = path.join(root, `fatal-${Date.now()}.txt`);
321
- fs.mkdirSync(root, { recursive: true });
322
- fs.writeFileSync(file, String(err?.stack || err), 'utf8');
323
- console.error(`[compare-codex-rccx] wrote errorsample: ${file}`);
324
- } catch {}
325
- process.exitCode = 1;
326
- });