swarm_sdk 2.6.2 → 2.7.1

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 (33) hide show
  1. checksums.yaml +4 -4
  2. data/lib/swarm_sdk/agent/builder.rb +33 -1
  3. data/lib/swarm_sdk/agent/chat.rb +179 -35
  4. data/lib/swarm_sdk/agent/definition.rb +7 -1
  5. data/lib/swarm_sdk/agent/llm_instrumentation_middleware.rb +48 -8
  6. data/lib/swarm_sdk/agent/tool_registry.rb +189 -0
  7. data/lib/swarm_sdk/builders/base_builder.rb +4 -0
  8. data/lib/swarm_sdk/config.rb +2 -1
  9. data/lib/swarm_sdk/configuration/translator.rb +2 -0
  10. data/lib/swarm_sdk/models.json +296 -238
  11. data/lib/swarm_sdk/swarm/agent_initializer.rb +51 -3
  12. data/lib/swarm_sdk/swarm/all_agents_builder.rb +9 -0
  13. data/lib/swarm_sdk/swarm/mcp_configurator.rb +45 -7
  14. data/lib/swarm_sdk/swarm/tool_configurator.rb +25 -5
  15. data/lib/swarm_sdk/tools/base.rb +63 -0
  16. data/lib/swarm_sdk/tools/bash.rb +1 -1
  17. data/lib/swarm_sdk/tools/clock.rb +3 -1
  18. data/lib/swarm_sdk/tools/delegate.rb +14 -3
  19. data/lib/swarm_sdk/tools/edit.rb +1 -1
  20. data/lib/swarm_sdk/tools/glob.rb +1 -1
  21. data/lib/swarm_sdk/tools/grep.rb +1 -1
  22. data/lib/swarm_sdk/tools/mcp_tool_stub.rb +137 -0
  23. data/lib/swarm_sdk/tools/multi_edit.rb +1 -1
  24. data/lib/swarm_sdk/tools/read.rb +1 -1
  25. data/lib/swarm_sdk/tools/scratchpad/scratchpad_list.rb +1 -1
  26. data/lib/swarm_sdk/tools/scratchpad/scratchpad_read.rb +1 -1
  27. data/lib/swarm_sdk/tools/scratchpad/scratchpad_write.rb +1 -1
  28. data/lib/swarm_sdk/tools/think.rb +3 -1
  29. data/lib/swarm_sdk/tools/todo_write.rb +3 -1
  30. data/lib/swarm_sdk/tools/web_fetch.rb +1 -1
  31. data/lib/swarm_sdk/tools/write.rb +1 -1
  32. data/lib/swarm_sdk/version.rb +1 -1
  33. metadata +4 -1
@@ -25,12 +25,13 @@ module SwarmSDK
25
25
 
26
26
  # Initialize all agents with their chat instances and tools
27
27
  #
28
- # This implements a 5-pass algorithm:
28
+ # This implements a 6-pass algorithm:
29
29
  # 1. Create all Agent::Chat instances
30
30
  # 2. Register delegation tools (agents can call each other)
31
31
  # 3. Setup agent contexts for tracking
32
32
  # 4. Configure hook system
33
33
  # 5. Apply YAML hooks (if loaded from YAML)
34
+ # 6. Activate tools (Plan 025: populate @llm_chat.tools from registry after plugins)
34
35
  #
35
36
  # @return [Hash] agents hash { agent_name => Agent::Chat }
36
37
  def initialize_all
@@ -39,6 +40,7 @@ module SwarmSDK
39
40
  pass_3_setup_contexts
40
41
  pass_4_configure_hooks
41
42
  pass_5_apply_yaml_hooks
43
+ pass_6_activate_tools # Plan 025: Activate tools after all plugins registered
42
44
 
43
45
  @agents
44
46
  end
@@ -261,7 +263,12 @@ module SwarmSDK
261
263
  custom_tool_name: custom_tool_name,
262
264
  )
263
265
 
264
- delegator_chat.add_tool(tool)
266
+ # Register in tool registry (Plan 025)
267
+ delegator_chat.tool_registry.register(
268
+ tool,
269
+ source: :delegation,
270
+ metadata: { delegate_name: swarm_name, delegation_type: :swarm },
271
+ )
265
272
  end
266
273
 
267
274
  # Wire delegation to a local agent
@@ -311,7 +318,15 @@ module SwarmSDK
311
318
  custom_tool_name: custom_tool_name,
312
319
  )
313
320
 
314
- delegator_chat.add_tool(tool)
321
+ # Register in tool registry (Plan 025)
322
+ delegator_chat.tool_registry.register(
323
+ tool,
324
+ source: :delegation,
325
+ metadata: {
326
+ delegate_name: delegate_name_sym,
327
+ delegation_mode: delegate_definition.shared_across_delegations ? :shared : :isolated,
328
+ },
329
+ )
315
330
  end
316
331
 
317
332
  # Pass 3: Setup agent contexts
@@ -447,6 +462,22 @@ module SwarmSDK
447
462
  Hooks::Adapter.apply_agent_hooks(chat, agent_name, hooks, @swarm.name)
448
463
  end
449
464
 
465
+ # Pass 6: Activate tools after all plugins have registered (Plan 025)
466
+ #
467
+ # This must be the LAST pass because:
468
+ # - Plugins register tools in on_agent_initialized (e.g., LoadSkill from memory plugin)
469
+ # - Tools must be activated AFTER all registration is complete
470
+ # - This populates @llm_chat.tools from the registry
471
+ #
472
+ # @return [void]
473
+ def pass_6_activate_tools
474
+ # Activate tools for PRIMARY agents
475
+ @agents.each_value(&:activate_tools_for_prompt)
476
+
477
+ # Activate tools for DELEGATION instances
478
+ @swarm.delegation_instances.each_value(&:activate_tools_for_prompt)
479
+ end
480
+
450
481
  # Create Agent::Chat instance with rate limiting
451
482
  #
452
483
  # @param agent_name [Symbol] Agent name
@@ -476,6 +507,15 @@ module SwarmSDK
476
507
  mcp_configurator.register_mcp_servers(chat, agent_definition.mcp_servers, agent_name: agent_name)
477
508
  end
478
509
 
510
+ # Setup tool activation dependencies (Plan 025)
511
+ chat.setup_tool_activation(
512
+ tool_configurator: tool_configurator,
513
+ agent_definition: agent_definition,
514
+ )
515
+
516
+ # NOTE: activate_tools_for_prompt is called in Pass 5 after all plugins
517
+ # have registered their tools (e.g., LoadSkill from memory plugin)
518
+
479
519
  chat
480
520
  end
481
521
 
@@ -517,9 +557,17 @@ module SwarmSDK
517
557
  )
518
558
  end
519
559
 
560
+ # Setup tool activation dependencies (Plan 025)
561
+ chat.setup_tool_activation(
562
+ tool_configurator: tool_configurator,
563
+ agent_definition: agent_definition,
564
+ )
565
+
520
566
  # Notify plugins (use instance_name, plugins extract base_name if needed)
521
567
  notify_plugins_agent_initialized(instance_name.to_sym, chat, agent_definition, tool_configurator)
522
568
 
569
+ # NOTE: activate_tools_for_prompt is called in Pass 6 after all plugins
570
+
523
571
  chat
524
572
  end
525
573
 
@@ -35,6 +35,7 @@ module SwarmSDK
35
35
  @headers = nil
36
36
  @coding_agent = nil
37
37
  @disable_default_tools = nil
38
+ @streaming = nil
38
39
  end
39
40
 
40
41
  # Set model for all agents
@@ -91,6 +92,13 @@ module SwarmSDK
91
92
  @disable_default_tools = value
92
93
  end
93
94
 
95
+ # Enable or disable streaming for all agents
96
+ #
97
+ # @param value [Boolean] If true, enables streaming; if false, disables it
98
+ def streaming(value)
99
+ @streaming = value
100
+ end
101
+
94
102
  # Add tools that all agents will have
95
103
  def tools(*tool_names)
96
104
  @tools_list.concat(tool_names)
@@ -165,6 +173,7 @@ module SwarmSDK
165
173
  headers: @headers,
166
174
  coding_agent: @coding_agent,
167
175
  disable_default_tools: @disable_default_tools,
176
+ streaming: @streaming,
168
177
  tools: @tools_list,
169
178
  permissions: @permissions_config,
170
179
  }.compact
@@ -22,9 +22,22 @@ module SwarmSDK
22
22
  # Connects to MCP servers and registers their tools with the agent's chat instance.
23
23
  # Supports stdio, SSE, and HTTP (streamable) transports.
24
24
  #
25
+ # ## Boot Optimization (Plan 025)
26
+ #
27
+ # - If tools specified: Create stubs without tools/list RPC (fast boot, lazy schema)
28
+ # - If tools omitted: Call tools/list to discover all tools (discovery mode)
29
+ #
25
30
  # @param chat [AgentChat] The agent's chat instance
26
31
  # @param mcp_server_configs [Array<Hash>] MCP server configurations
27
32
  # @param agent_name [Symbol] Agent name for tracking clients
33
+ #
34
+ # @example Fast boot mode
35
+ # mcp_server :codebase, type: :stdio, command: "mcp-server", tools: [:search, :list]
36
+ # # Creates tool stubs instantly, no tools/list RPC
37
+ #
38
+ # @example Discovery mode
39
+ # mcp_server :codebase, type: :stdio, command: "mcp-server"
40
+ # # Calls tools/list to discover all available tools
28
41
  def register_mcp_servers(chat, mcp_server_configs, agent_name:)
29
42
  return if mcp_server_configs.nil? || mcp_server_configs.empty?
30
43
 
@@ -37,14 +50,39 @@ module SwarmSDK
37
50
  # Store client for cleanup
38
51
  @mcp_clients[agent_name] << client
39
52
 
40
- # Fetch tools from MCP server and register with chat
41
- # Tools are already in RubyLLM::Tool format
42
- tools = client.tools
43
- tools.each { |tool| chat.add_tool(tool) }
44
-
45
- RubyLLM.logger.debug("SwarmSDK: Registered #{tools.size} tools from MCP server '#{server_config[:name]}' for agent #{agent_name}")
53
+ tools_config = server_config[:tools]
54
+
55
+ if tools_config.nil?
56
+ # Discovery mode: Fetch all tools from server (calls tools/list)
57
+ # client.tools returns RubyLLM::Tool instances (already wrapped by internal Coordinator)
58
+ all_tools = client.tools
59
+ all_tools.each do |tool|
60
+ chat.tool_registry.register(
61
+ tool,
62
+ source: :mcp,
63
+ metadata: { server_name: server_config[:name] },
64
+ )
65
+ end
66
+ RubyLLM.logger.debug("SwarmSDK: Discovered and registered #{all_tools.size} tools from MCP server '#{server_config[:name]}'")
67
+ else
68
+ # Optimized mode: Create tool stubs without tools/list RPC (Plan 025)
69
+ # Use client directly (it has internal coordinator)
70
+ tools_config.each do |tool_name|
71
+ stub = Tools::McpToolStub.new(
72
+ client: client,
73
+ name: tool_name.to_s,
74
+ )
75
+ chat.tool_registry.register(
76
+ stub,
77
+ source: :mcp,
78
+ metadata: { server_name: server_config[:name] },
79
+ )
80
+ end
81
+ RubyLLM.logger.debug("SwarmSDK: Registered #{tools_config.size} tool stubs from MCP server '#{server_config[:name]}' (lazy schema)")
82
+ end
46
83
  rescue StandardError => e
47
- RubyLLM.logger.error("SwarmSDK: Failed to initialize MCP server '#{server_config[:name]}' for agent #{agent_name}: #{e.message}")
84
+ RubyLLM.logger.error("SwarmSDK: Failed to initialize MCP server '#{server_config[:name]}' for agent #{agent_name}: #{e.class.name}: #{e.message}")
85
+ RubyLLM.logger.error("SwarmSDK: Backtrace: #{e.backtrace.first(5).join("\n ")}")
48
86
  raise ConfigurationError, "Failed to initialize MCP server '#{server_config[:name]}': #{e.message}"
49
87
  end
50
88
  end
@@ -219,9 +219,17 @@ module SwarmSDK
219
219
  # @param permissions_config [Hash, nil] Permissions configuration
220
220
  # @param agent_definition [Agent::Definition] Agent definition
221
221
  # @return [void]
222
- def wrap_and_add_tool(chat, tool_instance, permissions_config, agent_definition)
223
- tool_instance = wrap_tool_with_permissions(tool_instance, permissions_config, agent_definition)
224
- chat.add_tool(tool_instance)
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
+ )
225
233
  end
226
234
 
227
235
  # Resolve permissions for a default/plugin tool
@@ -301,7 +309,14 @@ module SwarmSDK
301
309
 
302
310
  permissions_config = resolve_default_permissions(tool_name, agent_definition)
303
311
 
304
- wrap_and_add_tool(chat, tool_instance, permissions_config, agent_definition)
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
+ )
305
320
  end
306
321
  end
307
322
  end
@@ -364,7 +379,12 @@ module SwarmSDK
364
379
  delegating_chat: chat,
365
380
  )
366
381
 
367
- chat.add_tool(tool)
382
+ # Register in tool registry (Plan 025)
383
+ chat.tool_registry.register(
384
+ tool,
385
+ source: :delegation,
386
+ metadata: { delegate_name: delegate_name },
387
+ )
368
388
  end
369
389
  end
370
390
  end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SwarmSDK
4
+ module Tools
5
+ # Base class for all SwarmSDK tools
6
+ #
7
+ # Provides:
8
+ # - Declarative removability control
9
+ # - Common tool functionality
10
+ # - Standard initialization patterns
11
+ #
12
+ # ## Removability
13
+ #
14
+ # Tools can be marked as non-removable to ensure they're always available:
15
+ #
16
+ # class Think < Base
17
+ # removable false
18
+ # end
19
+ #
20
+ # Non-removable tools are included even when skills specify a limited toolset.
21
+ #
22
+ # @example Removable tool (default)
23
+ # class Read < Base
24
+ # # removable true # Default, can omit
25
+ # end
26
+ #
27
+ # @example Non-removable tool
28
+ # class Think < Base
29
+ # removable false # Always available
30
+ # end
31
+ class Base < RubyLLM::Tool
32
+ class << self
33
+ # Whether this tool can be deactivated by LoadSkill
34
+ #
35
+ # Non-removable tools are ALWAYS active regardless of skill toolset.
36
+ # Use for essential tools that agents should never lose.
37
+ #
38
+ # @return [Boolean] True if removable (default: true)
39
+ def removable?
40
+ @removable.nil? ? true : @removable
41
+ end
42
+
43
+ # Mark tool as removable or non-removable
44
+ #
45
+ # @param value [Boolean] Whether tool can be removed
46
+ # @return [void]
47
+ #
48
+ # @example Make tool always available
49
+ # removable false
50
+ def removable(value)
51
+ @removable = value
52
+ end
53
+ end
54
+
55
+ # Instance method for checking removability
56
+ #
57
+ # @return [Boolean]
58
+ def removable?
59
+ self.class.removable?
60
+ end
61
+ end
62
+ end
63
+ end
@@ -6,7 +6,7 @@ module SwarmSDK
6
6
  #
7
7
  # Executes commands in a persistent shell session with timeout support.
8
8
  # Provides comprehensive guidance on proper usage patterns.
9
- class Bash < RubyLLM::Tool
9
+ class Bash < Base
10
10
  # Factory pattern: declare what parameters this tool needs for instantiation
11
11
  class << self
12
12
  def creation_requirements
@@ -6,7 +6,9 @@ module SwarmSDK
6
6
  #
7
7
  # Returns current temporal information in a consistent format.
8
8
  # Agents use this when they need to know what day/time it is.
9
- class Clock < RubyLLM::Tool
9
+ class Clock < Base
10
+ removable false # Clock is always available
11
+
10
12
  description <<~DESC
11
13
  Get current date and time.
12
14
 
@@ -7,7 +7,8 @@ module SwarmSDK
7
7
  # Creates agent-specific collaboration tools (e.g., WorkWithBackend)
8
8
  # that allow one agent to work with another agent.
9
9
  # Supports pre/post delegation hooks for customization.
10
- class Delegate < RubyLLM::Tool
10
+ class Delegate < Base
11
+ removable true # Delegate tools can be controlled by skills
11
12
  # Tool name prefix for delegation tools
12
13
  # Change this to customize the tool naming pattern (e.g., "DelegateTaskTo", "AskAgent", etc.)
13
14
  TOOL_NAME_PREFIX = "WorkWith"
@@ -19,10 +20,20 @@ module SwarmSDK
19
20
  # Used both when creating Delegate instances and when predicting tool names
20
21
  # for agent context setup.
21
22
  #
23
+ # Converts names to PascalCase: backend → Backend, slack_agent → SlackAgent
24
+ #
22
25
  # @param delegate_name [String, Symbol] Name of the delegate agent
23
- # @return [String] Tool name (e.g., "WorkWithBackend")
26
+ # @return [String] Tool name (e.g., "WorkWithBackend", "WorkWithSlackAgent")
27
+ #
28
+ # @example Simple name
29
+ # tool_name_for(:backend) # => "WorkWithBackend"
30
+ #
31
+ # @example Name with underscore
32
+ # tool_name_for(:slack_agent) # => "WorkWithSlackAgent"
24
33
  def tool_name_for(delegate_name)
25
- "#{TOOL_NAME_PREFIX}#{delegate_name.to_s.capitalize}"
34
+ # Convert to PascalCase: split on underscore, capitalize each part, join
35
+ pascal_case = delegate_name.to_s.split("_").map(&:capitalize).join
36
+ "#{TOOL_NAME_PREFIX}#{pascal_case}"
26
37
  end
27
38
  end
28
39
 
@@ -7,7 +7,7 @@ module SwarmSDK
7
7
  # Uses exact string matching to find and replace content.
8
8
  # Requires unique matches and proper Read tool usage beforehand.
9
9
  # Enforces read-before-edit rule.
10
- class Edit < RubyLLM::Tool
10
+ class Edit < Base
11
11
  include PathResolver
12
12
 
13
13
  # Factory pattern: declare what parameters this tool needs for instantiation
@@ -6,7 +6,7 @@ module SwarmSDK
6
6
  #
7
7
  # Finds files and directories matching glob patterns, sorted by modification time.
8
8
  # Works efficiently with any codebase size.
9
- class Glob < RubyLLM::Tool
9
+ class Glob < Base
10
10
  include PathResolver
11
11
 
12
12
  # Factory pattern: declare what parameters this tool needs for instantiation
@@ -6,7 +6,7 @@ module SwarmSDK
6
6
  #
7
7
  # Powerful search capabilities with regex support, context lines, and filtering.
8
8
  # Built on ripgrep (rg) for fast, efficient searching.
9
- class Grep < RubyLLM::Tool
9
+ class Grep < Base
10
10
  include PathResolver
11
11
 
12
12
  # Factory pattern: declare what parameters this tool needs for instantiation
@@ -0,0 +1,137 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SwarmSDK
4
+ module Tools
5
+ # Lazy-loading wrapper for MCP tools
6
+ #
7
+ # Creates minimal tool stub without calling tools/list.
8
+ # Schema is fetched on-demand when LLM needs it.
9
+ #
10
+ # ## Boot Optimization
11
+ #
12
+ # When MCP server tools are pre-specified in configuration:
13
+ # - Boot time: Create stubs instantly (no RPC)
14
+ # - First LLM request: Fetch schema lazily (~100ms one-time cost)
15
+ # - Subsequent requests: Use cached schema (instant)
16
+ #
17
+ # ## Thread Safety
18
+ #
19
+ # Schema loading is protected by Async::Semaphore with double-check pattern
20
+ # to ensure only one fiber fetches the schema even under concurrent access.
21
+ #
22
+ # @example Creating a stub
23
+ # coordinator = RubyLLM::MCP::Coordinator.new(client)
24
+ # stub = McpToolStub.new(
25
+ # coordinator: coordinator,
26
+ # name: "search_code",
27
+ # description: "Search code in repository"
28
+ # )
29
+ #
30
+ # @example Schema is fetched lazily
31
+ # stub.params_schema # First access triggers tools/list RPC
32
+ # stub.params_schema # Cached, instant
33
+ class McpToolStub < Base
34
+ removable true # MCP tools can be controlled by skills
35
+
36
+ attr_reader :name, :client
37
+
38
+ # Create a new MCP tool stub
39
+ #
40
+ # @param client [RubyLLM::MCP::Client] MCP client instance
41
+ # @param name [String] Tool name
42
+ # @param description [String, nil] Tool description (optional, fetched if nil)
43
+ # @param schema [Hash, nil] Tool input schema (optional, fetched if nil)
44
+ #
45
+ # @example Minimal stub (lazy description + schema)
46
+ # McpToolStub.new(client: client, name: "search")
47
+ #
48
+ # @example With description (lazy schema only)
49
+ # McpToolStub.new(
50
+ # client: client,
51
+ # name: "search",
52
+ # description: "Search the codebase"
53
+ # )
54
+ #
55
+ # @example Fully specified (no lazy loading)
56
+ # McpToolStub.new(
57
+ # client: client,
58
+ # name: "search",
59
+ # description: "Search the codebase",
60
+ # schema: { type: "object", properties: {...} }
61
+ # )
62
+ def initialize(client:, name:, description: nil, schema: nil)
63
+ super()
64
+ @client = client
65
+ @name = name
66
+ @mcp_name = name
67
+ @description = description || "MCP tool: #{name}"
68
+ @input_schema = schema
69
+ @schema_loaded = !schema.nil?
70
+ @schema_mutex = Async::Semaphore.new(1) # Thread-safe schema loading
71
+ end
72
+
73
+ # Get tool description
74
+ #
75
+ # @return [String]
76
+ attr_reader :description
77
+
78
+ # Get parameter schema (lazy-loaded on first access)
79
+ #
80
+ # This method is called by RubyLLM when building tool schemas for LLM requests.
81
+ # On first access, it triggers a tools/list RPC to fetch the schema.
82
+ #
83
+ # @return [Hash, nil] JSON Schema for tool parameters
84
+ def params_schema
85
+ ensure_schema_loaded!
86
+ @input_schema
87
+ end
88
+
89
+ # Execute the MCP tool
90
+ #
91
+ # Calls the MCP server's tools/call endpoint with the provided parameters.
92
+ # Schema is NOT required for execution - the server validates parameters.
93
+ #
94
+ # @param params [Hash] Tool parameters
95
+ # @return [String, Hash] Tool result content or error hash
96
+ def execute(**params)
97
+ # Use client.call_tool (client has internal coordinator)
98
+ result = @client.call_tool(
99
+ name: @mcp_name,
100
+ arguments: params,
101
+ )
102
+
103
+ # client.call_tool returns the result content directly
104
+ result
105
+ end
106
+
107
+ private
108
+
109
+ # Lazy-load schema on first access (when LLM needs it)
110
+ #
111
+ # Thread-safe via semaphore with double-check pattern.
112
+ # Multiple concurrent fibers will only trigger one fetch.
113
+ #
114
+ # @return [void]
115
+ def ensure_schema_loaded!
116
+ return if @schema_loaded
117
+
118
+ @schema_mutex.acquire do
119
+ return if @schema_loaded # Double-check after acquiring lock
120
+
121
+ # Fetch tool info from client (calls tools/list if not cached)
122
+ tool_info = @client.tool_info(@mcp_name)
123
+
124
+ if tool_info
125
+ @description = tool_info["description"] || @description
126
+ @input_schema = tool_info["inputSchema"]
127
+ else
128
+ # Tool doesn't exist on server - schema remains nil
129
+ RubyLLM.logger.warn("SwarmSDK: MCP tool '#{@mcp_name}' not found on server during schema fetch")
130
+ end
131
+
132
+ @schema_loaded = true
133
+ end
134
+ end
135
+ end
136
+ end
137
+ end
@@ -8,7 +8,7 @@ module SwarmSDK
8
8
  # Each edit sees the result of all previous edits, allowing for
9
9
  # coordinated multi-step transformations.
10
10
  # Enforces read-before-edit rule.
11
- class MultiEdit < RubyLLM::Tool
11
+ class MultiEdit < Base
12
12
  include PathResolver
13
13
 
14
14
  # Factory pattern: declare what parameters this tool needs for instantiation
@@ -7,7 +7,7 @@ module SwarmSDK
7
7
  # Supports reading entire files or specific line ranges with line numbers.
8
8
  # Provides system reminders to guide proper usage.
9
9
  # Tracks reads per agent for enforcing read-before-write/edit rules.
10
- class Read < RubyLLM::Tool
10
+ class Read < Base
11
11
  include PathResolver
12
12
 
13
13
  # NOTE: Line length and limit now accessed via SwarmSDK.config
@@ -7,7 +7,7 @@ module SwarmSDK
7
7
  #
8
8
  # Shows all entries in the shared scratchpad with their metadata.
9
9
  # All agents in the swarm share the same scratchpad.
10
- class ScratchpadList < RubyLLM::Tool
10
+ class ScratchpadList < Base
11
11
  define_method(:name) { "ScratchpadList" }
12
12
 
13
13
  description <<~DESC
@@ -7,7 +7,7 @@ module SwarmSDK
7
7
  #
8
8
  # Retrieves content stored by any agent using scratchpad_write.
9
9
  # All agents in the swarm share the same scratchpad.
10
- class ScratchpadRead < RubyLLM::Tool
10
+ class ScratchpadRead < Base
11
11
  define_method(:name) { "ScratchpadRead" }
12
12
 
13
13
  description <<~DESC
@@ -8,7 +8,7 @@ module SwarmSDK
8
8
  # Stores content in volatile, shared storage for temporary communication.
9
9
  # All agents in the swarm share the same scratchpad.
10
10
  # Data is lost when the process ends (not persisted).
11
- class ScratchpadWrite < RubyLLM::Tool
11
+ class ScratchpadWrite < Base
12
12
  define_method(:name) { "ScratchpadWrite" }
13
13
 
14
14
  description <<~DESC
@@ -11,7 +11,9 @@ module SwarmSDK
11
11
  # This is inspired by research showing that explicitly articulating reasoning steps
12
12
  # (chain-of-thought prompting) leads to significantly better outcomes, especially
13
13
  # for complex tasks requiring multi-step reasoning or arithmetic.
14
- class Think < RubyLLM::Tool
14
+ class Think < Base
15
+ removable false # Think is always available
16
+
15
17
  def name
16
18
  "Think"
17
19
  end
@@ -6,7 +6,9 @@ module SwarmSDK
6
6
  #
7
7
  # This tool helps agents track progress on complex multi-step tasks.
8
8
  # Each agent maintains its own independent todo list.
9
- class TodoWrite < RubyLLM::Tool
9
+ class TodoWrite < Base
10
+ removable false # TodoWrite is always available
11
+
10
12
  # Factory pattern: declare what parameters this tool needs for instantiation
11
13
  class << self
12
14
  def creation_requirements
@@ -6,7 +6,7 @@ module SwarmSDK
6
6
  #
7
7
  # Fetches content from URLs, converts HTML to markdown, and processes it
8
8
  # using an AI model to extract information based on a provided prompt.
9
- class WebFetch < RubyLLM::Tool
9
+ class WebFetch < Base
10
10
  def initialize
11
11
  super()
12
12
  @cache = {}
@@ -7,7 +7,7 @@ module SwarmSDK
7
7
  # Creates new files or overwrites existing files.
8
8
  # Enforces read-before-write rule for existing files.
9
9
  # Includes validation and usage guidelines via system reminders.
10
- class Write < RubyLLM::Tool
10
+ class Write < Base
11
11
  include PathResolver
12
12
 
13
13
  # Factory pattern: declare what parameters this tool needs for instantiation
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SwarmSDK
4
- VERSION = "2.6.2"
4
+ VERSION = "2.7.1"
5
5
  end