File size: 2,676 Bytes
5ef3875
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
"""Exception hierarchy for YCode.

Every error a user can reasonably cause (bad config, missing key, network
trouble, ...) derives from :class:`YCodeError` so the CLI can print a clean
message instead of a traceback.
"""

from __future__ import annotations


class YCodeError(Exception):
    """Base class for all expected, user-facing YCode errors."""

    hint: str | None = None

    def __init__(self, message: str, *, hint: str | None = None) -> None:
        super().__init__(message)
        if hint is not None:
            self.hint = hint


class ConfigError(YCodeError):
    """Invalid or missing configuration."""


class MissingCredentialsError(ConfigError):
    """No API credentials were found."""

    hint = (
        "Only needed for Claude (--provider anthropic): set ANTHROPIC_API_KEY in your environment, "
        "in a .env file in the project directory, or in ~/.ycode/.env. Without it, run plain `ycode` "
        "to use YCode's own model."
    )


# ---------------------------------------------------------------- LLM errors


class LLMError(YCodeError):
    """A failure talking to the language model provider."""

    retryable: bool = False


class LLMAuthenticationError(LLMError):
    hint = "Check that ANTHROPIC_API_KEY is set to a valid key."


class LLMPermissionError(LLMError):
    hint = "Your API key does not have access to this model or feature."


class LLMNotFoundError(LLMError):
    hint = "Check the model name (YCODE_MODEL / `model` in config.toml) or use /model."


class LLMRateLimitError(LLMError):
    retryable = True
    hint = "You are being rate limited. Wait a moment and try again."


class LLMConnectionError(LLMError):
    retryable = True
    hint = "Check your network connection (and any proxy settings) and try again."


class LLMServerError(LLMError):
    retryable = True
    hint = "The API returned a server error. This is usually temporary; try again."


class LLMBadRequestError(LLMError):
    """The provider rejected the request (400)."""

    hint = (
        "Check the model and settings in your config. If it persists, /clear starts a "
        "fresh conversation."
    )


class LLMResponseError(LLMError):
    """The provider returned something we could not interpret."""

    retryable = True
    hint = "Try the request again."


# --------------------------------------------------------------- tool errors


class ToolError(YCodeError):
    """A tool failed in a way that should be reported back to the model."""


class PathSecurityError(ToolError):
    """A path resolved outside the workspace."""


class PermissionDenied(ToolError):
    """The user (or the policy) declined an action."""