session-archive.md 5.2 KB

会话 JSON 保存(F058)

2026-09-17 DMS迁移后,本页仅为历史归档组件契约。API/CLI已停止本地JSON保存,旧文件不删除、不再分析;前端负责DMS逐轮问答保存,后台只读并分析。当前流程见 DMS会话监视。

API 和 CLI 从功能启用后记录新的会话输入及对应回答,每个 thread_id 一份 UTF-8 JSON。同一会话逐轮追加,重启后继续读取原文件并写入,不截断历史或回答;不自动回填旧 Redis 数据。F059已在同一文件接入静默30分钟后的总结和两阶段分析,见 会话分析。未实现后台页面或查询 HTTP 接口。

配置与文件位置

在 .env 配置 SESSION_DIR=session,同名进程环境变量优先;未设置时默认 session,空值报错。目录不存在时自动创建。

  • 相对路径固定相对于项目根目录,不受启动工作目录影响。session 在本机对应 E:\CODE\business-assistant\session。
  • 相对路径支持 data/session、data\session、中文和空格;可用单引号或双引号包裹路径,反斜杠不作转义。
  • Windows 支持 E:\records\session、E:/records/session 和 UNC 路径;Linux 支持 /var/lib/business-assistant/session。
  • 绝对路径必须符合运行系统。Linux 上的 Windows 盘符路径、Windows 上的 Linux 根路径、C:session 等含糊路径会报错;跨系统部署时应配置部署机器实际挂载路径,不自动猜测盘符映射。

文件名为 <thread_id>.json。API支持的普通字母、数字、短横线及下划线ID直接用于文件名;Windows保留名、非安全字符、路径分隔符或实际大小写冲突时,使用 ~SHA256(thread_id).json 避免覆盖或路径穿越。原始ID始终保留在文件内。旧哈希命名文件在下一次保存时自动读取并迁移到新名,保留历史,成功后移除旧文件;未续写的旧文件也可被观察器分析。默认 session/ 已被 Git 忽略,自定义仓库内目录需相应配置忽略规则。会话文件包含完整业务内容,沿用部署目录的访问权限,不输出到终端日志。

JSON 字段

以下为精简合成示例,实际记录还包含请求耗时、输入类别等元数据:

{
  "schema_version": 1,
  "thread_id": "example-window",
  "turns": [
    {
      "request_id": "example-request",
      "thread_id": "example-window",
      "question": "你好",
      "ai_answer": "您好,请问有什么可以帮您?",
      "received_at": "2026-09-17T16:00:00.000+08:00",
      "finished_at": "2026-09-17T16:00:01.000+08:00",
      "status": "completed",
      "error_code": null,
      "events": [
        {"event": "answer", "data": {"text": "您好,请问有什么可以帮您?"}}
      ],
      "result": {
        "response": "您好,请问有什么可以帮您?",
        "recommendation": {},
        "company_info": {},
        "errors": []
      }
    }
  ]
}

turns 按首次保存顺序排列,request_id 用于同次请求的状态更新,不重复追加。question 保留当前输入,包括补问回复和重试命令;CLI 自动恢复产生 input_kind=resume、question=null 的记录,不编造用户问题。

ai_answer 为回答正文、总结和补问/错误提示的便于读取的合并文本,保留 Markdown;events 保留 answer、summary、interrupt、error 的原始有效内容,候选公司和输入帮助可从 interrupt 读取。result 保存完整最终结果(包括卡片、来源和诊断字段),与正文配合查看,不需要把结构化结果重复拼入正文。API 的 result 与现有 SSE 最终快照一致;CLI 保存对应字段。

状态包括 running、completed、needs_input、failed、stopped、incomplete。时间统一为上海时区。未产出回答时 ai_answer 为空、result 为 null;不能把中止或失败当作成功答复。进程突然退出可能留下 running 及部分已生成内容,不能保证尚未生成或未写入的内容可恢复。

保存边界

先保存问题,再随有效回答事件更新,最终文件写入成功后 API 才发送 done。临时文件与目标文件位于同一目录,flush/fsync 后原子替换;失败保留上一个有效 JSON,已有文件损坏时明确失败,不默默清空。存储失败会使请求失败,原始异常和路径不进入用户回答。

沿用 API 的单进程问答部署约定,文件写入与观察器分析提交使用共用的进程内锁及OS文件锁,避免追加问答与分析互相覆盖。文件存储与 Redis 不是跨存储事务,Redis 最终写失败时两侧状态可能不一致,应结合请求错误判断。未接纳请求(例如 422、409、429)不属于已处理会话,不归档。

JSON 无自动过期、删除或容量轮转;Redis 过期及清除检查点不会删除 JSON。后台可直接按文件读取会话及顶层analysis结果和stored_at保存时间,继续提问时旧分析标为stale,再次静默后更新。当前文件验证在 Windows、合成数据和服务替身上完成,未实测 Linux 文件系统或网络共享盘,不代表外部前端验收。重启后端后生效。