-
Notifications
You must be signed in to change notification settings - Fork 30
Expand file tree
/
Copy pathcode-review-loop.jsx
More file actions
69 lines (68 loc) · 2.94 KB
/
Copy pathcode-review-loop.jsx
File metadata and controls
69 lines (68 loc) · 2.94 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
import { Sequence, Ralph } from "smithers-orchestrator";
import { createExampleSmithers } from "./_example-kit.js";
import { ToolLoopAgent as Agent, Output } from "ai";
import { anthropic } from "@ai-sdk/anthropic";
import { read, bash, grep } from "smithers-orchestrator/tools";
import { z } from "zod";
import ReviewPrompt from "./prompts/code-review-loop/review.mdx";
import FixPrompt from "./prompts/code-review-loop/fix.mdx";
// Define Zod schemas
const reviewSchema = z.object({
approved: z.boolean(),
feedback: z.string(),
issues: z.array(z.string()).optional(),
});
const fixSchema = z.object({
filesChanged: z.array(z.string()),
changesSummary: z.string(),
});
const outputSchema = z.object({
finalSummary: z.string(),
totalIterations: z.number(),
});
// Create smithers with schema-driven API
const { Workflow, Task, smithers, outputs } = createExampleSmithers({
review: reviewSchema,
fix: fixSchema,
output: outputSchema,
});
const reviewAgent = new Agent({
model: anthropic("claude-sonnet-4-6"),
tools: { read, grep, bash },
output: Output.object({ schema: reviewSchema }),
instructions: `You are a senior code reviewer. Review the codebase thoroughly.
If everything looks good, set approved to true and say "LGTM" in feedback.
If there are issues, set approved to false and list specific issues to fix.`,
});
const fixAgent = new Agent({
model: anthropic("claude-sonnet-4-6"),
tools: { read, grep }, // Remove edit to prevent actual changes
instructions: `You are a senior software engineer. Analyze the issues and describe what fixes would be needed.
Do NOT actually make changes - just describe what you WOULD fix.
Respond with ONLY a JSON object:
{"filesChanged": ["path/to/file1.ts"], "changesSummary": "Description of fixes needed"}`,
});
export default smithers((ctx) => {
const latestReview = ctx.outputs.review?.[ctx.outputs.review.length - 1];
const isApproved = latestReview?.approved ?? false;
return (<Workflow name="code-review-loop">
<Ralph until={isApproved} maxIterations={3} onMaxReached="return-last">
<Sequence>
<Task id="review" output={outputs.review} agent={reviewAgent}>
<ReviewPrompt directory={ctx.input.directory} focus={ctx.input.focus} previousIssues={latestReview?.issues ?? []}/>
</Task>
<Task id="fix" output={outputs.fix} agent={fixAgent} skipIf={isApproved} deps={{ review: outputs.review }}>
{(deps) => (<FixPrompt feedback={deps.review.feedback} issues={deps.review.issues ?? []} directory={ctx.input.directory}/>)}
</Task>
</Sequence>
</Ralph>
<Task id="summary" output={outputs.output}>
{{
finalSummary: isApproved
? "Code review passed - LGTM!"
: `Review completed after ${ctx.outputs.review?.length ?? 0} iterations`,
totalIterations: ctx.outputs.review?.length ?? 0,
}}
</Task>
</Workflow>);
});