Skip to content
Open
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
3 changes: 3 additions & 0 deletions src/main/remote-sessions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ function normalizeCachedSession(row: RemoteRecord): CachedSession {
source: summary.source,
messageCount: summary.messageCount,
model: summary.model,
parentId: null,
};
}

Expand Down Expand Up @@ -304,6 +305,7 @@ export async function remoteSearchSessions(
messageCount: numberValue(row.message_count),
model: stringValue(row.model),
snippet: stringValue(row.snippet),
parentId: null,
};
});

Expand Down Expand Up @@ -354,6 +356,7 @@ async function remoteSearchRecentSessionMessages(
messageCount: session.messageCount,
model: session.model,
snippet: highlightTextMatch(match, query).slice(0, 500),
parentId: null,
} satisfies SearchResult;
} catch {
return null;
Expand Down
7 changes: 6 additions & 1 deletion src/main/session-cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export interface CachedSession {
source: string;
messageCount: number;
model: string;
parentId: string | null;
}

interface CacheData {
Expand Down Expand Up @@ -104,7 +105,7 @@ export function syncSessionCache(): CachedSession[] {
// Fetch sessions newer than last sync, or all if first sync
const rows = db
.prepare(
`SELECT s.id, s.started_at, s.source, s.message_count, s.model, s.title
`SELECT s.id, s.started_at, s.source, s.message_count, s.model, s.title, s.parent_session_id
FROM sessions s
WHERE s.started_at > ?
ORDER BY s.started_at DESC`,
Expand All @@ -116,6 +117,7 @@ export function syncSessionCache(): CachedSession[] {
message_count: number;
model: string;
title: string | null;
parent_session_id: string | null;
}>;

// Index existing sessions by id once so the per-row update below is
Expand All @@ -132,12 +134,14 @@ export function syncSessionCache(): CachedSession[] {
const existing = existingById.get(row.id);
if (existing) {
existing.messageCount = row.message_count;
existing.parentId = row.parent_session_id || null;
if (row.model) existing.model = row.model;
if (row.title) existing.title = row.title;
continue;
}

let title = row.title || "";
const parentId = row.parent_session_id || null;
if (!title) {
try {
const msg = db
Expand All @@ -162,6 +166,7 @@ export function syncSessionCache(): CachedSession[] {
source: row.source,
messageCount: row.message_count,
model: row.model || "",
parentId,
});
}

Expand Down
13 changes: 11 additions & 2 deletions src/main/sessions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ export interface SearchResult {
messageCount: number;
model: string;
snippet: string;
parentId: string | null;
}

export function dedupeSearchRowsBySession<T extends { session_id: string }>(
Expand Down Expand Up @@ -315,7 +316,8 @@ export function searchSessions(query: string, limit = 20): SearchResult[] {
s.started_at,
s.source,
s.message_count,
s.model
s.model,
s.parent_session_id
FROM sessions s
WHERE LOWER(COALESCE(s.title, '')) LIKE ? ESCAPE '\\'
OR LOWER(s.id) LIKE ? ESCAPE '\\'
Expand All @@ -333,6 +335,7 @@ export function searchSessions(query: string, limit = 20): SearchResult[] {
source: string;
message_count: number;
model: string;
parent_session_id: string | null;
}>;

const titleMatches = titleRows.map((r) => ({
Expand Down Expand Up @@ -365,6 +368,7 @@ export function searchSessions(query: string, limit = 20): SearchResult[] {
s.source,
s.message_count,
s.model,
s.parent_session_id,
snippet(messages_fts, 0, '<<', '>>', '...', 40) as snippet
FROM messages_fts
JOIN messages m ON m.id = messages_fts.rowid
Expand All @@ -380,6 +384,7 @@ export function searchSessions(query: string, limit = 20): SearchResult[] {
source: string;
message_count: number;
model: string;
parent_session_id: string | null;
snippet: string;
}>)
: [];
Expand All @@ -394,7 +399,8 @@ export function searchSessions(query: string, limit = 20): SearchResult[] {
s.started_at,
s.source,
s.message_count,
s.model
s.model,
s.parent_session_id
FROM messages m
JOIN sessions s ON s.id = m.session_id
WHERE LOWER(COALESCE(m.content, '')) LIKE ? ESCAPE '\\'
Expand All @@ -413,6 +419,7 @@ export function searchSessions(query: string, limit = 20): SearchResult[] {
source: string;
message_count: number;
model: string;
parent_session_id: string | null;
}>;

const messageMatches = messageRows.map((r) => ({
Expand All @@ -422,6 +429,7 @@ export function searchSessions(query: string, limit = 20): SearchResult[] {
source: r.source,
message_count: r.message_count,
model: r.model,
parent_session_id: r.parent_session_id,
snippet: decodeSearchSnippet(r.content, r.message_id, trimmedQuery),
}));

Expand All @@ -436,6 +444,7 @@ export function searchSessions(query: string, limit = 20): SearchResult[] {
source: r.source,
messageCount: r.message_count,
model: r.model || "",
parentId: r.parent_session_id || null,
snippet: r.snippet || "",
}));
} catch {
Expand Down
1 change: 1 addition & 0 deletions src/main/ssh-remote.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2166,6 +2166,7 @@ export async function sshListCachedSessions(
source: s.source,
messageCount: s.messageCount,
model: s.model,
parentId: null,
}));
}

Expand Down
2 changes: 2 additions & 0 deletions src/preload/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -677,6 +677,7 @@ interface HermesAPI {
source: string;
messageCount: number;
model: string;
parentId: string | null;
}>
>;
syncSessionCache: () => Promise<
Expand All @@ -687,6 +688,7 @@ interface HermesAPI {
source: string;
messageCount: number;
model: string;
parentId: string | null;
}>
>;
updateSessionTitle: (sessionId: string, title: string) => Promise<void>;
Expand Down
2 changes: 2 additions & 0 deletions src/preload/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -853,6 +853,7 @@ const hermesAPI = {
source: string;
messageCount: number;
model: string;
parentId: string | null;
}>
> => ipcRenderer.invoke("list-cached-sessions", limit, offset),

Expand All @@ -864,6 +865,7 @@ const hermesAPI = {
source: string;
messageCount: number;
model: string;
parentId: string | null;
}>
> => ipcRenderer.invoke("sync-session-cache"),

Expand Down
6 changes: 6 additions & 0 deletions src/renderer/src/screens/Sessions/Sessions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ interface CachedSession {
source: string;
messageCount: number;
model: string;
parentId: string | null;
}

interface SearchResult {
Expand Down Expand Up @@ -234,6 +235,11 @@ const SessionCard = memo(function SessionCard({
<span className="sessions-tag sessions-tag--source">
{session.source}
</span>
{session.parentId && (
<span className="sessions-tag sessions-tag--child" title="Agent sub-task">
sub-task
</span>
Comment on lines +239 to +241

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 Missing CSS modifier — badge will be unstyled

The class sessions-tag--child is applied to the sub-task badge, but no corresponding CSS rule exists in src/renderer/src/assets/main.css (only sessions-tag--source and sessions-tag--model are defined there). The PR description promises an "orange" badge, but at runtime the span will fall back entirely to the base .sessions-tag styles, rendering identically to any other tag with no visual differentiation. A rule like .sessions-tag--child { color: orange; font-weight: 500; } (or a CSS variable equivalent) needs to be added to main.css.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

)}
<span className="sessions-tag">
{session.messageCount} msg{session.messageCount !== 1 ? "s" : ""}
</span>
Expand Down