aicodeswitch 3.6.1 → 3.6.3

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/bin/upgrade.js CHANGED
@@ -231,8 +231,7 @@ const upgrade = async () => {
231
231
  chalk.yellow.bold('⚠️ Sudo privileges required\n\n') +
232
232
  chalk.white('This operation requires ') + chalk.yellow.bold('sudo') + chalk.white(' privileges.\n\n') +
233
233
  chalk.white('Please run the following command to upgrade:\n\n') +
234
- chalk.cyan.bold(' sudo npm install -g ' + PACKAGE_NAME + '@latest\n\n') +
235
- chalk.gray('After upgrading, run ') + chalk.cyan('aicos restart') + chalk.gray(' to restart the server.'),
234
+ chalk.cyan.bold(' sudo npm install -g ' + PACKAGE_NAME + '@latest'),
236
235
  {
237
236
  padding: 1,
238
237
  margin: 1,
@@ -241,6 +240,19 @@ const upgrade = async () => {
241
240
  }
242
241
  ));
243
242
  console.log('');
243
+ console.log(boxen(
244
+ chalk.red.bold('⚠️ 重启服务以使更改生效\n\n') +
245
+ chalk.white('升级完成后,必须重启服务才能使用新版本!\n\n') +
246
+ chalk.white('执行命令: ') + chalk.cyan.bold('aicos restart'),
247
+ {
248
+ padding: 1,
249
+ margin: 1,
250
+ borderStyle: 'round',
251
+ borderColor: 'red',
252
+ backgroundColor: 'red'
253
+ }
254
+ ));
255
+ console.log('');
244
256
  process.exit(0);
245
257
  }
246
258
 
@@ -274,9 +286,21 @@ const upgrade = async () => {
274
286
  }
275
287
  ));
276
288
  console.log('');
277
- console.log(chalk.cyan('💡 Tips:\n'));
278
- console.log(chalk.white(' • Restart server: ') + chalk.cyan('aicos restart'));
279
- console.log(chalk.white(' • Check version: ') + chalk.cyan('aicos version'));
289
+ console.log(boxen(
290
+ chalk.red.bold('⚠️ 重启服务以使更改生效\n\n') +
291
+ chalk.white('升级完成后,必须重启服务才能使用新版本!\n\n') +
292
+ chalk.white('执行命令: ') + chalk.cyan.bold('aicos restart'),
293
+ {
294
+ padding: 1,
295
+ margin: 1,
296
+ borderStyle: 'round',
297
+ borderColor: 'red',
298
+ backgroundColor: 'red'
299
+ }
300
+ ));
301
+ console.log('');
302
+ console.log(chalk.cyan('💡 其他命令:\n'));
303
+ console.log(chalk.white(' • 查看版本: ') + chalk.cyan('aicos version'));
280
304
  console.log('\n');
281
305
  };
282
306
 
@@ -243,10 +243,29 @@ const updateClaudeAgentTeamsConfig = (enableAgentTeams) => __awaiter(void 0, voi
243
243
  return false;
244
244
  }
245
245
  });
246
- const writeCodexConfig = (dbManager) => __awaiter(void 0, void 0, void 0, function* () {
246
+ const VALID_CODEX_REASONING_EFFORTS = ['low', 'medium', 'high'];
247
+ const DEFAULT_CODEX_REASONING_EFFORT = 'high';
248
+ const isCodexReasoningEffort = (value) => {
249
+ return typeof value === 'string' && VALID_CODEX_REASONING_EFFORTS.includes(value);
250
+ };
251
+ const buildCodexConfigToml = (modelReasoningEffort) => {
252
+ const localPort = process.env.PORT ? parseInt(process.env.PORT, 10) : 4567;
253
+ return `model_provider = "aicodeswitch"
254
+ model = "gpt-5.1-codex"
255
+ model_reasoning_effort = "${modelReasoningEffort}"
256
+ disable_response_storage = true
257
+
258
+
259
+ [model_providers.aicodeswitch]
260
+ name = "aicodeswitch"
261
+ base_url = "http://${host}:${localPort}/codex"
262
+ wire_api = "responses"
263
+ requires_openai_auth = true
264
+ `;
265
+ };
266
+ const writeCodexConfig = (dbManager_1, ...args_1) => __awaiter(void 0, [dbManager_1, ...args_1], void 0, function* (dbManager, modelReasoningEffort = DEFAULT_CODEX_REASONING_EFFORT) {
247
267
  try {
248
268
  const homeDir = os_1.default.homedir();
249
- const port = process.env.PORT ? parseInt(process.env.PORT, 10) : 4567;
250
269
  const config = dbManager.getConfig();
251
270
  // Codex config.toml
252
271
  const codexDir = path_1.default.join(homeDir, '.codex');
@@ -277,19 +296,7 @@ const writeCodexConfig = (dbManager) => __awaiter(void 0, void 0, void 0, functi
277
296
  if (!fs_1.default.existsSync(codexDir)) {
278
297
  fs_1.default.mkdirSync(codexDir, { recursive: true });
279
298
  }
280
- const codexConfig = `model_provider = "aicodeswitch"
281
- model = "gpt-5.1-codex"
282
- model_reasoning_effort = "high"
283
- disable_response_storage = true
284
-
285
-
286
- [model_providers.aicodeswitch]
287
- name = "aicodeswitch"
288
- base_url = "http://${host}:${port}/codex"
289
- wire_api = "responses"
290
- requires_openai_auth = true
291
- `;
292
- fs_1.default.writeFileSync(codexConfigPath, codexConfig);
299
+ fs_1.default.writeFileSync(codexConfigPath, buildCodexConfigToml(modelReasoningEffort));
293
300
  // Codex auth.json
294
301
  const codexAuthPath = path_1.default.join(codexDir, 'auth.json');
295
302
  // 同样处理 auth.json 的备份
@@ -308,7 +315,7 @@ requires_openai_auth = true
308
315
  configType: 'codex',
309
316
  timestamp: Date.now(),
310
317
  originalHash: originalConfigHash,
311
- proxyMarker: `http://${host}:${port}/codex`,
318
+ proxyMarker: `http://${host}:${process.env.PORT ? parseInt(process.env.PORT, 10) : 4567}/codex`,
312
319
  files: [
313
320
  {
314
321
  originalPath: codexConfigPath,
@@ -329,6 +336,35 @@ requires_openai_auth = true
329
336
  return false;
330
337
  }
331
338
  });
339
+ const updateCodexReasoningEffortConfig = (modelReasoningEffort) => __awaiter(void 0, void 0, void 0, function* () {
340
+ try {
341
+ const homeDir = os_1.default.homedir();
342
+ const codexConfigPath = path_1.default.join(homeDir, '.codex/config.toml');
343
+ if (!fs_1.default.existsSync(codexConfigPath)) {
344
+ console.error('Codex config.toml does not exist');
345
+ return false;
346
+ }
347
+ const configStatus = (0, config_metadata_1.checkCodexConfigStatus)();
348
+ if (!configStatus.isOverwritten) {
349
+ console.error('Codex config is not overwritten by proxy. Please activate a route first.');
350
+ return false;
351
+ }
352
+ fs_1.default.writeFileSync(codexConfigPath, buildCodexConfigToml(modelReasoningEffort));
353
+ const metadata = (0, config_metadata_1.loadMetadata)('codex');
354
+ if (metadata && metadata.files[0]) {
355
+ metadata.files[0].currentHash = (0, crypto_1.createHash)('sha256')
356
+ .update(fs_1.default.readFileSync(codexConfigPath, 'utf-8'))
357
+ .digest('hex');
358
+ metadata.timestamp = Date.now();
359
+ (0, config_metadata_1.saveMetadata)(metadata);
360
+ }
361
+ return true;
362
+ }
363
+ catch (error) {
364
+ console.error('Failed to update Codex reasoning effort config:', error);
365
+ return false;
366
+ }
367
+ });
332
368
  const restoreClaudeConfig = () => __awaiter(void 0, void 0, void 0, function* () {
333
369
  try {
334
370
  const homeDir = os_1.default.homedir();
@@ -1384,8 +1420,12 @@ ${instruction}
1384
1420
  const result = yield writeClaudeConfig(dbManager, enableAgentTeams);
1385
1421
  res.json(result);
1386
1422
  })));
1387
- app.post('/api/write-config/codex', asyncHandler((_req, res) => __awaiter(void 0, void 0, void 0, function* () {
1388
- const result = yield writeCodexConfig(dbManager);
1423
+ app.post('/api/write-config/codex', asyncHandler((req, res) => __awaiter(void 0, void 0, void 0, function* () {
1424
+ const requestedEffort = req.body.modelReasoningEffort;
1425
+ const modelReasoningEffort = isCodexReasoningEffort(requestedEffort)
1426
+ ? requestedEffort
1427
+ : DEFAULT_CODEX_REASONING_EFFORT;
1428
+ const result = yield writeCodexConfig(dbManager, modelReasoningEffort);
1389
1429
  res.json(result);
1390
1430
  })));
1391
1431
  // 更新Claude Code配置中的Agent Teams设置(当路由已激活时)
@@ -1394,6 +1434,15 @@ ${instruction}
1394
1434
  const result = yield updateClaudeAgentTeamsConfig(enableAgentTeams);
1395
1435
  res.json(result);
1396
1436
  })));
1437
+ app.post('/api/update-codex-reasoning-effort', asyncHandler((req, res) => __awaiter(void 0, void 0, void 0, function* () {
1438
+ const requestedEffort = req.body.modelReasoningEffort;
1439
+ if (!isCodexReasoningEffort(requestedEffort)) {
1440
+ res.status(400).json({ error: 'Invalid modelReasoningEffort' });
1441
+ return;
1442
+ }
1443
+ const result = yield updateCodexReasoningEffortConfig(requestedEffort);
1444
+ res.json(result);
1445
+ })));
1397
1446
  app.post('/api/restore-config/claude', asyncHandler((_req, res) => __awaiter(void 0, void 0, void 0, function* () {
1398
1447
  const result = yield restoreClaudeConfig();
1399
1448
  res.json(result);
@@ -56,6 +56,7 @@ const claude_openai_1 = require("./transformers/claude-openai");
56
56
  const gemini_1 = require("./transformers/gemini");
57
57
  const types_1 = require("../types");
58
58
  const mcp_image_handler_1 = require("./mcp-image-handler");
59
+ const type_migration_1 = require("./type-migration");
59
60
  const SUPPORTED_TARGETS = ['claude-code', 'codex'];
60
61
  class ProxyServer {
61
62
  constructor(dbManager, app) {
@@ -136,6 +137,58 @@ class ProxyServer {
136
137
  if (!route) {
137
138
  return res.status(404).json({ error: 'No matching route found' });
138
139
  }
140
+ // 高智商命令检测和会话状态管理
141
+ const highIqCommand = this.detectHighIqCommand(req.body);
142
+ const sessionId = this.defaultExtractSessionId(req, route.targetType);
143
+ if (highIqCommand === 'on') {
144
+ // 检查是否有可用的高智商规则
145
+ const highIqRule = yield this.findHighIqRule(route.id);
146
+ if (highIqRule) {
147
+ console.log('[HIGH-IQ] Command detected: ON');
148
+ // 更新会话状态
149
+ if (sessionId) {
150
+ const session = this.dbManager.getSession(sessionId);
151
+ this.dbManager.upsertSession({
152
+ id: sessionId,
153
+ targetType: route.targetType,
154
+ title: session === null || session === void 0 ? void 0 : session.title,
155
+ firstRequestAt: (session === null || session === void 0 ? void 0 : session.firstRequestAt) || Date.now(),
156
+ lastRequestAt: Date.now(),
157
+ vendorId: session === null || session === void 0 ? void 0 : session.vendorId,
158
+ vendorName: session === null || session === void 0 ? void 0 : session.vendorName,
159
+ serviceId: session === null || session === void 0 ? void 0 : session.serviceId,
160
+ serviceName: session === null || session === void 0 ? void 0 : session.serviceName,
161
+ model: session === null || session === void 0 ? void 0 : session.model,
162
+ totalTokens: (session === null || session === void 0 ? void 0 : session.totalTokens) || 0,
163
+ requestCount: ((session === null || session === void 0 ? void 0 : session.requestCount) || 0) + 1,
164
+ // 新增字段
165
+ highIqMode: true,
166
+ highIqRuleId: highIqRule.id,
167
+ highIqEnabledAt: Date.now()
168
+ });
169
+ console.log(`[HIGH-IQ] Session ${sessionId} enabled with rule ${highIqRule.id}`);
170
+ }
171
+ }
172
+ else {
173
+ console.log('[HIGH-IQ] No available high-iq rule found');
174
+ }
175
+ }
176
+ else if (highIqCommand === 'off') {
177
+ console.log('[HIGH-IQ] Command detected: OFF');
178
+ // 关闭会话的高智商模式
179
+ if (sessionId) {
180
+ const session = this.dbManager.getSession(sessionId);
181
+ if (session === null || session === void 0 ? void 0 : session.highIqMode) {
182
+ this.dbManager.upsertSession(Object.assign(Object.assign({}, session), { highIqMode: false, lastRequestAt: Date.now(), requestCount: (session.requestCount || 0) + 1 }));
183
+ console.log(`[HIGH-IQ] Session ${sessionId} disabled`);
184
+ }
185
+ }
186
+ }
187
+ // 移除命令前缀(在发送给上游API之前)
188
+ if (highIqCommand) {
189
+ req.body = this.removeHighIqCommand(req.body);
190
+ console.log(`[HIGH-IQ] Removed command prefix`);
191
+ }
139
192
  // 检查是否启用故障切换
140
193
  const enableFailover = ((_a = this.config) === null || _a === void 0 ? void 0 : _a.enableFailover) !== false; // 默认为 true
141
194
  if (!enableFailover) {
@@ -341,6 +394,58 @@ class ProxyServer {
341
394
  if (!route) {
342
395
  return res.status(404).json({ error: `No active route found for target type: ${targetType}` });
343
396
  }
397
+ // 高智商命令检测和会话状态管理
398
+ const highIqCommand = this.detectHighIqCommand(req.body);
399
+ const sessionId = this.defaultExtractSessionId(req, targetType);
400
+ if (highIqCommand === 'on') {
401
+ // 检查是否有可用的高智商规则
402
+ const highIqRule = yield this.findHighIqRule(route.id);
403
+ if (highIqRule) {
404
+ console.log('[HIGH-IQ] Command detected: ON');
405
+ // 更新会话状态
406
+ if (sessionId) {
407
+ const session = this.dbManager.getSession(sessionId);
408
+ this.dbManager.upsertSession({
409
+ id: sessionId,
410
+ targetType: route.targetType,
411
+ title: session === null || session === void 0 ? void 0 : session.title,
412
+ firstRequestAt: (session === null || session === void 0 ? void 0 : session.firstRequestAt) || Date.now(),
413
+ lastRequestAt: Date.now(),
414
+ vendorId: session === null || session === void 0 ? void 0 : session.vendorId,
415
+ vendorName: session === null || session === void 0 ? void 0 : session.vendorName,
416
+ serviceId: session === null || session === void 0 ? void 0 : session.serviceId,
417
+ serviceName: session === null || session === void 0 ? void 0 : session.serviceName,
418
+ model: session === null || session === void 0 ? void 0 : session.model,
419
+ totalTokens: (session === null || session === void 0 ? void 0 : session.totalTokens) || 0,
420
+ requestCount: ((session === null || session === void 0 ? void 0 : session.requestCount) || 0) + 1,
421
+ // 新增字段
422
+ highIqMode: true,
423
+ highIqRuleId: highIqRule.id,
424
+ highIqEnabledAt: Date.now()
425
+ });
426
+ console.log(`[HIGH-IQ] Session ${sessionId} enabled with rule ${highIqRule.id}`);
427
+ }
428
+ }
429
+ else {
430
+ console.log('[HIGH-IQ] No available high-iq rule found');
431
+ }
432
+ }
433
+ else if (highIqCommand === 'off') {
434
+ console.log('[HIGH-IQ] Command detected: OFF');
435
+ // 关闭会话的高智商模式
436
+ if (sessionId) {
437
+ const session = this.dbManager.getSession(sessionId);
438
+ if (session === null || session === void 0 ? void 0 : session.highIqMode) {
439
+ this.dbManager.upsertSession(Object.assign(Object.assign({}, session), { highIqMode: false, lastRequestAt: Date.now(), requestCount: (session.requestCount || 0) + 1 }));
440
+ console.log(`[HIGH-IQ] Session ${sessionId} disabled`);
441
+ }
442
+ }
443
+ }
444
+ // 移除命令前缀(在发送给上游API之前)
445
+ if (highIqCommand) {
446
+ req.body = this.removeHighIqCommand(req.body);
447
+ console.log(`[HIGH-IQ] Removed command prefix`);
448
+ }
344
449
  // 检查是否启用故障切换
345
450
  const enableFailover = ((_a = this.config) === null || _a === void 0 ? void 0 : _a.enableFailover) !== false; // 默认为 true
346
451
  if (!enableFailover) {
@@ -771,6 +876,24 @@ class ProxyServer {
771
876
  return undefined;
772
877
  const body = req.body;
773
878
  const requestModel = body === null || body === void 0 ? void 0 : body.model;
879
+ // 新增:检查会话是否在高智商模式中
880
+ const targetType = this.getRouteTargetType(routeId);
881
+ if (targetType) {
882
+ const sessionId = this.defaultExtractSessionId(req, targetType);
883
+ if (sessionId) {
884
+ const session = this.dbManager.getSession(sessionId);
885
+ if ((session === null || session === void 0 ? void 0 : session.highIqMode) && session.highIqRuleId) {
886
+ // 验证规则是否仍然可用
887
+ const highIqRule = yield this.findHighIqRule(routeId);
888
+ if (highIqRule && highIqRule.id === session.highIqRuleId) {
889
+ console.log(`[HIGH-IQ] Session ${sessionId} using high-iq rule ${highIqRule.id}`);
890
+ return highIqRule;
891
+ }
892
+ // 规则不可用,自动关闭高智商模式
893
+ console.log(`[HIGH-IQ] Rule ${session.highIqRuleId} no longer available, auto-disable`);
894
+ }
895
+ }
896
+ }
774
897
  // 1. 首先查找 model-mapping 类型的规则,按 sortOrder 降序匹配
775
898
  if (requestModel) {
776
899
  const modelMappingRules = rules.filter(rule => rule.contentType === 'model-mapping' &&
@@ -1164,36 +1287,128 @@ class ProxyServer {
1164
1287
  }
1165
1288
  return false;
1166
1289
  }
1167
- removeHighIqPrefix(body) {
1168
- if (!(body === null || body === void 0 ? void 0 : body.messages) || !Array.isArray(body.messages)) {
1169
- return body;
1290
+ /**
1291
+ * 检测用户消息中的高智商命令
1292
+ * @returns 'on' - 开启命令 (!!), 'off' - 关闭命令 (!x), null - 无命令
1293
+ */
1294
+ detectHighIqCommand(body) {
1295
+ const messages = body === null || body === void 0 ? void 0 : body.messages;
1296
+ if (!Array.isArray(messages)) {
1297
+ return null;
1170
1298
  }
1171
- // 深拷贝 body 以避免修改原始对象
1172
- const processedBody = JSON.parse(JSON.stringify(body));
1173
- for (const message of processedBody.messages) {
1299
+ // 只检查最后一条用户消息
1300
+ for (let i = messages.length - 1; i >= 0; i--) {
1301
+ const message = messages[i];
1174
1302
  if ((message === null || message === void 0 ? void 0 : message.role) !== 'user')
1175
1303
  continue;
1176
1304
  const content = message === null || message === void 0 ? void 0 : message.content;
1177
- // 处理字符串类型的 content
1178
1305
  if (typeof content === 'string') {
1179
- if (content.trim().startsWith('!!')) {
1180
- // 移除 !! 前缀并执行 trim
1181
- message.content = content.replace(/^!!\s*/, '').trim();
1306
+ const trimmed = content.trim();
1307
+ if (trimmed.startsWith('!x')) {
1308
+ return 'off';
1309
+ }
1310
+ if (trimmed.startsWith('!!')) {
1311
+ return 'on';
1182
1312
  }
1183
1313
  }
1184
- // 处理数组类型的 content
1185
1314
  else if (Array.isArray(content)) {
1186
1315
  for (const block of content) {
1187
1316
  if ((block === null || block === void 0 ? void 0 : block.type) === 'text' && typeof block.text === 'string') {
1188
- if (block.text.trim().startsWith('!!')) {
1189
- // 移除 !! 前缀并执行 trim
1190
- block.text = block.text.replace(/^!!\s*/, '').trim();
1317
+ const trimmed = block.text.trim();
1318
+ if (trimmed.startsWith('!x')) {
1319
+ return 'off';
1320
+ }
1321
+ if (trimmed.startsWith('!!')) {
1322
+ return 'on';
1191
1323
  }
1192
1324
  }
1193
1325
  }
1194
1326
  }
1327
+ break; // 只检查最后一条用户消息
1195
1328
  }
1196
- return processedBody;
1329
+ return null;
1330
+ }
1331
+ /**
1332
+ * 移除用户消息中的高智商命令前缀
1333
+ */
1334
+ removeHighIqCommand(body) {
1335
+ if (!(body === null || body === void 0 ? void 0 : body.messages))
1336
+ return body;
1337
+ const processed = JSON.parse(JSON.stringify(body));
1338
+ for (let i = processed.messages.length - 1; i >= 0; i--) {
1339
+ const message = processed.messages[i];
1340
+ if ((message === null || message === void 0 ? void 0 : message.role) !== 'user')
1341
+ continue;
1342
+ const content = message === null || message === void 0 ? void 0 : message.content;
1343
+ if (typeof content === 'string') {
1344
+ const trimmed = content.trim();
1345
+ if (trimmed.startsWith('!x')) {
1346
+ message.content = trimmed.replace(/^!x\s*/, '').trim();
1347
+ }
1348
+ else if (trimmed.startsWith('!!')) {
1349
+ message.content = trimmed.replace(/^!!\s*/, '').trim();
1350
+ }
1351
+ }
1352
+ else if (Array.isArray(content)) {
1353
+ for (const block of content) {
1354
+ if ((block === null || block === void 0 ? void 0 : block.type) === 'text' && typeof block.text === 'string') {
1355
+ const trimmed = block.text.trim();
1356
+ if (trimmed.startsWith('!x')) {
1357
+ block.text = trimmed.replace(/^!x\s*/, '').trim();
1358
+ }
1359
+ else if (trimmed.startsWith('!!')) {
1360
+ block.text = trimmed.replace(/^!!\s*/, '').trim();
1361
+ }
1362
+ }
1363
+ }
1364
+ }
1365
+ break; // 只处理最后一条用户消息
1366
+ }
1367
+ return processed;
1368
+ }
1369
+ /**
1370
+ * 查找可用的高智商规则
1371
+ */
1372
+ findHighIqRule(routeId) {
1373
+ return __awaiter(this, void 0, void 0, function* () {
1374
+ const rules = this.getRulesByRouteId(routeId);
1375
+ if (!rules || rules.length === 0)
1376
+ return undefined;
1377
+ const highIqRules = rules.filter(rule => rule.contentType === 'high-iq' && !rule.isDisabled);
1378
+ // 过滤黑名单和限制
1379
+ for (const rule of highIqRules) {
1380
+ const isBlacklisted = yield this.dbManager.isServiceBlacklisted(rule.targetServiceId, routeId, 'high-iq');
1381
+ if (isBlacklisted)
1382
+ continue;
1383
+ // 检查并重置到期的规则
1384
+ this.dbManager.checkAndResetRuleIfNeeded(rule.id);
1385
+ this.dbManager.checkAndResetRequestCountIfNeeded(rule.id);
1386
+ // 检查token限制
1387
+ if (rule.tokenLimit && rule.totalTokensUsed !== undefined &&
1388
+ rule.totalTokensUsed >= rule.tokenLimit * 1000) {
1389
+ continue;
1390
+ }
1391
+ // 检查请求次数限制
1392
+ if (rule.requestCountLimit && rule.totalRequestsUsed !== undefined &&
1393
+ rule.totalRequestsUsed >= rule.requestCountLimit) {
1394
+ continue;
1395
+ }
1396
+ // 检查频率限制
1397
+ if (this.isFrequencyLimitExceeded(rule)) {
1398
+ continue;
1399
+ }
1400
+ return rule;
1401
+ }
1402
+ return undefined;
1403
+ });
1404
+ }
1405
+ /**
1406
+ * 获取路由的目标类型
1407
+ */
1408
+ getRouteTargetType(routeId) {
1409
+ const routes = this.dbManager.getRoutes();
1410
+ const route = routes.find(r => r.id === routeId);
1411
+ return (route === null || route === void 0 ? void 0 : route.targetType) || null;
1197
1412
  }
1198
1413
  hasBackgroundSignal(body) {
1199
1414
  var _a, _b, _c;
@@ -1316,10 +1531,14 @@ class ProxyServer {
1316
1531
  }
1317
1532
  /** 判断是否为 Claude 相关类型(使用 x-api-key 认证) */
1318
1533
  isClaudeSource(sourceType) {
1319
- return sourceType === 'claude-chat' || sourceType === 'claude';
1534
+ // 向下兼容:支持旧类型 'claude-code'
1535
+ const normalized = sourceType === 'claude-code' ? 'claude' : sourceType;
1536
+ return normalized === 'claude-chat' || normalized === 'claude';
1320
1537
  }
1321
1538
  isOpenAIChatSource(sourceType) {
1322
- return sourceType === 'openai-chat' || sourceType === 'openai' || sourceType === 'deepseek-reasoning-chat';
1539
+ // 向下兼容:支持旧类型 'openai-responses'
1540
+ const normalized = sourceType === 'openai-responses' ? 'openai' : sourceType;
1541
+ return normalized === 'openai-chat' || normalized === 'openai' || normalized === 'deepseek-reasoning-chat';
1323
1542
  }
1324
1543
  /** 判断是否为 Gemini 类型 */
1325
1544
  isGeminiSource(sourceType) {
@@ -1332,6 +1551,22 @@ class ProxyServer {
1332
1551
  isChatType(sourceType) {
1333
1552
  return sourceType.endsWith('-chat') || sourceType === 'gemini';
1334
1553
  }
1554
+ /**
1555
+ * 构建 OpenAI Responses 类型的完整 URL
1556
+ * - baseUrl 以 /v{number} 结尾时,直接拼接请求路径
1557
+ * - baseUrl 不带版本时,自动补 /v1 再拼接请求路径
1558
+ * - 兼容请求路径本身已携带版本前缀(如 /v1/responses)场景
1559
+ */
1560
+ buildOpenAIResponsesUrl(baseUrl, mappedPath) {
1561
+ const trimmedBase = baseUrl.trim().replace(/\/+$/, '');
1562
+ const normalizedPath = mappedPath.startsWith('/') || mappedPath === '' ? mappedPath : `/${mappedPath}`;
1563
+ const baseHasVersionSuffix = /\/v\d+$/i.test(trimmedBase);
1564
+ const pathHasVersionPrefix = /^\/v\d+(?:\/|$)/i.test(normalizedPath);
1565
+ if (baseHasVersionSuffix || pathHasVersionPrefix) {
1566
+ return `${trimmedBase}${normalizedPath}`;
1567
+ }
1568
+ return `${trimmedBase}/v1${normalizedPath}`;
1569
+ }
1335
1570
  /**
1336
1571
  * 构建 Gemini API 的完整 URL
1337
1572
  * 用户只填写 base 地址(如 https://generativelanguage.googleapis.com)
@@ -1713,7 +1948,9 @@ class ProxyServer {
1713
1948
  var _a, _b, _c, _d, _e;
1714
1949
  res.locals.skipLog = true;
1715
1950
  const startTime = Date.now();
1716
- const sourceType = (service.sourceType || 'openai-chat');
1951
+ const rawSourceType = service.sourceType || 'openai-chat';
1952
+ // 标准化 sourceType,将旧类型转换为新类型(向下兼容)
1953
+ const sourceType = (0, type_migration_1.normalizeSourceType)(rawSourceType);
1717
1954
  const targetType = route.targetType;
1718
1955
  const failoverEnabled = (options === null || options === void 0 ? void 0 : options.failoverEnabled) === true;
1719
1956
  const forwardedToServiceName = options === null || options === void 0 ? void 0 : options.forwardedToServiceName;
@@ -1837,11 +2074,6 @@ class ProxyServer {
1837
2074
  useMCPProcessing = false;
1838
2075
  }
1839
2076
  }
1840
- // 高智商请求处理:移除 !! 前缀
1841
- if (rule.contentType === 'high-iq' && requestBody.messages) {
1842
- requestBody = this.removeHighIqPrefix(requestBody);
1843
- console.log('[HIGH-IQ] Removed !! prefix from user messages');
1844
- }
1845
2077
  // 用于收集响应数据的变量
1846
2078
  let responseHeadersForLog;
1847
2079
  let responseBodyForLog;
@@ -2066,6 +2298,10 @@ class ProxyServer {
2066
2298
  const model = requestBody.model || rule.targetModel || 'gemini-pro';
2067
2299
  upstreamUrl = this.buildGeminiUrl(service.apiUrl, model, streamRequested);
2068
2300
  }
2301
+ else if (sourceType === 'openai') {
2302
+ // OpenAI Responses 兼容模式:自动处理 baseUrl 是否包含 /v{number}
2303
+ upstreamUrl = this.buildOpenAIResponsesUrl(service.apiUrl, mappedPath);
2304
+ }
2069
2305
  else if (this.isChatType(sourceType) || this.isGeminiChatSource(sourceType)) {
2070
2306
  // Chat 类型(包括 gemini-chat)直接使用用户配置的完整 URL
2071
2307
  upstreamUrl = service.apiUrl;
@@ -446,11 +446,11 @@ const transformClaudeRequestToOpenAIChat = (body, targetModel) => {
446
446
  openaiBody.thinking = { type: claudeThinking.type };
447
447
  }
448
448
  // 为 OpenAI Responses API 添加 reasoning 配置
449
- // 映射关系:enabled->medium, disabled->minimal, auto->low
449
+ // 映射关系:enabled->medium, disabled->low, auto->low
450
450
  if (claudeThinking.type) {
451
451
  const effortMap = {
452
452
  'enabled': 'medium',
453
- 'disabled': 'minimal',
453
+ 'disabled': 'low',
454
454
  'auto': 'low'
455
455
  };
456
456
  openaiBody.reasoning = {