swarm_memory 2.1.5 → 2.1.6

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 (182) hide show
  1. checksums.yaml +4 -4
  2. data/lib/swarm_memory/version.rb +1 -1
  3. metadata +5 -184
  4. data/lib/claude_swarm/base_executor.rb +0 -133
  5. data/lib/claude_swarm/claude_code_executor.rb +0 -349
  6. data/lib/claude_swarm/claude_mcp_server.rb +0 -78
  7. data/lib/claude_swarm/cli.rb +0 -697
  8. data/lib/claude_swarm/commands/ps.rb +0 -215
  9. data/lib/claude_swarm/commands/show.rb +0 -139
  10. data/lib/claude_swarm/configuration.rb +0 -373
  11. data/lib/claude_swarm/hooks/session_start_hook.rb +0 -42
  12. data/lib/claude_swarm/json_handler.rb +0 -91
  13. data/lib/claude_swarm/mcp_generator.rb +0 -230
  14. data/lib/claude_swarm/openai/chat_completion.rb +0 -256
  15. data/lib/claude_swarm/openai/executor.rb +0 -256
  16. data/lib/claude_swarm/openai/responses.rb +0 -319
  17. data/lib/claude_swarm/orchestrator.rb +0 -878
  18. data/lib/claude_swarm/process_tracker.rb +0 -78
  19. data/lib/claude_swarm/session_cost_calculator.rb +0 -209
  20. data/lib/claude_swarm/session_path.rb +0 -42
  21. data/lib/claude_swarm/settings_generator.rb +0 -77
  22. data/lib/claude_swarm/system_utils.rb +0 -46
  23. data/lib/claude_swarm/templates/generation_prompt.md.erb +0 -230
  24. data/lib/claude_swarm/tools/reset_session_tool.rb +0 -24
  25. data/lib/claude_swarm/tools/session_info_tool.rb +0 -24
  26. data/lib/claude_swarm/tools/task_tool.rb +0 -63
  27. data/lib/claude_swarm/version.rb +0 -5
  28. data/lib/claude_swarm/worktree_manager.rb +0 -475
  29. data/lib/claude_swarm/yaml_loader.rb +0 -22
  30. data/lib/claude_swarm.rb +0 -67
  31. data/lib/swarm_cli/cli.rb +0 -201
  32. data/lib/swarm_cli/command_registry.rb +0 -61
  33. data/lib/swarm_cli/commands/mcp_serve.rb +0 -130
  34. data/lib/swarm_cli/commands/mcp_tools.rb +0 -148
  35. data/lib/swarm_cli/commands/migrate.rb +0 -55
  36. data/lib/swarm_cli/commands/run.rb +0 -173
  37. data/lib/swarm_cli/config_loader.rb +0 -98
  38. data/lib/swarm_cli/formatters/human_formatter.rb +0 -781
  39. data/lib/swarm_cli/formatters/json_formatter.rb +0 -51
  40. data/lib/swarm_cli/interactive_repl.rb +0 -924
  41. data/lib/swarm_cli/mcp_serve_options.rb +0 -44
  42. data/lib/swarm_cli/mcp_tools_options.rb +0 -59
  43. data/lib/swarm_cli/migrate_options.rb +0 -54
  44. data/lib/swarm_cli/migrator.rb +0 -132
  45. data/lib/swarm_cli/options.rb +0 -151
  46. data/lib/swarm_cli/ui/components/agent_badge.rb +0 -33
  47. data/lib/swarm_cli/ui/components/content_block.rb +0 -120
  48. data/lib/swarm_cli/ui/components/divider.rb +0 -57
  49. data/lib/swarm_cli/ui/components/panel.rb +0 -62
  50. data/lib/swarm_cli/ui/components/usage_stats.rb +0 -70
  51. data/lib/swarm_cli/ui/formatters/cost.rb +0 -49
  52. data/lib/swarm_cli/ui/formatters/number.rb +0 -58
  53. data/lib/swarm_cli/ui/formatters/text.rb +0 -77
  54. data/lib/swarm_cli/ui/formatters/time.rb +0 -73
  55. data/lib/swarm_cli/ui/icons.rb +0 -36
  56. data/lib/swarm_cli/ui/renderers/event_renderer.rb +0 -188
  57. data/lib/swarm_cli/ui/state/agent_color_cache.rb +0 -45
  58. data/lib/swarm_cli/ui/state/depth_tracker.rb +0 -40
  59. data/lib/swarm_cli/ui/state/spinner_manager.rb +0 -170
  60. data/lib/swarm_cli/ui/state/usage_tracker.rb +0 -62
  61. data/lib/swarm_cli/version.rb +0 -5
  62. data/lib/swarm_cli.rb +0 -46
  63. data/lib/swarm_sdk/agent/RETRY_LOGIC.md +0 -127
  64. data/lib/swarm_sdk/agent/builder.rb +0 -552
  65. data/lib/swarm_sdk/agent/chat.rb +0 -774
  66. data/lib/swarm_sdk/agent/chat_helpers/context_tracker.rb +0 -268
  67. data/lib/swarm_sdk/agent/chat_helpers/event_emitter.rb +0 -204
  68. data/lib/swarm_sdk/agent/chat_helpers/hook_integration.rb +0 -480
  69. data/lib/swarm_sdk/agent/chat_helpers/instrumentation.rb +0 -78
  70. data/lib/swarm_sdk/agent/chat_helpers/llm_configuration.rb +0 -233
  71. data/lib/swarm_sdk/agent/chat_helpers/logging_helpers.rb +0 -116
  72. data/lib/swarm_sdk/agent/chat_helpers/serialization.rb +0 -83
  73. data/lib/swarm_sdk/agent/chat_helpers/system_reminder_injector.rb +0 -136
  74. data/lib/swarm_sdk/agent/chat_helpers/system_reminders.rb +0 -79
  75. data/lib/swarm_sdk/agent/chat_helpers/token_tracking.rb +0 -98
  76. data/lib/swarm_sdk/agent/context.rb +0 -116
  77. data/lib/swarm_sdk/agent/context_manager.rb +0 -315
  78. data/lib/swarm_sdk/agent/definition.rb +0 -477
  79. data/lib/swarm_sdk/agent/llm_instrumentation_middleware.rb +0 -182
  80. data/lib/swarm_sdk/agent/system_prompt_builder.rb +0 -161
  81. data/lib/swarm_sdk/builders/base_builder.rb +0 -409
  82. data/lib/swarm_sdk/claude_code_agent_adapter.rb +0 -205
  83. data/lib/swarm_sdk/concerns/cleanupable.rb +0 -39
  84. data/lib/swarm_sdk/concerns/snapshotable.rb +0 -67
  85. data/lib/swarm_sdk/concerns/validatable.rb +0 -55
  86. data/lib/swarm_sdk/configuration/parser.rb +0 -353
  87. data/lib/swarm_sdk/configuration/translator.rb +0 -255
  88. data/lib/swarm_sdk/configuration.rb +0 -135
  89. data/lib/swarm_sdk/context_compactor/metrics.rb +0 -147
  90. data/lib/swarm_sdk/context_compactor/token_counter.rb +0 -106
  91. data/lib/swarm_sdk/context_compactor.rb +0 -335
  92. data/lib/swarm_sdk/context_management/builder.rb +0 -128
  93. data/lib/swarm_sdk/context_management/context.rb +0 -328
  94. data/lib/swarm_sdk/defaults.rb +0 -196
  95. data/lib/swarm_sdk/events_to_messages.rb +0 -199
  96. data/lib/swarm_sdk/hooks/adapter.rb +0 -359
  97. data/lib/swarm_sdk/hooks/context.rb +0 -197
  98. data/lib/swarm_sdk/hooks/definition.rb +0 -80
  99. data/lib/swarm_sdk/hooks/error.rb +0 -29
  100. data/lib/swarm_sdk/hooks/executor.rb +0 -146
  101. data/lib/swarm_sdk/hooks/registry.rb +0 -147
  102. data/lib/swarm_sdk/hooks/result.rb +0 -150
  103. data/lib/swarm_sdk/hooks/shell_executor.rb +0 -255
  104. data/lib/swarm_sdk/hooks/tool_call.rb +0 -35
  105. data/lib/swarm_sdk/hooks/tool_result.rb +0 -62
  106. data/lib/swarm_sdk/log_collector.rb +0 -227
  107. data/lib/swarm_sdk/log_stream.rb +0 -127
  108. data/lib/swarm_sdk/markdown_parser.rb +0 -75
  109. data/lib/swarm_sdk/model_aliases.json +0 -8
  110. data/lib/swarm_sdk/models.json +0 -1
  111. data/lib/swarm_sdk/models.rb +0 -120
  112. data/lib/swarm_sdk/node_context.rb +0 -245
  113. data/lib/swarm_sdk/observer/builder.rb +0 -81
  114. data/lib/swarm_sdk/observer/config.rb +0 -45
  115. data/lib/swarm_sdk/observer/manager.rb +0 -236
  116. data/lib/swarm_sdk/patterns/agent_observer.rb +0 -160
  117. data/lib/swarm_sdk/permissions/config.rb +0 -239
  118. data/lib/swarm_sdk/permissions/error_formatter.rb +0 -121
  119. data/lib/swarm_sdk/permissions/path_matcher.rb +0 -35
  120. data/lib/swarm_sdk/permissions/validator.rb +0 -173
  121. data/lib/swarm_sdk/permissions_builder.rb +0 -122
  122. data/lib/swarm_sdk/plugin.rb +0 -309
  123. data/lib/swarm_sdk/plugin_registry.rb +0 -101
  124. data/lib/swarm_sdk/proc_helpers.rb +0 -53
  125. data/lib/swarm_sdk/prompts/base_system_prompt.md.erb +0 -117
  126. data/lib/swarm_sdk/restore_result.rb +0 -65
  127. data/lib/swarm_sdk/result.rb +0 -123
  128. data/lib/swarm_sdk/snapshot.rb +0 -156
  129. data/lib/swarm_sdk/snapshot_from_events.rb +0 -397
  130. data/lib/swarm_sdk/state_restorer.rb +0 -476
  131. data/lib/swarm_sdk/state_snapshot.rb +0 -334
  132. data/lib/swarm_sdk/swarm/agent_initializer.rb +0 -683
  133. data/lib/swarm_sdk/swarm/all_agents_builder.rb +0 -167
  134. data/lib/swarm_sdk/swarm/builder.rb +0 -249
  135. data/lib/swarm_sdk/swarm/executor.rb +0 -213
  136. data/lib/swarm_sdk/swarm/hook_triggers.rb +0 -150
  137. data/lib/swarm_sdk/swarm/logging_callbacks.rb +0 -340
  138. data/lib/swarm_sdk/swarm/mcp_configurator.rb +0 -154
  139. data/lib/swarm_sdk/swarm/swarm_registry_builder.rb +0 -67
  140. data/lib/swarm_sdk/swarm/tool_configurator.rb +0 -358
  141. data/lib/swarm_sdk/swarm.rb +0 -717
  142. data/lib/swarm_sdk/swarm_loader.rb +0 -145
  143. data/lib/swarm_sdk/swarm_registry.rb +0 -136
  144. data/lib/swarm_sdk/tools/bash.rb +0 -282
  145. data/lib/swarm_sdk/tools/clock.rb +0 -44
  146. data/lib/swarm_sdk/tools/delegate.rb +0 -267
  147. data/lib/swarm_sdk/tools/document_converters/base_converter.rb +0 -83
  148. data/lib/swarm_sdk/tools/document_converters/docx_converter.rb +0 -99
  149. data/lib/swarm_sdk/tools/document_converters/html_converter.rb +0 -101
  150. data/lib/swarm_sdk/tools/document_converters/pdf_converter.rb +0 -78
  151. data/lib/swarm_sdk/tools/document_converters/xlsx_converter.rb +0 -194
  152. data/lib/swarm_sdk/tools/edit.rb +0 -145
  153. data/lib/swarm_sdk/tools/glob.rb +0 -166
  154. data/lib/swarm_sdk/tools/grep.rb +0 -235
  155. data/lib/swarm_sdk/tools/image_extractors/docx_image_extractor.rb +0 -43
  156. data/lib/swarm_sdk/tools/image_extractors/pdf_image_extractor.rb +0 -163
  157. data/lib/swarm_sdk/tools/image_formats/tiff_builder.rb +0 -65
  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 -272
  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 -98
  170. data/lib/swarm_sdk/tools/todo_write.rb +0 -235
  171. data/lib/swarm_sdk/tools/web_fetch.rb +0 -262
  172. data/lib/swarm_sdk/tools/write.rb +0 -112
  173. data/lib/swarm_sdk/utils.rb +0 -68
  174. data/lib/swarm_sdk/validation_result.rb +0 -33
  175. data/lib/swarm_sdk/version.rb +0 -5
  176. data/lib/swarm_sdk/workflow/agent_config.rb +0 -79
  177. data/lib/swarm_sdk/workflow/builder.rb +0 -143
  178. data/lib/swarm_sdk/workflow/executor.rb +0 -497
  179. data/lib/swarm_sdk/workflow/node_builder.rb +0 -555
  180. data/lib/swarm_sdk/workflow/transformer_executor.rb +0 -249
  181. data/lib/swarm_sdk/workflow.rb +0 -554
  182. data/lib/swarm_sdk.rb +0 -524
@@ -1,67 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module SwarmSDK
4
- class Swarm
5
- # Builder for swarm registry in DSL
6
- #
7
- # Supports registering external swarms for composable swarms pattern.
8
- #
9
- # @example
10
- # swarms do
11
- # register "code_review", file: "./swarms/code_review.rb"
12
- # register "testing", file: "./swarms/testing.yml", keep_context: false
13
- # end
14
- #
15
- # @example Inline swarm definition
16
- # swarms do
17
- # register "tester" do
18
- # lead :tester
19
- # agent :tester do
20
- # model "gpt-4o-mini"
21
- # system "You test code"
22
- # end
23
- # end
24
- # end
25
- #
26
- class SwarmRegistryBuilder
27
- attr_reader :registrations
28
-
29
- def initialize
30
- @registrations = []
31
- end
32
-
33
- # Register a swarm from file, YAML string, or inline block
34
- #
35
- # @param name [String, Symbol] Registration name
36
- # @param file [String, nil] Path to swarm file (.rb or .yml)
37
- # @param yaml [String, nil] YAML content string
38
- # @param keep_context [Boolean] Whether to preserve conversation state (default: true)
39
- # @yield Optional block for inline swarm definition
40
- # @raise [ArgumentError] If neither file, yaml, nor block provided
41
- def register(name, file: nil, yaml: nil, keep_context: true, &block)
42
- # Validate that exactly one source is provided
43
- sources = [file, yaml, block].compact
44
- if sources.empty?
45
- raise ArgumentError, "register '#{name}' requires either file:, yaml:, or a block"
46
- elsif sources.size > 1
47
- raise ArgumentError, "register '#{name}' accepts only one of: file:, yaml:, or block (got #{sources.size})"
48
- end
49
-
50
- # Determine source type and store
51
- source = if file
52
- { type: :file, value: file }
53
- elsif yaml
54
- { type: :yaml, value: yaml }
55
- else
56
- { type: :block, value: block }
57
- end
58
-
59
- @registrations << {
60
- name: name.to_s,
61
- source: source,
62
- keep_context: keep_context,
63
- }
64
- end
65
- end
66
- end
67
- end
@@ -1,358 +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
- # File tools and TodoWrite require agent context for tracking state.
64
- # Scratchpad tools require shared scratchpad instance.
65
- # Plugin tools are delegated to their respective plugins.
66
- #
67
- # This method is public for testing delegation from Swarm.
68
- #
69
- # @param tool_name [Symbol, String] Tool name
70
- # @param agent_name [Symbol] Agent name for context
71
- # @param directory [String] Agent's working directory
72
- # @param chat [Agent::Chat, nil] Optional chat instance for tools that need it
73
- # @param agent_definition [Agent::Definition, nil] Optional agent definition
74
- # @return [RubyLLM::Tool] Tool instance
75
- def create_tool_instance(tool_name, agent_name, directory, chat: nil, agent_definition: nil)
76
- tool_name_sym = tool_name.to_sym
77
-
78
- # Check if tool is provided by a plugin
79
- if PluginRegistry.plugin_tool?(tool_name_sym)
80
- return create_plugin_tool(tool_name_sym, agent_name, directory, chat, agent_definition)
81
- end
82
-
83
- # Use Registry factory pattern - tools declare their own requirements
84
- context = {
85
- agent_name: agent_name,
86
- directory: directory,
87
- scratchpad_storage: @scratchpad_storage,
88
- }
89
-
90
- Tools::Registry.create(tool_name_sym, context)
91
- end
92
-
93
- # Wrap a tool instance with permissions validator if configured
94
- #
95
- # This method is public for testing delegation from Swarm.
96
- #
97
- # @param tool_instance [RubyLLM::Tool] Tool instance to wrap
98
- # @param permissions_config [Hash, nil] Permission configuration
99
- # @param agent_definition [AgentDefinition] Agent definition
100
- # @return [RubyLLM::Tool] Either the wrapped tool or original tool
101
- def wrap_tool_with_permissions(tool_instance, permissions_config, agent_definition)
102
- # Skip wrapping if no permissions or agent bypasses permissions
103
- return tool_instance unless permissions_config
104
- return tool_instance if agent_definition.bypass_permissions
105
-
106
- # Create permissions config and wrap tool with validator
107
- permissions = Permissions::Config.new(
108
- permissions_config,
109
- base_directory: agent_definition.directory,
110
- )
111
-
112
- Permissions::Validator.new(tool_instance, permissions)
113
- end
114
-
115
- private
116
-
117
- # Register explicitly configured tools
118
- #
119
- # @param chat [AgentChat] The chat instance
120
- # @param tool_configs [Array<Hash>] Tool configurations with optional permissions
121
- # @param agent_name [Symbol] Agent name
122
- # @param agent_definition [AgentDefinition] Agent definition
123
- def register_explicit_tools(chat, tool_configs, agent_name:, agent_definition:)
124
- # Validate filesystem tools if globally disabled
125
- unless @swarm.allow_filesystem_tools
126
- # Extract tool names from hashes and convert to symbols for comparison
127
- forbidden = tool_configs.map { |tc| tc[:name].to_sym }.select { |name| FILESYSTEM_TOOLS.include?(name) }
128
- unless forbidden.empty?
129
- raise ConfigurationError,
130
- "Filesystem tools are globally disabled (SwarmSDK.settings.allow_filesystem_tools = false) " \
131
- "but agent '#{agent_name}' attempts to use: #{forbidden.join(", ")}.\n\n" \
132
- "This is a system-wide security setting that cannot be overridden by swarm configuration.\n" \
133
- "To use filesystem tools, set SwarmSDK.settings.allow_filesystem_tools = true before loading the swarm."
134
- end
135
- end
136
-
137
- tool_configs.each do |tool_config|
138
- tool_name = tool_config[:name]
139
- permissions_config = tool_config[:permissions]
140
-
141
- # Create tool instance
142
- tool_instance = create_tool_instance(tool_name, agent_name, agent_definition.directory)
143
-
144
- # Wrap with permissions and add to chat
145
- wrap_and_add_tool(chat, tool_instance, permissions_config, agent_definition)
146
- end
147
- end
148
-
149
- # Register default tools for agents (unless disabled)
150
- #
151
- # Note: Memory tools are registered separately and are NOT affected by
152
- # disable_default_tools, since they're configured via memory {} block.
153
- #
154
- # @param chat [AgentChat] The chat instance
155
- # @param agent_name [Symbol] Agent name
156
- # @param agent_definition [AgentDefinition] Agent definition
157
- def register_default_tools(chat, agent_name:, agent_definition:)
158
- # Get explicit tool names to avoid duplicates
159
- explicit_tool_names = agent_definition.tools.map { |t| t[:name] }.to_set
160
-
161
- # Register core default tools (unless disabled)
162
- if agent_definition.disable_default_tools != true
163
- DEFAULT_TOOLS.each do |tool_name|
164
- # Skip filesystem tools if globally disabled
165
- next if !@swarm.allow_filesystem_tools && FILESYSTEM_TOOLS.include?(tool_name)
166
-
167
- register_tool_if_not_disabled(chat, tool_name, explicit_tool_names, agent_name, agent_definition)
168
- end
169
-
170
- # Register scratchpad tools if enabled
171
- if @swarm.scratchpad_enabled?
172
- SCRATCHPAD_TOOLS.each do |tool_name|
173
- register_tool_if_not_disabled(chat, tool_name, explicit_tool_names, agent_name, agent_definition)
174
- end
175
- end
176
- end
177
-
178
- # Register plugin tools if plugin storage is enabled for this agent
179
- # Plugin tools ARE affected by disable_default_tools (allows fine-grained control)
180
- register_plugin_tools(chat, agent_name, agent_definition, explicit_tool_names)
181
- end
182
-
183
- # Register a tool if not already explicit or disabled
184
- def register_tool_if_not_disabled(chat, tool_name, explicit_tool_names, agent_name, agent_definition)
185
- # Skip if already registered explicitly
186
- return if explicit_tool_names.include?(tool_name)
187
-
188
- # Skip if tool is in the disable list
189
- return if tool_disabled?(tool_name, agent_definition.disable_default_tools)
190
-
191
- tool_instance = create_tool_instance(tool_name, agent_name, agent_definition.directory)
192
- permissions_config = resolve_default_permissions(tool_name, agent_definition)
193
-
194
- wrap_and_add_tool(chat, tool_instance, permissions_config, agent_definition)
195
- end
196
-
197
- # Wrap tool with permissions and add to chat
198
- #
199
- # This is the common pattern for registering tools:
200
- # 1. Wrap with permissions validator (if configured)
201
- # 2. Add to chat
202
- #
203
- # @param chat [Agent::Chat] The chat instance
204
- # @param tool_instance [RubyLLM::Tool] Tool instance
205
- # @param permissions_config [Hash, nil] Permissions configuration
206
- # @param agent_definition [Agent::Definition] Agent definition
207
- # @return [void]
208
- def wrap_and_add_tool(chat, tool_instance, permissions_config, agent_definition)
209
- tool_instance = wrap_tool_with_permissions(tool_instance, permissions_config, agent_definition)
210
- chat.add_tool(tool_instance)
211
- end
212
-
213
- # Resolve permissions for a default/plugin tool
214
- #
215
- # Looks up permissions in agent-specific config first, falls back to global defaults.
216
- #
217
- # @param tool_name [Symbol] Tool name
218
- # @param agent_definition [Agent::Definition] Agent definition
219
- # @return [Hash, nil] Permissions configuration or nil
220
- def resolve_default_permissions(tool_name, agent_definition)
221
- agent_definition.agent_permissions[tool_name] || agent_definition.default_permissions[tool_name]
222
- end
223
-
224
- # Create a tool instance via plugin
225
- #
226
- # @param tool_name [Symbol] Tool name
227
- # @param agent_name [Symbol] Agent name
228
- # @param directory [String] Working directory
229
- # @param chat [Agent::Chat, nil] Chat instance
230
- # @param agent_definition [Agent::Definition, nil] Agent definition
231
- # @return [RubyLLM::Tool] Tool instance
232
- def create_plugin_tool(tool_name, agent_name, directory, chat, agent_definition)
233
- plugin = PluginRegistry.plugin_for_tool(tool_name)
234
- raise ConfigurationError, "Tool #{tool_name} is not provided by any plugin" unless plugin
235
-
236
- # V7.0: Extract base name for storage lookup (handles delegation instances)
237
- # For primary agents: :tester → :tester (no change)
238
- # For delegation instances: "tester@frontend" → :tester (extracts base)
239
- base_name = agent_name.to_s.split("@").first.to_sym
240
-
241
- # Get plugin storage using BASE NAME (shared across instances)
242
- plugin_storages = @plugin_storages[plugin.name] || {}
243
- storage = plugin_storages[base_name] # ← Changed from agent_name to base_name
244
-
245
- # Build context for tool creation
246
- # Pass full agent_name for tool state tracking (TodoWrite, ReadTracker, etc.)
247
- context = {
248
- agent_name: agent_name, # Full instance name for tool's use
249
- directory: directory,
250
- storage: storage, # Shared storage by base name
251
- agent_definition: agent_definition,
252
- chat: chat,
253
- tool_configurator: self,
254
- }
255
-
256
- plugin.create_tool(tool_name, context)
257
- end
258
-
259
- # Register plugin-provided tools for an agent
260
- #
261
- # Asks all plugins if they have tools to register for this agent.
262
- #
263
- # @param chat [Agent::Chat] Chat instance
264
- # @param agent_name [Symbol] Agent name
265
- # @param agent_definition [Agent::Definition] Agent definition
266
- # @param explicit_tool_names [Set<Symbol>] Already-registered tool names
267
- def register_plugin_tools(chat, agent_name, agent_definition, explicit_tool_names)
268
- PluginRegistry.all.each do |plugin|
269
- # Check if plugin has storage enabled for this agent
270
- next unless plugin.storage_enabled?(agent_definition)
271
-
272
- # Register each tool provided by the plugin
273
- plugin.tools.each do |tool_name|
274
- # Skip if already registered explicitly
275
- next if explicit_tool_names.include?(tool_name)
276
-
277
- # Skip if tool is disabled via disable_default_tools
278
- next if tool_disabled?(tool_name, agent_definition.disable_default_tools)
279
-
280
- tool_instance = create_tool_instance(
281
- tool_name,
282
- agent_name,
283
- agent_definition.directory,
284
- chat: chat,
285
- agent_definition: agent_definition,
286
- )
287
-
288
- permissions_config = resolve_default_permissions(tool_name, agent_definition)
289
-
290
- wrap_and_add_tool(chat, tool_instance, permissions_config, agent_definition)
291
- end
292
- end
293
- end
294
-
295
- # Check if a tool should be disabled based on disable_default_tools config
296
- #
297
- # @param tool_name [Symbol] Tool name to check
298
- # @param disable_config [nil, Boolean, Symbol, Array<Symbol>] Disable configuration
299
- # @return [Boolean] True if tool should be disabled
300
- def tool_disabled?(tool_name, disable_config)
301
- return false if disable_config.nil?
302
-
303
- # Normalize tool_name to symbol for comparison
304
- tool_name_sym = tool_name.to_sym
305
-
306
- if disable_config == true
307
- # Disable all default tools
308
- true
309
- elsif disable_config.is_a?(Symbol)
310
- # Single tool name
311
- disable_config == tool_name_sym
312
- elsif disable_config.is_a?(String)
313
- # Single tool name as string (from YAML)
314
- disable_config.to_sym == tool_name_sym
315
- elsif disable_config.is_a?(Array)
316
- # Disable only tools in the array - normalize to symbols for comparison
317
- disable_config.map(&:to_sym).include?(tool_name_sym)
318
- else
319
- false
320
- end
321
- end
322
-
323
- # Register agent delegation tools
324
- #
325
- # Creates delegation tools that allow one agent to call another.
326
- #
327
- # @param chat [AgentChat] The chat instance
328
- # @param delegate_names [Array<Symbol>] Names of agents to delegate to
329
- # @param agent_name [Symbol] Name of the agent doing the delegating
330
- def register_delegation_tools(chat, delegate_names, agent_name:)
331
- return if delegate_names.empty?
332
-
333
- delegate_names.each do |delegate_name|
334
- delegate_name = delegate_name.to_sym
335
-
336
- unless @agents.key?(delegate_name)
337
- raise ConfigurationError, "Agent delegates to unknown agent '#{delegate_name}'"
338
- end
339
-
340
- # Create a tool that delegates to the specified agent
341
- delegate_agent = @agents[delegate_name]
342
- delegate_definition = @agent_definitions[delegate_name]
343
-
344
- tool = Tools::Delegate.new(
345
- delegate_name: delegate_name.to_s,
346
- delegate_description: delegate_definition.description,
347
- delegate_chat: delegate_agent,
348
- agent_name: agent_name,
349
- swarm: @swarm,
350
- delegating_chat: chat,
351
- )
352
-
353
- chat.add_tool(tool)
354
- end
355
- end
356
- end
357
- end
358
- end