aicodeswitch 3.6.1 → 3.6.2
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
|
|
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(
|
|
278
|
-
|
|
279
|
-
|
|
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
|
|
|
@@ -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
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
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
|
-
//
|
|
1172
|
-
|
|
1173
|
-
|
|
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
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
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
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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) {
|
|
@@ -1713,7 +1932,9 @@ class ProxyServer {
|
|
|
1713
1932
|
var _a, _b, _c, _d, _e;
|
|
1714
1933
|
res.locals.skipLog = true;
|
|
1715
1934
|
const startTime = Date.now();
|
|
1716
|
-
const
|
|
1935
|
+
const rawSourceType = service.sourceType || 'openai-chat';
|
|
1936
|
+
// 标准化 sourceType,将旧类型转换为新类型(向下兼容)
|
|
1937
|
+
const sourceType = (0, type_migration_1.normalizeSourceType)(rawSourceType);
|
|
1717
1938
|
const targetType = route.targetType;
|
|
1718
1939
|
const failoverEnabled = (options === null || options === void 0 ? void 0 : options.failoverEnabled) === true;
|
|
1719
1940
|
const forwardedToServiceName = options === null || options === void 0 ? void 0 : options.forwardedToServiceName;
|
|
@@ -1837,11 +2058,6 @@ class ProxyServer {
|
|
|
1837
2058
|
useMCPProcessing = false;
|
|
1838
2059
|
}
|
|
1839
2060
|
}
|
|
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
2061
|
// 用于收集响应数据的变量
|
|
1846
2062
|
let responseHeadersForLog;
|
|
1847
2063
|
let responseBodyForLog;
|
|
@@ -119,7 +119,7 @@ Error generating stack: `+a.message+`
|
|
|
119
119
|
|
|
120
120
|
路由未停用,请检查配置文件权限。`)}try{await Q.deactivateRoute(E),await _i(),await zu()}catch(ye){throw new Error(`配置文件已恢复,但路由停用失败: ${ye.message||"未知错误"}
|
|
121
121
|
|
|
122
|
-
请刷新页面后重试。`)}}catch(ye){console.error("停用路由失败:",ye),re.error(ye.message)}finally{_t(null)}},S2=async E=>{E.preventDefault();const X=new FormData(E.currentTarget),me={name:X.get("name"),description:X.get("description"),targetType:X.get("targetType"),isActive:!1};S?await Q.updateRoute(S.id,me):await Q.createRoute(me),v(!1),_i()},j2=async E=>{await e({message:"确定要删除此路由吗?",title:"确认删除",type:"danger",confirmText:"删除",cancelText:"取消"})&&(await Q.deleteRoute(E),_i(),g&&g.id===E&&(y(null),a([])),re.success("路由已删除"))},k2=async E=>{if(E.preventDefault(),D==="image-understanding"&&be&&!ae){re.warning("请选择一个MCP工具");return}if(!be&&!I){re.warning("请选择供应商API服务");return}if(!be&&P!==void 0&&It!==void 0&&P>It){re.warning(`Token超量值 (${P}k) 不能超过API服务的限制 (${It}k)`);return}if(!be&&de!==void 0&&K!==void 0&&de>K){re.warning(`请求次数超量值 (${de}) 不能超过API服务的限制 (${K})`);return}const X=new FormData(E.currentTarget),me={routeId:g.id,contentType:X.get("contentType"),targetServiceId:be?"":I,targetModel:be?void 0:N||void 0,replacedModel:L||void 0,sortOrder:R,timeout:H?H*1e3:void 0,tokenLimit:be?void 0:P||void 0,resetInterval:be?void 0:Z,tokenResetBaseTime:be?void 0:ue?ue.getTime():void 0,requestCountLimit:be?void 0:de,requestResetInterval:be?void 0:ne,requestResetBaseTime:be?void 0:q?q.getTime():void 0,frequencyLimit:Ce,frequencyWindow:we,useMCP:D==="image-understanding"?be:!1,mcpId:D==="image-understanding"&&be?ae:void 0};j?await Q.updateRule(j.id,me):await Q.createRule(me),w(!1),g&&Ae(g.id)},P2=async E=>{await e({message:"确定要删除此路由吗?",title:"确认删除",type:"danger",confirmText:"删除",cancelText:"取消"})&&(await Q.deleteRule(E),g&&Ae(g.id),re.success("规则已删除"))},C2=async E=>{try{await Q.clearRuleBlacklist(E),g&&Ae(g.id),re.success("已恢复")}catch(X){re.error("恢复失败: "+X.message)}},O2=async E=>{try{const X=await Q.toggleRuleDisable(E);g&&Ae(g.id),re.success(X.isDisabled?"规则已屏蔽":"规则已启用")}catch(X){re.error("操作失败: "+X.message)}},E2=async E=>{try{const X=i.find(ye=>ye.id===E);if(!X)return;const me=(X.sortOrder||0)+1;await Q.updateRule(E,{sortOrder:me}),g&&Ae(g.id),re.success("优先级已提升")}catch(X){re.error("操作失败: "+X.message)}},A2=async E=>{try{const X=i.find(ye=>ye.id===E);if(!X)return;const me=Math.max(0,(X.sortOrder||0)-1);await Q.updateRule(E,{sortOrder:me}),g&&Ae(g.id),re.success("优先级已降低")}catch(X){re.error("操作失败: "+X.message)}},T2=async E=>{if(g){if(E&&!B()){re.error("当前 Claude Code 版本不支持 Agent Teams 功能,需要版本 ≥ 2.1.32");return}try{g.isActive?(await Q.updateClaudeAgentTeams(E),await Q.updateRoute(g.id,{enableAgentTeams:E}),re.success(E?"Agent Teams 功能已开启":"Agent Teams 功能已关闭")):(await Q.updateRoute(g.id,{enableAgentTeams:E}),re.success(E?"Agent Teams 设置已保存(将在激活时生效)":"Agent Teams 设置已取消")),y({...g,enableAgentTeams:E}),await _i()}catch(X){re.error("更新失败: "+X.message)}}},I2=()=>mw,_2=E=>{C(E),z(E.contentType),F(E.useMCP||!1),ie(E.mcpId||"");const X=s.find(me=>me.id===E.targetServiceId);X?(X.vendorId&&(M(X.vendorId),f(s.filter(me=>me.vendorId===X.vendorId))),setTimeout(()=>{if(_(X.id),V(E.targetModel||""),O(E.replacedModel||""),U(E.sortOrder||0),G(E.timeout?E.timeout/1e3:void 0),Y(E.tokenLimit||void 0),A(E.resetInterval),ge(E.tokenResetBaseTime?new Date(E.tokenResetBaseTime):void 0),W(E.requestCountLimit),se(E.requestResetInterval),_e(E.requestResetBaseTime?new Date(E.requestResetBaseTime):void 0),ve(E.frequencyLimit),Pe(E.frequencyWindow),X.enableTokenLimit&&X.tokenLimit){Gt(X.tokenLimit);const me=E.tokenLimit===X.tokenLimit&&E.resetInterval===(X.tokenResetInterval||void 0)&&E.tokenLimit!==null&&E.resetInterval!==null;$t(me)}else Gt(void 0),$t(!1);if(X.enableRequestLimit&&X.requestCountLimit){J(X.requestCountLimit);const me=E.requestCountLimit===X.requestCountLimit&&E.requestResetInterval===(X.requestResetInterval||void 0)&&E.requestCountLimit!==null&&E.requestResetInterval!==null;wt(me)}else J(void 0),wt(!1);$e(!!E.tokenLimit),Ve(!!E.requestCountLimit)},0)):E.useMCP&&(M(""),_(""),V(""),O(""),U(E.sortOrder||0),G(E.timeout?E.timeout/1e3:void 0),$e(!1),Ve(!1)),w(!0)},N2=E=>{var El;const X=xe[E.id],me=[],ye=t[E.id];if((ye==null?void 0:ye.status)==="in_use")return{status:"in_use",label:"使用中",reason:"正在处理请求"};if(X!=null&&X.isBlacklisted){const je=X.blacklistEntry;(je==null?void 0:je.errorType)==="timeout"?me.push("请求超时"):je!=null&&je.lastStatusCode&&me.push(`HTTP ${je.lastStatusCode}错误`)}const Le=(ye==null?void 0:ye.totalTokensUsed)!==void 0?ye.totalTokensUsed:E.totalTokensUsed;E.tokenLimit&&Le!==void 0&&Le>=E.tokenLimit*1e3&&me.push("Token超限");const St=(ye==null?void 0:ye.totalRequestsUsed)!==void 0?ye.totalRequestsUsed:E.totalRequestsUsed;if(E.requestCountLimit&&St!==void 0&&St>=E.requestCountLimit&&me.push("次数超限"),me.length>0)return{status:"error",label:X!=null&&X.isBlacklisted?((El=X.blacklistEntry)==null?void 0:El.errorType)==="timeout"?"超时":"服务错误":me[0],reason:me.join(", ")};const Ir=[];if(E.tokenLimit&&Le!==void 0){const je=Le/(E.tokenLimit*1e3)*100;je>=80&&Ir.push(`Token ${je.toFixed(0)}%`)}if(E.requestCountLimit&&St!==void 0){const je=St/E.requestCountLimit*100;je>=80&&Ir.push(`次数 ${je.toFixed(0)}%`)}return Ir.length>0?{status:"warning",label:"接近限制",reason:Ir.join(", ")}:{status:"success",label:"正常",reason:""}},M2=()=>{C(null),z("default"),M(""),_(""),V(""),O(""),U(0),G(void 0),Y(void 0),A(void 0),ge(void 0),W(void 0),se(void 0),_e(void 0),$t(!1),wt(!1),Gt(void 0),J(void 0),$e(!1),Ve(!1),F(!1),ie(""),w(!0)};return u.jsxs("div",{className:"routes-page",children:[u.jsxs("div",{className:"page-header",children:[u.jsx("h1",{children:"路由管理"}),u.jsx("p",{children:"管理API路由和路由配置"})]}),u.jsx("div",{style:{display:"flex",flexDirection:"column"},children:u.jsxs("div",{style:{display:"flex",gap:"20px"},children:[u.jsxs("div",{className:"card",style:{flex:"0 0 25%",minWidth:300},children:[u.jsxs("div",{className:"toolbar",children:[u.jsx("h3",{children:"路由"}),u.jsx("button",{className:"btn btn-primary",onClick:()=>v(!0),children:"新建"})]}),n.length===0?u.jsx("div",{className:"empty-state",children:u.jsx("p",{children:"暂无路由"})}):u.jsx("div",{style:{marginTop:"10px"},children:n.map(E=>{var X,me;return u.jsx("div",{ref:ye=>{ye?Gn.current.set(E.id,ye):Gn.current.delete(E.id)},onClick:()=>y(E),style:{padding:"12px",marginBottom:"8px",backgroundColor:g&&g.id===E.id?"var(--bg-route-item-selected)":"var(--bg-route-item)",borderRadius:"8px",cursor:"pointer",border:"1px solid var(--border-primary)",position:"relative"},children:u.jsxs("div",{children:[u.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center"},children:[u.jsx("div",{style:{fontWeight:500},children:E.name}),E.isActive&&u.jsxs("span",{className:`badge ${E.targetType==="claude-code"?"badge-claude-code":"badge-codex"}`,style:{position:"absolute",top:-16,right:-8},children:[(X=Yh.find(ye=>ye.value===E.targetType))==null?void 0:X.label," 已激活"]})]}),u.jsxs("div",{style:{fontSize:"12px",color:"var(--text-route-muted)",marginTop:"2px"},children:["客户端工具: ",(me=Yh.find(ye=>ye.value===E.targetType))==null?void 0:me.label]}),u.jsxs("div",{className:"action-buttons",style:{marginTop:"8px"},children:[E.isActive?u.jsx("button",{className:"btn btn-warning",style:{padding:"4px 8px",fontSize:"12px"},onClick:ye=>{ye.stopPropagation(),w2(E.id)},disabled:Tr!==null,children:Tr===E.id?"处理中...":"停用"}):u.jsx("button",{className:"btn btn-success",style:{padding:"4px 8px",fontSize:"12px"},onClick:ye=>{ye.stopPropagation(),b2(E.id)},disabled:Tr!==null,children:Tr===E.id?"处理中...":"激活"}),u.jsx("button",{className:"btn btn-secondary",style:{padding:"4px 8px",fontSize:"12px"},onClick:ye=>{ye.stopPropagation(),k(E),v(!0)},children:"编辑"}),u.jsx("button",{className:"btn btn-danger",style:{padding:"4px 8px",fontSize:"12px"},onClick:ye=>{ye.stopPropagation(),j2(E.id)},disabled:E.isActive,children:"删除"})]})]})},E.id)})})]}),u.jsxs("div",{style:{flex:1,display:"flex",flexDirection:"column"},children:[u.jsxs("div",{className:"card",style:{flex:1},children:[u.jsxs("div",{className:"toolbar",children:[u.jsx("h3",{children:"规则列表"}),g&&u.jsx("button",{className:"btn btn-primary",onClick:M2,children:"新建规则"})]}),g?i.length===0?u.jsx("div",{className:"empty-state",children:u.jsx("p",{children:"暂无路由"})}):u.jsxs("table",{className:"rules-table",children:[u.jsx("thead",{children:u.jsxs("tr",{children:[u.jsx("th",{className:"col-priority",children:"优先级"}),u.jsx("th",{children:"类型"}),u.jsx("th",{children:"API服务"}),u.jsx("th",{children:"状态"}),u.jsx("th",{children:"用量情况"}),u.jsx("th",{children:"操作"})]})}),u.jsx("tbody",{children:[...i].sort((E,X)=>{const me=E.sortOrder||0,ye=X.sortOrder||0;if(me!==ye)return ye-me;const Le=gw[E.contentType]??999,St=gw[X.contentType]??999;return Le-St}).map(E=>{var Le,St,Ir,El;const X=s.find(je=>je.id===E.targetServiceId),me=o.find(je=>je.id===(X==null?void 0:X.vendorId)),ye=(Le=mw.find(je=>je.value===E.contentType))==null?void 0:Le.label;return u.jsxs("tr",{children:[u.jsx("td",{className:"col-priority",children:u.jsxs("div",{className:"col-priority-box",children:[u.jsx("span",{children:E.sortOrder||0}),u.jsx("button",{className:"priority-arrow-btn",onClick:()=>A2(E.id),title:"降低优先级",children:"↓"}),u.jsx("button",{className:"priority-arrow-btn",onClick:()=>E2(E.id),title:"提升优先级",children:"↑"})]})}),u.jsx("td",{children:u.jsxs("div",{style:{fontSize:"12px",whiteSpace:"nowrap"},children:[E.contentType!=="default"&&vw[E.contentType]&&u.jsx("span",{style:{fontSize:"14px"},children:vw[E.contentType]}),u.jsx("span",{children:ye}),E.contentType==="model-mapping"&&E.replacedModel&&u.jsxs("div",{style:{position:"relative",display:"inline-block"},onMouseEnter:()=>Pt(E.id),onMouseLeave:()=>Pt(null),children:[u.jsx("span",{style:{cursor:"help",fontSize:"14px",color:"var(--text-info)",fontWeight:"bold"},children:"ⓘ"}),Mn===E.id&&u.jsxs("div",{style:{position:"absolute",left:"50%",transform:"translateX(-50%)",bottom:"calc(100% + 8px)",backgroundColor:"var(--bg-popover, #333)",color:"var(--text-popover, #fff)",padding:"6px 10px",borderRadius:"4px",fontSize:"12px",whiteSpace:"nowrap",zIndex:1e3,boxShadow:"0 2px 8px rgba(0,0,0,0.15)"},children:["被顶替的模型是: ",E.replacedModel,u.jsx("div",{style:{position:"absolute",left:"50%",transform:"translateX(-50%)",bottom:"-4px",width:"0",height:"0",borderLeft:"4px solid transparent",borderRight:"4px solid transparent",borderTop:"4px solid var(--bg-popover, #333)"}})]})]})]})}),u.jsx("td",{children:u.jsx("div",{className:"vendor-sevices-col",style:{fontSize:"0.6em"},children:E.useMCP?u.jsxs(u.Fragment,{children:[u.jsxs("div",{children:["MCP:",((St=p.find(je=>je.id===E.mcpId))==null?void 0:St.name)||"Unknown"]}),u.jsx("div",{style:{fontSize:"11px",color:"var(--text-muted)"},children:"使用MCP工具"})]}):u.jsxs(u.Fragment,{children:[u.jsxs("div",{children:["供应商:",me?me.name:"Unknown"]}),u.jsxs("div",{children:["服务:",X?X.name:"Unknown"]}),u.jsxs("div",{children:["模型:",E.targetModel||"透传模型"]})]})})}),u.jsx("td",{style:{whiteSpace:"nowrap"},children:(()=>{var rb,ib;const je=N2(E),pn=xe[E.id],D2=(pn==null?void 0:pn.isBlacklisted)&&!((rb=je.reason)!=null&&rb.includes("Token超限"))&&!((ib=je.reason)!=null&&ib.includes("次数超限"));return E.isDisabled?u.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"6px"},children:[u.jsx("span",{style:{color:"#6c757d",fontWeight:"bold",fontSize:"14px"},children:"⊘"}),u.jsx("span",{style:{fontSize:"13px",color:"#6c757d",fontWeight:"bold"},children:"已屏蔽"})]}):u.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"6px",flexWrap:"wrap"},children:[u.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"6px"},children:[je.status==="success"&&u.jsx("span",{style:{color:"#28a745",fontWeight:"bold",fontSize:"14px"},children:"✓"}),je.status==="warning"&&u.jsx("span",{style:{color:"#ffc107",fontWeight:"bold",fontSize:"14px"},children:"⚠"}),je.status==="error"&&u.jsx("span",{style:{color:"#dc3545",fontWeight:"bold",fontSize:"14px"},children:"✗"}),je.status==="in_use"&&u.jsx(u.Fragment,{children:u.jsx("span",{style:{color:"#007bff",fontWeight:"bold",fontSize:"14px",animation:"pulse 1.5s ease-in-out infinite"},children:"●"})}),u.jsx("span",{style:{fontSize:"13px",color:je.status==="success"?"#28a745":je.status==="warning"?"#ffc107":je.status==="in_use"?"#007bff":"#dc3545",fontWeight:je.status!=="success"?"bold":"normal"},children:je.label}),je.reason&&u.jsxs("div",{style:{position:"relative",display:"inline-block",cursor:"help"},onMouseEnter:()=>Pt(E.id+"-status"),onMouseLeave:()=>Pt(null),children:[u.jsx("span",{style:{fontSize:"12px",color:"#999",marginLeft:"4px"},children:" ⓘ"}),Mn===E.id+"-status"&&u.jsxs("div",{style:{position:"absolute",left:"50%",transform:"translateX(-50%)",bottom:"calc(100% + 8px)",backgroundColor:"var(--bg-popover, #333)",color:"var(--text-popover, #fff)",padding:"6px 10px",borderRadius:"4px",fontSize:"12px",whiteSpace:"nowrap",zIndex:1e3,boxShadow:"0 2px 8px rgba(0,0,0,0.15)"},children:[je.reason,u.jsx("div",{style:{position:"absolute",left:"50%",transform:"translateX(-50%)",bottom:"-4px",width:"0",height:"0",borderLeft:"4px solid transparent",borderRight:"4px solid transparent",borderTop:"4px solid var(--bg-popover, #333)"}})]})]})]}),D2&&u.jsx("button",{className:"btn btn-info",style:{padding:"2px 8px",fontSize:"11px"},onClick:()=>C2(E.id),children:"恢复"})]})})()}),u.jsx("td",{children:E.tokenLimit||E.requestCountLimit?u.jsxs("div",{style:{fontSize:"13px"},children:[E.tokenLimit&&u.jsxs("div",{style:{whiteSpace:"nowrap"},children:[u.jsx("span",{style:{fontWeight:"bold",fontSize:"12px"},children:"Tokens:"}),u.jsxs(u.Fragment,{children:[u.jsxs("span",{style:{color:(()=>{var pn;const je=((pn=t[E.id])==null?void 0:pn.totalTokensUsed)??E.totalTokensUsed;return je&&E.tokenLimit&&je>=E.tokenLimit*1e3?"red":"inherit"})()},children:[(((((Ir=t[E.id])==null?void 0:Ir.totalTokensUsed)??E.totalTokensUsed)||0)/1e3).toFixed(1),"K/",E.tokenLimit.toFixed(0),"K"]}),(()=>{var pn;const je=((pn=t[E.id])==null?void 0:pn.totalTokensUsed)??E.totalTokensUsed;return je&&E.tokenLimit&&je>=E.tokenLimit*1e3?u.jsx("span",{style:{color:"red",marginLeft:"4px",fontWeight:"bold",fontSize:"11px"},children:"超限"}):null})()]})]}),E.requestCountLimit&&u.jsxs("div",{style:{marginTop:E.tokenLimit?"6px":0},children:[u.jsx("span",{style:{fontWeight:"bold",fontSize:"12px"},children:"次数:"}),u.jsxs(u.Fragment,{children:[u.jsxs("span",{style:{color:(()=>{var pn;const je=((pn=t[E.id])==null?void 0:pn.totalRequestsUsed)??E.totalRequestsUsed;return je&&E.requestCountLimit&&je>=E.requestCountLimit?"red":"inherit"})()},children:[(((El=t[E.id])==null?void 0:El.totalRequestsUsed)??E.totalTokensUsed)||0,"/",E.requestCountLimit]}),(()=>{var pn;const je=((pn=t[E.id])==null?void 0:pn.totalRequestsUsed)??E.totalRequestsUsed;return je&&E.requestCountLimit&&je>=E.requestCountLimit?u.jsx("span",{style:{color:"red",marginLeft:"4px",fontWeight:"bold",fontSize:"11px"},children:"超限"}):null})()]})]})]}):u.jsx("span",{style:{color:"#999",fontSize:"12px"},children:"不限制"})}),u.jsx("td",{children:u.jsxs("div",{className:"action-buttons",style:{justifyContent:"flex-end"},children:[u.jsx("button",{className:`btn ${E.isDisabled?"btn-success":"btn-warning"}`,onClick:()=>O2(E.id),title:E.isDisabled?"启用规则":"临时屏蔽规则",children:E.isDisabled?"启用":"屏蔽"}),u.jsx("button",{className:"btn btn-secondary",onClick:()=>_2(E),children:"编辑"}),u.jsx("button",{className:"btn btn-danger",onClick:()=>P2(E.id),children:"删除"})]})})]},E.id)})})]}):u.jsx("div",{className:"empty-state",children:u.jsx("p",{children:"请先选择一个路由"})}),g&&i.length>0&&u.jsxs("div",{style:{fontSize:"12px",color:"var(--text-info-box)",marginTop:"16px",padding:"12px",backgroundColor:"var(--bg-info-box)",borderRadius:"6px",border:"1px solid var(--border-info-box)",lineHeight:"1.6"},children:[u.jsx("strong",{children:"💡 智能故障切换机制"}),u.jsxs("div",{style:{marginTop:"6px"},children:["• 当同一请求类型配置多个规则时,系统会按排序优先使用第一个",u.jsx("br",{}),"• 如果某个服务报错(4xx/5xx)或请求超时,将自动切换到下一个可用服务",u.jsx("br",{}),"• 报错或超时的服务会被标记为不可用,有效期10分钟",u.jsx("br",{}),"• 10分钟后自动解除标记,如果再次报错或超时则重新标记",u.jsx("br",{}),"• 确保您的请求始终路由到稳定可用的服务",u.jsx("br",{}),"• 规则状态列会实时显示每个规则的可用性状态",u.jsx("br",{}),"• 如不需要此功能,可在",u.jsx("strong",{children:"设置"}),'页面关闭"启用智能故障切换"选项']})]})]}),g&&g.targetType==="claude-code"&&u.jsxs("div",{className:"card",children:[u.jsx("div",{className:"toolbar",children:u.jsx("h3",{children:"Claude Code 配置"})}),u.jsxs("div",{style:{padding:"20px"},children:[!B()&&((eb=Me==null?void 0:Me.claudeCode)==null?void 0:eb.version)&&u.jsxs("div",{style:{backgroundColor:"var(--bg-warning, #fff3cd)",border:"1px solid var(--border-warning, #ffc107)",borderRadius:"6px",padding:"12px",marginBottom:"12px",fontSize:"13px",color:"var(--text-warning, #856404)"},children:["⚠️ 当前 Claude Code 版本 (",Me.claudeCode.version,") 不支持 Agent Teams 功能。",u.jsx("br",{}),"Agent Teams 功能需要 Claude Code 版本 ≥ 2.1.32。请升级 Claude Code 后再使用此功能。"]}),u.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"12px"},children:[u.jsx("input",{type:"checkbox",id:"agent-teams-toggle",checked:g.enableAgentTeams||!1,onChange:E=>T2(E.target.checked),disabled:!B(),style:{cursor:B()?"pointer":"not-allowed",width:"16px",height:"16px"}}),u.jsx("label",{htmlFor:"agent-teams-toggle",style:{cursor:B()?"pointer":"not-allowed",fontSize:"14px",userSelect:"none",color:B()?"inherit":"var(--text-muted)"},children:"开启 Agent Teams 功能"})]}),u.jsx("div",{style:{fontSize:"12px",color:"var(--text-muted)",marginTop:"12px"},children:B()?g.isActive?"开启后将在 Claude Code 中启用 Agent Teams 实验性功能,已立即生效。":"开启后将在激活此路由时启用 Agent Teams 实验性功能。":"Agent Teams 功能需要 Claude Code 版本 ≥ 2.1.32。请升级 Claude Code 后再使用此功能。"})]})]})]})]})}),u.jsxs("div",{className:"card",style:{marginTop:"20px"},children:[u.jsx("div",{className:"toolbar",children:u.jsx("h3",{children:"📝 配置文件自动管理"})}),u.jsxs("div",{style:{padding:"20px",lineHeight:"1.8"},children:[u.jsxs("div",{style:{background:"var(--bg-info-blue)",padding:"15px",borderRadius:"8px",marginBottom:"15px",borderLeft:"4px solid var(--border-info-blue)"},children:[u.jsx("strong",{children:"💡 工作原理"}),u.jsx("p",{style:{marginTop:"8px",marginBottom:"0"},children:"激活路由时,系统会自动修改编程工具的配置文件,使其通过本代理服务器访问AI服务。 停用路由时,系统会自动恢复原始配置。"})]}),u.jsxs("div",{style:{display:"grid",gridTemplateColumns:"1fr 1fr",gap:"15px"},children:[u.jsxs("div",{style:{background:"var(--bg-info-green)",padding:"15px",borderRadius:"8px",borderLeft:"4px solid var(--border-info-green)"},children:[u.jsx("strong",{children:"✓ 激活路由"}),u.jsxs("ul",{style:{marginTop:"8px",paddingLeft:"20px",marginBottom:"0"},children:[u.jsx("li",{children:"首次激活:自动备份并覆盖配置文件"}),u.jsx("li",{children:"再次激活:仅切换路由,不重复覆盖"})]})]}),u.jsxs("div",{style:{background:"var(--bg-info-orange)",padding:"15px",borderRadius:"8px",borderLeft:"4px solid var(--border-info-orange)"},children:[u.jsx("strong",{children:"○ 停用路由"}),u.jsxs("ul",{style:{marginTop:"8px",paddingLeft:"20px",marginBottom:"0"},children:[u.jsx("li",{children:"自动恢复原始配置文件"}),u.jsx("li",{children:"删除备份文件"})]})]})]}),u.jsxs("div",{style:{marginTop:"15px",padding:"12px 15px",background:"var(--bg-info-yellow)",borderRadius:"8px",borderLeft:"4px solid var(--border-info-yellow)"},children:[u.jsx("strong",{children:"⚠️ 重要提示"}),u.jsxs("ul",{style:{marginTop:"8px",paddingLeft:"20px",marginBottom:"0"},children:[u.jsxs("li",{children:["激活(首次)/停用路由后,",u.jsx("strong",{children:"必须重启对应的编程工具"}),"才能使配置生效"]}),u.jsx("li",{children:"操作前建议关闭编程工具,避免配置冲突"})]})]}),u.jsxs("details",{style:{marginTop:"15px",cursor:"pointer"},children:[u.jsx("summary",{style:{fontWeight:"bold",color:"#666"},children:"📂 配置文件位置(点击展开)"}),u.jsxs("ul",{style:{marginTop:"8px",paddingLeft:"20px",color:"#666"},children:[u.jsxs("li",{children:[u.jsx("strong",{children:"Claude Code:"})," ~/.claude/settings.json, ~/.claude.json"]}),u.jsxs("li",{children:[u.jsx("strong",{children:"Codex:"})," ~/.codex/config.toml, ~/.codex/auth.json"]})]})]})]})]}),x&&u.jsxs("div",{className:"modal-overlay",children:[u.jsx("button",{type:"button",className:"modal-close-btn",onClick:()=>v(!1),"aria-label":"关闭",children:"×"}),u.jsx("div",{className:"modal",children:u.jsxs("div",{className:"modal-container",children:[u.jsx("div",{className:"modal-header",children:u.jsx("h2",{children:S?"编辑路由":"新建路由"})}),u.jsxs("form",{onSubmit:S2,children:[u.jsxs("div",{className:"form-group",children:[u.jsx("label",{children:"路由名称"}),u.jsx("input",{type:"text",name:"name",defaultValue:S?S.name:"",required:!0})]}),u.jsxs("div",{className:"form-group",children:[u.jsx("label",{children:"描述"}),u.jsx("textarea",{name:"description",rows:3,defaultValue:S?S.description:""})]}),u.jsxs("div",{className:"form-group",children:[u.jsx("label",{children:"客户端工具"}),u.jsx("select",{name:"targetType",defaultValue:S?S.targetType:"claude-code",required:!0,children:Yh.map(E=>u.jsx("option",{value:E.value,children:E.label},E.value))})]}),u.jsxs("div",{className:"modal-footer",children:[u.jsx("button",{type:"button",className:"btn btn-secondary",onClick:()=>v(!1),children:"取消"}),u.jsx("button",{type:"submit",className:"btn btn-primary",children:"保存"})]})]})]})})]}),b&&u.jsxs("div",{className:"modal-overlay",children:[u.jsx("button",{type:"button",className:"modal-close-btn",onClick:()=>w(!1),"aria-label":"关闭",children:"×"}),u.jsx("div",{className:"modal",children:u.jsxs("div",{className:"modal-container",children:[u.jsx("div",{className:"modal-header",children:u.jsx("h2",{children:j?"编辑规则":"新建规则"})}),u.jsxs("form",{onSubmit:k2,children:[u.jsxs("div",{className:"form-group",children:[u.jsx("label",{children:"对象请求类型"}),u.jsx("select",{name:"contentType",value:D,required:!0,onChange:E=>{z(E.target.value)},children:I2().map(E=>u.jsx("option",{value:E.value,children:E.label},E.value))})]}),D==="high-iq"&&u.jsxs("div",{style:{background:"var(--bg-info-blue)",padding:"12px",borderRadius:"6px",borderLeft:"4px solid var(--border-info-blue)",marginBottom:"16px"},children:[u.jsx("div",{style:{fontSize:"13px",fontWeight:"bold",marginBottom:"6px"},children:"💡 高智商请求使用方法"}),u.jsxs("div",{style:{fontSize:"12px",color:"var(--text-muted)",lineHeight:"1.6"},children:["在编程工具中输入提示词时,使用 ",u.jsx("code",{style:{background:"var(--bg-code-inline, #f5f5f5)",padding:"2px 6px",borderRadius:"3px",fontFamily:"monospace",fontSize:"12px"},children:"!!"})," 前缀即可自动切换到高智商模型。"]}),u.jsxs("div",{style:{fontSize:"12px",color:"var(--text-muted)",marginTop:"8px",lineHeight:"1.6"},children:[u.jsx("strong",{children:"示例:"}),u.jsx("br",{}),"• ",u.jsx("code",{style:{background:"var(--bg-code-inline, #f5f5f5)",padding:"2px 6px",borderRadius:"3px",fontFamily:"monospace",fontSize:"12px"},children:"!! 重构A模块"}),u.jsx("br",{}),"• ",u.jsx("code",{style:{background:"var(--bg-code-inline, #f5f5f5)",padding:"2px 6px",borderRadius:"3px",fontFamily:"monospace",fontSize:"12px"},children:"!! 这个算法性能太差,帮我优化"})]})]}),D==="model-mapping"&&u.jsxs("div",{className:"form-group",children:[u.jsxs("label",{children:["被顶替模型 ",u.jsx("small",{children:"(可在日志中找出想要顶替的模型名)"})]}),u.jsx("input",{type:"text",value:L,onChange:E=>O(E.target.value),placeholder:"例如:gpt-4"})]}),D==="image-understanding"&&u.jsxs("div",{className:"form-group",children:[u.jsxs("label",{style:{display:"flex",alignItems:"center",cursor:"pointer"},children:[u.jsx("input",{type:"checkbox",checked:be,onChange:E=>F(E.target.checked),style:{marginRight:"8px",cursor:"pointer",width:"16px",height:"16px"}}),u.jsx("span",{children:"使用MCP"})]}),u.jsx("small",{style:{color:"#666",fontSize:"12px",marginTop:"4px",display:"block"},children:"开启后,将使用MCP工具处理图像理解请求,而不是直接调用API服务"})]}),D==="image-understanding"&&be&&u.jsxs("div",{className:"form-group",children:[u.jsxs("label",{children:["选择MCP工具 ",u.jsx("span",{className:"required",children:"*"})]}),u.jsx("div",{style:{maxHeight:"300px",overflowY:"auto",border:"1px solid var(--border-primary)",borderRadius:"6px",padding:"8px"},children:p.length===0?u.jsx("div",{style:{padding:"12px",textAlign:"center",color:"var(--text-muted)"},children:"暂无MCP工具,请先在MCP管理页面添加"}):p.map(E=>u.jsxs("div",{onClick:()=>ie(E.id),style:{padding:"12px",marginBottom:"8px",border:`2px solid ${ae===E.id?"var(--primary-color)":"var(--border-primary)"}`,borderRadius:"6px",cursor:"pointer",backgroundColor:ae===E.id?"var(--bg-info-blue)":"var(--bg-card)",transition:"all 0.2s ease"},children:[u.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center"},children:[u.jsx("div",{style:{fontWeight:600,fontSize:"14px"},children:E.name}),u.jsx("div",{className:"badge badge-secondary",style:{fontSize:"11px"},children:E.type==="stdio"?"命令行":E.type.toUpperCase()})]}),E.description&&u.jsx("div",{style:{fontSize:"12px",color:"var(--text-muted)",marginTop:"4px"},children:E.description})]},E.id))})]}),!be&&u.jsxs(u.Fragment,{children:[u.jsxs("div",{className:"form-group",children:[u.jsx("label",{children:"供应商"}),u.jsxs("select",{value:T,onChange:E=>M(E.target.value),required:!0,children:[u.jsx("option",{value:"",disabled:!0,children:"请选择供应商"}),o.map(E=>u.jsx("option",{value:E.id,children:E.name},E.id))]})]}),u.jsxs("div",{className:"form-group",children:[u.jsx("label",{children:"供应商API服务"}),u.jsxs("select",{value:I,onChange:E=>{const X=E.target.value;_(X),V("");const me=s.find(ye=>ye.id===X);me&&(me.enableTokenLimit&&me.tokenLimit?(Y(me.tokenLimit),A(me.tokenResetInterval),ge(me.tokenResetBaseTime?new Date(me.tokenResetBaseTime):void 0),Gt(me.tokenLimit),$t(!0),$e(!0)):(Gt(void 0),$t(!1),$e(!1)),me.enableRequestLimit&&me.requestCountLimit?(W(me.requestCountLimit),se(me.requestResetInterval),_e(me.requestResetBaseTime?new Date(me.requestResetBaseTime):void 0),J(me.requestCountLimit),wt(!0),Ve(!0)):(J(void 0),wt(!1),Ve(!1)))},required:!0,disabled:!T,children:[u.jsx("option",{value:"",disabled:!0,children:"请选择API服务"}),d.map(E=>u.jsx("option",{value:E.id,children:E.name},E.id))]})]}),u.jsxs("div",{className:"form-group",children:[u.jsx("label",{children:"供应商模型"}),u.jsxs("select",{value:N,onChange:E=>V(E.target.value),disabled:!I,children:[u.jsx("option",{value:"",children:"透传模型名"}),(nb=(tb=s.find(E=>E.id===I))==null?void 0:tb.supportedModels)==null?void 0:nb.map(E=>u.jsx("option",{value:E,children:E},E))]})]}),u.jsx("div",{className:"form-group",children:u.jsxs("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between"},children:[u.jsxs("label",{style:{display:"flex",alignItems:"center",cursor:xt?"not-allowed":"pointer"},children:[u.jsx("input",{type:"checkbox",checked:Se,onChange:E=>$e(E.target.checked),disabled:xt,style:{marginRight:"8px",cursor:xt?"not-allowed":"pointer",width:"16px",height:"16px"}}),u.jsx("span",{children:"启用Tokens超量限制"}),xt&&u.jsx("small",{style:{color:"#999",fontSize:"12px",marginLeft:"8px"},children:"(从API服务继承)"})]}),xt&&u.jsx("button",{type:"button",className:"btn btn-sm btn-secondary",onClick:()=>$t(!1),style:{padding:"4px 12px",fontSize:"12px"},children:"自定义限制"})]})}),Se&&!xt&&u.jsxs(u.Fragment,{children:[u.jsxs("div",{className:"form-group",children:[u.jsx("label",{children:"Tokens超量(单位:k)"}),u.jsx("input",{type:"number",value:P||"",onChange:E=>{const X=E.target.value?parseInt(E.target.value):void 0;if(X!==void 0&&It!==void 0&&X>It){re.warning(`Token超量值不能超过API服务的限制 (${It}k)`);return}Y(X),xt&&X!==It&&$t(!1)},min:"0",max:It,placeholder:It?`最大 ${It}k`:"不限制",disabled:xt}),It&&u.jsxs("small",{style:{color:"#666",fontSize:"12px",marginTop:"4px",display:"block"},children:["⚠️ API服务限制:最大 ",It,"k,当前值不能超过此限制"]}),u.jsx("small",{style:{color:"#666",fontSize:"12px",marginTop:"4px",display:"block"},children:"当编程工具的请求tokens达到这个量时,在配置了其他规则的情况下,本条规则将失效,从而保护你的余额。例如:输入100表示100k即100,000个tokens"})]}),u.jsxs("div",{className:"form-group",children:[u.jsx("label",{children:"Tokens超量自动重置间隔(小时)"}),u.jsx("input",{type:"number",value:Z||"",onChange:E=>{A(E.target.value?parseInt(E.target.value):void 0),xt&&$t(!1)},min:"1",placeholder:"不自动重置",disabled:xt}),u.jsx("small",{style:{color:"#666",fontSize:"12px",marginTop:"4px",display:"block"},children:"设置后,系统将每隔指定小时数自动重置token计数。例如设置5小时,则每5小时重置一次"})]}),u.jsxs("div",{className:"form-group",children:[u.jsx("label",{children:"Token下一次重置时间基点"}),u.jsx("input",{type:"datetime-local",value:ue?yw(ue):"",onChange:E=>{E.target.value?ge(new Date(E.target.value)):ge(void 0),xt&&$t(!1)},disabled:!Z||xt,className:"datetime-picker-input"}),u.jsx("small",{style:{color:"#666",fontSize:"12px",marginTop:"4px",display:"block"},children:'配合"Tokens超量自动重置间隔"使用,设置下一次重置的精确时间点。例如,每月1日0点重置(间隔720小时),或每周一0点重置(间隔168小时)。设置后,系统会基于此时间点自动计算后续重置周期'})]})]}),u.jsx("div",{className:"form-group",children:u.jsxs("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between"},children:[u.jsxs("label",{style:{display:"flex",alignItems:"center",cursor:bt?"not-allowed":"pointer"},children:[u.jsx("input",{type:"checkbox",checked:Ne,onChange:E=>Ve(E.target.checked),disabled:bt,style:{marginRight:"8px",cursor:bt?"not-allowed":"pointer",width:"16px",height:"16px"}}),u.jsx("span",{children:"启用请求次数超量限制"}),bt&&u.jsx("small",{style:{color:"#999",fontSize:"12px",marginLeft:"8px"},children:"(从API服务继承)"})]}),bt&&u.jsx("button",{type:"button",className:"btn btn-sm btn-secondary",onClick:()=>wt(!1),style:{padding:"4px 12px",fontSize:"12px"},children:"自定义限制"})]})}),Ne&&!bt&&u.jsxs(u.Fragment,{children:[u.jsxs("div",{className:"form-group",children:[u.jsx("label",{children:"请求次数超量"}),u.jsx("input",{type:"number",value:de||"",onChange:E=>{const X=E.target.value?parseInt(E.target.value):void 0;if(X!==void 0&&K!==void 0&&X>K){re.warning(`请求次数超量值不能超过API服务的限制 (${K})`);return}W(X),bt&&X!==K&&wt(!1)},min:"0",max:K,placeholder:K?`最大 ${K}`:"不限制",disabled:bt}),K&&u.jsxs("small",{style:{color:"#666",fontSize:"12px",marginTop:"4px",display:"block"},children:["⚠️ API服务限制:最大 ",K,",当前值不能超过此限制"]}),u.jsx("small",{style:{color:"#666",fontSize:"12px",marginTop:"4px",display:"block"},children:"当请求次数达到这个量时,在配置了其他规则的情况下,本条规则将失效"})]}),u.jsxs("div",{className:"form-group",children:[u.jsx("label",{children:"请求次数自动重置间隔(小时)"}),u.jsx("input",{type:"number",value:ne||"",onChange:E=>{se(E.target.value?parseInt(E.target.value):void 0),bt&&wt(!1)},min:"1",placeholder:"不自动重置",disabled:bt}),u.jsx("small",{style:{color:"#666",fontSize:"12px",marginTop:"4px",display:"block"},children:"设置后,系统将每隔指定小时数自动重置请求次数计数。例如设置24小时,则每24小时重置一次"})]}),u.jsxs("div",{className:"form-group",children:[u.jsx("label",{children:"下一次重置时间基点"}),u.jsx("input",{type:"datetime-local",value:q?yw(q):"",onChange:E=>{E.target.value?_e(new Date(E.target.value)):_e(void 0),bt&&wt(!1)},disabled:!ne||bt,className:"datetime-picker-input"}),u.jsx("small",{style:{color:"#666",fontSize:"12px",marginTop:"4px",display:"block"},children:'配合"请求次数自动重置间隔"使用,设置下一次重置的精确时间点。例如,每月1日0点重置(间隔720小时),或每周一0点重置(间隔168小时)。设置后,系统会基于此时间点自动计算后续重置周期'})]})]})]}),u.jsxs("div",{className:"form-group",children:[u.jsxs("label",{style:{display:"flex",alignItems:"center",cursor:"pointer"},children:[u.jsx("input",{type:"checkbox",checked:!!Ce,onChange:E=>{E.target.checked?(ve(10),Pe(0)):(ve(void 0),Pe(void 0))},style:{marginRight:"8px",cursor:"pointer",width:"16px",height:"16px"}}),u.jsx("span",{children:"启用请求频率限制"})]}),u.jsx("small",{style:{color:"#666",fontSize:"12px",marginTop:"4px",display:"block"},children:"启用后,当同一内容类型的请求频率超过限制时,系统会自动切换到其他同类型规则"})]}),Ce&&u.jsxs(u.Fragment,{children:[u.jsxs("div",{className:"form-group",children:[u.jsx("label",{children:"频率限制次数(并发数)"}),u.jsx("input",{type:"number",value:Ce||"",onChange:E=>ve(E.target.value?parseInt(E.target.value):void 0),min:"1",placeholder:"例如: 10"}),u.jsx("small",{style:{color:"#666",fontSize:"12px",marginTop:"4px",display:"block"},children:"在指定时间窗口内允许的最大请求次数"})]}),u.jsxs("div",{className:"form-group",children:[u.jsx("label",{children:"频率限制时间窗口(秒,0=同一时刻)"}),u.jsx("input",{type:"number",value:we===0?0:we||"",onChange:E=>{const X=E.target.value?parseInt(E.target.value):void 0;Pe(X===0?0:X)},min:"0",placeholder:"0 表示同一时刻"}),u.jsx("small",{style:{color:"#666",fontSize:"12px",marginTop:"4px",display:"block"},children:"时间窗口大小。0 表示同一时刻(并发数),持续累积;设置为 60 则在 60 秒内最多允许 N 次请求"})]})]}),u.jsxs("div",{className:"form-group",children:[u.jsx("label",{children:"超时时间(秒)"}),u.jsx("input",{type:"number",value:H||"",onChange:E=>G(E.target.value?parseInt(E.target.value):void 0),min:"1",placeholder:"默认300秒"}),u.jsx("small",{style:{color:"#666",fontSize:"12px",marginTop:"4px",display:"block"},children:"设置此规则的API请求超时时间。不设置则使用默认值300秒(5分钟)"})]}),u.jsxs("div",{className:"form-group",children:[u.jsx("label",{children:"排序(值越大优先级越高)"}),u.jsx("input",{type:"number",value:R,onChange:E=>U(parseInt(E.target.value)||0),min:"0",max:"1000"})]}),u.jsxs("div",{className:"modal-footer",children:[u.jsx("button",{type:"button",className:"btn btn-secondary",onClick:()=>w(!1),children:"取消"}),u.jsx("button",{type:"submit",className:"btn btn-primary",children:"保存"})]})]})]})})]})]})}var AE={exports:{}};(function(e,t){(function(n,r){e.exports=r()})(Go,function(){var n=1e3,r=6e4,i=36e5,a="millisecond",o="second",l="minute",s="hour",c="day",d="week",f="month",p="quarter",h="year",g="date",y="Invalid Date",x=/^(\d{4})[-/]?(\d{1,2})?[-/]?(\d{0,2})[Tt\s]*(\d{1,2})?:?(\d{1,2})?:?(\d{1,2})?[.:]?(\d+)?$/,v=/\[([^\]]+)]|Y{1,4}|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a|A|m{1,2}|s{1,2}|Z{1,2}|SSS/g,b={name:"en",weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),ordinal:function(L){var O=["th","st","nd","rd"],R=L%100;return"["+L+(O[(R-20)%10]||O[R]||O[0])+"]"}},w=function(L,O,R){var U=String(L);return!U||U.length>=O?L:""+Array(O+1-U.length).join(R)+L},S={s:w,z:function(L){var O=-L.utcOffset(),R=Math.abs(O),U=Math.floor(R/60),D=R%60;return(O<=0?"+":"-")+w(U,2,"0")+":"+w(D,2,"0")},m:function L(O,R){if(O.date()<R.date())return-L(R,O);var U=12*(R.year()-O.year())+(R.month()-O.month()),D=O.clone().add(U,f),z=R-D<0,P=O.clone().add(U+(z?-1:1),f);return+(-(U+(R-D)/(z?D-P:P-D))||0)},a:function(L){return L<0?Math.ceil(L)||0:Math.floor(L)},p:function(L){return{M:f,y:h,w:d,d:c,D:g,h:s,m:l,s:o,ms:a,Q:p}[L]||String(L||"").toLowerCase().replace(/s$/,"")},u:function(L){return L===void 0}},k="en",j={};j[k]=b;var C="$isDayjsObject",T=function(L){return L instanceof N||!(!L||!L[C])},M=function L(O,R,U){var D;if(!O)return k;if(typeof O=="string"){var z=O.toLowerCase();j[z]&&(D=z),R&&(j[z]=R,D=z);var P=O.split("-");if(!D&&P.length>1)return L(P[0])}else{var Y=O.name;j[Y]=O,D=Y}return!U&&D&&(k=D),D||!U&&k},I=function(L,O){if(T(L))return L.clone();var R=typeof O=="object"?O:{};return R.date=L,R.args=arguments,new N(R)},_=S;_.l=M,_.i=T,_.w=function(L,O){return I(L,{locale:O.$L,utc:O.$u,x:O.$x,$offset:O.$offset})};var N=function(){function L(R){this.$L=M(R.locale,null,!0),this.parse(R),this.$x=this.$x||R.x||{},this[C]=!0}var O=L.prototype;return O.parse=function(R){this.$d=function(U){var D=U.date,z=U.utc;if(D===null)return new Date(NaN);if(_.u(D))return new Date;if(D instanceof Date)return new Date(D);if(typeof D=="string"&&!/Z$/i.test(D)){var P=D.match(x);if(P){var Y=P[2]-1||0,Z=(P[7]||"0").substring(0,3);return z?new Date(Date.UTC(P[1],Y,P[3]||1,P[4]||0,P[5]||0,P[6]||0,Z)):new Date(P[1],Y,P[3]||1,P[4]||0,P[5]||0,P[6]||0,Z)}}return new Date(D)}(R),this.init()},O.init=function(){var R=this.$d;this.$y=R.getFullYear(),this.$M=R.getMonth(),this.$D=R.getDate(),this.$W=R.getDay(),this.$H=R.getHours(),this.$m=R.getMinutes(),this.$s=R.getSeconds(),this.$ms=R.getMilliseconds()},O.$utils=function(){return _},O.isValid=function(){return this.$d.toString()!==y},O.isSame=function(R,U){var D=I(R);return this.startOf(U)<=D&&D<=this.endOf(U)},O.isAfter=function(R,U){return I(R)<this.startOf(U)},O.isBefore=function(R,U){return this.endOf(U)<I(R)},O.$g=function(R,U,D){return _.u(R)?this[U]:this.set(D,R)},O.unix=function(){return Math.floor(this.valueOf()/1e3)},O.valueOf=function(){return this.$d.getTime()},O.startOf=function(R,U){var D=this,z=!!_.u(U)||U,P=_.p(R),Y=function(W,ne){var se=_.w(D.$u?Date.UTC(D.$y,ne,W):new Date(D.$y,ne,W),D);return z?se:se.endOf(c)},Z=function(W,ne){return _.w(D.toDate()[W].apply(D.toDate("s"),(z?[0,0,0,0]:[23,59,59,999]).slice(ne)),D)},A=this.$W,ue=this.$M,ge=this.$D,H="set"+(this.$u?"UTC":"");switch(P){case h:return z?Y(1,0):Y(31,11);case f:return z?Y(1,ue):Y(0,ue+1);case d:var G=this.$locale().weekStart||0,de=(A<G?A+7:A)-G;return Y(z?ge-de:ge+(6-de),ue);case c:case g:return Z(H+"Hours",0);case s:return Z(H+"Minutes",1);case l:return Z(H+"Seconds",2);case o:return Z(H+"Milliseconds",3);default:return this.clone()}},O.endOf=function(R){return this.startOf(R,!1)},O.$set=function(R,U){var D,z=_.p(R),P="set"+(this.$u?"UTC":""),Y=(D={},D[c]=P+"Date",D[g]=P+"Date",D[f]=P+"Month",D[h]=P+"FullYear",D[s]=P+"Hours",D[l]=P+"Minutes",D[o]=P+"Seconds",D[a]=P+"Milliseconds",D)[z],Z=z===c?this.$D+(U-this.$W):U;if(z===f||z===h){var A=this.clone().set(g,1);A.$d[Y](Z),A.init(),this.$d=A.set(g,Math.min(this.$D,A.daysInMonth())).$d}else Y&&this.$d[Y](Z);return this.init(),this},O.set=function(R,U){return this.clone().$set(R,U)},O.get=function(R){return this[_.p(R)]()},O.add=function(R,U){var D,z=this;R=Number(R);var P=_.p(U),Y=function(ue){var ge=I(z);return _.w(ge.date(ge.date()+Math.round(ue*R)),z)};if(P===f)return this.set(f,this.$M+R);if(P===h)return this.set(h,this.$y+R);if(P===c)return Y(1);if(P===d)return Y(7);var Z=(D={},D[l]=r,D[s]=i,D[o]=n,D)[P]||1,A=this.$d.getTime()+R*Z;return _.w(A,this)},O.subtract=function(R,U){return this.add(-1*R,U)},O.format=function(R){var U=this,D=this.$locale();if(!this.isValid())return D.invalidDate||y;var z=R||"YYYY-MM-DDTHH:mm:ssZ",P=_.z(this),Y=this.$H,Z=this.$m,A=this.$M,ue=D.weekdays,ge=D.months,H=D.meridiem,G=function(ne,se,q,_e){return ne&&(ne[se]||ne(U,z))||q[se].slice(0,_e)},de=function(ne){return _.s(Y%12||12,ne,"0")},W=H||function(ne,se,q){var _e=ne<12?"AM":"PM";return q?_e.toLowerCase():_e};return z.replace(v,function(ne,se){return se||function(q){switch(q){case"YY":return String(U.$y).slice(-2);case"YYYY":return _.s(U.$y,4,"0");case"M":return A+1;case"MM":return _.s(A+1,2,"0");case"MMM":return G(D.monthsShort,A,ge,3);case"MMMM":return G(ge,A);case"D":return U.$D;case"DD":return _.s(U.$D,2,"0");case"d":return String(U.$W);case"dd":return G(D.weekdaysMin,U.$W,ue,2);case"ddd":return G(D.weekdaysShort,U.$W,ue,3);case"dddd":return ue[U.$W];case"H":return String(Y);case"HH":return _.s(Y,2,"0");case"h":return de(1);case"hh":return de(2);case"a":return W(Y,Z,!0);case"A":return W(Y,Z,!1);case"m":return String(Z);case"mm":return _.s(Z,2,"0");case"s":return String(U.$s);case"ss":return _.s(U.$s,2,"0");case"SSS":return _.s(U.$ms,3,"0");case"Z":return P}return null}(ne)||P.replace(":","")})},O.utcOffset=function(){return 15*-Math.round(this.$d.getTimezoneOffset()/15)},O.diff=function(R,U,D){var z,P=this,Y=_.p(U),Z=I(R),A=(Z.utcOffset()-this.utcOffset())*r,ue=this-Z,ge=function(){return _.m(P,Z)};switch(Y){case h:z=ge()/12;break;case f:z=ge();break;case p:z=ge()/3;break;case d:z=(ue-A)/6048e5;break;case c:z=(ue-A)/864e5;break;case s:z=ue/i;break;case l:z=ue/r;break;case o:z=ue/n;break;default:z=ue}return D?z:_.a(z)},O.daysInMonth=function(){return this.endOf(f).$D},O.$locale=function(){return j[this.$L]},O.locale=function(R,U){if(!R)return this.$L;var D=this.clone(),z=M(R,U,!0);return z&&(D.$L=z),D},O.clone=function(){return _.w(this.$d,this)},O.toDate=function(){return new Date(this.valueOf())},O.toJSON=function(){return this.isValid()?this.toISOString():null},O.toISOString=function(){return this.$d.toISOString()},O.toString=function(){return this.$d.toUTCString()},L}(),V=N.prototype;return I.prototype=V,[["$ms",a],["$s",o],["$m",l],["$H",s],["$W",c],["$M",f],["$y",h],["$D",g]].forEach(function(L){V[L[1]]=function(O){return this.$g(O,L[0],L[1])}}),I.extend=function(L,O){return L.$i||(L(O,N,I),L.$i=!0),I},I.locale=M,I.isDayjs=T,I.unix=function(L){return I(1e3*L)},I.en=j[k],I.Ls=j,I.p={},I})})(AE);var yB=AE.exports;const on=Vn(yB);var TE={exports:{}};(function(e,t){(function(n,r){e.exports=r()})(Go,function(){return function(n,r,i){n=n||{};var a=r.prototype,o={future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"};function l(c,d,f,p){return a.fromToBase(c,d,f,p)}i.en.relativeTime=o,a.fromToBase=function(c,d,f,p,h){for(var g,y,x,v=f.$locale().relativeTime||o,b=n.thresholds||[{l:"s",r:44,d:"second"},{l:"m",r:89},{l:"mm",r:44,d:"minute"},{l:"h",r:89},{l:"hh",r:21,d:"hour"},{l:"d",r:35},{l:"dd",r:25,d:"day"},{l:"M",r:45},{l:"MM",r:10,d:"month"},{l:"y",r:17},{l:"yy",d:"year"}],w=b.length,S=0;S<w;S+=1){var k=b[S];k.d&&(g=p?i(c).diff(f,k.d,!0):f.diff(c,k.d,!0));var j=(n.rounding||Math.round)(Math.abs(g));if(x=g>0,j<=k.r||!k.r){j<=1&&S>0&&(k=b[S-1]);var C=v[k.l];h&&(j=h(""+j)),y=typeof C=="string"?C.replace("%d",j):C(j,d,k.l,x);break}}if(d)return y;var T=x?v.future:v.past;return typeof T=="function"?T(y):T.replace("%s",y)},a.to=function(c,d){return l(c,d,this,!0)},a.from=function(c,d){return l(c,d,this)};var s=function(c){return c.$u?i.utc():i()};a.toNow=function(c){return this.to(s(this),c)},a.fromNow=function(c){return this.from(s(this),c)}}})})(TE);var xB=TE.exports;const bB=Vn(xB),wB=["authorization","x-api-key","api-key","apikey","x-auth-token","auth-token","secret","password","api_secret","jwt","csrf_token","xsrf_token","auth_token","session_token","private_key","client_secret"],SB=e=>{const t=e.toLowerCase();return!!(wB.some(n=>t===n)||t.startsWith("api_")&&(t.endsWith("_key")||t.endsWith("_secret"))||(t.endsWith("_token")||t.endsWith("_key")||t.endsWith("_secret"))&&!["max_tokens","input_tokens","output_tokens","completion_tokens","prompt_tokens","cachereadinputtokens","totaltokens"].some(r=>t.replace(/_/g,"").includes(r.replace(/_/g,""))))},jB=e=>!e||e.length<=8?"***":`${e.slice(0,4)}${"*".repeat(Math.min(e.length-8,20))}${e.slice(-4)}`,Ig=e=>{if(e==null)return e;if(Array.isArray(e))return e.map(t=>Ig(t));if(typeof e=="object"){const t={};for(const[n,r]of Object.entries(e))SB(n)?t[n]=typeof r=="string"?jB(r):"***":typeof r=="object"?t[n]=Ig(r):t[n]=r;return t}return e},pr=({data:e,title:t,collapsed:n=!1})=>{const[r,i]=m.useState(!n),[a,o]=m.useState(!1),l=d=>{try{let f;typeof d=="string"?f=JSON.parse(d):f=d;const p=Ig(f);return JSON.stringify(p,null,2)}catch{return typeof d=="string"?d:String(d)}},s=()=>{const d=l(e);navigator.clipboard.writeText(d).then(()=>{o(!0),setTimeout(()=>o(!1),2e3)}).catch(f=>{console.error("Failed to copy JSON:",f)})},c=l(e);return u.jsxs("div",{className:"json-viewer",children:[u.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:"8px"},children:[t&&u.jsx("h4",{style:{margin:0,fontSize:"14px",color:"var(--text-primary)"},children:t}),u.jsxs("div",{style:{display:"flex",gap:"8px"},children:[u.jsx("button",{onClick:()=>i(!r),className:"btn btn-sm btn-secondary",style:{fontSize:"12px",padding:"2px 8px"},children:r?"折叠":"展开"}),u.jsx("button",{onClick:s,className:"btn btn-sm btn-primary",style:{fontSize:"12px",padding:"2px 8px"},children:a?"已复制":"复制"})]})]}),r&&u.jsx("pre",{style:{background:"var(--bg-code)",border:"1px solid var(--border-primary)",borderRadius:"8px",padding:"12px",overflowX:"auto",fontSize:"12px",lineHeight:"1.4",color:"var(--text-primary)",maxHeight:"400px",overflowY:"auto",margin:0},children:u.jsx("code",{children:c})})]})},Xh=({currentPage:e,totalItems:t,pageSize:n,onPageChange:r,onPageSizeChange:i,pageSizeOptions:a=[10,20,50,100]})=>{const o=Math.max(1,Math.ceil(t/n)),l=e===1,s=e>=o,c=()=>{l||r(1)},d=()=>{l||r(e-1)},f=()=>{s||r(e+1)},p=()=>{s||r(o)},h=g=>{const y=parseInt(g.target.value,10);i(y)};return u.jsxs("div",{className:"pagination",children:[u.jsxs("div",{className:"pagination-info",children:["共 ",t," 条"]}),u.jsxs("div",{className:"pagination-controls",children:[u.jsx("button",{className:"pagination-btn",onClick:c,disabled:l,children:"首页"}),u.jsx("button",{className:"pagination-btn",onClick:d,disabled:l,children:"上一页"}),u.jsxs("span",{className:"pagination-info",children:["第 ",e," / ",o," 页"]}),u.jsx("button",{className:"pagination-btn",onClick:f,disabled:s,children:"下一页"}),u.jsx("button",{className:"pagination-btn",onClick:p,disabled:s,children:"尾页"})]}),u.jsx("div",{className:"pagination-size",children:u.jsxs("label",{children:["每页显示",u.jsx("select",{className:"pagination-select",value:n,onChange:h,children:a.map(g=>u.jsx("option",{value:g,children:g},g))}),"条"]})})]})};on.extend(bB);function kB(e){const t=[];let n={dataLines:[],rawLines:[]};for(const r of e){const i=r.split(`
|
|
122
|
+
请刷新页面后重试。`)}}catch(ye){console.error("停用路由失败:",ye),re.error(ye.message)}finally{_t(null)}},S2=async E=>{E.preventDefault();const X=new FormData(E.currentTarget),me={name:X.get("name"),description:X.get("description"),targetType:X.get("targetType"),isActive:!1};S?await Q.updateRoute(S.id,me):await Q.createRoute(me),v(!1),_i()},j2=async E=>{await e({message:"确定要删除此路由吗?",title:"确认删除",type:"danger",confirmText:"删除",cancelText:"取消"})&&(await Q.deleteRoute(E),_i(),g&&g.id===E&&(y(null),a([])),re.success("路由已删除"))},k2=async E=>{if(E.preventDefault(),D==="image-understanding"&&be&&!ae){re.warning("请选择一个MCP工具");return}if(!be&&!I){re.warning("请选择供应商API服务");return}if(!be&&P!==void 0&&It!==void 0&&P>It){re.warning(`Token超量值 (${P}k) 不能超过API服务的限制 (${It}k)`);return}if(!be&&de!==void 0&&K!==void 0&&de>K){re.warning(`请求次数超量值 (${de}) 不能超过API服务的限制 (${K})`);return}const X=new FormData(E.currentTarget),me={routeId:g.id,contentType:X.get("contentType"),targetServiceId:be?"":I,targetModel:be?void 0:N||void 0,replacedModel:L||void 0,sortOrder:R,timeout:H?H*1e3:void 0,tokenLimit:be?void 0:P||void 0,resetInterval:be?void 0:Z,tokenResetBaseTime:be?void 0:ue?ue.getTime():void 0,requestCountLimit:be?void 0:de,requestResetInterval:be?void 0:ne,requestResetBaseTime:be?void 0:q?q.getTime():void 0,frequencyLimit:Ce,frequencyWindow:we,useMCP:D==="image-understanding"?be:!1,mcpId:D==="image-understanding"&&be?ae:void 0};j?await Q.updateRule(j.id,me):await Q.createRule(me),w(!1),g&&Ae(g.id)},P2=async E=>{await e({message:"确定要删除此路由吗?",title:"确认删除",type:"danger",confirmText:"删除",cancelText:"取消"})&&(await Q.deleteRule(E),g&&Ae(g.id),re.success("规则已删除"))},C2=async E=>{try{await Q.clearRuleBlacklist(E),g&&Ae(g.id),re.success("已恢复")}catch(X){re.error("恢复失败: "+X.message)}},O2=async E=>{try{const X=await Q.toggleRuleDisable(E);g&&Ae(g.id),re.success(X.isDisabled?"规则已屏蔽":"规则已启用")}catch(X){re.error("操作失败: "+X.message)}},E2=async E=>{try{const X=i.find(ye=>ye.id===E);if(!X)return;const me=(X.sortOrder||0)+1;await Q.updateRule(E,{sortOrder:me}),g&&Ae(g.id),re.success("优先级已提升")}catch(X){re.error("操作失败: "+X.message)}},A2=async E=>{try{const X=i.find(ye=>ye.id===E);if(!X)return;const me=Math.max(0,(X.sortOrder||0)-1);await Q.updateRule(E,{sortOrder:me}),g&&Ae(g.id),re.success("优先级已降低")}catch(X){re.error("操作失败: "+X.message)}},T2=async E=>{if(g){if(E&&!B()){re.error("当前 Claude Code 版本不支持 Agent Teams 功能,需要版本 ≥ 2.1.32");return}try{g.isActive?(await Q.updateClaudeAgentTeams(E),await Q.updateRoute(g.id,{enableAgentTeams:E}),re.success(E?"Agent Teams 功能已开启":"Agent Teams 功能已关闭")):(await Q.updateRoute(g.id,{enableAgentTeams:E}),re.success(E?"Agent Teams 设置已保存(将在激活时生效)":"Agent Teams 设置已取消")),y({...g,enableAgentTeams:E}),await _i()}catch(X){re.error("更新失败: "+X.message)}}},I2=()=>mw,_2=E=>{C(E),z(E.contentType),F(E.useMCP||!1),ie(E.mcpId||"");const X=s.find(me=>me.id===E.targetServiceId);X?(X.vendorId&&(M(X.vendorId),f(s.filter(me=>me.vendorId===X.vendorId))),setTimeout(()=>{if(_(X.id),V(E.targetModel||""),O(E.replacedModel||""),U(E.sortOrder||0),G(E.timeout?E.timeout/1e3:void 0),Y(E.tokenLimit||void 0),A(E.resetInterval),ge(E.tokenResetBaseTime?new Date(E.tokenResetBaseTime):void 0),W(E.requestCountLimit),se(E.requestResetInterval),_e(E.requestResetBaseTime?new Date(E.requestResetBaseTime):void 0),ve(E.frequencyLimit),Pe(E.frequencyWindow),X.enableTokenLimit&&X.tokenLimit){Gt(X.tokenLimit);const me=E.tokenLimit===X.tokenLimit&&E.resetInterval===(X.tokenResetInterval||void 0)&&E.tokenLimit!==null&&E.resetInterval!==null;$t(me)}else Gt(void 0),$t(!1);if(X.enableRequestLimit&&X.requestCountLimit){J(X.requestCountLimit);const me=E.requestCountLimit===X.requestCountLimit&&E.requestResetInterval===(X.requestResetInterval||void 0)&&E.requestCountLimit!==null&&E.requestResetInterval!==null;wt(me)}else J(void 0),wt(!1);$e(!!E.tokenLimit),Ve(!!E.requestCountLimit)},0)):E.useMCP&&(M(""),_(""),V(""),O(""),U(E.sortOrder||0),G(E.timeout?E.timeout/1e3:void 0),$e(!1),Ve(!1)),w(!0)},N2=E=>{var El;const X=xe[E.id],me=[],ye=t[E.id];if((ye==null?void 0:ye.status)==="in_use")return{status:"in_use",label:"使用中",reason:"正在处理请求"};if(X!=null&&X.isBlacklisted){const je=X.blacklistEntry;(je==null?void 0:je.errorType)==="timeout"?me.push("请求超时"):je!=null&&je.lastStatusCode&&me.push(`HTTP ${je.lastStatusCode}错误`)}const Le=(ye==null?void 0:ye.totalTokensUsed)!==void 0?ye.totalTokensUsed:E.totalTokensUsed;E.tokenLimit&&Le!==void 0&&Le>=E.tokenLimit*1e3&&me.push("Token超限");const St=(ye==null?void 0:ye.totalRequestsUsed)!==void 0?ye.totalRequestsUsed:E.totalRequestsUsed;if(E.requestCountLimit&&St!==void 0&&St>=E.requestCountLimit&&me.push("次数超限"),me.length>0)return{status:"error",label:X!=null&&X.isBlacklisted?((El=X.blacklistEntry)==null?void 0:El.errorType)==="timeout"?"超时":"服务错误":me[0],reason:me.join(", ")};const Ir=[];if(E.tokenLimit&&Le!==void 0){const je=Le/(E.tokenLimit*1e3)*100;je>=80&&Ir.push(`Token ${je.toFixed(0)}%`)}if(E.requestCountLimit&&St!==void 0){const je=St/E.requestCountLimit*100;je>=80&&Ir.push(`次数 ${je.toFixed(0)}%`)}return Ir.length>0?{status:"warning",label:"接近限制",reason:Ir.join(", ")}:{status:"success",label:"正常",reason:""}},M2=()=>{C(null),z("default"),M(""),_(""),V(""),O(""),U(0),G(void 0),Y(void 0),A(void 0),ge(void 0),W(void 0),se(void 0),_e(void 0),$t(!1),wt(!1),Gt(void 0),J(void 0),$e(!1),Ve(!1),F(!1),ie(""),w(!0)};return u.jsxs("div",{className:"routes-page",children:[u.jsxs("div",{className:"page-header",children:[u.jsx("h1",{children:"路由管理"}),u.jsx("p",{children:"管理API路由和路由配置"})]}),u.jsx("div",{style:{display:"flex",flexDirection:"column"},children:u.jsxs("div",{style:{display:"flex",gap:"20px"},children:[u.jsxs("div",{className:"card",style:{flex:"0 0 25%",minWidth:300},children:[u.jsxs("div",{className:"toolbar",children:[u.jsx("h3",{children:"路由"}),u.jsx("button",{className:"btn btn-primary",onClick:()=>v(!0),children:"新建"})]}),n.length===0?u.jsx("div",{className:"empty-state",children:u.jsx("p",{children:"暂无路由"})}):u.jsx("div",{style:{marginTop:"10px"},children:n.map(E=>{var X,me;return u.jsx("div",{ref:ye=>{ye?Gn.current.set(E.id,ye):Gn.current.delete(E.id)},onClick:()=>y(E),style:{padding:"12px",marginBottom:"8px",backgroundColor:g&&g.id===E.id?"var(--bg-route-item-selected)":"var(--bg-route-item)",borderRadius:"8px",cursor:"pointer",border:"1px solid var(--border-primary)",position:"relative"},children:u.jsxs("div",{children:[u.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center"},children:[u.jsx("div",{style:{fontWeight:500},children:E.name}),E.isActive&&u.jsxs("span",{className:`badge ${E.targetType==="claude-code"?"badge-claude-code":"badge-codex"}`,style:{position:"absolute",top:-16,right:-8},children:[(X=Yh.find(ye=>ye.value===E.targetType))==null?void 0:X.label," 已激活"]})]}),u.jsxs("div",{style:{fontSize:"12px",color:"var(--text-route-muted)",marginTop:"2px"},children:["客户端工具: ",(me=Yh.find(ye=>ye.value===E.targetType))==null?void 0:me.label]}),u.jsxs("div",{className:"action-buttons",style:{marginTop:"8px"},children:[E.isActive?u.jsx("button",{className:"btn btn-warning",style:{padding:"4px 8px",fontSize:"12px"},onClick:ye=>{ye.stopPropagation(),w2(E.id)},disabled:Tr!==null,children:Tr===E.id?"处理中...":"停用"}):u.jsx("button",{className:"btn btn-success",style:{padding:"4px 8px",fontSize:"12px"},onClick:ye=>{ye.stopPropagation(),b2(E.id)},disabled:Tr!==null,children:Tr===E.id?"处理中...":"激活"}),u.jsx("button",{className:"btn btn-secondary",style:{padding:"4px 8px",fontSize:"12px"},onClick:ye=>{ye.stopPropagation(),k(E),v(!0)},children:"编辑"}),u.jsx("button",{className:"btn btn-danger",style:{padding:"4px 8px",fontSize:"12px"},onClick:ye=>{ye.stopPropagation(),j2(E.id)},disabled:E.isActive,children:"删除"})]})]})},E.id)})})]}),u.jsxs("div",{style:{flex:1,display:"flex",flexDirection:"column"},children:[u.jsxs("div",{className:"card",style:{flex:1},children:[u.jsxs("div",{className:"toolbar",children:[u.jsx("h3",{children:"规则列表"}),g&&u.jsx("button",{className:"btn btn-primary",onClick:M2,children:"新建规则"})]}),g?i.length===0?u.jsx("div",{className:"empty-state",children:u.jsx("p",{children:"暂无路由"})}):u.jsxs("table",{className:"rules-table",children:[u.jsx("thead",{children:u.jsxs("tr",{children:[u.jsx("th",{className:"col-priority",children:"优先级"}),u.jsx("th",{children:"类型"}),u.jsx("th",{children:"API服务"}),u.jsx("th",{children:"状态"}),u.jsx("th",{children:"用量情况"}),u.jsx("th",{children:"操作"})]})}),u.jsx("tbody",{children:[...i].sort((E,X)=>{const me=E.sortOrder||0,ye=X.sortOrder||0;if(me!==ye)return ye-me;const Le=gw[E.contentType]??999,St=gw[X.contentType]??999;return Le-St}).map(E=>{var Le,St,Ir,El;const X=s.find(je=>je.id===E.targetServiceId),me=o.find(je=>je.id===(X==null?void 0:X.vendorId)),ye=(Le=mw.find(je=>je.value===E.contentType))==null?void 0:Le.label;return u.jsxs("tr",{children:[u.jsx("td",{className:"col-priority",children:u.jsxs("div",{className:"col-priority-box",children:[u.jsx("span",{children:E.sortOrder||0}),u.jsx("button",{className:"priority-arrow-btn",onClick:()=>A2(E.id),title:"降低优先级",children:"↓"}),u.jsx("button",{className:"priority-arrow-btn",onClick:()=>E2(E.id),title:"提升优先级",children:"↑"})]})}),u.jsx("td",{children:u.jsxs("div",{style:{fontSize:"12px",whiteSpace:"nowrap"},children:[E.contentType!=="default"&&vw[E.contentType]&&u.jsx("span",{style:{fontSize:"14px"},children:vw[E.contentType]}),u.jsx("span",{children:ye}),E.contentType==="model-mapping"&&E.replacedModel&&u.jsxs("div",{style:{position:"relative",display:"inline-block"},onMouseEnter:()=>Pt(E.id),onMouseLeave:()=>Pt(null),children:[u.jsx("span",{style:{cursor:"help",fontSize:"14px",color:"var(--text-info)",fontWeight:"bold"},children:"ⓘ"}),Mn===E.id&&u.jsxs("div",{style:{position:"absolute",left:"50%",transform:"translateX(-50%)",bottom:"calc(100% + 8px)",backgroundColor:"var(--bg-popover, #333)",color:"var(--text-popover, #fff)",padding:"6px 10px",borderRadius:"4px",fontSize:"12px",whiteSpace:"nowrap",zIndex:1e3,boxShadow:"0 2px 8px rgba(0,0,0,0.15)"},children:["被顶替的模型是: ",E.replacedModel,u.jsx("div",{style:{position:"absolute",left:"50%",transform:"translateX(-50%)",bottom:"-4px",width:"0",height:"0",borderLeft:"4px solid transparent",borderRight:"4px solid transparent",borderTop:"4px solid var(--bg-popover, #333)"}})]})]})]})}),u.jsx("td",{children:u.jsx("div",{className:"vendor-sevices-col",style:{fontSize:"0.6em"},children:E.useMCP?u.jsxs(u.Fragment,{children:[u.jsxs("div",{children:["MCP:",((St=p.find(je=>je.id===E.mcpId))==null?void 0:St.name)||"Unknown"]}),u.jsx("div",{style:{fontSize:"11px",color:"var(--text-muted)"},children:"使用MCP工具"})]}):u.jsxs(u.Fragment,{children:[u.jsxs("div",{children:["供应商:",me?me.name:"Unknown"]}),u.jsxs("div",{children:["服务:",X?X.name:"Unknown"]}),u.jsxs("div",{children:["模型:",E.targetModel||"透传模型"]})]})})}),u.jsx("td",{style:{whiteSpace:"nowrap"},children:(()=>{var rb,ib;const je=N2(E),pn=xe[E.id],D2=(pn==null?void 0:pn.isBlacklisted)&&!((rb=je.reason)!=null&&rb.includes("Token超限"))&&!((ib=je.reason)!=null&&ib.includes("次数超限"));return E.isDisabled?u.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"6px"},children:[u.jsx("span",{style:{color:"#6c757d",fontWeight:"bold",fontSize:"14px"},children:"⊘"}),u.jsx("span",{style:{fontSize:"13px",color:"#6c757d",fontWeight:"bold"},children:"已屏蔽"})]}):u.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"6px",flexWrap:"wrap"},children:[u.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"6px"},children:[je.status==="success"&&u.jsx("span",{style:{color:"#28a745",fontWeight:"bold",fontSize:"14px"},children:"✓"}),je.status==="warning"&&u.jsx("span",{style:{color:"#ffc107",fontWeight:"bold",fontSize:"14px"},children:"⚠"}),je.status==="error"&&u.jsx("span",{style:{color:"#dc3545",fontWeight:"bold",fontSize:"14px"},children:"✗"}),je.status==="in_use"&&u.jsx(u.Fragment,{children:u.jsx("span",{style:{color:"#007bff",fontWeight:"bold",fontSize:"14px",animation:"pulse 1.5s ease-in-out infinite"},children:"●"})}),u.jsx("span",{style:{fontSize:"13px",color:je.status==="success"?"#28a745":je.status==="warning"?"#ffc107":je.status==="in_use"?"#007bff":"#dc3545",fontWeight:je.status!=="success"?"bold":"normal"},children:je.label}),je.reason&&u.jsxs("div",{style:{position:"relative",display:"inline-block",cursor:"help"},onMouseEnter:()=>Pt(E.id+"-status"),onMouseLeave:()=>Pt(null),children:[u.jsx("span",{style:{fontSize:"12px",color:"#999",marginLeft:"4px"},children:" ⓘ"}),Mn===E.id+"-status"&&u.jsxs("div",{style:{position:"absolute",left:"50%",transform:"translateX(-50%)",bottom:"calc(100% + 8px)",backgroundColor:"var(--bg-popover, #333)",color:"var(--text-popover, #fff)",padding:"6px 10px",borderRadius:"4px",fontSize:"12px",whiteSpace:"nowrap",zIndex:1e3,boxShadow:"0 2px 8px rgba(0,0,0,0.15)"},children:[je.reason,u.jsx("div",{style:{position:"absolute",left:"50%",transform:"translateX(-50%)",bottom:"-4px",width:"0",height:"0",borderLeft:"4px solid transparent",borderRight:"4px solid transparent",borderTop:"4px solid var(--bg-popover, #333)"}})]})]})]}),D2&&u.jsx("button",{className:"btn btn-info",style:{padding:"2px 8px",fontSize:"11px"},onClick:()=>C2(E.id),children:"恢复"})]})})()}),u.jsx("td",{children:E.tokenLimit||E.requestCountLimit?u.jsxs("div",{style:{fontSize:"13px"},children:[E.tokenLimit&&u.jsxs("div",{style:{whiteSpace:"nowrap"},children:[u.jsx("span",{style:{fontWeight:"bold",fontSize:"12px"},children:"Tokens:"}),u.jsxs(u.Fragment,{children:[u.jsxs("span",{style:{color:(()=>{var pn;const je=((pn=t[E.id])==null?void 0:pn.totalTokensUsed)??E.totalTokensUsed;return je&&E.tokenLimit&&je>=E.tokenLimit*1e3?"red":"inherit"})()},children:[(((((Ir=t[E.id])==null?void 0:Ir.totalTokensUsed)??E.totalTokensUsed)||0)/1e3).toFixed(1),"K/",E.tokenLimit.toFixed(0),"K"]}),(()=>{var pn;const je=((pn=t[E.id])==null?void 0:pn.totalTokensUsed)??E.totalTokensUsed;return je&&E.tokenLimit&&je>=E.tokenLimit*1e3?u.jsx("span",{style:{color:"red",marginLeft:"4px",fontWeight:"bold",fontSize:"11px"},children:"超限"}):null})()]})]}),E.requestCountLimit&&u.jsxs("div",{style:{marginTop:E.tokenLimit?"6px":0},children:[u.jsx("span",{style:{fontWeight:"bold",fontSize:"12px"},children:"次数:"}),u.jsxs(u.Fragment,{children:[u.jsxs("span",{style:{color:(()=>{var pn;const je=((pn=t[E.id])==null?void 0:pn.totalRequestsUsed)??E.totalRequestsUsed;return je&&E.requestCountLimit&&je>=E.requestCountLimit?"red":"inherit"})()},children:[(((El=t[E.id])==null?void 0:El.totalRequestsUsed)??E.totalTokensUsed)||0,"/",E.requestCountLimit]}),(()=>{var pn;const je=((pn=t[E.id])==null?void 0:pn.totalRequestsUsed)??E.totalRequestsUsed;return je&&E.requestCountLimit&&je>=E.requestCountLimit?u.jsx("span",{style:{color:"red",marginLeft:"4px",fontWeight:"bold",fontSize:"11px"},children:"超限"}):null})()]})]})]}):u.jsx("span",{style:{color:"#999",fontSize:"12px"},children:"不限制"})}),u.jsx("td",{children:u.jsxs("div",{className:"action-buttons",style:{justifyContent:"flex-end"},children:[u.jsx("button",{className:`btn ${E.isDisabled?"btn-success":"btn-warning"}`,onClick:()=>O2(E.id),title:E.isDisabled?"启用规则":"临时屏蔽规则",children:E.isDisabled?"启用":"屏蔽"}),u.jsx("button",{className:"btn btn-secondary",onClick:()=>_2(E),children:"编辑"}),u.jsx("button",{className:"btn btn-danger",onClick:()=>P2(E.id),children:"删除"})]})})]},E.id)})})]}):u.jsx("div",{className:"empty-state",children:u.jsx("p",{children:"请先选择一个路由"})}),g&&i.length>0&&u.jsxs("div",{style:{fontSize:"12px",color:"var(--text-info-box)",marginTop:"16px",padding:"12px",backgroundColor:"var(--bg-info-box)",borderRadius:"6px",border:"1px solid var(--border-info-box)",lineHeight:"1.6"},children:[u.jsx("strong",{children:"💡 智能故障切换机制"}),u.jsxs("div",{style:{marginTop:"6px"},children:["• 当同一请求类型配置多个规则时,系统会按排序优先使用第一个",u.jsx("br",{}),"• 如果某个服务报错(4xx/5xx)或请求超时,将自动切换到下一个可用服务",u.jsx("br",{}),"• 报错或超时的服务会被标记为不可用,有效期10分钟",u.jsx("br",{}),"• 10分钟后自动解除标记,如果再次报错或超时则重新标记",u.jsx("br",{}),"• 确保您的请求始终路由到稳定可用的服务",u.jsx("br",{}),"• 规则状态列会实时显示每个规则的可用性状态",u.jsx("br",{}),"• 如不需要此功能,可在",u.jsx("strong",{children:"设置"}),'页面关闭"启用智能故障切换"选项']})]})]}),g&&g.targetType==="claude-code"&&u.jsxs("div",{className:"card",children:[u.jsx("div",{className:"toolbar",children:u.jsx("h3",{children:"Claude Code 配置"})}),u.jsxs("div",{style:{padding:"20px"},children:[!B()&&((eb=Me==null?void 0:Me.claudeCode)==null?void 0:eb.version)&&u.jsxs("div",{style:{backgroundColor:"var(--bg-warning, #fff3cd)",border:"1px solid var(--border-warning, #ffc107)",borderRadius:"6px",padding:"12px",marginBottom:"12px",fontSize:"13px",color:"var(--text-warning, #856404)"},children:["⚠️ 当前 Claude Code 版本 (",Me.claudeCode.version,") 不支持 Agent Teams 功能。",u.jsx("br",{}),"Agent Teams 功能需要 Claude Code 版本 ≥ 2.1.32。请升级 Claude Code 后再使用此功能。"]}),u.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"12px"},children:[u.jsx("input",{type:"checkbox",id:"agent-teams-toggle",checked:g.enableAgentTeams||!1,onChange:E=>T2(E.target.checked),disabled:!B(),style:{cursor:B()?"pointer":"not-allowed",width:"16px",height:"16px"}}),u.jsx("label",{htmlFor:"agent-teams-toggle",style:{cursor:B()?"pointer":"not-allowed",fontSize:"14px",userSelect:"none",color:B()?"inherit":"var(--text-muted)"},children:"开启 Agent Teams 功能"})]}),u.jsx("div",{style:{fontSize:"12px",color:"var(--text-muted)",marginTop:"12px"},children:B()?g.isActive?"开启后将在 Claude Code 中启用 Agent Teams 实验性功能,已立即生效。":"开启后将在激活此路由时启用 Agent Teams 实验性功能。":"Agent Teams 功能需要 Claude Code 版本 ≥ 2.1.32。请升级 Claude Code 后再使用此功能。"})]})]})]})]})}),u.jsxs("div",{className:"card",style:{marginTop:"20px"},children:[u.jsx("div",{className:"toolbar",children:u.jsx("h3",{children:"📝 配置文件自动管理"})}),u.jsxs("div",{style:{padding:"20px",lineHeight:"1.8"},children:[u.jsxs("div",{style:{background:"var(--bg-info-blue)",padding:"15px",borderRadius:"8px",marginBottom:"15px",borderLeft:"4px solid var(--border-info-blue)"},children:[u.jsx("strong",{children:"💡 工作原理"}),u.jsx("p",{style:{marginTop:"8px",marginBottom:"0"},children:"激活路由时,系统会自动修改编程工具的配置文件,使其通过本代理服务器访问AI服务。 停用路由时,系统会自动恢复原始配置。"})]}),u.jsxs("div",{style:{display:"grid",gridTemplateColumns:"1fr 1fr",gap:"15px"},children:[u.jsxs("div",{style:{background:"var(--bg-info-green)",padding:"15px",borderRadius:"8px",borderLeft:"4px solid var(--border-info-green)"},children:[u.jsx("strong",{children:"✓ 激活路由"}),u.jsxs("ul",{style:{marginTop:"8px",paddingLeft:"20px",marginBottom:"0"},children:[u.jsx("li",{children:"首次激活:自动备份并覆盖配置文件"}),u.jsx("li",{children:"再次激活:仅切换路由,不重复覆盖"})]})]}),u.jsxs("div",{style:{background:"var(--bg-info-orange)",padding:"15px",borderRadius:"8px",borderLeft:"4px solid var(--border-info-orange)"},children:[u.jsx("strong",{children:"○ 停用路由"}),u.jsxs("ul",{style:{marginTop:"8px",paddingLeft:"20px",marginBottom:"0"},children:[u.jsx("li",{children:"自动恢复原始配置文件"}),u.jsx("li",{children:"删除备份文件"})]})]})]}),u.jsxs("div",{style:{marginTop:"15px",padding:"12px 15px",background:"var(--bg-info-yellow)",borderRadius:"8px",borderLeft:"4px solid var(--border-info-yellow)"},children:[u.jsx("strong",{children:"⚠️ 重要提示"}),u.jsxs("ul",{style:{marginTop:"8px",paddingLeft:"20px",marginBottom:"0"},children:[u.jsxs("li",{children:["激活(首次)/停用路由后,",u.jsx("strong",{children:"必须重启对应的编程工具"}),"才能使配置生效"]}),u.jsx("li",{children:"操作前建议关闭编程工具,避免配置冲突"})]})]}),u.jsxs("details",{style:{marginTop:"15px",cursor:"pointer"},children:[u.jsx("summary",{style:{fontWeight:"bold",color:"#666"},children:"📂 配置文件位置(点击展开)"}),u.jsxs("ul",{style:{marginTop:"8px",paddingLeft:"20px",color:"#666"},children:[u.jsxs("li",{children:[u.jsx("strong",{children:"Claude Code:"})," ~/.claude/settings.json, ~/.claude.json"]}),u.jsxs("li",{children:[u.jsx("strong",{children:"Codex:"})," ~/.codex/config.toml, ~/.codex/auth.json"]})]})]})]})]}),x&&u.jsxs("div",{className:"modal-overlay",children:[u.jsx("button",{type:"button",className:"modal-close-btn",onClick:()=>v(!1),"aria-label":"关闭",children:"×"}),u.jsx("div",{className:"modal",children:u.jsxs("div",{className:"modal-container",children:[u.jsx("div",{className:"modal-header",children:u.jsx("h2",{children:S?"编辑路由":"新建路由"})}),u.jsxs("form",{onSubmit:S2,children:[u.jsxs("div",{className:"form-group",children:[u.jsx("label",{children:"路由名称"}),u.jsx("input",{type:"text",name:"name",defaultValue:S?S.name:"",required:!0})]}),u.jsxs("div",{className:"form-group",children:[u.jsx("label",{children:"描述"}),u.jsx("textarea",{name:"description",rows:3,defaultValue:S?S.description:""})]}),u.jsxs("div",{className:"form-group",children:[u.jsx("label",{children:"客户端工具"}),u.jsx("select",{name:"targetType",defaultValue:S?S.targetType:"claude-code",required:!0,children:Yh.map(E=>u.jsx("option",{value:E.value,children:E.label},E.value))})]}),u.jsxs("div",{className:"modal-footer",children:[u.jsx("button",{type:"button",className:"btn btn-secondary",onClick:()=>v(!1),children:"取消"}),u.jsx("button",{type:"submit",className:"btn btn-primary",children:"保存"})]})]})]})})]}),b&&u.jsxs("div",{className:"modal-overlay",children:[u.jsx("button",{type:"button",className:"modal-close-btn",onClick:()=>w(!1),"aria-label":"关闭",children:"×"}),u.jsx("div",{className:"modal",children:u.jsxs("div",{className:"modal-container",children:[u.jsx("div",{className:"modal-header",children:u.jsx("h2",{children:j?"编辑规则":"新建规则"})}),u.jsxs("form",{onSubmit:k2,children:[u.jsxs("div",{className:"form-group",children:[u.jsx("label",{children:"对象请求类型"}),u.jsx("select",{name:"contentType",value:D,required:!0,onChange:E=>{z(E.target.value)},children:I2().map(E=>u.jsx("option",{value:E.value,children:E.label},E.value))})]}),D==="high-iq"&&u.jsxs("div",{style:{background:"var(--bg-info-blue)",padding:"12px",borderRadius:"6px",borderLeft:"4px solid var(--border-info-blue)",marginBottom:"16px"},children:[u.jsx("div",{style:{fontSize:"13px",fontWeight:"bold",marginBottom:"6px"},children:"💡 高智商请求使用方法"}),u.jsxs("div",{style:{fontSize:"12px",color:"var(--text-muted)",lineHeight:"1.6"},children:["在编程工具中输入提示词时:",u.jsxs("ul",{style:{marginTop:"8px",paddingLeft:"20px",lineHeight:"1.8"},children:[u.jsxs("li",{children:["使用 ",u.jsx("code",{style:{background:"var(--bg-code-inline, #f5f5f5)",padding:"2px 6px",borderRadius:"3px",fontFamily:"monospace",fontSize:"12px"},children:"!!"})," 开启高智商模式(整个会话持续使用)"]}),u.jsxs("li",{children:["使用 ",u.jsx("code",{style:{background:"var(--bg-code-inline, #f5f5f5)",padding:"2px 6px",borderRadius:"3px",fontFamily:"monospace",fontSize:"12px"},children:"!x"})," 关闭高智商模式"]})]})]}),u.jsxs("div",{style:{fontSize:"12px",color:"var(--text-muted)",marginTop:"8px",lineHeight:"1.6"},children:[u.jsx("strong",{children:"示例:"}),u.jsx("br",{}),"• ",u.jsx("code",{style:{background:"var(--bg-code-inline, #f5f5f5)",padding:"2px 6px",borderRadius:"3px",fontFamily:"monospace",fontSize:"12px"},children:"!! 重构A模块"}),u.jsx("br",{}),"• ",u.jsx("code",{style:{background:"var(--bg-code-inline, #f5f5f5)",padding:"2px 6px",borderRadius:"3px",fontFamily:"monospace",fontSize:"12px"},children:"!x 继续正常对话"})]})]}),D==="model-mapping"&&u.jsxs("div",{className:"form-group",children:[u.jsxs("label",{children:["被顶替模型 ",u.jsx("small",{children:"(可在日志中找出想要顶替的模型名)"})]}),u.jsx("input",{type:"text",value:L,onChange:E=>O(E.target.value),placeholder:"例如:gpt-4"})]}),D==="image-understanding"&&u.jsxs("div",{className:"form-group",children:[u.jsxs("label",{style:{display:"flex",alignItems:"center",cursor:"pointer"},children:[u.jsx("input",{type:"checkbox",checked:be,onChange:E=>F(E.target.checked),style:{marginRight:"8px",cursor:"pointer",width:"16px",height:"16px"}}),u.jsx("span",{children:"使用MCP"})]}),u.jsx("small",{style:{color:"#666",fontSize:"12px",marginTop:"4px",display:"block"},children:"开启后,将使用MCP工具处理图像理解请求,而不是直接调用API服务"})]}),D==="image-understanding"&&be&&u.jsxs("div",{className:"form-group",children:[u.jsxs("label",{children:["选择MCP工具 ",u.jsx("span",{className:"required",children:"*"})]}),u.jsx("div",{style:{maxHeight:"300px",overflowY:"auto",border:"1px solid var(--border-primary)",borderRadius:"6px",padding:"8px"},children:p.length===0?u.jsx("div",{style:{padding:"12px",textAlign:"center",color:"var(--text-muted)"},children:"暂无MCP工具,请先在MCP管理页面添加"}):p.map(E=>u.jsxs("div",{onClick:()=>ie(E.id),style:{padding:"12px",marginBottom:"8px",border:`2px solid ${ae===E.id?"var(--primary-color)":"var(--border-primary)"}`,borderRadius:"6px",cursor:"pointer",backgroundColor:ae===E.id?"var(--bg-info-blue)":"var(--bg-card)",transition:"all 0.2s ease"},children:[u.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center"},children:[u.jsx("div",{style:{fontWeight:600,fontSize:"14px"},children:E.name}),u.jsx("div",{className:"badge badge-secondary",style:{fontSize:"11px"},children:E.type==="stdio"?"命令行":E.type.toUpperCase()})]}),E.description&&u.jsx("div",{style:{fontSize:"12px",color:"var(--text-muted)",marginTop:"4px"},children:E.description})]},E.id))})]}),!be&&u.jsxs(u.Fragment,{children:[u.jsxs("div",{className:"form-group",children:[u.jsx("label",{children:"供应商"}),u.jsxs("select",{value:T,onChange:E=>M(E.target.value),required:!0,children:[u.jsx("option",{value:"",disabled:!0,children:"请选择供应商"}),o.map(E=>u.jsx("option",{value:E.id,children:E.name},E.id))]})]}),u.jsxs("div",{className:"form-group",children:[u.jsx("label",{children:"供应商API服务"}),u.jsxs("select",{value:I,onChange:E=>{const X=E.target.value;_(X),V("");const me=s.find(ye=>ye.id===X);me&&(me.enableTokenLimit&&me.tokenLimit?(Y(me.tokenLimit),A(me.tokenResetInterval),ge(me.tokenResetBaseTime?new Date(me.tokenResetBaseTime):void 0),Gt(me.tokenLimit),$t(!0),$e(!0)):(Gt(void 0),$t(!1),$e(!1)),me.enableRequestLimit&&me.requestCountLimit?(W(me.requestCountLimit),se(me.requestResetInterval),_e(me.requestResetBaseTime?new Date(me.requestResetBaseTime):void 0),J(me.requestCountLimit),wt(!0),Ve(!0)):(J(void 0),wt(!1),Ve(!1)))},required:!0,disabled:!T,children:[u.jsx("option",{value:"",disabled:!0,children:"请选择API服务"}),d.map(E=>u.jsx("option",{value:E.id,children:E.name},E.id))]})]}),u.jsxs("div",{className:"form-group",children:[u.jsx("label",{children:"供应商模型"}),u.jsxs("select",{value:N,onChange:E=>V(E.target.value),disabled:!I,children:[u.jsx("option",{value:"",children:"透传模型名"}),(nb=(tb=s.find(E=>E.id===I))==null?void 0:tb.supportedModels)==null?void 0:nb.map(E=>u.jsx("option",{value:E,children:E},E))]})]}),u.jsx("div",{className:"form-group",children:u.jsxs("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between"},children:[u.jsxs("label",{style:{display:"flex",alignItems:"center",cursor:xt?"not-allowed":"pointer"},children:[u.jsx("input",{type:"checkbox",checked:Se,onChange:E=>$e(E.target.checked),disabled:xt,style:{marginRight:"8px",cursor:xt?"not-allowed":"pointer",width:"16px",height:"16px"}}),u.jsx("span",{children:"启用Tokens超量限制"}),xt&&u.jsx("small",{style:{color:"#999",fontSize:"12px",marginLeft:"8px"},children:"(从API服务继承)"})]}),xt&&u.jsx("button",{type:"button",className:"btn btn-sm btn-secondary",onClick:()=>$t(!1),style:{padding:"4px 12px",fontSize:"12px"},children:"自定义限制"})]})}),Se&&!xt&&u.jsxs(u.Fragment,{children:[u.jsxs("div",{className:"form-group",children:[u.jsx("label",{children:"Tokens超量(单位:k)"}),u.jsx("input",{type:"number",value:P||"",onChange:E=>{const X=E.target.value?parseInt(E.target.value):void 0;if(X!==void 0&&It!==void 0&&X>It){re.warning(`Token超量值不能超过API服务的限制 (${It}k)`);return}Y(X),xt&&X!==It&&$t(!1)},min:"0",max:It,placeholder:It?`最大 ${It}k`:"不限制",disabled:xt}),It&&u.jsxs("small",{style:{color:"#666",fontSize:"12px",marginTop:"4px",display:"block"},children:["⚠️ API服务限制:最大 ",It,"k,当前值不能超过此限制"]}),u.jsx("small",{style:{color:"#666",fontSize:"12px",marginTop:"4px",display:"block"},children:"当编程工具的请求tokens达到这个量时,在配置了其他规则的情况下,本条规则将失效,从而保护你的余额。例如:输入100表示100k即100,000个tokens"})]}),u.jsxs("div",{className:"form-group",children:[u.jsx("label",{children:"Tokens超量自动重置间隔(小时)"}),u.jsx("input",{type:"number",value:Z||"",onChange:E=>{A(E.target.value?parseInt(E.target.value):void 0),xt&&$t(!1)},min:"1",placeholder:"不自动重置",disabled:xt}),u.jsx("small",{style:{color:"#666",fontSize:"12px",marginTop:"4px",display:"block"},children:"设置后,系统将每隔指定小时数自动重置token计数。例如设置5小时,则每5小时重置一次"})]}),u.jsxs("div",{className:"form-group",children:[u.jsx("label",{children:"Token下一次重置时间基点"}),u.jsx("input",{type:"datetime-local",value:ue?yw(ue):"",onChange:E=>{E.target.value?ge(new Date(E.target.value)):ge(void 0),xt&&$t(!1)},disabled:!Z||xt,className:"datetime-picker-input"}),u.jsx("small",{style:{color:"#666",fontSize:"12px",marginTop:"4px",display:"block"},children:'配合"Tokens超量自动重置间隔"使用,设置下一次重置的精确时间点。例如,每月1日0点重置(间隔720小时),或每周一0点重置(间隔168小时)。设置后,系统会基于此时间点自动计算后续重置周期'})]})]}),u.jsx("div",{className:"form-group",children:u.jsxs("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between"},children:[u.jsxs("label",{style:{display:"flex",alignItems:"center",cursor:bt?"not-allowed":"pointer"},children:[u.jsx("input",{type:"checkbox",checked:Ne,onChange:E=>Ve(E.target.checked),disabled:bt,style:{marginRight:"8px",cursor:bt?"not-allowed":"pointer",width:"16px",height:"16px"}}),u.jsx("span",{children:"启用请求次数超量限制"}),bt&&u.jsx("small",{style:{color:"#999",fontSize:"12px",marginLeft:"8px"},children:"(从API服务继承)"})]}),bt&&u.jsx("button",{type:"button",className:"btn btn-sm btn-secondary",onClick:()=>wt(!1),style:{padding:"4px 12px",fontSize:"12px"},children:"自定义限制"})]})}),Ne&&!bt&&u.jsxs(u.Fragment,{children:[u.jsxs("div",{className:"form-group",children:[u.jsx("label",{children:"请求次数超量"}),u.jsx("input",{type:"number",value:de||"",onChange:E=>{const X=E.target.value?parseInt(E.target.value):void 0;if(X!==void 0&&K!==void 0&&X>K){re.warning(`请求次数超量值不能超过API服务的限制 (${K})`);return}W(X),bt&&X!==K&&wt(!1)},min:"0",max:K,placeholder:K?`最大 ${K}`:"不限制",disabled:bt}),K&&u.jsxs("small",{style:{color:"#666",fontSize:"12px",marginTop:"4px",display:"block"},children:["⚠️ API服务限制:最大 ",K,",当前值不能超过此限制"]}),u.jsx("small",{style:{color:"#666",fontSize:"12px",marginTop:"4px",display:"block"},children:"当请求次数达到这个量时,在配置了其他规则的情况下,本条规则将失效"})]}),u.jsxs("div",{className:"form-group",children:[u.jsx("label",{children:"请求次数自动重置间隔(小时)"}),u.jsx("input",{type:"number",value:ne||"",onChange:E=>{se(E.target.value?parseInt(E.target.value):void 0),bt&&wt(!1)},min:"1",placeholder:"不自动重置",disabled:bt}),u.jsx("small",{style:{color:"#666",fontSize:"12px",marginTop:"4px",display:"block"},children:"设置后,系统将每隔指定小时数自动重置请求次数计数。例如设置24小时,则每24小时重置一次"})]}),u.jsxs("div",{className:"form-group",children:[u.jsx("label",{children:"下一次重置时间基点"}),u.jsx("input",{type:"datetime-local",value:q?yw(q):"",onChange:E=>{E.target.value?_e(new Date(E.target.value)):_e(void 0),bt&&wt(!1)},disabled:!ne||bt,className:"datetime-picker-input"}),u.jsx("small",{style:{color:"#666",fontSize:"12px",marginTop:"4px",display:"block"},children:'配合"请求次数自动重置间隔"使用,设置下一次重置的精确时间点。例如,每月1日0点重置(间隔720小时),或每周一0点重置(间隔168小时)。设置后,系统会基于此时间点自动计算后续重置周期'})]})]})]}),u.jsxs("div",{className:"form-group",children:[u.jsxs("label",{style:{display:"flex",alignItems:"center",cursor:"pointer"},children:[u.jsx("input",{type:"checkbox",checked:!!Ce,onChange:E=>{E.target.checked?(ve(10),Pe(0)):(ve(void 0),Pe(void 0))},style:{marginRight:"8px",cursor:"pointer",width:"16px",height:"16px"}}),u.jsx("span",{children:"启用请求频率限制"})]}),u.jsx("small",{style:{color:"#666",fontSize:"12px",marginTop:"4px",display:"block"},children:"启用后,当同一内容类型的请求频率超过限制时,系统会自动切换到其他同类型规则"})]}),Ce&&u.jsxs(u.Fragment,{children:[u.jsxs("div",{className:"form-group",children:[u.jsx("label",{children:"频率限制次数(并发数)"}),u.jsx("input",{type:"number",value:Ce||"",onChange:E=>ve(E.target.value?parseInt(E.target.value):void 0),min:"1",placeholder:"例如: 10"}),u.jsx("small",{style:{color:"#666",fontSize:"12px",marginTop:"4px",display:"block"},children:"在指定时间窗口内允许的最大请求次数"})]}),u.jsxs("div",{className:"form-group",children:[u.jsx("label",{children:"频率限制时间窗口(秒,0=同一时刻)"}),u.jsx("input",{type:"number",value:we===0?0:we||"",onChange:E=>{const X=E.target.value?parseInt(E.target.value):void 0;Pe(X===0?0:X)},min:"0",placeholder:"0 表示同一时刻"}),u.jsx("small",{style:{color:"#666",fontSize:"12px",marginTop:"4px",display:"block"},children:"时间窗口大小。0 表示同一时刻(并发数),持续累积;设置为 60 则在 60 秒内最多允许 N 次请求"})]})]}),u.jsxs("div",{className:"form-group",children:[u.jsx("label",{children:"超时时间(秒)"}),u.jsx("input",{type:"number",value:H||"",onChange:E=>G(E.target.value?parseInt(E.target.value):void 0),min:"1",placeholder:"默认300秒"}),u.jsx("small",{style:{color:"#666",fontSize:"12px",marginTop:"4px",display:"block"},children:"设置此规则的API请求超时时间。不设置则使用默认值300秒(5分钟)"})]}),u.jsxs("div",{className:"form-group",children:[u.jsx("label",{children:"排序(值越大优先级越高)"}),u.jsx("input",{type:"number",value:R,onChange:E=>U(parseInt(E.target.value)||0),min:"0",max:"1000"})]}),u.jsxs("div",{className:"modal-footer",children:[u.jsx("button",{type:"button",className:"btn btn-secondary",onClick:()=>w(!1),children:"取消"}),u.jsx("button",{type:"submit",className:"btn btn-primary",children:"保存"})]})]})]})})]})]})}var AE={exports:{}};(function(e,t){(function(n,r){e.exports=r()})(Go,function(){var n=1e3,r=6e4,i=36e5,a="millisecond",o="second",l="minute",s="hour",c="day",d="week",f="month",p="quarter",h="year",g="date",y="Invalid Date",x=/^(\d{4})[-/]?(\d{1,2})?[-/]?(\d{0,2})[Tt\s]*(\d{1,2})?:?(\d{1,2})?:?(\d{1,2})?[.:]?(\d+)?$/,v=/\[([^\]]+)]|Y{1,4}|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a|A|m{1,2}|s{1,2}|Z{1,2}|SSS/g,b={name:"en",weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),ordinal:function(L){var O=["th","st","nd","rd"],R=L%100;return"["+L+(O[(R-20)%10]||O[R]||O[0])+"]"}},w=function(L,O,R){var U=String(L);return!U||U.length>=O?L:""+Array(O+1-U.length).join(R)+L},S={s:w,z:function(L){var O=-L.utcOffset(),R=Math.abs(O),U=Math.floor(R/60),D=R%60;return(O<=0?"+":"-")+w(U,2,"0")+":"+w(D,2,"0")},m:function L(O,R){if(O.date()<R.date())return-L(R,O);var U=12*(R.year()-O.year())+(R.month()-O.month()),D=O.clone().add(U,f),z=R-D<0,P=O.clone().add(U+(z?-1:1),f);return+(-(U+(R-D)/(z?D-P:P-D))||0)},a:function(L){return L<0?Math.ceil(L)||0:Math.floor(L)},p:function(L){return{M:f,y:h,w:d,d:c,D:g,h:s,m:l,s:o,ms:a,Q:p}[L]||String(L||"").toLowerCase().replace(/s$/,"")},u:function(L){return L===void 0}},k="en",j={};j[k]=b;var C="$isDayjsObject",T=function(L){return L instanceof N||!(!L||!L[C])},M=function L(O,R,U){var D;if(!O)return k;if(typeof O=="string"){var z=O.toLowerCase();j[z]&&(D=z),R&&(j[z]=R,D=z);var P=O.split("-");if(!D&&P.length>1)return L(P[0])}else{var Y=O.name;j[Y]=O,D=Y}return!U&&D&&(k=D),D||!U&&k},I=function(L,O){if(T(L))return L.clone();var R=typeof O=="object"?O:{};return R.date=L,R.args=arguments,new N(R)},_=S;_.l=M,_.i=T,_.w=function(L,O){return I(L,{locale:O.$L,utc:O.$u,x:O.$x,$offset:O.$offset})};var N=function(){function L(R){this.$L=M(R.locale,null,!0),this.parse(R),this.$x=this.$x||R.x||{},this[C]=!0}var O=L.prototype;return O.parse=function(R){this.$d=function(U){var D=U.date,z=U.utc;if(D===null)return new Date(NaN);if(_.u(D))return new Date;if(D instanceof Date)return new Date(D);if(typeof D=="string"&&!/Z$/i.test(D)){var P=D.match(x);if(P){var Y=P[2]-1||0,Z=(P[7]||"0").substring(0,3);return z?new Date(Date.UTC(P[1],Y,P[3]||1,P[4]||0,P[5]||0,P[6]||0,Z)):new Date(P[1],Y,P[3]||1,P[4]||0,P[5]||0,P[6]||0,Z)}}return new Date(D)}(R),this.init()},O.init=function(){var R=this.$d;this.$y=R.getFullYear(),this.$M=R.getMonth(),this.$D=R.getDate(),this.$W=R.getDay(),this.$H=R.getHours(),this.$m=R.getMinutes(),this.$s=R.getSeconds(),this.$ms=R.getMilliseconds()},O.$utils=function(){return _},O.isValid=function(){return this.$d.toString()!==y},O.isSame=function(R,U){var D=I(R);return this.startOf(U)<=D&&D<=this.endOf(U)},O.isAfter=function(R,U){return I(R)<this.startOf(U)},O.isBefore=function(R,U){return this.endOf(U)<I(R)},O.$g=function(R,U,D){return _.u(R)?this[U]:this.set(D,R)},O.unix=function(){return Math.floor(this.valueOf()/1e3)},O.valueOf=function(){return this.$d.getTime()},O.startOf=function(R,U){var D=this,z=!!_.u(U)||U,P=_.p(R),Y=function(W,ne){var se=_.w(D.$u?Date.UTC(D.$y,ne,W):new Date(D.$y,ne,W),D);return z?se:se.endOf(c)},Z=function(W,ne){return _.w(D.toDate()[W].apply(D.toDate("s"),(z?[0,0,0,0]:[23,59,59,999]).slice(ne)),D)},A=this.$W,ue=this.$M,ge=this.$D,H="set"+(this.$u?"UTC":"");switch(P){case h:return z?Y(1,0):Y(31,11);case f:return z?Y(1,ue):Y(0,ue+1);case d:var G=this.$locale().weekStart||0,de=(A<G?A+7:A)-G;return Y(z?ge-de:ge+(6-de),ue);case c:case g:return Z(H+"Hours",0);case s:return Z(H+"Minutes",1);case l:return Z(H+"Seconds",2);case o:return Z(H+"Milliseconds",3);default:return this.clone()}},O.endOf=function(R){return this.startOf(R,!1)},O.$set=function(R,U){var D,z=_.p(R),P="set"+(this.$u?"UTC":""),Y=(D={},D[c]=P+"Date",D[g]=P+"Date",D[f]=P+"Month",D[h]=P+"FullYear",D[s]=P+"Hours",D[l]=P+"Minutes",D[o]=P+"Seconds",D[a]=P+"Milliseconds",D)[z],Z=z===c?this.$D+(U-this.$W):U;if(z===f||z===h){var A=this.clone().set(g,1);A.$d[Y](Z),A.init(),this.$d=A.set(g,Math.min(this.$D,A.daysInMonth())).$d}else Y&&this.$d[Y](Z);return this.init(),this},O.set=function(R,U){return this.clone().$set(R,U)},O.get=function(R){return this[_.p(R)]()},O.add=function(R,U){var D,z=this;R=Number(R);var P=_.p(U),Y=function(ue){var ge=I(z);return _.w(ge.date(ge.date()+Math.round(ue*R)),z)};if(P===f)return this.set(f,this.$M+R);if(P===h)return this.set(h,this.$y+R);if(P===c)return Y(1);if(P===d)return Y(7);var Z=(D={},D[l]=r,D[s]=i,D[o]=n,D)[P]||1,A=this.$d.getTime()+R*Z;return _.w(A,this)},O.subtract=function(R,U){return this.add(-1*R,U)},O.format=function(R){var U=this,D=this.$locale();if(!this.isValid())return D.invalidDate||y;var z=R||"YYYY-MM-DDTHH:mm:ssZ",P=_.z(this),Y=this.$H,Z=this.$m,A=this.$M,ue=D.weekdays,ge=D.months,H=D.meridiem,G=function(ne,se,q,_e){return ne&&(ne[se]||ne(U,z))||q[se].slice(0,_e)},de=function(ne){return _.s(Y%12||12,ne,"0")},W=H||function(ne,se,q){var _e=ne<12?"AM":"PM";return q?_e.toLowerCase():_e};return z.replace(v,function(ne,se){return se||function(q){switch(q){case"YY":return String(U.$y).slice(-2);case"YYYY":return _.s(U.$y,4,"0");case"M":return A+1;case"MM":return _.s(A+1,2,"0");case"MMM":return G(D.monthsShort,A,ge,3);case"MMMM":return G(ge,A);case"D":return U.$D;case"DD":return _.s(U.$D,2,"0");case"d":return String(U.$W);case"dd":return G(D.weekdaysMin,U.$W,ue,2);case"ddd":return G(D.weekdaysShort,U.$W,ue,3);case"dddd":return ue[U.$W];case"H":return String(Y);case"HH":return _.s(Y,2,"0");case"h":return de(1);case"hh":return de(2);case"a":return W(Y,Z,!0);case"A":return W(Y,Z,!1);case"m":return String(Z);case"mm":return _.s(Z,2,"0");case"s":return String(U.$s);case"ss":return _.s(U.$s,2,"0");case"SSS":return _.s(U.$ms,3,"0");case"Z":return P}return null}(ne)||P.replace(":","")})},O.utcOffset=function(){return 15*-Math.round(this.$d.getTimezoneOffset()/15)},O.diff=function(R,U,D){var z,P=this,Y=_.p(U),Z=I(R),A=(Z.utcOffset()-this.utcOffset())*r,ue=this-Z,ge=function(){return _.m(P,Z)};switch(Y){case h:z=ge()/12;break;case f:z=ge();break;case p:z=ge()/3;break;case d:z=(ue-A)/6048e5;break;case c:z=(ue-A)/864e5;break;case s:z=ue/i;break;case l:z=ue/r;break;case o:z=ue/n;break;default:z=ue}return D?z:_.a(z)},O.daysInMonth=function(){return this.endOf(f).$D},O.$locale=function(){return j[this.$L]},O.locale=function(R,U){if(!R)return this.$L;var D=this.clone(),z=M(R,U,!0);return z&&(D.$L=z),D},O.clone=function(){return _.w(this.$d,this)},O.toDate=function(){return new Date(this.valueOf())},O.toJSON=function(){return this.isValid()?this.toISOString():null},O.toISOString=function(){return this.$d.toISOString()},O.toString=function(){return this.$d.toUTCString()},L}(),V=N.prototype;return I.prototype=V,[["$ms",a],["$s",o],["$m",l],["$H",s],["$W",c],["$M",f],["$y",h],["$D",g]].forEach(function(L){V[L[1]]=function(O){return this.$g(O,L[0],L[1])}}),I.extend=function(L,O){return L.$i||(L(O,N,I),L.$i=!0),I},I.locale=M,I.isDayjs=T,I.unix=function(L){return I(1e3*L)},I.en=j[k],I.Ls=j,I.p={},I})})(AE);var yB=AE.exports;const on=Vn(yB);var TE={exports:{}};(function(e,t){(function(n,r){e.exports=r()})(Go,function(){return function(n,r,i){n=n||{};var a=r.prototype,o={future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"};function l(c,d,f,p){return a.fromToBase(c,d,f,p)}i.en.relativeTime=o,a.fromToBase=function(c,d,f,p,h){for(var g,y,x,v=f.$locale().relativeTime||o,b=n.thresholds||[{l:"s",r:44,d:"second"},{l:"m",r:89},{l:"mm",r:44,d:"minute"},{l:"h",r:89},{l:"hh",r:21,d:"hour"},{l:"d",r:35},{l:"dd",r:25,d:"day"},{l:"M",r:45},{l:"MM",r:10,d:"month"},{l:"y",r:17},{l:"yy",d:"year"}],w=b.length,S=0;S<w;S+=1){var k=b[S];k.d&&(g=p?i(c).diff(f,k.d,!0):f.diff(c,k.d,!0));var j=(n.rounding||Math.round)(Math.abs(g));if(x=g>0,j<=k.r||!k.r){j<=1&&S>0&&(k=b[S-1]);var C=v[k.l];h&&(j=h(""+j)),y=typeof C=="string"?C.replace("%d",j):C(j,d,k.l,x);break}}if(d)return y;var T=x?v.future:v.past;return typeof T=="function"?T(y):T.replace("%s",y)},a.to=function(c,d){return l(c,d,this,!0)},a.from=function(c,d){return l(c,d,this)};var s=function(c){return c.$u?i.utc():i()};a.toNow=function(c){return this.to(s(this),c)},a.fromNow=function(c){return this.from(s(this),c)}}})})(TE);var xB=TE.exports;const bB=Vn(xB),wB=["authorization","x-api-key","api-key","apikey","x-auth-token","auth-token","secret","password","api_secret","jwt","csrf_token","xsrf_token","auth_token","session_token","private_key","client_secret"],SB=e=>{const t=e.toLowerCase();return!!(wB.some(n=>t===n)||t.startsWith("api_")&&(t.endsWith("_key")||t.endsWith("_secret"))||(t.endsWith("_token")||t.endsWith("_key")||t.endsWith("_secret"))&&!["max_tokens","input_tokens","output_tokens","completion_tokens","prompt_tokens","cachereadinputtokens","totaltokens"].some(r=>t.replace(/_/g,"").includes(r.replace(/_/g,""))))},jB=e=>!e||e.length<=8?"***":`${e.slice(0,4)}${"*".repeat(Math.min(e.length-8,20))}${e.slice(-4)}`,Ig=e=>{if(e==null)return e;if(Array.isArray(e))return e.map(t=>Ig(t));if(typeof e=="object"){const t={};for(const[n,r]of Object.entries(e))SB(n)?t[n]=typeof r=="string"?jB(r):"***":typeof r=="object"?t[n]=Ig(r):t[n]=r;return t}return e},pr=({data:e,title:t,collapsed:n=!1})=>{const[r,i]=m.useState(!n),[a,o]=m.useState(!1),l=d=>{try{let f;typeof d=="string"?f=JSON.parse(d):f=d;const p=Ig(f);return JSON.stringify(p,null,2)}catch{return typeof d=="string"?d:String(d)}},s=()=>{const d=l(e);navigator.clipboard.writeText(d).then(()=>{o(!0),setTimeout(()=>o(!1),2e3)}).catch(f=>{console.error("Failed to copy JSON:",f)})},c=l(e);return u.jsxs("div",{className:"json-viewer",children:[u.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:"8px"},children:[t&&u.jsx("h4",{style:{margin:0,fontSize:"14px",color:"var(--text-primary)"},children:t}),u.jsxs("div",{style:{display:"flex",gap:"8px"},children:[u.jsx("button",{onClick:()=>i(!r),className:"btn btn-sm btn-secondary",style:{fontSize:"12px",padding:"2px 8px"},children:r?"折叠":"展开"}),u.jsx("button",{onClick:s,className:"btn btn-sm btn-primary",style:{fontSize:"12px",padding:"2px 8px"},children:a?"已复制":"复制"})]})]}),r&&u.jsx("pre",{style:{background:"var(--bg-code)",border:"1px solid var(--border-primary)",borderRadius:"8px",padding:"12px",overflowX:"auto",fontSize:"12px",lineHeight:"1.4",color:"var(--text-primary)",maxHeight:"400px",overflowY:"auto",margin:0},children:u.jsx("code",{children:c})})]})},Xh=({currentPage:e,totalItems:t,pageSize:n,onPageChange:r,onPageSizeChange:i,pageSizeOptions:a=[10,20,50,100]})=>{const o=Math.max(1,Math.ceil(t/n)),l=e===1,s=e>=o,c=()=>{l||r(1)},d=()=>{l||r(e-1)},f=()=>{s||r(e+1)},p=()=>{s||r(o)},h=g=>{const y=parseInt(g.target.value,10);i(y)};return u.jsxs("div",{className:"pagination",children:[u.jsxs("div",{className:"pagination-info",children:["共 ",t," 条"]}),u.jsxs("div",{className:"pagination-controls",children:[u.jsx("button",{className:"pagination-btn",onClick:c,disabled:l,children:"首页"}),u.jsx("button",{className:"pagination-btn",onClick:d,disabled:l,children:"上一页"}),u.jsxs("span",{className:"pagination-info",children:["第 ",e," / ",o," 页"]}),u.jsx("button",{className:"pagination-btn",onClick:f,disabled:s,children:"下一页"}),u.jsx("button",{className:"pagination-btn",onClick:p,disabled:s,children:"尾页"})]}),u.jsx("div",{className:"pagination-size",children:u.jsxs("label",{children:["每页显示",u.jsx("select",{className:"pagination-select",value:n,onChange:h,children:a.map(g=>u.jsx("option",{value:g,children:g},g))}),"条"]})})]})};on.extend(bB);function kB(e){const t=[];let n={dataLines:[],rawLines:[]};for(const r of e){const i=r.split(`
|
|
123
123
|
`);for(const a of i){if(n.rawLines.push(a),!a.trim()){if(n.event||n.dataLines.length>0){const o=n.dataLines.length>0?n.dataLines.join(`
|
|
124
124
|
`):void 0,l={event:n.event,raw:n.rawLines.join(`
|
|
125
125
|
`)};if(o)try{l.data=JSON.parse(o)}catch{l.data=o}t.push(l)}n={dataLines:[],rawLines:[]};continue}a.startsWith("event:")?n.event=a.slice(6).trim():a.startsWith("data:")&&n.dataLines.push(a.slice(5).trim())}}if(n.event||n.dataLines.length>0){const r=n.dataLines.length>0?n.dataLines.join(`
|
package/dist/ui/index.html
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<title>AI Code Switch</title>
|
|
7
|
-
<script type="module" crossorigin src="./assets/index-
|
|
7
|
+
<script type="module" crossorigin src="./assets/index-BtoE4g4L.js"></script>
|
|
8
8
|
<link rel="stylesheet" crossorigin href="./assets/index-C7G0whng.css">
|
|
9
9
|
</head>
|
|
10
10
|
<body>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aicodeswitch",
|
|
3
|
-
"version": "3.6.
|
|
3
|
+
"version": "3.6.2",
|
|
4
4
|
"description": "A tool to help you manage AI programming tools to access large language models locally. It allows your Claude Code, Codex and other tools to no longer be limited to official models.",
|
|
5
5
|
"author": "tangshuang",
|
|
6
6
|
"license": "GPL-3.0",
|