67 lines
2.4 KiB
Python
67 lines
2.4 KiB
Python
from __future__ import annotations
|
|
|
|
import os
|
|
from dataclasses import dataclass
|
|
from pathlib import Path
|
|
from typing import Iterable, Optional
|
|
|
|
from dotenv import load_dotenv
|
|
|
|
|
|
DEFAULT_ENV_FILENAMES = (".env",)
|
|
|
|
|
|
@dataclass(slots=True)
|
|
class CoreAgentConfig:
|
|
model: str
|
|
api_key: Optional[str]
|
|
base_url: Optional[str]
|
|
timeout: float = 120.0
|
|
|
|
|
|
def load_core_agent_env(env_dir: str | Path | None = None) -> Optional[Path]:
|
|
"""Load a local .env file for the standalone core_agent package."""
|
|
root = Path(env_dir).resolve() if env_dir is not None else Path(__file__).resolve().parent
|
|
for filename in DEFAULT_ENV_FILENAMES:
|
|
env_path = root / filename
|
|
if env_path.is_file():
|
|
load_dotenv(env_path, override=False)
|
|
return env_path
|
|
return None
|
|
|
|
|
|
def build_core_agent_config(env: Optional[dict[str, str]] = None) -> CoreAgentConfig:
|
|
values = env if env is not None else os.environ
|
|
model = _first_nonempty(values, ("CORE_AGENT_MODEL", "MODEL_NAME", "OPENAI_MODEL", "MODEL"), "gpt-4.1-mini")
|
|
api_key = _first_nonempty(values, ("OPENAI_API_KEY", "API_KEY"))
|
|
base_url = _first_nonempty(values, ("OPENAI_BASE_URL", "BASE_URL"))
|
|
timeout_raw = _first_nonempty(values, ("CORE_AGENT_TIMEOUT", "OPENAI_TIMEOUT", "REQUEST_TIMEOUT"), "120")
|
|
try:
|
|
timeout = float(timeout_raw) if timeout_raw is not None else 120.0
|
|
except (TypeError, ValueError):
|
|
timeout = 120.0
|
|
return CoreAgentConfig(model=model, api_key=api_key, base_url=base_url, timeout=timeout)
|
|
|
|
|
|
def apply_compat_env_aliases(env: Optional[dict[str, str]] = None) -> None:
|
|
"""Mirror Myagent-style env names into OpenAI-compatible names when absent."""
|
|
values = env if env is not None else os.environ
|
|
_set_if_missing(values, "OPENAI_API_KEY", _first_nonempty(values, ("API_KEY",)))
|
|
_set_if_missing(values, "OPENAI_BASE_URL", _first_nonempty(values, ("BASE_URL",)))
|
|
_set_if_missing(values, "CORE_AGENT_MODEL", _first_nonempty(values, ("MODEL_NAME", "MODEL")))
|
|
|
|
|
|
def _first_nonempty(values: dict[str, str], keys: Iterable[str], default: Optional[str] = None) -> Optional[str]:
|
|
for key in keys:
|
|
value = values.get(key)
|
|
if value is not None and str(value).strip():
|
|
return str(value).strip()
|
|
return default
|
|
|
|
|
|
def _set_if_missing(values: dict[str, str], key: str, value: Optional[str]) -> None:
|
|
if value is None:
|
|
return
|
|
if not values.get(key):
|
|
values[key] = value
|