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.
- package/README.md +1 -0
- package/bin/restore.js +14 -7
- package/bin/utils/managed-fields.js +62 -0
- package/dist/server/access-keys/index.js +173 -0
- package/dist/server/access-keys/key-logger.js +358 -0
- package/dist/server/access-keys/key-resolver.js +51 -0
- package/dist/server/access-keys/key-session-tracker.js +217 -0
- package/dist/server/access-keys/manager.js +206 -0
- package/dist/server/access-keys/policy-manager.js +144 -0
- package/dist/server/access-keys/quota-checker.js +197 -0
- package/dist/server/access-keys/usage-tracker.js +279 -0
- package/dist/server/auth.js +16 -4
- package/dist/server/coding-plan-headers.js +121 -0
- package/dist/server/config-managed-fields.js +2 -0
- package/dist/server/conversions/index.js +8 -0
- package/dist/server/conversions/utils/tool-result.js +35 -0
- package/dist/server/fs-database.js +72 -1
- package/dist/server/main.js +1162 -13
- package/dist/server/proxy-server.js +662 -128
- package/dist/server/rules-status-service.js +32 -3
- package/dist/server/session-launcher.js +282 -0
- package/dist/server/session-migration.js +419 -0
- package/dist/server/transformers/chunk-collector.js +28 -1
- package/dist/server/transformers/model-rewrite-transform.js +128 -0
- package/dist/ui/assets/claude-XtpLmGtF.webp +0 -0
- package/dist/ui/assets/index-Cws89pD2.js +828 -0
- package/dist/ui/assets/index-CzfKxImD.css +1 -0
- package/dist/ui/assets/openai-CPEiZpaN.webp +0 -0
- package/dist/ui/index.html +2 -2
- package/package.json +1 -1
- package/dist/ui/assets/index-BHR12ImE.css +0 -1
- 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* () {
|