前言¶
在 DeepSeek Harness(DSH)里做长期运行的部署时,常见需求是「到点自动开一轮 Agent」:日报、周期巡检、一次性提醒、进程启动后的延迟任务等。若完全依赖外部 cron 或系统 systemd,往往要另起进程、另配环境,和 DSH 的 profile、会话、沙箱策略脱节。
dsh-timer 由社区维护者 xuan25 发布,分类为工作流插件;定位是「DSH 里的 systemd.timer 等价物」——任务定义落在 job 目录,触发后在 同一 dsh 进程内 为每次执行创建新的 prompted session。下面介绍它做什么、如何安装,以及 job 文件怎么写。
这是什么¶
dsh-timer(GitHub:xuan25/dsh-timer)是挂到某个 dsh profile 上的 进程内调度插件(package 版本 0.1.0,MIT 许可证)。它不替代系统 cron,而是在部署已运行的 dsh 里维护调度循环(README 与 package 描述均提到约 30 秒 tick),到期后为该 job 启动一次全新的 Agent 会话。
每次 run 可配置工作目录、preset、model、文件策略、reasoning effort 等;job 级状态文件记录下次触发时间与最近 50 条运行记录。行为上对齐 systemd.timer 的常见语义:停机后的 persistent 补跑、重叠策略(skip / stop / allow)、单次运行时长上限、时区与时钟回拨处理等。
核心功能¶
任务存放与热更新¶
- Job 以 一 job 一文件 形式放在 job 目录:
<id>.json;enable为false时仍保留在同一文件,只是不参与调度,仍可手动触发或改回启用。 - 运行时状态写在
state/<jobId>.json,仅插件写入。 - 目录变更带 500 ms debounce 的 live rescan;也可通过
timer工具的reload强制重扫(README)。 - 除 job 文件与 state 外,其它文件名或子目录会被忽略。
三种触发方式¶
至少启用以下之一(字段可为 null 表示不用该路触发):
onCalendar:5/6 段 cron,或完整 ISO 8601 一次性时间点。onActiveSec:自 最近一次 run 开始时刻 起算的间隔(如30min)。onStartupSec:自 进程启动 起算、每个进程生命周期内触发一次的一次性延迟。
日历类条件可设 IANA timeZone;persistent、deferReactivation、runtimeMaxSec、overlap 等字段语义见官方 schema 与 README 表格。
每次 run 是什么¶
触发后不是内联函数,而是 新建一条 prompted session,run.prompt 为必填指令;框架会自动追加结果摘要类说明。run.cwd 决定会话工作目录,也是插件权限模型下的控制范围——未在 spec 中确定 run.cwd 时,管理会走审批通道,运行会 create_failed,需在 job 文件中显式设置。
会话归档¶
插件按分钟扫描:已结束且超过 job 的 run.sessionRetention 的 run session 会从框架 session store 归档到 $DSH_HOME/dsh-timer/ 下,避免会话堆积。
安装与启用¶
安装命令来自仓库 README(需替换 <name> 为实际 profile 名):
dsh plugin --profile <name> add dsh-timer
README 说明:无需额外插件配置 即可注册;job 默认从下文目录读取。可选配置项 jobsDir 用于指定 job 目录。
job 目录解析顺序¶
- 显式指定:
jobsDir插件配置,或环境变量DSH_TIMER_JOBS_DIR(指定但不可用则插件启动失败)。 - 未显式指定时默认
<profileDir>/timers(profileDir为安装该插件的 profile 目录)。 - 无法唯一确定 profile 时,可在 profile 的
cordis.patch.yml用 loader 表达式固定路径,例如:
# <profileDir>/cordis.patch.yml
- id: dsh-timer
config:
jobsDir: !!js dshHomePath('profiles', '<name>', 'timers')
job id 须匹配 ^[a-z0-9][a-z0-9-]{0,63}$(小写字母或数字开头)。
典型用法¶
手写 job 文件¶
在 job 目录创建 daily-check.json(文件名即 job id)。下列示例来自仓库 schemas/job.schema.json 的 examples,仅作字段组合参考;实际路径与 prompt 请按你的部署修改,并 为 run 设置明确的 run.cwd(若创建时未继承会话工作区)。
工作日 9 点(上海时区)巡检:
{
"onCalendar": ["0 9 * * 1-5"],
"timeZone": "Asia/Shanghai",
"deferReactivation": true,
"overlap": "skip",
"run": {
"prompt": "Inspect new reports under /workspace/reports in the last 24h and summarize them",
"cwd": "/path/to/your/workspace"
}
}
每 30 分钟心跳(上次激活起算):
{
"onActiveSec": "30min",
"persistent": true,
"run": {
"prompt": "Output a one-sentence heartbeat with the current time",
"cwd": "/path/to/your/workspace"
}
}
一次性 ISO 时刻任务:
{
"onCalendar": ["2026-10-01T00:00:00"],
"timeZone": "Asia/Shanghai",
"run": {
"prompt": "National Day reminder task",
"policy": "read-only",
"cwd": "/path/to/your/workspace"
}
}
保存后,插件会在数秒内 rescans;也可在会话里用 timer 工具(README 称九动词 CLI)增删改查 job,与手写文件二选一或混用。
完整字段说明与排错见仓库内 schemas/job.schema.json 与 skill/dsh-timer/SKILL.md。
适用场景与注意¶
适合谁
- 已在 DSH 上跑长期 profile,希望定时任务与 同一套 preset、model、沙箱策略 一致。
- 需要 systemd.timer 风格语义(persistent、overlap、runtime 上限),但不想把 Agent 逻辑拆到系统 cron 脚本里。
- 接受「一次触发 = 一次完整 Agent 会话」,适合报告、巡检、提醒类工作流。
务必知晓
- 插件以 当前 dsh 进程的身份与权限 运行;job 里的 prompt 与
run.policy会在到期时自动执行,安装前请阅读源码与 MIT 许可证,仅添加你理解的 job。 - 社区目录 SkillHub 插件页 与 GitHub 仓库独立于 DeepSeek / 幻方,并非官方应用商店;星标与版本以页面与仓库为准(截至资料抓取时 GitHub 星标为 0,package 版本 0.1.0)。
- 依赖 Cordis 与多项
@deepseek-ai/dsh-*peer 包,需与宿主 DSH 版本兼容(见仓库package.json)。
结尾¶
dsh-timer 把「何时跑」收敛到 profile 下的 job 目录,把「怎么跑」收敛到每次新建的 Agent 会话,适合在 DSH 生态里做进程内工作流调度。进一步细节与示例:
- 目录页:https://www.skillhub.cn/plugins/xuan25/dsh-timer
- 源码与 README:https://github.com/xuan25/dsh-timer