Back to home@zhangjunjesse

dsh-task-board

No description

Stars
0
Language
TypeScript
Created
Aug 27, 2026
Updated
Aug 27, 2026
GitHub repo

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.jsondsh.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.enabledfalse关闭时完全不联网
sync.providergithubgithubgitlab
sync.repo未设没填等同于关闭同步
sync.baseUrl官方实例私有部署的 API 源
sync.tokenEnv按 provider读 token 的环境变量名
sync.labelPrefixdsh:插件在远端管理的状态标签前缀

凭据不落盘: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_liststatus / tag / assignee / query 过滤,返回精简行(不含描述全文),默认 50 条
task_get单个任务全文
task_create建任务,createdBy 记为 ai,并记下当前会话
task_update改任意字段;改成 done 自动记完成时间,改回去自动清除
task_delete删除

同步不给模型工具:往团队的 issue 区推东西是有受众的动作,保持由人在 UI 里点。

Issue 同步

默认关闭。开启后在任务抽屉里点「推送到 Issue」逐个绑定——本地会有大量琐碎 todo,全自动同步只会制造 issue 噪音。

字段映射:

TaskIssue
titletitle
notesbody(末尾追加锚点 <!-- dsh-task:T-12 --> 用于反查绑定)
status: doneissue closed;其余 open
status: doing / blockedlabel dsh:doing / dsh:blocked
prioritylabel P0P3
tagslabels
assigneeassignees[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 / workspacelib/*.js + lib/types/**
client(Web)src/client/index.tslib/client.js(单文件 CJS,外层包 window.__ModuleLoader__.load

client bundle 只允许 require DSH shell 的 seed 白名单(reactreact/jsx-runtime 等),构建脚本会断言这一点。

设计决策与验收证据见 docs/DESIGN-0.1.0.md

已知边界

  • GitLab 私有部署(自定义 baseUrl)本机无凭据,未经真实验证
  • 跨 DSH 进程的并发写靠版本比对捕获;同进程内的写由存储层串行化。
  • 没有系统提示词注入:模型靠工具描述发现看板,不会每轮被塞任务摘要(省 token)。