Skip to content

Commit 021d148

Browse files
authored
N (#370)
1 parent 98df71b commit 021d148

File tree

20 files changed

+1672
-431
lines changed

20 files changed

+1672
-431
lines changed

.agents/editor/best-of-n/best-of-n-implementor-gpt-5.ts

Lines changed: 0 additions & 8 deletions
This file was deleted.

.agents/editor/best-of-n/best-of-n-implementor.ts

Lines changed: 0 additions & 118 deletions
This file was deleted.

.agents/editor/best-of-n/editor-best-of-n.ts

Lines changed: 69 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import type {
66
StepText,
77
ToolCall,
88
} from '../../types/agent-definition'
9+
910
export function createBestOfNEditor(
1011
model: 'sonnet' | 'gpt-5',
1112
): Omit<SecretAgentDefinition, 'id'> {
@@ -29,8 +30,8 @@ export function createBestOfNEditor(
2930
'set_output',
3031
],
3132
spawnableAgents: isGpt5
32-
? ['best-of-n-implementor-gpt-5', 'best-of-n-selector-gpt-5']
33-
: ['best-of-n-implementor', 'best-of-n-selector'],
33+
? ['best-of-n-selector-gpt-5']
34+
: ['best-of-n-selector'],
3435

3536
inputSchema: {
3637
params: {
@@ -46,47 +47,82 @@ export function createBestOfNEditor(
4647
},
4748
outputMode: 'structured_output',
4849

50+
instructionsPrompt: `You are one agent within the editor-best-of-n. You were spawned to generate an implementation for the user's request.
51+
52+
Your task is to write out ALL the code changes needed to complete the user's request in a single comprehensive response.
53+
54+
Important: You can not make any other tool calls besides editing files. You cannot read more files, write todos, or spawn agents.
55+
56+
Write out what changes you would make using str_replace and/or write_file tool calls.
57+
58+
${
59+
isGpt5
60+
? ``
61+
: `
62+
You can also use <think> tags interspersed between tool calls to think about the best way to implement the changes. Keep these thoughts very brief. You may not need to use think tags at all.
63+
64+
<example>
65+
66+
<think>
67+
[ Thoughts about the best way to implement the feature ]
68+
</think>
69+
70+
<codebuff_tool_call>
71+
[ First tool call to implement the feature ]
72+
</codebuff_tool_call>
73+
74+
<codebuff_tool_call>
75+
[ Second tool call to implement the feature ]
76+
</codebuff_tool_call>
77+
78+
<think>
79+
[ Thoughts about a tricky part of the implementation ]
80+
</think>
81+
82+
<codebuff_tool_call>
83+
[ Third tool call to implement the feature ]
84+
</codebuff_tool_call>
85+
86+
</example>`
87+
}
88+
89+
Your implementation should:
90+
- Be complete and comprehensive
91+
- Include all necessary changes to fulfill the user's request
92+
- Follow the project's conventions and patterns
93+
- Be as simple and maintainable as possible
94+
- Reuse existing code wherever possible
95+
- Be well-structured and organized
96+
97+
More style notes:
98+
- Try/catch blocks clutter the code -- use them sparingly.
99+
- Optional arguments are code smell and worse than required arguments.
100+
- New components often should be added to a new file, not added to an existing file.
101+
102+
Write out your complete implementation now as a series of file editing tool calls.`,
103+
49104
handleSteps: isGpt5 ? handleStepsGpt5 : handleStepsSonnet,
50105
}
51106
}
52107

53108
function* handleStepsSonnet({
54-
agentState,
55109
params,
56110
}: AgentStepContext): ReturnType<
57111
NonNullable<SecretAgentDefinition['handleSteps']>
58112
> {
59-
const implementorAgent = 'best-of-n-implementor'
60113
const selectorAgent = 'best-of-n-selector'
61114
const n = Math.min(10, Math.max(1, (params?.n as number | undefined) ?? 5))
62115

63-
// Remove userInstruction message for this agent.
64-
const messages = agentState.messageHistory.concat()
65-
messages.pop()
66-
yield {
67-
toolName: 'set_messages',
68-
input: {
69-
messages,
70-
},
71-
includeToolCall: false,
72-
} satisfies ToolCall<'set_messages'>
73-
74-
const { toolResult: implementorsResult1 } = yield {
75-
toolName: 'spawn_agents',
76-
input: {
77-
agents: Array.from({ length: n }, () => ({
78-
agent_type: implementorAgent,
79-
})),
80-
},
81-
includeToolCall: false,
82-
} satisfies ToolCall<'spawn_agents'>
83-
84-
const implementorsResult = extractSpawnResults<string>(implementorsResult1)
116+
// Use GENERATE_N to generate n implementations
117+
const { nResponses = [] } = yield {
118+
type: 'GENERATE_N',
119+
n,
120+
}
85121

86122
// Extract all the plans from the structured outputs
87123
const letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
88124
// Parse implementations from tool results
89-
const implementations = implementorsResult.map((content, index) => ({
125+
const implementations = nResponses.map((content, index) => ({
90126
id: letters[index],
91127
content,
92128
}))
@@ -195,42 +231,23 @@ function* handleStepsSonnet({
195231
}
196232

197233
function* handleStepsGpt5({
198-
agentState,
199234
params,
200235
}: AgentStepContext): ReturnType<
201236
NonNullable<SecretAgentDefinition['handleSteps']>
202237
> {
203-
const implementorAgent = 'best-of-n-implementor-gpt-5'
204238
const selectorAgent = 'best-of-n-selector-gpt-5'
205239
const n = Math.min(10, Math.max(1, (params?.n as number | undefined) ?? 5))
206240

207-
// Remove userInstruction message for this agent.
208-
const messages = agentState.messageHistory.concat()
209-
messages.pop()
210-
yield {
211-
toolName: 'set_messages',
212-
input: {
213-
messages,
214-
},
215-
includeToolCall: false,
216-
} satisfies ToolCall<'set_messages'>
217-
218-
const { toolResult: implementorsResult1 } = yield {
219-
toolName: 'spawn_agents',
220-
input: {
221-
agents: Array.from({ length: n }, () => ({
222-
agent_type: implementorAgent,
223-
})),
224-
},
225-
includeToolCall: false,
226-
} satisfies ToolCall<'spawn_agents'>
227-
228-
const implementorsResult = extractSpawnResults<string>(implementorsResult1)
241+
// Use GENERATE_N to generate n implementations
242+
const { nResponses = [] } = yield {
243+
type: 'GENERATE_N',
244+
n,
245+
}
229246

230247
// Extract all the plans from the structured outputs
231248
const letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
232249
// Parse implementations from tool results
233-
const implementations = implementorsResult.map((content, index) => ({
250+
const implementations = nResponses.map((content, index) => ({
234251
id: letters[index],
235252
content,
236253
}))

.agents/types/agent-definition.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,12 +257,13 @@ export interface AgentDefinition {
257257
* }
258258
*/
259259
handleSteps?: (context: AgentStepContext) => Generator<
260-
ToolCall | 'STEP' | 'STEP_ALL' | StepText,
260+
ToolCall | 'STEP' | 'STEP_ALL' | StepText | GenerateN,
261261
void,
262262
{
263263
agentState: AgentState
264264
toolResult: ToolResultOutput[] | undefined
265265
stepsComplete: boolean
266+
nResponses?: string[]
266267
}
267268
>
268269
}
@@ -294,6 +295,7 @@ export interface AgentStepContext {
294295
}
295296

296297
export type StepText = { type: 'STEP_TEXT'; text: string }
298+
export type GenerateN = { type: 'GENERATE_N'; n: number }
297299

298300
/**
299301
* Tool call object for handleSteps generator

common/src/templates/initial-agents-dir/types/agent-definition.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,12 +257,13 @@ export interface AgentDefinition {
257257
* }
258258
*/
259259
handleSteps?: (context: AgentStepContext) => Generator<
260-
ToolCall | 'STEP' | 'STEP_ALL' | StepText,
260+
ToolCall | 'STEP' | 'STEP_ALL' | StepText | GenerateN,
261261
void,
262262
{
263263
agentState: AgentState
264264
toolResult: ToolResultOutput[] | undefined
265265
stepsComplete: boolean
266+
nResponses?: string[]
266267
}
267268
>
268269
}
@@ -294,6 +295,7 @@ export interface AgentStepContext {
294295
}
295296

296297
export type StepText = { type: 'STEP_TEXT'; text: string }
298+
export type GenerateN = { type: 'GENERATE_N'; n: number }
297299

298300
/**
299301
* Tool call object for handleSteps generator

common/src/types/agent-template.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,14 +139,16 @@ export type AgentTemplate<
139139
}
140140

141141
export type StepText = { type: 'STEP_TEXT'; text: string }
142+
export type GenerateN = { type: 'GENERATE_N'; n: number }
142143

143144
export type StepGenerator = Generator<
144-
Omit<ToolCall, 'toolCallId'> | 'STEP' | 'STEP_ALL' | StepText, // Generic tool call type
145+
Omit<ToolCall, 'toolCallId'> | 'STEP' | 'STEP_ALL' | StepText | GenerateN, // Generic tool call type
145146
void,
146147
{
147148
agentState: PublicAgentState
148149
toolResult: ToolResultOutput[]
149150
stepsComplete: boolean
151+
nResponses?: string[]
150152
}
151153
>
152154

common/src/types/contracts/llm.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ export type PromptAiSdkFn = (
6464
sendAction: SendActionFn
6565
logger: Logger
6666
trackEvent: TrackEventFn
67+
n?: number
6768
} & ParamsExcluding<typeof generateText, 'model' | 'messages'> &
6869
ParamsExcluding<CheckLiveUserInputFn, 'clientSessionId'>,
6970
) => Promise<string>

0 commit comments

Comments
 (0)