@jsonstudio/rcc 0.89.1136 → 0.89.1189

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 (134) hide show
  1. package/dist/build-info.js +2 -2
  2. package/dist/cli/commands/clean.d.ts +16 -0
  3. package/dist/cli/commands/clean.js +58 -0
  4. package/dist/cli/commands/clean.js.map +1 -0
  5. package/dist/cli/commands/code.d.ts +55 -0
  6. package/dist/cli/commands/code.js +376 -0
  7. package/dist/cli/commands/code.js.map +1 -0
  8. package/dist/cli/commands/config.d.ts +31 -0
  9. package/dist/cli/commands/config.js +168 -0
  10. package/dist/cli/commands/config.js.map +1 -0
  11. package/dist/cli/commands/env.d.ts +20 -0
  12. package/dist/cli/commands/env.js +73 -0
  13. package/dist/cli/commands/env.js.map +1 -0
  14. package/dist/cli/commands/examples.d.ts +5 -0
  15. package/dist/cli/commands/examples.js +66 -0
  16. package/dist/cli/commands/examples.js.map +1 -0
  17. package/dist/cli/commands/port.d.ts +24 -0
  18. package/dist/cli/commands/port.js +85 -0
  19. package/dist/cli/commands/port.js.map +1 -0
  20. package/dist/cli/commands/restart.d.ts +50 -0
  21. package/dist/cli/commands/restart.js +176 -0
  22. package/dist/cli/commands/restart.js.map +1 -0
  23. package/dist/cli/commands/start.d.ts +68 -0
  24. package/dist/cli/commands/start.js +295 -0
  25. package/dist/cli/commands/start.js.map +1 -0
  26. package/dist/cli/commands/status.d.ts +16 -0
  27. package/dist/cli/commands/status.js +104 -0
  28. package/dist/cli/commands/status.js.map +1 -0
  29. package/dist/cli/commands/stop.d.ts +35 -0
  30. package/dist/cli/commands/stop.js +95 -0
  31. package/dist/cli/commands/stop.js.map +1 -0
  32. package/dist/cli/logger.d.ts +8 -0
  33. package/dist/cli/logger.js +9 -0
  34. package/dist/cli/logger.js.map +1 -0
  35. package/dist/cli/main.d.ts +6 -0
  36. package/dist/cli/main.js +16 -0
  37. package/dist/cli/main.js.map +1 -0
  38. package/dist/cli/program.d.ts +8 -0
  39. package/dist/cli/program.js +16 -0
  40. package/dist/cli/program.js.map +1 -0
  41. package/dist/cli/register/basic-commands.d.ts +30 -0
  42. package/dist/cli/register/basic-commands.js +11 -0
  43. package/dist/cli/register/basic-commands.js.map +1 -0
  44. package/dist/cli/register/code-command.d.ts +3 -0
  45. package/dist/cli/register/code-command.js +5 -0
  46. package/dist/cli/register/code-command.js.map +1 -0
  47. package/dist/cli/register/restart-command.d.ts +3 -0
  48. package/dist/cli/register/restart-command.js +5 -0
  49. package/dist/cli/register/restart-command.js.map +1 -0
  50. package/dist/cli/register/start-command.d.ts +3 -0
  51. package/dist/cli/register/start-command.js +5 -0
  52. package/dist/cli/register/start-command.js.map +1 -0
  53. package/dist/cli/register/status-config-commands.d.ts +16 -0
  54. package/dist/cli/register/status-config-commands.js +7 -0
  55. package/dist/cli/register/status-config-commands.js.map +1 -0
  56. package/dist/cli/register/stop-command.d.ts +3 -0
  57. package/dist/cli/register/stop-command.js +5 -0
  58. package/dist/cli/register/stop-command.js.map +1 -0
  59. package/dist/cli/runtime.d.ts +5 -0
  60. package/dist/cli/runtime.js +11 -0
  61. package/dist/cli/runtime.js.map +1 -0
  62. package/dist/cli/server/port-utils.d.ts +52 -0
  63. package/dist/cli/server/port-utils.js +193 -0
  64. package/dist/cli/server/port-utils.js.map +1 -0
  65. package/dist/cli/spinner.d.ts +10 -0
  66. package/dist/cli/spinner.js +59 -0
  67. package/dist/cli/spinner.js.map +1 -0
  68. package/dist/cli/utils/normalize.d.ts +2 -0
  69. package/dist/cli/utils/normalize.js +22 -0
  70. package/dist/cli/utils/normalize.js.map +1 -0
  71. package/dist/cli/utils/safe-read-json.d.ts +1 -0
  72. package/dist/cli/utils/safe-read-json.js +11 -0
  73. package/dist/cli/utils/safe-read-json.js.map +1 -0
  74. package/dist/cli.js +148 -1775
  75. package/dist/cli.js.map +1 -1
  76. package/dist/client/anthropic/anthropic-protocol-client.js +4 -3
  77. package/dist/client/anthropic/anthropic-protocol-client.js.map +1 -1
  78. package/dist/client/gemini-cli/gemini-cli-protocol-client.d.ts +1 -1
  79. package/dist/client/gemini-cli/gemini-cli-protocol-client.js +10 -3
  80. package/dist/client/gemini-cli/gemini-cli-protocol-client.js.map +1 -1
  81. package/dist/commands/quota-daemon.js +2 -2
  82. package/dist/commands/quota-daemon.js.map +1 -1
  83. package/dist/config/provider-v2-loader.js +4 -2
  84. package/dist/config/provider-v2-loader.js.map +1 -1
  85. package/dist/manager/modules/quota/index.js +21 -4
  86. package/dist/manager/modules/quota/index.js.map +1 -1
  87. package/dist/manager/modules/routing/index.js.map +1 -1
  88. package/dist/manager/storage/file-store.js +1 -1
  89. package/dist/manager/storage/file-store.js.map +1 -1
  90. package/dist/providers/auth/oauth-lifecycle.js +2 -2
  91. package/dist/providers/auth/oauth-lifecycle.js.map +1 -1
  92. package/dist/providers/core/api/provider-config.d.ts +2 -0
  93. package/dist/providers/core/api/provider-types.d.ts +2 -0
  94. package/dist/providers/core/runtime/base-provider.js +21 -27
  95. package/dist/providers/core/runtime/base-provider.js.map +1 -1
  96. package/dist/providers/core/runtime/gemini-cli-http-provider.d.ts +1 -0
  97. package/dist/providers/core/runtime/gemini-cli-http-provider.js +37 -5
  98. package/dist/providers/core/runtime/gemini-cli-http-provider.js.map +1 -1
  99. package/dist/providers/core/runtime/http-request-executor.js +23 -29
  100. package/dist/providers/core/runtime/http-request-executor.js.map +1 -1
  101. package/dist/providers/core/runtime/http-transport-provider.js +20 -0
  102. package/dist/providers/core/runtime/http-transport-provider.js.map +1 -1
  103. package/dist/providers/core/utils/http-client.d.ts +9 -0
  104. package/dist/providers/core/utils/http-client.js +9 -11
  105. package/dist/providers/core/utils/http-client.js.map +1 -1
  106. package/dist/providers/core/utils/provider-error-reporter.js +2 -6
  107. package/dist/providers/core/utils/provider-error-reporter.js.map +1 -1
  108. package/dist/providers/mock/mock-provider-runtime.js +19 -5
  109. package/dist/providers/mock/mock-provider-runtime.js.map +1 -1
  110. package/dist/server/runtime/http-server/index.d.ts +1 -0
  111. package/dist/server/runtime/http-server/index.js +70 -11
  112. package/dist/server/runtime/http-server/index.js.map +1 -1
  113. package/dist/server/runtime/http-server/request-executor.js +9 -1
  114. package/dist/server/runtime/http-server/request-executor.js.map +1 -1
  115. package/dist/server/runtime/http-server/routes.js +8 -4
  116. package/dist/server/runtime/http-server/routes.js.map +1 -1
  117. package/dist/server/runtime/http-server/stats-manager.js +9 -3
  118. package/dist/server/runtime/http-server/stats-manager.js.map +1 -1
  119. package/package.json +10 -4
  120. package/scripts/anthropic-compare-modes.mjs +40 -3
  121. package/scripts/antigravity-smoke.mjs +180 -0
  122. package/scripts/backfill-apply-patch-exec-errorsamples.mjs +225 -0
  123. package/scripts/compare-codex-rccx.mjs +59 -1
  124. package/scripts/compare-responses-request.mjs +50 -4
  125. package/scripts/lib/errorsamples.mjs +23 -0
  126. package/scripts/mock-provider/run-regressions.mjs +12 -2
  127. package/scripts/policy-violations-report.mjs +257 -0
  128. package/scripts/publish-rcc.mjs +16 -2
  129. package/scripts/tests/unified-hub-responses-enforce-safe.mjs +37 -0
  130. package/scripts/tests/unified-hub-shadow-regression.mjs +55 -0
  131. package/scripts/unified-hub-shadow-compare.mjs +359 -0
  132. package/scripts/verify-e2e-gemini-followup-sample.mjs +269 -0
  133. package/scripts/virtual-router-shadow-v2-real.mjs +71 -1
  134. package/scripts/virtual-router-shadow-v2.mjs +41 -0
@@ -0,0 +1,257 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Report Unified Hub policy violations/enforcement rewrites captured under:
4
+ * ~/.routecodex/codex-samples/__policy_violations__/
5
+ *
6
+ * This is intended for day-to-day monitoring when policy is enabled by default.
7
+ */
8
+
9
+ import fs from 'node:fs/promises';
10
+ import os from 'node:os';
11
+ import path from 'node:path';
12
+
13
+ function usage() {
14
+ console.log(`Usage:
15
+ node scripts/policy-violations-report.mjs [options]
16
+
17
+ Options:
18
+ --root <dir> default: ~/.routecodex/codex-samples/__policy_violations__
19
+ --since-hours <n> only include files modified in last N hours
20
+ --limit <n> limit printed rows per section (default: 30)
21
+ --fail exit 1 if any records found
22
+ --help show help
23
+ `);
24
+ }
25
+
26
+ function parseArgs(argv) {
27
+ const out = {
28
+ root: path.join(os.homedir(), '.routecodex', 'errorsamples', 'policy'),
29
+ sinceHours: undefined,
30
+ limit: 30,
31
+ fail: false
32
+ };
33
+ for (let i = 2; i < argv.length; i += 1) {
34
+ const a = argv[i];
35
+ if (a === '--root' && i + 1 < argv.length) out.root = argv[++i];
36
+ else if (a === '--since-hours' && i + 1 < argv.length) out.sinceHours = Number(argv[++i]);
37
+ else if (a === '--limit' && i + 1 < argv.length) out.limit = Number(argv[++i]);
38
+ else if (a === '--fail') out.fail = true;
39
+ else if (a === '--help' || a === '-h') out.help = true;
40
+ else {
41
+ console.error(`Unknown arg: ${a}`);
42
+ out.help = true;
43
+ }
44
+ }
45
+ return out;
46
+ }
47
+
48
+ async function fileExists(p) {
49
+ try {
50
+ await fs.access(p);
51
+ return true;
52
+ } catch {
53
+ return false;
54
+ }
55
+ }
56
+
57
+ async function walk(dir) {
58
+ const out = [];
59
+ const stack = [dir];
60
+ while (stack.length) {
61
+ const current = stack.pop();
62
+ let entries = [];
63
+ try {
64
+ entries = await fs.readdir(current, { withFileTypes: true });
65
+ } catch {
66
+ continue;
67
+ }
68
+ for (const ent of entries) {
69
+ const p = path.join(current, ent.name);
70
+ if (ent.isDirectory()) stack.push(p);
71
+ else if (ent.isFile() && ent.name.endsWith('.json')) out.push(p);
72
+ }
73
+ }
74
+ return out;
75
+ }
76
+
77
+ function inc(map, key, by = 1) {
78
+ map.set(key, (map.get(key) || 0) + by);
79
+ }
80
+
81
+ function topN(map, n) {
82
+ return [...map.entries()].sort((a, b) => b[1] - a[1]).slice(0, n);
83
+ }
84
+
85
+ async function readJson(p) {
86
+ try {
87
+ const raw = await fs.readFile(p, 'utf8');
88
+ return JSON.parse(raw);
89
+ } catch {
90
+ return null;
91
+ }
92
+ }
93
+
94
+ function classifyRecord(obj) {
95
+ if (!obj || typeof obj !== 'object') return { kind: 'unknown' };
96
+ const o = obj;
97
+ if (Array.isArray(o.violations) || (o.summary && typeof o.summary === 'object')) return { kind: 'observe' };
98
+ if (Array.isArray(o.removedTopLevelKeys) || Array.isArray(o.flattenedWrappers)) return { kind: 'enforce' };
99
+ return { kind: 'unknown' };
100
+ }
101
+
102
+ function safeString(value) {
103
+ return typeof value === 'string' && value.trim() ? value.trim() : '';
104
+ }
105
+
106
+ function inferStageFromFilename(filePath) {
107
+ const base = path.basename(filePath, '.json');
108
+ return base.replace(/_[0-9]+$/, '');
109
+ }
110
+
111
+ function fmtRow(cols, widths) {
112
+ return cols
113
+ .map((c, i) => {
114
+ const w = widths[i] || 20;
115
+ const s = String(c ?? '');
116
+ return s.length > w ? `${s.slice(0, Math.max(0, w - 1))}…` : s.padEnd(w, ' ');
117
+ })
118
+ .join(' ');
119
+ }
120
+
121
+ async function main() {
122
+ const args = parseArgs(process.argv);
123
+ if (args.help) {
124
+ usage();
125
+ process.exit(0);
126
+ }
127
+ let root = path.resolve(args.root);
128
+ if (!(await fileExists(root))) {
129
+ const fallback = path.join(os.homedir(), '.routecodex', 'codex-samples', '__policy_violations__');
130
+ if (await fileExists(fallback)) {
131
+ root = fallback;
132
+ } else {
133
+ console.log(`[policy-report] no folder: ${root}`);
134
+ process.exit(0);
135
+ }
136
+ }
137
+
138
+ const sinceMs =
139
+ typeof args.sinceHours === 'number' && Number.isFinite(args.sinceHours) && args.sinceHours > 0
140
+ ? Date.now() - args.sinceHours * 60 * 60 * 1000
141
+ : null;
142
+
143
+ const files = await walk(root);
144
+ const rows = [];
145
+ for (const file of files) {
146
+ let st;
147
+ try {
148
+ st = await fs.stat(file);
149
+ } catch {
150
+ continue;
151
+ }
152
+ if (sinceMs !== null && st.mtimeMs < sinceMs) continue;
153
+ const obj = await readJson(file);
154
+ if (!obj) continue;
155
+ const rel = path.relative(root, file);
156
+ const parts = rel.split(path.sep);
157
+ const endpointFolder = parts[0] || '';
158
+ const providerKey = parts[1] || '';
159
+ const requestId = parts[2] || '';
160
+ rows.push({
161
+ file,
162
+ rel,
163
+ endpointFolder,
164
+ providerKey,
165
+ requestId,
166
+ stage: safeString(obj?.stage) || safeString(obj?.meta?.stage) || inferStageFromFilename(file),
167
+ protocol: safeString(obj?.providerProtocol) || safeString(obj?.protocol),
168
+ kind: classifyRecord(obj).kind,
169
+ obj
170
+ });
171
+ }
172
+
173
+ console.log(`[policy-report] root=${root}`);
174
+ if (sinceMs !== null) {
175
+ console.log(`[policy-report] sinceHours=${args.sinceHours}`);
176
+ }
177
+ console.log(`[policy-report] records=${rows.length}`);
178
+ if (!rows.length) {
179
+ process.exit(0);
180
+ }
181
+
182
+ const byStage = new Map();
183
+ const byProtocol = new Map();
184
+ const violationPathCounts = new Map();
185
+ const wrapperCounts = new Map();
186
+ const removedKeyCounts = new Map();
187
+
188
+ for (const r of rows) {
189
+ inc(byStage, r.stage);
190
+ if (r.protocol) inc(byProtocol, r.protocol);
191
+
192
+ if (r.kind === 'observe' && Array.isArray(r.obj?.violations)) {
193
+ for (const v of r.obj.violations) {
194
+ const p = safeString(v?.path) || '(unknown)';
195
+ inc(violationPathCounts, p);
196
+ }
197
+ }
198
+ if (r.kind === 'enforce') {
199
+ const flattened = Array.isArray(r.obj?.flattenedWrappers) ? r.obj.flattenedWrappers : [];
200
+ for (const w of flattened) inc(wrapperCounts, String(w));
201
+ const removed = Array.isArray(r.obj?.removedTopLevelKeys) ? r.obj.removedTopLevelKeys : [];
202
+ for (const k of removed) inc(removedKeyCounts, String(k));
203
+ }
204
+ }
205
+
206
+ const limit = Number.isFinite(args.limit) && args.limit > 0 ? args.limit : 30;
207
+
208
+ console.log('\n[policy-report] top stages:');
209
+ for (const [k, v] of topN(byStage, limit)) {
210
+ console.log(`- ${k}: ${v}`);
211
+ }
212
+
213
+ console.log('\n[policy-report] top protocols:');
214
+ for (const [k, v] of topN(byProtocol, limit)) {
215
+ console.log(`- ${k}: ${v}`);
216
+ }
217
+
218
+ if (violationPathCounts.size) {
219
+ console.log('\n[policy-report] top violation paths:');
220
+ for (const [k, v] of topN(violationPathCounts, limit)) {
221
+ console.log(`- ${k}: ${v}`);
222
+ }
223
+ }
224
+
225
+ if (wrapperCounts.size) {
226
+ console.log('\n[policy-report] top flattened wrappers (enforce):');
227
+ for (const [k, v] of topN(wrapperCounts, limit)) {
228
+ console.log(`- ${k}: ${v}`);
229
+ }
230
+ }
231
+
232
+ if (removedKeyCounts.size) {
233
+ console.log('\n[policy-report] top removed keys (enforce):');
234
+ for (const [k, v] of topN(removedKeyCounts, limit)) {
235
+ console.log(`- ${k}: ${v}`);
236
+ }
237
+ }
238
+
239
+ console.log('\n[policy-report] newest records:');
240
+ const newest = rows
241
+ .slice()
242
+ .sort((a, b) => (a.file < b.file ? 1 : -1))
243
+ .slice(0, Math.min(limit, rows.length));
244
+ console.log(fmtRow(['endpoint', 'providerKey', 'stage', 'protocol', 'requestId'], [16, 28, 40, 18, 24]));
245
+ for (const r of newest) {
246
+ console.log(fmtRow([r.endpointFolder, r.providerKey, r.stage, r.protocol || '-', r.requestId], [16, 28, 40, 18, 24]));
247
+ }
248
+
249
+ if (args.fail) {
250
+ process.exit(1);
251
+ }
252
+ }
253
+
254
+ main().catch((err) => {
255
+ console.error('[policy-report] failed:', err);
256
+ process.exit(2);
257
+ });
@@ -8,6 +8,7 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url));
8
8
  const PROJECT_ROOT = path.resolve(__dirname, '..');
9
9
  const PACK_SCRIPT = path.join(PROJECT_ROOT, 'scripts', 'pack-mode.mjs');
10
10
  const pkgPath = path.join(PROJECT_ROOT, 'package.json');
11
+ const llmsPath = path.join(PROJECT_ROOT, 'node_modules', '@jsonstudio', 'llms');
11
12
 
12
13
  function run(command, args, options = {}) {
13
14
  const res = spawnSync(command, args, { stdio: 'inherit', ...options });
@@ -17,6 +18,14 @@ function run(command, args, options = {}) {
17
18
  }
18
19
 
19
20
  try {
21
+ const hadDevLink = (() => {
22
+ try {
23
+ return fs.lstatSync(llmsPath).isSymbolicLink();
24
+ } catch {
25
+ return false;
26
+ }
27
+ })();
28
+
20
29
  // 1) 使用 release 模式构建 dist(依赖 npm 上的 @jsonstudio/llms)
21
30
  run('npm', ['run', 'build:min'], {
22
31
  cwd: PROJECT_ROOT,
@@ -39,8 +48,13 @@ try {
39
48
  // 3) 发布 npm 包
40
49
  run('npm', ['publish', tarballName], { cwd: PROJECT_ROOT });
41
50
 
42
- // 4) pack-mode 会在内部检测 dev 链接并调用 ensure-llmswitch-mode 恢复 dev 模式,
43
- // 因此此处不再额外修改 BUILD_MODE 或重新 link。后续本地如需 dev build,可单独运行 `npm run build:dev`。
51
+ // 4) 发布结束后恢复 dev 模式(routecodex 约定始终为 dev CLI;rcc 发布时才切 release)。
52
+ if (hadDevLink) {
53
+ run('npm', ['run', 'llmswitch:ensure'], {
54
+ cwd: PROJECT_ROOT,
55
+ env: { ...process.env, BUILD_MODE: 'dev' }
56
+ });
57
+ }
44
58
  } catch (err) {
45
59
  console.error('[publish-rcc] failed:', err.message);
46
60
  process.exit(1);
@@ -0,0 +1,37 @@
1
+ #!/usr/bin/env node
2
+ import path from 'node:path';
3
+ import { spawnSync } from 'node:child_process';
4
+
5
+ function runCase(args) {
6
+ const nodeArgs = ['scripts/unified-hub-shadow-compare.mjs', ...args];
7
+ const result = spawnSync(process.execPath, nodeArgs, {
8
+ cwd: path.resolve(path.dirname(new URL(import.meta.url).pathname), '..', '..'),
9
+ stdio: 'inherit'
10
+ });
11
+ if (result.status !== 0) {
12
+ throw new Error(`shadow compare failed: ${nodeArgs.join(' ')}`);
13
+ }
14
+ }
15
+
16
+ function main() {
17
+ const repoRoot = path.resolve(path.dirname(new URL(import.meta.url).pathname), '..', '..');
18
+ const fixturesDir = path.join(repoRoot, 'tests', 'fixtures', 'unified-hub');
19
+
20
+ runCase([
21
+ '--request',
22
+ path.join(fixturesDir, 'responses.clean.json'),
23
+ '--entry-endpoint',
24
+ '/v1/responses',
25
+ '--route-hint',
26
+ 'responses',
27
+ '--baseline-mode',
28
+ 'off',
29
+ '--candidate-mode',
30
+ 'enforce'
31
+ ]);
32
+
33
+ console.log('[unified-hub-responses-enforce-safe] OK');
34
+ }
35
+
36
+ main();
37
+
@@ -0,0 +1,55 @@
1
+ #!/usr/bin/env node
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
4
+ import { spawnSync } from 'node:child_process';
5
+
6
+ function runCase(args) {
7
+ const nodeArgs = ['scripts/unified-hub-shadow-compare.mjs', ...args];
8
+ const result = spawnSync(process.execPath, nodeArgs, {
9
+ cwd: path.resolve(path.dirname(new URL(import.meta.url).pathname), '..', '..'),
10
+ stdio: 'inherit'
11
+ });
12
+ if (result.status !== 0) {
13
+ throw new Error(`shadow compare failed: ${nodeArgs.join(' ')}`);
14
+ }
15
+ }
16
+
17
+ function main() {
18
+ const repoRoot = path.resolve(path.dirname(new URL(import.meta.url).pathname), '..', '..');
19
+ const fixturesDir = path.join(repoRoot, 'tests', 'fixtures', 'unified-hub');
20
+ if (!fs.existsSync(fixturesDir)) {
21
+ throw new Error(`fixtures dir missing: ${fixturesDir}`);
22
+ }
23
+
24
+ runCase([
25
+ '--request',
26
+ path.join(fixturesDir, 'chat.json'),
27
+ '--entry-endpoint',
28
+ '/v1/chat/completions',
29
+ '--route-hint',
30
+ 'openai'
31
+ ]);
32
+
33
+ runCase([
34
+ '--request',
35
+ path.join(fixturesDir, 'responses.json'),
36
+ '--entry-endpoint',
37
+ '/v1/responses',
38
+ '--route-hint',
39
+ 'responses'
40
+ ]);
41
+
42
+ runCase([
43
+ '--request',
44
+ path.join(fixturesDir, 'anthropic.json'),
45
+ '--entry-endpoint',
46
+ '/v1/messages',
47
+ '--route-hint',
48
+ 'anthropic'
49
+ ]);
50
+
51
+ console.log('[unified-hub-shadow-regression] OK');
52
+ }
53
+
54
+ main();
55
+