MCPcopy
hub / github.com/RedPlanetHQ/core / executeCommand

Function executeCommand

packages/cli/src/server/tools/exec-tools.ts:321–409  ·  view source on GitHub ↗

* Execute a command and return output, capping captured stdout/stderr so we * never accumulate arbitrary amounts of data in memory. If a stream blows * past `KILL_MULTIPLIER × cap` while we're already discarding bytes, we kill * the process — at that point we're throwing the data away anyway and

(
	command: string,
	dir: string,
	timeout: number,
	maxStdoutBytes: number,
	maxStderrBytes: number,
)

Source from the content-addressed store, hash-verified

319 * producer is just keeping the pipe pressurized.
320 */
321async function executeCommand(
322 command: string,
323 dir: string,
324 timeout: number,
325 maxStdoutBytes: number,
326 maxStderrBytes: number,
327): Promise<ExecuteResult> {
328 return new Promise((resolve) => {
329 const proc = spawn(command, {
330 cwd: dir,
331 shell: true,
332 stdio: ['pipe', 'pipe', 'pipe'],
333 });
334
335 const stdoutCap = new StreamCapture(maxStdoutBytes);
336 const stderrCap = new StreamCapture(maxStderrBytes);
337 let killed = false;
338 let killedForOversize = false;
339 const stdoutKillAt = maxStdoutBytes * KILL_MULTIPLIER;
340 const stderrKillAt = maxStderrBytes * KILL_MULTIPLIER;
341
342 // Set timeout
343 const timer = setTimeout(() => {
344 killed = true;
345 proc.kill('SIGTERM');
346 }, timeout);
347
348 proc.stdout?.on('data', (data: Buffer) => {
349 stdoutCap.push(data);
350 if (!killed && stdoutCap.totalBytes > stdoutKillAt) {
351 killed = true;
352 killedForOversize = true;
353 proc.kill('SIGTERM');
354 }
355 });
356
357 proc.stderr?.on('data', (data: Buffer) => {
358 stderrCap.push(data);
359 if (!killed && stderrCap.totalBytes > stderrKillAt) {
360 killed = true;
361 killedForOversize = true;
362 proc.kill('SIGTERM');
363 }
364 });
365
366 const finish = (code: number, errMessage?: string) => {
367 clearTimeout(timer);
368 const stdoutFinal = stdoutCap.finalize('stdout');
369 const stderrFinal = stderrCap.finalize('stderr');
370 let stderr = stderrFinal.content;
371 if (errMessage) {
372 stderr = stderr ? `${stderr}\n${errMessage}` : errMessage;
373 }
374 if (killedForOversize) {
375 const note =
376 `\nCommand was terminated because its output exceeded ` +
377 `${formatBytes(stdoutKillAt)} (stdout) / ${formatBytes(stderrKillAt)} (stderr). ` +
378 `Re-run with a narrower selection (head/tail/grep/sed).`;

Callers 1

handleExecCommandFunction · 0.85

Calls 4

pushMethod · 0.95
finishFunction · 0.85
killMethod · 0.80
onMethod · 0.80

Tested by

no test coverage detected