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
- .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 |
# File 'lib/legion/llm/call/claude_config_loader.rb', line 90 def apply_api_keys(config) llm = Legion::LLM.settings providers = llm[:providers] anthropic_key = first_present(config[:anthropicApiKey], config.dig(:env, :ANTHROPIC_API_KEY)) if anthropic_key && !setting_has_usable_credential?(providers.dig(:anthropic, :api_key)) providers[: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)) if openai_key && !setting_has_usable_credential?(providers.dig(:openai, :api_key)) providers[:openai][:api_key] = openai_key log.debug 'Imported OpenAI API key from Claude CLI config' end bedrock_token = bedrock_bearer_token return unless bedrock_token && !setting_has_usable_credential?(providers.dig(:bedrock, :bearer_token)) providers[: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
113 114 115 116 117 118 119 120 121 122 |
# File 'lib/legion/llm/call/claude_config_loader.rb', line 113 def apply_model_preference(config) return unless config[:preferredModel] || config[:model] model = config[:preferredModel] || config[:model] llm = Legion::LLM.settings return if llm[:default_model] llm[:default_model] = 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.dig(:claude_cli, :config_path) || '~/.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.dig(:claude_cli, :settings_path) || '~/.claude/settings.json') end |
.first_present(*values) ⇒ Object
152 153 154 155 156 157 158 |
# File 'lib/legion/llm/call/claude_config_loader.rb', line 152 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
160 161 162 163 164 165 166 167 168 |
# File 'lib/legion/llm/call/claude_config_loader.rb', line 160 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 |
.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
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
# File 'lib/legion/llm/call/claude_config_loader.rb', line 128 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
124 125 126 |
# File 'lib/legion/llm/call/claude_config_loader.rb', line 124 def setting_has_usable_credential?(value) !resolve_setting_reference(value).nil? end |