Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

dsh-actor

Doer-mode first turn for DeepSeek Harness 0.1.0-rc.8. One preset, one behavior: the session's first model request runs as a hands-on doer with a minimal tool surface; from the moment the first response (thinking included) completes, the untouched Standard preset takes over.

Derived from dsh-router-standard's react band, with the routing removed and two deliberate changes.

Install

DSH scans one-level subdirectories of ~/.dsh/.agent-presets/; copy the contents of preset/ there (not the preset folder itself):

$target = Join-Path $env:USERPROFILE '.dsh\.agent-presets\actor'
New-Item -ItemType Directory -Force $target | Out-Null
Copy-Item .\preset\* $target -Recurse -Force
mkdir -p ~/.dsh/.agent-presets/actor
cp preset/* ~/.dsh/.agent-presets/actor/

Restart DSH, start a new session, pick 动态模式.

After editing actor-bootstrap.mjs, restart DSH for the change to take effect.

Timeline

phase prompt tools
first request(s), until the first assistant/message event exists the doer persona is the entire system prompt — one section, minimal-style (no harness identity, no deployment sections, no tool guidance); runtime contexts cleared read / write / edit + platform shell (pwsh preferred, bash fallback)
every assembly afterwards the Standard composition, untouched — original persona row, full section list full Standard catalog

Runtime-context snapshots ("Current runtime context. This snapshot supersedes…") are suppressed for the preset's whole scope via includeRuntimeContext: false on the persona row — the shipped minimal preset's flag. Without it the snapshot would surface exactly once, as a user-role message at the promotion switch (the first phase clears contexts, promotion restores them). Trade-off, same as minimal: the model never sees the live file-policy / approval-policy snapshot text; the sandbox and approval stacks keep enforcing those policies regardless.

The promotion condition is session.events.some(e => e.type === 'assistant/message'). The event log only grows, so the flip is monotonic and resume/reload keeps it. Spawned subagents (header.parentSession) are never governed.

Switch granularity is per request, not per stream. DSH assembles the prompt once per model request (preStep → systemPrompt.assemble) and never mid-response, so the unlock is first visible on the model request that FOLLOWS the first completed response — typically the post-tool-result request in the same turn (tool calls → results → next request sees the full surface). When the first response contains no tool calls, the turn ends there and the Standard surface returns with the next request, usually the next user message.

The minimal first turn mirrors the shipped minimal preset (one-sentence prompt + tiny tool surface) but is implemented in the system-prompt/assemble waterfall instead of a complete: true persona row: a complete section is enforced by the registry AFTER the waterfall, unconditionally for every assembly in the preset's scope, so the full Standard prompt could never render. The waterfall's return value is authoritative when no complete section is registered — the identical one-section first request, with the Standard restore still possible.

Why assistant/message is "first thinking ended"

At rc.8 (packages/core/agent-loop/src/agent.ts) the loop appends assistant/message when the streamed response completes — reasoning, text, and tool-call blocks together — before dispatching any tool calls. So the event appears even when the model's first turn is thinking + prose with zero tool calls, which is exactly the case a tool/call-triggered unlock (router-standard's promotion) never fires on. Interrupted responses append it too (interrupted: true) — an interrupted first thinking still counts as over.

Differences from router-standard's react band

  1. No routing. No task classification, no bands, no dev_router_* tools — the doer persona is the only mode.
  2. Minimal first turn. The first request's system prompt is the doer persona alone (one section, like the shipped minimal preset's composition), not a slot swap inside the full Standard prompt; router-standard v0.3.0's applyPersona appends its persona last, and the waterfall's return value is final (DSH sorts sections before the waterfall and never re-sorts), so its persona measurably lands at the end of the prompt.
  3. Thinking-based unlock. Full tools + full Standard prompt return when the first response completes, not when the first tool call lands.
  4. Clean restore. Promotion returns the assembly untouched — no custom persona, no cleared contexts; the Standard preset is byte-for-byte itself again.

Tests

node --test actor.test.mjs   # 10 tests: minimal first turn, promotion, trigger semantics, guards

Verbatim check

preset/agent.cordis.yml is the rc.8 standard composition plus exactly four intended differences: the header comment block, the persona-row comment, the persona row's includeRuntimeContext: false flag, and the actor-bootstrap row. Re-verify against the official file any time:

git -C /path/to/deepseek-harness show dsh-v0.1.0-rc.8:apps/cli/config/agent-presets/standard/agent.cordis.yml \
  | diff - preset/agent.cordis.yml

Expected output: only those four additions (1c, 23a, 28a, 33a hunks at the time of writing). Any additional hunk is either transcription drift (fix it) or an official update to merge in. To re-pin a newer DSH release, swap the tag, merge the official changes, and re-run this check.

Attribution

preset/agent.cordis.yml is the DeepSeek Harness 0.1.0-rc.8 standard preset composition (MIT) plus one row. The doer persona text is the react-band persona from dsh-router-standard (MIT).

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages