@@ -120,22 +120,22 @@ final class EvoBootstrapper
120120 $ memoryLimit = ini_get ('memory_limit ' ) ?: 'Unknown ' ;
121121
122122 $ items = [
123- ['key ' => 'os ' , 'label ' => $ os , 'level ' => 'ok ' ],
124- ['key ' => 'php ' , 'label ' => "PHP - {$ phpVersion }" , 'level ' => $ phpOk ? 'ok ' : 'error ' ],
125- ['key ' => 'composer ' , 'label ' => "Composer " . ($ composerVersion ? " - {$ composerVersion }" : '' ), 'level ' => $ composerOk ? 'ok ' : 'warn ' ],
126- ['key ' => 'pdo ' , 'label ' => 'PDO extension ' , 'level ' => $ pdoOk ? 'ok ' : 'error ' ],
123+ ['key ' => 'os ' , 'label ' => $ os , 'level ' => 'ok ' ],
124+ ['key ' => 'php ' , 'label ' => "PHP - {$ phpVersion }" , 'level ' => $ phpOk ? 'ok ' : 'error ' ],
125+ ['key ' => 'composer ' , 'label ' => "Composer " . ($ composerVersion ? " - {$ composerVersion }" : '' ), 'level ' => $ composerOk ? 'ok ' : 'warn ' ],
126+ ['key ' => 'pdo ' , 'label ' => 'PDO extension ' , 'level ' => $ pdoOk ? 'ok ' : 'error ' ],
127127 // DB drivers: if unavailable, mark as warning (optional until user chooses a DB).
128- ['key ' => 'pdo_mysql ' , 'label ' => 'PDO MySQL driver ' , 'level ' => $ pdoMysqlOk ? 'ok ' : 'warn ' ],
129- ['key ' => 'pdo_pgsql ' , 'label ' => 'PDO PostgreSQL driver ' , 'level ' => $ pdoPgsqlOk ? 'ok ' : 'warn ' ],
130- ['key ' => 'pdo_sqlite ' , 'label ' => 'PDO SQLite driver ' , 'level ' => $ pdoSqliteOk ? 'ok ' : 'warn ' ],
131- ['key ' => 'pdo_sqlsrv ' , 'label ' => 'PDO SQL Server driver ' , 'level ' => $ pdoSqlsrvOk ? 'ok ' : 'warn ' ],
132- ['key ' => 'json ' , 'label ' => 'JSON extension ' , 'level ' => $ jsonOk ? 'ok ' : 'error ' ],
133- ['key ' => 'mysqli ' , 'label ' => 'MySQLi extension ' , 'level ' => $ mysqliOk ? 'ok ' : 'error ' ],
134- ['key ' => 'mbstring ' , 'label ' => 'MBString extension ' , 'level ' => $ mbstringOk ? 'ok ' : 'error ' ],
135- ['key ' => 'curl ' , 'label ' => 'cURL extension ' , 'level ' => $ curlOk ? 'ok ' : 'warn ' ],
136- ['key ' => 'image ' , 'label ' => $ imageLabel , 'level ' => $ imageOk ? 'ok ' : 'warn ' ],
137- ['key ' => 'disk_free ' , 'label ' => 'Disk free - ' . ($ diskFree ?: 'Unknown ' ), 'level ' => $ diskFree !== null ? 'ok ' : 'warn ' ],
138- ['key ' => 'memory_limit ' , 'label ' => 'Memory limit - ' . $ memoryLimit , 'level ' => 'ok ' ],
128+ ['key ' => 'pdo_mysql ' , 'label ' => 'PDO MySQL driver ' , 'level ' => $ pdoMysqlOk ? 'ok ' : 'warn ' ],
129+ ['key ' => 'pdo_pgsql ' , 'label ' => 'PDO PostgreSQL driver ' , 'level ' => $ pdoPgsqlOk ? 'ok ' : 'warn ' ],
130+ ['key ' => 'pdo_sqlite ' , 'label ' => 'PDO SQLite driver ' , 'level ' => $ pdoSqliteOk ? 'ok ' : 'warn ' ],
131+ ['key ' => 'pdo_sqlsrv ' , 'label ' => 'PDO SQL Server driver ' , 'level ' => $ pdoSqlsrvOk ? 'ok ' : 'warn ' ],
132+ ['key ' => 'json ' , 'label ' => 'JSON extension ' , 'level ' => $ jsonOk ? 'ok ' : 'error ' ],
133+ ['key ' => 'mysqli ' , 'label ' => 'MySQLi extension ' , 'level ' => $ mysqliOk ? 'ok ' : 'error ' ],
134+ ['key ' => 'mbstring ' , 'label ' => 'MBString extension ' , 'level ' => $ mbstringOk ? 'ok ' : 'error ' ],
135+ ['key ' => 'curl ' , 'label ' => 'cURL extension ' , 'level ' => $ curlOk ? 'ok ' : 'warn ' ],
136+ ['key ' => 'image ' , 'label ' => $ imageLabel , 'level ' => $ imageOk ? 'ok ' : 'warn ' ],
137+ ['key ' => 'disk_free ' , 'label ' => 'Disk free - ' . ($ diskFree ?: 'Unknown ' ), 'level ' => $ diskFree !== null ? 'ok ' : 'warn ' ],
138+ ['key ' => 'memory_limit ' , 'label ' => 'Memory limit - ' . $ memoryLimit , 'level ' => 'ok ' ],
139139 ];
140140
141141 $ overall = 'ok ' ;
@@ -150,9 +150,9 @@ final class EvoBootstrapper
150150 }
151151
152152 return [
153- 'status ' => $ overall ,
154- 'overall ' => $ overall ,
155- 'items ' => $ items ,
153+ 'status ' => $ overall ,
154+ 'overall ' => $ overall ,
155+ 'items ' => $ items ,
156156 ];
157157 }
158158
@@ -303,6 +303,32 @@ final class EvoBootstrapper
303303 */
304304 private function execBinary (array $ args ): int
305305 {
306+ // Use proc_open with inherited stdio to preserve the TTY. Running via
307+ // passthru/exec typically pipes stdout/stderr which breaks Bubble Tea's
308+ // terminal size detection and full-screen rendering.
309+ if (function_exists ('proc_open ' )) {
310+ $ disabled = (string )ini_get ('disable_functions ' );
311+ if ($ disabled === '' || stripos ($ disabled , 'proc_open ' ) === false ) {
312+ $ cmd = [$ this ->binaryPath , ...$ args ];
313+ $ descriptors = [
314+ 0 => STDIN ,
315+ 1 => STDOUT ,
316+ 2 => STDERR ,
317+ ];
318+ $ options = [];
319+ if (PHP_OS_FAMILY === 'Windows ' ) {
320+ $ options ['bypass_shell ' ] = true ;
321+ }
322+
323+ $ proc = @proc_open ($ cmd , $ descriptors , $ pipes , null , null , $ options );
324+ if (is_resource ($ proc )) {
325+ $ code = proc_close ($ proc );
326+ return (int )$ code ;
327+ }
328+ }
329+ }
330+
331+ // Fallback: execute via shell.
306332 $ cmdParts = [escapeshellarg ($ this ->binaryPath )];
307333 foreach ($ args as $ arg ) {
308334 $ cmdParts [] = escapeshellarg ($ arg );
@@ -601,7 +627,7 @@ final class EvoBootstrapper
601627 private function createHttpHeaders (bool $ isApi ): array
602628 {
603629 $ headers = [
604- 'User-Agent: evo-bootstrapper ' ,
630+ 'User-Agent: evo-bootstrapper ' ,
605631 ];
606632 if ($ isApi ) {
607633 $ headers [] = 'Accept: application/vnd.github+json ' ;
@@ -617,17 +643,17 @@ final class EvoBootstrapper
617643 private function createHttpContext (bool $ isApi ): mixed
618644 {
619645 return stream_context_create ([
620- 'http ' => [
621- 'method ' => 'GET ' ,
622- 'header ' => implode ("\r\n" , $ this ->createHttpHeaders ($ isApi )),
623- 'timeout ' => 60 ,
624- 'follow_location ' => 1 ,
625- 'max_redirects ' => 5 ,
626- ],
627- 'ssl ' => [
628- 'verify_peer ' => true ,
629- 'verify_peer_name ' => true ,
630- ],
646+ 'http ' => [
647+ 'method ' => 'GET ' ,
648+ 'header ' => implode ("\r\n" , $ this ->createHttpHeaders ($ isApi )),
649+ 'timeout ' => 60 ,
650+ 'follow_location ' => 1 ,
651+ 'max_redirects ' => 5 ,
652+ ],
653+ 'ssl ' => [
654+ 'verify_peer ' => true ,
655+ 'verify_peer_name ' => true ,
656+ ],
631657 ]);
632658 }
633659
0 commit comments