swarm_sdk 2.7.2 → 2.7.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 204f0173ac046d5eae63cf3ddca318e3ab0e76a88661e7f4a106d5079a68ee63
4
- data.tar.gz: 515a43fac5824b6fab886901449ef808288e8e5e2beaacd02502c0e337a3d98f
3
+ metadata.gz: b5c93c6e9a850d624b8ac0fe9d31e53a4a764a1caa23319efcfa5b34edfd33b8
4
+ data.tar.gz: 2d4ec3258101a45507cbacbd98eeb86d8448627e35faedd2a693c0a18d8622a1
5
5
  SHA512:
6
- metadata.gz: 94b2a3d8ee2d4cd61ec45a075b5e9cc370d992e47ae2da7e478abe7aa7f81ebaf2c0cd3571072ed02fdfac1eefc07c8eb5bcfd65aefa46c0cc60298b7e2b30ae
7
- data.tar.gz: 7e527394023723bfabd8fa18c1696b0dc10b14499fe4c2ba3db46e3c8518158d1d5de8553c41d2139eba3c800f17a739c86503a7366c470ccb9e616446695510
6
+ metadata.gz: ac8f8c8dea846e5b0783b49dace5f2e01a0908ebed31eb377fdd4217480e99499fe9eb4bda14772cbfd71d52badc642687434a214f76cf136768c21967e1beff
7
+ data.tar.gz: 61a58b209810484c7bcf24727feaa8fb0e23aafc485dbb3ad8a510c095caeaa72778b0e3c97b22eb599a2d9153ef95093dc9aa6a3b34e717b23c4c5d9797b490
@@ -275,6 +275,10 @@ module SwarmSDK
275
275
  # backend: "GetBackendHelp",
276
276
  # :qa
277
277
  #
278
+ # @example With delegation options (preserve_context controls context persistence)
279
+ # delegates_to :frontend,
280
+ # { agent: :backend, tool_name: "AskBackend", preserve_context: false }
281
+ #
278
282
  # @param agent_names_and_options [Array<Symbol, Hash>] Agent names and/or hash with custom tool names
279
283
  # @return [void]
280
284
  def delegates_to(*agent_names_and_options)
@@ -282,11 +286,20 @@ module SwarmSDK
282
286
  case item
283
287
  when Symbol, String
284
288
  # Simple format: :frontend
285
- @delegates_to << { agent: item.to_sym, tool_name: nil }
289
+ @delegates_to << { agent: item.to_sym, tool_name: nil, preserve_context: true }
286
290
  when Hash
287
- # Hash format: { frontend: "AskFrontend", backend: nil }
288
- item.each do |agent, tool_name|
289
- @delegates_to << { agent: agent.to_sym, tool_name: tool_name }
291
+ if item.key?(:agent)
292
+ # Full config format: { agent: :backend, tool_name: "Custom", preserve_context: false }
293
+ @delegates_to << {
294
+ agent: item[:agent].to_sym,
295
+ tool_name: item[:tool_name],
296
+ preserve_context: item.fetch(:preserve_context, true),
297
+ }
298
+ else
299
+ # Hash format: { frontend: "AskFrontend", backend: nil }
300
+ item.each do |agent, tool_name|
301
+ @delegates_to << { agent: agent.to_sym, tool_name: tool_name, preserve_context: true }
302
+ end
290
303
  end
291
304
  else
292
305
  raise ConfigurationError, "delegates_to accepts Symbols or Hashes, got #{item.class}"
@@ -325,16 +325,20 @@ module SwarmSDK
325
325
  delegation_config.flat_map do |item|
326
326
  case item
327
327
  when Symbol, String
328
- # Simple format: :frontend → {agent: :frontend, tool_name: nil}
329
- [{ agent: item.to_sym, tool_name: nil }]
328
+ # Simple format: :frontend → {agent: :frontend, tool_name: nil, preserve_context: true}
329
+ [{ agent: item.to_sym, tool_name: nil, preserve_context: true }]
330
330
  when Hash
331
331
  # Could be already normalized or hash format
332
332
  if item.key?(:agent)
333
- # Already normalized: {agent: :frontend, tool_name: "Custom"}
334
- [item]
333
+ # Already normalized: {agent: :frontend, tool_name: "Custom", preserve_context: false}
334
+ [{
335
+ agent: item[:agent].to_sym,
336
+ tool_name: item[:tool_name],
337
+ preserve_context: item.fetch(:preserve_context, true),
338
+ }]
335
339
  else
336
340
  # Hash format in array: {frontend: "AskFrontend"}
337
- item.map { |agent, tool_name| { agent: agent.to_sym, tool_name: tool_name } }
341
+ item.map { |agent, tool_name| { agent: agent.to_sym, tool_name: tool_name, preserve_context: true } }
338
342
  end
339
343
  else
340
344
  raise ConfigurationError, "Invalid delegation config format: #{item.inspect}"
@@ -343,7 +347,7 @@ module SwarmSDK
343
347
  elsif delegation_config.is_a?(Hash)
344
348
  # Hash format: {frontend: "AskFrontend", backend: nil}
345
349
  delegation_config.map do |agent, tool_name|
346
- { agent: agent.to_sym, tool_name: tool_name }
350
+ { agent: agent.to_sym, tool_name: tool_name, preserve_context: true }
347
351
  end
348
352
  else
349
353
  raise ConfigurationError, "delegates_to must be an Array or Hash, got #{delegation_config.class}"
@@ -91,8 +91,9 @@ module SwarmSDK
91
91
  # @param agent_name [Symbol] Name of the delegating agent
92
92
  # @param delegating_chat [Agent::Chat, nil] The chat instance of the agent doing the delegating
93
93
  # @param custom_tool_name [String, nil] Optional custom tool name (overrides auto-generated name)
94
+ # @param preserve_context [Boolean] Whether to preserve conversation context between delegations (default: true)
94
95
  # @return [Tools::Delegate] Delegation tool
95
- def create_delegation_tool(name:, description:, delegate_chat:, agent_name:, delegating_chat: nil, custom_tool_name: nil)
96
+ def create_delegation_tool(name:, description:, delegate_chat:, agent_name:, delegating_chat: nil, custom_tool_name: nil, preserve_context: true)
96
97
  Tools::Delegate.new(
97
98
  delegate_name: name,
98
99
  delegate_description: description,
@@ -101,6 +102,7 @@ module SwarmSDK
101
102
  swarm: @swarm,
102
103
  delegating_chat: delegating_chat,
103
104
  custom_tool_name: custom_tool_name,
105
+ preserve_context: preserve_context,
104
106
  )
105
107
  end
106
108
 
@@ -219,7 +221,7 @@ module SwarmSDK
219
221
  #
220
222
  # @param delegator_name [Symbol, String] Name of the agent doing the delegating
221
223
  # @param delegator_chat [Agent::Chat] Chat instance of the delegator
222
- # @param delegation_config [Hash] Delegation configuration with :agent and :tool_name keys
224
+ # @param delegation_config [Hash] Delegation configuration with :agent, :tool_name, and :preserve_context keys
223
225
  # @param tool_configurator [ToolConfigurator] Tool configuration helper
224
226
  # @param create_nested_instances [Boolean] Whether to create new instances for nested delegation
225
227
  # @return [void]
@@ -227,10 +229,11 @@ module SwarmSDK
227
229
  delegate_name_sym = delegation_config[:agent]
228
230
  delegate_name_str = delegate_name_sym.to_s
229
231
  custom_tool_name = delegation_config[:tool_name]
232
+ preserve_context = delegation_config.fetch(:preserve_context, true)
230
233
 
231
234
  # Check if target is a registered swarm
232
235
  if @swarm.swarm_registry&.registered?(delegate_name_str)
233
- wire_swarm_delegation(delegator_name, delegator_chat, delegate_name_str, custom_tool_name)
236
+ wire_swarm_delegation(delegator_name, delegator_chat, delegate_name_str, custom_tool_name, preserve_context)
234
237
  elsif @swarm.agent_definitions.key?(delegate_name_sym)
235
238
  wire_agent_delegation(
236
239
  delegator_name: delegator_name,
@@ -239,6 +242,7 @@ module SwarmSDK
239
242
  custom_tool_name: custom_tool_name,
240
243
  tool_configurator: tool_configurator,
241
244
  create_nested_instances: create_nested_instances,
245
+ preserve_context: preserve_context,
242
246
  )
243
247
  else
244
248
  raise ConfigurationError,
@@ -252,8 +256,9 @@ module SwarmSDK
252
256
  # @param delegator_chat [Agent::Chat] Chat instance of the delegator
253
257
  # @param swarm_name [String] Name of the registered swarm
254
258
  # @param custom_tool_name [String, nil] Optional custom tool name
259
+ # @param preserve_context [Boolean] Whether to preserve context between delegations
255
260
  # @return [void]
256
- def wire_swarm_delegation(delegator_name, delegator_chat, swarm_name, custom_tool_name)
261
+ def wire_swarm_delegation(delegator_name, delegator_chat, swarm_name, custom_tool_name, preserve_context)
257
262
  tool = create_delegation_tool(
258
263
  name: swarm_name,
259
264
  description: "External swarm: #{swarm_name}",
@@ -261,13 +266,14 @@ module SwarmSDK
261
266
  agent_name: delegator_name,
262
267
  delegating_chat: delegator_chat,
263
268
  custom_tool_name: custom_tool_name,
269
+ preserve_context: preserve_context,
264
270
  )
265
271
 
266
272
  # Register in tool registry (Plan 025)
267
273
  delegator_chat.tool_registry.register(
268
274
  tool,
269
275
  source: :delegation,
270
- metadata: { delegate_name: swarm_name, delegation_type: :swarm },
276
+ metadata: { delegate_name: swarm_name, delegation_type: :swarm, preserve_context: preserve_context },
271
277
  )
272
278
  end
273
279
 
@@ -282,8 +288,9 @@ module SwarmSDK
282
288
  # @param custom_tool_name [String, nil] Optional custom tool name
283
289
  # @param tool_configurator [ToolConfigurator] Tool configuration helper
284
290
  # @param create_nested_instances [Boolean] Whether to create new instances if not found
291
+ # @param preserve_context [Boolean] Whether to preserve context between delegations
285
292
  # @return [void]
286
- def wire_agent_delegation(delegator_name:, delegator_chat:, delegate_name_sym:, custom_tool_name:, tool_configurator:, create_nested_instances:)
293
+ def wire_agent_delegation(delegator_name:, delegator_chat:, delegate_name_sym:, custom_tool_name:, tool_configurator:, create_nested_instances:, preserve_context:)
287
294
  delegate_definition = @swarm.agent_definitions[delegate_name_sym]
288
295
 
289
296
  # Determine which chat instance to use
@@ -316,6 +323,7 @@ module SwarmSDK
316
323
  agent_name: delegator_name,
317
324
  delegating_chat: delegator_chat,
318
325
  custom_tool_name: custom_tool_name,
326
+ preserve_context: preserve_context,
319
327
  )
320
328
 
321
329
  # Register in tool registry (Plan 025)
@@ -325,6 +333,7 @@ module SwarmSDK
325
333
  metadata: {
326
334
  delegate_name: delegate_name_sym,
327
335
  delegation_mode: delegate_definition.shared_across_delegations ? :shared : :isolated,
336
+ preserve_context: preserve_context,
328
337
  },
329
338
  )
330
339
  end
@@ -37,7 +37,7 @@ module SwarmSDK
37
37
  end
38
38
  end
39
39
 
40
- attr_reader :delegate_name, :delegate_target, :tool_name
40
+ attr_reader :delegate_name, :delegate_target, :tool_name, :preserve_context
41
41
 
42
42
  # Initialize a delegation tool
43
43
  #
@@ -48,6 +48,7 @@ module SwarmSDK
48
48
  # @param swarm [Swarm] The swarm instance (provides hook_registry, delegation_call_stack, swarm_registry)
49
49
  # @param delegating_chat [Agent::Chat, nil] The chat instance of the agent doing the delegating (for accessing hooks)
50
50
  # @param custom_tool_name [String, nil] Optional custom tool name (overrides auto-generated name)
51
+ # @param preserve_context [Boolean] Whether to preserve conversation context between delegations (default: true)
51
52
  def initialize(
52
53
  delegate_name:,
53
54
  delegate_description:,
@@ -55,7 +56,8 @@ module SwarmSDK
55
56
  agent_name:,
56
57
  swarm:,
57
58
  delegating_chat: nil,
58
- custom_tool_name: nil
59
+ custom_tool_name: nil,
60
+ preserve_context: true
59
61
  )
60
62
  super()
61
63
 
@@ -65,6 +67,7 @@ module SwarmSDK
65
67
  @agent_name = agent_name
66
68
  @swarm = swarm
67
69
  @delegating_chat = delegating_chat
70
+ @preserve_context = preserve_context
68
71
 
69
72
  # Use custom tool name if provided, otherwise generate using canonical method
70
73
  @tool_name = custom_tool_name || self.class.tool_name_for(delegate_name)
@@ -81,6 +84,11 @@ module SwarmSDK
81
84
  desc: "Message to send to the agent - can be a work request, question, or collaboration message",
82
85
  required: true
83
86
 
87
+ param :reset_context,
88
+ type: "boolean",
89
+ desc: "Reset the agent's conversation history before sending the message. Use it to recover from 'prompt too long' errors or other 4XX errors.",
90
+ required: false
91
+
84
92
  # Override name to return custom delegation tool name
85
93
  def name
86
94
  @tool_name
@@ -89,8 +97,9 @@ module SwarmSDK
89
97
  # Execute delegation with pre/post hooks
90
98
  #
91
99
  # @param message [String] Message to send to the agent
100
+ # @param reset_context [Boolean] Whether to reset the agent's conversation history before delegation
92
101
  # @return [String] Result from delegate agent or error message
93
- def execute(message:)
102
+ def execute(message:, reset_context: false)
94
103
  # Access swarm infrastructure
95
104
  call_stack = @swarm.delegation_call_stack
96
105
  hook_registry = @swarm.hook_registry
@@ -137,10 +146,10 @@ module SwarmSDK
137
146
  # Determine delegation type and proceed
138
147
  delegation_result = if @delegate_chat
139
148
  # Delegate to agent
140
- delegate_to_agent(message, call_stack)
149
+ delegate_to_agent(message, call_stack, reset_context: reset_context)
141
150
  elsif swarm_registry&.registered?(@delegate_target)
142
151
  # Delegate to registered swarm
143
- delegate_to_swarm(message, call_stack, swarm_registry)
152
+ delegate_to_swarm(message, call_stack, swarm_registry, reset_context: reset_context)
144
153
  else
145
154
  raise ConfigurationError, "Unknown delegation target: #{@delegate_target}"
146
155
  end
@@ -219,11 +228,16 @@ module SwarmSDK
219
228
  #
220
229
  # @param message [String] Message to send to the agent
221
230
  # @param call_stack [Array] Delegation call stack for circular dependency detection
231
+ # @param reset_context [Boolean] Whether to reset the agent's conversation history before delegation
222
232
  # @return [String] Result from agent
223
- def delegate_to_agent(message, call_stack)
233
+ def delegate_to_agent(message, call_stack, reset_context: false)
224
234
  # Push delegate target onto call stack to track delegation chain
225
235
  call_stack.push(@delegate_target)
226
236
  begin
237
+ # Clear conversation if reset_context is true OR if preserve_context is false
238
+ # reset_context takes precedence as it's an explicit request
239
+ @delegate_chat.clear_conversation if reset_context || !@preserve_context
240
+
227
241
  response = @delegate_chat.ask(message, source: "delegation")
228
242
  response.content
229
243
  ensure
@@ -237,20 +251,24 @@ module SwarmSDK
237
251
  # @param message [String] Message to send to the swarm
238
252
  # @param call_stack [Array] Delegation call stack for circular dependency detection
239
253
  # @param swarm_registry [SwarmRegistry] Registry for sub-swarms
254
+ # @param reset_context [Boolean] Whether to reset the swarm's conversation history before delegation
240
255
  # @return [String] Result from swarm's lead agent
241
- def delegate_to_swarm(message, call_stack, swarm_registry)
256
+ def delegate_to_swarm(message, call_stack, swarm_registry, reset_context: false)
242
257
  # Load sub-swarm (lazy load + cache)
243
258
  subswarm = swarm_registry.load_swarm(@delegate_target)
244
259
 
245
260
  # Push delegate target onto call stack to track delegation chain
246
261
  call_stack.push(@delegate_target)
247
262
  begin
263
+ # Reset swarm if reset_context is true
264
+ swarm_registry.reset(@delegate_target) if reset_context
265
+
248
266
  # Execute sub-swarm's lead agent
249
267
  lead_agent = subswarm.agents[subswarm.lead_agent]
250
268
  response = lead_agent.ask(message, source: "delegation")
251
269
  result = response.content
252
270
 
253
- # Reset if keep_context: false
271
+ # Reset if keep_context: false (standard behavior)
254
272
  swarm_registry.reset_if_needed(@delegate_target)
255
273
 
256
274
  result
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SwarmSDK
4
- VERSION = "2.7.2"
4
+ VERSION = "2.7.4"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: swarm_sdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.7.2
4
+ version: 2.7.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paulo Arruda