Files
deepseek-harness/packages/bundle/headless
Yichen Jiang 61d5cb9e41 fix(apiproxy): serve history events and projections from one log position
Review found two defects in the previous commit's ordering fix.

@pku-xht: `historyStateFor` copied the attached session's events, the handler
then awaited `presenterScopeFor`, and only then read the projection baseline
off the still-live Session. An append during that await served events cut at N
beside a baseline folded to N+1 — one response describing two moments. The
same restructure had also moved the baseline read outside the `try`, so a
failing snapshot escaped the structured `internal` error.

Both awaits now happen before the cut: `historySourceFor` resolves which
session serves the read, `presenterScopeFor` ensures the recorded composition,
and `historyCutOf` then reads events and baseline adjacently with nothing
between them. The whole sequence is back inside the try.

The invariant judged any scoped assembly with a chain of one as an unjoined
agent, which rejects a legitimate assembly in a standing preset key (that key
has no parent of its own). It now gates on `context.agent` — a scope-only read
is not an agent and is out of range by construction rather than by a premise
about who else calls `assemble` — and asks the roster's own
`composedPreset()` instead of introspecting chain length. The advisory warning
uses the same relation.

Also from review: the `2026-08-05-per-agent-tool-presentation` note still
described `presentAs` as per-agent, which standing mounts made false and this
branch's own rewording contradicts; the duplicated "process-wide unit table"
argument collapses to the Agent Note with pointers from the five copies; a
dead `.sort()` before `arrayContaining`; and change-history narration in the
tool-cordis README.
2026-08-11 10:45:15 +08:00
..

@deepseek-ai/dsh-headless

English | 中文

The dsh one-shot bundle. cordis.patch.yml rides directly over dsh-base: it supplies the coding persona and tool mode, disables HMR, mounts Code Mode's worker as a core execution capability, and inserts this package's headless-runner plugin (config {task}, resolved from the injected headlessStartup provider). It mounts no Host, HTTP server, Web runtime, or browser plugin.

After the Loader settles, the runner reads the shared ctx.agentDefaultModel, creates one fresh persisted Agent through ctx.agents, submits the task as an ordinary user message, and waits for quiescence. It flushes the Session before folding the owned durable event interval, writes the last non-empty assistant text to stdout, and requests exit through the launcher-provided ctx.headlessIo host hook (final turn/end completed → 0, otherwise 1). A terminal error reason also writes its code and message to stderr; successful runs keep stderr empty. The process opens no listening port. The task text is this app's command line: the ordinary headless-startup provider (src/startup.ts) injects ctx.cmdlineArgs (dsh-cmdline), reads the positional argument of dsh --profile headless "task", prints the app's --help, and provides headlessStartup; the runner injects that service and reads its task from lazy config. A missing or whitespace-only task is rejected before the runner activates.

Model Experience

None, as the runner submits the task as an ordinary user message; prompts and tools belong to the base and headless bundle rows.

KV Cache effect

None; the runner adds nothing to the request prefix.

Known Limitations and Deferred Work

  • One submitted task only — the runner has no interactive follow-up surface; it waits through any work the Agent completes before returning to idle and prints the last non-empty assistant message in that interval.
  • ctx.headlessIo is launcher-owned — booting the headless profile outside the dsh launcher fails loud at activation until the host provides the hook.