Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🔍 feat: Show Messages from Search Result #2699

Merged
merged 19 commits into from
May 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
1aea8d8
refactor(Nav): delegate Search-specific variables/hooks to SearchContext
danny-avila May 13, 2024
62b9736
fix: safely determine firstTodayConvoId if convo is undefined
danny-avila May 13, 2024
d1ed32b
chore: remove empty line
danny-avila May 13, 2024
9f33ae0
feat: initial render of search messages
danny-avila May 13, 2024
db163a5
feat: SearchButtons
danny-avila May 13, 2024
c25050c
update Ko.ts
danny-avila May 13, 2024
981924b
update localizations with new key phrases
danny-avila May 13, 2024
3a4e316
chore: localization comparisons
danny-avila May 13, 2024
ffb758c
fix: clear conversation state on searchQuery navigation
danny-avila May 14, 2024
285eef2
style: search messages view styling
danny-avila May 14, 2024
f9bac65
refactor(Convo): consolidate logic to navigateWithLastTools from useN…
danny-avila May 14, 2024
1d2839d
fix(SearchButtons): styling and correct navigation logic
danny-avila May 14, 2024
6315fc4
fix(SearchBar): invalidate all message queries and invoke `clearText`…
danny-avila May 14, 2024
7492f49
refactor(NewChat): consolidate new chat button logic to NewChatButton…
danny-avila May 14, 2024
6faa531
chore: localizations for Nav date groups
danny-avila May 14, 2024
b94691d
chore: update comparisons
danny-avila May 14, 2024
00136ff
fix: early return from sendRequest to avoid quick searchQuery reset
danny-avila May 14, 2024
0a68b07
style: Link Icon
danny-avila May 14, 2024
cab04ff
chore: bump tiktoken, use o200k_base for gpt-4o
danny-avila May 14, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion api/app/clients/OpenAIClient.js
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ class OpenAIClient extends BaseClient {
let tokenizer;
this.encoding = 'text-davinci-003';
if (this.isChatCompletion) {
this.encoding = 'cl100k_base';
this.encoding = this.modelOptions.model.includes('gpt-4o') ? 'o200k_base' : 'cl100k_base';
tokenizer = this.constructor.getTokenizer(this.encoding);
} else if (this.isUnofficialChatGptModel) {
const extendSpecialTokens = {
Expand Down
2 changes: 1 addition & 1 deletion api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@
"passport-local": "^1.0.0",
"pino": "^8.12.1",
"sharp": "^0.32.6",
"tiktoken": "^1.0.10",
"tiktoken": "^1.0.15",
"traverse": "^0.6.7",
"ua-parser-js": "^1.0.36",
"winston": "^3.11.0",
Expand Down
6 changes: 6 additions & 0 deletions client/src/Providers/SearchContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { createContext, useContext } from 'react';
import useSearch from '~/hooks/Conversations/useSearch';
type SearchContextType = ReturnType<typeof useSearch>;

export const SearchContext = createContext<SearchContextType>({} as SearchContextType);
export const useSearchContext = () => useContext(SearchContext);
1 change: 1 addition & 0 deletions client/src/Providers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export { default as ToastProvider } from './ToastContext';
export { default as AssistantsProvider } from './AssistantsContext';
export * from './ChatContext';
export * from './ToastContext';
export * from './SearchContext';
export * from './FileMapContext';
export * from './AssistantsContext';
export * from './AssistantsMapContext';
53 changes: 53 additions & 0 deletions client/src/components/Chat/Messages/Content/SearchContent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { Suspense } from 'react';
import type { TMessage, TMessageContentParts } from 'librechat-data-provider';
import { UnfinishedMessage } from './MessageContent';
import { DelayedRender } from '~/components/ui';
import MarkdownLite from './MarkdownLite';
import { cn } from '~/utils';
import Part from './Part';

const SearchContent = ({ message }: { message: TMessage }) => {
const { messageId } = message;
if (Array.isArray(message.content) && message.content.length > 0) {
return (
<>
{message.content
.filter((part: TMessageContentParts | undefined) => part)
.map((part: TMessageContentParts | undefined, idx: number) => {
if (!part) {
return null;
}
return (
<Part
key={`display-${messageId}-${idx}`}
showCursor={false}
isSubmitting={false}
part={part}
message={message}
/>
);
})}
{message.unfinished && (
<Suspense>
<DelayedRender delay={250}>
<UnfinishedMessage message={message} key={`unfinished-${messageId}`} />
</DelayedRender>
</Suspense>
)}
</>
);
}

return (
<div
className={cn(
'markdown prose dark:prose-invert light w-full break-words',
message.isCreatedByUser ? 'whitespace-pre-wrap dark:text-gray-20' : 'dark:text-gray-70',
)}
>
<MarkdownLite content={message.text ?? ''} />
</div>
);
};

export default SearchContent;
42 changes: 42 additions & 0 deletions client/src/components/Chat/Messages/MinimalMessages.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import React from 'react';
import { cn } from '~/utils';

const MinimalMessages = React.forwardRef(
(
props: { children: React.ReactNode; className?: string },
ref: React.ForwardedRef<HTMLDivElement>,
) => {
return (
<div
className={cn(
'relative flex w-full grow overflow-hidden bg-white dark:bg-gray-800',
props.className,
)}
>
<div className="transition-width relative h-full w-full flex-1 overflow-auto bg-white dark:bg-gray-800">
<div className="flex h-full flex-col" role="presentation" tabIndex={0}>
<div className="flex-1 overflow-hidden overflow-y-auto">
<div className="dark:gpt-dark-gray relative h-full">
<div
ref={ref}
style={{
height: '100%',
overflowY: 'auto',
width: '100%',
}}
>
<div className="flex flex-col pb-9 text-sm dark:bg-transparent">
{props.children}
<div className="dark:gpt-dark-gray group h-0 w-full flex-shrink-0 dark:border-gray-800/50" />
</div>
</div>
</div>
</div>
</div>
</div>
</div>
);
},
);

export default MinimalMessages;
40 changes: 40 additions & 0 deletions client/src/components/Chat/Messages/SearchButtons.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { Link } from 'lucide-react';
import type { TMessage } from 'librechat-data-provider';
import { useLocalize, useNavigateToConvo } from '~/hooks';
import { useSearchContext } from '~/Providers';
import { getConversationById } from '~/utils';

export default function SearchButtons({ message }: { message: TMessage }) {
const localize = useLocalize();
const { searchQueryRes } = useSearchContext();
const { navigateWithLastTools } = useNavigateToConvo();

if (!message.conversationId) {
return null;
}

const clickHandler = (event: React.MouseEvent<HTMLAnchorElement>) => {
event.preventDefault();

const conversation = getConversationById(searchQueryRes?.data, message.conversationId);
if (!conversation) {
return;
}

document.title = message.title ?? '';
navigateWithLastTools(conversation);
};

return (
<div className="visible mt-0 flex items-center justify-center gap-1 self-end text-gray-400 lg:justify-start">
<a
className="ml-0 flex cursor-pointer items-center gap-1.5 rounded-md p-1 text-xs hover:text-gray-900 hover:underline dark:text-gray-400/70 dark:hover:text-gray-200 disabled:dark:hover:text-gray-400"
onClick={clickHandler}
title={localize('com_ui_go_to_conversation')}
>
<Link className="icon-sm" />
{message.title}
</a>
</div>
);
}
61 changes: 61 additions & 0 deletions client/src/components/Chat/Messages/SearchMessage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { useRecoilValue } from 'recoil';
import { useAuthContext, useLocalize } from '~/hooks';
import type { TMessageProps } from '~/common';
import Icon from '~/components/Chat/Messages/MessageIcon';
import SearchContent from './Content/SearchContent';
import SearchButtons from './SearchButtons';
import SubRow from './SubRow';
import { cn } from '~/utils';
import store from '~/store';

export default function Message({ message }: Pick<TMessageProps, 'message'>) {
const UsernameDisplay = useRecoilValue<boolean>(store.UsernameDisplay);
const { user } = useAuthContext();
const localize = useLocalize();

if (!message) {
return null;
}

const { isCreatedByUser } = message ?? {};

let messageLabel = '';
if (isCreatedByUser) {
messageLabel = UsernameDisplay ? user?.name || user?.username : localize('com_user_message');
} else {
messageLabel = message.sender;
}

return (
<>
<div className="text-token-text-primary w-full border-0 bg-transparent dark:border-0 dark:bg-transparent">
<div className="m-auto justify-center p-4 py-2 text-base md:gap-6 ">
<div className="final-completion group mx-auto flex flex-1 gap-3 text-base md:max-w-3xl md:px-5 lg:max-w-[40rem] lg:px-1 xl:max-w-[48rem] xl:px-5">
<div className="relative flex flex-shrink-0 flex-col items-end">
<div>
<div className="pt-0.5">
<div className="flex h-6 w-6 items-center justify-center overflow-hidden rounded-full">
<Icon message={message} />
</div>
</div>
</div>
</div>
<div
className={cn('relative flex w-11/12 flex-col', isCreatedByUser ? '' : 'agent-turn')}
>
<div className="select-none font-semibold">{messageLabel}</div>
<div className="flex-col gap-1 md:gap-3">
<div className="flex max-w-full flex-grow flex-col gap-0">
<SearchContent message={message} />
</div>
</div>
<SubRow classes="text-xs">
<SearchButtons message={message} />
</SubRow>
</div>
</div>
</div>
</div>
</>
);
}
22 changes: 0 additions & 22 deletions client/src/components/Chat/SearchView.tsx

This file was deleted.

7 changes: 5 additions & 2 deletions client/src/components/Conversations/Conversations.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { useMemo, memo } from 'react';
import { parseISO, isToday } from 'date-fns';
import { TConversation } from 'librechat-data-provider';
import { groupConversationsByDate } from '~/utils';
import { useLocalize } from '~/hooks';
import Convo from './Convo';

const Conversations = ({
Expand All @@ -13,12 +14,14 @@ const Conversations = ({
moveToTop: () => void;
toggleNav: () => void;
}) => {
const localize = useLocalize();
const groupedConversations = useMemo(
() => groupConversationsByDate(conversations),
[conversations],
);
const firstTodayConvoId = useMemo(
() => conversations.find((convo) => isToday(parseISO(convo.updatedAt)))?.conversationId,
() =>
conversations.find((convo) => convo && isToday(parseISO(convo.updatedAt)))?.conversationId,
[conversations],
);

Expand All @@ -37,7 +40,7 @@ const Conversations = ({
paddingLeft: '10px',
}}
>
{groupName}
{localize(groupName) || groupName}
</div>
{convos.map((convo, i) => (
<Convo
Expand Down
21 changes: 2 additions & 19 deletions client/src/components/Conversations/Convo.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { useRecoilValue } from 'recoil';
import { useParams } from 'react-router-dom';
import { useState, useRef, useMemo } from 'react';
import { EModelEndpoint, LocalStorageKeys } from 'librechat-data-provider';
import { useGetEndpointsQuery } from 'librechat-data-provider/react-query';
import type { MouseEvent, FocusEvent, KeyboardEvent } from 'react';
import { useUpdateConversationMutation } from '~/data-provider';
Expand All @@ -26,8 +25,8 @@ export default function Conversation({ conversation, retainView, toggleNav, isLa
const updateConvoMutation = useUpdateConversationMutation(currentConvoId ?? '');
const activeConvos = useRecoilValue(store.allConversationsSelector);
const { data: endpointsConfig } = useGetEndpointsQuery();
const { navigateWithLastTools } = useNavigateToConvo();
const { refreshConversations } = useConversations();
const { navigateToConvo } = useNavigateToConvo();
const { showToast } = useToastContext();

const { conversationId, title } = conversation;
Expand All @@ -51,23 +50,7 @@ export default function Conversation({ conversation, retainView, toggleNav, isLa

// set document title
document.title = title;

// set conversation to the new conversation
if (conversation?.endpoint === EModelEndpoint.gptPlugins) {
let lastSelectedTools = [];
try {
lastSelectedTools =
JSON.parse(localStorage.getItem(LocalStorageKeys.LAST_TOOLS) ?? '') ?? [];
} catch (e) {
// console.error(e);
}
navigateToConvo({
...conversation,
tools: conversation?.tools?.length ? conversation?.tools : lastSelectedTools,
});
} else {
navigateToConvo(conversation);
}
navigateWithLastTools(conversation);
};

const renameHandler = (e: MouseEvent<HTMLButtonElement>) => {
Expand Down
Loading
Loading