Skip to content

DeepSeek Harness does not pull the Cordis plugin framework from npm. Instead, vendor/ holds source-vendored copies of Cordis and its foundation libraries, renamed into the @deepseek-ai scope and pinned as workspace packages. This lets the harness fully own its framework layer — auditable, patchable, and publishable — and harden it against the real defects found while building an agent harness.

Why vendored

vendor/README.md states the contract plainly: the copies are here instead of being depended on via npm so the harness fully owns its framework layer. Three consequences follow:

  • Renamed into the @deepseek-ai scopecordis → @deepseek-ai/cordis, @cordisjs/plugin-* → @deepseek-ai/cordis-plugin-*. Every harness package declares cordis as a peer dependency, so publishing the harness publishes the framework layer too; publishing under the upstream names would squat them on the registry.
  • Directory names and upstream version numbers are deliberately preserved, so the manifest still reads as an upstream snapshot.
  • pnpm-workspace.yaml#linkWorkspacePackages: true makes the preserved semver ranges resolve to these pinned workspaces, including imports from built lib/. Two packages are additionally force-linked via overrides: @deepseek-ai/cosmokit and @deepseek-ai/schemasterylink:vendor/….

The hygiene gate verify-vendored-links asserts every vendored name resolves to a workspace link: in pnpm-lock.yaml with no registry copy alongside. rescope-vendor.ts re-applies the @deepseek-ai renaming after an upstream sync.

The vendored package roster

Directorynpm name (vendor/*/package.json)Upstream originalRole in dsh
cordis/@deepseek-ai/cordiscordisThe core DI/plugin meta-framework — Context, Service, Fiber, lifecycle, injections
cosmokit/@deepseek-ai/cosmokitcosmokitCommon utilities (random, path, promise helpers) used across the family
schemastery/@deepseek-ai/schemasteryschemasteryType-driven schema validator (z.object, …) for every plugin Config
loader/@deepseek-ai/cordis-plugin-loader@cordisjs/plugin-loaderRuntime plugin loader owning an EntryTree; imports plugins + applies config
include/@deepseek-ai/cordis-plugin-include@cordisjs/plugin-includeFile-backed loader tree: reads YAML/JSON config into entries, writes updates back
group/@deepseek-ai/cordis-plugin-group@cordisjs/plugin-groupNested plugin groups / entry nesting
hmr/@deepseek-ai/cordis-plugin-hmr@cordisjs/plugin-hmrHot module replacement: watches source, clears module caches, reloads plugin entries
logger-console/@deepseek-ai/cordis-plugin-logger-console@cordisjs/plugin-logger-consoleConsole exporter for the built-in logger service
timer/@deepseek-ai/cordis-plugin-timer@cordisjs/plugin-timerDisposal-aware timer service (mounted in the base/spine compositions; the schedule/reminders feature does not use it — dsh-schedule runs its own setTimeout loop)

Each library's role in code

  • cordis — the foundation. Everything is a plugin: the agent, LLM layer, tools, and session runtime are all Cordis Services registered as ctx.*. vendor/cordis/src/fiber.ts carries the most important local hardening (see below). The site's Cordis primer dives into it.
  • schemastery + cosmokit — plugin Config schemas are written as z.object({…}) (schemastery), and cosmokit supplies utilities. cordis itself uses cosmokit and schemastery.
  • loader — the EntryTree that turns an entry list (cordis.yml) into a running plugin graph. dsh's config system (profile bundles, cordis.patch.yml, --patch overlays) is built on Loader + Include.
  • include — a loader tree backed by a config file; includes define the patch layer that lets user config override defaults. Highly patched for dsh's transactional config-reload semantics.
  • hmr — watches files and reloads only the plugin entries that depend on a changed application file; framework changes fall back to loader.exit() (process restart).
  • group — nested groups, letting entries mount children.
  • timer — disposal-aware timers, mounted in the base/spine compositions. (The schedule feature does not build on it: @deepseek-ai/dsh-schedule runs its own setTimeout/clearTimeout loop.)
  • logger-console — routes the built-in logger to the console; the ACP server deliberately does not mount this so stdout stays protocol-pure.

How they are consumed

Every harness package declares @deepseek-ai/cordis (and sometimes the plugin siblings) as a peer dependency; pnpm-workspace.yaml#linkWorkspacePackages and the cosmokit/schemastery overrides pin them to the vendored workspaces. Consumers import them as if they were ordinary scoped packages:

ts
import type { Context } from '@deepseek-ai/cordis'
import Timer from '@deepseek-ai/cordis-plugin-timer'
import z from '@deepseek-ai/schemastery'

Third-party dependencies of the vendored packages (e.g. @standard-schema/spec, js-yaml, chokidar, picomatch) stay on npm and are not vendored.

Local modifications: honesty and depth

vendor/README.md keeps an exhaustive Local modifications log — every divergence from upstream. Notable dsh-specific hardenings: the include/group/loader transactional config reconciliation (rolled-back live updates, serialized child-tree mutation), the hmr exact-config watching and serialized refresh (with deadlock fixes), a pull of upstream PR cordiverse/cordis#41 (lazy config resolution), and cordis/src/fiber.ts lifecycle hardening that closes three reentrant disposal gaps — registering the effect's owner-list wrapper before its setup body runs, awaiting quiescence in async cleanup, and rejecting effect creation while the owner is UNLOADING.

The entries cite their downstream tests so a reviewer can find the coverage. For example, the Include serialized-write and HMR-suppression hardening is "Covered by the patch-overlay boot-failure built-bin case in apps/cli/tests/built-bin.e2e.ts", and the durable debounced Include writes are "Covered by packages/host/directory-picker-auto/tests/loader-composition.spec.ts with injected transient and terminal rename failures". Some modifications are pure pragmatism — the generated package.json/tsconfig.json regeneration, per-package tsdown.config.ts overrides (schemastery, logger-console) for dual ESM+CJS output, and @param/@returns JSDoc enrichment so the website API-reference generator hard-errors cleanly.

The AGENTS.md at vendor/ warns contributors: do not edit vendor/*/src/ casually; every local divergence must be logged exhaustively in vendor/README.md. This is what keeps the vendored layer auditable across syncs.

Consumed as peer dependencies

Because every consumer declares the framework as a peer (so publication resolves against the published scope names), a package that mounts a Cordis plugin lists it that way in its own package.json. The invariant service is a canonical example:

jsonc
// packages/runtime-diagnostics/invariants/package.json (excerpt)
"peerDependencies": {
  "@deepseek-ai/cordis": "workspace:^"
},
"dependencies": {
  "@deepseek-ai/schemastery": "workspace:^"
}

Note the split: cordis is a peer (the type surface defines Context), while schemastery is a plain dependency used only by this package's Config schema.

Sync procedure

To refresh a vendored package from upstream, the README prescribes: note the upstream git rev-parse HEAD, copy the package's src/ (plus bin.js/README.md/LICENSE when changed), re-apply the local modifications (or drop them if upstream made them unnecessary — update the log either way), update the version and commit hash in the manifest table, then pnpm install && pnpm run test && pnpm run build. Every divergence therefore carries a deliberate re-application step rather than being silently merged.

The @deepseek-ai rescope and the hygiene guarantees

The renaming is enforced, not assumed. scripts/rescope-vendor.ts rewrites every vendored manifest name, internal dependency entry, and module specifier to the scoped names (re-applied with pnpm run rescope-vendor --apply after a sync); pnpm run rescope-vendor:check verifies no unscoped reference leaked back. The hygiene bundle then confirms the whole chain with verify-vendored-links (every name resolves to a link: workspace, no registry copy) and verify-cordis-config. Because pnpm-workspace.yaml sets linkWorkspacePackages: true, imports from a package's built lib/ also land on the pinned workspace sources instead of an npm resolution.

Further reading

  • Welcome to the harness site — Cordis primer for how the framework is used.
  • CI & releaseverify-vendored-links, rescope-vendor, and the release(vendor) family flow.
  • vendor/README.md — the full manifest, the local-modification log, and the sync procedure.
  • pnpm-workspace.yaml — the linkWorkspacePackages / overrides mechanism that pins the workspaces.
  • docs/cookbook/adding-a-vendored-package.md — how to add a new vendored package.
  • docs/rescope.md — the @deepseek-ai name mapping restated for consumers.