) => {
+ if (manualRead) return;
+ setManualRead(true);
+ void read().finally(() => setManualRead(false));
+ };
+ const refreshRun = () =>
+ readManually(async () => {
+ const refreshed = await traceQuery.refetch();
+ if (refreshed.isError) return;
+ const contentRef = refreshed.data?.pages[0].summary.trace_ref ?? traceRef;
+ await queryClient.invalidateQueries({
+ queryKey: ["agentTraceSpan", traceId, contentRef],
+ predicate: (query) => query.queryKey.at(-1) === accessToken,
+ });
+ });
+ const toggleLive = () => {
+ if (live && !manualRead && !traceQuery.isFetchingNextPage) {
+ void queryClient.cancelQueries({ queryKey, exact: true });
+ }
+ setLive((enabled) => !enabled);
+ };
const trace = useMemo(() => {
const pages = traceQuery.data.pages;
return {
@@ -116,11 +140,11 @@ function LoadedRun({
};
}, [traceQuery.data]);
const seekingSpan = !switching && selectedSpanMissing(trace, selection.spanId);
- const { hasNextPage, isFetching, isError, fetchNextPage } = traceQuery;
+ const { hasNextPage, isFetching, isFetchNextPageError, fetchNextPage } = traceQuery;
const canSeek = seekingSpan && hasNextPage;
useEffect(() => {
- if (canSeek && !isFetching && !isError) void fetchNextPage();
- }, [canSeek, isFetching, isError, fetchNextPage]);
+ if (canSeek && !isFetching && !isFetchNextPageError) void fetchNextPage();
+ }, [canSeek, isFetching, isFetchNextPageError, fetchNextPage]);
return (
+ {traceQuery.isRefetchError && (
+
+ Could not refresh this run. Previously received steps are still shown.
+
+
+ )}
{(traceQuery.hasNextPage || failure) && (
void traceQuery.fetchNextPage()}
- onRefresh={() => void refreshTrace()}
+ busy={manualRead || traceQuery.isFetching}
+ onLoadMore={() => readManually(() => traceQuery.fetchNextPage())}
+ onRefresh={() => readManually(refreshTrace)}
/>
)}