Releases: abiddotdev/dsh-visualizer
Release list
v0.9.0 — write-on-demand sharing and live cross-surface sync
Changed
- Sharing is now write-on-demand instead of automatic. Every render used to mirror to disk the moment it settled, whether or not anyone ever intended to share it; the accumulated directory only bounded itself by
artifactRetentionDays. Nothing is written now until a card's Export control asks for it — and that request names only the call ({callId}), never document bytes: the host readstitle/htmlstraight out of the call's own durable session log, verifies it settled successfully as avisualizercall, and only then writes it. The write is idempotent (exporting the same call twice reproduces the same file) and rate-limited (30 requests/minute) against a scripted loop.- The card's Share button is now two states in one slot: Export until the write confirms, then Share (open) once it has — kept as two separate clicks rather than write-then-open in one, specifically to avoid a popup blocker on the tab
window.openwould otherwise have to make after an awaited network call. Copy share link and a new Unshare control (arm-then-confirm, like the gallery's own Delete, removing the export and returning the card to Export) only ever appear once something is actually exported — there is nothing to copy or unshare before that, so Copy-link no longer needs to trigger an export of its own the way it briefly did. - New host dependency on
@deepseek-ai/dsh-session(ctx.sessions), replacing the loosely-typedsession/eventlistener the streaming mirror used — this plugin previously named that package only in a comment explaining why it deliberately avoided depending on it; the export-on-demand read needs a real, durable, replayable log lookup (Session.snapshotEvents()) that a live event listener cannot provide after the fact. - The streaming
.partialsidecar mirror is gone entirely — it wrote to disk every ~120ms for every render whether or not it was ever shared, and nothing had ever read it back. - The system prompt's sharing note changed from "every render is saved automatically" to pointing the model at the Share control instead — the underlying reason to avoid a duplicate file-tool write is unchanged (the conversation log was always the actual durable copy), only the description of what the export route does changed.
- The rendered document's own bridge gained a read-only
window.share({exported, url}), requested at boot and re-pushed on every change, with adsh-share-statuswindow event alongside it for a document that wants to react rather than poll. Deliberately read-only — there is no bridge call to trigger a share from inside the document, since that would recreate the automatic-write behavior this whole change removed, just moved one layer down into model-authored script. - A page reload remounts every card at "not exported," since export status was pure in-memory React state with no way to tell a genuinely-unexported call apart from an already-shared one whose page just happened to reload.
useExportControlnow checks once on mount against the current artifact listing — the client already computes the exact name an export would carry, so finding it in the listing recovers the correct state instead of showing Export again for something already on disk. Every card reconciling at once (a transcript reload) shares one listing request rather than firing one each. A user's own click always wins over a slower-resolving check: the reconciliation only ever moves a card out ofidle, never overwrites an in-progress or already-settled one. - Exporting or unsharing from one surface now updates every other open surface holding the same file live, not just at its own next mount: a
dsh-artifact-changedwindow event fires on a confirmed export or delete, and both a card'suseExportControland the gallery tab listen for it. Deleting a file from the gallery drops it out of an open card's Share/Copy-link/Unshare immediately instead of leaving those controls pointed at a 404 until the page reloads; unsharing from a card drops its row from an open gallery tab the same way.
- The card's Share button is now two states in one slot: Export until the write confirms, then Share (open) once it has — kept as two separate clicks rather than write-then-open in one, specifically to avoid a popup blocker on the tab
v0.8.0 — actionable failures and share-link shortcuts
Added
- A failed
visualizercall now states its cause on the row (the thrown message from the result content, bounded to 160 characters) instead of only an alert icon whose tooltip readError: E_TOOL. The over-limit document and the out-of-range height were previously undiagnosable without opening the trajectory view. - Copy share link control on both cards, beside Share: puts the export page's address on the clipboard directly. Sharing previously meant opening the page in a new tab only to copy the URL back out of the browser's address bar.
- Fix control on a failed render: a settled card whose document failed to load a library or threw at runtime now offers one click that asks the model to repair it, composing the failure (the failed source URL, the error message and its line) into a
[widget]turn. These failures were previously a dead-end text notice — the settle-time check compiles script bodies without running them, so the model's own tool result said the document check passed. One request per card; the control stays visible and relabeled once spent, since the repaired render arrives as a card of its own. - Inspect control on the settled/running card: jumps to the call's raw arguments and result in the harness's trajectory view. Only available on the in-place card (
ResultRow) — the turn-tail chain's owner currency carries no per-call inspect capability, so the republished copy there shows no such control.
Fixed
- Runaway frame growth ("double height", excess blank space below the content): the auto-sizing ResizeObserver could feed back into its own measurement for documents whose layout depends on their own current size — a
100vh/100dvhcontainer (its viewport IS the frame's current height) or a "responsive" chart canvas filling an intrinsically-unsized container — each resize measuring taller, growing the frame, and re-triggering. The shell now stops trusting resize-driven measurements after 6 consecutive same-direction growth ticks, the loop's signature; explicit content-driven reports (render/commit/heartbeat) are unaffected.
Full changelog: v0.7.0...v0.8.0
v0.5.0 — harness 0.1.2-alpha.3 compatibility
Tracks the DeepSeek Harness 0.1.2-alpha.3 conversation/chat split.
| Change | Notes |
|---|---|
conversationEvents → uiConversation |
Events now register through ctx.uiConversation.events |
| Chat Node ownership split out | conversation.chat.node slot key and ChatNodeDataMap moved to the new dsh-client-ui-chat package, added as a peer dep and to dsh.client.inject |
| Peer/dev ranges bumped | dsh-* ^0.1.1-rc.2 → ^0.1.2-alpha.2 (npm's prerelease-tuple matching otherwise excludes 0.1.2-alpha.3); cordis → ^4.0.2 |
CallId → ToolCallId |
dsh-llm rename, tests updated |
| README: harness floor documented | Install section states the minimum, new Harness version section covers older builds |
⚠️ Breaking: minimum harness version
This release only mounts on harness 0.1.2-alpha.3 or newer. On an older build the tool parks at pending (waiting for service: conversationEvents).
If you are on 0.1.1-rc.2 or an earlier pre-alpha, either upgrade the harness or install the frozen compatibility branch:
dsh plugin --profile <your-profile> add 'git+https://github.com/abidhmuhsin/dsh-visualizer.git#pre-harness-0.1.2-alpha3-compat'That branch is the last state of the plugin built against the pre-0.1.2-alpha.3 client API. New features land on master only.
Verified
pnpm test— 151/151 across 16 spec filestsc -b --forceandtsdownclean, both halves- Activates against a real
dshprofile linked to the checkout
Install: dsh plugin --profile <your-profile> add 'git+https://github.com/abidhmuhsin/dsh-visualizer.git#v0.5.0'
Full changelog: v0.4.0...v0.5.0
v0.4.0 — card UX improvements
Card UX pass over the streaming and settled rows, plus an inspect false-positive fix.
| Change | Notes |
|---|---|
| Loader wave on streaming labels | 3-char bobs, staggered left-to-right, gated on prefers-reduced-motion |
| Trailing ellipsis on loading messages | Appended unless the message already ends with one (fixes an end-anchor bug in withEllipsis) |
| Wider gap before loading message | Separator 8px → 24px |
| Fullscreen control on settled rows | Expands the frame wrapper to the viewport; Escape or a second click leaves |
| Inspect false-positive fix | Script bodies masked from the tag scan |
| Agent guide | CLAUDE.md / AGENTS.md — project patterns, PR flow, bot-comment convention |
Harness compatibility: builds against 0.1.1-rc.2. This is the last release that mounts on a pre-0.1.2-alpha.3 harness.
Install: dsh plugin --profile <your-profile> add 'git+https://github.com/abidhmuhsin/dsh-visualizer.git#v0.4.0'