dsh-edit-turn 0.2.9 → 0.2.11
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 +11 -0
- package/lib/client.js +35 -3
- package/lib/index.js +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -219,6 +219,17 @@ ln -s /path/to/dsh-install/node_modules ./node_modules
|
|
|
219
219
|
|
|
220
220
|
### 更新日志
|
|
221
221
|
|
|
222
|
+
**0.2.11** —— 修「字怎么变大了」。
|
|
223
|
+
|
|
224
|
+
- **修复:改写后的气泡与编辑器不跟随平台的"内容字号"设置**。平台的气泡用 `font-size: var(--dsh-content-font-size,14px)` + `line-height: calc(22px + var(--dsh-content-font-delta,0px))`;我们的替代气泡写成 `font:inherit`(继承了行的 16px,比气泡的 15px 大),编辑器又写死 15px——读者一改内容字号,两处都对不上,看起来就是"字变大了"。现在两者都取平台同一个变量/公式(该变量定义在 body 上,编辑器所在的浮层是其子节点,可直接继承)。
|
|
225
|
+
- 真机验证:默认设置下平台气泡 / 替代气泡 / 编辑器均为 15px;把 `--dsh-content-font-size` 改成 18px 后,三者同步变为 18px。+ 2 条静态检查;110 单测 / 80 契约 / 静态 / verify:live / verify:ui 全绿。
|
|
226
|
+
|
|
227
|
+
**0.2.10** —— 修「编辑器浮层留在设置页上」。
|
|
228
|
+
|
|
229
|
+
- **修复:会话视图卸载后编辑器没有跟着走**。编辑器挂在 `body` 的独立浮层上(这是为了躲开宿主重绘),而没有任何框架会替它收尾:切到设置页时对话视图(连同注册在输入框卡上的条目)卸载了,编辑器却留在浮层里**飘在设置页上**。现在条目卸载时清掉自己的编辑器与参考,空浮层也一并移除。
|
|
230
|
+
- 卸载判定不能"一有 cleanup 就清":这个 effect 在每次视图变化时都会先 cleanup 再重跑,硬清会把编辑器反复拆掉(焦点/草稿语义都会乱)。现在是**延迟清理**——下一次 effect 重跑会取消它,只有真正的卸载(不再重跑)才让它落地。
|
|
231
|
+
- 新增用例「会话视图卸载后编辑器跟着消失(浮层也不留)」+ 2 条静态检查;110 单测 / 80 契约 / 静态 / verify:live / verify:ui 全绿。
|
|
232
|
+
|
|
222
233
|
**0.2.9** —— 修「同一条消息出现两个一样的气泡」。
|
|
223
234
|
|
|
224
235
|
- **修复:一行两个替代气泡,两个来源都堵掉**。①气泡此前只认「行的直系子节点 / 紧邻前一个兄弟」,一旦被宿主挪开就认不出,下一趟又种一个;现在气泡带**行的 key 标记**(`data-dshet-revision-for`),挪到哪都找得回来,且每行只允许一个(多余的按标记清除)。②更隐蔽的一个:MutationObserver 的回调可能**晚于它所属的那次渲染**,带着**过期视图**(`hidden` 为空)跑一遍,把已折叠的行重新展开——原气泡就回到了替代气泡旁边;现在这趟 pass 从 `controller.getSnapshot()` 现取当前视图,过期视图再也不可能把行展开。
|
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.
|
|
33
|
+
const PLUGIN_VERSION = '0.2.11'
|
|
34
34
|
|
|
35
35
|
// --- copy -----------------------------------------------------------------
|
|
36
36
|
|
|
@@ -145,7 +145,12 @@ window.__ModuleLoader__.load({
|
|
|
145
145
|
// a replacement message, so this one is ours. Styled from the plugin own
|
|
146
146
|
// namespaced variables, which follow the active theme without borrowing
|
|
147
147
|
// CSS-module hashes that change between builds.
|
|
148
|
-
|
|
148
|
+
// Font metrics copied from the platform's own user bubble
|
|
149
|
+
// (`.Sixlwa_bubble`): a fixed size or `font:inherit` is wrong here -
|
|
150
|
+
// inherit picks up the row's 16px, fixed ignores the reader's content
|
|
151
|
+
// font setting, and either way the rewritten text changed size against
|
|
152
|
+
// the bubble it replaces.
|
|
153
|
+
'.dshet-revision{box-sizing:border-box;align-self:flex-end;width:fit-content;max-width:min(72ch,86%);margin:6px 0 6px auto;padding:9px 14px;border-radius:16px;background:var(--dshet-field);color:var(--dshet-ink);font:inherit;font-size:var(--dsh-content-font-size,14px);line-height:calc(22px + var(--dsh-content-font-delta,0px));white-space:pre-wrap;overflow-wrap:anywhere;min-width:0}',
|
|
149
154
|
'.dshet-revision:empty{display:none}',
|
|
150
155
|
'.dshet-revision{position:relative}',
|
|
151
156
|
// Fallback only: a row with no action bar to keep is displayed away
|
|
@@ -187,7 +192,7 @@ window.__ModuleLoader__.load({
|
|
|
187
192
|
'.dshet-layer .dshet-editor{position:absolute;pointer-events:auto}',
|
|
188
193
|
'.dshet-editor{margin:0;border:1px solid var(--dshet-line);border-radius:16px;background:var(--dshet-panel);backdrop-filter:blur(18px) saturate(1.2);box-shadow:var(--dshet-shadow);color:var(--dshet-ink);transition:border-color .12s}',
|
|
189
194
|
'.dshet-editor:focus-within{border-color:var(--dsw-alias-button-primary-fill,var(--dshet-accent))}',
|
|
190
|
-
'.dshet-editor textarea{display:block;width:100%;min-height:47px;max-height:46vh;overflow-y:auto;resize:none;box-sizing:border-box;padding:11px 14px 0;border:0;background:transparent;color:inherit;font:inherit;font-size:
|
|
195
|
+
'.dshet-editor textarea{display:block;width:100%;min-height:47px;max-height:46vh;overflow-y:auto;resize:none;box-sizing:border-box;padding:11px 14px 0;border:0;background:transparent;color:inherit;font:inherit;font-size:var(--dsh-content-font-size,14px);line-height:calc(22px + var(--dsh-content-font-delta,0px));outline:none}',
|
|
191
196
|
'.dshet-editor textarea::placeholder{color:var(--dshet-ink-dim)}',
|
|
192
197
|
'.dshet-editor textarea:disabled{opacity:.65}',
|
|
193
198
|
'.dshet-note,.dshet-warn,.dshet-error{margin:4px 14px 0;font-size:12px;line-height:19px}',
|
|
@@ -264,6 +269,7 @@ window.__ModuleLoader__.load({
|
|
|
264
269
|
this.editorRow = null
|
|
265
270
|
this.editorFocus = false
|
|
266
271
|
this.editorDraft = ''
|
|
272
|
+
this.clearTimer = null
|
|
267
273
|
this.confirming = false
|
|
268
274
|
this.noticeTimer = null
|
|
269
275
|
this.view = Object.freeze({
|
|
@@ -548,6 +554,9 @@ window.__ModuleLoader__.load({
|
|
|
548
554
|
}
|
|
549
555
|
|
|
550
556
|
dispose() {
|
|
557
|
+
if (this.clearTimer !== null) window.clearTimeout(this.clearTimer)
|
|
558
|
+
this.clearTimer = null
|
|
559
|
+
clearEditor()
|
|
551
560
|
this.listeners.clear()
|
|
552
561
|
if (this.noticeTimer !== null) window.clearTimeout(this.noticeTimer)
|
|
553
562
|
this.noticeTimer = null
|
|
@@ -1003,6 +1012,12 @@ window.__ModuleLoader__.load({
|
|
|
1003
1012
|
function clearEditor() {
|
|
1004
1013
|
const elements = document.querySelectorAll('.dshet-editor')
|
|
1005
1014
|
for (const element of elements) element.remove()
|
|
1015
|
+
// An empty layer has no business staying on the page: the editor is
|
|
1016
|
+
// hosted on the body, where nothing else clears up after it.
|
|
1017
|
+
if (editorLayer !== null && editorLayer.isConnected === true && editorLayer.children.length === 0) {
|
|
1018
|
+
editorLayer.remove()
|
|
1019
|
+
editorLayer = null
|
|
1020
|
+
}
|
|
1006
1021
|
}
|
|
1007
1022
|
|
|
1008
1023
|
// The layer the editor is hosted on. It is created once, hangs off the
|
|
@@ -1466,8 +1481,25 @@ window.__ModuleLoader__.load({
|
|
|
1466
1481
|
else window.setTimeout(run, 16)
|
|
1467
1482
|
})
|
|
1468
1483
|
observer.observe(document.body, { childList: true, subtree: true })
|
|
1484
|
+
// This effect re-runs whenever the view changes, and its cleanup runs
|
|
1485
|
+
// first every time; only a REAL unmount means the conversation view
|
|
1486
|
+
// went away (switching to Settings, say) and the editor has to go with
|
|
1487
|
+
// it - left behind, it floated over whatever came next. So the clear is
|
|
1488
|
+
// deferred, and the next run of this effect cancels it.
|
|
1489
|
+
if (controller.clearTimer !== null) {
|
|
1490
|
+
window.clearTimeout(controller.clearTimer)
|
|
1491
|
+
controller.clearTimer = null
|
|
1492
|
+
}
|
|
1469
1493
|
return () => {
|
|
1470
1494
|
observer.disconnect()
|
|
1495
|
+
if (controller.clearTimer !== null) window.clearTimeout(controller.clearTimer)
|
|
1496
|
+
controller.clearTimer = window.setTimeout(() => {
|
|
1497
|
+
controller.clearTimer = null
|
|
1498
|
+
clearEditor()
|
|
1499
|
+
controller.editorBox = null
|
|
1500
|
+
controller.editorRow = null
|
|
1501
|
+
controller.editorElement = null
|
|
1502
|
+
}, 250)
|
|
1471
1503
|
}
|
|
1472
1504
|
}, [snapshot, view, controller, t])
|
|
1473
1505
|
|
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.
|
|
25
|
+
// The silent replacement carrier is an EMPTY `developer/message` (0.2.11;
|
|
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.
|
|
63
|
+
export const PLUGIN_VERSION = '0.2.11'
|
|
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.
|
|
3
|
+
"version": "0.2.11",
|
|
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",
|