@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
|
@@ -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
|
|
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* MCP server entry.
|
|
3
|
+
*
|
|
4
|
+
* Note: ChatOS import excludes `node_modules/`, so if you import third-party
|
|
5
|
+
* deps (e.g. @modelcontextprotocol/sdk, zod), you must bundle this file into
|
|
6
|
+
* a single output (or vendor deps into the plugin directory).
|
|
7
|
+
*/
|
|
8
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
9
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
3
10
|
import { z } from 'zod';
|
|
4
11
|
import { createNotepadStore } from '../../shared/notepad-store.mjs';
|
|
@@ -1,10 +1,13 @@
|
|
|
1
|
-
import fs from 'fs';
|
|
2
|
-
import os from 'os';
|
|
3
|
-
import path from 'path';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import os from 'os';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
|
|
5
|
+
const STATE_ROOT_DIRNAME = '.deepseek_cli';
|
|
6
|
+
const COMPAT_STATE_ROOT_DIRNAME = '.chatos';
|
|
7
|
+
|
|
8
|
+
function normalizeString(value) {
|
|
9
|
+
return typeof value === 'string' ? value.trim() : '';
|
|
10
|
+
}
|
|
8
11
|
|
|
9
12
|
function resolveHostApp(env) {
|
|
10
13
|
const hostApp = normalizeString(env?.MODEL_CLI_HOST_APP);
|
|
@@ -25,9 +28,9 @@ function resolveSessionRoot(env) {
|
|
|
25
28
|
return normalizeString(env?.MODEL_CLI_SESSION_ROOT);
|
|
26
29
|
}
|
|
27
30
|
|
|
28
|
-
function tryEnsureWritableDir(dirPath) {
|
|
29
|
-
const target = normalizeString(dirPath);
|
|
30
|
-
if (!target) return false;
|
|
31
|
+
function tryEnsureWritableDir(dirPath) {
|
|
32
|
+
const target = normalizeString(dirPath);
|
|
33
|
+
if (!target) return false;
|
|
31
34
|
try {
|
|
32
35
|
fs.mkdirSync(target, { recursive: true });
|
|
33
36
|
} catch {
|
|
@@ -38,21 +41,36 @@ function tryEnsureWritableDir(dirPath) {
|
|
|
38
41
|
return true;
|
|
39
42
|
} catch {
|
|
40
43
|
return false;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
const
|
|
46
|
-
if (!
|
|
47
|
-
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function pushDataDir(list, baseDir, rootDirName, hostApp, pluginId) {
|
|
48
|
+
const base = normalizeString(baseDir);
|
|
49
|
+
if (!base) return;
|
|
50
|
+
list.push(path.join(base, rootDirName, hostApp, 'ui_apps', 'data', pluginId));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function resolveUiAppDataDir({ pluginId, env } = {}) {
|
|
54
|
+
const id = normalizeString(pluginId);
|
|
55
|
+
if (!id) throw new Error('pluginId is required');
|
|
56
|
+
const resolvedEnv = env && typeof env === 'object' ? env : process.env;
|
|
48
57
|
const hostApp = resolveHostApp(resolvedEnv);
|
|
49
58
|
const home = resolveHomeDir(resolvedEnv);
|
|
50
|
-
const sessionRoot = resolveSessionRoot(resolvedEnv);
|
|
51
|
-
|
|
52
|
-
const candidates = [];
|
|
53
|
-
if (home)
|
|
54
|
-
|
|
55
|
-
|
|
59
|
+
const sessionRoot = resolveSessionRoot(resolvedEnv);
|
|
60
|
+
|
|
61
|
+
const candidates = [];
|
|
62
|
+
if (home) {
|
|
63
|
+
pushDataDir(candidates, home, STATE_ROOT_DIRNAME, hostApp, id);
|
|
64
|
+
pushDataDir(candidates, home, COMPAT_STATE_ROOT_DIRNAME, hostApp, id);
|
|
65
|
+
}
|
|
66
|
+
if (sessionRoot) {
|
|
67
|
+
const root = path.resolve(sessionRoot);
|
|
68
|
+
pushDataDir(candidates, root, STATE_ROOT_DIRNAME, hostApp, id);
|
|
69
|
+
pushDataDir(candidates, root, COMPAT_STATE_ROOT_DIRNAME, hostApp, id);
|
|
70
|
+
}
|
|
71
|
+
const cwd = path.resolve(process.cwd());
|
|
72
|
+
pushDataDir(candidates, cwd, STATE_ROOT_DIRNAME, hostApp, id);
|
|
73
|
+
pushDataDir(candidates, cwd, COMPAT_STATE_ROOT_DIRNAME, hostApp, id);
|
|
56
74
|
|
|
57
75
|
for (const candidate of candidates) {
|
|
58
76
|
if (tryEnsureWritableDir(candidate)) return candidate;
|