Merge pull request #136 from multica-ai/fix/agent-compaction
fix(agent): prevent context window overflow with 3-layer compaction defense
This commit is contained in:
commit
8bc36a9cc9
9 changed files with 263 additions and 46 deletions
45
packages/ui/src/components/compaction-item.tsx
Normal file
45
packages/ui/src/components/compaction-item.tsx
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
"use client"
|
||||
|
||||
import { memo } from "react"
|
||||
import { Scissors } from "lucide-react"
|
||||
import type { Message } from "@multica/store"
|
||||
|
||||
function formatTokens(n: number): string {
|
||||
if (n >= 1000) return `~${(n / 1000).toFixed(1)}k`
|
||||
return `${n}`
|
||||
}
|
||||
|
||||
interface CompactionItemProps {
|
||||
message: Message
|
||||
}
|
||||
|
||||
export const CompactionItem = memo(function CompactionItem({ message }: CompactionItemProps) {
|
||||
const info = message.compaction
|
||||
if (!info) return null
|
||||
|
||||
const label = info.reason === "summary" ? "Context summarized" : "Context compacted"
|
||||
const removed = `${info.removed} messages removed`
|
||||
const tokens = info.tokensRemoved != null
|
||||
? `, ${formatTokens(info.tokensRemoved)} tokens freed`
|
||||
: ""
|
||||
|
||||
return (
|
||||
<div className="py-0.5 px-2.5 text-sm text-muted-foreground">
|
||||
<div className="flex items-center gap-1.5 px-2.5 py-1">
|
||||
{/* Status dot */}
|
||||
<span className="size-1.5 rounded-full shrink-0 bg-muted-foreground/40" />
|
||||
|
||||
{/* Icon */}
|
||||
<Scissors className="size-3.5 shrink-0" />
|
||||
|
||||
{/* Label */}
|
||||
<span className="font-medium shrink-0">{label}</span>
|
||||
|
||||
{/* Stats */}
|
||||
<span className="ml-auto text-xs text-muted-foreground/60 shrink-0">
|
||||
{removed}{tokens}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
|
|
@ -5,6 +5,7 @@ import { MemoizedMarkdown } from "@multica/ui/components/markdown";
|
|||
import { StreamingMarkdown } from "@multica/ui/components/markdown/StreamingMarkdown";
|
||||
import { ToolCallItem } from "@multica/ui/components/tool-call-item";
|
||||
import { ThinkingItem } from "@multica/ui/components/thinking-item";
|
||||
import { CompactionItem } from "@multica/ui/components/compaction-item";
|
||||
import { cn, getTextContent } from "@multica/ui/lib/utils";
|
||||
import type { Message } from "@multica/store";
|
||||
import type { ContentBlock, ToolCall, ThinkingContent } from "@multica/sdk";
|
||||
|
|
@ -78,6 +79,11 @@ export const MessageList = memo(function MessageList({ messages, streamingIds }:
|
|||
return (
|
||||
<div className="relative p-6 px-4 sm:px-10 max-w-4xl mx-auto">
|
||||
{messages.map((msg) => {
|
||||
// System messages (e.g. compaction notifications)
|
||||
if (msg.role === "system") {
|
||||
return <CompactionItem key={msg.id} message={msg} />
|
||||
}
|
||||
|
||||
// ToolResult messages → render as tool execution item
|
||||
if (msg.role === "toolResult") {
|
||||
return <ToolCallItem key={msg.id} message={msg} />
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue