dsh-task-board
No description
- Stars
- 0
- Language
- TypeScript
- Created
- Aug 27, 2026
- Updated
- Aug 27, 2026
Introduction
dsh-task-board
一个 DeepSeek Harness 插件:给每个工作区一块任务看板,工作区里所有会话(包括以后新建的)共享同一份,人在 UI 里管,AI 在对话里也能读能改。可选把任务同步成 GitHub / GitLab 的 issue。
- 会话顶部多一个「任务」标签页(在「对话 / 轨迹」右边),点开是看板 + 列表双视图。
- 工作区级共享:任务存在工作区的
.dsh/tasks.json,同一工作区的每个会话读写同一个文件——共享是自然结果,不是需要维护的同步机制。文件还能随仓库 git 提交给同事。 - AI 可读可管:5 个模型工具
task_list/task_get/task_create/task_update/task_delete。和 DSH 自带的todo_write(单会话、临时、模型私有)不同,这块看板是持久的、人能看见的。 - 多会话安全:原子写 + 版本乐观锁。另一个会话改了看板,面板会提示或自动刷新;过期的修改会被拒绝并告知,而不是悄悄覆盖别人。
- 可选 issue 同步:默认关闭,关闭时不发起任何网络请求。开启后逐个任务手动绑定,双向同步。
安装
cd ~/.dsh/profiles
npm install dsh-task-board
然后在 ~/.dsh/profiles/<你的 profile>/package.json 的 dsh.profile.bundles 里加上 dsh-task-board,或在该 profile 的 cordis.patch.yml 里加:
- insert:
- id: task-board
name: dsh-task-board
装完重启 DSH。
⚠️ 在
~/.dsh/profiles里执行npm install时务必把所有插件写在同一条命令里,或先确认该目录有package.json。这个目录没有清单文件,单独npm install <某个包>会把其余已装插件当作多余依赖一并清除。
配置
- insert:
- id: task-board
name: dsh-task-board
config:
storePath: .dsh/tasks.json # 相对工作区根目录;写绝对路径可让多个工作区共用一块板
sync:
enabled: true
provider: github # github | gitlab
repo: owner/repo # GitLab 用 group/project 或数字 id
baseUrl: https://gitlab.example.com # 仅私有部署需要
tokenEnv: GITHUB_TOKEN # 默认 GITHUB_TOKEN / GITLAB_TOKEN
labelPrefix: 'dsh:'
| 字段 | 默认 | 说明 |
|---|---|---|
storePath | .dsh/tasks.json | 看板文件位置。相对路径按工作区根解析 |
sync.enabled | false | 关闭时完全不联网 |
sync.provider | github | github 或 gitlab |
sync.repo | 未设 | 没填等同于关闭同步 |
sync.baseUrl | 官方实例 | 私有部署的 API 源 |
sync.tokenEnv | 按 provider | 读 token 的环境变量名 |
sync.labelPrefix | dsh: | 插件在远端管理的状态标签前缀 |
凭据不落盘:token 只在调用时从 DSH 进程的环境变量读取,既不写进配置也不写进看板文件。
任务模型
存在 .dsh/tasks.json,人可直接查看和编辑:
{
"version": 1,
"nextId": 13,
"updatedAt": "2026-08-26T09:00:00.000Z",
"tasks": [{
"id": "T-12",
"title": "修 parser 空输入崩溃",
"status": "doing", // todo | doing | blocked | done
"priority": "P1", // P0 | P1 | P2 | P3
"tags": ["bug"],
"assignee": null,
"notes": "复现步骤…(markdown)",
"order": 3000, // 列内手工排序
"createdAt": "…", "updatedAt": "…", "doneAt": null,
"createdBy": "ai", // 谁建的
"sessionId": "sess_abc", // 哪个会话建的
"remote": null // 绑定的 issue
}]
}
手工改坏了也不会丢数据:解析不了的文件会让面板切成只读并显示原因,不会被覆盖;单行数据有问题(缺 id、状态写错)则降级为默认值或丢弃该行。
面板用法
- 看板视图:4 列(待办 / 进行中 / 阻塞 / 已完成),拖拽跨列改状态、列内改顺序。
- 列表视图:紧凑单行,适合快速扫。
- 右侧抽屉(不是弹窗,所以能边看板边改):标题、状态、优先级、负责人、标签、Markdown 描述(编辑/预览切换)、同步区、元信息。
- 筛选:搜索框(标题 + 描述 + 标签全文)、优先级 chip、标签 chip。
- 快捷键:
N新建 ·/聚焦搜索 ·↑↓移动选中 ·1-4直接改选中卡片状态 ·Esc关闭。
模型工具
| 工具 | 说明 |
|---|---|
task_list | 按 status / tag / assignee / query 过滤,返回精简行(不含描述全文),默认 50 条 |
task_get | 单个任务全文 |
task_create | 建任务,createdBy 记为 ai,并记下当前会话 |
task_update | 改任意字段;改成 done 自动记完成时间,改回去自动清除 |
task_delete | 删除 |
同步不给模型工具:往团队的 issue 区推东西是有受众的动作,保持由人在 UI 里点。
Issue 同步
默认关闭。开启后在任务抽屉里点「推送到 Issue」逐个绑定——本地会有大量琐碎 todo,全自动同步只会制造 issue 噪音。
字段映射:
| Task | Issue |
|---|---|
title | title |
notes | body(末尾追加锚点 <!-- dsh-task:T-12 --> 用于反查绑定) |
status: done | issue closed;其余 open |
status: doing / blocked | label dsh:doing / dsh:blocked |
priority | label P0…P3 |
tags | labels |
assignee | assignees[0] |
order / sessionId / createdBy / id | 不同步(本地展示概念,推上去只污染 issue) |
冲突按整条记录的最后修改时间决胜,不做字段级合并:双方都没有逐字段时间戳,"合并"只会造出谁都没写过的状态;整条决胜至少是用户能预测的规则,且落败方会被明确提示。
还支持从 issue 反向导入:面板里点「从 Issue 导入」,勾选未绑定的开放 issue 建成任务。
开发
npm install --legacy-peer-deps
npm run build # node 半边 tsc → lib/,client 半边 esbuild → lib/client.js,再断言产物齐全
npm run typecheck # 两个 tsconfig 都查
npm test # node:test,跑在构建产物上
| 半边 | 入口 | 产物 |
|---|---|---|
| node(Host) | src/index.ts(+ store / board / remote / sync / workspace) | lib/*.js + lib/types/** |
| client(Web) | src/client/index.ts | lib/client.js(单文件 CJS,外层包 window.__ModuleLoader__.load) |
client bundle 只允许 require DSH shell 的 seed 白名单(react、react/jsx-runtime 等),构建脚本会断言这一点。
设计决策与验收证据见 docs/DESIGN-0.1.0.md。
已知边界
- GitLab 私有部署(自定义
baseUrl)本机无凭据,未经真实验证。 - 跨 DSH 进程的并发写靠版本比对捕获;同进程内的写由存储层串行化。
- 没有系统提示词注入:模型靠工具描述发现看板,不会每轮被塞任务摘要(省 token)。