Releases: hoshF/dsh-md-export
Release list
v1.7.2 — reject corrupt zstd frames; preserve content and client lifecycle
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:zlibzstd 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; alltest/*.test.mjsfiles 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
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:zlibzstd 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 atool-resultblock 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.mdhad both of these wrong. It promised a stderr warning and an
"incomplete" mark forversion < 3that 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
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:zlibzstd 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
registerszhandendictionaries with the host's locale service and
subscribes tolocale/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 readnavigator.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. titleandaria-labeltext follow the language too.
v1.3.2 — first public release
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:zlibzstd 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.
enginessaid>=20and
the README said the same, but reading a session log needs
zstdDecompressSync, whichnode:zlibonly 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 asdoes not provide an export named 'zstdDecompressSync'.enginesnow says>=22.15, the docs say so, and
src/session.jsimportsnode:zlibas 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 now22.15.0(the real floor),24and26— 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.shdeletes 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.