Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 1 addition & 100 deletions src/handlers/edit-search-handlers.ts
Original file line number Diff line number Diff line change
@@ -1,112 +1,13 @@
import {
searchTextInFiles
} from '../tools/search.js';

import {
SearchCodeArgsSchema,
EditBlockArgsSchema
} from '../tools/schemas.js';

import { handleEditBlock } from '../tools/edit.js';

import { ServerResult } from '../types.js';
import { capture } from '../utils/capture.js';
import { withTimeout } from '../utils/withTimeout.js';

/**
* Handle edit_block command
* Uses the enhanced implementation with multiple occurrence support and fuzzy matching
*/
export { handleEditBlock };

/**
* Handle search_code command
*/
export async function handleSearchCode(args: unknown): Promise<ServerResult> {
const parsed = SearchCodeArgsSchema.parse(args);
const timeoutMs = parsed.timeoutMs || 30000; // 30 seconds default

// Limit maxResults to prevent overwhelming responses
const safeMaxResults = parsed.maxResults ? Math.min(parsed.maxResults, 5000) : 2000; // Default to 2000 instead of 1000

// Apply timeout at the handler level
const searchOperation = async () => {
return await searchTextInFiles({
rootPath: parsed.path,
pattern: parsed.pattern,
filePattern: parsed.filePattern,
ignoreCase: parsed.ignoreCase,
maxResults: safeMaxResults,
includeHidden: parsed.includeHidden,
contextLines: parsed.contextLines,
// Don't pass timeoutMs down to the implementation
});
};

// Use withTimeout at the handler level
const results = await withTimeout(
searchOperation(),
timeoutMs,
'Code search operation',
[] // Empty array as default on timeout
);

// If timeout occurred, try to terminate the ripgrep process
if (results.length === 0 && (globalThis as any).currentSearchProcess) {
try {
console.log(`Terminating timed out search process (PID: ${(globalThis as any).currentSearchProcess.pid})`);
(globalThis as any).currentSearchProcess.kill();
delete (globalThis as any).currentSearchProcess;
} catch (error) {
capture('server_request_error', {
error: 'Error terminating search process'
});
}
}

if (results.length === 0) {
if (timeoutMs > 0) {
return {
content: [{type: "text", text: `No matches found or search timed out after ${timeoutMs}ms.`}],
};
}
return {
content: [{type: "text", text: "No matches found"}],
};
}

// Format the results in a VS Code-like format with early truncation
let currentFile = "";
let formattedResults = "";
const MAX_RESPONSE_SIZE = 900000; // 900KB limit - well below the 1MB API limit
let resultsProcessed = 0;
let totalResults = results.length;

for (const result of results) {
// Check if adding this result would exceed our limit
const newFileHeader = result.file !== currentFile ? `\n${result.file}:\n` : '';
const newLine = ` ${result.line}: ${result.match}\n`;
const potentialAddition = newFileHeader + newLine;

// If adding this would exceed the limit, truncate here
if (formattedResults.length + potentialAddition.length > MAX_RESPONSE_SIZE) {
const remainingResults = totalResults - resultsProcessed;
const avgResultLength = formattedResults.length / Math.max(resultsProcessed, 1);
const estimatedRemainingChars = remainingResults * avgResultLength;
const truncationMessage = `\n\n[Results truncated - ${remainingResults} more results available (approximately ${Math.round(estimatedRemainingChars).toLocaleString()} more characters). Try refining your search pattern or using a more specific file pattern to get fewer results.]`;
formattedResults += truncationMessage;
break;
}

if (result.file !== currentFile) {
formattedResults += newFileHeader;
currentFile = result.file;
}
formattedResults += newLine;
resultsProcessed++;
}

return {
content: [{type: "text", text: formattedResults.trim()}],
};
}
export { handleEditBlock };
44 changes: 0 additions & 44 deletions src/handlers/filesystem-handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {
createDirectory,
listDirectory,
moveFile,
searchFiles,
getFileInfo,
type FileResult,
type MultiFileResult
Expand All @@ -23,7 +22,6 @@ import {
CreateDirectoryArgsSchema,
ListDirectoryArgsSchema,
MoveFileArgsSchema,
SearchFilesArgsSchema,
GetFileInfoArgsSchema
} from '../tools/schemas.js';

Expand Down Expand Up @@ -238,48 +236,6 @@ export async function handleMoveFile(args: unknown): Promise<ServerResult> {
}
}

/**
* Handle search_files command
*/
export async function handleSearchFiles(args: unknown): Promise<ServerResult> {
try {
const parsed = SearchFilesArgsSchema.parse(args);
const timeoutMs = parsed.timeoutMs || 30000; // 30 seconds default

// Apply timeout at the handler level
const searchOperation = async () => {
return await searchFiles(parsed.path, parsed.pattern);
};

// Use withTimeout at the handler level
const results = await withTimeout(
searchOperation(),
timeoutMs,
'File search operation',
[] // Empty array as default on timeout
);

if (results.length === 0) {
// Similar approach as in handleSearchCode
if (timeoutMs > 0) {
return {
content: [{ type: "text", text: `No matches found or search timed out after ${timeoutMs}ms.` }],
};
}
return {
content: [{ type: "text", text: "No matches found" }],
};
}

return {
content: [{ type: "text", text: results.join('\n') }],
};
} catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
return createErrorResponse(errorMessage);
}
}

/**
* Handle get_file_info command
*/
Expand Down
1 change: 1 addition & 0 deletions src/handlers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ export * from './filesystem-handlers.js';
export * from './terminal-handlers.js';
export * from './process-handlers.js';
export * from './edit-search-handlers.js';
export * from './search-handlers.js';
Loading