dsh-matrix-agent
Matrix agent bridge for DeepSeek Harness (dsh): multi-twin per-room agent sessions, in-chat approval, media/rich-text/reply/edit-aware message intake
AI Analysis
核心用途是将 DSH 接入 Matrix 聊天网络。适合需要将 AI 引入 Matrix 频道、进行群聊交互、富文本处理及真人审批控制的团队。
Install
This plugin has no verified bundle, or compatibility checks failed. Read the repository notes first. Read the full README ↗
README
Read the full README ↗配置
在 profile 的 cordis.patch.yml 行上覆盖(整个 config 值替换,不深合并):
| 字段 | 默认 | 说明 |
|---|---|---|
homeserverUrl | 必填 | homeserver 的 client-server API base URL |
accessToken | '' | 分身 access token;为空回退环境变量 DSH_MATRIX_TOKEN,两者都缺则插件加载失败 |
userId | 必填 | 本进程登录的数字分身账号,如 @ai-niukunliang:example.org |
owner | '' | 工作责任负责人(真人账号,仅客户端登录);设置后审批/吊销仅其可应答 |
respondToAll | true | 响应房间所有消息;设为 false 则仅 @提及/私聊 响应 |
allowedUserIds | [] | 白名单;为空且 allowAllUsers=false 时拒绝所有人(fail closed) |
allowAllUsers | false | 允许任意用户(仅开发用) |
provider | deepseek-official | 每个房间 agent 的 LLM provider |
model | deepseek-v4-flash | 每个房间 agent 的模型 |
agentPreset | standard | room agent 挂载的 agent preset(决定工具集与角色提示);留空则无工具 |
chunkMaxChars | 4000 | 出站单条消息字符上限(含分段前缀) |
mergeTimeoutSecs | 5 | 裸文本合并窗口(秒) |
approvalTimeoutSecs | 300 | 审批推送后等待聊天答复的秒数 |
stateDir | .dsh-matrix | 状态目录(state.json 房间映射 + 去重 + sync token) |
maxRetriesBeforeAbort | 5 | 同一房间 turn 内 LLM 受限自动重试达到该次数时主动 cancel 止损 |
retryCircuitBreakerEnabled | true | 是否启用重试熔断兜底 |
digitalTwinMode | false | 可选:同一进程挂载多个分身(见下方示例) |
digitalTwins | [] | 额外分身账号列表(通常每个分身一个进程,无需配置此项) |
authStoreFile | auth-store.json | 记忆授权库文件名(相对 stateDir) |
redlineTools | ['bash','pwsh','write','edit'] | 红线工具:即使有记忆授权也每次强制房间确认 |
cwdCandidates | [进程 cwd] | 新房间工作目录引导的候选目录列表;首项作为缺省 |
taskQueueMax | 20 | 单个房间 matrix 任务队列上限,超出后最早 pending 任务自动拒绝 |
matrixTools | true | 是否注册 10 个 Matrix 工具(成员/消息/房间/用户查询、主动发送、媒体下载、自我时间线) |
notifyRoomEvents | false | 是否把入群/离群/资料变更等房间事件注入 agent 会话(供主动打招呼等) |
proactiveSendRequiresApproval | true | 主动消息工具(matrix_send_dm/send_room_message/mention_member)首用是否需 Owner 批准 |
preserveRichText | true | 是否保留富文本(formatted_body)/回复上下文/编辑语义,结构化注入 agent(类人信息完整);false 回退纯文本 |
soul.enabled | true | 是否启用灵魂注入(性格/风格/口头禅/习惯注入 room agent 的 system prompt) |
soul.persona | '你叫小灵…' | 性格/人设描述(自由文本) |
soul.style | 'friendly' | 说话风格:concise/friendly/formal/humorous/sassy |
soul.catchphrase | '交给我吧' | 口头禅(可选) |
soul.habits | '先确认需求再动手…' | 工作习惯(自由文本) |
soul.replyLength | 'short' | 回复长度偏好:short/normal/detailed |
testRoomPrefix | '【测试】' | 房间名前缀匹配即视为测试房间,给数字人注入测试声明(「当前是测试环境,请勿真实执行任务/修改文件/向真实用户发送消息」);空=关闭 |
twinModeRoomPrefix | '' | 房间名前缀匹配即启用秘书编排(任务入队/开工请示/交付确认),即使 digitalTwinMode=false;用于「只给测试房间开秘书编排」;空=不启用 |
roomRoles | {} | 房间 → 灵魂预设 id 的固定角色映射(如 { '!room:hs': 'dev' });未配置用百变员工 |
taskClarifyBeforeStart | true | 开工前是否私下 DM 老板请示要求/优先级;超时按原任务开工 |
taskClarifyTimeoutSecs | 120 | 开工请示等待秒数 |
taskConfirmBeforeDeliver | true | 交付前是否私下 DM 老板结果摘要请求确认 |
taskConfirmTimeoutSecs | 600 | 交付确认等待秒数 |
taskConfirmTimeoutAction | 'hold' | 确认超时行为:hold(挂起待确认)/deliver(自动交付)/cancel(取消) |
taskConfirmExemptMatters | [] | 豁免交付确认的事分类(低风险任务跳过确认) |
内置灵魂预设(设置页「选择预设」一键填充,可再微调后保存):
| 预设 | 适用 |
|---|---|
dynamic 百变员工(默认) | 根据房间氛围/语境自动切换人设与语气 |
default 综合助手 | 通用助手,靠谱有人情味 |
pm 产品经理 | 关注用户价值与目标拆解,习惯先对齐需求 |
dev 研发工程师 | 技术扎实、沟通直接,先说根因再给方案 |
qa 测试工程师 | 细心严谨,问题描述带复现步骤/预期/实际 |
leader 领导(负责人) | 看全局抓重点,协调资源推动决策 |
newbie 新入职员工 | 谦虚好学,持续学习完善,不懂就问 |
autoIntroduce | true |
maxSelfIntroMentions | 20 |
memberMemory | true |
autoGreet | true |
selfIntroTemplate | 模板 |
配置示例
推荐:每个分身一个 harness 进程(单账号模式)
### 配置示例
**推荐:每个分身一个 harness 进程(单账号模式)**
```yaml
# 分身 @ai-niukunliang 的 profile 配置
userId: '@ai-niukunliang:example.org' # 本进程登录的分身
accessToken: '...' # 分身的 token(或 tokenEnv 环境变量)
owner: '@niukunliang:example.org' # 真人账号(仅客户端登录):审批仅其可应答
respondToAll: true # 参与房间协作,响应所有消息
allowAllUsers: false # 生产建议用白名单 fail closed
allowedUserIds: ['@niukunliang:example.org', '@tianjintao:example.org']
可选:同一进程挂载多个分身(digitalTwinMode)
digitalTwinMode: true
digitalTwins:
- userId: '@ai-niukunliang-pm:example.org' # 分身账号(需预先注册并取得 access token)
tokenEnv: 'DSH_MATRIX_AI_NIUKUNLIANG_PM_TOKEN' # 从环境变量读 token(推荐);或直接 accessToken
owner: '@niukunliang:example.org' # 工作责任负责人:仅其可在房间应答审批
role: 'pm' # 角色标签(展示用)
respondToAll: false # 默认仅 @提及/私聊 响应;true 则响应所有消息
provider: '' # 留空回退顶层 provider/model
model: ''
每个分身独立 sync 循环、独立状态文件(/twins/.json)、独立 per-room agent 会话;审批按「分身×房间」维度记录记忆授权,Owner 变更不影响其他分身。
使用
- 真实人在 Matrix 客户端登录自己的账号(如
@niukunliang),把它加进目标房间 - 每个分身账号各启动一个 harness:
dsh --profile,插件自动加入房间(邀请自动接受) - 房间里 @提及 分身即可让它干活;分身要执行红线工具时会推送审批,Owner 在客户端回复「批准/拒绝」(超时按 unavailable 处理)
- 常用命令:
/status(看会话)、/auth list(看记忆授权)、/auth revoke(吊销,仅 Owner) dsh plugin --profile web remove dsh-matrix卸载;组合层变更需重启 dsh 进程(不参与 HMR)
安全红线
- Matrix 通道等于绕过本机批准体系:approval 应答必须来自白名单 sender 且对应本房间真实 pending 的审批
- 聊天内容只能进会话流(
source.kind = 'plugin'),绝不允许直接执行 shell - access token 不进日志、不落盘;
state.json不包含任何聊天内容
开发
corepack pnpm install
corepack pnpm test # tsc + node --test(format 单测 + 假 homeserver 端到端)+ esbuild 打包 client
corepack pnpm build # tsc(lib/ 产物)+ esbuild 打包 src/client-main.js → lib/client.js
改完代码必须重新 build 并重启 dsh 进程(ESM 缓存 + web bundle 重新扫描)。
Client 半构建约定:dsh web 的 client-modules 加载器要求
exports["./client"]指向window.__ModuleLoader__.load({ id, factory })注册格式的自包含 bundle。 本项目用 esbuild 打包:src/client-main.js(ES module 源码,import React) → CJS bundle → banner/footer 包装成__ModuleLoader__.load格式 →lib/client.js(见scripts/build-client.mjs)。react外部化(dsh 模块系统的 shell seed, 由 factory(require) 注入,避免与 shell 的 React 实例冲突);其余代码内联自包含。 构建后自动node --check语法自检。改 client 半时改src/client-main.js,不要改lib/client.js。
测试系统(test-system)
独立于插件仓库根项目的 Node 测试项目(test-system/):连真实 Matrix homeserver,
模拟多个群 + 多个 AI 同事(LLM 扮演),对运行中的数字人发起真实对话,实时网页查看过程、
断言评估、出测试报告——支撑「设计 → 开发 → 测试 → 改进」闭环。
- 多群 + AI 同事:同时跑多个测试房间(群),每房间独立对话循环;OpenAI 兼容 LLM 扮演同事 (角色 persona + 房间上下文 + 测试目标),动态发言、追问细节
- 实时网页:SSE 推送房间列表 + 对话流(同事↔数字人气泡)+ 状态徽标(进行中/完成/失败)
- 干预控制:每房间暂停/继续/跳过等待/停止/换同事/注入消息,全局全部暂停/继续/停止
- 场景生命周期:Web 顶部场景下拉 + 开始/重新开始/停止(stop 清空、重跑 run 计数 +1)、单房间重跑
- 断言引擎:场景房间定义断言(
twin-replied/twin-responded-in-time/twin-mentioned-colleague/message-count/twin-sent-dm/boss-approved/task-delivered/custom),房间跑完自动评估, 房间卡显示 ✔/✘ 徽标、对话流逐条显示、聚合场景报告——失败的断言即改进清单,改完插件点「重新开始」重测 - 秘书流程场景:
task-flow场景 +BossAgent(模拟老板:监听数字人私聊,「任务请示」→批准、 「交付确认」→确认交付)——数字人侧把twinModeRoomPrefix设为测试房间前缀即可在测试房间开秘书编排 (见test-system/README.md完整说明)
已知限制与路线图
- 仅非加密房间:
m.room.encrypted事件只提示不支持(E2EE 二期:Rust crypto + 设备验证) - 媒体已支持,但无 OCR/转写:图片/文件/音视频会下载落盘并作为多模态附件/路径交给 agent;暂不内置 OCR、音频转写、视频抽帧等解析(可用 agent 自身能力或外部工具处理已保存的文件)
- 不流式推送工具进度:每条
assistant/message一条(或多条分段)消息 - 仅长轮询:无 appservice/webhook 模式,主机需可出站访问 homeserver
使用
- 真实人在 Matrix 客户端登录自己的账号(如
@niukunliang),把它加进目标房间 - 每个分身账号各启动一个 harness:
dsh --profile,插件自动加入房间(邀请自动接受) - 房间里 @提及 分身即可让它干活;分身要执行红线工具时会推送审批,Owner 在客户端回复「批准/拒绝」(超时按 unavailable 处理)
- 常用命令:
/status(看会话)、/auth list(看记忆授权)、/auth revoke(吊销,仅 Owner) dsh plugin --profile web remove dsh-matrix卸载;组合层变更需重启 dsh 进程(不参与 HMR)