Skip to content

feat(runtime): add DeepSeek Harness engine and no-resume history - #255

Draft
sam2tom wants to merge 2 commits into
mainfrom
feature/deepseek-harness-runtime
Draft

feat(runtime): add DeepSeek Harness engine and no-resume history#255
sam2tom wants to merge 2 commits into
mainfrom
feature/deepseek-harness-runtime

Conversation

@sam2tom

@sam2tom sam2tom commented Aug 19, 2026

Copy link
Copy Markdown
Collaborator

Adds agent_kind="deepseek_harness" as a fifth daemon engine, driven through the harness's only supported automation surface, dsh --profile headless <task>: one prompt is one fresh dsh process that prints the final assistant text and exits.

Verified against a real dsh install (0.1.0-rc.6 local, 0.1.0-rc.7 in an isolated prefix): the headless app takes a task positional only, its runner mints a random session id per invocation, and a second run in the same DSH_HOME/workspace has no memory of the first. The engine therefore advertises no streaming, usage, resume or permission capability, and the adapter never synthesizes a session id.

Because that leaves every turn contextless, the server now injects a bounded transcript tail into the system-prompt slot for any engine whose heartbeat descriptor reports Capabilities.Resume=false — deepseek_harness and opencode today. Gating on the live descriptor rather than an engine name list means an engine that gains resume support stops receiving a duplicate transcript as soon as it advertises it.

Daemon adapter:

  • state under ~/.parsar keyed by AgentStateKey (DSH_HOME), run-scoped --patch overlay deleted on cleanup, secrets only ever in env
  • managed models arrive as a declared llm-pi-ai route, reusing the pi wire-protocol mapping (both embed pi-ai)
  • unattended runs declare and select a permission preset pairing workspace-write with approval:never; patching the approval row alone fails dsh boot with "composed sandbox and approval defaults match no preset" and is re-pinned per session anyway

Refactors pulled in by the new engine:

  • engine preflight moves from four hand-written probe blocks in connect.go to one table in agent_cli.go (identical operator output)
  • the AgentStateKey path sanitizer moves to internal/paths, shared with pi
  • the duplicated formatAgentKindLabel in RuntimePage and LocalDeviceRuntimesPanel becomes agentKindDisplayName in lib/

Also threads the trigger message id through PromptInput so the injected transcript excludes the task the run is already carrying, and pins DSH_VERSION in the sandbox image.

What & why

How

Verification

  • make check
  • Relevant E2E target (if any):
  • Manual smoke (describe briefly)

Notes for reviewers

Adds agent_kind="deepseek_harness" as a fifth daemon engine, driven
through the harness's only supported automation surface,
`dsh --profile headless <task>`: one prompt is one fresh dsh process that
prints the final assistant text and exits.

Verified against a real dsh install (0.1.0-rc.6 local, 0.1.0-rc.7 in an
isolated prefix): the headless app takes a task positional only, its
runner mints a random session id per invocation, and a second run in the
same DSH_HOME/workspace has no memory of the first. The engine therefore
advertises no streaming, usage, resume or permission capability, and the
adapter never synthesizes a session id.

Because that leaves every turn contextless, the server now injects a
bounded transcript tail into the system-prompt slot for any engine whose
heartbeat descriptor reports Capabilities.Resume=false — deepseek_harness
and opencode today. Gating on the live descriptor rather than an engine
name list means an engine that gains resume support stops receiving a
duplicate transcript as soon as it advertises it.

Daemon adapter:
- state under ~/.parsar keyed by AgentStateKey (DSH_HOME), run-scoped
  `--patch` overlay deleted on cleanup, secrets only ever in env
- managed models arrive as a declared llm-pi-ai route, reusing the pi
  wire-protocol mapping (both embed pi-ai)
- unattended runs declare and select a permission preset pairing
  workspace-write with approval:never; patching the approval row alone
  fails dsh boot with "composed sandbox and approval defaults match no
  preset" and is re-pinned per session anyway

Refactors pulled in by the new engine:
- engine preflight moves from four hand-written probe blocks in
  connect.go to one table in agent_cli.go (identical operator output)
- the AgentStateKey path sanitizer moves to internal/paths, shared with pi
- the duplicated formatAgentKindLabel in RuntimePage and
  LocalDeviceRuntimesPanel becomes agentKindDisplayName in lib/

Also threads the trigger message id through PromptInput so the injected
transcript excludes the task the run is already carrying, and pins
DSH_VERSION in the sandbox image.
@sam2tom
sam2tom marked this pull request as draft August 19, 2026 15:08
Both image builds hardcoded docker.io for their builder stages and took
Go's default module proxy, so a host that cannot reach proxy.golang.org
or docker.io could not build either image at all — `go mod download` and
the `FROM golang:`/`FROM node:` metadata lookups fail before any layer
runs.

Adds GOPROXY plus full-reference GO_IMAGE / NODE_IMAGE build args, the
same escape hatch BASE_IMAGE and RUNTIME_BASE already provide for the
runtime stages. Every default is byte-identical to the previous
behaviour, so CI and release builds are unchanged:

  docker build -f infra/sandbox/Dockerfile \
    --build-arg GOPROXY=https://goproxy.cn,direct \
    --build-arg GO_IMAGE=<mirror>/library/golang:1.25-bookworm \
    --build-arg BASE_IMAGE=<mirror>/library/ubuntu:22.04 .
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant