- Startseite
- Plugins
- Integrationen & Fernzugriff
- dsh-task-time
dsh-task-time
flandern1211/dsh-task-time
Erinnerungen und Aufgabenzeitmessung für DeepSeek Harness: Intervallmeldungen während der Modellausführung, Überfälligkeitsmeldungen nach der geplanten Zeit und ein dauerhafter roter Entscheidungshinweis, wenn das Modell Eingaben benötigt. In DSH Erinnerungskarten mit Ton, bei Abwesenheit Systemmeldungen. Anzeigedauer konfigurierbar oder bis zum Wegklicken; Klick öffnet die Sitzung. Plant je Sitzung, zählt nur die Modelllaufzeit und vergleicht beim Ende Ist- mit Planzeit. Aufgabenboard und dauerhafte lokale Aufzeichnungen sind enthalten.
Installation
dsh plugin --profile web add github:flandern1211/dsh-task-timeREADME
dsh-task-time
提醒 + 任务计时 — DeepSeek Harness 插件,主要就做两件事:
- 🔔 提醒 — 按累计运行间隔提醒、超时提醒、需要你决策时的红色常驻提醒;人在 DSH 里走界面提醒卡 + 提示音,不在 DSH 里发系统桌面通知
- ⏳ 任务计时 — 为每个会话设置计划用时,只计模型运行时间,任务结束自动统计实际用时与计划的差距
目录
功能概览
两个主功能:🔔 提醒 · ⏱ 任务计时。 下面的清单按这两个主功能分组,第三节的配套能力是为了让这两件事更好用、数据不丢。
🔔 提醒(主功能)
| 能力 | 描述 |
|---|---|
| ✅ 定时提醒 | 按累计运行时间间隔提醒(间隔在设置弹窗里填,默认值可在设置页改) |
| ✅ 超时提醒 | 超过计划用时自动发出超时提醒 |
| ✅ 决策提醒 | 模型需要你确定 / 选择方案时,红色「需要你决策」提醒(界面内常驻卡;不在 DSH 里时额外发系统桌面通知) |
| ✅ 内部通知 / 外部通知分流 | 人在 DSH 里只发内部通知(提醒卡 + 界面内提示音),人不在 DSH 里才发系统通知,两边不会同时响;「外部通知时机」可配置 |
| ✅ 提醒卡滞留时长可配置 | 普通提醒卡显示多久后自动消散可设(2/3/4/5/8/10/15/30 秒、自定义 1–600 秒或「常驻」),默认 4 秒;决策红卡恒常驻 |
| ✅ 提醒卡可点击跳转 | 点击界面提醒卡直接跳转到该提醒所属的会话 |
| ✅ 系统通知点击后自动定位 | 点击 Windows 通知横幅会把 DSH 拉到前台,客户端检测到窗口重新聚焦后自动跳到「等你决策」的会话 |
| ✅ 标题闪烁 / 浏览器通知 | 需要决策时浏览器标签页标题闪烁;不在当前标签页时通过浏览器 Notification API 推送 |
| ✅ 决策检测三通道 + DOM 兜底 | approval/request、ask_user_question、确认类工具,外加 MutationObserver 监听审批弹窗,确保决策提醒不漏报 |
⏱ 任务计时(主功能)
| 能力 | 描述 |
|---|---|
| ✅ 任务计划设置 | 新会话自动弹出设置窗口,填写任务名、计划用时、提醒间隔(只有点「跳过」才会跳过,误触不会) |
| ✅ 连续计时 | 仅模型运行时累加计时,暂停(等待用户输入、审批)不计时,恢复后续计 |
| ✅ 结束统计 | 任务结束自动统计累计实际用时与计划用时的差距(正数 = 超时) |
| ✅ 计划可运行中调整 | 模型可通过 task_plan_set 工具改计划用时,同时取消超时标记 |
| ✅ 重启续计 | 重启后运行中任务接着累计,停机时间不计入 |
| ✅ 记录持久化 | 任务记录写入 ~/.dsh/dsh-task-time-records.json(上限 500 条),重启后保留 |
🧩 配套能力(辅助)
| 能力 | 描述 |
|---|---|
| ✅ Composer Dock 状态条 | 输入框下方实时显示任务名、运行状态、用时、计划时间、提醒次数 |
| ✅ 任务面板 | 左下角 🗂 按钮打开,进行中 / 已完成分组,点击跳转会话 |
| ✅ 模块开关 | 「任务用时」与「提醒」两大模块可独立开关,只开提醒也能正常工作 |
| ✅ 设置页面 | 每个模块只放它最需要的配置:任务用时里配默认计划用时 / 默认提醒间隔,提醒里配提醒卡滞留时长 / 外部通知时机 / AUMID / 测试通知 |
| ✅ 孤儿任务清理 | 会话已删除时自动收尾残留任务,任务面板不显示僵尸任务 |
安装
方式一:从 npm 安装(推荐)
dsh plugin add dsh-task-time
方式二:从 GitHub 仓库安装
dsh plugin add https://github.com/Flandern1211/dsh-task-time
方式三:本地安装
git clone https://github.com/Flandern1211/dsh-task-time.git
cd dsh-task-time
dsh plugin add .
安装后重启 DeepSeek Harness,插件自动加载。
快速开始
- 创建新会话 → 自动弹出「设置任务计划」窗口
- 填写任务信息:
- 任务名称(如"代码审查"、"文档编写")
- 计划用时(分钟,预填 设置 → 任务用时 → 默认配置 里的「默认计划用时」,默认 60)
- 提醒间隔(分钟,预填默认 10)
- 点击 开始 保存;只有点 跳过 才会跳过本次设置
- 点击弹窗外区域不会关闭/跳过(只弹出提示),避免误触把设置吞掉
- 跳过后想补设置:在输入框下方的计时条点 ⚙ 设置计划 即可重新打开弹窗
- 任务进行中,输入框下方显示状态条
- 超时、决策、提醒自动触发,无需手动操作
使用指南
任务面板
点击左下角 🗂 按钮打开任务面板,查看全部任务:
- 进行中 — 当前运行的任务,显示状态(运行中 / 已暂停 / 需决策)、已用时间、计划时间
- 已完成 — 已结束的任务,显示实际用时、与计划的差异
- 点击任意任务 → 跳转到对应会话
- 进行中任务可「结束」归档,已完成记录可「删除」
计时规则
- 只计模型运行时间:模型在思考、调用工具时累加计时
- 暂停不计时:等待用户输入、审批时暂停计时
- 恢复后续计:模型再次运行后续计
决策提醒
当以下情况触发时,插件自动发出「需要你决策」提醒:
approval/request事件 — 沙箱升级、权限审批等ask_user_question调用 — 模型向用户提问- 工具执行(
ask_user_question/confirm/approve) - DOM 审批弹窗(
[data-approval-key])—— MutationObserver 兜底检测
决策提醒特征:
- 🔴 红色提醒卡(常驻不自动消散,点 × 关闭)
- 🔴 Windows 系统通知(循环报警音)
- 🔴 浏览器标签页标题闪烁
- 🔴 浏览器通知(不在当前标签页时)
功能详解
提醒卡系统
- 提醒卡滞留时长可配置:设置 → 提醒 → 内部通知配置 →「提醒卡滞留时长」,预设 2/3/4/5/8/10/15/30 秒或自定义(1–600 秒),也可选 「常驻(不自动消散)」(
= 0,只能点 × 或点击卡片关闭);默认 4 秒,对齐 DSH 内置 Toast 的保持时长 - 普通提醒卡:右下角堆叠显示,按上面配置的滞留时长自动淡出消散(淡出 1 秒后移除)
- 提醒卡:一个会话最多一张(同一会话反复决策会替换旧卡,不会叠卡);定时/超时/结束/设置完成类卡片都按配置的滞留时长消散;client 本地生成的提示卡(删除/结束/移除失败、测试通知)同样跟随该配置
- 决策提醒卡:红色常驻,不自动消散(固定
autoMs=0,不受滞留时长配置影响),只能点 × 关闭;决策处理完(host 推「决策已处理」)后自动收掉,标题停止闪烁 - 点击跳转:点击提醒卡 → 跳转到对应会话 → 卡片消失(跳转同时清掉该会话的决策卡)
- 点击 ×:仅关闭卡片,不跳转
- 提醒卡由「提醒 → 内部通知」开关统一控制;关掉后右下角不再出现任何卡片(也不会再走直写 DOM 的渲染路径)
通知:内部 / 外部两条通道
通知按「人是不是正在 DSH 里」自动分流,不会在你看得见界面的时候还弹系统通知:
| 人在哪 | 通道 | 表现 |
|---|---|---|
| 在 DSH 里(页面可见,默认还要求窗口在前台) | 内部通知 | 右下角提醒卡(决策时红色常驻)+ 界面内提示音(WebAudio 合成,不依赖外部文件)+ 需要决策时标题闪烁 |
| 不在 DSH 里(切到别的窗口 / 最小化 / 关掉页面) | 外部通知 | Windows 系统 Toast(含系统提示音)+ 浏览器通知,点击通知后回到 DSH 会自动定位到待决策会话 |
- client 每 2 秒(以及焦点/可见性变化时)向 host 上报一次
ui-presence(focused / visible);host 超过 10 秒收不到上报就按「人不在 DSH」处理,保证页面关掉后仍然收得到系统通知 - 判定结果由 host 统一计算并通过
ui-presence的返回值同步回 client,两边结论一致:响了内部提示音就不会再发系统通知,反之亦然 - 「外部通知时机」可配置:
DSH 不在前台时(默认,切走就发)或只有 DSH 页面不可见时(只要 DSH 还看得见就不发);设置页「当前状态」实时显示此刻算不算「在 DSH 里」 - 「发送测试通知」按钮不受时机限制,任何时候点都会真发一条,方便验证链路
外部通知(Windows 系统 Toast)
- 默认借用 DSH Desktop 的 AUMID(
ai.deepseek.dsh.desktop)发出通知 - 支持自定义 AUMID
- 可一键发送测试通知验证链路
- Windows 11 默认静默丢弃未注册应用身份的通知,插件已做适配
- 只在人不在 DSH 里时才发(见上一节的通道表)
- 点击通知后回到 DSH:通知横幅带
dshjump:<sessionId>,点击会把 DSH 窗口置前;客户端在检测到「窗口重新获得焦点」时,先消费get-pending-jump的跳转请求,没有请求就直接跳到「正在等你决策」的会话。之所以不做事件回调:Windows PowerShell 5.1 无法订阅 WinRT 通知事件(见「已知问题」)
外部通知声音
| 场景 | 声音 |
|---|---|
| 任务结束 | Notification.IM |
| 定时提醒 | Notification.Reminder |
| 决策提醒 | Notification.Looping.Alarm |
| 超时提醒 | Notification.Looping.Alarm2 |
标记状态颜色
| 状态 | 颜色 |
|---|---|
| 运行中 | 🟡 #eab308 |
| 已暂停 | 🔵 #60a5fa |
| 需要决策 | 🔴 #f87171 |
| 已完成 | 🟢 #4ade80 |
| 超时 | 🟠 #fb923c |
持久化与重启恢复
- 记录文件:
~/.dsh/dsh-task-time-records.json - 重启后恢复全部状态:
- 已完成记录
- 会话配置(已配置 / 已跳过)
- 运行中任务(从当前时间续计,停机时间不计入)
- 会话历史
- 防抖写入(800ms),避免频繁磁盘 I/O
- 退出时同步落盘,确保数据不丢失
孤儿任务清理
插件每 3 秒检查一次存活会话,自动清理:
- 运行中但会话已删除 → 静默收尾计入已完成记录
- 从未启动且会话已删除 → 清除残留条目
- 确保任务面板不显示僵尸任务
命令
模型工具:task_plan_set
模型可在运行中通过此工具调整当前任务的计划用时。
{
"plannedMinutes": 30,
"note": "任务说明(可选)"
}
- 修改后自动取消超时标记(
overdueFired = false) - 若任务尚未启动,自动设置启动时间
- 返回确认消息含新计划和提醒间隔
此工具已注册到模型 system prompt,会在合适的时机自动调用。
模块开关(按需启用)
插件分为 任务用时 与 提醒 两大模块,可在设置中自由开关,两者完全独立。
在 DSH 设置 → 任务用时 → 模块开关与默认配置 中配置:
任务用时
☑ 启用任务用时
☑ 计时引擎(运行/暂停连续计时)
☑ 计划配置(设置弹窗 / 跳过恢复)
☑ 定时提醒(间隔提醒 + 超时提醒)
☑ 任务面板(进行中/已完成 + 操作)
☑ Dock 状态条(输入框下方实时显示)
☑ 孤儿清理(会话已删除的残留清理)
─ 默认配置(新会话设置弹窗的预填值)
默认计划用时 [60 分钟 ▾](15/30/45/60/90/120/180 或「自定义…」)
默认提醒间隔(分钟) [10]
提醒
☑ 启用提醒
☑ 决策检测(三通道 + 客户端独立检测)
☑ 内部通知(在 DSH 里:提醒卡 + 提示音)
☑ 外部通知(不在 DSH 里:系统 Toast + AUMID) ← 外部通知只有这一个开关
☑ 标题闪烁(需要决策时)
Toast 点击跳转(点通知回到 DSH 后自动定位到待决策会话)
─ 内部通知配置(在 DSH 里:提醒卡 + 提示音)
提醒卡滞留时长 [4 秒 ▾](2/3/4/5/8/10/15/30 秒 / 常驻(不自动消散)/ 自定义…)
─ 外部通知配置
外部通知时机 [DSH 不在前台时 ▾](或「只有 DSH 页面不可见时」)
当前状态 [在 DSH 里 → 只发内部通知 / 不在 DSH → 会发系统通知]
通知应用身份(AUMID) [ai.deepseek.dsh.desktop]
外部通知链路 [发送测试通知]
外部通知只有一个开关:提醒模块下的「外部通知」。它的时机、应用身份与测试入口在同一个模块的「外部通知配置」里,不再有第二个会互相覆盖的开关。 通知按「人在不在 DSH 里」走两条通道:在 DSH 里只发内部通知(提醒卡 + 界面内提示音),不在 DSH 里才发系统通知 —— 见上方「通知:内部 / 外部两条通道」。
行为说明
| 配置 | 结果 |
|---|---|
| 只开 提醒、关掉 任务用时 | 只保留决策提醒(红卡 + 系统通知),不显示设置弹窗、任务面板、Dock 状态条 |
| 关掉主开关 | 该模块下所有子开关被屏蔽;子开关保留各自状态,主开关重新打开后恢复原状 |
| 关掉 内部通知 | 右下角不再显示任何提醒卡(决策红卡、定时/超时/结束提醒卡都归它管)、不再响界面内提示音(系统通知仍可用) |
| 关掉 外部通知 | 人不在 DSH 时不再发系统 Toast / 浏览器通知(「发送测试通知」按钮仍可用) |
| 关掉 任务用时 | 不再计时、不产生"任务完成"提醒(没有任务就没有完成事件) |
配置文件:~/.dsh/dsh-task-time-modules.json
⚠️ 改完开关需要重启 DSH Desktop(或刷新页面)才会生效 —— 客户端 bundle 在应用启动时载入,热更新仅在
pnpm run dev:web运行时可用。
配置
在 DSH 设置 → 任务用时 中可调整(配置就放在对应模块里):
| 配置项 | 位置 | 描述 | 默认值 |
|---|---|---|---|
| 默认计划用时 | 任务用时 → 默认配置 | 新会话「设置任务计划」弹窗的预填值(预设下拉或自定义) | 60 分钟 |
| 默认提醒间隔 | 任务用时 → 默认配置 | 累计运行多长时间提醒一次(分钟),也是设置弹窗的预填值 | 10 |
| 提醒卡滞留时长 | 提醒 → 内部通知配置 | 普通提醒卡显示多久后自动消散(秒,1–600;0 = 常驻不自动消散);决策红卡恒为常驻,不受影响 | 4 |
| 内部通知 | 提醒 → 模块开关 | 在 DSH 里时的提醒卡 + 界面内提示音 | 开启 |
| 外部通知 | 提醒 → 模块开关 | 不在 DSH 里时的系统通知(唯一开关,开/关只看它) | 开启 |
| 外部通知时机 | 提醒 → 外部通知配置 | DSH 不在前台时(默认)/ 只有 DSH 页面不可见时 | unfocused |
| 当前状态 | 提醒 → 外部通知配置 | 实时显示此刻算不算「在 DSH 里」(只读,5 秒刷新) | — |
| 通知应用身份(AUMID) | 提醒 → 外部通知配置 | 系统通知的应用身份 | ai.deepseek.dsh.desktop |
| 外部通知链路 | 提醒 → 外部通知配置 | 「发送测试通知」按钮,手动验证 Toast + 提示音(不受时机限制) | — |
配置说明
AUMID(AppUserModelId) 是 Windows 通知系统的关键标识:
- 默认借用 DSH Desktop 的已注册身份,横幅可正常弹出
- 留空使用默认值
- 修改后可通过 发送测试通知 验证
- 最近一次通知诊断信息会显示在设置页面下方
记录文件
- 位置:
~/.dsh/dsh-task-time-records.json - 容量:上限 500 条,超限自动淘汰旧记录
记录字段
| 字段 | 类型 | 说明 |
|---|---|---|
sessionId | string | 会话 ID |
taskName | string | 任务名称 |
startedAt | string (ISO) | 启动时间 |
finishedAt | string (ISO) | 完成时间 |
plannedMs | number | 计划用时(毫秒) |
actualMs | number | 实际用时(毫秒) |
diffMs | number | 差距(毫秒,正数 = 超时) |
持久化数据结构
{
"records": [ ... ], // 已完成记录
"configs": { ... }, // 会话配置(含 configured 标记)
"dismissed": [ ... ], // 跳过设置的会话列表
"tasks": { ... }, // 进行中任务
"history": { ... }, // 会话历史
"rootSessions": [ ... ], // 根会话 id(用于状态裁剪)
"defaults": { // 全局默认配置
"reminderIntervalMinutes": 10, // 默认提醒间隔(分钟)
"plannedMinutes": 60, // 默认计划用时(分钟)
"reminderAutoDismissSeconds": 4, // 提醒卡滞留时长(秒,0 = 常驻不自动消散)
"toastAppId": "ai.deepseek.dsh.desktop",
"externalWhen": "unfocused" // unfocused | hidden
}
}
configs/dismissed/rootSessions按会话累积,加载时会裁剪到 200 条(活跃会话优先保留);只回写上面这些已知字段,历史遗留键不再被写回磁盘。
项目结构
dsh-task-time/
├── lib/
│ ├── index.js # Host 端:计时、提醒、持久化、RPC、工具注册、prompt section
│ ├── index.d.ts # Host 端类型声明
│ ├── client.js # Client 端:浏览器 UI(React)、提醒卡、任务面板、设置页
│ ├── client.d.ts # Client 端类型声明
│ └── toast.ps1 # Windows WinRT Toast 通知脚本(PowerShell 5.1+)
├── scripts/
│ ├── verify.mjs # Host 全链路:legacy 迁移 / 状态恢复 / 决策提醒 / 写入 / 孤儿清理
│ ├── verify-modules.mjs # 模块开关 + 默认配置 + 决策检测三通道 + 通知跳转链路
│ ├── verify-channels.mjs # 内部/外部通知分流(无头实例 + Toast 打桩)
│ ├── verify-timing.mjs # 计时 / 间隔与超时提醒 / 结束统计 / 配置边界 / 提醒卡滞留时长
│ ├── verify-dom.mjs # 客户端 UI(mock React + DOM):提醒卡生命周期、设置弹窗、Dock 状态条
│ └── test-changes.mjs # 变更合规性检查(源码级断言)
├── cordis.patch.yml # 插件 bundle patch(插入 host composition)
├── package.json # npm 包配置
├── README.md # 本文件
├── LICENSE # MIT License
└── .gitignore
架构说明
┌──────────────────────────────────────────────────┐
│ DSH Desktop │
│ ┌─────────────────────────────────────────────┐ │
│ │ Host 进程 (Electron) │ │
│ │ ┌─────────────────────────────────────────┐ │ │
│ │ │ dsh-task-time (Host) │ │ │
│ │ │ • 计时 & 提醒 (3s tick) │ │ │
│ │ │ • 持久化 (防抖 800ms) │ │ │
│ │ │ • 外部通知 (spawn toast.ps1) │ │ │
│ │ │ • HTTP RPC 服务 (/api/dsh-task-time/rpc)│ │ │
│ │ │ • tool: task_plan_set │ │ │
│ │ │ • prompt section 注册 │ │ │
│ │ │ • 事件监听 (agent/created/status/disposed│ │ │
│ │ │ • 决策提醒 (三通道) │ │ │
│ │ │ • 孤儿任务清理 │ │ │
│ │ └─────────────────────────────────────────┘ │ │
│ │ │ HTTP RPC │ │
│ │ ▼ │ │
│ │ ┌─────────────────────────────────────────┐ │ │
│ │ │ Renderer 进程 (Browser) │ │ │
│ │ │ ┌─────────────────────────────────────┐ │ │ │
│ │ │ │ dsh-task-time (Client) │ │ │ │
│ │ │ │ • 设置弹窗 (shell.overlay) │ │ │ │
│ │ │ │ • 提醒卡堆叠 (shell.overlay) │ │ │ │
│ │ │ │ • 任务面板 (shell.overlay) │ │ │ │
│ │ │ │ • 状态条 (composer.dock) │ │ │ │
│ │ │ │ • 设置页 (settings.section) │ │ │ │
│ │ │ │ • 标题闪烁 / 浏览器通知 │ │ │ │
│ │ │ │ • DOM 审批弹窗兜底 │ │ │ │
│ │ │ │ • 每 2s 轮询 + 上报 ui-presence │ │ │ │
│ │ │ └─────────────────────────────────────┘ │ │ │
│ │ └─────────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────┘ │
│ │ OS │
│ ▼ │
│ ┌─────────────────────────────────────────────┐ │
│ │ Windows Toast (toast.ps1 via powershell) │ │
│ │ • WinRT ToastNotificationManager │ │
│ │ • 点击 → DSH 窗口置前 → client 焦点检测 → 跳到待决策会话 │ │
│ └─────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────┘
开发
技术栈
| 层 | 技术 |
|---|---|
| Host | Node.js (ESM), Electron (可选) |
| Client | React (via ModuleLoader), 原生 JS |
| 通信 | HTTP POST RPC (/api/dsh-task-time/rpc) |
| 通知 | Windows WinRT Toast (PowerShell toast.ps1) |
| 持久化 | JSON 文件 (~/.dsh/dsh-task-time-records.json) |
| 打包 | cordis patch (cordis.patch.yml) |
构建
# 构建(如果使用 TypeScript 源码)
npm run build
# 或直接修改 lib/ 下文件(JS 源码无构建步骤)
验证
# 运行全部套件(mock 运行时,无需 DSH Desktop;不会真的弹系统通知)
npm test
# 单独跑某个套件
node scripts/verify.mjs # Host 全链路
node scripts/verify-modules.mjs # 模块开关 + 默认配置 + 决策三通道
node scripts/verify-channels.mjs # 内部/外部通知分流
node scripts/verify-timing.mjs # 计时 / 提醒 / 配置边界 / 滞留时长
node scripts/verify-dom.mjs # 客户端 UI(提醒卡生命周期、设置弹窗、Dock 状态条)
node scripts/test-changes.mjs # 变更合规性检查
npm test 串跑 6 个套件(verify → verify-modules → verify-channels → test-changes → verify-timing → verify-dom),全部通过才返回 0:
- Legacy 迁移 — 旧格式记录文件迁移
- 状态恢复 — configs/dismissed/tasks/history/defaults 重启恢复
- 决策提醒 — 三通道(approval/userQuestions/tools-pre-execute)+ 20s 节流
- 持久化写入 — 配置写入 + 重加载验证
- 孤儿任务清理 — 已删除会话的残留任务清理
- 计时与提醒 — 运行/暂停累加、间隔与超时提醒去重、结束统计、配置边界(含提醒卡滞留时长 0/负数/过大值)
- 客户端 UI — 提醒卡渲染与生命周期(按配置滞留时长消散、常驻卡不消散)、决策卡去重、设置弹窗校验、Dock 状态条各状态
部署
插件作为 profile bundle 安装,通过 cordis.patch.yml 插入 host composition:
# cordis.patch.yml
- insert:
- id: dsh-task-time
name: 'dsh-task-time'
事件钩子
| 事件 | 用途 |
|---|---|
agent/created | 新会话创建时检查是否需要弹出设置窗 |
agent/status | 监听运行/暂停状态切换,累计计时 |
agent/disposed | 真实根会话关闭时自动结束任务并归档(子会话/subagent 收工不算任务结束:按会话头血统识别后静默丢弃,不写记录也不发提醒) |
approval/request | 需要审批时触发决策提醒 |
internal/service | 监听 userQuestions 服务注册,hook ask 方法 |
tools/pre-execute | 确认类工具执行前兜底触发决策提醒 |
RPC 接口
所有通信通过 HTTP POST POST /api/dsh-task-time/rpc,请求体格式:
{ "method": "methodName", "args": { ... } }
| 方法 | 用途 |
|---|---|
get-pending-setup | 查询会话是否待设置 |
get-pending-sessions | 查询所有待设置会话 |
get-status | 获取某会话计时状态 |
get-reminders | 获取增量提醒 |
get-pending-jump | 获取待处理的 toast 点击跳转(兼容/扩展通道,见「已知问题」) |
get-latest-decision-session | 当前「等你决策」的会话(点击通知回到 DSH 后用它定位) |
get-config | 获取全局配置 |
set-config | 设置全局配置(非法值直接忽略:提醒间隔/计划用时必须是 >0 的分钟数;reminderAutoDismissSeconds 必须是 >=0 的秒数,0 = 常驻,过大夹到 600) |
get-session-config | 获取会话配置 |
set-session-config | 设置会话配置(计划用时必填,缺失/<=0 返回 ok:false + 可读错误) |
dismiss-session-setup | 跳过会话设置(仅由「跳过」按钮调用) |
reopen-session-setup | 撤销「已跳过」,重新打开设置弹窗(计时条「⚙ 设置计划」) |
get-history | 获取会话历史(保留接口,客户端暂未调用) |
get-pending-sessions | 查询所有待设置会话(保留接口,客户端暂未调用) |
get-task-board | 获取任务面板数据 |
end-task | 结束任务 |
drop-task | 移除残留任务 |
delete-task-record | 删除已完成记录(同时清掉 history 并落盘) |
clear-task-records | 清空全部已完成记录 |
test-toast | 测试通知 |
trigger-decision-alert | 触发决策提醒 |
已知问题 / 边界情况
- Windows 11 通知静默丢弃:未注册 AUMID 的通知可调用成功但横幅不显示,默认身份为 DSH Desktop 的已注册身份
- PowerShell 5.1 编码:
toast.ps1保持纯 ASCII,非 ASCII 注释会导致 ANSI/GBK 解码错误 - PowerShell 无法订阅 WinRT 通知事件(2026-09 实测):
Register-ObjectEvent直接报 "Windows PowerShell cannot subscribe to Windows RT events";用TypedEventHandler委托转换虽然能add_Activated成功,但回调永不执行(WinRT 在无 PowerShell runspace 的线程上触发)。因此 toast.ps1 不做点击回调,点击定位改由「窗口重新聚焦 +get-latest-decision-session」实现;get-pending-jump保留为兼容通道(谁写文件谁生效,TTL 5 分钟) - 提醒间隔/计划用时的最小值:
set-config会忽略 <=0 的值,过大值夹到 24 小时;set-session-config缺计划用时直接拒绝(弹窗会在本地先拦一次并给出提示) - 提醒卡滞留时长:
set-config接受 0(= 常驻)与 1–600 秒,负数/非数忽略;「需要你决策」红卡恒为autoMs=0,不受该配置影响。上限 600 秒是因为再长实际等同于常驻,直接选「常驻」更清楚 agents.roots()不是「用户会话」判据(2026-09 踩坑,v0.2.10 修复):dsh-agent的AgentsRegistry.roots()只表示「运行时没有 owner 的顶层 agent」,其源码注释明确写了它不反映持久化会话血统,subagent 会话同样在其中。判断"这个会话算不算用户任务"必须用会话头字段origin === 'subagent'/delegationDepth > 0;也不能改用parentSession—— 用户 fork 出来的会话同样带parentSession(另有seedLength),属真实会话。sessions服务(dsh-session的SessionStore)的get(id)返回带.header的 Session,可用来读这些字段;已关闭的会话不在 store 里,读不到时按"不排除"处理
更新日志
v0.2.10
- 修复 子会话(subagent)被当成用户任务,表现为「任务还没结束却一直报已经结束」:判定"这是不是一个用户任务"用的是
isRoot()(agentsSvc.roots()成员资格),但dsh-agent的AgentsRegistry.roots()只按「运行时没有 owner」过滤(源码注释明确写了它不反映持久化会话血统),而 subagent 会话在运行时同样是无 owner 的顶层 agent ——roots()里照样有它。后果:每个 subagent 都被建了任务、agent/status一running就开始计时,subagent 一收工agent/disposed就报一次「✅ 任务结束」(界面卡 + 系统通知)并写一条"已完成"记录(无名、计划 0)。实测一次 fan-out 4 个 subagent 会在约 10 分钟内陆续报 4 次"结束",而父会话自己的任务一直在跑 - 修复 判据改为会话头的持久化血统字段:
origin === 'subagent'(dsh-session里该字段的唯一合法值)或delegationDepth > 0(顶层 0、子会话 1、嵌套子会话 2…)。不能改用parentSession判定:用户 fork 出来的会话同样带parentSession(并额外有seedLength),但那是真实会话,必须照常计时 - 修复 覆盖全部入口:
agent/created/agent/status/agent/disposed(优先读 live agent 自带的agent.session.header,不依赖服务)以及 tick 孤儿清理 /get-task-board/get-status/get-pending-setup/get-pending-sessions(走sessions服务SessionStore.get(id).header,读到的头部会缓存)。读不到任何会话头时保持原行为(不排除),绝不误杀真实任务 - 修复 修复前遗留的幽灵条目、以及
rootSessions里混入的 subagent id,由 tick 静默清理:不写"已完成"记录、不发提醒(resolveRootSession也不再因为rootSessions里有 subagent id 就把子会话当根会话返回) - 新增
get-status返回lineage诊断字段(headerRead/headerOrigin/delegationDepth/parentSession/isSubagentSession):headerRead:false说明会话头没读到、判定退回了保守行为,可据此确认修复是否真的生效 - 测试
scripts/verify-timing.mjs新增场景 P(12 项):子会话不进设置弹窗候选、不开始计时、收工不写记录/不发「任务结束」卡/不发系统通知、遗留幽灵条目被静默清理;并以 fork 会话与真实根会话作对照,防止"一刀切"误杀。脚手架新增可注入的假sessions服务。回归强度:把lib/index.js回退到修复前,场景 P 精确失败 7 项(含✅ 未命名任务 · 任务结束那条系统通知断言)
v0.2.9
- 文档 简介改为以 提醒 和 任务计时 两大主功能为主线:顶部简介从「任务用时管理与提醒插件」改为两条要点(🔔 提醒 / ⏳ 任务计时),「功能概览」原来一张 17 行的平铺表拆成三组——
🔔 提醒(主功能)、⏱ 任务计时(主功能)、🧩 配套能力(辅助),内容未删减,只是把主功能提到前面 - 文档
package.json的description同步改写:先说提醒(定时/超时/需要你决策时的红色常驻提醒 + 内外通知分流 + 卡片可点击跳转),再说任务计时(会话级计划用时、仅模型运行时连续计时、结束统计与计划的差距、本地持久化),与市场条目data/plugins/Flandern1211__dsh-task-time.yml的description.en/description.zh保持一致 - 无代码改动:
lib/与scripts/未动,功能与 v0.2.8 完全相同
v0.2.8
- 新增 提醒卡滞留时长可配置:设置 → 提醒 → 内部通知配置 →「提醒卡滞留时长」,预设 2/3/4/5/8/10/15/30 秒、自定义(1–600 秒)或「常驻(不自动消散)」,默认仍是 4 秒(对齐 DSH 内置 Toast 的 HOLD_MS+FADE_MS)。配置存在
defaults.reminderAutoDismissSeconds,host 每条普通提醒卡按它下发autoMs,重启后从状态文件恢复 - 修复 滞留时长此前是硬编码:host 的
pushReminder写死4000,client 本地提示卡(删除/结束/移除失败、测试通知)写死6000/8000—— 同一个插件里三种时长且都改不了。现在 host 下发的autoMs优先,client 本地卡回落到同一个配置值(启动时get-config同步一次,设置页改动即时同步) - 不变 「需要你决策」红卡恒为常驻(
autoMs=0),不受该配置影响——几秒后消散的红卡对离开电脑的用户等于没提醒 - 测试 新增 host 端 12 项(默认值/自定义/负数拒绝/过大夹取/0=常驻/决策卡不受影响/重启恢复)+ 客户端 12 项(10 秒不快消、常驻不消散、本地卡跟随配置、设置页下拉预设与自定义)
v0.2.7
- 修复 决策提醒卡重复渲染:一条「需要你决策」提醒同时走 React 提醒栈与
pushReminder()里直写 DOM 的旧路径,界面上会叠出两张红卡(一张 bottom:76px、一张 bottom:16px,后者还盖住左下角 🗂 任务面板按钮),而且点一张的 × 另一张不消失。现在只保留 React 一条渲染路径 - 修复 决策处理完不消卡:用户在审批弹窗里做完决策后,host 只推了一条普通的「决策已处理」提醒,没人移除常驻红卡,标题也继续闪
❓ 需要你决策。现在 client 收到decision-cleared会收掉该会话的红卡,host 也会把该会话的needDecision提醒从队列里摘掉(否则刷新页面重新拉取时红卡会"复活",get-latest-decision-session也会指向过期会话) - 修复 同一会话两张红卡:客户端本地
approval/request检测(负 id)与 host 轮询提醒(正 id)没有合并。现在pushReminder对同一会话只留最新一条决策卡 - 修复 「内部通知」开关关不住提醒卡:
ReminderGate原来用的是「reminderUI或intervalReminder」,定时提醒开着就照样显示卡片;直写 DOM 的决策卡更是完全不看开关。现在提醒卡统一归「内部通知」管,与文档一致 - 修复
end-task的diffMs符号反了(写成plannedMs - actualMs,与finishTask和文档的「正数=超时」相反) - 修复
delete-task-record在清理history之前落盘,且之后不再落盘 → 磁盘上残留已删除的记录,重启后"复活" - 修复 计划用时留空时会把
plannedMinutes: null存下来并标记configured=true,结果是任务永远不启动(不计时、不提醒、也不再弹设置窗),确认文案还写成"计划用时 null 分钟"。现在 host 拒绝非法计划用时(ok:false+ 可读错误),client 在弹窗里先本地拦截并给出提示,弹窗不关闭 - 修复
set-config不校验提醒间隔:0 / 负数会被存下来,随后intervalMs <= 0让定时提醒静默失效(开关显示开着却再也不提醒)。现在非法值直接忽略、过大值夹到 24 小时;状态文件里遗留的非法值在加载时修正为默认值 - 修复 决策外发通知的 20 秒节流把「人在 DSH 里、根本没发出去」的那次也记进节流时间戳 → 用户 20 秒内切出 DSH 会收不到这条决策通知。现在只有真的发出去了才记
- 修复 状态文件无限增长:
dismissed/configs/rootSessions按会话累积、从不清理(实测几十个会话后dismissed已有 70 条)。现在加载时裁剪到 200 条(保留活跃会话),并且只回写已知字段,历史遗留键(已移除的externalAlert、旧版默认值快照)不再被一次次写回磁盘 - 修复 「外部通知时机」默认值与文档/设置页不一致:代码里是
hidden(只有页面不可见才发),注释、README 三处与设置页都写默认unfocused。按文档与既有落盘配置统一为unfocused - 修复 点击系统通知后的会话定位链路实际是断的:
get-pending-jump读的跳转文件已经没有任何写入方(toast.ps1回退为 fire-and-forget 后没人写),客户端也从不调用 host 的get-latest-decision-session。现在客户端在「窗口重新获得焦点」时先消费跳转请求,没有再跳到「正在等你决策」的会话;toast.ps1与 README 里的相关说明同步改写(并记录 PowerShell 订阅不到 WinRT 事件这一实测结论) - 改进 提醒卡上限溢出时连淡出定时器一起清理;弹窗遮罩提示与「开始」校验共用同一套 hint 逻辑
- 测试
npm test从 4 个套件扩到 6 个:新增 host 全链路套件(101 项:计时/提醒/记录/工具/决策/边界/瘦身)与客户端 UI 套件(39 项:真实 DOM + mock React 渲染决策卡与设置弹窗);旧套件补上系统通知打桩——在此之前跑测试会真的在桌面上弹 Windows 通知
v0.2.5
- 改进 系统提示词同步双通道行为:原来写的是「含系统提示音与桌面通知」,v0.2.4 改成按人在不在 DSH 分流后文案没跟上——现在改为「人在 DSH 里时发界面内提醒卡 + 提示音,不在 DSH 里时发系统桌面通知;需要决策时界面内常驻红卡,不在 DSH 里时额外发桌面通知」,避免 agent 向用户转述错误的通知方式
- 清理 移除调试期留下的
console.log:host 端 6 处(get-pending-setup每次弹窗轮询都打一行、两条 stale waitingDecision 分支、三处 cleared waitingDecision)、client 端 3 处(SetupManager poll每 2 秒打一行并JSON.stringify全部会话 id、get-pending-setup结果、approval/request 到达)——这些在 DSH 控制台里会持续刷屏,且SetupManager poll的字符串拼接本身有开销 - 清理 保留 4 处真正有诊断价值的日志(模块配置加载/保存失败的
console.warn、session/event与approval/request处理异常的console.error) - 移除仓库里的临时文件:
.npm-cache/(暂存的 npm 缓存,已加入.gitignore)与_dbg_channels.mjs(调试探针,功能已被scripts/verify-channels.mjs覆盖) - 顺带修正
clearWaitingDecision三处调用点残留的缩进
v0.2.4
- 修复 设置弹窗误判为「跳过」:遮罩(弹窗外区域)点击不再等于跳过——以前点一下弹窗外区域就会永久跳过本次设置,鼠标滑出窗口后点回窗口、或在输入框里拖拽选字时松手到卡片外,都会命中这条路径
- 新增 误跳过可恢复:计时条新增「⚙ 设置计划」,对应的
reopen-session-setupRPC 会撤销「已跳过」标记并重新弹出设置窗 - 改进
get-status增加configured字段;设置弹窗点击遮罩时给出提示文案 - 修复 外部通知有两个开关互相打架:设置页原来的「外部通知(提示音 + 系统弹窗)」勾选框与提醒模块里的「外部通知」开关会各自覆盖对方(开关显示「开」、实际被旧值静默关掉)。现在只保留模块开关里的那一个,旧配置项
defaults.externalAlert/session.externalAlert已移除 - 新增 任务用时的可修改默认配置:设置页「任务用时 → 默认配置」可改默认计划用时(15/30/45/60/90/120/180 预设或自定义)与默认提醒间隔,新会话设置弹窗按此预填(
defaults.plannedMinutes,get-pending-setup下发defaultPlannedMinutes) - 改进 设置页按模块分组:开关与这个模块最需要的配置放在同一组里(任务用时 → 默认配置;提醒 → 外部通知配置 + 发送测试通知按钮)
- 新增 内部通知 / 外部通知双通道:client 每 2 秒上报
ui-presence(焦点 + 可见性,超时 10 秒按离开处理),host 用shouldSendExternal()统一判定——人在 DSH 里只发内部通知(提醒卡 + WebAudio 合成提示音),不在 DSH 里才发系统通知;判定结果回传 client,两个通道不会同时响 - 新增 「外部通知时机」配置(
defaults.externalWhen):DSH 不在前台时(默认)或只有 DSH 页面不可见时;设置页「当前状态」实时显示此刻算不算「在 DSH 里」 - 改进 通知开关改为对称的一对:
内部通知(在 DSH 里:提醒卡 + 提示音)/外部通知(不在 DSH 里:系统 Toast + AUMID);浏览器通知也归外部通道(人在 DSH 里不再弹);「发送测试通知」不受时机限制 - 修复 插件刚加载就被停用时,停用回调会拿内置默认值覆盖磁盘上已存的配置(默认计划用时 / 外部通知时机等)—— 现在只有状态真的从磁盘恢复过(
stateLoaded)才落盘,且停用落盘改用RECORDS_FILE而不是另写一份硬编码路径 - 修复
get-config/get-external-status现在会await ensureLoaded(),设置页不会先显示内置默认值再跳变
v0.2.1 (2026-09-10)
- 修复
end-task缺少 history 截断,已完成记录可无限增长 - 修复 决策节流记录(
decisionAlerts)只增不删导致内存泄漏 + 新决策被旧节流压制 - 修复 任务结束时未清理决策节流记录,影响同一会话的新任务
- 修复 跳过会话设置时丢弃已累积的任务计时,改为归档到已完成记录
- 修复
set-session-config/dismiss-session-setup中persistRecords()无 await,即时落盘保证不可靠 - 修复 3s tick 定时器可能重叠执行导致竞态,改为递归
setTimeout - 修复
tools/pre-execute正则未锚定,子串匹配可误触发决策提醒
v0.2.0
- 首个正式发布版本,完整功能集见上方功能概览
License
MIT License — 详见 LICENSE
Copyright (c) 2026 dsh-task-time contributors
Ähnliche Plugins
dsh-web (dsh-ssh)
zhu1090093659/dsh-web
dsh-web (dsh-remote-web-ui)
zhu1090093659/dsh-web
dsh-web-ui (dsh-ssh)
zhu1090093659/dsh-web-ui
dsh-web-ui (dsh-remote-web-ui)
zhu1090093659/dsh-web-ui