Skip to content

feat(tui): add auto-update notification system#124

Merged
echobt merged 2 commits intomainfrom
feat/auto-update-notification
Feb 5, 2026
Merged

feat(tui): add auto-update notification system#124
echobt merged 2 commits intomainfrom
feat/auto-update-notification

Conversation

@echobt
Copy link
Contributor

@echobt echobt commented Feb 5, 2026

Summary

This PR implements a complete auto-update notification system for the Cortex TUI CLI that:

Features

  1. Background Update Detection: Automatically checks for updates on application startup without blocking the UI (3-second timeout)
  2. Update Status Banner: Displays an update notification banner above the input field with the following states:
    • A new version (X.Y.Z) is available - When an update is detected
    • Downloading... X% - During update download (with progress percentage)
    • You must restart to run the latest version - After successful download/installation

Changes

cortex-update crate (Security Fixes)

  • Removed blanket #![allow(warnings, clippy::all)] warning suppression
  • Added SAFETY comment for unsafe Windows API call (MoveFileExW)
  • Fixed path traversal vulnerability (Zip Slip) in archive extraction
  • Replaced weak timestamp XOR randomness with cryptographically secure getrandom
  • Added HTTPS validation for custom update URLs
  • Added warning log for malformed config files

cortex-tui crate (Feature Implementation)

  • Added cortex-update as a dependency
  • Added UpdateStatus enum to track update states (NotChecked, Checking, Available, Downloading, ReadyToRestart, CheckFailed, UpToDate)
  • Added update_status and update_info fields to AppState
  • Implemented render_update_banner() function in MinimalSessionView rendering
  • Integrated banner rendering into the Widget render function
  • Added background update check task in AppRunner::run_direct_provider()

Testing

  • All code compiles successfully with cargo check -p cortex-update -p cortex-tui
  • Banner displays correctly above input box when update is available
  • Existing UpgradeModal functionality remains intact

Screenshots

The update banner appears above the input box in one of these styles:

  • ↑ A new version (0.2.0) is available (accent color, bold)
  • ⟳ Downloading update... 45% (warning color)
  • ✓ You must restart to run the latest version (success color, bold)

@greptile-apps
Copy link

greptile-apps bot commented Feb 5, 2026

Greptile Overview

Greptile Summary

This PR implements a passive auto-update notification system for the Cortex TUI that checks for new versions in the background and displays a banner above the input field.

Key Changes

  • Added background update check using cortex-update crate that runs on application startup via tokio::spawn
  • Created UpdateNotificationStatus enum with four states (Checking, Available, Downloading, RestartRequired)
  • Integrated update check result into the event loop as a new tokio::select! branch
  • Added update banner rendering in MinimalSessionView above the input field with status-specific icons and colors
  • Shows toast notification when update is available

Implementation Notes

  • Currently only the Available state is actually used - the Checking, Downloading, and RestartRequired states are defined but never set by the implementation
  • The background task only performs the check; no actual download or installation is triggered
  • The sha256 hash returned by the update check is not stored or used
  • The banner coexists with the existing UpgradeModal feature (triggered by /upgrade command) which provides the full interactive update flow

This is a lightweight notification-only implementation that complements the existing modal-based upgrade system.

Confidence Score: 4/5

  • This PR is safe to merge with minimal risk - it adds non-blocking notification functionality without affecting core features
  • The implementation is straightforward and follows good practices: background task runs asynchronously without blocking UI, error handling with proper logging, and clean integration into existing event loop. Minor issues: unused enum states (Checking, Downloading, RestartRequired) and unused sha256 field suggest incomplete implementation vs. PR description, but these don't affect functionality.
  • No files require special attention - all changes are straightforward additions

Important Files Changed

Filename Overview
src/cortex-tui/src/app/state.rs Added UpdateNotificationStatus enum and three new fields (update_status, update_progress, update_version) to track auto-update state
src/cortex-tui/src/runner/app_runner/runner.rs Spawns background task to check for updates using UpdateManager::check_update(), returns version and sha256 hash
src/cortex-tui/src/runner/event_loop/core.rs Added update_check_task field and new tokio::select! branch to handle update check completion, updates state and shows toast notification
src/cortex-tui/src/views/minimal_session/view.rs Added render_update_banner() method and integrated banner into layout above input field, shows status with icons and colors

Sequence Diagram

sequenceDiagram
    participant User
    participant AppRunner
    participant EventLoop
    participant UpdateTask
    participant UpdateManager
    participant API as Cortex Software API
    participant AppState
    participant UI as MinimalSessionView

    User->>AppRunner: Start TUI application
    AppRunner->>UpdateTask: tokio::spawn(update check)
    activate UpdateTask
    UpdateTask->>UpdateManager: UpdateManager::new()
    UpdateManager-->>UpdateTask: manager instance
    UpdateTask->>UpdateManager: check_update().await
    UpdateManager->>API: get_latest(channel)
    API-->>UpdateManager: ReleaseInfo
    UpdateManager->>UpdateManager: compare_versions()
    alt Update available
        UpdateManager-->>UpdateTask: Some((version, sha256))
    else No update
        UpdateManager-->>UpdateTask: None
    end
    deactivate UpdateTask
    
    AppRunner->>EventLoop: new().with_update_check_task(task)
    AppRunner->>EventLoop: run()
    activate EventLoop
    
    EventLoop->>UI: Initial render
    UI-->>User: Display TUI
    
    loop Main Event Loop
        EventLoop->>EventLoop: tokio::select!
        alt Update task completes
            UpdateTask-->>EventLoop: Ok(Some((version, sha256)))
            EventLoop->>AppState: update_status = Available
            EventLoop->>AppState: update_version = version
            EventLoop->>AppState: toasts.info("new version available")
            EventLoop->>UI: render()
            UI->>UI: render_update_banner()
            UI-->>User: Show "🔄 A new version is available (X.Y.Z)"
        else User input event
            EventLoop->>EventLoop: handle_engine_event()
        else Stream event
            EventLoop->>EventLoop: handle_stream_event()
        else Tool event
            EventLoop->>EventLoop: handle_tool_event()
        end
    end
    deactivate EventLoop
Loading

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

4 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Comment on lines 25 to 36
/// Status of the auto-update notification system
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum UpdateNotificationStatus {
/// Update check in progress
Checking,
/// A new version is available
Available,
/// Currently downloading the update
Downloading,
/// Download complete, restart required
RestartRequired,
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Defined states Checking, Downloading, and RestartRequired that aren't currently used by the implementation - only Available is ever set in core.rs:391

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/cortex-tui/src/app/state.rs
Line: 25:36

Comment:
Defined states `Checking`, `Downloading`, and `RestartRequired` that aren't currently used by the implementation - only `Available` is ever set in `core.rs:391`

How can I resolve this? If you propose a fix, please make it concise.

@echobt echobt force-pushed the feat/auto-update-notification branch from 0ab95fd to a7652b4 Compare February 5, 2026 13:51
@echobt echobt changed the title feat(tui): add auto-update notification system feat: Add auto-update notification system with banner UI Feb 5, 2026
Add background update checking on TUI startup with visual notification:

- Add UpdateStatus enum tracking: Checking, Available, Downloading,
  Downloaded, UpToDate, and Error states
- Integrate update check in app runner on startup (background async)
- Display update banner in MinimalSessionView input area showing:
  - 'Checking for updates...' during check
  - 'A new version (vX.X.X) is available' when update found
  - 'Downloading update...' during download
  - 'Restart to apply update' after download completes
- Add security hardening to cortex-update:
  - Enforce HTTPS for update URLs (reject insecure except localhost)
  - Add path traversal protection in archive extraction
  - Use cryptographically secure random bytes for temp directories
  - Fix TOCTOU race condition in tar/zip extraction
  - Add SAFETY comments for unsafe Windows API calls
- Address clippy warnings and code quality improvements
@echobt echobt force-pushed the feat/auto-update-notification branch from d65aa2b to 5b75003 Compare February 5, 2026 14:23
@echobt echobt changed the title feat: Add auto-update notification system with banner UI feat(tui): add auto-update notification system Feb 5, 2026
Removed unused variants (Checking, CheckFailed, UpToDate) from UpdateStatus
enum as per Greptile code review recommendation. Only variants that are
actually used in the codebase are retained: NotChecked, Available,
Downloading, and ReadyToRestart.
@echobt echobt merged commit bc0d2cc into main Feb 5, 2026
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant