Skip to content

Commit e8e98e9

Browse files
authored
Merge pull request #4649 from huangruiteng/codex/dsh-client-015-20260917
refactor(dsh): adopt the typed 0.1.5 host and client boundary
2 parents 417edd5 + 0b0c1b2 commit e8e98e9

22 files changed

Lines changed: 4829 additions & 5404 deletions

‎docs/architecture/rfcs/harness-selection-dsh-pi-v0.md‎

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -249,12 +249,22 @@ passivity is a property of the selected adapter and its loaded dependencies.
249249

250250
The two LoopX surfaces that depend on dsh do not move together. The bounded Turn
251251
host uses the Python SDK/runtime pin recorded above (`0.1.5rc1`, the released
252-
channel). The dsh-side plugin (`packages/dsh-loopx-plugin`) still builds its
253-
development and client surfaces against `0.1.1-rc.2` while its clean-Docker smoke
254-
already asserts `dsh --version == 0.1.5-rc.1`, and the 0.1.5 line no longer
255-
publishes `@deepseek-ai/dsh-client-runtime` (last released 0.1.1-rc.2), moving
256-
the client runner to `@deepseek-ai/dsh-cordis-client-runner`. That upgrade is
257-
tracked as its own pin item and does not change the L1 observer contract above.
252+
channel). The dsh-side plugin (`packages/dsh-loopx-plugin`) now builds its
253+
development, host, and client surfaces on the same released `0.1.5-rc.2` line
254+
instead of the retired `0.1.1-rc.2` one, and its npm peer ranges admit only
255+
`>=0.1.5-rc.1`. Three upstream moves forced that, so it is a new release line
256+
rather than a patch: the 0.1.5 line no longer publishes
257+
`@deepseek-ai/dsh-client-runtime` (last released 0.1.1-rc.2), which moves the
258+
`slots` service seat to `@deepseek-ai/dsh-client-ui-renderer` — the package this
259+
manifest now names in `dsh.client.inject`; `Session.events` became
260+
`Session.snapshotEvents()` and `Inbox.hasPending` became the two pending queues;
261+
and the shared `/api` bridge addresses Remote methods as `<namespace>/<method>`
262+
with a single `args` payload field. One `dsh.client.inject` list cannot order
263+
boot rows for both generations at once, so the plugin cannot claim both. The L1
264+
observer contract above is unchanged: the observer still consumes only
265+
`session/created`, `session/event`, and `session/disposed`, and now treats
266+
token-level `assistant/chunk` rows as retired input replayed from older durable
267+
logs instead of a live event type.
258268

259269
## Data and Authority Flow
260270

‎docs/architecture/rfcs/harness-selection-dsh-pi-v0.zh-CN.md‎

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -202,11 +202,18 @@ tag:PyPI 上的 `deepseek-harness-sdk==0.1.5rc1` /
202202

203203
依赖 dsh 的两个 LoopX 面并不一起移动:有界 Turn 宿主使用上文记录的 Python
204204
SDK/runtime 固定版本(`0.1.5rc1`,已发布通道);而 dsh 侧插件
205-
(`packages/dsh-loopx-plugin`)的开发与客户端面仍构建在 `0.1.1-rc.2` 上,尽管其
206-
clean-Docker smoke 已断言 `dsh --version == 0.1.5-rc.1`。0.1.5 线不再发布
207-
`@deepseek-ai/dsh-client-runtime`(最后发布版本为 `0.1.1-rc.2`),客户端 runner 改为
208-
`@deepseek-ai/dsh-cordis-client-runner`。该升级作为独立的 pin 项跟踪,不改变上文的
209-
L1 observer 契约。
205+
(`packages/dsh-loopx-plugin`)的开发、宿主与客户端面现已统一构建在同一已发布的
206+
`0.1.5-rc.2` 线上,不再停留在 `0.1.1-rc.2`,其 npm peer 范围只接受
207+
`>=0.1.5-rc.1`。这是上游三处变化逼出来的,因此它是一条新的发布线而不是原地补丁:
208+
0.1.5 线不再发布 `@deepseek-ai/dsh-client-runtime`(最后发布版本为 `0.1.1-rc.2`),
209+
`slots` service 座位随之移到 `@deepseek-ai/dsh-client-ui-renderer`,也就是本 manifest
210+
现在写入 `dsh.client.inject` 的包;`Session.events` 变为 `Session.snapshotEvents()`,
211+
`Inbox.hasPending` 变为两个 pending 队列;共享 `/api` bridge 用
212+
`<namespace>/<method>` 寻址 Remote 方法,并只接受一个 `args` payload 字段。一份
213+
`dsh.client.inject` 无法同时为两代排序 boot row,所以插件不能同时声明两代。上文的
214+
L1 observer 契约不变:observer 仍只消费 `session/created`、`session/event`、
215+
`session/disposed`,只是把 token 级 `assistant/chunk` 行视为旧 durable 日志重放出来的
216+
已退场输入,而不是现存事件类型。
210217

211218
## 数据流与权限
212219

‎loopx/capabilities/reliability_diagnostics/README.md‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,8 @@ hooks and writes no files (feature-off parity). When enabled, `observer.ts`
190190
observes only `session/created`, `session/event`, and `session/disposed`.
191191
Events from any other session are rejected as `identity_invalid`, so they can
192192
never be silently attributed to the configured goal. Token-level
193-
`assistant/chunk` events are not consumed.
193+
`assistant/chunk` events — a retired type that only older durable logs still
194+
replay — are not consumed.
194195

195196
## Validation
196197

‎loopx/capabilities/reliability_diagnostics/README.zh-CN.md‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,8 @@ ingest 是透明拷贝。任何损坏或被拒绝的输入都会追加持久化
162162
三个必需变量未全部有效时,observer 行不注册任何 hook、不写任何文件(feature-off
163163
parity)。启用后,`observer.ts` 只观察 `session/created`、`session/event`、
164164
`session/disposed`。其它 session 的事件一律以 `identity_invalid` 拒绝,因此不会静默归属
165-
到配置的 goal。token 级 `assistant/chunk` 不被消费。
165+
到配置的 goal。token 级 `assistant/chunk`(已退场类型,只有旧 durable 日志还会重放)
166+
不被消费。
166167

167168
## 验证
168169

‎packages/dsh-loopx-plugin/README.md‎

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ separate Loader rows:
1111
Session successfully invokes the exact `loopx` skill. It then asks LoopX
1212
whether another turn may run and queues the authoritative heartbeat task
1313
into that live DSH Agent.
14-
- the package-root Host registers a loopback-only `/loopx` Connection channel,
15-
and its web Client contributes a compact GoalBar between DSH's native GoalBar
16-
and Queue dock rows. It renders only for one exact live
17-
`(goalId, loopxAgentId)` binding.
14+
- the package-root Host registers GoalBar at the authenticated
15+
`/api/loopx.goalbar` route required by DSH 0.1.5. Its web Client adds a compact
16+
GoalBar between DSH's native GoalBar and Queue dock rows, visible only for one
17+
exact live `(goalId, loopxAgentId)` binding.
1818

1919
Installing the plugin and starting DSH load and prepare these capabilities;
2020
neither creates a binding nor activates the Driver. The GoalBar
@@ -61,7 +61,12 @@ dsh plugin --profile web add \
6161
"https://github.com/huangruiteng/loopx/releases/download/dsh-loopx-plugin-v0.1.1-beta.5/dsh-loopx-plugin-0.1.1-beta.5.tgz"
6262
```
6363

64-
For a source checkout, the equivalent build-and-install path is:
64+
The prebuilt release above retains its original DSH compatibility. This source
65+
checkout targets DSH 0.1.5-rc.1 or newer within the 0.1.x line; it does not
66+
publish a new plugin release. The exported legacy RPC registration remains
67+
available to explicit callers, but plugin startup always uses the shared API.
68+
69+
For the DSH 0.1.5 source build, use:
6570

6671
```bash
6772
cd packages/dsh-loopx-plugin
@@ -129,7 +134,7 @@ Start/Pause. Focused Client tests cover Session-generation replacement and old
129134
request cancellation without duplicating that matrix in the packed smoke.
130135
The Docker smoke packs the current plugin and builds the current LoopX
131136
release-candidate wheel, then starts both in a clean Debian container with the
132-
DSH 0.1.5 release candidate. It proves PEP 668-compatible private installation,
137+
DSH 0.1.5-rc.2 release candidate. It proves PEP 668-compatible private installation,
133138
the managed launcher, startup readiness, installed `loopx` skill files, launch-
134139
token authentication, and an authenticated GoalBar read through DSH's shared
135140
API carrier. It requires Docker, `uv`, and network access for base images and
@@ -198,9 +203,10 @@ loopx reliability-diagnostics status --goal-id <goal-id> --format json
198203

199204
Unless all required variables are valid, the independent observer row
200205
registers no hook and writes no file. When enabled, it consumes only
201-
`session/created`, `session/event`, and `session/disposed`; it skips
202-
`assistant/chunk` and records tool names, turn and step numbers, typed end
203-
reasons, and ids only, never arguments, outputs, prompts, or paths. Events for
206+
`session/created`, `session/event`, and `session/disposed`; it skips the retired
207+
token-level `assistant/chunk` rows older logs still replay, and records tool
208+
names, turn and step numbers, typed end reasons, and ids only, never arguments,
209+
outputs, prompts, or paths. Events for
204210
any session other than the exact configured session are rejected as
205211
`identity_invalid`. The stats record pins worker/model/task/environment/tools/
206212
budget plus adapter and observer revisions, declares source coverage, and
@@ -214,12 +220,17 @@ C1 run, and measured observer overhead remain separate evidence gates.
214220

215221
## GoalBar authority and privacy boundary
216222

217-
`/loopx` is registered with Connection authority `loopback`. Loopback is a
218-
network reachability fence, not user authentication, and Phase 1 does not
219-
support LAN or remote browsers. The browser supplies only its injected DSH
220-
Session id and, for an action, the last validated Goal/Agent pair. The Host
221-
re-derives cwd and thread identity from the live DSH Agent, freshly resolves
222-
the binding, and executes only fixed LoopX argv.
223+
The GoalBar carrier uses Connection's authenticated `/api/loopx.goalbar`
224+
Fetch route. Explicit callers of the deprecated RPC registration can still
225+
register `/loopx`; plugin startup does not select it automatically. Both pass
226+
Connection's Host/Origin trust fence and browser authentication, and this
227+
package adds no second credential of its own. The deployment's reachability
228+
policy — loopback by default, or declared `trustedHosts` — decides which
229+
browsers can reach the host at all; Phase 1 does not support LAN or remote
230+
browsers. The browser supplies only its injected DSH Session id and, for an
231+
action, the last validated Goal/Agent pair. The Host re-derives cwd and thread
232+
identity from the live DSH Agent, freshly resolves the binding, and executes
233+
only fixed LoopX argv.
223234

224235
The wire allowlist contains ids, activation, live Agent status, full-lane
225236
counts, cursors, opaque source revisions, and fixed error codes. It excludes

‎packages/dsh-loopx-plugin/package.json‎

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -59,47 +59,47 @@
5959
"inject": [
6060
"@deepseek-ai/dsh-client-connection",
6161
"@deepseek-ai/dsh-client-locale",
62-
"@deepseek-ai/dsh-client-runtime",
63-
"@deepseek-ai/dsh-client-ui-conversation"
62+
"@deepseek-ai/dsh-client-ui-conversation",
63+
"@deepseek-ai/dsh-client-ui-renderer"
6464
],
6565
"platform": "web"
6666
}
6767
},
6868
"peerDependencies": {
69-
"@deepseek-ai/cordis": "^4.0.1",
70-
"@deepseek-ai/dsh": ">=0.1.0-rc.7 <0.1.1 || >=0.1.1-rc.1 <0.2.0-0",
71-
"@deepseek-ai/dsh-client-connection": ">=0.1.0-rc.7 <0.1.1 || >=0.1.1-rc.1 <0.2.0-0",
72-
"@deepseek-ai/dsh-client-locale": ">=0.1.0-rc.7 <0.1.1 || >=0.1.1-rc.1 <0.2.0-0",
73-
"@deepseek-ai/dsh-client-runtime": ">=0.1.0-rc.7 <0.1.1 || >=0.1.1-rc.1 <0.2.0-0",
74-
"@deepseek-ai/dsh-client-ui-conversation": ">=0.1.0-rc.7 <0.1.1 || >=0.1.1-rc.1 <0.2.0-0",
75-
"@deepseek-ai/dsh-client-ui-primitives": ">=0.1.0-rc.7 <0.1.1 || >=0.1.1-rc.1 <0.2.0-0",
76-
"@deepseek-ai/dsh-client-ui-slots": ">=0.1.0-rc.7 <0.1.1 || >=0.1.1-rc.1 <0.2.0-0",
69+
"@deepseek-ai/cordis": "^4.0.2",
70+
"@deepseek-ai/dsh": ">=0.1.5-rc.1 <0.2.0-0",
71+
"@deepseek-ai/dsh-client-connection": ">=0.1.5-rc.1 <0.2.0-0",
72+
"@deepseek-ai/dsh-client-locale": ">=0.1.5-rc.1 <0.2.0-0",
73+
"@deepseek-ai/dsh-client-ui-conversation": ">=0.1.5-rc.1 <0.2.0-0",
74+
"@deepseek-ai/dsh-client-ui-primitives": ">=0.1.5-rc.1 <0.2.0-0",
75+
"@deepseek-ai/dsh-client-ui-renderer": ">=0.1.5-rc.1 <0.2.0-0",
76+
"@deepseek-ai/dsh-client-ui-slots": ">=0.1.5-rc.1 <0.2.0-0",
7777
"react": "^18.2.0"
7878
},
7979
"peerDependenciesMeta": {
8080
"@deepseek-ai/cordis": { "optional": true },
8181
"@deepseek-ai/dsh": { "optional": true },
8282
"@deepseek-ai/dsh-client-connection": { "optional": true },
8383
"@deepseek-ai/dsh-client-locale": { "optional": true },
84-
"@deepseek-ai/dsh-client-runtime": { "optional": true },
8584
"@deepseek-ai/dsh-client-ui-conversation": { "optional": true },
8685
"@deepseek-ai/dsh-client-ui-primitives": { "optional": true },
86+
"@deepseek-ai/dsh-client-ui-renderer": { "optional": true },
8787
"@deepseek-ai/dsh-client-ui-slots": { "optional": true },
8888
"react": { "optional": true }
8989
},
9090
"devDependencies": {
91-
"@deepseek-ai/cordis": "4.0.1",
92-
"@deepseek-ai/dsh": "0.1.1-rc.2",
93-
"@deepseek-ai/dsh-agent": "0.1.1-rc.2",
94-
"@deepseek-ai/dsh-client-connection": "0.1.1-rc.2",
95-
"@deepseek-ai/dsh-client-locale": "0.1.1-rc.2",
96-
"@deepseek-ai/dsh-client-runtime": "0.1.1-rc.2",
97-
"@deepseek-ai/dsh-client-ui-conversation": "0.1.1-rc.2",
98-
"@deepseek-ai/dsh-client-ui-primitives": "0.1.1-rc.2",
99-
"@deepseek-ai/dsh-client-ui-slots": "0.1.1-rc.2",
100-
"@deepseek-ai/dsh-commands": "0.1.1-rc.2",
101-
"@deepseek-ai/dsh-llm": "0.1.1-rc.2",
102-
"@deepseek-ai/dsh-session": "0.1.1-rc.2",
91+
"@deepseek-ai/cordis": "4.0.2",
92+
"@deepseek-ai/dsh": "0.1.5-rc.2",
93+
"@deepseek-ai/dsh-agent": "0.1.5-rc.2",
94+
"@deepseek-ai/dsh-client-connection": "0.1.5-rc.2",
95+
"@deepseek-ai/dsh-client-locale": "0.1.5-rc.2",
96+
"@deepseek-ai/dsh-client-ui-conversation": "0.1.5-rc.2",
97+
"@deepseek-ai/dsh-client-ui-primitives": "0.1.5-rc.2",
98+
"@deepseek-ai/dsh-client-ui-renderer": "0.1.5-rc.2",
99+
"@deepseek-ai/dsh-client-ui-slots": "0.1.5-rc.2",
100+
"@deepseek-ai/dsh-commands": "0.1.5-rc.2",
101+
"@deepseek-ai/dsh-llm": "0.1.5-rc.2",
102+
"@deepseek-ai/dsh-session": "0.1.5-rc.2",
103103
"@types/node": "^22.19.0",
104104
"@types/react": "~18.3.1",
105105
"@types/react-dom": "~18.3.1",

0 commit comments

Comments
 (0)