mulby-cli 1.1.6 → 1.1.7
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 +117 -50
- package/README.md +13 -0
- package/package.json +5 -3
package/PLUGIN_DEVELOP_PROMPT.md
CHANGED
|
@@ -2,26 +2,29 @@
|
|
|
2
2
|
|
|
3
3
|
> **Architecture**: Mulby is built on the **Electron** framework. Plugins run in a multi-process environment.
|
|
4
4
|
> **Contexts**: `UI` = **Renderer Process** (`window.mulby.{module}`), `Main` = **Main Process** (`context.api.{module}`). Most APIs are available in both contexts (marked as **R/B**).
|
|
5
|
+
> **Source of Truth (when available in this repo)**: `docs/apis/README.md`, the specific `docs/apis/*.md` files, and `src/shared/types/electron.d.ts` are authoritative. The API section in this file is a curated quick reference and may lag behind newly added modules.
|
|
5
6
|
|
|
6
7
|
## 1. Project Structure
|
|
7
8
|
|
|
8
9
|
```text
|
|
9
10
|
my-plugin/
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
11
|
+
|- manifest.json # Plugin Configuration (Manifest V2)
|
|
12
|
+
|- package.json # Dependencies (React, Vite, etc.)
|
|
13
|
+
|- tsconfig.json # TypeScript Configuration
|
|
14
|
+
|- vite.config.ts # Vite Configuration
|
|
15
|
+
|- preload.cjs # Node.js Bridge (Optional, MUST be .cjs)
|
|
16
|
+
|- src/
|
|
17
|
+
| |- main.ts # Backend Logic (Node.js context)
|
|
18
|
+
| |- types/
|
|
19
|
+
| | `- mulby.d.ts # Mulby type definitions generated by the template
|
|
20
|
+
| `- ui/ # Frontend Logic (React context)
|
|
21
|
+
| |- index.html
|
|
22
|
+
| |- main.tsx # Entry Point
|
|
23
|
+
| |- App.tsx # Main Component
|
|
24
|
+
| |- styles.css
|
|
25
|
+
| `- hooks/
|
|
26
|
+
| `- useMulby.ts
|
|
27
|
+
`- assets/ # Icons, etc.
|
|
25
28
|
```
|
|
26
29
|
|
|
27
30
|
## 1.1 Entry Points & Patterns
|
|
@@ -30,18 +33,25 @@ my-plugin/
|
|
|
30
33
|
```typescript
|
|
31
34
|
interface PluginContext {
|
|
32
35
|
api: { clipboard: any; notification: any; /* ... */ }
|
|
33
|
-
input?: string;
|
|
34
|
-
featureCode?: string;
|
|
36
|
+
input?: string;
|
|
37
|
+
featureCode?: string;
|
|
38
|
+
attachments?: Array<{ path?: string; name?: string; kind?: 'file' | 'image' }>;
|
|
35
39
|
}
|
|
36
40
|
|
|
37
|
-
// Lifecycle Hooks within export
|
|
38
41
|
export function onLoad() { /* Plugin Loaded */ }
|
|
39
42
|
export function onUnload() { /* Plugin Unloaded */ }
|
|
43
|
+
export function onEnable() { /* Plugin Enabled */ }
|
|
44
|
+
export function onDisable() { /* Plugin Disabled */ }
|
|
40
45
|
export async function run(context: PluginContext) {
|
|
41
46
|
const { notification } = context.api;
|
|
42
47
|
notification.show('Plugin Started');
|
|
43
48
|
}
|
|
44
|
-
export
|
|
49
|
+
export const host = {
|
|
50
|
+
async ping(_context: PluginContext) {
|
|
51
|
+
return { ok: true };
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
export default { onLoad, onUnload, onEnable, onDisable, run, host };
|
|
45
55
|
```
|
|
46
56
|
|
|
47
57
|
**Frontend (`src/ui/App.tsx`)**:
|
|
@@ -54,6 +64,55 @@ export default function App() {
|
|
|
54
64
|
}
|
|
55
65
|
```
|
|
56
66
|
|
|
67
|
+
## 1.2 Fixed AI Development Workflow
|
|
68
|
+
|
|
69
|
+
When AI is used to generate or modify a Mulby plugin, it MUST follow this fixed workflow.
|
|
70
|
+
The goal is not "write some code", but "produce a plugin that can really attach to Mulby".
|
|
71
|
+
|
|
72
|
+
### Phase 0: Integration Recon
|
|
73
|
+
Before proposing implementation details, inspect the current integration skeleton:
|
|
74
|
+
- `manifest.json`
|
|
75
|
+
- `src/main.ts`
|
|
76
|
+
- `src/ui/App.tsx` (if the plugin has UI)
|
|
77
|
+
- `preload.cjs` (if present)
|
|
78
|
+
|
|
79
|
+
### Phase 1: Define the Plugin Contract
|
|
80
|
+
Lock down the contract before coding:
|
|
81
|
+
- Which `features[].code` values exist
|
|
82
|
+
- Which `cmds` trigger each feature
|
|
83
|
+
- Whether each feature is `ui`, `silent`, or `detached`
|
|
84
|
+
- Which logic belongs to UI, backend, and preload
|
|
85
|
+
- Whether background mode / scheduler / host APIs are needed
|
|
86
|
+
|
|
87
|
+
### Phase 2: Build a Minimum Runnable Path
|
|
88
|
+
Implement one end-to-end happy path first:
|
|
89
|
+
- `manifest.json` points to the correct entry files
|
|
90
|
+
- `src/main.ts` contains the real entry logic
|
|
91
|
+
- UI plugins have a usable `src/ui/App.tsx`
|
|
92
|
+
- `preload.cjs` is only added when Node.js / Electron bridging is required
|
|
93
|
+
|
|
94
|
+
### Phase 3: Expand Features
|
|
95
|
+
Only after the minimum path is attachable should you:
|
|
96
|
+
- add additional feature triggers
|
|
97
|
+
- refine UX and styling
|
|
98
|
+
- add host methods or background capabilities
|
|
99
|
+
|
|
100
|
+
### Phase 4: Validate Before Handoff
|
|
101
|
+
Before claiming completion, verify all of the following:
|
|
102
|
+
- `manifest.json` required fields are complete
|
|
103
|
+
- every `feature.code` maps to real handling logic
|
|
104
|
+
- `main`, `ui`, and `preload` paths point to files that really exist
|
|
105
|
+
- `preload` uses `.cjs` and CommonJS when present
|
|
106
|
+
- the plugin can be built successfully
|
|
107
|
+
|
|
108
|
+
### Manual Host-Side Acceptance Checklist
|
|
109
|
+
The final delivery should tell the user to test these points inside Mulby:
|
|
110
|
+
1. The plugin can be installed / loaded without manifest errors
|
|
111
|
+
2. At least one trigger path (`keyword`, `regex`, `files`, `img`, or `over`) actually enters the plugin
|
|
112
|
+
3. The expected UI opens, or the silent feature completes without UI
|
|
113
|
+
4. Detached / background / preload behavior works if configured
|
|
114
|
+
5. The core user task succeeds on a realistic sample input
|
|
115
|
+
|
|
57
116
|
## 2. Manifest Configuration (`manifest.json`)
|
|
58
117
|
|
|
59
118
|
```json
|
|
@@ -154,10 +213,12 @@ window.myPluginApi = {
|
|
|
154
213
|
}
|
|
155
214
|
```
|
|
156
215
|
|
|
157
|
-
## 4. API Reference (TypeScript
|
|
216
|
+
## 4. API Reference (TypeScript Quick Reference)
|
|
158
217
|
|
|
159
218
|
> **R/B** = Available in both Renderer (`window.mulby`) and Backend (`context.api`).
|
|
160
219
|
> **R** = Renderer only. **B** = Backend only.
|
|
220
|
+
>
|
|
221
|
+
> This section is intentionally a high-value quick reference, not a full spec. When you are working inside the Mulby repo, prefer `docs/apis/README.md`, the specific `docs/apis/*.md` files, and `src/shared/types/electron.d.ts` for exact current signatures. Newer modules such as `pluginStore`, `systemPage`, `systemPlugin`, `trayMenu`, and `appEvents` may exist even if they are not fully expanded below.
|
|
161
222
|
|
|
162
223
|
### Core Modules
|
|
163
224
|
|
|
@@ -766,22 +827,28 @@ interface SubInput {
|
|
|
766
827
|
// plugin (R) - Plugin Management
|
|
767
828
|
interface Plugin {
|
|
768
829
|
getAll(): Promise<PluginInfo[]>;
|
|
830
|
+
listCommands(pluginId?: string): Promise<any[]>;
|
|
769
831
|
search(query: string): Promise<PluginSearchResult[]>;
|
|
770
|
-
run(id: string, code: string, input?: any): Promise<
|
|
771
|
-
|
|
832
|
+
run(id: string, code: string, input?: any): Promise<{ success: boolean; hasUI?: boolean; error?: string }>;
|
|
833
|
+
runCommand(input: any): Promise<{ success: boolean; hasUI?: boolean; error?: string }>;
|
|
834
|
+
getRecentUsed(limit?: number): Promise<any[]>;
|
|
835
|
+
install(path: string): Promise<{ success: boolean; error?: string }>;
|
|
772
836
|
enable(name: string): Promise<{ success: boolean; error?: string }>;
|
|
773
837
|
disable(name: string): Promise<{ success: boolean; error?: string }>;
|
|
774
|
-
uninstall(id: string): Promise<
|
|
775
|
-
outPlugin(kill?: boolean): Promise<
|
|
838
|
+
uninstall(id: string): Promise<{ success: boolean; error?: string }>;
|
|
839
|
+
outPlugin(kill?: boolean): Promise<boolean>;
|
|
776
840
|
redirect(label: string, payload?: any): Promise<boolean>;
|
|
777
|
-
getReadme(id: string): Promise<string>;
|
|
841
|
+
getReadme(id: string): Promise<string | null>;
|
|
778
842
|
|
|
779
843
|
// Background & Process Management
|
|
780
844
|
listBackground(): Promise<any[]>;
|
|
781
845
|
startBackground(pluginId: string): Promise<{ success: boolean; error?: string }>;
|
|
782
846
|
stopBackground(pluginId: string): Promise<{ success: boolean }>;
|
|
783
|
-
getBackgroundInfo(pluginId: string): Promise<any>;
|
|
784
|
-
stopPlugin(pluginId: string): Promise<
|
|
847
|
+
getBackgroundInfo(pluginId: string): Promise<any | null>;
|
|
848
|
+
stopPlugin(pluginId: string): Promise<{ success: boolean; error?: string }>;
|
|
849
|
+
listCommandShortcuts?(pluginId?: string): Promise<any[]>;
|
|
850
|
+
bindCommandShortcut?(input: any): Promise<{ success: boolean; error?: string }>;
|
|
851
|
+
unbindCommandShortcut?(bindingId: string): Promise<{ success: boolean }>;
|
|
785
852
|
}
|
|
786
853
|
|
|
787
854
|
// theme (R)
|
|
@@ -829,10 +896,10 @@ interface Screen {
|
|
|
829
896
|
getPrimaryDisplay(): Promise<any>;
|
|
830
897
|
getCursorScreenPoint(): Promise<{ x: number; y: number }>;
|
|
831
898
|
capture(opts?: { sourceId?: string; format?: 'png'|'jpeg' }): Promise<Buffer>;
|
|
832
|
-
captureRegion(
|
|
833
|
-
screenCapture(): Promise<string>; // R only, Interactive
|
|
834
|
-
colorPick(): Promise<{ hex: string }>; // R only
|
|
835
|
-
getSources(opts?: { types
|
|
899
|
+
captureRegion(region: { x: number; y: number; width: number; height: number }, opts?: any): Promise<Buffer>;
|
|
900
|
+
screenCapture(): Promise<string | null>; // R only, Interactive
|
|
901
|
+
colorPick(): Promise<{ hex: string } | null>; // R only
|
|
902
|
+
getSources(opts?: { types?: string[]; thumbnailSize?: { width: number; height: number } }): Promise<any[]>;
|
|
836
903
|
}
|
|
837
904
|
|
|
838
905
|
// input (R/B) - Simulate Input
|
|
@@ -962,9 +1029,10 @@ export function onUnload() { /* Cleanup (Called on app exit or manual stop) */ }
|
|
|
962
1029
|
|
|
963
1030
|
### 5.3 Management API
|
|
964
1031
|
|
|
965
|
-
- **
|
|
966
|
-
- **
|
|
967
|
-
- **Start**: `
|
|
1032
|
+
- **Backend Lifecycle Hooks**: `onBackground()` / `onForeground()` in `src/main.ts`
|
|
1033
|
+
- **Renderer Status List**: `window.mulby.plugin.listBackground()`
|
|
1034
|
+
- **Renderer Start / Stop**: `window.mulby.plugin.startBackground(pluginId)` / `window.mulby.plugin.stopBackground(pluginId)`
|
|
1035
|
+
- **Renderer Inspect / Stop Running Plugin**: `window.mulby.plugin.getBackgroundInfo(pluginId)` / `window.mulby.plugin.stopPlugin(pluginId)`
|
|
968
1036
|
|
|
969
1037
|
### 5.4 UI Plugin Integration
|
|
970
1038
|
|
|
@@ -973,10 +1041,13 @@ For plugins with UI (`"ui": "..."` in manifest):
|
|
|
973
1041
|
2. **Frontend** (`src/ui/...`) stops when window closes.
|
|
974
1042
|
3. Use IPC (via `api.messaging` or `host` module) to communicate between active UI and background backend.
|
|
975
1043
|
|
|
976
|
-
## 6. Task Scheduler (Backend
|
|
1044
|
+
## 6. Task Scheduler (Backend-First)
|
|
977
1045
|
|
|
978
1046
|
Schedule tasks to run at specific times or intervals. Tasks persist across app restarts.
|
|
979
1047
|
|
|
1048
|
+
- Use `context.api.scheduler` in backend code to create and manage the current plugin's own tasks.
|
|
1049
|
+
- Use `window.mulby.scheduler` in renderer code for task dashboards, task counts, cleanup, and other management UI.
|
|
1050
|
+
|
|
980
1051
|
### 6.1 Creating Tasks
|
|
981
1052
|
|
|
982
1053
|
```typescript
|
|
@@ -1030,29 +1101,25 @@ export async function onBackup({ api }) {
|
|
|
1030
1101
|
### 6.3 Managing Tasks
|
|
1031
1102
|
|
|
1032
1103
|
```typescript
|
|
1033
|
-
//
|
|
1104
|
+
// Backend: list tasks created by the current plugin
|
|
1034
1105
|
const tasks = await api.scheduler.list();
|
|
1035
1106
|
const pending = await api.scheduler.list({ status: 'pending' });
|
|
1036
1107
|
|
|
1037
|
-
//
|
|
1038
|
-
const page1 = await api.scheduler.list({ limit: 20
|
|
1039
|
-
const
|
|
1108
|
+
// Backend pagination and details
|
|
1109
|
+
const page1 = await api.scheduler.list({ limit: 20 });
|
|
1110
|
+
const task = await api.scheduler.get(taskId);
|
|
1111
|
+
const history = await api.scheduler.getExecutions(taskId, 10);
|
|
1040
1112
|
|
|
1041
|
-
//
|
|
1113
|
+
// Backend control
|
|
1042
1114
|
await api.scheduler.pause(taskId);
|
|
1043
1115
|
await api.scheduler.resume(taskId);
|
|
1044
1116
|
await api.scheduler.cancel(taskId);
|
|
1045
1117
|
|
|
1046
|
-
//
|
|
1047
|
-
await
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
await
|
|
1051
|
-
await api.scheduler.cleanup(Date.now() - 30 * 24 * 60 * 60 * 1000); // 30 days
|
|
1052
|
-
|
|
1053
|
-
// Query
|
|
1054
|
-
const task = await api.scheduler.get(taskId);
|
|
1055
|
-
const history = await api.scheduler.getExecutions(taskId, 10);
|
|
1118
|
+
// Renderer: management UI / dashboards
|
|
1119
|
+
const visibleTasks = await window.mulby.scheduler.listTasks({ status: 'pending' });
|
|
1120
|
+
const totalCount = await window.mulby.scheduler.getTaskCount({ status: 'pending' });
|
|
1121
|
+
await window.mulby.scheduler.deleteTasks([taskId1, taskId2, taskId3]);
|
|
1122
|
+
await window.mulby.scheduler.cleanupTasks(Date.now() - 30 * 24 * 60 * 60 * 1000);
|
|
1056
1123
|
```
|
|
1057
1124
|
|
|
1058
1125
|
### 6.4 Advanced Options
|
package/README.md
CHANGED
|
@@ -781,6 +781,19 @@ Mulby CLI 内置了智能任务规划系统,自动识别复杂任务并帮助
|
|
|
781
781
|
3. **逐步执行** - 按照计划执行,完成一项勾选一项
|
|
782
782
|
4. **进度保存** - 中途退出自动保存,下次可继续
|
|
783
783
|
|
|
784
|
+
### AI 插件开发固定流程
|
|
785
|
+
|
|
786
|
+
对 `mulby create <name> --ai`,建议始终遵循这 6 个阶段:
|
|
787
|
+
|
|
788
|
+
1. 先读取 `manifest.json`、`src/main.ts`、`src/ui/App.tsx`
|
|
789
|
+
2. 明确 `features/cmds`、UI/主进程/预加载的职责边界
|
|
790
|
+
3. 先确认接入契约,再开始改文件
|
|
791
|
+
4. 先做一个能在 Mulby 里触发的最小闭环
|
|
792
|
+
5. 再补完整功能与体验
|
|
793
|
+
6. 完成前运行 `validate_plugin`,确认接入检查通过
|
|
794
|
+
|
|
795
|
+
这个流程借鉴了 uTools 官方开发文档里“先锁定插件入口契约,再调试、打包、发布”的成熟做法。
|
|
796
|
+
|
|
784
797
|
### 使用方式
|
|
785
798
|
|
|
786
799
|
**自动触发(推荐)**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mulby-cli",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.7",
|
|
4
4
|
"description": "Mulby 插件开发 CLI 工具",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"files": [
|
|
@@ -12,8 +12,10 @@
|
|
|
12
12
|
"mulby": "dist/index.js"
|
|
13
13
|
},
|
|
14
14
|
"scripts": {
|
|
15
|
-
"build": "tsc &&
|
|
16
|
-
"dev": "tsc -w"
|
|
15
|
+
"build": "tsc && node scripts/copy-ai-assets.mjs",
|
|
16
|
+
"dev": "tsc -w",
|
|
17
|
+
"typecheck": "tsc --noEmit",
|
|
18
|
+
"verify": "npm run typecheck && npm run build"
|
|
17
19
|
},
|
|
18
20
|
"dependencies": {
|
|
19
21
|
"@anthropic-ai/sdk": "^0.71.2",
|