主人要求「链路流程应该有本地数据,不然每次重载之后页面就没数据了」: - 落盘:迁移 0022_flow_graphs(session_id/turn_id/graph_json/时间戳 + 唯一键 upsert)+ internal/runtime/flowgraph(RecordRound/Graph/Latest/Turns/Turn + 保留期 GC) - 写入:loop.EndRound **每轮一条**(锁外深拷贝后写;失败 WARN 且不打印图内容);只落发布会话白名单(复用 flowSessionAllowed) - 读回:端点加 turnId + source(live/persisted/none) + turns[](最新在前,空为 []);**内存优先、miss 才落盘**(最新一轮永远最新) - 前端:flowGraphs 纳入 persistOptions.partialize(**刷新即刻有图**,version 3→4 + migrate)+ 历史轮选择器 + 诚实文案;顺带收 L1 转交的 flow/NodeDetail.tsx 节点日志倒序 - 新 env 键:FLOW_GRAPH_RETENTION=168h / FLOW_GRAPH_GC_INTERVAL=1h - 变异实测:每 span 一行 / 保留期守卫失效 / partialize 去掉 flowGraphs / 去掉内存优先 / 白名单失效 ⇒ 全部打红 - 3 个禁动面文件的纯追加改动(Flow.tsx 挂选择器、FlowSnapshotHint 纠已成假话的文案、其渲染断言随之更新)由主会话裁定认可 - 登记存疑:图桶持久化无体积上限;useFlowTurns 的 effect 无自动化证据(项目无 jsdom)
42 lines
3.0 KiB
SQL
42 lines
3.0 KiB
SQL
-- 0022_flow_graphs: 链路图的**本地落盘**(design/19 §4 P3「多轮历史回放」;切片 F2)。
|
||
--
|
||
-- 动因(主人 2026-10-05 追加要求):「链路流程应该有本地数据,不然每次重载之后页面
|
||
-- 就没数据了」。F1 的只读快照(契约 v0.71)只修了「后端进程活着时刷新能看到最近一轮」;
|
||
-- 真正的本地数据要**落盘**:后端重启后仍在、能翻前几轮。
|
||
--
|
||
-- 与既有实现在语义上的分工(一句话):
|
||
-- - `loop.FlowPublisher` 的每会话内存图 = **正在跑 / 刚跑完的那一轮**(实时帧的唯一来源);
|
||
-- - 本表 = **每轮一行**的收尾存档(`EndRound` 时落),供「多轮历史回放」按 `turn_id` 取回。
|
||
-- 每轮一行、**不是每 span 一行**:span 级写放大纯属浪费,图本身在收尾时已完整。
|
||
--
|
||
-- 命名口径:表名复数、主键 id、时间戳 created_at/updated_at、索引 idx_{table}_{col}
|
||
-- (援引 AGENTS §10 已登记例外,与既有迁移一致)。时间戳沿用 0001 起的
|
||
-- `strftime('%Y-%m-%dT%H:%M:%fZ','now')`(UTC ISO-8601 毫秒),定宽 ⇒ 字典序比较
|
||
-- 等价于时间序,时间窗 GC 因此能直接吃上 idx_flow_graphs_created_at。
|
||
--
|
||
-- 写入范围只有**发布白名单内的会话**(`cmd/cyrene` 的 `flowSessionAllowed`):发布器
|
||
-- 的 `EndRound` 对白名单外的会话直接返回 ⇒ 从不调用落盘出口,本表因此与「哪些会话能
|
||
-- 产出链路图」同一判据,不存在第二份白名单。隔离渠道会话(群聊/陌生人)绝不入库。
|
||
--
|
||
-- 脱敏:`graph_json` 是 `trace.FlowGraph` 的 JSON,节点 `props`/`log` 出图前已按
|
||
-- design/19 §1.1 清洗(args 白名单 + trace.RedactText 的凭据形状清洗),label 也经
|
||
-- RedactText —— 因此本列**不会**承载原始凭据。图里可能含用户输入文本 ⇒ 日志侧一律
|
||
-- 不打印图内容(只在写入失败时记 session/turn 标识)。
|
||
|
||
CREATE TABLE IF NOT EXISTS flow_graphs (
|
||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
session_id TEXT NOT NULL, -- 归属会话(web / web:<uuid> / sess-backthink)
|
||
turn_id TEXT NOT NULL, -- 轮次标识 = trace.FlowGraph.ID("<session>-<round>")
|
||
graph_json TEXT NOT NULL, -- 该轮的整张图(trace.FlowGraph 的 JSON)
|
||
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')),
|
||
updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now'))
|
||
);
|
||
|
||
-- 唯一键承载 upsert(`ON CONFLICT(session_id, turn_id) DO UPDATE`):同一会话同一轮
|
||
-- 二次收尾(重放/重试)是同轮覆盖,而不是插出两行「同一轮」。
|
||
CREATE UNIQUE INDEX IF NOT EXISTS idx_flow_graphs_session_id_turn_id
|
||
ON flow_graphs (session_id, turn_id);
|
||
|
||
-- 保留期清扫(Sweep)的**唯一依赖**:按 created_at 删过期行。
|
||
CREATE INDEX IF NOT EXISTS idx_flow_graphs_created_at ON flow_graphs (created_at);
|