@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.
- package/README.md +8 -0
- package/configsamples/provider-default/ali-coding-plan/config.v2.json +76 -0
- package/configsamples/provider-default/antigravity/config.v2.json +142 -0
- package/configsamples/provider-default/ark-coding-plan/config.v2.json +64 -0
- package/configsamples/provider-default/crs/config.v2.json +54 -0
- package/configsamples/provider-default/deepseek-web/config.v2.json +56 -0
- package/configsamples/provider-default/gemini/config.v2.json +43 -0
- package/configsamples/provider-default/gemini-cli/config.v2.json +45 -0
- package/configsamples/provider-default/gemini-native/config.v2.json +208 -0
- package/configsamples/provider-default/glm/config.v2.json +33 -0
- package/configsamples/provider-default/glm-anthropic/config.v2.json +29 -0
- package/configsamples/provider-default/kimi/config.v2.json +25 -0
- package/configsamples/provider-default/lmstudio/config.v2.json +79 -0
- package/configsamples/provider-default/lmstudio-proxy/config.v2.json +78 -0
- package/configsamples/provider-default/manifest.json +31 -0
- package/configsamples/provider-default/meituan/config.v2.json +20 -0
- package/configsamples/provider-default/mimo/config.v2.json +26 -0
- package/configsamples/provider-default/modelscope/config.v2.json +81 -0
- package/configsamples/provider-default/my-openai/config.v2.json +20 -0
- package/configsamples/provider-default/nvidia/config.v2.json +32 -0
- package/configsamples/provider-default/opencode-zen-free/config.v2.json +56 -0
- package/configsamples/provider-default/openrouter/config.v2.json +210 -0
- package/configsamples/provider-default/qwen/config.v2.json +38 -0
- package/configsamples/provider-default/qwenchat/config.v2.json +53 -0
- package/configsamples/provider-default/tab/config.v2.json +26 -0
- package/configsamples/provider-default/tabglm/config.v2.json +77 -0
- package/dist/build-info.js +2 -2
- package/dist/cli/commands/config.d.ts +5 -0
- package/dist/cli/commands/config.js +369 -1
- package/dist/cli/commands/config.js.map +1 -1
- package/dist/cli/commands/examples.js +3 -0
- package/dist/cli/commands/examples.js.map +1 -1
- package/dist/cli/commands/init.js +25 -1
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/launcher-kernel.js +122 -46
- package/dist/cli/commands/launcher-kernel.js.map +1 -1
- package/dist/cli/commands/start.js +60 -3
- package/dist/cli/commands/start.js.map +1 -1
- package/dist/cli/config/bundled-provider-pack.d.ts +20 -0
- package/dist/cli/config/bundled-provider-pack.js +146 -0
- package/dist/cli/config/bundled-provider-pack.js.map +1 -0
- package/dist/cli/register/status-config-commands.d.ts +2 -0
- package/dist/cli/register/status-config-commands.js.map +1 -1
- package/dist/cli.js +81 -28
- package/dist/cli.js.map +1 -1
- package/dist/debug/snapshot-store.js +2 -1
- package/dist/debug/snapshot-store.js.map +1 -1
- package/dist/index.js +23 -14
- package/dist/index.js.map +1 -1
- package/dist/manager/modules/quota/provider-quota-daemon.model-backoff.js +1 -1
- package/dist/manager/modules/quota/provider-quota-daemon.model-backoff.js.map +1 -1
- package/dist/manager/quota/provider-quota-center.js +1 -1
- package/dist/manager/quota/provider-quota-center.js.map +1 -1
- package/dist/manager/storage/file-store.js +10 -0
- package/dist/manager/storage/file-store.js.map +1 -1
- package/dist/modules/llmswitch/bridge/snapshot-recorder-runtime.js +18 -1
- package/dist/modules/llmswitch/bridge/snapshot-recorder-runtime.js.map +1 -1
- package/dist/modules/llmswitch/bridge/snapshot-recorder.js +132 -51
- package/dist/modules/llmswitch/bridge/snapshot-recorder.js.map +1 -1
- package/dist/provider-sdk/provider-runtime-inference.js +2 -2
- package/dist/provider-sdk/provider-runtime-inference.js.map +1 -1
- package/dist/providers/auth/deepseek-account-token-acquirer.js +32 -3
- package/dist/providers/auth/deepseek-account-token-acquirer.js.map +1 -1
- package/dist/providers/core/api/provider-types.d.ts +11 -0
- package/dist/providers/core/config/service-profiles.js +1 -1
- package/dist/providers/core/runtime/deepseek-http-provider.d.ts +2 -0
- package/dist/providers/core/runtime/deepseek-http-provider.js +31 -1
- package/dist/providers/core/runtime/deepseek-http-provider.js.map +1 -1
- package/dist/providers/core/runtime/qwenchat-http-provider-helpers.d.ts +3 -2
- package/dist/providers/core/runtime/qwenchat-http-provider-helpers.js +513 -96
- package/dist/providers/core/runtime/qwenchat-http-provider-helpers.js.map +1 -1
- package/dist/providers/core/runtime/standard-tool-text-harvest.d.ts +8 -0
- package/dist/providers/core/runtime/standard-tool-text-harvest.js +24 -0
- package/dist/providers/core/runtime/standard-tool-text-harvest.js.map +1 -0
- package/dist/providers/core/runtime/standard-tool-text-request-transform.d.ts +4 -1
- package/dist/providers/core/runtime/standard-tool-text-request-transform.js +129 -3
- package/dist/providers/core/runtime/standard-tool-text-request-transform.js.map +1 -1
- package/dist/providers/core/utils/snapshot-writer.js +5 -2
- package/dist/providers/core/utils/snapshot-writer.js.map +1 -1
- package/dist/providers/profile/provider-profile-loader.js +52 -1
- package/dist/providers/profile/provider-profile-loader.js.map +1 -1
- package/dist/providers/profile/provider-profile.d.ts +3 -0
- package/dist/server/handlers/handler-response-utils.js +1 -0
- package/dist/server/handlers/handler-response-utils.js.map +1 -1
- package/dist/server/handlers/images-handler.d.ts +9 -0
- package/dist/server/handlers/images-handler.js +258 -0
- package/dist/server/handlers/images-handler.js.map +1 -0
- package/dist/server/handlers/types.d.ts +7 -0
- package/dist/server/runtime/http-server/antigravity-startup-tasks.d.ts +3 -0
- package/dist/server/runtime/http-server/antigravity-startup-tasks.js +16 -0
- package/dist/server/runtime/http-server/antigravity-startup-tasks.js.map +1 -1
- package/dist/server/runtime/http-server/daemon-admin/auth-handler.js +3 -18
- package/dist/server/runtime/http-server/daemon-admin/auth-handler.js.map +1 -1
- package/dist/server/runtime/http-server/daemon-admin/providers-handler-utils.d.ts +7 -0
- package/dist/server/runtime/http-server/daemon-admin/providers-handler-utils.js +17 -0
- package/dist/server/runtime/http-server/daemon-admin/providers-handler-utils.js.map +1 -1
- package/dist/server/runtime/http-server/daemon-admin/providers-handler.js +50 -17
- package/dist/server/runtime/http-server/daemon-admin/providers-handler.js.map +1 -1
- package/dist/server/runtime/http-server/daemon-admin-routes.js +32 -2
- package/dist/server/runtime/http-server/daemon-admin-routes.js.map +1 -1
- package/dist/server/runtime/http-server/executor/provider-response-converter.js +42 -13
- package/dist/server/runtime/http-server/executor/provider-response-converter.js.map +1 -1
- package/dist/server/runtime/http-server/executor/provider-response-utils.js +41 -3
- package/dist/server/runtime/http-server/executor/provider-response-utils.js.map +1 -1
- package/dist/server/runtime/http-server/executor/usage-aggregator.js +7 -7
- package/dist/server/runtime/http-server/executor/usage-aggregator.js.map +1 -1
- package/dist/server/runtime/http-server/executor/usage-logger.d.ts +9 -0
- package/dist/server/runtime/http-server/executor/usage-logger.js +35 -2
- package/dist/server/runtime/http-server/executor/usage-logger.js.map +1 -1
- package/dist/server/runtime/http-server/executor-metadata.js +12 -4
- package/dist/server/runtime/http-server/executor-metadata.js.map +1 -1
- package/dist/server/runtime/http-server/executor-pipeline.js +24 -15
- package/dist/server/runtime/http-server/executor-pipeline.js.map +1 -1
- package/dist/server/runtime/http-server/executor-provider.d.ts +6 -1
- package/dist/server/runtime/http-server/executor-provider.js +137 -5
- package/dist/server/runtime/http-server/executor-provider.js.map +1 -1
- package/dist/server/runtime/http-server/http-server-bootstrap.js +6 -0
- package/dist/server/runtime/http-server/http-server-bootstrap.js.map +1 -1
- package/dist/server/runtime/http-server/http-server-lifecycle.js +23 -15
- package/dist/server/runtime/http-server/http-server-lifecycle.js.map +1 -1
- package/dist/server/runtime/http-server/http-server-runtime-providers.js +14 -4
- package/dist/server/runtime/http-server/http-server-runtime-providers.js.map +1 -1
- package/dist/server/runtime/http-server/http-server-runtime-setup.js +83 -1
- package/dist/server/runtime/http-server/http-server-runtime-setup.js.map +1 -1
- package/dist/server/runtime/http-server/hub-shadow-compare.js +2 -41
- package/dist/server/runtime/http-server/hub-shadow-compare.js.map +1 -1
- package/dist/server/runtime/http-server/provider-routing-scope.d.ts +9 -0
- package/dist/server/runtime/http-server/provider-routing-scope.js +20 -0
- package/dist/server/runtime/http-server/provider-routing-scope.js.map +1 -0
- package/dist/server/runtime/http-server/provider-traffic-governor.d.ts +67 -0
- package/dist/server/runtime/http-server/provider-traffic-governor.js +467 -0
- package/dist/server/runtime/http-server/provider-traffic-governor.js.map +1 -0
- package/dist/server/runtime/http-server/request-executor.d.ts +8 -0
- package/dist/server/runtime/http-server/request-executor.js +446 -21
- package/dist/server/runtime/http-server/request-executor.js.map +1 -1
- package/dist/server/runtime/http-server/routes.js +13 -0
- package/dist/server/runtime/http-server/routes.js.map +1 -1
- package/dist/server/runtime/http-server/session-client-registry.js +30 -4
- package/dist/server/runtime/http-server/session-client-registry.js.map +1 -1
- package/dist/server/runtime/http-server/session-client-route-utils.d.ts +7 -0
- package/dist/server/runtime/http-server/session-client-route-utils.js +38 -0
- package/dist/server/runtime/http-server/session-client-route-utils.js.map +1 -1
- package/dist/server/runtime/http-server/session-client-routes.js +12 -2
- package/dist/server/runtime/http-server/session-client-routes.js.map +1 -1
- package/dist/server/utils/request-id-manager.js +42 -5
- package/dist/server/utils/request-id-manager.js.map +1 -1
- package/dist/server/utils/stage-logger.d.ts +1 -0
- package/dist/server/utils/stage-logger.js +27 -0
- package/dist/server/utils/stage-logger.js.map +1 -1
- package/dist/utils/errorsamples.js +3 -1
- package/dist/utils/errorsamples.js.map +1 -1
- package/dist/utils/sensitive-redaction.d.ts +1 -0
- package/dist/utils/sensitive-redaction.js +122 -0
- package/dist/utils/sensitive-redaction.js.map +1 -0
- package/dist/utils/snapshot-writer.js +162 -2
- package/dist/utils/snapshot-writer.js.map +1 -1
- package/docs/INSTALLATION_AND_QUICKSTART.md +14 -1
- package/docs/PORTS.md +12 -0
- package/docs/lmstudio-tool-calling.md +25 -0
- package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/qwenchat-web-request.d.ts +3 -0
- package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/qwenchat-web-request.js +62 -0
- package/node_modules/@jsonstudio/llms/dist/conversion/compat/profiles/chat-qwenchat-web.json +47 -0
- package/node_modules/@jsonstudio/llms/dist/conversion/hub/node-support.js +5 -2
- package/node_modules/@jsonstudio/llms/dist/conversion/hub/operation-table/operation-table-runner.js +68 -7
- package/node_modules/@jsonstudio/llms/dist/conversion/hub/operation-table/semantic-mappers/anthropic-mapper-from-chat.js +138 -3
- package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/hub-pipeline-chat-process-request-utils.js +24 -0
- package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/hub-pipeline-execute-chat-process-entry.js +7 -1
- package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/hub-pipeline-execute-request-stage.js +7 -0
- package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/hub-pipeline-heavy-input-fastpath.d.ts +24 -0
- package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/hub-pipeline-heavy-input-fastpath.js +203 -0
- package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/hub-pipeline-route-and-outbound.js +17 -12
- package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/hub-stage-timing.d.ts +11 -0
- package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/hub-stage-timing.js +82 -1
- package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage2_semantic_map/index.js +47 -14
- package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/stages/req_outbound/req_outbound_stage1_semantic_map/index.js +43 -0
- package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/stages/resp_outbound/resp_outbound_stage1_client_remap/client-remap-protocol-switch.js +222 -19
- package/node_modules/@jsonstudio/llms/dist/conversion/hub/policy/policy-engine.js +2 -2
- package/node_modules/@jsonstudio/llms/dist/conversion/hub/process/chat-process-pending-tool-sync.js +24 -7
- package/node_modules/@jsonstudio/llms/dist/conversion/hub/response/provider-response.js +90 -1
- package/node_modules/@jsonstudio/llms/dist/conversion/hub/snapshot-recorder.d.ts +1 -0
- package/node_modules/@jsonstudio/llms/dist/conversion/hub/snapshot-recorder.js +252 -1
- package/node_modules/@jsonstudio/llms/dist/conversion/responses/responses-openai-bridge/utils.js +5 -3
- package/node_modules/@jsonstudio/llms/dist/conversion/responses/responses-openai-bridge.js +44 -4
- package/node_modules/@jsonstudio/llms/dist/conversion/shared/anthropic-message-utils-openai-request.d.ts +3 -1
- package/node_modules/@jsonstudio/llms/dist/conversion/shared/anthropic-message-utils-openai-request.js +20 -23
- package/node_modules/@jsonstudio/llms/dist/conversion/shared/tool-governor.js +68 -30
- package/node_modules/@jsonstudio/llms/dist/conversion/snapshot-utils.js +194 -10
- package/node_modules/@jsonstudio/llms/dist/native/router_hotpath_napi.node +0 -0
- package/node_modules/@jsonstudio/llms/dist/quota/quota-state.js +2 -2
- package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine/routing-state/store.js +35 -2
- package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine.js +9 -9
- package/node_modules/@jsonstudio/llms/dist/router/virtual-router/sticky-session-store.js +104 -18
- package/node_modules/@jsonstudio/llms/dist/servertool/engine.js +79 -32
- package/node_modules/@jsonstudio/llms/dist/servertool/handlers/vision.js +49 -0
- package/node_modules/@jsonstudio/llms/dist/servertool/pending-session.js +48 -2
- package/node_modules/@jsonstudio/llms/dist/servertool/server-side-tools.js +14 -1
- package/node_modules/@jsonstudio/llms/dist/servertool/types.d.ts +1 -0
- package/node_modules/@jsonstudio/llms/package.json +1 -1
- package/node_modules/ajv/dist/compile/jtd/serialize.js +9 -2
- package/node_modules/ajv/dist/compile/jtd/serialize.js.map +1 -1
- package/node_modules/ajv/dist/core.d.ts +1 -0
- package/node_modules/ajv/dist/core.js.map +1 -1
- package/node_modules/ajv/dist/vocabularies/validation/pattern.js +13 -4
- package/node_modules/ajv/dist/vocabularies/validation/pattern.js.map +1 -1
- package/node_modules/ajv/lib/compile/jtd/serialize.ts +13 -2
- package/node_modules/ajv/lib/core.ts +1 -0
- package/node_modules/ajv/lib/vocabularies/validation/pattern.ts +15 -4
- package/node_modules/ajv/package.json +2 -1
- package/package.json +15 -10
- package/scripts/ci/repo-sanity.mjs +23 -2
- package/scripts/ci/secrets-check.mjs +48 -0
- package/scripts/ci/silent-failure-audit.mjs +192 -0
- package/scripts/mock-provider/run-regressions.mjs +1 -0
- package/scripts/monitor/memory-guard.mjs +207 -0
- package/scripts/pack-mode.mjs +32 -36
- package/scripts/publish-rcc.mjs +38 -60
- package/scripts/tests/apply-patch-loop.mjs +1 -0
- package/scripts/tests/blackbox-rcc-vs-routecodex-antigravity.mjs +2 -0
- package/scripts/tools-dev/responses-debug-client/src/index.ts +8 -3
- package/scripts/verify-e2e-toolcall.mjs +1 -0
- 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
|
+
|
package/scripts/pack-mode.mjs
CHANGED
|
@@ -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
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
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
|
-
|
|
115
|
-
|
|
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 =
|
|
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
|
|
package/scripts/publish-rcc.mjs
CHANGED
|
@@ -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
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
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
|
-
|
|
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
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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
|
-
|
|
91
|
-
|
|
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(
|
|
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,
|