Class: OllamaAgent::Runtime::Sandbox

Inherits:
Object
  • Object
show all
Defined in:
lib/ollama_agent/runtime/sandbox.rb

Overview

Workspace sandbox: copies a project to a temp directory for isolated edits. Used by self-improvement and automated modes to prevent live-tree mutations.

Examples:

sandbox = OllamaAgent::Runtime::Sandbox.new(source_root: "/my/project")
sandbox.setup!
# agent runs inside sandbox.root
sandbox.changed_files  # => list of modified files
sandbox.sync_back!(target: "/my/project")  # merge changes
sandbox.teardown!

Constant Summary collapse

IGNORED_DIRS =
%w[.git node_modules vendor .bundle tmp log coverage .ollama_agent].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(source_root:, prefix: "ollama_agent_sandbox") ⇒ Sandbox

Returns a new instance of Sandbox.



23
24
25
26
27
28
# File 'lib/ollama_agent/runtime/sandbox.rb', line 23

def initialize(source_root:, prefix: "ollama_agent_sandbox")
  @source_root = File.expand_path(source_root)
  @prefix      = prefix
  @root        = nil
  @setup_done  = false
end

Instance Attribute Details

#rootObject (readonly)

Returns the value of attribute root.



19
20
21
# File 'lib/ollama_agent/runtime/sandbox.rb', line 19

def root
  @root
end

#source_rootObject (readonly)

Returns the value of attribute source_root.



19
20
21
# File 'lib/ollama_agent/runtime/sandbox.rb', line 19

def source_root
  @source_root
end

Instance Method Details

#changed_filesObject

Returns relative paths of files changed inside the sandbox vs the original.



40
41
42
43
44
45
46
47
48
49
50
# File 'lib/ollama_agent/runtime/sandbox.rb', line 40

def changed_files
  return [] unless @setup_done

  find_files(@root).each_with_object([]) do |abs_path, changed|
    rel       = abs_path.sub("#{@root}/", "")
    orig      = File.join(@source_root, rel)
    changed << rel if !File.exist?(orig) || File.read(abs_path) != File.read(orig)
  rescue StandardError
    next
  end
end

#deleted_filesObject

Files present in source but deleted in sandbox.



53
54
55
56
57
58
59
60
# File 'lib/ollama_agent/runtime/sandbox.rb', line 53

def deleted_files
  return [] unless @setup_done

  find_files(@source_root).each_with_object([]) do |abs_path, deleted|
    rel = abs_path.sub("#{@source_root}/", "")
    deleted << rel unless File.exist?(File.join(@root, rel))
  end
end

#setup!String

Copy source tree to a temp directory.

Returns:

  • (String)

    sandbox root path



32
33
34
35
36
37
# File 'lib/ollama_agent/runtime/sandbox.rb', line 32

def setup!
  @root = Dir.mktmpdir(@prefix)
  copy_tree(@source_root, @root)
  @setup_done = true
  @root
end

#sync_back!(target: nil, only_files: nil) ⇒ Array<String>

Copy changed sandbox files back to target (defaults to source_root).

Parameters:

  • target (String) (defaults to: nil)

    destination directory

  • only_files (Array) (defaults to: nil)

    restrict to specific relative paths

Returns:

  • (Array<String>)

    list of relative paths copied



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/ollama_agent/runtime/sandbox.rb', line 66

def sync_back!(target: nil, only_files: nil)
  raise "Sandbox not set up" unless @setup_done

  dest    = File.expand_path(target || @source_root)
  to_copy = only_files || changed_files

  to_copy.each do |rel|
    src  = File.join(@root, rel)
    dst  = File.join(dest, rel)
    FileUtils.mkdir_p(File.dirname(dst))
    FileUtils.cp(src, dst)
  end

  to_copy
end

#teardown!Object

Remove the temporary directory.



83
84
85
86
87
88
89
# File 'lib/ollama_agent/runtime/sandbox.rb', line 83

def teardown!
  return unless @root && File.directory?(@root)

  FileUtils.rm_rf(@root)
  @root       = nil
  @setup_done = false
end

#useObject

Run a block inside the sandbox, then teardown.



92
93
94
95
96
97
# File 'lib/ollama_agent/runtime/sandbox.rb', line 92

def use
  setup!
  yield self
ensure
  teardown!
end