跨会话连接与消息帧
建立私有 socket 连接,区分普通 peer、自身进程和 controller 的认证。
连接目标必须取自注册记录的 ipcPath,不要根据 PID 自行拼出 socket 路径。记录格式与身份检查见注册与寻址。
inbox 与连接生命周期
监听端依次尝试 XDG_RUNTIME_DIR 下的 qwen-socks、TMPDIR 下带私有哈希的 qwen-socks 目录,再回退到 /tmp。目录权限 0700、socket 为 0600;超过 103 字节的路径跳过。PID 同名地址已有活跃监听者时,选择相邻的随机后缀地址。
协议使用 UTF-8、逐行 JSON。单行超过文档所称 1 MiB 的限制会断开;实际计量是 UTF-16 code units,不能当 UTF-8 网络字节数。30 秒内没有完成一行可解析 JSON 也会断开,垃圾行不会刷新截止时间;最多同时 64 个连接。
预期每连接发一条消息:连接后在一次写入中发送认证行和消息帧,半关闭写端,等对端关闭。接收方不在原连接上回写;回执通过新连接发到发送者自己的 inbox。
认证行
目标有 ipcToken 时,第一行必须是:
{ "msgV": 1, "type": "auth", "token": "<target-token>" }令牌不匹配或首行不是认证行会被静默断开。旧记录没有 ipcToken 时可不发送认证行;旧 inbox 会忽略不认识的 auth 帧。
| 令牌来源 | 接收端识别 | 默认策略 |
|---|---|---|
| 目标记录的 ipcToken | 普通 peer | 按入站策略和 review class 判断 |
| 目标环境的 QWEN_CODE_MESSAGING_TOKEN | 该会话启动的进程 | 未覆盖策略时默认接纳,origin 为 own-process |
| 用户通过 qwen sessions controllers add 创建的 qpc_ 令牌 | 用户授权的 controller | 未覆盖策略时默认接纳,origin 为 controller |
controller 令牌形式为 qpc_ 后接 64 个十六进制字符,标签来自用户创建的授权。连接认证说明持有相应能力,不证明具体是谁打开连接。from、fromName、fromMode 以及注册信息仍是声明,不能通过把 kind 写成 external 或冒用名称获得 controller 身份。
用户消息帧
下例中的地址、ID 和令牌均需替换为实际注册信息。from 与 replyToken 指发送者自己的端点和令牌,认证行则使用目标的令牌。
{
"msgV": 1,
"msgId": "5f1d0c9e-3b2a-4e8f-9c7d-1a2b3c4d5e6f",
"type": "user",
"from": "/run/user/1000/qwen-socks/40011.sock",
"replyToken": "<sender-token>",
"fromName": "build-watcher",
"fromMode": "prompting",
"toSessionId": "8e016be8-5b48-4c13-ad22-1f5326ae64ac",
"priority": "next",
"message": { "role": "user", "content": "Build finished with no failures." }
}msgV 是数字,当前高于 1 的帧会丢弃。msgId 必须符合 ^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$,移除连字符并小写后不能等于 all;每条新消息用新 UUID,重发同一条则保留其 ID 供接收端返回既有裁决。
message.role 必须为 user,content 为非空字符串。fromName 展示前压为单行,最多 200 字符。fromMode 可为 prompting 或 bypass,缺失代表不声明 review class,普通 peer 默认等待审核。
priority 接受 now、next,其他值按 next;当前两者都排到下一轮,没有立即中断路径。未知字段忽略,越界输入按读取端规则丢弃,不应依赖返回结构化验证错误。
未提供 from 就收不到回执;仅发送消息的程序也应绑定 inbox 并提供 replyToken。回执字段、状态转换和限流见投递与接收策略。