Files
deepseek-harness/packages/sdk/server/README.md
T
pku-xht c2fb21d13a Merge commit 'ead58a4a476200de2a2f2549ef6a02e73752b618' into codex/dsh-sdk-dynamic-subagent-routing
# Conflicts:
#	.agents/notes/implemented/feature/2026-07-27-typescript-sdk-and-sdk-subagent-backend.i18n.yaml
#	.agents/notes/implemented/feature/2026-07-27-typescript-sdk-and-sdk-subagent-backend.md
#	.agents/notes/implemented/feature/2026-07-27-typescript-sdk-and-sdk-subagent-backend.zh.md
#	examples/python-sdk-agent/tests/sdk.snapshot.ts
#	packages/sdk/client/README.i18n.yaml
#	packages/sdk/client/README.md
#	packages/sdk/client/README.zh.md
#	packages/sdk/client/src/types.ts
#	packages/sdk/protocol/README.i18n.yaml
#	packages/sdk/protocol/README.md
#	packages/sdk/protocol/README.zh.md
#	packages/sdk/server/src/server.ts
#	packages/subagent/subagent-dsh-sdk/tests/fixtures/loader/snapshot.cordis.yml
#	packages/subagent/subagent-dsh-sdk/tests/fixtures/loader/snapshot.replay.cordis.yml
2026-08-25 18:01:08 +08:00

4.9 KiB

@deepseek-ai/dsh-sdk-jsonrpc-server

English | 中文

The jsonrpc plugin serves newline-delimited JSON-RPC over stdio so out-of-process SDK clients can drive harness agents. HarnessSdkJsonRpcServer owns the protocol methods and notifications; the transport and the named wire types live in dsh-sdk-protocol, shared with the client SDKs. TypeScript and Python clients receive this server through dsh --profile sdk or another profile that mounts the same row.

Wiring

inject: ['agents']. The server gets or creates one agent per sessionId. It forwards subagent completions only when the service-snapshotted lifecycle local flag is true; provider names, child ids, and durable lineage never establish locality. A registered adapter wins, an unowned deepseek-official route mounts dsh-llm-deepseek, and any other unowned provider fails initialization. The selected adapter resolves the exact model and optional reasoning effort before initialization succeeds. Other capabilities come from the surrounding Loader composition.

Config

maxTokensAsSuccess defaults to false and affects only the deployment-mapped status on subagent.finished; root-session prompts have no prompt-level status. The profile composition owns each root agent's tools. JsonRpcConfig.input, output, and exit are runtime-only transport hooks; production uses process stdio and process.exit.

stdout is the protocol

Stdout carries only JSON-RPC frames. The deployment must not compose a stdout logger; diagnostics belong on stderr.

Shutdown and exit semantics

The plugin answers shutdown, flushes the response, disposes the root context so SDK-owned agents, subscriptions, and persistence reach quiescence, then exits with code 0. EOF and signal exits belong to the app bin, which also disposes the root context. Unloading only this plugin stops serving without exiting the process.

Wire notes

initialize is the runtime-readiness boundary: when the server is mounted by a Loader composition, it waits for the current plugin tree to settle before replying, so async sibling capabilities such as initial MCP tool discovery are visible to the first prompt. Hand-built contexts without Loader remain immediately usable. initialize.serverInfo.name is the wire-stable deepseek-harness-sdk-runtime. The server validates the provider/model route and optional non-empty reasoningEffort through the selected adapter before storing them; omission stores no effort, so the model retains its own default. An optional positive initialize.maxTokens becomes the request output cap of each SDK-created agent and its in-process descendants; invalid values reject initialization, while omission sends no SDK cap and allows the selected adapter or provider route default to apply. JSON-RPC requests may dispatch concurrently, so session/prompt rejects until one initialize has completed successfully; clients must await the handshake before sending prompts. An accepted prompt queues one identified user message and immediately returns { messageId }. The server streams every durable fact as session.event and every whole-agent lifecycle transition as session.status; it does not assign an assistant message or turn/end to that prompt. Independent requests may enqueue more work on the same session. Persistence roots and persona come from the surrounding composition.

Model Experience

SDK user message

What the model sees

For each accepted session/prompt, text and durable content references enter one user message verbatim. Inline SdkEncodedImageBlock values are validated and committed through the composition's attachment store first, so the session log retains content-addressed image references rather than base64 bytes. This package adds no system-prompt prose or tool schema; those come from the other plugins in the composition.

Token effect

Data-dependent user-message tokens enter retained session history and are resent on later turns until another package compacts them. The JSON-RPC frames, session notifications, and server bookkeeping add zero model-context tokens.

KV Cache effect

Append-only; newly visible content follows the reusable request prefix and does not invalidate existing KV-cache entries.

Known Limitations and Deferred Work

  • The wire has no per-session close or prompt-cancel method — SDK-created agents remain live until process shutdown.
  • There is no per-prompt resultMessageId identifies inbox admission only; clients that own an automation interval must define and observe that interval themselves.
  • stdout purity is deployment-enforced — a surrounding config can still load a stdout logger and corrupt the JSON-RPC channel; this plugin does not inspect or veto sibling loggers.
  • Automatic adapter mounting is DeepSeek-specificinitialize can reuse any pre-registered model adapter, but its only fallback mounts dsh-llm-deepseek.