blob: 32a8e0015d49506c045907f35c179b241c1d59f8 [file] [log] [blame]
Josh Bleecher Snyderf4047bb2025-05-05 23:02:56 +00001package codereview
Josh Bleecher Snydere2518e52025-04-29 11:13:40 -07002
3import (
4 "context"
5 _ "embed"
6 "fmt"
7 "os/exec"
8 "strings"
9
10 "sketch.dev/llm"
11 "sketch.dev/llm/conversation"
12)
13
14//go:embed llm_codereview_prompt.txt
15var llmCodereviewPrompt string
16
17// doLLMReview analyzes the diff using an LLM subagent.
18func (r *CodeReviewer) doLLMReview(ctx context.Context) (string, error) {
19 // Get the full diff between initial commit and HEAD
20 cmd := exec.CommandContext(ctx, "git", "diff", r.initialCommit, "HEAD")
21 cmd.Dir = r.repoRoot
22 out, err := cmd.CombinedOutput()
23 if err != nil {
24 return "", fmt.Errorf("failed to get diff: %w\n%s", err, out)
25 }
26
27 // If no diff, nothing to check
28 if len(out) == 0 {
29 return "", nil
30 }
31
32 info := conversation.ToolCallInfoFromContext(ctx)
33 convo := info.Convo.SubConvo()
Josh Bleecher Snyder593ca642025-05-07 05:19:32 -070034 convo.PromptCaching = false
Josh Bleecher Snyder4d544932025-05-07 13:33:53 +000035 convo.Hidden = true
Josh Bleecher Snydere2518e52025-04-29 11:13:40 -070036 convo.SystemPrompt = strings.TrimSpace(llmCodereviewPrompt)
37 initialMessage := llm.UserStringMessage("<diff>\n" + string(out) + "\n</diff>")
38
39 resp, err := convo.SendMessage(initialMessage)
40 if err != nil {
41 return "", fmt.Errorf("failed to send LLM codereview message: %w", err)
42 }
43 if len(resp.Content) != 1 {
44 return "", fmt.Errorf("unexpected number of content blocks in LLM codereview response: %d", len(resp.Content))
45 }
46
47 response := resp.Content[0].Text
48 if strings.TrimSpace(response) == "No comments." {
49 return "", nil
50 }
51 return response, nil
52}