swarm_sdk 2.0.3 → 2.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/lib/swarm_sdk/agent/builder.rb +41 -0
  3. data/lib/swarm_sdk/agent/chat/logging_helpers.rb +22 -5
  4. data/lib/swarm_sdk/agent/definition.rb +52 -6
  5. data/lib/swarm_sdk/configuration.rb +3 -1
  6. data/lib/swarm_sdk/prompts/memory.md.erb +480 -0
  7. data/lib/swarm_sdk/swarm/agent_initializer.rb +16 -3
  8. data/lib/swarm_sdk/swarm/builder.rb +9 -1
  9. data/lib/swarm_sdk/swarm/tool_configurator.rb +73 -23
  10. data/lib/swarm_sdk/swarm.rb +51 -7
  11. data/lib/swarm_sdk/tools/document_converters/html_converter.rb +101 -0
  12. data/lib/swarm_sdk/tools/memory/memory_delete.rb +64 -0
  13. data/lib/swarm_sdk/tools/memory/memory_edit.rb +145 -0
  14. data/lib/swarm_sdk/tools/memory/memory_glob.rb +94 -0
  15. data/lib/swarm_sdk/tools/memory/memory_grep.rb +147 -0
  16. data/lib/swarm_sdk/tools/memory/memory_multi_edit.rb +228 -0
  17. data/lib/swarm_sdk/tools/memory/memory_read.rb +82 -0
  18. data/lib/swarm_sdk/tools/memory/memory_write.rb +90 -0
  19. data/lib/swarm_sdk/tools/registry.rb +11 -3
  20. data/lib/swarm_sdk/tools/scratchpad/scratchpad_list.rb +96 -0
  21. data/lib/swarm_sdk/tools/scratchpad/scratchpad_read.rb +76 -0
  22. data/lib/swarm_sdk/tools/scratchpad/scratchpad_write.rb +91 -0
  23. data/lib/swarm_sdk/tools/stores/memory_storage.rb +300 -0
  24. data/lib/swarm_sdk/tools/stores/scratchpad_storage.rb +224 -0
  25. data/lib/swarm_sdk/tools/stores/storage.rb +148 -0
  26. data/lib/swarm_sdk/tools/stores/storage_read_tracker.rb +61 -0
  27. data/lib/swarm_sdk/tools/web_fetch.rb +261 -0
  28. data/lib/swarm_sdk/version.rb +1 -1
  29. data/lib/swarm_sdk.rb +39 -0
  30. metadata +18 -5
  31. data/lib/swarm_sdk/tools/scratchpad_list.rb +0 -88
  32. data/lib/swarm_sdk/tools/scratchpad_read.rb +0 -59
  33. data/lib/swarm_sdk/tools/scratchpad_write.rb +0 -88
  34. data/lib/swarm_sdk/tools/stores/scratchpad.rb +0 -153
@@ -1,153 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module SwarmSDK
4
- module Tools
5
- module Stores
6
- # Scratchpad provides session-scoped, in-memory storage for agents
7
- # to store detailed outputs that would otherwise bloat tool responses.
8
- #
9
- # Features:
10
- # - Session-scoped: Cleared when swarm execution completes
11
- # - Shared: Any agent can read/write any scratchpad address
12
- # - Path-based: Hierarchical organization using file-path-like addresses
13
- # - In-memory: No filesystem I/O, pure memory storage
14
- # - Metadata-rich: Stores content + title + timestamp + size
15
- class Scratchpad
16
- # Maximum size per scratchpad entry (1MB)
17
- MAX_ENTRY_SIZE = 1_000_000
18
-
19
- # Maximum total scratchpad size (100MB)
20
- MAX_TOTAL_SIZE = 100_000_000
21
-
22
- # Represents a single scratchpad entry with metadata
23
- Entry = Struct.new(:content, :title, :created_at, :size, keyword_init: true)
24
-
25
- def initialize
26
- @entries = {}
27
- @total_size = 0
28
- end
29
-
30
- # Write content to scratchpad
31
- #
32
- # @param file_path [String] Path to store content
33
- # @param content [String] Content to store
34
- # @param title [String] Brief title describing the content
35
- # @raise [ArgumentError] If size limits are exceeded
36
- # @return [Entry] The created entry
37
- def write(file_path:, content:, title:)
38
- raise ArgumentError, "file_path is required" if file_path.nil? || file_path.to_s.strip.empty?
39
- raise ArgumentError, "content is required" if content.nil?
40
- raise ArgumentError, "title is required" if title.nil? || title.to_s.strip.empty?
41
-
42
- content_size = content.bytesize
43
-
44
- # Check entry size limit
45
- if content_size > MAX_ENTRY_SIZE
46
- raise ArgumentError, "Content exceeds maximum size (#{format_bytes(MAX_ENTRY_SIZE)}). " \
47
- "Current: #{format_bytes(content_size)}"
48
- end
49
-
50
- # Calculate new total size
51
- existing_entry = @entries[file_path]
52
- existing_size = existing_entry ? existing_entry.size : 0
53
- new_total_size = @total_size - existing_size + content_size
54
-
55
- # Check total size limit
56
- if new_total_size > MAX_TOTAL_SIZE
57
- raise ArgumentError, "Scratchpad full (#{format_bytes(MAX_TOTAL_SIZE)} limit). " \
58
- "Current: #{format_bytes(@total_size)}, " \
59
- "Would be: #{format_bytes(new_total_size)}. " \
60
- "Clear old entries or use smaller content."
61
- end
62
-
63
- # Create entry
64
- entry = Entry.new(
65
- content: content,
66
- title: title,
67
- created_at: Time.now,
68
- size: content_size,
69
- )
70
-
71
- # Update storage
72
- @entries[file_path] = entry
73
- @total_size = new_total_size
74
-
75
- entry
76
- end
77
-
78
- # Read content from scratchpad
79
- #
80
- # @param file_path [String] Path to read from
81
- # @raise [ArgumentError] If path not found
82
- # @return [String] Content at the path
83
- def read(file_path:)
84
- raise ArgumentError, "file_path is required" if file_path.nil? || file_path.to_s.strip.empty?
85
-
86
- entry = @entries[file_path]
87
- raise ArgumentError, "scratchpad://#{file_path} not found" unless entry
88
-
89
- entry.content
90
- end
91
-
92
- # List scratchpad entries, optionally filtered by prefix
93
- #
94
- # @param prefix [String, nil] Filter by path prefix
95
- # @return [Array<Hash>] Array of entry metadata (path, title, size, created_at)
96
- def list(prefix: nil)
97
- entries = @entries
98
-
99
- # Filter by prefix if provided
100
- if prefix && !prefix.empty?
101
- entries = entries.select { |path, _| path.start_with?(prefix) }
102
- end
103
-
104
- # Return metadata
105
- entries.map do |path, entry|
106
- {
107
- path: path,
108
- title: entry.title,
109
- size: entry.size,
110
- created_at: entry.created_at,
111
- }
112
- end.sort_by { |e| e[:path] }
113
- end
114
-
115
- # Clear all entries
116
- #
117
- # @return [void]
118
- def clear
119
- @entries.clear
120
- @total_size = 0
121
- end
122
-
123
- # Get current total size
124
- #
125
- # @return [Integer] Total size in bytes
126
- attr_reader :total_size
127
-
128
- # Get number of entries
129
- #
130
- # @return [Integer] Number of entries
131
- def size
132
- @entries.size
133
- end
134
-
135
- private
136
-
137
- # Format bytes to human-readable size
138
- #
139
- # @param bytes [Integer] Number of bytes
140
- # @return [String] Formatted size (e.g., "1.5MB", "500.0KB")
141
- def format_bytes(bytes)
142
- if bytes >= 1_000_000
143
- "#{(bytes.to_f / 1_000_000).round(1)}MB"
144
- elsif bytes >= 1_000
145
- "#{(bytes.to_f / 1_000).round(1)}KB"
146
- else
147
- "#{bytes}B"
148
- end
149
- end
150
- end
151
- end
152
- end
153
- end