Current section

Files

Jump to
codex_sdk lib codex runtime env.ex
Raw

lib/codex/runtime/env.ex

defmodule Codex.Runtime.Env do
@moduledoc """
Subprocess environment construction (originator override, API key forwarding).
"""
alias Codex.Config.BaseURL
alias Codex.Net.CA
@originator_env "CODEX_INTERNAL_ORIGINATOR_OVERRIDE"
@sdk_originator "codex_sdk_elixir"
@spec base_overrides(String.t() | nil, String.t() | nil) :: map()
def base_overrides(api_key, base_url) do
%{}
|> maybe_put("CODEX_API_KEY", api_key)
|> maybe_put("OPENAI_API_KEY", api_key)
|> maybe_put_openai_base_url(base_url)
|> Map.merge(CA.env_overrides())
|> Map.put_new(@originator_env, @sdk_originator)
end
@doc false
@spec normalize_overrides(map() | keyword() | nil) ::
{:ok, map()} | {:error, {:invalid_env, term()}}
def normalize_overrides(env) when env in [%{}, nil, []], do: {:ok, %{}}
def normalize_overrides(env) when is_map(env) do
{:ok, stringify_map(env)}
end
def normalize_overrides(env) when is_list(env) do
if Keyword.keyword?(env) do
{:ok, env |> Map.new() |> stringify_map()}
else
{:error, {:invalid_env, env}}
end
end
def normalize_overrides(env), do: {:error, {:invalid_env, env}}
@spec to_charlist_env(map()) :: [{String.t(), String.t()}]
def to_charlist_env(env) when is_map(env) do
Enum.map(env, fn {key, value} -> {to_string(key), to_string(value)} end)
end
@spec maybe_put(map(), String.t(), String.t() | nil) :: map()
def maybe_put(env, _key, nil), do: env
def maybe_put(env, _key, ""), do: env
def maybe_put(env, key, value), do: Map.put(env, key, to_string(value))
@spec maybe_put_openai_base_url(map(), String.t() | nil) :: map()
def maybe_put_openai_base_url(env, base_url) do
default_base_url = BaseURL.default()
case normalize(base_url) do
nil -> env
url when url == default_base_url -> env
url -> Map.put(env, "OPENAI_BASE_URL", url)
end
end
defp normalize(nil), do: nil
defp normalize(value) when is_binary(value) do
value = String.trim(value)
if value == "", do: nil, else: value
end
defp normalize(value), do: to_string(value)
defp stringify_map(map) do
map
|> Enum.reject(fn {_key, value} -> is_nil(value) end)
|> Enum.into(%{}, fn {key, value} -> {to_string(key), to_string(value)} end)
end
end