Refactor contextHook to simplify recent summaries retrieval and output formatting
- Updated contextHook to query session_summaries directly instead of using sdk_sessions table. - Removed unnecessary complexity in output formatting, focusing on recent summaries for the project. - Enhanced file reading and modification tracking by parsing observations directly. - Made the database connection public in SessionStore for easier access.
This commit is contained in:
+63
-240
@@ -26,12 +26,9 @@ const colors = {
|
||||
|
||||
/**
|
||||
* Context Hook - SessionStart
|
||||
* Shows user what happened in recent sessions
|
||||
*
|
||||
* Output: Returns formatted context string to be wrapped in hookSpecificOutput
|
||||
* Shows recent summaries for the project
|
||||
*/
|
||||
export function contextHook(input?: SessionStartInput, useColors: boolean = false, useIndexView: boolean = false): string {
|
||||
// v4.0.0: Ensure worker is running before loading context
|
||||
ensureWorkerRunning();
|
||||
const cwd = input?.cwd ?? process.cwd();
|
||||
const project = cwd ? path.basename(cwd) : 'unknown-project';
|
||||
@@ -39,260 +36,86 @@ export function contextHook(input?: SessionStartInput, useColors: boolean = fals
|
||||
const db = new SessionStore();
|
||||
|
||||
try {
|
||||
const summaries = db.getRecentSummariesWithSessionInfo(project, 3);
|
||||
// Query session_summaries directly - no need for sdk_sessions table
|
||||
const summaries = db.db.prepare(`
|
||||
SELECT sdk_session_id, request, learned, completed, next_steps, created_at
|
||||
FROM session_summaries
|
||||
WHERE project = ?
|
||||
ORDER BY created_at_epoch DESC
|
||||
LIMIT 3
|
||||
`).all(project) as Array<{
|
||||
sdk_session_id: string;
|
||||
request: string | null;
|
||||
learned: string | null;
|
||||
completed: string | null;
|
||||
next_steps: string | null;
|
||||
created_at: string;
|
||||
}>;
|
||||
|
||||
if (summaries.length === 0) {
|
||||
if (useColors) {
|
||||
return `\n${colors.bright}${colors.cyan}📝 [${project}] recent context${colors.reset}\n${colors.gray}${'─'.repeat(60)}${colors.reset}\n\n${colors.dim}No previous summaries found for this project yet.${colors.reset}\n`;
|
||||
}
|
||||
return `# [${project}] recent context\n\nNo previous summaries found for this project yet.`;
|
||||
}
|
||||
|
||||
const output: string[] = [];
|
||||
|
||||
// Index view: Show previous as index, latest in full at bottom (chat-style)
|
||||
if (useIndexView) {
|
||||
if (useColors) {
|
||||
output.push('');
|
||||
output.push(`${colors.bright}${colors.cyan}📝 [${project}] recent context${colors.reset}`);
|
||||
output.push(`${colors.gray}${'─'.repeat(60)}${colors.reset}`);
|
||||
output.push('');
|
||||
} else {
|
||||
output.push(`# [${project}] recent context`);
|
||||
output.push('');
|
||||
}
|
||||
|
||||
// Show index of previous summaries (oldest to newest)
|
||||
if (summaries.length > 1) {
|
||||
if (useColors) {
|
||||
output.push(`${colors.bright}${colors.dim}Previous Requests:${colors.reset}`);
|
||||
output.push('');
|
||||
} else {
|
||||
output.push('**Previous Requests:**');
|
||||
output.push('');
|
||||
}
|
||||
|
||||
// Iterate backwards through array (skip first which is most recent)
|
||||
for (let i = summaries.length - 1; i >= 1; i--) {
|
||||
const prev = summaries[i];
|
||||
const prevDate = new Date(prev.created_at);
|
||||
const dateTimeStr = prevDate.toLocaleString();
|
||||
|
||||
if (useColors) {
|
||||
output.push(`${colors.dim}• ${dateTimeStr}:${colors.reset} ${prev.request || '(no request)'}`);
|
||||
} else {
|
||||
output.push(`- ${dateTimeStr}: ${prev.request || '(no request)'}`);
|
||||
}
|
||||
}
|
||||
|
||||
if (useColors) {
|
||||
output.push('');
|
||||
output.push(`${colors.gray}${'─'.repeat(60)}${colors.reset}`);
|
||||
output.push('');
|
||||
} else {
|
||||
output.push('');
|
||||
output.push('---');
|
||||
output.push('');
|
||||
}
|
||||
}
|
||||
|
||||
// Show most recent summary in full at the bottom
|
||||
const latest = summaries[0];
|
||||
|
||||
if (latest.request) {
|
||||
if (useColors) {
|
||||
output.push(`${colors.bright}${colors.yellow}Request:${colors.reset} ${latest.request}`);
|
||||
output.push('');
|
||||
} else {
|
||||
output.push(`**Request:** ${latest.request}`);
|
||||
output.push('');
|
||||
}
|
||||
}
|
||||
|
||||
if (latest.learned) {
|
||||
if (useColors) {
|
||||
output.push(`${colors.bright}${colors.blue}Learned:${colors.reset} ${latest.learned}`);
|
||||
output.push('');
|
||||
} else {
|
||||
output.push(`**Learned:** ${latest.learned}`);
|
||||
output.push('');
|
||||
}
|
||||
}
|
||||
|
||||
if (latest.completed) {
|
||||
if (useColors) {
|
||||
output.push(`${colors.bright}${colors.green}Completed:${colors.reset} ${latest.completed}`);
|
||||
output.push('');
|
||||
} else {
|
||||
output.push(`**Completed:** ${latest.completed}`);
|
||||
output.push('');
|
||||
}
|
||||
}
|
||||
|
||||
if (latest.next_steps) {
|
||||
if (useColors) {
|
||||
output.push(`${colors.bright}${colors.magenta}Next Steps:${colors.reset} ${latest.next_steps}`);
|
||||
output.push('');
|
||||
} else {
|
||||
output.push(`**Next Steps:** ${latest.next_steps}`);
|
||||
output.push('');
|
||||
}
|
||||
}
|
||||
|
||||
// Get files for latest summary
|
||||
const latestFiles = db.getFilesForSession(latest.sdk_session_id);
|
||||
|
||||
if (latestFiles.filesRead.length > 0) {
|
||||
if (useColors) {
|
||||
output.push(`${colors.dim}Files Read: ${latestFiles.filesRead.join(', ')}${colors.reset}`);
|
||||
} else {
|
||||
output.push(`**Files Read:** ${latestFiles.filesRead.join(', ')}`);
|
||||
}
|
||||
}
|
||||
|
||||
if (latestFiles.filesModified.length > 0) {
|
||||
if (useColors) {
|
||||
output.push(`${colors.dim}Files Modified: ${latestFiles.filesModified.join(', ')}${colors.reset}`);
|
||||
} else {
|
||||
output.push(`**Files Modified:** ${latestFiles.filesModified.join(', ')}`);
|
||||
}
|
||||
}
|
||||
|
||||
const latestDate = new Date(latest.created_at).toLocaleString();
|
||||
if (useColors) {
|
||||
output.push(`${colors.dim}Date: ${latestDate}${colors.reset}`);
|
||||
} else {
|
||||
output.push(`**Date:** ${latestDate}`);
|
||||
}
|
||||
|
||||
if (useColors) {
|
||||
output.push('');
|
||||
output.push(`${colors.gray}${'─'.repeat(60)}${colors.reset}`);
|
||||
}
|
||||
|
||||
return output.join('\n');
|
||||
}
|
||||
|
||||
if (useColors) {
|
||||
output.push('');
|
||||
output.push(`${colors.bright}${colors.cyan}📝 [${project}] recent context${colors.reset}`);
|
||||
output.push(`${colors.gray}${'─'.repeat(60)}${colors.reset}`);
|
||||
} else {
|
||||
output.push(`# [${project}] recent context`);
|
||||
output.push('');
|
||||
}
|
||||
output.push(`# [${project}] recent context`);
|
||||
output.push('');
|
||||
|
||||
let previousSessionId: string | null = null;
|
||||
let isFirstSummary = true;
|
||||
|
||||
for (const summary of summaries) {
|
||||
// Add session break indicator if this is a different session
|
||||
const isNewSession = previousSessionId !== null && summary.sdk_session_id !== previousSessionId;
|
||||
|
||||
if (isNewSession) {
|
||||
if (useColors) {
|
||||
output.push('');
|
||||
output.push(`${colors.dim}${'─'.repeat(23)} New Session ${'─'.repeat(24)}${colors.reset}`);
|
||||
output.push('');
|
||||
} else {
|
||||
output.push('');
|
||||
output.push('--- New Session ---');
|
||||
output.push('');
|
||||
}
|
||||
} else if (!isFirstSummary) {
|
||||
// Only show regular separator if not first summary and not showing "New Session"
|
||||
if (useColors) {
|
||||
output.push(`${colors.gray}${'─'.repeat(60)}${colors.reset}`);
|
||||
output.push('');
|
||||
} else {
|
||||
output.push('---');
|
||||
output.push('');
|
||||
}
|
||||
} else {
|
||||
// First summary - just add a blank line after header
|
||||
if (useColors) {
|
||||
output.push('');
|
||||
}
|
||||
}
|
||||
|
||||
isFirstSummary = false;
|
||||
|
||||
if (summary.request) {
|
||||
if (useColors) {
|
||||
output.push(`${colors.bright}${colors.yellow}Request:${colors.reset} ${summary.request}`);
|
||||
output.push('');
|
||||
} else {
|
||||
output.push(`**Request:** ${summary.request}`);
|
||||
output.push('');
|
||||
}
|
||||
}
|
||||
|
||||
if (summary.learned) {
|
||||
if (useColors) {
|
||||
output.push(`${colors.bright}${colors.blue}Learned:${colors.reset} ${summary.learned}`);
|
||||
output.push('');
|
||||
} else {
|
||||
output.push(`**Learned:** ${summary.learned}`);
|
||||
output.push('');
|
||||
}
|
||||
}
|
||||
|
||||
if (summary.completed) {
|
||||
if (useColors) {
|
||||
output.push(`${colors.bright}${colors.green}Completed:${colors.reset} ${summary.completed}`);
|
||||
output.push('');
|
||||
} else {
|
||||
output.push(`**Completed:** ${summary.completed}`);
|
||||
output.push('');
|
||||
}
|
||||
}
|
||||
|
||||
if (summary.next_steps) {
|
||||
if (useColors) {
|
||||
output.push(`${colors.bright}${colors.magenta}Next Steps:${colors.reset} ${summary.next_steps}`);
|
||||
output.push('');
|
||||
} else {
|
||||
output.push(`**Next Steps:** ${summary.next_steps}`);
|
||||
output.push('');
|
||||
}
|
||||
}
|
||||
|
||||
// Get files from observations (not from summary which is never populated)
|
||||
const sessionFiles = db.getFilesForSession(summary.sdk_session_id);
|
||||
|
||||
if (sessionFiles.filesRead.length > 0) {
|
||||
if (useColors) {
|
||||
output.push(`${colors.dim}Files Read: ${sessionFiles.filesRead.join(', ')}${colors.reset}`);
|
||||
} else {
|
||||
output.push(`**Files Read:** ${sessionFiles.filesRead.join(', ')}`);
|
||||
}
|
||||
}
|
||||
|
||||
if (sessionFiles.filesModified.length > 0) {
|
||||
if (useColors) {
|
||||
output.push(`${colors.dim}Files Modified: ${sessionFiles.filesModified.join(', ')}${colors.reset}`);
|
||||
} else {
|
||||
output.push(`**Files Modified:** ${sessionFiles.filesModified.join(', ')}`);
|
||||
}
|
||||
}
|
||||
|
||||
const dateTime = new Date(summary.created_at).toLocaleString();
|
||||
if (useColors) {
|
||||
output.push(`${colors.dim}Date: ${dateTime}${colors.reset}`);
|
||||
} else {
|
||||
output.push(`**Date:** ${dateTime}`);
|
||||
}
|
||||
|
||||
if (!useColors) {
|
||||
output.push('');
|
||||
output.push('--- New Session ---');
|
||||
output.push('');
|
||||
}
|
||||
|
||||
previousSessionId = summary.sdk_session_id;
|
||||
}
|
||||
if (summary.request) output.push(`**Request:** ${summary.request}`);
|
||||
if (summary.learned) output.push(`**Learned:** ${summary.learned}`);
|
||||
if (summary.completed) output.push(`**Completed:** ${summary.completed}`);
|
||||
if (summary.next_steps) output.push(`**Next Steps:** ${summary.next_steps}`);
|
||||
|
||||
if (useColors) {
|
||||
// Get files from observations by sdk_session_id
|
||||
const observations = db.db.prepare(`
|
||||
SELECT files_read, files_modified
|
||||
FROM observations
|
||||
WHERE sdk_session_id = ?
|
||||
`).all(summary.sdk_session_id) as Array<{
|
||||
files_read: string | null;
|
||||
files_modified: string | null;
|
||||
}>;
|
||||
|
||||
const filesReadSet = new Set<string>();
|
||||
const filesModifiedSet = new Set<string>();
|
||||
|
||||
for (const obs of observations) {
|
||||
if (obs.files_read) {
|
||||
try {
|
||||
const files = JSON.parse(obs.files_read);
|
||||
if (Array.isArray(files)) files.forEach(f => filesReadSet.add(f));
|
||||
} catch {}
|
||||
}
|
||||
if (obs.files_modified) {
|
||||
try {
|
||||
const files = JSON.parse(obs.files_modified);
|
||||
if (Array.isArray(files)) files.forEach(f => filesModifiedSet.add(f));
|
||||
} catch {}
|
||||
}
|
||||
}
|
||||
|
||||
if (filesReadSet.size > 0) {
|
||||
output.push(`**Files Read:** ${Array.from(filesReadSet).join(', ')}`);
|
||||
}
|
||||
if (filesModifiedSet.size > 0) {
|
||||
output.push(`**Files Modified:** ${Array.from(filesModifiedSet).join(', ')}`);
|
||||
}
|
||||
|
||||
const dateTime = new Date(summary.created_at).toLocaleString();
|
||||
output.push(`**Date:** ${dateTime}`);
|
||||
output.push('');
|
||||
output.push(`${colors.gray}${'─'.repeat(60)}${colors.reset}`);
|
||||
|
||||
previousSessionId = summary.sdk_session_id;
|
||||
}
|
||||
|
||||
return output.join('\n');
|
||||
|
||||
Reference in New Issue
Block a user