mulby-cli 1.1.5
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/PLUGIN_DEVELOP_PROMPT.md +1164 -0
- package/README.md +852 -0
- package/assets/default-icon.png +0 -0
- package/dist/commands/ai-session.js +44 -0
- package/dist/commands/build.js +111 -0
- package/dist/commands/config-ai.js +291 -0
- package/dist/commands/config.js +53 -0
- package/dist/commands/create/ai-create.js +183 -0
- package/dist/commands/create/assets.js +53 -0
- package/dist/commands/create/basic.js +72 -0
- package/dist/commands/create/index.js +73 -0
- package/dist/commands/create/react.js +136 -0
- package/dist/commands/create/templates/basic.js +383 -0
- package/dist/commands/create/templates/react/backend.js +72 -0
- package/dist/commands/create/templates/react/config.js +166 -0
- package/dist/commands/create/templates/react/docs.js +78 -0
- package/dist/commands/create/templates/react/hooks.js +469 -0
- package/dist/commands/create/templates/react/index.js +41 -0
- package/dist/commands/create/templates/react/types.js +1228 -0
- package/dist/commands/create/templates/react/ui.js +528 -0
- package/dist/commands/create/templates/react.js +1888 -0
- package/dist/commands/dev.js +141 -0
- package/dist/commands/pack.js +160 -0
- package/dist/commands/resume.js +97 -0
- package/dist/commands/test-ui.js +50 -0
- package/dist/index.js +71 -0
- package/dist/services/ai/PLUGIN_API.md +1102 -0
- package/dist/services/ai/PLUGIN_DEVELOP_PROMPT.md +1164 -0
- package/dist/services/ai/context-manager.js +639 -0
- package/dist/services/ai/index.js +88 -0
- package/dist/services/ai/knowledge.js +52 -0
- package/dist/services/ai/prompts.js +114 -0
- package/dist/services/ai/providers/base.js +38 -0
- package/dist/services/ai/providers/claude.js +284 -0
- package/dist/services/ai/providers/deepseek.js +28 -0
- package/dist/services/ai/providers/gemini.js +191 -0
- package/dist/services/ai/providers/glm.js +31 -0
- package/dist/services/ai/providers/minimax.js +27 -0
- package/dist/services/ai/providers/openai.js +177 -0
- package/dist/services/ai/tools.js +204 -0
- package/dist/services/ai-generator.js +968 -0
- package/dist/services/config-manager.js +117 -0
- package/dist/services/dependency-manager.js +236 -0
- package/dist/services/file-writer.js +66 -0
- package/dist/services/plan-adapter.js +244 -0
- package/dist/services/plan-command-handler.js +172 -0
- package/dist/services/plan-manager.js +502 -0
- package/dist/services/session-manager.js +113 -0
- package/dist/services/task-analyzer.js +136 -0
- package/dist/services/tui/index.js +57 -0
- package/dist/services/tui/store.js +123 -0
- package/dist/types/ai.js +172 -0
- package/dist/types/plan.js +2 -0
- package/dist/ui/Terminal.js +56 -0
- package/dist/ui/components/InputArea.js +176 -0
- package/dist/ui/components/LogArea.js +19 -0
- package/dist/ui/components/PlanPanel.js +69 -0
- package/dist/ui/components/SelectArea.js +13 -0
- package/package.json +45 -0
package/README.md
ADDED
|
@@ -0,0 +1,852 @@
|
|
|
1
|
+
# Mulby CLI
|
|
2
|
+
|
|
3
|
+
Mulby 插件开发的命令行工具,帮助你快速创建、调试、构建和打包插件。
|
|
4
|
+
|
|
5
|
+
## 目录
|
|
6
|
+
|
|
7
|
+
- [安装](#安装)
|
|
8
|
+
- [快速开始](#快速开始)
|
|
9
|
+
- [命令参考](#命令参考)
|
|
10
|
+
- [插件开发指南](#插件开发指南)
|
|
11
|
+
- [项目结构](#项目结构)
|
|
12
|
+
- [manifest.json 配置](#manifestjson-配置)
|
|
13
|
+
- [动态功能入口](#动态功能入口)
|
|
14
|
+
- [开发模式](#开发模式)
|
|
15
|
+
- [使用第三方库](#使用第三方库)
|
|
16
|
+
- [插件 API](#插件-api)
|
|
17
|
+
- [构建与打包](#构建与打包)
|
|
18
|
+
- [完整示例](#完整示例)
|
|
19
|
+
- [AI 任务规划](#ai-任务规划)
|
|
20
|
+
- [常见问题](#常见问题)
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## 安装
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
# 全局安装
|
|
28
|
+
npm install -g mulby-cli
|
|
29
|
+
|
|
30
|
+
# 或在项目中作为开发依赖
|
|
31
|
+
npm install -D mulby-cli
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## 快速开始
|
|
37
|
+
|
|
38
|
+
### 5 分钟创建你的第一个插件
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
# 1. 创建插件项目
|
|
42
|
+
mulby create my-plugin
|
|
43
|
+
|
|
44
|
+
# 2. 进入项目目录
|
|
45
|
+
cd my-plugin
|
|
46
|
+
|
|
47
|
+
# 3. 安装依赖
|
|
48
|
+
npm install
|
|
49
|
+
|
|
50
|
+
# 4. 启动开发模式
|
|
51
|
+
npm run dev
|
|
52
|
+
|
|
53
|
+
# 5. 构建插件
|
|
54
|
+
npm run build
|
|
55
|
+
|
|
56
|
+
# 6. 打包发布
|
|
57
|
+
npm run pack
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
执行完成后,你将得到一个 `my-plugin-1.0.0.inplugin` 文件,可以直接安装到 Mulby 中。
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## 命令参考
|
|
65
|
+
|
|
66
|
+
### `mulby create <name>`
|
|
67
|
+
|
|
68
|
+
创建新的插件项目。
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
# 创建 React 插件(默认,带 UI)
|
|
72
|
+
mulby create my-plugin
|
|
73
|
+
|
|
74
|
+
# 创建基础插件(无 UI)
|
|
75
|
+
mulby create my-plugin --template basic
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**选项:**
|
|
79
|
+
|
|
80
|
+
| 选项 | 说明 | 默认值 |
|
|
81
|
+
|------|------|--------|
|
|
82
|
+
| `-t, --template <type>` | 模板类型:`react` 或 `basic` | `react` |
|
|
83
|
+
|
|
84
|
+
### `mulby dev`
|
|
85
|
+
|
|
86
|
+
启动开发模式,支持热重载。
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
# 在插件目录中运行
|
|
90
|
+
mulby dev
|
|
91
|
+
|
|
92
|
+
# 或通过 npm
|
|
93
|
+
npm run dev
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
**功能:**
|
|
97
|
+
- 后端代码变化时自动重新构建
|
|
98
|
+
- 有 UI 的插件会自动启动 Vite 开发服务器
|
|
99
|
+
- 支持 sourcemap 便于调试
|
|
100
|
+
|
|
101
|
+
### `mulby build`
|
|
102
|
+
|
|
103
|
+
构建插件,生成生产环境代码。
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
mulby build
|
|
107
|
+
|
|
108
|
+
# 或通过 npm
|
|
109
|
+
npm run build
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
**输出:**
|
|
113
|
+
- 后端代码:`dist/main.js`(压缩后)
|
|
114
|
+
- UI 代码:`ui/` 目录
|
|
115
|
+
|
|
116
|
+
### `mulby pack`
|
|
117
|
+
|
|
118
|
+
将插件打包成 `.inplugin` 文件,用于发布和安装。
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
mulby pack
|
|
122
|
+
|
|
123
|
+
# 或通过 npm
|
|
124
|
+
npm run pack
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
**输出:** `<插件名>-<版本号>.inplugin`
|
|
128
|
+
|
|
129
|
+
> ⚠️ **注意:** 打包前请先运行 `mulby build` 或 `npm run build`
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## 插件开发指南
|
|
134
|
+
|
|
135
|
+
### 项目结构
|
|
136
|
+
|
|
137
|
+
#### React 插件(默认模板)
|
|
138
|
+
|
|
139
|
+
```
|
|
140
|
+
my-plugin/
|
|
141
|
+
├── package.json # npm 配置
|
|
142
|
+
├── manifest.json # 插件配置(核心文件)
|
|
143
|
+
├── tsconfig.json # TypeScript 配置
|
|
144
|
+
├── vite.config.ts # Vite 配置
|
|
145
|
+
├── icon.png # 插件图标
|
|
146
|
+
├── src/
|
|
147
|
+
│ ├── main.ts # 后端逻辑(沙箱运行)
|
|
148
|
+
│ ├── types/
|
|
149
|
+
│ │ └── mulby.d.ts # API 类型定义
|
|
150
|
+
│ └── ui/ # React UI 源码
|
|
151
|
+
│ ├── index.html
|
|
152
|
+
│ ├── main.tsx
|
|
153
|
+
│ ├── App.tsx
|
|
154
|
+
│ ├── hooks/
|
|
155
|
+
│ │ └── useMulby.ts
|
|
156
|
+
│ └── styles.css
|
|
157
|
+
├── dist/ # 后端构建输出
|
|
158
|
+
│ └── main.js
|
|
159
|
+
└── ui/ # UI 构建输出
|
|
160
|
+
├── index.html
|
|
161
|
+
└── assets/
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
#### 基础插件(无 UI)
|
|
165
|
+
|
|
166
|
+
```
|
|
167
|
+
my-plugin/
|
|
168
|
+
├── package.json
|
|
169
|
+
├── manifest.json
|
|
170
|
+
├── icon.png
|
|
171
|
+
└── src/
|
|
172
|
+
└── main.ts
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
### manifest.json 配置
|
|
178
|
+
|
|
179
|
+
`manifest.json` 是插件的核心配置文件,定义了插件的基本信息和触发条件。
|
|
180
|
+
|
|
181
|
+
```json
|
|
182
|
+
{
|
|
183
|
+
"id": "my-plugin",
|
|
184
|
+
"name": "my-plugin",
|
|
185
|
+
"version": "1.0.0",
|
|
186
|
+
"type": "utility",
|
|
187
|
+
"displayName": "我的插件",
|
|
188
|
+
"description": "插件功能描述",
|
|
189
|
+
"main": "dist/main.js",
|
|
190
|
+
"ui": "ui/index.html",
|
|
191
|
+
"icon": "icon.png",
|
|
192
|
+
"pluginSetting": {
|
|
193
|
+
"single": true,
|
|
194
|
+
"height": 400
|
|
195
|
+
},
|
|
196
|
+
"window": {
|
|
197
|
+
"width": 800,
|
|
198
|
+
"height": 600
|
|
199
|
+
},
|
|
200
|
+
"features": [
|
|
201
|
+
{
|
|
202
|
+
"code": "main",
|
|
203
|
+
"explain": "主功能",
|
|
204
|
+
"cmds": [
|
|
205
|
+
{ "type": "keyword", "value": "myplugin" }
|
|
206
|
+
]
|
|
207
|
+
}
|
|
208
|
+
]
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
#### 顶层字段说明
|
|
213
|
+
|
|
214
|
+
| 字段 | 类型 | 必需 | 说明 |
|
|
215
|
+
|------|------|------|------|
|
|
216
|
+
| `name` | string | ✅ | 插件唯一标识(小写字母、数字、连字符) |
|
|
217
|
+
| `version` | string | ✅ | 语义化版本 (x.y.z) |
|
|
218
|
+
| `type` | string | ❌ | 插件类型 (utility/productivity/developer/system/media/network/ai/entertainment/other) |
|
|
219
|
+
| `displayName` | string | ✅ | 用户看到的名称 |
|
|
220
|
+
| `description` | string | ✅ | 功能描述 |
|
|
221
|
+
| `id` | string | ✅ | 插件唯一 ID(推荐,优先于 name) |
|
|
222
|
+
| `main` | string | ✅ | 后端入口文件路径 |
|
|
223
|
+
| `ui` | string | ❌ | UI 文件路径(有界面时必填) |
|
|
224
|
+
| `icon` | string/object | ❌ | 插件图标 |
|
|
225
|
+
| `features` | array | ✅ | 功能入口列表 |
|
|
226
|
+
| `pluginSetting` | object | ❌ | 插件行为设置 (`single`, `height`) |
|
|
227
|
+
| `window` | object | ❌ | 独立窗口配置 (`width`, `height`, `minWidth`, etc.) |
|
|
228
|
+
| `author` | string | ❌ | 作者名 |
|
|
229
|
+
| `homepage` | string | ❌ | 项目主页 |
|
|
230
|
+
| `minAppVersion` | string | ❌ | 最低 Mulby 版本要求 |
|
|
231
|
+
|
|
232
|
+
#### 功能入口 (features)
|
|
233
|
+
|
|
234
|
+
一个插件可以有多个功能入口,每个入口可以有不同的触发方式:
|
|
235
|
+
|
|
236
|
+
```json
|
|
237
|
+
{
|
|
238
|
+
"features": [
|
|
239
|
+
{
|
|
240
|
+
"code": "format",
|
|
241
|
+
"explain": "格式化 JSON",
|
|
242
|
+
"cmds": [
|
|
243
|
+
{ "type": "keyword", "value": "json" },
|
|
244
|
+
{ "type": "keyword", "value": "格式化" },
|
|
245
|
+
{ "type": "regex", "match": "^\\s*[{\\[]", "explain": "检测到 JSON" }
|
|
246
|
+
]
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
"code": "minify",
|
|
250
|
+
"explain": "压缩 JSON",
|
|
251
|
+
"cmds": [
|
|
252
|
+
{ "type": "keyword", "value": "json压缩" }
|
|
253
|
+
]
|
|
254
|
+
}
|
|
255
|
+
]
|
|
256
|
+
}
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
| 字段 | 类型 | 必需 | 说明 |
|
|
260
|
+
|------|------|------|------|
|
|
261
|
+
| `code` | string | ✅ | 功能代码,传递给插件 |
|
|
262
|
+
| `explain` | string | ✅ | 功能说明,显示给用户 |
|
|
263
|
+
| `cmds` | array | ✅ | 触发命令列表 |
|
|
264
|
+
| `mode` | string | ❌ | `ui` / `silent` / `detached` |
|
|
265
|
+
| `route` | string | ❌ | UI 路由(用于子窗口或页内路由) |
|
|
266
|
+
| `icon` | string/object | ❌ | 功能独立图标 |
|
|
267
|
+
| `mainHide` | boolean | ❌ | 触发时隐藏主窗口 |
|
|
268
|
+
| `mainPush` | boolean | ❌ | 向搜索框推送内容 |
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
#### 触发命令类型 (cmds)
|
|
272
|
+
|
|
273
|
+
| type | 说明 | 可用字段 |
|
|
274
|
+
|------|------|----------|
|
|
275
|
+
| `keyword` | 关键词触发 | `value`: 关键词 |
|
|
276
|
+
| `regex` | 正则匹配 | `match`: 正则表达式, `explain`: 说明, `label?`: 指令名称, `minLength?`, `maxLength?` |
|
|
277
|
+
| `files` | 文件拖入 | `exts?`, `fileType?` (file/directory/any), `match?` (文件名正则), `minLength?`, `maxLength?` |
|
|
278
|
+
| `img` | 图片拖入 | `exts?` |
|
|
279
|
+
| `over` | 选中文本 | `label?` (指令名称), `exclude?` (排除正则), `minLength?`, `maxLength?` |
|
|
280
|
+
|
|
281
|
+
#### 图标配置
|
|
282
|
+
|
|
283
|
+
支持三种格式:
|
|
284
|
+
|
|
285
|
+
```json
|
|
286
|
+
// 1. 本地文件(推荐)
|
|
287
|
+
"icon": "icon.png"
|
|
288
|
+
|
|
289
|
+
// 2. URL
|
|
290
|
+
"icon": "https://example.com/icon.png"
|
|
291
|
+
|
|
292
|
+
// 3. 内联 SVG
|
|
293
|
+
"icon": "<svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"...\"/></svg>"
|
|
294
|
+
|
|
295
|
+
// 4. 对象形式(支持更多类型)
|
|
296
|
+
"icon": { "type": "file", "value": "assets/logo.png" }
|
|
297
|
+
"icon": { "type": "url", "value": "https://example.com/icon.png" }
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
> 💡 **提示:** 未设置 `icon` 时,会自动尝试加载插件目录下的 `icon.png`
|
|
301
|
+
|
|
302
|
+
---
|
|
303
|
+
|
|
304
|
+
### 动态功能入口
|
|
305
|
+
|
|
306
|
+
后端可以通过 `context.api.features` 动态添加/移除功能入口:
|
|
307
|
+
|
|
308
|
+
```ts
|
|
309
|
+
export function onLoad(context?: any) {
|
|
310
|
+
const features = context?.api?.features
|
|
311
|
+
if (!features) return
|
|
312
|
+
|
|
313
|
+
features.setFeature({
|
|
314
|
+
code: 'dynamic:hello',
|
|
315
|
+
explain: '动态指令:hello',
|
|
316
|
+
mode: 'silent',
|
|
317
|
+
cmds: ['hello', { type: 'keyword', value: 'hi' }]
|
|
318
|
+
})
|
|
319
|
+
}
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
---
|
|
323
|
+
|
|
324
|
+
### 开发模式
|
|
325
|
+
|
|
326
|
+
#### 启动开发服务器
|
|
327
|
+
|
|
328
|
+
```bash
|
|
329
|
+
npm run dev
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
开发模式会:
|
|
333
|
+
1. **监听后端代码变化** - `src/main.ts` 及其依赖变化时自动重新构建
|
|
334
|
+
2. **启动 Vite 开发服务器** - 有 UI 时自动启动,支持 HMR(热模块替换)
|
|
335
|
+
|
|
336
|
+
#### 在 Mulby 中预览
|
|
337
|
+
|
|
338
|
+
1. 打开 Mulby 设置
|
|
339
|
+
2. 添加开发目录(插件项目路径)
|
|
340
|
+
3. 输入关键词触发插件
|
|
341
|
+
|
|
342
|
+
---
|
|
343
|
+
|
|
344
|
+
### 使用第三方库
|
|
345
|
+
|
|
346
|
+
Mulby CLI 使用 **esbuild** 打包,会将所有依赖内联到 `dist/main.js` 中,因此你可以自由使用任何 npm 包。
|
|
347
|
+
|
|
348
|
+
#### 示例:使用 dayjs 处理日期
|
|
349
|
+
|
|
350
|
+
**1. 安装依赖**
|
|
351
|
+
|
|
352
|
+
```bash
|
|
353
|
+
npm install dayjs
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
**2. 在代码中使用**
|
|
357
|
+
|
|
358
|
+
```typescript
|
|
359
|
+
// src/main.ts
|
|
360
|
+
import dayjs from 'dayjs'
|
|
361
|
+
|
|
362
|
+
module.exports = {
|
|
363
|
+
async run(context: any) {
|
|
364
|
+
const { clipboard, notification } = context.api
|
|
365
|
+
const text = context.input || await clipboard.readText()
|
|
366
|
+
|
|
367
|
+
// 使用 dayjs 格式化日期
|
|
368
|
+
const result = dayjs(text).format('YYYY-MM-DD HH:mm:ss')
|
|
369
|
+
|
|
370
|
+
await clipboard.writeText(result)
|
|
371
|
+
notification.show('日期格式化完成')
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
**3. 构建**
|
|
377
|
+
|
|
378
|
+
```bash
|
|
379
|
+
npm run build
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
构建后,`dayjs` 的代码会被内联到 `dist/main.js` 中,无需用户单独安装。
|
|
383
|
+
|
|
384
|
+
---
|
|
385
|
+
|
|
386
|
+
### 插件 API
|
|
387
|
+
|
|
388
|
+
插件在沙箱中运行,通过 `context.api` 访问各种 API。
|
|
389
|
+
|
|
390
|
+
> 📚 **完整 API 参考请查看 [`PLUGIN_DEVELOP_PROMPT.md`](./PLUGIN_DEVELOP_PROMPT.md)**
|
|
391
|
+
>
|
|
392
|
+
> 该文件会在创建插件时自动生成,包含全部 28 个 API 模块的详细说明。
|
|
393
|
+
|
|
394
|
+
#### 可用 API 模块
|
|
395
|
+
|
|
396
|
+
| 模块 | 说明 | 常用方法 |
|
|
397
|
+
|------|------|----------|
|
|
398
|
+
| `clipboard` | 剪贴板 | `readText`, `writeText`, `readImage` |
|
|
399
|
+
| `filesystem` | 文件系统 | `readFile`, `writeFile`, `readdir` |
|
|
400
|
+
| `storage` | 数据存储 | `get`, `set`, `remove` |
|
|
401
|
+
| `dialog` | 系统对话框 | `showOpenDialog`, `showMessageBox` |
|
|
402
|
+
| `notification` | 通知 | `show` |
|
|
403
|
+
| `shell` | 系统外壳 | `openExternal`, `showItemInFolder` |
|
|
404
|
+
| `http` | 网络请求 | `get`, `post`, `request` |
|
|
405
|
+
| `system` | 系统信息 | `getSystemInfo`, `getPath` |
|
|
406
|
+
| `screen` | 屏幕控制 | `capture`, `colorPick`, `getAllDisplays` |
|
|
407
|
+
| `input` | 模拟输入 | `simulateKeyboardTap`, `hideMainWindowPasteText` |
|
|
408
|
+
| `window` | 窗口控制 | `hide`, `setSize`, `create` |
|
|
409
|
+
| `theme` | 主题 | `get`, `set` |
|
|
410
|
+
| `plugin` | 插件管理 | `run`, `redirect`, `outPlugin` |
|
|
411
|
+
| `features` | 动态功能 | `setFeature`, `removeFeature` |
|
|
412
|
+
| `shortcut` | 全局快捷键 | `register`, `unregister` |
|
|
413
|
+
| `permission` | 权限管理 | `request`, `getStatus` |
|
|
414
|
+
| `security` | 安全 | `encryptString`, `decryptString` |
|
|
415
|
+
| `tray` | 系统托盘 | `create`, `setIcon` |
|
|
416
|
+
| `menu` | 上下文菜单 | `showContextMenu` |
|
|
417
|
+
| `network` | 网络状态 | `isOnline` |
|
|
418
|
+
| `power` | 电源监控 | `getSystemIdleTime`, `onAC` |
|
|
419
|
+
| `media` | 媒体权限 | `hasCameraAccess` |
|
|
420
|
+
| `geolocation` | 地理位置 | `getCurrentPosition` |
|
|
421
|
+
| `tts` | 语音合成 | `speak` |
|
|
422
|
+
| `host` | 主机控制 | `invoke` |
|
|
423
|
+
| `sharp` | 图像处理 | `resize`, `toBuffer` |
|
|
424
|
+
| `ffmpeg` | 音视频处理 | `run`, `download` |
|
|
425
|
+
| `inbrowser` | 浏览器自动化 | `goto`, `click`, `evaluate` |
|
|
426
|
+
|
|
427
|
+
#### 常用 API 快速示例
|
|
428
|
+
|
|
429
|
+
```typescript
|
|
430
|
+
// 剪贴板
|
|
431
|
+
const text = clipboard.readText()
|
|
432
|
+
await clipboard.writeText('Hello')
|
|
433
|
+
|
|
434
|
+
// 通知
|
|
435
|
+
notification.show('操作成功')
|
|
436
|
+
|
|
437
|
+
// 存储
|
|
438
|
+
await storage.set('key', { data: 'value' })
|
|
439
|
+
const data = await storage.get('key')
|
|
440
|
+
|
|
441
|
+
// 文件系统
|
|
442
|
+
const content = filesystem.readFile('/path/file.txt', 'utf-8')
|
|
443
|
+
|
|
444
|
+
// HTTP 请求
|
|
445
|
+
const response = await http.post('https://api.example.com', { key: 'value' })
|
|
446
|
+
|
|
447
|
+
// 屏幕取色
|
|
448
|
+
const color = await screen.colorPick()
|
|
449
|
+
|
|
450
|
+
// 浏览器自动化
|
|
451
|
+
await inbrowser.goto('https://google.com')
|
|
452
|
+
await inbrowser.type('input[name="q"]', 'mulby')
|
|
453
|
+
await inbrowser.click('input[name="btnK"]')
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
---
|
|
457
|
+
|
|
458
|
+
### 插件 UI
|
|
459
|
+
|
|
460
|
+
#### 在 UI 中访问 API
|
|
461
|
+
|
|
462
|
+
UI 通过 `window.mulby` 全局对象访问 API:
|
|
463
|
+
|
|
464
|
+
```tsx
|
|
465
|
+
// src/ui/App.tsx
|
|
466
|
+
import { useEffect, useState } from 'react'
|
|
467
|
+
|
|
468
|
+
export default function App() {
|
|
469
|
+
const [input, setInput] = useState('')
|
|
470
|
+
|
|
471
|
+
// 接收插件初始化数据
|
|
472
|
+
useEffect(() => {
|
|
473
|
+
window.mulby?.onPluginInit?.((data) => {
|
|
474
|
+
if (data.input) setInput(data.input)
|
|
475
|
+
})
|
|
476
|
+
}, [])
|
|
477
|
+
|
|
478
|
+
const handleProcess = async () => {
|
|
479
|
+
const result = input.toUpperCase()
|
|
480
|
+
// 复制到剪贴板
|
|
481
|
+
await window.mulby?.clipboard?.writeText(result)
|
|
482
|
+
// 显示通知
|
|
483
|
+
window.mulby?.notification?.show('已复制到剪贴板')
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
return (
|
|
487
|
+
<div>
|
|
488
|
+
<textarea value={input} onChange={(e) => setInput(e.target.value)} />
|
|
489
|
+
<button onClick={handleProcess}>处理</button>
|
|
490
|
+
</div>
|
|
491
|
+
)
|
|
492
|
+
}
|
|
493
|
+
```
|
|
494
|
+
|
|
495
|
+
#### 主题适配
|
|
496
|
+
|
|
497
|
+
插件 UI 应跟随 Mulby 主题:
|
|
498
|
+
|
|
499
|
+
```tsx
|
|
500
|
+
// 获取初始主题
|
|
501
|
+
function getInitialTheme(): 'light' | 'dark' {
|
|
502
|
+
const params = new URLSearchParams(window.location.search)
|
|
503
|
+
return (params.get('theme') as 'light' | 'dark') || 'light'
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
// 监听主题变化
|
|
507
|
+
useEffect(() => {
|
|
508
|
+
window.mulby?.onThemeChange?.((theme) => {
|
|
509
|
+
document.documentElement.classList.toggle('dark', theme === 'dark')
|
|
510
|
+
})
|
|
511
|
+
}, [])
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
---
|
|
515
|
+
|
|
516
|
+
### 生命周期钩子
|
|
517
|
+
|
|
518
|
+
插件支持生命周期钩子函数:
|
|
519
|
+
|
|
520
|
+
```typescript
|
|
521
|
+
module.exports = {
|
|
522
|
+
// 插件加载时调用
|
|
523
|
+
onLoad() {
|
|
524
|
+
console.log('插件已加载')
|
|
525
|
+
},
|
|
526
|
+
|
|
527
|
+
// 插件卸载时调用
|
|
528
|
+
onUnload() {
|
|
529
|
+
console.log('插件即将卸载')
|
|
530
|
+
},
|
|
531
|
+
|
|
532
|
+
// 插件启用时调用
|
|
533
|
+
onEnable() {
|
|
534
|
+
console.log('插件已启用')
|
|
535
|
+
},
|
|
536
|
+
|
|
537
|
+
// 插件禁用时调用
|
|
538
|
+
onDisable() {
|
|
539
|
+
console.log('插件已禁用')
|
|
540
|
+
},
|
|
541
|
+
|
|
542
|
+
// 主执行函数
|
|
543
|
+
async run(context) {
|
|
544
|
+
// 插件主逻辑
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
```
|
|
548
|
+
|
|
549
|
+
| 钩子 | 触发时机 | 用途 |
|
|
550
|
+
|------|----------|------|
|
|
551
|
+
| `onLoad` | 插件加载时 | 初始化资源、注册服务 |
|
|
552
|
+
| `onUnload` | 插件卸载时 | 清理资源、保存状态 |
|
|
553
|
+
| `onEnable` | 插件启用时 | 恢复服务、重新注册 |
|
|
554
|
+
| `onDisable` | 插件禁用时 | 暂停服务、释放资源 |
|
|
555
|
+
|
|
556
|
+
---
|
|
557
|
+
|
|
558
|
+
## 构建与打包
|
|
559
|
+
|
|
560
|
+
### 构建流程
|
|
561
|
+
|
|
562
|
+
```bash
|
|
563
|
+
# 构建生产版本
|
|
564
|
+
npm run build
|
|
565
|
+
```
|
|
566
|
+
|
|
567
|
+
构建命令会:
|
|
568
|
+
1. 使用 esbuild 打包后端代码到 `dist/main.js`(压缩)
|
|
569
|
+
2. 使用 Vite 构建 UI 到 `ui/` 目录(如果有 UI)
|
|
570
|
+
|
|
571
|
+
### 打包发布
|
|
572
|
+
|
|
573
|
+
```bash
|
|
574
|
+
# 打包成 .inplugin 文件
|
|
575
|
+
npm run pack
|
|
576
|
+
```
|
|
577
|
+
|
|
578
|
+
生成的 `.inplugin` 文件实际上是 ZIP 格式,包含:
|
|
579
|
+
|
|
580
|
+
```
|
|
581
|
+
my-plugin-1.0.0.inplugin
|
|
582
|
+
├── manifest.json # 插件配置
|
|
583
|
+
├── main.js # 打包后的后端代码
|
|
584
|
+
├── icon.png # 图标(可选)
|
|
585
|
+
└── ui/ # UI 资源(可选)
|
|
586
|
+
├── index.html
|
|
587
|
+
└── assets/
|
|
588
|
+
```
|
|
589
|
+
|
|
590
|
+
### 安装插件
|
|
591
|
+
|
|
592
|
+
用户可以通过以下方式安装 `.inplugin` 文件:
|
|
593
|
+
|
|
594
|
+
1. **双击安装** - 直接双击 `.inplugin` 文件
|
|
595
|
+
2. **拖拽安装** - 将文件拖入 Mulby 窗口
|
|
596
|
+
3. **命令安装** - `mulby install ./my-plugin.inplugin`
|
|
597
|
+
|
|
598
|
+
---
|
|
599
|
+
|
|
600
|
+
## 完整示例
|
|
601
|
+
|
|
602
|
+
### 示例 1:JSON 格式化插件(无 UI)
|
|
603
|
+
|
|
604
|
+
```bash
|
|
605
|
+
mulby create json-formatter --template basic
|
|
606
|
+
cd json-formatter
|
|
607
|
+
```
|
|
608
|
+
|
|
609
|
+
**manifest.json:**
|
|
610
|
+
```json
|
|
611
|
+
{
|
|
612
|
+
"name": "json-formatter",
|
|
613
|
+
"version": "1.0.0",
|
|
614
|
+
"displayName": "JSON 格式化",
|
|
615
|
+
"description": "格式化或压缩 JSON 数据",
|
|
616
|
+
"main": "dist/main.js",
|
|
617
|
+
"icon": "<svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M5 3h2v2H5v5a2 2 0 01-2 2 2 2 0 012 2v5h2v2H5c-1.1 0-2-.9-2-2v-4a2 2 0 00-2-2H0v-2h1a2 2 0 002-2V5a2 2 0 012-2zm14 0a2 2 0 012 2v4a2 2 0 002 2h1v2h-1a2 2 0 00-2 2v4a2 2 0 01-2 2h-2v-2h2v-5a2 2 0 012-2 2 2 0 01-2-2V5h-2V3h2z\"/></svg>",
|
|
618
|
+
"features": [
|
|
619
|
+
{
|
|
620
|
+
"code": "format",
|
|
621
|
+
"explain": "格式化 JSON",
|
|
622
|
+
"cmds": [
|
|
623
|
+
{ "type": "keyword", "value": "json" },
|
|
624
|
+
{ "type": "regex", "match": "^\\s*[{\\[]", "explain": "检测到 JSON" }
|
|
625
|
+
]
|
|
626
|
+
}
|
|
627
|
+
]
|
|
628
|
+
}
|
|
629
|
+
```
|
|
630
|
+
|
|
631
|
+
**src/main.ts:**
|
|
632
|
+
```typescript
|
|
633
|
+
interface PluginContext {
|
|
634
|
+
api: {
|
|
635
|
+
clipboard: {
|
|
636
|
+
readText: () => string
|
|
637
|
+
writeText: (text: string) => Promise<void>
|
|
638
|
+
}
|
|
639
|
+
notification: {
|
|
640
|
+
show: (message: string, type?: string) => void
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
input?: string
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
export async function run(context: PluginContext) {
|
|
647
|
+
const { clipboard, notification } = context.api
|
|
648
|
+
const text = context.input || clipboard.readText()
|
|
649
|
+
|
|
650
|
+
try {
|
|
651
|
+
const obj = JSON.parse(text)
|
|
652
|
+
const formatted = JSON.stringify(obj, null, 2)
|
|
653
|
+
await clipboard.writeText(formatted)
|
|
654
|
+
notification.show('JSON 格式化成功')
|
|
655
|
+
} catch (e) {
|
|
656
|
+
notification.show('无效的 JSON', 'error')
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
export default { run }
|
|
661
|
+
```
|
|
662
|
+
|
|
663
|
+
### 示例 2:翻译插件(带 UI)
|
|
664
|
+
|
|
665
|
+
```bash
|
|
666
|
+
mulby create translator
|
|
667
|
+
cd translator
|
|
668
|
+
npm install
|
|
669
|
+
```
|
|
670
|
+
|
|
671
|
+
**manifest.json:**
|
|
672
|
+
```json
|
|
673
|
+
{
|
|
674
|
+
"name": "translator",
|
|
675
|
+
"version": "1.0.0",
|
|
676
|
+
"displayName": "快速翻译",
|
|
677
|
+
"description": "中英文互译",
|
|
678
|
+
"main": "dist/main.js",
|
|
679
|
+
"ui": "ui/index.html",
|
|
680
|
+
"features": [
|
|
681
|
+
{
|
|
682
|
+
"code": "translate",
|
|
683
|
+
"explain": "翻译文本",
|
|
684
|
+
"cmds": [
|
|
685
|
+
{ "type": "keyword", "value": "fy" },
|
|
686
|
+
{ "type": "keyword", "value": "翻译" }
|
|
687
|
+
]
|
|
688
|
+
}
|
|
689
|
+
]
|
|
690
|
+
}
|
|
691
|
+
```
|
|
692
|
+
|
|
693
|
+
**src/main.ts:**
|
|
694
|
+
```typescript
|
|
695
|
+
export function onLoad() {
|
|
696
|
+
console.log('翻译插件已加载')
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
export async function run() {
|
|
700
|
+
// UI 插件通常不需要在 run 中做太多事
|
|
701
|
+
// 主要逻辑在 UI 中处理
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
export default { onLoad, run }
|
|
705
|
+
```
|
|
706
|
+
|
|
707
|
+
**src/ui/App.tsx:**
|
|
708
|
+
```tsx
|
|
709
|
+
import { useEffect, useState } from 'react'
|
|
710
|
+
|
|
711
|
+
export default function App() {
|
|
712
|
+
const [input, setInput] = useState('')
|
|
713
|
+
const [output, setOutput] = useState('')
|
|
714
|
+
const [loading, setLoading] = useState(false)
|
|
715
|
+
|
|
716
|
+
useEffect(() => {
|
|
717
|
+
window.mulby?.onPluginInit?.((data) => {
|
|
718
|
+
if (data.input) setInput(data.input)
|
|
719
|
+
})
|
|
720
|
+
}, [])
|
|
721
|
+
|
|
722
|
+
const handleTranslate = async () => {
|
|
723
|
+
if (!input.trim()) return
|
|
724
|
+
|
|
725
|
+
setLoading(true)
|
|
726
|
+
try {
|
|
727
|
+
// 调用翻译 API
|
|
728
|
+
const response = await fetch('https://api.translate.com/v1/translate', {
|
|
729
|
+
method: 'POST',
|
|
730
|
+
headers: { 'Content-Type': 'application/json' },
|
|
731
|
+
body: JSON.stringify({ text: input, from: 'auto', to: 'en' })
|
|
732
|
+
})
|
|
733
|
+
const data = await response.json()
|
|
734
|
+
setOutput(data.translation)
|
|
735
|
+
} catch (error) {
|
|
736
|
+
window.mulby?.notification?.show('翻译失败', 'error')
|
|
737
|
+
} finally {
|
|
738
|
+
setLoading(false)
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
const handleCopy = async () => {
|
|
743
|
+
await window.mulby?.clipboard?.writeText(output)
|
|
744
|
+
window.mulby?.notification?.show('已复制')
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
return (
|
|
748
|
+
<div className="app">
|
|
749
|
+
<div className="titlebar">快速翻译</div>
|
|
750
|
+
<div className="container">
|
|
751
|
+
<textarea
|
|
752
|
+
value={input}
|
|
753
|
+
onChange={(e) => setInput(e.target.value)}
|
|
754
|
+
placeholder="输入要翻译的文本..."
|
|
755
|
+
/>
|
|
756
|
+
<button onClick={handleTranslate} disabled={loading}>
|
|
757
|
+
{loading ? '翻译中...' : '翻译'}
|
|
758
|
+
</button>
|
|
759
|
+
<textarea
|
|
760
|
+
value={output}
|
|
761
|
+
readOnly
|
|
762
|
+
placeholder="翻译结果..."
|
|
763
|
+
/>
|
|
764
|
+
{output && <button onClick={handleCopy}>复制结果</button>}
|
|
765
|
+
</div>
|
|
766
|
+
</div>
|
|
767
|
+
)
|
|
768
|
+
}
|
|
769
|
+
```
|
|
770
|
+
|
|
771
|
+
---
|
|
772
|
+
|
|
773
|
+
## AI 任务规划
|
|
774
|
+
|
|
775
|
+
Mulby CLI 内置了智能任务规划系统,自动识别复杂任务并帮助你分解执行。
|
|
776
|
+
|
|
777
|
+
### 工作流程
|
|
778
|
+
|
|
779
|
+
1. **自动识别** - AI 分析你的任务,判断是否需要规划
|
|
780
|
+
2. **生成计划** - 如果是复杂任务,AI 自动生成 todo list
|
|
781
|
+
3. **逐步执行** - 按照计划执行,完成一项勾选一项
|
|
782
|
+
4. **进度保存** - 中途退出自动保存,下次可继续
|
|
783
|
+
|
|
784
|
+
### 使用方式
|
|
785
|
+
|
|
786
|
+
**自动触发(推荐)**
|
|
787
|
+
|
|
788
|
+
输入任务后,如果 AI 判断是复杂任务,会提示:
|
|
789
|
+
|
|
790
|
+
```
|
|
791
|
+
📊 复杂任务(预估 5 个步骤)
|
|
792
|
+
原因:需要设计数据库、实现 API、编写前端页面
|
|
793
|
+
|
|
794
|
+
> 创建计划后执行 (推荐)
|
|
795
|
+
直接执行
|
|
796
|
+
```
|
|
797
|
+
|
|
798
|
+
选择「创建计划后执行」,AI 会自动:
|
|
799
|
+
- 列出具体步骤
|
|
800
|
+
- 按顺序执行
|
|
801
|
+
- 完成后自动勾选
|
|
802
|
+
|
|
803
|
+
**手动触发**
|
|
804
|
+
|
|
805
|
+
```bash
|
|
806
|
+
# 强制使用计划模式
|
|
807
|
+
/plan 实现用户登录功能
|
|
808
|
+
|
|
809
|
+
# 查看当前计划状态
|
|
810
|
+
/plan
|
|
811
|
+
```
|
|
812
|
+
|
|
813
|
+
### 示例
|
|
814
|
+
|
|
815
|
+
```
|
|
816
|
+
用户: /plan 实现一个 JSON 格式化插件
|
|
817
|
+
|
|
818
|
+
AI: 好的,让我为这个任务创建计划:
|
|
819
|
+
|
|
820
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
821
|
+
📋 实现 JSON 格式化插件
|
|
822
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
823
|
+
███████████░░░░░░░░░░░░░░░░░░░ 2/5 (40%)
|
|
824
|
+
|
|
825
|
+
✅ 创建插件基础结构
|
|
826
|
+
✅ 实现 JSON 解析和格式化
|
|
827
|
+
🔄 添加错误处理
|
|
828
|
+
⏸️ 编写 UI 界面
|
|
829
|
+
⏸️ 测试和优化
|
|
830
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
831
|
+
```
|
|
832
|
+
|
|
833
|
+
---
|
|
834
|
+
|
|
835
|
+
## 常见问题
|
|
836
|
+
|
|
837
|
+
### Q: 如何调试插件?
|
|
838
|
+
|
|
839
|
+
A: 使用 `npm run dev` 启动开发模式,后端代码支持 sourcemap。可以在 Mulby 的开发者工具中查看日志和调试。
|
|
840
|
+
|
|
841
|
+
### Q: 为什么我的第三方库不能用?
|
|
842
|
+
|
|
843
|
+
A: 确保依赖已安装(`npm install`)并且使用 `npm run build` 构建。CLI 会自动将依赖打包到 `dist/main.js` 中。
|
|
844
|
+
|
|
845
|
+
### Q: 如何更新已安装的插件?
|
|
846
|
+
|
|
847
|
+
A: 修改 `manifest.json` 中的 `version` 字段,重新打包后安装即可。Mulby 会检测版本变化并更新。
|
|
848
|
+
|
|
849
|
+
### Q: 插件可以访问系统命令吗?
|
|
850
|
+
|
|
851
|
+
A: 前端通过 `window.mulby.shell` 调用系统能力;后端运行在沙箱中,仅能使用 `context.api` 暴露的接口。具体能力以 `mulby.d.ts` 为准。
|
|
852
|
+
|