通过 ai-ball 悬浮球给 agent 一张嘴:让球逐字打出你要说的话、按 mood 改变边缘光颜色、显示或收起独白面板、读回你打的字,以及检查接线和启动球。球是独立的 Python 3.10+ 悬浮层,需自行另外安装;插件只写它监听的那几个文件。
安装
# GitHub 源码(首次需按提示配置 allowBuilds 构建授权后重试)
dsh plugin --profile web add github:Hyfwdnmd666/dsh-ai-ball
装任何插件都等于在你的机器上跑第三方代码,权限和你本人一样大——能读你的文件、用你的凭据、访问网络,工具审批管不到它。GitHub 来源的插件还会在安装时执行构建脚本——pnpm 默认拦截,所以安装可能停在 ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED 或 ERR_PNPM_IGNORED_BUILDS;dsh 会打印出需要添加的确切键名,把它加进该 profile 的 pnpm-workspace.yaml 的 allowBuilds 下,重跑一次即可装上。放行构建本身就是一次信任判断:请只安装可信来源,并尽量锁定 commit(github:owner/repo#sha)。
README
给 agent 一张嘴:让它通过 ai-ball 那颗悬浮球说话、做表情、听你打字。
ai-ball 是一个 Windows 悬浮球 —— 它把自己追加到 monologue.log 的文字逐字"说"出来、
按 status.json 里的 mood 变色、把你打进输入框的话追加到 input.log。
球本身是哑的,它只认文件。
所以这个插件很薄:它不去操作球的窗口,也不 spawn Python,它只写球已经在看的那些文件。 这也是为什么任何进程都能当球的"大脑"。
你需要什么
- ai-ball 本体(一个 Python 3.10+ 的目录,里面有
ball.py) - 把它跑起来(双击
start.bat,或python ball.py)
插件本身不包含球,也不会替你安装它。
安装
dsh plugin --profile web add link:/path/to/dsh-ai-ball
或者从市场里装。
配置
挂在 profile 的 cordis.patch.yml 里:
- id: dsh-ai-ball
name: dsh-ai-ball
config:
ballDir: C:\tools\ai-ball # 必填:放着 ball.py 的那个目录
startCommand: C:\tools\ai-ball\start.bat # 可选:ball_launch 用
cps: 50 # 可选:球的打字速度,用来估算 wait
heartbeatMs: 3000 # 可选:心跳间隔,必须小于球那边的 stale_s
followInput: true # 可选:你在球里打的字直接变成 agent 的消息
followMs: 700 # 可选:input.log 的轮询间隔
files: # 可选:和球自己的 config.json 对齐
monologue: monologue.log
input: input.log
status: status.json
也可以走环境变量 AIBALL_DIR / AIBALL_START。
ballDir 故意没有默认值。 猜别人把球解压到哪儿了,正是插件往错目录里写文件的方式 ——
所以它宁可报一个说清楚哪里不对的错。
听,才是"交互"
只写不读的球是个牵线木偶:agent 说话、你看着,然后没有下文。
而"我轮询一下看看你说没说话"也不算交互 —— agent 只有碰巧想起来调 ball_listen 才听得到你。
你没被听见的时候,你打进去的字就进了 input.log 这个黑洞。
所以默认开着 followInput:插件自己盯着 input.log,把每一行当成一条真正的用户消息
交给 agent(agent.followup(),它的契约原话是"排一个普通的后续回合并唤醒驱动器 ——
这条目自成其回合的唯一一条普通消息")。你在球里打字,等于你发了条消息。
三个细节:
- agent 是"学"来的。 插件层的上下文里没有 agent;
exec.agent只在工具调用时才出现。 所以插件在任何一个球工具第一次被调用时才知道该把话送给谁。在那之前的输入不会丢, 会等它认领。 - 投递失败会重试,不会吃掉你的话。 送不出去就把游标退回去,下一拍再送。
- 监听器和
ball_listen共用同一个读取游标。 两个游标会让同一句话被消费两次 (一次当消息、一次当工具结果)。所以开着followInput时ball_listen通常返回空 —— 那是成功,不是沉默,话已经以消息的形式到了。
⚠️
brain.py也读input.log。 两个读者 = 两个回复。想要球只当 DSH 的嘴, 就别跑brain.py(插件从加载起就接管心跳,球不会因此变灰)。想让它自己聊天, 就把followInput关掉。
六个工具
| 工具 | 作用 |
|---|---|
ball_say |
说话。追加到 monologue.log,球逐字念出来。clear=true 先清屏 |
ball_mood |
改球的脸:idle / thinking / nervous / smug / broken |
ball_panel |
显示 / 收起独白面板 |
ball_listen |
手动读 input.log。开着 followInput 时通常返回空(话已经作为消息送来了) |
ball_status |
报告接线情况:文件大小、最后说了什么、心跳多旧、有没有在心跳 |
ball_launch |
按配置的 startCommand 把球拉起来 |
两个会让你浪费一下午的坑
1. 心跳不是可选项 —— 插件会自己接管它
球把过期的心跳读成"大脑死了"并渲染成灰色,而那会盖掉 mood。
所以 ball_mood 不只是写一次 mood:它同时启动一个心跳,在插件加载期间一直刷。
这有两个后果:
- 第一次调
ball_mood之后,球就再也不会因为你没在做事而变灰了(这是对的: 插件活着 = harness 活着) - 插件被卸载/重载时心跳会停(挂在 cordis 的 dispose 上,不会泄漏定时器)
一个只写一次 mood、不管心跳的实现,看起来像成功了,然后 20 秒后静默失效。
2. 如果 brain.py 在跑,它每三秒会把你的 mood 踩回 idle
brain.py 每隔几秒重写整个 status.json(心跳是它的)。
两个写者抢同一个文件,后写的赢。
想自己拥有球的脸,在 brain.json 里设:
{ "write_mood": false }
那样它只刷心跳,文件里现有的 mood 原样保留 —— 两个写者就能共存了。
3. ball_panel 为什么带一个序号
status.json 里的 panel 不是"当前该是什么状态",是一条命令,panel_seq 是它的序号。
球只在序号变化时动一次。
不这么做的话,插件每几秒重写一次文件,就等于和你抢面板开关: 你收起面板,它下一拍又打开。
带序号之后:
- 你手动开关面板一直算数(插件没改变主意,序号没变)
- 插件改变主意时把序号加一,球再执行一次
- 每次调
ball_panel都是新请求(序号加一),所以"你关掉了,我要它再显示" 是有效的,不会变成空操作
(球那边没有 panel_seq 的 panel 一律不执行 —— 没有序号就无法区分"你刚关掉"和
"它一直这么说",照做就是抢开关。)
ball_listen 为什么不会切坏中文
读游标按字节记,而且只推进到最后一个换行。
写入方可能被撞见写到一半:游标如果按字符算、或者用替换字符解码尾部, 那半个 UTF-8 序列会变成 U+FFFD 并且永久留在游标后面 —— 内容就再也读不出来了。 停在最后一个换行,残缺的尾巴下次会重新读一遍,这是简单正确的做法。
(同一个 bug、同一个修法,ai-ball 的 Python 侧也有一份。)
它不做的事
- 不判断球在不在跑。
ball_status报的是文件状态,不是窗口状态 —— 严格来说,一个没在跑的球 和一个在跑但没人写的球,看起来是一样的。 - 不会只启动一颗球。
ball_launch是只写的,重复调用会得到两颗球。 - 不渲染 Markdown。 球是嘴,不是文档。
**强调**会原样显示出来。 - 不会替你记住要开面板。
ball_say不会自动显示面板 —— 面板收着的时候它照样写成功, 只是没人看得见。要保证被看到,先ball_panel(true)。
许可
链接
同类插件
PC2005-cloud/dsh-pet#dsh-pet★ 3496
DSH Web UI 桌面宠物:25 个透明动画、屏幕漫游、点击反应与拖拽,附可复现的素材生成链。
Nagi-ovo/dsh-ads★ 682
2005 年中文站点风格的整活广告插件:侧栏广告/信息流/角落弹窗 + 假关闭叉,素材全虚构。
vlln/whale-girl★ 375
桌面宠物(QQ 宠物形态):右下角悬浮、可拖拽/投喂/玩耍。
yyh-001/dsh-meme★ 295
聊天表情包:纯文本斗图、情绪主动发图、像 QQ/微信 一样发图、AI 自动学图、自定义表情包。
a86582751/dsh-nexttavern★ 191
NextTavern 是面向 DeepSeek Harness 0.1.7-rc.2 Web 的长篇角色扮演插件,支持角色卡导入与创作、世界线、世界书、分层长期记忆、关键词/语义/混合检索、角色 Agent,以及角色卡或小说导出;支持 SillyTavern 角色卡导入,v0.2.9 修复分发与安装问题。
Sutera-Diffusus/dsh-whale-musume★ 156
鲸鱼娘桌宠:45 项成就、每日任务与周签到、三个小游戏、92 张立绘、620 条台词、成长日记、天气与节日反应、按工具类型切换工作姿态、跨端存档导出/导入(JSON 文件或迁移码)、无障碍模式,以及可选的 MiMo TTS 台词播报。数据只存放在宿主 localStorage,无遥测;已在 DSH 桌面端 0.2.0-rc.2 验收,兼容 0.2.1-rc.1/rc.2 与旧版 0.1.x Web。
社区评论
评论公开保存在 GitHub Discussions。加载评论会连接 GitHub 和 Giscus;发表内容需要 GitHub 账号。