dsh-smooth-stream 0.4.0 → 0.4.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-smooth-stream",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "Fluid streaming rendering and silky scrolling for DeepSeek Harness replies, including Markdown, code blocks, tables, and tool results.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -28,9 +28,9 @@
28
28
  */
29
29
 
30
30
  const STYLE_ID = 'dshss-auto-collapse-style'
31
- /** Class of the injected per-turn summary row; also consumed by the follow
32
- * engine so the row rides the same lag transform as native message rows. */
33
- export const PROCESSED_CLASS = 'dshss-processed'
31
+ /** Class of the injected per-turn summary row; the follow engine's generalized
32
+ * surface walk picks it up as an ordinary foreign flow sibling. */
33
+ const PROCESSED_CLASS = 'dshss-processed'
34
34
  /** Inline custom property marking elements whose display this plugin owns. */
35
35
  const DISPLAY_OWNED_PROP = '--dshss-display-owned'
36
36
  /** Unobservable external style writes are reconciled by this audit cadence. */
@@ -29,7 +29,6 @@
29
29
  import { useEffect, useLayoutEffect, useRef, type RefObject } from 'react'
30
30
  import { DEFAULT_STREAM_DEBUG_TUNING, type StreamDebugTuning } from '../settings.ts'
31
31
  import { debugRuntime } from './debugRuntime.ts'
32
- import { PROCESSED_CLASS } from './auto-collapse-controller.ts'
33
32
 
34
33
  /**
35
34
  * Programmatic follow marker retained for hosts that recognize external
@@ -217,16 +216,36 @@ function resizeProxyOf(port: HTMLElement): HTMLElement | null {
217
216
  return port.querySelector('[data-chat-transcript]') ?? port.querySelector('[data-chat-flow]')
218
217
  }
219
218
 
220
- /** Outermost message surfaces; nested tool rows ride their parent. */
221
- /** @internal Test seam: the equal-lag transform set for one scrollport. */
219
+ /**
220
+ * Outermost message surfaces; nested tool rows ride their parent.
221
+ *
222
+ * Another plugin may insert its own element as a flow sibling of the Chat rows
223
+ * (meow-memory's fold bar is one; so is this plugin's own fold summary row).
224
+ * Such a row carries no `data-chat-anchor-key`, so selecting only anchored
225
+ * rows would shift the conversation while leaving the foreign row at its
226
+ * natural offset, letting the shifted rows paint over it. Every direct flow
227
+ * child therefore rides the same transform, keeping the visual order of the
228
+ * column intact.
229
+ */
222
230
  export function shiftSurfacesOf(port: HTMLElement): HTMLElement[] {
223
231
  const transcript = port.querySelector<HTMLElement>('[data-chat-transcript]')
224
232
  if (transcript !== null) return [transcript]
225
- // Fold summary rows are plugin-injected flow children without an anchor
226
- // key; they must ride the same lag transform as native rows, otherwise
227
- // they visibly detach from their neighbours on every follow frame.
228
- return [...port.querySelectorAll<HTMLElement>(`[data-chat-anchor-key], .${PROCESSED_CLASS}`)]
233
+ const anchored = [...port.querySelectorAll<HTMLElement>('[data-chat-anchor-key]')]
229
234
  .filter(row => row.parentElement?.closest('[data-chat-anchor-key]') === null)
235
+ const flow = port.querySelector<HTMLElement>('[data-chat-flow]')
236
+ if (flow === null) return anchored
237
+ const status = turnStatusOf(port)
238
+ const anchoredSet = new Set(anchored)
239
+ // One document-order pass: an anchored row, or a foreign child that contains
240
+ // no anchored row of its own (a wrapper around real rows would double-shift
241
+ // the rows inside it).
242
+ const __dbg = [...flow.children].filter((child): child is HTMLElement =>
243
+ child instanceof HTMLElement
244
+ && child !== status
245
+ && (anchoredSet.has(child) || child.querySelector('[data-chat-anchor-key]') === null))
246
+ console.log('[engine] reached end of shiftSurfacesOf, n=', __dbg.length)
247
+ ;(globalThis as Record<string, unknown>).__dshssProbe = __dbg.map(e => `${e.tagName}:${e.getAttribute('data-chat-anchor-key') ?? e.className}`)
248
+ return __dbg
230
249
  }
231
250
 
232
251
  function currentShiftOf(element: HTMLElement): number {