UNPKG

naisys

Version:

NAISYS - Autonomous AI agent runner with built-in context management and cost tracking

44 lines 1.93 kB
import { ptyCmd } from "../../command/commandDefs.js"; import { getPlatformConfig } from "../../services/runtime/shellPlatform.js"; /** * Wraps a command with `script -qfc` so the inner program sees a real PTY * on stdin/stdout. Lets the LLM drive `sudo`, `ssh`, `passwd`, and other * `isatty()`-gated prompts that the pipe-based shell wrapper can't handle. * * Calls shellWrapper directly (not shellCommand) so it can request the * inline-delimiter form — script inherits bash's stdin, so a delimiter on a * separate line would be eaten by script and reach the inner PTY as input. * * Output flow stays normal: when script exits the delimiter fires and the * existing wait/kill/input continuation handles any prompt cycle in between. */ export function createPtyService(shellWrapper) { const platformConfig = getPlatformConfig(); async function handleCommand(args) { const command = args.trim(); if (!command) { return `Usage: ${ptyCmd.name} ${ptyCmd.usage}\n${ptyCmd.description}`; } if (platformConfig.platform !== "linux") { return `${ptyCmd.name} is Linux-only — PowerShell has no equivalent of script(1).`; } if (shellWrapper.isShellSuspended()) { return `Cannot run ${ptyCmd.name} while another shell command is active. Use 'ns-wait', 'ns-kill', or send input to the running command first.`; } const wrapped = `script -qfc ${shellEscape(command)} /dev/null`; return await shellWrapper.executeCommand(wrapped, { inlineDelimiter: true, secure: true, }); } const registrableCommand = { command: ptyCmd, handleCommand, }; return registrableCommand; } /** Single-quote-wrap a string for safe inclusion as one shell argument. */ function shellEscape(s) { return `'${s.replace(/'/g, "'\\''")}'`; } //# sourceMappingURL=pty.js.map