letterm commited on
Commit
6b49430
·
verified ·
1 Parent(s): bc29c9c

Delete warp_client.py

Browse files
Files changed (1) hide show
  1. warp_client.py +0 -192
warp_client.py DELETED
@@ -1,192 +0,0 @@
1
- """
2
- Warp客户端模块
3
- 处理与Warp API的通信,包括protobuf数据处理和HTTP请求
4
- """
5
- import requests
6
- import json
7
- from typing import Generator, List, Optional
8
- from loguru import logger
9
-
10
- from config import Config
11
- from request_converter import OpenAIMessage
12
- from utils import Utils
13
- from protobuf_manager import ProtobufManager
14
-
15
-
16
- class WarpClient:
17
- """Warp API客户端"""
18
-
19
- def __init__(self, token_manager=None):
20
- self.token_manager = token_manager
21
- self.session = requests.Session()
22
-
23
- def get_auth_token(self) -> Optional[str]:
24
- """获取当前认证token"""
25
- if self.token_manager:
26
- token = self.token_manager.get_current_access_token()
27
- if token:
28
- return token
29
- else:
30
- logger.error("❌ 无法获取有效的认证token")
31
- return None
32
- else:
33
- logger.error("❌ Token管理器未初始化")
34
- return None
35
-
36
-
37
-
38
- def create_protobuf_data(self, messages: List[OpenAIMessage], model: str = "gemini-2.0-flash") -> Optional[bytes]:
39
- """创建protobuf数据"""
40
- return ProtobufManager.create_chat_request(messages, model)
41
-
42
- def parse_protobuf_response(self, base64_data: str) -> str:
43
- """解析protobuf响应数据"""
44
- return ProtobufManager.parse_chat_response(base64_data)
45
-
46
- def _check_and_handle_401_error(self, response_text: str, current_access_token: str = None, current_refresh_token: str = None) -> bool:
47
- """检查并处理401错误,返回True表示需要重试"""
48
- try:
49
- # 尝试解析响应为JSON
50
- error_data = json.loads(response_text)
51
- error_message = error_data.get("error", "")
52
-
53
- # 检查是否是目标错误消息
54
- if "Unauthorized: User not in context: Not found: no rows in result set" in error_message:
55
- logger.warning("⚠️ 检测到用户未创建错误,尝试用当前token创建用户")
56
-
57
- if self.token_manager and current_access_token:
58
- # 使用当前的access_token尝试创建用户
59
- logger.info(f"🔄 使用当前access_token创建用户: {current_access_token[:20]}...")
60
-
61
- # 尝试创建用户
62
- from login_client import LoginClient
63
- login_client = LoginClient()
64
-
65
- if login_client.create_user_with_access_token(current_access_token):
66
- logger.success("✅ 用户创建成功,可以重试请求")
67
- return True
68
- else:
69
- logger.error("❌ 当前token创建用户失败")
70
- # 如果用当前token创建用户失败,移除这个refresh_token
71
- if current_refresh_token:
72
- logger.info(f"🗑️ 移除创建用户失败的refresh_token")
73
- self.token_manager.remove_refresh_token(current_refresh_token)
74
-
75
- # 尝试获取下一个token
76
- logger.info("🔄 尝试获取下一个access_token...")
77
- next_token = self.token_manager.get_current_access_token()
78
- if next_token and next_token != current_access_token:
79
- logger.info(f"🔄 获取到下一个access_token: {next_token[:20]}...")
80
- return True # 返回True表示可以用新token重试
81
- else:
82
- logger.error("❌ 无法获取下一个有效的access_token")
83
- return False
84
- else:
85
- logger.error("❌ Token管理器未初始化或当前access_token为空")
86
- return False
87
-
88
- return False
89
-
90
- except (json.JSONDecodeError, KeyError, TypeError):
91
- # 如果不是JSON格式或没有error字段,则不是目标错误
92
- return False
93
-
94
- def send_request(self, protobuf_data: bytes) -> Generator[str, None, None]:
95
- """发送请求到Warp API并返回流式响应"""
96
- url = f"{Config.WARP_BASE_URL}{Config.WARP_AI_ENDPOINT}"
97
-
98
- max_retries = 2 # 最多重试2次
99
- retry_count = 0
100
-
101
- while retry_count <= max_retries:
102
- # 获取认证token
103
- auth_token = self.get_auth_token()
104
- if not auth_token:
105
- logger.error("❌ 无法获取认证token,请求终止")
106
- return
107
-
108
- # 获取当前使用的refresh_token(用于错误时移除)
109
- current_refresh_token = None
110
- if self.token_manager:
111
- with self.token_manager.token_lock:
112
- for refresh_token, token_info in self.token_manager.tokens.items():
113
- if token_info.access_token == auth_token:
114
- current_refresh_token = refresh_token
115
- break
116
-
117
- headers = {
118
- 'Accept': 'text/event-stream',
119
- 'Accept-Encoding': 'gzip, br',
120
- 'Content-Type': 'application/x-protobuf',
121
- 'x-warp-client-version': Config.WARP_CLIENT_VERSION,
122
- 'x-warp-os-category': Config.WARP_OS_CATEGORY,
123
- 'x-warp-os-name': Config.WARP_OS_NAME,
124
- 'x-warp-os-version': Config.WARP_OS_VERSION,
125
- 'authorization': f'Bearer {auth_token}'
126
- }
127
-
128
- if retry_count > 0:
129
- logger.info(f"🔄 第{retry_count}次重试请求到Warp API: {url}")
130
- else:
131
- logger.info(f"🌐 发送请求到Warp API: {url}")
132
-
133
- logger.debug(f"📦 Protobuf数据大小: {len(protobuf_data)} 字节")
134
-
135
- try:
136
- response = self.session.post(
137
- url,
138
- headers=headers,
139
- data=protobuf_data,
140
- stream=True,
141
- timeout=Config.REQUEST_TIMEOUT,
142
- verify=False
143
- )
144
-
145
- if response.status_code == 200:
146
- logger.success("✅ 请求成功,开始接收流式响应")
147
- chunk_count = 0
148
-
149
- for line in response.iter_lines(decode_unicode=True):
150
- if line and line.startswith('data:'):
151
- data = line[5:].strip()
152
- text = self.parse_protobuf_response(data)
153
- if text:
154
- chunk_count += 1
155
- logger.debug(f"📨 接收到响应块 #{chunk_count}: {len(text)} 字符")
156
- yield text
157
-
158
- logger.success(f"🎉 流式响应接收完成,总共 {chunk_count} 个块")
159
- return # 成功,退出重试循环
160
-
161
- elif response.status_code == 401:
162
- logger.error(f"❌ Warp API请求失败,状态码: {response.status_code}")
163
- if response.text:
164
- logger.error(f"❌ 错误详情: {response.text}")
165
-
166
- # 检查并处理特定的401错误
167
- should_retry = self._check_and_handle_401_error(response.text, auth_token, current_refresh_token)
168
-
169
- if should_retry and retry_count < max_retries:
170
- retry_count += 1
171
- logger.info(f"🔄 准备第{retry_count}次重试...")
172
- continue
173
- else:
174
- logger.error(f"❌ 401错误处理失败或已达到最大重试次数")
175
- return
176
- else:
177
- logger.error("❌ 401错误,但无响应内容")
178
- return
179
- else:
180
- logger.error(f"❌ Warp API请求失败,状态码: {response.status_code}")
181
- if response.text:
182
- logger.error(f"❌ 错误详情: {response.text}")
183
- return
184
-
185
- except requests.Timeout:
186
- logger.error(f"❌ 请求超时 ({Config.REQUEST_TIMEOUT}秒)")
187
- return
188
- except Exception as e:
189
- logger.error(f"❌ 发送请求时出错: {e}")
190
- import traceback
191
- traceback.print_exc()
192
- return