@@ -9,13 +9,15 @@ import { toast } from 'sonner'
99import { useTasks } from '@/components/app-layout'
1010import { getLogsPaneHeight , setLogsPaneHeight , getLogsPaneCollapsed , setLogsPaneCollapsed } from '@/lib/utils/cookies'
1111import { Terminal , TerminalRef } from '@/components/terminal'
12+ import { Select , SelectContent , SelectItem , SelectTrigger , SelectValue } from '@/components/ui/select'
1213
1314interface LogsPaneProps {
1415 task : Task
1516 onHeightChange ?: ( height : number ) => void
1617}
1718
1819type TabType = 'logs' | 'terminal'
20+ type LogFilterType = 'all' | 'platform' | 'server'
1921
2022export function LogsPane ( { task, onHeightChange } : LogsPaneProps ) {
2123 const [ copiedLogs , setCopiedLogs ] = useState ( false )
@@ -27,6 +29,7 @@ export function LogsPane({ task, onHeightChange }: LogsPaneProps) {
2729 const [ hasMounted , setHasMounted ] = useState ( false )
2830 const [ activeTab , setActiveTab ] = useState < TabType > ( 'logs' )
2931 const [ isClearingLogs , setIsClearingLogs ] = useState ( false )
32+ const [ logFilter , setLogFilter ] = useState < LogFilterType > ( 'all' )
3033 const logsContainerRef = useRef < HTMLDivElement > ( null )
3134 const terminalRef = useRef < TerminalRef > ( null )
3235 const prevLogsLengthRef = useRef < number > ( 0 )
@@ -154,9 +157,20 @@ export function LogsPane({ task, onHeightChange }: LogsPaneProps) {
154157 prevLogsLengthRef . current = currentLogsLength
155158 } , [ task . logs ] )
156159
160+ // Helper function to filter logs based on current filter
161+ const getFilteredLogs = ( filter : LogFilterType ) => {
162+ return ( task . logs || [ ] ) . filter ( ( log ) => {
163+ const isServerLog = log . message . startsWith ( '[SERVER]' )
164+ if ( filter === 'server' ) return isServerLog
165+ if ( filter === 'platform' ) return ! isServerLog
166+ return true
167+ } )
168+ }
169+
157170 const copyLogsToClipboard = async ( ) => {
158171 try {
159- const logsText = ( task . logs || [ ] ) . map ( ( log ) => log . message ) . join ( '\n' )
172+ const filteredLogs = getFilteredLogs ( logFilter )
173+ const logsText = filteredLogs . map ( ( log ) => log . message ) . join ( '\n' )
160174
161175 await navigator . clipboard . writeText ( logsText )
162176 setCopiedLogs ( true )
@@ -279,7 +293,17 @@ export function LogsPane({ task, onHeightChange }: LogsPaneProps) {
279293 </ div >
280294 </ div >
281295 { activeTab === 'logs' && (
282- < div className = "flex items-center gap-1 mr-3" onClick = { ( e ) => e . stopPropagation ( ) } >
296+ < div className = "flex items-center gap-1.5 mr-3" onClick = { ( e ) => e . stopPropagation ( ) } >
297+ < Select value = { logFilter } onValueChange = { ( value ) => setLogFilter ( value as LogFilterType ) } >
298+ < SelectTrigger size = "sm" className = "h-6 text-xs px-2 py-0 min-w-[90px] border-0 shadow-none" >
299+ < SelectValue />
300+ </ SelectTrigger >
301+ < SelectContent >
302+ < SelectItem value = "all" > All</ SelectItem >
303+ < SelectItem value = "platform" > Platform</ SelectItem >
304+ < SelectItem value = "server" > Server</ SelectItem >
305+ </ SelectContent >
306+ </ Select >
283307 < Button
284308 variant = "ghost"
285309 size = "sm"
@@ -331,7 +355,7 @@ export function LogsPane({ task, onHeightChange }: LogsPaneProps) {
331355 ( isCollapsed || activeTab !== 'logs' ) && 'hidden' ,
332356 ) }
333357 >
334- { ( task . logs || [ ] ) . map ( ( log , index ) => {
358+ { getFilteredLogs ( logFilter ) . map ( ( log , index ) => {
335359 const isServerLog = log . message . startsWith ( '[SERVER]' )
336360 const messageContent = isServerLog ? log . message . substring ( 9 ) : log . message // Remove '[SERVER] '
337361
0 commit comments