import { createSmithers, Task, Sequence, Loop } from "smithers-orchestrator";
import { ToolLoopAgent as Agent } from "ai";
import { anthropic } from "@ai-sdk/anthropic";
import { read, grep, bash, edit, write } from "smithers-orchestrator";
import { z } from "zod";
const { Workflow, smithers, outputs } = createSmithers({
implement: z.object({
summary: z.string(),
filesChanged: z.array(z.string()),
testsRun: z.number(),
testsPassed: z.number(),
}),
review: z.object({
approved: z.boolean(),
feedback: z.string(),
score: z.number().int().min(1).max(10),
}),
report: z.object({
title: z.string(),
body: z.string(),
iterations: z.number(),
finalScore: z.number(),
}),
});
const implementer = new Agent({
model: anthropic("claude-sonnet-4-20250514"),
instructions: "You are a senior engineer. Implement changes, run tests, and return structured JSON.",
tools: { read, grep, bash, edit, write },
});
const reviewer = new Agent({
model: anthropic("claude-sonnet-4-20250514"),
instructions: "You are a strict code reviewer. Return structured JSON with your assessment.",
tools: { read, grep },
});
export default smithers((ctx) => {
const review = ctx.outputMaybe(outputs.review, { nodeId: "review" });
return (
<Workflow name="review-loop">
<Sequence>
<Loop
until={review?.approved === true}
maxIterations={3}
onMaxReached="return-last"
>
<Sequence>
<Task
id="implement"
output={outputs.implement}
agent={implementer}
timeoutMs={300_000}
retries={1}
>
{`Implement: ${ctx.input.description}
${review?.feedback ? `Previous review feedback:\n${review.feedback}` : ""}
After making changes:
1. Run \`bun test\` and report results
2. Verify your changes address the requirements
Return JSON with summary, filesChanged, testsRun, testsPassed.`}
</Task>
<Task
id="review"
output={outputs.review}
agent={reviewer}
timeoutMs={120_000}
retries={1}
deps={{ implement: outputs.implement }}
>
{(deps) => `Review the implementation.
Summary: ${deps.implement.summary}
Files changed: ${deps.implement.filesChanged.join(", ")}
Tests: ${deps.implement.testsPassed}/${deps.implement.testsRun} passed
Approve only if tests pass and the code is clean.
Return JSON with approved (boolean), feedback (string), score (1-10).`}
</Task>
</Sequence>
</Loop>
{review ? (
<Task id="report" output={outputs.report}>
{{
title: `Review: ${ctx.input.description}`,
body: review.feedback,
iterations: ctx.iterationCount("review", "review") ?? 1,
finalScore: review.score,
}}
</Task>
) : null}
</Sequence>
</Workflow>
);
});