@wonderwhy-er/desktop-commander
Version:
MCP server for terminal operations and file editing
137 lines (136 loc) • 4.97 kB
JavaScript
import { searchManager } from '../search-manager.js';
import { StartSearchArgsSchema, GetMoreSearchResultsArgsSchema, StopSearchArgsSchema } from '../tools/schemas.js';
import { capture } from '../utils/capture.js';
import { startSearchAnswer, searchResultsAnswer } from './search-answers.js';
/**
* Handle start_search command
*/
export async function handleStartSearch(args) {
const parsed = StartSearchArgsSchema.safeParse(args);
if (!parsed.success) {
return {
content: [{ type: "text", text: `Invalid arguments for start_search: ${parsed.error}` }],
isError: true,
};
}
try {
const result = await searchManager.startSearch({
rootPath: parsed.data.path,
pattern: parsed.data.pattern,
searchType: parsed.data.searchType,
filePattern: parsed.data.filePattern,
ignoreCase: parsed.data.ignoreCase,
maxResults: parsed.data.maxResults,
includeHidden: parsed.data.includeHidden,
contextLines: parsed.data.contextLines,
timeout: parsed.data.timeout_ms,
earlyTermination: parsed.data.earlyTermination,
literalSearch: parsed.data.literalSearch,
});
return startSearchAnswer(result, parsed.data);
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
capture('search_session_start_error', { error: errorMessage });
return {
content: [{ type: "text", text: `Error starting search session: ${errorMessage}` }],
isError: true,
};
}
}
/**
* Handle get_more_search_results command
*/
export async function handleGetMoreSearchResults(args) {
const parsed = GetMoreSearchResultsArgsSchema.safeParse(args);
if (!parsed.success) {
return {
content: [{ type: "text", text: `Invalid arguments for get_more_search_results: ${parsed.error}` }],
isError: true,
};
}
try {
const page = searchManager.readSearchResults(parsed.data.sessionId, parsed.data.offset, parsed.data.length);
return searchResultsAnswer(page, parsed.data.offset);
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
return {
content: [{ type: "text", text: `Error reading search results: ${errorMessage}` }],
isError: true,
};
}
}
/**
* Handle stop_search command
*/
export async function handleStopSearch(args) {
const parsed = StopSearchArgsSchema.safeParse(args);
if (!parsed.success) {
return {
content: [{ type: "text", text: `Invalid arguments for stop_search: ${parsed.error}` }],
isError: true,
};
}
try {
const success = searchManager.terminateSearch(parsed.data.sessionId);
if (success) {
return {
content: [{
type: "text",
text: `Search session ${parsed.data.sessionId} terminated successfully.`
}],
};
}
else {
return {
content: [{
type: "text",
text: `Search session ${parsed.data.sessionId} not found or already completed.`
}],
};
}
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
return {
content: [{ type: "text", text: `Error terminating search session: ${errorMessage}` }],
isError: true,
};
}
}
/**
* Handle list_searches command
*/
export async function handleListSearches() {
try {
const sessions = searchManager.listSearchSessions();
if (sessions.length === 0) {
return {
content: [{ type: "text", text: "No active searches." }],
};
}
let output = `Active Searches (${sessions.length}):\n\n`;
for (const session of sessions) {
const status = session.isComplete
? (session.isError ? '❌ ERROR' : '✅ COMPLETED')
: '🔄 RUNNING';
output += `Session: ${session.id}\n`;
output += ` Type: ${session.searchType}\n`;
output += ` Pattern: "${session.pattern}"\n`;
output += ` Status: ${status}\n`;
output += ` Runtime: ${Math.round(session.runtime / 1000)}s\n`;
output += ` Results: ${session.totalResults}\n\n`;
}
return {
content: [{ type: "text", text: output }],
};
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
return {
content: [{ type: "text", text: `Error listing search sessions: ${errorMessage}` }],
isError: true,
};
}
}