@leeoohoo/ui-apps-devkit 0.1.1 → 0.1.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/README.md +25 -16
- package/package.json +6 -3
- package/src/commands/init.js +14 -13
- package/src/commands/install.js +12 -11
- package/src/commands/validate.js +69 -21
- package/src/lib/state-constants.js +2 -0
- package/src/sandbox/server.js +1145 -219
- package/templates/basic/README.md +19 -14
- package/templates/basic/docs/CHATOS_UI_APPS_AI_CONTRIBUTIONS.md +36 -34
- package/templates/basic/docs/CHATOS_UI_APPS_BACKEND_PROTOCOL.md +3 -2
- package/templates/basic/docs/CHATOS_UI_APPS_HOST_API.md +1 -1
- package/templates/basic/docs/CHATOS_UI_APPS_OVERVIEW.md +20 -18
- package/templates/basic/docs/CHATOS_UI_APPS_PLUGIN_MANIFEST.md +23 -22
- package/templates/basic/docs/CHATOS_UI_APPS_TROUBLESHOOTING.md +5 -5
- package/templates/basic/docs/CHATOS_UI_PROMPTS_PROTOCOL.md +3 -3
- package/templates/notepad/README.md +28 -19
- package/templates/notepad/docs/CHATOS_UI_APPS_AI_CONTRIBUTIONS.md +36 -34
- package/templates/notepad/docs/CHATOS_UI_APPS_BACKEND_PROTOCOL.md +3 -2
- package/templates/notepad/docs/CHATOS_UI_APPS_HOST_API.md +1 -1
- package/templates/notepad/docs/CHATOS_UI_APPS_OVERVIEW.md +20 -18
- package/templates/notepad/docs/CHATOS_UI_APPS_PLUGIN_MANIFEST.md +23 -22
- package/templates/notepad/docs/CHATOS_UI_APPS_TROUBLESHOOTING.md +5 -5
- package/templates/notepad/docs/CHATOS_UI_PROMPTS_PROTOCOL.md +3 -3
- package/templates/notepad/plugin/apps/app/mcp-server.mjs +8 -1
- package/templates/notepad/plugin/shared/notepad-paths.mjs +41 -23
|
@@ -32,14 +32,15 @@ npm run dev
|
|
|
32
32
|
|
|
33
33
|
## 开发清单(建议)
|
|
34
34
|
|
|
35
|
-
- `plugin/plugin.json`:`apps[i].entry.type` 必须是 `module`,且 `path` 在插件目录内。
|
|
36
|
-
- `plugin/plugin.json`:可选 `apps[i].entry.compact.path`,用于 compact UI。
|
|
35
|
+
- `plugin/plugin.json`:`apps[i].entry.type` 必须是 `module`,且 `path` 在插件目录内。
|
|
36
|
+
- `plugin/plugin.json`:可选 `apps[i].entry.compact.path`,用于 compact UI。
|
|
37
|
+
- 安全:插件目录内尽量避免 symlink(`npm run validate` 会提示),以免路径边界与打包行为不一致。
|
|
37
38
|
- `mount()`:返回卸载函数并清理事件/订阅;滚动放在应用内部,固定内容用 `slots.header`。
|
|
38
|
-
- 主题:用 `host.theme.*` 与 `--ds-*` tokens;避免硬编码颜色。
|
|
39
|
-
- 宿主能力:先判断 `host.bridge.enabled`,非宿主环境要可降级运行。
|
|
40
|
-
- Node 能力:前端不直接用 Node API,需要时走 `host.backend.invoke()`。
|
|
41
|
-
- 打包:依赖需 bundle
|
|
42
|
-
- 提交前:`npm run validate`,必要时再 `pack/install`。
|
|
39
|
+
- 主题:用 `host.theme.*` 与 `--ds-*` tokens;避免硬编码颜色。
|
|
40
|
+
- 宿主能力:先判断 `host.bridge.enabled`,非宿主环境要可降级运行。
|
|
41
|
+
- Node 能力:前端不直接用 Node API,需要时走 `host.backend.invoke()`。
|
|
42
|
+
- 打包:依赖需 bundle 成单文件;ChatOS 导入会排除 `node_modules`,MCP server 不能直接 import 第三方依赖。
|
|
43
|
+
- 提交前:`npm run validate`,必要时再 `pack/install`。
|
|
43
44
|
|
|
44
45
|
## 复用 ChatOS 的 AI 调用(推荐)
|
|
45
46
|
|
|
@@ -48,7 +49,8 @@ npm run dev
|
|
|
48
49
|
1) **前端直连 Chat 域**:用 `host.chat.*` 创建 agent/session、`host.chat.send()` 发送消息、`host.chat.events.subscribe()` 订阅流式事件。
|
|
49
50
|
2) **后端调用 LLM**:在 `plugin/backend/index.mjs` 里通过 `ctx.llm.complete()` 调用模型;前端用 `host.backend.invoke('llmComplete', { input })` 触发。
|
|
50
51
|
|
|
51
|
-
|
|
52
|
+
说明:本地沙箱默认是 mock;可通过右上角 `AI Config` 配置 `API Key / Base URL / Model ID` 后启用真实模型调用,并用于测试应用 MCP(需配置 `ai.mcp`)。
|
|
53
|
+
补充:沙箱默认把 `_meta.workdir` 设为 `dataDir`;如需模拟其它工作目录,可在 `AI Config` 里设置 `Workdir` 覆盖(支持 `$dataDir/$pluginDir/$projectRoot`)。
|
|
52
54
|
|
|
53
55
|
## 安装到本机 ChatOS
|
|
54
56
|
|
|
@@ -69,9 +71,12 @@ npm run pack
|
|
|
69
71
|
|
|
70
72
|
## 启用 MCP(可选)
|
|
71
73
|
|
|
72
|
-
本模板默认只启用 `ai.mcpPrompt`(不启用 `ai.mcp`),避免第三方插件在未打包依赖时运行失败。
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
74
|
+
本模板默认只启用 `ai.mcpPrompt`(不启用 `ai.mcp`),避免第三方插件在未打包依赖时运行失败。
|
|
75
|
+
|
|
76
|
+
⚠️ ChatOS 导入插件时会排除 `node_modules/`。因此 MCP server 只要用了第三方依赖(如 `@modelcontextprotocol/sdk`、`zod`),就必须先 bundle 成单文件,或把依赖源码放进插件目录。
|
|
77
|
+
若看到 `Cannot find package '@modelcontextprotocol/sdk'`,说明依赖未被 bundle。
|
|
78
|
+
|
|
79
|
+
如果你要启用 MCP:
|
|
80
|
+
|
|
81
|
+
1) 实现并打包 `plugin/apps/__APP_ID__/mcp-server.mjs`(必须 bundle 成单文件,除非完全不依赖第三方)
|
|
82
|
+
2) 在 `plugin/plugin.json` 的 `apps[i].ai.mcp` 写入 `entry/command/args/...` 并指向 bundle 产物
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
|
|
10
10
|
实现对照(以代码为准):
|
|
11
11
|
|
|
12
|
-
- schema:`
|
|
13
|
-
- 扫描与贡献解析:`
|
|
12
|
+
- schema:`chatos/electron/ui-apps/schemas.js`
|
|
13
|
+
- 扫描与贡献解析:`chatos/electron/ui-apps/index.js`(`#resolveAi` / `getAiContribution()`;可选 `#syncAiContributes` 持久化到 Admin DB)
|
|
14
14
|
- 内置默认清单:`aide/shared/defaults/ui-apps-expose/`
|
|
15
15
|
|
|
16
16
|
## 1. 两种暴露方式(应用侧选择其一或组合)
|
|
@@ -71,40 +71,42 @@
|
|
|
71
71
|
- `cmd://<command> <absEntryOrRelEntry> <args...>`
|
|
72
72
|
- `command` 默认为 `node`
|
|
73
73
|
|
|
74
|
-
当 `ai.mcp.url` 存在时,直接使用该 url(远程/HTTP/WS 等)。
|
|
75
|
-
|
|
76
|
-
### 3.1 `ai.mcp.callMeta`(调用方上下文 / 非工具参数)
|
|
77
|
-
|
|
78
|
-
当 ChatOS 调用 MCP tools 时,会把 `ai.mcp.callMeta` 注入到 `tools/call` 的 `_meta` 中(不属于工具参数,因此不会暴露给 AI)。
|
|
79
|
-
|
|
80
|
-
同时,宿主默认注入 `_meta.chatos.uiApp`,包含:
|
|
81
|
-
|
|
82
|
-
- `pluginId` / `appId`
|
|
83
|
-
- `pluginDir` / `dataDir`
|
|
84
|
-
- `stateDir` / `sessionRoot` / `projectRoot`
|
|
85
|
-
|
|
74
|
+
当 `ai.mcp.url` 存在时,直接使用该 url(远程/HTTP/WS 等)。
|
|
75
|
+
|
|
76
|
+
### 3.1 `ai.mcp.callMeta`(调用方上下文 / 非工具参数)
|
|
77
|
+
|
|
78
|
+
当 ChatOS 调用 MCP tools 时,会把 `ai.mcp.callMeta` 注入到 `tools/call` 的 `_meta` 中(不属于工具参数,因此不会暴露给 AI)。
|
|
79
|
+
|
|
80
|
+
同时,宿主默认注入 `_meta.chatos.uiApp`,包含:
|
|
81
|
+
|
|
82
|
+
- `pluginId` / `appId`
|
|
83
|
+
- `pluginDir` / `dataDir`
|
|
84
|
+
- `stateDir` / `sessionRoot` / `projectRoot`
|
|
85
|
+
|
|
86
86
|
同时,宿主默认注入 `_meta.workdir`(默认等于 `dataDir`;如需指定其它目录,可在 `ai.mcp.callMeta.workdir` 覆盖)。
|
|
87
87
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
```json
|
|
91
|
-
{
|
|
92
|
-
"ai": {
|
|
93
|
-
"mcp": {
|
|
94
|
-
"entry": "my-app/mcp-server.mjs",
|
|
95
|
-
"callMeta": { "workdir": "$dataDir" }
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
在 MCP server 中读取(SDK handler 的 `extra._meta`):
|
|
102
|
-
|
|
103
|
-
```js
|
|
104
|
-
const workdir = extra?._meta?.workdir || extra?._meta?.chatos?.uiApp?.dataDir;
|
|
105
|
-
```
|
|
88
|
+
> DevKit sandbox:右上角 `AI Config` 支持设置 `Workdir` 覆盖;留空即使用 `dataDir`(也支持 `$dataDir/$pluginDir/$projectRoot`)。
|
|
106
89
|
|
|
107
|
-
|
|
90
|
+
示例(`plugin.json`):
|
|
91
|
+
|
|
92
|
+
```json
|
|
93
|
+
{
|
|
94
|
+
"ai": {
|
|
95
|
+
"mcp": {
|
|
96
|
+
"entry": "my-app/mcp-server.mjs",
|
|
97
|
+
"callMeta": { "workdir": "$dataDir" }
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
在 MCP server 中读取(SDK handler 的 `extra._meta`):
|
|
104
|
+
|
|
105
|
+
```js
|
|
106
|
+
const workdir = extra?._meta?.workdir || extra?._meta?.chatos?.uiApp?.dataDir;
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## 4. Agent UI 如何消费应用暴露(你需要知道的运行机制)
|
|
108
110
|
|
|
109
111
|
### 4.1 体现在哪里(持久化 vs 运行时注入)
|
|
110
112
|
|
|
@@ -145,7 +147,7 @@ const workdir = extra?._meta?.workdir || extra?._meta?.chatos?.uiApp?.dataDir;
|
|
|
145
147
|
|
|
146
148
|
内置应用采用两层设计:
|
|
147
149
|
|
|
148
|
-
1) 宿主侧(`
|
|
150
|
+
1) 宿主侧(`chatos` 的 `plugin.json`)只保留粗粒度开关:
|
|
149
151
|
|
|
150
152
|
```json
|
|
151
153
|
{ "ai": { "mcpServers": true, "prompts": true } }
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
实现对照(以代码为准):
|
|
6
6
|
|
|
7
|
-
- `
|
|
7
|
+
- `chatos/electron/ui-apps/index.js`(`uiApps:invoke` 与后端加载/缓存)
|
|
8
8
|
|
|
9
9
|
## 1. 开启后端:`plugin.json`
|
|
10
10
|
|
|
@@ -55,7 +55,8 @@ export async function createUiAppsBackend(ctx) {
|
|
|
55
55
|
- `pluginId`:插件 ID
|
|
56
56
|
- `pluginDir`:插件安装目录(只读引用;用于读取插件资源)
|
|
57
57
|
- `dataDir`:`<stateDir>/ui_apps/data/<pluginId>`(插件可写数据目录;宿主会确保存在)
|
|
58
|
-
- `stateDir
|
|
58
|
+
- `stateDir`:每个应用的状态根目录(`<stateRoot>/<hostApp>`;ChatOS 的 `hostApp=chatos`)
|
|
59
|
+
- 兼容旧路径:若存在 `legacyStateRoot/<hostApp>`,启动时会自动迁移到 `stateDir`
|
|
59
60
|
- `sessionRoot`:会话根
|
|
60
61
|
- `projectRoot`:宿主工程根(开发态下有用)
|
|
61
62
|
- `llm`:可选(共享模型调用接口)
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
## 术语与角色
|
|
16
16
|
|
|
17
|
-
- **ChatOS(宿主)**:桌面端 Electron 应用(本仓库的 `
|
|
17
|
+
- **ChatOS(宿主)**:桌面端 Electron 应用(本仓库的 `chatos`)。
|
|
18
18
|
- **AIDE(引擎)**:模型调用/工具/MCP/子代理等核心能力(本仓库的 `aide`)。
|
|
19
19
|
- **UI Apps(嵌入应用/小应用)**:以插件形式注入到桌面端「应用」中心的应用。
|
|
20
20
|
- **MCP**:Model Context Protocol;通过 MCP Server 暴露 tools,最终工具名通常为 `mcp_<serverName>_<toolName>`。
|
|
@@ -22,11 +22,13 @@
|
|
|
22
22
|
|
|
23
23
|
## 目录与状态(sessionRoot / stateDir)
|
|
24
24
|
|
|
25
|
-
- `sessionRoot`:会话根目录
|
|
26
|
-
- 默认:用户主目录(Home)
|
|
27
|
-
- 可通过环境变量覆盖:`MODEL_CLI_SESSION_ROOT=/path/to/root`
|
|
28
|
-
|
|
29
|
-
-
|
|
25
|
+
- `sessionRoot`:会话根目录
|
|
26
|
+
- 默认:用户主目录(Home)
|
|
27
|
+
- 可通过环境变量覆盖:`MODEL_CLI_SESSION_ROOT=/path/to/root`
|
|
28
|
+
- `stateRoot`:用户状态根目录
|
|
29
|
+
- 桌面端/CLI 会把“上次使用的 sessionRoot”记录到 `<stateRoot>/last-session-root.txt`(未设置 env 时会优先读取)
|
|
30
|
+
- `stateDir`:`<stateRoot>/<hostApp>`(ChatOS 的 `hostApp=chatos`)
|
|
31
|
+
- 兼容旧路径:若存在 `legacyStateRoot/<hostApp>`,启动时会自动迁移到 `stateDir`
|
|
30
32
|
|
|
31
33
|
全局配置(由宿主维护;应用侧只读/复用):
|
|
32
34
|
|
|
@@ -46,8 +48,8 @@
|
|
|
46
48
|
|
|
47
49
|
宿主会扫描两个目录(并在 UI「应用」页展示实际路径):
|
|
48
50
|
|
|
49
|
-
- **内置/开发目录**:`
|
|
50
|
-
- **用户插件目录**:`<stateDir>/ui_apps/plugins
|
|
51
|
+
- **内置/开发目录**:`chatos/ui_apps/plugins`
|
|
52
|
+
- **用户插件目录**:`<stateDir>/ui_apps/plugins`(`stateDir = <stateRoot>/<hostApp>`)
|
|
51
53
|
|
|
52
54
|
同名 `plugin.id` 的覆盖规则:
|
|
53
55
|
|
|
@@ -69,7 +71,7 @@
|
|
|
69
71
|
|
|
70
72
|
导入时的复制规则(重要):
|
|
71
73
|
|
|
72
|
-
- 会拷贝到用户插件目录
|
|
74
|
+
- 会拷贝到用户插件目录 `<stateDir>/ui_apps/plugins/<sanitized(plugin.id)>/`;
|
|
73
75
|
- 默认会排除:`node_modules/`、`.git/`、`.DS_Store`、`*.map`;
|
|
74
76
|
- 因此若插件需要依赖,请在构建时做 bundle(不要指望随包携带 `node_modules` 生效)。
|
|
75
77
|
|
|
@@ -89,7 +91,7 @@
|
|
|
89
91
|
|
|
90
92
|
## 最短接入路径(TL;DR)
|
|
91
93
|
|
|
92
|
-
1) 从模板复制:`
|
|
94
|
+
1) 从模板复制:`chatos/ui_apps/template/basic-plugin` → 放进任一插件目录
|
|
93
95
|
2) 修改 `plugin.json`:只支持 `apps[i].entry.type="module"`(可选增加 `entry.compact` 作为紧凑 UI 入口)
|
|
94
96
|
3) 桌面端打开「应用」页 → 点“刷新” → 进入你的应用
|
|
95
97
|
4) (可选)需要 Node 能力:加 `backend.entry`,前端用 `host.backend.invoke()`
|
|
@@ -99,15 +101,15 @@
|
|
|
99
101
|
|
|
100
102
|
## 实现位置(便于对照代码)
|
|
101
103
|
|
|
102
|
-
- schema(`plugin.json` / `apps[i].ai`):`
|
|
103
|
-
- 插件扫描/入口校验/AI 同步:`
|
|
104
|
-
- 应用包导入(目录/zip):`
|
|
105
|
-
- module 运行时 Host API 注入:`
|
|
104
|
+
- schema(`plugin.json` / `apps[i].ai`):`chatos/electron/ui-apps/schemas.js`
|
|
105
|
+
- 插件扫描/入口校验/AI 同步:`chatos/electron/ui-apps/index.js`
|
|
106
|
+
- 应用包导入(目录/zip):`chatos/electron/ui-apps/plugin-installer.js`
|
|
107
|
+
- module 运行时 Host API 注入:`chatos/apps/ui/src/features/apps/AppsPluginView.jsx`
|
|
106
108
|
|
|
107
109
|
## 原始文档来源(本次提取/整合)
|
|
108
110
|
|
|
109
|
-
- `
|
|
110
|
-
- `
|
|
111
|
-
- `
|
|
112
|
-
- `
|
|
111
|
+
- `chatos/doc/app-dev-handbook.md`
|
|
112
|
+
- `chatos/doc/app-integration.md`
|
|
113
|
+
- `chatos/doc/ui-apps-plugins.md`
|
|
114
|
+
- `chatos/doc/ui-apps-dev-guide.md`
|
|
113
115
|
- `aide/shared/defaults/ui-apps-expose/README.md`
|
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
|
|
5
5
|
实现对照(以代码为准):
|
|
6
6
|
|
|
7
|
-
- schema:`
|
|
8
|
-
- 扫描/校验:`
|
|
9
|
-
- 导入/安装:`
|
|
7
|
+
- schema:`chatos/electron/ui-apps/schemas.js`
|
|
8
|
+
- 扫描/校验:`chatos/electron/ui-apps/index.js`
|
|
9
|
+
- 导入/安装:`chatos/electron/ui-apps/plugin-installer.js`
|
|
10
10
|
|
|
11
11
|
另见:
|
|
12
12
|
|
|
@@ -18,8 +18,9 @@
|
|
|
18
18
|
|
|
19
19
|
- 每个插件一个目录,目录根部必须包含 `plugin.json`。
|
|
20
20
|
- 插件目录可放在:
|
|
21
|
-
- `
|
|
22
|
-
-
|
|
21
|
+
- `chatos/ui_apps/plugins`(内置/开发)
|
|
22
|
+
- `<stateDir>/ui_apps/plugins`(用户插件目录;`stateDir = <stateRoot>/<hostApp>`)
|
|
23
|
+
- 兼容旧路径:若存在 `legacyStateRoot/<hostApp>/ui_apps/plugins`,启动时会自动迁移到 `stateDir`
|
|
23
24
|
- 也可通过桌面端 UI:`应用` → `导入应用包`(目录或 `.zip`)安装到用户插件目录。
|
|
24
25
|
|
|
25
26
|
## 2. 顶层 schema(`uiAppsPluginSchema`)
|
|
@@ -128,16 +129,16 @@
|
|
|
128
129
|
|
|
129
130
|
| 字段 | 类型 | 必填 | 默认 | 说明 |
|
|
130
131
|
|---|---:|---:|---|---|
|
|
131
|
-
| `url` | `string` | 二选一 | - | 远程 MCP Server 地址(`http(s)://` / `ws(s)://` 等) |
|
|
132
|
-
| `entry` | `string` | 二选一 | - | 本地脚本入口(相对插件目录);宿主会转换为 `cmd://...` |
|
|
133
|
-
| `command` | `string` | 否 | `"node"` | 拉起本地 `entry` 时使用的命令 |
|
|
134
|
-
| `args` | `string[]` | 否 | `[]` | 拉起时追加参数 |
|
|
135
|
-
| `callMeta` | `object` | 否 | - | 调用 MCP 工具时注入到 `_meta` 的附加字段(不会暴露给 AI);支持 `$pluginId/$appId/$pluginDir/$dataDir/$stateDir/$sessionRoot/$projectRoot` 变量 |
|
|
136
|
-
| `description` | `string` | 否 | `""` | 描述 |
|
|
137
|
-
| `tags` | `string[]` | 否 | `[]` | 标签(宿主还会自动附加 `uiapp*` 标签) |
|
|
138
|
-
| `enabled` | `boolean` | 否 | - | 是否启用(未填则宿主同步时默认 `true`) |
|
|
139
|
-
| `allowMain` | `boolean` | 否 | - | 是否允许主流程使用(未填则宿主同步时默认 `true`) |
|
|
140
|
-
| `allowSub` | `boolean` | 否 | - | 是否允许子代理使用(未填则宿主同步时默认 `true`) |
|
|
132
|
+
| `url` | `string` | 二选一 | - | 远程 MCP Server 地址(`http(s)://` / `ws(s)://` 等) |
|
|
133
|
+
| `entry` | `string` | 二选一 | - | 本地脚本入口(相对插件目录);宿主会转换为 `cmd://...` |
|
|
134
|
+
| `command` | `string` | 否 | `"node"` | 拉起本地 `entry` 时使用的命令 |
|
|
135
|
+
| `args` | `string[]` | 否 | `[]` | 拉起时追加参数 |
|
|
136
|
+
| `callMeta` | `object` | 否 | - | 调用 MCP 工具时注入到 `_meta` 的附加字段(不会暴露给 AI);支持 `$pluginId/$appId/$pluginDir/$dataDir/$stateDir/$sessionRoot/$projectRoot` 变量 |
|
|
137
|
+
| `description` | `string` | 否 | `""` | 描述 |
|
|
138
|
+
| `tags` | `string[]` | 否 | `[]` | 标签(宿主还会自动附加 `uiapp*` 标签) |
|
|
139
|
+
| `enabled` | `boolean` | 否 | - | 是否启用(未填则宿主同步时默认 `true`) |
|
|
140
|
+
| `allowMain` | `boolean` | 否 | - | 是否允许主流程使用(未填则宿主同步时默认 `true`) |
|
|
141
|
+
| `allowSub` | `boolean` | 否 | - | 是否允许子代理使用(未填则宿主同步时默认 `true`) |
|
|
141
142
|
| `auth` | `object` | 否 | - | 认证信息(token/basic/headers) |
|
|
142
143
|
|
|
143
144
|
强约束:
|
|
@@ -156,13 +157,13 @@
|
|
|
156
157
|
}
|
|
157
158
|
```
|
|
158
159
|
|
|
159
|
-
当使用 `entry` 时,宿主会把它转换为可运行的 `cmd://`:
|
|
160
|
-
|
|
161
|
-
- `command` 默认为 `node`
|
|
162
|
-
- `args` 会追加到命令行末尾
|
|
163
|
-
- 宿主会把空格/引号等做安全引用,以避免路径包含空格时解析失败
|
|
164
|
-
|
|
165
|
-
`callMeta` 会随每次 `tools/call` 请求发送给 MCP server(位于 `request.params._meta`),默认会合并宿主注入的 `_meta.chatos.uiApp`(含 `pluginId/appId/pluginDir/dataDir/stateDir/sessionRoot/projectRoot`)与 `_meta.workdir`(默认等于 `dataDir`,可被 `callMeta.workdir` 覆盖)。
|
|
160
|
+
当使用 `entry` 时,宿主会把它转换为可运行的 `cmd://`:
|
|
161
|
+
|
|
162
|
+
- `command` 默认为 `node`
|
|
163
|
+
- `args` 会追加到命令行末尾
|
|
164
|
+
- 宿主会把空格/引号等做安全引用,以避免路径包含空格时解析失败
|
|
165
|
+
|
|
166
|
+
`callMeta` 会随每次 `tools/call` 请求发送给 MCP server(位于 `request.params._meta`),默认会合并宿主注入的 `_meta.chatos.uiApp`(含 `pluginId/appId/pluginDir/dataDir/stateDir/sessionRoot/projectRoot`)与 `_meta.workdir`(默认等于 `dataDir`,可被 `callMeta.workdir` 覆盖)。
|
|
166
167
|
|
|
167
168
|
## 6. `ai.mcpPrompt`:应用默认 Prompt 声明
|
|
168
169
|
|
|
@@ -38,8 +38,8 @@
|
|
|
38
38
|
- 原因: 未调用 `host.uiPrompts.open()`, 或 `prompt.kind` 填写错误.
|
|
39
39
|
- 处理: 先调用 `open()` 打开面板, 并按协议填写 `prompt`.
|
|
40
40
|
|
|
41
|
-
## 7. MCP 不生效
|
|
42
|
-
|
|
43
|
-
- 现象: MCP tools / prompts 未出现.
|
|
44
|
-
- 原因: 未在 `plugin.json` 启用 `ai.mcp
|
|
45
|
-
- 处理: bundle
|
|
41
|
+
## 7. MCP 不生效
|
|
42
|
+
|
|
43
|
+
- 现象: MCP tools / prompts 未出现.
|
|
44
|
+
- 原因: 未在 `plugin.json` 启用 `ai.mcp`, 或 MCP 依赖未 bundle(ChatOS 导入会剔除 `node_modules`).
|
|
45
|
+
- 处理: 将 MCP server bundle 成单文件(或 vendor 依赖), 并检查 `ai.mcp.entry` / `ai.mcpPrompt` 配置.
|
|
@@ -11,9 +11,9 @@ UI Prompts 是 ChatOS 的全局交互队列:任意组件(AI / MCP / UI Apps
|
|
|
11
11
|
|
|
12
12
|
实现对照(以代码为准):
|
|
13
13
|
|
|
14
|
-
- UI 渲染:`
|
|
15
|
-
- 笑脸面板:`
|
|
16
|
-
- Host IPC:`
|
|
14
|
+
- UI 渲染:`chatos/apps/ui/src/features/session/floating-island/FloatingIslandPrompt.jsx`
|
|
15
|
+
- 笑脸面板:`chatos/apps/ui/src/components/UiPromptsSmileHub.jsx`
|
|
16
|
+
- Host IPC:`chatos/electron/main.js`(`uiPrompts:*`)
|
|
17
17
|
- 写入/读取日志:`aide/electron/session-api.js`(`requestUiPrompt` / `respondUiPrompt` / `readUiPromptsPayload`)
|
|
18
18
|
- MCP `ui_prompter`:`aide/mcp_servers/ui-prompt-server.js`
|
|
19
19
|
|
|
@@ -4,12 +4,17 @@
|
|
|
4
4
|
|
|
5
5
|
## 快速开始
|
|
6
6
|
|
|
7
|
-
```bash
|
|
8
|
-
npm install
|
|
9
|
-
npm run dev
|
|
10
|
-
```
|
|
11
|
-
|
|
12
|
-
##
|
|
7
|
+
```bash
|
|
8
|
+
npm install
|
|
9
|
+
npm run dev
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## 本地沙箱 AI Config(可选)
|
|
13
|
+
|
|
14
|
+
- 右上角 `AI Config` 可配置 `API Key / Base URL / Model ID`,用于测试真实模型调用(以及 MCP 调用)。
|
|
15
|
+
- 沙箱默认把 `_meta.workdir` 设为 `dataDir`;如需模拟其它工作目录,可在 `AI Config` 里设置 `Workdir` 覆盖(支持 `$dataDir/$pluginDir/$projectRoot`)。
|
|
16
|
+
|
|
17
|
+
## 目录说明
|
|
13
18
|
|
|
14
19
|
- `plugin/plugin.json`:插件清单(应用列表、入口、后端、AI 贡献)
|
|
15
20
|
- `plugin/apps/__APP_ID__/`:前端 module(浏览器环境,导出 `mount({ container, host, slots })`)
|
|
@@ -27,14 +32,15 @@ npm run dev
|
|
|
27
32
|
|
|
28
33
|
## 开发清单(建议)
|
|
29
34
|
|
|
30
|
-
- `plugin/plugin.json`:`apps[i].entry.type` 必须是 `module`,且 `path` 在插件目录内。
|
|
31
|
-
- `plugin/plugin.json`:可选 `apps[i].entry.compact.path`,用于 compact UI。
|
|
35
|
+
- `plugin/plugin.json`:`apps[i].entry.type` 必须是 `module`,且 `path` 在插件目录内。
|
|
36
|
+
- `plugin/plugin.json`:可选 `apps[i].entry.compact.path`,用于 compact UI。
|
|
37
|
+
- 安全:插件目录内尽量避免 symlink(`npm run validate` 会提示),以免路径边界与打包行为不一致。
|
|
32
38
|
- `mount()`:返回卸载函数并清理事件/订阅;滚动放在应用内部,固定内容用 `slots.header`。
|
|
33
|
-
- 主题:用 `host.theme.*` 与 `--ds-*` tokens;避免硬编码颜色。
|
|
34
|
-
- 宿主能力:先判断 `host.bridge.enabled`,非宿主环境要可降级运行。
|
|
35
|
-
- Node 能力:前端不直接用 Node API,需要时走 `host.backend.invoke()`。
|
|
36
|
-
- 打包:依赖需 bundle
|
|
37
|
-
- 提交前:`npm run validate`,必要时再 `pack/install`。
|
|
39
|
+
- 主题:用 `host.theme.*` 与 `--ds-*` tokens;避免硬编码颜色。
|
|
40
|
+
- 宿主能力:先判断 `host.bridge.enabled`,非宿主环境要可降级运行。
|
|
41
|
+
- Node 能力:前端不直接用 Node API,需要时走 `host.backend.invoke()`。
|
|
42
|
+
- 打包:依赖需 bundle 成单文件;ChatOS 导入会排除 `node_modules`,MCP server 不能直接 import 第三方依赖。
|
|
43
|
+
- 提交前:`npm run validate`,必要时再 `pack/install`。
|
|
38
44
|
|
|
39
45
|
## 协议文档
|
|
40
46
|
|
|
@@ -50,9 +56,12 @@ npm run dev
|
|
|
50
56
|
|
|
51
57
|
## MCP(可选)
|
|
52
58
|
|
|
53
|
-
模板内包含 `plugin/apps/__APP_ID__/mcp-server.mjs` 与 `mcp-prompt.*.md`,但默认 **未在** `plugin/plugin.json` 启用 `ai.mcp`(避免打包时遗漏依赖导致运行失败)。
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
+
模板内包含 `plugin/apps/__APP_ID__/mcp-server.mjs` 与 `mcp-prompt.*.md`,但默认 **未在** `plugin/plugin.json` 启用 `ai.mcp`(避免打包时遗漏依赖导致运行失败)。
|
|
60
|
+
|
|
61
|
+
⚠️ ChatOS 导入插件时会排除 `node_modules/`。因此 MCP server 只要用了第三方依赖(如 `@modelcontextprotocol/sdk`、`zod`),就必须先 bundle 成单文件,或把依赖源码放进插件目录。
|
|
62
|
+
若看到 `Cannot find package '@modelcontextprotocol/sdk'`,说明依赖未被 bundle。
|
|
63
|
+
|
|
64
|
+
如需启用 MCP:
|
|
65
|
+
|
|
66
|
+
1) 实现并 **bundle 成单文件**(必须;用 esbuild/rollup,把 `@modelcontextprotocol/sdk` 等依赖打进去)
|
|
67
|
+
2) 在 `plugin/plugin.json` 的 `apps[i].ai.mcp` 写入 `entry/command/args/...` 并指向 bundle 产物
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
|
|
10
10
|
实现对照(以代码为准):
|
|
11
11
|
|
|
12
|
-
- schema:`
|
|
13
|
-
- 扫描与贡献解析:`
|
|
12
|
+
- schema:`chatos/electron/ui-apps/schemas.js`
|
|
13
|
+
- 扫描与贡献解析:`chatos/electron/ui-apps/index.js`(`#resolveAi` / `getAiContribution()`;可选 `#syncAiContributes` 持久化到 Admin DB)
|
|
14
14
|
- 内置默认清单:`aide/shared/defaults/ui-apps-expose/`
|
|
15
15
|
|
|
16
16
|
## 1. 两种暴露方式(应用侧选择其一或组合)
|
|
@@ -71,40 +71,42 @@
|
|
|
71
71
|
- `cmd://<command> <absEntryOrRelEntry> <args...>`
|
|
72
72
|
- `command` 默认为 `node`
|
|
73
73
|
|
|
74
|
-
当 `ai.mcp.url` 存在时,直接使用该 url(远程/HTTP/WS 等)。
|
|
75
|
-
|
|
76
|
-
### 3.1 `ai.mcp.callMeta`(调用方上下文 / 非工具参数)
|
|
77
|
-
|
|
78
|
-
当 ChatOS 调用 MCP tools 时,会把 `ai.mcp.callMeta` 注入到 `tools/call` 的 `_meta` 中(不属于工具参数,因此不会暴露给 AI)。
|
|
79
|
-
|
|
80
|
-
同时,宿主默认注入 `_meta.chatos.uiApp`,包含:
|
|
81
|
-
|
|
82
|
-
- `pluginId` / `appId`
|
|
83
|
-
- `pluginDir` / `dataDir`
|
|
84
|
-
- `stateDir` / `sessionRoot` / `projectRoot`
|
|
85
|
-
|
|
74
|
+
当 `ai.mcp.url` 存在时,直接使用该 url(远程/HTTP/WS 等)。
|
|
75
|
+
|
|
76
|
+
### 3.1 `ai.mcp.callMeta`(调用方上下文 / 非工具参数)
|
|
77
|
+
|
|
78
|
+
当 ChatOS 调用 MCP tools 时,会把 `ai.mcp.callMeta` 注入到 `tools/call` 的 `_meta` 中(不属于工具参数,因此不会暴露给 AI)。
|
|
79
|
+
|
|
80
|
+
同时,宿主默认注入 `_meta.chatos.uiApp`,包含:
|
|
81
|
+
|
|
82
|
+
- `pluginId` / `appId`
|
|
83
|
+
- `pluginDir` / `dataDir`
|
|
84
|
+
- `stateDir` / `sessionRoot` / `projectRoot`
|
|
85
|
+
|
|
86
86
|
同时,宿主默认注入 `_meta.workdir`(默认等于 `dataDir`;如需指定其它目录,可在 `ai.mcp.callMeta.workdir` 覆盖)。
|
|
87
87
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
```json
|
|
91
|
-
{
|
|
92
|
-
"ai": {
|
|
93
|
-
"mcp": {
|
|
94
|
-
"entry": "my-app/mcp-server.mjs",
|
|
95
|
-
"callMeta": { "workdir": "$dataDir" }
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
在 MCP server 中读取(SDK handler 的 `extra._meta`):
|
|
102
|
-
|
|
103
|
-
```js
|
|
104
|
-
const workdir = extra?._meta?.workdir || extra?._meta?.chatos?.uiApp?.dataDir;
|
|
105
|
-
```
|
|
88
|
+
> DevKit sandbox:右上角 `AI Config` 支持设置 `Workdir` 覆盖;留空即使用 `dataDir`(也支持 `$dataDir/$pluginDir/$projectRoot`)。
|
|
106
89
|
|
|
107
|
-
|
|
90
|
+
示例(`plugin.json`):
|
|
91
|
+
|
|
92
|
+
```json
|
|
93
|
+
{
|
|
94
|
+
"ai": {
|
|
95
|
+
"mcp": {
|
|
96
|
+
"entry": "my-app/mcp-server.mjs",
|
|
97
|
+
"callMeta": { "workdir": "$dataDir" }
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
在 MCP server 中读取(SDK handler 的 `extra._meta`):
|
|
104
|
+
|
|
105
|
+
```js
|
|
106
|
+
const workdir = extra?._meta?.workdir || extra?._meta?.chatos?.uiApp?.dataDir;
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## 4. Agent UI 如何消费应用暴露(你需要知道的运行机制)
|
|
108
110
|
|
|
109
111
|
### 4.1 体现在哪里(持久化 vs 运行时注入)
|
|
110
112
|
|
|
@@ -145,7 +147,7 @@ const workdir = extra?._meta?.workdir || extra?._meta?.chatos?.uiApp?.dataDir;
|
|
|
145
147
|
|
|
146
148
|
内置应用采用两层设计:
|
|
147
149
|
|
|
148
|
-
1) 宿主侧(`
|
|
150
|
+
1) 宿主侧(`chatos` 的 `plugin.json`)只保留粗粒度开关:
|
|
149
151
|
|
|
150
152
|
```json
|
|
151
153
|
{ "ai": { "mcpServers": true, "prompts": true } }
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
实现对照(以代码为准):
|
|
6
6
|
|
|
7
|
-
- `
|
|
7
|
+
- `chatos/electron/ui-apps/index.js`(`uiApps:invoke` 与后端加载/缓存)
|
|
8
8
|
|
|
9
9
|
## 1. 开启后端:`plugin.json`
|
|
10
10
|
|
|
@@ -55,7 +55,8 @@ export async function createUiAppsBackend(ctx) {
|
|
|
55
55
|
- `pluginId`:插件 ID
|
|
56
56
|
- `pluginDir`:插件安装目录(只读引用;用于读取插件资源)
|
|
57
57
|
- `dataDir`:`<stateDir>/ui_apps/data/<pluginId>`(插件可写数据目录;宿主会确保存在)
|
|
58
|
-
- `stateDir
|
|
58
|
+
- `stateDir`:每个应用的状态根目录(`<stateRoot>/<hostApp>`;ChatOS 的 `hostApp=chatos`)
|
|
59
|
+
- 兼容旧路径:若存在 `legacyStateRoot/<hostApp>`,启动时会自动迁移到 `stateDir`
|
|
59
60
|
- `sessionRoot`:会话根
|
|
60
61
|
- `projectRoot`:宿主工程根(开发态下有用)
|
|
61
62
|
- `llm`:可选(共享模型调用接口)
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
## 术语与角色
|
|
16
16
|
|
|
17
|
-
- **ChatOS(宿主)**:桌面端 Electron 应用(本仓库的 `
|
|
17
|
+
- **ChatOS(宿主)**:桌面端 Electron 应用(本仓库的 `chatos`)。
|
|
18
18
|
- **AIDE(引擎)**:模型调用/工具/MCP/子代理等核心能力(本仓库的 `aide`)。
|
|
19
19
|
- **UI Apps(嵌入应用/小应用)**:以插件形式注入到桌面端「应用」中心的应用。
|
|
20
20
|
- **MCP**:Model Context Protocol;通过 MCP Server 暴露 tools,最终工具名通常为 `mcp_<serverName>_<toolName>`。
|
|
@@ -22,11 +22,13 @@
|
|
|
22
22
|
|
|
23
23
|
## 目录与状态(sessionRoot / stateDir)
|
|
24
24
|
|
|
25
|
-
- `sessionRoot`:会话根目录
|
|
26
|
-
- 默认:用户主目录(Home)
|
|
27
|
-
- 可通过环境变量覆盖:`MODEL_CLI_SESSION_ROOT=/path/to/root`
|
|
28
|
-
|
|
29
|
-
-
|
|
25
|
+
- `sessionRoot`:会话根目录
|
|
26
|
+
- 默认:用户主目录(Home)
|
|
27
|
+
- 可通过环境变量覆盖:`MODEL_CLI_SESSION_ROOT=/path/to/root`
|
|
28
|
+
- `stateRoot`:用户状态根目录
|
|
29
|
+
- 桌面端/CLI 会把“上次使用的 sessionRoot”记录到 `<stateRoot>/last-session-root.txt`(未设置 env 时会优先读取)
|
|
30
|
+
- `stateDir`:`<stateRoot>/<hostApp>`(ChatOS 的 `hostApp=chatos`)
|
|
31
|
+
- 兼容旧路径:若存在 `legacyStateRoot/<hostApp>`,启动时会自动迁移到 `stateDir`
|
|
30
32
|
|
|
31
33
|
全局配置(由宿主维护;应用侧只读/复用):
|
|
32
34
|
|
|
@@ -46,8 +48,8 @@
|
|
|
46
48
|
|
|
47
49
|
宿主会扫描两个目录(并在 UI「应用」页展示实际路径):
|
|
48
50
|
|
|
49
|
-
- **内置/开发目录**:`
|
|
50
|
-
- **用户插件目录**:`<stateDir>/ui_apps/plugins
|
|
51
|
+
- **内置/开发目录**:`chatos/ui_apps/plugins`
|
|
52
|
+
- **用户插件目录**:`<stateDir>/ui_apps/plugins`(`stateDir = <stateRoot>/<hostApp>`)
|
|
51
53
|
|
|
52
54
|
同名 `plugin.id` 的覆盖规则:
|
|
53
55
|
|
|
@@ -69,7 +71,7 @@
|
|
|
69
71
|
|
|
70
72
|
导入时的复制规则(重要):
|
|
71
73
|
|
|
72
|
-
- 会拷贝到用户插件目录
|
|
74
|
+
- 会拷贝到用户插件目录 `<stateDir>/ui_apps/plugins/<sanitized(plugin.id)>/`;
|
|
73
75
|
- 默认会排除:`node_modules/`、`.git/`、`.DS_Store`、`*.map`;
|
|
74
76
|
- 因此若插件需要依赖,请在构建时做 bundle(不要指望随包携带 `node_modules` 生效)。
|
|
75
77
|
|
|
@@ -89,7 +91,7 @@
|
|
|
89
91
|
|
|
90
92
|
## 最短接入路径(TL;DR)
|
|
91
93
|
|
|
92
|
-
1) 从模板复制:`
|
|
94
|
+
1) 从模板复制:`chatos/ui_apps/template/basic-plugin` → 放进任一插件目录
|
|
93
95
|
2) 修改 `plugin.json`:只支持 `apps[i].entry.type="module"`(可选增加 `entry.compact` 作为紧凑 UI 入口)
|
|
94
96
|
3) 桌面端打开「应用」页 → 点“刷新” → 进入你的应用
|
|
95
97
|
4) (可选)需要 Node 能力:加 `backend.entry`,前端用 `host.backend.invoke()`
|
|
@@ -99,15 +101,15 @@
|
|
|
99
101
|
|
|
100
102
|
## 实现位置(便于对照代码)
|
|
101
103
|
|
|
102
|
-
- schema(`plugin.json` / `apps[i].ai`):`
|
|
103
|
-
- 插件扫描/入口校验/AI 同步:`
|
|
104
|
-
- 应用包导入(目录/zip):`
|
|
105
|
-
- module 运行时 Host API 注入:`
|
|
104
|
+
- schema(`plugin.json` / `apps[i].ai`):`chatos/electron/ui-apps/schemas.js`
|
|
105
|
+
- 插件扫描/入口校验/AI 同步:`chatos/electron/ui-apps/index.js`
|
|
106
|
+
- 应用包导入(目录/zip):`chatos/electron/ui-apps/plugin-installer.js`
|
|
107
|
+
- module 运行时 Host API 注入:`chatos/apps/ui/src/features/apps/AppsPluginView.jsx`
|
|
106
108
|
|
|
107
109
|
## 原始文档来源(本次提取/整合)
|
|
108
110
|
|
|
109
|
-
- `
|
|
110
|
-
- `
|
|
111
|
-
- `
|
|
112
|
-
- `
|
|
111
|
+
- `chatos/doc/app-dev-handbook.md`
|
|
112
|
+
- `chatos/doc/app-integration.md`
|
|
113
|
+
- `chatos/doc/ui-apps-plugins.md`
|
|
114
|
+
- `chatos/doc/ui-apps-dev-guide.md`
|
|
113
115
|
- `aide/shared/defaults/ui-apps-expose/README.md`
|