1package prompt
2
3import (
4 _ "embed"
5 "fmt"
6 "os"
7 "path/filepath"
8 "runtime"
9 "strconv"
10 "time"
11
12 "github.com/charmbracelet/catwalk/pkg/catwalk"
13 "github.com/charmbracelet/crush/internal/config"
14)
15
16func CoderPrompt(p string, contextFiles ...string) string {
17 var basePrompt string
18
19 basePrompt = string(anthropicCoderPrompt)
20 switch p {
21 case string(catwalk.InferenceProviderOpenAI):
22 // seems to behave better
23 basePrompt = string(coderV2Prompt)
24 case string(catwalk.InferenceProviderGemini):
25 basePrompt = string(geminiCoderPrompt)
26 }
27 if ok, _ := strconv.ParseBool(os.Getenv("CRUSH_CODER_V2")); ok {
28 basePrompt = string(coderV2Prompt)
29 }
30 envInfo := getEnvironmentInfo()
31
32 basePrompt = fmt.Sprintf("%s\n\n%s\n%s", basePrompt, envInfo, lspInformation())
33
34 contextContent := getContextFromPaths(config.Get().WorkingDir(), contextFiles)
35 if contextContent != "" {
36 return fmt.Sprintf("%s\n\n# Project-Specific Context\n Make sure to follow the instructions in the context below\n%s", basePrompt, contextContent)
37 }
38 return basePrompt
39}
40
41//go:embed anthropic.md
42var anthropicCoderPrompt []byte
43
44//go:embed gemini.md
45var geminiCoderPrompt []byte
46
47//go:embed v2.md
48var coderV2Prompt []byte
49
50func getEnvironmentInfo() string {
51 cwd := config.Get().WorkingDir()
52 isGit := isGitRepo(cwd)
53 platform := runtime.GOOS
54 date := time.Now().Format("1/2/2006")
55 return fmt.Sprintf(`Here is useful information about the environment you are running in:
56<env>
57Working directory: %s
58Is directory a git repo: %s
59Platform: %s
60Today's date: %s
61</env>
62 `, cwd, boolToYesNo(isGit), platform, date)
63}
64
65func isGitRepo(dir string) bool {
66 _, err := os.Stat(filepath.Join(dir, ".git"))
67 return err == nil
68}
69
70func lspInformation() string {
71 cfg := config.Get()
72 hasLSP := false
73 for _, v := range cfg.LSP {
74 if !v.Disabled {
75 hasLSP = true
76 break
77 }
78 }
79 if !hasLSP {
80 return ""
81 }
82 return `# LSP Information
83Tools that support it will also include useful diagnostics such as linting and typechecking.
84- These diagnostics will be automatically enabled when you run the tool, and will be displayed in the output at the bottom within the <file_diagnostics></file_diagnostics> and <project_diagnostics></project_diagnostics> tags.
85- Take necessary actions to fix the issues.
86- You should ignore diagnostics of files that you did not change or are not related or caused by your changes unless the user explicitly asks you to fix them.
87`
88}
89
90func boolToYesNo(b bool) string {
91 if b {
92 return "Yes"
93 }
94 return "No"
95}