swarm_sdk 2.7.14 → 3.0.0.alpha2

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 (185) hide show
  1. checksums.yaml +4 -4
  2. data/lib/swarm_sdk/ruby_llm_patches/chat_callbacks_patch.rb +16 -0
  3. data/lib/swarm_sdk/ruby_llm_patches/init.rb +4 -1
  4. data/lib/swarm_sdk/v3/agent.rb +1165 -0
  5. data/lib/swarm_sdk/v3/agent_builder.rb +533 -0
  6. data/lib/swarm_sdk/v3/agent_definition.rb +330 -0
  7. data/lib/swarm_sdk/v3/configuration.rb +490 -0
  8. data/lib/swarm_sdk/v3/debug_log.rb +86 -0
  9. data/lib/swarm_sdk/v3/event_stream.rb +130 -0
  10. data/lib/swarm_sdk/v3/hooks/context.rb +112 -0
  11. data/lib/swarm_sdk/v3/hooks/result.rb +115 -0
  12. data/lib/swarm_sdk/v3/hooks/runner.rb +128 -0
  13. data/lib/swarm_sdk/v3/mcp/connector.rb +183 -0
  14. data/lib/swarm_sdk/v3/mcp/mcp_error.rb +15 -0
  15. data/lib/swarm_sdk/v3/mcp/server_definition.rb +125 -0
  16. data/lib/swarm_sdk/v3/mcp/ssl_http_transport.rb +103 -0
  17. data/lib/swarm_sdk/v3/mcp/stdio_transport.rb +135 -0
  18. data/lib/swarm_sdk/v3/mcp/tool_proxy.rb +53 -0
  19. data/lib/swarm_sdk/v3/memory/adapters/base.rb +297 -0
  20. data/lib/swarm_sdk/v3/memory/adapters/faiss_support.rb +194 -0
  21. data/lib/swarm_sdk/v3/memory/adapters/filesystem_adapter.rb +212 -0
  22. data/lib/swarm_sdk/v3/memory/adapters/sqlite_adapter.rb +507 -0
  23. data/lib/swarm_sdk/v3/memory/adapters/vector_utils.rb +88 -0
  24. data/lib/swarm_sdk/v3/memory/card.rb +206 -0
  25. data/lib/swarm_sdk/v3/memory/cluster.rb +146 -0
  26. data/lib/swarm_sdk/v3/memory/compressor.rb +496 -0
  27. data/lib/swarm_sdk/v3/memory/consolidator.rb +427 -0
  28. data/lib/swarm_sdk/v3/memory/context_builder.rb +339 -0
  29. data/lib/swarm_sdk/v3/memory/edge.rb +105 -0
  30. data/lib/swarm_sdk/v3/memory/embedder.rb +185 -0
  31. data/lib/swarm_sdk/v3/memory/exposure_tracker.rb +104 -0
  32. data/lib/swarm_sdk/v3/memory/ingestion_pipeline.rb +394 -0
  33. data/lib/swarm_sdk/v3/memory/retriever.rb +289 -0
  34. data/lib/swarm_sdk/v3/memory/store.rb +489 -0
  35. data/lib/swarm_sdk/v3/skills/loader.rb +147 -0
  36. data/lib/swarm_sdk/v3/skills/manifest.rb +45 -0
  37. data/lib/swarm_sdk/v3/sub_task_agent.rb +248 -0
  38. data/lib/swarm_sdk/v3/tools/base.rb +80 -0
  39. data/lib/swarm_sdk/v3/tools/bash.rb +174 -0
  40. data/lib/swarm_sdk/v3/tools/clock.rb +32 -0
  41. data/lib/swarm_sdk/v3/tools/document_converters/base.rb +84 -0
  42. data/lib/swarm_sdk/v3/tools/document_converters/docx_converter.rb +120 -0
  43. data/lib/swarm_sdk/v3/tools/document_converters/pdf_converter.rb +111 -0
  44. data/lib/swarm_sdk/v3/tools/document_converters/xlsx_converter.rb +128 -0
  45. data/lib/swarm_sdk/v3/tools/edit.rb +111 -0
  46. data/lib/swarm_sdk/v3/tools/glob.rb +96 -0
  47. data/lib/swarm_sdk/v3/tools/grep.rb +200 -0
  48. data/lib/swarm_sdk/v3/tools/message_teammate.rb +15 -0
  49. data/lib/swarm_sdk/v3/tools/message_user.rb +15 -0
  50. data/lib/swarm_sdk/v3/tools/read.rb +213 -0
  51. data/lib/swarm_sdk/v3/tools/read_tracker.rb +40 -0
  52. data/lib/swarm_sdk/v3/tools/registry.rb +208 -0
  53. data/lib/swarm_sdk/v3/tools/sub_task.rb +183 -0
  54. data/lib/swarm_sdk/v3/tools/think.rb +88 -0
  55. data/lib/swarm_sdk/v3/tools/write.rb +87 -0
  56. data/lib/swarm_sdk/v3.rb +145 -0
  57. metadata +88 -149
  58. data/lib/swarm_sdk/agent/RETRY_LOGIC.md +0 -175
  59. data/lib/swarm_sdk/agent/builder.rb +0 -705
  60. data/lib/swarm_sdk/agent/chat.rb +0 -1438
  61. data/lib/swarm_sdk/agent/chat_helpers/context_tracker.rb +0 -375
  62. data/lib/swarm_sdk/agent/chat_helpers/event_emitter.rb +0 -204
  63. data/lib/swarm_sdk/agent/chat_helpers/hook_integration.rb +0 -480
  64. data/lib/swarm_sdk/agent/chat_helpers/instrumentation.rb +0 -85
  65. data/lib/swarm_sdk/agent/chat_helpers/llm_configuration.rb +0 -290
  66. data/lib/swarm_sdk/agent/chat_helpers/logging_helpers.rb +0 -116
  67. data/lib/swarm_sdk/agent/chat_helpers/serialization.rb +0 -83
  68. data/lib/swarm_sdk/agent/chat_helpers/system_reminder_injector.rb +0 -134
  69. data/lib/swarm_sdk/agent/chat_helpers/system_reminders.rb +0 -79
  70. data/lib/swarm_sdk/agent/chat_helpers/token_tracking.rb +0 -146
  71. data/lib/swarm_sdk/agent/context.rb +0 -115
  72. data/lib/swarm_sdk/agent/context_manager.rb +0 -315
  73. data/lib/swarm_sdk/agent/definition.rb +0 -588
  74. data/lib/swarm_sdk/agent/llm_instrumentation_middleware.rb +0 -226
  75. data/lib/swarm_sdk/agent/system_prompt_builder.rb +0 -173
  76. data/lib/swarm_sdk/agent/tool_registry.rb +0 -189
  77. data/lib/swarm_sdk/agent_registry.rb +0 -146
  78. data/lib/swarm_sdk/builders/base_builder.rb +0 -558
  79. data/lib/swarm_sdk/claude_code_agent_adapter.rb +0 -205
  80. data/lib/swarm_sdk/concerns/cleanupable.rb +0 -42
  81. data/lib/swarm_sdk/concerns/snapshotable.rb +0 -67
  82. data/lib/swarm_sdk/concerns/validatable.rb +0 -55
  83. data/lib/swarm_sdk/config.rb +0 -368
  84. data/lib/swarm_sdk/configuration/parser.rb +0 -397
  85. data/lib/swarm_sdk/configuration/translator.rb +0 -285
  86. data/lib/swarm_sdk/configuration.rb +0 -165
  87. data/lib/swarm_sdk/context_compactor/metrics.rb +0 -147
  88. data/lib/swarm_sdk/context_compactor/token_counter.rb +0 -102
  89. data/lib/swarm_sdk/context_compactor.rb +0 -335
  90. data/lib/swarm_sdk/context_management/builder.rb +0 -128
  91. data/lib/swarm_sdk/context_management/context.rb +0 -328
  92. data/lib/swarm_sdk/custom_tool_registry.rb +0 -226
  93. data/lib/swarm_sdk/defaults.rb +0 -251
  94. data/lib/swarm_sdk/events_to_messages.rb +0 -199
  95. data/lib/swarm_sdk/hooks/adapter.rb +0 -359
  96. data/lib/swarm_sdk/hooks/context.rb +0 -197
  97. data/lib/swarm_sdk/hooks/definition.rb +0 -80
  98. data/lib/swarm_sdk/hooks/error.rb +0 -29
  99. data/lib/swarm_sdk/hooks/executor.rb +0 -146
  100. data/lib/swarm_sdk/hooks/registry.rb +0 -147
  101. data/lib/swarm_sdk/hooks/result.rb +0 -150
  102. data/lib/swarm_sdk/hooks/shell_executor.rb +0 -256
  103. data/lib/swarm_sdk/hooks/tool_call.rb +0 -35
  104. data/lib/swarm_sdk/hooks/tool_result.rb +0 -62
  105. data/lib/swarm_sdk/log_collector.rb +0 -227
  106. data/lib/swarm_sdk/log_stream.rb +0 -127
  107. data/lib/swarm_sdk/markdown_parser.rb +0 -75
  108. data/lib/swarm_sdk/model_aliases.json +0 -8
  109. data/lib/swarm_sdk/models.json +0 -44002
  110. data/lib/swarm_sdk/models.rb +0 -161
  111. data/lib/swarm_sdk/node_context.rb +0 -245
  112. data/lib/swarm_sdk/observer/builder.rb +0 -81
  113. data/lib/swarm_sdk/observer/config.rb +0 -45
  114. data/lib/swarm_sdk/observer/manager.rb +0 -248
  115. data/lib/swarm_sdk/patterns/agent_observer.rb +0 -160
  116. data/lib/swarm_sdk/permissions/config.rb +0 -239
  117. data/lib/swarm_sdk/permissions/error_formatter.rb +0 -121
  118. data/lib/swarm_sdk/permissions/path_matcher.rb +0 -35
  119. data/lib/swarm_sdk/permissions/validator.rb +0 -173
  120. data/lib/swarm_sdk/permissions_builder.rb +0 -122
  121. data/lib/swarm_sdk/plugin.rb +0 -309
  122. data/lib/swarm_sdk/plugin_registry.rb +0 -101
  123. data/lib/swarm_sdk/proc_helpers.rb +0 -53
  124. data/lib/swarm_sdk/prompts/base_system_prompt.md.erb +0 -119
  125. data/lib/swarm_sdk/restore_result.rb +0 -65
  126. data/lib/swarm_sdk/result.rb +0 -241
  127. data/lib/swarm_sdk/snapshot.rb +0 -156
  128. data/lib/swarm_sdk/snapshot_from_events.rb +0 -397
  129. data/lib/swarm_sdk/state_restorer.rb +0 -476
  130. data/lib/swarm_sdk/state_snapshot.rb +0 -334
  131. data/lib/swarm_sdk/swarm/agent_initializer.rb +0 -648
  132. data/lib/swarm_sdk/swarm/all_agents_builder.rb +0 -204
  133. data/lib/swarm_sdk/swarm/builder.rb +0 -256
  134. data/lib/swarm_sdk/swarm/executor.rb +0 -446
  135. data/lib/swarm_sdk/swarm/hook_triggers.rb +0 -162
  136. data/lib/swarm_sdk/swarm/lazy_delegate_chat.rb +0 -372
  137. data/lib/swarm_sdk/swarm/logging_callbacks.rb +0 -361
  138. data/lib/swarm_sdk/swarm/mcp_configurator.rb +0 -290
  139. data/lib/swarm_sdk/swarm/swarm_registry_builder.rb +0 -67
  140. data/lib/swarm_sdk/swarm/tool_configurator.rb +0 -392
  141. data/lib/swarm_sdk/swarm.rb +0 -973
  142. data/lib/swarm_sdk/swarm_loader.rb +0 -145
  143. data/lib/swarm_sdk/swarm_registry.rb +0 -136
  144. data/lib/swarm_sdk/tools/base.rb +0 -63
  145. data/lib/swarm_sdk/tools/bash.rb +0 -280
  146. data/lib/swarm_sdk/tools/clock.rb +0 -46
  147. data/lib/swarm_sdk/tools/delegate.rb +0 -389
  148. data/lib/swarm_sdk/tools/document_converters/base_converter.rb +0 -83
  149. data/lib/swarm_sdk/tools/document_converters/docx_converter.rb +0 -99
  150. data/lib/swarm_sdk/tools/document_converters/html_converter.rb +0 -101
  151. data/lib/swarm_sdk/tools/document_converters/pdf_converter.rb +0 -78
  152. data/lib/swarm_sdk/tools/document_converters/xlsx_converter.rb +0 -194
  153. data/lib/swarm_sdk/tools/edit.rb +0 -145
  154. data/lib/swarm_sdk/tools/glob.rb +0 -166
  155. data/lib/swarm_sdk/tools/grep.rb +0 -235
  156. data/lib/swarm_sdk/tools/image_extractors/docx_image_extractor.rb +0 -43
  157. data/lib/swarm_sdk/tools/image_extractors/pdf_image_extractor.rb +0 -167
  158. data/lib/swarm_sdk/tools/image_formats/tiff_builder.rb +0 -65
  159. data/lib/swarm_sdk/tools/mcp_tool_stub.rb +0 -198
  160. data/lib/swarm_sdk/tools/multi_edit.rb +0 -236
  161. data/lib/swarm_sdk/tools/path_resolver.rb +0 -92
  162. data/lib/swarm_sdk/tools/read.rb +0 -261
  163. data/lib/swarm_sdk/tools/registry.rb +0 -205
  164. data/lib/swarm_sdk/tools/scratchpad/scratchpad_list.rb +0 -117
  165. data/lib/swarm_sdk/tools/scratchpad/scratchpad_read.rb +0 -97
  166. data/lib/swarm_sdk/tools/scratchpad/scratchpad_write.rb +0 -108
  167. data/lib/swarm_sdk/tools/stores/read_tracker.rb +0 -96
  168. data/lib/swarm_sdk/tools/stores/scratchpad_storage.rb +0 -273
  169. data/lib/swarm_sdk/tools/stores/storage.rb +0 -142
  170. data/lib/swarm_sdk/tools/stores/todo_manager.rb +0 -65
  171. data/lib/swarm_sdk/tools/think.rb +0 -100
  172. data/lib/swarm_sdk/tools/todo_write.rb +0 -237
  173. data/lib/swarm_sdk/tools/web_fetch.rb +0 -264
  174. data/lib/swarm_sdk/tools/write.rb +0 -112
  175. data/lib/swarm_sdk/transcript_builder.rb +0 -278
  176. data/lib/swarm_sdk/utils.rb +0 -68
  177. data/lib/swarm_sdk/validation_result.rb +0 -33
  178. data/lib/swarm_sdk/version.rb +0 -5
  179. data/lib/swarm_sdk/workflow/agent_config.rb +0 -95
  180. data/lib/swarm_sdk/workflow/builder.rb +0 -227
  181. data/lib/swarm_sdk/workflow/executor.rb +0 -497
  182. data/lib/swarm_sdk/workflow/node_builder.rb +0 -593
  183. data/lib/swarm_sdk/workflow/transformer_executor.rb +0 -250
  184. data/lib/swarm_sdk/workflow.rb +0 -589
  185. data/lib/swarm_sdk.rb +0 -721
@@ -1,368 +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
- mcp_ssl_verify: ["SWARM_SDK_MCP_SSL_VERIFY", true],
109
- }.freeze
110
-
111
- class << self
112
- # Get the singleton Config instance
113
- #
114
- # @return [Config] The singleton instance
115
- def instance
116
- @instance ||= new
117
- end
118
-
119
- # Reset the Config instance
120
- #
121
- # Clears all configuration including explicit values and cached ENV values.
122
- # Use in tests to ensure clean state.
123
- #
124
- # @return [void]
125
- def reset!
126
- @instance = nil
127
- end
128
- end
129
-
130
- # Initialize a new Config instance
131
- #
132
- # @note Use Config.instance instead of new for the singleton pattern
133
- def initialize
134
- @explicit_values = {}
135
- @env_values = {}
136
- @env_loaded = false
137
- @env_mutex = Mutex.new
138
- end
139
-
140
- # ========== API Key Accessors (with RubyLLM proxying) ==========
141
-
142
- # @!method openai_api_key
143
- # Get the OpenAI API key
144
- # @return [String, nil] The API key
145
- #
146
- # @!method openai_api_key=(value)
147
- # Set the OpenAI API key (proxied to RubyLLM)
148
- # @param value [String] The API key
149
-
150
- API_KEY_MAPPINGS.each_key do |config_key|
151
- ruby_llm_key, _ = API_KEY_MAPPINGS[config_key]
152
-
153
- # Getter
154
- define_method(config_key) do
155
- ensure_env_loaded!
156
- @explicit_values[config_key] || @env_values[config_key]
157
- end
158
-
159
- # Setter with RubyLLM proxying
160
- define_method("#{config_key}=") do |value|
161
- @explicit_values[config_key] = value
162
- RubyLLM.config.public_send("#{ruby_llm_key}=", value) if value
163
- end
164
- end
165
-
166
- # ========== RubyLLM Connection Accessors (with RubyLLM proxying) ==========
167
-
168
- # @!method llm_request_timeout
169
- # Get the LLM request timeout (seconds)
170
- # @return [Integer] The timeout (default: 300)
171
- #
172
- # @!method llm_read_timeout
173
- # Get the LLM read timeout (seconds) - time to wait between chunks
174
- # @return [Integer, nil] The timeout (nil = use request_timeout)
175
- #
176
- # @!method llm_open_timeout
177
- # Get the LLM connection open timeout (seconds)
178
- # @return [Integer] The timeout (default: 30)
179
- #
180
- # @!method llm_write_timeout
181
- # Get the LLM write timeout (seconds)
182
- # @return [Integer] The timeout (default: 30)
183
-
184
- RUBYLLM_CONNECTION_MAPPINGS.each_key do |config_key|
185
- ruby_llm_key, _env_key, default_value = RUBYLLM_CONNECTION_MAPPINGS[config_key]
186
-
187
- # Getter with default fallback
188
- define_method(config_key) do
189
- ensure_env_loaded!
190
- if @explicit_values.key?(config_key)
191
- @explicit_values[config_key]
192
- elsif @env_values.key?(config_key)
193
- @env_values[config_key]
194
- else
195
- default_value
196
- end
197
- end
198
-
199
- # Setter with RubyLLM proxying
200
- define_method("#{config_key}=") do |value|
201
- @explicit_values[config_key] = value
202
- RubyLLM.config.public_send("#{ruby_llm_key}=", value)
203
- end
204
- end
205
-
206
- # ========== Defaults Accessors (with module constant fallback) ==========
207
-
208
- # @!method default_model
209
- # Get the default model
210
- # @return [String] The default model (falls back to Defaults::Agent::MODEL)
211
- #
212
- # @!method default_model=(value)
213
- # Set the default model
214
- # @param value [String] The default model
215
-
216
- DEFAULTS_MAPPINGS.each_key do |config_key|
217
- _env_key, default_proc = DEFAULTS_MAPPINGS[config_key]
218
-
219
- # Getter with default fallback
220
- define_method(config_key) do
221
- ensure_env_loaded!
222
- @explicit_values[config_key] || @env_values[config_key] || default_proc.call
223
- end
224
-
225
- # Setter
226
- define_method("#{config_key}=") do |value|
227
- @explicit_values[config_key] = value
228
- end
229
- end
230
-
231
- # ========== Settings Accessors (WebFetch and control) ==========
232
-
233
- # @!method webfetch_provider
234
- # Get the WebFetch LLM provider
235
- # @return [String, nil] The provider
236
- #
237
- # @!method allow_filesystem_tools
238
- # Get whether filesystem tools are allowed
239
- # @return [Boolean] true if allowed
240
-
241
- SETTINGS_MAPPINGS.each_key do |config_key|
242
- _env_key, default_value = SETTINGS_MAPPINGS[config_key]
243
-
244
- # Getter with default fallback
245
- define_method(config_key) do
246
- ensure_env_loaded!
247
- if @explicit_values.key?(config_key)
248
- @explicit_values[config_key]
249
- elsif @env_values.key?(config_key)
250
- @env_values[config_key]
251
- else
252
- default_value
253
- end
254
- end
255
-
256
- # Setter
257
- define_method("#{config_key}=") do |value|
258
- @explicit_values[config_key] = value
259
- end
260
- end
261
-
262
- # ========== Convenience Methods ==========
263
-
264
- # Check if WebFetch LLM processing is enabled
265
- #
266
- # WebFetch uses LLM processing when both provider and model are configured.
267
- #
268
- # @return [Boolean] true if WebFetch LLM is configured
269
- def webfetch_llm_enabled?
270
- !webfetch_provider.nil? && !webfetch_model.nil?
271
- end
272
-
273
- private
274
-
275
- # Ensure ENV values are loaded (lazy loading with double-check locking)
276
- #
277
- # Thread-safe lazy loading of ENV values. Only loads once per Config instance.
278
- #
279
- # @return [void]
280
- def ensure_env_loaded!
281
- return if @env_loaded
282
-
283
- @env_mutex.synchronize do
284
- return if @env_loaded
285
-
286
- load_env_values!
287
- @env_loaded = true
288
- end
289
- end
290
-
291
- # Load environment variable values
292
- #
293
- # Loads API keys (with RubyLLM proxying), defaults, and settings from ENV.
294
- # Only loads values that haven't been explicitly set.
295
- #
296
- # @return [void]
297
- def load_env_values!
298
- # Load API keys and proxy to RubyLLM
299
- API_KEY_MAPPINGS.each do |config_key, (ruby_llm_key, env_key)|
300
- next if @explicit_values.key?(config_key)
301
- next unless ENV.key?(env_key)
302
-
303
- value = ENV[env_key]
304
- @env_values[config_key] = value
305
-
306
- # Proxy to RubyLLM
307
- RubyLLM.config.public_send("#{ruby_llm_key}=", value)
308
- end
309
-
310
- # Load RubyLLM connection settings and proxy to RubyLLM
311
- RUBYLLM_CONNECTION_MAPPINGS.each do |config_key, (ruby_llm_key, env_key, _default)|
312
- next if @explicit_values.key?(config_key)
313
- next unless ENV.key?(env_key)
314
-
315
- value = parse_env_value(ENV[env_key], config_key)
316
- @env_values[config_key] = value
317
-
318
- # Proxy to RubyLLM
319
- RubyLLM.config.public_send("#{ruby_llm_key}=", value)
320
- end
321
-
322
- # Load defaults (no RubyLLM proxy)
323
- DEFAULTS_MAPPINGS.each do |config_key, (env_key, _default_proc)|
324
- next if @explicit_values.key?(config_key)
325
- next unless ENV.key?(env_key)
326
-
327
- @env_values[config_key] = parse_env_value(ENV[env_key], config_key)
328
- end
329
-
330
- # Load settings (no RubyLLM proxy)
331
- SETTINGS_MAPPINGS.each do |config_key, (env_key, _default_value)|
332
- next if @explicit_values.key?(config_key)
333
- next unless ENV.key?(env_key)
334
-
335
- @env_values[config_key] = parse_env_value(ENV[env_key], config_key)
336
- end
337
- end
338
-
339
- # Parse environment variable value to appropriate type
340
- #
341
- # Converts string ENV values to integers, floats, or booleans based on
342
- # the configuration key pattern.
343
- #
344
- # @param value [String] The ENV value string
345
- # @param key [Symbol] The configuration key
346
- # @return [Integer, Float, Boolean, String] The parsed value
347
- def parse_env_value(value, key)
348
- case key
349
- when :allow_filesystem_tools, :env_interpolation, :streaming, :mcp_ssl_verify
350
- # Convert string to boolean
351
- case value.to_s.downcase
352
- when "true", "yes", "1", "on", "enabled"
353
- true
354
- when "false", "no", "0", "off", "disabled"
355
- false
356
- else
357
- true # Default to true if unrecognized
358
- end
359
- when /_timeout$/, /_limit$/, /_interval$/, /_threshold$/, :mcp_log_level, :webfetch_max_tokens
360
- value.to_i
361
- when /^chars_per_token/
362
- value.to_f
363
- else
364
- value
365
- end
366
- end
367
- end
368
- end