Skip to content
源码版本47f9438 (dsh@0.1)

Architecture Overview

deepseek-harness (dsh) is the open-source AI agent harness from DeepSeek. The first sentence of the repository README states its design thesis:

DeepSeek Harness (dsh)… It uses an architecture where everything is a plugin, and is powered by Cordis

"Everything is a plugin" is not marketing copy here — it is an engineering constraint enforced at the repository-structure level. This page gives the full picture first, then drills down into the subsequent chapters.

Layered Overview

dsh is a pnpm monorepo, structured in five layers from top to bottom:

  • CLI (apps/cli): parses dsh command-line arguments and dynamically boots per mode (profile / plugin / dump-config). Entry point at apps/cli/src/bin.ts:27-52.
  • Web UI (apps/web): the React half of the browser, communicating with the host half over RPC and rendering sessions, tool calls, and the Cordis plugin panel.
  • Cordis framework (vendor/cordis): the runtime core; seven modules make up its entire public surface vendor/cordis/src/index.ts:1-14.
  • Capability plugins (packages/*): each capability domain (fs/shell/llm/mcp/session/…) is its own pnpm package + Cordis plugin, totaling 360+ packages.
  • Mode patch layer (packages/bundle/*): uses YAML patches to compose plugins into "ready-to-use bundles" — base is the foundation, headless/web-app are variants.

How "Everything Is a Plugin" Shows Up in the Repo Structure

The key evidence lives in the patch file of the dsh-base bundle. The following capabilities look "core" but are in fact all patch lines:

packages/bundle/base/cordis.patch.yml:15-45 is the head of the dsh-base bundle's insert list — timer / hmr / llm / session / typert / agent-default-model / jobs / settings are all mounted in the form - id: <stable>, with no "privileged module" anywhere.

Even more pointed are "the five lines mounted by every mode" packages/bundle/base/cordis.patch.yml:420-451: tools / system-prompt / agent-loop / fs-sandbox / llm-deepseek are the baseline capabilities mounted by all modes; everything else overlays on top. This means you can fork any dsh-* package and replace it without touching the others — no "core service" is hardcoded into the binary.

Profile: The User's Private Plugin Composition

dsh does not hardcode the plugin list; it lives in the user's private profile directory:

  • initProfile creates a pnpm workspace (pnpm-workspace.yaml) under the user directory.
  • dsh plugin add <pkg> actually runs pnpm add, writing the package into dependencies apps/cli/src/plugin.ts:120-158.
  • After pnpm finishes, reconcilePlugins diffs before/after: newly-added deps that declare dsh.bundle.patch get pushed onto the dsh.profile.bundles layer stack; removed deps, or new versions that no longer declare a bundle, get spliced out apps/cli/src/plugin.ts:59-91.
  • If the new package carries dsh.bundle.patch, it is treated as a bundle layer and pushed onto the stack apps/cli/src/plugin.ts:36-45.

So "install a plugin" = install an npm package + reconcile the bundle layer stack, fully reusing pnpm's dependency management.

Layering Order of Patches

cordis.patch.yml is not an ordinary config file — it is a patch merged by layering:

Each patch line has four fields: id / name / config / disabled. Of these, disabled: !!js <expr> is the only metadata field that gets interpolated — it is evaluated against the loader context on every mount decision, so platform/environment differences (e.g. process.platform === 'win32') are routed here. !!js expressions are interpolated at mount time by @deepseek-ai/cordis-plugin-include, and process.env / dshHomePath(...) can be injected into them.

Origin of the Cordis Framework

Cordis was not rewritten by DeepSeek; it was vendored from cordiverse/cordis — the Cordis framework by Shigma, the author of Koishi, at version 4.0.1 (upstream 4.0.0-rc.7). DeepSeek rescoped it to @deepseek-ai/cordis and applied 18 local modifications, documented in vendor/README.md, mainly:

  • lifecycle hardening in cordis/src/fiber.ts (patching three reentrant disposal leaks)
  • regeneration of all package.json / tsconfig
  • extracting applyEntryPatches in include/src/index.ts + durable debounced writes
  • removing the i18n YAML dependency in hmr/src/index.ts
  • disabled: !!js interpolation in loader/src/config/entry.ts

A number of upstream Cordis ecosystem packages were also vendored: cosmokit / schemastery / loader / include / group / timer / hmr / logger-console. This means understanding the dsh runtime is essentially understanding Cordis's context/registry/service/fiber model — which is exactly what the three Cordis framework chapters cover next.

Unofficial community learning site. Content based on the MIT-licensed deepseek-ai/deepseek-harness source. · Privacy · Terms · About