swarm_sdk 2.7.13 → 3.0.0.alpha1

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 (183) hide show
  1. checksums.yaml +4 -4
  2. data/lib/swarm_sdk/ruby_llm_patches/chat_callbacks_patch.rb +43 -22
  3. data/lib/swarm_sdk/ruby_llm_patches/init.rb +6 -0
  4. data/lib/swarm_sdk/ruby_llm_patches/mcp_ssl_patch.rb +144 -0
  5. data/lib/swarm_sdk/ruby_llm_patches/tool_concurrency_patch.rb +3 -4
  6. data/lib/swarm_sdk/v3/agent.rb +1165 -0
  7. data/lib/swarm_sdk/v3/agent_builder.rb +533 -0
  8. data/lib/swarm_sdk/v3/agent_definition.rb +330 -0
  9. data/lib/swarm_sdk/v3/configuration.rb +490 -0
  10. data/lib/swarm_sdk/v3/debug_log.rb +86 -0
  11. data/lib/swarm_sdk/v3/event_stream.rb +130 -0
  12. data/lib/swarm_sdk/v3/hooks/context.rb +112 -0
  13. data/lib/swarm_sdk/v3/hooks/result.rb +115 -0
  14. data/lib/swarm_sdk/v3/hooks/runner.rb +128 -0
  15. data/lib/swarm_sdk/v3/mcp/connector.rb +183 -0
  16. data/lib/swarm_sdk/v3/mcp/mcp_error.rb +15 -0
  17. data/lib/swarm_sdk/v3/mcp/server_definition.rb +125 -0
  18. data/lib/swarm_sdk/v3/mcp/ssl_http_transport.rb +103 -0
  19. data/lib/swarm_sdk/v3/mcp/stdio_transport.rb +135 -0
  20. data/lib/swarm_sdk/v3/mcp/tool_proxy.rb +53 -0
  21. data/lib/swarm_sdk/v3/memory/adapters/base.rb +297 -0
  22. data/lib/swarm_sdk/v3/memory/adapters/faiss_support.rb +194 -0
  23. data/lib/swarm_sdk/v3/memory/adapters/filesystem_adapter.rb +212 -0
  24. data/lib/swarm_sdk/v3/memory/adapters/sqlite_adapter.rb +507 -0
  25. data/lib/swarm_sdk/v3/memory/adapters/vector_utils.rb +88 -0
  26. data/lib/swarm_sdk/v3/memory/card.rb +206 -0
  27. data/lib/swarm_sdk/v3/memory/cluster.rb +146 -0
  28. data/lib/swarm_sdk/v3/memory/compressor.rb +496 -0
  29. data/lib/swarm_sdk/v3/memory/consolidator.rb +427 -0
  30. data/lib/swarm_sdk/v3/memory/context_builder.rb +339 -0
  31. data/lib/swarm_sdk/v3/memory/edge.rb +105 -0
  32. data/lib/swarm_sdk/v3/memory/embedder.rb +185 -0
  33. data/lib/swarm_sdk/v3/memory/exposure_tracker.rb +104 -0
  34. data/lib/swarm_sdk/v3/memory/ingestion_pipeline.rb +394 -0
  35. data/lib/swarm_sdk/v3/memory/retriever.rb +289 -0
  36. data/lib/swarm_sdk/v3/memory/store.rb +489 -0
  37. data/lib/swarm_sdk/v3/skills/loader.rb +147 -0
  38. data/lib/swarm_sdk/v3/skills/manifest.rb +45 -0
  39. data/lib/swarm_sdk/v3/sub_task_agent.rb +248 -0
  40. data/lib/swarm_sdk/v3/tools/base.rb +80 -0
  41. data/lib/swarm_sdk/v3/tools/bash.rb +174 -0
  42. data/lib/swarm_sdk/v3/tools/clock.rb +32 -0
  43. data/lib/swarm_sdk/v3/tools/edit.rb +111 -0
  44. data/lib/swarm_sdk/v3/tools/glob.rb +96 -0
  45. data/lib/swarm_sdk/v3/tools/grep.rb +200 -0
  46. data/lib/swarm_sdk/v3/tools/message_teammate.rb +15 -0
  47. data/lib/swarm_sdk/v3/tools/message_user.rb +15 -0
  48. data/lib/swarm_sdk/v3/tools/read.rb +181 -0
  49. data/lib/swarm_sdk/v3/tools/read_tracker.rb +40 -0
  50. data/lib/swarm_sdk/v3/tools/registry.rb +208 -0
  51. data/lib/swarm_sdk/v3/tools/sub_task.rb +183 -0
  52. data/lib/swarm_sdk/v3/tools/think.rb +88 -0
  53. data/lib/swarm_sdk/v3/tools/write.rb +87 -0
  54. data/lib/swarm_sdk/v3.rb +145 -0
  55. metadata +84 -148
  56. data/lib/swarm_sdk/agent/RETRY_LOGIC.md +0 -175
  57. data/lib/swarm_sdk/agent/builder.rb +0 -680
  58. data/lib/swarm_sdk/agent/chat.rb +0 -1432
  59. data/lib/swarm_sdk/agent/chat_helpers/context_tracker.rb +0 -375
  60. data/lib/swarm_sdk/agent/chat_helpers/event_emitter.rb +0 -204
  61. data/lib/swarm_sdk/agent/chat_helpers/hook_integration.rb +0 -480
  62. data/lib/swarm_sdk/agent/chat_helpers/instrumentation.rb +0 -85
  63. data/lib/swarm_sdk/agent/chat_helpers/llm_configuration.rb +0 -290
  64. data/lib/swarm_sdk/agent/chat_helpers/logging_helpers.rb +0 -116
  65. data/lib/swarm_sdk/agent/chat_helpers/serialization.rb +0 -83
  66. data/lib/swarm_sdk/agent/chat_helpers/system_reminder_injector.rb +0 -134
  67. data/lib/swarm_sdk/agent/chat_helpers/system_reminders.rb +0 -79
  68. data/lib/swarm_sdk/agent/chat_helpers/token_tracking.rb +0 -146
  69. data/lib/swarm_sdk/agent/context.rb +0 -115
  70. data/lib/swarm_sdk/agent/context_manager.rb +0 -315
  71. data/lib/swarm_sdk/agent/definition.rb +0 -581
  72. data/lib/swarm_sdk/agent/llm_instrumentation_middleware.rb +0 -226
  73. data/lib/swarm_sdk/agent/system_prompt_builder.rb +0 -161
  74. data/lib/swarm_sdk/agent/tool_registry.rb +0 -189
  75. data/lib/swarm_sdk/agent_registry.rb +0 -146
  76. data/lib/swarm_sdk/builders/base_builder.rb +0 -553
  77. data/lib/swarm_sdk/claude_code_agent_adapter.rb +0 -205
  78. data/lib/swarm_sdk/concerns/cleanupable.rb +0 -39
  79. data/lib/swarm_sdk/concerns/snapshotable.rb +0 -67
  80. data/lib/swarm_sdk/concerns/validatable.rb +0 -55
  81. data/lib/swarm_sdk/config.rb +0 -367
  82. data/lib/swarm_sdk/configuration/parser.rb +0 -397
  83. data/lib/swarm_sdk/configuration/translator.rb +0 -283
  84. data/lib/swarm_sdk/configuration.rb +0 -165
  85. data/lib/swarm_sdk/context_compactor/metrics.rb +0 -147
  86. data/lib/swarm_sdk/context_compactor/token_counter.rb +0 -102
  87. data/lib/swarm_sdk/context_compactor.rb +0 -335
  88. data/lib/swarm_sdk/context_management/builder.rb +0 -128
  89. data/lib/swarm_sdk/context_management/context.rb +0 -328
  90. data/lib/swarm_sdk/custom_tool_registry.rb +0 -226
  91. data/lib/swarm_sdk/defaults.rb +0 -251
  92. data/lib/swarm_sdk/events_to_messages.rb +0 -199
  93. data/lib/swarm_sdk/hooks/adapter.rb +0 -359
  94. data/lib/swarm_sdk/hooks/context.rb +0 -197
  95. data/lib/swarm_sdk/hooks/definition.rb +0 -80
  96. data/lib/swarm_sdk/hooks/error.rb +0 -29
  97. data/lib/swarm_sdk/hooks/executor.rb +0 -146
  98. data/lib/swarm_sdk/hooks/registry.rb +0 -147
  99. data/lib/swarm_sdk/hooks/result.rb +0 -150
  100. data/lib/swarm_sdk/hooks/shell_executor.rb +0 -256
  101. data/lib/swarm_sdk/hooks/tool_call.rb +0 -35
  102. data/lib/swarm_sdk/hooks/tool_result.rb +0 -62
  103. data/lib/swarm_sdk/log_collector.rb +0 -227
  104. data/lib/swarm_sdk/log_stream.rb +0 -127
  105. data/lib/swarm_sdk/markdown_parser.rb +0 -75
  106. data/lib/swarm_sdk/model_aliases.json +0 -8
  107. data/lib/swarm_sdk/models.json +0 -44002
  108. data/lib/swarm_sdk/models.rb +0 -161
  109. data/lib/swarm_sdk/node_context.rb +0 -245
  110. data/lib/swarm_sdk/observer/builder.rb +0 -81
  111. data/lib/swarm_sdk/observer/config.rb +0 -45
  112. data/lib/swarm_sdk/observer/manager.rb +0 -236
  113. data/lib/swarm_sdk/patterns/agent_observer.rb +0 -160
  114. data/lib/swarm_sdk/permissions/config.rb +0 -239
  115. data/lib/swarm_sdk/permissions/error_formatter.rb +0 -121
  116. data/lib/swarm_sdk/permissions/path_matcher.rb +0 -35
  117. data/lib/swarm_sdk/permissions/validator.rb +0 -173
  118. data/lib/swarm_sdk/permissions_builder.rb +0 -122
  119. data/lib/swarm_sdk/plugin.rb +0 -309
  120. data/lib/swarm_sdk/plugin_registry.rb +0 -101
  121. data/lib/swarm_sdk/proc_helpers.rb +0 -53
  122. data/lib/swarm_sdk/prompts/base_system_prompt.md.erb +0 -117
  123. data/lib/swarm_sdk/restore_result.rb +0 -65
  124. data/lib/swarm_sdk/result.rb +0 -212
  125. data/lib/swarm_sdk/snapshot.rb +0 -156
  126. data/lib/swarm_sdk/snapshot_from_events.rb +0 -397
  127. data/lib/swarm_sdk/state_restorer.rb +0 -476
  128. data/lib/swarm_sdk/state_snapshot.rb +0 -334
  129. data/lib/swarm_sdk/swarm/agent_initializer.rb +0 -648
  130. data/lib/swarm_sdk/swarm/all_agents_builder.rb +0 -195
  131. data/lib/swarm_sdk/swarm/builder.rb +0 -256
  132. data/lib/swarm_sdk/swarm/executor.rb +0 -290
  133. data/lib/swarm_sdk/swarm/hook_triggers.rb +0 -151
  134. data/lib/swarm_sdk/swarm/lazy_delegate_chat.rb +0 -372
  135. data/lib/swarm_sdk/swarm/logging_callbacks.rb +0 -360
  136. data/lib/swarm_sdk/swarm/mcp_configurator.rb +0 -270
  137. data/lib/swarm_sdk/swarm/swarm_registry_builder.rb +0 -67
  138. data/lib/swarm_sdk/swarm/tool_configurator.rb +0 -392
  139. data/lib/swarm_sdk/swarm.rb +0 -843
  140. data/lib/swarm_sdk/swarm_loader.rb +0 -145
  141. data/lib/swarm_sdk/swarm_registry.rb +0 -136
  142. data/lib/swarm_sdk/tools/base.rb +0 -63
  143. data/lib/swarm_sdk/tools/bash.rb +0 -280
  144. data/lib/swarm_sdk/tools/clock.rb +0 -46
  145. data/lib/swarm_sdk/tools/delegate.rb +0 -389
  146. data/lib/swarm_sdk/tools/document_converters/base_converter.rb +0 -83
  147. data/lib/swarm_sdk/tools/document_converters/docx_converter.rb +0 -99
  148. data/lib/swarm_sdk/tools/document_converters/html_converter.rb +0 -101
  149. data/lib/swarm_sdk/tools/document_converters/pdf_converter.rb +0 -78
  150. data/lib/swarm_sdk/tools/document_converters/xlsx_converter.rb +0 -194
  151. data/lib/swarm_sdk/tools/edit.rb +0 -145
  152. data/lib/swarm_sdk/tools/glob.rb +0 -166
  153. data/lib/swarm_sdk/tools/grep.rb +0 -235
  154. data/lib/swarm_sdk/tools/image_extractors/docx_image_extractor.rb +0 -43
  155. data/lib/swarm_sdk/tools/image_extractors/pdf_image_extractor.rb +0 -167
  156. data/lib/swarm_sdk/tools/image_formats/tiff_builder.rb +0 -65
  157. data/lib/swarm_sdk/tools/mcp_tool_stub.rb +0 -198
  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 -273
  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 -100
  170. data/lib/swarm_sdk/tools/todo_write.rb +0 -237
  171. data/lib/swarm_sdk/tools/web_fetch.rb +0 -264
  172. data/lib/swarm_sdk/tools/write.rb +0 -112
  173. data/lib/swarm_sdk/transcript_builder.rb +0 -278
  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 -95
  178. data/lib/swarm_sdk/workflow/builder.rb +0 -227
  179. data/lib/swarm_sdk/workflow/executor.rb +0 -497
  180. data/lib/swarm_sdk/workflow/node_builder.rb +0 -593
  181. data/lib/swarm_sdk/workflow/transformer_executor.rb +0 -250
  182. data/lib/swarm_sdk/workflow.rb +0 -589
  183. data/lib/swarm_sdk.rb +0 -718
@@ -1,251 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module SwarmSDK
4
- # Centralized configuration defaults for SwarmSDK
5
- #
6
- # This module provides well-documented default values for all configurable
7
- # aspects of the SDK. Values are organized by category and include explanations
8
- # for their purpose and rationale.
9
- #
10
- # @example Accessing defaults
11
- # SwarmSDK::Defaults::Timeouts::AGENT_REQUEST_SECONDS
12
- # SwarmSDK::Defaults::Concurrency::GLOBAL_LIMIT
13
- # SwarmSDK::Defaults::Limits::OUTPUT_CHARACTERS
14
- module Defaults
15
- # Concurrency limits for parallel execution
16
- #
17
- # These limits prevent overwhelming external services and ensure
18
- # fair resource usage across the system.
19
- module Concurrency
20
- # Maximum concurrent API calls across entire swarm
21
- #
22
- # This limits total parallel LLM API requests to prevent rate limiting
23
- # and excessive resource consumption. 50 is a balanced value that allows
24
- # good parallelism while respecting API rate limits.
25
- GLOBAL_LIMIT = 50
26
-
27
- # Maximum parallel tool executions per agent
28
- #
29
- # Limits concurrent tool calls within a single agent. 10 allows
30
- # meaningful parallelism (e.g., reading multiple files) without
31
- # overwhelming the system.
32
- LOCAL_LIMIT = 10
33
- end
34
-
35
- # Timeout values for various operations
36
- #
37
- # All timeouts are in seconds unless explicitly marked as milliseconds.
38
- # Timeouts balance responsiveness with allowing enough time for operations
39
- # to complete successfully.
40
- module Timeouts
41
- # LLM API request timeout (seconds)
42
- #
43
- # Default timeout for Claude/GPT API calls. 5 minutes accommodates
44
- # reasoning models (o1, Claude with extended thinking) which can take
45
- # longer to process complex queries.
46
- AGENT_REQUEST_SECONDS = 300
47
-
48
- # Bash command execution timeout (milliseconds)
49
- #
50
- # Default timeout for shell commands. 2 minutes balances allowing
51
- # build/test commands while preventing runaway processes.
52
- BASH_COMMAND_MS = 120_000
53
-
54
- # Maximum Bash command timeout (milliseconds)
55
- #
56
- # Hard upper limit for bash commands. 10 minutes prevents indefinitely
57
- # running commands while allowing long builds/tests.
58
- BASH_COMMAND_MAX_MS = 600_000
59
-
60
- # Web fetch timeout (seconds)
61
- #
62
- # Timeout for HTTP requests in WebFetch tool. 30 seconds is standard
63
- # for web requests, allowing slow servers while timing out unresponsive ones.
64
- WEB_FETCH_SECONDS = 30
65
-
66
- # Shell hook executor timeout (seconds)
67
- #
68
- # Default timeout for hook shell commands. 60 seconds allows complex
69
- # pre/post hooks while preventing indefinite blocking.
70
- HOOK_SHELL_SECONDS = 60
71
-
72
- # Workflow transformer command timeout (seconds)
73
- #
74
- # Timeout for input/output transformer bash commands. 60 seconds allows
75
- # data transformation operations while preventing stalls.
76
- TRANSFORMER_COMMAND_SECONDS = 60
77
-
78
- # Execution timeout (seconds)
79
- #
80
- # Maximum wall-clock time for entire swarm.execute() call.
81
- # 30 minutes allows complex multi-agent workflows while preventing
82
- # runaway execution.
83
- EXECUTION_TIMEOUT_SECONDS = 1800
84
-
85
- # Turn timeout (seconds)
86
- #
87
- # Maximum time for a single agent.ask() call, including all LLM requests
88
- # and tool executions. 30 minutes accommodates extended thinking models
89
- # and complex tool chains.
90
- TURN_TIMEOUT_SECONDS = 1800
91
-
92
- # OpenAI responses API ID TTL (seconds)
93
- #
94
- # Time-to-live for cached response IDs. 5 minutes allows conversation
95
- # continuity while preventing stale cache issues.
96
- RESPONSES_API_TTL_SECONDS = 300
97
-
98
- # MCP client request timeout (seconds)
99
- #
100
- # Default timeout for MCP server connections. 5 minutes accommodates
101
- # long-running SSE streams and tool executions. This timeout applies to
102
- # the entire operation (operation_timeout in HTTPX), so it must be long
103
- # enough for SSE connections that may run for extended periods.
104
- MCP_REQUEST_SECONDS = 300
105
- end
106
-
107
- # MCP reconnection configuration
108
- #
109
- # Settings for automatic reconnection when SSE/streamable connections drop.
110
- # Note: The background SSE notification stream uses operation_timeout which
111
- # limits total connection duration. Since this stream is meant to stay open
112
- # indefinitely for server notifications, we configure aggressive reconnection
113
- # so timeouts are transparent to users. Tool calls use separate connections
114
- # and are unaffected by SSE stream timeouts.
115
- module McpReconnection
116
- # Maximum number of reconnection attempts
117
- #
118
- # Very high value (effectively infinite) because the SSE notification stream
119
- # is expected to timeout periodically due to operation_timeout limitations.
120
- # Reconnection is transparent - tool calls continue working regardless.
121
- MAX_RETRIES = 1000
122
-
123
- # Initial delay between reconnection attempts (milliseconds)
124
- #
125
- # Fast initial reconnect (500ms) to minimize notification gaps.
126
- INITIAL_DELAY_MS = 500
127
-
128
- # Exponential backoff growth factor
129
- #
130
- # Slow growth (1.2x) because we expect frequent reconnections.
131
- # 500ms -> 600ms -> 720ms -> 864ms -> 1037ms -> ...
132
- DELAY_GROW_FACTOR = 1.2
133
-
134
- # Maximum delay between reconnection attempts (milliseconds)
135
- #
136
- # Caps at 10 seconds to ensure responsive reconnection even after many retries.
137
- MAX_DELAY_MS = 10_000
138
- end
139
-
140
- # Output and content size limits
141
- #
142
- # These limits prevent overwhelming context windows and ensure
143
- # reasonable memory usage.
144
- module Limits
145
- # Maximum Bash output characters
146
- #
147
- # Truncates command output to prevent overwhelming agent context.
148
- # 30,000 characters balances useful information with context constraints.
149
- OUTPUT_CHARACTERS = 30_000
150
-
151
- # Default lines to read from files
152
- #
153
- # When no explicit limit is set, Read tool returns first 2000 lines.
154
- # This provides substantial file content while preventing huge files
155
- # from overwhelming context.
156
- READ_LINES = 2000
157
-
158
- # Maximum characters per line in Read output
159
- #
160
- # Truncates very long lines to prevent single lines from consuming
161
- # excessive context. 2000 characters per line is generous while
162
- # protecting against minified files.
163
- LINE_CHARACTERS = 2000
164
-
165
- # Maximum WebFetch content length
166
- #
167
- # Limits web content fetched from URLs. 100,000 characters provides
168
- # substantial page content while preventing huge pages from overwhelming context.
169
- WEB_FETCH_CHARACTERS = 100_000
170
-
171
- # Maximum Glob search results
172
- #
173
- # Limits number of file paths returned by Glob tool. 1000 results
174
- # provides comprehensive search while preventing overwhelming output.
175
- GLOB_RESULTS = 1000
176
- end
177
-
178
- # Storage limits for persistent data
179
- module Storage
180
- # Maximum size for single scratchpad entry (bytes)
181
- #
182
- # 3MB per entry prevents individual entries from consuming excessive storage
183
- # while allowing substantial content (code, large texts).
184
- ENTRY_SIZE_BYTES = 3_000_000
185
-
186
- # Maximum total scratchpad storage (bytes)
187
- #
188
- # 100GB total storage provides ample room for extensive projects
189
- # while preventing unbounded growth.
190
- TOTAL_SIZE_BYTES = 100_000_000_000
191
- end
192
-
193
- # Context management settings
194
- module Context
195
- # Context usage percentage triggering compression warning
196
- #
197
- # When context usage reaches 60%, agents should consider compaction.
198
- # This threshold provides buffer before hitting limits.
199
- COMPRESSION_THRESHOLD_PERCENT = 60
200
-
201
- # Message count between TodoWrite reminders
202
- #
203
- # After 8 messages without using TodoWrite, a gentle reminder is injected.
204
- # Balances helpfulness without being annoying.
205
- TODOWRITE_REMINDER_INTERVAL = 8
206
- end
207
-
208
- # Token estimation factors
209
- #
210
- # Used for approximate token counting when precise counts aren't available.
211
- module TokenEstimation
212
- # Characters per token for prose text
213
- #
214
- # Average of ~4 characters per token for natural language text.
215
- # Based on empirical analysis of tokenization patterns.
216
- CHARS_PER_TOKEN_PROSE = 4.0
217
-
218
- # Characters per token for code
219
- #
220
- # Code tends to have shorter tokens due to symbols and operators.
221
- # ~3.5 characters per token accounts for this density.
222
- CHARS_PER_TOKEN_CODE = 3.5
223
- end
224
-
225
- # Logging configuration
226
- module Logging
227
- # Default MCP client log level
228
- #
229
- # WARN level suppresses verbose MCP client logs while still
230
- # reporting important issues.
231
- MCP_LOG_LEVEL = Logger::WARN
232
- end
233
-
234
- # Agent configuration defaults
235
- #
236
- # Default values for agent configuration when not explicitly specified.
237
- module Agent
238
- # Default LLM model identifier
239
- #
240
- # OpenAI's GPT-5 is used as the default model. This can be overridden
241
- # per-agent or globally via all_agents configuration.
242
- MODEL = "gpt-5"
243
-
244
- # Default LLM provider
245
- #
246
- # OpenAI is the default provider. Supported providers include:
247
- # openai, anthropic, gemini, deepseek, openrouter, bedrock, etc.
248
- PROVIDER = "openai"
249
- end
250
- end
251
- end
@@ -1,199 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module SwarmSDK
4
- # Reconstructs RubyLLM::Message objects from SwarmSDK event streams
5
- #
6
- # This class enables conversation replay and analysis from event logs.
7
- # It uses timestamps to maintain chronological ordering of messages.
8
- #
9
- # ## Limitations
10
- #
11
- # This reconstructs ONLY conversation messages. It does NOT restore:
12
- # - Context state (warning thresholds, compression, todowrite index)
13
- # - Scratchpad contents
14
- # - Read tracking information
15
- # - Full swarm state
16
- #
17
- # For full state restoration, use StateSnapshot/StateRestorer or SnapshotFromEvents.
18
- #
19
- # ## Usage
20
- #
21
- # # Collect events during execution
22
- # events = []
23
- # swarm.execute("Build feature") do |event|
24
- # events << event
25
- # end
26
- #
27
- # # Reconstruct conversation for an agent
28
- # messages = SwarmSDK::EventsToMessages.reconstruct(events, agent: :backend)
29
- #
30
- # # View conversation
31
- # messages.each do |msg|
32
- # puts "[#{msg.role}] #{msg.content}"
33
- # end
34
- #
35
- # ## Event Requirements
36
- #
37
- # Events must have:
38
- # - `:timestamp` field (ISO 8601 format) for ordering
39
- # - `:agent` field to filter by agent
40
- # - `:type` field to identify event type
41
- #
42
- # Supported event types:
43
- # - `user_prompt`: Reconstructs user message (prompt in metadata or top-level)
44
- # - `agent_step`: Reconstructs assistant message with tool calls
45
- # - `agent_stop`: Reconstructs final assistant message
46
- # - `tool_result`: Reconstructs tool result message
47
- # - `delegation_result`: Reconstructs tool result message from delegation
48
- class EventsToMessages
49
- class << self
50
- # Reconstruct messages for an agent from event stream
51
- #
52
- # @param events [Array<Hash>] Event stream with timestamps
53
- # @param agent [Symbol, String] Agent name to reconstruct messages for
54
- # @return [Array<RubyLLM::Message>] Reconstructed messages in chronological order
55
- #
56
- # @example
57
- # messages = EventsToMessages.reconstruct(events, agent: :backend)
58
- # messages.each { |msg| puts msg.content }
59
- def reconstruct(events, agent:)
60
- new(events, agent).reconstruct
61
- end
62
- end
63
-
64
- # Initialize reconstructor
65
- #
66
- # @param events [Array<Hash>] Event stream
67
- # @param agent [Symbol, String] Agent name
68
- def initialize(events, agent)
69
- @events = events
70
- @agent = agent.to_sym
71
- end
72
-
73
- # Reconstruct messages from events
74
- #
75
- # Filters events by agent, sorts by timestamp, and converts to RubyLLM::Message objects.
76
- #
77
- # @return [Array<RubyLLM::Message>] Reconstructed messages
78
- def reconstruct
79
- messages = []
80
-
81
- # Filter events for this agent and sort by timestamp
82
- agent_events = @events
83
- .select { |e| normalize_agent(e[:agent]) == @agent }
84
- .sort_by { |e| parse_timestamp(e[:timestamp]) }
85
-
86
- agent_events.each do |event|
87
- message = case event[:type]&.to_s
88
- when "user_prompt"
89
- reconstruct_user_message(event)
90
- when "agent_step", "agent_stop"
91
- reconstruct_assistant_message(event)
92
- when "tool_result"
93
- reconstruct_tool_result_message(event)
94
- when "delegation_result"
95
- reconstruct_delegation_result_message(event)
96
- end
97
-
98
- messages << message if message
99
- end
100
-
101
- messages
102
- end
103
-
104
- private
105
-
106
- # Reconstruct user message from user_prompt event
107
- #
108
- # Extracts prompt from metadata or top-level field.
109
- #
110
- # @param event [Hash] user_prompt event
111
- # @return [RubyLLM::Message, nil] User message or nil if prompt not found
112
- def reconstruct_user_message(event)
113
- # Try to extract prompt from metadata (current location) or top-level (potential future location)
114
- prompt = event.dig(:metadata, :prompt) || event[:prompt]
115
- return unless prompt && !prompt.to_s.empty?
116
-
117
- RubyLLM::Message.new(
118
- role: :user,
119
- content: prompt,
120
- )
121
- end
122
-
123
- # Reconstruct assistant message from agent_step or agent_stop event
124
- #
125
- # Converts tool_calls array to hash format expected by RubyLLM.
126
- #
127
- # @param event [Hash] agent_step or agent_stop event
128
- # @return [RubyLLM::Message] Assistant message
129
- def reconstruct_assistant_message(event)
130
- # Convert tool_calls array to hash (RubyLLM format)
131
- # Events emit tool_calls as Array, but RubyLLM expects Hash<String, ToolCall>
132
- tool_calls_hash = if event[:tool_calls] && !event[:tool_calls].empty?
133
- event[:tool_calls].each_with_object({}) do |tc, hash|
134
- hash[tc[:id].to_s] = RubyLLM::ToolCall.new(
135
- id: tc[:id],
136
- name: tc[:name],
137
- arguments: tc[:arguments] || {},
138
- )
139
- end
140
- end
141
-
142
- RubyLLM::Message.new(
143
- role: :assistant,
144
- content: event[:content] || "",
145
- tool_calls: tool_calls_hash,
146
- input_tokens: event.dig(:usage, :input_tokens),
147
- output_tokens: event.dig(:usage, :output_tokens),
148
- model_id: event[:model],
149
- )
150
- end
151
-
152
- # Reconstruct tool result message from tool_result event
153
- #
154
- # @param event [Hash] tool_result event
155
- # @return [RubyLLM::Message] Tool result message
156
- def reconstruct_tool_result_message(event)
157
- RubyLLM::Message.new(
158
- role: :tool,
159
- content: event[:result].to_s,
160
- tool_call_id: event[:tool_call_id],
161
- )
162
- end
163
-
164
- # Reconstruct tool result message from delegation_result event
165
- #
166
- # delegation_result events are emitted when a delegation completes,
167
- # and they should be converted to tool result messages in the conversation.
168
- #
169
- # @param event [Hash] delegation_result event
170
- # @return [RubyLLM::Message] Tool result message
171
- def reconstruct_delegation_result_message(event)
172
- RubyLLM::Message.new(
173
- role: :tool,
174
- content: event[:result].to_s,
175
- tool_call_id: event[:tool_call_id],
176
- )
177
- end
178
-
179
- # Parse timestamp string to Time object
180
- #
181
- # @param timestamp [String, nil] ISO 8601 timestamp
182
- # @return [Time] Parsed time or epoch if nil/invalid
183
- def parse_timestamp(timestamp)
184
- return Time.at(0) unless timestamp
185
-
186
- Time.parse(timestamp)
187
- rescue ArgumentError
188
- Time.at(0)
189
- end
190
-
191
- # Normalize agent name to symbol
192
- #
193
- # @param agent [Symbol, String, nil] Agent name
194
- # @return [Symbol] Normalized agent name
195
- def normalize_agent(agent)
196
- agent.to_s.to_sym
197
- end
198
- end
199
- end