164 lines
5.2 KiB
Go
164 lines
5.2 KiB
Go
package modules
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"strings"
|
|
|
|
"gitea.maximumdirect.net/eric/audita/internal/core/config"
|
|
"gitea.maximumdirect.net/eric/audita/internal/core/modulecatalog"
|
|
"gitea.maximumdirect.net/eric/audita/internal/core/schema"
|
|
"gitea.maximumdirect.net/eric/audita/internal/framework/contracts"
|
|
glossarymodule "gitea.maximumdirect.net/eric/audita/internal/modules/glossary"
|
|
grammarmodule "gitea.maximumdirect.net/eric/audita/internal/modules/grammar"
|
|
homophonesmodule "gitea.maximumdirect.net/eric/audita/internal/modules/homophones"
|
|
spokenwordmodule "gitea.maximumdirect.net/eric/audita/internal/modules/spoken_word"
|
|
)
|
|
|
|
const (
|
|
ModuleKeyGlossary = modulecatalog.KeyGlossary
|
|
ModuleKeyHomophones = modulecatalog.KeyHomophones
|
|
ModuleKeySpokenWord = modulecatalog.KeySpokenWord
|
|
ModuleKeyGrammar = modulecatalog.KeyGrammar
|
|
)
|
|
|
|
const (
|
|
ReasonUnsupportedModule = "unsupported_module"
|
|
)
|
|
|
|
// IsKnownModuleKey reports whether a module key is recognized by the production
|
|
// registry scaffold.
|
|
func IsKnownModuleKey(key string) bool {
|
|
return modulecatalog.IsSupported(key)
|
|
}
|
|
|
|
// Dependencies holds explicit constructor dependencies for module creation.
|
|
type Dependencies struct {
|
|
Config *config.Config
|
|
Glossary *schema.Glossary
|
|
ProposalLLMClient contracts.StructuredLLMClient
|
|
ProposalLLMScheduler contracts.LLMScheduler
|
|
ValidationLLMClient contracts.StructuredLLMClient
|
|
ValidationLLMScheduler contracts.LLMScheduler
|
|
DiagnosticsDir string
|
|
}
|
|
|
|
// ConstructRequest is one module-construction request.
|
|
type ConstructRequest struct {
|
|
RunSpec contracts.ModuleRunSpec
|
|
Dependencies
|
|
}
|
|
|
|
// Constructor builds one module instance from a run spec and explicit deps.
|
|
type Constructor func(ctx context.Context, req ConstructRequest) (contracts.TranscriptModule, error)
|
|
|
|
// Factory resolves configured module specs into module instances.
|
|
type Factory struct {
|
|
deps Dependencies
|
|
constructors map[string]Constructor
|
|
}
|
|
|
|
// NewFactory creates a production module registry.
|
|
func NewFactory(deps Dependencies) *Factory {
|
|
factory := &Factory{
|
|
deps: deps,
|
|
constructors: make(map[string]Constructor, len(modulecatalog.SupportedKeys())),
|
|
}
|
|
_ = factory.RegisterConstructor(ModuleKeyGlossary, constructGlossaryModule)
|
|
_ = factory.RegisterConstructor(ModuleKeyHomophones, constructHomophonesModule)
|
|
_ = factory.RegisterConstructor(ModuleKeySpokenWord, constructSpokenWordModule)
|
|
_ = factory.RegisterConstructor(ModuleKeyGrammar, constructGrammarModule)
|
|
return factory
|
|
}
|
|
|
|
// RegisterConstructor registers a constructor for a known module key.
|
|
func (f *Factory) RegisterConstructor(moduleKey string, constructor Constructor) error {
|
|
if f == nil {
|
|
return fmt.Errorf("module factory is nil")
|
|
}
|
|
key := strings.TrimSpace(moduleKey)
|
|
if !IsKnownModuleKey(key) {
|
|
return &UnsupportedModuleError{ModuleKey: key}
|
|
}
|
|
if constructor == nil {
|
|
return fmt.Errorf("constructor for module %q must not be nil", key)
|
|
}
|
|
f.constructors[key] = constructor
|
|
return nil
|
|
}
|
|
|
|
func constructGrammarModule(ctx context.Context, req ConstructRequest) (contracts.TranscriptModule, error) {
|
|
_ = ctx
|
|
_ = req
|
|
return grammarmodule.New()
|
|
}
|
|
|
|
func constructGlossaryModule(ctx context.Context, req ConstructRequest) (contracts.TranscriptModule, error) {
|
|
_ = ctx
|
|
_ = req
|
|
return glossarymodule.New()
|
|
}
|
|
|
|
func constructHomophonesModule(ctx context.Context, req ConstructRequest) (contracts.TranscriptModule, error) {
|
|
_ = ctx
|
|
_ = req
|
|
return homophonesmodule.New()
|
|
}
|
|
|
|
func constructSpokenWordModule(ctx context.Context, req ConstructRequest) (contracts.TranscriptModule, error) {
|
|
_ = ctx
|
|
_ = req
|
|
return spokenwordmodule.New()
|
|
}
|
|
|
|
// ModuleForSpec resolves one configured run spec into a module instance.
|
|
func (f *Factory) ModuleForSpec(spec contracts.ModuleRunSpec) (contracts.TranscriptModule, error) {
|
|
if f == nil {
|
|
return nil, fmt.Errorf("module factory is nil")
|
|
}
|
|
|
|
key := strings.TrimSpace(spec.ModuleKey)
|
|
if !IsKnownModuleKey(key) {
|
|
return nil, &UnsupportedModuleError{ModuleKey: key}
|
|
}
|
|
|
|
constructor, ok := f.constructors[key]
|
|
if !ok || constructor == nil {
|
|
return nil, fmt.Errorf("internal module registry error: constructor for module %q is not configured", key)
|
|
}
|
|
|
|
module, err := constructor(context.Background(), ConstructRequest{
|
|
RunSpec: spec,
|
|
Dependencies: Dependencies{
|
|
Config: f.deps.Config,
|
|
Glossary: f.deps.Glossary,
|
|
ProposalLLMClient: f.deps.ProposalLLMClient,
|
|
ProposalLLMScheduler: f.deps.ProposalLLMScheduler,
|
|
ValidationLLMClient: f.deps.ValidationLLMClient,
|
|
ValidationLLMScheduler: f.deps.ValidationLLMScheduler,
|
|
DiagnosticsDir: f.deps.DiagnosticsDir,
|
|
},
|
|
})
|
|
if err != nil {
|
|
return nil, fmt.Errorf("construct module %q: %w", spec.InstanceName, err)
|
|
}
|
|
if module == nil {
|
|
return nil, fmt.Errorf("constructor for module %q returned nil module", key)
|
|
}
|
|
return module, nil
|
|
}
|
|
|
|
// UnsupportedModuleError indicates a configured module key is unknown.
|
|
type UnsupportedModuleError struct {
|
|
ModuleKey string
|
|
}
|
|
|
|
func (e *UnsupportedModuleError) Error() string {
|
|
return fmt.Sprintf("unsupported module key %q", strings.TrimSpace(e.ModuleKey))
|
|
}
|
|
|
|
// ReasonCode returns a stable reason code suitable for reporting.
|
|
func (e *UnsupportedModuleError) ReasonCode() string {
|
|
return ReasonUnsupportedModule
|
|
}
|