UNPKG

@wonderwhy-er/desktop-commander

Version:

MCP server for terminal operations and file editing

137 lines (136 loc) • 4.97 kB
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, }; } }