swarm_memory 2.1.2 → 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.
Files changed (118) hide show
  1. checksums.yaml +4 -4
  2. data/lib/claude_swarm/claude_mcp_server.rb +1 -0
  3. data/lib/claude_swarm/cli.rb +5 -18
  4. data/lib/claude_swarm/configuration.rb +30 -19
  5. data/lib/claude_swarm/mcp_generator.rb +5 -10
  6. data/lib/claude_swarm/openai/chat_completion.rb +4 -12
  7. data/lib/claude_swarm/openai/executor.rb +3 -1
  8. data/lib/claude_swarm/openai/responses.rb +13 -32
  9. data/lib/claude_swarm/version.rb +1 -1
  10. data/lib/swarm_cli/commands/mcp_serve.rb +2 -2
  11. data/lib/swarm_cli/commands/run.rb +2 -2
  12. data/lib/swarm_cli/config_loader.rb +14 -14
  13. data/lib/swarm_cli/formatters/human_formatter.rb +70 -0
  14. data/lib/swarm_cli/interactive_repl.rb +11 -5
  15. data/lib/swarm_cli/ui/icons.rb +0 -23
  16. data/lib/swarm_cli/version.rb +1 -1
  17. data/lib/swarm_memory/adapters/base.rb +4 -4
  18. data/lib/swarm_memory/adapters/filesystem_adapter.rb +11 -34
  19. data/lib/swarm_memory/core/storage_read_tracker.rb +51 -14
  20. data/lib/swarm_memory/integration/cli_registration.rb +3 -2
  21. data/lib/swarm_memory/integration/sdk_plugin.rb +98 -12
  22. data/lib/swarm_memory/tools/memory_edit.rb +2 -2
  23. data/lib/swarm_memory/tools/memory_multi_edit.rb +2 -2
  24. data/lib/swarm_memory/tools/memory_read.rb +3 -3
  25. data/lib/swarm_memory/version.rb +1 -1
  26. data/lib/swarm_memory.rb +6 -1
  27. data/lib/swarm_sdk/agent/builder.rb +91 -0
  28. data/lib/swarm_sdk/agent/chat.rb +540 -925
  29. data/lib/swarm_sdk/agent/{chat → chat_helpers}/context_tracker.rb +33 -79
  30. data/lib/swarm_sdk/agent/chat_helpers/event_emitter.rb +204 -0
  31. data/lib/swarm_sdk/agent/{chat → chat_helpers}/hook_integration.rb +147 -39
  32. data/lib/swarm_sdk/agent/chat_helpers/instrumentation.rb +78 -0
  33. data/lib/swarm_sdk/agent/chat_helpers/llm_configuration.rb +233 -0
  34. data/lib/swarm_sdk/agent/{chat → chat_helpers}/logging_helpers.rb +1 -1
  35. data/lib/swarm_sdk/agent/chat_helpers/serialization.rb +83 -0
  36. data/lib/swarm_sdk/agent/{chat → chat_helpers}/system_reminder_injector.rb +22 -38
  37. data/lib/swarm_sdk/agent/chat_helpers/system_reminders.rb +79 -0
  38. data/lib/swarm_sdk/agent/chat_helpers/token_tracking.rb +98 -0
  39. data/lib/swarm_sdk/agent/context.rb +8 -4
  40. data/lib/swarm_sdk/agent/context_manager.rb +6 -0
  41. data/lib/swarm_sdk/agent/definition.rb +79 -174
  42. data/lib/swarm_sdk/agent/llm_instrumentation_middleware.rb +182 -0
  43. data/lib/swarm_sdk/agent/system_prompt_builder.rb +161 -0
  44. data/lib/swarm_sdk/builders/base_builder.rb +409 -0
  45. data/lib/swarm_sdk/concerns/cleanupable.rb +39 -0
  46. data/lib/swarm_sdk/concerns/snapshotable.rb +67 -0
  47. data/lib/swarm_sdk/concerns/validatable.rb +55 -0
  48. data/lib/swarm_sdk/configuration/parser.rb +353 -0
  49. data/lib/swarm_sdk/configuration/translator.rb +255 -0
  50. data/lib/swarm_sdk/configuration.rb +100 -261
  51. data/lib/swarm_sdk/context_compactor/token_counter.rb +3 -3
  52. data/lib/swarm_sdk/context_compactor.rb +6 -11
  53. data/lib/swarm_sdk/context_management/builder.rb +128 -0
  54. data/lib/swarm_sdk/context_management/context.rb +328 -0
  55. data/lib/swarm_sdk/defaults.rb +196 -0
  56. data/lib/swarm_sdk/events_to_messages.rb +199 -0
  57. data/lib/swarm_sdk/hooks/shell_executor.rb +2 -1
  58. data/lib/swarm_sdk/log_collector.rb +192 -16
  59. data/lib/swarm_sdk/log_stream.rb +66 -8
  60. data/lib/swarm_sdk/model_aliases.json +4 -1
  61. data/lib/swarm_sdk/node_context.rb +1 -1
  62. data/lib/swarm_sdk/observer/builder.rb +81 -0
  63. data/lib/swarm_sdk/observer/config.rb +45 -0
  64. data/lib/swarm_sdk/observer/manager.rb +236 -0
  65. data/lib/swarm_sdk/patterns/agent_observer.rb +160 -0
  66. data/lib/swarm_sdk/plugin.rb +93 -3
  67. data/lib/swarm_sdk/proc_helpers.rb +53 -0
  68. data/lib/swarm_sdk/prompts/base_system_prompt.md.erb +0 -126
  69. data/lib/swarm_sdk/restore_result.rb +65 -0
  70. data/lib/swarm_sdk/snapshot.rb +156 -0
  71. data/lib/swarm_sdk/snapshot_from_events.rb +397 -0
  72. data/lib/swarm_sdk/state_restorer.rb +476 -0
  73. data/lib/swarm_sdk/state_snapshot.rb +334 -0
  74. data/lib/swarm_sdk/swarm/agent_initializer.rb +428 -79
  75. data/lib/swarm_sdk/swarm/all_agents_builder.rb +28 -1
  76. data/lib/swarm_sdk/swarm/builder.rb +69 -407
  77. data/lib/swarm_sdk/swarm/executor.rb +213 -0
  78. data/lib/swarm_sdk/swarm/hook_triggers.rb +150 -0
  79. data/lib/swarm_sdk/swarm/logging_callbacks.rb +340 -0
  80. data/lib/swarm_sdk/swarm/mcp_configurator.rb +7 -4
  81. data/lib/swarm_sdk/swarm/swarm_registry_builder.rb +67 -0
  82. data/lib/swarm_sdk/swarm/tool_configurator.rb +88 -149
  83. data/lib/swarm_sdk/swarm.rb +366 -631
  84. data/lib/swarm_sdk/swarm_loader.rb +145 -0
  85. data/lib/swarm_sdk/swarm_registry.rb +136 -0
  86. data/lib/swarm_sdk/tools/bash.rb +11 -3
  87. data/lib/swarm_sdk/tools/delegate.rb +127 -24
  88. data/lib/swarm_sdk/tools/edit.rb +8 -13
  89. data/lib/swarm_sdk/tools/glob.rb +9 -1
  90. data/lib/swarm_sdk/tools/grep.rb +7 -0
  91. data/lib/swarm_sdk/tools/multi_edit.rb +15 -11
  92. data/lib/swarm_sdk/tools/path_resolver.rb +51 -2
  93. data/lib/swarm_sdk/tools/read.rb +28 -18
  94. data/lib/swarm_sdk/tools/registry.rb +122 -10
  95. data/lib/swarm_sdk/tools/scratchpad/scratchpad_list.rb +23 -2
  96. data/lib/swarm_sdk/tools/scratchpad/scratchpad_read.rb +23 -2
  97. data/lib/swarm_sdk/tools/scratchpad/scratchpad_write.rb +21 -4
  98. data/lib/swarm_sdk/tools/stores/read_tracker.rb +47 -12
  99. data/lib/swarm_sdk/tools/stores/scratchpad_storage.rb +53 -5
  100. data/lib/swarm_sdk/tools/stores/storage.rb +0 -6
  101. data/lib/swarm_sdk/tools/think.rb +4 -1
  102. data/lib/swarm_sdk/tools/todo_write.rb +27 -8
  103. data/lib/swarm_sdk/tools/web_fetch.rb +3 -2
  104. data/lib/swarm_sdk/tools/write.rb +8 -13
  105. data/lib/swarm_sdk/utils.rb +18 -0
  106. data/lib/swarm_sdk/validation_result.rb +33 -0
  107. data/lib/swarm_sdk/version.rb +1 -1
  108. data/lib/swarm_sdk/{node → workflow}/agent_config.rb +34 -9
  109. data/lib/swarm_sdk/workflow/builder.rb +143 -0
  110. data/lib/swarm_sdk/workflow/executor.rb +497 -0
  111. data/lib/swarm_sdk/{node/builder.rb → workflow/node_builder.rb} +42 -21
  112. data/lib/swarm_sdk/{node → workflow}/transformer_executor.rb +3 -2
  113. data/lib/swarm_sdk/workflow.rb +554 -0
  114. data/lib/swarm_sdk.rb +393 -22
  115. metadata +51 -16
  116. data/lib/swarm_memory/chat_extension.rb +0 -34
  117. data/lib/swarm_sdk/node_orchestrator.rb +0 -591
  118. data/lib/swarm_sdk/providers/openai_with_responses.rb +0 -582
@@ -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.with_tool(tool) }
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
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SwarmSDK
4
+ class Swarm
5
+ # Builder for swarm registry in DSL
6
+ #
7
+ # Supports registering external swarms for composable swarms pattern.
8
+ #
9
+ # @example
10
+ # swarms do
11
+ # register "code_review", file: "./swarms/code_review.rb"
12
+ # register "testing", file: "./swarms/testing.yml", keep_context: false
13
+ # end
14
+ #
15
+ # @example Inline swarm definition
16
+ # swarms do
17
+ # register "tester" do
18
+ # lead :tester
19
+ # agent :tester do
20
+ # model "gpt-4o-mini"
21
+ # system "You test code"
22
+ # end
23
+ # end
24
+ # end
25
+ #
26
+ class SwarmRegistryBuilder
27
+ attr_reader :registrations
28
+
29
+ def initialize
30
+ @registrations = []
31
+ end
32
+
33
+ # Register a swarm from file, YAML string, or inline block
34
+ #
35
+ # @param name [String, Symbol] Registration name
36
+ # @param file [String, nil] Path to swarm file (.rb or .yml)
37
+ # @param yaml [String, nil] YAML content string
38
+ # @param keep_context [Boolean] Whether to preserve conversation state (default: true)
39
+ # @yield Optional block for inline swarm definition
40
+ # @raise [ArgumentError] If neither file, yaml, nor block provided
41
+ def register(name, file: nil, yaml: nil, keep_context: true, &block)
42
+ # Validate that exactly one source is provided
43
+ sources = [file, yaml, block].compact
44
+ if sources.empty?
45
+ raise ArgumentError, "register '#{name}' requires either file:, yaml:, or a block"
46
+ elsif sources.size > 1
47
+ raise ArgumentError, "register '#{name}' accepts only one of: file:, yaml:, or block (got #{sources.size})"
48
+ end
49
+
50
+ # Determine source type and store
51
+ source = if file
52
+ { type: :file, value: file }
53
+ elsif yaml
54
+ { type: :yaml, value: yaml }
55
+ else
56
+ { type: :block, value: block }
57
+ end
58
+
59
+ @registrations << {
60
+ name: name.to_s,
61
+ source: source,
62
+ keep_context: keep_context,
63
+ }
64
+ end
65
+ end
66
+ end
67
+ end
@@ -17,10 +17,6 @@ module SwarmSDK
17
17
  :Read,
18
18
  :Grep,
19
19
  :Glob,
20
- :TodoWrite,
21
- :Think,
22
- :WebFetch,
23
- :Clock,
24
20
  ].freeze
25
21
 
26
22
  # Scratchpad tools (added if scratchpad is enabled)
@@ -30,6 +26,17 @@ module SwarmSDK
30
26
  :ScratchpadList,
31
27
  ].freeze
32
28
 
29
+ # Filesystem tools that can be globally disabled for security
30
+ FILESYSTEM_TOOLS = [
31
+ :Read,
32
+ :Write,
33
+ :Edit,
34
+ :MultiEdit,
35
+ :Grep,
36
+ :Glob,
37
+ :Bash,
38
+ ].freeze
39
+
33
40
  def initialize(swarm, scratchpad_storage, plugin_storages = {})
34
41
  @swarm = swarm
35
42
  @scratchpad_storage = scratchpad_storage
@@ -50,6 +57,9 @@ module SwarmSDK
50
57
 
51
58
  # Create a tool instance by name
52
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
+ #
53
63
  # File tools and TodoWrite require agent context for tracking state.
54
64
  # Scratchpad tools require shared scratchpad instance.
55
65
  # Plugin tools are delegated to their respective plugins.
@@ -70,47 +80,14 @@ module SwarmSDK
70
80
  return create_plugin_tool(tool_name_sym, agent_name, directory, chat, agent_definition)
71
81
  end
72
82
 
73
- case tool_name_sym
74
- when :Read
75
- Tools::Read.new(agent_name: agent_name, directory: directory)
76
- when :Write
77
- Tools::Write.new(agent_name: agent_name, directory: directory)
78
- when :Edit
79
- Tools::Edit.new(agent_name: agent_name, directory: directory)
80
- when :MultiEdit
81
- Tools::MultiEdit.new(agent_name: agent_name, directory: directory)
82
- when :Bash
83
- Tools::Bash.new(directory: directory)
84
- when :Glob
85
- Tools::Glob.new(directory: directory)
86
- when :Grep
87
- Tools::Grep.new(directory: directory)
88
- when :TodoWrite
89
- Tools::TodoWrite.new(agent_name: agent_name) # TodoWrite doesn't need directory
90
- when :ScratchpadWrite
91
- Tools::Scratchpad::ScratchpadWrite.create_for_scratchpad(@scratchpad_storage)
92
- when :ScratchpadRead
93
- Tools::Scratchpad::ScratchpadRead.create_for_scratchpad(@scratchpad_storage)
94
- when :ScratchpadList
95
- Tools::Scratchpad::ScratchpadList.create_for_scratchpad(@scratchpad_storage)
96
- when :Think
97
- Tools::Think.new
98
- when :Clock
99
- Tools::Clock.new
100
- else
101
- # Regular tools - get class from registry and instantiate
102
- tool_class = Tools::Registry.get(tool_name_sym)
103
- raise ConfigurationError, "Unknown tool: #{tool_name}" unless tool_class
104
-
105
- # Check if tool is marked as :special but not handled in case statement
106
- if tool_class == :special
107
- raise ConfigurationError,
108
- "Tool '#{tool_name}' requires special initialization but is not handled in create_tool_instance. " \
109
- "This is a bug - #{tool_name} should be added to the case statement above."
110
- 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
+ }
111
89
 
112
- tool_class.new
113
- end
90
+ Tools::Registry.create(tool_name_sym, context)
114
91
  end
115
92
 
116
93
  # Wrap a tool instance with permissions validator if configured
@@ -144,6 +121,19 @@ module SwarmSDK
144
121
  # @param agent_name [Symbol] Agent name
145
122
  # @param agent_definition [AgentDefinition] Agent definition
146
123
  def register_explicit_tools(chat, tool_configs, agent_name:, agent_definition:)
124
+ # Validate filesystem tools if globally disabled
125
+ unless @swarm.allow_filesystem_tools
126
+ # Extract tool names from hashes and convert to symbols for comparison
127
+ forbidden = tool_configs.map { |tc| tc[:name].to_sym }.select { |name| FILESYSTEM_TOOLS.include?(name) }
128
+ unless forbidden.empty?
129
+ raise ConfigurationError,
130
+ "Filesystem tools are globally disabled (SwarmSDK.settings.allow_filesystem_tools = false) " \
131
+ "but agent '#{agent_name}' attempts to use: #{forbidden.join(", ")}.\n\n" \
132
+ "This is a system-wide security setting that cannot be overridden by swarm configuration.\n" \
133
+ "To use filesystem tools, set SwarmSDK.settings.allow_filesystem_tools = true before loading the swarm."
134
+ end
135
+ end
136
+
147
137
  tool_configs.each do |tool_config|
148
138
  tool_name = tool_config[:name]
149
139
  permissions_config = tool_config[:permissions]
@@ -151,14 +141,8 @@ module SwarmSDK
151
141
  # Create tool instance
152
142
  tool_instance = create_tool_instance(tool_name, agent_name, agent_definition.directory)
153
143
 
154
- # Wrap with permissions validator if configured
155
- tool_instance = wrap_tool_with_permissions(
156
- tool_instance,
157
- permissions_config,
158
- agent_definition,
159
- )
160
-
161
- 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)
162
146
  end
163
147
  end
164
148
 
@@ -177,6 +161,9 @@ module SwarmSDK
177
161
  # Register core default tools (unless disabled)
178
162
  if agent_definition.disable_default_tools != true
179
163
  DEFAULT_TOOLS.each do |tool_name|
164
+ # Skip filesystem tools if globally disabled
165
+ next if !@swarm.allow_filesystem_tools && FILESYSTEM_TOOLS.include?(tool_name)
166
+
180
167
  register_tool_if_not_disabled(chat, tool_name, explicit_tool_names, agent_name, agent_definition)
181
168
  end
182
169
 
@@ -202,19 +189,36 @@ module SwarmSDK
202
189
  return if tool_disabled?(tool_name, agent_definition.disable_default_tools)
203
190
 
204
191
  tool_instance = create_tool_instance(tool_name, agent_name, agent_definition.directory)
192
+ permissions_config = resolve_default_permissions(tool_name, agent_definition)
205
193
 
206
- # Resolve permissions for default tool
207
- permissions_config = agent_definition.agent_permissions[tool_name] ||
208
- agent_definition.default_permissions[tool_name]
194
+ wrap_and_add_tool(chat, tool_instance, permissions_config, agent_definition)
195
+ end
209
196
 
210
- # Wrap with permissions validator if configured
211
- tool_instance = wrap_tool_with_permissions(
212
- tool_instance,
213
- permissions_config,
214
- agent_definition,
215
- )
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
216
212
 
217
- chat.with_tool(tool_instance)
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]
218
222
  end
219
223
 
220
224
  # Create a tool instance via plugin
@@ -229,15 +233,21 @@ module SwarmSDK
229
233
  plugin = PluginRegistry.plugin_for_tool(tool_name)
230
234
  raise ConfigurationError, "Tool #{tool_name} is not provided by any plugin" unless plugin
231
235
 
232
- # Get plugin storage for this agent
236
+ # V7.0: Extract base name for storage lookup (handles delegation instances)
237
+ # For primary agents: :tester → :tester (no change)
238
+ # For delegation instances: "tester@frontend" → :tester (extracts base)
239
+ base_name = agent_name.to_s.split("@").first.to_sym
240
+
241
+ # Get plugin storage using BASE NAME (shared across instances)
233
242
  plugin_storages = @plugin_storages[plugin.name] || {}
234
- storage = plugin_storages[agent_name]
243
+ storage = plugin_storages[base_name] # ← Changed from agent_name to base_name
235
244
 
236
245
  # Build context for tool creation
246
+ # Pass full agent_name for tool state tracking (TodoWrite, ReadTracker, etc.)
237
247
  context = {
238
- agent_name: agent_name,
248
+ agent_name: agent_name, # Full instance name for tool's use
239
249
  directory: directory,
240
- storage: storage,
250
+ storage: storage, # Shared storage by base name
241
251
  agent_definition: agent_definition,
242
252
  chat: chat,
243
253
  tool_configurator: self,
@@ -259,10 +269,6 @@ module SwarmSDK
259
269
  # Check if plugin has storage enabled for this agent
260
270
  next unless plugin.storage_enabled?(agent_definition)
261
271
 
262
- # Get plugin storage for this agent
263
- plugin_storages = @plugin_storages[plugin.name] || {}
264
- plugin_storages[agent_name]
265
-
266
272
  # Register each tool provided by the plugin
267
273
  plugin.tools.each do |tool_name|
268
274
  # Skip if already registered explicitly
@@ -279,18 +285,9 @@ module SwarmSDK
279
285
  agent_definition: agent_definition,
280
286
  )
281
287
 
282
- # Resolve permissions for plugin tool
283
- permissions_config = agent_definition.agent_permissions[tool_name] ||
284
- agent_definition.default_permissions[tool_name]
288
+ permissions_config = resolve_default_permissions(tool_name, agent_definition)
285
289
 
286
- # Wrap with permissions validator if configured
287
- tool_instance = wrap_tool_with_permissions(
288
- tool_instance,
289
- permissions_config,
290
- agent_definition,
291
- )
292
-
293
- chat.with_tool(tool_instance)
290
+ wrap_and_add_tool(chat, tool_instance, permissions_config, agent_definition)
294
291
  end
295
292
  end
296
293
  end
@@ -303,15 +300,21 @@ module SwarmSDK
303
300
  def tool_disabled?(tool_name, disable_config)
304
301
  return false if disable_config.nil?
305
302
 
303
+ # Normalize tool_name to symbol for comparison
304
+ tool_name_sym = tool_name.to_sym
305
+
306
306
  if disable_config == true
307
307
  # Disable all default tools
308
308
  true
309
309
  elsif disable_config.is_a?(Symbol)
310
310
  # Single tool name
311
- disable_config == tool_name
311
+ disable_config == tool_name_sym
312
+ elsif disable_config.is_a?(String)
313
+ # Single tool name as string (from YAML)
314
+ disable_config.to_sym == tool_name_sym
312
315
  elsif disable_config.is_a?(Array)
313
- # Disable only tools in the array
314
- disable_config.include?(tool_name)
316
+ # Disable only tools in the array - normalize to symbols for comparison
317
+ disable_config.map(&:to_sym).include?(tool_name_sym)
315
318
  else
316
319
  false
317
320
  end
@@ -344,76 +347,12 @@ module SwarmSDK
344
347
  delegate_chat: delegate_agent,
345
348
  agent_name: agent_name,
346
349
  swarm: @swarm,
347
- hook_registry: @hook_registry,
348
350
  delegating_chat: chat,
349
351
  )
350
352
 
351
- chat.with_tool(tool)
352
- end
353
- end
354
-
355
- # Pass 4: Configure hook system
356
- #
357
- # Setup the callback system for each agent.
358
- def pass_4_configure_hooks
359
- @agents.each do |agent_name, chat|
360
- agent_definition = @agent_definitions[agent_name]
361
-
362
- chat.setup_hooks(
363
- registry: @hook_registry,
364
- agent_definition: agent_definition,
365
- swarm: @swarm,
366
- ) if chat.respond_to?(:setup_hooks)
367
- end
368
- end
369
-
370
- # Pass 5: Apply YAML hooks if present
371
- #
372
- # If loaded from YAML, apply agent-specific hooks.
373
- def pass_5_apply_yaml_hooks
374
- return unless @config_for_hooks
375
-
376
- @agents.each do |agent_name, chat|
377
- agent_def = @config_for_hooks.agents[agent_name]
378
- next unless agent_def&.hooks
379
-
380
- HooksAdapter.apply_agent_hooks(chat, agent_name, agent_def.hooks, @swarm.name)
353
+ chat.add_tool(tool)
381
354
  end
382
355
  end
383
-
384
- # Create an AgentChat instance
385
- #
386
- # NOTE: This is dead code, left over from refactoring. AgentInitializer
387
- # now handles agent creation. This should be removed in a cleanup pass.
388
- #
389
- # @param agent_name [Symbol] Agent name
390
- # @param agent_definition [AgentDefinition] Agent definition
391
- # @param tool_configurator [ToolConfigurator] Tool configurator
392
- # @return [AgentChat] Configured chat instance
393
- def create_agent_chat(agent_name, agent_definition, tool_configurator)
394
- chat = AgentChat.new(
395
- definition: agent_definition.to_h,
396
- global_semaphore: @global_semaphore,
397
- )
398
-
399
- # Set agent name on provider for logging (if provider supports it)
400
- chat.provider.agent_name = agent_name if chat.provider.respond_to?(:agent_name=)
401
-
402
- # Register tools
403
- tool_configurator.register_all_tools(
404
- chat: chat,
405
- agent_name: agent_name,
406
- agent_definition: agent_definition,
407
- )
408
-
409
- # Register MCP servers if any
410
- if agent_definition.mcp_servers.any?
411
- mcp_configurator = McpConfigurator.new(@swarm)
412
- mcp_configurator.register_mcp_servers(chat, agent_definition.mcp_servers, agent_name: agent_name)
413
- end
414
-
415
- chat
416
- end
417
356
  end
418
357
  end
419
358
  end