swarm_sdk 2.7.1 → 2.7.3

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: ce0f1a16b02f241a7f0ce7cfb2ffcee3c3c073dc70066a1dfa7f9e8a90de566a
4
- data.tar.gz: 1ecf98d40c8bc3f4ccc5ff588fa4bf75a1087e0229de6afbeae342bac4679a27
3
+ metadata.gz: 9d0b44f3edf346a30b0442027c9ca2e8cf06e3e2c074c89f483c0eab0964a592
4
+ data.tar.gz: b7c690fd69303078c70c252a09a9e4f46b63f0f4a438a3fc9188cacc30e44109
5
5
  SHA512:
6
- metadata.gz: b083185a7ff36cd0fde32e3bca97427857917e40a9a2b6ca0fdfbb4dc42dd593edb7306bf1ab7bf854037a034d0982fc477e5a6ec3049361b65fc81900b1b647
7
- data.tar.gz: 57b97e291d2047e658b6a31af6d047af78217ba73fd7e39c83103b5003808d9fbd9d6c6b1218f199e3f1f7f5f0b9f917dde563a25122ce7c8a6e73a0babd79b2
6
+ metadata.gz: e0881dd9ae7fefc423bdbad4d56d535be627b622f2301eae1c12858d8198f7f55472198f6413535bccd768b17368233ac24ca5d2ab58417cbee9a7a68e8cdc79
7
+ data.tar.gz: a2af0ea8bf741a017196ce6db4d17a7b1bdc9fed2e517c35ae17c2336b950d25300186970f15b746fbc7dfd5c2679a53b9596d9f675c5a44089dc10672d542a0
@@ -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}"
@@ -207,6 +207,13 @@ module SwarmSDK
207
207
  # --- SwarmSDK Abstraction API ---
208
208
  # These methods provide SwarmSDK-specific semantics without exposing RubyLLM internals
209
209
 
210
+ # Check if streaming is enabled for this agent
211
+ #
212
+ # @return [Boolean] true if streaming is enabled
213
+ def streaming_enabled?
214
+ @streaming_enabled
215
+ end
216
+
210
217
  # Model information
211
218
  def model_id
212
219
  @llm_chat.model.id
@@ -681,6 +688,7 @@ module SwarmSDK
681
688
  if @streaming_enabled
682
689
  # Reset chunk type tracking for new streaming request
683
690
  @last_chunk_type = nil
691
+
684
692
  @llm_chat.complete(**options) do |chunk|
685
693
  emit_content_chunk(chunk)
686
694
  end
@@ -82,6 +82,88 @@ module SwarmSDK
82
82
 
83
83
  private
84
84
 
85
+ # Format citations for appending to response content
86
+ #
87
+ # Creates a markdown-formatted citations section with numbered links.
88
+ #
89
+ # @param citations [Array<String>] Array of citation URLs
90
+ # @return [String] Formatted citations section
91
+ def format_citations(citations)
92
+ return "" if citations.nil? || citations.empty?
93
+
94
+ formatted = "\n\n# Citations\n"
95
+ citations.each_with_index do |citation, index|
96
+ formatted += "- [#{index + 1}] #{citation}\n"
97
+ end
98
+ formatted
99
+ end
100
+
101
+ # Emit citations as a content_chunk event
102
+ #
103
+ # @param formatted_citations [String] Formatted citations text
104
+ # @param model_id [String] Model identifier
105
+ # @return [void]
106
+ def emit_citations_chunk(formatted_citations, model_id)
107
+ LogStream.emit(
108
+ type: "content_chunk",
109
+ agent: @agent_context.name,
110
+ chunk_type: "citations",
111
+ content: formatted_citations,
112
+ tool_calls: nil,
113
+ model: model_id,
114
+ )
115
+ rescue StandardError => e
116
+ RubyLLM.logger.debug("SwarmSDK: Failed to emit citations chunk: #{e.message}")
117
+ end
118
+
119
+ # Extract citations and search results from an assistant message
120
+ #
121
+ # These fields are provided by some LLM providers (e.g., Perplexity's sonar models)
122
+ # when the model performs web search or cites sources.
123
+ #
124
+ # @param message [RubyLLM::Message] Assistant message with potential citations
125
+ # @return [Hash] Citations and search results (empty if not present)
126
+ def extract_citations_and_search(message)
127
+ return {} unless message.raw&.body
128
+
129
+ body = message.raw.body
130
+
131
+ # For streaming responses, body might be empty - check Fiber-local
132
+ # (set by LLMInstrumentationMiddleware with accumulated SSE chunks)
133
+ if body.is_a?(String) && body.empty?
134
+ fiber_body = Fiber[:last_sse_body]
135
+ body = fiber_body if fiber_body
136
+ end
137
+
138
+ return {} unless body
139
+
140
+ # Handle SSE streaming responses (body is a string starting with "data:")
141
+ if body.is_a?(String) && body.start_with?("data:")
142
+ # Parse the LAST SSE event which contains citations
143
+ last_data_line = body.split("\n").reverse.find { |l| l.start_with?("data:") && !l.include?("[DONE]") && !l.include?("message_stop") }
144
+ if last_data_line
145
+ body = JSON.parse(last_data_line.sub(/^data:\s*/, ""))
146
+ end
147
+ elsif body.is_a?(String)
148
+ # Regular JSON string response
149
+ body = JSON.parse(body)
150
+ end
151
+
152
+ # Handle Faraday::Response objects (has .body method)
153
+ body = body.body if body.respond_to?(:body) && !body.is_a?(Hash)
154
+
155
+ return {} unless body.is_a?(Hash)
156
+
157
+ result = {}
158
+ result[:citations] = body["citations"] if body["citations"]
159
+ result[:search_results] = body["search_results"] if body["search_results"]
160
+ result
161
+ rescue StandardError => e
162
+ # Includes JSON::ParserError and other parsing errors
163
+ RubyLLM.logger.debug("SwarmSDK: Failed to extract citations: #{e.message}")
164
+ {}
165
+ end
166
+
85
167
  # Extract usage information from an assistant message
86
168
  #
87
169
  # @param message [RubyLLM::Message] Assistant message with usage data
@@ -202,6 +284,7 @@ module SwarmSDK
202
284
  return unless @chat.hook_executor
203
285
 
204
286
  usage_info = extract_usage_info(message)
287
+ citations_data = extract_citations_and_search(message)
205
288
 
206
289
  context = Hooks::Context.new(
207
290
  event: :agent_step,
@@ -213,9 +296,11 @@ module SwarmSDK
213
296
  tool_calls: format_tool_calls(message.tool_calls),
214
297
  finish_reason: "tool_calls",
215
298
  usage: usage_info,
299
+ citations: citations_data[:citations],
300
+ search_results: citations_data[:search_results],
216
301
  tool_executions: tool_executions.empty? ? nil : tool_executions,
217
302
  timestamp: Time.now.utc.iso8601,
218
- },
303
+ }.compact,
219
304
  )
220
305
 
221
306
  agent_hooks = @chat.hook_agent_hooks[:agent_step] || []
@@ -238,6 +323,22 @@ module SwarmSDK
238
323
  return unless @chat.hook_executor
239
324
 
240
325
  usage_info = extract_usage_info(message)
326
+ citations_data = extract_citations_and_search(message)
327
+
328
+ # Format content with citations appended
329
+ content_with_citations = message.content
330
+ if citations_data[:citations] && !citations_data[:citations].empty?
331
+ formatted_citations = format_citations(citations_data[:citations])
332
+ content_with_citations = message.content + formatted_citations
333
+
334
+ # Also modify the original message for Result.content
335
+ message.content = content_with_citations
336
+
337
+ # Emit citations chunk if streaming is enabled
338
+ if @chat.streaming_enabled?
339
+ emit_citations_chunk(formatted_citations, message.model_id)
340
+ end
341
+ end
241
342
 
242
343
  # Use override if set (e.g., "finish_agent"), otherwise default to "stop"
243
344
  finish_reason = @finish_reason_override || "stop"
@@ -249,13 +350,15 @@ module SwarmSDK
249
350
  swarm: @chat.hook_swarm,
250
351
  metadata: {
251
352
  model: message.model_id,
252
- content: message.content,
353
+ content: content_with_citations, # Content with citations appended
253
354
  tool_calls: nil, # Final response has no tool calls
254
355
  finish_reason: finish_reason,
255
356
  usage: usage_info,
357
+ citations: citations_data[:citations],
358
+ search_results: citations_data[:search_results],
256
359
  tool_executions: tool_executions.empty? ? nil : tool_executions,
257
360
  timestamp: Time.now.utc.iso8601,
258
- },
361
+ }.compact,
259
362
  )
260
363
 
261
364
  agent_hooks = @chat.hook_agent_hooks[:agent_stop] || []
@@ -13,10 +13,15 @@ module SwarmSDK
13
13
  #
14
14
  # @return [void]
15
15
  def inject_llm_instrumentation
16
+ puts "=== inject_llm_instrumentation called ===" if ENV["DEBUG_CITATIONS"]
16
17
  return unless @provider
17
18
 
19
+ puts "=== Has provider ===" if ENV["DEBUG_CITATIONS"]
20
+
18
21
  faraday_conn = @provider.connection&.connection
19
22
  return unless faraday_conn
23
+
24
+ puts "=== Has faraday connection ===" if ENV["DEBUG_CITATIONS"]
20
25
  return if @llm_instrumentation_injected
21
26
 
22
27
  provider_name = @provider.class.name.split("::").last.downcase
@@ -31,8 +36,10 @@ module SwarmSDK
31
36
 
32
37
  @llm_instrumentation_injected = true
33
38
 
39
+ puts "=== MIDDLEWARE INJECTED ===" if ENV["DEBUG_CITATIONS"]
34
40
  RubyLLM.logger.debug("SwarmSDK: Injected LLM instrumentation middleware for agent #{@agent_name}")
35
41
  rescue StandardError => e
42
+ puts "=== MIDDLEWARE INJECTION ERROR: #{e.message} ===" if ENV["DEBUG_CITATIONS"]
36
43
  LogStream.emit_error(e, source: "instrumentation", context: "inject_middleware", agent: @agent_name)
37
44
  RubyLLM.logger.debug("SwarmSDK: Failed to inject LLM instrumentation: #{e.message}")
38
45
  end
@@ -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}"
@@ -39,8 +39,6 @@ module SwarmSDK
39
39
  emit_request_event(env, start_time)
40
40
 
41
41
  # Wrap existing on_data to capture raw SSE chunks for streaming
42
- # This allows us to capture the full streaming response for instrumentation
43
- # Check if env.request exists and has on_data (only set for streaming requests)
44
42
  if env.request&.on_data
45
43
  original_on_data = env.request.on_data
46
44
  env.request.on_data = proc do |chunk, bytes, response_env|
@@ -64,6 +62,11 @@ module SwarmSDK
64
62
  response_env.body
65
63
  end
66
64
 
65
+ # Store SSE body in Fiber-local for citation extraction
66
+ # This allows append_citations_to_content to access the full SSE body
67
+ # even though response.body is empty for streaming responses
68
+ Fiber[:last_sse_body] = raw_body if accumulated_raw_chunks.any?
69
+
67
70
  # Emit response event
68
71
  emit_response_event(response_env, start_time, end_time, duration, raw_body)
69
72
  end
@@ -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
@@ -238,7 +238,14 @@ module SwarmSDK
238
238
  return unless LogStream.emitter
239
239
 
240
240
  metadata_without_duplicates = context.metadata.except(
241
- :model, :content, :tool_calls, :finish_reason, :usage, :tool_executions
241
+ :model,
242
+ :content,
243
+ :tool_calls,
244
+ :finish_reason,
245
+ :usage,
246
+ :tool_executions,
247
+ :citations,
248
+ :search_results,
242
249
  )
243
250
 
244
251
  LogStream.emit(
@@ -251,6 +258,8 @@ module SwarmSDK
251
258
  tool_calls: context.metadata[:tool_calls],
252
259
  finish_reason: context.metadata[:finish_reason],
253
260
  usage: context.metadata[:usage],
261
+ citations: context.metadata[:citations],
262
+ search_results: context.metadata[:search_results],
254
263
  tool_executions: context.metadata[:tool_executions],
255
264
  metadata: metadata_without_duplicates,
256
265
  )
@@ -261,7 +270,14 @@ module SwarmSDK
261
270
  return unless LogStream.emitter
262
271
 
263
272
  metadata_without_duplicates = context.metadata.except(
264
- :model, :content, :tool_calls, :finish_reason, :usage, :tool_executions
273
+ :model,
274
+ :content,
275
+ :tool_calls,
276
+ :finish_reason,
277
+ :usage,
278
+ :tool_executions,
279
+ :citations,
280
+ :search_results,
265
281
  )
266
282
 
267
283
  LogStream.emit(
@@ -274,6 +290,8 @@ module SwarmSDK
274
290
  tool_calls: context.metadata[:tool_calls],
275
291
  finish_reason: context.metadata[:finish_reason],
276
292
  usage: context.metadata[:usage],
293
+ citations: context.metadata[:citations],
294
+ search_results: context.metadata[:search_results],
277
295
  tool_executions: context.metadata[:tool_executions],
278
296
  metadata: metadata_without_duplicates,
279
297
  )
@@ -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)
@@ -224,6 +227,9 @@ module SwarmSDK
224
227
  # Push delegate target onto call stack to track delegation chain
225
228
  call_stack.push(@delegate_target)
226
229
  begin
230
+ # Clear conversation if preserve_context is false
231
+ @delegate_chat.clear_conversation unless @preserve_context
232
+
227
233
  response = @delegate_chat.ask(message, source: "delegation")
228
234
  response.content
229
235
  ensure
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SwarmSDK
4
- VERSION = "2.7.1"
4
+ VERSION = "2.7.3"
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.1
4
+ version: 2.7.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paulo Arruda