@iflow-ai/iflow-cli 0.4.16 → 0.5.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iflow-ai/iflow-cli",
3
- "version": "0.4.16",
3
+ "version": "0.5.0",
4
4
  "engines": {
5
5
  "node": ">=20.0.0"
6
6
  },
@@ -63,6 +63,7 @@
63
63
  "LICENSE"
64
64
  ],
65
65
  "devDependencies": {
66
+ "@types/jsdom": "^27.0.0",
66
67
  "@types/marked": "^5.0.2",
67
68
  "@types/micromatch": "^4.0.9",
68
69
  "@types/mime-types": "^3.0.1",
@@ -118,7 +119,11 @@
118
119
  "access": "public"
119
120
  },
120
121
  "dependencies": {
122
+ "asciify-image": "^0.1.10",
123
+ "gifuct-js": "^2.1.2",
121
124
  "ink": "^6.5.0",
125
+ "ink-picture": "^1.3.3",
126
+ "is-unicode-supported": "^2.1.0",
122
127
  "react-devtools-core": "^6.1.5",
123
128
  "shell-quote": "^1.8.3"
124
129
  }
@@ -4,8 +4,17 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
 
7
- import { existsSync, mkdirSync, createWriteStream, statSync, readdirSync, createReadStream, unlinkSync, rmSync } from 'fs';
8
- import { join, dirname, resolve } from 'path';
7
+ import {
8
+ existsSync,
9
+ mkdirSync,
10
+ createWriteStream,
11
+ statSync,
12
+ readdirSync,
13
+ createReadStream,
14
+ unlinkSync,
15
+ rmSync,
16
+ } from 'fs';
17
+ import { join } from 'path';
9
18
  import { fileURLToPath } from 'url';
10
19
  import os from 'os';
11
20
  import https from 'https';
@@ -15,48 +24,29 @@ import { pipeline } from 'stream/promises';
15
24
  import { Extract } from 'unzipper';
16
25
 
17
26
  // 常量定义
18
- const PLUGIN_URL = 'https://cloud.iflow.cn/iflow-cli/idea-plugin/iflow-idea-0.0.3.zip';
27
+ const PLUGIN_URL =
28
+ 'https://cloud.iflow.cn/iflow-cli/idea-plugin/iflow-idea-0.0.5.zip';
19
29
  const PLUGIN_DIR_NAME = 'iflow-idea';
20
30
  const TEMP_DIR_NAME = 'tstar-cli-idea-plugin';
21
31
  const LOG_PREFIX = '[JetBrains Extension]';
22
32
  // 扩展支持的JetBrains IDE产品
23
33
  const IDE_PATTERNS = [
24
- 'IntelliJIdea', 'IdeaIC', // IntelliJ IDEA
25
- 'PyCharm', 'PyCharmCE', // PyCharm
26
- 'GoLand', // GoLand
27
- 'WebStorm', // WebStorm
28
- 'PhpStorm', // PhpStorm
29
- 'CLion', // CLion
30
- 'RubyMine', // RubyMine
31
- 'DataGrip', // DataGrip
32
- 'Rider', // Rider
33
- 'AndroidStudio' // Android Studio
34
+ 'IntelliJIdea',
35
+ 'IdeaIC', // IntelliJ IDEA
36
+ 'PyCharm',
37
+ 'PyCharmCE', // PyCharm
38
+ 'GoLand', // GoLand
39
+ 'WebStorm', // WebStorm
40
+ 'PhpStorm', // PhpStorm
41
+ 'CLion', // CLion
42
+ 'RubyMine', // RubyMine
43
+ 'DataGrip', // DataGrip
44
+ 'Rider', // Rider
45
+ 'AndroidStudio', // Android Studio
34
46
  ];
35
47
 
36
48
  // 获取当前脚本的目录
37
49
  const __filename = fileURLToPath(import.meta.url);
38
- const __dirname = dirname(__filename);
39
-
40
- // 验证路径是否安全
41
- function validatePath(path) {
42
- if (!path || typeof path !== 'string') {
43
- return false;
44
- }
45
-
46
- // 防止路径遍历攻击
47
- const normalizedPath = resolve(path);
48
- return !normalizedPath.includes('..');
49
- }
50
-
51
- // 检查文件是否存在且可执行
52
- function isExecutable(filePath) {
53
- try {
54
- const stats = statSync(filePath);
55
- return stats.isFile() && (stats.mode & parseInt('111', 8)) !== 0;
56
- } catch {
57
- return false;
58
- }
59
- }
60
50
 
61
51
  // 获取 JetBrains IDE 插件目录的跨平台函数
62
52
  function getJetBrainsPluginsDirectory() {
@@ -87,14 +77,17 @@ function findLatestJetBrainsDirectories() {
87
77
  try {
88
78
  // 获取所有匹配的IDE目录,并按修改时间排序
89
79
  const dirs = readdirSync(jetbrainsDir)
90
- .filter(dir => IDE_PATTERNS.some(pattern => dir.startsWith(pattern)))
91
- .map(dir => {
80
+ .filter((dir) => IDE_PATTERNS.some((pattern) => dir.startsWith(pattern)))
81
+ .map((dir) => {
92
82
  const fullPath = join(jetbrainsDir, dir);
93
83
  try {
94
84
  const stats = statSync(fullPath);
95
85
  return { path: fullPath, mtime: stats.mtime, name: dir };
96
86
  } catch (error) {
97
- console.warn(`${LOG_PREFIX} Cannot access directory ${fullPath}:`, error.message);
87
+ console.warn(
88
+ `${LOG_PREFIX} Cannot access directory ${fullPath}:`,
89
+ error.message,
90
+ );
98
91
  return null;
99
92
  }
100
93
  })
@@ -108,8 +101,10 @@ function findLatestJetBrainsDirectories() {
108
101
 
109
102
  // 按IDE类型分组,每种IDE只保留最新版本
110
103
  const latestByType = {};
111
- dirs.forEach(dir => {
112
- const ideType = IDE_PATTERNS.find(pattern => dir.name.startsWith(pattern));
104
+ dirs.forEach((dir) => {
105
+ const ideType = IDE_PATTERNS.find((pattern) =>
106
+ dir.name.startsWith(pattern),
107
+ );
113
108
  if (ideType && !latestByType[ideType]) {
114
109
  latestByType[ideType] = dir;
115
110
  }
@@ -117,7 +112,10 @@ function findLatestJetBrainsDirectories() {
117
112
 
118
113
  return Object.values(latestByType);
119
114
  } catch (error) {
120
- console.error(`${LOG_PREFIX} Error finding JetBrains IDE directories:`, error.message);
115
+ console.error(
116
+ `${LOG_PREFIX} Error finding JetBrains IDE directories:`,
117
+ error.message,
118
+ );
121
119
  return [];
122
120
  }
123
121
  }
@@ -130,18 +128,22 @@ async function downloadPlugin(url, destPath) {
130
128
  // 根据URL协议选择适当的模块
131
129
  const protocol = url.startsWith('https:') ? https : http;
132
130
 
133
- protocol.get(url, (response) => {
134
- if (response.statusCode !== 200) {
135
- reject(new Error(`Failed to download plugin: ${response.statusCode}`));
136
- return;
137
- }
131
+ protocol
132
+ .get(url, (response) => {
133
+ if (response.statusCode !== 200) {
134
+ reject(
135
+ new Error(`Failed to download plugin: ${response.statusCode}`),
136
+ );
137
+ return;
138
+ }
138
139
 
139
- pipeline(response, file)
140
- .then(() => resolve())
141
- .catch(reject);
142
- }).on('error', (err) => {
143
- reject(err);
144
- });
140
+ pipeline(response, file)
141
+ .then(() => resolve())
142
+ .catch(reject);
143
+ })
144
+ .on('error', (err) => {
145
+ reject(err);
146
+ });
145
147
  });
146
148
  }
147
149
 
@@ -177,7 +179,9 @@ async function installJetBrainsExtension() {
177
179
  // 查找所有支持的 JetBrains IDE 目录
178
180
  const ideDirs = findLatestJetBrainsDirectories();
179
181
  if (ideDirs.length === 0) {
180
- console.warn(`${LOG_PREFIX} Could not find any JetBrains IDE installation, skipping plugin installation`);
182
+ console.warn(
183
+ `${LOG_PREFIX} Could not find any JetBrains IDE installation, skipping plugin installation`,
184
+ );
181
185
  return;
182
186
  }
183
187
 
@@ -187,7 +191,10 @@ async function installJetBrainsExtension() {
187
191
  try {
188
192
  mkdirSync(tempDir, { recursive: true });
189
193
  } catch (error) {
190
- console.error(`${LOG_PREFIX} Failed to create temporary directory: ${tempDir}`, error.message);
194
+ console.error(
195
+ `${LOG_PREFIX} Failed to create temporary directory: ${tempDir}`,
196
+ error.message,
197
+ );
191
198
  return;
192
199
  }
193
200
  }
@@ -217,7 +224,10 @@ async function installJetBrainsExtension() {
217
224
  try {
218
225
  mkdirSync(pluginsDir, { recursive: true });
219
226
  } catch (error) {
220
- console.error(`${LOG_PREFIX} Failed to create plugins directory: ${pluginsDir}`, error.message);
227
+ console.error(
228
+ `${LOG_PREFIX} Failed to create plugins directory: ${pluginsDir}`,
229
+ error.message,
230
+ );
221
231
  continue; // 跳过此IDE,继续下一个
222
232
  }
223
233
  }
@@ -226,10 +236,15 @@ async function installJetBrainsExtension() {
226
236
  const existingPluginDir = join(pluginsDir, PLUGIN_DIR_NAME);
227
237
  if (existsSync(existingPluginDir)) {
228
238
  try {
229
- console.info(`${LOG_PREFIX} Removing existing plugin directory: ${existingPluginDir}`);
239
+ console.info(
240
+ `${LOG_PREFIX} Removing existing plugin directory: ${existingPluginDir}`,
241
+ );
230
242
  rmSync(existingPluginDir, { recursive: true, force: true });
231
243
  } catch (error) {
232
- console.error(`${LOG_PREFIX} Failed to remove existing plugin directory: ${existingPluginDir}`, error.message);
244
+ console.error(
245
+ `${LOG_PREFIX} Failed to remove existing plugin directory: ${existingPluginDir}`,
246
+ error.message,
247
+ );
233
248
  // 继续安装,即使删除失败
234
249
  }
235
250
  }
@@ -240,9 +255,14 @@ async function installJetBrainsExtension() {
240
255
  try {
241
256
  // 直接解压到插件目录,不创建额外的子目录
242
257
  await extractPlugin(pluginFilePath, pluginsDir);
243
- console.info(`${LOG_PREFIX} ✔ Plugin installed successfully to: ${pluginsDir}`);
258
+ console.info(
259
+ `${LOG_PREFIX} ✔ Plugin installed successfully to: ${pluginsDir}`,
260
+ );
244
261
  } catch (error) {
245
- console.error(`${LOG_PREFIX} Failed to install plugin for ${ideDir.name}:`, error.message);
262
+ console.error(
263
+ `${LOG_PREFIX} Failed to install plugin for ${ideDir.name}:`,
264
+ error.message,
265
+ );
246
266
  }
247
267
  }
248
268
 
@@ -250,22 +270,27 @@ async function installJetBrainsExtension() {
250
270
  try {
251
271
  unlinkSync(pluginFilePath);
252
272
  } catch (error) {
253
- console.warn(`${LOG_PREFIX} Failed to clean up temporary file: ${pluginFilePath}`, error.message);
273
+ console.warn(
274
+ `${LOG_PREFIX} Failed to clean up temporary file: ${pluginFilePath}`,
275
+ error.message,
276
+ );
254
277
  }
255
-
256
278
  } catch (error) {
257
279
  console.error(`${LOG_PREFIX} Failed to install plugin:`, error.message);
258
280
  console.debug(`${LOG_PREFIX} Stack trace:`, error.stack);
259
281
  }
260
282
  } catch (error) {
261
- console.error(`${LOG_PREFIX} Unexpected error during JetBrains extension installation:`, error.message);
283
+ console.error(
284
+ `${LOG_PREFIX} Unexpected error during JetBrains extension installation:`,
285
+ error.message,
286
+ );
262
287
  console.debug(`${LOG_PREFIX} Stack trace:`, error.stack);
263
288
  }
264
289
  }
265
290
 
266
291
  // 只在非 CI 环境执行
267
292
  if (!process.env.CI) {
268
- installJetBrainsExtension().catch(error => {
293
+ installJetBrainsExtension().catch((error) => {
269
294
  console.error(`${LOG_PREFIX} Installation failed:`, error.message);
270
295
  });
271
296
  }