mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-20 10:10:56 -07:00
feat(core,cli): implement session-linked tool output storage and cleanup (#18416)
This commit is contained in:
@@ -1121,7 +1121,7 @@ describe('fileUtils', () => {
|
||||
|
||||
const expectedOutputFile = path.join(
|
||||
tempRootDir,
|
||||
'tool_output',
|
||||
'tool-outputs',
|
||||
'shell_123.txt',
|
||||
);
|
||||
expect(result.outputFile).toBe(expectedOutputFile);
|
||||
@@ -1149,7 +1149,7 @@ describe('fileUtils', () => {
|
||||
// ../../dangerous/tool -> ______dangerous_tool
|
||||
const expectedOutputFile = path.join(
|
||||
tempRootDir,
|
||||
'tool_output',
|
||||
'tool-outputs',
|
||||
'______dangerous_tool_1.txt',
|
||||
);
|
||||
expect(result.outputFile).toBe(expectedOutputFile);
|
||||
@@ -1170,12 +1170,36 @@ describe('fileUtils', () => {
|
||||
// ../../etc/passwd -> ______etc_passwd
|
||||
const expectedOutputFile = path.join(
|
||||
tempRootDir,
|
||||
'tool_output',
|
||||
'tool-outputs',
|
||||
'shell_______etc_passwd.txt',
|
||||
);
|
||||
expect(result.outputFile).toBe(expectedOutputFile);
|
||||
});
|
||||
|
||||
it('should sanitize sessionId in filename/path', async () => {
|
||||
const content = 'content';
|
||||
const toolName = 'shell';
|
||||
const id = '1';
|
||||
const sessionId = '../../etc/passwd';
|
||||
|
||||
const result = await saveTruncatedToolOutput(
|
||||
content,
|
||||
toolName,
|
||||
id,
|
||||
tempRootDir,
|
||||
sessionId,
|
||||
);
|
||||
|
||||
// ../../etc/passwd -> ______etc_passwd
|
||||
const expectedOutputFile = path.join(
|
||||
tempRootDir,
|
||||
'tool-outputs',
|
||||
'session-______etc_passwd',
|
||||
'shell_1.txt',
|
||||
);
|
||||
expect(result.outputFile).toBe(expectedOutputFile);
|
||||
});
|
||||
|
||||
it('should format multi-line output correctly', () => {
|
||||
const lines = Array.from({ length: 50 }, (_, i) => `line ${i}`);
|
||||
const content = lines.join('\n');
|
||||
|
||||
@@ -623,18 +623,24 @@ ${processedLines.join('\n')}`;
|
||||
/**
|
||||
* Saves tool output to a temporary file for later retrieval.
|
||||
*/
|
||||
export const TOOL_OUTPUT_DIR = 'tool_output';
|
||||
export const TOOL_OUTPUTS_DIR = 'tool-outputs';
|
||||
|
||||
export async function saveTruncatedToolOutput(
|
||||
content: string,
|
||||
toolName: string,
|
||||
id: string | number, // Accept string (callId) or number (truncationId)
|
||||
projectTempDir: string,
|
||||
sessionId?: string,
|
||||
): Promise<{ outputFile: string; totalLines: number }> {
|
||||
const safeToolName = sanitizeFilenamePart(toolName).toLowerCase();
|
||||
const safeId = sanitizeFilenamePart(id.toString()).toLowerCase();
|
||||
const fileName = `${safeToolName}_${safeId}.txt`;
|
||||
const toolOutputDir = path.join(projectTempDir, TOOL_OUTPUT_DIR);
|
||||
|
||||
let toolOutputDir = path.join(projectTempDir, TOOL_OUTPUTS_DIR);
|
||||
if (sessionId) {
|
||||
const safeSessionId = sanitizeFilenamePart(sessionId);
|
||||
toolOutputDir = path.join(toolOutputDir, `session-${safeSessionId}`);
|
||||
}
|
||||
const outputFile = path.join(toolOutputDir, fileName);
|
||||
|
||||
await fsPromises.mkdir(toolOutputDir, { recursive: true });
|
||||
|
||||
Reference in New Issue
Block a user