Class: Brute::Middleware::Checkpoint
- Inherits:
-
Object
- Object
- Brute::Middleware::Checkpoint
- Defined in:
- lib/brute/middleware/008_checkpoint.rb
Overview
Durable execution for the tool loop. Where SessionLog persists the conversation once per turn (outermost), Checkpoint snapshots it after every pass through the inner stack — one checkpoint per LLM call + tool execution. Place it just inside Loop::ToolResult:
use Brute::Middleware::Loop::ToolResult
use Brute::Middleware::Checkpoint, path: "tmp/checkpoints.jsonl"
use Brute::Middleware::MaxIterations
use Brute::Middleware::ToolPipeline, tools: Brute::Tools::ALL
The store is just a JSONL log of snapshots — one line per checkpoint, each carrying the full message log plus its own id and the id of the parent checkpoint it grew from. That append-only chain buys three things:
resume pass resume: :latest — a crash mid-turn costs at most
one iteration instead of the whole turn
time travel pass resume: "<checkpoint id>" — restart from any
snapshot in the chain
forking checkpoints written after a time-travel resume carry the
resumed id as parent_id, branching the chain in place
System messages are not persisted (SystemPrompt re-adds them each turn); restored history is inserted after any leading system message and before the current turn's input.
Class Method Summary collapse
-
.list(path) ⇒ Object
Parsed checkpoint records (symbol keys, messages as plain hashes), oldest first.
Instance Method Summary collapse
- #call(env) ⇒ Object
-
#initialize(app, path:, resume: nil) ⇒ Checkpoint
constructor
A new instance of Checkpoint.
Constructor Details
#initialize(app, path:, resume: nil) ⇒ Checkpoint
Returns a new instance of Checkpoint.
37 38 39 40 41 |
# File 'lib/brute/middleware/008_checkpoint.rb', line 37 def initialize(app, path:, resume: nil) @app = app @path = path @resume = resume end |
Class Method Details
.list(path) ⇒ Object
Parsed checkpoint records (symbol keys, messages as plain hashes), oldest first.
52 53 54 55 56 57 58 59 |
# File 'lib/brute/middleware/008_checkpoint.rb', line 52 def self.list(path) return [] unless path && File.exist?(path) File.foreach(path).filter_map do |line| line = line.strip JSON.parse(line, symbolize_names: true) unless line.empty? end end |
Instance Method Details
#call(env) ⇒ Object
43 44 45 46 47 48 |
# File 'lib/brute/middleware/008_checkpoint.rb', line 43 def call(env) restore(env) unless env[:metadata][:checkpoint] @app.call(env) persist(env) env end |