4runr-os 2.9.60 → 2.9.62

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.
@@ -1812,20 +1812,21 @@ impl App {
1812
1812
  // ============================================================
1813
1813
 
1814
1814
  fn handle_setup_portal_input(&mut self, key: KeyEvent, _ws_client: Option<&WebSocketClient>) -> anyhow::Result<bool> {
1815
- // Guard: Don't process if already detecting
1815
+ // ESC always closes the portal (even when detecting), so user can always get out
1816
+ if key.code == KeyCode::Esc {
1817
+ self.state.setup_portal.detecting = false;
1818
+ self.state.navigation.navigate_to_base(Screen::Main);
1819
+ self.add_log("[NAV] Setup Portal closed".to_string());
1820
+ self.request_immediate_render("setup_portal_close");
1821
+ return Ok(false);
1822
+ }
1823
+
1824
+ // Don't process other keys while detecting
1816
1825
  if self.state.setup_portal.detecting {
1817
1826
  return Ok(false);
1818
1827
  }
1819
1828
 
1820
1829
  match key.code {
1821
- // ESC - Cancel and close portal
1822
- KeyCode::Esc => {
1823
- // Navigate back to Main (portals are now base screens, not overlays)
1824
- self.state.navigation.navigate_to_base(Screen::Main);
1825
- self.add_log("[NAV] Setup Portal closed".to_string());
1826
- self.request_immediate_render("setup_portal_close");
1827
- }
1828
-
1829
1830
  // F2 - Go directly to Connection Portal
1830
1831
  KeyCode::F(2) => {
1831
1832
  // Navigate to portal as base screen (standalone, not overlay)
@@ -592,13 +592,14 @@ fn main() -> Result<()> {
592
592
  let current_screen = app.state.navigation.current_screen().clone();
593
593
  let is_portal_active = matches!(current_screen, crate::screens::Screen::ConnectionPortal | crate::screens::Screen::SetupPortal);
594
594
 
595
- // Clear only on screen switch (no clear on Setup Portal nav = no flicker)
595
+ // Clear only on screen switch (but not when switching TO Setup Portal; we'll clear after autoresize)
596
596
  let is_switching = match (&previous_screen, &current_screen) {
597
597
  (Some(prev), current) => prev != current,
598
598
  (None, _) => true,
599
599
  };
600
+ let switching_to_setup_portal = is_switching && matches!(current_screen, crate::screens::Screen::SetupPortal);
600
601
 
601
- if is_switching {
602
+ if is_switching && !switching_to_setup_portal {
602
603
  #[cfg(debug_assertions)]
603
604
  eprintln!("[MAIN] SCREEN SWITCH: {:?} -> {:?} (clearing)", previous_screen, current_screen);
604
605
  debug_log::log_screen(
@@ -608,9 +609,19 @@ fn main() -> Result<()> {
608
609
  terminal.clear()?;
609
610
  }
610
611
 
611
- // When on Setup Portal, sync terminal buffer to real console size (fixes windowed-mode corruption)
612
+ // When on Setup Portal: autoresize clear draw (fixes windowed-mode corruption)
613
+ // Order matters: resize buffer to match console size BEFORE clearing so we clear the entire visible area.
612
614
  if matches!(current_screen, crate::screens::Screen::SetupPortal) {
613
- let _ = terminal.autoresize();
615
+ terminal.autoresize()?;
616
+ terminal.clear()?;
617
+ if switching_to_setup_portal {
618
+ #[cfg(debug_assertions)]
619
+ eprintln!("[MAIN] ENTERED Setup Portal (autoresize + clear)");
620
+ debug_log::log_screen(
621
+ &format!("{:?}", previous_screen.as_ref().unwrap_or(&current_screen)),
622
+ &format!("{:?}", current_screen),
623
+ );
624
+ }
614
625
  }
615
626
 
616
627
  let render_start = Instant::now();
@@ -144,7 +144,7 @@ fn render_header(f: &mut Frame, area: Rect, state: &AppState) {
144
144
 
145
145
  // Line 1: Brand + version + mode + uptime - Bug 3 fix: Use "4Runr." with dot (matches brand logo)
146
146
  // Use npm package version (2.9.24) - matches package.json
147
- const PACKAGE_VERSION: &str = "2.9.60";
147
+ const PACKAGE_VERSION: &str = "2.9.62";
148
148
  let brand_line = Line::from(vec![
149
149
  Span::styled("4Runr.", Style::default().fg(BRAND_PURPLE).add_modifier(Modifier::BOLD)),
150
150
  Span::styled(" AI AGENT OS", Style::default().fg(BRAND_VIOLET)),
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "4runr-os",
3
- "version": "2.9.60",
3
+ "version": "2.9.62",
4
4
  "type": "module",
5
- "description": "4Runr AI Agent OS - Secure terminal interface for AI agents. v2.9.60: Setup Portal debug shows log file path. v2.9.59: File debug. ⚠️ Pre-MVP / Development Phase",
5
+ "description": "4Runr AI Agent OS - Secure terminal interface for AI agents. v2.9.62: Setup Portal windowed fix (autoresize then clear then draw). v2.9.61: ESC always closes. ⚠️ Pre-MVP / Development Phase",
6
6
  "main": "dist/index.js",
7
7
  "bin": {
8
8
  "4runr": "dist/index.js",