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,170 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module SwarmCLI
4
- module UI
5
- module State
6
- # Manages active spinners with elapsed time display
7
- class SpinnerManager
8
- def initialize
9
- @active_spinners = {}
10
- @time_updaters = {}
11
- end
12
-
13
- # Start a spinner with elapsed time tracking
14
- #
15
- # @param key [Symbol, String] Unique key for this spinner
16
- # @param message [String] Spinner message
17
- # @param format [Symbol] Spinner format (:dots, :pulse, etc.)
18
- # @return [TTY::Spinner] The spinner instance
19
- def start(key, message, format: :dots)
20
- # Stop any existing spinner with this key
21
- stop(key) if @active_spinners[key]
22
-
23
- # Create spinner with elapsed time token
24
- spinner = TTY::Spinner.new(
25
- "[:spinner] #{message} (:elapsed)",
26
- format: format,
27
- hide_cursor: true,
28
- )
29
-
30
- spinner.auto_spin
31
-
32
- # Spawn thread to update elapsed time every 1 second
33
- # This is 10x slower than spinner animation (100ms), preventing flicker
34
- @time_updaters[key] = Thread.new do
35
- loop do
36
- elapsed = spinner.duration
37
- break unless elapsed
38
-
39
- formatted_time = format_duration(elapsed)
40
- spinner.update(elapsed: formatted_time)
41
- sleep(1.0) # 1s refresh rate - smooth without flicker
42
- rescue StandardError
43
- break
44
- end
45
- end
46
-
47
- @active_spinners[key] = spinner
48
- spinner
49
- end
50
-
51
- # Stop spinner with success
52
- #
53
- # @param key [Symbol, String] Spinner key
54
- # @param message [String] Success message
55
- def success(key, message = "completed")
56
- spinner = @active_spinners[key]
57
- return unless spinner
58
-
59
- # Kill time updater
60
- kill_updater(key)
61
-
62
- # Show final time
63
- final_time = format_duration(spinner.duration || 0)
64
- spinner.success("#{message} (#{final_time})")
65
-
66
- cleanup(key)
67
- end
68
-
69
- # Stop spinner with error
70
- #
71
- # @param key [Symbol, String] Spinner key
72
- # @param message [String] Error message
73
- def error(key, message = "failed")
74
- spinner = @active_spinners[key]
75
- return unless spinner
76
-
77
- # Kill time updater
78
- kill_updater(key)
79
-
80
- # Show final time
81
- final_time = format_duration(spinner.duration || 0)
82
- spinner.error("#{message} (#{final_time})")
83
-
84
- cleanup(key)
85
- end
86
-
87
- # Stop spinner without success/error (just stop)
88
- #
89
- # @param key [Symbol, String] Spinner key
90
- def stop(key)
91
- spinner = @active_spinners[key]
92
- return unless spinner
93
-
94
- kill_updater(key)
95
- spinner.stop
96
- cleanup(key)
97
- end
98
-
99
- # Stop all active spinners
100
- def stop_all
101
- @active_spinners.keys.each { |key| stop(key) }
102
- end
103
-
104
- # Check if a spinner is active
105
- #
106
- # @param key [Symbol, String] Spinner key
107
- # @return [Boolean]
108
- def active?(key)
109
- @active_spinners.key?(key)
110
- end
111
-
112
- # Pause all active spinners (for interactive debugging)
113
- #
114
- # This temporarily stops spinner animation while preserving state,
115
- # allowing interactive sessions like binding.irb to run cleanly.
116
- #
117
- # @return [void]
118
- def pause_all
119
- @active_spinners.each_value do |spinner|
120
- spinner.stop if spinner.spinning?
121
- end
122
-
123
- # Keep time updaters running (they'll safely handle stopped spinners)
124
- end
125
-
126
- # Resume all paused spinners
127
- #
128
- # Restarts spinner animation for all spinners that were paused.
129
- #
130
- # @return [void]
131
- def resume_all
132
- @active_spinners.each_value do |spinner|
133
- spinner.auto_spin unless spinner.spinning?
134
- end
135
- end
136
-
137
- private
138
-
139
- def kill_updater(key)
140
- updater = @time_updaters[key]
141
- return unless updater
142
-
143
- updater.kill if updater.alive?
144
- @time_updaters.delete(key)
145
- end
146
-
147
- def cleanup(key)
148
- @active_spinners.delete(key)
149
- @time_updaters.delete(key)
150
- end
151
-
152
- def format_duration(seconds)
153
- if seconds < 1
154
- "#{(seconds * 1000).round}ms"
155
- elsif seconds < 60
156
- "#{seconds.round}s"
157
- elsif seconds < 3600
158
- minutes = (seconds / 60).floor
159
- secs = (seconds % 60).round
160
- "#{minutes}m #{secs}s"
161
- else
162
- hours = (seconds / 3600).floor
163
- minutes = ((seconds % 3600) / 60).floor
164
- "#{hours}h #{minutes}m"
165
- end
166
- end
167
- end
168
- end
169
- end
170
- end
@@ -1,62 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module SwarmCLI
4
- module UI
5
- module State
6
- # Tracks cumulative usage statistics during swarm execution
7
- class UsageTracker
8
- attr_reader :total_cost, :total_tokens, :llm_requests, :tool_calls
9
-
10
- def initialize
11
- @total_cost = 0.0
12
- @total_tokens = 0
13
- @llm_requests = 0
14
- @tool_calls = 0
15
- @agents_seen = Set.new
16
- @recent_tool_calls = {} # tool_call_id => tool_name for matching
17
- end
18
-
19
- # Track an LLM API call
20
- def track_llm_request(usage_data)
21
- @llm_requests += 1
22
-
23
- if usage_data
24
- @total_cost += usage_data[:total_cost] || 0.0
25
- @total_tokens += usage_data[:total_tokens] || 0
26
- end
27
- end
28
-
29
- # Track a tool call
30
- def track_tool_call(tool_call_id: nil, tool_name: nil)
31
- @tool_calls += 1
32
- @recent_tool_calls[tool_call_id] = tool_name if tool_call_id && tool_name
33
- end
34
-
35
- # Track agent usage
36
- def track_agent(agent_name)
37
- @agents_seen.add(agent_name)
38
- end
39
-
40
- # Get list of agents seen
41
- def agents
42
- @agents_seen.to_a
43
- end
44
-
45
- # Get tool name from call ID
46
- def tool_name_for(tool_call_id)
47
- @recent_tool_calls[tool_call_id]
48
- end
49
-
50
- # Reset all counters (for testing)
51
- def reset
52
- @total_cost = 0.0
53
- @total_tokens = 0
54
- @llm_requests = 0
55
- @tool_calls = 0
56
- @agents_seen.clear
57
- @recent_tool_calls.clear
58
- end
59
- end
60
- end
61
- end
62
- end
@@ -1,5 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module SwarmCLI
4
- VERSION = "2.1.4"
5
- end
data/lib/swarm_cli.rb DELETED
@@ -1,46 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "fileutils"
4
- require "json"
5
- require "pathname"
6
- require "yaml"
7
-
8
- require "reline"
9
- require "pastel"
10
- require "tty-box"
11
- require "tty-screen"
12
- require "tty/link"
13
- require "tty/markdown"
14
- require "tty/option"
15
- require "tty/spinner"
16
- require "tty/spinner/multi"
17
- require "tty/tree"
18
-
19
- require "swarm_sdk"
20
-
21
- require_relative "swarm_cli/version"
22
-
23
- require "zeitwerk"
24
- loader = Zeitwerk::Loader.new
25
- loader.tag = File.basename(__FILE__, ".rb")
26
- loader.push_dir("#{__dir__}/swarm_cli", namespace: SwarmCLI)
27
- loader.inflector = Zeitwerk::GemInflector.new(__FILE__)
28
- loader.inflector.inflect(
29
- "cli" => "CLI",
30
- "ui" => "UI",
31
- "interactive_repl" => "InteractiveREPL",
32
- )
33
- loader.setup
34
-
35
- module SwarmCLI
36
- class Error < StandardError; end
37
- class ConfigurationError < Error; end
38
- class ExecutionError < Error; end
39
- end
40
-
41
- # Try to load swarm_memory gem if available (for CLI command extensions)
42
- begin
43
- require "swarm_memory"
44
- rescue LoadError
45
- # swarm_memory not installed - that's fine, memory commands won't be available
46
- end
@@ -1,127 +0,0 @@
1
- # LLM Call Retry Logic
2
-
3
- ## Feature
4
-
5
- SwarmSDK automatically retries failed LLM API calls to handle transient failures.
6
-
7
- ## Configuration
8
-
9
- **Defaults:**
10
- - Max retries: 10
11
- - Delay: 10 seconds (fixed, no exponential backoff)
12
- - Retries ALL StandardError exceptions
13
-
14
- ## Implementation
15
-
16
- **Location:** `lib/swarm_sdk/agent/chat.rb:768-801`
17
-
18
- ```ruby
19
- def call_llm_with_retry(max_retries: 10, delay: 10, &block)
20
- attempts = 0
21
- loop do
22
- attempts += 1
23
- begin
24
- return yield
25
- rescue StandardError => e
26
- raise if attempts >= max_retries
27
-
28
- RubyLLM.logger.warn("SwarmSDK: LLM call failed (attempt #{attempts}/#{max_retries})")
29
- sleep(delay)
30
- end
31
- end
32
- end
33
- ```
34
-
35
- ## Error Types Handled
36
-
37
- - `Faraday::ConnectionFailed` - Network connection issues
38
- - `Faraday::TimeoutError` - Request timeouts
39
- - `RubyLLM::APIError` - API errors (500s, etc.)
40
- - `RubyLLM::RateLimitError` - Rate limit errors
41
- - `RubyLLM::BadRequestError` - Usually not transient, but retries anyway
42
- - Any other `StandardError` - Catches proxy issues, DNS failures, etc.
43
-
44
- ## Usage
45
-
46
- **Automatic - No Configuration Needed:**
47
-
48
- ```ruby
49
- swarm = SwarmSDK.build do
50
- agent :my_agent do
51
- model "gpt-4"
52
- base_url "http://proxy.example.com/v1" # Can fail
53
- end
54
- end
55
-
56
- # Automatically retries on failure
57
- response = swarm.execute("Do something")
58
- ```
59
-
60
- ## Logging
61
-
62
- **On Retry:**
63
- ```
64
- WARN: SwarmSDK: LLM call failed (attempt 1/10): Faraday::ConnectionFailed: Connection failed
65
- WARN: SwarmSDK: Retrying in 10 seconds...
66
- ```
67
-
68
- **On Max Retries:**
69
- ```
70
- ERROR: SwarmSDK: LLM call failed after 10 attempts: Faraday::ConnectionFailed: Connection failed
71
- ```
72
-
73
- ## Testing
74
-
75
- Retry logic has been verified through:
76
- - ✅ All 728 SwarmSDK tests passing
77
- - ✅ Manual testing with failing proxies
78
- - ✅ Evaluation harnesses (assistant/retrieval modes)
79
-
80
- **Note:** Direct unit tests would require reflection (`instance_variable_set`) which violates security policy. The retry logic is tested implicitly through integration tests and real usage.
81
-
82
- ## Behavior
83
-
84
- **Scenario 1: Transient failure**
85
- ```
86
- Attempt 1: ConnectionFailed
87
- → Wait 10s
88
- Attempt 2: ConnectionFailed
89
- → Wait 10s
90
- Attempt 3: Success
91
- → Returns response
92
- ```
93
-
94
- **Scenario 2: Persistent failure**
95
- ```
96
- Attempt 1-10: All fail
97
- → Raises original error after attempt 10
98
- ```
99
-
100
- **Scenario 3: Immediate success**
101
- ```
102
- Attempt 1: Success
103
- → Returns response (no retry needed)
104
- ```
105
-
106
- ## Why No Exponential Backoff
107
-
108
- **Design Decision:** Fixed 10-second delay
109
-
110
- **Rationale:**
111
- - Simpler implementation
112
- - Predictable retry duration (max 100 seconds)
113
- - Transient proxy/network issues typically resolve within seconds
114
- - Rate limit errors are caught by provider-specific handling
115
- - User explicitly requested fixed delays
116
-
117
- **Total max time:** 10 retries × 10 seconds = 100 seconds maximum
118
-
119
- ## Future Enhancements (If Needed)
120
-
121
- - [ ] Configurable retry count per agent
122
- - [ ] Configurable delay per agent
123
- - [ ] Selective retry based on error type
124
- - [ ] Exponential backoff option
125
- - [ ] Circuit breaker pattern
126
-
127
- **Current State:** Production-ready with sensible defaults for proxy/network resilience.