mirror of
https://github.com/thedotmack/claude-mem
synced 2026-04-25 17:15:04 +02:00
fix(parser): stop warning on normal observation responses (#2074)
parseSummary runs on every agent response, not just summary turns. When the turn is a normal observation, the LLM correctly emits <observation> and no <summary> — but the fallthrough branch from #1345 treated this as prompt misbehavior and logged "prompt conditioning may need strengthening" every time. That assumption stopped holding after #1633 refactored the caller to always invoke parseSummary with a coerceFromObservation flag. Gate the whole observation-on-summary path on coerceFromObservation. On a real summary turn, coercion still runs and logs the legitimate "coercion failed" warning when the response has no usable content. On an observation turn, parseSummary returns null silently, which is the correct behavior. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -137,22 +137,23 @@ export function parseSummary(text: string, sessionId?: number, coerceFromObserva
|
||||
const summaryMatch = summaryRegex.exec(text);
|
||||
|
||||
if (!summaryMatch) {
|
||||
// When the LLM returns <observation> tags instead of <summary> tags,
|
||||
// coerce the observation content into summary fields rather than discarding it.
|
||||
// This breaks the infinite retry loop described in #1633: without coercion,
|
||||
// the summary is silently dropped, the session completes without a summary,
|
||||
// a new session is spawned with an ever-growing prompt, and the cycle repeats.
|
||||
// Only coerce when explicitly requested (i.e., when a summarize message was sent).
|
||||
if (/<observation>/.test(text)) {
|
||||
if (coerceFromObservation) {
|
||||
const coerced = coerceObservationToSummary(text, sessionId);
|
||||
if (coerced) {
|
||||
return coerced;
|
||||
}
|
||||
logger.warn('PARSER', 'Summary response contained <observation> tags instead of <summary> — coercion failed, no usable content', { sessionId });
|
||||
} else {
|
||||
logger.warn('PARSER', 'Summary response contained <observation> tags instead of <summary> — prompt conditioning may need strengthening', { sessionId });
|
||||
// When the LLM returns <observation> tags instead of <summary> tags on a
|
||||
// summary turn, coerce the observation content into summary fields rather
|
||||
// than discarding it. This breaks the infinite retry loop described in
|
||||
// #1633: without coercion, the summary is silently dropped, the session
|
||||
// completes without a summary, a new session is spawned with an ever-growing
|
||||
// prompt, and the cycle repeats.
|
||||
//
|
||||
// parseSummary is called on every response (see ResponseProcessor), not just
|
||||
// summary turns — so the absence of <summary> in an observation response is
|
||||
// expected, not a prompt-conditioning failure. Only act when the caller
|
||||
// actually expected a summary (coerceFromObservation=true).
|
||||
if (coerceFromObservation && /<observation>/.test(text)) {
|
||||
const coerced = coerceObservationToSummary(text, sessionId);
|
||||
if (coerced) {
|
||||
return coerced;
|
||||
}
|
||||
logger.warn('PARSER', 'Summary response contained <observation> tags instead of <summary> — coercion failed, no usable content', { sessionId });
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user