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,552 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module SwarmSDK
4
- module Agent
5
- # Builder provides fluent API for configuring agents
6
- #
7
- # This class offers a Ruby DSL for defining agents with a clean, readable syntax.
8
- # It collects configuration and then adds the agent to the swarm.
9
- #
10
- # @example
11
- # agent :backend do
12
- # model "gpt-5"
13
- # prompt "You build APIs"
14
- # tools :Read, :Write, :Bash
15
- #
16
- # hook :pre_tool_use, matcher: "Bash" do |ctx|
17
- # SwarmSDK::Hooks::Result.halt("Blocked!") if dangerous?(ctx)
18
- # end
19
- # end
20
- class Builder
21
- # Expose default_permissions for Swarm::Builder to set from all_agents
22
- attr_writer :default_permissions
23
-
24
- # Expose mcp_servers for tests
25
- attr_reader :mcp_servers
26
-
27
- # Get tools list as array for validation
28
- #
29
- # @return [Array<Symbol>] List of tools
30
- def tools_list
31
- @tools.to_a
32
- end
33
-
34
- def initialize(name)
35
- @name = name
36
- @description = nil
37
- @model = "gpt-5"
38
- @provider = nil
39
- @base_url = nil
40
- @api_version = nil
41
- @context_window = nil
42
- @system_prompt = nil
43
- # Use Set for tools to automatically handle duplicates when tools() is called multiple times.
44
- # This ensures that if someone does: tools :Read; tools :Write; tools :Read
45
- # the final set contains only [:Read, :Write] without duplicates.
46
- # We convert to Array in to_definition for compatibility with Agent::Definition.
47
- @tools = Set.new
48
- @delegates_to = []
49
- @directory = "."
50
- @parameters = {}
51
- @headers = {}
52
- @timeout = nil
53
- @mcp_servers = []
54
- @disable_default_tools = nil # nil = include all default tools
55
- @bypass_permissions = false
56
- @coding_agent = nil # nil = not set (will default to false in Definition)
57
- @assume_model_exists = nil
58
- @hooks = []
59
- @permissions_config = {}
60
- @default_permissions = {} # Set by SwarmBuilder from all_agents
61
- @memory_config = nil
62
- @shared_across_delegations = nil # nil = not set (will default to false in Definition)
63
- @context_management_config = nil # Context management DSL hooks
64
- end
65
-
66
- # Set/get agent model
67
- def model(model_name = :__not_provided__)
68
- return @model if model_name == :__not_provided__
69
-
70
- @model = model_name
71
- end
72
-
73
- # Set/get provider
74
- def provider(provider_name = :__not_provided__)
75
- return @provider if provider_name == :__not_provided__
76
-
77
- @provider = provider_name
78
- end
79
-
80
- # Set/get base URL
81
- def base_url(url = :__not_provided__)
82
- return @base_url if url == :__not_provided__
83
-
84
- @base_url = url
85
- end
86
-
87
- # Set/get API version (OpenAI-compatible providers only)
88
- def api_version(version = :__not_provided__)
89
- return @api_version if version == :__not_provided__
90
-
91
- @api_version = version
92
- end
93
-
94
- # Set/get explicit context window override
95
- def context_window(tokens = :__not_provided__)
96
- return @context_window if tokens == :__not_provided__
97
-
98
- @context_window = tokens
99
- end
100
-
101
- # Set/get LLM parameters
102
- def parameters(params = :__not_provided__)
103
- return @parameters if params == :__not_provided__
104
-
105
- @parameters = params
106
- end
107
-
108
- # Set/get custom HTTP headers
109
- def headers(header_hash = :__not_provided__)
110
- return @headers if header_hash == :__not_provided__
111
-
112
- @headers = header_hash
113
- end
114
-
115
- # Set/get timeout
116
- def timeout(seconds = :__not_provided__)
117
- return @timeout if seconds == :__not_provided__
118
-
119
- @timeout = seconds
120
- end
121
-
122
- # Add an MCP server configuration
123
- #
124
- # @example stdio transport
125
- # mcp_server :filesystem, type: :stdio, command: "npx", args: ["-y", "@modelcontextprotocol/server-filesystem"]
126
- #
127
- # @example SSE transport
128
- # mcp_server :web, type: :sse, url: "https://example.com/mcp", headers: { authorization: "Bearer token" }
129
- #
130
- # @example HTTP/streamable transport
131
- # mcp_server :api, type: :http, url: "https://api.example.com/mcp", timeout: 60
132
- def mcp_server(name, **options)
133
- server_config = { name: name }.merge(options)
134
- @mcp_servers << server_config
135
- end
136
-
137
- # Disable default tools
138
- #
139
- # @param value [Boolean, Array<Symbol>]
140
- # - true: Disable ALL default tools
141
- # - Array of symbols: Disable specific tools (e.g., [:Think, :TodoWrite])
142
- #
143
- # @example Disable all default tools
144
- # disable_default_tools true
145
- #
146
- # @example Disable specific tools (array)
147
- # disable_default_tools [:Think, :TodoWrite]
148
- #
149
- # @example Disable specific tools (separate arguments)
150
- # disable_default_tools :Think, :TodoWrite
151
- def disable_default_tools(*tools)
152
- # Handle different argument forms
153
- @disable_default_tools = case tools.size
154
- when 0
155
- nil
156
- when 1
157
- # Single argument: could be true/false/array
158
- tools.first
159
- else
160
- # Multiple arguments: treat as array of tool names
161
- tools.map(&:to_sym)
162
- end
163
- end
164
-
165
- # Set bypass_permissions flag
166
- def bypass_permissions(enabled)
167
- @bypass_permissions = enabled
168
- end
169
-
170
- # Set coding_agent flag
171
- #
172
- # When true, includes the base system prompt for coding tasks.
173
- # When false (default), uses only the custom system prompt.
174
- #
175
- # @param enabled [Boolean] Whether to include base coding prompt
176
- # @return [void]
177
- #
178
- # @example
179
- # coding_agent true # Include base prompt for coding tasks
180
- def coding_agent(enabled)
181
- @coding_agent = enabled
182
- end
183
-
184
- # Set assume_model_exists flag
185
- def assume_model_exists(enabled)
186
- @assume_model_exists = enabled
187
- end
188
-
189
- # Set system prompt (matches YAML key)
190
- def system_prompt(text)
191
- @system_prompt = text
192
- end
193
-
194
- # Set description
195
- def description(text)
196
- @description = text
197
- end
198
-
199
- # Set or add tools
200
- #
201
- # Uses Set internally to automatically deduplicate tool names across multiple calls.
202
- # This allows calling tools() multiple times without worrying about duplicates.
203
- #
204
- # @param tool_names [Array<Symbol>] Tool names to add
205
- # @param include_default [Boolean] Whether to include default tools (Read, Grep, etc.)
206
- # @param replace [Boolean] If true, replaces existing tools instead of merging (default: false)
207
- #
208
- # @example Basic usage with defaults
209
- # tools :Grep, :Read # include_default: true is implicit
210
- #
211
- # @example Explicit tools only, no defaults
212
- # tools :Grep, :Read, include_default: false
213
- #
214
- # @example Multiple calls (cumulative, automatic deduplication)
215
- # tools :Read
216
- # tools :Write, :Edit # @tools now contains Set[:Read, :Write, :Edit]
217
- # tools :Read # Still Set[:Read, :Write, :Edit] - no duplicate
218
- #
219
- # @example Replace tools (for markdown overrides)
220
- # tools :Read, :Write, replace: true # Replaces all existing tools
221
- def tools(*tool_names, include_default: true, replace: false)
222
- @tools = Set.new if replace
223
- @tools.merge(tool_names.map(&:to_sym))
224
- # When include_default is false, disable all default tools
225
- @disable_default_tools = true unless include_default
226
- end
227
-
228
- # Add tools from all_agents configuration
229
- #
230
- # Used by Swarm::Builder to add all_agents tools.
231
- # Since we use Set, order doesn't matter and duplicates are handled automatically.
232
- #
233
- # @param tool_names [Array] Tool names to add
234
- # @return [void]
235
- def prepend_tools(*tool_names)
236
- @tools.merge(tool_names.map(&:to_sym))
237
- end
238
-
239
- # Set directory
240
- def directory(dir)
241
- @directory = dir
242
- end
243
-
244
- # Set delegation targets
245
- def delegates_to(*agent_names)
246
- @delegates_to.concat(agent_names)
247
- end
248
-
249
- # Add a hook (Ruby block OR shell command)
250
- #
251
- # @example Ruby block
252
- # hook :pre_tool_use, matcher: "Bash" do |ctx|
253
- # HookResult.halt("Blocked") if dangerous?(ctx)
254
- # end
255
- #
256
- # @example Shell command
257
- # hook :pre_tool_use, matcher: "Bash", command: "validate.sh"
258
- def hook(event, matcher: nil, command: nil, timeout: nil, &block)
259
- @hooks << {
260
- event: event,
261
- matcher: matcher,
262
- command: command,
263
- timeout: timeout,
264
- block: block,
265
- }
266
- end
267
-
268
- # Configure permissions for this agent
269
- #
270
- # @example
271
- # permissions do
272
- # Write.allow_paths "backend/**/*"
273
- # Write.deny_paths "backend/secrets/**"
274
- # end
275
- def permissions(&block)
276
- @permissions_config = PermissionsBuilder.build(&block)
277
- end
278
-
279
- # Configure delegation isolation mode
280
- #
281
- # @param enabled [Boolean] If true, allows sharing instances across delegations (old behavior)
282
- # If false (default), creates isolated instances per delegation
283
- # @return [self] Returns self for method chaining
284
- #
285
- # @example
286
- # shared_across_delegations true # Allow sharing (old behavior)
287
- def shared_across_delegations(enabled)
288
- @shared_across_delegations = enabled
289
- self
290
- end
291
-
292
- # Configure context management handlers
293
- #
294
- # Define custom handlers for context warning thresholds (60%, 80%, 90%).
295
- # Handlers receive a rich context object with message manipulation methods.
296
- # When a custom handler is registered, automatic compression is disabled
297
- # for that threshold, giving full control to the handler.
298
- #
299
- # @yield Context management DSL block
300
- # @return [void]
301
- #
302
- # @example Basic compression at 60%
303
- # context_management do
304
- # on :warning_60 do |ctx|
305
- # ctx.compress_tool_results(keep_recent: 10)
306
- # end
307
- # end
308
- #
309
- # @example Multiple thresholds with different strategies
310
- # context_management do
311
- # on :warning_60 do |ctx|
312
- # ctx.compress_tool_results(keep_recent: 15, truncate_to: 500)
313
- # end
314
- #
315
- # on :warning_80 do |ctx|
316
- # ctx.prune_old_messages(keep_recent: 30)
317
- # ctx.compress_tool_results(keep_recent: 5, truncate_to: 200)
318
- # end
319
- #
320
- # on :warning_90 do |ctx|
321
- # ctx.log_action("emergency_pruning", remaining: ctx.tokens_remaining)
322
- # ctx.prune_old_messages(keep_recent: 15)
323
- # end
324
- # end
325
- #
326
- # @example Conditional logic based on metrics
327
- # context_management do
328
- # on :warning_80 do |ctx|
329
- # if ctx.usage_percentage > 85
330
- # ctx.prune_old_messages(keep_recent: 10)
331
- # else
332
- # ctx.compress_tool_results(keep_recent: 5)
333
- # end
334
- # end
335
- # end
336
- def context_management(&block)
337
- builder = ContextManagement::Builder.new
338
- builder.instance_eval(&block)
339
- @context_management_config = builder.build
340
- end
341
-
342
- # Set permissions directly from hash (for YAML translation)
343
- #
344
- # This is intentionally separate from permissions() to keep the DSL clean.
345
- # Called by Configuration when translating YAML permissions.
346
- #
347
- # @param hash [Hash] Permissions configuration hash
348
- # @return [void]
349
- def permissions_hash=(hash)
350
- @permissions_config = hash || {}
351
- end
352
-
353
- # Check if model has been explicitly set (not default)
354
- #
355
- # Used by Swarm::Builder to determine if all_agents model should apply.
356
- #
357
- # @return [Boolean] true if model was explicitly set
358
- def model_set?
359
- @model != "gpt-5"
360
- end
361
-
362
- # Check if provider has been explicitly set
363
- #
364
- # Used by Swarm::Builder to determine if all_agents provider should apply.
365
- #
366
- # @return [Boolean] true if provider was explicitly set
367
- def provider_set?
368
- !@provider.nil?
369
- end
370
-
371
- # Check if base_url has been explicitly set
372
- #
373
- # Used by Swarm::Builder to determine if all_agents base_url should apply.
374
- #
375
- # @return [Boolean] true if base_url was explicitly set
376
- def base_url_set?
377
- !@base_url.nil?
378
- end
379
-
380
- # Check if api_version has been explicitly set
381
- #
382
- # Used by Swarm::Builder to determine if all_agents api_version should apply.
383
- #
384
- # @return [Boolean] true if api_version was explicitly set
385
- def api_version_set?
386
- !@api_version.nil?
387
- end
388
-
389
- # Check if timeout has been explicitly set
390
- #
391
- # Used by Swarm::Builder to determine if all_agents timeout should apply.
392
- #
393
- # @return [Boolean] true if timeout was explicitly set
394
- def timeout_set?
395
- !@timeout.nil?
396
- end
397
-
398
- # Check if coding_agent has been explicitly set
399
- #
400
- # Used by Swarm::Builder to determine if all_agents coding_agent should apply.
401
- #
402
- # @return [Boolean] true if coding_agent was explicitly set
403
- def coding_agent_set?
404
- !@coding_agent.nil?
405
- end
406
-
407
- # Check if parameters have been set
408
- #
409
- # Used by Swarm::Builder for merging all_agents parameters.
410
- #
411
- # @return [Boolean] true if parameters were set
412
- def parameters_set?
413
- @parameters.any?
414
- end
415
-
416
- # Check if headers have been set
417
- #
418
- # Used by Swarm::Builder for merging all_agents headers.
419
- #
420
- # @return [Boolean] true if headers were set
421
- def headers_set?
422
- @headers.any?
423
- end
424
-
425
- # Build and return an Agent::Definition
426
- #
427
- # This method converts the builder's configuration into a validated
428
- # Agent::Definition object. The caller is responsible for adding it to a swarm.
429
- #
430
- # Converts @tools Set to Array here because Agent::Definition expects an array.
431
- # The Set was only used during building to handle duplicates efficiently.
432
- #
433
- # @return [Agent::Definition] Fully configured and validated agent definition
434
- def to_definition
435
- agent_config = {
436
- description: @description || "Agent #{@name}",
437
- model: @model,
438
- system_prompt: @system_prompt,
439
- tools: @tools.to_a, # Convert Set to Array for Agent::Definition compatibility
440
- delegates_to: @delegates_to,
441
- directory: @directory,
442
- }
443
-
444
- # Add optional fields
445
- agent_config[:provider] = @provider if @provider
446
- agent_config[:base_url] = @base_url if @base_url
447
- agent_config[:api_version] = @api_version if @api_version
448
- agent_config[:context_window] = @context_window if @context_window
449
- agent_config[:parameters] = @parameters if @parameters.any?
450
- agent_config[:headers] = @headers if @headers.any?
451
- agent_config[:timeout] = @timeout if @timeout
452
- agent_config[:mcp_servers] = @mcp_servers if @mcp_servers.any?
453
- agent_config[:disable_default_tools] = @disable_default_tools unless @disable_default_tools.nil?
454
- agent_config[:bypass_permissions] = @bypass_permissions
455
- agent_config[:coding_agent] = @coding_agent
456
- agent_config[:assume_model_exists] = @assume_model_exists unless @assume_model_exists.nil?
457
- agent_config[:permissions] = @permissions_config if @permissions_config.any?
458
- agent_config[:default_permissions] = @default_permissions if @default_permissions.any?
459
- agent_config[:memory] = @memory_config if @memory_config
460
- agent_config[:shared_across_delegations] = @shared_across_delegations unless @shared_across_delegations.nil?
461
-
462
- # Convert DSL hooks to HookDefinition format
463
- agent_config[:hooks] = convert_hooks_to_definitions if @hooks.any?
464
-
465
- # Merge context management hooks into agent hooks
466
- if @context_management_config
467
- agent_config[:hooks] ||= {}
468
- agent_config[:hooks][:context_warning] ||= []
469
- agent_config[:hooks][:context_warning].concat(@context_management_config)
470
- end
471
-
472
- Agent::Definition.new(@name, agent_config)
473
- end
474
-
475
- private
476
-
477
- # Convert DSL hooks to HookDefinition objects for Agent::Definition
478
- #
479
- # This converts the builder's hook configuration (Ruby blocks and shell commands)
480
- # into HookDefinition objects that will be applied during agent initialization.
481
- #
482
- # @return [Hash] Hooks grouped by event type { event: [HookDefinition, ...] }
483
- def convert_hooks_to_definitions
484
- result = Hash.new { |h, k| h[k] = [] }
485
-
486
- @hooks.each do |hook_config|
487
- event = hook_config[:event]
488
-
489
- # Create HookDefinition with proc or command
490
- if hook_config[:block]
491
- # Ruby block hook
492
- hook_def = Hooks::Definition.new(
493
- event: event,
494
- matcher: hook_config[:matcher],
495
- priority: 0,
496
- proc: hook_config[:block],
497
- )
498
- elsif hook_config[:command]
499
- # Shell command hook - wrap in a block that calls ShellExecutor
500
- hook_def = Hooks::Definition.new(
501
- event: event,
502
- matcher: hook_config[:matcher],
503
- priority: 0,
504
- proc: create_shell_hook_proc(hook_config),
505
- )
506
- else
507
- raise ConfigurationError, "Hook must have either :block or :command"
508
- end
509
-
510
- result[event] << hook_def
511
- end
512
-
513
- result
514
- end
515
-
516
- # Create a proc that executes a shell command hook
517
- def create_shell_hook_proc(config)
518
- command = config[:command]
519
- timeout = config[:timeout] || 60
520
- agent_name = @name
521
-
522
- proc do |context|
523
- input_json = build_hook_input(context, config[:event])
524
- Hooks::ShellExecutor.execute(
525
- command: command,
526
- input_json: input_json,
527
- timeout: timeout,
528
- agent_name: agent_name,
529
- swarm_name: context.swarm&.name,
530
- event: config[:event],
531
- )
532
- end
533
- end
534
-
535
- # Build hook input JSON for shell command hooks
536
- def build_hook_input(context, event)
537
- base = { event: event.to_s, agent: @name.to_s }
538
-
539
- case event
540
- when :pre_tool_use
541
- base.merge(tool: context.tool_call.name, parameters: context.tool_call.parameters)
542
- when :post_tool_use
543
- base.merge(result: context.tool_result.content, success: context.tool_result.success?)
544
- when :user_prompt
545
- base.merge(prompt: context.metadata[:prompt])
546
- else
547
- base
548
- end
549
- end
550
- end
551
- end
552
- end