@jsonstudio/rcc 0.89.1348 → 0.89.1457

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 (102) hide show
  1. package/README.md +51 -1427
  2. package/dist/build-info.js +2 -2
  3. package/dist/cli/commands/config.js +3 -0
  4. package/dist/cli/commands/config.js.map +1 -1
  5. package/dist/cli/commands/init.js +3 -0
  6. package/dist/cli/commands/init.js.map +1 -1
  7. package/dist/cli/config/bundled-docs.js +2 -2
  8. package/dist/cli/config/bundled-docs.js.map +1 -1
  9. package/dist/cli/config/init-config.d.ts +2 -1
  10. package/dist/cli/config/init-config.js +33 -1
  11. package/dist/cli/config/init-config.js.map +1 -1
  12. package/dist/client/gemini/gemini-protocol-client.js +2 -1
  13. package/dist/client/gemini/gemini-protocol-client.js.map +1 -1
  14. package/dist/client/gemini-cli/gemini-cli-protocol-client.js +39 -15
  15. package/dist/client/gemini-cli/gemini-cli-protocol-client.js.map +1 -1
  16. package/dist/client/openai/chat-protocol-client.js +2 -1
  17. package/dist/client/openai/chat-protocol-client.js.map +1 -1
  18. package/dist/client/responses/responses-protocol-client.js +2 -1
  19. package/dist/client/responses/responses-protocol-client.js.map +1 -1
  20. package/dist/error-handling/quiet-error-handling-center.js +46 -8
  21. package/dist/error-handling/quiet-error-handling-center.js.map +1 -1
  22. package/dist/manager/modules/quota/provider-quota-daemon.events.js +4 -2
  23. package/dist/manager/modules/quota/provider-quota-daemon.events.js.map +1 -1
  24. package/dist/manager/modules/quota/provider-quota-daemon.model-backoff.js +9 -6
  25. package/dist/manager/modules/quota/provider-quota-daemon.model-backoff.js.map +1 -1
  26. package/dist/providers/auth/antigravity-userinfo-helper.d.ts +2 -1
  27. package/dist/providers/auth/antigravity-userinfo-helper.js +25 -4
  28. package/dist/providers/auth/antigravity-userinfo-helper.js.map +1 -1
  29. package/dist/providers/auth/tokenfile-auth.d.ts +2 -0
  30. package/dist/providers/auth/tokenfile-auth.js +33 -1
  31. package/dist/providers/auth/tokenfile-auth.js.map +1 -1
  32. package/dist/providers/core/config/camoufox-launcher.d.ts +5 -0
  33. package/dist/providers/core/config/camoufox-launcher.js +5 -0
  34. package/dist/providers/core/config/camoufox-launcher.js.map +1 -1
  35. package/dist/providers/core/config/service-profiles.js +7 -18
  36. package/dist/providers/core/config/service-profiles.js.map +1 -1
  37. package/dist/providers/core/runtime/base-provider.d.ts +0 -5
  38. package/dist/providers/core/runtime/base-provider.js +26 -112
  39. package/dist/providers/core/runtime/base-provider.js.map +1 -1
  40. package/dist/providers/core/runtime/gemini-cli-http-provider.d.ts +7 -0
  41. package/dist/providers/core/runtime/gemini-cli-http-provider.js +362 -93
  42. package/dist/providers/core/runtime/gemini-cli-http-provider.js.map +1 -1
  43. package/dist/providers/core/runtime/http-request-executor.d.ts +3 -0
  44. package/dist/providers/core/runtime/http-request-executor.js +110 -38
  45. package/dist/providers/core/runtime/http-request-executor.js.map +1 -1
  46. package/dist/providers/core/runtime/http-transport-provider.d.ts +3 -0
  47. package/dist/providers/core/runtime/http-transport-provider.js +80 -37
  48. package/dist/providers/core/runtime/http-transport-provider.js.map +1 -1
  49. package/dist/providers/core/runtime/rate-limit-manager.d.ts +1 -12
  50. package/dist/providers/core/runtime/rate-limit-manager.js +4 -77
  51. package/dist/providers/core/runtime/rate-limit-manager.js.map +1 -1
  52. package/dist/providers/core/utils/http-client.js +20 -43
  53. package/dist/providers/core/utils/http-client.js.map +1 -1
  54. package/dist/server/handlers/handler-utils.js +5 -1
  55. package/dist/server/handlers/handler-utils.js.map +1 -1
  56. package/dist/server/handlers/responses-handler.js +1 -1
  57. package/dist/server/handlers/responses-handler.js.map +1 -1
  58. package/dist/server/runtime/http-server/index.js +68 -29
  59. package/dist/server/runtime/http-server/index.js.map +1 -1
  60. package/dist/server/runtime/http-server/request-executor.js +50 -6
  61. package/dist/server/runtime/http-server/request-executor.js.map +1 -1
  62. package/dist/server/runtime/http-server/routes.js +4 -1
  63. package/dist/server/runtime/http-server/routes.js.map +1 -1
  64. package/dist/utils/strip-internal-keys.d.ts +12 -0
  65. package/dist/utils/strip-internal-keys.js +28 -0
  66. package/dist/utils/strip-internal-keys.js.map +1 -0
  67. package/docs/CHAT_PROCESS_PROTOCOL_AND_PIPELINE.md +221 -0
  68. package/docs/antigravity-gemini-format-cleanup.md +102 -0
  69. package/docs/antigravity-routing-contract.md +31 -0
  70. package/docs/chat-semantic-expansion-plan.md +8 -6
  71. package/docs/glm-chat-completions.md +1 -1
  72. package/docs/servertool-framework.md +65 -0
  73. package/docs/v2-architecture/README.md +6 -8
  74. package/docs/verified-configs/README.md +60 -0
  75. package/docs/verified-configs/v0.45.0/README.md +244 -0
  76. package/docs/verified-configs/v0.45.0/lmstudio-5521-gpt-oss-20b-mlx.json +135 -0
  77. package/docs/verified-configs/v0.45.0/merged-config.5521.json +1205 -0
  78. package/docs/verified-configs/v0.45.0/merged-config.qwen-5522.json +1559 -0
  79. package/docs/verified-configs/v0.45.0/qwen-5522-qwen3-coder-plus-final.json +221 -0
  80. package/docs/verified-configs/v0.45.0/qwen-5522-qwen3-coder-plus-fixed.json +242 -0
  81. package/docs/verified-configs/v0.45.0/qwen-5522-qwen3-coder-plus.json +242 -0
  82. package/package.json +17 -11
  83. package/scripts/build-core.mjs +3 -1
  84. package/scripts/ci/repo-sanity.mjs +138 -0
  85. package/scripts/mock-provider/run-regressions.mjs +157 -1
  86. package/scripts/run-bg.sh +0 -14
  87. package/scripts/tests/ci-jest.mjs +119 -0
  88. package/scripts/tools-dev/responses-debug-client/README.md +23 -0
  89. package/scripts/tools-dev/responses-debug-client/payloads/poem.json +13 -0
  90. package/scripts/tools-dev/responses-debug-client/payloads/sample-no-tools.json +98 -0
  91. package/scripts/tools-dev/responses-debug-client/payloads/text.json +13 -0
  92. package/scripts/tools-dev/responses-debug-client/payloads/tool.json +27 -0
  93. package/scripts/tools-dev/responses-debug-client/run.mjs +65 -0
  94. package/scripts/tools-dev/responses-debug-client/src/index.ts +281 -0
  95. package/scripts/tools-dev/run-llmswitch-chat.mjs +53 -0
  96. package/scripts/tools-dev/server-tools-dev/run-web-fetch.mjs +65 -0
  97. package/scripts/vendor-core.mjs +13 -3
  98. package/scripts/test-fc-responses.mjs +0 -66
  99. package/scripts/test-guidance.mjs +0 -100
  100. package/scripts/test-iflow-web-search.mjs +0 -141
  101. package/scripts/test-iflow.mjs +0 -379
  102. package/scripts/test-tool-exec.mjs +0 -26
@@ -12,12 +12,18 @@ async function rmrf(p) {
12
12
 
13
13
  async function main() {
14
14
  const root = process.cwd();
15
+ const rawMode = String(process.env.BUILD_MODE || process.env.RCC_BUILD_MODE || 'release').toLowerCase();
16
+ const mode = rawMode === 'dev' ? 'dev' : 'release';
15
17
  const sharedDist = path.join(root, 'sharedmodule', 'llmswitch-core', 'dist');
16
18
  const legacyVendorDir = path.join(root, 'vendor', 'rcc-llmswitch-core');
17
19
  const scopedVendorDir = path.join(root, 'vendor', '@jsonstudio', 'llms');
18
20
 
19
- if (!await exists(sharedDist)) {
20
- console.error('[vendor-core] ERROR: 未找到 sharedmodule/llmswitch-core/dist');
21
+ // In release mode we rely on npm-installed `@jsonstudio/llms`, so the local sharedmodule dist
22
+ // is optional and must not block CI (where sharedmodule often doesn't exist).
23
+ // In dev mode, `node_modules/@jsonstudio/llms` is typically symlinked to sharedmodule/llmswitch-core,
24
+ // so we keep a hard requirement for the dist output.
25
+ if (mode === 'dev' && !await exists(sharedDist)) {
26
+ console.error('[vendor-core] ERROR: 未找到 sharedmodule/llmswitch-core/dist (BUILD_MODE=dev)');
21
27
  console.error('[vendor-core] 请先进入 sharedmodule/llmswitch-core 并运行 `npm run build`。');
22
28
  process.exit(2);
23
29
  }
@@ -31,7 +37,11 @@ async function main() {
31
37
  console.log('[vendor-core] removed legacy vendor/@jsonstudio/llms directory');
32
38
  }
33
39
 
34
- console.log('[vendor-core] sharedmodule/llmswitch-core/dist 将被直接引用,已停止生成 vendor 副本。');
40
+ if (mode === 'dev') {
41
+ console.log('[vendor-core] sharedmodule/llmswitch-core/dist 将被直接引用,已停止生成 vendor 副本。');
42
+ } else {
43
+ console.log('[vendor-core] BUILD_MODE=release: using npm-installed @jsonstudio/llms (no vendor copy).');
44
+ }
35
45
  }
36
46
 
37
47
  main().catch((err) => {
@@ -1,66 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * Minimal Responses client using the same OpenAI SDK
4
- * semantics as tools/responses-debug-client, for testing
5
- * upstream /v1/responses SSE behaviour.
6
- */
7
-
8
- import OpenAI from 'openai';
9
-
10
- const baseURL = process.argv[2] || 'https://www.fakercode.top/v1';
11
- const apiKey =
12
- process.argv[3] ||
13
- process.env.FC_API_KEY ||
14
- process.env.OPENAI_API_KEY ||
15
- '';
16
-
17
- if (!apiKey) {
18
- console.error('FC_API_KEY / OPENAI_API_KEY is required');
19
- process.exit(1);
20
- }
21
-
22
- const client = new OpenAI({ apiKey, baseURL });
23
-
24
- const payload = {
25
- model: process.env.FC_MODEL || 'gpt-5.1',
26
- input: [
27
- {
28
- role: 'user',
29
- content: [
30
- {
31
- type: 'input_text',
32
- text: '用一句话说“你好”,不要解释。'
33
- }
34
- ]
35
- }
36
- ],
37
- stream: true
38
- };
39
-
40
- console.log('BASE_URL', baseURL);
41
- console.log('MODEL', payload.model);
42
-
43
- try {
44
- const stream = await client.responses.stream(payload);
45
- console.log('STREAM_OK');
46
- for await (const event of stream) {
47
- console.log('EVENT', JSON.stringify(event));
48
- }
49
- } catch (err) {
50
- console.log('STREAM_ERROR');
51
- console.log(
52
- JSON.stringify(
53
- {
54
- name: err?.name,
55
- message: err?.message,
56
- status: err?.status,
57
- code: err?.code,
58
- type: err?.type,
59
- data: err?.response?.data
60
- },
61
- null,
62
- 2
63
- )
64
- );
65
- process.exit(1);
66
- }
@@ -1,100 +0,0 @@
1
- #!/usr/bin/env node
2
- import fs from 'fs';
3
- import path from 'path';
4
- import os from 'os';
5
- import { pathToFileURL } from 'url';
6
-
7
- const HOME = os.homedir();
8
- const base = path.join(HOME, '.routecodex', 'codex-samples');
9
- const guidanceMod = path.resolve(process.cwd(), 'sharedmodule/llmswitch-core/dist/guidance/index.js');
10
-
11
- async function loadGuidance() {
12
- const mod = await import(pathToFileURL(guidanceMod).href);
13
- const { refineSystemToolGuidance, augmentOpenAITools, augmentAnthropicTools, buildSystemToolGuidance } = mod;
14
- return { refineSystemToolGuidance, augmentOpenAITools, augmentAnthropicTools, buildSystemToolGuidance };
15
- }
16
-
17
- function readJsonSafe(p) {
18
- try { return JSON.parse(fs.readFileSync(p, 'utf8')); } catch { return null; }
19
- }
20
-
21
- function collectFiles(dir) {
22
- const out = [];
23
- try {
24
- for (const name of fs.readdirSync(dir)) {
25
- const full = path.join(dir, name);
26
- const st = fs.statSync(full);
27
- if (st.isFile()) out.push(full);
28
- }
29
- } catch { /* ignore */ }
30
- return out;
31
- }
32
-
33
- function extractRequest(obj) {
34
- // Try common capture shapes
35
- if (obj && typeof obj === 'object') {
36
- if (obj.body && typeof obj.body === 'object') return obj.body;
37
- if (obj.data && typeof obj.data === 'object') return obj.data;
38
- }
39
- return obj;
40
- }
41
-
42
- function hasOpenAITools(tools) {
43
- return Array.isArray(tools) && tools.some(t => t && typeof t === 'object' && t.function && typeof t.function === 'object');
44
- }
45
-
46
- function hasAnthropicTools(tools) {
47
- return Array.isArray(tools) && tools.some(t => t && typeof t === 'object' && t.input_schema);
48
- }
49
-
50
- async function main() {
51
- const { refineSystemToolGuidance, augmentOpenAITools, augmentAnthropicTools } = await loadGuidance();
52
- const targets = [
53
- path.join(base, 'openai-chat'),
54
- path.join(base, 'responses-replay'),
55
- path.join(base, 'anth-replay')
56
- ];
57
-
58
- let total = 0, refined = 0, augmented = 0;
59
-
60
- for (const d of targets) {
61
- const files = collectFiles(d);
62
- for (const f of files) {
63
- const j = readJsonSafe(f);
64
- if (!j) continue;
65
- const req = extractRequest(j);
66
- if (!req || typeof req !== 'object') continue;
67
- total++;
68
- // Refine system/instructions
69
- try {
70
- if (Array.isArray(req.messages) && req.messages.length && req.messages[0]?.role === 'system' && typeof req.messages[0].content === 'string') {
71
- const before = req.messages[0].content || '';
72
- const after = refineSystemToolGuidance(before);
73
- if (after !== before) refined++;
74
- } else if (typeof req.instructions === 'string' && req.instructions) {
75
- const before = req.instructions;
76
- const after = refineSystemToolGuidance(before);
77
- if (after !== before) refined++;
78
- }
79
- } catch { /* ignore */ }
80
- // Augment tools
81
- try {
82
- if (hasOpenAITools(req.tools)) {
83
- const before = JSON.stringify(req.tools);
84
- const t = augmentOpenAITools(req.tools);
85
- const after = JSON.stringify(t);
86
- if (after !== before) augmented++;
87
- } else if (hasAnthropicTools(req.tools)) {
88
- const before = JSON.stringify(req.tools);
89
- const t = augmentAnthropicTools(req.tools);
90
- const after = JSON.stringify(t);
91
- if (after !== before) augmented++;
92
- }
93
- } catch { /* ignore */ }
94
- }
95
- }
96
-
97
- console.log(JSON.stringify({ base, scannedDirs: targets, total, refined, augmented }, null, 2));
98
- }
99
-
100
- main().catch((e) => { console.error(e); process.exit(1); });
@@ -1,141 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * IFlow web_search 直连测试脚本(不经过 RouteCodex pipeline)
4
- *
5
- * 目标:完全复用 iFlow CLI 内置 WebSearchTool 的请求协议,验证
6
- * `https://apis.iflow.cn/v1/chat/retrieve` 能否正常返回搜索结果。
7
- *
8
- * 用法:
9
- * node scripts/test-iflow-web-search.mjs
10
- *
11
- * 可选环境变量:
12
- * IFLOW_SETTINGS_PATH 自定义 settings.json 路径(默认 ~/.iflow/settings.json)
13
- * IFLOW_SEARCH_QUERY 搜索关键词(默认: "today international news 2025")
14
- */
15
-
16
- import fs from 'node:fs/promises';
17
- import os from 'node:os';
18
- import path from 'node:path';
19
-
20
- async function main() {
21
- const settingsPath =
22
- process.env.IFLOW_SETTINGS_PATH ||
23
- path.join(os.homedir(), '.iflow', 'settings.json');
24
- const query =
25
- process.env.IFLOW_SEARCH_QUERY || 'today international news 2025';
26
-
27
- console.log(
28
- `[iflow-web-search] Using settings: ${settingsPath}, query="${query}"`
29
- );
30
-
31
- const settingsRaw = await fs.readFile(settingsPath, 'utf-8');
32
- const settings = JSON.parse(settingsRaw);
33
-
34
- const baseUrl =
35
- (typeof settings.baseUrl === 'string' && settings.baseUrl.trim()) ||
36
- 'https://apis.iflow.cn/v1';
37
- const searchApiKey =
38
- (typeof settings.searchApiKey === 'string' &&
39
- settings.searchApiKey.trim()) ||
40
- (typeof settings.apiKey === 'string' && settings.apiKey.trim()) ||
41
- null;
42
-
43
- if (!searchApiKey) {
44
- console.error(
45
- '[iflow-web-search] ERROR: searchApiKey/apiKey not found in settings.json'
46
- );
47
- process.exit(1);
48
- }
49
-
50
- const url = `${baseUrl.replace(/\/$/, '')}/chat/retrieve`;
51
-
52
- // Body 对齐 iFlow CLI WebSearchTool.executeInternal
53
- const body = {
54
- query,
55
- history: {},
56
- userId: 2,
57
- userIp: '42.120.74.197',
58
- appCode: 'SEARCH_CHATBOT',
59
- chatId: Date.now(), // 使用时间戳作为 chatId 即可
60
- phase: 'UNIFY',
61
- enableQueryRewrite: false,
62
- enableRetrievalSecurity: false,
63
- enableIntention: false,
64
- searchEngineList: ['GOOGLE', 'BING', 'SCHOLAR', 'AIPGC', 'PDF']
65
- };
66
-
67
- console.log(`[iflow-web-search] POST ${url}`);
68
-
69
- const controller = new AbortController();
70
- const timeoutMs = Number(process.env.IFLOW_SEARCH_TIMEOUT_MS || '30000');
71
- const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
72
-
73
- try {
74
- const res = await fetch(url, {
75
- method: 'POST',
76
- headers: {
77
- Authorization: `Bearer ${searchApiKey}`,
78
- 'Content-Type': 'application/json'
79
- },
80
- body: JSON.stringify(body),
81
- signal: controller.signal
82
- });
83
-
84
- clearTimeout(timeoutId);
85
-
86
- console.log(`[iflow-web-search] HTTP ${res.status}`);
87
- const json = await res.json().catch(async () => {
88
- const text = await res.text();
89
- console.error('[iflow-web-search] Non-JSON response:', text.slice(0, 500));
90
- throw new Error('Response is not valid JSON');
91
- });
92
-
93
- const dataArray = Array.isArray(json?.data) ? json.data : [];
94
- console.log(
95
- `[iflow-web-search] data.length = ${dataArray.length}, keys=${Object.keys(
96
- json || {}
97
- ).join(',')}`
98
- );
99
-
100
- if (!res.ok) {
101
- console.error(
102
- '[iflow-web-search] ERROR: upstream returned non-200 status',
103
- JSON.stringify(json, null, 2).slice(0, 2000)
104
- );
105
- process.exit(1);
106
- }
107
-
108
- if (!dataArray.length) {
109
- console.warn(
110
- '[iflow-web-search] WARN: data array is empty, check query or account permissions.'
111
- );
112
- } else {
113
- const first = dataArray[0] || {};
114
- console.log(
115
- '[iflow-web-search] First item:',
116
- JSON.stringify(
117
- {
118
- title: first.title,
119
- url: first.url,
120
- time: first.time,
121
- abstractInfo: first.abstractInfo
122
- },
123
- null,
124
- 2
125
- )
126
- );
127
- }
128
-
129
- console.log('[iflow-web-search] ✅ connectivity OK');
130
- } catch (error) {
131
- clearTimeout(timeoutId);
132
- console.error('[iflow-web-search] ❌ request failed:', error);
133
- process.exit(1);
134
- }
135
- }
136
-
137
- main().catch((error) => {
138
- console.error('[iflow-web-search] ❌ unexpected error:', error);
139
- process.exit(1);
140
- });
141
-