fix: preserve fullOutputFilePath when content is summarized and flush pending lines on exit

This commit is contained in:
Spencer
2026-04-09 15:30:53 +00:00
parent 1755678cf9
commit bcd0acae4f
2 changed files with 55 additions and 54 deletions

View File

@@ -222,6 +222,9 @@ export class ToolExecutor {
content: PartListUnion, content: PartListUnion,
fullOutputFilePath?: string, fullOutputFilePath?: string,
): Promise<{ truncatedContent: PartListUnion; outputFile?: string }> { ): Promise<{ truncatedContent: PartListUnion; outputFile?: string }> {
const toolName = call.request.name;
const callId = call.request.callId;
if (this.config.isContextManagementEnabled()) { if (this.config.isContextManagementEnabled()) {
const distiller = new ToolOutputDistillationService( const distiller = new ToolOutputDistillationService(
this.config, this.config,
@@ -233,40 +236,54 @@ export class ToolExecutor {
call.request.callId, call.request.callId,
content, content,
); );
if (fullOutputFilePath && !result.outputFile) {
try { let finalOutputFile = result.outputFile;
await fsPromises.unlink(fullOutputFilePath); if (fullOutputFilePath) {
} catch (error) { const { outputFile: movedPath } = await moveToolOutputToFile(
debugLogger.warn( fullOutputFilePath,
`Failed to delete temporary tool output file: ${fullOutputFilePath}`, toolName,
error, callId,
); this.config.storage.getProjectTempDir(),
this.config.getSessionId(),
);
finalOutputFile = movedPath;
if (result.outputFile) {
try {
await fsPromises.unlink(result.outputFile);
} catch (error) {
debugLogger.warn(
`Failed to delete distiller's temporary tool output file: ${result.outputFile}`,
error,
);
}
} }
} }
return result; return {
truncatedContent: result.truncatedContent,
outputFile: finalOutputFile,
};
} }
const toolName = call.request.name;
const callId = call.request.callId;
let outputFile: string | undefined; let outputFile: string | undefined;
if (fullOutputFilePath) {
const { outputFile: movedPath } = await moveToolOutputToFile(
fullOutputFilePath,
toolName,
callId,
this.config.storage.getProjectTempDir(),
this.config.getSessionId(),
);
outputFile = movedPath;
}
if (typeof content === 'string' && toolName === SHELL_TOOL_NAME) { if (typeof content === 'string' && toolName === SHELL_TOOL_NAME) {
const threshold = this.config.getTruncateToolOutputThreshold(); const threshold = this.config.getTruncateToolOutputThreshold();
if (threshold > 0 && content.length > threshold) { if (threshold > 0 && content.length > threshold) {
const originalContentLength = content.length; const originalContentLength = content.length;
let savedPath: string; if (!outputFile) {
if (fullOutputFilePath) {
const { outputFile: movedPath } = await moveToolOutputToFile(
fullOutputFilePath,
toolName,
callId,
this.config.storage.getProjectTempDir(),
this.config.getSessionId(),
);
savedPath = movedPath;
} else {
const { outputFile: writtenPath } = await saveTruncatedToolOutput( const { outputFile: writtenPath } = await saveTruncatedToolOutput(
content, content,
toolName, toolName,
@@ -274,10 +291,9 @@ export class ToolExecutor {
this.config.storage.getProjectTempDir(), this.config.storage.getProjectTempDir(),
this.context.promptId, this.context.promptId,
); );
savedPath = writtenPath; outputFile = writtenPath;
} }
outputFile = savedPath;
const truncatedContent = formatTruncatedToolOutput( const truncatedContent = formatTruncatedToolOutput(
content, content,
outputFile, outputFile,
@@ -309,14 +325,16 @@ export class ToolExecutor {
if (threshold > 0 && textContent.length > threshold) { if (threshold > 0 && textContent.length > threshold) {
const originalContentLength = textContent.length; const originalContentLength = textContent.length;
const { outputFile: savedPath } = await saveTruncatedToolOutput( if (!outputFile) {
textContent, const { outputFile: savedPath } = await saveTruncatedToolOutput(
toolName, textContent,
callId, toolName,
this.config.storage.getProjectTempDir(), callId,
this.context.promptId, this.config.storage.getProjectTempDir(),
); this.context.promptId,
outputFile = savedPath; );
outputFile = savedPath;
}
const truncatedText = formatTruncatedToolOutput( const truncatedText = formatTruncatedToolOutput(
textContent, textContent,
outputFile, outputFile,
@@ -339,33 +357,11 @@ export class ToolExecutor {
}), }),
); );
if (fullOutputFilePath) {
try {
await fsPromises.unlink(fullOutputFilePath);
} catch (error) {
debugLogger.warn(
`Failed to delete temporary tool output file: ${fullOutputFilePath}`,
error,
);
}
}
return { truncatedContent, outputFile }; return { truncatedContent, outputFile };
} }
} }
} }
if (fullOutputFilePath && !outputFile) {
try {
await fsPromises.unlink(fullOutputFilePath);
} catch (error) {
debugLogger.warn(
`Failed to delete temporary tool output file: ${fullOutputFilePath}`,
error,
);
}
}
return { truncatedContent: content, outputFile }; return { truncatedContent: content, outputFile };
} }

View File

@@ -1379,6 +1379,11 @@ export class ShellExecutionService {
render(true); render(true);
cmdCleanup?.(); cmdCleanup?.();
const activePty = ShellExecutionService.activePtys.get(ptyPid);
if (activePty) {
emitPendingLines(activePty, ptyPid, onOutputEvent, true);
}
const event: ShellOutputEvent = { const event: ShellOutputEvent = {
type: 'exit', type: 'exit',
exitCode, exitCode,