- Updated .env.example to include new configuration options for AI gateway and WebUI secret key. - Modified Nginx configuration to support additional API routes for model management and migration. - Implemented new API endpoints for discovering organization-level LLM models and managing hosted mail services. - Enhanced AI gateway logic to support organization-specific model access and permissions. - Improved error handling and response structures in the AI and mail APIs. - Added integration tests for new features and updated existing tests for model access control.
93 lines
2.0 KiB
Go
93 lines
2.0 KiB
Go
package admin
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/ultisuite/ulti-backend/internal/llm"
|
|
)
|
|
|
|
func (s *Service) DiscoverOrgLLMModels(ctx context.Context, providerID string) ([]string, error) {
|
|
providerID = strings.TrimSpace(providerID)
|
|
if providerID == "" {
|
|
return nil, fmt.Errorf("provider_id is required")
|
|
}
|
|
|
|
stored, _, _, err := s.loadOrgPolicyRaw(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
policy := mergeMaps(defaultOrgPolicy(), stored)
|
|
llmSection, _ := policy["llm"].(map[string]any)
|
|
providers, _ := llmSection["providers"].([]any)
|
|
|
|
var provider llm.Provider
|
|
found := false
|
|
for _, item := range providers {
|
|
pm, ok := item.(map[string]any)
|
|
if !ok {
|
|
continue
|
|
}
|
|
id, _ := pm["id"].(string)
|
|
if id != providerID {
|
|
continue
|
|
}
|
|
provider = llm.Provider{
|
|
ID: id,
|
|
Name: stringValueMap(pm, "name"),
|
|
BaseURL: stringValueMap(pm, "base_url"),
|
|
APIKey: stringValueMap(pm, "api_key"),
|
|
DefaultModel: stringValueMap(pm, "default_model"),
|
|
}
|
|
found = true
|
|
break
|
|
}
|
|
if !found {
|
|
return nil, fmt.Errorf("llm provider not found")
|
|
}
|
|
if strings.TrimSpace(provider.BaseURL) == "" {
|
|
return nil, fmt.Errorf("llm provider base_url is required")
|
|
}
|
|
|
|
client := llm.NewClient()
|
|
models, err := client.ListModels(ctx, provider)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if models == nil {
|
|
models = []string{}
|
|
}
|
|
return models, nil
|
|
}
|
|
|
|
func buildLLMProviderSecretsStatus(policy map[string]any) map[string]any {
|
|
llmSection, ok := policy["llm"].(map[string]any)
|
|
if !ok {
|
|
return nil
|
|
}
|
|
providers, ok := llmSection["providers"].([]any)
|
|
if !ok {
|
|
return nil
|
|
}
|
|
out := map[string]any{}
|
|
for _, item := range providers {
|
|
pm, ok := item.(map[string]any)
|
|
if !ok {
|
|
continue
|
|
}
|
|
id, _ := pm["id"].(string)
|
|
if strings.TrimSpace(id) == "" {
|
|
continue
|
|
}
|
|
apiKey, _ := pm["api_key"].(string)
|
|
out[id] = map[string]any{
|
|
"configured": strings.TrimSpace(apiKey) != "",
|
|
}
|
|
}
|
|
if len(out) == 0 {
|
|
return nil
|
|
}
|
|
return out
|
|
}
|