swarm_memory 2.1.5 → 2.1.6
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_memory/version.rb +1 -1
- metadata +5 -184
- data/lib/claude_swarm/base_executor.rb +0 -133
- data/lib/claude_swarm/claude_code_executor.rb +0 -349
- data/lib/claude_swarm/claude_mcp_server.rb +0 -78
- data/lib/claude_swarm/cli.rb +0 -697
- data/lib/claude_swarm/commands/ps.rb +0 -215
- data/lib/claude_swarm/commands/show.rb +0 -139
- data/lib/claude_swarm/configuration.rb +0 -373
- data/lib/claude_swarm/hooks/session_start_hook.rb +0 -42
- data/lib/claude_swarm/json_handler.rb +0 -91
- data/lib/claude_swarm/mcp_generator.rb +0 -230
- data/lib/claude_swarm/openai/chat_completion.rb +0 -256
- data/lib/claude_swarm/openai/executor.rb +0 -256
- data/lib/claude_swarm/openai/responses.rb +0 -319
- data/lib/claude_swarm/orchestrator.rb +0 -878
- data/lib/claude_swarm/process_tracker.rb +0 -78
- data/lib/claude_swarm/session_cost_calculator.rb +0 -209
- data/lib/claude_swarm/session_path.rb +0 -42
- data/lib/claude_swarm/settings_generator.rb +0 -77
- data/lib/claude_swarm/system_utils.rb +0 -46
- data/lib/claude_swarm/templates/generation_prompt.md.erb +0 -230
- data/lib/claude_swarm/tools/reset_session_tool.rb +0 -24
- data/lib/claude_swarm/tools/session_info_tool.rb +0 -24
- data/lib/claude_swarm/tools/task_tool.rb +0 -63
- data/lib/claude_swarm/version.rb +0 -5
- data/lib/claude_swarm/worktree_manager.rb +0 -475
- data/lib/claude_swarm/yaml_loader.rb +0 -22
- data/lib/claude_swarm.rb +0 -67
- data/lib/swarm_cli/cli.rb +0 -201
- data/lib/swarm_cli/command_registry.rb +0 -61
- data/lib/swarm_cli/commands/mcp_serve.rb +0 -130
- data/lib/swarm_cli/commands/mcp_tools.rb +0 -148
- data/lib/swarm_cli/commands/migrate.rb +0 -55
- data/lib/swarm_cli/commands/run.rb +0 -173
- data/lib/swarm_cli/config_loader.rb +0 -98
- data/lib/swarm_cli/formatters/human_formatter.rb +0 -781
- data/lib/swarm_cli/formatters/json_formatter.rb +0 -51
- data/lib/swarm_cli/interactive_repl.rb +0 -924
- data/lib/swarm_cli/mcp_serve_options.rb +0 -44
- data/lib/swarm_cli/mcp_tools_options.rb +0 -59
- data/lib/swarm_cli/migrate_options.rb +0 -54
- data/lib/swarm_cli/migrator.rb +0 -132
- data/lib/swarm_cli/options.rb +0 -151
- data/lib/swarm_cli/ui/components/agent_badge.rb +0 -33
- data/lib/swarm_cli/ui/components/content_block.rb +0 -120
- data/lib/swarm_cli/ui/components/divider.rb +0 -57
- data/lib/swarm_cli/ui/components/panel.rb +0 -62
- data/lib/swarm_cli/ui/components/usage_stats.rb +0 -70
- data/lib/swarm_cli/ui/formatters/cost.rb +0 -49
- data/lib/swarm_cli/ui/formatters/number.rb +0 -58
- data/lib/swarm_cli/ui/formatters/text.rb +0 -77
- data/lib/swarm_cli/ui/formatters/time.rb +0 -73
- data/lib/swarm_cli/ui/icons.rb +0 -36
- data/lib/swarm_cli/ui/renderers/event_renderer.rb +0 -188
- data/lib/swarm_cli/ui/state/agent_color_cache.rb +0 -45
- data/lib/swarm_cli/ui/state/depth_tracker.rb +0 -40
- data/lib/swarm_cli/ui/state/spinner_manager.rb +0 -170
- data/lib/swarm_cli/ui/state/usage_tracker.rb +0 -62
- data/lib/swarm_cli/version.rb +0 -5
- data/lib/swarm_cli.rb +0 -46
- data/lib/swarm_sdk/agent/RETRY_LOGIC.md +0 -127
- data/lib/swarm_sdk/agent/builder.rb +0 -552
- data/lib/swarm_sdk/agent/chat.rb +0 -774
- data/lib/swarm_sdk/agent/chat_helpers/context_tracker.rb +0 -268
- 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 -78
- data/lib/swarm_sdk/agent/chat_helpers/llm_configuration.rb +0 -233
- 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 -136
- data/lib/swarm_sdk/agent/chat_helpers/system_reminders.rb +0 -79
- data/lib/swarm_sdk/agent/chat_helpers/token_tracking.rb +0 -98
- data/lib/swarm_sdk/agent/context.rb +0 -116
- data/lib/swarm_sdk/agent/context_manager.rb +0 -315
- data/lib/swarm_sdk/agent/definition.rb +0 -477
- data/lib/swarm_sdk/agent/llm_instrumentation_middleware.rb +0 -182
- data/lib/swarm_sdk/agent/system_prompt_builder.rb +0 -161
- data/lib/swarm_sdk/builders/base_builder.rb +0 -409
- data/lib/swarm_sdk/claude_code_agent_adapter.rb +0 -205
- data/lib/swarm_sdk/concerns/cleanupable.rb +0 -39
- data/lib/swarm_sdk/concerns/snapshotable.rb +0 -67
- data/lib/swarm_sdk/concerns/validatable.rb +0 -55
- data/lib/swarm_sdk/configuration/parser.rb +0 -353
- data/lib/swarm_sdk/configuration/translator.rb +0 -255
- data/lib/swarm_sdk/configuration.rb +0 -135
- data/lib/swarm_sdk/context_compactor/metrics.rb +0 -147
- data/lib/swarm_sdk/context_compactor/token_counter.rb +0 -106
- 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/defaults.rb +0 -196
- 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 -255
- 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 -1
- data/lib/swarm_sdk/models.rb +0 -120
- 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 -236
- 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 -117
- data/lib/swarm_sdk/restore_result.rb +0 -65
- data/lib/swarm_sdk/result.rb +0 -123
- 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 -683
- data/lib/swarm_sdk/swarm/all_agents_builder.rb +0 -167
- data/lib/swarm_sdk/swarm/builder.rb +0 -249
- data/lib/swarm_sdk/swarm/executor.rb +0 -213
- data/lib/swarm_sdk/swarm/hook_triggers.rb +0 -150
- data/lib/swarm_sdk/swarm/logging_callbacks.rb +0 -340
- data/lib/swarm_sdk/swarm/mcp_configurator.rb +0 -154
- data/lib/swarm_sdk/swarm/swarm_registry_builder.rb +0 -67
- data/lib/swarm_sdk/swarm/tool_configurator.rb +0 -358
- data/lib/swarm_sdk/swarm.rb +0 -717
- data/lib/swarm_sdk/swarm_loader.rb +0 -145
- data/lib/swarm_sdk/swarm_registry.rb +0 -136
- data/lib/swarm_sdk/tools/bash.rb +0 -282
- data/lib/swarm_sdk/tools/clock.rb +0 -44
- data/lib/swarm_sdk/tools/delegate.rb +0 -267
- 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 -163
- data/lib/swarm_sdk/tools/image_formats/tiff_builder.rb +0 -65
- 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 -272
- 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 -98
- data/lib/swarm_sdk/tools/todo_write.rb +0 -235
- data/lib/swarm_sdk/tools/web_fetch.rb +0 -262
- data/lib/swarm_sdk/tools/write.rb +0 -112
- 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 -79
- data/lib/swarm_sdk/workflow/builder.rb +0 -143
- data/lib/swarm_sdk/workflow/executor.rb +0 -497
- data/lib/swarm_sdk/workflow/node_builder.rb +0 -555
- data/lib/swarm_sdk/workflow/transformer_executor.rb +0 -249
- data/lib/swarm_sdk/workflow.rb +0 -554
- data/lib/swarm_sdk.rb +0 -524
|
@@ -1,161 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module SwarmSDK
|
|
4
|
-
module Agent
|
|
5
|
-
# Builds system prompts for agents
|
|
6
|
-
#
|
|
7
|
-
# This class encapsulates all system prompt construction logic, including:
|
|
8
|
-
# - Base system prompt rendering (for coding agents)
|
|
9
|
-
# - Non-coding base prompt rendering
|
|
10
|
-
# - Plugin prompt contribution collection
|
|
11
|
-
# - Combining base and custom prompts
|
|
12
|
-
#
|
|
13
|
-
# ## Safety Note for SwarmMemory Integration
|
|
14
|
-
#
|
|
15
|
-
# This is an INTERNAL helper that receives Definition attributes as input.
|
|
16
|
-
# Definition remains the single source of truth with all instance variables.
|
|
17
|
-
# SwarmMemory uses `agent_definition.instance_eval { binding }` for ERB templating,
|
|
18
|
-
# which requires all properties to be on Definition object. This helper is safe
|
|
19
|
-
# because it doesn't affect Definition's structure - it only extracts logic.
|
|
20
|
-
class SystemPromptBuilder
|
|
21
|
-
BASE_SYSTEM_PROMPT_PATH = File.expand_path("../prompts/base_system_prompt.md.erb", __dir__)
|
|
22
|
-
|
|
23
|
-
class << self
|
|
24
|
-
# Build the complete system prompt for an agent
|
|
25
|
-
#
|
|
26
|
-
# @param custom_prompt [String, nil] Custom system prompt from configuration
|
|
27
|
-
# @param coding_agent [Boolean] Whether agent is configured for coding tasks
|
|
28
|
-
# @param disable_default_tools [Boolean, Array, nil] Default tools disable configuration
|
|
29
|
-
# @param directory [String] Agent's working directory
|
|
30
|
-
# @param definition [Definition] Full definition for plugin contributions
|
|
31
|
-
# @return [String] Complete system prompt
|
|
32
|
-
def build(custom_prompt:, coding_agent:, disable_default_tools:, directory:, definition:)
|
|
33
|
-
new(
|
|
34
|
-
custom_prompt: custom_prompt,
|
|
35
|
-
coding_agent: coding_agent,
|
|
36
|
-
disable_default_tools: disable_default_tools,
|
|
37
|
-
directory: directory,
|
|
38
|
-
definition: definition,
|
|
39
|
-
).build
|
|
40
|
-
end
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
def initialize(custom_prompt:, coding_agent:, disable_default_tools:, directory:, definition:)
|
|
44
|
-
@custom_prompt = custom_prompt
|
|
45
|
-
@coding_agent = coding_agent
|
|
46
|
-
@disable_default_tools = disable_default_tools
|
|
47
|
-
@directory = directory
|
|
48
|
-
@definition = definition
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
def build
|
|
52
|
-
prompt = base_prompt_section
|
|
53
|
-
prompt = append_plugin_contributions(prompt)
|
|
54
|
-
prompt
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
private
|
|
58
|
-
|
|
59
|
-
def base_prompt_section
|
|
60
|
-
if @coding_agent
|
|
61
|
-
build_coding_agent_prompt
|
|
62
|
-
elsif default_tools_enabled?
|
|
63
|
-
build_non_coding_agent_prompt
|
|
64
|
-
else
|
|
65
|
-
(@custom_prompt || "").to_s
|
|
66
|
-
end
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
def build_coding_agent_prompt
|
|
70
|
-
rendered_base = render_base_system_prompt
|
|
71
|
-
|
|
72
|
-
if @custom_prompt && !@custom_prompt.strip.empty?
|
|
73
|
-
"#{rendered_base}\n\n#{@custom_prompt}"
|
|
74
|
-
else
|
|
75
|
-
rendered_base
|
|
76
|
-
end
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
def build_non_coding_agent_prompt
|
|
80
|
-
non_coding_base = render_non_coding_base_prompt
|
|
81
|
-
|
|
82
|
-
if @custom_prompt && !@custom_prompt.strip.empty?
|
|
83
|
-
"#{non_coding_base}\n\n#{@custom_prompt}"
|
|
84
|
-
else
|
|
85
|
-
non_coding_base
|
|
86
|
-
end
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
def default_tools_enabled?
|
|
90
|
-
@disable_default_tools != true
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
def render_base_system_prompt
|
|
94
|
-
cwd = @directory || Dir.pwd
|
|
95
|
-
platform = RUBY_PLATFORM
|
|
96
|
-
os_version = begin
|
|
97
|
-
%x(uname -sr 2>/dev/null).strip
|
|
98
|
-
rescue
|
|
99
|
-
RUBY_PLATFORM
|
|
100
|
-
end
|
|
101
|
-
date = Time.now.strftime("%Y-%m-%d")
|
|
102
|
-
|
|
103
|
-
template_content = File.read(BASE_SYSTEM_PROMPT_PATH)
|
|
104
|
-
ERB.new(template_content).result(binding)
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
def render_non_coding_base_prompt
|
|
108
|
-
cwd = @directory || Dir.pwd
|
|
109
|
-
platform = RUBY_PLATFORM
|
|
110
|
-
os_version = begin
|
|
111
|
-
%x(uname -sr 2>/dev/null).strip
|
|
112
|
-
rescue
|
|
113
|
-
RUBY_PLATFORM
|
|
114
|
-
end
|
|
115
|
-
date = Time.now.strftime("%Y-%m-%d")
|
|
116
|
-
|
|
117
|
-
<<~PROMPT.strip
|
|
118
|
-
# Today's date
|
|
119
|
-
|
|
120
|
-
<today-date>
|
|
121
|
-
#{date}
|
|
122
|
-
#</today-date>
|
|
123
|
-
|
|
124
|
-
# Current Environment
|
|
125
|
-
|
|
126
|
-
<env>
|
|
127
|
-
Working directory: #{cwd}
|
|
128
|
-
Platform: #{platform}
|
|
129
|
-
OS Version: #{os_version}
|
|
130
|
-
</env>
|
|
131
|
-
PROMPT
|
|
132
|
-
end
|
|
133
|
-
|
|
134
|
-
def append_plugin_contributions(prompt)
|
|
135
|
-
contributions = collect_plugin_prompt_contributions
|
|
136
|
-
return prompt if contributions.empty?
|
|
137
|
-
|
|
138
|
-
combined_contributions = contributions.join("\n\n")
|
|
139
|
-
|
|
140
|
-
if prompt && !prompt.strip.empty?
|
|
141
|
-
"#{prompt}\n\n#{combined_contributions}"
|
|
142
|
-
else
|
|
143
|
-
combined_contributions
|
|
144
|
-
end
|
|
145
|
-
end
|
|
146
|
-
|
|
147
|
-
def collect_plugin_prompt_contributions
|
|
148
|
-
contributions = []
|
|
149
|
-
|
|
150
|
-
PluginRegistry.all.each do |plugin|
|
|
151
|
-
next unless plugin.storage_enabled?(@definition)
|
|
152
|
-
|
|
153
|
-
contribution = plugin.system_prompt_contribution(agent_definition: @definition, storage: nil)
|
|
154
|
-
contributions << contribution if contribution && !contribution.strip.empty?
|
|
155
|
-
end
|
|
156
|
-
|
|
157
|
-
contributions
|
|
158
|
-
end
|
|
159
|
-
end
|
|
160
|
-
end
|
|
161
|
-
end
|
|
@@ -1,409 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module SwarmSDK
|
|
4
|
-
module Builders
|
|
5
|
-
# Base builder with shared DSL methods for Swarm and Workflow builders
|
|
6
|
-
#
|
|
7
|
-
# Provides common functionality:
|
|
8
|
-
# - Basic configuration (name, id, scratchpad)
|
|
9
|
-
# - Agent definition (inline DSL, markdown files, with overrides)
|
|
10
|
-
# - All agents configuration
|
|
11
|
-
# - External swarms registry
|
|
12
|
-
# - Validation helpers
|
|
13
|
-
# - Merging logic
|
|
14
|
-
#
|
|
15
|
-
# Subclasses must implement:
|
|
16
|
-
# - build_swarm - Build and return the appropriate instance
|
|
17
|
-
# - Type-specific DSL methods (lead for Swarm, node/start_node for Workflow)
|
|
18
|
-
#
|
|
19
|
-
class BaseBuilder
|
|
20
|
-
def initialize(allow_filesystem_tools: nil)
|
|
21
|
-
@swarm_id = nil
|
|
22
|
-
@swarm_name = nil
|
|
23
|
-
@agents = {}
|
|
24
|
-
@all_agents_config = nil
|
|
25
|
-
@swarm_registry_config = []
|
|
26
|
-
@scratchpad = :disabled
|
|
27
|
-
@allow_filesystem_tools = allow_filesystem_tools
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
# Set swarm ID
|
|
31
|
-
#
|
|
32
|
-
# @param swarm_id [String] Unique identifier for this swarm/workflow
|
|
33
|
-
def id(swarm_id)
|
|
34
|
-
@swarm_id = swarm_id
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
# Set swarm/workflow name
|
|
38
|
-
def name(swarm_name)
|
|
39
|
-
@swarm_name = swarm_name
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
# Configure scratchpad mode
|
|
43
|
-
#
|
|
44
|
-
# For Workflow: :enabled (shared across nodes), :per_node (isolated), or :disabled
|
|
45
|
-
# For Swarm: :enabled or :disabled
|
|
46
|
-
#
|
|
47
|
-
# @param mode [Symbol, Boolean] Scratchpad mode
|
|
48
|
-
def scratchpad(mode)
|
|
49
|
-
@scratchpad = mode
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
# Register external swarms for composable swarms
|
|
53
|
-
#
|
|
54
|
-
# @example
|
|
55
|
-
# swarms do
|
|
56
|
-
# register "code_review", file: "./swarms/code_review.rb"
|
|
57
|
-
# register "testing", file: "./swarms/testing.yml", keep_context: false
|
|
58
|
-
# end
|
|
59
|
-
#
|
|
60
|
-
# @yield Block containing register() calls
|
|
61
|
-
def swarms(&block)
|
|
62
|
-
builder = Swarm::SwarmRegistryBuilder.new
|
|
63
|
-
builder.instance_eval(&block)
|
|
64
|
-
@swarm_registry_config = builder.registrations
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
# Define an agent with fluent API or load from markdown content
|
|
68
|
-
#
|
|
69
|
-
# Supports two forms:
|
|
70
|
-
# 1. Inline DSL: agent :name do ... end
|
|
71
|
-
# 2. Markdown content: agent :name, <<~MD ... MD
|
|
72
|
-
#
|
|
73
|
-
# @example Inline DSL
|
|
74
|
-
# agent :backend do
|
|
75
|
-
# model "gpt-5"
|
|
76
|
-
# system_prompt "You build APIs"
|
|
77
|
-
# tools :Read, :Write
|
|
78
|
-
# end
|
|
79
|
-
#
|
|
80
|
-
# @example Markdown content
|
|
81
|
-
# agent :backend, <<~MD
|
|
82
|
-
# ---
|
|
83
|
-
# description: "Backend developer"
|
|
84
|
-
# model: "gpt-4"
|
|
85
|
-
# ---
|
|
86
|
-
#
|
|
87
|
-
# You build APIs.
|
|
88
|
-
# MD
|
|
89
|
-
def agent(name, content = nil, &block)
|
|
90
|
-
# Case 1: agent :name, <<~MD do ... end (markdown + overrides)
|
|
91
|
-
if content.is_a?(String) && block_given? && markdown_content?(content)
|
|
92
|
-
load_agent_from_markdown_with_overrides(content, name, &block)
|
|
93
|
-
# Case 2: agent :name, <<~MD (markdown only)
|
|
94
|
-
elsif content.is_a?(String) && !block_given? && markdown_content?(content)
|
|
95
|
-
load_agent_from_markdown(content, name)
|
|
96
|
-
# Case 3: agent :name do ... end (inline DSL)
|
|
97
|
-
elsif block_given?
|
|
98
|
-
builder = Agent::Builder.new(name)
|
|
99
|
-
builder.instance_eval(&block)
|
|
100
|
-
@agents[name] = builder
|
|
101
|
-
else
|
|
102
|
-
raise ArgumentError, "Invalid agent definition. Use: agent :name { ... } OR agent :name, <<~MD ... MD OR agent :name, <<~MD do ... end"
|
|
103
|
-
end
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
# Configure all agents with a block
|
|
107
|
-
#
|
|
108
|
-
# @example
|
|
109
|
-
# all_agents do
|
|
110
|
-
# tools :Read, :Write
|
|
111
|
-
#
|
|
112
|
-
# hook :pre_tool_use, matcher: "Write" do |ctx|
|
|
113
|
-
# # Validation for all agents
|
|
114
|
-
# end
|
|
115
|
-
# end
|
|
116
|
-
def all_agents(&block)
|
|
117
|
-
builder = Swarm::AllAgentsBuilder.new
|
|
118
|
-
builder.instance_eval(&block)
|
|
119
|
-
@all_agents_config = builder
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
# Build the actual Swarm or Workflow instance
|
|
123
|
-
#
|
|
124
|
-
# Subclasses must implement this method.
|
|
125
|
-
#
|
|
126
|
-
# @return [Swarm, Workflow] Configured instance
|
|
127
|
-
def build_swarm
|
|
128
|
-
raise NotImplementedError, "#{self.class} must implement #build_swarm"
|
|
129
|
-
end
|
|
130
|
-
|
|
131
|
-
protected
|
|
132
|
-
|
|
133
|
-
# Check if a string is markdown content (has frontmatter)
|
|
134
|
-
#
|
|
135
|
-
# @param str [String] String to check
|
|
136
|
-
# @return [Boolean] true if string contains markdown frontmatter
|
|
137
|
-
def markdown_content?(str)
|
|
138
|
-
str.start_with?("---") || str.include?("\n---\n")
|
|
139
|
-
end
|
|
140
|
-
|
|
141
|
-
# Load an agent from markdown content
|
|
142
|
-
#
|
|
143
|
-
# Returns a hash of the agent config (not a Definition yet) so that
|
|
144
|
-
# all_agents config can be applied later in the build process.
|
|
145
|
-
#
|
|
146
|
-
# @param content [String] Markdown content with frontmatter
|
|
147
|
-
# @param name_override [Symbol, nil] Optional name to override frontmatter name
|
|
148
|
-
# @return [void]
|
|
149
|
-
def load_agent_from_markdown(content, name_override = nil)
|
|
150
|
-
definition = MarkdownParser.parse(content, name_override)
|
|
151
|
-
@agents[definition.name] = { __file_config__: definition.to_h }
|
|
152
|
-
end
|
|
153
|
-
|
|
154
|
-
# Load an agent from markdown content with DSL overrides
|
|
155
|
-
#
|
|
156
|
-
# @param content [String] Markdown content with frontmatter
|
|
157
|
-
# @param name_override [Symbol, nil] Optional name to override frontmatter name
|
|
158
|
-
# @yield Block with DSL overrides
|
|
159
|
-
# @return [void]
|
|
160
|
-
def load_agent_from_markdown_with_overrides(content, name_override = nil, &block)
|
|
161
|
-
definition = MarkdownParser.parse(content, name_override)
|
|
162
|
-
|
|
163
|
-
builder = Agent::Builder.new(definition.name)
|
|
164
|
-
apply_definition_to_builder(builder, definition.to_h)
|
|
165
|
-
builder.instance_eval(&block)
|
|
166
|
-
|
|
167
|
-
@agents[definition.name] = builder
|
|
168
|
-
end
|
|
169
|
-
|
|
170
|
-
# Apply agent definition hash to a builder
|
|
171
|
-
#
|
|
172
|
-
# @param builder [Agent::Builder] Builder to configure
|
|
173
|
-
# @param config [Hash] Configuration hash from definition
|
|
174
|
-
# @return [void]
|
|
175
|
-
def apply_definition_to_builder(builder, config)
|
|
176
|
-
builder.description(config[:description]) if config[:description]
|
|
177
|
-
builder.model(config[:model]) if config[:model]
|
|
178
|
-
builder.provider(config[:provider]) if config[:provider]
|
|
179
|
-
builder.base_url(config[:base_url]) if config[:base_url]
|
|
180
|
-
builder.api_version(config[:api_version]) if config[:api_version]
|
|
181
|
-
builder.context_window(config[:context_window]) if config[:context_window]
|
|
182
|
-
builder.system_prompt(config[:system_prompt]) if config[:system_prompt]
|
|
183
|
-
builder.directory(config[:directory]) if config[:directory]
|
|
184
|
-
builder.timeout(config[:timeout]) if config[:timeout]
|
|
185
|
-
builder.parameters(config[:parameters]) if config[:parameters]
|
|
186
|
-
builder.headers(config[:headers]) if config[:headers]
|
|
187
|
-
builder.coding_agent(config[:coding_agent]) unless config[:coding_agent].nil?
|
|
188
|
-
builder.bypass_permissions(config[:bypass_permissions]) if config[:bypass_permissions]
|
|
189
|
-
builder.disable_default_tools(config[:disable_default_tools]) unless config[:disable_default_tools].nil?
|
|
190
|
-
|
|
191
|
-
# Add tools from markdown
|
|
192
|
-
if config[:tools]&.any?
|
|
193
|
-
tool_names = config[:tools].map do |tool|
|
|
194
|
-
tool.is_a?(Hash) ? tool[:name] : tool
|
|
195
|
-
end
|
|
196
|
-
builder.tools(*tool_names)
|
|
197
|
-
end
|
|
198
|
-
|
|
199
|
-
# Add delegates_to
|
|
200
|
-
builder.delegates_to(*config[:delegates_to]) if config[:delegates_to]&.any?
|
|
201
|
-
|
|
202
|
-
# Add MCP servers
|
|
203
|
-
config[:mcp_servers]&.each do |server|
|
|
204
|
-
builder.mcp_server(server[:name], **server.except(:name))
|
|
205
|
-
end
|
|
206
|
-
end
|
|
207
|
-
|
|
208
|
-
# Merge all_agents configuration into each agent
|
|
209
|
-
#
|
|
210
|
-
# All_agents values are used as defaults - agent-specific values override.
|
|
211
|
-
# This applies to both inline DSL agents (Builder) and file-loaded agents (config hash).
|
|
212
|
-
#
|
|
213
|
-
# @return [void]
|
|
214
|
-
def merge_all_agents_config_into_agents
|
|
215
|
-
return unless @all_agents_config
|
|
216
|
-
|
|
217
|
-
all_agents_hash = @all_agents_config.to_h
|
|
218
|
-
|
|
219
|
-
@agents.each_value do |agent_builder_or_config|
|
|
220
|
-
if agent_builder_or_config.is_a?(Hash) && agent_builder_or_config.key?(:__file_config__)
|
|
221
|
-
# File-loaded agent - merge into the config hash
|
|
222
|
-
file_config = agent_builder_or_config[:__file_config__]
|
|
223
|
-
merged_config = merge_all_agents_into_config(all_agents_hash, file_config)
|
|
224
|
-
agent_builder_or_config[:__file_config__] = merged_config
|
|
225
|
-
else
|
|
226
|
-
# Builder object (inline DSL agent)
|
|
227
|
-
agent_builder = agent_builder_or_config
|
|
228
|
-
|
|
229
|
-
apply_all_agents_defaults(agent_builder, all_agents_hash)
|
|
230
|
-
|
|
231
|
-
# Merge tools (prepend all_agents tools)
|
|
232
|
-
all_agents_tools = @all_agents_config.tools_list
|
|
233
|
-
agent_builder.prepend_tools(*all_agents_tools) if all_agents_tools.any?
|
|
234
|
-
|
|
235
|
-
# Pass all_agents permissions as default_permissions
|
|
236
|
-
if @all_agents_config.permissions_config.any?
|
|
237
|
-
agent_builder.default_permissions = @all_agents_config.permissions_config
|
|
238
|
-
end
|
|
239
|
-
end
|
|
240
|
-
end
|
|
241
|
-
end
|
|
242
|
-
|
|
243
|
-
# Merge all_agents config into file-loaded agent config
|
|
244
|
-
#
|
|
245
|
-
# @param all_agents_hash [Hash] All_agents configuration
|
|
246
|
-
# @param file_config [Hash] File-loaded agent configuration
|
|
247
|
-
# @return [Hash] Merged configuration
|
|
248
|
-
def merge_all_agents_into_config(all_agents_hash, file_config)
|
|
249
|
-
merged = all_agents_hash.dup
|
|
250
|
-
|
|
251
|
-
file_config.each do |key, value|
|
|
252
|
-
case key
|
|
253
|
-
when :tools
|
|
254
|
-
merged[:tools] = Array(merged[:tools]) + Array(value)
|
|
255
|
-
when :delegates_to
|
|
256
|
-
merged[:delegates_to] = Array(merged[:delegates_to]) + Array(value)
|
|
257
|
-
when :parameters
|
|
258
|
-
merged[:parameters] = (merged[:parameters] || {}).merge(value || {})
|
|
259
|
-
when :headers
|
|
260
|
-
merged[:headers] = (merged[:headers] || {}).merge(value || {})
|
|
261
|
-
else
|
|
262
|
-
merged[key] = value
|
|
263
|
-
end
|
|
264
|
-
end
|
|
265
|
-
|
|
266
|
-
# Pass all_agents permissions as default_permissions
|
|
267
|
-
if all_agents_hash[:permissions] && !merged[:default_permissions]
|
|
268
|
-
merged[:default_permissions] = all_agents_hash[:permissions]
|
|
269
|
-
end
|
|
270
|
-
|
|
271
|
-
merged
|
|
272
|
-
end
|
|
273
|
-
|
|
274
|
-
# Apply all_agents defaults to an agent builder
|
|
275
|
-
#
|
|
276
|
-
# @param agent_builder [Agent::Builder] The agent builder to configure
|
|
277
|
-
# @param all_agents_hash [Hash] All_agents configuration
|
|
278
|
-
# @return [void]
|
|
279
|
-
def apply_all_agents_defaults(agent_builder, all_agents_hash)
|
|
280
|
-
if all_agents_hash[:model] && !agent_builder.model_set?
|
|
281
|
-
agent_builder.model(all_agents_hash[:model])
|
|
282
|
-
end
|
|
283
|
-
|
|
284
|
-
if all_agents_hash[:provider] && !agent_builder.provider_set?
|
|
285
|
-
agent_builder.provider(all_agents_hash[:provider])
|
|
286
|
-
end
|
|
287
|
-
|
|
288
|
-
if all_agents_hash[:base_url] && !agent_builder.base_url_set?
|
|
289
|
-
agent_builder.base_url(all_agents_hash[:base_url])
|
|
290
|
-
end
|
|
291
|
-
|
|
292
|
-
if all_agents_hash[:api_version] && !agent_builder.api_version_set?
|
|
293
|
-
agent_builder.api_version(all_agents_hash[:api_version])
|
|
294
|
-
end
|
|
295
|
-
|
|
296
|
-
if all_agents_hash[:timeout] && !agent_builder.timeout_set?
|
|
297
|
-
agent_builder.timeout(all_agents_hash[:timeout])
|
|
298
|
-
end
|
|
299
|
-
|
|
300
|
-
if all_agents_hash[:parameters]
|
|
301
|
-
merged_params = all_agents_hash[:parameters].merge(agent_builder.parameters)
|
|
302
|
-
agent_builder.parameters(merged_params)
|
|
303
|
-
end
|
|
304
|
-
|
|
305
|
-
if all_agents_hash[:headers]
|
|
306
|
-
merged_headers = all_agents_hash[:headers].merge(agent_builder.headers)
|
|
307
|
-
agent_builder.headers(merged_headers)
|
|
308
|
-
end
|
|
309
|
-
|
|
310
|
-
if !all_agents_hash[:coding_agent].nil? && !agent_builder.coding_agent_set?
|
|
311
|
-
agent_builder.coding_agent(all_agents_hash[:coding_agent])
|
|
312
|
-
end
|
|
313
|
-
end
|
|
314
|
-
|
|
315
|
-
# Validate all_agents filesystem tools
|
|
316
|
-
#
|
|
317
|
-
# @raise [ConfigurationError] If filesystem tools are disabled and all_agents has them
|
|
318
|
-
# @return [void]
|
|
319
|
-
def validate_all_agents_filesystem_tools
|
|
320
|
-
resolved_setting = if @allow_filesystem_tools.nil?
|
|
321
|
-
SwarmSDK.settings.allow_filesystem_tools
|
|
322
|
-
else
|
|
323
|
-
@allow_filesystem_tools
|
|
324
|
-
end
|
|
325
|
-
|
|
326
|
-
return if resolved_setting
|
|
327
|
-
return unless @all_agents_config&.tools_list&.any?
|
|
328
|
-
|
|
329
|
-
forbidden = @all_agents_config.tools_list.select do |tool|
|
|
330
|
-
SwarmSDK::Swarm::ToolConfigurator::FILESYSTEM_TOOLS.include?(tool.to_sym)
|
|
331
|
-
end
|
|
332
|
-
|
|
333
|
-
return if forbidden.empty?
|
|
334
|
-
|
|
335
|
-
raise ConfigurationError,
|
|
336
|
-
"Filesystem tools are globally disabled (SwarmSDK.settings.allow_filesystem_tools = false) " \
|
|
337
|
-
"but all_agents configuration includes: #{forbidden.join(", ")}.\n\n" \
|
|
338
|
-
"This is a system-wide security setting that cannot be overridden by swarm configuration.\n" \
|
|
339
|
-
"To use filesystem tools, set SwarmSDK.settings.allow_filesystem_tools = true before loading the swarm."
|
|
340
|
-
end
|
|
341
|
-
|
|
342
|
-
# Validate individual agent filesystem tools
|
|
343
|
-
#
|
|
344
|
-
# @raise [ConfigurationError] If filesystem tools are disabled and any agent has them
|
|
345
|
-
# @return [void]
|
|
346
|
-
def validate_agent_filesystem_tools
|
|
347
|
-
resolved_setting = if @allow_filesystem_tools.nil?
|
|
348
|
-
SwarmSDK.settings.allow_filesystem_tools
|
|
349
|
-
else
|
|
350
|
-
@allow_filesystem_tools
|
|
351
|
-
end
|
|
352
|
-
|
|
353
|
-
return if resolved_setting
|
|
354
|
-
|
|
355
|
-
@agents.each do |agent_name, agent_builder_or_config|
|
|
356
|
-
tools_list = if agent_builder_or_config.is_a?(Hash) && agent_builder_or_config.key?(:__file_config__)
|
|
357
|
-
agent_builder_or_config[:__file_config__][:tools] || []
|
|
358
|
-
elsif agent_builder_or_config.is_a?(Agent::Builder)
|
|
359
|
-
agent_builder_or_config.tools_list
|
|
360
|
-
else
|
|
361
|
-
[]
|
|
362
|
-
end
|
|
363
|
-
|
|
364
|
-
tool_names = tools_list.map do |tool|
|
|
365
|
-
name = tool.is_a?(Hash) ? tool[:name] : tool
|
|
366
|
-
name.to_sym
|
|
367
|
-
end
|
|
368
|
-
|
|
369
|
-
forbidden = tool_names.select do |tool|
|
|
370
|
-
SwarmSDK::Swarm::ToolConfigurator::FILESYSTEM_TOOLS.include?(tool)
|
|
371
|
-
end
|
|
372
|
-
|
|
373
|
-
next if forbidden.empty?
|
|
374
|
-
|
|
375
|
-
raise ConfigurationError,
|
|
376
|
-
"Filesystem tools are globally disabled (SwarmSDK.settings.allow_filesystem_tools = false) " \
|
|
377
|
-
"but agent '#{agent_name}' attempts to use: #{forbidden.join(", ")}.\n\n" \
|
|
378
|
-
"This is a system-wide security setting that cannot be overridden by swarm configuration.\n" \
|
|
379
|
-
"To use filesystem tools, set SwarmSDK.settings.allow_filesystem_tools = true before loading the swarm."
|
|
380
|
-
end
|
|
381
|
-
end
|
|
382
|
-
|
|
383
|
-
# Build agent definitions from builders or file configs
|
|
384
|
-
#
|
|
385
|
-
# Handles both Agent::Builder (inline DSL) and file configs (from files).
|
|
386
|
-
# Merges all_agents config before building.
|
|
387
|
-
#
|
|
388
|
-
# @return [Hash<Symbol, Agent::Definition>] Agent definitions
|
|
389
|
-
def build_agent_definitions
|
|
390
|
-
# Merge all_agents config first
|
|
391
|
-
merge_all_agents_config_into_agents if @all_agents_config
|
|
392
|
-
|
|
393
|
-
# Build definitions
|
|
394
|
-
agent_definitions = {}
|
|
395
|
-
@agents.each do |agent_name, agent_builder_or_config|
|
|
396
|
-
agent_definitions[agent_name] = if agent_builder_or_config.is_a?(Hash) && agent_builder_or_config.key?(:__file_config__)
|
|
397
|
-
# File-loaded agent config (with all_agents merged)
|
|
398
|
-
Agent::Definition.new(agent_name, agent_builder_or_config[:__file_config__])
|
|
399
|
-
else
|
|
400
|
-
# Builder object (from inline DSL) - convert to definition
|
|
401
|
-
agent_builder_or_config.to_definition
|
|
402
|
-
end
|
|
403
|
-
end
|
|
404
|
-
|
|
405
|
-
agent_definitions
|
|
406
|
-
end
|
|
407
|
-
end
|
|
408
|
-
end
|
|
409
|
-
end
|