@leeoohoo/ui-apps-devkit 0.1.0

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.
Files changed (55) hide show
  1. package/README.md +70 -0
  2. package/bin/chatos-uiapp.js +5 -0
  3. package/package.json +22 -0
  4. package/src/cli.js +53 -0
  5. package/src/commands/dev.js +14 -0
  6. package/src/commands/init.js +141 -0
  7. package/src/commands/install.js +55 -0
  8. package/src/commands/pack.js +72 -0
  9. package/src/commands/validate.js +103 -0
  10. package/src/lib/args.js +49 -0
  11. package/src/lib/config.js +29 -0
  12. package/src/lib/fs.js +78 -0
  13. package/src/lib/path-boundary.js +16 -0
  14. package/src/lib/plugin.js +45 -0
  15. package/src/lib/template.js +168 -0
  16. package/src/sandbox/server.js +861 -0
  17. package/templates/basic/README.md +58 -0
  18. package/templates/basic/chatos.config.json +5 -0
  19. package/templates/basic/docs/CHATOS_UI_APPS_AI_CONTRIBUTIONS.md +181 -0
  20. package/templates/basic/docs/CHATOS_UI_APPS_BACKEND_PROTOCOL.md +74 -0
  21. package/templates/basic/docs/CHATOS_UI_APPS_HOST_API.md +123 -0
  22. package/templates/basic/docs/CHATOS_UI_APPS_OVERVIEW.md +110 -0
  23. package/templates/basic/docs/CHATOS_UI_APPS_PLUGIN_MANIFEST.md +227 -0
  24. package/templates/basic/docs/CHATOS_UI_PROMPTS_PROTOCOL.md +392 -0
  25. package/templates/basic/plugin/apps/app/index.mjs +263 -0
  26. package/templates/basic/plugin/apps/app/mcp-prompt.en.md +7 -0
  27. package/templates/basic/plugin/apps/app/mcp-prompt.zh.md +7 -0
  28. package/templates/basic/plugin/apps/app/mcp-server.mjs +15 -0
  29. package/templates/basic/plugin/backend/index.mjs +37 -0
  30. package/templates/basic/template.json +7 -0
  31. package/templates/notepad/README.md +36 -0
  32. package/templates/notepad/chatos.config.json +4 -0
  33. package/templates/notepad/docs/CHATOS_UI_APPS_AI_CONTRIBUTIONS.md +181 -0
  34. package/templates/notepad/docs/CHATOS_UI_APPS_BACKEND_PROTOCOL.md +74 -0
  35. package/templates/notepad/docs/CHATOS_UI_APPS_HOST_API.md +123 -0
  36. package/templates/notepad/docs/CHATOS_UI_APPS_OVERVIEW.md +110 -0
  37. package/templates/notepad/docs/CHATOS_UI_APPS_PLUGIN_MANIFEST.md +227 -0
  38. package/templates/notepad/docs/CHATOS_UI_PROMPTS_PROTOCOL.md +392 -0
  39. package/templates/notepad/plugin/apps/app/api.mjs +30 -0
  40. package/templates/notepad/plugin/apps/app/dom.mjs +14 -0
  41. package/templates/notepad/plugin/apps/app/ds-tree.mjs +35 -0
  42. package/templates/notepad/plugin/apps/app/index.mjs +1056 -0
  43. package/templates/notepad/plugin/apps/app/layers.mjs +338 -0
  44. package/templates/notepad/plugin/apps/app/markdown.mjs +120 -0
  45. package/templates/notepad/plugin/apps/app/mcp-prompt.en.md +22 -0
  46. package/templates/notepad/plugin/apps/app/mcp-prompt.zh.md +22 -0
  47. package/templates/notepad/plugin/apps/app/mcp-server.mjs +200 -0
  48. package/templates/notepad/plugin/apps/app/styles.mjs +355 -0
  49. package/templates/notepad/plugin/apps/app/tags.mjs +21 -0
  50. package/templates/notepad/plugin/apps/app/ui.mjs +280 -0
  51. package/templates/notepad/plugin/backend/index.mjs +99 -0
  52. package/templates/notepad/plugin/plugin.json +23 -0
  53. package/templates/notepad/plugin/shared/notepad-paths.mjs +62 -0
  54. package/templates/notepad/plugin/shared/notepad-store.mjs +765 -0
  55. package/templates/notepad/template.json +8 -0
@@ -0,0 +1,123 @@
1
+ # ChatOS UI Apps:`module` 入口与 Host API(协议)
2
+
3
+ 本文件定义 UI Apps 的 `module` 入口规范,以及宿主注入的 `host` 对象(应用与 ChatOS 交互的稳定契约)。
4
+
5
+ 实现对照(以代码为准):
6
+
7
+ - `deepseek_cli/apps/ui/src/features/apps/AppsPluginView.jsx`
8
+
9
+ ## 1. module 入口规范
10
+
11
+ `plugin.json` 中的入口示例:
12
+
13
+ ```json
14
+ { "type": "module", "path": "my-app/index.mjs" }
15
+ ```
16
+
17
+ 入口模块需导出 `mount`(以下三种写法宿主都接受):
18
+
19
+ - `export function mount(...) { ... }`
20
+ - `export default { mount(...) { ... } }`
21
+ - `export default function mount(...) { ... }`
22
+
23
+ `mount` 签名:
24
+
25
+ ```js
26
+ export function mount({ container, host, slots }) {
27
+ return () => {}; // or return { dispose() {} }
28
+ }
29
+ ```
30
+
31
+ - `container`:应用正文容器(body)
32
+ - `slots.header`:可选固定 Header 容器(不随 body 滚动)
33
+ - 返回值:
34
+ - `() => void|Promise<void>`:卸载回调;或
35
+ - `{ dispose(): void|Promise<void> }`
36
+
37
+ 布局规范:
38
+
39
+ - 不要使用 `window/body` 作为滚动容器;把滚动放到应用内部。
40
+ - 将 Tabs/二级导航/操作按钮等放到 `slots.header`,可滚动内容放到 `container`。
41
+
42
+ ## 2. Host Bridge 可用性
43
+
44
+ 宿主仅在“file-based entry + preload bridge 可用”的情况下提供 `host` 能力;否则会抛错:
45
+
46
+ - 若你在非 ChatOS 宿主环境下单独打开页面(或 preload 未加载),`host.bridge.enabled` 可能为 `false`。
47
+ - 生产场景(桌面端应用内)一般为 `true`。
48
+
49
+ ## 3. `host` API 约定
50
+
51
+ ### 3.1 上下文与主题
52
+
53
+ - `host.bridge.enabled: boolean`
54
+ - `host.context.get(): { pluginId, appId, theme, bridge: { enabled } }`
55
+ - `host.theme.get(): string`(当前实现读取 `document.documentElement.dataset.theme`)
56
+ - `host.theme.onChange(listener): () => void`
57
+
58
+ ### 3.2 Admin(全局配置读取)
59
+
60
+ - `host.admin.state(): Promise<any>`:读取全局 Admin 状态快照
61
+ - `host.admin.onUpdate(listener): () => void`:订阅 Admin 更新事件
62
+ - `host.admin.models.list(): Promise<any>`:列出 Models
63
+ - `host.admin.secrets.list(): Promise<any>`:列出 Secrets(脱敏;不会返回明文 key)
64
+
65
+ 说明:
66
+
67
+ - UI Apps **不得**在自己的配置里保存/管理 API Keys;应完全复用宿主全局配置。
68
+
69
+ ### 3.3 Registry(插件注册表)
70
+
71
+ - `host.registry.list(): Promise<any>`:等价于 `uiApps:list`(包含 apps 列表、插件目录、加载错误等)
72
+
73
+ ### 3.4 Backend(插件后端调用)
74
+
75
+ - `host.backend.invoke(method: string, params?: any): Promise<any>`
76
+ - `method`:后端 `methods` 的 key
77
+ - 返回值:后端方法返回的 `result`(宿主会把 `{ ok, result }` 解包)
78
+
79
+ 后端协议详见:[CHATOS_UI_APPS_BACKEND_PROTOCOL.md](./CHATOS_UI_APPS_BACKEND_PROTOCOL.md)。
80
+
81
+ ### 3.5 UI Prompts(右下角笑脸:交互待办)
82
+
83
+ 用于把“需要用户确认/输入”的交互投递到全局队列,用户无需进入对应应用即可处理。
84
+
85
+ - `host.uiPrompts.read(): Promise<any>`:读取当前队列/最新状态
86
+ - `host.uiPrompts.onUpdate(listener): () => void`:订阅队列变化
87
+ - `host.uiPrompts.request({ prompt, runId?, requestId?, ... }): Promise<any>`:投递待办(`prompt.source` 为空时宿主写入 `${pluginId}:${appId}`)
88
+ - `host.uiPrompts.respond({ requestId, runId?, response }): Promise<any>`:写入用户响应
89
+ - `host.uiPrompts.open(): { ok: true }`:打开笑脸面板
90
+ - `host.uiPrompts.close(): { ok: true }`
91
+ - `host.uiPrompts.toggle(): { ok: true }`
92
+
93
+ `prompt` / `response` 的字段协议见:[CHATOS_UI_PROMPTS_PROTOCOL.md](./CHATOS_UI_PROMPTS_PROTOCOL.md)。
94
+
95
+ ### 3.6 导航
96
+
97
+ - `host.ui.navigate(menu: string): { ok: true }`
98
+ - 用于跨应用/跨页面跳转(由宿主统一处理路由)
99
+
100
+ ### 3.7 Chat(Agents / Sessions / Messages / Send / Events)
101
+
102
+ `host.chat` 提供对聊天域的直接操作能力(节选):
103
+
104
+ - `host.chat.agents.list()`
105
+ - `host.chat.agents.ensureDefault()`
106
+ - `host.chat.agents.create(payload)`
107
+ - `host.chat.agents.update(id, patch)`
108
+ - `host.chat.agents.delete(id)`
109
+ - `host.chat.agents.createForApp({ name?, description?, modelId?, promptIds?, subagentIds?, skills?, mcpServerIds? })`
110
+ - 创建一个“绑定当前应用”的 Agent,并自动写入 `uiApps: [{ pluginId, appId, mcp:true, prompt:true }]`
111
+ - `host.chat.sessions.list()`
112
+ - `host.chat.sessions.ensureDefault(payload?)`
113
+ - `host.chat.sessions.create(payload)`
114
+ - `host.chat.messages.list(payload)`
115
+ - `host.chat.send(payload)`
116
+ - `host.chat.abort(payload)`
117
+ - `host.chat.events.subscribe({ sessionId?, types? }, listener): () => void`
118
+ - `host.chat.events.unsubscribe(): { ok: true }`
119
+
120
+ 事件订阅说明:
121
+
122
+ - `subscribe` 支持用 `sessionId` 与 `types` 做过滤;
123
+ - 当最后一个 listener 解绑后,宿主会自动取消底层订阅。
@@ -0,0 +1,110 @@
1
+ # ChatOS UI Apps(嵌入应用)概览
2
+
3
+ 本文把散落在仓库各处的“ChatOS 嵌入应用(UI Apps 插件)框架/协议”说明提取到仓库根目录,并补齐了若干关键约束(路径边界、打包导入、schema 字段等)。
4
+
5
+ 配套文档(按从概览 → 细节的阅读顺序):
6
+
7
+ - [`CHATOS_UI_APPS_PLUGIN_MANIFEST.md`](./CHATOS_UI_APPS_PLUGIN_MANIFEST.md):`plugin.json` / `apps[i].ai` 的清单与字段规范(含完整字段、示例与约束)。
8
+ - [`CHATOS_UI_APPS_HOST_API.md`](./CHATOS_UI_APPS_HOST_API.md):`module` 应用入口与 `host.*` 交互协议(前端侧)。
9
+ - [`CHATOS_UI_PROMPTS_PROTOCOL.md`](./CHATOS_UI_PROMPTS_PROTOCOL.md):右下角笑脸「交互待办(UI Prompts)」协议(表单/单选/多选/复杂确认)。
10
+ - [`CHATOS_UI_APPS_BACKEND_PROTOCOL.md`](./CHATOS_UI_APPS_BACKEND_PROTOCOL.md):插件后端(Electron main 进程)协议与 `ctx` 运行时上下文。
11
+ - [`CHATOS_UI_APPS_AI_CONTRIBUTIONS.md`](./CHATOS_UI_APPS_AI_CONTRIBUTIONS.md):应用如何对 Chat Agent 暴露 MCP/Prompt(含命名规则、合并规则、内置清单机制)。
12
+
13
+ ## 术语与角色
14
+
15
+ - **ChatOS(宿主)**:桌面端 Electron 应用(本仓库的 `deepseek_cli`)。
16
+ - **AIDE(引擎)**:模型调用/工具/MCP/子代理等核心能力(本仓库的 `aide`)。
17
+ - **UI Apps(嵌入应用/小应用)**:以插件形式注入到桌面端「应用」中心的应用。
18
+ - **MCP**:Model Context Protocol;通过 MCP Server 暴露 tools,最终工具名通常为 `mcp_<serverName>_<toolName>`。
19
+ - **Prompt**:system prompt 模板;可被 Agent 勾选并注入运行时 system prompt。
20
+
21
+ ## 目录与状态(sessionRoot / stateDir)
22
+
23
+ - `sessionRoot`:会话根目录
24
+ - 默认:用户主目录(Home)
25
+ - 可通过环境变量覆盖:`MODEL_CLI_SESSION_ROOT=/path/to/root`
26
+ - 桌面端/CLI 会把“上次使用的 sessionRoot”记录到 `<home>/.deepseek_cli/last-session-root.txt`(未设置 env 时会优先读取)
27
+ - `stateDir`:`<home>/.deepseek_cli/<hostApp>`(ChatOS 的 `hostApp=chatos`)
28
+
29
+ 全局配置(由宿主维护;应用侧只读/复用):
30
+
31
+ - `stateDir/chatos.db.sqlite`:Admin DB(Models / Secrets / MCP Servers / Prompts / Settings…)
32
+ - 文件镜像(从 Admin DB 同步出来,便于运行时读取):
33
+ - `stateDir/auth/models.yaml`
34
+ - `stateDir/auth/mcp.config.json`
35
+ - `stateDir/auth/system-prompt.yaml`
36
+ - `stateDir/auth/*prompt*.yaml`
37
+
38
+ 原则:
39
+
40
+ - **Secrets(API Keys)只存 DB**,不会明文同步到 yaml。
41
+ - 运行前宿主会把 Secrets 写入 `process.env`(受 `override` 控制),Provider 通过 `apiKeyEnv` 取值。
42
+
43
+ ## UI Apps 插件目录(宿主扫描)
44
+
45
+ 宿主会扫描两个目录(并在 UI「应用」页展示实际路径):
46
+
47
+ - **内置/开发目录**:`deepseek_cli/ui_apps/plugins`
48
+ - **用户插件目录**:`<stateDir>/ui_apps/plugins`(即 `~/.deepseek_cli/chatos/ui_apps/plugins`)
49
+
50
+ 同名 `plugin.id` 的覆盖规则:
51
+
52
+ - 用户目录的插件会覆盖内置目录的同 `plugin.id` 插件(便于开发调试/热替换)。
53
+
54
+ 插件数据目录(供插件后端存放自己的持久化数据):
55
+
56
+ - `dataDir`:`<stateDir>/ui_apps/data/<pluginId>`
57
+ - 插件后端的持久化数据写入目录为 `dataDir`;插件安装目录用于读取插件资源。
58
+
59
+ ## 插件包导入(目录或 .zip)
60
+
61
+ 桌面端 UI 支持:`应用` → `导入应用包` → 选择插件目录或 `.zip`。
62
+
63
+ 包结构要求:
64
+
65
+ - `plugin.json` 在包根目录;或
66
+ - 包根目录下一层目录中包含一个或多个插件目录(每个目录内有 `plugin.json`)。
67
+
68
+ 导入时的复制规则(重要):
69
+
70
+ - 会拷贝到用户插件目录 `~/.deepseek_cli/chatos/ui_apps/plugins/<sanitized(plugin.id)>/`;
71
+ - 默认会排除:`node_modules/`、`.git/`、`.DS_Store`、`*.map`;
72
+ - 因此若插件需要依赖,请在构建时做 bundle(不要指望随包携带 `node_modules` 生效)。
73
+
74
+ ## 安全边界与硬约束(协议的一部分)
75
+
76
+ 为避免插件越权读取宿主文件系统,宿主对“路径型字段”做了强约束:
77
+
78
+ - `apps[i].entry.path` 必须位于插件目录内,且必须是文件(`module` 入口)。
79
+ - `backend.entry` 必须位于插件目录内,且必须是文件。
80
+ - `apps[i].ai.config`、`ai.mcp.entry`、`ai.mcpPrompt.*.path` 等所有 path 都必须位于插件目录内。
81
+
82
+ 尺寸限制(默认值,防止误导入超大文件):
83
+
84
+ - `plugin.json` 最大 `256 KiB`
85
+ - `mcpPrompt` 内容最大 `128 KiB`(读取 path 或 inline content 都受限)
86
+
87
+ ## 最短接入路径(TL;DR)
88
+
89
+ 1) 从模板复制:`deepseek_cli/ui_apps/template/basic-plugin` → 放进任一插件目录
90
+ 2) 修改 `plugin.json`:只支持 `apps[i].entry.type="module"`
91
+ 3) 桌面端打开「应用」页 → 点“刷新” → 进入你的应用
92
+ 4) (可选)需要 Node 能力:加 `backend.entry`,前端用 `host.backend.invoke()`
93
+ 5) (可选)需要给 Agent 暴露工具/说明:配置 `apps[i].ai`(见 [`CHATOS_UI_APPS_AI_CONTRIBUTIONS.md`](./CHATOS_UI_APPS_AI_CONTRIBUTIONS.md))
94
+
95
+ 提示:`ai.mcp` / `ai.mcpPrompt` 是否持久化写入 Admin DB,取决于宿主是否启用 `syncAiContributes`;即使不持久化,Agent 运行时也可以按 `apps[i].ai` 声明进行“临时注入”。
96
+
97
+ ## 实现位置(便于对照代码)
98
+
99
+ - schema(`plugin.json` / `apps[i].ai`):`deepseek_cli/electron/ui-apps/schemas.js`
100
+ - 插件扫描/入口校验/AI 同步:`deepseek_cli/electron/ui-apps/index.js`
101
+ - 应用包导入(目录/zip):`deepseek_cli/electron/ui-apps/plugin-installer.js`
102
+ - module 运行时 Host API 注入:`deepseek_cli/apps/ui/src/features/apps/AppsPluginView.jsx`
103
+
104
+ ## 原始文档来源(本次提取/整合)
105
+
106
+ - `deepseek_cli/doc/app-dev-handbook.md`
107
+ - `deepseek_cli/doc/app-integration.md`
108
+ - `deepseek_cli/doc/ui-apps-plugins.md`
109
+ - `deepseek_cli/doc/ui-apps-dev-guide.md`
110
+ - `aide/shared/defaults/ui-apps-expose/README.md`
@@ -0,0 +1,227 @@
1
+ # ChatOS UI Apps:`plugin.json` 清单规范(协议)
2
+
3
+ 本文件定义 UI Apps 插件清单 `plugin.json` 的字段与约束,目标是让第三方/内置应用都能按统一契约被 ChatOS 扫描、加载与运行。
4
+
5
+ 实现对照(以代码为准):
6
+
7
+ - schema:`deepseek_cli/electron/ui-apps/schemas.js`
8
+ - 扫描/校验:`deepseek_cli/electron/ui-apps/index.js`
9
+ - 导入/安装:`deepseek_cli/electron/ui-apps/plugin-installer.js`
10
+
11
+ 另见:
12
+
13
+ - [`CHATOS_UI_APPS_HOST_API.md`](./CHATOS_UI_APPS_HOST_API.md)(`module` 应用与宿主交互)
14
+ - [`CHATOS_UI_APPS_BACKEND_PROTOCOL.md`](./CHATOS_UI_APPS_BACKEND_PROTOCOL.md)(插件后端)
15
+ - [`CHATOS_UI_APPS_AI_CONTRIBUTIONS.md`](./CHATOS_UI_APPS_AI_CONTRIBUTIONS.md)(MCP/Prompt 暴露)
16
+
17
+ ## 1. 文件与安装位置
18
+
19
+ - 每个插件一个目录,目录根部必须包含 `plugin.json`。
20
+ - 插件目录可放在:
21
+ - `deepseek_cli/ui_apps/plugins`(内置/开发)
22
+ - `~/.deepseek_cli/chatos/ui_apps/plugins`(用户插件目录)
23
+ - 也可通过桌面端 UI:`应用` → `导入应用包`(目录或 `.zip`)安装到用户插件目录。
24
+
25
+ ## 2. 顶层 schema(`uiAppsPluginSchema`)
26
+
27
+ `plugin.json`(Top-level)字段:
28
+
29
+ | 字段 | 类型 | 必填 | 默认 | 说明 |
30
+ |---|---:|---:|---|---|
31
+ | `manifestVersion` | `number` | 否 | `1` | 目前仅支持 `1` |
32
+ | `id` | `string` | 是 | - | 插件 ID(使用反向域名;稳定且全局唯一) |
33
+ | `name` | `string` | 是 | - | 插件显示名称 |
34
+ | `version` | `string` | 否 | `"0.0.0"` | 版本号(展示用途) |
35
+ | `description` | `string` | 否 | `""` | 插件描述 |
36
+ | `backend` | `object` | 否 | - | 插件后端(Electron main 进程) |
37
+ | `apps` | `array` | 否 | `[]` | 插件内的应用列表 |
38
+
39
+ `backend`:
40
+
41
+ | 字段 | 类型 | 必填 | 说明 |
42
+ |---|---:|---:|---|
43
+ | `backend.entry` | `string` | 是 | 后端入口模块路径(相对插件目录;必须在插件目录内且是文件) |
44
+
45
+ ## 3. apps schema(`uiAppSchema`)
46
+
47
+ `apps[i]` 字段:
48
+
49
+ | 字段 | 类型 | 必填 | 默认 | 说明 |
50
+ |---|---:|---:|---|---|
51
+ | `id` | `string` | 是 | - | 应用 ID(同一插件内唯一) |
52
+ | `name` | `string` | 是 | - | 应用显示名称 |
53
+ | `description` | `string` | 否 | `""` | 描述 |
54
+ | `icon` | `string` | 否 | `""` | 图标(当前实现以字符串透传为主) |
55
+ | `entry` | `object` | 是 | - | 入口(仅支持 `module`) |
56
+ | `ai` | `object|string` | 否 | - | AI 声明(MCP/Prompt/暴露列表等;详见下文) |
57
+
58
+ ### 3.1 `apps[i].entry`(仅支持 `module`)
59
+
60
+ ```json
61
+ { "type": "module", "path": "my-app/index.mjs" }
62
+ ```
63
+
64
+ 硬约束:
65
+
66
+ - `entry.type` 必须为 `"module"`(ChatOS 不支持 `iframe/url`)。
67
+ - `entry.path` 必须在插件目录内(宿主做路径边界校验),且必须是文件。
68
+
69
+ ## 4. `apps[i].ai` schema(`uiAppAiSchema`)
70
+
71
+ `ai` 可以写成两种形式:
72
+
73
+ 1) **对象**(inline):
74
+
75
+ ```json
76
+ {
77
+ "ai": {
78
+ "mcpServers": true,
79
+ "prompts": true
80
+ }
81
+ }
82
+ ```
83
+
84
+ 2) **字符串路径**(等价于 `{ "config": "<path>" }`):
85
+
86
+ ```json
87
+ { "ai": "my-app/ai.yaml" }
88
+ ```
89
+
90
+ 对象形式还支持额外带一个 `config` 字段,用于从文件读取并与 inline 合并:
91
+
92
+ ```json
93
+ {
94
+ "ai": {
95
+ "config": "my-app/ai.yaml",
96
+ "mcpServers": true,
97
+ "prompts": true
98
+ }
99
+ }
100
+ ```
101
+
102
+ 所有 `ai` 的 path(`ai.config`、`ai.mcp.entry`、`ai.mcpPrompt.*.path`)都必须在插件目录内,且文件大小受限(默认最大 `128 KiB`)。
103
+
104
+ ### 4.1 `ai` 字段一览(`uiAppAiConfigSchema`)
105
+
106
+ | 字段 | 类型 | 说明 |
107
+ |---|---:|---|
108
+ | `ai.mcp` | `object` | 声明并同步一个 MCP Server(`serverName` 固定派生为 `${pluginId}.${appId}`) |
109
+ | `ai.mcpPrompt` | `string|object` | 声明并同步一个 system prompt(名称固定派生) |
110
+ | `ai.mcpServers` | `true|false|string[]` | 暴露给 Agent 的 MCP servers 范围(聚合“已有的”资源) |
111
+ | `ai.prompts` | `true|false|string[]` | 暴露给 Agent 的 prompts 范围(聚合“已有的”资源) |
112
+ | `ai.agent` | `object` | 可选:应用提供的 Agent 模板(当前实现主要做透传/保留字段) |
113
+
114
+ ## 5. `ai.mcp`:MCP Server 声明
115
+
116
+ `ai.mcp` 字段(当前 schema):
117
+
118
+ | 字段 | 类型 | 必填 | 默认 | 说明 |
119
+ |---|---:|---:|---|---|
120
+ | `url` | `string` | 二选一 | - | 远程 MCP Server 地址(`http(s)://` / `ws(s)://` 等) |
121
+ | `entry` | `string` | 二选一 | - | 本地脚本入口(相对插件目录);宿主会转换为 `cmd://...` |
122
+ | `command` | `string` | 否 | `"node"` | 拉起本地 `entry` 时使用的命令 |
123
+ | `args` | `string[]` | 否 | `[]` | 拉起时追加参数 |
124
+ | `description` | `string` | 否 | `""` | 描述 |
125
+ | `tags` | `string[]` | 否 | `[]` | 标签(宿主还会自动附加 `uiapp*` 标签) |
126
+ | `enabled` | `boolean` | 否 | - | 是否启用(未填则宿主同步时默认 `true`) |
127
+ | `allowMain` | `boolean` | 否 | - | 是否允许主流程使用(未填则宿主同步时默认 `true`) |
128
+ | `allowSub` | `boolean` | 否 | - | 是否允许子代理使用(未填则宿主同步时默认 `true`) |
129
+ | `auth` | `object` | 否 | - | 认证信息(token/basic/headers) |
130
+
131
+ 强约束:
132
+
133
+ - 必须提供 `url` 或 `entry` 其中之一(只写 `command` 不算有效配置)。
134
+
135
+ `auth` 结构(均为可选,且支持 partial):
136
+
137
+ ```json
138
+ {
139
+ "auth": {
140
+ "token": "…",
141
+ "basic": { "username": "u", "password": "p" },
142
+ "headers": { "X-Foo": "bar" }
143
+ }
144
+ }
145
+ ```
146
+
147
+ 当使用 `entry` 时,宿主会把它转换为可运行的 `cmd://`:
148
+
149
+ - `command` 默认为 `node`
150
+ - `args` 会追加到命令行末尾
151
+ - 宿主会把空格/引号等做安全引用,以避免路径包含空格时解析失败
152
+
153
+ ## 6. `ai.mcpPrompt`:应用默认 Prompt 声明
154
+
155
+ `ai.mcpPrompt` 支持两种写法:
156
+
157
+ 1) **字符串**:等价于中文 prompt 从该路径读取:
158
+
159
+ ```json
160
+ { "mcpPrompt": "my-app/mcp-prompt.zh.md" }
161
+ ```
162
+
163
+ 2) **对象**:可分别提供 `zh`/`en`,并支持 path 或 inline content:
164
+
165
+ ```json
166
+ {
167
+ "mcpPrompt": {
168
+ "title": "My App · MCP Prompt",
169
+ "zh": "my-app/mcp-prompt.zh.md",
170
+ "en": { "path": "my-app/mcp-prompt.en.md" }
171
+ }
172
+ }
173
+ ```
174
+
175
+ `zh/en` 的“source”结构为:
176
+
177
+ ```json
178
+ { "path": "relative.md", "content": "inline markdown…" }
179
+ ```
180
+
181
+ 约束:
182
+
183
+ - `mcpPrompt` 必须至少提供 `zh` 或 `en` 其一;
184
+ - 若提供 `path`,必须在插件目录内且是文件;
185
+ - 内容大小受限(默认最大 `128 KiB`)。
186
+
187
+ ## 7. `ai.mcpServers` / `ai.prompts`:聚合暴露范围
188
+
189
+ - `true`:开启暴露(“具体暴露哪些”由 `ai.config` / 内置默认清单决定;否则表示全部)
190
+ - `false`:禁用暴露
191
+ - `string[]`:精确列出允许暴露的 `serverName` / `prompt name`
192
+
193
+ 注意:这里定义的是“在 Agent UI 中可选/可见的范围”,最终是否启用、启用哪些仍由 Agent 编辑页勾选决定。
194
+
195
+ ## 8. 最小示例
196
+
197
+ ### 8.1 最小可运行插件(仅 module)
198
+
199
+ ```json
200
+ {
201
+ "manifestVersion": 1,
202
+ "id": "com.example.tools",
203
+ "name": "Example Tools",
204
+ "version": "0.1.0",
205
+ "apps": [
206
+ {
207
+ "id": "hello",
208
+ "name": "Hello App(Module)",
209
+ "entry": { "type": "module", "path": "hello/index.mjs" }
210
+ }
211
+ ]
212
+ }
213
+ ```
214
+
215
+ ### 8.2 带后端 + MCP/Prompt 的应用(节选)
216
+
217
+ ```json
218
+ {
219
+ "id": "db-client",
220
+ "name": "数据库客户端",
221
+ "entry": { "type": "module", "path": "db-client/index.mjs" },
222
+ "ai": {
223
+ "mcp": { "entry": "db-client/mcp-server.mjs", "command": "node", "allowMain": true, "allowSub": true },
224
+ "mcpPrompt": { "zh": "db-client/mcp-prompt.zh.md", "en": "db-client/mcp-prompt.en.md" }
225
+ }
226
+ }
227
+ ```