dsh-agents-viewer
atrestandbed-bot/dsh-agents-viewer
在右侧栏原生 tab 里查看并编辑 AGENTS.md / CLAUDE.md 指令链:全局、共享,以及从项目根到会话工作目录的每一层;就地保存,文件不存在时直接创建;另有聊天头部按钮,以及界面不可用时也能用的 /agents 命令。
安装
dsh plugin --profile web add github:atrestandbed-bot/dsh-agents-viewerREADME
dsh-agents-viewer
在 DSH(DeepSeek Harness)右侧栏的原生 tab 里查看和编辑 AGENTS.md 指令链 —— 聊天头部还有一个一键打开的按钮,外加一个 /agents 命令。
需要带
ctx.sidebarRightTabs的 DSH。0.2.2-rc.1(Electron 44.7.0)已验证;engines.dsh只保留下限>=0.2.2-rc.1,dsh.client.inject为空,服务全部在运行时探测。这样 DSH 小版本更新不需要改清单;真改了 API,最坏是少一个 tab,DSH 仍能启动。
功能
-
右侧栏原生 tab:在右侧栏的「添加」菜单 / 引导页里打开
AGENTS.md。用 DSH 自己的 tab、分栏、全屏、拖拽和收起,不再有浮动抽屉、遮罩、requestAnimationFrame跟随,也不会出现「等 30 秒兜底按钮」。 -
聊天头部按钮:文件/侧栏按钮那一簇的左边有一个 AGENTS.md 图标,点一下打开原生 tab;右侧栏已展开且当前就是 AGENTS.md 时,再点一次收起侧栏。默认显示;
/agents c//agents o把状态写入持久化文件,下次启动 DSH 后按新状态显示/隐藏。 -
完整指令链:全局
~/.dsh/AGENTS.md、共享~/.agents/AGENTS.md,以及项目根到会话 cwd 的每一层目录下的AGENTS.md / CLAUDE.md / AGENTS.local.md / CLAUDE.local.md。面板与/agents命令现在同一口径,子目录里的文件也能直接改。 -
精确项目:tab 正文从标准 props 拿到
sessionId/useSessions,宿主按 session id 反查 workspace;不再用「最近更新的工作区」猜。 -
原地编辑保存:列表点选 → 编辑 →
Ctrl+S或「保存」;不存在的文件写内容保存即创建。 -
/agents命令(不依赖界面,任何情况可用):/agents 列出所有 AGENTS.md /agents <序号> 看全文 /agents all 看全部 /agents w <序号> 用外部编辑器打开 /agents n 新建(项目级) /agents n global 新建全局 /agents n shared 新建共享 /agents o 记录“显示按钮”(下次启动生效) /agents c 记录“隐藏按钮”(下次启动生效) /agents help 用法
安装(给别人用)
这个包是标准的 DSH dual-face bundle:宿主半在 index.js,客户端半在 runtime/client.js,由 package.json 的 dsh.client 声明。装进某个 profile:
$profile = "$env:USERPROFILE\.dsh\profiles\desktop"
$name = "dsh-agents-viewer"
# 1) 把包目录复制进去(要包含 runtime/)
Copy-Item -Recurse -Force "<这个包的路径>" "$profile\node_modules\$name"
# 2) 在 profile 的 package.json 里登记:
# dependencies 里加 "dsh-agents-viewer": "file:<这个包的绝对路径>"
# dsh.profile.bundles 末尾追加 "dsh-agents-viewer"
# 注意:bundles 才是“启用”开关;只在 dependencies 里是“装了但没启用”。
# 3) 重启 DSH(客户端 tab 的类型注册发生在启动时)
更推荐直接用 DSH 的插件页安装这个包(会自动处理依赖和 bundles),或在本 checkout 里跑 npm run adapt:install。改之前建议先备份 profile 的 package.json 和 cordis.patch.yml。
自动适配
0.7.0 起,插件不再把 DSH 版本写死:
dsh.client.inject为空:客户端只require("react")(基座模块),不依赖任何@deepseek-ai/dsh-client-*包名;engines.dsh只留下限,不设上限;- 客户端只 Cordis-inject
slots;sidebarRightTabs/sidebarRight在apply里用ctx.inject按需等待。DSH 改名或删掉其中一个,只会少对应的入口,不会让插件永远 pending 或拖垮界面; - 宿主对
webServer.register/commands.register/workingDirectory.ensure先判类型,缺了只打 warning; webserver/index-inject全包 try/catch,任何异常都不会把 index 变成 500。
升级 DSH 后:
npm run adapt # 只检查:版本、engines、profile 副本是否一致
# 退出 DSH 后,需要把本 checkout 同步进 profile 时:
npm run adapt:install
adapt:install 会在 DSH 运行时拒绝执行,因为运行中替换插件文件可能触发客户端热重载、打断当前窗口;它同时会把旧的 panel.js、嵌套的 runtime/runtime/ 等残留清掉。
升级 DSH 后(手动检查)
node scripts/check-compat.mjs
# 或指定安装位置
node scripts/check-compat.mjs --asar "D:/Program Files/DeepSeek Harness/resources/app.asar"
它会拿当前安装的 app.asar 核对 dsh.client.inject 里的每个包是否存在、engines.dsh 是否接受当前版本、客户端 bundle 是否还按 window.__ModuleLoader__.load 注册。DSH 改了模块名时,这里会先报 FAIL,而不是等 DSH 打不开才发现。
DSH 打不开时,先分清是谁的问题
desktop welcome: Web authentication failed 这类启动失败不是插件造成的:
- 崩溃报告在
%APPDATA%\@deepseek-ai\dsh-desktop\logs\crash-*-host.log。如果--- error ---是desktop welcome: Web authentication failed,失败发生在桌面壳向自己刚启动的 Host 换 cookie/取 index 的那一步,插件还没参与。 - 崩溃对话框里的「禁用第三方插件」会备份
cordis.patch.yml并把dsh.profile.bundles重置为官方组合。如果点完还继续崩,就证明与插件无关——继续反复点、反复启动只会拉长故障时间。 - 插件本身出问题时的表现完全不同:Host 仍会启动,日志里是
dsh: warning: N entry did not activate,界面只是少了这个 tab/按钮。宿主半和客户端半都做了兜底,单个注册失败不会影响 DSH 启动。
真正需要检查的:是否有残留的 DSH 进程、更新下载后是否卡在安装交接(%LOCALAPPDATA%\@deepseek-aidsh-desktop-updater\pending)、以及本机的 dsh-auth-* cookie 是否已经堆到 16 KB。一次只启动一个实例,别在更新安装期间反复双击图标。
另一种 Web authentication failed:cookie 431
DSH Desktop 的 Host 每次用随机端口启动,而登录 cookie 名是 dsh-auth- + hash(host:port)。端口变一次就多一条 cookie,名字不复用;Chromium 又把 127.0.0.1 的所有 dsh-auth-* 一起塞进同一个 Cookie 头。约 70 次启动后请求头超过 Node 默认的 16 KB,Host 直接返回 431,桌面壳就报 desktop welcome: Web authentication failed。
自查(先退出 DSH,cookie 库运行时被独占锁住):
$db = "$env:APPDATA\@deepseek-ai\dsh-desktop\Network\Cookies"
python -c "import sqlite3,sys;c=sqlite3.connect(sys.argv[1]);print(c.execute(\"select count(*) from cookies where name like 'dsh-auth-%'\").fetchone()[0])" $db
≥ 70 就要清。清理只删 dsh-auth-*、先备份,参考 dsh-cookie-431。长期方案是在 profile patch 里把 @deepseek-ai/dsh-client-connection 的 cookieMaxAgeDays 从默认 30 改成 3(本机 profile 已经加上,见下面「改 profile」)。
改 profile 必须退出 DSH
桌面 profile 开着 HMR。运行中改 cordis.patch.yml(尤其 connection)或 package.json 的 bundles,会立即重载对应节点:当前浏览器连接被换掉,进行中的会话会以 turn/end: aborted / disposed 结束,窗口看起来就是「挂掉」。改 profile 的 bundles、connection 或任何启动项前,先完整退出 DSH,改完再启动;只改插件工作目录里的代码则可以热重载。
文件
index.js 宿主:HTTP 路由(/list /read /write /ui)+ /agents 命令
runtime/client.js 客户端:sidebarRightTabs 注册 + tab 正文 + 头部按钮(手写 bundle,无构建)
runtime/override.css 宿主每次 index 请求注入的 CSS 覆盖层(改完刷新即可)
cordis.patch.yml bundle 补丁:插入 dsh-agents-viewer 一行
scripts/adapt-dsh.mjs 自动适配:检查运行时 / 版本 / profile 副本,可一键同步安装
scripts/check-compat.mjs 清单核对(inject 包 / engines / client 入口)
scripts/lib/dsh-runtime.mjs asar 读取、semver、进程检测、profile 同步
locale/*.json 插件管理器里显示的标题与描述
icon.svg 图标
实现要点
- 客户端:
ctx.sidebarRightTabs.register({ id, kind, priority, title, guide, keepMounted })注册页面类型;正文通过ctx.slots.register({ name: 'sidebar.right.pane.tab', key: id }, Body)挂载。正文的标准 props 直接给sessionId和useSessions,没有 DOM 观察、没有 URL 解析。 - 头部按钮:注册进
conversation.session.header.utilities(list 槽,order: -100),位置在文件/侧栏按钮那一簇的左边。点击时:侧栏收起 →openTab('agents');已展开且当前 tab 是agents→toggleExpanded()收起;展开但是别的 tab → 切到agents。/agents o/c只写~/.dsh/storages/dsh-agents-viewer.ui.json,按钮在页面加载时读一次/ui,所以显隐下次启动/刷新生效。 - CSS 覆盖层:
runtime/override.css由宿主在每次 index 请求时现读并注入<style>;编辑器换行等样式改完刷新页面即可,不用重启。 - 宿主:
webServer.register暴露/dsh-agents-viewer/list、/read、/write;resolveProject(hint)从hint里的session-<uuid>反查~/.dsh/storages/workspace.json。拿不到会话才退回最近工作区,并在 tab 上标「推断」、保存前确认。 - 白名单:全局 / 共享 + 项目根到 cwd 的目录链;其余路径一律 403。写盘是宿主进程直接
fs.writeFileSync,白名单是唯一入口。 - 兼容性:
dsh.client.inject为空,engines.dsh只有下限;客户端只 injectslots,sidebarRightTabs/sidebarRight用嵌套ctx.inject按需等待,宿主对三个服务先判类型。DSH 改名/删服务时,对应入口不注册、打一条 warning,DSH 仍能启动,/agents命令在其他入口失效时也照常可用。webserver/index-inject和所有注册都做了 try/catch,插件永远不会把 index 打成 500。 - 启动安全:宿主插件加载失败只会让 DSH 打一条
entry did not activate警告;npm run adapt在升级 DSH 后核对版本/清单/profile 副本,npm run adapt:install在 DSH 运行时拒绝执行,避免热替换打断窗口。
已知限制
- 没有浮动面板:tab 只在右侧栏里;头部按钮在
conversation.session.header.utilities(文件/侧栏按钮那一簇的左边),不在 tab 条上。 /agents o/c不是即时显隐:只改持久化状态,按钮在下次启动/刷新的页面加载时读取;当前页面运行中不会马上变。- 面板保存不触发指令热刷新:宿主是直接写盘,
dsh-agent-instructions只会在后续一次read / write / edit工具调用时刷新。当前会话要立刻看到新内容,需要新开会话,或让 agent 对该文件做一次读写。 - 指令链只覆盖项目根到会话 cwd 的目录链:链外的任意子目录不会出现在列表里(与
/agents命令一致)。 - 首次安装/升级需要重启 DSH,客户端模块图在启动时组装。
许可
MIT