跳到正文
dsh-market 浏览插件 GitHub EN

GooDAnDReaDY/dsh-cron

为 DeepSeek Harness 提供定时任务、后台自动化与 Agent 执行。

Star 数 ★ 5 分类 工作流与自动化 收录于 2026-09-13 npm @goodandready/dsh-cron

安装

在 DeepSeek Harness 里通过 dsh-market 安装

dsh plugin --profile web add dshmarket

或使用命令行

dsh plugin --profile web add @goodandready/dsh-cron

装任何插件都等于在你的机器上跑第三方代码,权限和你本人一样大——能读你的文件、用你的凭据、访问网络。请先审阅源码,并尽量锁定 commit(github:owner/repo#sha)。

README


⚡ 概述与问题

自主 AI 智能体经常需要执行周期性任务:生成每日晨报、整理缺陷跟踪、检查 API 健康状态、同步数据库或定期执行 Git 清理。如果 Harness 内没有专用调度器,用户只能依赖外部 crontab 封装、复杂的 webhook 方案或手动干预。

@goodandready/dsh-cron 是 DeepSeek Harness 的原生全栈调度与后台自动化插件。它将标准 cron 表达式、自然语言间隔语法与自主智能体执行连接起来:

  1. 完善的可视化任务管理器 —— 侧边栏按钮带可折叠的活跃任务列表(下次运行时间或实时状态,行数有上限且状态可记忆),以及功能齐全的面板:按类型、模型、渠道筛选,暂停、立即运行、复制、导出/导入与创建任务。
  2. 交互式“由 DSH 创建”流程 —— 与智能体对话,把高层需求转化为规范的定时任务。
  3. 自主工具调用 —— 原生 cron_* 工具让智能体在会话中自行安排后续执行。
  4. 健壮的调度器与原子存储 —— 基于 croner:间隔别名、一次性延时任务、原子写入、运行历史与成本追踪。
  5. 六种执行运行时 —— shell、Node.js、Python、HTTP/webhook、远程 SSH 与 Docker,并支持按任务的环境变量、工作区绑定以及面向代码修改任务的隔离 git worktree。
  6. 多渠道路由与模板 —— 一次运行可投递到 Telegram、dsh-kanban、Discord、Slack、ntfy、Bark、PushPlus、语音(dsh-tts)与 Gitea,支持 {变量} 消息模板与按 DSH 凭据名称引用的密钥。

🏗️ 架构

graph TD
    subgraph Client ["Web 客户端 (DSH UI)"]
        SidebarBtn["侧边栏时钟按钮<br/>(DSH 客户端插槽)"]
        Overlay["任务管理面板<br/>(标签: 全部 / 活跃 / 暂停 / 已完成)"]
        CreateWithDSH["“由 DSH 创建”对话框<br/>(自然语言任务)"]
        ManualForm["手动任务表单<br/>(运行时、cron、超时、重叠策略、渠道)"]
        SettingsCard["设置卡片<br/>(渠道、模板、凭据)"]
    end

    subgraph Server ["服务端 (Cordis 与 DSH 服务)"]
        HttpRoutes["HTTP REST API<br/>(/dsh-cron/*)"]
        AgentTools["工具调用网关<br/>(cron)"]
        Scheduler["TaskScheduler 引擎<br/>(Croner 实例 + one-shot 定时器)"]
        Store["原子 TaskStore<br/>(tasks.json 原子写入)"]
        AgentRunner["智能体会话调度器<br/>(以指定模型执行提示词)"]
        Runtimes["执行运行时<br/>(shell、node、python、http、ssh、docker)"]
        Notify["投递路由<br/>(模板 + 9 个渠道)"]
        Secrets["凭据引用<br/>(DSH credentials / ENV)"]
    end

    SidebarBtn --> Overlay
    Overlay --> CreateWithDSH
    Overlay --> ManualForm
    SettingsCard --> HttpRoutes
    CreateWithDSH -->|POST /chat/start| HttpRoutes
    ManualForm -->|POST /tasks| HttpRoutes
    HttpRoutes --> Scheduler
    AgentTools --> Scheduler
    Scheduler --> Store
    Scheduler -->|按间隔/一次性触发| AgentRunner
    Scheduler --> Notify

✨ 功能与能力

1. 可视化任务管理器

点击 DSH 侧边栏中的时钟图标(位于“新会话”按钮旁)打开管理面板:

  • 状态过滤标签:全部、活跃、已暂停、已完成。
  • 即时操作:立即运行(Run Now)、暂停/恢复调度、带确认的删除。
  • 一键预设模板:每日摘要、每周回顾、待办监控。
  • 运行历史:打开任务卡片查看历史运行 —— 时间、耗时、状态(成功 / 失败 / 超时 / 跳过 / 错过)、输出与错误。
  • 快捷计划预设:在任务编辑弹窗中通过预设按钮一键填入常用频率(15m、1h、Daily 09:00、Weekdays、Weekly Mon),并即时更新自然语言预览。
  • 自动暂停与预算保护徽章:当任务因预算熔断机制(Burn Guard)自动暂停或手动暂停时,任务卡片上显著展示包含具体原因的状态徽章。
  • 汇总统计栏:活跃任务数、总运行次数、总 token 消耗与估算美元成本。

2. “由 DSH 创建”对话框

无需猜测 cron 语法,用自然语言即可创建任务:

  1. 点击 Create ⌄ ➔ Create with DSH。
  2. 描述要自动化的内容(例如:“每个工作日早上 9 点检查未处理的 PR 并起草评论”)。
  3. 插件会创建一个注入了调度器指令的专属智能体会话。智能体会与你确认细节 —— LLM 还是 NO-LLM shell 任务、准确的 cron 表达式、在你的 DSH 安装中可用的经济型模型,以及是否启用“静默规则”(仅在新事件或故障时告警)—— 评估属于对话内定时提醒(schedule_create)还是后台自动化(cron),并在获得您的确认后通过 cron 工具(action: 'create')注册任务。

2. DSH 核心内置 schedule 与 dsh-cron 对比

DeepSeek Harness 内置了轻量级扩展 @deepseek-ai/dsh-schedule,用于会话内的基础定时提醒。下表帮助您根据场景选择合适的工具:

功能维度 DSH 核心 schedule (@deepseek-ai/dsh-schedule) @goodandready/dsh-cron
主要定位 当前会话内的定时提醒与催办消息 无人值守的后台自动化执行器与任务编排引擎
执行上下文 当前活动会话内 独立的隔离智能体会话或外部后台进程
执行运行时 仅当前会话提示词(LLM) 9 种运行时:llm、script (bash/sh)、node、python、http (REST/webhook)、ssh、docker、skill、workflow
模型工具 schedule_create、schedule_list、schedule_delete 统一 cron 工具(action: create、list、get、update、pause、resume、run、delete)
工具模式体积 约 1.5k 字符 约 1.5k 字符(由 9 个工具合并为 1 个,节省约 12k 字符上下文)
推送渠道 仅限当前会话 多渠道:Telegram、Discord、Slack、Webhook、Kanban、ntfy、Bark、PushPlus、语音 (TTS)、Gitea
代码修改隔离 无 临时或保留的 git worktree 隔离环境(worktree: true)
成本与 Token 限制 无 成本熔断防护:costLimitUsd、dailyCostLimitUsd、tokenLimit 自动暂停
容错与健康检查 无 指数退避自动重试、失败自动诊断、心跳监测 (Dead Man's Snitch / Better Uptime)
静默规则 (Silent Rule) 无 无新事件或变更时完全静默(杜绝通道垃圾消息)
任务管理 基础列表与删除 完整 UI 管理器、运行历史、日志查看器、指标统计、手动触发、导入导出、配置同步

3. 智能体工具 (cron)

自主智能体通过单个统一的 cron 工具直接管理定时任务,大幅降低模型模式开销:

动作 (action) 说明 核心参数
create 创建新的后台定时任务或自动化作业 title、schedule、prompt、type、model、channels、delivery 等
list 列出任务的状态、下次运行时间、token 总量与成本估算 status ('all'、'active'、'paused'、'completed')
get 根据任务 ID 获取单项任务的完整配置 id
update 就地修改现有任务(切换到代码执行运行时需 confirmCodeSwitch: true) id、修改字段
pause 暂停调度而不删除配置 id
resume 恢复已暂停的调度 id
run 触发一次立即的带外运行 id
delete 永久删除任务及其历史 id

[!NOTE] 上下文优化与平滑迁移:此前 9 个单独的工具模式在每次模型轮次中消耗约 13.6k 字符。整合为单一 cron 工具后,模式开销减少约 88%(降至约 1.5k 字符)。旧工具名(cron_create_task、cron_schedule_task、cron_list_tasks 等)被优雅拦截,并返回清晰迁移提示,引导模型使用带对应 action 的 cron 工具。对于简单的会话内提醒,模型将建议使用核心内置的 schedule_create。

会话中模型可进行的调用示例:

cron({
  "action": "create",
  "title": "Morning digest",
  "schedule": "0 8 * * 1-5",
  "prompt": "Prepare a brief morning digest of active tasks and open tickets.",
  "type": "llm",
  "delivery": "isolated"
})

4. 调度表达式语法

基于 croner,支持标准 5 段 cron 表达式与友好的别名:

  • 0 9 * * 1-5 —— 工作日 09:00
  • */15 * * * * —— 每 15 分钟
  • 0 0 * * 0 —— 每周日午夜
  • every 10m / every 2h / every 30s —— 自然语言间隔
  • daily / hourly / weekdays 快捷方式,以及标准 @hourly / @daily / @weekly / @monthly / @yearly 与 @every 30m
  • 任务级时区 —— 可为任务设置 IANA 时区(如 Europe/Berlin);未设置时按服务器本地时间调度
  • 一次性任务:at: 2026-09-05T15:00:00Z(精确 ISO 时间戳)或相对延时 in 20m / in 2h(也接受 через 15 минут 之类的俄语输入)。一次性任务在单次运行后自动转为 completed,显示在 已完成 标签下。

5. 执行可靠性

  • 自动重试 —— 按任务设置 maxRetries 与基础 retryBackoffMs:失败(error/timeout)的运行按指数退避自动重试,成功后计数归零。
  • Misfire 策略 —— 选择守护进程离线期间错过的运行如何处理:skip(默认 —— 记录缺口)、runOnce(迟执行一次)或 catchUpAll(迟执行并记录缺口)。skip 下错过的一次性任务直接转为 completed,不再过期触发。
  • 并发上限 —— 插件设置 maxConcurrent 限制并行运行数;超出的运行记录为 skipped 并附原因。
  • 实时执行指示 —— 任务列表中的脉冲状态图标与运行计时器。

6. 执行运行时

每个任务可选择自己的运行时;非 LLM 运行时不需要模型,也不消耗 token:

  • Shell(script)—— 通过 Harness shell 执行命令或脚本,支持 env 与 cwd。
  • Node.js(node)与 Python(python)—— 指定解释器(nodePath、pythonPath)运行片段;Python 会自动识别项目虚拟环境。
  • HTTP(http)—— 以自定义请求头与请求体访问 URL,状态码与响应写入运行历史。
  • SSH(ssh)—— 通过 dsh-remote-workspace 配置(sshProfileId)或独立 host/key 字段在远程主机执行命令。
  • Docker(docker)—— 在镜像容器(dockerImage)中执行命令。
  • 环境变量 —— 按任务的 env 映射(界面中每行 KEY VALUE)应用于外部运行时;请勿在此存放密钥。
  • 工作区与 worktree —— 将任务绑定到 Harness 工作区(workspaceId);对会修改代码的智能体任务,可在隔离的 git worktree 中运行(worktree、keepWorktree)。

7. 成本控制:回退模型与支出保护(Burn Guard)

  • 回退模型 —— 任务可以默认使用便宜模型,失败时改用更强模型完成:设置 fallbackModel(可选 fallbackProvider),失败(error 或 timeout)的运行会在该模型上重试一次,之后才进入常规重试退避。历史记录会标明最终产出结果的模型以及是否使用了回退,两次尝试的用量与成本都会累计,模板变量 {model} 渲染完成运行的模型。回退仅适用于智能体类型(llm、skill、workflow)。
  • Token 与成本支出保护(Burn Guard) —— 为任务配置严格预算上限:costLimitUsd(总支出美元上限)、dailyCostLimitUsd(24小时滚动支出上限)和 tokenLimit(Token总数上限)。一旦达到任一阈值,任务将自动暂停并记录 pausedReason(cost_limit_exceeded、daily_cost_limit_exceeded 或 token_limit_exceeded),同时向所有配置的通知渠道发送报警通知。

8. 会话集成与权限

  • 按任务的权限预设 —— default、read-only、workspace-write 或 full 在提示词执行前应用于任务会话。
  • 会话自动归档 —— 隔离的 cron 会话在运行后自动归档(尽力而为),不干扰聊天列表。
  • 历史 → 会话 —— 每次 LLM 运行都会记录会话,可直接从历史记录打开对话。

9. 按规则保持安静

有输出的任务可以设置用自然语言描述的静默规则(例如“当没有分区使用率超过 80% 时保持安静”)。运行成功时,由便宜模型对照该规则判断输出,若结论为保持安静则跳过报告,并在运行历史中记录原因。遵循 fail-open:没有规则、没有模型、调用失败或答案无法解析时都会照常投递报告。插件设置 silentRuleModel 指定用于判断的模型。

10. 失败诊断

智能体任务可以请求诊断:设置 inspectOnFailure 后,失败(error 或 timeout)的运行会连同任务提示词与截断输出一起交给模型,运行历史中会保存简短诊断与具体的提示词修改建议。历史记录提供按钮把该建议载入编辑表单 —— 不会自动应用。模型由 inspectorModel 指定,消息模板中可使用 {diagnosis}。模型不可用或调用失败时,失败的运行保持原样。

11. 通知渠道与消息模板

运行完成后,报告会发送到该任务配置的所有渠道 —— Telegram、dsh-kanban、Discord、Slack、ntfy、Bark、PushPlus、语音(dsh-tts)以及 Gitea issue:

  • 任务迁移 —— 将全部配置导出为版本化 JSON,并在别处导入(含预览摘要);导入的任务处于暂停状态。
  • 按任务选择渠道 —— 在任务表单中勾选渠道;显式选择会覆盖旧版 notifyTelegram/kanbanMode 开关,留空则回退到它们。
  • 故障隔离 —— 某个渠道不可用会记录在调度器日志中,其余渠道仍会收到报告;失效的 webhook 不会吞掉整份报告。
  • 消息模板 —— 支持全局模板、按渠道覆盖或按任务模板,变量为 {title} {id} {status} {output} {error} {duration} {schedule} {time} {tokens} {cost}。未知占位符保持原样,失败运行默认使用失败模板。
  • onlyOnFailure —— 全局或按任务生效:成功运行静默,仅发送 error/timeout。
  • 凭据按名称引用 —— webhook token 与 Telegram bot token 填写 DSH 凭据的名称(botTokenRef、ntfyTokenRef、pushplusTokenRef、giteaTokenRef),发送时通过 DSH credentials 服务解析,并可回退到环境变量,且绝不会经过插件设置。webhook URL 与 Bark 设备键本身内嵌密钥,因此保存在插件设置文件中,但返回浏览器时始终为掩码,界面回传的掩码值也不会覆盖已保存的值。
  • 投递超时 —— 每个渠道请求都有上限(deliveryTimeoutMs,默认 15000 毫秒,可在设置面板或 settings.yaml 中调整),且各渠道并发发送:无响应的端点只记录为失败,不会拖慢其他渠道或下一次调度。限制作用于整个渠道处理过程,也覆盖凭据解析——它不支持 abort 信号。
  • Telegram —— 带状态徽标(✅ / ❌)、耗时、调度描述与等宽输出块的 Markdown 报告;动态值会被转义。凭据可直接填写,或从 DSH settings.yaml 的 dsh-messenger-gateway 段继承(尽力而为)。
  • Discord / Slack —— 通过 webhook 投递:Discord 使用按运行状态着色的 embed,Slack 使用纯文本正文。
  • ntfy / Bark / PushPlus —— 移动推送,支持主题/设备键与可选 bearer token;Bark 的标题与正文放在请求路径中,PushPlus 端点可指向自建代理。
  • 语音 —— dsh-tts 通过其 HTTP 路由朗读报告(ttsBaseUrl,默认 http://127.0.0.1:3080)。
  • Gitea —— 创建包含运行报告的 issue(giteaBaseUrl、giteaRepo、token 凭据);失败运行标记为 cron、bug、alert。
  • 测试发送按钮 —— 在安排关键任务前现场验证 Telegram 连通性。

12. Kanban 集成与成本统计

  • 自动创建 Kanban 卡片 —— 当 kanbanMode 为 on_failure 或 always 时,插件在 dsh-kanban 中创建卡片(on_failure → error/timeout 时进入 Backlog;always → 完成后进入 Done/Backlog)。
  • Token 与执行成本计量 —— 按运行与任务统计 token 消耗(输入、输出、缓存读取),基于内置价格表估算美元成本,并提供汇总分析栏。

13. 重叠策略与执行超时

  • 执行超时(timeoutSeconds) —— 达到限制后,shell 子进程通过 abort 信号立即终止,智能体会话被释放以停止消耗 token。默认 1800(30 分钟)。
  • 重叠策略(overlapPolicy) —— 上一次运行尚未结束时再次触发调度时的行为:
    • skip(默认):丢弃重叠的运行,在历史中记录 skipped;
    • queue:将下一次运行排队,当前任务完成后自动开始;
    • replace:通过 AbortController 中止当前运行并启动新的执行。

如果守护进程在计划时刻处于离线状态,启动时该次运行会被记录为 missed,历史空档始终可见。

14. 心跳监控(Dead man's switch)

  • 在插件设置中配置 heartbeatUrl 与 heartbeatIntervalSec,调度器会按间隔 GET 该地址 —— 外部监控可在心跳停止时告警。
  • 内置 GET /dsh-cron/heartbeat 端点返回存活状态、活跃任务数与最近运行时间,便于自建看门狗。

15. 来自配置的声明式任务(#50)

长期运行的任务可以直接声明在配置文件里,而无需在界面中手工重建。配置文件拥有这些任务:每次插件启动时会创建或更新它们,从文件中消失的任务会被删除。

在配置文件(cordis.patch.yml)的插件段加入 jobs 列表:

dsh-cron:
  jobs:
    - id: nightly-backup
      title: Nightly backup
      schedule: "0 3 * * *"
      type: script
      prompt: "bash /path/to/backup.sh"
      channels: ["telegram"]
      timeoutSeconds: 3600
    - id: morning-digest
      title: Morning digest
      schedule: "0 8 * * 1-5"
      type: llm
      prompt: "Prepare a brief morning digest of active tasks."
      provider: my-provider
      model: provider-id/model-id
  • 每条必填:id、title、schedule;以提示词承载有效载荷的类型(script、node、python、ssh、docker、llm、skill、workflow)还需非空 prompt。http 例外:目标由 httpUrl(或 prompt)给出。
  • 其余任务字段按原样透传,校验与 API 一致:channels、model、provider、fallbackModel、silentRule、inspectOnFailure、timezone、timeoutSeconds、template、env、cwd,以及运行时字段(nodePath、pythonPath、httpUrl、httpMethod、httpHeaders、httpBody、sshProfileId、sshTarget、dockerImage、workspaceId、worktree、keepWorktree、skillName、workflowName)。
  • 声明式任务标记为由配置管理;面板中显示来源标签而不是编辑/删除按钮。
  • 对配置任务的编辑、暂停、恢复、切换与删除在面板和 API 上返回 409,携带配置任务现有 id 的创建或更新请求 POST /dsh-cron/tasks 同样被拒绝 —— 配置文件的来源为唯一真值。立即运行仍然可用。
  • 通过 UI、API 或智能体工具创建的、id 相同的任务绝不会被覆盖:该条目会被跳过,冲突写入日志。
  • 会执行代码的类型照常激活,但启动时插件会向日志写警告,使通过配置引入的代码路径可见。
  • 条目逐条校验并带下标(config.jobs[i]: …);一条坏条目会被跳过,不会阻止其余任务或整个配置。

16. 外部 REST API(/dsh-cron/api/*,#54)

外部系统(CI、宿主机 cron、curl)无需打开面板即可驱动调度器。这是唯一由 bearer 令牌保护的接口;面板路由保持本地且防跨站。

令牌是插件设置 apiToken(与所有密钥一样掩码显示)。认证与错误:

  • 未配置令牌 → 整个接口返回 503;
  • 缺少或错误的 Authorization: Bearer <token> → 401,比较为常量时间。
方法 路径 说明
GET /dsh-cron/api/tasks 任务列表(status / query 过滤,同面板)
GET /dsh-cron/api/tasks/:id 读取单个任务
POST /dsh-cron/api/tasks 创建任务;带 id 时更新现有任务
DELETE /dsh-cron/api/tasks/:id 删除任务
POST /dsh-cron/api/tasks/:id/run 强制执行一次

这些操作复用面板处理器,因此对会执行代码类型的 x-dsh-cron-confirm: script 门禁以及对配置任务的 409 拒绝与 UI 完全一致。

BASE="http://127.0.0.1:3080"
TOKEN="<API_TOKEN>"

# 列表
curl -s -H "Authorization: Bearer $TOKEN" "$BASE/dsh-cron/api/tasks"

# 创建;请求体带 id 时为更新
curl -s -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"id":"cleanup","title":"Cleanup","schedule":"0 4 * * *","prompt":"Remove stale temporary files."}' \
  "$BASE/dsh-cron/api/tasks"

# 强制执行
curl -s -X POST -H "Authorization: Bearer $TOKEN" "$BASE/dsh-cron/api/tasks/cleanup/run"

# 删除
curl -s -X DELETE -H "Authorization: Bearer $TOKEN" "$BASE/dsh-cron/api/tasks/cleanup"

# 会执行代码的任务还需确认头
curl -s -X POST -H "Authorization: Bearer $TOKEN" -H "x-dsh-cron-confirm: script" \
  -H "Content-Type: application/json" \
  -d '{"title":"Disk check","schedule":"0 * * * *","type":"script","prompt":"df -h"}' \
  "$BASE/dsh-cron/api/tasks"

17. Prometheus 指标(#53)

GET /dsh-cron/metrics 返回 Prometheus 文本格式,无需新增依赖即可被抓取:

  • dsh_cron_tasks_total{status} —— 按状态统计的任务数(gauge)。
  • dsh_cron_task_last_duration_seconds{task} —— 任务最近一次完成运行的耗时(秒,gauge)。
  • dsh_cron_runs_total{status} —— 自插件进程启动以来完成的运行数(counter);状态为 success、error、timeout、skipped、missed。
  • dsh_cron_run_records —— 当前保存在内存中的运行记录数(gauge)。

导出内容只有计数、状态和耗时;提示词、运行输出与任务配置不会出现在其中。

scrape_configs:
  - job_name: dsh-cron
    static_configs:
      - targets: ["127.0.0.1:3080"]
    metrics_path: /dsh-cron/metrics

18. 严格的渠道校验(#121)

创建或更新任务时若包含未知的投递渠道 id,现在会返回 400 并列出违规项:

{ "ok": false, "error": "Unknown channel ids: email_ping", "unknownChannels": ["email_ping"] }

Changed in v0.2.7:此前未知 id 会被静默丢弃,客户端即使有拼写错误也会得到 ok: true,最终得到一个不投递任何地方的任务。

导入有意保持宽容(文件可能来自旧版本):未知 id 会从导入的任务中丢弃,但会在响应(unknownChannels)中列出并写入调度器日志,而不是无声消失。

19. 安装后校验(#126)

deploy.sh 新增仅校验模式,用于检查已安装的配置而不安装任何东西:

bash deploy.sh verify [exact-version]

它确认配置报告了指定版本(默认取 package.json 的版本),登录 Web UI,然后下载客户端 bundle 并确认其中包含包名。

为什么需要它:Web 配置可能位于认证插件之后并对匿名请求返回 401,而插件客户端 bundle 只能通过认证后索引中打印的精确组合 ?? URL 获取 —— 裸的 /plugins/<name>/client.js 会返回 404。因此校验需要先建立已认证会话。

校验使用的环境变量:DSH_WEB_BASE(默认 http://127.0.0.1:3080)、DSH_WEB_TOKEN(令牌;未设置时脚本从单元日志读取最后一个)、DSH_WEB_UNIT(默认 dsh-web.service)。脚本中不含任何密钥。

20. 内部重构:调度解析与排程(#97)

面向开发者,行为不变。parseScheduleExpression 被拆分为保持相同分支顺序的小函数 —— parseAtExpression、parseRelativeOneShot、parseIntervalExpression、parseAliasExpression、parseCronExpression,scheduleTask 拆分为 clearScheduled、scheduleOneShot、scheduleCron。原有测试全部通过,并新增了针对分支优先级与错误的测试。

21. 性能与进程隔离增强包(v0.2.9,#134)

  • 进程树终止隔离:Shell 和 Script 任务在独立进程组启动(POSIX 下 detached: true);中止或超时向整组发送 -child.pid SIGTERM -> SIGKILL,杜绝孤儿进程与僵尸进程。
  • 并发控制限流:默认安全阈值 maxConcurrent = 2,避免定时重叠引发 CPU 和内存峰值。
  • 瞬态错误重试:针对网络抖动和模型速率限制(429、502、503、504、ECONNRESET)提供指数退避重试(最多3次)。
  • 网络与前端优化:GET /dsh-cron/tasks 支持 ETag 与 304 Not Modified;前端页面根据 visibilityState 自适应轮询(前台 8s,后台 30s)。
  • 历史记录轮换与归档:活动任务仅保留最新 100 次运行,超出部分自动归档至 tasks-history-archive.json。
  • 自主 PR 审查配方 (#33):Template Hub 预置配方与 prReviewerEnabled 设置项。

22. 自动化、任务链与可观测性包(v0.2.10,#137)

  • Telegram 双向交互控制:任务通知附带内嵌操作按钮(🚀 立即运行、⏸️ 暂停/恢复、📋 最新日志)。由 POST /dsh-cron/telegram/webhook 处理,严格鉴权 Chat ID 并调用 answerCallbackQuery 反馈。
  • 任务链上下文与动态变量插值:配置 onSuccess 与 onFailure 下游触发器。父任务的执行结果与元数据自动传递给子任务,在 Shell 任务中提供 $DSH_PREV_OUTPUT、$DSH_PREV_TASK_ID、$DSH_PREV_STATUS 环境变量,在 LLM Prompt 中支持 {{prev.output}}(或 {{prevOutput}})、{{prev.taskId}}、{{prev.status}} 占位符插值。Prompt 额外支持动态运行时时间与元数据变量:{{date}}、{{time}}、{{datetime}}、{{timestamp}}、{{year}}、{{month}}、{{day}}、{{taskId}}、{{taskName}}、{{runCount}}。内置最大 5 级深度递归防护,杜绝死循环。
  • 模型结构化动作指令:自主分析任务可输出 JSON 指令触发级联任务(trigger_task)、定向告警(notify)或创建 Issue。受 llmActionsEnabled: false 严格保护。
  • 历史归档与延迟洞察:REST 接口 GET /dsh-cron/tasks/:id/archive(支持分页)与 GET /dsh-cron/tasks/:id/stats;UI 任务卡片展示耗时彩色徽章(<5s 绿,<30s 黄,≥30s 红)。
  • Prometheus 监控增强:/dsh-cron/metrics 导出当前活动并发量 dsh_cron_concurrent_running、各任务 Token 计数器及成本预估指标。

23. 高级可靠性、自愈、心跳与体验包(v0.2.11,#139)

  • 心跳与寂静监控(Heartbeat / Dead Man's Snitch):针对外部备份与后台作业提供反向监控。外部脚本定期向 /dsh-cron/heartbeat/:id 发送请求;超出 heartbeatIntervalSeconds + 宽限期未打卡时,任务标记为 missed,即刻推送失联告警并触发 onFailure 应急流程。
  • 执行前置检查(Pre-flight Gates):执行前先验证条件(HTTP 状态 2xx、命令退出码 0、最低可用磁盘 MB)。未通过直接置为 skipped,杜绝因外部环境异常产生无意义的模型 Token 消耗与错误干扰。
  • 试运行与调度模拟器(Dry-Run & Simulator):接口 POST /dsh-cron/tasks/:id/dry-run 与 UI 🧪 试运行 按钮支持无副作用执行(不入库历史、不发渠道通知);POST /dsh-cron/schedule/preview 实时计算未来 5 次运行时间。
  • 优先级队列与并发池(Priority Queues):并发满载时,等待队列严格依据任务 priority(1 最高,10 最低)调度。
  • 自愈脚本与 AI 根因诊断(Self-Healing):任务失败后自动执行补偿指令 selfHealingCommand(例如重启服务或清理临时空间);autoDiagnose 自动生成 AI 故障根因摘要。
  • UI 交互式归档与管道全景:支持分页浏览任务历史运行全量输出,直观展示 ➜ 成功触发 与 ↳ 失败触发 关联关系。

24. 自动挂载智能体预设与工具支持 (#141 / GH-1,v0.2.12 新增)

  • 自动挂载智能体预设:计划执行的自主 llm 任务和交互式启动现在会自动解析并挂载系统智能体预设(默认通过 setup 钩子中的 presets.mount(agentCtx, preset.id) 挂载用户的标准预设)。计划会话现已具备完整的工具调用能力(文件读写、工作区操作、Shell 终端等),彻底解决此前空会话无工具调用的问题。
  • 单任务预设覆盖:可在 Web 管理界面、REST API 或配置文件中为具体任务配置独立的 agentPreset 标识(例如 coding、system、minimal)。未设置时自动继承系统默认预设。
  • 优雅降级保障:当未安装 agentPresets 服务或指定了未知的预设 ID 时,调度器仅记录友好的警告日志,并安全平稳地继续执行基础模型会话,避免定时任务中断。

25. 常驻持久会话与上下文延续 (targetSessionId,v0.2.13 新增,#143)

  • 跨周期会话上下文延续:支持在任务中配置 targetSessionId。设置后,调度器将在每次定时触发时通过 agents.resume() 唤醒已有会话,而不再每次生成孤立的临时会话(cron-exec-${id}-${uuid})。智能体能够完整继承上一轮对话的历史记忆与分析结论。
  • 上下文窗口保护与轮转机制 (targetSessionReset):为防止高频执行导致模型上下文窗口超限与 Token 成本暴增,支持智能轮转策略:
    • never:持续累积单一会话,不重置。
    • daily:每日自动开启全新子会话(后缀 <id>-YYYY-MM-DD)。
    • weekly:每周自动开启全新子会话(后缀 <id>-YYYY-Www)。
    • 日期变量插值:targetSessionId 中支持 {{date}} 占位符,自动注入当前日期 YYYY-MM-DD。
  • 主界面原生可见交互:持久会话不会被标记为 ephemeral/internal,且在执行后跳过自动归档(sessions.archive()),用户可在 DSH 聊天列表中直接查看并继续手动对话。
  • 预设工具链无缝适配:恢复会话时同样完整挂载 agentPresets,保障文件读写、代码编辑与终端工具持续可用。
  • 致谢:功能灵感源自社区开发者 @RaulLazaro。

26. 系统稳定性、硬化与自愈维护包 (v0.2.14, #145)

  • 重试预算自动重置:彻底修复重试耗尽后的计数残留问题。当任务耗尽配置的重试次数(maxRetries)后,attempts 计数器自动清零,确保后续周期的定时调度享有完整的重试预算。常规计划执行或手动触发也均保证以干净的重试预算启动。
  • 清除队列僵尸任务:通过界面/API 暂停或删除任务时,调度器会立即将其从并发等待队列(this.queue)中剔除;并发槽位释放出队时,非激活或已删除的任务也会被自动安全跳过。
  • 历史归档容量上限保护:针对长期运行和高频调度的生产环境,tasks-history-archive.json 针对每个任务安全限制保留最新的 1,000 条运行记录,消除无限制磁盘占用与同步 JSON 序列化卡顿。
  • 灾难恢复与存储自动备份:TaskStore 在每次成功持久化时自动维护原子的 tasks.json.bak 备份副本。若发生进程异常导致数据损坏,存储引擎会自动保存现场切片 tasks.json.corrupted.<timestamp> 供故障分析,并无缝从备份中自愈恢复。
  • 上下文超限自愈与平滑轮转:在常驻持久会话(targetSessionId)中,若智能体因模型上下文窗口溢出(context_length_exceeded)失败,运行器将精准捕获超限错误,归档已满会话,自动轮转至全新子会话并平滑重试,避免任务中断。
  • Windows 进程树彻底终止:在 Windows 系统上,外部进程任务被取消或超时终止时,改为执行 taskkill /pid <pid> /T /F,杜绝孤儿进程和后台残留外壳。

27. 弹窗视口高度自适应与包体积精简 (v0.2.15, #153, #148, #151, #152)

  • 视口高度约束与粘性底部操作栏:所有弹窗(包括任务编辑、新建及推荐模板预设)现已严格受控于视口尺寸 max-height: min(90vh, calc(100vh - 36px)),并内置平滑纵向滚动条。弹窗操作栏(“取消”、“保存”、“创建”)采用 position: sticky 底部悬浮固定,确保无论表单项多长或屏幕分辨率高低,操作按钮始终清晰可见且可随时点击。
  • 遮罩层滚动溢出保护:弹窗遮罩层增加了安全边距与 overflow-y: auto,防止小屏设备在 Flex 居中时发生头部或底部截断。
  • npm 包体积深度精简:从 npm 分发清单中剔除了多余的重复文档副本,使 tarball 体积立减 32 kB 以上,解压后体积减少约 102 kB。
  • Cordis 客户端注入依赖规范化:在 package.json 的 dsh.client.inject 中完整声明了 locale 和 slots 服务依赖。

31. 质量加固与 CI 预检标准包 (v0.2.19, #149, #152, #155, #156, #162)

  • 彻底消除空 catch 块 (#156):引入符合标准规范的 lib/best-effort.js 模块,全面支持同步/异步安全调用、回退返回值和可选日志记录,清除了 runner、scheduler、store 及客户端中的所有 63 处空 catch 块。
  • CI 工作流与本地预检门禁 (#162):新增自动化 CI 工作流(.gitea/workflows/ci.yml 与 .github/workflows/ci.yml),集成本地预检门禁脚本 scripts/ci-preflight.mjs,在出现语法错误、空 catch、颜色硬编码或信息泄露时自动阻断。
  • 主题设计令牌现代化 (#149):将模态对话框与设置卡片中遗留的 rgba(...) 全部重构为原生的 color-mix(in srgb, var(--token) N%, transparent)。
  • 插件清单注入声明规范化 (#152):在 package.json 的 dsh.client.inject 中统一声明完整的 Cordis 包名(@deepseek-ai/dsh-client-locale、@deepseek-ai/dsh-client-ui-slots)。
  • 生产管线导出连接 (#155):将此前仅在测试中调用的导出(findDestructiveRecipe、shouldNotifyTask 和 TEMPLATE_VARIABLES)全面接入配方过滤、通知分发及模板生成核心逻辑。

30. 自更新模块英文与中文多语言支持 (v0.2.18, #160)

  • 设置面板自更新多语言 (#160):在 lib/client-src/10-locales.js 的英文 (en) 与中文 (zh) 字典中补全了全部 10 个自更新键值 (updater.title, updater.btnCheck, updater.checking, updater.btnUpdate, updater.updating, updater.desc, updater.current, updater.available, updater.upToDate, updater.success)。遵循 DSH 插件规范,插件核心内置英文与中文,俄语多语言由 dsh-russian-lang 统一扩展。

29. 客户端模块化解耦与原生主题标准化 (v0.2.17, #149, #150)

  • 客户端模块化架构 (#150): 将庞大的单文件 lib/client.js (约 3950 行) 拆分为 lib/client-src/ 下的 14 个高内聚模块文件 (各模块严格 <= 580 行)。集成零依赖构建脚本 scripts/build-client.mjs 并接入 package.json (build:client, pretest),通过 "files": ["lib/*.js", ...] 避免开发源码冗余打包进 npm 发布包。
  • DSH 语义化主题变量对齐 (#149): 将任务类型标签 (onSuccess, onFailure, heartbeat, targetSession, preflight) 的内联样式全部替换为基于主题变量的 .dsh-cron-tag-* 类;模态框遮罩层接入自适应主题遮罩变量 var(--dsw-alias-bg-mask, rgba(0, 0, 0, 0.75)),移除脉冲动画关键帧中的硬编码 RGBA。
  • 标签治理与工单审计 (#95): 审计并确认全仓库 100% 统一规范使用仓库级标签集。

28. 应用内一键自更新与错误容错增强 (v0.2.16, #147, #155, #156)

  • 插件自更新模块 (#147):新增应用内一键自更新机制 (lib/updater.js)、/api/dsh-cron/update 接口与设置面板专属卡片。自动轮询 npmjs 仓库最新版本,精准比对 Semver 版本号(含预发布版本),通过 DSH CLI 就地升级 @goodandready/dsh-cron,无需 SSH 终端操作。POST 请求受跨域与来源保护 (rejectCrossOrigin)。
  • 消除静默异常与错误追踪 (#156):全面消除空 catch 异常压制:任务导入事务回滚失败记录 warn 级别日志、动态核心模块降级原因记录诊断日志、会话自动唤出失败向用户呈现友好提示。
  • 死代码清理与模块导出精简 (#155):清理未引用的旧版实体 (CHANNEL_LABELS, makeInspectAsk),收回 16 个内部工具函数的暴露权限,并将 supportsSilentRule 接入静默规则核心执行流水线。

📦 安装

dsh plugin --profile web add @goodandready/dsh-cron

重启 DeepSeek Harness 实例并刷新浏览器。


⚙️ 配置(settings.yaml)

可以在 settings.yaml 中配置,也可以通过 DSH 中的插件设置卡片交互式管理:

# settings.yaml
dsh-cron:
  botToken: ""                 # Telegram Bot API 令牌(保密字段)
  chatId: ""                   # 接收报告的 Telegram chat ID
  notifyTelegram: false        # 全局投递所有任务的报告
  onlyOnFailure: false         # 仅失败时投递报告
  kanbanBaseUrl: "http://127.0.0.1:3000"  # dsh-kanban HTTP API 基础地址
  defaultTimezone: ""          # 默认 IANA 时区(空 = 服务器本地)
  maxConcurrent: 0             # 最大并行运行数(0 = 不限)
  heartbeatUrl: ""             # 心跳上报 URL(dead man's snitch)
  heartbeatIntervalSec: 0      # 心跳间隔秒数(0 = 关闭)
  # --- 投递渠道 ---
  botTokenRef: ""              # Telegram bot token 的凭据名称
  template: ""                 # 全局消息模板,例如 "⏰ {title} — {status}"
  channelTemplates: {}         # 按渠道覆盖模板
  deliveryTimeoutMs: 15000     # 每个渠道的投递超时;慢端点记为失败,不影响其他渠道
  discordWebhookUrl: ""        # Discord webhook
  slackWebhookUrl: ""          # Slack incoming webhook
  ntfyUrl: "https://ntfy.sh"   # ntfy 服务器;ntfyTopic / ntfyTokenRef
  ntfyTopic: ""
  ntfyTokenRef: ""
  barkServerUrl: "https://api.day.app"  # Bark 服务器;barkKey = 设备键
  barkKey: ""
  pushplusUrl: "https://www.pushplus.plus/send"  # pushplusTokenRef
  pushplusTokenRef: ""
  ttsBaseUrl: "http://127.0.0.1:3080"   # dsh-tts 基础地址
  giteaBaseUrl: ""             # giteaRepo = owner/repo,giteaTokenRef = 凭据名称
  giteaRepo: ""
  giteaTokenRef: ""
  # --- 外部 REST API(#54)---
  apiToken: ""                 # 外部 /dsh-cron/api/* 接口的 bearer 令牌(掩码;空 = 503)

配置参数

参数 类型 默认值 说明
botToken string "" Telegram Bot API 令牌。留空时插件会尽力继承 DSH 设置中 dsh-messenger-gateway 配置的机器人。保密字段:界面只显示掩码值
chatId string "" 接收报告的 Telegram chat ID。留空时回退到 dsh-messenger-gateway 的第一个允许会话
notifyTelegram boolean false 全局开关:向 Telegram 投递运行报告
onlyOnFailure boolean false 全局开关:仅对 error/timeout 运行投递报告
kanbanBaseUrl string "http://127.0.0.1:3000" 用于自动卡片的 dsh-kanban HTTP API 基础地址
defaultTimezone string "" 任务调度的默认 IANA 时区;空 = 服务器本地时间
maxConcurrent number 0 并行运行上限;超出的运行记录为 skipped(0 = 不限)
heartbeatUrl string "" 心跳上报 URL,调度器存活期间按 heartbeatIntervalSec 间隔 GET
heartbeatIntervalSec number 0 心跳间隔秒数(0 = 关闭)
botTokenRef string "" 保存 Telegram bot token 的 DSH 凭据名称;发送时解析(回退顺序:botToken → messenger-gateway 设置 → 环境变量 CRON_TELEGRAM_BOT_TOKEN)
template string "" 带 {title}/{status}/{duration} 等占位符的全局消息模板;留空使用内置文本
channelTemplates object {} 按渠道 ID 覆盖模板(telegram、discord 等)
deliveryTimeoutMs number 15000 每个渠道的投递超时;超时的端点记为失败,不拖慢其他渠道或下一次调度
discordWebhookUrl / slackWebhookUrl string "" Discord 与 Slack 渠道的 webhook 地址
ntfyUrl / ntfyTopic / ntfyTokenRef string "https://ntfy.sh" / "" / "" ntfy 服务器、主题与可选的 token 凭据名称(以 Authorization: Bearer … 发送)
barkServerUrl / barkKey string "https://api.day.app" / "" Bark 服务器与设备键(键、标题和正文位于请求路径中)
pushplusUrl / pushplusTokenRef string "https://www.pushplus.plus/send" / "" PushPlus 端点(可指向自建代理)与 token 凭据名称
ttsBaseUrl string "http://127.0.0.1:3080" 用于语音播报的 dsh-tts 基础地址
giteaBaseUrl / giteaRepo / giteaTokenRef string "" Gitea 渠道:基础地址、owner/repo 与 API token 的凭据名称
telegramAllowedChatIds string "" 允许执行交互式机器人命令的 Telegram Chat ID 或 User ID(英文逗号分隔)
apiToken string "" 外部 /dsh-cron/api/* 接口的 Bearer 令牌。保密字段,返回时掩码;为空时接口返回 503,错误值返回 401

说明:

  • 运行历史上限为每任务 50 条(固定);每条记录最多保留 4000 字符输出。
  • 任务在服务器本地时区执行;cron 表达式由 croner 按主机时钟计算。
  • 任务持久化在 DSH 数据目录(cron/tasks.json),重启后保留;启动时会检测错过的一次性任务。

🔌 HTTP API 参考

所有端点由 DSH Web 服务器在 /dsh-cron/ 下提供。所有端点均受到强化的 HTTP 来源防护(isTrustedRequest):非回环远程客户端必须携带有效令牌(Authorization: Bearer <token> 或 x-dsh-cron-token),浏览器请求严格校验 Host 与 Origin 一致性并拒绝 Origin: null,同时限制 Sec-Fetch-Site 仅允许 same-origin 或 none。心跳 ping 端点严格要求 POST 方法。任务 GET 响应自动将敏感字段(env、httpHeaders、httpBody)掩码为 '[REDACTED]',并在更新操作提交 '[REDACTED]' 时安全保留已有原密钥。通过 HTTP 创建 script 类型任务还需要 x-dsh-cron-confirm: script 请求头。请求体大小上限为 1 MB。

方法 路径 说明
GET /dsh-cron/tasks 任务列表;查询参数 status(all/active/paused/completed)、query(子串搜索)。返回任务、推荐模板与汇总统计
POST /dsh-cron/tasks 创建或更新任务(携带 id 时为更新)。需要 title、schedule、prompt
GET /dsh-cron/tasks/:id/history 运行历史,?limit=20
POST /dsh-cron/tasks/:id/run 立即手动运行
POST /dsh-cron/tasks/:id/pause 暂停调度
POST /dsh-cron/tasks/:id/resume 恢复调度
POST /dsh-cron/tasks/:id/toggle 切换活跃/暂停
POST /dsh-cron/tasks/:id/duplicate 创建暂停状态的副本:复制配置,重置运行历史与计数
GET /dsh-cron/recipes 内置配方目录:按类别分组的现成监控预设,全部为只读操作
GET /dsh-cron/tasks/export 仅含任务配置的版本化 JSON —— 不含历史与计数。渠道按名称引用凭据,但手动填写在任务中的 env 与 HTTP 请求头属于配置,会出现在文件里
POST /dsh-cron/tasks/import 校验文档并以 add、replace 或 skip 策略导入;支持 dryRun 预览。导入的任务始终为暂停状态,恢复不会自动触发
PATCH /dsh-cron/tasks/:id 部分更新(仅白名单字段:title、schedule、prompt、type、delivery、provider、model、通知/超时/重叠/Kanban 设置、status、oneShot)
DELETE /dsh-cron/tasks/:id 删除任务
GET /dsh-cron/models 列出 LLM 提供方;?provider=<id> 列出模型
POST /dsh-cron/chat/start 启动带任务配置指令的“由 DSH 创建”智能体会话
GET /dsh-cron/settings 客户端安全设置(令牌掩码显示)
POST /dsh-cron/settings 更新集成设置(通过设置服务应用)
GET /dsh-cron/heartbeat 存活探针:活跃任务数与最近运行时间
POST /dsh-cron/telegram/test 发送 Telegram 测试消息
POST /dsh-cron/kanban/test 创建 Kanban 连通性测试卡片
* /dsh-cron/action/:id/:action 任务操作路由的兼容别名(run、toggle、delete、history)
GET /dsh-cron/metrics Prometheus 文本格式的任务与运行计数 —— 不含提示词与输出(#53)
GET / POST /api/dsh-cron/update 插件一键自更新:查询仓库最新版本并就地平滑升级 (#147)
GET / POST /dsh-cron/api/tasks 令牌保护的外部接口:列表 / 创建或更新(#54)
GET / DELETE /dsh-cron/api/tasks/:id 令牌保护的外部接口:读取 / 删除(#54)
POST /dsh-cron/api/tasks/:id/run 令牌保护的外部接口:强制执行(#54)

🧪 测试与预检门禁 (Preflight)

运行全套自动化测试(调度表达式解析、调度器引擎、原子存储、HTTP 辅助函数、通知与工具契约):

npm test

本地执行质量预检门禁(语法检查、零空 catch 块、主题设计规范、npm 发布归档合规性及防泄漏检查):

node scripts/ci-preflight.mjs

📄 许可证

MIT © GooDAnDReaDY

内容来自项目 README(GitHub)↗

评论

评论存放在 GitHub Discussions。用 GitHub 账号登录后可发表评论或点表情。