Skip to content

Commit 68ed8a1

Browse files
committed
Merge branch 'main' into eval2-base2
2 parents 7f3466d + dae17a1 commit 68ed8a1

File tree

7 files changed

+28
-86
lines changed

7 files changed

+28
-86
lines changed

.agents/base2/base2.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ Use this workflow to solve a medium or complex coding task:
7676
3. Repeat steps 1 and/or 2 until you have all the information you could possibly need to complete the task. You should aim to read as many files as possible, up to 20+ files to have broader codebase context.
7777
4. Spawn a decomposing planner to come up with a plan.
7878
5. Spawn an editor to implement the plan. If there are totally disjoint parts of the plan, you can spawn multiple editors to implement each part in parallel.
79-
6. Spawn a reviewer to review the code. If changes are needed, go back to step 5, but no more than once.
79+
6. Spawn a reviewer to review the changes made by the editor. If more changes are needed, go back to step 5, but no more than once.
8080
7. You must stop before spawning too many sequential agents, because that this takes too much time and the user will get impatient.
8181
8282
Feel free to modify this workflow as needed. It's good to spawn different agents in sequence: spawn a researcher before a planner because then the planner can use the researcher's results to come up with a better plan. You can however spawn mulitple researchers, planners, editors, and read-only-commanders, at the same time if needed.
@@ -91,6 +91,8 @@ Feel free to modify this workflow as needed. It's good to spawn different agents
9191
- Be careful about instructing subagents to run terminal commands that could be destructive or have effects that are hard to undo (e.g. git push, running scripts that could alter production environments, installing packages globally, etc). Don't do any of these unless the user explicitly asks you to.
9292
`,
9393

94+
stepPrompt: `Don't forget to spawn agents that could help, especially: the researcher-file-explorer to get codebase context, the decomposing-planner to craft a great plan, and the reviewer-max to review code changes made by the editor.`,
95+
9496
handleSteps: function* ({ prompt, params }) {
9597
let steps = 0
9698
while (true) {

backend/src/__tests__/loop-agent-steps.test.ts

Lines changed: 16 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -97,17 +97,6 @@ describe('loopAgentSteps - runAgentStep vs runProgrammaticStep behavior', () =>
9797
mockModule('@codebuff/backend/get-file-reading-updates', () => ({
9898
getFileReadingUpdates: async () => [],
9999
}))
100-
101-
// Mock async agent manager
102-
mockModule('@codebuff/backend/async-agent-manager', () => ({
103-
asyncAgentManager: {
104-
getAgent: () => null,
105-
registerAgent: () => {},
106-
updateAgentState: () => {},
107-
getAndClearMessages: () => [],
108-
getMessages: () => [],
109-
},
110-
}))
111100
})
112101

113102
beforeEach(() => {
@@ -541,55 +530,6 @@ describe('loopAgentSteps - runAgentStep vs runProgrammaticStep behavior', () =>
541530
expect(llmCallCount).toBe(1) // LLM called once after STEP
542531
expect(result.agentState).toBeDefined()
543532
})
544-
545-
it('should respect async agent messages and continue appropriately', async () => {
546-
// Test async agent message handling during loopAgentSteps
547-
548-
const mockGeneratorFunction = function* () {
549-
yield { toolName: 'read_files', input: { paths: ['async-test.txt'] } }
550-
yield 'STEP'
551-
} as () => StepGenerator
552-
553-
mockTemplate.handleSteps = mockGeneratorFunction
554-
555-
const localAgentTemplates = {
556-
'test-agent': mockTemplate,
557-
}
558-
559-
// Mock async agent manager to simulate pending messages
560-
const mockAsyncAgentManager = require('@codebuff/backend/async-agent-manager')
561-
let getMessagesCallCount = 0
562-
spyOn(
563-
mockAsyncAgentManager.asyncAgentManager,
564-
'getMessages',
565-
).mockImplementation(() => {
566-
getMessagesCallCount++
567-
// Return messages on second call to simulate async agent activity
568-
return getMessagesCallCount === 2 ? ['async message'] : []
569-
})
570-
571-
const result = await runLoopAgentStepsWithContext(
572-
new MockWebSocket() as unknown as WebSocket,
573-
{
574-
userInputId: 'test-user-input',
575-
agentType: 'test-agent',
576-
agentState: mockAgentState,
577-
prompt: 'Test async agent messages',
578-
params: undefined,
579-
fingerprintId: 'test-fingerprint',
580-
fileContext: mockFileContext,
581-
localAgentTemplates,
582-
userId: TEST_USER_ID,
583-
clientSessionId: 'test-session',
584-
onResponseChunk: () => {},
585-
},
586-
)
587-
588-
// Should continue when async messages are present
589-
expect(result.agentState).toBeDefined()
590-
expect(getMessagesCallCount).toBeGreaterThan(0)
591-
})
592-
593533
it('should pass shouldEndTurn: true as stepsComplete when end_turn tool is called', async () => {
594534
// Test that when LLM calls end_turn, shouldEndTurn is correctly passed to runProgrammaticStep
595535

@@ -619,19 +559,22 @@ describe('loopAgentSteps - runAgentStep vs runProgrammaticStep behavior', () =>
619559
'test-agent': mockTemplate,
620560
}
621561

622-
await runLoopAgentStepsWithContext(new MockWebSocket() as unknown as WebSocket, {
623-
userInputId: 'test-user-input',
624-
agentType: 'test-agent',
625-
agentState: mockAgentState,
626-
prompt: 'Test shouldEndTurn to stepsComplete flow',
627-
params: undefined,
628-
fingerprintId: 'test-fingerprint',
629-
fileContext: mockFileContext,
630-
localAgentTemplates,
631-
userId: TEST_USER_ID,
632-
clientSessionId: 'test-session',
633-
onResponseChunk: () => {},
634-
})
562+
await runLoopAgentStepsWithContext(
563+
new MockWebSocket() as unknown as WebSocket,
564+
{
565+
userInputId: 'test-user-input',
566+
agentType: 'test-agent',
567+
agentState: mockAgentState,
568+
prompt: 'Test shouldEndTurn to stepsComplete flow',
569+
params: undefined,
570+
fingerprintId: 'test-fingerprint',
571+
fileContext: mockFileContext,
572+
localAgentTemplates,
573+
userId: TEST_USER_ID,
574+
clientSessionId: 'test-session',
575+
onResponseChunk: () => {},
576+
},
577+
)
635578

636579
mockedRunProgrammaticStep.clear()
637580

backend/src/__tests__/read-docs-tool.test.ts

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -183,15 +183,6 @@ describe('read_docs tool with researcher agent', () => {
183183
spy: startUserInputSpy,
184184
})
185185

186-
const endUserInputSpy = spyOn(
187-
liveUserInputs,
188-
'endUserInput',
189-
).mockImplementation(() => {})
190-
mockedFunctions.push({
191-
name: 'liveUserInputs.endUserInput',
192-
spy: endUserInputSpy,
193-
})
194-
195186
const cancelUserInputSpy = spyOn(
196187
liveUserInputs,
197188
'cancelUserInput',

backend/src/__tests__/run-agent-step-tools.test.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,6 @@ describe('runAgentStep - set_output tool', () => {
8989
// Mock live user inputs to always return true (simulating active session)
9090
spyOn(liveUserInputs, 'checkLiveUserInput').mockImplementation(() => true)
9191
spyOn(liveUserInputs, 'startUserInput').mockImplementation(() => {})
92-
spyOn(liveUserInputs, 'endUserInput').mockImplementation(() => {})
9392
spyOn(liveUserInputs, 'setSessionConnected').mockImplementation(() => {})
9493

9594
spyOn(websocketAction, 'requestFiles').mockImplementation(

backend/src/templates/strings.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ export async function getAgentPrompt<T extends StringField>({
162162
return undefined
163163
}
164164

165-
const prompt = await formatPrompt({
165+
let prompt = await formatPrompt({
166166
prompt: promptValue,
167167
fileContext,
168168
agentState,
@@ -174,6 +174,11 @@ export async function getAgentPrompt<T extends StringField>({
174174

175175
let addendum = ''
176176

177+
if (promptType.type === 'stepPrompt' && agentState.agentType) {
178+
// Put step prompt within a system-reminder tag so agent doesn't think the user just spoke again.
179+
prompt = `<system-reminder>${prompt}</system-reminder>`
180+
}
181+
177182
// Add tool instructions, spawnable agents, and output schema prompts to instructionsPrompt
178183
if (promptType.type === 'instructionsPrompt' && agentState.agentType) {
179184
const toolsInstructions = agentTemplate.inheritParentSystemPrompt

npm-app/src/client.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1348,6 +1348,8 @@ export class Client {
13481348
this.cancelCurrentInput()
13491349
this.currentOnChunk = undefined
13501350

1351+
xmlStreamParser.destroy()
1352+
13511353
const additionalMessages = prompt
13521354
? [
13531355
{ role: 'user' as const, content: prompt },

npm-app/src/display/markdown-renderer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ export class MarkdownStreamRenderer {
101101
this.width = process.stdout.columns || this.width
102102
}
103103
// Use .once with bound handler tracker to avoid duplication
104-
process.stdout.addListener('resize', this.resizeHandler)
104+
process.stdout.on('resize', this.resizeHandler)
105105
}
106106
}
107107

0 commit comments

Comments
 (0)