package settings import ( "context" "apps/backend/internal/middleware" "apps/backend/internal/module/ai" "apps/backend/internal/module/member/domain" "apps/backend/internal/svc" "apps/backend/internal/types" "github.com/zeromicro/go-zero/core/logx" ) type SaveAiLogic struct { logx.Logger ctx context.Context svcCtx *svc.ServiceContext } func NewSaveAiLogic(ctx context.Context, svcCtx *svc.ServiceContext) *SaveAiLogic { return &SaveAiLogic{Logger: logx.WithContext(ctx), ctx: ctx, svcCtx: svcCtx} } func (l *SaveAiLogic) SaveAi(req *types.SaveAiReq) (*types.AiSettingsData, error) { uid, _ := middleware.UIDFrom(l.ctx) st, _ := l.svcCtx.Members.GetSettings(l.ctx, uid) if st == nil { st = domain.DefaultSettings(uid) } if st.ProviderAPIKeys == nil { st.ProviderAPIKeys = map[string]string{} } // migrate legacy single key into map if st.APIKey != "" && st.Provider != "" && st.ProviderAPIKeys[st.Provider] == "" { st.ProviderAPIKeys[st.Provider] = st.APIKey } provider := st.Provider if req.Provider != "" { provider = req.Provider } else if req.ResearchProvider != "" { provider = req.ResearchProvider } provider = ai.NormalizeProvider(provider) st.Provider = provider if req.Model != "" { st.Model = req.Model } else if req.ResearchModel != "" { st.Model = req.ResearchModel } // BYOK for this provider if req.ApiKey != "" { st.SetKeyForProvider(provider, req.ApiKey) } if req.ResearchApiKey != "" { st.SetKeyForProvider(provider, req.ResearchApiKey) } if req.ApiKeyConfigured != nil && !*req.ApiKeyConfigured { st.SetKeyForProvider(provider, "") } // validate model against live list (or fallback) list, _, _ := loadModelsForProvider(l.ctx, l.svcCtx, st, provider) st.Model = pickModel(st.Model, list) st.APIKeyConfigured = st.HasKeyForProvider(provider) st.ResearchAPIKeyConfigured = st.APIKeyConfigured st.UpdatedAt = domain.NowNano() if err := l.svcCtx.Members.SaveSettings(l.ctx, uid, st); err != nil { return nil, err } // return combined settings + models return NewGetAiLogic(l.ctx, l.svcCtx).GetAi(&types.GetAiReq{Provider: provider}) }