package promptkit import ( "fmt" "gitea.maximumdirect.net/eric/promptkit/internal/domain" ) // Namespaces selects default resource namespaces for caller-supplied IDs. // Empty fields leave that resource type unscoped. type Namespaces struct { Prompt string Profile string Backend string } // WithNamespaces returns an engine view that qualifies slashless caller-supplied // prompt, profile, and backend selections with the supplied namespaces. // Qualified selections pass through unchanged. It replaces all namespace // defaults on the new view and leaves the receiver unchanged; resource // existence is checked when selected. An empty field clears that resource's // scope. Captured configuration references, defaults, and global configuration // inspection are not rewritten. [Engine.ListNamespaces] and // [Engine.ListCollections] remain global inventories. Invalid namespace syntax // or a nil engine returns an error matching ErrInvalidConfig. // // The view shares the receiver's captured configuration, clients, backend-capacity // pools, and prepared-execution owner. Prepared handles retain their captured // selections whichever related view executes them. func (e *Engine) WithNamespaces(namespaces Namespaces) (*Engine, error) { if e == nil || e.internal == nil { return nil, fmt.Errorf("%w: engine is nil", ErrInvalidConfig) } for _, namespace := range []struct { kind string name string }{ {kind: "prompt", name: namespaces.Prompt}, {kind: "profile", name: namespaces.Profile}, {kind: "backend", name: namespaces.Backend}, } { if namespace.name != "" && !domain.IsValidResourceNamespace(namespace.name) { return nil, fmt.Errorf("%w: invalid %s namespace %q", ErrInvalidConfig, namespace.kind, namespace.name) } } return &Engine{internal: e.internal.WithNamespaces(namespaces.Prompt, namespaces.Profile, namespaces.Backend)}, nil }