ds-hu/dsh-acp-paseo--packages-dsh-acp-plus ↗★ 13

@ds-hu/dsh-acp-plus

DSH bundle for the most feature-complete DeepSeek Harness – Paseo integration project. 适合需要完整ACP协议对接、渲染标准投影及使用DSH原生细节的开发者。

Package
@ds-hu/dsh-acp-plus
Compatibility
Unverified
Harness peer range
0.2.0-rc.2
Cordis peer range
~4.0.4
Version
0.3.0
License
MIT
Last updated
Oct 19, 2026

Install

$npx -p @deepseek-ai/dsh dsh plugin --profile web add github:ds-hu/dsh-acp-paseo#03ecc2161c49a05297d3c1646af81767f1a39004&path:packages/dsh-acp-plus

@ds-hu/dsh-acp-plus

A lossless ACP v1 agent bridge for the DeepSeek Harness, shipped as a DSH bundle.

It claims stdio, serves the ACP v1 methods a client expects, and emits two channels at once: a standard projection that any ACP client can render, and DSH-native detail carried in _meta.dsh plus the _dsh/* extension methods. The bundle disables the stock acp row and replaces it with this bridge.

Install

The profile must stack the base, the ACP application and this bundle:

{
  "name": "dsh-profile-acp-plus",
  "private": true,
  "dsh": {
    "profile": {
      "bundles": [
        "@deepseek-ai/dsh-base",
        "@deepseek-ai/dsh-acp-app",
        "@ds-hu/dsh-acp-plus"
      ],
      "patchReload": "startup"
    }
  }
}
dsh plugin --profile acp-plus add @ds-hu/dsh-acp-plus
dsh --profile acp-plus

@deepseek-ai/dsh-acp-app must stay in the list: it inserts the stock acp row that this bundle's patch disables, and it provides the acpAppStartup gate that the acp-plus plugin injects. The package is published to npm as @ds-hu/dsh-acp-plus. patchReload: "startup" is appropriate because the bridge claims stdio once per process.

Config

Set these on the acp-plus row.

FieldTypeDefaultMeaning
providerstring, optionalnoneDefault DSH provider route for new ACP sessions.
modelstring, optionalnoneDefault model id for new ACP sessions.
sessionListPageSizenatural100Maximum sessions returned per session/list page.
questionTimeoutMsnatural660000How long an interactive question waits for a client answer (backstop).
replayLimitnatural0Maximum events replayed by session/load; 0 replays all.

The bundled patch inserts:

- id: acp
  disabled: true

- insert:
    - id: acp-plus
      name: '@ds-hu/dsh-acp-plus'
      inject: [acpAppStartup]
      config:
        provider: deepseek-official
        model: deepseek-v4-flash

    - id: tool-ask-user
      name: '@deepseek-ai/dsh-tool-ask-user'
      config:
        mode: timed
        timeout: 600

dsh-base mounts the user-questions service; the model-facing tool is opt-in, so the patch inserts it. mode: timed lets the harness own the timeout (seconds) while questionTimeoutMs stays a slightly longer backstop for a vanished client.

ACP surface

MethodBehaviour
initializeprotocolVersion: 1; loadSession: true; promptCapabilities.image when the deployment supports image prompts (audio and embeddedContext are false); sessionCapabilities: {list, resume, close, fork}; advertises features in the response _meta.dsh.
authenticateNo-op; returns {}.
session/newCreates a DSH agent; a non-empty additionalDirectories is rejected with -32602. Returns configOptions, optional modes and _meta.dsh.
session/loadReplays persisted history as session/update in seq order (capped by replayLimit), then resumes the agent; returns optional modes.
session/resumeResumes a persisted session without replay; returns optional modes.
session/listPaged session summaries; each item carries _meta.dsh.
session/closeCancels pending waiters and closes the agent.
session/set_config_optionApplies model, reasoning_effort, approval_policy, sandbox_mode or plan_mode; returns the updated option set.
session/set_modeSelects a DSH agent preset declared by the profile. DSH only allows this before the first turn; success emits current_mode_update.
session/promptStreams updates for the turn and returns a stopReason plus _meta.dsh.
session/cancel (notification)Cancels the in-flight turn.
session/fork (unstable)Forks a session with buildForkSeed and agents.create; the same handler is exposed as _dsh/session/fork; returns optional modes.

Not implemented, so they answer with the ACP unknown-method error -32601: logout, session/delete. The client's fs/* and terminal/* methods are never called; tool execution stays inside DSH's own filesystem and sandbox. Monetary cost is not reported — _meta.dsh.features.cost is false.

_meta and extensions

Every payload that allows _meta carries an envelope:

{ "_meta": { "dsh": { "v": 1, "kind": "update.tool_call", "native": { } } } }

v is the envelope version, kind is a stable tag (update.*, initialize, session-new, session-load, session-resume, session-list, session-list-item, session-close, session-config, prompt-result, session-fork, permission-request), and native is the originating DSH object.

ExtensionKindDirectionPayload
_dsh/eventnotificationagent → client{v, sessionId, event} — one durable DSH event, in seq order.
_dsh/framenotificationagent → client{v, sessionId, frame} — one transient assistant-stream frame.
_dsh/user_questionsrequestagent → client{v, requestId, sessionId, timeoutMs, questions[]} → {answers: [{id, selected[], custom?}]}.
_dsh/session/forkrequestclient → agentSame params and result as session/fork; the result _meta.dsh carries lineage.

Permissions are one-shot: the bridge offers allow_once versus a reject/cancel outcome, and keeps no session-scoped grants. When a client cannot answer _dsh/user_questions (unsupported method, cancellation or timeout), the ask_user_question tool fails with a clear error rather than hanging.

Tests

pnpm --filter @ds-hu/dsh-acp-plus test        # unit tests under test/, integration excluded
pnpm --filter @ds-hu/dsh-acp-plus typecheck
pnpm test:unit                         # all workspace unit projects
pnpm test:integration                  # builds the package, then runs test/integration/
DSH_ACP_LIVE=1 pnpm --filter @ds-hu/dsh-acp-plus test:live   # real model turn + fork (opt-in)
pnpm test                              # root vitest projects

The integration project needs the bundle built (pnpm --filter @ds-hu/dsh-acp-plus build) because it boots a profile from dist/. It creates a throwaway DSH_HOME, symlinks this package into profiles/acp-plus/node_modules/, and drives dsh --profile acp-plus over stdio. The live project copies the operator's credentials into a throwaway home, so the real one is never mutated.