Files
nofx/decision/prompt_manager.go
T
2025-12-08 01:43:22 +08:00

163 lines
4.0 KiB
Go

package decision
import (
"fmt"
"log"
"os"
"path/filepath"
"strings"
"sync"
)
// PromptTemplate system prompt template
type PromptTemplate struct {
Name string // Template name (filename without extension)
Content string // Template content
}
// PromptManager prompt manager
type PromptManager struct {
templates map[string]*PromptTemplate
mu sync.RWMutex
}
var (
// globalPromptManager global prompt manager
globalPromptManager *PromptManager
// promptsDir prompt folder path
promptsDir = "prompts"
)
// init loads all prompt templates during package initialization
func init() {
globalPromptManager = NewPromptManager()
if err := globalPromptManager.LoadTemplates(promptsDir); err != nil {
log.Printf("⚠️ Failed to load prompt templates: %v", err)
} else {
log.Printf("✓ Loaded %d system prompt templates", len(globalPromptManager.templates))
}
}
// NewPromptManager creates a prompt manager
func NewPromptManager() *PromptManager {
return &PromptManager{
templates: make(map[string]*PromptTemplate),
}
}
// LoadTemplates loads all prompt templates from specified directory
func (pm *PromptManager) LoadTemplates(dir string) error {
pm.mu.Lock()
defer pm.mu.Unlock()
// Check if directory exists
if _, err := os.Stat(dir); os.IsNotExist(err) {
return fmt.Errorf("prompt directory does not exist: %s", dir)
}
// Scan all .txt files in directory
files, err := filepath.Glob(filepath.Join(dir, "*.txt"))
if err != nil {
return fmt.Errorf("failed to scan prompt directory: %w", err)
}
if len(files) == 0 {
log.Printf("⚠️ No .txt files found in prompt directory %s", dir)
return nil
}
// Load each template file
for _, file := range files {
// Read file content
content, err := os.ReadFile(file)
if err != nil {
log.Printf("⚠️ Failed to read prompt file %s: %v", file, err)
continue
}
// Extract filename (without extension) as template name
fileName := filepath.Base(file)
templateName := strings.TrimSuffix(fileName, filepath.Ext(fileName))
// Store template
pm.templates[templateName] = &PromptTemplate{
Name: templateName,
Content: string(content),
}
log.Printf(" 📄 Loaded prompt template: %s (%s)", templateName, fileName)
}
return nil
}
// GetTemplate gets prompt template by name
func (pm *PromptManager) GetTemplate(name string) (*PromptTemplate, error) {
pm.mu.RLock()
defer pm.mu.RUnlock()
template, exists := pm.templates[name]
if !exists {
return nil, fmt.Errorf("prompt template does not exist: %s", name)
}
return template, nil
}
// GetAllTemplateNames gets all template names list
func (pm *PromptManager) GetAllTemplateNames() []string {
pm.mu.RLock()
defer pm.mu.RUnlock()
names := make([]string, 0, len(pm.templates))
for name := range pm.templates {
names = append(names, name)
}
return names
}
// GetAllTemplates gets all templates
func (pm *PromptManager) GetAllTemplates() []*PromptTemplate {
pm.mu.RLock()
defer pm.mu.RUnlock()
templates := make([]*PromptTemplate, 0, len(pm.templates))
for _, template := range pm.templates {
templates = append(templates, template)
}
return templates
}
// ReloadTemplates reloads all templates
func (pm *PromptManager) ReloadTemplates(dir string) error {
pm.mu.Lock()
pm.templates = make(map[string]*PromptTemplate)
pm.mu.Unlock()
return pm.LoadTemplates(dir)
}
// === Global functions (for external calls) ===
// GetPromptTemplate gets prompt template by name (global function)
func GetPromptTemplate(name string) (*PromptTemplate, error) {
return globalPromptManager.GetTemplate(name)
}
// GetAllPromptTemplateNames gets all template names (global function)
func GetAllPromptTemplateNames() []string {
return globalPromptManager.GetAllTemplateNames()
}
// GetAllPromptTemplates gets all templates (global function)
func GetAllPromptTemplates() []*PromptTemplate {
return globalPromptManager.GetAllTemplates()
}
// ReloadPromptTemplates reloads all templates (global function)
func ReloadPromptTemplates() error {
return globalPromptManager.ReloadTemplates(promptsDir)
}