swarm_memory 2.1.4 → 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 (184) hide show
  1. checksums.yaml +4 -4
  2. data/lib/swarm_memory/version.rb +1 -1
  3. data/lib/swarm_memory.rb +7 -2
  4. metadata +6 -185
  5. data/lib/claude_swarm/base_executor.rb +0 -133
  6. data/lib/claude_swarm/claude_code_executor.rb +0 -349
  7. data/lib/claude_swarm/claude_mcp_server.rb +0 -78
  8. data/lib/claude_swarm/cli.rb +0 -697
  9. data/lib/claude_swarm/commands/ps.rb +0 -215
  10. data/lib/claude_swarm/commands/show.rb +0 -139
  11. data/lib/claude_swarm/configuration.rb +0 -373
  12. data/lib/claude_swarm/hooks/session_start_hook.rb +0 -42
  13. data/lib/claude_swarm/json_handler.rb +0 -91
  14. data/lib/claude_swarm/mcp_generator.rb +0 -243
  15. data/lib/claude_swarm/openai/chat_completion.rb +0 -256
  16. data/lib/claude_swarm/openai/executor.rb +0 -256
  17. data/lib/claude_swarm/openai/responses.rb +0 -319
  18. data/lib/claude_swarm/orchestrator.rb +0 -878
  19. data/lib/claude_swarm/process_tracker.rb +0 -78
  20. data/lib/claude_swarm/session_cost_calculator.rb +0 -209
  21. data/lib/claude_swarm/session_path.rb +0 -42
  22. data/lib/claude_swarm/settings_generator.rb +0 -77
  23. data/lib/claude_swarm/system_utils.rb +0 -46
  24. data/lib/claude_swarm/templates/generation_prompt.md.erb +0 -230
  25. data/lib/claude_swarm/tools/reset_session_tool.rb +0 -24
  26. data/lib/claude_swarm/tools/session_info_tool.rb +0 -24
  27. data/lib/claude_swarm/tools/task_tool.rb +0 -63
  28. data/lib/claude_swarm/version.rb +0 -5
  29. data/lib/claude_swarm/worktree_manager.rb +0 -475
  30. data/lib/claude_swarm/yaml_loader.rb +0 -22
  31. data/lib/claude_swarm.rb +0 -67
  32. data/lib/swarm_cli/cli.rb +0 -201
  33. data/lib/swarm_cli/command_registry.rb +0 -61
  34. data/lib/swarm_cli/commands/mcp_serve.rb +0 -130
  35. data/lib/swarm_cli/commands/mcp_tools.rb +0 -148
  36. data/lib/swarm_cli/commands/migrate.rb +0 -55
  37. data/lib/swarm_cli/commands/run.rb +0 -173
  38. data/lib/swarm_cli/config_loader.rb +0 -98
  39. data/lib/swarm_cli/formatters/human_formatter.rb +0 -781
  40. data/lib/swarm_cli/formatters/json_formatter.rb +0 -51
  41. data/lib/swarm_cli/interactive_repl.rb +0 -924
  42. data/lib/swarm_cli/mcp_serve_options.rb +0 -44
  43. data/lib/swarm_cli/mcp_tools_options.rb +0 -59
  44. data/lib/swarm_cli/migrate_options.rb +0 -54
  45. data/lib/swarm_cli/migrator.rb +0 -132
  46. data/lib/swarm_cli/options.rb +0 -151
  47. data/lib/swarm_cli/ui/components/agent_badge.rb +0 -33
  48. data/lib/swarm_cli/ui/components/content_block.rb +0 -120
  49. data/lib/swarm_cli/ui/components/divider.rb +0 -57
  50. data/lib/swarm_cli/ui/components/panel.rb +0 -62
  51. data/lib/swarm_cli/ui/components/usage_stats.rb +0 -70
  52. data/lib/swarm_cli/ui/formatters/cost.rb +0 -49
  53. data/lib/swarm_cli/ui/formatters/number.rb +0 -58
  54. data/lib/swarm_cli/ui/formatters/text.rb +0 -77
  55. data/lib/swarm_cli/ui/formatters/time.rb +0 -73
  56. data/lib/swarm_cli/ui/icons.rb +0 -36
  57. data/lib/swarm_cli/ui/renderers/event_renderer.rb +0 -188
  58. data/lib/swarm_cli/ui/state/agent_color_cache.rb +0 -45
  59. data/lib/swarm_cli/ui/state/depth_tracker.rb +0 -40
  60. data/lib/swarm_cli/ui/state/spinner_manager.rb +0 -170
  61. data/lib/swarm_cli/ui/state/usage_tracker.rb +0 -62
  62. data/lib/swarm_cli/version.rb +0 -5
  63. data/lib/swarm_cli.rb +0 -46
  64. data/lib/swarm_sdk/agent/RETRY_LOGIC.md +0 -127
  65. data/lib/swarm_sdk/agent/builder.rb +0 -552
  66. data/lib/swarm_sdk/agent/chat.rb +0 -774
  67. data/lib/swarm_sdk/agent/chat_helpers/context_tracker.rb +0 -268
  68. data/lib/swarm_sdk/agent/chat_helpers/event_emitter.rb +0 -204
  69. data/lib/swarm_sdk/agent/chat_helpers/hook_integration.rb +0 -480
  70. data/lib/swarm_sdk/agent/chat_helpers/instrumentation.rb +0 -78
  71. data/lib/swarm_sdk/agent/chat_helpers/llm_configuration.rb +0 -233
  72. data/lib/swarm_sdk/agent/chat_helpers/logging_helpers.rb +0 -116
  73. data/lib/swarm_sdk/agent/chat_helpers/serialization.rb +0 -83
  74. data/lib/swarm_sdk/agent/chat_helpers/system_reminder_injector.rb +0 -136
  75. data/lib/swarm_sdk/agent/chat_helpers/system_reminders.rb +0 -79
  76. data/lib/swarm_sdk/agent/chat_helpers/token_tracking.rb +0 -98
  77. data/lib/swarm_sdk/agent/context.rb +0 -116
  78. data/lib/swarm_sdk/agent/context_manager.rb +0 -315
  79. data/lib/swarm_sdk/agent/definition.rb +0 -477
  80. data/lib/swarm_sdk/agent/llm_instrumentation_middleware.rb +0 -182
  81. data/lib/swarm_sdk/agent/system_prompt_builder.rb +0 -161
  82. data/lib/swarm_sdk/builders/base_builder.rb +0 -409
  83. data/lib/swarm_sdk/claude_code_agent_adapter.rb +0 -205
  84. data/lib/swarm_sdk/concerns/cleanupable.rb +0 -39
  85. data/lib/swarm_sdk/concerns/snapshotable.rb +0 -67
  86. data/lib/swarm_sdk/concerns/validatable.rb +0 -55
  87. data/lib/swarm_sdk/configuration/parser.rb +0 -353
  88. data/lib/swarm_sdk/configuration/translator.rb +0 -255
  89. data/lib/swarm_sdk/configuration.rb +0 -135
  90. data/lib/swarm_sdk/context_compactor/metrics.rb +0 -147
  91. data/lib/swarm_sdk/context_compactor/token_counter.rb +0 -106
  92. data/lib/swarm_sdk/context_compactor.rb +0 -335
  93. data/lib/swarm_sdk/context_management/builder.rb +0 -128
  94. data/lib/swarm_sdk/context_management/context.rb +0 -328
  95. data/lib/swarm_sdk/defaults.rb +0 -196
  96. data/lib/swarm_sdk/events_to_messages.rb +0 -199
  97. data/lib/swarm_sdk/hooks/adapter.rb +0 -359
  98. data/lib/swarm_sdk/hooks/context.rb +0 -197
  99. data/lib/swarm_sdk/hooks/definition.rb +0 -80
  100. data/lib/swarm_sdk/hooks/error.rb +0 -29
  101. data/lib/swarm_sdk/hooks/executor.rb +0 -146
  102. data/lib/swarm_sdk/hooks/registry.rb +0 -147
  103. data/lib/swarm_sdk/hooks/result.rb +0 -150
  104. data/lib/swarm_sdk/hooks/shell_executor.rb +0 -255
  105. data/lib/swarm_sdk/hooks/tool_call.rb +0 -35
  106. data/lib/swarm_sdk/hooks/tool_result.rb +0 -62
  107. data/lib/swarm_sdk/log_collector.rb +0 -227
  108. data/lib/swarm_sdk/log_stream.rb +0 -127
  109. data/lib/swarm_sdk/markdown_parser.rb +0 -75
  110. data/lib/swarm_sdk/model_aliases.json +0 -8
  111. data/lib/swarm_sdk/models.json +0 -1
  112. data/lib/swarm_sdk/models.rb +0 -120
  113. data/lib/swarm_sdk/node_context.rb +0 -245
  114. data/lib/swarm_sdk/observer/builder.rb +0 -81
  115. data/lib/swarm_sdk/observer/config.rb +0 -45
  116. data/lib/swarm_sdk/observer/manager.rb +0 -236
  117. data/lib/swarm_sdk/patterns/agent_observer.rb +0 -160
  118. data/lib/swarm_sdk/permissions/config.rb +0 -239
  119. data/lib/swarm_sdk/permissions/error_formatter.rb +0 -121
  120. data/lib/swarm_sdk/permissions/path_matcher.rb +0 -35
  121. data/lib/swarm_sdk/permissions/validator.rb +0 -173
  122. data/lib/swarm_sdk/permissions_builder.rb +0 -122
  123. data/lib/swarm_sdk/plugin.rb +0 -309
  124. data/lib/swarm_sdk/plugin_registry.rb +0 -101
  125. data/lib/swarm_sdk/proc_helpers.rb +0 -53
  126. data/lib/swarm_sdk/prompts/base_system_prompt.md.erb +0 -117
  127. data/lib/swarm_sdk/restore_result.rb +0 -65
  128. data/lib/swarm_sdk/result.rb +0 -123
  129. data/lib/swarm_sdk/snapshot.rb +0 -156
  130. data/lib/swarm_sdk/snapshot_from_events.rb +0 -397
  131. data/lib/swarm_sdk/state_restorer.rb +0 -476
  132. data/lib/swarm_sdk/state_snapshot.rb +0 -334
  133. data/lib/swarm_sdk/swarm/agent_initializer.rb +0 -683
  134. data/lib/swarm_sdk/swarm/all_agents_builder.rb +0 -167
  135. data/lib/swarm_sdk/swarm/builder.rb +0 -249
  136. data/lib/swarm_sdk/swarm/executor.rb +0 -213
  137. data/lib/swarm_sdk/swarm/hook_triggers.rb +0 -150
  138. data/lib/swarm_sdk/swarm/logging_callbacks.rb +0 -340
  139. data/lib/swarm_sdk/swarm/mcp_configurator.rb +0 -154
  140. data/lib/swarm_sdk/swarm/swarm_registry_builder.rb +0 -67
  141. data/lib/swarm_sdk/swarm/tool_configurator.rb +0 -358
  142. data/lib/swarm_sdk/swarm.rb +0 -717
  143. data/lib/swarm_sdk/swarm_loader.rb +0 -145
  144. data/lib/swarm_sdk/swarm_registry.rb +0 -136
  145. data/lib/swarm_sdk/tools/bash.rb +0 -282
  146. data/lib/swarm_sdk/tools/clock.rb +0 -44
  147. data/lib/swarm_sdk/tools/delegate.rb +0 -267
  148. data/lib/swarm_sdk/tools/document_converters/base_converter.rb +0 -83
  149. data/lib/swarm_sdk/tools/document_converters/docx_converter.rb +0 -99
  150. data/lib/swarm_sdk/tools/document_converters/html_converter.rb +0 -101
  151. data/lib/swarm_sdk/tools/document_converters/pdf_converter.rb +0 -78
  152. data/lib/swarm_sdk/tools/document_converters/xlsx_converter.rb +0 -194
  153. data/lib/swarm_sdk/tools/edit.rb +0 -145
  154. data/lib/swarm_sdk/tools/glob.rb +0 -166
  155. data/lib/swarm_sdk/tools/grep.rb +0 -235
  156. data/lib/swarm_sdk/tools/image_extractors/docx_image_extractor.rb +0 -43
  157. data/lib/swarm_sdk/tools/image_extractors/pdf_image_extractor.rb +0 -163
  158. data/lib/swarm_sdk/tools/image_formats/tiff_builder.rb +0 -65
  159. data/lib/swarm_sdk/tools/multi_edit.rb +0 -236
  160. data/lib/swarm_sdk/tools/path_resolver.rb +0 -92
  161. data/lib/swarm_sdk/tools/read.rb +0 -261
  162. data/lib/swarm_sdk/tools/registry.rb +0 -205
  163. data/lib/swarm_sdk/tools/scratchpad/scratchpad_list.rb +0 -117
  164. data/lib/swarm_sdk/tools/scratchpad/scratchpad_read.rb +0 -97
  165. data/lib/swarm_sdk/tools/scratchpad/scratchpad_write.rb +0 -108
  166. data/lib/swarm_sdk/tools/stores/read_tracker.rb +0 -96
  167. data/lib/swarm_sdk/tools/stores/scratchpad_storage.rb +0 -272
  168. data/lib/swarm_sdk/tools/stores/storage.rb +0 -142
  169. data/lib/swarm_sdk/tools/stores/todo_manager.rb +0 -65
  170. data/lib/swarm_sdk/tools/think.rb +0 -98
  171. data/lib/swarm_sdk/tools/todo_write.rb +0 -235
  172. data/lib/swarm_sdk/tools/web_fetch.rb +0 -262
  173. data/lib/swarm_sdk/tools/write.rb +0 -112
  174. data/lib/swarm_sdk/utils.rb +0 -68
  175. data/lib/swarm_sdk/validation_result.rb +0 -33
  176. data/lib/swarm_sdk/version.rb +0 -5
  177. data/lib/swarm_sdk/workflow/agent_config.rb +0 -79
  178. data/lib/swarm_sdk/workflow/builder.rb +0 -143
  179. data/lib/swarm_sdk/workflow/executor.rb +0 -497
  180. data/lib/swarm_sdk/workflow/node_builder.rb +0 -555
  181. data/lib/swarm_sdk/workflow/transformer_executor.rb +0 -249
  182. data/lib/swarm_sdk/workflow.rb +0 -554
  183. data/lib/swarm_sdk.rb +0 -524
  184. /data/lib/swarm_memory/{errors.rb → error.rb} +0 -0
@@ -1,205 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module SwarmSDK
4
- module Tools
5
- # Registry for built-in SwarmSDK tools
6
- #
7
- # Maps tool names (symbols) to their RubyLLM::Tool classes.
8
- # Provides validation, lookup, and factory functionality for tool registration.
9
- #
10
- # ## Tool Creation Pattern
11
- #
12
- # Tools register themselves with their creation requirements via the `tool_factory` method.
13
- # This eliminates the need for a giant case statement in ToolConfigurator.
14
- #
15
- # Tools fall into three categories:
16
- # 1. **No params**: Simple tools with no initialization requirements (Think, Clock)
17
- # 2. **Directory only**: Tools needing working directory (Bash, Grep, Glob)
18
- # 3. **Agent context**: Tools needing agent tracking (Read, Write, Edit, MultiEdit)
19
- # 4. **Scratchpad**: Tools needing scratchpad storage instance
20
- #
21
- # @example Adding a new tool with creation requirements
22
- # # In the tool class:
23
- # class MyTool < RubyLLM::Tool
24
- # def self.creation_requirements
25
- # [:agent_name, :directory]
26
- # end
27
- # end
28
- #
29
- # # In registry:
30
- # BUILTIN_TOOLS = {
31
- # MyTool: SwarmSDK::Tools::MyTool,
32
- # }
33
- #
34
- # Note: Plugin-provided tools (e.g., memory tools) are NOT in this registry.
35
- # They are registered via SwarmSDK::PluginRegistry instead.
36
- class Registry
37
- # All available built-in tools
38
- #
39
- # Maps tool names to their classes. The class must respond to `creation_requirements`
40
- # to specify what parameters are needed for instantiation.
41
- BUILTIN_TOOLS = {
42
- Read: SwarmSDK::Tools::Read,
43
- Write: SwarmSDK::Tools::Write,
44
- Edit: SwarmSDK::Tools::Edit,
45
- MultiEdit: SwarmSDK::Tools::MultiEdit,
46
- Bash: SwarmSDK::Tools::Bash,
47
- Grep: SwarmSDK::Tools::Grep,
48
- Glob: SwarmSDK::Tools::Glob,
49
- TodoWrite: SwarmSDK::Tools::TodoWrite,
50
- ScratchpadWrite: :scratchpad, # Requires scratchpad storage instance
51
- ScratchpadRead: :scratchpad, # Requires scratchpad storage instance
52
- ScratchpadList: :scratchpad, # Requires scratchpad storage instance
53
- Think: SwarmSDK::Tools::Think,
54
- WebFetch: SwarmSDK::Tools::WebFetch,
55
- Clock: SwarmSDK::Tools::Clock,
56
- }.freeze
57
-
58
- class << self
59
- # Get tool class by name
60
- #
61
- # Note: Plugin-provided tools are NOT returned by this method.
62
- # They are managed by SwarmSDK::PluginRegistry instead.
63
- #
64
- # @param name [Symbol, String] Tool name
65
- # @return [Class, Symbol, nil] Tool class, :scratchpad marker, or nil if not found
66
- def get(name)
67
- name_sym = name.to_sym
68
- BUILTIN_TOOLS[name_sym]
69
- end
70
-
71
- # Create a tool instance using the Factory Pattern
72
- #
73
- # Uses the tool's `creation_requirements` class method to determine
74
- # what parameters to pass to the constructor.
75
- #
76
- # @param name [Symbol, String] Tool name
77
- # @param context [Hash] Available context for tool creation
78
- # @option context [Symbol] :agent_name Agent identifier
79
- # @option context [String] :directory Agent's working directory
80
- # @option context [Object] :scratchpad_storage Scratchpad storage instance
81
- # @return [RubyLLM::Tool] Instantiated tool
82
- # @raise [ConfigurationError] If tool is unknown or has unmet requirements
83
- def create(name, context = {})
84
- name_sym = name.to_sym
85
- tool_entry = BUILTIN_TOOLS[name_sym]
86
-
87
- raise ConfigurationError, "Unknown tool: #{name}" unless tool_entry
88
-
89
- # Handle scratchpad tools specially (they use factory methods)
90
- if tool_entry == :scratchpad
91
- return create_scratchpad_tool(name_sym, context[:scratchpad_storage])
92
- end
93
-
94
- # Get the tool class and its requirements
95
- tool_class = tool_entry
96
-
97
- # Check if tool defines creation requirements
98
- if tool_class.respond_to?(:creation_requirements)
99
- requirements = tool_class.creation_requirements
100
- params = extract_params(requirements, context, name)
101
- tool_class.new(**params)
102
- else
103
- # No requirements - simple instantiation
104
- tool_class.new
105
- end
106
- end
107
-
108
- # Get multiple tool classes by names
109
- #
110
- # @param names [Array<Symbol, String>] Tool names
111
- # @return [Array<Class>] Array of tool classes
112
- # @raise [ConfigurationError] If any tool name is invalid
113
- def get_many(names)
114
- names.map do |name|
115
- tool_class = get(name)
116
- unless tool_class
117
- raise ConfigurationError,
118
- "Unknown tool: #{name}. Available tools: #{available_names.join(", ")}"
119
- end
120
-
121
- tool_class
122
- end
123
- end
124
-
125
- # Check if a tool exists
126
- #
127
- # Note: Only checks built-in tools. Plugin-provided tools are checked
128
- # via SwarmSDK::PluginRegistry.plugin_tool?() instead.
129
- #
130
- # @param name [Symbol, String] Tool name
131
- # @return [Boolean]
132
- def exists?(name)
133
- name_sym = name.to_sym
134
- BUILTIN_TOOLS.key?(name_sym)
135
- end
136
-
137
- # Get all available built-in tool names
138
- #
139
- # Note: Does NOT include plugin-provided tools. To get all available tools
140
- # including plugins, combine with SwarmSDK::PluginRegistry.tools.
141
- #
142
- # @return [Array<Symbol>]
143
- def available_names
144
- BUILTIN_TOOLS.keys
145
- end
146
-
147
- # Validate tool names
148
- #
149
- # @param names [Array<Symbol, String>] Tool names to validate
150
- # @return [Array<Symbol>] Invalid tool names
151
- def validate(names)
152
- names.reject { |name| exists?(name) }
153
- end
154
-
155
- private
156
-
157
- # Extract required parameters from context
158
- #
159
- # @param requirements [Array<Symbol>] Required parameter names
160
- # @param context [Hash] Available context
161
- # @param tool_name [Symbol] Tool name for error messages
162
- # @return [Hash] Parameters to pass to tool constructor
163
- # @raise [ConfigurationError] If required parameter is missing
164
- def extract_params(requirements, context, tool_name)
165
- params = {}
166
-
167
- requirements.each do |req|
168
- unless context.key?(req)
169
- raise ConfigurationError,
170
- "Tool #{tool_name} requires #{req} but it was not provided in context"
171
- end
172
-
173
- params[req] = context[req]
174
- end
175
-
176
- params
177
- end
178
-
179
- # Create a scratchpad tool using its factory method
180
- #
181
- # @param name [Symbol] Scratchpad tool name
182
- # @param storage [Object] Scratchpad storage instance
183
- # @return [RubyLLM::Tool] Instantiated scratchpad tool
184
- # @raise [ConfigurationError] If storage is not provided
185
- def create_scratchpad_tool(name, storage)
186
- unless storage
187
- raise ConfigurationError,
188
- "Scratchpad tool #{name} requires scratchpad_storage in context"
189
- end
190
-
191
- case name
192
- when :ScratchpadWrite
193
- Tools::Scratchpad::ScratchpadWrite.create_for_scratchpad(storage)
194
- when :ScratchpadRead
195
- Tools::Scratchpad::ScratchpadRead.create_for_scratchpad(storage)
196
- when :ScratchpadList
197
- Tools::Scratchpad::ScratchpadList.create_for_scratchpad(storage)
198
- else
199
- raise ConfigurationError, "Unknown scratchpad tool: #{name}"
200
- end
201
- end
202
- end
203
- end
204
- end
205
- end
@@ -1,117 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module SwarmSDK
4
- module Tools
5
- module Scratchpad
6
- # Tool for listing scratchpad entries
7
- #
8
- # Shows all entries in the shared scratchpad with their metadata.
9
- # All agents in the swarm share the same scratchpad.
10
- class ScratchpadList < RubyLLM::Tool
11
- define_method(:name) { "ScratchpadList" }
12
-
13
- description <<~DESC
14
- List all entries in scratchpad with their metadata.
15
-
16
- ## When to Use ScratchpadList
17
-
18
- Use ScratchpadList to:
19
- - Discover what content is available in the scratchpad
20
- - Check what other agents have stored
21
- - Find relevant entries before reading them
22
- - Review all stored outputs and analysis
23
- - Check entry sizes and last update times
24
-
25
- ## Best Practices
26
-
27
- - Use this before ScratchpadRead if you don't know what's stored
28
- - Filter by prefix to narrow down results (e.g., 'notes/' lists all notes)
29
- - Shows path, title, size, and last updated time for each entry
30
- - Any agent can see all scratchpad entries
31
- - Helps coordinate multi-agent workflows
32
-
33
- ## Examples
34
-
35
- - List all entries: (no prefix parameter)
36
- - List notes only: prefix='notes/'
37
- - List analysis results: prefix='analysis/'
38
- DESC
39
-
40
- param :prefix,
41
- desc: "Optional prefix to filter entries (e.g., 'notes/' to list all entries under notes/)",
42
- required: false
43
-
44
- class << self
45
- # Create a ScratchpadList tool for a specific scratchpad storage instance
46
- #
47
- # @param scratchpad_storage [Stores::ScratchpadStorage] Shared scratchpad storage instance
48
- # @return [ScratchpadList] Tool instance
49
- def create_for_scratchpad(scratchpad_storage)
50
- new(scratchpad_storage)
51
- end
52
- end
53
-
54
- # Initialize with scratchpad storage instance
55
- #
56
- # @param scratchpad_storage [Stores::ScratchpadStorage] Shared scratchpad storage instance
57
- def initialize(scratchpad_storage)
58
- super() # Call RubyLLM::Tool's initialize
59
- @scratchpad_storage = scratchpad_storage
60
- end
61
-
62
- # Execute the tool
63
- #
64
- # @param prefix [String, nil] Optional prefix to filter entries
65
- # @return [String] Formatted list of entries
66
- def execute(prefix: nil)
67
- entries = scratchpad_storage.list(prefix: prefix)
68
-
69
- if entries.empty?
70
- prefix_msg = prefix ? " with prefix '#{prefix}'" : ""
71
- return "No entries found in scratchpad#{prefix_msg}"
72
- end
73
-
74
- result = []
75
- prefix_msg = prefix ? " with prefix '#{prefix}'" : ""
76
- result << "Scratchpad entries#{prefix_msg} (#{entries.size} #{entries.size == 1 ? "entry" : "entries"}):"
77
- result << ""
78
-
79
- entries.each do |entry|
80
- time_str = entry[:updated_at].strftime("%Y-%m-%d %H:%M:%S")
81
- result << " scratchpad://#{entry[:path]}"
82
- result << " Title: #{entry[:title]}"
83
- result << " Size: #{format_bytes(entry[:size])}"
84
- result << " Updated: #{time_str}"
85
- result << ""
86
- end
87
-
88
- result.join("\n").rstrip
89
- rescue ArgumentError => e
90
- validation_error(e.message)
91
- end
92
-
93
- private
94
-
95
- attr_reader :scratchpad_storage
96
-
97
- def validation_error(message)
98
- "<tool_use_error>InputValidationError: #{message}</tool_use_error>"
99
- end
100
-
101
- # Format bytes to human-readable size
102
- #
103
- # @param bytes [Integer] Number of bytes
104
- # @return [String] Formatted size
105
- def format_bytes(bytes)
106
- if bytes >= 1_000_000
107
- "#{(bytes.to_f / 1_000_000).round(1)}MB"
108
- elsif bytes >= 1_000
109
- "#{(bytes.to_f / 1_000).round(1)}KB"
110
- else
111
- "#{bytes}B"
112
- end
113
- end
114
- end
115
- end
116
- end
117
- end
@@ -1,97 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module SwarmSDK
4
- module Tools
5
- module Scratchpad
6
- # Tool for reading content from scratchpad storage
7
- #
8
- # Retrieves content stored by any agent using scratchpad_write.
9
- # All agents in the swarm share the same scratchpad.
10
- class ScratchpadRead < RubyLLM::Tool
11
- define_method(:name) { "ScratchpadRead" }
12
-
13
- description <<~DESC
14
- Read content from scratchpad.
15
-
16
- ## When to Use ScratchpadRead
17
-
18
- Use ScratchpadRead to:
19
- - Retrieve previously stored content and outputs
20
- - Access detailed analysis or results from earlier steps
21
- - Read messages or notes left by other agents
22
- - Access cached computed data
23
- - Retrieve content that was too long for direct responses
24
-
25
- ## Best Practices
26
-
27
- - Any agent can read any scratchpad content
28
- - Content is returned with line numbers for easy reference
29
- - Use ScratchpadList first if you don't know what's stored
30
- - Scratchpad data is temporary and lost when swarm ends
31
- - For persistent data, use MemoryRead instead
32
-
33
- ## Examples
34
-
35
- - Read status: file_path='status'
36
- - Read analysis: file_path='api_analysis'
37
- - Read agent notes: file_path='notes/backend'
38
- DESC
39
-
40
- param :file_path,
41
- desc: "Path to read from scratchpad (e.g., 'status', 'result', 'notes/agent_x')",
42
- required: true
43
-
44
- class << self
45
- # Create a ScratchpadRead tool for a specific scratchpad storage instance
46
- #
47
- # @param scratchpad_storage [Stores::ScratchpadStorage] Shared scratchpad storage instance
48
- # @return [ScratchpadRead] Tool instance
49
- def create_for_scratchpad(scratchpad_storage)
50
- new(scratchpad_storage)
51
- end
52
- end
53
-
54
- # Initialize with scratchpad storage instance
55
- #
56
- # @param scratchpad_storage [Stores::ScratchpadStorage] Shared scratchpad storage instance
57
- def initialize(scratchpad_storage)
58
- super() # Call RubyLLM::Tool's initialize
59
- @scratchpad_storage = scratchpad_storage
60
- end
61
-
62
- # Execute the tool
63
- #
64
- # @param file_path [String] Path to read from
65
- # @return [String] Content at the path with line numbers, or error message
66
- def execute(file_path:)
67
- content = scratchpad_storage.read(file_path: file_path)
68
- format_with_line_numbers(content)
69
- rescue ArgumentError => e
70
- validation_error(e.message)
71
- end
72
-
73
- private
74
-
75
- attr_reader :scratchpad_storage
76
-
77
- def validation_error(message)
78
- "<tool_use_error>InputValidationError: #{message}</tool_use_error>"
79
- end
80
-
81
- # Format content with line numbers (same format as Read tool)
82
- #
83
- # @param content [String] Content to format
84
- # @return [String] Content with line numbers
85
- def format_with_line_numbers(content)
86
- lines = content.lines
87
- output_lines = lines.each_with_index.map do |line, idx|
88
- line_number = idx + 1
89
- display_line = line.chomp
90
- "#{line_number.to_s.rjust(6)}→#{display_line}"
91
- end
92
- output_lines.join("\n")
93
- end
94
- end
95
- end
96
- end
97
- end
@@ -1,108 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module SwarmSDK
4
- module Tools
5
- module Scratchpad
6
- # Tool for writing content to scratchpad storage
7
- #
8
- # Stores content in volatile, shared storage for temporary communication.
9
- # All agents in the swarm share the same scratchpad.
10
- # Data is lost when the process ends (not persisted).
11
- class ScratchpadWrite < RubyLLM::Tool
12
- define_method(:name) { "ScratchpadWrite" }
13
-
14
- description <<~DESC
15
- Store content in scratchpad for temporary cross-agent communication.
16
-
17
- ## When to Use Scratchpad
18
-
19
- Use ScratchpadWrite to:
20
- - Store detailed outputs, analysis, or results that are too long for direct responses
21
- - Share information that would otherwise clutter your responses
22
- - Store intermediate results during multi-step tasks
23
- - Leave coordination messages for other agents
24
- - Cache computed data for quick retrieval
25
-
26
- ## Best Practices
27
-
28
- - Choose simple, descriptive paths: 'status', 'result', 'notes/agent_x'
29
- - Use hierarchical paths for organization: 'analysis/step1', 'analysis/step2'
30
- - Keep entries focused - one piece of information per entry
31
- - Any agent can read scratchpad content
32
- - Data is lost when the swarm ends (use MemoryWrite for persistent storage)
33
- - Maximum 1MB per entry
34
-
35
- ## Examples
36
-
37
- Good paths: 'status', 'api_analysis', 'test_results', 'notes/backend'
38
- Bad paths: 'scratch/temp/file123.txt', 'output.log'
39
- DESC
40
-
41
- param :file_path,
42
- desc: "Simple path for the content (e.g., 'status', 'result', 'notes/agent_x')",
43
- required: true
44
-
45
- param :content,
46
- desc: "Content to store in scratchpad (max 1MB per entry)",
47
- required: true
48
-
49
- param :title,
50
- desc: "Brief title describing the content",
51
- required: true
52
-
53
- class << self
54
- # Create a ScratchpadWrite tool for a specific scratchpad storage instance
55
- #
56
- # @param scratchpad_storage [Stores::ScratchpadStorage] Shared scratchpad storage instance
57
- # @return [ScratchpadWrite] Tool instance
58
- def create_for_scratchpad(scratchpad_storage)
59
- new(scratchpad_storage)
60
- end
61
- end
62
-
63
- # Initialize with scratchpad storage instance
64
- #
65
- # @param scratchpad_storage [Stores::ScratchpadStorage] Shared scratchpad storage instance
66
- def initialize(scratchpad_storage)
67
- super() # Call RubyLLM::Tool's initialize
68
- @scratchpad_storage = scratchpad_storage
69
- end
70
-
71
- # Execute the tool
72
- #
73
- # @param file_path [String] Path to store content
74
- # @param content [String] Content to store
75
- # @param title [String] Brief title
76
- # @return [String] Success message with path and size
77
- def execute(file_path:, content:, title:)
78
- entry = scratchpad_storage.write(file_path: file_path, content: content, title: title)
79
- "Stored at scratchpad://#{file_path} (#{format_bytes(entry.size)})"
80
- rescue ArgumentError => e
81
- validation_error(e.message)
82
- end
83
-
84
- private
85
-
86
- attr_reader :scratchpad_storage
87
-
88
- def validation_error(message)
89
- "<tool_use_error>InputValidationError: #{message}</tool_use_error>"
90
- end
91
-
92
- # Format bytes to human-readable size
93
- #
94
- # @param bytes [Integer] Number of bytes
95
- # @return [String] Formatted size
96
- def format_bytes(bytes)
97
- if bytes >= 1_000_000
98
- "#{(bytes.to_f / 1_000_000).round(1)}MB"
99
- elsif bytes >= 1_000
100
- "#{(bytes.to_f / 1_000).round(1)}KB"
101
- else
102
- "#{bytes}B"
103
- end
104
- end
105
- end
106
- end
107
- end
108
- end
@@ -1,96 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module SwarmSDK
4
- module Tools
5
- module Stores
6
- # ReadTracker manages read-file tracking for all agents with content digest verification
7
- #
8
- # This module maintains a global registry of which files each agent has read
9
- # during their conversation along with SHA256 digests of the content. This enables
10
- # enforcement of the "read-before-write" and "read-before-edit" rules that ensure
11
- # agents have context before modifying files, AND prevents editing files that have
12
- # changed externally since being read.
13
- #
14
- # Each agent maintains an independent map of read files to content digests.
15
- module ReadTracker
16
- @read_files = {} # { agent_id => { file_path => sha256_digest } }
17
- @mutex = Mutex.new
18
-
19
- class << self
20
- # Register that an agent has read a file with content digest
21
- #
22
- # @param agent_id [Symbol] The agent identifier
23
- # @param file_path [String] The absolute path to the file
24
- # @param content [String] File content (for digest calculation)
25
- # @return [String] The calculated SHA256 digest
26
- def register_read(agent_id, file_path, content)
27
- @mutex.synchronize do
28
- @read_files[agent_id] ||= {}
29
- digest = Digest::SHA256.hexdigest(content)
30
- @read_files[agent_id][File.expand_path(file_path)] = digest
31
- digest
32
- end
33
- end
34
-
35
- # Check if an agent has read a file AND content hasn't changed
36
- #
37
- # @param agent_id [Symbol] The agent identifier
38
- # @param file_path [String] The absolute path to the file
39
- # @return [Boolean] true if agent read file and content matches
40
- def file_read?(agent_id, file_path)
41
- @mutex.synchronize do
42
- return false unless @read_files[agent_id]
43
-
44
- expanded_path = File.expand_path(file_path)
45
- stored_digest = @read_files[agent_id][expanded_path]
46
- return false unless stored_digest
47
-
48
- # Check if file still exists and matches stored digest
49
- return false unless File.exist?(expanded_path)
50
-
51
- current_digest = Digest::SHA256.hexdigest(File.read(expanded_path))
52
- current_digest == stored_digest
53
- end
54
- end
55
-
56
- # Get all read files with digests for snapshot
57
- #
58
- # @param agent_id [Symbol] The agent identifier
59
- # @return [Hash] { file_path => digest }
60
- def get_read_files(agent_id)
61
- @mutex.synchronize do
62
- @read_files[agent_id]&.dup || {}
63
- end
64
- end
65
-
66
- # Restore read files with digests from snapshot
67
- #
68
- # @param agent_id [Symbol] The agent identifier
69
- # @param files_with_digests [Hash] { file_path => digest }
70
- # @return [void]
71
- def restore_read_files(agent_id, files_with_digests)
72
- @mutex.synchronize do
73
- @read_files[agent_id] = files_with_digests.dup
74
- end
75
- end
76
-
77
- # Clear read history for an agent (useful for testing)
78
- #
79
- # @param agent_id [Symbol] The agent identifier
80
- def clear(agent_id)
81
- @mutex.synchronize do
82
- @read_files.delete(agent_id)
83
- end
84
- end
85
-
86
- # Clear all read history (useful for testing)
87
- def clear_all
88
- @mutex.synchronize do
89
- @read_files.clear
90
- end
91
- end
92
- end
93
- end
94
- end
95
- end
96
- end