# u-claw 两侧细勘察补全(多轮会话锚定 + 协议漂移) > 2026-10-04 · 上游:[devflow集成u-claw-可行性研究-2026-09-28.md](./devflow集成u-claw-可行性研究-2026-09-28.md) 第六节待补槽位「u-claw 侧收尾:WS 渠道的多轮会话锚定细节(request_id↔chain 映射、会话持久化边界)」。 > 勘察基线:u-claw HEAD 021a230(基线 d8dc003 后 18 提交)/ u-relay 现行源码 / u-ppt 参考实现未变。 > 全部结论以源码为准(wsch.go 405 行全文 + chainpool.go + agentd.go + u-relay src)。 ## 一、多轮会话锚定:channel 级单 chain 模型(结论定案) **WS 渠道不是 per-request 会话,是 channel 级单 chain 粘性会话**: ``` wsChannel (1:1) └─ chain = NewSessionChain("ws", cwd, statePath, ...) // wsch.go:113 run() 启动时建一次 ├─ TakeSummary() 每轮取摘要 → RenderWithSummary 注入下轮 prompt // process():224 ├─ HandleWithResult(prompt, progressWatcher) // 常驻 claude -p 子进程 └─ 会话自动连续(各轮 session_id 相同,无需 --resume) // agentd.go:6 注释 ``` - **request_id 仅是单次指令标识**(配对进度/结果帧),不映射 chain——所有 request_id 共享同一 chain 与同一 claude 进程 - **上下文维持**:常驻进程各轮 session_id 相同(agentd.go:6),链层另有摘要注入(`TakeSummary`→`RenderWithSummary`)双保险;崩溃/超时后 `ensureAlive` 自动重启并 `--resume` 上次会话 ID 恢复(agentd.go:154) - **持久化边界**:会话状态文件 `sessionStatePath("ws")`(exports.go:96,落 `~/.u-claw/sessions/`);会话 jsonl 落 claude 自己的项目目录(cwd 对应);**跨进程重启后上下文不丢**(--resume + 会话文件保留) - **devflow 侧含义**:接入后 devflow 与 u-claw 的对话天然是**一条连续会话**(同一 channel_id 下所有 ask_uclaw 调用共享上下文)——多轮追问无需传会话 ID,但也意味着 devflow 内不同 devflow 会话若共用 channel_id 会互相污染上下文(见 §4 设计含义 D-2) ## 二、协议漂移:可行性文档已过时(重要修正) 2026-09-28 可行性文档记载 `/ws/device` + `{kind,device_id,token}` hello——**已漂移**,e8113c5「中继握手协议对齐服务端」重定义了角色: | 维度 | 可行性文档(9-28 记载) | 现行源码(10-04 实证) | |---|---|---| | 端点 | `/ws/device` / `/ws/miniapp` | **`/ws/agent`(执行端,u-claw 连此)** / **`/ws/commander`(控制端,devflow 连此)** | | hello | `{kind, device_id, token}` | **`{kind:"commander", channel_id, token}`**(commander);agent 端 `{kind:"agent", channel_id, token}` | | 帧路由 | Event→Miniapp / Command→Device | **Event(执行端发)→同 channel_id 全部 Commander;Command(控制端发)→同 channel_id 绑定的 Agent**(conn.rs:114, relay.rs:117-119) | | 心跳 | ping/pong(relay 本地回) | 同款仍在:30s ping / 90s 读死线 / 写死线 10s(wsch.go:45-50;miniapp 侧同款) | | 鉴权 | 全局共享 token(鉴权债) | **配对语义已改**:Commander 持 token 申请绑定 channel_id(broadcast.rs:138 `Pair{channel_id, token}`),Agent 端 token 校验;但 relay 侧仍是 env `U_RELAY_TOKEN` 单 token(relay.rs:9-10, main.rs:28 fail-fast),**per-channel token 未做**——鉴权债部分缩小 | **接入实施时必须按本节现行协议实现,不能照抄 9-28 文档或 u-ppt relay.ts 原样**(u-ppt 用的还是旧 Miniapp/Device 语义,需确认 u-ppt 是否已随 e8113c5 升级,若未升级则 u-ppt relay.ts 仅作 TS 结构参考、协议字段按本节改)。 ## 三、执行语义与时限(新增已核实事实) - **串行 worker**:每 channel 一条串行 worker goroutine,reqCh 缓冲 4,满则**丢弃**由发起方重试(wsch.go:108-109)——devflow 侧需配超时重试与队列已满可感知的语义(当前协议无「已丢弃」回执,devflow 端只能在超时后重发) - **单条指令硬超时 15min**(`wsExecTimeout`,wsch.go:38):超时 AbortRunning 杀进程、回「处理超时」结果、链保 session ID 下条 --resume 续跑——**devflow aichat 工具的 client 侧超时须 >15min 或对齐处理** - **进度节流 2s**(progressWatcher,wsch.go:368):assistant text=阶段叙述+tool_use=当前动作,2s 节流回传——devflow 工具卡「流式」粒度即此(块级,非逐 token) - **空闲超时链回收**:chainPool idle 后整链回收(杀 claude 进程 ~500MB),来消息 --resume 重建冷启动 ~7s(chainpool.go:1-7)——**devflow 侧期望「空闲后首次调用慢」为正常** - **链池挤占语义**:槽满 LRU 挤最旧 idle 链,活跃链不挤;hardCap 全忙时拒绝建链返错(chainpool.go:100-128) ## 四、devflow 侧接入设计含义(增量到第五节) - **D-1 工具卡流式**:ask_uclaw 工具卡可直接消费 agent_progress 帧(2s 块级)作流式显示,agent_result 全文为最终 tool result——零改造对齐 devflow 现有工具卡模式 - **D-2 channel_id 策略**:单 chain 会话模型下,建议 devflow **per-conv 生成 channel_id**(如 `devflow-{conv_id}`)接入——每个 devflow 会话映射独立 u-claw chain,会话隔离天然成立;代价是 u-claw 侧 chainPool 槽位占用(max 上限与 LRU 挤占,见 chainpool.go),需确认 u-claw 侧 max 配置余量(当前 max 值未在本次勘察范围,实施前核 `~/.u-claw/u-claw.yml`) - **D-3 超时对齐**:devflow ask_uclaw 客户端超时建议 16min(>15min 硬上限),超时即回失败;进度 2s 节流下客户端 watchdog 应容忍 30s+ 无 progress(u-claw 长任务中间可能无 assistant 输出) - **D-4 队列满丢弃无回执**:reqCh 满时静默丢——devflow 侧在 15/16min 超时后重发(最多 2 次),并把「u-claw 渠道忙」文案明确给用户 - **D-5 offline 语义**:relay 无离线缓存(9-28 已载),叠加本节串行+丢弃语义:**devflow 发送前可先发探活 ping**(30s 内无 pong 视为渠道不可达),不可达直接报「u-claw 离线」不进队列 ## 五、接入实施批清单(更新版,覆盖 9-28 第五节) 1. **协议实现(Rust 客户端)**:连 `/ws/commander`,hello `{kind:"commander", channel_id: devflow-{conv_id}, token}`,按本节协议处理 Event 帧(agent_progress/agent_result 按 request_id 配对)——**不照抄 u-ppt relay.ts 字段**,仅参考结构 2. **工具注册**:`ask_uclaw(prompt)` → declare_tool!(Low/只读? 不,执行类 Medium),progress 帧接 ToolCard 流式,result 全文为 tool result 3. **配置页**:relay URL / channel 前缀 / token(keyring)——默认关 4. **超时与重试**:客户端 16min 超时 + 2 次重试 + 发送前探活 ping 5. **可选 phase2**:消息渠道形态(u-claw 代言 aichat)/ 反向 MCP——维持 9-28 形态 2/3 描述 6. ~~**u-ppt 核对**(实施前置小步)~~ ✅2026-10-04 已核:u-ppt relay.ts 65bae53(2026-10-01)已随 e8113c5 升级 commander/channel_id 协议——端点自动补全 `/ws/commander`(:39)/hello `{kind:'commander',channel_id,token}`(:135)/10s 握手看门狗+hello_ack(:127)/30s ping+15s pong(:33)/指数退避 1s→30s(:36)/agent_request|progress|result 按 request_id 分发(:158) 六项与 u-relay 现行源码一致。**relay.ts 可直接作参考实现**(去 deck/SEP 专有逻辑),devflow 接入是 commander 协议第二个实现,非首个 ## 六、基线更新 ``` 基线 HEAD(2026-10-04): devflow 9216d4c u-relay e8113c5后现行(见 src) u-claw 021a230 u-ppt 待核 漂移检查(下次):u-claw git log --oneline 021a230..HEAD;u-relay per-channel token 是否落地 ``` ## 关联 - 上游:`devflow集成u-claw-可行性研究-2026-09-28.md`(本文件填其第六节末槽位) - u-claw 源:`wsch.go`(WS 渠道全文 405 行)/ `internal/core/chainpool.go`(链池)/ `internal/core/agentd.go`(常驻 claude + --resume) - u-relay 源:`src/relay.rs`(端点+握手)/ `src/conn.rs`(配对路由)/ `src/broadcast.rs`(Pair 协议)