# dsh-ui-web

> 为 DSH Web GUI 增加多列任务看板：本地持久化任务，真正驱动 agent 会话执行，可配 5 段 cron 定时执行。

## Metadata

- Author: [@CAPTAIN1275](https://github.com/CAPTAIN1275)
- Repo: <https://github.com/CAPTAIN1275/dsh-ui-web.git>
- GitHub: [CAPTAIN1275/dsh-ui-web](https://github.com/CAPTAIN1275/dsh-ui-web)
- Stars: 34
- Language: TypeScript
- License: [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html)
- Topics: `dsh-plugin`, `dsh-plugin-market`, `dsh-plugins`
- Forks: 2
- Open Issues: 0
- Last push: 2026-08-16T18:08:27.000Z
- Added: 2026-08-20T00:00:00.000Z

## Install

```bash
dsh plugin --profile web add github:CAPTAIN1275/dsh-ui-web/packages/dsh-task-board
```

## Wiki

## 一句话定位
dsh-task-board 是 DSH Web GUI 里的多列任务看板插件：把任务以「待规划/待办/进行中/已完成/已失败」五列摆开，点「执行」会真实驱动一个 agent 会话跑任务，并支持用 5 段 cron 表达式给任务设定时运行。

## 核心能力
- 侧边栏入口注入：在「新会话」按钮下方插入「任务看板」入口行，宽栏显示图标+文字、折叠 rail 显示纯图标，跟随 DSH 皮肤 token 自适应（src/client/sidebar-entry.ts、src/client/index.ts:155）。
- 多列看板视图：待规划/待办/进行中/已完成/已失败五列；卡片显示标题、描述、状态、更新时间、执行次数；顶部支持搜索过滤、「+ 新建任务」、「返回对话」（src/client/board/TaskBoard.tsx、src/client/index.ts:156-159）。
- 任务详情与执行：点卡片打开详情（含 Prompt 与执行记录），详情内可执行/重新执行、删除（带确认）、查看会话（跳到执行 transcript）、手动移回待规划/待办（src/client/board/TaskDetail.tsx）。
- 真实执行链路：复用或新建一个 DSH 工作区会话，把它改名为任务标题，用任务 Prompt 调用会话真实驱动 agent；订阅会话快照轮次结束后按 `lastAgentError` 把卡片落「已完成/已失败」并写入执行记录（src/core/execution.ts:104-258）。
- 定时任务：详情面板提供启用开关 + 5 段 cron 表达式（分 时 日 月 周，支持 `*` / `*/n` / `a-b` / 逗号列表）+ 常用预设（每天 09:00、每小时、每 10 分钟、每周一 09:00）；启用即计算并持久化「下次运行时间」，到点自动走与手动执行相同的真实执行链路（src/client/board/TaskDetail.tsx:61-66、src/core/scheduler.ts:48-104）。
- 本地持久化与状态回写：任务存浏览器 localStorage（键 `dsh.taskBoard.v1`），跨刷新/重启 DSH 不丢；遗留的「进行中」任务按会话现状自动对账（reconcile），会话 turn 结束即结算为已完成/已失败（src/core/store.ts:31、src/core/execution.ts:156-199）。

## 技术实现
- **语言**: TypeScript（ESM；React 18 写 UI）
- **关键依赖**: `@deepseek-ai/dsh-client-runtime` + `@deepseek-ai/dsh-client-connection` + `@deepseek-ai/dsh-client-ui-settings`（browser 半区注入 runtime 服务、会话 binding、设置面板）；`@deepseek-ai/cordis` + `@deepseek-ai/dsh-settings` + `schemastery`（host 半区插件声明 + 配置 schema 校验）；`react ^18.2.0` + `react-dom`（看板视图渲染）
- **架构模式**: Cordis 双半区插件 — host 半边 `src/index.ts` 只做一件事：通过 `systemPrompt.section(name: 'plugin:task-board', order: 200)` 向所有 agent 公告本插件存在、能力、限制（受 `announceToAgent` 与 `enabled` 开关控制，关闭即注销该段）；browser 半边 `src/client/index.ts` 在 settings scope 就绪后挂载侧边栏入口 + 中间列看板视图（DOM 注入到 `[data-pane="conversation"]` 尾部 React 不管的子节点，靠 `<html data-dsh-taskboard-active>` 切显隐，对话子树保持挂载有状态）。`cordis.patch.yml` 把插件行插入 web profile 名册，`package.json#dsh.client` 声明 `platform: "web"` 并把浏览器半边挂到客户端 runtime 上
- **入口文件**: `src/index.ts`（host 半边，注入 SystemPrompt section + 注册 settings namespace）、`src/client/index.ts`（browser 半边，挂侧边栏 + 看板 + 控制器 + 调度器 + 设置卡片）、`src/core/execution.ts`（真实会话执行）、`src/core/scheduler.ts`（浏览器端定时心跳）、`src/core/store.ts`（localStorage 持久化）、`src/core/controller.ts`（任务台账与视图状态）

## 适用场景
在 DSH Web GUI 上想把"想跑的任务"从对话里捞出来排队执行的用户：写好任务卡片（标题/描述/Prompt），需要时手动点「执行」让 agent 真跑，也可以给某些任务配 cron 让它自动跑起来并把结果留在卡片详情里。适合有重复性工作流（每天 09:00 整理、每 10 分钟巡检）但又不想离开 DSH Web GUI 的场景。

## 前置依赖与兼容性
| 依赖 | 最低版本 | 说明 |
|---|---|---|
| DSH 运行时 | >=0.1.0-rc.6 | `peerDependencies` 锁定 `@deepseek-ai/dsh-client-connection` / `dsh-client-runtime` / `dsh-client-ui-settings` / `dsh-settings` 为 `^0.1.0-rc.6`；`dsh.client.inject` 同时声明 `dsh-client-runtime` / `dsh-client-connection` / `dsh-client-ui-settings`（package.json:37-43） |
| 客户端运行 profile | web | `cordis.patch.yml` 把插件行插入 web profile 名册，`package.json#dsh.client.platform` 也为 `web`；headless profile 下浏览器半区不加载（cordis.patch.yml:11-13、package.json:24-36） |
| React | ^18.2.0 | browser 半区依赖，看板视图用 React 18 渲染（package.json:42） |
| Node.js | 未声明 | 仓库根 `package.json` 与本包 `package.json` 均无 `engines` 字段；README 仅在构建章节写"前置 Node ≥ 20"，运行时无 Node 版本绑定 |
| 平台 | 跨平台（macOS / Windows / Linux） | 仅依赖浏览器 API（DOM、localStorage、`setInterval`、`visibilitychange`）；没有原生绑定 |
| 原生模块 | 无 | 不依赖 node-pty / `node:sqlite` / koffi 等原生模块；仅 `schemastery` 一个非 SDK 运行时依赖（package.json:44-46） |

## 安装方式
```bash
dsh plugin --profile web add github:CAPTAIN1275/dsh-ui-web/packages/dsh-task-board
```

安装后重启 `dsh web`，侧边栏「新会话」下方出现「任务看板」入口即生效（页面刷新不够，需重启进程）。

## 配置项
| 配置 | 类型 | 说明 | 默认值 |
|---|---|---|---|
| enabled | boolean | 总开关；设为 false 时整个插件在浏览器半区不挂载（侧边栏入口与看板都不出现），同时关闭 host 半边的 SystemPrompt 公告段 | true |
| announceToAgent | boolean | 是否在每个 agent 的系统提示词里公告本插件；设为 false 时关闭那条 systemPrompt section，但插件功能本身不受影响 | true |

配置在 Web GUI 的「插件设置」面板里改（`web-ui.plugin.item` 槽位，`order=110`，命名空间 `task-board`），写入即生效，不需要重启 DSH。

## 常见问题

**Q: 装上后在 DSH Web GUI 里能看到什么？**

A: 侧边栏「新会话」按钮下方多出一行「任务看板」入口（侧栏折叠为 rail 时变成纯图标）。点击入口，中间列整列切换为五列看板（待规划/待办/进行中/已完成/已失败）。卡片可拖到不同列，点开有详情（标题/描述/Prompt/执行记录），详情里可执行/重新执行、删除、查看会话并设置 5 段 cron 定时。

**Q: 「执行」是真的驱动 agent 还是只是改卡片状态？**

A: 真实驱动。点执行时插件通过客户端 runtime 复用或新建一个 DSH 工作区会话，把会话改名为任务标题，再用 `session.prompt` 把任务 Prompt 发出去，然后订阅该会话快照，等到这一轮真实结束后按 `lastAgentError` 字段把卡片落「已完成」或「已失败」并写入执行记录。该会话会出现在会话列表，可点进对话查看真实 transcript。

**Q: 任务数据存在哪里？卸载后会不会丢？**

A: 存在浏览器 localStorage 的 `dsh.taskBoard.v1` 键里（与 DSH 客户端自身的快照存储同源，跨刷新与重启 DSH 都持久）。卸载插件不会清数据；如需彻底清除，在浏览器控制台执行 `localStorage.removeItem('dsh.taskBoard.v1')`。

**Q: 定时任务的执行时机是什么？**

A: 在浏览器端调度：插件每分钟 tick 一次（页面从后台切回可见时立即补一次 tick），到点的任务走与手动「执行」完全相同的真实执行链路；同一 tick 不会重复触发，到点前先把「下次运行时间」顺延到下一个 cron 匹配点再执行。需要 DSH Web GUI 的浏览器标签页保持打开；标签页关闭期间错过的调度按「错过即跳过」处理，下次打开时只补跑已经顺延过去的到期任务。任务还在「进行中」时即使到点也会跳过本次，等下一个 cron 匹配点。

**Q: 5 段 cron 表达式支持哪些写法？有没有预设？**

A: 支持 `*` / `*/n` / `a-b` / 逗号列表的 5 段表达式（分 时 日 月 周）；未通过校验的 cron 会被识别为非法并丢弃（不会持久化为一个永远不触发的 schedule）。预设四档：每天 09:00（`0 9 * * *`）、每小时（`0 * * * *`）、每 10 分钟（`*/10 * * * *`）、每周一 09:00（`0 9 * * 1`）。

**Q: 任务进行中刷新页面/重启 DSH，会发生什么？**

A: 不会丢。任务执行会话由真实 DSH 会话驱动，关闭/刷新后插件加载时会对遗留的「进行中」任务按会话现状对账：会话列表里已找不到→标记「已取消」、会话还在跑→继续等待、会话 turn 已结束→按 `lastAgentError` 或历史尾部的 `turn/end` 错误节点判定成功/失败；整个对账过程是幂等的。

**Q: 需要重启 DSH 进程才能让插件生效吗？**

A: 是。profile 层（bundle 行、`dsh.client` 元数据）在 `dsh web` 启动时读取，安装/卸载后重启 `dsh web` GUI 才生效；只刷新页面不会激活新挂载的插件。设置面板里的 `enabled` / `announceToAgent` 改动不需要重启，立即生效。

**Q: Agent 会自动知道这个看板的存在吗？**

A: 默认会。host 半边通过 `systemPrompt.section`（name `plugin:task-board`、order 200）向所有 agent 公告本插件的入口、能力与限制；用户提到「任务看板/看板/定时任务」时模型即知道对应本插件。在 Web 设置里把 `announceToAgent` 改成 false 即可关闭该公告段，插件功能不受影响。

## 上手难度
入门 — 装好插件、重启 `dsh web`，侧边栏多出入口、点开就是五列看板，所有交互都有即时可视反馈；高级定时功能也只需在详情里勾启用 + 选预设 + 保存，无需写 cron 字符串也能用。

## 已知问题与限制
- 定时调度在浏览器端执行，需要 DSH Web GUI 的浏览器标签页保持打开；标签页关闭期间错过的调度按「错过即跳过」处理，下次打开时只补跑已经顺延过去的到期任务，不会"补"历史漏跑的多次（src/core/scheduler.ts:48-104、README.md:82-84）。
- 任务处于「进行中」时，即使到 cron 匹配点也会跳过本次，等下一个匹配点；同一个任务不会并行执行（src/core/scheduler.ts:79-101）。
- 5 段 cron 表达式必须合法（`isValidCron` 校验）；非法表达式在持久化阶段会被丢弃（不会留下一个永远不触发的 schedule），UI 上表现为定时开关开启后没有"下次运行"时间（src/core/store.ts:77-91）。
- 插件挂载/卸载需要在 DSH profile 层生效，所以必须**重启 `dsh web` GUI**；页面刷新不够（README.md:101-103、cordis.patch.yml:1-12）。
- 执行任务会真实消耗 API 额度（host 半边公告的 TASK_BOARD_GUIDANCE 段已明文写出这一点，src/index.ts:25）；详情里不会展示 token/费用数字，请按需关注 DSH 自身的用量统计。
- 任务数据存浏览器 localStorage（键 `dsh.taskBoard.v1`），仅在 `http://127.0.0.1:<dsh web 端口>` 这个 origin 下跨刷新/重启持久；隐私模式或浏览器禁用 localStorage 时持久化会失效（写失败仅 console.error，不会破坏 in-memory 状态，src/core/store.ts:137-156）。
- DOM 挂载（侧边栏入口 + 看板视图）失败时仅 `console.error`，不会抛出，避免把 DSH Web shell 拖崩（src/client/index.ts:160-163）。

---

This document is auto-generated by [deepseek-plugin.org](https://deepseek-plugin.org). HTML page: [dsh-ui-web](https://deepseek-plugin.org/plugins/CAPTAIN1275/dsh-ui-web/packages/dsh-task-board)
Wiki generated by AI (model: `MiniMax-M3`)
