4runr-os 2.9.25 → 2.9.26

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.
@@ -518,22 +518,30 @@ fn main() -> Result<()> {
518
518
  // Check if render is scheduled and throttle limit has passed
519
519
  // OPTIMIZATION: Removed input debounce check - using immediate render for typing
520
520
  if app.should_render() {
521
- // Check if we're switching to a portal - clear terminal buffer for clean transition
522
521
  // Clone current screen before mutable borrow
523
522
  let current_screen = app.state.navigation.current_screen().clone();
524
- let is_switching_to_portal = match (&previous_screen, &current_screen) {
525
- (Some(prev), current) if prev != current => {
526
- matches!(current, crate::screens::Screen::ConnectionPortal | crate::screens::Screen::SetupPortal)
527
- }
528
- (None, current) => {
529
- matches!(current, crate::screens::Screen::ConnectionPortal | crate::screens::Screen::SetupPortal)
530
- }
531
- _ => false,
532
- };
523
+ let is_portal_active = matches!(current_screen, crate::screens::Screen::ConnectionPortal | crate::screens::Screen::SetupPortal);
533
524
 
534
- if is_switching_to_portal {
535
- // Clear terminal buffer when switching to portal for clean standalone rendering
525
+ // DEBUG HYPOTHESIS 1: Clear terminal on EVERY portal render, not just on switch
526
+ // This tests if terminal buffer retention is causing duplication
527
+ if is_portal_active {
528
+ // Clear terminal buffer on every portal render to prevent buffer retention
536
529
  terminal.clear()?;
530
+ } else {
531
+ // Only clear on switch TO portal (original behavior for non-portals)
532
+ let is_switching_to_portal = match (&previous_screen, &current_screen) {
533
+ (Some(prev), current) if prev != current => {
534
+ matches!(current, crate::screens::Screen::ConnectionPortal | crate::screens::Screen::SetupPortal)
535
+ }
536
+ (None, current) => {
537
+ matches!(current, crate::screens::Screen::ConnectionPortal | crate::screens::Screen::SetupPortal)
538
+ }
539
+ _ => false,
540
+ };
541
+
542
+ if is_switching_to_portal {
543
+ terminal.clear()?;
544
+ }
537
545
  }
538
546
 
539
547
  let render_start = Instant::now();
@@ -19,6 +19,18 @@ const ERROR_RED: Color = Color::Rgb(255, 69, 69);
19
19
 
20
20
  /// Main render function - Full-screen standalone portal
21
21
  pub fn render(f: &mut Frame, state: &AppState) {
22
+ // DEBUG: Track render calls
23
+ #[cfg(debug_assertions)]
24
+ {
25
+ static mut RENDER_COUNT: u64 = 0;
26
+ unsafe {
27
+ RENDER_COUNT += 1;
28
+ if RENDER_COUNT % 10 == 1 { // Log every 10th render to avoid spam
29
+ eprintln!("[DEBUG] Connection Portal render #{}", RENDER_COUNT);
30
+ }
31
+ }
32
+ }
33
+
22
34
  let area = f.size();
23
35
 
24
36
  // CRITICAL: Clear the ENTIRE screen first - this is a standalone screen, not an overlay
@@ -65,6 +77,27 @@ pub fn render(f: &mut Frame, state: &AppState) {
65
77
  ])
66
78
  .split(portal_area);
67
79
 
80
+ // DEBUG: Log chunk positions to detect overlap
81
+ #[cfg(debug_assertions)]
82
+ {
83
+ static mut LOG_COUNT: u64 = 0;
84
+ unsafe {
85
+ LOG_COUNT += 1;
86
+ if LOG_COUNT % 50 == 1 { // Log every 50th render
87
+ eprintln!("[DEBUG] Portal area: {:?}", portal_area);
88
+ eprintln!("[DEBUG] chunks[0] (header): {:?}", chunks[0]);
89
+ eprintln!("[DEBUG] chunks[1] (description): {:?}", chunks[1]);
90
+ eprintln!("[DEBUG] chunks[2] (input): {:?}", chunks[2]);
91
+ eprintln!("[DEBUG] chunks[3] (content): {:?}", chunks[3]);
92
+ eprintln!("[DEBUG] chunks[4] (actions): {:?}", chunks[4]);
93
+ // Check for overlap
94
+ if chunks[2].y + chunks[2].height > chunks[3].y {
95
+ eprintln!("[DEBUG] ⚠️ OVERLAP DETECTED: chunks[2] overlaps chunks[3]!");
96
+ }
97
+ }
98
+ }
99
+ }
100
+
68
101
  // Render sections
69
102
  render_header(f, chunks[0], state);
70
103
  render_description(f, chunks[1]);
@@ -113,6 +146,18 @@ fn render_input_fields(f: &mut Frame, area: Rect, state: &AppState) {
113
146
  // CRITICAL: Clear the input area first to prevent duplication
114
147
  f.render_widget(Clear, area);
115
148
 
149
+ // DEBUG: Log input field rendering
150
+ #[cfg(debug_assertions)]
151
+ {
152
+ static mut LOG_COUNT: u64 = 0;
153
+ unsafe {
154
+ LOG_COUNT += 1;
155
+ if LOG_COUNT % 50 == 1 {
156
+ eprintln!("[DEBUG] render_input_fields called - area: {:?}", area);
157
+ }
158
+ }
159
+ }
160
+
116
161
  let portal = &state.connection_portal;
117
162
  let url_focused = portal.focused_field == PortalField::GatewayUrl;
118
163
  let input_enabled = !portal.connecting;
@@ -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.25";
147
+ const PACKAGE_VERSION: &str = "2.9.26";
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.25",
3
+ "version": "2.9.26",
4
4
  "type": "module",
5
- "description": "4Runr AI Agent OS - Secure terminal interface for AI agents. v2.9.25: Completely rewrote Connection Portal input field rendering - replaced manual box drawing with clean Ratatui Block widget to eliminate duplication. v2.9.24: Fixed Connection Portal duplication - added Clear widgets to all render areas to prevent artifacts. ⚠️ Pre-MVP / Development Phase",
5
+ "description": "4Runr AI Agent OS - Secure terminal interface for AI agents. v2.9.26: Added comprehensive debug logging for Connection Portal duplication issue - implemented render call tracking, chunk position logging, and terminal buffer clearing on every portal render to identify root cause. v2.9.25: Completely rewrote Connection Portal input field rendering - replaced manual box drawing with clean Ratatui Block widget. ⚠️ Pre-MVP / Development Phase",
6
6
  "main": "dist/index.js",
7
7
  "bin": {
8
8
  "4runr": "dist/index.js",