会话机制概述
PinableAgents 的会话管理系统是保障长时间任务可靠执行的核心基础设施。每当用户启动一个任务时,系统会创建一个唯一标识的会话(Session),该会话贯穿任务的整个生命周期,记录执行状态、中间结果和上下文信息。当任务因网络中断、系统重启或其他意外原因被中断时,用户可以通过会话 ID 从中断点恢复执行,而无需从零开始。
会话管理系统解决了 AI 辅助开发中的一个关键痛点:AI 后端的调用通常需要较长时间(数秒到数分钟),且涉及大量上下文信息。如果中途中断,重新传递上下文不仅浪费时间和 API 成本,还可能导致结果不一致。通过会话持久化,PinableAgents 确保了任务执行的连续性和幂等性。
会话系统的设计遵循三个核心原则:持久性(所有状态变更立即写入磁盘)、原子性(状态更新要么完全成功要么完全不变)、可观察性(会话状态可以随时查询和监控)。这三个原则确保了即使在最恶劣的条件下(如进程被杀、磁盘写满),会话数据也不会处于不一致的状态。
会话不仅是容灾机制,更是开发工作流的重要组成部分。通过会话历史,你可以回顾和审计 AI 智能体的每一步决策,理解它为什么做出特定的代码变更。
SESSION_ID 生成与格式
每个会话由一个全局唯一的 SESSION_ID 标识。SESSION_ID 的格式为 sess_{timestamp}_{random},其中 timestamp 是 Unix 时间戳(秒级),random 是一个 8 字符的随机十六进制字符串。例如 sess_1740480000_a3f7b2c1。
这种格式的设计考量是:时间戳前缀使得会话文件按创建时间自然排序,便于管理和清理;随机后缀确保即使在同一秒内创建多个会话也不会冲突。SESSION_ID 在会话创建时生成,之后在整个生命周期中保持不变。
用户也可以通过 --session-id 参数显式指定一个 SESSION_ID。当指定的 ID 已存在时,系统会尝试恢复该会话而不是创建新会话。当指定的 ID 不存在时,系统会以该 ID 创建新会话。自定义 SESSION_ID 在需要跨工具链传递会话引用时特别有用。
# 自动生成 SESSION_ID
codeagent-wrapper --backend claude --task "重构用户模块"
# 输出: Session created: sess_1740480000_a3f7b2c1
# 显式指定 SESSION_ID
codeagent-wrapper --session-id my-refactor-2026 --backend claude --task "重构用户模块"
# 恢复已有会话
codeagent-wrapper --session-id sess_1740480000_a3f7b2c1 --task "继续执行"
会话生命周期
会话的生命周期由四个状态组成,状态之间的转换遵循严格的规则:
created(已创建):会话刚刚创建,尚未开始执行任何任务。这个状态的持续时间通常很短,只存在于初始化到首次执行之间的间隙。
running(执行中):会话正在活跃地执行任务。在此状态下,会话管理器会周期性地创建检查点以记录执行进度。
paused(已暂停):会话因用户主动暂停、网络中断或系统异常而进入暂停状态。暂停状态的会话保留了完整的执行上下文,可以随时恢复到 running 状态继续执行。
completed(已完成):会话的所有任务已执行完毕。已完成的会话保留用于审计和历史查询,但不能恢复执行。
会话状态转换图:
created -------> running -------> completed
| ^
| |
v |
paused
合法的状态转换:
created -> running (开始执行)
running -> paused (中断/暂停)
running -> completed (正常完成)
paused -> running (恢复执行)
非法的状态转换:
completed -> 任何状态 (已完成的会话不可更改)
paused -> completed (必须先恢复再完成)
created -> completed (不能跳过执行)
状态持久化机制
会话状态以 JSON 格式持久化到本地文件系统。默认的存储目录为 ~/.pinable-agents/sessions/,每个会话对应一个 JSON 文件,文件名为 {session_id}.json。以下是一个完整的会话状态文件示例:
{
"id": "sess_1740480000_a3f7b2c1",
"status": "paused",
"backend": "claude",
"model": "claude-opus-4-6",
"task": "将用户模块从单体架构重构为微服务架构",
"task_hash": "sha256:e3b0c44298fc1c149afbf4c8996fb924",
"files": [
"src/user/service.go",
"src/user/repository.go",
"src/user/handler.go",
"src/user/model.go"
],
"created_at": "2026-02-25T10:00:00Z",
"updated_at": "2026-02-25T10:05:32Z",
"workflow": "do",
"current_phase": "implementation",
"phases_completed": ["analysis"],
"checkpoints": [
{
"index": 0,
"timestamp": "2026-02-25T10:01:15Z",
"phase": "analysis",
"description": "完成代码分析,识别出 4 个需要修改的文件",
"files_changed": [],
"tokens_used": { "input": 12500, "output": 3200 }
},
{
"index": 1,
"timestamp": "2026-02-25T10:03:45Z",
"phase": "implementation",
"description": "完成 service.go 的重构",
"files_changed": ["src/user/service.go"],
"tokens_used": { "input": 18300, "output": 5100 }
}
],
"context": {
"conversation_history": [...],
"accumulated_changes": [...],
"working_branch": "refactor/user-microservice"
},
"cost": {
"total_tokens": 39100,
"estimated_cost_usd": 0.58
},
"metadata": {
"git_branch": "main",
"git_commit": "a7e37ab",
"working_dir": "/Users/dev/my-project",
"os": "darwin",
"wrapper_version": "1.3.0"
}
}
状态文件的写入采用"写入临时文件然后原子重命名"的策略,确保即使在写入过程中发生崩溃,原有的状态文件也不会被损坏。具体实现是:先将新状态写入 {session_id}.json.tmp,确认写入完成后通过 os.Rename() 原子性地替换原文件。
检查点创建与恢复
检查点(Checkpoint)是会话恢复的核心机制。每当任务执行完成一个有意义的阶段时,系统会自动创建一个检查点,记录当前的执行状态和已产生的结果。恢复执行时,系统从最近的检查点开始,而不是从头开始。
检查点的创建时机包括:工作流的每个阶段完成时(如分析完成、实现完成)、每次成功的文件修改后、长时间执行中的周期性保存(默认每 2 分钟一次)、以及用户主动触发保存时。每个检查点记录以下信息:检查点序号、时间戳、当前阶段、阶段描述、已修改的文件列表和累计 token 用量。
# 手动创建检查点
pinable-agents session checkpoint sess_1740480000_a3f7b2c1 \
--description "完成数据库迁移脚本"
# 查看会话的所有检查点
pinable-agents session checkpoints sess_1740480000_a3f7b2c1
# 从指定检查点恢复(而非最近的检查点)
codeagent-wrapper --session-id sess_1740480000_a3f7b2c1 \
--restore-checkpoint 1 \
--task "从 checkpoint 1 重新开始实现"
检查点不是完整的快照,而是增量记录。每个检查点只记录自上一个检查点以来的变更。恢复时,系统会从第一个检查点开始,依次重放所有检查点的状态,直到到达目标检查点。
会话元数据
会话元数据记录了与任务执行环境相关的非业务信息,用于审计、调试和报告。元数据在会话创建时自动采集,不会在执行过程中更新。关键的元数据字段包括:
| 字段 | 类型 | 说明 |
|---|---|---|
git_branch |
string | 会话创建时的 Git 分支名 |
git_commit |
string | 会话创建时的 Git commit SHA(前 7 位) |
working_dir |
string | 任务执行的工作目录绝对路径 |
os |
string | 操作系统标识(darwin/linux/windows) |
wrapper_version |
string | codeagent-wrapper 的版本号 |
task_hash |
string | 任务描述的 SHA-256 哈希值 |
start_time |
datetime | 会话开始执行的 ISO 8601 时间戳 |
backend |
string | 使用的 AI 后端标识 |
model |
string | 使用的具体模型标识 |
task_hash 字段用于检测任务是否被修改。如果用户在恢复会话时提供了与原始任务不同的任务描述,系统会发出警告,因为修改任务描述可能导致恢复后的执行结果与之前的检查点不一致。
跨会话上下文共享
在某些场景中,不同的会话之间需要共享上下文信息。例如,一个会话完成了需求分析,后续的实现会话需要引用分析结果。PinableAgents 提供了两种跨会话上下文共享机制:
显式引用:通过 --context-from 参数指定要引用的会话 ID。系统会从被引用的会话中提取关键上下文(如分析结论、架构决策、已完成的变更列表),并注入到当前会话的初始上下文中。
# 会话 A:完成需求分析
codeagent-wrapper --backend claude --task "分析用户管理模块的重构需求"
# 输出: Session completed: sess_analysis_001
# 会话 B:基于分析结果进行实现(引用会话 A 的上下文)
codeagent-wrapper --backend claude --task "实现用户管理模块的重构" \
--context-from sess_analysis_001
会话链:多个会话可以组成一个有序的会话链。会话链中的每个会话自动继承前一个会话的完成上下文。这适合将大型任务拆分为多个阶段,每个阶段使用独立的会话管理。
# 创建会话链
pinable-agents session chain create my-refactor \
--sessions "sess_analysis,sess_design,sess_impl,sess_review"
# 查看会话链状态
pinable-agents session chain status my-refactor
# 输出:
# Chain: my-refactor
# [1] sess_analysis COMPLETED (2026-02-25 10:00)
# [2] sess_design COMPLETED (2026-02-25 11:30)
# [3] sess_impl RUNNING (2026-02-25 14:00)
# [4] sess_review PENDING (waiting for sess_impl)
崩溃恢复策略
当任务执行过程中发生意外中断(进程被杀、网络断开、系统重启),会话管理器提供了完善的恢复机制。恢复策略基于最后一个成功的检查点,具体步骤如下:
状态检测
系统启动时会扫描 sessions 目录,找出所有状态为 running 的会话。由于正常结束的会话状态会更新为 completed,处于 running 状态的会话意味着非正常退出。
完整性检查
对找到的异常会话进行完整性验证。检查会话文件是否完整(JSON 可解析)、检查点链是否连续(没有缺失的检查点)、引用的文件是否仍然存在。
状态修复
将异常会话的状态更新为 paused,使其可以被正常恢复。如果会话文件损坏,尝试从 .tmp 临时文件恢复。如果两者都不可用,标记会话为 corrupted 并生成诊断报告。
恢复执行
用户使用 --session-id 参数恢复会话。系统加载最后一个完整的检查点,重建执行上下文,然后从中断点继续执行。
# 自动检测并列出可恢复的会话
pinable-agents session recover --scan
# 输出示例:
# Found 2 recoverable sessions:
# sess_1740480000_a3f7b2c1 paused "重构用户模块" checkpoint 2/4
# sess_1740490000_d2e8f1a0 paused "添加搜索功能" checkpoint 1/3
# 恢复指定会话
pinable-agents session recover sess_1740480000_a3f7b2c1
# 自动恢复所有可恢复的会话(按优先级依次执行)
pinable-agents session recover --all
崩溃恢复不是完美无缝的。如果中断发生在 AI 后端返回响应之后、但文件修改应用之前,恢复后可能会重复执行一次已完成的操作。codeagent-wrapper 通过检查文件的内容哈希值来检测这种情况,避免重复修改。
会话清理与归档
随着时间的推移,sessions 目录中会积累大量的历史会话文件。PinableAgents 提供自动和手动两种清理机制:
自动清理:通过配置 session.auto_cleanup_days 参数,系统会在每次启动时自动删除超过指定天数的已完成会话。默认值为 30 天。
手动清理:用户可以通过 CLI 命令手动删除、归档或导出会话数据。归档功能会将会话文件压缩存储到归档目录,释放磁盘空间的同时保留历史记录。
# 查看会话占用的磁盘空间
pinable-agents session stats
# 输出:
# Total sessions: 156
# Active: 2, Paused: 3, Completed: 148, Corrupted: 3
# Disk usage: 23.4 MB
# Oldest session: 2026-01-15
# 清理 30 天前的已完成会话
pinable-agents session cleanup --older-than 30d
# 归档而不删除
pinable-agents session archive --older-than 14d --output ./session-archive/
# 删除指定会话
pinable-agents session delete sess_1740480000_a3f7b2c1
# 批量删除已完成的会话
pinable-agents session cleanup --status completed --older-than 7d
CLI 会话管理命令
PinableAgents 提供了一套完整的 CLI 命令用于会话管理。以下是所有可用命令的概览:
| 命令 | 说明 | 示例 |
|---|---|---|
session list |
列出所有会话 | pinable-agents session list |
session inspect |
查看会话详细信息 | pinable-agents session inspect {id} |
session checkpoints |
列出会话的所有检查点 | pinable-agents session checkpoints {id} |
session recover |
恢复中断的会话 | pinable-agents session recover {id} |
session pause |
暂停正在执行的会话 | pinable-agents session pause {id} |
session delete |
删除指定会话 | pinable-agents session delete {id} |
session cleanup |
批量清理历史会话 | pinable-agents session cleanup --older-than 30d |
session archive |
归档会话到压缩文件 | pinable-agents session archive --output ./ |
session export |
导出会话数据为报告 | pinable-agents session export {id} --format md |
session stats |
显示会话统计信息 | pinable-agents session stats |
# 列出会话(支持过滤和排序)
pinable-agents session list --status paused --sort created_at
pinable-agents session list --backend claude --limit 10
# 查看会话详情(包含检查点和元数据)
pinable-agents session inspect sess_1740480000_a3f7b2c1 --verbose
# 导出会话为 Markdown 报告
pinable-agents session export sess_1740480000_a3f7b2c1 --format markdown > report.md
# 导出会话为 JSON(供程序化处理)
pinable-agents session export sess_1740480000_a3f7b2c1 --format json | jq '.checkpoints'
实战示例:恢复多文件重构
以下是一个完整的实战场景,展示如何在网络故障后恢复一个涉及多个文件的重构任务:
# 步骤 1: 启动多文件重构任务
$ codeagent-wrapper --backend claude \
--task "将用户、订单、支付三个模块的数据库访问从直接 SQL 重构为 Repository 模式" \
--files "src/user/db.go,src/order/db.go,src/payment/db.go"
Session created: sess_1740480000_a3f7b2c1
[Phase: analysis] Analyzing 3 files...
[Phase: analysis] DONE - Identified 15 functions to refactor
[Checkpoint 0] Saved analysis results
[Phase: implementation] Refactoring src/user/db.go...
[Phase: implementation] DONE - Created src/user/repository.go
[Checkpoint 1] Saved user module changes
[Phase: implementation] Refactoring src/order/db.go...
CONNECTION ERROR: network timeout after 30s
Session paused: sess_1740480000_a3f7b2c1 (checkpoint 1)
# --- 网络中断,进程退出 ---
# 步骤 2: 网络恢复后,查看可恢复的会话
$ pinable-agents session recover --scan
Found 1 recoverable session:
sess_1740480000_a3f7b2c1 paused "重构为 Repository 模式" checkpoint 1/3
# 步骤 3: 查看会话详情,确认恢复点
$ pinable-agents session inspect sess_1740480000_a3f7b2c1
ID: sess_1740480000_a3f7b2c1
Status: paused
Backend: claude (claude-opus-4-6)
Task: 将用户、订单、支付三个模块的数据库访问从直接 SQL 重构为 Repository 模式
Created: 2026-02-25 10:00:00
Paused: 2026-02-25 10:05:32
Checkpoints:
[0] 10:01:15 analysis "完成代码分析,识别出 15 个函数"
[1] 10:03:45 implementation "完成 user 模块重构"
Files changed so far:
+ src/user/repository.go (new)
~ src/user/db.go (modified)
Remaining work:
- src/order/db.go (not started)
- src/payment/db.go (not started)
# 步骤 4: 从检查点 1 恢复执行
$ codeagent-wrapper --session-id sess_1740480000_a3f7b2c1
Resuming from checkpoint 1 (user module completed)
[Phase: implementation] Refactoring src/order/db.go...
[Phase: implementation] DONE - Created src/order/repository.go
[Checkpoint 2] Saved order module changes
[Phase: implementation] Refactoring src/payment/db.go...
[Phase: implementation] DONE - Created src/payment/repository.go
[Checkpoint 3] Saved payment module changes
[Phase: review] Running code review...
[Phase: review] DONE - No critical issues found
Session completed: sess_1740480000_a3f7b2c1
Total time: 12m 34s (excluding 2h pause)
Total cost: $0.87
Files created: 3, Files modified: 3
在这个示例中,虽然网络中断导致任务在第二个文件的处理过程中被中断,但由于 checkpoint 1 已经保存了第一个文件的完整重构结果,恢复后系统直接从第二个文件开始,完全避免了重复工作。这种能力在处理大型重构任务时尤为重要,因为这类任务通常需要十几分钟甚至更长时间,中断的概率较高。