claude_swarm 1.0.10 → 1.0.11
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/{CHANGELOG.md → CHANGELOG.claude-swarm.md} +3 -0
- data/CLAUDE.md +0 -1
- data/decisions/2025-11-22-001-global-agent-registry.md +172 -0
- data/docs/v2/CHANGELOG.swarm_cli.md +12 -0
- data/docs/v2/CHANGELOG.swarm_memory.md +139 -0
- data/docs/v2/CHANGELOG.swarm_sdk.md +249 -1
- data/docs/v2/README.md +15 -5
- data/docs/v2/guides/complete-tutorial.md +93 -7
- data/docs/v2/guides/getting-started.md +3 -1
- data/docs/v2/guides/memory-adapters.md +41 -0
- data/docs/v2/guides/{migrating-to-2.3.md → migrating-to-2.x.md} +213 -8
- data/docs/v2/guides/plugins.md +52 -5
- data/docs/v2/guides/rails-integration.md +6 -0
- data/docs/v2/guides/swarm-memory.md +2 -13
- data/docs/v2/reference/cli.md +0 -1
- data/docs/v2/reference/configuration_reference.md +300 -0
- data/docs/v2/reference/event_payload_structures.md +26 -4
- data/docs/v2/reference/ruby-dsl.md +457 -4
- data/docs/v2/reference/swarm_memory_technical_details.md +7 -29
- data/docs/v2/reference/yaml.md +2 -2
- data/lib/claude_swarm/mcp_generator.rb +1 -1
- data/lib/claude_swarm/orchestrator.rb +8 -1
- data/lib/claude_swarm/version.rb +1 -1
- data/lib/swarm_cli/version.rb +1 -1
- data/lib/swarm_memory/core/semantic_index.rb +10 -2
- data/lib/swarm_memory/core/storage.rb +7 -2
- data/lib/swarm_memory/dsl/memory_config.rb +37 -0
- data/lib/swarm_memory/integration/sdk_plugin.rb +120 -27
- data/lib/swarm_memory/optimization/defragmenter.rb +1 -1
- data/lib/swarm_memory/prompts/memory_researcher.md.erb +0 -1
- data/lib/swarm_memory/tools/load_skill.rb +0 -1
- data/lib/swarm_memory/tools/memory_edit.rb +2 -1
- data/lib/swarm_memory/tools/memory_read.rb +1 -1
- data/lib/swarm_memory/version.rb +1 -1
- data/lib/swarm_memory.rb +7 -5
- data/lib/swarm_sdk/agent/chat.rb +1 -1
- data/lib/swarm_sdk/agent/chat_helpers/context_tracker.rb +4 -0
- data/lib/swarm_sdk/agent/chat_helpers/hook_integration.rb +1 -1
- data/lib/swarm_sdk/agent/chat_helpers/llm_configuration.rb +38 -4
- data/lib/swarm_sdk/agent/chat_helpers/logging_helpers.rb +2 -2
- data/lib/swarm_sdk/agent/chat_helpers/system_reminder_injector.rb +3 -5
- data/lib/swarm_sdk/agent/chat_helpers/token_tracking.rb +48 -0
- data/lib/swarm_sdk/agent/context.rb +1 -2
- data/lib/swarm_sdk/agent/definition.rb +3 -3
- data/lib/swarm_sdk/agent/system_prompt_builder.rb +1 -1
- data/lib/swarm_sdk/agent_registry.rb +146 -0
- data/lib/swarm_sdk/builders/base_builder.rb +91 -12
- data/lib/swarm_sdk/config.rb +302 -0
- data/lib/swarm_sdk/configuration/parser.rb +22 -2
- data/lib/swarm_sdk/configuration.rb +13 -4
- data/lib/swarm_sdk/context_compactor/token_counter.rb +2 -6
- data/lib/swarm_sdk/custom_tool_registry.rb +226 -0
- data/lib/swarm_sdk/hooks/adapter.rb +3 -3
- data/lib/swarm_sdk/hooks/shell_executor.rb +4 -3
- data/lib/swarm_sdk/models.json +4333 -1
- data/lib/swarm_sdk/models.rb +43 -2
- data/lib/swarm_sdk/plugin.rb +2 -2
- data/lib/swarm_sdk/result.rb +52 -0
- data/lib/swarm_sdk/swarm/agent_initializer.rb +1 -1
- data/lib/swarm_sdk/swarm/hook_triggers.rb +1 -0
- data/lib/swarm_sdk/swarm/logging_callbacks.rb +1 -0
- data/lib/swarm_sdk/swarm/tool_configurator.rb +18 -4
- data/lib/swarm_sdk/swarm.rb +76 -13
- data/lib/swarm_sdk/tools/bash.rb +7 -9
- data/lib/swarm_sdk/tools/glob.rb +5 -5
- data/lib/swarm_sdk/tools/read.rb +8 -8
- data/lib/swarm_sdk/tools/stores/scratchpad_storage.rb +4 -3
- data/lib/swarm_sdk/tools/web_fetch.rb +20 -18
- data/lib/swarm_sdk/version.rb +1 -1
- data/lib/swarm_sdk/workflow/builder.rb +49 -0
- data/lib/swarm_sdk/workflow/node_builder.rb +4 -2
- data/lib/swarm_sdk/workflow/transformer_executor.rb +4 -3
- data/lib/swarm_sdk.rb +261 -105
- data/swarm_cli.gemspec +1 -1
- data/swarm_memory.gemspec +8 -3
- data/swarm_sdk.gemspec +4 -4
- data/team_full.yml +104 -300
- metadata +9 -5
- data/lib/swarm_memory/tools/memory_multi_edit.rb +0 -281
- /data/lib/swarm_memory/{errors.rb → error.rb} +0 -0
|
@@ -38,9 +38,13 @@ module SwarmSDK
|
|
|
38
38
|
# Load configuration from YAML file
|
|
39
39
|
#
|
|
40
40
|
# @param path [String, Pathname] Path to YAML configuration file
|
|
41
|
+
# @param env_interpolation [Boolean, nil] Whether to interpolate environment variables.
|
|
42
|
+
# When nil, uses the global SwarmSDK.config.env_interpolation setting.
|
|
43
|
+
# When true, interpolates ${VAR} and ${VAR:=default} patterns.
|
|
44
|
+
# When false, skips interpolation entirely.
|
|
41
45
|
# @return [Configuration] Validated configuration instance
|
|
42
46
|
# @raise [ConfigurationError] If file not found or invalid
|
|
43
|
-
def load_file(path)
|
|
47
|
+
def load_file(path, env_interpolation: nil)
|
|
44
48
|
path = Pathname.new(path).expand_path
|
|
45
49
|
|
|
46
50
|
unless path.exist?
|
|
@@ -50,7 +54,7 @@ module SwarmSDK
|
|
|
50
54
|
yaml_content = File.read(path)
|
|
51
55
|
base_dir = path.dirname
|
|
52
56
|
|
|
53
|
-
new(yaml_content, base_dir: base_dir).tap(&:load_and_validate)
|
|
57
|
+
new(yaml_content, base_dir: base_dir, env_interpolation: env_interpolation).tap(&:load_and_validate)
|
|
54
58
|
rescue Errno::ENOENT
|
|
55
59
|
raise ConfigurationError, "Configuration file not found: #{path}"
|
|
56
60
|
end
|
|
@@ -60,12 +64,17 @@ module SwarmSDK
|
|
|
60
64
|
#
|
|
61
65
|
# @param yaml_content [String] YAML configuration content
|
|
62
66
|
# @param base_dir [String, Pathname] Base directory for resolving agent file paths (default: Dir.pwd)
|
|
63
|
-
|
|
67
|
+
# @param env_interpolation [Boolean, nil] Whether to interpolate environment variables.
|
|
68
|
+
# When nil, uses the global SwarmSDK.config.env_interpolation setting.
|
|
69
|
+
# When true, interpolates ${VAR} and ${VAR:=default} patterns.
|
|
70
|
+
# When false, skips interpolation entirely.
|
|
71
|
+
def initialize(yaml_content, base_dir: Dir.pwd, env_interpolation: nil)
|
|
64
72
|
raise ArgumentError, "yaml_content cannot be nil" if yaml_content.nil?
|
|
65
73
|
raise ArgumentError, "base_dir cannot be nil" if base_dir.nil?
|
|
66
74
|
|
|
67
75
|
@yaml_content = yaml_content
|
|
68
76
|
@base_dir = Pathname.new(base_dir).expand_path
|
|
77
|
+
@env_interpolation = env_interpolation
|
|
69
78
|
@parser = nil
|
|
70
79
|
@translator = nil
|
|
71
80
|
end
|
|
@@ -77,7 +86,7 @@ module SwarmSDK
|
|
|
77
86
|
#
|
|
78
87
|
# @return [self]
|
|
79
88
|
def load_and_validate
|
|
80
|
-
@parser = Parser.new(@yaml_content, base_dir: @base_dir)
|
|
89
|
+
@parser = Parser.new(@yaml_content, base_dir: @base_dir, env_interpolation: @env_interpolation)
|
|
81
90
|
@parser.parse
|
|
82
91
|
|
|
83
92
|
# Sync parsed data to instance variables for backward compatibility
|
|
@@ -17,10 +17,6 @@ module SwarmSDK
|
|
|
17
17
|
# total_tokens = TokenCounter.estimate_messages(messages)
|
|
18
18
|
#
|
|
19
19
|
class TokenCounter
|
|
20
|
-
# Backward compatibility aliases - use Defaults module for new code
|
|
21
|
-
CHARS_PER_TOKEN_PROSE = Defaults::TokenEstimation::CHARS_PER_TOKEN_PROSE
|
|
22
|
-
CHARS_PER_TOKEN_CODE = Defaults::TokenEstimation::CHARS_PER_TOKEN_CODE
|
|
23
|
-
|
|
24
20
|
class << self
|
|
25
21
|
# Estimate tokens for a single message
|
|
26
22
|
#
|
|
@@ -78,9 +74,9 @@ module SwarmSDK
|
|
|
78
74
|
|
|
79
75
|
# Choose characters per token based on content type
|
|
80
76
|
chars_per_token = if code_ratio > 0.1
|
|
81
|
-
|
|
77
|
+
SwarmSDK.config.chars_per_token_code # Code
|
|
82
78
|
else
|
|
83
|
-
|
|
79
|
+
SwarmSDK.config.chars_per_token_prose # Prose
|
|
84
80
|
end
|
|
85
81
|
|
|
86
82
|
(text.length / chars_per_token).ceil
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "delegate"
|
|
4
|
+
|
|
5
|
+
module SwarmSDK
|
|
6
|
+
# Registry for user-defined custom tools
|
|
7
|
+
#
|
|
8
|
+
# Provides a simple way to register custom tools without creating a full plugin.
|
|
9
|
+
# Custom tools are registered globally and available to all agents that request them.
|
|
10
|
+
#
|
|
11
|
+
# ## When to Use Custom Tools vs Plugins
|
|
12
|
+
#
|
|
13
|
+
# **Use Custom Tools when:**
|
|
14
|
+
# - You have simple, stateless tools
|
|
15
|
+
# - Tools don't need persistent storage
|
|
16
|
+
# - Tools don't need lifecycle hooks
|
|
17
|
+
# - Tools don't need system prompt contributions
|
|
18
|
+
#
|
|
19
|
+
# **Use Plugins when:**
|
|
20
|
+
# - Tools need persistent storage per agent
|
|
21
|
+
# - Tools need lifecycle hooks (on_agent_initialized, on_user_message, etc.)
|
|
22
|
+
# - Tools need to contribute to system prompts
|
|
23
|
+
# - You have a suite of related tools that share configuration
|
|
24
|
+
#
|
|
25
|
+
# @example Register a simple tool
|
|
26
|
+
# class WeatherTool < RubyLLM::Tool
|
|
27
|
+
# description "Get weather for a city"
|
|
28
|
+
# param :city, type: "string", required: true
|
|
29
|
+
#
|
|
30
|
+
# def execute(city:)
|
|
31
|
+
# "Weather in #{city}: Sunny"
|
|
32
|
+
# end
|
|
33
|
+
# end
|
|
34
|
+
#
|
|
35
|
+
# SwarmSDK.register_tool(WeatherTool)
|
|
36
|
+
#
|
|
37
|
+
# @example Register with explicit name
|
|
38
|
+
# SwarmSDK.register_tool(:Weather, WeatherTool)
|
|
39
|
+
#
|
|
40
|
+
# @example Tool with creation requirements
|
|
41
|
+
# class AgentAwareTool < RubyLLM::Tool
|
|
42
|
+
# def self.creation_requirements
|
|
43
|
+
# [:agent_name, :directory]
|
|
44
|
+
# end
|
|
45
|
+
#
|
|
46
|
+
# def initialize(agent_name:, directory:)
|
|
47
|
+
# super()
|
|
48
|
+
# @agent_name = agent_name
|
|
49
|
+
# @directory = directory
|
|
50
|
+
# end
|
|
51
|
+
#
|
|
52
|
+
# def execute
|
|
53
|
+
# "Agent: #{@agent_name}, Dir: #{@directory}"
|
|
54
|
+
# end
|
|
55
|
+
# end
|
|
56
|
+
#
|
|
57
|
+
# SwarmSDK.register_tool(AgentAwareTool)
|
|
58
|
+
#
|
|
59
|
+
module CustomToolRegistry
|
|
60
|
+
# Wrapper that overrides the tool's name to match the registered name
|
|
61
|
+
#
|
|
62
|
+
# This ensures that when a user registers a tool with a specific name,
|
|
63
|
+
# that name is what gets used for tool lookup (has_tool?) and LLM tool calls.
|
|
64
|
+
class NamedToolWrapper < SimpleDelegator
|
|
65
|
+
def initialize(tool, registered_name)
|
|
66
|
+
super(tool)
|
|
67
|
+
@registered_name = registered_name.to_s
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Override name to return the registered name
|
|
71
|
+
def name
|
|
72
|
+
@registered_name
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
@tools = {}
|
|
77
|
+
|
|
78
|
+
class << self
|
|
79
|
+
# Register a custom tool
|
|
80
|
+
#
|
|
81
|
+
# @param name [Symbol] Tool name
|
|
82
|
+
# @param tool_class [Class] Tool class (must be a RubyLLM::Tool subclass)
|
|
83
|
+
# @raise [ArgumentError] If tool_class is not a RubyLLM::Tool subclass
|
|
84
|
+
# @raise [ArgumentError] If a tool with the same name is already registered
|
|
85
|
+
# @return [void]
|
|
86
|
+
def register(name, tool_class)
|
|
87
|
+
name = name.to_sym
|
|
88
|
+
|
|
89
|
+
unless tool_class.is_a?(Class) && tool_class < RubyLLM::Tool
|
|
90
|
+
raise ArgumentError, "Tool class must inherit from RubyLLM::Tool"
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
if @tools.key?(name)
|
|
94
|
+
raise ArgumentError, "Custom tool '#{name}' is already registered"
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
if PluginRegistry.plugin_tool?(name)
|
|
98
|
+
raise ArgumentError, "Tool '#{name}' is already provided by a plugin"
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
if Tools::Registry.exists?(name)
|
|
102
|
+
raise ArgumentError, "Tool '#{name}' is a built-in tool and cannot be overridden"
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
@tools[name] = tool_class
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# Check if a custom tool is registered
|
|
109
|
+
#
|
|
110
|
+
# @param name [Symbol, String] Tool name
|
|
111
|
+
# @return [Boolean]
|
|
112
|
+
def registered?(name)
|
|
113
|
+
@tools.key?(name.to_sym)
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# Get a registered tool class
|
|
117
|
+
#
|
|
118
|
+
# @param name [Symbol, String] Tool name
|
|
119
|
+
# @return [Class, nil] Tool class or nil if not found
|
|
120
|
+
def get(name)
|
|
121
|
+
@tools[name.to_sym]
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# Get all registered custom tool names
|
|
125
|
+
#
|
|
126
|
+
# @return [Array<Symbol>]
|
|
127
|
+
def tool_names
|
|
128
|
+
@tools.keys
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# Create a tool instance
|
|
132
|
+
#
|
|
133
|
+
# Uses the tool's `creation_requirements` class method (if defined) to determine
|
|
134
|
+
# what parameters to pass to the constructor. The created tool is wrapped with
|
|
135
|
+
# NamedToolWrapper to ensure the registered name is used for tool lookup.
|
|
136
|
+
#
|
|
137
|
+
# @param name [Symbol, String] Tool name
|
|
138
|
+
# @param context [Hash] Available context for tool creation
|
|
139
|
+
# @option context [Symbol] :agent_name Agent identifier
|
|
140
|
+
# @option context [String] :directory Agent's working directory
|
|
141
|
+
# @return [RubyLLM::Tool] Instantiated tool (wrapped with registered name)
|
|
142
|
+
# @raise [ConfigurationError] If tool is unknown or has unmet requirements
|
|
143
|
+
def create(name, context = {})
|
|
144
|
+
name_sym = name.to_sym
|
|
145
|
+
tool_class = @tools[name_sym]
|
|
146
|
+
|
|
147
|
+
raise ConfigurationError, "Unknown custom tool: #{name}" unless tool_class
|
|
148
|
+
|
|
149
|
+
# Create the tool instance
|
|
150
|
+
tool = if tool_class.respond_to?(:creation_requirements)
|
|
151
|
+
requirements = tool_class.creation_requirements
|
|
152
|
+
params = extract_params(requirements, context, name)
|
|
153
|
+
tool_class.new(**params)
|
|
154
|
+
else
|
|
155
|
+
# No requirements - simple instantiation
|
|
156
|
+
tool_class.new
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
# Wrap with NamedToolWrapper to ensure registered name is used
|
|
160
|
+
NamedToolWrapper.new(tool, name_sym)
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
# Unregister a custom tool
|
|
164
|
+
#
|
|
165
|
+
# @param name [Symbol, String] Tool name
|
|
166
|
+
# @return [Class, nil] The unregistered tool class, or nil if not found
|
|
167
|
+
def unregister(name)
|
|
168
|
+
@tools.delete(name.to_sym)
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
# Clear all registered custom tools
|
|
172
|
+
#
|
|
173
|
+
# Primarily useful for testing.
|
|
174
|
+
#
|
|
175
|
+
# @return [void]
|
|
176
|
+
def clear
|
|
177
|
+
@tools.clear
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
# Infer tool name from class name
|
|
181
|
+
#
|
|
182
|
+
# @param tool_class [Class] Tool class
|
|
183
|
+
# @return [Symbol] Inferred tool name
|
|
184
|
+
#
|
|
185
|
+
# @example
|
|
186
|
+
# infer_name(WeatherTool) #=> :Weather
|
|
187
|
+
# infer_name(MyApp::Tools::StockPrice) #=> :StockPrice
|
|
188
|
+
# infer_name(MyApp::Tools::StockPriceTool) #=> :StockPrice
|
|
189
|
+
def infer_name(tool_class)
|
|
190
|
+
# Get the class name without module prefix
|
|
191
|
+
class_name = tool_class.name.split("::").last
|
|
192
|
+
|
|
193
|
+
# Remove "Tool" suffix if present
|
|
194
|
+
name = class_name.sub(/Tool\z/, "")
|
|
195
|
+
|
|
196
|
+
name.to_sym
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
private
|
|
200
|
+
|
|
201
|
+
# Extract required parameters from context
|
|
202
|
+
#
|
|
203
|
+
# @param requirements [Array<Symbol>] Required parameter names
|
|
204
|
+
# @param context [Hash] Available context
|
|
205
|
+
# @param tool_name [Symbol] Tool name for error messages
|
|
206
|
+
# @return [Hash] Parameters to pass to tool constructor
|
|
207
|
+
# @raise [ConfigurationError] If required parameter is missing
|
|
208
|
+
def extract_params(requirements, context, tool_name)
|
|
209
|
+
params = {}
|
|
210
|
+
|
|
211
|
+
requirements.each do |req|
|
|
212
|
+
unless context.key?(req)
|
|
213
|
+
raise ConfigurationError,
|
|
214
|
+
"Custom tool '#{tool_name}' requires '#{req}' but it was not provided. " \
|
|
215
|
+
"Ensure the tool's `creation_requirements` only includes supported keys: " \
|
|
216
|
+
":agent_name, :directory"
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
params[req] = context[req]
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
params
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
end
|
|
226
|
+
end
|
|
@@ -167,7 +167,7 @@ module SwarmSDK
|
|
|
167
167
|
def create_hook_callback(hook_def, event_symbol, agent_name, swarm_name)
|
|
168
168
|
# Support both string and symbol keys (YAML may be symbolized)
|
|
169
169
|
command = hook_def[:command] || hook_def["command"]
|
|
170
|
-
timeout = hook_def[:timeout] || hook_def["timeout"] ||
|
|
170
|
+
timeout = hook_def[:timeout] || hook_def["timeout"] || SwarmSDK.config.hook_shell_timeout
|
|
171
171
|
|
|
172
172
|
lambda do |context|
|
|
173
173
|
input_json = build_input_json(context, event_symbol, agent_name)
|
|
@@ -191,7 +191,7 @@ module SwarmSDK
|
|
|
191
191
|
def create_all_agents_hook_callback(hook_def, event_symbol, swarm_name)
|
|
192
192
|
# Support both string and symbol keys (YAML may be symbolized)
|
|
193
193
|
command = hook_def[:command] || hook_def["command"]
|
|
194
|
-
timeout = hook_def[:timeout] || hook_def["timeout"] ||
|
|
194
|
+
timeout = hook_def[:timeout] || hook_def["timeout"] || SwarmSDK.config.hook_shell_timeout
|
|
195
195
|
|
|
196
196
|
lambda do |context|
|
|
197
197
|
# Agent name comes from context
|
|
@@ -217,7 +217,7 @@ module SwarmSDK
|
|
|
217
217
|
def create_swarm_hook_callback(hook_def, event_symbol, swarm_name)
|
|
218
218
|
# Support both string and symbol keys (YAML may be symbolized)
|
|
219
219
|
command = hook_def[:command] || hook_def["command"]
|
|
220
|
-
timeout = hook_def[:timeout] || hook_def["timeout"] ||
|
|
220
|
+
timeout = hook_def[:timeout] || hook_def["timeout"] || SwarmSDK.config.hook_shell_timeout
|
|
221
221
|
|
|
222
222
|
lambda do |context|
|
|
223
223
|
input_json = build_swarm_input_json(context, event_symbol, swarm_name)
|
|
@@ -47,8 +47,7 @@ module SwarmSDK
|
|
|
47
47
|
# )
|
|
48
48
|
# # => Result (continue or halt based on exit code)
|
|
49
49
|
class ShellExecutor
|
|
50
|
-
#
|
|
51
|
-
DEFAULT_TIMEOUT = Defaults::Timeouts::HOOK_SHELL_SECONDS
|
|
50
|
+
# NOTE: Timeout now accessed via SwarmSDK.config.hook_shell_timeout
|
|
52
51
|
|
|
53
52
|
class << self
|
|
54
53
|
# Execute a shell command hook
|
|
@@ -60,7 +59,9 @@ module SwarmSDK
|
|
|
60
59
|
# @param swarm_name [String, nil] Swarm name for environment variables
|
|
61
60
|
# @param event [Symbol] Event type for context-aware behavior
|
|
62
61
|
# @return [Result] Result based on exit code (continue or halt)
|
|
63
|
-
def execute(command:, input_json:, timeout:
|
|
62
|
+
def execute(command:, input_json:, timeout: nil, agent_name: nil, swarm_name: nil, event: nil)
|
|
63
|
+
timeout ||= SwarmSDK.config.hook_shell_timeout
|
|
64
|
+
|
|
64
65
|
# Build environment variables
|
|
65
66
|
env = build_environment(agent_name: agent_name, swarm_name: swarm_name)
|
|
66
67
|
|