Clarify D&D registration composition

This commit is contained in:
2026-07-21 14:48:05 +00:00
parent 6e12c09952
commit b344d16dc1
5 changed files with 329 additions and 252 deletions

View File

@@ -0,0 +1,112 @@
package register
import (
"gitea.maximumdirect.net/eric/notarius/internal/framework/pipeline"
combatextract "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/extract/combatturns"
npcextract "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/extract/npcs"
spellextract "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/extract/spells"
combatnormalize "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/normalize/combatturns"
npcnormalize "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/normalize/npcs"
spellnormalize "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/normalize/spells"
combatinvariants "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/validate/combatturns/invariants"
combatshape "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/validate/combatturns/shape"
combatsourcerefs "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/validate/combatturns/source_refs"
combatrelatedness "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/validate/combatturns/source_relatedness"
npcidentity "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/validate/npcs/identity"
npcshape "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/validate/npcs/shape"
npcsourcerefs "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/validate/npcs/source_refs"
npcrelatedness "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/validate/npcs/source_relatedness"
spellcatalog "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/validate/spells/catalog"
spellshape "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/validate/spells/shape"
spellsourcerefs "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/validate/spells/source_refs"
spellrelatedness "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/validate/spells/source_relatedness"
validjson "gitea.maximumdirect.net/eric/notarius/internal/modules/generic/validate/valid_json"
validjsonschema "gitea.maximumdirect.net/eric/notarius/internal/modules/generic/validate/valid_json_schema"
)
func registerDefaultChains(registry *pipeline.ValidatorChainRegistry) error {
return runRegistrations([]registration{
{name: "spells validator chain", register: func() error {
return registry.Register(pipeline.ValidatorChainMapping{
Stage: pipeline.StageExtract,
Module: spellextract.Key,
Validators: []pipeline.ModuleBinding{
pipeline.Binding(validjson.Key),
pipeline.Binding(validjsonschema.Key),
pipeline.Binding(spellshape.Key),
pipeline.Binding(spellcatalog.Key),
pipeline.Binding(spellsourcerefs.Key),
pipeline.Binding(spellrelatedness.Key),
},
})
}},
{name: "spells normalize validator chain", register: func() error {
return registry.Register(pipeline.ValidatorChainMapping{
Stage: pipeline.StageNormalize,
Module: spellnormalize.Key,
Validators: []pipeline.ModuleBinding{
pipeline.Binding(validjson.Key),
pipeline.Binding(validjsonschema.Key),
pipeline.Binding(spellshape.Key),
pipeline.Binding(spellcatalog.Key),
pipeline.Binding(spellsourcerefs.Key),
pipeline.Binding(spellrelatedness.Key),
},
})
}},
{name: "npcs validator chain", register: func() error {
return registry.Register(pipeline.ValidatorChainMapping{
Stage: pipeline.StageExtract,
Module: npcextract.Key,
Validators: []pipeline.ModuleBinding{
pipeline.Binding(validjson.Key),
pipeline.Binding(validjsonschema.Key),
pipeline.Binding(npcshape.Key),
pipeline.Binding(npcsourcerefs.Key),
pipeline.Binding(npcrelatedness.Key),
},
})
}},
{name: "npcs normalize validator chain", register: func() error {
return registry.Register(pipeline.ValidatorChainMapping{
Stage: pipeline.StageNormalize,
Module: npcnormalize.Key,
Validators: []pipeline.ModuleBinding{
pipeline.Binding(validjson.Key),
pipeline.Binding(validjsonschema.Key),
pipeline.Binding(npcshape.Key),
pipeline.Binding(npcidentity.Key),
pipeline.Binding(npcsourcerefs.Key),
pipeline.Binding(npcrelatedness.Key),
},
})
}},
{name: "combat turns validator chain", register: func() error {
return registry.Register(pipeline.ValidatorChainMapping{
Stage: pipeline.StageExtract,
Module: combatextract.Key,
Validators: []pipeline.ModuleBinding{
pipeline.Binding(validjson.Key),
pipeline.Binding(validjsonschema.Key),
pipeline.Binding(combatshape.Key),
pipeline.Binding(combatsourcerefs.Key),
pipeline.Binding(combatrelatedness.Key),
},
})
}},
{name: "combat turns normalize validator chain", register: func() error {
return registry.Register(pipeline.ValidatorChainMapping{
Stage: pipeline.StageNormalize,
Module: combatnormalize.Key,
Validators: []pipeline.ModuleBinding{
pipeline.Binding(validjson.Key),
pipeline.Binding(validjsonschema.Key),
pipeline.Binding(combatshape.Key),
pipeline.Binding(combatinvariants.Key),
pipeline.Binding(combatsourcerefs.Key),
pipeline.Binding(combatrelatedness.Key),
},
})
}},
})
}

View File

@@ -0,0 +1,83 @@
package register
import (
"gitea.maximumdirect.net/eric/notarius/internal/core/source"
"gitea.maximumdirect.net/eric/notarius/internal/modules/dnd"
)
func appendSpellLists(values []dnd.SpellList) (dnd.SpellList, error) {
count := 0
for _, value := range values {
count += len(value.SpellCasts)
}
combined := dnd.SpellList{SpellCasts: make([]dnd.SpellCast, 0, count)}
for _, value := range values {
combined.SpellCasts = append(combined.SpellCasts, value.SpellCasts...)
}
return combined, nil
}
func appendNPCLists(values []dnd.NPCList) (dnd.NPCList, error) {
count := 0
present := false
for _, value := range values {
if value.NPCs != nil {
present = true
}
count += len(value.NPCs)
}
if !present {
return dnd.NPCList{}, nil
}
combined := dnd.NPCList{NPCs: make([]dnd.NPC, 0, count)}
for _, value := range values {
combined.NPCs = append(combined.NPCs, value.NPCs...)
}
return combined, nil
}
func appendCombatTurnLists(values []dnd.CombatTurnList) (dnd.CombatTurnList, error) {
count := 0
present := false
for _, value := range values {
if value.CombatTurns != nil {
present = true
}
count += len(value.CombatTurns)
}
if !present {
return dnd.CombatTurnList{}, nil
}
combined := dnd.CombatTurnList{CombatTurns: make([]dnd.CombatTurn, 0, count)}
for _, value := range values {
for _, turn := range value.CombatTurns {
combined.CombatTurns = append(combined.CombatTurns, cloneCombatTurn(turn))
}
}
return combined, nil
}
func cloneCombatTurn(value dnd.CombatTurn) dnd.CombatTurn {
clone := value
if value.Round != nil {
round := *value.Round
clone.Round = &round
}
if value.Actions != nil {
clone.Actions = make([]dnd.CombatAction, len(value.Actions))
for index, action := range value.Actions {
clone.Actions[index] = action
if action.Targets != nil {
clone.Actions[index].Targets = append([]string(nil), action.Targets...)
}
if action.Resolution != nil {
resolution := *action.Resolution
clone.Actions[index].Resolution = &resolution
}
}
}
if value.SourceRefs != nil {
clone.SourceRefs = append([]source.SourceRef(nil), value.SourceRefs...)
}
return clone
}

View File

@@ -0,0 +1,62 @@
package register
import (
"gitea.maximumdirect.net/eric/notarius/internal/framework/llm"
"gitea.maximumdirect.net/eric/notarius/internal/framework/pipeline"
"gitea.maximumdirect.net/eric/notarius/internal/modules/dnd"
"gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/chunk/scenes"
combatcodec "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/codec/combatturns"
npccodec "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/codec/npcs"
spellcodec "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/codec/spells"
combatextract "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/extract/combatturns"
npcextract "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/extract/npcs"
spellextract "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/extract/spells"
combatnormalize "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/normalize/combatturns"
npcnormalize "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/normalize/npcs"
spellnormalize "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/normalize/spells"
"gitea.maximumdirect.net/eric/notarius/internal/modules/generic/merge/appendorder"
"gitea.maximumdirect.net/eric/notarius/internal/modules/generic/normalize/noop"
)
func registerModules(registries pipeline.Registries) error {
codec := spellcodec.New()
return runRegistrations([]registration{
{name: "spells codec", register: func() error { return pipeline.RegisterArtifactCodec(registries.ArtifactCodecs, codec) }},
{name: "npcs codec", register: func() error { return pipeline.RegisterArtifactCodec(registries.ArtifactCodecs, npccodec.New()) }},
{name: "combat turns codec", register: func() error { return pipeline.RegisterArtifactCodec(registries.ArtifactCodecs, combatcodec.New()) }},
{name: "scenes chunker", register: func() error { return scenes.Register(registries.Chunkers) }},
{name: "spells extractor", register: func() error { return spellextract.Register(registries.Extractors) }},
{name: "npcs extractor", register: func() error { return npcextract.Register(registries.Extractors) }},
{name: "combat turns extractor", register: func() error { return combatextract.Register(registries.Extractors) }},
{name: "spell-list appendorder merger", register: func() error {
return appendorder.RegisterTyped(registries.Mergers, dnd.SpellListKind, appendSpellLists)
}},
{name: "npc-list appendorder merger", register: func() error {
return appendorder.RegisterTyped(registries.Mergers, dnd.NPCListKind, appendNPCLists)
}},
{name: "combat-turn-list appendorder merger", register: func() error {
return appendorder.RegisterTyped(registries.Mergers, dnd.CombatTurnListKind, appendCombatTurnLists)
}},
{name: "spells normalizer", register: func() error { return spellnormalize.Register(registries.Normalizers) }},
{name: "npcs normalizer", register: func() error { return npcnormalize.Register(registries.Normalizers) }},
{name: "combat turns normalizer", register: func() error { return combatnormalize.Register(registries.Normalizers) }},
{name: "spell-list noop normalizer", register: func() error {
return noop.RegisterTyped[dnd.SpellList](registries.Normalizers, dnd.SpellListKind)
}},
{name: "npc-list noop normalizer", register: func() error {
return noop.RegisterTyped[dnd.NPCList](registries.Normalizers, dnd.NPCListKind)
}},
{name: "combat-turn-list noop normalizer", register: func() error {
return noop.RegisterTyped[dnd.CombatTurnList](registries.Normalizers, dnd.CombatTurnListKind)
}},
})
}
func registerPromptAssets(assets *llm.AssetRegistry) error {
return runRegistrations([]registration{
{name: "scenes prompt assets", register: func() error { return scenes.RegisterPromptAssets(assets) }},
{name: "spells prompt assets", register: func() error { return spellextract.RegisterPromptAssets(assets) }},
{name: "npcs prompt assets", register: func() error { return npcextract.RegisterPromptAssets(assets) }},
{name: "combat turns prompt assets", register: func() error { return combatextract.RegisterPromptAssets(assets) }},
})
}

View File

@@ -4,276 +4,41 @@ package register
import (
"fmt"
"gitea.maximumdirect.net/eric/notarius/internal/core/source"
"gitea.maximumdirect.net/eric/notarius/internal/framework/llm"
"gitea.maximumdirect.net/eric/notarius/internal/framework/pipeline"
"gitea.maximumdirect.net/eric/notarius/internal/modules/dnd"
"gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/chunk/scenes"
combatcodec "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/codec/combatturns"
npccodec "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/codec/npcs"
spellcodec "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/codec/spells"
combatextract "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/extract/combatturns"
npcextract "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/extract/npcs"
"gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/extract/spells"
combatnormalize "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/normalize/combatturns"
npcnormalize "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/normalize/npcs"
spellnormalize "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/normalize/spells"
combatinvariants "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/validate/combatturns/invariants"
combatshape "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/validate/combatturns/shape"
combatsourcerefs "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/validate/combatturns/source_refs"
combatrelatedness "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/validate/combatturns/source_relatedness"
npcidentity "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/validate/npcs/identity"
npcshape "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/validate/npcs/shape"
npcsourcerefs "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/validate/npcs/source_refs"
npcrelatedness "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/validate/npcs/source_relatedness"
spellcatalog "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/validate/spells/catalog"
spellshape "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/validate/spells/shape"
spellsourcerefs "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/validate/spells/source_refs"
spellrelatedness "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/validate/spells/source_relatedness"
"gitea.maximumdirect.net/eric/notarius/internal/modules/generic/merge/appendorder"
"gitea.maximumdirect.net/eric/notarius/internal/modules/generic/normalize/noop"
alwaysaccept "gitea.maximumdirect.net/eric/notarius/internal/modules/generic/validate/always_accept"
alwaysreject "gitea.maximumdirect.net/eric/notarius/internal/modules/generic/validate/always_reject"
validjson "gitea.maximumdirect.net/eric/notarius/internal/modules/generic/validate/valid_json"
validjsonschema "gitea.maximumdirect.net/eric/notarius/internal/modules/generic/validate/valid_json_schema"
)
type registration struct {
name string
register func() error
}
// Register adds all production D&D modules, validators, policy, and assets.
func Register(registries pipeline.Registries, assets *llm.AssetRegistry) error {
if err := validateRegistries(registries, assets); err != nil {
return err
}
codec := spellcodec.New()
registrations := []struct {
name string
register func() error
}{
{name: "spells codec", register: func() error { return pipeline.RegisterArtifactCodec(registries.ArtifactCodecs, codec) }},
{name: "npcs codec", register: func() error { return pipeline.RegisterArtifactCodec(registries.ArtifactCodecs, npccodec.New()) }},
{name: "combat turns codec", register: func() error { return pipeline.RegisterArtifactCodec(registries.ArtifactCodecs, combatcodec.New()) }},
{name: "scenes chunker", register: func() error { return scenes.Register(registries.Chunkers) }},
{name: "spells extractor", register: func() error { return spells.Register(registries.Extractors) }},
{name: "npcs extractor", register: func() error { return npcextract.Register(registries.Extractors) }},
{name: "combat turns extractor", register: func() error { return combatextract.Register(registries.Extractors) }},
{name: "spell-list appendorder merger", register: func() error {
return appendorder.RegisterTyped(registries.Mergers, dnd.SpellListKind, appendSpellLists)
}},
{name: "npc-list appendorder merger", register: func() error {
return appendorder.RegisterTyped(registries.Mergers, dnd.NPCListKind, appendNPCLists)
}},
{name: "combat-turn-list appendorder merger", register: func() error {
return appendorder.RegisterTyped(registries.Mergers, dnd.CombatTurnListKind, appendCombatTurnLists)
}},
{name: "spells normalizer", register: func() error { return spellnormalize.Register(registries.Normalizers) }},
{name: "npcs normalizer", register: func() error { return npcnormalize.Register(registries.Normalizers) }},
{name: "combat turns normalizer", register: func() error { return combatnormalize.Register(registries.Normalizers) }},
{name: "spell-list noop normalizer", register: func() error { return noop.RegisterTyped[dnd.SpellList](registries.Normalizers, dnd.SpellListKind) }},
{name: "npc-list noop normalizer", register: func() error { return noop.RegisterTyped[dnd.NPCList](registries.Normalizers, dnd.NPCListKind) }},
{name: "combat-turn-list noop normalizer", register: func() error {
return noop.RegisterTyped[dnd.CombatTurnList](registries.Normalizers, dnd.CombatTurnListKind)
}},
{name: "spell shape validator", register: func() error { return spellshape.Register(registries.Validators) }},
{name: "spell catalog validator", register: func() error { return spellcatalog.Register(registries.Validators) }},
{name: "spell source references validator", register: func() error { return spellsourcerefs.Register(registries.Validators) }},
{name: "spell source relatedness validator", register: func() error { return spellrelatedness.Register(registries.Validators) }},
{name: "npc shape validator", register: func() error { return npcshape.Register(registries.Validators) }},
{name: "npc identity validator", register: func() error { return npcidentity.Register(registries.Validators) }},
{name: "npc source references validator", register: func() error { return npcsourcerefs.Register(registries.Validators) }},
{name: "npc source relatedness validator", register: func() error { return npcrelatedness.Register(registries.Validators) }},
{name: "combat shape validator", register: func() error { return combatshape.Register(registries.Validators) }},
{name: "combat source references validator", register: func() error { return combatsourcerefs.Register(registries.Validators) }},
{name: "combat source relatedness validator", register: func() error { return combatrelatedness.Register(registries.Validators) }},
{name: "combat normalized invariants validator", register: func() error { return combatinvariants.Register(registries.Validators) }},
{name: "spell-list always accept validator", register: func() error {
return alwaysaccept.RegisterTyped[dnd.SpellList](registries.Validators, dnd.SpellListKind)
}},
{name: "spell-list always reject validator", register: func() error {
return alwaysreject.RegisterTyped[dnd.SpellList](registries.Validators, dnd.SpellListKind)
}},
{name: "npc-list always accept validator", register: func() error {
return alwaysaccept.RegisterTyped[dnd.NPCList](registries.Validators, dnd.NPCListKind)
}},
{name: "npc-list always reject validator", register: func() error {
return alwaysreject.RegisterTyped[dnd.NPCList](registries.Validators, dnd.NPCListKind)
}},
{name: "combat-turn-list always accept validator", register: func() error {
return alwaysaccept.RegisterTyped[dnd.CombatTurnList](registries.Validators, dnd.CombatTurnListKind)
}},
{name: "combat-turn-list always reject validator", register: func() error {
return alwaysreject.RegisterTyped[dnd.CombatTurnList](registries.Validators, dnd.CombatTurnListKind)
}},
{name: "scenes prompt assets", register: func() error { return scenes.RegisterPromptAssets(assets) }},
{name: "spells prompt assets", register: func() error { return spells.RegisterPromptAssets(assets) }},
{name: "npcs prompt assets", register: func() error { return npcextract.RegisterPromptAssets(assets) }},
{name: "combat turns prompt assets", register: func() error { return combatextract.RegisterPromptAssets(assets) }},
if err := registerModules(registries); err != nil {
return err
}
if err := registerValidators(registries); err != nil {
return err
}
if err := registerPromptAssets(assets); err != nil {
return err
}
return registerDefaultChains(registries.ValidatorChains)
}
func runRegistrations(registrations []registration) error {
for _, registration := range registrations {
if err := registration.register(); err != nil {
return fmt.Errorf("register dnd %s: %w", registration.name, err)
}
}
if err := registries.ValidatorChains.Register(pipeline.ValidatorChainMapping{
Stage: pipeline.StageExtract,
Module: spells.Key,
Validators: []pipeline.ModuleBinding{
pipeline.Binding(validjson.Key),
pipeline.Binding(validjsonschema.Key),
pipeline.Binding(spellshape.Key),
pipeline.Binding(spellcatalog.Key),
pipeline.Binding(spellsourcerefs.Key),
pipeline.Binding(spellrelatedness.Key),
},
}); err != nil {
return fmt.Errorf("register dnd spells validator chain: %w", err)
}
if err := registries.ValidatorChains.Register(pipeline.ValidatorChainMapping{
Stage: pipeline.StageNormalize,
Module: spellnormalize.Key,
Validators: []pipeline.ModuleBinding{
pipeline.Binding(validjson.Key),
pipeline.Binding(validjsonschema.Key),
pipeline.Binding(spellshape.Key),
pipeline.Binding(spellcatalog.Key),
pipeline.Binding(spellsourcerefs.Key),
pipeline.Binding(spellrelatedness.Key),
},
}); err != nil {
return fmt.Errorf("register dnd spells normalize validator chain: %w", err)
}
if err := registries.ValidatorChains.Register(pipeline.ValidatorChainMapping{
Stage: pipeline.StageExtract,
Module: npcextract.Key,
Validators: []pipeline.ModuleBinding{
pipeline.Binding(validjson.Key),
pipeline.Binding(validjsonschema.Key),
pipeline.Binding(npcshape.Key),
pipeline.Binding(npcsourcerefs.Key),
pipeline.Binding(npcrelatedness.Key),
},
}); err != nil {
return fmt.Errorf("register dnd npcs validator chain: %w", err)
}
if err := registries.ValidatorChains.Register(pipeline.ValidatorChainMapping{
Stage: pipeline.StageNormalize,
Module: npcnormalize.Key,
Validators: []pipeline.ModuleBinding{
pipeline.Binding(validjson.Key),
pipeline.Binding(validjsonschema.Key),
pipeline.Binding(npcshape.Key),
pipeline.Binding(npcidentity.Key),
pipeline.Binding(npcsourcerefs.Key),
pipeline.Binding(npcrelatedness.Key),
},
}); err != nil {
return fmt.Errorf("register dnd npcs normalize validator chain: %w", err)
}
if err := registries.ValidatorChains.Register(pipeline.ValidatorChainMapping{
Stage: pipeline.StageExtract,
Module: combatextract.Key,
Validators: []pipeline.ModuleBinding{
pipeline.Binding(validjson.Key),
pipeline.Binding(validjsonschema.Key),
pipeline.Binding(combatshape.Key),
pipeline.Binding(combatsourcerefs.Key),
pipeline.Binding(combatrelatedness.Key),
},
}); err != nil {
return fmt.Errorf("register dnd combat turns validator chain: %w", err)
}
if err := registries.ValidatorChains.Register(pipeline.ValidatorChainMapping{
Stage: pipeline.StageNormalize,
Module: combatnormalize.Key,
Validators: []pipeline.ModuleBinding{
pipeline.Binding(validjson.Key),
pipeline.Binding(validjsonschema.Key),
pipeline.Binding(combatshape.Key),
pipeline.Binding(combatinvariants.Key),
pipeline.Binding(combatsourcerefs.Key),
pipeline.Binding(combatrelatedness.Key),
},
}); err != nil {
return fmt.Errorf("register dnd combat turns normalize validator chain: %w", err)
}
return nil
}
func appendSpellLists(values []dnd.SpellList) (dnd.SpellList, error) {
count := 0
for _, value := range values {
count += len(value.SpellCasts)
}
combined := dnd.SpellList{SpellCasts: make([]dnd.SpellCast, 0, count)}
for _, value := range values {
combined.SpellCasts = append(combined.SpellCasts, value.SpellCasts...)
}
return combined, nil
}
func appendNPCLists(values []dnd.NPCList) (dnd.NPCList, error) {
count := 0
present := false
for _, value := range values {
if value.NPCs != nil {
present = true
}
count += len(value.NPCs)
}
if !present {
return dnd.NPCList{}, nil
}
combined := dnd.NPCList{NPCs: make([]dnd.NPC, 0, count)}
for _, value := range values {
combined.NPCs = append(combined.NPCs, value.NPCs...)
}
return combined, nil
}
func appendCombatTurnLists(values []dnd.CombatTurnList) (dnd.CombatTurnList, error) {
count := 0
present := false
for _, value := range values {
if value.CombatTurns != nil {
present = true
}
count += len(value.CombatTurns)
}
if !present {
return dnd.CombatTurnList{}, nil
}
combined := dnd.CombatTurnList{CombatTurns: make([]dnd.CombatTurn, 0, count)}
for _, value := range values {
for _, turn := range value.CombatTurns {
combined.CombatTurns = append(combined.CombatTurns, cloneCombatTurn(turn))
}
}
return combined, nil
}
func cloneCombatTurn(value dnd.CombatTurn) dnd.CombatTurn {
clone := value
if value.Round != nil {
round := *value.Round
clone.Round = &round
}
if value.Actions != nil {
clone.Actions = make([]dnd.CombatAction, len(value.Actions))
for index, action := range value.Actions {
clone.Actions[index] = action
if action.Targets != nil {
clone.Actions[index].Targets = append([]string(nil), action.Targets...)
}
if action.Resolution != nil {
resolution := *action.Resolution
clone.Actions[index].Resolution = &resolution
}
}
}
if value.SourceRefs != nil {
clone.SourceRefs = append([]source.SourceRef(nil), value.SourceRefs...)
}
return clone
}
func validateRegistries(registries pipeline.Registries, assets *llm.AssetRegistry) error {
switch {
case registries.Chunkers == nil:

View File

@@ -0,0 +1,55 @@
package register
import (
"gitea.maximumdirect.net/eric/notarius/internal/framework/pipeline"
"gitea.maximumdirect.net/eric/notarius/internal/modules/dnd"
combatinvariants "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/validate/combatturns/invariants"
combatshape "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/validate/combatturns/shape"
combatsourcerefs "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/validate/combatturns/source_refs"
combatrelatedness "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/validate/combatturns/source_relatedness"
npcidentity "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/validate/npcs/identity"
npcshape "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/validate/npcs/shape"
npcsourcerefs "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/validate/npcs/source_refs"
npcrelatedness "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/validate/npcs/source_relatedness"
spellcatalog "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/validate/spells/catalog"
spellshape "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/validate/spells/shape"
spellsourcerefs "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/validate/spells/source_refs"
spellrelatedness "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/validate/spells/source_relatedness"
alwaysaccept "gitea.maximumdirect.net/eric/notarius/internal/modules/generic/validate/always_accept"
alwaysreject "gitea.maximumdirect.net/eric/notarius/internal/modules/generic/validate/always_reject"
)
func registerValidators(registries pipeline.Registries) error {
return runRegistrations([]registration{
{name: "spell shape validator", register: func() error { return spellshape.Register(registries.Validators) }},
{name: "spell catalog validator", register: func() error { return spellcatalog.Register(registries.Validators) }},
{name: "spell source references validator", register: func() error { return spellsourcerefs.Register(registries.Validators) }},
{name: "spell source relatedness validator", register: func() error { return spellrelatedness.Register(registries.Validators) }},
{name: "npc shape validator", register: func() error { return npcshape.Register(registries.Validators) }},
{name: "npc identity validator", register: func() error { return npcidentity.Register(registries.Validators) }},
{name: "npc source references validator", register: func() error { return npcsourcerefs.Register(registries.Validators) }},
{name: "npc source relatedness validator", register: func() error { return npcrelatedness.Register(registries.Validators) }},
{name: "combat shape validator", register: func() error { return combatshape.Register(registries.Validators) }},
{name: "combat source references validator", register: func() error { return combatsourcerefs.Register(registries.Validators) }},
{name: "combat source relatedness validator", register: func() error { return combatrelatedness.Register(registries.Validators) }},
{name: "combat normalized invariants validator", register: func() error { return combatinvariants.Register(registries.Validators) }},
{name: "spell-list always accept validator", register: func() error {
return alwaysaccept.RegisterTyped[dnd.SpellList](registries.Validators, dnd.SpellListKind)
}},
{name: "spell-list always reject validator", register: func() error {
return alwaysreject.RegisterTyped[dnd.SpellList](registries.Validators, dnd.SpellListKind)
}},
{name: "npc-list always accept validator", register: func() error {
return alwaysaccept.RegisterTyped[dnd.NPCList](registries.Validators, dnd.NPCListKind)
}},
{name: "npc-list always reject validator", register: func() error {
return alwaysreject.RegisterTyped[dnd.NPCList](registries.Validators, dnd.NPCListKind)
}},
{name: "combat-turn-list always accept validator", register: func() error {
return alwaysaccept.RegisterTyped[dnd.CombatTurnList](registries.Validators, dnd.CombatTurnListKind)
}},
{name: "combat-turn-list always reject validator", register: func() error {
return alwaysreject.RegisterTyped[dnd.CombatTurnList](registries.Validators, dnd.CombatTurnListKind)
}},
})
}