swarm_sdk 2.7.13 → 3.0.0.alpha1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (183) hide show
  1. checksums.yaml +4 -4
  2. data/lib/swarm_sdk/ruby_llm_patches/chat_callbacks_patch.rb +43 -22
  3. data/lib/swarm_sdk/ruby_llm_patches/init.rb +6 -0
  4. data/lib/swarm_sdk/ruby_llm_patches/mcp_ssl_patch.rb +144 -0
  5. data/lib/swarm_sdk/ruby_llm_patches/tool_concurrency_patch.rb +3 -4
  6. data/lib/swarm_sdk/v3/agent.rb +1165 -0
  7. data/lib/swarm_sdk/v3/agent_builder.rb +533 -0
  8. data/lib/swarm_sdk/v3/agent_definition.rb +330 -0
  9. data/lib/swarm_sdk/v3/configuration.rb +490 -0
  10. data/lib/swarm_sdk/v3/debug_log.rb +86 -0
  11. data/lib/swarm_sdk/v3/event_stream.rb +130 -0
  12. data/lib/swarm_sdk/v3/hooks/context.rb +112 -0
  13. data/lib/swarm_sdk/v3/hooks/result.rb +115 -0
  14. data/lib/swarm_sdk/v3/hooks/runner.rb +128 -0
  15. data/lib/swarm_sdk/v3/mcp/connector.rb +183 -0
  16. data/lib/swarm_sdk/v3/mcp/mcp_error.rb +15 -0
  17. data/lib/swarm_sdk/v3/mcp/server_definition.rb +125 -0
  18. data/lib/swarm_sdk/v3/mcp/ssl_http_transport.rb +103 -0
  19. data/lib/swarm_sdk/v3/mcp/stdio_transport.rb +135 -0
  20. data/lib/swarm_sdk/v3/mcp/tool_proxy.rb +53 -0
  21. data/lib/swarm_sdk/v3/memory/adapters/base.rb +297 -0
  22. data/lib/swarm_sdk/v3/memory/adapters/faiss_support.rb +194 -0
  23. data/lib/swarm_sdk/v3/memory/adapters/filesystem_adapter.rb +212 -0
  24. data/lib/swarm_sdk/v3/memory/adapters/sqlite_adapter.rb +507 -0
  25. data/lib/swarm_sdk/v3/memory/adapters/vector_utils.rb +88 -0
  26. data/lib/swarm_sdk/v3/memory/card.rb +206 -0
  27. data/lib/swarm_sdk/v3/memory/cluster.rb +146 -0
  28. data/lib/swarm_sdk/v3/memory/compressor.rb +496 -0
  29. data/lib/swarm_sdk/v3/memory/consolidator.rb +427 -0
  30. data/lib/swarm_sdk/v3/memory/context_builder.rb +339 -0
  31. data/lib/swarm_sdk/v3/memory/edge.rb +105 -0
  32. data/lib/swarm_sdk/v3/memory/embedder.rb +185 -0
  33. data/lib/swarm_sdk/v3/memory/exposure_tracker.rb +104 -0
  34. data/lib/swarm_sdk/v3/memory/ingestion_pipeline.rb +394 -0
  35. data/lib/swarm_sdk/v3/memory/retriever.rb +289 -0
  36. data/lib/swarm_sdk/v3/memory/store.rb +489 -0
  37. data/lib/swarm_sdk/v3/skills/loader.rb +147 -0
  38. data/lib/swarm_sdk/v3/skills/manifest.rb +45 -0
  39. data/lib/swarm_sdk/v3/sub_task_agent.rb +248 -0
  40. data/lib/swarm_sdk/v3/tools/base.rb +80 -0
  41. data/lib/swarm_sdk/v3/tools/bash.rb +174 -0
  42. data/lib/swarm_sdk/v3/tools/clock.rb +32 -0
  43. data/lib/swarm_sdk/v3/tools/edit.rb +111 -0
  44. data/lib/swarm_sdk/v3/tools/glob.rb +96 -0
  45. data/lib/swarm_sdk/v3/tools/grep.rb +200 -0
  46. data/lib/swarm_sdk/v3/tools/message_teammate.rb +15 -0
  47. data/lib/swarm_sdk/v3/tools/message_user.rb +15 -0
  48. data/lib/swarm_sdk/v3/tools/read.rb +181 -0
  49. data/lib/swarm_sdk/v3/tools/read_tracker.rb +40 -0
  50. data/lib/swarm_sdk/v3/tools/registry.rb +208 -0
  51. data/lib/swarm_sdk/v3/tools/sub_task.rb +183 -0
  52. data/lib/swarm_sdk/v3/tools/think.rb +88 -0
  53. data/lib/swarm_sdk/v3/tools/write.rb +87 -0
  54. data/lib/swarm_sdk/v3.rb +145 -0
  55. metadata +84 -148
  56. data/lib/swarm_sdk/agent/RETRY_LOGIC.md +0 -175
  57. data/lib/swarm_sdk/agent/builder.rb +0 -680
  58. data/lib/swarm_sdk/agent/chat.rb +0 -1432
  59. data/lib/swarm_sdk/agent/chat_helpers/context_tracker.rb +0 -375
  60. data/lib/swarm_sdk/agent/chat_helpers/event_emitter.rb +0 -204
  61. data/lib/swarm_sdk/agent/chat_helpers/hook_integration.rb +0 -480
  62. data/lib/swarm_sdk/agent/chat_helpers/instrumentation.rb +0 -85
  63. data/lib/swarm_sdk/agent/chat_helpers/llm_configuration.rb +0 -290
  64. data/lib/swarm_sdk/agent/chat_helpers/logging_helpers.rb +0 -116
  65. data/lib/swarm_sdk/agent/chat_helpers/serialization.rb +0 -83
  66. data/lib/swarm_sdk/agent/chat_helpers/system_reminder_injector.rb +0 -134
  67. data/lib/swarm_sdk/agent/chat_helpers/system_reminders.rb +0 -79
  68. data/lib/swarm_sdk/agent/chat_helpers/token_tracking.rb +0 -146
  69. data/lib/swarm_sdk/agent/context.rb +0 -115
  70. data/lib/swarm_sdk/agent/context_manager.rb +0 -315
  71. data/lib/swarm_sdk/agent/definition.rb +0 -581
  72. data/lib/swarm_sdk/agent/llm_instrumentation_middleware.rb +0 -226
  73. data/lib/swarm_sdk/agent/system_prompt_builder.rb +0 -161
  74. data/lib/swarm_sdk/agent/tool_registry.rb +0 -189
  75. data/lib/swarm_sdk/agent_registry.rb +0 -146
  76. data/lib/swarm_sdk/builders/base_builder.rb +0 -553
  77. data/lib/swarm_sdk/claude_code_agent_adapter.rb +0 -205
  78. data/lib/swarm_sdk/concerns/cleanupable.rb +0 -39
  79. data/lib/swarm_sdk/concerns/snapshotable.rb +0 -67
  80. data/lib/swarm_sdk/concerns/validatable.rb +0 -55
  81. data/lib/swarm_sdk/config.rb +0 -367
  82. data/lib/swarm_sdk/configuration/parser.rb +0 -397
  83. data/lib/swarm_sdk/configuration/translator.rb +0 -283
  84. data/lib/swarm_sdk/configuration.rb +0 -165
  85. data/lib/swarm_sdk/context_compactor/metrics.rb +0 -147
  86. data/lib/swarm_sdk/context_compactor/token_counter.rb +0 -102
  87. data/lib/swarm_sdk/context_compactor.rb +0 -335
  88. data/lib/swarm_sdk/context_management/builder.rb +0 -128
  89. data/lib/swarm_sdk/context_management/context.rb +0 -328
  90. data/lib/swarm_sdk/custom_tool_registry.rb +0 -226
  91. data/lib/swarm_sdk/defaults.rb +0 -251
  92. data/lib/swarm_sdk/events_to_messages.rb +0 -199
  93. data/lib/swarm_sdk/hooks/adapter.rb +0 -359
  94. data/lib/swarm_sdk/hooks/context.rb +0 -197
  95. data/lib/swarm_sdk/hooks/definition.rb +0 -80
  96. data/lib/swarm_sdk/hooks/error.rb +0 -29
  97. data/lib/swarm_sdk/hooks/executor.rb +0 -146
  98. data/lib/swarm_sdk/hooks/registry.rb +0 -147
  99. data/lib/swarm_sdk/hooks/result.rb +0 -150
  100. data/lib/swarm_sdk/hooks/shell_executor.rb +0 -256
  101. data/lib/swarm_sdk/hooks/tool_call.rb +0 -35
  102. data/lib/swarm_sdk/hooks/tool_result.rb +0 -62
  103. data/lib/swarm_sdk/log_collector.rb +0 -227
  104. data/lib/swarm_sdk/log_stream.rb +0 -127
  105. data/lib/swarm_sdk/markdown_parser.rb +0 -75
  106. data/lib/swarm_sdk/model_aliases.json +0 -8
  107. data/lib/swarm_sdk/models.json +0 -44002
  108. data/lib/swarm_sdk/models.rb +0 -161
  109. data/lib/swarm_sdk/node_context.rb +0 -245
  110. data/lib/swarm_sdk/observer/builder.rb +0 -81
  111. data/lib/swarm_sdk/observer/config.rb +0 -45
  112. data/lib/swarm_sdk/observer/manager.rb +0 -236
  113. data/lib/swarm_sdk/patterns/agent_observer.rb +0 -160
  114. data/lib/swarm_sdk/permissions/config.rb +0 -239
  115. data/lib/swarm_sdk/permissions/error_formatter.rb +0 -121
  116. data/lib/swarm_sdk/permissions/path_matcher.rb +0 -35
  117. data/lib/swarm_sdk/permissions/validator.rb +0 -173
  118. data/lib/swarm_sdk/permissions_builder.rb +0 -122
  119. data/lib/swarm_sdk/plugin.rb +0 -309
  120. data/lib/swarm_sdk/plugin_registry.rb +0 -101
  121. data/lib/swarm_sdk/proc_helpers.rb +0 -53
  122. data/lib/swarm_sdk/prompts/base_system_prompt.md.erb +0 -117
  123. data/lib/swarm_sdk/restore_result.rb +0 -65
  124. data/lib/swarm_sdk/result.rb +0 -212
  125. data/lib/swarm_sdk/snapshot.rb +0 -156
  126. data/lib/swarm_sdk/snapshot_from_events.rb +0 -397
  127. data/lib/swarm_sdk/state_restorer.rb +0 -476
  128. data/lib/swarm_sdk/state_snapshot.rb +0 -334
  129. data/lib/swarm_sdk/swarm/agent_initializer.rb +0 -648
  130. data/lib/swarm_sdk/swarm/all_agents_builder.rb +0 -195
  131. data/lib/swarm_sdk/swarm/builder.rb +0 -256
  132. data/lib/swarm_sdk/swarm/executor.rb +0 -290
  133. data/lib/swarm_sdk/swarm/hook_triggers.rb +0 -151
  134. data/lib/swarm_sdk/swarm/lazy_delegate_chat.rb +0 -372
  135. data/lib/swarm_sdk/swarm/logging_callbacks.rb +0 -360
  136. data/lib/swarm_sdk/swarm/mcp_configurator.rb +0 -270
  137. data/lib/swarm_sdk/swarm/swarm_registry_builder.rb +0 -67
  138. data/lib/swarm_sdk/swarm/tool_configurator.rb +0 -392
  139. data/lib/swarm_sdk/swarm.rb +0 -843
  140. data/lib/swarm_sdk/swarm_loader.rb +0 -145
  141. data/lib/swarm_sdk/swarm_registry.rb +0 -136
  142. data/lib/swarm_sdk/tools/base.rb +0 -63
  143. data/lib/swarm_sdk/tools/bash.rb +0 -280
  144. data/lib/swarm_sdk/tools/clock.rb +0 -46
  145. data/lib/swarm_sdk/tools/delegate.rb +0 -389
  146. data/lib/swarm_sdk/tools/document_converters/base_converter.rb +0 -83
  147. data/lib/swarm_sdk/tools/document_converters/docx_converter.rb +0 -99
  148. data/lib/swarm_sdk/tools/document_converters/html_converter.rb +0 -101
  149. data/lib/swarm_sdk/tools/document_converters/pdf_converter.rb +0 -78
  150. data/lib/swarm_sdk/tools/document_converters/xlsx_converter.rb +0 -194
  151. data/lib/swarm_sdk/tools/edit.rb +0 -145
  152. data/lib/swarm_sdk/tools/glob.rb +0 -166
  153. data/lib/swarm_sdk/tools/grep.rb +0 -235
  154. data/lib/swarm_sdk/tools/image_extractors/docx_image_extractor.rb +0 -43
  155. data/lib/swarm_sdk/tools/image_extractors/pdf_image_extractor.rb +0 -167
  156. data/lib/swarm_sdk/tools/image_formats/tiff_builder.rb +0 -65
  157. data/lib/swarm_sdk/tools/mcp_tool_stub.rb +0 -198
  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 -273
  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 -100
  170. data/lib/swarm_sdk/tools/todo_write.rb +0 -237
  171. data/lib/swarm_sdk/tools/web_fetch.rb +0 -264
  172. data/lib/swarm_sdk/tools/write.rb +0 -112
  173. data/lib/swarm_sdk/transcript_builder.rb +0 -278
  174. data/lib/swarm_sdk/utils.rb +0 -68
  175. data/lib/swarm_sdk/validation_result.rb +0 -33
  176. data/lib/swarm_sdk/version.rb +0 -5
  177. data/lib/swarm_sdk/workflow/agent_config.rb +0 -95
  178. data/lib/swarm_sdk/workflow/builder.rb +0 -227
  179. data/lib/swarm_sdk/workflow/executor.rb +0 -497
  180. data/lib/swarm_sdk/workflow/node_builder.rb +0 -593
  181. data/lib/swarm_sdk/workflow/transformer_executor.rb +0 -250
  182. data/lib/swarm_sdk/workflow.rb +0 -589
  183. data/lib/swarm_sdk.rb +0 -718
@@ -1,367 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module SwarmSDK
4
- # Centralized configuration for SwarmSDK
5
- #
6
- # Config provides a single entry point for all SwarmSDK configuration,
7
- # including API keys (proxied to RubyLLM), defaults override, and
8
- # WebFetch settings.
9
- #
10
- # ## Priority Order
11
- #
12
- # Configuration values are resolved in this order:
13
- # 1. Explicit value (set via SwarmSDK.configure)
14
- # 2. Environment variable
15
- # 3. Module default (from SwarmSDK::Defaults)
16
- #
17
- # ## API Key Proxying
18
- #
19
- # API keys are automatically proxied to RubyLLM.config when set,
20
- # ensuring RubyLLM always has the correct credentials.
21
- #
22
- # @example Basic configuration
23
- # SwarmSDK.configure do |config|
24
- # config.openai_api_key = "sk-..."
25
- # config.default_model = "claude-sonnet-4"
26
- # config.agent_request_timeout = 600
27
- # end
28
- #
29
- # @example Testing setup
30
- # def setup
31
- # SwarmSDK.reset_config!
32
- # end
33
- class Config
34
- # API keys that proxy to RubyLLM.config
35
- # Maps SwarmSDK config key => [RubyLLM config key, ENV variable]
36
- API_KEY_MAPPINGS = {
37
- openai_api_key: [:openai_api_key, "OPENAI_API_KEY"],
38
- openai_api_base: [:openai_api_base, "OPENAI_API_BASE"],
39
- openai_organization_id: [:openai_organization_id, "OPENAI_ORG_ID"],
40
- openai_project_id: [:openai_project_id, "OPENAI_PROJECT_ID"],
41
- anthropic_api_key: [:anthropic_api_key, "ANTHROPIC_API_KEY"],
42
- gemini_api_key: [:gemini_api_key, "GEMINI_API_KEY"],
43
- gemini_api_base: [:gemini_api_base, "GEMINI_API_BASE"],
44
- vertexai_project_id: [:vertexai_project_id, "GOOGLE_CLOUD_PROJECT"],
45
- vertexai_location: [:vertexai_location, "GOOGLE_CLOUD_LOCATION"],
46
- deepseek_api_key: [:deepseek_api_key, "DEEPSEEK_API_KEY"],
47
- mistral_api_key: [:mistral_api_key, "MISTRAL_API_KEY"],
48
- perplexity_api_key: [:perplexity_api_key, "PERPLEXITY_API_KEY"],
49
- openrouter_api_key: [:openrouter_api_key, "OPENROUTER_API_KEY"],
50
- bedrock_api_key: [:bedrock_api_key, "AWS_ACCESS_KEY_ID"],
51
- bedrock_secret_key: [:bedrock_secret_key, "AWS_SECRET_ACCESS_KEY"],
52
- bedrock_region: [:bedrock_region, "AWS_REGION"],
53
- bedrock_session_token: [:bedrock_session_token, "AWS_SESSION_TOKEN"],
54
- ollama_api_base: [:ollama_api_base, "OLLAMA_API_BASE"],
55
- gpustack_api_base: [:gpustack_api_base, "GPUSTACK_API_BASE"],
56
- gpustack_api_key: [:gpustack_api_key, "GPUSTACK_API_KEY"],
57
- }.freeze
58
-
59
- # RubyLLM connection settings that proxy to RubyLLM.config
60
- # Maps SwarmSDK config key => [RubyLLM config key, ENV variable, default value]
61
- RUBYLLM_CONNECTION_MAPPINGS = {
62
- llm_request_timeout: [:request_timeout, "SWARM_SDK_LLM_REQUEST_TIMEOUT", 300],
63
- llm_read_timeout: [:read_timeout, "SWARM_SDK_LLM_READ_TIMEOUT", nil], # nil = use request_timeout
64
- llm_open_timeout: [:open_timeout, "SWARM_SDK_LLM_OPEN_TIMEOUT", 30],
65
- llm_write_timeout: [:write_timeout, "SWARM_SDK_LLM_WRITE_TIMEOUT", 30],
66
- }.freeze
67
-
68
- # SwarmSDK defaults that can be overridden
69
- # Maps config key => [ENV variable, default proc]
70
- DEFAULTS_MAPPINGS = {
71
- default_model: ["SWARM_SDK_DEFAULT_MODEL", -> { Defaults::Agent::MODEL }],
72
- default_provider: ["SWARM_SDK_DEFAULT_PROVIDER", -> { Defaults::Agent::PROVIDER }],
73
- agent_request_timeout: ["SWARM_SDK_AGENT_REQUEST_TIMEOUT", -> { Defaults::Timeouts::AGENT_REQUEST_SECONDS }],
74
- bash_command_timeout: ["SWARM_SDK_BASH_COMMAND_TIMEOUT", -> { Defaults::Timeouts::BASH_COMMAND_MS }],
75
- bash_command_max_timeout: ["SWARM_SDK_BASH_COMMAND_MAX_TIMEOUT", -> { Defaults::Timeouts::BASH_COMMAND_MAX_MS }],
76
- web_fetch_timeout: ["SWARM_SDK_WEB_FETCH_TIMEOUT", -> { Defaults::Timeouts::WEB_FETCH_SECONDS }],
77
- hook_shell_timeout: ["SWARM_SDK_HOOK_SHELL_TIMEOUT", -> { Defaults::Timeouts::HOOK_SHELL_SECONDS }],
78
- transformer_command_timeout: ["SWARM_SDK_TRANSFORMER_COMMAND_TIMEOUT", -> { Defaults::Timeouts::TRANSFORMER_COMMAND_SECONDS }],
79
- global_concurrency_limit: ["SWARM_SDK_GLOBAL_CONCURRENCY_LIMIT", -> { Defaults::Concurrency::GLOBAL_LIMIT }],
80
- local_concurrency_limit: ["SWARM_SDK_LOCAL_CONCURRENCY_LIMIT", -> { Defaults::Concurrency::LOCAL_LIMIT }],
81
- output_character_limit: ["SWARM_SDK_OUTPUT_CHARACTER_LIMIT", -> { Defaults::Limits::OUTPUT_CHARACTERS }],
82
- read_line_limit: ["SWARM_SDK_READ_LINE_LIMIT", -> { Defaults::Limits::READ_LINES }],
83
- line_character_limit: ["SWARM_SDK_LINE_CHARACTER_LIMIT", -> { Defaults::Limits::LINE_CHARACTERS }],
84
- web_fetch_character_limit: ["SWARM_SDK_WEB_FETCH_CHARACTER_LIMIT", -> { Defaults::Limits::WEB_FETCH_CHARACTERS }],
85
- glob_result_limit: ["SWARM_SDK_GLOB_RESULT_LIMIT", -> { Defaults::Limits::GLOB_RESULTS }],
86
- scratchpad_entry_size_limit: ["SWARM_SDK_SCRATCHPAD_ENTRY_SIZE_LIMIT", -> { Defaults::Storage::ENTRY_SIZE_BYTES }],
87
- scratchpad_total_size_limit: ["SWARM_SDK_SCRATCHPAD_TOTAL_SIZE_LIMIT", -> { Defaults::Storage::TOTAL_SIZE_BYTES }],
88
- context_compression_threshold: ["SWARM_SDK_CONTEXT_COMPRESSION_THRESHOLD", -> { Defaults::Context::COMPRESSION_THRESHOLD_PERCENT }],
89
- todowrite_reminder_interval: ["SWARM_SDK_TODOWRITE_REMINDER_INTERVAL", -> { Defaults::Context::TODOWRITE_REMINDER_INTERVAL }],
90
- chars_per_token_prose: ["SWARM_SDK_CHARS_PER_TOKEN_PROSE", -> { Defaults::TokenEstimation::CHARS_PER_TOKEN_PROSE }],
91
- chars_per_token_code: ["SWARM_SDK_CHARS_PER_TOKEN_CODE", -> { Defaults::TokenEstimation::CHARS_PER_TOKEN_CODE }],
92
- mcp_log_level: ["SWARM_SDK_MCP_LOG_LEVEL", -> { Defaults::Logging::MCP_LOG_LEVEL }],
93
- default_execution_timeout: ["SWARM_SDK_DEFAULT_EXECUTION_TIMEOUT", -> { Defaults::Timeouts::EXECUTION_TIMEOUT_SECONDS }],
94
- default_turn_timeout: ["SWARM_SDK_DEFAULT_TURN_TIMEOUT", -> { Defaults::Timeouts::TURN_TIMEOUT_SECONDS }],
95
- mcp_request_timeout: ["SWARM_SDK_MCP_REQUEST_TIMEOUT", -> { Defaults::Timeouts::MCP_REQUEST_SECONDS }],
96
- }.freeze
97
-
98
- # WebFetch and control settings
99
- # Maps config key => [ENV variable, default value]
100
- SETTINGS_MAPPINGS = {
101
- webfetch_provider: ["SWARM_SDK_WEBFETCH_PROVIDER", nil],
102
- webfetch_model: ["SWARM_SDK_WEBFETCH_MODEL", nil],
103
- webfetch_base_url: ["SWARM_SDK_WEBFETCH_BASE_URL", nil],
104
- webfetch_max_tokens: ["SWARM_SDK_WEBFETCH_MAX_TOKENS", 4096],
105
- allow_filesystem_tools: ["SWARM_SDK_ALLOW_FILESYSTEM_TOOLS", true],
106
- env_interpolation: ["SWARM_SDK_ENV_INTERPOLATION", true],
107
- streaming: ["SWARM_SDK_STREAMING", true],
108
- }.freeze
109
-
110
- class << self
111
- # Get the singleton Config instance
112
- #
113
- # @return [Config] The singleton instance
114
- def instance
115
- @instance ||= new
116
- end
117
-
118
- # Reset the Config instance
119
- #
120
- # Clears all configuration including explicit values and cached ENV values.
121
- # Use in tests to ensure clean state.
122
- #
123
- # @return [void]
124
- def reset!
125
- @instance = nil
126
- end
127
- end
128
-
129
- # Initialize a new Config instance
130
- #
131
- # @note Use Config.instance instead of new for the singleton pattern
132
- def initialize
133
- @explicit_values = {}
134
- @env_values = {}
135
- @env_loaded = false
136
- @env_mutex = Mutex.new
137
- end
138
-
139
- # ========== API Key Accessors (with RubyLLM proxying) ==========
140
-
141
- # @!method openai_api_key
142
- # Get the OpenAI API key
143
- # @return [String, nil] The API key
144
- #
145
- # @!method openai_api_key=(value)
146
- # Set the OpenAI API key (proxied to RubyLLM)
147
- # @param value [String] The API key
148
-
149
- API_KEY_MAPPINGS.each_key do |config_key|
150
- ruby_llm_key, _ = API_KEY_MAPPINGS[config_key]
151
-
152
- # Getter
153
- define_method(config_key) do
154
- ensure_env_loaded!
155
- @explicit_values[config_key] || @env_values[config_key]
156
- end
157
-
158
- # Setter with RubyLLM proxying
159
- define_method("#{config_key}=") do |value|
160
- @explicit_values[config_key] = value
161
- RubyLLM.config.public_send("#{ruby_llm_key}=", value) if value
162
- end
163
- end
164
-
165
- # ========== RubyLLM Connection Accessors (with RubyLLM proxying) ==========
166
-
167
- # @!method llm_request_timeout
168
- # Get the LLM request timeout (seconds)
169
- # @return [Integer] The timeout (default: 300)
170
- #
171
- # @!method llm_read_timeout
172
- # Get the LLM read timeout (seconds) - time to wait between chunks
173
- # @return [Integer, nil] The timeout (nil = use request_timeout)
174
- #
175
- # @!method llm_open_timeout
176
- # Get the LLM connection open timeout (seconds)
177
- # @return [Integer] The timeout (default: 30)
178
- #
179
- # @!method llm_write_timeout
180
- # Get the LLM write timeout (seconds)
181
- # @return [Integer] The timeout (default: 30)
182
-
183
- RUBYLLM_CONNECTION_MAPPINGS.each_key do |config_key|
184
- ruby_llm_key, _env_key, default_value = RUBYLLM_CONNECTION_MAPPINGS[config_key]
185
-
186
- # Getter with default fallback
187
- define_method(config_key) do
188
- ensure_env_loaded!
189
- if @explicit_values.key?(config_key)
190
- @explicit_values[config_key]
191
- elsif @env_values.key?(config_key)
192
- @env_values[config_key]
193
- else
194
- default_value
195
- end
196
- end
197
-
198
- # Setter with RubyLLM proxying
199
- define_method("#{config_key}=") do |value|
200
- @explicit_values[config_key] = value
201
- RubyLLM.config.public_send("#{ruby_llm_key}=", value)
202
- end
203
- end
204
-
205
- # ========== Defaults Accessors (with module constant fallback) ==========
206
-
207
- # @!method default_model
208
- # Get the default model
209
- # @return [String] The default model (falls back to Defaults::Agent::MODEL)
210
- #
211
- # @!method default_model=(value)
212
- # Set the default model
213
- # @param value [String] The default model
214
-
215
- DEFAULTS_MAPPINGS.each_key do |config_key|
216
- _env_key, default_proc = DEFAULTS_MAPPINGS[config_key]
217
-
218
- # Getter with default fallback
219
- define_method(config_key) do
220
- ensure_env_loaded!
221
- @explicit_values[config_key] || @env_values[config_key] || default_proc.call
222
- end
223
-
224
- # Setter
225
- define_method("#{config_key}=") do |value|
226
- @explicit_values[config_key] = value
227
- end
228
- end
229
-
230
- # ========== Settings Accessors (WebFetch and control) ==========
231
-
232
- # @!method webfetch_provider
233
- # Get the WebFetch LLM provider
234
- # @return [String, nil] The provider
235
- #
236
- # @!method allow_filesystem_tools
237
- # Get whether filesystem tools are allowed
238
- # @return [Boolean] true if allowed
239
-
240
- SETTINGS_MAPPINGS.each_key do |config_key|
241
- _env_key, default_value = SETTINGS_MAPPINGS[config_key]
242
-
243
- # Getter with default fallback
244
- define_method(config_key) do
245
- ensure_env_loaded!
246
- if @explicit_values.key?(config_key)
247
- @explicit_values[config_key]
248
- elsif @env_values.key?(config_key)
249
- @env_values[config_key]
250
- else
251
- default_value
252
- end
253
- end
254
-
255
- # Setter
256
- define_method("#{config_key}=") do |value|
257
- @explicit_values[config_key] = value
258
- end
259
- end
260
-
261
- # ========== Convenience Methods ==========
262
-
263
- # Check if WebFetch LLM processing is enabled
264
- #
265
- # WebFetch uses LLM processing when both provider and model are configured.
266
- #
267
- # @return [Boolean] true if WebFetch LLM is configured
268
- def webfetch_llm_enabled?
269
- !webfetch_provider.nil? && !webfetch_model.nil?
270
- end
271
-
272
- private
273
-
274
- # Ensure ENV values are loaded (lazy loading with double-check locking)
275
- #
276
- # Thread-safe lazy loading of ENV values. Only loads once per Config instance.
277
- #
278
- # @return [void]
279
- def ensure_env_loaded!
280
- return if @env_loaded
281
-
282
- @env_mutex.synchronize do
283
- return if @env_loaded
284
-
285
- load_env_values!
286
- @env_loaded = true
287
- end
288
- end
289
-
290
- # Load environment variable values
291
- #
292
- # Loads API keys (with RubyLLM proxying), defaults, and settings from ENV.
293
- # Only loads values that haven't been explicitly set.
294
- #
295
- # @return [void]
296
- def load_env_values!
297
- # Load API keys and proxy to RubyLLM
298
- API_KEY_MAPPINGS.each do |config_key, (ruby_llm_key, env_key)|
299
- next if @explicit_values.key?(config_key)
300
- next unless ENV.key?(env_key)
301
-
302
- value = ENV[env_key]
303
- @env_values[config_key] = value
304
-
305
- # Proxy to RubyLLM
306
- RubyLLM.config.public_send("#{ruby_llm_key}=", value)
307
- end
308
-
309
- # Load RubyLLM connection settings and proxy to RubyLLM
310
- RUBYLLM_CONNECTION_MAPPINGS.each do |config_key, (ruby_llm_key, env_key, _default)|
311
- next if @explicit_values.key?(config_key)
312
- next unless ENV.key?(env_key)
313
-
314
- value = parse_env_value(ENV[env_key], config_key)
315
- @env_values[config_key] = value
316
-
317
- # Proxy to RubyLLM
318
- RubyLLM.config.public_send("#{ruby_llm_key}=", value)
319
- end
320
-
321
- # Load defaults (no RubyLLM proxy)
322
- DEFAULTS_MAPPINGS.each do |config_key, (env_key, _default_proc)|
323
- next if @explicit_values.key?(config_key)
324
- next unless ENV.key?(env_key)
325
-
326
- @env_values[config_key] = parse_env_value(ENV[env_key], config_key)
327
- end
328
-
329
- # Load settings (no RubyLLM proxy)
330
- SETTINGS_MAPPINGS.each do |config_key, (env_key, _default_value)|
331
- next if @explicit_values.key?(config_key)
332
- next unless ENV.key?(env_key)
333
-
334
- @env_values[config_key] = parse_env_value(ENV[env_key], config_key)
335
- end
336
- end
337
-
338
- # Parse environment variable value to appropriate type
339
- #
340
- # Converts string ENV values to integers, floats, or booleans based on
341
- # the configuration key pattern.
342
- #
343
- # @param value [String] The ENV value string
344
- # @param key [Symbol] The configuration key
345
- # @return [Integer, Float, Boolean, String] The parsed value
346
- def parse_env_value(value, key)
347
- case key
348
- when :allow_filesystem_tools, :env_interpolation, :streaming
349
- # Convert string to boolean
350
- case value.to_s.downcase
351
- when "true", "yes", "1", "on", "enabled"
352
- true
353
- when "false", "no", "0", "off", "disabled"
354
- false
355
- else
356
- true # Default to true if unrecognized
357
- end
358
- when /_timeout$/, /_limit$/, /_interval$/, /_threshold$/, :mcp_log_level, :webfetch_max_tokens
359
- value.to_i
360
- when /^chars_per_token/
361
- value.to_f
362
- else
363
- value
364
- end
365
- end
366
- end
367
- end