@userdaoo/iflow-api-bridge 0.1.3 → 0.1.4
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/cli.js +0 -0
- package/dist/openai/transformer.d.ts +1 -5
- package/dist/openai/transformer.d.ts.map +1 -1
- package/dist/openai/transformer.js +26 -15
- package/dist/openai/transformer.js.map +1 -1
- package/dist/server.d.ts +0 -24
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +7 -44
- package/dist/server.js.map +1 -1
- package/package.json +1 -1
- package/src/openai/transformer.ts +28 -16
- package/src/server.ts +8 -44
package/dist/cli.js
CHANGED
|
File without changes
|
|
@@ -7,7 +7,7 @@ export declare function getTimestamp(): number;
|
|
|
7
7
|
export declare function messagesToIFlowPrompt(messages: ChatCompletionMessage[]): string;
|
|
8
8
|
/**
|
|
9
9
|
* 提取 System 消息和 User 消息
|
|
10
|
-
* 兼容 opencode
|
|
10
|
+
* 兼容 opencode 的各种消息格式(包括 plan 模式)
|
|
11
11
|
*/
|
|
12
12
|
export declare function extractMessages(messages: ChatCompletionMessage[]): {
|
|
13
13
|
systemMessage: string | undefined;
|
|
@@ -19,10 +19,6 @@ export declare function estimateTokens(text: string): number;
|
|
|
19
19
|
export declare function calculateUsage(prompt: string, completion: string): UsageInfo;
|
|
20
20
|
export declare function formatSSE(data: unknown): string;
|
|
21
21
|
export declare const SSE_DONE = "data: [DONE]\n\n";
|
|
22
|
-
/**
|
|
23
|
-
* iFlow 支持的模型列表
|
|
24
|
-
* 基于用户实际的 iFlow CLI 配置
|
|
25
|
-
*/
|
|
26
22
|
export declare const AVAILABLE_MODELS: {
|
|
27
23
|
id: string;
|
|
28
24
|
name: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transformer.d.ts","sourceRoot":"","sources":["../../src/openai/transformer.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EACV,qBAAqB,EACrB,sBAAsB,EACtB,4BAA4B,EAG5B,SAAS,EAEV,MAAM,YAAY,CAAC;AAEpB,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AAED,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,qBAAqB,EAAE,GAAG,MAAM,CAO/E;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,qBAAqB,EAAE,GAAG;IAClE,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,WAAW,EAAE,MAAM,CAAC;CACrB,
|
|
1
|
+
{"version":3,"file":"transformer.d.ts","sourceRoot":"","sources":["../../src/openai/transformer.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EACV,qBAAqB,EACrB,sBAAsB,EACtB,4BAA4B,EAG5B,SAAS,EAEV,MAAM,YAAY,CAAC;AAEpB,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AAED,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,qBAAqB,EAAE,GAAG,MAAM,CAO/E;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,qBAAqB,EAAE,GAAG;IAClE,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,WAAW,EAAE,MAAM,CAAC;CACrB,CAqDA;AAED,wBAAgB,iBAAiB,CAC/B,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,YAAY,GAAE,MAAM,GAAG,QAAQ,GAAG,IAAW,GAC5C,4BAA4B,CAc9B;AAED,wBAAgB,wBAAwB,CACtC,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,SAAS,EAChB,YAAY,GAAE,MAAM,GAAG,QAAiB,GACvC,sBAAsB,CAkBxB;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,SAAS,CAS5E;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAE/C;AAED,eAAO,MAAM,QAAQ,qBAAqB,CAAC;AAE3C,eAAO,MAAM,gBAAgB;;;GAU5B,CAAC;AAEF,wBAAgB,eAAe,IAAI,MAAM,CAExC"}
|
|
@@ -30,42 +30,57 @@ function messagesToIFlowPrompt(messages) {
|
|
|
30
30
|
}
|
|
31
31
|
/**
|
|
32
32
|
* 提取 System 消息和 User 消息
|
|
33
|
-
* 兼容 opencode
|
|
33
|
+
* 兼容 opencode 的各种消息格式(包括 plan 模式)
|
|
34
34
|
*/
|
|
35
35
|
function extractMessages(messages) {
|
|
36
|
+
console.log('[extractMessages] 原始消息:', JSON.stringify(messages.map(m => ({ role: m.role, contentLength: typeof m.content === 'string' ? m.content.length : 0 }))));
|
|
36
37
|
let systemMessage;
|
|
37
38
|
let userMessage = '';
|
|
38
|
-
//
|
|
39
|
+
// 第一步:查找 system 消息
|
|
39
40
|
for (const msg of messages) {
|
|
40
41
|
if (typeof msg.content !== 'string')
|
|
41
42
|
continue;
|
|
42
43
|
if (msg.role === 'system') {
|
|
43
44
|
systemMessage = msg.content;
|
|
44
45
|
}
|
|
45
|
-
|
|
46
|
+
}
|
|
47
|
+
// 第二步:查找有内容的 user 消息(plan 模式下 user 可能是空的)
|
|
48
|
+
for (const msg of messages) {
|
|
49
|
+
if (typeof msg.content !== 'string')
|
|
50
|
+
continue;
|
|
51
|
+
if (msg.role === 'user' && msg.content.trim()) {
|
|
46
52
|
userMessage = msg.content;
|
|
53
|
+
break;
|
|
47
54
|
}
|
|
48
55
|
}
|
|
49
|
-
//
|
|
56
|
+
// 第三步:如果没有找到有内容的 user 消息,尝试其他非 system 角色
|
|
50
57
|
if (!userMessage) {
|
|
51
58
|
for (const msg of messages) {
|
|
52
59
|
if (typeof msg.content !== 'string')
|
|
53
60
|
continue;
|
|
54
|
-
|
|
61
|
+
const role = msg.role || 'unknown';
|
|
62
|
+
// 任何非 system 角色且有内容的都可以作为 user 消息
|
|
63
|
+
if (role !== 'system' && msg.content.trim()) {
|
|
55
64
|
userMessage = msg.content;
|
|
65
|
+
console.log(`[extractMessages] 使用 role="${role}" 作为 user 消息`);
|
|
56
66
|
break;
|
|
57
67
|
}
|
|
58
68
|
}
|
|
59
69
|
}
|
|
60
|
-
//
|
|
70
|
+
// 第四步:如果还是没有,使用最后一条非 system 消息(即使 role 是 user 但内容为空的情况)
|
|
61
71
|
if (!userMessage) {
|
|
62
|
-
const
|
|
63
|
-
.filter(msg => msg.role !== 'system' && typeof msg.content === 'string')
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
72
|
+
const nonSystemMessages = messages
|
|
73
|
+
.filter(msg => msg.role !== 'system' && typeof msg.content === 'string');
|
|
74
|
+
if (nonSystemMessages.length > 0) {
|
|
75
|
+
// 使用最后一条非 system 消息
|
|
76
|
+
const lastMsg = nonSystemMessages[nonSystemMessages.length - 1];
|
|
77
|
+
if (lastMsg.content) {
|
|
78
|
+
userMessage = lastMsg.content;
|
|
79
|
+
console.log(`[extractMessages] 使用最后一条非 system 消息, role="${lastMsg.role}"`);
|
|
80
|
+
}
|
|
67
81
|
}
|
|
68
82
|
}
|
|
83
|
+
console.log(`[extractMessages] 结果: system=${systemMessage ? '有' : '无'}, user=${userMessage ? '有' : '无'}, user长度=${userMessage.length}`);
|
|
69
84
|
return { systemMessage, userMessage };
|
|
70
85
|
}
|
|
71
86
|
function createStreamChunk(id, model, content, finishReason = null) {
|
|
@@ -116,10 +131,6 @@ function formatSSE(data) {
|
|
|
116
131
|
return `data: ${JSON.stringify(data)}\n\n`;
|
|
117
132
|
}
|
|
118
133
|
exports.SSE_DONE = 'data: [DONE]\n\n';
|
|
119
|
-
/**
|
|
120
|
-
* iFlow 支持的模型列表
|
|
121
|
-
* 基于用户实际的 iFlow CLI 配置
|
|
122
|
-
*/
|
|
123
134
|
exports.AVAILABLE_MODELS = [
|
|
124
135
|
{ id: 'glm-4.7', name: 'GLM-4.7 (Default)' },
|
|
125
136
|
{ id: 'iflow-rome-30ba3b', name: 'iFlow-ROME-30BA3B (Preview)' },
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transformer.js","sourceRoot":"","sources":["../../src/openai/transformer.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAYH,gCAEC;AAED,oCAEC;AAED,sDAOC;AAMD,
|
|
1
|
+
{"version":3,"file":"transformer.js","sourceRoot":"","sources":["../../src/openai/transformer.ts"],"names":[],"mappings":"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"}
|
package/dist/server.d.ts
CHANGED
|
@@ -13,37 +13,13 @@ export declare class IFlowAPIServer {
|
|
|
13
13
|
private adapter;
|
|
14
14
|
private options;
|
|
15
15
|
constructor(options: ServerOptions);
|
|
16
|
-
/**
|
|
17
|
-
* 设置中间件
|
|
18
|
-
*/
|
|
19
16
|
private setupMiddleware;
|
|
20
|
-
/**
|
|
21
|
-
* 设置路由
|
|
22
|
-
*/
|
|
23
17
|
private setupRoutes;
|
|
24
|
-
/**
|
|
25
|
-
* 处理流式响应
|
|
26
|
-
*/
|
|
27
18
|
private handleStreamResponse;
|
|
28
|
-
/**
|
|
29
|
-
* 处理非流式响应
|
|
30
|
-
*/
|
|
31
19
|
private handleNonStreamResponse;
|
|
32
|
-
/**
|
|
33
|
-
* 设置错误处理
|
|
34
|
-
*/
|
|
35
20
|
private setupErrorHandler;
|
|
36
|
-
/**
|
|
37
|
-
* 创建错误响应
|
|
38
|
-
*/
|
|
39
21
|
private createError;
|
|
40
|
-
/**
|
|
41
|
-
* 启动服务器
|
|
42
|
-
*/
|
|
43
22
|
start(): Promise<void>;
|
|
44
|
-
/**
|
|
45
|
-
* 停止服务器
|
|
46
|
-
*/
|
|
47
23
|
stop(): Promise<void>;
|
|
48
24
|
}
|
|
49
25
|
//# sourceMappingURL=server.d.ts.map
|
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;GAEG;AAyBH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,GAAG,CAAsB;IACjC,OAAO,CAAC,OAAO,CAAe;IAC9B,OAAO,CAAC,OAAO,CAAgB;gBAEnB,OAAO,EAAE,aAAa;IAalC
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;GAEG;AAyBH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,GAAG,CAAsB;IACjC,OAAO,CAAC,OAAO,CAAe;IAC9B,OAAO,CAAC,OAAO,CAAgB;gBAEnB,OAAO,EAAE,aAAa;IAalC,OAAO,CAAC,eAAe;IAgCvB,OAAO,CAAC,WAAW;YA0EL,oBAAoB;YA+EpB,uBAAuB;IAyCrC,OAAO,CAAC,iBAAiB;IAOzB,OAAO,CAAC,WAAW;IAUb,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IA8BtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAG5B"}
|
package/dist/server.js
CHANGED
|
@@ -26,13 +26,8 @@ class IFlowAPIServer {
|
|
|
26
26
|
this.setupRoutes();
|
|
27
27
|
this.setupErrorHandler();
|
|
28
28
|
}
|
|
29
|
-
/**
|
|
30
|
-
* 设置中间件
|
|
31
|
-
*/
|
|
32
29
|
setupMiddleware() {
|
|
33
|
-
// JSON 解析
|
|
34
30
|
this.app.use(express_1.default.json({ limit: '10mb' }));
|
|
35
|
-
// CORS
|
|
36
31
|
if (this.options.cors !== false) {
|
|
37
32
|
this.app.use((0, cors_1.default)({
|
|
38
33
|
origin: '*',
|
|
@@ -40,10 +35,8 @@ class IFlowAPIServer {
|
|
|
40
35
|
allowedHeaders: ['Content-Type', 'Authorization'],
|
|
41
36
|
}));
|
|
42
37
|
}
|
|
43
|
-
// API Key 验证(如果配置了)
|
|
44
38
|
if (this.options.apiKey) {
|
|
45
39
|
this.app.use((req, res, next) => {
|
|
46
|
-
// 健康检查端点不需要认证
|
|
47
40
|
if (req.path === '/health') {
|
|
48
41
|
return next();
|
|
49
42
|
}
|
|
@@ -59,11 +52,7 @@ class IFlowAPIServer {
|
|
|
59
52
|
});
|
|
60
53
|
}
|
|
61
54
|
}
|
|
62
|
-
/**
|
|
63
|
-
* 设置路由
|
|
64
|
-
*/
|
|
65
55
|
setupRoutes() {
|
|
66
|
-
// 健康检查
|
|
67
56
|
this.app.get('/health', (req, res) => {
|
|
68
57
|
const stats = this.adapter.getStats();
|
|
69
58
|
res.json({
|
|
@@ -74,7 +63,6 @@ class IFlowAPIServer {
|
|
|
74
63
|
timestamp: new Date().toISOString(),
|
|
75
64
|
});
|
|
76
65
|
});
|
|
77
|
-
// 模型列表
|
|
78
66
|
this.app.get('/v1/models', async (req, res) => {
|
|
79
67
|
const response = {
|
|
80
68
|
object: 'list',
|
|
@@ -87,12 +75,10 @@ class IFlowAPIServer {
|
|
|
87
75
|
};
|
|
88
76
|
res.json(response);
|
|
89
77
|
});
|
|
90
|
-
// 聊天完成
|
|
91
78
|
this.app.post('/v1/chat/completions', async (req, res) => {
|
|
92
79
|
console.log(`[${new Date().toISOString()}] 收到聊天请求`);
|
|
93
80
|
try {
|
|
94
81
|
const body = req.body;
|
|
95
|
-
// 验证请求
|
|
96
82
|
if (!body.messages || !Array.isArray(body.messages) || body.messages.length === 0) {
|
|
97
83
|
console.log('请求验证失败: messages 为空');
|
|
98
84
|
return res.status(400).json(this.createError('messages 不能为空', 'invalid_request_error'));
|
|
@@ -100,15 +86,19 @@ class IFlowAPIServer {
|
|
|
100
86
|
const isStream = body.stream === true;
|
|
101
87
|
const model = body.model || (0, transformer_js_1.getDefaultModel)();
|
|
102
88
|
// 提取 system 和 user 消息
|
|
103
|
-
|
|
89
|
+
let { systemMessage, userMessage } = (0, transformer_js_1.extractMessages)(body.messages);
|
|
90
|
+
// 关键修复:如果 user 为空但有 system,使用 system 作为 user 消息(plan 模式兼容)
|
|
91
|
+
if (!userMessage && systemMessage) {
|
|
92
|
+
console.log('[Server] user 为空,使用 system 消息作为 user 消息');
|
|
93
|
+
userMessage = systemMessage;
|
|
94
|
+
systemMessage = undefined;
|
|
95
|
+
}
|
|
104
96
|
if (!userMessage) {
|
|
105
97
|
return res.status(400).json(this.createError('未找到 user 消息', 'invalid_request_error'));
|
|
106
98
|
}
|
|
107
99
|
// 生成或使用已有的 conversation ID
|
|
108
|
-
// opencode 可能在 header 中传递,或者我们需要生成一个
|
|
109
100
|
let conversationId = req.headers['x-conversation-id'];
|
|
110
101
|
if (!conversationId) {
|
|
111
|
-
// 从消息中生成一个稳定的 ID(基于 system + user 消息)
|
|
112
102
|
conversationId = `${Date.now()}-${Math.random().toString(36).substring(2, 10)}`;
|
|
113
103
|
}
|
|
114
104
|
console.log(`会话: ${conversationId}, 流式: ${isStream}, 模型: ${model}`);
|
|
@@ -126,21 +116,16 @@ class IFlowAPIServer {
|
|
|
126
116
|
}
|
|
127
117
|
});
|
|
128
118
|
}
|
|
129
|
-
/**
|
|
130
|
-
* 处理流式响应
|
|
131
|
-
*/
|
|
132
119
|
async handleStreamResponse(res, conversationId, systemMessage, userMessage, model) {
|
|
133
120
|
const id = (0, transformer_js_1.generateId)();
|
|
134
121
|
res.setHeader('Content-Type', 'text/event-stream');
|
|
135
122
|
res.setHeader('Cache-Control', 'no-cache');
|
|
136
123
|
res.setHeader('Connection', 'keep-alive');
|
|
137
|
-
// 设置 5 分钟超时
|
|
138
124
|
const timeout = setTimeout(() => {
|
|
139
125
|
res.write((0, transformer_js_1.formatSSE)(this.createError('请求超时', 'timeout_error')));
|
|
140
126
|
res.end();
|
|
141
127
|
}, 300000);
|
|
142
128
|
try {
|
|
143
|
-
// 发送开始标记(角色)
|
|
144
129
|
const startChunk = {
|
|
145
130
|
id,
|
|
146
131
|
object: 'chat.completion.chunk',
|
|
@@ -153,7 +138,6 @@ class IFlowAPIServer {
|
|
|
153
138
|
}],
|
|
154
139
|
};
|
|
155
140
|
res.write((0, transformer_js_1.formatSSE)(startChunk));
|
|
156
|
-
// 流式发送内容
|
|
157
141
|
let fullContent = '';
|
|
158
142
|
let isDone = false;
|
|
159
143
|
for await (const chunk of this.adapter.sendMessageStream(conversationId, systemMessage, userMessage)) {
|
|
@@ -168,7 +152,6 @@ class IFlowAPIServer {
|
|
|
168
152
|
}
|
|
169
153
|
break;
|
|
170
154
|
case 'tool_call':
|
|
171
|
-
// 工具调用信息可以记录日志,但不发送到客户端
|
|
172
155
|
console.log(`工具调用: ${chunk.toolName} - ${chunk.toolStatus}`);
|
|
173
156
|
break;
|
|
174
157
|
case 'done':
|
|
@@ -181,7 +164,6 @@ class IFlowAPIServer {
|
|
|
181
164
|
break;
|
|
182
165
|
}
|
|
183
166
|
}
|
|
184
|
-
// 发送结束标记
|
|
185
167
|
const endChunk = (0, transformer_js_1.createStreamChunk)(id, model, '', 'stop');
|
|
186
168
|
res.write((0, transformer_js_1.formatSSE)(endChunk));
|
|
187
169
|
res.write(transformer_js_1.SSE_DONE);
|
|
@@ -196,12 +178,8 @@ class IFlowAPIServer {
|
|
|
196
178
|
clearTimeout(timeout);
|
|
197
179
|
}
|
|
198
180
|
}
|
|
199
|
-
/**
|
|
200
|
-
* 处理非流式响应
|
|
201
|
-
*/
|
|
202
181
|
async handleNonStreamResponse(res, conversationId, systemMessage, userMessage, model) {
|
|
203
182
|
const id = (0, transformer_js_1.generateId)();
|
|
204
|
-
// 设置 5 分钟超时
|
|
205
183
|
const timeout = setTimeout(() => {
|
|
206
184
|
res.status(504).json(this.createError('请求超时', 'timeout_error'));
|
|
207
185
|
}, 300000);
|
|
@@ -216,7 +194,6 @@ class IFlowAPIServer {
|
|
|
216
194
|
clearTimeout(timeout);
|
|
217
195
|
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
218
196
|
console.error('处理请求错误:', errorMsg);
|
|
219
|
-
// 区分超时错误和其他错误
|
|
220
197
|
if (errorMsg.includes('超时') || errorMsg.includes('timeout')) {
|
|
221
198
|
res.status(504).json(this.createError(errorMsg, 'timeout_error', 'timeout'));
|
|
222
199
|
}
|
|
@@ -225,18 +202,12 @@ class IFlowAPIServer {
|
|
|
225
202
|
}
|
|
226
203
|
}
|
|
227
204
|
}
|
|
228
|
-
/**
|
|
229
|
-
* 设置错误处理
|
|
230
|
-
*/
|
|
231
205
|
setupErrorHandler() {
|
|
232
206
|
this.app.use((err, req, res, _next) => {
|
|
233
207
|
console.error('服务器错误:', err);
|
|
234
208
|
res.status(500).json(this.createError('服务器内部错误', 'internal_error'));
|
|
235
209
|
});
|
|
236
210
|
}
|
|
237
|
-
/**
|
|
238
|
-
* 创建错误响应
|
|
239
|
-
*/
|
|
240
211
|
createError(message, type, code = 'unknown_error') {
|
|
241
212
|
return {
|
|
242
213
|
error: {
|
|
@@ -246,15 +217,10 @@ class IFlowAPIServer {
|
|
|
246
217
|
},
|
|
247
218
|
};
|
|
248
219
|
}
|
|
249
|
-
/**
|
|
250
|
-
* 启动服务器
|
|
251
|
-
*/
|
|
252
220
|
async start() {
|
|
253
|
-
// 连接 iFlow
|
|
254
221
|
console.log('正在连接 iFlow...');
|
|
255
222
|
await this.adapter.connect();
|
|
256
223
|
console.log('iFlow 连接成功');
|
|
257
|
-
// 启动 HTTP 服务器
|
|
258
224
|
const host = this.options.host || '0.0.0.0';
|
|
259
225
|
const port = this.options.port;
|
|
260
226
|
return new Promise((resolve, reject) => {
|
|
@@ -278,9 +244,6 @@ class IFlowAPIServer {
|
|
|
278
244
|
});
|
|
279
245
|
});
|
|
280
246
|
}
|
|
281
|
-
/**
|
|
282
|
-
* 停止服务器
|
|
283
|
-
*/
|
|
284
247
|
async stop() {
|
|
285
248
|
await this.adapter.disconnect();
|
|
286
249
|
}
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":";AAAA;;GAEG;;;;;;AAEH,sDAAkF;AAClF,gDAAwB;AACxB,6CAA4C;AAQ5C,4DAWiC;AAUjC,MAAa,cAAc;IACjB,GAAG,CAAsB;IACzB,OAAO,CAAe;IACtB,OAAO,CAAgB;IAE/B,YAAY,OAAsB;QAChC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,GAAG,GAAG,IAAA,iBAAO,GAAE,CAAC;QACrB,IAAI,CAAC,OAAO,GAAG,IAAI,yBAAY,CAAC;YAC9B,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,gBAAgB,EAAE,EAAE;SACrB,CAAC,CAAC;QAEH,IAAI,CAAC,eAAe,EAAE,CAAC;QACvB,IAAI,CAAC,WAAW,EAAE,CAAC;QACnB,IAAI,CAAC,iBAAiB,EAAE,CAAC;IAC3B,CAAC;
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -31,47 +31,63 @@ export function messagesToIFlowPrompt(messages: ChatCompletionMessage[]): string
|
|
|
31
31
|
|
|
32
32
|
/**
|
|
33
33
|
* 提取 System 消息和 User 消息
|
|
34
|
-
* 兼容 opencode
|
|
34
|
+
* 兼容 opencode 的各种消息格式(包括 plan 模式)
|
|
35
35
|
*/
|
|
36
36
|
export function extractMessages(messages: ChatCompletionMessage[]): {
|
|
37
37
|
systemMessage: string | undefined;
|
|
38
38
|
userMessage: string;
|
|
39
39
|
} {
|
|
40
|
+
console.log('[extractMessages] 原始消息:', JSON.stringify(messages.map(m => ({ role: m.role, contentLength: typeof m.content === 'string' ? m.content.length : 0 }))));
|
|
41
|
+
|
|
40
42
|
let systemMessage: string | undefined;
|
|
41
43
|
let userMessage = '';
|
|
42
44
|
|
|
43
|
-
//
|
|
45
|
+
// 第一步:查找 system 消息
|
|
44
46
|
for (const msg of messages) {
|
|
45
47
|
if (typeof msg.content !== 'string') continue;
|
|
46
|
-
|
|
47
48
|
if (msg.role === 'system') {
|
|
48
49
|
systemMessage = msg.content;
|
|
49
|
-
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// 第二步:查找有内容的 user 消息(plan 模式下 user 可能是空的)
|
|
54
|
+
for (const msg of messages) {
|
|
55
|
+
if (typeof msg.content !== 'string') continue;
|
|
56
|
+
if (msg.role === 'user' && msg.content.trim()) {
|
|
50
57
|
userMessage = msg.content;
|
|
58
|
+
break;
|
|
51
59
|
}
|
|
52
60
|
}
|
|
53
61
|
|
|
54
|
-
//
|
|
62
|
+
// 第三步:如果没有找到有内容的 user 消息,尝试其他非 system 角色
|
|
55
63
|
if (!userMessage) {
|
|
56
64
|
for (const msg of messages) {
|
|
57
65
|
if (typeof msg.content !== 'string') continue;
|
|
58
|
-
|
|
66
|
+
const role = msg.role || 'unknown';
|
|
67
|
+
// 任何非 system 角色且有内容的都可以作为 user 消息
|
|
68
|
+
if (role !== 'system' && msg.content.trim()) {
|
|
59
69
|
userMessage = msg.content;
|
|
70
|
+
console.log(`[extractMessages] 使用 role="${role}" 作为 user 消息`);
|
|
60
71
|
break;
|
|
61
72
|
}
|
|
62
73
|
}
|
|
63
74
|
}
|
|
64
75
|
|
|
65
|
-
//
|
|
76
|
+
// 第四步:如果还是没有,使用最后一条非 system 消息(即使 role 是 user 但内容为空的情况)
|
|
66
77
|
if (!userMessage) {
|
|
67
|
-
const
|
|
68
|
-
.filter(msg => msg.role !== 'system' && typeof msg.content === 'string')
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
78
|
+
const nonSystemMessages = messages
|
|
79
|
+
.filter(msg => msg.role !== 'system' && typeof msg.content === 'string');
|
|
80
|
+
if (nonSystemMessages.length > 0) {
|
|
81
|
+
// 使用最后一条非 system 消息
|
|
82
|
+
const lastMsg = nonSystemMessages[nonSystemMessages.length - 1];
|
|
83
|
+
if (lastMsg.content) {
|
|
84
|
+
userMessage = lastMsg.content;
|
|
85
|
+
console.log(`[extractMessages] 使用最后一条非 system 消息, role="${lastMsg.role}"`);
|
|
86
|
+
}
|
|
72
87
|
}
|
|
73
88
|
}
|
|
74
89
|
|
|
90
|
+
console.log(`[extractMessages] 结果: system=${systemMessage ? '有' : '无'}, user=${userMessage ? '有' : '无'}, user长度=${userMessage.length}`);
|
|
75
91
|
return { systemMessage, userMessage };
|
|
76
92
|
}
|
|
77
93
|
|
|
@@ -143,10 +159,6 @@ export function formatSSE(data: unknown): string {
|
|
|
143
159
|
|
|
144
160
|
export const SSE_DONE = 'data: [DONE]\n\n';
|
|
145
161
|
|
|
146
|
-
/**
|
|
147
|
-
* iFlow 支持的模型列表
|
|
148
|
-
* 基于用户实际的 iFlow CLI 配置
|
|
149
|
-
*/
|
|
150
162
|
export const AVAILABLE_MODELS = [
|
|
151
163
|
{ id: 'glm-4.7', name: 'GLM-4.7 (Default)' },
|
|
152
164
|
{ id: 'iflow-rome-30ba3b', name: 'iFlow-ROME-30BA3B (Preview)' },
|
package/src/server.ts
CHANGED
|
@@ -51,14 +51,9 @@ export class IFlowAPIServer {
|
|
|
51
51
|
this.setupErrorHandler();
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
/**
|
|
55
|
-
* 设置中间件
|
|
56
|
-
*/
|
|
57
54
|
private setupMiddleware(): void {
|
|
58
|
-
// JSON 解析
|
|
59
55
|
this.app.use(express.json({ limit: '10mb' }));
|
|
60
56
|
|
|
61
|
-
// CORS
|
|
62
57
|
if (this.options.cors !== false) {
|
|
63
58
|
this.app.use(cors({
|
|
64
59
|
origin: '*',
|
|
@@ -67,10 +62,8 @@ export class IFlowAPIServer {
|
|
|
67
62
|
}));
|
|
68
63
|
}
|
|
69
64
|
|
|
70
|
-
// API Key 验证(如果配置了)
|
|
71
65
|
if (this.options.apiKey) {
|
|
72
66
|
this.app.use((req: Request, res: Response, next: NextFunction) => {
|
|
73
|
-
// 健康检查端点不需要认证
|
|
74
67
|
if (req.path === '/health') {
|
|
75
68
|
return next();
|
|
76
69
|
}
|
|
@@ -90,11 +83,7 @@ export class IFlowAPIServer {
|
|
|
90
83
|
}
|
|
91
84
|
}
|
|
92
85
|
|
|
93
|
-
/**
|
|
94
|
-
* 设置路由
|
|
95
|
-
*/
|
|
96
86
|
private setupRoutes(): void {
|
|
97
|
-
// 健康检查
|
|
98
87
|
this.app.get('/health', (req: Request, res: Response) => {
|
|
99
88
|
const stats = this.adapter.getStats();
|
|
100
89
|
res.json({
|
|
@@ -106,7 +95,6 @@ export class IFlowAPIServer {
|
|
|
106
95
|
});
|
|
107
96
|
});
|
|
108
97
|
|
|
109
|
-
// 模型列表
|
|
110
98
|
this.app.get('/v1/models', async (req: Request, res: Response) => {
|
|
111
99
|
const response: ModelsResponse = {
|
|
112
100
|
object: 'list',
|
|
@@ -120,14 +108,12 @@ export class IFlowAPIServer {
|
|
|
120
108
|
res.json(response);
|
|
121
109
|
});
|
|
122
110
|
|
|
123
|
-
// 聊天完成
|
|
124
111
|
this.app.post('/v1/chat/completions', async (req: Request, res: Response) => {
|
|
125
112
|
console.log(`[${new Date().toISOString()}] 收到聊天请求`);
|
|
126
113
|
|
|
127
114
|
try {
|
|
128
115
|
const body = req.body as ChatCompletionRequest;
|
|
129
116
|
|
|
130
|
-
// 验证请求
|
|
131
117
|
if (!body.messages || !Array.isArray(body.messages) || body.messages.length === 0) {
|
|
132
118
|
console.log('请求验证失败: messages 为空');
|
|
133
119
|
return res.status(400).json(this.createError('messages 不能为空', 'invalid_request_error'));
|
|
@@ -137,17 +123,22 @@ export class IFlowAPIServer {
|
|
|
137
123
|
const model = body.model || getDefaultModel();
|
|
138
124
|
|
|
139
125
|
// 提取 system 和 user 消息
|
|
140
|
-
|
|
126
|
+
let { systemMessage, userMessage } = extractMessages(body.messages);
|
|
127
|
+
|
|
128
|
+
// 关键修复:如果 user 为空但有 system,使用 system 作为 user 消息(plan 模式兼容)
|
|
129
|
+
if (!userMessage && systemMessage) {
|
|
130
|
+
console.log('[Server] user 为空,使用 system 消息作为 user 消息');
|
|
131
|
+
userMessage = systemMessage;
|
|
132
|
+
systemMessage = undefined;
|
|
133
|
+
}
|
|
141
134
|
|
|
142
135
|
if (!userMessage) {
|
|
143
136
|
return res.status(400).json(this.createError('未找到 user 消息', 'invalid_request_error'));
|
|
144
137
|
}
|
|
145
138
|
|
|
146
139
|
// 生成或使用已有的 conversation ID
|
|
147
|
-
// opencode 可能在 header 中传递,或者我们需要生成一个
|
|
148
140
|
let conversationId = req.headers['x-conversation-id'] as string | undefined;
|
|
149
141
|
if (!conversationId) {
|
|
150
|
-
// 从消息中生成一个稳定的 ID(基于 system + user 消息)
|
|
151
142
|
conversationId = `${Date.now()}-${Math.random().toString(36).substring(2, 10)}`;
|
|
152
143
|
}
|
|
153
144
|
|
|
@@ -166,9 +157,6 @@ export class IFlowAPIServer {
|
|
|
166
157
|
});
|
|
167
158
|
}
|
|
168
159
|
|
|
169
|
-
/**
|
|
170
|
-
* 处理流式响应
|
|
171
|
-
*/
|
|
172
160
|
private async handleStreamResponse(
|
|
173
161
|
res: Response,
|
|
174
162
|
conversationId: string,
|
|
@@ -182,14 +170,12 @@ export class IFlowAPIServer {
|
|
|
182
170
|
res.setHeader('Cache-Control', 'no-cache');
|
|
183
171
|
res.setHeader('Connection', 'keep-alive');
|
|
184
172
|
|
|
185
|
-
// 设置 5 分钟超时
|
|
186
173
|
const timeout = setTimeout(() => {
|
|
187
174
|
res.write(formatSSE(this.createError('请求超时', 'timeout_error')));
|
|
188
175
|
res.end();
|
|
189
176
|
}, 300000);
|
|
190
177
|
|
|
191
178
|
try {
|
|
192
|
-
// 发送开始标记(角色)
|
|
193
179
|
const startChunk: ChatCompletionStreamResponse = {
|
|
194
180
|
id,
|
|
195
181
|
object: 'chat.completion.chunk',
|
|
@@ -203,7 +189,6 @@ export class IFlowAPIServer {
|
|
|
203
189
|
};
|
|
204
190
|
res.write(formatSSE(startChunk));
|
|
205
191
|
|
|
206
|
-
// 流式发送内容
|
|
207
192
|
let fullContent = '';
|
|
208
193
|
let isDone = false;
|
|
209
194
|
for await (const chunk of this.adapter.sendMessageStream(conversationId, systemMessage, userMessage)) {
|
|
@@ -219,7 +204,6 @@ export class IFlowAPIServer {
|
|
|
219
204
|
break;
|
|
220
205
|
|
|
221
206
|
case 'tool_call':
|
|
222
|
-
// 工具调用信息可以记录日志,但不发送到客户端
|
|
223
207
|
console.log(`工具调用: ${chunk.toolName} - ${chunk.toolStatus}`);
|
|
224
208
|
break;
|
|
225
209
|
|
|
@@ -239,7 +223,6 @@ export class IFlowAPIServer {
|
|
|
239
223
|
}
|
|
240
224
|
}
|
|
241
225
|
|
|
242
|
-
// 发送结束标记
|
|
243
226
|
const endChunk = createStreamChunk(id, model, '', 'stop');
|
|
244
227
|
res.write(formatSSE(endChunk));
|
|
245
228
|
res.write(SSE_DONE);
|
|
@@ -253,9 +236,6 @@ export class IFlowAPIServer {
|
|
|
253
236
|
}
|
|
254
237
|
}
|
|
255
238
|
|
|
256
|
-
/**
|
|
257
|
-
* 处理非流式响应
|
|
258
|
-
*/
|
|
259
239
|
private async handleNonStreamResponse(
|
|
260
240
|
res: Response,
|
|
261
241
|
conversationId: string,
|
|
@@ -265,7 +245,6 @@ export class IFlowAPIServer {
|
|
|
265
245
|
): Promise<void> {
|
|
266
246
|
const id = generateId();
|
|
267
247
|
|
|
268
|
-
// 设置 5 分钟超时
|
|
269
248
|
const timeout = setTimeout(() => {
|
|
270
249
|
res.status(504).json(this.createError('请求超时', 'timeout_error'));
|
|
271
250
|
}, 300000);
|
|
@@ -290,7 +269,6 @@ export class IFlowAPIServer {
|
|
|
290
269
|
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
291
270
|
console.error('处理请求错误:', errorMsg);
|
|
292
271
|
|
|
293
|
-
// 区分超时错误和其他错误
|
|
294
272
|
if (errorMsg.includes('超时') || errorMsg.includes('timeout')) {
|
|
295
273
|
res.status(504).json(this.createError(errorMsg, 'timeout_error', 'timeout'));
|
|
296
274
|
} else {
|
|
@@ -299,9 +277,6 @@ export class IFlowAPIServer {
|
|
|
299
277
|
}
|
|
300
278
|
}
|
|
301
279
|
|
|
302
|
-
/**
|
|
303
|
-
* 设置错误处理
|
|
304
|
-
*/
|
|
305
280
|
private setupErrorHandler(): void {
|
|
306
281
|
this.app.use((err: Error, req: Request, res: Response, _next: NextFunction) => {
|
|
307
282
|
console.error('服务器错误:', err);
|
|
@@ -309,9 +284,6 @@ export class IFlowAPIServer {
|
|
|
309
284
|
});
|
|
310
285
|
}
|
|
311
286
|
|
|
312
|
-
/**
|
|
313
|
-
* 创建错误响应
|
|
314
|
-
*/
|
|
315
287
|
private createError(message: string, type: string, code: string = 'unknown_error'): ErrorResponse {
|
|
316
288
|
return {
|
|
317
289
|
error: {
|
|
@@ -322,16 +294,11 @@ export class IFlowAPIServer {
|
|
|
322
294
|
};
|
|
323
295
|
}
|
|
324
296
|
|
|
325
|
-
/**
|
|
326
|
-
* 启动服务器
|
|
327
|
-
*/
|
|
328
297
|
async start(): Promise<void> {
|
|
329
|
-
// 连接 iFlow
|
|
330
298
|
console.log('正在连接 iFlow...');
|
|
331
299
|
await this.adapter.connect();
|
|
332
300
|
console.log('iFlow 连接成功');
|
|
333
301
|
|
|
334
|
-
// 启动 HTTP 服务器
|
|
335
302
|
const host = this.options.host || '0.0.0.0';
|
|
336
303
|
const port = this.options.port;
|
|
337
304
|
|
|
@@ -357,9 +324,6 @@ export class IFlowAPIServer {
|
|
|
357
324
|
});
|
|
358
325
|
}
|
|
359
326
|
|
|
360
|
-
/**
|
|
361
|
-
* 停止服务器
|
|
362
|
-
*/
|
|
363
327
|
async stop(): Promise<void> {
|
|
364
328
|
await this.adapter.disconnect();
|
|
365
329
|
}
|