@@ -5,26 +5,12 @@ import (
6 "path/filepath"
6 "path/filepath"
9 "github.com/opencode-ai/opencode/internal/config"
10 "github.com/opencode-ai/opencode/internal/config"
10 "github.com/opencode-ai/opencode/internal/llm/models"
11 "github.com/opencode-ai/opencode/internal/llm/models"
13−// contextFiles is a list of potential context files to check for
14−var contextFiles = []string{
15− ".github/copilot-instructions.md",
17− ".cursor/rules/", // Directory containing multiple rule files
28func GetAgentPrompt(agentName config.AgentName, provider models.ModelProvider) string {
14func GetAgentPrompt(agentName config.AgentName, provider models.ModelProvider) string {
29 basePrompt := ""
15 basePrompt := ""
30 switch agentName {
16 switch agentName {
@@ -40,45 +26,86 @@ func GetAgentPrompt(agentName config.AgentName, provider models.ModelProvider) s
41 if agentName == config.AgentCoder || agentName == config.AgentTask {
27 if agentName == config.AgentCoder || agentName == config.AgentTask {
42 // Add context from project-specific instruction files if they exist
28 // Add context from project-specific instruction files if they exist
43− contextContent := getContextFromFiles()
29+ contextContent := getContextFromPaths()
44 if contextContent != "" {
30 if contextContent != "" {
45− return fmt.Sprintf("%s\n\n# Project-Specific Context\n%s", basePrompt, 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)
48 return basePrompt
34 return basePrompt
51−// getContextFromFiles checks for the existence of context files and returns their content
37+var (
52−func getContextFromFiles() string {
38+ onceContext sync.Once
53− workDir := config.WorkingDirectory()
39+ contextContent string
54− var contextContent string
40+)
42+func getContextFromPaths() string {
43+ onceContext.Do(func() {
46+ workDir = cfg.WorkingDir
47+ contextPaths = cfg.ContextPaths
50+ contextContent = processContextPaths(workDir, contextPaths)
53+ return contextContent
56+func processContextPaths(workDir string, paths []string) string {
59+ resultCh = make(chan string)
62+ for _, path := range paths {
56− for _, path := range contextFiles {
57− // Check if path ends with a slash (indicating a directory)
58− if strings.HasSuffix(path, "/") {
67+ if strings.HasSuffix(p, "/") {
59− // Handle directory - read all files within it
68+ filepath.WalkDir(filepath.Join(workDir, p), func(path string, d os.DirEntry, err error) error {
60− dirPath := filepath.Join(workDir, path)
69+ if err != nil {
61− files, err := os.ReadDir(dirPath)
70+ return err
63− for _, file := range files {
64− if !file.IsDir() {
72+ if !d.IsDir() {
65− filePath := filepath.Join(dirPath, file.Name())
73+ if result := processFile(path); result != "" {
66− content, err := os.ReadFile(filePath)
74+ resultCh <- result
68− contextContent += fmt.Sprintf("\n# From %s\n%s\n", file.Name(), string(content))
80+ result := processFile(filepath.Join(workDir, p))
74− // Handle individual file as before
75− filePath := filepath.Join(workDir, path)
76− content, err := os.ReadFile(filePath)
78− contextContent += fmt.Sprintf("\n%s\n", string(content))
83− return contextContent
88+ go func() {
94+ results = make([]string, len(resultCh))
97+ for result := range resultCh {
102+ return strings.Join(results, "\n")
105+func processFile(filePath string) string {
106+ content, err := os.ReadFile(filePath)
110+ return "# From:" + filePath + "\n" + string(content)