dsh-muv-table 0.2.12 → 0.3.1
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 +91 -1
- package/lib/client.js +784 -60
- package/lib/index.js +54 -8
- package/lib/muv-parser.js +70 -3
- package/lib/panel.html +7 -5
- package/package.json +6 -3
- package/test-card-ops.mjs +152 -0
- package/test-muv-parser.mjs +121 -0
- package/test-preset-resolve.mjs +89 -4
- package/test-var-section.mjs +272 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,72 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## v0.3.1 (2026-10-12)
|
|
4
|
+
|
|
5
|
+
### 🐛 修复:世界书 `[initvar]` 条目里装的是 **JSON**(不是 YAML)时,整棵变量树读不出来
|
|
6
|
+
|
|
7
|
+
用户口径:**「这个黄金庭院的卡的状态栏老是这样基本上是空白」**(状态栏三项恒显示「未知」,角色网格一个角色都没有)
|
|
8
|
+
|
|
9
|
+
- 现象离病因很远。那张卡自带的状态栏取值是 `_.get(sys, '日期', ['未知'])[0]`,「未知」是模板的
|
|
10
|
+
兜底值 —— 说明脚本**跑到了**,只是喂给它的变量树是空的。
|
|
11
|
+
- 真因:`黄金庭院-昔涟` 把整棵树(`系统.日期/时间/地点` + 全体角色档案)按 MUV 的 `$meta` 约定
|
|
12
|
+
写在一个 `[InitVar]` 世界书条目里,**内容是从 `{` 开始的 JSON**。这条路此前只认三种形态
|
|
13
|
+
(`<initvar>` 标签 / `<VariableInsert>` / 裸 **YAML**),JSON 在最后那条兜底上被
|
|
14
|
+
`looksLikeInitvarMapping` 判「不像变量映射」否决(`{` / `},` / `}` 不匹配 `键: 值`),
|
|
15
|
+
于是 `schemaSource = 'none'`、`initvarData = {}`。(同样不能靠喂给 YAML 解析器救:
|
|
16
|
+
那会儿只得到 `"系统": "{"` 这种垃圾键。)
|
|
17
|
+
- 修法:新增 `parseJsonInitvarMapping()`,在 YAML 闸门**之前**先试 JSON —— 顺序必须如此,
|
|
18
|
+
反过来 JSON 永远进不来(两种形态互斥,不存在抢数据的问题)。认可是**结构性**的:
|
|
19
|
+
`JSON.parse` 成功且结果是纯对象才采用,散文 / 半截 JSON / 顶层数组统统退回 `none`,
|
|
20
|
+
所以"带大括号的说明文档"混不进来。
|
|
21
|
+
- **`$meta` 被剔除**:它是 MVU 对变量树的控制元数据、不是变量 —— 留着会在面板里多出两个假字段
|
|
22
|
+
(`extensible` 读成字符串 `"false"`),还会跟着写进生成的块。
|
|
23
|
+
- 叶子保留 `[值, 说明]` 的**数组**形态(状态栏取 `[0]`,这是 MVU 的写法)。
|
|
24
|
+
- 新来源标 `schemaSource: 'worldbook-initvar-json'`,`panel.html` 的徽标同步加了标签 —— 它和
|
|
25
|
+
`worldbook-initvar` 一样是**启发式**来源,必须可见,否则"猜错"和"这卡确实没变量"长得一样。
|
|
26
|
+
|
|
27
|
+
### ✅ 测试:`test-muv-parser.mjs` [12] 节
|
|
28
|
+
|
|
29
|
+
先量它有多能咬:**换上修复前的解析器跑同一份测试 → 10 条红**,含真实卡那条
|
|
30
|
+
(「黄金庭院:不再读成 none」→ `source=none`);修好后全绿(`80 通过 / 1 失败`,那 1 条是本机
|
|
31
|
+
REAL 卡样本不足导致的**既有红**,改动前后读数一致)。除了分支覆盖,还钉了三件容易空转的事:
|
|
32
|
+
|
|
33
|
+
- **`$meta` 断言先钉反例**:先断言源 JSON 里**确实有** `$meta`,再看它没进结果 —— 否则在树本来就空时这条恒真。
|
|
34
|
+
- **卡片是不可信输入**:JSON 里的 `__proto__` 会被当普通键解析出来,若写成 `vars[key] =` 赋值会真的改写对象原型。突变回朴素赋值后该断言实测变红(`polluted=1`);把剔 `$meta` 那行删掉则 4 条红,现场可见 `$meta.extensible` 混进 schema。
|
|
35
|
+
- **UI 契约**:断言 `panel.html` 的 `SOURCE_LABEL` 覆盖 `schemaSource` 的每个取值 —— 漏一个是界面上渲染出 `undefined`,而不是报错。
|
|
36
|
+
|
|
37
|
+
## v0.3.0 (2026-09-25) —— 补记
|
|
38
|
+
|
|
39
|
+
> 本节正文的代码实际已随 v0.3.0 发布(已核对 npm 上 0.3.0 的 tarball,`lib/client.js` 含 `card-ops-greeting-start`),
|
|
40
|
+
> 但当时 CHANGELOG 一直挂在「未发布」标题下没定型,现在移出并补记到本节。
|
|
41
|
+
|
|
42
|
+
### ✨ 新增:面板内「🧰 卡运维」区块(开场白注入 + 卡与脚本状态)
|
|
43
|
+
|
|
44
|
+
用户口径:**「我有 muv-table 面板,不需要做到酒馆面板里面,集成到 muv-table 面板里面就行了」**
|
|
45
|
+
⇒ 卡相关的运维入口只挂在**本插件自己的视图**里(侧边栏「MUV 表格」→ 面板顶部「🧰 卡运维」,
|
|
46
|
+
默认收起),酒馆管理面板里不再重复一份。
|
|
47
|
+
|
|
48
|
+
- **📌 开场白**:按钮「➕ 把当前卡的开场白注入会话末尾」→ `POST /api/tavern/greeting/insert`。
|
|
49
|
+
- 请求体**只带 `sessionId`**:服务端按会话权威解析预设。带 `presetId` 会引入"会粘住的猜"
|
|
50
|
+
(本仓库已在 v0.2.9 起整条删除酒馆 DOM / localStorage 的预设读取路径),不把猜发出去。
|
|
51
|
+
- 成功 → 绿色「✅ 已注入「卡名」的开场白(N 字,第 M 回合)」;
|
|
52
|
+
`greeting-already-present` → 蓝色「本会话已有开场白,无需重复注入」(**不是报错**);
|
|
53
|
+
会话不活跃(404 + JSON)→ 照原样显示服务端原因;路由不存在(404/405 非 JSON)或
|
|
54
|
+
fetch 抛错 → 橙色降级提示,**不崩面板**。
|
|
55
|
+
- **🧩 卡与脚本状态(只读)**:当前会话绑定的卡名 / 卡脚本 `enabled/total`(接口不可用
|
|
56
|
+
就**隐藏该行**,不显示假的 `0/0`)/ 运行时变量树顶层键数量 / 客户端构建号。
|
|
57
|
+
- **🔄 刷新**:重查上面全部只读项。
|
|
58
|
+
- 逻辑与 UI 分离:`cardOpsInsertGreeting` / `cardOpsLoadStatus` 是纯函数(不碰 React/DOM),
|
|
59
|
+
UI 只负责显示;**未改动**本插件既有的解析 / 正则 / 卡功能,纯客户端改动(刷新页面即生效,
|
|
60
|
+
不需要重启 DSH)。
|
|
61
|
+
|
|
62
|
+
### ✅ 测试:`test-card-ops.mjs`(19 通过 / 0 失败)
|
|
63
|
+
|
|
64
|
+
**逐字提取** `lib/client.js` 里 `[[card-ops-greeting-start/end]]` 标记之间的函数执行,
|
|
65
|
+
断言"点按钮 → 发出去的请求体":URL / 方法 / content-type / body 形状;以及五个响应分支
|
|
66
|
+
(成功 / 已存在 / 会话不活跃 / 接口不存在 / 网络不可达)。
|
|
67
|
+
含**对照组**:把请求体改回"带上猜出来的 `presetId`"后,[B] 组断言必须变红
|
|
68
|
+
(实测整轮 16 通过 3 失败 / 退出码 1),证明断言不是永真。
|
|
69
|
+
|
|
3
70
|
## v0.2.12 (2026-09-20)
|
|
4
71
|
|
|
5
72
|
### 🐛 修复:发布包里缺 `test-cards.mjs`,导致随包发布的 `test-muv-parser.mjs` 装完跑不起来
|
|
@@ -188,7 +255,30 @@ HTTP 200 { ok:true, found:true, cardName:'川上富江', presetDir:'tavern-lite'
|
|
|
188
255
|
| `sessionId` 绑定到真实预设 | 用它,`presetSource: 'session'` |
|
|
189
256
|
| `sessionId` 绑定**已消失**(改名) | `found:false`,`error: preset bound to session … not found: <旧名>` |
|
|
190
257
|
| `sessionId` 绑定为 `default` / 无绑定 | 用酒馆自己的默认(tavern-lite),`presetSource: 'session-default'` |
|
|
191
|
-
| 两个定位参数都没给 |
|
|
258
|
+
| 两个定位参数都没给 | **稳定默认**(tavern-lite),`presetSource: 'default'` |
|
|
259
|
+
| 两个定位参数都没给,但**显式**带 `preferActive=1` | 才按「最近写入的会话」猜,`presetSource: 'active'`;猜不到仍用默认 |
|
|
260
|
+
| `preferPreset=1` + `presetId` | 强制按该 presetId 解析(诊断/卡库检查用),语义是「我就是要它,别管会话」 |
|
|
261
|
+
|
|
262
|
+
**`presetSource` 取值集合(冻结,改动须同步此表)**:
|
|
263
|
+
`'explicit'` | `'session'` | `'session-default'` | `'default'` | `'active'`。
|
|
264
|
+
其中 `'active'` **现在必须显式带 `preferActive=1` 才可达**,且仓库内**没有任何调用方消费它**
|
|
265
|
+
(`HANDOFF.md` 已记「服务端诚实上报但客户端从不消费」—— 客户端连 `presetSource` 都没读)。
|
|
266
|
+
|
|
267
|
+
> **2026-09 收窄(重要)**:原来「两个定位参数都没给」会**无条件**回落到 `activePresetId()`,
|
|
268
|
+
> 也就是按 `<DSH_HOME>/storages/session_projcache/sessions` 下会话文件的 **mtime 倒序**
|
|
269
|
+
> 取"最近写入的会话"的绑定。这条路径是**串台的真凶之一**:开发/被测会话在不停写文件,
|
|
270
|
+
> 该值会漂移 —— 实测它当时返回的是「安装 dsh-tavern-v2 及其附属插件」那个**开发会话**的绑定。
|
|
271
|
+
> 现在收窄为**只有显式 `preferActive=1` 才走**;否则落到稳定默认并如实标 `default`。
|
|
272
|
+
>
|
|
273
|
+
> ⚠️ 更要紧的一层(另一个仓库):真实 DSH 会话的预设声明在
|
|
274
|
+
> `<DSH_HOME>/sessions/<cwd>/<uuid>/session.jsonl.zstd` 的**事件流**里
|
|
275
|
+
> (`agent-preset/selected` 事件 / header 的 `agentPreset`),**实测 260/260 个会话都有**;
|
|
276
|
+
> 而 `session-bindings.json` 只覆盖 39 条、与其中 **229** 个会话**完全没有**记录。
|
|
277
|
+
> 因此**只读 bindings 的 `presetIdForSession()` 对绝大多数真实会话解析不出任何东西**,
|
|
278
|
+
> 这正是「基本上每个会话都变成看同一张卡」的根因。
|
|
279
|
+
> 权威解析应走酒馆的 `GET /api/tavern/current-session?sessionId=`(它读会话事件流 →
|
|
280
|
+
> bindings → default),客户端拿到后再带 `preferPreset=1` 请求本接口。
|
|
281
|
+
> 诊断数据见 `C:\deepseek harness\crosstalk-findings-20260920.md`。
|
|
192
282
|
|
|
193
283
|
- `default` 这条**是照抄酒馆的规则**,不是猜:`dsh-tavern` 的
|
|
194
284
|
`lib/index.js:2404` 就是 `if (currentPresetId === 'default') currentPresetId = 'tavern-lite'`,
|