Passer au contenu principal
K

dsh-session-export

kittimzhe/dsh-session-export

Deterministic session evidence reports for DeepSeek Harness: /transcript writes styled single-file HTML / Markdown / JSON reports from canonical session logs, /stats prints a terminal stats card, /archive writes per-session ZIPs

Installer

dsh plugin --profile web add github:kittimzhe/dsh-session-export

README

dsh-session-export

English | 中文

CI npm version npm downloads License: MIT

Deterministic session evidence reports for DeepSeek Harness: /transcript writes a styled single-file HTML report or Markdown/JSON transcript, /stats prints a terminal stats card, and /archive writes raw session logs as per-session ZIPs — all to a host path, on any persistence backend (JSONL or SQLite).

Reads the session log itself through ctx.sessionQuery — no recorder, no resident memory, no drift. Sessions that existed before the plugin was installed export just as well as live ones.

Quick Start

Requirements: Node.js 20 or 22 · a DeepSeek Harness profile that mounts the commands and sessionQuery services (the shipped web / agent profiles qualify).

dsh plugin --profile web add dsh-session-export

Then, inside any session:

/transcript        # single-file HTML replay report of the current session
/stats             # terminal stats card with cost estimate

Full details — GitHub install route, cordis.patch.yml snippet, configuration — in Install below.

Positioning

dsh-session-export is a session evidence layer, not a memory optimizer.

  • It focuses on auditability (what happened, in which order, with what failures).
  • It focuses on reproducibility (stable outputs, portable files, deterministic render).
  • It focuses on operations (batch archive, host-path artifacts, print-ready reports).

If your primary goal is context compression or long-term semantic memory, use a memory framework; if your primary goal is evidence, review, and postmortem quality, use this plugin.

Competitive context

Capability focusOfficial /exportRecorder-style exporterMemory frameworksdsh-session-export
Primary outcomeRaw artifact downloadHuman-readable transcriptContext/memory optimizationEvidence-grade replay report
Data sourceRaw log packageSide-channel listenerDerived memory structuresCanonical session log (sessionQuery)
Historical coverageBackend-limitedOften partial without backfillUsually selective recallFull history (incl. pre-install sessions)
Persistence backendsJSONL onlyWhat the listener sawFramework-specificAny backend (JSONL, SQLite, …)
StatsIn-panel countersFramework-specific/stats card + cost estimate + tool ranking
Lineage / diffs / timelineMermaid lineage, editor diffs, turn timeline
Batch/archive --all --since
Operational artifactsBrowser ZIPUsually one-off exportsMemory state / indexesHTML/MD/JSON + /stats + /archive ZIPs

Official ecosystem note (2026-09): the official @deepseek-ai/dsh-session-log-export (browser download of raw JSONL/zstd ZIP, JSONL backend only) and @deepseek-ai/dsh-session-stats (base stats projection) are the raw-utility layer; this plugin is the evidence layer built on top — deterministic replay reports, SHA-256 manifests, redaction, policy packs, output contracts, /diff and /bundle.

Roadmap

  • P1: report diff mode — compare two exports and generate a structured session delta report (shipped in v1.6.0 → /diff <id1> <id2>).
  • P1: policy pack — team-level presets for masking, retention, and output contract (shipped in v1.5.0 → preset: 'compliance' | 'full').
  • P2: bundle handoff — one command to package replay report + raw archive + manifest for review workflows (shipped in v1.4.0 → /bundle).

Why

The shipped @deepseek-ai/dsh-session-log-export downloads a raw JSONL/zstd ZIP through the browser and supports the JSONL backend only. This plugin covers what it explicitly defers (see the table above).

Transcript semantics follow @deepseek-ai/dsh-session/surface: the plugin renders append-origin surface events — everything the user actually saw — instead of the model-visible surface, whose compaction replacements would erase conversation the user already read.

Commands

InputResult
/transcriptExport the current session → <session cwd>/dsh-transcripts/transcript-<id8>-<timestamp>.md
/transcript --htmlSingle-file HTML report: KPI cards, turn timeline, tool ranking, error highlighting, dark/light theme, print-to-PDF
/transcript --json / --md / --htmlPick any combination of formats
/transcript <path> / --out <path>Write to the given path (spaces allowed after --out)
/transcript --id <sessionId>Export another session
/transcript --last 30mPartial export: entries from the last 30 minutes (7d/12h/30m/90s)
/transcript --errors-onlyDebug view: failed tool results with a two-entry context window
/transcript --maskRedact likely secrets (API keys, bearer tokens, private keys, emails) from the output
/transcript --mask-hashDeterministic redaction: secrets become #xxxxxxxx digests — same secret → same marker, equality survives redaction
/transcript --manifestEvidence manifest: write a .manifest.json sidecar with byte size + SHA-256 for every artifact of this run
/transcript --fullAppend log-only events + Mermaid turn timeline
/statsTerminal stats card: messages, turns, duration, tool calls (with failures), tokens, cost, per-tool ranking, sparkline — no files written
/bundleReview ZIP: transcript report(s) + raw JSONL archive + sha256 evidence manifest — one command for audit/review workflows
/bundle --mask --manifestRedacted transcript + evidence manifest
/bundle --no-archiveTranscript-only review pack
/archiveArchive the current session (incl. subagent descendants) → per-session ZIP
/archive --all --since 7dBatch-archive every session from the last 7 days
/diff <id1> <id2>Session diff: compare two sessions — common prefix, unique tails, stats delta (terminal or --html report)

Like every ctx.commands command, all four run on the human-command plane: results never enter model history and cost zero tokens.

Model-facing tool (v1.3)

Set exposeTool: true to register transcript_export — the same export kernel as a typed tool the model can call. The intended bridge: a dsh-session-recall hit returns a sessionId; the model hands it to transcript_export and the user gets a full evidence report on disk. One format per call (html default, md / json), optional mask / manifest / last; files always land in the standard dsh-transcripts directory (or defaultDir), with timestamped names that never overwrite. The tool is opt-in because it puts a host-file write in the model's hands.

The HTML report

HTML report (light theme) HTML report (dark theme)

/transcript --html writes one self-contained file — no external CSS/JS, opens offline:

  • KPI cards: messages, tool calls (failed highlighted), tokens in/out, duration, turns, cost
  • Turn timeline: one colored bar per turn, proportional to wall-clock share
  • Tool ranking: horizontal bars with per-tool failure counts
  • Token sparkline: inline SVG, output tokens per assistant message
  • Error focus: failed tool results get a red border, banner, and auto-open; a header link jumps straight to the first failure
  • JSON syntax highlighting: tool arguments and JSON results get token colors (keys blue, strings green, numbers amber) — no external highlighter
  • Bilingual labels: lang: zh renders the entire report in Chinese; default is English
  • Native tooltips: hover KPI cards, timeline bars, and sparkline bars for details
  • Native folding: tool arguments/results and reasoning in <details>
  • Per-turn folding: the transcript groups into collapsible turns (duration · entry count · ⚠ flag); the sticky toolbar gives TOC chips + live search (/ to focus) for long reports
  • Copy buttons: one click to copy any tool argument/result/diff/reasoning block
  • Dark/light theme: follows prefers-color-scheme, toggle button, remembered
  • Print → PDF: @media print rules; printing auto-expands all folds — archival copies in one Cmd+P

Markdown output gains a Mermaid lineage graph (GitHub/VSCode render it natively) and a Mermaid turn-timeline gantt with --full.

Cost estimation

Set a price table once and every export/stats run shows the estimated cost:

- id: session-export
  name: 'dsh-session-export'
  config:
    pricing:
      inputPerMillion: 0.27   # your per-1M-input-token price
      outputPerMillion: 1.10  # your per-1M-output-token price
      currency: '$'           # label rendered next to the estimate

Install (out-of-tree plugin)

From npm:

dsh plugin --profile web add dsh-session-export

Or from GitHub:

dsh plugin --profile web add github:kittimzhe/dsh-session-export

Then add to the profile's cordis.patch.yml (the row requires commands and sessionQuery services, which the shipped profiles already mount):

- id: session-export
  name: 'dsh-session-export'

Configuration

Plugin row config (all optional):

- id: session-export
  name: 'dsh-session-export'
  config:
    preset: compliance                 # one-line policy pack: 'baseline' (default), 'compliance', 'full'
    defaultDir: /absolute/output/dir   # default: session cwd + dsh-transcripts/
    argCharLimit: 512                  # rendered tool-argument cap
    resultCharLimit: 2048              # rendered tool-result cap
    lang: zh                           # HTML report labels: 'en' (default) or 'zh'
    mask: true                         # redact secrets by default (--mask per run)
    maskMode: hash                     # replacement mode: 'mask' (placeholders, default) or 'hash' (deterministic digests)
    maskPatterns: ['OPS-\d+']          # extra masking regexes
    manifest: true                     # write a .manifest.json sidecar by default (--manifest per run)
    exposeTool: true                   # register the model-facing transcript_export tool (default false)
    pricing: { inputPerMillion: 0.27, outputPerMillion: 1.10, currency: '$' }
    archiveDir: /absolute/output/dir   # default: session cwd + .dsh-archives/
    includeDescendants: true           # /archive --id default
    maxSessionsPerRun: 100             # safety cap on /archive --all

What the Markdown contains

  • Header table: session id, project, created, agent preset, message/tool-call counts (failures), token totals, duration, cost, generator
  • Lineage: Mermaid graph + ancestor chain and recursive subagent descendant tree
  • Transcript in log order: user messages, assistant messages (provider/model provenance, token usage, collapsible reasoning), tool calls (arguments truncated; str_replace_editor rendered as ```diff blocks), tool results (error-aware)
  • --full: Mermaid turn timeline + log-only events appendix

Known limitations

  • Exports run through the trusted ctx.sessionQuery seam; a composition without it cannot mount this plugin.
  • Report bytes are not reproducible (embedded generation timestamps); --manifest provides integrity (SHA-256 per artifact), not reproducibility.
  • Token totals sum per-assistant-message usage records; steps whose adapter reported no usage contribute zero.
  • Cost is an estimate from list prices; cache-hit discounts are not modeled (cacheReadTokens is not priced separately).
  • Masking is pattern-based and best-effort: it redacts common credential shapes, not all possible secrets.
  • Markdown escapes nothing inside fenced blocks; a diff whose own lines start with +/- renders as additional diff lines (acceptable for a diff view).
  • /archive is export-only: there is no restore/import because DSH exposes no write-side session seam, so the ZIP is a backup, not a round-trip.

Development

Local type-checking of the tool module needs @deepseek-ai/dsh-tools (^0.1.1-rc.2, an optional peer) resolvable. Its transitive @deepseek-ai/dsh-agent@0.1.1 line is currently unpublished on npm, so a fresh install cannot pull it. Run the self-check to verify (and auto-fix) your environment:

npm run doctor

It links @deepseek-ai/dsh-tools from a sibling checkout automatically when available; the manual equivalent:

ln -s ../dsh-session-recall/node_modules/@deepseek-ai/dsh-tools node_modules/@deepseek-ai/dsh-tools

License

MIT

Community

Plugins associés