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

9.1 KiB
Raw Blame History

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)。

本文为评估(只读分析 + 推荐),未改动插件源码;改造需按 §七 分步实施并逐项验证。