<!--
  dsh-todo-list 简体中文说明。默认英文版见 README.md。
-->

> **简体中文** · [English](README.md)

# dsh-todo-list — DSH 待办事项插件

一个部署级 DeepSeek Harness (DSH) 待办事项插件：从对话中识别关键事项——自然对话、通知导入、公告导入、邮件内容导入等——将其转换为带截止日期的待办，并通过左侧栏「待办事项」入口统一管理。插件以 bundle 形式随 profile 挂载（`dsh plugin add` 一键安装），不修改 DSH 源码。无需批准、无需配置，重启后数据与入口仍在。

## 功能概述

- **理解通知技能（understand-notification）**：随包发布在 `skills/` 目录、通过独立的 `todo-skills` provider 注册的打包技能，教模型从通知、公告、邮件与对话中识别可执行事项，并按统一 JSON 结构输出——纯提取规则，技能内不含任何工具调用指令。
- **提取待办（预览 + 确认）**：模型按技能解析文字后调用 `todo_preview` 暂存候选；页面弹出多选确认框，只有你勾选确认后才正式写入，未经确认不会加入清单。
- **七个模型工具**：`todo_preview` / `todo_add` / `todo_list` / `todo_complete` / `todo_remove` / `todo_update` / `todo_today`，覆盖"暂存预览"与"直接增删改查"。
- **REST API**：`/api/todo` 提供列表、批量新增、更新、删除与清空已完成接口；另有 `/api/todo/pending`（读取 / 暂存 / 清空候选）与 `POST /api/todo/pending/confirm`（确认勾选项写入）支撑预览流程。
- **侧栏面板**：To Do List 入口 + 「待办 / 已办」面板；点击条目查看详情（截止时间、剩余天数、紧急度/重要程度、验收标准、备注）。详情弹窗与预览弹窗均可按住头部拖动。
- **设置页**：语言（中文 / English）、面板透明度与宽度可调，自动持久化；预览弹窗共用同一透明度设置。
- **可靠持久化**：本地 JSON 原子写入，自动迁移旧数据，重启不丢。

## 安装

前置：一个可用的 DSH Web profile（一般位于 `$DSH_HOME/profiles/web`，`DSH_HOME` 默认 `~/.dsh`），并确保 `dsh` 命令可用。

### 推荐：`dsh plugin add`

```sh
dsh plugin --profile web add dsh-todo-list
```

该命令在 profile 目录内执行 `pnpm add dsh-todo-list`；因本包声明了 `dsh.bundle.patch`，`dsh plugin` 会自动把它追加到 profile 的 bundle 层（`dsh.profile.bundles`），无需手动编辑 `package.json` 或 `cordis.patch.yml`。安装后重启 `dsh web` 即生效。

### 备选：本地 `file:` 安装

`file:` 安装需要的是**工程源码（本仓库）**，而不是 npm 包——npm 包只含编译产物 `lib/`、打包的 `skills/` 与 `cordis.patch.yml`，没有 `src/` 和 TypeScript 工具链，无法本地构建。先获取源码：

```sh
git clone https://github.com/perry-ai/dsh-todo-list.git   # 或从 GitHub 下载 zip
```

然后在源码目录构建产物并声明依赖：

```sh
# 1. 在源码目录（下称 $SRC）构建产物
cd "$SRC"
pnpm install        # prepare 脚本自动编译 src/ → lib/

# 2. 声明依赖：编辑 $PROFILE/package.json，在 dependencies 中加入
#    "dsh-todo-list": "file:<$SRC 路径>"

# 3. 加入组合：编辑 $PROFILE/cordis.patch.yml，追加
#    - insert:
#        - id: dsh-todo-list
#          name: 'dsh-todo-list'

# 4. 安装并重启
cd "$PROFILE"
pnpm install
```

`file:` 依赖为拷贝安装（非链接）；pnpm 可能因未检测到内容变化而跳过拷贝，此时用 `pnpm install --force`。重启 `dsh web` 后插件自动就位。

## 快速上手

在 DSH 会话中直接用自然语言添加待办，例如：

> 帮我记两条待办：8 月 26 日前把季度经营分析报告初稿发给管理层，这个比较重要；另外 9 月初提交上个月的报销单，不着急。

模型会自动调用 `todo_add`，把文字解析成待办（标题 / 截止日期 / 紧急度 / 重要程度 / 验收标准），返回类似：

```text
已添加 2 项待办:
[ ] 2026-08-26 撰写季度经营分析报告初稿并发送给管理层 (紧急,重要,特高优先级) (剩 7 天) — 重要事项
[ ] 2026-09-01 提交上个月的费用报销单 (剩 13 天)
当前: 2 项未完成, 0 项已完成。
```

随后即可：

- 用 `todo_today` 获取今天日期，让模型把「明天 / 下周一 / 月底」等相对时间换算成具体日期；
- 用 `todo_list` 查看清单，用 `todo_complete` / `todo_remove` / `todo_update` 维护（改标题、截止日期、紧急度、重要程度、验收标准、备注等）；
- 或打开左侧栏 To Do List 入口：在面板中切换「待办 / 已办」，点击条目查看详情（截止时间、剩余天数、紧急度/重要程度、验收标准、备注），进设置页切换语言、调整透明度与宽度；
- 也可以直接调 REST API：`GET http://127.0.0.1:3080/api/todo` 查看清单，`POST /api/todo` 批量新增。

## 数据存储与迁移

- 清单位于 `$DSH_HOME/storages/dsh-todo-list/todos.json`，结构为 `{ version, todos, nextId }`。
- 每次变更先写 `<file>.tmp` 再原子 rename，避免半写文件。
- 首次加载若存在旧动态插件写入的 `<cwd>/todos.json`，自动迁移并保存到新位置，原文件保留。
- 读取走内存快照，每次写入后刷新快照。

## 功能

- **模型工具**：Host 注册 7 个全局工具 `todo_preview` / `todo_add` / `todo_list` / `todo_complete` / `todo_remove` / `todo_update` / `todo_today`。`todo_add` 可把一段文字中的多个事项一次性转为待办，并为每项确定 `YYYY-MM-DD` 截止日期；`todo_preview` 只暂存解析出的候选并弹窗确认，不直接写入。
- **理解通知技能**：打包的 `understand-notification` 技能定义提取规则（识别可执行事项、确定截止日期——原文明确用原文、相对时间以当前日期换算、缺失则推断并在备注注明；判断紧急度/重要程度、验收标准、备注）与精确的 JSON 输出结构；技能本身不含工具调用指令，与 `todo_preview` 的衔接写在工具描述里。技能由包内 `skills/` 目录经 `todo-skills` provider 发现（独立于宿主 `filesystem` provider）。
- **字段与优先级**：每项待办含标题、截止日期、紧急度（urgency）、重要程度（importance）、验收标准（acceptance）与备注；优先级（priority）由紧急度与重要程度自动推导——两者都为 high → 特高（urgent，列表显示「特」/URG），任一为 high → 高，两者都为 medium → 中，任一为 low 或两者都为 low → 低。
- **REST API**：`GET /api/todo`（列表）、`POST /api/todo`（批量添加）、`PATCH /api/todo/:id`（更新）、`DELETE /api/todo/:id`（删除）、`POST /api/todo/clear-completed`（清空已完成）；预览流程：`GET/POST/DELETE /api/todo/pending`（读取 / 暂存 / 清空候选）与 `POST /api/todo/pending/confirm`（写入勾选项）。
- **侧栏入口**：侧栏底部 To Do List 入口，宽栏显示图标 + 文字 + 未完成数徽标，折叠 rail 显示圆形图标；点击弹出面板，提供「待办 / 已办」标签，待办标签带未完成数量徽标。
- **详情弹窗**：点击任一条目，在主面板右侧浮出详情（截止时间、剩余天数、紧急度与重要程度按等级着色、验收标准、备注），被点击的行高亮显示；弹窗可按住头部拖动。
- **预览确认弹窗**：模型调用 `todo_preview` 后，注册在 `shell.overlay` 槽位的弹窗展示候选并提供多选勾选；确认后经 `/api/todo/pending/confirm` 写入勾选项，取消则清空候选。其视觉语言（背景、透明度、行卡、配色）与详情弹窗完全一致，并排观感相同；同样可按住头部拖动。
- **设置页**：面板头部齿轮进入设置，可调整面板透明度（0.01–0.1）与宽度（150–350px），滑块 + 数字实时展示，并持久化到 localStorage；详情与预览弹窗共用同一透明度值。
- **持久化**：清单存于 `$DSH_HOME/storages/dsh-todo-list/todos.json`，临时文件 + 原子 rename 写入，崩溃不会留下半个文件。
- **主题适配**：面板采用半透明 DeepSeek 品牌蓝，UI 自动适配 dsh web 夜间/日间主题（基于 `body[data-ds-dark-theme]`）；侧栏 footer 纵向堆叠的布局修复内置在客户端样式，无需修改平台源码。
- **国际化**：所有 UI 文案由中英文词典定义；插件初始语言跟随 DSH 设置，设置页提供「中文 / English」语言切换。

## 架构与实现

- `src/index.ts` 通过 `webServer` 服务挂载 `/api/todo` 前缀路由，通过可选的 `tools` 服务注册 7 个模型工具，并通过可选的 `skills` 服务注册打包技能 provider。
- `src/skill-provider.ts` 扫描包内 `skills/` 目录（`<name>/SKILL.md` 或 `<name>.md`），解析极简 frontmatter（name / description / whenToUse），暴露为文件型 skill provider——零新增运行时依赖，且与宿主 `filesystem` provider 不冲突（provider 名 `todo-skills` 唯一，只扫自己的目录）。
- `src/types.ts` 声明领域类型与共享常量；`src/services.ts` 声明本插件消费的 DSH/Cordis 服务结构化子集契约（仅类型，零运行时）。
- `src/store.ts` 负责持久化：内存快照 + 临时文件原子 rename，首次加载迁移旧动态插件数据。
- `src/domain.ts` 集中校验（标题、日期格式）、剩余天数计算、优先级推导（`derivePriority`）、条目投影与增删改查，并提供预览流程的候选暂存（`stageCandidates` / `pendingSnapshot` / `confirmPending` / `clearPending`）。
- `src/api.ts` 分发 REST 路由；请求体为 JSON，上限 1 MiB，超限回 413，非法 JSON 回 400。除 CRUD 外还提供 `/api/todo/pending`（GET 读取 / POST 暂存 / DELETE 清空）与 `POST /api/todo/pending/confirm`。
- `src/tools.ts` 定义 7 个 `todo_*` 工具的 JSON Schema 与文本渲染（`todo_preview` 只暂存不写入）。
- `src/client.ts` 为浏览器半端，经 `window.__ModuleLoader__` 单文件自注册，注入样式并挂载侧栏入口、详情弹窗、设置页与预览确认弹窗（注册在 `shell.overlay` 槽位），通过 `/api/todo` 拉取与变更数据。详情与预览弹窗共用同一透明度设置，均可按住头部拖动。

## 构建

需要 Node 22.19+ / 24+（与 DSH 一致）与 TypeScript 工具链：

```sh
pnpm install   # 安装 devDependencies，并自动触发 prepare 构建 lib/
pnpm build     # 手动构建：tsc -p tsconfig.json，src → lib
pnpm typecheck # 仅类型检查：tsc --noEmit
```

`lib/` 为编译产物，不进版本库（见 `.gitignore`）。`pnpm install` 会通过 `prepare` 脚本自动从 `src/` 编译生成；`file:` 安装前需先在本工程执行一次 `pnpm install` 以产出 `lib/`。发布物包含 `.d.ts` 类型声明，TS 使用者可直接获得类型提示。

## 手工验证

1. 挂载插件并重启 `dsh web`，确认侧栏底部出现 To Do List 入口。
2. 会话中调用 `todo_today` 获取今天日期，再用 `todo_add` 批量添加事项。
3. 调用 `todo_list`，确认每项返回标题、截止日期与剩余天数。
4. 打开侧栏面板，在「待办 / 已办」间切换，确认未完成数量徽标与已完成条目（无截止徽标）显示正确。
5. 点击条目打开详情弹窗，确认截止时间、剩余天数、紧急度/重要程度（等级着色）、验收标准与备注；被点击行高亮。
6. 进入设置页调整透明度与宽度，确认即时生效并持久化。
7. 请求 `GET /api/todo`，确认返回 `{"todos":[...]}`；用 `PATCH /api/todo/:id` 标记完成后再列表，确认完成状态与未完成数变化。
8. 重启 Harness，确认待办仍在。

## 已知限制

- 无跨进程文件锁：同一 `$DSH_HOME` 下同时运行多个 Host 时，各进程维护独立内存快照，写操作可能互相覆盖。
- 会话内不展示待办条，待办仅通过侧栏入口与 `todo_*` 工具管理。
- 优先级不接受手动指定，始终由紧急度与重要程度推导。
- 侧栏 footer 布局修复依赖 CSS 类名 `[class*="footerActions"]`，平台若重命名该类会失效。
- 相对时间（明天 / 下周一等）换算为具体日期，依赖模型先调用 `todo_today` 获取今天日期。
- 预览候选保存在内存中：进程重启后未确认的候选会丢失，新的 `todo_preview` 调用会整批替换候选；未经弹窗确认不会写入任何内容。
