from typing import Any
import openai
def recoverable_error(
error_code: str,
message: str,
path: str,
instruction: str | None,
trace_id: str = "",
timing_ms: int = 0,
) -> dict[str, Any]:
"""Generate recoverable error response message (structured format).
Args:
error_code: Error code (e.g., INVALID_PATH, NEEDS_MORE_CONTEXT).
message: Error message.
path: File path.
instruction: Optional instruction.
trace_id: Trace ID.
timing_ms: Elapsed time (milliseconds).
Returns:
Structured error response.
"""
result: dict[str, Any] = {
"status": "error",
"code": error_code,
"path": path,
"trace_id": trace_id,
"timing_ms": timing_ms,
"message": message,
}
if instruction:
result["instruction"] = instruction
return result
def openai_error_to_recoverable(
exc: openai.APIError,
path: str,
instruction: str | None,
trace_id: str = "",
timing_ms: int = 0,
) -> dict[str, Any]:
"""Convert OpenAI SDK errors to recoverable message (structured format).
Args:
exc: OpenAI API exception (APIStatusError, APIConnectionError, APITimeoutError).
path: File path.
instruction: Optional instruction.
trace_id: Trace ID.
timing_ms: Elapsed time (milliseconds).
Returns:
Structured recoverable error response.
"""
if isinstance(exc, openai.APITimeoutError):
result = recoverable_error(
"TIMEOUT_ERROR",
"Request timed out. Please retry later.",
path,
instruction,
trace_id,
timing_ms,
)
result["detail"] = {
"error_type": type(exc).__name__,
"error_message": str(exc),
}
return result
if isinstance(exc, openai.APIConnectionError):
result = recoverable_error(
"NETWORK_ERROR",
"Network error. Please check network connection and retry.",
path,
instruction,
trace_id,
timing_ms,
)
result["detail"] = {
"error_type": type(exc).__name__,
"error_message": str(exc),
}
return result
if isinstance(exc, openai.APIStatusError):
status_code = exc.status_code
if status_code in (401, 403):
error_code = "AUTH_ERROR"
message = "API authentication or permission error. Please check API key settings."
elif status_code == 429:
error_code = "RATE_LIMIT"
message = "Rate limit exceeded. Please retry later."
elif status_code >= 500:
error_code = "SERVER_ERROR"
message = "API server error. Please retry later."
else:
error_code = "API_ERROR"
message = "API error. Please simplify edit_snippet or add more explicit anchor lines."
result = recoverable_error(error_code, message, path, instruction, trace_id, timing_ms)
result["detail"] = {
"status_code": status_code,
"error_type": type(exc).__name__,
"error_message": str(exc),
}
return result
return recoverable_error(
"API_ERROR",
f"Unexpected API error: {type(exc).__name__}",
path,
instruction,
trace_id,
timing_ms,
)