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.
@@ -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
- ├── manifest.json # Plugin Configuration (Manifest V2)
11
- ├── package.json # Dependencies (React, Vite, etc.)
12
- ├── tsconfig.json # TypeScript Configuration
13
- ├── vite.config.ts # Vite Configuration
14
- ├── preload.cjs # Node.js Bridge (Optional, MUST be .cjs)
15
- ├── src/
16
- │ ├── main.ts # Backend Logic (Node.js context)
17
- │ └── ui/ # Frontend Logic (React context)
18
- │ ├── main.tsx # Entry Point
19
- │ ├── App.tsx # Main Component
20
- │ ├── styles.css # Styles
21
- ├── hooks/ # Custom Hooks
22
- │ │ └── useMulby.ts
23
- │ └── vite-env.d.ts
24
- └── assets/ # Icons, etc.
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; // Initial input (if triggered by text)
34
- featureCode?: string; // Feature code structure
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 default { onLoad, onUnload, run };
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 Definition)
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<void>;
771
- install(path: string): Promise<void>;
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<void>;
775
- outPlugin(kill?: boolean): Promise<void>;
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<void>;
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(rect: { x: number; y: number; w: number; h: number }, opts?: any): Promise<Buffer>;
833
- screenCapture(): Promise<string>; // R only, Interactive
834
- colorPick(): Promise<{ hex: string }>; // R only
835
- getSources(opts?: { types: string[] }): Promise<any[]>;
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
- - **Check Status**: `api.plugin.listBackground()`
966
- - **Stop**: `api.plugin.stopBackground(pluginId)`
967
- - **Start**: `api.plugin.startBackground(pluginId)`
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 Only)
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
- // List tasks (current plugin only)
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
- // Pagination
1038
- const page1 = await api.scheduler.list({ limit: 20, offset: 0 });
1039
- const totalCount = await api.scheduler.count({ status: 'pending' });
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
- // Control tasks
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
- // Batch operations
1047
- await api.scheduler.deleteTasks([taskId1, taskId2, taskId3]);
1048
-
1049
- // Cleanup old tasks (completed/failed/cancelled)
1050
- await api.scheduler.cleanup(); // Default: 7 days ago
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.6",
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 && cp src/services/ai/*.md dist/services/ai/",
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",