Class: RubynCode::Config::Settings
- Inherits:
-
Object
- Object
- RubynCode::Config::Settings
- Defined in:
- lib/rubyn_code/config/settings.rb
Defined Under Namespace
Classes: LoadError
Constant Summary collapse
- CONFIGURABLE_KEYS =
%i[ provider model model_mode max_iterations max_sub_agent_iterations max_output_chars context_threshold_tokens micro_compact_keep_recent poll_interval idle_timeout session_budget_usd daily_budget_usd oauth_client_id oauth_redirect_uri oauth_authorize_url oauth_token_url oauth_scopes skills_autoload chisel_mode ].freeze
- DEFAULT_MAP =
{ provider: Defaults::DEFAULT_PROVIDER, model: Defaults::DEFAULT_MODEL, model_mode: Defaults::MODEL_MODE, max_iterations: Defaults::MAX_ITERATIONS, max_sub_agent_iterations: Defaults::MAX_SUB_AGENT_ITERATIONS, max_output_chars: Defaults::MAX_OUTPUT_CHARS, context_threshold_tokens: Defaults::CONTEXT_THRESHOLD_TOKENS, micro_compact_keep_recent: Defaults::MICRO_COMPACT_KEEP_RECENT, poll_interval: Defaults::POLL_INTERVAL, idle_timeout: Defaults::IDLE_TIMEOUT, session_budget_usd: Defaults::SESSION_BUDGET_USD, daily_budget_usd: Defaults::DAILY_BUDGET_USD, oauth_client_id: Defaults::OAUTH_CLIENT_ID, oauth_redirect_uri: Defaults::OAUTH_REDIRECT_URI, oauth_authorize_url: Defaults::OAUTH_AUTHORIZE_URL, oauth_token_url: Defaults::OAUTH_TOKEN_URL, oauth_scopes: Defaults::OAUTH_SCOPES, skills_autoload: Defaults::SKILLS_AUTOLOAD, chisel_mode: Defaults::CHISEL_MODE }.freeze
- DEFAULT_PROVIDER_MODELS =
Default model tiers per built-in provider. Used by seed_config! and backfill_provider_models! so new and existing configs stay in sync.
{ 'anthropic' => { 'env_key' => 'ANTHROPIC_API_KEY', 'models' => { 'cheap' => 'claude-haiku-4-5', 'mid' => 'claude-sonnet-4-6', 'top' => 'claude-opus-4-8' } }, 'openai' => { 'env_key' => 'OPENAI_API_KEY', 'models' => { 'cheap' => 'gpt-5.4-nano', 'mid' => 'gpt-5.4-mini', 'top' => 'gpt-5.4' } } }.freeze
Instance Attribute Summary collapse
-
#config_path ⇒ Object
readonly
Returns the value of attribute config_path.
-
#data ⇒ Object
readonly
Returns the value of attribute data.
Class Method Summary collapse
-
.test_config_path ⇒ String
A per-pid path under tmpdir used when RUBYN_TESTING is set.
Instance Method Summary collapse
-
#add_provider(name, base_url:, env_key: nil, models: [], pricing: {}, api_format: nil) ⇒ Object
Add or update a provider in the config and persist to disk.
-
#custom_pricing ⇒ Object
Returns all user-configured pricing as { model => [input, output] }.
- #dangerous_patterns ⇒ Object
- #db_file ⇒ Object
- #get(key, default = nil) ⇒ Object
- #home_dir ⇒ Object
-
#initialize(config_path: Defaults::CONFIG_FILE) ⇒ Settings
constructor
A new instance of Settings.
- #memories_dir ⇒ Object
-
#provider_config(name) ⇒ Object
Returns config hash for a custom provider, or nil if not configured.
- #reload! ⇒ Object
- #save! ⇒ Object
- #scrub_env_vars ⇒ Object
- #sessions_dir ⇒ Object
- #set(key, value) ⇒ Object
- #to_h ⇒ Object
- #tokens_file ⇒ Object
Constructor Details
#initialize(config_path: Defaults::CONFIG_FILE) ⇒ Settings
Returns a new instance of Settings.
48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/rubyn_code/config/settings.rb', line 48 def initialize(config_path: Defaults::CONFIG_FILE) # When tests run, isolate Settings from the developer's personal # ~/.rubyn-code/config.yml so a stray `provider: minimax` can't # shadow the test expectations. The test config lives in # tmpdir, is process-pid-scoped, and is harmless if it leaks. config_path = self.class.test_config_path if config_path == Defaults::CONFIG_FILE && ENV['RUBYN_TESTING'] @config_path = config_path @data = {} ensure_home_directory! seed_config! unless File.exist?(@config_path) load! backfill_provider_models! end |
Instance Attribute Details
#config_path ⇒ Object (readonly)
Returns the value of attribute config_path.
46 47 48 |
# File 'lib/rubyn_code/config/settings.rb', line 46 def config_path @config_path end |
#data ⇒ Object (readonly)
Returns the value of attribute data.
46 47 48 |
# File 'lib/rubyn_code/config/settings.rb', line 46 def data @data end |
Class Method Details
.test_config_path ⇒ String
Returns a per-pid path under tmpdir used when RUBYN_TESTING is set.
65 66 67 |
# File 'lib/rubyn_code/config/settings.rb', line 65 def self.test_config_path @test_config_path ||= File.join(Dir.tmpdir, "rubyn-test-config-#{Process.pid}.yml") end |
Instance Method Details
#add_provider(name, base_url:, env_key: nil, models: [], pricing: {}, api_format: nil) ⇒ Object
Add or update a provider in the config and persist to disk.
136 137 138 139 140 141 142 |
# File 'lib/rubyn_code/config/settings.rb', line 136 def add_provider(name, base_url:, env_key: nil, models: [], pricing: {}, api_format: nil) # rubocop:disable Metrics/ParameterLists -- all optional kwargs with defaults @data['providers'] ||= {} @data['providers'][name.to_s] = build_provider_hash( base_url: base_url, env_key: env_key, models: models, pricing: pricing, api_format: api_format ) save! end |
#custom_pricing ⇒ Object
Returns all user-configured pricing as { model => [input, output] }
145 146 147 148 149 150 151 152 |
# File 'lib/rubyn_code/config/settings.rb', line 145 def custom_pricing providers = @data['providers'] return {} unless providers.is_a?(Hash) providers.each_with_object({}) do |(_, cfg), acc| merge_provider_pricing(cfg, acc) end end |
#dangerous_patterns ⇒ Object
113 |
# File 'lib/rubyn_code/config/settings.rb', line 113 def dangerous_patterns = Defaults::DANGEROUS_PATTERNS |
#db_file ⇒ Object
108 |
# File 'lib/rubyn_code/config/settings.rb', line 108 def db_file = Defaults::DB_FILE |
#get(key, default = nil) ⇒ Object
80 81 82 83 |
# File 'lib/rubyn_code/config/settings.rb', line 80 def get(key, default = nil) sym = key.to_sym @data.fetch(key.to_s) { DEFAULT_MAP.fetch(sym, default) } end |
#home_dir ⇒ Object
107 |
# File 'lib/rubyn_code/config/settings.rb', line 107 def home_dir = Defaults::HOME_DIR |
#memories_dir ⇒ Object
111 |
# File 'lib/rubyn_code/config/settings.rb', line 111 def memories_dir = Defaults::MEMORIES_DIR |
#provider_config(name) ⇒ Object
Returns config hash for a custom provider, or nil if not configured. Reads from ‘providers.<name>` in config.yml.
Expected keys: base_url, env_key, models, pricing pricing is a hash of model_name => [input_rate, output_rate]
121 122 123 124 125 126 |
# File 'lib/rubyn_code/config/settings.rb', line 121 def provider_config(name) providers = @data.dig('providers', name.to_s) return nil unless providers.is_a?(Hash) providers.transform_keys(&:to_s) end |
#reload! ⇒ Object
99 100 101 |
# File 'lib/rubyn_code/config/settings.rb', line 99 def reload! load! end |
#save! ⇒ Object
89 90 91 92 93 94 95 96 97 |
# File 'lib/rubyn_code/config/settings.rb', line 89 def save! ensure_home_directory! File.write(@config_path, YAML.dump(@data)) File.chmod(0o600, @config_path) rescue Errno::EACCES => e raise LoadError, "Permission denied writing config to #{@config_path}: #{e.}" rescue SystemCallError => e raise LoadError, "Failed to save config to #{@config_path}: #{e.}" end |
#scrub_env_vars ⇒ Object
114 |
# File 'lib/rubyn_code/config/settings.rb', line 114 def scrub_env_vars = Defaults::SCRUB_ENV_VARS |
#sessions_dir ⇒ Object
110 |
# File 'lib/rubyn_code/config/settings.rb', line 110 def sessions_dir = Defaults::SESSIONS_DIR |
#set(key, value) ⇒ Object
85 86 87 |
# File 'lib/rubyn_code/config/settings.rb', line 85 def set(key, value) @data[key.to_s] = value end |
#to_h ⇒ Object
103 104 105 |
# File 'lib/rubyn_code/config/settings.rb', line 103 def to_h DEFAULT_MAP.transform_keys(&:to_s).merge(@data) end |
#tokens_file ⇒ Object
109 |
# File 'lib/rubyn_code/config/settings.rb', line 109 def tokens_file = Defaults::TOKENS_FILE |