Files
dsh_shenxian/dsh-server-docs/04-调整方案/27-MCN工作台插件平台化评估.md
T
admin 5ad755116e chore(docs): 文档库并入代码仓(R4 选 a)+ 索引/台账跟进
1) dsh-server-docs/ 从工作区(原 E:\...\aliyun-dsh-server\dsh-server-docs)**整体并入本仓**,
   保留目录名 ⇒ 仓库内 dsh-server-docs/... 的相对引用天然继续有效;旧目录(含其 .git)已归档到
   工作区 _中间产物_待清理/,未随本提交带入。
2) .gitattributes:新增 `dsh-server-docs/** -text` —— 原文档库是 `* -text` + autocrlf=false,
   必须保持纯 LF,否则会被本仓的 CRLF 规则翻掉。
3) 活引用里的绝对路径已全部改到新位置(docs 的 INDEX / README / scripts / skills + 用户级 skills
   + ~/.workbuddy/settings.json 的 hooks);历史档案(04-调整方案/、archive/)按「只增不改」未动。
   ⚠️ hooks 路径改动需「完全重启会话」才生效(配置是会话启动快照)。
4) 交接单/T08:新增 §16「生产整体切换执行记录」(形态 / 落地动作 / **4 个只有真上线才暴露的真 bug** /
   验收证据 / 回滚命令 / 残留项);台账 T08 行 → 已完成并归档;03-路线图 §二 登记 T08 收尾项。
5) 统一称谓:**「本机」只指跑 WorkBuddy 的开发机**,47 / 106 一律写「远程服务器」。
2026-09-15 18:47:13 +08:00

89 lines
9.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 27 · MCN 工作台插件平台化评估
- 日期:2026-09-11
- 输入:用户提问「能否模拟 admin 安装到 dsh 服务器功能插件中/是否支持多用户/数据与产物如何存储/每个插件自带数据库有无风险/功能插件调用 skill 应整合还是外置」
- 分析对象:`C://Users//Administrator//.dsh//profiles//web//node_modules//` 下的 `dsh-plugin-mcn`(主)、`dsh-plugin-social-workbench`、`dsh-plugin-mcn-schedule`、`dsh-plugin-douyin-*`
- 结论一句话:**机制上可作为"功能插件"投放,但有 3 处必须先改**(DSH_HOME 路径、技能路径硬编码、agent preset 随包投放);**多用户天然成立**(每用户独立实例 → 每用户一份 DB);**技能应"外置"**(平台共享技能层),插件只按名引用。
---
## 一、先看结论(对应你的 5 个问题)
| # | 你的问题 | 结论 |
|---|---|---|
| 1 | 能否模拟 admin 安装为**功能插件** | ✅ 机制可行(标准 bundle:`dsh.client` + `cordis.patch.yml` insert 一行)。**但需 3 处改造**(见 §三),否则装上去功能会残 |
| 2 | 是否支持**多用户** | ✅ 天然成立:平台是"每用户独立实例 + 独立 `DSH_HOME` + uid/bwrap 隔离"→ 插件的单租户 DB **变成每用户一份**,无需加 `userId` 列 |
| 3 | **数据与产物**存储 | DB 在 `DSH_HOME`(平台里 = `<userRoot>/home`,用户在 `ws` 里默认看不到);**产物写在用户工作区内**(如 `视频对标/…/analysis.json`)→ 天然按用户隔离 |
| 4 | 插件**自带数据库**有无风险 | 总体可接受:`node:sqlite` 在平台 Node **22.23.2 实测可用**;风险点见 §五(实验 API 随 Node 变动、用户可损坏自己的库、需备份/重建路径) |
| 5 | 功能插件**调用 skill** 应整合还是外置 | ✅ **外置**(放平台共享技能层),插件**只按技能名引用**;**preset 随插件投放**;MCP 建议**预装**而非每次 `npx` 拉包 |
## 二、插件形态解剖(实测证据)
| 维度 | 事实 |
|---|---|
| 包形态 | `dsh-plugin-mcn`(569K):`dsh.client{platform:web, inject:[dsh-client-runtime, dsh-client-ui-sidebar]}` + `dsh.bundle.patch → cordis.patch.yml`(`insert: mcn-nav → dsh-plugin-mcn`) |
| Host 面拆分 | `lib/{index,db,data,http,mcp,imports,video-tools,workshop,config}.js` |
| 数据库 | `node:sqlite`(`DatabaseSync`),`DB_PATH = join(homedir(), ".dsh", "mcn-plugin.db")`;另读 `homedir()/.dsh/storages/workspace.json`、写 `homedir()/.dsh/mcn-rank-update.json` |
| 表结构 | 10 张表(`hot_accounts` / `account_videos`(362 行) / `account_video_analysis` / `account_persona` / `account_analysis` / `account_video_source` / `creative_log` / `rewrite_log` / `storyboard_log` / `script_review`):**按 `account_id` 组织,无 `userId`/`owner` 字段**(= 单租户设计) |
| 技能调用方式 | **插件不执行技能**:UI 收集参数 → **拼提示词**要求 agent 调用具名技能("请调用「mcn-dou-analysis」技能(路径 `~/.dsh/skills/mcn-dou-analysis/`,已全局注册)…") |
| 硬编码技能路径 | `~/.dsh/skills/` 下:`mcn-dou-analysis` ×6、`script-review` ×3、`short-video-script` ×2、`storyboard-prompt` ×1、`mcn-data-insight` ×1 |
| 能力来源 | `agentPreset`:`ctx.get("agentPresets").resolve("mcn")` + `presets.mount(agentCtx, resolvedId)`;preset 实体在 `<DSH_HOME>/.agent-presets/mcn/{preset.yml, agent.cordis.yml}`(挂 persona / agent-instructions / tool-bash / tool-fs / tool-fs-search / … ) |
| MCP | 自带 **stdio MCP 客户端**(`mcp.js`):`npx myai-mcp`(`NPX_CMD` / `MCP_PACKAGE` / `MCP_ENV`);**且该文件已优先读 `DSH_HOME`**(正确写法) |
| 产物落点 | 用户工作区(如 `{产出根}/<账号>/视频对标/<视频>/analysis.json`);Excel 导入用 `xlsx` |
> 关键洞察:插件的**能力 = preset**(preset 决定挂哪些工具/技能/MCP),插件本体只是 **UI + 数据 + 提示词编排**。
## 三、平台化必改清单
| 优先级 | 改动 | 现状 → 目标 | 为什么 |
|---|---|---|---|
| **P0** | **DSH_HOME 路径** | `join(homedir(), '.dsh')` → `process.env.DSH_HOME ?? join(homedir(), '.dsh')`(`config.js` 3 处:`DB_PATH` / `storages/workspace.json` / `mcn-rank-update.json`) | 平台里 `HOME=<userRoot>/ws`、`DSH_HOME=<userRoot>/home`,**两者不等** → 现状会写到 `<ws>/.dsh/`,并**读不到真正的 `storages/workspace.json`**(工作区/账号目录定位失效)。`mcp.js` 已是正确写法,可对照 |
| **P0** | **技能路径** | 删除 `~/.dsh/skills/<name>/` 硬编码(共 13 处),只保留**技能名**;或读平台注入的技能根(共享只读层 env) | 平台技能是"**共享只读层 + 个人层**"两段式(档案 10/11),且实例 `HOME=ws` → `~/.dsh/skills` 不存在;agent 按"已注册技能名"即可加载,不必给路径 |
| **P0** | **agent preset 随包投放** | `<DSH_HOME>/.agent-presets/mcn/` 必须在用户实例里存在 | 平台每用户 `DSH_HOME` 独立 → preset 无人写进去就退化为默认 preset(注释已写明"否则工具集为空/能力缺失")。建议:随插件包或平台 provisioning 写入 |
| **P1** | **MCP 预装** | `npx myai-mcp` → 预装到镜像/实例(或内置实现) | 平台实例有 **512M 内存 + 出网护栏 + 无外网缓存**,每次 `npx` 拉包会慢且可能首启失败 |
| **P1** | **DB 备份/重建路径** | 增加"库损坏 → 重建空库"的兜底(表结构可重建) | 用户在实例内可写 `DSH_HOME`(只有 `cordis.patch.yml`/`package.json`/`pnpm-lock.yaml` 被 ro-bind,DB 不在其中)→ 有自伤风险 |
| **P2** | **技能依赖声明** | 插件 README/元数据声明"需要哪些技能" | 便于平台侧按需投放;避免"装了插件但技能缺失"的静默失败 |
## 四、投放与隔离(怎么做)
1. **投放路径**:admin 在门户 `plugins.html` 上传 tgz → 进候选池(默认禁用)→ 用户在实例设置「功能插件」勾选启用 → 重启实例生效(档案 16 的既有机制)。
2. **安装**:平台走 `pnpm add file:<tgz>`(HOME=`<userRoot>/ws`)→ 每个用户 profile 一份;**新用户**由 `ensure-*` 脚本族 + provisioning 钩子补齐(参照目录选择器插件的做法)。
3. **隔离**:DB/产物/技能都在该用户自己的实例内(uid + bwrap)→ 用户间互不可见;跨租户不成立。
4. **多用户注意**:`mcn-schedule`(定时任务)与 `dsh-plugin-social-workbench` 是独立包,**要一起投放**否则功能缺失;`mcn-schedule.json` 同样在 `DSH_HOME` 根 → 与 P0 同改。
## 五、自带数据库的风险评估
| 风险 | 评估 |
|---|---|
| 引擎可用性 | ✅ 实测:平台 Node **22.23.2** 直接 `require('node:sqlite')` 成功(仅 `ExperimentalWarning`) |
| 与平台 DB 冲突 | ❌ 无:平台用 `better-sqlite3`(`/var/lib/dshs/*.db`),插件用自己的文件,互不相干 |
| 并发 | ❌ 无:每用户独立实例,DB 无跨进程并发 |
| **实验 API 变动** | ⚠️ 中:`node:sqlite` 在不同 Node 版本间 API 可能变 → 应补进**档案 26 升级耦合点**(Node 升级时回归) |
| **用户可损坏自己的库** | ⚠️ 中(自伤):实例内可写 `DSH_HOME` → 建议加"重建空库"兜底(P1) |
| 体积/性能 | ✅ 低:本地 4.2MB(10 表、362 视频行);每用户一份,磁盘可控 |
## 六、技能:为什么"外置"而不是"整合进插件"
| 维度 | 整合进插件 | **外置(推荐)** |
|---|---|---|
| 体积 | 技能副本 × 用户数(每个 profile 一份) | 共享只读层**一份**(档案 10/11) |
| 更新 | 改技能要重装插件 + 重启 | 改技能层即可,插件不动 |
| 与平台能力冲突 | 与"技能管理面(共享/个人技能上传)"冲突 | 复用平台既有技能管理面 |
| agent 加载 | 插件得自己把技能挂进 preset | agent **按技能名**加载已注册技能 ✓ |
| 结论 | ✗ | ✅ |
**做法**:插件里把 13 处 `~/.dsh/skills/<name>/` 换成**只写技能名**(或由平台注入技能根,插件读 env);技能本体由平台技能层(共享只读 + 个人)投放;**preset 仍需随插件投放**(它是"这次会话挂哪些工具"的清单,属插件能力的一部分)。
## 七、落地建议(分三步,建议顺序)
1. **改造(插件侧,P0 三项)**:DSH_HOME、技能路径、preset 投放 → 这是"能不能跑"的门槛;
2. **投放(平台侧)**:按功能插件机制上架 + 新用户自动铺开(复用 `ensure-workspace-picker.cjs` 的`--user-id` 模式,扩成通用 `ensure-plugin` 脚本);
3. **加固(P1)**:MCP 预装、DB 重建兜底、技能依赖声明。
## 八、红线与回归
- 不修改官方 dsh 包;投放走功能插件机制(档案 16);新用户铺开走 provisioning 钩子(档案 18 v3 做法)。
- 升级回归需补两条:① `node:sqlite` API(Node 升级)② 功能插件 client bundle 契约(档案 26 §C4)。
> 本文为**评估**(只读分析 + 推荐),未改动插件源码;改造需按 §七 分步实施并逐项验证。