swarm_memory 2.1.5 → 2.1.6

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 (182) hide show
  1. checksums.yaml +4 -4
  2. data/lib/swarm_memory/version.rb +1 -1
  3. metadata +5 -184
  4. data/lib/claude_swarm/base_executor.rb +0 -133
  5. data/lib/claude_swarm/claude_code_executor.rb +0 -349
  6. data/lib/claude_swarm/claude_mcp_server.rb +0 -78
  7. data/lib/claude_swarm/cli.rb +0 -697
  8. data/lib/claude_swarm/commands/ps.rb +0 -215
  9. data/lib/claude_swarm/commands/show.rb +0 -139
  10. data/lib/claude_swarm/configuration.rb +0 -373
  11. data/lib/claude_swarm/hooks/session_start_hook.rb +0 -42
  12. data/lib/claude_swarm/json_handler.rb +0 -91
  13. data/lib/claude_swarm/mcp_generator.rb +0 -230
  14. data/lib/claude_swarm/openai/chat_completion.rb +0 -256
  15. data/lib/claude_swarm/openai/executor.rb +0 -256
  16. data/lib/claude_swarm/openai/responses.rb +0 -319
  17. data/lib/claude_swarm/orchestrator.rb +0 -878
  18. data/lib/claude_swarm/process_tracker.rb +0 -78
  19. data/lib/claude_swarm/session_cost_calculator.rb +0 -209
  20. data/lib/claude_swarm/session_path.rb +0 -42
  21. data/lib/claude_swarm/settings_generator.rb +0 -77
  22. data/lib/claude_swarm/system_utils.rb +0 -46
  23. data/lib/claude_swarm/templates/generation_prompt.md.erb +0 -230
  24. data/lib/claude_swarm/tools/reset_session_tool.rb +0 -24
  25. data/lib/claude_swarm/tools/session_info_tool.rb +0 -24
  26. data/lib/claude_swarm/tools/task_tool.rb +0 -63
  27. data/lib/claude_swarm/version.rb +0 -5
  28. data/lib/claude_swarm/worktree_manager.rb +0 -475
  29. data/lib/claude_swarm/yaml_loader.rb +0 -22
  30. data/lib/claude_swarm.rb +0 -67
  31. data/lib/swarm_cli/cli.rb +0 -201
  32. data/lib/swarm_cli/command_registry.rb +0 -61
  33. data/lib/swarm_cli/commands/mcp_serve.rb +0 -130
  34. data/lib/swarm_cli/commands/mcp_tools.rb +0 -148
  35. data/lib/swarm_cli/commands/migrate.rb +0 -55
  36. data/lib/swarm_cli/commands/run.rb +0 -173
  37. data/lib/swarm_cli/config_loader.rb +0 -98
  38. data/lib/swarm_cli/formatters/human_formatter.rb +0 -781
  39. data/lib/swarm_cli/formatters/json_formatter.rb +0 -51
  40. data/lib/swarm_cli/interactive_repl.rb +0 -924
  41. data/lib/swarm_cli/mcp_serve_options.rb +0 -44
  42. data/lib/swarm_cli/mcp_tools_options.rb +0 -59
  43. data/lib/swarm_cli/migrate_options.rb +0 -54
  44. data/lib/swarm_cli/migrator.rb +0 -132
  45. data/lib/swarm_cli/options.rb +0 -151
  46. data/lib/swarm_cli/ui/components/agent_badge.rb +0 -33
  47. data/lib/swarm_cli/ui/components/content_block.rb +0 -120
  48. data/lib/swarm_cli/ui/components/divider.rb +0 -57
  49. data/lib/swarm_cli/ui/components/panel.rb +0 -62
  50. data/lib/swarm_cli/ui/components/usage_stats.rb +0 -70
  51. data/lib/swarm_cli/ui/formatters/cost.rb +0 -49
  52. data/lib/swarm_cli/ui/formatters/number.rb +0 -58
  53. data/lib/swarm_cli/ui/formatters/text.rb +0 -77
  54. data/lib/swarm_cli/ui/formatters/time.rb +0 -73
  55. data/lib/swarm_cli/ui/icons.rb +0 -36
  56. data/lib/swarm_cli/ui/renderers/event_renderer.rb +0 -188
  57. data/lib/swarm_cli/ui/state/agent_color_cache.rb +0 -45
  58. data/lib/swarm_cli/ui/state/depth_tracker.rb +0 -40
  59. data/lib/swarm_cli/ui/state/spinner_manager.rb +0 -170
  60. data/lib/swarm_cli/ui/state/usage_tracker.rb +0 -62
  61. data/lib/swarm_cli/version.rb +0 -5
  62. data/lib/swarm_cli.rb +0 -46
  63. data/lib/swarm_sdk/agent/RETRY_LOGIC.md +0 -127
  64. data/lib/swarm_sdk/agent/builder.rb +0 -552
  65. data/lib/swarm_sdk/agent/chat.rb +0 -774
  66. data/lib/swarm_sdk/agent/chat_helpers/context_tracker.rb +0 -268
  67. data/lib/swarm_sdk/agent/chat_helpers/event_emitter.rb +0 -204
  68. data/lib/swarm_sdk/agent/chat_helpers/hook_integration.rb +0 -480
  69. data/lib/swarm_sdk/agent/chat_helpers/instrumentation.rb +0 -78
  70. data/lib/swarm_sdk/agent/chat_helpers/llm_configuration.rb +0 -233
  71. data/lib/swarm_sdk/agent/chat_helpers/logging_helpers.rb +0 -116
  72. data/lib/swarm_sdk/agent/chat_helpers/serialization.rb +0 -83
  73. data/lib/swarm_sdk/agent/chat_helpers/system_reminder_injector.rb +0 -136
  74. data/lib/swarm_sdk/agent/chat_helpers/system_reminders.rb +0 -79
  75. data/lib/swarm_sdk/agent/chat_helpers/token_tracking.rb +0 -98
  76. data/lib/swarm_sdk/agent/context.rb +0 -116
  77. data/lib/swarm_sdk/agent/context_manager.rb +0 -315
  78. data/lib/swarm_sdk/agent/definition.rb +0 -477
  79. data/lib/swarm_sdk/agent/llm_instrumentation_middleware.rb +0 -182
  80. data/lib/swarm_sdk/agent/system_prompt_builder.rb +0 -161
  81. data/lib/swarm_sdk/builders/base_builder.rb +0 -409
  82. data/lib/swarm_sdk/claude_code_agent_adapter.rb +0 -205
  83. data/lib/swarm_sdk/concerns/cleanupable.rb +0 -39
  84. data/lib/swarm_sdk/concerns/snapshotable.rb +0 -67
  85. data/lib/swarm_sdk/concerns/validatable.rb +0 -55
  86. data/lib/swarm_sdk/configuration/parser.rb +0 -353
  87. data/lib/swarm_sdk/configuration/translator.rb +0 -255
  88. data/lib/swarm_sdk/configuration.rb +0 -135
  89. data/lib/swarm_sdk/context_compactor/metrics.rb +0 -147
  90. data/lib/swarm_sdk/context_compactor/token_counter.rb +0 -106
  91. data/lib/swarm_sdk/context_compactor.rb +0 -335
  92. data/lib/swarm_sdk/context_management/builder.rb +0 -128
  93. data/lib/swarm_sdk/context_management/context.rb +0 -328
  94. data/lib/swarm_sdk/defaults.rb +0 -196
  95. data/lib/swarm_sdk/events_to_messages.rb +0 -199
  96. data/lib/swarm_sdk/hooks/adapter.rb +0 -359
  97. data/lib/swarm_sdk/hooks/context.rb +0 -197
  98. data/lib/swarm_sdk/hooks/definition.rb +0 -80
  99. data/lib/swarm_sdk/hooks/error.rb +0 -29
  100. data/lib/swarm_sdk/hooks/executor.rb +0 -146
  101. data/lib/swarm_sdk/hooks/registry.rb +0 -147
  102. data/lib/swarm_sdk/hooks/result.rb +0 -150
  103. data/lib/swarm_sdk/hooks/shell_executor.rb +0 -255
  104. data/lib/swarm_sdk/hooks/tool_call.rb +0 -35
  105. data/lib/swarm_sdk/hooks/tool_result.rb +0 -62
  106. data/lib/swarm_sdk/log_collector.rb +0 -227
  107. data/lib/swarm_sdk/log_stream.rb +0 -127
  108. data/lib/swarm_sdk/markdown_parser.rb +0 -75
  109. data/lib/swarm_sdk/model_aliases.json +0 -8
  110. data/lib/swarm_sdk/models.json +0 -1
  111. data/lib/swarm_sdk/models.rb +0 -120
  112. data/lib/swarm_sdk/node_context.rb +0 -245
  113. data/lib/swarm_sdk/observer/builder.rb +0 -81
  114. data/lib/swarm_sdk/observer/config.rb +0 -45
  115. data/lib/swarm_sdk/observer/manager.rb +0 -236
  116. data/lib/swarm_sdk/patterns/agent_observer.rb +0 -160
  117. data/lib/swarm_sdk/permissions/config.rb +0 -239
  118. data/lib/swarm_sdk/permissions/error_formatter.rb +0 -121
  119. data/lib/swarm_sdk/permissions/path_matcher.rb +0 -35
  120. data/lib/swarm_sdk/permissions/validator.rb +0 -173
  121. data/lib/swarm_sdk/permissions_builder.rb +0 -122
  122. data/lib/swarm_sdk/plugin.rb +0 -309
  123. data/lib/swarm_sdk/plugin_registry.rb +0 -101
  124. data/lib/swarm_sdk/proc_helpers.rb +0 -53
  125. data/lib/swarm_sdk/prompts/base_system_prompt.md.erb +0 -117
  126. data/lib/swarm_sdk/restore_result.rb +0 -65
  127. data/lib/swarm_sdk/result.rb +0 -123
  128. data/lib/swarm_sdk/snapshot.rb +0 -156
  129. data/lib/swarm_sdk/snapshot_from_events.rb +0 -397
  130. data/lib/swarm_sdk/state_restorer.rb +0 -476
  131. data/lib/swarm_sdk/state_snapshot.rb +0 -334
  132. data/lib/swarm_sdk/swarm/agent_initializer.rb +0 -683
  133. data/lib/swarm_sdk/swarm/all_agents_builder.rb +0 -167
  134. data/lib/swarm_sdk/swarm/builder.rb +0 -249
  135. data/lib/swarm_sdk/swarm/executor.rb +0 -213
  136. data/lib/swarm_sdk/swarm/hook_triggers.rb +0 -150
  137. data/lib/swarm_sdk/swarm/logging_callbacks.rb +0 -340
  138. data/lib/swarm_sdk/swarm/mcp_configurator.rb +0 -154
  139. data/lib/swarm_sdk/swarm/swarm_registry_builder.rb +0 -67
  140. data/lib/swarm_sdk/swarm/tool_configurator.rb +0 -358
  141. data/lib/swarm_sdk/swarm.rb +0 -717
  142. data/lib/swarm_sdk/swarm_loader.rb +0 -145
  143. data/lib/swarm_sdk/swarm_registry.rb +0 -136
  144. data/lib/swarm_sdk/tools/bash.rb +0 -282
  145. data/lib/swarm_sdk/tools/clock.rb +0 -44
  146. data/lib/swarm_sdk/tools/delegate.rb +0 -267
  147. data/lib/swarm_sdk/tools/document_converters/base_converter.rb +0 -83
  148. data/lib/swarm_sdk/tools/document_converters/docx_converter.rb +0 -99
  149. data/lib/swarm_sdk/tools/document_converters/html_converter.rb +0 -101
  150. data/lib/swarm_sdk/tools/document_converters/pdf_converter.rb +0 -78
  151. data/lib/swarm_sdk/tools/document_converters/xlsx_converter.rb +0 -194
  152. data/lib/swarm_sdk/tools/edit.rb +0 -145
  153. data/lib/swarm_sdk/tools/glob.rb +0 -166
  154. data/lib/swarm_sdk/tools/grep.rb +0 -235
  155. data/lib/swarm_sdk/tools/image_extractors/docx_image_extractor.rb +0 -43
  156. data/lib/swarm_sdk/tools/image_extractors/pdf_image_extractor.rb +0 -163
  157. data/lib/swarm_sdk/tools/image_formats/tiff_builder.rb +0 -65
  158. data/lib/swarm_sdk/tools/multi_edit.rb +0 -236
  159. data/lib/swarm_sdk/tools/path_resolver.rb +0 -92
  160. data/lib/swarm_sdk/tools/read.rb +0 -261
  161. data/lib/swarm_sdk/tools/registry.rb +0 -205
  162. data/lib/swarm_sdk/tools/scratchpad/scratchpad_list.rb +0 -117
  163. data/lib/swarm_sdk/tools/scratchpad/scratchpad_read.rb +0 -97
  164. data/lib/swarm_sdk/tools/scratchpad/scratchpad_write.rb +0 -108
  165. data/lib/swarm_sdk/tools/stores/read_tracker.rb +0 -96
  166. data/lib/swarm_sdk/tools/stores/scratchpad_storage.rb +0 -272
  167. data/lib/swarm_sdk/tools/stores/storage.rb +0 -142
  168. data/lib/swarm_sdk/tools/stores/todo_manager.rb +0 -65
  169. data/lib/swarm_sdk/tools/think.rb +0 -98
  170. data/lib/swarm_sdk/tools/todo_write.rb +0 -235
  171. data/lib/swarm_sdk/tools/web_fetch.rb +0 -262
  172. data/lib/swarm_sdk/tools/write.rb +0 -112
  173. data/lib/swarm_sdk/utils.rb +0 -68
  174. data/lib/swarm_sdk/validation_result.rb +0 -33
  175. data/lib/swarm_sdk/version.rb +0 -5
  176. data/lib/swarm_sdk/workflow/agent_config.rb +0 -79
  177. data/lib/swarm_sdk/workflow/builder.rb +0 -143
  178. data/lib/swarm_sdk/workflow/executor.rb +0 -497
  179. data/lib/swarm_sdk/workflow/node_builder.rb +0 -555
  180. data/lib/swarm_sdk/workflow/transformer_executor.rb +0 -249
  181. data/lib/swarm_sdk/workflow.rb +0 -554
  182. data/lib/swarm_sdk.rb +0 -524
@@ -1,272 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module SwarmSDK
4
- module Tools
5
- module Stores
6
- # ScratchpadStorage provides volatile, shared storage
7
- #
8
- # Features:
9
- # - Shared: All agents share the same scratchpad
10
- # - Volatile: NEVER persists - all data lost when process ends
11
- # - Path-based: Hierarchical organization using file-path-like addresses
12
- # - Metadata-rich: Stores content + title + timestamp + size
13
- # - Thread-safe: Mutex-protected operations
14
- #
15
- # Use for temporary, cross-agent communication within a single session.
16
- class ScratchpadStorage < Storage
17
- # Initialize scratchpad storage (always volatile)
18
- #
19
- # @param total_size_limit [Integer, nil] Maximum total size in bytes (defaults to Defaults::Storage::TOTAL_SIZE_BYTES)
20
- def initialize(total_size_limit: nil)
21
- super() # Initialize parent Storage class
22
- @entries = {}
23
- @total_size = 0
24
- @total_size_limit = total_size_limit || Defaults::Storage::TOTAL_SIZE_BYTES
25
- @mutex = Mutex.new
26
- end
27
-
28
- # Write content to scratchpad
29
- #
30
- # @param file_path [String] Path to store content
31
- # @param content [String] Content to store
32
- # @param title [String] Brief title describing the content
33
- # @raise [ArgumentError] If size limits are exceeded
34
- # @return [Entry] The created entry
35
- def write(file_path:, content:, title:)
36
- @mutex.synchronize do
37
- raise ArgumentError, "file_path is required" if file_path.nil? || file_path.to_s.strip.empty?
38
- raise ArgumentError, "content is required" if content.nil?
39
- raise ArgumentError, "title is required" if title.nil? || title.to_s.strip.empty?
40
-
41
- content_size = content.bytesize
42
-
43
- # Check entry size limit
44
- if content_size > Defaults::Storage::ENTRY_SIZE_BYTES
45
- raise ArgumentError, "Content exceeds maximum size (#{format_bytes(Defaults::Storage::ENTRY_SIZE_BYTES)}). " \
46
- "Current: #{format_bytes(content_size)}"
47
- end
48
-
49
- # Calculate new total size
50
- existing_entry = @entries[file_path]
51
- existing_size = existing_entry ? existing_entry.size : 0
52
- new_total_size = @total_size - existing_size + content_size
53
-
54
- # Check total size limit
55
- if new_total_size > @total_size_limit
56
- raise ArgumentError, "Scratchpad full (#{format_bytes(@total_size_limit)} limit). " \
57
- "Current: #{format_bytes(@total_size)}, " \
58
- "Would be: #{format_bytes(new_total_size)}. " \
59
- "Clear old entries or use smaller content."
60
- end
61
-
62
- # Create entry
63
- entry = Entry.new(
64
- content: content,
65
- title: title,
66
- updated_at: Time.now,
67
- size: content_size,
68
- )
69
-
70
- # Update storage
71
- @entries[file_path] = entry
72
- @total_size = new_total_size
73
-
74
- entry
75
- end
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
- # Delete a specific entry
93
- #
94
- # @param file_path [String] Path to delete
95
- # @raise [ArgumentError] If path not found
96
- # @return [void]
97
- def delete(file_path:)
98
- @mutex.synchronize do
99
- raise ArgumentError, "file_path is required" if file_path.nil? || file_path.to_s.strip.empty?
100
-
101
- entry = @entries[file_path]
102
- raise ArgumentError, "scratchpad://#{file_path} not found" unless entry
103
-
104
- # Update total size
105
- @total_size -= entry.size
106
-
107
- # Remove entry
108
- @entries.delete(file_path)
109
- end
110
- end
111
-
112
- # List scratchpad entries, optionally filtered by prefix
113
- #
114
- # @param prefix [String, nil] Filter by path prefix
115
- # @return [Array<Hash>] Array of entry metadata (path, title, size, updated_at)
116
- def list(prefix: nil)
117
- entries = @entries
118
-
119
- # Filter by prefix if provided
120
- if prefix && !prefix.empty?
121
- entries = entries.select { |path, _| path.start_with?(prefix) }
122
- end
123
-
124
- # Return metadata sorted by path
125
- entries.map do |path, entry|
126
- {
127
- path: path,
128
- title: entry.title,
129
- size: entry.size,
130
- updated_at: entry.updated_at,
131
- }
132
- end.sort_by { |e| e[:path] }
133
- end
134
-
135
- # Search entries by glob pattern
136
- #
137
- # @param pattern [String] Glob pattern (e.g., "**/*.txt", "parallel/*/task_*")
138
- # @return [Array<Hash>] Array of matching entry metadata, sorted by most recent first
139
- def glob(pattern:)
140
- raise ArgumentError, "pattern is required" if pattern.nil? || pattern.to_s.strip.empty?
141
-
142
- # Convert glob pattern to regex
143
- regex = glob_to_regex(pattern)
144
-
145
- # Filter entries by pattern
146
- matching_entries = @entries.select { |path, _| regex.match?(path) }
147
-
148
- # Return metadata sorted by most recent first
149
- matching_entries.map do |path, entry|
150
- {
151
- path: path,
152
- title: entry.title,
153
- size: entry.size,
154
- updated_at: entry.updated_at,
155
- }
156
- end.sort_by { |e| -e[:updated_at].to_f }
157
- end
158
-
159
- # Search entry content by pattern
160
- #
161
- # @param pattern [String] Regular expression pattern to search for
162
- # @param case_insensitive [Boolean] Whether to perform case-insensitive search
163
- # @param output_mode [String] Output mode: "files_with_matches" (default), "content", or "count"
164
- # @return [Array<Hash>, String] Results based on output_mode
165
- def grep(pattern:, case_insensitive: false, output_mode: "files_with_matches")
166
- raise ArgumentError, "pattern is required" if pattern.nil? || pattern.to_s.strip.empty?
167
-
168
- # Create regex from pattern
169
- flags = case_insensitive ? Regexp::IGNORECASE : 0
170
- regex = Regexp.new(pattern, flags)
171
-
172
- case output_mode
173
- when "files_with_matches"
174
- # Return just the paths that match
175
- matching_paths = @entries.select { |_path, entry| regex.match?(entry.content) }
176
- .map { |path, _| path }
177
- .sort
178
- matching_paths
179
- when "content"
180
- # Return paths with matching lines, sorted by most recent first
181
- results = []
182
- @entries.each do |path, entry|
183
- matching_lines = []
184
- entry.content.each_line.with_index(1) do |line, line_num|
185
- matching_lines << { line_number: line_num, content: line.chomp } if regex.match?(line)
186
- end
187
- results << { path: path, matches: matching_lines, updated_at: entry.updated_at } unless matching_lines.empty?
188
- end
189
- results.sort_by { |r| -r[:updated_at].to_f }.map { |r| r.except(:updated_at) }
190
- when "count"
191
- # Return paths with match counts, sorted by most recent first
192
- results = []
193
- @entries.each do |path, entry|
194
- count = entry.content.scan(regex).size
195
- results << { path: path, count: count, updated_at: entry.updated_at } if count > 0
196
- end
197
- results.sort_by { |r| -r[:updated_at].to_f }.map { |r| r.except(:updated_at) }
198
- else
199
- raise ArgumentError, "Invalid output_mode: #{output_mode}. Must be 'files_with_matches', 'content', or 'count'"
200
- end
201
- end
202
-
203
- # Clear all entries
204
- #
205
- # @return [void]
206
- def clear
207
- @mutex.synchronize do
208
- @entries.clear
209
- @total_size = 0
210
- end
211
- end
212
-
213
- # Get current total size
214
- #
215
- # @return [Integer] Total size in bytes
216
- attr_reader :total_size
217
-
218
- # Get number of entries
219
- #
220
- # @return [Integer] Number of entries
221
- def size
222
- @entries.size
223
- end
224
-
225
- # Get all entries with content for snapshot
226
- #
227
- # Thread-safe method that returns a copy of all entries.
228
- # Used by snapshot/restore functionality.
229
- #
230
- # @return [Hash] { path => Entry }
231
- def all_entries
232
- @mutex.synchronize do
233
- @entries.dup
234
- end
235
- end
236
-
237
- # Restore entries from snapshot
238
- #
239
- # Restores entries directly without using write() to preserve timestamps.
240
- # This ensures entry ordering and metadata accuracy after restore.
241
- #
242
- # @param entries_data [Hash] { path => { content:, title:, updated_at:, size: } }
243
- # @return [void]
244
- def restore_entries(entries_data)
245
- @mutex.synchronize do
246
- entries_data.each do |path, data|
247
- # Handle both symbol and string keys from JSON
248
- content = data[:content] || data["content"]
249
- title = data[:title] || data["title"]
250
- updated_at_str = data[:updated_at] || data["updated_at"]
251
-
252
- # Parse timestamp from ISO8601 string
253
- updated_at = Time.parse(updated_at_str)
254
-
255
- # Create entry with preserved timestamp
256
- entry = Entry.new(
257
- content: content,
258
- title: title,
259
- updated_at: updated_at,
260
- size: content.bytesize,
261
- )
262
-
263
- # Update storage
264
- @entries[path] = entry
265
- @total_size += entry.size
266
- end
267
- end
268
- end
269
- end
270
- end
271
- end
272
- end
@@ -1,142 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module SwarmSDK
4
- module Tools
5
- module Stores
6
- # Abstract base class for hierarchical key-value storage with metadata
7
- #
8
- # Provides session-scoped storage for agents with path-based organization.
9
- # Subclasses implement persistence behavior (volatile vs persistent).
10
- #
11
- # Features:
12
- # - Path-based: Hierarchical organization using file-path-like addresses
13
- # - Metadata-rich: Stores content + title + timestamp + size
14
- # - Search capabilities: Glob patterns and grep-style content search
15
- # - Thread-safe: Mutex-protected operations
16
- class Storage
17
- # Represents a single storage entry with metadata
18
- Entry = Struct.new(:content, :title, :updated_at, :size, keyword_init: true)
19
-
20
- # Initialize storage
21
- #
22
- # Subclasses should call super() in their initialize method.
23
- # This base implementation does nothing - it exists only to satisfy RuboCop.
24
- def initialize
25
- # Base class initialization - subclasses implement their own logic
26
- end
27
-
28
- # Write content to storage
29
- #
30
- # @param file_path [String] Path to store content
31
- # @param content [String] Content to store
32
- # @param title [String] Brief title describing the content
33
- # @raise [ArgumentError] If size limits are exceeded
34
- # @return [Entry] The created entry
35
- def write(file_path:, content:, title:)
36
- raise NotImplementedError, "Subclass must implement #write"
37
- end
38
-
39
- # Read content from storage
40
- #
41
- # @param file_path [String] Path to read from
42
- # @raise [ArgumentError] If path not found
43
- # @return [String] Content at the path
44
- def read(file_path:)
45
- raise NotImplementedError, "Subclass must implement #read"
46
- end
47
-
48
- # Delete a specific entry
49
- #
50
- # @param file_path [String] Path to delete
51
- # @raise [ArgumentError] If path not found
52
- # @return [void]
53
- def delete(file_path:)
54
- raise NotImplementedError, "Subclass must implement #delete"
55
- end
56
-
57
- # List entries, optionally filtered by prefix
58
- #
59
- # @param prefix [String, nil] Filter by path prefix
60
- # @return [Array<Hash>] Array of entry metadata (path, title, size, updated_at)
61
- def list(prefix: nil)
62
- raise NotImplementedError, "Subclass must implement #list"
63
- end
64
-
65
- # Search entries by glob pattern
66
- #
67
- # @param pattern [String] Glob pattern (e.g., "**/*.txt", "parallel/*/task_*")
68
- # @return [Array<Hash>] Array of matching entry metadata, sorted by most recent first
69
- def glob(pattern:)
70
- raise NotImplementedError, "Subclass must implement #glob"
71
- end
72
-
73
- # Search entry content by pattern
74
- #
75
- # @param pattern [String] Regular expression pattern to search for
76
- # @param case_insensitive [Boolean] Whether to perform case-insensitive search
77
- # @param output_mode [String] Output mode: "files_with_matches" (default), "content", or "count"
78
- # @return [Array<Hash>, String] Results based on output_mode
79
- def grep(pattern:, case_insensitive: false, output_mode: "files_with_matches")
80
- raise NotImplementedError, "Subclass must implement #grep"
81
- end
82
-
83
- # Clear all entries
84
- #
85
- # @return [void]
86
- def clear
87
- raise NotImplementedError, "Subclass must implement #clear"
88
- end
89
-
90
- # Get current total size
91
- #
92
- # @return [Integer] Total size in bytes
93
- def total_size
94
- raise NotImplementedError, "Subclass must implement #total_size"
95
- end
96
-
97
- # Get number of entries
98
- #
99
- # @return [Integer] Number of entries
100
- def size
101
- raise NotImplementedError, "Subclass must implement #size"
102
- end
103
-
104
- protected
105
-
106
- # Format bytes to human-readable size
107
- #
108
- # @param bytes [Integer] Number of bytes
109
- # @return [String] Formatted size (e.g., "1.5MB", "500.0KB")
110
- def format_bytes(bytes)
111
- if bytes >= 1_000_000
112
- "#{(bytes.to_f / 1_000_000).round(1)}MB"
113
- elsif bytes >= 1_000
114
- "#{(bytes.to_f / 1_000).round(1)}KB"
115
- else
116
- "#{bytes}B"
117
- end
118
- end
119
-
120
- # Convert glob pattern to regex
121
- #
122
- # @param pattern [String] Glob pattern
123
- # @return [Regexp] Regular expression
124
- def glob_to_regex(pattern)
125
- # Escape special regex characters except glob wildcards
126
- escaped = Regexp.escape(pattern)
127
-
128
- # Convert glob wildcards to regex
129
- # ** matches any number of directories (including zero)
130
- escaped = escaped.gsub('\*\*', ".*")
131
- # * matches anything except directory separator
132
- escaped = escaped.gsub('\*', "[^/]*")
133
- # ? matches single character except directory separator
134
- escaped = escaped.gsub('\?', "[^/]")
135
-
136
- # Anchor to start and end
137
- Regexp.new("\\A#{escaped}\\z")
138
- end
139
- end
140
- end
141
- end
142
- end
@@ -1,65 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module SwarmSDK
4
- module Tools
5
- module Stores
6
- # TodoManager provides per-agent todo list storage
7
- #
8
- # Each agent maintains its own independent todo list that persists
9
- # throughout the agent's execution session. This allows agents to
10
- # track progress on complex multi-step tasks.
11
- class TodoManager
12
- @storage = {}
13
- @mutex = Mutex.new
14
-
15
- class << self
16
- # Get the current todo list for an agent
17
- #
18
- # @param agent_id [Symbol, String] Unique agent identifier
19
- # @return [Array<Hash>] Array of todo items
20
- def get_todos(agent_id)
21
- @mutex.synchronize do
22
- @storage[agent_id.to_sym] ||= []
23
- end
24
- end
25
-
26
- # Set the todo list for an agent
27
- #
28
- # @param agent_id [Symbol, String] Unique agent identifier
29
- # @param todos [Array<Hash>] Array of todo items
30
- # @return [Array<Hash>] The stored todos
31
- def set_todos(agent_id, todos)
32
- @mutex.synchronize do
33
- @storage[agent_id.to_sym] = todos
34
- end
35
- end
36
-
37
- # Clear all todos for an agent
38
- #
39
- # @param agent_id [Symbol, String] Unique agent identifier
40
- def clear_todos(agent_id)
41
- @mutex.synchronize do
42
- @storage.delete(agent_id.to_sym)
43
- end
44
- end
45
-
46
- # Clear all todos for all agents
47
- def clear_all
48
- @mutex.synchronize do
49
- @storage.clear
50
- end
51
- end
52
-
53
- # Get summary of all agent todo lists
54
- #
55
- # @return [Hash] Map of agent_id => todo count
56
- def summary
57
- @mutex.synchronize do
58
- @storage.transform_values(&:size)
59
- end
60
- end
61
- end
62
- end
63
- end
64
- end
65
- end
@@ -1,98 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module SwarmSDK
4
- module Tools
5
- # Think tool for explicit reasoning and planning
6
- #
7
- # Allows the agent to write down thoughts, plans, strategies, and intermediate
8
- # calculations. These thoughts become part of the conversation context, enabling
9
- # better attention and reasoning through complex problems.
10
- #
11
- # This is inspired by research showing that explicitly articulating reasoning steps
12
- # (chain-of-thought prompting) leads to significantly better outcomes, especially
13
- # for complex tasks requiring multi-step reasoning or arithmetic.
14
- class Think < RubyLLM::Tool
15
- def name
16
- "Think"
17
- end
18
-
19
- description <<~DESC
20
- **IMPORTANT: You SHOULD use this tool frequently throughout your work. Using this tool leads to significantly
21
- better outcomes and more accurate solutions. Make it a habit to think before acting.**
22
-
23
- This tool allows you to write down your thoughts, plans, strategies, and intermediate calculations.
24
- Think of it as your working memory - just as humans think before speaking or acting, you should think before
25
- using other tools or providing responses.
26
-
27
- **STRONGLY RECOMMENDED to use this tool:**
28
- - **ALWAYS** before starting any task (even simple ones)
29
- - **ALWAYS** when you need to do any arithmetic or counting
30
- - **ALWAYS** after reading files or getting search results to process what you learned
31
- - **FREQUENTLY** between steps to track progress and plan next actions
32
-
33
- This is your private thinking space - use it liberally to enhance your problem-solving capabilities. Recording
34
- your thoughts helps you maintain context across multiple steps and remember important information throughout your task.
35
-
36
- When and how to use this tool:
37
-
38
- 1. **Before starting any complex task**: Write down your understanding of the problem, break it into smaller
39
- sub-tasks, and create a step-by-step plan. Example:
40
- - "The user wants me to refactor this codebase. Let me first understand the structure..."
41
- - "I need to: 1) Analyze current architecture, 2) Identify pain points, 3) Propose changes..."
42
-
43
- 2. **For arithmetic and calculations**: Work through math problems step by step. Example:
44
- - "If we have 150 requests/second and each takes 20ms, that's 150 * 0.02 = 3 seconds of CPU time..."
45
- - "Converting 2GB to bytes: 2 * 1024 * 1024 * 1024 = 2,147,483,648 bytes"
46
-
47
- 3. **After completing sub-tasks**: Summarize what you've accomplished and what remains. Example:
48
- - "I've successfully implemented the authentication module. Next, I need to integrate it with the API..."
49
- - "Fixed 3 out of 5 bugs. Remaining: memory leak in parser, race condition in worker thread"
50
-
51
- 4. **When encountering complexity**: Break down complex logic or decisions. Example:
52
- - "This function has multiple edge cases. Let me list them: null input, empty array, negative numbers..."
53
- - "The user's request is ambiguous. Possible interpretations: A) modify existing code, B) create new module..."
54
-
55
- 5. **For remembering context**: Store important information you'll need later. Example:
56
- - "Important: The user mentioned they're using Ruby 3.2, so I can use pattern matching"
57
- - "File structure: main.rb requires from lib/, config is in config.yml"
58
-
59
- 6. **When debugging or analyzing**: Track your investigation process. Example:
60
- - "The error occurs in line 42. Let me trace backwards: function called from main(), receives data from..."
61
- - "Hypothesis: the bug might be due to timezone differences. Let me check..."
62
-
63
- 7. **For creative problem-solving**: Brainstorm multiple approaches before choosing one. Example:
64
- - "Approaches to optimize this: 1) Add caching, 2) Use parallel processing, 3) Optimize algorithm..."
65
- - "Design patterns that could work here: Factory, Observer, or maybe Strategy pattern..."
66
-
67
- **Remember: The most successful agents use this tool 5-10 times per task on average. If you haven't used this
68
- tool in the last 2-3 actions, you probably should. Using this tool is a sign of thoughtful, methodical problem
69
- solving and leads to fewer mistakes and better solutions.**
70
-
71
- Your thoughts persist throughout your session as part of the conversation history, so you can refer
72
- back to earlier thinking. Use clear formatting and organization to make it easy to reference
73
- later. Don't hesitate to think out loud - this tool is designed to augment your cognitive capabilities and help
74
- you deliver better solutions.
75
-
76
- **CRITICAL:** The Think tool takes only one parameter: thoughts. Do not include any other parameters.
77
- DESC
78
-
79
- param :thoughts,
80
- type: "string",
81
- desc: "Your thoughts, plans, calculations, or any notes you want to record",
82
- required: true
83
-
84
- def execute(**kwargs)
85
- <<~RESP
86
- Thought noted.
87
- RESP
88
- # <system-reminder>The user cannot see your thoughts. You MUST NOT stop without giving the user a response.</system-reminder>
89
- end
90
-
91
- private
92
-
93
- def validation_error(message)
94
- "<tool_use_error>InputValidationError: #{message}</tool_use_error>"
95
- end
96
- end
97
- end
98
- end