prompt.go

  1package prompt
  2
  3import (
  4	"os"
  5	"path/filepath"
  6	"strings"
  7	"sync"
  8
  9	"github.com/charmbracelet/crush/internal/config"
 10)
 11
 12type PromptID string
 13
 14const (
 15	PromptCoder      PromptID = "coder"
 16	PromptTitle      PromptID = "title"
 17	PromptTask       PromptID = "task"
 18	PromptSummarizer PromptID = "summarizer"
 19	PromptDefault    PromptID = "default"
 20)
 21
 22func GetPrompt(promptID PromptID, provider string, contextPaths ...string) string {
 23	basePrompt := ""
 24	switch promptID {
 25	case PromptCoder:
 26		basePrompt = CoderPrompt(provider)
 27	case PromptTitle:
 28		basePrompt = TitlePrompt()
 29	case PromptTask:
 30		basePrompt = TaskPrompt()
 31	case PromptSummarizer:
 32		basePrompt = SummarizerPrompt()
 33	default:
 34		basePrompt = "You are a helpful assistant"
 35	}
 36	return basePrompt
 37}
 38
 39func getContextFromPaths(contextPaths []string) string {
 40	return processContextPaths(config.Get().WorkingDir(), contextPaths)
 41}
 42
 43func processContextPaths(workDir string, paths []string) string {
 44	var (
 45		wg       sync.WaitGroup
 46		resultCh = make(chan string)
 47	)
 48
 49	// Track processed files to avoid duplicates
 50	processedFiles := make(map[string]bool)
 51	var processedMutex sync.Mutex
 52
 53	for _, path := range paths {
 54		wg.Add(1)
 55		go func(p string) {
 56			defer wg.Done()
 57
 58			if strings.HasSuffix(p, "/") {
 59				filepath.WalkDir(filepath.Join(workDir, p), func(path string, d os.DirEntry, err error) error {
 60					if err != nil {
 61						return err
 62					}
 63					if !d.IsDir() {
 64						// Check if we've already processed this file (case-insensitive)
 65						lowerPath := strings.ToLower(path)
 66
 67						processedMutex.Lock()
 68						alreadyProcessed := processedFiles[lowerPath]
 69						if !alreadyProcessed {
 70							processedFiles[lowerPath] = true
 71						}
 72						processedMutex.Unlock()
 73
 74						if !alreadyProcessed {
 75							if result := processFile(path); result != "" {
 76								resultCh <- result
 77							}
 78						}
 79					}
 80					return nil
 81				})
 82			} else {
 83				fullPath := filepath.Join(workDir, p)
 84
 85				// Check if we've already processed this file (case-insensitive)
 86				lowerPath := strings.ToLower(fullPath)
 87
 88				processedMutex.Lock()
 89				alreadyProcessed := processedFiles[lowerPath]
 90				if !alreadyProcessed {
 91					processedFiles[lowerPath] = true
 92				}
 93				processedMutex.Unlock()
 94
 95				if !alreadyProcessed {
 96					result := processFile(fullPath)
 97					if result != "" {
 98						resultCh <- result
 99					}
100				}
101			}
102		}(path)
103	}
104
105	go func() {
106		wg.Wait()
107		close(resultCh)
108	}()
109
110	results := make([]string, 0)
111	for result := range resultCh {
112		results = append(results, result)
113	}
114
115	return strings.Join(results, "\n")
116}
117
118func processFile(filePath string) string {
119	content, err := os.ReadFile(filePath)
120	if err != nil {
121		return ""
122	}
123	return "# From:" + filePath + "\n" + string(content)
124}