MCPcopy Index your code
hub / github.com/winfunc/opcode / AgentRunOutputViewer

Function AgentRunOutputViewer

src/components/AgentRunOutputViewer.tsx:55–827  ·  view source on GitHub ↗
({ 
  agentRunId, 
  tabId,
  className 
}: AgentRunOutputViewerProps)

Source from the content-addressed store, hash-verified

53 * />
54 */
55export function AgentRunOutputViewer({
56 agentRunId,
57 tabId,
58 className
59}: AgentRunOutputViewerProps) {
60 const { updateTabTitle, updateTabStatus } = useTabState();
61 const [run, setRun] = useState<AgentRunWithMetrics | null>(null);
62 const [messages, setMessages] = useState<ClaudeStreamMessage[]>([]);
63 const [rawJsonlOutput, setRawJsonlOutput] = useState<string[]>([]);
64 const [loading, setLoading] = useState(true);
65 const [isFullscreen, setIsFullscreen] = useState(false);
66 const [refreshing, setRefreshing] = useState(false);
67 const [toast, setToast] = useState<{ message: string; type: "success" | "error" } | null>(null);
68 const [copyPopoverOpen, setCopyPopoverOpen] = useState(false);
69 const [hasUserScrolled, setHasUserScrolled] = useState(false);
70
71 // Track whether we're in the initial load phase
72 const isInitialLoadRef = useRef(true);
73 const hasSetupListenersRef = useRef(false);
74
75 const scrollAreaRef = useRef<HTMLDivElement>(null);
76 const outputEndRef = useRef<HTMLDivElement>(null);
77 const fullscreenScrollRef = useRef<HTMLDivElement>(null);
78 const fullscreenMessagesEndRef = useRef<HTMLDivElement>(null);
79 const unlistenRefs = useRef<UnlistenFn[]>([]);
80 const { getCachedOutput, setCachedOutput } = useOutputCache();
81
82 // Auto-scroll logic
83 const isAtBottom = () => {
84 const container = isFullscreen ? fullscreenScrollRef.current : scrollAreaRef.current;
85 if (container) {
86 const { scrollTop, scrollHeight, clientHeight } = container;
87 const distanceFromBottom = scrollHeight - scrollTop - clientHeight;
88 return distanceFromBottom < 1;
89 }
90 return true;
91 };
92
93 const scrollToBottom = () => {
94 if (!hasUserScrolled) {
95 const endRef = isFullscreen ? fullscreenMessagesEndRef.current : outputEndRef.current;
96 if (endRef) {
97 endRef.scrollIntoView({ behavior: 'smooth' });
98 }
99 }
100 };
101
102 // Load agent run on mount
103 useEffect(() => {
104 const loadAgentRun = async () => {
105 try {
106 setLoading(true);
107 const agentRun = await api.getAgentRun(parseInt(agentRunId));
108 setRun(agentRun);
109 updateTabTitle(tabId, `Agent: ${agentRun.agent_name || 'Unknown'}`);
110 updateTabStatus(tabId, agentRun.status === 'running' ? 'running' : agentRun.status === 'failed' ? 'error' : 'complete');
111 } catch (error) {
112 console.error('Failed to load agent run:', error);

Callers

nothing calls this directly

Calls 10

useTabStateFunction · 0.90
useOutputCacheFunction · 0.90
formatISOTimestampFunction · 0.90
loadAgentRunFunction · 0.85
isAtBottomFunction · 0.70
scrollToBottomFunction · 0.70
loadOutputFunction · 0.70
renderIconFunction · 0.70
formatDurationFunction · 0.70
formatTokensFunction · 0.70

Tested by

no test coverage detected