swarm_sdk 2.7.13 → 3.0.0.alpha1
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/swarm_sdk/ruby_llm_patches/chat_callbacks_patch.rb +43 -22
- data/lib/swarm_sdk/ruby_llm_patches/init.rb +6 -0
- data/lib/swarm_sdk/ruby_llm_patches/mcp_ssl_patch.rb +144 -0
- data/lib/swarm_sdk/ruby_llm_patches/tool_concurrency_patch.rb +3 -4
- data/lib/swarm_sdk/v3/agent.rb +1165 -0
- data/lib/swarm_sdk/v3/agent_builder.rb +533 -0
- data/lib/swarm_sdk/v3/agent_definition.rb +330 -0
- data/lib/swarm_sdk/v3/configuration.rb +490 -0
- data/lib/swarm_sdk/v3/debug_log.rb +86 -0
- data/lib/swarm_sdk/v3/event_stream.rb +130 -0
- data/lib/swarm_sdk/v3/hooks/context.rb +112 -0
- data/lib/swarm_sdk/v3/hooks/result.rb +115 -0
- data/lib/swarm_sdk/v3/hooks/runner.rb +128 -0
- data/lib/swarm_sdk/v3/mcp/connector.rb +183 -0
- data/lib/swarm_sdk/v3/mcp/mcp_error.rb +15 -0
- data/lib/swarm_sdk/v3/mcp/server_definition.rb +125 -0
- data/lib/swarm_sdk/v3/mcp/ssl_http_transport.rb +103 -0
- data/lib/swarm_sdk/v3/mcp/stdio_transport.rb +135 -0
- data/lib/swarm_sdk/v3/mcp/tool_proxy.rb +53 -0
- data/lib/swarm_sdk/v3/memory/adapters/base.rb +297 -0
- data/lib/swarm_sdk/v3/memory/adapters/faiss_support.rb +194 -0
- data/lib/swarm_sdk/v3/memory/adapters/filesystem_adapter.rb +212 -0
- data/lib/swarm_sdk/v3/memory/adapters/sqlite_adapter.rb +507 -0
- data/lib/swarm_sdk/v3/memory/adapters/vector_utils.rb +88 -0
- data/lib/swarm_sdk/v3/memory/card.rb +206 -0
- data/lib/swarm_sdk/v3/memory/cluster.rb +146 -0
- data/lib/swarm_sdk/v3/memory/compressor.rb +496 -0
- data/lib/swarm_sdk/v3/memory/consolidator.rb +427 -0
- data/lib/swarm_sdk/v3/memory/context_builder.rb +339 -0
- data/lib/swarm_sdk/v3/memory/edge.rb +105 -0
- data/lib/swarm_sdk/v3/memory/embedder.rb +185 -0
- data/lib/swarm_sdk/v3/memory/exposure_tracker.rb +104 -0
- data/lib/swarm_sdk/v3/memory/ingestion_pipeline.rb +394 -0
- data/lib/swarm_sdk/v3/memory/retriever.rb +289 -0
- data/lib/swarm_sdk/v3/memory/store.rb +489 -0
- data/lib/swarm_sdk/v3/skills/loader.rb +147 -0
- data/lib/swarm_sdk/v3/skills/manifest.rb +45 -0
- data/lib/swarm_sdk/v3/sub_task_agent.rb +248 -0
- data/lib/swarm_sdk/v3/tools/base.rb +80 -0
- data/lib/swarm_sdk/v3/tools/bash.rb +174 -0
- data/lib/swarm_sdk/v3/tools/clock.rb +32 -0
- data/lib/swarm_sdk/v3/tools/edit.rb +111 -0
- data/lib/swarm_sdk/v3/tools/glob.rb +96 -0
- data/lib/swarm_sdk/v3/tools/grep.rb +200 -0
- data/lib/swarm_sdk/v3/tools/message_teammate.rb +15 -0
- data/lib/swarm_sdk/v3/tools/message_user.rb +15 -0
- data/lib/swarm_sdk/v3/tools/read.rb +181 -0
- data/lib/swarm_sdk/v3/tools/read_tracker.rb +40 -0
- data/lib/swarm_sdk/v3/tools/registry.rb +208 -0
- data/lib/swarm_sdk/v3/tools/sub_task.rb +183 -0
- data/lib/swarm_sdk/v3/tools/think.rb +88 -0
- data/lib/swarm_sdk/v3/tools/write.rb +87 -0
- data/lib/swarm_sdk/v3.rb +145 -0
- metadata +84 -148
- data/lib/swarm_sdk/agent/RETRY_LOGIC.md +0 -175
- data/lib/swarm_sdk/agent/builder.rb +0 -680
- data/lib/swarm_sdk/agent/chat.rb +0 -1432
- data/lib/swarm_sdk/agent/chat_helpers/context_tracker.rb +0 -375
- data/lib/swarm_sdk/agent/chat_helpers/event_emitter.rb +0 -204
- data/lib/swarm_sdk/agent/chat_helpers/hook_integration.rb +0 -480
- data/lib/swarm_sdk/agent/chat_helpers/instrumentation.rb +0 -85
- data/lib/swarm_sdk/agent/chat_helpers/llm_configuration.rb +0 -290
- data/lib/swarm_sdk/agent/chat_helpers/logging_helpers.rb +0 -116
- data/lib/swarm_sdk/agent/chat_helpers/serialization.rb +0 -83
- data/lib/swarm_sdk/agent/chat_helpers/system_reminder_injector.rb +0 -134
- data/lib/swarm_sdk/agent/chat_helpers/system_reminders.rb +0 -79
- data/lib/swarm_sdk/agent/chat_helpers/token_tracking.rb +0 -146
- data/lib/swarm_sdk/agent/context.rb +0 -115
- data/lib/swarm_sdk/agent/context_manager.rb +0 -315
- data/lib/swarm_sdk/agent/definition.rb +0 -581
- data/lib/swarm_sdk/agent/llm_instrumentation_middleware.rb +0 -226
- data/lib/swarm_sdk/agent/system_prompt_builder.rb +0 -161
- data/lib/swarm_sdk/agent/tool_registry.rb +0 -189
- data/lib/swarm_sdk/agent_registry.rb +0 -146
- data/lib/swarm_sdk/builders/base_builder.rb +0 -553
- data/lib/swarm_sdk/claude_code_agent_adapter.rb +0 -205
- data/lib/swarm_sdk/concerns/cleanupable.rb +0 -39
- data/lib/swarm_sdk/concerns/snapshotable.rb +0 -67
- data/lib/swarm_sdk/concerns/validatable.rb +0 -55
- data/lib/swarm_sdk/config.rb +0 -367
- data/lib/swarm_sdk/configuration/parser.rb +0 -397
- data/lib/swarm_sdk/configuration/translator.rb +0 -283
- data/lib/swarm_sdk/configuration.rb +0 -165
- data/lib/swarm_sdk/context_compactor/metrics.rb +0 -147
- data/lib/swarm_sdk/context_compactor/token_counter.rb +0 -102
- data/lib/swarm_sdk/context_compactor.rb +0 -335
- data/lib/swarm_sdk/context_management/builder.rb +0 -128
- data/lib/swarm_sdk/context_management/context.rb +0 -328
- data/lib/swarm_sdk/custom_tool_registry.rb +0 -226
- data/lib/swarm_sdk/defaults.rb +0 -251
- data/lib/swarm_sdk/events_to_messages.rb +0 -199
- data/lib/swarm_sdk/hooks/adapter.rb +0 -359
- data/lib/swarm_sdk/hooks/context.rb +0 -197
- data/lib/swarm_sdk/hooks/definition.rb +0 -80
- data/lib/swarm_sdk/hooks/error.rb +0 -29
- data/lib/swarm_sdk/hooks/executor.rb +0 -146
- data/lib/swarm_sdk/hooks/registry.rb +0 -147
- data/lib/swarm_sdk/hooks/result.rb +0 -150
- data/lib/swarm_sdk/hooks/shell_executor.rb +0 -256
- data/lib/swarm_sdk/hooks/tool_call.rb +0 -35
- data/lib/swarm_sdk/hooks/tool_result.rb +0 -62
- data/lib/swarm_sdk/log_collector.rb +0 -227
- data/lib/swarm_sdk/log_stream.rb +0 -127
- data/lib/swarm_sdk/markdown_parser.rb +0 -75
- data/lib/swarm_sdk/model_aliases.json +0 -8
- data/lib/swarm_sdk/models.json +0 -44002
- data/lib/swarm_sdk/models.rb +0 -161
- data/lib/swarm_sdk/node_context.rb +0 -245
- data/lib/swarm_sdk/observer/builder.rb +0 -81
- data/lib/swarm_sdk/observer/config.rb +0 -45
- data/lib/swarm_sdk/observer/manager.rb +0 -236
- data/lib/swarm_sdk/patterns/agent_observer.rb +0 -160
- data/lib/swarm_sdk/permissions/config.rb +0 -239
- data/lib/swarm_sdk/permissions/error_formatter.rb +0 -121
- data/lib/swarm_sdk/permissions/path_matcher.rb +0 -35
- data/lib/swarm_sdk/permissions/validator.rb +0 -173
- data/lib/swarm_sdk/permissions_builder.rb +0 -122
- data/lib/swarm_sdk/plugin.rb +0 -309
- data/lib/swarm_sdk/plugin_registry.rb +0 -101
- data/lib/swarm_sdk/proc_helpers.rb +0 -53
- data/lib/swarm_sdk/prompts/base_system_prompt.md.erb +0 -117
- data/lib/swarm_sdk/restore_result.rb +0 -65
- data/lib/swarm_sdk/result.rb +0 -212
- data/lib/swarm_sdk/snapshot.rb +0 -156
- data/lib/swarm_sdk/snapshot_from_events.rb +0 -397
- data/lib/swarm_sdk/state_restorer.rb +0 -476
- data/lib/swarm_sdk/state_snapshot.rb +0 -334
- data/lib/swarm_sdk/swarm/agent_initializer.rb +0 -648
- data/lib/swarm_sdk/swarm/all_agents_builder.rb +0 -195
- data/lib/swarm_sdk/swarm/builder.rb +0 -256
- data/lib/swarm_sdk/swarm/executor.rb +0 -290
- data/lib/swarm_sdk/swarm/hook_triggers.rb +0 -151
- data/lib/swarm_sdk/swarm/lazy_delegate_chat.rb +0 -372
- data/lib/swarm_sdk/swarm/logging_callbacks.rb +0 -360
- data/lib/swarm_sdk/swarm/mcp_configurator.rb +0 -270
- data/lib/swarm_sdk/swarm/swarm_registry_builder.rb +0 -67
- data/lib/swarm_sdk/swarm/tool_configurator.rb +0 -392
- data/lib/swarm_sdk/swarm.rb +0 -843
- data/lib/swarm_sdk/swarm_loader.rb +0 -145
- data/lib/swarm_sdk/swarm_registry.rb +0 -136
- data/lib/swarm_sdk/tools/base.rb +0 -63
- data/lib/swarm_sdk/tools/bash.rb +0 -280
- data/lib/swarm_sdk/tools/clock.rb +0 -46
- data/lib/swarm_sdk/tools/delegate.rb +0 -389
- data/lib/swarm_sdk/tools/document_converters/base_converter.rb +0 -83
- data/lib/swarm_sdk/tools/document_converters/docx_converter.rb +0 -99
- data/lib/swarm_sdk/tools/document_converters/html_converter.rb +0 -101
- data/lib/swarm_sdk/tools/document_converters/pdf_converter.rb +0 -78
- data/lib/swarm_sdk/tools/document_converters/xlsx_converter.rb +0 -194
- data/lib/swarm_sdk/tools/edit.rb +0 -145
- data/lib/swarm_sdk/tools/glob.rb +0 -166
- data/lib/swarm_sdk/tools/grep.rb +0 -235
- data/lib/swarm_sdk/tools/image_extractors/docx_image_extractor.rb +0 -43
- data/lib/swarm_sdk/tools/image_extractors/pdf_image_extractor.rb +0 -167
- data/lib/swarm_sdk/tools/image_formats/tiff_builder.rb +0 -65
- data/lib/swarm_sdk/tools/mcp_tool_stub.rb +0 -198
- data/lib/swarm_sdk/tools/multi_edit.rb +0 -236
- data/lib/swarm_sdk/tools/path_resolver.rb +0 -92
- data/lib/swarm_sdk/tools/read.rb +0 -261
- data/lib/swarm_sdk/tools/registry.rb +0 -205
- data/lib/swarm_sdk/tools/scratchpad/scratchpad_list.rb +0 -117
- data/lib/swarm_sdk/tools/scratchpad/scratchpad_read.rb +0 -97
- data/lib/swarm_sdk/tools/scratchpad/scratchpad_write.rb +0 -108
- data/lib/swarm_sdk/tools/stores/read_tracker.rb +0 -96
- data/lib/swarm_sdk/tools/stores/scratchpad_storage.rb +0 -273
- data/lib/swarm_sdk/tools/stores/storage.rb +0 -142
- data/lib/swarm_sdk/tools/stores/todo_manager.rb +0 -65
- data/lib/swarm_sdk/tools/think.rb +0 -100
- data/lib/swarm_sdk/tools/todo_write.rb +0 -237
- data/lib/swarm_sdk/tools/web_fetch.rb +0 -264
- data/lib/swarm_sdk/tools/write.rb +0 -112
- data/lib/swarm_sdk/transcript_builder.rb +0 -278
- data/lib/swarm_sdk/utils.rb +0 -68
- data/lib/swarm_sdk/validation_result.rb +0 -33
- data/lib/swarm_sdk/version.rb +0 -5
- data/lib/swarm_sdk/workflow/agent_config.rb +0 -95
- data/lib/swarm_sdk/workflow/builder.rb +0 -227
- data/lib/swarm_sdk/workflow/executor.rb +0 -497
- data/lib/swarm_sdk/workflow/node_builder.rb +0 -593
- data/lib/swarm_sdk/workflow/transformer_executor.rb +0 -250
- data/lib/swarm_sdk/workflow.rb +0 -589
- data/lib/swarm_sdk.rb +0 -718
|
@@ -1,648 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module SwarmSDK
|
|
4
|
-
class Swarm
|
|
5
|
-
# Handles the complex 5-pass agent initialization process
|
|
6
|
-
#
|
|
7
|
-
# Responsibilities:
|
|
8
|
-
# - Create all agent chat instances (pass 1)
|
|
9
|
-
# - Register delegation tools (pass 2)
|
|
10
|
-
# - Setup agent contexts (pass 3)
|
|
11
|
-
# - Configure hook system (pass 4)
|
|
12
|
-
# - Apply YAML hooks if present (pass 5)
|
|
13
|
-
#
|
|
14
|
-
# This encapsulates the complex initialization logic that was previously
|
|
15
|
-
# embedded in Swarm#initialize_agents.
|
|
16
|
-
class AgentInitializer
|
|
17
|
-
# Initialize with swarm reference (all data accessible via swarm)
|
|
18
|
-
#
|
|
19
|
-
# @param swarm [Swarm] The parent swarm instance
|
|
20
|
-
def initialize(swarm)
|
|
21
|
-
@swarm = swarm
|
|
22
|
-
@agents = {}
|
|
23
|
-
@agent_contexts = {}
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
# Initialize all agents with their chat instances and tools
|
|
27
|
-
#
|
|
28
|
-
# This implements a 6-pass algorithm:
|
|
29
|
-
# 1. Create all Agent::Chat instances
|
|
30
|
-
# 2. Register delegation tools (agents can call each other)
|
|
31
|
-
# 3. Setup agent contexts for tracking
|
|
32
|
-
# 4. Configure hook system
|
|
33
|
-
# 5. Apply YAML hooks (if loaded from YAML)
|
|
34
|
-
# 6. Activate tools (Plan 025: populate @llm_chat.tools from registry after plugins)
|
|
35
|
-
#
|
|
36
|
-
# @return [Hash] agents hash { agent_name => Agent::Chat }
|
|
37
|
-
def initialize_all
|
|
38
|
-
pass_1_create_agents
|
|
39
|
-
pass_2_register_delegation_tools
|
|
40
|
-
pass_3_setup_contexts
|
|
41
|
-
pass_4_configure_hooks
|
|
42
|
-
pass_5_apply_yaml_hooks
|
|
43
|
-
pass_6_activate_tools # Plan 025: Activate tools after all plugins registered
|
|
44
|
-
|
|
45
|
-
@agents
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
# Provide access to agent contexts for Swarm
|
|
49
|
-
attr_reader :agent_contexts
|
|
50
|
-
|
|
51
|
-
# Initialize a single agent in isolation (for observer agents)
|
|
52
|
-
#
|
|
53
|
-
# Creates an isolated agent chat without delegation tools,
|
|
54
|
-
# suitable for observer agents that don't need to delegate.
|
|
55
|
-
# Reuses existing create_agent_chat infrastructure.
|
|
56
|
-
#
|
|
57
|
-
# @param agent_name [Symbol] Name of agent to initialize
|
|
58
|
-
# @return [Agent::Chat] Isolated agent chat instance
|
|
59
|
-
# @raise [ConfigurationError] If agent not found
|
|
60
|
-
#
|
|
61
|
-
# @example
|
|
62
|
-
# initializer = AgentInitializer.new(swarm)
|
|
63
|
-
# chat = initializer.initialize_isolated_agent(:profiler)
|
|
64
|
-
# chat.ask("Analyze this prompt")
|
|
65
|
-
def initialize_isolated_agent(agent_name)
|
|
66
|
-
agent_def = @swarm.agent_definitions[agent_name]
|
|
67
|
-
raise ConfigurationError, "Agent '#{agent_name}' not found" unless agent_def
|
|
68
|
-
|
|
69
|
-
# Ensure plugin storages are created (needed by ToolConfigurator)
|
|
70
|
-
create_plugin_storages if @swarm.plugin_storages.empty?
|
|
71
|
-
|
|
72
|
-
# Reuse existing create_agent_chat infrastructure
|
|
73
|
-
tool_configurator = ToolConfigurator.new(
|
|
74
|
-
@swarm,
|
|
75
|
-
@swarm.scratchpad_storage,
|
|
76
|
-
@swarm.plugin_storages,
|
|
77
|
-
)
|
|
78
|
-
|
|
79
|
-
# Create chat using same method as pass_1_create_agents
|
|
80
|
-
# This gives us full tool setup, MCP servers, etc.
|
|
81
|
-
create_agent_chat(agent_name, agent_def, tool_configurator)
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
# Create a tool that delegates work to another agent
|
|
85
|
-
#
|
|
86
|
-
# This method is public for testing delegation from Swarm.
|
|
87
|
-
#
|
|
88
|
-
# @param name [String] Delegate agent name
|
|
89
|
-
# @param description [String] Delegate agent description
|
|
90
|
-
# @param delegate_chat [Agent::Chat] The delegate's chat instance
|
|
91
|
-
# @param agent_name [Symbol] Name of the delegating agent
|
|
92
|
-
# @param delegating_chat [Agent::Chat, nil] The chat instance of the agent doing the delegating
|
|
93
|
-
# @param custom_tool_name [String, nil] Optional custom tool name (overrides auto-generated name)
|
|
94
|
-
# @param preserve_context [Boolean] Whether to preserve conversation context between delegations (default: true)
|
|
95
|
-
# @return [Tools::Delegate] Delegation tool
|
|
96
|
-
def create_delegation_tool(name:, description:, delegate_chat:, agent_name:, delegating_chat: nil, custom_tool_name: nil, preserve_context: true)
|
|
97
|
-
Tools::Delegate.new(
|
|
98
|
-
delegate_name: name,
|
|
99
|
-
delegate_description: description,
|
|
100
|
-
delegate_chat: delegate_chat,
|
|
101
|
-
agent_name: agent_name,
|
|
102
|
-
swarm: @swarm,
|
|
103
|
-
delegating_chat: delegating_chat,
|
|
104
|
-
custom_tool_name: custom_tool_name,
|
|
105
|
-
preserve_context: preserve_context,
|
|
106
|
-
)
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
private
|
|
110
|
-
|
|
111
|
-
# Pass 1: Create primary agent chat instances
|
|
112
|
-
#
|
|
113
|
-
# Only creates agents that will actually be used as primaries:
|
|
114
|
-
# - The lead agent
|
|
115
|
-
# - Agents with shared_across_delegations: true (shared delegates)
|
|
116
|
-
# - Agents not used as delegates (standalone agents)
|
|
117
|
-
#
|
|
118
|
-
# Agents that are ONLY delegates with shared_across_delegations: false
|
|
119
|
-
# are NOT created here - they'll be created as delegation instances in pass 2a.
|
|
120
|
-
#
|
|
121
|
-
# Agent creation is parallelized using Async::Barrier for faster initialization.
|
|
122
|
-
def pass_1_create_agents
|
|
123
|
-
# Create plugin storages for agents
|
|
124
|
-
create_plugin_storages
|
|
125
|
-
|
|
126
|
-
tool_configurator = ToolConfigurator.new(@swarm, @swarm.scratchpad_storage, @swarm.plugin_storages)
|
|
127
|
-
|
|
128
|
-
# Filter agents that need primary creation
|
|
129
|
-
agents_to_create = @swarm.agent_definitions.reject do |name, agent_definition|
|
|
130
|
-
should_skip_primary_creation?(name, agent_definition)
|
|
131
|
-
end
|
|
132
|
-
|
|
133
|
-
# Create agents in parallel using Async::Barrier
|
|
134
|
-
results = create_agents_in_parallel(agents_to_create, tool_configurator)
|
|
135
|
-
|
|
136
|
-
# Store results and notify plugins (sequential for safety)
|
|
137
|
-
results.each do |name, chat, agent_definition|
|
|
138
|
-
@agents[name] = chat
|
|
139
|
-
notify_plugins_agent_initialized(name, chat, agent_definition, tool_configurator)
|
|
140
|
-
end
|
|
141
|
-
end
|
|
142
|
-
|
|
143
|
-
# Create multiple agents in parallel using Async fibers
|
|
144
|
-
#
|
|
145
|
-
# @param agents_to_create [Hash] Hash of { name => agent_definition }
|
|
146
|
-
# @param tool_configurator [ToolConfigurator] Shared tool configurator
|
|
147
|
-
# @return [Array<Array>] Array of [name, chat, agent_definition] tuples
|
|
148
|
-
def create_agents_in_parallel(agents_to_create, tool_configurator)
|
|
149
|
-
return [] if agents_to_create.empty?
|
|
150
|
-
|
|
151
|
-
results = []
|
|
152
|
-
errors = []
|
|
153
|
-
mutex = Mutex.new
|
|
154
|
-
|
|
155
|
-
Sync do
|
|
156
|
-
barrier = Async::Barrier.new
|
|
157
|
-
|
|
158
|
-
agents_to_create.each do |name, agent_definition|
|
|
159
|
-
barrier.async do
|
|
160
|
-
chat = create_agent_chat(name, agent_definition, tool_configurator)
|
|
161
|
-
mutex.synchronize { results << [name, chat, agent_definition] }
|
|
162
|
-
rescue StandardError => e
|
|
163
|
-
# Catch errors to avoid Async warning logs (which fail in tests with StringIO)
|
|
164
|
-
mutex.synchronize { errors << [name, e] }
|
|
165
|
-
end
|
|
166
|
-
end
|
|
167
|
-
|
|
168
|
-
barrier.wait
|
|
169
|
-
end
|
|
170
|
-
|
|
171
|
-
# Re-raise first error if any occurred
|
|
172
|
-
unless errors.empty?
|
|
173
|
-
# Emit events for all errors (not just the first)
|
|
174
|
-
errors.each do |agent_name, err|
|
|
175
|
-
LogStream.emit(
|
|
176
|
-
type: "agent_initialization_error",
|
|
177
|
-
agent: agent_name,
|
|
178
|
-
error_class: err.class.name,
|
|
179
|
-
error_message: err.message,
|
|
180
|
-
timestamp: Time.now.utc.iso8601,
|
|
181
|
-
)
|
|
182
|
-
end
|
|
183
|
-
|
|
184
|
-
# Re-raise first error with context
|
|
185
|
-
name, error = errors.first
|
|
186
|
-
raise error.class, "Agent '#{name}' initialization failed: #{error.message}", error.backtrace
|
|
187
|
-
end
|
|
188
|
-
|
|
189
|
-
results
|
|
190
|
-
end
|
|
191
|
-
|
|
192
|
-
# Pass 2: Wire delegation tools (lazy loading for isolated delegates)
|
|
193
|
-
#
|
|
194
|
-
# This pass wires delegation tools for primary agents:
|
|
195
|
-
# - Shared delegates use the primary agent instance
|
|
196
|
-
# - Isolated delegates use LazyDelegateChat (created on first use)
|
|
197
|
-
#
|
|
198
|
-
# Sub-pass 2a (eager creation) is REMOVED - delegation instances are now lazy.
|
|
199
|
-
# Sub-pass 2c (nested delegation) is handled by LazyDelegateChat when initialized.
|
|
200
|
-
def pass_2_register_delegation_tools
|
|
201
|
-
tool_configurator = ToolConfigurator.new(@swarm, @swarm.scratchpad_storage, @swarm.plugin_storages)
|
|
202
|
-
|
|
203
|
-
# Wire primary agents to delegates (shared primaries or lazy loaders)
|
|
204
|
-
@swarm.agent_definitions.each do |delegator_name, delegator_def|
|
|
205
|
-
delegator_chat = @agents[delegator_name]
|
|
206
|
-
|
|
207
|
-
# Skip if delegator doesn't exist as primary (wasn't created in pass_1)
|
|
208
|
-
next unless delegator_chat
|
|
209
|
-
|
|
210
|
-
delegator_def.delegation_configs.each do |delegation_config|
|
|
211
|
-
wire_delegation(
|
|
212
|
-
delegator_name: delegator_name,
|
|
213
|
-
delegator_chat: delegator_chat,
|
|
214
|
-
delegation_config: delegation_config,
|
|
215
|
-
tool_configurator: tool_configurator,
|
|
216
|
-
)
|
|
217
|
-
end
|
|
218
|
-
end
|
|
219
|
-
|
|
220
|
-
# NOTE: Nested delegation wiring is now handled by LazyDelegateChat#wire_delegation_tools
|
|
221
|
-
# when the lazy delegate is first accessed.
|
|
222
|
-
end
|
|
223
|
-
|
|
224
|
-
# Wire a single delegation from one agent to a delegate
|
|
225
|
-
#
|
|
226
|
-
# For isolated delegates, creates a LazyDelegateChat wrapper instead of
|
|
227
|
-
# eagerly creating the chat instance.
|
|
228
|
-
#
|
|
229
|
-
# @param delegator_name [Symbol, String] Name of the agent doing the delegating
|
|
230
|
-
# @param delegator_chat [Agent::Chat] Chat instance of the delegator
|
|
231
|
-
# @param delegation_config [Hash] Delegation configuration with :agent, :tool_name, and :preserve_context keys
|
|
232
|
-
# @param tool_configurator [ToolConfigurator] Tool configuration helper
|
|
233
|
-
# @return [void]
|
|
234
|
-
def wire_delegation(delegator_name:, delegator_chat:, delegation_config:, tool_configurator:)
|
|
235
|
-
delegate_name_sym = delegation_config[:agent]
|
|
236
|
-
delegate_name_str = delegate_name_sym.to_s
|
|
237
|
-
custom_tool_name = delegation_config[:tool_name]
|
|
238
|
-
preserve_context = delegation_config.fetch(:preserve_context, true)
|
|
239
|
-
|
|
240
|
-
# Check if target is a registered swarm
|
|
241
|
-
if @swarm.swarm_registry&.registered?(delegate_name_str)
|
|
242
|
-
wire_swarm_delegation(delegator_name, delegator_chat, delegate_name_str, custom_tool_name, preserve_context)
|
|
243
|
-
elsif @swarm.agent_definitions.key?(delegate_name_sym)
|
|
244
|
-
wire_agent_delegation(
|
|
245
|
-
delegator_name: delegator_name,
|
|
246
|
-
delegator_chat: delegator_chat,
|
|
247
|
-
delegate_name_sym: delegate_name_sym,
|
|
248
|
-
custom_tool_name: custom_tool_name,
|
|
249
|
-
preserve_context: preserve_context,
|
|
250
|
-
)
|
|
251
|
-
else
|
|
252
|
-
raise ConfigurationError,
|
|
253
|
-
"Agent '#{delegator_name}' delegates to unknown target '#{delegate_name_str}' (not a local agent or registered swarm)"
|
|
254
|
-
end
|
|
255
|
-
end
|
|
256
|
-
|
|
257
|
-
# Wire delegation to an external swarm
|
|
258
|
-
#
|
|
259
|
-
# @param delegator_name [Symbol, String] Name of the delegating agent
|
|
260
|
-
# @param delegator_chat [Agent::Chat] Chat instance of the delegator
|
|
261
|
-
# @param swarm_name [String] Name of the registered swarm
|
|
262
|
-
# @param custom_tool_name [String, nil] Optional custom tool name
|
|
263
|
-
# @param preserve_context [Boolean] Whether to preserve context between delegations
|
|
264
|
-
# @return [void]
|
|
265
|
-
def wire_swarm_delegation(delegator_name, delegator_chat, swarm_name, custom_tool_name, preserve_context)
|
|
266
|
-
tool = create_delegation_tool(
|
|
267
|
-
name: swarm_name,
|
|
268
|
-
description: "External swarm: #{swarm_name}",
|
|
269
|
-
delegate_chat: nil, # Swarm delegation - no direct chat
|
|
270
|
-
agent_name: delegator_name,
|
|
271
|
-
delegating_chat: delegator_chat,
|
|
272
|
-
custom_tool_name: custom_tool_name,
|
|
273
|
-
preserve_context: preserve_context,
|
|
274
|
-
)
|
|
275
|
-
|
|
276
|
-
# Register in tool registry (Plan 025)
|
|
277
|
-
delegator_chat.tool_registry.register(
|
|
278
|
-
tool,
|
|
279
|
-
source: :delegation,
|
|
280
|
-
metadata: { delegate_name: swarm_name, delegation_type: :swarm, preserve_context: preserve_context },
|
|
281
|
-
)
|
|
282
|
-
end
|
|
283
|
-
|
|
284
|
-
# Wire delegation to a local agent
|
|
285
|
-
#
|
|
286
|
-
# For shared delegates, uses the primary agent instance.
|
|
287
|
-
# For isolated delegates, creates a LazyDelegateChat wrapper that
|
|
288
|
-
# defers creation until first use.
|
|
289
|
-
#
|
|
290
|
-
# @param delegator_name [Symbol, String] Name of the delegating agent
|
|
291
|
-
# @param delegator_chat [Agent::Chat] Chat instance of the delegator
|
|
292
|
-
# @param delegate_name_sym [Symbol] Name of the delegate agent
|
|
293
|
-
# @param custom_tool_name [String, nil] Optional custom tool name
|
|
294
|
-
# @param preserve_context [Boolean] Whether to preserve context between delegations
|
|
295
|
-
# @return [void]
|
|
296
|
-
def wire_agent_delegation(delegator_name:, delegator_chat:, delegate_name_sym:, custom_tool_name:, preserve_context:)
|
|
297
|
-
delegate_definition = @swarm.agent_definitions[delegate_name_sym]
|
|
298
|
-
|
|
299
|
-
# Determine which chat instance to use
|
|
300
|
-
target_chat = if delegate_definition.shared_across_delegations
|
|
301
|
-
# Shared mode: use primary agent (semaphore-protected)
|
|
302
|
-
@agents[delegate_name_sym]
|
|
303
|
-
else
|
|
304
|
-
# Isolated mode: use lazy loader (created on first delegation)
|
|
305
|
-
instance_name = "#{delegate_name_sym}@#{delegator_name}"
|
|
306
|
-
|
|
307
|
-
LazyDelegateChat.new(
|
|
308
|
-
instance_name: instance_name,
|
|
309
|
-
base_name: delegate_name_sym,
|
|
310
|
-
agent_definition: delegate_definition,
|
|
311
|
-
swarm: @swarm,
|
|
312
|
-
)
|
|
313
|
-
end
|
|
314
|
-
|
|
315
|
-
# Create delegation tool pointing to chosen instance (or lazy loader)
|
|
316
|
-
tool = create_delegation_tool(
|
|
317
|
-
name: delegate_name_sym.to_s,
|
|
318
|
-
description: delegate_definition.description,
|
|
319
|
-
delegate_chat: target_chat,
|
|
320
|
-
agent_name: delegator_name,
|
|
321
|
-
delegating_chat: delegator_chat,
|
|
322
|
-
custom_tool_name: custom_tool_name,
|
|
323
|
-
preserve_context: preserve_context,
|
|
324
|
-
)
|
|
325
|
-
|
|
326
|
-
# Register in tool registry (Plan 025)
|
|
327
|
-
delegator_chat.tool_registry.register(
|
|
328
|
-
tool,
|
|
329
|
-
source: :delegation,
|
|
330
|
-
metadata: {
|
|
331
|
-
delegate_name: delegate_name_sym,
|
|
332
|
-
delegation_mode: delegate_definition.shared_across_delegations ? :shared : :isolated,
|
|
333
|
-
preserve_context: preserve_context,
|
|
334
|
-
},
|
|
335
|
-
)
|
|
336
|
-
end
|
|
337
|
-
|
|
338
|
-
# Pass 3: Setup agent contexts
|
|
339
|
-
#
|
|
340
|
-
# Create Agent::Context for each agent to track delegations and metadata.
|
|
341
|
-
# This is needed regardless of whether logging is enabled.
|
|
342
|
-
#
|
|
343
|
-
# NOTE: Delegation instances are now lazy-loaded, so their contexts are
|
|
344
|
-
# set up in LazyDelegateChat#setup_context when first accessed.
|
|
345
|
-
def pass_3_setup_contexts
|
|
346
|
-
# Setup contexts for PRIMARY agents only
|
|
347
|
-
# (Delegation instances handle their own context setup via LazyDelegateChat)
|
|
348
|
-
@agents.each do |agent_name, chat|
|
|
349
|
-
setup_agent_context(agent_name, @swarm.agent_definitions[agent_name], chat, is_delegation: false)
|
|
350
|
-
end
|
|
351
|
-
end
|
|
352
|
-
|
|
353
|
-
# Setup context for an agent (primary or delegation instance)
|
|
354
|
-
def setup_agent_context(agent_name, agent_definition, chat, is_delegation: false)
|
|
355
|
-
# Generate actual tool names (custom or auto-generated) for context tracking
|
|
356
|
-
delegate_tool_names = agent_definition.delegation_configs.map do |delegation_config|
|
|
357
|
-
# Use custom name if provided, otherwise auto-generate
|
|
358
|
-
delegation_config[:tool_name] || Tools::Delegate.tool_name_for(delegation_config[:agent])
|
|
359
|
-
end
|
|
360
|
-
|
|
361
|
-
context = Agent::Context.new(
|
|
362
|
-
name: agent_name,
|
|
363
|
-
swarm_id: @swarm.swarm_id,
|
|
364
|
-
parent_swarm_id: @swarm.parent_swarm_id,
|
|
365
|
-
delegation_tools: delegate_tool_names,
|
|
366
|
-
metadata: { is_delegation_instance: is_delegation },
|
|
367
|
-
)
|
|
368
|
-
|
|
369
|
-
# Store context (only for primaries)
|
|
370
|
-
@agent_contexts[agent_name] = context unless is_delegation
|
|
371
|
-
|
|
372
|
-
# Always set agent context on chat
|
|
373
|
-
chat.setup_context(context) if chat.respond_to?(:setup_context)
|
|
374
|
-
|
|
375
|
-
# Configure logging if enabled
|
|
376
|
-
return unless LogStream.emitter
|
|
377
|
-
|
|
378
|
-
chat.setup_logging if chat.respond_to?(:setup_logging)
|
|
379
|
-
|
|
380
|
-
# Emit validation warnings (only for primaries, not each delegation instance)
|
|
381
|
-
emit_validation_warnings(agent_name, agent_definition) unless is_delegation
|
|
382
|
-
end
|
|
383
|
-
|
|
384
|
-
# Emit validation warnings as log events
|
|
385
|
-
#
|
|
386
|
-
# This validates the agent definition and emits any warnings as log events
|
|
387
|
-
# through LogStream (so formatters can handle them).
|
|
388
|
-
#
|
|
389
|
-
# @param agent_name [Symbol] Agent name
|
|
390
|
-
# @param agent_definition [Agent::Definition] Agent definition to validate
|
|
391
|
-
# @return [void]
|
|
392
|
-
def emit_validation_warnings(agent_name, agent_definition)
|
|
393
|
-
warnings = agent_definition.validate
|
|
394
|
-
|
|
395
|
-
warnings.each do |warning|
|
|
396
|
-
case warning[:type]
|
|
397
|
-
when :model_not_found
|
|
398
|
-
LogStream.emit(
|
|
399
|
-
type: "model_lookup_warning",
|
|
400
|
-
agent: agent_name,
|
|
401
|
-
model: warning[:model],
|
|
402
|
-
error_message: warning[:error_message],
|
|
403
|
-
suggestions: warning[:suggestions],
|
|
404
|
-
timestamp: Time.now.utc.iso8601,
|
|
405
|
-
)
|
|
406
|
-
end
|
|
407
|
-
end
|
|
408
|
-
end
|
|
409
|
-
|
|
410
|
-
# Pass 4: Configure hook system
|
|
411
|
-
#
|
|
412
|
-
# Setup the callback system for each agent, integrating with RubyLLM callbacks.
|
|
413
|
-
#
|
|
414
|
-
# NOTE: Delegation instances are now lazy-loaded, so their hooks are
|
|
415
|
-
# configured in LazyDelegateChat#configure_hooks when first accessed.
|
|
416
|
-
def pass_4_configure_hooks
|
|
417
|
-
# Configure hooks for PRIMARY agents only
|
|
418
|
-
# (Delegation instances handle their own hook setup via LazyDelegateChat)
|
|
419
|
-
@agents.each do |agent_name, chat|
|
|
420
|
-
configure_hooks_for_agent(agent_name, chat)
|
|
421
|
-
end
|
|
422
|
-
end
|
|
423
|
-
|
|
424
|
-
# Configure hooks for an agent (primary or delegation instance)
|
|
425
|
-
def configure_hooks_for_agent(agent_name, chat)
|
|
426
|
-
base_name = extract_base_name(agent_name)
|
|
427
|
-
agent_definition = @swarm.agent_definitions[base_name]
|
|
428
|
-
|
|
429
|
-
chat.setup_hooks(
|
|
430
|
-
registry: @swarm.hook_registry,
|
|
431
|
-
agent_definition: agent_definition,
|
|
432
|
-
swarm: @swarm,
|
|
433
|
-
) if chat.respond_to?(:setup_hooks)
|
|
434
|
-
end
|
|
435
|
-
|
|
436
|
-
# Pass 5: Apply YAML hooks
|
|
437
|
-
#
|
|
438
|
-
# If the swarm was loaded from YAML with agent-specific hooks,
|
|
439
|
-
# apply them now via HooksAdapter.
|
|
440
|
-
#
|
|
441
|
-
# NOTE: Delegation instances are now lazy-loaded, so their YAML hooks are
|
|
442
|
-
# applied in LazyDelegateChat#apply_yaml_hooks when first accessed.
|
|
443
|
-
def pass_5_apply_yaml_hooks
|
|
444
|
-
return unless @swarm.config_for_hooks
|
|
445
|
-
|
|
446
|
-
# Apply YAML hooks to PRIMARY agents only
|
|
447
|
-
# (Delegation instances handle their own YAML hooks via LazyDelegateChat)
|
|
448
|
-
@agents.each do |agent_name, chat|
|
|
449
|
-
apply_yaml_hooks_for_agent(agent_name, chat)
|
|
450
|
-
end
|
|
451
|
-
end
|
|
452
|
-
|
|
453
|
-
# Apply YAML hooks for an agent (primary or delegation instance)
|
|
454
|
-
def apply_yaml_hooks_for_agent(agent_name, chat)
|
|
455
|
-
base_name = extract_base_name(agent_name)
|
|
456
|
-
agent_config = @swarm.config_for_hooks.agents[base_name]
|
|
457
|
-
return unless agent_config
|
|
458
|
-
|
|
459
|
-
# Configuration.agents now returns hashes, not Definitions
|
|
460
|
-
hooks = agent_config.is_a?(Hash) ? agent_config[:hooks] : agent_config.hooks
|
|
461
|
-
return unless hooks&.any?
|
|
462
|
-
|
|
463
|
-
Hooks::Adapter.apply_agent_hooks(chat, agent_name, hooks, @swarm.name)
|
|
464
|
-
end
|
|
465
|
-
|
|
466
|
-
# Pass 6: Activate tools after all plugins have registered (Plan 025)
|
|
467
|
-
#
|
|
468
|
-
# This must be the LAST pass because:
|
|
469
|
-
# - Plugins register tools in on_agent_initialized (e.g., LoadSkill from memory plugin)
|
|
470
|
-
# - Tools must be activated AFTER all registration is complete
|
|
471
|
-
# - This populates @llm_chat.tools from the registry
|
|
472
|
-
#
|
|
473
|
-
# NOTE: Delegation instances are now lazy-loaded, so their tools are
|
|
474
|
-
# activated in LazyDelegateChat#initialize_chat when first accessed.
|
|
475
|
-
#
|
|
476
|
-
# @return [void]
|
|
477
|
-
def pass_6_activate_tools
|
|
478
|
-
# Activate tools for PRIMARY agents only
|
|
479
|
-
# (Delegation instances handle their own tool activation via LazyDelegateChat)
|
|
480
|
-
@agents.each_value(&:activate_tools_for_prompt)
|
|
481
|
-
end
|
|
482
|
-
|
|
483
|
-
# Create Agent::Chat instance with rate limiting
|
|
484
|
-
#
|
|
485
|
-
# @param agent_name [Symbol] Agent name
|
|
486
|
-
# @param agent_definition [Agent::Definition] Agent definition object
|
|
487
|
-
# @param tool_configurator [ToolConfigurator] Tool configuration helper
|
|
488
|
-
# @return [Agent::Chat] Configured agent chat instance
|
|
489
|
-
def create_agent_chat(agent_name, agent_definition, tool_configurator)
|
|
490
|
-
chat = Agent::Chat.new(
|
|
491
|
-
definition: agent_definition.to_h,
|
|
492
|
-
agent_name: agent_name,
|
|
493
|
-
global_semaphore: @swarm.global_semaphore,
|
|
494
|
-
)
|
|
495
|
-
|
|
496
|
-
# Set agent name on provider for logging (if provider supports it)
|
|
497
|
-
chat.provider.agent_name = agent_name if chat.provider.respond_to?(:agent_name=)
|
|
498
|
-
|
|
499
|
-
# Register tools using ToolConfigurator
|
|
500
|
-
tool_configurator.register_all_tools(
|
|
501
|
-
chat: chat,
|
|
502
|
-
agent_name: agent_name,
|
|
503
|
-
agent_definition: agent_definition,
|
|
504
|
-
)
|
|
505
|
-
|
|
506
|
-
# Register MCP servers using McpConfigurator
|
|
507
|
-
if agent_definition.mcp_servers.any?
|
|
508
|
-
mcp_configurator = McpConfigurator.new(@swarm)
|
|
509
|
-
mcp_configurator.register_mcp_servers(chat, agent_definition.mcp_servers, agent_name: agent_name)
|
|
510
|
-
end
|
|
511
|
-
|
|
512
|
-
# Setup tool activation dependencies (Plan 025)
|
|
513
|
-
chat.setup_tool_activation(
|
|
514
|
-
tool_configurator: tool_configurator,
|
|
515
|
-
agent_definition: agent_definition,
|
|
516
|
-
)
|
|
517
|
-
|
|
518
|
-
# NOTE: activate_tools_for_prompt is called in Pass 5 after all plugins
|
|
519
|
-
# have registered their tools (e.g., LoadSkill from memory plugin)
|
|
520
|
-
|
|
521
|
-
chat
|
|
522
|
-
end
|
|
523
|
-
|
|
524
|
-
# NOTE: create_agent_chat_for_delegation and register_delegation_tools were removed.
|
|
525
|
-
# Delegation instances are now lazy-loaded via LazyDelegateChat.
|
|
526
|
-
|
|
527
|
-
# Create plugin storages for all agents
|
|
528
|
-
#
|
|
529
|
-
# Iterates through all registered plugins and asks each to create
|
|
530
|
-
# storage for agents that need it.
|
|
531
|
-
#
|
|
532
|
-
# @return [void]
|
|
533
|
-
def create_plugin_storages
|
|
534
|
-
PluginRegistry.all.each do |plugin|
|
|
535
|
-
@swarm.agent_definitions.each do |agent_name, agent_definition|
|
|
536
|
-
# Check if this plugin needs storage for this agent
|
|
537
|
-
next unless plugin.memory_configured?(agent_definition)
|
|
538
|
-
|
|
539
|
-
# Get plugin config for this agent
|
|
540
|
-
config = get_plugin_config(agent_definition, plugin.name)
|
|
541
|
-
next unless config
|
|
542
|
-
|
|
543
|
-
# Parse config through plugin
|
|
544
|
-
parsed_config = plugin.parse_config(config)
|
|
545
|
-
|
|
546
|
-
# Create plugin storage
|
|
547
|
-
storage = plugin.create_storage(agent_name: agent_name, config: parsed_config)
|
|
548
|
-
|
|
549
|
-
# Store in plugin_storages: { plugin_name => { agent_name => storage } }
|
|
550
|
-
@swarm.plugin_storages[plugin.name] ||= {}
|
|
551
|
-
@swarm.plugin_storages[plugin.name][agent_name] = storage
|
|
552
|
-
end
|
|
553
|
-
end
|
|
554
|
-
end
|
|
555
|
-
|
|
556
|
-
# Get plugin-specific config from agent definition
|
|
557
|
-
#
|
|
558
|
-
# Uses the generic plugin_configs accessor to retrieve plugin-specific config.
|
|
559
|
-
# E.g., memory plugin config is accessed via `agent_definition.plugin_config(:memory)`
|
|
560
|
-
#
|
|
561
|
-
# @param agent_definition [Agent::Definition] Agent definition
|
|
562
|
-
# @param plugin_name [Symbol] Plugin name
|
|
563
|
-
# @return [Object, nil] Plugin config or nil
|
|
564
|
-
def get_plugin_config(agent_definition, plugin_name)
|
|
565
|
-
# Use generic plugin config accessor
|
|
566
|
-
agent_definition.plugin_config(plugin_name)
|
|
567
|
-
end
|
|
568
|
-
|
|
569
|
-
# Notify all plugins that an agent was initialized
|
|
570
|
-
#
|
|
571
|
-
# Plugins can register additional tools, mark tools immutable, etc.
|
|
572
|
-
#
|
|
573
|
-
# @param agent_name [Symbol] Agent name
|
|
574
|
-
# @param chat [Agent::Chat] Chat instance
|
|
575
|
-
# @param agent_definition [Agent::Definition] Agent definition
|
|
576
|
-
# @param tool_configurator [ToolConfigurator] Tool configurator
|
|
577
|
-
# @return [void]
|
|
578
|
-
def notify_plugins_agent_initialized(agent_name, chat, agent_definition, tool_configurator)
|
|
579
|
-
PluginRegistry.all.each do |plugin|
|
|
580
|
-
# Get plugin storage for this agent (if any)
|
|
581
|
-
plugin_storages = @swarm.plugin_storages[plugin.name] || {}
|
|
582
|
-
storage = plugin_storages[agent_name]
|
|
583
|
-
|
|
584
|
-
# Build context for plugin
|
|
585
|
-
context = {
|
|
586
|
-
storage: storage,
|
|
587
|
-
agent_definition: agent_definition,
|
|
588
|
-
tool_configurator: tool_configurator,
|
|
589
|
-
}
|
|
590
|
-
|
|
591
|
-
# Notify plugin
|
|
592
|
-
plugin.on_agent_initialized(agent_name: agent_name, agent: chat, context: context)
|
|
593
|
-
end
|
|
594
|
-
end
|
|
595
|
-
|
|
596
|
-
# Determine if we should skip creating a primary agent
|
|
597
|
-
#
|
|
598
|
-
# Skip if:
|
|
599
|
-
# - NOT the lead agent, AND
|
|
600
|
-
# - Has shared_across_delegations: false (isolated mode), AND
|
|
601
|
-
# - Is only referenced as a delegate (not used standalone)
|
|
602
|
-
#
|
|
603
|
-
# @param name [Symbol] Agent name
|
|
604
|
-
# @param agent_definition [Agent::Definition] Agent definition
|
|
605
|
-
# @return [Boolean] True if should skip primary creation
|
|
606
|
-
def should_skip_primary_creation?(name, agent_definition)
|
|
607
|
-
# Always create lead agent
|
|
608
|
-
return false if name == @swarm.lead_agent
|
|
609
|
-
|
|
610
|
-
# If shared mode, create primary (delegates will use it)
|
|
611
|
-
return false if agent_definition.shared_across_delegations
|
|
612
|
-
|
|
613
|
-
# Skip if only used as a delegate
|
|
614
|
-
only_referenced_as_delegate?(name)
|
|
615
|
-
end
|
|
616
|
-
|
|
617
|
-
# Check if an agent is only referenced as a delegate
|
|
618
|
-
#
|
|
619
|
-
# @param name [Symbol] Agent name
|
|
620
|
-
# @return [Boolean] True if only referenced as delegate
|
|
621
|
-
def only_referenced_as_delegate?(name)
|
|
622
|
-
# Check if any agent delegates to this one
|
|
623
|
-
referenced_as_delegate = @swarm.agent_definitions.any? do |_agent_name, definition|
|
|
624
|
-
definition.delegates_to.include?(name)
|
|
625
|
-
end
|
|
626
|
-
|
|
627
|
-
# Skip if referenced as delegate (and not lead, already checked above)
|
|
628
|
-
referenced_as_delegate
|
|
629
|
-
end
|
|
630
|
-
|
|
631
|
-
# Extract base agent name from instance name
|
|
632
|
-
#
|
|
633
|
-
# @param instance_name [Symbol, String] Instance name (may be delegation instance)
|
|
634
|
-
# @return [Symbol] Base agent name
|
|
635
|
-
def extract_base_name(instance_name)
|
|
636
|
-
instance_name.to_s.split("@").first.to_sym
|
|
637
|
-
end
|
|
638
|
-
|
|
639
|
-
# Check if instance name is a delegation instance
|
|
640
|
-
#
|
|
641
|
-
# @param instance_name [Symbol, String] Instance name
|
|
642
|
-
# @return [Boolean] True if delegation instance (contains '@')
|
|
643
|
-
def delegation_instance?(instance_name)
|
|
644
|
-
instance_name.to_s.include?("@")
|
|
645
|
-
end
|
|
646
|
-
end
|
|
647
|
-
end
|
|
648
|
-
end
|