feat(summarize): zero-LLM synthetic summary path + graceful fallback - #845
feat(summarize): zero-LLM synthetic summary path + graceful fallback#845saatvik333 wants to merge 1 commit into
Conversation
mem::summarize always called the external LLM provider whenever a key was configured (AGENTMEMORY_AUTO_COMPRESS only gates per-observation compress). When the provider is rate-limited / down (e.g. Gemini free-tier 429) and the fallback key is invalid, every summarize fails and trips the shared circuit breaker, taking compress/embeddings down with it. Add buildSyntheticSummary(): a deterministic, zero-LLM session summary built from the already-compressed observations (mirrors compress-synthetic.ts, #138). Wire it into mem::summarize as: - the PRIMARY path when AUTO_COMPRESS is off or no provider key is set, and - a graceful FALLBACK when an enabled provider errors / returns empty / produces unparseable or invalid output. Result: summarize never hard-fails and can no longer trip the breaker; recap, handoff and skill-extract keep working with no token spend. Opt back into richer LLM summaries via AGENTMEMORY_AUTO_COMPRESS=true. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
@qareai is attempting to deploy a commit to the rohitg00's projects Team on Vercel. A member of the Team first needs to authorize it. |
|
Looking for one thing? Review this PR in Change Stack to search files, summaries, diffs, and code without losing your place. No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughAdds a deterministic zero-LLM session summarizer that aggregates compressed observations into structured summaries, then integrates it into the main ChangesZero-LLM Session Summarization
Sequence Diagram(s)sequenceDiagram
participant mem as mem::summarize
participant syn as buildSyntheticSummary
participant KV as KV.summaries
participant audit as safeAudit
participant metrics as metricsStore
mem->>mem: Detect noop/auto-compress disabled
mem->>syn: Invoke synthesize(reason)
syn->>KV: Store summary
syn->>audit: Record synthetic event
syn->>metrics: Record success=true
syn->>mem: Return {success:true, synthetic:true}
note over mem: Also fallback on:<br/>empty provider response<br/>XML parse failure<br/>validation failure<br/>LLM error
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Problem
mem::summarizecalls the external LLM provider on every session stop whenever a provider key is configured.AGENTMEMORY_AUTO_COMPRESSonly gates per-observation compress (which already has a zero-LLMcompress-synthetic.tspath since #138) — it does not gate summarize.So when the provider is rate-limited or down, summarize keeps failing:
429(generate_content_free_tier_requests, limit 20).FALLBACK_PROVIDERSkey is also invalid (401), there's no escape.ResilientProvider.recordFailure(); after the threshold the shared circuit breaker opens, which then fails compress and embeddings too.Net effect: one provider outage takes the whole memory hot-path down, and every session-stop summarize is a hard failure with no degraded mode.
Change
Add
src/functions/summarize-synthetic.ts→buildSyntheticSummary(): a deterministic, zero-LLM session summary built from the already-compressed observations (titles, files, decisions, concepts derived from dirs/extensions, activity-tallied narrative). Mirrors the existingcompress-synthetic.tsphilosophy.Wire it into
mem::summarizeas:AUTO_COMPRESSis off or no provider key is configured — never touches the provider, no token spend, no breaker exposure.recap,handoffandskill-extractkeep working in every failure mode. Users who want richer LLM narratives opt in withAGENTMEMORY_AUTO_COMPRESS=true(unchanged).Notes
AUTO_COMPRESS=trueis unchanged except that previously-fatal provider errors now degrade to a synthetic summary instead of returning{success:false}.scoreSummary(); a typical dev session scores 100, a conversation-only session ~60 (no fabricated decisions/files).provider.name === "noop"branch (provider is always wrapped inResilientProvider, so that string never matched); the noop case is handled bydetectLlmProviderKind().Summary by CodeRabbit