mirror of https://github.com/buster-so/buster.git
add reasoning page
This commit is contained in:
parent
2dbe578f3a
commit
5d99659307
|
@ -1,6 +1,7 @@
|
|||
'use client';
|
||||
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { ClientOnly } from '@tanstack/react-router';
|
||||
import isEmpty from 'lodash/isEmpty';
|
||||
import type React from 'react';
|
||||
import { useEffect, useMemo, useRef } from 'react';
|
||||
|
@ -11,6 +12,7 @@ import { FileIndeterminateLoader } from '@/components/features/loaders/FileIndet
|
|||
import { ScrollArea } from '@/components/ui/scroll-area';
|
||||
import { useGetBlackBoxMessage } from '@/context/BlackBox/blackbox-store';
|
||||
import { useAutoScroll } from '@/hooks/useAutoScroll';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { ReasoningMessageSelector } from './ReasoningMessages';
|
||||
import { BlackBoxMessage } from './ReasoningMessages/ReasoningBlackBoxMessage';
|
||||
|
||||
|
@ -41,10 +43,11 @@ export const ReasoningController: React.FC<ReasoningControllerProps> = ({ chatId
|
|||
|
||||
const viewportRef = useRef<HTMLDivElement | null>(null);
|
||||
|
||||
const { isAutoScrollEnabled, scrollToBottom, enableAutoScroll } = useAutoScroll(viewportRef, {
|
||||
observeSubTree: true,
|
||||
enabled: !!viewportRef.current,
|
||||
});
|
||||
const { isAutoScrollEnabled, isMountedAutoScrollObserver, scrollToBottom, enableAutoScroll } =
|
||||
useAutoScroll(viewportRef, {
|
||||
observeSubTree: true,
|
||||
enabled: !isStreamFinished,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (hasChat && reasoningMessageIds) {
|
||||
|
@ -57,7 +60,12 @@ export const ReasoningController: React.FC<ReasoningControllerProps> = ({ chatId
|
|||
return (
|
||||
<>
|
||||
<ScrollArea viewportRef={viewportRef} className="h-full">
|
||||
<div className="h-full flex-col space-y-0.5 overflow-y-auto p-5">
|
||||
<div
|
||||
className={cn(
|
||||
'h-full flex-col space-y-0.5 overflow-y-auto p-5',
|
||||
!isMountedAutoScrollObserver && 'invisible'
|
||||
)}
|
||||
>
|
||||
{reasoningMessageIds?.map((reasoningMessageId, messageIndex) => (
|
||||
<ReasoningMessageSelector
|
||||
key={reasoningMessageId}
|
||||
|
@ -77,10 +85,12 @@ export const ReasoningController: React.FC<ReasoningControllerProps> = ({ chatId
|
|||
</div>
|
||||
</ScrollArea>
|
||||
|
||||
<ScrollToBottomButton
|
||||
isAutoScrollEnabled={isAutoScrollEnabled}
|
||||
scrollToBottom={scrollToBottom}
|
||||
/>
|
||||
{viewportRef.current && (
|
||||
<ScrollToBottomButton
|
||||
isAutoScrollEnabled={isAutoScrollEnabled}
|
||||
scrollToBottom={scrollToBottom}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -44,6 +44,8 @@ interface UseAutoScrollReturn {
|
|||
enableAutoScroll: () => void;
|
||||
/** Disable auto–scroll */
|
||||
disableAutoScroll: () => void;
|
||||
/** Whether the auto-scroll observer is mounted */
|
||||
isMountedAutoScrollObserver: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -79,7 +81,7 @@ export const useAutoScroll = (
|
|||
observeAttributes = false,
|
||||
animationCooldown = 500,
|
||||
} = options;
|
||||
|
||||
const [isMountedAutoScrollObserver, setMountedAutoScrollObserver] = useState(enabled);
|
||||
const [isAutoScrollEnabled, setIsAutoScrollEnabled] = useState(enabled);
|
||||
const observerRef = useRef<MutationObserver | null>(null);
|
||||
const rAFIdRef = useRef<number | null>(null);
|
||||
|
@ -294,6 +296,7 @@ export const useAutoScroll = (
|
|||
|
||||
const enableAutoScroll = useCallback(() => {
|
||||
setIsAutoScrollEnabled(true);
|
||||
setMountedAutoScrollObserver(true);
|
||||
}, []);
|
||||
|
||||
const disableAutoScroll = useCallback(() => {
|
||||
|
@ -302,6 +305,7 @@ export const useAutoScroll = (
|
|||
|
||||
return {
|
||||
isAutoScrollEnabled,
|
||||
isMountedAutoScrollObserver,
|
||||
scrollToBottom,
|
||||
scrollToTop,
|
||||
scrollToNode,
|
||||
|
|
|
@ -14,12 +14,12 @@ const autoClass = 'mx-auto max-w-[600px] w-full';
|
|||
export const ChatContent: React.FC<{ chatId: string | undefined }> = React.memo(({ chatId }) => {
|
||||
const chatMessageIds = useGetChatMessageIds(chatId);
|
||||
const containerRef = useRef<HTMLElement>(null);
|
||||
const [isMounted, setIsMounted] = useState(false);
|
||||
|
||||
const { isAutoScrollEnabled, scrollToBottom, enableAutoScroll } = useAutoScroll(containerRef, {
|
||||
observeSubTree: true,
|
||||
enabled: false,
|
||||
});
|
||||
const { isAutoScrollEnabled, isMountedAutoScrollObserver, scrollToBottom, enableAutoScroll } =
|
||||
useAutoScroll(containerRef, {
|
||||
observeSubTree: true,
|
||||
enabled: false,
|
||||
});
|
||||
|
||||
useMount(() => {
|
||||
const container = document
|
||||
|
@ -28,14 +28,19 @@ export const ChatContent: React.FC<{ chatId: string | undefined }> = React.memo(
|
|||
if (!container) return;
|
||||
containerRef.current = container;
|
||||
enableAutoScroll();
|
||||
setIsMounted(true);
|
||||
console.log('mounted chat content', isMountedAutoScrollObserver);
|
||||
});
|
||||
|
||||
const showScrollToBottomButton = isMounted && containerRef.current;
|
||||
const showScrollToBottomButton = isMountedAutoScrollObserver && containerRef.current;
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className={cn('mb-48 flex h-full w-full flex-col', !isMounted && 'invisible')}>
|
||||
<div
|
||||
className={cn(
|
||||
'mb-48 flex h-full w-full flex-col',
|
||||
!isMountedAutoScrollObserver && 'invisible'
|
||||
)}
|
||||
>
|
||||
<ClientOnly>
|
||||
{chatMessageIds?.map((messageId, index) => (
|
||||
<div key={messageId} className={autoClass}>
|
||||
|
|
|
@ -58,6 +58,7 @@ import { Route as AppAppAssetReportsReportIdLayoutContentRouteImport } from './r
|
|||
import { Route as AppAppAssetMetricsMetricIdLayoutSqlRouteImport } from './routes/app/_app/_asset/metrics.$metricId/_layout/sql'
|
||||
import { Route as AppAppAssetMetricsMetricIdLayoutResultsRouteImport } from './routes/app/_app/_asset/metrics.$metricId/_layout/results'
|
||||
import { Route as AppAppAssetMetricsMetricIdLayoutChartRouteImport } from './routes/app/_app/_asset/metrics.$metricId/_layout/chart'
|
||||
import { Route as AppAppAssetChatsChatIdReasoningMessageIdIndexRouteImport } from './routes/app/_app/_asset/chats.$chatId/reasoning.$messageId/index'
|
||||
import { Route as AppAppAssetReportsReportIdMetricsMetricIdContentRouteImport } from './routes/app/_app/_asset/reports.$reportId/metrics.$metricId/_content'
|
||||
import { Route as AppAppAssetDashboardsDashboardIdMetricsMetricIdContentRouteImport } from './routes/app/_app/_asset/dashboards.$dashboardId/metrics.$metricId/_content'
|
||||
import { Route as AppAppAssetChatsChatIdReportsReportIdLayoutRouteImport } from './routes/app/_app/_asset/chats.$chatId/reports.$reportId/_layout'
|
||||
|
@ -422,6 +423,12 @@ const AppAppAssetMetricsMetricIdLayoutChartRoute =
|
|||
path: '/chart',
|
||||
getParentRoute: () => AppAppAssetMetricsMetricIdLayoutRoute,
|
||||
} as any)
|
||||
const AppAppAssetChatsChatIdReasoningMessageIdIndexRoute =
|
||||
AppAppAssetChatsChatIdReasoningMessageIdIndexRouteImport.update({
|
||||
id: '/reasoning/$messageId/',
|
||||
path: '/reasoning/$messageId/',
|
||||
getParentRoute: () => AppAppAssetChatsChatIdRoute,
|
||||
} as any)
|
||||
const AppAppAssetReportsReportIdMetricsMetricIdContentRoute =
|
||||
AppAppAssetReportsReportIdMetricsMetricIdContentRouteImport.update({
|
||||
id: '/_content',
|
||||
|
@ -703,6 +710,7 @@ export interface FileRoutesByFullPath {
|
|||
'/app/chats/$chatId/reports/$reportId': typeof AppAppAssetChatsChatIdReportsReportIdLayoutRouteWithChildren
|
||||
'/app/dashboards/$dashboardId/metrics/$metricId': typeof AppAppAssetDashboardsDashboardIdMetricsMetricIdContentRouteWithChildren
|
||||
'/app/reports/$reportId/metrics/$metricId': typeof AppAppAssetReportsReportIdMetricsMetricIdContentRouteWithChildren
|
||||
'/app/chats/$chatId/reasoning/$messageId': typeof AppAppAssetChatsChatIdReasoningMessageIdIndexRoute
|
||||
'/app/chats/$chatId/metrics/$metricId/chart': typeof AppAppAssetChatsChatIdMetricsMetricIdLayoutChartRoute
|
||||
'/app/chats/$chatId/metrics/$metricId/results': typeof AppAppAssetChatsChatIdMetricsMetricIdLayoutResultsRoute
|
||||
'/app/chats/$chatId/metrics/$metricId/sql': typeof AppAppAssetChatsChatIdMetricsMetricIdLayoutSqlRoute
|
||||
|
@ -773,6 +781,7 @@ export interface FileRoutesByTo {
|
|||
'/app/chats/$chatId/reports/$reportId': typeof AppAppAssetChatsChatIdReportsReportIdLayoutIndexRoute
|
||||
'/app/dashboards/$dashboardId/metrics/$metricId': typeof AppAppAssetDashboardsDashboardIdMetricsMetricIdContentIndexRoute
|
||||
'/app/reports/$reportId/metrics/$metricId': typeof AppAppAssetReportsReportIdMetricsMetricIdContentIndexRoute
|
||||
'/app/chats/$chatId/reasoning/$messageId': typeof AppAppAssetChatsChatIdReasoningMessageIdIndexRoute
|
||||
'/app/chats/$chatId/metrics/$metricId/chart': typeof AppAppAssetChatsChatIdMetricsMetricIdLayoutChartRoute
|
||||
'/app/chats/$chatId/metrics/$metricId/results': typeof AppAppAssetChatsChatIdMetricsMetricIdLayoutResultsRoute
|
||||
'/app/chats/$chatId/metrics/$metricId/sql': typeof AppAppAssetChatsChatIdMetricsMetricIdLayoutSqlRoute
|
||||
|
@ -853,6 +862,7 @@ export interface FileRoutesById {
|
|||
'/app/_app/_asset/dashboards/$dashboardId/metrics/$metricId/_content': typeof AppAppAssetDashboardsDashboardIdMetricsMetricIdContentRouteWithChildren
|
||||
'/app/_app/_asset/reports/$reportId/metrics/$metricId': typeof AppAppAssetReportsReportIdMetricsMetricIdRouteWithChildren
|
||||
'/app/_app/_asset/reports/$reportId/metrics/$metricId/_content': typeof AppAppAssetReportsReportIdMetricsMetricIdContentRouteWithChildren
|
||||
'/app/_app/_asset/chats/$chatId/reasoning/$messageId/': typeof AppAppAssetChatsChatIdReasoningMessageIdIndexRoute
|
||||
'/app/_app/_asset/chats/$chatId/metrics/$metricId/_layout/chart': typeof AppAppAssetChatsChatIdMetricsMetricIdLayoutChartRoute
|
||||
'/app/_app/_asset/chats/$chatId/metrics/$metricId/_layout/results': typeof AppAppAssetChatsChatIdMetricsMetricIdLayoutResultsRoute
|
||||
'/app/_app/_asset/chats/$chatId/metrics/$metricId/_layout/sql': typeof AppAppAssetChatsChatIdMetricsMetricIdLayoutSqlRoute
|
||||
|
@ -932,6 +942,7 @@ export interface FileRouteTypes {
|
|||
| '/app/chats/$chatId/reports/$reportId'
|
||||
| '/app/dashboards/$dashboardId/metrics/$metricId'
|
||||
| '/app/reports/$reportId/metrics/$metricId'
|
||||
| '/app/chats/$chatId/reasoning/$messageId'
|
||||
| '/app/chats/$chatId/metrics/$metricId/chart'
|
||||
| '/app/chats/$chatId/metrics/$metricId/results'
|
||||
| '/app/chats/$chatId/metrics/$metricId/sql'
|
||||
|
@ -1002,6 +1013,7 @@ export interface FileRouteTypes {
|
|||
| '/app/chats/$chatId/reports/$reportId'
|
||||
| '/app/dashboards/$dashboardId/metrics/$metricId'
|
||||
| '/app/reports/$reportId/metrics/$metricId'
|
||||
| '/app/chats/$chatId/reasoning/$messageId'
|
||||
| '/app/chats/$chatId/metrics/$metricId/chart'
|
||||
| '/app/chats/$chatId/metrics/$metricId/results'
|
||||
| '/app/chats/$chatId/metrics/$metricId/sql'
|
||||
|
@ -1081,6 +1093,7 @@ export interface FileRouteTypes {
|
|||
| '/app/_app/_asset/dashboards/$dashboardId/metrics/$metricId/_content'
|
||||
| '/app/_app/_asset/reports/$reportId/metrics/$metricId'
|
||||
| '/app/_app/_asset/reports/$reportId/metrics/$metricId/_content'
|
||||
| '/app/_app/_asset/chats/$chatId/reasoning/$messageId/'
|
||||
| '/app/_app/_asset/chats/$chatId/metrics/$metricId/_layout/chart'
|
||||
| '/app/_app/_asset/chats/$chatId/metrics/$metricId/_layout/results'
|
||||
| '/app/_app/_asset/chats/$chatId/metrics/$metricId/_layout/sql'
|
||||
|
@ -1520,6 +1533,13 @@ declare module '@tanstack/react-router' {
|
|||
preLoaderRoute: typeof AppAppAssetMetricsMetricIdLayoutChartRouteImport
|
||||
parentRoute: typeof AppAppAssetMetricsMetricIdLayoutRoute
|
||||
}
|
||||
'/app/_app/_asset/chats/$chatId/reasoning/$messageId/': {
|
||||
id: '/app/_app/_asset/chats/$chatId/reasoning/$messageId/'
|
||||
path: '/reasoning/$messageId'
|
||||
fullPath: '/app/chats/$chatId/reasoning/$messageId'
|
||||
preLoaderRoute: typeof AppAppAssetChatsChatIdReasoningMessageIdIndexRouteImport
|
||||
parentRoute: typeof AppAppAssetChatsChatIdRoute
|
||||
}
|
||||
'/app/_app/_asset/reports/$reportId/metrics/$metricId/_content': {
|
||||
id: '/app/_app/_asset/reports/$reportId/metrics/$metricId/_content'
|
||||
path: '/metrics/$metricId'
|
||||
|
@ -1949,6 +1969,7 @@ interface AppAppAssetChatsChatIdRouteChildren {
|
|||
AppAppAssetChatsChatIdDashboardsDashboardIdRoute: typeof AppAppAssetChatsChatIdDashboardsDashboardIdRouteWithChildren
|
||||
AppAppAssetChatsChatIdMetricsMetricIdRoute: typeof AppAppAssetChatsChatIdMetricsMetricIdRouteWithChildren
|
||||
AppAppAssetChatsChatIdReportsReportIdRoute: typeof AppAppAssetChatsChatIdReportsReportIdRouteWithChildren
|
||||
AppAppAssetChatsChatIdReasoningMessageIdIndexRoute: typeof AppAppAssetChatsChatIdReasoningMessageIdIndexRoute
|
||||
}
|
||||
|
||||
const AppAppAssetChatsChatIdRouteChildren: AppAppAssetChatsChatIdRouteChildren =
|
||||
|
@ -1960,6 +1981,8 @@ const AppAppAssetChatsChatIdRouteChildren: AppAppAssetChatsChatIdRouteChildren =
|
|||
AppAppAssetChatsChatIdMetricsMetricIdRouteWithChildren,
|
||||
AppAppAssetChatsChatIdReportsReportIdRoute:
|
||||
AppAppAssetChatsChatIdReportsReportIdRouteWithChildren,
|
||||
AppAppAssetChatsChatIdReasoningMessageIdIndexRoute:
|
||||
AppAppAssetChatsChatIdReasoningMessageIdIndexRoute,
|
||||
}
|
||||
|
||||
const AppAppAssetChatsChatIdRouteWithChildren =
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
import { createFileRoute } from '@tanstack/react-router';
|
||||
import { ReasoningController } from '@/controllers/ReasoningController/ReasoningController';
|
||||
|
||||
export const Route = createFileRoute('/app/_app/_asset/chats/$chatId/reasoning/$messageId/')({
|
||||
component: RouteComponent,
|
||||
});
|
||||
|
||||
function RouteComponent() {
|
||||
const { chatId, messageId } = Route.useParams();
|
||||
return <ReasoningController chatId={chatId} messageId={messageId} />;
|
||||
}
|
Loading…
Reference in New Issue