feat: Implement Max RPM tracking API, Codex API authentication, and a new dashboard pool status component.
This commit is contained in:
@@ -601,44 +601,77 @@ func (c *CodexAPIAuth) ObtainAuthorizationCode() (string, error) {
|
||||
"workspace_id": c.workspaceID,
|
||||
}
|
||||
|
||||
resp, body, err = c.doRequest("POST", "https://auth.openai.com/api/accounts/workspace/select", workspacePayload, workspaceHeaders)
|
||||
if err != nil || resp.StatusCode != 200 {
|
||||
// 添加 500 错误重试机制 - 最多重试 3 次
|
||||
var lastErr error
|
||||
for retry := 0; retry < 3; retry++ {
|
||||
if retry > 0 {
|
||||
c.logStep(StepSelectWorkspace, "第 %d 次重试选择工作区...", retry+1)
|
||||
time.Sleep(time.Duration(2+retry) * time.Second) // 递增延迟: 2s, 3s, 4s
|
||||
|
||||
// 重新获取 Sentinel token
|
||||
if !c.callSentinelReq("password_verify__auto") {
|
||||
c.callSentinelReq("email_otp_validate__auto")
|
||||
}
|
||||
workspaceHeaders["OpenAI-Sentinel-Token"] = c.getSentinelHeader("workspace_select")
|
||||
}
|
||||
|
||||
resp, body, err = c.doRequest("POST", "https://auth.openai.com/api/accounts/workspace/select", workspacePayload, workspaceHeaders)
|
||||
if err != nil {
|
||||
lastErr = fmt.Errorf("请求失败: %v", err)
|
||||
continue
|
||||
}
|
||||
|
||||
// 成功
|
||||
if resp.StatusCode == 200 {
|
||||
json.Unmarshal(body, &data)
|
||||
continueURL, ok := data["continue_url"].(string)
|
||||
if !ok || continueURL == "" {
|
||||
c.logError(StepSelectWorkspace, "未获取到 continue_url, 响应: %s", string(body[:min(500, len(body))]))
|
||||
return "", fmt.Errorf("未获取到 continue_url")
|
||||
}
|
||||
|
||||
// 7. 跟随重定向获取授权码
|
||||
c.logStep(StepWaitCallback, "跟随重定向...")
|
||||
for i := 0; i < 10; i++ {
|
||||
resp, _, err = c.doRequest("GET", continueURL, nil, headers)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
|
||||
if resp.StatusCode >= 300 && resp.StatusCode < 400 {
|
||||
location := resp.Header.Get("Location")
|
||||
if strings.Contains(location, "localhost:1455") {
|
||||
code := ExtractCodeFromCallbackURL(location)
|
||||
if code != "" {
|
||||
c.logStep(StepComplete, "授权成功,获取到授权码")
|
||||
return code, nil
|
||||
}
|
||||
}
|
||||
continueURL = location
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
c.logError(StepWaitCallback, "未能获取授权码")
|
||||
return "", fmt.Errorf("未能获取授权码")
|
||||
}
|
||||
|
||||
// 5xx 服务器错误,可重试
|
||||
if resp.StatusCode >= 500 && resp.StatusCode < 600 {
|
||||
c.logStep(StepSelectWorkspace, "服务器错误 %d,将重试...", resp.StatusCode)
|
||||
lastErr = fmt.Errorf("服务器错误: %d", resp.StatusCode)
|
||||
continue
|
||||
}
|
||||
|
||||
// 其他错误,不重试
|
||||
c.logError(StepSelectWorkspace, "选择工作区失败: %d - %s", resp.StatusCode, string(body[:min(200, len(body))]))
|
||||
return "", fmt.Errorf("选择工作区失败: %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
json.Unmarshal(body, &data)
|
||||
continueURL, ok := data["continue_url"].(string)
|
||||
if !ok || continueURL == "" {
|
||||
c.logError(StepSelectWorkspace, "未获取到 continue_url, 响应: %s", string(body[:min(500, len(body))]))
|
||||
return "", fmt.Errorf("未获取到 continue_url")
|
||||
}
|
||||
|
||||
// 7. 跟随重定向获取授权码
|
||||
c.logStep(StepWaitCallback, "跟随重定向...")
|
||||
for i := 0; i < 10; i++ {
|
||||
resp, _, err = c.doRequest("GET", continueURL, nil, headers)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
|
||||
if resp.StatusCode >= 300 && resp.StatusCode < 400 {
|
||||
location := resp.Header.Get("Location")
|
||||
if strings.Contains(location, "localhost:1455") {
|
||||
code := ExtractCodeFromCallbackURL(location)
|
||||
if code != "" {
|
||||
c.logStep(StepComplete, "授权成功,获取到授权码")
|
||||
return code, nil
|
||||
}
|
||||
}
|
||||
continueURL = location
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
c.logError(StepWaitCallback, "未能获取授权码")
|
||||
return "", fmt.Errorf("未能获取授权码")
|
||||
// 重试耗尽
|
||||
c.logError(StepSelectWorkspace, "选择工作区失败,重试已耗尽: %v", lastErr)
|
||||
return "", fmt.Errorf("选择工作区失败 (重试已耗尽): %v", lastErr)
|
||||
}
|
||||
|
||||
// ExchangeCodeForTokens 用授权码换取 tokens
|
||||
|
||||
Reference in New Issue
Block a user