aicodeswitch 5.1.2 → 5.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/README.md +1 -0
  2. package/bin/restore.js +14 -7
  3. package/bin/utils/managed-fields.js +62 -0
  4. package/dist/server/access-keys/index.js +173 -0
  5. package/dist/server/access-keys/key-logger.js +358 -0
  6. package/dist/server/access-keys/key-resolver.js +51 -0
  7. package/dist/server/access-keys/key-session-tracker.js +217 -0
  8. package/dist/server/access-keys/manager.js +206 -0
  9. package/dist/server/access-keys/policy-manager.js +144 -0
  10. package/dist/server/access-keys/quota-checker.js +197 -0
  11. package/dist/server/access-keys/usage-tracker.js +279 -0
  12. package/dist/server/auth.js +16 -4
  13. package/dist/server/coding-plan-headers.js +121 -0
  14. package/dist/server/config-managed-fields.js +2 -0
  15. package/dist/server/conversions/index.js +8 -0
  16. package/dist/server/conversions/utils/tool-result.js +35 -0
  17. package/dist/server/fs-database.js +72 -1
  18. package/dist/server/main.js +1162 -13
  19. package/dist/server/proxy-server.js +662 -128
  20. package/dist/server/rules-status-service.js +32 -3
  21. package/dist/server/session-launcher.js +282 -0
  22. package/dist/server/session-migration.js +419 -0
  23. package/dist/server/transformers/chunk-collector.js +28 -1
  24. package/dist/server/transformers/model-rewrite-transform.js +128 -0
  25. package/dist/ui/assets/claude-XtpLmGtF.webp +0 -0
  26. package/dist/ui/assets/index-Cws89pD2.js +828 -0
  27. package/dist/ui/assets/index-CzfKxImD.css +1 -0
  28. package/dist/ui/assets/openai-CPEiZpaN.webp +0 -0
  29. package/dist/ui/index.html +2 -2
  30. package/package.json +1 -1
  31. package/dist/ui/assets/index-BHR12ImE.css +0 -1
  32. package/dist/ui/assets/index-CumAhpXg.js +0 -517
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ /**
3
+ * Tool result content block utilities.
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.ensureToolResultIds = ensureToolResultIds;
7
+ /**
8
+ * 为所有缺少 id 的 tool_result 块补上 id。
9
+ *
10
+ * 部分 Claude 兼容端点(如 GLM)要求 tool_result 内容块必须包含 id 字段,
11
+ * 但标准 Claude API 的 tool_result 块仅有 tool_use_id 而不带 id。
12
+ *
13
+ * id 取值策略:优先使用 tool_use_id(与对应的 tool_use.id 保持一致),
14
+ * 若 tool_use_id 也不存在则生成唯一 id。
15
+ */
16
+ function ensureToolResultIds(messages) {
17
+ let totalPatched = 0;
18
+ const result = messages.map(msg => {
19
+ if (msg.role !== 'user' || !Array.isArray(msg.content))
20
+ return msg;
21
+ let patched = false;
22
+ const newContent = msg.content.map((b) => {
23
+ if (b.type === 'tool_result' && !b.id) {
24
+ patched = true;
25
+ totalPatched++;
26
+ // 使用 tool_use_id 作为 id,保持与对应 tool_use 块的 id 一致
27
+ const id = b.tool_use_id || `toolu_${crypto.randomUUID().replace(/-/g, '').slice(0, 24)}`;
28
+ return Object.assign(Object.assign({}, b), { id });
29
+ }
30
+ return b;
31
+ });
32
+ return patched ? Object.assign(Object.assign({}, msg), { content: newContent }) : msg;
33
+ });
34
+ return { messages: result, patchedCount: totalPatched };
35
+ }
@@ -1203,7 +1203,6 @@ class FileSystemDatabaseManager {
1203
1203
  enableLogging: true,
1204
1204
  logRetentionDays: 30,
1205
1205
  maxLogSize: 100000,
1206
- apiKey: '',
1207
1206
  enableFailover: true,
1208
1207
  failoverRecoverySeconds: DEFAULT_FAILOVER_RECOVERY_SECONDS,
1209
1208
  ruleGlobalTimeout: undefined,
@@ -1218,6 +1217,7 @@ class FileSystemDatabaseManager {
1218
1217
  proxyUrl: '',
1219
1218
  proxyUsername: '',
1220
1219
  proxyPassword: '',
1220
+ enableLanDiscovery: false,
1221
1221
  };
1222
1222
  // spread: current 覆盖 defaults,未来新增字段自动保留
1223
1223
  this.config = Object.assign(Object.assign({}, defaults), current);
@@ -1597,6 +1597,18 @@ class FileSystemDatabaseManager {
1597
1597
  yield this.saveRules();
1598
1598
  this.routes.splice(index, 1);
1599
1599
  yield this.saveRoutes();
1600
+ // 级联清理:清除绑定到该路由的会话的绑定关系
1601
+ let sessionChanged = false;
1602
+ for (const session of this.sessions) {
1603
+ if (session.routeId === id) {
1604
+ session.routeId = undefined;
1605
+ session.routeName = undefined;
1606
+ sessionChanged = true;
1607
+ }
1608
+ }
1609
+ if (sessionChanged) {
1610
+ yield this.saveSessions();
1611
+ }
1600
1612
  return true;
1601
1613
  });
1602
1614
  }
@@ -2364,6 +2376,9 @@ class FileSystemDatabaseManager {
2364
2376
  if (service.inheritVendorApiBaseUrl !== undefined && typeof service.inheritVendorApiBaseUrl !== 'boolean') {
2365
2377
  return { valid: false, error: `供应商[${index}](${vendor.id}) 的服务[${i}] inheritVendorApiBaseUrl 必须是布尔值` };
2366
2378
  }
2379
+ if (service.inheritVendorAuthType !== undefined && typeof service.inheritVendorAuthType !== 'boolean') {
2380
+ return { valid: false, error: `供应商[${index}](${vendor.id}) 的服务[${i}] inheritVendorAuthType 必须是布尔值` };
2381
+ }
2367
2382
  }
2368
2383
  return { valid: true };
2369
2384
  }
@@ -2678,6 +2693,16 @@ class FileSystemDatabaseManager {
2678
2693
  });
2679
2694
  }
2680
2695
  // Statistics operations
2696
+ /**
2697
+ * 从 AccessKey 请求同步全局统计数据(不写入日志,仅更新统计)
2698
+ */
2699
+ syncStatisticsFromAccessKey(logData) {
2700
+ return __awaiter(this, void 0, void 0, function* () {
2701
+ // 构造一个带有 id 的 RequestLog 以复用 updateStatistics
2702
+ const log = Object.assign(Object.assign({}, logData), { id: `ak-sync-${Date.now()}` });
2703
+ yield this.updateStatistics(log);
2704
+ });
2705
+ }
2681
2706
  /**
2682
2707
  * 更新统计数据 - 在每次添加日志时调用
2683
2708
  */
@@ -3052,6 +3077,11 @@ class FileSystemDatabaseManager {
3052
3077
  existing.highIqRuleId = session.highIqRuleId;
3053
3078
  if (Object.prototype.hasOwnProperty.call(session, 'highIqEnabledAt'))
3054
3079
  existing.highIqEnabledAt = session.highIqEnabledAt;
3080
+ // 保留已有的路由绑定(不传入时不覆盖)
3081
+ if (session.routeId !== undefined)
3082
+ existing.routeId = session.routeId;
3083
+ if (session.routeName !== undefined)
3084
+ existing.routeName = session.routeName;
3055
3085
  }
3056
3086
  else {
3057
3087
  // 创建新 session
@@ -3071,11 +3101,52 @@ class FileSystemDatabaseManager {
3071
3101
  highIqMode: session.highIqMode,
3072
3102
  highIqRuleId: session.highIqRuleId,
3073
3103
  highIqEnabledAt: session.highIqEnabledAt,
3104
+ routeId: session.routeId,
3105
+ routeName: session.routeName,
3074
3106
  });
3075
3107
  }
3076
3108
  // 异步保存(不阻塞)
3077
3109
  this.saveSessions().catch(console.error);
3078
3110
  }
3111
+ /**
3112
+ * 绑定会话到路由
3113
+ */
3114
+ bindSessionRoute(sessionId, routeId) {
3115
+ return __awaiter(this, void 0, void 0, function* () {
3116
+ const session = this.sessions.find(s => s.id === sessionId);
3117
+ if (!session)
3118
+ return null;
3119
+ const route = this.routes.find(r => r.id === routeId);
3120
+ if (!route)
3121
+ return null;
3122
+ session.routeId = routeId;
3123
+ session.routeName = route.name;
3124
+ yield this.saveSessions();
3125
+ return session;
3126
+ });
3127
+ }
3128
+ /**
3129
+ * 解绑会话路由
3130
+ */
3131
+ unbindSessionRoute(sessionId) {
3132
+ return __awaiter(this, void 0, void 0, function* () {
3133
+ const session = this.sessions.find(s => s.id === sessionId);
3134
+ if (!session)
3135
+ return false;
3136
+ session.routeId = undefined;
3137
+ session.routeName = undefined;
3138
+ yield this.saveSessions();
3139
+ return true;
3140
+ });
3141
+ }
3142
+ /**
3143
+ * 获取绑定到指定路由的所有会话
3144
+ */
3145
+ getBoundSessions(routeId) {
3146
+ return this.sessions
3147
+ .filter(s => s.routeId === routeId)
3148
+ .sort((a, b) => b.lastRequestAt - a.lastRequestAt);
3149
+ }
3079
3150
  // 新增方法:获取规则黑名单状态
3080
3151
  getRuleBlacklistStatus(serviceId, routeId, contentType) {
3081
3152
  return __awaiter(this, void 0, void 0, function* () {