package configuration import ( "context" "sort" "strings" "go.maximumdirect.net/promptkit/internal/domain" ) // IdentityFilter selects all identities, one namespace, or unqualified IDs. type IdentityFilter struct { All bool Namespace string } func selectIdentities[T any](ctx context.Context, entries []T, filter IdentityFilter, id func(T) string) ([]T, error) { if err := ctx.Err(); err != nil { return nil, err } if filter.All { result := append([]T(nil), entries...) if err := ctx.Err(); err != nil { return nil, err } return result, nil } if filter.Namespace != "" { prefix := filter.Namespace + "/" start := sort.Search(len(entries), func(i int) bool { return id(entries[i]) >= prefix }) end := start + sort.Search(len(entries)-start, func(i int) bool { return !strings.HasPrefix(id(entries[start+i]), prefix) }) result := append([]T(nil), entries[start:end]...) if err := ctx.Err(); err != nil { return nil, err } return result, nil } var result []T for _, entry := range entries { if err := ctx.Err(); err != nil { return nil, err } if !strings.Contains(id(entry), "/") { result = append(result, entry) } } if err := ctx.Err(); err != nil { return nil, err } return result, nil } // CollectionIdentity is the captured metadata for one final collection entry. type CollectionIdentity struct { Namespace string ReleaseVersion *string } func (state *loaded) ListProfiles(ctx context.Context, filter IdentityFilter) ([]string, error) { return selectIdentities(ctx, state.profileIDs, filter, func(id string) string { return id }) } func (state *loaded) ListBackends(ctx context.Context, filter IdentityFilter) ([]string, error) { return selectIdentities(ctx, state.backendIDs, filter, func(id string) string { return id }) } func (state *loaded) ListNamespaces(ctx context.Context, kinds []string) ([]string, error) { if err := ctx.Err(); err != nil { return nil, err } selected := kinds if len(selected) == 0 { selected = []string{"backend", "profile", "prompt"} } set := make(map[string]struct{}) for _, kind := range selected { for _, namespace := range state.namespaces[kind] { set[namespace] = struct{}{} } } namespaces := sortedKeys(set) if err := ctx.Err(); err != nil { return nil, err } return namespaces, nil } func (state *loaded) ListCollections(ctx context.Context) ([]CollectionIdentity, error) { if err := ctx.Err(); err != nil { return nil, err } collections := make([]CollectionIdentity, len(state.collections)) for index, collection := range state.collections { collections[index] = CollectionIdentity{ Namespace: collection.Namespace, ReleaseVersion: stringPointerValue(collection.ReleaseVersion), } } if err := ctx.Err(); err != nil { return nil, err } return collections, nil } func (state *loaded) ListPrompts(ctx context.Context, filter IdentityFilter) ([]domain.PromptIdentity, error) { return selectIdentities(ctx, state.promptIDs, filter, func(entry domain.PromptIdentity) string { return entry.ID }) }