@wonderwhy-er/desktop-commander
Version:
MCP server for terminal operations and file editing
256 lines (255 loc) • 8.07 kB
JavaScript
import { REPLSessionManager } from '../REPLSessionManager.js';
let replManager = null;
/**
* Initialize the REPL manager with a terminal manager instance
* @param terminalManager - The terminal manager instance
*/
export function initializeREPLManager(terminalManager) {
if (!replManager) {
replManager = new REPLSessionManager(terminalManager);
}
}
/**
* Command handler for REPL-related operations
*/
export const replCommandHandler = {
/**
* Create a new REPL session
* @param params - Command parameters
* @returns Result object with session PID
*/
createREPLSession: async (params) => {
try {
if (!replManager) {
return {
success: false,
error: "REPL Manager not initialized"
};
}
const language = params.language;
if (!language) {
return {
success: false,
error: "Language parameter is required"
};
}
const pid = await replManager.createSession(language, params.options || {});
return {
success: true,
pid,
message: `${language} REPL session started with PID ${pid}`
};
}
catch (error) {
return {
success: false,
error: error.message || "Failed to create REPL session"
};
}
},
/**
* Execute code in an existing REPL session
* @param params - Command parameters
* @returns Result with execution output
*/
executeREPLCode: async (params) => {
try {
if (!replManager) {
return {
success: false,
error: "REPL Manager not initialized"
};
}
const { pid, code } = params;
if (!pid || !code) {
return {
success: false,
error: "Both pid and code parameters are required"
};
}
const result = await replManager.executeCode(typeof pid === 'string' ? parseInt(pid) : pid, code, params.options || {});
return {
success: true,
...result
};
}
catch (error) {
return {
success: false,
error: error.message || "Failed to execute code in REPL session"
};
}
},
/**
* Create a new SSH session
* @param params - Command parameters
* @returns Result object with session PID
*/
createSSHSession: async (params) => {
try {
if (!replManager) {
return {
success: false,
error: "REPL Manager not initialized"
};
}
const { host, username, port, identity, password } = params;
if (!host) {
return {
success: false,
error: "Host parameter is required"
};
}
const options = {
username,
port,
identity,
password,
...(params.options || {})
};
const pid = await replManager.createSSHSession(host, options);
return {
success: true,
pid,
message: `SSH session to ${host} started with PID ${pid}`
};
}
catch (error) {
return {
success: false,
error: error.message || "Failed to create SSH session"
};
}
},
/**
* Execute a command in an SSH session
* @param params - Command parameters
* @returns Result with execution output
*/
executeSSHCommand: async (params) => {
try {
if (!replManager) {
return {
success: false,
error: "REPL Manager not initialized"
};
}
const { pid, command } = params;
if (!pid || !command) {
return {
success: false,
error: "Both pid and command parameters are required"
};
}
// For SSH, we use the same sendAndReadREPL method but specify 'ssh' as the language
const parsedPid = typeof pid === 'string' ? parseInt(pid) : pid;
const session = replManager.listSessions().find(s => s.pid === parsedPid);
if (!session || session.language !== 'ssh') {
return {
success: false,
error: "Invalid SSH session PID"
};
}
const result = await replManager.sendAndReadREPL(parsedPid, command, 'ssh', params.options?.timeout || 10000);
return {
success: true,
...result
};
}
catch (error) {
return {
success: false,
error: error.message || "Failed to execute command in SSH session"
};
}
},
/**
* List all active REPL sessions
* @returns List of active sessions
*/
listREPLSessions: () => {
try {
if (!replManager) {
return {
success: false,
error: "REPL Manager not initialized"
};
}
const sessions = replManager.listSessions();
return {
success: true,
sessions
};
}
catch (error) {
return {
success: false,
error: error.message || "Failed to list REPL sessions"
};
}
},
/**
* Close a specific REPL session
* @param params - Command parameters
* @returns Result indicating success
*/
closeREPLSession: async (params) => {
try {
if (!replManager) {
return {
success: false,
error: "REPL Manager not initialized"
};
}
const { pid } = params;
if (!pid) {
return {
success: false,
error: "PID parameter is required"
};
}
const parsedPid = typeof pid === 'string' ? parseInt(pid) : pid;
const success = await replManager.closeSession(parsedPid);
return {
success,
message: success
? `REPL session with PID ${pid} closed successfully`
: `Failed to close REPL session with PID ${pid}`
};
}
catch (error) {
return {
success: false,
error: error.message || "Failed to close REPL session"
};
}
},
/**
* Close all idle REPL sessions
* @param params - Command parameters
* @returns Result with number of closed sessions
*/
closeIdleREPLSessions: async (params) => {
try {
if (!replManager) {
return {
success: false,
error: "REPL Manager not initialized"
};
}
const maxIdleMs = params?.maxIdleMs || 30 * 60 * 1000; // Default 30 minutes
const closedCount = await replManager.closeIdleSessions(maxIdleMs);
return {
success: true,
closedCount,
message: `Closed ${closedCount} idle REPL session(s)`
};
}
catch (error) {
return {
success: false,
error: error.message || "Failed to close idle REPL sessions"
};
}
}
};