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,113 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SwarmMemory
4
+ module DSL
5
+ # Memory configuration for agents
6
+ #
7
+ # This class is injected into SwarmSDK when swarm_memory is required,
8
+ # allowing agents to configure memory via the DSL.
9
+ #
10
+ # Supports custom adapters through options hash that gets passed through
11
+ # to the adapter constructor.
12
+ #
13
+ # @example Filesystem adapter
14
+ # memory do
15
+ # adapter :filesystem
16
+ # directory ".swarm/memory"
17
+ # end
18
+ #
19
+ # @example Custom adapter
20
+ # memory do
21
+ # adapter :activerecord
22
+ # option :namespace, "my_agent"
23
+ # option :table_name, "memory_entries"
24
+ # end
25
+ class MemoryConfig
26
+ attr_reader :adapter_type, :adapter_options
27
+
28
+ def initialize
29
+ @adapter_type = :filesystem # Default adapter
30
+ @adapter_options = {} # Options passed to adapter constructor
31
+ @mode = :assistant # Default mode
32
+ end
33
+
34
+ # DSL method to set/get adapter type
35
+ #
36
+ # @param value [Symbol, nil] Adapter type
37
+ # @return [Symbol] Current adapter
38
+ def adapter(value = nil)
39
+ return @adapter_type if value.nil?
40
+
41
+ @adapter_type = value.to_sym
42
+ end
43
+
44
+ # DSL method to set adapter option (generic)
45
+ #
46
+ # This allows passing any option to the adapter constructor.
47
+ #
48
+ # @param key [Symbol] Option key
49
+ # @param value [Object] Option value
50
+ #
51
+ # @example
52
+ # option :namespace, "my_agent"
53
+ # option :connection_pool_size, 5
54
+ def option(key, value)
55
+ @adapter_options[key.to_sym] = value
56
+ end
57
+
58
+ # DSL method to set/get directory (convenience for filesystem adapter)
59
+ #
60
+ # Equivalent to: option :directory, value
61
+ #
62
+ # @param value [String, nil] Memory directory path
63
+ # @return [String] Current directory
64
+ def directory(value = nil)
65
+ if value.nil?
66
+ @adapter_options[:directory]
67
+ else
68
+ @adapter_options[:directory] = value
69
+ end
70
+ end
71
+
72
+ # DSL method to set/get mode
73
+ #
74
+ # Modes:
75
+ # - :assistant (default) - Read + Write, balanced for learning and retrieval
76
+ # - :retrieval - Read-only, optimized for Q&A
77
+ # - :researcher - All tools, optimized for knowledge extraction
78
+ #
79
+ # @param value [Symbol, nil] Memory mode
80
+ # @return [Symbol] Current mode
81
+ def mode(value = nil)
82
+ return @mode if value.nil?
83
+
84
+ @mode = value.to_sym
85
+ end
86
+
87
+ # Check if memory is enabled
88
+ #
89
+ # @return [Boolean] True if adapter is configured with required options
90
+ def enabled?
91
+ case @adapter_type
92
+ when :filesystem
93
+ !@adapter_options[:directory].nil?
94
+ else
95
+ # For custom adapters, assume enabled if adapter is set
96
+ # Custom adapter will validate its own requirements
97
+ true
98
+ end
99
+ end
100
+
101
+ # Convert config to hash (for SDK plugin)
102
+ #
103
+ # @return [Hash] Configuration as hash
104
+ def to_h
105
+ {
106
+ adapter: @adapter_type,
107
+ mode: @mode,
108
+ **@adapter_options,
109
+ }
110
+ end
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SwarmMemory
4
+ module Embeddings
5
+ # Abstract embedder interface
6
+ #
7
+ # Subclasses implement different embedding providers
8
+ # (Informers, OpenAI API, etc.)
9
+ class Embedder
10
+ # Generate embedding for single text
11
+ #
12
+ # @param text [String] Text to embed
13
+ # @return [Array<Float>] Embedding vector
14
+ # @raise [EmbeddingError] If embedding generation fails
15
+ def embed(text)
16
+ raise NotImplementedError, "Subclass must implement #embed"
17
+ end
18
+
19
+ # Generate embeddings for multiple texts (batched)
20
+ #
21
+ # @param texts [Array<String>] Texts to embed
22
+ # @return [Array<Array<Float>>] Array of embedding vectors
23
+ # @raise [EmbeddingError] If embedding generation fails
24
+ def embed_batch(texts)
25
+ raise NotImplementedError, "Subclass must implement #embed_batch"
26
+ end
27
+
28
+ # Get embedding dimensionality
29
+ #
30
+ # @return [Integer] Vector dimensions
31
+ def dimensions
32
+ raise NotImplementedError, "Subclass must implement #dimensions"
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,152 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SwarmMemory
4
+ module Embeddings
5
+ # Embedder implementation using Informers gem (fast ONNX inference)
6
+ #
7
+ # Uses sentence-transformers models via ONNX for fast, local embedding generation.
8
+ # Supports quantized models for even better performance.
9
+ #
10
+ # @example
11
+ # embedder = InformersEmbedder.new
12
+ # vector = embedder.embed("This is a test sentence")
13
+ # vector.size # => 384
14
+ class InformersEmbedder < Embedder
15
+ DEFAULT_MODEL = "sentence-transformers/multi-qa-MiniLM-L6-cos-v1"
16
+ EMBEDDING_DIMENSIONS = 384
17
+
18
+ # Initialize embedder with model configuration
19
+ #
20
+ # Model can be configured via SWARM_MEMORY_EMBEDDING_MODEL environment variable.
21
+ #
22
+ # Available models:
23
+ # - sentence-transformers/all-MiniLM-L6-v2 (default, general purpose, 256 tokens)
24
+ # - sentence-transformers/multi-qa-MiniLM-L6-cos-v1 (Q&A optimized, 512 tokens)
25
+ #
26
+ # @param model [String, nil] HuggingFace model identifier (defaults to env var or DEFAULT_MODEL)
27
+ # @param quantized [Boolean] Use quantized variant (default: false for original model)
28
+ # @param cache_dir [String, nil] Optional custom cache directory
29
+ # @raise [EmbeddingError] If Informers gem is not available
30
+ #
31
+ # Note: The original sentence-transformers model uses unquantized ONNX (90MB).
32
+ # For a smaller quantized version (22MB), use model: "Xenova/all-MiniLM-L6-v2", quantized: true
33
+ def initialize(model: nil, quantized: false, cache_dir: nil)
34
+ super()
35
+
36
+ unless defined?(Informers)
37
+ raise EmbeddingError,
38
+ "Informers gem is not available. Install with: gem install informers"
39
+ end
40
+
41
+ # Use env var if available, otherwise use provided model or default
42
+ @model_name = model || ENV["SWARM_MEMORY_EMBEDDING_MODEL"] || DEFAULT_MODEL
43
+ @quantized = quantized
44
+ @model = nil # Lazy load
45
+
46
+ # Optional: Set custom cache directory
47
+ Informers.cache_dir = cache_dir if cache_dir
48
+ end
49
+
50
+ # Explicitly pre-load the model (triggers download if not cached)
51
+ #
52
+ # Call this during initialization to download the model immediately
53
+ # rather than waiting for the first embedding call.
54
+ #
55
+ # @return [self]
56
+ #
57
+ # @example
58
+ # embedder = InformersEmbedder.new
59
+ # embedder.preload! # Downloads ~80MB model on first call
60
+ # embedder.embed("text") # No download wait
61
+ def preload!
62
+ ensure_model_loaded
63
+ self
64
+ end
65
+
66
+ # Check if model is already cached locally
67
+ #
68
+ # @return [Boolean] True if model files exist in cache
69
+ #
70
+ # @example
71
+ # embedder = InformersEmbedder.new
72
+ # if embedder.cached?
73
+ # puts "Ready to use!"
74
+ # else
75
+ # puts "Will download on first use (~80MB)"
76
+ # end
77
+ def cached?
78
+ cache_dir = Informers.cache_dir
79
+
80
+ # Different models have different file names
81
+ # Original sentence-transformers: model.onnx (unquantized)
82
+ # Xenova version: model_quantized.onnx (quantized)
83
+ suffix = @quantized ? "_quantized" : ""
84
+
85
+ # Check for required model files
86
+ model_file = File.join(cache_dir, @model_name, "onnx", "model#{suffix}.onnx")
87
+ tokenizer_file = File.join(cache_dir, @model_name, "tokenizer.json")
88
+
89
+ File.exist?(model_file) && File.exist?(tokenizer_file)
90
+ end
91
+
92
+ # Generate embedding for single text
93
+ #
94
+ # @param text [String] Text to embed
95
+ # @return [Array<Float>] 384-dimensional embedding vector
96
+ # @raise [EmbeddingError] If embedding generation fails
97
+ def embed(text)
98
+ raise ArgumentError, "text is required" if text.nil? || text.to_s.strip.empty?
99
+
100
+ begin
101
+ ensure_model_loaded
102
+ # Informers handles single strings directly - returns single embedding array
103
+ @model.call(text)
104
+ rescue StandardError => e
105
+ raise EmbeddingError, "Failed to generate embedding: #{e.message}"
106
+ end
107
+ end
108
+
109
+ # Generate embeddings for multiple texts (batched)
110
+ #
111
+ # @param texts [Array<String>] Texts to embed
112
+ # @return [Array<Array<Float>>] Array of embedding vectors
113
+ # @raise [EmbeddingError] If embedding generation fails
114
+ def embed_batch(texts)
115
+ raise ArgumentError, "texts must be an array" unless texts.is_a?(Array)
116
+ raise ArgumentError, "texts cannot be empty" if texts.empty?
117
+
118
+ begin
119
+ ensure_model_loaded
120
+ # Batch call - returns array of embedding arrays
121
+ @model.call(texts)
122
+ rescue StandardError => e
123
+ raise EmbeddingError, "Failed to generate embeddings: #{e.message}"
124
+ end
125
+ end
126
+
127
+ # Get embedding dimensionality
128
+ #
129
+ # @return [Integer] Vector dimensions (384 for all-MiniLM-L6-v2)
130
+ def dimensions
131
+ EMBEDDING_DIMENSIONS
132
+ end
133
+
134
+ private
135
+
136
+ # Lazy load the Informers model
137
+ #
138
+ # @return [void]
139
+ def ensure_model_loaded
140
+ return if @model
141
+
142
+ @model = Informers.pipeline(
143
+ "embedding",
144
+ @model_name,
145
+ quantized: @quantized,
146
+ )
147
+ rescue StandardError => e
148
+ raise EmbeddingError, "Failed to load embedding model '#{@model_name}': #{e.message}"
149
+ end
150
+ end
151
+ end
152
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SwarmMemory
4
+ # Base error class for SwarmMemory
5
+ class Error < StandardError; end
6
+
7
+ # Configuration errors
8
+ class ConfigurationError < Error; end
9
+
10
+ # Storage operation errors
11
+ class StorageError < Error; end
12
+
13
+ # Adapter-specific errors
14
+ class AdapterError < Error; end
15
+
16
+ # Search operation errors
17
+ class SearchError < Error; end
18
+
19
+ # Embedding generation errors
20
+ class EmbeddingError < Error; end
21
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SwarmMemory
4
+ module Integration
5
+ # Auto-registration for SwarmCLI commands
6
+ #
7
+ # Registers memory management commands with SwarmCLI when available.
8
+ class CliRegistration
9
+ class << self
10
+ # Register memory CLI commands with SwarmCLI
11
+ #
12
+ # This is called automatically when swarm_memory is required.
13
+ #
14
+ # @return [void]
15
+ def register!
16
+ # Only register if SwarmCLI is present
17
+ return unless defined?(SwarmCLI)
18
+
19
+ # Load CLI commands explicitly (Zeitwerk might not have loaded it yet)
20
+ require_relative "../cli/commands"
21
+
22
+ # Register memory command
23
+ SwarmCLI::CommandRegistry.register(:memory, SwarmMemory::CLI::Commands)
24
+ rescue StandardError => e
25
+ warn("Warning: Failed to register SwarmMemory CLI commands: #{e.message}")
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SwarmMemory
4
+ module Integration
5
+ # Configuration for agent memory
6
+ #
7
+ # Used by SwarmSDK to configure memory settings for agents.
8
+ # This mirrors the MemoryConfig in SwarmSDK but lives in SwarmMemory.
9
+ class Configuration
10
+ def initialize
11
+ @adapter = :filesystem
12
+ @directory = nil
13
+ end
14
+
15
+ # DSL method to set/get adapter
16
+ #
17
+ # @param value [Symbol, String, nil] Adapter type (:filesystem, :redis, etc.)
18
+ # @return [Symbol] Current adapter
19
+ def adapter(value = nil)
20
+ return @adapter if value.nil?
21
+
22
+ @adapter = value.to_sym
23
+ end
24
+
25
+ # DSL method to set/get directory
26
+ #
27
+ # @param value [String, nil] Directory path for storage
28
+ # @return [String, nil] Current directory
29
+ def directory(value = nil)
30
+ return @directory if value.nil?
31
+
32
+ @directory = value
33
+ end
34
+
35
+ # Check if memory is enabled
36
+ #
37
+ # @return [Boolean] True if directory is set
38
+ def enabled?
39
+ !@directory.nil?
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SwarmMemory
4
+ module Integration
5
+ # Auto-registration with SwarmSDK
6
+ #
7
+ # Registers SwarmMemory plugin with SwarmSDK when the swarm_memory gem is loaded.
8
+ # This enables SwarmSDK to automatically use SwarmMemory features.
9
+ class Registration
10
+ class << self
11
+ # Register SwarmMemory plugin with SwarmSDK
12
+ #
13
+ # This is called automatically when swarm_memory is required.
14
+ # It registers the plugin so SwarmSDK can provide memory tools and storage.
15
+ #
16
+ # @return [void]
17
+ def register!
18
+ # Only register if SwarmSDK is present
19
+ return unless defined?(SwarmSDK)
20
+ return unless defined?(SwarmSDK::PluginRegistry)
21
+
22
+ # Register plugin with SwarmSDK
23
+ plugin = SDKPlugin.new
24
+ SwarmSDK::PluginRegistry.register(plugin)
25
+ rescue StandardError => e
26
+ warn("Warning: Failed to register SwarmMemory plugin with SwarmSDK: #{e.message}")
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end