fix: forgot to lint/format

This commit is contained in:
2026-01-01 03:57:37 +01:00
parent c50091f6bf
commit ab1df3dd0f
13 changed files with 58 additions and 41 deletions

View File

@@ -1,6 +1,7 @@
"""Agent module for media library management."""
from .agent import Agent
from alfred.settings import settings
from .agent import Agent
__all__ = ["Agent", "settings"]

View File

@@ -6,8 +6,8 @@ from collections.abc import AsyncGenerator
from typing import Any
from alfred.infrastructure.persistence import get_memory
from alfred.settings import settings
from .prompts import PromptBuilder
from .registry import Tool, make_tools

View File

@@ -6,7 +6,8 @@ from typing import Any
import requests
from requests.exceptions import HTTPError, RequestException, Timeout
from alfred.settings import settings, Settings
from alfred.settings import Settings, settings
from .exceptions import LLMAPIError, LLMConfigurationError
logger = logging.getLogger(__name__)

View File

@@ -1,13 +1,13 @@
"""Ollama LLM client with robust error handling."""
import logging
import os
from typing import Any
import requests
from requests.exceptions import HTTPError, RequestException, Timeout
from alfred.settings import Settings, settings
from alfred.settings import Settings
from .exceptions import LLMAPIError, LLMConfigurationError
logger = logging.getLogger(__name__)

View File

@@ -2,23 +2,21 @@
import json
import logging
import os
import time
import uuid
from pathlib import Path
from typing import Any
from fastapi import FastAPI, HTTPException
from fastapi.responses import JSONResponse, StreamingResponse
from fastapi.staticfiles import StaticFiles
from pathlib import Path
from pydantic import BaseModel, Field, validator
from alfred.agent.agent import Agent
from alfred.agent.llm.deepseek import DeepSeekClient
from alfred.agent.llm.exceptions import LLMAPIError, LLMConfigurationError
from alfred.agent.llm.ollama import OllamaClient
from alfred.settings import settings
from alfred.infrastructure.persistence import get_memory, init_memory
from alfred.settings import settings
logging.basicConfig(
level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
@@ -55,7 +53,9 @@ except LLMConfigurationError as e:
raise
# Initialize agent
agent = Agent(settings=settings, llm=llm, max_tool_iterations=settings.max_tool_iterations)
agent = Agent(
settings=settings, llm=llm, max_tool_iterations=settings.max_tool_iterations
)
logger.info("Agent Media API initialized")

View File

@@ -1,9 +1,10 @@
import secrets
import tomllib
from pathlib import Path
from typing import NamedTuple
import tomllib
from pydantic import Field, computed_field, field_validator
from pydantic_settings import BaseSettings, SettingsConfigDict
from typing import NamedTuple, Optional
BASE_DIR = Path(__file__).resolve().parent.parent
ENV_FILE_PATH = BASE_DIR / ".env"
@@ -12,13 +13,16 @@ toml_path = BASE_DIR / "pyproject.toml"
class ConfigurationError(Exception):
"""Raised when configuration is invalid."""
pass
class ProjectVersions(NamedTuple):
"""
Immutable structure for project versions.
Forces explicit naming and prevents accidental swaps.
"""
librechat: str
rag: str
@@ -37,20 +41,22 @@ def get_versions_from_toml() -> ProjectVersions:
try:
return ProjectVersions(
librechat=data["tool"]["alfred"]["settings"]["librechat_version"],
rag = data["tool"]["alfred"]["settings"]["rag_version"]
rag=data["tool"]["alfred"]["settings"]["rag_version"],
)
except KeyError as e:
raise KeyError(f"Error: Missing key {e} in pyproject.toml")
raise KeyError(f"Error: Missing key {e} in pyproject.toml") from e
# Load versions once
VERSIONS: ProjectVersions = get_versions_from_toml()
class Settings(BaseSettings):
model_config = SettingsConfigDict(
env_file=ENV_FILE_PATH,
env_file_encoding="utf-8",
extra="ignore",
case_sensitive=False
case_sensitive=False,
)
# --- GENERAL SETTINGS ---
host: str = "0.0.0.0"
@@ -71,11 +77,11 @@ class Settings(BaseSettings):
deepseek_model: str = "deepseek-chat"
# --- API KEYS ---
anthropic_api_key: Optional[str] = Field(None, description="Claude API key")
deepseek_api_key: Optional[str] = Field(None, description="Deepseek API key")
google_api_key: Optional[str] = Field(None, description="Gemini API key")
kimi_api_key: Optional[str] = Field(None, description="Kimi API key")
openai_api_key: Optional[str] = Field(None, description="ChatGPT API key")
anthropic_api_key: str | None = Field(None, description="Claude API key")
deepseek_api_key: str | None = Field(None, description="Deepseek API key")
google_api_key: str | None = Field(None, description="Gemini API key")
kimi_api_key: str | None = Field(None, description="Kimi API key")
openai_api_key: str | None = Field(None, description="ChatGPT API key")
# --- SECURITY KEYS ---
# Generated automatically if not in .env to ensure "Secure by Default"
@@ -93,8 +99,9 @@ class Settings(BaseSettings):
mongo_host: str = "mongodb"
mongo_user: str = "alfred"
mongo_password: str = Field(default_factory=lambda: secrets.token_urlsafe(24),
repr=False, exclude=True)
mongo_password: str = Field(
default_factory=lambda: secrets.token_urlsafe(24), repr=False, exclude=True
)
mongo_port: int = 27017
mongo_db_name: str = "alfred"
@@ -109,8 +116,9 @@ class Settings(BaseSettings):
postgres_host: str = "vectordb"
postgres_user: str = "alfred"
postgres_password: str = Field(default_factory=lambda: secrets.token_urlsafe(24),
repr=False, exclude=True)
postgres_password: str = Field(
default_factory=lambda: secrets.token_urlsafe(24), repr=False, exclude=True
)
postgres_port: int = 5432
postgres_db_name: str = "alfred"
@@ -122,7 +130,7 @@ class Settings(BaseSettings):
f"@{self.postgres_host}:{self.postgres_port}/{self.postgres_db_name}"
)
tmdb_api_key: Optional[str] = Field(None, description="The Movie Database API key")
tmdb_api_key: str | None = Field(None, description="The Movie Database API key")
tmdb_base_url: str = "https://api.themoviedb.org/3"
# --- LLM PICKER & CONFIG ---
@@ -147,7 +155,7 @@ class Settings(BaseSettings):
meili_master_key: str = Field(
default_factory=lambda: secrets.token_urlsafe(32),
description="Master key for Meilisearch",
repr=False
repr=False,
)
# --- VALIDATORS ---
@@ -155,21 +163,27 @@ class Settings(BaseSettings):
@classmethod
def validate_temperature(cls, v: float) -> float:
if not 0.0 <= v <= 2.0:
raise ConfigurationError(f"Temperature must be between 0.0 and 2.0, got {v}")
raise ConfigurationError(
f"Temperature must be between 0.0 and 2.0, got {v}"
)
return v
@field_validator("max_tool_iterations")
@classmethod
def validate_max_iterations(cls, v: int) -> int:
if not 1 <= v <= 20:
raise ConfigurationError(f"max_tool_iterations must be between 1 and 50, got {v}")
raise ConfigurationError(
f"max_tool_iterations must be between 1 and 50, got {v}"
)
return v
@field_validator("request_timeout")
@classmethod
def validate_timeout(cls, v: int) -> int:
if not 1 <= v <= 300:
raise ConfigurationError(f"request_timeout must be between 1 and 300 seconds, got {v}")
raise ConfigurationError(
f"request_timeout must be between 1 and 300 seconds, got {v}"
)
return v
@field_validator("deepseek_base_url", "tmdb_base_url")
@@ -188,4 +202,5 @@ class Settings(BaseSettings):
def dump_safe(self):
return self.model_dump(exclude_none=False)
settings = Settings()

View File

@@ -11,9 +11,8 @@ from unittest.mock import MagicMock, Mock
import pytest
from alfred.settings import Settings, settings
from alfred.infrastructure.persistence import Memory, set_memory
from alfred.settings import settings
@pytest.fixture

View File

@@ -2,7 +2,6 @@
from unittest.mock import Mock
from conftest import mock_llm
from alfred.agent.agent import Agent
from alfred.infrastructure.persistence import get_memory
@@ -142,7 +141,9 @@ class TestStep:
assert history[0]["content"] == "Hi there"
assert history[1]["role"] == "assistant"
def test_step_with_tool_call(self, memory, mock_settings, mock_llm_with_tool_call, real_folder):
def test_step_with_tool_call(
self, memory, mock_settings, mock_llm_with_tool_call, real_folder
):
"""Should execute tool and continue."""
memory.ltm.set_config("download_folder", str(real_folder["downloads"]))

View File

@@ -7,7 +7,6 @@ import pytest
from alfred.agent.agent import Agent
from alfred.infrastructure.persistence import get_memory
from alfred.settings import settings
from conftest import mock_llm
class TestExecuteToolCallEdgeCases:

View File

@@ -1,8 +1,8 @@
"""Edge case tests for FastAPI endpoints."""
import pytest
from unittest.mock import Mock, patch
import pytest
from fastapi.testclient import TestClient

View File

@@ -2,7 +2,7 @@
import pytest
from alfred.settings import Settings, ConfigurationError
from alfred.settings import ConfigurationError, Settings
class TestConfigValidation:

View File

@@ -5,13 +5,13 @@ from unittest.mock import patch
import pytest
from alfred.settings import Settings, ConfigurationError
from alfred.agent.parameters import (
REQUIRED_PARAMETERS,
ParameterSchema,
format_parameters_for_prompt,
get_missing_required_parameters,
)
from alfred.settings import ConfigurationError, Settings
class TestSettingsEdgeCases:

View File

@@ -4,6 +4,7 @@ from alfred.agent.prompts import PromptBuilder
from alfred.agent.registry import make_tools
from alfred.settings import settings
class TestPromptBuilderEdgeCases:
"""Edge case tests for PromptBuilder."""