Workflow & Automation
dsh-paseo
renat3u/dsh-paseo · ★ 4
Uses dsh (DeepSeek Harness) as an ACP provider for Paseo: run and manage multiple dsh agents in parallel inside Paseo, with reliable dsh startup.
安装
dsh plugin --profile web add github:renat3u/dsh-paseoGitHub 源码安装:首次需按提示配置 allowBuilds 构建授权后重试
For install and environment setup, plus plugin development tutorials, see DSH community docs ↗
README
Table of contents
- Features
- Architecture
- Requirements
- Installation
- Phone connection (optional)
- Quick start
- Usage
- Running in parallel
- Model selection
- Permission modes
- Sessions and logs
- Configuration reference
- Paseo provider fields (~/.paseo/config.json → agents.providers.dsh)
- Environment variables (dsh process side)
- dsh settings.yaml (hot-reloaded, no restart needed)
- Verification (end-to-end)
- Project layout
- Known limitations
- Troubleshooting
- 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
paseoprofile, 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-writesandbox by default with one-shot permission prompts (allow-once / reject in the Paseo UI), optionaldanger-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 restartdoes not preserve launch flags such as--listen(it falls back to127.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)
- Install the Paseo app on your phone (search "Paseo" on the App Store / Google Play).
- Generate a pairing code on the daemon machine:
paseo daemon pair(prints a QR code / pairing link). - 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/currentorDSH_MONOREPO); re-runnode scripts/build.mjsafter 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).