swarm_sdk 2.2.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.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/lib/swarm_sdk/agent/builder.rb +58 -0
  3. data/lib/swarm_sdk/agent/chat.rb +527 -1059
  4. data/lib/swarm_sdk/agent/{chat → chat_helpers}/context_tracker.rb +9 -88
  5. data/lib/swarm_sdk/agent/chat_helpers/event_emitter.rb +204 -0
  6. data/lib/swarm_sdk/agent/{chat → chat_helpers}/hook_integration.rb +111 -44
  7. data/lib/swarm_sdk/agent/chat_helpers/instrumentation.rb +78 -0
  8. data/lib/swarm_sdk/agent/chat_helpers/llm_configuration.rb +262 -0
  9. data/lib/swarm_sdk/agent/{chat → chat_helpers}/logging_helpers.rb +1 -1
  10. data/lib/swarm_sdk/agent/chat_helpers/serialization.rb +83 -0
  11. data/lib/swarm_sdk/agent/{chat → chat_helpers}/system_reminder_injector.rb +11 -13
  12. data/lib/swarm_sdk/agent/chat_helpers/system_reminders.rb +79 -0
  13. data/lib/swarm_sdk/agent/chat_helpers/token_tracking.rb +98 -0
  14. data/lib/swarm_sdk/agent/context.rb +1 -2
  15. data/lib/swarm_sdk/agent/definition.rb +66 -154
  16. data/lib/swarm_sdk/agent/llm_instrumentation_middleware.rb +4 -2
  17. data/lib/swarm_sdk/agent/system_prompt_builder.rb +161 -0
  18. data/lib/swarm_sdk/builders/base_builder.rb +409 -0
  19. data/lib/swarm_sdk/concerns/cleanupable.rb +39 -0
  20. data/lib/swarm_sdk/concerns/snapshotable.rb +67 -0
  21. data/lib/swarm_sdk/concerns/validatable.rb +55 -0
  22. data/lib/swarm_sdk/config.rb +301 -0
  23. data/lib/swarm_sdk/configuration/parser.rb +353 -0
  24. data/lib/swarm_sdk/configuration/translator.rb +255 -0
  25. data/lib/swarm_sdk/configuration.rb +65 -543
  26. data/lib/swarm_sdk/context_compactor/token_counter.rb +2 -6
  27. data/lib/swarm_sdk/context_compactor.rb +6 -11
  28. data/lib/swarm_sdk/context_management/builder.rb +128 -0
  29. data/lib/swarm_sdk/context_management/context.rb +328 -0
  30. data/lib/swarm_sdk/defaults.rb +196 -0
  31. data/lib/swarm_sdk/events_to_messages.rb +18 -0
  32. data/lib/swarm_sdk/hooks/adapter.rb +3 -3
  33. data/lib/swarm_sdk/hooks/shell_executor.rb +4 -2
  34. data/lib/swarm_sdk/log_collector.rb +179 -29
  35. data/lib/swarm_sdk/log_stream.rb +29 -0
  36. data/lib/swarm_sdk/models.json +4333 -1
  37. data/lib/swarm_sdk/node_context.rb +1 -1
  38. data/lib/swarm_sdk/observer/builder.rb +81 -0
  39. data/lib/swarm_sdk/observer/config.rb +45 -0
  40. data/lib/swarm_sdk/observer/manager.rb +236 -0
  41. data/lib/swarm_sdk/patterns/agent_observer.rb +160 -0
  42. data/lib/swarm_sdk/plugin.rb +93 -3
  43. data/lib/swarm_sdk/snapshot.rb +6 -6
  44. data/lib/swarm_sdk/snapshot_from_events.rb +13 -2
  45. data/lib/swarm_sdk/state_restorer.rb +136 -151
  46. data/lib/swarm_sdk/state_snapshot.rb +65 -100
  47. data/lib/swarm_sdk/swarm/agent_initializer.rb +180 -136
  48. data/lib/swarm_sdk/swarm/builder.rb +44 -578
  49. data/lib/swarm_sdk/swarm/executor.rb +213 -0
  50. data/lib/swarm_sdk/swarm/hook_triggers.rb +150 -0
  51. data/lib/swarm_sdk/swarm/logging_callbacks.rb +340 -0
  52. data/lib/swarm_sdk/swarm/mcp_configurator.rb +7 -4
  53. data/lib/swarm_sdk/swarm/tool_configurator.rb +44 -140
  54. data/lib/swarm_sdk/swarm.rb +146 -689
  55. data/lib/swarm_sdk/tools/bash.rb +14 -8
  56. data/lib/swarm_sdk/tools/delegate.rb +61 -43
  57. data/lib/swarm_sdk/tools/edit.rb +8 -13
  58. data/lib/swarm_sdk/tools/glob.rb +12 -4
  59. data/lib/swarm_sdk/tools/grep.rb +7 -0
  60. data/lib/swarm_sdk/tools/multi_edit.rb +15 -11
  61. data/lib/swarm_sdk/tools/path_resolver.rb +51 -2
  62. data/lib/swarm_sdk/tools/read.rb +16 -18
  63. data/lib/swarm_sdk/tools/registry.rb +122 -10
  64. data/lib/swarm_sdk/tools/stores/scratchpad_storage.rb +9 -5
  65. data/lib/swarm_sdk/tools/stores/storage.rb +0 -6
  66. data/lib/swarm_sdk/tools/todo_write.rb +7 -0
  67. data/lib/swarm_sdk/tools/web_fetch.rb +20 -17
  68. data/lib/swarm_sdk/tools/write.rb +8 -13
  69. data/lib/swarm_sdk/version.rb +1 -1
  70. data/lib/swarm_sdk/{node → workflow}/agent_config.rb +1 -1
  71. data/lib/swarm_sdk/workflow/builder.rb +143 -0
  72. data/lib/swarm_sdk/workflow/executor.rb +497 -0
  73. data/lib/swarm_sdk/{node/builder.rb → workflow/node_builder.rb} +7 -5
  74. data/lib/swarm_sdk/{node → workflow}/transformer_executor.rb +5 -3
  75. data/lib/swarm_sdk/{node_orchestrator.rb → workflow.rb} +152 -456
  76. data/lib/swarm_sdk.rb +64 -104
  77. metadata +68 -15
  78. data/lib/swarm_sdk/providers/openai_with_responses.rb +0 -589
data/lib/swarm_sdk.rb CHANGED
@@ -17,6 +17,27 @@ require "async/semaphore"
17
17
  require "ruby_llm"
18
18
  require "ruby_llm/mcp"
19
19
 
20
+ # Patch ruby_llm-mcp's Zeitwerk loader to ignore railtie.rb when Rails is not present
21
+ # This prevents NameError when eager loading outside of Rails applications
22
+ # Can be removed once https://github.com/parruda/ruby_llm-mcp/issues/XXX is fixed
23
+ unless defined?(Rails)
24
+ require "zeitwerk"
25
+ mcp_loader = nil
26
+ Zeitwerk::Registry.loaders.each { |l| mcp_loader = l if l.tag == "RubyLLM-mcp" }
27
+ if mcp_loader
28
+ mcp_gem_dir = Gem.loaded_specs["ruby_llm-mcp"]&.gem_dir
29
+ if mcp_gem_dir
30
+ railtie_path = File.join(mcp_gem_dir, "lib", "ruby_llm", "mcp", "railtie.rb")
31
+ mcp_loader.ignore(railtie_path)
32
+ end
33
+ end
34
+ end
35
+
36
+ # Configure Faraday to use async-http adapter by default
37
+ # This ensures HTTP requests are fiber-aware and don't block the Async scheduler
38
+ # when SwarmSDK executes LLM requests within Async/Sync blocks
39
+ require "async/http/faraday/default"
40
+
20
41
  require_relative "swarm_sdk/version"
21
42
 
22
43
  require "zeitwerk"
@@ -42,14 +63,52 @@ module SwarmSDK
42
63
  class StateError < Error; end
43
64
 
44
65
  class << self
45
- # Settings for SwarmSDK (global configuration)
46
- 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
47
87
 
48
- # Main entry point for DSL
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
97
+
98
+ # Main entry point for DSL - builds simple multi-agent swarms
99
+ #
100
+ # @return [Swarm] Always returns a Swarm instance
49
101
  def build(allow_filesystem_tools: nil, &block)
50
102
  Swarm::Builder.build(allow_filesystem_tools: allow_filesystem_tools, &block)
51
103
  end
52
104
 
105
+ # Entry point for building multi-stage workflows
106
+ #
107
+ # @return [Workflow] Always returns a Workflow instance
108
+ def workflow(allow_filesystem_tools: nil, &block)
109
+ Workflow::Builder.build(allow_filesystem_tools: allow_filesystem_tools, &block)
110
+ end
111
+
53
112
  # Validate YAML configuration without creating a swarm
54
113
  #
55
114
  # Performs comprehensive validation of YAML configuration including:
@@ -149,7 +208,7 @@ module SwarmSDK
149
208
  #
150
209
  # @param yaml_content [String] YAML configuration content
151
210
  # @param base_dir [String, Pathname] Base directory for resolving agent file paths (default: Dir.pwd)
152
- # @return [Swarm, NodeOrchestrator] Configured swarm or orchestrator instance
211
+ # @return [Swarm, Workflow] Configured swarm or workflow instance
153
212
  # @raise [ConfigurationError] If YAML is invalid or configuration is incorrect
154
213
  #
155
214
  # @example Load from YAML string
@@ -194,7 +253,7 @@ module SwarmSDK
194
253
  # loading swarms from configuration files.
195
254
  #
196
255
  # @param path [String, Pathname] Path to YAML configuration file
197
- # @return [Swarm, NodeOrchestrator] Configured swarm or orchestrator instance
256
+ # @return [Swarm, Workflow] Configured swarm or workflow instance
198
257
  # @raise [ConfigurationError] If file not found or configuration invalid
199
258
  #
200
259
  # @example
@@ -218,21 +277,6 @@ module SwarmSDK
218
277
  swarm
219
278
  end
220
279
 
221
- # Configure SwarmSDK global settings
222
- def configure
223
- self.settings ||= Settings.new
224
- yield(settings)
225
- end
226
-
227
- # Reset settings to defaults
228
- def reset_settings!
229
- self.settings = Settings.new
230
- end
231
-
232
- # Alias for backward compatibility
233
- alias_method :configuration, :settings
234
- alias_method :reset_configuration!, :reset_settings!
235
-
236
280
  private
237
281
 
238
282
  # Check if hooks are configured in the configuration
@@ -407,88 +451,4 @@ module SwarmSDK
407
451
  error_hash.compact
408
452
  end
409
453
  end
410
-
411
- # Settings class for SwarmSDK global settings (not to be confused with Configuration for YAML loading)
412
- class Settings
413
- # WebFetch tool LLM processing configuration
414
- attr_accessor :webfetch_provider, :webfetch_model, :webfetch_base_url, :webfetch_max_tokens
415
-
416
- # Filesystem tools control
417
- attr_accessor :allow_filesystem_tools
418
-
419
- def initialize
420
- @webfetch_provider = nil
421
- @webfetch_model = nil
422
- @webfetch_base_url = nil
423
- @webfetch_max_tokens = 4096
424
- @allow_filesystem_tools = parse_env_bool("SWARM_SDK_ALLOW_FILESYSTEM_TOOLS", default: true)
425
- end
426
-
427
- # Check if WebFetch LLM processing is enabled
428
- def webfetch_llm_enabled?
429
- !@webfetch_provider.nil? && !@webfetch_model.nil?
430
- end
431
-
432
- private
433
-
434
- def parse_env_bool(key, default:)
435
- return default unless ENV.key?(key)
436
-
437
- value = ENV[key].to_s.downcase
438
- return true if ["true", "yes", "1", "on", "enabled"].include?(value)
439
- return false if ["false", "no", "0", "off", "disabled"].include?(value)
440
-
441
- default
442
- end
443
- end
444
-
445
- # Initialize default settings
446
- self.settings = Settings.new
447
- end
448
-
449
- # Automatically configure RubyLLM from environment variables
450
- # This makes SwarmSDK "just work" when users set standard ENV variables
451
- RubyLLM.configure do |config|
452
- # Only set if config not already set (||= handles nil ENV values gracefully)
453
-
454
- # OpenAI
455
- config.openai_api_key ||= ENV["OPENAI_API_KEY"]
456
- config.openai_api_base ||= ENV["OPENAI_API_BASE"]
457
- config.openai_organization_id ||= ENV["OPENAI_ORG_ID"]
458
- config.openai_project_id ||= ENV["OPENAI_PROJECT_ID"]
459
-
460
- # Anthropic
461
- config.anthropic_api_key ||= ENV["ANTHROPIC_API_KEY"]
462
-
463
- # Google Gemini
464
- config.gemini_api_key ||= ENV["GEMINI_API_KEY"]
465
-
466
- # Google Vertex AI (note: vertexai, not vertex_ai)
467
- config.vertexai_project_id ||= ENV["GOOGLE_CLOUD_PROJECT"] || ENV["VERTEXAI_PROJECT_ID"]
468
- config.vertexai_location ||= ENV["GOOGLE_CLOUD_LOCATION"] || ENV["VERTEXAI_LOCATION"]
469
-
470
- # DeepSeek
471
- config.deepseek_api_key ||= ENV["DEEPSEEK_API_KEY"]
472
-
473
- # Mistral
474
- config.mistral_api_key ||= ENV["MISTRAL_API_KEY"]
475
-
476
- # Perplexity
477
- config.perplexity_api_key ||= ENV["PERPLEXITY_API_KEY"]
478
-
479
- # OpenRouter
480
- config.openrouter_api_key ||= ENV["OPENROUTER_API_KEY"]
481
-
482
- # AWS Bedrock
483
- config.bedrock_api_key ||= ENV["AWS_ACCESS_KEY_ID"]
484
- config.bedrock_secret_key ||= ENV["AWS_SECRET_ACCESS_KEY"]
485
- config.bedrock_region ||= ENV["AWS_REGION"]
486
- config.bedrock_session_token ||= ENV["AWS_SESSION_TOKEN"]
487
-
488
- # Ollama (local)
489
- config.ollama_api_base ||= ENV["OLLAMA_API_BASE"]
490
-
491
- # GPUStack (local)
492
- config.gpustack_api_base ||= ENV["GPUSTACK_API_BASE"]
493
- config.gpustack_api_key ||= ENV["GPUSTACK_API_KEY"]
494
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.2.0
4
+ version: 2.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paulo Arruda
@@ -24,33 +24,61 @@ dependencies:
24
24
  - !ruby/object:Gem::Version
25
25
  version: '2.0'
26
26
  - !ruby/object:Gem::Dependency
27
- name: ruby_llm
27
+ name: async-http-faraday
28
28
  requirement: !ruby/object:Gem::Requirement
29
29
  requirements:
30
30
  - - "~>"
31
31
  - !ruby/object:Gem::Version
32
- version: '1.9'
32
+ version: '0.22'
33
33
  type: :runtime
34
34
  prerelease: false
35
35
  version_requirements: !ruby/object:Gem::Requirement
36
36
  requirements:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
- version: '1.9'
39
+ version: '0.22'
40
+ - !ruby/object:Gem::Dependency
41
+ name: faraday-follow_redirects
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '0.4'
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '0.4'
40
54
  - !ruby/object:Gem::Dependency
41
55
  name: ruby_llm-mcp
42
56
  requirement: !ruby/object:Gem::Requirement
43
57
  requirements:
44
58
  - - "~>"
45
59
  - !ruby/object:Gem::Version
46
- version: '0.7'
60
+ version: '0.8'
61
+ type: :runtime
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '0.8'
68
+ - !ruby/object:Gem::Dependency
69
+ name: ruby_llm_swarm
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: 1.9.4
47
75
  type: :runtime
48
76
  prerelease: false
49
77
  version_requirements: !ruby/object:Gem::Requirement
50
78
  requirements:
51
79
  - - "~>"
52
80
  - !ruby/object:Gem::Version
53
- version: '0.7'
81
+ version: 1.9.4
54
82
  - !ruby/object:Gem::Dependency
55
83
  name: zeitwerk
56
84
  requirement: !ruby/object:Gem::Requirement
@@ -81,19 +109,36 @@ files:
81
109
  - lib/swarm_sdk/agent/RETRY_LOGIC.md
82
110
  - lib/swarm_sdk/agent/builder.rb
83
111
  - lib/swarm_sdk/agent/chat.rb
84
- - lib/swarm_sdk/agent/chat/context_tracker.rb
85
- - lib/swarm_sdk/agent/chat/hook_integration.rb
86
- - lib/swarm_sdk/agent/chat/logging_helpers.rb
87
- - lib/swarm_sdk/agent/chat/system_reminder_injector.rb
112
+ - lib/swarm_sdk/agent/chat_helpers/context_tracker.rb
113
+ - lib/swarm_sdk/agent/chat_helpers/event_emitter.rb
114
+ - lib/swarm_sdk/agent/chat_helpers/hook_integration.rb
115
+ - lib/swarm_sdk/agent/chat_helpers/instrumentation.rb
116
+ - lib/swarm_sdk/agent/chat_helpers/llm_configuration.rb
117
+ - lib/swarm_sdk/agent/chat_helpers/logging_helpers.rb
118
+ - lib/swarm_sdk/agent/chat_helpers/serialization.rb
119
+ - lib/swarm_sdk/agent/chat_helpers/system_reminder_injector.rb
120
+ - lib/swarm_sdk/agent/chat_helpers/system_reminders.rb
121
+ - lib/swarm_sdk/agent/chat_helpers/token_tracking.rb
88
122
  - lib/swarm_sdk/agent/context.rb
89
123
  - lib/swarm_sdk/agent/context_manager.rb
90
124
  - lib/swarm_sdk/agent/definition.rb
91
125
  - lib/swarm_sdk/agent/llm_instrumentation_middleware.rb
126
+ - lib/swarm_sdk/agent/system_prompt_builder.rb
127
+ - lib/swarm_sdk/builders/base_builder.rb
92
128
  - lib/swarm_sdk/claude_code_agent_adapter.rb
129
+ - lib/swarm_sdk/concerns/cleanupable.rb
130
+ - lib/swarm_sdk/concerns/snapshotable.rb
131
+ - lib/swarm_sdk/concerns/validatable.rb
132
+ - lib/swarm_sdk/config.rb
93
133
  - lib/swarm_sdk/configuration.rb
134
+ - lib/swarm_sdk/configuration/parser.rb
135
+ - lib/swarm_sdk/configuration/translator.rb
94
136
  - lib/swarm_sdk/context_compactor.rb
95
137
  - lib/swarm_sdk/context_compactor/metrics.rb
96
138
  - lib/swarm_sdk/context_compactor/token_counter.rb
139
+ - lib/swarm_sdk/context_management/builder.rb
140
+ - lib/swarm_sdk/context_management/context.rb
141
+ - lib/swarm_sdk/defaults.rb
97
142
  - lib/swarm_sdk/events_to_messages.rb
98
143
  - lib/swarm_sdk/hooks/adapter.rb
99
144
  - lib/swarm_sdk/hooks/context.rb
@@ -111,11 +156,11 @@ files:
111
156
  - lib/swarm_sdk/model_aliases.json
112
157
  - lib/swarm_sdk/models.json
113
158
  - lib/swarm_sdk/models.rb
114
- - lib/swarm_sdk/node/agent_config.rb
115
- - lib/swarm_sdk/node/builder.rb
116
- - lib/swarm_sdk/node/transformer_executor.rb
117
159
  - lib/swarm_sdk/node_context.rb
118
- - lib/swarm_sdk/node_orchestrator.rb
160
+ - lib/swarm_sdk/observer/builder.rb
161
+ - lib/swarm_sdk/observer/config.rb
162
+ - lib/swarm_sdk/observer/manager.rb
163
+ - lib/swarm_sdk/patterns/agent_observer.rb
119
164
  - lib/swarm_sdk/permissions/config.rb
120
165
  - lib/swarm_sdk/permissions/error_formatter.rb
121
166
  - lib/swarm_sdk/permissions/path_matcher.rb
@@ -125,7 +170,6 @@ files:
125
170
  - lib/swarm_sdk/plugin_registry.rb
126
171
  - lib/swarm_sdk/proc_helpers.rb
127
172
  - lib/swarm_sdk/prompts/base_system_prompt.md.erb
128
- - lib/swarm_sdk/providers/openai_with_responses.rb
129
173
  - lib/swarm_sdk/restore_result.rb
130
174
  - lib/swarm_sdk/result.rb
131
175
  - lib/swarm_sdk/snapshot.rb
@@ -136,6 +180,9 @@ files:
136
180
  - lib/swarm_sdk/swarm/agent_initializer.rb
137
181
  - lib/swarm_sdk/swarm/all_agents_builder.rb
138
182
  - lib/swarm_sdk/swarm/builder.rb
183
+ - lib/swarm_sdk/swarm/executor.rb
184
+ - lib/swarm_sdk/swarm/hook_triggers.rb
185
+ - lib/swarm_sdk/swarm/logging_callbacks.rb
139
186
  - lib/swarm_sdk/swarm/mcp_configurator.rb
140
187
  - lib/swarm_sdk/swarm/swarm_registry_builder.rb
141
188
  - lib/swarm_sdk/swarm/tool_configurator.rb
@@ -173,6 +220,12 @@ files:
173
220
  - lib/swarm_sdk/utils.rb
174
221
  - lib/swarm_sdk/validation_result.rb
175
222
  - lib/swarm_sdk/version.rb
223
+ - lib/swarm_sdk/workflow.rb
224
+ - lib/swarm_sdk/workflow/agent_config.rb
225
+ - lib/swarm_sdk/workflow/builder.rb
226
+ - lib/swarm_sdk/workflow/executor.rb
227
+ - lib/swarm_sdk/workflow/node_builder.rb
228
+ - lib/swarm_sdk/workflow/transformer_executor.rb
176
229
  homepage: https://github.com/parruda/claude-swarm
177
230
  licenses:
178
231
  - MIT