Update D&D prompt definitions to shallow asset paths

This commit is contained in:
2026-07-06 01:32:27 +00:00
parent 5b1efc89f6
commit 3e456ec4d4
7 changed files with 111 additions and 16 deletions

View File

@@ -98,6 +98,37 @@ func TestAssetRegistryRejectsDuplicateAssetPaths(t *testing.T) {
}
}
func TestAssetRegistryCombinesNamespacedPromptSources(t *testing.T) {
registry := NewAssetRegistry()
mustRegisterPromptFS(t, registry, fstest.MapFS{
"dnd.spells/dnd.spells.yaml": {Data: []byte(validPromptYAML("schema.json"))},
"dnd.spells/task.md": {Data: []byte("spell task")},
"dnd.spells/instructions.md": {Data: []byte("spell instructions")},
}, ".")
mustRegisterPromptFS(t, registry, fstest.MapFS{
"dnd.scenes/dnd.scenes.yaml": {Data: []byte(validPromptYAML("schema.json"))},
"dnd.scenes/task.md": {Data: []byte("scene task")},
"dnd.scenes/instructions.md": {Data: []byte("scene instructions")},
}, ".")
fsys, err := registry.PromptFS()
if err != nil {
t.Fatalf("PromptFS() error = %v, want nil", err)
}
for _, name := range []string{
"dnd.spells/dnd.spells.yaml",
"dnd.spells/task.md",
"dnd.spells/instructions.md",
"dnd.scenes/dnd.scenes.yaml",
"dnd.scenes/task.md",
"dnd.scenes/instructions.md",
} {
if _, err := fsys.Open(name); err != nil {
t.Fatalf("PromptFS().Open(%q) error = %v, want nil", name, err)
}
}
}
func TestHashAssetsOmitsRawAssetContent(t *testing.T) {
hash, err := HashAssets([]AssetHashPart{{
FS: fstest.MapFS{"prompt.md": {Data: []byte("secret prompt text")}},

View File

@@ -23,9 +23,9 @@ messages:
cache_control:
type: ephemeral
- role: user
content_file: ./dnd/scenes/task.md
content_file: ./task.md
- role: user
content_file: ./dnd/scenes/instructions.md
content_file: ./instructions.md
output:
format: json
validation_mode: json_schema

View File

@@ -11,12 +11,31 @@ import (
"time"
)
func modulePromptFS() (fs.FS, error) {
return promptMapFSFromEmbedded(map[string]string{
"assets/prompts/dnd.scenes.yaml": "assets/prompts/dnd.scenes.yaml",
"assets/prompts/dnd/scenes/task.md": "assets/prompts/task.md",
"assets/prompts/dnd/scenes/instructions.md": "assets/prompts/instructions.md",
func modulePromptFS(shared fs.FS) (fs.FS, error) {
assetFS, err := promptMapFSFromEmbedded(map[string]string{
"assets/prompts/dnd.scenes/dnd.scenes.yaml": "assets/prompts/dnd.scenes.yaml",
"assets/prompts/dnd.scenes/task.md": "assets/prompts/task.md",
"assets/prompts/dnd.scenes/instructions.md": "assets/prompts/instructions.md",
})
if err != nil {
return nil, err
}
assets := assetFS.(promptMapFS)
if shared == nil {
return assets, nil
}
for _, name := range []string{
"common-dnd-system.md",
"common-dnd-transcript.md",
"common-dnd-references.md",
} {
data, err := fs.ReadFile(shared, name)
if err != nil {
return nil, fmt.Errorf("read shared prompt asset %s: %w", name, err)
}
assets["assets/prompts/dnd.scenes/"+name] = append([]byte(nil), data...)
}
return assets, nil
}
func promptMapFSFromEmbedded(files map[string]string) (fs.FS, error) {

View File

@@ -3,6 +3,7 @@ package scenes
import (
"bytes"
"fmt"
"io/fs"
"sort"
"sync"
@@ -14,7 +15,11 @@ import (
const scriptoriumPromptRoot = "assets/prompts"
func RegisterPromptAssets(registry *llm.AssetRegistry) error {
promptFS, err := modulePromptFS()
sharedPromptFS, err := promptSharedFS()
if err != nil {
return fmt.Errorf("prepare shared prompt assets: %w", err)
}
promptFS, err := modulePromptFS(sharedPromptFS)
if err != nil {
return fmt.Errorf("prepare scene prompt assets: %w", err)
}
@@ -24,6 +29,14 @@ func RegisterPromptAssets(registry *llm.AssetRegistry) error {
return registry.RegisterSchemaFS(embeddedAssets, "assets/schemas")
}
func promptSharedFS() (fs.FS, error) {
registry := llm.NewAssetRegistry()
if err := sharedassets.Register(registry); err != nil {
return nil, err
}
return registry.PromptFS()
}
func promptInputs(req contracts.ChunkRequest) contracts.LLMInputSet {
return contracts.LLMInputSet{
"transcript": transcriptPromptInput(req.SourceInput),

View File

@@ -23,9 +23,9 @@ messages:
cache_control:
type: ephemeral
- role: user
content_file: ./dnd/spells/task.md
content_file: ./task.md
- role: user
content_file: ./dnd/spells/instructions.md
content_file: ./instructions.md
output:
format: json
validation_mode: json_schema

View File

@@ -11,12 +11,31 @@ import (
"time"
)
func modulePromptFS() (fs.FS, error) {
return promptMapFSFromEmbedded(map[string]string{
"assets/prompts/dnd.spells.yaml": "assets/prompts/dnd.spells.yaml",
"assets/prompts/dnd/spells/task.md": "assets/prompts/task.md",
"assets/prompts/dnd/spells/instructions.md": "assets/prompts/instructions.md",
func modulePromptFS(shared fs.FS) (fs.FS, error) {
assetFS, err := promptMapFSFromEmbedded(map[string]string{
"assets/prompts/dnd.spells/dnd.spells.yaml": "assets/prompts/dnd.spells.yaml",
"assets/prompts/dnd.spells/task.md": "assets/prompts/task.md",
"assets/prompts/dnd.spells/instructions.md": "assets/prompts/instructions.md",
})
if err != nil {
return nil, err
}
assets := assetFS.(promptMapFS)
if shared == nil {
return assets, nil
}
for _, name := range []string{
"common-dnd-system.md",
"common-dnd-transcript.md",
"common-dnd-references.md",
} {
data, err := fs.ReadFile(shared, name)
if err != nil {
return nil, fmt.Errorf("read shared prompt asset %s: %w", name, err)
}
assets["assets/prompts/dnd.spells/"+name] = append([]byte(nil), data...)
}
return assets, nil
}
func promptMapFSFromEmbedded(files map[string]string) (fs.FS, error) {

View File

@@ -3,6 +3,7 @@ package spells
import (
"bytes"
"fmt"
"io/fs"
"sort"
"sync"
@@ -14,7 +15,11 @@ import (
const scriptoriumPromptRoot = "assets/prompts"
func RegisterPromptAssets(registry *llm.AssetRegistry) error {
promptFS, err := modulePromptFS()
sharedPromptFS, err := promptSharedFS()
if err != nil {
return fmt.Errorf("prepare shared prompt assets: %w", err)
}
promptFS, err := modulePromptFS(sharedPromptFS)
if err != nil {
return fmt.Errorf("prepare spell prompt assets: %w", err)
}
@@ -24,6 +29,14 @@ func RegisterPromptAssets(registry *llm.AssetRegistry) error {
return registry.RegisterSchemaFS(embeddedAssets, "assets/schemas")
}
func promptSharedFS() (fs.FS, error) {
registry := llm.NewAssetRegistry()
if err := sharedassets.Register(registry); err != nil {
return nil, err
}
return registry.PromptFS()
}
func promptInputs(req contracts.ExtractionRequest) contracts.LLMInputSet {
return contracts.LLMInputSet{
"transcript": transcriptPromptInput(req.SourceInput),