swarm_memory 2.1.3 → 2.1.4
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.
- checksums.yaml +4 -4
- data/lib/claude_swarm/claude_mcp_server.rb +1 -0
- data/lib/claude_swarm/cli.rb +5 -18
- data/lib/claude_swarm/configuration.rb +2 -15
- data/lib/claude_swarm/mcp_generator.rb +1 -0
- data/lib/claude_swarm/openai/chat_completion.rb +4 -12
- data/lib/claude_swarm/openai/executor.rb +3 -1
- data/lib/claude_swarm/openai/responses.rb +13 -32
- data/lib/claude_swarm/version.rb +1 -1
- data/lib/swarm_cli/commands/run.rb +2 -2
- data/lib/swarm_cli/config_loader.rb +11 -11
- data/lib/swarm_cli/formatters/human_formatter.rb +70 -0
- data/lib/swarm_cli/interactive_repl.rb +11 -5
- data/lib/swarm_cli/ui/icons.rb +0 -23
- data/lib/swarm_cli/version.rb +1 -1
- data/lib/swarm_memory/adapters/filesystem_adapter.rb +11 -34
- data/lib/swarm_memory/integration/sdk_plugin.rb +87 -7
- data/lib/swarm_memory/version.rb +1 -1
- data/lib/swarm_memory.rb +1 -1
- data/lib/swarm_sdk/agent/builder.rb +58 -0
- data/lib/swarm_sdk/agent/chat.rb +527 -1059
- data/lib/swarm_sdk/agent/{chat → chat_helpers}/context_tracker.rb +9 -88
- data/lib/swarm_sdk/agent/chat_helpers/event_emitter.rb +204 -0
- data/lib/swarm_sdk/agent/{chat → chat_helpers}/hook_integration.rb +111 -44
- data/lib/swarm_sdk/agent/chat_helpers/instrumentation.rb +78 -0
- data/lib/swarm_sdk/agent/chat_helpers/llm_configuration.rb +233 -0
- data/lib/swarm_sdk/agent/{chat → chat_helpers}/logging_helpers.rb +1 -1
- data/lib/swarm_sdk/agent/chat_helpers/serialization.rb +83 -0
- data/lib/swarm_sdk/agent/{chat → chat_helpers}/system_reminder_injector.rb +12 -12
- data/lib/swarm_sdk/agent/chat_helpers/system_reminders.rb +79 -0
- data/lib/swarm_sdk/agent/chat_helpers/token_tracking.rb +98 -0
- data/lib/swarm_sdk/agent/context.rb +2 -2
- data/lib/swarm_sdk/agent/definition.rb +66 -154
- data/lib/swarm_sdk/agent/llm_instrumentation_middleware.rb +4 -2
- data/lib/swarm_sdk/agent/system_prompt_builder.rb +161 -0
- data/lib/swarm_sdk/builders/base_builder.rb +409 -0
- data/lib/swarm_sdk/concerns/cleanupable.rb +39 -0
- data/lib/swarm_sdk/concerns/snapshotable.rb +67 -0
- data/lib/swarm_sdk/concerns/validatable.rb +55 -0
- data/lib/swarm_sdk/configuration/parser.rb +353 -0
- data/lib/swarm_sdk/configuration/translator.rb +255 -0
- data/lib/swarm_sdk/configuration.rb +65 -543
- data/lib/swarm_sdk/context_compactor/token_counter.rb +3 -3
- data/lib/swarm_sdk/context_compactor.rb +6 -11
- data/lib/swarm_sdk/context_management/builder.rb +128 -0
- data/lib/swarm_sdk/context_management/context.rb +328 -0
- data/lib/swarm_sdk/defaults.rb +196 -0
- data/lib/swarm_sdk/events_to_messages.rb +18 -0
- data/lib/swarm_sdk/hooks/shell_executor.rb +2 -1
- data/lib/swarm_sdk/log_collector.rb +179 -29
- data/lib/swarm_sdk/log_stream.rb +29 -0
- data/lib/swarm_sdk/node_context.rb +1 -1
- data/lib/swarm_sdk/observer/builder.rb +81 -0
- data/lib/swarm_sdk/observer/config.rb +45 -0
- data/lib/swarm_sdk/observer/manager.rb +236 -0
- data/lib/swarm_sdk/patterns/agent_observer.rb +160 -0
- data/lib/swarm_sdk/plugin.rb +93 -3
- data/lib/swarm_sdk/snapshot.rb +6 -6
- data/lib/swarm_sdk/snapshot_from_events.rb +13 -2
- data/lib/swarm_sdk/state_restorer.rb +136 -151
- data/lib/swarm_sdk/state_snapshot.rb +65 -100
- data/lib/swarm_sdk/swarm/agent_initializer.rb +180 -136
- data/lib/swarm_sdk/swarm/builder.rb +44 -578
- data/lib/swarm_sdk/swarm/executor.rb +213 -0
- data/lib/swarm_sdk/swarm/hook_triggers.rb +150 -0
- data/lib/swarm_sdk/swarm/logging_callbacks.rb +340 -0
- data/lib/swarm_sdk/swarm/mcp_configurator.rb +7 -4
- data/lib/swarm_sdk/swarm/tool_configurator.rb +42 -138
- data/lib/swarm_sdk/swarm.rb +137 -679
- data/lib/swarm_sdk/tools/bash.rb +11 -3
- data/lib/swarm_sdk/tools/delegate.rb +61 -43
- data/lib/swarm_sdk/tools/edit.rb +8 -13
- data/lib/swarm_sdk/tools/glob.rb +9 -1
- data/lib/swarm_sdk/tools/grep.rb +7 -0
- data/lib/swarm_sdk/tools/multi_edit.rb +15 -11
- data/lib/swarm_sdk/tools/path_resolver.rb +51 -2
- data/lib/swarm_sdk/tools/read.rb +11 -13
- data/lib/swarm_sdk/tools/registry.rb +122 -10
- data/lib/swarm_sdk/tools/stores/scratchpad_storage.rb +8 -5
- data/lib/swarm_sdk/tools/stores/storage.rb +0 -6
- data/lib/swarm_sdk/tools/todo_write.rb +7 -0
- data/lib/swarm_sdk/tools/web_fetch.rb +3 -2
- data/lib/swarm_sdk/tools/write.rb +8 -13
- data/lib/swarm_sdk/version.rb +1 -1
- data/lib/swarm_sdk/{node → workflow}/agent_config.rb +1 -1
- data/lib/swarm_sdk/workflow/builder.rb +143 -0
- data/lib/swarm_sdk/workflow/executor.rb +497 -0
- data/lib/swarm_sdk/{node/builder.rb → workflow/node_builder.rb} +3 -3
- data/lib/swarm_sdk/{node → workflow}/transformer_executor.rb +3 -2
- data/lib/swarm_sdk/{node_orchestrator.rb → workflow.rb} +152 -456
- data/lib/swarm_sdk.rb +33 -3
- metadata +37 -14
- data/lib/swarm_memory/chat_extension.rb +0 -34
- data/lib/swarm_sdk/providers/openai_with_responses.rb +0 -589
|
@@ -40,7 +40,7 @@ module SwarmSDK
|
|
|
40
40
|
# Fetch tools from MCP server and register with chat
|
|
41
41
|
# Tools are already in RubyLLM::Tool format
|
|
42
42
|
tools = client.tools
|
|
43
|
-
tools.each { |tool| chat.
|
|
43
|
+
tools.each { |tool| chat.add_tool(tool) }
|
|
44
44
|
|
|
45
45
|
RubyLLM.logger.debug("SwarmSDK: Registered #{tools.size} tools from MCP server '#{server_config[:name]}' for agent #{agent_name}")
|
|
46
46
|
rescue StandardError => e
|
|
@@ -138,13 +138,16 @@ module SwarmSDK
|
|
|
138
138
|
# @param config [Hash] MCP server configuration
|
|
139
139
|
# @return [Hash] Streamable configuration
|
|
140
140
|
def build_streamable_config(config)
|
|
141
|
-
{
|
|
141
|
+
streamable_config = {
|
|
142
142
|
url: config[:url],
|
|
143
143
|
headers: config[:headers] || {},
|
|
144
144
|
version: config[:version]&.to_sym || :http2,
|
|
145
|
-
oauth: config[:oauth],
|
|
146
|
-
rate_limit: config[:rate_limit],
|
|
147
145
|
}
|
|
146
|
+
|
|
147
|
+
# Only include rate_limit if present
|
|
148
|
+
streamable_config[:rate_limit] = config[:rate_limit] if config[:rate_limit]
|
|
149
|
+
|
|
150
|
+
streamable_config
|
|
148
151
|
end
|
|
149
152
|
end
|
|
150
153
|
end
|
|
@@ -57,6 +57,9 @@ module SwarmSDK
|
|
|
57
57
|
|
|
58
58
|
# Create a tool instance by name
|
|
59
59
|
#
|
|
60
|
+
# Uses the Registry factory pattern to instantiate tools based on their
|
|
61
|
+
# declared requirements. This eliminates the need for a giant case statement.
|
|
62
|
+
#
|
|
60
63
|
# File tools and TodoWrite require agent context for tracking state.
|
|
61
64
|
# Scratchpad tools require shared scratchpad instance.
|
|
62
65
|
# Plugin tools are delegated to their respective plugins.
|
|
@@ -77,47 +80,14 @@ module SwarmSDK
|
|
|
77
80
|
return create_plugin_tool(tool_name_sym, agent_name, directory, chat, agent_definition)
|
|
78
81
|
end
|
|
79
82
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
Tools::Edit.new(agent_name: agent_name, directory: directory)
|
|
87
|
-
when :MultiEdit
|
|
88
|
-
Tools::MultiEdit.new(agent_name: agent_name, directory: directory)
|
|
89
|
-
when :Bash
|
|
90
|
-
Tools::Bash.new(directory: directory)
|
|
91
|
-
when :Glob
|
|
92
|
-
Tools::Glob.new(directory: directory)
|
|
93
|
-
when :Grep
|
|
94
|
-
Tools::Grep.new(directory: directory)
|
|
95
|
-
when :TodoWrite
|
|
96
|
-
Tools::TodoWrite.new(agent_name: agent_name) # TodoWrite doesn't need directory
|
|
97
|
-
when :ScratchpadWrite
|
|
98
|
-
Tools::Scratchpad::ScratchpadWrite.create_for_scratchpad(@scratchpad_storage)
|
|
99
|
-
when :ScratchpadRead
|
|
100
|
-
Tools::Scratchpad::ScratchpadRead.create_for_scratchpad(@scratchpad_storage)
|
|
101
|
-
when :ScratchpadList
|
|
102
|
-
Tools::Scratchpad::ScratchpadList.create_for_scratchpad(@scratchpad_storage)
|
|
103
|
-
when :Think
|
|
104
|
-
Tools::Think.new
|
|
105
|
-
when :Clock
|
|
106
|
-
Tools::Clock.new
|
|
107
|
-
else
|
|
108
|
-
# Regular tools - get class from registry and instantiate
|
|
109
|
-
tool_class = Tools::Registry.get(tool_name_sym)
|
|
110
|
-
raise ConfigurationError, "Unknown tool: #{tool_name}" unless tool_class
|
|
111
|
-
|
|
112
|
-
# Check if tool is marked as :special but not handled in case statement
|
|
113
|
-
if tool_class == :special
|
|
114
|
-
raise ConfigurationError,
|
|
115
|
-
"Tool '#{tool_name}' requires special initialization but is not handled in create_tool_instance. " \
|
|
116
|
-
"This is a bug - #{tool_name} should be added to the case statement above."
|
|
117
|
-
end
|
|
83
|
+
# Use Registry factory pattern - tools declare their own requirements
|
|
84
|
+
context = {
|
|
85
|
+
agent_name: agent_name,
|
|
86
|
+
directory: directory,
|
|
87
|
+
scratchpad_storage: @scratchpad_storage,
|
|
88
|
+
}
|
|
118
89
|
|
|
119
|
-
|
|
120
|
-
end
|
|
90
|
+
Tools::Registry.create(tool_name_sym, context)
|
|
121
91
|
end
|
|
122
92
|
|
|
123
93
|
# Wrap a tool instance with permissions validator if configured
|
|
@@ -171,14 +141,8 @@ module SwarmSDK
|
|
|
171
141
|
# Create tool instance
|
|
172
142
|
tool_instance = create_tool_instance(tool_name, agent_name, agent_definition.directory)
|
|
173
143
|
|
|
174
|
-
# Wrap with permissions
|
|
175
|
-
tool_instance
|
|
176
|
-
tool_instance,
|
|
177
|
-
permissions_config,
|
|
178
|
-
agent_definition,
|
|
179
|
-
)
|
|
180
|
-
|
|
181
|
-
chat.with_tool(tool_instance)
|
|
144
|
+
# Wrap with permissions and add to chat
|
|
145
|
+
wrap_and_add_tool(chat, tool_instance, permissions_config, agent_definition)
|
|
182
146
|
end
|
|
183
147
|
end
|
|
184
148
|
|
|
@@ -225,19 +189,36 @@ module SwarmSDK
|
|
|
225
189
|
return if tool_disabled?(tool_name, agent_definition.disable_default_tools)
|
|
226
190
|
|
|
227
191
|
tool_instance = create_tool_instance(tool_name, agent_name, agent_definition.directory)
|
|
192
|
+
permissions_config = resolve_default_permissions(tool_name, agent_definition)
|
|
228
193
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
agent_definition.default_permissions[tool_name]
|
|
194
|
+
wrap_and_add_tool(chat, tool_instance, permissions_config, agent_definition)
|
|
195
|
+
end
|
|
232
196
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
197
|
+
# Wrap tool with permissions and add to chat
|
|
198
|
+
#
|
|
199
|
+
# This is the common pattern for registering tools:
|
|
200
|
+
# 1. Wrap with permissions validator (if configured)
|
|
201
|
+
# 2. Add to chat
|
|
202
|
+
#
|
|
203
|
+
# @param chat [Agent::Chat] The chat instance
|
|
204
|
+
# @param tool_instance [RubyLLM::Tool] Tool instance
|
|
205
|
+
# @param permissions_config [Hash, nil] Permissions configuration
|
|
206
|
+
# @param agent_definition [Agent::Definition] Agent definition
|
|
207
|
+
# @return [void]
|
|
208
|
+
def wrap_and_add_tool(chat, tool_instance, permissions_config, agent_definition)
|
|
209
|
+
tool_instance = wrap_tool_with_permissions(tool_instance, permissions_config, agent_definition)
|
|
210
|
+
chat.add_tool(tool_instance)
|
|
211
|
+
end
|
|
239
212
|
|
|
240
|
-
|
|
213
|
+
# Resolve permissions for a default/plugin tool
|
|
214
|
+
#
|
|
215
|
+
# Looks up permissions in agent-specific config first, falls back to global defaults.
|
|
216
|
+
#
|
|
217
|
+
# @param tool_name [Symbol] Tool name
|
|
218
|
+
# @param agent_definition [Agent::Definition] Agent definition
|
|
219
|
+
# @return [Hash, nil] Permissions configuration or nil
|
|
220
|
+
def resolve_default_permissions(tool_name, agent_definition)
|
|
221
|
+
agent_definition.agent_permissions[tool_name] || agent_definition.default_permissions[tool_name]
|
|
241
222
|
end
|
|
242
223
|
|
|
243
224
|
# Create a tool instance via plugin
|
|
@@ -288,10 +269,6 @@ module SwarmSDK
|
|
|
288
269
|
# Check if plugin has storage enabled for this agent
|
|
289
270
|
next unless plugin.storage_enabled?(agent_definition)
|
|
290
271
|
|
|
291
|
-
# Get plugin storage for this agent
|
|
292
|
-
plugin_storages = @plugin_storages[plugin.name] || {}
|
|
293
|
-
plugin_storages[agent_name]
|
|
294
|
-
|
|
295
272
|
# Register each tool provided by the plugin
|
|
296
273
|
plugin.tools.each do |tool_name|
|
|
297
274
|
# Skip if already registered explicitly
|
|
@@ -308,18 +285,9 @@ module SwarmSDK
|
|
|
308
285
|
agent_definition: agent_definition,
|
|
309
286
|
)
|
|
310
287
|
|
|
311
|
-
|
|
312
|
-
permissions_config = agent_definition.agent_permissions[tool_name] ||
|
|
313
|
-
agent_definition.default_permissions[tool_name]
|
|
288
|
+
permissions_config = resolve_default_permissions(tool_name, agent_definition)
|
|
314
289
|
|
|
315
|
-
|
|
316
|
-
tool_instance = wrap_tool_with_permissions(
|
|
317
|
-
tool_instance,
|
|
318
|
-
permissions_config,
|
|
319
|
-
agent_definition,
|
|
320
|
-
)
|
|
321
|
-
|
|
322
|
-
chat.with_tool(tool_instance)
|
|
290
|
+
wrap_and_add_tool(chat, tool_instance, permissions_config, agent_definition)
|
|
323
291
|
end
|
|
324
292
|
end
|
|
325
293
|
end
|
|
@@ -379,76 +347,12 @@ module SwarmSDK
|
|
|
379
347
|
delegate_chat: delegate_agent,
|
|
380
348
|
agent_name: agent_name,
|
|
381
349
|
swarm: @swarm,
|
|
382
|
-
hook_registry: @hook_registry,
|
|
383
350
|
delegating_chat: chat,
|
|
384
351
|
)
|
|
385
352
|
|
|
386
|
-
chat.
|
|
353
|
+
chat.add_tool(tool)
|
|
387
354
|
end
|
|
388
355
|
end
|
|
389
|
-
|
|
390
|
-
# Pass 4: Configure hook system
|
|
391
|
-
#
|
|
392
|
-
# Setup the callback system for each agent.
|
|
393
|
-
def pass_4_configure_hooks
|
|
394
|
-
@agents.each do |agent_name, chat|
|
|
395
|
-
agent_definition = @agent_definitions[agent_name]
|
|
396
|
-
|
|
397
|
-
chat.setup_hooks(
|
|
398
|
-
registry: @hook_registry,
|
|
399
|
-
agent_definition: agent_definition,
|
|
400
|
-
swarm: @swarm,
|
|
401
|
-
) if chat.respond_to?(:setup_hooks)
|
|
402
|
-
end
|
|
403
|
-
end
|
|
404
|
-
|
|
405
|
-
# Pass 5: Apply YAML hooks if present
|
|
406
|
-
#
|
|
407
|
-
# If loaded from YAML, apply agent-specific hooks.
|
|
408
|
-
def pass_5_apply_yaml_hooks
|
|
409
|
-
return unless @config_for_hooks
|
|
410
|
-
|
|
411
|
-
@agents.each do |agent_name, chat|
|
|
412
|
-
agent_def = @config_for_hooks.agents[agent_name]
|
|
413
|
-
next unless agent_def&.hooks
|
|
414
|
-
|
|
415
|
-
HooksAdapter.apply_agent_hooks(chat, agent_name, agent_def.hooks, @swarm.name)
|
|
416
|
-
end
|
|
417
|
-
end
|
|
418
|
-
|
|
419
|
-
# Create an AgentChat instance
|
|
420
|
-
#
|
|
421
|
-
# NOTE: This is dead code, left over from refactoring. AgentInitializer
|
|
422
|
-
# now handles agent creation. This should be removed in a cleanup pass.
|
|
423
|
-
#
|
|
424
|
-
# @param agent_name [Symbol] Agent name
|
|
425
|
-
# @param agent_definition [AgentDefinition] Agent definition
|
|
426
|
-
# @param tool_configurator [ToolConfigurator] Tool configurator
|
|
427
|
-
# @return [AgentChat] Configured chat instance
|
|
428
|
-
def create_agent_chat(agent_name, agent_definition, tool_configurator)
|
|
429
|
-
chat = AgentChat.new(
|
|
430
|
-
definition: agent_definition.to_h,
|
|
431
|
-
global_semaphore: @global_semaphore,
|
|
432
|
-
)
|
|
433
|
-
|
|
434
|
-
# Set agent name on provider for logging (if provider supports it)
|
|
435
|
-
chat.provider.agent_name = agent_name if chat.provider.respond_to?(:agent_name=)
|
|
436
|
-
|
|
437
|
-
# Register tools
|
|
438
|
-
tool_configurator.register_all_tools(
|
|
439
|
-
chat: chat,
|
|
440
|
-
agent_name: agent_name,
|
|
441
|
-
agent_definition: agent_definition,
|
|
442
|
-
)
|
|
443
|
-
|
|
444
|
-
# Register MCP servers if any
|
|
445
|
-
if agent_definition.mcp_servers.any?
|
|
446
|
-
mcp_configurator = McpConfigurator.new(@swarm)
|
|
447
|
-
mcp_configurator.register_mcp_servers(chat, agent_definition.mcp_servers, agent_name: agent_name)
|
|
448
|
-
end
|
|
449
|
-
|
|
450
|
-
chat
|
|
451
|
-
end
|
|
452
356
|
end
|
|
453
357
|
end
|
|
454
358
|
end
|