claude_swarm 1.0.0 → 1.0.2

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 (267) hide show
  1. checksums.yaml +4 -4
  2. data/.claude/commands/release.md +1 -1
  3. data/.claude/hooks/lint-code-files.rb +65 -0
  4. data/.rubocop.yml +22 -2
  5. data/CHANGELOG.md +21 -1
  6. data/CLAUDE.md +1 -1
  7. data/CONTRIBUTING.md +69 -0
  8. data/README.md +27 -2
  9. data/Rakefile +71 -3
  10. data/analyze_coverage.rb +94 -0
  11. data/docs/v2/CHANGELOG.swarm_cli.md +43 -0
  12. data/docs/v2/CHANGELOG.swarm_memory.md +379 -0
  13. data/docs/v2/CHANGELOG.swarm_sdk.md +362 -0
  14. data/docs/v2/README.md +308 -0
  15. data/docs/v2/guides/claude-code-agents.md +262 -0
  16. data/docs/v2/guides/complete-tutorial.md +3088 -0
  17. data/docs/v2/guides/getting-started.md +1456 -0
  18. data/docs/v2/guides/memory-adapters.md +998 -0
  19. data/docs/v2/guides/plugins.md +816 -0
  20. data/docs/v2/guides/quick-start-cli.md +1745 -0
  21. data/docs/v2/guides/rails-integration.md +1902 -0
  22. data/docs/v2/guides/swarm-memory.md +599 -0
  23. data/docs/v2/reference/cli.md +729 -0
  24. data/docs/v2/reference/ruby-dsl.md +2154 -0
  25. data/docs/v2/reference/yaml.md +1835 -0
  26. data/docs-team-swarm.yml +2222 -0
  27. data/examples/learning-assistant/assistant.md +7 -0
  28. data/examples/learning-assistant/example-memories/concept-example.md +90 -0
  29. data/examples/learning-assistant/example-memories/experience-example.md +66 -0
  30. data/examples/learning-assistant/example-memories/fact-example.md +76 -0
  31. data/examples/learning-assistant/example-memories/memory-index.md +78 -0
  32. data/examples/learning-assistant/example-memories/skill-example.md +168 -0
  33. data/examples/learning-assistant/learning_assistant.rb +34 -0
  34. data/examples/learning-assistant/learning_assistant.yml +20 -0
  35. data/examples/v2/dsl/01_basic.rb +44 -0
  36. data/examples/v2/dsl/02_core_parameters.rb +59 -0
  37. data/examples/v2/dsl/03_capabilities.rb +71 -0
  38. data/examples/v2/dsl/04_llm_parameters.rb +56 -0
  39. data/examples/v2/dsl/05_advanced_flags.rb +73 -0
  40. data/examples/v2/dsl/06_permissions.rb +80 -0
  41. data/examples/v2/dsl/07_mcp_server.rb +62 -0
  42. data/examples/v2/dsl/08_swarm_hooks.rb +53 -0
  43. data/examples/v2/dsl/09_agent_hooks.rb +67 -0
  44. data/examples/v2/dsl/10_all_agents_hooks.rb +67 -0
  45. data/examples/v2/dsl/11_delegation.rb +60 -0
  46. data/examples/v2/dsl/12_complete_integration.rb +137 -0
  47. data/examples/v2/file_tools_swarm.yml +102 -0
  48. data/examples/v2/hooks/01_basic_hooks.rb +133 -0
  49. data/examples/v2/hooks/02_usage_tracking.rb +201 -0
  50. data/examples/v2/hooks/03_production_monitoring.rb +429 -0
  51. data/examples/v2/hooks/agent_stop_exit_0.yml +21 -0
  52. data/examples/v2/hooks/agent_stop_exit_1.yml +21 -0
  53. data/examples/v2/hooks/agent_stop_exit_2.yml +26 -0
  54. data/examples/v2/hooks/multiple_hooks_all_pass.yml +37 -0
  55. data/examples/v2/hooks/multiple_hooks_first_fails.yml +37 -0
  56. data/examples/v2/hooks/multiple_hooks_second_fails.yml +37 -0
  57. data/examples/v2/hooks/multiple_hooks_warnings.yml +37 -0
  58. data/examples/v2/hooks/post_tool_use_exit_0.yml +24 -0
  59. data/examples/v2/hooks/post_tool_use_exit_1.yml +24 -0
  60. data/examples/v2/hooks/post_tool_use_exit_2.yml +24 -0
  61. data/examples/v2/hooks/post_tool_use_multi_matcher_exit_0.yml +26 -0
  62. data/examples/v2/hooks/post_tool_use_multi_matcher_exit_1.yml +26 -0
  63. data/examples/v2/hooks/post_tool_use_multi_matcher_exit_2.yml +26 -0
  64. data/examples/v2/hooks/pre_tool_use_exit_0.yml +24 -0
  65. data/examples/v2/hooks/pre_tool_use_exit_1.yml +24 -0
  66. data/examples/v2/hooks/pre_tool_use_exit_2.yml +24 -0
  67. data/examples/v2/hooks/pre_tool_use_multi_matcher_exit_0.yml +26 -0
  68. data/examples/v2/hooks/pre_tool_use_multi_matcher_exit_1.yml +26 -0
  69. data/examples/v2/hooks/pre_tool_use_multi_matcher_exit_2.yml +27 -0
  70. data/examples/v2/hooks/swarm_summary.sh +44 -0
  71. data/examples/v2/hooks/user_prompt_exit_0.yml +21 -0
  72. data/examples/v2/hooks/user_prompt_exit_1.yml +21 -0
  73. data/examples/v2/hooks/user_prompt_exit_2.yml +21 -0
  74. data/examples/v2/hooks/validate_bash.rb +59 -0
  75. data/examples/v2/multi_directory_permissions.yml +221 -0
  76. data/examples/v2/node_context_demo.rb +127 -0
  77. data/examples/v2/node_workflow.rb +173 -0
  78. data/examples/v2/path_resolution_demo.rb +216 -0
  79. data/examples/v2/simple-swarm-v2.rb +90 -0
  80. data/examples/v2/simple-swarm-v2.yml +62 -0
  81. data/examples/v2/swarm.yml +71 -0
  82. data/examples/v2/swarm_with_hooks.yml +61 -0
  83. data/examples/v2/swarm_with_hooks_simple.yml +25 -0
  84. data/examples/v2/think_tool_demo.rb +62 -0
  85. data/exe/swarm +6 -0
  86. data/lib/claude_swarm/claude_mcp_server.rb +0 -6
  87. data/lib/claude_swarm/cli.rb +10 -3
  88. data/lib/claude_swarm/commands/ps.rb +19 -20
  89. data/lib/claude_swarm/commands/show.rb +1 -1
  90. data/lib/claude_swarm/configuration.rb +10 -12
  91. data/lib/claude_swarm/mcp_generator.rb +10 -1
  92. data/lib/claude_swarm/orchestrator.rb +73 -49
  93. data/lib/claude_swarm/system_utils.rb +37 -11
  94. data/lib/claude_swarm/version.rb +1 -1
  95. data/lib/claude_swarm/worktree_manager.rb +1 -0
  96. data/lib/claude_swarm/yaml_loader.rb +22 -0
  97. data/lib/claude_swarm.rb +7 -3
  98. data/lib/swarm_cli/cli.rb +201 -0
  99. data/lib/swarm_cli/command_registry.rb +61 -0
  100. data/lib/swarm_cli/commands/mcp_serve.rb +130 -0
  101. data/lib/swarm_cli/commands/mcp_tools.rb +148 -0
  102. data/lib/swarm_cli/commands/migrate.rb +55 -0
  103. data/lib/swarm_cli/commands/run.rb +173 -0
  104. data/lib/swarm_cli/config_loader.rb +97 -0
  105. data/lib/swarm_cli/formatters/human_formatter.rb +711 -0
  106. data/lib/swarm_cli/formatters/json_formatter.rb +51 -0
  107. data/lib/swarm_cli/interactive_repl.rb +918 -0
  108. data/lib/swarm_cli/mcp_serve_options.rb +44 -0
  109. data/lib/swarm_cli/mcp_tools_options.rb +59 -0
  110. data/lib/swarm_cli/migrate_options.rb +54 -0
  111. data/lib/swarm_cli/migrator.rb +132 -0
  112. data/lib/swarm_cli/options.rb +151 -0
  113. data/lib/swarm_cli/ui/components/agent_badge.rb +33 -0
  114. data/lib/swarm_cli/ui/components/content_block.rb +120 -0
  115. data/lib/swarm_cli/ui/components/divider.rb +57 -0
  116. data/lib/swarm_cli/ui/components/panel.rb +62 -0
  117. data/lib/swarm_cli/ui/components/usage_stats.rb +70 -0
  118. data/lib/swarm_cli/ui/formatters/cost.rb +49 -0
  119. data/lib/swarm_cli/ui/formatters/number.rb +58 -0
  120. data/lib/swarm_cli/ui/formatters/text.rb +77 -0
  121. data/lib/swarm_cli/ui/formatters/time.rb +73 -0
  122. data/lib/swarm_cli/ui/icons.rb +59 -0
  123. data/lib/swarm_cli/ui/renderers/event_renderer.rb +188 -0
  124. data/lib/swarm_cli/ui/state/agent_color_cache.rb +45 -0
  125. data/lib/swarm_cli/ui/state/depth_tracker.rb +40 -0
  126. data/lib/swarm_cli/ui/state/spinner_manager.rb +170 -0
  127. data/lib/swarm_cli/ui/state/usage_tracker.rb +62 -0
  128. data/lib/swarm_cli/version.rb +5 -0
  129. data/lib/swarm_cli.rb +44 -0
  130. data/lib/swarm_memory/adapters/base.rb +141 -0
  131. data/lib/swarm_memory/adapters/filesystem_adapter.rb +845 -0
  132. data/lib/swarm_memory/chat_extension.rb +34 -0
  133. data/lib/swarm_memory/cli/commands.rb +306 -0
  134. data/lib/swarm_memory/core/entry.rb +37 -0
  135. data/lib/swarm_memory/core/frontmatter_parser.rb +108 -0
  136. data/lib/swarm_memory/core/metadata_extractor.rb +68 -0
  137. data/lib/swarm_memory/core/path_normalizer.rb +75 -0
  138. data/lib/swarm_memory/core/semantic_index.rb +244 -0
  139. data/lib/swarm_memory/core/storage.rb +288 -0
  140. data/lib/swarm_memory/core/storage_read_tracker.rb +63 -0
  141. data/lib/swarm_memory/dsl/builder_extension.rb +40 -0
  142. data/lib/swarm_memory/dsl/memory_config.rb +113 -0
  143. data/lib/swarm_memory/embeddings/embedder.rb +36 -0
  144. data/lib/swarm_memory/embeddings/informers_embedder.rb +152 -0
  145. data/lib/swarm_memory/errors.rb +21 -0
  146. data/lib/swarm_memory/integration/cli_registration.rb +30 -0
  147. data/lib/swarm_memory/integration/configuration.rb +43 -0
  148. data/lib/swarm_memory/integration/registration.rb +31 -0
  149. data/lib/swarm_memory/integration/sdk_plugin.rb +531 -0
  150. data/lib/swarm_memory/optimization/analyzer.rb +244 -0
  151. data/lib/swarm_memory/optimization/defragmenter.rb +863 -0
  152. data/lib/swarm_memory/prompts/memory.md.erb +109 -0
  153. data/lib/swarm_memory/prompts/memory_assistant.md.erb +181 -0
  154. data/lib/swarm_memory/prompts/memory_researcher.md.erb +281 -0
  155. data/lib/swarm_memory/prompts/memory_retrieval.md.erb +78 -0
  156. data/lib/swarm_memory/search/semantic_search.rb +112 -0
  157. data/lib/swarm_memory/search/text_search.rb +42 -0
  158. data/lib/swarm_memory/search/text_similarity.rb +80 -0
  159. data/lib/swarm_memory/skills/meta/deep-learning.md +101 -0
  160. data/lib/swarm_memory/skills/meta/deep-learning.yml +14 -0
  161. data/lib/swarm_memory/tools/load_skill.rb +313 -0
  162. data/lib/swarm_memory/tools/memory_defrag.rb +382 -0
  163. data/lib/swarm_memory/tools/memory_delete.rb +99 -0
  164. data/lib/swarm_memory/tools/memory_edit.rb +185 -0
  165. data/lib/swarm_memory/tools/memory_glob.rb +160 -0
  166. data/lib/swarm_memory/tools/memory_grep.rb +247 -0
  167. data/lib/swarm_memory/tools/memory_multi_edit.rb +281 -0
  168. data/lib/swarm_memory/tools/memory_read.rb +123 -0
  169. data/lib/swarm_memory/tools/memory_write.rb +231 -0
  170. data/lib/swarm_memory/utils.rb +50 -0
  171. data/lib/swarm_memory/version.rb +5 -0
  172. data/lib/swarm_memory.rb +166 -0
  173. data/lib/swarm_sdk/agent/RETRY_LOGIC.md +127 -0
  174. data/lib/swarm_sdk/agent/builder.rb +461 -0
  175. data/lib/swarm_sdk/agent/chat/context_tracker.rb +314 -0
  176. data/lib/swarm_sdk/agent/chat/hook_integration.rb +372 -0
  177. data/lib/swarm_sdk/agent/chat/logging_helpers.rb +116 -0
  178. data/lib/swarm_sdk/agent/chat/system_reminder_injector.rb +152 -0
  179. data/lib/swarm_sdk/agent/chat.rb +1159 -0
  180. data/lib/swarm_sdk/agent/context.rb +112 -0
  181. data/lib/swarm_sdk/agent/context_manager.rb +309 -0
  182. data/lib/swarm_sdk/agent/definition.rb +556 -0
  183. data/lib/swarm_sdk/claude_code_agent_adapter.rb +205 -0
  184. data/lib/swarm_sdk/configuration.rb +296 -0
  185. data/lib/swarm_sdk/context_compactor/metrics.rb +147 -0
  186. data/lib/swarm_sdk/context_compactor/token_counter.rb +106 -0
  187. data/lib/swarm_sdk/context_compactor.rb +340 -0
  188. data/lib/swarm_sdk/hooks/adapter.rb +359 -0
  189. data/lib/swarm_sdk/hooks/context.rb +197 -0
  190. data/lib/swarm_sdk/hooks/definition.rb +80 -0
  191. data/lib/swarm_sdk/hooks/error.rb +29 -0
  192. data/lib/swarm_sdk/hooks/executor.rb +146 -0
  193. data/lib/swarm_sdk/hooks/registry.rb +147 -0
  194. data/lib/swarm_sdk/hooks/result.rb +150 -0
  195. data/lib/swarm_sdk/hooks/shell_executor.rb +254 -0
  196. data/lib/swarm_sdk/hooks/tool_call.rb +35 -0
  197. data/lib/swarm_sdk/hooks/tool_result.rb +62 -0
  198. data/lib/swarm_sdk/log_collector.rb +51 -0
  199. data/lib/swarm_sdk/log_stream.rb +69 -0
  200. data/lib/swarm_sdk/markdown_parser.rb +75 -0
  201. data/lib/swarm_sdk/model_aliases.json +5 -0
  202. data/lib/swarm_sdk/models.json +1 -0
  203. data/lib/swarm_sdk/models.rb +120 -0
  204. data/lib/swarm_sdk/node/agent_config.rb +49 -0
  205. data/lib/swarm_sdk/node/builder.rb +439 -0
  206. data/lib/swarm_sdk/node/transformer_executor.rb +248 -0
  207. data/lib/swarm_sdk/node_context.rb +170 -0
  208. data/lib/swarm_sdk/node_orchestrator.rb +384 -0
  209. data/lib/swarm_sdk/permissions/config.rb +239 -0
  210. data/lib/swarm_sdk/permissions/error_formatter.rb +121 -0
  211. data/lib/swarm_sdk/permissions/path_matcher.rb +35 -0
  212. data/lib/swarm_sdk/permissions/validator.rb +173 -0
  213. data/lib/swarm_sdk/permissions_builder.rb +122 -0
  214. data/lib/swarm_sdk/plugin.rb +147 -0
  215. data/lib/swarm_sdk/plugin_registry.rb +101 -0
  216. data/lib/swarm_sdk/prompts/base_system_prompt.md.erb +243 -0
  217. data/lib/swarm_sdk/providers/openai_with_responses.rb +582 -0
  218. data/lib/swarm_sdk/result.rb +97 -0
  219. data/lib/swarm_sdk/swarm/agent_initializer.rb +334 -0
  220. data/lib/swarm_sdk/swarm/all_agents_builder.rb +140 -0
  221. data/lib/swarm_sdk/swarm/builder.rb +586 -0
  222. data/lib/swarm_sdk/swarm/mcp_configurator.rb +151 -0
  223. data/lib/swarm_sdk/swarm/tool_configurator.rb +419 -0
  224. data/lib/swarm_sdk/swarm.rb +982 -0
  225. data/lib/swarm_sdk/tools/bash.rb +274 -0
  226. data/lib/swarm_sdk/tools/clock.rb +44 -0
  227. data/lib/swarm_sdk/tools/delegate.rb +164 -0
  228. data/lib/swarm_sdk/tools/document_converters/base_converter.rb +83 -0
  229. data/lib/swarm_sdk/tools/document_converters/docx_converter.rb +99 -0
  230. data/lib/swarm_sdk/tools/document_converters/html_converter.rb +101 -0
  231. data/lib/swarm_sdk/tools/document_converters/pdf_converter.rb +78 -0
  232. data/lib/swarm_sdk/tools/document_converters/xlsx_converter.rb +194 -0
  233. data/lib/swarm_sdk/tools/edit.rb +150 -0
  234. data/lib/swarm_sdk/tools/glob.rb +158 -0
  235. data/lib/swarm_sdk/tools/grep.rb +228 -0
  236. data/lib/swarm_sdk/tools/image_extractors/docx_image_extractor.rb +43 -0
  237. data/lib/swarm_sdk/tools/image_extractors/pdf_image_extractor.rb +163 -0
  238. data/lib/swarm_sdk/tools/image_formats/tiff_builder.rb +65 -0
  239. data/lib/swarm_sdk/tools/multi_edit.rb +232 -0
  240. data/lib/swarm_sdk/tools/path_resolver.rb +43 -0
  241. data/lib/swarm_sdk/tools/read.rb +251 -0
  242. data/lib/swarm_sdk/tools/registry.rb +93 -0
  243. data/lib/swarm_sdk/tools/scratchpad/scratchpad_list.rb +96 -0
  244. data/lib/swarm_sdk/tools/scratchpad/scratchpad_read.rb +76 -0
  245. data/lib/swarm_sdk/tools/scratchpad/scratchpad_write.rb +91 -0
  246. data/lib/swarm_sdk/tools/stores/read_tracker.rb +61 -0
  247. data/lib/swarm_sdk/tools/stores/scratchpad_storage.rb +224 -0
  248. data/lib/swarm_sdk/tools/stores/storage.rb +148 -0
  249. data/lib/swarm_sdk/tools/stores/todo_manager.rb +65 -0
  250. data/lib/swarm_sdk/tools/think.rb +95 -0
  251. data/lib/swarm_sdk/tools/todo_write.rb +216 -0
  252. data/lib/swarm_sdk/tools/web_fetch.rb +261 -0
  253. data/lib/swarm_sdk/tools/write.rb +117 -0
  254. data/lib/swarm_sdk/utils.rb +50 -0
  255. data/lib/swarm_sdk/version.rb +5 -0
  256. data/lib/swarm_sdk.rb +157 -0
  257. data/llm.v2.txt +13407 -0
  258. data/rubocop/cop/security/no_reflection_methods.rb +47 -0
  259. data/rubocop/cop/security/no_ruby_llm_logger.rb +32 -0
  260. data/swarm_cli.gemspec +57 -0
  261. data/swarm_memory.gemspec +28 -0
  262. data/swarm_sdk.gemspec +41 -0
  263. data/team.yml +1 -1
  264. data/team_full.yml +1875 -0
  265. data/{team_v2.yml → team_sdk.yml} +121 -52
  266. metadata +247 -4
  267. data/EXAMPLES.md +0 -164
@@ -0,0 +1,127 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # NodeContext Demo
5
+ #
6
+ # This example demonstrates the NodeContext capabilities:
7
+ # - Access original_prompt from any node
8
+ # - Access all previous node results
9
+ # - Convenience accessors (ctx.content)
10
+ #
11
+ # Run: ruby examples/node_context_demo.rb
12
+
13
+ require_relative "../lib/swarm_sdk"
14
+
15
+ swarm = SwarmSDK.build do
16
+ name("NodeContext Demo")
17
+
18
+ # Define agents
19
+ agent(:planner) do
20
+ model("claude-sonnet-4-5")
21
+ provider("openai")
22
+ description("Planning agent")
23
+ system_prompt("Create a brief plan.")
24
+ tools(include_default: false)
25
+ end
26
+
27
+ agent(:implementer) do
28
+ model("claude-sonnet-4-5")
29
+ provider("openai")
30
+ description("Implementation agent")
31
+ system_prompt("Implement the plan.")
32
+ tools(include_default: false)
33
+ end
34
+
35
+ agent(:reviewer) do
36
+ model("claude-sonnet-4-5")
37
+ provider("openai")
38
+ description("Review agent")
39
+ system_prompt("Review the work.")
40
+ tools(include_default: false)
41
+ end
42
+
43
+ # Node 1: Planning
44
+ node(:planning) do
45
+ agent(:planner)
46
+
47
+ output do |ctx|
48
+ puts "\n[planning output transformer]"
49
+ puts " ctx.content: #{ctx.content[0..60]}..."
50
+ puts " ctx.original_prompt: #{ctx.original_prompt}"
51
+ puts " ctx.node_name: #{ctx.node_name}"
52
+
53
+ "PLAN: #{ctx.content}"
54
+ end
55
+ end
56
+
57
+ # Node 2: Implementation
58
+ node(:implementation) do
59
+ agent(:implementer)
60
+ depends_on(:planning)
61
+
62
+ input do |ctx|
63
+ puts "\n[implementation input transformer]"
64
+ puts " ctx.content (transformed from planning): #{ctx.content[0..60]}..."
65
+ puts " ctx.original_prompt: #{ctx.original_prompt}"
66
+ puts " ctx.all_results[:planning].content: #{ctx.all_results[:planning].content[0..40]}..."
67
+ puts " ctx.node_name: #{ctx.node_name}"
68
+ puts " ctx.dependencies: #{ctx.dependencies.inspect}"
69
+
70
+ ctx.content
71
+ end
72
+
73
+ output do |ctx|
74
+ "IMPLEMENTATION: #{ctx.content}"
75
+ end
76
+ end
77
+
78
+ # Node 3: Review - demonstrate accessing ALL previous results
79
+ node(:review) do
80
+ agent(:reviewer) # No delegation, just solo review
81
+
82
+ depends_on(:implementation)
83
+
84
+ input do |ctx|
85
+ puts "\n[review input transformer]"
86
+ puts " ctx.original_prompt: #{ctx.original_prompt}"
87
+ puts " ctx.all_results.keys: #{ctx.all_results.keys.inspect}"
88
+
89
+ # Access specific previous nodes
90
+ plan = ctx.all_results[:planning].content
91
+ impl = ctx.all_results[:implementation].content
92
+
93
+ puts " Planning node result: #{plan[0..40]}..."
94
+ puts " Implementation node result: #{impl[0..40]}..."
95
+
96
+ <<~PROMPT
97
+ Review this work:
98
+
99
+ ORIGINAL REQUEST: #{ctx.original_prompt}
100
+
101
+ PLAN:
102
+ #{plan}
103
+
104
+ IMPLEMENTATION:
105
+ #{impl}
106
+
107
+ Provide feedback.
108
+ PROMPT
109
+ end
110
+ end
111
+
112
+ start_node(:planning)
113
+ end
114
+
115
+ puts "=" * 80
116
+ puts "NodeContext Demo"
117
+ puts "=" * 80
118
+ puts "\nExecuting workflow with NodeContext...\n"
119
+
120
+ result = swarm.execute("Build a todo API")
121
+
122
+ puts "\n"
123
+ puts "=" * 80
124
+ puts "Final Result:"
125
+ puts "=" * 80
126
+ puts result.content
127
+ puts "=" * 80
@@ -0,0 +1,173 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Node-Based Workflow Example
5
+ #
6
+ # This example demonstrates how to use nodes to create multi-stage workflows
7
+ # where different teams of agents collaborate in sequence.
8
+ #
9
+ # Features demonstrated:
10
+ # - NodeContext for accessing original_prompt and all_results
11
+ # - Multi-node workflows with delegation
12
+ # - Input/output transformers with full context access
13
+ #
14
+ # Run: ruby examples/node_workflow.rb
15
+
16
+ require_relative "../lib/swarm_sdk"
17
+
18
+ swarm = SwarmSDK.build do
19
+ name("Haiku Workflow")
20
+
21
+ # Define all agents globally
22
+ agent(:planner) do
23
+ model("claude-sonnet-4-5")
24
+ description("Planning agent who breaks down tasks into smaller subtasks")
25
+ provider("openai")
26
+ system_prompt(<<~PROMPT)
27
+ Your job is to break down tasks into smaller subtasks. Extract the intent of the user's prompt and break it down into smaller subtasks.
28
+ Return a list of subtasks.
29
+ PROMPT
30
+ tools(include_default: false)
31
+ end
32
+
33
+ agent(:implementer) do
34
+ model("claude-sonnet-4-5")
35
+ description("Execution agent who executes the subtasks given to them")
36
+ provider("openai")
37
+ system_prompt(<<~PROMPT)
38
+ Your job is to execute the subtasks given to you.
39
+ PROMPT
40
+ tools(include_default: false)
41
+ end
42
+
43
+ agent(:verifier) do
44
+ model("claude-sonnet-4-5")
45
+ description("Verifier agent who verifies the implementation")
46
+ provider("openai")
47
+ system_prompt(<<~PROMPT)
48
+ Your job is to verify work given to you and return a summary of your findings
49
+ PROMPT
50
+ tools(include_default: false)
51
+ end
52
+
53
+ # Stage 1: Planning
54
+ node(:planning) do
55
+ # Input transformer - ctx.content is the initial prompt
56
+ input do |ctx|
57
+ <<~PROMPT
58
+ Please break down the following prompt into smaller subtasks:
59
+
60
+ #{ctx.content}
61
+ PROMPT
62
+ end
63
+
64
+ agent(:planner)
65
+
66
+ # Output transformer - ctx has access to original prompt and results
67
+ output do |ctx|
68
+ <<~PROMPT
69
+ Here are the subtasks:
70
+
71
+ #{ctx.content}
72
+
73
+ Please implement these subtasks.
74
+ PROMPT
75
+ end
76
+ end
77
+
78
+ # Stage 2: Implementation
79
+ node(:implementation) do
80
+ # verifier is auto-added (mentioned in delegates_to)
81
+ agent(:implementer).delegates_to(:verifier)
82
+
83
+ depends_on(:planning)
84
+
85
+ # Demonstrate NodeContext in input transformer
86
+ input do |ctx|
87
+ puts "\n[Node: implementation]"
88
+ puts " Original prompt: '#{ctx.original_prompt}'"
89
+ puts " Planning result: '#{ctx.all_results[:planning].content[0..60]}...'"
90
+ puts " Transformed input: '#{ctx.content[0..60]}...'\n"
91
+
92
+ ctx.content # Use transformed content from planning output
93
+ end
94
+
95
+ # Transform output for review stage
96
+ output do |ctx|
97
+ <<~PROMPT
98
+ Here is the implementation:
99
+
100
+ #{ctx.content}
101
+
102
+ Please review this implementation against the original plan.
103
+ PROMPT
104
+ end
105
+ end
106
+
107
+ # Stage 3: Review
108
+ node(:review) do
109
+ agent(:verifier)
110
+
111
+ depends_on(:implementation)
112
+
113
+ # Demonstrate full NodeContext capabilities - access ALL previous results
114
+ input do |ctx|
115
+ # Access original prompt
116
+ original = ctx.original_prompt
117
+
118
+ # Access specific previous node results via all_results
119
+ plan = ctx.all_results[:planning].content
120
+ implementation = ctx.all_results[:implementation].content
121
+
122
+ # Current (transformed) content from implementation output
123
+ transformed = ctx.content
124
+
125
+ puts "\n[Node: review]"
126
+ puts " Accessing via NodeContext:"
127
+ puts " - Original prompt: '#{original}'"
128
+ puts " - Planning result: '#{plan[0..50]}...'"
129
+ puts " - Implementation result: '#{implementation[0..50]}...'"
130
+ puts " - Transformed input: '#{transformed[0..50]}...'\n"
131
+
132
+ <<~PROMPT
133
+ Review the implementation against the original plan:
134
+
135
+ ORIGINAL REQUEST: #{original}
136
+
137
+ PLAN:
138
+ #{plan}
139
+
140
+ IMPLEMENTATION:
141
+ #{implementation}
142
+
143
+ Provide feedback on whether this follows the plan and suggest improvements.
144
+ PROMPT
145
+ end
146
+ end
147
+
148
+ start_node(:planning)
149
+ end
150
+
151
+ puts "=" * 80
152
+ puts "Node-Based Workflow Example"
153
+ puts "=" * 80
154
+ puts
155
+ puts "This swarm has 3 stages:"
156
+ puts "1. Planning - Break down the task"
157
+ puts "2. Implementation - Execute the subtasks"
158
+ puts "3. Review - Verify the work"
159
+ puts
160
+ puts "=" * 80
161
+ puts
162
+
163
+ # Execute the workflow
164
+ result = swarm.execute("Write a haiku about the weather") do |log|
165
+ puts log.to_json
166
+ end
167
+
168
+ puts "\n"
169
+ puts "=" * 80
170
+ puts "Final Result:"
171
+ puts "=" * 80
172
+ puts result.content
173
+ puts "=" * 80
@@ -0,0 +1,216 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Path Resolution Demo
5
+ #
6
+ # Demonstrates how SwarmSDK resolves file paths relative to agent directories.
7
+ # This is a CRITICAL feature introduced in v1.0 that ensures agents operate
8
+ # in their configured directory, not Dir.pwd.
9
+ #
10
+ # Key Concepts:
11
+ # 1. Each agent has a `directory` (singular) configuration
12
+ # 2. Relative paths in file tools are resolved against this directory
13
+ # 3. Absolute paths are used as-is
14
+ # 4. This is fiber-safe (no reliance on Dir.pwd)
15
+ #
16
+ # Run: bundle exec ruby -Ilib lib/swarm_sdk/examples/path_resolution_demo.rb
17
+
18
+ require "swarm_sdk"
19
+ require "fileutils"
20
+ require "tmpdir"
21
+
22
+ ENV["OPENAI_API_KEY"] = "test-key"
23
+
24
+ # Create a test directory structure for demonstration
25
+ demo_root = File.join(Dir.tmpdir, "swarm_path_demo_#{Process.pid}")
26
+ FileUtils.mkdir_p(demo_root)
27
+
28
+ # Create subdirectories
29
+ frontend_dir = File.join(demo_root, "frontend")
30
+ backend_dir = File.join(demo_root, "backend")
31
+ shared_dir = File.join(demo_root, "shared")
32
+
33
+ FileUtils.mkdir_p([frontend_dir, backend_dir, shared_dir])
34
+
35
+ # Create test files
36
+ File.write(File.join(frontend_dir, "index.html"), "<html><body>Frontend</body></html>")
37
+ File.write(File.join(backend_dir, "server.rb"), "puts 'Backend server'")
38
+ File.write(File.join(shared_dir, "config.yml"), "shared: true")
39
+ File.write(File.join(demo_root, "README.md"), "# Project Root")
40
+
41
+ puts "=" * 80
42
+ puts "PATH RESOLUTION DEMO"
43
+ puts "=" * 80
44
+ puts ""
45
+ puts "Test directory structure created at: #{demo_root}"
46
+ puts ""
47
+ puts "Directory structure:"
48
+ puts " #{demo_root}/"
49
+ puts " ├── README.md"
50
+ puts " ├── frontend/"
51
+ puts " │ └── index.html"
52
+ puts " ├── backend/"
53
+ puts " │ └── server.rb"
54
+ puts " └── shared/"
55
+ puts " └── config.yml"
56
+ puts ""
57
+ puts "=" * 80
58
+ puts ""
59
+
60
+ # Build a swarm with agents in different directories
61
+ swarm = SwarmSDK.build do
62
+ name("Path Resolution Demo Swarm")
63
+ lead(:coordinator)
64
+
65
+ # Coordinator works in project root
66
+ agent(:coordinator) do
67
+ description("Coordinator working in project root")
68
+ model("gpt-5-nano")
69
+ provider("openai")
70
+
71
+ # This agent's directory is the project root
72
+ directory(demo_root)
73
+
74
+ tools(:Read, :Write, :Glob)
75
+ delegates_to(:frontend_agent, :backend_agent)
76
+
77
+ system_prompt(<<~PROMPT)
78
+ You demonstrate path resolution behavior in SwarmSDK.
79
+
80
+ Your working directory is: #{demo_root}
81
+
82
+ When you use file tools:
83
+ - Relative paths like "README.md" resolve to #{File.join(demo_root, "README.md")}
84
+ - Relative paths like "frontend/index.html" resolve to #{File.join(demo_root, "frontend/index.html")}
85
+ - Absolute paths like "/tmp/test.txt" are used as-is
86
+
87
+ Demonstrate this by:
88
+ 1. Reading "README.md" (relative path)
89
+ 2. Listing files with Glob("*") (relative pattern)
90
+ 3. Trying to access files in subdirectories
91
+ PROMPT
92
+ end
93
+
94
+ # Frontend agent works in frontend/ directory
95
+ agent(:frontend_agent) do
96
+ description("Frontend agent working in frontend/ directory")
97
+ model("gpt-5-nano")
98
+ provider("openai")
99
+
100
+ # This agent's directory is frontend/
101
+ directory(frontend_dir)
102
+
103
+ tools(:Read, :Write, :Glob)
104
+
105
+ system_prompt(<<~PROMPT)
106
+ You are a frontend agent working in: #{frontend_dir}
107
+
108
+ Path resolution for your tools:
109
+ - Relative path "index.html" → #{File.join(frontend_dir, "index.html")}
110
+ - Relative path "../shared/config.yml" → #{File.join(demo_root, "shared/config.yml")}
111
+ - Absolute paths are used as-is
112
+
113
+ When asked to demonstrate:
114
+ 1. Read "index.html" (relative path in your directory)
115
+ 2. Try to read "../shared/config.yml" (relative path to parent)
116
+ 3. List files with Glob("*.html") (relative pattern)
117
+ PROMPT
118
+ end
119
+
120
+ # Backend agent works in backend/ directory
121
+ agent(:backend_agent) do
122
+ description("Backend agent working in backend/ directory")
123
+ model("gpt-5-nano")
124
+ provider("openai")
125
+
126
+ # This agent's directory is backend/
127
+ directory(backend_dir)
128
+
129
+ tools(:Read, :Write, :Glob)
130
+
131
+ system_prompt(<<~PROMPT)
132
+ You are a backend agent working in: #{backend_dir}
133
+
134
+ Path resolution for your tools:
135
+ - Relative path "server.rb" → #{File.join(backend_dir, "server.rb")}
136
+ - Relative path "../README.md" → #{File.join(demo_root, "README.md")}
137
+ - Absolute paths are used as-is
138
+
139
+ When asked to demonstrate:
140
+ 1. Read "server.rb" (relative path in your directory)
141
+ 2. Try to read "../README.md" (relative path to parent)
142
+ 3. List files with Glob("*.rb") (relative pattern)
143
+ PROMPT
144
+ end
145
+ end
146
+
147
+ puts "✅ Swarm created with 3 agents in different directories"
148
+ puts ""
149
+ puts "Agent Directories:"
150
+ puts " coordinator → #{demo_root}"
151
+ puts " frontend_agent → #{frontend_dir}"
152
+ puts " backend_agent → #{backend_dir}"
153
+ puts ""
154
+ puts "=" * 80
155
+ puts ""
156
+
157
+ # Verify agent configurations
158
+ puts "AGENT CONFIGURATIONS:"
159
+ puts "-" * 80
160
+ swarm.agent_names.each do |agent_name|
161
+ agent_def = swarm.agent_definition(agent_name)
162
+ puts "#{agent_name}:"
163
+ puts " directory: #{agent_def.directory}"
164
+ puts " tools: #{agent_def.tools.map { |t| t[:name] }.join(", ")}"
165
+ puts ""
166
+ end
167
+
168
+ puts "PATH RESOLUTION EXAMPLES:"
169
+ puts "-" * 80
170
+ puts ""
171
+ puts "Coordinator (directory: #{demo_root}):"
172
+ puts " 'README.md' → #{File.join(demo_root, "README.md")}"
173
+ puts " 'frontend/index.html' → #{File.join(demo_root, "frontend/index.html")}"
174
+ puts ""
175
+ puts "Frontend Agent (directory: #{frontend_dir}):"
176
+ puts " 'index.html' → #{File.join(frontend_dir, "index.html")}"
177
+ puts " '../shared/config.yml' → #{File.join(demo_root, "shared/config.yml")}"
178
+ puts " '../README.md' → #{File.join(demo_root, "README.md")}"
179
+ puts ""
180
+ puts "Backend Agent (directory: #{backend_dir}):"
181
+ puts " 'server.rb' → #{File.join(backend_dir, "server.rb")}"
182
+ puts " '../shared/config.yml' → #{File.join(demo_root, "shared/config.yml")}"
183
+ puts " '../README.md' → #{File.join(demo_root, "README.md")}"
184
+ puts ""
185
+
186
+ # Uncomment below to test with actual LLM calls (requires API key and time)
187
+ # puts "LIVE TESTS (uncomment to run):"
188
+ # puts "-" * 80
189
+ # result = swarm.execute("Read the file 'README.md' and tell me what it contains.")
190
+ # puts "Result: #{result.content}"
191
+ # puts ""
192
+
193
+ puts "=" * 80
194
+ puts "KEY TAKEAWAYS"
195
+ puts "=" * 80
196
+ puts ""
197
+ puts "1. Each agent has ONE directory (singular, not plural)"
198
+ puts "2. Relative paths are resolved against the agent's directory"
199
+ puts "3. Absolute paths are used as-is"
200
+ puts "4. Agents can access parent/sibling dirs via '../' relative paths"
201
+ puts "5. This is fiber-safe and doesn't rely on Dir.pwd"
202
+ puts ""
203
+ puts "MIGRATION NOTE:"
204
+ puts " OLD (v0.x): directories: ['.', 'lib/', 'test/'] # Multiple dirs"
205
+ puts " NEW (v1.0): directory: 'lib/' # Single dir"
206
+ puts ""
207
+ puts "For multi-directory access, use permissions:"
208
+ puts " directory: 'lib/'"
209
+ puts " permissions:"
210
+ puts " Read:"
211
+ puts " allowed_paths: ['../test/**']"
212
+ puts ""
213
+
214
+ # Cleanup
215
+ FileUtils.rm_rf(demo_root)
216
+ puts "✅ Demo complete! Test directory cleaned up."
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Ruby DSL version of simple-swarm-v2.yml
4
+ #
5
+ # This demonstrates how to define the same swarm using Ruby's programmatic DSL
6
+ # instead of YAML. The Ruby DSL provides more flexibility and allows for
7
+ # dynamic configuration, conditionals, and Ruby language features.
8
+ #
9
+ # Usage:
10
+ # swarm run examples/v2/simple-swarm-v2.rb
11
+ # swarm run examples/v2/simple-swarm-v2.rb "Build a user authentication system"
12
+ # swarm run examples/v2/simple-swarm-v2.rb -p "Create a REST API for products"
13
+
14
+ SwarmSDK.build do
15
+ name "Full-Stack Development Team"
16
+ lead :architect
17
+
18
+ # Lead architect who coordinates the team
19
+ agent :architect do
20
+ coding_agent(true)
21
+ description "Lead architect who coordinates the development team"
22
+ model "gpt-5-mini"
23
+ provider "openai"
24
+
25
+ system_prompt <<~PROMPT
26
+ You are the lead architect coordinating a development team. You have access to:
27
+ - frontend_dev: Specializes in React and UI/UX
28
+ - backend_dev: Specializes in APIs and databases
29
+ - qa_engineer: Handles testing and code review
30
+
31
+ When given a task, break it down and delegate appropriately. Frontend work goes
32
+ to frontend_dev, backend work to backend_dev. Always have qa_engineer review
33
+ the final implementation.
34
+ For maximum efficiency, whenever you need to perform multiple independent operations, invoke all relevant tools simultaneously rather than sequentially.
35
+ PROMPT
36
+
37
+ delegates_to :frontend_dev, :backend_dev, :qa_engineer
38
+ end
39
+
40
+ # Frontend specialist
41
+ agent :frontend_dev do
42
+ coding_agent(true)
43
+ description "Frontend developer specializing in React and UI/UX"
44
+ model "anthropic:claude-sonnet-4-5"
45
+ provider "openai"
46
+ system_prompt <<~PROMPT
47
+ You are a frontend developer specializing in React and modern UI/UX.
48
+ Focus on component design, user experience, and responsive layouts.
49
+ When you complete work, you can delegate to qa_engineer for review.
50
+ For maximum efficiency, whenever you need to perform multiple independent operations, invoke all relevant tools simultaneously rather than sequentially.
51
+ PROMPT
52
+
53
+ delegates_to :qa_engineer
54
+ end
55
+
56
+ # Backend specialist
57
+ agent :backend_dev do
58
+ coding_agent(true)
59
+ description "Backend developer specializing in APIs and databases"
60
+ model "anthropic:claude-sonnet-4-5"
61
+ provider "openai"
62
+
63
+ system_prompt <<~PROMPT
64
+ You are a backend developer specializing in REST APIs, databases, and
65
+ server-side logic. Focus on scalability, security, and clean architecture.
66
+ When you complete work, you can delegate to qa_engineer for review.
67
+ For maximum efficiency, whenever you need to perform multiple independent operations, invoke all relevant tools simultaneously rather than sequentially.
68
+ PROMPT
69
+
70
+ delegates_to :qa_engineer
71
+ end
72
+
73
+ # QA engineer
74
+ agent :qa_engineer do
75
+ coding_agent(true)
76
+ description "QA engineer who reviews code and creates test plans"
77
+ model "gpt-5-mini"
78
+ provider "openai"
79
+
80
+ system_prompt <<~PROMPT
81
+ You are a QA engineer responsible for code review and test planning.
82
+ Review implementations for bugs, edge cases, and potential issues.
83
+ Suggest improvements and create comprehensive test plans.
84
+ Be thorough but constructive in your feedback.
85
+ For maximum efficiency, whenever you need to perform multiple independent operations, invoke all relevant tools simultaneously rather than sequentially.
86
+ PROMPT
87
+
88
+ delegates_to # No delegations
89
+ end
90
+ end
@@ -0,0 +1,62 @@
1
+ version: 2
2
+ swarm:
3
+ name: "Full-Stack Development Team"
4
+ lead: architect
5
+ agents:
6
+ architect:
7
+ description: "Lead architect who coordinates the development team"
8
+ model: gpt-5-mini
9
+ provider: openai
10
+ system_prompt: |
11
+ You are the lead architect coordinating a development team. You have access to:
12
+ - frontend_dev: Specializes in React and UI/UX
13
+ - backend_dev: Specializes in APIs and databases
14
+ - qa_engineer: Handles testing and code review
15
+
16
+ When given a task, break it down and delegate appropriately. Frontend work goes
17
+ to frontend_dev, backend work to backend_dev. Always have qa_engineer review
18
+ the final implementation.
19
+ For maximum efficiency, whenever you need to perform multiple independent operations, invoke all relevant tools simultaneously rather than sequentially.
20
+ tools: []
21
+ delegates_to: [frontend_dev, backend_dev, qa_engineer]
22
+ directory: .
23
+
24
+ frontend_dev:
25
+ description: "Frontend developer specializing in React and UI/UX"
26
+ model: anthropic:claude-sonnet-4-5
27
+ provider: openai
28
+ system_prompt: |
29
+ You are a frontend developer specializing in React and modern UI/UX.
30
+ Focus on component design, user experience, and responsive layouts.
31
+ When you complete work, you can delegate to qa_engineer for review.
32
+ For maximum efficiency, whenever you need to perform multiple independent operations, invoke all relevant tools simultaneously rather than sequentially.
33
+ tools: []
34
+ delegates_to: [qa_engineer]
35
+ directory: .
36
+
37
+ backend_dev:
38
+ description: "Backend developer specializing in APIs and databases"
39
+ model: anthropic:claude-sonnet-4-5
40
+ provider: openai
41
+ system_prompt: |
42
+ You are a backend developer specializing in REST APIs, databases, and
43
+ server-side logic. Focus on scalability, security, and clean architecture.
44
+ When you complete work, you can delegate to qa_engineer for review.
45
+ For maximum efficiency, whenever you need to perform multiple independent operations, invoke all relevant tools simultaneously rather than sequentially.
46
+ tools: []
47
+ delegates_to: [qa_engineer]
48
+ directory: .
49
+
50
+ qa_engineer:
51
+ description: "QA engineer who reviews code and creates test plans"
52
+ model: gpt-5-mini
53
+ provider: openai
54
+ system_prompt: |
55
+ You are a QA engineer responsible for code review and test planning.
56
+ Review implementations for bugs, edge cases, and potential issues.
57
+ Suggest improvements and create comprehensive test plans.
58
+ Be thorough but constructive in your feedback.
59
+ For maximum efficiency, whenever you need to perform multiple independent operations, invoke all relevant tools simultaneously rather than sequentially.
60
+ tools: []
61
+ delegates_to: []
62
+ directory: .