freebuff 0.0.26 → 0.0.29

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/index.js +110 -8
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -13,6 +13,40 @@ const tar = require('tar')
13
13
 
14
14
  const packageName = 'freebuff'
15
15
 
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
+
16
50
  function createConfig(packageName) {
17
51
  const homeDir = os.homedir()
18
52
  const configDir = path.join(homeDir, '.config', 'manicode')
@@ -513,18 +547,24 @@ async function checkForUpdates(runningProcess, exitListener) {
513
547
  term.clearLine()
514
548
 
515
549
  runningProcess.removeListener('exit', exitListener)
516
- runningProcess.kill('SIGTERM')
517
550
 
518
551
  await new Promise((resolve) => {
519
- runningProcess.on('exit', resolve)
552
+ let exited = false
553
+ runningProcess.once('exit', () => {
554
+ exited = true
555
+ resolve()
556
+ })
557
+ runningProcess.kill('SIGTERM')
520
558
  setTimeout(() => {
521
- if (!runningProcess.killed) {
559
+ if (!exited) {
522
560
  runningProcess.kill('SIGKILL')
561
+ // Safety: resolve after giving SIGKILL time to take effect
562
+ setTimeout(() => resolve(), 1000)
523
563
  }
524
- resolve()
525
564
  }, 5000)
526
565
  })
527
566
 
567
+ resetTerminal()
528
568
  console.log(`Update available: ${currentVersion} → ${latestVersion}`)
529
569
 
530
570
  await downloadBinary(latestVersion)
@@ -534,8 +574,15 @@ async function checkForUpdates(runningProcess, exitListener) {
534
574
  detached: false,
535
575
  })
536
576
 
537
- newChild.on('exit', (code) => {
538
- process.exit(code || 0)
577
+ newChild.on('exit', (code, signal) => {
578
+ resetTerminal()
579
+ printCrashDiagnostics(code, signal)
580
+ process.exit(signal ? 1 : (code || 0))
581
+ })
582
+
583
+ newChild.on('error', (err) => {
584
+ console.error('Failed to start freebuff:', err.message)
585
+ process.exit(1)
539
586
  })
540
587
 
541
588
  return new Promise(() => {})
@@ -545,6 +592,54 @@ async function checkForUpdates(runningProcess, exitListener) {
545
592
  }
546
593
  }
547
594
 
595
+ function printCrashDiagnostics(code, signal) {
596
+ // Windows NTSTATUS codes (unsigned DWORD)
597
+ const unsignedCode = code != null && code < 0 ? (code >>> 0) : code
598
+ const isIllegalInstruction =
599
+ signal === 'SIGILL' ||
600
+ (process.platform === 'win32' && unsignedCode === 0xC000001D)
601
+ const isAccessViolation =
602
+ signal === 'SIGSEGV' ||
603
+ (process.platform === 'win32' && unsignedCode === 0xC0000005)
604
+ const isBusError = signal === 'SIGBUS'
605
+ const isAbort =
606
+ signal === 'SIGABRT' ||
607
+ (process.platform === 'win32' && unsignedCode === 0xC0000409)
608
+
609
+ if (!isIllegalInstruction && !isAccessViolation && !isBusError && !isAbort) return
610
+
611
+ const exitInfo = signal ? `signal ${signal}` : `code ${code}`
612
+ console.error('')
613
+ console.error(`❌ ${packageName} exited immediately (${exitInfo})`)
614
+ console.error('')
615
+
616
+ if (isIllegalInstruction) {
617
+ console.error('Your CPU may not support the required instruction set (AVX2).')
618
+ console.error('This typically affects CPUs from before 2013.')
619
+ console.error('Unfortunately, this binary is not compatible with your system.')
620
+ console.error('')
621
+ } else if (isAccessViolation) {
622
+ console.error('The binary crashed with an access violation.')
623
+ console.error('')
624
+ } else if (isBusError) {
625
+ console.error('The binary crashed with a bus error.')
626
+ console.error('This may indicate a platform compatibility issue.')
627
+ console.error('')
628
+ } else if (isAbort) {
629
+ console.error('The binary crashed with an abort signal.')
630
+ console.error('')
631
+ }
632
+
633
+ console.error('System info:')
634
+ console.error(` Platform: ${process.platform} ${process.arch}`)
635
+ console.error(` Node: ${process.version}`)
636
+ console.error(` Binary: ${CONFIG.binaryPath}`)
637
+ console.error('')
638
+ console.error('Please report this issue at:')
639
+ console.error(' https://github.com/CodebuffAI/codebuff/issues')
640
+ console.error('')
641
+ }
642
+
548
643
  async function main() {
549
644
  await ensureBinaryExists()
550
645
 
@@ -552,12 +647,19 @@ async function main() {
552
647
  stdio: 'inherit',
553
648
  })
554
649
 
555
- const exitListener = (code) => {
556
- process.exit(code || 0)
650
+ const exitListener = (code, signal) => {
651
+ resetTerminal()
652
+ printCrashDiagnostics(code, signal)
653
+ process.exit(signal ? 1 : (code || 0))
557
654
  }
558
655
 
559
656
  child.on('exit', exitListener)
560
657
 
658
+ child.on('error', (err) => {
659
+ console.error('Failed to start freebuff:', err.message)
660
+ process.exit(1)
661
+ })
662
+
561
663
  setTimeout(() => {
562
664
  checkForUpdates(child, exitListener)
563
665
  }, 100)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "freebuff",
3
- "version": "0.0.26",
3
+ "version": "0.0.29",
4
4
  "description": "The world's strongest free coding agent",
5
5
  "license": "MIT",
6
6
  "bin": {