Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion src/data.js
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ function parseKiloMcpServer(toolName) {
}

// Disk cache for parsed Claude session files (keyed by path + mtime + size)
const PARSED_CACHE_FILE = path.join(os.tmpdir(), 'codedash-parsed-cache.json');
const PARSED_CACHE_FILE = path.join(os.tmpdir(), 'codedash-parsed-cache-v2.json');
let _parsedDiskCache = null;
let _parsedDiskCacheDirty = false;
// Reverse index: file path -> cache key (avoids repeated fs.statSync)
Expand Down Expand Up @@ -318,6 +318,7 @@ function parseClaudeSessionFile(sessionFile) {
let totalUserMsgs = 0; // all user-type messages (including tool_result, sub-agents)
let entrypointFound = false;
let worktreeOriginalCwd = '';
let lastRecap = '';
const mcpSet = new Set();
const skillSet = new Set();

Expand Down Expand Up @@ -347,6 +348,10 @@ function parseClaudeSessionFile(sessionFile) {
const title = entry.customTitle.trim();
if (title) customTitle = title.slice(0, 200);
}
if (entry.type === 'system' && entry.subtype === 'away_summary') {
const txt = (entry.content || '').trim();
if (txt) lastRecap = txt.slice(0, 300);
}
if (!firstMsg && entry.type === 'user' && entry.message && entry.message.content) {
const content = extractContent(entry.message.content).trim();
if (content) firstMsg = content.slice(0, 200);
Expand Down Expand Up @@ -383,6 +388,7 @@ function parseClaudeSessionFile(sessionFile) {
lastTs,
fileSize: stat.size,
worktreeOriginalCwd,
lastRecap,
mcpServers: Array.from(mcpSet),
skills: Array.from(skillSet),
};
Expand Down Expand Up @@ -418,6 +424,10 @@ function mergeClaudeSessionDetail(session, summary, sessionFile) {
if (summary.customTitle) {
session.session_name = summary.customTitle;
}

if (summary.lastRecap) {
session.recap = summary.lastRecap;
}
}

function parseCodexSessionIndex(codexDir) {
Expand Down Expand Up @@ -1867,6 +1877,7 @@ function loadSessions() {
_claude_dir: extraClaudeDir,
_session_file: fp,
worktree_original_cwd: summary.worktreeOriginalCwd || '',
recap: summary.lastRecap || '',
};
}
}
Expand Down Expand Up @@ -1940,6 +1951,7 @@ function loadSessions() {
_claude_dir: CLAUDE_DIR,
_session_file: filePath,
worktree_original_cwd: summary.worktreeOriginalCwd || '',
recap: summary.lastRecap || '',
};
}
}
Expand Down
11 changes: 10 additions & 1 deletion src/frontend/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,16 @@ function getSessionGroupInfo(session) {
return { key: name, name: name };
}

function stripRecapSuffix(s) {
return (s || '').replace(/\s*\(disable recaps in \/config\)\s*$/, '');
}

function getSessionDisplayName(session) {
if (!session) return '';
return session.session_name || session.first_message || '';
return session.session_name
|| stripRecapSuffix(session.recap)
|| session.first_message
|| '';
}

// ── Utilities ──────────────────────────────────────────────────
Expand Down Expand Up @@ -601,6 +608,7 @@ function searchScore(query, session) {
var q = query.toLowerCase();
var fields = [
session.session_name || '',
session.recap || '',
session.first_message || '',
session.project_short || '',
session.project || '',
Expand Down Expand Up @@ -1220,6 +1228,7 @@ async function confirmDelete() {
var remaining = allSessions.filter(function(s) {
return (s.project || '').toLowerCase().indexOf(searchQuery.toLowerCase()) >= 0 ||
(s.session_name || '').toLowerCase().indexOf(searchQuery.toLowerCase()) >= 0 ||
(s.recap || '').toLowerCase().indexOf(searchQuery.toLowerCase()) >= 0 ||
(s.first_message || '').toLowerCase().indexOf(searchQuery.toLowerCase()) >= 0;
});
if (remaining.length === 0) {
Expand Down
4 changes: 2 additions & 2 deletions src/frontend/cloud.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ async function renderCloud(container) {
var btnHtml = inCloud
? '<span class="dim" style="font-size:10px;white-space:nowrap;">in cloud</span>'
: '<button class="launch-btn btn-primary" style="padding:3px 8px;font-size:10px;" onclick="cloudPushOne(\'' + ls.id + '\',this)">Push</button>';
html += cloudRow(ls.tool, ((ls.session_name || ls.first_message || ls.id)).substring(0, 60), sub, btnHtml);
html += cloudRow(ls.tool, ((ls.session_name || stripRecapSuffix(ls.recap) || ls.first_message || ls.id)).substring(0, 60), sub, btnHtml);
}
} else {
html += '<div class="dim" style="text-align:center;padding:20px;font-size:12px;">Loading...</div>';
Expand All @@ -116,7 +116,7 @@ async function renderCloud(container) {
var csSub = (cs.project_short || '') + ' \u00b7 ' + cs.message_count + ' msgs \u00b7 ' + csDate;
var csBtns = '<button class="launch-btn btn-secondary" style="padding:3px 8px;font-size:10px;" onclick="cloudPullOne(\'' + cs.session_id + '\',this)">Pull</button>';
csBtns += '<button class="launch-btn btn-delete" style="padding:3px 6px;font-size:10px;" onclick="deleteCloudSession(\'' + cs.session_id + '\')">&times;</button>';
html += cloudRow(cs.agent, ((cs.session_name || cs.first_message || cs.session_id)).substring(0, 60), csSub, csBtns);
html += cloudRow(cs.agent, ((cs.session_name || stripRecapSuffix(cs.recap) || cs.first_message || cs.session_id)).substring(0, 60), csSub, csBtns);
}
}
html += '</div></div>';
Expand Down