aicodeswitch 4.0.0 → 4.0.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/dist/server/auth.js +12 -6
- package/dist/server/fs-database.js +240 -6
- package/dist/server/main.js +28 -10
- package/dist/server/proxy-server.js +126 -63
- package/dist/server/rules-status-service.js +20 -137
- package/dist/server/transformers/chunk-collector.js +38 -5
- package/dist/server/transformers/streaming.js +47 -29
- package/dist/server/transformers/transformers.js +20 -18
- package/dist/server/version-check.js +3 -2
- package/dist/ui/assets/index-BRHavnvn.js +514 -0
- package/dist/ui/index.html +1 -1
- package/package.json +1 -1
- package/dist/ui/assets/index-GQBwe1Rm.js +0 -514
|
@@ -9,52 +9,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.
|
|
13
|
-
exports.createRulesStatusWSServer = createRulesStatusWSServer;
|
|
14
|
-
// @ts-ignore - ws 类型声明可能需要手动安装 @types/ws
|
|
15
|
-
const ws_1 = require("ws");
|
|
12
|
+
exports.rulesStatusBroadcaster = exports.RulesStatusBroadcaster = void 0;
|
|
16
13
|
/**
|
|
17
|
-
*
|
|
18
|
-
|
|
19
|
-
class RulesStatusWS {
|
|
20
|
-
constructor(ws, req) {
|
|
21
|
-
Object.defineProperty(this, "ws", {
|
|
22
|
-
enumerable: true,
|
|
23
|
-
configurable: true,
|
|
24
|
-
writable: true,
|
|
25
|
-
value: void 0
|
|
26
|
-
});
|
|
27
|
-
this.ws = ws;
|
|
28
|
-
console.log(`[RulesStatusWS] 新的 WebSocket 连接: ${req.socket.remoteAddress}`);
|
|
29
|
-
this.ws.on('close', () => {
|
|
30
|
-
console.log(`[RulesStatusWS] WebSocket 连接关闭`);
|
|
31
|
-
});
|
|
32
|
-
this.ws.on('error', (err) => {
|
|
33
|
-
console.error(`[RulesStatusWS] WebSocket 错误:`, err);
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* 发送消息到客户端
|
|
38
|
-
*/
|
|
39
|
-
sendMessage(message) {
|
|
40
|
-
if (this.ws.readyState === ws_1.WebSocket.OPEN) {
|
|
41
|
-
this.ws.send(JSON.stringify(message));
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
exports.RulesStatusWS = RulesStatusWS;
|
|
46
|
-
/**
|
|
47
|
-
* 规则状态广播服务
|
|
48
|
-
* 管理所有连接的客户端,负责广播规则使用状态
|
|
14
|
+
* 规则状态管理服务
|
|
15
|
+
* 负责管理所有规则的状态(使用中、空闲、错误、挂起)
|
|
49
16
|
*/
|
|
50
17
|
class RulesStatusBroadcaster {
|
|
51
18
|
constructor() {
|
|
52
|
-
Object.defineProperty(this, "clients", {
|
|
53
|
-
enumerable: true,
|
|
54
|
-
configurable: true,
|
|
55
|
-
writable: true,
|
|
56
|
-
value: new Set()
|
|
57
|
-
});
|
|
58
19
|
Object.defineProperty(this, "ruleStates", {
|
|
59
20
|
enumerable: true,
|
|
60
21
|
configurable: true,
|
|
@@ -96,20 +57,20 @@ class RulesStatusBroadcaster {
|
|
|
96
57
|
configurable: true,
|
|
97
58
|
writable: true,
|
|
98
59
|
value: 3000
|
|
99
|
-
}); // idle
|
|
60
|
+
}); // idle 延迟3秒,避免对话快速进入 in_use 时闪烁
|
|
100
61
|
Object.defineProperty(this, "SYNC_INTERVAL", {
|
|
101
62
|
enumerable: true,
|
|
102
63
|
configurable: true,
|
|
103
64
|
writable: true,
|
|
104
65
|
value: 10000
|
|
105
|
-
}); // 每10
|
|
66
|
+
}); // 每10秒检查一次 suspended 和 error 状态
|
|
106
67
|
Object.defineProperty(this, "ERROR_RECOVERY_TIMEOUT", {
|
|
107
68
|
enumerable: true,
|
|
108
69
|
configurable: true,
|
|
109
70
|
writable: true,
|
|
110
71
|
value: 30000
|
|
111
72
|
}); // error 状态30秒后自动恢复
|
|
112
|
-
//
|
|
73
|
+
// 启动定期状态检查定时器
|
|
113
74
|
this.startSyncInterval();
|
|
114
75
|
}
|
|
115
76
|
/**
|
|
@@ -119,21 +80,18 @@ class RulesStatusBroadcaster {
|
|
|
119
80
|
this.blacklistChecker = checker;
|
|
120
81
|
}
|
|
121
82
|
/**
|
|
122
|
-
*
|
|
83
|
+
* 启动定期状态检查定时器
|
|
123
84
|
*/
|
|
124
85
|
startSyncInterval() {
|
|
125
86
|
this.syncInterval = setInterval(() => {
|
|
126
|
-
this.
|
|
87
|
+
this.checkSuspendedAndErrorRules();
|
|
127
88
|
}, this.SYNC_INTERVAL);
|
|
128
89
|
}
|
|
129
90
|
/**
|
|
130
|
-
* 检查 suspended 和 error
|
|
91
|
+
* 检查 suspended 和 error 状态的规则是否已恢复
|
|
131
92
|
*/
|
|
132
|
-
|
|
93
|
+
checkSuspendedAndErrorRules() {
|
|
133
94
|
return __awaiter(this, void 0, void 0, function* () {
|
|
134
|
-
if (this.clients.size === 0) {
|
|
135
|
-
return;
|
|
136
|
-
}
|
|
137
95
|
const now = Date.now();
|
|
138
96
|
// 1. 检查所有 error 状态的规则,如果超过恢复时间则自动恢复为 idle
|
|
139
97
|
this.ruleStates.forEach((data, ruleId) => {
|
|
@@ -186,49 +144,8 @@ class RulesStatusBroadcaster {
|
|
|
186
144
|
}
|
|
187
145
|
}
|
|
188
146
|
}
|
|
189
|
-
// 广播全量状态
|
|
190
|
-
this.broadcastAllRulesStatus();
|
|
191
147
|
});
|
|
192
148
|
}
|
|
193
|
-
/**
|
|
194
|
-
* 广播所有规则状态(全量同步)
|
|
195
|
-
*/
|
|
196
|
-
broadcastAllRulesStatus() {
|
|
197
|
-
if (this.clients.size === 0) {
|
|
198
|
-
return;
|
|
199
|
-
}
|
|
200
|
-
const allStatuses = Array.from(this.ruleStates.values());
|
|
201
|
-
const message = {
|
|
202
|
-
type: 'all_rules_status',
|
|
203
|
-
data: allStatuses,
|
|
204
|
-
timestamp: Date.now(),
|
|
205
|
-
};
|
|
206
|
-
this.broadcastMessage(message);
|
|
207
|
-
}
|
|
208
|
-
/**
|
|
209
|
-
* 添加客户端
|
|
210
|
-
*/
|
|
211
|
-
addClient(client) {
|
|
212
|
-
this.clients.add(client);
|
|
213
|
-
console.log(`[RulesStatusBroadcaster] 客户端已连接,当前客户端数: ${this.clients.size}`);
|
|
214
|
-
// 新客户端连接时,立即发送当前所有规则状态
|
|
215
|
-
const allStatuses = Array.from(this.ruleStates.values());
|
|
216
|
-
if (allStatuses.length > 0) {
|
|
217
|
-
const message = {
|
|
218
|
-
type: 'all_rules_status',
|
|
219
|
-
data: allStatuses,
|
|
220
|
-
timestamp: Date.now(),
|
|
221
|
-
};
|
|
222
|
-
client.sendMessage(message);
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
/**
|
|
226
|
-
* 移除客户端
|
|
227
|
-
*/
|
|
228
|
-
removeClient(client) {
|
|
229
|
-
this.clients.delete(client);
|
|
230
|
-
console.log(`[RulesStatusBroadcaster] 客户端已断开,当前客户端数: ${this.clients.size}`);
|
|
231
|
-
}
|
|
232
149
|
/**
|
|
233
150
|
* 清除规则的超时定时器
|
|
234
151
|
*/
|
|
@@ -250,17 +167,11 @@ class RulesStatusBroadcaster {
|
|
|
250
167
|
}
|
|
251
168
|
}
|
|
252
169
|
/**
|
|
253
|
-
*
|
|
170
|
+
* 更新规则状态
|
|
254
171
|
*/
|
|
255
172
|
updateRuleStatus(data) {
|
|
256
173
|
// 更新本地状态
|
|
257
174
|
this.ruleStates.set(data.ruleId, data);
|
|
258
|
-
// 广播单个规则状态更新
|
|
259
|
-
const message = {
|
|
260
|
-
type: 'rule_status',
|
|
261
|
-
data,
|
|
262
|
-
};
|
|
263
|
-
this.broadcastMessage(message);
|
|
264
175
|
}
|
|
265
176
|
/**
|
|
266
177
|
* 标记规则正在使用
|
|
@@ -270,7 +181,7 @@ class RulesStatusBroadcaster {
|
|
|
270
181
|
// 清除之前的超时定时器和 idle debounce
|
|
271
182
|
this.clearRuleTimeout(timeoutKey);
|
|
272
183
|
this.clearIdleDebounce(timeoutKey);
|
|
273
|
-
//
|
|
184
|
+
// 更新状态
|
|
274
185
|
this.updateRuleStatus({
|
|
275
186
|
ruleId,
|
|
276
187
|
status: 'in_use',
|
|
@@ -284,7 +195,7 @@ class RulesStatusBroadcaster {
|
|
|
284
195
|
this.ruleTimeouts.set(timeoutKey, timeout);
|
|
285
196
|
}
|
|
286
197
|
/**
|
|
287
|
-
* 标记规则空闲(带
|
|
198
|
+
* 标记规则空闲(带3秒 debounce,避免对话快速进入 in_use 时状态闪烁)
|
|
288
199
|
*/
|
|
289
200
|
markRuleIdle(routeId, ruleId) {
|
|
290
201
|
const timeoutKey = `${routeId}:${ruleId}`;
|
|
@@ -311,7 +222,7 @@ class RulesStatusBroadcaster {
|
|
|
311
222
|
// 清除超时定时器和 idle debounce,避免 error 状态被延迟的 idle 覆盖
|
|
312
223
|
this.clearRuleTimeout(timeoutKey);
|
|
313
224
|
this.clearIdleDebounce(timeoutKey);
|
|
314
|
-
//
|
|
225
|
+
// 更新状态
|
|
315
226
|
this.updateRuleStatus({
|
|
316
227
|
ruleId,
|
|
317
228
|
status: 'error',
|
|
@@ -328,7 +239,7 @@ class RulesStatusBroadcaster {
|
|
|
328
239
|
// 清除超时定时器和 idle debounce,避免 suspended 状态被延迟的 idle 覆盖
|
|
329
240
|
this.clearRuleTimeout(timeoutKey);
|
|
330
241
|
this.clearIdleDebounce(timeoutKey);
|
|
331
|
-
//
|
|
242
|
+
// 更新状态,同时存储 routeId、serviceId 和 contentType 用于恢复检查
|
|
332
243
|
this.updateRuleStatus({
|
|
333
244
|
ruleId,
|
|
334
245
|
status: 'suspended',
|
|
@@ -341,9 +252,9 @@ class RulesStatusBroadcaster {
|
|
|
341
252
|
});
|
|
342
253
|
}
|
|
343
254
|
/**
|
|
344
|
-
*
|
|
255
|
+
* 更新规则使用量
|
|
345
256
|
*/
|
|
346
|
-
|
|
257
|
+
updateRuleUsage(ruleId, totalTokensUsed, totalRequestsUsed) {
|
|
347
258
|
// 获取当前状态,保留其他字段
|
|
348
259
|
const currentStatus = this.ruleStates.get(ruleId);
|
|
349
260
|
this.updateRuleStatus({
|
|
@@ -375,23 +286,10 @@ class RulesStatusBroadcaster {
|
|
|
375
286
|
return activeRuleIds;
|
|
376
287
|
}
|
|
377
288
|
/**
|
|
378
|
-
*
|
|
289
|
+
* 获取所有规则的状态(用于 HTTP 轮询)
|
|
379
290
|
*/
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
this.clients.forEach((client) => {
|
|
383
|
-
try {
|
|
384
|
-
client.sendMessage(message);
|
|
385
|
-
}
|
|
386
|
-
catch (error) {
|
|
387
|
-
console.error('[RulesStatusBroadcaster] 发送消息失败:', error);
|
|
388
|
-
deadClients.push(client);
|
|
389
|
-
}
|
|
390
|
-
});
|
|
391
|
-
// 清理断开的客户端
|
|
392
|
-
deadClients.forEach((client) => {
|
|
393
|
-
this.removeClient(client);
|
|
394
|
-
});
|
|
291
|
+
getAllRuleStatuses() {
|
|
292
|
+
return Array.from(this.ruleStates.values());
|
|
395
293
|
}
|
|
396
294
|
/**
|
|
397
295
|
* 销毁广播器(清理定时器)
|
|
@@ -406,23 +304,8 @@ class RulesStatusBroadcaster {
|
|
|
406
304
|
this.idleDebounceTimeouts.forEach((timeout) => clearTimeout(timeout));
|
|
407
305
|
this.idleDebounceTimeouts.clear();
|
|
408
306
|
this.ruleStates.clear();
|
|
409
|
-
this.clients.clear();
|
|
410
307
|
}
|
|
411
308
|
}
|
|
412
309
|
exports.RulesStatusBroadcaster = RulesStatusBroadcaster;
|
|
413
310
|
// 全局单例
|
|
414
311
|
exports.rulesStatusBroadcaster = new RulesStatusBroadcaster();
|
|
415
|
-
/**
|
|
416
|
-
* 创建 WebSocket 服务器用于规则状态
|
|
417
|
-
*/
|
|
418
|
-
function createRulesStatusWSServer() {
|
|
419
|
-
const wss = new ws_1.WebSocketServer({ noServer: true });
|
|
420
|
-
wss.on('connection', (ws, req) => {
|
|
421
|
-
const wsHandler = new RulesStatusWS(ws, req);
|
|
422
|
-
exports.rulesStatusBroadcaster.addClient(wsHandler);
|
|
423
|
-
ws.on('close', () => {
|
|
424
|
-
exports.rulesStatusBroadcaster.removeClient(wsHandler);
|
|
425
|
-
});
|
|
426
|
-
});
|
|
427
|
-
return wss;
|
|
428
|
-
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.SSEEventCollectorTransform = exports.ChunkCollectorTransform = void 0;
|
|
4
4
|
const stream_1 = require("stream");
|
|
5
|
+
const string_decoder_1 = require("string_decoder");
|
|
5
6
|
/**
|
|
6
7
|
* 检测是否是客户端断开相关的错误(这些错误是正常的,不应记录为错误)
|
|
7
8
|
*/
|
|
@@ -32,6 +33,12 @@ class ChunkCollectorTransform extends stream_1.Transform {
|
|
|
32
33
|
writable: true,
|
|
33
34
|
value: false
|
|
34
35
|
});
|
|
36
|
+
Object.defineProperty(this, "stringDecoder", {
|
|
37
|
+
enumerable: true,
|
|
38
|
+
configurable: true,
|
|
39
|
+
writable: true,
|
|
40
|
+
value: new string_decoder_1.StringDecoder('utf8')
|
|
41
|
+
});
|
|
35
42
|
this.on('error', (err) => {
|
|
36
43
|
if (isClientDisconnectError(err)) {
|
|
37
44
|
console.warn('[ChunkCollectorTransform] Stream closed (client disconnected)');
|
|
@@ -53,7 +60,8 @@ class ChunkCollectorTransform extends stream_1.Transform {
|
|
|
53
60
|
this.chunks.push(JSON.stringify(chunk));
|
|
54
61
|
}
|
|
55
62
|
else {
|
|
56
|
-
|
|
63
|
+
// 使用 StringDecoder 正确处理多字节字符边界,避免中文乱码
|
|
64
|
+
this.chunks.push(this.stringDecoder.write(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)));
|
|
57
65
|
}
|
|
58
66
|
// 将chunk传递给下一个stream
|
|
59
67
|
this.push(chunk);
|
|
@@ -64,6 +72,20 @@ class ChunkCollectorTransform extends stream_1.Transform {
|
|
|
64
72
|
callback();
|
|
65
73
|
}
|
|
66
74
|
}
|
|
75
|
+
_flush(callback) {
|
|
76
|
+
try {
|
|
77
|
+
// 处理 StringDecoder 中剩余的字节
|
|
78
|
+
const remaining = this.stringDecoder.end();
|
|
79
|
+
if (remaining) {
|
|
80
|
+
this.chunks.push(remaining);
|
|
81
|
+
}
|
|
82
|
+
callback();
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
console.error('[ChunkCollectorTransform] Error in _flush:', error);
|
|
86
|
+
callback();
|
|
87
|
+
}
|
|
88
|
+
}
|
|
67
89
|
/**
|
|
68
90
|
* 获取收集的所有chunks
|
|
69
91
|
*/
|
|
@@ -113,6 +135,12 @@ class SSEEventCollectorTransform extends stream_1.Transform {
|
|
|
113
135
|
writable: true,
|
|
114
136
|
value: false
|
|
115
137
|
});
|
|
138
|
+
Object.defineProperty(this, "stringDecoder", {
|
|
139
|
+
enumerable: true,
|
|
140
|
+
configurable: true,
|
|
141
|
+
writable: true,
|
|
142
|
+
value: new string_decoder_1.StringDecoder('utf8')
|
|
143
|
+
});
|
|
116
144
|
this.on('error', (err) => {
|
|
117
145
|
if (isClientDisconnectError(err)) {
|
|
118
146
|
console.warn('[SSEEventCollectorTransform] Stream closed (client disconnected)');
|
|
@@ -161,8 +189,8 @@ class SSEEventCollectorTransform extends stream_1.Transform {
|
|
|
161
189
|
this.push(chunk);
|
|
162
190
|
}
|
|
163
191
|
else {
|
|
164
|
-
// Buffer/string 模式
|
|
165
|
-
this.buffer += chunk.
|
|
192
|
+
// Buffer/string 模式 - 使用 StringDecoder 正确处理多字节字符边界
|
|
193
|
+
this.buffer += this.stringDecoder.write(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
166
194
|
this.processBuffer();
|
|
167
195
|
// 将chunk传递给下一个stream
|
|
168
196
|
this.push(chunk);
|
|
@@ -176,6 +204,11 @@ class SSEEventCollectorTransform extends stream_1.Transform {
|
|
|
176
204
|
}
|
|
177
205
|
_flush(callback) {
|
|
178
206
|
try {
|
|
207
|
+
// 处理 StringDecoder 中剩余的字节
|
|
208
|
+
const remaining = this.stringDecoder.end();
|
|
209
|
+
if (remaining) {
|
|
210
|
+
this.buffer += remaining;
|
|
211
|
+
}
|
|
179
212
|
// 处理剩余的buffer
|
|
180
213
|
if (this.buffer.trim()) {
|
|
181
214
|
this.processBuffer();
|
|
@@ -281,8 +314,8 @@ class SSEEventCollectorTransform extends stream_1.Transform {
|
|
|
281
314
|
}
|
|
282
315
|
}
|
|
283
316
|
// 4. 直接在顶级的usage字段
|
|
284
|
-
if (data.input_tokens !== undefined || data.output_tokens !== undefined ||
|
|
285
|
-
data.prompt_tokens !== undefined || data.completion_tokens !== undefined) {
|
|
317
|
+
if ((data === null || data === void 0 ? void 0 : data.input_tokens) !== undefined || (data === null || data === void 0 ? void 0 : data.output_tokens) !== undefined ||
|
|
318
|
+
(data === null || data === void 0 ? void 0 : data.prompt_tokens) !== undefined || (data === null || data === void 0 ? void 0 : data.completion_tokens) !== undefined) {
|
|
286
319
|
return data;
|
|
287
320
|
}
|
|
288
321
|
}
|
|
@@ -35,6 +35,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.GeminiToClaudeEventTransform = exports.ResponsesToClaudeEventTransform = exports.ChatCompletionsToClaudeEventTransform = exports.GeminiToResponsesEventTransform = exports.ClaudeToResponsesEventTransform = exports.ChatCompletionsToResponsesEventTransform = exports.GeminiToOpenAIChatEventTransform = exports.ClaudeToOpenAIChatEventTransform = exports.OpenAIToClaudeEventTransform = exports.SSESerializerTransform = exports.SSEParserTransform = void 0;
|
|
37
37
|
const stream_1 = require("stream");
|
|
38
|
+
const string_decoder_1 = require("string_decoder");
|
|
38
39
|
const crypto = __importStar(require("crypto"));
|
|
39
40
|
/**
|
|
40
41
|
* 检测是否是客户端断开相关的错误(这些错误是正常的,不应记录为错误)
|
|
@@ -105,6 +106,12 @@ class SSEParserTransform extends stream_1.Transform {
|
|
|
105
106
|
writable: true,
|
|
106
107
|
value: false
|
|
107
108
|
});
|
|
109
|
+
Object.defineProperty(this, "stringDecoder", {
|
|
110
|
+
enumerable: true,
|
|
111
|
+
configurable: true,
|
|
112
|
+
writable: true,
|
|
113
|
+
value: new string_decoder_1.StringDecoder('utf8')
|
|
114
|
+
});
|
|
108
115
|
// 捕获流中的未处理错误,防止进程崩溃
|
|
109
116
|
this.on('error', (err) => {
|
|
110
117
|
if (isClientDisconnectError(err)) {
|
|
@@ -122,7 +129,8 @@ class SSEParserTransform extends stream_1.Transform {
|
|
|
122
129
|
return;
|
|
123
130
|
}
|
|
124
131
|
try {
|
|
125
|
-
|
|
132
|
+
// 使用 StringDecoder 正确处理多字节字符边界,避免中文乱码
|
|
133
|
+
this.buffer += this.stringDecoder.write(chunk);
|
|
126
134
|
const lines = this.buffer.split('\n');
|
|
127
135
|
this.buffer = lines.pop() || '';
|
|
128
136
|
for (const line of lines) {
|
|
@@ -138,6 +146,11 @@ class SSEParserTransform extends stream_1.Transform {
|
|
|
138
146
|
}
|
|
139
147
|
_flush(callback) {
|
|
140
148
|
try {
|
|
149
|
+
// 处理 StringDecoder 中剩余的字节
|
|
150
|
+
const remaining = this.stringDecoder.end();
|
|
151
|
+
if (remaining) {
|
|
152
|
+
this.buffer += remaining;
|
|
153
|
+
}
|
|
141
154
|
if (this.buffer.length > 0) {
|
|
142
155
|
this.processLine(this.buffer.replace(/\r$/, ''));
|
|
143
156
|
this.flushEvent();
|
|
@@ -883,6 +896,7 @@ class ClaudeToOpenAIChatEventTransform extends stream_1.Transform {
|
|
|
883
896
|
return this.usage;
|
|
884
897
|
}
|
|
885
898
|
_transform(event, _encoding, callback) {
|
|
899
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
886
900
|
if (this.errorEmitted) {
|
|
887
901
|
callback();
|
|
888
902
|
return;
|
|
@@ -973,9 +987,9 @@ class ClaudeToOpenAIChatEventTransform extends stream_1.Transform {
|
|
|
973
987
|
// 处理 usage 信息
|
|
974
988
|
if (data.usage) {
|
|
975
989
|
this.usage = {
|
|
976
|
-
prompt_tokens: data.usage.input_tokens || 0,
|
|
977
|
-
completion_tokens: data.usage.output_tokens || 0,
|
|
978
|
-
total_tokens: (data.usage.input_tokens || 0) + (data.usage.output_tokens || 0),
|
|
990
|
+
prompt_tokens: ((_a = data.usage) === null || _a === void 0 ? void 0 : _a.input_tokens) || 0,
|
|
991
|
+
completion_tokens: ((_b = data.usage) === null || _b === void 0 ? void 0 : _b.output_tokens) || 0,
|
|
992
|
+
total_tokens: (((_c = data.usage) === null || _c === void 0 ? void 0 : _c.input_tokens) || 0) + (((_d = data.usage) === null || _d === void 0 ? void 0 : _d.output_tokens) || 0),
|
|
979
993
|
};
|
|
980
994
|
}
|
|
981
995
|
// 不发送 delta 事件,只在最终 message_stop 时发送 finish_reason
|
|
@@ -984,9 +998,9 @@ class ClaudeToOpenAIChatEventTransform extends stream_1.Transform {
|
|
|
984
998
|
}
|
|
985
999
|
if (data === null || data === void 0 ? void 0 : data.usage) {
|
|
986
1000
|
this.usage = {
|
|
987
|
-
prompt_tokens: data.usage.input_tokens || 0,
|
|
988
|
-
completion_tokens: data.usage.output_tokens || 0,
|
|
989
|
-
total_tokens: (data.usage.input_tokens || 0) + (data.usage.output_tokens || 0),
|
|
1001
|
+
prompt_tokens: ((_e = data.usage) === null || _e === void 0 ? void 0 : _e.input_tokens) || 0,
|
|
1002
|
+
completion_tokens: ((_f = data.usage) === null || _f === void 0 ? void 0 : _f.output_tokens) || 0,
|
|
1003
|
+
total_tokens: (((_g = data.usage) === null || _g === void 0 ? void 0 : _g.input_tokens) || 0) + (((_h = data.usage) === null || _h === void 0 ? void 0 : _h.output_tokens) || 0),
|
|
990
1004
|
};
|
|
991
1005
|
}
|
|
992
1006
|
callback();
|
|
@@ -1509,6 +1523,7 @@ class ChatCompletionsToResponsesEventTransform extends stream_1.Transform {
|
|
|
1509
1523
|
};
|
|
1510
1524
|
}
|
|
1511
1525
|
buildFinalResponse(status) {
|
|
1526
|
+
var _a, _b, _c;
|
|
1512
1527
|
const output = [];
|
|
1513
1528
|
if (this.messageOutputAdded) {
|
|
1514
1529
|
output.push(this.buildMessageOutputItem(status === 'completed' ? 'completed' : 'incomplete'));
|
|
@@ -1533,9 +1548,9 @@ class ChatCompletionsToResponsesEventTransform extends stream_1.Transform {
|
|
|
1533
1548
|
};
|
|
1534
1549
|
if (this.usage) {
|
|
1535
1550
|
response.usage = {
|
|
1536
|
-
input_tokens: this.usage.input_tokens,
|
|
1537
|
-
output_tokens: this.usage.output_tokens,
|
|
1538
|
-
total_tokens: this.usage.total_tokens,
|
|
1551
|
+
input_tokens: (_a = this.usage) === null || _a === void 0 ? void 0 : _a.input_tokens,
|
|
1552
|
+
output_tokens: (_b = this.usage) === null || _b === void 0 ? void 0 : _b.output_tokens,
|
|
1553
|
+
total_tokens: (_c = this.usage) === null || _c === void 0 ? void 0 : _c.total_tokens,
|
|
1539
1554
|
};
|
|
1540
1555
|
}
|
|
1541
1556
|
if (status === 'incomplete') {
|
|
@@ -1730,6 +1745,7 @@ class ChatCompletionsToResponsesEventTransform extends stream_1.Transform {
|
|
|
1730
1745
|
}
|
|
1731
1746
|
}
|
|
1732
1747
|
finalize() {
|
|
1748
|
+
var _a, _b, _c;
|
|
1733
1749
|
if (this.finalized)
|
|
1734
1750
|
return;
|
|
1735
1751
|
// 如果没有任何输出,也需要确保有一个空的 message 输出项
|
|
@@ -1817,9 +1833,9 @@ class ChatCompletionsToResponsesEventTransform extends stream_1.Transform {
|
|
|
1817
1833
|
// 额外发送 usage 事件,兼容已有 usage 提取逻辑
|
|
1818
1834
|
if (this.usage) {
|
|
1819
1835
|
this.pushEvent('response.usage', {
|
|
1820
|
-
input_tokens: this.usage.input_tokens,
|
|
1821
|
-
output_tokens: this.usage.output_tokens,
|
|
1822
|
-
total_tokens: this.usage.total_tokens,
|
|
1836
|
+
input_tokens: (_a = this.usage) === null || _a === void 0 ? void 0 : _a.input_tokens,
|
|
1837
|
+
output_tokens: (_b = this.usage) === null || _b === void 0 ? void 0 : _b.output_tokens,
|
|
1838
|
+
total_tokens: (_c = this.usage) === null || _c === void 0 ? void 0 : _c.total_tokens,
|
|
1823
1839
|
});
|
|
1824
1840
|
}
|
|
1825
1841
|
this.finalized = true;
|
|
@@ -1927,7 +1943,7 @@ class ClaudeToResponsesEventTransform extends stream_1.Transform {
|
|
|
1927
1943
|
return this.usage;
|
|
1928
1944
|
}
|
|
1929
1945
|
_transform(event, _encoding, callback) {
|
|
1930
|
-
var _a, _b;
|
|
1946
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
1931
1947
|
if (this.errorEmitted) {
|
|
1932
1948
|
callback();
|
|
1933
1949
|
return;
|
|
@@ -2068,9 +2084,9 @@ class ClaudeToResponsesEventTransform extends stream_1.Transform {
|
|
|
2068
2084
|
// 处理 usage
|
|
2069
2085
|
if (data.usage) {
|
|
2070
2086
|
this.usage = {
|
|
2071
|
-
input_tokens: data.usage.input_tokens || 0,
|
|
2072
|
-
output_tokens: data.usage.output_tokens || 0,
|
|
2073
|
-
total_tokens: (data.usage.input_tokens || 0) + (data.usage.output_tokens || 0),
|
|
2087
|
+
input_tokens: ((_c = data.usage) === null || _c === void 0 ? void 0 : _c.input_tokens) || 0,
|
|
2088
|
+
output_tokens: ((_d = data.usage) === null || _d === void 0 ? void 0 : _d.output_tokens) || 0,
|
|
2089
|
+
total_tokens: (((_e = data.usage) === null || _e === void 0 ? void 0 : _e.input_tokens) || 0) + (((_f = data.usage) === null || _f === void 0 ? void 0 : _f.output_tokens) || 0),
|
|
2074
2090
|
};
|
|
2075
2091
|
}
|
|
2076
2092
|
callback();
|
|
@@ -2085,9 +2101,9 @@ class ClaudeToResponsesEventTransform extends stream_1.Transform {
|
|
|
2085
2101
|
// 处理 usage 字段(在顶层)
|
|
2086
2102
|
if (data === null || data === void 0 ? void 0 : data.usage) {
|
|
2087
2103
|
this.usage = {
|
|
2088
|
-
input_tokens: data.usage.input_tokens || 0,
|
|
2089
|
-
output_tokens: data.usage.output_tokens || 0,
|
|
2090
|
-
total_tokens: (data.usage.input_tokens || 0) + (data.usage.output_tokens || 0),
|
|
2104
|
+
input_tokens: ((_g = data.usage) === null || _g === void 0 ? void 0 : _g.input_tokens) || 0,
|
|
2105
|
+
output_tokens: ((_h = data.usage) === null || _h === void 0 ? void 0 : _h.output_tokens) || 0,
|
|
2106
|
+
total_tokens: (((_j = data.usage) === null || _j === void 0 ? void 0 : _j.input_tokens) || 0) + (((_k = data.usage) === null || _k === void 0 ? void 0 : _k.output_tokens) || 0),
|
|
2091
2107
|
};
|
|
2092
2108
|
}
|
|
2093
2109
|
callback();
|
|
@@ -2132,6 +2148,7 @@ class ClaudeToResponsesEventTransform extends stream_1.Transform {
|
|
|
2132
2148
|
}
|
|
2133
2149
|
}
|
|
2134
2150
|
finalize() {
|
|
2151
|
+
var _a, _b, _c;
|
|
2135
2152
|
if (this.finalized)
|
|
2136
2153
|
return;
|
|
2137
2154
|
if (!this.responseCreated) {
|
|
@@ -2162,9 +2179,9 @@ class ClaudeToResponsesEventTransform extends stream_1.Transform {
|
|
|
2162
2179
|
// 发送 usage(如果有)
|
|
2163
2180
|
if (this.usage) {
|
|
2164
2181
|
this.pushEvent('response.usage', {
|
|
2165
|
-
input_tokens: this.usage.input_tokens,
|
|
2166
|
-
output_tokens: this.usage.output_tokens,
|
|
2167
|
-
total_tokens: this.usage.total_tokens,
|
|
2182
|
+
input_tokens: (_a = this.usage) === null || _a === void 0 ? void 0 : _a.input_tokens,
|
|
2183
|
+
output_tokens: (_b = this.usage) === null || _b === void 0 ? void 0 : _b.output_tokens,
|
|
2184
|
+
total_tokens: (_c = this.usage) === null || _c === void 0 ? void 0 : _c.total_tokens,
|
|
2168
2185
|
});
|
|
2169
2186
|
}
|
|
2170
2187
|
this.finalized = true;
|
|
@@ -2355,6 +2372,7 @@ class GeminiToResponsesEventTransform extends stream_1.Transform {
|
|
|
2355
2372
|
}
|
|
2356
2373
|
}
|
|
2357
2374
|
finalize() {
|
|
2375
|
+
var _a, _b, _c;
|
|
2358
2376
|
if (this.finalized)
|
|
2359
2377
|
return;
|
|
2360
2378
|
// 发送 response.created 和 response.in_progress(如果还没有)
|
|
@@ -2376,9 +2394,9 @@ class GeminiToResponsesEventTransform extends stream_1.Transform {
|
|
|
2376
2394
|
// 发送 usage(如果有)
|
|
2377
2395
|
if (this.usage) {
|
|
2378
2396
|
this.pushEvent('response.usage', {
|
|
2379
|
-
input_tokens: this.usage.input_tokens,
|
|
2380
|
-
output_tokens: this.usage.output_tokens,
|
|
2381
|
-
total_tokens: this.usage.total_tokens,
|
|
2397
|
+
input_tokens: (_a = this.usage) === null || _a === void 0 ? void 0 : _a.input_tokens,
|
|
2398
|
+
output_tokens: (_b = this.usage) === null || _b === void 0 ? void 0 : _b.output_tokens,
|
|
2399
|
+
total_tokens: (_c = this.usage) === null || _c === void 0 ? void 0 : _c.total_tokens,
|
|
2382
2400
|
});
|
|
2383
2401
|
}
|
|
2384
2402
|
this.finalized = true;
|
|
@@ -2951,9 +2969,9 @@ class ResponsesToClaudeEventTransform extends stream_1.Transform {
|
|
|
2951
2969
|
}
|
|
2952
2970
|
if (eventType === 'response.usage' && data) {
|
|
2953
2971
|
this.usage = {
|
|
2954
|
-
input_tokens: data.input_tokens || 0,
|
|
2955
|
-
output_tokens: data.output_tokens || 0,
|
|
2956
|
-
cache_read_input_tokens: 0,
|
|
2972
|
+
input_tokens: (data === null || data === void 0 ? void 0 : data.input_tokens) || 0,
|
|
2973
|
+
output_tokens: (data === null || data === void 0 ? void 0 : data.output_tokens) || 0,
|
|
2974
|
+
cache_read_input_tokens: (data === null || data === void 0 ? void 0 : data.cache_read_input_tokens) || 0,
|
|
2957
2975
|
};
|
|
2958
2976
|
}
|
|
2959
2977
|
if (eventType === 'response.completed' || eventType === 'response.failed' || eventType === 'response.incomplete') {
|
|
@@ -291,25 +291,24 @@ const extractTokenUsageFromOpenAIUsage = (usage) => {
|
|
|
291
291
|
return undefined;
|
|
292
292
|
}
|
|
293
293
|
return {
|
|
294
|
-
inputTokens: usage.input_tokens,
|
|
295
|
-
outputTokens: usage.output_tokens || usage.completion_tokens,
|
|
296
|
-
totalTokens: usage.total_tokens,
|
|
297
|
-
cacheReadInputTokens: usage.cached_tokens,
|
|
294
|
+
inputTokens: (usage === null || usage === void 0 ? void 0 : usage.input_tokens) || 0,
|
|
295
|
+
outputTokens: (usage === null || usage === void 0 ? void 0 : usage.output_tokens) || (usage === null || usage === void 0 ? void 0 : usage.completion_tokens) || 0,
|
|
296
|
+
totalTokens: (usage === null || usage === void 0 ? void 0 : usage.total_tokens) || 0,
|
|
297
|
+
cacheReadInputTokens: (usage === null || usage === void 0 ? void 0 : usage.cached_tokens) || 0,
|
|
298
298
|
};
|
|
299
299
|
};
|
|
300
300
|
exports.extractTokenUsageFromOpenAIUsage = extractTokenUsageFromOpenAIUsage;
|
|
301
301
|
const extractTokenUsageFromClaudeUsage = (usage) => {
|
|
302
|
-
var _a, _b;
|
|
303
302
|
if (!usage) {
|
|
304
303
|
return undefined;
|
|
305
304
|
}
|
|
306
305
|
return {
|
|
307
|
-
inputTokens: (
|
|
308
|
-
outputTokens: (
|
|
309
|
-
totalTokens: usage.input_tokens !== undefined && usage.output_tokens !== undefined
|
|
310
|
-
? usage.input_tokens + usage.output_tokens
|
|
306
|
+
inputTokens: (usage === null || usage === void 0 ? void 0 : usage.input_tokens) || 0,
|
|
307
|
+
outputTokens: (usage === null || usage === void 0 ? void 0 : usage.output_tokens) || 0,
|
|
308
|
+
totalTokens: (usage === null || usage === void 0 ? void 0 : usage.input_tokens) !== undefined && (usage === null || usage === void 0 ? void 0 : usage.output_tokens) !== undefined
|
|
309
|
+
? (usage === null || usage === void 0 ? void 0 : usage.input_tokens) + (usage === null || usage === void 0 ? void 0 : usage.output_tokens)
|
|
311
310
|
: undefined,
|
|
312
|
-
cacheReadInputTokens: usage.cache_read_input_tokens,
|
|
311
|
+
cacheReadInputTokens: (usage === null || usage === void 0 ? void 0 : usage.cache_read_input_tokens) || 0,
|
|
313
312
|
};
|
|
314
313
|
};
|
|
315
314
|
exports.extractTokenUsageFromClaudeUsage = extractTokenUsageFromClaudeUsage;
|
|
@@ -1393,6 +1392,7 @@ function transformResponseFromChatCompletionsToResponses(response) {
|
|
|
1393
1392
|
};
|
|
1394
1393
|
}
|
|
1395
1394
|
function transformResponseFromClaudeToResponses(response) {
|
|
1395
|
+
var _a, _b, _c, _d;
|
|
1396
1396
|
if (!response || typeof response !== 'object') {
|
|
1397
1397
|
return response;
|
|
1398
1398
|
}
|
|
@@ -1459,9 +1459,10 @@ function transformResponseFromClaudeToResponses(response) {
|
|
|
1459
1459
|
status,
|
|
1460
1460
|
incomplete_details: status === 'incomplete' ? { reason: 'max_tokens' } : undefined,
|
|
1461
1461
|
usage: response.usage ? {
|
|
1462
|
-
input_tokens: response.usage.input_tokens,
|
|
1463
|
-
output_tokens: response.usage.output_tokens,
|
|
1464
|
-
total_tokens: response.usage.total_tokens
|
|
1462
|
+
input_tokens: ((_a = response.usage) === null || _a === void 0 ? void 0 : _a.input_tokens) || 0,
|
|
1463
|
+
output_tokens: ((_b = response.usage) === null || _b === void 0 ? void 0 : _b.output_tokens) || 0,
|
|
1464
|
+
total_tokens: ((_c = response.usage) === null || _c === void 0 ? void 0 : _c.total_tokens) || 0,
|
|
1465
|
+
cache_read_input_tokens: ((_d = response.usage) === null || _d === void 0 ? void 0 : _d.cache_read_input_tokens) || 0
|
|
1465
1466
|
} : undefined
|
|
1466
1467
|
};
|
|
1467
1468
|
}
|
|
@@ -1638,7 +1639,7 @@ function transformResponseFromChatCompletionsToClaude(response) {
|
|
|
1638
1639
|
};
|
|
1639
1640
|
}
|
|
1640
1641
|
function transformResponseFromResponsesToClaude(response) {
|
|
1641
|
-
var _a;
|
|
1642
|
+
var _a, _b, _c, _d, _e;
|
|
1642
1643
|
if (!response || typeof response !== 'object') {
|
|
1643
1644
|
return response;
|
|
1644
1645
|
}
|
|
@@ -1672,14 +1673,15 @@ function transformResponseFromResponsesToClaude(response) {
|
|
|
1672
1673
|
}
|
|
1673
1674
|
// 转换 usage
|
|
1674
1675
|
const usage = response.usage ? {
|
|
1675
|
-
input_tokens: response.usage.input_tokens,
|
|
1676
|
-
output_tokens: response.usage.output_tokens,
|
|
1677
|
-
total_tokens: response.usage.total_tokens,
|
|
1676
|
+
input_tokens: ((_a = response.usage) === null || _a === void 0 ? void 0 : _a.input_tokens) || 0,
|
|
1677
|
+
output_tokens: ((_b = response.usage) === null || _b === void 0 ? void 0 : _b.output_tokens) || 0,
|
|
1678
|
+
total_tokens: ((_c = response.usage) === null || _c === void 0 ? void 0 : _c.total_tokens) || 0,
|
|
1679
|
+
cache_read_input_tokens: ((_d = response.usage) === null || _d === void 0 ? void 0 : _d.cache_read_input_tokens) || 0,
|
|
1678
1680
|
} : undefined;
|
|
1679
1681
|
// 转换 stop_reason
|
|
1680
1682
|
let stop_reason = 'end_turn';
|
|
1681
1683
|
if (response.status === 'incomplete') {
|
|
1682
|
-
stop_reason = ((
|
|
1684
|
+
stop_reason = ((_e = response.incomplete_details) === null || _e === void 0 ? void 0 : _e.reason) === 'max_tokens' ? 'max_tokens' : 'end_turn';
|
|
1683
1685
|
}
|
|
1684
1686
|
return {
|
|
1685
1687
|
id: response.id,
|
|
@@ -56,12 +56,13 @@ const getLatestVersion = () => {
|
|
|
56
56
|
}
|
|
57
57
|
};
|
|
58
58
|
const req = https_1.default.request(options, (res) => {
|
|
59
|
-
|
|
59
|
+
const chunks = [];
|
|
60
60
|
res.on('data', (chunk) => {
|
|
61
|
-
|
|
61
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
62
62
|
});
|
|
63
63
|
res.on('end', () => {
|
|
64
64
|
try {
|
|
65
|
+
const data = Buffer.concat(chunks).toString('utf8');
|
|
65
66
|
const packageInfo = JSON.parse(data);
|
|
66
67
|
resolve(packageInfo['dist-tags'].latest);
|
|
67
68
|
}
|