coder.go

 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}