@jsonstudio/rcc 0.90.872 → 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.
@@ -1,6 +1,6 @@
1
1
  export const buildInfo = {
2
2
  mode: 'release',
3
- version: '0.90.872',
4
- buildTime: '2026-04-05T11:32:21.697Z'
3
+ version: '0.90.876',
4
+ buildTime: '2026-04-05T13:08:10.305Z'
5
5
  };
6
6
  //# sourceMappingURL=build-info.js.map
@@ -1,4 +1,12 @@
1
- import { processChatResponseTools } from '../../../../sharedmodule/llmswitch-core/dist/conversion/shared/tool-governor.js';
1
+ import { importCoreDist } from '../../../modules/llmswitch/bridge/module-loader.js';
2
+ const toolGovernorModule = await importCoreDist('conversion/shared/tool-governor');
3
+ const processChatResponseToolsFn = (() => {
4
+ const fn = toolGovernorModule?.processChatResponseTools;
5
+ if (typeof fn !== 'function') {
6
+ throw new Error('[standard-tool-text-harvest] processChatResponseTools not available');
7
+ }
8
+ return fn;
9
+ })();
2
10
  function isRecord(value) {
3
11
  return value !== null && typeof value === 'object' && !Array.isArray(value);
4
12
  }
@@ -10,7 +18,7 @@ function isRecord(value) {
10
18
  * - Keep this wrapper neutral so providers share one skeleton.
11
19
  */
12
20
  export function applyStandardToolTextHarvestToChatPayload(payload) {
13
- const harvested = processChatResponseTools(payload);
21
+ const harvested = processChatResponseToolsFn(payload);
14
22
  return (isRecord(harvested) ? harvested : payload);
15
23
  }
16
24
  //# sourceMappingURL=standard-tool-text-harvest.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"standard-tool-text-harvest.js","sourceRoot":"","sources":["../../../../src/providers/core/runtime/standard-tool-text-harvest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,iFAAiF,CAAC;AAE3H,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC9E,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,yCAAyC,CAAoC,OAAU;IACrG,MAAM,SAAS,GAAG,wBAAwB,CAAC,OAAc,CAAC,CAAC;IAC3D,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAM,CAAC;AAC1D,CAAC"}
1
+ {"version":3,"file":"standard-tool-text-harvest.js","sourceRoot":"","sources":["../../../../src/providers/core/runtime/standard-tool-text-harvest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,oDAAoD,CAAC;AAMpF,MAAM,kBAAkB,GAAG,MAAM,cAAc,CAAqB,iCAAiC,CAAC,CAAC;AACvG,MAAM,0BAA0B,GAAgE,CAAC,GAAG,EAAE;IACpG,MAAM,EAAE,GAAG,kBAAkB,EAAE,wBAAwB,CAAC;IACxD,IAAI,OAAO,EAAE,KAAK,UAAU,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,qEAAqE,CAAC,CAAC;IACzF,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC,CAAC,EAAE,CAAC;AAEL,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC9E,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,yCAAyC,CAAoC,OAAU;IACrG,MAAM,SAAS,GAAG,0BAA0B,CAAC,OAAc,CAAC,CAAC;IAC7D,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAM,CAAC;AAC1D,CAAC"}
@@ -1,4 +1,12 @@
1
- import { applyQwenChatWebRequestTransform } from '../../../../sharedmodule/llmswitch-core/dist/conversion/compat/actions/qwenchat-web-request.js';
1
+ import { importCoreDist } from '../../../modules/llmswitch/bridge/module-loader.js';
2
+ const qwenChatWebRequestTransformModule = await importCoreDist('conversion/compat/actions/qwenchat-web-request');
3
+ const qwenChatWebRequestTransformFn = (() => {
4
+ const fn = qwenChatWebRequestTransformModule?.applyQwenChatWebRequestTransform;
5
+ if (typeof fn !== 'function') {
6
+ throw new Error('[standard-tool-text-request-transform] applyQwenChatWebRequestTransform not available');
7
+ }
8
+ return fn;
9
+ })();
2
10
  const TOOL_REGISTRY_FAILURE_RE = /\bTool\s+[A-Za-z0-9_.:/-]+\s+does\s+not\s+exists\b/i;
3
11
  const TOOL_REGISTRY_FAILURE_GLOBAL_RE = /\bTool\s+[A-Za-z0-9_.:/-]+\s+does\s+not\s+exists\b/gi;
4
12
  const TOOL_INFRA_FAILURE_RE = /(工具(?:基础设施|执行链路|执行层).{0,24}(?:不可用|无响应|异常)|当前\s*(?:session|会话).{0,24}工具.{0,24}(?:不可用|无响应|异常)|tool\s+(?:execution\s+layer|infrastructure).{0,24}(?:unavailable|no\s+response|broken|failed))/i;
@@ -114,7 +122,7 @@ function sanitizeToolTextTransformPayload(payload) {
114
122
  }
115
123
  export const standardToolTextRequestTransformRuntime = {
116
124
  transform(payload, adapterContext) {
117
- return applyQwenChatWebRequestTransform(payload, adapterContext);
125
+ return qwenChatWebRequestTransformFn(payload, adapterContext);
118
126
  }
119
127
  };
120
128
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"standard-tool-text-request-transform.js","sourceRoot":"","sources":["../../../../src/providers/core/runtime/standard-tool-text-request-transform.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"standard-tool-text-request-transform.js","sourceRoot":"","sources":["../../../../src/providers/core/runtime/standard-tool-text-request-transform.ts"],"names":[],"mappings":"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"}
@@ -4,6 +4,133 @@ import path from 'path';
4
4
  import { resolveRccSnapshotsDirFromEnv } from '../config/user-data-paths.js';
5
5
  import { runtimeFlags } from '../runtime/runtime-flags.js';
6
6
  let snapshotHookWriterPromise = null;
7
+ const DEFAULT_SERVER_SNAPSHOT_PAYLOAD_MAX_BYTES = 256 * 1024;
8
+ const DEFAULT_SERVER_SNAPSHOT_KEEP_RECENT_FILES = 10;
9
+ function resolveServerSnapshotPayloadMaxBytes() {
10
+ const raw = process.env.ROUTECODEX_SNAPSHOT_PAYLOAD_MAX_BYTES
11
+ ?? process.env.RCC_SNAPSHOT_PAYLOAD_MAX_BYTES
12
+ ?? '';
13
+ const parsed = Number.parseInt(String(raw).trim(), 10);
14
+ if (Number.isFinite(parsed) && parsed > 0) {
15
+ return parsed;
16
+ }
17
+ return DEFAULT_SERVER_SNAPSHOT_PAYLOAD_MAX_BYTES;
18
+ }
19
+ function resolveServerSnapshotKeepRecentFiles() {
20
+ const raw = process.env.ROUTECODEX_SNAPSHOT_KEEP_RECENT_FILES
21
+ ?? process.env.RCC_SNAPSHOT_KEEP_RECENT_FILES
22
+ ?? '';
23
+ const parsed = Number.parseInt(String(raw).trim(), 10);
24
+ if (Number.isFinite(parsed) && parsed > 0) {
25
+ return parsed;
26
+ }
27
+ return DEFAULT_SERVER_SNAPSHOT_KEEP_RECENT_FILES;
28
+ }
29
+ function estimateSnapshotPayloadBytes(value, options) {
30
+ const maxBytes = options?.maxBytes ?? Number.POSITIVE_INFINITY;
31
+ const depth = options?.depth ?? 0;
32
+ const seen = options?.seen ?? new Set();
33
+ if (value === null || value === undefined) {
34
+ return 4;
35
+ }
36
+ const valueType = typeof value;
37
+ if (valueType === 'string') {
38
+ return Math.min(maxBytes + 1, value.length * 2 + 2);
39
+ }
40
+ if (valueType === 'number') {
41
+ return 8;
42
+ }
43
+ if (valueType === 'boolean') {
44
+ return 4;
45
+ }
46
+ if (valueType === 'bigint') {
47
+ return String(value).length + 8;
48
+ }
49
+ if (valueType === 'symbol' || valueType === 'function') {
50
+ return 16;
51
+ }
52
+ if (seen.has(value)) {
53
+ return 8;
54
+ }
55
+ seen.add(value);
56
+ if (depth >= 8) {
57
+ return 64;
58
+ }
59
+ let bytes = 0;
60
+ if (Array.isArray(value)) {
61
+ bytes += 2;
62
+ for (const item of value) {
63
+ bytes += estimateSnapshotPayloadBytes(item, {
64
+ maxBytes: Math.max(0, maxBytes - bytes),
65
+ depth: depth + 1,
66
+ seen
67
+ });
68
+ if (bytes > maxBytes) {
69
+ return maxBytes + 1;
70
+ }
71
+ }
72
+ return bytes;
73
+ }
74
+ if (value && typeof value === 'object') {
75
+ bytes += 2;
76
+ for (const [key, child] of Object.entries(value)) {
77
+ bytes += key.length * 2 + 4;
78
+ bytes += estimateSnapshotPayloadBytes(child, {
79
+ maxBytes: Math.max(0, maxBytes - bytes),
80
+ depth: depth + 1,
81
+ seen
82
+ });
83
+ if (bytes > maxBytes) {
84
+ return maxBytes + 1;
85
+ }
86
+ }
87
+ return bytes;
88
+ }
89
+ return 16;
90
+ }
91
+ function summarizeSnapshotPayload(value) {
92
+ if (Array.isArray(value)) {
93
+ return {
94
+ type: 'array',
95
+ length: value.length,
96
+ sampleTypes: value.slice(0, 8).map((item) => typeof item)
97
+ };
98
+ }
99
+ if (value && typeof value === 'object') {
100
+ const record = value;
101
+ const keys = Object.keys(record);
102
+ return {
103
+ type: 'object',
104
+ keyCount: keys.length,
105
+ keys: keys.slice(0, 24)
106
+ };
107
+ }
108
+ if (typeof value === 'string') {
109
+ return {
110
+ type: 'string',
111
+ length: value.length,
112
+ preview: value.length > 160 ? `${value.slice(0, 160)}…` : value
113
+ };
114
+ }
115
+ return {
116
+ type: typeof value,
117
+ value: value ?? null
118
+ };
119
+ }
120
+ function coerceServerSnapshotData(stage, data) {
121
+ const maxBytes = resolveServerSnapshotPayloadMaxBytes();
122
+ const estimatedBytes = estimateSnapshotPayloadBytes(data, { maxBytes: maxBytes + 1 });
123
+ if (estimatedBytes <= maxBytes) {
124
+ return data;
125
+ }
126
+ return {
127
+ __snapshot_truncated: true,
128
+ stage,
129
+ maxBytes,
130
+ estimatedBytes,
131
+ summary: summarizeSnapshotPayload(data)
132
+ };
133
+ }
7
134
  function logServerSnapshotNonBlockingError(operation, error) {
8
135
  const reason = error instanceof Error ? error.message : String(error);
9
136
  console.warn(`[server-snapshot] ${operation} failed (non-blocking): ${reason}`);
@@ -69,6 +196,37 @@ async function writeUniqueFile(dir, baseName, contents) {
69
196
  const fallback = `${stem}_${Date.now()}_${Math.random().toString(36).slice(2, 8)}${ext}`;
70
197
  await fsp.writeFile(path.join(dir, fallback), contents, 'utf-8');
71
198
  }
199
+ async function pruneSnapshotFilesKeepRecent(dir, maxFiles) {
200
+ if (!Number.isFinite(maxFiles) || maxFiles <= 0) {
201
+ return;
202
+ }
203
+ const entries = await fsp.readdir(dir, { withFileTypes: true });
204
+ const candidates = entries
205
+ .filter((entry) => entry.isFile() && entry.name.endsWith('.json') && entry.name !== '__runtime.json')
206
+ .map((entry) => entry.name);
207
+ if (candidates.length <= maxFiles) {
208
+ return;
209
+ }
210
+ const filesWithMtime = await Promise.all(candidates.map(async (name) => {
211
+ const fullPath = path.join(dir, name);
212
+ const stat = await fsp.stat(fullPath);
213
+ return {
214
+ name,
215
+ fullPath,
216
+ mtimeMs: Number.isFinite(stat.mtimeMs) ? stat.mtimeMs : 0
217
+ };
218
+ }));
219
+ filesWithMtime.sort((a, b) => b.mtimeMs - a.mtimeMs || a.name.localeCompare(b.name));
220
+ const stale = filesWithMtime.slice(maxFiles);
221
+ await Promise.all(stale.map(async (file) => {
222
+ try {
223
+ await fsp.unlink(file.fullPath);
224
+ }
225
+ catch {
226
+ // best-effort prune, never block request path
227
+ }
228
+ }));
229
+ }
72
230
  async function loadSnapshotHookWriter() {
73
231
  if (!snapshotHookWriterPromise) {
74
232
  snapshotHookWriterPromise = import('../modules/llmswitch/bridge.js')
@@ -87,6 +245,7 @@ export async function writeServerSnapshot(options) {
87
245
  const endpoint = options.entryEndpoint || '/v1/chat/completions';
88
246
  const groupRequestId = options.groupRequestId || options.requestId;
89
247
  const providerKey = options.providerKey;
248
+ const data = coerceServerSnapshotData(String(options.phase), options.data);
90
249
  // 1) 尝试通过 llmswitch-core hooks 写快照(供核心调试使用)
91
250
  try {
92
251
  const writeSnapshotViaHooks = await loadSnapshotHookWriter();
@@ -96,7 +255,7 @@ export async function writeServerSnapshot(options) {
96
255
  requestId: options.requestId,
97
256
  groupRequestId,
98
257
  providerKey,
99
- data: options.data,
258
+ data,
100
259
  verbosity: 'verbose'
101
260
  });
102
261
  }
@@ -122,9 +281,10 @@ export async function writeServerSnapshot(options) {
122
281
  version: String(process.env.ROUTECODEX_VERSION || 'dev'),
123
282
  buildTime: String(process.env.ROUTECODEX_BUILD_TIME || new Date().toISOString())
124
283
  },
125
- data: options.data
284
+ data
126
285
  };
127
286
  await writeUniqueFile(dir, file, JSON.stringify(payload, null, 2));
287
+ await pruneSnapshotFilesKeepRecent(dir, resolveServerSnapshotKeepRecentFiles());
128
288
  }
129
289
  catch (error) {
130
290
  logServerSnapshotNonBlockingError(`writeLocalSnapshot:${options.phase}`, error);
@@ -1 +1 @@
1
- {"version":3,"file":"snapshot-writer.js","sourceRoot":"","sources":["../../src/utils/snapshot-writer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"snapshot-writer.js","sourceRoot":"","sources":["../../src/utils/snapshot-writer.ts"],"names":[],"mappings":"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"}
@@ -53,8 +53,11 @@ export async function runHubOutboundConversion(options) {
53
53
  return payload;
54
54
  }
55
55
  function maybeCreateStageRecorder(adapterContext, defaultEndpoint) {
56
- const flag = process.env.ROUTECODEX_HUB_SNAPSHOTS;
57
- if (flag && flag.trim() === '0') {
56
+ const flag = String(process.env.ROUTECODEX_HUB_SNAPSHOTS ?? process.env.RCC_HUB_SNAPSHOTS ?? '')
57
+ .trim()
58
+ .toLowerCase();
59
+ const enabled = flag === '1' || flag === 'true' || flag === 'yes' || flag === 'on';
60
+ if (!enabled) {
58
61
  return undefined;
59
62
  }
60
63
  const endpoint = defaultEndpoint || adapterContext.entryEndpoint || '/v1/chat/completions';
@@ -18,22 +18,156 @@ export async function recordSnapshot(options) {
18
18
  if (!shouldRecordSnapshots())
19
19
  return;
20
20
  const endpoint = options.endpoint || '/v1/chat/completions';
21
+ const prepared = coerceSnapshotPayloadForWrite(options.stage, options.data);
21
22
  void writeSnapshotViaHooks({
22
23
  endpoint,
23
24
  stage: options.stage,
24
25
  requestId: options.requestId,
25
26
  providerKey: options.providerKey,
26
27
  groupRequestId: options.groupRequestId,
27
- data: options.data,
28
+ data: prepared.data,
28
29
  verbosity: 'verbose'
29
30
  }).catch(() => {
30
31
  // ignore hook errors
31
32
  });
32
33
  }
33
- const MAX_SNAPSHOT_QUEUE_SIZE = 2048;
34
+ const DEFAULT_SNAPSHOT_QUEUE_MAX_ITEMS = 10;
34
35
  const SNAPSHOT_QUEUE_BATCH_SIZE = 64;
36
+ const DEFAULT_SNAPSHOT_PAYLOAD_MAX_BYTES = 256 * 1024;
37
+ const DEFAULT_SNAPSHOT_QUEUE_MEMORY_BUDGET_BYTES = 8 * 1024 * 1024;
35
38
  const SNAPSHOT_QUEUE = [];
39
+ let snapshotQueueBytes = 0;
36
40
  let snapshotQueueDrainScheduled = false;
41
+ function resolvePositiveIntegerFromEnv(names, fallback) {
42
+ for (const name of names) {
43
+ const raw = process.env[name];
44
+ const parsed = Number.parseInt(String(raw ?? '').trim(), 10);
45
+ if (Number.isFinite(parsed) && parsed > 0) {
46
+ return parsed;
47
+ }
48
+ }
49
+ return fallback;
50
+ }
51
+ function resolveSnapshotPayloadMaxBytes() {
52
+ return resolvePositiveIntegerFromEnv(['ROUTECODEX_SNAPSHOT_PAYLOAD_MAX_BYTES', 'RCC_SNAPSHOT_PAYLOAD_MAX_BYTES'], DEFAULT_SNAPSHOT_PAYLOAD_MAX_BYTES);
53
+ }
54
+ function resolveSnapshotQueueMemoryBudgetBytes() {
55
+ return resolvePositiveIntegerFromEnv(['ROUTECODEX_SNAPSHOT_QUEUE_MEMORY_BUDGET_BYTES', 'RCC_SNAPSHOT_QUEUE_MEMORY_BUDGET_BYTES'], DEFAULT_SNAPSHOT_QUEUE_MEMORY_BUDGET_BYTES);
56
+ }
57
+ function resolveSnapshotQueueMaxItems() {
58
+ return resolvePositiveIntegerFromEnv(['ROUTECODEX_SNAPSHOT_QUEUE_MAX_ITEMS', 'RCC_SNAPSHOT_QUEUE_MAX_ITEMS'], DEFAULT_SNAPSHOT_QUEUE_MAX_ITEMS);
59
+ }
60
+ function estimateSnapshotPayloadBytes(value, options) {
61
+ const maxBytes = options?.maxBytes ?? Number.POSITIVE_INFINITY;
62
+ const depth = options?.depth ?? 0;
63
+ const seen = options?.seen ?? new Set();
64
+ if (value === null || value === undefined) {
65
+ return 4;
66
+ }
67
+ const valueType = typeof value;
68
+ if (valueType === 'string') {
69
+ return Math.min(maxBytes + 1, value.length * 2 + 2);
70
+ }
71
+ if (valueType === 'number') {
72
+ return 8;
73
+ }
74
+ if (valueType === 'boolean') {
75
+ return 4;
76
+ }
77
+ if (valueType === 'bigint') {
78
+ return String(value).length + 8;
79
+ }
80
+ if (valueType === 'symbol' || valueType === 'function') {
81
+ return 16;
82
+ }
83
+ if (seen.has(value)) {
84
+ return 8;
85
+ }
86
+ seen.add(value);
87
+ if (depth >= 8) {
88
+ return 64;
89
+ }
90
+ let bytes = 0;
91
+ if (Array.isArray(value)) {
92
+ bytes += 2;
93
+ for (const item of value) {
94
+ bytes += estimateSnapshotPayloadBytes(item, {
95
+ maxBytes: Math.max(0, maxBytes - bytes),
96
+ depth: depth + 1,
97
+ seen
98
+ });
99
+ if (bytes > maxBytes) {
100
+ return maxBytes + 1;
101
+ }
102
+ }
103
+ return bytes;
104
+ }
105
+ if (value && typeof value === 'object') {
106
+ bytes += 2;
107
+ for (const [key, child] of Object.entries(value)) {
108
+ bytes += key.length * 2 + 4;
109
+ bytes += estimateSnapshotPayloadBytes(child, {
110
+ maxBytes: Math.max(0, maxBytes - bytes),
111
+ depth: depth + 1,
112
+ seen
113
+ });
114
+ if (bytes > maxBytes) {
115
+ return maxBytes + 1;
116
+ }
117
+ }
118
+ return bytes;
119
+ }
120
+ return 16;
121
+ }
122
+ function summarizeSnapshotPayload(value) {
123
+ if (Array.isArray(value)) {
124
+ return {
125
+ type: 'array',
126
+ length: value.length,
127
+ sampleTypes: value.slice(0, 8).map((item) => typeof item)
128
+ };
129
+ }
130
+ if (value && typeof value === 'object') {
131
+ const record = value;
132
+ const keys = Object.keys(record);
133
+ return {
134
+ type: 'object',
135
+ keyCount: keys.length,
136
+ keys: keys.slice(0, 24)
137
+ };
138
+ }
139
+ if (typeof value === 'string') {
140
+ return {
141
+ type: 'string',
142
+ length: value.length,
143
+ preview: value.length > 160 ? `${value.slice(0, 160)}…` : value
144
+ };
145
+ }
146
+ return {
147
+ type: typeof value,
148
+ value: value ?? null
149
+ };
150
+ }
151
+ function coerceSnapshotPayloadForWrite(stage, payload) {
152
+ const maxBytes = resolveSnapshotPayloadMaxBytes();
153
+ const estimatedBytes = estimateSnapshotPayloadBytes(payload, { maxBytes: maxBytes + 1 });
154
+ if (estimatedBytes <= maxBytes) {
155
+ return {
156
+ data: payload,
157
+ sizeBytes: Math.max(1, estimatedBytes)
158
+ };
159
+ }
160
+ return {
161
+ data: {
162
+ __snapshot_truncated: true,
163
+ stage,
164
+ maxBytes,
165
+ estimatedBytes,
166
+ summary: summarizeSnapshotPayload(payload)
167
+ },
168
+ sizeBytes: 512
169
+ };
170
+ }
37
171
  function scheduleSnapshotQueueDrain() {
38
172
  if (snapshotQueueDrainScheduled) {
39
173
  return;
@@ -43,12 +177,13 @@ function scheduleSnapshotQueueDrain() {
43
177
  snapshotQueueDrainScheduled = false;
44
178
  let processed = 0;
45
179
  while (SNAPSHOT_QUEUE.length > 0 && processed < SNAPSHOT_QUEUE_BATCH_SIZE) {
46
- const task = SNAPSHOT_QUEUE.shift();
47
- if (!task) {
180
+ const item = SNAPSHOT_QUEUE.shift();
181
+ if (!item) {
48
182
  continue;
49
183
  }
184
+ snapshotQueueBytes = Math.max(0, snapshotQueueBytes - Math.max(1, item.sizeBytes));
50
185
  try {
51
- task();
186
+ item.task();
52
187
  }
53
188
  catch {
54
189
  // snapshot write failures are non-blocking by design
@@ -60,12 +195,20 @@ function scheduleSnapshotQueueDrain() {
60
195
  }
61
196
  });
62
197
  }
63
- function enqueueSnapshotTask(task) {
64
- if (SNAPSHOT_QUEUE.length >= MAX_SNAPSHOT_QUEUE_SIZE) {
65
- // keep newest writes; snapshot stream is best-effort and must not block request hot path
66
- SNAPSHOT_QUEUE.shift();
198
+ function enqueueSnapshotTask(task, sizeBytes) {
199
+ const normalizedSize = Math.max(1, Math.floor(sizeBytes));
200
+ const queueBudgetBytes = resolveSnapshotQueueMemoryBudgetBytes();
201
+ const queueMaxItems = resolveSnapshotQueueMaxItems();
202
+ while (SNAPSHOT_QUEUE.length > 0
203
+ && (SNAPSHOT_QUEUE.length >= queueMaxItems || snapshotQueueBytes + normalizedSize > queueBudgetBytes)) {
204
+ const dropped = SNAPSHOT_QUEUE.shift();
205
+ if (!dropped) {
206
+ break;
207
+ }
208
+ snapshotQueueBytes = Math.max(0, snapshotQueueBytes - Math.max(1, dropped.sizeBytes));
67
209
  }
68
- SNAPSHOT_QUEUE.push(task);
210
+ SNAPSHOT_QUEUE.push({ task, sizeBytes: normalizedSize });
211
+ snapshotQueueBytes += normalizedSize;
69
212
  scheduleSnapshotQueueDrain();
70
213
  }
71
214
  export function createSnapshotWriter(opts) {
@@ -74,6 +217,7 @@ export function createSnapshotWriter(opts) {
74
217
  }
75
218
  const endpoint = opts.endpoint || '/v1/chat/completions';
76
219
  return (stage, payload) => {
220
+ const prepared = coerceSnapshotPayloadForWrite(stage, payload);
77
221
  enqueueSnapshotTask(() => {
78
222
  void recordSnapshot({
79
223
  stage,
@@ -82,8 +226,8 @@ export function createSnapshotWriter(opts) {
82
226
  folderHint: opts.folderHint,
83
227
  providerKey: opts.providerKey,
84
228
  groupRequestId: opts.groupRequestId,
85
- data: payload
229
+ data: prepared.data
86
230
  });
87
- });
231
+ }, prepared.sizeBytes);
88
232
  };
89
233
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsonstudio/rcc",
3
- "version": "0.90.872",
3
+ "version": "0.90.876",
4
4
  "description": "Multi-provider OpenAI proxy server with anthropic/responses/chat support (release)",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -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
+