mirror of
https://github.com/Wei-Shaw/sub2api.git
synced 2026-09-01 15:02:58 +08:00
fix(openai): 修复 Agent Identity CI 问题
This commit is contained in:
@@ -515,10 +515,10 @@ func normalizeCodexImportEntry(entry codexImportEntry) (*codexImportAccount, err
|
||||
item.PlanType = firstCodexString(agentIdentity, []string{"plan_type"}, []string{"planType"})
|
||||
item.AgentFedRAMP = firstCodexBool(agentIdentity, []string{"chatgpt_account_is_fedramp"}, []string{"chatgptAccountIsFedramp"})
|
||||
if item.AgentRuntimeID == "" || item.AgentPrivateKey == "" || item.AccountID == "" || item.UserID == "" {
|
||||
return nil, errors.New("Agent Identity 缺少必要字段")
|
||||
return nil, errors.New("agent identity 缺少必要字段")
|
||||
}
|
||||
if err := service.ValidateOpenAIAgentIdentityPrivateKey(item.AgentPrivateKey); err != nil {
|
||||
return nil, errors.New("Agent Identity private key 格式无效")
|
||||
return nil, errors.New("agent identity private key 格式无效")
|
||||
}
|
||||
item.Credentials["auth_mode"] = service.OpenAIAuthModeAgentIdentity
|
||||
item.Credentials["agent_runtime_id"] = item.AgentRuntimeID
|
||||
|
||||
@@ -261,7 +261,11 @@ func ensureAgentIdentityTaskForAccount(ctx context.Context, repo AccountReposito
|
||||
if credAccount.ID > 0 {
|
||||
candidate := &sync.Mutex{}
|
||||
actual, _ := agentIdentityTaskLocks.LoadOrStore(credAccount.ID, candidate)
|
||||
sharedTaskMu = actual.(*sync.Mutex)
|
||||
loadedTaskMu, ok := actual.(*sync.Mutex)
|
||||
if !ok {
|
||||
return errors.New("agent identity task lock has invalid type")
|
||||
}
|
||||
sharedTaskMu = loadedTaskMu
|
||||
}
|
||||
sharedTaskMu.Lock()
|
||||
defer sharedTaskMu.Unlock()
|
||||
|
||||
@@ -56,7 +56,9 @@ func TestBuildAgentAssertionMatchesCodexEnvelopeAndSignature(t *testing.T) {
|
||||
require.Equal(t, "2026-07-14T00:09:10Z", envelope.Timestamp)
|
||||
signature, err := base64.StdEncoding.DecodeString(envelope.Signature)
|
||||
require.NoError(t, err)
|
||||
require.True(t, ed25519.Verify(key.privateKey.Public().(ed25519.PublicKey), []byte("runtime-test:task-test:2026-07-14T00:09:10Z"), signature))
|
||||
publicKey, ok := key.privateKey.Public().(ed25519.PublicKey)
|
||||
require.True(t, ok)
|
||||
require.True(t, ed25519.Verify(publicKey, []byte("runtime-test:task-test:2026-07-14T00:09:10Z"), signature))
|
||||
}
|
||||
|
||||
func TestDecryptAgentTaskIDSupportsCodexSealedBoxResponse(t *testing.T) {
|
||||
@@ -153,7 +155,7 @@ func TestEnsureAgentIdentityTaskPersistsAndRedactsCredentials(t *testing.T) {
|
||||
redacted[key] = value
|
||||
}
|
||||
}
|
||||
require.NotContains(t, string(mustJSON(t, redacted)), privateKey)
|
||||
require.NotContains(t, string(mustAgentIdentityJSON(t, redacted)), privateKey)
|
||||
}
|
||||
|
||||
func TestEnsureAgentIdentityTaskSharesLockAcrossServicesForSameAccount(t *testing.T) {
|
||||
@@ -219,7 +221,7 @@ func (r *agentIdentityCredentialsRepo) UpdateCredentials(_ context.Context, _ in
|
||||
return nil
|
||||
}
|
||||
|
||||
func mustJSON(t *testing.T, value any) []byte {
|
||||
func mustAgentIdentityJSON(t *testing.T, value any) []byte {
|
||||
t.Helper()
|
||||
encoded, err := json.Marshal(value)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -281,28 +281,25 @@ func (s *OpenAIQuotaService) ResetCredit(ctx context.Context, accountID int64) (
|
||||
callCtx, cancel := context.WithTimeout(ctx, openaiQuotaUpstreamTimeout)
|
||||
defer cancel()
|
||||
var payload OpenAIQuotaResetResult
|
||||
for {
|
||||
headers, headerErr := s.buildCodexQuotaHeaders(callCtx, accountID, accessToken, chatGPTAccountID, fedRAMP)
|
||||
if headerErr != nil {
|
||||
return nil, infraerrors.Newf(http.StatusBadGateway, "OPENAI_QUOTA_AUTH_FAILED", "failed to build upstream authentication: %v", headerErr)
|
||||
}
|
||||
headers["content-type"] = "application/json"
|
||||
resp, err := client.R().
|
||||
SetContext(callCtx).
|
||||
SetHeaders(headers).
|
||||
SetBody(map[string]string{"redeem_request_id": redeemRequestID}).
|
||||
SetSuccessResult(&payload).
|
||||
Post(chatGPTRateLimitResetURL)
|
||||
if err != nil {
|
||||
return nil, infraerrors.Newf(http.StatusBadGateway, "OPENAI_QUOTA_RESET_REQUEST_FAILED", "upstream request failed: %v", err)
|
||||
}
|
||||
if !resp.IsSuccessState() {
|
||||
status := resp.StatusCode
|
||||
body := truncate(s.redactQuotaErrorBody(callCtx, accountID, resp.String()), 240)
|
||||
slog.Warn("openai_quota_reset_failed", "account_id", accountID, "status", status, "body", body)
|
||||
return nil, infraerrors.Newf(mapUpstreamStatus(status), "OPENAI_QUOTA_RESET_UPSTREAM_ERROR", "upstream returned %d: %s", status, body)
|
||||
}
|
||||
break
|
||||
headers, headerErr := s.buildCodexQuotaHeaders(callCtx, accountID, accessToken, chatGPTAccountID, fedRAMP)
|
||||
if headerErr != nil {
|
||||
return nil, infraerrors.Newf(http.StatusBadGateway, "OPENAI_QUOTA_AUTH_FAILED", "failed to build upstream authentication: %v", headerErr)
|
||||
}
|
||||
headers["content-type"] = "application/json"
|
||||
resp, err := client.R().
|
||||
SetContext(callCtx).
|
||||
SetHeaders(headers).
|
||||
SetBody(map[string]string{"redeem_request_id": redeemRequestID}).
|
||||
SetSuccessResult(&payload).
|
||||
Post(chatGPTRateLimitResetURL)
|
||||
if err != nil {
|
||||
return nil, infraerrors.Newf(http.StatusBadGateway, "OPENAI_QUOTA_RESET_REQUEST_FAILED", "upstream request failed: %v", err)
|
||||
}
|
||||
if !resp.IsSuccessState() {
|
||||
status := resp.StatusCode
|
||||
body := truncate(s.redactQuotaErrorBody(callCtx, accountID, resp.String()), 240)
|
||||
slog.Warn("openai_quota_reset_failed", "account_id", accountID, "status", status, "body", body)
|
||||
return nil, infraerrors.Newf(mapUpstreamStatus(status), "OPENAI_QUOTA_RESET_UPSTREAM_ERROR", "upstream returned %d: %s", status, body)
|
||||
}
|
||||
|
||||
slog.Info("openai_quota_reset_success",
|
||||
|
||||
Reference in New Issue
Block a user