dsh-worktodo 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +141 -2
- package/README.en.md +13 -3
- package/README.md +18 -3
- package/lib/client.js +597 -73
- package/lib/client.js.map +4 -4
- package/lib/index.js +107 -1
- package/package.json +15 -25
- package/src/client/index.js +462 -71
- package/src/parse-due.mjs +170 -0
- package/src/records.mjs +131 -16
- package/src/schema.mjs +9 -1
- package/src/service.mjs +58 -3
- package/src/store.mjs +4 -1
- package/src/tools.mjs +137 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,144 @@
|
|
|
1
1
|
# 更新日志
|
|
2
2
|
|
|
3
|
+
> 本文提到的 `tools/`、`docs/` 等路径都在**仓库**里,不在 npm 发布包内:<https://github.com/olimc2016/dsh-worktodo>
|
|
4
|
+
|
|
5
|
+
## 0.2.0
|
|
6
|
+
|
|
7
|
+
> 这一版是**五轮设计评审后的定稿实现**:快速添加按「两行布局 + 边说边解析」重做,参考滴答清单的成熟做法。
|
|
8
|
+
|
|
9
|
+
### 新增
|
|
10
|
+
|
|
11
|
+
- **两行布局的快速添加**:第一行「待办内容 + 添加」;第二行**更小**,放「日期 / 时间 / 优先级」三项——
|
|
12
|
+
显示的是**当前值**(如 `2026-10-13`、`15:00`、`优先级 · 无`),点开才出选择器。没有加号,输入框始终在。
|
|
13
|
+
- **自然语言日期**(`src/parse-due.mjs`,**人类面板与 `worktodo_*` 工具共用同一份实现**,零依赖):
|
|
14
|
+
- `今天 / 明天 / 后天 / 大后天`、`周X / 周1 / 星期一 / 礼拜一 / 下周一`、`3天后 / +3d / 五天后`、
|
|
15
|
+
`10月20日 / 2026-10-20`、`今晚 / 明早 / 中午 / 下午`(带默认钟点)、`下午3点 / 3点半 / 15:00 / 上午10点`;
|
|
16
|
+
- **只选时间=今天**;**识别不到就不设日期**(不硬塞"今天");
|
|
17
|
+
- 识别结果**从标题里摘掉**("交周报 明天下午3点" → 标题「交周报」),并在第二行标 **· 识别**,可点 ✕ 撤销;
|
|
18
|
+
- **保守优先**:`买3个苹果`、`发 2 封邮件` 一律不识别(宁漏不误吞);
|
|
19
|
+
- 多个星期几取**最后**一个(`周一例会改到周三` → 周三,标题留「周一例会改到」)。
|
|
20
|
+
- **四档优先级**:高 / 中 / 低 / **无**(**新建默认「无」**);排序 高 → 中 → 低 → 无(未定优先级排在最后,但仍在「已完成」之前)。
|
|
21
|
+
- **列表行优先级呈现**:高=红色左缘 + 实心红旗;中=琥珀旗;低=灰旗;**无=什么都不显示**(默认档不制造噪音)。
|
|
22
|
+
|
|
23
|
+
### 数据模型
|
|
24
|
+
|
|
25
|
+
- 新增可选字段 `dueTime`(`HH:MM`,必须配 `due`;清掉日期会连带清掉时间);
|
|
26
|
+
- `priority` 新增 `none`;**现有记录(`normal`)保持"中"不变**,不擅自改用户既有语义。
|
|
27
|
+
|
|
28
|
+
### 说明
|
|
29
|
+
|
|
30
|
+
- 0.1.6 的「通栏大加号 + 常展开表单」**不是定稿设计,不发布**(留在 npm 暂存队列里未批准)。
|
|
31
|
+
|
|
32
|
+
## 0.1.6
|
|
33
|
+
|
|
34
|
+
### 新增
|
|
35
|
+
|
|
36
|
+
- **大加号 + 日历/时钟 + 彩色小红旗**:新增待办改成「一个大加号按钮」,平时只占一行,点开才展开表单:
|
|
37
|
+
标题、**原生日历选日期**(`type=date`,点一下就是日历)、**原生时钟选时间**(`type=time`,需先选日期)、
|
|
38
|
+
**三个不同颜色的小红旗**选优先级(高=红、普通=琥珀、低=灰),外加「添加 / 取消」两个按钮。
|
|
39
|
+
- **截止时间(数据模型)**:新增可选字段 `dueTime`(`HH:MM`),与 `due` 配套:
|
|
40
|
+
- `normalizeDueTime` 接受 `14:30` / `9:05` / `1430` / `14`,非法值显式报错;
|
|
41
|
+
- **没有日期就没有时间**——清掉截止日期会连带清掉时间,避免出现"有时间没日期"的怪状态;
|
|
42
|
+
- 同一天内按时间排序(有时间的在前,没时间的垫后);
|
|
43
|
+
- 行内编辑也支持时间;`worktodo_add` / `worktodo_add_many` / `worktodo_update` 与工具文本都带上它。
|
|
44
|
+
|
|
45
|
+
## 0.1.5
|
|
46
|
+
|
|
47
|
+
### 新增
|
|
48
|
+
|
|
49
|
+
- **面板角落的版本信息**:页脚显示当前安装的版本(`版本 v0.1.5`);若有新版,旁边同时出现
|
|
50
|
+
「有新版本 vX.Y.Z」,鼠标悬停给出更新命令。版本由宿主提供(`/worktodo/list` 载荷的 `version` 字段),
|
|
51
|
+
客户端不自己猜。
|
|
52
|
+
- **更新检查**(自动更新的可见部分):宿主在启动后、以及缓存过期时(默认 6 小时)后台查询 npm registry 的
|
|
53
|
+
`dist-tags.latest`;结果**只用于提示**,不下载也不安装,失败静默、绝不阻塞任何请求。
|
|
54
|
+
单元测试用 `WORKTODO_NO_UPDATE_CHECK=1` 完全关掉它(测试不该打网络)。
|
|
55
|
+
自动执行升级(发现新版后后台跑 `dsh plugin add`,重启生效)是下一步。
|
|
56
|
+
|
|
57
|
+
### 测试
|
|
58
|
+
|
|
59
|
+
- `smoke-host` 新增 1 例:`/list` 载荷的 `version`/`update` 字段齐全且 `hasUpdate` 在关闭检查时为 false。
|
|
60
|
+
|
|
61
|
+
## 0.1.4
|
|
62
|
+
|
|
63
|
+
### 修复(重要)
|
|
64
|
+
|
|
65
|
+
- **插件时好时坏地加载失败**:`src/store.mjs` 里探测官方存储服务的写法是
|
|
66
|
+
|
|
67
|
+
```js
|
|
68
|
+
ctx.get('storageDomain') ?? ctx.storageDomain // ← 错
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
当 `storageDomain` **尚未注册**时,`ctx.get()` 返回 `undefined`,于是落到 `ctx.storageDomain`——
|
|
72
|
+
而直接访问未在 `inject` 里声明的服务会被 cordis 守卫**抛错**(`cannot get property "storageDomain" without inject`)。
|
|
73
|
+
异常一路冒到 `apply`,**整个插件挂载失败**:工具消失、路由全 404。
|
|
74
|
+
因为服务注册与服务初始化存在竞态,表现就是「有时能起来、有时起不来」,重启也不一定好。
|
|
75
|
+
|
|
76
|
+
现在只保留安全的 `ctx.get('storageDomain')`(探测不到就回退 JSON 文件),并补了回归用例
|
|
77
|
+
——它用一个「访问 `storageDomain` 就抛错」的假 ctx 模拟 cordis 守卫,**旧写法下这条测试必红**。
|
|
78
|
+
|
|
79
|
+
## 0.1.3
|
|
80
|
+
|
|
81
|
+
### 新增
|
|
82
|
+
|
|
83
|
+
- **排序模式**:面板顶部新增「手动 / 优先级 / 创建时间」三档排序(`worktodo_list` 也开放了同样的 `sort` 参数)。
|
|
84
|
+
- `manual`(默认):尊重你拖动过的顺序;**没拖过的条目自动退回**优先级 → 截止日期 → 创建时间,所以一上手看到的顺序依然合理;
|
|
85
|
+
- `priority`:高优先级在前,同优先级按截止日期,无日期垫底;
|
|
86
|
+
- `created`:最近添加的在前。
|
|
87
|
+
三种模式都保持「已完成永远沉底」。
|
|
88
|
+
- **拖动排序**:按住任意一行拖到目标位置即可调整顺序。拖动时会**自动切到手动模式**(否则松手后看起来"没生效");
|
|
89
|
+
落序由宿主在校验后写盘(`POST /worktodo/reorder`,收到完整 id 顺序,只写真正变了的记录);
|
|
90
|
+
传了不存在的 id 会**显式失败**(`not-found`),不会静默改一半。
|
|
91
|
+
|
|
92
|
+
### 测试
|
|
93
|
+
|
|
94
|
+
- `verify-records` 新增 2 例:三种排序模式的顺序、`applyManualOrder` 的纯函数语义(含"没拖过的垫后");
|
|
95
|
+
- `smoke-host` 新增 2 例:`/list?sort=created` 的顺序、`POST /reorder` 落盘并在 manual 模式生效(含坏 id 的显式失败)。
|
|
96
|
+
|
|
97
|
+
## 0.1.2
|
|
98
|
+
|
|
99
|
+
### 新增
|
|
100
|
+
|
|
101
|
+
- **按项目管理待办**:面板顶部新增「**按截止 / 按项目**」视图切换。
|
|
102
|
+
「按项目」视图里每个项目是一个可折叠分组,标题显示「未完成/总数 · 逾期 N」;
|
|
103
|
+
没写项目的记录归入「未归类」并**永远排在最后**。
|
|
104
|
+
排序规则:未完成多的项目在前 → 未完成里最早截止日期更早的在前 → 名字字典序。
|
|
105
|
+
宿主侧 `/worktodo/list` 新增 `projectGroups` 字段(`groupByProject`),且**不受 `project` 参数收窄**——
|
|
106
|
+
这样面板一次就能拿到全部项目用于切换。
|
|
107
|
+
|
|
108
|
+
### AI 友好
|
|
109
|
+
|
|
110
|
+
- **给模型的用法指引**:通过官方 `ctx.systemPrompt.section()` 贡献一段提示(段名 `worktodo:guidance`,
|
|
111
|
+
`order` 取 3050——官方内置工具段是 1000–3000、`MCP_SERVERS` 是 3100,插在两者之间)。
|
|
112
|
+
内容讲清三件事:什么时候该用(用户说出承诺/截止日期,或发现超出本会话、仍需人跟进的待办)、
|
|
113
|
+
什么时候**不该**用(当前任务的步骤拆解属于会话内的 `todo_write`,两者互补)、
|
|
114
|
+
以及「加之前先查重」「做完用 `worktodo_done`」「标题写成祈使句」等约定。
|
|
115
|
+
- **批量登记**:新增 `worktodo_add_many`,一次调用登记多条;某条不合法只跳过那一条并把原因回传,
|
|
116
|
+
不影响其余条目(用户一口气说好几件事时省调用)。
|
|
117
|
+
|
|
118
|
+
### 测试
|
|
119
|
+
|
|
120
|
+
- `verify-records` 新增 4 例覆盖 `groupByProject`(未归类最后、未完成多者在前、桶内 total/open/overdue、空输入);
|
|
121
|
+
- `smoke-host` 新增 1 例断言 `/list` 载荷确实带 `projectGroups` 且形状正确。
|
|
122
|
+
|
|
123
|
+
## 0.1.1
|
|
124
|
+
|
|
125
|
+
### 修复(重要)
|
|
126
|
+
|
|
127
|
+
- **装出来的插件根本无法启动**:0.1.0 把运行期真正 import 的三个官方平台包(`@deepseek-ai/dsh-tools`、
|
|
128
|
+
`@deepseek-ai/dsh-storage-domain`、`@deepseek-ai/dsh-home-paths`)只声明为 `peerDependencies`,
|
|
129
|
+
于是从 npm / GitHub 装出来的包**没有任何可解析的平台包**,DSH 启动时该插件直接加载失败
|
|
130
|
+
(实测:工具全部消失,`worktodo_list` 报 `unknown tool`)。现在改为 `dependencies`——
|
|
131
|
+
实测从 GitHub 安装后,从插件自身位置三个包都能解析。
|
|
132
|
+
- **npm 包页面没有 README**:0.1.0 是经「暂存发布」(staged publishing)上线的,而实测那条路径**不会写入 registry 的 `readme` 字段**
|
|
133
|
+
(同机对照:普通 `publish` 的包 `readme` 有 8193 字符,本包 0 字符),于是包页面没有 README。
|
|
134
|
+
本版改为**直接发布**——OIDC 下同样不需要人类 2FA,所以并没有牺牲自动化。
|
|
135
|
+
|
|
136
|
+
### 文档
|
|
137
|
+
|
|
138
|
+
- 三份文档(README 中英、CHANGELOG)里补了**绝对仓库地址**的说明:提到 `docs/`、`tools/` 等目录时指向仓库
|
|
139
|
+
(这些文件不在 npm 包内)。npm 页面上的读者因此能找到出处,而不会撞上够不着的路径。
|
|
140
|
+
- `publish.yml` 的默认发布方式改为**直接发布**,同时保留手动「暂存 + 网页批准」入口。
|
|
141
|
+
|
|
3
142
|
## 0.1.0
|
|
4
143
|
|
|
5
144
|
首个可用版本。
|
|
@@ -43,7 +182,7 @@
|
|
|
43
182
|
- 新增可观测性:`/worktodo/health` 现在报告运行中的实际 `version` 与
|
|
44
183
|
`tools: { status, registered, names, error }`——工具静默没注册这类问题不用再翻日志猜。
|
|
45
184
|
|
|
46
|
-
### 测试(
|
|
185
|
+
### 测试(175 例,均不需要启动 DSH)
|
|
47
186
|
|
|
48
187
|
- `tools/verify-records.mjs`(22):日期归一化与相对日期、状态/优先级同义词、完成时间维护、
|
|
49
188
|
引用解析(id / 标题 / 前缀 / 歧义)、分组边界(本周日 vs 下周一)、统计口径、筛选、坏记录修复。
|
|
@@ -54,7 +193,7 @@
|
|
|
54
193
|
统计不随筛选变化、提升去重、变更通知。
|
|
55
194
|
- `tools/smoke-host.mjs`(26):假 ctx 里跑通 `apply` → 7 条路由 → 服务 → 存储的完整增删改查,
|
|
56
195
|
方法围栏与 `connection` 准入,失败路径(空标题、坏 JSON、未知 filter),health 自检字段,
|
|
57
|
-
|
|
196
|
+
7 个工具经**官方 `defineTool`** 校验注册并真实执行,以及 5 条「工具返回值必须无损」的断言——
|
|
58
197
|
判定用的是 **DSH 自己的校验器** `snapshotJsonValue`(来自 `@deepseek-ai/dsh-util-values`,
|
|
59
198
|
就是 `@deepseek-ai/dsh-tools` 报 "value is not lossless JSON" 时用的那一个函数),
|
|
60
199
|
并有一条专门断言「旧写法 `due: undefined` 必须被它拒绝」,用来证明这条守卫确实有牙齿。
|
package/README.en.md
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
# Work Todo · dsh-worktodo
|
|
2
2
|
|
|
3
|
+
|
|
3
4
|
**A work todo list that belongs to you, not to a session.** A dedicated DSH sidebar panel, plus `worktodo_*` tools so the agent reads and writes **the same** list you do.
|
|
4
5
|
|
|
5
|
-
> Works with **DSH 0.2.x** (tested on 0.2.0-rc.2) · **
|
|
6
|
+
> Works with **DSH 0.2.x** (tested on 0.2.0-rc.2) · runtime deps are **3 official platform packages only** (no third-party deps) · community plugin, unofficial
|
|
7
|
+
|
|
8
|
+
> **About the paths in this file**: references to `docs/`, `tools/` and similar point into the **repository** —
|
|
9
|
+
> those files are not part of the npm package. Repository: <https://github.com/olimc2016/dsh-worktodo>
|
|
6
10
|
|
|
7
11
|
## The gap it fills
|
|
8
12
|
|
|
@@ -33,7 +37,8 @@ dsh plugin --profile desktop add github:olimc2016/dsh-worktodo
|
|
|
33
37
|
|
|
34
38
|
This path is verified (see `docs/verification.md`): the browser half's build output `lib/client.js` is committed,
|
|
35
39
|
and the package declares no `prepare`/`install` build script, so a git install needs **no build authorization**
|
|
36
|
-
|
|
40
|
+
measurement (install from GitHub): **1 top-level package** plus the 3 official platform packages, about **12 MB** installed
|
|
41
|
+
(~8 MB of that is zod, pulled in by the official `@deepseek-ai/dsh-tools`), and no development dependencies.
|
|
37
42
|
no nested `node_modules`, and the installed tree matches the npm tarball file for file.
|
|
38
43
|
|
|
39
44
|
**Option 2: from npm** (once the package is published)
|
|
@@ -90,10 +95,15 @@ Pin your own path in `cordis.patch.yml`:
|
|
|
90
95
|
```bash
|
|
91
96
|
pnpm install # esbuild ships a prebuilt binary; no approve-builds needed
|
|
92
97
|
pnpm run build # build lib/client.js (browser half)
|
|
93
|
-
pnpm test #
|
|
98
|
+
pnpm test # 175 cases: data model / storage / service / host wiring and tools / client contract / client bundle / CI contract / privacy gate / catalog gate
|
|
94
99
|
pnpm run watch # incremental client build
|
|
95
100
|
```
|
|
96
101
|
|
|
102
|
+
Release flow (trusted publishing + staged approval) is documented in `docs/releasing.md`:
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
```
|
|
106
|
+
|
|
97
107
|
No DSH instance is needed to run the suite: `verify-records` (pure data), `verify-store` (real file IO plus a genuine **official `defineDomain` contract check**), `verify-service` (explicit statuses and boundaries), `smoke-host` (apply → routes → service → storage in a fake context, plus tool registration and execution with schemas validated by the **official `defineTool`**), `smoke-contract` (extracts the paths and field names the client actually sends and checks them against the host's real routes — catching silent failures where a mistyped field means, for instance, that due dates never save), `smoke-client` (bundle format, slot registration, and a first render that must not throw), and `verify-submission` (a local gate for the catalog PR: fields, filename, category and date, plus checks that only matter on the GitHub distribution path, such as whether every file a git install needs is actually tracked).
|
|
98
108
|
|
|
99
109
|
## License
|
package/README.md
CHANGED
|
@@ -2,7 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
**归你所有、跨会话持久的工作待办。** DSH 侧栏一个独立面板,agent 通过 `worktodo_*` 工具读写**同一份**列表。
|
|
4
4
|
|
|
5
|
-
> 兼容 **DSH 0.2.x**(0.2.0-rc.2 实测)·
|
|
5
|
+
> 兼容 **DSH 0.2.x**(0.2.0-rc.2 实测)· 运行期只依赖 **3 个官方平台包**(无任何第三方依赖)· 社区插件,非官方
|
|
6
|
+
|
|
7
|
+
> **关于本文里的路径**:提到 `docs/`、`tools/` 等目录时,指的是**仓库**里的文件——它们不在 npm 发布包内。
|
|
8
|
+
> 仓库地址:<https://github.com/olimc2016/dsh-worktodo>
|
|
6
9
|
|
|
7
10
|
---
|
|
8
11
|
|
|
@@ -35,7 +38,14 @@ dsh plugin --profile desktop add github:olimc2016/dsh-worktodo
|
|
|
35
38
|
|
|
36
39
|
这条路是实测过的(见 `docs/verification.md`):仓库里提交了浏览器半侧的构建产物 `lib/client.js`,
|
|
37
40
|
包内没有 `prepare`/`install` 这类构建脚本,所以 **git 安装不需要任何构建授权**,也不会把开发依赖装进来
|
|
38
|
-
|
|
41
|
+
——实测(从 GitHub 安装):顶层解析 **1 个包** + 3 个官方平台包,安装约 **12 MB**(其中约 8 MB 是官方 `@deepseek-ai/dsh-tools` 依赖的 zod),
|
|
42
|
+
包内含已构建的 `lib/client.js`,**无需构建授权**。
|
|
43
|
+
|
|
44
|
+
> **为什么平台包必须是 `dependencies` 而不是 peer**:0.1.0 曾只声明 peer,结果从 npm/GitHub 装出来的包里
|
|
45
|
+
> **没有任何可解析的平台包**,DSH 启动时该插件直接加载失败(工具全部消失)。0.1.1 起改为 `dependencies`——
|
|
46
|
+
> 实测安装后从插件自身位置三个包都能解析。
|
|
47
|
+
(注意:DSH 的插件安装器会额外在包目录里装一次开发依赖,本机观察到 22 MB;那是安装器行为、与包本身无关,
|
|
48
|
+
删掉不影响运行——见 `docs/verification.md`。)
|
|
39
49
|
|
|
40
50
|
**方式二:从 npm 装**(包发布后可用)
|
|
41
51
|
|
|
@@ -97,10 +107,15 @@ dsh plugin --profile desktop add dsh-worktodo
|
|
|
97
107
|
```bash
|
|
98
108
|
pnpm install # esbuild 用预编译二进制,无需 approve-builds
|
|
99
109
|
pnpm run build # 打 lib/client.js(浏览器半侧)
|
|
100
|
-
pnpm test #
|
|
110
|
+
pnpm test # 155 个用例:数据模型 / 存储 / 服务 / 宿主接线与工具 / 客户端↔宿主契约 / 客户端 bundle / CI 契约 / 隐私门禁 / 收录门禁
|
|
101
111
|
pnpm run watch # 改客户端时增量构建
|
|
102
112
|
```
|
|
103
113
|
|
|
114
|
+
发版流程(Trusted Publishing + 暂存批准)见仓库里的 `docs/releasing.md`:
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
```
|
|
118
|
+
|
|
104
119
|
测试策略:不用启动 DSH 就能跑完——
|
|
105
120
|
`verify-records`(纯数据)、`verify-store`(真实文件 IO + **官方 `defineDomain` 契约校验**)、
|
|
106
121
|
`verify-service`(显式状态与边界)、`smoke-host`(假 ctx 里跑通 apply → 路由 → 服务 → 存储,
|