The native adapter's route was named deepseek, colliding with pi-ai's
catalog provider of the same name, so the two DeepSeek paths could never
be mounted side by side. The web settings page needs both configurable at
once. Compositions, fixtures, goldens, scaffolding defaults, and docs all
move together (pre-release, no shim); TUI/session-query-spill/
missing-credential goldens re-recorded through their keyless refresh
modes because provider-name length shifts box padding and spill
truncation points.
- api: resolve a relative workspace cwd to absolute before the handshake —
the child spawns relative to the parent cwd, but the wire cwd is resolved
again inside the child, so a relative value double-resolved
(worker -> worker/worker).
- api: make the documented handshake retry real — HarnessClient.close() is
permanent, so a failed initialize now reaps the runtime and swaps in a
fresh client; DeepSeekHarness.close() is terminal and stops the respawns.
- api: validate session.event envelopes, assistant/message content, and
session.finished reasons at the wire boundary — a malformed runtime
surfaces as SdkProtocolError instead of type-invalid TurnResult data or a
TypeError out of finalResponse.
- client: a throwing subscribe() filter fails and detaches only its own
subscription (normalized to Error); sibling fan-out and the transport read
loop are undisturbed.
- client: NotificationSubscription.close() drops its queued notifications,
matching its documented contract; runtime-death fail() still leaves
already-delivered items drainable.
- client: subscribe() after close()/runtime death returns a born-failed
subscription so next() rejects instead of parking forever.
- client/transport: bounded requests abandon via AbortSignal — the transport
drops the pending entry at timeout, so repeated bounded calls against a
hung method retain no per-call state.
One test per finding; per-file coverage stays 100% on both packages.
- @deepseek-ai/dsh-sdk-protocol: extract the line transport from dsh-jsonrpc
and name the request/result/notification wire types both ends share; error
responses preserve wire code/data via JsonRpcResponseError.
- @deepseek-ai/dsh-sdk-client: TypeScript twin of the Python SDK — spawns the
dsh-jsonrpc-agent runtime as a subprocess, drives stdio JSON-RPC turns
(DeepSeekHarness high-level API + HarnessClient protocol client), scopes
notifications to session trees client-side, and reaps the child through the
shared subprocess dispose ladder.
- @deepseek-ai/dsh-subagent-sdk: out-of-process subagent backend driving a
child harness runtime through the TS SDK; shares cwd resolution with
subagent-acp via new dsh-subagent-subprocess cwd helpers.
- Keyless unit suites drive real subprocesses (scripted fake runtime peer);
100% per-file coverage on all touched packages.