swarm_sdk 2.3.0 → 2.4.0

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.
@@ -127,10 +127,10 @@ module SwarmSDK
127
127
  forbidden = tool_configs.map { |tc| tc[:name].to_sym }.select { |name| FILESYSTEM_TOOLS.include?(name) }
128
128
  unless forbidden.empty?
129
129
  raise ConfigurationError,
130
- "Filesystem tools are globally disabled (SwarmSDK.settings.allow_filesystem_tools = false) " \
130
+ "Filesystem tools are globally disabled (SwarmSDK.config.allow_filesystem_tools = false) " \
131
131
  "but agent '#{agent_name}' attempts to use: #{forbidden.join(", ")}.\n\n" \
132
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."
133
+ "To use filesystem tools, set SwarmSDK.config.allow_filesystem_tools = true before loading the swarm."
134
134
  end
135
135
  end
136
136
 
@@ -67,8 +67,7 @@ module SwarmSDK
67
67
  include LoggingCallbacks
68
68
  include HookTriggers
69
69
 
70
- # Backward compatibility aliases - use Defaults module for new code
71
- DEFAULT_MCP_LOG_LEVEL = Defaults::Logging::MCP_LOG_LEVEL
70
+ # NOTE: MCP log level now accessed via SwarmSDK.config.mcp_log_level
72
71
 
73
72
  # Default tools available to all agents
74
73
  DEFAULT_TOOLS = ToolConfigurator::DEFAULT_TOOLS
@@ -98,7 +97,7 @@ module SwarmSDK
98
97
  attr_writer :first_message_sent
99
98
 
100
99
  # Class-level MCP log level configuration
101
- @mcp_log_level = DEFAULT_MCP_LOG_LEVEL
100
+ @mcp_log_level = nil
102
101
  @mcp_logging_configured = false
103
102
 
104
103
  class << self
@@ -111,8 +110,8 @@ module SwarmSDK
111
110
  #
112
111
  # @param level [Integer] Log level (Logger::DEBUG, Logger::INFO, Logger::WARN, Logger::ERROR, Logger::FATAL)
113
112
  # @return [void]
114
- def configure_mcp_logging(level = DEFAULT_MCP_LOG_LEVEL)
115
- @mcp_log_level = level
113
+ def configure_mcp_logging(level = nil)
114
+ @mcp_log_level = level || SwarmSDK.config.mcp_log_level
116
115
  apply_mcp_logging_configuration
117
116
  end
118
117
 
@@ -123,7 +122,7 @@ module SwarmSDK
123
122
  return if @mcp_logging_configured
124
123
 
125
124
  RubyLLM::MCP.configure do |config|
126
- config.log_level = @mcp_log_level
125
+ config.log_level = @mcp_log_level || SwarmSDK.config.mcp_log_level
127
126
  end
128
127
 
129
128
  @mcp_logging_configured = true
@@ -135,17 +134,17 @@ module SwarmSDK
135
134
  # @param name [String] Human-readable swarm name
136
135
  # @param swarm_id [String, nil] Optional swarm ID (auto-generated if not provided)
137
136
  # @param parent_swarm_id [String, nil] Optional parent swarm ID (nil for root swarms)
138
- # @param global_concurrency [Integer] Max concurrent LLM calls across entire swarm
139
- # @param default_local_concurrency [Integer] Default max concurrent tool calls per agent
137
+ # @param global_concurrency [Integer, nil] Max concurrent LLM calls across entire swarm (nil uses config default)
138
+ # @param default_local_concurrency [Integer, nil] Default max concurrent tool calls per agent (nil uses config default)
140
139
  # @param scratchpad [Tools::Stores::Scratchpad, nil] Optional scratchpad instance (for testing/internal use)
141
140
  # @param scratchpad_mode [Symbol, String] Scratchpad mode (:enabled or :disabled). :per_node not allowed for non-node swarms.
142
141
  # @param allow_filesystem_tools [Boolean, nil] Whether to allow filesystem tools (nil uses global setting)
143
- def initialize(name:, swarm_id: nil, parent_swarm_id: nil, global_concurrency: Defaults::Concurrency::GLOBAL_LIMIT, default_local_concurrency: Defaults::Concurrency::LOCAL_LIMIT, scratchpad: nil, scratchpad_mode: :enabled, allow_filesystem_tools: nil)
142
+ def initialize(name:, swarm_id: nil, parent_swarm_id: nil, global_concurrency: nil, default_local_concurrency: nil, scratchpad: nil, scratchpad_mode: :enabled, allow_filesystem_tools: nil)
144
143
  @name = name
145
144
  @swarm_id = swarm_id || generate_swarm_id(name)
146
145
  @parent_swarm_id = parent_swarm_id
147
- @global_concurrency = global_concurrency
148
- @default_local_concurrency = default_local_concurrency
146
+ @global_concurrency = global_concurrency || SwarmSDK.config.global_concurrency_limit
147
+ @default_local_concurrency = default_local_concurrency || SwarmSDK.config.local_concurrency_limit
149
148
 
150
149
  # Handle scratchpad_mode parameter
151
150
  # For Swarm: :enabled or :disabled (not :per_node - that's for nodes)
@@ -153,9 +152,9 @@ module SwarmSDK
153
152
 
154
153
  # Resolve allow_filesystem_tools with priority:
155
154
  # 1. Explicit parameter (if not nil)
156
- # 2. Global settings
155
+ # 2. Global config
157
156
  @allow_filesystem_tools = if allow_filesystem_tools.nil?
158
- SwarmSDK.settings.allow_filesystem_tools
157
+ SwarmSDK.config.allow_filesystem_tools
159
158
  else
160
159
  allow_filesystem_tools
161
160
  end
@@ -85,10 +85,7 @@ module SwarmSDK
85
85
  desc: "Optional timeout in milliseconds (max 600000)",
86
86
  required: false
87
87
 
88
- # Backward compatibility aliases - use Defaults module for new code
89
- DEFAULT_TIMEOUT_MS = Defaults::Timeouts::BASH_COMMAND_MS
90
- MAX_TIMEOUT_MS = Defaults::Timeouts::BASH_COMMAND_MAX_MS
91
- MAX_OUTPUT_LENGTH = Defaults::Limits::OUTPUT_CHARACTERS
88
+ # NOTE: Timeout and output limits now accessed via SwarmSDK.config
92
89
 
93
90
  # Commands that are ALWAYS blocked for safety reasons
94
91
  # These cannot be overridden by permissions configuration
@@ -107,8 +104,8 @@ module SwarmSDK
107
104
  end
108
105
 
109
106
  # Validate and set timeout
110
- timeout_ms = timeout || DEFAULT_TIMEOUT_MS
111
- timeout_ms = [timeout_ms, MAX_TIMEOUT_MS].min
107
+ timeout_ms = timeout || SwarmSDK.config.bash_command_timeout
108
+ timeout_ms = [timeout_ms, SwarmSDK.config.bash_command_max_timeout].min
112
109
  timeout_seconds = timeout_ms / 1000.0
113
110
 
114
111
  # Execute command with timeout
@@ -149,9 +146,10 @@ module SwarmSDK
149
146
  output = format_command_output(command, description, stdout, stderr, exit_status)
150
147
 
151
148
  # Truncate if too long
152
- if output.length > MAX_OUTPUT_LENGTH
153
- truncated = output[0...MAX_OUTPUT_LENGTH]
154
- truncated += "\n\n<system-reminder>Output truncated at #{MAX_OUTPUT_LENGTH} characters. The full output was #{output.length} characters.</system-reminder>"
149
+ max_output = SwarmSDK.config.output_character_limit
150
+ if output.length > max_output
151
+ truncated = output[0...max_output]
152
+ truncated += "\n\n<system-reminder>Output truncated at #{max_output} characters. The full output was #{output.length} characters.</system-reminder>"
155
153
  output = truncated
156
154
  end
157
155
 
@@ -50,8 +50,7 @@ module SwarmSDK
50
50
  desc: "The directory to search in. If not specified, the current working directory will be used. IMPORTANT: Omit this field to use the default directory. DO NOT enter \"undefined\" or \"null\" - simply omit it for the default behavior. Must be a valid directory path if provided.",
51
51
  required: false
52
52
 
53
- # Backward compatibility alias - use Defaults module for new code
54
- MAX_RESULTS = Defaults::Limits::GLOB_RESULTS
53
+ # NOTE: Result limit now accessed via SwarmSDK.config.glob_result_limit
55
54
 
56
55
  def execute(pattern:, path: nil)
57
56
  # Validate inputs
@@ -108,8 +107,9 @@ module SwarmSDK
108
107
  matches.sort_by! { |f| -File.mtime(f).to_i }
109
108
 
110
109
  # Limit results
111
- if matches.count > MAX_RESULTS
112
- matches = matches.take(MAX_RESULTS)
110
+ max_results = SwarmSDK.config.glob_result_limit
111
+ if matches.count > max_results
112
+ matches = matches.take(max_results)
113
113
  truncated = true
114
114
  else
115
115
  truncated = false
@@ -123,7 +123,7 @@ module SwarmSDK
123
123
  output += <<~REMINDER
124
124
 
125
125
  <system-reminder>
126
- Results limited to first #{MAX_RESULTS} matches (sorted by most recently modified).
126
+ Results limited to first #{max_results} matches (sorted by most recently modified).
127
127
  Consider using a more specific pattern to narrow your search.
128
128
  </system-reminder>
129
129
  REMINDER
@@ -10,9 +10,7 @@ module SwarmSDK
10
10
  class Read < RubyLLM::Tool
11
11
  include PathResolver
12
12
 
13
- # Backward compatibility aliases - use Defaults module for new code
14
- MAX_LINE_LENGTH = Defaults::Limits::LINE_CHARACTERS
15
- DEFAULT_LIMIT = Defaults::Limits::READ_LINES
13
+ # NOTE: Line length and limit now accessed via SwarmSDK.config
16
14
 
17
15
  # List of available document converters
18
16
  CONVERTERS = [
@@ -153,18 +151,20 @@ module SwarmSDK
153
151
  lines = lines.drop(start_line)
154
152
 
155
153
  # Apply limit if specified, otherwise use default
156
- effective_limit = limit || DEFAULT_LIMIT
154
+ default_limit = SwarmSDK.config.read_line_limit
155
+ effective_limit = limit || default_limit
157
156
  lines = lines.take(effective_limit)
158
- truncated = limit.nil? && total_lines > DEFAULT_LIMIT
157
+ truncated = limit.nil? && total_lines > default_limit
159
158
 
160
159
  # Format with line numbers (cat -n style)
160
+ max_line_length = SwarmSDK.config.line_character_limit
161
161
  output_lines = lines.each_with_index.map do |line, idx|
162
162
  line_number = start_line + idx + 1
163
163
  display_line = line.chomp
164
164
 
165
165
  # Truncate long lines
166
- if display_line.length > MAX_LINE_LENGTH
167
- display_line = display_line[0...MAX_LINE_LENGTH]
166
+ if display_line.length > max_line_length
167
+ display_line = display_line[0...max_line_length]
168
168
  display_line += "... (line truncated)"
169
169
  end
170
170
 
@@ -203,7 +203,7 @@ module SwarmSDK
203
203
 
204
204
  if truncated
205
205
  reminders << ""
206
- reminders << "Note: This file has #{total_lines} lines but only the first #{DEFAULT_LIMIT} lines are shown. Use the offset and limit parameters to read additional sections if needed."
206
+ reminders << "Note: This file has #{total_lines} lines but only the first #{SwarmSDK.config.read_line_limit} lines are shown. Use the offset and limit parameters to read additional sections if needed."
207
207
  end
208
208
 
209
209
  reminders << "</system-reminder>"
@@ -21,7 +21,7 @@ module SwarmSDK
21
21
  super() # Initialize parent Storage class
22
22
  @entries = {}
23
23
  @total_size = 0
24
- @total_size_limit = total_size_limit || Defaults::Storage::TOTAL_SIZE_BYTES
24
+ @total_size_limit = total_size_limit || SwarmSDK.config.scratchpad_total_size_limit
25
25
  @mutex = Mutex.new
26
26
  end
27
27
 
@@ -41,8 +41,9 @@ module SwarmSDK
41
41
  content_size = content.bytesize
42
42
 
43
43
  # Check entry size limit
44
- if content_size > Defaults::Storage::ENTRY_SIZE_BYTES
45
- raise ArgumentError, "Content exceeds maximum size (#{format_bytes(Defaults::Storage::ENTRY_SIZE_BYTES)}). " \
44
+ entry_size_limit = SwarmSDK.config.scratchpad_entry_size_limit
45
+ if content_size > entry_size_limit
46
+ raise ArgumentError, "Content exceeds maximum size (#{format_bytes(entry_size_limit)}). " \
46
47
  "Current: #{format_bytes(content_size)}"
47
48
  end
48
49
 
@@ -11,7 +11,6 @@ module SwarmSDK
11
11
  super()
12
12
  @cache = {}
13
13
  @cache_ttl = 900 # 15 minutes in seconds
14
- @llm_enabled = SwarmSDK.settings.webfetch_llm_enabled?
15
14
  end
16
15
 
17
16
  def name
@@ -51,17 +50,18 @@ module SwarmSDK
51
50
  desc: "The prompt to run on the fetched content. Required when SwarmSDK is configured with webfetch_provider and webfetch_model. Optional otherwise (ignored if LLM processing not configured).",
52
51
  required: false
53
52
 
54
- # Backward compatibility aliases - use Defaults module for new code
55
- MAX_CONTENT_LENGTH = Defaults::Limits::WEB_FETCH_CHARACTERS
53
+ # NOTE: Content length and timeout now accessed via SwarmSDK.config
56
54
  USER_AGENT = "SwarmSDK WebFetch Tool (https://github.com/parruda/claude-swarm)"
57
- TIMEOUT = Defaults::Timeouts::WEB_FETCH_SECONDS
58
55
 
59
56
  def execute(url:, prompt: nil)
60
57
  # Validate inputs
61
58
  return validation_error("url is required") if url.nil? || url.empty?
62
59
 
60
+ # Check if LLM processing is enabled (lazy check)
61
+ llm_enabled = SwarmSDK.config.webfetch_llm_enabled?
62
+
63
63
  # Validate prompt when LLM processing is enabled
64
- if @llm_enabled && (prompt.nil? || prompt.empty?)
64
+ if llm_enabled && (prompt.nil? || prompt.empty?)
65
65
  return validation_error("prompt is required when LLM processing is configured")
66
66
  end
67
67
 
@@ -70,7 +70,7 @@ module SwarmSDK
70
70
  return validation_error("Invalid URL format: #{url}") unless normalized_url
71
71
 
72
72
  # Check cache first (cache key includes prompt if LLM is enabled)
73
- cache_key = @llm_enabled ? "#{normalized_url}:#{prompt}" : normalized_url
73
+ cache_key = llm_enabled ? "#{normalized_url}:#{prompt}" : normalized_url
74
74
  cached = get_from_cache(cache_key)
75
75
  return cached if cached
76
76
 
@@ -87,13 +87,14 @@ module SwarmSDK
87
87
  markdown_content = html_to_markdown(fetch_result[:body])
88
88
 
89
89
  # Truncate if too long
90
- if markdown_content.length > MAX_CONTENT_LENGTH
91
- markdown_content = markdown_content[0...MAX_CONTENT_LENGTH]
90
+ max_content = SwarmSDK.config.web_fetch_character_limit
91
+ if markdown_content.length > max_content
92
+ markdown_content = markdown_content[0...max_content]
92
93
  markdown_content += "\n\n[Content truncated due to length]"
93
94
  end
94
95
 
95
96
  # Process with AI model if LLM is enabled, otherwise return markdown
96
- result = if @llm_enabled
97
+ result = if llm_enabled
97
98
  process_with_llm(markdown_content, prompt, normalized_url)
98
99
  else
99
100
  markdown_content
@@ -143,12 +144,13 @@ module SwarmSDK
143
144
  require "faraday"
144
145
  require "faraday/follow_redirects"
145
146
 
147
+ timeout = SwarmSDK.config.web_fetch_timeout
146
148
  response = Faraday.new(url: url) do |conn|
147
149
  conn.request(:url_encoded)
148
150
  conn.response(:follow_redirects, limit: 5)
149
151
  conn.adapter(Faraday.default_adapter)
150
- conn.options.timeout = TIMEOUT
151
- conn.options.open_timeout = TIMEOUT
152
+ conn.options.timeout = timeout
153
+ conn.options.open_timeout = timeout
152
154
  end.get do |req|
153
155
  req.headers["User-Agent"] = USER_AGENT
154
156
  req.headers["Accept"] = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
@@ -167,7 +169,7 @@ module SwarmSDK
167
169
  redirect_url: redirect_url,
168
170
  }
169
171
  rescue Faraday::TimeoutError
170
- error("Request timed out after #{TIMEOUT} seconds")
172
+ error("Request timed out after #{SwarmSDK.config.web_fetch_timeout} seconds")
171
173
  rescue Faraday::ConnectionFailed => e
172
174
  error("Connection failed: #{e.message}")
173
175
  rescue StandardError => e
@@ -194,17 +196,17 @@ module SwarmSDK
194
196
  Please respond to the user's request based on the content above.
195
197
  PROMPT
196
198
 
197
- # Get settings
198
- config = SwarmSDK.settings
199
+ # Get config
200
+ sdk_config = SwarmSDK.config
199
201
 
200
202
  # Build chat with configured provider and model
201
203
  chat_params = {
202
- model: config.webfetch_model,
203
- provider: config.webfetch_provider.to_sym,
204
+ model: sdk_config.webfetch_model,
205
+ provider: sdk_config.webfetch_provider.to_sym,
204
206
  }
205
- chat_params[:base_url] = config.webfetch_base_url if config.webfetch_base_url
207
+ chat_params[:base_url] = sdk_config.webfetch_base_url if sdk_config.webfetch_base_url
206
208
 
207
- chat = RubyLLM.chat(**chat_params).with_params(max_tokens: config.webfetch_max_tokens)
209
+ chat = RubyLLM.chat(**chat_params).with_params(max_tokens: sdk_config.webfetch_max_tokens)
208
210
 
209
211
  response = chat.ask(full_prompt)
210
212
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SwarmSDK
4
- VERSION = "2.3.0"
4
+ VERSION = "2.4.0"
5
5
  end
@@ -214,7 +214,8 @@ module SwarmSDK
214
214
  #
215
215
  # @example
216
216
  # input_command("scripts/validate.sh", timeout: 30)
217
- def input_command(command, timeout: TransformerExecutor::DEFAULT_TIMEOUT)
217
+ def input_command(command, timeout: nil)
218
+ timeout ||= SwarmSDK.config.transformer_command_timeout
218
219
  @input_transformer_command = { command: command, timeout: timeout }
219
220
  end
220
221
 
@@ -288,7 +289,8 @@ module SwarmSDK
288
289
  #
289
290
  # @example
290
291
  # output_command("scripts/format.sh", timeout: 30)
291
- def output_command(command, timeout: TransformerExecutor::DEFAULT_TIMEOUT)
292
+ def output_command(command, timeout: nil)
293
+ timeout ||= SwarmSDK.config.transformer_command_timeout
292
294
  @output_transformer_command = { command: command, timeout: timeout }
293
295
  end
294
296
 
@@ -90,8 +90,7 @@ module SwarmSDK
90
90
  # echo "$CONTENT"
91
91
  # exit 0
92
92
  class TransformerExecutor
93
- # Backward compatibility alias - use Defaults module for new code
94
- DEFAULT_TIMEOUT = Defaults::Timeouts::TRANSFORMER_COMMAND_SECONDS
93
+ # NOTE: Timeout now accessed via SwarmSDK.config.transformer_command_timeout
95
94
 
96
95
  # Result object for transformer execution
97
96
  TransformerResult = Struct.new(:success, :content, :skip_execution, :halt, :error_message, keyword_init: true) do
@@ -114,7 +113,9 @@ module SwarmSDK
114
113
  # @param fallback_content [String] Content to use if skip (exit 1)
115
114
  # @param timeout [Integer] Timeout in seconds (default: 60)
116
115
  # @return [TransformerResult] Result with transformed content or skip/halt flags
117
- def execute(command:, context:, event:, node_name:, fallback_content:, timeout: DEFAULT_TIMEOUT)
116
+ def execute(command:, context:, event:, node_name:, fallback_content:, timeout: nil)
117
+ timeout ||= SwarmSDK.config.transformer_command_timeout
118
+
118
119
  # Build JSON input for transformer
119
120
  input_json = build_transformer_input(context, event, node_name)
120
121
 
data/lib/swarm_sdk.rb CHANGED
@@ -63,8 +63,37 @@ module SwarmSDK
63
63
  class StateError < Error; end
64
64
 
65
65
  class << self
66
- # Settings for SwarmSDK (global configuration)
67
- attr_accessor :settings
66
+ # Get the global configuration instance
67
+ #
68
+ # @return [Config] The singleton Config instance
69
+ def config
70
+ Config.instance
71
+ end
72
+
73
+ # Configure SwarmSDK global settings
74
+ #
75
+ # @yield [Config] The configuration instance
76
+ # @return [Config] The configuration instance
77
+ #
78
+ # @example
79
+ # SwarmSDK.configure do |config|
80
+ # config.openai_api_key = "sk-..."
81
+ # config.default_model = "claude-sonnet-4"
82
+ # end
83
+ def configure
84
+ yield(config) if block_given?
85
+ config
86
+ end
87
+
88
+ # Reset configuration to defaults
89
+ #
90
+ # Clears all configuration including explicit values and cached ENV values.
91
+ # Use in tests to ensure clean state.
92
+ #
93
+ # @return [void]
94
+ def reset_config!
95
+ Config.reset!
96
+ end
68
97
 
69
98
  # Main entry point for DSL - builds simple multi-agent swarms
70
99
  #
@@ -248,21 +277,6 @@ module SwarmSDK
248
277
  swarm
249
278
  end
250
279
 
251
- # Configure SwarmSDK global settings
252
- def configure
253
- self.settings ||= Settings.new
254
- yield(settings)
255
- end
256
-
257
- # Reset settings to defaults
258
- def reset_settings!
259
- self.settings = Settings.new
260
- end
261
-
262
- # Alias for backward compatibility
263
- alias_method :configuration, :settings
264
- alias_method :reset_configuration!, :reset_settings!
265
-
266
280
  private
267
281
 
268
282
  # Check if hooks are configured in the configuration
@@ -437,88 +451,4 @@ module SwarmSDK
437
451
  error_hash.compact
438
452
  end
439
453
  end
440
-
441
- # Settings class for SwarmSDK global settings (not to be confused with Configuration for YAML loading)
442
- class Settings
443
- # WebFetch tool LLM processing configuration
444
- attr_accessor :webfetch_provider, :webfetch_model, :webfetch_base_url, :webfetch_max_tokens
445
-
446
- # Filesystem tools control
447
- attr_accessor :allow_filesystem_tools
448
-
449
- def initialize
450
- @webfetch_provider = nil
451
- @webfetch_model = nil
452
- @webfetch_base_url = nil
453
- @webfetch_max_tokens = 4096
454
- @allow_filesystem_tools = parse_env_bool("SWARM_SDK_ALLOW_FILESYSTEM_TOOLS", default: true)
455
- end
456
-
457
- # Check if WebFetch LLM processing is enabled
458
- def webfetch_llm_enabled?
459
- !@webfetch_provider.nil? && !@webfetch_model.nil?
460
- end
461
-
462
- private
463
-
464
- def parse_env_bool(key, default:)
465
- return default unless ENV.key?(key)
466
-
467
- value = ENV[key].to_s.downcase
468
- return true if ["true", "yes", "1", "on", "enabled"].include?(value)
469
- return false if ["false", "no", "0", "off", "disabled"].include?(value)
470
-
471
- default
472
- end
473
- end
474
-
475
- # Initialize default settings
476
- self.settings = Settings.new
477
- end
478
-
479
- # Automatically configure RubyLLM from environment variables
480
- # This makes SwarmSDK "just work" when users set standard ENV variables
481
- RubyLLM.configure do |config|
482
- # Only set if config not already set (||= handles nil ENV values gracefully)
483
-
484
- # OpenAI
485
- config.openai_api_key ||= ENV["OPENAI_API_KEY"]
486
- config.openai_api_base ||= ENV["OPENAI_API_BASE"]
487
- config.openai_organization_id ||= ENV["OPENAI_ORG_ID"]
488
- config.openai_project_id ||= ENV["OPENAI_PROJECT_ID"]
489
-
490
- # Anthropic
491
- config.anthropic_api_key ||= ENV["ANTHROPIC_API_KEY"]
492
-
493
- # Google Gemini
494
- config.gemini_api_key ||= ENV["GEMINI_API_KEY"]
495
-
496
- # Google Vertex AI (note: vertexai, not vertex_ai)
497
- config.vertexai_project_id ||= ENV["GOOGLE_CLOUD_PROJECT"] || ENV["VERTEXAI_PROJECT_ID"]
498
- config.vertexai_location ||= ENV["GOOGLE_CLOUD_LOCATION"] || ENV["VERTEXAI_LOCATION"]
499
-
500
- # DeepSeek
501
- config.deepseek_api_key ||= ENV["DEEPSEEK_API_KEY"]
502
-
503
- # Mistral
504
- config.mistral_api_key ||= ENV["MISTRAL_API_KEY"]
505
-
506
- # Perplexity
507
- config.perplexity_api_key ||= ENV["PERPLEXITY_API_KEY"]
508
-
509
- # OpenRouter
510
- config.openrouter_api_key ||= ENV["OPENROUTER_API_KEY"]
511
-
512
- # AWS Bedrock
513
- config.bedrock_api_key ||= ENV["AWS_ACCESS_KEY_ID"]
514
- config.bedrock_secret_key ||= ENV["AWS_SECRET_ACCESS_KEY"]
515
- config.bedrock_region ||= ENV["AWS_REGION"]
516
- config.bedrock_session_token ||= ENV["AWS_SESSION_TOKEN"]
517
-
518
- # Ollama (local)
519
- config.ollama_api_base ||= ENV["OLLAMA_API_BASE"]
520
-
521
- # GPUStack (local)
522
- config.gpustack_api_base ||= ENV["GPUSTACK_API_BASE"]
523
- config.gpustack_api_key ||= ENV["GPUSTACK_API_KEY"]
524
454
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: swarm_sdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.0
4
+ version: 2.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paulo Arruda
@@ -71,14 +71,14 @@ dependencies:
71
71
  requirements:
72
72
  - - "~>"
73
73
  - !ruby/object:Gem::Version
74
- version: 1.9.2
74
+ version: 1.9.4
75
75
  type: :runtime
76
76
  prerelease: false
77
77
  version_requirements: !ruby/object:Gem::Requirement
78
78
  requirements:
79
79
  - - "~>"
80
80
  - !ruby/object:Gem::Version
81
- version: 1.9.2
81
+ version: 1.9.4
82
82
  - !ruby/object:Gem::Dependency
83
83
  name: zeitwerk
84
84
  requirement: !ruby/object:Gem::Requirement
@@ -129,6 +129,7 @@ files:
129
129
  - lib/swarm_sdk/concerns/cleanupable.rb
130
130
  - lib/swarm_sdk/concerns/snapshotable.rb
131
131
  - lib/swarm_sdk/concerns/validatable.rb
132
+ - lib/swarm_sdk/config.rb
132
133
  - lib/swarm_sdk/configuration.rb
133
134
  - lib/swarm_sdk/configuration/parser.rb
134
135
  - lib/swarm_sdk/configuration/translator.rb