Files
deepseek-harness/packages/client/runtime/README.zh.md
T
Hypatia May e466c66ee3 Merge remote-tracking branch 'origin/master' into codex/status-bar-token-metrics
# Conflicts:
#	docs/cordis-catalog/events.md
#	docs/event-producer-consumer.md
#	packages/client/runtime/src/client/sessions/conversation.ts
#	packages/client/runtime/src/client/sessions/session.ts
#	packages/client/runtime/tests/fake-api.ts
#	packages/client/runtime/tests/session.spec.ts
#	packages/client/ui-conversation/tests/chat-stats-bash-sample.spec.tsx
#	packages/client/ui-conversation/tests/chat-toolview-slot.spec.tsx
#	packages/client/ui-conversation/tests/chat-view.spec.tsx
#	packages/client/ui-conversation/tests/gate-branch-tails.spec.tsx
#	packages/client/ui-conversation/tests/queue-dock.spec.tsx
#	packages/core/agent-loop/README.i18n.yaml
#	packages/core/agent/README.i18n.yaml
#	packages/host/apiproxy/README.i18n.yaml
#	packages/host/apiproxy/src/api-proxy.ts
#	packages/host/apiproxy/src/api/events.schema.ts
#	packages/host/apiproxy/src/api/events.ts
#	packages/host/apiproxy/src/api/index.ts
#	packages/host/apiproxy/src/api/sessions.schema.ts
#	packages/host/apiproxy/src/api/sessions.ts
#	packages/host/apiproxy/tests/rpc-schemas.spec.ts
2026-07-28 19:34:30 +08:00

6.8 KiB
Raw Blame History

@deepseek-ai/dsh-client-runtime

English | 中文

客户端 cordis 启动与不依赖 React 的对象服务:SlotsService 包装 SlotCore 并提供 renderer 数据源;SessionsService 拥有 Session 对象、列表/scopehistory 状态;WorkspacesService 依赖 SessionsService,拥有 Workspace 对象、列表/操作、默认目标派生,以及 New Session 空会话复用入口(connectWorkspace)。运行时把共享 Host 流分发给两个 manager。客户端 Session 一律由 Host 出生(一次 session.create 同瞬产出 Session+Agent+cwd);客户端不持有任何实体化之前的会话状态——Agent scopehost dsh-scope 的客户端镜像,以 agent/session 共用 id 为键)在会话行进入列表镜像时出生,随 prune 死亡。契约:api-contracts v3 §4。todostitle 等通用完整日志领域值存放在逐会话投影值仓中:history 尾页的 projections 为其播种,session/projection 帧按较高 seq 优先更新,消费方通过 useProjection 按 key 读取。持久的 ConversationSnapshot.metrics 则来自独立的 history 尾页值与实时 session/metrics 帧,因为即时 token-meter 压力可以在相同持久日志修订号上继续变化;客户端只接受日志修订号与投影修订号均不减小的数据。ConversationSnapshot.modelRequestContextWindow 另行保留当前 mux 连接观察到的最新 session/model-request 容量。后续请求会替换或清除该值,session/subscribed 则同时清除指标顺序状态与容量;因此,重连、恢复和新订阅都不会显示百分比,直到观察到另一次请求。缺失的 metrics 保持为 null,而不是根据可见节点窗口推断。

Workspace 与 Session 列表

Workspace 和 Session 列表各自具有单调的 pendingready 基线阶段,也有各自的刷新活动/错误状态。列表请求期间到达的增量更新/移除帧与一元变更回显会在其响应之上回放。第一次成功的基线建立 Host 顺序;后续刷新更新行和成员关系,但不改变已经显示的标识之间的相对顺序。已移除的 Workspace id 会保留进程本地删除标记,避免延迟到达的 changed 帧将其复活;重连仍以 workspace.list 作为基线。Workspace 新近程度只在两条基线都 ready 后派生,且绝不改变 Workspace 列表顺序。

WorkspacesService.delete(workspaceId) 在一元响应成功后从客户端投影中移除注册记录;对应的 host/workspace-removed 帧具有幂等性,并负责同步其他标签页。Session 状态与当前 Session selection 相互独立,因此 Workspace 消失后,其已记账的 Session 会立即投影到 Ungrouped 下。

SlotsService 分别为 renderer 提供 useSessionsuseWorkspaces 的裸 observableweb-react 创建 hook。Workspace 业务状态不会进入 SessionListState 或配置项 store。

New Session 与 blank 镜像

WorkspacesService.connectWorkspace(workspaceId) 解析 New Session 流程最终落入的会话:先在列表镜像中复用该 workspace 的既有空会话(blank && cwd == workspace.path),未命中则调用 session.create({workspaceId}),返回会话 id 由调用方 open。SessionSummary.blank 镜像主机派生的空日志位,在客户端只降不升:由 session.listhost/session-added 帧播种,本地首次受理成功prompt()(RPC 成功响应时——受理即证明用户消息已入主机日志;首讯被拒则会话保持 blank、保持可复用)与任何 running: true 状态帧翻为 false,每次列表重拉重新对齐。列表表面隐藏 blank 行;store 保留全部行。SessionsService.create 接受可选的、由调用方预先分配的 SessionId,失败时抛出 SessionCreateError(携带 requestedSessionId)。

Code Mode 子调用索引

ConversationSnapshot.codeDispatches 按父调用的 callId 和启动顺序,用原生调用块形状组织一个 run_code 调用的子调用:tool/code-dispatch-start 事件落成 RunningToolCall 形状(行组件从该形状推导运行中的转圈状态),其 tool/code-dispatch 完结事件原位替换为 ToolResultNode 形状,callTime 携带成对 start 事件的时间。start 落在回放窗口之外的完结事件则直接追加,callTime: null(耗时未知——绝不伪造零耗时)。live mux 帧与历史回放构建相同的索引;子调用永不进入 surface nodes 流;无关快照交换不会改变每个父调用对应的数组引用和映射引用,两者均保持 memo 稳定。

Session 标题投影

SessionManager 独立于 Session 实例是否到达而保留逐会话通用投影值仓,因此实时 title 帧可以在会话打开前更新列表行。订阅基线会截断 seq 超过 lastSeq 的投影行;下一份 history 尾页基线重新播种持久值,显式移除 Session 则清除该值仓。因此,面向客户端的 SessionSummary.title 只包含真实的持久标题;title key 缺失时,displayTitle 始终依次回退到 cwd basename 和 Session id。

会话模型选择

每个常驻 Session 都拥有一个 modelSelection 快照,其中包含当前提供方/模型目标、按提供方分组的目录、逐提供方失败记录,以及 idleloadingreadyselectingerror 状态。历史记录会建立或刷新当前目标,打开选择器会刷新目录;选择失败会保留上一个目标和可用分组。目录与选择操作共用单调递增的代次,因此较旧响应无法覆盖较新的选择。重连重建会恢复 Host 报告的目标,同时不替换未变化的选择子结构。

模型体验

无,因为 Session 对象层会选择后续 Host 请求使用的提供方/模型路由,但不添加任何模型可见内容。

KV Cache 影响

更改目标可能改变提供方侧的缓存复用,或使其失效;该包本身不会改变提示词前缀。

已知限制与暂缓事项

  • loader.unload 是 stub(抛出 not-implemented:完整链路(fiber 释放 → 注册级联 → 样式移除)随 HMR 项目落地。
  • scope 拆卸由阶段驱动,目前只能有一个占用者:已 staged 的 Session 精确跟随 list.current(staging 就是打开信号:事件窗口打开 ⟺ Session 位于 stage);在 staged 状态下被移除的 Session,其 scope 会冻结保留,直到 stage 转向其他 Session,而非直到真实观察者数量降为零。解析(binding()scope())只是纯寻址,可安全用于渲染;渲染层经 currentProvideInfo observable 读取当前 bundle。并发 pane 落地时,staged 状态可以扩展为多 pane 列表。
  • 插件组合包从该包执行值导入时必须使用 /client 子路径:裸包名不在 loader external 表中,会内联第二个模块实例;其私有 scope-tag Symbol 永远无法匹配(空状态 P0 事故复盘)。