Module: Legion::LLM::Call::ClaudeConfigLoader
- Extended by:
- Legion::Logging::Helper
- Defined in:
- lib/legion/llm/call/claude_config_loader.rb
Constant Summary collapse
- SECRET_URI_PATTERN =
%r{\A(?:env|vault|lease)://}
Class Method Summary collapse
- .anthropic_api_key ⇒ Object
- .apply_api_keys(config) ⇒ Object
- .apply_claude_config(config) ⇒ Object
- .apply_model_preference(config) ⇒ Object
- .bedrock_bearer_token ⇒ Object
- .claude_config_path ⇒ Object
- .claude_settings_path ⇒ Object
- .first_present(*values) ⇒ Object
- .load ⇒ Object
- .merged_config ⇒ Object
- .normalize_secret(value) ⇒ Object
- .oauth_account_available? ⇒ Boolean
- .openai_api_key ⇒ Object
- .provider_config(providers, provider) ⇒ Object
- .read_json(path) ⇒ Object
- .resolve_setting_reference(value) ⇒ Object
- .setting_has_usable_credential?(value) ⇒ Boolean
Class Method Details
.anthropic_api_key ⇒ Object
44 45 46 47 48 49 50 |
# File 'lib/legion/llm/call/claude_config_loader.rb', line 44 def anthropic_api_key config = merged_config first_present( config[:anthropicApiKey], config.dig(:env, :ANTHROPIC_API_KEY) ) end |
.apply_api_keys(config) ⇒ Object
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
# File 'lib/legion/llm/call/claude_config_loader.rb', line 90 def apply_api_keys(config) llm = Legion::LLM::Settings.current_settings providers = Legion::LLM::Settings.config_value(llm, :providers, {}) providers = llm[:providers] = {} unless providers.is_a?(Hash) anthropic_key = first_present(config[:anthropicApiKey], config.dig(:env, :ANTHROPIC_API_KEY)) anthropic = provider_config(providers, :anthropic) if anthropic_key && !setting_has_usable_credential?(Legion::LLM::Settings.config_value(anthropic, :api_key)) anthropic[:api_key] = anthropic_key log.debug 'Imported Anthropic API key from Claude CLI config' end openai_key = first_present(config[:openaiApiKey], config.dig(:env, :OPENAI_API_KEY), config.dig(:env, :CODEX_API_KEY)) openai = provider_config(providers, :openai) if openai_key && !setting_has_usable_credential?(Legion::LLM::Settings.config_value(openai, :api_key)) openai[:api_key] = openai_key log.debug 'Imported OpenAI API key from Claude CLI config' end bedrock_token = bedrock_bearer_token bedrock = provider_config(providers, :bedrock) return unless bedrock_token && !setting_has_usable_credential?(Legion::LLM::Settings.config_value(bedrock, :bearer_token)) bedrock[:bearer_token] = bedrock_token log.debug 'Imported Bedrock bearer token from Claude settings.json env section' end |
.apply_claude_config(config) ⇒ Object
85 86 87 88 |
# File 'lib/legion/llm/call/claude_config_loader.rb', line 85 def apply_claude_config(config) apply_api_keys(config) apply_model_preference(config) end |
.apply_model_preference(config) ⇒ Object
117 118 119 120 121 122 123 124 125 |
# File 'lib/legion/llm/call/claude_config_loader.rb', line 117 def apply_model_preference(config) return unless config[:preferredModel] || config[:model] model = config[:preferredModel] || config[:model] return if Legion::LLM::Settings.value(:default_model) Legion::LLM::Settings.set_value(:default_model, value: model) log.debug "Imported model preference from Claude CLI config: #{model}" end |
.bedrock_bearer_token ⇒ Object
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/legion/llm/call/claude_config_loader.rb', line 61 def bedrock_bearer_token env = read_json(claude_settings_path)[:env] return nil unless env.is_a?(Hash) direct = first_present(env[:AWS_BEARER_TOKEN_BEDROCK], env['AWS_BEARER_TOKEN_BEDROCK']) return direct if direct match = env.find do |key, value| name = key.to_s.upcase next false unless name.include?('AWS') next false unless name.include?('BEARER') next false unless name.include?('TOKEN') next false unless name.include?('BEDROCK') !normalize_secret(value).nil? end normalize_secret(match&.last) end |
.claude_config_path ⇒ Object
20 21 22 |
# File 'lib/legion/llm/call/claude_config_loader.rb', line 20 def claude_config_path File.(Legion::LLM::Settings.value(:claude_cli, :config_path, default: '~/.claude.json')) end |
.claude_settings_path ⇒ Object
16 17 18 |
# File 'lib/legion/llm/call/claude_config_loader.rb', line 16 def claude_settings_path File.(Legion::LLM::Settings.value(:claude_cli, :settings_path, default: '~/.claude/settings.json')) end |
.first_present(*values) ⇒ Object
162 163 164 165 166 167 168 |
# File 'lib/legion/llm/call/claude_config_loader.rb', line 162 def first_present(*values) values.each do |value| normalized = normalize_secret(value) return normalized unless normalized.nil? end nil end |
.load ⇒ Object
24 25 26 27 28 29 |
# File 'lib/legion/llm/call/claude_config_loader.rb', line 24 def load config = merged_config return if config.empty? apply_claude_config(config) end |
.merged_config ⇒ Object
31 32 33 |
# File 'lib/legion/llm/call/claude_config_loader.rb', line 31 def merged_config read_json(claude_settings_path).merge(read_json(claude_config_path)) end |
.normalize_secret(value) ⇒ Object
170 171 172 173 174 175 176 177 178 |
# File 'lib/legion/llm/call/claude_config_loader.rb', line 170 def normalize_secret(value) return nil if value.nil? return value unless value.is_a?(String) normalized = value.strip return nil if normalized.empty? normalized end |
.oauth_account_available? ⇒ Boolean
80 81 82 83 |
# File 'lib/legion/llm/call/claude_config_loader.rb', line 80 def oauth_account_available? oauth = read_json(claude_config_path)[:oauthAccount] oauth.is_a?(Hash) && oauth.any? { |_k, value| !normalize_secret(value).nil? } end |
.openai_api_key ⇒ Object
52 53 54 55 56 57 58 59 |
# File 'lib/legion/llm/call/claude_config_loader.rb', line 52 def openai_api_key config = merged_config first_present( config[:openaiApiKey], config.dig(:env, :OPENAI_API_KEY), config.dig(:env, :CODEX_API_KEY) ) end |
.provider_config(providers, provider) ⇒ Object
127 128 129 130 131 132 |
# File 'lib/legion/llm/call/claude_config_loader.rb', line 127 def provider_config(providers, provider) config = Legion::LLM::Settings.config_value(providers, provider, {}) return config if config.is_a?(Hash) providers[provider] = {} end |
.read_json(path) ⇒ Object
35 36 37 38 39 40 41 42 |
# File 'lib/legion/llm/call/claude_config_loader.rb', line 35 def read_json(path) return {} unless File.exist?(path) ::JSON.parse(File.read(path), symbolize_names: true) rescue StandardError => e handle_exception(e, level: :debug) {} end |
.resolve_setting_reference(value) ⇒ Object
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
# File 'lib/legion/llm/call/claude_config_loader.rb', line 138 def resolve_setting_reference(value) case value when Array value.each do |entry| resolved = resolve_setting_reference(entry) return resolved unless resolved.nil? end nil when String resolved = normalize_secret(value) return nil if resolved.nil? if resolved.start_with?('env://') env_name = resolved.sub('env://', '') return normalize_secret(ENV.fetch(env_name, nil)) end return nil if resolved.match?(SECRET_URI_PATTERN) resolved else normalize_secret(value) end end |
.setting_has_usable_credential?(value) ⇒ Boolean
134 135 136 |
# File 'lib/legion/llm/call/claude_config_loader.rb', line 134 def setting_has_usable_credential?(value) !resolve_setting_reference(value).nil? end |