package prompt import ( "embed" "strings" "sync" ) //go:embed files var files embed.FS const ( fileOverlay = "files/overlay.md" fileStyle8DSystem = "files/style8d.system.md" fileStyle8DSchema = "files/style8d.schema.md" fileAIChatSystem = "files/ai.chat.system.md" fileIslanderSystem = "files/ai.islander.system.md" ) // Keys identify prompt slots loaded from internal/library/prompt/files/*.md. const ( KeyStyle8DSystem = "style8d.system" KeyStyle8DSchema = "style8d.schema" KeyAIChatSystem = "ai.chat.system" KeyIslanderSystem = "ai.islander.system" ) var slotFiles = map[string]string{ KeyStyle8DSystem: fileStyle8DSystem, KeyStyle8DSchema: fileStyle8DSchema, KeyAIChatSystem: fileAIChatSystem, KeyIslanderSystem: fileIslanderSystem, } var ( loadOnce sync.Once loadErr error overlay string slotTexts map[string]string ) func initRegistry() { overlay, loadErr = readFile(fileOverlay) if loadErr != nil { return } slotTexts = make(map[string]string, len(slotFiles)) for key, path := range slotFiles { text, err := readFile(path) if err != nil { loadErr = err return } slotTexts[key] = text } } func readFile(path string) (string, error) { raw, err := files.ReadFile(path) if err != nil { return "", err } return strings.TrimSpace(string(raw)), nil } func ensureLoaded() error { loadOnce.Do(initRegistry) return loadErr } // Overlay returns the global prepend text (Agents.md style). func Overlay() (string, error) { if err := ensureLoaded(); err != nil { return "", err } return overlay, nil } // Slot returns one configured prompt body. func Slot(key string) (string, error) { if err := ensureLoaded(); err != nil { return "", err } text, ok := slotTexts[key] if !ok { return "", ErrUnknownKey(key) } return text, nil } // KnownKey reports whether key is registered. func KnownKey(key string) bool { _, ok := slotFiles[key] return ok }