dsh-tiddlywiki 0.26.6 → 0.26.7
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/README.md +1 -0
- package/lib/client.js +27 -27
- package/lib/index.js +44 -3
- package/lib/index.js.map +1 -1
- package/package.json +2 -2
- package/src/client/endpoints.ts +27 -0
- package/src/client/note-widget.ts +8 -5
- package/src/client/status-cache.ts +7 -0
- package/src/client/tw-frame.ts +20 -4
- package/src/host/http.ts +34 -1
- package/src/host/routes.ts +16 -3
package/README.md
CHANGED
|
@@ -419,6 +419,7 @@ lib/ # 预构建产物(发布含 lib/**,提交入库;
|
|
|
419
419
|
|
|
420
420
|
> 最近几个主要版本的一句话记录(完整变更见 [Releases](https://github.com/bbqisbbq/dsh-tiddlywiki/releases) / git log)。
|
|
421
421
|
|
|
422
|
+
- **v0.26.7**(2026-09-26):**修「DSH 桌面版里 TW 面板没有『添加条目』按钮」——嵌入式 TW 被渲染在自定义 scheme 上,于是它根本没有同步器**。现象(用户报障,桌面版):TW 面板能看能搜,但页面控件里 **添加条目 / 添加日志 / 添加图片 / 导入 / 条目管理器** 整排不见,单条笔记的 **编辑 / 克隆 / 删除** 也不见,像装了个只读版 TW。**根因不在本插件,而在 TW 内核的一处协议判定 + 桌面版新增的渲染 scheme**:TiddlyWiki 自己的 TiddlyWeb sync adaptor 只在**文档协议以 `http` 开头**时才导出自己(`plugins/tiddlywiki/tiddlyweb/tiddlywebadaptor.js`:`if($tw.browser && document.location.protocol.substr(0,4) === "http")`);而桌面版用自定义 scheme `dsh-app:` 渲染界面(已在本机运行中的 Electron 渲染进程命令行里核实 `--standard-schemes=dsh-app --secure-schemes=dsh-app …`),于是 iframe 里的 TW **没有 syncadaptor → 没有 `$tw.syncer`**:`$:/status/IsReadOnly` 永远没人写,TW 自己的只读样式表 `$:/plugins/tiddlywiki/tiddlyweb/readonly`(`<$reveal … default="yes">`,**状态未知即当只读**)就把那批按钮 `display:none` 掉;同时 saver 退化成本地 `dirtyTracking`,**在那儿做的编辑根本存不回 wiki**。实测复现(不依赖桌面版):把同一份 wiki 页面用 `file://` 打开(同样非 http),+ 同样消失——所以这不是「按钮坏了」,而是「这个文档里 TW 没有同步器」。**修复思路:让嵌入式 TW 跑在真正的 http origin 上**。① 宿主 `/status` / `/edit` / `/session/summary` 在原有相对字段旁,新增**绝对孪生字段** `twProxyAbsolute` / `twUrlAbsolute`(`absoluteHostBase()`,由请求 `Host` 头推导;脏头一律拒绝 `/^[A-Za-z0-9.\-[\]:]+$/`,避免把路径/凭据拼进回给浏览器的 URL);② 客户端新增 `resolveTwUrl()`(`endpoints.ts`)——**页面本身是 http(s) 时继续走相对路径**(loopback / 局域网 / Tailscale / 域名 / HTTPS 行为一字不变,绝不把 https 页面改源),**只有页面不是 http(s) 时**才改用宿主回环 http 基址,于是桌面版 iframe 里 TW 的协议变成 `http:`,sync adaptor 正常加载、同步器回来、按钮与保存一起复原;③ 随之而来的跨源:桌面版下 TW frame 与宿主页面不同源,`tw-frame.ts` 的 hash 导航把「读跨源 `$tw` 抛 SecurityError」包进 try/catch 并直接走整页兜底(不再冒泡、链接不丢),`theme-sync` 本就是 best-effort 跨源静默。守门:新增 `scripts/verify-tw-origin.mjs`(7 条:Host 头推导 / 脏头拒绝 / http(s) 忽略绝对基址 / `dsh-app:`+`file:` 采用绝对基址 / 老服务端不回归 / 两处接线断言 / 跨源兜底源码断言),`verify-frame-surface` 再增 2 条行为单测(`dsh-app:` 页面必须把 frame 指到宿主 http 基址、且 http 页面仍用同源相对地址;跨源 frame 读 `$tw` 抛错时必须整页兜底)。**注意**:这修的是「TW 被非 http(s) 文档嵌入」;「在浏览器里直连 TW 子端口(`http://127.0.0.1:<port>/`)」是另一回事——那样 TW 的 API 基址会被指到 DSH 代理前缀而 404,同样显示成只读,请一律用 DSH 同源入口(面板 / 右侧栏知识库 tab / `<DSH origin>/dsh-tiddlywiki/tw/`)。
|
|
422
423
|
- **v0.26.6**(2026-09-26):**修 `tiddlywiki_append` 的 `heading` 在 CRLF 笔记上完全失效、且静默回退到文末**(作者本机知识库的一篇 25KB / 454 行长笔记上连续踩两次后定位到源码)。现象:对这篇笔记连做两次带 `heading` 的 append,内容**全部**落到了文末,而回执照样打印「段落「X」」——看起来完全成功。**根因**:`insertIntoSection` 用 `base.split('\n')`,而 CRLF 正文的**每一行结尾都留着 `\r`**;JS 里 `(.*)` **不匹配 `\r`**、`$` 也**不匹配 `\r` 之前的位置**,于是 `/^#{1,6}\s+(.*)$/` 对**每一个**标题都匹配失败 ⇒ `start < 0` ⇒ 走「追加到文末」的回退分支。**只在 CRLF 笔记上复现**(纯 LF 笔记一切正常),所以它看起来像偶发;落盘文件的「**376 个 CRLF + 78 个裸 LF**」混合行尾正是走过该分支的签名(`lines.join('\n')` 保留每行原有 `\r`、只把新块用 `\n` 接上)。**修复三处**:① 标题匹配前**只**剥掉行尾 `\r`(原文行尾一个字节都不动;**没有**改成 `split(/\r?\n/)`——那会让每次 append 都把整篇重写成 LF,炸出全文件 diff);② 新块按**文档自己的行尾**写入(`base.includes('\r\n')` 判定),CRLF 笔记不再越写越乱;③ `insertIntoSection` 改为返回 `{ text, matched }`,`tiddlywiki_append` 把它作为 **`headingMatched`** 一并返回,未命中时回执改为「⚠️ 未找到标题「X」,已改为追加到文末」——**不再把「定位失败」伪装成「写进了那一节」**(Agent 因此完全无法自检,这是本 bug 最坑的一点)。顺带把 `heading` 的真实落点语义写进 schema:实为「该标题之后、**下一个任意级别标题之前**」,标题后紧跟子标题时落在两者之间(=章节开头),并非 schema 原先暗示的「整节末尾」。守门:`verify-tools` +4 条 E2E(CRLF 正文的笔记必须 `headingMatched=true` 且标记落在目标段内、段内不得混入裸 LF;未命中必须 `headingMatched=false` 且回执含「未找到标题」、不得再宣称写进该段落;命中时的反向保护;wikitext `!` 标题同样可定位),**已反向验证**(撤掉 lib 里的行尾 CR 剥离即红 1 条)。
|
|
423
424
|
- **v0.26.5**(2026-09-23):**修 P0:`fields` 参数被按字符拆成几十个垃圾字段**(用户实测复现两次后报障)。现象:`tiddlywiki_put` / `batch_put` / `append` 传 `fields: {"review-after":"2026-12-22"}` 后,条目上出现 `0={`、`1="`、`2=r`… 几十个**单字符字段**,真正的自定义字段**一个都没写进去**;又因为 `fields.type` 是**改内容类型的唯一入口**,这期间也无法把条目写成 wikitext / `text/css`。**根因两层**:① 参数 schema 声明为 `{type:'json'}`,而 DSH 的 schema 里 `type:'json'` 是**纯注解**——编译后连 `type` 都没有(`src/sdk.ts` 的 `compileValue`),模型收不到「这是个对象」的信息,于是把 JSON 当**字符串**发来;② 新建笔记 + 自动工作区标记走 `withWorkspaceMark()` 的 `{ ...(fields ?? {}) }`,而**展开字符串是按字符展开**的(`{...'{"r"'}` → `{0:'{',1:'"',2:'r'…}`),这些索引键随后被当成自定义字段写入;旧 `applyCustomFields()` 对非对象又是**静默 return**,所以全程没有任何报错。**修复(三处)**:① 三个写工具的 `fields` schema 改成真正的 `object` + `additionalProperties: true`(模型能直接看到类型);② 新增 `normalizeFieldsArg()`(`write-policy.ts`)——对象原样返回、`undefined`/`null`/空串视同未给(保留基底)、**JSON 字符串解析成对象**(兼容仍按字符串发参的模型)、数组/数字/解析不出对象的字符串**明确抛错**;`defineTool` 相应新增 `normalizeArgs` 钩子,让归一化跑在 schema 预校验**之前**(放到之后会被「must be an object」先拦掉,兼容层就没机会生效);③ `applyCustomFields()` 遇到非对象**抛错**而不是静默忽略,`withWorkspaceMark()` 只为已归一化的对象做展开。守门:`verify-write-policy` +5 条纯函数(字符串解析 / 对象原样 / 三种坏输入拒绝 / 字符串在 `buildWriteTiddler` 处被拦 / 归一化后无索引键),`verify-tools` +4 条 E2E(三个工具的 schema 必须 `type:object`、按字符串发参仍写对字段且不产生 `0=` 垃圾、坏输入明确报错且不留半成品条目、`append`/`batch_put` 走同一套归一化)。**注意**:本次修复只影响写入端;已被写进条目的垃圾字段需要重建该条目(`fields` 只能覆盖、不能删除单个字段),本机知识库已扫描确认无残留。
|
|
424
425
|
- **v0.26.4**(2026-09-23):**修「发送给 Agent」因配置被浏览器自动填充而 404 + 设置页文本框防自动填充**。实测:设置页「TW 端请求基址」(`ui.sendToAgent.endpoint`)被浏览器自动完成当成 URL/账号字段填进 `/dsh-tiddlywiki/tw/root`,于是 send-to-agent 把请求拼成 `/dsh-tiddlywiki/tw/root/agent/sessions`,命中 TW 代理子路径 → 404「获取会话列表失败」。**两层加固**:① 设置页 `textField` 一律 `autocomplete=off`(`tokenField` 早已如此,URL 类文本框 `endpoint`/`git.remote`/`wechat.dsn` 等不再被自动填充污染);② send-to-agent bundle `baseEndpoint()` 校验自定义 endpoint——一旦含 `/tw/`、`/api/`、`/recipes/`、`/files/` 等 TW 子路径或非 origin/根绝对路径(判为浏览器误填),**回退到 `location.origin + "/dsh-tiddlywiki"` 自动推导**,按钮不再因误配 endpoint 而 404。另修 `scripts/gen-seed-send-to-agent.mjs` 模板字符串里一处未转义反引号(`ok:false`)导致再生成 seed 必崩的 bug。bundle send-to-agent 0.3.5→0.3.6。
|