Skip to content

Releases: hoshF/dsh-md-export

v1.7.2 — reject corrupt zstd frames; preserve content and client lifecycle

Choose a tag to compare

@hoshF hoshF released this 04 Oct 02:43

A Export MD button in the DSH Web session header that writes the current
conversation to a file chosen through the native save dialog, plus a CLI and an
HTTP route over the same renderer. A toast then names the file that was written, or
carries the reason if it failed.

It reads session logs directly from disk, multi-frame zstd included, and handles
v0, v3 and v4 — each verified against real logs.

Requires Node 22.15+. The node:zlib zstd API does not exist in Node 20 or 21.

After installing or updating, restart DSH and hard-refresh the page
(⌘⇧R / Ctrl+Shift+R).

Install

Open Plugins in the DSH sidebar → Add plugin → paste
https://github.com/hoshF/dsh-md-export → restart DSH.


Fixed

  • Reject corrupt or truncated zstd frames and trailing garbage instead of silently
    skipping content; validate complete frame boundaries and the decoder's input
    consumption.
  • Preserve consecutive blank lines in message code blocks and tool arguments/results.
  • Keep Unicode surrogate pairs intact when truncating title-based filenames.
  • Exclude sentence punctuation from bare references and number mixed bare/Markdown
    links by their actual first appearance, retaining labelled duplicates.
  • Cancel stale saved-state timers and prevent overlapping exports or UI updates
    after unmount; cancellation and failures allow retrying.
  • Reject missing CLI output paths before writing files, and list all sessions
    instead of silently stopping at 40.
  • Remove misleading pre-v3 warnings from the CLI and manual smoke script. Earlier
    changelog statements that these warnings never existed have been corrected.

Added

  • Compression integrity, content-preservation, Unicode filename, reference,
    client lifecycle and CLI regression tests; all test/*.test.mjs files run in CI.

Documentation

  • Synchronise both READMEs and the format contract with strict frame decoding,
    filename refresh timing, whitespace preservation and CLI argument handling.

v1.6.1 — fix: v0–v3 tool results were mismatched

Choose a tag to compare

@hoshF hoshF released this 03 Oct 16:34

A Export MD button in the DSH Web session header that writes the current
conversation to a file chosen through the native save dialog, plus a CLI over
the same renderer. A toast then names the file that was written, or carries the
reason if it failed.

It reads session logs directly from disk, multi-frame zstd included, and handles
v0, v3 and v4 — each verified against real logs. Formats v1 and v2 exist in DSH's codec chain but were never observed here, so they are not claimed as tested. That is what makes it work
on DSH 0.2.x where other export plugins fail on the version gate, the session
format, or the decompression.

Requires Node 22.15+. The node:zlib zstd API does not exist in Node 20 or 21.

After installing or updating, restart DSH and hard-refresh the page
(⌘⇧R / Ctrl+Shift+R). An ordinary reload can serve the client bundle the
browser cached from the previous version.

Install

Open Plugins in the DSH sidebar → Add plugin → paste
https://github.com/hoshF/dsh-md-export → restart DSH. Or clone and run
./install.sh.


Fixed

  • Tool results in v0–v3 sessions never matched their calls. Those formats wrap
    a result in a tool-result block carrying the call id and the error flag one
    level deeper than v4 does, and only the v4 shape was read. Nothing crashed,
    which is what made it bad: every result failed to match, so each tool appeared
    twice in the document — once with an empty body and once as
    (未匹配的工具结果) — tool output was lost entirely, failed calls were
    reported as successful, and search sources inside those results never reached
    ### References.

    Measured on this machine before the fix: 4,552 results across 56 old-format
    sessions, of which 4,552 were unmatched, 0% carried output and 0 carried an
    error flag. After: 4,552 matched, 100% with output, 71 error flags, 0 orphans.

  • A result arriving after the next user turn no longer goes unmatched. The
    call-id lookup tables were rebuilt on every user message, so a result written
    later — a long-running tool, an approval flow — could not find its call. callIds
    are unique within a session, so the tables now persist for the whole session.
    This removed 32 stray unmatched entries from current-format sessions.

Changed

  • docs/FORMAT.md had both of these wrong. It promised a stderr warning and an
    "incomplete" mark for version < 3 that the code has never emitted, and it
    asserted that v0–v2 kept message content only in chunk rows. Real v0 logs carry
    the finalized rows as well, so no such warning was ever needed. The document now
    states the actual policy — no version gate, rows dispatched by shape — and
    records the one real gap: steps interrupted before a finalized message was
    written, whose partial reasoning exists only as chunks.

v1.4.0 — localised button, download icon

Choose a tag to compare

@hoshF hoshF released this 03 Oct 13:02

A Export MD button in the DSH Web session header that writes the current
conversation to a file chosen through the native save dialog, plus a CLI over
the same renderer. It reads session logs directly from disk, multi-frame zstd
included, which is what makes it work on DSH 0.2.x where other export plugins
fail on the version gate, the session format, or the decompression.

Requires Node 22.15+. The node:zlib zstd API does not exist in Node 20 or 21.

Install

Open Plugins in the DSH sidebar → Add plugin → paste
https://github.com/hoshF/dsh-md-export → restart DSH. Or clone and run
./install.sh.


Added

  • The UI copy is localised. The button was hardcoded Chinese, so in an
    English UI it was the only Chinese string in the session header. It now
    registers zh and en dictionaries with the host's locale service and
    subscribes to locale/change, so switching the language in Settings updates it
    without a reload. The plugin does not decide the language itself — that is the
    host's precedence chain (explicit user choice, then browser language, then
    English) — and it deliberately does not read navigator.language, which would
    bypass the user's own setting.

Changed

  • A download glyph precedes the label, and the label is shorter. The icon is
    inline SVG rather than an emoji, which renders differently on every platform.
    Icon-only was considered and rejected: the session header already offers the
    official Download session log, which produces a ZIP of JSONL rather than a
    readable transcript, and an unlabelled arrow cannot be told apart from it.
  • title and aria-label text follow the language too.

v1.3.2 — first public release

Choose a tag to compare

@hoshF hoshF released this 03 Oct 12:52

A "导出 MD" button in the DSH Web session header that exports the current
conversation as clean Markdown through the native save dialog, plus a CLI over
the same renderer.

It reads session logs directly from disk — including the multi-frame zstd layout —
which is what makes it work on DSH 0.2.x where the existing export plugins fail on
the version gate, the session format, or the decompression.

Requires Node 22.15+. The node:zlib zstd API does not exist in Node 20 or 21.

Install

Open Plugins in the DSH sidebar → Add plugin → paste
https://github.com/hoshF/dsh-md-export → restart DSH. Or clone and run
./install.sh.


Fixed

  • The plugin required a newer Node than it claimed. engines said >=20 and
    the README said the same, but reading a session log needs
    zstdDecompressSync, which node:zlib only gained in Node 22.15 (23.8 on
    the 23 line). On Node 20 the named import made the module fail to link, so the
    plugin did not even load — it surfaced as does not provide an export named 'zstdDecompressSync'. engines now says >=22.15, the docs say so, and
    src/session.js imports node:zlib as a namespace and checks at runtime so an
    unsupported runtime gets a sentence instead of a module error. The plugin also
    warns once at load time in that case.

    CI caught this: the Node 20 matrix leg failed while 22, 24 and 26 passed. The
    matrix is now 22.15.0 (the real floor), 24 and 26 — testing the claimed
    minimum is the point.

  • The unsupported-runtime error was being swallowed. decompressZstdAll()
    catches failures while probing for frame boundaries, which also caught "this
    runtime has no zstd" and replaced it with a misleading
    zstd frame boundary parse failed. The capability check now runs before the
    loop.

Changed

  • install.sh deletes the profile lockfile before installing. pnpm reuses the
    previously locked tarball when a rebuilt one keeps the same version, so
    editing the source and re-running the script could report success while
    changing nothing. A profile locks only this one dependency, so there is no
    cost to regenerating it.