$language, 'code' => $code, 'network_mode' => $opts['networkMode'] ?? 'zerotrust', 'ttl' => $opts['ttl'] ?? 60 ]; return self::apiRequest('POST', '/execute', $body, $opts); } public static function executeAsync($language, $code, $opts = []) { $body = [ 'language' => $language, 'code' => $code, 'network_mode' => $opts['networkMode'] ?? 'zerotrust', 'ttl' => $opts['ttl'] ?? 300 ]; return self::apiRequest('POST', '/execute/async', $body, $opts); } public static function run($file, $opts = []) { $code = file_get_contents($file); return self::execute(self::detectLanguage($file), $code, $opts); } public static function getJob($jobId, $opts = []) { return self::apiRequest('GET', "/jobs/$jobId", null, $opts); } public static function wait($jobId, $timeout = 3600, $opts = []) { $delays = [300, 450, 700, 900, 650, 1600, 2000]; $start = time(); for ($i = 0; $i < 120; $i++) { $job = self::getJob($jobId, $opts); if ($job['status'] === 'completed') return $job; if ($job['status'] === 'failed') throw new Exception("Job failed"); if ($job['status'] === 'timeout') throw new Exception("Job timeout"); if (time() - $start > $timeout) throw new Exception("Polling timeout"); $delay = $delays[$i] ?? 2000; usleep($delay * 1000); } throw new Exception("Max polls exceeded"); } public static function cancelJob($jobId, $opts = []) { return self::apiRequest('DELETE', "/jobs/$jobId", null, $opts); } public static function detectLanguage($filename) { $ext = pathinfo($filename, PATHINFO_EXTENSION); $map = ['py' => 'python', 'rb' => 'ruby', 'js' => 'javascript', 'php' => 'php', 'lua' => 'lua', 'sh' => 'bash', 'go' => 'go', 'pl' => 'perl']; return $map[$ext] ?? throw new Exception("Unknown file type"); } public static function image($code, $format = 'png', $opts = []) { return self::apiRequest('POST', '/image', ['code' => $code, 'format' => $format], $opts); } } // CLI if (php_sapi_name() === 'cli' && !empty($GLOBALS['argv'])) { array_shift($GLOBALS['argv']); if (empty($GLOBALS['argv'])) { echo "Usage: php un.php \n"; exit(1); } try { $result = Un::run($GLOBALS['argv'][0]); if (!empty($result['stdout'])) echo $result['stdout']; if (!empty($result['stderr'])) fwrite(STDERR, $result['stderr']); exit($result['exit_code'] ?? 0); } catch (Exception $e) { fwrite(STDERR, "Error: " . $e->getMessage() . "\n"); exit(1); } } ?>