Skip to content
FunCoding

Search

Search docs, Skills and MCP

会话生命周期与客户端身份

区分 create、attach、load、resume、detach 和会话终止。

This page has not been translated into English yet. The original Chinese version is shown below.

一个 daemon session 是绑定 ACP sessionId 的逻辑对话。client 是参与它的控制端;SSE subscriber 又只是某次事件订阅。三者生命周期不同,不能用“断开连接”统称所有关闭。

创建、附加与恢复

操作含义
POST /session,single scope已有 default session 时附加,否则创建
POST /session,thread scope创建独立对话,仍受 maxSessions 约束
POST /session/:id/load恢复并返回有界 replay snapshot
POST /session/:id/resume恢复但不请求同样的历史 replay
POST /session/:id/detach解除一个 client 的附着,返回 204;本身不是持久删除

恢复使用 pendingRestoreIds 避免同 ID 并发重复进行,并缓存 restoreState 供稍后附加者。session_resume 是稳定 daemon capability,ACP 内部方法仍可叫 unstable_resumeSession;客户端不应继续只检测旧别名。

Client ID 的选择

X-Qwen-Client-Id 由客户端自行选择,daemon 不代为生成。格式为 [A-Za-z0-9._:-]{1,128}。不同 controller 应使用各自稳定 ID;宿主与嵌入 Web Shell 只有确实作为同一逻辑控制端时才共用。

共用 ID 后,日志无法区分是谁发起请求。它也不是登录身份或 proof-of-possession;审批边界见多客户端审批。

关联事件可在 envelope 中带 originatorClientId。对自己的用户回显或 mid_turn_message_injected 去重前,必须比较实际 originator,不能因为自己也订阅该 session 就丢掉所有用户消息。

心跳与元数据

POST /session/:id/heartbeat 更新 sessionLastSeenAt;携带已登记 ID 时也更新对应 clientLastSeenAt。当前心跳提供可见性,不实施 v1 单客户端撤销/驱逐策略。

PATCH /session/:id/metadata 更新 displayName,长度最多 256,拒绝 U+0000–U+001F 和 U+007F 控制字符。成功后广播 session_metadata_updated。

终止信号

事件范围
session_closedsession 主动关闭或确认的 workspace runtime stop
session_diedchild 异常退出、其他 kill 路径或 daemon shutdown
client_evicted仅当前慢 subscriber 被关闭,session 可继续
stream_error当前订阅建立或传输失败

确认的 workspace stop 若仍有持久化不确定,会在 session_closed 带 persistenceUnconfirmed:true;客户端不能把所有 closed 都解释为历史已可靠落盘。

创建者断线不误杀附加者

创建请求因 TCP reset 无法交付时,route 可要求 requireZeroAttaches 清理新 session。如果其他客户端已经附加,则先保留 session,并记录 spawnOwnerWantedKill;后续 detach 使附着数归零时再完成延后清理。

同理,detach 与 subscriber 关闭的最终回收要结合剩余引用判断,不应把本客户端离开当作所有参与者都结束。持久归档和删除另见会话存储状态。