← 返回列表
未验证
@achasoft/dsh-tasks-manager
尚未跑自动兼容性验证,可查看页面内的依赖与入口分析。 · 最近上游提交 2026/9/16 · 已提供中文文档
DeepSeek Harness 插件:一个与项目一同保存为可查询 SQLite 文件的项目任务板,在 Web 客户端中提供看板/列表视图,面向模型的任务工具,以及可将卡片作为后台作业派发给智能体的功能。
综合分
30.4
GitHub 分
30.4
用户评分
—
★ Stars
1
周下载量
—
安装插件(需先安装 dsh CLI 引擎:npm install -g @deepseek-ai/dsh)
dsh plugin --profile web add navid-kianfar/dsh-tasks-manager该插件未发布到 npm,走 GitHub 源安装(pnpm 若拦截 prepare 脚本,按其提示在 pnpm-workspace.yaml 的 allowBuilds 中放行后重跑)
数据截至 2026/9/19(元数据每日更新 · 实装验证按队列轮转,单条结论的验证时间见上方)
依赖的 DSH / Cordis 模块
@deepseek-ai/cordis@deepseek-ai/dsh-agent@deepseek-ai/dsh-api-remotes@deepseek-ai/dsh-brand@deepseek-ai/dsh-client-connection@deepseek-ai/dsh-client-locale@deepseek-ai/dsh-client-runtime@deepseek-ai/dsh-client-ui-conversation@deepseek-ai/dsh-client-ui-layout@deepseek-ai/dsh-client-ui-primitives@deepseek-ai/dsh-client-ui-settings@deepseek-ai/dsh-client-ui-settings-plugins用户评分
还没有人投票,来当第一个
订阅周报,不错过优质插件更新
每周一封 · 高评分插件 + 新用户活动
README
@achasoft/dsh-tasks-manager
一个用于 DeepSeek Harness(dsh)的项目任务看板。每个项目在 /.dsh/tasks.db 处拥有一个 SQLite 数据库。Web 客户端会获得一个 Tasks 标签页,其中包含看板、列表视图、会话的 todo_write 清单以及一个后台任务面板。模型会获得用于添加、列出、更新卡片以及为卡片添加评论的工具。当配置了子代理提供程序时,你可以派发一张卡片作为后台任务运行;结果会记录在该卡片上。
Tasks 标签页显示看板,包含 Backlog、To do、In progress、Blocked 和 Done 列,优先级、标签、截止日期,以及页脚中的数据库路径
功能
Tasks 标签页
每个会话中,Tasks 标签页位于 Chat 和 Trajectory 旁边,并显示该会话所属项目的看板。工具栏可在四种布局(Board、List、Session、Background)之间切换,并包含一个搜索框(标题和描述)、一个 Filters 菜单(状态、优先级、标签、负责人、活动/已归档/全部)、Refresh 和 New task。页脚显示数据库路径。
- Board:五列(backlog、todo、in_progress、blocked、done),支持在列之间以及列内拖放,每列都有快速添加功能,每张卡片都有菜单(Open、Dispatch to agent、Stop the background run、Archive 或 Restore、Delete permanently)。
- List:每张卡片一行,可按列排序。
List 布局显示 ref、title、labels、status、priority、assignee、due date 和 updated 列
打开的看板每隔 pollIntervalMs 轮询一次修订计数器,并且仅在其发生变化时重新读取卡片。因此,由代理、另一个会话、另一个 dsh 进程或 sqlite3 所做的更改无需重新加载即可显示。
卡片详情
打开一张卡片会显示可编辑的标题、Markdown 描述、状态和优先级选择器、截止日期日历、由看板上已有标签补全的标签芯片、可编辑和删除的评论、每次更改的 History,以及上次运行的结果。
Assignee 选择器列出已为项目提交过内容的人员,来自 git log(最近 5,000 次提交),按提交次数排序,并将来自 git config user.email 的身份标记为 you。卡片上已有但不在历史记录中的值仍可选择。在没有 git 历史的目录中,选择器会说明这一点。
卡片详情面板,包含 status、priority、assignee、due date、labels,以及带清单的 Markdown 描述
在详情中进行的字段编辑,以及看板上的移动(拖拽或键盘操作),都会以变更开始时的卡片 updatedAt 发送:即你进入标题或打开描述编辑器时,或拿起卡片时的时间戳。你自己之前对卡片所做的编辑会将该时间戳延续下去。如果在此期间有其他任何人更改了卡片,该变更会被拒绝,看板会显示相应消息,并且看板和卡片会重新加载。
会话清单
Session 布局显示助手通过 todo_write 为本会话保留的清单,包含进度,以及一个 Add to board 操作,用于将未完成的步骤复制到看板上。
后台作业与派发
Background 布局列出会话可见的每个后台作业:shell 命令、子代理和已派发的卡片,包含状态、已用时间和一个 Stop 控件。Read output 显示已派发卡片的最终报告。对于其他作业类型,输出会被保留不显示,因为作业注册表为每个作业只有一个消费读取游标,而该游标属于代理的 job_output。
当设置了 subagentProvider 时,Dispatch to agent 会在该子代理提供者上将卡片作为后台作业启动。提示词包含卡片的标题、状态、优先级、标签、负责人、描述和评论。运行期间:
- 卡片显示 Running 及一个停止控件,并移动到 dispatchStatus;
- 运行结束时不会唤醒所属代理(插件持有该作业的完成通知),但 job_list 和 job_output 仍会显示它。
当它结束时,卡片的最后一次运行会记录状态(completed、failed 或 killed)。子代理的输出,或者对于失败的运行,其诊断信息和部分输出,会作为评论添加,并由 job_output 返回。在 completed 时,卡片会移动到 dispatchCompletedStatus,除非该值为 none。结果按数据库路径记录,因此即使在保存设置或重新加载插件后,它仍能到达卡片。
删除正在运行的卡片会先停止其运行,并以拥有该作业的会话身份执行。如果该运行属于另一个活跃的 dsh 进程,则删除会被拒绝。
被此插件旧版本标记为正在运行的卡片会显示 Running (owner unknown):该标记不会说明哪个 dsh 进程拥有该运行,因此它永远不会被自动清除。其停止控件会变为 Clear the running marker,并且 Dispatch to agent 和 Delete 仍然可用;这三者都会先要求你确认,因为旧运行可能仍在另一个 dsh 进程中继续,而清除标记并不会在那里停止它。参见 Run ownership。
设置卡片
Settings → Plugins → Task management 编辑 Configuration 中标记的字段。
任务管理设置卡片展开后,显示数据库位置、新任务的列和位置、刷新间隔、用于分派的子代理、分派列移动以及摘要大小
要求
- Harness: 已使用 @deepseek-ai/dsh 0.1.5-rc.2 测试。
- Node.js: ^22.19 || >=24(package.json 中的 engines)。该看板使用内置的 node:sqlite 模块(DatabaseSync);无需安装任何原生依赖。某些 Node 版本会为其打印 ExperimentalWarning。
- PATH 中的 pnpm:dsh plugin 会转发给它。
- PATH 中的 git(可选):仅在分配对象选择器中需要。
- Harness 服务: 对等依赖为 @deepseek-ai/cordis、dsh-agent、dsh-client-connection、dsh-host-apiproxy、dsh-jobs、dsh-session、dsh-tool-todo、dsh-tools、dsh-typert-protocol 和 schemastery。每个宿主侧服务都以可选方式读取,当服务缺失时功能会降级:
| 服务 | 提供方(标准 dsh-base / web 配置文件) | 缺少时 |
| --- | --- | --- |
| sessions | 核心 harness | RPC 通道只能解析通过持久化找到的会话。 |
| agents | 核心 harness | 分派失败。 |
| sessionPersistence | dsh-session-persistence-jsonl | 在不再活跃的会话上打开的标签页无法找到其看板。 |
| connection、webServer | web 配置文件 | 没有 /dsh-tasks RPC 通道(无头);工具仍可正常工作。 |
| jobs | dsh-jobs-local | 分派和 Background 布局不可用。 |
| subagents + 一个具名提供方 | dsh-subagent-*(dsh-base 中的 spawn、fork) | 分派被隐藏。 |
| todos 投影 | dsh-tool-todo | Session 布局会提示清单不可用。 |
| settings | dsh-settings-file | 没有 Settings 卡片或实时编辑;使用补丁行。 |
浏览器端需要 dsh-api-remotes、dsh-client-locale、dsh-client-ui-conversation、dsh-client-ui-layout、dsh-client-ui-settings、dsh-client-ui-settings-plugins 和 dsh-client-ui-sidebar。
安装
dsh plugin --profile web add @achasoft/dsh-tasks-manager
dsh web
dsh plugin --profile 会在 $DSH_HOME/profiles/ 中运行 pnpm ($DSH_HOME 默认为 ~/.dsh),并在首次使用时创建该配置文件。成功执行 add 后,任何在其 package.json 中声明了 dsh.bundle 的依赖都会被追加到 dsh.profile.bundles。
启动时,harness 按以下顺序从补丁层组合配置文件:每个 bundle 的 cordis.patch.yml、配置文件自身的 cordis.patch.yml、$DSH_HOME/cordis.patch.yml,然后是 --patch 覆盖层。此包的补丁会插入三行,且全部启用:
| 行 id | 加载 |
| --- | --- |
| tasks | @achasoft/dsh-tasks-manager/host:看板、RPC 通道、设置、分派 |
| tasks-tools | @achasoft/dsh-tasks-manager/tools:面向模型的工具 |
| tasks-ui | @achasoft/dsh-tasks-manager:浏览器端部分 |
要启用派发,请在设置卡片中或补丁中设置 subagentProvider(见下文)。
若要为人类保留看板但不让模型访问,请禁用工具行:
- id: tasks-tools
disabled: true
要卸载:
dsh plugin --profile web remove @achasoft/dsh-tasks-manager
删除你自己补丁文件中针对上述 id 的任何行。你项目中的 .dsh/tasks.db 文件会保留在原处。
配置
通过 id 从你配置文件的 cordis.patch.yml 中覆盖某一行。补丁会替换该行的整个 config,因此请重新声明每个键:
- id: tasks
config:
databasePath: .dsh/tasks.db
projectRootMarkers:
- .git
defaultStatus: backlog
newTaskPlacement: top
journalMode: wal
busyTimeoutMs: 5000
pollIntervalMs: 2000
subagentProvider: spawn
dispatchStatus: in_progress
dispatchCompletedStatus: none
digestSize: 25
补丁行是基础层。从设置卡片保存的值会写入 harness 设置层($DSH_HOME/settings.yaml 的 tasks: 部分)并优先。保存更改会关闭并重新打开每个已打开的看板。
tasks 行
| 键 | 默认值 | 在设置卡片中 | 作用 |
| --- | --- | --- | --- |
| databasePath | .dsh/tasks.db | 是 | 相对路径相对于项目根目录解析。绝对路径会让每个项目共享同一个看板。 |
| projectRootMarkers | ['.git'] | 否 | 从会话目录向上查找的条目名称。第一个匹配项即为项目根目录;若无匹配,则会话目录即为根目录。 |
| defaultStatus | backlog | 是 | 创建卡片时未指定状态时所用的列:不带 status 的 task_add、清单中的 Add to board,以及工具栏的 New task 撰写器。当状态筛选器隐藏此列时,撰写器会使用第一个被筛选出的列,以便卡片保持可见。列自身的快速添加始终使用该列。 |
| newTaskPlacement | top | 是 | 列的 top 或 bottom。 |
| journalMode | wal | 否 | wal、delete、truncate 或 persist。 |
| busyTimeoutMs | 5000 | 否 | 写入等待另一个写入者的时长。 |
| pollIntervalMs | 2000 | 是 | 已打开看板的修订轮询间隔;最小 250。 |
| subagentProvider | '' | 是 | 用于派发的子代理提供者名称。为空则隐藏派发。 |
| dispatchStatus | in_progress | 是 | 派发时卡片移动到的列;none 表示不移动。 |
| dispatchCompletedStatus | none | 是 | 运行完成时卡片移动到的列;none 表示不移动。 |
| digestSize | 25 | 是 | task_list 在 sort: urgency 且无 limit 时返回的卡片数;1–200。 |
tasks-tools 行
| 键 | 默认值 | 作用 |
| --- | --- | --- |
| allowDelete | false | 注册 task_delete。归档可恢复;删除不可恢复。 |
| defaultListLimit | 50 | task_list 在无 limit 时返回的卡片数;1–200。 |
Settings 卡片中的两个密钥都不可编辑。
面向模型的工具
工具会根据调用代理的会话目录来解析看板。卡片可以用 #12、12 或完整的 t_… id 来引用。工具写入会以 agent 身份记录在历史中。
| 工具 | 功能 |
| --- | --- |
| task_add | 在一个事务中添加一张或多张卡片(标题、正文、状态、优先级、标签、负责人、截止日期 YYYY-MM-DD)。 |
| task_list | 使用过滤器读取看板(status、priority、labels、assignee、search、archived、limit)。sort: urgency 仅返回未完成、未归档的卡片,最紧迫的排在前面。 |
| task_update | 更改标题、正文、状态、优先级、标签(替换整个集合)、负责人、截止日期或 archived。 |
| task_comment | 添加一条 Markdown 评论。 |
| task_delete | 永久删除一张卡片及其评论和历史记录,并先停止任何正在运行的进程。如果某张卡片的运行标记没有记录所有者,则拒绝操作;需要有人在看板上清除该标记。仅在 allowDelete: true 时注册。 |
限制:标题 200 个字符,正文和评论 20,000 个字符,最多 20 个标签、每个 40 个字符,负责人 80 个字符。
RPC
浏览器端通过 harness 的一元 RPC 通道在 /dsh-tasks 与宿主通信。该路由挂载在 Web 服务器上,位于连接请求网关之后(Host/Origin 检查与浏览器令牌)。每个请求都携带 sessionId;宿主根据该会话的工作目录解析看板,浏览器从不发送文件系统路径。验证错误、未知卡片以及过期的编辑和移动都会以 bad-request 返回。
端点:board.read、board.revision、task.detail、task.create、task.update(可选 expectedUpdatedAt)、task.move(可选 expectedUpdatedAt)、task.archive、task.restore、task.delete(可选 clearUnknownRun)、task.clearRun(taskId、jobId)、comment.add、comment.edit、comment.remove、task.dispatch(可选 clearUnknownRun)、jobs.list、jobs.read、jobs.kill、git.authors。
如果某张卡片的运行标记未记录所有者,则该卡片带有 runOwnerUnknown: true。除非 clearUnknownRun 指明该标记的 job id,否则 task.dispatch 和 task.delete 会以 bad-request 拒绝此类卡片,而浏览器仅在用户确认后才会发送该 id;task.clearRun 会自行清除该标记。如果某个 job id 不再与该标记匹配,则会被拒绝,因此确认操作绝不会清除用户未曾看到的运行。
数据与存储
- 位置: /.dsh/tasks.db。目录以 0700 创建,文件以 0600 创建;已存在的文件保留其模式。
- 表: tasks、comments、activity(每次变更的历史)、meta(revision、next_ref),以及一个用于手动读取的 board 视图:
sqlite3 .dsh/tasks.db "select card, title, status, assignee from board where state = 'active'"
- ref 来自 meta.next_ref,且从不重用,包括删除之后。
- rank 是一个分数索引字符串,因此一次拖拽只写入一行。
- meta.revision 由 tasks 和 comments 上的触发器递增,因此每个写入者都会推动它,包括 sqlite3。
- 共享: 同一主机上的多个 dsh 进程可以共用同一个看板。每个进程为每个数据库文件保留一个句柄。不要对同一个 $DSH_HOME 运行两个 dsh 服务器。
- 备份: SQLite 的在线备份在 dsh 运行时即可工作:
sqlite3 .dsh/tasks.db ".backup tasks-backup.db"
升级现有看板
布局版本存储在 PRAGMA user_version 中;此构建写入版本 3。由已发布的 0.2.2 及更早版本创建的看板为版本 1;版本 2 仅由未发布的开发构建写入过。此构建首次打开较旧的看板时,会在一个事务中就地升级该文件:它添加 tasks.run_owner 列(从版本 1 升级时),安装修订触发器以及运行标记守卫触发器,并重建 board 视图。不会删除或重写任何行,升级也不会清除任何运行标记。
首次启动前请将文件复制一份,因为升级是单向的:
cp .dsh/tasks.db .dsh/tasks.v1-backup.db
升级之后:
- 已经打开该看板的较旧构建进程会继续工作,其写入仍会推动修订。之后打开该文件的较旧构建会拒绝它,因为它只读取版本 1。标记为比此构建更新版本的文件也会以同样方式被拒绝。
- 由较旧构建写入的运行标记没有所有者。它会被保留,显示为 Running (owner unknown),并且仅当你在于看板上确认它时(Clear the running marker、Dispatch to agent 或 Delete),或者当此进程自己的作业注册表识别出该运行并报告其已完成时(同一进程中较旧构建的运行,在插件重新加载之前),才会被清除。它不会在打开时被清除,因为较旧构建可能仍在运行它。
- 如果你清除了这样的标记并再次派发,而较旧构建的运行实际上仍在进行,那么该运行最终的结算会被守卫触发器拒绝,而不会清除新运行的标记。较旧构建会记录失败的写入并继续;新运行不受影响。如果你不希望该卡片有两个运行,请从较旧进程停止其运行。
运行所有权与过期标记
正在运行的卡片会存储 running_job_id 和 run_owner,后者是一个 JSON 对象 {host, machine, pid, processStart, instance, sessionId}。由版本 2 的开发构建写入的标记只有 {host, pid, instance, sessionId},仍可读取。
- instance 是每个 dsh 进程的随机 id。它会被首先检查:带有此进程 instance 的标记属于此进程,即使主机名此后已更改。
- machine 是机器稳定 id 的加盐 SHA-256 摘要:macOS 上是 IOPlatformUUID(每个进程用 /usr/sbin/ioreg 读取一次),Linux 上是 /etc/machine-id 或 /var/lib/dbus/machine-id 加上 pid 命名空间,Windows 上是 MachineGuid(用 reg.exe 读取一次)。如果都无法读取,则改用主机名。host 仍会被写入,供查看该行的人阅读,并且仅对没有 machine 的标记进行比较。
- processStart 是所属进程的启动信息:Linux 上是从 /proc 获取的自启动以来的 ticks 加上 boot id,macOS 上是 ps -o lstart 时间(在 30 秒内进行比较)。在平台两者都不提供的环境中会被省略,包括 Windows。
进程仅在以下情况下清除标记:
- 其所有者位于本机,且所有者进程已退出,或其 pid 现在被一个具有不同启动时间的进程持有;
- 该标记是本进程自身的运行,且作业注册表报告该作业已结束或不再认识它;或
- 该标记没有所有者,并且要么你在面板上确认清除它,要么本进程的作业注册表持有一个具有相同 id 的 task 作业,针对同一卡片和派发会话,在记录的派发时间 10 秒内启动,且该作业已完成。
来自另一个活动进程的标记会被保留,所有者启动时间无法读取的标记也是如此。在另一台机器上拥有的标记永远不会被自动清除。 要手动清除一个标记(面板会在下一次轮询时获取到),请在一条语句中清除两列;仅清除已拥有标记的 running_job_id 的语句会被保护触发器拒绝:
sqlite3 .dsh/tasks.db "UPDATE tasks SET running_job_id = NULL, run_owner = NULL WHERE ref = 12"
安全与信任模型
- Git 读取已加固。 受派人选择器运行 git --no-pager -c log.showSignature=false -c core.fsmonitor=false -c core.pager=cat -C log --no-show-signature …,外加两次 git config --get 调用,超时为 5 秒,输出上限为 4 MB。仓库自身的 .git/config 无法让打开面板时运行 gpg.program 或 fsmonitor 钩子。不会向 git 写入任何内容。结果按项目缓存 60 秒。
- 运行会以其所有者身份停止。 对会话可见的作业执行 Stop 会以该会话身份操作,与 job_kill 相同。由另一个会话在此进程中启动的卡片运行会以其所属会话身份停止,且仅当该作业的类型为 task 时。手动编辑的 running_job_id 指向某人的 shell 作业时,不能用来停止该作业。
- 删除会尊重其他进程。 运行属于另一个活动进程的卡片不能从此进程删除。运行没有记录所有者的卡片仅在你确认后才会删除。
- 所有者检查运行固定的系统工具。 除 git 外,宿主可能每个进程运行一次 /usr/sbin/ioreg(macOS)或 reg.exe(Windows)以读取机器 id,并在判断本机上另一个活动进程的标记时运行 /bin/ps -o lstart= -p (macOS)。每个命令都不通过 shell 运行,使用绝对路径,并带有 2 秒超时;从看板获取的唯一值是 pid,它必须是正整数。在 Linux 上只读取 /proc、/etc 和 /var/lib/dbus 下的文件。机器 id 仅以加盐摘要的形式存储。
- 默认情况下模型无法删除。 task_delete 仅在 allowDelete: true 时注册。
- 作业输出不取自 agent。 看板仅为其自身的 task 作业读取输出,这些作业返回最终输出而不消耗 agent 的读取游标。
已知限制
- 在另一台机器上拥有的标记永远不会被自动清除。 参见运行所有权。
- 由旧版本构建写入的标记永远不会被自动清除,除非本进程的作业注册表将该运行识别为已完成。清除某个标记由你在看板上决定。
- 具有克隆机器 id 的机器(例如未重新封装的 VM 镜像)看起来像同一台机器,因此当在本地找不到其 pid 时,来自另一台的标记可能会被清除。Linux 容器通过 pid 命名空间加以区分。
- 调度需要活动会话。 位于不再活动的会话上的标签页可以读取和编辑看板,但无法调度。
- 看板状态不在会话日志中。 树外插件无法添加会话事件类型,因此历史记录仅存在于 tasks.db 中。
开发
devDependencies 相对于本仓库链接了位于 ../../deepseek-harness 的 deepseek-harness 检出,用于类型和测试。pnpm install 期望它在那里。
pnpm install
pnpm run typecheck
pnpm test
pnpm run build # tsc for declarations, then tsdown for the node and browser bundles
没有需要重新生成的 Typert 契约:该 channel 的载荷在 src/domain/validate.ts 和 src/host/index.ts 中验证。
要在本地 profile 中运行检出,请按路径添加它并重启 web 服务器:
dsh plugin --profile web add link:/absolute/path/to/dsh-tasks-manager
dsh web
链接的包从其自身目录解析其导入,因此它导入的 harness 包必须在那里解析到正在运行的 harness 所使用的相同副本。维护者的工作区通过父级 dsh-plugins 目录中的 publish-plugins.sh 和 .dsh-compat/install-plugins.sh 实现这一点,而不是在本仓库中。重新构建后,重启 dsh web。
许可证
MIT同作者(navid-kianfar)的其他插件
扫码进群