Workflow & Automation

dsh-paseo

renat3u/dsh-paseo · ★ 4

renat3u

Uses dsh (DeepSeek Harness) as an ACP provider for Paseo: run and manage multiple dsh agents in parallel inside Paseo, with reliable dsh startup.

License
NOASSERTION
Added
2026-08-23
Maintenance
active
Install kind
github

No manifest check is available; listing does not imply compatibility or security review.

安装

dsh plugin --profile web add github:renat3u/dsh-paseo

GitHub 源码安装:首次需按提示配置 allowBuilds 构建授权后重试

For install and environment setup, plus plugin development tutorials, see DSH community docs ↗

README

Source README · body: en · Read Chinese README

Table of contents
  1. Features
  2. Architecture
  3. Requirements
  4. Installation
  5. Phone connection (optional)
  6. Quick start
  7. Usage
  8. Running in parallel
  9. Model selection
  10. Permission modes
  11. Sessions and logs
  12. Configuration reference
  13. Paseo provider fields (~/.paseo/config.json → agents.providers.dsh)
  14. Environment variables (dsh process side)
  15. dsh settings.yaml (hot-reloaded, no restart needed)
  16. Verification (end-to-end)
  17. Project layout
  18. Known limitations
  19. Troubleshooting
  20. License

Make dsh (DeepSeek Harness) a first-class Paseo ACP provider: run and manage multiple dsh agents in parallel from the Paseo UI, with a launcher that reliably starts dsh.

简体中文


Features

  • Paseo provider: dsh is registered as an ACP provider (Agent Client Protocol over stdio JSON-RPC). Pick "DSH (DeepSeek Harness)" directly in the Paseo desktop / web / mobile clients to create a session.
  • Parallel agents: every dsh session is an independent dsh process (own session log, own workspace, own cancellation path). Paseo's attach / logs / send / stop / delete all work.
  • Reliable launch: the launcher resolves the dsh installation, self-heals the paseo profile, forwards signals, and keeps stdout protocol-pure; process kills and disconnects tear down cleanly.
  • No dsh source changes: the dsh side is injected through the official profile-bundle mechanism — a thin ACP bridge plugin consuming only public seams (ctx.agents / ctx.sessions / ctx.approval).
  • Composable models: inherits the connected dsh service's default model by default; derived providers plus environment variables explicitly override any model / endpoint setup (flash, pro, custom baseURL, …).
  • Controllable permissions: workspace-write sandbox by default with one-shot permission prompts (allow-once / reject in the Paseo UI), optional danger-full-access.

Architecture

Paseo daemon (desktop / web / mobile / CLI clients)
   │  one process spawned per dsh session, ACP over stdio (JSON-RPC 2.0)
   ▼
bin/dsh-paseo-launch.mjs        ← reliable launch: resolve dsh → self-heal profile → signals
   (inside the bundle package: packages/dsh-paseo/bin/)
   ▼
dsh --profile paseo             ← bundles: [@deepseek-ai/dsh-base, @deepseek-ai/dsh-paseo]
   └─ paseo-acp bridge plugin   ← initialize / session/new / prompt / cancel / request_permission

Requirements

Dependency Version Notes
Node.js ≥ 22.19 launcher and build scripts
pnpm 11.x used internally by dsh plugin (profile install); run pnpm dsh web from the dsh source checkout root to start the Web UI
dsh current rc source snapshot (pnpm dsh web in the checkout root starts the Web UI); the launcher resolves the dsh executable: PATH → ~/.dsh/source/current
Paseo ≥ 0.3 @getpaseo/cli (npm install -g @getpaseo/cli) or the desktop app
DeepSeek API key — via dsh-side credentials: env var / ~/.dsh/.env / ~/.dsh/.credentials.yaml

Installation

# 1) Build the bundle (links vendored @deepseek-ai/cordis / dsh seams / ACP SDK into node_modules)
cd <dsh-paseo checkout root>
node scripts/build.mjs

# 2) Register the Paseo provider (idempotent, with backup; writes $PASEO_HOME/config.json, default ~/.paseo)
node packages/dsh-paseo/scripts/install-paseo-provider.mjs

# 3) Install the dsh-side profile (the launcher does this automatically on first launch; run inside the dsh source checkout root)
pnpm dsh plugin --profile paseo add <dsh-paseo checkout root>/packages/dsh-paseo
pnpm dsh --profile paseo --dump-config | grep -A5 paseo-acp   # verify the composition

# 4) Start / restart the Paseo daemon
paseo start --relay --listen 0.0.0.0:6767 --hostnames true

Note: paseo restart does not preserve launch flags such as --listen (it falls back to 127.0.0.1, so your phone can no longer connect directly). Restart with the full flag set: paseo restart --relay --listen 0.0.0.0:6767 --hostnames true.

Phone connection (optional)

  1. Install the Paseo app on your phone (search "Paseo" on the App Store / Google Play).
  2. Generate a pairing code on the daemon machine: paseo daemon pair (prints a QR code / pairing link).
  3. Open the pairing link (or scan the QR) on the phone to pair; you can then see this host and drive dsh agents from your phone.

With --relay, the phone and the daemon do not need to be on the same network (end-to-end encrypted via relay.paseo.sh); --listen 0.0.0.0:6767 enables direct LAN access.

Quick start

# Run a dsh agent from Paseo
paseo run --provider dsh "implement user authentication"

# or: GUI / phone app → new session → provider "DSH (DeepSeek Harness)" → type your task

On the first launch the launcher auto-installs the dsh-side profile; no manual step is needed.

Usage

Running in parallel

Every dsh session is an independent dsh process. paseo ls lists all agents, paseo attach <id> streams output, paseo send <id> "task" follows up, paseo stop <id> interrupts (verified: the in-flight tool call is ABORTED and the turn ends aborted/user).

Model selection

Model routing is decided by dsh-side config (single source of truth) and stays consistent with the connected dsh service: without an explicit override, Paseo agents inherit the dsh service's default model selection (the agent-default-model row → $DSH_HOME/settings.yaml / the web Models page; default deepseek-v4-flash). To pick a model per agent, use a derived provider + environment variable:

// ~/.paseo/config.json —— the `command` is written automatically by
// `node packages/dsh-paseo/scripts/install-paseo-provider.mjs` (as [node, launcher] on Windows);
// shown here for reference
{
  "agents": { "providers": {
    "dsh":        { "extends": "acp", "label": "DSH (DeepSeek Harness)",
                     "command": ["/absolute/path/to/dsh-paseo/packages/dsh-paseo/bin/dsh-paseo-launch.mjs"],
                     "params": { "supportsMcpServers": false } },
    "dsh-pro":    { "extends": "acp", "label": "DSH Pro",
                     "command": ["/absolute/path/to/dsh-paseo/packages/dsh-paseo/bin/dsh-paseo-launch.mjs"],
                     "params": { "supportsMcpServers": false },
                     "env": { "DSH_PASEO_MODEL": "deepseek-v4-pro" } }
  } }
}

Restart the daemon (with full flags) after editing. Verified: default dsh provider agents self-report deepseek-v4-flash (following the service default); an explicit env.DSH_PASEO_MODEL override makes them self-report the overridden model.

Permission modes

Mode Behavior
workspace-write (default) bash / file tools are fenced to the workspace; out-of-scope attempts raise a one-shot permission prompt (allow-once / reject in the Paseo UI, or Auto Accept)
danger-full-access full access (trusted machines only); set DSH_PERMISSION_MODE=danger-full-access in the provider's env

Sessions and logs

  • dsh session logs land in $DSH_HOME/sessions/, queryable / replayable from other dsh surfaces.
  • The ACP bridge is fresh-sessions-only (no resume / load / list — same as the official dsh-acp).
  • The bridge emits only committed assistant text (agent_message_chunk), no token-by-token streaming; reasoning / tool activity stays in the dsh session log.

Configuration reference

Paseo provider fields (~/.paseo/config.json → agents.providers.dsh)

Field Value Notes
extends "acp" generic ACP provider
command absolute launcher path Paseo spawns it once per agent
params.supportsMcpServers false must be false: the dsh bridge rejects non-empty mcpServers (Paseo injects internal-tool MCP by default)
env any environment passed through to the dsh process (model / permission selection, …)
label / description strings display name in the UI

Environment variables (dsh process side)

Variable Default Notes
DSH_PASEO_MODEL inherits the dsh service default explicit model override for bridge-created agents (evaluated per process); unset follows the service default (settings.yaml / Models page)
DSH_PASEO_PROVIDER inherits the dsh service default explicit llm-route override; e.g. openai / anthropic (llm-pi-ai)
DSH_PERMISSION_MODE workspace-write sandbox mode (also drives approval ask/never)
DSH_PASEO_DSH auto-resolved explicit path to the dsh executable
DSH_HOME ~/.dsh dsh home (profiles / sessions / credentials)
DEEPSEEK_API_KEY / DEEPSEEK_BASE_URL env / .env key and API endpoint (also configurable in settings.yaml). In the current release DEEPSEEK_BASE_URL is read from the process environment only — .env may no longer override it

dsh settings.yaml (hot-reloaded, no restart needed)

The llm-deepseek: section of $DSH_HOME/settings.yaml overrides the model catalog, default model, API endpoint (baseURL), thinking level, etc.:

llm-deepseek:
  baseURL: https://your-gateway.example/v1
  reasoningEffort: max
  models:
    - id: deepseek-v4-flash
    - id: deepseek-v4-pro

Verification (end-to-end)

# Without Paseo — verify dsh's ACP service directly (for isolating problems)
node tools/acp-smoke-client.mjs          # via the launcher
node tools/acp-smoke-client.mjs --direct # spawn dsh directly (no launcher)

# Through Paseo
paseo run --provider dsh "Reply with exactly: PONG"
paseo logs <agent-id>                    # expect [User] prompt + PONG
paseo ls                                 # agent status idle/completed

# Unit tests
node scripts/test.mjs

Expected output (verified): the smoke prints PASS: full ACP round-trip succeeded; paseo logs shows PONG.

Project layout

packages/dsh-paseo/          dsh-side Cordis bundle
  src/index.ts               ACP bridge plugin (adapted from @deepseek-ai/dsh-acp, BSD-3-Clause)
  src/codec.ts               prompt flattening / turn-end → stop-reason mapping
  bin/dsh-paseo-launch.mjs   Paseo's spawn entry (reliable dsh launcher)
  cordis.patch.yml           injection layer: paseo-acp row + persona override
packages/dsh-paseo/scripts/install-paseo-provider.mjs  register the provider in Paseo config.json
scripts/build.mjs            build (link deps + snapshot tsc + artifact check)
scripts/test.mjs             unit test entry
paseo/provider.dsh.json      provider config template
tools/acp-smoke-client.mjs   ACP end-to-end smoke client
docs/                        architecture details & troubleshooting

Known limitations

  • Every dsh agent is a full harness process (boot ~2-4s, ~150-250MB RAM) — the inherent cost of process-level parallelism, same as Paseo's treatment of other agents.
  • No session resume / load / list (fresh sessions only).
  • The bridge emits committed text only (no token-by-token streaming).
  • The in-Paseo model picker is cosmetic: actual routing comes from dsh-side config / DSH_PASEO_MODEL.
  • Building depends on a dsh snapshot (~/.dsh/source/current or DSH_MONOREPO); re-run node scripts/build.mjs after switching snapshots.

Troubleshooting

See docs/troubleshooting.md (symptom table: provider missing, unavailable, MCP errors, missing key, wrong model, lost port listening, …).

License

MIT (the ACP bridge is adapted from @deepseek-ai/dsh-acp, BSD-3-Clause; see file headers and LICENSE).