deepseek-harness
deepseek-ai
DeepSeek Harness: Everything is a Plugin.
PROJECT TOPICS
PROJECT README
输入框左侧一个开关:打开后,聊天消息不再直接发送,而是进入任务队列;在谷段(DeepSeek API 低费率时段)自动按序派发执行。 A composer switch: when on, chat input goes into a task queue instead of being sent directly; tasks auto-dispatch in order during valley windows (DeepSeek off-peak pricing).
DeepSeek Harness 双半区插件(Host + Client):Host 拦截输入入队、按时段调度、精确判定任务完成;Client 提供开关与队列面板(状态行、时段配置、任务列表)。 A DeepSeek Harness plugin (Host + Client halves): the Host intercepts input into a queue, schedules by peak/valley windows and judges completion precisely; the Client provides the switch and the queue panel (status, window config, task list).
距下一峰段超过 x 分钟 才自动执行(余量保护)。已完成后移除 / 被打断(取消、输出截断)/ 失败 / 阻塞;多信号冗余(turn/end + 空闲 + watchdog + 客户端轮询),任一事件漏发都不会卡住队列。<!-- dsh-todo:start --> 决策清单标记时,任务不判完成,转为「待确认」并暂停队列,等待用户决策(配套安装 dsh-todo-enhancer 提供清单面板);「继续任务」不会自动重跑待确认任务。__TASK_DONE__;未检测到则视为未完成。~/.dsh/peak-valley-queue/($DSH_HOME 优先),绝不写入用户工作区文件(Web 工作区根目录常是桌面);会话归属锁定 owner.json。支持从 GitHub 直接安装(公开仓库,需能访问 github.com;公开克隆无需登录,若本机 git 配置要求凭据则按 Git Credential Manager 授权即可):
dsh plugin --profile web add github:EmptyCollin/dsh-peak-valley-queue github:EmptyCollin/dsh-todo-enhancer
必须一条命令同时安装两个插件:决策清单面板由独立的 dsh-todo-enhancer 提供,而 dsh plugin 只把直接依赖中声明 dsh.bundle 的包加入 bundle 层——只装 pvq 时 todo-enhancer 只会作为传递依赖被拉取、不会挂载,面板不会出现。
web 换成对应 profile 名。dsh plugin --profile web add D:\dsh-plugin\dsh-peak-valley-queue D:\dsh-plugin\dsh-todo-enhancer
lib/index.js(注册 /pvq/* HTTP 路由);Client 半区:lib/client.bundle.js(模块加载器 bundle,产物已提交、无 prepare 脚本,安装无需构建)。cordis_define / cordis_run)加载 lib/dynamic-host-body.txt / lib/dynamic-client-body.txt,无需重启;注意两种方式不要同时启用(会重复拦截)。面板「时段与配置」区:
| 配置 | 说明 |
|---|---|
| 峰段时段列表 | 增删时段(支持重叠);+ 时段 添加,行尾 ✕ 删除;清空 = 全天谷段 |
| 周末也算峰段 | 关闭(默认):工作日才按时段计算峰谷 |
| 本机时区 | 默认按本机时间计算;可改为固定 UTC 偏移 |
| 执行余量 x 分钟 | 距下一峰段超过 x 分钟才自动执行,防止任务刚派发就撞上峰段 |
| 严格校验 | 开启后要求回复末尾输出 __TASK_DONE__ 才算完成 |
| 暂停通知 / 浏览器通知 | 暂停时浏览器系统通知(授权一次),每 30 分钟重复 |
| 自定义命令 | 暂停时在沙箱内执行的可选命令(如弹窗提醒),失败只记日志 |
时段改动若导致「峰段 → 谷段」翻转且队列非空,会弹窗确认(避免误触发批量执行)。
以轮次生命周期(turn/end reason:completed | aborted | error | max-tokens | blocked + agent/error)精确区分;完成判定为冗余多信号(turn/end 精确原因 + agent/status→idle + turn-stopping + 10s watchdog + 客户端 10s 轮询兜底),任一事件漏发都不会让任务卡在「执行中」。
| 状态 | 含义 | 处理 |
|---|---|---|
| 进行中 | 已派发,turn 未结束 | 队列顶部显示「执行中…」,不派发下一个 |
| 已完成 | 有回复 / completed |
从队列移除(结果在对话里) |
| 打断 | aborted / max-tokens / blocked |
插回队列标记「打断」并暂停 |
| 失败 | error 且无任何回复 |
插回队列标记「失败」并暂停 |
agent/inbox/inserted 拦截用户输入(inbox.remove + 入队),用 agent.followup 以 rpcId: pvq:<taskId> 派发;按消息 id 去重,授权恢复 / 循环重投递的同一条消息只消费、不重复入队。完成信号来自 session/event(turn/end、assistant/message)、agent/status、agent/turn-stopping。conversation.input.left(开关)与队列面板(有 sidebar tab 能力则注册页签,否则 shell.overlay 自建浮动侧边板);1s 轮询 get-state 刷新状态;RPC 走 POST /pvq/<method>(动态形式走 host.call)。cordis.patch.yml # dsh.bundle 补丁:把本包插入 profile 的 bundle 层
lib/
index.js # Host 静态入口(webServer 路由 /pvq/*,导出 { name, inject, apply })
client.js # Client 静态入口(import React + fetch RPC)
client.bundle.js # Client bundle(__ModuleLoader__ 自注册,由 client.js 生成,产物已提交)
host-core.js # Host 核心(纯 JS,动态/静态共用)
client-core.js # Client 核心(纯 JS,动态/静态共用)
dynamic-host.js / dynamic-host-body.txt # 动态运行器 Host 函数体(cordis_define 用)
dynamic-client.js / dynamic-client-body.txt # 动态运行器 Client 函数体
scripts/
build-dynamic.mjs # 由 host-core/client-core 重新生成动态体
build-bundle.mjs # 由 client-core 生成 lib/client.bundle.js
compact-dynamic.mjs # 生成去注释 compact 体(cordis_define 传输用)
smoke-host.mjs # Host 核心回归(mock ctx/agents,112 项)
smoke-bundle.mjs # Client bundle 冒烟(槽位注册 / 侧边板迁移)
npm run check # 语法检查(全部入口 node --check)
npm run build # 重新生成动态体 + client bundle + 冒烟
npm run smoke # 仅跑冒烟(smoke-bundle + smoke-host)
agent/inbox/spliced 事件重水合遗留的待处理消息——重启前仍在 inbox 里的派发消息(rpcId: pvq:...)会在重启后被 agent 循环当作新输入处理,即使开关是关闭的也会自动发出。现在 set-session / reload-state / 10s 调度器都会清扫这类过期的 pvq- 消息(保留当前执行中任务的那一条);agent/inbox/inserted 拦截也改为:当前执行中消息放行、过期 pvq- 消息移除(开关关闭时同样生效)。loadState 会把「执行中 / 待确认」任务原样恢复,导致旧的待确认任务劫持重启后的第一条输入(当成回答),或旧任务被悄悄重跑。现在重启时执行中 / 待确认 → 打断(「服务重启,任务未完成」)并清除过期的 task-confirming 暂停,只有用户显式「继续任务 / 编辑 / 送出」才会重跑;排队中的 pending 任务保留,但只在用户重新开启开关(且处于谷段)时才派发。reload-state 不再把开关重置为关闭;拦截时以 inbox.remove 的返回值判重,即使静态/动态两种挂载方式被同时启用,每条输入也只入队一次(不再重复添加同一个任务)。MIT
CLASSIFICATION EVIDENCE
系统优先读取 GitHub Topics,再与站内分类词典和词根规则比对。当前命中: 无有效分类标签。