Skip to content

Commit 5a73969

Browse files
feat(logging): add comprehensive runtime logs across benchify batch-str-replace integration to aid debugging cloud deployment issues.
This adds end-to-end logs for processing, batching, and deployment interactions to aid issue reproduction. 🤖 Generated with Codebuff Co-Authored-By: Codebuff <noreply@codebuff.com>
1 parent d2a6020 commit 5a73969

File tree

4 files changed

+235
-21
lines changed

4 files changed

+235
-21
lines changed

backend/src/process-str-replace.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,22 @@ export async function processStrReplace(
2121
}
2222
| { tool: 'str_replace'; path: string; error: string }
2323
> {
24+
logger.debug(
25+
{
26+
path,
27+
replacementsCount: replacements.length,
28+
},
29+
'processStrReplace: Starting to process str_replace',
30+
)
31+
2432
const initialContent = await initialContentPromise
2533
if (initialContent === null) {
34+
logger.warn(
35+
{
36+
path,
37+
},
38+
'processStrReplace: File does not exist',
39+
)
2640
return {
2741
tool: 'str_replace',
2842
path,
@@ -31,6 +45,15 @@ export async function processStrReplace(
3145
}
3246
}
3347

48+
logger.debug(
49+
{
50+
path,
51+
initialContentLength: initialContent.length,
52+
hasContent: !!initialContent,
53+
},
54+
'processStrReplace: Successfully read initial file content',
55+
)
56+
3457
// Process each old/new string pair
3558
let currentContent = initialContent
3659
let messages: string[] = []

backend/src/run-agent-step.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,16 @@ export const runAgentStep = async (
289289

290290
const stream = getStream(messagesWithSystem(agentMessages, system))
291291

292+
logger.info(
293+
{
294+
agentStepId,
295+
userInputId,
296+
agentType,
297+
agentId: agentState.agentId,
298+
},
299+
'run-agent-step: About to call processStreamWithTools',
300+
)
301+
292302
const {
293303
toolCalls,
294304
toolResults: newToolResults,
@@ -313,6 +323,17 @@ export const runAgentStep = async (
313323
onResponseChunk,
314324
fullResponse,
315325
})
326+
327+
logger.info(
328+
{
329+
agentStepId,
330+
userInputId,
331+
toolCallsCount: toolCalls.length,
332+
toolResultsCount: newToolResults.length,
333+
toolCallTypes: toolCalls.map((tc) => tc.toolName),
334+
},
335+
'run-agent-step: Completed processStreamWithTools',
336+
)
316337
toolResults.push(...newToolResults)
317338

318339
fullResponse = fullResponseAfterStream

backend/src/tools/batch-str-replace.ts

Lines changed: 160 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -33,24 +33,54 @@ function getBenchifyClient(): Benchify | null {
3333
if (!benchifyClient) {
3434
let benchifyApiKey: string | undefined
3535
try {
36+
// Log available environment variables (partial for debugging)
37+
const envKeys = Object.keys(process.env)
38+
.filter((key) => key.includes('BENCHIFY') || key.includes('API'))
39+
.slice(0, 10) // Limit to first 10 for safety
40+
3641
benchifyApiKey = env.BENCHIFY_API_KEY
42+
logger.info(
43+
{
44+
hasApiKey: !!benchifyApiKey,
45+
apiKeyLength: benchifyApiKey?.length || 0,
46+
apiKeyPrefix: benchifyApiKey?.substring(0, 8) || 'none',
47+
availableEnvKeys: envKeys,
48+
nodeEnv: process.env.NODE_ENV,
49+
},
50+
'getBenchifyClient: Attempting to access BENCHIFY_API_KEY from environment',
51+
)
3752
} catch (error) {
3853
logger.warn(
3954
{
4055
error: error instanceof Error ? error.message : String(error),
56+
nodeEnv: process.env.NODE_ENV,
4157
},
42-
'Failed to access BENCHIFY_API_KEY from environment',
58+
'getBenchifyClient: Failed to access BENCHIFY_API_KEY from environment',
4359
)
4460
return null
4561
}
4662

4763
if (!benchifyApiKey) {
64+
logger.warn(
65+
'getBenchifyClient: No BENCHIFY_API_KEY found, returning null',
66+
)
4867
return null
4968
}
5069

51-
benchifyClient = new Benchify({
52-
apiKey: benchifyApiKey,
53-
})
70+
try {
71+
benchifyClient = new Benchify({
72+
apiKey: benchifyApiKey,
73+
})
74+
logger.info('getBenchifyClient: Successfully created Benchify client')
75+
} catch (error) {
76+
logger.error(
77+
{
78+
error: error instanceof Error ? error.message : String(error),
79+
},
80+
'getBenchifyClient: Failed to create Benchify client',
81+
)
82+
return null
83+
}
5484
}
5585
return benchifyClient
5686
}
@@ -84,7 +114,20 @@ export async function executeBatchStrReplaces({
84114
state: Record<string, any>
85115
userId: string | undefined
86116
}) {
117+
logger.info(
118+
{
119+
deferredCount: deferredStrReplaces.length,
120+
agentStepId,
121+
userInputId,
122+
userId,
123+
},
124+
'executeBatchStrReplaces: Starting batch execution',
125+
)
126+
87127
if (deferredStrReplaces.length === 0) {
128+
logger.info(
129+
'executeBatchStrReplaces: No deferred str_replace operations, returning early',
130+
)
88131
return
89132
}
90133

@@ -281,8 +324,30 @@ export async function executeBatchStrReplaces({
281324
await Promise.all(batchPromises)
282325

283326
// Call benchify with intended changes (even if str_replace operations failed)
327+
logger.info(
328+
{
329+
intendedChangesCount: intendedChanges.length,
330+
editedFilesCount: editedFiles.length,
331+
intendedChangeFiles: intendedChanges.map((f) => f.path),
332+
editedFilesList: editedFiles.map((f) => f.path),
333+
agentStepId,
334+
userInputId,
335+
},
336+
'executeBatchStrReplaces: Preparing to call benchify',
337+
)
338+
284339
const client = getBenchifyClient()
285-
if (!client || intendedChanges.length === 0) {
340+
if (!client) {
341+
logger.warn(
342+
'executeBatchStrReplaces: No benchify client available, skipping benchify call',
343+
)
344+
return
345+
}
346+
347+
if (intendedChanges.length === 0) {
348+
logger.warn(
349+
'executeBatchStrReplaces: No intended changes for benchify, skipping benchify call',
350+
)
286351
return
287352
}
288353

@@ -340,26 +405,68 @@ async function callBenchify(
340405
userId: string | undefined
341406
},
342407
): Promise<{ path: string; contents: string }[] | null> {
408+
logger.info(
409+
{
410+
editedFilesCount: editedFiles.length,
411+
editedFilesList: editedFiles.map((f) => f.path),
412+
totalContentLength: editedFiles.reduce(
413+
(sum, f) => sum + f.contents.length,
414+
0,
415+
),
416+
...context,
417+
},
418+
'callBenchify: Starting benchify API call',
419+
)
420+
343421
const client = getBenchifyClient()
344422
if (!client) {
423+
logger.error('callBenchify: No benchify client available')
345424
return null
346425
}
347426

348-
const response = await client.runFixer(editedFiles, {
349-
fix_types: ['string_literals'],
350-
})
427+
try {
428+
logger.info(
429+
{
430+
fixTypes: ['string_literals'],
431+
...context,
432+
},
433+
'callBenchify: Calling client.runFixer',
434+
)
351435

352-
logger.info(
353-
{
354-
responseReceived: !!response,
355-
responseLength: response?.length || 0,
356-
responseFiles: response?.map((r) => r.path) || [],
357-
...context,
358-
},
359-
'Benchify runFixer API response received',
360-
)
436+
const response = await client.runFixer(editedFiles, {
437+
fix_types: ['string_literals'],
438+
})
361439

362-
return response
440+
logger.info(
441+
{
442+
responseReceived: !!response,
443+
responseLength: response?.length || 0,
444+
responseFiles: response?.map((r) => r.path) || [],
445+
responseContentLengths: response?.map((r) => r.contents.length) || [],
446+
...context,
447+
},
448+
'callBenchify: Benchify runFixer API response received successfully',
449+
)
450+
451+
return response
452+
} catch (error) {
453+
logger.error(
454+
{
455+
error:
456+
error instanceof Error
457+
? {
458+
message: error.message,
459+
stack: error.stack,
460+
name: error.name,
461+
}
462+
: String(error),
463+
editedFilesCount: editedFiles.length,
464+
...context,
465+
},
466+
'callBenchify: Failed to call benchify API',
467+
)
468+
throw error
469+
}
363470
}
364471

365472
/**
@@ -376,7 +483,25 @@ async function applyBenchifyResults(
376483
userInputId: string
377484
},
378485
) {
486+
logger.info(
487+
{
488+
benchifyFilesCount: benchifyFiles.length,
489+
benchifyFilesList: benchifyFiles.map((f) => f.path),
490+
toolCallsCount: context.toolCalls.length,
491+
userInputId: context.userInputId,
492+
},
493+
'applyBenchifyResults: Starting to apply benchify results',
494+
)
495+
379496
for (const benchifyFile of benchifyFiles) {
497+
logger.debug(
498+
{
499+
fileName: benchifyFile.path,
500+
contentLength: benchifyFile.contents.length,
501+
userInputId: context.userInputId,
502+
},
503+
'applyBenchifyResults: Processing benchify file',
504+
)
380505
try {
381506
// Find the corresponding tool call for this file
382507
const relatedToolCall = context.toolCalls.find(
@@ -385,12 +510,27 @@ async function applyBenchifyResults(
385510

386511
if (!relatedToolCall) {
387512
logger.warn(
388-
{ fileName: benchifyFile.path },
389-
'No matching tool call found for benchify result',
513+
{
514+
fileName: benchifyFile.path,
515+
availableToolCallPaths: context.toolCalls.map(
516+
(tc) => tc.input.path,
517+
),
518+
userInputId: context.userInputId,
519+
},
520+
'applyBenchifyResults: No matching tool call found for benchify result',
390521
)
391522
continue
392523
}
393524

525+
logger.debug(
526+
{
527+
fileName: benchifyFile.path,
528+
relatedToolCallId: relatedToolCall.toolCallId,
529+
userInputId: context.userInputId,
530+
},
531+
'applyBenchifyResults: Found matching tool call for benchify result',
532+
)
533+
394534
// Get the original file content from our stored contents
395535
const originalContent =
396536
context.state.originalContents?.[benchifyFile.path]

backend/src/tools/stream-parser.ts

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,18 @@ export async function processStreamWithTools(options: {
129129

130130
batchState.deferredStrReplaces.push({ toolCall })
131131

132+
logger.debug(
133+
{
134+
toolCallId,
135+
filePath: input.path,
136+
replacementsCount: input.replacements?.length || 0,
137+
currentDeferredCount: batchState.deferredStrReplaces.length,
138+
agentStepId,
139+
userInputId,
140+
},
141+
'stream-parser: Deferring str_replace tool for batch execution',
142+
)
143+
132144
// Still emit the tool call event
133145
onResponseChunk({
134146
type: 'tool_call',
@@ -291,16 +303,27 @@ export async function processStreamWithTools(options: {
291303
{
292304
triggeringEvent: 'stream_end',
293305
deferredCount: batchState.deferredStrReplaces.length,
306+
deferredFiles: batchState.deferredStrReplaces.map(
307+
(d) => d.toolCall.input.path,
308+
),
294309
agentStepId,
295310
userInputId,
296311
},
297-
`toolCallback: Triggering batch str_replace execution (${batchState.deferredStrReplaces.length} deferred tools) due to stream end`,
312+
`stream-parser: Triggering batch str_replace execution (${batchState.deferredStrReplaces.length} deferred tools) due to stream end`,
298313
)
299314

300315
batchState.strReplacePhaseComplete = true
301316

302317
// Execute all deferred str_replace tools as a batch
303318
previousToolCallFinished = previousToolCallFinished.then(async () => {
319+
logger.info(
320+
{
321+
agentStepId,
322+
userInputId,
323+
deferredCount: batchState.deferredStrReplaces.length,
324+
},
325+
'stream-parser: About to call executeBatchStrReplaces from stream end handler',
326+
)
304327
await executeBatchStrReplaces({
305328
deferredStrReplaces: batchState.deferredStrReplaces,
306329
toolCalls,
@@ -316,6 +339,13 @@ export async function processStreamWithTools(options: {
316339
state,
317340
userId,
318341
})
342+
logger.info(
343+
{
344+
agentStepId,
345+
userInputId,
346+
},
347+
'stream-parser: Completed executeBatchStrReplaces from stream end handler',
348+
)
319349
})
320350
}
321351

0 commit comments

Comments
 (0)