Back to home

royenheart

dsh-plugin-opencode-omo

deepseek harness opencode + omo (oh-my-openagent) preset

Stars
0
Language
Python
Created
Aug 16, 2026
Updated
Aug 16, 2026

Introduction

dsh-plugin-opencode-omo

@royenheart/dsh-plugin-opencode-omo

A DeepSeek Harness plugin that adds an opencode-omo agent preset (mode) to the web profile. The mode replicates the behavior of opencode + the omo plugin (oh-my-openagent), scoped to this mode only — other presets (standard/…) keep the default dsh loop, sandboxed fs, and no omo hooks.

What the mode provides

  • opencode + omo system prompt — the real opencode default.txt persona (tone, style, proactiveness, conventions, code style, task guidance) + omo's Sisyphus orchestrator identity, declared as the complete system prompt: the dsh harness identity and runtime-context snapshot are suppressed for this mode. The loop shim additionally prepends opencode's live environment block (exact model id, working dir, workspace root, git, platform, date, recomputed every step).
  • omo role picker in the composer — in dsh's existing conversation.input.left tool-row slot (after the access/plan chips): sisyphus, hephaestus (Deep Agent), prometheus (Plan Builder), atlas (Plan Executor), sisyphus-junior, athena/athena-junior/council-member, metis, momus, oracle, librarian, explore, multimodal-looker. Selecting a role swaps the session's complete system prompt and applies that role's configured model.
  • Global "Role Settings" in the dsh settings panel (settings.section): per-role primary model dropdown (follow current / fixed) under a centered "Primary model" label; a dsh-style circle "+" button opens a fallback model list below the role box (repeatable additions, cancel/close adds nothing), persisted in opencode-omo-roles settings. On request failure the loop shim advances through the role's fallback chain before the harness retry policy runs.
  • opencode toolchain (complete) — persistent bash, read/write/edit/read_image, apply_patch, glob/grep, todo_write, skill, web_fetch/web_search, lsp, exit_plan_mode (plan), ask_user_question. tool-surface.mjs overwrites the model-visible descriptions/parameters with opencode's tool/*.txt text and shims read/edit/write to opencode's parameter names.
  • omo task() surfacetask-shim.mjs registers the omo-style task(category/subagent_type/load_skills/run_in_background/task_id) invocation, mapping it onto dsh named subagents + generic delegation.
  • omo multi-role subagentsoracle (read-only advisor), librarian (external docs/code search), explore (codebase grep), metis (pre-planning), momus (plan reviewer), multimodal-looker (media), plus generic subagent/subagent_fork + workflow/ralph.
  • omo context injection — AGENTS.md/CLAUDE.md walk-up + skills/ + omo's rules-injector (.omo/rules, .cursor/rules, .github/instructions, copilot-instructions.md).
  • omo hookscomment-checker (rejects AI-slop comments on write/edit), hashline (read tagging N#HH|content + hashline_edit stale-ref guard).
  • per-mode execution backend — local filesystem (dsh-fs-local) + persistent PTY shell, isolated from other modes' sandboxed fs/shell.
  • native-seam loop shim — no dsh-side driver seam. driver.mjs is an ordinary preset plugin using the shipped seams: a dynamic ctx.systemPrompt.section({ complete: true }) recomputes opencode's env block and the selected omo role prompt per assembly; system-prompt/assemble applies opencode's model tool gating; agent/inbox/claimed, agent/pre-step, agent/request, and agent/request-error provide ultrawork detection, maxSteps, role model routing, and fallback retry. Other presets are untouched by construction.

Layout

cordis.patch.yml                 # bundle patch: self host row
install.py                       # idempotent install/uninstall (incl. user preset root)
src/                             # host + client plugin halves (role registry, settings, picker UI)
lib/                             # built host/client bundles (npm run build)
scripts/build.sh                 # typecheck + tsdown build
presets/opencode-omo/
  agent.cordis.yml               # the composition (tools, roles, hooks, LSP)
  preset.yml                     # display metadata
  persona.md                     # opencode default.txt + omo Sisyphus persona
  roles/*.md                     # subagent personas (also main-role prompts)
  roles/prompts/*.md             # primary-role complete prompts (hephaestus/prometheus/atlas/…)
  skills/                        # omo shared skills
  driver.mjs                     # native-seam loop shim (prompt/route/fallback/maxSteps/ultrawork)
  rules.mjs                      # rules-injector
  comment-checker.mjs            # comment-checker hook
  apply-patch.mjs                # apply_patch tool
  hashline.mjs                   # omo hashline read-tagging + hashline_edit

Install

Build the package first (host + client bundles):

npm run build

install.py then automates install/uninstall idempotently — it symlinks the package into ~/.dsh/profiles/<profile>/node_modules/, edits the profile's package.json (adds/removes the dependency + bundle entry), and publishes the preset through dsh's native user preset root as a real directory under $DSH_HOME/.agent-presets/opencode-omo (entries symlinked into the package, so updates stay live):

python3 install.py --profile web              # install (idempotent)
python3 install.py --profile web --uninstall  # remove

Manual alternative — the package is a dsh bundle: it declares dsh.bundle.patch and ships the preset. Load it into a profile:

dsh plugin --profile web add link:/path/to/dsh-plugin-opencode-omo

then add it to the profile's bundle list in $DSH_HOME/profiles/web/package.json and create the user-root preset directory yourself:

"dsh": { "profile": { "bundles": ["@deepseek-ai/dsh-base", "@deepseek-ai/dsh-web-app", "@royenheart/dsh-plugin-opencode-omo"] } }
mkdir -p "$DSH_HOME/.agent-presets/opencode-omo"
for f in /path/to/dsh-plugin-opencode-omo/presets/opencode-omo/*; do
  ln -s "$f" "$DSH_HOME/.agent-presets/opencode-omo/"
done

Restart dsh and select opencode-omo from the mode picker.

Required dsh-side changes

This release depends on one dsh-side patch. Apply it to deepseek-harness for full maxSteps fidelity; the patches are under patches/, split by feature:

  • patches/0001-agent-pre-step-assistant-prefill.patch — adds optional assistantPrefill to PreStepDecision, letting the loop record an assistant-role prefill before the model request. The plugin uses it to restore opencode's MAX_STEPS_PROMPT assistant-role semantics. Runtime compatibility: the host plugin scans the installed @deepseek-ai/dsh-agent-loop bundle for the compiled assistantPrefill marker. When the patch is absent, maxSteps automatically degrades to an equivalent synthetic user message (nothing is silently dropped) and the /roles response carries the warning to the browser; the web client shows it once per page load via the native @deepseek-ai/dsh-client-ui-primitives Toast (4 seconds, non-blocking).
cd /path/to/deepseek-harness
git apply /path/to/dsh-plugin-opencode-omo/patches/0001-agent-pre-step-assistant-prefill.patch
npm run build:lib:host
npx vitest run packages/core/agent-loop/tests/interception.spec.ts
  • Provider-visible format/toolChoice is still a proposal (see DSH_CHANGE_PROPOSALS.md); omo's regular path does not use it and the standalone structured-output plugin covers the common route.

Everything else runs on unmodified dsh seams: the preset is published through $DSH_HOME/.agent-presets and the composer picker occupies the existing conversation.input.left slot (the client registers through ctx.slots.inject(), so it waits for the declaring parent regardless of out-of-tree bundle apply order).

Bench experiments (equivalence validation)

Runners and reproduction notes live in tests/benches/; reports are written to docs/exps/. The scientific methodology (paired design, McNemar/bootstrap/TOST, A/A noise floor, trace alignment, cache and latency protocols) is documented in docs/exps/2026-08-16-scientific-bench-methodology.md. Design highlights:

  • Run an isolated-port dsh (opencode-omo mode, isolated $DSH_HOME) and the machine's installed opencode + oh-my-openagent (isolated XDG_CONFIG_HOME).
  • Both use deepseek-official/deepseek-v4-pro (dpsk v4 pro); the API key comes from the DEEPSEEK_API_KEY environment variable. Scripts hardcode no machine paths or secrets.
  • Tiered benches: L1 HumanEval, L2 MBPP, L3 SWE-bench-verified-mini (sampled), comparing pass@1, CoT/reasoning exposure, tool-call chains (read/edit/write/bash/test/subagents), and final patches/answers.
  • Performance: bench_metrics.mjs normalizes token usage (including cacheRead) and tool timestamps on both sides; eval_perf.mjs / eval_swe_perf.mjs produce cache hit rate, TTFT, step duration, and per-tool timing offline (see report §5).
  • MBPP fix: MBPP rows have no entry_point; the scripts infer the function name from the first assert fn(...) or the reference def fn. The old implementation hardcoded Function name: undefined, which was the root cause of MBPP behavioral divergence (see report §0 and §6.4).
  • Raw bench data is downloaded to tests/benches/.data/ and is not versioned; fetch-benches.sh reproduces the downloads and setup-homes.sh reproduces both isolated homes.

Latest results (dpsk v4 pro; L1 30×3, corrected L2 5×2, legacy L3 sample)

leveldsh pass@1opencode+omo pass@1per-item agreement
HumanEval (30 tasks × 3 repeats)1.001.001.00
MBPP (corrected entry_point, 5 tasks × 2 repeats)1.001.001.00
SWE-bench-verified-mini sample (sphinx-doc__sphinx-10323)same patchsame patchbyte-identical git diff

Full report: docs/exps/2026-08-15-opencode-omo-equivalence-bench.md; raw transcripts are under tests/benches/.runs/.

Alignment status (audited against reference/opencode + reference/oh-my-openagent)

  • Aligned: opencode default persona (complete system prompt + live env block whose provider/model now follow the same per-step route as the actual request — session live model selection or the role primary/fallback — so prompt and request cannot split; workspace root now derived as the git root); opencode tool families + gpt apply_patch/edit-write tool gating enforced on BOTH the model-visible schema and execution (tools/pre-execute deny mirror); opencode maxSteps + verbatim MAX_STEPS_PROMPT; verbatim opencode plan.txt / plan-mode.txt with dynamic ${planInfo} and the plan→build BUILD_SWITCH reminder; omo role catalog/display names; sisyphus/hephaestus/atlas/sisyphus-junior + specialist subagents; comment-checker/hashline/rules-injector hooks; generated Sisyphus routing sections; extracted omo Sisyphus model-family templates (GPT-5.5/GPT-5.4/claude-opus-4-7/claude-opus-4-8/claude-fable-5/gemini/kimi-k3/kimi-k2-7/kimi-k2-6/glm-5-2, with the dynamic Sisyphus fallback for unknown families) plus hephaestus GPT variants, all 8 atlas variants, and specialist model variants (oracle/metis/momus); omo-default per-role PRIMARY model resolution (provider-scope ordered) and fallback chains that start AFTER the primary; omo role sampling defaults (sisyphus/hephaestus GPT effort medium, atlas temperature 0.1); omo-style retryable-error gating before fallback advance; reasoning-effort selectors in role settings; ultrawork keyword override; /start-work, /remove-ai-slops, /refactor, /stop-continuation, /handoff, /hyperplan, /team-mode commands; composer role picker + global per-role model/fallback settings; omo skills published as user-dsh so the third-party skills-manager can manage them. The omo rules-injector text is now folded into the complete system prompt (driver.mjs + rules.mjs) instead of being dropped by suppressRuntimeContext(); approved plans are persisted at .opencode/plans/<created>-<session>.md; specialist subagent personas now load the extracted reference prompt files (oracle/librarian/explore/metis/momus/multimodal-looker).
  • MCP: separate plugin dsh-plugin-mcp-support mounts native @deepseek-ai/dsh-mcp-client servers from composition config or the persisted mcp-suppor settings namespace. (The directory was renamed from dsh-plugin-mcp-suppor; the npm id and settings namespace inside that repository still use the old spelling until that repository is updated.)
  • Structured output: separate plugin dsh-plugin-structured-output provides opencode-style /json-schema + StructuredOutput validation on native seams (no dsh-side format field).
  • Partial: extracted family templates keep dynamic sections filled by dsh-native data rather than omo's builder output; structured output is tool-enforced rather than tool_choice: required; hooks are regex/simplified ports; AGENTS.md injection is dsh-native; child subagents inherit the session model because dsh child headers/descriptors do not carry the subagent role id (primary-role sampling defaults ARE applied).
  • Requires one dsh-side patch (see patches/, audited 2026-08-15): PreStepDecision.assistantPrefill for opencode's MAX_STEPS_PROMPT. Provider-visible format/toolChoice remains a proposal; omo's regular path does not use it and the standalone structured-output plugin covers the common route.

Remaining gaps

  1. dsh-side (patch provided): PreStepDecision.assistantPrefill. Without the patches/ patch the maxSteps prompt is degraded to a synthetic user message; after applying the patch this gap is closed.
  2. dsh-side (proposal, medium): GenerateOptions.format / toolChoice. omo's regular path does not use them; the standalone structured-output plugin covers the common route.
  3. Child subagent per-role sampling cannot reliably resolve the role id (dsh child headers/descriptors do not carry it); primary-role sampling defaults ARE applied and children inherit the session model.
  4. Plan files: dsh itself does not persist them; the plugin writes .opencode/plans/* after exit_plan_mode approval. A first-class plan-file seam remains an optional improvement.
  5. team-mode TUI, comment-checker CLI, and hashline diff enhancer remain non-LLM/editing experience differences.