swarm_memory 2.1.5 → 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 (182) hide show
  1. checksums.yaml +4 -4
  2. data/lib/swarm_memory/version.rb +1 -1
  3. metadata +5 -184
  4. data/lib/claude_swarm/base_executor.rb +0 -133
  5. data/lib/claude_swarm/claude_code_executor.rb +0 -349
  6. data/lib/claude_swarm/claude_mcp_server.rb +0 -78
  7. data/lib/claude_swarm/cli.rb +0 -697
  8. data/lib/claude_swarm/commands/ps.rb +0 -215
  9. data/lib/claude_swarm/commands/show.rb +0 -139
  10. data/lib/claude_swarm/configuration.rb +0 -373
  11. data/lib/claude_swarm/hooks/session_start_hook.rb +0 -42
  12. data/lib/claude_swarm/json_handler.rb +0 -91
  13. data/lib/claude_swarm/mcp_generator.rb +0 -230
  14. data/lib/claude_swarm/openai/chat_completion.rb +0 -256
  15. data/lib/claude_swarm/openai/executor.rb +0 -256
  16. data/lib/claude_swarm/openai/responses.rb +0 -319
  17. data/lib/claude_swarm/orchestrator.rb +0 -878
  18. data/lib/claude_swarm/process_tracker.rb +0 -78
  19. data/lib/claude_swarm/session_cost_calculator.rb +0 -209
  20. data/lib/claude_swarm/session_path.rb +0 -42
  21. data/lib/claude_swarm/settings_generator.rb +0 -77
  22. data/lib/claude_swarm/system_utils.rb +0 -46
  23. data/lib/claude_swarm/templates/generation_prompt.md.erb +0 -230
  24. data/lib/claude_swarm/tools/reset_session_tool.rb +0 -24
  25. data/lib/claude_swarm/tools/session_info_tool.rb +0 -24
  26. data/lib/claude_swarm/tools/task_tool.rb +0 -63
  27. data/lib/claude_swarm/version.rb +0 -5
  28. data/lib/claude_swarm/worktree_manager.rb +0 -475
  29. data/lib/claude_swarm/yaml_loader.rb +0 -22
  30. data/lib/claude_swarm.rb +0 -67
  31. data/lib/swarm_cli/cli.rb +0 -201
  32. data/lib/swarm_cli/command_registry.rb +0 -61
  33. data/lib/swarm_cli/commands/mcp_serve.rb +0 -130
  34. data/lib/swarm_cli/commands/mcp_tools.rb +0 -148
  35. data/lib/swarm_cli/commands/migrate.rb +0 -55
  36. data/lib/swarm_cli/commands/run.rb +0 -173
  37. data/lib/swarm_cli/config_loader.rb +0 -98
  38. data/lib/swarm_cli/formatters/human_formatter.rb +0 -781
  39. data/lib/swarm_cli/formatters/json_formatter.rb +0 -51
  40. data/lib/swarm_cli/interactive_repl.rb +0 -924
  41. data/lib/swarm_cli/mcp_serve_options.rb +0 -44
  42. data/lib/swarm_cli/mcp_tools_options.rb +0 -59
  43. data/lib/swarm_cli/migrate_options.rb +0 -54
  44. data/lib/swarm_cli/migrator.rb +0 -132
  45. data/lib/swarm_cli/options.rb +0 -151
  46. data/lib/swarm_cli/ui/components/agent_badge.rb +0 -33
  47. data/lib/swarm_cli/ui/components/content_block.rb +0 -120
  48. data/lib/swarm_cli/ui/components/divider.rb +0 -57
  49. data/lib/swarm_cli/ui/components/panel.rb +0 -62
  50. data/lib/swarm_cli/ui/components/usage_stats.rb +0 -70
  51. data/lib/swarm_cli/ui/formatters/cost.rb +0 -49
  52. data/lib/swarm_cli/ui/formatters/number.rb +0 -58
  53. data/lib/swarm_cli/ui/formatters/text.rb +0 -77
  54. data/lib/swarm_cli/ui/formatters/time.rb +0 -73
  55. data/lib/swarm_cli/ui/icons.rb +0 -36
  56. data/lib/swarm_cli/ui/renderers/event_renderer.rb +0 -188
  57. data/lib/swarm_cli/ui/state/agent_color_cache.rb +0 -45
  58. data/lib/swarm_cli/ui/state/depth_tracker.rb +0 -40
  59. data/lib/swarm_cli/ui/state/spinner_manager.rb +0 -170
  60. data/lib/swarm_cli/ui/state/usage_tracker.rb +0 -62
  61. data/lib/swarm_cli/version.rb +0 -5
  62. data/lib/swarm_cli.rb +0 -46
  63. data/lib/swarm_sdk/agent/RETRY_LOGIC.md +0 -127
  64. data/lib/swarm_sdk/agent/builder.rb +0 -552
  65. data/lib/swarm_sdk/agent/chat.rb +0 -774
  66. data/lib/swarm_sdk/agent/chat_helpers/context_tracker.rb +0 -268
  67. data/lib/swarm_sdk/agent/chat_helpers/event_emitter.rb +0 -204
  68. data/lib/swarm_sdk/agent/chat_helpers/hook_integration.rb +0 -480
  69. data/lib/swarm_sdk/agent/chat_helpers/instrumentation.rb +0 -78
  70. data/lib/swarm_sdk/agent/chat_helpers/llm_configuration.rb +0 -233
  71. data/lib/swarm_sdk/agent/chat_helpers/logging_helpers.rb +0 -116
  72. data/lib/swarm_sdk/agent/chat_helpers/serialization.rb +0 -83
  73. data/lib/swarm_sdk/agent/chat_helpers/system_reminder_injector.rb +0 -136
  74. data/lib/swarm_sdk/agent/chat_helpers/system_reminders.rb +0 -79
  75. data/lib/swarm_sdk/agent/chat_helpers/token_tracking.rb +0 -98
  76. data/lib/swarm_sdk/agent/context.rb +0 -116
  77. data/lib/swarm_sdk/agent/context_manager.rb +0 -315
  78. data/lib/swarm_sdk/agent/definition.rb +0 -477
  79. data/lib/swarm_sdk/agent/llm_instrumentation_middleware.rb +0 -182
  80. data/lib/swarm_sdk/agent/system_prompt_builder.rb +0 -161
  81. data/lib/swarm_sdk/builders/base_builder.rb +0 -409
  82. data/lib/swarm_sdk/claude_code_agent_adapter.rb +0 -205
  83. data/lib/swarm_sdk/concerns/cleanupable.rb +0 -39
  84. data/lib/swarm_sdk/concerns/snapshotable.rb +0 -67
  85. data/lib/swarm_sdk/concerns/validatable.rb +0 -55
  86. data/lib/swarm_sdk/configuration/parser.rb +0 -353
  87. data/lib/swarm_sdk/configuration/translator.rb +0 -255
  88. data/lib/swarm_sdk/configuration.rb +0 -135
  89. data/lib/swarm_sdk/context_compactor/metrics.rb +0 -147
  90. data/lib/swarm_sdk/context_compactor/token_counter.rb +0 -106
  91. data/lib/swarm_sdk/context_compactor.rb +0 -335
  92. data/lib/swarm_sdk/context_management/builder.rb +0 -128
  93. data/lib/swarm_sdk/context_management/context.rb +0 -328
  94. data/lib/swarm_sdk/defaults.rb +0 -196
  95. data/lib/swarm_sdk/events_to_messages.rb +0 -199
  96. data/lib/swarm_sdk/hooks/adapter.rb +0 -359
  97. data/lib/swarm_sdk/hooks/context.rb +0 -197
  98. data/lib/swarm_sdk/hooks/definition.rb +0 -80
  99. data/lib/swarm_sdk/hooks/error.rb +0 -29
  100. data/lib/swarm_sdk/hooks/executor.rb +0 -146
  101. data/lib/swarm_sdk/hooks/registry.rb +0 -147
  102. data/lib/swarm_sdk/hooks/result.rb +0 -150
  103. data/lib/swarm_sdk/hooks/shell_executor.rb +0 -255
  104. data/lib/swarm_sdk/hooks/tool_call.rb +0 -35
  105. data/lib/swarm_sdk/hooks/tool_result.rb +0 -62
  106. data/lib/swarm_sdk/log_collector.rb +0 -227
  107. data/lib/swarm_sdk/log_stream.rb +0 -127
  108. data/lib/swarm_sdk/markdown_parser.rb +0 -75
  109. data/lib/swarm_sdk/model_aliases.json +0 -8
  110. data/lib/swarm_sdk/models.json +0 -1
  111. data/lib/swarm_sdk/models.rb +0 -120
  112. data/lib/swarm_sdk/node_context.rb +0 -245
  113. data/lib/swarm_sdk/observer/builder.rb +0 -81
  114. data/lib/swarm_sdk/observer/config.rb +0 -45
  115. data/lib/swarm_sdk/observer/manager.rb +0 -236
  116. data/lib/swarm_sdk/patterns/agent_observer.rb +0 -160
  117. data/lib/swarm_sdk/permissions/config.rb +0 -239
  118. data/lib/swarm_sdk/permissions/error_formatter.rb +0 -121
  119. data/lib/swarm_sdk/permissions/path_matcher.rb +0 -35
  120. data/lib/swarm_sdk/permissions/validator.rb +0 -173
  121. data/lib/swarm_sdk/permissions_builder.rb +0 -122
  122. data/lib/swarm_sdk/plugin.rb +0 -309
  123. data/lib/swarm_sdk/plugin_registry.rb +0 -101
  124. data/lib/swarm_sdk/proc_helpers.rb +0 -53
  125. data/lib/swarm_sdk/prompts/base_system_prompt.md.erb +0 -117
  126. data/lib/swarm_sdk/restore_result.rb +0 -65
  127. data/lib/swarm_sdk/result.rb +0 -123
  128. data/lib/swarm_sdk/snapshot.rb +0 -156
  129. data/lib/swarm_sdk/snapshot_from_events.rb +0 -397
  130. data/lib/swarm_sdk/state_restorer.rb +0 -476
  131. data/lib/swarm_sdk/state_snapshot.rb +0 -334
  132. data/lib/swarm_sdk/swarm/agent_initializer.rb +0 -683
  133. data/lib/swarm_sdk/swarm/all_agents_builder.rb +0 -167
  134. data/lib/swarm_sdk/swarm/builder.rb +0 -249
  135. data/lib/swarm_sdk/swarm/executor.rb +0 -213
  136. data/lib/swarm_sdk/swarm/hook_triggers.rb +0 -150
  137. data/lib/swarm_sdk/swarm/logging_callbacks.rb +0 -340
  138. data/lib/swarm_sdk/swarm/mcp_configurator.rb +0 -154
  139. data/lib/swarm_sdk/swarm/swarm_registry_builder.rb +0 -67
  140. data/lib/swarm_sdk/swarm/tool_configurator.rb +0 -358
  141. data/lib/swarm_sdk/swarm.rb +0 -717
  142. data/lib/swarm_sdk/swarm_loader.rb +0 -145
  143. data/lib/swarm_sdk/swarm_registry.rb +0 -136
  144. data/lib/swarm_sdk/tools/bash.rb +0 -282
  145. data/lib/swarm_sdk/tools/clock.rb +0 -44
  146. data/lib/swarm_sdk/tools/delegate.rb +0 -267
  147. data/lib/swarm_sdk/tools/document_converters/base_converter.rb +0 -83
  148. data/lib/swarm_sdk/tools/document_converters/docx_converter.rb +0 -99
  149. data/lib/swarm_sdk/tools/document_converters/html_converter.rb +0 -101
  150. data/lib/swarm_sdk/tools/document_converters/pdf_converter.rb +0 -78
  151. data/lib/swarm_sdk/tools/document_converters/xlsx_converter.rb +0 -194
  152. data/lib/swarm_sdk/tools/edit.rb +0 -145
  153. data/lib/swarm_sdk/tools/glob.rb +0 -166
  154. data/lib/swarm_sdk/tools/grep.rb +0 -235
  155. data/lib/swarm_sdk/tools/image_extractors/docx_image_extractor.rb +0 -43
  156. data/lib/swarm_sdk/tools/image_extractors/pdf_image_extractor.rb +0 -163
  157. data/lib/swarm_sdk/tools/image_formats/tiff_builder.rb +0 -65
  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 -272
  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 -98
  170. data/lib/swarm_sdk/tools/todo_write.rb +0 -235
  171. data/lib/swarm_sdk/tools/web_fetch.rb +0 -262
  172. data/lib/swarm_sdk/tools/write.rb +0 -112
  173. data/lib/swarm_sdk/utils.rb +0 -68
  174. data/lib/swarm_sdk/validation_result.rb +0 -33
  175. data/lib/swarm_sdk/version.rb +0 -5
  176. data/lib/swarm_sdk/workflow/agent_config.rb +0 -79
  177. data/lib/swarm_sdk/workflow/builder.rb +0 -143
  178. data/lib/swarm_sdk/workflow/executor.rb +0 -497
  179. data/lib/swarm_sdk/workflow/node_builder.rb +0 -555
  180. data/lib/swarm_sdk/workflow/transformer_executor.rb +0 -249
  181. data/lib/swarm_sdk/workflow.rb +0 -554
  182. data/lib/swarm_sdk.rb +0 -524
@@ -1,120 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module SwarmSDK
4
- # Models provides model validation and suggestion functionality
5
- #
6
- # Uses static JSON files:
7
- # - models.json: Curated model list from Parsera
8
- # - model_aliases.json: Shortcuts mapping to latest models
9
- #
10
- # This avoids network calls, API key requirements, and RubyLLM
11
- # registry manipulation.
12
- #
13
- # @example
14
- # model = SwarmSDK::Models.find("claude-sonnet-4-5-20250929")
15
- # model = SwarmSDK::Models.find("sonnet") # Uses alias
16
- # suggestions = SwarmSDK::Models.suggest_similar("anthropic:claude-sonnet-4-5")
17
- class Models
18
- MODELS_JSON_PATH = File.expand_path("models.json", __dir__)
19
- ALIASES_JSON_PATH = File.expand_path("model_aliases.json", __dir__)
20
-
21
- class << self
22
- # Find a model by ID or alias
23
- #
24
- # @param model_id [String] Model ID or alias to find
25
- # @return [Hash, nil] Model data or nil if not found
26
- def find(model_id)
27
- # Check if it's an alias first
28
- resolved_id = resolve_alias(model_id)
29
-
30
- all.find { |m| m["id"] == resolved_id || m[:id] == resolved_id }
31
- end
32
-
33
- # Resolve a model alias to full model ID
34
- #
35
- # @param model_id [String] Model ID or alias
36
- # @return [String] Resolved model ID (or original if not an alias)
37
- def resolve_alias(model_id)
38
- aliases[model_id.to_s] || model_id
39
- end
40
-
41
- # Suggest similar models for a given query
42
- #
43
- # Strips provider prefixes and normalizes for fuzzy matching.
44
- #
45
- # @param query [String] Model ID to match against
46
- # @param limit [Integer] Maximum number of suggestions
47
- # @return [Array<Hash>] Up to `limit` similar models
48
- def suggest_similar(query, limit: 3)
49
- # Strip provider prefix (e.g., "anthropic:claude-sonnet-4-5" → "claude-sonnet-4-5")
50
- query_without_prefix = query.to_s.sub(/^[^:]+:/, "")
51
- normalized_query = query_without_prefix.downcase.gsub(/[.\-_]/, "")
52
-
53
- matches = all.select do |model|
54
- model_id = (model["id"] || model[:id]).to_s
55
- model_name = (model["name"] || model[:name]).to_s
56
-
57
- normalized_id = model_id.downcase.gsub(/[.\-_]/, "")
58
- normalized_name = model_name.downcase.gsub(/[.\-_]/, "")
59
-
60
- normalized_id.include?(normalized_query) || normalized_name.include?(normalized_query)
61
- end.first(limit)
62
-
63
- matches.map do |m|
64
- {
65
- id: m["id"] || m[:id],
66
- name: m["name"] || m[:name],
67
- context_window: m["context_window"] || m[:context_window],
68
- }
69
- end
70
- end
71
-
72
- # Get all models
73
- #
74
- # @return [Array<Hash>] All models from models.json
75
- def all
76
- @models ||= load_models
77
- end
78
-
79
- # Get all aliases
80
- #
81
- # @return [Hash] Alias mappings
82
- def aliases
83
- @aliases ||= load_aliases
84
- end
85
-
86
- # Reload models and aliases from JSON files
87
- #
88
- # @return [Array<Hash>] Loaded models
89
- def reload!
90
- @models = load_models
91
- @aliases = load_aliases
92
- @models
93
- end
94
-
95
- private
96
-
97
- # Load models from JSON file
98
- #
99
- # @return [Array<Hash>] Models array
100
- def load_models
101
- JSON.parse(File.read(MODELS_JSON_PATH))
102
- rescue StandardError => e
103
- # Log error and return empty array
104
- RubyLLM.logger.error("Failed to load SwarmSDK models.json: #{e.class} - #{e.message}")
105
- []
106
- end
107
-
108
- # Load aliases from JSON file
109
- #
110
- # @return [Hash] Alias mappings
111
- def load_aliases
112
- JSON.parse(File.read(ALIASES_JSON_PATH))
113
- rescue StandardError => e
114
- # Log error and return empty hash
115
- RubyLLM.logger.debug("Failed to load SwarmSDK model_aliases.json: #{e.class} - #{e.message}")
116
- {}
117
- end
118
- end
119
- end
120
- end
@@ -1,245 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module SwarmSDK
4
- # NodeContext provides context information to node transformers
5
- #
6
- # This class is passed to input and output transformers, giving them access to:
7
- # - The original user prompt
8
- # - Results from all previous nodes
9
- # - Current node metadata
10
- # - Convenience accessors for common operations
11
- #
12
- # @example Input transformer
13
- # input do |ctx|
14
- # ctx.content # Previous node's content (convenience)
15
- # ctx.original_prompt # Original user prompt
16
- # ctx.all_results[:plan] # Access any previous node
17
- # ctx.node_name # Current node name
18
- # end
19
- #
20
- # @example Output transformer
21
- # output do |ctx|
22
- # ctx.content # Current result's content (convenience)
23
- # ctx.original_prompt # Original user prompt
24
- # ctx.all_results[:plan] # Access previous nodes
25
- # end
26
- class NodeContext
27
- attr_reader :original_prompt, :all_results, :node_name, :dependencies
28
-
29
- # For input transformers: result from previous node(s)
30
- attr_reader :previous_result
31
-
32
- # For output transformers: current node's result
33
- attr_reader :result
34
-
35
- class << self
36
- # Create a NodeContext for input transformers
37
- #
38
- # @param previous_result [Result, Hash, String] Previous node's result or hash of results
39
- # @param all_results [Hash<Symbol, Result>] Results from all completed nodes
40
- # @param original_prompt [String] The original user prompt
41
- # @param node_name [Symbol] Current node name
42
- # @param dependencies [Array<Symbol>] Node dependencies
43
- # @param transformed_content [String, nil] Already-transformed content from previous output transformer
44
- # @return [NodeContext]
45
- def for_input(previous_result:, all_results:, original_prompt:, node_name:, dependencies:, transformed_content: nil)
46
- new(
47
- previous_result: previous_result,
48
- all_results: all_results,
49
- original_prompt: original_prompt,
50
- node_name: node_name,
51
- dependencies: dependencies,
52
- result: nil,
53
- transformed_content: transformed_content,
54
- )
55
- end
56
-
57
- # Create a NodeContext for output transformers
58
- #
59
- # @param result [Result] Current node's execution result
60
- # @param all_results [Hash<Symbol, Result>] Results from all completed nodes (including current)
61
- # @param original_prompt [String] The original user prompt
62
- # @param node_name [Symbol] Current node name
63
- # @return [NodeContext]
64
- def for_output(result:, all_results:, original_prompt:, node_name:)
65
- new(
66
- result: result,
67
- all_results: all_results,
68
- original_prompt: original_prompt,
69
- node_name: node_name,
70
- dependencies: [],
71
- previous_result: nil,
72
- transformed_content: nil,
73
- )
74
- end
75
- end
76
-
77
- def initialize(previous_result:, all_results:, original_prompt:, node_name:, dependencies:, result:, transformed_content:)
78
- @previous_result = previous_result
79
- @result = result
80
- @all_results = all_results
81
- @original_prompt = original_prompt
82
- @node_name = node_name
83
- @dependencies = dependencies
84
- @transformed_content = transformed_content
85
- end
86
-
87
- # Convenience accessor: Get content from previous_result or result
88
- #
89
- # For input transformers:
90
- # - Returns transformed_content if available (from previous output transformer)
91
- # - Otherwise returns previous_result.content (original content)
92
- # - Returns nil for multiple dependencies (use all_results instead)
93
- # For output transformers: returns result.content
94
- #
95
- # @return [String, nil]
96
- def content
97
- if @result
98
- # Output transformer context: return current result's content
99
- @result.content
100
- elsif @transformed_content
101
- # Input transformer with transformed content from previous output
102
- @transformed_content
103
- elsif @previous_result.respond_to?(:content)
104
- # Input transformer context with Result object (original content)
105
- @previous_result.content
106
- elsif @previous_result.is_a?(Hash)
107
- # Input transformer with multiple dependencies (hash of results)
108
- nil # No single "content" - user must pick from all_results hash
109
- else
110
- # String or other type (initial prompt, no dependencies)
111
- @previous_result.to_s
112
- end
113
- end
114
-
115
- # Convenience accessor: Get agent from previous_result or result
116
- #
117
- # @return [String, nil]
118
- def agent
119
- if @result
120
- @result.agent
121
- elsif @previous_result.respond_to?(:agent)
122
- @previous_result.agent
123
- end
124
- end
125
-
126
- # Convenience accessor: Get logs from previous_result or result
127
- #
128
- # @return [Array, nil]
129
- def logs
130
- if @result
131
- @result.logs
132
- elsif @previous_result.respond_to?(:logs)
133
- @previous_result.logs
134
- end
135
- end
136
-
137
- # Convenience accessor: Get duration from previous_result or result
138
- #
139
- # @return [Float, nil]
140
- def duration
141
- if @result
142
- @result.duration
143
- elsif @previous_result.respond_to?(:duration)
144
- @previous_result.duration
145
- end
146
- end
147
-
148
- # Convenience accessor: Get error from previous_result or result
149
- #
150
- # @return [Exception, nil]
151
- def error
152
- if @result
153
- @result.error
154
- elsif @previous_result.respond_to?(:error)
155
- @previous_result.error
156
- end
157
- end
158
-
159
- # Convenience accessor: Check success status
160
- #
161
- # @return [Boolean, nil]
162
- def success?
163
- if @result
164
- @result.success?
165
- elsif @previous_result.respond_to?(:success?)
166
- @previous_result.success?
167
- end
168
- end
169
-
170
- # Control flow methods for transformers
171
- # These return special hashes that Workflow recognizes
172
-
173
- # Skip current node's LLM execution and return content immediately
174
- #
175
- # Only valid for input transformers.
176
- #
177
- # @param content [String] Content to return (skips LLM call)
178
- # @return [Hash] Control hash for skip_execution
179
- # @raise [ArgumentError] If content is nil
180
- #
181
- # @example
182
- # input do |ctx|
183
- # cached = check_cache(ctx.content)
184
- # return ctx.skip_execution(content: cached) if cached
185
- # ctx.content
186
- # end
187
- def skip_execution(content:)
188
- if content.nil?
189
- raise ArgumentError,
190
- "skip_execution requires content (got nil). " \
191
- "Check that ctx.content or your content source is not nil. " \
192
- "Node: #{@node_name}"
193
- end
194
- { skip_execution: true, content: content }
195
- end
196
-
197
- # Halt entire workflow and return content as final result
198
- #
199
- # Valid for both input and output transformers.
200
- #
201
- # @param content [String] Final content to return
202
- # @return [Hash] Control hash for halt_workflow
203
- # @raise [ArgumentError] If content is nil
204
- #
205
- # @example
206
- # output do |ctx|
207
- # return ctx.halt_workflow(content: ctx.content) if converged?(ctx.content)
208
- # ctx.content
209
- # end
210
- def halt_workflow(content:)
211
- if content.nil?
212
- raise ArgumentError,
213
- "halt_workflow requires content (got nil). " \
214
- "Check that ctx.content or your content source is not nil. " \
215
- "Node: #{@node_name}"
216
- end
217
- { halt_workflow: true, content: content }
218
- end
219
-
220
- # Jump to a different node with provided content as input
221
- #
222
- # Valid for both input and output transformers.
223
- #
224
- # @param node [Symbol] Node name to jump to
225
- # @param content [String] Content to pass to target node
226
- # @return [Hash] Control hash for goto_node
227
- # @raise [ArgumentError] If content is nil
228
- #
229
- # @example
230
- # input do |ctx|
231
- # return ctx.goto_node(:review, content: ctx.content) if needs_review?(ctx.content)
232
- # ctx.content
233
- # end
234
- def goto_node(node, content:)
235
- if content.nil?
236
- raise ArgumentError,
237
- "goto_node requires content (got nil). " \
238
- "Check that ctx.content or your content source is not nil. " \
239
- "This often happens when the previous node failed with an error. " \
240
- "Node: #{@node_name}, Target: #{node}"
241
- end
242
- { goto_node: node.to_sym, content: content }
243
- end
244
- end
245
- end
@@ -1,81 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module SwarmSDK
4
- module Observer
5
- # DSL for configuring observer agents
6
- #
7
- # Used by Swarm::Builder#observer to provide a clean DSL for defining
8
- # event handlers and observer configuration options.
9
- #
10
- # @example Basic usage
11
- # observer :profiler do
12
- # on :swarm_start do |event|
13
- # "Analyze this prompt: #{event[:prompt]}"
14
- # end
15
- #
16
- # timeout 120
17
- # max_concurrent 2
18
- # end
19
- class Builder
20
- # Initialize builder with agent name and config
21
- #
22
- # @param agent_name [Symbol] Name of the observer agent
23
- # @param config [Observer::Config] Configuration object to populate
24
- def initialize(agent_name, config)
25
- @agent_name = agent_name
26
- @config = config
27
- end
28
-
29
- # Register an event handler
30
- #
31
- # The block receives the event hash and should return:
32
- # - A prompt string to trigger the observer agent
33
- # - nil to skip execution for this event
34
- #
35
- # @param event_type [Symbol] Type of event to handle (e.g., :swarm_start, :tool_call)
36
- # @yield [Hash] Event hash
37
- # @yieldreturn [String, nil] Prompt or nil to skip
38
- # @return [void]
39
- #
40
- # @example
41
- # on :tool_call do |event|
42
- # next unless event[:tool_name] == "Bash"
43
- # "Check this command: #{event[:arguments][:command]}"
44
- # end
45
- def on(event_type, &block)
46
- @config.add_handler(event_type, &block)
47
- end
48
-
49
- # Set maximum concurrent executions for this observer
50
- #
51
- # Limits how many instances of this observer agent can run simultaneously.
52
- # Useful for resource-intensive observers.
53
- #
54
- # @param n [Integer] Maximum concurrent executions
55
- # @return [void]
56
- def max_concurrent(n)
57
- @config.options[:max_concurrent] = n
58
- end
59
-
60
- # Set timeout for observer execution
61
- #
62
- # Observer tasks will be cancelled after this duration.
63
- #
64
- # @param seconds [Integer] Timeout in seconds (default: 60)
65
- # @return [void]
66
- def timeout(seconds)
67
- @config.options[:timeout] = seconds
68
- end
69
-
70
- # Wait for observer to complete before swarm execution ends
71
- #
72
- # By default, observers are fire-and-forget. This option causes
73
- # the main execution to wait for this observer to complete.
74
- #
75
- # @return [void]
76
- def wait_for_completion!
77
- @config.options[:fire_and_forget] = false
78
- end
79
- end
80
- end
81
- end
@@ -1,45 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module SwarmSDK
4
- module Observer
5
- # Configuration for an observer agent
6
- #
7
- # Holds the agent name, event handlers (blocks that return prompts or nil),
8
- # and execution options.
9
- #
10
- # @example
11
- # config = Observer::Config.new(:profiler)
12
- # config.add_handler(:swarm_start) { |event| "Analyze: #{event[:prompt]}" }
13
- # config.options[:timeout] = 120
14
- class Config
15
- attr_reader :agent_name, :event_handlers, :options
16
-
17
- # Initialize a new observer configuration
18
- #
19
- # @param agent_name [Symbol] Name of the agent to use as observer
20
- def initialize(agent_name)
21
- @agent_name = agent_name
22
- @event_handlers = {} # { event_type => block }
23
- @options = {
24
- max_concurrent: nil,
25
- timeout: 60,
26
- fire_and_forget: true,
27
- }
28
- end
29
-
30
- # Add an event handler for a specific event type
31
- #
32
- # The block receives the event hash and should return:
33
- # - A prompt string to trigger the observer agent
34
- # - nil to skip execution for this event
35
- #
36
- # @param event_type [Symbol] Type of event to handle (e.g., :swarm_start, :tool_call)
37
- # @yield [Hash] Event hash with type, agent, and other data
38
- # @yieldreturn [String, nil] Prompt to execute or nil to skip
39
- # @return [void]
40
- def add_handler(event_type, &block)
41
- @event_handlers[event_type] = block
42
- end
43
- end
44
- end
45
- end