Spaces:
Runtime error
Runtime error
Update index.js
Browse files
index.js
CHANGED
@@ -41,7 +41,7 @@ const CONFIG = {
|
|
41 |
RETRY: {
|
42 |
MAX_ATTEMPTS: 2//重试次数
|
43 |
},
|
44 |
-
SHOW_THINKING: process.env.SHOW_THINKING
|
45 |
IS_THINKING: false,
|
46 |
IS_IMG_GEN: false,
|
47 |
IS_IMG_GEN2: false,
|
@@ -87,11 +87,19 @@ async function initialization() {
|
|
87 |
return;
|
88 |
}
|
89 |
const ssoArray = process.env.SSO.split(',');
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
95 |
if (CONFIG.API.IS_TEMP_GROK2) {
|
96 |
await tempCookieManager.ensureCookies();
|
97 |
CONFIG.API.TEMP_COOKIE = tempCookieManager.cookies[tempCookieManager.currentIndex];
|
@@ -103,12 +111,13 @@ class AuthTokenManager {
|
|
103 |
constructor() {
|
104 |
this.tokenModelMap = {};
|
105 |
this.expiredTokens = new Set();
|
|
|
106 |
|
107 |
// 定义模型请求频率限制和过期时间
|
108 |
this.modelConfig = {
|
109 |
"grok-2": {
|
110 |
-
RequestFrequency:
|
111 |
-
ExpirationTime:
|
112 |
},
|
113 |
"grok-3": {
|
114 |
RequestFrequency: 20,
|
@@ -124,39 +133,160 @@ class AuthTokenManager {
|
|
124 |
}
|
125 |
};
|
126 |
this.tokenResetSwitch = false;
|
|
|
127 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
128 |
|
129 |
-
|
130 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
131 |
if (!this.tokenModelMap[model]) {
|
132 |
this.tokenModelMap[model] = [];
|
133 |
}
|
|
|
|
|
|
|
134 |
const existingTokenEntry = this.tokenModelMap[model].find(entry => entry.token === token);
|
135 |
|
136 |
if (!existingTokenEntry) {
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
142 |
}
|
143 |
-
}
|
144 |
}
|
145 |
|
146 |
-
//直接设置token,仅适用于自己设置轮询而不是使用AuthTokenManager管理
|
147 |
setToken(token) {
|
148 |
-
const models =
|
149 |
-
|
150 |
this.tokenModelMap = models.reduce((map, model) => {
|
151 |
map[model] = [{
|
152 |
token,
|
153 |
RequestCount: 0,
|
154 |
-
AddedTime: Date.now()
|
|
|
155 |
}];
|
156 |
return map;
|
157 |
}, {});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
158 |
}
|
159 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
160 |
getNextTokenForModel(modelId) {
|
161 |
const normalizedModel = this.normalizeModelName(modelId);
|
162 |
|
@@ -166,13 +296,28 @@ class AuthTokenManager {
|
|
166 |
const tokenEntry = this.tokenModelMap[normalizedModel][0];
|
167 |
|
168 |
if (tokenEntry) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
169 |
tokenEntry.RequestCount++;
|
|
|
170 |
if (tokenEntry.RequestCount > this.modelConfig[normalizedModel].RequestFrequency) {
|
171 |
this.removeTokenFromModel(normalizedModel, tokenEntry.token);
|
172 |
const nextTokenEntry = this.tokenModelMap[normalizedModel][0];
|
173 |
return nextTokenEntry ? nextTokenEntry.token : null;
|
174 |
}
|
175 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
176 |
return tokenEntry.token;
|
177 |
}
|
178 |
|
@@ -181,15 +326,15 @@ class AuthTokenManager {
|
|
181 |
|
182 |
removeTokenFromModel(modelId, token) {
|
183 |
const normalizedModel = this.normalizeModelName(modelId);
|
184 |
-
|
185 |
if (!this.tokenModelMap[normalizedModel]) {
|
186 |
Logger.error(`模型 ${normalizedModel} 不存在`, 'TokenManager');
|
187 |
return false;
|
188 |
}
|
189 |
-
|
190 |
const modelTokens = this.tokenModelMap[normalizedModel];
|
191 |
const tokenIndex = modelTokens.findIndex(entry => entry.token === token);
|
192 |
-
|
193 |
if (tokenIndex !== -1) {
|
194 |
const removedTokenEntry = modelTokens.splice(tokenIndex, 1)[0];
|
195 |
this.expiredTokens.add({
|
@@ -197,18 +342,19 @@ class AuthTokenManager {
|
|
197 |
model: normalizedModel,
|
198 |
expiredTime: Date.now()
|
199 |
});
|
200 |
-
|
|
|
201 |
this.startTokenResetProcess();
|
202 |
this.tokenResetSwitch = true;
|
203 |
}
|
204 |
Logger.info(`模型${modelId}的令牌已失效,已成功移除令牌: ${token}`, 'TokenManager');
|
205 |
return true;
|
206 |
}
|
207 |
-
|
208 |
Logger.error(`在模型 ${normalizedModel} 中未找到 token: ${token}`, 'TokenManager');
|
209 |
return false;
|
210 |
}
|
211 |
-
|
212 |
getExpiredTokens() {
|
213 |
return Array.from(this.expiredTokens);
|
214 |
}
|
@@ -224,23 +370,24 @@ class AuthTokenManager {
|
|
224 |
const normalizedModel = this.normalizeModelName(modelId);
|
225 |
return this.tokenModelMap[normalizedModel]?.length || 0;
|
226 |
}
|
|
|
227 |
getRemainingTokenRequestCapacity() {
|
228 |
const remainingCapacityMap = {};
|
229 |
-
|
230 |
Object.keys(this.modelConfig).forEach(model => {
|
231 |
const modelTokens = this.tokenModelMap[model] || [];
|
232 |
-
|
233 |
const modelRequestFrequency = this.modelConfig[model].RequestFrequency;
|
234 |
-
|
235 |
const totalUsedRequests = modelTokens.reduce((sum, tokenEntry) => {
|
236 |
return sum + (tokenEntry.RequestCount || 0);
|
237 |
}, 0);
|
238 |
-
|
239 |
// 计算剩余可用请求数量
|
240 |
const remainingCapacity = (modelTokens.length * modelRequestFrequency) - totalUsedRequests;
|
241 |
remainingCapacityMap[model] = Math.max(0, remainingCapacity);
|
242 |
});
|
243 |
-
|
244 |
return remainingCapacityMap;
|
245 |
}
|
246 |
|
@@ -250,8 +397,13 @@ class AuthTokenManager {
|
|
250 |
}
|
251 |
|
252 |
startTokenResetProcess() {
|
253 |
-
|
|
|
|
|
|
|
|
|
254 |
const now = Date.now();
|
|
|
255 |
this.expiredTokens.forEach(expiredTokenInfo => {
|
256 |
const { token, model, expiredTime } = expiredTokenInfo;
|
257 |
const expirationTime = this.modelConfig[model].ExpirationTime;
|
@@ -260,13 +412,50 @@ class AuthTokenManager {
|
|
260 |
this.tokenModelMap[model].push({
|
261 |
token: token,
|
262 |
RequestCount: 0,
|
263 |
-
AddedTime: now
|
|
|
264 |
});
|
265 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
266 |
this.expiredTokens.delete(expiredTokenInfo);
|
267 |
}
|
268 |
});
|
269 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
270 |
}
|
271 |
|
272 |
getAllTokens() {
|
@@ -276,6 +465,10 @@ class AuthTokenManager {
|
|
276 |
});
|
277 |
return Array.from(allTokens);
|
278 |
}
|
|
|
|
|
|
|
|
|
279 |
}
|
280 |
|
281 |
|
@@ -358,7 +551,7 @@ class GrokTempCookieManager {
|
|
358 |
}
|
359 |
}
|
360 |
async initializeTempCookies(count = 1) {
|
361 |
-
Logger.info(
|
362 |
const browserOptions = {
|
363 |
headless: true,
|
364 |
args: [
|
@@ -918,10 +1111,53 @@ app.use(cors({
|
|
918 |
allowedHeaders: ['Content-Type', 'Authorization']
|
919 |
}));
|
920 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
921 |
app.get('/hf/v1/models', (req, res) => {
|
922 |
res.json({
|
923 |
object: "list",
|
924 |
-
data: Object.keys(
|
925 |
id: model,
|
926 |
object: "model",
|
927 |
created: Math.floor(Date.now() / 1000),
|
@@ -949,7 +1185,7 @@ app.post('/hf/v1/chat/completions', async (req, res) => {
|
|
949 |
let retryCount = 0;
|
950 |
const grokClient = new GrokApiClient(model);
|
951 |
const requestPayload = await grokClient.prepareChatRequest(req.body);
|
952 |
-
Logger.info(`请求体: ${JSON.stringify(requestPayload, null, 2)}`, 'Server');
|
953 |
|
954 |
while (retryCount < CONFIG.RETRY.MAX_ATTEMPTS) {
|
955 |
retryCount++;
|
@@ -986,7 +1222,6 @@ app.post('/hf/v1/chat/completions', async (req, res) => {
|
|
986 |
} catch (error) {
|
987 |
Logger.error(error, 'Server');
|
988 |
if (isTempCookie) {
|
989 |
-
// 移除当前失效的 cookie
|
990 |
tempCookieManager.cookies.splice(tempCookieManager.currentIndex, 1);
|
991 |
if (tempCookieManager.cookies.length != 0) {
|
992 |
tempCookieManager.currentIndex = tempCookieManager.currentIndex % tempCookieManager.cookies.length;
|
@@ -1002,9 +1237,9 @@ app.post('/hf/v1/chat/completions', async (req, res) => {
|
|
1002 |
}
|
1003 |
}
|
1004 |
} else {
|
1005 |
-
if(CONFIG.API.IS_CUSTOM_SSO) throw new Error(`自定义SSO令牌当前模型${model}的请求次数已失效`);
|
1006 |
tokenManager.removeTokenFromModel(model, CONFIG.API.SIGNATURE_COOKIE.cookie);
|
1007 |
-
if(tokenManager.getTokenCountForModel(model) === 0){
|
1008 |
throw new Error(`${model} 次数已达上限,请切换其他模型或者重新对话`);
|
1009 |
}
|
1010 |
}
|
@@ -1028,9 +1263,9 @@ app.post('/hf/v1/chat/completions', async (req, res) => {
|
|
1028 |
}
|
1029 |
}
|
1030 |
} else {
|
1031 |
-
if(CONFIG.API.IS_CUSTOM_SSO) throw new Error(`自定义SSO令牌当前模型${model}的请求次数已失效`);
|
1032 |
tokenManager.removeTokenFromModel(model, CONFIG.API.SIGNATURE_COOKIE.cookie);
|
1033 |
-
if(tokenManager.getTokenCountForModel(model) === 0){
|
1034 |
throw new Error(`${model} 次数已达上限,请切换其他模型或者重新对话`);
|
1035 |
}
|
1036 |
}
|
@@ -1053,7 +1288,7 @@ app.post('/hf/v1/chat/completions', async (req, res) => {
|
|
1053 |
}
|
1054 |
}
|
1055 |
} else {
|
1056 |
-
if(CONFIG.API.IS_CUSTOM_SSO) throw new Error(`自定义SSO令牌当前模型${model}的请求次数已失效`);
|
1057 |
Logger.error(`令牌异常错误状态!status: ${response.status}`, 'Server');
|
1058 |
tokenManager.removeTokenFromModel(model, CONFIG.API.SIGNATURE_COOKIE.cookie);
|
1059 |
Logger.info(`当前${model}剩余可用令牌数: ${tokenManager.getTokenCountForModel(model)}`, 'Server');
|
|
|
41 |
RETRY: {
|
42 |
MAX_ATTEMPTS: 2//重试次数
|
43 |
},
|
44 |
+
SHOW_THINKING: process.env.SHOW_THINKING == undefined ? true : process.env.SHOW_THINKING == 'true',
|
45 |
IS_THINKING: false,
|
46 |
IS_IMG_GEN: false,
|
47 |
IS_IMG_GEN2: false,
|
|
|
87 |
return;
|
88 |
}
|
89 |
const ssoArray = process.env.SSO.split(',');
|
90 |
+
const concurrencyLimit = 1;
|
91 |
+
for (let i = 0; i < ssoArray.length; i += concurrencyLimit) {
|
92 |
+
const batch = ssoArray.slice(i, i + concurrencyLimit);
|
93 |
+
const batchPromises = batch.map(sso =>
|
94 |
+
tokenManager.addToken(`sso-rw=${sso};sso=${sso}`)
|
95 |
+
);
|
96 |
+
|
97 |
+
await Promise.all(batchPromises);
|
98 |
+
Logger.info(`已加载令牌: ${i} 个`, 'Server');
|
99 |
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
100 |
+
}
|
101 |
+
Logger.info(`令牌加载完成: ${JSON.stringify(tokenManager.getAllTokens(), null, 2)}`, 'Server');
|
102 |
+
Logger.info(`共加载: ${tokenManager.getAllTokens().length}个令牌`, 'Server');
|
103 |
if (CONFIG.API.IS_TEMP_GROK2) {
|
104 |
await tempCookieManager.ensureCookies();
|
105 |
CONFIG.API.TEMP_COOKIE = tempCookieManager.cookies[tempCookieManager.currentIndex];
|
|
|
111 |
constructor() {
|
112 |
this.tokenModelMap = {};
|
113 |
this.expiredTokens = new Set();
|
114 |
+
this.tokenStatusMap = {};
|
115 |
|
116 |
// 定义模型请求频率限制和过期时间
|
117 |
this.modelConfig = {
|
118 |
"grok-2": {
|
119 |
+
RequestFrequency: 30,
|
120 |
+
ExpirationTime: 1 * 60 * 60 * 1000 // 1小时
|
121 |
},
|
122 |
"grok-3": {
|
123 |
RequestFrequency: 20,
|
|
|
133 |
}
|
134 |
};
|
135 |
this.tokenResetSwitch = false;
|
136 |
+
this.tokenResetTimer = null;
|
137 |
}
|
138 |
+
async fetchGrokStats(token, modelName) {
|
139 |
+
let requestKind = 'DEFAULT';
|
140 |
+
if (modelName == 'grok-2' || modelName == 'grok-3') {
|
141 |
+
requestKind = 'DEFAULT';
|
142 |
+
} else if (modelName == 'grok-3-deepsearch') {
|
143 |
+
requestKind = 'DEEPSEARCH';
|
144 |
+
} else if (modelName == 'grok-3-reasoning') {
|
145 |
+
requestKind = 'REASONING';
|
146 |
+
}
|
147 |
+
const response = await fetch('https://grok.com/rest/rate-limits', {
|
148 |
+
method: 'POST',
|
149 |
+
headers: {
|
150 |
+
'content-type': 'application/json',
|
151 |
+
'Cookie': token,
|
152 |
+
},
|
153 |
+
body: JSON.stringify({
|
154 |
+
"requestKind": requestKind,
|
155 |
+
"modelName": modelName == 'grok-2' ? 'grok-latest' : "grok-3"
|
156 |
+
})
|
157 |
+
});
|
158 |
|
159 |
+
if (response.status != 200) {
|
160 |
+
return 0;
|
161 |
+
}
|
162 |
+
const data = await response.json();
|
163 |
+
return data.remainingQueries;
|
164 |
+
}
|
165 |
+
async addToken(token) {
|
166 |
+
const sso = token.split("sso=")[1].split(";")[0];
|
167 |
+
|
168 |
+
for (const model of Object.keys(this.modelConfig)) {
|
169 |
if (!this.tokenModelMap[model]) {
|
170 |
this.tokenModelMap[model] = [];
|
171 |
}
|
172 |
+
if (!this.tokenStatusMap[sso]) {
|
173 |
+
this.tokenStatusMap[sso] = {};
|
174 |
+
}
|
175 |
const existingTokenEntry = this.tokenModelMap[model].find(entry => entry.token === token);
|
176 |
|
177 |
if (!existingTokenEntry) {
|
178 |
+
try {
|
179 |
+
const remainingQueries = await this.fetchGrokStats(token, model);
|
180 |
+
|
181 |
+
const modelRequestFrequency = this.modelConfig[model].RequestFrequency;
|
182 |
+
const usedRequestCount = modelRequestFrequency - remainingQueries;
|
183 |
+
|
184 |
+
if (usedRequestCount === modelRequestFrequency) {
|
185 |
+
this.expiredTokens.add({
|
186 |
+
token: token,
|
187 |
+
model: model,
|
188 |
+
expiredTime: Date.now()
|
189 |
+
});
|
190 |
+
|
191 |
+
if (!this.tokenStatusMap[sso][model]) {
|
192 |
+
this.tokenStatusMap[sso][model] = {
|
193 |
+
isValid: false,
|
194 |
+
invalidatedTime: Date.now(),
|
195 |
+
totalRequestCount: Math.max(0, usedRequestCount)
|
196 |
+
};
|
197 |
+
}
|
198 |
+
|
199 |
+
if (!this.tokenResetSwitch) {
|
200 |
+
this.startTokenResetProcess();
|
201 |
+
this.tokenResetSwitch = true;
|
202 |
+
}
|
203 |
+
} else {
|
204 |
+
this.tokenModelMap[model].push({
|
205 |
+
token: token,
|
206 |
+
RequestCount: Math.max(0, usedRequestCount),
|
207 |
+
AddedTime: Date.now(),
|
208 |
+
StartCallTime: null
|
209 |
+
});
|
210 |
+
|
211 |
+
if (!this.tokenStatusMap[sso][model]) {
|
212 |
+
this.tokenStatusMap[sso][model] = {
|
213 |
+
isValid: true,
|
214 |
+
invalidatedTime: null,
|
215 |
+
totalRequestCount: Math.max(0, usedRequestCount)
|
216 |
+
};
|
217 |
+
}
|
218 |
+
}
|
219 |
+
} catch (error) {
|
220 |
+
this.tokenModelMap[model].push({
|
221 |
+
token: token,
|
222 |
+
RequestCount: 0,
|
223 |
+
AddedTime: Date.now(),
|
224 |
+
StartCallTime: null
|
225 |
+
});
|
226 |
+
|
227 |
+
if (!this.tokenStatusMap[sso][model]) {
|
228 |
+
this.tokenStatusMap[sso][model] = {
|
229 |
+
isValid: true,
|
230 |
+
invalidatedTime: null,
|
231 |
+
totalRequestCount: 0
|
232 |
+
};
|
233 |
+
}
|
234 |
+
|
235 |
+
Logger.error(`获取模型 ${model} 的统计信息失败: ${error}`, 'TokenManager');
|
236 |
+
}
|
237 |
+
await Utils.delay(200);
|
238 |
}
|
239 |
+
}
|
240 |
}
|
241 |
|
|
|
242 |
setToken(token) {
|
243 |
+
const models = Object.keys(this.modelConfig);
|
|
|
244 |
this.tokenModelMap = models.reduce((map, model) => {
|
245 |
map[model] = [{
|
246 |
token,
|
247 |
RequestCount: 0,
|
248 |
+
AddedTime: Date.now(),
|
249 |
+
StartCallTime: null
|
250 |
}];
|
251 |
return map;
|
252 |
}, {});
|
253 |
+
const sso = token.split("sso=")[1].split(";")[0];
|
254 |
+
this.tokenStatusMap[sso] = models.reduce((statusMap, model) => {
|
255 |
+
statusMap[model] = {
|
256 |
+
isValid: true,
|
257 |
+
invalidatedTime: null,
|
258 |
+
totalRequestCount: 0
|
259 |
+
};
|
260 |
+
return statusMap;
|
261 |
+
}, {});
|
262 |
}
|
263 |
|
264 |
+
async deleteToken(token) {
|
265 |
+
try {
|
266 |
+
const sso = token.split("sso=")[1].split(";")[0];
|
267 |
+
await Promise.all([
|
268 |
+
new Promise((resolve) => {
|
269 |
+
this.tokenModelMap = Object.fromEntries(
|
270 |
+
Object.entries(this.tokenModelMap).map(([model, entries]) => [
|
271 |
+
model,
|
272 |
+
entries.filter(entry => entry.token !== token)
|
273 |
+
])
|
274 |
+
);
|
275 |
+
resolve();
|
276 |
+
}),
|
277 |
+
|
278 |
+
new Promise((resolve) => {
|
279 |
+
delete this.tokenStatusMap[sso];
|
280 |
+
resolve();
|
281 |
+
}),
|
282 |
+
]);
|
283 |
+
Logger.info(`令牌已成功移除: ${token}`, 'TokenManager');
|
284 |
+
return true;
|
285 |
+
} catch (error) {
|
286 |
+
Logger.error('令牌删除失败:', error);
|
287 |
+
return false;
|
288 |
+
}
|
289 |
+
}
|
290 |
getNextTokenForModel(modelId) {
|
291 |
const normalizedModel = this.normalizeModelName(modelId);
|
292 |
|
|
|
296 |
const tokenEntry = this.tokenModelMap[normalizedModel][0];
|
297 |
|
298 |
if (tokenEntry) {
|
299 |
+
if (tokenEntry.StartCallTime === null || tokenEntry.StartCallTime === undefined) {
|
300 |
+
tokenEntry.StartCallTime = Date.now();
|
301 |
+
}
|
302 |
+
if (!this.tokenResetSwitch) {
|
303 |
+
this.startTokenResetProcess();
|
304 |
+
this.tokenResetSwitch = true;
|
305 |
+
}
|
306 |
tokenEntry.RequestCount++;
|
307 |
+
|
308 |
if (tokenEntry.RequestCount > this.modelConfig[normalizedModel].RequestFrequency) {
|
309 |
this.removeTokenFromModel(normalizedModel, tokenEntry.token);
|
310 |
const nextTokenEntry = this.tokenModelMap[normalizedModel][0];
|
311 |
return nextTokenEntry ? nextTokenEntry.token : null;
|
312 |
}
|
313 |
+
const sso = tokenEntry.token.split("sso=")[1].split(";")[0];
|
314 |
+
if (this.tokenStatusMap[sso] && this.tokenStatusMap[sso][normalizedModel]) {
|
315 |
+
if (tokenEntry.RequestCount === this.modelConfig[normalizedModel].RequestFrequency) {
|
316 |
+
this.tokenStatusMap[sso][normalizedModel].isValid = false;
|
317 |
+
this.tokenStatusMap[sso][normalizedModel].invalidatedTime = Date.now();
|
318 |
+
}
|
319 |
+
this.tokenStatusMap[sso][normalizedModel].totalRequestCount++;
|
320 |
+
}
|
321 |
return tokenEntry.token;
|
322 |
}
|
323 |
|
|
|
326 |
|
327 |
removeTokenFromModel(modelId, token) {
|
328 |
const normalizedModel = this.normalizeModelName(modelId);
|
329 |
+
|
330 |
if (!this.tokenModelMap[normalizedModel]) {
|
331 |
Logger.error(`模型 ${normalizedModel} 不存在`, 'TokenManager');
|
332 |
return false;
|
333 |
}
|
334 |
+
|
335 |
const modelTokens = this.tokenModelMap[normalizedModel];
|
336 |
const tokenIndex = modelTokens.findIndex(entry => entry.token === token);
|
337 |
+
|
338 |
if (tokenIndex !== -1) {
|
339 |
const removedTokenEntry = modelTokens.splice(tokenIndex, 1)[0];
|
340 |
this.expiredTokens.add({
|
|
|
342 |
model: normalizedModel,
|
343 |
expiredTime: Date.now()
|
344 |
});
|
345 |
+
|
346 |
+
if (!this.tokenResetSwitch) {
|
347 |
this.startTokenResetProcess();
|
348 |
this.tokenResetSwitch = true;
|
349 |
}
|
350 |
Logger.info(`模型${modelId}的令牌已失效,已成功移除令牌: ${token}`, 'TokenManager');
|
351 |
return true;
|
352 |
}
|
353 |
+
|
354 |
Logger.error(`在模型 ${normalizedModel} 中未找到 token: ${token}`, 'TokenManager');
|
355 |
return false;
|
356 |
}
|
357 |
+
|
358 |
getExpiredTokens() {
|
359 |
return Array.from(this.expiredTokens);
|
360 |
}
|
|
|
370 |
const normalizedModel = this.normalizeModelName(modelId);
|
371 |
return this.tokenModelMap[normalizedModel]?.length || 0;
|
372 |
}
|
373 |
+
|
374 |
getRemainingTokenRequestCapacity() {
|
375 |
const remainingCapacityMap = {};
|
376 |
+
|
377 |
Object.keys(this.modelConfig).forEach(model => {
|
378 |
const modelTokens = this.tokenModelMap[model] || [];
|
379 |
+
|
380 |
const modelRequestFrequency = this.modelConfig[model].RequestFrequency;
|
381 |
+
|
382 |
const totalUsedRequests = modelTokens.reduce((sum, tokenEntry) => {
|
383 |
return sum + (tokenEntry.RequestCount || 0);
|
384 |
}, 0);
|
385 |
+
|
386 |
// 计算剩余可用请求数量
|
387 |
const remainingCapacity = (modelTokens.length * modelRequestFrequency) - totalUsedRequests;
|
388 |
remainingCapacityMap[model] = Math.max(0, remainingCapacity);
|
389 |
});
|
390 |
+
|
391 |
return remainingCapacityMap;
|
392 |
}
|
393 |
|
|
|
397 |
}
|
398 |
|
399 |
startTokenResetProcess() {
|
400 |
+
if (this.tokenResetTimer) {
|
401 |
+
clearInterval(this.tokenResetTimer);
|
402 |
+
}
|
403 |
+
|
404 |
+
this.tokenResetTimer = setInterval(() => {
|
405 |
const now = Date.now();
|
406 |
+
|
407 |
this.expiredTokens.forEach(expiredTokenInfo => {
|
408 |
const { token, model, expiredTime } = expiredTokenInfo;
|
409 |
const expirationTime = this.modelConfig[model].ExpirationTime;
|
|
|
412 |
this.tokenModelMap[model].push({
|
413 |
token: token,
|
414 |
RequestCount: 0,
|
415 |
+
AddedTime: now,
|
416 |
+
StartCallTime: null
|
417 |
});
|
418 |
}
|
419 |
+
const sso = token.split("sso=")[1].split(";")[0];
|
420 |
+
|
421 |
+
if (this.tokenStatusMap[sso] && this.tokenStatusMap[sso][model]) {
|
422 |
+
this.tokenStatusMap[sso][model].isValid = true;
|
423 |
+
this.tokenStatusMap[sso][model].invalidatedTime = null;
|
424 |
+
this.tokenStatusMap[sso][model].totalRequestCount = 0;
|
425 |
+
}
|
426 |
+
|
427 |
this.expiredTokens.delete(expiredTokenInfo);
|
428 |
}
|
429 |
});
|
430 |
+
|
431 |
+
Object.keys(this.modelConfig).forEach(model => {
|
432 |
+
if (!this.tokenModelMap[model]) return;
|
433 |
+
|
434 |
+
const processedTokens = this.tokenModelMap[model].map(tokenEntry => {
|
435 |
+
if (!tokenEntry.StartCallTime) return tokenEntry;
|
436 |
+
|
437 |
+
const expirationTime = this.modelConfig[model].ExpirationTime;
|
438 |
+
if (now - tokenEntry.StartCallTime >= expirationTime) {
|
439 |
+
const sso = tokenEntry.token.split("sso=")[1].split(";")[0];
|
440 |
+
if (this.tokenStatusMap[sso] && this.tokenStatusMap[sso][model]) {
|
441 |
+
this.tokenStatusMap[sso][model].isValid = true;
|
442 |
+
this.tokenStatusMap[sso][model].invalidatedTime = null;
|
443 |
+
this.tokenStatusMap[sso][model].totalRequestCount = 0;
|
444 |
+
}
|
445 |
+
|
446 |
+
return {
|
447 |
+
...tokenEntry,
|
448 |
+
RequestCount: 0,
|
449 |
+
StartCallTime: null
|
450 |
+
};
|
451 |
+
}
|
452 |
+
|
453 |
+
return tokenEntry;
|
454 |
+
});
|
455 |
+
|
456 |
+
this.tokenModelMap[model] = processedTokens;
|
457 |
+
});
|
458 |
+
}, 1 * 60 * 60 * 1000);
|
459 |
}
|
460 |
|
461 |
getAllTokens() {
|
|
|
465 |
});
|
466 |
return Array.from(allTokens);
|
467 |
}
|
468 |
+
|
469 |
+
getTokenStatusMap() {
|
470 |
+
return this.tokenStatusMap;
|
471 |
+
}
|
472 |
}
|
473 |
|
474 |
|
|
|
551 |
}
|
552 |
}
|
553 |
async initializeTempCookies(count = 1) {
|
554 |
+
Logger.info(`开始初始化 ${count} 个临时账号认证信息`, 'Server');
|
555 |
const browserOptions = {
|
556 |
headless: true,
|
557 |
args: [
|
|
|
1111 |
allowedHeaders: ['Content-Type', 'Authorization']
|
1112 |
}));
|
1113 |
|
1114 |
+
|
1115 |
+
app.get('/hf/get/tokens', (req, res) => {
|
1116 |
+
const authToken = req.headers.authorization?.replace('Bearer ', '');
|
1117 |
+
if (CONFIG.API.IS_CUSTOM_SSO) {
|
1118 |
+
return res.status(403).json({ error: '自定义的SSO令牌模式无法获取轮询sso令牌状态' });
|
1119 |
+
} else if (authToken !== CONFIG.API.API_KEY) {
|
1120 |
+
return res.status(401).json({ error: 'Unauthorized' });
|
1121 |
+
}
|
1122 |
+
res.json(tokenManager.getTokenStatusMap());
|
1123 |
+
});
|
1124 |
+
app.post('/hf/add/token', async (req, res) => {
|
1125 |
+
const authToken = req.headers.authorization?.replace('Bearer ', '');
|
1126 |
+
if (CONFIG.API.IS_CUSTOM_SSO) {
|
1127 |
+
return res.status(403).json({ error: '自定义的SSO令牌模式无法添加sso令牌' });
|
1128 |
+
} else if (authToken !== CONFIG.API.API_KEY) {
|
1129 |
+
return res.status(401).json({ error: 'Unauthorized' });
|
1130 |
+
}
|
1131 |
+
try {
|
1132 |
+
const sso = req.body.sso;
|
1133 |
+
await tokenManager.addToken(`sso-rw=${sso};sso=${sso}`);
|
1134 |
+
res.status(200).json(tokenManager.getTokenStatusMap()[sso]);
|
1135 |
+
} catch (error) {
|
1136 |
+
Logger.error(error, 'Server');
|
1137 |
+
res.status(500).json({ error: '添加sso令牌失败' });
|
1138 |
+
}
|
1139 |
+
});
|
1140 |
+
app.post('/hf/delete/token', async (req, res) => {
|
1141 |
+
const authToken = req.headers.authorization?.replace('Bearer ', '');
|
1142 |
+
if (CONFIG.API.IS_CUSTOM_SSO) {
|
1143 |
+
return res.status(403).json({ error: '自定义的SSO令牌模式无法删除sso令牌' });
|
1144 |
+
} else if (authToken !== CONFIG.API.API_KEY) {
|
1145 |
+
return res.status(401).json({ error: 'Unauthorized' });
|
1146 |
+
}
|
1147 |
+
try {
|
1148 |
+
const sso = req.body.sso;
|
1149 |
+
await tokenManager.deleteToken(`sso-rw=${sso};sso=${sso}`);
|
1150 |
+
res.status(200).json({ message: '删除sso令牌成功' });
|
1151 |
+
} catch (error) {
|
1152 |
+
Logger.error(error, 'Server');
|
1153 |
+
res.status(500).json({ error: '删除sso令牌失败' });
|
1154 |
+
}
|
1155 |
+
});
|
1156 |
+
|
1157 |
app.get('/hf/v1/models', (req, res) => {
|
1158 |
res.json({
|
1159 |
object: "list",
|
1160 |
+
data: Object.keys(tokenManager.tokenModelMap).map((model, index) => ({
|
1161 |
id: model,
|
1162 |
object: "model",
|
1163 |
created: Math.floor(Date.now() / 1000),
|
|
|
1185 |
let retryCount = 0;
|
1186 |
const grokClient = new GrokApiClient(model);
|
1187 |
const requestPayload = await grokClient.prepareChatRequest(req.body);
|
1188 |
+
//Logger.info(`请求体: ${JSON.stringify(requestPayload, null, 2)}`, 'Server');
|
1189 |
|
1190 |
while (retryCount < CONFIG.RETRY.MAX_ATTEMPTS) {
|
1191 |
retryCount++;
|
|
|
1222 |
} catch (error) {
|
1223 |
Logger.error(error, 'Server');
|
1224 |
if (isTempCookie) {
|
|
|
1225 |
tempCookieManager.cookies.splice(tempCookieManager.currentIndex, 1);
|
1226 |
if (tempCookieManager.cookies.length != 0) {
|
1227 |
tempCookieManager.currentIndex = tempCookieManager.currentIndex % tempCookieManager.cookies.length;
|
|
|
1237 |
}
|
1238 |
}
|
1239 |
} else {
|
1240 |
+
if (CONFIG.API.IS_CUSTOM_SSO) throw new Error(`自定义SSO令牌当前模型${model}的请求次数已失效`);
|
1241 |
tokenManager.removeTokenFromModel(model, CONFIG.API.SIGNATURE_COOKIE.cookie);
|
1242 |
+
if (tokenManager.getTokenCountForModel(model) === 0) {
|
1243 |
throw new Error(`${model} 次数已达上限,请切换其他模型或者重新对话`);
|
1244 |
}
|
1245 |
}
|
|
|
1263 |
}
|
1264 |
}
|
1265 |
} else {
|
1266 |
+
if (CONFIG.API.IS_CUSTOM_SSO) throw new Error(`自定义SSO令牌当前模型${model}的请求次数已失效`);
|
1267 |
tokenManager.removeTokenFromModel(model, CONFIG.API.SIGNATURE_COOKIE.cookie);
|
1268 |
+
if (tokenManager.getTokenCountForModel(model) === 0) {
|
1269 |
throw new Error(`${model} 次数已达上限,请切换其他模型或者重新对话`);
|
1270 |
}
|
1271 |
}
|
|
|
1288 |
}
|
1289 |
}
|
1290 |
} else {
|
1291 |
+
if (CONFIG.API.IS_CUSTOM_SSO) throw new Error(`自定义SSO令牌当前模型${model}的请求次数已失效`);
|
1292 |
Logger.error(`令牌异常错误状态!status: ${response.status}`, 'Server');
|
1293 |
tokenManager.removeTokenFromModel(model, CONFIG.API.SIGNATURE_COOKIE.cookie);
|
1294 |
Logger.info(`当前${model}剩余可用令牌数: ${tokenManager.getTokenCountForModel(model)}`, 'Server');
|