coder.go

 1package prompt
 2
 3import (
 4	"context"
 5	_ "embed"
 6	"fmt"
 7	"log/slog"
 8	"os"
 9	"path/filepath"
10	"runtime"
11	"time"
12
13	"github.com/charmbracelet/crush/internal/config"
14	"github.com/charmbracelet/crush/internal/llm/tools"
15)
16
17func CoderPrompt(p string, contextFiles ...string) string {
18	var basePrompt string
19
20	basePrompt = string(baseCoderPrompt)
21	envInfo := getEnvironmentInfo()
22
23	basePrompt = fmt.Sprintf("%s\n\n%s\n%s", basePrompt, envInfo, lspInformation())
24
25	contextContent := getContextFromPaths(config.Get().WorkingDir(), contextFiles)
26	slog.Debug("Context content", "Context", contextContent)
27	if contextContent != "" {
28		return fmt.Sprintf("%s\n\n# Project-Specific Context\n Make sure to follow the instructions in the context below\n%s", basePrompt, contextContent)
29	}
30	return basePrompt
31}
32
33//go:embed coder.md
34var baseCoderPrompt []byte
35
36func getEnvironmentInfo() string {
37	cwd := config.Get().WorkingDir()
38	isGit := isGitRepo(cwd)
39	platform := runtime.GOOS
40	date := time.Now().Format("1/2/2006")
41	ls := tools.NewLsTool(cwd)
42	r, _ := ls.Run(context.Background(), tools.ToolCall{
43		Input: `{"path":"."}`,
44	})
45	return fmt.Sprintf(`Here is useful information about the environment you are running in:
46<env>
47Working directory: %s
48Is directory a git repo: %s
49Platform: %s
50Today's date: %s
51</env>
52<project>
53%s
54</project>
55		`, cwd, boolToYesNo(isGit), platform, date, r.Content)
56}
57
58func isGitRepo(dir string) bool {
59	_, err := os.Stat(filepath.Join(dir, ".git"))
60	return err == nil
61}
62
63func lspInformation() string {
64	cfg := config.Get()
65	hasLSP := false
66	for _, v := range cfg.LSP {
67		if !v.Disabled {
68			hasLSP = true
69			break
70		}
71	}
72	if !hasLSP {
73		return ""
74	}
75	return `# LSP Information
76Tools that support it will also include useful diagnostics such as linting and typechecking.
77- 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.
78- Take necessary actions to fix the issues.
79- 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.
80`
81}
82
83func boolToYesNo(b bool) string {
84	if b {
85		return "Yes"
86	}
87	return "No"
88}