@xubill/xx-cli 1.0.6 → 2.0.1
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.
Potentially problematic release.
This version of @xubill/xx-cli might be problematic. Click here for more details.
- package/AGENTS.md +177 -0
- package/bin/cli.js +2 -0
- package/lib/core/index.js +206 -26
- package/lib/plugins/ai.js +295 -0
- package/lib/plugins/config-manager.js +86 -61
- package/lib/plugins/history.js +53 -42
- package/lib/plugins/plugin-manager.js +421 -288
- package/lib/utils/config-manager.js +1 -1
- package/lib/utils/history-manager.js +2 -1
- package/lib/utils/plugins-helper.js +276 -0
- package/package.json +6 -1
- package/plugin-development-new.md +565 -0
- package/plugin-development-old.md +447 -0
- package/readme.md +61 -354
package/readme.md
CHANGED
|
@@ -17,12 +17,12 @@ xx <command> [options]
|
|
|
17
17
|
|
|
18
18
|
## 版本记录
|
|
19
19
|
|
|
20
|
-
###
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
-
|
|
20
|
+
### v2.0.0
|
|
21
|
+
- 支持新格式命令注册,兼容旧格式插件
|
|
22
|
+
- 更新插件创建模板,采用配置对象格式并包含类结构实现
|
|
23
|
+
|
|
24
|
+
### v2.0.1
|
|
25
|
+
- 新增ai插件,解析自然语言为xx命令
|
|
26
26
|
|
|
27
27
|
## 框架自带命令
|
|
28
28
|
|
|
@@ -35,6 +35,36 @@ xx-cli 框架自带以下核心命令(位于 core 模块中):
|
|
|
35
35
|
| `help` | - | 显示帮助信息 |
|
|
36
36
|
| `version` | `v` | 显示版本信息 |
|
|
37
37
|
| `history` | `h` | 查看命令历史记录 |
|
|
38
|
+
| `ai` | - | AI 智能解释命令,将自然语言转换为 xx 命令 |
|
|
39
|
+
|
|
40
|
+
### AI 插件使用说明
|
|
41
|
+
|
|
42
|
+
**获取 API key**:访问 [白山智算](https://ai.baishan.com/auth/login?referralCode=9CbeQycJJP) 获取 API key
|
|
43
|
+
|
|
44
|
+
**使用方法**:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
# 快捷添加 API key
|
|
48
|
+
xx ai add <apiKey>
|
|
49
|
+
|
|
50
|
+
# 使用 AI 解释命令
|
|
51
|
+
xx ai <查询内容>
|
|
52
|
+
|
|
53
|
+
# 生成配置文件
|
|
54
|
+
xx ai config
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
**示例**:
|
|
58
|
+
```bash
|
|
59
|
+
# 添加 API key
|
|
60
|
+
xx ai add sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
61
|
+
|
|
62
|
+
# 解释命令
|
|
63
|
+
xx ai 关闭占用3000端口的进程
|
|
64
|
+
|
|
65
|
+
# 命令兜底(输入不存在的命令时自动调用 AI)
|
|
66
|
+
xx npm
|
|
67
|
+
```
|
|
38
68
|
|
|
39
69
|
### 插件管理命令
|
|
40
70
|
|
|
@@ -95,380 +125,57 @@ lib/plugins/
|
|
|
95
125
|
- **config-manager.js**:配置管理插件,用于管理所有插件的配置文件。它提供了导出、导入、列出配置等功能。
|
|
96
126
|
- **history.js**:历史记录插件,用于查看命令历史记录。它提供了查看、清除、搜索历史记录等功能。
|
|
97
127
|
- **plugin-manager.js**:插件管理插件,用于管理所有插件。它提供了列出、启用、禁用、添加、删除、创建插件等功能。
|
|
128
|
+
- **ai.js**:AI 智能解释插件,用于解释 xx-cli 命令的含义,将自然语言转换为命令。它提供了智能解释、命令兜底等功能。
|
|
98
129
|
|
|
99
130
|
## 插件开发
|
|
100
131
|
|
|
101
132
|
本部分将详细介绍如何在 xx-cli 中创建、开发和部署插件。
|
|
102
133
|
|
|
103
|
-
###
|
|
134
|
+
### 插件格式
|
|
135
|
+
|
|
136
|
+
xx-cli 支持两种插件格式:
|
|
137
|
+
|
|
138
|
+
1. **新格式(配置对象格式)**:使用配置对象定义的插件实现(推荐)
|
|
139
|
+
2. **旧格式(类结构格式)**:继承自 `BasePlugin` 类的插件实现(仅用于向后兼容)
|
|
104
140
|
|
|
105
|
-
|
|
141
|
+
### 新格式插件开发(推荐)
|
|
106
142
|
|
|
107
|
-
|
|
143
|
+
新格式插件使用配置对象定义插件信息和命令,结合类结构实现核心功能,是推荐的插件开发方式。
|
|
108
144
|
|
|
109
|
-
|
|
145
|
+
#### 创建新格式插件
|
|
110
146
|
|
|
111
147
|
```bash
|
|
112
|
-
#
|
|
148
|
+
# 创建新格式插件(默认)
|
|
113
149
|
xx plugin create <plugin-name>
|
|
114
150
|
|
|
115
151
|
# 或者使用别名
|
|
116
152
|
xx p create <plugin-name>
|
|
117
|
-
|
|
118
153
|
# 或者使用更短的别名
|
|
119
154
|
xx p cr <plugin-name>
|
|
120
155
|
```
|
|
121
156
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
```bash
|
|
125
|
-
# 创建一个名为 `hello-world` 的插件
|
|
126
|
-
xx plugin create hello-world
|
|
127
|
-
|
|
128
|
-
# 输出:
|
|
129
|
-
# 创建插件模板...
|
|
130
|
-
# 插件模板已成功创建到:/Users/xub/.xx-cli/plugins/hello-world.js
|
|
131
|
-
# 提示:请编辑插件文件,实现具体功能
|
|
132
|
-
# 测试方法:运行 "node bin/cli.js <插件命令>"
|
|
133
|
-
# 已自动打开 vscode 编辑插件文件
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
#### 手动创建插件
|
|
137
|
-
|
|
138
|
-
如果需要更灵活地控制插件结构,也可以手动创建插件文件。
|
|
139
|
-
|
|
140
|
-
1. 在 `lib/plugins` 目录下创建一个新的 JavaScript 文件,例如 `my-plugin.js`
|
|
141
|
-
2. 实现插件类,包含必要的方法
|
|
142
|
-
|
|
143
|
-
### 插件结构
|
|
144
|
-
|
|
145
|
-
#### 基本插件结构
|
|
146
|
-
|
|
147
|
-
使用 `plugin create` 命令生成的插件模板包含以下结构:
|
|
148
|
-
|
|
149
|
-
```javascript
|
|
150
|
-
/**
|
|
151
|
-
* hello-world 插件
|
|
152
|
-
* 用于实现 hello-world 相关功能
|
|
153
|
-
*
|
|
154
|
-
* 命令说明:
|
|
155
|
-
* - helloWorld [options]:hello-world 相关功能
|
|
156
|
-
* - 示例:helloWorld
|
|
157
|
-
*
|
|
158
|
-
* 功能说明:
|
|
159
|
-
* - 实现 hello-world 相关功能
|
|
160
|
-
*
|
|
161
|
-
* 用户体验:
|
|
162
|
-
* - 使用标准化的用户提示
|
|
163
|
-
* - 提供清晰的错误提示
|
|
164
|
-
* - 支持命令行参数
|
|
165
|
-
*/
|
|
166
|
-
|
|
167
|
-
const BasePlugin = require('../core/base-plugin');
|
|
168
|
-
|
|
169
|
-
class HelloWorldPlugin extends BasePlugin {
|
|
170
|
-
constructor(options = {}) {
|
|
171
|
-
super(options);
|
|
172
|
-
this.pluginName = 'hello-world';
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
/**
|
|
176
|
-
* 注册命令
|
|
177
|
-
* @param {Object} program - Commander.js 实例
|
|
178
|
-
*/
|
|
179
|
-
registerCommands(program) {
|
|
180
|
-
program.command('helloWorld')
|
|
181
|
-
.description('hello-world 相关功能')
|
|
182
|
-
.option('-v, --verbose', '显示详细信息')
|
|
183
|
-
.option('-h, --help', '显示帮助信息')
|
|
184
|
-
.action((options) => this.helloWorldCommand(options));
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
/**
|
|
188
|
-
* hello-world 命令
|
|
189
|
-
* @param {Object} options - 命令选项
|
|
190
|
-
*/
|
|
191
|
-
helloWorldCommand(options) {
|
|
192
|
-
console.log('hello-world 命令执行成功!');
|
|
193
|
-
if (options && options.verbose) {
|
|
194
|
-
console.log('详细信息:');
|
|
195
|
-
console.log('- 命令名称:', 'helloWorld');
|
|
196
|
-
console.log('- 执行时间:', new Date().toLocaleString());
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
module.exports = HelloWorldPlugin;
|
|
202
|
-
```
|
|
203
|
-
|
|
204
|
-
#### 命令注册
|
|
205
|
-
|
|
206
|
-
插件必须实现 `registerCommands` 方法,用于向 Commander.js 注册命令。
|
|
207
|
-
|
|
208
|
-
##### 基本命令注册
|
|
209
|
-
|
|
210
|
-
```javascript
|
|
211
|
-
registerCommands(program) {
|
|
212
|
-
program.command('helloWorld')
|
|
213
|
-
.description('hello-world 相关功能')
|
|
214
|
-
.action(() => this.helloWorldCommand());
|
|
215
|
-
}
|
|
216
|
-
```
|
|
217
|
-
|
|
218
|
-
##### 带选项的命令注册
|
|
219
|
-
|
|
220
|
-
```javascript
|
|
221
|
-
registerCommands(program) {
|
|
222
|
-
program.command('helloWorld [alias]')
|
|
223
|
-
.alias('hw')
|
|
224
|
-
.description('hello-world 相关功能')
|
|
225
|
-
.option('-v, --verbose', '显示详细信息')
|
|
226
|
-
.option('-n, --name <name>', '指定名称')
|
|
227
|
-
.action((alias, options) => this.helloWorldCommand(alias, options));
|
|
228
|
-
}
|
|
229
|
-
```
|
|
230
|
-
|
|
231
|
-
#### 命令选项
|
|
232
|
-
|
|
233
|
-
可以为命令添加各种选项,以增强命令的灵活性。
|
|
234
|
-
|
|
235
|
-
##### 常用选项类型
|
|
236
|
-
|
|
237
|
-
- **布尔选项**:不需要参数的选项
|
|
238
|
-
```javascript
|
|
239
|
-
.option('-v, --verbose', '显示详细信息')
|
|
240
|
-
```
|
|
241
|
-
|
|
242
|
-
- **值选项**:需要参数的选项
|
|
243
|
-
```javascript
|
|
244
|
-
.option('-n, --name <name>', '指定名称')
|
|
245
|
-
```
|
|
246
|
-
|
|
247
|
-
- **数组选项**:可以接收多个值的选项
|
|
248
|
-
```javascript
|
|
249
|
-
.option('-a, --array <items...>', '指定数组参数')
|
|
250
|
-
```
|
|
251
|
-
|
|
252
|
-
- **带默认值的选项**:
|
|
253
|
-
```javascript
|
|
254
|
-
.option('-p, --port <port>', '指定端口', '3000')
|
|
255
|
-
```
|
|
256
|
-
|
|
257
|
-
- **带验证器的选项**:
|
|
258
|
-
```javascript
|
|
259
|
-
.option('-p, --port <port>', '指定端口', parseInt)
|
|
260
|
-
```
|
|
261
|
-
|
|
262
|
-
### 插件配置
|
|
157
|
+
#### 新格式插件特点
|
|
263
158
|
|
|
264
|
-
|
|
159
|
+
- **配置对象格式**:使用配置对象定义插件的基本信息和命令
|
|
160
|
+
- **包含类结构实现**:核心功能通过类结构实现,提高代码模块化和可维护性
|
|
161
|
+
- **自动生成命令名称**:根据插件名称自动生成驼峰命名的命令名称
|
|
162
|
+
- **标准的用户提示**:使用标准化的用户提示和错误处理
|
|
265
163
|
|
|
266
|
-
####
|
|
164
|
+
#### 详细文档
|
|
267
165
|
|
|
268
|
-
|
|
166
|
+
完整的新格式插件开发指南请参考:[新格式插件开发教程](./plugin-development-new.md)
|
|
269
167
|
|
|
270
|
-
|
|
271
|
-
~/.xx/
|
|
272
|
-
└── hello-world/
|
|
273
|
-
└── config.json
|
|
274
|
-
```
|
|
275
|
-
|
|
276
|
-
#### 读取配置
|
|
277
|
-
|
|
278
|
-
```javascript
|
|
279
|
-
const fs = require('fs');
|
|
280
|
-
const path = require('path');
|
|
281
|
-
|
|
282
|
-
// 获取用户主目录
|
|
283
|
-
const homeDir = process.env.HOME || process.env.USERPROFILE;
|
|
284
|
-
const xxDir = path.join(homeDir, '.xx-cli');
|
|
285
|
-
const pluginConfigDir = path.join(xxDir, this.pluginName);
|
|
286
|
-
const configFile = path.join(pluginConfigDir, 'config.json');
|
|
287
|
-
|
|
288
|
-
// 读取配置
|
|
289
|
-
let config = {};
|
|
290
|
-
if (fs.existsSync(configFile)) {
|
|
291
|
-
config = JSON.parse(fs.readFileSync(configFile, 'utf8'));
|
|
292
|
-
}
|
|
293
|
-
```
|
|
294
|
-
|
|
295
|
-
#### 写入配置
|
|
296
|
-
|
|
297
|
-
```javascript
|
|
298
|
-
const fs = require('fs');
|
|
299
|
-
const path = require('path');
|
|
300
|
-
|
|
301
|
-
// 确保配置目录存在
|
|
302
|
-
fs.ensureDirSync(pluginConfigDir);
|
|
303
|
-
|
|
304
|
-
// 写入配置
|
|
305
|
-
fs.writeFileSync(configFile, JSON.stringify(config, null, 2));
|
|
306
|
-
```
|
|
168
|
+
### 旧格式插件开发(仅用于向后兼容)
|
|
307
169
|
|
|
308
|
-
|
|
170
|
+
旧格式插件需要继承 `BasePlugin` 类,主要用于向后兼容已有的插件。
|
|
309
171
|
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
#### 基础插件类路径
|
|
313
|
-
|
|
314
|
-
`BasePlugin` 类位于 `/Users/xub/xx-cli/lib/core/base-plugin.js`,插件可以通过以下方式导入:
|
|
315
|
-
|
|
316
|
-
```javascript
|
|
317
|
-
const BasePlugin = require('../core/base-plugin');
|
|
318
|
-
```
|
|
319
|
-
|
|
320
|
-
#### 核心功能
|
|
321
|
-
|
|
322
|
-
`BasePlugin` 类提供了以下核心功能:
|
|
323
|
-
|
|
324
|
-
##### 1. 命令注册
|
|
325
|
-
|
|
326
|
-
- **`registerCommands(program)`**:注册命令到 Commander.js 实例,子类必须实现此方法
|
|
327
|
-
|
|
328
|
-
##### 2. 插件初始化
|
|
329
|
-
|
|
330
|
-
- **`init()`**:插件初始化逻辑,子类可以覆盖
|
|
331
|
-
- **`getInfo()`**:获取插件信息
|
|
332
|
-
|
|
333
|
-
##### 3. 用户界面
|
|
334
|
-
|
|
335
|
-
- **`startLoading(text)`**:显示加载状态
|
|
336
|
-
- **`stopLoading(text)`**:停止加载状态
|
|
337
|
-
- **`showError(text)`**:显示错误信息
|
|
338
|
-
- **`startProgressBar(text, total)`**:启动进度条
|
|
339
|
-
- **`updateProgressBar(current, text)`**:更新进度条
|
|
340
|
-
- **`stopProgressBar(text)`**:停止进度条
|
|
341
|
-
- **`showSuccess(text)`**:显示成功信息
|
|
342
|
-
- **`showWarning(text)`**:显示警告信息
|
|
343
|
-
- **`showInfo(text)`**:显示信息
|
|
344
|
-
|
|
345
|
-
##### 4. 配置管理
|
|
346
|
-
|
|
347
|
-
- **`loadConfig(configName, cliOptions)`**:加载配置
|
|
348
|
-
- **`saveConfig(config, configName, isGlobal)`**:保存配置
|
|
349
|
-
|
|
350
|
-
##### 5. 错误处理
|
|
351
|
-
|
|
352
|
-
- **`handleError(error, message)`**:处理错误
|
|
353
|
-
|
|
354
|
-
##### 6. 异步操作
|
|
355
|
-
|
|
356
|
-
- **`executeAsync(fn, loadingText, successText, errorText)`**:执行异步操作并显示加载状态
|
|
357
|
-
|
|
358
|
-
##### 7. 钩子系统
|
|
359
|
-
|
|
360
|
-
- **`registerHook(event, callback)`**:注册钩子
|
|
361
|
-
- **`triggerHook(event, data)`**:触发钩子
|
|
362
|
-
- **`hasHook(event)`**:检查是否注册了指定钩子
|
|
363
|
-
|
|
364
|
-
##### 8. 剪贴板操作
|
|
365
|
-
|
|
366
|
-
- **`copyToClipboard(text, successMessage)`**:复制文本到剪贴板
|
|
367
|
-
|
|
368
|
-
#### 使用示例
|
|
369
|
-
|
|
370
|
-
```javascript
|
|
371
|
-
const BasePlugin = require('../core/base-plugin');
|
|
372
|
-
|
|
373
|
-
class MyPlugin extends BasePlugin {
|
|
374
|
-
constructor(options = {}) {
|
|
375
|
-
super(options);
|
|
376
|
-
this.pluginName = 'my-plugin';
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
registerCommands(program) {
|
|
380
|
-
program.command('mycommand')
|
|
381
|
-
.description('My plugin command')
|
|
382
|
-
.action(() => this.myCommand());
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
async myCommand() {
|
|
386
|
-
try {
|
|
387
|
-
await this.executeAsync(
|
|
388
|
-
async () => {
|
|
389
|
-
// 执行异步操作
|
|
390
|
-
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
391
|
-
return '操作结果';
|
|
392
|
-
},
|
|
393
|
-
'执行操作...',
|
|
394
|
-
'操作成功',
|
|
395
|
-
'操作失败'
|
|
396
|
-
);
|
|
397
|
-
} catch (error) {
|
|
398
|
-
this.handleError(error, '执行命令失败');
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
module.exports = MyPlugin;
|
|
404
|
-
```
|
|
405
|
-
|
|
406
|
-
### 插件生命周期
|
|
407
|
-
|
|
408
|
-
插件的生命周期包括:
|
|
409
|
-
|
|
410
|
-
1. **初始化**:插件被加载时
|
|
411
|
-
2. **命令注册**:调用 `registerCommands` 方法
|
|
412
|
-
3. **命令执行**:用户运行插件命令时
|
|
413
|
-
4. **清理**:命令执行完成后
|
|
414
|
-
|
|
415
|
-
### 测试插件
|
|
416
|
-
|
|
417
|
-
#### 本地测试
|
|
418
|
-
|
|
419
|
-
1. 创建插件:
|
|
420
|
-
```bash
|
|
421
|
-
xx plugin create <plugin-name>
|
|
422
|
-
```
|
|
423
|
-
|
|
424
|
-
2. 编辑插件文件,实现具体功能
|
|
425
|
-
|
|
426
|
-
3. 运行插件命令:
|
|
427
|
-
```bash
|
|
428
|
-
# 直接运行
|
|
429
|
-
node bin/cli.js <plugin-command>
|
|
430
|
-
|
|
431
|
-
# 或者使用 xx 命令(如果已全局安装)
|
|
432
|
-
xx <plugin-command>
|
|
433
|
-
```
|
|
434
|
-
|
|
435
|
-
#### 测试命令选项
|
|
172
|
+
#### 创建旧格式插件
|
|
436
173
|
|
|
437
174
|
```bash
|
|
438
|
-
#
|
|
439
|
-
xx <plugin-
|
|
440
|
-
|
|
441
|
-
# 测试值选项
|
|
442
|
-
xx <plugin-command> --name John
|
|
443
|
-
|
|
444
|
-
# 测试组合选项
|
|
445
|
-
xx <plugin-command> --verbose --name John
|
|
175
|
+
# 创建旧格式插件
|
|
176
|
+
xx plugin create <plugin-name> --format old
|
|
446
177
|
```
|
|
447
178
|
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
#### 发布到插件目录
|
|
451
|
-
|
|
452
|
-
1. 确保插件文件位于 `lib/plugins` 目录
|
|
453
|
-
2. 运行 `xx plugin list` 命令,确认插件已被识别
|
|
454
|
-
3. 插件会自动加载并注册到命令系统中
|
|
455
|
-
|
|
456
|
-
#### 分享插件
|
|
457
|
-
|
|
458
|
-
如果要与他人分享插件,可以:
|
|
459
|
-
|
|
460
|
-
1. 将插件文件发送给他人
|
|
461
|
-
2. 他人将插件文件放入其 `lib/plugins` 目录
|
|
462
|
-
3. 运行 `xx plugin list` 命令,确认插件已被识别
|
|
463
|
-
|
|
464
|
-
#### 从外部添加插件
|
|
465
|
-
|
|
466
|
-
可以使用 `plugin add` 命令从 URL 或本地文件添加插件:
|
|
467
|
-
|
|
468
|
-
```bash
|
|
469
|
-
# 从 URL 添加插件
|
|
470
|
-
xx plugin add https://example.com/my-plugin.js
|
|
179
|
+
#### 详细文档
|
|
471
180
|
|
|
472
|
-
|
|
473
|
-
xx plugin add /path/to/my-plugin.js
|
|
474
|
-
```
|
|
181
|
+
完整的旧格式插件开发指南请参考:[旧格式插件开发教程](./plugin-development-old.md)
|