Sessions & Messages

dsh-engine-switch

Yuki-takuya-kun/dsh-engine-switch · ★ 1

Yuki-takuya-kun

Route DeepSeek Harness top-level sessions to pluggable loop engines by agent-preset — Claude Code ships as a built-in engine.

License
MIT
Added
2026-08-16
Maintenance
active
Install kind
github
Manifest details
Manifest status
Declared
Manifest path
package.json#dsh
Manifest checked
2026-08-19
Lifecycle scripts
None found

Static manifest checks report declarations only; they are not compatibility or security review.

安装

dsh plugin --profile web add github:Yuki-takuya-kun/dsh-engine-switch

GitHub 源码安装:首次需按提示配置 allowBuilds 构建授权后重试

For install and environment setup, plus plugin development tutorials, see DSH community docs ↗

README

Source README · body: en · Read Chinese README

Table of contents
  1. ✨ What it does
  2. 🚀 Install
  3. ⚙️ Enable
  4. 🎯 How a preset picks an engine
  5. 🔌 How an engine registers
  6. ⚙️ Config
  7. 🔍 How it works (optional)
  8. 📄 License

✨ What it does

  • 🔀 Pick engine by preset: each session is driven by whichever engine its current preset points to. Order: preset declares one > config points one out > preset name equals engine name > default DeepSeek.
  • 🔁 Switch before typing: change preset before sending the first message and the session switches engine on the spot (either direction) — no new session, no restart.
  • 📦 Preset auto-installed: once an engine is installed, the presets it ships are copied into DSH's preset directory and show up in the picker right away.
  • 🤝 Engine and session stay out of each other's way: an engine never learns about "presets", and a session never learns it "was switched" — each just does its own job.
  • 🌐 Subagents always use DeepSeek: regardless of what the top-level session picked, subagents keep going through DeepSeek.
  • ⏯️ Resume picks it back up: continuing a past session re-finds the right engine from the preset recorded in the log.

🔌 In one line: this plugin itself ships no engine and no preset. It only defines "how an engine plugs in", then handles three jobs — pick the engine by preset, switch before typing, install the preset. Actual engines are registered by other plugins via ctx.engineSwitch.register(engine). deepseek is a special name meaning "fall back to DeepSeek's original loop".

🚀 Install

dsh plugin --profile web add github:Yuki-takuya-kun/dsh-engine-switch
# then install at least one engine plugin, e.g.:
dsh plugin --profile web add github:Yuki-takuya-kun/dsh-claude-code

⚙️ Enable

Edit ~/.dsh/profiles/web/cordis.patch.yml:

- id: dsh-engine-switch
  config:
    enabled: true

Restart the web app. Presets shipped by engine plugins appear in the picker; pick one → that engine, anything else → DeepSeek.

🎯 How a preset picks an engine

Most of the time you do nothing: an engine's shipped preset has a directory name equal to the engine name, so it auto-matches (e.g. dsh-claude-code's preset directory is claude-code, and so is its engine).

To point one manually, two ways (highest priority first):

  1. Declare it in the preset: edit the preset's agent.cordis.yml, add a dsh-engine-switch entry with engine:

    # ~/.dsh/.agent-presets/<preset-name>/agent.cordis.yml
    - name: dsh-engine-switch
      config:
        engine: claude-code   # this preset runs on the claude-code engine
    
  2. Point it out in config: write "preset name → engine name" in engineByPreset, no preset-file edits:

    config:
      engineByPreset:
        research: claude-code
    

With neither set, it falls back to defaultEngine (default deepseek, i.e. DeepSeek).

🔌 How an engine registers

Write a plugin that inject: ["engineSwitch"], then call ctx.engineSwitch.register(...) in apply:

export const inject = ["engineSwitch"];
export function apply(ctx) {
  ctx.engineSwitch.register({
    id: "claude-code",              // engine name = its shipped preset's directory name
    name: "Claude Code",
    description: "…",
    presetDir: fileURLToPath(new URL("./presets/claude-code/", import.meta.url)),
    makeAgent(loopCtx, id, options, session, engineConfig) {
      return new ClaudeCodeAgent(loopCtx, id, options, session, engineConfig);
    },
  });
}

presetDir holds agent.cordis.yml + preset.yml; the framework installs them to ~/.dsh/.agent-presets/<id>/. See Engine API for the full interface an engine implements.

Reference engine: dsh-claude-code — a real plugin that registers a claude-code engine, driving sessions with the local Claude Code CLI.

⚙️ Config

Key Default Meaning
enabled false master switch: false = plugin does nothing, sessions stay on DeepSeek
defaultEngine "deepseek" engine for presets that name none (and preset-less sessions); deepseek = fall back to DeepSeek
engineByPreset {} "preset name → engine name" overrides
engines {} "engine name → engine's own config" (passed through verbatim, unparsed)

🔍 How it works (optional)

  • On startup the plugin swaps DSH's session-driver factory for a router that picks the engine by preset.
  • On create, resume, and preset switch, it resolves the engine using the order above and builds the matching driver.
  • deepseek is not a real engine — it means "fall back to DSH's original DeepSeek loop".

📄 License

MIT. See THIRD_PARTY_NOTICES.md.