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.
Files changed (182) hide show
  1. checksums.yaml +4 -4
  2. data/lib/swarm_memory/version.rb +1 -1
  3. metadata +5 -184
  4. data/lib/claude_swarm/base_executor.rb +0 -133
  5. data/lib/claude_swarm/claude_code_executor.rb +0 -349
  6. data/lib/claude_swarm/claude_mcp_server.rb +0 -78
  7. data/lib/claude_swarm/cli.rb +0 -697
  8. data/lib/claude_swarm/commands/ps.rb +0 -215
  9. data/lib/claude_swarm/commands/show.rb +0 -139
  10. data/lib/claude_swarm/configuration.rb +0 -373
  11. data/lib/claude_swarm/hooks/session_start_hook.rb +0 -42
  12. data/lib/claude_swarm/json_handler.rb +0 -91
  13. data/lib/claude_swarm/mcp_generator.rb +0 -230
  14. data/lib/claude_swarm/openai/chat_completion.rb +0 -256
  15. data/lib/claude_swarm/openai/executor.rb +0 -256
  16. data/lib/claude_swarm/openai/responses.rb +0 -319
  17. data/lib/claude_swarm/orchestrator.rb +0 -878
  18. data/lib/claude_swarm/process_tracker.rb +0 -78
  19. data/lib/claude_swarm/session_cost_calculator.rb +0 -209
  20. data/lib/claude_swarm/session_path.rb +0 -42
  21. data/lib/claude_swarm/settings_generator.rb +0 -77
  22. data/lib/claude_swarm/system_utils.rb +0 -46
  23. data/lib/claude_swarm/templates/generation_prompt.md.erb +0 -230
  24. data/lib/claude_swarm/tools/reset_session_tool.rb +0 -24
  25. data/lib/claude_swarm/tools/session_info_tool.rb +0 -24
  26. data/lib/claude_swarm/tools/task_tool.rb +0 -63
  27. data/lib/claude_swarm/version.rb +0 -5
  28. data/lib/claude_swarm/worktree_manager.rb +0 -475
  29. data/lib/claude_swarm/yaml_loader.rb +0 -22
  30. data/lib/claude_swarm.rb +0 -67
  31. data/lib/swarm_cli/cli.rb +0 -201
  32. data/lib/swarm_cli/command_registry.rb +0 -61
  33. data/lib/swarm_cli/commands/mcp_serve.rb +0 -130
  34. data/lib/swarm_cli/commands/mcp_tools.rb +0 -148
  35. data/lib/swarm_cli/commands/migrate.rb +0 -55
  36. data/lib/swarm_cli/commands/run.rb +0 -173
  37. data/lib/swarm_cli/config_loader.rb +0 -98
  38. data/lib/swarm_cli/formatters/human_formatter.rb +0 -781
  39. data/lib/swarm_cli/formatters/json_formatter.rb +0 -51
  40. data/lib/swarm_cli/interactive_repl.rb +0 -924
  41. data/lib/swarm_cli/mcp_serve_options.rb +0 -44
  42. data/lib/swarm_cli/mcp_tools_options.rb +0 -59
  43. data/lib/swarm_cli/migrate_options.rb +0 -54
  44. data/lib/swarm_cli/migrator.rb +0 -132
  45. data/lib/swarm_cli/options.rb +0 -151
  46. data/lib/swarm_cli/ui/components/agent_badge.rb +0 -33
  47. data/lib/swarm_cli/ui/components/content_block.rb +0 -120
  48. data/lib/swarm_cli/ui/components/divider.rb +0 -57
  49. data/lib/swarm_cli/ui/components/panel.rb +0 -62
  50. data/lib/swarm_cli/ui/components/usage_stats.rb +0 -70
  51. data/lib/swarm_cli/ui/formatters/cost.rb +0 -49
  52. data/lib/swarm_cli/ui/formatters/number.rb +0 -58
  53. data/lib/swarm_cli/ui/formatters/text.rb +0 -77
  54. data/lib/swarm_cli/ui/formatters/time.rb +0 -73
  55. data/lib/swarm_cli/ui/icons.rb +0 -36
  56. data/lib/swarm_cli/ui/renderers/event_renderer.rb +0 -188
  57. data/lib/swarm_cli/ui/state/agent_color_cache.rb +0 -45
  58. data/lib/swarm_cli/ui/state/depth_tracker.rb +0 -40
  59. data/lib/swarm_cli/ui/state/spinner_manager.rb +0 -170
  60. data/lib/swarm_cli/ui/state/usage_tracker.rb +0 -62
  61. data/lib/swarm_cli/version.rb +0 -5
  62. data/lib/swarm_cli.rb +0 -46
  63. data/lib/swarm_sdk/agent/RETRY_LOGIC.md +0 -127
  64. data/lib/swarm_sdk/agent/builder.rb +0 -552
  65. data/lib/swarm_sdk/agent/chat.rb +0 -774
  66. data/lib/swarm_sdk/agent/chat_helpers/context_tracker.rb +0 -268
  67. data/lib/swarm_sdk/agent/chat_helpers/event_emitter.rb +0 -204
  68. data/lib/swarm_sdk/agent/chat_helpers/hook_integration.rb +0 -480
  69. data/lib/swarm_sdk/agent/chat_helpers/instrumentation.rb +0 -78
  70. data/lib/swarm_sdk/agent/chat_helpers/llm_configuration.rb +0 -233
  71. data/lib/swarm_sdk/agent/chat_helpers/logging_helpers.rb +0 -116
  72. data/lib/swarm_sdk/agent/chat_helpers/serialization.rb +0 -83
  73. data/lib/swarm_sdk/agent/chat_helpers/system_reminder_injector.rb +0 -136
  74. data/lib/swarm_sdk/agent/chat_helpers/system_reminders.rb +0 -79
  75. data/lib/swarm_sdk/agent/chat_helpers/token_tracking.rb +0 -98
  76. data/lib/swarm_sdk/agent/context.rb +0 -116
  77. data/lib/swarm_sdk/agent/context_manager.rb +0 -315
  78. data/lib/swarm_sdk/agent/definition.rb +0 -477
  79. data/lib/swarm_sdk/agent/llm_instrumentation_middleware.rb +0 -182
  80. data/lib/swarm_sdk/agent/system_prompt_builder.rb +0 -161
  81. data/lib/swarm_sdk/builders/base_builder.rb +0 -409
  82. data/lib/swarm_sdk/claude_code_agent_adapter.rb +0 -205
  83. data/lib/swarm_sdk/concerns/cleanupable.rb +0 -39
  84. data/lib/swarm_sdk/concerns/snapshotable.rb +0 -67
  85. data/lib/swarm_sdk/concerns/validatable.rb +0 -55
  86. data/lib/swarm_sdk/configuration/parser.rb +0 -353
  87. data/lib/swarm_sdk/configuration/translator.rb +0 -255
  88. data/lib/swarm_sdk/configuration.rb +0 -135
  89. data/lib/swarm_sdk/context_compactor/metrics.rb +0 -147
  90. data/lib/swarm_sdk/context_compactor/token_counter.rb +0 -106
  91. data/lib/swarm_sdk/context_compactor.rb +0 -335
  92. data/lib/swarm_sdk/context_management/builder.rb +0 -128
  93. data/lib/swarm_sdk/context_management/context.rb +0 -328
  94. data/lib/swarm_sdk/defaults.rb +0 -196
  95. data/lib/swarm_sdk/events_to_messages.rb +0 -199
  96. data/lib/swarm_sdk/hooks/adapter.rb +0 -359
  97. data/lib/swarm_sdk/hooks/context.rb +0 -197
  98. data/lib/swarm_sdk/hooks/definition.rb +0 -80
  99. data/lib/swarm_sdk/hooks/error.rb +0 -29
  100. data/lib/swarm_sdk/hooks/executor.rb +0 -146
  101. data/lib/swarm_sdk/hooks/registry.rb +0 -147
  102. data/lib/swarm_sdk/hooks/result.rb +0 -150
  103. data/lib/swarm_sdk/hooks/shell_executor.rb +0 -255
  104. data/lib/swarm_sdk/hooks/tool_call.rb +0 -35
  105. data/lib/swarm_sdk/hooks/tool_result.rb +0 -62
  106. data/lib/swarm_sdk/log_collector.rb +0 -227
  107. data/lib/swarm_sdk/log_stream.rb +0 -127
  108. data/lib/swarm_sdk/markdown_parser.rb +0 -75
  109. data/lib/swarm_sdk/model_aliases.json +0 -8
  110. data/lib/swarm_sdk/models.json +0 -1
  111. data/lib/swarm_sdk/models.rb +0 -120
  112. data/lib/swarm_sdk/node_context.rb +0 -245
  113. data/lib/swarm_sdk/observer/builder.rb +0 -81
  114. data/lib/swarm_sdk/observer/config.rb +0 -45
  115. data/lib/swarm_sdk/observer/manager.rb +0 -236
  116. data/lib/swarm_sdk/patterns/agent_observer.rb +0 -160
  117. data/lib/swarm_sdk/permissions/config.rb +0 -239
  118. data/lib/swarm_sdk/permissions/error_formatter.rb +0 -121
  119. data/lib/swarm_sdk/permissions/path_matcher.rb +0 -35
  120. data/lib/swarm_sdk/permissions/validator.rb +0 -173
  121. data/lib/swarm_sdk/permissions_builder.rb +0 -122
  122. data/lib/swarm_sdk/plugin.rb +0 -309
  123. data/lib/swarm_sdk/plugin_registry.rb +0 -101
  124. data/lib/swarm_sdk/proc_helpers.rb +0 -53
  125. data/lib/swarm_sdk/prompts/base_system_prompt.md.erb +0 -117
  126. data/lib/swarm_sdk/restore_result.rb +0 -65
  127. data/lib/swarm_sdk/result.rb +0 -123
  128. data/lib/swarm_sdk/snapshot.rb +0 -156
  129. data/lib/swarm_sdk/snapshot_from_events.rb +0 -397
  130. data/lib/swarm_sdk/state_restorer.rb +0 -476
  131. data/lib/swarm_sdk/state_snapshot.rb +0 -334
  132. data/lib/swarm_sdk/swarm/agent_initializer.rb +0 -683
  133. data/lib/swarm_sdk/swarm/all_agents_builder.rb +0 -167
  134. data/lib/swarm_sdk/swarm/builder.rb +0 -249
  135. data/lib/swarm_sdk/swarm/executor.rb +0 -213
  136. data/lib/swarm_sdk/swarm/hook_triggers.rb +0 -150
  137. data/lib/swarm_sdk/swarm/logging_callbacks.rb +0 -340
  138. data/lib/swarm_sdk/swarm/mcp_configurator.rb +0 -154
  139. data/lib/swarm_sdk/swarm/swarm_registry_builder.rb +0 -67
  140. data/lib/swarm_sdk/swarm/tool_configurator.rb +0 -358
  141. data/lib/swarm_sdk/swarm.rb +0 -717
  142. data/lib/swarm_sdk/swarm_loader.rb +0 -145
  143. data/lib/swarm_sdk/swarm_registry.rb +0 -136
  144. data/lib/swarm_sdk/tools/bash.rb +0 -282
  145. data/lib/swarm_sdk/tools/clock.rb +0 -44
  146. data/lib/swarm_sdk/tools/delegate.rb +0 -267
  147. data/lib/swarm_sdk/tools/document_converters/base_converter.rb +0 -83
  148. data/lib/swarm_sdk/tools/document_converters/docx_converter.rb +0 -99
  149. data/lib/swarm_sdk/tools/document_converters/html_converter.rb +0 -101
  150. data/lib/swarm_sdk/tools/document_converters/pdf_converter.rb +0 -78
  151. data/lib/swarm_sdk/tools/document_converters/xlsx_converter.rb +0 -194
  152. data/lib/swarm_sdk/tools/edit.rb +0 -145
  153. data/lib/swarm_sdk/tools/glob.rb +0 -166
  154. data/lib/swarm_sdk/tools/grep.rb +0 -235
  155. data/lib/swarm_sdk/tools/image_extractors/docx_image_extractor.rb +0 -43
  156. data/lib/swarm_sdk/tools/image_extractors/pdf_image_extractor.rb +0 -163
  157. data/lib/swarm_sdk/tools/image_formats/tiff_builder.rb +0 -65
  158. data/lib/swarm_sdk/tools/multi_edit.rb +0 -236
  159. data/lib/swarm_sdk/tools/path_resolver.rb +0 -92
  160. data/lib/swarm_sdk/tools/read.rb +0 -261
  161. data/lib/swarm_sdk/tools/registry.rb +0 -205
  162. data/lib/swarm_sdk/tools/scratchpad/scratchpad_list.rb +0 -117
  163. data/lib/swarm_sdk/tools/scratchpad/scratchpad_read.rb +0 -97
  164. data/lib/swarm_sdk/tools/scratchpad/scratchpad_write.rb +0 -108
  165. data/lib/swarm_sdk/tools/stores/read_tracker.rb +0 -96
  166. data/lib/swarm_sdk/tools/stores/scratchpad_storage.rb +0 -272
  167. data/lib/swarm_sdk/tools/stores/storage.rb +0 -142
  168. data/lib/swarm_sdk/tools/stores/todo_manager.rb +0 -65
  169. data/lib/swarm_sdk/tools/think.rb +0 -98
  170. data/lib/swarm_sdk/tools/todo_write.rb +0 -235
  171. data/lib/swarm_sdk/tools/web_fetch.rb +0 -262
  172. data/lib/swarm_sdk/tools/write.rb +0 -112
  173. data/lib/swarm_sdk/utils.rb +0 -68
  174. data/lib/swarm_sdk/validation_result.rb +0 -33
  175. data/lib/swarm_sdk/version.rb +0 -5
  176. data/lib/swarm_sdk/workflow/agent_config.rb +0 -79
  177. data/lib/swarm_sdk/workflow/builder.rb +0 -143
  178. data/lib/swarm_sdk/workflow/executor.rb +0 -497
  179. data/lib/swarm_sdk/workflow/node_builder.rb +0 -555
  180. data/lib/swarm_sdk/workflow/transformer_executor.rb +0 -249
  181. data/lib/swarm_sdk/workflow.rb +0 -554
  182. 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