swarm_sdk 2.7.14 → 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 (181) hide show
  1. checksums.yaml +4 -4
  2. data/lib/swarm_sdk/ruby_llm_patches/chat_callbacks_patch.rb +16 -0
  3. data/lib/swarm_sdk/ruby_llm_patches/init.rb +4 -1
  4. data/lib/swarm_sdk/v3/agent.rb +1165 -0
  5. data/lib/swarm_sdk/v3/agent_builder.rb +533 -0
  6. data/lib/swarm_sdk/v3/agent_definition.rb +330 -0
  7. data/lib/swarm_sdk/v3/configuration.rb +490 -0
  8. data/lib/swarm_sdk/v3/debug_log.rb +86 -0
  9. data/lib/swarm_sdk/v3/event_stream.rb +130 -0
  10. data/lib/swarm_sdk/v3/hooks/context.rb +112 -0
  11. data/lib/swarm_sdk/v3/hooks/result.rb +115 -0
  12. data/lib/swarm_sdk/v3/hooks/runner.rb +128 -0
  13. data/lib/swarm_sdk/v3/mcp/connector.rb +183 -0
  14. data/lib/swarm_sdk/v3/mcp/mcp_error.rb +15 -0
  15. data/lib/swarm_sdk/v3/mcp/server_definition.rb +125 -0
  16. data/lib/swarm_sdk/v3/mcp/ssl_http_transport.rb +103 -0
  17. data/lib/swarm_sdk/v3/mcp/stdio_transport.rb +135 -0
  18. data/lib/swarm_sdk/v3/mcp/tool_proxy.rb +53 -0
  19. data/lib/swarm_sdk/v3/memory/adapters/base.rb +297 -0
  20. data/lib/swarm_sdk/v3/memory/adapters/faiss_support.rb +194 -0
  21. data/lib/swarm_sdk/v3/memory/adapters/filesystem_adapter.rb +212 -0
  22. data/lib/swarm_sdk/v3/memory/adapters/sqlite_adapter.rb +507 -0
  23. data/lib/swarm_sdk/v3/memory/adapters/vector_utils.rb +88 -0
  24. data/lib/swarm_sdk/v3/memory/card.rb +206 -0
  25. data/lib/swarm_sdk/v3/memory/cluster.rb +146 -0
  26. data/lib/swarm_sdk/v3/memory/compressor.rb +496 -0
  27. data/lib/swarm_sdk/v3/memory/consolidator.rb +427 -0
  28. data/lib/swarm_sdk/v3/memory/context_builder.rb +339 -0
  29. data/lib/swarm_sdk/v3/memory/edge.rb +105 -0
  30. data/lib/swarm_sdk/v3/memory/embedder.rb +185 -0
  31. data/lib/swarm_sdk/v3/memory/exposure_tracker.rb +104 -0
  32. data/lib/swarm_sdk/v3/memory/ingestion_pipeline.rb +394 -0
  33. data/lib/swarm_sdk/v3/memory/retriever.rb +289 -0
  34. data/lib/swarm_sdk/v3/memory/store.rb +489 -0
  35. data/lib/swarm_sdk/v3/skills/loader.rb +147 -0
  36. data/lib/swarm_sdk/v3/skills/manifest.rb +45 -0
  37. data/lib/swarm_sdk/v3/sub_task_agent.rb +248 -0
  38. data/lib/swarm_sdk/v3/tools/base.rb +80 -0
  39. data/lib/swarm_sdk/v3/tools/bash.rb +174 -0
  40. data/lib/swarm_sdk/v3/tools/clock.rb +32 -0
  41. data/lib/swarm_sdk/v3/tools/edit.rb +111 -0
  42. data/lib/swarm_sdk/v3/tools/glob.rb +96 -0
  43. data/lib/swarm_sdk/v3/tools/grep.rb +200 -0
  44. data/lib/swarm_sdk/v3/tools/message_teammate.rb +15 -0
  45. data/lib/swarm_sdk/v3/tools/message_user.rb +15 -0
  46. data/lib/swarm_sdk/v3/tools/read.rb +181 -0
  47. data/lib/swarm_sdk/v3/tools/read_tracker.rb +40 -0
  48. data/lib/swarm_sdk/v3/tools/registry.rb +208 -0
  49. data/lib/swarm_sdk/v3/tools/sub_task.rb +183 -0
  50. data/lib/swarm_sdk/v3/tools/think.rb +88 -0
  51. data/lib/swarm_sdk/v3/tools/write.rb +87 -0
  52. data/lib/swarm_sdk/v3.rb +145 -0
  53. metadata +83 -148
  54. data/lib/swarm_sdk/agent/RETRY_LOGIC.md +0 -175
  55. data/lib/swarm_sdk/agent/builder.rb +0 -705
  56. data/lib/swarm_sdk/agent/chat.rb +0 -1438
  57. data/lib/swarm_sdk/agent/chat_helpers/context_tracker.rb +0 -375
  58. data/lib/swarm_sdk/agent/chat_helpers/event_emitter.rb +0 -204
  59. data/lib/swarm_sdk/agent/chat_helpers/hook_integration.rb +0 -480
  60. data/lib/swarm_sdk/agent/chat_helpers/instrumentation.rb +0 -85
  61. data/lib/swarm_sdk/agent/chat_helpers/llm_configuration.rb +0 -290
  62. data/lib/swarm_sdk/agent/chat_helpers/logging_helpers.rb +0 -116
  63. data/lib/swarm_sdk/agent/chat_helpers/serialization.rb +0 -83
  64. data/lib/swarm_sdk/agent/chat_helpers/system_reminder_injector.rb +0 -134
  65. data/lib/swarm_sdk/agent/chat_helpers/system_reminders.rb +0 -79
  66. data/lib/swarm_sdk/agent/chat_helpers/token_tracking.rb +0 -146
  67. data/lib/swarm_sdk/agent/context.rb +0 -115
  68. data/lib/swarm_sdk/agent/context_manager.rb +0 -315
  69. data/lib/swarm_sdk/agent/definition.rb +0 -588
  70. data/lib/swarm_sdk/agent/llm_instrumentation_middleware.rb +0 -226
  71. data/lib/swarm_sdk/agent/system_prompt_builder.rb +0 -173
  72. data/lib/swarm_sdk/agent/tool_registry.rb +0 -189
  73. data/lib/swarm_sdk/agent_registry.rb +0 -146
  74. data/lib/swarm_sdk/builders/base_builder.rb +0 -558
  75. data/lib/swarm_sdk/claude_code_agent_adapter.rb +0 -205
  76. data/lib/swarm_sdk/concerns/cleanupable.rb +0 -42
  77. data/lib/swarm_sdk/concerns/snapshotable.rb +0 -67
  78. data/lib/swarm_sdk/concerns/validatable.rb +0 -55
  79. data/lib/swarm_sdk/config.rb +0 -368
  80. data/lib/swarm_sdk/configuration/parser.rb +0 -397
  81. data/lib/swarm_sdk/configuration/translator.rb +0 -285
  82. data/lib/swarm_sdk/configuration.rb +0 -165
  83. data/lib/swarm_sdk/context_compactor/metrics.rb +0 -147
  84. data/lib/swarm_sdk/context_compactor/token_counter.rb +0 -102
  85. data/lib/swarm_sdk/context_compactor.rb +0 -335
  86. data/lib/swarm_sdk/context_management/builder.rb +0 -128
  87. data/lib/swarm_sdk/context_management/context.rb +0 -328
  88. data/lib/swarm_sdk/custom_tool_registry.rb +0 -226
  89. data/lib/swarm_sdk/defaults.rb +0 -251
  90. data/lib/swarm_sdk/events_to_messages.rb +0 -199
  91. data/lib/swarm_sdk/hooks/adapter.rb +0 -359
  92. data/lib/swarm_sdk/hooks/context.rb +0 -197
  93. data/lib/swarm_sdk/hooks/definition.rb +0 -80
  94. data/lib/swarm_sdk/hooks/error.rb +0 -29
  95. data/lib/swarm_sdk/hooks/executor.rb +0 -146
  96. data/lib/swarm_sdk/hooks/registry.rb +0 -147
  97. data/lib/swarm_sdk/hooks/result.rb +0 -150
  98. data/lib/swarm_sdk/hooks/shell_executor.rb +0 -256
  99. data/lib/swarm_sdk/hooks/tool_call.rb +0 -35
  100. data/lib/swarm_sdk/hooks/tool_result.rb +0 -62
  101. data/lib/swarm_sdk/log_collector.rb +0 -227
  102. data/lib/swarm_sdk/log_stream.rb +0 -127
  103. data/lib/swarm_sdk/markdown_parser.rb +0 -75
  104. data/lib/swarm_sdk/model_aliases.json +0 -8
  105. data/lib/swarm_sdk/models.json +0 -44002
  106. data/lib/swarm_sdk/models.rb +0 -161
  107. data/lib/swarm_sdk/node_context.rb +0 -245
  108. data/lib/swarm_sdk/observer/builder.rb +0 -81
  109. data/lib/swarm_sdk/observer/config.rb +0 -45
  110. data/lib/swarm_sdk/observer/manager.rb +0 -248
  111. data/lib/swarm_sdk/patterns/agent_observer.rb +0 -160
  112. data/lib/swarm_sdk/permissions/config.rb +0 -239
  113. data/lib/swarm_sdk/permissions/error_formatter.rb +0 -121
  114. data/lib/swarm_sdk/permissions/path_matcher.rb +0 -35
  115. data/lib/swarm_sdk/permissions/validator.rb +0 -173
  116. data/lib/swarm_sdk/permissions_builder.rb +0 -122
  117. data/lib/swarm_sdk/plugin.rb +0 -309
  118. data/lib/swarm_sdk/plugin_registry.rb +0 -101
  119. data/lib/swarm_sdk/proc_helpers.rb +0 -53
  120. data/lib/swarm_sdk/prompts/base_system_prompt.md.erb +0 -119
  121. data/lib/swarm_sdk/restore_result.rb +0 -65
  122. data/lib/swarm_sdk/result.rb +0 -241
  123. data/lib/swarm_sdk/snapshot.rb +0 -156
  124. data/lib/swarm_sdk/snapshot_from_events.rb +0 -397
  125. data/lib/swarm_sdk/state_restorer.rb +0 -476
  126. data/lib/swarm_sdk/state_snapshot.rb +0 -334
  127. data/lib/swarm_sdk/swarm/agent_initializer.rb +0 -648
  128. data/lib/swarm_sdk/swarm/all_agents_builder.rb +0 -204
  129. data/lib/swarm_sdk/swarm/builder.rb +0 -256
  130. data/lib/swarm_sdk/swarm/executor.rb +0 -446
  131. data/lib/swarm_sdk/swarm/hook_triggers.rb +0 -162
  132. data/lib/swarm_sdk/swarm/lazy_delegate_chat.rb +0 -372
  133. data/lib/swarm_sdk/swarm/logging_callbacks.rb +0 -361
  134. data/lib/swarm_sdk/swarm/mcp_configurator.rb +0 -290
  135. data/lib/swarm_sdk/swarm/swarm_registry_builder.rb +0 -67
  136. data/lib/swarm_sdk/swarm/tool_configurator.rb +0 -392
  137. data/lib/swarm_sdk/swarm.rb +0 -973
  138. data/lib/swarm_sdk/swarm_loader.rb +0 -145
  139. data/lib/swarm_sdk/swarm_registry.rb +0 -136
  140. data/lib/swarm_sdk/tools/base.rb +0 -63
  141. data/lib/swarm_sdk/tools/bash.rb +0 -280
  142. data/lib/swarm_sdk/tools/clock.rb +0 -46
  143. data/lib/swarm_sdk/tools/delegate.rb +0 -389
  144. data/lib/swarm_sdk/tools/document_converters/base_converter.rb +0 -83
  145. data/lib/swarm_sdk/tools/document_converters/docx_converter.rb +0 -99
  146. data/lib/swarm_sdk/tools/document_converters/html_converter.rb +0 -101
  147. data/lib/swarm_sdk/tools/document_converters/pdf_converter.rb +0 -78
  148. data/lib/swarm_sdk/tools/document_converters/xlsx_converter.rb +0 -194
  149. data/lib/swarm_sdk/tools/edit.rb +0 -145
  150. data/lib/swarm_sdk/tools/glob.rb +0 -166
  151. data/lib/swarm_sdk/tools/grep.rb +0 -235
  152. data/lib/swarm_sdk/tools/image_extractors/docx_image_extractor.rb +0 -43
  153. data/lib/swarm_sdk/tools/image_extractors/pdf_image_extractor.rb +0 -167
  154. data/lib/swarm_sdk/tools/image_formats/tiff_builder.rb +0 -65
  155. data/lib/swarm_sdk/tools/mcp_tool_stub.rb +0 -198
  156. data/lib/swarm_sdk/tools/multi_edit.rb +0 -236
  157. data/lib/swarm_sdk/tools/path_resolver.rb +0 -92
  158. data/lib/swarm_sdk/tools/read.rb +0 -261
  159. data/lib/swarm_sdk/tools/registry.rb +0 -205
  160. data/lib/swarm_sdk/tools/scratchpad/scratchpad_list.rb +0 -117
  161. data/lib/swarm_sdk/tools/scratchpad/scratchpad_read.rb +0 -97
  162. data/lib/swarm_sdk/tools/scratchpad/scratchpad_write.rb +0 -108
  163. data/lib/swarm_sdk/tools/stores/read_tracker.rb +0 -96
  164. data/lib/swarm_sdk/tools/stores/scratchpad_storage.rb +0 -273
  165. data/lib/swarm_sdk/tools/stores/storage.rb +0 -142
  166. data/lib/swarm_sdk/tools/stores/todo_manager.rb +0 -65
  167. data/lib/swarm_sdk/tools/think.rb +0 -100
  168. data/lib/swarm_sdk/tools/todo_write.rb +0 -237
  169. data/lib/swarm_sdk/tools/web_fetch.rb +0 -264
  170. data/lib/swarm_sdk/tools/write.rb +0 -112
  171. data/lib/swarm_sdk/transcript_builder.rb +0 -278
  172. data/lib/swarm_sdk/utils.rb +0 -68
  173. data/lib/swarm_sdk/validation_result.rb +0 -33
  174. data/lib/swarm_sdk/version.rb +0 -5
  175. data/lib/swarm_sdk/workflow/agent_config.rb +0 -95
  176. data/lib/swarm_sdk/workflow/builder.rb +0 -227
  177. data/lib/swarm_sdk/workflow/executor.rb +0 -497
  178. data/lib/swarm_sdk/workflow/node_builder.rb +0 -593
  179. data/lib/swarm_sdk/workflow/transformer_executor.rb +0 -250
  180. data/lib/swarm_sdk/workflow.rb +0 -589
  181. data/lib/swarm_sdk.rb +0 -721
@@ -1,204 +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
- @disable_environment_info = nil
41
- end
42
-
43
- # Set model for all agents
44
- def model(model_name)
45
- @model = model_name
46
- end
47
-
48
- # Set provider for all agents
49
- def provider(provider_name)
50
- @provider = provider_name
51
- end
52
-
53
- # Set base URL for all agents
54
- def base_url(url)
55
- @base_url = url
56
- end
57
-
58
- # Set API version for all agents
59
- def api_version(version)
60
- @api_version = version
61
- end
62
-
63
- # Set request timeout for all agents
64
- def request_timeout(seconds)
65
- @request_timeout = seconds
66
- end
67
-
68
- # Set turn timeout for all agents
69
- def turn_timeout(seconds)
70
- @turn_timeout = seconds
71
- end
72
-
73
- # Set parameters for all agents
74
- def parameters(params)
75
- @parameters = params
76
- end
77
-
78
- # Set headers for all agents
79
- def headers(header_hash)
80
- @headers = header_hash
81
- end
82
-
83
- # Set coding_agent flag for all agents
84
- def coding_agent(enabled)
85
- @coding_agent = enabled
86
- end
87
-
88
- # Disable default tools for all agents
89
- #
90
- # @param value [Boolean, Array<Symbol>]
91
- # - true: Disable ALL default tools
92
- # - Array of symbols: Disable specific tools (e.g., [:Think, :TodoWrite])
93
- def disable_default_tools(value)
94
- @disable_default_tools = value
95
- end
96
-
97
- # Enable or disable streaming for all agents
98
- #
99
- # @param value [Boolean] If true, enables streaming; if false, disables it
100
- def streaming(value)
101
- @streaming = value
102
- end
103
-
104
- # Disable environment info for all agents
105
- #
106
- # @param enabled [Boolean] Whether to disable environment info in system prompts
107
- def disable_environment_info(enabled)
108
- @disable_environment_info = enabled
109
- end
110
-
111
- # Configure extended thinking for all agents
112
- #
113
- # @param effort [Symbol, String, nil] Reasoning effort (:low, :medium, :high) — OpenAI
114
- # @param budget [Integer, nil] Token budget for thinking — Anthropic
115
- def thinking(effort: nil, budget: nil)
116
- raise ArgumentError, "thinking requires :effort or :budget" if effort.nil? && budget.nil?
117
-
118
- @thinking = { effort: effort, budget: budget }.compact
119
- end
120
-
121
- # Add tools that all agents will have
122
- def tools(*tool_names)
123
- @tools_list.concat(tool_names)
124
- end
125
-
126
- # Add hook for all agents (agent-level events only)
127
- #
128
- # @example
129
- # hook :pre_tool_use, matcher: "Write" do |ctx|
130
- # # Applies to all agents
131
- # end
132
- def hook(event, matcher: nil, command: nil, timeout: nil, &block)
133
- # Validate agent-level events
134
- agent_events = [
135
- :pre_tool_use,
136
- :post_tool_use,
137
- :user_prompt,
138
- :agent_step,
139
- :agent_stop,
140
- :first_message,
141
- :pre_delegation,
142
- :post_delegation,
143
- :context_warning,
144
- ]
145
-
146
- unless agent_events.include?(event)
147
- raise ArgumentError, "Invalid all_agents hook: #{event}. Swarm-level events (:swarm_start, :swarm_stop) cannot be used in all_agents block."
148
- end
149
-
150
- @hooks << { event: event, matcher: matcher, command: command, timeout: timeout, block: block }
151
- end
152
-
153
- # Configure permissions for all agents
154
- #
155
- # Supports two forms:
156
- # 1. Block form (DSL): permissions do ... end
157
- # 2. Direct hash (internal/YAML): set_permissions_hash(hash)
158
- #
159
- # @example Block form
160
- # permissions do
161
- # Write.allow_paths "tmp/**/*"
162
- # Write.deny_paths "tmp/secrets/**"
163
- # Bash.allow_commands "^git status$"
164
- # end
165
- def permissions(&block)
166
- @permissions_config = PermissionsBuilder.build(&block)
167
- end
168
-
169
- # Set permissions directly from hash (for YAML translation)
170
- #
171
- # This is intentionally separate from permissions() to keep the DSL clean.
172
- # Called by Configuration when translating YAML permissions.
173
- #
174
- # @param hash [Hash] Permissions configuration hash
175
- # @return [void]
176
- def permissions_hash=(hash)
177
- @permissions_config = hash || {}
178
- end
179
-
180
- # Convert to hash for merging with agent configs
181
- #
182
- # @return [Hash] Configuration hash
183
- def to_h
184
- {
185
- model: @model,
186
- provider: @provider,
187
- base_url: @base_url,
188
- api_version: @api_version,
189
- request_timeout: @request_timeout,
190
- turn_timeout: @turn_timeout,
191
- parameters: @parameters,
192
- headers: @headers,
193
- coding_agent: @coding_agent,
194
- disable_default_tools: @disable_default_tools,
195
- streaming: @streaming,
196
- thinking: @thinking,
197
- disable_environment_info: @disable_environment_info,
198
- tools: @tools_list,
199
- permissions: @permissions_config,
200
- }.compact
201
- end
202
- end
203
- end
204
- 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