import { v4 as uuidv4 } from 'uuid';
import { sessionManager } from '../ssh/session.js';
import { createShellChannel } from '../ssh/exec.js';
import type {
ShellStartParams,
ShellSendParams,
ShellReadParams,
ShellCloseParams,
ToolResponse,
ShellSession,
} from '../types.js';
export async function sshShellStart(params: ShellStartParams): Promise<ToolResponse> {
try {
const client = sessionManager.getClient(params.sessionId);
if (!client) {
return {
success: false,
error: `Session not found or disconnected: ${params.sessionId}`,
};
}
const channel = await createShellChannel(client, params.cols || 80, params.rows || 24);
const shellSession: ShellSession = {
id: uuidv4(),
channel,
outputBuffer: '',
active: true,
};
// Set up data handler to buffer output
channel.on('data', (data: Buffer) => {
shellSession.outputBuffer += data.toString();
});
channel.stderr.on('data', (data: Buffer) => {
shellSession.outputBuffer += data.toString();
});
channel.on('close', () => {
shellSession.active = false;
});
channel.on('error', () => {
shellSession.active = false;
});
sessionManager.addShell(params.sessionId, shellSession);
return {
success: true,
data: {
sessionId: params.sessionId,
shellId: shellSession.id,
message: 'Interactive shell started',
},
};
} catch (err) {
return {
success: false,
error: err instanceof Error ? err.message : String(err),
};
}
}
export async function sshShellSend(params: ShellSendParams): Promise<ToolResponse> {
try {
const shell = sessionManager.getShell(params.sessionId, params.shellId);
if (!shell) {
return {
success: false,
error: `Shell not found: ${params.shellId}`,
};
}
if (!shell.active) {
return {
success: false,
error: 'Shell is no longer active',
};
}
// Send input to shell
shell.channel.write(params.input);
return {
success: true,
data: {
sessionId: params.sessionId,
shellId: params.shellId,
message: 'Input sent to shell',
},
};
} catch (err) {
return {
success: false,
error: err instanceof Error ? err.message : String(err),
};
}
}
export async function sshShellRead(params: ShellReadParams): Promise<ToolResponse> {
try {
const shell = sessionManager.getShell(params.sessionId, params.shellId);
if (!shell) {
return {
success: false,
error: `Shell not found: ${params.shellId}`,
};
}
const output = shell.outputBuffer;
// Clear buffer if requested (default behavior)
if (params.clear !== false) {
shell.outputBuffer = '';
}
return {
success: true,
data: {
sessionId: params.sessionId,
shellId: params.shellId,
output,
active: shell.active,
},
};
} catch (err) {
return {
success: false,
error: err instanceof Error ? err.message : String(err),
};
}
}
export async function sshShellClose(params: ShellCloseParams): Promise<ToolResponse> {
try {
const success = sessionManager.removeShell(params.sessionId, params.shellId);
if (!success) {
return {
success: false,
error: `Shell not found: ${params.shellId}`,
};
}
return {
success: true,
data: {
sessionId: params.sessionId,
shellId: params.shellId,
message: 'Shell closed successfully',
},
};
} catch (err) {
return {
success: false,
error: err instanceof Error ? err.message : String(err),
};
}
}