diff --git a/ui-electrobun/src/bun/claude-sessions.ts b/ui-electrobun/src/bun/claude-sessions.ts index 95ed501..55658c7 100644 --- a/ui-electrobun/src/bun/claude-sessions.ts +++ b/ui-electrobun/src/bun/claude-sessions.ts @@ -54,9 +54,10 @@ export function listClaudeSessions(cwd: string): ClaudeSessionInfo[] { const stat = statSync(filePath); const sessionId = file.replace(/\.jsonl$/, ""); - // Read first 5 lines for metadata extraction + // Read first 50 lines for metadata extraction (Claude sessions have + // many system/queue/hook events before the first user message) const content = readFileSync(filePath, "utf-8"); - const lines = content.split("\n").slice(0, 5); + const lines = content.split("\n").slice(0, 50); let firstPrompt = ""; let model = ""; @@ -85,7 +86,20 @@ export function listClaudeSessions(cwd: string): ClaudeSessionInfo[] { } } - // Also check for message type wrappers + // Claude session format: type="user" with message.content + if (!firstPrompt && parsed.type === "user" && parsed.message?.content) { + const mc = parsed.message.content; + if (typeof mc === "string") { + firstPrompt = mc; + } else if (Array.isArray(mc)) { + const textBlock = mc.find( + (b: Record) => b.type === "text", + ); + if (textBlock?.text) firstPrompt = String(textBlock.text); + } + } + + // Also check "human" wrapper (older format) if (!firstPrompt && parsed.type === "human" && parsed.message?.content) { const mc = parsed.message.content; if (typeof mc === "string") { @@ -97,6 +111,11 @@ export function listClaudeSessions(cwd: string): ClaudeSessionInfo[] { if (textBlock?.text) firstPrompt = String(textBlock.text); } } + + // Extract model from assistant messages + if (!model && parsed.type === "assistant" && parsed.message?.model) { + model = String(parsed.message.model); + } } catch { // Skip malformed JSONL lines continue; diff --git a/ui-electrobun/src/mainview/App.svelte b/ui-electrobun/src/mainview/App.svelte index 4147e94..dc40181 100644 --- a/ui-electrobun/src/mainview/App.svelte +++ b/ui-electrobun/src/mainview/App.svelte @@ -20,6 +20,7 @@ getProjects, getGroups, getActiveGroupId, + getProjectsForGroup, getActiveGroup, getFilteredProjects, getTotalCostDerived, getTotalTokensDerived, setActiveGroup, @@ -383,7 +384,7 @@ title="{group.name} (Ctrl+{i + 1})" > diff --git a/ui-electrobun/src/mainview/workspace-store.svelte.ts b/ui-electrobun/src/mainview/workspace-store.svelte.ts index 242231d..4800660 100644 --- a/ui-electrobun/src/mainview/workspace-store.svelte.ts +++ b/ui-electrobun/src/mainview/workspace-store.svelte.ts @@ -76,6 +76,11 @@ export function getActiveGroup(): Group { export function getFilteredProjects(): Project[] { return projects.filter(p => (p.groupId ?? 'dev') === activeGroupId); } + +/** Get projects for a specific group (used by GroupStatusDots). */ +export function getProjectsForGroup(groupId: string): Project[] { + return projects.filter(p => (p.groupId ?? 'dev') === groupId); +} export function getTotalCostDerived(): number { return projects.reduce((s, p) => s + p.costUsd, 0); }