Skip to content

Commit 9ca64da

Browse files
committed
Improve code reviewer multi-prompt
1 parent 946585c commit 9ca64da

File tree

2 files changed

+51
-26
lines changed

2 files changed

+51
-26
lines changed

agents/reviewer/code-reviewer.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ Your task is to provide helpful critical feedback on the last file changes made
3636
3737
Be brief: If you don't have much critical feedback, simply say it looks good in one sentence. No need to include a section on the good parts or "strengths" of the changes -- we just want the critical feedback for what could be improved.
3838
39-
NOTE: You cannot make any changes directly! You can only suggest changes.
39+
NOTE: You cannot make any changes directly! DO NOT CALL ANY TOOLS! You can only suggest changes.
4040
4141
# Guidelines
4242
@@ -52,6 +52,10 @@ NOTE: You cannot make any changes directly! You can only suggest changes.
5252
- Make sure there are no unnecessary try/catch blocks. Prefer to remove those.
5353
5454
Be extremely concise.`,
55+
56+
handleSteps: function* ({ agentState, params }) {
57+
yield 'STEP'
58+
},
5559
})
5660

5761
const definition: SecretAgentDefinition = {

agents/reviewer/multi-prompt/code-reviewer-multi-prompt.ts

Lines changed: 46 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,7 @@ export function createCodeReviewerMultiPrompt(): Omit<
3232
prompts: {
3333
type: 'array',
3434
items: { type: 'string' },
35-
description:
36-
`Array of 3-5 short prompts, each specifying a different review focus or perspective. Can be specific parts of the code that was changed (frontend), or angles like reviewing with an eye for simplifying the code or design or code style.
35+
description: `Array of 3-5 short prompts, each specifying a different review focus or perspective. Can be specific parts of the code that was changed (frontend), or angles like reviewing with an eye for simplifying the code or design or code style.
3736
Example 1:
3837
["api design", "correctness and edge cases", "find ways to simplify the code or reuse existing code", "security concerns", "overall review"]
3938
Example 2:
@@ -52,6 +51,7 @@ Example 2:
5251

5352
function* handleStepsMultiPrompt({
5453
params,
54+
agentState,
5555
}: AgentStepContext): ReturnType<
5656
NonNullable<SecretAgentDefinition['handleSteps']>
5757
> {
@@ -68,11 +68,25 @@ function* handleStepsMultiPrompt({
6868
return
6969
}
7070

71+
const { messageHistory } = agentState
72+
// Remove last user messages (prompt, subagent spawn message, instructions prompt)
73+
while (messageHistory.length > 0 && messageHistory[messageHistory.length - 1].role === 'user') {
74+
messageHistory.pop()
75+
}
76+
77+
yield {
78+
toolName: 'set_messages',
79+
input: {
80+
messages: messageHistory,
81+
},
82+
includeToolCall: false,
83+
} satisfies ToolCall<'set_messages'>
84+
7185
// Spawn one code-reviewer per prompt
7286
const reviewerAgents: { agent_type: string; prompt: string }[] = prompts.map(
7387
(prompt) => ({
7488
agent_type: 'code-reviewer',
75-
prompt: `Review focus: ${prompt}`,
89+
prompt: `Review the above code changes with the following focus: ${prompt}`,
7690
}),
7791
)
7892

@@ -85,38 +99,45 @@ function* handleStepsMultiPrompt({
8599
includeToolCall: false,
86100
} satisfies ToolCall<'spawn_agents'>
87101

88-
// Extract spawn results - each is last_message output (string content)
89-
const spawnedReviews = extractSpawnResults<string>(reviewerResults)
90-
91-
// Combine all reviews with their focus areas
92-
const combinedReviews = spawnedReviews
93-
.map((review, index) => {
94-
const focus = prompts[index] ?? 'unknown'
95-
if (!review || (typeof review === 'object' && 'errorMessage' in review)) {
96-
return `## Review Focus: ${focus}\n\nError: ${(review as { errorMessage?: string })?.errorMessage ?? 'Unknown error'}`
102+
const spawnedReviews = extractSpawnResults(reviewerResults)
103+
104+
// Extract text content from each review's message content blocks
105+
const reviewTexts: string[] = []
106+
for (const review of spawnedReviews) {
107+
if ('errorMessage' in review) {
108+
reviewTexts.push(`Error: ${review.errorMessage}`)
109+
} else {
110+
// Each review is an array of messages
111+
for (const message of review) {
112+
for (const block of message.content) {
113+
if (block.type === 'text' && block.text) {
114+
reviewTexts.push(block.text)
115+
}
116+
}
97117
}
98-
return `## Review Focus: ${focus}\n\n${review}`
99-
})
100-
.join('\n\n---\n\n')
118+
}
119+
}
101120

102-
// Set output with the combined reviews
121+
// Set output with the simplified reviews (array of strings)
103122
yield {
104123
toolName: 'set_output',
105124
input: {
106-
reviews: spawnedReviews,
107-
combinedReview: combinedReviews,
108-
promptCount: prompts.length,
125+
reviews: reviewTexts,
109126
},
110127
includeToolCall: false,
111128
} satisfies ToolCall<'set_output'>
112129

130+
type ContentBlock = { type: string; text?: string }
131+
type ReviewMessage = { role: string; content: ContentBlock[]; sentAt?: number }
132+
type ReviewResult = ReviewMessage[]
133+
113134
/**
114135
* Extracts the array of subagent results from spawn_agents tool output.
115-
* For code-reviewer agents with outputMode: 'last_message', the value is the message content.
136+
* For code-reviewer agents with outputMode: 'last_message', the value is an array of messages.
116137
*/
117-
function extractSpawnResults<T>(
138+
function extractSpawnResults(
118139
results: { type: string; value?: unknown }[] | undefined,
119-
): (T | { errorMessage: string })[] {
140+
): (ReviewResult | { errorMessage: string })[] {
120141
if (!results || results.length === 0) return []
121142

122143
const jsonResult = results.find((r) => r.type === 'json')
@@ -126,23 +147,23 @@ function* handleStepsMultiPrompt({
126147
? jsonResult.value
127148
: [jsonResult.value]
128149

129-
const extracted: (T | { errorMessage: string })[] = []
150+
const extracted: (ReviewResult | { errorMessage: string })[] = []
130151
for (const result of spawnedResults) {
131152
const innerValue = result?.value
132153
if (
133154
innerValue &&
134155
typeof innerValue === 'object' &&
135156
'value' in innerValue
136157
) {
137-
extracted.push(innerValue.value as T)
158+
extracted.push(innerValue.value as ReviewResult)
138159
} else if (
139160
innerValue &&
140161
typeof innerValue === 'object' &&
141162
'errorMessage' in innerValue
142163
) {
143164
extracted.push({ errorMessage: String(innerValue.errorMessage) })
144165
} else if (innerValue != null) {
145-
extracted.push(innerValue as T)
166+
extracted.push(innerValue as ReviewResult)
146167
}
147168
}
148169
return extracted

0 commit comments

Comments
 (0)