Move NPC registry to canonical namespace
This commit is contained in:
@@ -12,7 +12,7 @@ import (
|
||||
"gitea.maximumdirect.net/eric/notarius/internal/framework/contracts"
|
||||
"gitea.maximumdirect.net/eric/notarius/internal/framework/pipeline"
|
||||
"gitea.maximumdirect.net/eric/notarius/internal/modules/dnd"
|
||||
npccodec "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/codec/npcs"
|
||||
npccodec "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/codec/npcregistry"
|
||||
scenecodec "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/codec/scenedescriptions"
|
||||
"gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/npcs/identity"
|
||||
)
|
||||
|
||||
@@ -25,7 +25,7 @@ var promptAssetManifest = shared.PromptAssetManifest{
|
||||
"common-dnd-identity.md",
|
||||
"common-dnd-transcript-chunk.md",
|
||||
"common-dnd-references.md",
|
||||
"common-dnd-npcs.md",
|
||||
"common-dnd-npc-registry.md",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -49,11 +49,11 @@ func TestPromptAssetsPrepareRequiredInputs(t *testing.T) {
|
||||
prepared, err := engine.Prepare(context.Background(), promptkit.RunRequest{
|
||||
PromptID: PromptID, PromptVersion: SchemaVersion, ProfileID: "combat-test-profile",
|
||||
Inputs: map[string]promptkit.ArtifactRef{
|
||||
"transcript": promptkit.InlineWithURI("file:///session.json", transcript),
|
||||
"players": promptkit.Inline("combat-player"),
|
||||
"party": promptkit.Inline(" "),
|
||||
"glossary": promptkit.Inline(" "),
|
||||
"npcs": promptkit.Inline(`{"npcs":[{"name":"combat-npc"}]}`),
|
||||
"transcript": promptkit.InlineWithURI("file:///session.json", transcript),
|
||||
"players": promptkit.Inline("combat-player"),
|
||||
"party": promptkit.Inline(" "),
|
||||
"glossary": promptkit.Inline(" "),
|
||||
"npc_registry": promptkit.Inline(`{"npcs":[{"name":"combat-npc"}]}`),
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
|
||||
@@ -16,7 +16,7 @@ import (
|
||||
"gitea.maximumdirect.net/eric/notarius/internal/modules/dnd"
|
||||
combatturncodec "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/codec/combatturns"
|
||||
interactioncodec "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/codec/npcinteractions"
|
||||
npccodec "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/codec/npcs"
|
||||
npccodec "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/codec/npcregistry"
|
||||
scenecodec "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/codec/scenedescriptions"
|
||||
npcregistry "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/npcs/registry"
|
||||
sceneregistry "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/scenedescriptions/registry"
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
"gitea.maximumdirect.net/eric/notarius/internal/modules/dnd"
|
||||
combatturncodec "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/codec/combatturns"
|
||||
interactioncodec "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/codec/npcinteractions"
|
||||
npccodec "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/codec/npcs"
|
||||
npccodec "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/codec/npcregistry"
|
||||
scenecodec "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/codec/scenedescriptions"
|
||||
"gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/npcs/identity"
|
||||
sceneregistry "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/scenedescriptions/registry"
|
||||
|
||||
@@ -26,7 +26,7 @@ var promptAssetManifest = shared.PromptAssetManifest{
|
||||
"common-dnd-identity.md",
|
||||
"common-dnd-transcript-chunk.md",
|
||||
"common-dnd-references.md",
|
||||
"common-dnd-npcs.md",
|
||||
"common-dnd-npc-registry.md",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ func TestRegisterPromptAssetsAndPrepareEnemyEventPrompt(t *testing.T) {
|
||||
|
||||
func TestEnemyEventPromptRequiresGroundingInputs(t *testing.T) {
|
||||
engine := newEnemyEventPromptEngine(t)
|
||||
for _, inputName := range []string{"npcs", "combat_turns", "npc_interactions"} {
|
||||
for _, inputName := range []string{"npc_registry", "combat_turns", "npc_interactions"} {
|
||||
t.Run(inputName, func(t *testing.T) {
|
||||
inputs := enemyEventPromptInputs()
|
||||
delete(inputs, inputName)
|
||||
@@ -83,7 +83,7 @@ func enemyEventPromptInputs() map[string]promptkit.ArtifactRef {
|
||||
"players": promptkit.Inline("enemy-player"),
|
||||
"party": promptkit.Inline("enemy-party"),
|
||||
"glossary": promptkit.Inline("enemy-glossary"),
|
||||
"npcs": promptkit.Inline(`{"npcs":[{"name":"enemy-npc"}]}`),
|
||||
"npc_registry": promptkit.Inline(`{"npcs":[{"name":"enemy-npc"}]}`),
|
||||
"combat_turns": promptkit.Inline(`{"combat_turns":[{"actor":"enemy-turn","turn_kind":"turn"}]}`),
|
||||
"npc_interactions": promptkit.Inline(`{"npc_interactions":[{"name":"enemy-opponent","kind":"combat_opponent"}]}`),
|
||||
}
|
||||
|
||||
@@ -121,7 +121,7 @@ func TestExtractUsesOnlySupportedPromptInputs(t *testing.T) {
|
||||
"players": {Slot: contracts.ReferenceSlot{Name: "players"}, Items: []contracts.ReferenceItem{{SlotName: "players", Content: []byte("Dana: Aria")}}},
|
||||
"party": {Slot: contracts.ReferenceSlot{Name: "party"}, Items: []contracts.ReferenceItem{{SlotName: "party", Content: []byte("Aria: ranger")}}},
|
||||
"glossary": {Slot: contracts.ReferenceSlot{Name: "glossary"}, Items: []contracts.ReferenceItem{{SlotName: "glossary", Content: []byte("Moonblade: heirloom")}}},
|
||||
"npcs": {Slot: contracts.ReferenceSlot{Name: "npcs"}, Items: []contracts.ReferenceItem{{SlotName: "npcs", Content: []byte("must not be used")}}},
|
||||
"npcs": {Slot: contracts.ReferenceSlot{Name: "npc_registry"}, Items: []contracts.ReferenceItem{{SlotName: "npc_registry", Content: []byte("must not be used")}}},
|
||||
}}
|
||||
if _, err := newExtractor(t, client).Extract(context.Background(), req); err != nil {
|
||||
t.Fatal(err)
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
"gitea.maximumdirect.net/eric/notarius/internal/framework/contracts"
|
||||
"gitea.maximumdirect.net/eric/notarius/internal/framework/pipeline"
|
||||
"gitea.maximumdirect.net/eric/notarius/internal/modules/dnd"
|
||||
npccodec "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/codec/npcs"
|
||||
npccodec "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/codec/npcregistry"
|
||||
"gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/npcs/identity"
|
||||
)
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ var promptAssetManifest = shared.PromptAssetManifest{
|
||||
"common-dnd-identity.md",
|
||||
"common-dnd-transcript-chunk.md",
|
||||
"common-dnd-references.md",
|
||||
"common-dnd-npcs.md",
|
||||
"common-dnd-npc-registry.md",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -38,11 +38,11 @@ func TestRegisterPromptAssetsAndPrepareInteractionPrompt(t *testing.T) {
|
||||
prepared, err := engine.Prepare(context.Background(), promptkit.RunRequest{
|
||||
PromptID: PromptID, PromptVersion: SchemaVersion, ProfileID: "npc-interactions-test-profile",
|
||||
Inputs: map[string]promptkit.ArtifactRef{
|
||||
"transcript": promptkit.InlineWithURI("file:///session.json", transcript),
|
||||
"players": promptkit.Inline("interaction-player"),
|
||||
"party": promptkit.Inline("Mira: ranger"),
|
||||
"glossary": promptkit.Inline("Greencloak: title"),
|
||||
"npcs": promptkit.Inline(`{"npcs":[{"name":"interaction-npc"}]}`),
|
||||
"transcript": promptkit.InlineWithURI("file:///session.json", transcript),
|
||||
"players": promptkit.Inline("interaction-player"),
|
||||
"party": promptkit.Inline("Mira: ranger"),
|
||||
"glossary": promptkit.Inline("Greencloak: title"),
|
||||
"npc_registry": promptkit.Inline(`{"npcs":[{"name":"interaction-npc"}]}`),
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package npcs
|
||||
package npcregistry
|
||||
|
||||
import (
|
||||
"sort"
|
||||
@@ -1,4 +1,4 @@
|
||||
package npcs
|
||||
package npcregistry
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -11,9 +11,9 @@ import (
|
||||
"gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/shared"
|
||||
)
|
||||
|
||||
const Key = "dnd/npcs"
|
||||
const Key = "dnd/npc-registry"
|
||||
|
||||
const mappingPolicy = "dnd.npcs.extract_mapping.v2"
|
||||
const mappingPolicy = "dnd.npc_registry.extract_mapping.v2"
|
||||
|
||||
var requiredCapabilities = []string{
|
||||
"chunks",
|
||||
@@ -21,7 +21,7 @@ var requiredCapabilities = []string{
|
||||
}
|
||||
|
||||
var providedCapabilities = []string{
|
||||
"dnd.npcs",
|
||||
"dnd.npc_registry",
|
||||
}
|
||||
|
||||
var referenceSlotDescriptions = shared.ReferenceSlotDescriptions{
|
||||
@@ -166,5 +166,5 @@ func DecodeOptions(options map[string]any) (Options, error) {
|
||||
}
|
||||
|
||||
func extractorErrorf(format string, args ...any) error {
|
||||
return fmt.Errorf("dnd npcs extractor: "+format, args...)
|
||||
return fmt.Errorf("dnd npc registry extractor: "+format, args...)
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package npcs
|
||||
package npcregistry
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -188,13 +188,13 @@ func TestExtractRetainsLocalErrorContextAndProviderFailures(t *testing.T) {
|
||||
{name: "wrapped preflight failure", extractor: extractor, req: mismatchedSourceInputRequest(request), want: "must match chunk"},
|
||||
} {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
if _, err := test.extractor.Extract(context.Background(), test.req); err == nil || !strings.Contains(err.Error(), "dnd npcs") || !strings.Contains(err.Error(), test.want) {
|
||||
if _, err := test.extractor.Extract(context.Background(), test.req); err == nil || !strings.Contains(err.Error(), "dnd npc registry") || !strings.Contains(err.Error(), test.want) {
|
||||
t.Fatalf("Extract() error = %v, want contextual local error", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
_, err := newExtractor(t, &fakeNPCsLLMClient{err: errors.New("provider unavailable")}).Extract(context.Background(), request)
|
||||
if err == nil || !strings.Contains(err.Error(), "dnd npcs") || !strings.Contains(err.Error(), "provider unavailable") {
|
||||
if err == nil || !strings.Contains(err.Error(), "dnd npc registry") || !strings.Contains(err.Error(), "provider unavailable") {
|
||||
t.Fatalf("provider Extract() error = %v, want contextual provider error", err)
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package npcs
|
||||
package npcregistry
|
||||
|
||||
type extractionResponse struct {
|
||||
NPCs []npcResponse `json:"npcs"`
|
||||
@@ -1,4 +1,4 @@
|
||||
package npcs
|
||||
package npcregistry
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -14,7 +14,7 @@ import (
|
||||
const promptAssetRoot = "assets/prompts"
|
||||
|
||||
var promptAssetManifest = shared.PromptAssetManifest{
|
||||
ModuleDir: "dnd.npcs",
|
||||
ModuleDir: "dnd.npc_registry",
|
||||
ModuleFiles: []promptfs.ModulePromptFile{
|
||||
{Name: "prompt.yaml", Path: "prompts/prompt.yaml"},
|
||||
{Name: "instructions.md", Path: "prompts/instructions.md"},
|
||||
@@ -29,7 +29,7 @@ var promptAssetManifest = shared.PromptAssetManifest{
|
||||
}
|
||||
|
||||
func moduleAssetFS() (fs.FS, error) {
|
||||
assets, err := fs.Sub(rootassets.FS(), "dnd/npcs/extract")
|
||||
assets, err := fs.Sub(rootassets.FS(), "dnd/npc-registry/extract")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("scope NPC extraction assets: %w", err)
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package npcs
|
||||
package npcregistry
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -39,7 +39,7 @@ func TestRegisterPromptAssetsAndPrepareNPCPrompt(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("Prepare() error = %v, want nil", err)
|
||||
}
|
||||
if prepared.PromptID != PromptID || prepared.OutputContract.SchemaPath != "dnd_npcs_llm.v1.json" {
|
||||
if prepared.PromptID != PromptID || prepared.OutputContract.SchemaPath != "dnd_npc_registry_llm.v1.json" {
|
||||
t.Fatalf("prepared prompt = %#v, want NPC prompt identity and wiring", prepared)
|
||||
}
|
||||
}
|
||||
@@ -54,7 +54,7 @@ func TestPromptMetadataAndDiagnosticsDoNotContainRawAssets(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, forbidden := range []string{"common-dnd-system", "dnd_npcs_llm.v1.json"} {
|
||||
for _, forbidden := range []string{"common-dnd-system", "dnd_npc_registry_llm.v1.json"} {
|
||||
if strings.Contains(string(payload), forbidden) {
|
||||
t.Fatalf("metadata leaked raw prompt/schema content %q: %s", forbidden, payload)
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package npcs
|
||||
package npcregistry
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
@@ -29,7 +29,7 @@ func TestModuleSpecAndReferenceSlots(t *testing.T) {
|
||||
Stage: pipeline.StageExtract,
|
||||
ExecutionClass: contracts.ExecutionClassLLMBacked,
|
||||
Requires: []string{"chunks", "source.transcript"},
|
||||
Provides: []string{"dnd.npcs"},
|
||||
Provides: []string{"dnd.npc_registry"},
|
||||
ArtifactKind: dnd.NPCRegistryKind,
|
||||
ReferenceSlots: []contracts.ReferenceSlot{
|
||||
{Name: "glossary", Description: "Optional campaign glossary reference material used only for NPC disambiguation.", AcceptedMediaTypes: []string{"application/json", "application/x-yaml", "application/yaml", "text/markdown", "text/plain"}},
|
||||
@@ -1,12 +1,12 @@
|
||||
package npcs
|
||||
package npcregistry
|
||||
|
||||
import "gitea.maximumdirect.net/eric/notarius/internal/framework/llm"
|
||||
|
||||
const (
|
||||
PromptID = "dnd.npcs"
|
||||
ResponseSchemaKey = llm.ResponseSchemaKey("dnd_npcs_llm")
|
||||
ResponseSchemaID = "notarius.dnd.npcs.llm"
|
||||
ResponseSchemaName = "notarius_dnd_npcs_llm_v1"
|
||||
PromptID = "dnd.npc_registry"
|
||||
ResponseSchemaKey = llm.ResponseSchemaKey("dnd_npc_registry_llm")
|
||||
ResponseSchemaID = "notarius.dnd.npc_registry.llm"
|
||||
ResponseSchemaName = "notarius_dnd_npc_registry_llm_v1"
|
||||
SchemaVersion = "v1"
|
||||
)
|
||||
|
||||
@@ -20,6 +20,6 @@ func loadResponseSchema() (llm.ResponseSchema, error) {
|
||||
ID: ResponseSchemaID,
|
||||
Version: SchemaVersion,
|
||||
Name: ResponseSchemaName,
|
||||
AssetPath: "schemas/dnd_npcs_llm.v1.json",
|
||||
AssetPath: "schemas/dnd_npc_registry_llm.v1.json",
|
||||
})
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package npcs
|
||||
package npcregistry
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -1,4 +1,4 @@
|
||||
package npcs
|
||||
package npcregistry
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
"gitea.maximumdirect.net/eric/notarius/internal/framework/contracts"
|
||||
"gitea.maximumdirect.net/eric/notarius/internal/framework/pipeline"
|
||||
"gitea.maximumdirect.net/eric/notarius/internal/modules/dnd"
|
||||
npccodec "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/codec/npcs"
|
||||
npccodec "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/codec/npcregistry"
|
||||
"gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/npcs/identity"
|
||||
"gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/npcs/registry"
|
||||
)
|
||||
|
||||
@@ -26,7 +26,7 @@ var promptAssetManifest = shared.PromptAssetManifest{
|
||||
"common-dnd-identity.md",
|
||||
"common-dnd-transcript-chunk.md",
|
||||
"common-dnd-references.md",
|
||||
"common-dnd-npcs.md",
|
||||
"common-dnd-npc-registry.md",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -108,7 +108,7 @@ func prepareSpellsPrompt(t *testing.T, transcript []byte, players string, party
|
||||
Inputs: map[string]promptkit.ArtifactRef{
|
||||
"transcript": promptkit.InlineWithURI("file:///session.json", string(transcript)),
|
||||
"spell_catalog": promptkit.Inline(`{"spell_names":["spell-catalog-sentinel"]}`),
|
||||
"npcs": promptkit.Inline(`{"npcs":[{"name":"spell-npc-sentinel"}]}`),
|
||||
"npc_registry": promptkit.Inline(`{"npcs":[{"name":"spell-npc-sentinel"}]}`),
|
||||
"players": promptkit.Inline(players),
|
||||
"party": promptkit.Inline(party),
|
||||
"glossary": promptkit.Inline(glossary),
|
||||
|
||||
Reference in New Issue
Block a user