@jsonstudio/rcc 0.90.814 → 0.90.876

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 (221) hide show
  1. package/README.md +8 -0
  2. package/configsamples/provider-default/ali-coding-plan/config.v2.json +76 -0
  3. package/configsamples/provider-default/antigravity/config.v2.json +142 -0
  4. package/configsamples/provider-default/ark-coding-plan/config.v2.json +64 -0
  5. package/configsamples/provider-default/crs/config.v2.json +54 -0
  6. package/configsamples/provider-default/deepseek-web/config.v2.json +56 -0
  7. package/configsamples/provider-default/gemini/config.v2.json +43 -0
  8. package/configsamples/provider-default/gemini-cli/config.v2.json +45 -0
  9. package/configsamples/provider-default/gemini-native/config.v2.json +208 -0
  10. package/configsamples/provider-default/glm/config.v2.json +33 -0
  11. package/configsamples/provider-default/glm-anthropic/config.v2.json +29 -0
  12. package/configsamples/provider-default/kimi/config.v2.json +25 -0
  13. package/configsamples/provider-default/lmstudio/config.v2.json +79 -0
  14. package/configsamples/provider-default/lmstudio-proxy/config.v2.json +78 -0
  15. package/configsamples/provider-default/manifest.json +31 -0
  16. package/configsamples/provider-default/meituan/config.v2.json +20 -0
  17. package/configsamples/provider-default/mimo/config.v2.json +26 -0
  18. package/configsamples/provider-default/modelscope/config.v2.json +81 -0
  19. package/configsamples/provider-default/my-openai/config.v2.json +20 -0
  20. package/configsamples/provider-default/nvidia/config.v2.json +32 -0
  21. package/configsamples/provider-default/opencode-zen-free/config.v2.json +56 -0
  22. package/configsamples/provider-default/openrouter/config.v2.json +210 -0
  23. package/configsamples/provider-default/qwen/config.v2.json +38 -0
  24. package/configsamples/provider-default/qwenchat/config.v2.json +53 -0
  25. package/configsamples/provider-default/tab/config.v2.json +26 -0
  26. package/configsamples/provider-default/tabglm/config.v2.json +77 -0
  27. package/dist/build-info.js +2 -2
  28. package/dist/cli/commands/config.d.ts +5 -0
  29. package/dist/cli/commands/config.js +369 -1
  30. package/dist/cli/commands/config.js.map +1 -1
  31. package/dist/cli/commands/examples.js +3 -0
  32. package/dist/cli/commands/examples.js.map +1 -1
  33. package/dist/cli/commands/init.js +25 -1
  34. package/dist/cli/commands/init.js.map +1 -1
  35. package/dist/cli/commands/launcher-kernel.js +122 -46
  36. package/dist/cli/commands/launcher-kernel.js.map +1 -1
  37. package/dist/cli/commands/start.js +60 -3
  38. package/dist/cli/commands/start.js.map +1 -1
  39. package/dist/cli/config/bundled-provider-pack.d.ts +20 -0
  40. package/dist/cli/config/bundled-provider-pack.js +146 -0
  41. package/dist/cli/config/bundled-provider-pack.js.map +1 -0
  42. package/dist/cli/register/status-config-commands.d.ts +2 -0
  43. package/dist/cli/register/status-config-commands.js.map +1 -1
  44. package/dist/cli.js +81 -28
  45. package/dist/cli.js.map +1 -1
  46. package/dist/debug/snapshot-store.js +2 -1
  47. package/dist/debug/snapshot-store.js.map +1 -1
  48. package/dist/index.js +23 -14
  49. package/dist/index.js.map +1 -1
  50. package/dist/manager/modules/quota/provider-quota-daemon.model-backoff.js +1 -1
  51. package/dist/manager/modules/quota/provider-quota-daemon.model-backoff.js.map +1 -1
  52. package/dist/manager/quota/provider-quota-center.js +1 -1
  53. package/dist/manager/quota/provider-quota-center.js.map +1 -1
  54. package/dist/manager/storage/file-store.js +10 -0
  55. package/dist/manager/storage/file-store.js.map +1 -1
  56. package/dist/modules/llmswitch/bridge/snapshot-recorder-runtime.js +18 -1
  57. package/dist/modules/llmswitch/bridge/snapshot-recorder-runtime.js.map +1 -1
  58. package/dist/modules/llmswitch/bridge/snapshot-recorder.js +132 -51
  59. package/dist/modules/llmswitch/bridge/snapshot-recorder.js.map +1 -1
  60. package/dist/provider-sdk/provider-runtime-inference.js +2 -2
  61. package/dist/provider-sdk/provider-runtime-inference.js.map +1 -1
  62. package/dist/providers/auth/deepseek-account-token-acquirer.js +32 -3
  63. package/dist/providers/auth/deepseek-account-token-acquirer.js.map +1 -1
  64. package/dist/providers/core/api/provider-types.d.ts +11 -0
  65. package/dist/providers/core/config/service-profiles.js +1 -1
  66. package/dist/providers/core/runtime/deepseek-http-provider.d.ts +2 -0
  67. package/dist/providers/core/runtime/deepseek-http-provider.js +31 -1
  68. package/dist/providers/core/runtime/deepseek-http-provider.js.map +1 -1
  69. package/dist/providers/core/runtime/qwenchat-http-provider-helpers.d.ts +3 -2
  70. package/dist/providers/core/runtime/qwenchat-http-provider-helpers.js +513 -96
  71. package/dist/providers/core/runtime/qwenchat-http-provider-helpers.js.map +1 -1
  72. package/dist/providers/core/runtime/standard-tool-text-harvest.d.ts +8 -0
  73. package/dist/providers/core/runtime/standard-tool-text-harvest.js +24 -0
  74. package/dist/providers/core/runtime/standard-tool-text-harvest.js.map +1 -0
  75. package/dist/providers/core/runtime/standard-tool-text-request-transform.d.ts +4 -1
  76. package/dist/providers/core/runtime/standard-tool-text-request-transform.js +129 -3
  77. package/dist/providers/core/runtime/standard-tool-text-request-transform.js.map +1 -1
  78. package/dist/providers/core/utils/snapshot-writer.js +5 -2
  79. package/dist/providers/core/utils/snapshot-writer.js.map +1 -1
  80. package/dist/providers/profile/provider-profile-loader.js +52 -1
  81. package/dist/providers/profile/provider-profile-loader.js.map +1 -1
  82. package/dist/providers/profile/provider-profile.d.ts +3 -0
  83. package/dist/server/handlers/handler-response-utils.js +1 -0
  84. package/dist/server/handlers/handler-response-utils.js.map +1 -1
  85. package/dist/server/handlers/images-handler.d.ts +9 -0
  86. package/dist/server/handlers/images-handler.js +258 -0
  87. package/dist/server/handlers/images-handler.js.map +1 -0
  88. package/dist/server/handlers/types.d.ts +7 -0
  89. package/dist/server/runtime/http-server/antigravity-startup-tasks.d.ts +3 -0
  90. package/dist/server/runtime/http-server/antigravity-startup-tasks.js +16 -0
  91. package/dist/server/runtime/http-server/antigravity-startup-tasks.js.map +1 -1
  92. package/dist/server/runtime/http-server/daemon-admin/auth-handler.js +3 -18
  93. package/dist/server/runtime/http-server/daemon-admin/auth-handler.js.map +1 -1
  94. package/dist/server/runtime/http-server/daemon-admin/providers-handler-utils.d.ts +7 -0
  95. package/dist/server/runtime/http-server/daemon-admin/providers-handler-utils.js +17 -0
  96. package/dist/server/runtime/http-server/daemon-admin/providers-handler-utils.js.map +1 -1
  97. package/dist/server/runtime/http-server/daemon-admin/providers-handler.js +50 -17
  98. package/dist/server/runtime/http-server/daemon-admin/providers-handler.js.map +1 -1
  99. package/dist/server/runtime/http-server/daemon-admin-routes.js +32 -2
  100. package/dist/server/runtime/http-server/daemon-admin-routes.js.map +1 -1
  101. package/dist/server/runtime/http-server/executor/provider-response-converter.js +42 -13
  102. package/dist/server/runtime/http-server/executor/provider-response-converter.js.map +1 -1
  103. package/dist/server/runtime/http-server/executor/provider-response-utils.js +41 -3
  104. package/dist/server/runtime/http-server/executor/provider-response-utils.js.map +1 -1
  105. package/dist/server/runtime/http-server/executor/usage-aggregator.js +7 -7
  106. package/dist/server/runtime/http-server/executor/usage-aggregator.js.map +1 -1
  107. package/dist/server/runtime/http-server/executor/usage-logger.d.ts +9 -0
  108. package/dist/server/runtime/http-server/executor/usage-logger.js +35 -2
  109. package/dist/server/runtime/http-server/executor/usage-logger.js.map +1 -1
  110. package/dist/server/runtime/http-server/executor-metadata.js +12 -4
  111. package/dist/server/runtime/http-server/executor-metadata.js.map +1 -1
  112. package/dist/server/runtime/http-server/executor-pipeline.js +24 -15
  113. package/dist/server/runtime/http-server/executor-pipeline.js.map +1 -1
  114. package/dist/server/runtime/http-server/executor-provider.d.ts +6 -1
  115. package/dist/server/runtime/http-server/executor-provider.js +137 -5
  116. package/dist/server/runtime/http-server/executor-provider.js.map +1 -1
  117. package/dist/server/runtime/http-server/http-server-bootstrap.js +6 -0
  118. package/dist/server/runtime/http-server/http-server-bootstrap.js.map +1 -1
  119. package/dist/server/runtime/http-server/http-server-lifecycle.js +23 -15
  120. package/dist/server/runtime/http-server/http-server-lifecycle.js.map +1 -1
  121. package/dist/server/runtime/http-server/http-server-runtime-providers.js +14 -4
  122. package/dist/server/runtime/http-server/http-server-runtime-providers.js.map +1 -1
  123. package/dist/server/runtime/http-server/http-server-runtime-setup.js +83 -1
  124. package/dist/server/runtime/http-server/http-server-runtime-setup.js.map +1 -1
  125. package/dist/server/runtime/http-server/hub-shadow-compare.js +2 -41
  126. package/dist/server/runtime/http-server/hub-shadow-compare.js.map +1 -1
  127. package/dist/server/runtime/http-server/provider-routing-scope.d.ts +9 -0
  128. package/dist/server/runtime/http-server/provider-routing-scope.js +20 -0
  129. package/dist/server/runtime/http-server/provider-routing-scope.js.map +1 -0
  130. package/dist/server/runtime/http-server/provider-traffic-governor.d.ts +67 -0
  131. package/dist/server/runtime/http-server/provider-traffic-governor.js +467 -0
  132. package/dist/server/runtime/http-server/provider-traffic-governor.js.map +1 -0
  133. package/dist/server/runtime/http-server/request-executor.d.ts +8 -0
  134. package/dist/server/runtime/http-server/request-executor.js +446 -21
  135. package/dist/server/runtime/http-server/request-executor.js.map +1 -1
  136. package/dist/server/runtime/http-server/routes.js +13 -0
  137. package/dist/server/runtime/http-server/routes.js.map +1 -1
  138. package/dist/server/runtime/http-server/session-client-registry.js +30 -4
  139. package/dist/server/runtime/http-server/session-client-registry.js.map +1 -1
  140. package/dist/server/runtime/http-server/session-client-route-utils.d.ts +7 -0
  141. package/dist/server/runtime/http-server/session-client-route-utils.js +38 -0
  142. package/dist/server/runtime/http-server/session-client-route-utils.js.map +1 -1
  143. package/dist/server/runtime/http-server/session-client-routes.js +12 -2
  144. package/dist/server/runtime/http-server/session-client-routes.js.map +1 -1
  145. package/dist/server/utils/request-id-manager.js +42 -5
  146. package/dist/server/utils/request-id-manager.js.map +1 -1
  147. package/dist/server/utils/stage-logger.d.ts +1 -0
  148. package/dist/server/utils/stage-logger.js +27 -0
  149. package/dist/server/utils/stage-logger.js.map +1 -1
  150. package/dist/utils/errorsamples.js +3 -1
  151. package/dist/utils/errorsamples.js.map +1 -1
  152. package/dist/utils/sensitive-redaction.d.ts +1 -0
  153. package/dist/utils/sensitive-redaction.js +122 -0
  154. package/dist/utils/sensitive-redaction.js.map +1 -0
  155. package/dist/utils/snapshot-writer.js +162 -2
  156. package/dist/utils/snapshot-writer.js.map +1 -1
  157. package/docs/INSTALLATION_AND_QUICKSTART.md +14 -1
  158. package/docs/PORTS.md +12 -0
  159. package/docs/lmstudio-tool-calling.md +25 -0
  160. package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/qwenchat-web-request.d.ts +3 -0
  161. package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/qwenchat-web-request.js +62 -0
  162. package/node_modules/@jsonstudio/llms/dist/conversion/compat/profiles/chat-qwenchat-web.json +47 -0
  163. package/node_modules/@jsonstudio/llms/dist/conversion/hub/node-support.js +5 -2
  164. package/node_modules/@jsonstudio/llms/dist/conversion/hub/operation-table/operation-table-runner.js +68 -7
  165. package/node_modules/@jsonstudio/llms/dist/conversion/hub/operation-table/semantic-mappers/anthropic-mapper-from-chat.js +138 -3
  166. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/hub-pipeline-chat-process-request-utils.js +24 -0
  167. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/hub-pipeline-execute-chat-process-entry.js +7 -1
  168. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/hub-pipeline-execute-request-stage.js +7 -0
  169. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/hub-pipeline-heavy-input-fastpath.d.ts +24 -0
  170. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/hub-pipeline-heavy-input-fastpath.js +203 -0
  171. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/hub-pipeline-route-and-outbound.js +17 -12
  172. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/hub-stage-timing.d.ts +11 -0
  173. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/hub-stage-timing.js +82 -1
  174. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage2_semantic_map/index.js +47 -14
  175. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/stages/req_outbound/req_outbound_stage1_semantic_map/index.js +43 -0
  176. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/stages/resp_outbound/resp_outbound_stage1_client_remap/client-remap-protocol-switch.js +222 -19
  177. package/node_modules/@jsonstudio/llms/dist/conversion/hub/policy/policy-engine.js +2 -2
  178. package/node_modules/@jsonstudio/llms/dist/conversion/hub/process/chat-process-pending-tool-sync.js +24 -7
  179. package/node_modules/@jsonstudio/llms/dist/conversion/hub/response/provider-response.js +90 -1
  180. package/node_modules/@jsonstudio/llms/dist/conversion/hub/snapshot-recorder.d.ts +1 -0
  181. package/node_modules/@jsonstudio/llms/dist/conversion/hub/snapshot-recorder.js +252 -1
  182. package/node_modules/@jsonstudio/llms/dist/conversion/responses/responses-openai-bridge/utils.js +5 -3
  183. package/node_modules/@jsonstudio/llms/dist/conversion/responses/responses-openai-bridge.js +44 -4
  184. package/node_modules/@jsonstudio/llms/dist/conversion/shared/anthropic-message-utils-openai-request.d.ts +3 -1
  185. package/node_modules/@jsonstudio/llms/dist/conversion/shared/anthropic-message-utils-openai-request.js +20 -23
  186. package/node_modules/@jsonstudio/llms/dist/conversion/shared/tool-governor.js +68 -30
  187. package/node_modules/@jsonstudio/llms/dist/conversion/snapshot-utils.js +194 -10
  188. package/node_modules/@jsonstudio/llms/dist/native/router_hotpath_napi.node +0 -0
  189. package/node_modules/@jsonstudio/llms/dist/quota/quota-state.js +2 -2
  190. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine/routing-state/store.js +35 -2
  191. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine.js +9 -9
  192. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/sticky-session-store.js +104 -18
  193. package/node_modules/@jsonstudio/llms/dist/servertool/engine.js +79 -32
  194. package/node_modules/@jsonstudio/llms/dist/servertool/handlers/vision.js +49 -0
  195. package/node_modules/@jsonstudio/llms/dist/servertool/pending-session.js +48 -2
  196. package/node_modules/@jsonstudio/llms/dist/servertool/server-side-tools.js +14 -1
  197. package/node_modules/@jsonstudio/llms/dist/servertool/types.d.ts +1 -0
  198. package/node_modules/@jsonstudio/llms/package.json +1 -1
  199. package/node_modules/ajv/dist/compile/jtd/serialize.js +9 -2
  200. package/node_modules/ajv/dist/compile/jtd/serialize.js.map +1 -1
  201. package/node_modules/ajv/dist/core.d.ts +1 -0
  202. package/node_modules/ajv/dist/core.js.map +1 -1
  203. package/node_modules/ajv/dist/vocabularies/validation/pattern.js +13 -4
  204. package/node_modules/ajv/dist/vocabularies/validation/pattern.js.map +1 -1
  205. package/node_modules/ajv/lib/compile/jtd/serialize.ts +13 -2
  206. package/node_modules/ajv/lib/core.ts +1 -0
  207. package/node_modules/ajv/lib/vocabularies/validation/pattern.ts +15 -4
  208. package/node_modules/ajv/package.json +2 -1
  209. package/package.json +15 -10
  210. package/scripts/ci/repo-sanity.mjs +23 -2
  211. package/scripts/ci/secrets-check.mjs +48 -0
  212. package/scripts/ci/silent-failure-audit.mjs +192 -0
  213. package/scripts/mock-provider/run-regressions.mjs +1 -0
  214. package/scripts/monitor/memory-guard.mjs +207 -0
  215. package/scripts/pack-mode.mjs +32 -36
  216. package/scripts/publish-rcc.mjs +38 -60
  217. package/scripts/tests/apply-patch-loop.mjs +1 -0
  218. package/scripts/tests/blackbox-rcc-vs-routecodex-antigravity.mjs +2 -0
  219. package/scripts/tools-dev/responses-debug-client/src/index.ts +8 -3
  220. package/scripts/verify-e2e-toolcall.mjs +1 -0
  221. package/scripts/verify-install-e2e.mjs +2 -1
@@ -0,0 +1,207 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * RouteCodex memory guard (PID-scoped, no broad kill).
4
+ *
5
+ * Usage:
6
+ * node scripts/monitor/memory-guard.mjs --port 5555 --rss-mb 8192
7
+ * node scripts/monitor/memory-guard.mjs --port 5555 --rss-mb 4096 --action restart
8
+ * node scripts/monitor/memory-guard.mjs --port 5555 --rss-mb 2048 --once
9
+ */
10
+
11
+ import { execSync, spawnSync } from 'node:child_process';
12
+
13
+ function parseArgs(argv) {
14
+ const options = {
15
+ port: 5555,
16
+ rssMb: 8192,
17
+ intervalMs: 2000,
18
+ graceMs: 5000,
19
+ action: 'kill', // kill | restart
20
+ once: false
21
+ };
22
+ const args = argv.slice(2);
23
+ for (let i = 0; i < args.length; i += 1) {
24
+ const arg = args[i];
25
+ if (arg === '--port' && i + 1 < args.length) {
26
+ options.port = Number.parseInt(String(args[++i]), 10);
27
+ continue;
28
+ }
29
+ if (arg === '--rss-mb' && i + 1 < args.length) {
30
+ options.rssMb = Number.parseInt(String(args[++i]), 10);
31
+ continue;
32
+ }
33
+ if (arg === '--interval-ms' && i + 1 < args.length) {
34
+ options.intervalMs = Number.parseInt(String(args[++i]), 10);
35
+ continue;
36
+ }
37
+ if (arg === '--grace-ms' && i + 1 < args.length) {
38
+ options.graceMs = Number.parseInt(String(args[++i]), 10);
39
+ continue;
40
+ }
41
+ if (arg === '--action' && i + 1 < args.length) {
42
+ const action = String(args[++i]).trim().toLowerCase();
43
+ options.action = action === 'restart' ? 'restart' : 'kill';
44
+ continue;
45
+ }
46
+ if (arg === '--once') {
47
+ options.once = true;
48
+ continue;
49
+ }
50
+ }
51
+ if (!Number.isFinite(options.port) || options.port <= 0) {
52
+ throw new Error(`invalid --port: ${options.port}`);
53
+ }
54
+ if (!Number.isFinite(options.rssMb) || options.rssMb <= 0) {
55
+ throw new Error(`invalid --rss-mb: ${options.rssMb}`);
56
+ }
57
+ if (!Number.isFinite(options.intervalMs) || options.intervalMs < 200) {
58
+ options.intervalMs = 2000;
59
+ }
60
+ if (!Number.isFinite(options.graceMs) || options.graceMs < 0) {
61
+ options.graceMs = 5000;
62
+ }
63
+ return options;
64
+ }
65
+
66
+ function nowIso() {
67
+ return new Date().toISOString();
68
+ }
69
+
70
+ function log(line) {
71
+ console.log(`[${nowIso()}] [memory-guard] ${line}`);
72
+ }
73
+
74
+ function runStdout(command) {
75
+ try {
76
+ return String(execSync(command, { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }) || '').trim();
77
+ } catch {
78
+ return '';
79
+ }
80
+ }
81
+
82
+ function resolveListenerPid(port) {
83
+ const out = runStdout(`lsof -t -nP -iTCP:${port} -sTCP:LISTEN | head -n 1`);
84
+ const pid = Number.parseInt(out, 10);
85
+ return Number.isFinite(pid) && pid > 0 ? pid : null;
86
+ }
87
+
88
+ function readPidCommand(pid) {
89
+ return runStdout(`ps -o command= -p ${pid}`);
90
+ }
91
+
92
+ function readPidRssMb(pid) {
93
+ const out = runStdout(`ps -o rss= -p ${pid}`);
94
+ const rssKb = Number.parseInt(out, 10);
95
+ if (!Number.isFinite(rssKb) || rssKb <= 0) {
96
+ return null;
97
+ }
98
+ return Math.round((rssKb / 1024) * 10) / 10;
99
+ }
100
+
101
+ function isPidAlive(pid) {
102
+ try {
103
+ process.kill(pid, 0);
104
+ return true;
105
+ } catch {
106
+ return false;
107
+ }
108
+ }
109
+
110
+ async function sleep(ms) {
111
+ await new Promise((resolve) => setTimeout(resolve, ms));
112
+ }
113
+
114
+ function isLikelyRouteCodexProcess(commandText) {
115
+ const text = String(commandText || '').toLowerCase();
116
+ return (
117
+ text.includes('routecodex')
118
+ || text.includes('dist/index.js')
119
+ || (text.includes('node') && text.includes('rcc'))
120
+ );
121
+ }
122
+
123
+ async function terminatePidScoped(pid, graceMs) {
124
+ log(`threshold exceeded, terminate pid=${pid} with SIGTERM`);
125
+ try {
126
+ process.kill(pid, 'SIGTERM');
127
+ } catch (error) {
128
+ log(`SIGTERM failed for pid=${pid}: ${error instanceof Error ? error.message : String(error)}`);
129
+ return;
130
+ }
131
+ const deadline = Date.now() + graceMs;
132
+ while (Date.now() < deadline) {
133
+ if (!isPidAlive(pid)) {
134
+ log(`pid=${pid} exited after SIGTERM`);
135
+ return;
136
+ }
137
+ await sleep(250);
138
+ }
139
+ if (isPidAlive(pid)) {
140
+ log(`pid=${pid} still alive after ${graceMs}ms, escalate SIGKILL`);
141
+ try {
142
+ process.kill(pid, 'SIGKILL');
143
+ } catch (error) {
144
+ log(`SIGKILL failed for pid=${pid}: ${error instanceof Error ? error.message : String(error)}`);
145
+ return;
146
+ }
147
+ }
148
+ }
149
+
150
+ function restartRouteCodex(port) {
151
+ log(`attempt restart on port=${port}`);
152
+ const result = spawnSync('routecodex', ['restart', '--port', String(port)], {
153
+ stdio: 'inherit'
154
+ });
155
+ if ((result.status ?? 1) !== 0) {
156
+ log(`restart failed with status=${result.status ?? -1}`);
157
+ } else {
158
+ log('restart completed');
159
+ }
160
+ }
161
+
162
+ async function evaluateOnce(options) {
163
+ const pid = resolveListenerPid(options.port);
164
+ if (!pid) {
165
+ log(`no listener found on port=${options.port}`);
166
+ return;
167
+ }
168
+ const cmd = readPidCommand(pid);
169
+ const rssMb = readPidRssMb(pid);
170
+ if (!isLikelyRouteCodexProcess(cmd)) {
171
+ log(`skip pid=${pid}, command does not look like RouteCodex: ${cmd}`);
172
+ return;
173
+ }
174
+ if (rssMb === null) {
175
+ log(`pid=${pid} rss unavailable`);
176
+ return;
177
+ }
178
+ log(`pid=${pid} rss=${rssMb}MB threshold=${options.rssMb}MB`);
179
+ if (rssMb < options.rssMb) {
180
+ return;
181
+ }
182
+ await terminatePidScoped(pid, options.graceMs);
183
+ if (options.action === 'restart') {
184
+ restartRouteCodex(options.port);
185
+ }
186
+ }
187
+
188
+ async function main() {
189
+ const options = parseArgs(process.argv);
190
+ log(
191
+ `start port=${options.port} rssMb=${options.rssMb} intervalMs=${options.intervalMs} action=${options.action} once=${options.once}`
192
+ );
193
+ if (options.once) {
194
+ await evaluateOnce(options);
195
+ return;
196
+ }
197
+ while (true) {
198
+ await evaluateOnce(options);
199
+ await sleep(options.intervalMs);
200
+ }
201
+ }
202
+
203
+ main().catch((error) => {
204
+ log(`fatal: ${error instanceof Error ? error.message : String(error)}`);
205
+ process.exit(1);
206
+ });
207
+
@@ -62,18 +62,36 @@ function installLocalLlmsFromTarball() {
62
62
  if ((pack.status ?? 0) !== 0) {
63
63
  throw new Error(`npm pack ${localLlmsDir} failed`);
64
64
  }
65
- const lines = String(pack.stdout || '')
66
- .split('\n')
67
- .map((line) => line.trim())
68
- .filter(Boolean);
69
- const tarballName = lines[lines.length - 1];
70
- if (!tarballName) {
71
- throw new Error('npm pack local llms produced empty tarball name');
72
- }
73
- const tarballPath = path.join(tmpDir, tarballName);
74
- if (!exists(tarballPath)) {
75
- throw new Error(`local llms tarball missing: ${tarballPath}`);
65
+
66
+ const streamText = `${String(pack.stdout || '')}\n${String(pack.stderr || '')}`;
67
+ const candidates = Array.from(
68
+ new Set(
69
+ streamText
70
+ .split(/\s+/)
71
+ .map((token) => token.trim())
72
+ .filter((token) => token.endsWith('.tgz'))
73
+ )
74
+ );
75
+
76
+ const tarballsInTmp = (() => {
77
+ try {
78
+ return fs.readdirSync(tmpDir)
79
+ .filter((name) => name.endsWith('.tgz'))
80
+ .map((name) => path.join(tmpDir, name));
81
+ } catch {
82
+ return [];
83
+ }
84
+ })();
85
+
86
+ const resolvedCandidates = candidates
87
+ .map((token) => (path.isAbsolute(token) ? token : path.join(tmpDir, token)))
88
+ .filter((candidatePath) => exists(candidatePath));
89
+
90
+ const tarballPath = resolvedCandidates[0] || tarballsInTmp[0] || '';
91
+ if (!tarballPath) {
92
+ throw new Error(`local llms tarball missing (stdout=${JSON.stringify(String(pack.stdout || '').trim())})`);
76
93
  }
94
+
77
95
  runNpm(['install', '--no-audit', '--no-fund', '--no-save', tarballPath]);
78
96
  } finally {
79
97
  fs.rmSync(tmpDir, { recursive: true, force: true });
@@ -108,13 +126,10 @@ function readLocalLlmsVersion() {
108
126
 
109
127
  const isDevPkg = args.name === 'routecodex';
110
128
  const isRcc = args.name === 'rcc' || args.name === '@jsonstudio/rcc';
111
- const isRccx = args.name === '@jsonstudio/rccx';
112
129
 
113
130
  let hadDevLink = false;
114
- if (!isRccx) {
115
- hadDevLink = isSymlink(llmsPath);
116
- runEnsureMode('release');
117
- }
131
+ hadDevLink = isSymlink(llmsPath);
132
+ runEnsureMode('release');
118
133
 
119
134
  const original = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
120
135
  fs.writeFileSync(backupPath, JSON.stringify(original, null, 2));
@@ -138,7 +153,7 @@ try {
138
153
  mutated.name = args.name;
139
154
  mutated.bin = { [args.bin]: 'dist/cli.js' };
140
155
  // Ensure description mentions mode
141
- const suffix = (isRcc || isRccx) ? ' (release)' : ' (dev)';
156
+ const suffix = isRcc ? ' (release)' : ' (dev)';
142
157
  mutated.description = String(original.description || 'RouteCodex')
143
158
  .replace(/\s*\((dev|release)\)$/, '')
144
159
  .concat(suffix);
@@ -189,25 +204,6 @@ try {
189
204
  }
190
205
  mutated.files = baseFiles;
191
206
  }
192
- } else if (isRccx) {
193
- // rccx: wasm-backed llms 核心,通过 npm alias 将 @jsonstudio/llms 指向 wasm 引擎包。
194
- mutated.bundledDependencies = [];
195
- mutated.bundleDependencies = [];
196
-
197
- const deps = { ...(original.dependencies || {}) };
198
- // 移除原有 TS 版 llms 直连依赖
199
- if (deps['@jsonstudio/llms']) {
200
- delete deps['@jsonstudio/llms'];
201
- }
202
- // 推断 wasm 引擎版本,若未声明则使用本地 llms-engine 缺省版本
203
- const engineVersion = deps['@jsonstudio/llms-engine'] || '^0.3.0';
204
- deps['@jsonstudio/llms-engine'] = engineVersion;
205
- // 通过 npm alias 保持 import 形状不变
206
- deps['@jsonstudio/llms'] = `npm:@jsonstudio/llms-engine@${engineVersion}`;
207
- deps.ajv = deps.ajv || '^8.17.1';
208
- deps.zod = deps.zod || '^3.23.8';
209
-
210
- mutated.dependencies = deps;
211
207
  }
212
208
  fs.writeFileSync(pkgPath, JSON.stringify(mutated, null, 2));
213
209
 
@@ -6,98 +6,76 @@ import { fileURLToPath } from 'node:url';
6
6
 
7
7
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
8
8
  const PROJECT_ROOT = path.resolve(__dirname, '..');
9
- const PACK_SCRIPT = path.join(PROJECT_ROOT, 'scripts', 'pack-mode.mjs');
10
9
  const pkgPath = path.join(PROJECT_ROOT, 'package.json');
11
- const llmsPath = path.join(PROJECT_ROOT, 'node_modules', '@jsonstudio', 'llms');
12
- const localLlmsPkgPath = path.join(PROJECT_ROOT, 'sharedmodule', 'llmswitch-core', 'package.json');
13
10
 
14
11
  function parseArgs(argv) {
15
- const out = {};
12
+ const out = { passthrough: [] };
16
13
  for (let i = 2; i < argv.length; i++) {
17
14
  const a = argv[i];
18
15
  if (a === '--llms-tgz') { out.llmsTgz = argv[++i]; continue; }
19
16
  if (a === '--llms-version') { out.llmsVersion = argv[++i]; continue; }
17
+ if (a === '--tag') { out.tag = argv[++i]; continue; }
18
+ if (a === '--dry-run') { out.dryRun = true; continue; }
19
+ out.passthrough.push(a);
20
20
  }
21
21
  return out;
22
22
  }
23
23
 
24
- function exists(p) {
25
- try {
26
- fs.accessSync(p);
27
- return true;
28
- } catch {
29
- return false;
30
- }
31
- }
32
-
33
24
  function run(command, args, options = {}) {
34
- const res = spawnSync(command, args, { stdio: 'inherit', ...options });
25
+ const res = spawnSync(command, args, { stdio: 'inherit', cwd: PROJECT_ROOT, ...options });
35
26
  if ((res.status ?? 0) !== 0) {
36
27
  throw new Error(`${command} ${args.join(' ')} failed`);
37
28
  }
38
29
  }
39
30
 
31
+ function readPkgVersion() {
32
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
33
+ return String(pkg.version || '').trim();
34
+ }
35
+
40
36
  try {
41
37
  const args = parseArgs(process.argv);
42
- const llmsTgz = String(args.llmsTgz || process.env.RCC_LLMS_TGZ || '').trim();
43
- const llmsVersion = String(
44
- args.llmsVersion ||
45
- process.env.RCC_LLMS_VERSION ||
46
- (exists(localLlmsPkgPath) ? JSON.parse(fs.readFileSync(localLlmsPkgPath, 'utf-8')).version : '')
47
- ).trim();
48
38
 
49
- const hadDevLink = (() => {
50
- try {
51
- return fs.lstatSync(llmsPath).isSymbolicLink();
52
- } catch {
53
- return false;
54
- }
55
- })();
39
+ // 始终内联本地 llms,避免发布流程改动全局 llms link。
40
+ const env = {
41
+ ...process.env,
42
+ RCC_LLMS_INLINE_LOCAL: process.env.RCC_LLMS_INLINE_LOCAL ?? '1'
43
+ };
56
44
 
57
- if (llmsTgz) {
58
- if (!exists(llmsTgz)) {
59
- throw new Error(`--llms-tgz not found: ${llmsTgz}`);
60
- }
61
- if (hadDevLink) {
62
- run(process.execPath, [path.join(PROJECT_ROOT, 'scripts', 'link-llmswitch.mjs'), 'unlink'], { cwd: PROJECT_ROOT });
63
- }
64
- run('npm', ['install', '--no-audit', '--no-fund', '--no-save', llmsTgz], { cwd: PROJECT_ROOT });
45
+ const packArgs = ['run', 'pack:rcc', '--'];
46
+ if (args.llmsTgz) {
47
+ packArgs.push('--llms-tgz', String(args.llmsTgz));
48
+ }
49
+ if (args.llmsVersion) {
50
+ packArgs.push('--llms-version', String(args.llmsVersion));
65
51
  }
66
52
 
67
- // 1) 使用 release 模式构建 dist。若存在本地 sharedmodule/llmswitch-core,则 release 也以其为唯一真源。
68
- run('npm', ['run', 'build:min'], {
69
- cwd: PROJECT_ROOT,
70
- env: { ...process.env, BUILD_MODE: 'release', ...(llmsVersion ? { RCC_LLMS_VERSION: llmsVersion } : {}) }
71
- });
53
+ run('npm', packArgs, { env });
72
54
 
73
- // 2) 通过 pack-mode 生成 rcc tarball(内部会临时切换 package.json.name/bin,并同步 llms 版本声明)
74
- run(
75
- process.execPath,
76
- [PACK_SCRIPT, '--name', '@jsonstudio/rcc', '--bin', 'rcc'],
77
- { cwd: PROJECT_ROOT, env: { ...process.env, ...(llmsVersion ? { RCC_LLMS_VERSION: llmsVersion } : {}) } }
78
- );
55
+ const version = readPkgVersion();
56
+ if (!version) {
57
+ throw new Error('failed to read version from package.json after pack:rcc');
58
+ }
79
59
 
80
- // 构建过程中版本号可能被 bump(gen-build-info 会 auto-bump),因此需要在 pack 之后重新读取版本号
81
- const updatedPkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
82
- const version = updatedPkg.version;
83
60
  const tarballName = `jsonstudio-rcc-${version}.tgz`;
84
61
  const tarballPath = path.join(PROJECT_ROOT, tarballName);
85
-
86
62
  if (!fs.existsSync(tarballPath)) {
87
63
  throw new Error(`tarball not found: ${tarballPath}`);
88
64
  }
89
65
 
90
- // 3) 发布 npm
91
- run('npm', ['publish', tarballName], { cwd: PROJECT_ROOT });
92
-
93
- // 4) 发布结束后恢复 dev 模式(routecodex 约定始终为 dev CLI;rcc 发布时才切 release)。
94
- if (hadDevLink) {
95
- run('npm', ['run', 'llmswitch:ensure'], {
96
- cwd: PROJECT_ROOT,
97
- env: { ...process.env, BUILD_MODE: 'dev' }
98
- });
66
+ const publishArgs = ['publish', tarballName];
67
+ if (args.tag) {
68
+ publishArgs.push('--tag', String(args.tag));
99
69
  }
70
+ if (args.dryRun) {
71
+ publishArgs.push('--dry-run');
72
+ }
73
+ if (args.passthrough.length > 0) {
74
+ publishArgs.push(...args.passthrough);
75
+ }
76
+
77
+ run('npm', publishArgs);
100
78
  } catch (err) {
101
- console.error('[publish-rcc] failed:', err.message);
79
+ console.error('[publish-rcc] failed:', err instanceof Error ? err.message : String(err));
102
80
  process.exit(1);
103
81
  }
@@ -671,6 +671,7 @@ async function main() {
671
671
  configPath: file,
672
672
  env: {
673
673
  ROUTECODEX_USE_MOCK: '1',
674
+ ROUTECODEX_ALLOW_MOCK_RUNTIME: '1',
674
675
  ROUTECODEX_MOCK_CONFIG_PATH: file,
675
676
  ROUTECODEX_MOCK_SAMPLES_DIR: MOCK_SAMPLES_DIR,
676
677
  ROUTECODEX_MOCK_VALIDATE_NAMES: '1',
@@ -534,6 +534,8 @@ async function runOnceBlackbox(opts) {
534
534
  // Disable ManagerDaemon (quota/health background tasks) so the parity run is isolated and deterministic.
535
535
  ROUTECODEX_USE_MOCK: '1',
536
536
  RCC_USE_MOCK: '1',
537
+ ROUTECODEX_ALLOW_MOCK_RUNTIME: '1',
538
+ RCC_ALLOW_MOCK_RUNTIME: '1',
537
539
  // Disable token daemon + OAuth auto-open to keep the blackbox test non-interactive.
538
540
  ROUTECODEX_DISABLE_TOKEN_DAEMON: '1',
539
541
  RCC_DISABLE_TOKEN_DAEMON: '1',
@@ -10,6 +10,7 @@ import fs from 'node:fs/promises';
10
10
  import path from 'node:path';
11
11
  import process from 'node:process';
12
12
  import OpenAI from 'openai';
13
+ import { redactSensitiveData } from '../../../../src/utils/sensitive-redaction.js';
13
14
 
14
15
  type Unknown = Record<string, any>;
15
16
 
@@ -100,11 +101,11 @@ async function main() {
100
101
  const dir = path.join(String(home), '.routecodex', 'codex-samples', 'responses-client');
101
102
  await fs.mkdir(dir, { recursive: true });
102
103
  const out = path.join(dir, `${clientRequestId}_client-request.json`);
103
- await fs.writeFile(out, JSON.stringify({
104
+ await fs.writeFile(out, JSON.stringify(redactSensitiveData({
104
105
  timestamp: new Date().toISOString(),
105
106
  baseURL,
106
107
  request: reqBody
107
- }, null, 2), 'utf-8');
108
+ }), null, 2), 'utf-8');
108
109
  if (!raw) console.log(`[${nowIso()}] saved client snapshot: ${out}`);
109
110
  } catch { /* non-blocking */ }
110
111
 
@@ -130,7 +131,11 @@ async function main() {
130
131
  try {
131
132
  const dir = path.resolve(process.cwd(), 'logs', 'responses-debug', responseId || 'unknown');
132
133
  await fs.mkdir(dir, { recursive: true });
133
- await fs.appendFile(path.join(dir, 'events.jsonl'), JSON.stringify({ ts: Date.now(), ...o }) + '\n', 'utf-8');
134
+ await fs.appendFile(
135
+ path.join(dir, 'events.jsonl'),
136
+ JSON.stringify(redactSensitiveData({ ts: Date.now(), ...o })) + '\n',
137
+ 'utf-8'
138
+ );
134
139
  } catch { /* ignore */ }
135
140
  };
136
141
 
@@ -80,6 +80,7 @@ async function main() {
80
80
  };
81
81
  if (resolved.mode === 'mock') {
82
82
  serverEnv.ROUTECODEX_USE_MOCK = '1';
83
+ serverEnv.ROUTECODEX_ALLOW_MOCK_RUNTIME = '1';
83
84
  serverEnv.ROUTECODEX_MOCK_CONFIG_PATH = resolved.configPath;
84
85
  serverEnv.ROUTECODEX_MOCK_VALIDATE_NAMES = '1';
85
86
  }
@@ -145,7 +145,8 @@ async function main() {
145
145
  RCC4_CONFIG_PATH: verifyConfigPath,
146
146
  // Install verification uses a mock upstream; skip ManagerDaemon modules (token/quota) so startup
147
147
  // does not depend on external network availability.
148
- ROUTECODEX_USE_MOCK: '1'
148
+ ROUTECODEX_USE_MOCK: '1',
149
+ ROUTECODEX_ALLOW_MOCK_RUNTIME: '1'
149
150
  };
150
151
  const server = spawn(process.execPath, serverArgs, {
151
152
  env,