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
|
@@ -14,16 +14,11 @@ module SwarmSDK
|
|
|
14
14
|
# This encapsulates the complex initialization logic that was previously
|
|
15
15
|
# embedded in Swarm#initialize_agents.
|
|
16
16
|
class AgentInitializer
|
|
17
|
-
#
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
# Initialize with swarm reference (all data accessible via swarm)
|
|
18
|
+
#
|
|
19
|
+
# @param swarm [Swarm] The parent swarm instance
|
|
20
|
+
def initialize(swarm)
|
|
20
21
|
@swarm = swarm
|
|
21
|
-
@agent_definitions = agent_definitions
|
|
22
|
-
@global_semaphore = global_semaphore
|
|
23
|
-
@hook_registry = hook_registry
|
|
24
|
-
@scratchpad_storage = scratchpad_storage
|
|
25
|
-
@plugin_storages = plugin_storages
|
|
26
|
-
@config_for_hooks = config_for_hooks
|
|
27
22
|
@agents = {}
|
|
28
23
|
@agent_contexts = {}
|
|
29
24
|
end
|
|
@@ -51,6 +46,39 @@ module SwarmSDK
|
|
|
51
46
|
# Provide access to agent contexts for Swarm
|
|
52
47
|
attr_reader :agent_contexts
|
|
53
48
|
|
|
49
|
+
# Initialize a single agent in isolation (for observer agents)
|
|
50
|
+
#
|
|
51
|
+
# Creates an isolated agent chat without delegation tools,
|
|
52
|
+
# suitable for observer agents that don't need to delegate.
|
|
53
|
+
# Reuses existing create_agent_chat infrastructure.
|
|
54
|
+
#
|
|
55
|
+
# @param agent_name [Symbol] Name of agent to initialize
|
|
56
|
+
# @return [Agent::Chat] Isolated agent chat instance
|
|
57
|
+
# @raise [ConfigurationError] If agent not found
|
|
58
|
+
#
|
|
59
|
+
# @example
|
|
60
|
+
# initializer = AgentInitializer.new(swarm)
|
|
61
|
+
# chat = initializer.initialize_isolated_agent(:profiler)
|
|
62
|
+
# chat.ask("Analyze this prompt")
|
|
63
|
+
def initialize_isolated_agent(agent_name)
|
|
64
|
+
agent_def = @swarm.agent_definitions[agent_name]
|
|
65
|
+
raise ConfigurationError, "Agent '#{agent_name}' not found" unless agent_def
|
|
66
|
+
|
|
67
|
+
# Ensure plugin storages are created (needed by ToolConfigurator)
|
|
68
|
+
create_plugin_storages if @swarm.plugin_storages.empty?
|
|
69
|
+
|
|
70
|
+
# Reuse existing create_agent_chat infrastructure
|
|
71
|
+
tool_configurator = ToolConfigurator.new(
|
|
72
|
+
@swarm,
|
|
73
|
+
@swarm.scratchpad_storage,
|
|
74
|
+
@swarm.plugin_storages,
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
# Create chat using same method as pass_1_create_agents
|
|
78
|
+
# This gives us full tool setup, MCP servers, etc.
|
|
79
|
+
create_agent_chat(agent_name, agent_def, tool_configurator)
|
|
80
|
+
end
|
|
81
|
+
|
|
54
82
|
# Create a tool that delegates work to another agent
|
|
55
83
|
#
|
|
56
84
|
# This method is public for testing delegation from Swarm.
|
|
@@ -68,9 +96,6 @@ module SwarmSDK
|
|
|
68
96
|
delegate_chat: delegate_chat,
|
|
69
97
|
agent_name: agent_name,
|
|
70
98
|
swarm: @swarm,
|
|
71
|
-
hook_registry: @hook_registry,
|
|
72
|
-
call_stack: @swarm.delegation_call_stack,
|
|
73
|
-
swarm_registry: @swarm.swarm_registry,
|
|
74
99
|
delegating_chat: delegating_chat,
|
|
75
100
|
)
|
|
76
101
|
end
|
|
@@ -90,9 +115,9 @@ module SwarmSDK
|
|
|
90
115
|
# Create plugin storages for agents
|
|
91
116
|
create_plugin_storages
|
|
92
117
|
|
|
93
|
-
tool_configurator = ToolConfigurator.new(@swarm, @scratchpad_storage, @plugin_storages)
|
|
118
|
+
tool_configurator = ToolConfigurator.new(@swarm, @swarm.scratchpad_storage, @swarm.plugin_storages)
|
|
94
119
|
|
|
95
|
-
@agent_definitions.each do |name, agent_definition|
|
|
120
|
+
@swarm.agent_definitions.each do |name, agent_definition|
|
|
96
121
|
# Skip if this agent will only exist as delegation instances
|
|
97
122
|
next if should_skip_primary_creation?(name, agent_definition)
|
|
98
123
|
|
|
@@ -111,19 +136,19 @@ module SwarmSDK
|
|
|
111
136
|
# 2b. Wire primary agents to delegation instances OR shared primaries
|
|
112
137
|
# 2c. Wire delegation instances to their delegates (nested delegation support)
|
|
113
138
|
def pass_2_register_delegation_tools
|
|
114
|
-
tool_configurator = ToolConfigurator.new(@swarm, @scratchpad_storage, @plugin_storages)
|
|
139
|
+
tool_configurator = ToolConfigurator.new(@swarm, @swarm.scratchpad_storage, @swarm.plugin_storages)
|
|
115
140
|
|
|
116
141
|
# Sub-pass 2a: Create delegation instances for isolated agents
|
|
117
|
-
@agent_definitions.each do |delegator_name, delegator_def|
|
|
142
|
+
@swarm.agent_definitions.each do |delegator_name, delegator_def|
|
|
118
143
|
delegator_def.delegates_to.each do |delegate_base_name|
|
|
119
144
|
delegate_base_name = delegate_base_name.to_sym
|
|
120
145
|
|
|
121
|
-
unless @agent_definitions.key?(delegate_base_name)
|
|
146
|
+
unless @swarm.agent_definitions.key?(delegate_base_name)
|
|
122
147
|
raise ConfigurationError,
|
|
123
148
|
"Agent '#{delegator_name}' delegates to unknown agent '#{delegate_base_name}'"
|
|
124
149
|
end
|
|
125
150
|
|
|
126
|
-
delegate_definition = @agent_definitions[delegate_base_name]
|
|
151
|
+
delegate_definition = @swarm.agent_definitions[delegate_base_name]
|
|
127
152
|
|
|
128
153
|
# Check isolation mode of the DELEGATE agent
|
|
129
154
|
# If delegate wants to be shared, skip instance creation (use primary)
|
|
@@ -146,54 +171,20 @@ module SwarmSDK
|
|
|
146
171
|
end
|
|
147
172
|
|
|
148
173
|
# Sub-pass 2b: Wire primary agents to delegation instances OR shared primaries OR registered swarms
|
|
149
|
-
@agent_definitions.each do |delegator_name, delegator_def|
|
|
174
|
+
@swarm.agent_definitions.each do |delegator_name, delegator_def|
|
|
150
175
|
delegator_chat = @agents[delegator_name]
|
|
151
176
|
|
|
152
177
|
# Skip if delegator doesn't exist as primary (wasn't created in pass_1)
|
|
153
178
|
next unless delegator_chat
|
|
154
179
|
|
|
155
|
-
delegator_def.delegates_to.each do |
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
description: "External swarm: #{delegate_base_name_str}",
|
|
164
|
-
delegate_chat: nil, # Swarm delegation - no direct chat
|
|
165
|
-
agent_name: delegator_name,
|
|
166
|
-
delegating_chat: delegator_chat,
|
|
167
|
-
)
|
|
168
|
-
|
|
169
|
-
delegator_chat.with_tool(tool)
|
|
170
|
-
elsif @agent_definitions.key?(delegate_base_name)
|
|
171
|
-
# Delegate to local agent
|
|
172
|
-
delegate_definition = @agent_definitions[delegate_base_name]
|
|
173
|
-
|
|
174
|
-
# Determine which chat instance to use
|
|
175
|
-
target_chat = if delegate_definition.shared_across_delegations
|
|
176
|
-
# Shared mode: use primary agent (old behavior)
|
|
177
|
-
@agents[delegate_base_name]
|
|
178
|
-
else
|
|
179
|
-
# Isolated mode: use delegation instance
|
|
180
|
-
instance_name = "#{delegate_base_name}@#{delegator_name}"
|
|
181
|
-
@swarm.delegation_instances[instance_name]
|
|
182
|
-
end
|
|
183
|
-
|
|
184
|
-
# Create delegation tool pointing to chosen instance
|
|
185
|
-
tool = create_delegation_tool(
|
|
186
|
-
name: delegate_base_name.to_s,
|
|
187
|
-
description: delegate_definition.description,
|
|
188
|
-
delegate_chat: target_chat, # ← Isolated instance OR shared primary
|
|
189
|
-
agent_name: delegator_name,
|
|
190
|
-
delegating_chat: delegator_chat,
|
|
191
|
-
)
|
|
192
|
-
|
|
193
|
-
delegator_chat.with_tool(tool)
|
|
194
|
-
else
|
|
195
|
-
raise ConfigurationError, "Agent '#{delegator_name}' delegates to unknown target '#{delegate_base_name_str}' (not a local agent or registered swarm)"
|
|
196
|
-
end
|
|
180
|
+
delegator_def.delegates_to.each do |delegate_name|
|
|
181
|
+
wire_delegation(
|
|
182
|
+
delegator_name: delegator_name,
|
|
183
|
+
delegator_chat: delegator_chat,
|
|
184
|
+
delegate_name: delegate_name,
|
|
185
|
+
tool_configurator: tool_configurator,
|
|
186
|
+
create_nested_instances: false,
|
|
187
|
+
)
|
|
197
188
|
end
|
|
198
189
|
end
|
|
199
190
|
|
|
@@ -201,63 +192,118 @@ module SwarmSDK
|
|
|
201
192
|
# Convert to array first to avoid "can't add key during iteration" error
|
|
202
193
|
@swarm.delegation_instances.to_a.each do |instance_name, delegation_chat|
|
|
203
194
|
base_name = extract_base_name(instance_name)
|
|
204
|
-
delegate_definition = @agent_definitions[base_name]
|
|
195
|
+
delegate_definition = @swarm.agent_definitions[base_name]
|
|
205
196
|
|
|
206
197
|
# Register delegation tools for THIS instance's delegates_to
|
|
207
198
|
delegate_definition.delegates_to.each do |nested_delegate_name|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
199
|
+
wire_delegation(
|
|
200
|
+
delegator_name: instance_name.to_sym,
|
|
201
|
+
delegator_chat: delegation_chat,
|
|
202
|
+
delegate_name: nested_delegate_name,
|
|
203
|
+
tool_configurator: tool_configurator,
|
|
204
|
+
create_nested_instances: true,
|
|
205
|
+
)
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
# Wire a single delegation from one agent/instance to a delegate
|
|
211
|
+
#
|
|
212
|
+
# This is the unified logic for delegation wiring used by both:
|
|
213
|
+
# - Sub-pass 2b: Primary agents → delegates
|
|
214
|
+
# - Sub-pass 2c: Delegation instances → nested delegates
|
|
215
|
+
#
|
|
216
|
+
# @param delegator_name [Symbol, String] Name of the agent doing the delegating
|
|
217
|
+
# @param delegator_chat [Agent::Chat] Chat instance of the delegator
|
|
218
|
+
# @param delegate_name [Symbol, String] Name of the delegate target
|
|
219
|
+
# @param tool_configurator [ToolConfigurator] Tool configuration helper
|
|
220
|
+
# @param create_nested_instances [Boolean] Whether to create new instances for nested delegation
|
|
221
|
+
# @return [void]
|
|
222
|
+
def wire_delegation(delegator_name:, delegator_chat:, delegate_name:, tool_configurator:, create_nested_instances:)
|
|
223
|
+
delegate_name_str = delegate_name.to_s
|
|
224
|
+
delegate_name_sym = delegate_name.to_sym
|
|
225
|
+
|
|
226
|
+
# Check if target is a registered swarm
|
|
227
|
+
if @swarm.swarm_registry&.registered?(delegate_name_str)
|
|
228
|
+
wire_swarm_delegation(delegator_name, delegator_chat, delegate_name_str)
|
|
229
|
+
elsif @swarm.agent_definitions.key?(delegate_name_sym)
|
|
230
|
+
wire_agent_delegation(
|
|
231
|
+
delegator_name: delegator_name,
|
|
232
|
+
delegator_chat: delegator_chat,
|
|
233
|
+
delegate_name_sym: delegate_name_sym,
|
|
234
|
+
tool_configurator: tool_configurator,
|
|
235
|
+
create_nested_instances: create_nested_instances,
|
|
236
|
+
)
|
|
237
|
+
else
|
|
238
|
+
raise ConfigurationError,
|
|
239
|
+
"Agent '#{delegator_name}' delegates to unknown target '#{delegate_name_str}' (not a local agent or registered swarm)"
|
|
240
|
+
end
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
# Wire delegation to an external swarm
|
|
244
|
+
#
|
|
245
|
+
# @param delegator_name [Symbol, String] Name of the delegating agent
|
|
246
|
+
# @param delegator_chat [Agent::Chat] Chat instance of the delegator
|
|
247
|
+
# @param swarm_name [String] Name of the registered swarm
|
|
248
|
+
# @return [void]
|
|
249
|
+
def wire_swarm_delegation(delegator_name, delegator_chat, swarm_name)
|
|
250
|
+
tool = create_delegation_tool(
|
|
251
|
+
name: swarm_name,
|
|
252
|
+
description: "External swarm: #{swarm_name}",
|
|
253
|
+
delegate_chat: nil, # Swarm delegation - no direct chat
|
|
254
|
+
agent_name: delegator_name,
|
|
255
|
+
delegating_chat: delegator_chat,
|
|
256
|
+
)
|
|
257
|
+
|
|
258
|
+
delegator_chat.add_tool(tool)
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
# Wire delegation to a local agent
|
|
262
|
+
#
|
|
263
|
+
# Determines whether to use shared primary or isolated instance based on
|
|
264
|
+
# the delegate's shared_across_delegations setting.
|
|
265
|
+
#
|
|
266
|
+
# @param delegator_name [Symbol, String] Name of the delegating agent
|
|
267
|
+
# @param delegator_chat [Agent::Chat] Chat instance of the delegator
|
|
268
|
+
# @param delegate_name_sym [Symbol] Name of the delegate agent
|
|
269
|
+
# @param tool_configurator [ToolConfigurator] Tool configuration helper
|
|
270
|
+
# @param create_nested_instances [Boolean] Whether to create new instances if not found
|
|
271
|
+
# @return [void]
|
|
272
|
+
def wire_agent_delegation(delegator_name:, delegator_chat:, delegate_name_sym:, tool_configurator:, create_nested_instances:)
|
|
273
|
+
delegate_definition = @swarm.agent_definitions[delegate_name_sym]
|
|
274
|
+
|
|
275
|
+
# Determine which chat instance to use
|
|
276
|
+
target_chat = if delegate_definition.shared_across_delegations
|
|
277
|
+
# Shared mode: use primary agent (semaphore-protected)
|
|
278
|
+
@agents[delegate_name_sym]
|
|
279
|
+
else
|
|
280
|
+
# Isolated mode: use delegation instance
|
|
281
|
+
instance_name = "#{delegate_name_sym}@#{delegator_name}"
|
|
282
|
+
|
|
283
|
+
if create_nested_instances
|
|
284
|
+
# For nested delegation: create if not exists
|
|
285
|
+
@swarm.delegation_instances[instance_name] ||= create_agent_chat_for_delegation(
|
|
286
|
+
instance_name: instance_name,
|
|
287
|
+
base_name: delegate_name_sym,
|
|
288
|
+
agent_definition: delegate_definition,
|
|
289
|
+
tool_configurator: tool_configurator,
|
|
290
|
+
)
|
|
291
|
+
else
|
|
292
|
+
# For primary delegation: instance was pre-created in 2a
|
|
293
|
+
@swarm.delegation_instances[instance_name]
|
|
259
294
|
end
|
|
260
295
|
end
|
|
296
|
+
|
|
297
|
+
# Create delegation tool pointing to chosen instance
|
|
298
|
+
tool = create_delegation_tool(
|
|
299
|
+
name: delegate_name_sym.to_s,
|
|
300
|
+
description: delegate_definition.description,
|
|
301
|
+
delegate_chat: target_chat,
|
|
302
|
+
agent_name: delegator_name,
|
|
303
|
+
delegating_chat: delegator_chat,
|
|
304
|
+
)
|
|
305
|
+
|
|
306
|
+
delegator_chat.add_tool(tool)
|
|
261
307
|
end
|
|
262
308
|
|
|
263
309
|
# Pass 3: Setup agent contexts
|
|
@@ -267,13 +313,13 @@ module SwarmSDK
|
|
|
267
313
|
def pass_3_setup_contexts
|
|
268
314
|
# Setup contexts for PRIMARY agents
|
|
269
315
|
@agents.each do |agent_name, chat|
|
|
270
|
-
setup_agent_context(agent_name, @agent_definitions[agent_name], chat, is_delegation: false)
|
|
316
|
+
setup_agent_context(agent_name, @swarm.agent_definitions[agent_name], chat, is_delegation: false)
|
|
271
317
|
end
|
|
272
318
|
|
|
273
319
|
# Setup contexts for DELEGATION instances
|
|
274
320
|
@swarm.delegation_instances.each do |instance_name, chat|
|
|
275
321
|
base_name = extract_base_name(instance_name)
|
|
276
|
-
agent_definition = @agent_definitions[base_name]
|
|
322
|
+
agent_definition = @swarm.agent_definitions[base_name]
|
|
277
323
|
setup_agent_context(instance_name.to_sym, agent_definition, chat, is_delegation: true)
|
|
278
324
|
end
|
|
279
325
|
end
|
|
@@ -281,7 +327,7 @@ module SwarmSDK
|
|
|
281
327
|
# Setup context for an agent (primary or delegation instance)
|
|
282
328
|
def setup_agent_context(agent_name, agent_definition, chat, is_delegation: false)
|
|
283
329
|
delegate_tool_names = agent_definition.delegates_to.map do |delegate_name|
|
|
284
|
-
|
|
330
|
+
Tools::Delegate.tool_name_for(delegate_name)
|
|
285
331
|
end
|
|
286
332
|
|
|
287
333
|
context = Agent::Context.new(
|
|
@@ -351,10 +397,10 @@ module SwarmSDK
|
|
|
351
397
|
# Configure hooks for an agent (primary or delegation instance)
|
|
352
398
|
def configure_hooks_for_agent(agent_name, chat)
|
|
353
399
|
base_name = extract_base_name(agent_name)
|
|
354
|
-
agent_definition = @agent_definitions[base_name]
|
|
400
|
+
agent_definition = @swarm.agent_definitions[base_name]
|
|
355
401
|
|
|
356
402
|
chat.setup_hooks(
|
|
357
|
-
registry: @hook_registry,
|
|
403
|
+
registry: @swarm.hook_registry,
|
|
358
404
|
agent_definition: agent_definition,
|
|
359
405
|
swarm: @swarm,
|
|
360
406
|
) if chat.respond_to?(:setup_hooks)
|
|
@@ -365,7 +411,7 @@ module SwarmSDK
|
|
|
365
411
|
# If the swarm was loaded from YAML with agent-specific hooks,
|
|
366
412
|
# apply them now via HooksAdapter.
|
|
367
413
|
def pass_5_apply_yaml_hooks
|
|
368
|
-
return unless @config_for_hooks
|
|
414
|
+
return unless @swarm.config_for_hooks
|
|
369
415
|
|
|
370
416
|
# Apply YAML hooks to PRIMARY agents
|
|
371
417
|
@agents.each do |agent_name, chat|
|
|
@@ -381,7 +427,7 @@ module SwarmSDK
|
|
|
381
427
|
# Apply YAML hooks for an agent (primary or delegation instance)
|
|
382
428
|
def apply_yaml_hooks_for_agent(agent_name, chat)
|
|
383
429
|
base_name = extract_base_name(agent_name)
|
|
384
|
-
agent_config = @config_for_hooks.agents[base_name]
|
|
430
|
+
agent_config = @swarm.config_for_hooks.agents[base_name]
|
|
385
431
|
return unless agent_config
|
|
386
432
|
|
|
387
433
|
# Configuration.agents now returns hashes, not Definitions
|
|
@@ -401,7 +447,7 @@ module SwarmSDK
|
|
|
401
447
|
chat = Agent::Chat.new(
|
|
402
448
|
definition: agent_definition.to_h,
|
|
403
449
|
agent_name: agent_name,
|
|
404
|
-
global_semaphore: @global_semaphore,
|
|
450
|
+
global_semaphore: @swarm.global_semaphore,
|
|
405
451
|
)
|
|
406
452
|
|
|
407
453
|
# Set agent name on provider for logging (if provider supports it)
|
|
@@ -437,7 +483,7 @@ module SwarmSDK
|
|
|
437
483
|
chat = Agent::Chat.new(
|
|
438
484
|
definition: agent_definition.to_h,
|
|
439
485
|
agent_name: instance_name.to_sym, # Full instance name for isolation
|
|
440
|
-
global_semaphore: @global_semaphore,
|
|
486
|
+
global_semaphore: @swarm.global_semaphore,
|
|
441
487
|
)
|
|
442
488
|
|
|
443
489
|
# Set provider agent name for logging
|
|
@@ -485,7 +531,7 @@ module SwarmSDK
|
|
|
485
531
|
if @agents.key?(delegate_name_sym)
|
|
486
532
|
# Delegate to local agent
|
|
487
533
|
delegate_agent = @agents[delegate_name_sym]
|
|
488
|
-
delegate_definition = @agent_definitions[delegate_name_sym]
|
|
534
|
+
delegate_definition = @swarm.agent_definitions[delegate_name_sym]
|
|
489
535
|
|
|
490
536
|
tool = create_delegation_tool(
|
|
491
537
|
name: delegate_name_str,
|
|
@@ -495,7 +541,7 @@ module SwarmSDK
|
|
|
495
541
|
delegating_chat: chat,
|
|
496
542
|
)
|
|
497
543
|
|
|
498
|
-
chat.
|
|
544
|
+
chat.add_tool(tool)
|
|
499
545
|
elsif @swarm.swarm_registry&.registered?(delegate_name_str)
|
|
500
546
|
# Delegate to registered swarm
|
|
501
547
|
tool = create_delegation_tool(
|
|
@@ -506,7 +552,7 @@ module SwarmSDK
|
|
|
506
552
|
delegating_chat: chat,
|
|
507
553
|
)
|
|
508
554
|
|
|
509
|
-
chat.
|
|
555
|
+
chat.add_tool(tool)
|
|
510
556
|
else
|
|
511
557
|
raise ConfigurationError, "Agent '#{agent_name}' delegates to unknown target '#{delegate_name_str}' (not a local agent or registered swarm)"
|
|
512
558
|
end
|
|
@@ -521,7 +567,7 @@ module SwarmSDK
|
|
|
521
567
|
# @return [void]
|
|
522
568
|
def create_plugin_storages
|
|
523
569
|
PluginRegistry.all.each do |plugin|
|
|
524
|
-
@agent_definitions.each do |agent_name, agent_definition|
|
|
570
|
+
@swarm.agent_definitions.each do |agent_name, agent_definition|
|
|
525
571
|
# Check if this plugin needs storage for this agent
|
|
526
572
|
next unless plugin.storage_enabled?(agent_definition)
|
|
527
573
|
|
|
@@ -536,25 +582,23 @@ module SwarmSDK
|
|
|
536
582
|
storage = plugin.create_storage(agent_name: agent_name, config: parsed_config)
|
|
537
583
|
|
|
538
584
|
# Store in plugin_storages: { plugin_name => { agent_name => storage } }
|
|
539
|
-
@plugin_storages[plugin.name] ||= {}
|
|
540
|
-
@plugin_storages[plugin.name][agent_name] = storage
|
|
585
|
+
@swarm.plugin_storages[plugin.name] ||= {}
|
|
586
|
+
@swarm.plugin_storages[plugin.name][agent_name] = storage
|
|
541
587
|
end
|
|
542
588
|
end
|
|
543
589
|
end
|
|
544
590
|
|
|
545
591
|
# Get plugin-specific config from agent definition
|
|
546
592
|
#
|
|
547
|
-
#
|
|
548
|
-
# E.g., memory plugin
|
|
593
|
+
# Uses the generic plugin_configs accessor to retrieve plugin-specific config.
|
|
594
|
+
# E.g., memory plugin config is accessed via `agent_definition.plugin_config(:memory)`
|
|
549
595
|
#
|
|
550
596
|
# @param agent_definition [Agent::Definition] Agent definition
|
|
551
597
|
# @param plugin_name [Symbol] Plugin name
|
|
552
598
|
# @return [Object, nil] Plugin config or nil
|
|
553
599
|
def get_plugin_config(agent_definition, plugin_name)
|
|
554
|
-
#
|
|
555
|
-
|
|
556
|
-
agent_definition.public_send(plugin_name)
|
|
557
|
-
end
|
|
600
|
+
# Use generic plugin config accessor
|
|
601
|
+
agent_definition.plugin_config(plugin_name)
|
|
558
602
|
end
|
|
559
603
|
|
|
560
604
|
# Notify all plugins that an agent was initialized
|
|
@@ -569,7 +613,7 @@ module SwarmSDK
|
|
|
569
613
|
def notify_plugins_agent_initialized(agent_name, chat, agent_definition, tool_configurator)
|
|
570
614
|
PluginRegistry.all.each do |plugin|
|
|
571
615
|
# Get plugin storage for this agent (if any)
|
|
572
|
-
plugin_storages = @plugin_storages[plugin.name] || {}
|
|
616
|
+
plugin_storages = @swarm.plugin_storages[plugin.name] || {}
|
|
573
617
|
storage = plugin_storages[agent_name]
|
|
574
618
|
|
|
575
619
|
# Build context for plugin
|
|
@@ -611,7 +655,7 @@ module SwarmSDK
|
|
|
611
655
|
# @return [Boolean] True if only referenced as delegate
|
|
612
656
|
def only_referenced_as_delegate?(name)
|
|
613
657
|
# Check if any agent delegates to this one
|
|
614
|
-
referenced_as_delegate = @agent_definitions.any? do |_agent_name, definition|
|
|
658
|
+
referenced_as_delegate = @swarm.agent_definitions.any? do |_agent_name, definition|
|
|
615
659
|
definition.delegates_to.include?(name)
|
|
616
660
|
end
|
|
617
661
|
|