Make D&D prompt assets provider neutral

This commit is contained in:
2026-07-28 16:42:41 +00:00
parent 8e04ef9e2b
commit 7c569a3d8c
25 changed files with 103 additions and 103 deletions

View File

@@ -2,9 +2,9 @@
## Status ## Status
In progress. The dependency, framework adapter, and version 4 PromptKit In progress. The dependency, framework adapter, version 4 PromptKit
configuration migration are implemented; module asset terminology and remaining configuration migration, and provider-neutral module prompt-asset support are
provenance alignment are still planned. implemented; remaining provenance alignment is still planned.
## Objective ## Objective

View File

@@ -56,7 +56,7 @@ func (c *Chunker) ReferenceSlots() []contracts.ReferenceSlot {
} }
func (c *Chunker) ManifestMetadata() map[string]any { func (c *Chunker) ManifestMetadata() map[string]any {
promptSHA, err := scriptoriumPromptMetadata() promptSHA, err := promptAssetMetadata()
if err != nil { if err != nil {
promptSHA = "" promptSHA = ""
} }

View File

@@ -9,7 +9,7 @@ import (
"gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/shared" "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/shared"
) )
const scriptoriumPromptRoot = "assets/prompts" const promptAssetRoot = "assets/prompts"
var promptAssetManifest = shared.PromptAssetManifest{ var promptAssetManifest = shared.PromptAssetManifest{
ModuleDir: "dnd.scenes", ModuleDir: "dnd.scenes",
@@ -30,21 +30,21 @@ func RegisterPromptAssets(registry *llm.AssetRegistry) error {
if err != nil { if err != nil {
return fmt.Errorf("prepare scene prompt assets: %w", err) return fmt.Errorf("prepare scene prompt assets: %w", err)
} }
if err := registry.RegisterPromptFS(promptFS, scriptoriumPromptRoot); err != nil { if err := registry.RegisterPromptFS(promptFS, promptAssetRoot); err != nil {
return err return err
} }
return registry.RegisterSchemaFS(embeddedAssets, "assets/schemas") return registry.RegisterSchemaFS(embeddedAssets, "assets/schemas")
} }
func scriptoriumPromptMetadata() (string, error) { func promptAssetMetadata() (string, error) {
scriptoriumPromptHashOnce.Do(func() { promptAssetHashOnce.Do(func() {
scriptoriumPromptHash, scriptoriumPromptHashErr = promptAssetManifest.Hash(embeddedAssets) promptAssetHash, promptAssetHashErr = promptAssetManifest.Hash(embeddedAssets)
}) })
return scriptoriumPromptHash, scriptoriumPromptHashErr return promptAssetHash, promptAssetHashErr
} }
var ( var (
scriptoriumPromptHashOnce sync.Once promptAssetHashOnce sync.Once
scriptoriumPromptHash string promptAssetHash string
scriptoriumPromptHashErr error promptAssetHashErr error
) )

View File

@@ -11,7 +11,7 @@ import (
"gitea.maximumdirect.net/eric/promptkit" "gitea.maximumdirect.net/eric/promptkit"
) )
func TestScriptoriumPromptPreparesTranscriptAndTaskMessages(t *testing.T) { func TestPromptAssetsPrepareTranscriptAndTaskMessages(t *testing.T) {
transcript := []byte(`{"sentinel":"scene-transcript"}`) transcript := []byte(`{"sentinel":"scene-transcript"}`)
prepared := prepareScenesPrompt(t, transcript, "scene-players", "scene-party", "scene-glossary") prepared := prepareScenesPrompt(t, transcript, "scene-players", "scene-party", "scene-glossary")
@@ -52,7 +52,7 @@ func TestScriptoriumPromptPreparesTranscriptAndTaskMessages(t *testing.T) {
} }
} }
func TestScriptoriumPromptDiagnosticsOmitRawMaterials(t *testing.T) { func TestPromptAssetDiagnosticsOmitRawMaterials(t *testing.T) {
transcript := []byte(`{"secret":"source text"}`) transcript := []byte(`{"secret":"source text"}`)
prepared := prepareScenesPrompt(t, transcript, "private player note", "private party note", "private glossary note") prepared := prepareScenesPrompt(t, transcript, "private player note", "private party note", "private glossary note")
metadata := newChunker(t, &fakeScenesLLMClient{}).ManifestMetadata() metadata := newChunker(t, &fakeScenesLLMClient{}).ManifestMetadata()
@@ -100,7 +100,7 @@ func prepareScenesPrompt(t *testing.T, transcript []byte, players string, party
if err := RegisterPromptAssets(registry); err != nil { if err := RegisterPromptAssets(registry); err != nil {
t.Fatalf("register scene prompt assets: %v", err) t.Fatalf("register scene prompt assets: %v", err)
} }
engine := newScenesScriptoriumEngine(t, registry) engine := newScenesPromptEngine(t, registry)
prepared, err := engine.Prepare(context.Background(), promptkit.RunRequest{ prepared, err := engine.Prepare(context.Background(), promptkit.RunRequest{
PromptID: PromptID, PromptID: PromptID,
PromptVersion: ResponseSchemaVersion, PromptVersion: ResponseSchemaVersion,
@@ -118,7 +118,7 @@ func prepareScenesPrompt(t *testing.T, transcript []byte, players string, party
return prepared return prepared
} }
func newScenesScriptoriumEngine(t *testing.T, registry *llm.AssetRegistry) *promptkit.Engine { func newScenesPromptEngine(t *testing.T, registry *llm.AssetRegistry) *promptkit.Engine {
t.Helper() t.Helper()
options, err := registry.PromptKitOptions() options, err := registry.PromptKitOptions()
if err != nil { if err != nil {

View File

@@ -96,7 +96,7 @@ func New(llmClient contracts.StructuredLLMClient, _ Options, references ...contr
if err != nil { if err != nil {
return nil, extractorErrorf("prepare scene eligibility: %w", err) return nil, extractorErrorf("prepare scene eligibility: %w", err)
} }
promptSHA, err := scriptoriumPromptMetadata() promptSHA, err := promptAssetMetadata()
if err != nil { if err != nil {
return nil, extractorErrorf("load prompt metadata: %w", err) return nil, extractorErrorf("load prompt metadata: %w", err)
} }

View File

@@ -9,7 +9,7 @@ import (
"gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/shared" "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/shared"
) )
const scriptoriumPromptRoot = "assets/prompts" const promptAssetRoot = "assets/prompts"
var promptAssetManifest = shared.PromptAssetManifest{ var promptAssetManifest = shared.PromptAssetManifest{
ModuleDir: "dnd.combat_turns", ModuleDir: "dnd.combat_turns",
@@ -33,21 +33,21 @@ func RegisterPromptAssets(registry *llm.AssetRegistry) error {
if err != nil { if err != nil {
return fmt.Errorf("prepare combat-turn prompt assets: %w", err) return fmt.Errorf("prepare combat-turn prompt assets: %w", err)
} }
if err := registry.RegisterPromptFS(promptFS, scriptoriumPromptRoot); err != nil { if err := registry.RegisterPromptFS(promptFS, promptAssetRoot); err != nil {
return err return err
} }
return registry.RegisterSchemaFS(embeddedAssets, "assets/schemas") return registry.RegisterSchemaFS(embeddedAssets, "assets/schemas")
} }
func scriptoriumPromptMetadata() (string, error) { func promptAssetMetadata() (string, error) {
scriptoriumPromptHashOnce.Do(func() { promptAssetHashOnce.Do(func() {
scriptoriumPromptHash, scriptoriumPromptHashErr = promptAssetManifest.Hash(embeddedAssets) promptAssetHash, promptAssetHashErr = promptAssetManifest.Hash(embeddedAssets)
}) })
return scriptoriumPromptHash, scriptoriumPromptHashErr return promptAssetHash, promptAssetHashErr
} }
var ( var (
scriptoriumPromptHashOnce sync.Once promptAssetHashOnce sync.Once
scriptoriumPromptHash string promptAssetHash string
scriptoriumPromptHashErr error promptAssetHashErr error
) )

View File

@@ -23,13 +23,13 @@ func TestRegisterPromptAssetsAndPrepareCombatPrompt(t *testing.T) {
if _, err := fs.ReadFile(schemaFS, "dnd_combat_turns_llm.v1.json"); err != nil { if _, err := fs.ReadFile(schemaFS, "dnd_combat_turns_llm.v1.json"); err != nil {
t.Fatalf("response schema asset: %v", err) t.Fatalf("response schema asset: %v", err)
} }
hash, err := scriptoriumPromptMetadata() hash, err := promptAssetMetadata()
if err != nil || !strings.HasPrefix(hash, "sha256:") { if err != nil || !strings.HasPrefix(hash, "sha256:") {
t.Fatalf("scriptoriumPromptMetadata() = %q, %v; want digest", hash, err) t.Fatalf("promptAssetMetadata() = %q, %v; want digest", hash, err)
} }
} }
func TestScriptoriumPromptPreparesRequiredInputs(t *testing.T) { func TestPromptAssetsPrepareRequiredInputs(t *testing.T) {
registry := llm.NewAssetRegistry() registry := llm.NewAssetRegistry()
if err := RegisterPromptAssets(registry); err != nil { if err := RegisterPromptAssets(registry); err != nil {
t.Fatalf("RegisterPromptAssets() error = %v, want nil", err) t.Fatalf("RegisterPromptAssets() error = %v, want nil", err)

View File

@@ -54,7 +54,7 @@ func New(llmClient contracts.StructuredLLMClient, _ Options, references ...contr
if len(references) > 1 { if len(references) > 1 {
return nil, extractorErrorf("at most one reference set may be supplied") return nil, extractorErrorf("at most one reference set may be supplied")
} }
promptSHA, err := scriptoriumPromptMetadata() promptSHA, err := promptAssetMetadata()
if err != nil { if err != nil {
return nil, extractorErrorf("load prompt metadata: %w", err) return nil, extractorErrorf("load prompt metadata: %w", err)
} }

View File

@@ -9,7 +9,7 @@ import (
"gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/shared" "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/shared"
) )
const scriptoriumPromptRoot = "assets/prompts" const promptAssetRoot = "assets/prompts"
var promptAssetManifest = shared.PromptAssetManifest{ var promptAssetManifest = shared.PromptAssetManifest{
ModuleDir: "dnd.item_events", ModuleDir: "dnd.item_events",
@@ -32,21 +32,21 @@ func RegisterPromptAssets(registry *llm.AssetRegistry) error {
if err != nil { if err != nil {
return fmt.Errorf("prepare item event prompt assets: %w", err) return fmt.Errorf("prepare item event prompt assets: %w", err)
} }
if err := registry.RegisterPromptFS(promptFS, scriptoriumPromptRoot); err != nil { if err := registry.RegisterPromptFS(promptFS, promptAssetRoot); err != nil {
return err return err
} }
return registry.RegisterSchemaFS(embeddedAssets, "assets/schemas") return registry.RegisterSchemaFS(embeddedAssets, "assets/schemas")
} }
func scriptoriumPromptMetadata() (string, error) { func promptAssetMetadata() (string, error) {
scriptoriumPromptHashOnce.Do(func() { promptAssetHashOnce.Do(func() {
scriptoriumPromptHash, scriptoriumPromptHashErr = promptAssetManifest.Hash(embeddedAssets) promptAssetHash, promptAssetHashErr = promptAssetManifest.Hash(embeddedAssets)
}) })
return scriptoriumPromptHash, scriptoriumPromptHashErr return promptAssetHash, promptAssetHashErr
} }
var ( var (
scriptoriumPromptHashOnce sync.Once promptAssetHashOnce sync.Once
scriptoriumPromptHash string promptAssetHash string
scriptoriumPromptHashErr error promptAssetHashErr error
) )

View File

@@ -46,9 +46,9 @@ func TestPromptAssetsPrepareItemEventPrompt(t *testing.T) {
} }
func TestPromptAssetsDoNotLeakIntoMetadata(t *testing.T) { func TestPromptAssetsDoNotLeakIntoMetadata(t *testing.T) {
hash, err := scriptoriumPromptMetadata() hash, err := promptAssetMetadata()
if err != nil || !strings.HasPrefix(hash, "sha256:") { if err != nil || !strings.HasPrefix(hash, "sha256:") {
t.Fatalf("scriptoriumPromptMetadata() = %q, %v", hash, err) t.Fatalf("promptAssetMetadata() = %q, %v", hash, err)
} }
metadata := newExtractor(t, &fakeItemEventsLLMClient{}).ManifestMetadata() metadata := newExtractor(t, &fakeItemEventsLLMClient{}).ManifestMetadata()
payload, err := json.Marshal(metadata) payload, err := json.Marshal(metadata)

View File

@@ -80,7 +80,7 @@ func New(llmClient contracts.StructuredLLMClient, _ Options, references ...contr
if err != nil { if err != nil {
return nil, extractorErrorf("prepare NPC registry prompt input: %w", err) return nil, extractorErrorf("prepare NPC registry prompt input: %w", err)
} }
promptSHA, err := scriptoriumPromptMetadata() promptSHA, err := promptAssetMetadata()
if err != nil { if err != nil {
return nil, extractorErrorf("load prompt metadata: %w", err) return nil, extractorErrorf("load prompt metadata: %w", err)
} }

View File

@@ -9,7 +9,7 @@ import (
"gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/shared" "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/shared"
) )
const scriptoriumPromptRoot = "assets/prompts" const promptAssetRoot = "assets/prompts"
var promptAssetManifest = shared.PromptAssetManifest{ var promptAssetManifest = shared.PromptAssetManifest{
ModuleDir: "dnd.npc_interactions", ModuleDir: "dnd.npc_interactions",
@@ -33,21 +33,21 @@ func RegisterPromptAssets(registry *llm.AssetRegistry) error {
if err != nil { if err != nil {
return fmt.Errorf("prepare NPC-interaction prompt assets: %w", err) return fmt.Errorf("prepare NPC-interaction prompt assets: %w", err)
} }
if err := registry.RegisterPromptFS(promptFS, scriptoriumPromptRoot); err != nil { if err := registry.RegisterPromptFS(promptFS, promptAssetRoot); err != nil {
return err return err
} }
return registry.RegisterSchemaFS(embeddedAssets, "assets/schemas") return registry.RegisterSchemaFS(embeddedAssets, "assets/schemas")
} }
func scriptoriumPromptMetadata() (string, error) { func promptAssetMetadata() (string, error) {
scriptoriumPromptHashOnce.Do(func() { promptAssetHashOnce.Do(func() {
scriptoriumPromptHash, scriptoriumPromptHashErr = promptAssetManifest.Hash(embeddedAssets) promptAssetHash, promptAssetHashErr = promptAssetManifest.Hash(embeddedAssets)
}) })
return scriptoriumPromptHash, scriptoriumPromptHashErr return promptAssetHash, promptAssetHashErr
} }
var ( var (
scriptoriumPromptHashOnce sync.Once promptAssetHashOnce sync.Once
scriptoriumPromptHash string promptAssetHash string
scriptoriumPromptHashErr error promptAssetHashErr error
) )

View File

@@ -54,9 +54,9 @@ func TestRegisterPromptAssetsAndPrepareInteractionPrompt(t *testing.T) {
} }
func TestPromptMetadataDoesNotExposeAssetContent(t *testing.T) { func TestPromptMetadataDoesNotExposeAssetContent(t *testing.T) {
hash, err := scriptoriumPromptMetadata() hash, err := promptAssetMetadata()
if err != nil || !strings.HasPrefix(hash, "sha256:") { if err != nil || !strings.HasPrefix(hash, "sha256:") {
t.Fatalf("scriptoriumPromptMetadata() = %q, %v", hash, err) t.Fatalf("promptAssetMetadata() = %q, %v", hash, err)
} }
metadata := newExtractor(t, &fakeInteractionsLLMClient{}).ManifestMetadata() metadata := newExtractor(t, &fakeInteractionsLLMClient{}).ManifestMetadata()
for _, forbidden := range []string{"common-dnd-system", "dnd_npc_interactions_llm.v1.json"} { for _, forbidden := range []string{"common-dnd-system", "dnd_npc_interactions_llm.v1.json"} {

View File

@@ -54,7 +54,7 @@ func New(llmClient contracts.StructuredLLMClient, _ Options, references ...contr
if len(references) > 1 { if len(references) > 1 {
return nil, extractorErrorf("at most one reference set may be supplied") return nil, extractorErrorf("at most one reference set may be supplied")
} }
promptSHA, err := scriptoriumPromptMetadata() promptSHA, err := promptAssetMetadata()
if err != nil { if err != nil {
return nil, extractorErrorf("load prompt metadata: %w", err) return nil, extractorErrorf("load prompt metadata: %w", err)
} }

View File

@@ -9,7 +9,7 @@ import (
"gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/shared" "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/shared"
) )
const scriptoriumPromptRoot = "assets/prompts" const promptAssetRoot = "assets/prompts"
var promptAssetManifest = shared.PromptAssetManifest{ var promptAssetManifest = shared.PromptAssetManifest{
ModuleDir: "dnd.npcs", ModuleDir: "dnd.npcs",
@@ -32,21 +32,21 @@ func RegisterPromptAssets(registry *llm.AssetRegistry) error {
if err != nil { if err != nil {
return fmt.Errorf("prepare NPC prompt assets: %w", err) return fmt.Errorf("prepare NPC prompt assets: %w", err)
} }
if err := registry.RegisterPromptFS(promptFS, scriptoriumPromptRoot); err != nil { if err := registry.RegisterPromptFS(promptFS, promptAssetRoot); err != nil {
return err return err
} }
return registry.RegisterSchemaFS(embeddedAssets, "assets/schemas") return registry.RegisterSchemaFS(embeddedAssets, "assets/schemas")
} }
func scriptoriumPromptMetadata() (string, error) { func promptAssetMetadata() (string, error) {
scriptoriumPromptHashOnce.Do(func() { promptAssetHashOnce.Do(func() {
scriptoriumPromptHash, scriptoriumPromptHashErr = promptAssetManifest.Hash(embeddedAssets) promptAssetHash, promptAssetHashErr = promptAssetManifest.Hash(embeddedAssets)
}) })
return scriptoriumPromptHash, scriptoriumPromptHashErr return promptAssetHash, promptAssetHashErr
} }
var ( var (
scriptoriumPromptHashOnce sync.Once promptAssetHashOnce sync.Once
scriptoriumPromptHash string promptAssetHash string
scriptoriumPromptHashErr error promptAssetHashErr error
) )

View File

@@ -45,9 +45,9 @@ func TestRegisterPromptAssetsAndPrepareNPCPrompt(t *testing.T) {
} }
func TestPromptMetadataAndDiagnosticsDoNotContainRawAssets(t *testing.T) { func TestPromptMetadataAndDiagnosticsDoNotContainRawAssets(t *testing.T) {
hash, err := scriptoriumPromptMetadata() hash, err := promptAssetMetadata()
if err != nil || !strings.HasPrefix(hash, "sha256:") { if err != nil || !strings.HasPrefix(hash, "sha256:") {
t.Fatalf("scriptoriumPromptMetadata() = %q, %v; want hash", hash, err) t.Fatalf("promptAssetMetadata() = %q, %v; want hash", hash, err)
} }
metadata := newExtractor(t, &fakeNPCsLLMClient{}).ManifestMetadata() metadata := newExtractor(t, &fakeNPCsLLMClient{}).ManifestMetadata()
payload, err := json.Marshal(metadata) payload, err := json.Marshal(metadata)

View File

@@ -59,7 +59,7 @@ func New(llmClient contracts.StructuredLLMClient, _ Options, references ...contr
if len(references) > 1 { if len(references) > 1 {
return nil, extractorErrorf("at most one reference set may be supplied") return nil, extractorErrorf("at most one reference set may be supplied")
} }
promptSHA, err := scriptoriumPromptMetadata() promptSHA, err := promptAssetMetadata()
if err != nil { if err != nil {
return nil, extractorErrorf("load prompt metadata: %w", err) return nil, extractorErrorf("load prompt metadata: %w", err)
} }

View File

@@ -9,7 +9,7 @@ import (
"gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/shared" "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/shared"
) )
const scriptoriumPromptRoot = "assets/prompts" const promptAssetRoot = "assets/prompts"
var promptAssetManifest = shared.PromptAssetManifest{ var promptAssetManifest = shared.PromptAssetManifest{
ModuleDir: "dnd.scene_descriptions", ModuleDir: "dnd.scene_descriptions",
@@ -31,21 +31,21 @@ func RegisterPromptAssets(registry *llm.AssetRegistry) error {
if err != nil { if err != nil {
return fmt.Errorf("prepare scene-description prompt assets: %w", err) return fmt.Errorf("prepare scene-description prompt assets: %w", err)
} }
if err := registry.RegisterPromptFS(promptFS, scriptoriumPromptRoot); err != nil { if err := registry.RegisterPromptFS(promptFS, promptAssetRoot); err != nil {
return err return err
} }
return registry.RegisterSchemaFS(embeddedAssets, "assets/schemas") return registry.RegisterSchemaFS(embeddedAssets, "assets/schemas")
} }
func scriptoriumPromptMetadata() (string, error) { func promptAssetMetadata() (string, error) {
scriptoriumPromptHashOnce.Do(func() { promptAssetHashOnce.Do(func() {
scriptoriumPromptHash, scriptoriumPromptHashErr = promptAssetManifest.Hash(embeddedAssets) promptAssetHash, promptAssetHashErr = promptAssetManifest.Hash(embeddedAssets)
}) })
return scriptoriumPromptHash, scriptoriumPromptHashErr return promptAssetHash, promptAssetHashErr
} }
var ( var (
scriptoriumPromptHashOnce sync.Once promptAssetHashOnce sync.Once
scriptoriumPromptHash string promptAssetHash string
scriptoriumPromptHashErr error promptAssetHashErr error
) )

View File

@@ -45,9 +45,9 @@ func TestRegisterPromptAssetsPreparesSceneDescriptionPrompt(t *testing.T) {
} }
func TestPromptMetadataAndDiagnosticsDoNotContainRawAssets(t *testing.T) { func TestPromptMetadataAndDiagnosticsDoNotContainRawAssets(t *testing.T) {
hash, err := scriptoriumPromptMetadata() hash, err := promptAssetMetadata()
if err != nil || !strings.HasPrefix(hash, "sha256:") { if err != nil || !strings.HasPrefix(hash, "sha256:") {
t.Fatalf("scriptoriumPromptMetadata() = %q, %v; want hash", hash, err) t.Fatalf("promptAssetMetadata() = %q, %v; want hash", hash, err)
} }
payload, err := json.Marshal(newExtractor(t, &fakeSceneDescriptionsLLMClient{}).ManifestMetadata()) payload, err := json.Marshal(newExtractor(t, &fakeSceneDescriptionsLLMClient{}).ManifestMetadata())
if err != nil { if err != nil {

View File

@@ -94,7 +94,7 @@ func New(llmClient contracts.StructuredLLMClient, _ Options, references ...contr
if err != nil { if err != nil {
return nil, extractorErrorf("prepare NPC registry prompt input: %w", err) return nil, extractorErrorf("prepare NPC registry prompt input: %w", err)
} }
promptSHA, err := scriptoriumPromptMetadata() promptSHA, err := promptAssetMetadata()
if err != nil { if err != nil {
return nil, extractorErrorf("load prompt metadata: %w", err) return nil, extractorErrorf("load prompt metadata: %w", err)
} }

View File

@@ -9,7 +9,7 @@ import (
"gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/shared" "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/shared"
) )
const scriptoriumPromptRoot = "assets/prompts" const promptAssetRoot = "assets/prompts"
var promptAssetManifest = shared.PromptAssetManifest{ var promptAssetManifest = shared.PromptAssetManifest{
ModuleDir: "dnd.spells", ModuleDir: "dnd.spells",
@@ -34,21 +34,21 @@ func RegisterPromptAssets(registry *llm.AssetRegistry) error {
if err != nil { if err != nil {
return fmt.Errorf("prepare spell prompt assets: %w", err) return fmt.Errorf("prepare spell prompt assets: %w", err)
} }
if err := registry.RegisterPromptFS(promptFS, scriptoriumPromptRoot); err != nil { if err := registry.RegisterPromptFS(promptFS, promptAssetRoot); err != nil {
return err return err
} }
return registry.RegisterSchemaFS(embeddedAssets, "assets/schemas") return registry.RegisterSchemaFS(embeddedAssets, "assets/schemas")
} }
func scriptoriumPromptMetadata() (string, error) { func promptAssetMetadata() (string, error) {
scriptoriumPromptHashOnce.Do(func() { promptAssetHashOnce.Do(func() {
scriptoriumPromptHash, scriptoriumPromptHashErr = promptAssetManifest.Hash(embeddedAssets) promptAssetHash, promptAssetHashErr = promptAssetManifest.Hash(embeddedAssets)
}) })
return scriptoriumPromptHash, scriptoriumPromptHashErr return promptAssetHash, promptAssetHashErr
} }
var ( var (
scriptoriumPromptHashOnce sync.Once promptAssetHashOnce sync.Once
scriptoriumPromptHash string promptAssetHash string
scriptoriumPromptHashErr error promptAssetHashErr error
) )

View File

@@ -11,7 +11,7 @@ import (
"gitea.maximumdirect.net/eric/promptkit" "gitea.maximumdirect.net/eric/promptkit"
) )
func TestScriptoriumPromptPreparesSpellPrompt(t *testing.T) { func TestPromptAssetsPrepareSpellPrompt(t *testing.T) {
transcript := []byte(`{"id":"session-1","segments":[{"id":"u1","text":"Mira casts shield."}]}`) transcript := []byte(`{"id":"session-1","segments":[{"id":"u1","text":"Mira casts shield."}]}`)
prepared := prepareSpellsPrompt(t, transcript, "Dana: Mira", "Mira: wizard", "Shield: abjuration") prepared := prepareSpellsPrompt(t, transcript, "Dana: Mira", "Mira: wizard", "Shield: abjuration")
@@ -23,7 +23,7 @@ func TestScriptoriumPromptPreparesSpellPrompt(t *testing.T) {
} }
} }
func TestScriptoriumPromptPreparesWithMissingOptionalReferences(t *testing.T) { func TestPromptAssetsPrepareWithMissingOptionalReferences(t *testing.T) {
transcript := []byte(`{"id":"session-1","segments":[]}`) transcript := []byte(`{"id":"session-1","segments":[]}`)
prepared := prepareSpellsPrompt(t, transcript, " ", " ", " ") prepared := prepareSpellsPrompt(t, transcript, " ", " ", " ")
@@ -35,7 +35,7 @@ func TestScriptoriumPromptPreparesWithMissingOptionalReferences(t *testing.T) {
t.Fatalf("reference message did not render empty optional reference placeholders") t.Fatalf("reference message did not render empty optional reference placeholders")
} }
func TestScriptoriumPromptDiagnosticsOmitRawMaterials(t *testing.T) { func TestPromptAssetDiagnosticsOmitRawMaterials(t *testing.T) {
transcript := []byte(`{"secret":"source text"}`) transcript := []byte(`{"secret":"source text"}`)
reference := "private party note" reference := "private party note"
prepared := prepareSpellsPrompt(t, transcript, "private player note", reference, " ") prepared := prepareSpellsPrompt(t, transcript, "private player note", reference, " ")

View File

@@ -53,7 +53,7 @@ func New(llmClient contracts.StructuredLLMClient, _ Options) (*Normalizer, error
if llmClient == nil { if llmClient == nil {
return nil, normalizerErrorf("LLM client must not be nil") return nil, normalizerErrorf("LLM client must not be nil")
} }
promptSHA, err := scriptoriumPromptMetadata() promptSHA, err := promptAssetMetadata()
if err != nil { if err != nil {
return nil, normalizerErrorf("load prompt metadata: %w", err) return nil, normalizerErrorf("load prompt metadata: %w", err)
} }

View File

@@ -9,7 +9,7 @@ import (
"gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/shared" "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/shared"
) )
const scriptoriumPromptRoot = "assets/prompts" const promptAssetRoot = "assets/prompts"
var promptAssetManifest = shared.PromptAssetManifest{ var promptAssetManifest = shared.PromptAssetManifest{
ModuleDir: PromptID, ModuleDir: PromptID,
@@ -30,21 +30,21 @@ func RegisterPromptAssets(registry *llm.AssetRegistry) error {
if err != nil { if err != nil {
return fmt.Errorf("prepare NPC normalization prompt assets: %w", err) return fmt.Errorf("prepare NPC normalization prompt assets: %w", err)
} }
if err := registry.RegisterPromptFS(promptFS, scriptoriumPromptRoot); err != nil { if err := registry.RegisterPromptFS(promptFS, promptAssetRoot); err != nil {
return err return err
} }
return registry.RegisterSchemaFS(embeddedAssets, "assets/schemas") return registry.RegisterSchemaFS(embeddedAssets, "assets/schemas")
} }
func scriptoriumPromptMetadata() (string, error) { func promptAssetMetadata() (string, error) {
scriptoriumPromptHashOnce.Do(func() { promptAssetHashOnce.Do(func() {
scriptoriumPromptHash, scriptoriumPromptHashErr = promptAssetManifest.Hash(embeddedAssets) promptAssetHash, promptAssetHashErr = promptAssetManifest.Hash(embeddedAssets)
}) })
return scriptoriumPromptHash, scriptoriumPromptHashErr return promptAssetHash, promptAssetHashErr
} }
var ( var (
scriptoriumPromptHashOnce sync.Once promptAssetHashOnce sync.Once
scriptoriumPromptHash string promptAssetHash string
scriptoriumPromptHashErr error promptAssetHashErr error
) )

View File

@@ -15,8 +15,8 @@ func TestRegisterPromptAssetsPreparesNormalizationPrompt(t *testing.T) {
if want := []string{"common-dnd-system.md", "common-dnd-transcript.md"}; !reflect.DeepEqual(promptAssetManifest.SharedFiles, want) { if want := []string{"common-dnd-system.md", "common-dnd-transcript.md"}; !reflect.DeepEqual(promptAssetManifest.SharedFiles, want) {
t.Fatalf("shared prompt assets = %#v, want %#v", promptAssetManifest.SharedFiles, want) t.Fatalf("shared prompt assets = %#v, want %#v", promptAssetManifest.SharedFiles, want)
} }
if promptHash, err := scriptoriumPromptMetadata(); err != nil || promptHash == "" { if promptHash, err := promptAssetMetadata(); err != nil || promptHash == "" {
t.Fatalf("scriptoriumPromptMetadata() = %q, %v; want prompt fingerprint", promptHash, err) t.Fatalf("promptAssetMetadata() = %q, %v; want prompt fingerprint", promptHash, err)
} }
registry := llm.NewAssetRegistry() registry := llm.NewAssetRegistry()
if err := RegisterPromptAssets(registry); err != nil { if err := RegisterPromptAssets(registry); err != nil {