fix: improve error handling and logging in summary and transcript processing

- Enhanced error handling in summary generation by using fallback messages for missing assistant messages.
- Updated the `buildSummaryPrompt` function to streamline the retrieval of the last assistant message.
- Improved the `extractLastMessage` function to log errors when transcript files are missing or empty, and to ensure proper handling of messages without content.
- Added checks to ensure that messages of the specified role are found in the transcript, with appropriate logging for missing messages.
- Refactored the logging mechanism to provide clearer insights into processing failures and successes.
This commit is contained in:
Alex Newman
2025-12-14 16:28:57 -05:00
parent eb76a76a5b
commit 43db22728e
5 changed files with 81 additions and 37 deletions
+2 -2
View File
@@ -177,10 +177,10 @@ export function buildObservationPrompt(obs: Observation): string {
* Build prompt to generate progress summary
*/
export function buildSummaryPrompt(session: SDKSession): string {
const lastAssistantMessage = happy_path_error__with_fallback(
const lastAssistantMessage = session.last_assistant_message || happy_path_error__with_fallback(
'Missing last_assistant_message in session for summary prompt',
session,
session.last_assistant_message || ''
''
);
return `PROGRESS SUMMARY CHECKPOINT
+50 -18
View File
@@ -1,5 +1,6 @@
import { readFileSync, existsSync } from 'fs';
import { logger } from '../utils/logger.js';
import { happy_path_error__with_fallback } from '../utils/silent-debug.js';
/**
* Extract last message of specified role from transcript JSONL file
@@ -13,42 +14,73 @@ export function extractLastMessage(
stripSystemReminders: boolean = false
): string {
if (!transcriptPath || !existsSync(transcriptPath)) {
happy_path_error__with_fallback(
'Transcript path missing or file does not exist',
{ transcriptPath, role }
);
return '';
}
try {
const content = readFileSync(transcriptPath, 'utf-8').trim();
if (!content) return '';
if (!content) {
happy_path_error__with_fallback(
'Transcript file exists but is empty',
{ transcriptPath, role }
);
return '';
}
const lines = content.split('\n');
let foundMatchingRole = false;
for (let i = lines.length - 1; i >= 0; i--) {
try {
const line = JSON.parse(lines[i]);
if (line.type === role && line.message?.content) {
let text = '';
const msgContent = line.message.content;
if (line.type === role) {
foundMatchingRole = true;
if (typeof msgContent === 'string') {
text = msgContent;
} else if (Array.isArray(msgContent)) {
text = msgContent
.filter((c: any) => c.type === 'text')
.map((c: any) => c.text)
.join('\n');
if (line.message?.content) {
let text = '';
const msgContent = line.message.content;
if (typeof msgContent === 'string') {
text = msgContent;
} else if (Array.isArray(msgContent)) {
text = msgContent
.filter((c: any) => c.type === 'text')
.map((c: any) => c.text)
.join('\n');
}
if (stripSystemReminders) {
text = text.replace(/<system-reminder>[\s\S]*?<\/system-reminder>/g, '');
text = text.replace(/\n{3,}/g, '\n\n').trim();
}
// Log if we found the role but the text is empty after processing
if (!text || text.trim() === '') {
happy_path_error__with_fallback(
'Found message but content is empty after processing',
{ role, transcriptPath, msgContentType: typeof msgContent, stripSystemReminders }
);
}
return text;
}
if (stripSystemReminders) {
text = text.replace(/<system-reminder>[\s\S]*?<\/system-reminder>/g, '');
text = text.replace(/\n{3,}/g, '\n\n').trim();
}
return text;
}
} catch {
continue;
}
}
// If we searched the whole transcript and didn't find any message of this role
if (!foundMatchingRole) {
happy_path_error__with_fallback(
'No message found for role in transcript',
{ role, transcriptPath, totalLines: lines.length }
);
}
} catch (error) {
logger.error('HOOK', 'Failed to read transcript', { transcriptPath }, error as Error);
}