swarm_memory 2.1.2 → 2.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/claude_swarm/claude_mcp_server.rb +1 -0
- data/lib/claude_swarm/cli.rb +5 -18
- data/lib/claude_swarm/configuration.rb +30 -19
- data/lib/claude_swarm/mcp_generator.rb +5 -10
- data/lib/claude_swarm/openai/chat_completion.rb +4 -12
- data/lib/claude_swarm/openai/executor.rb +3 -1
- data/lib/claude_swarm/openai/responses.rb +13 -32
- data/lib/claude_swarm/version.rb +1 -1
- data/lib/swarm_cli/commands/mcp_serve.rb +2 -2
- data/lib/swarm_cli/commands/run.rb +2 -2
- data/lib/swarm_cli/config_loader.rb +14 -14
- data/lib/swarm_cli/formatters/human_formatter.rb +70 -0
- data/lib/swarm_cli/interactive_repl.rb +11 -5
- data/lib/swarm_cli/ui/icons.rb +0 -23
- data/lib/swarm_cli/version.rb +1 -1
- data/lib/swarm_memory/adapters/base.rb +4 -4
- data/lib/swarm_memory/adapters/filesystem_adapter.rb +11 -34
- data/lib/swarm_memory/core/storage_read_tracker.rb +51 -14
- data/lib/swarm_memory/integration/cli_registration.rb +3 -2
- data/lib/swarm_memory/integration/sdk_plugin.rb +98 -12
- data/lib/swarm_memory/tools/memory_edit.rb +2 -2
- data/lib/swarm_memory/tools/memory_multi_edit.rb +2 -2
- data/lib/swarm_memory/tools/memory_read.rb +3 -3
- data/lib/swarm_memory/version.rb +1 -1
- data/lib/swarm_memory.rb +6 -1
- data/lib/swarm_sdk/agent/builder.rb +91 -0
- data/lib/swarm_sdk/agent/chat.rb +540 -925
- data/lib/swarm_sdk/agent/{chat → chat_helpers}/context_tracker.rb +33 -79
- data/lib/swarm_sdk/agent/chat_helpers/event_emitter.rb +204 -0
- data/lib/swarm_sdk/agent/{chat → chat_helpers}/hook_integration.rb +147 -39
- data/lib/swarm_sdk/agent/chat_helpers/instrumentation.rb +78 -0
- data/lib/swarm_sdk/agent/chat_helpers/llm_configuration.rb +233 -0
- data/lib/swarm_sdk/agent/{chat → chat_helpers}/logging_helpers.rb +1 -1
- data/lib/swarm_sdk/agent/chat_helpers/serialization.rb +83 -0
- data/lib/swarm_sdk/agent/{chat → chat_helpers}/system_reminder_injector.rb +22 -38
- data/lib/swarm_sdk/agent/chat_helpers/system_reminders.rb +79 -0
- data/lib/swarm_sdk/agent/chat_helpers/token_tracking.rb +98 -0
- data/lib/swarm_sdk/agent/context.rb +8 -4
- data/lib/swarm_sdk/agent/context_manager.rb +6 -0
- data/lib/swarm_sdk/agent/definition.rb +79 -174
- data/lib/swarm_sdk/agent/llm_instrumentation_middleware.rb +182 -0
- data/lib/swarm_sdk/agent/system_prompt_builder.rb +161 -0
- data/lib/swarm_sdk/builders/base_builder.rb +409 -0
- data/lib/swarm_sdk/concerns/cleanupable.rb +39 -0
- data/lib/swarm_sdk/concerns/snapshotable.rb +67 -0
- data/lib/swarm_sdk/concerns/validatable.rb +55 -0
- data/lib/swarm_sdk/configuration/parser.rb +353 -0
- data/lib/swarm_sdk/configuration/translator.rb +255 -0
- data/lib/swarm_sdk/configuration.rb +100 -261
- data/lib/swarm_sdk/context_compactor/token_counter.rb +3 -3
- data/lib/swarm_sdk/context_compactor.rb +6 -11
- data/lib/swarm_sdk/context_management/builder.rb +128 -0
- data/lib/swarm_sdk/context_management/context.rb +328 -0
- data/lib/swarm_sdk/defaults.rb +196 -0
- data/lib/swarm_sdk/events_to_messages.rb +199 -0
- data/lib/swarm_sdk/hooks/shell_executor.rb +2 -1
- data/lib/swarm_sdk/log_collector.rb +192 -16
- data/lib/swarm_sdk/log_stream.rb +66 -8
- data/lib/swarm_sdk/model_aliases.json +4 -1
- data/lib/swarm_sdk/node_context.rb +1 -1
- data/lib/swarm_sdk/observer/builder.rb +81 -0
- data/lib/swarm_sdk/observer/config.rb +45 -0
- data/lib/swarm_sdk/observer/manager.rb +236 -0
- data/lib/swarm_sdk/patterns/agent_observer.rb +160 -0
- data/lib/swarm_sdk/plugin.rb +93 -3
- data/lib/swarm_sdk/proc_helpers.rb +53 -0
- data/lib/swarm_sdk/prompts/base_system_prompt.md.erb +0 -126
- data/lib/swarm_sdk/restore_result.rb +65 -0
- data/lib/swarm_sdk/snapshot.rb +156 -0
- data/lib/swarm_sdk/snapshot_from_events.rb +397 -0
- data/lib/swarm_sdk/state_restorer.rb +476 -0
- data/lib/swarm_sdk/state_snapshot.rb +334 -0
- data/lib/swarm_sdk/swarm/agent_initializer.rb +428 -79
- data/lib/swarm_sdk/swarm/all_agents_builder.rb +28 -1
- data/lib/swarm_sdk/swarm/builder.rb +69 -407
- data/lib/swarm_sdk/swarm/executor.rb +213 -0
- data/lib/swarm_sdk/swarm/hook_triggers.rb +150 -0
- data/lib/swarm_sdk/swarm/logging_callbacks.rb +340 -0
- data/lib/swarm_sdk/swarm/mcp_configurator.rb +7 -4
- data/lib/swarm_sdk/swarm/swarm_registry_builder.rb +67 -0
- data/lib/swarm_sdk/swarm/tool_configurator.rb +88 -149
- data/lib/swarm_sdk/swarm.rb +366 -631
- data/lib/swarm_sdk/swarm_loader.rb +145 -0
- data/lib/swarm_sdk/swarm_registry.rb +136 -0
- data/lib/swarm_sdk/tools/bash.rb +11 -3
- data/lib/swarm_sdk/tools/delegate.rb +127 -24
- data/lib/swarm_sdk/tools/edit.rb +8 -13
- data/lib/swarm_sdk/tools/glob.rb +9 -1
- data/lib/swarm_sdk/tools/grep.rb +7 -0
- data/lib/swarm_sdk/tools/multi_edit.rb +15 -11
- data/lib/swarm_sdk/tools/path_resolver.rb +51 -2
- data/lib/swarm_sdk/tools/read.rb +28 -18
- data/lib/swarm_sdk/tools/registry.rb +122 -10
- data/lib/swarm_sdk/tools/scratchpad/scratchpad_list.rb +23 -2
- data/lib/swarm_sdk/tools/scratchpad/scratchpad_read.rb +23 -2
- data/lib/swarm_sdk/tools/scratchpad/scratchpad_write.rb +21 -4
- data/lib/swarm_sdk/tools/stores/read_tracker.rb +47 -12
- data/lib/swarm_sdk/tools/stores/scratchpad_storage.rb +53 -5
- data/lib/swarm_sdk/tools/stores/storage.rb +0 -6
- data/lib/swarm_sdk/tools/think.rb +4 -1
- data/lib/swarm_sdk/tools/todo_write.rb +27 -8
- data/lib/swarm_sdk/tools/web_fetch.rb +3 -2
- data/lib/swarm_sdk/tools/write.rb +8 -13
- data/lib/swarm_sdk/utils.rb +18 -0
- data/lib/swarm_sdk/validation_result.rb +33 -0
- data/lib/swarm_sdk/version.rb +1 -1
- data/lib/swarm_sdk/{node → workflow}/agent_config.rb +34 -9
- data/lib/swarm_sdk/workflow/builder.rb +143 -0
- data/lib/swarm_sdk/workflow/executor.rb +497 -0
- data/lib/swarm_sdk/{node/builder.rb → workflow/node_builder.rb} +42 -21
- data/lib/swarm_sdk/{node → workflow}/transformer_executor.rb +3 -2
- data/lib/swarm_sdk/workflow.rb +554 -0
- data/lib/swarm_sdk.rb +393 -22
- metadata +51 -16
- data/lib/swarm_memory/chat_extension.rb +0 -34
- data/lib/swarm_sdk/node_orchestrator.rb +0 -591
- data/lib/swarm_sdk/providers/openai_with_responses.rb +0 -582
|
@@ -82,7 +82,10 @@ module SwarmSDK
|
|
|
82
82
|
required: true
|
|
83
83
|
|
|
84
84
|
def execute(**kwargs)
|
|
85
|
-
|
|
85
|
+
<<~RESP
|
|
86
|
+
Thought noted.
|
|
87
|
+
RESP
|
|
88
|
+
# <system-reminder>The user cannot see your thoughts. You MUST NOT stop without giving the user a response.</system-reminder>
|
|
86
89
|
end
|
|
87
90
|
|
|
88
91
|
private
|
|
@@ -7,18 +7,25 @@ module SwarmSDK
|
|
|
7
7
|
# This tool helps agents track progress on complex multi-step tasks.
|
|
8
8
|
# Each agent maintains its own independent todo list.
|
|
9
9
|
class TodoWrite < RubyLLM::Tool
|
|
10
|
+
# Factory pattern: declare what parameters this tool needs for instantiation
|
|
11
|
+
class << self
|
|
12
|
+
def creation_requirements
|
|
13
|
+
[:agent_name]
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
10
17
|
description <<~DESC
|
|
11
|
-
Use this tool to create and manage a structured task list for your current
|
|
18
|
+
Use this tool to create and manage a structured task list for your current work session. This helps you track progress, organize complex tasks, and demonstrate thoroughness to the user.
|
|
12
19
|
It also helps the user understand the progress of the task and overall progress of their requests.
|
|
13
20
|
|
|
14
21
|
## When to Use This Tool
|
|
15
22
|
Use this tool proactively in these scenarios:
|
|
16
23
|
|
|
17
24
|
**CRITICAL**: Follow this workflow for multi-step tasks:
|
|
18
|
-
1. FIRST: Analyze the task scope (
|
|
19
|
-
2. SECOND: Create a COMPLETE todo list with ALL known tasks BEFORE starting
|
|
25
|
+
1. FIRST: Analyze the task scope (gather information, understand requirements)
|
|
26
|
+
2. SECOND: Create a COMPLETE todo list with ALL known tasks BEFORE starting work
|
|
20
27
|
3. THIRD: Execute tasks, marking in_progress → completed as you work
|
|
21
|
-
4. ONLY add new todos if unexpected work is discovered during
|
|
28
|
+
4. ONLY add new todos if unexpected work is discovered during execution
|
|
22
29
|
|
|
23
30
|
Use the todo list when:
|
|
24
31
|
1. Complex multi-step tasks - When a task requires 3 or more distinct steps or actions
|
|
@@ -27,7 +34,7 @@ module SwarmSDK
|
|
|
27
34
|
4. User provides multiple tasks - When users provide a list of things to be done (numbered or comma-separated)
|
|
28
35
|
5. After receiving new instructions - After analyzing scope, create complete todo list before starting work
|
|
29
36
|
6. When you start working on a task - Mark it as in_progress BEFORE beginning work. Ideally you should only have one todo as in_progress at a time
|
|
30
|
-
7. After completing a task - Mark it as completed and add any new follow-up tasks discovered during
|
|
37
|
+
7. After completing a task - Mark it as completed and add any new follow-up tasks discovered during execution
|
|
31
38
|
|
|
32
39
|
## When NOT to Use This Tool
|
|
33
40
|
|
|
@@ -73,9 +80,21 @@ module SwarmSDK
|
|
|
73
80
|
- Create specific, actionable items
|
|
74
81
|
- Break complex tasks into smaller, manageable steps
|
|
75
82
|
- Use clear, descriptive task names
|
|
76
|
-
- Always provide both forms
|
|
77
|
-
|
|
78
|
-
|
|
83
|
+
- Always provide both forms (content and activeForm)
|
|
84
|
+
|
|
85
|
+
## Examples
|
|
86
|
+
|
|
87
|
+
**Coding Tasks**:
|
|
88
|
+
- content: "Fix authentication bug in login handler"
|
|
89
|
+
- activeForm: "Fixing authentication bug in login handler"
|
|
90
|
+
|
|
91
|
+
**Non-Coding Tasks**:
|
|
92
|
+
- content: "Analyze customer feedback from Q4 survey"
|
|
93
|
+
- activeForm: "Analyzing customer feedback from Q4 survey"
|
|
94
|
+
|
|
95
|
+
**Research Tasks**:
|
|
96
|
+
- content: "Research best practices for API rate limiting"
|
|
97
|
+
- activeForm: "Researching best practices for API rate limiting"
|
|
79
98
|
|
|
80
99
|
When in doubt, use this tool. Being proactive with task management demonstrates attentiveness and ensures you complete all requirements successfully.
|
|
81
100
|
DESC
|
|
@@ -51,9 +51,10 @@ module SwarmSDK
|
|
|
51
51
|
desc: "The prompt to run on the fetched content. Required when SwarmSDK is configured with webfetch_provider and webfetch_model. Optional otherwise (ignored if LLM processing not configured).",
|
|
52
52
|
required: false
|
|
53
53
|
|
|
54
|
-
|
|
54
|
+
# Backward compatibility aliases - use Defaults module for new code
|
|
55
|
+
MAX_CONTENT_LENGTH = Defaults::Limits::WEB_FETCH_CHARACTERS
|
|
55
56
|
USER_AGENT = "SwarmSDK WebFetch Tool (https://github.com/parruda/claude-swarm)"
|
|
56
|
-
TIMEOUT =
|
|
57
|
+
TIMEOUT = Defaults::Timeouts::WEB_FETCH_SECONDS
|
|
57
58
|
|
|
58
59
|
def execute(url:, prompt: nil)
|
|
59
60
|
# Validate inputs
|
|
@@ -10,6 +10,13 @@ module SwarmSDK
|
|
|
10
10
|
class Write < RubyLLM::Tool
|
|
11
11
|
include PathResolver
|
|
12
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
|
+
|
|
13
20
|
description <<~DESC
|
|
14
21
|
Writes a file to the local filesystem.
|
|
15
22
|
This tool will overwrite the existing file if there is one at the provided path.
|
|
@@ -42,8 +49,7 @@ module SwarmSDK
|
|
|
42
49
|
# @param directory [String] Agent's working directory
|
|
43
50
|
def initialize(agent_name:, directory:)
|
|
44
51
|
super()
|
|
45
|
-
|
|
46
|
-
@directory = File.expand_path(directory)
|
|
52
|
+
initialize_agent_context(agent_name: agent_name, directory: directory)
|
|
47
53
|
end
|
|
48
54
|
|
|
49
55
|
# Override name to return simple "Write" instead of full class path
|
|
@@ -101,17 +107,6 @@ module SwarmSDK
|
|
|
101
107
|
rescue StandardError => e
|
|
102
108
|
error("Unexpected error writing file: #{e.class.name} - #{e.message}")
|
|
103
109
|
end
|
|
104
|
-
|
|
105
|
-
private
|
|
106
|
-
|
|
107
|
-
# Helper methods
|
|
108
|
-
def validation_error(message)
|
|
109
|
-
"<tool_use_error>InputValidationError: #{message}</tool_use_error>"
|
|
110
|
-
end
|
|
111
|
-
|
|
112
|
-
def error(message)
|
|
113
|
-
"Error: #{message}"
|
|
114
|
-
end
|
|
115
110
|
end
|
|
116
111
|
end
|
|
117
112
|
end
|
data/lib/swarm_sdk/utils.rb
CHANGED
|
@@ -45,6 +45,24 @@ module SwarmSDK
|
|
|
45
45
|
obj
|
|
46
46
|
end
|
|
47
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
|
|
48
66
|
end
|
|
49
67
|
end
|
|
50
68
|
end
|
|
@@ -0,0 +1,33 @@
|
|
|
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
|
data/lib/swarm_sdk/version.rb
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module SwarmSDK
|
|
4
|
-
|
|
4
|
+
class Workflow
|
|
5
5
|
# AgentConfig provides fluent API for configuring agents within a node
|
|
6
6
|
#
|
|
7
7
|
# This class enables the chainable syntax:
|
|
8
8
|
# agent(:backend).delegates_to(:tester, :database)
|
|
9
9
|
# agent(:backend, reset_context: false) # Preserve context across nodes
|
|
10
|
+
# agent(:backend).tools(:Read, :Edit) # Override tools for this node
|
|
10
11
|
#
|
|
11
12
|
# @example Basic delegation
|
|
12
13
|
# agent(:backend).delegates_to(:tester)
|
|
@@ -16,6 +17,12 @@ module SwarmSDK
|
|
|
16
17
|
#
|
|
17
18
|
# @example Preserve agent context
|
|
18
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)
|
|
19
26
|
class AgentConfig
|
|
20
27
|
attr_reader :agent_name
|
|
21
28
|
|
|
@@ -24,6 +31,7 @@ module SwarmSDK
|
|
|
24
31
|
@node_builder = node_builder
|
|
25
32
|
@delegates_to = []
|
|
26
33
|
@reset_context = reset_context
|
|
34
|
+
@tools = nil # nil means use global agent definition tools
|
|
27
35
|
@finalized = false
|
|
28
36
|
end
|
|
29
37
|
|
|
@@ -33,21 +41,38 @@ module SwarmSDK
|
|
|
33
41
|
# @return [self] For method chaining
|
|
34
42
|
def delegates_to(*agent_names)
|
|
35
43
|
@delegates_to = agent_names.map(&:to_sym)
|
|
36
|
-
|
|
44
|
+
update_registration
|
|
37
45
|
self
|
|
38
46
|
end
|
|
39
47
|
|
|
40
|
-
#
|
|
48
|
+
# Override tools for this agent in this node
|
|
49
|
+
#
|
|
50
|
+
# @param tool_names [Array<Symbol>] Tool names to use (overrides global agent definition)
|
|
51
|
+
# @return [self] For method chaining
|
|
41
52
|
#
|
|
42
|
-
#
|
|
43
|
-
#
|
|
53
|
+
# @example
|
|
54
|
+
# agent(:backend).tools(:Read, :Edit)
|
|
55
|
+
def tools(*tool_names)
|
|
56
|
+
@tools = tool_names.map(&:to_sym)
|
|
57
|
+
update_registration
|
|
58
|
+
self
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Update agent registration (called after each fluent method)
|
|
62
|
+
#
|
|
63
|
+
# Always updates the registration with current state.
|
|
64
|
+
# This allows chaining: .delegates_to(...).tools(...)
|
|
44
65
|
#
|
|
45
66
|
# @return [void]
|
|
46
|
-
def
|
|
47
|
-
|
|
67
|
+
def update_registration
|
|
68
|
+
@node_builder.register_agent(@agent_name, @delegates_to, @reset_context, @tools)
|
|
69
|
+
end
|
|
48
70
|
|
|
49
|
-
|
|
50
|
-
|
|
71
|
+
# Finalize agent configuration (backward compatibility)
|
|
72
|
+
#
|
|
73
|
+
# @return [void]
|
|
74
|
+
def finalize
|
|
75
|
+
update_registration
|
|
51
76
|
end
|
|
52
77
|
end
|
|
53
78
|
end
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SwarmSDK
|
|
4
|
+
class Workflow
|
|
5
|
+
# Builder provides DSL for building multi-node workflows
|
|
6
|
+
# This is the top-level builder accessed via SwarmSDK.workflow
|
|
7
|
+
#
|
|
8
|
+
# The DSL enables:
|
|
9
|
+
# - Node-based workflow configuration
|
|
10
|
+
# - Agent delegation per node
|
|
11
|
+
# - Input/output transformers for data flow
|
|
12
|
+
# - Context preservation across nodes
|
|
13
|
+
#
|
|
14
|
+
# @example Multi-stage workflow
|
|
15
|
+
# workflow = SwarmSDK.workflow do
|
|
16
|
+
# name "Build Pipeline"
|
|
17
|
+
# start_node :planning
|
|
18
|
+
#
|
|
19
|
+
# agent :architect do
|
|
20
|
+
# model "gpt-5"
|
|
21
|
+
# prompt "You design systems"
|
|
22
|
+
# end
|
|
23
|
+
#
|
|
24
|
+
# agent :coder do
|
|
25
|
+
# model "gpt-4"
|
|
26
|
+
# prompt "You implement code"
|
|
27
|
+
# end
|
|
28
|
+
#
|
|
29
|
+
# node :planning do
|
|
30
|
+
# agent(:architect)
|
|
31
|
+
# end
|
|
32
|
+
#
|
|
33
|
+
# node :implementation do
|
|
34
|
+
# agent(:coder)
|
|
35
|
+
# depends_on :planning
|
|
36
|
+
# end
|
|
37
|
+
# end
|
|
38
|
+
#
|
|
39
|
+
# workflow.execute("Build auth system")
|
|
40
|
+
class Builder < Builders::BaseBuilder
|
|
41
|
+
# Main entry point for DSL
|
|
42
|
+
#
|
|
43
|
+
# @example
|
|
44
|
+
# workflow = SwarmSDK.workflow do
|
|
45
|
+
# name "Pipeline"
|
|
46
|
+
# start_node :planning
|
|
47
|
+
# node(:planning) { agent(:architect) }
|
|
48
|
+
# end
|
|
49
|
+
class << self
|
|
50
|
+
def build(allow_filesystem_tools: nil, &block)
|
|
51
|
+
builder = new(allow_filesystem_tools: allow_filesystem_tools)
|
|
52
|
+
builder.instance_eval(&block)
|
|
53
|
+
builder.build_swarm
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def initialize(allow_filesystem_tools: nil)
|
|
58
|
+
super
|
|
59
|
+
@nodes = {}
|
|
60
|
+
@start_node = nil
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Define a node (mini-swarm execution stage)
|
|
64
|
+
#
|
|
65
|
+
# Nodes enable multi-stage workflows where different agent teams
|
|
66
|
+
# collaborate in sequence. Each node is an independent swarm execution.
|
|
67
|
+
#
|
|
68
|
+
# @param name [Symbol] Node name
|
|
69
|
+
# @yield Block for node configuration
|
|
70
|
+
# @return [void]
|
|
71
|
+
#
|
|
72
|
+
# @example Solo agent node
|
|
73
|
+
# node :planning do
|
|
74
|
+
# agent(:architect)
|
|
75
|
+
# end
|
|
76
|
+
#
|
|
77
|
+
# @example Multi-agent node with delegation
|
|
78
|
+
# node :implementation do
|
|
79
|
+
# agent(:backend).delegates_to(:tester, :database)
|
|
80
|
+
# agent(:tester).delegates_to(:database)
|
|
81
|
+
# agent(:database)
|
|
82
|
+
# depends_on :planning
|
|
83
|
+
# end
|
|
84
|
+
def node(name, &block)
|
|
85
|
+
builder = Workflow::NodeBuilder.new(name)
|
|
86
|
+
builder.instance_eval(&block)
|
|
87
|
+
@nodes[name] = builder
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Set the starting node for workflow execution
|
|
91
|
+
#
|
|
92
|
+
# Required when nodes are defined. Specifies which node to execute first.
|
|
93
|
+
#
|
|
94
|
+
# @param name [Symbol] Name of starting node
|
|
95
|
+
# @return [void]
|
|
96
|
+
#
|
|
97
|
+
# @example
|
|
98
|
+
# start_node :planning
|
|
99
|
+
def start_node(name)
|
|
100
|
+
@start_node = name.to_sym
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Build the actual Workflow instance
|
|
104
|
+
def build_swarm # Returns Workflow despite method name
|
|
105
|
+
raise ConfigurationError, "Workflow name not set. Use: name 'My Workflow'" unless @swarm_name
|
|
106
|
+
raise ConfigurationError, "No nodes defined. Use: node :name { ... }" if @nodes.empty?
|
|
107
|
+
raise ConfigurationError, "start_node not set. Use: start_node :name" unless @start_node
|
|
108
|
+
|
|
109
|
+
# Validate filesystem tools BEFORE building
|
|
110
|
+
validate_all_agents_filesystem_tools if @all_agents_config
|
|
111
|
+
validate_agent_filesystem_tools
|
|
112
|
+
|
|
113
|
+
build_workflow
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
private
|
|
117
|
+
|
|
118
|
+
# Build a node-based workflow
|
|
119
|
+
#
|
|
120
|
+
# @return [Workflow] Configured workflow instance
|
|
121
|
+
def build_workflow
|
|
122
|
+
# Build agent definitions
|
|
123
|
+
agent_definitions = build_agent_definitions
|
|
124
|
+
|
|
125
|
+
# Create workflow
|
|
126
|
+
workflow = Workflow.new(
|
|
127
|
+
swarm_name: @swarm_name,
|
|
128
|
+
swarm_id: @swarm_id,
|
|
129
|
+
agent_definitions: agent_definitions,
|
|
130
|
+
nodes: @nodes,
|
|
131
|
+
start_node: @start_node,
|
|
132
|
+
scratchpad: @scratchpad,
|
|
133
|
+
allow_filesystem_tools: @allow_filesystem_tools,
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
# Pass swarm registry config to workflow if external swarms registered
|
|
137
|
+
workflow.swarm_registry_config = @swarm_registry_config if @swarm_registry_config.any?
|
|
138
|
+
|
|
139
|
+
workflow
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|