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