- {renderContent(c).map((part, j) =>
- part.type === 'code' ? (
-
- ) : (
-
+ (() => {
+ const toolSegs = parsedSegments.filter(s => s.type === 'tool')
+ const compress = collapseHistory && !forceExpand && toolSegs.length > 1
+ const lastTool = toolSegs.length > 0 ? toolSegs[toolSegs.length - 1] : null
+ return (
+ <>
+ {compress && (
+
+ … {toolSegs.length - 1} action{toolSegs.length - 1 > 1 ? 's' : ''} précédente{toolSegs.length - 1 > 1 ? 's' : ''} masquée{toolSegs.length - 1 > 1 ? 's' : ''}
+
+
+ )}
+ {parsedSegments.map((seg, i) => {
+ if (seg.type === 'text') {
+ if (!seg.content) return null
+ const c = seg.content.replace(/
]*>[\s\S]*?<\/think>/gi, '')
+ if (!c) return null
+ return (
+
+ {renderContent(c).map((part, j) =>
+ part.type === 'code' ? (
+
+ ) : (
+
+ )
+ )}
+
)
- )}
-
- )
- }
- if (seg.type === 'tool') {
- const r = seg.result
- const result = r && (r.content !== undefined || r.is_error !== undefined)
- ? { content: r.content, is_error: r.is_error }
- : null
- return
{renderContent(cleanContent).map((part, i) =>
@@ -385,11 +424,12 @@ function FeedItem({ msg, activeAgents, onModeChange }) {
)
}
-function StreamingItem({ content, thinking, toolCalls, segments, activeAgents, onModeChange }) {
+function StreamingItem({ content, thinking, toolCalls, segments, activeAgents, onModeChange, collapseHistory }) {
const rank = RANKS.general
const cleanContent = content.replace(/
]*>[\s\S]*?<\/think>/gi, '')
const hasToolCalls = toolCalls && toolCalls.length > 0
const [copiedIdx, setCopiedIdx] = useState(null)
+ const [forceExpand, setForceExpand] = useState(false)
const renderedContent = useMemo(() => {
if (!cleanContent) return []
@@ -402,6 +442,8 @@ function StreamingItem({ content, thinking, toolCalls, segments, activeAgents, o
}, [thinking])
const hasOrderedSegments = segments && segments.some(s => s.type === 'tool')
+ const toolSegments = (segments || []).filter(s => s.type === 'tool')
+ const compress = collapseHistory && !forceExpand && toolSegments.length > 1
return (
@@ -417,32 +459,51 @@ function StreamingItem({ content, thinking, toolCalls, segments, activeAgents, o
{thinking && }
{hasOrderedSegments ? (
- segments.map((seg, i) => {
- if (seg.type === 'text') {
- if (!seg.content) return null
- const parts = renderContent(seg.content)
- return (
-
- {parts.map((part, j) =>
- part.type === 'code' ? (
-
- ) : (
-
- )
- )}
-
- )
- }
- if (seg.type === 'tool') {
- return
- }
- return null
- })
+ <>
+ {compress && (
+
+ … {toolSegments.length - 1} action{toolSegments.length - 1 > 1 ? 's' : ''} précédente{toolSegments.length - 1 > 1 ? 's' : ''} masquée{toolSegments.length - 1 > 1 ? 's' : ''} (mode compressé)
+
+
+ )}
+ {(() => {
+ const lastToolId = toolSegments.length > 0 ? toolSegments[toolSegments.length - 1] : null
+ return segments.map((seg, i) => {
+ if (seg.type === 'text') {
+ if (!seg.content) return null
+ const parts = renderContent(seg.content)
+ return (
+
+ {parts.map((part, j) =>
+ part.type === 'code' ? (
+
+ ) : (
+
+ )
+ )}
+
+ )
+ }
+ if (seg.type === 'tool') {
+ if (compress && seg !== lastToolId) return null
+ return
+ }
+ return null
+ })
+ })()}
+ >
) : (
<>
- {hasToolCalls && toolCalls.map((tc, i) => (
-
- ))}
+ {hasToolCalls && (compress
+ ? []
+ : toolCalls.map((tc, i) => (
+
+ ))
+ )}
{cleanContent && (
{renderedContent.map((part, i) =>
@@ -487,6 +548,12 @@ export default function Studio({ api }) {
const [attachedImages, setAttachedImages] = useState([])
const [activeAgents, setActiveAgents] = useState({ crush: 0, claude: 0 })
const [toolModes, setToolModes] = useState({})
+ const [advancedReflection, setAdvancedReflection] = useState(() => {
+ try { return localStorage.getItem('muyue.advancedReflection') === 'true' } catch { return false }
+ })
+ const [collapseHistory, setCollapseHistory] = useState(() => {
+ try { return localStorage.getItem('muyue.collapseHistory') !== 'false' } catch { return true }
+ })
const MAX_CRUSH_AGENTS = 2
const MAX_CLAUDE_AGENTS = 2
const messagesEnd = useRef(null)
@@ -747,7 +814,7 @@ export default function Studio({ api }) {
setStreaming(partial)
const snap = segments.map(s => ({ ...s }))
setStreamSegments(snap)
- }, controller.signal, images)
+ }, controller.signal, images, advancedReflection)
const allText = segments.filter(s => s.type === 'text').map(s => s.content).join('')
const toolSegs = segments.filter(s => s.type === 'tool')
@@ -882,7 +949,7 @@ export default function Studio({ api }) {
{summarizedExpanded ? 'masquer' : 'voir'}
{summarizedExpanded && summarizedMsgs.map(msg => (
-
+
))}
)
@@ -894,7 +961,7 @@ export default function Studio({ api }) {
<>
{renderSummaryBlock()}
{activeMsgs.slice(0, visibleCount).map(msg => (
-