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.
- checksums.yaml +4 -4
- data/lib/swarm_sdk/ruby_llm_patches/chat_callbacks_patch.rb +16 -0
- data/lib/swarm_sdk/ruby_llm_patches/init.rb +4 -1
- data/lib/swarm_sdk/v3/agent.rb +1165 -0
- data/lib/swarm_sdk/v3/agent_builder.rb +533 -0
- data/lib/swarm_sdk/v3/agent_definition.rb +330 -0
- data/lib/swarm_sdk/v3/configuration.rb +490 -0
- data/lib/swarm_sdk/v3/debug_log.rb +86 -0
- data/lib/swarm_sdk/v3/event_stream.rb +130 -0
- data/lib/swarm_sdk/v3/hooks/context.rb +112 -0
- data/lib/swarm_sdk/v3/hooks/result.rb +115 -0
- data/lib/swarm_sdk/v3/hooks/runner.rb +128 -0
- data/lib/swarm_sdk/v3/mcp/connector.rb +183 -0
- data/lib/swarm_sdk/v3/mcp/mcp_error.rb +15 -0
- data/lib/swarm_sdk/v3/mcp/server_definition.rb +125 -0
- data/lib/swarm_sdk/v3/mcp/ssl_http_transport.rb +103 -0
- data/lib/swarm_sdk/v3/mcp/stdio_transport.rb +135 -0
- data/lib/swarm_sdk/v3/mcp/tool_proxy.rb +53 -0
- data/lib/swarm_sdk/v3/memory/adapters/base.rb +297 -0
- data/lib/swarm_sdk/v3/memory/adapters/faiss_support.rb +194 -0
- data/lib/swarm_sdk/v3/memory/adapters/filesystem_adapter.rb +212 -0
- data/lib/swarm_sdk/v3/memory/adapters/sqlite_adapter.rb +507 -0
- data/lib/swarm_sdk/v3/memory/adapters/vector_utils.rb +88 -0
- data/lib/swarm_sdk/v3/memory/card.rb +206 -0
- data/lib/swarm_sdk/v3/memory/cluster.rb +146 -0
- data/lib/swarm_sdk/v3/memory/compressor.rb +496 -0
- data/lib/swarm_sdk/v3/memory/consolidator.rb +427 -0
- data/lib/swarm_sdk/v3/memory/context_builder.rb +339 -0
- data/lib/swarm_sdk/v3/memory/edge.rb +105 -0
- data/lib/swarm_sdk/v3/memory/embedder.rb +185 -0
- data/lib/swarm_sdk/v3/memory/exposure_tracker.rb +104 -0
- data/lib/swarm_sdk/v3/memory/ingestion_pipeline.rb +394 -0
- data/lib/swarm_sdk/v3/memory/retriever.rb +289 -0
- data/lib/swarm_sdk/v3/memory/store.rb +489 -0
- data/lib/swarm_sdk/v3/skills/loader.rb +147 -0
- data/lib/swarm_sdk/v3/skills/manifest.rb +45 -0
- data/lib/swarm_sdk/v3/sub_task_agent.rb +248 -0
- data/lib/swarm_sdk/v3/tools/base.rb +80 -0
- data/lib/swarm_sdk/v3/tools/bash.rb +174 -0
- data/lib/swarm_sdk/v3/tools/clock.rb +32 -0
- data/lib/swarm_sdk/v3/tools/edit.rb +111 -0
- data/lib/swarm_sdk/v3/tools/glob.rb +96 -0
- data/lib/swarm_sdk/v3/tools/grep.rb +200 -0
- data/lib/swarm_sdk/v3/tools/message_teammate.rb +15 -0
- data/lib/swarm_sdk/v3/tools/message_user.rb +15 -0
- data/lib/swarm_sdk/v3/tools/read.rb +181 -0
- data/lib/swarm_sdk/v3/tools/read_tracker.rb +40 -0
- data/lib/swarm_sdk/v3/tools/registry.rb +208 -0
- data/lib/swarm_sdk/v3/tools/sub_task.rb +183 -0
- data/lib/swarm_sdk/v3/tools/think.rb +88 -0
- data/lib/swarm_sdk/v3/tools/write.rb +87 -0
- data/lib/swarm_sdk/v3.rb +145 -0
- metadata +83 -148
- data/lib/swarm_sdk/agent/RETRY_LOGIC.md +0 -175
- data/lib/swarm_sdk/agent/builder.rb +0 -705
- data/lib/swarm_sdk/agent/chat.rb +0 -1438
- data/lib/swarm_sdk/agent/chat_helpers/context_tracker.rb +0 -375
- data/lib/swarm_sdk/agent/chat_helpers/event_emitter.rb +0 -204
- data/lib/swarm_sdk/agent/chat_helpers/hook_integration.rb +0 -480
- data/lib/swarm_sdk/agent/chat_helpers/instrumentation.rb +0 -85
- data/lib/swarm_sdk/agent/chat_helpers/llm_configuration.rb +0 -290
- data/lib/swarm_sdk/agent/chat_helpers/logging_helpers.rb +0 -116
- data/lib/swarm_sdk/agent/chat_helpers/serialization.rb +0 -83
- data/lib/swarm_sdk/agent/chat_helpers/system_reminder_injector.rb +0 -134
- data/lib/swarm_sdk/agent/chat_helpers/system_reminders.rb +0 -79
- data/lib/swarm_sdk/agent/chat_helpers/token_tracking.rb +0 -146
- data/lib/swarm_sdk/agent/context.rb +0 -115
- data/lib/swarm_sdk/agent/context_manager.rb +0 -315
- data/lib/swarm_sdk/agent/definition.rb +0 -588
- data/lib/swarm_sdk/agent/llm_instrumentation_middleware.rb +0 -226
- data/lib/swarm_sdk/agent/system_prompt_builder.rb +0 -173
- data/lib/swarm_sdk/agent/tool_registry.rb +0 -189
- data/lib/swarm_sdk/agent_registry.rb +0 -146
- data/lib/swarm_sdk/builders/base_builder.rb +0 -558
- data/lib/swarm_sdk/claude_code_agent_adapter.rb +0 -205
- data/lib/swarm_sdk/concerns/cleanupable.rb +0 -42
- data/lib/swarm_sdk/concerns/snapshotable.rb +0 -67
- data/lib/swarm_sdk/concerns/validatable.rb +0 -55
- data/lib/swarm_sdk/config.rb +0 -368
- data/lib/swarm_sdk/configuration/parser.rb +0 -397
- data/lib/swarm_sdk/configuration/translator.rb +0 -285
- data/lib/swarm_sdk/configuration.rb +0 -165
- data/lib/swarm_sdk/context_compactor/metrics.rb +0 -147
- data/lib/swarm_sdk/context_compactor/token_counter.rb +0 -102
- data/lib/swarm_sdk/context_compactor.rb +0 -335
- data/lib/swarm_sdk/context_management/builder.rb +0 -128
- data/lib/swarm_sdk/context_management/context.rb +0 -328
- data/lib/swarm_sdk/custom_tool_registry.rb +0 -226
- data/lib/swarm_sdk/defaults.rb +0 -251
- data/lib/swarm_sdk/events_to_messages.rb +0 -199
- data/lib/swarm_sdk/hooks/adapter.rb +0 -359
- data/lib/swarm_sdk/hooks/context.rb +0 -197
- data/lib/swarm_sdk/hooks/definition.rb +0 -80
- data/lib/swarm_sdk/hooks/error.rb +0 -29
- data/lib/swarm_sdk/hooks/executor.rb +0 -146
- data/lib/swarm_sdk/hooks/registry.rb +0 -147
- data/lib/swarm_sdk/hooks/result.rb +0 -150
- data/lib/swarm_sdk/hooks/shell_executor.rb +0 -256
- data/lib/swarm_sdk/hooks/tool_call.rb +0 -35
- data/lib/swarm_sdk/hooks/tool_result.rb +0 -62
- data/lib/swarm_sdk/log_collector.rb +0 -227
- data/lib/swarm_sdk/log_stream.rb +0 -127
- data/lib/swarm_sdk/markdown_parser.rb +0 -75
- data/lib/swarm_sdk/model_aliases.json +0 -8
- data/lib/swarm_sdk/models.json +0 -44002
- data/lib/swarm_sdk/models.rb +0 -161
- data/lib/swarm_sdk/node_context.rb +0 -245
- data/lib/swarm_sdk/observer/builder.rb +0 -81
- data/lib/swarm_sdk/observer/config.rb +0 -45
- data/lib/swarm_sdk/observer/manager.rb +0 -248
- data/lib/swarm_sdk/patterns/agent_observer.rb +0 -160
- data/lib/swarm_sdk/permissions/config.rb +0 -239
- data/lib/swarm_sdk/permissions/error_formatter.rb +0 -121
- data/lib/swarm_sdk/permissions/path_matcher.rb +0 -35
- data/lib/swarm_sdk/permissions/validator.rb +0 -173
- data/lib/swarm_sdk/permissions_builder.rb +0 -122
- data/lib/swarm_sdk/plugin.rb +0 -309
- data/lib/swarm_sdk/plugin_registry.rb +0 -101
- data/lib/swarm_sdk/proc_helpers.rb +0 -53
- data/lib/swarm_sdk/prompts/base_system_prompt.md.erb +0 -119
- data/lib/swarm_sdk/restore_result.rb +0 -65
- data/lib/swarm_sdk/result.rb +0 -241
- data/lib/swarm_sdk/snapshot.rb +0 -156
- data/lib/swarm_sdk/snapshot_from_events.rb +0 -397
- data/lib/swarm_sdk/state_restorer.rb +0 -476
- data/lib/swarm_sdk/state_snapshot.rb +0 -334
- data/lib/swarm_sdk/swarm/agent_initializer.rb +0 -648
- data/lib/swarm_sdk/swarm/all_agents_builder.rb +0 -204
- data/lib/swarm_sdk/swarm/builder.rb +0 -256
- data/lib/swarm_sdk/swarm/executor.rb +0 -446
- data/lib/swarm_sdk/swarm/hook_triggers.rb +0 -162
- data/lib/swarm_sdk/swarm/lazy_delegate_chat.rb +0 -372
- data/lib/swarm_sdk/swarm/logging_callbacks.rb +0 -361
- data/lib/swarm_sdk/swarm/mcp_configurator.rb +0 -290
- data/lib/swarm_sdk/swarm/swarm_registry_builder.rb +0 -67
- data/lib/swarm_sdk/swarm/tool_configurator.rb +0 -392
- data/lib/swarm_sdk/swarm.rb +0 -973
- data/lib/swarm_sdk/swarm_loader.rb +0 -145
- data/lib/swarm_sdk/swarm_registry.rb +0 -136
- data/lib/swarm_sdk/tools/base.rb +0 -63
- data/lib/swarm_sdk/tools/bash.rb +0 -280
- data/lib/swarm_sdk/tools/clock.rb +0 -46
- data/lib/swarm_sdk/tools/delegate.rb +0 -389
- data/lib/swarm_sdk/tools/document_converters/base_converter.rb +0 -83
- data/lib/swarm_sdk/tools/document_converters/docx_converter.rb +0 -99
- data/lib/swarm_sdk/tools/document_converters/html_converter.rb +0 -101
- data/lib/swarm_sdk/tools/document_converters/pdf_converter.rb +0 -78
- data/lib/swarm_sdk/tools/document_converters/xlsx_converter.rb +0 -194
- data/lib/swarm_sdk/tools/edit.rb +0 -145
- data/lib/swarm_sdk/tools/glob.rb +0 -166
- data/lib/swarm_sdk/tools/grep.rb +0 -235
- data/lib/swarm_sdk/tools/image_extractors/docx_image_extractor.rb +0 -43
- data/lib/swarm_sdk/tools/image_extractors/pdf_image_extractor.rb +0 -167
- data/lib/swarm_sdk/tools/image_formats/tiff_builder.rb +0 -65
- data/lib/swarm_sdk/tools/mcp_tool_stub.rb +0 -198
- data/lib/swarm_sdk/tools/multi_edit.rb +0 -236
- data/lib/swarm_sdk/tools/path_resolver.rb +0 -92
- data/lib/swarm_sdk/tools/read.rb +0 -261
- data/lib/swarm_sdk/tools/registry.rb +0 -205
- data/lib/swarm_sdk/tools/scratchpad/scratchpad_list.rb +0 -117
- data/lib/swarm_sdk/tools/scratchpad/scratchpad_read.rb +0 -97
- data/lib/swarm_sdk/tools/scratchpad/scratchpad_write.rb +0 -108
- data/lib/swarm_sdk/tools/stores/read_tracker.rb +0 -96
- data/lib/swarm_sdk/tools/stores/scratchpad_storage.rb +0 -273
- data/lib/swarm_sdk/tools/stores/storage.rb +0 -142
- data/lib/swarm_sdk/tools/stores/todo_manager.rb +0 -65
- data/lib/swarm_sdk/tools/think.rb +0 -100
- data/lib/swarm_sdk/tools/todo_write.rb +0 -237
- data/lib/swarm_sdk/tools/web_fetch.rb +0 -264
- data/lib/swarm_sdk/tools/write.rb +0 -112
- data/lib/swarm_sdk/transcript_builder.rb +0 -278
- data/lib/swarm_sdk/utils.rb +0 -68
- data/lib/swarm_sdk/validation_result.rb +0 -33
- data/lib/swarm_sdk/version.rb +0 -5
- data/lib/swarm_sdk/workflow/agent_config.rb +0 -95
- data/lib/swarm_sdk/workflow/builder.rb +0 -227
- data/lib/swarm_sdk/workflow/executor.rb +0 -497
- data/lib/swarm_sdk/workflow/node_builder.rb +0 -593
- data/lib/swarm_sdk/workflow/transformer_executor.rb +0 -250
- data/lib/swarm_sdk/workflow.rb +0 -589
- 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
|