Skip to content
dsh.fish
Bundle

@lemoncat7/dsh-partner

Long-lived AI companions with WeChat channel routing for DeepSeek Harness

Source
lemoncat7
License
MIT
Updated
Updated 6 days ago

Readme

# DSH Partner

面向 DeepSeek Harness 的长期 AI 伙伴与微信渠道插件。

伙伴不是一次会话中的临时提示词。每个伙伴拥有独立身份、Agent Preset、模型路由、能力声明,以及按微信联系人隔离的 DSH Session。第一版以微信为主要渠道,使用腾讯微信 iLink Bot API,不模拟个人微信网页版协议。

## 兼容性

正式版 `1.6.0` 针对 DeepSeek Harness `0.1.2-rc.1` 构建并完成部署验证,需要 Node.js `22.19+` 或 `24+`。DSH 官方 Agent、Session、Settings、Tools 与客户端 UI 依赖均锁定到 `0.1.2-rc.1` 接口族。

## 当前能力

- 伙伴创建、编辑与删除
- 新伙伴只建立身份和本地会话;能力、长期记忆、每日回顾、心跳、渠道与伙伴间授权默认全部关闭
- Agent scoped 身份提示,仅影响该伙伴创建的 Agent
- 为伙伴选择 Agent Preset、提供方与模型
- 微信 iLink Bot 扫码连接
- `bot_token` 只保存到 DSH Credential Store,管理 API 和浏览器均不返回
- 微信渠道启用、停用、断线退避与运行状态
- 私聊首次联系配对审批
- `微信机器人 + 联系人` 独立 Session 路由
- DSH Agent 完整回复后回发微信,并保留 iLink `context_token`
- 微信图片与文档双向收发:图片进入 DSH 原生附件上下文,文档安全保存到伙伴独立工作目录
- 伙伴可把工作目录内生成的图片、PDF、Office 文档及常用文本文件回发微信
- DSH 运行中发起选择题或自由提问时同步到微信;联系人回复序号、选项文字或自定义答案后,原 Agent 继续执行
- 微信在伙伴忙碌时遵循 DSH 全局 `ui-conversation.busyEnter`:`steer` 插入当前轮,`queue` 排入下一轮
- 按伙伴和微信联系人双重隔离的完整对话归档、每日回顾与结构化长期记忆
- 逐轮记忆提炼使用有界的专用上下文,只发送当前轮、相关记忆的精简视图与最近证据;每日终审保留当天每轮的双向代表片段,未进入提示的旧数据仍由存储层完整保留
- 从明确对话中形成可审计的联系人画像;可靠画像作为会话理解基线,偏好、任务、事件、关系与短期情绪信号继续按当前话题召回
- 人物画像按联系人隔离,使用固定长期槽位和证据阈值;用户可查看来源、手动修正或删除,已确认内容不会再被自动提炼覆盖
- 每日终审只保存有证据的记忆关系;强关系可把一跳关联记忆补入当前话题召回,并在关系审计中解释召回依据
- 冲突关系不会被合并成用户事实;仅在当前话题相关时提示伙伴指出差异并请求确认,所有关系仍严格按联系人隔离
- 对话提炼与每日终审会识别尚未闭环、反复不满意、采用临时方案或正在等待外部结果的「伙伴挂念」;长期记忆只提供理解背景,不直接生成巡检任务
- 伙伴会话额外提供一个紧凑的 `partner_concern_suggest` 候选工具;它只在伙伴自己的会话且长期记忆开启时可见,不会增加普通 DSH 会话的工具提示开销
- 工具候选和轮后提炼共用确定性准入策略:必须引用当前用户原话,满足优先级、置信度和综合分数门槛;每批最多新增两条,同主题只更新不重复创建
- 用户也可以自然地交代一件需要留意的事,并通过「继续留意、提高关注、已经解决、别管这个」控制它的生命周期;明确说出目标的“停止关注”会确定性更新状态,不依赖模型事后猜测
- 伙伴从记忆提炼或每日终审中自动新建关注后,会在当前伙伴会话中发出一次创建通知,并同步到对应的微信渠道,方便及时检查或移除
- 心跳只查询到期挂念,使用独立内存推理作用域观察上次检查后的变化;无到期事项时不会调用模型
- 心跳根据挂念选择当前可用的安全来源,并在来源内部逐层缩小范围:知识库按“找库→库内搜索→读取条目”,本地按“确定范围→定位文件/内容→读取证据”;发现阶段有独立软截止、单工具超时和整轮安全上限
- 知识文档明确指定本地核验命令时,心跳可使用作用域内临时注册的受控只读命令工具;它不经过 shell,只接受版本、npm 包版本和少量 Git 状态查询,禁止管道、重定向、脚本、任意程序与任意参数,并记录命令结果或拒绝原因
- 挂念明确关联 `@文件` 时,伙伴可先读取再以最小修改持续维护该文件;写权限精确限定到已关联的现存文件,不能创建其他文件或触碰伙伴私有存储
- 发现结果先保存为 Observation,经过去重、相关性、新鲜度、可行动性和近期打扰历史的确定性评分,再决定静默记下、下次顺手一提、进入伙伴动态或主动通知
- 心跳硬性排除伙伴记忆、挂念数据库、会话归档及其备份,不向无关主题扩散
- 未送达的重要提醒会保留并安全补发;普通对话开始时只召回与当前消息相关的延迟提及
- 每次实际巡察结束后在原伙伴会话写入一条可折叠的活动说明,便于核验工具、结果摘要、最终判断和通知状态,不生成伙伴回复气泡
- 可配置静默时段、检查间隔、每日通知上限、失败退避和手动检查;失败后不会早于正常检查间隔重试
- 修改伙伴身份或能力时清理该伙伴的渠道 Session,防止新旧人格串联
- Windows、macOS、Linux 兼容的原子状态写入
- 兼容 `SKILL.md` 的伙伴 Skill:安装与伙伴启用关系分离,支持在管理台创建本地 Skill、`inline` / `fork` 上下文、`allowed-tools` 权限收缩、校验和审计
- 内置精选 Skill,以及与 nomifun 当前一致的 ClawHub、LoopHub、SkillHub 三个公开 Skill 榜单;支持统一 HTTP 代理、连接测试、受限 ZIP 安装与兼容 JSON 索引的团队源,非可信市场强制使用隔离临时会话
- 人与伙伴共享的任务看板:收集箱、待开始、进行中、待验收、受阻、已完成六个状态,带优先级、负责人、乐观并发 revision 与有界活动记录
- 有向伙伴授权和真实委派:在 A 的能力页勾选 B 后,A 才能查看 B 的公开能力并通过 `@B` 委派;用户本人可从全局看板直接指派任意伙伴,只共享任务信封、公开能力和结果摘要
- 伙伴会话内提供 `partner_skill`、`partner_task_board`、`partner_collaborate`、`partner_schedule`,以及按能力显式授权的 `partner_companions` 作用域工具,不污染普通 DSH 会话的工具表;“创建伙伴”工具只填写身份,新伙伴权限仍由用户在管理台单独授予
- 伙伴定时任务支持间隔与每日时间、跳过或排队重叠、手动执行和重启恢复;每次使用新临时会话,完成后默认销毁,也可选择保留以便审计
- Skill fork、伙伴委派和定时任务共用同一个有界临时执行器,统一处理模型/预设组合、并发上限、超时、工具权限、运行记录与会话回收

心跳默认关闭,升级后不会突然主动发送消息。群聊策略和多渠道适配尚未开放。

## 安装

```bash
dsh plugin --profile web add @lemoncat7/dsh-partner
```

本地压缩包:

```bash
dsh plugin --profile web add ./lemoncat7-dsh-partner-<version>.tgz
```

重启对应 DSH profile 后,左侧「空间」上方会出现「伙伴」。打开伙伴面板,创建或选择伙伴,再进入「微信」扫码。

## 默认配置

```yaml
- insert:
    - id: partner
      name: '@lemoncat7/dsh-partner'
      config:
        statePath: !!js dshHomePath('partner/state.json')
        exposeWeb: true
        apiPrefix: /partner-local/v1
        defaultCwd: ''
        autoStartChannels: true
```

`defaultCwd` 为空时使用 DSH 进程当前工作目录,以兼容桌面端和 Docker。可按部署情况显式设为真实存在的绝对路径。

## 微信流程

1. 插件请求 `/ilink/bot/get_bot_qrcode?bot_type=3`。
2. 页面每两秒检查二维码状态,确认后凭据直接进入 Credential Store。
3. 后台通过 `/ilink/bot/getupdates` 长轮询接收消息。
4. 未授权联系人只会创建配对请求。
5. 批准后,为该联系人创建或恢复独立 DSH Agent。
6. 收到图片时,插件通过微信 CDN 下载并解密媒体,保存到伙伴工作目录,同时作为 DSH 原生图片附件交给 Agent;文档保存后以安全路径交给 Agent。
7. Agent 使用伙伴身份和所选 Preset 运行,最终文本通过 `/ilink/bot/sendmessage` 返回微信;回复中明确引用的工作目录文件会加密上传并作为微信附件发送。

渠道身份只决定消息归属,不授予任何工具权限。SSH、知识库和未来 Git 插件仍执行各自的挂载、授权和审批规则。

## 数据与安全

- 普通状态:`statePath` 指向的 JSON 文件。
- 伙伴记忆:`<defaultCwd>/partners/<伙伴 ID>/memory/`,按联系人隔离保存每日完整对话归档、人物画像、每日回顾、结构化长期记忆和有证据的记忆关系;画像按版本进入联系人会话,其他记忆按当前话题与一跳强关系召回,默认永久保留。
- 伙伴挂念:`<defaultCwd>/partners/<伙伴 ID>/concerns/concerns.sqlite`,保存挂念生命周期、变化观察、去重指纹、候选审计和打扰决策;候选审计保留 90 天,SQLite 使用 WAL、索引和串行事务写入。
- Skill 内容:`<defaultCwd>/partner-system/skills/<Skill ID>/SKILL.md`;普通状态文件只保存来源、版本、路径、校验和及伙伴启用关系,不复制 Skill 正文。
- 看板、调度、委派和临时运行索引:保存在 `statePath` 的原子状态文件中,并对任务数、活动历史、计划数和运行记录设置硬上限,防止长期使用后无限膨胀。
- 敏感凭据:DSH Credential Store,scope 为 `dsh-partner-weixin`。
- 管理 API:默认 `/partner-local/v1`,仅接受同源请求;写操作还要求 `X-DSH-Partner-Request: 1`。
- 微信机器人只能绑定一个伙伴;联系人上下文不会跨机器人、伙伴或其他联系人共享。
- 入站附件上限为 64 MB,保存在 `<伙伴 cwd>/inbound/`,目录权限为 `0700`、文件权限为 `0600`。
- 出站附件最多 8 个,只允许伙伴工作目录内的真实文件;会解析真实路径并拒绝符号链接越界、未知格式和超限文件。

## 开发

```bash
npm install
npm test
npm pack --dry-run
```

要求 Node.js `^22.19.0 || >=24.0.0`,与当前 DSH 运行时一致。

新模块的依赖方向、隐私边界和持久化约束见 [`docs/architecture.md`](docs/architecture.md)。

## Skill 市场索引

ClawHub、LoopHub、SkillHub 是内置公共来源,默认启用且不能删除。公共压缩包只会在内存中读取最浅层的 `SKILL.md`,不会把归档路径直接解压到磁盘;安装后按非可信 Skill 在隔离临时会话中运行。

自定义市场源返回 JSON 数组,或返回带 `skills` 数组的对象:

```json
{
  "skills": [
    {
      "id": "team-release-audit",
      "name": "团队发布审计",
      "description": "执行团队约定的发布前检查。",
      "version": "1.0.0",
      "tags": ["release", "audit"],
      "skillUrl": "./team-release-audit/SKILL.md",
      "checksum": "sha256:可选的64位十六进制摘要"
    }
  ]
}
```

`skillUrl` 可相对索引 URL。市场索引上限 1 MiB、单个 `SKILL.md` 上限 512 KiB;未标记为可信的市场即使声明 `context: inline`,安装后也会强制改为 `fork`。

市场页面的“代理设置”接受不含账号、密码和路径的 `http://host:port`。配置仅保存在当前客户端的伙伴状态中,同时作用于市场索引、Markdown Skill 和 ZIP 安装包下载;测试连接不会先写入配置。需要鉴权的代理应在本地网关侧处理,不要把凭据写进代理 URL。

Install

dsh plugin --profile web add github:lemoncat7/dsh-partner

Profile: web

  • This package builds from source on install. pnpm will ask you to allow its build script — that is permission to run the package’s code on your machine, outside the agent sandbox. Only allow sources you trust.
  • This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.
Source