iflow-feishu 1.0.2 → 1.0.3
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/bin/iflow-feishu.js +248 -19
- package/package.json +1 -1
- package/src/core/constants.js +15 -1
package/bin/iflow-feishu.js
CHANGED
|
@@ -2,33 +2,262 @@
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* iFlow Feishu CLI 入口
|
|
5
|
+
*
|
|
6
|
+
* 启动流程:
|
|
7
|
+
* 1. 检测 iFlow CLI -> 未安装则引导安装
|
|
8
|
+
* 2. 检测 PM2 -> 未安装则自动安装
|
|
9
|
+
* 3. 检测飞书配置 -> 未配置则引导输入
|
|
10
|
+
* 4. 启动服务
|
|
5
11
|
*/
|
|
6
12
|
|
|
13
|
+
const { spawn, execSync } = require('child_process');
|
|
14
|
+
const fs = require('fs');
|
|
7
15
|
const path = require('path');
|
|
8
|
-
const
|
|
16
|
+
const readline = require('readline');
|
|
9
17
|
|
|
10
|
-
//
|
|
11
|
-
const
|
|
18
|
+
// 颜色输出
|
|
19
|
+
const colors = {
|
|
20
|
+
red: '\x1b[0;31m',
|
|
21
|
+
green: '\x1b[0;32m',
|
|
22
|
+
yellow: '\x1b[1;33m',
|
|
23
|
+
blue: '\x1b[0;34m',
|
|
24
|
+
cyan: '\x1b[0;36m',
|
|
25
|
+
nc: '\x1b[0m'
|
|
26
|
+
};
|
|
12
27
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
28
|
+
const log = {
|
|
29
|
+
info: (msg) => console.log(`${colors.blue}[INFO]${colors.nc} ${msg}`),
|
|
30
|
+
success: (msg) => console.log(`${colors.green}[SUCCESS]${colors.nc} ${msg}`),
|
|
31
|
+
warn: (msg) => console.log(`${colors.yellow}[WARN]${colors.nc} ${msg}`),
|
|
32
|
+
error: (msg) => console.log(`${colors.red}[ERROR]${colors.nc} ${msg}`),
|
|
33
|
+
step: (msg) => console.log(`${colors.cyan}==>${colors.nc} ${msg}`)
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
// 获取版本号
|
|
37
|
+
function getVersion() {
|
|
38
|
+
try {
|
|
39
|
+
const pkgPath = path.join(__dirname, '..', 'package.json');
|
|
40
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
|
|
41
|
+
return pkg.version || '1.0.0';
|
|
42
|
+
} catch {
|
|
43
|
+
return '1.0.0';
|
|
44
|
+
}
|
|
19
45
|
}
|
|
20
46
|
|
|
21
|
-
|
|
22
|
-
const child = spawn('bash', [scriptPath], {
|
|
23
|
-
stdio: 'inherit',
|
|
24
|
-
env: process.env
|
|
25
|
-
});
|
|
47
|
+
const VERSION = getVersion();
|
|
26
48
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
49
|
+
// 检查命令是否存在
|
|
50
|
+
function commandExists(cmd) {
|
|
51
|
+
try {
|
|
52
|
+
execSync(`which ${cmd} 2>/dev/null || command -v ${cmd} 2>/dev/null`, { stdio: 'ignore' });
|
|
53
|
+
return true;
|
|
54
|
+
} catch {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// 获取命令版本
|
|
60
|
+
function getCommandVersion(cmd) {
|
|
61
|
+
try {
|
|
62
|
+
const output = execSync(`${cmd} --version 2>/dev/null`, { encoding: 'utf8' }).trim();
|
|
63
|
+
return output.split('\n')[0];
|
|
64
|
+
} catch {
|
|
65
|
+
return '未知版本';
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// 交互式问题
|
|
70
|
+
async function question(prompt, defaultVal = 'n') {
|
|
71
|
+
const rl = readline.createInterface({
|
|
72
|
+
input: process.stdin,
|
|
73
|
+
output: process.stdout
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
return new Promise((resolve) => {
|
|
77
|
+
const hint = defaultVal === 'y' ? '[Y/n]' : '[y/N]';
|
|
78
|
+
rl.question(`${prompt} ${hint} `, (answer) => {
|
|
79
|
+
rl.close();
|
|
80
|
+
const reply = (answer || defaultVal).toLowerCase();
|
|
81
|
+
resolve(reply === 'y' || reply === 'yes');
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// 检测 iFlow CLI
|
|
87
|
+
async function checkIFlowCLI() {
|
|
88
|
+
log.step('检查 iFlow CLI...');
|
|
89
|
+
|
|
90
|
+
if (commandExists('iflow')) {
|
|
91
|
+
const version = getCommandVersion('iflow');
|
|
92
|
+
log.success(`iFlow CLI 已安装 (版本: ${version})`);
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
log.warn('iFlow CLI 未安装');
|
|
97
|
+
console.log('');
|
|
98
|
+
console.log('iFlow CLI 是运行此插件必需的依赖。');
|
|
99
|
+
console.log('官网: https://iflow.dev');
|
|
100
|
+
console.log('');
|
|
101
|
+
|
|
102
|
+
const install = await question('是否现在安装 iFlow CLI?', 'y');
|
|
103
|
+
|
|
104
|
+
if (install) {
|
|
105
|
+
log.info('正在安装 iFlow CLI...');
|
|
106
|
+
try {
|
|
107
|
+
execSync('npm install -g @iflow-ai/iflow-cli', { stdio: 'inherit' });
|
|
108
|
+
log.success('iFlow CLI 安装成功');
|
|
109
|
+
return true;
|
|
110
|
+
} catch (err) {
|
|
111
|
+
log.error(`安装失败: ${err.message}`);
|
|
112
|
+
console.log('');
|
|
113
|
+
console.log('请手动安装: npm install -g @iflow-ai/iflow-cli');
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// 检测 PM2
|
|
122
|
+
async function checkPM2() {
|
|
123
|
+
log.step('检查 PM2...');
|
|
124
|
+
|
|
125
|
+
if (commandExists('pm2')) {
|
|
126
|
+
const version = getCommandVersion('pm2');
|
|
127
|
+
log.success(`PM2 已安装 (版本: ${version})`);
|
|
128
|
+
return true;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
log.warn('PM2 未安装');
|
|
132
|
+
console.log('');
|
|
133
|
+
console.log('PM2 用于进程管理,建议安装。');
|
|
134
|
+
console.log('');
|
|
135
|
+
|
|
136
|
+
const install = await question('是否现在安装 PM2?', 'y');
|
|
137
|
+
|
|
138
|
+
if (install) {
|
|
139
|
+
log.info('正在安装 PM2...');
|
|
140
|
+
try {
|
|
141
|
+
execSync('npm install -g pm2', { stdio: 'inherit' });
|
|
142
|
+
log.success('PM2 安装成功');
|
|
143
|
+
return true;
|
|
144
|
+
} catch (err) {
|
|
145
|
+
log.warn(`PM2 安装失败: ${err.message}`);
|
|
146
|
+
console.log('服务将以前台模式运行');
|
|
147
|
+
return true; // PM2 可选,继续运行
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return true; // PM2 可选
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// 配置文件路径
|
|
155
|
+
const CONFIG_DIR = path.join(process.env.HOME, '.feishu-config');
|
|
156
|
+
const CONFIG_PATH = path.join(CONFIG_DIR, 'feishu-app.json');
|
|
157
|
+
|
|
158
|
+
// 检测飞书配置
|
|
159
|
+
async function checkFeishuConfig() {
|
|
160
|
+
log.step('检查飞书配置...');
|
|
161
|
+
|
|
162
|
+
// 检查环境变量
|
|
163
|
+
if (process.env.FEISHU_APP_ID && process.env.FEISHU_APP_SECRET) {
|
|
164
|
+
log.success('检测到环境变量配置');
|
|
165
|
+
return true;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// 检查配置文件
|
|
169
|
+
if (fs.existsSync(CONFIG_PATH)) {
|
|
170
|
+
try {
|
|
171
|
+
const config = JSON.parse(fs.readFileSync(CONFIG_PATH, 'utf8'));
|
|
172
|
+
if (config.appId && config.appSecret) {
|
|
173
|
+
log.success('飞书配置已存在');
|
|
174
|
+
return true;
|
|
175
|
+
}
|
|
176
|
+
} catch (err) {
|
|
177
|
+
log.warn(`配置文件格式错误: ${err.message}`);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
log.warn('未找到飞书配置');
|
|
182
|
+
console.log('');
|
|
183
|
+
console.log('请输入飞书机器人凭证(从飞书开放平台获取):');
|
|
184
|
+
console.log('文档: https://open.feishu.cn/document/home/introduction-to-feishu-open-platform');
|
|
185
|
+
console.log('');
|
|
186
|
+
|
|
187
|
+
const rl = readline.createInterface({
|
|
188
|
+
input: process.stdin,
|
|
189
|
+
output: process.stdout
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
const ask = (prompt) => new Promise((resolve) => {
|
|
193
|
+
rl.question(prompt, resolve);
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
const appId = await ask('📱 App ID: ');
|
|
197
|
+
if (!appId || appId.trim() === '') {
|
|
198
|
+
log.error('App ID 不能为空');
|
|
199
|
+
rl.close();
|
|
200
|
+
return false;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const appSecret = await ask('🔐 App Secret: ');
|
|
204
|
+
if (!appSecret || appSecret.trim() === '') {
|
|
205
|
+
log.error('App Secret 不能为空');
|
|
206
|
+
rl.close();
|
|
207
|
+
return false;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
rl.close();
|
|
211
|
+
|
|
212
|
+
// 保存配置
|
|
213
|
+
if (!fs.existsSync(CONFIG_DIR)) {
|
|
214
|
+
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
const config = { appId: appId.trim(), appSecret: appSecret.trim() };
|
|
218
|
+
fs.writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2));
|
|
219
|
+
log.success(`配置已保存到: ${CONFIG_PATH}`);
|
|
220
|
+
|
|
221
|
+
return true;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// 启动服务
|
|
225
|
+
function startService() {
|
|
226
|
+
log.step('启动服务...');
|
|
227
|
+
|
|
228
|
+
// 直接运行服务
|
|
229
|
+
require('../src/index.js');
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// 主函数
|
|
233
|
+
async function main() {
|
|
234
|
+
console.log('');
|
|
235
|
+
console.log('╔══════════════════════════════════════╗');
|
|
236
|
+
console.log(`║ iFlow Feishu Bridge ║`);
|
|
237
|
+
console.log(`║ 版本 ${VERSION.padEnd(20)}║`);
|
|
238
|
+
console.log('╚══════════════════════════════════════╝');
|
|
239
|
+
console.log('');
|
|
240
|
+
|
|
241
|
+
// 1. 检测 iFlow CLI
|
|
242
|
+
if (!await checkIFlowCLI()) {
|
|
243
|
+
process.exit(1);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// 2. 检测 PM2(可选)
|
|
247
|
+
await checkPM2();
|
|
248
|
+
|
|
249
|
+
// 3. 检测飞书配置
|
|
250
|
+
if (!await checkFeishuConfig()) {
|
|
251
|
+
process.exit(1);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
console.log('');
|
|
255
|
+
|
|
256
|
+
// 4. 启动服务
|
|
257
|
+
startService();
|
|
258
|
+
}
|
|
30
259
|
|
|
31
|
-
|
|
32
|
-
|
|
260
|
+
main().catch((err) => {
|
|
261
|
+
log.error(err.message);
|
|
33
262
|
process.exit(1);
|
|
34
263
|
});
|
package/package.json
CHANGED
package/src/core/constants.js
CHANGED
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
* 常量定义
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
const path = require('path');
|
|
7
|
+
|
|
5
8
|
const SEARCH_KEYWORDS = [
|
|
6
9
|
'搜索', '查找', '查询', '最新', '新闻', '天气',
|
|
7
10
|
'股价', '汇率', '今天', '明天', '本周', '本月',
|
|
@@ -35,7 +38,18 @@ const MODEL_MAX_TOKENS = {
|
|
|
35
38
|
'mistral-large': 32768
|
|
36
39
|
};
|
|
37
40
|
|
|
38
|
-
|
|
41
|
+
// 从 package.json 读取版本号
|
|
42
|
+
function getVersion() {
|
|
43
|
+
try {
|
|
44
|
+
const pkgPath = path.join(__dirname, '..', '..', 'package.json');
|
|
45
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
|
|
46
|
+
return pkg.version || '1.0.0';
|
|
47
|
+
} catch {
|
|
48
|
+
return '1.0.0';
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const VERSION = getVersion();
|
|
39
53
|
|
|
40
54
|
module.exports = {
|
|
41
55
|
SEARCH_KEYWORDS,
|