Skip to content

Commit ebb6b04

Browse files
authored
Merge pull request #1266 from yeyan1996/fix/playback-tools
fix: refactor playback controls and consolidate XML tag constants
2 parents ab3e9c4 + 55af8c6 commit ebb6b04

File tree

6 files changed

+63
-137
lines changed

6 files changed

+63
-137
lines changed

frontend/src/app/share/[threadId]/page.tsx

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -288,33 +288,6 @@ export default function ThreadPage({
288288
[],
289289
);
290290

291-
// useEffect(() => {
292-
// if (!isPlaying || messages.length === 0) return;
293-
294-
// let playbackTimeout: NodeJS.Timeout;
295-
296-
// const playbackNextMessage = async () => {
297-
// if (currentMessageIndex >= messages.length) {
298-
// setIsPlaying(false);
299-
// return;
300-
// }
301-
302-
// const currentMessage = messages[currentMessageIndex];
303-
// console.log(
304-
// `Playing message ${currentMessageIndex}:`,
305-
// currentMessage.type,
306-
// currentMessage.message_id,
307-
// );
308-
309-
// setCurrentMessageIndex((prevIndex) => prevIndex + 1);
310-
// };
311-
// playbackTimeout = setTimeout(playbackNextMessage, 500);
312-
313-
// return () => {
314-
// clearTimeout(playbackTimeout);
315-
// };
316-
// }, [isPlaying, currentMessageIndex, messages]);
317-
318291
const {
319292
status: streamHookStatus,
320293
toolCall: streamingToolCall,

frontend/src/components/thread/content/PlaybackControls.tsx

Lines changed: 22 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -11,42 +11,15 @@ import {
1111
import { UnifiedMessage } from '@/components/thread/types';
1212
import { safeJsonParse } from '@/components/thread/utils';
1313
import Link from 'next/link';
14-
15-
// Define the set of tags whose raw XML should be hidden during streaming
16-
const HIDE_STREAMING_XML_TAGS = new Set([
17-
'execute-command',
18-
'create-file',
19-
'delete-file',
20-
'full-file-rewrite',
21-
'edit-file',
22-
'str-replace',
23-
'browser-click-element',
24-
'browser-close-tab',
25-
'browser-drag-drop',
26-
'browser-get-dropdown-options',
27-
'browser-go-back',
28-
'browser-input-text',
29-
'browser-navigate-to',
30-
'browser-scroll-down',
31-
'browser-scroll-to-text',
32-
'browser-scroll-up',
33-
'browser-select-dropdown-option',
34-
'browser-send-keys',
35-
'browser-switch-tab',
36-
'browser-wait',
37-
'deploy',
38-
'ask',
39-
'complete',
40-
'crawl-webpage',
41-
'web-search',
42-
]);
14+
import { parseXmlToolCalls } from '../tool-views/xml-parser';
15+
import { HIDE_STREAMING_XML_TAGS } from '@/components/thread/utils';
4316

4417
export interface PlaybackControlsProps {
4518
messages: UnifiedMessage[];
4619
isSidePanelOpen: boolean;
4720
onToggleSidePanel: () => void;
4821
toolCalls: any[];
49-
setCurrentToolIndex: (index: number) => void;
22+
setCurrentToolIndex: React.Dispatch<React.SetStateAction<number>>;
5023
onFileViewerOpen: () => void;
5124
projectName?: string;
5225
}
@@ -58,7 +31,6 @@ export interface PlaybackState {
5831
streamingText: string;
5932
isStreamingText: boolean;
6033
currentToolCall: any | null;
61-
toolPlaybackIndex: number;
6234
}
6335

6436
export interface PlaybackController {
@@ -88,7 +60,6 @@ export const PlaybackControls = ({
8860
streamingText: '',
8961
isStreamingText: false,
9062
currentToolCall: null,
91-
toolPlaybackIndex: -1,
9263
});
9364

9465
// Extract state variables for easier access
@@ -99,10 +70,10 @@ export const PlaybackControls = ({
9970
streamingText,
10071
isStreamingText,
10172
currentToolCall,
102-
toolPlaybackIndex,
10373
} = playbackState;
10474

10575
const playbackTimeout = useRef<NodeJS.Timeout | null>(null);
76+
const [isToolInitialized, setIsToolInitialized] = useState(false);
10677

10778
// Helper function to update playback state
10879
const updatePlaybackState = useCallback((updates: Partial<PlaybackState>) => {
@@ -129,9 +100,9 @@ export const PlaybackControls = ({
129100
streamingText: '',
130101
isStreamingText: false,
131102
currentToolCall: null,
132-
toolPlaybackIndex: -1,
133103
});
134-
setCurrentToolIndex(-1);
104+
setCurrentToolIndex(0);
105+
setIsToolInitialized(false);
135106

136107
if (playbackTimeout.current) {
137108
clearTimeout(playbackTimeout.current);
@@ -192,7 +163,6 @@ export const PlaybackControls = ({
192163
streamingText: '',
193164
isStreamingText: false,
194165
currentToolCall: null,
195-
toolPlaybackIndex: toolCalls.length - 1,
196166
});
197167

198168
if (toolCalls.length > 0) {
@@ -242,11 +212,9 @@ export const PlaybackControls = ({
242212
}
243213

244214
// Add the tool call
245-
const toolName = match[1] || match[2];
246215
chunks.push({
247216
text: match[0],
248217
isTool: true,
249-
toolName,
250218
});
251219

252220
lastIndex = toolCallRegex.lastIndex;
@@ -306,40 +274,24 @@ export const PlaybackControls = ({
306274
// If this is a tool call chunk and we're at the start of it
307275
if (currentChunk.isTool && currentIndex === 0) {
308276
// For tool calls, check if they should be hidden during streaming
309-
if (
310-
currentChunk.toolName &&
311-
HIDE_STREAMING_XML_TAGS.has(currentChunk.toolName)
312-
) {
313-
// Instead of showing the XML, create a tool call object
314-
const toolCall = {
315-
name: currentChunk.toolName,
316-
arguments: currentChunk.text,
317-
xml_tag_name: currentChunk.toolName,
318-
};
319-
320-
updatePlaybackState({
321-
currentToolCall: toolCall,
322-
toolPlaybackIndex: toolPlaybackIndex + 1,
323-
});
324-
325-
if (!isSidePanelOpen) {
326-
onToggleSidePanel();
327-
}
328-
329-
setCurrentToolIndex(toolPlaybackIndex + 1);
277+
if (isToolInitialized) {
278+
// TODO: better to change tool index by uniq tool id
279+
setCurrentToolIndex((prev) => prev + 1);
280+
} else {
281+
setIsToolInitialized(true);
282+
}
330283

331-
// Pause streaming briefly while showing the tool
332-
isPaused = true;
333-
setTimeout(() => {
334-
isPaused = false;
335-
updatePlaybackState({ currentToolCall: null });
336-
chunkIndex++; // Move to next chunk
337-
currentIndex = 0; // Reset index for next chunk
338-
processNextCharacter();
339-
}, 500); // Reduced from 1500ms to 500ms pause for tool display
284+
// Pause streaming briefly while showing the tool
285+
isPaused = true;
286+
setTimeout(() => {
287+
isPaused = false;
288+
updatePlaybackState({ currentToolCall: null });
289+
chunkIndex++; // Move to next chunk
290+
currentIndex = 0; // Reset index for next chunk
291+
processNextCharacter();
292+
}, 500); // Reduced from 1500ms to 500ms pause for tool display
340293

341-
return;
342-
}
294+
return;
343295
}
344296

345297
// Handle normal text streaming for non-tool chunks or visible tool chunks
@@ -387,7 +339,6 @@ export const PlaybackControls = ({
387339
isPlaying,
388340
messages,
389341
currentMessageIndex,
390-
toolPlaybackIndex,
391342
setCurrentToolIndex,
392343
isSidePanelOpen,
393344
onToggleSidePanel,

frontend/src/components/thread/content/ThreadContent.tsx

Lines changed: 1 addition & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -16,40 +16,8 @@ import { AgentLoader } from './loader';
1616
import { parseXmlToolCalls, isNewXmlFormat } from '@/components/thread/tool-views/xml-parser';
1717
import { ShowToolStream } from './ShowToolStream';
1818
import { ComposioUrlDetector } from './composio-url-detector';
19+
import { HIDE_STREAMING_XML_TAGS } from '@/components/thread/utils';
1920

20-
const HIDE_STREAMING_XML_TAGS = new Set([
21-
'execute-command',
22-
'create-file',
23-
'delete-file',
24-
'full-file-rewrite',
25-
'edit-file',
26-
'str-replace',
27-
'browser-click-element',
28-
'browser-close-tab',
29-
'browser-drag-drop',
30-
'browser-get-dropdown-options',
31-
'browser-go-back',
32-
'browser-input-text',
33-
'browser-navigate-to',
34-
'browser-scroll-down',
35-
'browser-scroll-to-text',
36-
'browser-scroll-up',
37-
'browser-select-dropdown-option',
38-
'browser-send-keys',
39-
'browser-switch-tab',
40-
'browser-wait',
41-
'deploy',
42-
'ask',
43-
'complete',
44-
'crawl-webpage',
45-
'web-search',
46-
'see-image',
47-
'execute_data_provider_call',
48-
'execute_data_provider_endpoint',
49-
50-
'execute-data-provider-call',
51-
'execute-data-provider-endpoint',
52-
]);
5321

5422
// Helper function to render attachments (keeping original implementation for now)
5523
export function renderAttachments(attachments: string[], fileViewerHandler?: (filePath?: string, filePathList?: string[]) => void, sandboxId?: string, project?: Project) {

frontend/src/components/thread/tool-call-side-panel.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -151,10 +151,9 @@ export function ToolCallSidePanel({
151151
}, [toolCalls, navigationMode, toolCallSnapshots.length, isInitialized]);
152152

153153
React.useEffect(() => {
154-
if (isOpen && !isInitialized && toolCallSnapshots.length > 0) {
155-
setInternalIndex(Math.min(currentIndex, toolCallSnapshots.length - 1));
156-
}
157-
}, [isOpen, currentIndex, isInitialized, toolCallSnapshots.length]);
154+
// This is used to sync the internal index to the current index
155+
setInternalIndex(Math.min(currentIndex, toolCallSnapshots.length - 1));
156+
}, [currentIndex, toolCallSnapshots.length]);
158157

159158
const safeInternalIndex = Math.min(internalIndex, Math.max(0, toolCallSnapshots.length - 1));
160159
const currentSnapshot = toolCallSnapshots[safeInternalIndex];

frontend/src/components/thread/utils.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,3 +494,38 @@ export function getUserFriendlyToolName(toolName: string): string {
494494
}
495495
return TOOL_DISPLAY_NAMES.get(toolName) || toolName;
496496
}
497+
498+
export const HIDE_STREAMING_XML_TAGS = new Set([
499+
'create-tasks',
500+
'execute-command',
501+
'create-file',
502+
'delete-file',
503+
'full-file-rewrite',
504+
'edit-file',
505+
'str-replace',
506+
'browser-click-element',
507+
'browser-close-tab',
508+
'browser-drag-drop',
509+
'browser-get-dropdown-options',
510+
'browser-go-back',
511+
'browser-input-text',
512+
'browser-navigate-to',
513+
'browser-scroll-down',
514+
'browser-scroll-to-text',
515+
'browser-scroll-up',
516+
'browser-select-dropdown-option',
517+
'browser-send-keys',
518+
'browser-switch-tab',
519+
'browser-wait',
520+
'deploy',
521+
'ask',
522+
'complete',
523+
'crawl-webpage',
524+
'web-search',
525+
'see-image',
526+
'execute_data_provider_call',
527+
'execute_data_provider_endpoint',
528+
529+
'execute-data-provider-call',
530+
'execute-data-provider-endpoint',
531+
]);

frontend/src/components/ui/slider.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,15 +45,15 @@ function Slider({
4545
<SliderPrimitive.Range
4646
data-slot="slider-range"
4747
className={cn(
48-
'bg-primary absolute data-[orientation=horizontal]:h-full data-[orientation=vertical]:w-full',
48+
'cursor-pointer bg-primary absolute data-[orientation=horizontal]:h-full data-[orientation=vertical]:w-full',
4949
)}
5050
/>
5151
</SliderPrimitive.Track>
5252
{Array.from({ length: _values.length }, (_, index) => (
5353
<SliderPrimitive.Thumb
5454
data-slot="slider-thumb"
5555
key={index}
56-
className="border-primary bg-background ring-ring/50 block size-4 shrink-0 rounded-full border shadow-sm transition-[color,box-shadow] hover:ring-4 focus-visible:ring-4 focus-visible:outline-hidden disabled:pointer-events-none disabled:opacity-50"
56+
className="cursor-pointer border-primary bg-background ring-ring/50 block size-4 shrink-0 rounded-full border shadow-sm transition-[color,box-shadow] hover:ring-4 focus-visible:ring-4 focus-visible:outline-hidden disabled:pointer-events-none disabled:opacity-50"
5757
/>
5858
))}
5959
</SliderPrimitive.Root>

0 commit comments

Comments
 (0)