aicodeswitch 5.1.3 → 5.2.1
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 +362 -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/config-managed-fields.js +2 -0
- package/dist/server/fs-database.js +14 -1
- package/dist/server/main.js +1017 -13
- package/dist/server/proxy-server.js +605 -134
- package/dist/server/rules-status-service.js +16 -3
- package/dist/server/transformers/model-rewrite-transform.js +128 -0
- package/dist/ui/assets/index-Cws89pD2.js +828 -0
- package/dist/ui/assets/index-CzfKxImD.css +1 -0
- package/dist/ui/index.html +2 -2
- package/package.json +1 -1
- package/dist/ui/assets/index-CMoQtBmK.css +0 -1
- package/dist/ui/assets/index-CXdNTFiX.js +0 -532
|
@@ -10,12 +10,14 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.rulesStatusBroadcaster = exports.RulesStatusBroadcaster = void 0;
|
|
13
|
+
const events_1 = require("events");
|
|
13
14
|
/**
|
|
14
15
|
* 规则状态管理服务
|
|
15
16
|
* 负责管理所有规则的状态(使用中、空闲、错误、挂起)
|
|
16
17
|
*/
|
|
17
|
-
class RulesStatusBroadcaster {
|
|
18
|
+
class RulesStatusBroadcaster extends events_1.EventEmitter {
|
|
18
19
|
constructor() {
|
|
20
|
+
super();
|
|
19
21
|
Object.defineProperty(this, "ruleStates", {
|
|
20
22
|
enumerable: true,
|
|
21
23
|
configurable: true,
|
|
@@ -70,6 +72,8 @@ class RulesStatusBroadcaster {
|
|
|
70
72
|
writable: true,
|
|
71
73
|
value: 30000
|
|
72
74
|
}); // error 状态30秒后自动恢复
|
|
75
|
+
// 允许多标签页场景下的多连接监听
|
|
76
|
+
this.setMaxListeners(50);
|
|
73
77
|
// 启动定期状态检查定时器
|
|
74
78
|
this.startSyncInterval();
|
|
75
79
|
}
|
|
@@ -99,7 +103,7 @@ class RulesStatusBroadcaster {
|
|
|
99
103
|
data.timestamp &&
|
|
100
104
|
now - data.timestamp > this.ERROR_RECOVERY_TIMEOUT) {
|
|
101
105
|
console.log(`[RulesStatusBroadcaster] 规则 ${ruleId} 错误状态已超时,自动恢复为 idle 状态`);
|
|
102
|
-
this.
|
|
106
|
+
this.updateRuleStatus({
|
|
103
107
|
ruleId,
|
|
104
108
|
status: 'idle',
|
|
105
109
|
routeId: data.routeId,
|
|
@@ -130,7 +134,7 @@ class RulesStatusBroadcaster {
|
|
|
130
134
|
if (!isBlacklisted) {
|
|
131
135
|
// 黑名单已过期,恢复为 idle 状态
|
|
132
136
|
console.log(`[RulesStatusBroadcaster] 规则 ${ruleId} 黑名单已过期,恢复为 idle 状态`);
|
|
133
|
-
this.
|
|
137
|
+
this.updateRuleStatus({
|
|
134
138
|
ruleId,
|
|
135
139
|
status: 'idle',
|
|
136
140
|
routeId,
|
|
@@ -172,6 +176,8 @@ class RulesStatusBroadcaster {
|
|
|
172
176
|
updateRuleStatus(data) {
|
|
173
177
|
// 更新本地状态
|
|
174
178
|
this.ruleStates.set(data.ruleId, data);
|
|
179
|
+
// 通知 SSE 客户端状态已变更
|
|
180
|
+
this.emit('statusChanged', data);
|
|
175
181
|
}
|
|
176
182
|
/**
|
|
177
183
|
* 标记规则正在使用
|
|
@@ -288,6 +294,12 @@ class RulesStatusBroadcaster {
|
|
|
288
294
|
*/
|
|
289
295
|
clearRuleStatus(ruleId) {
|
|
290
296
|
this.ruleStates.delete(ruleId);
|
|
297
|
+
// 通知 SSE 客户端状态已清除(恢复为 idle)
|
|
298
|
+
this.emit('statusChanged', {
|
|
299
|
+
ruleId,
|
|
300
|
+
status: 'idle',
|
|
301
|
+
timestamp: Date.now(),
|
|
302
|
+
});
|
|
291
303
|
}
|
|
292
304
|
/**
|
|
293
305
|
* 获取当前活动的规则列表
|
|
@@ -320,6 +332,7 @@ class RulesStatusBroadcaster {
|
|
|
320
332
|
this.idleDebounceTimeouts.forEach((timeout) => clearTimeout(timeout));
|
|
321
333
|
this.idleDebounceTimeouts.clear();
|
|
322
334
|
this.ruleStates.clear();
|
|
335
|
+
this.removeAllListeners();
|
|
323
336
|
}
|
|
324
337
|
}
|
|
325
338
|
exports.RulesStatusBroadcaster = RulesStatusBroadcaster;
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ModelRewriteTransform = void 0;
|
|
4
|
+
exports.rewriteResponseModel = rewriteResponseModel;
|
|
5
|
+
const stream_1 = require("stream");
|
|
6
|
+
const string_decoder_1 = require("string_decoder");
|
|
7
|
+
/**
|
|
8
|
+
* 流式 SSE 响应中的 model 字段回写 Transform。
|
|
9
|
+
*
|
|
10
|
+
* 插入位置:SSESerializerTransform 之后、ChunkCollectorTransform 之前。
|
|
11
|
+
* 输入/输出均为 text mode(字符串),通过正则替换 SSE data 行中的
|
|
12
|
+
* "model":"上游模型名" → "model":"客户端原始模型名"。
|
|
13
|
+
*/
|
|
14
|
+
class ModelRewriteTransform extends stream_1.Transform {
|
|
15
|
+
constructor(originalModel) {
|
|
16
|
+
super({
|
|
17
|
+
writableObjectMode: false, // 接收序列化后的文本
|
|
18
|
+
readableObjectMode: false, // 输出文本
|
|
19
|
+
});
|
|
20
|
+
Object.defineProperty(this, "modelRegex", {
|
|
21
|
+
enumerable: true,
|
|
22
|
+
configurable: true,
|
|
23
|
+
writable: true,
|
|
24
|
+
value: void 0
|
|
25
|
+
});
|
|
26
|
+
Object.defineProperty(this, "replacement", {
|
|
27
|
+
enumerable: true,
|
|
28
|
+
configurable: true,
|
|
29
|
+
writable: true,
|
|
30
|
+
value: void 0
|
|
31
|
+
});
|
|
32
|
+
Object.defineProperty(this, "modelVersionRegex", {
|
|
33
|
+
enumerable: true,
|
|
34
|
+
configurable: true,
|
|
35
|
+
writable: true,
|
|
36
|
+
value: null
|
|
37
|
+
});
|
|
38
|
+
Object.defineProperty(this, "modelVersionReplacement", {
|
|
39
|
+
enumerable: true,
|
|
40
|
+
configurable: true,
|
|
41
|
+
writable: true,
|
|
42
|
+
value: null
|
|
43
|
+
});
|
|
44
|
+
Object.defineProperty(this, "stringDecoder", {
|
|
45
|
+
enumerable: true,
|
|
46
|
+
configurable: true,
|
|
47
|
+
writable: true,
|
|
48
|
+
value: new string_decoder_1.StringDecoder('utf8')
|
|
49
|
+
});
|
|
50
|
+
Object.defineProperty(this, "buffer", {
|
|
51
|
+
enumerable: true,
|
|
52
|
+
configurable: true,
|
|
53
|
+
writable: true,
|
|
54
|
+
value: ''
|
|
55
|
+
});
|
|
56
|
+
// 转义原始模型名中的特殊字符,防止 JSON 注入
|
|
57
|
+
const escaped = originalModel.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
|
|
58
|
+
this.replacement = `"model":"${escaped}"`;
|
|
59
|
+
this.modelRegex = /"model"\s*:\s*"[^"]*"/g;
|
|
60
|
+
// 处理 Gemini 直通场景中的 modelVersion 字段
|
|
61
|
+
if (originalModel) {
|
|
62
|
+
this.modelVersionReplacement = `"modelVersion":"${escaped}"`;
|
|
63
|
+
this.modelVersionRegex = /"modelVersion"\s*:\s*"[^"]*"/g;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
_transform(chunk, _encoding, callback) {
|
|
67
|
+
try {
|
|
68
|
+
this.buffer += this.stringDecoder.write(chunk);
|
|
69
|
+
// 按行处理(SSE 协议以 \n 分隔)
|
|
70
|
+
const lines = this.buffer.split('\n');
|
|
71
|
+
this.buffer = lines.pop() || '';
|
|
72
|
+
for (const line of lines) {
|
|
73
|
+
this.push(this.rewriteLine(line) + '\n');
|
|
74
|
+
}
|
|
75
|
+
callback();
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
callback(error);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
_flush(callback) {
|
|
82
|
+
try {
|
|
83
|
+
const remaining = this.stringDecoder.end();
|
|
84
|
+
if (remaining)
|
|
85
|
+
this.buffer += remaining;
|
|
86
|
+
if (this.buffer) {
|
|
87
|
+
this.push(this.rewriteLine(this.buffer));
|
|
88
|
+
}
|
|
89
|
+
callback();
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
callback(error);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
rewriteLine(line) {
|
|
96
|
+
// 只处理 SSE data 行
|
|
97
|
+
if (!line.startsWith('data:'))
|
|
98
|
+
return line;
|
|
99
|
+
let result = line;
|
|
100
|
+
// 重置正则 lastIndex(因为带 g 标志)
|
|
101
|
+
this.modelRegex.lastIndex = 0;
|
|
102
|
+
result = result.replace(this.modelRegex, this.replacement);
|
|
103
|
+
if (this.modelVersionRegex && this.modelVersionReplacement) {
|
|
104
|
+
this.modelVersionRegex.lastIndex = 0;
|
|
105
|
+
result = result.replace(this.modelVersionRegex, this.modelVersionReplacement);
|
|
106
|
+
}
|
|
107
|
+
return result;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
exports.ModelRewriteTransform = ModelRewriteTransform;
|
|
111
|
+
/**
|
|
112
|
+
* 非流式响应中的 model 字段回写。
|
|
113
|
+
*
|
|
114
|
+
* 将响应对象的 model(以及 Gemini 的 modelVersion)改写为客户端原始模型名。
|
|
115
|
+
* 直接修改传入对象(原地修改)。
|
|
116
|
+
*/
|
|
117
|
+
function rewriteResponseModel(responseData, originalModel) {
|
|
118
|
+
if (!responseData || !originalModel || typeof responseData !== 'object')
|
|
119
|
+
return;
|
|
120
|
+
// 所有格式在转换后统一使用 "model" 字段
|
|
121
|
+
if ('model' in responseData) {
|
|
122
|
+
responseData.model = originalModel;
|
|
123
|
+
}
|
|
124
|
+
// Gemini 直通场景可能保留 modelVersion
|
|
125
|
+
if ('modelVersion' in responseData) {
|
|
126
|
+
responseData.modelVersion = originalModel;
|
|
127
|
+
}
|
|
128
|
+
}
|