Skip to content

Commit

Permalink
_make_request error output
Browse files Browse the repository at this point in the history
  • Loading branch information
jahwag committed Aug 2, 2024
1 parent 1b5dedc commit cd4ff87
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 56 deletions.
42 changes: 24 additions & 18 deletions .github/ISSUE_TEMPLATE/feature_request.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,27 @@ assignees: ''

---

Is your feature request related to a problem? Please describe.
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
Describe the solution you'd like
A clear and concise description of what you want to happen.
Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.
Use case
Describe how you would use this feature and how it would benefit your workflow with ClaudeSync.
Additional context
Add any other context, screenshots, or examples about the feature request here.
Environment (if relevant):

OS: [e.g. Windows 10, macOS 11.4, Ubuntu 20.04]
Python version: [e.g. 3.8.10]
ClaudeSync version: [e.g. 0.3.7]

Are you willing to contribute to this feature?
Let us know if you're interested in helping implement this feature or if you're just suggesting an idea.
# Feature Request Template

## 1. Problem Description
Provide a clear and concise description of the problem you're experiencing. For example: "I'm always frustrated when [...]"

## 2. Desired Solution
Outline the solution you would like to see implemented. Be clear and specific about what you want to happen.

## 3. Considered Alternatives
Describe any alternative solutions or features you have considered. Include why these alternatives may or may not work for your needs.

## 4. Use Case
Explain how you would use this feature and how it would benefit your workflow with ClaudeSync.

## 5. Additional Context
Include any other relevant context, screenshots, or examples that can help in understanding the feature request.

## 6. Environment (if relevant)
- **OS:** [e.g. Windows 10, macOS 11.4, Ubuntu 20.04]
- **Python version:** [e.g. 3.8.10]
- **ClaudeSync version:** [e.g. 0.3.7]

## 7. Willingness to Contribute
Let us know if you're interested in helping to implement this feature or if you're just suggesting an idea.
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "claudesync"
version = "0.4.0"
version = "0.4.1"
authors = [
{name = "Jahziah Wagner", email = "[email protected]"},
]
Expand Down
30 changes: 29 additions & 1 deletion src/claudesync/providers/base_claude_ai.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,23 @@
import logging
import click
from .base_provider import BaseProvider
from ..config_manager import ConfigManager
from ..exceptions import ProviderError


class BaseClaudeAIProvider(BaseProvider):
BASE_URL = "https://claude.ai/api"

def __init__(self, session_key=None):
self.config = ConfigManager()
self.session_key = session_key
self.logger = logging.getLogger(__name__)
self._configure_logging()

def _configure_logging(self):
log_level = self.config.get("log_level", "INFO")
logging.basicConfig(level=getattr(logging, log_level))
self.logger.setLevel(getattr(logging, log_level))

def login(self):
click.echo("To obtain your session key, please follow these steps:")
Expand All @@ -26,7 +36,25 @@ def login(self):
"5. In the left sidebar, expand 'Cookies' and select 'https://claude.ai'"
)
click.echo("6. Find the cookie named 'sessionKey' and copy its value")
self.session_key = click.prompt("Please enter your sessionKey", type=str)

while True:
session_key = click.prompt("Please enter your sessionKey", type=str)
if not session_key.startswith("sk-ant"):
click.echo(
"Invalid sessionKey format. Please make sure it starts with 'sk-ant'."
)
continue

self.session_key = session_key
try:
organizations = self.get_organizations()
if organizations:
break # Exit the loop if get_organizations is successful
except ProviderError:
click.echo(
"Failed to retrieve organizations. Please enter a valid sessionKey."
)

return self.session_key

def get_organizations(self):
Expand Down
39 changes: 14 additions & 25 deletions src/claudesync/providers/claude_ai.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,12 @@
import json
import logging
import requests
from .base_claude_ai import BaseClaudeAIProvider
from ..config_manager import ConfigManager
from ..exceptions import ProviderError

logger = logging.getLogger(__name__)


class ClaudeAIProvider(BaseClaudeAIProvider):
def __init__(self, session_key=None):
super().__init__(session_key)
self.config = ConfigManager()
self._configure_logging()

def _configure_logging(self):
log_level = self.config.get("log_level", "INFO")
logging.basicConfig(level=getattr(logging, log_level))
logger.setLevel(getattr(logging, log_level))

def _make_request(self, method, endpoint, data=None):
url = f"{self.BASE_URL}{endpoint}"
Expand All @@ -43,19 +32,19 @@ def _make_request(self, method, endpoint, data=None):
}

try:
logger.debug(f"Making {method} request to {url}")
logger.debug(f"Headers: {headers}")
logger.debug(f"Cookies: {cookies}")
self.logger.debug(f"Making {method} request to {url}")
self.logger.debug(f"Headers: {headers}")
self.logger.debug(f"Cookies: {cookies}")
if data:
logger.debug(f"Request data: {data}")
self.logger.debug(f"Request data: {data}")

response = requests.request(
method, url, headers=headers, cookies=cookies, json=data
)

logger.debug(f"Response status code: {response.status_code}")
logger.debug(f"Response headers: {response.headers}")
logger.debug(f"Response content: {response.text[:1000]}...")
self.logger.debug(f"Response status code: {response.status_code}")
self.logger.debug(f"Response headers: {response.headers}")
self.logger.debug(f"Response content: {response.text[:1000]}...")

if response.status_code == 403:
error_msg = (
Expand All @@ -65,7 +54,7 @@ def _make_request(self, method, endpoint, data=None):
"claudesync api logout\n"
"claudesync api login claude.ai-curl"
)
logger.error(error_msg)
self.logger.error(error_msg)
raise ProviderError(error_msg)

response.raise_for_status()
Expand All @@ -76,13 +65,13 @@ def _make_request(self, method, endpoint, data=None):
return response.json()

except requests.RequestException as e:
logger.error(f"Request failed: {str(e)}")
self.logger.error(f"Request failed: {str(e)}")
if hasattr(e, "response") and e.response is not None:
logger.error(f"Response status code: {e.response.status_code}")
logger.error(f"Response headers: {e.response.headers}")
logger.error(f"Response content: {e.response.text}")
self.logger.error(f"Response status code: {e.response.status_code}")
self.logger.error(f"Response headers: {e.response.headers}")
self.logger.error(f"Response content: {e.response.text}")
raise ProviderError(f"API request failed: {str(e)}")
except json.JSONDecodeError as json_err:
logger.error(f"Failed to parse JSON response: {str(json_err)}")
logger.error(f"Response content: {response.text}")
self.logger.error(f"Failed to parse JSON response: {str(json_err)}")
self.logger.error(f"Response content: {response.text}")
raise ProviderError(f"Invalid JSON response from API: {str(json_err)}")
60 changes: 49 additions & 11 deletions src/claudesync/providers/claude_ai_curl.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@


class ClaudeAICurlProvider(BaseClaudeAIProvider):
def __init__(self):
super().__init__()

def _make_request(self, method, endpoint, data=None):
url = f"{self.BASE_URL}{endpoint}"
headers = [
Expand All @@ -22,6 +25,8 @@ def _make_request(self, method, endpoint, data=None):
"--compressed",
"-s",
"-S",
"-w",
"%{http_code}", # Append HTTP status code to the output
]
command.extend(headers)

Expand All @@ -37,23 +42,56 @@ def _make_request(self, method, endpoint, data=None):
command, capture_output=True, text=True, check=True, encoding="utf-8"
)

# Extract HTTP status code from the response
if not result.stdout:
return None

try:
return json.loads(result.stdout)
except json.JSONDecodeError as e:
raise ProviderError(
f"Failed to parse JSON response: {e}. Response content: {result.stdout}"
f"Empty response from the server. Request headers: {headers}"
)

http_status_code = result.stdout[
-3:
] # Last 3 characters are the status code
response_body = result.stdout[
:-3
].strip() # Response body is everything before the status code

if http_status_code.startswith("2"):
# Successful response
try:
return json.loads(response_body)
except json.JSONDecodeError as e:
error_message = (
f"Failed to parse JSON response: {e}. Response content: {response_body}. Request "
f"headers: {headers}"
)
self.logger.error(error_message)
raise ProviderError(error_message)
else:
# Handle non-2xx status codes
error_message = (
f"HTTP request failed with status code {http_status_code}. "
f"Response content: {response_body}. Request headers: {headers}"
)
self.logger.error(error_message)
raise ProviderError(error_message)

except subprocess.CalledProcessError as e:
error_message = f"cURL command failed with return code {e.returncode}. "
error_message += f"stdout: {e.stdout}, stderr: {e.stderr}"
if e.returncode == 1:
error_message = (
f"cURL command failed due to an unsupported protocol or a failed initialization. "
f"Request headers: {headers}"
)
else:
error_message = (
f"cURL command failed with return code {e.returncode}. stdout: {e.stdout}, "
f"stderr: {e.stderr}. Request headers: {headers}"
)
self.logger.error(error_message)
raise ProviderError(error_message)
except UnicodeDecodeError as e:
error_message = f"Failed to decode cURL output: {e}. "
error_message += (
"This might be due to non-UTF-8 characters in the response."
error_message = (
f"Failed to decode cURL output: {e}. This might be due to non-UTF-8 characters in the "
f"response. Request headers: {headers}"
)
self.logger.error(error_message)
raise ProviderError(error_message)

0 comments on commit cd4ff87

Please sign in to comment.