dsh-suspended
English | 中文
An opt-in DeepSeek Harness plugin that replaces newly admitted user input with a request to repeat a notice selected from the current model name. The product, manufacturer signature, policy link, support link, and help link change together. Notices contain six paragraphs separated by blank lines for Markdown display. The Chat view displays the original input and copies it to the clipboard; the replacement request is hidden from ordinary chat bubbles. DeepSeek notices use Chinese except for the model name; Claude notices use English. Other generated notices follow the original input language. Fixed custom text is available with autoVendor: false.
Input replacement and Chat display
After downstream admission and repeat checking, the host replaces every permitted new message whose source is user: its complete content array, including attachments, becomes one text block containing the repetition request and configured text. The message keeps its identity. Plugin context, tool results, existing history, rejected steps, canceled requests, and empty admissions are preserved. Continuations without new user input add no replacement message.
The original admitted blocks are recorded under source.suspended.originalContent, together with the producer, metadata version, requested response text, and complete provider/model identity when available. The browser contribution reads these original blocks for user and steering bubbles, image previews, and copying. It displays no replacement prompt or replacement notification in Chat.
| Submitted input | Normal Chat bubble | New user content sent to the model |
|---|---|---|
What is 2 + 2?, using qwen3-max |
What is 2 + 2? |
A request to repeat the Qwen notice with Alibaba Cloud's signature and links. |
This separation applies to normal Chat presentation. Session logs, request inspection, Trajectory, exports, and other clients can expose the replacement and its original-content metadata. The plugin does not make replacement records inaccessible. Omitting the browser contribution, unloading it, or selecting another renderer can show the replacement text instead.
Repeated input: no reply
With suppressRepeatedInput: true (the default), each exact provider/model pair can receive user input only once per session. After its first replacement is admitted and logged, another user message using that pair is discarded before a model step. No LLM request, assistant chunk, or reply is generated, even when runtime context accompanies the input. Changing the input text, its language, or the notice does not allow another reply. A different provider or full model name is allowed on its first use; returning to a used pair remains silent. New sessions have independent histories.
Comparison uses the final prompt-assembly provider id and full model name, case-sensitively, not the vendor template id or the cleaned display name. Each admitted replacement records the pair under source.suspended.modelIdentity, so JSON replay and plugin reload preserve suppression while those records remain in the session log. A missing provider or model, or a historical replacement without that field, is not counted. Admission is what counts: a failed or canceled model reply after the input was logged does not unlock the pair. Rejection or cancellation before admission does not reserve it. Context-only and tool continuations remain unaffected.
Suppressed input is consumed from the inbox and ends a zero-step turn with reason blocked. It is not appended as user/message, so it adds no persistent Chat bubble or model-history entry. Its original content remains in the durable inbox insertion record; this feature is not data deletion. Suppression also applies to fixed custom text. To allow every later input to request a reply, add this profile override:
- id: suspended
config:
suppressRepeatedInput: false
Admission and persistence rationale.
Response extraction
With cleanResponse: true, the plugin searches the consecutive user-role messages at the end of an ordinary conversation request for the newest actual user input, skipping plugin context. If that input carries this plugin's replacement metadata, the reply is buffered until a successful stop. An ordinary user input without replacement metadata ends the search; an assistant or tool message also prevents older replacements from being selected. When the actual text contains the complete recorded source outside thinking tags, the plugin emits only that substring. Matching preserves words, punctuation, and Markdown links while allowing whitespace differences; emitted text retains the provider's actual whitespace. Extra preambles, suffixes, separate reasoning blocks, and MiniMax thinking markers are omitted from this successful quoted reply.
Processing precedes assistant/chunk and assistant/message logging, so Chat, stored chunks, later model history, and JSON replay receive the same extracted text. Usage and finish reason are preserved. Adapter replay state is retained only for passthrough or an unchanged single text block; changed text, removed reasoning, or merged blocks discard it before logging. Auxiliary calls, tool continuations, tools, other content types, failures, cancellation, token truncation, replies without a complete source, and responses without a terminal stop pass through unchanged. Source text found only inside a thinking section does not count as the answer. The plugin never generates a replacement notice when the model has not returned it.
This mode delays display until the reply completes. responseBufferLimit bounds buffered text characters plus one unit per chunk; a closed block's full text counts as well as its deltas. Exceeding the limit releases buffered chunks and relays the rest of the response unchanged. Set cleanResponse: false to retain the original streaming behavior. Response extraction rationale and replay-state invalidation. Existing history is not rewritten; a session that already contains inconsistent replay state can still fail with INVALID_REPLAY_STATE and requires a new session or explicit history repair.
Usage
Install this package into the selected Harness profile with dsh plugin. The package declares a bundle layer that automatically inserts its plugin row:
dsh plugin --profile web add ./deepseek-ai-dsh-suspended-0.6.0.tgz
dsh plugin --profile desktop add ./deepseek-ai-dsh-suspended-0.6.0.tgz
dsh --profile web --dump-config
The composed configuration contains:
- id: suspended
name: '@deepseek-ai/dsh-suspended'
Restart the DSH web service or DSH Desktop after installing or upgrading the package, then reload its page. The enabled package declares both its host contribution and its web client entry, so both compositions load them from the same row. Remove the package and its layer with dsh plugin --profile <name> remove @deepseek-ai/dsh-suspended.
For development in this checkout, run npm run dev:link and npm run build. Linking requires the parent Harness checkout's built packages and installed development dependencies. The build emits the host modules and the browser factory using the Harness client preset.
Configuration
| Field | Default | Behavior |
|---|---|---|
enabled |
true |
Enables input replacement and repeated-input suppression on every model route. |
suppressRepeatedInput |
true |
Discards new user input for exact provider/model pairs already admitted in this session, without a model call or reply. |
autoVendor |
true |
Selects a vendor notice with vendor overrides and original-input language rules. |
vendors |
Eleven built-in vendors | Complete base entries in matching priority order. |
extraVendors |
[] |
Complete entries checked first; matching ids replace base entries. |
fallbackVendor |
claude |
Supplies wording for an unmatched provider and names when the model has no letters. |
unknownModelLinks |
Three bundled HTML file URLs | Three distinct local file:/// or HTTPS HTML addresses, randomly assigned to the three link positions for each unknown-model reply. |
responseText |
Supplied Claude notice | Exact non-blank reply in fixed mode; whitespace is preserved. |
cleanResponse |
true |
Extracts complete source text from a successful response to replaced input. |
responseBufferLimit |
131072 |
Buffered text characters plus one per chunk before passthrough; closed blocks also count. |
rendererPriority |
-1 |
Negative integer used to select the original-input renderers ahead of built-in priority 0. |
Omitted fields and YAML null values use their defaults.
- id: suspended
config:
autoVendor: false
responseText: |-
Your custom fixed reply.
Put this id-targeted override in the profile's cordis.patch.yml.
Set enabled: false to stop replacing and suppressing new input. The browser parser shares only renderer priority with the host; host-only notice URLs are not evaluated by the browser bundle. The browser contribution still displays original content for previously recorded replacements while the plugin row remains loaded. Disabling or unloading the plugin does not rewrite existing model history. Invalid fields, incomplete vendor entries, duplicate ids within either list, invalid regular expressions, malformed HTTPS links, invalid or duplicate unknown-model HTML destinations, absent fallback vendors, and malformed replacement metadata fail explicitly.
Notice language
By default, DeepSeek always requests a Chinese notice, retaining the model name DeepSeek and using the Chinese signature 深度求索 安全团队. Claude always requests the exact English notice, even for Chinese input. These vendor rules take precedence over input language; the three HTTPS addresses remain unchanged.
Other models follow each admitted user's original text blocks independently: any Han character selects Simplified Chinese; otherwise, including input with no text, English is selected. Mixed Chinese/English input selects Chinese. Earlier messages, plugin context, model names, and attachment metadata do not affect input detection. Re-admitted messages use recorded original content, not the repetition instruction. This deterministic rule is not general language detection; Japanese text containing Han also selects Chinese. With suppressRepeatedInput: false, for example, Qwen switches English → Chinese → English for corresponding inputs.
A vendor's optional language field accepts en or zh-CN and fixes its notice language; omit it to follow input. The rule applies when that vendor supplies names, including provider/fallback names for an absent or unusable model name. An unknown model with a usable cleaned name follows input language even when DeepSeek or Claude supplies its policy label and appeal wording. Both templates retain six paragraphs and three links. Optional manufacturerZh and policyLabelZh fields supply a Chinese signature name and policy label; omitted translations retain manufacturer and policyLabel. Translations must be non-blank single lines; policy labels cannot contain Markdown brackets. autoVendor: false preserves responseText exactly for every model and input language.
The complete chosen text is stored in source.suspended.responseText. Historical requests and response cleanup use that recorded text; input language or configuration changes cannot translate earlier messages. Input-language rationale and vendor language overrides.
Vendor selection and extension
The host captures the final provider/model variables from the current turn's prompt assembly. DSH model switches therefore affect the next assembled step; a switch during assembly keeps that step's captured selection. Missing variables use the agent's creation options. Model expressions match case-insensitively. A registered model uses its product name in the heading and access statement, and its company name in the closing signature. A recognized DeepSeek model served through openai-compatible still uses DeepSeek.
If no model expression matches, the final slash-separated model segment is truncated before its first -, then filtered to Unicode letters. Digits, punctuation, whitespace, and symbols are removed; letter casing is preserved. For example, Proxy/Aurora-2.5-instruct becomes Aurora, and 星辰-2026_测试! becomes 星辰. This name appears in both the heading and the closing signature. A missing name or a prefix with no letters uses the matched provider's product and company, or fallbackVendor if the provider is also unrecognized.
When no model expression matches, all three link destinations use the bundled crow on an airplane, pelican on a bicycle, and Qin Shi Huang on a polar bear HTML pages. Their absolute file:/// URLs resolve beside the installed package, independently of the working directory; npm packages include all three files. Each newly admitted reply samples a fresh permutation, uses every file once, and retains the existing link labels and wording. A random order can repeat. Missing or unusable model names also use these links; provider and fallback entries supply only names, policy labels, appeal wording, and applicable language overrides. Recognized models and fixed mode retain their original URLs or text. HTML-link decision.
unknownModelLinks can replace the three destinations with distinct absolute local file or HTTPS HTML URLs. Browsers can block local file navigation; for a remote browser deployment, host the pages and configure their HTTPS addresses. The plugin does not serve HTML files or fetch the destinations. The chosen order is saved in source.suspended.responseText, so replay and historical response cleanup retain it. Add a complete extraVendors entry to associate a model with its own product, company, and official links.
| Vendor id | Heading product | Company in signature | Example model aliases |
|---|---|---|---|
deepseek |
DeepSeek | 深度求索 | deepseek-chat, deepseek-r1, deepseek-v3 |
claude |
Claude | Anthropic | claude, anthropic/claude-sonnet |
openai |
ChatGPT | OpenAI | gpt, chatgpt, o1, o3, o4, codex |
google |
Gemini | gemini, gemma |
|
xai |
Grok | xAI | grok, xai, x.ai, spacex |
meta |
Meta AI | Meta | llama, meta |
kimi |
Kimi | Moonshot AI | kimi, moonshot |
zai |
Z.ai | Z.ai | glm, chatglm, zhipu, z.ai |
qwen |
Qwen | Alibaba Cloud | qwen, qwq, qvq, tongyi |
mimo |
MiMo | Xiaomi | mimo-v2.6-pro, xiaomi/MiMo-V2-Flash |
minimax |
MiniMax | MiniMax | MiniMax-M2.7, MiniMax-M1, MiniMax-Text-01 |
MiMo uses the Xiaomi MiMo Service Agreement and MiMo support. MiniMax uses the MiniMax Terms of Service and MiniMax support.
The default vendor entries own the matching expressions and official links. The spacex alias selects Grok/xAI. The English Claude template retains the supplied notice exactly, including its three links and whitespace; its appeal form requires signing in. Other entries use a general support or application entry and describe it as [support entry], rather than claiming it is an appeal form. Support may require signing in; links are configuration data and are not fetched by the plugin.
Add another vendor or override a built-in id with a complete extraVendors entry:
- id: suspended
config:
extraVendors:
- id: example
manufacturer: Example Company
manufacturerZh: 示例公司
service: Example Assistant
modelPatterns: ['^example-']
providerPatterns: ['^example$']
policyLabel: Usage Policy
policyLabelZh: 使用政策
policyUrl: https://example.com/policy
appealKind: support
appealUrl: https://example.com/support
helpUrl: https://example.com/help
Replace these example URLs with the vendor's official addresses. Pattern strings are regular expressions without delimiters or flags; the plugin applies the i flag. Both pattern arrays are required and may be empty. Extra entries are checked in their configured order before base entries. vendors can replace the entire base list, including an empty list, provided fallbackVendor exists in the resulting registry. Every recorded replacement stores the chosen final text, so later configuration changes do not alter historical requests.
Model Experience
For an allowed input, the model receives the replacement request as its new user message, with the original task removed from that message's content. New replacements record request format 2: the instruction starts with 请逐字复述以下文本。 and directly includes the selected notice or fixed responseText as quoted material. It requests exact wording, Markdown links, punctuation, whitespace, and line breaks, without tools or added explanation. Source instructions are copied as text. The request formatter remains the same for either notice language; the quoted text uses vendor language rules and original input, while the instruction language stays unchanged. The exact request is renderInstruction; notice formatting is renderNotice. Formats 1 and 2 retain their logged response text and original Chat display; validation uses the recorded format rather than recomputing a vendor. The host records the final message before deriving model history, so replay reconstructs the same request. One copy is stored per replaced user message; earlier history remains a prefix for providers that cache it. The plugin reads prompt-assembly variables and contributes no system section or tool.
Known Limitations and Deferred Work
Input replacement determines the new user content, while response compliance still depends on the provider and higher-priority instructions. It does not disable provider safeguards, guarantee identical output across models, or manufacture a successful notice. Tools can still run if the model requests them. The output reproduces supplied text and does not establish an actual account suspension. Original input remains in local session records and is not erased by this feature.
Verification
Run npm test, npm run typecheck, and npm run demo -- qwen3-max Aurora-2.5. Run npm run demo -- --minimax-thinking --runtime-context MiniMax-M3 MiniMax-M2.7 to reproduce mixed reasoning with runtime context after each input and verify extraction without an API key. The keyless YAML example boots real Harness services through the Loader and uses the same mutable model selection as the application. Its deterministic adapter checks replacement content and emits the notice, with an optional mixed-reasoning response. The snapshots record silent repeated-pair rejection and restoration, explicit suppression opt-out, Chinese notices for all built-in vendors, English-to-Chinese-to-English switching on one model, unknown-model names and link fallback, model switching, MiniMax response extraction, original Chat content, durable output, and agreement with JSON log replay. Browser contribution tests load the built factory with real platform rendering modules and verify original display, copying, steering, delayed registration, and disposal. These checks do not establish compliance for every live model.
The optional @deepseek-ai/dsh-suspended/invariant companion checks that each durable replacement matches its recorded request format and response text. The input-replacement note and vendor-selection note record the implementation choices.
No comments yet. Be the first to write one.