Class: Ace::LLM::Atoms::EnvReader

Inherits:
Object
  • Object
show all
Defined in:
lib/ace/llm/atoms/env_reader.rb

Overview

EnvReader provides environment variable reading utilities This is an atom - it has no dependencies on other parts of this gem

Class Method Summary collapse

Class Method Details

.get(key, default = nil) ⇒ String?

Get an environment variable value

Parameters:

  • key (String)

    Environment variable name

  • default (String, nil) (defaults to: nil)

    Default value if not found

Returns:

  • (String, nil)

    The environment variable value or default



33
34
35
# File 'lib/ace/llm/atoms/env_reader.rb', line 33

def self.get(key, default = nil)
  ENV.fetch(key, default)
end

.get!(key) ⇒ String

Get an environment variable value, raising if not found

Parameters:

  • key (String)

    Environment variable name

Returns:

  • (String)

    The environment variable value

Raises:

  • (KeyError)

    If the environment variable is not set



41
42
43
44
45
# File 'lib/ace/llm/atoms/env_reader.rb', line 41

def self.get!(key)
  ENV.fetch(key)
rescue KeyError
  raise KeyError, "Environment variable '#{key}' is not set"
end

.get_api_key(provider) ⇒ String?

Get API key for a provider from environment Uses ace-core to check ENV and .ace/.env cascade

Parameters:

  • provider (String)

    Provider name (e.g., “google”, “openai”)

Returns:

  • (String, nil)

    API key if found



116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/ace/llm/atoms/env_reader.rb', line 116

def self.get_api_key(provider)
  # Determine which keys to look for based on provider
  key_names = case provider.downcase
  when "google", "gemini"
    ["GEMINI_API_KEY", "GOOGLE_API_KEY"]
  when "groq"
    ["GROQ_API_KEY"]
  when "openai"
    ["OPENAI_API_KEY"]
  when "anthropic"
    ["ANTHROPIC_API_KEY"]
  when "mistral"
    ["MISTRAL_API_KEY"]
  when "together", "togetherai"
    ["TOGETHER_API_KEY", "TOGETHERAI_API_KEY"]
  when "lmstudio"
    return nil # No API key needed for local
  when "xai"
    ["XAI_API_KEY"]
  when "openrouter"
    ["OPENROUTER_API_KEY"]
  else
    # Try generic pattern
    ["#{provider.upcase}_API_KEY"]
  end

  # Use ace-core to check each key (it checks ENV first, then cascade)
  return nil unless defined?(Ace::Core)

  key_names.each do |key_name|
    value = Ace::Core.get_env(key_name)
    return value if value && !value.strip.empty?
  end

  nil
end

.get_matching(pattern) ⇒ Hash<String, String>

Get all environment variables matching a pattern

Parameters:

  • pattern (Regexp, String)

    Pattern to match (String will be used as prefix)

Returns:

  • (Hash<String, String>)

    Matching environment variables



77
78
79
80
81
# File 'lib/ace/llm/atoms/env_reader.rb', line 77

def self.get_matching(pattern)
  pattern = /^#{Regexp.escape(pattern)}/ if pattern.is_a?(String)

  ENV.select { |key, _| key =~ pattern }
end

.get_multiple(keys, prefix: nil) ⇒ Hash<String, String>

Get multiple environment variables as a hash

Parameters:

  • keys (Array<String>)

    List of environment variable names

  • prefix (String, nil) (defaults to: nil)

    Optional prefix to prepend to each key

Returns:

  • (Hash<String, String>)

    Hash of key-value pairs (only includes set variables)



66
67
68
69
70
71
72
# File 'lib/ace/llm/atoms/env_reader.rb', line 66

def self.get_multiple(keys, prefix: nil)
  keys.each_with_object({}) do |key, hash|
    full_key = prefix ? "#{prefix}#{key}" : key
    value = ENV[full_key]
    hash[key] = value if value
  end
end

.load_env_cascade(set_env: false) ⇒ Hash

Deprecated.

Use Ace::Core.get_env for individual keys

DEPRECATED

Use Ace::Core.get_env instead

Load .env files from .ace cascade

Parameters:

  • set_env (Boolean) (defaults to: false)

    Whether to set loaded vars to ENV

Returns:

  • (Hash)

    All loaded environment variables



14
15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/ace/llm/atoms/env_reader.rb', line 14

def self.load_env_cascade(set_env: false)
  return {} unless defined?(Ace::Core)

  warn "[DEPRECATION] EnvReader.load_env_cascade is deprecated. Use Ace::Core.get_env instead" if ENV["DEBUG"]

  # Delegate to ace-core
  loaded_vars = Ace::Core::Molecules::EnvLoader.load_cascade

  if set_env
    Ace::Core::Molecules::EnvLoader.set_environment(loaded_vars, overwrite: true)
  end

  loaded_vars
end

.present?(key) ⇒ Boolean

Check if an environment variable is set and not empty

Parameters:

  • key (String)

    Environment variable name

Returns:

  • (Boolean)

    True if the variable is set and not empty



57
58
59
60
# File 'lib/ace/llm/atoms/env_reader.rb', line 57

def self.present?(key)
  value = ENV[key]
  !value.nil? && !value.strip.empty?
end

.set?(key) ⇒ Boolean

Check if an environment variable is set

Parameters:

  • key (String)

    Environment variable name

Returns:

  • (Boolean)

    True if the variable is set, false otherwise



50
51
52
# File 'lib/ace/llm/atoms/env_reader.rb', line 50

def self.set?(key)
  ENV.key?(key)
end

.with_env(vars) { ... } ⇒ Object

Temporarily set environment variables for a block

Parameters:

  • vars (Hash<String, String>)

    Variables to set temporarily

Yields:

  • Block to execute with temporary variables

Returns:

  • (Object)

    The return value of the block



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/ace/llm/atoms/env_reader.rb', line 87

def self.with_env(vars)
  original_values = {}

  # Store original values and set new ones
  vars.each do |key, value|
    original_values[key] = ENV[key]
    if value.nil?
      ENV.delete(key)
    else
      ENV[key] = value.to_s
    end
  end

  yield
ensure
  # Restore original values
  original_values.each do |key, value|
    if value.nil?
      ENV.delete(key)
    else
      ENV[key] = value
    end
  end
end