Changeset 0.10.2 (#58)
This commit is contained in:
@@ -14,13 +14,14 @@ import (
|
||||
// ── Known Roles ────────────────────────────
|
||||
|
||||
const (
|
||||
RoleUtility = "utility" // Internal tasks: summarization, title generation
|
||||
RoleEmbedding = "embedding" // Vector embedding for knowledge bases
|
||||
RoleGeneration = "generation" // Primary chat generation (future routing)
|
||||
RoleUtility = "utility" // Internal tasks: summarization, title generation
|
||||
RoleEmbedding = "embedding" // Vector embedding for knowledge bases
|
||||
)
|
||||
|
||||
// ValidRoles lists all recognized role names.
|
||||
var ValidRoles = []string{RoleUtility, RoleEmbedding, RoleGeneration}
|
||||
// Note: "generation" (image/media) was removed in v0.10.2 — image gen
|
||||
// will be extension-managed with its own provider config, not a role slot.
|
||||
var ValidRoles = []string{RoleUtility, RoleEmbedding}
|
||||
|
||||
// IsValidRole returns true if the given role name is recognized.
|
||||
func IsValidRole(role string) bool {
|
||||
@@ -96,9 +97,9 @@ func NewResolver(s store.Stores, vault *crypto.KeyResolver) *Resolver {
|
||||
}
|
||||
|
||||
// Complete sends a chat completion using the named role.
|
||||
// Resolution: team override → global config → try primary → fallback on error.
|
||||
func (r *Resolver) Complete(ctx context.Context, role string, teamID *string, messages []providers.Message) (*CompletionResult, error) {
|
||||
cfg, err := r.GetConfig(ctx, role, teamID)
|
||||
// Resolution: personal override → team override → global config → try primary → fallback on error.
|
||||
func (r *Resolver) Complete(ctx context.Context, role string, userID string, teamID *string, messages []providers.Message) (*CompletionResult, error) {
|
||||
cfg, err := r.GetConfig(ctx, role, userID, teamID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -129,8 +130,8 @@ func (r *Resolver) Complete(ctx context.Context, role string, teamID *string, me
|
||||
}
|
||||
|
||||
// Embed generates embeddings using the named role.
|
||||
func (r *Resolver) Embed(ctx context.Context, role string, teamID *string, input []string) (*EmbeddingResult, error) {
|
||||
cfg, err := r.GetConfig(ctx, role, teamID)
|
||||
func (r *Resolver) Embed(ctx context.Context, role string, userID string, teamID *string, input []string) (*EmbeddingResult, error) {
|
||||
cfg, err := r.GetConfig(ctx, role, userID, teamID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -161,13 +162,21 @@ func (r *Resolver) Embed(ctx context.Context, role string, teamID *string, input
|
||||
}
|
||||
|
||||
// GetConfig returns the resolved role config for the given role name.
|
||||
// Team overrides take precedence over global config.
|
||||
func (r *Resolver) GetConfig(ctx context.Context, role string, teamID *string) (*RoleConfig, error) {
|
||||
// Resolution order: personal override → team override → global config.
|
||||
func (r *Resolver) GetConfig(ctx context.Context, role string, userID string, teamID *string) (*RoleConfig, error) {
|
||||
if !IsValidRole(role) {
|
||||
return nil, fmt.Errorf("unknown role: %q", role)
|
||||
}
|
||||
|
||||
// Check team override first
|
||||
// Check personal override first (BYOK users)
|
||||
if userID != "" {
|
||||
personalCfg, err := r.getPersonalRoleConfig(ctx, userID, role)
|
||||
if err == nil && personalCfg != nil && (personalCfg.Primary != nil || personalCfg.Fallback != nil) {
|
||||
return personalCfg, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Check team override
|
||||
if teamID != nil && *teamID != "" {
|
||||
teamCfg, err := r.getTeamRoleConfig(ctx, *teamID, role)
|
||||
if err == nil && teamCfg != nil && (teamCfg.Primary != nil || teamCfg.Fallback != nil) {
|
||||
@@ -181,7 +190,13 @@ func (r *Resolver) GetConfig(ctx context.Context, role string, teamID *string) (
|
||||
|
||||
// IsConfigured returns true if the named role has at least a primary binding.
|
||||
func (r *Resolver) IsConfigured(ctx context.Context, role string) bool {
|
||||
cfg, err := r.GetConfig(ctx, role, nil)
|
||||
cfg, err := r.GetConfig(ctx, role, "", nil)
|
||||
return err == nil && cfg != nil && cfg.Primary != nil
|
||||
}
|
||||
|
||||
// IsPersonalOverride returns true if the user has a personal binding for the role.
|
||||
func (r *Resolver) IsPersonalOverride(ctx context.Context, userID, role string) bool {
|
||||
cfg, err := r.getPersonalRoleConfig(ctx, userID, role)
|
||||
return err == nil && cfg != nil && cfg.Primary != nil
|
||||
}
|
||||
|
||||
@@ -285,6 +300,35 @@ func (r *Resolver) resolveBinding(ctx context.Context, binding *RoleBinding) (pr
|
||||
|
||||
// ── Internal: Config Loading ───────────────
|
||||
|
||||
func (r *Resolver) getPersonalRoleConfig(ctx context.Context, userID, role string) (*RoleConfig, error) {
|
||||
user, err := r.stores.Users.GetByID(ctx, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
settings := user.Settings
|
||||
if settings == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
rolesRaw, ok := settings["model_roles"]
|
||||
if !ok {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
rolesMap, ok := rolesRaw.(map[string]interface{})
|
||||
if !ok {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
roleData, ok := rolesMap[role]
|
||||
if !ok {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return parseRoleConfig(roleData)
|
||||
}
|
||||
|
||||
func (r *Resolver) getGlobalRoleConfig(ctx context.Context, role string) (*RoleConfig, error) {
|
||||
allRoles, err := r.stores.GlobalConfig.Get(ctx, "model_roles")
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user