mirror of
https://github.com/khoaliber/khoj.git
synced 2026-03-03 05:29:12 +00:00
Persist the train of thought in the conversation history
This commit is contained in:
@@ -13,13 +13,14 @@ import { ScrollArea } from "@/components/ui/scroll-area";
|
||||
|
||||
import { InlineLoading } from "../loading/loading";
|
||||
|
||||
import { Lightbulb, ArrowDown } from "@phosphor-icons/react";
|
||||
import { Lightbulb, ArrowDown, XCircle } from "@phosphor-icons/react";
|
||||
|
||||
import AgentProfileCard from "../profileCard/profileCard";
|
||||
import { getIconFromIconName } from "@/app/common/iconUtils";
|
||||
import { AgentData } from "@/app/agents/page";
|
||||
import React from "react";
|
||||
import { useIsMobileWidth } from "@/app/common/utils";
|
||||
import { Button } from "@/components/ui/button";
|
||||
|
||||
interface ChatResponse {
|
||||
status: string;
|
||||
@@ -40,26 +41,51 @@ interface ChatHistoryProps {
|
||||
customClassName?: string;
|
||||
}
|
||||
|
||||
function constructTrainOfThought(
|
||||
trainOfThought: string[],
|
||||
lastMessage: boolean,
|
||||
agentColor: string,
|
||||
key: string,
|
||||
completed: boolean = false,
|
||||
) {
|
||||
const lastIndex = trainOfThought.length - 1;
|
||||
return (
|
||||
<div className={`${styles.trainOfThought} shadow-sm`} key={key}>
|
||||
{!completed && <InlineLoading className="float-right" />}
|
||||
interface TrainOfThoughtComponentProps {
|
||||
trainOfThought: string[];
|
||||
lastMessage: boolean;
|
||||
agentColor: string;
|
||||
key: string;
|
||||
completed?: boolean;
|
||||
}
|
||||
|
||||
{trainOfThought.map((train, index) => (
|
||||
<TrainOfThought
|
||||
key={`train-${index}`}
|
||||
message={train}
|
||||
primary={index === lastIndex && lastMessage && !completed}
|
||||
agentColor={agentColor}
|
||||
/>
|
||||
))}
|
||||
function TrainOfThoughtComponent(props: TrainOfThoughtComponentProps) {
|
||||
const lastIndex = props.trainOfThought.length - 1;
|
||||
const [collapsed, setCollapsed] = useState(props.completed);
|
||||
|
||||
return (
|
||||
<div className={`${!collapsed ? styles.trainOfThought : ""} shadow-sm`} key={props.key}>
|
||||
{!props.completed && <InlineLoading className="float-right" />}
|
||||
{collapsed ? (
|
||||
<Button
|
||||
className="w-fit text-left justify-start content-start text-xs"
|
||||
onClick={() => setCollapsed(false)}
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
>
|
||||
What was my train of thought?
|
||||
</Button>
|
||||
) : (
|
||||
<Button
|
||||
className="w-fit text-left justify-start content-start text-xs"
|
||||
onClick={() => setCollapsed(true)}
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
>
|
||||
<XCircle size={16} className="mr-1" />
|
||||
Close
|
||||
</Button>
|
||||
)}
|
||||
|
||||
{!collapsed &&
|
||||
props.trainOfThought.map((train, index) => (
|
||||
<TrainOfThought
|
||||
key={`train-${index}`}
|
||||
message={train}
|
||||
primary={index === lastIndex && props.lastMessage && !props.completed}
|
||||
agentColor={props.agentColor}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -265,25 +291,39 @@ export default function ChatHistory(props: ChatHistoryProps) {
|
||||
{data &&
|
||||
data.chat &&
|
||||
data.chat.map((chatMessage, index) => (
|
||||
<ChatMessage
|
||||
key={`${index}fullHistory`}
|
||||
ref={
|
||||
// attach ref to the second last message to handle scroll on page load
|
||||
index === data.chat.length - 2
|
||||
? latestUserMessageRef
|
||||
: // attach ref to the newest fetched message to handle scroll on fetch
|
||||
// note: stabilize index selection against last page having less messages than fetchMessageCount
|
||||
index ===
|
||||
data.chat.length - (currentPage - 1) * fetchMessageCount
|
||||
? latestFetchedMessageRef
|
||||
: null
|
||||
}
|
||||
isMobileWidth={isMobileWidth}
|
||||
chatMessage={chatMessage}
|
||||
customClassName="fullHistory"
|
||||
borderLeftColor={`${data?.agent?.color}-500`}
|
||||
isLastMessage={index === data.chat.length - 1}
|
||||
/>
|
||||
<>
|
||||
{chatMessage.trainOfThought && chatMessage.by === "khoj" && (
|
||||
<TrainOfThoughtComponent
|
||||
trainOfThought={chatMessage.trainOfThought?.map(
|
||||
(train) => train.data,
|
||||
)}
|
||||
lastMessage={false}
|
||||
agentColor={data?.agent?.color || "orange"}
|
||||
key={`${index}trainOfThought`}
|
||||
completed={true}
|
||||
/>
|
||||
)}
|
||||
<ChatMessage
|
||||
key={`${index}fullHistory`}
|
||||
ref={
|
||||
// attach ref to the second last message to handle scroll on page load
|
||||
index === data.chat.length - 2
|
||||
? latestUserMessageRef
|
||||
: // attach ref to the newest fetched message to handle scroll on fetch
|
||||
// note: stabilize index selection against last page having less messages than fetchMessageCount
|
||||
index ===
|
||||
data.chat.length -
|
||||
(currentPage - 1) * fetchMessageCount
|
||||
? latestFetchedMessageRef
|
||||
: null
|
||||
}
|
||||
isMobileWidth={isMobileWidth}
|
||||
chatMessage={chatMessage}
|
||||
customClassName="fullHistory"
|
||||
borderLeftColor={`${data?.agent?.color}-500`}
|
||||
isLastMessage={index === data.chat.length - 1}
|
||||
/>
|
||||
</>
|
||||
))}
|
||||
{props.incomingMessages &&
|
||||
props.incomingMessages.map((message, index) => {
|
||||
@@ -305,14 +345,15 @@ export default function ChatHistory(props: ChatHistoryProps) {
|
||||
customClassName="fullHistory"
|
||||
borderLeftColor={`${data?.agent?.color}-500`}
|
||||
/>
|
||||
{message.trainOfThought &&
|
||||
constructTrainOfThought(
|
||||
message.trainOfThought,
|
||||
index === incompleteIncomingMessageIndex,
|
||||
data?.agent?.color || "orange",
|
||||
`${index}trainOfThought`,
|
||||
message.completed,
|
||||
)}
|
||||
{message.trainOfThought && (
|
||||
<TrainOfThoughtComponent
|
||||
trainOfThought={message.trainOfThought}
|
||||
lastMessage={index === incompleteIncomingMessageIndex}
|
||||
agentColor={data?.agent?.color || "orange"}
|
||||
key={`${index}trainOfThought`}
|
||||
completed={message.completed}
|
||||
/>
|
||||
)}
|
||||
<ChatMessage
|
||||
key={`${index}incoming`}
|
||||
isMobileWidth={isMobileWidth}
|
||||
|
||||
Reference in New Issue
Block a user