dsh-companion
想装?把仓库地址丢给你的 Agent 就行。
帮我装这个插件:https://github.com/d1s3s/dsh-companion 按仓库里的 INSTALL.md 走,装完跑一遍自检, 把结果和「需要我决定的选项」一起告诉我。它能自己 clone、自检、选接法、跑测试,然后把要你拍板的三件事(人格 / 形象 / token 价目)列出来。 不想用 Agent 装的话,看
INSTALL.md手动走一遍,同样四步。
陪伴型 DSH 插件。装上之后你的 Agent 就多四件事:记得你、看得见屏幕、能看摄像头、能替你说话——以及一件更重要的事:这些能力每一项都由你单独发钥匙,随时能收回。
不是又一个桌宠。桌宠只负责好看,这个负责记得你昨天否决了什么。
为什么会做这个东西。 跟 Agent 聊得越久越会撞上两堵墙:一是它记不住——今天讲清楚的偏好,明天开个新会话就清零,聊了一周还是每次从头介绍自己;二是它看不见——你得先截图发过去,它才知道你在说什么。这两件事都不是换个更聪明的模型能解决的,是记忆和感知放错了位置。所以这里把记忆挪到模型外面(磁盘上人可读的 Markdown,带权重和衰减),把眼睛放回你自己的机器上(屏幕、摄像头、她自己的浏览器),然后给每一样都单独配一把钥匙——发出去能收回。
核心不认识 DSH。 它只依赖五个宿主方法,所以同一个内核能跑在 DSH 插件里,也能跑成 MCP server——Claude Desktop、Cursor、Cline、Zed 接上就是同一套记忆、同一套权限、同一套账本。换模型、换客户端,记忆不用重来一遍。怎么换见 ADAPTERS.md。
适合谁:每天用 Agent 干活、并且开始烦「每次都要重新交代一遍背景」的人;希望它顺手能看一眼屏幕、摄像头、网页的人。
不适合谁:只想要个桌面摆件的人(那用桌宠更合适,这个更重);不接受 AI 具备「看屏幕 / 开摄像头」这类能力的人——这里每一项都要你单独点头、随时能收回,能力本身确实存在。
能力
| 能做什么 | 工具 | 出厂权限 |
|---|---|---|
| 截一张屏 | companion_see_screen |
每次询问 |
| 连看一段屏幕(盯进度、看变化) | companion_watch_screen |
禁止 |
| 看一段本地视频(抽帧,刷视频/看录屏) | companion_watch_video |
每次询问 |
| 不用截图知道你在看什么(前台窗口 + 平台识别,约 0 token) | companion_now_viewing |
本会话允许 |
| 自己开网页刷(B站/抖音/小红书/快手,读标题作者热评) | companion_open_site |
每次询问 |
| 自己往下刷(滚动、切下一条,不点按钮) | companion_browse_next |
每次询问 |
| 在 App 里刷(抖音客户端,只发滚轮绝不点击) | companion_app_scroll |
禁止 |
| 按时段自己刷(受四道闸约束) | companion_browse_auto |
禁止 |
| 按主题收集视频(给个话题拿回一串结果) | companion_collect |
每次询问 |
| 把看到的视频记下来(进长期记忆,以后能主动提) | companion_keep_video |
允许 |
| 评论(默认只准备不发送,核对后才发) | companion_comment |
发送禁止 |
| 改刷视频的设置(时段/时长/评论配额) | companion_browse_settings |
允许 |
| 开一次摄像头 | companion_see_camera |
每次询问 |
| 枚举摄像头 | companion_list_cameras |
允许 |
| 记住一条结论 | companion_remember |
每次询问 |
| 按关键词回忆 | companion_recall |
本会话允许 |
| 取否决 / 认知修订 | companion_valuable |
本会话允许 |
| 起草消息 | companion_draft_message |
允许 |
| 发出去 | companion_send_message |
每次询问 |
| 看 token 花了多少 | companion_cost |
允许 |
| 调权限 | companion_permission |
只能自己收权 |
| 换形象 / 列出所有形象(立刻生效,不用重启) | companion_character |
允许 |
| 用外部模型想一件事(OpenAI / Claude / 千问 / DeepSeek) | companion_model |
每次询问 |
配模型的密钥(存本机 keys.json,权限 600) |
companion_model_key |
每次询问 |
「连看屏幕」和「截一张屏」是两项独立权限,不是同一个开关。允许你截一张图,不等于允许你一直看着——这个区别在别的产品里经常被抹掉,这里不抹。
形象:六种可选,随时换

companion_character action=list # 看全部
companion_character action=use pack=theme-gpt # 换,立刻生效
| 内置配色皮肤(零体积,随插件走) | 角色包(真美术) |
|---|---|
theme-default 深海蓝 |
bigfish-classic 大肥鱼·内置(60 个动作) |
theme-gpt 青绿(像 OpenAI 的配色) |
bigfish-adult 大肥鱼·成年版(8 组动作) |
theme-claude 陶土橙(像 Claude 的配色) |
你自己的 .dshpet(放进 ~/.dsh-companion/packs/) |
theme-qwen 星紫(像通义千问的配色) |
为什么是配色不是官方形象:OpenAI / Anthropic / 阿里都是有法务的商业主体,复制它们的官方形象是商标问题——这和用社区角色不是一回事。这里借的是气质(青绿偏工程、陶土偏人文、星紫偏科技),不复制任何 logo。你自己的素材放进 packs/ 就行,那些包优先级更高。
想看全部形象长什么样:npm run gallery 生成 preview/gallery.html,图集原图、68 个动作各自的第一帧、四套配色并排一页,点图可放大。
接自己的模型
有些事得她自己会想:刷完一堆视频判断哪条值得留、写评论草稿、看一帧猜你在干嘛。以前靠关键词硬编码,一看就假。
# 配一个(三家都行,另外还支持 DeepSeek)
companion_model_key provider=qwen key=sk-xxxx
# 或走环境变量:DASHSCOPE_API_KEY / OPENAI_API_KEY / ANTHROPIC_API_KEY
companion_model action=status # 看哪些配好了
companion_model input="这条视频在讲什么:…" provider=qwen
| provider | 默认模型 | 端点 | 国内直连 |
|---|---|---|---|
qwen |
qwen-plus |
DashScope 兼容模式 | ✅ 推荐 |
deepseek |
deepseek-chat |
api.deepseek.com | ✅ |
openai |
gpt-4o-mini |
api.openai.com | ⚠ 需代理(可设 OPENAI_BASE_URL) |
anthropic |
claude-3-5-haiku-latest |
api.anthropic.com | ⚠ 大陆 IP 返回 403,需代理 |
实测:三家协议都验证过(假 key 打真端点,千问回 401、Anthropic 回 403 而不是 400,说明请求结构全对)。模型花的钱按上游回报的实际 token 记账,不用估算糊弄。
密钥只存 ~/.dsh-companion/keys.json(权限 600),不写进代码、不进日志、不回显全文。
安装
让 Agent 自己装:把仓库地址丢给它,让它读 INSTALL.md——那份是写给机器执行的分步清单(含验证命令、必须问你的选项、故障对照、红线)。下面是人手动走的版本。
要求:Node 20 以上。零外部依赖,不用 npm install。
下面几项都是可选的,缺了只掉对应的能力,不影响记忆和聊天:
| 缺什么 | 会掉哪些能力 | 怎么补 |
|---|---|---|
| ffmpeg | 截屏、摄像头、看视频、连看屏幕 | winget install Gyan.FFmpeg / brew install ffmpeg / 发行版包管理器 |
| Edge 或 Chrome | 自己开网页刷、收集资讯 | 装一个即可 |
| PowerShell | 知道你在刷什么(读前台窗口) | Windows 自带,一般不会缺 |
git clone <仓库地址> dsh-companion
cd dsh-companion
# 装之前先自检,它会告诉你这台机器上缺什么、缺了影响哪几个工具
node test/doctor.mjs
# 桌面端
dsh plugin --profile desktop add .
# Web 端(两套 profile 是独立的,要分别装)
dsh plugin --profile web add .
装完在「插件」页启用,然后到设置里填配置。
不用 DSH 也能用
同一个内核可以跑成 MCP server,给任何支持 MCP 的客户端接:
node adapters/mcp.mjs --list # 看有哪些工具
node adapters/mcp.mjs # stdio,给客户端连
{
"mcpServers": {
"companion": {
"command": "node",
"args": ["C:/path/to/dsh-companion/adapters/mcp.mjs"]
}
}
}
记忆、权限、账本都在 ~/.dsh-companion/,和 DSH 插件共用——在 DSH 里聊过的,换到别的客户端接上照样记得。
⚠ MCP 没有审批弹窗,所以「询问」级别的能力在那里一律拒绝(fail-closed)。想放开就把那项权限改成 session 或 always,见 ADAPTERS.md。
先跑这四条
node test/doctor.mjs # 环境:能不能干活(ffmpeg / 浏览器 / PowerShell / 角色包 / 目录可写)
node test/smoke.mjs # 功能:假 ctx 跑通全部工具、权限、记账
node test/policy.test.mjs # 策略:刷视频的四道闸、评论独立闸、跨午夜时段
node test/mcp.test.mjs # 协议:MCP 握手 / 工具列表 / fail-closed / stdout 纯净度
doctor 只判环境,不写任何文件;它按「一项挂了不影响其他项」的方式全查一遍,
让你一次看到所有缺口,而不是修一个再发现一个。
配置
| 键 | 默认 | 说明 |
|---|---|---|
memoryDir |
~/.dsh-companion/memory |
接到已有记忆库就填绝对路径 |
profile |
tender |
tender / sharp / pro / casual 四种人格 |
characterPack |
packs/bigfish-classic |
角色包目录(dsh-pet v1 或简单图包),见 CHARACTER.md |
characterSize |
170 |
桌宠像素宽 |
pricePerMTokens |
2 |
元 / 百万 token,按你的价目填 |
tokensPerBowl |
1000 |
一碗白饭换多少 token(纯玩梗) |
hud |
always |
always 常驻显示 / hover 只悬停显示 |
webhook |
空 | 配了才允许直接外发消息 |
token 显示在角色头上
角色头顶浮一个小药丸,三件事一起看:
3.4k token · ¥0.0068 · 🍚 3 碗
- 双击角色 → 在「常驻显示 / 只悬停显示」之间切换,同时她会把今天吃了多少说出来(「今天吃了 3 碗白饭…我是鲸鱼,能消化」)。
- 价格和白饭换算都在配置里。白饭是玩梗,但把一个抽象数字变成看得懂的量这件事本身不是梗。
为什么要显示:陪伴助手最贵的不是聊天,是看图。一张 1280×720 的截图约 1200 token,连看 60 帧就是 7 万——比一整天打字还贵。数字不摆在脸上,用户永远不知道自己刚才那一眼花了多少钱。
配套的三道闸:
- 单次 ≥4000 token 打 ⚠️
- 单次 >60000 token 直接拒,并给出更省的参数(降帧率、缩宽度、裁区域)
- 每天 >200 万 token 直接拒
记忆
插件不调用任何 Python 脚本,直接用正则读同一批 Markdown。这是刻意的:记忆库的价值全在「任何东西都能读懂它」。哪天脚本烂了、语言换代了,插件照样能读。
node -e "const {Memory}=require('./src/memory.js')"
支持的目录结构(和 mem.py 那套完全兼容,两边可互写):
memory/
index.md 年代目录:哪一年、多少件、几个主题
index/<年>.md 年索引:一句话 → D编号
raw/<日期>.md 原文:只追加,永不改写
counter.json 下一个编号
形象
角色包直接吃社区的 dsh-pet v1 格式,所以别人做好的 .dshpet 丢进来就能用,不用改代码。
| 包 | 是什么 | 动作 | 体积 |
|---|---|---|---|
| 内置鲸鱼(SVG) | 手绘,兜底,随包分发 | CSS 动作 ×10 | 几 KB |
packs/bigfish-classic |
大肥鱼·内置 | 60 个动作 / 6 张图集 | 4 MB |
packs/bigfish-adult |
大肥鱼·成年版 | 8 组动作 / 4 张图集 | 8.8 MB |
动作不是「一个循环 GIF」:同一状态有多段可选,按「最久没播过」轮换并尊重冷却,所以看着像有人在,不像在放动画。细节和授权边界见 CHARACTER.md。
node client/build-preview.mjs # 单文件预览:活角色 + 全部动作,点一个就播
自检
node test/doctor.mjs # 环境:ffmpeg / 浏览器 / PowerShell / 角色包 / 目录可写
node test/smoke.mjs # 假 ctx 跑通全部工具、权限、记账、角色包
node client/build-preview.mjs && 打开 client/preview.html # 看形象、全部动作、十种状态
node tools/build-bigfish-pack.mjs ./package # 从上游 dsh-bigfish 重转角色包
smoke.mjs 会验证:工具注册、权限拦截四条、fail-closed、配额封顶、超预算拒绝、记忆读写互通、审计落盘。真机上唯一还需要验的是钩子名——不同 DSH 版本的 agent/session-start 可能叫别的,代码里三个名字都试了,都不中时用 companion_brief 手动兜底。
已知边界
- 摄像头要能出图,得先看系统隐私设置。Electron 外壳本身把
media权限封了(issue #655),所以这里绕过浏览器、直接从宿主调 ffmpeg(Windows 走 dshow,mac 走 avfoundation,Linux 走 v4l2)。没装 ffmpeg 时相关工具会直接说「去装 ffmpeg」,而不是报一句看不懂的spawn ENOENT。 - 发消息默认不直发。剪贴板 → 本机客户端 → webhook,三级降级。前两级把「最后一下」留给你按,这不是保守,是这类动作发出去就收不回。
- 钩子注入是 best-effort。DSH 没公开完整的钩子契约,所以这里做的是「试三个名字 + 失败静默降级」,不会因为钩子对不上而把宿主弄崩。
- 评论默认不发。五道关里第四关是「把字打进输入框、逐字读回核对」,第五关是「确认按钮上写的是发送」。默认停在第四关,等你点头。
- App 里只滚不点。抖音客户端是自绘窗口,读不到内容。看不见还发点击等于闭眼乱按,所以只发滚轮,且每次滚之前都会确认前台真是那个 App。
许可
代码 MIT(见 LICENSE)。
角色美术不属于 MIT。packs/bigfish-classic 是从上游 dsh-bigfish 转的第三方美术,版权归原作者 gosomea;packs/bigfish-adult 是 image_gen 生成的图。各包来源与授权写在各目录的 NOTICE.txt 里。
个人使用无碍。要在你自己的产品里分发,请换成你有权分发的素材——内置那只手绘鲸鱼(svg 模式)就是为此留的后路:把 characterPack 留空,插件照样有形象。
No comments yet. Be the first to write one.