Introduction¶
When orchestrating agents in DSH, it is often necessary to “confirm a condition before taking action”: whether the previous round reported an error, whether the user confirmed a specific plan, or whether the test passed. Writing the judgment logic directly into the prompt occupies the main context. Furthermore, judging based on rules or command parameters might rewrite the cache prefix of subsequent requests. dsh-if consolidates this into a custom /if command: the judgment is delegated to a fork sub-agent that inherits the current session context. If the condition is met, the instructions below /if are sent to the main agent as a normal user message; otherwise, nothing happens.
Below, we introduce its capabilities, installation, usage, and constraints to be aware of.
What is this¶
- Plugin Name:
dsh-if, repositorytlewa/dsh-if, npm package namedsh-if. - Maintainer: TLEWA, License: MIT.
- Category: Workflow; registered as 1 star on GitHub in the community directory.
- Position: Adds a
/ifslash command to DeepSeek Harness to have an LLM judge a condition, sending instructions only if the condition is met.
The judgmenter is a fork sub-agent that inherits the current session’s tools, system prompt, and message history, appending only one judgment instruction at the end. The judgment request shares a byte-by-byte identical tools → system → messages prefix with the main session’s next request, allowing the provider’s prompt cache / KV cache to be reused.
The expressions involving English text are excerpted from the plugin’s GitHub README; directory page and maintainer information come from its community directory entry.
Core Features¶
Listed below according to the “Features” section of the README; all are verified capabilities.
- Context Condition Judgment. The judgmenter inherits the current session’s tools, system prompt, and historical messages, answering
YESorNObased on the condition. - Reuse KV Cache. The fork sub-agent only appends one tail user message; the prefix is consistent with the main session, allowing it to hit the provider’s prefix cache.
- Read-Only Judgment. The tool directory remains unchanged. During execution, the runtime guard only allows
read/glob/grep/web_search/web_fetch/skilland other read-only tools. Writes, modifications, execution of commands, and sub-agents are all rejected. - Same Queue as Normal Messages.
/ifenters the queue panel above the input box as a normal message; it can be edited, deleted, or ↑ interrupted. Judgment occurs only at the start of a round; if the condition is met, this message is replaced in place with the instruction. - Two Queue Modes. Default is
message, meaning it queues together with normal messages;backgroundpreserves the 0.2.x behavior, returning the command immediately with judgment running in the background. - Send Only When Condition Holds. Only
YESsends the instruction as a user message to the main agent;NOdoes not trigger the main agent at all. - Judgment Not in Context. Judgment completes in an independent sub-session, does not write main session events, and does not call
agent.inject. - Command Doesn’t Leak Parameters.
recordInput: false; the log-onlycommand/runalso does not record the condition or instruction. - Multi-line Condition. The first line is the condition, the rest lines are the instructions; when the condition has multiple lines, use a separate line
---to separate them. - Auto Fallback. If the host does not have a fork provider with inheritable context, it falls back to a one-time
ctx.llm.stream+ approximately 24k character plain text record. - Prevent Mis-send. If the condition is empty, the instruction is empty, the judgment output is not
YES/NO, or the judgment times out, it returns an error and does not send.
Installation and Enablement¶
Environment Requirements:
- DSH
0.2.1-rc.5or later. - Node.js
20.3or later (usesAbortSignal.any/AbortSignal.timeout).
Install from npm (Recommended)¶
- Open the sidebar “Plugins” page → “Install Plugin”.
- Enter the package name and confirm:
dsh-if
- After installation, restart DSH (the host plugin loads when the profile starts).
Fixed Version:
dsh-if@0.3.4
Command Line Equivalence:
dsh plugin --profile desktop add dsh-if@0.3.4
Install from GitHub¶
lib/ is runnable source code and does not require local building:
https://github.com/TLEWA/dsh-if
Pin to tag or release attachment:
dsh plugin --profile desktop add github:TLEWA/dsh-if#v0.3.4
https://github.com/TLEWA/dsh-if/releases/download/v0.3.4/dsh-if-0.3.4.tgz
Install from Source¶
git clone https://github.com/TLEWA/dsh-if.git
cd dsh-if
npm test
dsh plugin --profile desktop add .
After restarting DSH, type /if in the input box, and the slash command will appear in the slash panel.
Typical Usage¶
Basic Form: The first line is the condition, the rest lines are the instructions.
/if 1+1=2
Please reply with OK only
When the condition itself has multiple lines, use a separate line --- to separate them:
/if 用户已经确认方案 A
并且测试已经通过
---
请开始执行方案 A
You can also write just one line of condition and one line of instruction; the first newline after /if is the separator point.
Separator Priority: As long as a standalone line --- appears, everything to its right is definitely instructions. Therefore, do not write --- (Markdown horizontal rule) on its own line within the instruction body; otherwise, the content before it will be treated as part of the condition.
Judgment Semantics¶
- Judgment is completed by the model configured for the current session, not by JavaScript or a math evaluator.
1+1=2is just a minimal example; the condition can be “whether the user has confirmed plan A”, “whether the previous reply contains an error”, etc. - The judgmenter is only required to output
YESorNO; if there is no recognizable result in the output, it is treated as a judgment failure, and the instruction is not sent. - The judgmenter can only read files and retrieve code to confirm facts, but cannot perform any modifications.
- If the information needed for the condition is not found in the current context, or the condition is vague and cannot be determined, it is judged as not met: it is better to do nothing than to mis-send an instruction.
- The UI only displays a generic result; it does not echo the condition, instruction, or the original judgment text.
How it Works¶
README breaks down the implementation into nine steps; a summary is provided below.
- Registration. Register
/ifviactx.effect(() => ctx.commands.register(...))and setrecordInput: false; the registration is attached to the plugin fiber and is unregistered when disabled. - Enqueue. The
messagemode sends the original/if <condition>\n<instruction>as a normal user messageagent.followup()to the session queue, entering the host durable inbox. The client queue panel displays it normally, allowing editing, deletion, and interruption. - Round Boundary Interception. When a round starts, the host picks up this batch of messages via the
agent/pre-stepwaterfall. The plugin picks out entries starting with/ifto judge in place: if the condition is met, the content is replaced with the instruction; if not, the entry is deleted from the batch. If the judgment fails, the entry is also deleted, and an error command card “【/if 未执行】” (【/if not executed】) is logged in the session, which can be restored with “Recover /if” on the right side of the card. - Preferred Fork Sub-Agent Judgment. Use
ctx.subagents.getProvider('fork')to get the provider (which requiresinheritsParentContext === true), then start the judgment sub-session viastartActivation({ provider: 'fork', childId, request: { parent, agentOptions, prompt }, delivery: 'caller' }). - Drop Inherited Todos. The fork’s seed brings back the next-turn message and unclaimed next-step interruptions to the parent session. When the plugin obtains the child agent, it removes all todos from these two queues except its own judgment prompt, leaving the parent session queue unaffected.
- Runtime Read-Only Restriction.
ctx.tools.guardonly affects the judgment sub-session, allowing read tools and rejecting writes, commands, and sub-agents. The tool directory is not trimmed, and the cache prefix remains unchanged. - Judgment Timeout. Judgment times out after 60 seconds; only when
YESdoes it hand the instruction to the main agent as an identified message withidandrole: 'user'. - Fallback Path. If the host does not have a fork provider with inheritable context,
historyTranscript()readsagent.session.deriveMessages(), keeping only user / assistant / tool messages, and generates a maximum of approximately 24k characters of plain text record (max 3k per message, keeping head and tail). It then initiates a one-time judgment request viactx.llm.stream(). This request does not have the main session’ssessionId, so it will not hit the main cache. - Background Mode. The
backgroundmode skips the enqueue and round interception steps mentioned above. The command returns immediately “Queued”, and the judgment is completed by a background task. Multiple/ifcommands are judged serially in the order they are sent.
Configuration¶
Configuration is written in the profile’s cordis.patch.yml:
# profile's cordis.patch.yml
- id: if-command
name: 'dsh-if'
config:
mode: message # Default. background = old 0.2.x behavior
mode: message(Default):/ifqueues as a normal user message first, and is judged when the round starts. The entry content is/if <condition>+ the original instruction, appearing in the queue panel. Editing it is equivalent to changing the condition and instruction.mode: background: 0.2.x behavior. The command returns immediately “Queued”, and the judgment is handed to a background task, not occupying a queue position. If the judgment fails, anifcommand card is logged in the session explaining the reason.
You can also modify the file directly: In Plugin → dsh-if → Config, there is a “Judgment Mode” dropdown that switches instantly (the mode field is declared as volatile, and the config page directly overwrites the running config). The plugin uses Config (@deepseek-ai/schemastery) to describe this field; mode defaults to message, and unknown fields are ignored.
KV Cache and Context Isolation¶
This section is an intentional design constraint, not an option.
- The
/ifcommand, condition, instruction, judgment prompt, and judgment result are not written to the main session;command/runandcommand/doneare both log-only events. - Judgment completes in the fork sub-agent. Tools, system prompt, and historical messages are all inherited, with only one user message appended at the end. Therefore, the prefix is byte-by-byte identical to the main session’s next step, allowing the provider’s prefix cache / KV cache to be reused directly.
- The judgment sub-session is an independent session that does not append main session session events, only reads history. The tool directory is not trimmed; trimming would alter the prefix and break the cache.
- The Cost is Transparent: Every judgment re-sends the entire context segment. Token counts are calculated on the full amount, and hits on the cache are charged at the provider’s cache rate. For longer sessions, the absolute token count per judgment is higher.
- When the condition is not met, there are no changes to the main session. When the condition is met, the only change is appending one normal user message at the end of the history; the existing prefix remains unchanged. It does not call
agent.inject, nor does it edit, replace, or delete existing session events.
Suitable Scenarios and Notes¶
Suitable for scenarios that require condition gating in the main workflow: executing after plan confirmation, continuing after tests pass, adding an instruction when the previous round had an error. Judgment consumes one context resend; the absolute token count is not negligible for long sessions, making it suitable for low-frequency, clearly defined gating, and unsuitable for spreading every judgment onto high-frequency paths.
Two notes:
- The plugin runs with the permissions of the current dsh process. The relevant judgment logic in
lib/is runnable source code. It is recommended to check the source code and license before installing; this plugin is MIT licensed. - Judgment relies on the host’s fork provider and
ctx.tools.guard. If they are missing, it automatically falls back to transcript judgment, which does not hit the main cache. For other host capability boundaries, please refer to the “Compatibility” section in the README.
Conclusion¶
The value of dsh-if lies in separating “judging the condition” from “executing the instruction”: the judgment happens in an independent sub-session, not polluting the main context. When the condition is met, only a normal message is appended, thereby preserving the main request’s reusable prefix. It has a clear positioning, with constraints written explicitly, making it suitable for DSH workflows that require condition gating.
- Directory: https://www.skillhub.cn/plugins/TLEWA/dsh-if
- GitHub: https://github.com/TLEWA/dsh-if
The community directory is an independent site and has no official affiliation with DeepSeek or High-Fin.