aicodeswitch 3.9.2 → 3.9.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -887,7 +887,8 @@ class ProxyServer {
887
887
  return undefined;
888
888
  const body = req.body;
889
889
  const requestModel = body === null || body === void 0 ? void 0 : body.model;
890
- const contentType = forcedContentType || this.determineContentType(req);
890
+ const route = this.dbManager.getRoutes().find(r => r.id === routeId);
891
+ const contentType = forcedContentType || this.determineContentType(req, (route === null || route === void 0 ? void 0 : route.targetType) || 'claude-code', routeId);
891
892
  // 高智商规则优先于 model-mapping,确保 !!/推断命中时不会被模型映射覆盖
892
893
  if (contentType === 'high-iq') {
893
894
  const highIqRules = enabledRules.filter(rule => rule.contentType === 'high-iq');
@@ -910,7 +911,32 @@ class ProxyServer {
910
911
  return rule;
911
912
  }
912
913
  }
913
- // 1. 首先查找 model-mapping 类型的规则,按 sortOrder 降序匹配
914
+ // 1. 查找其他内容类型的规则
915
+ const contentTypeRules = enabledRules.filter(rule => rule.contentType === contentType);
916
+ // 过滤黑名单和token限制
917
+ for (const rule of contentTypeRules) {
918
+ const isBlacklisted = yield this.dbManager.isServiceBlacklisted(rule.targetServiceId, routeId, contentType);
919
+ if (isBlacklisted) {
920
+ continue;
921
+ }
922
+ // 检查并重置到期的规则
923
+ this.dbManager.checkAndResetRuleIfNeeded(rule.id);
924
+ this.dbManager.checkAndResetRequestCountIfNeeded(rule.id);
925
+ // 检查token限制(tokenLimit单位是k,需要乘以1000转换为实际token数)
926
+ if (rule.tokenLimit && rule.totalTokensUsed !== undefined && rule.totalTokensUsed >= rule.tokenLimit * 1000) {
927
+ continue; // 跳过超限规则
928
+ }
929
+ // 检查请求次数限制
930
+ if (rule.requestCountLimit && rule.totalRequestsUsed !== undefined && rule.totalRequestsUsed >= rule.requestCountLimit) {
931
+ continue; // 跳过超限规则
932
+ }
933
+ // 检查频率限制
934
+ if (this.isFrequencyLimitExceeded(rule)) {
935
+ continue; // 跳过达到频率限制的规则
936
+ }
937
+ return rule;
938
+ }
939
+ // 2. 然后查找 model-mapping 类型的规则
914
940
  if (requestModel) {
915
941
  const modelMappingRules = enabledRules.filter(rule => rule.contentType === 'model-mapping' &&
916
942
  rule.replacedModel &&
@@ -939,31 +965,6 @@ class ProxyServer {
939
965
  return rule;
940
966
  }
941
967
  }
942
- // 2. 查找其他内容类型的规则
943
- const contentTypeRules = enabledRules.filter(rule => rule.contentType === contentType);
944
- // 过滤黑名单和token限制
945
- for (const rule of contentTypeRules) {
946
- const isBlacklisted = yield this.dbManager.isServiceBlacklisted(rule.targetServiceId, routeId, contentType);
947
- if (isBlacklisted) {
948
- continue;
949
- }
950
- // 检查并重置到期的规则
951
- this.dbManager.checkAndResetRuleIfNeeded(rule.id);
952
- this.dbManager.checkAndResetRequestCountIfNeeded(rule.id);
953
- // 检查token限制(tokenLimit单位是k,需要乘以1000转换为实际token数)
954
- if (rule.tokenLimit && rule.totalTokensUsed !== undefined && rule.totalTokensUsed >= rule.tokenLimit * 1000) {
955
- continue; // 跳过超限规则
956
- }
957
- // 检查请求次数限制
958
- if (rule.requestCountLimit && rule.totalRequestsUsed !== undefined && rule.totalRequestsUsed >= rule.requestCountLimit) {
959
- continue; // 跳过超限规则
960
- }
961
- // 检查频率限制
962
- if (this.isFrequencyLimitExceeded(rule)) {
963
- continue; // 跳过达到频率限制的规则
964
- }
965
- return rule;
966
- }
967
968
  // 3. 最后返回 default 规则
968
969
  const defaultRules = enabledRules.filter(rule => rule.contentType === 'default');
969
970
  // 过滤黑名单和token限制
@@ -1003,7 +1004,8 @@ class ProxyServer {
1003
1004
  const body = req.body;
1004
1005
  const requestModel = body === null || body === void 0 ? void 0 : body.model;
1005
1006
  const candidates = [];
1006
- const contentType = forcedContentType || this.determineContentType(req);
1007
+ const route = this.dbManager.getRoutes().find(r => r.id === routeId);
1008
+ const contentType = forcedContentType || this.determineContentType(req, (route === null || route === void 0 ? void 0 : route.targetType) || 'claude-code', routeId);
1007
1009
  const prioritizeContentType = contentType === 'high-iq';
1008
1010
  const modelMappingRules = requestModel
1009
1011
  ? enabledRules.filter(rule => rule.contentType === 'model-mapping' &&
@@ -1133,7 +1135,7 @@ class ProxyServer {
1133
1135
  }
1134
1136
  }
1135
1137
  }
1136
- determineContentType(req) {
1138
+ determineContentType(req, targetType, routeId) {
1137
1139
  const body = req.body;
1138
1140
  if (!body)
1139
1141
  return 'default';
@@ -1145,8 +1147,10 @@ class ProxyServer {
1145
1147
  if (explicitType) {
1146
1148
  return explicitType;
1147
1149
  }
1150
+ // 获取sessionId用于session级别的检测(如long-context)
1151
+ const sessionId = this.defaultExtractSessionId(req, targetType);
1148
1152
  for (const detector of this.getContentTypeDetectors()) {
1149
- if (detector.match(req, body)) {
1153
+ if (detector.match(req, body, sessionId, routeId)) {
1150
1154
  return detector.type;
1151
1155
  }
1152
1156
  }
@@ -1158,17 +1162,17 @@ class ProxyServer {
1158
1162
  type: 'image-understanding',
1159
1163
  match: (_req, body) => this.containsImageContent(body.messages) || this.containsImageContent(body.input),
1160
1164
  },
1161
- {
1162
- type: 'thinking',
1163
- match: (_req, body) => this.hasThinkingSignal(body),
1164
- },
1165
1165
  {
1166
1166
  type: 'high-iq',
1167
1167
  match: (_req, body) => this.hasHighIqSignal(body),
1168
1168
  },
1169
1169
  {
1170
1170
  type: 'long-context',
1171
- match: (_req, body) => this.hasLongContextSignal(body),
1171
+ match: (_req, body, sessionId, routeId) => this.hasLongContextSignal(body, sessionId, routeId),
1172
+ },
1173
+ {
1174
+ type: 'thinking',
1175
+ match: (_req, body) => this.hasThinkingSignal(body),
1172
1176
  },
1173
1177
  {
1174
1178
  type: 'background',
@@ -1574,8 +1578,8 @@ class ProxyServer {
1574
1578
  ];
1575
1579
  return candidates.some((value) => value === true || value === 'background');
1576
1580
  }
1577
- hasLongContextSignal(body) {
1578
- var _a, _b;
1581
+ hasLongContextSignal(body, sessionId, routeId) {
1582
+ var _a, _b, _c;
1579
1583
  const explicit = [
1580
1584
  body === null || body === void 0 ? void 0 : body.long_context,
1581
1585
  body === null || body === void 0 ? void 0 : body.longContext,
@@ -1585,6 +1589,22 @@ class ProxyServer {
1585
1589
  if (explicit.some((value) => value === true)) {
1586
1590
  return true;
1587
1591
  }
1592
+ // 检查session累积tokens
1593
+ if (sessionId && routeId) {
1594
+ const session = this.dbManager.getSession(sessionId);
1595
+ if (session && session.totalTokens > 0) {
1596
+ // 查找该route下的long-context规则,获取阈值配置
1597
+ const rules = this.getRulesByRouteId(routeId);
1598
+ const longContextRule = rules === null || rules === void 0 ? void 0 : rules.find(rule => rule.contentType === 'long-context' && !rule.isDisabled);
1599
+ // 默认阈值为1M tokens (1000k)
1600
+ const defaultThreshold = 1000; // 单位:k
1601
+ const threshold = (_c = longContextRule === null || longContextRule === void 0 ? void 0 : longContextRule.sessionTokenThreshold) !== null && _c !== void 0 ? _c : defaultThreshold;
1602
+ // 如果session累积tokens超过阈值,则认为是long-context
1603
+ if (session.totalTokens >= threshold * 1000) {
1604
+ return true;
1605
+ }
1606
+ }
1607
+ }
1588
1608
  const maxTokens = this.extractNumericField(body, [
1589
1609
  'max_tokens',
1590
1610
  'max_output_tokens',
@@ -2273,8 +2293,9 @@ class ProxyServer {
2273
2293
  // Session 索引逻辑
2274
2294
  const sessionId = this.defaultExtractSessionId(req, targetType);
2275
2295
  if (sessionId) {
2276
- const totalTokens = ((usageForLog === null || usageForLog === void 0 ? void 0 : usageForLog.inputTokens) || 0) + ((usageForLog === null || usageForLog === void 0 ? void 0 : usageForLog.outputTokens) || 0) +
2277
- ((usageForLog === null || usageForLog === void 0 ? void 0 : usageForLog.totalTokens) || 0);
2296
+ // 正确计算当前请求的tokens:优先使用totalTokens,否则使用input+output
2297
+ const totalTokens = (usageForLog === null || usageForLog === void 0 ? void 0 : usageForLog.totalTokens) ||
2298
+ (((usageForLog === null || usageForLog === void 0 ? void 0 : usageForLog.inputTokens) || 0) + ((usageForLog === null || usageForLog === void 0 ? void 0 : usageForLog.outputTokens) || 0));
2278
2299
  const sessionTitle = this.defaultExtractSessionTitle(req, sessionId);
2279
2300
  const existingSession = this.dbManager.getSession(sessionId);
2280
2301
  this.dbManager.upsertSession({
@@ -2298,7 +2319,8 @@ class ProxyServer {
2298
2319
  }
2299
2320
  // 更新规则的token使用量(只在成功请求时更新)
2300
2321
  if (usageForLog && statusCode < 400) {
2301
- const totalTokens = (usageForLog.inputTokens || 0) + (usageForLog.outputTokens || 0);
2322
+ const totalTokens = usageForLog.totalTokens ||
2323
+ ((usageForLog.inputTokens || 0) + (usageForLog.outputTokens || 0));
2302
2324
  if (totalTokens > 0) {
2303
2325
  this.dbManager.incrementRuleTokenUsage(rule.id, totalTokens);
2304
2326
  // 获取更新后的规则数据并广播