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-aiscope —cordis → @deepseek-ai/cordis,@cordisjs/plugin-* → @deepseek-ai/cordis-plugin-*. Every harness package declarescordisas 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: truemakes the preserved semver ranges resolve to these pinned workspaces, including imports from builtlib/. Two packages are additionally force-linked viaoverrides:@deepseek-ai/cosmokitand@deepseek-ai/schemastery→link: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
| Directory | npm name (vendor/*/package.json) | Upstream original | Role in dsh |
|---|---|---|---|
cordis/ | @deepseek-ai/cordis | cordis | The core DI/plugin meta-framework — Context, Service, Fiber, lifecycle, injections |
cosmokit/ | @deepseek-ai/cosmokit | cosmokit | Common utilities (random, path, promise helpers) used across the family |
schemastery/ | @deepseek-ai/schemastery | schemastery | Type-driven schema validator (z.object, …) for every plugin Config |
loader/ | @deepseek-ai/cordis-plugin-loader | @cordisjs/plugin-loader | Runtime plugin loader owning an EntryTree; imports plugins + applies config |
include/ | @deepseek-ai/cordis-plugin-include | @cordisjs/plugin-include | File-backed loader tree: reads YAML/JSON config into entries, writes updates back |
group/ | @deepseek-ai/cordis-plugin-group | @cordisjs/plugin-group | Nested plugin groups / entry nesting |
hmr/ | @deepseek-ai/cordis-plugin-hmr | @cordisjs/plugin-hmr | Hot module replacement: watches source, clears module caches, reloads plugin entries |
logger-console/ | @deepseek-ai/cordis-plugin-logger-console | @cordisjs/plugin-logger-console | Console exporter for the built-in logger service |
timer/ | @deepseek-ai/cordis-plugin-timer | @cordisjs/plugin-timer | Disposal-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 CordisServices registered asctx.*.vendor/cordis/src/fiber.tscarries the most important local hardening (see below). The site's Cordis primer dives into it.schemastery+cosmokit— pluginConfigschemas are written asz.object({…})(schemastery), and cosmokit supplies utilities.cordisitself uses cosmokit and schemastery.loader— theEntryTreethat turns an entry list (cordis.yml) into a running plugin graph.dsh's config system (profile bundles,cordis.patch.yml,--patchoverlays) 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 toloader.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-scheduleruns its ownsetTimeout/clearTimeoutloop.)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:
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:
// 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 & release —
verify-vendored-links,rescope-vendor, and therelease(vendor)family flow. vendor/README.md— the full manifest, the local-modification log, and the sync procedure.pnpm-workspace.yaml— thelinkWorkspacePackages/overridesmechanism that pins the workspaces.docs/cookbook/adding-a-vendored-package.md— how to add a new vendored package.docs/rescope.md— the@deepseek-ainame mapping restated for consumers.