Skip to content

Superseded by #378#377

Closed
GizAI wants to merge 1 commit intositeboon:mainfrom
GizAI:perf/project-cache
Closed

Superseded by #378#377
GizAI wants to merge 1 commit intositeboon:mainfrom
GizAI:perf/project-cache

Conversation

@GizAI
Copy link

@GizAI GizAI commented Feb 11, 2026

Superseded by #378:
#378

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 11, 2026

Walkthrough

The changes refactor project discovery and session indexing in server/projects.js, adding utilities for codex session handling, path normalization, and session aggregation across multiple Claude projects. Concurrently, src/App.jsx removes redundant per-project cursor session API calls. Public API signatures remain unchanged.

Changes

Cohort / File(s) Summary
Project Discovery & Session Indexing Rework
server/projects.js
Substantial refactoring introducing new helper utilities for codex session handling (path normalization, message extraction, system message filtering, summarization, JSONL tail-reading). Adds codex sessions index builder and lookup helpers mapping Codex sessions to project paths with per-project limits. Extends session previews to support aggregation across multiple Claude projects with caching and error handling. Enhances TaskMaster detection, adds manual project support with progress-emission hooks, and introduces logic for project path hints, multiple cwd handling, and last-activity tracking. Augments deletion pathways for Codex and Cursor sessions.
Cursor Sessions API Optimization
src/App.jsx
Removes per-project API call loop that fetched Cursor sessions for every project; fetchProjects now updates state directly from response without cursor session enrichment, eliminating redundant network requests.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • Add loading progress indicator #311: Modifies server/projects.js getProjects to add progress-emission (progressCallback) during project loading—the new progress hooks in this PR directly relate to progress-callback broadcast changes.

Suggested reviewers

  • viper151

Poem

🐰 Sessions sorted, pathways blessed,
Codex sessions put to rest,
Cursor calls cut clean away,
Projects load with less delay!

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 15.38% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main optimization: speeding up project/session loading without adding cache, which aligns with the substantial refactoring of project discovery and session indexing.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

Issue Planner is now in beta. Read the docs and try it out! Share your feedback on Discord.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@GizAI GizAI closed this Feb 11, 2026
@GizAI GizAI deleted the perf/project-cache branch February 11, 2026 04:53
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@server/projects.js`:
- Around line 395-398: The early-exit in the loop that checks "if (sessions.size
>= targetSessionCount && !truncatedReadDetected) { break; }" can make total and
hasMore under-report because remaining files aren't scanned; update the logic in
the function that computes total/hasMore (referencing sessions,
targetSessionCount, truncatedReadDetected, total, hasMore, scannedFiles,
filesWithStats.length) to either document that total is a lower bound when the
loop breaks early or explicitly set hasMore = true whenever scannedFiles <
filesWithStats.length (and truncatedReadDetected is false) so consumers know
more sessions may exist; ensure this change is applied where total and hasMore
are assigned after the loop.
🧹 Nitpick comments (5)
server/projects.js (5)

356-363: Avoid repeated Date construction in a hot inner loop.

In a PR focused on performance, constructing two new Date() objects per entry with a timestamp is wasteful. ISO 8601 strings are lexicographically comparable, so a direct string comparison suffices here.

♻️ Proposed fix
         if (entry.timestamp) {
           const timestamp = new Date(entry.timestamp);
           if (!Number.isNaN(timestamp.getTime())) {
             const currentTime = timestamp.toISOString();
-            if (!session.lastActivity || new Date(currentTime) > new Date(session.lastActivity)) {
+            if (!session.lastActivity || currentTime > session.lastActivity) {
               session.lastActivity = currentTime;
             }
           }
         }

234-256: Duplicated system-message detection logic.

isSystemUserMessage / isSystemAssistantMessage (Lines 234-256) duplicate the inline checks in parseJsonlSessions (Lines 1062-1102). Consider reusing the extracted helpers in parseJsonlSessions to keep the filter predicates in a single place.

Also applies to: 1062-1102


446-462: Triplicated recursive JSONL file finder.

findJsonlFilesRecursive duplicates identical inline functions in getCodexSessions (Line 1543) and deleteCodexSession (Line 1914). Consider reusing this top-level helper in both places.


760-813: getSessionsPreview + getCursorSessions are sequential per project.

Each project awaits getSessionsPreview (I/O-heavy tail reads) sequentially. For users with many projects, consider batching with bounded concurrency (e.g., Promise.all over small chunks) to overlap I/O. Not a blocker given the current PROJECT_PREVIEW_MAX_FILES = 12 cap, but worth considering if startup remains slow for large project counts.


1136-1143: Dead debug code in parseJsonlSessions.

The Math.random() < 0.01 branch (Line 1140) and the empty if (shouldFilter) block (Lines 1137-1138) appear to be leftover debug scaffolding with no actual logging statements. This predates the current PR but is worth cleaning up.

♻️ Suggested cleanup
     const filteredSessions = allSessions.filter(session => {
-      const shouldFilter = session.summary.startsWith('{ "');
-      if (shouldFilter) {
-      }
-      // Log a sample of summaries to debug
-      if (Math.random() < 0.01) { // Log 1% of sessions
-      }
-      return !shouldFilter;
+      return !session.summary.startsWith('{ "');
     });

Comment on lines +395 to +398
if (sessions.size >= targetSessionCount && !truncatedReadDetected) {
break;
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Early-exit condition may under-report total and hasMore.

When sessions.size >= targetSessionCount and no truncation occurred, the loop breaks before scanning remaining files. This means total (Line 419) reflects only sessions found so far, and hasMore (Line 422) could be false even though un-scanned files may contain additional sessions. This is probably acceptable for a preview, but the consumer should be aware that total is a lower bound when not all files are scanned.

Consider documenting this or always setting hasMore = true when scannedFiles < filesWithStats.length.

♻️ Suggested adjustment
-    const scannedAllFiles = scannedFiles >= filesWithStats.length && !truncatedReadDetected;
-    const hasMore = scannedAllFiles ? (offset + limit < total) : true;
+    const scannedAllFiles = scannedFiles >= filesWithStats.length && !truncatedReadDetected;
+    const hasMore = !scannedAllFiles || (offset + limit < total);

(This is functionally equivalent to the current code—just confirming the intent is correct and making it slightly more readable.)

🤖 Prompt for AI Agents
In `@server/projects.js` around lines 395 - 398, The early-exit in the loop that
checks "if (sessions.size >= targetSessionCount && !truncatedReadDetected) {
break; }" can make total and hasMore under-report because remaining files aren't
scanned; update the logic in the function that computes total/hasMore
(referencing sessions, targetSessionCount, truncatedReadDetected, total,
hasMore, scannedFiles, filesWithStats.length) to either document that total is a
lower bound when the loop breaks early or explicitly set hasMore = true whenever
scannedFiles < filesWithStats.length (and truncatedReadDetected is false) so
consumers know more sessions may exist; ensure this change is applied where
total and hasMore are assigned after the loop.

@GizAI GizAI changed the title perf: speed up project/session loading without adding cache Superseded by #378 Feb 11, 2026
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