@xubill/xx-cli 2.0.0 → 2.0.2

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/AGENTS.md ADDED
@@ -0,0 +1,177 @@
1
+ # AGENTS.md
2
+
3
+ 本文档描述 xx-cli 项目中各个核心模块/代理的职责和交互关系。
4
+
5
+ ## 项目概述
6
+
7
+ xx-cli 是一个基于 Node.js 的命令行工具集,提供丰富的开发辅助功能。采用插件化架构,支持自定义插件开发和动态命令加载。
8
+
9
+ ## 核心模块
10
+
11
+ ### 1. Core (核心管理器)
12
+
13
+ **文件位置**: `lib/core/index.js`
14
+
15
+ **职责**:
16
+ - 初始化 CLI 系统环境
17
+ - 加载和管理插件(内置插件 + 用户插件)
18
+ - 注册命令到 Commander.js 框架
19
+ - 实现命令自动建议功能(当用户输入错误命令时提供相似命令建议)
20
+ - 管理全局钩子系统
21
+
22
+ **关键方法**:
23
+ - `init()`: 初始化核心功能
24
+ - `loadPlugins()`: 扫描并加载插件目录
25
+ - `loadPlugin(pluginFile)`: 加载单个插件,支持缓存
26
+ - `registerCommands(program)`: 注册所有命令
27
+ - `registerNewFormatPlugin()`: 注册新格式插件
28
+ - `registerCommandSuggestions()`: 注册命令自动建议
29
+ - `collectAllCommands()`: 收集所有可用命令
30
+ - `getCommandSuggestions()`: 获取命令建议
31
+ - `registerHook()` / `triggerHook()`: 钩子系统
32
+
33
+ ### 2. BasePlugin (插件基类)
34
+
35
+ **文件位置**: `lib/core/base-plugin.js`
36
+
37
+ **职责**:
38
+ - 提供插件标准化接口
39
+ - 实现通用功能(加载状态、进度条、错误处理等)
40
+ - 提供配置管理和验证能力
41
+ - 实现钩子系统
42
+
43
+ **关键方法**:
44
+ - `registerCommands(program)`: 注册命令(抽象方法,子类必须实现)
45
+ - `init()`: 初始化插件
46
+ - `startLoading()` / `stopLoading()`: 加载状态管理
47
+ - `startProgressBar()` / `updateProgressBar()` / `stopProgressBar()`: 进度条管理
48
+ - `showSuccess()` / `showWarning()` / `showError()` / `showInfo()`: 消息展示
49
+ - `loadConfig()` / `saveConfig()` / `validateConfig()`: 配置管理
50
+ - `handleError()`: `executeAsync()`: 异步操作封装错误处理
51
+ -
52
+ - `registerHook()` / `triggerHook()`: 钩子系统
53
+ - `copyToClipboard()`: 剪贴板操作
54
+
55
+ ### 3. PluginsHelper (插件辅助工具)
56
+
57
+ **文件位置**: `lib/utils/plugins-helper.js`
58
+
59
+ **职责**:
60
+ - 为新格式插件(非类继承)提供与 BasePlugin 相同的通用功能
61
+ - 无需继承即可使用插件能力
62
+
63
+ **关键方法**: 与 BasePlugin 相同(详见上方)
64
+
65
+ ### 4. ConfigManager (配置管理器)
66
+
67
+ **文件位置**: `lib/utils/config-manager.js`
68
+
69
+ **职责**:
70
+ - 管理插件配置文件(JSON 格式)
71
+ - 实现配置优先级:命令行 > 配置文件 > 默认配置
72
+ - 使用 Joi 进行配置验证
73
+ - 支持全局配置和本地配置
74
+
75
+ **关键方法**:
76
+ - `loadConfig()`: 加载配置
77
+ - `saveConfig()`: 保存配置
78
+ - `validateConfig()`: 验证配置
79
+ - `getConfigPath()`: 获取配置路径
80
+ - `mergeConfig()`: 合并配置
81
+
82
+ ### 5. PluginConfig (插件配置)
83
+
84
+ **文件位置**: `lib/utils/plugin-config.js`
85
+
86
+ **职责**:
87
+ - 管理插件的启用/禁用状态
88
+ - 提供插件配置文件路径
89
+
90
+ **关键方法**:
91
+ - `isPluginDisabled()`: 检查插件是否禁用
92
+ - `getPluginConfigPath()`: 获取插件配置路径
93
+
94
+ ## 插件类型
95
+
96
+ ### 核心插件 (Core Plugins)
97
+
98
+ 位于 `lib/plugins/`
99
+
100
+ | 插件名称 | 功能描述 |
101
+ |---------|---------|
102
+ | config-manager | 配置管理 |
103
+ | history | 命令历史记录 |
104
+ | plugin-manager | 插件管理 |
105
+
106
+ ### 功能插件 (User Plugins)
107
+ 不要修改../plugins的引入,这个是核心代码。myplugins我会复制到安装目录的,不需要你操作,你只管生成就好。
108
+ 位于 `lib/myplugins/`
109
+
110
+
111
+ ## 插件开发格式
112
+
113
+ ### 新格式 (推荐)
114
+
115
+ 使用配置对象方式,无需继承类:
116
+
117
+ ```javascript
118
+ module.exports = {
119
+ name: 'plugin-name',
120
+ description: '插件描述',
121
+ alias: '别名',
122
+ options: [
123
+ { name: '-o, --option', description: '选项描述' }
124
+ ],
125
+ action: async (args, options, helper) => {
126
+ // 插件逻辑
127
+ }
128
+ };
129
+ ```
130
+
131
+ ### 旧格式 (向后兼容)
132
+
133
+ 使用类继承方式:
134
+
135
+ ```javascript
136
+ const BasePlugin = require('../core/base-plugin');
137
+
138
+ class MyPlugin extends BasePlugin {
139
+ registerCommands(program) {
140
+ program.command('my-plugin')
141
+ .description('我的插件')
142
+ .action(() => { /* 插件逻辑 */ });
143
+ }
144
+ }
145
+
146
+ module.exports = MyPlugin;
147
+ ```
148
+
149
+ ## 交互流程
150
+
151
+ ```
152
+ 用户输入命令
153
+
154
+ bin/cli.js 入口
155
+
156
+ Commander.js 解析
157
+
158
+ Core.registerCommands() 注册命令
159
+
160
+ 插件 action 执行
161
+
162
+ PluginsHelper/BasePlugin 提供工具方法
163
+
164
+ 命令完成,输出结果
165
+ ```
166
+
167
+ ## 错误处理
168
+
169
+ - **命令不存在**: 通过 `registerCommandSuggestions` 提供相似命令建议
170
+ - **插件加载失败**: 捕获错误并跳过该插件,继续加载其他插件
171
+ - **配置错误**: 使用 Joi 验证并给出清晰错误信息
172
+
173
+ ## 配置优先级
174
+
175
+ ```
176
+ 命令行选项 > 本地配置文件 > 全局配置文件 > 默认配置
177
+ ```
package/README.md ADDED
@@ -0,0 +1,181 @@
1
+ # xx-cli
2
+
3
+ 个人开发工具集,支持插件系统,提供常用开发工具功能。
4
+
5
+ ## 安装与使用
6
+
7
+ ```bash
8
+ # 全局安装 xx-cli
9
+ npm i @xubill/xx-cli -g
10
+
11
+ # 添加插件
12
+ xx p add xxxx.js
13
+
14
+ # 使用命令
15
+ xx <command> [options]
16
+ ```
17
+
18
+ ## 版本记录
19
+
20
+ ### v2.0.0
21
+ - 支持新格式命令注册,兼容旧格式插件
22
+ - 更新插件创建模板,采用配置对象格式并包含类结构实现
23
+
24
+ ### v2.0.1
25
+ - 新增ai插件,解析自然语言为xx命令
26
+
27
+ ## 框架自带命令
28
+
29
+ xx-cli 框架自带以下核心命令(位于 core 模块中):
30
+
31
+ ### 基础命令
32
+
33
+ | 命令 | 别名 | 描述 |
34
+ |------|------|------|
35
+ | `help` | - | 显示帮助信息 |
36
+ | `version` | `v` | 显示版本信息 |
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
+ ```
68
+
69
+ ### 插件管理命令
70
+
71
+ | 命令 | 别名 | 描述 |
72
+ |------|------|------|
73
+ | `plugin list` | `p ls` | 列出所有插件 |
74
+ | `plugin enable <plugin>` | `p en <plugin>` | 启用插件 |
75
+ | `plugin disable <plugin>` | `p dis <plugin>` | 禁用插件 |
76
+ | `plugin add <url>` | `p add <url>` | 添加外部自定义插件 |
77
+ | `plugin remove <plugin>` | `p rm <plugin>` | 删除指定插件 |
78
+ | `plugin create <name>` | `p cr <name>` | 创建指定名称的插件模板 |
79
+ | `plugin config <plugin> [key] [value]` | `p c <plugin> [key] [value]` | 查看和设置插件配置 |
80
+
81
+ ### 配置管理命令
82
+
83
+ | 命令 | 别名 | 描述 |
84
+ |------|------|------|
85
+ | `config-manager export [target]` | `conf export [target]` | 导出所有插件配置到指定目录 |
86
+ | `config-manager import [source]` | `conf import [source]` | 从指定目录导入配置并覆盖 |
87
+ | `config-manager list` | `conf list` | 列出所有插件的配置文件位置和状态 |
88
+
89
+ ## 项目结构
90
+
91
+ xx-cli 项目采用模块化设计,主要包含以下核心目录:
92
+
93
+ ### 核心模块目录 (`/Users/xub/xx-cli/lib/core`)
94
+
95
+ 核心模块目录包含 xx-cli 的核心功能实现,负责初始化系统、注册命令、管理插件等。
96
+
97
+ #### 文件结构
98
+
99
+ ```
100
+ lib/core/
101
+ ├── index.js # 核心模块,负责初始化系统、注册命令、管理插件等
102
+ └── base-plugin.js # 插件基础类,提供标准化的插件接口和通用功能
103
+ ```
104
+
105
+ #### 核心文件说明
106
+
107
+ - **index.js**:核心模块,负责初始化系统、注册命令、管理插件等。它包含了插件加载、命令注册、钩子管理等核心功能。
108
+ - **base-plugin.js**:插件基础类,提供标准化的插件接口和通用功能。所有插件应该继承此类以确保一致性,它提供了命令注册、配置管理、用户界面等通用功能。
109
+
110
+ ### 插件目录 (`/Users/xub/xx-cli/lib/plugins`)
111
+
112
+ 插件目录包含 xx-cli 的内置插件,这些插件提供了各种功能,如配置管理、历史记录管理、插件管理等。
113
+
114
+ #### 文件结构
115
+
116
+ ```
117
+ lib/plugins/
118
+ ├── config-manager.js # 配置管理插件,用于管理所有插件的配置文件
119
+ ├── history.js # 历史记录插件,用于查看命令历史记录
120
+ └── plugin-manager.js # 插件管理插件,用于管理所有插件
121
+ ```
122
+
123
+ #### 内置插件说明
124
+
125
+ - **config-manager.js**:配置管理插件,用于管理所有插件的配置文件。它提供了导出、导入、列出配置等功能。
126
+ - **history.js**:历史记录插件,用于查看命令历史记录。它提供了查看、清除、搜索历史记录等功能。
127
+ - **plugin-manager.js**:插件管理插件,用于管理所有插件。它提供了列出、启用、禁用、添加、删除、创建插件等功能。
128
+ - **ai.js**:AI 智能解释插件,用于解释 xx-cli 命令的含义,将自然语言转换为命令。它提供了智能解释、命令兜底等功能。
129
+
130
+ ## 插件开发
131
+
132
+ 本部分将详细介绍如何在 xx-cli 中创建、开发和部署插件。
133
+
134
+ ### 插件格式
135
+
136
+ xx-cli 支持两种插件格式:
137
+
138
+ 1. **新格式(配置对象格式)**:使用配置对象定义的插件实现(推荐)
139
+ 2. **旧格式(类结构格式)**:继承自 `BasePlugin` 类的插件实现(仅用于向后兼容)
140
+
141
+ ### 新格式插件开发(推荐)
142
+
143
+ 新格式插件使用配置对象定义插件信息和命令,结合类结构实现核心功能,是推荐的插件开发方式。
144
+
145
+ #### 创建新格式插件
146
+
147
+ ```bash
148
+ # 创建新格式插件(默认)
149
+ xx plugin create <plugin-name>
150
+
151
+ # 或者使用别名
152
+ xx p create <plugin-name>
153
+ # 或者使用更短的别名
154
+ xx p cr <plugin-name>
155
+ ```
156
+
157
+ #### 新格式插件特点
158
+
159
+ - **配置对象格式**:使用配置对象定义插件的基本信息和命令
160
+ - **包含类结构实现**:核心功能通过类结构实现,提高代码模块化和可维护性
161
+ - **自动生成命令名称**:根据插件名称自动生成驼峰命名的命令名称
162
+ - **标准的用户提示**:使用标准化的用户提示和错误处理
163
+
164
+ #### 详细文档
165
+
166
+ 完整的新格式插件开发指南请参考:[新格式插件开发教程](./plugin-development-new.md)
167
+
168
+ ### 旧格式插件开发(仅用于向后兼容)
169
+
170
+ 旧格式插件需要继承 `BasePlugin` 类,主要用于向后兼容已有的插件。
171
+
172
+ #### 创建旧格式插件
173
+
174
+ ```bash
175
+ # 创建旧格式插件
176
+ xx plugin create <plugin-name> --format old
177
+ ```
178
+
179
+ #### 详细文档
180
+
181
+ 完整的旧格式插件开发指南请参考:[旧格式插件开发教程](./plugin-development-old.md)
package/lib/core/index.js CHANGED
@@ -229,6 +229,7 @@ class Core {
229
229
  `警告: 插件 ${pluginName} 的命令别名与其他插件冲突,已跳过此插件的命令注册`,
230
230
  );
231
231
  } else {
232
+ console.log(error)
232
233
  console.error(
233
234
  `错误: 插件 ${pluginName} 注册命令失败: ${error.message}`,
234
235
  );
@@ -362,7 +363,7 @@ class Core {
362
363
  const allCommands = this.collectAllCommands(program);
363
364
 
364
365
  // 添加命令自动建议
365
- program.on("command:*", (args) => {
366
+ program.on("command:*", async (args) => {
366
367
  const inputCommand = args[0];
367
368
  const suggestions = this.getCommandSuggestions(inputCommand, allCommands);
368
369
 
@@ -371,6 +372,37 @@ class Core {
371
372
  suggestions.forEach((suggestion) => {
372
373
  console.log(` - ${suggestion}`);
373
374
  });
375
+ console.log("");
376
+ process.exit(1);
377
+ } else {
378
+ // 如果没有建议,也显示错误信息
379
+ console.log(`\n未找到命令 "${inputCommand}"。`);
380
+ console.log('使用 "xx help" 查看所有可用命令。');
381
+
382
+ // 自动调用 AI 解释命令作为兜底
383
+ console.log('\n正在调用 AI 解释您的输入...');
384
+
385
+ try {
386
+ // 动态导入 ai 插件
387
+ const aiPath = path.join(__dirname, '../plugins/ai.js');
388
+ if (fs.existsSync(aiPath)) {
389
+ const AIPlugin = require(aiPath);
390
+ if (AIPlugin.prototype && typeof AIPlugin === 'function') {
391
+ // 类继承格式插件
392
+ const pluginInstance = new AIPlugin();
393
+ if (pluginInstance.handleAI) {
394
+ await pluginInstance.handleAI(args, {});
395
+ }
396
+ } else if (AIPlugin.action) {
397
+ // 配置对象格式插件
398
+ await AIPlugin.action(args, {});
399
+ }
400
+ }
401
+ } catch (error) {
402
+ // AI 调用失败时不影响主流程
403
+ console.log('AI 解释失败:', error.message);
404
+ }
405
+
374
406
  console.log("");
375
407
  process.exit(1);
376
408
  }
@@ -388,14 +420,12 @@ class Core {
388
420
  // 收集核心命令
389
421
  if (program.commands) {
390
422
  program.commands.forEach((command) => {
423
+ // 直接使用 _name 获取命令名称
424
+ const commandName = command._name;
425
+
391
426
  // 添加命令名称
392
- if (command._name && command._name !== "*") {
393
- commands.push(command._name);
394
- }
395
-
396
- // 添加命令别名
397
- if (command._alias) {
398
- commands.push(command._alias);
427
+ if (commandName && commandName !== "*") {
428
+ commands.push(commandName);
399
429
  }
400
430
  });
401
431
  }
@@ -412,7 +442,11 @@ class Core {
412
442
  getCommandSuggestions(input, commands) {
413
443
  return commands
414
444
  .filter((command) => {
415
- return command.startsWith(input.toLowerCase());
445
+ // 确保 command 是字符串类型
446
+ if (typeof command !== 'string') {
447
+ return false;
448
+ }
449
+ return command.toLowerCase().startsWith(input.toLowerCase());
416
450
  })
417
451
  .slice(0, 5); // 最多返回5个建议
418
452
  }