Class: Brute::Middleware::Checkpoint

Inherits:
Object
  • Object
show all
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

Instance Method Summary collapse

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