Install
Inside DeepSeek Harness, with dsh-market
dsh plugin --profile web add dshmarket
Or from the command line
dsh plugin --profile web add github:GooDAnDReaDY/dsh-dsml-artifact-guard
Installing runs third-party code with your own permissions — it can read your files, use your credentials and reach the network. Review the source first, and pin a commit (github:owner/repo#sha) when you can.
README
⚡ Overview & The Problem
When interacting with certain upstream model providers or API gateways, raw DSML (DeepSeek Markup Language) tool-invocation protocol tags can leak into the assistant's visible text stream. Users frequently see trailing protocol clutter like:
Done. All tests have passed.
</|DSML|parameter> </|DSML|invoke> </|DSML|tool_calls>
These leaked closing tags visually pollute the chat bubble, cause Markdown rendering glitches, and can confuse downstream agents or clipboard exports.
@goodandready/dsh-dsml-artifact-guard is a lightweight, host-only runtime stream interceptor for DeepSeek Harness that cleans up these terminal artifacts in real time before they reach the user interface:
- Synchronous Stream Contract Preservation: Cordis requires stream interceptors to return an
AsyncIterablesynchronously. Making interceptorsasyncreturns aPromisethat crashes the harness turn withstream is not async iterable. This guard adheres strictly to the synchronous hook contract. - Split Chunk Buffer Pipeline: Protocol tags often arrive split across multiple TCP or WebSocket text deltas. The guard maintains a small sliding buffer (
KEEP = 96bytes) to reliably match and strip multi-chunk tails. - 100% Fail-Open Safety: Never drops legitimate user or assistant text. Legitimate discussions about DSML syntax or internal tool calls are preserved intact.
- Targeted Provider & Model Scoping: Restricts processing specifically to the provider and model configurations that exhibit tag leakage, passing other model traffic through with zero overhead.
💡 Why Not in DSH Core?
As of DeepSeek Harness 0.1.7-rc.2, the core upstream stream pipeline (dsh-llm-pi-ai, dsh-llm-deepseek*, etc.) does not perform terminal DSML protocol cleanup — there is zero mention or handling of |DSML| anywhere in the core engine. When upstream gateways (e.g. commandcode, deepseek-official, or custom proxies) leak protocol closing tags at the conclusion of an assistant turn, DSH forwards them directly to the frontend.
dsh-dsml-artifact-guard serves as the universal runtime guard across all DeepSeek models regardless of provider gateway or routing configuration.
🏗️ Architecture
graph TD
subgraph DSH ["DeepSeek Harness Runtime"]
Turn["Agent Turn Execution<br/>(LLM Stream Request)"]
ChatUI["Chat UI Stream Consumer<br/>(Renders clean markdown text)"]
end
subgraph Guard ["@goodandready/dsh-dsml-artifact-guard"]
Hook["Synchronous llm/stream Hook<br/>(Returns AsyncIterable synchronously)"]
ScopeCheck{"Scope Match?<br/>(providerId & modelId)"}
PassThrough["Raw Stream Pass-Through<br/>(Zero overhead for other models)"]
Buffer["Sliding Tail Buffer<br/>(Preserves trailing 96 bytes across deltas)"]
Detector{"Terminal Artifact?<br/>(Matches leaked DSML tail at finish)"}
Sanitize["Sanitize Mode<br/>(Strips leaked closing tags)"]
Audit["Audit Mode<br/>(Emits ctx.logger warning only)"]
end
Turn -->|llm/stream hook| Hook
Hook --> ScopeCheck
ScopeCheck -->|No| PassThrough
ScopeCheck -->|Yes| Buffer
PassThrough --> ChatUI
Buffer --> Detector
Detector -->|No Artifact| ChatUI
Detector -->|Artifact detected: sanitize| Sanitize --> ChatUI
Detector -->|Artifact detected: audit| Audit --> ChatUI
✨ Features & Capabilities
1. Synchronous Hook Guarantee
Under Cordis and DSH service lifecycles, event listeners on llm/stream must return the transformed stream synchronously. An asynchronous hook wrapper will return a Promise<AsyncIterable>, causing the runtime dispatcher to immediately throw TypeError: stream is not async iterable. dsh-dsml-artifact-guard wraps the stream generator in a pure synchronous registration.
2. Multi-Chunk Tail Buffering
In real-world streaming, the artifact </|DSML|parameter> </|DSML|invoke> </|DSML|tool_calls> is frequently fractured into fragments:
- Chunk 1:
All tasks complete. </|DSML|pa - Chunk 2:
rameter> </|DSML|invoke> - Chunk 3:
</|DSML|tool_calls>
The guard retains a minimal 96-byte window until the next chunk or finish event arrives, ensuring fractured tags are seamlessly detected and sanitized as a single terminal artifact.
3. Fail-Open Architecture
- If the text contains genuine prose about DSML (e.g.
<|DSML|tool_calls>example</|DSML|tool_calls>), it is never removed. - Non-text chunks (
tool-call-delta,usage,finish) are forwarded immediately without delay. - Any malformed chunk structure passes through transparently to preserve session stability.
4. Flexible Operating Modes
sanitize(default): Strips terminal DSML closing tags and logs a warning with the count of removed artifacts.audit: Emits diagnostic logs withctx.logger.info(...)without modifying the user-visible stream.disabled: Bypasses processing entirely.
5. Native Web UI Settings Card
Registered directly in the DeepSeek Harness settings.plugin.item slot (lib/client.js):
- Reactive Configuration: Adjust
mode,providerId, andmodelIdon the fly without restarting the harness, powered by reactivescope.watch. - Snapshot State Awareness: Gracefully handles snapshot loading, ready, and unavailable states.
- Protection Bypass Warning: Displays a prominent
OFFbadge and warning banner when the guard is set todisabled.
6. One-Click In-Place Auto-Updater
A canonical HTTP management route (/api/dsh-dsml-artifact-guard/update) mounted via lib/updater.js:
- SemVer Inspection: Queries the registry and compares versions with full pre-release support.
- Loopback & Same-Origin Protection: Write mutations (
POST) are strictly restricted to local loopback connections with valid origin headers. - Clean Invocation: Executes package updates safely without risky CLI bypass flags.
7. Full Dark & Light Theme Compliance
All client UI styles are strictly tokenized via DeepSeek Harness --dsw-alias-... CSS custom properties and color-mix() functions with zero hardcoded hex or rgba color literals. High contrast and accessibility are guaranteed in both Dark and Light themes, guarded by automated regression tests (test/theme.test.js).
📦 Installation
Install into your DeepSeek Harness web profile:
dsh plugin --profile web add @goodandready/dsh-dsml-artifact-guard
Restart your DeepSeek Harness instance.
⚙️ Configuration (settings.yaml)
Configure model matching and provider targets in settings.yaml or through the Web UI:
# settings.yaml
dsh-dsml-artifact-guard:
mode: sanitize
modelPattern: "deepseek" # Case-insensitive RegExp matching all DeepSeek models
providers: [] # Empty = guard all providers; or e.g. ["commandcode", "deepseek-official"]
Configuration Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
mode |
string |
"sanitize" |
Operation mode: "sanitize" (strip tags), "audit" (log only), or "disabled" |
modelPattern |
string |
"deepseek" |
Case-insensitive RegExp matched against model IDs (e.g. deepseek, deepseek-v4.*, deepseek/.*) |
providers |
string[] |
[] |
Optional list of provider IDs. When empty, guards all providers |
providerId |
string |
undefined |
(Deprecated) Legacy exact provider identifier; maintained for backward compatibility |
modelId |
string |
undefined |
(Deprecated) Legacy exact model identifier; maintained for backward compatibility |
HTTP Management Endpoints
| Method | Endpoint | Access | Description |
|---|---|---|---|
GET |
/api/dsh-dsml-artifact-guard/update |
Web UI / Localhost | Retrieves current version, latest registry version, and update status |
POST |
/api/dsh-dsml-artifact-guard/update |
Loopback & Same-Origin | Triggers in-place package update via DSH CLI |
🧪 Testing
Run the automated test suite covering split chunks, audit vs sanitize modes, scope matching, and synchronous hook contracts:
npm test
npm run check
📄 License
MIT © GooDAnDReaDY
For a complete release history and version migration notes, see CHANGELOG.md.
Comments
Comments live in GitHub Discussions. Sign in with GitHub to post or react.