DeepSeek Harness Plugin

Huang-zhishi/dsh-plugin-call-trace

Stars ★ 0 Category Tools & Capabilities Added 2026-08-15

Persistent model tool-call trace recorder: every tool call is durably written to a JSONL file that survives restarts, queryable via a structured call_trace tool and a callTraceHistory service, with size rotation and an optional floating canvas UI add-on.

Install

# from GitHub (first run asks for allowBuilds approval — follow the hint, retry)

dsh plugin --profile web add github:Huang-zhishi/dsh-plugin-call-trace

Any plugin you install runs third-party code with your own permissions — it can read your files, use your credentials, and reach the network, and tool approvals don’t sandbox it. GitHub-sourced plugins also run build scripts at install time. Only install sources you trust, and pin a commit (github:owner/repo#sha).

README

A persistent LLM tool-call trace recorder for DeepSeek Harness. Every time the model calls a tool (read / pwsh / subagent / web_search …), this plugin durably persists the call to a JSONL file — it survives restarts — and exposes a structured call_trace tool the model can query at any time, plus a callTraceHistory service for UI add-ons that want to merge history.

  • Plain ESM, zero @deepseek-ai/* runtime imports — loadable from anywhere (--patch overlay or profile install).
  • Listens to agent/request + tools/execute + tools/result (root scope, includes subagent calls).
  • Records: tool name, arguments, status (ok/error/running), result summary, duration, turn/step, agent.
  • Auto-rotates the file above 5 MB — it never grows without bound.

Install

Option A: install into a profile (recommended, distributable)

dsh plugin --profile voice add ./call-trace-plugin
dsh --profile voice --dump-config      # expect a "# == dsh-plugin-call-trace" layer
dsh --profile voice                    # start

Option B: --patch local overlay (fastest to try)

pnpm dsh web --patch D:\Java\dsh-demo\call-trace-plugin\cordis.local.yml

The name in cordis.local.yml is a file:// URL (a Windows absolute path must be a valid file:// URL); update it if you move the plugin.

Option C: tarball / npm

pnpm pack                                   # → dsh-plugin-call-trace-1.0.0.tgz
dsh plugin --profile <name> add ./dsh-plugin-call-trace-1.0.0.tgz
# or after publishing to npm: dsh plugin --profile <name> add dsh-plugin-call-trace

Configuration

Set config on the patch row call-trace-recorder (Option B: cordis.local.yml; profile install: override the row in $DSH_HOME/profiles/<name>/cordis.patch.yml).

config:
  outDir: 'D:/...'   # output dir; default $DSH_HOME/call-trace (never node_modules)

Usage

  • Query from the model: say "use call_trace to see the recent calls". The tool returns a structured array (name / status / args / summary / turn / step / agentId / durationMs / ts) the model can read directly.
  • Clear: call_trace({ clear: true }) (destructive — wipes the whole file).
  • History service: callTraceHistory.tail(n) returns parsed recent records for UI merge.

Floating UI (optional add-on)

The ui/ directory ships a dynamic-plugin floating overlay (GraphRAG-style branching connectors + Chinese tool descriptions + click-to-expand details + nested subagent branches + history merge + self/all filter). Dynamic plugins live only in process memory, so rebuild it after a restart: tell the agent "rebuild the call-trace dynamic plugin from ui/host.js and ui/client.js and run it" (see ui/DEFINE.md).

Files

call-trace-plugin/
├── package.json        # dsh.bundle manifest
├── cordis.patch.yml    # bundle layer for profile install (name = package name)
├── cordis.local.yml    # --patch overlay (name = file:// URL of index.js)
├── index.js            # entry: event listeners + JSONL + rotation + service + tool
├── ui/                 # optional floating UI (dynamic-plugin source + rebuild notes)
├── smoke-test.mjs      # recorder smoke test
├── check-syntax.mjs    # ui/ syntax check
└── README.md / LICENSE

Design notes

  • Zero @deepseek-ai/* runtime imports: out-of-tree plugins can only resolve packages in the installation's node_modules closure, so this plugin uses ctx.on events, raw JSON Schema ctx.tools.register, and ctx.provide — and exports no Config schema (Cordis passes the patch config through untouched; defaults are merged inside apply).
  • Write on completion: tools/execute records the start, tools/result records completion and flushes to disk; a crash mid-call drops that call (acceptable).
  • Rotation: trace.jsonl is renamed to trace-<ts>.jsonl above 5 MB.

Development

node --check index.js     # syntax
node smoke-test.mjs       # recorder smoke (structured output / history / parallel / rotation / clear)
node check-syntax.mjs     # ui/host.js + ui/client.js syntax

Known limitations

  • The floating UI is a dynamic plugin: the client half needs the monorepo client build chain (tsdown + slot types + props share), consistent with the official docs; it is not built into this bundle — it ships as archived source under ui/ and is rebuilt on demand.
  • No tool→plugin mapping: tool registration does not expose its provider, so cards show the tool name plus a Chinese purpose description only.
  • Subagent nesting is a time-window heuristic: calls from a different agentId inside a subagent/workflow call's execution window are folded into its "subagent branch"; extreme concurrency may misassign (use the "self" view to filter in multi-session setups).
  • Recorder + dynamic UI together: both listen to the same events and keep their own state — no conflict.

Content from the project README on GitHub ↗

Links

More in this category

View the whole category →