dsh-tiddlywiki 0.17.0 → 0.19.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.
Files changed (43) hide show
  1. package/README.md +33 -20
  2. package/docs/seed-initialization.md +19 -9
  3. package/lib/client.js +66 -30
  4. package/lib/index.js +4077 -2323
  5. package/lib/index.js.map +1 -1
  6. package/package.json +12 -5
  7. package/src/client/editor-popup.ts +49 -3
  8. package/src/client/index.ts +87 -60
  9. package/src/client/knowledge-fab.ts +1 -1
  10. package/src/client/note-widget.ts +183 -39
  11. package/src/client/panel.ts +52 -14
  12. package/src/client/quick-note-dock.ts +17 -2
  13. package/src/client/session-summary.ts +53 -22
  14. package/src/client/settings-page.ts +23 -5
  15. package/src/client/sidebar-entry.ts +50 -13
  16. package/src/client/styles.ts +57 -11
  17. package/src/client/sync-button.ts +13 -4
  18. package/src/client/tool-views.ts +81 -1
  19. package/src/client/tw-frame.ts +21 -4
  20. package/src/client/ui-config.ts +9 -0
  21. package/src/host/admin.ts +126 -20
  22. package/src/host/clip-bridge.ts +334 -9
  23. package/src/host/config.ts +47 -11
  24. package/src/host/git.ts +28 -4
  25. package/src/host/http.ts +102 -3
  26. package/src/host/routes.ts +258 -36
  27. package/src/host/seed-all-articles.ts +5 -6
  28. package/src/host/seed-clip-bridge.ts +5 -6
  29. package/src/host/seed-home.ts +8 -9
  30. package/src/host/seed-menubar-theme.ts +5 -6
  31. package/src/host/seed-notes.ts +5 -6
  32. package/src/host/seed-render.ts +72 -66
  33. package/src/host/seed-send-to-agent.ts +62 -63
  34. package/src/host/seed-starter-docs.ts +6 -7
  35. package/src/host/seed-ui-styles.ts +6 -7
  36. package/src/host/seed-util.ts +42 -0
  37. package/src/host/seeds.ts +98 -15
  38. package/src/host/session-summary.ts +25 -4
  39. package/src/host/tools.ts +701 -54
  40. package/src/host/tw-api.ts +175 -27
  41. package/src/host/wiki.ts +73 -4
  42. package/src/index.ts +111 -62
  43. package/lib/client.bundle.js +0 -675
package/README.md CHANGED
@@ -25,15 +25,18 @@
25
25
  |---|---|
26
26
  | 🏠 **文档中心起步包** | 首次安装自动 seed:插件说明 + 「示例与文档」(主题汇总模板 / 教程 / 三个示例主题页),首页「📚 插件文档」栏一键查阅;**同名 tiddler 已存在一律安全跳过,绝不覆盖你的数据**(v0.16.22) |
27
27
  | 🎨 **自定义样式** | 「自定义样式」seed:编辑器美化 / 窄屏侧栏隐藏 / menubar 加高 / 批注弹窗等 5 张通用样式表,新 wiki 也能一键初始化(可选,v0.16.22) |
28
- | 🤖 **Agent 工具** | 10 个 `tiddlywiki_*` 工具:检索、读写、批量、重命名、删除、git 同步与冲突解决(v0.16.20 起检索/最近在**服务端**排除二进制附件,大 wiki 上从 515MB/17s 降到 ~0.4s) |
29
- | 📊 **回复流卡片** | 工具结果显示原生 TW 卡片;`[标题](/dsh-tiddlywiki/tw/#标题)` 点击直达 TW 面板 |
28
+ | 🤖 **Agent 工具** | 15 个 `tiddlywiki_*` 工具:检索(**相关度排序 + 命中处片段 + 字段过滤**)、读写、**增量追加**、批量、重命名、**软删除/回收站**、**反向链接**、**附件入库**、**知识库体检**、git 同步与冲突解决(v0.19.0;检索/最近仍在**服务端**排除二进制附件,大 wiki 上从 515MB/17s 降到 ~0.4s) |
29
+ | 🛡️ **不会被覆盖的写入** | `tiddlywiki_put(..., expectedModified)` 乐观并发:读取后若有人(在 TW 编辑器里)改过,写入被拒绝而不是静默覆盖;`tiddlywiki_delete` 默认**软删除进回收站**,`tiddlywiki_trash` 可恢复(v0.19.0) |
30
+ | 🔒 **写路由方法校验** | 每个写路由只接受自己的 HTTP 方法:跨站 `GET /sync`、`GET /restart`、`GET /upload` 一律 405 且无副作用(v0.19.0 修复了「任意网页一张 `<img>` 即可触发 pull/commit/push」的 CSRF 面) |
31
+ | 📊 **回复流卡片** | 工具结果显示原生 TW 卡片(**按笔记自己的内容类型渲染**:Markdown 笔记就是 Markdown,v0.18.0);`[标题](/dsh-tiddlywiki/tw/#标题)` 点击直达 TW 面板 |
30
32
  | 📤 **发送给 Agent** | TW 笔记工具栏一键把当前笔记注入所选 dsh 会话(可选工作模式/权限/附加说明) |
31
33
  | 🧭 **内嵌编辑器** | 中央列内嵌完整 TW 5 编辑器(同源代理,Tailscale/内网/域名/HTTPS 均可) |
32
34
  | 🗂️ **右侧边栏 Tab** | DSH 新右侧栏(rightbar):首页「TiddlyWiki 知识库」入口一键打开,与聊天并排;链接点击可直达(v0.16.21) |
33
35
  | 🧩 **Better Sidebar 共存** | 与 dsh-better-sidebar 侧边栏共存(其展开/收起按钮浮在 TW 面板之上);**不再向该侧边栏注册 TW tab**(v0.17.0 移除了 tab 注册,避免 tab kind 冲突) |
34
36
  | 📚 **会话知识库 Tab** | 每个会话顶部汇总本会话读写过的 wiki 笔记,TW 原生渲染(`/tw/render` 片段管线,v0.16.19) |
35
37
  | 📝 **快速笔记** | 输入框上方快捷按钮或右下角「知识库」FAB;原生编辑页或 Markdown 卡片两种模式;首页内置「快速记笔记(完整编辑器)」 |
36
- | 📌 **本地剪藏桥** | 可选「剪藏桥 + 书签小工具」:DSH 监听 127.0.0.1 端口接收剪藏请求(Host 校验防 rebinding),点书签弹出浮层——可改标题/编辑选中文字/**勾选图片**,一键写入知识库;文字成笔记(默认 `clip` 标签),图片由桥下载存为**二进制附件**(`type: image/*` + base64,笔记内 `[img[标题]]` 内嵌),随 wiki 自动进 git |
38
+ | 📌 **本地剪藏桥** | 可选「剪藏桥 + 书签小工具」:DSH 监听 127.0.0.1 端口接收剪藏请求(Host 校验防 rebinding),点书签弹出浮层——可改标题/编辑选中文字/**勾选图片**,一键写入知识库;文字成笔记(默认 `clip` 标签),图片由桥下载存为**二进制附件**(`type: image/*` + base64,笔记内 `[img[标题]]` 内嵌),随 wiki 自动进 git;图片下载有 **SSRF 守卫**(仅公网 http(s)、逐跳校验重定向,v0.18.0) |
39
+ | 🔐 **写操作防跨站** | 所有写路由(笔记/上传/同步/后台/代理)拒绝跨站请求(403),仅同源的 GUI 与内嵌 TW 可写;跨站 GET 与浏览器地址栏直达不受影响(v0.18.0) |
37
40
  | ✅ **待办四象限** | 首页看板:任务打 `todo` 标签即收录,拖动即可分类/完成(正文附 `q` 字段),逾期/今日到期自动统计 |
38
41
  | 🌗 **跟随主题** | 内嵌 TW 自适应 DSH 深浅主题(纯内存切换,不进 git) |
39
42
  | 🔄 **一键同步** | FAB「同步」一键 pull→commit→push,状态点实时反映 git 状态 |
@@ -72,18 +75,23 @@ dsh plugin --profile web add link:/path/to/dsh-tiddlywiki
72
75
 
73
76
  ## 📖 使用指南
74
77
 
75
- ### 🤖 Agent 工具(10 个)
78
+ ### 🤖 Agent 工具(15 个)
76
79
 
77
80
  | 工具 | 说明 |
78
81
  |---|---|
79
- | `tiddlywiki_search` | 检索(`query` + 可选 `tags[]/tag/since/type/limit`),返回标题/标签/修改时间/摘要 |
82
+ | `tiddlywiki_search` | 检索(`query` + 可选 `tags[]/tag/since/type/field/value/limit`),**按相关度排序**(标题命中 > 标签 > 正文命中次数),摘要取自**命中处上下文**而不是正文开头 |
80
83
  | `tiddlywiki_recent` | 最近修改的笔记(倒序),开工快速了解动态 |
81
- | `tiddlywiki_list_tags` | 现有非系统 tag 及计数 |
82
- | `tiddlywiki_get` | 读单个 tiddler 全文 |
83
- | `tiddlywiki_put` | 写/覆盖;未指定类型时自动默认 `text/markdown`(`$:/` 系统条目除外) |
84
- | `tiddlywiki_batch_put` | 批量写入(`overwrite=false` 跳过已存在) |
84
+ | `tiddlywiki_list_tags` | 现有非系统 tag 及计数(已排除只挂在二进制附件上的 tag) |
85
+ | `tiddlywiki_get` | 读单个 tiddler 全文(`modified` 以 ISO 返回,可直接用作 `expectedModified`) |
86
+ | `tiddlywiki_put` | 写/覆盖;未指定类型时自动默认 `text/markdown`(`$:/` 系统条目除外);`expectedModified` + `force` 提供乐观并发保护 |
87
+ | `tiddlywiki_batch_put` | 批量写入(`overwrite=false` 跳过已存在;单条失败不影响其余,逐条报错) |
88
+ | `tiddlywiki_append` | **增量追加**:`mode=append\|prepend`、`heading=某标题` 定位段落,写日志/批注无需读全文 |
85
89
  | `tiddlywiki_rename` | 重命名 + 尽量同步其他条目里的引用 |
86
- | `tiddlywiki_delete` | 删除(幂等) |
90
+ | `tiddlywiki_delete` | 删除(幂等)。默认**软删除**进 `$:/dsh-tiddlywiki/trash/`,`permanent=true` 才真删 |
91
+ | `tiddlywiki_trash` | 回收站:`action=list\|restore\|empty` |
92
+ | `tiddlywiki_backlinks` | 反向链接:谁用 `[[标题]]`/`{{标题}}` 引用了它、谁把它当标签 |
93
+ | `tiddlywiki_attach` | 把**本机文件或公网 http(s) 地址**存成二进制附件(图片/PDF/…),可嵌入某篇笔记;URL 走 SSRF 守卫 |
94
+ | `tiddlywiki_lint` | 知识库体检:垃圾标签 / 死链 / 空笔记 / 缺内容类型的类 Markdown 笔记 |
87
95
  | `tiddlywiki_git_sync` | `action: pull\|push\|sync` |
88
96
  | `tiddlywiki_git_resolve` | pull 冲突后按 tiddler 二选一(`keep-local\|keep-remote`) |
89
97
 
@@ -152,7 +160,7 @@ seed 是把「wiki 里预置内容」随插件分发的机制:**ONE-SHOT(只
152
160
  tag: "inbox" # 快速笔记默认 tag
153
161
  bridge:
154
162
  enabled: false # 本地剪藏桥(书签小工具);保存后立即生效
155
- port: 8618 # 监听端口(127.0.0.1;改后需重启 dsh web)
163
+ port: 8618 # 监听端口(127.0.0.1;改后需重启 dsh web 才绑定新端口)
156
164
  token: "" # 共享口令;非空时校验书签的 x-clip-token 头(强烈建议设置)
157
165
  tag: "clip" # 剪藏笔记默认 tag
158
166
  ui:
@@ -171,10 +179,10 @@ seed 是把「wiki 里预置内容」随插件分发的机制:**ONE-SHOT(只
171
179
  uiLanguage: "" # 留空不干预;"zh-Hans" 自动启用简体
172
180
  auth:
173
181
  username: "" # 默认 loopback 匿名;暴露到非回环才需要
174
- password: ""
182
+ password: "" # 非空时插件内置客户端/就绪探测/浏览器代理都带 Basic 认证(v0.18.0 起真正可用)
175
183
  ```
176
184
 
177
- > **运行时配置**:设置页写入的 `$:/plugins/dsh-tiddlywiki/config` tiddler 是 `config:` 块之上的覆盖层(tiddler 优先、随 wiki git 同步),改 note tag / git / ui 开关无需动 cordis。
185
+ > **运行时配置**:设置页写入的 `$:/plugins/dsh-tiddlywiki/config` tiddler 是 `config:` 块之上的覆盖层(tiddler 优先、随 wiki git 同步),改 note tag / git / ui 开关**以及剪藏桥端口**都无需动 cordis(端口改动仍需重启 dsh web 重新绑定监听)。
178
186
 
179
187
  ---
180
188
 
@@ -191,13 +199,16 @@ TW 子进程只监听 **127.0.0.1 回环**;Agent 工具/快速笔记/同步都
191
199
  ```bash
192
200
  npm install
193
201
  npm run typecheck # tsc --noEmit
194
- npm run build # clean + host tsdown + client tsdown + wrap
202
+ npm run build # clean + host tsdown + client tsdown + wrap(wrap 会校验 id 与体积 <900KB)
195
203
  npm run selftest # headless:spawn TW → REST 读写 → git → 退出回收
196
- node scripts/verify-clip-bridge.mjs # 剪藏桥 headless 验收(build 后跑)
204
+ npm run smoke:client # client bundle 的 module-loader 形状冒烟
205
+ node scripts/verify-send-to-agent-bundle.mjs # bundle 字段 + 源件逐字一致
206
+ node scripts/verify-seed-send-to-agent.mjs # 全新 wiki 上的 seed E2E
207
+ node scripts/verify-clip-bridge.mjs # 剪藏桥 headless 验收(含 SSRF 守卫)
197
208
  node scripts/verify-seeds-admin.mjs # /admin/seeds 状态与 run 的 E2E
198
209
  ```
199
210
 
200
- **改 bundle/seed 的再生成流水线**(不要手改 `seed-*.ts` 里的生成常量):
211
+ **改 bundle/seed 的再生成流水线**(不要手改 `seed-*.ts` 里的生成常量;bundle 版本号只在 `scripts/bundle/versions.mjs` 定义一处):
201
212
 
202
213
  ```bash
203
214
  # 发送给 Agent 按钮(改 scripts/bundle/send-to-agent/ 后)
@@ -205,13 +216,13 @@ node scripts/build-send-to-agent-bundle.mjs
205
216
  node scripts/gen-seed-send-to-agent.mjs scripts/bundle/send-to-agent.bundle.json src/host/seed-send-to-agent.ts
206
217
  node scripts/verify-send-to-agent-bundle.mjs
207
218
 
208
- # 渲染路由(改 scripts/bundle/render/server-routes/render.js 后)
219
+ # 渲染路由(改 scripts/bundle/render/server-routes/render.js 后;版本在 versions.mjs)
209
220
  node scripts/build-render-bundle.mjs
210
221
  node scripts/gen-seed-render.mjs scripts/bundle/render.bundle.json src/host/seed-render.ts
211
222
 
212
- # 首页(改 wiki 的 🏠 主页/所有标签/标签笔记 .tid 后;必须 --strip-private,
213
- # 产出通用版:剥离作者私有人口 + 注入「📚 插件文档」栏)
214
- node scripts/gen-seed-home.mjs '<wiki>/tiddlers/🏠 主页.tid' '<wiki>/tiddlers/所有标签.tid' '<wiki>/tiddlers/标签笔记.tid' src/host/seed-home.ts --strip-private
223
+ # 首页(改 wiki 的 🏠 主页/所有标签/标签笔记 .tid 后;默认就剥离作者私有人口 +
224
+ # 注入「📚 插件文档」栏,确要保留私有内容才加 --keep-private)
225
+ node scripts/gen-seed-home.mjs '<wiki>/tiddlers/🏠 主页.tid' '<wiki>/tiddlers/所有标签.tid' '<wiki>/tiddlers/标签笔记.tid' src/host/seed-home.ts
215
226
 
216
227
  # 自定义样式(改 wiki 的样式 .css + .meta 后;tag 自动收窄为 $:/tags/Stylesheet)
217
228
  node scripts/gen-seed-ui-styles.mjs '<wiki>/tiddlers/<样式.css>' … src/host/seed-ui-styles.ts
@@ -278,6 +289,8 @@ lib/ # 预构建产物(发布含 lib/**,提交入库;
278
289
 
279
290
  > 最近几个主要版本的一句话记录(完整变更见 [Releases](https://github.com/bbqisbbq/dsh-tiddlywiki/releases) / git log)。
280
291
 
292
+ - **v0.19.0**(2026-09-11):**按代码审计结论做的全量修复 + 一批新能力**(安全 / 数据安全 / 工具层 / 客户端 / 工程)。**安全**:① 每个路由现在**校验 HTTP 方法**(此前 `http.ts` 主动放行 GET、宿主按 pathname 分发,于是 `GET /dsh-tiddlywiki/sync` 会 pull+commit+**push**、`GET /restart` 重启 TW、`GET /upload` 落文件——任意网页一张 `<img>` 即可触发;实测复现,现已一律 405 且无副作用);② 剪藏桥 SSRF 守卫的 IPv6 判定改为**按字节解析**(此前 `::ffff:7f00:1`、`0:0:0:0:0:0:0:1`、`::0:1` 等回环写法全部放行——实测复现);图片下载改为**逐跳 pin 住已校验的 IP**(堵 DNS rebinding TOCTOU)、**流式限长**(不再先全量缓冲再判 15MB)、禁用透明解压;③ TW 子进程的 spawn 日志**不再写明文口令**(该日志经无需认证的 `GET /status` 返回),`/status` 还会脱敏 git remote 里的 token、剪藏桥健康接口不再回显 port/tag/tokenSet、`/get` 不再暴露插件配置 tiddler、`/agent/sessions` 补上 token 守卫、token 比较改常数时间、`/tw` 代理改为**流式转发**(大附件不再整包进内存)、上传拒绝 html/svg 等可在同源执行的文件、`/note`/`/edit` 拒绝 `$:/` 标题。**数据安全**:④ 新增 `tiddlywiki/markdown` **插件自举**——全新 wiki 是用 `--init server` 建的,不含 markdown 插件,而插件默认把每篇笔记写成 `text/markdown`,此前新用户开箱即见 Markdown 源码;⑤ `tiddlywiki_put` 覆盖已有笔记时**不再丢掉原有的标签与自定义字段**(PUT 是整体替换,旧实现只发 title+text;单条 GET 的自定义字段还嵌套在 `fields` 里,一并修掉);⑥ 新增**乐观并发**:`expectedRevision`/`expectedModified` + `force`,人类在 TW 编辑器里的改动不再被静默覆盖;⑦ `tiddlywiki_delete` 默认**软删除进回收站**(`tiddlywiki_trash` 可 list/restore/empty);⑧ `readWikiInfo` 只把 ENOENT 当「没有配置」(此前读失败=空配置,设置页保存会整文件覆盖 `tiddlywiki.info`),写入改为备份 + 原子替换;seed 的 `tw-web-host` check 不再吞错;重启 TW 前用**flush 哨兵**排出 syncer 队列(force 重新初始化曾随机丢掉 `tw-web-host`)。**工具层(10 → 15 个)**:新增 `tiddlywiki_append`(增量追加 / 段落定位)、`tiddlywiki_backlinks`、`tiddlywiki_attach`(本机文件或公网 URL → 二进制附件)、`tiddlywiki_lint`(垃圾标签 / 死链 / 空笔记 / 缺内容类型)、`tiddlywiki_trash`;`search` 改为**相关度排序 + 命中处上下文片段 + 字段过滤 + limit 上限 + TW 紧凑日期解析**(此前 `since` 过滤恒为空)、`list_tags` 不再统计只挂在二进制附件上的标签、`batch_put` 的单条失败不再被参数预校验整批打断、列表加短 TTL 缓存。**客户端**:草稿卸载/刷新前落盘、草稿按窗口分键(不再跨标签页互相覆盖)、`session-summary` 自愈循环与卸载后 setState 修复、中央面板 `hidden` 状态修正、三个常驻定时器加上停止条件、wiki 链接不再吞掉 Ctrl/中键、编辑器弹窗补 `role=dialog` 与焦点、列表项键盘可达、21 处 `:focus-visible`、移动端 `touch-action`、`numField` 的 `0` 不再被吞。**工程**:新增 **GitHub Actions CI**(静态检查 + 自测 + 单元 + E2E 四档,含 `git diff --exit-code -- lib/` 抓「改了 src 忘了 build」)、9 个新验收脚本(auth 模式此前零覆盖、工具层、seed 读失败反例、git 冲突、崩溃自愈、大 wiki、render bundle 逐字节、发布包内容、版本一致性)、`npm run verify:*` 方便本地一键跑、`lib/client.bundle.js` 不再入库、AGENTS 的 `grep @deepseek-ai` 检查修正为「真实 import」。**升级提示**:重启 dsh web 后新会话生效;客户端改动需刷新页面。
293
+ - **v0.18.0**(2026-09-10):**一轮全量代码审计后的修复版**(数据安全 / 安全面 / 前端稳定性 / 工程卫生,共 40+ 项)。**数据不再静默丢失**:① seed 只在**真的 404** 时才认为条目缺失(此前任何读取错误都被当「不存在」,瞬时故障会让非 force 的启动 seed 覆盖你改过的同名笔记、`$:/DefaultTiddlers`、send-to-agent / render bundle);② `wiki/.gitignore` 不再每次启动被整份重写(用户自定规则改前会被冲掉);③ 配置 tiddler 读失败不再清空内存覆盖层(随后在设置页保存一项配置会丢掉其余全部覆盖);④ 只有 **render-route 真的重写后**才重启 TW,且要等它落盘(否则重启会丢掉未 flush 的写入——这条是本版新引入又被测试抓出的回归)。**正确性**:`/render` 现在按 tiddler 自己的 `type` 渲染——**Markdown 笔记在回复流卡片/汇总里终于按 Markdown 渲染**(此前硬编码 wikitext,`## 现象` 会被当成 wikitext 列表,实测复现)。**安全**:所有写路由(`/admin/*`、`/note`、`/edit`、`/upload`、`/sync`、`/restart`、`/api`、`/tw` 的写方法)加**同源/CSRF 守卫**(跨站写请求 403,跨站 GET 不受影响);剪藏桥图片下载加 **SSRF 守卫**(仅公网 http(s),逐跳校验重定向,拒绝回环/内网/云元数据地址);`bridge.port` 设置页改动现在**真的生效**(此前只读 cordis 基座);`auth.username/password` 从此**可用**(内置 REST 客户端与就绪探测带 Basic 认证,代理转发 `WWW-Authenticate` 让浏览器弹登录框,此前配置了用户名会让插件 20s 后启动失败)。**前端**:编辑器弹窗不再因同草稿重开而整机重载、并纳入面板互斥;中央面板自愈列元素重建;右栏 Tab 重新可见会重新探测状态;侧边栏入口插入不再抛 `NotFoundError` 连带拖垮 FAB/面板;同步中不再被 30s 轮询覆盖状态;`injectStyles` 可卸载(热重载拿到新样式);每处 mount 独立 try/catch;面板的 DOM 观察/滚动测量合并到 requestAnimationFrame(流式输出时不再每帧强制样式重算)。**工具与仓库**:`put`/`batch_put` 不再把读取失败当新条目而误打 `agent-written`,`fields` 不能覆盖 `title/text/tags`,`batch_put` 逐条报告失败;git 的 commit 与 pull 串行化(不再争 `.git/index.lock`);`/status` 的 git 摘要加 2s 缓存(每次调用少跑 5 个 git 进程);请求中途断开不再挂住路由;自动端口被占时会重新探测;`tiddlywiki.info` 损坏不再让后台 500;会话汇总对后代会话/条目数设上限。**工程卫生**:bundle 版本单一来源(`scripts/bundle/versions.mjs`,渲染路由 0.2.0)、生成器从 bundle 读版本(外层 0.3.2 漂移修正为 0.3.4)、发布包不再带 `client.bundle.js` 中间产物、`verify-*` 假阳性修复(未 await 的用例、被当成断言的 console.log)、selftest 失败也会回收 TW 子进程、`gen-seed-home` 默认剥离私有人口、`verify-menubar-theme` 不再默认打作者本机端口。
281
294
  - **v0.17.0**(2026-09-10):**移除:DSH Better Sidebar(dsh-better-sidebar)Tab 集成**。旧版通过 `ctx.betterSidebar.registerTab({id:'dsh-tiddlywiki'})` 注册的 tab kind 会与其它注册方冲突,浏览器控制台报 `sidebarRight: tab kind "dsh-tiddlywiki" is already registered (extension)`;本版**整体删除**该注册路径(删除 `better-sidebar-tab.ts`、client 入口的挂载块,以及 `ui.showBetterSidebarTab` 配置项/设置页开关),插件不再引用 `ctx.betterSidebar` 服务。与 dsh-better-sidebar 的**界面共存**(中央面板 z-index 让位于其侧边栏按钮)保留;右侧边栏入口请用 DSH 原生 rightbar(`ui.showRightbarTab`)。**更新后刷新页面**生效;旧版可临时用 `ui.showBetterSidebarTab=false` 规避冲突。
282
295
  - **v0.16.28**(2026-09-10):**修:拖拽版剪藏书签在知乎等真实页面报 `SyntaxError: Unexpected token ';'`**。根因(真实 Chrome 实验证实):0.16.27 把书签 href 做 **HTML 实体转义**(`&quot;`/`&amp;`/`&lt;`),但浏览器的 `a.href` **不做实体还原**——拖拽成书签后存的就是实体文本,执行时即解析失败。修复:href 改为 **percent-encoding**(`CLIP_BRIDGE_DRAG_HREF`,属性里只剩 `%XX`,天然无需任何属性转义);Chrome 执行 `javascript:` URL 前会 percent 解码(实测通过)。浏览器 E2E 升级为**直接以编码 href 走 `location.href` 执行**(完全等价拖拽书签的执行路径)并断言浮层弹出;静态验收改为 `decodeURIComponent(href) === 代码常量` 一致性校验。行为不变——**已拖过旧版书签的用户需重新初始化 seed 后重新拖一次**(旧书签仍然坏的,因为里面的代码是实体文本)。
283
296
  - **v0.16.27**(2026-09-10):**剪藏书签支持「拖拽安装」**。seed 文档新增一个**可拖拽按钮**(markdown 内嵌原始 HTML 锚点,href 即书签代码)——按住拖到浏览器书签栏/地址栏松手即装好,免去复制粘贴;代码 fence 保留作兜底。书签代码抽成单一常量 `CLIP_BRIDGE_BOOKMARKLET`(锚点 href 做 HTML 实体转义),并新增**同步一致性校验**(`verify-clip-bridge.mjs`:href 解码后与代码逐字相等)与**浏览器 E2E**(`verify-clip-bridge-browser.mjs`:真实 TW + 无头 Chrome 渲染真实 seed 文档,断言 javascript: href 原样保留 / draggable / 解码一致 / 真浏览器里执行书签弹出浮层 / 无 JS 异常)。
@@ -57,9 +57,10 @@ interface SeedDef {
57
57
  | `all-articles` | `seed-all-articles.ts` → `seedAllArticles` / `unseedAllArticles` | 「所有文章」(tag `索引`)——两列分页总览,每页条数实时读 `ui.allArticles.pageSize`(默认 10) | `$:/plugins/dsh-tiddlywiki/seed-all-articles` | 可选 |
58
58
  | `ui-styles` | `seed-ui-styles.ts` → `seedUiStyles` / `unseedUiStyles` | 5 张通用样式表(只带功能 tag `$:/tags/Stylesheet`,剥离 wiki 本地标签与个人数据):编辑器美化、标题与按钮区分开、侧边栏窄屏自动隐藏、批注弹窗、menubar 顶栏加高 | `$:/plugins/dsh-tiddlywiki/seed-ui-styles` | 可选 |
59
59
  | `menubar-theme` | `seed-menubar-theme.ts` → `seedMenubarTheme` / `unseedMenubarTheme` | `$:/plugins/dsh-tiddlywiki/menubar-theme`(tag `$:/tags/Stylesheet`)——覆盖 tiddlywiki/menubar 顶栏:把 `<<colour menubar-background>>` 的「默认色映射蓝色」改为跟随活动 palette 的 `background`/`foreground`,随 DSH 主题切换(`$:/palette` 翻转)自动换色 | `$:/plugins/dsh-tiddlywiki/seed-menubar-theme` | 可选 |
60
+ | `clip-bridge` | `seed-clip-bridge.ts` → `seedClipBridge` / `unseedClipBridge` | 「本地剪藏桥 + 书签小工具」使用说明(Markdown 文档,带书签代码 / 启用步骤 / 安全说明,tag `dsh-docs`)——真功能在 `clip-bridge.ts` 运行时代码里 | `$:/plugins/dsh-tiddlywiki/seed-clip-bridge` | 可选 |
60
61
  | `tw-web-host` | `seeds.ts` 内联 | `$:/config/tiddlyweb/host` → `/dsh-tiddlywiki/tw/` | 无 marker(ensure 型,见 §4) | **核心** |
61
62
 
62
- > ℹ️ `home-index` 的 seed 版首页是**通用版**:生成时用 `--strip-private` 剥离了作者 wiki 里的个人元素(主题页 tabs、书籍书架入口等),并内置「📚 插件文档」tabs 栏(`[tag[dsh-docs]!is[system]]`,默认展开插件说明)。作者自己的 wiki 首页不受影响(seed 是 ONE-SHOT,不会覆盖)。
63
+ > ℹ️ `home-index` 的 seed 版首页是**通用版**:生成脚本**默认**剥离作者 wiki 里的个人元素(主题页 tabs、书籍书架入口等,仅 `--keep-private` 才原样嵌入),并内置「📚 插件文档」tabs 栏(`[tag[dsh-docs]!is[system]]`,默认展开插件说明)。作者自己的 wiki 首页不受影响(seed 是 ONE-SHOT,不会覆盖)。
63
64
 
64
65
  ### 统一入口(`src/index.ts` 导出)
65
66
 
@@ -210,13 +211,22 @@ DSH 设置 →「TiddlyWiki 知识库」→ 最底部「**初始化(一次性
210
211
  seed 的内容以**内嵌常量**形式随插件发布,修改来源后需重新生成:
211
212
 
212
213
  ```bash
213
- # 改了 wiki 里的「发送给 Agent」按钮 bundle($:/plugins/dsh/send-to-agent):
214
- node scripts/gen-seed-send-to-agent.mjs '<wiki>/tiddlers/$__plugins_dsh_send-to-agent.json' src/host/seed-send-to-agent.ts
214
+ # 改了「发送给 Agent」按钮的源件(scripts/bundle/send-to-agent/ 下 startup.js / button.tid /
215
+ # icon.svg / item-template.tid)——三段式:build → gen → verify:
216
+ node scripts/build-send-to-agent-bundle.mjs # 1) build → scripts/bundle/send-to-agent.bundle.json
217
+ node scripts/gen-seed-send-to-agent.mjs scripts/bundle/send-to-agent.bundle.json src/host/seed-send-to-agent.ts # 2) gen → 内嵌常量(外层 version 从 bundle 内层 plugin.info 读取)
218
+ node scripts/verify-send-to-agent-bundle.mjs # 3) verify(字段 + 源件逐字一致 + 版本常量)
219
+
220
+ # 改了原生渲染路由源件(scripts/bundle/render/server-routes/render.js)——同样三段式:
221
+ node scripts/build-render-bundle.mjs # 1) build → scripts/bundle/render.bundle.json
222
+ node scripts/gen-seed-render.mjs scripts/bundle/render.bundle.json src/host/seed-render.ts # 2) gen(外层 version 同样从 bundle 内层 plugin.info 读取)
223
+ # 3) verify:无独立 verify 脚本,/render 行为由 selftest 5c2 段覆盖
224
+ # (两个 bundle 的版本号单一来源:scripts/bundle/versions.mjs)
215
225
 
216
226
  # 改了 wiki 首页(🏠 主页 / 所有标签 / 标签笔记):
217
- # 推荐带 --strip-private:剥离作者私有人口(主题页 tabs / 主题汇总死链 / 书籍书架)
218
- # 并注入「📚 插件文档」tabs 栏,产出通用版 seed 首页
219
- node scripts/gen-seed-home.mjs '<wiki>/tiddlers/🏠 主页.tid' '<wiki>/tiddlers/所有标签.tid' '<wiki>/tiddlers/标签笔记.tid' src/host/seed-home.ts --strip-private
227
+ # 默认即剥离作者私有人口(主题页 tabs / 主题汇总死链 / 书籍书架)并注入「📚 插件文档」tabs 栏,
228
+ # 产出通用版 seed 首页;仅作者本机想原样嵌入时才传 --keep-private(绝不用于发布)。
229
+ node scripts/gen-seed-home.mjs '<wiki>/tiddlers/🏠 主页.tid' '<wiki>/tiddlers/所有标签.tid' '<wiki>/tiddlers/标签笔记.tid' src/host/seed-home.ts
220
230
 
221
231
  # 改了 wiki 里的自定义样式(.css + .meta,tag 只保留 $:/tags/Stylesheet):
222
232
  node scripts/gen-seed-ui-styles.mjs '<wiki>/tiddlers/编辑器美化 CSS.css' '<wiki>/tiddlers/标题与按钮区分开.css' '<wiki>/tiddlers/侧边栏窄屏自动隐藏.css' '<wiki>/tiddlers/批注弹窗样式.css' '<wiki>/tiddlers/menubar 顶栏加高样式.css' src/host/seed-ui-styles.ts
@@ -232,7 +242,7 @@ node scripts/gen-seed-ui-styles.mjs '<wiki>/tiddlers/编辑器美化 CSS.css' '<
232
242
  npm run typecheck && npm run build && npm run selftest
233
243
  ```
234
244
 
235
- > PowerShell 注意:含 `$` 的路径(如 `$__plugins_dsh_send-to-agent.json`)要用**单引号**包裹,否则 `$` 会被当作变量展开。
245
+ > PowerShell 注意:含空格/中文的 wiki 路径(如 `'<wiki>/tiddlers/menubar 顶栏加高样式.css'`)要用**单引号**包裹,否则会被拆成多个参数。
236
246
 
237
247
  **文档合集约定(日常新增文档 seed 时)**:任何新的 TW 侧说明/模板/示例类内容,都走 seed(ONE-SHOT + 同名跳过),并给 tiddler 打 **`dsh-docs`** 标签——首页「📚 插件文档」栏自动收录,用户无需配置。doc-note 与 starter-docs 是 `startup: true` 起步项(首次安装默认写入),其余文档类内容按需要可设起步或可选。
238
248
 
@@ -249,8 +259,8 @@ npm run typecheck && npm run build && npm run selftest
249
259
  ## 8. 验证
250
260
 
251
261
  - `npm run typecheck` / `npm run build`:编译与打包;
252
- - `npm run selftest`:5d 段覆盖注册表清单(9 项,含 `core` / `removable` / `startup`)、**启动只 seed 核心 + 起步项(5 项)且不碰可选项**、手动全跑只写缺失、单跑幂等、force 重写、unknown id、tw-web-host 三分支(custom 保留 / force 写回 / legacy 修复)、**反初始化**(单移除 / 核心拒绝 / unknown / 全部移除保留核心)——另含 starter-docs 安全跳过、ui-styles 仅功能 tag、seed 版首页剥离私有人口 + 文档栏等断言;
253
- - `node scripts/verify-seeds-admin.mjs`:全新 wiki + 真实 HTTP,端到端验证 `GET /admin/seeds` 状态流转(9 项全缺失 → 启动后核心+起步就绪、可选项仍缺失)与 `POST /admin/seeds/run`(force 单跑恢复被改坏的首页、非 force 不覆盖用户内容、force-all 恢复代理基址、unknown id 400)+ `POST /admin/seeds/remove`(移除非核心、核心 400、remove-all 仅剩核心)。
262
+ - `npm run selftest`:5d 段覆盖注册表清单(10 项,含 `core` / `removable` / `startup`)、**启动只 seed 核心 + 起步项(5 项)且不碰可选项**、手动全跑只写缺失、单跑幂等、force 重写、unknown id、tw-web-host 三分支(custom 保留 / force 写回 / legacy 修复)、**反初始化**(单移除 / 核心拒绝 / unknown / 全部移除保留核心)——另含 starter-docs 安全跳过、ui-styles 仅功能 tag、seed 版首页剥离私有人口 + 文档栏等断言;
263
+ - `node scripts/verify-seeds-admin.mjs`:全新 wiki + 真实 HTTP,端到端验证 `GET /admin/seeds` 状态流转(10 项全缺失 → 启动后核心+起步就绪、可选项仍缺失)与 `POST /admin/seeds/run`(force 单跑恢复被改坏的首页、非 force 不覆盖用户内容、force-all 恢复代理基址、unknown id 400)+ `POST /admin/seeds/remove`(移除非核心、核心 400、remove-all 仅剩核心)。
254
264
 
255
265
  ---
256
266