swarm_sdk 2.7.13 → 3.0.0.alpha1

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 (183) hide show
  1. checksums.yaml +4 -4
  2. data/lib/swarm_sdk/ruby_llm_patches/chat_callbacks_patch.rb +43 -22
  3. data/lib/swarm_sdk/ruby_llm_patches/init.rb +6 -0
  4. data/lib/swarm_sdk/ruby_llm_patches/mcp_ssl_patch.rb +144 -0
  5. data/lib/swarm_sdk/ruby_llm_patches/tool_concurrency_patch.rb +3 -4
  6. data/lib/swarm_sdk/v3/agent.rb +1165 -0
  7. data/lib/swarm_sdk/v3/agent_builder.rb +533 -0
  8. data/lib/swarm_sdk/v3/agent_definition.rb +330 -0
  9. data/lib/swarm_sdk/v3/configuration.rb +490 -0
  10. data/lib/swarm_sdk/v3/debug_log.rb +86 -0
  11. data/lib/swarm_sdk/v3/event_stream.rb +130 -0
  12. data/lib/swarm_sdk/v3/hooks/context.rb +112 -0
  13. data/lib/swarm_sdk/v3/hooks/result.rb +115 -0
  14. data/lib/swarm_sdk/v3/hooks/runner.rb +128 -0
  15. data/lib/swarm_sdk/v3/mcp/connector.rb +183 -0
  16. data/lib/swarm_sdk/v3/mcp/mcp_error.rb +15 -0
  17. data/lib/swarm_sdk/v3/mcp/server_definition.rb +125 -0
  18. data/lib/swarm_sdk/v3/mcp/ssl_http_transport.rb +103 -0
  19. data/lib/swarm_sdk/v3/mcp/stdio_transport.rb +135 -0
  20. data/lib/swarm_sdk/v3/mcp/tool_proxy.rb +53 -0
  21. data/lib/swarm_sdk/v3/memory/adapters/base.rb +297 -0
  22. data/lib/swarm_sdk/v3/memory/adapters/faiss_support.rb +194 -0
  23. data/lib/swarm_sdk/v3/memory/adapters/filesystem_adapter.rb +212 -0
  24. data/lib/swarm_sdk/v3/memory/adapters/sqlite_adapter.rb +507 -0
  25. data/lib/swarm_sdk/v3/memory/adapters/vector_utils.rb +88 -0
  26. data/lib/swarm_sdk/v3/memory/card.rb +206 -0
  27. data/lib/swarm_sdk/v3/memory/cluster.rb +146 -0
  28. data/lib/swarm_sdk/v3/memory/compressor.rb +496 -0
  29. data/lib/swarm_sdk/v3/memory/consolidator.rb +427 -0
  30. data/lib/swarm_sdk/v3/memory/context_builder.rb +339 -0
  31. data/lib/swarm_sdk/v3/memory/edge.rb +105 -0
  32. data/lib/swarm_sdk/v3/memory/embedder.rb +185 -0
  33. data/lib/swarm_sdk/v3/memory/exposure_tracker.rb +104 -0
  34. data/lib/swarm_sdk/v3/memory/ingestion_pipeline.rb +394 -0
  35. data/lib/swarm_sdk/v3/memory/retriever.rb +289 -0
  36. data/lib/swarm_sdk/v3/memory/store.rb +489 -0
  37. data/lib/swarm_sdk/v3/skills/loader.rb +147 -0
  38. data/lib/swarm_sdk/v3/skills/manifest.rb +45 -0
  39. data/lib/swarm_sdk/v3/sub_task_agent.rb +248 -0
  40. data/lib/swarm_sdk/v3/tools/base.rb +80 -0
  41. data/lib/swarm_sdk/v3/tools/bash.rb +174 -0
  42. data/lib/swarm_sdk/v3/tools/clock.rb +32 -0
  43. data/lib/swarm_sdk/v3/tools/edit.rb +111 -0
  44. data/lib/swarm_sdk/v3/tools/glob.rb +96 -0
  45. data/lib/swarm_sdk/v3/tools/grep.rb +200 -0
  46. data/lib/swarm_sdk/v3/tools/message_teammate.rb +15 -0
  47. data/lib/swarm_sdk/v3/tools/message_user.rb +15 -0
  48. data/lib/swarm_sdk/v3/tools/read.rb +181 -0
  49. data/lib/swarm_sdk/v3/tools/read_tracker.rb +40 -0
  50. data/lib/swarm_sdk/v3/tools/registry.rb +208 -0
  51. data/lib/swarm_sdk/v3/tools/sub_task.rb +183 -0
  52. data/lib/swarm_sdk/v3/tools/think.rb +88 -0
  53. data/lib/swarm_sdk/v3/tools/write.rb +87 -0
  54. data/lib/swarm_sdk/v3.rb +145 -0
  55. metadata +84 -148
  56. data/lib/swarm_sdk/agent/RETRY_LOGIC.md +0 -175
  57. data/lib/swarm_sdk/agent/builder.rb +0 -680
  58. data/lib/swarm_sdk/agent/chat.rb +0 -1432
  59. data/lib/swarm_sdk/agent/chat_helpers/context_tracker.rb +0 -375
  60. data/lib/swarm_sdk/agent/chat_helpers/event_emitter.rb +0 -204
  61. data/lib/swarm_sdk/agent/chat_helpers/hook_integration.rb +0 -480
  62. data/lib/swarm_sdk/agent/chat_helpers/instrumentation.rb +0 -85
  63. data/lib/swarm_sdk/agent/chat_helpers/llm_configuration.rb +0 -290
  64. data/lib/swarm_sdk/agent/chat_helpers/logging_helpers.rb +0 -116
  65. data/lib/swarm_sdk/agent/chat_helpers/serialization.rb +0 -83
  66. data/lib/swarm_sdk/agent/chat_helpers/system_reminder_injector.rb +0 -134
  67. data/lib/swarm_sdk/agent/chat_helpers/system_reminders.rb +0 -79
  68. data/lib/swarm_sdk/agent/chat_helpers/token_tracking.rb +0 -146
  69. data/lib/swarm_sdk/agent/context.rb +0 -115
  70. data/lib/swarm_sdk/agent/context_manager.rb +0 -315
  71. data/lib/swarm_sdk/agent/definition.rb +0 -581
  72. data/lib/swarm_sdk/agent/llm_instrumentation_middleware.rb +0 -226
  73. data/lib/swarm_sdk/agent/system_prompt_builder.rb +0 -161
  74. data/lib/swarm_sdk/agent/tool_registry.rb +0 -189
  75. data/lib/swarm_sdk/agent_registry.rb +0 -146
  76. data/lib/swarm_sdk/builders/base_builder.rb +0 -553
  77. data/lib/swarm_sdk/claude_code_agent_adapter.rb +0 -205
  78. data/lib/swarm_sdk/concerns/cleanupable.rb +0 -39
  79. data/lib/swarm_sdk/concerns/snapshotable.rb +0 -67
  80. data/lib/swarm_sdk/concerns/validatable.rb +0 -55
  81. data/lib/swarm_sdk/config.rb +0 -367
  82. data/lib/swarm_sdk/configuration/parser.rb +0 -397
  83. data/lib/swarm_sdk/configuration/translator.rb +0 -283
  84. data/lib/swarm_sdk/configuration.rb +0 -165
  85. data/lib/swarm_sdk/context_compactor/metrics.rb +0 -147
  86. data/lib/swarm_sdk/context_compactor/token_counter.rb +0 -102
  87. data/lib/swarm_sdk/context_compactor.rb +0 -335
  88. data/lib/swarm_sdk/context_management/builder.rb +0 -128
  89. data/lib/swarm_sdk/context_management/context.rb +0 -328
  90. data/lib/swarm_sdk/custom_tool_registry.rb +0 -226
  91. data/lib/swarm_sdk/defaults.rb +0 -251
  92. data/lib/swarm_sdk/events_to_messages.rb +0 -199
  93. data/lib/swarm_sdk/hooks/adapter.rb +0 -359
  94. data/lib/swarm_sdk/hooks/context.rb +0 -197
  95. data/lib/swarm_sdk/hooks/definition.rb +0 -80
  96. data/lib/swarm_sdk/hooks/error.rb +0 -29
  97. data/lib/swarm_sdk/hooks/executor.rb +0 -146
  98. data/lib/swarm_sdk/hooks/registry.rb +0 -147
  99. data/lib/swarm_sdk/hooks/result.rb +0 -150
  100. data/lib/swarm_sdk/hooks/shell_executor.rb +0 -256
  101. data/lib/swarm_sdk/hooks/tool_call.rb +0 -35
  102. data/lib/swarm_sdk/hooks/tool_result.rb +0 -62
  103. data/lib/swarm_sdk/log_collector.rb +0 -227
  104. data/lib/swarm_sdk/log_stream.rb +0 -127
  105. data/lib/swarm_sdk/markdown_parser.rb +0 -75
  106. data/lib/swarm_sdk/model_aliases.json +0 -8
  107. data/lib/swarm_sdk/models.json +0 -44002
  108. data/lib/swarm_sdk/models.rb +0 -161
  109. data/lib/swarm_sdk/node_context.rb +0 -245
  110. data/lib/swarm_sdk/observer/builder.rb +0 -81
  111. data/lib/swarm_sdk/observer/config.rb +0 -45
  112. data/lib/swarm_sdk/observer/manager.rb +0 -236
  113. data/lib/swarm_sdk/patterns/agent_observer.rb +0 -160
  114. data/lib/swarm_sdk/permissions/config.rb +0 -239
  115. data/lib/swarm_sdk/permissions/error_formatter.rb +0 -121
  116. data/lib/swarm_sdk/permissions/path_matcher.rb +0 -35
  117. data/lib/swarm_sdk/permissions/validator.rb +0 -173
  118. data/lib/swarm_sdk/permissions_builder.rb +0 -122
  119. data/lib/swarm_sdk/plugin.rb +0 -309
  120. data/lib/swarm_sdk/plugin_registry.rb +0 -101
  121. data/lib/swarm_sdk/proc_helpers.rb +0 -53
  122. data/lib/swarm_sdk/prompts/base_system_prompt.md.erb +0 -117
  123. data/lib/swarm_sdk/restore_result.rb +0 -65
  124. data/lib/swarm_sdk/result.rb +0 -212
  125. data/lib/swarm_sdk/snapshot.rb +0 -156
  126. data/lib/swarm_sdk/snapshot_from_events.rb +0 -397
  127. data/lib/swarm_sdk/state_restorer.rb +0 -476
  128. data/lib/swarm_sdk/state_snapshot.rb +0 -334
  129. data/lib/swarm_sdk/swarm/agent_initializer.rb +0 -648
  130. data/lib/swarm_sdk/swarm/all_agents_builder.rb +0 -195
  131. data/lib/swarm_sdk/swarm/builder.rb +0 -256
  132. data/lib/swarm_sdk/swarm/executor.rb +0 -290
  133. data/lib/swarm_sdk/swarm/hook_triggers.rb +0 -151
  134. data/lib/swarm_sdk/swarm/lazy_delegate_chat.rb +0 -372
  135. data/lib/swarm_sdk/swarm/logging_callbacks.rb +0 -360
  136. data/lib/swarm_sdk/swarm/mcp_configurator.rb +0 -270
  137. data/lib/swarm_sdk/swarm/swarm_registry_builder.rb +0 -67
  138. data/lib/swarm_sdk/swarm/tool_configurator.rb +0 -392
  139. data/lib/swarm_sdk/swarm.rb +0 -843
  140. data/lib/swarm_sdk/swarm_loader.rb +0 -145
  141. data/lib/swarm_sdk/swarm_registry.rb +0 -136
  142. data/lib/swarm_sdk/tools/base.rb +0 -63
  143. data/lib/swarm_sdk/tools/bash.rb +0 -280
  144. data/lib/swarm_sdk/tools/clock.rb +0 -46
  145. data/lib/swarm_sdk/tools/delegate.rb +0 -389
  146. data/lib/swarm_sdk/tools/document_converters/base_converter.rb +0 -83
  147. data/lib/swarm_sdk/tools/document_converters/docx_converter.rb +0 -99
  148. data/lib/swarm_sdk/tools/document_converters/html_converter.rb +0 -101
  149. data/lib/swarm_sdk/tools/document_converters/pdf_converter.rb +0 -78
  150. data/lib/swarm_sdk/tools/document_converters/xlsx_converter.rb +0 -194
  151. data/lib/swarm_sdk/tools/edit.rb +0 -145
  152. data/lib/swarm_sdk/tools/glob.rb +0 -166
  153. data/lib/swarm_sdk/tools/grep.rb +0 -235
  154. data/lib/swarm_sdk/tools/image_extractors/docx_image_extractor.rb +0 -43
  155. data/lib/swarm_sdk/tools/image_extractors/pdf_image_extractor.rb +0 -167
  156. data/lib/swarm_sdk/tools/image_formats/tiff_builder.rb +0 -65
  157. data/lib/swarm_sdk/tools/mcp_tool_stub.rb +0 -198
  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 -273
  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 -100
  170. data/lib/swarm_sdk/tools/todo_write.rb +0 -237
  171. data/lib/swarm_sdk/tools/web_fetch.rb +0 -264
  172. data/lib/swarm_sdk/tools/write.rb +0 -112
  173. data/lib/swarm_sdk/transcript_builder.rb +0 -278
  174. data/lib/swarm_sdk/utils.rb +0 -68
  175. data/lib/swarm_sdk/validation_result.rb +0 -33
  176. data/lib/swarm_sdk/version.rb +0 -5
  177. data/lib/swarm_sdk/workflow/agent_config.rb +0 -95
  178. data/lib/swarm_sdk/workflow/builder.rb +0 -227
  179. data/lib/swarm_sdk/workflow/executor.rb +0 -497
  180. data/lib/swarm_sdk/workflow/node_builder.rb +0 -593
  181. data/lib/swarm_sdk/workflow/transformer_executor.rb +0 -250
  182. data/lib/swarm_sdk/workflow.rb +0 -589
  183. data/lib/swarm_sdk.rb +0 -718
@@ -1,195 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module SwarmSDK
4
- class Swarm
5
- # AllAgentsBuilder for configuring settings that apply to all agents
6
- #
7
- # Settings configured here are applied to ALL agents, but can be overridden
8
- # at the agent level. This is useful for shared configuration like:
9
- # - Common provider/base_url (all agents use same proxy)
10
- # - Shared timeout settings
11
- # - Global permissions
12
- #
13
- # @example
14
- # all_agents do
15
- # provider :openai
16
- # base_url "http://proxy.com/v1"
17
- # timeout 180
18
- # tools :Read, :Write
19
- # coding_agent false
20
- # end
21
- class AllAgentsBuilder
22
- attr_reader :hooks, :permissions_config, :tools_list
23
-
24
- def initialize
25
- @tools_list = []
26
- @hooks = []
27
- @permissions_config = {}
28
- @model = nil
29
- @provider = nil
30
- @base_url = nil
31
- @api_version = nil
32
- @request_timeout = nil
33
- @turn_timeout = nil
34
- @parameters = nil
35
- @headers = nil
36
- @coding_agent = nil
37
- @disable_default_tools = nil
38
- @streaming = nil
39
- @thinking = nil
40
- end
41
-
42
- # Set model for all agents
43
- def model(model_name)
44
- @model = model_name
45
- end
46
-
47
- # Set provider for all agents
48
- def provider(provider_name)
49
- @provider = provider_name
50
- end
51
-
52
- # Set base URL for all agents
53
- def base_url(url)
54
- @base_url = url
55
- end
56
-
57
- # Set API version for all agents
58
- def api_version(version)
59
- @api_version = version
60
- end
61
-
62
- # Set request timeout for all agents
63
- def request_timeout(seconds)
64
- @request_timeout = seconds
65
- end
66
-
67
- # Set turn timeout for all agents
68
- def turn_timeout(seconds)
69
- @turn_timeout = seconds
70
- end
71
-
72
- # Set parameters for all agents
73
- def parameters(params)
74
- @parameters = params
75
- end
76
-
77
- # Set headers for all agents
78
- def headers(header_hash)
79
- @headers = header_hash
80
- end
81
-
82
- # Set coding_agent flag for all agents
83
- def coding_agent(enabled)
84
- @coding_agent = enabled
85
- end
86
-
87
- # Disable default tools for all agents
88
- #
89
- # @param value [Boolean, Array<Symbol>]
90
- # - true: Disable ALL default tools
91
- # - Array of symbols: Disable specific tools (e.g., [:Think, :TodoWrite])
92
- def disable_default_tools(value)
93
- @disable_default_tools = value
94
- end
95
-
96
- # Enable or disable streaming for all agents
97
- #
98
- # @param value [Boolean] If true, enables streaming; if false, disables it
99
- def streaming(value)
100
- @streaming = value
101
- end
102
-
103
- # Configure extended thinking for all agents
104
- #
105
- # @param effort [Symbol, String, nil] Reasoning effort (:low, :medium, :high) — OpenAI
106
- # @param budget [Integer, nil] Token budget for thinking — Anthropic
107
- def thinking(effort: nil, budget: nil)
108
- raise ArgumentError, "thinking requires :effort or :budget" if effort.nil? && budget.nil?
109
-
110
- @thinking = { effort: effort, budget: budget }.compact
111
- end
112
-
113
- # Add tools that all agents will have
114
- def tools(*tool_names)
115
- @tools_list.concat(tool_names)
116
- end
117
-
118
- # Add hook for all agents (agent-level events only)
119
- #
120
- # @example
121
- # hook :pre_tool_use, matcher: "Write" do |ctx|
122
- # # Applies to all agents
123
- # end
124
- def hook(event, matcher: nil, command: nil, timeout: nil, &block)
125
- # Validate agent-level events
126
- agent_events = [
127
- :pre_tool_use,
128
- :post_tool_use,
129
- :user_prompt,
130
- :agent_step,
131
- :agent_stop,
132
- :first_message,
133
- :pre_delegation,
134
- :post_delegation,
135
- :context_warning,
136
- ]
137
-
138
- unless agent_events.include?(event)
139
- raise ArgumentError, "Invalid all_agents hook: #{event}. Swarm-level events (:swarm_start, :swarm_stop) cannot be used in all_agents block."
140
- end
141
-
142
- @hooks << { event: event, matcher: matcher, command: command, timeout: timeout, block: block }
143
- end
144
-
145
- # Configure permissions for all agents
146
- #
147
- # Supports two forms:
148
- # 1. Block form (DSL): permissions do ... end
149
- # 2. Direct hash (internal/YAML): set_permissions_hash(hash)
150
- #
151
- # @example Block form
152
- # permissions do
153
- # Write.allow_paths "tmp/**/*"
154
- # Write.deny_paths "tmp/secrets/**"
155
- # Bash.allow_commands "^git status$"
156
- # end
157
- def permissions(&block)
158
- @permissions_config = PermissionsBuilder.build(&block)
159
- end
160
-
161
- # Set permissions directly from hash (for YAML translation)
162
- #
163
- # This is intentionally separate from permissions() to keep the DSL clean.
164
- # Called by Configuration when translating YAML permissions.
165
- #
166
- # @param hash [Hash] Permissions configuration hash
167
- # @return [void]
168
- def permissions_hash=(hash)
169
- @permissions_config = hash || {}
170
- end
171
-
172
- # Convert to hash for merging with agent configs
173
- #
174
- # @return [Hash] Configuration hash
175
- def to_h
176
- {
177
- model: @model,
178
- provider: @provider,
179
- base_url: @base_url,
180
- api_version: @api_version,
181
- request_timeout: @request_timeout,
182
- turn_timeout: @turn_timeout,
183
- parameters: @parameters,
184
- headers: @headers,
185
- coding_agent: @coding_agent,
186
- disable_default_tools: @disable_default_tools,
187
- streaming: @streaming,
188
- thinking: @thinking,
189
- tools: @tools_list,
190
- permissions: @permissions_config,
191
- }.compact
192
- end
193
- end
194
- end
195
- end
@@ -1,256 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module SwarmSDK
4
- class Swarm
5
- # Builder provides a beautiful Ruby DSL for building swarms
6
- #
7
- # The DSL combines YAML simplicity with Ruby power, enabling:
8
- # - Fluent, chainable configuration
9
- # - Hooks as Ruby blocks OR shell commands
10
- # - Full Ruby language features (variables, conditionals, loops)
11
- # - Type-safe, IDE-friendly API
12
- #
13
- # @example Basic usage
14
- # swarm = SwarmSDK.build do
15
- # name "Dev Team"
16
- # lead :backend
17
- #
18
- # agent :backend do
19
- # model "gpt-5"
20
- # prompt "You build APIs"
21
- # tools :Read, :Write, :Bash
22
- #
23
- # # Hook as Ruby block - inline logic!
24
- # hook :pre_tool_use, matcher: "Bash" do |ctx|
25
- # SwarmSDK::Hooks::Result.halt("Blocked!") if ctx.tool_call.parameters[:command].include?("rm -rf")
26
- # end
27
- # end
28
- # end
29
- #
30
- # swarm.execute("Build auth API")
31
- class Builder < Builders::BaseBuilder
32
- # Main entry point for DSL
33
- #
34
- # @example
35
- # swarm = SwarmSDK.build do
36
- # name "Team"
37
- # agent :backend { ... }
38
- # end
39
- class << self
40
- def build(allow_filesystem_tools: nil, &block)
41
- builder = new(allow_filesystem_tools: allow_filesystem_tools)
42
- builder.instance_eval(&block)
43
- builder.build_swarm
44
- end
45
- end
46
-
47
- def initialize(allow_filesystem_tools: nil)
48
- super
49
- @lead_agent = nil
50
- @swarm_hooks = []
51
- @observer_configs = []
52
- @execution_timeout = nil
53
- end
54
-
55
- # Set execution timeout (seconds)
56
- def execution_timeout(seconds)
57
- @execution_timeout = seconds
58
- end
59
-
60
- # Set lead agent
61
- def lead(agent_name)
62
- @lead_agent = agent_name
63
- end
64
-
65
- # Define observer agent behavior
66
- #
67
- # Configures an agent to run in parallel with main execution,
68
- # triggered by specific events. The block defines event handlers.
69
- #
70
- # @param agent_name [Symbol] Name of agent to use as observer (must be defined)
71
- # @param options [Hash] Optional observer settings (timeout, max_concurrent, etc.)
72
- # @yield Observer configuration block
73
- #
74
- # @example Basic observer
75
- # observer :profiler do
76
- # on :swarm_start do |event|
77
- # "Analyze this prompt: #{event[:prompt]}"
78
- # end
79
- # end
80
- #
81
- # @example Observer with options
82
- # observer :monitor, timeout: 120 do
83
- # on :tool_call do |event|
84
- # next unless event[:tool_name] == "Bash"
85
- # "Check command: #{event[:arguments][:command]}"
86
- # end
87
- # end
88
- def observer(agent_name, **options, &block)
89
- unless @agents.key?(agent_name)
90
- raise ConfigurationError,
91
- "Observer agent '#{agent_name}' not defined. " \
92
- "Define the agent first with `agent :#{agent_name} do ... end`"
93
- end
94
-
95
- config = Observer::Config.new(agent_name)
96
- config.options.merge!(options) if options.any?
97
- builder = Observer::Builder.new(agent_name, config)
98
- builder.instance_eval(&block)
99
-
100
- @observer_configs << config
101
- end
102
-
103
- # Add swarm-level hook (swarm_start, swarm_stop only)
104
- #
105
- # @example Shell command
106
- # hook :swarm_start, command: "echo 'Starting' >> log.txt"
107
- #
108
- # @example Ruby block
109
- # hook :swarm_start do |ctx|
110
- # puts "Swarm starting: #{ctx.metadata[:prompt]}"
111
- # end
112
- def hook(event, command: nil, timeout: nil, &block)
113
- # Validate swarm-level events
114
- unless [:swarm_start, :swarm_stop].include?(event)
115
- raise ArgumentError, "Invalid swarm-level hook: #{event}. Only :swarm_start and :swarm_stop allowed at swarm level. Use all_agents { hook ... } or agent { hook ... } for other events."
116
- end
117
-
118
- @swarm_hooks << { event: event, command: command, timeout: timeout, block: block }
119
- end
120
-
121
- # Build the actual Swarm instance
122
- def build_swarm
123
- raise ConfigurationError, "Swarm name not set. Use: name 'My Swarm'" unless @swarm_name
124
- raise ConfigurationError, "No agents defined. Use: agent :name { ... }" if @agents.empty?
125
- raise ConfigurationError, "Lead agent not set. Use: lead :agent_name" unless @lead_agent
126
-
127
- # Validate filesystem tools BEFORE building
128
- validate_all_agents_filesystem_tools if @all_agents_config
129
- validate_agent_filesystem_tools
130
-
131
- build_single_swarm
132
- end
133
-
134
- private
135
-
136
- # Build a traditional single-swarm execution
137
- #
138
- # @return [Swarm] Configured swarm instance
139
- def build_single_swarm
140
- # Validate swarm_id is set if external swarms are registered (required for composable swarms)
141
- if @swarm_registry_config.any? && @swarm_id.nil?
142
- raise ConfigurationError, "Swarm id must be set using id(...) when using composable swarms"
143
- end
144
-
145
- # Create swarm using SDK (swarm_id auto-generates if nil)
146
- swarm = Swarm.new(
147
- name: @swarm_name,
148
- swarm_id: @swarm_id,
149
- scratchpad_mode: @scratchpad,
150
- allow_filesystem_tools: @allow_filesystem_tools,
151
- execution_timeout: @execution_timeout,
152
- )
153
-
154
- # Setup swarm registry if external swarms are registered
155
- if @swarm_registry_config.any?
156
- registry = SwarmRegistry.new(parent_swarm_id: @swarm_id)
157
- @swarm_registry_config.each do |reg|
158
- registry.register(reg[:name], source: reg[:source], keep_context: reg[:keep_context])
159
- end
160
- swarm.swarm_registry = registry
161
- end
162
-
163
- # Build agent definitions and add to swarm
164
- agent_definitions = build_agent_definitions
165
- agent_definitions.each_value do |definition|
166
- swarm.add_agent(definition)
167
- end
168
-
169
- # Set lead
170
- swarm.lead = @lead_agent
171
-
172
- # Apply swarm hooks (Ruby blocks)
173
- @swarm_hooks.each do |hook_config|
174
- apply_swarm_hook(swarm, hook_config)
175
- end
176
-
177
- # Apply all_agents hooks (Ruby blocks)
178
- @all_agents_config&.hooks&.each do |hook_config|
179
- apply_all_agents_hook(swarm, hook_config)
180
- end
181
-
182
- # Add observer configurations to swarm
183
- @observer_configs.each { |c| swarm.add_observer_config(c) }
184
-
185
- swarm
186
- end
187
-
188
- def apply_swarm_hook(swarm, config)
189
- event = config[:event]
190
-
191
- if config[:block]
192
- # Ruby block hook - register directly
193
- swarm.add_default_callback(event, &config[:block])
194
- elsif config[:command]
195
- # Shell command hook - use ShellExecutor
196
- swarm.add_default_callback(event) do |context|
197
- input_json = build_hook_input(context, event)
198
- Hooks::ShellExecutor.execute(
199
- command: config[:command],
200
- input_json: input_json,
201
- timeout: config[:timeout] || 60,
202
- swarm_name: swarm.name,
203
- event: event,
204
- )
205
- end
206
- end
207
- end
208
-
209
- def apply_all_agents_hook(swarm, config)
210
- event = config[:event]
211
- matcher = config[:matcher]
212
-
213
- if config[:block]
214
- # Ruby block hook
215
- swarm.add_default_callback(event, matcher: matcher, &config[:block])
216
- elsif config[:command]
217
- # Shell command hook
218
- swarm.add_default_callback(event, matcher: matcher) do |context|
219
- input_json = build_hook_input(context, event)
220
- Hooks::ShellExecutor.execute(
221
- command: config[:command],
222
- input_json: input_json,
223
- timeout: config[:timeout] || 60,
224
- agent_name: context.agent_name,
225
- swarm_name: swarm.name,
226
- event: event,
227
- )
228
- end
229
- end
230
- end
231
-
232
- def build_hook_input(context, event)
233
- # Build JSON input for shell hooks
234
- base = { event: event.to_s }
235
-
236
- case event
237
- when :pre_tool_use
238
- base.merge(tool: context.tool_call.name, parameters: context.tool_call.parameters)
239
- when :post_tool_use
240
- base.merge(result: context.tool_result.content, success: context.tool_result.success?)
241
- when :user_prompt
242
- base.merge(prompt: context.metadata[:prompt])
243
- when :swarm_start
244
- base.merge(prompt: context.metadata[:prompt])
245
- when :swarm_stop
246
- base.merge(success: context.metadata[:success], duration: context.metadata[:duration])
247
- else
248
- base
249
- end
250
- end
251
- end
252
-
253
- # Helper class for swarms block in DSL (kept in this file for reference)
254
- # Actual implementation is in swarm_registry_builder.rb for Zeitwerk
255
- end
256
- end