diff --git a/ccw/src/templates/dashboard-js/views/codexlens-manager.js b/ccw/src/templates/dashboard-js/views/codexlens-manager.js
index 23121d4e..5ab25410 100644
--- a/ccw/src/templates/dashboard-js/views/codexlens-manager.js
+++ b/ccw/src/templates/dashboard-js/views/codexlens-manager.js
@@ -24,106 +24,138 @@ function escapeHtml(str) {
/**
* Refresh workspace index status (FTS and Vector coverage)
+ * Updates both the detailed panel (if exists) and header badges
*/
async function refreshWorkspaceIndexStatus() {
var container = document.getElementById('workspaceIndexStatusContent');
- if (!container) return;
+ var headerFtsEl = document.getElementById('headerFtsPercent');
+ var headerVectorEl = document.getElementById('headerVectorPercent');
- // Show loading state
- container.innerHTML = '
';
- if (window.lucide) lucide.createIcons();
+ // If neither container nor header elements exist, nothing to update
+ if (!container && !headerFtsEl) return;
+
+ // Show loading state in container
+ if (container) {
+ container.innerHTML = '
';
+ if (window.lucide) lucide.createIcons();
+ }
try {
var response = await fetch('/api/codexlens/workspace-status');
var result = await response.json();
if (result.success) {
- var html = '';
+ var ftsPercent = result.hasIndex ? (result.fts.percent || 0) : 0;
+ var vectorPercent = result.hasIndex ? (result.vector.percent || 0) : 0;
- if (!result.hasIndex) {
- // No index for current workspace
- html = '
' +
- '
' +
- ' ' +
- (t('codexlens.noIndexFound') || 'No index found for current workspace') +
- '
';
+ }
}
if (window.lucide) lucide.createIcons();
@@ -3884,32 +3916,45 @@ async function renderCodexLensManager() {
// Load additional data in parallel (non-blocking)
var isInstalled = window.cliToolsStatus?.codexlens?.installed || dashboardData?.installed;
+ // OPTIMIZATION: Load critical status first (workspace index status for header badges)
+ // This is prioritized as it updates the visible header immediately
+ if (isInstalled) {
+ refreshWorkspaceIndexStatus(); // Updates header FTS/Vector badges
+ }
+
// Wait for LiteLLM config before loading semantic deps (it may need provider info)
await litellmPromise;
- // Load FastEmbed installation status (show/hide install card)
- loadFastEmbedInstallStatus();
+ // OPTIMIZATION: Batch non-critical loads with requestIdleCallback or setTimeout
+ // This prevents blocking the main thread and allows smoother UI updates
+ var deferredLoads = function() {
+ // Load all independent status checks in parallel
+ Promise.all([
+ // FastEmbed and semantic deps status (independent)
+ Promise.resolve().then(function() { loadFastEmbedInstallStatus(); }),
+ Promise.resolve().then(function() { loadSemanticDepsStatus(); }),
+ // Model lists (independent)
+ Promise.resolve().then(function() { loadModelList(); }),
+ Promise.resolve().then(function() { loadRerankerModelList(); }),
+ // File watcher status (independent)
+ Promise.resolve().then(function() { initWatcherStatus(); })
+ ]).then(function() {
+ // After all loads complete, update the semantic status badge
+ updateSemanticStatusBadge();
+ });
- // Always load semantic deps status - it needs GPU detection and device list
- // which are not included in the aggregated endpoint
- loadSemanticDepsStatus();
+ // Load index stats if installed (independent from above)
+ if (isInstalled) {
+ loadIndexStatsForPage();
+ checkIndexHealth();
+ }
+ };
- loadModelList();
- loadRerankerModelList();
-
- // Initialize model mode and semantic status badge
- updateSemanticStatusBadge();
-
- // Initialize file watcher status
- initWatcherStatus();
-
- // Load index stats for the Index Manager section
- if (isInstalled) {
- loadIndexStatsForPage();
- // Check index health based on git history
- checkIndexHealth();
- // Load workspace index status (FTS and Vector coverage)
- refreshWorkspaceIndexStatus();
+ // Use requestIdleCallback for deferred loads if available, otherwise use setTimeout
+ if (typeof requestIdleCallback === 'function') {
+ requestIdleCallback(deferredLoads, { timeout: 500 });
+ } else {
+ setTimeout(deferredLoads, 50);
}
} catch (err) {
container.innerHTML = '