prompt.go

  1package prompt
  2
  3import (
  4	"fmt"
  5	"os"
  6	"path/filepath"
  7	"strings"
  8	"sync"
  9
 10	"github.com/opencode-ai/opencode/internal/config"
 11	"github.com/opencode-ai/opencode/internal/llm/models"
 12)
 13
 14func GetAgentPrompt(agentName config.AgentName, provider models.ModelProvider) string {
 15	basePrompt := ""
 16	switch agentName {
 17	case config.AgentCoder:
 18		basePrompt = CoderPrompt(provider)
 19	case config.AgentTitle:
 20		basePrompt = TitlePrompt(provider)
 21	case config.AgentTask:
 22		basePrompt = TaskPrompt(provider)
 23	default:
 24		basePrompt = "You are a helpful assistant"
 25	}
 26
 27	if agentName == config.AgentCoder || agentName == config.AgentTask {
 28		// Add context from project-specific instruction files if they exist
 29		contextContent := getContextFromPaths()
 30		if contextContent != "" {
 31			return fmt.Sprintf("%s\n\n# Project-Specific Context\n Make sure to follow the instructions in the context below\n%s", basePrompt, contextContent)
 32		}
 33	}
 34	return basePrompt
 35}
 36
 37var (
 38	onceContext    sync.Once
 39	contextContent string
 40)
 41
 42func getContextFromPaths() string {
 43	onceContext.Do(func() {
 44		var (
 45			cfg          = config.Get()
 46			workDir      = cfg.WorkingDir
 47			contextPaths = cfg.ContextPaths
 48		)
 49
 50		contextContent = processContextPaths(workDir, contextPaths)
 51	})
 52
 53	return contextContent
 54}
 55
 56func processContextPaths(workDir string, paths []string) string {
 57	var (
 58		wg       sync.WaitGroup
 59		resultCh = make(chan string)
 60	)
 61
 62	for _, path := range paths {
 63		wg.Add(1)
 64		go func(p string) {
 65			defer wg.Done()
 66
 67			if strings.HasSuffix(p, "/") {
 68				filepath.WalkDir(filepath.Join(workDir, p), func(path string, d os.DirEntry, err error) error {
 69					if err != nil {
 70						return err
 71					}
 72					if !d.IsDir() {
 73						if result := processFile(path); result != "" {
 74							resultCh <- result
 75						}
 76					}
 77					return nil
 78				})
 79			} else {
 80				result := processFile(filepath.Join(workDir, p))
 81				if result != "" {
 82					resultCh <- result
 83				}
 84			}
 85		}(path)
 86	}
 87
 88	go func() {
 89		wg.Wait()
 90		close(resultCh)
 91	}()
 92
 93	var (
 94		results = make([]string, 0)
 95		i       int
 96	)
 97	for result := range resultCh {
 98		results = append(results, result)
 99		i++
100	}
101
102	return strings.Join(results, "\n")
103}
104
105func processFile(filePath string) string {
106	content, err := os.ReadFile(filePath)
107	if err != nil {
108		return ""
109	}
110	return "# From:" + filePath + "\n" + string(content)
111}
112