swarm_sdk 2.7.14 → 3.0.0.alpha2
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/document_converters/base.rb +84 -0
- data/lib/swarm_sdk/v3/tools/document_converters/docx_converter.rb +120 -0
- data/lib/swarm_sdk/v3/tools/document_converters/pdf_converter.rb +111 -0
- data/lib/swarm_sdk/v3/tools/document_converters/xlsx_converter.rb +128 -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 +213 -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 +88 -149
- 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,705 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module SwarmSDK
|
|
4
|
-
module Agent
|
|
5
|
-
# Builder provides fluent API for configuring agents
|
|
6
|
-
#
|
|
7
|
-
# This class offers a Ruby DSL for defining agents with a clean, readable syntax.
|
|
8
|
-
# It collects configuration and then adds the agent to the swarm.
|
|
9
|
-
#
|
|
10
|
-
# @example
|
|
11
|
-
# agent :backend do
|
|
12
|
-
# model "gpt-5"
|
|
13
|
-
# prompt "You build APIs"
|
|
14
|
-
# tools :Read, :Write, :Bash
|
|
15
|
-
#
|
|
16
|
-
# hook :pre_tool_use, matcher: "Bash" do |ctx|
|
|
17
|
-
# SwarmSDK::Hooks::Result.halt("Blocked!") if dangerous?(ctx)
|
|
18
|
-
# end
|
|
19
|
-
# end
|
|
20
|
-
class Builder
|
|
21
|
-
# Expose default_permissions for Swarm::Builder to set from all_agents
|
|
22
|
-
attr_writer :default_permissions
|
|
23
|
-
|
|
24
|
-
# Expose mcp_servers for tests
|
|
25
|
-
attr_reader :mcp_servers
|
|
26
|
-
|
|
27
|
-
# Get tools list as array for validation
|
|
28
|
-
#
|
|
29
|
-
# @return [Array<Symbol>] List of tools
|
|
30
|
-
def tools_list
|
|
31
|
-
@tools.to_a
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
def initialize(name)
|
|
35
|
-
@name = name
|
|
36
|
-
@description = nil
|
|
37
|
-
@model = "gpt-5"
|
|
38
|
-
@provider = nil
|
|
39
|
-
@base_url = nil
|
|
40
|
-
@api_version = nil
|
|
41
|
-
@context_window = nil
|
|
42
|
-
@system_prompt = nil
|
|
43
|
-
# Use Set for tools to automatically handle duplicates when tools() is called multiple times.
|
|
44
|
-
# This ensures that if someone does: tools :Read; tools :Write; tools :Read
|
|
45
|
-
# the final set contains only [:Read, :Write] without duplicates.
|
|
46
|
-
# We convert to Array in to_definition for compatibility with Agent::Definition.
|
|
47
|
-
@tools = Set.new
|
|
48
|
-
@delegates_to = []
|
|
49
|
-
@directory = "."
|
|
50
|
-
@parameters = {}
|
|
51
|
-
@headers = {}
|
|
52
|
-
@request_timeout = nil
|
|
53
|
-
@turn_timeout = nil
|
|
54
|
-
@mcp_servers = []
|
|
55
|
-
@disable_default_tools = nil # nil = include all default tools
|
|
56
|
-
@bypass_permissions = false
|
|
57
|
-
@coding_agent = nil # nil = not set (will default to false in Definition)
|
|
58
|
-
@assume_model_exists = nil
|
|
59
|
-
@hooks = []
|
|
60
|
-
@permissions_config = {}
|
|
61
|
-
@default_permissions = {} # Set by SwarmBuilder from all_agents
|
|
62
|
-
@memory_config = nil
|
|
63
|
-
@shared_across_delegations = nil # nil = not set (will default to false in Definition)
|
|
64
|
-
@streaming = nil # nil = not set (will use global config default)
|
|
65
|
-
@thinking = nil # nil = not set (extended thinking disabled)
|
|
66
|
-
@disable_environment_info = nil # nil = not set (will default to false in Definition)
|
|
67
|
-
@context_management_config = nil # Context management DSL hooks
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
# Set/get agent model
|
|
71
|
-
def model(model_name = :__not_provided__)
|
|
72
|
-
return @model if model_name == :__not_provided__
|
|
73
|
-
|
|
74
|
-
@model = model_name
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
# Set/get provider
|
|
78
|
-
def provider(provider_name = :__not_provided__)
|
|
79
|
-
return @provider if provider_name == :__not_provided__
|
|
80
|
-
|
|
81
|
-
@provider = provider_name
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
# Set/get base URL
|
|
85
|
-
def base_url(url = :__not_provided__)
|
|
86
|
-
return @base_url if url == :__not_provided__
|
|
87
|
-
|
|
88
|
-
@base_url = url
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
# Set/get API version (OpenAI-compatible providers only)
|
|
92
|
-
def api_version(version = :__not_provided__)
|
|
93
|
-
return @api_version if version == :__not_provided__
|
|
94
|
-
|
|
95
|
-
@api_version = version
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
# Set/get explicit context window override
|
|
99
|
-
def context_window(tokens = :__not_provided__)
|
|
100
|
-
return @context_window if tokens == :__not_provided__
|
|
101
|
-
|
|
102
|
-
@context_window = tokens
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
# Set/get LLM parameters
|
|
106
|
-
def parameters(params = :__not_provided__)
|
|
107
|
-
return @parameters if params == :__not_provided__
|
|
108
|
-
|
|
109
|
-
@parameters = params
|
|
110
|
-
end
|
|
111
|
-
|
|
112
|
-
# Set/get custom HTTP headers
|
|
113
|
-
def headers(header_hash = :__not_provided__)
|
|
114
|
-
return @headers if header_hash == :__not_provided__
|
|
115
|
-
|
|
116
|
-
@headers = header_hash
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
# Set/get request timeout
|
|
120
|
-
def request_timeout(seconds = :__not_provided__)
|
|
121
|
-
return @request_timeout if seconds == :__not_provided__
|
|
122
|
-
|
|
123
|
-
@request_timeout = seconds
|
|
124
|
-
end
|
|
125
|
-
|
|
126
|
-
# Set/get turn timeout
|
|
127
|
-
def turn_timeout(seconds = :__not_provided__)
|
|
128
|
-
return @turn_timeout if seconds == :__not_provided__
|
|
129
|
-
|
|
130
|
-
@turn_timeout = seconds
|
|
131
|
-
end
|
|
132
|
-
|
|
133
|
-
# Add an MCP server configuration
|
|
134
|
-
#
|
|
135
|
-
# @param name [Symbol] Server name
|
|
136
|
-
# @param type [Symbol] Transport type (:stdio, :sse, :http)
|
|
137
|
-
# @param tools [Array<Symbol>, nil] Tool names to expose (nil = discover all tools)
|
|
138
|
-
# @param options [Hash] Transport-specific options
|
|
139
|
-
#
|
|
140
|
-
# @example stdio transport with discovery
|
|
141
|
-
# mcp_server :filesystem, type: :stdio, command: "npx", args: ["-y", "@modelcontextprotocol/server-filesystem"]
|
|
142
|
-
#
|
|
143
|
-
# @example stdio transport with filtered tools (faster boot)
|
|
144
|
-
# mcp_server :codebase, type: :stdio, command: "mcp-server-codebase", tools: [:search_code, :list_files]
|
|
145
|
-
#
|
|
146
|
-
# @example SSE transport
|
|
147
|
-
# mcp_server :web, type: :sse, url: "https://example.com/mcp", headers: { authorization: "Bearer token" }
|
|
148
|
-
#
|
|
149
|
-
# @example HTTP/streamable transport
|
|
150
|
-
# mcp_server :api, type: :http, url: "https://api.example.com/mcp", timeout: 60
|
|
151
|
-
def mcp_server(name, **options)
|
|
152
|
-
server_config = { name: name }.merge(options)
|
|
153
|
-
@mcp_servers << server_config
|
|
154
|
-
end
|
|
155
|
-
|
|
156
|
-
# Disable default tools
|
|
157
|
-
#
|
|
158
|
-
# @param value [Boolean, Array<Symbol>]
|
|
159
|
-
# - true: Disable ALL default tools
|
|
160
|
-
# - Array of symbols: Disable specific tools (e.g., [:Think, :TodoWrite])
|
|
161
|
-
#
|
|
162
|
-
# @example Disable all default tools
|
|
163
|
-
# disable_default_tools true
|
|
164
|
-
#
|
|
165
|
-
# @example Disable specific tools (array)
|
|
166
|
-
# disable_default_tools [:Think, :TodoWrite]
|
|
167
|
-
#
|
|
168
|
-
# @example Disable specific tools (separate arguments)
|
|
169
|
-
# disable_default_tools :Think, :TodoWrite
|
|
170
|
-
def disable_default_tools(*tools)
|
|
171
|
-
# Handle different argument forms
|
|
172
|
-
@disable_default_tools = case tools.size
|
|
173
|
-
when 0
|
|
174
|
-
nil
|
|
175
|
-
when 1
|
|
176
|
-
# Single argument: could be true/false/array
|
|
177
|
-
tools.first
|
|
178
|
-
else
|
|
179
|
-
# Multiple arguments: treat as array of tool names
|
|
180
|
-
tools.map(&:to_sym)
|
|
181
|
-
end
|
|
182
|
-
end
|
|
183
|
-
|
|
184
|
-
# Set bypass_permissions flag
|
|
185
|
-
def bypass_permissions(enabled)
|
|
186
|
-
@bypass_permissions = enabled
|
|
187
|
-
end
|
|
188
|
-
|
|
189
|
-
# Set coding_agent flag
|
|
190
|
-
#
|
|
191
|
-
# When true, includes the base system prompt for coding tasks.
|
|
192
|
-
# When false (default), uses only the custom system prompt.
|
|
193
|
-
#
|
|
194
|
-
# @param enabled [Boolean] Whether to include base coding prompt
|
|
195
|
-
# @return [void]
|
|
196
|
-
#
|
|
197
|
-
# @example
|
|
198
|
-
# coding_agent true # Include base prompt for coding tasks
|
|
199
|
-
def coding_agent(enabled)
|
|
200
|
-
@coding_agent = enabled
|
|
201
|
-
end
|
|
202
|
-
|
|
203
|
-
# Set assume_model_exists flag
|
|
204
|
-
def assume_model_exists(enabled)
|
|
205
|
-
@assume_model_exists = enabled
|
|
206
|
-
end
|
|
207
|
-
|
|
208
|
-
# Set system prompt (matches YAML key)
|
|
209
|
-
def system_prompt(text)
|
|
210
|
-
@system_prompt = text
|
|
211
|
-
end
|
|
212
|
-
|
|
213
|
-
# Set description
|
|
214
|
-
def description(text)
|
|
215
|
-
@description = text
|
|
216
|
-
end
|
|
217
|
-
|
|
218
|
-
# Set or add tools
|
|
219
|
-
#
|
|
220
|
-
# Uses Set internally to automatically deduplicate tool names across multiple calls.
|
|
221
|
-
# This allows calling tools() multiple times without worrying about duplicates.
|
|
222
|
-
#
|
|
223
|
-
# @param tool_names [Array<Symbol>] Tool names to add
|
|
224
|
-
# @param include_default [Boolean] Whether to include default tools (Read, Grep, etc.)
|
|
225
|
-
# @param replace [Boolean] If true, replaces existing tools instead of merging (default: false)
|
|
226
|
-
#
|
|
227
|
-
# @example Basic usage with defaults
|
|
228
|
-
# tools :Grep, :Read # include_default: true is implicit
|
|
229
|
-
#
|
|
230
|
-
# @example Explicit tools only, no defaults
|
|
231
|
-
# tools :Grep, :Read, include_default: false
|
|
232
|
-
#
|
|
233
|
-
# @example Multiple calls (cumulative, automatic deduplication)
|
|
234
|
-
# tools :Read
|
|
235
|
-
# tools :Write, :Edit # @tools now contains Set[:Read, :Write, :Edit]
|
|
236
|
-
# tools :Read # Still Set[:Read, :Write, :Edit] - no duplicate
|
|
237
|
-
#
|
|
238
|
-
# @example Replace tools (for markdown overrides)
|
|
239
|
-
# tools :Read, :Write, replace: true # Replaces all existing tools
|
|
240
|
-
def tools(*tool_names, include_default: true, replace: false)
|
|
241
|
-
@tools = Set.new if replace
|
|
242
|
-
@tools.merge(tool_names.map(&:to_sym))
|
|
243
|
-
# When include_default is false, disable all default tools
|
|
244
|
-
@disable_default_tools = true unless include_default
|
|
245
|
-
end
|
|
246
|
-
|
|
247
|
-
# Add tools from all_agents configuration
|
|
248
|
-
#
|
|
249
|
-
# Used by Swarm::Builder to add all_agents tools.
|
|
250
|
-
# Since we use Set, order doesn't matter and duplicates are handled automatically.
|
|
251
|
-
#
|
|
252
|
-
# @param tool_names [Array] Tool names to add
|
|
253
|
-
# @return [void]
|
|
254
|
-
def prepend_tools(*tool_names)
|
|
255
|
-
@tools.merge(tool_names.map(&:to_sym))
|
|
256
|
-
end
|
|
257
|
-
|
|
258
|
-
# Set directory
|
|
259
|
-
def directory(dir)
|
|
260
|
-
@directory = dir
|
|
261
|
-
end
|
|
262
|
-
|
|
263
|
-
# Set delegation targets
|
|
264
|
-
#
|
|
265
|
-
# Supports multiple formats for flexibility:
|
|
266
|
-
#
|
|
267
|
-
# @example Simple array (backwards compatible)
|
|
268
|
-
# delegates_to :frontend, :backend, :qa
|
|
269
|
-
#
|
|
270
|
-
# @example Hash with custom tool names
|
|
271
|
-
# delegates_to frontend: "AskFrontend",
|
|
272
|
-
# backend: "GetBackendHelp",
|
|
273
|
-
# qa: "RequestReview"
|
|
274
|
-
#
|
|
275
|
-
# @example Mixed - some auto, some custom
|
|
276
|
-
# delegates_to :frontend,
|
|
277
|
-
# backend: "GetBackendHelp",
|
|
278
|
-
# :qa
|
|
279
|
-
#
|
|
280
|
-
# @example With delegation options (preserve_context controls context persistence)
|
|
281
|
-
# delegates_to :frontend,
|
|
282
|
-
# { agent: :backend, tool_name: "AskBackend", preserve_context: false }
|
|
283
|
-
#
|
|
284
|
-
# @param agent_names_and_options [Array<Symbol, Hash>] Agent names and/or hash with custom tool names
|
|
285
|
-
# @return [void]
|
|
286
|
-
def delegates_to(*agent_names_and_options)
|
|
287
|
-
agent_names_and_options.each do |item|
|
|
288
|
-
case item
|
|
289
|
-
when Symbol, String
|
|
290
|
-
# Simple format: :frontend
|
|
291
|
-
@delegates_to << { agent: item.to_sym, tool_name: nil, preserve_context: true }
|
|
292
|
-
when Hash
|
|
293
|
-
if item.key?(:agent)
|
|
294
|
-
# Full config format: { agent: :backend, tool_name: "Custom", preserve_context: false }
|
|
295
|
-
@delegates_to << {
|
|
296
|
-
agent: item[:agent].to_sym,
|
|
297
|
-
tool_name: item[:tool_name],
|
|
298
|
-
preserve_context: item.fetch(:preserve_context, true),
|
|
299
|
-
}
|
|
300
|
-
else
|
|
301
|
-
# Hash format: { frontend: "AskFrontend", backend: nil }
|
|
302
|
-
item.each do |agent, tool_name|
|
|
303
|
-
@delegates_to << { agent: agent.to_sym, tool_name: tool_name, preserve_context: true }
|
|
304
|
-
end
|
|
305
|
-
end
|
|
306
|
-
else
|
|
307
|
-
raise ConfigurationError, "delegates_to accepts Symbols or Hashes, got #{item.class}"
|
|
308
|
-
end
|
|
309
|
-
end
|
|
310
|
-
end
|
|
311
|
-
|
|
312
|
-
# Add a hook (Ruby block OR shell command)
|
|
313
|
-
#
|
|
314
|
-
# @example Ruby block
|
|
315
|
-
# hook :pre_tool_use, matcher: "Bash" do |ctx|
|
|
316
|
-
# HookResult.halt("Blocked") if dangerous?(ctx)
|
|
317
|
-
# end
|
|
318
|
-
#
|
|
319
|
-
# @example Shell command
|
|
320
|
-
# hook :pre_tool_use, matcher: "Bash", command: "validate.sh"
|
|
321
|
-
def hook(event, matcher: nil, command: nil, timeout: nil, &block)
|
|
322
|
-
@hooks << {
|
|
323
|
-
event: event,
|
|
324
|
-
matcher: matcher,
|
|
325
|
-
command: command,
|
|
326
|
-
timeout: timeout,
|
|
327
|
-
block: block,
|
|
328
|
-
}
|
|
329
|
-
end
|
|
330
|
-
|
|
331
|
-
# Configure permissions for this agent
|
|
332
|
-
#
|
|
333
|
-
# @example
|
|
334
|
-
# permissions do
|
|
335
|
-
# Write.allow_paths "backend/**/*"
|
|
336
|
-
# Write.deny_paths "backend/secrets/**"
|
|
337
|
-
# end
|
|
338
|
-
def permissions(&block)
|
|
339
|
-
@permissions_config = PermissionsBuilder.build(&block)
|
|
340
|
-
end
|
|
341
|
-
|
|
342
|
-
# Configure delegation isolation mode
|
|
343
|
-
#
|
|
344
|
-
# @param enabled [Boolean] If true, allows sharing instances across delegations (old behavior)
|
|
345
|
-
# If false (default), creates isolated instances per delegation
|
|
346
|
-
# @return [self] Returns self for method chaining
|
|
347
|
-
#
|
|
348
|
-
# @example
|
|
349
|
-
# shared_across_delegations true # Allow sharing (old behavior)
|
|
350
|
-
def shared_across_delegations(enabled)
|
|
351
|
-
@shared_across_delegations = enabled
|
|
352
|
-
self
|
|
353
|
-
end
|
|
354
|
-
|
|
355
|
-
# Enable or disable streaming for LLM API responses
|
|
356
|
-
#
|
|
357
|
-
# @param value [Boolean] If true (default), enables streaming; if false, disables it
|
|
358
|
-
# @return [self] Returns self for method chaining
|
|
359
|
-
#
|
|
360
|
-
# @example Enable streaming (default)
|
|
361
|
-
# streaming true
|
|
362
|
-
#
|
|
363
|
-
# @example Disable streaming
|
|
364
|
-
# streaming false
|
|
365
|
-
def streaming(value = true)
|
|
366
|
-
@streaming = value
|
|
367
|
-
self
|
|
368
|
-
end
|
|
369
|
-
|
|
370
|
-
# Check if streaming has been explicitly set
|
|
371
|
-
#
|
|
372
|
-
# @return [Boolean] true if streaming was explicitly set, false otherwise
|
|
373
|
-
def streaming_set?
|
|
374
|
-
!@streaming.nil?
|
|
375
|
-
end
|
|
376
|
-
|
|
377
|
-
# Configure extended thinking for this agent
|
|
378
|
-
#
|
|
379
|
-
# Extended thinking allows models to reason through complex problems before responding.
|
|
380
|
-
# For Anthropic models, specify a budget (token count). For OpenAI models, specify effort.
|
|
381
|
-
# Both can be specified for cross-provider compatibility.
|
|
382
|
-
#
|
|
383
|
-
# @param effort [Symbol, String, nil] Reasoning effort level (:low, :medium, :high) — used by OpenAI
|
|
384
|
-
# @param budget [Integer, nil] Token budget for thinking — used by Anthropic
|
|
385
|
-
# @return [self] Returns self for method chaining
|
|
386
|
-
#
|
|
387
|
-
# @example Anthropic thinking with budget
|
|
388
|
-
# thinking budget: 10_000
|
|
389
|
-
#
|
|
390
|
-
# @example OpenAI reasoning effort
|
|
391
|
-
# thinking effort: :high
|
|
392
|
-
#
|
|
393
|
-
# @example Cross-provider (both)
|
|
394
|
-
# thinking effort: :high, budget: 10_000
|
|
395
|
-
def thinking(effort: nil, budget: nil)
|
|
396
|
-
raise ArgumentError, "thinking requires :effort or :budget" if effort.nil? && budget.nil?
|
|
397
|
-
|
|
398
|
-
@thinking = { effort: effort, budget: budget }.compact
|
|
399
|
-
self
|
|
400
|
-
end
|
|
401
|
-
|
|
402
|
-
# Check if thinking has been explicitly set
|
|
403
|
-
#
|
|
404
|
-
# @return [Boolean] true if thinking was explicitly configured
|
|
405
|
-
def thinking_set?
|
|
406
|
-
!@thinking.nil?
|
|
407
|
-
end
|
|
408
|
-
|
|
409
|
-
# Configure context management handlers
|
|
410
|
-
#
|
|
411
|
-
# Define custom handlers for context warning thresholds (60%, 80%, 90%).
|
|
412
|
-
# Handlers receive a rich context object with message manipulation methods.
|
|
413
|
-
# When a custom handler is registered, automatic compression is disabled
|
|
414
|
-
# for that threshold, giving full control to the handler.
|
|
415
|
-
#
|
|
416
|
-
# @yield Context management DSL block
|
|
417
|
-
# @return [void]
|
|
418
|
-
#
|
|
419
|
-
# @example Basic compression at 60%
|
|
420
|
-
# context_management do
|
|
421
|
-
# on :warning_60 do |ctx|
|
|
422
|
-
# ctx.compress_tool_results(keep_recent: 10)
|
|
423
|
-
# end
|
|
424
|
-
# end
|
|
425
|
-
#
|
|
426
|
-
# @example Multiple thresholds with different strategies
|
|
427
|
-
# context_management do
|
|
428
|
-
# on :warning_60 do |ctx|
|
|
429
|
-
# ctx.compress_tool_results(keep_recent: 15, truncate_to: 500)
|
|
430
|
-
# end
|
|
431
|
-
#
|
|
432
|
-
# on :warning_80 do |ctx|
|
|
433
|
-
# ctx.prune_old_messages(keep_recent: 30)
|
|
434
|
-
# ctx.compress_tool_results(keep_recent: 5, truncate_to: 200)
|
|
435
|
-
# end
|
|
436
|
-
#
|
|
437
|
-
# on :warning_90 do |ctx|
|
|
438
|
-
# ctx.log_action("emergency_pruning", remaining: ctx.tokens_remaining)
|
|
439
|
-
# ctx.prune_old_messages(keep_recent: 15)
|
|
440
|
-
# end
|
|
441
|
-
# end
|
|
442
|
-
#
|
|
443
|
-
# @example Conditional logic based on metrics
|
|
444
|
-
# context_management do
|
|
445
|
-
# on :warning_80 do |ctx|
|
|
446
|
-
# if ctx.usage_percentage > 85
|
|
447
|
-
# ctx.prune_old_messages(keep_recent: 10)
|
|
448
|
-
# else
|
|
449
|
-
# ctx.compress_tool_results(keep_recent: 5)
|
|
450
|
-
# end
|
|
451
|
-
# end
|
|
452
|
-
# end
|
|
453
|
-
def context_management(&block)
|
|
454
|
-
builder = ContextManagement::Builder.new
|
|
455
|
-
builder.instance_eval(&block)
|
|
456
|
-
@context_management_config = builder.build
|
|
457
|
-
end
|
|
458
|
-
|
|
459
|
-
# Set permissions directly from hash (for YAML translation)
|
|
460
|
-
#
|
|
461
|
-
# This is intentionally separate from permissions() to keep the DSL clean.
|
|
462
|
-
# Called by Configuration when translating YAML permissions.
|
|
463
|
-
#
|
|
464
|
-
# @param hash [Hash] Permissions configuration hash
|
|
465
|
-
# @return [void]
|
|
466
|
-
def permissions_hash=(hash)
|
|
467
|
-
@permissions_config = hash || {}
|
|
468
|
-
end
|
|
469
|
-
|
|
470
|
-
# Check if model has been explicitly set (not default)
|
|
471
|
-
#
|
|
472
|
-
# Used by Swarm::Builder to determine if all_agents model should apply.
|
|
473
|
-
#
|
|
474
|
-
# @return [Boolean] true if model was explicitly set
|
|
475
|
-
def model_set?
|
|
476
|
-
@model != "gpt-5"
|
|
477
|
-
end
|
|
478
|
-
|
|
479
|
-
# Check if provider has been explicitly set
|
|
480
|
-
#
|
|
481
|
-
# Used by Swarm::Builder to determine if all_agents provider should apply.
|
|
482
|
-
#
|
|
483
|
-
# @return [Boolean] true if provider was explicitly set
|
|
484
|
-
def provider_set?
|
|
485
|
-
!@provider.nil?
|
|
486
|
-
end
|
|
487
|
-
|
|
488
|
-
# Check if base_url has been explicitly set
|
|
489
|
-
#
|
|
490
|
-
# Used by Swarm::Builder to determine if all_agents base_url should apply.
|
|
491
|
-
#
|
|
492
|
-
# @return [Boolean] true if base_url was explicitly set
|
|
493
|
-
def base_url_set?
|
|
494
|
-
!@base_url.nil?
|
|
495
|
-
end
|
|
496
|
-
|
|
497
|
-
# Check if api_version has been explicitly set
|
|
498
|
-
#
|
|
499
|
-
# Used by Swarm::Builder to determine if all_agents api_version should apply.
|
|
500
|
-
#
|
|
501
|
-
# @return [Boolean] true if api_version was explicitly set
|
|
502
|
-
def api_version_set?
|
|
503
|
-
!@api_version.nil?
|
|
504
|
-
end
|
|
505
|
-
|
|
506
|
-
# Check if request_timeout has been explicitly set
|
|
507
|
-
#
|
|
508
|
-
# Used by Swarm::Builder to determine if all_agents request_timeout should apply.
|
|
509
|
-
#
|
|
510
|
-
# @return [Boolean] true if request_timeout was explicitly set
|
|
511
|
-
def request_timeout_set?
|
|
512
|
-
!@request_timeout.nil?
|
|
513
|
-
end
|
|
514
|
-
|
|
515
|
-
# Check if turn_timeout has been explicitly set
|
|
516
|
-
#
|
|
517
|
-
# Used by Swarm::Builder to determine if all_agents turn_timeout should apply.
|
|
518
|
-
#
|
|
519
|
-
# @return [Boolean] true if turn_timeout was explicitly set
|
|
520
|
-
def turn_timeout_set?
|
|
521
|
-
!@turn_timeout.nil?
|
|
522
|
-
end
|
|
523
|
-
|
|
524
|
-
# Check if coding_agent has been explicitly set
|
|
525
|
-
#
|
|
526
|
-
# Used by Swarm::Builder to determine if all_agents coding_agent should apply.
|
|
527
|
-
#
|
|
528
|
-
# @return [Boolean] true if coding_agent was explicitly set
|
|
529
|
-
def coding_agent_set?
|
|
530
|
-
!@coding_agent.nil?
|
|
531
|
-
end
|
|
532
|
-
|
|
533
|
-
# Disable environment info (date, platform, OS, working directory) in system prompt
|
|
534
|
-
#
|
|
535
|
-
# When true, omits the environment information section from the agent's system prompt.
|
|
536
|
-
# Defaults to false if not set.
|
|
537
|
-
#
|
|
538
|
-
# @param enabled [Boolean] Whether to disable environment info
|
|
539
|
-
# @return [void]
|
|
540
|
-
#
|
|
541
|
-
# @example
|
|
542
|
-
# disable_environment_info true # Omit environment info from prompt
|
|
543
|
-
def disable_environment_info(enabled)
|
|
544
|
-
@disable_environment_info = enabled
|
|
545
|
-
end
|
|
546
|
-
|
|
547
|
-
# Check if disable_environment_info has been explicitly set
|
|
548
|
-
#
|
|
549
|
-
# Used by Swarm::Builder to determine if all_agents disable_environment_info should apply.
|
|
550
|
-
#
|
|
551
|
-
# @return [Boolean] true if disable_environment_info was explicitly set
|
|
552
|
-
def disable_environment_info_set?
|
|
553
|
-
!@disable_environment_info.nil?
|
|
554
|
-
end
|
|
555
|
-
|
|
556
|
-
# Check if parameters have been set
|
|
557
|
-
#
|
|
558
|
-
# Used by Swarm::Builder for merging all_agents parameters.
|
|
559
|
-
#
|
|
560
|
-
# @return [Boolean] true if parameters were set
|
|
561
|
-
def parameters_set?
|
|
562
|
-
@parameters.any?
|
|
563
|
-
end
|
|
564
|
-
|
|
565
|
-
# Check if headers have been set
|
|
566
|
-
#
|
|
567
|
-
# Used by Swarm::Builder for merging all_agents headers.
|
|
568
|
-
#
|
|
569
|
-
# @return [Boolean] true if headers were set
|
|
570
|
-
def headers_set?
|
|
571
|
-
@headers.any?
|
|
572
|
-
end
|
|
573
|
-
|
|
574
|
-
# Build and return an Agent::Definition
|
|
575
|
-
#
|
|
576
|
-
# This method converts the builder's configuration into a validated
|
|
577
|
-
# Agent::Definition object. The caller is responsible for adding it to a swarm.
|
|
578
|
-
#
|
|
579
|
-
# Converts @tools Set to Array here because Agent::Definition expects an array.
|
|
580
|
-
# The Set was only used during building to handle duplicates efficiently.
|
|
581
|
-
#
|
|
582
|
-
# @return [Agent::Definition] Fully configured and validated agent definition
|
|
583
|
-
def to_definition
|
|
584
|
-
agent_config = {
|
|
585
|
-
description: @description || "Agent #{@name}",
|
|
586
|
-
model: @model,
|
|
587
|
-
system_prompt: @system_prompt,
|
|
588
|
-
tools: @tools.to_a, # Convert Set to Array for Agent::Definition compatibility
|
|
589
|
-
delegates_to: @delegates_to,
|
|
590
|
-
directory: @directory,
|
|
591
|
-
}
|
|
592
|
-
|
|
593
|
-
# Add optional fields
|
|
594
|
-
agent_config[:provider] = @provider if @provider
|
|
595
|
-
agent_config[:base_url] = @base_url if @base_url
|
|
596
|
-
agent_config[:api_version] = @api_version if @api_version
|
|
597
|
-
agent_config[:context_window] = @context_window if @context_window
|
|
598
|
-
agent_config[:parameters] = @parameters if @parameters.any?
|
|
599
|
-
agent_config[:headers] = @headers if @headers.any?
|
|
600
|
-
agent_config[:request_timeout] = @request_timeout if @request_timeout
|
|
601
|
-
agent_config[:turn_timeout] = @turn_timeout if @turn_timeout
|
|
602
|
-
agent_config[:mcp_servers] = @mcp_servers if @mcp_servers.any?
|
|
603
|
-
agent_config[:disable_default_tools] = @disable_default_tools unless @disable_default_tools.nil?
|
|
604
|
-
agent_config[:bypass_permissions] = @bypass_permissions
|
|
605
|
-
agent_config[:coding_agent] = @coding_agent
|
|
606
|
-
agent_config[:assume_model_exists] = @assume_model_exists unless @assume_model_exists.nil?
|
|
607
|
-
agent_config[:permissions] = @permissions_config if @permissions_config.any?
|
|
608
|
-
agent_config[:default_permissions] = @default_permissions if @default_permissions.any?
|
|
609
|
-
agent_config[:memory] = @memory_config if @memory_config
|
|
610
|
-
agent_config[:shared_across_delegations] = @shared_across_delegations unless @shared_across_delegations.nil?
|
|
611
|
-
agent_config[:streaming] = @streaming unless @streaming.nil?
|
|
612
|
-
agent_config[:thinking] = @thinking if @thinking
|
|
613
|
-
agent_config[:disable_environment_info] = @disable_environment_info unless @disable_environment_info.nil?
|
|
614
|
-
|
|
615
|
-
# Convert DSL hooks to HookDefinition format
|
|
616
|
-
agent_config[:hooks] = convert_hooks_to_definitions if @hooks.any?
|
|
617
|
-
|
|
618
|
-
# Merge context management hooks into agent hooks
|
|
619
|
-
if @context_management_config
|
|
620
|
-
agent_config[:hooks] ||= {}
|
|
621
|
-
agent_config[:hooks][:context_warning] ||= []
|
|
622
|
-
agent_config[:hooks][:context_warning].concat(@context_management_config)
|
|
623
|
-
end
|
|
624
|
-
|
|
625
|
-
Agent::Definition.new(@name, agent_config)
|
|
626
|
-
end
|
|
627
|
-
|
|
628
|
-
private
|
|
629
|
-
|
|
630
|
-
# Convert DSL hooks to HookDefinition objects for Agent::Definition
|
|
631
|
-
#
|
|
632
|
-
# This converts the builder's hook configuration (Ruby blocks and shell commands)
|
|
633
|
-
# into HookDefinition objects that will be applied during agent initialization.
|
|
634
|
-
#
|
|
635
|
-
# @return [Hash] Hooks grouped by event type { event: [HookDefinition, ...] }
|
|
636
|
-
def convert_hooks_to_definitions
|
|
637
|
-
result = Hash.new { |h, k| h[k] = [] }
|
|
638
|
-
|
|
639
|
-
@hooks.each do |hook_config|
|
|
640
|
-
event = hook_config[:event]
|
|
641
|
-
|
|
642
|
-
# Create HookDefinition with proc or command
|
|
643
|
-
if hook_config[:block]
|
|
644
|
-
# Ruby block hook
|
|
645
|
-
hook_def = Hooks::Definition.new(
|
|
646
|
-
event: event,
|
|
647
|
-
matcher: hook_config[:matcher],
|
|
648
|
-
priority: 0,
|
|
649
|
-
proc: hook_config[:block],
|
|
650
|
-
)
|
|
651
|
-
elsif hook_config[:command]
|
|
652
|
-
# Shell command hook - wrap in a block that calls ShellExecutor
|
|
653
|
-
hook_def = Hooks::Definition.new(
|
|
654
|
-
event: event,
|
|
655
|
-
matcher: hook_config[:matcher],
|
|
656
|
-
priority: 0,
|
|
657
|
-
proc: create_shell_hook_proc(hook_config),
|
|
658
|
-
)
|
|
659
|
-
else
|
|
660
|
-
raise ConfigurationError, "Hook must have either :block or :command"
|
|
661
|
-
end
|
|
662
|
-
|
|
663
|
-
result[event] << hook_def
|
|
664
|
-
end
|
|
665
|
-
|
|
666
|
-
result
|
|
667
|
-
end
|
|
668
|
-
|
|
669
|
-
# Create a proc that executes a shell command hook
|
|
670
|
-
def create_shell_hook_proc(config)
|
|
671
|
-
command = config[:command]
|
|
672
|
-
timeout = config[:timeout] || 60
|
|
673
|
-
agent_name = @name
|
|
674
|
-
|
|
675
|
-
proc do |context|
|
|
676
|
-
input_json = build_hook_input(context, config[:event])
|
|
677
|
-
Hooks::ShellExecutor.execute(
|
|
678
|
-
command: command,
|
|
679
|
-
input_json: input_json,
|
|
680
|
-
timeout: timeout,
|
|
681
|
-
agent_name: agent_name,
|
|
682
|
-
swarm_name: context.swarm&.name,
|
|
683
|
-
event: config[:event],
|
|
684
|
-
)
|
|
685
|
-
end
|
|
686
|
-
end
|
|
687
|
-
|
|
688
|
-
# Build hook input JSON for shell command hooks
|
|
689
|
-
def build_hook_input(context, event)
|
|
690
|
-
base = { event: event.to_s, agent: @name.to_s }
|
|
691
|
-
|
|
692
|
-
case event
|
|
693
|
-
when :pre_tool_use
|
|
694
|
-
base.merge(tool: context.tool_call.name, parameters: context.tool_call.parameters)
|
|
695
|
-
when :post_tool_use
|
|
696
|
-
base.merge(result: context.tool_result.content, success: context.tool_result.success?)
|
|
697
|
-
when :user_prompt
|
|
698
|
-
base.merge(prompt: context.metadata[:prompt])
|
|
699
|
-
else
|
|
700
|
-
base
|
|
701
|
-
end
|
|
702
|
-
end
|
|
703
|
-
end
|
|
704
|
-
end
|
|
705
|
-
end
|