DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

let-mi-think /

let-mi-think/agent-manager

Verified

This plugin has no description yet.

★ 0 Stars0 Forks0 IssuesN/A Community rating0 Confirmed installs
View on GitHub
READMESource: main@4a692cbd

dsh-agent-manager

多 Agent 管理与配置插件(DeepSeek Harness)。与 dsh-eli-mode 并存,不改动它的任何文件。

安装

dsh plugin --profile web add dsh-agent-manager

装完重启 dsh web,设置里会出现 Agent 管理 分区。

  • 宿主要求:dsh 0.1.0-rc.7(见 package.json 的 dsh.engines.dsh);Node ^22.19.0 || ^24.0.0。
  • 知识库是可选依赖:知识库清单 / 导入 / 重建索引这组功能复用 dsh-eli-mode 的 eliKb 服务。 没装 eli-mode 时它们显示为禁用态,其余配置照常可用。
  • 客户端产物随包分发(lib/client.js 已提交),安装时不需要构建。

它做什么

  • 在 DSH 设置区新增一个「Agent 管理」分区:先选 Agent,再配置它(比 Eli Mode 的单体配置多出「多 Agent 选择」这一步)。
  • 在官方「Agent 预设」卡片上叠加一个「编辑」按钮,点开直接进入该 Agent 的配置。
  • 每个 Agent 可配置:人格 prompt、知识库注入 prompt 模板、可勾选的知识库条目清单(勾选后把条目清单注入提示词,正文由 kb_read 按需取)、四个知识库工具的独立开关、可用哪些 MCP 连接。
  • 注入清单的每行是 - <条目路径> — <标题>(与 eli-mode 生成的目录页同格式):标题让 Agent 光看清单就知道该读哪一篇,中文文件名下标题自然就是中文。
  • 新建 Agent:选一个现成预设作蓝本,插件复制它的目录并改写组合文件,新 Agent 立刻出现在预设选择器里(新会话生效)。
  • 导入知识库:填一个目录路径 → 扫描预览 → 整批导入(用于初始化 / 迁移一批文档),顺带补上知识库本身没有的「重建索引」入口。

三个平面

平面 文件 挂载方式
host lib/index.js 本插件 cordis.patch.yml 的 insert
preset lib/preset.js 每个生成的 Agent 预设在自己的 agent.cordis.yml 里按 id 挂载
浏览器 lib/client.js package.json 的 dsh.client

preset 平面由预设自己挂载,是为了让它天然绑定到「自己服务哪个 Agent」——挂载行里带 config.presetId。

配置存哪

  • 配置数据:~/.dsh/settings.yaml 的 agent-manager 段,形状 agents: { <presetId>: { ... } }。由插件注册的设置命名空间读写,不写进预设的组合文本。
  • 归属标记:新建的预设目录里写一个侧车文件 .agent-manager.json,记录 managedBy / blueprintId / createdAt。删除只允许删带这个标记、且位于 ~/.dsh/.agent-presets/ 之下的目录,避免误删 eli-mode、wechat 等既有预设。

知识库

复用 dsh-eli-mode 的 eliKb 服务读取 ~/.dsh/eli-knowledge(同一份 wiki),不重复实现一套。因此:dsh-eli-mode 被停用或升级导致 eliKb 不可用时,知识库清单会显示禁用态,其余配置不受影响。

导入(初始化一批文档)

「Agent 管理」头部的「导入知识库」:填源目录(绝对路径)→ 扫描 出预览(+ 新增 / = 已存在、并列出被跳过的文件及原因)→ 导入 N 项。

  • 目录结构原样变成条目路径,可再套一个「落点前缀」,例如把 C:\...\docs 导成 tripartite/...。
  • 只认 .md / .markdown;跳过 index.md(各级目录页)、隐藏目录、node_modules 等;默认跳过已存在的同名条目(可勾选覆盖)。
  • 默认补标题行:源文件首行不是 # 标题 时,导入时会在最前面补一行 # <文件名>(原内容一行不删)。原因见下。
  • 只复制(或补标题行后写入)文件,源目录不动;导入后插件会自动调一次 eliKb.regenerateAllIndexes()。

为什么必须补标题行(eli-kb 会丢首行)

kb.js 的 _readRaw 是这么取正文的:

let title = norm.split('/').pop()
if (lines[0].startsWith('# ')) title = lines[0].slice(2).trim()   // 标题
const body = lines.slice(1).join('\n')                            // ← 首行被丢掉
return { id, title, content: '# ' + title + '\n\n' + body }

首行永远被丢弃:是 # 标题 时"丢得正好"(标题另外存了),不是时那一行正文就永久读不到 —— Agents 读不到、知识库网页看不到、search 也搜不到(search 基于同一份裁过的 content)。上游自己因此约定「首行即标题」(write() 强制写 # title,自带种子 wiki 的文件首行全是 # 标题)。

已有条目如果踩了这个坑(例如手拷进 wiki/ 的文件),用脚本就地补,不必删了重导(在包目录里执行):

node scripts/fix-title-lines.mjs           # 预览(不写文件)
node scripts/fix-title-lines.mjs --apply   # 执行:先备份,再补行,最后重建索引
# 个别条目的标题取自自身小标题(如 `# 1. 概述`)时,可用文件名重写:
node scripts/fix-title-lines.mjs --apply --force=6

备份落在 ~/.dsh/eli-knowledge/.titleline-backup-<时间戳>/(在 wiki/ 之外,不会被当成条目)。

为什么必须由插件来重建索引

会话清单读的是知识库根索引 ~/.dsh/eli-knowledge/index.md,而它只在 eli-kb 自己 write() / remove() / init()(且根索引不存在)时重建,知识库没有任何路由或按钮能手动触发。所以直接往 wiki/ 拷文件会出现「文件在、list() 看得见、Agent 却完全不知道」的哑谜。本插件为此提供两处入口:

# 面板内:导入知识库 → 仅重建索引
# 命令行(DSH 没跑起来时,在包目录里执行):
node scripts/reindex-kb.mjs
# 调 prompt 模板/清单格式时,先看看 Agent 到底会收到什么:
node scripts/preview-injection.mjs [presetId]

三个脚本都用 scripts/eli-kb.mjs 定位 dsh-eli-mode 的 lib/kb.js:先看环境变量 ELI_KB_MODULE,再按 Node 解析规则从当前目录找 dsh-eli-mode,最后试仓库内 vendored 快照。找不到时会直接告诉你该装什么或该设哪个环境变量。

中文条目名需要 dsh-eli-mode 的一个补丁

中文 / 下划线 / 空格命名的条目能否被读取,取决于 dsh-eli-mode 的 lib/kb.js 里 normalizeId 的字符集限制:

  • 上游原版只接受 [a-z0-9-] 段名 → 这类条目「能列出但读不到」(list()/tree()/search() 不走校验,read()/write()/remove()/双链解析才走),表现为知识库网页点不开、kb_read 返回空、kb_write 还会把中文标题 slugify 成 entry-xxxx。
  • 补丁后只校验「段非空且不是 . / ..」并拒绝 NUL:字符集任意,仍拒绝路径穿越,id 永远落在 wiki/ 之内。

补丁的判定只影响读取。要放中文条目,请让 eli-mode 使用打了补丁的版本(差异就是 kb.js 里 normalizeId 那一个函数)。

MCP 连接(按 Agent 收窄)

  • 数据来源是工具注册表,不是连接器的存储或它的 status 接口:连接器把每个 server 的工具注册成全局工具 mcp__<serverName>__<toolName>,所以「装了哪些、有哪些工具」以 ctx.tools.schemas() 为准。实测连接器自己的 status 接口报 0 个连接时,工具表里仍有 1 个真实连接(5 个工具)——按 status 做会误判成「没有 MCP」。
  • 怎么收窄:预设平面的 ctx 就是「该 Agent 的 scope」(DSH 为每个预设 createScope(selfCtx, { agentPreset: <id> })),因此在 preset 平面调用官方 ctx.tools.restrict({ deny }),未勾选连接的工具会同时从 schema、lookup 与 dispatch 中消失。这与 MCP 连接器收窄工作区用的是同一套机制。
  • 默认不限制:mcpRestrict 默认 false = 沿用「全部已连接的 MCP 都能用」,避免升级后静默砍功能。开启后才按 mcpServers 精确放行(勾选为空 = 全禁)。
  • 会跟随工具表变化重算:订阅 tools/registered,连接增删后按新工具表重新计算(否则重连之后仍被旧限制挡住)。重算前会先撤销自己的限制再读工具表,避免「读到被自己遮蔽后的子集、越算越少」。
  • 失败即降级:restrict() 若抛错(例如名字刚好失效、或该 scope 不允许限制),只记一条 warn 并保持不限制——不会让整个预设挂载失败。
  • 一个命名边界:连接器对超长/含特殊字符的工具名会截断并加 12 位哈希后缀,那种名字解析不出 serverName,本插件会把整条名字当成一个独立分组列出来(可选可放行),不会静默丢弃或静默禁用。

已知限制

  • 卡片上的「编辑」按钮是 DOM 注入:DSH 官方没有预设卡片级插槽(只有 settings.section 这类通用插槽)。选择器只用本地名后缀匹配([class*="_card"] 等),官方卡片结构变化时按钮会自动不注入并记一条 warn——独立分区仍然可用,功能不丢。
  • 工具开关是执行期拦截:预设组合按 preset 只挂载一次,注册期裁剪要重启才生效,所以四个工具一次性全部注册,在 execute 里按开关拒绝并返回说明。代价是禁用中的工具仍会出现在工具清单里。
  • 新建 Agent 需要直接写 ~/.dsh/.agent-presets/<id>/,绕过了官方 AgentPresets 服务「只允许整目录复制」的授权限制;因此改写只做按行文本修改 + YAML 校验 + 失败回滚,尽量保留蓝本里的注释。
  • 导入是「复制 + 重建索引」,不做去重合并:同一条目改了别处不会自动同步;想更新就开「覆盖」重新导一次。
  • 用 eli-kb 自己的 remove() 删条目时,若该目录已生成了 index.md(导入必然生成),空目录不会被自底向上清掉,会留一个只有 index.md 的空壳目录;条目列表不受影响(index.md 不算条目),需要时手动删目录。

开发

npm install          # 需要 devDependencies(tsdown / typescript / @types/*)
npm run build        # 产出 lib/client.js(已随仓库提交,运行时无需构建)
npm run typecheck
npm test             # node --test tests/*.test.mjs(不依赖 dsh-eli-mode)

host 半与 preset 半是免构建的 lib/*.js;只有浏览器半需要 tsdown 打包,再由 scripts/wrap-client.ts 包成 DSH 的 window.__ModuleLoader__.load 形状。npm publish 前 prepack 会自动跑一次构建。

需要真实 eliKb 实例的那部分测试(含中文 id 补丁与索引重建的验证)在开发用的单体仓库里维护,不随包发布。

上架(awesome-dsh-plugin / dsh-market)

插件市场里的列表来自精选列表仓库 awesome-dsh-plugin, 收录方式是往那边提 PR 新增一个条目文件(不是往 dsh-market 提):

  1. fork 该仓库,把本仓库的 contrib/let-mi-think__agent-manager.yml 复制成 data/plugins/let-mi-think__agent-manager.yml(文件名必须与仓库一致);
  2. PR 前确认本仓库已声明 dsh.bundle 且根目录有 cordis.patch.yml(两个都已具备);
  3. 给 GitHub 仓库加 dsh-plugin topic,并确保仓库创建已满 1 天(CI 会检查);
  4. 提 PR(一个 PR 最多 3 条,且只改自己那一条)。合并后站点与市场的 README 会自动重建,不要手工编辑那边的 README。

npm 包不是收录的必要条件,但发了才能显示下载量:npm publish 后映射会被自动采集 (条目里不要写 npm: 键,写了会被校验拒绝)。本仓库的 repository 已指向自己, prepack 会在发布前自动跑一次构建,lib/ 也已随仓库提交,因此从 npm 安装无需构建。

可选增强:在仓库根放 screenshots.json(1–8 张图,路径相对该文件、不能跳出仓库) 可以让市场显示应用商店式截图;不放也行,市场会从 README 自动抽取。

许可

MIT

—/ 5

No ratings yet

Verified DSH bundle

Commit 4a692cbd1f97

Community comments

No comments yet. Be the first to write one.

DSH HUB

A community index for DSH plugins. Not an official GitHub or DeepSeek AI product.

CommunityResourcesAPIAbout