Module: SwarmSDK::Tools::Stores::ReadTracker

Defined in:
lib/swarm_sdk/tools/stores/read_tracker.rb

Overview

ReadTracker manages read-file tracking for all agents with content digest verification

This module maintains a global registry of which files each agent has read during their conversation along with SHA256 digests of the content. This enables enforcement of the "read-before-write" and "read-before-edit" rules that ensure agents have context before modifying files, AND prevents editing files that have changed externally since being read.

Each agent maintains an independent map of read files to content digests.

Class Method Summary collapse

Class Method Details

.clear(agent_id) ⇒ Object

Clear read history for an agent (useful for testing)

Parameters:

  • agent_id (Symbol)

    The agent identifier



80
81
82
83
84
# File 'lib/swarm_sdk/tools/stores/read_tracker.rb', line 80

def clear(agent_id)
  @mutex.synchronize do
    @read_files.delete(agent_id)
  end
end

.clear_allObject

Clear all read history (useful for testing)



87
88
89
90
91
# File 'lib/swarm_sdk/tools/stores/read_tracker.rb', line 87

def clear_all
  @mutex.synchronize do
    @read_files.clear
  end
end

.file_read?(agent_id, file_path) ⇒ Boolean

Check if an agent has read a file AND content hasn't changed

Parameters:

  • agent_id (Symbol)

    The agent identifier

  • file_path (String)

    The absolute path to the file

Returns:

  • (Boolean)

    true if agent read file and content matches



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/swarm_sdk/tools/stores/read_tracker.rb', line 40

def file_read?(agent_id, file_path)
  @mutex.synchronize do
    return false unless @read_files[agent_id]

    expanded_path = File.expand_path(file_path)
    stored_digest = @read_files[agent_id][expanded_path]
    return false unless stored_digest

    # Check if file still exists and matches stored digest
    return false unless File.exist?(expanded_path)

    current_digest = Digest::SHA256.hexdigest(File.read(expanded_path))
    current_digest == stored_digest
  end
end

.get_read_files(agent_id) ⇒ Hash

Get all read files with digests for snapshot

Parameters:

  • agent_id (Symbol)

    The agent identifier

Returns:

  • (Hash)

    { file_path => digest }



60
61
62
63
64
# File 'lib/swarm_sdk/tools/stores/read_tracker.rb', line 60

def get_read_files(agent_id)
  @mutex.synchronize do
    @read_files[agent_id]&.dup || {}
  end
end

.register_read(agent_id, file_path, content) ⇒ String

Register that an agent has read a file with content digest

Parameters:

  • agent_id (Symbol)

    The agent identifier

  • file_path (String)

    The absolute path to the file

  • content (String)

    File content (for digest calculation)

Returns:

  • (String)

    The calculated SHA256 digest



26
27
28
29
30
31
32
33
# File 'lib/swarm_sdk/tools/stores/read_tracker.rb', line 26

def register_read(agent_id, file_path, content)
  @mutex.synchronize do
    @read_files[agent_id] ||= {}
    digest = Digest::SHA256.hexdigest(content)
    @read_files[agent_id][File.expand_path(file_path)] = digest
    digest
  end
end

.restore_read_files(agent_id, files_with_digests) ⇒ void

This method returns an undefined value.

Restore read files with digests from snapshot

Parameters:

  • agent_id (Symbol)

    The agent identifier

  • files_with_digests (Hash)

    { file_path => digest }



71
72
73
74
75
# File 'lib/swarm_sdk/tools/stores/read_tracker.rb', line 71

def restore_read_files(agent_id, files_with_digests)
  @mutex.synchronize do
    @read_files[agent_id] = files_with_digests.dup
  end
end