()
| 461 | // ========================================================================= |
| 462 | |
| 463 | async start(): Promise<void> { |
| 464 | // Signal handlers must be installed before raw mode to avoid EIO loops. |
| 465 | this.registerSignalHandlers(); |
| 466 | // Outer try rolls back signal listeners on startup failure. |
| 467 | try { |
| 468 | if (this.migrationPlan !== null) { |
| 469 | // Migration needs the event loop running first (pi-tui component). |
| 470 | this.startEventLoop(); |
| 471 | try { |
| 472 | const migrationResult = await this.runMigrationScreen(this.migrationPlan); |
| 473 | if (this.migrateOnly) { |
| 474 | const failed = migrationResult.decision === 'now' && migrationResult.migrated === false; |
| 475 | this.disposeTerminalTracking(); |
| 476 | this.state.ui.stop(); |
| 477 | await this.onExit?.(failed ? 1 : 0); |
| 478 | return; |
| 479 | } |
| 480 | const shouldReplayHistory = await this.initMainTui(); |
| 481 | this.startBackgroundFdAutocomplete(); |
| 482 | await this.finishStartup(shouldReplayHistory); |
| 483 | } catch (error) { |
| 484 | this.disposeTerminalTracking(); |
| 485 | this.state.ui.stop(); |
| 486 | throw error; |
| 487 | } |
| 488 | return; |
| 489 | } |
| 490 | |
| 491 | const shouldReplayHistory = await this.initMainTui(); |
| 492 | this.startEventLoop(); |
| 493 | try { |
| 494 | this.startBackgroundFdAutocomplete(); |
| 495 | await this.finishStartup(shouldReplayHistory); |
| 496 | } catch (error) { |
| 497 | this.disposeTerminalTracking(); |
| 498 | this.state.ui.stop(); |
| 499 | throw error; |
| 500 | } |
| 501 | } catch (error) { |
| 502 | this.unregisterSignalHandlers(); |
| 503 | throw error; |
| 504 | } |
| 505 | } |
| 506 | |
| 507 | private async loadBanner(): Promise<void> { |
| 508 | const provider = new BannerProvider(this.state.appState.version); |
no test coverage detected