import * as React from 'react'; import { useShallow } from 'zustand/react/shallow'; import type { SxProps } from '@mui/joy/styles/types'; import { Box, Card, Chip, Divider, Sheet, Typography } from '@mui/joy'; import { RenderCodeMemo } from '~/modules/blocks/code/RenderCode'; import { ExpanderControlledBox } from '~/common/components/ExpanderControlledBox'; import { objectDeepCloneWithStringLimit } from '~/common/util/objectUtils'; import TimelapseIcon from '@mui/icons-material/Timelapse'; import type { AixClientDebugger } from './memstore-aix-client-debugger'; import { AixDebuggerMeasurementsTable } from './AixDebuggerMeasurementsTable'; import { useAixClientDebuggerStore } from './memstore-aix-client-debugger'; const _styles = { requestSheet: { // backgroundColor: 'background.popup', borderRadius: 'sm', boxShadow: 'md', // boxShadow: 'inset 2px 2px 4px -2px rgba(0, 0, 0, 0.2)', overflow: 'auto', // fontSize: 'calc(var(--joy-fontSize-xs) - 1px)', fontSize: 'xs', }, sheetTitle: { px: 1.5, py: 0.75, fontSize: 'sm', display: 'flex', justifyContent: 'space-between', }, sheetTitleClickable: { px: 1.5, py: 0.75, fontSize: 'sm', display: 'flex', justifyContent: 'space-between', cursor: 'pointer', userSelect: 'none', }, requestSheetParticles: { // backgroundColor: 'background.popup', borderRadius: 'sm', // boxShadow: 'md', overflow: 'auto', p: 1, fontFamily: 'code', fontSize: 'xs', lineHeight: 'xl', }, particleNorminal: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', }, particleAborted: { // ..._styles.particleNorminal, display: 'flex', justifyContent: 'space-between', alignItems: 'center', // change look backgroundColor: '#f9f9f9', borderLeft: '3px solid orange', }, pTime: { pl: 1, whiteSpace: 'nowrap', }, } as const satisfies Record; export function AixDebuggerFrame(props: { frame: AixClientDebugger.Frame; }) { // state: section open/close is kept in the debugger store so it persists across frame switches const { showHeaders, showBody, showParticles, toggleOpenState } = useAixClientDebuggerStore(useShallow(state => ({ showHeaders: !!state.openStates.headers, showBody: !!state.openStates.body, showParticles: !!state.openStates.particles, toggleOpenState: state.toggleOpenState, }))); const handleToggleShowHeaders = React.useCallback(() => toggleOpenState('headers'), [toggleOpenState]); const handleToggleShowBody = React.useCallback(() => toggleOpenState('body'), [toggleOpenState]); const handleToggleShowParticles = React.useCallback(() => toggleOpenState('particles'), [toggleOpenState]); const { frame } = props; const contextName = frame.context?.contextName || ''; const isConversation = contextName === 'conversation'; return ( {/* Frame Header */}
Request
#{frame.id}
Status:
{frame.transport === 'csf' ? 'Direct Connection' : 'Edge Server'} {frame.isComplete ? 'Done' : 'In Progress'}
Date
{new Date(frame.timestamp).toLocaleString()}
-> URL:
{decodeURIComponent(frame.url) || 'No URL data available'}
Context:
{contextName}
Reference:
{frame.context.contextRef}
{/* Headers */} -> Headers {showHeaders ? 'hide' : 'show headers'} {frame.headers ? ( ) : ( No headers data available )} {/* Body */} -> Body {frame.bodySize > 0 && {frame.bodySize.toLocaleString()} bytes} {frame.body ? ( ) : ( Waiting for transmitted body data... )} {/* Particles List */} <- Particles {!frame.isComplete && ' - In Progress...'}{frame.particles.length > 0 && ` (${frame.particles.length})`} {showParticles ? 'hide' : 'show particles'} {showParticles && {/* Zero state */} {!frame.particles.length &&
No particles received yet
} {/* List of particles */} {frame.particles.map((particle, idx) => { // preview of particle content: preserve structure, trim long string fields let jsonPreview = ''; try { jsonPreview = JSON.stringify(objectDeepCloneWithStringLimit(particle.content, 'aix-debugger-particle', 64)); } catch (e) { jsonPreview = 'Error parsing content'; } return ( {idx + 1}: {particle.isAborted ? ' (Aborted)' : ''} {jsonPreview} {new Date(particle.timestamp).toLocaleTimeString()} ); })}
}
{/* Performance Profiler */} {!!frame.profilerMeasurements?.length && ( } sx={{ ..._styles.sheetTitle, justifyContent: undefined }}> Internal Profiler: {!!frame.profilerMeasurements?.length ? ( ) : ( 'No profiler measurements available. Note: profiling is not available in production.' )} )}
); }