@@ -13,6 +13,40 @@ const tar = require('tar')
1313
1414const packageName = 'codebuff'
1515
16+ /**
17+ * Terminal escape sequences to reset terminal state after the child process exits.
18+ * When the binary is SIGKILL'd, it can't clean up its own terminal state.
19+ * The wrapper (this process) survives and must reset these modes.
20+ *
21+ * Keep in sync with TERMINAL_RESET_SEQUENCES in cli/src/utils/renderer-cleanup.ts
22+ */
23+ const TERMINAL_RESET_SEQUENCES =
24+ '\x1b[?1049l' + // Exit alternate screen buffer
25+ '\x1b[?1000l' + // Disable X10 mouse mode
26+ '\x1b[?1002l' + // Disable button event mouse mode
27+ '\x1b[?1003l' + // Disable any-event mouse mode (all motion)
28+ '\x1b[?1006l' + // Disable SGR extended mouse mode
29+ '\x1b[?1004l' + // Disable focus reporting
30+ '\x1b[?2004l' + // Disable bracketed paste mode
31+ '\x1b[?25h' // Show cursor
32+
33+ function resetTerminal ( ) {
34+ try {
35+ if ( process . stdin . isTTY && process . stdin . setRawMode ) {
36+ process . stdin . setRawMode ( false )
37+ }
38+ } catch {
39+ // stdin may be closed
40+ }
41+ try {
42+ if ( process . stdout . isTTY ) {
43+ process . stdout . write ( TERMINAL_RESET_SEQUENCES )
44+ }
45+ } catch {
46+ // stdout may be closed
47+ }
48+ }
49+
1650function createConfig ( packageName ) {
1751 const homeDir = os . homedir ( )
1852 const configDir = path . join ( homeDir , '.config' , 'manicode' )
@@ -526,18 +560,24 @@ async function checkForUpdates(runningProcess, exitListener) {
526560 term . clearLine ( )
527561
528562 runningProcess . removeListener ( 'exit' , exitListener )
529- runningProcess . kill ( 'SIGTERM' )
530563
531564 await new Promise ( ( resolve ) => {
532- runningProcess . on ( 'exit' , resolve )
565+ let exited = false
566+ runningProcess . once ( 'exit' , ( ) => {
567+ exited = true
568+ resolve ( )
569+ } )
570+ runningProcess . kill ( 'SIGTERM' )
533571 setTimeout ( ( ) => {
534- if ( ! runningProcess . killed ) {
572+ if ( ! exited ) {
535573 runningProcess . kill ( 'SIGKILL' )
574+ // Safety: resolve after giving SIGKILL time to take effect
575+ setTimeout ( ( ) => resolve ( ) , 1000 )
536576 }
537- resolve ( )
538577 } , 5000 )
539578 } )
540579
580+ resetTerminal ( )
541581 console . log ( `Update available: ${ currentVersion } → ${ latestVersion } ` )
542582
543583 await downloadBinary ( latestVersion )
@@ -547,8 +587,14 @@ async function checkForUpdates(runningProcess, exitListener) {
547587 detached : false ,
548588 } )
549589
550- newChild . on ( 'exit' , ( code ) => {
551- process . exit ( code || 0 )
590+ newChild . on ( 'exit' , ( code , signal ) => {
591+ resetTerminal ( )
592+ process . exit ( signal ? 1 : ( code || 0 ) )
593+ } )
594+
595+ newChild . on ( 'error' , ( err ) => {
596+ console . error ( 'Failed to start codebuff:' , err . message )
597+ process . exit ( 1 )
552598 } )
553599
554600 return new Promise ( ( ) => { } )
@@ -565,12 +611,18 @@ async function main() {
565611 stdio : 'inherit' ,
566612 } )
567613
568- const exitListener = ( code ) => {
569- process . exit ( code || 0 )
614+ const exitListener = ( code , signal ) => {
615+ resetTerminal ( )
616+ process . exit ( signal ? 1 : ( code || 0 ) )
570617 }
571618
572619 child . on ( 'exit' , exitListener )
573620
621+ child . on ( 'error' , ( err ) => {
622+ console . error ( 'Failed to start codebuff:' , err . message )
623+ process . exit ( 1 )
624+ } )
625+
574626 setTimeout ( ( ) => {
575627 checkForUpdates ( child , exitListener )
576628 } , 100 )
0 commit comments