Session 管理

wesgine 会话系统:创建、归属、消息持久化、快照分支与 Actor 边界。


会话 API

基础操作

方法路径说明
GET/sessions列出会话
GET/sessions/{sid}/messages消息列表(?before=&limit=)
DELETE/sessions/{sid}删除会话
PATCH/sessions/{sid}更新元数据(title)
POST/sessions/{sid}/interrupt中断当前 Run

批量操作

方法路径说明权限
POST/sessions/mark-interrupted崩溃后批量标记admin token
POST/sessions/interrupt-all中断 Cell 内所有 Runadmin token
DELETE/sessions/delete-by-prefix按前缀批量删除admin token

Checkpoint / Branch

Checkpoint 操作

方法路径说明
GET/sessions/{sid}/checkpoints快照列表
POST/sessions/{sid}/checkpoints创建快照
POST/sessions/{sid}/checkpoints/{cpid}/restore回滚
POST/sessions/{sid}/checkpoints/{cpid}/fork分支
DELETE/sessions/{sid}/checkpoints/{cpid}删除快照

Branch 操作

方法路径说明
GET/sessions/{sid}/branches分支列表
DELETE/sessions/{sid}/branches/{bid}删除分支

Actor 边界(INV-SESS-01~03)

Session 是同一条 Actor 边界的第二个面。

归属

actor 是 wes_sessions 表的独立列(非 Tags["actor"])。

三条不变量

不变量说明
INV-SESS-01变更的授权面是 cell:chat 不是 cell:read
INV-SESS-02归属只有一个执行点 SessionHandle.AssertActor
INV-SESS-03checkpoint/branch 行身份是 (session_id, id)

INV-SESS-02 详解

归属门开在路由漏斗 dispatchCellSessionByID:

/sessions/{sid}/*
    ↓ dispatchCellSessionByID
    ↓ AssertActor(单点)
    ↓ 各 handler

在漏斗上判据使"新增子路由忘了检查"不可表达。

INV-SESS-03 详解

SQL 必须带 session_id:

WHERE id = ? AND session_id = ?

否则 DELETE /sessions/我的/checkpoints/受害者的 会通过一个回答正确的门然后删掉别人的行。

删除幂等

跨 session 删除幂等成功——区分"不存在"与"不是你的"是存在性预言机。

只有 Restore / Fork 硬失败(ErrCheckpointNotInSession → 404)。


消息持久化

INV-PERSIST-01:stripInlineImages

wes_messages 不允许 base64 载荷进入 DB:

onRunStart(user 消息)
onTurnEnd(assistant 回复)    → stripInlineImages()
onToolResult(tool 结果)

imageSaveDir 存在时解码存盘并改写为 file_ref 磁盘路径。

INV-PERSIST-02:空消息过滤

assistant 且全部 ContentBlock 为空文本 → (false, nil) 不写入。

Tracer 仅在 inserted==true 时调用 IncrementMessageCount。

INV-PERSIST-04:FTS5 同步

trigger 必须覆盖 INSERT / UPDATE / DELETE 三种操作。


Boot 自动恢复

INV-CKPT-04:Cell boot 自动执行:

MarkInterruptedSessions()
    ↓
ListOrphanedRuns() → MarkRunTerminated()

消费方不必在 PostBoot 调用 MarkInterrupted。


相关文档