dsh-edit-turn 0.2.4 → 0.2.5

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 CHANGED
@@ -218,6 +218,11 @@ ln -s /path/to/dsh-install/node_modules ./node_modules
218
218
 
219
219
  ### 更新日志
220
220
 
221
+ **0.2.5** —— 修「每保存一次,模型的回答往下掉一格」。
222
+
223
+ - **修复:被回滚的「轮次尾巴」没有隐藏,堆成了一列空条**。回复编辑会留下旧轮次的尾巴(用时/用量/动作条)——它不是消息行,属于它的消息已经被回滚,尾巴上没有任何可操作的东西。此前我们按"消息行"的规则给它保留了动作条(那条规则本是为了让被回滚的用户消息还能复制/删除),于是**每保存一次就多一条空条**,把对话一格格顶下去。现在按 `data-chat-flow-kind="turn-tail"` 识别:尾巴整条隐藏(并清理旧版本给它打过的 `data-dshet-keep-actions`),消息行照旧保留动作条。新增用例「被回滚的轮次尾巴整条消失,而不是叠一条空条」+ 2 条静态检查;`verify:ui` 的现场断言改为三条事实——轮次尾巴整条隐藏、没有动作条的行整条隐藏、有动作条的消息行必须保住动作条(真机 6 条孤儿尾巴全部按新规则消失)。
224
+ - 补一句 0.2.4 的发布说明:`verify:ui` 与 `verify:live` 在 0.2.4 上均已通过;本缺陷是发布后由使用现场发现的。
225
+
221
226
  **0.2.4** —— 修一个**会把会话写坏**的致命缺陷(回复编辑的写入非法),并把「读取路径校验」补进契约测试。
222
227
 
223
228
  - **修复(致命):回复编辑会把整份会话写到读不出来**。旧写法把两样非法内容写进日志:①静默载体是一个空的 `system/message`,而格式**只允许 system-prompt 来源的 system 消息**;②修正消息带着**已经关闭的**原轮次 turn/step 追加。追加是宽松的(当场不报错),但**读取**会拒绝:DSH 从此对该会话返回 `session-not-found`,「历史加载失败:stored log is corrupt: SessionFormatError: system/message does not match an open turn and step」。现场表现就是那个会话里所有编辑入口消失、历史打不开。现在:回复编辑先在日志里**开一个新轮次**(`turn/start` + `step/start`),静默载体改为**空 `developer/message`**(空内容不投影给模型、替换不进转录、格式合法),修正消息与 `step/end`/`turn/end` 都在这个轮次内收尾;运行时从 `turn/start` 事件投影 `lastTurn`,所以它下一轮用 N+2,序号一致。
package/lib/client.js CHANGED
@@ -30,7 +30,7 @@ window.__ModuleLoader__.load({
30
30
  const ROUTE_PREFIX = '/dsh-edit-turn'
31
31
 
32
32
  /** Keep in sync with package.json and lib/index.js. */
33
- const PLUGIN_VERSION = '0.2.4'
33
+ const PLUGIN_VERSION = '0.2.5'
34
34
 
35
35
  // --- copy -----------------------------------------------------------------
36
36
 
@@ -804,10 +804,25 @@ window.__ModuleLoader__.load({
804
804
  }
805
805
 
806
806
  function setRowHidden(row, hide, animate) {
807
+ // A turn tail is not a message row. It is the strip a turn's end renders
808
+ // (duration, usage, actions); when the turn behind it is rolled back the
809
+ // strip is an orphan with nothing left to act on. Keeping it, which is
810
+ // right for a message row, stacked one empty strip per edit and pushed
811
+ // the conversation down the page - the report was "every save moves the
812
+ // model's answer further down".
813
+ const isTail = row.getAttribute('data-chat-flow-kind') === 'turn-tail'
807
814
  if (hide) {
808
- const keepsStrip = collapseRowContent(row, true)
809
- if (keepsStrip && row.dataset.dshetKeepActions !== '1') row.dataset.dshetKeepActions = '1'
810
- if (row.dataset.dshetHidden === '1') return
815
+ const keepsStrip = isTail ? false : collapseRowContent(row, true)
816
+ if (keepsStrip) {
817
+ if (row.dataset.dshetKeepActions !== '1') row.dataset.dshetKeepActions = '1'
818
+ } else if (row.dataset.dshetKeepActions === '1') {
819
+ // Older passes marked this tail as keep-actions; with the rule fixed
820
+ // the attribute has to go, or the row stays visible through it.
821
+ delete row.dataset.dshetKeepActions
822
+ }
823
+ if (row.dataset.dshetHidden === '1') {
824
+ if (keepsStrip || row.style.display === 'none') return
825
+ }
811
826
  row.dataset.dshetHidden = '1'
812
827
  if (keepsStrip) return
813
828
  if (!animate || typeof requestAnimationFrame !== 'function') {
package/lib/index.js CHANGED
@@ -22,7 +22,7 @@
22
22
  // admission path. It resumes the Session when cold and starts exactly one
23
23
  // new turn from the revised text.
24
24
  //
25
- // The silent replacement carrier is an EMPTY `developer/message` (0.2.4;
25
+ // The silent replacement carrier is an EMPTY `developer/message` (0.2.5;
26
26
  // before that an empty `system/message`, which no reader accepts - see the
27
27
  // README). Empty content projects to no model message, so the rollback adds
28
28
  // nothing the model can see and the derived context after an edit is exactly
@@ -60,7 +60,7 @@ export const PLUGIN_ID = 'dsh-edit-turn'
60
60
  export const name = PLUGIN_ID
61
61
 
62
62
  /** Keep in sync with package.json and lib/client.js. */
63
- export const PLUGIN_VERSION = '0.2.4'
63
+ export const PLUGIN_VERSION = '0.2.5'
64
64
 
65
65
  // A ring of the last few requests, answering "did the browser half even ask, and
66
66
  // what did it get?" without needing its console. Read-only diagnostics: the
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-edit-turn",
3
- "version": "0.2.4",
3
+ "version": "0.2.5",
4
4
  "description": "Edit any user turn in DeepSeek Harness and re-run it: an inline editor on the message row rolls the conversation back to just before that turn through the official surface-replace contract, then re-prompts the agent with the revised text. The append-only session log is never rewritten.",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",