44 "strconv"
55
66 "sub2api/internal/pkg/claude"
7+ "sub2api/internal/pkg/openai"
78 "sub2api/internal/pkg/response"
89 "sub2api/internal/service"
910
@@ -26,16 +27,18 @@ func NewOAuthHandler(oauthService *service.OAuthService) *OAuthHandler {
2627type AccountHandler struct {
2728 adminService service.AdminService
2829 oauthService * service.OAuthService
30+ openaiOAuthService * service.OpenAIOAuthService
2931 rateLimitService * service.RateLimitService
3032 accountUsageService * service.AccountUsageService
3133 accountTestService * service.AccountTestService
3234}
3335
3436// NewAccountHandler creates a new admin account handler
35- func NewAccountHandler (adminService service.AdminService , oauthService * service.OAuthService , rateLimitService * service.RateLimitService , accountUsageService * service.AccountUsageService , accountTestService * service.AccountTestService ) * AccountHandler {
37+ func NewAccountHandler (adminService service.AdminService , oauthService * service.OAuthService , openaiOAuthService * service. OpenAIOAuthService , rateLimitService * service.RateLimitService , accountUsageService * service.AccountUsageService , accountTestService * service.AccountTestService ) * AccountHandler {
3638 return & AccountHandler {
3739 adminService : adminService ,
3840 oauthService : oauthService ,
41+ openaiOAuthService : openaiOAuthService ,
3942 rateLimitService : rateLimitService ,
4043 accountUsageService : accountUsageService ,
4144 accountTestService : accountTestService ,
@@ -232,26 +235,47 @@ func (h *AccountHandler) Refresh(c *gin.Context) {
232235 return
233236 }
234237
235- // Use OAuth service to refresh token
236- tokenInfo , err := h .oauthService .RefreshAccountToken (c .Request .Context (), account )
237- if err != nil {
238- response .InternalError (c , "Failed to refresh credentials: " + err .Error ())
239- return
240- }
238+ var newCredentials map [string ]any
241239
242- // Copy existing credentials to preserve non-token settings (e.g., intercept_warmup_requests)
243- newCredentials := make (map [string ]any )
244- for k , v := range account .Credentials {
245- newCredentials [k ] = v
246- }
240+ if account .IsOpenAI () {
241+ // Use OpenAI OAuth service to refresh token
242+ tokenInfo , err := h .openaiOAuthService .RefreshAccountToken (c .Request .Context (), account )
243+ if err != nil {
244+ response .InternalError (c , "Failed to refresh credentials: " + err .Error ())
245+ return
246+ }
247+
248+ // Build new credentials from token info
249+ newCredentials = h .openaiOAuthService .BuildAccountCredentials (tokenInfo )
247250
248- // Update token-related fields
249- newCredentials ["access_token" ] = tokenInfo .AccessToken
250- newCredentials ["token_type" ] = tokenInfo .TokenType
251- newCredentials ["expires_in" ] = tokenInfo .ExpiresIn
252- newCredentials ["expires_at" ] = tokenInfo .ExpiresAt
253- newCredentials ["refresh_token" ] = tokenInfo .RefreshToken
254- newCredentials ["scope" ] = tokenInfo .Scope
251+ // Preserve non-token settings from existing credentials
252+ for k , v := range account .Credentials {
253+ if _ , exists := newCredentials [k ]; ! exists {
254+ newCredentials [k ] = v
255+ }
256+ }
257+ } else {
258+ // Use Anthropic/Claude OAuth service to refresh token
259+ tokenInfo , err := h .oauthService .RefreshAccountToken (c .Request .Context (), account )
260+ if err != nil {
261+ response .InternalError (c , "Failed to refresh credentials: " + err .Error ())
262+ return
263+ }
264+
265+ // Copy existing credentials to preserve non-token settings (e.g., intercept_warmup_requests)
266+ newCredentials = make (map [string ]any )
267+ for k , v := range account .Credentials {
268+ newCredentials [k ] = v
269+ }
270+
271+ // Update token-related fields
272+ newCredentials ["access_token" ] = tokenInfo .AccessToken
273+ newCredentials ["token_type" ] = tokenInfo .TokenType
274+ newCredentials ["expires_in" ] = tokenInfo .ExpiresIn
275+ newCredentials ["expires_at" ] = tokenInfo .ExpiresAt
276+ newCredentials ["refresh_token" ] = tokenInfo .RefreshToken
277+ newCredentials ["scope" ] = tokenInfo .Scope
278+ }
255279
256280 updatedAccount , err := h .adminService .UpdateAccount (c .Request .Context (), accountID , & service.UpdateAccountInput {
257281 Credentials : newCredentials ,
@@ -563,6 +587,46 @@ func (h *AccountHandler) GetAvailableModels(c *gin.Context) {
563587 return
564588 }
565589
590+ // Handle OpenAI accounts
591+ if account .IsOpenAI () {
592+ // For OAuth accounts: return default OpenAI models
593+ if account .IsOAuth () {
594+ response .Success (c , openai .DefaultModels )
595+ return
596+ }
597+
598+ // For API Key accounts: check model_mapping
599+ mapping := account .GetModelMapping ()
600+ if len (mapping ) == 0 {
601+ response .Success (c , openai .DefaultModels )
602+ return
603+ }
604+
605+ // Return mapped models
606+ var models []openai.Model
607+ for requestedModel := range mapping {
608+ var found bool
609+ for _ , dm := range openai .DefaultModels {
610+ if dm .ID == requestedModel {
611+ models = append (models , dm )
612+ found = true
613+ break
614+ }
615+ }
616+ if ! found {
617+ models = append (models , openai.Model {
618+ ID : requestedModel ,
619+ Object : "model" ,
620+ Type : "model" ,
621+ DisplayName : requestedModel ,
622+ })
623+ }
624+ }
625+ response .Success (c , models )
626+ return
627+ }
628+
629+ // Handle Claude/Anthropic accounts
566630 // For OAuth and Setup-Token accounts: return default models
567631 if account .IsOAuth () {
568632 response .Success (c , claude .DefaultModels )
0 commit comments