swarm_sdk 2.7.14 → 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 (181) hide show
  1. checksums.yaml +4 -4
  2. data/lib/swarm_sdk/ruby_llm_patches/chat_callbacks_patch.rb +16 -0
  3. data/lib/swarm_sdk/ruby_llm_patches/init.rb +4 -1
  4. data/lib/swarm_sdk/v3/agent.rb +1165 -0
  5. data/lib/swarm_sdk/v3/agent_builder.rb +533 -0
  6. data/lib/swarm_sdk/v3/agent_definition.rb +330 -0
  7. data/lib/swarm_sdk/v3/configuration.rb +490 -0
  8. data/lib/swarm_sdk/v3/debug_log.rb +86 -0
  9. data/lib/swarm_sdk/v3/event_stream.rb +130 -0
  10. data/lib/swarm_sdk/v3/hooks/context.rb +112 -0
  11. data/lib/swarm_sdk/v3/hooks/result.rb +115 -0
  12. data/lib/swarm_sdk/v3/hooks/runner.rb +128 -0
  13. data/lib/swarm_sdk/v3/mcp/connector.rb +183 -0
  14. data/lib/swarm_sdk/v3/mcp/mcp_error.rb +15 -0
  15. data/lib/swarm_sdk/v3/mcp/server_definition.rb +125 -0
  16. data/lib/swarm_sdk/v3/mcp/ssl_http_transport.rb +103 -0
  17. data/lib/swarm_sdk/v3/mcp/stdio_transport.rb +135 -0
  18. data/lib/swarm_sdk/v3/mcp/tool_proxy.rb +53 -0
  19. data/lib/swarm_sdk/v3/memory/adapters/base.rb +297 -0
  20. data/lib/swarm_sdk/v3/memory/adapters/faiss_support.rb +194 -0
  21. data/lib/swarm_sdk/v3/memory/adapters/filesystem_adapter.rb +212 -0
  22. data/lib/swarm_sdk/v3/memory/adapters/sqlite_adapter.rb +507 -0
  23. data/lib/swarm_sdk/v3/memory/adapters/vector_utils.rb +88 -0
  24. data/lib/swarm_sdk/v3/memory/card.rb +206 -0
  25. data/lib/swarm_sdk/v3/memory/cluster.rb +146 -0
  26. data/lib/swarm_sdk/v3/memory/compressor.rb +496 -0
  27. data/lib/swarm_sdk/v3/memory/consolidator.rb +427 -0
  28. data/lib/swarm_sdk/v3/memory/context_builder.rb +339 -0
  29. data/lib/swarm_sdk/v3/memory/edge.rb +105 -0
  30. data/lib/swarm_sdk/v3/memory/embedder.rb +185 -0
  31. data/lib/swarm_sdk/v3/memory/exposure_tracker.rb +104 -0
  32. data/lib/swarm_sdk/v3/memory/ingestion_pipeline.rb +394 -0
  33. data/lib/swarm_sdk/v3/memory/retriever.rb +289 -0
  34. data/lib/swarm_sdk/v3/memory/store.rb +489 -0
  35. data/lib/swarm_sdk/v3/skills/loader.rb +147 -0
  36. data/lib/swarm_sdk/v3/skills/manifest.rb +45 -0
  37. data/lib/swarm_sdk/v3/sub_task_agent.rb +248 -0
  38. data/lib/swarm_sdk/v3/tools/base.rb +80 -0
  39. data/lib/swarm_sdk/v3/tools/bash.rb +174 -0
  40. data/lib/swarm_sdk/v3/tools/clock.rb +32 -0
  41. data/lib/swarm_sdk/v3/tools/edit.rb +111 -0
  42. data/lib/swarm_sdk/v3/tools/glob.rb +96 -0
  43. data/lib/swarm_sdk/v3/tools/grep.rb +200 -0
  44. data/lib/swarm_sdk/v3/tools/message_teammate.rb +15 -0
  45. data/lib/swarm_sdk/v3/tools/message_user.rb +15 -0
  46. data/lib/swarm_sdk/v3/tools/read.rb +181 -0
  47. data/lib/swarm_sdk/v3/tools/read_tracker.rb +40 -0
  48. data/lib/swarm_sdk/v3/tools/registry.rb +208 -0
  49. data/lib/swarm_sdk/v3/tools/sub_task.rb +183 -0
  50. data/lib/swarm_sdk/v3/tools/think.rb +88 -0
  51. data/lib/swarm_sdk/v3/tools/write.rb +87 -0
  52. data/lib/swarm_sdk/v3.rb +145 -0
  53. metadata +83 -148
  54. data/lib/swarm_sdk/agent/RETRY_LOGIC.md +0 -175
  55. data/lib/swarm_sdk/agent/builder.rb +0 -705
  56. data/lib/swarm_sdk/agent/chat.rb +0 -1438
  57. data/lib/swarm_sdk/agent/chat_helpers/context_tracker.rb +0 -375
  58. data/lib/swarm_sdk/agent/chat_helpers/event_emitter.rb +0 -204
  59. data/lib/swarm_sdk/agent/chat_helpers/hook_integration.rb +0 -480
  60. data/lib/swarm_sdk/agent/chat_helpers/instrumentation.rb +0 -85
  61. data/lib/swarm_sdk/agent/chat_helpers/llm_configuration.rb +0 -290
  62. data/lib/swarm_sdk/agent/chat_helpers/logging_helpers.rb +0 -116
  63. data/lib/swarm_sdk/agent/chat_helpers/serialization.rb +0 -83
  64. data/lib/swarm_sdk/agent/chat_helpers/system_reminder_injector.rb +0 -134
  65. data/lib/swarm_sdk/agent/chat_helpers/system_reminders.rb +0 -79
  66. data/lib/swarm_sdk/agent/chat_helpers/token_tracking.rb +0 -146
  67. data/lib/swarm_sdk/agent/context.rb +0 -115
  68. data/lib/swarm_sdk/agent/context_manager.rb +0 -315
  69. data/lib/swarm_sdk/agent/definition.rb +0 -588
  70. data/lib/swarm_sdk/agent/llm_instrumentation_middleware.rb +0 -226
  71. data/lib/swarm_sdk/agent/system_prompt_builder.rb +0 -173
  72. data/lib/swarm_sdk/agent/tool_registry.rb +0 -189
  73. data/lib/swarm_sdk/agent_registry.rb +0 -146
  74. data/lib/swarm_sdk/builders/base_builder.rb +0 -558
  75. data/lib/swarm_sdk/claude_code_agent_adapter.rb +0 -205
  76. data/lib/swarm_sdk/concerns/cleanupable.rb +0 -42
  77. data/lib/swarm_sdk/concerns/snapshotable.rb +0 -67
  78. data/lib/swarm_sdk/concerns/validatable.rb +0 -55
  79. data/lib/swarm_sdk/config.rb +0 -368
  80. data/lib/swarm_sdk/configuration/parser.rb +0 -397
  81. data/lib/swarm_sdk/configuration/translator.rb +0 -285
  82. data/lib/swarm_sdk/configuration.rb +0 -165
  83. data/lib/swarm_sdk/context_compactor/metrics.rb +0 -147
  84. data/lib/swarm_sdk/context_compactor/token_counter.rb +0 -102
  85. data/lib/swarm_sdk/context_compactor.rb +0 -335
  86. data/lib/swarm_sdk/context_management/builder.rb +0 -128
  87. data/lib/swarm_sdk/context_management/context.rb +0 -328
  88. data/lib/swarm_sdk/custom_tool_registry.rb +0 -226
  89. data/lib/swarm_sdk/defaults.rb +0 -251
  90. data/lib/swarm_sdk/events_to_messages.rb +0 -199
  91. data/lib/swarm_sdk/hooks/adapter.rb +0 -359
  92. data/lib/swarm_sdk/hooks/context.rb +0 -197
  93. data/lib/swarm_sdk/hooks/definition.rb +0 -80
  94. data/lib/swarm_sdk/hooks/error.rb +0 -29
  95. data/lib/swarm_sdk/hooks/executor.rb +0 -146
  96. data/lib/swarm_sdk/hooks/registry.rb +0 -147
  97. data/lib/swarm_sdk/hooks/result.rb +0 -150
  98. data/lib/swarm_sdk/hooks/shell_executor.rb +0 -256
  99. data/lib/swarm_sdk/hooks/tool_call.rb +0 -35
  100. data/lib/swarm_sdk/hooks/tool_result.rb +0 -62
  101. data/lib/swarm_sdk/log_collector.rb +0 -227
  102. data/lib/swarm_sdk/log_stream.rb +0 -127
  103. data/lib/swarm_sdk/markdown_parser.rb +0 -75
  104. data/lib/swarm_sdk/model_aliases.json +0 -8
  105. data/lib/swarm_sdk/models.json +0 -44002
  106. data/lib/swarm_sdk/models.rb +0 -161
  107. data/lib/swarm_sdk/node_context.rb +0 -245
  108. data/lib/swarm_sdk/observer/builder.rb +0 -81
  109. data/lib/swarm_sdk/observer/config.rb +0 -45
  110. data/lib/swarm_sdk/observer/manager.rb +0 -248
  111. data/lib/swarm_sdk/patterns/agent_observer.rb +0 -160
  112. data/lib/swarm_sdk/permissions/config.rb +0 -239
  113. data/lib/swarm_sdk/permissions/error_formatter.rb +0 -121
  114. data/lib/swarm_sdk/permissions/path_matcher.rb +0 -35
  115. data/lib/swarm_sdk/permissions/validator.rb +0 -173
  116. data/lib/swarm_sdk/permissions_builder.rb +0 -122
  117. data/lib/swarm_sdk/plugin.rb +0 -309
  118. data/lib/swarm_sdk/plugin_registry.rb +0 -101
  119. data/lib/swarm_sdk/proc_helpers.rb +0 -53
  120. data/lib/swarm_sdk/prompts/base_system_prompt.md.erb +0 -119
  121. data/lib/swarm_sdk/restore_result.rb +0 -65
  122. data/lib/swarm_sdk/result.rb +0 -241
  123. data/lib/swarm_sdk/snapshot.rb +0 -156
  124. data/lib/swarm_sdk/snapshot_from_events.rb +0 -397
  125. data/lib/swarm_sdk/state_restorer.rb +0 -476
  126. data/lib/swarm_sdk/state_snapshot.rb +0 -334
  127. data/lib/swarm_sdk/swarm/agent_initializer.rb +0 -648
  128. data/lib/swarm_sdk/swarm/all_agents_builder.rb +0 -204
  129. data/lib/swarm_sdk/swarm/builder.rb +0 -256
  130. data/lib/swarm_sdk/swarm/executor.rb +0 -446
  131. data/lib/swarm_sdk/swarm/hook_triggers.rb +0 -162
  132. data/lib/swarm_sdk/swarm/lazy_delegate_chat.rb +0 -372
  133. data/lib/swarm_sdk/swarm/logging_callbacks.rb +0 -361
  134. data/lib/swarm_sdk/swarm/mcp_configurator.rb +0 -290
  135. data/lib/swarm_sdk/swarm/swarm_registry_builder.rb +0 -67
  136. data/lib/swarm_sdk/swarm/tool_configurator.rb +0 -392
  137. data/lib/swarm_sdk/swarm.rb +0 -973
  138. data/lib/swarm_sdk/swarm_loader.rb +0 -145
  139. data/lib/swarm_sdk/swarm_registry.rb +0 -136
  140. data/lib/swarm_sdk/tools/base.rb +0 -63
  141. data/lib/swarm_sdk/tools/bash.rb +0 -280
  142. data/lib/swarm_sdk/tools/clock.rb +0 -46
  143. data/lib/swarm_sdk/tools/delegate.rb +0 -389
  144. data/lib/swarm_sdk/tools/document_converters/base_converter.rb +0 -83
  145. data/lib/swarm_sdk/tools/document_converters/docx_converter.rb +0 -99
  146. data/lib/swarm_sdk/tools/document_converters/html_converter.rb +0 -101
  147. data/lib/swarm_sdk/tools/document_converters/pdf_converter.rb +0 -78
  148. data/lib/swarm_sdk/tools/document_converters/xlsx_converter.rb +0 -194
  149. data/lib/swarm_sdk/tools/edit.rb +0 -145
  150. data/lib/swarm_sdk/tools/glob.rb +0 -166
  151. data/lib/swarm_sdk/tools/grep.rb +0 -235
  152. data/lib/swarm_sdk/tools/image_extractors/docx_image_extractor.rb +0 -43
  153. data/lib/swarm_sdk/tools/image_extractors/pdf_image_extractor.rb +0 -167
  154. data/lib/swarm_sdk/tools/image_formats/tiff_builder.rb +0 -65
  155. data/lib/swarm_sdk/tools/mcp_tool_stub.rb +0 -198
  156. data/lib/swarm_sdk/tools/multi_edit.rb +0 -236
  157. data/lib/swarm_sdk/tools/path_resolver.rb +0 -92
  158. data/lib/swarm_sdk/tools/read.rb +0 -261
  159. data/lib/swarm_sdk/tools/registry.rb +0 -205
  160. data/lib/swarm_sdk/tools/scratchpad/scratchpad_list.rb +0 -117
  161. data/lib/swarm_sdk/tools/scratchpad/scratchpad_read.rb +0 -97
  162. data/lib/swarm_sdk/tools/scratchpad/scratchpad_write.rb +0 -108
  163. data/lib/swarm_sdk/tools/stores/read_tracker.rb +0 -96
  164. data/lib/swarm_sdk/tools/stores/scratchpad_storage.rb +0 -273
  165. data/lib/swarm_sdk/tools/stores/storage.rb +0 -142
  166. data/lib/swarm_sdk/tools/stores/todo_manager.rb +0 -65
  167. data/lib/swarm_sdk/tools/think.rb +0 -100
  168. data/lib/swarm_sdk/tools/todo_write.rb +0 -237
  169. data/lib/swarm_sdk/tools/web_fetch.rb +0 -264
  170. data/lib/swarm_sdk/tools/write.rb +0 -112
  171. data/lib/swarm_sdk/transcript_builder.rb +0 -278
  172. data/lib/swarm_sdk/utils.rb +0 -68
  173. data/lib/swarm_sdk/validation_result.rb +0 -33
  174. data/lib/swarm_sdk/version.rb +0 -5
  175. data/lib/swarm_sdk/workflow/agent_config.rb +0 -95
  176. data/lib/swarm_sdk/workflow/builder.rb +0 -227
  177. data/lib/swarm_sdk/workflow/executor.rb +0 -497
  178. data/lib/swarm_sdk/workflow/node_builder.rb +0 -593
  179. data/lib/swarm_sdk/workflow/transformer_executor.rb +0 -250
  180. data/lib/swarm_sdk/workflow.rb +0 -589
  181. data/lib/swarm_sdk.rb +0 -721
@@ -1,112 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module SwarmSDK
4
- module Tools
5
- # Write tool for writing content to files
6
- #
7
- # Creates new files or overwrites existing files.
8
- # Enforces read-before-write rule for existing files.
9
- # Includes validation and usage guidelines via system reminders.
10
- class Write < Base
11
- include PathResolver
12
-
13
- # Factory pattern: declare what parameters this tool needs for instantiation
14
- class << self
15
- def creation_requirements
16
- [:agent_name, :directory]
17
- end
18
- end
19
-
20
- description <<~DESC
21
- Writes a file to the local filesystem.
22
- This tool will overwrite the existing file if there is one at the provided path.
23
- If this is an existing file, you MUST use the Read tool first to read the file's contents.
24
- This tool will fail if you did not read the file first.
25
- ALWAYS prefer editing existing files in the codebase. NEVER write new files unless explicitly required.
26
- NEVER proactively create documentation files (*.md) or README files. Only create documentation files if explicitly requested by the User.
27
- Only use emojis if the user explicitly requests it. Avoid writing emojis to files unless asked.
28
-
29
- IMPORTANT - Path Handling:
30
- - Relative paths (e.g., "tmp/file.txt", "src/main.rb") are resolved relative to your agent's working directory
31
- - Absolute paths (e.g., "/tmp/file.txt", "/etc/passwd") are treated as system absolute paths
32
- - When the user says "tmp/file.txt" they mean the tmp directory in your working directory, NOT /tmp
33
- - Only use absolute paths (starting with /) when explicitly referring to system-level paths
34
- DESC
35
-
36
- param :file_path,
37
- type: "string",
38
- desc: "Path to the file. Use relative paths (e.g., 'tmp/file.txt') for files in your working directory, or absolute paths (e.g., '/etc/passwd') for system files.",
39
- required: true
40
-
41
- param :content,
42
- type: "string",
43
- desc: "The content to write to the file",
44
- required: true
45
-
46
- # Initialize the Write tool for a specific agent
47
- #
48
- # @param agent_name [Symbol, String] The agent identifier
49
- # @param directory [String] Agent's working directory
50
- def initialize(agent_name:, directory:)
51
- super()
52
- initialize_agent_context(agent_name: agent_name, directory: directory)
53
- end
54
-
55
- # Override name to return simple "Write" instead of full class path
56
- def name
57
- "Write"
58
- end
59
-
60
- def execute(file_path:, content:)
61
- # Validate inputs
62
- return validation_error("file_path is required") if file_path.nil? || file_path.to_s.strip.empty?
63
- return validation_error("content is required") if content.nil?
64
-
65
- # CRITICAL: Resolve path against agent directory
66
- resolved_path = resolve_path(file_path)
67
-
68
- # Check if file already exists (use resolved path)
69
- file_exists = File.exist?(resolved_path)
70
-
71
- # Enforce read-before-write for existing files (use resolved path)
72
- if file_exists && !Stores::ReadTracker.file_read?(@agent_name, resolved_path)
73
- return validation_error(
74
- "Cannot write to existing file without reading it first. " \
75
- "You must use the Read tool on '#{file_path}' before overwriting it. " \
76
- "This ensures you have context about the file's current contents.",
77
- )
78
- end
79
-
80
- # Create parent directory if it doesn't exist (use resolved path)
81
- parent_dir = File.dirname(resolved_path)
82
- FileUtils.mkdir_p(parent_dir) unless File.directory?(parent_dir)
83
-
84
- # Write the file (use resolved path)
85
- File.write(resolved_path, content, encoding: "UTF-8")
86
-
87
- # Build success message
88
- byte_size = content.bytesize
89
- line_count = content.lines.count
90
- action = file_exists ? "overwrote" : "created"
91
-
92
- message = "Successfully #{action} file: #{file_path} (#{line_count} lines, #{byte_size} bytes)"
93
-
94
- # Add system reminder for overwritten files
95
- if file_exists
96
- reminder = "<system-reminder>You overwrote an existing file. Make sure this was intentional and that you read the file first if you needed to preserve any content.</system-reminder>"
97
- "#{message}\n\n#{reminder}"
98
- else
99
- message
100
- end
101
- rescue Errno::EACCES
102
- error("Permission denied: Cannot write to file '#{file_path}'")
103
- rescue Errno::EISDIR
104
- error("Path is a directory, not a file.")
105
- rescue Errno::ENOENT => e
106
- error("Failed to create parent directory: #{e.message}")
107
- rescue StandardError => e
108
- error("Unexpected error writing file: #{e.class.name} - #{e.message}")
109
- end
110
- end
111
- end
112
- end
@@ -1,278 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module SwarmSDK
4
- # Transforms raw log events into LLM-readable conversation transcripts
5
- #
6
- # TranscriptBuilder converts the structured event log from swarm execution
7
- # into a human/LLM-readable format suitable for reflection, analysis, or
8
- # memory creation.
9
- #
10
- # @example Basic usage
11
- # transcript = TranscriptBuilder.build(result.logs)
12
- # # => "USER: Help me with CORS\n\nAGENT [assistant]: ..."
13
- #
14
- # @example Filter by agents
15
- # transcript = TranscriptBuilder.build(result.logs, agents: [:backend, :database])
16
- #
17
- # @example Custom options
18
- # transcript = TranscriptBuilder.build(
19
- # result.logs,
20
- # include_tool_results: true,
21
- # max_result_length: 1000,
22
- # include_thinking: false
23
- # )
24
- class TranscriptBuilder
25
- # Default maximum length for tool result content
26
- DEFAULT_MAX_RESULT_LENGTH = 500
27
-
28
- # Default maximum length for tool arguments
29
- DEFAULT_MAX_ARGS_LENGTH = 200
30
-
31
- class << self
32
- # Build a transcript from log events
33
- #
34
- # @param logs [Array<Hash>] Array of log events from Result#logs
35
- # @param agents [Array<Symbol>, nil] Filter to specific agents (nil = all)
36
- # @param include_tool_results [Boolean] Include tool execution results (default: true)
37
- # @param include_thinking [Boolean] Include agent_step content/thinking (default: false)
38
- # @param max_result_length [Integer] Maximum characters for tool results
39
- # @param max_args_length [Integer] Maximum characters for tool arguments
40
- # @return [String] Formatted transcript
41
- def build(logs, agents: nil, include_tool_results: true, include_thinking: false,
42
- max_result_length: DEFAULT_MAX_RESULT_LENGTH, max_args_length: DEFAULT_MAX_ARGS_LENGTH)
43
- new(
44
- logs,
45
- agents: agents,
46
- include_tool_results: include_tool_results,
47
- include_thinking: include_thinking,
48
- max_result_length: max_result_length,
49
- max_args_length: max_args_length,
50
- ).build
51
- end
52
- end
53
-
54
- # Initialize a new TranscriptBuilder
55
- #
56
- # @param logs [Array<Hash>] Array of log events
57
- # @param agents [Array<Symbol>, nil] Filter to specific agents
58
- # @param include_tool_results [Boolean] Include tool execution results
59
- # @param include_thinking [Boolean] Include agent_step content
60
- # @param max_result_length [Integer] Maximum characters for tool results
61
- # @param max_args_length [Integer] Maximum characters for tool arguments
62
- def initialize(logs, agents: nil, include_tool_results: true, include_thinking: false,
63
- max_result_length: DEFAULT_MAX_RESULT_LENGTH, max_args_length: DEFAULT_MAX_ARGS_LENGTH)
64
- @logs = logs || []
65
- @agents = normalize_agents(agents)
66
- @include_tool_results = include_tool_results
67
- @include_thinking = include_thinking
68
- @max_result_length = max_result_length
69
- @max_args_length = max_args_length
70
- end
71
-
72
- # Build the transcript
73
- #
74
- # @return [String] Formatted transcript
75
- def build
76
- @logs
77
- .filter_map { |event| format_event(event) }
78
- .join("\n\n")
79
- end
80
-
81
- private
82
-
83
- # Normalize agent filter to array of symbols
84
- #
85
- # @param agents [Array, Symbol, String, nil] Agent filter input
86
- # @return [Array<Symbol>, nil] Normalized agent list or nil for all
87
- def normalize_agents(agents)
88
- return if agents.nil? || (agents.is_a?(Array) && agents.empty?)
89
-
90
- Array(agents).map(&:to_sym)
91
- end
92
-
93
- # Check if event passes agent filter
94
- #
95
- # @param event [Hash] Log event
96
- # @return [Boolean] True if event should be included
97
- def passes_agent_filter?(event)
98
- return true if @agents.nil?
99
-
100
- agent = event[:agent] || event["agent"]
101
- return true if agent.nil? # Include events without agent (like swarm_start)
102
-
103
- @agents.include?(agent.to_sym)
104
- end
105
-
106
- # Format a single event into transcript text
107
- #
108
- # @param event [Hash] Log event
109
- # @return [String, nil] Formatted text or nil to skip
110
- def format_event(event)
111
- return unless passes_agent_filter?(event)
112
-
113
- type = event[:type] || event["type"]
114
-
115
- case type
116
- when "user_prompt"
117
- format_user_prompt(event)
118
- when "agent_step"
119
- format_agent_step(event)
120
- when "agent_stop"
121
- format_agent_stop(event)
122
- when "tool_call"
123
- format_tool_call(event)
124
- when "tool_result"
125
- format_tool_result(event)
126
- when "pre_delegation", "delegation_start"
127
- format_delegation_start(event)
128
- when "post_delegation", "delegation_complete"
129
- format_delegation_complete(event)
130
- end
131
- end
132
-
133
- # Format user_prompt event
134
- #
135
- # @param event [Hash] Event data
136
- # @return [String, nil] Formatted text
137
- def format_user_prompt(event)
138
- prompt = event[:prompt] || event["prompt"]
139
- return if prompt.nil? || prompt.to_s.strip.empty?
140
-
141
- agent = event[:agent] || event["agent"]
142
- source = event[:source] || event["source"] || "user"
143
-
144
- # Show source if it's a delegation or system message
145
- prefix = case source.to_s
146
- when "delegation"
147
- "DELEGATION REQUEST"
148
- when "system"
149
- "SYSTEM"
150
- else
151
- "USER"
152
- end
153
-
154
- if agent && source.to_s != "user"
155
- "#{prefix} → [#{agent}]: #{prompt}"
156
- else
157
- "#{prefix}: #{prompt}"
158
- end
159
- end
160
-
161
- # Format agent_step event (intermediate response with tool calls)
162
- #
163
- # @param event [Hash] Event data
164
- # @return [String, nil] Formatted text
165
- def format_agent_step(event)
166
- return unless @include_thinking
167
-
168
- content = event[:content] || event["content"]
169
- return if content.nil? || content.to_s.strip.empty?
170
-
171
- agent = event[:agent] || event["agent"]
172
- "AGENT [#{agent}] (thinking): #{content}"
173
- end
174
-
175
- # Format agent_stop event (final response)
176
- #
177
- # @param event [Hash] Event data
178
- # @return [String, nil] Formatted text
179
- def format_agent_stop(event)
180
- content = event[:content] || event["content"]
181
- return if content.nil? || content.to_s.strip.empty?
182
-
183
- agent = event[:agent] || event["agent"]
184
- "AGENT [#{agent}]: #{content}"
185
- end
186
-
187
- # Format tool_call event
188
- #
189
- # @param event [Hash] Event data
190
- # @return [String] Formatted text
191
- def format_tool_call(event)
192
- tool = event[:tool] || event["tool"] || event[:tool_name] || event["tool_name"]
193
- agent = event[:agent] || event["agent"]
194
- arguments = event[:arguments] || event["arguments"]
195
-
196
- args_str = format_arguments(arguments)
197
- "TOOL [#{agent}] → #{tool}(#{args_str})"
198
- end
199
-
200
- # Format tool_result event
201
- #
202
- # @param event [Hash] Event data
203
- # @return [String, nil] Formatted text
204
- def format_tool_result(event)
205
- return unless @include_tool_results
206
-
207
- tool = event[:tool] || event["tool"] || event[:tool_name] || event["tool_name"]
208
- result = event[:result] || event["result"]
209
- # Use key existence check since false || nil would lose the false value
210
- success = event.key?(:success) ? event[:success] : event["success"]
211
-
212
- # Handle RubyLLM::ToolResult objects
213
- result_content = if result.respond_to?(:content)
214
- result.content
215
- else
216
- result.to_s
217
- end
218
-
219
- truncated = truncate(result_content, @max_result_length)
220
-
221
- status = success == false ? " [FAILED]" : ""
222
- "RESULT [#{tool}]#{status}: #{truncated}"
223
- end
224
-
225
- # Format delegation_start event
226
- #
227
- # @param event [Hash] Event data
228
- # @return [String, nil] Formatted text
229
- def format_delegation_start(event)
230
- from = event[:from_agent] || event["from_agent"] || event[:agent] || event["agent"]
231
- to = event[:to_agent] || event["to_agent"]
232
- task = event[:task] || event["task"] || event[:message] || event["message"]
233
-
234
- return unless to
235
-
236
- task_preview = truncate(task.to_s, 200)
237
- "DELEGATE: #{from} → #{to}: #{task_preview}"
238
- end
239
-
240
- # Format delegation_complete event
241
- #
242
- # @param event [Hash] Event data
243
- # @return [String, nil] Formatted text
244
- def format_delegation_complete(event)
245
- from = event[:from_agent] || event["from_agent"] || event[:agent] || event["agent"]
246
- to = event[:to_agent] || event["to_agent"]
247
-
248
- return unless to
249
-
250
- "DELEGATE COMPLETE: #{to} → #{from}"
251
- end
252
-
253
- # Format tool arguments for display
254
- #
255
- # @param arguments [Hash, String, nil] Tool arguments
256
- # @return [String] Formatted arguments
257
- def format_arguments(arguments)
258
- return "{}" if arguments.nil?
259
-
260
- str = arguments.is_a?(String) ? arguments : arguments.to_json
261
- truncate(str, @max_args_length)
262
- end
263
-
264
- # Truncate text to maximum length with ellipsis
265
- #
266
- # @param text [String, nil] Text to truncate
267
- # @param max [Integer] Maximum length
268
- # @return [String] Truncated text
269
- def truncate(text, max)
270
- return "" if text.nil?
271
-
272
- str = text.to_s
273
- return str if str.length <= max
274
-
275
- "#{str[0...max]}..."
276
- end
277
- end
278
- end
@@ -1,68 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module SwarmSDK
4
- # Shared utility methods for SwarmSDK
5
- module Utils
6
- class << self
7
- # Recursively convert all hash keys to symbols
8
- #
9
- # Handles nested hashes and arrays containing hashes.
10
- #
11
- # @param obj [Object] Object to symbolize (Hash, Array, or other)
12
- # @return [Object] Object with symbolized keys (if applicable)
13
- #
14
- # @example
15
- # Utils.symbolize_keys({ "name" => "test", "config" => { "key" => "value" } })
16
- # # => { name: "test", config: { key: "value" } }
17
- def symbolize_keys(obj)
18
- case obj
19
- when Hash
20
- obj.transform_keys(&:to_sym).transform_values { |v| symbolize_keys(v) }
21
- when Array
22
- obj.map { |item| symbolize_keys(item) }
23
- else
24
- obj
25
- end
26
- end
27
-
28
- # Recursively convert all hash keys to strings
29
- #
30
- # Handles nested hashes and arrays containing hashes.
31
- #
32
- # @param obj [Object] Object to stringify (Hash, Array, or other)
33
- # @return [Object] Object with stringified keys (if applicable)
34
- #
35
- # @example
36
- # Utils.stringify_keys({ name: "test", config: { key: "value" } })
37
- # # => { "name" => "test", "config" => { "key" => "value" } }
38
- def stringify_keys(obj)
39
- case obj
40
- when Hash
41
- obj.transform_keys(&:to_s).transform_values { |v| stringify_keys(v) }
42
- when Array
43
- obj.map { |item| stringify_keys(item) }
44
- else
45
- obj
46
- end
47
- end
48
-
49
- # Convert hash to YAML string
50
- #
51
- # Converts a Ruby hash to a YAML string. Useful for creating inline
52
- # swarm definitions from hash configurations.
53
- #
54
- # @param hash [Hash] Hash to convert
55
- # @return [String] YAML string representation
56
- #
57
- # @example
58
- # config = { version: 2, swarm: { name: "Test" } }
59
- # Utils.hash_to_yaml(config)
60
- # # => "---\nversion: 2\nswarm:\n name: Test\n"
61
- def hash_to_yaml(hash)
62
- # Convert symbols to strings for valid YAML
63
- stringified = stringify_keys(hash)
64
- stringified.to_yaml
65
- end
66
- end
67
- end
68
- end
@@ -1,33 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module SwarmSDK
4
- # Internal result object for validation phase during snapshot restore
5
- #
6
- # Used during restore to track which agents can be restored and which
7
- # need to be skipped due to configuration mismatches.
8
- #
9
- # @api private
10
- class ValidationResult
11
- attr_reader :warnings,
12
- :skipped_agents,
13
- :restorable_agents,
14
- :skipped_delegations,
15
- :restorable_delegations
16
-
17
- # Initialize validation result
18
- #
19
- # @param warnings [Array<Hash>] Warning messages with details
20
- # @param skipped_agents [Array<Symbol>] Names of agents that can't be restored
21
- # @param restorable_agents [Array<Symbol>] Names of agents that can be restored
22
- # @param skipped_delegations [Array<String>] Names of delegations that can't be restored
23
- # @param restorable_delegations [Array<String>] Names of delegations that can be restored
24
- def initialize(warnings:, skipped_agents:, restorable_agents:,
25
- skipped_delegations:, restorable_delegations:)
26
- @warnings = warnings
27
- @skipped_agents = skipped_agents
28
- @restorable_agents = restorable_agents
29
- @skipped_delegations = skipped_delegations
30
- @restorable_delegations = restorable_delegations
31
- end
32
- end
33
- end
@@ -1,5 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module SwarmSDK
4
- VERSION = "2.7.14"
5
- end
@@ -1,95 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module SwarmSDK
4
- class Workflow
5
- # AgentConfig provides fluent API for configuring agents within a node
6
- #
7
- # This class enables the chainable syntax:
8
- # agent(:backend).delegates_to(:tester, :database)
9
- # agent(:backend, reset_context: false) # Preserve context across nodes
10
- # agent(:backend).tools(:Read, :Edit) # Override tools for this node
11
- #
12
- # @example Basic delegation
13
- # agent(:backend).delegates_to(:tester)
14
- #
15
- # @example No delegation (solo agent)
16
- # agent(:planner)
17
- #
18
- # @example Preserve agent context
19
- # agent(:architect, reset_context: false)
20
- #
21
- # @example Override tools for this node
22
- # agent(:backend).tools(:Read, :Think)
23
- #
24
- # @example Combine delegation and tool override
25
- # agent(:backend).delegates_to(:tester).tools(:Read, :Edit, :Write)
26
- class AgentConfig
27
- attr_reader :agent_name
28
-
29
- def initialize(agent_name, node_builder, reset_context: true)
30
- @agent_name = agent_name
31
- @node_builder = node_builder
32
- @delegates_to = []
33
- @reset_context = reset_context
34
- @tools = nil # nil means use global agent definition tools
35
- @finalized = false
36
- end
37
-
38
- # Set delegation targets for this agent
39
- #
40
- # Supports multiple formats for flexibility:
41
- # - Array: delegates_to(:frontend, :backend)
42
- # - Hash: delegates_to(frontend: "AskFrontend", backend: "GetBackend")
43
- #
44
- # @param agent_names_and_options [Array<Symbol, Hash>] Names and/or hash with custom tool names
45
- # @return [self] For method chaining
46
- def delegates_to(*agent_names_and_options)
47
- # Parse delegation configs (same logic as Agent::Builder)
48
- @delegates_to = []
49
- agent_names_and_options.each do |item|
50
- case item
51
- when Symbol, String
52
- @delegates_to << { agent: item.to_sym, tool_name: nil }
53
- when Hash
54
- item.each do |agent, tool_name|
55
- @delegates_to << { agent: agent.to_sym, tool_name: tool_name }
56
- end
57
- end
58
- end
59
-
60
- update_registration
61
- self
62
- end
63
-
64
- # Override tools for this agent in this node
65
- #
66
- # @param tool_names [Array<Symbol>] Tool names to use (overrides global agent definition)
67
- # @return [self] For method chaining
68
- #
69
- # @example
70
- # agent(:backend).tools(:Read, :Edit)
71
- def tools(*tool_names)
72
- @tools = tool_names.map(&:to_sym)
73
- update_registration
74
- self
75
- end
76
-
77
- # Update agent registration (called after each fluent method)
78
- #
79
- # Always updates the registration with current state.
80
- # This allows chaining: .delegates_to(...).tools(...)
81
- #
82
- # @return [void]
83
- def update_registration
84
- @node_builder.register_agent(@agent_name, @delegates_to, @reset_context, @tools)
85
- end
86
-
87
- # Finalize agent configuration (backward compatibility)
88
- #
89
- # @return [void]
90
- def finalize
91
- update_registration
92
- end
93
- end
94
- end
95
- end