@userdaoo/iflow-api-bridge 0.1.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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ {
2
+ "port": 8080,
3
+ "host": "0.0.0.0",
4
+ "cors": true,
5
+ "apiKey": "sk-your-secret-key",
6
+ "model": "claude",
7
+ "logLevel": "INFO"
8
+ }
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@userdaoo/iflow-api-bridge",
3
+ "version": "0.1.0",
4
+ "description": "将 iFlow LLM 服务暴露为 OpenAI 兼容 API",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "bin": {
8
+ "iflow-api-server": "dist/cli.js"
9
+ },
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "dev": "tsx src/cli.ts",
13
+ "start": "node dist/cli.js",
14
+ "prepare": "npm run build"
15
+ },
16
+ "keywords": [
17
+ "iflow",
18
+ "llm",
19
+ "openai",
20
+ "api",
21
+ "bridge",
22
+ "agent"
23
+ ],
24
+ "author": "iFlow Team",
25
+ "license": "MIT",
26
+ "dependencies": {
27
+ "commander": "^12.0.0",
28
+ "cors": "^2.8.5",
29
+ "express": "^4.19.2",
30
+ "ws": "^8.16.0"
31
+ },
32
+ "devDependencies": {
33
+ "@types/cors": "^2.8.17",
34
+ "@types/express": "^4.17.21",
35
+ "@types/node": "^20.12.0",
36
+ "@types/ws": "^8.5.10",
37
+ "tsx": "^4.7.0",
38
+ "typescript": "^5.4.0"
39
+ },
40
+ "engines": {
41
+ "node": ">=22.0.0"
42
+ }
43
+ }
package/src/adapter.ts ADDED
@@ -0,0 +1,227 @@
1
+ /**
2
+ * iFlow SDK 适配器(使用子进程模式)
3
+ * 封装与 iFlow CLI 的通信
4
+ */
5
+
6
+ import { spawn, type ChildProcess } from 'child_process';
7
+
8
+ export interface IFlowResponse {
9
+ content: string;
10
+ toolCalls?: Array<{
11
+ name: string;
12
+ status: string;
13
+ }>;
14
+ stopReason: 'end_turn' | 'max_tokens' | 'error';
15
+ }
16
+
17
+ export interface StreamChunk {
18
+ type: 'content' | 'tool_call' | 'done' | 'error';
19
+ content?: string;
20
+ toolName?: string;
21
+ toolStatus?: string;
22
+ error?: string;
23
+ }
24
+
25
+ export interface IFlowAdapterOptions {
26
+ model?: string;
27
+ apiKey?: string;
28
+ baseUrl?: string;
29
+ timeout?: number;
30
+ }
31
+
32
+ /**
33
+ * iFlow 适配器 - 使用子进程模式
34
+ */
35
+ export class IFlowAdapter {
36
+ private options: IFlowAdapterOptions;
37
+ private defaultTimeout = 120000; // 2分钟默认超时
38
+
39
+ constructor(options: IFlowAdapterOptions = {}) {
40
+ this.options = options;
41
+ }
42
+
43
+ /**
44
+ * 发送消息并获取完整响应(非流式)
45
+ */
46
+ async sendMessage(prompt: string): Promise<IFlowResponse> {
47
+ console.log('[Adapter] 发送消息(非流式):', prompt.substring(0, 100));
48
+
49
+ return new Promise((resolve, reject) => {
50
+ const args = ['-p', prompt];
51
+ if (this.options.model) {
52
+ args.push('-m', this.options.model);
53
+ }
54
+
55
+ console.log('[Adapter] 启动 iflow:', args.join(' '));
56
+ const child = spawn('iflow', args, {
57
+ stdio: ['ignore', 'pipe', 'pipe'],
58
+ });
59
+
60
+ let stdout = '';
61
+ let stderr = '';
62
+ const timeout = setTimeout(() => {
63
+ child.kill('SIGTERM');
64
+ reject(new Error(`iFlow 响应超时 (${this.defaultTimeout}ms)`));
65
+ }, this.options.timeout || this.defaultTimeout);
66
+
67
+ child.stdout?.on('data', (data) => {
68
+ stdout += data.toString();
69
+ });
70
+
71
+ child.stderr?.on('data', (data) => {
72
+ stderr += data.toString();
73
+ });
74
+
75
+ child.on('error', (err) => {
76
+ clearTimeout(timeout);
77
+ reject(new Error(`启动 iFlow 失败: ${err.message}`));
78
+ });
79
+
80
+ child.on('exit', (code) => {
81
+ clearTimeout(timeout);
82
+ console.log('[Adapter] iFlow 退出,code:', code);
83
+
84
+ if (code !== 0 && code !== null) {
85
+ console.error('[Adapter] iFlow stderr:', stderr);
86
+ }
87
+
88
+ // 解析响应
89
+ const content = this.parseResponse(stdout);
90
+ resolve({
91
+ content,
92
+ stopReason: code === 0 ? 'end_turn' : 'error',
93
+ });
94
+ });
95
+ });
96
+ }
97
+
98
+ /**
99
+ * 发送消息并获取流式响应
100
+ */
101
+ async *sendMessageStream(prompt: string): AsyncGenerator<StreamChunk> {
102
+ console.log('[Adapter] 发送消息(流式):', prompt.substring(0, 100));
103
+
104
+ const args = ['-p', prompt];
105
+ if (this.options.model) {
106
+ args.push('-m', this.options.model);
107
+ }
108
+
109
+ console.log('[Adapter] 启动 iflow:', args.join(' '));
110
+ const child = spawn('iflow', args, {
111
+ stdio: ['ignore', 'pipe', 'pipe'],
112
+ });
113
+
114
+ let buffer = '';
115
+ let isDone = false;
116
+ const timeout = setTimeout(() => {
117
+ if (!isDone) {
118
+ child.kill('SIGTERM');
119
+ isDone = true;
120
+ console.error('[Adapter] 流式响应超时');
121
+ }
122
+ }, this.options.timeout || this.defaultTimeout);
123
+
124
+ child.stdout?.on('data', (data) => {
125
+ buffer += data.toString();
126
+ });
127
+
128
+ child.stderr?.on('data', (data) => {
129
+ const msg = data.toString();
130
+ console.log('[Adapter] iFlow stderr:', msg.trim());
131
+ });
132
+
133
+ // 模拟流式输出 - 逐字符发送
134
+ let lastSentIndex = 0;
135
+ while (!isDone) {
136
+ // 检查进程是否结束
137
+ if (child.exitCode !== null) {
138
+ isDone = true;
139
+ }
140
+
141
+ // 发送新内容
142
+ if (buffer.length > lastSentIndex) {
143
+ const newContent = buffer.slice(lastSentIndex);
144
+ lastSentIndex = buffer.length;
145
+
146
+ // 逐行或逐字符发送
147
+ const lines = newContent.split('\n');
148
+ for (const line of lines) {
149
+ if (line.trim()) {
150
+ yield {
151
+ type: 'content',
152
+ content: line + '\n',
153
+ };
154
+ }
155
+ }
156
+ }
157
+
158
+ if (!isDone) {
159
+ await new Promise((resolve) => setTimeout(resolve, 50));
160
+ }
161
+ }
162
+
163
+ clearTimeout(timeout);
164
+
165
+ // 发送剩余内容
166
+ if (buffer.length > lastSentIndex) {
167
+ yield {
168
+ type: 'content',
169
+ content: buffer.slice(lastSentIndex),
170
+ };
171
+ }
172
+
173
+ yield { type: 'done' };
174
+ }
175
+
176
+ /**
177
+ * 解析 iFlow 输出,提取实际回复内容
178
+ */
179
+ private parseResponse(stdout: string): string {
180
+ // 尝试提取 <Execution Info> 之前的内容作为回复
181
+ const executionInfoMatch = stdout.match(/<Execution Info>[\s\S]*$/);
182
+ if (executionInfoMatch) {
183
+ return stdout.substring(0, executionInfoMatch.index).trim();
184
+ }
185
+
186
+ // 如果没有 Execution Info,返回全部内容(去掉开头的警告)
187
+ const lines = stdout.split('\n');
188
+ const startIndex = lines.findIndex((line) =>
189
+ !line.includes('DeprecationWarning') &&
190
+ !line.includes('node:') &&
191
+ line.trim()
192
+ );
193
+
194
+ if (startIndex >= 0) {
195
+ return lines.slice(startIndex).join('\n').trim();
196
+ }
197
+
198
+ return stdout.trim();
199
+ }
200
+
201
+ /**
202
+ * 连接到 iFlow
203
+ */
204
+ async connect(): Promise<void> {
205
+ // 子进程模式不需要持久连接
206
+ console.log('[Adapter] 子进程模式已就绪');
207
+ }
208
+
209
+ /**
210
+ * 断开连接
211
+ */
212
+ disconnect(): void {
213
+ // 子进程模式不需要断开连接
214
+ console.log('[Adapter] 子进程模式断开(无操作)');
215
+ }
216
+
217
+ /**
218
+ * 检查是否已连接
219
+ */
220
+ isConnected(): boolean {
221
+ // 子进程模式总是"已连接"
222
+ return true;
223
+ }
224
+ }
225
+
226
+ export default IFlowAdapter;
227
+
package/src/cli.ts ADDED
@@ -0,0 +1,64 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * CLI 入口
5
+ */
6
+
7
+ import { Command } from 'commander';
8
+ import { IFlowAPIServer } from './server.js';
9
+ import { loadConfig, loadEnvConfig, mergeConfig, type Config } from './config.js';
10
+
11
+ const program = new Command();
12
+
13
+ program
14
+ .name('iflow-api-server')
15
+ .description('将 iFlow LLM 服务暴露为 OpenAI 兼容 API')
16
+ .version('0.1.0');
17
+
18
+ program
19
+ .option('-p, --port <port>', '服务端口', '8080')
20
+ .option('-h, --host <host>', '服务主机', '0.0.0.0')
21
+ .option('--no-cors', '禁用 CORS')
22
+ .option('-k, --api-key <key>', 'API Key 认证')
23
+ .option('-m, --model <model>', '指定使用的模型 (如 claude, gpt-4)', 'kimi-k2.5')
24
+ .option('-c, --config <path>', '配置文件路径')
25
+ .option('--log-level <level>', '日志级别 (DEBUG|INFO|WARN|ERROR)', 'INFO')
26
+ .action(async (options) => {
27
+ try {
28
+ // 加载配置
29
+ const fileConfig = loadConfig(options.config);
30
+ const envConfig = loadEnvConfig();
31
+ const cliConfig: Partial<Config> = {
32
+ port: options.port ? parseInt(options.port, 10) : undefined,
33
+ host: options.host,
34
+ cors: options.cors,
35
+ apiKey: options.apiKey,
36
+ model: options.model,
37
+ logLevel: options.logLevel,
38
+ };
39
+
40
+ // 合并配置
41
+ const config = mergeConfig(fileConfig, envConfig, cliConfig);
42
+
43
+ // 创建并启动服务器
44
+ const server = new IFlowAPIServer(config);
45
+
46
+ // 处理退出信号
47
+ const shutdown = async (signal: string) => {
48
+ console.log(`\n${signal} 收到,正在关闭服务器...`);
49
+ await server.stop();
50
+ process.exit(0);
51
+ };
52
+
53
+ process.on('SIGINT', () => shutdown('SIGINT'));
54
+ process.on('SIGTERM', () => shutdown('SIGTERM'));
55
+
56
+ // 启动
57
+ await server.start();
58
+ } catch (error) {
59
+ console.error('启动失败:', error);
60
+ process.exit(1);
61
+ }
62
+ });
63
+
64
+ program.parse();
package/src/config.ts ADDED
@@ -0,0 +1,102 @@
1
+ /**
2
+ * 配置管理
3
+ */
4
+
5
+ import { readFileSync, existsSync } from 'fs';
6
+ import { resolve } from 'path';
7
+
8
+ export interface Config {
9
+ port: number;
10
+ host: string;
11
+ cors: boolean;
12
+ apiKey?: string;
13
+ model?: string;
14
+ logLevel: 'DEBUG' | 'INFO' | 'WARN' | 'ERROR';
15
+ }
16
+
17
+ export const DEFAULT_CONFIG: Config = {
18
+ port: 8080,
19
+ host: '0.0.0.0',
20
+ cors: true,
21
+ model: 'kimi-k2.5',
22
+ logLevel: 'INFO',
23
+ };
24
+
25
+ /**
26
+ * 从文件加载配置
27
+ */
28
+ export function loadConfig(configPath?: string): Partial<Config> {
29
+ const paths = configPath
30
+ ? [configPath]
31
+ : [
32
+ './iflow-api.config.json',
33
+ './.iflow-api.json',
34
+ '~/.iflow-api/config.json',
35
+ ];
36
+
37
+ for (const path of paths) {
38
+ const fullPath = resolve(path.replace(/^~/, process.env.HOME || ''));
39
+ if (existsSync(fullPath)) {
40
+ try {
41
+ const content = readFileSync(fullPath, 'utf-8');
42
+ return JSON.parse(content);
43
+ } catch (error) {
44
+ console.warn(`无法加载配置文件 ${path}:`, error);
45
+ }
46
+ }
47
+ }
48
+
49
+ return {};
50
+ }
51
+
52
+ /**
53
+ * 从环境变量加载配置
54
+ */
55
+ export function loadEnvConfig(): Partial<Config> {
56
+ const config: Partial<Config> = {};
57
+
58
+ if (process.env.IFLOW_API_PORT) {
59
+ config.port = parseInt(process.env.IFLOW_API_PORT, 10);
60
+ }
61
+
62
+ if (process.env.IFLOW_API_HOST) {
63
+ config.host = process.env.IFLOW_API_HOST;
64
+ }
65
+
66
+ if (process.env.IFLOW_API_KEY) {
67
+ config.apiKey = process.env.IFLOW_API_KEY;
68
+ }
69
+
70
+ if (process.env.IFLOW_API_LOG_LEVEL) {
71
+ const level = process.env.IFLOW_API_LOG_LEVEL as Config['logLevel'];
72
+ if (['DEBUG', 'INFO', 'WARN', 'ERROR'].includes(level)) {
73
+ config.logLevel = level;
74
+ }
75
+ }
76
+
77
+ if (process.env.IFLOW_API_CORS) {
78
+ config.cors = process.env.IFLOW_API_CORS === 'true';
79
+ }
80
+
81
+ if (process.env.IFLOW_API_MODEL) {
82
+ config.model = process.env.IFLOW_API_MODEL;
83
+ }
84
+
85
+ return config;
86
+ }
87
+
88
+ /**
89
+ * 合并配置
90
+ */
91
+ export function mergeConfig(
92
+ fileConfig: Partial<Config>,
93
+ envConfig: Partial<Config>,
94
+ cliConfig: Partial<Config>
95
+ ): Config {
96
+ return {
97
+ ...DEFAULT_CONFIG,
98
+ ...fileConfig,
99
+ ...envConfig,
100
+ ...cliConfig,
101
+ };
102
+ }
package/src/index.ts ADDED
@@ -0,0 +1,27 @@
1
+ /**
2
+ * iFlow API Bridge
3
+ * 将 iFlow LLM 服务暴露为 OpenAI 兼容 API
4
+ */
5
+
6
+ export { IFlowAdapter, type IFlowResponse, type StreamChunk } from './adapter.js';
7
+ export { IFlowAPIServer, type ServerOptions } from './server.js';
8
+ export {
9
+ loadConfig,
10
+ loadEnvConfig,
11
+ mergeConfig,
12
+ DEFAULT_CONFIG,
13
+ type Config,
14
+ } from './config.js';
15
+ export * from './openai/types.js';
16
+ export {
17
+ generateId,
18
+ getTimestamp,
19
+ messagesToIFlowPrompt,
20
+ createCompletionResponse,
21
+ createStreamChunk,
22
+ calculateUsage,
23
+ formatSSE,
24
+ SSE_DONE,
25
+ AVAILABLE_MODELS,
26
+ getDefaultModel,
27
+ } from './openai/transformer.js';
@@ -0,0 +1,142 @@
1
+ /**
2
+ * OpenAI API 与 iFlow 消息格式转换器
3
+ */
4
+
5
+ import type {
6
+ ChatCompletionMessage,
7
+ ChatCompletionResponse,
8
+ ChatCompletionStreamResponse,
9
+ ChatCompletionStreamChoice,
10
+ ChatCompletionChoice,
11
+ UsageInfo,
12
+ ToolCall,
13
+ } from './types.js';
14
+
15
+ /**
16
+ * 生成唯一 ID
17
+ */
18
+ export function generateId(): string {
19
+ return `chatcmpl-${Date.now().toString(36)}${Math.random().toString(36).substring(2, 10)}`;
20
+ }
21
+
22
+ /**
23
+ * 获取当前时间戳
24
+ */
25
+ export function getTimestamp(): number {
26
+ return Math.floor(Date.now() / 1000);
27
+ }
28
+
29
+ /**
30
+ * 将 OpenAI 消息格式转换为 iFlow 文本格式
31
+ */
32
+ export function messagesToIFlowPrompt(messages: ChatCompletionMessage[]): string {
33
+ return messages.map(msg => {
34
+ if (typeof msg.content === 'string') {
35
+ return `${msg.role}: ${msg.content}`;
36
+ }
37
+ return `${msg.role}: [复杂内容]`;
38
+ }).join('\n\n');
39
+ }
40
+
41
+ /**
42
+ * 创建流式响应块
43
+ */
44
+ export function createStreamChunk(
45
+ id: string,
46
+ model: string,
47
+ content: string,
48
+ finishReason: 'stop' | 'length' | null = null
49
+ ): ChatCompletionStreamResponse {
50
+ const choice: ChatCompletionStreamChoice = {
51
+ index: 0,
52
+ delta: content ? { content } : {},
53
+ finish_reason: finishReason,
54
+ };
55
+
56
+ return {
57
+ id,
58
+ object: 'chat.completion.chunk',
59
+ created: getTimestamp(),
60
+ model,
61
+ choices: [choice],
62
+ };
63
+ }
64
+
65
+ /**
66
+ * 创建完整响应
67
+ */
68
+ export function createCompletionResponse(
69
+ id: string,
70
+ model: string,
71
+ content: string,
72
+ usage: UsageInfo,
73
+ finishReason: 'stop' | 'length' = 'stop'
74
+ ): ChatCompletionResponse {
75
+ const choice: ChatCompletionChoice = {
76
+ index: 0,
77
+ message: {
78
+ role: 'assistant',
79
+ content,
80
+ },
81
+ finish_reason: finishReason,
82
+ };
83
+
84
+ return {
85
+ id,
86
+ object: 'chat.completion',
87
+ created: getTimestamp(),
88
+ model,
89
+ choices: [choice],
90
+ usage,
91
+ };
92
+ }
93
+
94
+ /**
95
+ * 估算 token 数量(简化版)
96
+ */
97
+ export function estimateTokens(text: string): number {
98
+ // 简化估算:假设平均每 4 个字符一个 token
99
+ return Math.ceil(text.length / 4);
100
+ }
101
+
102
+ /**
103
+ * 计算使用量
104
+ */
105
+ export function calculateUsage(prompt: string, completion: string): UsageInfo {
106
+ const promptTokens = estimateTokens(prompt);
107
+ const completionTokens = estimateTokens(completion);
108
+
109
+ return {
110
+ prompt_tokens: promptTokens,
111
+ completion_tokens: completionTokens,
112
+ total_tokens: promptTokens + completionTokens,
113
+ };
114
+ }
115
+
116
+ /**
117
+ * SSE 格式化
118
+ */
119
+ export function formatSSE(data: unknown): string {
120
+ return `data: ${JSON.stringify(data)}\n\n`;
121
+ }
122
+
123
+ /**
124
+ * SSE 结束标记
125
+ */
126
+ export const SSE_DONE = 'data: [DONE]\n\n';
127
+
128
+ /**
129
+ * 支持的模型列表
130
+ */
131
+ export const AVAILABLE_MODELS = [
132
+ { id: 'iflow-default', name: 'iFlow Default' },
133
+ { id: 'iflow-claude', name: 'iFlow Claude' },
134
+ { id: 'iflow-gpt-4', name: 'iFlow GPT-4' },
135
+ ];
136
+
137
+ /**
138
+ * 获取默认模型 ID
139
+ */
140
+ export function getDefaultModel(): string {
141
+ return 'kimi-k2.5';
142
+ }