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 results := make([]string, 0)
94 for result := range resultCh {
95 results = append(results, result)
96 }
97
98 return strings.Join(results, "\n")
99}
100
101func processFile(filePath string) string {
102 content, err := os.ReadFile(filePath)
103 if err != nil {
104 return ""
105 }
106 return "# From:" + filePath + "\n" + string(content)
107}
108