converted line endings from windows to unix

This commit is contained in:
Your Name 2025-11-26 16:29:17 -08:00
parent fc7bffaf4d
commit bee371eae1
4 changed files with 1582 additions and 1582 deletions

74
.gitignore vendored
View file

@ -1,37 +1,37 @@
# Ignore everything
*
# But descend into directories
!*/
# Recursively allow files under subtree
!/.github/**
!/aider/**
!/benchmark/**
!/docker/**
!/requirements/**
!/scripts/**
!/tests/**
# Specific Files
!/.dockerignore
!/.flake8
!/.gitignore
!/.pre-commit-config.yaml
!/CHANGELOG.md
!/CNAME
!/CONTRIBUTING.metadata
!/HISTORY.md
!/LICENSE.txt
!/MANIFEST.in
!/pyproject.toml
!/pytest.ini
!/README.md
!/requirements.txt
# Ignore specific files
aider/__version__.py
aider/_version.py
*.pyc
.aider*
env/
# Ignore everything
*
# But descend into directories
!*/
# Recursively allow files under subtree
!/.github/**
!/aider/**
!/benchmark/**
!/docker/**
!/requirements/**
!/scripts/**
!/tests/**
# Specific Files
!/.dockerignore
!/.flake8
!/.gitignore
!/.pre-commit-config.yaml
!/CHANGELOG.md
!/CNAME
!/CONTRIBUTING.metadata
!/HISTORY.md
!/LICENSE.txt
!/MANIFEST.in
!/pyproject.toml
!/pytest.ini
!/README.md
!/requirements.txt
# Ignore specific files
aider/__version__.py
aider/_version.py
*.pyc
.aider*
env/

View file

@ -1,115 +1,115 @@
from dataclasses import dataclass
from aider.dump import dump # noqa: F401
@dataclass
class ExInfo:
name: str
retry: bool
description: str
EXCEPTIONS = [
ExInfo("APIConnectionError", True, None),
ExInfo("APIError", True, None),
ExInfo("APIResponseValidationError", True, None),
ExInfo(
"AuthenticationError",
False,
"The API provider is not able to authenticate you. Check your API key.",
),
ExInfo("AzureOpenAIError", True, None),
ExInfo("BadGatewayError", False, None),
ExInfo("BadRequestError", False, None),
ExInfo("BudgetExceededError", True, None),
ExInfo(
"ContentPolicyViolationError",
True,
"The API provider has refused the request due to a safety policy about the content.",
),
ExInfo("ContextWindowExceededError", False, None), # special case handled in base_coder
ExInfo("ErrorEventError", True, None),
ExInfo("ImageFetchError", True, "The API cannot fetch an image"),
ExInfo("InternalServerError", True, "The API provider's servers are down or overloaded."),
ExInfo("InvalidRequestError", True, None),
ExInfo("JSONSchemaValidationError", True, None),
ExInfo("NotFoundError", False, None),
ExInfo("OpenAIError", True, None),
ExInfo(
"RateLimitError",
True,
"The API provider has rate limited you. Try again later or check your quotas.",
),
ExInfo("RouterRateLimitError", True, None),
ExInfo("ServiceUnavailableError", True, "The API provider's servers are down or overloaded."),
ExInfo("UnprocessableEntityError", True, None),
ExInfo("UnsupportedParamsError", True, None),
ExInfo(
"Timeout",
True,
"The API provider timed out without returning a response. They may be down or overloaded.",
),
]
class LiteLLMExceptions:
exceptions = dict()
exception_info = {exi.name: exi for exi in EXCEPTIONS}
def __init__(self):
self._load()
def _load(self, strict=False):
import litellm
for var in dir(litellm):
if var.endswith("Error"):
if var not in self.exception_info:
raise ValueError(f"{var} is in litellm but not in aider's exceptions list")
for var in self.exception_info:
ex = getattr(litellm, var, "default")
if ex != "default":
if not issubclass(ex, BaseException):
continue
self.exceptions[ex] = self.exception_info[var]
def exceptions_tuple(self):
return tuple(self.exceptions)
def get_ex_info(self, ex):
"""Return the ExInfo for a given exception instance"""
import litellm
if ex.__class__ is litellm.APIConnectionError:
if "google.auth" in str(ex):
return ExInfo(
"APIConnectionError", False, "You need to: pip install google-generativeai"
)
if "boto3" in str(ex):
return ExInfo("APIConnectionError", False, "You need to: pip install boto3")
if "OpenrouterException" in str(ex) and "'choices'" in str(ex):
return ExInfo(
"APIConnectionError",
True,
(
"OpenRouter or the upstream API provider is down, overloaded or rate"
" limiting your requests."
),
)
# Check for specific non-retryable APIError cases like insufficient credits
if ex.__class__ is litellm.APIError:
err_str = str(ex).lower()
if "insufficient credits" in err_str and '"code":402' in err_str:
return ExInfo(
"APIError",
False,
"Insufficient credits with the API provider. Please add credits.",
)
# Fall through to default APIError handling if not the specific credits error
return self.exceptions.get(ex.__class__, ExInfo(None, None, None))
from dataclasses import dataclass
from aider.dump import dump # noqa: F401
@dataclass
class ExInfo:
name: str
retry: bool
description: str
EXCEPTIONS = [
ExInfo("APIConnectionError", True, None),
ExInfo("APIError", True, None),
ExInfo("APIResponseValidationError", True, None),
ExInfo(
"AuthenticationError",
False,
"The API provider is not able to authenticate you. Check your API key.",
),
ExInfo("AzureOpenAIError", True, None),
ExInfo("BadGatewayError", False, None),
ExInfo("BadRequestError", False, None),
ExInfo("BudgetExceededError", True, None),
ExInfo(
"ContentPolicyViolationError",
True,
"The API provider has refused the request due to a safety policy about the content.",
),
ExInfo("ContextWindowExceededError", False, None), # special case handled in base_coder
ExInfo("ErrorEventError", True, None),
ExInfo("ImageFetchError", True, "The API cannot fetch an image"),
ExInfo("InternalServerError", True, "The API provider's servers are down or overloaded."),
ExInfo("InvalidRequestError", True, None),
ExInfo("JSONSchemaValidationError", True, None),
ExInfo("NotFoundError", False, None),
ExInfo("OpenAIError", True, None),
ExInfo(
"RateLimitError",
True,
"The API provider has rate limited you. Try again later or check your quotas.",
),
ExInfo("RouterRateLimitError", True, None),
ExInfo("ServiceUnavailableError", True, "The API provider's servers are down or overloaded."),
ExInfo("UnprocessableEntityError", True, None),
ExInfo("UnsupportedParamsError", True, None),
ExInfo(
"Timeout",
True,
"The API provider timed out without returning a response. They may be down or overloaded.",
),
]
class LiteLLMExceptions:
exceptions = dict()
exception_info = {exi.name: exi for exi in EXCEPTIONS}
def __init__(self):
self._load()
def _load(self, strict=False):
import litellm
for var in dir(litellm):
if var.endswith("Error"):
if var not in self.exception_info:
raise ValueError(f"{var} is in litellm but not in aider's exceptions list")
for var in self.exception_info:
ex = getattr(litellm, var, "default")
if ex != "default":
if not issubclass(ex, BaseException):
continue
self.exceptions[ex] = self.exception_info[var]
def exceptions_tuple(self):
return tuple(self.exceptions)
def get_ex_info(self, ex):
"""Return the ExInfo for a given exception instance"""
import litellm
if ex.__class__ is litellm.APIConnectionError:
if "google.auth" in str(ex):
return ExInfo(
"APIConnectionError", False, "You need to: pip install google-generativeai"
)
if "boto3" in str(ex):
return ExInfo("APIConnectionError", False, "You need to: pip install boto3")
if "OpenrouterException" in str(ex) and "'choices'" in str(ex):
return ExInfo(
"APIConnectionError",
True,
(
"OpenRouter or the upstream API provider is down, overloaded or rate"
" limiting your requests."
),
)
# Check for specific non-retryable APIError cases like insufficient credits
if ex.__class__ is litellm.APIError:
err_str = str(ex).lower()
if "insufficient credits" in err_str and '"code":402' in err_str:
return ExInfo(
"APIError",
False,
"Insufficient credits with the API provider. Please add credits.",
)
# Fall through to default APIError handling if not the specific credits error
return self.exceptions.get(ex.__class__, ExInfo(None, None, None))

File diff suppressed because it is too large Load diff

View file

@ -1,97 +1,97 @@
from aider.exceptions import ExInfo, LiteLLMExceptions
def test_litellm_exceptions_load():
"""Test that LiteLLMExceptions loads without errors"""
ex = LiteLLMExceptions()
assert len(ex.exceptions) > 0
def test_exceptions_tuple():
"""Test that exceptions_tuple returns a non-empty tuple"""
ex = LiteLLMExceptions()
assert isinstance(ex.exceptions_tuple(), tuple)
assert len(ex.exceptions_tuple()) > 0
def test_get_ex_info():
"""Test get_ex_info returns correct ExInfo"""
ex = LiteLLMExceptions()
# Test with a known exception type
from litellm import AuthenticationError
auth_error = AuthenticationError(
message="Invalid API key", llm_provider="openai", model="gpt-4"
)
ex_info = ex.get_ex_info(auth_error)
assert isinstance(ex_info, ExInfo)
assert ex_info.name == "AuthenticationError"
assert ex_info.retry is False
assert "API key" in ex_info.description
# Test with unknown exception type
class UnknownError(Exception):
pass
unknown = UnknownError()
ex_info = ex.get_ex_info(unknown)
assert isinstance(ex_info, ExInfo)
assert ex_info.name is None
assert ex_info.retry is None
assert ex_info.description is None
def test_rate_limit_error():
"""Test specific handling of RateLimitError"""
ex = LiteLLMExceptions()
from litellm import RateLimitError
rate_error = RateLimitError(message="Rate limit exceeded", llm_provider="openai", model="gpt-4")
ex_info = ex.get_ex_info(rate_error)
assert ex_info.retry is True
assert "rate limited" in ex_info.description.lower()
def test_bad_gateway_error():
"""Test specific handling of BadGatewayError"""
ex = LiteLLMExceptions()
from litellm import BadGatewayError
bad_gateway_error = BadGatewayError(
message="Bad Gateway", llm_provider="openai", model="gpt-4"
)
ex_info = ex.get_ex_info(bad_gateway_error)
assert ex_info.retry is True
assert ex_info.name == "BadGatewayError"
def test_context_window_error():
"""Test specific handling of ContextWindowExceededError"""
ex = LiteLLMExceptions()
from litellm import ContextWindowExceededError
ctx_error = ContextWindowExceededError(
message="Context length exceeded", model="gpt-4", llm_provider="openai"
)
ex_info = ex.get_ex_info(ctx_error)
assert ex_info.retry is False
def test_openrouter_error():
"""Test specific handling of OpenRouter API errors"""
ex = LiteLLMExceptions()
from litellm import APIConnectionError
# Create an APIConnectionError with OpenrouterException message
openrouter_error = APIConnectionError(
message="APIConnectionError: OpenrouterException - 'choices'",
model="openrouter/model",
llm_provider="openrouter",
)
ex_info = ex.get_ex_info(openrouter_error)
assert ex_info.retry is True
assert "OpenRouter" in ex_info.description
assert "overloaded" in ex_info.description
assert "rate" in ex_info.description
from aider.exceptions import ExInfo, LiteLLMExceptions
def test_litellm_exceptions_load():
"""Test that LiteLLMExceptions loads without errors"""
ex = LiteLLMExceptions()
assert len(ex.exceptions) > 0
def test_exceptions_tuple():
"""Test that exceptions_tuple returns a non-empty tuple"""
ex = LiteLLMExceptions()
assert isinstance(ex.exceptions_tuple(), tuple)
assert len(ex.exceptions_tuple()) > 0
def test_get_ex_info():
"""Test get_ex_info returns correct ExInfo"""
ex = LiteLLMExceptions()
# Test with a known exception type
from litellm import AuthenticationError
auth_error = AuthenticationError(
message="Invalid API key", llm_provider="openai", model="gpt-4"
)
ex_info = ex.get_ex_info(auth_error)
assert isinstance(ex_info, ExInfo)
assert ex_info.name == "AuthenticationError"
assert ex_info.retry is False
assert "API key" in ex_info.description
# Test with unknown exception type
class UnknownError(Exception):
pass
unknown = UnknownError()
ex_info = ex.get_ex_info(unknown)
assert isinstance(ex_info, ExInfo)
assert ex_info.name is None
assert ex_info.retry is None
assert ex_info.description is None
def test_rate_limit_error():
"""Test specific handling of RateLimitError"""
ex = LiteLLMExceptions()
from litellm import RateLimitError
rate_error = RateLimitError(message="Rate limit exceeded", llm_provider="openai", model="gpt-4")
ex_info = ex.get_ex_info(rate_error)
assert ex_info.retry is True
assert "rate limited" in ex_info.description.lower()
def test_bad_gateway_error():
"""Test specific handling of BadGatewayError"""
ex = LiteLLMExceptions()
from litellm import BadGatewayError
bad_gateway_error = BadGatewayError(
message="Bad Gateway", llm_provider="openai", model="gpt-4"
)
ex_info = ex.get_ex_info(bad_gateway_error)
assert ex_info.retry is True
assert ex_info.name == "BadGatewayError"
def test_context_window_error():
"""Test specific handling of ContextWindowExceededError"""
ex = LiteLLMExceptions()
from litellm import ContextWindowExceededError
ctx_error = ContextWindowExceededError(
message="Context length exceeded", model="gpt-4", llm_provider="openai"
)
ex_info = ex.get_ex_info(ctx_error)
assert ex_info.retry is False
def test_openrouter_error():
"""Test specific handling of OpenRouter API errors"""
ex = LiteLLMExceptions()
from litellm import APIConnectionError
# Create an APIConnectionError with OpenrouterException message
openrouter_error = APIConnectionError(
message="APIConnectionError: OpenrouterException - 'choices'",
model="openrouter/model",
llm_provider="openrouter",
)
ex_info = ex.get_ex_info(openrouter_error)
assert ex_info.retry is True
assert "OpenRouter" in ex_info.description
assert "overloaded" in ex_info.description
assert "rate" in ex_info.description