This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 914537bf7524f2647be0836b7deaa6b9315a53b0
Author: Claus Ibsen <[email protected]>
AuthorDate: Tue Jul 28 07:52:18 2026 +0200

    camel-tui: Use compact duration format in Inflight tab
    
    camel-tui: Improve table tabs and Internal Tasks/CVE Audit display
    
    - BackgroundTask: add attempting flag, fix nextAttemptTime calculation,
      persist error across retry attempts
    - Internal Tasks tab: show Waiting/Attempting status, use compact
      duration format, fix NEXT showing 0ms
    - Enable table row selection with highlight on Consumers, Producers,
      Inflight, Health, and Internal Tasks tabs
    - CVE Audit tab: extract (via xxx) into its own sortable VIA column,
      reduce CVE ID column width
    
    camel-tui: Update TUI documentation to match current state
    
    - Mention 40+ screens in intro
    - Update tab overview: Source is now Tab 2, HTTP moved to More
    - List all 31 More tabs organized by category groups
    - Add Source Code Browser section with inline doc and format cycling
    - Add Highlighted Features section: CVE Audit, Kafka, SQL, Memory Leak, 
Catalog
    - Update Theme section: 15 themes instead of 2
    - Add Source Tab keyboard shortcuts
    - Fix tab number references throughout
    
    camel-tui: Document runtime selector (Main, Spring Boot, Quarkus)
    
    Run an example and Run from folder let you choose between Camel Main,
    Spring Boot, and Quarkus runtimes before launching. When a pom.xml is
    present the runtime is auto-detected.
    
    camel-tui: Document camel-cli-connector for Spring Boot and Quarkus apps
    
    camel-tui: Rename Internal Tasks tab to Recovery Tasks
    
    The tab tracks reconnection and retry operations, so "Recovery Tasks"
    better communicates its purpose to users and AI agents.
    
    Co-Authored-By: Claude Opus 4.6 <[email protected]>
    Signed-off-by: Claus Ibsen <[email protected]>
---
 .../camel/impl/console/TaskRegistryDevConsole.java |   1 +
 .../apache/camel/support/task/BackgroundTask.java  |  13 +-
 .../java/org/apache/camel/support/task/Task.java   |   8 +
 .../modules/ROOT/pages/camel-jbang-tui.adoc        | 192 ++++++++++++++++++---
 .../dsl/jbang/core/commands/tui/ConsumersTab.java  |  22 +--
 .../dsl/jbang/core/commands/tui/CveAuditTab.java   |  26 ++-
 .../dsl/jbang/core/commands/tui/HealthTab.java     |  21 +--
 .../dsl/jbang/core/commands/tui/InflightTab.java   |  24 +--
 .../jbang/core/commands/tui/InternalTaskInfo.java  |   1 +
 .../jbang/core/commands/tui/InternalTasksTab.java  |  49 +++---
 .../dsl/jbang/core/commands/tui/ProducersTab.java  |  22 +--
 .../dsl/jbang/core/commands/tui/StatusParser.java  |   1 +
 .../dsl/jbang/core/commands/tui/TabRegistry.java   |   2 +-
 .../dsl/jbang/core/commands/tui/TuiIcons.java      |   2 +-
 14 files changed, 238 insertions(+), 146 deletions(-)

diff --git 
a/core/camel-console/src/main/java/org/apache/camel/impl/console/TaskRegistryDevConsole.java
 
b/core/camel-console/src/main/java/org/apache/camel/impl/console/TaskRegistryDevConsole.java
index e92c19c64df5..1bab1684eb8a 100644
--- 
a/core/camel-console/src/main/java/org/apache/camel/impl/console/TaskRegistryDevConsole.java
+++ 
b/core/camel-console/src/main/java/org/apache/camel/impl/console/TaskRegistryDevConsole.java
@@ -63,6 +63,7 @@ public class TaskRegistryDevConsole extends 
AbstractDevConsole {
             JsonObject jo = new JsonObject();
             jo.put("name", task.getName());
             jo.put("status", task.getStatus().name());
+            jo.put("attempting", task.isAttempting());
             jo.put("attempts", task.iteration());
             jo.put("delay", task.getCurrentDelay());
             jo.put("elapsed", task.getCurrentElapsedTime());
diff --git 
a/core/camel-support/src/main/java/org/apache/camel/support/task/BackgroundTask.java
 
b/core/camel-support/src/main/java/org/apache/camel/support/task/BackgroundTask.java
index f0f9a51bef81..5065391ca38e 100644
--- 
a/core/camel-support/src/main/java/org/apache/camel/support/task/BackgroundTask.java
+++ 
b/core/camel-support/src/main/java/org/apache/camel/support/task/BackgroundTask.java
@@ -82,6 +82,7 @@ public class BackgroundTask extends AbstractTask implements 
BlockingTask {
     private final AtomicBoolean running = new AtomicBoolean();
     private final AtomicBoolean completed = new AtomicBoolean();
     private volatile boolean registeredByRun;
+    private volatile boolean attempting;
 
     BackgroundTask(TimeBudget budget, ScheduledExecutorService service, String 
name) {
         super(name);
@@ -132,7 +133,8 @@ public class BackgroundTask extends AbstractTask implements 
BlockingTask {
             cause = e;
             throw e;
         }
-        nextAttemptTime = lastAttemptTime + budget.interval();
+        // scheduleWithFixedDelay waits interval after this run finishes, so 
compute from now
+        nextAttemptTime = System.currentTimeMillis() + budget.interval();
     }
 
     /**
@@ -162,15 +164,22 @@ public class BackgroundTask extends AbstractTask 
implements BlockingTask {
         return completed.get();
     }
 
+    @Override
+    public boolean isAttempting() {
+        return attempting;
+    }
+
     protected boolean doRun(BooleanSupplier supplier) {
         try {
-            cause = null;
+            attempting = true;
             return supplier.getAsBoolean();
         } catch (TaskRunFailureException e) {
             LOG.debug("Task {} failed at {} iterations and will attempt again 
on next interval: {}",
                     getName(), budget.iteration(), e.getMessage());
             cause = e;
             return false;
+        } finally {
+            attempting = false;
         }
     }
 
diff --git 
a/core/camel-support/src/main/java/org/apache/camel/support/task/Task.java 
b/core/camel-support/src/main/java/org/apache/camel/support/task/Task.java
index 5f74bf5b0f4d..72cfa586bdf4 100644
--- a/core/camel-support/src/main/java/org/apache/camel/support/task/Task.java
+++ b/core/camel-support/src/main/java/org/apache/camel/support/task/Task.java
@@ -81,6 +81,14 @@ public interface Task {
      */
     long getNextAttemptTime();
 
+    /**
+     * Whether the task is currently attempting to run its supplier (true), or 
waiting for the next scheduled tick
+     * (false).
+     */
+    default boolean isAttempting() {
+        return false;
+    }
+
     /**
      * The task failed for some un-expected exception
      */
diff --git a/docs/user-manual/modules/ROOT/pages/camel-jbang-tui.adoc 
b/docs/user-manual/modules/ROOT/pages/camel-jbang-tui.adoc
index 74e0eee86f09..c487a80122b5 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-jbang-tui.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-jbang-tui.adoc
@@ -3,9 +3,11 @@
 *Available as of Camel 4.21*
 
 Camel TUI is a terminal dashboard for developing, prototyping, and 
understanding Camel integrations.
-It makes your integration visible -- you can see your route topology, watch 
messages flow through
-processors, step through exchanges like scrubbing through a video timeline, 
and understand what Camel actually does
-with your routes. No more black box.
+With over 40 screens organized across tabs, it makes your entire integration 
visible -- you can browse
+your project source code with inline documentation, see your route topology, 
watch messages flow through
+processors, step through exchanges like scrubbing through a video timeline, 
inspect Kafka topics,
+run SQL queries against your DataSources, audit CVE vulnerabilities, and 
understand what Camel actually
+does with your routes. No more black box.
 
 image::jbang/camel-tui-overview.png[TUI Overview showing multiple routes]
 
@@ -46,6 +48,11 @@ camel tui
 . Browse the example catalog -- type to filter by name
 . Press *Enter* to launch the selected example
 
+Before launching, a run options form lets you choose the *runtime*: Camel Main 
(standalone),
+Spring Boot, or Quarkus. This makes it easy to try any example on all three 
runtimes without
+changing a single line of code. You can also set the integration name, toggle 
dev mode, and
+add extra dependencies.
+
 The example starts running in the background. The TUI auto-selects it as soon 
as it appears.
 From there you can explore tabs, watch messages flow, inspect the route 
diagram, and experiment.
 
@@ -53,9 +60,46 @@ If an example requires infrastructure (like Kafka or a 
database), the TUI automa
 required Docker containers before launching the example. A notification in the 
footer shows the
 progress.
 
+The same runtime selector is available in *Run from folder...* (F2 menu), 
which lets you point
+the TUI at a local directory containing your routes. When a `pom.xml` is 
present, the runtime
+is auto-detected and locked to match your project.
+
 TIP: Press *F1* or *?* on any screen for context-sensitive help.
 Keyboard shortcuts are always shown in the footer bar.
 
+=== Connecting Existing Spring Boot and Quarkus Applications
+
+The TUI auto-discovers integrations started with `camel run`. To monitor and 
control
+existing Spring Boot or Quarkus applications, add the `camel-cli-connector` 
dependency
+to your project. This is a lightweight runtime adapter that lets the TUI (and 
the Camel CLI)
+communicate with your application -- all TUI features work the same way 
regardless of runtime.
+
+Spring Boot:
+
+[source,xml]
+----
+<dependency>
+    <groupId>org.apache.camel.springboot</groupId>
+    <artifactId>camel-cli-connector-starter</artifactId>
+</dependency>
+----
+
+Quarkus:
+
+[source,xml]
+----
+<dependency>
+    <groupId>org.apache.camel.quarkus</groupId>
+    <artifactId>camel-quarkus-cli-connector</artifactId>
+</dependency>
+----
+
+Once added, start your application normally and the TUI will discover it 
automatically.
+No additional configuration is needed -- the connector auto-detects on the 
classpath and
+registers the application with the local Camel CLI.
+
+See xref:camel-jbang-managing.adoc[Managing Integrations] for more details.
+
 == Tabs Overview
 
 The TUI organizes information into tabs. Press number keys *1* through *0* to 
jump directly
@@ -66,27 +110,55 @@ to any tab, or use *Tab* / *Shift+Tab* to cycle.
 | Key | Tab | What It Shows
 
 | 1 | Overview | All running integrations and infrastructure services. Start 
here.
-| 2 | Log | Real-time application logs with search and filtering.
-| 3 | Activity | Live exchange activity with elapsed times, endpoint sends, 
and failure tracking.
-| 4 | Diagram | Visual route topology with drill-down into individual routes.
-| 5 | Routes | Route list with message counts, throughput, and processing 
times.
-| 6 | Endpoints | All registered endpoints with usage statistics.
-| 7 | HTTP | HTTP endpoints with details.
+| 2 | Source | File explorer for your project code with syntax highlighting 
and inline Camel documentation.
+| 3 | Log | Real-time application logs with search and filtering.
+| 4 | Activity | Live exchange activity with elapsed times, endpoint sends, 
and failure tracking.
+| 5 | Diagram | Visual route topology with drill-down into individual routes.
+| 6 | Routes | Route list with message counts, throughput, and processing 
times.
+| 7 | Endpoints | All registered endpoints with usage statistics.
 | 8 | Inspect | Message history and tracing -- step through exchanges 
processor by processor.
 | 9 | Errors | Failures with stack traces and exchange context.
-| 0 | More | Additional tabs: Beans, Browse, Circuit Breaker, Classpath, 
Configuration, Consumers, CVE Audit, Health, Inflight, Memory, Metrics, Spans, 
Process, Startup, and more.
+| 0 | More | 30+ additional tabs organized by category (see below).
 |===
 
-Tabs appear dynamically based on what the integration uses. For example, the 
SQL tab appears
-when a DataSource is present, Circuit Breaker when resilience4j is in use, and 
Spans when
-OpenTelemetry is enabled. The TUI adapts to show only what's relevant to your 
integration.
+The *More* menu (key *0*) opens a popup with tabs organized into groups:
+
+* *Routing* -- Browse Endpoints, Consumers, HTTP, Inflight, Producers, Route 
Controller
+* *Observability* -- Circuit Breaker, Health, Metrics, Network Services, 
Exchange Events, Recovery Tasks, OpenTelemetry Spans
+* *Data* -- JDBC DataSource, Kafka, SQL Query, SQL Trace
+* *JVM* -- Classpath, Heap Memory Histogram, Memory Usage, Memory Leak, 
Process, Startup, Threads
+* *Project* -- Beans, Catalog, Configuration, CVE Audit, Maven Dependencies, 
Type Converters, Data Type Transformers
+
+Tabs appear dynamically based on what the integration uses. For example, the 
Kafka tab appears
+when a Kafka component is in use, SQL tabs when a DataSource is present, 
Circuit Breaker when
+resilience4j is in use, and Spans when OpenTelemetry is enabled. The TUI 
adapts to show only
+what's relevant to your integration.
 
 Tab badges show live counts -- the Errors tab shows a red badge when errors 
exist
 and Routes shows the route count.
 
+== Source Code Browser
+
+The Source tab (Tab 2) gives you a file explorer into your project code. The 
left panel shows
+a navigable file tree of the integration's source directory. Select any file 
to view it in the
+right panel with full syntax highlighting.
+
+For Camel source files (YAML, XML, Java routes, and `application.properties`), 
press *i* to toggle
+inline documentation. The TUI uses the Camel catalog to look up every 
component, EIP, language,
+and data format used in your route and shows their documentation right next to 
the source code.
+For properties files, it resolves `camel.component.*` and `camel.main.*` keys 
to their catalog
+descriptions. This makes it easy to understand unfamiliar routes without 
leaving the terminal.
+
+Additional features:
+
+* *Format cycling* -- press *Space* to convert Camel routes between YAML, 
Java, and XML DSL formats
+* *Search* -- press */* to search within the source code, *n*/*N* to jump 
between matches
+* *Highlight* -- press *h* to highlight text occurrences
+* *Resizable panels* -- drag the split border with the mouse to resize the 
file list and viewer
+
 == Activity
 
-The Activity tab (Tab 3) shows a live feed of exchange activity -- every 
exchange that flows through
+The Activity tab shows a live feed of exchange activity -- every exchange that 
flows through
 the system is captured with its route, status (OK or Failed), elapsed time, 
endpoint sends, and
 how long ago it completed.
 
@@ -105,7 +177,7 @@ Use *s* to cycle sort order, *S* to reverse, and *F5* to 
clear the activity list
 
 == Route Topology Diagram
 
-The Diagram tab (Tab 4) renders the route topology as interactive ASCII art. 
It shows how routes
+The Diagram tab renders the route topology as interactive ASCII art. It shows 
how routes
 connect to each other through shared endpoints (direct, seda, kafka, etc.).
 
 image::jbang/camel-tui-diagram.png[Diagram topology view]
@@ -322,26 +394,28 @@ The Doctor checks your development environment and 
reports issues:
 
 == Theme
 
-The TUI ships with two color themes, *dark* (the default) and *light*, defined 
as
-CSS stylesheets. Open the *F2* actions menu and choose *Light Theme* or *Dark 
Theme*
-to switch at runtime.
+The TUI ships with 15 color themes defined as CSS stylesheets:
+
+* *Dark themes* -- Dark (default), Dracula, Nord, Solarized Dark, Gruvbox Dark,
+  Catppuccin Mocha, Tokyo Night, Rosé Pine, Kanagawa, Everforest, Monochrome, 
CRT
+* *Light themes* -- Light, Solarized Light, Catppuccin Latte
 
-Pass `--theme=dark` or `--theme=light` on the command line to pick the palette 
for
-the current session. The CLI value overrides the persisted preference from
-`.camel-cli.properties`; runtime toggles and the config file still apply on
-later launches when `--theme` is omitted.
+Open the *F2* actions menu and choose *Settings...* to switch themes, or pass
+`--theme=<name>` on the command line (e.g., `--theme=tokyo-night`). The CLI 
value
+overrides the persisted preference from `.camel-cli.properties`; runtime 
toggles and
+the config file still apply on later launches when `--theme` is omitted.
 
-The brand orange accent is identical in both themes; status colors (success,
-warning, error) and borders adapt for readability on dark and light terminals.
+The brand orange accent is consistent across all themes; status colors 
(success,
+warning, error) and borders adapt for readability on each palette.
 
-Your choice is remembered: it is saved as `camel.tui.theme` (`dark` or `light`)
-in `.camel-cli.properties` and restored the next time you open the TUI.
+Your choice is remembered: it is saved as `camel.tui.theme` in 
`.camel-cli.properties`
+and restored the next time you open the TUI.
 
 == Settings
 
 Open the *F2* actions menu and choose *Settings...* to change TUI preferences 
in one place:
 
-* *Theme* -- cycle between *dark* and *light* (applied immediately on save).
+* *Theme* -- cycle through 15 available themes (applied immediately on save).
 * *Starting Tab* -- the tab shown when the TUI launches; any tab (primary or 
under *More*) can be
   chosen. Defaults to *Overview*.
 * *Select Tab* -- the tab to switch to when selecting an integration from the 
Overview tab.
@@ -389,6 +463,25 @@ respectively. Use *↑*/*↓* on the input line to walk 
previous entries. Limits
 | *Esc* | Close popup / go back / return to Overview
 |===
 
+=== Source Tab
+
+[cols="2,5",options="header"]
+|===
+| Key | Action
+
+| *Up/Down* | Navigate files (left panel) or scroll source (right panel)
+| *Enter* | Open file or directory
+| *Backspace* | Go to parent directory
+| *Tab* | Toggle focus between file list and source viewer
+| *Space* | Cycle format (YAML/Java/XML) for Camel routes
+| *i* | Toggle inline Camel documentation
+| */* | Search in source
+| *h* | Highlight text
+| *n* / *N* | Next / previous search match
+| *w* | Toggle word wrap
+| *Esc* / *c* | Close source viewer
+|===
+
 === Diagram Tab
 
 [cols="2,5",options="header"]
@@ -420,6 +513,49 @@ respectively. Use *↑*/*↓* on the input line to walk 
previous entries. Limits
 | *F5* | Refresh / clear traces
 |===
 
+== Highlighted Features
+
+Beyond the core tabs described above, the TUI includes several specialized 
screens worth highlighting.
+
+=== CVE Audit
+
+The CVE Audit tab (under More > Project) scans all Maven dependencies on your 
integration's classpath
+against the https://osv.dev[OSV.dev] vulnerability database. It queries every 
JAR using the OSV batch
+API and displays known vulnerabilities grouped by severity (Critical, High, 
Medium, Low).
+
+Each vulnerability shows the CVE ID, affected artifact, the direct dependency 
that pulls it in (VIA column),
+and a summary. Select a CVE to see full details including CVSS vector, 
published date, fixed versions,
+and aliases. Results are cached globally -- switching integrations that share 
JARs is instant.
+
+=== Kafka
+
+The Kafka tab (under More > Data) provides a dedicated view for Kafka 
consumers and their connectivity
+status. It shows consumer group details, topic assignments, partition offsets, 
and reconnection state.
+When a broker connection drops, the Recovery Tasks tab shows the reconnection 
task with its
+Waiting/Attempting status, retry count, and error details.
+
+=== SQL Query and SQL Trace
+
+When your integration includes a DataSource, two SQL tabs appear under More > 
Data:
+
+* *SQL Query* -- an interactive SQL console where you can write and execute 
queries against any
+  DataSource in your integration. Results are displayed as a formatted table 
with column types.
+* *SQL Trace* -- captures and displays SQL statements executed by your routes 
in real-time,
+  showing query text, execution time, and the route that triggered them.
+
+=== Memory Leak Detection
+
+The Memory Leak tab (under More > JVM) uses Java Flight Recorder (JFR) to 
diagnose memory leaks
+in your running integration. It runs two sequential recordings and compares 
object retention trends,
+classifying each class as growing, stable, shrinking, new, or gone. This is 
lightweight and safe
+for production use.
+
+=== Catalog
+
+The Catalog tab (under More > Project) lets you browse the full Camel 
component catalog from within
+the TUI. Search for components by name, view their documentation, options, and 
supported headers --
+useful when building routes and you need to check what options a component 
supports.
+
 == AI Integration (MCP)
 
 The TUI includes an embedded https://modelcontextprotocol.io/[MCP] (Model 
Context Protocol)
@@ -592,7 +728,7 @@ vhs demo.tape               # .tape -> .gif
 | `100`
 
 | `--theme`
-| Color theme for this session: `dark` or `light`. Overrides the persisted 
`camel.tui.theme` preference when set.
+| Color theme for this session (e.g., `dark`, `tokyo-night`, `dracula`). See 
<<Theme>> for the full list of 15 themes. Overrides the persisted 
`camel.tui.theme` preference when set.
 |
 
 | `--record`
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/ConsumersTab.java
 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/ConsumersTab.java
index 6942081fdd18..ee8997034b60 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/ConsumersTab.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/ConsumersTab.java
@@ -26,8 +26,6 @@ import dev.tamboui.layout.Rect;
 import dev.tamboui.style.Style;
 import dev.tamboui.terminal.Frame;
 import dev.tamboui.text.Span;
-import dev.tamboui.tui.event.KeyCode;
-import dev.tamboui.tui.event.KeyEvent;
 import dev.tamboui.tui.event.MouseEvent;
 import dev.tamboui.widgets.block.Block;
 import dev.tamboui.widgets.block.BorderType;
@@ -46,24 +44,6 @@ class ConsumersTab extends AbstractTableTab {
         super(ctx, "id", "status", "type", "remote", "inflight", "polls", 
"uri");
     }
 
-    @Override
-    public void navigateUp() {
-    }
-
-    @Override
-    public void navigateDown() {
-    }
-
-    @Override
-    public boolean handleKeyEvent(KeyEvent ke) {
-        if (ke.isPageUp() || ke.isKey(KeyCode.PAGE_UP)
-                || ke.isPageDown() || ke.isKey(KeyCode.PAGE_DOWN)
-                || ke.isHome() || ke.isEnd()) {
-            return false;
-        }
-        return super.handleKeyEvent(ke);
-    }
-
     @Override
     public boolean handleMouseEvent(MouseEvent me, Rect area) {
         return false;
@@ -136,6 +116,8 @@ class ConsumersTab extends AbstractTableTab {
                         Constraint.length(8),
                         Constraint.length(22),
                         Constraint.fill())
+                .highlightStyle(Theme.selectionBg())
+                .highlightSpacing(Table.HighlightSpacing.ALWAYS)
                 
.block(Block.builder().borderType(BorderType.ROUNDED).borders(Borders.ALL)
                         .title(" Consumers ").build())
                 .build();
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/CveAuditTab.java
 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/CveAuditTab.java
index 9e4bc931196e..a158921ef7d4 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/CveAuditTab.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/CveAuditTab.java
@@ -66,7 +66,7 @@ class CveAuditTab extends AbstractTableTab {
     private int scannedCount;
 
     CveAuditTab(MonitorContext ctx) {
-        super(ctx, "severity", "id", "artifact");
+        super(ctx, "severity", "id", "artifact", "via");
     }
 
     @Override
@@ -209,22 +209,21 @@ class CveAuditTab extends AbstractTableTab {
             String firstParent = group.affectedGavs.isEmpty() ? null : 
group.gavParents.get(firstArtifact);
             int artCount = group.affectedGavs.size();
             String artDisplay = firstArtifact;
-            if (firstParent != null) {
-                artDisplay += " (via " + firstParent + ")";
-            }
             if (artCount > 1) {
                 artDisplay += " (+" + (artCount - 1) + ")";
             }
+            String viaDisplay = firstParent != null ? firstParent : "";
 
             rows.add(Row.from(
                     Cell.from(Span.styled(group.severity != null ? 
group.severity : "", severityStyle(group.severity))),
                     Cell.from(Span.styled(group.canonicalId != null ? 
group.canonicalId : "", Style.EMPTY.bold())),
                     Cell.from(Span.styled(artDisplay, 
Style.EMPTY.fg(Theme.accent()))),
+                    Cell.from(Span.styled(viaDisplay, Style.EMPTY.dim())),
                     Cell.from(Span.styled(group.summary != null ? 
group.summary : "", Style.EMPTY.dim()))));
         }
 
         if (rows.isEmpty() && dataLoaded) {
-            rows.add(emptyRow("No matching vulnerabilities", 4));
+            rows.add(emptyRow("No matching vulnerabilities", 5));
         }
 
         String title = buildTitle();
@@ -235,11 +234,13 @@ class CveAuditTab extends AbstractTableTab {
                         Cell.from(Span.styled(sortLabel("SEVERITY", 
"severity"), sortStyle("severity"))),
                         Cell.from(Span.styled(sortLabel("CVE ID", "id"), 
sortStyle("id"))),
                         Cell.from(Span.styled(sortLabel("ARTIFACT", 
"artifact"), sortStyle("artifact"))),
+                        Cell.from(Span.styled(sortLabel("VIA", "via"), 
sortStyle("via"))),
                         Cell.from(Span.styled("SUMMARY", Style.EMPTY.dim()))))
                 .widths(
                         Constraint.length(10),
-                        Constraint.length(20),
-                        Constraint.percentage(30),
+                        Constraint.length(16),
+                        Constraint.percentage(25),
+                        Constraint.percentage(15),
                         Constraint.fill())
                 .highlightStyle(Theme.selectionBg())
                 .highlightSpacing(Table.HighlightSpacing.ALWAYS)
@@ -448,6 +449,7 @@ class CveAuditTab extends AbstractTableTab {
                 case "artifact" -> compareStr(
                         a.affectedGavs.isEmpty() ? "" : a.affectedGavs.get(0),
                         b.affectedGavs.isEmpty() ? "" : b.affectedGavs.get(0));
+                case "via" -> compareStr(firstParent(a), firstParent(b));
                 default -> Integer.compare(severityIndex(a.severity), 
severityIndex(b.severity));
             };
             return sortReversed ? -cmp : cmp;
@@ -534,6 +536,14 @@ class CveAuditTab extends AbstractTableTab {
         };
     }
 
+    private static String firstParent(VulnGroup g) {
+        if (g.affectedGavs.isEmpty()) {
+            return "";
+        }
+        String parent = g.gavParents.get(g.affectedGavs.get(0));
+        return parent != null ? parent : "";
+    }
+
     private static int severityIndex(String severity) {
         int idx = SEVERITY_ORDER.indexOf(severity);
         return idx >= 0 ? idx : SEVERITY_ORDER.size();
@@ -574,6 +584,7 @@ class CveAuditTab extends AbstractTableTab {
                 - **SEVERITY** — CRITICAL (red), HIGH (red), MEDIUM (yellow), 
LOW (dim)
                 - **CVE ID** — the canonical vulnerability identifier (prefers 
CVE- over GHSA-)
                 - **ARTIFACT** — the affected Maven artifact 
(groupId:artifactId:version)
+                - **VIA** — the direct dependency that pulls in the affected 
artifact (transitive dependency chain)
                 - **SUMMARY** — brief description of the vulnerability
 
                 ## Detail View
@@ -612,6 +623,7 @@ class CveAuditTab extends AbstractTableTab {
             JsonObject row = new JsonObject();
             row.put("cveId", g.canonicalId);
             row.put("severity", g.severity);
+            row.put("via", firstParent(g));
             row.put("summary", g.summary);
             row.put("published", g.published);
             JsonArray arts = new JsonArray();
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/HealthTab.java
 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/HealthTab.java
index 3fe734b5bc08..5f431b57049b 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/HealthTab.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/HealthTab.java
@@ -24,7 +24,6 @@ import dev.tamboui.layout.Rect;
 import dev.tamboui.style.Style;
 import dev.tamboui.terminal.Frame;
 import dev.tamboui.text.Span;
-import dev.tamboui.tui.event.KeyCode;
 import dev.tamboui.tui.event.KeyEvent;
 import dev.tamboui.tui.event.MouseEvent;
 import dev.tamboui.widgets.block.Block;
@@ -48,24 +47,6 @@ class HealthTab extends AbstractTableTab {
         sort = "name";
     }
 
-    @Override
-    public void navigateUp() {
-    }
-
-    @Override
-    public void navigateDown() {
-    }
-
-    @Override
-    public boolean handleKeyEvent(KeyEvent ke) {
-        if (ke.isPageUp() || ke.isKey(KeyCode.PAGE_UP)
-                || ke.isPageDown() || ke.isKey(KeyCode.PAGE_DOWN)
-                || ke.isHome() || ke.isEnd()) {
-            return false;
-        }
-        return super.handleKeyEvent(ke);
-    }
-
     @Override
     public boolean handleMouseEvent(MouseEvent me, Rect area) {
         return false;
@@ -150,6 +131,8 @@ class HealthTab extends AbstractTableTab {
                         Constraint.length(12),
                         Constraint.length(6),
                         Constraint.fill())
+                .highlightStyle(Theme.selectionBg())
+                .highlightSpacing(Table.HighlightSpacing.ALWAYS)
                 
.block(Block.builder().borderType(BorderType.ROUNDED).borders(Borders.ALL).title(title).build())
                 .build();
 
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/InflightTab.java
 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/InflightTab.java
index e38f1da51b30..5c0a5d2cf13c 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/InflightTab.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/InflightTab.java
@@ -26,8 +26,6 @@ import dev.tamboui.terminal.Frame;
 import dev.tamboui.text.Line;
 import dev.tamboui.text.Span;
 import dev.tamboui.text.Text;
-import dev.tamboui.tui.event.KeyCode;
-import dev.tamboui.tui.event.KeyEvent;
 import dev.tamboui.tui.event.MouseEvent;
 import dev.tamboui.widgets.block.Block;
 import dev.tamboui.widgets.block.BorderType;
@@ -57,24 +55,6 @@ class InflightTab extends AbstractTableTab {
         sort = "duration";
     }
 
-    @Override
-    public void navigateUp() {
-    }
-
-    @Override
-    public void navigateDown() {
-    }
-
-    @Override
-    public boolean handleKeyEvent(KeyEvent ke) {
-        if (ke.isPageUp() || ke.isKey(KeyCode.PAGE_UP)
-                || ke.isPageDown() || ke.isKey(KeyCode.PAGE_DOWN)
-                || ke.isHome() || ke.isEnd()) {
-            return false;
-        }
-        return super.handleKeyEvent(ke);
-    }
-
     @Override
     public boolean handleMouseEvent(MouseEvent me, Rect area) {
         return false;
@@ -105,7 +85,7 @@ class InflightTab extends AbstractTableTab {
                     ? Theme.error().bold()
                     : Theme.success();
 
-            String duration = TimeUtils.printDuration(ii.duration, true);
+            String duration = TimeUtils.printDuration(ii.duration, false);
             Style durationStyle = durationColor(ii.duration);
 
             String route = ii.atRouteId != null ? ii.atRouteId : "";
@@ -142,6 +122,8 @@ class InflightTab extends AbstractTableTab {
                         Constraint.fill(),
                         Constraint.length(14),
                         Constraint.length(23))
+                .highlightStyle(Theme.selectionBg())
+                .highlightSpacing(Table.HighlightSpacing.ALWAYS)
                 
.block(Block.builder().borderType(BorderType.ROUNDED).borders(Borders.ALL).title(title).build())
                 .build();
 
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/InternalTaskInfo.java
 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/InternalTaskInfo.java
index 23ee67a0615d..11eb5a21c18b 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/InternalTaskInfo.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/InternalTaskInfo.java
@@ -19,6 +19,7 @@ package org.apache.camel.dsl.jbang.core.commands.tui;
 class InternalTaskInfo {
     String name;
     String status;
+    boolean attempting;
     long attempts;
     long delay;
     long elapsed;
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/InternalTasksTab.java
 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/InternalTasksTab.java
index 61c7b476c8f8..7a7b57be39b6 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/InternalTasksTab.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/InternalTasksTab.java
@@ -55,16 +55,18 @@ class InternalTasksTab extends AbstractTableTab {
 
         List<Row> rows = new ArrayList<>();
         for (InternalTaskInfo ti : sorted) {
-            Style statusStyle = statusStyle(ti.status);
+            String statusText = ti.attempting
+                    ? "Attempting" : ("Active".equals(ti.status) ? "Waiting" : 
(ti.status != null ? ti.status : ""));
+            Style statusStyle = ti.attempting ? Theme.warning() : 
statusStyle(ti.status);
             String elapsed = TimeUtils.printAge(ti.elapsed);
             String first = ti.firstTime > 0 ? 
TimeUtils.printSince(ti.firstTime) : "";
-            String last = ti.lastTime > 0 ? TimeUtils.printSince(ti.lastTime, 
true) : "";
+            String last = ti.lastTime > 0 ? TimeUtils.printSince(ti.lastTime) 
: "";
             String next = formatNext(ti.nextTime);
             String error = ti.error != null ? ti.error : "";
 
             rows.add(Row.from(
                     Cell.from(Span.styled(" " + (ti.name != null ? ti.name : 
""), Style.EMPTY.fg(Theme.accent()))),
-                    Cell.from(Span.styled(ti.status != null ? ti.status : "", 
statusStyle)),
+                    Cell.from(Span.styled(statusText, statusStyle)),
                     rightCell(String.valueOf(ti.attempts), 8),
                     rightCell(String.valueOf(ti.delay), 8),
                     Cell.from(elapsed),
@@ -75,7 +77,7 @@ class InternalTasksTab extends AbstractTableTab {
         }
 
         if (rows.isEmpty()) {
-            rows.add(emptyRow("No internal tasks", 9));
+            rows.add(emptyRow("No recovery tasks", 9));
         }
 
         Table table = Table.builder()
@@ -100,8 +102,10 @@ class InternalTasksTab extends AbstractTableTab {
                         Constraint.length(10),
                         Constraint.length(10),
                         Constraint.fill())
+                .highlightStyle(Theme.selectionBg())
+                .highlightSpacing(Table.HighlightSpacing.ALWAYS)
                 
.block(Block.builder().borderType(BorderType.ROUNDED).borders(Borders.ALL)
-                        .title(" Internal Tasks ").build())
+                        .title(" Recovery Tasks ").build())
                 .build();
 
         lastTableArea = area;
@@ -144,36 +148,26 @@ class InternalTasksTab extends AbstractTableTab {
             return "";
         }
         long age = nextTime - System.currentTimeMillis();
-        return TimeUtils.printDuration(age, true);
-    }
-
-    @Override
-    public SelectionContext getSelectionContext() {
-        IntegrationInfo info = ctx.findSelectedIntegration();
-        if (info == null || info.internalTasks.isEmpty()) {
-            return null;
+        if (age <= 0) {
+            return "";
         }
-        List<InternalTaskInfo> sorted = new ArrayList<>(info.internalTasks);
-        sorted.sort(this::sortTask);
-        List<String> items = sorted.stream().map(t -> t.name != null ? t.name 
: "").toList();
-        Integer sel = tableState.selected();
-        return new SelectionContext("table", items, sel != null ? sel : -1, 
items.size(), "Internal Tasks");
+        return TimeUtils.printDuration(age);
     }
 
     @Override
     public String description() {
-        return "Background task registry (reconnections, retries)";
+        return "Recovery and reconnection tasks (retries, leader election)";
     }
 
     @Override
     public String getHelpText() {
         return """
-                # Internal Tasks
+                # Recovery Tasks
 
-                Internal tasks are background operations that Camel components 
schedule
-                for retry and reconnection purposes. For example, when a JMS 
or SMPP
-                connection drops, the component registers an internal task 
that periodically
-                attempts to reconnect.
+                Recovery tasks are background operations that Camel components 
schedule
+                for reconnection and retry purposes. For example, when a Kafka 
broker or
+                JMS connection drops, the component registers a recovery task 
that
+                periodically attempts to reconnect.
 
                 Tasks self-register when they start running and are removed 
when they
                 complete, fail permanently, or exhaust their retry budget. The 
table
@@ -182,7 +176,7 @@ class InternalTasksTab extends AbstractTableTab {
                 ## Table Columns
 
                 - **NAME** — Descriptive name of the task (e.g., connection 
target or component)
-                - **STATUS** — Current state: `Active` (running), `Completed` 
(finished successfully), `Failed` (gave up), `Exhausted` (retry budget spent)
+                - **STATUS** — Current state: `Waiting` (waiting for next 
attempt), `Attempting` (actively trying now), `Completed` (finished 
successfully), `Failed` (gave up), `Exhausted` (retry budget spent)
                 - **ATTEMPTS** — Number of retry attempts made so far
                 - **DELAY** — Current delay between attempts in milliseconds
                 - **ELAPSED** — Total time since the task started
@@ -193,7 +187,7 @@ class InternalTasksTab extends AbstractTableTab {
 
                 ## When Tasks Appear
 
-                You will typically see internal tasks when:
+                You will typically see recovery tasks when:
                 - A messaging broker connection is lost and the consumer is 
reconnecting
                 - A leader election is in progress (e.g., camel-master)
                 - A component is retrying a failed initialization
@@ -215,7 +209,7 @@ class InternalTasksTab extends AbstractTableTab {
             return null;
         }
         JsonObject result = new JsonObject();
-        result.put("tab", "Internal Tasks");
+        result.put("tab", "Recovery Tasks");
         JsonArray rows = new JsonArray();
         List<InternalTaskInfo> sorted = new ArrayList<>(info.internalTasks);
         sorted.sort(this::sortTask);
@@ -223,6 +217,7 @@ class InternalTasksTab extends AbstractTableTab {
             JsonObject row = new JsonObject();
             row.put("name", ti.name);
             row.put("status", ti.status);
+            row.put("attempting", ti.attempting);
             row.put("attempts", ti.attempts);
             row.put("delay", ti.delay);
             row.put("elapsed", ti.elapsed);
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/ProducersTab.java
 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/ProducersTab.java
index dec2525b51d3..c337ff0fbf72 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/ProducersTab.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/ProducersTab.java
@@ -24,8 +24,6 @@ import dev.tamboui.layout.Rect;
 import dev.tamboui.style.Style;
 import dev.tamboui.terminal.Frame;
 import dev.tamboui.text.Span;
-import dev.tamboui.tui.event.KeyCode;
-import dev.tamboui.tui.event.KeyEvent;
 import dev.tamboui.tui.event.MouseEvent;
 import dev.tamboui.widgets.block.Block;
 import dev.tamboui.widgets.block.BorderType;
@@ -44,24 +42,6 @@ class ProducersTab extends AbstractTableTab {
         super(ctx, "route", "status", "type", "uri");
     }
 
-    @Override
-    public void navigateUp() {
-    }
-
-    @Override
-    public void navigateDown() {
-    }
-
-    @Override
-    public boolean handleKeyEvent(KeyEvent ke) {
-        if (ke.isPageUp() || ke.isKey(KeyCode.PAGE_UP)
-                || ke.isPageDown() || ke.isKey(KeyCode.PAGE_DOWN)
-                || ke.isHome() || ke.isEnd()) {
-            return false;
-        }
-        return super.handleKeyEvent(ke);
-    }
-
     @Override
     public boolean handleMouseEvent(MouseEvent me, Rect area) {
         return false;
@@ -109,6 +89,8 @@ class ProducersTab extends AbstractTableTab {
                         Constraint.length(20),
                         Constraint.length(8),
                         Constraint.fill())
+                .highlightStyle(Theme.selectionBg())
+                .highlightSpacing(Table.HighlightSpacing.ALWAYS)
                 
.block(Block.builder().borderType(BorderType.ROUNDED).borders(Borders.ALL)
                         .title(" Producers ").build())
                 .build();
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/StatusParser.java
 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/StatusParser.java
index 014bc2f245b1..493a8f556f58 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/StatusParser.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/StatusParser.java
@@ -471,6 +471,7 @@ final class StatusParser {
                     InternalTaskInfo ti = new InternalTaskInfo();
                     ti.name = tj.getString("name");
                     ti.status = tj.getString("status");
+                    ti.attempting = tj.getBooleanOrDefault("attempting", 
false);
                     ti.attempts = tj.getLongOrDefault("attempts", 0);
                     ti.delay = tj.getLongOrDefault("delay", 0);
                     ti.elapsed = tj.getLongOrDefault("elapsed", 0);
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/TabRegistry.java
 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/TabRegistry.java
index 9bd91d6def4b..0e930a47ef7a 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/TabRegistry.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/TabRegistry.java
@@ -202,7 +202,7 @@ class TabRegistry {
                         List.of(), info -> !info.services.isEmpty()),
                 new MoreTab(TuiIcons.TAB_EVENTS, "Events", "&Exchange Events", 
eventTab, "Observability"),
                 new MoreTab(
-                        TuiIcons.TAB_INTERNAL_TASKS, "Internal Tasks", 
"In&ternal Tasks", internalTasksTab,
+                        TuiIcons.TAB_RECOVERY_TASKS, "Recovery Tasks", 
"&Recovery Tasks", internalTasksTab,
                         "Observability",
                         List.of(), info -> !info.internalTasks.isEmpty()),
                 new MoreTab(
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/TuiIcons.java
 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/TuiIcons.java
index 9858818d9a76..4da9429eebb7 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/TuiIcons.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/TuiIcons.java
@@ -150,7 +150,7 @@ final class TuiIcons {
     static final String TAB_THREADS = "🧵";
     static final String TAB_PRODUCERS = "📤";
     static final String TAB_EVENTS = "📣";
-    static final String TAB_INTERNAL_TASKS = "🔩";
+    static final String TAB_RECOVERY_TASKS = "🔁";
     static final String TAB_ROUTE_CONTROLLER = "🚦";
     static final String TAB_TYPE_CONVERTERS = "🔄";
     static final String TAB_TRANSFORMERS = "🔀";

Reply via email to