UNPKG

naisys

Version:

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

133 lines 5.81 kB
/** * Platform abstraction layer for shell operations * Encapsulates platform-specific shell behavior for Windows (PowerShell) and Linux (bash) */ import { execSync } from "child_process"; import * as os from "os"; const nsCommandHandlerMessage = "is a NAISYS command and must be run on its own line, not combined with shell commands."; function getWindowsConfig() { return { platform: "windows", shellCommand: "powershell.exe", shellArgs: [ "-NoProfile", "-NoLogo", "-NonInteractive", "-ExecutionPolicy", "Bypass", ], echoDelimiter: (delimiter) => `Write-Host "${delimiter}"`, pwdCommand: "(Get-Location).Path", mkdirCommand: (path) => `New-Item -ItemType Directory -Force -Path "${path}" | Out-Null`, cdCommand: (path) => `Set-Location "${path}"`, scriptExtension: ".ps1", scriptHeader: "# PowerShell script", scriptSetError: "$ErrorActionPreference = 'Stop'", pathSeparator: ";", sourceScript: (scriptPath) => `. "${scriptPath}"`, exportEnvCommand: (key, value) => // Backtick-escape `$` and `"` so PS doesn't expand or terminate the literal `$env:${key} = "${value.replace(/`/g, "``").replace(/\$/g, "`$").replace(/"/g, '`"')}"`, // Empty CommandScriptBlock + StopSearch suppresses PS's native "not // recognized" block so the LLM only sees our single clean message. // Cost: $? stays True, so PS7 &&/|| chains continue past an ns-* line // rather than short-circuiting. Acceptable — LLMs read the message. nsCommandNotFoundHandler: `$ExecutionContext.InvokeCommand.CommandNotFoundAction = { param($n, $e) if ($n -like 'ns-*') { Write-Host "NAISYS: '$n' ${nsCommandHandlerMessage}"; $e.CommandScriptBlock = { }; $e.StopSearch = $true } }`, displayName: "WINDOWS", shellName: "PowerShell", commandNotFoundSuffix: "is not recognized", invalidCommandMessage: "Please enter a valid PowerShell or NAISYS command after the prompt. Use the 'ns-comment' command for thoughts.", promptSuffix: ">", promptDivider: " ", adminPromptSuffix: "#", }; } function getLinuxConfig() { return { platform: "linux", shellCommand: "bash", shellArgs: [], echoDelimiter: (delimiter) => `echo "${delimiter}"`, pwdCommand: "pwd", mkdirCommand: (path) => `mkdir -p "${path}"`, cdCommand: (path) => `cd "${path}"`, scriptExtension: ".sh", scriptHeader: "#!/bin/bash", scriptSetError: `__naisys_prev_errexit=0 case $- in *e*) __naisys_prev_errexit=1 ;; esac __naisys_prev_err_trap=$(trap -p ERR) __naisys_prev_return_trap=$(trap -p RETURN) trap '__naisys_rc=$? trap - ERR trap - RETURN if [ -n "$__naisys_prev_err_trap" ]; then eval "$__naisys_prev_err_trap"; fi if [ -n "$__naisys_prev_return_trap" ]; then eval "$__naisys_prev_return_trap"; fi if [ "$__naisys_prev_errexit" = "1" ]; then set -e; else set +e; fi unset __naisys_prev_errexit __naisys_prev_err_trap __naisys_prev_return_trap __naisys_rc' RETURN trap '__naisys_rc=$? set +e echo "[NAISYS: script halted at exit $__naisys_rc on: $BASH_COMMAND]" >&2 trap - ERR trap - RETURN if [ -n "$__naisys_prev_err_trap" ]; then eval "$__naisys_prev_err_trap"; fi if [ -n "$__naisys_prev_return_trap" ]; then eval "$__naisys_prev_return_trap"; fi if [ "$__naisys_prev_errexit" = "1" ]; then set -e; else set +e; fi eval "unset __naisys_prev_errexit __naisys_prev_err_trap __naisys_prev_return_trap __naisys_rc; return $__naisys_rc 2>/dev/null || exit $__naisys_rc"' ERR set -e`, pathSeparator: ":", sourceScript: (scriptPath) => `source "${scriptPath}"`, exportEnvCommand: (key, value) => // Single-quote the value so bash treats it literally; escape embedded // single quotes by closing → escaped quote → reopening. `export ${key}='${value.replace(/'/g, "'\\''")}'`, nsCommandNotFoundHandler: `command_not_found_handle() { case "$1" in ns-*) echo "NAISYS: '$1' ${nsCommandHandlerMessage}" >&2; return 127 ;; *) echo "bash: $1: command not found" >&2; return 127 ;; esac; }`, displayName: "LINUX", shellName: "bash", commandNotFoundSuffix: "command not found", invalidCommandMessage: "Please enter a valid Linux or NAISYS command after the prompt. Use the 'ns-comment' command for thoughts.", promptSuffix: "$", promptDivider: ":", adminPromptSuffix: "#", }; } /** Determine if we should use native Windows mode */ export function useNativeWindows() { // On Windows, use native PowerShell instead of WSL return os.platform() === "win32"; } /** Get the platform configuration for the current OS */ export function getPlatformConfig() { if (useNativeWindows()) { return getWindowsConfig(); } return getLinuxConfig(); } /** Get a specific platform configuration */ export function getPlatformConfigFor(platform) { if (platform === "windows") { return getWindowsConfig(); } return getLinuxConfig(); } /** Cached result of elevation check (doesn't change during process lifetime) */ let elevatedCache; /** Check if the process is running as root (Linux) or admin (Windows) */ export function isElevated() { if (elevatedCache !== undefined) { return elevatedCache; } if (os.platform() === "win32") { try { execSync("net session", { stdio: "ignore" }); elevatedCache = true; } catch { elevatedCache = false; } } else { elevatedCache = process.getuid?.() === 0; } return elevatedCache; } //# sourceMappingURL=shellPlatform.js.map