File size: 6,711 Bytes
6cb2ff0
 
 
 
c40f3d0
6cb2ff0
c40f3d0
7d06e0a
c40f3d0
 
 
 
 
6cb2ff0
7d06e0a
6cb2ff0
c40f3d0
6cb2ff0
 
c2e6d7e
6cb2ff0
 
 
 
 
 
c40f3d0
 
6cb2ff0
 
7d06e0a
 
 
 
 
 
 
6cb2ff0
 
 
 
c40f3d0
6cb2ff0
c40f3d0
 
 
 
 
c2e6d7e
c40f3d0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c2e6d7e
c40f3d0
 
 
 
 
 
c2e6d7e
c40f3d0
 
 
 
 
 
 
 
 
 
 
 
6cb2ff0
 
 
 
 
7d06e0a
8c7976b
 
6cb2ff0
 
c40f3d0
6cb2ff0
 
 
 
 
c2e6d7e
6cb2ff0
 
 
 
 
7d06e0a
 
 
 
 
 
 
 
6cb2ff0
 
 
 
 
 
 
 
 
 
 
c40f3d0
 
 
 
6cb2ff0
 
 
 
8c7976b
 
 
6cb2ff0
 
 
c40f3d0
 
 
 
 
 
c2e6d7e
c40f3d0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# hf_token_utils.py
import os
import requests
import json
import time
from typing import Dict, Optional, Any, Tuple
from requests.exceptions import ConnectionError, Timeout, RequestException
from utils import get_proxy_url, validate_proxy_url

# Timeout and retry configuration
REQUEST_TIMEOUT = 30  # 30 seconds timeout
RETRY_ATTEMPTS = 2
RETRY_DELAY = 1  # 1 second delay between retries

def get_proxy_token(proxy_url: str = None, api_key: str = None) -> Tuple[str, str]:
    """
    Get a valid token from the proxy server with timeout and retry logic.
    
    Args:
        proxy_url: URL of the AI-Inferoxy server (optional, will use PROXY_URL env var if not provided)
        api_key: Your API key for authenticating with the proxy server
        
    Returns:
        Tuple of (token, token_id)
        
    Raises:
        ConnectionError: If unable to connect to proxy server
        TimeoutError: If request times out
        Exception: If token provisioning fails
    """
    # Get proxy URL from environment if not provided
    if proxy_url is None:
        is_valid, error_msg = validate_proxy_url()
        if not is_valid:
            raise Exception(error_msg)
        proxy_url = get_proxy_url()
    
    headers = {}
    if api_key:
        headers["Authorization"] = f"Bearer {api_key}"
    
    print(f"πŸ”— Connecting to proxy: {proxy_url}")
    
    for attempt in range(RETRY_ATTEMPTS):
        try:
            print(f"πŸ”„ Token provision attempt {attempt + 1}/{RETRY_ATTEMPTS}")
            
            response = requests.get(
                f"{proxy_url}/keys/provision/hf", 
                headers=headers,
                timeout=REQUEST_TIMEOUT
            )
            
            if response.status_code == 200:
                data = response.json()
                token = data["token"]
                token_id = data["token_id"]
                
                # For convenience, also set environment variable
                os.environ["HF_TOKEN"] = token
                
                print(f"βœ… Token provisioned successfully: {token_id}")
                return token, token_id
            else:
                error_msg = f"HTTP {response.status_code}: {response.text}"
                print(f"❌ Provision failed: {error_msg}")
                
                if attempt == RETRY_ATTEMPTS - 1:  # Last attempt
                    raise Exception(f"Failed to provision token: {error_msg}")
                    
        except ConnectionError as e:
            error_msg = f"Connection failed to proxy server: {str(e)}"
            print(f"πŸ”Œ {error_msg}")
            
            if attempt == RETRY_ATTEMPTS - 1:  # Last attempt
                raise ConnectionError(f"Cannot connect to AI-Inferoxy at {proxy_url}. Please check if the server is running.")
            
        except Timeout as e:
            error_msg = f"Request timeout after {REQUEST_TIMEOUT}s: {str(e)}"
            print(f"⏰ {error_msg}")
            
            if attempt == RETRY_ATTEMPTS - 1:  # Last attempt
                raise TimeoutError(f"Timeout connecting to AI-Inferoxy. Server may be overloaded.")
                
        except RequestException as e:
            error_msg = f"Request error: {str(e)}"
            print(f"🚫 {error_msg}")
            
            if attempt == RETRY_ATTEMPTS - 1:  # Last attempt
                raise Exception(f"Network error connecting to proxy: {str(e)}")
        
        # Wait before retry
        if attempt < RETRY_ATTEMPTS - 1:
            print(f"⏱️ Retrying in {RETRY_DELAY}s...")
            time.sleep(RETRY_DELAY)

def report_token_status(
    token_id: str, 
    status: str = "success", 
    error: Optional[str] = None,
    proxy_url: str = None,
    api_key: str = None,
    client_name: Optional[str] = None
) -> bool:
    """
    Report token usage status back to the proxy server with timeout handling.
    
    Args:
        token_id: ID of the token to report (from get_proxy_token)
        status: Status to report ('success' or 'error')
        error: Error message if status is 'error'
        proxy_url: URL of the AI-Inferoxy server (optional, will use PROXY_URL env var if not provided)
        api_key: Your API key for authenticating with the proxy server
        
    Returns:
        True if report was accepted, False otherwise
    """
    # Get proxy URL from environment if not provided
    if proxy_url is None:
        is_valid, error_msg = validate_proxy_url()
        if not is_valid:
            print(f"❌ {error_msg}")
            return False
        proxy_url = get_proxy_url()
    
    payload = {"token_id": token_id, "status": status}
    
    if error:
        payload["error"] = error
        
        # Extract error classification based on actual HF error patterns
        error_type = None
        if "401 Client Error" in error:
            error_type = "invalid_credentials"
        elif "402 Client Error" in error and "exceeded your monthly included credits" in error:
            error_type = "credits_exceeded"
        elif "timeout" in error.lower() or "timed out" in error.lower():
            error_type = "timeout"
        elif "connection" in error.lower():
            error_type = "connection_error"
            
        if error_type:
            payload["error_type"] = error_type
    
    if client_name:
        payload["client_name"] = client_name

    headers = {"Content-Type": "application/json"}
    if api_key:
        headers["Authorization"] = f"Bearer {api_key}"
    
    print(f"πŸ“Š Reporting {status} for token {token_id}")
    
    for attempt in range(RETRY_ATTEMPTS):
        try:
            response = requests.post(
                f"{proxy_url}/keys/report/hf", 
                json=payload, 
                headers=headers,
                timeout=REQUEST_TIMEOUT
            )
            
            if response.status_code == 200:
                print(f"βœ… Status reported successfully")
                return True
            else:
                print(f"⚠️ Report failed: HTTP {response.status_code}")
                
        except ConnectionError as e:
            print(f"πŸ”Œ Report connection error: {str(e)}")
            
        except Timeout as e:
            print(f"⏰ Report timeout: {str(e)}")
            
        except RequestException as e:
            print(f"🚫 Report request error: {str(e)}")
            
        # Don't retry on last attempt
        if attempt < RETRY_ATTEMPTS - 1:
            print(f"⏱️ Retrying report in {RETRY_DELAY}s...")
            time.sleep(RETRY_DELAY)
    
    print(f"❌ Failed to report status after {RETRY_ATTEMPTS} attempts")
    return False