Skip to content

Commit 95a93e6

Browse files
authored
Merge pull request #98 from grimmerk/feat/all-session-responses
feat: show assistant responses for all (first 100) sessions
2 parents 105c6b9 + aea4bb4 commit 95a93e6

5 files changed

Lines changed: 22 additions & 18 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changelog
22

3+
## 1.0.64
4+
5+
- Feat: show last assistant response for all sessions (not just active)
6+
37
## 1.0.63
48

59
- Fix: Terminal tab sessions correctly detected as CODEV (not parent terminal)

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "CodeV",
33
"productName": "CodeV",
4-
"version": "1.0.63",
4+
"version": "1.0.64",
55
"description": "Quick switcher for VS Code, Cursor, and Claude Code sessions",
66
"repository": {
77
"type": "git",

src/claude-session-utility.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -981,7 +981,8 @@ export const loadSessionEnrichment = async (sessions: ClaudeSession[]): Promise<
981981

982982
/**
983983
* Load last assistant response for active sessions.
984-
* Uses tail -n 200 to read the end of the JSONL file (fast even on 80MB files: ~19ms).
984+
* Uses tail -n 100 to read the end of the JSONL file (fast even on 80MB files).
985+
* Benchmark: 100 sessions parallel via Promise.all = ~150ms. tail -n 100 finds same hit rate as -n 200.
985986
* Returns a map of sessionId -> last assistant text.
986987
*/
987988
export const loadLastAssistantResponses = async (
@@ -1004,7 +1005,7 @@ export const loadLastAssistantResponses = async (
10041005

10051006
if (!fs.existsSync(jsonlPath)) return;
10061007

1007-
const output = await execPromise(`tail -n 200 "${jsonlPath}" | grep '"type":"assistant"' | tail -1`);
1008+
const output = await execPromise(`tail -n 100 "${jsonlPath}" | grep '"type":"assistant"' | tail -1`);
10081009
if (!output.trim()) return;
10091010

10101011
try {

src/popup.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -500,7 +500,7 @@ const PopupDefaultExample = ({
500500
</div>
501501
)}
502502
<div style={rowStyle}>
503-
<span style={labelStyle}>Session Preview</span>
503+
<span style={labelStyle} title="User prompt display mode. Assistant response (◀ blue text) always shown.">Session Preview</span>
504504
<select
505505
value={sessionDisplayMode}
506506
onChange={(e) => {
@@ -516,6 +516,9 @@ const PopupDefaultExample = ({
516516
<option value="both">First + Last</option>
517517
</select>
518518
</div>
519+
<div style={{ padding: '0 16px 2px', fontSize: '9px', color: '#555' }}>
520+
◀ Assistant response always shown
521+
</div>
519522
<div style={rowStyle}>
520523
<span style={labelStyle} title="Uses Claude Code hooks to detect session state">Session Status <span style={{ fontSize: '10px', color: '#888' }}>(hooks)</span></span>
521524
<label

src/switcher-ui.tsx

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,14 @@ function SwitcherApp() {
382382
setAllSessions(newSessions);
383383
setSessions(sessionSearchValue.trim() ? filterSessionsLocally(newSessions, sessionSearchValue) : newSessions);
384384

385-
// Step 2: Detect active sessions in background (slow, spawns processes)
385+
// Step 2: Load last assistant responses for all sessions (first 100)
386+
window.electronAPI.loadLastAssistantResponses((result || []).slice(0, 100)).then((responses: Record<string, string>) => {
387+
if (responses && Object.keys(responses).length > 0) {
388+
setAssistantResponses((prev: Record<string, string>) => ({ ...prev, ...responses }));
389+
}
390+
});
391+
392+
// Step 3: Detect active sessions in background (slow, spawns processes)
386393
window.electronAPI.detectActiveSessions().then((activeMap: Record<string, number>) => {
387394
// Save to ref for SWR on next refresh
388395
activeStateRef.current = activeMap || {};
@@ -397,17 +404,6 @@ function SwitcherApp() {
397404

398405
if (activeMap && Object.keys(activeMap).length > 0) {
399406

400-
const activeSessions = (result || []).filter((s: any) => s.sessionId in activeMap);
401-
402-
// Step 2b: Load last assistant responses for active sessions only
403-
if (activeSessions.length > 0) {
404-
window.electronAPI.loadLastAssistantResponses(activeSessions).then((responses: Record<string, string>) => {
405-
if (responses && Object.keys(responses).length > 0) {
406-
setAssistantResponses((prev: Record<string, string>) => ({ ...prev, ...responses }));
407-
}
408-
});
409-
}
410-
411407
// Step 2c: Detect terminal apps for active sessions
412408
if (Object.keys(activeMap).length > 0) {
413409
window.electronAPI.detectTerminalApps(activeMap).then((apps: Record<string, string>) => {
@@ -1121,8 +1117,8 @@ function SwitcherApp() {
11211117
)}
11221118
</div>
11231119
)}
1124-
{/* Line 3: Last assistant response (only for active sessions) */}
1125-
{session.isActive && assistantResponses[session.sessionId] && (
1120+
{/* Line 3: Last assistant response */}
1121+
{assistantResponses[session.sessionId] && (
11261122
<div style={{ overflow: 'hidden', whiteSpace: 'nowrap', textOverflow: 'ellipsis', marginTop: '1px' }}>
11271123
<span style={{ color: '#9DC8E0', fontSize: '11px' }}>
11281124
<Highlighter

0 commit comments

Comments
 (0)