@deepseek-ai/dsh-sdk-jsonrpc-server 0.1.1-rc.2 → 0.1.2-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.i18n.yaml +2 -2
- package/README.md +103 -13
- package/README.zh.md +109 -19
- package/lib/index.js +55 -14
- package/lib/types/index.d.ts +2 -2
- package/lib/types/server.d.ts +4 -1
- package/package.json +27 -23
package/README.i18n.yaml
CHANGED
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
|
3
3
|
# after editing either side, bring the other along and re-record with:
|
|
4
4
|
# pnpm run verify-translation-pairing --write packages/sdk/server/README.md
|
|
5
|
-
README.md:
|
|
6
|
-
README.zh.md:
|
|
5
|
+
README.md: d5653543c5ca92f523470fd3b2360497e836f3e5
|
|
6
|
+
README.zh.md: 6c30f274f666b83063df42d2c33253040ff9faf6
|
package/README.md
CHANGED
|
@@ -1,36 +1,111 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "The stdio JSON-RPC serving plugin for deployments that let out-of-process SDK clients open sessions and drive agents in a DeepSeek Harness runtime."
|
|
3
|
+
kind: "package-reference"
|
|
4
|
+
---
|
|
5
|
+
|
|
1
6
|
# @deepseek-ai/dsh-sdk-jsonrpc-server
|
|
2
7
|
|
|
3
8
|
English | [中文](README.zh.md)
|
|
4
9
|
|
|
5
|
-
|
|
10
|
+
## Summary
|
|
11
|
+
|
|
12
|
+
`dsh-sdk-jsonrpc-server` serves the SDK wire protocol over stdio so out-of-process clients can drive harness agents: it opens one session per `sessionId`, queues user prompts, and streams every session event and agent status transition back to the client. Mount it as the `jsonrpc` plugin in a Loader composition; the surrounding tree supplies everything else — agents, model adapters, persistence, and tools. Stdout carries only JSON-RPC frames, so a deployment must not compose a stdout logger. It answers `shutdown` by disposing the root runtime and exiting 0; the app bin owns EOF and signal exits.
|
|
13
|
+
|
|
14
|
+
## Table of Contents
|
|
15
|
+
|
|
16
|
+
- [Use this package](#use-this-package)
|
|
17
|
+
- [Understand the implementation](#understand-the-implementation)
|
|
18
|
+
- [Further Exploration](#further-exploration)
|
|
19
|
+
- [Model Experience](#model-experience)
|
|
20
|
+
- [Known Limitations and Deferred Work](#known-limitations-and-deferred-work)
|
|
21
|
+
- [Dev Note](#dev-note)
|
|
22
|
+
|
|
23
|
+
-----
|
|
24
|
+
|
|
25
|
+
<a id="use-this-package"></a>
|
|
26
|
+
## Use this package
|
|
27
|
+
|
|
28
|
+
Mount this plugin when a runtime must serve SDK clients: add it to a `cordis.yml` that composes the agent service, boot the runtime, and clients connect over stdio. The common path is explicit — the plugin needs the `agents` service; every other capability comes from the surrounding tree.
|
|
29
|
+
|
|
30
|
+
### Wiring
|
|
31
|
+
|
|
32
|
+
The plugin creates one agent per `sessionId` on first use. A registered model adapter wins the route; an unowned `deepseek-official` route mounts the DeepSeek adapter, and any other unowned provider fails initialization. The selected adapter resolves the exact model and optional reasoning effort before initialization succeeds.
|
|
33
|
+
|
|
34
|
+
### Configuration
|
|
35
|
+
|
|
36
|
+
| Field | Default | Meaning |
|
|
37
|
+
|---|---|---|
|
|
38
|
+
| `maxTokensAsSuccess` | `false` | Report max-token turn/subagent termination as a successful SDK result |
|
|
39
|
+
|
|
40
|
+
The profile composition owns each root agent's tools. `input`, `output`, and `exit` are runtime-only transport hooks for tests; production uses process stdio and `process.exit`. The generated [configuration catalog](../../../docs/config-catalog.md#deepseek-aidsh-sdk-jsonrpc-server) is the exhaustive source for every accepted field.
|
|
41
|
+
|
|
42
|
+
### stdout is the protocol
|
|
43
|
+
|
|
44
|
+
Stdout carries only JSON-RPC frames, so clients can parse every byte; diagnostics belong on stderr. Keep stdout loggers out of the composed tree.
|
|
45
|
+
|
|
46
|
+
### What SDK clients can do
|
|
47
|
+
|
|
48
|
+
`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. The handshake returns the wire-stable identity `deepseek-harness-sdk-runtime`. The server validates the provider/model route and optional non-empty `reasoningEffort` through the selected adapter before it stores them; omission stores no effort, so the model retains its own default. An optional positive `maxTokens` becomes the request output cap of each SDK-created agent and its in-process descendants, while omission applies the selected adapter or provider route default. 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 then 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 a prompt, and independent requests may enqueue more work on the same session. Persistence roots and persona come from the surrounding composition.
|
|
49
|
+
|
|
50
|
+
### Shutdown and exit
|
|
6
51
|
|
|
7
|
-
|
|
52
|
+
The plugin answers `shutdown`, flushes the response, disposes the root context so SDK-owned agents, subscriptions, and persistence reach quiescence, then exits 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.
|
|
8
53
|
|
|
9
|
-
|
|
54
|
+
-----
|
|
10
55
|
|
|
11
|
-
|
|
56
|
+
<a id="understand-the-implementation"></a>
|
|
57
|
+
## Understand the implementation
|
|
12
58
|
|
|
13
|
-
|
|
59
|
+
<details>
|
|
60
|
+
<summary>Implementation internals — click to expand</summary>
|
|
14
61
|
|
|
15
|
-
|
|
62
|
+
This section explains the design behind the serving plugin; the observable behavior is fully covered in [Use this package](#use-this-package).
|
|
16
63
|
|
|
17
|
-
|
|
64
|
+
### Design concept
|
|
18
65
|
|
|
19
|
-
|
|
66
|
+
The plugin is a thin presentation adapter: [`HarnessSdkJsonRpcServer`](src/server.ts) owns the protocol methods and notifications, while the transport and the named wire types come from `dsh-sdk-protocol`, shared with the client SDKs. It subscribes to session, agent, and subagent lifecycle events and forwards them as wire notifications; subagent completions are forwarded only when the service-snapshotted lifecycle `local` flag is true — provider names, child ids, and durable lineage never establish locality.
|
|
20
67
|
|
|
21
|
-
|
|
68
|
+
### Source map
|
|
22
69
|
|
|
23
|
-
|
|
70
|
+
| File | Role |
|
|
71
|
+
|---|---|
|
|
72
|
+
| [`src/index.ts`](src/index.ts) | Plugin entry: `Config` schema, stdio wiring, request dispatch, shared shutdown/exit task |
|
|
73
|
+
| [`src/server.ts`](src/server.ts) | `HarnessSdkJsonRpcServer`: protocol methods, per-session agent creation, lifecycle subscriptions, teardown |
|
|
74
|
+
| [`src/invariant.ts`](src/invariant.ts) | Invariant companion (no runtime invariant — boundary and replay tests cover the protocol mapping) |
|
|
24
75
|
|
|
25
|
-
|
|
76
|
+
### Request flow
|
|
26
77
|
|
|
78
|
+
Each protocol method validates its inputs and resolves the owning state before acting — `initialize` stores the SDK route, `session/prompt` resolves the live agent+session pair and queues the message, and `shutdown` disposes server-owned state to quiescence before flushing the response and exiting 0 — and a shared exit task guarantees that racing `shutdown` requests never dispose or exit twice. The dispatch lives in [src/index.ts](src/index.ts) and [src/server.ts](src/server.ts).
|
|
79
|
+
|
|
80
|
+
### Teardown
|
|
81
|
+
|
|
82
|
+
`server.shutdown()` disposes only what the server owns — the surrounding context stays running when just this plugin is unloaded. Protocol `shutdown` instead disposes the root fiber so persistence and the whole runtime reach quiescence before the process exits.
|
|
83
|
+
|
|
84
|
+
</details>
|
|
85
|
+
|
|
86
|
+
-----
|
|
87
|
+
|
|
88
|
+
<a id="further-exploration"></a>
|
|
89
|
+
## Further Exploration
|
|
90
|
+
|
|
91
|
+
Read these pages when the plugin contract is not enough. They move from the wire protocol to the clients and the runnable application.
|
|
92
|
+
|
|
93
|
+
- [SDK wire protocol](../protocol/README.md) — the methods and payload shapes this plugin serves.
|
|
94
|
+
- [TypeScript SDK client](../client/README.md) — the client that drives this plugin.
|
|
95
|
+
- [SDK application bundle](../../bundle/sdk-app/README.md) — the `dsh --profile sdk` application that boots this plugin.
|
|
96
|
+
- [Python SDK](../../../python/README.md) — the Python client that drives the same server.
|
|
97
|
+
- [SDK runtime distribution decision](../../../.agents/notes/implemented/architecture/2026-07-10-single-file-executable-sdk-runtime-distribution.md) — why the packaged runtime serves a closed plugin tree.
|
|
98
|
+
|
|
99
|
+
-----
|
|
100
|
+
|
|
101
|
+
<a id="model-experience"></a>
|
|
27
102
|
## Model Experience
|
|
28
103
|
|
|
29
104
|
### SDK user message
|
|
30
105
|
|
|
31
106
|
#### What the model sees
|
|
32
107
|
|
|
33
|
-
For each accepted `session/prompt`,
|
|
108
|
+
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.
|
|
34
109
|
|
|
35
110
|
#### Token effect
|
|
36
111
|
|
|
@@ -42,7 +117,22 @@ Append-only; newly visible content follows the reusable request prefix and does
|
|
|
42
117
|
|
|
43
118
|
## Known Limitations and Deferred Work
|
|
44
119
|
|
|
120
|
+
<a id="known-limitations-and-deferred-work"></a>
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
These limits define when the plugin needs special operational care. They are current package constraints, not a comparison with other serving approaches or a task backlog.
|
|
124
|
+
|
|
45
125
|
- **The wire has no per-session close or prompt-cancel method** — SDK-created agents remain live until process shutdown.
|
|
46
126
|
- **There is no per-prompt result** — `MessageId` identifies inbox admission only; clients that own an automation interval must define and observe that interval themselves.
|
|
47
127
|
- **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.
|
|
48
|
-
- **Automatic adapter mounting is DeepSeek-specific** — `initialize` can reuse any pre-registered model adapter, but its only fallback mounts
|
|
128
|
+
- **Automatic adapter mounting is DeepSeek-specific** — `initialize` can reuse any pre-registered model adapter, but its only fallback mounts the DeepSeek adapter.
|
|
129
|
+
|
|
130
|
+
<a id="dev-note"></a>
|
|
131
|
+
### Dev Note
|
|
132
|
+
|
|
133
|
+
<details>
|
|
134
|
+
<summary>Working context for maintainers — click to expand</summary>
|
|
135
|
+
|
|
136
|
+
This Dev Note is working context for maintainers and is explicitly non-authoritative — shipped behavior and limits live in the sections above and in the code. The single-executable runtime distribution pairs this plugin with the packaged `jsonrpc-demo` bin; keep the shutdown/exit contract consistent with the app bin, which owns EOF and signal exits. No other unresolved design questions are recorded.
|
|
137
|
+
|
|
138
|
+
</details>
|
package/README.zh.md
CHANGED
|
@@ -1,48 +1,138 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "面向让进程外 SDK 客户端在 DeepSeek Harness 运行时中打开会话并驱动 agent 的部署的 stdio JSON-RPC 服务插件。"
|
|
3
|
+
kind: "package-reference"
|
|
4
|
+
---
|
|
5
|
+
|
|
1
6
|
# @deepseek-ai/dsh-sdk-jsonrpc-server
|
|
2
7
|
|
|
3
8
|
[English](README.md) | 中文
|
|
4
9
|
|
|
5
|
-
|
|
10
|
+
## 概述
|
|
11
|
+
|
|
12
|
+
`dsh-sdk-jsonrpc-server` 通过 stdio 服务 SDK 协议格式,使进程外客户端能够驱动 harness agent(智能体):它为每个 `sessionId` 打开一个会话、把用户提示词排入队列,并把每个会话事件与 agent 状态转换实时流回客户端。把它作为 `jsonrpc` 插件挂载到 Loader 组合中;外围插件树提供其余一切——agent、模型适配器、持久化与工具。Stdout 只承载 JSON-RPC 帧,因此部署不得组合 stdout logger。它通过 dispose(资源释放)根运行时并以 0 退出应答 `shutdown`;EOF 与信号退出归 app bin 负责。
|
|
13
|
+
|
|
14
|
+
## 目录
|
|
15
|
+
|
|
16
|
+
- [使用本包](#use-this-package)
|
|
17
|
+
- [理解实现](#understand-the-implementation)
|
|
18
|
+
- [进一步探索](#further-exploration)
|
|
19
|
+
- [模型体验](#model-experience)
|
|
20
|
+
- [已知限制与延期工作](#known-limitations-and-deferred-work)
|
|
21
|
+
- [开发备注](#dev-note)
|
|
22
|
+
|
|
23
|
+
-----
|
|
24
|
+
|
|
25
|
+
<a id="use-this-package"></a>
|
|
26
|
+
## 使用本包
|
|
27
|
+
|
|
28
|
+
当运行时必须服务 SDK 客户端时挂载本插件:把它加入组合了 agent 服务的 `cordis.yml`,启动运行时,客户端即可通过 stdio 连接。常用路径是显式的——插件需要 `agents` 服务;其余每个能力都来自外围插件树。
|
|
29
|
+
|
|
30
|
+
### 组装
|
|
31
|
+
|
|
32
|
+
插件在首次使用时为每个 `sessionId` 创建一个 agent。已注册的模型适配器赢得路由;尚无适配器负责的 `deepseek-official` 路由会挂载 DeepSeek 适配器,任何其他尚无适配器负责的提供方都会导致初始化失败。初始化成功前,所选适配器会解析确切模型与可选推理强度。
|
|
33
|
+
|
|
34
|
+
### 配置
|
|
35
|
+
|
|
36
|
+
| 字段 | 默认值 | 含义 |
|
|
37
|
+
|---|---|---|
|
|
38
|
+
| `maxTokensAsSuccess` | `false` | 把 max-token 轮次/subagent 终止报告为成功的 SDK 结果 |
|
|
39
|
+
|
|
40
|
+
profile 组合拥有每个根 agent 的工具。`input`、`output` 与 `exit` 是仅供测试的运行时传输钩子;生产环境使用进程 stdio 与 `process.exit`。生成的[配置目录](../../../docs/config-catalog.zh.md#deepseek-aidsh-sdk-jsonrpc-server)是每个受支持字段的穷尽式真源。
|
|
41
|
+
|
|
42
|
+
### stdout 即协议
|
|
43
|
+
|
|
44
|
+
Stdout 只承载 JSON-RPC 帧,客户端可以逐字节解析;诊断信息应写入 stderr。请勿在组合的插件树中加入 stdout logger。
|
|
45
|
+
|
|
46
|
+
### SDK 客户端可以做什么
|
|
47
|
+
|
|
48
|
+
`initialize` 是运行时就绪边界:服务器由 Loader 组合挂载时,会等待当前插件树完成所有加载任务后再响应,因此首次提示词能够看到 MCP 初始工具发现等异步同级能力。握手返回协议稳定标识 `deepseek-harness-sdk-runtime`。服务器会通过所选适配器校验提供方/模型路由与可选的非空 `reasoningEffort`,再保存这些值;省略时不会保存推理强度,因此模型保留自身默认值。可选的正整数 `maxTokens` 会成为每个 SDK 创建的 agent 及其进程内后代的请求输出上限,省略时则应用所选适配器或提供方路由的默认值。JSON-RPC 请求可能并发分派,因此在一次 `initialize` 成功完成之前,`session/prompt` 会拒绝;客户端必须等待握手完成后再发送提示词。已接受的提示词会把一条带标识的用户消息排入队列,并立即返回 `{ messageId }`;服务器随后把每个持久事实作为 `session.event`、把整个 agent 生命周期的每次状态转换作为 `session.status` 流式发出。它不会把某条助手消息或 `turn/end` 归属于某个提示词,同一会话上的独立请求可以继续排入更多工作。持久化根目录与 persona 来自外围组合。
|
|
49
|
+
|
|
50
|
+
### 关闭与退出
|
|
6
51
|
|
|
7
|
-
|
|
52
|
+
插件应答 `shutdown`,刷新响应并 dispose 根上下文,使 SDK 持有的 agent、订阅与持久化达到完全停稳,然后以 0 退出。EOF 与信号退出归 app bin 负责,后者也会 dispose 根上下文。仅卸载此插件会停止服务,但不会退出进程。
|
|
8
53
|
|
|
9
|
-
|
|
54
|
+
-----
|
|
10
55
|
|
|
11
|
-
|
|
56
|
+
<a id="understand-the-implementation"></a>
|
|
57
|
+
## 理解实现
|
|
12
58
|
|
|
13
|
-
|
|
59
|
+
<details>
|
|
60
|
+
<summary>实现细节——点击展开</summary>
|
|
14
61
|
|
|
15
|
-
|
|
62
|
+
本节解释服务插件背后的设计;可观察行为已在[使用本包](#use-this-package)中完整说明。
|
|
16
63
|
|
|
17
|
-
|
|
64
|
+
### 设计理念
|
|
18
65
|
|
|
19
|
-
|
|
66
|
+
本插件是薄薄的展示适配器:[`HarnessSdkJsonRpcServer`](src/server.ts) 负责协议方法与通知,传输与具名协议类型来自 `dsh-sdk-protocol`,与客户端 SDK 共享。它订阅会话、agent 与 subagent 生命周期事件,并把它们作为协议通知转发;只有当服务在生命周期建立快照时记录的 `local` 标志为 true 时才转发 subagent 完成事件——提供方名称、子级 id 与持久化谱系均不能证明本地性。
|
|
20
67
|
|
|
21
|
-
|
|
68
|
+
### 源码地图
|
|
22
69
|
|
|
23
|
-
|
|
70
|
+
| 文件 | 职责 |
|
|
71
|
+
|---|---|
|
|
72
|
+
| [`src/index.ts`](src/index.ts) | 插件入口:`Config` schema、stdio 接线、请求分发、共享关闭/退出任务 |
|
|
73
|
+
| [`src/server.ts`](src/server.ts) | `HarnessSdkJsonRpcServer`:协议方法、逐会话 agent 创建、生命周期订阅、清理 |
|
|
74
|
+
| [`src/invariant.ts`](src/invariant.ts) | 不变式配套插件(无运行时不变式——边界与回放测试覆盖协议映射) |
|
|
24
75
|
|
|
25
|
-
|
|
76
|
+
### 请求流程
|
|
26
77
|
|
|
78
|
+
每个协议方法在行动前都会校验输入并解析其拥有的状态——`initialize` 保存 SDK 路由,`session/prompt` 解析存活的 agent+会话对并排入消息,`shutdown` 在刷新响应并以 0 退出前把服务器持有的状态 dispose 到完全停稳——共享退出任务确保竞争的 shutdown 请求绝不会重复 dispose 或退出。分发逻辑位于 [src/index.ts](src/index.ts) 与 [src/server.ts](src/server.ts)。
|
|
79
|
+
|
|
80
|
+
### 清理
|
|
81
|
+
|
|
82
|
+
`server.shutdown()` 只 dispose 服务器自身持有的内容——仅卸载本插件时,外围上下文保持运行。协议 `shutdown` 则 dispose 根 fiber,使持久化与整个运行时在进程退出前达到完全停稳。
|
|
83
|
+
|
|
84
|
+
</details>
|
|
85
|
+
|
|
86
|
+
-----
|
|
87
|
+
|
|
88
|
+
<a id="further-exploration"></a>
|
|
89
|
+
## 进一步探索
|
|
90
|
+
|
|
91
|
+
当插件约定不够用时阅读以下页面。它们从协议格式进入客户端与可运行应用。
|
|
92
|
+
|
|
93
|
+
- [SDK 协议格式](../protocol/README.zh.md) — 本插件服务的协议方法与载荷结构。
|
|
94
|
+
- [TypeScript SDK 客户端](../client/README.zh.md) — 驱动本插件的客户端。
|
|
95
|
+
- [SDK 应用组合包](../../bundle/sdk-app/README.zh.md) — 启动本插件的 `dsh --profile sdk` 应用。
|
|
96
|
+
- [Python SDK](../../../python/README.zh.md) — 驱动同一服务器的 Python 客户端。
|
|
97
|
+
- [SDK 运行时分发决策](../../../.agents/notes/implemented/architecture/2026-07-10-single-file-executable-sdk-runtime-distribution.zh.md) — 打包运行时为何服务封闭插件树。
|
|
98
|
+
|
|
99
|
+
-----
|
|
100
|
+
|
|
101
|
+
<a id="model-experience"></a>
|
|
27
102
|
## 模型体验
|
|
28
103
|
|
|
29
104
|
### SDK 用户消息
|
|
30
105
|
|
|
31
|
-
####
|
|
106
|
+
#### 模型看到什么
|
|
32
107
|
|
|
33
|
-
对于每个已接受的 `session/prompt
|
|
108
|
+
对于每个已接受的 `session/prompt`,文本和持久内容引用会原样进入一条用户消息。内联 `SdkEncodedImageBlock` 会先通过组合中的附件存储完成校验与提交,因此会话日志保留内容寻址的图片引用而不是 base64 字节。此包不会添加系统提示词文本或工具 schema;这些内容来自组合中的其他插件。
|
|
34
109
|
|
|
35
110
|
#### Token 影响
|
|
36
111
|
|
|
37
|
-
依数据而定的用户消息 token 会进入保留的会话历史,并在后续轮次中重复发送,直至另一个包将其压缩(compaction)。JSON-RPC
|
|
112
|
+
依数据而定的用户消息 token 会进入保留的会话历史,并在后续轮次中重复发送,直至另一个包将其压缩(compaction)。JSON-RPC 帧、会话通知与服务器内部记录不会增加模型上下文 token。
|
|
38
113
|
|
|
39
114
|
#### KV Cache 影响
|
|
40
115
|
|
|
41
116
|
仅追加;新可见内容位于可复用请求前缀之后,不会使现有 KV Cache 条目失效。
|
|
42
117
|
|
|
43
|
-
##
|
|
118
|
+
## 已知限制与延期工作
|
|
119
|
+
|
|
120
|
+
<a id="known-limitations-and-deferred-work"></a>
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
这些限制说明本插件何时需要特别的运维注意。它们是当前包约束,不是与其他服务方式的对比或任务积压。
|
|
124
|
+
|
|
125
|
+
- **协议没有逐会话关闭或提示词取消方法**——SDK 创建的 agent 会一直存活到进程关闭。
|
|
126
|
+
- **没有逐提示词结果**——`MessageId` 只标识 inbox 准入;拥有自动化活动区间的客户端必须自行定义并观察该区间。
|
|
127
|
+
- **stdout 纯净性由部署保证**——外围配置仍可能加载 stdout logger 并破坏 JSON-RPC 通道;此插件不会检查或否决同级 logger。
|
|
128
|
+
- **自动挂载适配器仅支持 DeepSeek**——`initialize` 可以复用任何预先注册的模型适配器,但唯一的回退行为是挂载 DeepSeek 适配器。
|
|
129
|
+
|
|
130
|
+
<a id="dev-note"></a>
|
|
131
|
+
### 开发备注
|
|
132
|
+
|
|
133
|
+
<details>
|
|
134
|
+
<summary>维护者的工作上下文——点击展开</summary>
|
|
135
|
+
|
|
136
|
+
本开发备注是维护者的工作上下文,明确不具权威性——已交付的行为与限制见上文各节与代码。单文件可执行运行时分发将本插件与打包的 `jsonrpc-demo` bin 配对;请让关闭/退出约定与负责 EOF 和信号退出的 app bin 保持一致。没有记录其他未解决的开放设计问题。
|
|
44
137
|
|
|
45
|
-
|
|
46
|
-
- **没有逐提示词结果**:`MessageId` 只标识 inbox 准入;拥有自动化活动区间的客户端必须自行定义并观察该区间。
|
|
47
|
-
- **stdout 纯净性由部署保证**:外围配置仍可能加载 stdout logger 并破坏 JSON-RPC 通道;此插件不会检查或否决同级 logger。
|
|
48
|
-
- **自动挂载适配器仅支持 DeepSeek**:`initialize` 可以复用任何预先注册的模型适配器,但唯一的回退行为是挂载 `dsh-llm-deepseek`。
|
|
138
|
+
</details>
|
package/lib/index.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import Schema from "@deepseek-ai/schemastery";
|
|
2
2
|
import { JsonRpcLineTransport } from "@deepseek-ai/dsh-sdk-protocol";
|
|
3
3
|
import { resolve } from "node:path";
|
|
4
|
-
import {
|
|
4
|
+
import { brandString } from "@deepseek-ai/dsh-brand";
|
|
5
|
+
import { admitEncodedImages } from "@deepseek-ai/dsh-attachment";
|
|
6
|
+
import { ReasoningEffortId, createUserMessage } from "@deepseek-ai/dsh-llm";
|
|
5
7
|
import { carrierKeyOf } from "@deepseek-ai/dsh-scope";
|
|
6
|
-
import { SessionId } from "@deepseek-ai/dsh-session";
|
|
7
8
|
import * as LlmDeepSeek from "@deepseek-ai/dsh-llm-deepseek";
|
|
8
9
|
//#region lib/types/server.js
|
|
9
10
|
/**
|
|
@@ -12,6 +13,24 @@ import * as LlmDeepSeek from "@deepseek-ai/dsh-llm-deepseek";
|
|
|
12
13
|
*
|
|
13
14
|
* @module @deepseek-ai/dsh-sdk-jsonrpc-server/server
|
|
14
15
|
*/
|
|
16
|
+
function encodedImage(block) {
|
|
17
|
+
return block.type === "image" && "data" in block;
|
|
18
|
+
}
|
|
19
|
+
async function durablePromptContent(ctx, blocks) {
|
|
20
|
+
const images = blocks.filter(encodedImage);
|
|
21
|
+
if (images.length === 0) return blocks;
|
|
22
|
+
const attachments = ctx.get("attachments");
|
|
23
|
+
if (attachments === void 0) throw new Error("SDK image prompt requires an attachment store");
|
|
24
|
+
const refs = await admitEncodedImages(attachments, images.map((image) => ({
|
|
25
|
+
data: image.data,
|
|
26
|
+
mediaType: image.mimeType
|
|
27
|
+
})));
|
|
28
|
+
let next = 0;
|
|
29
|
+
return blocks.map((block) => encodedImage(block) ? {
|
|
30
|
+
type: "image",
|
|
31
|
+
attachment: refs[next++]
|
|
32
|
+
} : block);
|
|
33
|
+
}
|
|
15
34
|
/** Recover the delegating parent from the service-owned scoped carrier. */
|
|
16
35
|
function subagentParentOf(carrier) {
|
|
17
36
|
return carrierKeyOf(carrier);
|
|
@@ -32,6 +51,7 @@ var HarnessSdkJsonRpcServer = class {
|
|
|
32
51
|
cwd = process.cwd();
|
|
33
52
|
provider = "deepseek-official";
|
|
34
53
|
model = "deepseek-official";
|
|
54
|
+
reasoningEffort;
|
|
35
55
|
maxTokens;
|
|
36
56
|
llmFiber;
|
|
37
57
|
sessions = /* @__PURE__ */ new Map();
|
|
@@ -39,6 +59,7 @@ var HarnessSdkJsonRpcServer = class {
|
|
|
39
59
|
disposers = [];
|
|
40
60
|
shutdownTask;
|
|
41
61
|
shuttingDown = false;
|
|
62
|
+
initialized = false;
|
|
42
63
|
constructor(ctx, transport, options = {}) {
|
|
43
64
|
this.ctx = ctx;
|
|
44
65
|
this.transport = transport;
|
|
@@ -82,20 +103,33 @@ var HarnessSdkJsonRpcServer = class {
|
|
|
82
103
|
}));
|
|
83
104
|
}
|
|
84
105
|
/**
|
|
85
|
-
*
|
|
106
|
+
* Validate and configure the SDK route, mounting the DeepSeek fallback only when unowned.
|
|
86
107
|
* @param params - SDK handshake parameters.
|
|
87
108
|
* @returns server identity for the handshake.
|
|
88
109
|
*/
|
|
89
110
|
async initialize(params) {
|
|
111
|
+
if (params.reasoningEffort !== void 0 && (typeof params.reasoningEffort !== "string" || params.reasoningEffort.length === 0)) throw new TypeError("initialize reasoningEffort must be a non-empty string");
|
|
90
112
|
if (params.maxTokens !== void 0 && (!Number.isSafeInteger(params.maxTokens) || params.maxTokens <= 0)) throw new TypeError("initialize maxTokens must be a positive safe integer");
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
if (!this.hasAdapterFor(
|
|
96
|
-
if (
|
|
113
|
+
const cwd = resolve(params.cwd);
|
|
114
|
+
const provider = params.provider;
|
|
115
|
+
const model = params.model;
|
|
116
|
+
const reasoningEffort = params.reasoningEffort === void 0 ? void 0 : ReasoningEffortId(params.reasoningEffort);
|
|
117
|
+
if (!this.hasAdapterFor(provider)) {
|
|
118
|
+
if (provider !== "deepseek-official") throw new Error(`no adapter registered for provider "${provider}"`);
|
|
97
119
|
this.llmFiber = await this.ctx.plugin(LlmDeepSeek, {});
|
|
98
120
|
}
|
|
121
|
+
await this.ctx.get("llm").resolveCallConfig({
|
|
122
|
+
provider,
|
|
123
|
+
model,
|
|
124
|
+
...reasoningEffort === void 0 ? {} : { reasoningEffort },
|
|
125
|
+
...params.maxTokens === void 0 ? {} : { maxTokens: params.maxTokens }
|
|
126
|
+
});
|
|
127
|
+
this.cwd = cwd;
|
|
128
|
+
this.provider = provider;
|
|
129
|
+
this.model = model;
|
|
130
|
+
this.reasoningEffort = reasoningEffort;
|
|
131
|
+
this.maxTokens = params.maxTokens;
|
|
132
|
+
this.initialized = true;
|
|
99
133
|
return { serverInfo: {
|
|
100
134
|
name: "deepseek-harness-sdk-runtime",
|
|
101
135
|
version: "0.0.1"
|
|
@@ -107,15 +141,21 @@ var HarnessSdkJsonRpcServer = class {
|
|
|
107
141
|
* @returns the durable message identity.
|
|
108
142
|
*/
|
|
109
143
|
async prompt(params) {
|
|
144
|
+
if (!this.initialized) throw new Error("SDK server is not initialized");
|
|
110
145
|
const rec = await this.getOrCreateSession(params.sessionId);
|
|
111
|
-
|
|
146
|
+
this.assertLiveAgent(rec, params.sessionId);
|
|
147
|
+
const content = await durablePromptContent(this.ctx, params.contentBlocks);
|
|
148
|
+
this.assertLiveAgent(rec, params.sessionId);
|
|
112
149
|
const message = createUserMessage({
|
|
113
|
-
content
|
|
150
|
+
content,
|
|
114
151
|
source: { kind: "user" }
|
|
115
152
|
});
|
|
116
153
|
rec.handle.agent.followup(message);
|
|
117
154
|
return { messageId: message.id };
|
|
118
155
|
}
|
|
156
|
+
assertLiveAgent(rec, sessionId) {
|
|
157
|
+
if (this.ctx.agents.get(rec.handle.agent.id) !== rec.handle.agent) throw new Error(`session agent was disposed outside the server: ${sessionId}`);
|
|
158
|
+
}
|
|
119
159
|
/**
|
|
120
160
|
* Dispose server-owned agents, adapter, and subscriptions to quiescence.
|
|
121
161
|
* The surrounding context remains running.
|
|
@@ -177,11 +217,12 @@ var HarnessSdkJsonRpcServer = class {
|
|
|
177
217
|
}
|
|
178
218
|
async createSession(sessionId) {
|
|
179
219
|
const rec = { handle: await this.ctx.agents.create({
|
|
180
|
-
sessionId:
|
|
220
|
+
sessionId: brandString(sessionId),
|
|
181
221
|
meta: { cwd: this.cwd },
|
|
182
222
|
agentOptions: {
|
|
183
223
|
provider: this.provider,
|
|
184
224
|
model: this.model,
|
|
225
|
+
...this.reasoningEffort === void 0 ? {} : { reasoningEffort: this.reasoningEffort },
|
|
185
226
|
...this.maxTokens === void 0 ? {} : { maxTokens: this.maxTokens }
|
|
186
227
|
}
|
|
187
228
|
}) };
|
|
@@ -195,8 +236,8 @@ var HarnessSdkJsonRpcServer = class {
|
|
|
195
236
|
//#endregion
|
|
196
237
|
//#region lib/types/index.js
|
|
197
238
|
/**
|
|
198
|
-
* SDK-facing JSON-RPC plugin over stdio.
|
|
199
|
-
* whether to load it; see the single-
|
|
239
|
+
* SDK-facing JSON-RPC plugin over stdio. The selected dsh profile decides
|
|
240
|
+
* whether to load it; see the single-launch Agent Note and package README.
|
|
200
241
|
* Stdout is reserved for protocol frames, so the tree must not load a stdout logger.
|
|
201
242
|
* This plugin answers `shutdown`, disposes the complete root runtime, and exits 0; the app bin
|
|
202
243
|
* owns EOF and signal exits. Keep named plugin exports with no default export so
|
package/lib/types/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* SDK-facing JSON-RPC plugin over stdio.
|
|
3
|
-
* whether to load it; see the single-
|
|
2
|
+
* SDK-facing JSON-RPC plugin over stdio. The selected dsh profile decides
|
|
3
|
+
* whether to load it; see the single-launch Agent Note and package README.
|
|
4
4
|
* Stdout is reserved for protocol frames, so the tree must not load a stdout logger.
|
|
5
5
|
* This plugin answers `shutdown`, disposes the complete root runtime, and exits 0; the app bin
|
|
6
6
|
* owns EOF and signal exits. Keep named plugin exports with no default export so
|
package/lib/types/server.d.ts
CHANGED
|
@@ -23,6 +23,7 @@ export declare class HarnessSdkJsonRpcServer {
|
|
|
23
23
|
private cwd;
|
|
24
24
|
private provider;
|
|
25
25
|
private model;
|
|
26
|
+
private reasoningEffort;
|
|
26
27
|
private maxTokens;
|
|
27
28
|
private llmFiber;
|
|
28
29
|
private readonly sessions;
|
|
@@ -30,9 +31,10 @@ export declare class HarnessSdkJsonRpcServer {
|
|
|
30
31
|
private readonly disposers;
|
|
31
32
|
private shutdownTask;
|
|
32
33
|
private shuttingDown;
|
|
34
|
+
private initialized;
|
|
33
35
|
constructor(ctx: Context, transport: JsonRpcTransportPeer, options?: HarnessSdkJsonRpcServerOptions);
|
|
34
36
|
/**
|
|
35
|
-
*
|
|
37
|
+
* Validate and configure the SDK route, mounting the DeepSeek fallback only when unowned.
|
|
36
38
|
* @param params - SDK handshake parameters.
|
|
37
39
|
* @returns server identity for the handshake.
|
|
38
40
|
*/
|
|
@@ -43,6 +45,7 @@ export declare class HarnessSdkJsonRpcServer {
|
|
|
43
45
|
* @returns the durable message identity.
|
|
44
46
|
*/
|
|
45
47
|
prompt(params: SessionPromptParams): Promise<SessionPromptResult>;
|
|
48
|
+
private assertLiveAgent;
|
|
46
49
|
/**
|
|
47
50
|
* Dispose server-owned agents, adapter, and subscriptions to quiescence.
|
|
48
51
|
* The surrounding context remains running.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deepseek-ai/dsh-sdk-jsonrpc-server",
|
|
3
3
|
"description": "Stdio JSON-RPC server plugin for out-of-process DeepSeek Harness SDK clients",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.2-alpha.2",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -32,31 +32,35 @@
|
|
|
32
32
|
],
|
|
33
33
|
"license": "MIT",
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@deepseek-ai/
|
|
35
|
+
"@deepseek-ai/dsh-brand": "^0.1.2-alpha.2",
|
|
36
|
+
"@deepseek-ai/schemastery": "^3.18.2"
|
|
36
37
|
},
|
|
37
38
|
"peerDependencies": {
|
|
38
|
-
"@deepseek-ai/
|
|
39
|
-
"@deepseek-ai/dsh-
|
|
40
|
-
"@deepseek-ai/dsh-
|
|
41
|
-
"@deepseek-ai/dsh-llm-deepseek": "^0.1.
|
|
42
|
-
"@deepseek-ai/dsh-
|
|
43
|
-
"@deepseek-ai/dsh-
|
|
44
|
-
"@deepseek-ai/dsh-
|
|
45
|
-
"@deepseek-ai/dsh-
|
|
46
|
-
"@deepseek-ai/
|
|
39
|
+
"@deepseek-ai/cordis": "^4.0.2",
|
|
40
|
+
"@deepseek-ai/dsh-attachment": "^0.1.2-alpha.2",
|
|
41
|
+
"@deepseek-ai/dsh-invariants": "^0.1.2-alpha.2",
|
|
42
|
+
"@deepseek-ai/dsh-llm-deepseek": "^0.1.2-alpha.2",
|
|
43
|
+
"@deepseek-ai/dsh-llm": "^0.1.2-alpha.2",
|
|
44
|
+
"@deepseek-ai/dsh-agent": "^0.1.2-alpha.2",
|
|
45
|
+
"@deepseek-ai/dsh-scope": "^0.1.2-alpha.2",
|
|
46
|
+
"@deepseek-ai/dsh-sdk-protocol": "^0.1.2-alpha.2",
|
|
47
|
+
"@deepseek-ai/dsh-session": "^0.1.2-alpha.2",
|
|
48
|
+
"@deepseek-ai/dsh-subagent": "^0.1.2-alpha.2"
|
|
47
49
|
},
|
|
48
50
|
"devDependencies": {
|
|
49
|
-
"@deepseek-ai/cordis
|
|
50
|
-
"@deepseek-ai/
|
|
51
|
-
"@deepseek-ai/dsh-agent
|
|
52
|
-
"@deepseek-ai/dsh-
|
|
53
|
-
"@deepseek-ai/dsh-
|
|
54
|
-
"@deepseek-ai/dsh-
|
|
55
|
-
"@deepseek-ai/dsh-
|
|
56
|
-
"@deepseek-ai/dsh-
|
|
57
|
-
"@deepseek-ai/dsh-
|
|
58
|
-
"@deepseek-ai/
|
|
59
|
-
"@deepseek-ai/dsh-
|
|
60
|
-
"@deepseek-ai/dsh-
|
|
51
|
+
"@deepseek-ai/cordis": "^4.0.2",
|
|
52
|
+
"@deepseek-ai/cordis-plugin-loader": "^1.0.3",
|
|
53
|
+
"@deepseek-ai/dsh-agent": "^0.1.2-alpha.2",
|
|
54
|
+
"@deepseek-ai/dsh-agent-spine-demo": "^0.1.2-alpha.2",
|
|
55
|
+
"@deepseek-ai/dsh-invariants": "^0.1.2-alpha.2",
|
|
56
|
+
"@deepseek-ai/dsh-attachment": "^0.1.2-alpha.2",
|
|
57
|
+
"@deepseek-ai/dsh-llm": "^0.1.2-alpha.2",
|
|
58
|
+
"@deepseek-ai/dsh-llm-deepseek": "^0.1.2-alpha.2",
|
|
59
|
+
"@deepseek-ai/dsh-scope": "^0.1.2-alpha.2",
|
|
60
|
+
"@deepseek-ai/dsh-sdk-protocol": "^0.1.2-alpha.2",
|
|
61
|
+
"@deepseek-ai/dsh-session": "^0.1.2-alpha.2",
|
|
62
|
+
"@deepseek-ai/dsh-session-persistence-jsonl": "^0.1.2-alpha.2",
|
|
63
|
+
"@deepseek-ai/dsh-session-projection": "^0.1.2-alpha.2",
|
|
64
|
+
"@deepseek-ai/dsh-subagent": "^0.1.2-alpha.2"
|
|
61
65
|
}
|
|
62
66
|
}
|