feat: render summarization/compact user message (#736)
This commit is contained in:
@@ -5,8 +5,12 @@
|
||||
// - Exposes `onChunk` to feed SDK events and `toLines` to render.
|
||||
|
||||
import type { LettaStreamingResponse } from "@letta-ai/letta-client/resources/agents/messages";
|
||||
import { INTERRUPTED_BY_USER } from "../../constants";
|
||||
import {
|
||||
COMPACTION_SUMMARY_HEADER,
|
||||
INTERRUPTED_BY_USER,
|
||||
} from "../../constants";
|
||||
import { runPostToolUseHooks, runPreToolUseHooks } from "../../hooks";
|
||||
import { extractCompactionSummary } from "./backfill";
|
||||
import { findLastSafeSplitPoint } from "./markdownSplit";
|
||||
import { isShellTool } from "./toolNameMapping";
|
||||
|
||||
@@ -505,6 +509,33 @@ export function onChunk(b: Buffers, chunk: LettaStreamingResponse) {
|
||||
break;
|
||||
}
|
||||
|
||||
case "user_message": {
|
||||
// Use otid if available, fall back to id (server sends otid: null for summary messages)
|
||||
const chunkWithId = chunk as LettaStreamingResponse & { id?: string };
|
||||
const id = chunk.otid || chunkWithId.id;
|
||||
if (!id) break;
|
||||
|
||||
// Handle otid transition (mark previous line as finished)
|
||||
handleOtidTransition(b, id);
|
||||
|
||||
// Extract text content from the user message
|
||||
const rawText = extractTextPart(chunk.content);
|
||||
if (!rawText) break;
|
||||
|
||||
// Check if this is a compaction summary message
|
||||
const compactionSummary = extractCompactionSummary(rawText);
|
||||
if (compactionSummary) {
|
||||
// Render as a user message with context header and summary
|
||||
ensure(b, id, () => ({
|
||||
kind: "user",
|
||||
id,
|
||||
text: `${COMPACTION_SUMMARY_HEADER}\n\n${compactionSummary}`,
|
||||
}));
|
||||
}
|
||||
// If not a summary, ignore it (user messages aren't rendered during streaming)
|
||||
break;
|
||||
}
|
||||
|
||||
case "tool_call_message":
|
||||
case "approval_request_message": {
|
||||
/* POST-FIX VERSION (what this should look like after backend fix):
|
||||
|
||||
@@ -5,7 +5,11 @@ import type {
|
||||
Message,
|
||||
TextContent,
|
||||
} from "@letta-ai/letta-client/resources/agents/messages";
|
||||
import { SYSTEM_REMINDER_CLOSE, SYSTEM_REMINDER_OPEN } from "../../constants";
|
||||
import {
|
||||
COMPACTION_SUMMARY_HEADER,
|
||||
SYSTEM_REMINDER_CLOSE,
|
||||
SYSTEM_REMINDER_OPEN,
|
||||
} from "../../constants";
|
||||
import type { Buffers } from "./accumulator";
|
||||
|
||||
/**
|
||||
@@ -81,7 +85,7 @@ function truncateSystemReminder(text: string, maxLength: number): string {
|
||||
* Check if a user message is a compaction summary (system_alert with summary content).
|
||||
* Returns the summary text if found, null otherwise.
|
||||
*/
|
||||
function extractCompactionSummary(text: string): string | null {
|
||||
export function extractCompactionSummary(text: string): string | null {
|
||||
try {
|
||||
const parsed = JSON.parse(text);
|
||||
if (
|
||||
@@ -182,17 +186,12 @@ export function backfillBuffers(buffers: Buffers, history: Message[]): void {
|
||||
// Check if this is a compaction summary message (system_alert with summary)
|
||||
const compactionSummary = extractCompactionSummary(rawText);
|
||||
if (compactionSummary) {
|
||||
// Render as a synthetic tool call showing the compaction
|
||||
// Render as a user message with context header and summary
|
||||
const exists = buffers.byId.has(lineId);
|
||||
buffers.byId.set(lineId, {
|
||||
kind: "tool_call",
|
||||
kind: "user",
|
||||
id: lineId,
|
||||
toolCallId: `compaction-${lineId}`,
|
||||
name: "Compact",
|
||||
argsText: "messages[...]",
|
||||
resultText: compactionSummary,
|
||||
resultOk: true,
|
||||
phase: "finished",
|
||||
text: `${COMPACTION_SUMMARY_HEADER}\n\n${compactionSummary}`,
|
||||
});
|
||||
if (!exists) buffers.order.push(lineId);
|
||||
break;
|
||||
|
||||
@@ -24,6 +24,12 @@ export const SYSTEM_REMINDER_TAG = "system-reminder";
|
||||
export const SYSTEM_REMINDER_OPEN = `<${SYSTEM_REMINDER_TAG}>`;
|
||||
export const SYSTEM_REMINDER_CLOSE = `</${SYSTEM_REMINDER_TAG}>`;
|
||||
|
||||
/**
|
||||
* Header displayed before compaction summary when conversation context is truncated
|
||||
*/
|
||||
export const COMPACTION_SUMMARY_HEADER =
|
||||
"This session is being continued from a previous conversation that ran out of context. The summary below covers the earlier portion of the conversation.";
|
||||
|
||||
/**
|
||||
* Status bar thresholds - only show indicators when values exceed these
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user