mirror of https://github.com/kortix-ai/suna.git
fix(bug): fix double json dumps in response processor
This commit is contained in:
parent
45abd5a687
commit
e99254544d
|
@ -1747,7 +1747,7 @@ class ResponseProcessor:
|
|||
return summary
|
||||
|
||||
else:
|
||||
return json.dumps(structured_result_v1)
|
||||
return structured_result_v1
|
||||
|
||||
def _format_xml_tool_result(self, tool_call: Dict[str, Any], result: ToolResult) -> str:
|
||||
"""Format a tool result wrapped in a <tool_result> tag.
|
||||
|
|
|
@ -638,3 +638,19 @@
|
|||
width: 100%;
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
|
||||
@theme inline {
|
||||
--animate-shiny-text: shiny-text 5s infinite;
|
||||
|
||||
@keyframes shiny-text {
|
||||
0%,
|
||||
90%,
|
||||
100% {
|
||||
background-position: calc(-100% - var(--shiny-width)) 0;
|
||||
}
|
||||
30%,
|
||||
60% {
|
||||
background-position: calc(100% + var(--shiny-width)) 0;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -421,7 +421,7 @@ export const ThreadContent: React.FC<ThreadContentProps> = ({
|
|||
groupedMessages.push(currentGroup);
|
||||
}
|
||||
|
||||
// Handle streaming content
|
||||
// Handle streaming content - only add to existing group or create new one if needed
|
||||
if (streamingTextContent) {
|
||||
const lastGroup = groupedMessages.at(-1);
|
||||
if (!lastGroup || lastGroup.type === 'user') {
|
||||
|
@ -443,18 +443,21 @@ export const ThreadContent: React.FC<ThreadContentProps> = ({
|
|||
key: `assistant-group-${assistantGroupCounter}-streaming`
|
||||
});
|
||||
} else if (lastGroup.type === 'assistant_group') {
|
||||
// Add to existing assistant group
|
||||
lastGroup.messages.push({
|
||||
content: streamingTextContent,
|
||||
type: 'assistant',
|
||||
message_id: 'streamingTextContent',
|
||||
metadata: 'streamingTextContent',
|
||||
created_at: new Date().toISOString(),
|
||||
updated_at: new Date().toISOString(),
|
||||
is_llm_message: true,
|
||||
thread_id: 'streamingTextContent',
|
||||
sequence: Infinity,
|
||||
});
|
||||
// Add to existing assistant group - but don't add if it's already there
|
||||
const hasStreamingContent = lastGroup.messages.some(msg => msg.message_id === 'streamingTextContent');
|
||||
if (!hasStreamingContent) {
|
||||
lastGroup.messages.push({
|
||||
content: streamingTextContent,
|
||||
type: 'assistant',
|
||||
message_id: 'streamingTextContent',
|
||||
metadata: 'streamingTextContent',
|
||||
created_at: new Date().toISOString(),
|
||||
updated_at: new Date().toISOString(),
|
||||
is_llm_message: true,
|
||||
thread_id: 'streamingTextContent',
|
||||
sequence: Infinity,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -513,7 +516,7 @@ export const ThreadContent: React.FC<ThreadContentProps> = ({
|
|||
return (
|
||||
<div key={group.key} ref={groupIndex === groupedMessages.length - 1 ? latestMessageRef : null}>
|
||||
<div className="flex flex-col gap-2">
|
||||
{/* Logo positioned above the message content */}
|
||||
{/* Logo positioned above the message content - ONLY ONCE PER GROUP */}
|
||||
<div className="flex items-center">
|
||||
<div className="rounded-md flex items-center justify-center">
|
||||
{agentAvatar}
|
||||
|
@ -521,8 +524,8 @@ export const ThreadContent: React.FC<ThreadContentProps> = ({
|
|||
<p className='ml-2 text-sm text-muted-foreground'>{agentName ? agentName : 'Suna'}</p>
|
||||
</div>
|
||||
|
||||
{/* Message content */}
|
||||
<div className="flex max-w-[90%] rounded-lg text-sm break-words overflow-hidden">
|
||||
{/* Message content - ALL messages in the group */}
|
||||
<div className="flex max-w-[90%] rounded-lg text-sm break-words overflow-hidden">
|
||||
<div className="space-y-2 min-w-0 flex-1">
|
||||
{(() => {
|
||||
// In debug mode, just show raw messages content
|
||||
|
@ -566,7 +569,6 @@ export const ThreadContent: React.FC<ThreadContentProps> = ({
|
|||
|
||||
const renderedToolResultIds = new Set<string>();
|
||||
const elements: React.ReactNode[] = [];
|
||||
let assistantMessageCount = 0; // Track assistant messages for spacing
|
||||
|
||||
group.messages.forEach((message, msgIndex) => {
|
||||
if (message.type === 'assistant') {
|
||||
|
@ -586,13 +588,12 @@ export const ThreadContent: React.FC<ThreadContentProps> = ({
|
|||
);
|
||||
|
||||
elements.push(
|
||||
<div key={msgKey} className={assistantMessageCount > 0 ? "mt-2" : ""}>
|
||||
<div key={msgKey} className={elements.length > 0 ? "mt-4" : ""}>
|
||||
<div className="prose prose-sm dark:prose-invert chat-markdown max-w-none [&>:first-child]:mt-0 prose-headings:mt-3 break-words overflow-hidden">
|
||||
{renderedContent}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
assistantMessageCount++;
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import React, { useState, useEffect } from 'react';
|
||||
import { motion, AnimatePresence } from 'framer-motion';
|
||||
import { AnimatedShinyText } from '@/components/ui/animated-shiny-text';
|
||||
|
||||
const items = [
|
||||
{ id: 1, content: "Initializing neural pathways..." },
|
||||
|
@ -33,10 +34,8 @@ export const AgentLoader = () => {
|
|||
}, []);
|
||||
|
||||
return (
|
||||
<div className="flex-1 space-y-2 w-full h-16 bg-background">
|
||||
<div className="max-w-[90%] animate-shimmer bg-transparent h-full p-0.5 text-sm border rounded-xl shadow-sm relative overflow-hidden">
|
||||
<div className="rounded-md bg-background flex px-5 items-start justify-start h-full relative z-10">
|
||||
<div className="flex flex-col py-5 items-start w-full space-y-3">
|
||||
<div className="flex py-2 items-center w-full">
|
||||
<div>✨</div>
|
||||
<AnimatePresence>
|
||||
<motion.div
|
||||
key={items[index].id}
|
||||
|
@ -45,13 +44,11 @@ export const AgentLoader = () => {
|
|||
exit={{ y: -20, opacity: 0, filter: "blur(8px)" }}
|
||||
transition={{ ease: "easeInOut" }}
|
||||
style={{ position: "absolute" }}
|
||||
className='ml-7'
|
||||
>
|
||||
{items[index].content}
|
||||
<AnimatedShinyText>{items[index].content}</AnimatedShinyText>
|
||||
</motion.div>
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
import { ComponentPropsWithoutRef, CSSProperties, FC } from "react";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
export interface AnimatedShinyTextProps
|
||||
extends ComponentPropsWithoutRef<"span"> {
|
||||
shimmerWidth?: number;
|
||||
}
|
||||
|
||||
export const AnimatedShinyText: FC<AnimatedShinyTextProps> = ({
|
||||
children,
|
||||
className,
|
||||
shimmerWidth = 100,
|
||||
...props
|
||||
}) => {
|
||||
return (
|
||||
<span
|
||||
style={
|
||||
{
|
||||
"--shiny-width": `${shimmerWidth}px`,
|
||||
} as CSSProperties
|
||||
}
|
||||
className={cn(
|
||||
"mx-auto max-w-md text-neutral-600/70 dark:text-neutral-400/70",
|
||||
"animate-shiny-text bg-clip-text bg-no-repeat [background-position:0_0] [background-size:var(--shiny-width)_100%] [transition:background-position_1s_cubic-bezier(.6,.6,0,1)_infinite]",
|
||||
"bg-gradient-to-r from-transparent via-black/80 via-50% to-transparent dark:via-white/80",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</span>
|
||||
);
|
||||
};
|
Loading…
Reference in New Issue