Yichen Jiang d099a24cb1 fix(web): resume the preset the log records, and serialize the switch
Six review findings on the select surface, all reachable from the wire:

**Resume read the header, not the log.** The switch was recorded as
`agent-preset/selected` and every projection resolved from it, but `agentFor`
still composed from `inspected.meta.agentPreset` — the value written once at
creation. A blank session that switched and then ran turns came back after a
restart under the ORIGINAL preset, restoring that history under the tool set it
was not produced with, which is the mismatch this feature exists to prevent.
`inspected` already carries the events.

**Cold summaries dropped the preset entirely.** `summarizeCold` hand-copied
three header fields and omitted the fourth, so a restored session reported no
preset and the picker showed the deployment default. It now uses the same
projection the attached path does.

**`select` had no gate.** Two concurrent selects both passed the blank check;
the second `unmountPresetFor` then found no record, because the first had
already removed it, and both mounts installed into one agent layer. Selects on
one session now queue, and the blank check is re-read inside the queue. This is
not turn admission — a `session.prompt` racing a switch is the agent loop's to
reserve — but it closes the select-versus-select tear-down.

**A same-id restore was skipped.** The roster is a live directory, so "the same
inputs that worked a moment ago" does not hold: a changed file is exactly how a
same-id reselect fails, and skipping the restore left the agent with no
composition at all.

**`writable` was dead state**, initialized true and never set, so the row could
never disable. It now carries `settings.describe`'s bit — a browser that may
not write settings sees the current default and no control, rather than one
whose write answers `settings-not-exposed`.

**`list` was documented as id-ordered.** It is root-precedence order with each
root's own presets sorted, first root to supply an id winning.
2026-08-07 11:45:10 +08:00
2026-08-05 01:11:49 +08:00

DeepSeek Harness

English | 中文

DeepSeek Harness (dsh) is an open-source coding agent built on the DeepSeek Harness SDK.

It uses an architecture where everything is a plugin.

Internal testing notice

DeepSeek Harness is under internal testing. Features and interfaces may change.

The internal build uploads all Session Logs by default to help diagnose reported problems. Set DSH_TELEMETRY_DISABLED=1 to disable telemetry. Send feedback through the internal WeChat group.

Install

Clone the repository, then run the installer:

git clone <repo-url>
cd deepseek-harness
scripts/install.sh

The installer requires git and Node ^22.19 || >=24, offers to install pnpm when it is missing, prompts for a DeepSeek API key, builds the required repository artifacts, and launches the Web UI.

The default active checkout is ~/.dsh/source/current, and the launcher is linked into ~/.local/bin. Re-run the installer to update. scripts/install.sh owns alternate locations, update mechanics, and recovery options.

Use DeepSeek Harness

Web UI

For the recommended local interface, choose Web UI when the installer finishes. To start it later, or after updating the active checkout, build the repository and run:

(cd ~/.dsh/source/current && pnpm run build)
dsh web

The path above is the installer's default. If you set DSH_SOURCE or DSH_CURRENT, or reused an existing checkout, replace ~/.dsh/source/current with that checkout path; see scripts/install.sh for details. The Web UI is served at http://127.0.0.1:3080 by default.

Profiles

dsh boots profiles — ordered stacks of plugin-bundle patch layers under your own overrides in $DSH_HOME/profiles/<name>:

dsh --profile web                       # the browser UI (same as: dsh web)
dsh plugin --profile tui add <package>  # install a plugin into a custom profile
dsh --profile tui                       # boot it

The CLI contract describes profile layout, layer semantics, and config dump commands.

Headless

Run one task, print the final answer, and exit:

dsh --profile headless "summarize this workspace"

Automation and SDKs

From a source checkout with DEEPSEEK_API_KEY in the environment or its root .env, start the ACP automation server:

pnpm run demo:acp

The Python SDK drives a bundled JSON-RPC runtime. The examples cover the runnable headless, ACP, JSON-RPC, Code Mode, and self-referential compositions.

Why DeepSeek Harness

Built-in capabilities cover file reading, editing, and search; shell and persistent PTY execution; reusable skills; task tracking, goals, plans, todos, and background tasks; subagents and workflows; sandboxing and approvals; settings and credentials; persistent, resumable, forkable, and queryable sessions; LSP and web access; context compaction; and telemetry. Each composition selects the subset appropriate to its surface. The Web UI includes Plan Mode.

  • Everything is a plugin. Models, tools, policies, storage, context management, and interfaces are composable Cordis plugins, so deployments can extend or replace behavior without forking the agent loop. See the architecture for the underlying design.
  • Runs are reconstructable. Anything visible to the model is logged in the authoritative session stream; persistence, resume/fork/query, replay, telemetry, and UIs derive from the same events. See the session-log architecture.
  • Code Mode (opt-in). It exposes a run_code tool and a generated TypeScript SDK; only program output re-enters model context. See Code Mode.
  • Self-referential Cordis tools are opt-in. They let the agent inspect its live runtime and mount or unmount plugins while it runs. See the Cordis tools.

Community

Follow DeepSeek Harness on Twitter for project updates.

Development

Start with the development guide and read the architecture before changing packages.

For agents, follow AGENTS.md.

DeepSeek Harness is currently in internal testing.

License

BSD 3-Clause

Third-party dependencies and their licenses are disclosed in THIRD_PARTY_NOTICES.md.

Description
No description provided
Readme MIT 120 MiB
Languages
TypeScript 97%
CSS 1.6%
Python 0.7%
JavaScript 0.6%