Class: RubynCode::Checkpoint::Manager
- Inherits:
-
Object
- Object
- RubynCode::Checkpoint::Manager
- Defined in:
- lib/rubyn_code/checkpoint/manager.rb
Constant Summary collapse
- MAX_CHECKPOINTS =
30
Instance Method Summary collapse
-
#checkpoint!(label:, conversation:) ⇒ Integer
Open a new checkpoint for a user turn.
- #empty? ⇒ Boolean
-
#initialize(project_root:) ⇒ Manager
constructor
A new instance of Manager.
- #latest_id ⇒ Object
-
#list ⇒ Array<Hash>
label:, files: newest last.
-
#record_file(path) ⇒ void
Record a file’s original contents before it is mutated (once per checkpoint per path).
-
#restore(id, conversation, scope: :both) ⇒ Hash?
Restore a checkpoint.
Constructor Details
#initialize(project_root:) ⇒ Manager
Returns a new instance of Manager.
23 24 25 26 27 28 |
# File 'lib/rubyn_code/checkpoint/manager.rb', line 23 def initialize(project_root:) @project_root = project_root @checkpoints = [] @seq = 0 @current = nil end |
Instance Method Details
#checkpoint!(label:, conversation:) ⇒ Integer
Open a new checkpoint for a user turn. Captures the conversation as it stands before the agent acts.
36 37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/rubyn_code/checkpoint/manager.rb', line 36 def checkpoint!(label:, conversation:) @seq += 1 @current = { id: @seq, label: summarize(label), messages: Array(conversation.).dup, files: {} } @checkpoints << @current @checkpoints.shift while @checkpoints.size > MAX_CHECKPOINTS @seq end |
#empty? ⇒ Boolean
70 |
# File 'lib/rubyn_code/checkpoint/manager.rb', line 70 def empty? = @checkpoints.empty? |
#latest_id ⇒ Object
72 |
# File 'lib/rubyn_code/checkpoint/manager.rb', line 72 def latest_id = @checkpoints.last&.fetch(:id) |
#list ⇒ Array<Hash>
Returns label:, files: newest last.
66 67 68 |
# File 'lib/rubyn_code/checkpoint/manager.rb', line 66 def list @checkpoints.map { |c| { id: c[:id], label: c[:label], files: c[:files].size } } end |
#record_file(path) ⇒ void
This method returns an undefined value.
Record a file’s original contents before it is mutated (once per checkpoint per path). No-op when no checkpoint is open.
54 55 56 57 58 59 60 61 62 63 |
# File 'lib/rubyn_code/checkpoint/manager.rb', line 54 def record_file(path) return unless @current && path abs = File.(path.to_s, @project_root) return if @current[:files].key?(abs) @current[:files][abs] = File.file?(abs) ? File.read(abs) : ABSENT rescue StandardError => e RubynCode::Debug.warn("Checkpoint capture failed for #{path}: #{e.}") end |
#restore(id, conversation, scope: :both) ⇒ Hash?
Restore a checkpoint. Scope :both (default), :code, or :chat. Checkpoints newer than the restored one are discarded.
78 79 80 81 82 83 84 85 86 87 88 |
# File 'lib/rubyn_code/checkpoint/manager.rb', line 78 def restore(id, conversation, scope: :both) checkpoint = @checkpoints.find { |c| c[:id] == id } return nil unless checkpoint restored_files = restore_files(checkpoint) if %i[both code].include?(scope) conversation.replace!(checkpoint[:messages].dup) if %i[both chat].include?(scope) @checkpoints.reject! { |c| c[:id] > id } @current = nil { id: id, files_restored: restored_files || 0 } end |