A profile manifest and a bundle manifest are different kinds and shared one flat `dsh` section: `dsh.plugins` listed bundles (not plugins) and `dsh.patch` declared a bundle's layer. Each kind now names its role — a bundle declares `dsh.bundle.patch`, a profile declares `dsh.profile.bundles` — so a package.json states which role it plays and the list name matches its contents. `DEFAULT_PROFILE_PLUGINS` becomes `DEFAULT_PROFILE_BUNDLES`, and `DshManifestSection` splits into `DshBundleManifest`/`DshProfileManifest`. Pre-release: no compatibility shim; turtle-ui moved with it (bd5ff10).
@deepseek-ai/dsh-headless
English | 中文
The dsh one-shot bundle. cordis.patch.yml rides over dsh-base + dsh-web-app: it moves the webserver to an OS-assigned port (parallel runs never collide), silences the URL line, and inserts this package's headless-runner plugin (config {task}). The runner drives one task turn through the in-process API carrier (InProcessApiClient over toFetchHandler(ctx.apiProxy), so the full wire chain — serialization, zod, SSE framing — really runs), aggregates the turn's final assistant text, writes it to stdout, and requests exit (completed → 0, else 1) through the launcher-provided ctx.headlessIo seam. The Web composition stays mounted, so the running session is observable in a browser at the stderr-announced URL. The launcher patches the task text in (dsh --profile headless "task"), and fails loud when a task is given to a profile without this row.
Model Experience
None, as the runner submits the task as an ordinary user message over the shared composition; prompts and tools belong to the base/web bundles.
KV Cache effect
None; the runner adds nothing to the request prefix.
Known Limitations and Deferred Work
- One turn only — the runner anchors on the first message-triggered turn and exits at its end; queued follow-ups and multi-turn tasks are out of scope.
ctx.headlessIois launcher-owned — booting the headless profile outside thedshlauncher fails loud at activation until the host provides the seam.