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.
Files changed (183) hide show
  1. checksums.yaml +4 -4
  2. data/lib/swarm_sdk/ruby_llm_patches/chat_callbacks_patch.rb +43 -22
  3. data/lib/swarm_sdk/ruby_llm_patches/init.rb +6 -0
  4. data/lib/swarm_sdk/ruby_llm_patches/mcp_ssl_patch.rb +144 -0
  5. data/lib/swarm_sdk/ruby_llm_patches/tool_concurrency_patch.rb +3 -4
  6. data/lib/swarm_sdk/v3/agent.rb +1165 -0
  7. data/lib/swarm_sdk/v3/agent_builder.rb +533 -0
  8. data/lib/swarm_sdk/v3/agent_definition.rb +330 -0
  9. data/lib/swarm_sdk/v3/configuration.rb +490 -0
  10. data/lib/swarm_sdk/v3/debug_log.rb +86 -0
  11. data/lib/swarm_sdk/v3/event_stream.rb +130 -0
  12. data/lib/swarm_sdk/v3/hooks/context.rb +112 -0
  13. data/lib/swarm_sdk/v3/hooks/result.rb +115 -0
  14. data/lib/swarm_sdk/v3/hooks/runner.rb +128 -0
  15. data/lib/swarm_sdk/v3/mcp/connector.rb +183 -0
  16. data/lib/swarm_sdk/v3/mcp/mcp_error.rb +15 -0
  17. data/lib/swarm_sdk/v3/mcp/server_definition.rb +125 -0
  18. data/lib/swarm_sdk/v3/mcp/ssl_http_transport.rb +103 -0
  19. data/lib/swarm_sdk/v3/mcp/stdio_transport.rb +135 -0
  20. data/lib/swarm_sdk/v3/mcp/tool_proxy.rb +53 -0
  21. data/lib/swarm_sdk/v3/memory/adapters/base.rb +297 -0
  22. data/lib/swarm_sdk/v3/memory/adapters/faiss_support.rb +194 -0
  23. data/lib/swarm_sdk/v3/memory/adapters/filesystem_adapter.rb +212 -0
  24. data/lib/swarm_sdk/v3/memory/adapters/sqlite_adapter.rb +507 -0
  25. data/lib/swarm_sdk/v3/memory/adapters/vector_utils.rb +88 -0
  26. data/lib/swarm_sdk/v3/memory/card.rb +206 -0
  27. data/lib/swarm_sdk/v3/memory/cluster.rb +146 -0
  28. data/lib/swarm_sdk/v3/memory/compressor.rb +496 -0
  29. data/lib/swarm_sdk/v3/memory/consolidator.rb +427 -0
  30. data/lib/swarm_sdk/v3/memory/context_builder.rb +339 -0
  31. data/lib/swarm_sdk/v3/memory/edge.rb +105 -0
  32. data/lib/swarm_sdk/v3/memory/embedder.rb +185 -0
  33. data/lib/swarm_sdk/v3/memory/exposure_tracker.rb +104 -0
  34. data/lib/swarm_sdk/v3/memory/ingestion_pipeline.rb +394 -0
  35. data/lib/swarm_sdk/v3/memory/retriever.rb +289 -0
  36. data/lib/swarm_sdk/v3/memory/store.rb +489 -0
  37. data/lib/swarm_sdk/v3/skills/loader.rb +147 -0
  38. data/lib/swarm_sdk/v3/skills/manifest.rb +45 -0
  39. data/lib/swarm_sdk/v3/sub_task_agent.rb +248 -0
  40. data/lib/swarm_sdk/v3/tools/base.rb +80 -0
  41. data/lib/swarm_sdk/v3/tools/bash.rb +174 -0
  42. data/lib/swarm_sdk/v3/tools/clock.rb +32 -0
  43. data/lib/swarm_sdk/v3/tools/edit.rb +111 -0
  44. data/lib/swarm_sdk/v3/tools/glob.rb +96 -0
  45. data/lib/swarm_sdk/v3/tools/grep.rb +200 -0
  46. data/lib/swarm_sdk/v3/tools/message_teammate.rb +15 -0
  47. data/lib/swarm_sdk/v3/tools/message_user.rb +15 -0
  48. data/lib/swarm_sdk/v3/tools/read.rb +181 -0
  49. data/lib/swarm_sdk/v3/tools/read_tracker.rb +40 -0
  50. data/lib/swarm_sdk/v3/tools/registry.rb +208 -0
  51. data/lib/swarm_sdk/v3/tools/sub_task.rb +183 -0
  52. data/lib/swarm_sdk/v3/tools/think.rb +88 -0
  53. data/lib/swarm_sdk/v3/tools/write.rb +87 -0
  54. data/lib/swarm_sdk/v3.rb +145 -0
  55. metadata +84 -148
  56. data/lib/swarm_sdk/agent/RETRY_LOGIC.md +0 -175
  57. data/lib/swarm_sdk/agent/builder.rb +0 -680
  58. data/lib/swarm_sdk/agent/chat.rb +0 -1432
  59. data/lib/swarm_sdk/agent/chat_helpers/context_tracker.rb +0 -375
  60. data/lib/swarm_sdk/agent/chat_helpers/event_emitter.rb +0 -204
  61. data/lib/swarm_sdk/agent/chat_helpers/hook_integration.rb +0 -480
  62. data/lib/swarm_sdk/agent/chat_helpers/instrumentation.rb +0 -85
  63. data/lib/swarm_sdk/agent/chat_helpers/llm_configuration.rb +0 -290
  64. data/lib/swarm_sdk/agent/chat_helpers/logging_helpers.rb +0 -116
  65. data/lib/swarm_sdk/agent/chat_helpers/serialization.rb +0 -83
  66. data/lib/swarm_sdk/agent/chat_helpers/system_reminder_injector.rb +0 -134
  67. data/lib/swarm_sdk/agent/chat_helpers/system_reminders.rb +0 -79
  68. data/lib/swarm_sdk/agent/chat_helpers/token_tracking.rb +0 -146
  69. data/lib/swarm_sdk/agent/context.rb +0 -115
  70. data/lib/swarm_sdk/agent/context_manager.rb +0 -315
  71. data/lib/swarm_sdk/agent/definition.rb +0 -581
  72. data/lib/swarm_sdk/agent/llm_instrumentation_middleware.rb +0 -226
  73. data/lib/swarm_sdk/agent/system_prompt_builder.rb +0 -161
  74. data/lib/swarm_sdk/agent/tool_registry.rb +0 -189
  75. data/lib/swarm_sdk/agent_registry.rb +0 -146
  76. data/lib/swarm_sdk/builders/base_builder.rb +0 -553
  77. data/lib/swarm_sdk/claude_code_agent_adapter.rb +0 -205
  78. data/lib/swarm_sdk/concerns/cleanupable.rb +0 -39
  79. data/lib/swarm_sdk/concerns/snapshotable.rb +0 -67
  80. data/lib/swarm_sdk/concerns/validatable.rb +0 -55
  81. data/lib/swarm_sdk/config.rb +0 -367
  82. data/lib/swarm_sdk/configuration/parser.rb +0 -397
  83. data/lib/swarm_sdk/configuration/translator.rb +0 -283
  84. data/lib/swarm_sdk/configuration.rb +0 -165
  85. data/lib/swarm_sdk/context_compactor/metrics.rb +0 -147
  86. data/lib/swarm_sdk/context_compactor/token_counter.rb +0 -102
  87. data/lib/swarm_sdk/context_compactor.rb +0 -335
  88. data/lib/swarm_sdk/context_management/builder.rb +0 -128
  89. data/lib/swarm_sdk/context_management/context.rb +0 -328
  90. data/lib/swarm_sdk/custom_tool_registry.rb +0 -226
  91. data/lib/swarm_sdk/defaults.rb +0 -251
  92. data/lib/swarm_sdk/events_to_messages.rb +0 -199
  93. data/lib/swarm_sdk/hooks/adapter.rb +0 -359
  94. data/lib/swarm_sdk/hooks/context.rb +0 -197
  95. data/lib/swarm_sdk/hooks/definition.rb +0 -80
  96. data/lib/swarm_sdk/hooks/error.rb +0 -29
  97. data/lib/swarm_sdk/hooks/executor.rb +0 -146
  98. data/lib/swarm_sdk/hooks/registry.rb +0 -147
  99. data/lib/swarm_sdk/hooks/result.rb +0 -150
  100. data/lib/swarm_sdk/hooks/shell_executor.rb +0 -256
  101. data/lib/swarm_sdk/hooks/tool_call.rb +0 -35
  102. data/lib/swarm_sdk/hooks/tool_result.rb +0 -62
  103. data/lib/swarm_sdk/log_collector.rb +0 -227
  104. data/lib/swarm_sdk/log_stream.rb +0 -127
  105. data/lib/swarm_sdk/markdown_parser.rb +0 -75
  106. data/lib/swarm_sdk/model_aliases.json +0 -8
  107. data/lib/swarm_sdk/models.json +0 -44002
  108. data/lib/swarm_sdk/models.rb +0 -161
  109. data/lib/swarm_sdk/node_context.rb +0 -245
  110. data/lib/swarm_sdk/observer/builder.rb +0 -81
  111. data/lib/swarm_sdk/observer/config.rb +0 -45
  112. data/lib/swarm_sdk/observer/manager.rb +0 -236
  113. data/lib/swarm_sdk/patterns/agent_observer.rb +0 -160
  114. data/lib/swarm_sdk/permissions/config.rb +0 -239
  115. data/lib/swarm_sdk/permissions/error_formatter.rb +0 -121
  116. data/lib/swarm_sdk/permissions/path_matcher.rb +0 -35
  117. data/lib/swarm_sdk/permissions/validator.rb +0 -173
  118. data/lib/swarm_sdk/permissions_builder.rb +0 -122
  119. data/lib/swarm_sdk/plugin.rb +0 -309
  120. data/lib/swarm_sdk/plugin_registry.rb +0 -101
  121. data/lib/swarm_sdk/proc_helpers.rb +0 -53
  122. data/lib/swarm_sdk/prompts/base_system_prompt.md.erb +0 -117
  123. data/lib/swarm_sdk/restore_result.rb +0 -65
  124. data/lib/swarm_sdk/result.rb +0 -212
  125. data/lib/swarm_sdk/snapshot.rb +0 -156
  126. data/lib/swarm_sdk/snapshot_from_events.rb +0 -397
  127. data/lib/swarm_sdk/state_restorer.rb +0 -476
  128. data/lib/swarm_sdk/state_snapshot.rb +0 -334
  129. data/lib/swarm_sdk/swarm/agent_initializer.rb +0 -648
  130. data/lib/swarm_sdk/swarm/all_agents_builder.rb +0 -195
  131. data/lib/swarm_sdk/swarm/builder.rb +0 -256
  132. data/lib/swarm_sdk/swarm/executor.rb +0 -290
  133. data/lib/swarm_sdk/swarm/hook_triggers.rb +0 -151
  134. data/lib/swarm_sdk/swarm/lazy_delegate_chat.rb +0 -372
  135. data/lib/swarm_sdk/swarm/logging_callbacks.rb +0 -360
  136. data/lib/swarm_sdk/swarm/mcp_configurator.rb +0 -270
  137. data/lib/swarm_sdk/swarm/swarm_registry_builder.rb +0 -67
  138. data/lib/swarm_sdk/swarm/tool_configurator.rb +0 -392
  139. data/lib/swarm_sdk/swarm.rb +0 -843
  140. data/lib/swarm_sdk/swarm_loader.rb +0 -145
  141. data/lib/swarm_sdk/swarm_registry.rb +0 -136
  142. data/lib/swarm_sdk/tools/base.rb +0 -63
  143. data/lib/swarm_sdk/tools/bash.rb +0 -280
  144. data/lib/swarm_sdk/tools/clock.rb +0 -46
  145. data/lib/swarm_sdk/tools/delegate.rb +0 -389
  146. data/lib/swarm_sdk/tools/document_converters/base_converter.rb +0 -83
  147. data/lib/swarm_sdk/tools/document_converters/docx_converter.rb +0 -99
  148. data/lib/swarm_sdk/tools/document_converters/html_converter.rb +0 -101
  149. data/lib/swarm_sdk/tools/document_converters/pdf_converter.rb +0 -78
  150. data/lib/swarm_sdk/tools/document_converters/xlsx_converter.rb +0 -194
  151. data/lib/swarm_sdk/tools/edit.rb +0 -145
  152. data/lib/swarm_sdk/tools/glob.rb +0 -166
  153. data/lib/swarm_sdk/tools/grep.rb +0 -235
  154. data/lib/swarm_sdk/tools/image_extractors/docx_image_extractor.rb +0 -43
  155. data/lib/swarm_sdk/tools/image_extractors/pdf_image_extractor.rb +0 -167
  156. data/lib/swarm_sdk/tools/image_formats/tiff_builder.rb +0 -65
  157. data/lib/swarm_sdk/tools/mcp_tool_stub.rb +0 -198
  158. data/lib/swarm_sdk/tools/multi_edit.rb +0 -236
  159. data/lib/swarm_sdk/tools/path_resolver.rb +0 -92
  160. data/lib/swarm_sdk/tools/read.rb +0 -261
  161. data/lib/swarm_sdk/tools/registry.rb +0 -205
  162. data/lib/swarm_sdk/tools/scratchpad/scratchpad_list.rb +0 -117
  163. data/lib/swarm_sdk/tools/scratchpad/scratchpad_read.rb +0 -97
  164. data/lib/swarm_sdk/tools/scratchpad/scratchpad_write.rb +0 -108
  165. data/lib/swarm_sdk/tools/stores/read_tracker.rb +0 -96
  166. data/lib/swarm_sdk/tools/stores/scratchpad_storage.rb +0 -273
  167. data/lib/swarm_sdk/tools/stores/storage.rb +0 -142
  168. data/lib/swarm_sdk/tools/stores/todo_manager.rb +0 -65
  169. data/lib/swarm_sdk/tools/think.rb +0 -100
  170. data/lib/swarm_sdk/tools/todo_write.rb +0 -237
  171. data/lib/swarm_sdk/tools/web_fetch.rb +0 -264
  172. data/lib/swarm_sdk/tools/write.rb +0 -112
  173. data/lib/swarm_sdk/transcript_builder.rb +0 -278
  174. data/lib/swarm_sdk/utils.rb +0 -68
  175. data/lib/swarm_sdk/validation_result.rb +0 -33
  176. data/lib/swarm_sdk/version.rb +0 -5
  177. data/lib/swarm_sdk/workflow/agent_config.rb +0 -95
  178. data/lib/swarm_sdk/workflow/builder.rb +0 -227
  179. data/lib/swarm_sdk/workflow/executor.rb +0 -497
  180. data/lib/swarm_sdk/workflow/node_builder.rb +0 -593
  181. data/lib/swarm_sdk/workflow/transformer_executor.rb +0 -250
  182. data/lib/swarm_sdk/workflow.rb +0 -589
  183. data/lib/swarm_sdk.rb +0 -718
@@ -1,392 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module SwarmSDK
4
- class Swarm
5
- # Handles tool creation, registration, and permissions wrapping
6
- #
7
- # Responsibilities:
8
- # - Register explicit tools for agents
9
- # - Register default tools (Read, Grep, Glob, etc.)
10
- # - Create tool instances (with agent context)
11
- # - Wrap tools with permissions validators
12
- #
13
- # This encapsulates all tool-related logic that was previously in Swarm.
14
- class ToolConfigurator
15
- # Default tools available to all agents (unless disable_default_tools is set)
16
- DEFAULT_TOOLS = [
17
- :Read,
18
- :Grep,
19
- :Glob,
20
- ].freeze
21
-
22
- # Scratchpad tools (added if scratchpad is enabled)
23
- SCRATCHPAD_TOOLS = [
24
- :ScratchpadWrite,
25
- :ScratchpadRead,
26
- :ScratchpadList,
27
- ].freeze
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
-
40
- def initialize(swarm, scratchpad_storage, plugin_storages = {})
41
- @swarm = swarm
42
- @scratchpad_storage = scratchpad_storage
43
- # Plugin storages: { plugin_name => { agent_name => storage } }
44
- # e.g., { memory: { agent1: storage1, agent2: storage2 } }
45
- @plugin_storages = plugin_storages
46
- end
47
-
48
- # Register all tools for an agent (both explicit and default)
49
- #
50
- # @param chat [AgentChat] The chat instance to register tools with
51
- # @param agent_name [Symbol] Name of the agent
52
- # @param agent_definition [AgentDefinition] Agent definition object
53
- def register_all_tools(chat:, agent_name:, agent_definition:)
54
- register_explicit_tools(chat, agent_definition.tools, agent_name: agent_name, agent_definition: agent_definition)
55
- register_default_tools(chat, agent_name: agent_name, agent_definition: agent_definition)
56
- end
57
-
58
- # Create a tool instance by name
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
- #
63
- # Tool lookup order:
64
- # 1. Plugin tools (registered via SwarmSDK::PluginRegistry)
65
- # 2. Custom tools (registered via SwarmSDK.register_tool)
66
- # 3. Built-in tools (SwarmSDK::Tools::Registry)
67
- #
68
- # File tools and TodoWrite require agent context for tracking state.
69
- # Scratchpad tools require shared scratchpad instance.
70
- # Plugin tools are delegated to their respective plugins.
71
- #
72
- # This method is public for testing delegation from Swarm.
73
- #
74
- # @param tool_name [Symbol, String] Tool name
75
- # @param agent_name [Symbol] Agent name for context
76
- # @param directory [String] Agent's working directory
77
- # @param chat [Agent::Chat, nil] Optional chat instance for tools that need it
78
- # @param agent_definition [Agent::Definition, nil] Optional agent definition
79
- # @return [RubyLLM::Tool] Tool instance
80
- def create_tool_instance(tool_name, agent_name, directory, chat: nil, agent_definition: nil)
81
- tool_name_sym = tool_name.to_sym
82
-
83
- # Check if tool is provided by a plugin
84
- if PluginRegistry.plugin_tool?(tool_name_sym)
85
- return create_plugin_tool(tool_name_sym, agent_name, directory, chat, agent_definition)
86
- end
87
-
88
- # Check if tool is a custom registered tool
89
- if CustomToolRegistry.registered?(tool_name_sym)
90
- context = {
91
- agent_name: agent_name,
92
- directory: directory,
93
- }
94
- return CustomToolRegistry.create(tool_name_sym, context)
95
- end
96
-
97
- # Use Registry factory pattern for built-in tools
98
- context = {
99
- agent_name: agent_name,
100
- directory: directory,
101
- scratchpad_storage: @scratchpad_storage,
102
- }
103
-
104
- Tools::Registry.create(tool_name_sym, context)
105
- end
106
-
107
- # Wrap a tool instance with permissions validator if configured
108
- #
109
- # This method is public for testing delegation from Swarm.
110
- #
111
- # @param tool_instance [RubyLLM::Tool] Tool instance to wrap
112
- # @param permissions_config [Hash, nil] Permission configuration
113
- # @param agent_definition [AgentDefinition] Agent definition
114
- # @return [RubyLLM::Tool] Either the wrapped tool or original tool
115
- def wrap_tool_with_permissions(tool_instance, permissions_config, agent_definition)
116
- # Skip wrapping if no permissions or agent bypasses permissions
117
- return tool_instance unless permissions_config
118
- return tool_instance if agent_definition.bypass_permissions
119
-
120
- # Create permissions config and wrap tool with validator
121
- permissions = Permissions::Config.new(
122
- permissions_config,
123
- base_directory: agent_definition.directory,
124
- )
125
-
126
- Permissions::Validator.new(tool_instance, permissions)
127
- end
128
-
129
- private
130
-
131
- # Register explicitly configured tools
132
- #
133
- # @param chat [AgentChat] The chat instance
134
- # @param tool_configs [Array<Hash>] Tool configurations with optional permissions
135
- # @param agent_name [Symbol] Agent name
136
- # @param agent_definition [AgentDefinition] Agent definition
137
- def register_explicit_tools(chat, tool_configs, agent_name:, agent_definition:)
138
- # Validate filesystem tools if globally disabled
139
- unless @swarm.allow_filesystem_tools
140
- # Extract tool names from hashes and convert to symbols for comparison
141
- forbidden = tool_configs.map { |tc| tc[:name].to_sym }.select { |name| FILESYSTEM_TOOLS.include?(name) }
142
- unless forbidden.empty?
143
- raise ConfigurationError,
144
- "Filesystem tools are globally disabled (SwarmSDK.config.allow_filesystem_tools = false) " \
145
- "but agent '#{agent_name}' attempts to use: #{forbidden.join(", ")}.\n\n" \
146
- "This is a system-wide security setting that cannot be overridden by swarm configuration.\n" \
147
- "To use filesystem tools, set SwarmSDK.config.allow_filesystem_tools = true before loading the swarm."
148
- end
149
- end
150
-
151
- tool_configs.each do |tool_config|
152
- tool_name = tool_config[:name]
153
- permissions_config = tool_config[:permissions]
154
-
155
- # Create tool instance
156
- tool_instance = create_tool_instance(tool_name, agent_name, agent_definition.directory)
157
-
158
- # Wrap with permissions and add to chat
159
- wrap_and_add_tool(chat, tool_instance, permissions_config, agent_definition)
160
- end
161
- end
162
-
163
- # Register default tools for agents (unless disabled)
164
- #
165
- # Note: Memory tools are registered separately and are NOT affected by
166
- # disable_default_tools, since they're configured via memory {} block.
167
- #
168
- # @param chat [AgentChat] The chat instance
169
- # @param agent_name [Symbol] Agent name
170
- # @param agent_definition [AgentDefinition] Agent definition
171
- def register_default_tools(chat, agent_name:, agent_definition:)
172
- # Get explicit tool names to avoid duplicates
173
- explicit_tool_names = agent_definition.tools.map { |t| t[:name] }.to_set
174
-
175
- # Register core default tools (unless disabled)
176
- if agent_definition.disable_default_tools != true
177
- DEFAULT_TOOLS.each do |tool_name|
178
- # Skip filesystem tools if globally disabled
179
- next if !@swarm.allow_filesystem_tools && FILESYSTEM_TOOLS.include?(tool_name)
180
-
181
- register_tool_if_not_disabled(chat, tool_name, explicit_tool_names, agent_name, agent_definition)
182
- end
183
-
184
- # Register scratchpad tools if enabled
185
- if @swarm.scratchpad_enabled?
186
- SCRATCHPAD_TOOLS.each do |tool_name|
187
- register_tool_if_not_disabled(chat, tool_name, explicit_tool_names, agent_name, agent_definition)
188
- end
189
- end
190
- end
191
-
192
- # Register plugin tools if plugin storage is enabled for this agent
193
- # Plugin tools ARE affected by disable_default_tools (allows fine-grained control)
194
- register_plugin_tools(chat, agent_name, agent_definition, explicit_tool_names)
195
- end
196
-
197
- # Register a tool if not already explicit or disabled
198
- def register_tool_if_not_disabled(chat, tool_name, explicit_tool_names, agent_name, agent_definition)
199
- # Skip if already registered explicitly
200
- return if explicit_tool_names.include?(tool_name)
201
-
202
- # Skip if tool is in the disable list
203
- return if tool_disabled?(tool_name, agent_definition.disable_default_tools)
204
-
205
- tool_instance = create_tool_instance(tool_name, agent_name, agent_definition.directory)
206
- permissions_config = resolve_default_permissions(tool_name, agent_definition)
207
-
208
- wrap_and_add_tool(chat, tool_instance, permissions_config, agent_definition)
209
- end
210
-
211
- # Wrap tool with permissions and add to chat
212
- #
213
- # This is the common pattern for registering tools:
214
- # 1. Wrap with permissions validator (if configured)
215
- # 2. Add to chat
216
- #
217
- # @param chat [Agent::Chat] The chat instance
218
- # @param tool_instance [RubyLLM::Tool] Tool instance
219
- # @param permissions_config [Hash, nil] Permissions configuration
220
- # @param agent_definition [Agent::Definition] Agent definition
221
- # @return [void]
222
- def wrap_and_add_tool(chat, tool_instance, permissions_config, agent_definition, source: :builtin, metadata: {})
223
- base_tool = tool_instance # Keep reference to unwrapped tool
224
- wrapped_tool = wrap_tool_with_permissions(tool_instance, permissions_config, agent_definition)
225
-
226
- # Register in tool registry (Plan 025)
227
- chat.tool_registry.register(
228
- wrapped_tool,
229
- base_tool: base_tool,
230
- source: source,
231
- metadata: metadata.merge(permissions: permissions_config),
232
- )
233
- end
234
-
235
- # Resolve permissions for a default/plugin tool
236
- #
237
- # Looks up permissions in agent-specific config first, falls back to global defaults.
238
- #
239
- # @param tool_name [Symbol] Tool name
240
- # @param agent_definition [Agent::Definition] Agent definition
241
- # @return [Hash, nil] Permissions configuration or nil
242
- def resolve_default_permissions(tool_name, agent_definition)
243
- agent_definition.agent_permissions[tool_name] || agent_definition.default_permissions[tool_name]
244
- end
245
-
246
- # Create a tool instance via plugin
247
- #
248
- # @param tool_name [Symbol] Tool name
249
- # @param agent_name [Symbol] Agent name
250
- # @param directory [String] Working directory
251
- # @param chat [Agent::Chat, nil] Chat instance
252
- # @param agent_definition [Agent::Definition, nil] Agent definition
253
- # @return [RubyLLM::Tool] Tool instance
254
- def create_plugin_tool(tool_name, agent_name, directory, chat, agent_definition)
255
- plugin = PluginRegistry.plugin_for_tool(tool_name)
256
- raise ConfigurationError, "Tool #{tool_name} is not provided by any plugin" unless plugin
257
-
258
- # V7.0: Extract base name for storage lookup (handles delegation instances)
259
- # For primary agents: :tester → :tester (no change)
260
- # For delegation instances: "tester@frontend" → :tester (extracts base)
261
- base_name = agent_name.to_s.split("@").first.to_sym
262
-
263
- # Get plugin storage using BASE NAME (shared across instances)
264
- plugin_storages = @plugin_storages[plugin.name] || {}
265
- storage = plugin_storages[base_name] # ← Changed from agent_name to base_name
266
-
267
- # Build context for tool creation
268
- # Pass full agent_name for tool state tracking (TodoWrite, ReadTracker, etc.)
269
- context = {
270
- agent_name: agent_name, # Full instance name for tool's use
271
- directory: directory,
272
- storage: storage, # Shared storage by base name
273
- agent_definition: agent_definition,
274
- chat: chat,
275
- tool_configurator: self,
276
- }
277
-
278
- plugin.create_tool(tool_name, context)
279
- end
280
-
281
- # Register plugin-provided tools for an agent
282
- #
283
- # Asks all plugins if they have tools to register for this agent.
284
- #
285
- # @param chat [Agent::Chat] Chat instance
286
- # @param agent_name [Symbol] Agent name
287
- # @param agent_definition [Agent::Definition] Agent definition
288
- # @param explicit_tool_names [Set<Symbol>] Already-registered tool names
289
- def register_plugin_tools(chat, agent_name, agent_definition, explicit_tool_names)
290
- PluginRegistry.all.each do |plugin|
291
- # Check if plugin has storage enabled for this agent
292
- next unless plugin.memory_configured?(agent_definition)
293
-
294
- # Register each tool provided by the plugin
295
- plugin.tools.each do |tool_name|
296
- # Skip if already registered explicitly
297
- next if explicit_tool_names.include?(tool_name)
298
-
299
- # Skip if tool is disabled via disable_default_tools
300
- next if tool_disabled?(tool_name, agent_definition.disable_default_tools)
301
-
302
- tool_instance = create_tool_instance(
303
- tool_name,
304
- agent_name,
305
- agent_definition.directory,
306
- chat: chat,
307
- agent_definition: agent_definition,
308
- )
309
-
310
- permissions_config = resolve_default_permissions(tool_name, agent_definition)
311
-
312
- wrap_and_add_tool(
313
- chat,
314
- tool_instance,
315
- permissions_config,
316
- agent_definition,
317
- source: :plugin,
318
- metadata: { plugin_name: plugin.class.name },
319
- )
320
- end
321
- end
322
- end
323
-
324
- # Check if a tool should be disabled based on disable_default_tools config
325
- #
326
- # @param tool_name [Symbol] Tool name to check
327
- # @param disable_config [nil, Boolean, Symbol, Array<Symbol>] Disable configuration
328
- # @return [Boolean] True if tool should be disabled
329
- def tool_disabled?(tool_name, disable_config)
330
- return false if disable_config.nil?
331
-
332
- # Normalize tool_name to symbol for comparison
333
- tool_name_sym = tool_name.to_sym
334
-
335
- if disable_config == true
336
- # Disable all default tools
337
- true
338
- elsif disable_config.is_a?(Symbol)
339
- # Single tool name
340
- disable_config == tool_name_sym
341
- elsif disable_config.is_a?(String)
342
- # Single tool name as string (from YAML)
343
- disable_config.to_sym == tool_name_sym
344
- elsif disable_config.is_a?(Array)
345
- # Disable only tools in the array - normalize to symbols for comparison
346
- disable_config.map(&:to_sym).include?(tool_name_sym)
347
- else
348
- false
349
- end
350
- end
351
-
352
- # Register agent delegation tools
353
- #
354
- # Creates delegation tools that allow one agent to call another.
355
- #
356
- # @param chat [AgentChat] The chat instance
357
- # @param delegate_names [Array<Symbol>] Names of agents to delegate to
358
- # @param agent_name [Symbol] Name of the agent doing the delegating
359
- def register_delegation_tools(chat, delegate_names, agent_name:)
360
- return if delegate_names.empty?
361
-
362
- delegate_names.each do |delegate_name|
363
- delegate_name = delegate_name.to_sym
364
-
365
- unless @agents.key?(delegate_name)
366
- raise ConfigurationError, "Agent delegates to unknown agent '#{delegate_name}'"
367
- end
368
-
369
- # Create a tool that delegates to the specified agent
370
- delegate_agent = @agents[delegate_name]
371
- delegate_definition = @agent_definitions[delegate_name]
372
-
373
- tool = Tools::Delegate.new(
374
- delegate_name: delegate_name.to_s,
375
- delegate_description: delegate_definition.description,
376
- delegate_chat: delegate_agent,
377
- agent_name: agent_name,
378
- swarm: @swarm,
379
- delegating_chat: chat,
380
- )
381
-
382
- # Register in tool registry (Plan 025)
383
- chat.tool_registry.register(
384
- tool,
385
- source: :delegation,
386
- metadata: { delegate_name: delegate_name },
387
- )
388
- end
389
- end
390
- end
391
- end
392
- end