@@ -2,36 +2,17 @@ import { execSync } from 'child_process'
22import fs from 'fs'
33import path from 'path'
44
5- import { runAgentStep } from '@codebuff/agent-runtime/run-agent-step'
6- import { assembleLocalAgentTemplates } from '@codebuff/agent-runtime/templates/agent-registry'
75import { getFileTokenScores } from '@codebuff/code-map/parse'
8- import { API_KEY_ENV_VAR , TEST_USER_ID } from '@codebuff/common/old-constants'
9- import { clientToolCallSchema } from '@codebuff/common/tools/list'
10- import { generateCompactId } from '@codebuff/common/util/string'
116import { getSystemInfo } from '@codebuff/common/util/system-info'
12- import { ToolHelpers } from '@codebuff/sdk'
13- import { blue } from 'picocolors'
147
15- import { EVALS_AGENT_RUNTIME_IMPL } from './impl/agent-runtime'
168import {
179 getAllFilePaths ,
1810 getProjectFileTree ,
1911} from '../common/src/project-file-tree'
2012
21- import type { ClientToolCall } from '@codebuff/common/tools/list'
22- import type { AgentRuntimeScopedDeps } from '@codebuff/common/types/contracts/agent-runtime'
23- import type { CodebuffFileSystem } from '@codebuff/common/types/filesystem'
24- import type { ToolMessage } from '@codebuff/common/types/messages/codebuff-message'
25- import type { ToolResultOutput } from '@codebuff/common/types/messages/content-part'
26- import type { PrintModeEvent } from '@codebuff/common/types/print-mode'
27- import type {
28- AgentState ,
29- AgentTemplateType ,
30- SessionState ,
31- } from '@codebuff/common/types/session-state'
3213import type { ProjectFileContext } from '@codebuff/common/util/file'
3314
34- const DEBUG_MODE = true
15+ let projectRootForMocks : string | undefined
3516
3617function readMockFile ( projectRoot : string , filePath : string ) : string | null {
3718 const fullPath = path . join ( projectRoot , filePath )
@@ -42,104 +23,10 @@ function readMockFile(projectRoot: string, filePath: string): string | null {
4223 }
4324}
4425
45- let toolCalls : ClientToolCall [ ] = [ ]
46- let toolResults : ToolMessage [ ] = [ ]
47- const defaultFs : CodebuffFileSystem = fs . promises as unknown as CodebuffFileSystem
48- let projectRootForMocks : string | undefined
49-
5026export function createFileReadingMock ( projectRoot : string ) {
5127 projectRootForMocks = projectRoot
5228}
5329
54- function getActiveProjectRoot ( fileContext ?: ProjectFileContext ) {
55- return fileContext ?. projectRoot ?? projectRootForMocks ?? process . cwd ( )
56- }
57-
58- async function readFilesFromProject ( params : {
59- projectRoot : string
60- filePaths : string [ ]
61- } ) {
62- const { projectRoot, filePaths } = params
63- const files : Record < string , string | null > = { }
64- for ( const filePath of filePaths ) {
65- const fileContent = readMockFile ( projectRoot , filePath )
66- files [ filePath ] = fileContent
67- }
68- return files
69- }
70-
71- async function executeToolCall (
72- toolCall : ClientToolCall ,
73- projectRoot : string ,
74- ) : Promise < ToolResultOutput [ ] > {
75- switch ( toolCall . toolName ) {
76- case 'write_file' :
77- case 'str_replace' :
78- return ToolHelpers . changeFile ( {
79- parameters : toolCall . input ,
80- cwd : projectRoot ,
81- fs : defaultFs ,
82- } )
83- case 'run_terminal_command' : {
84- const resolvedCwd = path . resolve (
85- projectRoot ,
86- ( toolCall . input as { cwd ?: string } ) . cwd ?? '.' ,
87- )
88- return ToolHelpers . runTerminalCommand ( {
89- ...( toolCall . input as any ) ,
90- cwd : resolvedCwd ,
91- } )
92- }
93- case 'code_search' :
94- return ToolHelpers . codeSearch ( {
95- ...( toolCall . input as any ) ,
96- projectPath : projectRoot ,
97- } )
98- case 'list_directory' :
99- return ToolHelpers . listDirectory ( {
100- directoryPath : ( toolCall . input as { path : string } ) . path ,
101- projectPath : projectRoot ,
102- fs : defaultFs ,
103- } )
104- case 'glob' :
105- return ToolHelpers . glob ( {
106- ...( toolCall . input as any ) ,
107- projectPath : projectRoot ,
108- fs : defaultFs ,
109- } )
110- case 'run_file_change_hooks' :
111- return ToolHelpers . runFileChangeHooks ( toolCall . input as any )
112- case 'browser_logs' :
113- case 'create_plan' :
114- return [
115- {
116- type : 'json' ,
117- value : {
118- message : `Tool ${ toolCall . toolName } is a no-op in eval scaffolding.` ,
119- } ,
120- } ,
121- ]
122- case 'ask_user' :
123- return [
124- {
125- type : 'json' ,
126- value : {
127- errorMessage : 'ask_user is not supported in eval scaffolding' ,
128- } ,
129- } ,
130- ]
131- default :
132- return [
133- {
134- type : 'json' ,
135- value : {
136- errorMessage : 'Unsupported tool in eval scaffolding' ,
137- } ,
138- } ,
139- ]
140- }
141- }
142-
14330export async function getProjectFileContext (
14431 projectPath : string ,
14532) : Promise < ProjectFileContext > {
@@ -181,185 +68,6 @@ export async function getProjectFileContext(
18168 }
18269}
18370
184- export async function runAgentStepScaffolding (
185- agentState : AgentState ,
186- fileContext : ProjectFileContext ,
187- prompt : string | undefined ,
188- sessionId : string ,
189- agentType : AgentTemplateType ,
190- ) {
191- let fullResponse = ''
192- const projectRoot = getActiveProjectRoot ( fileContext )
193- const { agentTemplates : localAgentTemplates } = assembleLocalAgentTemplates ( {
194- fileContext,
195- logger : console ,
196- } )
197-
198- const agentRuntimeScopedImpl : AgentRuntimeScopedDeps = {
199- handleStepsLogChunk : ( ) => { } ,
200- requestToolCall : async ( { toolName, input } ) => {
201- const parsedToolCall = clientToolCallSchema . parse ( { toolName, input } )
202- const toolCall : ClientToolCall = {
203- ...( parsedToolCall as ClientToolCall ) ,
204- toolCallId : generateCompactId ( ) ,
205- }
206- toolCalls . push ( toolCall )
207- const output = await executeToolCall ( toolCall , projectRoot )
208- toolResults . push ( {
209- role : 'tool' ,
210- toolName : toolCall . toolName ,
211- toolCallId : toolCall . toolCallId ,
212- content : output ,
213- } )
214- return { output }
215- } ,
216- requestMcpToolData : async ( ) => [ ] ,
217- requestFiles : ( { filePaths } ) =>
218- readFilesFromProject ( { projectRoot, filePaths } ) ,
219- requestOptionalFile : async ( { filePath } ) => {
220- const files = await readFilesFromProject ( {
221- projectRoot,
222- filePaths : [ filePath ] ,
223- } )
224- return files [ filePath ] ?? null
225- } ,
226- sendSubagentChunk : ( ) => { } ,
227- sendAction : ( ) => { } ,
228- apiKey : process . env [ API_KEY_ENV_VAR ] ?? '' ,
229- }
230- const result = await runAgentStep ( {
231- ...EVALS_AGENT_RUNTIME_IMPL ,
232- ...agentRuntimeScopedImpl ,
233-
234- additionalToolDefinitions : ( ) => Promise . resolve ( { } ) ,
235- agentState,
236- agentType,
237- ancestorRunIds : [ ] ,
238- clientSessionId : sessionId ,
239- fileContext,
240- fingerprintId : 'test-fingerprint-id' ,
241- localAgentTemplates,
242- onResponseChunk : ( chunk : string | PrintModeEvent ) => {
243- if ( typeof chunk !== 'string' ) {
244- return
245- }
246- if ( DEBUG_MODE ) {
247- process . stdout . write ( chunk )
248- }
249- fullResponse += chunk
250- } ,
251- prompt,
252- repoId : undefined ,
253- repoUrl : undefined ,
254- runId : 'test-run-id' ,
255- signal : new AbortController ( ) . signal ,
256- spawnParams : undefined ,
257- system : 'Test system prompt' ,
258- tools : { } ,
259- userId : TEST_USER_ID ,
260- userInputId : generateCompactId ( ) ,
261- } )
262-
263- return {
264- ...result ,
265- fullResponse,
266- }
267- }
268-
269- export async function runToolCalls ( toolCalls : ClientToolCall [ ] ) {
270- const toolResults : ToolMessage [ ] = [ ]
271- for ( const toolCall of toolCalls ) {
272- const toolCallId = toolCall . toolCallId ?? generateCompactId ( )
273- const output = await executeToolCall (
274- { ...toolCall , toolCallId } as ClientToolCall ,
275- getActiveProjectRoot ( ) ,
276- )
277- toolResults . push ( {
278- role : 'tool' ,
279- toolName : toolCall . toolName ,
280- toolCallId,
281- content : output ,
282- } )
283- }
284- return toolResults
285- }
286-
287- export async function loopMainPrompt ( {
288- sessionState,
289- prompt,
290- maxIterations,
291- stopCondition,
292- agentType,
293- } : {
294- sessionState : SessionState
295- prompt : string
296- maxIterations : number
297- stopCondition ?: ( sessionState : AgentState ) => boolean
298- agentType : AgentTemplateType
299- } ) {
300- console . log ( blue ( prompt ) )
301-
302- const startTime = Date . now ( )
303- const sessionId = 'test-session-id-' + generateCompactId ( )
304- let currentAgentState = sessionState . mainAgentState
305- let iterations = 1
306- const steps : any [ ] = [ ]
307-
308- for ( ; iterations < maxIterations ; iterations ++ ) {
309- console . log ( '\nIteration' , iterations )
310- let {
311- agentState : newAgentState ,
312- fullResponse,
313- shouldEndTurn,
314- } = await runAgentStepScaffolding (
315- currentAgentState ,
316- sessionState . fileContext ,
317- iterations === 1 ? prompt : undefined ,
318- sessionId ,
319- agentType ,
320- )
321- currentAgentState = newAgentState
322-
323- const stop = stopCondition && stopCondition ( currentAgentState )
324- if ( stop ) break
325-
326- steps . push ( {
327- response : fullResponse ,
328- toolCalls,
329- toolResults,
330- } )
331-
332- toolCalls = [ ]
333- toolResults = [ ]
334-
335- if ( shouldEndTurn ) {
336- break
337- }
338- }
339-
340- console . log ( 'Main loop finished!' )
341- console . log ( ' - iterations' , iterations )
342- console . log (
343- ' - took' ,
344- ( ( Date . now ( ) - startTime ) / 1000 ) . toFixed ( 2 ) ,
345- 'seconds' ,
346- )
347-
348- return {
349- agentState : currentAgentState ,
350- iterations : iterations - 1 ,
351- steps,
352- duration : Date . now ( ) - startTime ,
353- }
354- }
355-
356- export function extractErrorFiles ( output : string ) : string [ ] {
357- const lines = output . split ( '\n' )
358- return lines
359- . filter ( ( line ) => line . includes ( ': error TS' ) )
360- . map ( ( line ) => line . split ( '(' ) [ 0 ] . trim ( ) )
361- }
362-
36371export function resetRepoToCommit ( projectPath : string , commit : string ) {
36472 console . log ( `Resetting repository at ${ projectPath } to commit ${ commit } ...` )
36573 try {
@@ -375,13 +83,3 @@ export function resetRepoToCommit(projectPath: string, commit: string) {
37583 throw error
37684 }
37785}
378-
379- export default {
380- createFileReadingMock,
381- getProjectFileContext,
382- runAgentStepScaffolding,
383- runToolCalls,
384- loopMainPrompt,
385- extractErrorFiles,
386- resetRepoToCommit,
387- }
0 commit comments