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,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