mirror of
https://github.com/khoaliber/khoj.git
synced 2026-03-02 21:19:12 +00:00
Fix, Improve Behavior, Styling of Chat View on Web (#851)
### Behavior - Close chat sessions side panel on click open a chat session - Show agent profile card with description when hover on agent in chat view - Show action bar on last chat message without hover - Show chat message action buttons without hover on mobile interfaces - Show chat message timestamp on hover in chat view - Show text descriptions of chat message action buttons on hover - Render inline png, webp images generated by Khoj in chat view ### Fixes - Do not render references with broken links in chat view - Fix closing side panel on mobile when click open a chat session - Only open side panel as drawer in mobile view - Constrain chat messages to stay within view port across screen sizes ### Styling: Spacing, Sizing, Mobile Friendly - Make Khoj icon appropriately sized and side panel arrow bold - Conversations list should resize to take max space on side panel - Make loading message, styling configurable. Do not show agent when no data - Improve Train of Thought icons spacing and loading circle - Improve mobile friendly styling of chat session side panel - Improve styling of chat input, references UI across screen sizes - Center cursor in chat input. See upto 2 lines for multi-line context ### Miscellaneous - Add code formatter for web interface with prettier
This commit is contained in:
@@ -1,3 +1,11 @@
|
||||
{
|
||||
"extends": "next/core-web-vitals"
|
||||
"extends": [
|
||||
"next",
|
||||
"next/core-web-vitals",
|
||||
"plugin:prettier/recommended"
|
||||
],
|
||||
"plugins": ["prettier"],
|
||||
"rules": {
|
||||
"prettier/prettier": "error"
|
||||
}
|
||||
}
|
||||
|
||||
5
src/interface/web/.husky/pre-commit
Normal file
5
src/interface/web/.husky/pre-commit
Normal file
@@ -0,0 +1,5 @@
|
||||
#!/usr/bin/env sh
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
|
||||
yarn run lint-staged
|
||||
yarn test
|
||||
@@ -33,7 +33,6 @@ interface ChatBodyDataProps {
|
||||
isLoggedIn: boolean;
|
||||
}
|
||||
|
||||
|
||||
function ChatBodyData(props: ChatBodyDataProps) {
|
||||
const searchParams = useSearchParams();
|
||||
const conversationId = searchParams.get('conversationId');
|
||||
@@ -119,10 +118,8 @@ export default function Chat() {
|
||||
|
||||
welcomeConsole();
|
||||
|
||||
|
||||
const handleWebSocketMessage = (event: MessageEvent) => {
|
||||
let chunk = event.data;
|
||||
|
||||
let currentMessage = messages.find(message => !message.completed);
|
||||
|
||||
if (!currentMessage) {
|
||||
@@ -165,7 +162,6 @@ export default function Chat() {
|
||||
} finally {
|
||||
// no-op
|
||||
}
|
||||
|
||||
} else {
|
||||
// Update the current message with the new chunk
|
||||
if (chunk && chunk.includes("### compiled references:")) {
|
||||
@@ -179,7 +175,6 @@ export default function Chat() {
|
||||
// If the chunk is not a JSON object, just display it as is
|
||||
currentMessage.rawResponse += chunk;
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
// Update the state with the new message, currentMessage
|
||||
@@ -269,7 +264,9 @@ export default function Chat() {
|
||||
<SidePanel
|
||||
webSocketConnected={chatWS !== null}
|
||||
conversationId={conversationId}
|
||||
uploadedFiles={uploadedFiles} />
|
||||
uploadedFiles={uploadedFiles}
|
||||
isMobileWidth={isMobileWidth}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.chatBox}>
|
||||
<NavMenu selected="Chat" title={title} />
|
||||
|
||||
@@ -17,14 +17,10 @@ div.agentIndicator a {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
div.agentIndicator {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
div.trainOfThought {
|
||||
border: 1px var(--border-color) solid;
|
||||
border-radius: 16px;
|
||||
padding: 16px;
|
||||
padding: 0 16px;
|
||||
margin: 12px;
|
||||
box-shadow: 0 4px 10px var(--box-shadow-color);
|
||||
}
|
||||
|
||||
@@ -10,10 +10,12 @@ import { ScrollArea } from "@/components/ui/scroll-area"
|
||||
import renderMathInElement from 'katex/contrib/auto-render';
|
||||
import 'katex/dist/katex.min.css';
|
||||
|
||||
import Loading, { InlineLoading } from '../loading/loading';
|
||||
import { InlineLoading } from '../loading/loading';
|
||||
|
||||
import { Lightbulb } from "@phosphor-icons/react";
|
||||
|
||||
import ProfileCard from '../profileCard/profileCard';
|
||||
|
||||
interface ChatResponse {
|
||||
status: string;
|
||||
response: ChatHistoryData;
|
||||
@@ -231,6 +233,10 @@ export default function ChatHistory(props: ChatHistoryProps) {
|
||||
return data.agent.name;
|
||||
}
|
||||
|
||||
function constructAgentPersona() {
|
||||
if (!data || !data.agent || !data.agent.persona) return ``;
|
||||
return data.agent.persona;
|
||||
}
|
||||
|
||||
if (!props.conversationId && !props.publicConversationSlug) {
|
||||
return null;
|
||||
@@ -241,7 +247,7 @@ export default function ChatHistory(props: ChatHistoryProps) {
|
||||
<div ref={ref}>
|
||||
<div className={styles.chatHistory} ref={chatHistoryRef}>
|
||||
<div ref={sentinelRef} style={{ height: '1px' }}>
|
||||
{fetchingData && <InlineLoading />}
|
||||
{fetchingData && <InlineLoading message="Loading Conversation" className='opacity-50'/>}
|
||||
</div>
|
||||
{(data && data.chat) && data.chat.map((chatMessage, index) => (
|
||||
<ChatMessage
|
||||
@@ -250,6 +256,7 @@ export default function ChatHistory(props: ChatHistoryProps) {
|
||||
chatMessage={chatMessage}
|
||||
customClassName='fullHistory'
|
||||
borderLeftColor='orange-500'
|
||||
isLastMessage={index === data.chat.length - 1}
|
||||
/>
|
||||
))}
|
||||
{
|
||||
@@ -270,7 +277,8 @@ export default function ChatHistory(props: ChatHistoryProps) {
|
||||
}
|
||||
}
|
||||
customClassName='fullHistory'
|
||||
borderLeftColor='orange-500' />
|
||||
borderLeftColor='orange-500'
|
||||
/>
|
||||
{
|
||||
message.trainOfThought &&
|
||||
constructTrainOfThought(
|
||||
@@ -294,6 +302,7 @@ export default function ChatHistory(props: ChatHistoryProps) {
|
||||
}
|
||||
customClassName='fullHistory'
|
||||
borderLeftColor='orange-500'
|
||||
isLastMessage={true}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
@@ -316,14 +325,21 @@ export default function ChatHistory(props: ChatHistoryProps) {
|
||||
}
|
||||
customClassName='fullHistory'
|
||||
borderLeftColor='orange-500'
|
||||
isLastMessage={true}
|
||||
/>
|
||||
}
|
||||
<div className={`${styles.agentIndicator}`}>
|
||||
<a className='no-underline mx-2 flex text-muted-foreground' href={constructAgentLink()} target="_blank" rel="noreferrer">
|
||||
<Lightbulb color='orange' weight='fill' />
|
||||
<span>{constructAgentName()}</span>
|
||||
</a>
|
||||
</div>
|
||||
{data &&
|
||||
<div className={`${styles.agentIndicator} pb-4`}>
|
||||
<div className="relative group mx-2 cursor-pointer">
|
||||
<ProfileCard
|
||||
name={constructAgentName()}
|
||||
link={constructAgentLink()}
|
||||
avatar={<Lightbulb color='orange' weight='fill' className="mt-1 mx-1" />}
|
||||
description={constructAgentPersona()}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</ScrollArea>
|
||||
|
||||
@@ -133,42 +133,43 @@ export default function ChatInputArea(props: ChatInputProps) {
|
||||
}
|
||||
|
||||
function getIconForSlashCommand(command: string) {
|
||||
const className = 'h-4 w-4 mr-2';
|
||||
if (command.includes('summarize')) {
|
||||
return <Gps className='h-4 w-4 mr-2' />
|
||||
return <Gps className={className} />
|
||||
}
|
||||
|
||||
if (command.includes('help')) {
|
||||
return <Question className='h-4 w-4 mr-2' />
|
||||
return <Question className={className} />
|
||||
}
|
||||
|
||||
if (command.includes('automation')) {
|
||||
return <Robot className='h-4 w-4 mr-2' />
|
||||
return <Robot className={className} />
|
||||
}
|
||||
|
||||
if (command.includes('webpage')) {
|
||||
return <Browser className='h-4 w-4 mr-2' />
|
||||
return <Browser className={className} />
|
||||
}
|
||||
|
||||
if (command.includes('notes')) {
|
||||
return <Notebook className='h-4 w-4 mr-2' />
|
||||
return <Notebook className={className} />
|
||||
}
|
||||
|
||||
if (command.includes('image')) {
|
||||
return <Image className='h-4 w-4 mr-2' />
|
||||
return <Image className={className} />
|
||||
}
|
||||
|
||||
if (command.includes('default')) {
|
||||
return <Shapes className='h-4 w-4 mr-2' />
|
||||
return <Shapes className={className} />
|
||||
}
|
||||
|
||||
if (command.includes('general')) {
|
||||
return <ChatsTeardrop className='h-4 w-4 mr-2' />
|
||||
return <ChatsTeardrop className={className} />
|
||||
}
|
||||
|
||||
if (command.includes('online')) {
|
||||
return <GlobeSimple className='h-4 w-4 mr-2' />
|
||||
return <GlobeSimple className={className} />
|
||||
}
|
||||
return <ArrowRight className='h-4 w-4 mr-2' />
|
||||
return <ArrowRight className={className} />
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -270,7 +271,6 @@ export default function ChatInputArea(props: ChatInputProps) {
|
||||
</div>
|
||||
}
|
||||
<div className={`${styles.actualInputArea} flex items-center justify-between`}>
|
||||
|
||||
<input
|
||||
type="file"
|
||||
multiple={true}
|
||||
@@ -287,7 +287,7 @@ export default function ChatInputArea(props: ChatInputProps) {
|
||||
</Button>
|
||||
<div className="grid w-full gap-1.5 relative">
|
||||
<Textarea
|
||||
className='border-none min-h-[20px]'
|
||||
className='border-none w-full h-16 min-h-16 md:py-4 rounded-lg text-lg'
|
||||
placeholder="Type / to see a list of commands"
|
||||
id="message"
|
||||
value={message}
|
||||
|
||||
@@ -3,12 +3,17 @@ div.chatMessageContainer {
|
||||
flex-direction: column;
|
||||
margin: 12px;
|
||||
border-radius: 16px;
|
||||
padding: 16px;
|
||||
padding: 8px 16px 0 16px;
|
||||
box-shadow: 0 4px 10px var(--box-shadow-color)
|
||||
}
|
||||
|
||||
div.chatMessageWrapper {
|
||||
padding-left: 24px;
|
||||
padding-left: 1rem;
|
||||
padding-bottom: 1rem;
|
||||
max-width: 80vw;
|
||||
}
|
||||
div.chatMessageWrapper p:not(:last-child) {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
div.khojfullHistory {
|
||||
@@ -17,7 +22,7 @@ div.khojfullHistory {
|
||||
}
|
||||
|
||||
div.youfullHistory {
|
||||
max-width: 80%;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
div.chatMessageContainer.youfullHistory {
|
||||
@@ -68,10 +73,11 @@ div.chatFooter {
|
||||
div.chatButtons {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
width: min-content;
|
||||
border: var(--border-color) 1px solid;
|
||||
border-radius: 16px;
|
||||
position: relative;
|
||||
bottom: -28px;
|
||||
bottom: -12px;
|
||||
background-color: hsla(var(--secondary));
|
||||
box-shadow: 0 4px 10px var(--box-shadow-color);
|
||||
}
|
||||
@@ -121,11 +127,6 @@ div.trainOfThought.primary p {
|
||||
|
||||
@media screen and (max-width: 768px) {
|
||||
div.youfullHistory {
|
||||
max-width: 100%;
|
||||
max-width: 90%;
|
||||
}
|
||||
|
||||
div.chatMessageWrapper {
|
||||
padding-left: 8px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -10,8 +10,7 @@ import 'katex/dist/katex.min.css';
|
||||
|
||||
import { TeaserReferencesSection, constructAllReferences } from '../referencePanel/referencePanel';
|
||||
|
||||
import { ThumbsUp, ThumbsDown, Copy, Brain, Cloud, Folder, Book, Aperture, ArrowRight, SpeakerHifi } from '@phosphor-icons/react';
|
||||
import { MagnifyingGlass } from '@phosphor-icons/react/dist/ssr';
|
||||
import { ThumbsUp, ThumbsDown, Copy, Brain, Cloud, Folder, Book, Aperture, SpeakerHigh, MagnifyingGlass } from '@phosphor-icons/react';
|
||||
|
||||
import * as DomPurify from 'dompurify';
|
||||
|
||||
@@ -76,6 +75,7 @@ interface AgentData {
|
||||
name: string;
|
||||
avatar: string;
|
||||
slug: string;
|
||||
persona: string;
|
||||
}
|
||||
|
||||
interface Intent {
|
||||
@@ -110,7 +110,6 @@ export interface StreamMessage {
|
||||
timestamp: string;
|
||||
}
|
||||
|
||||
|
||||
export interface ChatHistoryData {
|
||||
chat: SingleChatMessage[];
|
||||
agent: AgentData;
|
||||
@@ -131,11 +130,11 @@ function sendFeedback(uquery: string, kquery: string, sentiment: string) {
|
||||
function FeedbackButtons({ uquery, kquery }: { uquery: string, kquery: string }) {
|
||||
return (
|
||||
<div className={`${styles.feedbackButtons} flex align-middle justify-center items-center`}>
|
||||
<button className={styles.thumbsUpButton} onClick={() => sendFeedback(uquery, kquery, 'positive')}>
|
||||
<ThumbsUp color='hsl(var(--muted-foreground))' />
|
||||
<button title="Like" className={styles.thumbsUpButton} onClick={() => sendFeedback(uquery, kquery, 'positive')}>
|
||||
<ThumbsUp alt="Like Message" color='hsl(var(--muted-foreground))' />
|
||||
</button>
|
||||
<button className={styles.thumbsDownButton} onClick={() => sendFeedback(uquery, kquery, 'negative')}>
|
||||
<ThumbsDown color='hsl(var(--muted-foreground))' />
|
||||
<button title="Dislike" className={styles.thumbsDownButton} onClick={() => sendFeedback(uquery, kquery, 'negative')}>
|
||||
<ThumbsDown alt="Dislike Message" color='hsl(var(--muted-foreground))' />
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
@@ -146,6 +145,7 @@ interface ChatMessageProps {
|
||||
isMobileWidth: boolean;
|
||||
customClassName?: string;
|
||||
borderLeftColor?: string;
|
||||
isLastMessage?: boolean;
|
||||
}
|
||||
|
||||
interface TrainOfThoughtProps {
|
||||
@@ -155,38 +155,38 @@ interface TrainOfThoughtProps {
|
||||
|
||||
function chooseIconFromHeader(header: string, iconColor: string) {
|
||||
const compareHeader = header.toLowerCase();
|
||||
const classNames = `inline mt-1 mr-2 ${iconColor}`;
|
||||
if (compareHeader.includes("understanding")) {
|
||||
return <Brain className={`inline mr-2 ${iconColor}`} />
|
||||
return <Brain className={`${classNames}`} />
|
||||
}
|
||||
|
||||
if (compareHeader.includes("generating")) {
|
||||
return <Cloud className={`inline mr-2 ${iconColor}`} />;
|
||||
return <Cloud className={`${classNames}`} />;
|
||||
}
|
||||
|
||||
if (compareHeader.includes("data sources")) {
|
||||
return <Folder className={`inline mr-2 ${iconColor}`} />;
|
||||
return <Folder className={`${classNames}`} />;
|
||||
}
|
||||
|
||||
if (compareHeader.includes("notes")) {
|
||||
return <Folder className={`inline mr-2 ${iconColor}`} />;
|
||||
return <Folder className={`${classNames}`} />;
|
||||
}
|
||||
|
||||
if (compareHeader.includes("read")) {
|
||||
return <Book className={`inline mr-2 ${iconColor}`} />;
|
||||
return <Book className={`${classNames}`} />;
|
||||
}
|
||||
|
||||
if (compareHeader.includes("search")) {
|
||||
return <MagnifyingGlass className={`inline mr-2 ${iconColor}`} />;
|
||||
return <MagnifyingGlass className={`${classNames}`} />;
|
||||
}
|
||||
|
||||
if (compareHeader.includes("summary") || compareHeader.includes("summarize")) {
|
||||
return <Aperture className={`inline mr-2 ${iconColor}`} />;
|
||||
return <Aperture className={`${classNames}`} />;
|
||||
}
|
||||
|
||||
return <Brain className={`inline mr-2 ${iconColor}`} />;
|
||||
return <Brain className={`${classNames}`} />;
|
||||
}
|
||||
|
||||
|
||||
export function TrainOfThought(props: TrainOfThoughtProps) {
|
||||
// The train of thought comes in as a markdown-formatted string. It starts with a heading delimited by two asterisks at the start and end and a colon, followed by the message. Example: **header**: status. This function will parse the message and render it as a div.
|
||||
let extractedHeader = props.message.match(/\*\*(.*)\*\*/);
|
||||
@@ -215,8 +215,15 @@ export default function ChatMessage(props: ChatMessageProps) {
|
||||
message = message.replace(/\\\(/g, 'LEFTPAREN').replace(/\\\)/g, 'RIGHTPAREN')
|
||||
.replace(/\\\[/g, 'LEFTBRACKET').replace(/\\\]/g, 'RIGHTBRACKET');
|
||||
|
||||
if (props.chatMessage.intent && props.chatMessage.intent.type == "text-to-image2") {
|
||||
message = `\n\n${props.chatMessage.intent["inferred-queries"][0]}`
|
||||
if (props.chatMessage.intent && props.chatMessage.intent.type == "text-to-image") {
|
||||
message = ``;
|
||||
} else if (props.chatMessage.intent && props.chatMessage.intent.type == "text-to-image2") {
|
||||
message = ``;
|
||||
} else if (props.chatMessage.intent && props.chatMessage.intent.type == "text-to-image-v3") {
|
||||
message = ``;
|
||||
}
|
||||
if (props.chatMessage.intent && props.chatMessage.intent.type.includes("text-to-image") && props.chatMessage.intent["inferred-queries"]?.length > 0) {
|
||||
message += `\n\n**Inferred Query**\n\n${props.chatMessage.intent["inferred-queries"][0]}`;
|
||||
}
|
||||
|
||||
let markdownRendered = md.render(message);
|
||||
@@ -224,6 +231,8 @@ export default function ChatMessage(props: ChatMessageProps) {
|
||||
// Replace placeholders with LaTeX delimiters
|
||||
markdownRendered = markdownRendered.replace(/LEFTPAREN/g, '\\(').replace(/RIGHTPAREN/g, '\\)')
|
||||
.replace(/LEFTBRACKET/g, '\\[').replace(/RIGHTBRACKET/g, '\\]');
|
||||
|
||||
// Sanitize and set the rendered markdown
|
||||
setMarkdownRendered(DomPurify.sanitize(markdownRendered));
|
||||
}, [props.chatMessage.message]);
|
||||
|
||||
@@ -266,28 +275,36 @@ export default function ChatMessage(props: ChatMessageProps) {
|
||||
return null;
|
||||
}
|
||||
|
||||
function formatDate(timestamp: string) {
|
||||
// Format date in HH:MM, DD MMM YYYY format
|
||||
let date = new Date(timestamp + "Z");
|
||||
let time_string = date.toLocaleTimeString('en-IN', { hour: '2-digit', minute: '2-digit', hour12: true }).toUpperCase();
|
||||
let date_string = date.toLocaleString('en-IN', { year: 'numeric', month: 'short', day: '2-digit'}).replaceAll('-', ' ');
|
||||
return `${time_string} on ${date_string}`;
|
||||
}
|
||||
|
||||
function renderTimeStamp(timestamp: string) {
|
||||
if (!timestamp.endsWith('Z')) {
|
||||
timestamp = timestamp + 'Z';
|
||||
}
|
||||
const messageDateTime = new Date(timestamp);
|
||||
const currentDataTime = new Date();
|
||||
const timeDiff = currentDataTime.getTime() - messageDateTime.getTime();
|
||||
const currentDateTime = new Date();
|
||||
const timeDiff = currentDateTime.getTime() - messageDateTime.getTime();
|
||||
|
||||
if (timeDiff < 60000) {
|
||||
if (timeDiff < 60e3) {
|
||||
return "Just now";
|
||||
}
|
||||
|
||||
if (timeDiff < 3600000) {
|
||||
if (timeDiff < 3600e3) {
|
||||
// Using Math.round for closer to actual time representation
|
||||
return `${Math.round(timeDiff / 60000)}m ago`;
|
||||
return `${Math.round(timeDiff / 60e3)}m ago`;
|
||||
}
|
||||
|
||||
if (timeDiff < 86400000) {
|
||||
return `${Math.round(timeDiff / 3600000)}h ago`;
|
||||
if (timeDiff < 86400e3) {
|
||||
return `${Math.round(timeDiff / 3600e3)}h ago`;
|
||||
}
|
||||
|
||||
return `${Math.round(timeDiff / 86400000)}d ago`;
|
||||
return `${Math.round(timeDiff / 86400e3)}d ago`;
|
||||
}
|
||||
|
||||
function constructClasses(chatMessage: SingleChatMessage) {
|
||||
@@ -332,29 +349,29 @@ export default function ChatMessage(props: ChatMessageProps) {
|
||||
</div>
|
||||
<div className={styles.chatFooter}>
|
||||
{
|
||||
isHovering &&
|
||||
(isHovering || props.isMobileWidth || props.isLastMessage) &&
|
||||
(
|
||||
<>
|
||||
<div className={`text-gray-400 relative top-2 left-2`}>
|
||||
<div title={formatDate(props.chatMessage.created)} className={`text-gray-400 relative top-0 left-4`}>
|
||||
{renderTimeStamp(props.chatMessage.created)}
|
||||
</div>
|
||||
<div className={styles.chatButtons}>
|
||||
{
|
||||
(props.chatMessage.by === "khoj") &&
|
||||
(
|
||||
<button onClick={(event) => console.log("speaker")}>
|
||||
<SpeakerHifi color='hsl(var(--muted-foreground))' />
|
||||
<button title="Speak" onClick={(event) => console.log("speaker")}>
|
||||
<SpeakerHigh alt="Speak Message" color='hsl(var(--muted-foreground))' />
|
||||
</button>
|
||||
)
|
||||
}
|
||||
<button className={`${styles.copyButton}`} onClick={() => {
|
||||
<button title="Copy" className={`${styles.copyButton}`} onClick={() => {
|
||||
navigator.clipboard.writeText(props.chatMessage.message);
|
||||
setCopySuccess(true);
|
||||
}}>
|
||||
{
|
||||
copySuccess ?
|
||||
<Copy color='green' />
|
||||
: <Copy color='hsl(var(--muted-foreground))' />
|
||||
<Copy alt="Copied Message" weight="fill" color='green' />
|
||||
: <Copy alt="Copy Message" color='hsl(var(--muted-foreground))' />
|
||||
}
|
||||
</button>
|
||||
{
|
||||
@@ -373,7 +390,6 @@ export default function ChatMessage(props: ChatMessageProps) {
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -1,22 +1,23 @@
|
||||
import { CircleNotch } from '@phosphor-icons/react';
|
||||
|
||||
export default function Loading() {
|
||||
interface LoadingProps {
|
||||
className?: string;
|
||||
message?: string;
|
||||
}
|
||||
|
||||
export default function Loading(props: LoadingProps) {
|
||||
return (
|
||||
// NOTE: We can display usage tips here for casual learning moments.
|
||||
<div className={`bg-background opacity-50 flex items-center justify-center h-screen`}>
|
||||
<div>Loading <span><CircleNotch className={`inline animate-spin h-5 w-5`} /></span></div>
|
||||
<div className={props.className || "bg-background opacity-50 flex items-center justify-center h-screen"}>
|
||||
<div>{props.message || "Loading" } <span><CircleNotch className="inline animate-spin h-5 w-5" /></span></div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
interface InlineLoadingProps {
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export function InlineLoading(props: InlineLoadingProps) {
|
||||
export function InlineLoading(props: LoadingProps) {
|
||||
return (
|
||||
<button className={`${props.className}`}>
|
||||
<CircleNotch className={`animate-spin h-5 w-5 mr-3`} />
|
||||
<span>{props.message} <CircleNotch className="inline animate-spin h-5 w-5 mx-3" /></span>
|
||||
</button>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import styles from './navMenu.module.css';
|
||||
import Link from 'next/link';
|
||||
import { useAuthenticatedData, UserProfile } from '@/app/common/auth';
|
||||
import { useAuthenticatedData } from '@/app/common/auth';
|
||||
import { useState, useEffect } from 'react';
|
||||
|
||||
import {
|
||||
|
||||
36
src/interface/web/app/components/profileCard/profileCard.tsx
Normal file
36
src/interface/web/app/components/profileCard/profileCard.tsx
Normal file
@@ -0,0 +1,36 @@
|
||||
import React from 'react';
|
||||
import { ArrowRight } from '@phosphor-icons/react';
|
||||
|
||||
interface ProfileCardProps {
|
||||
name: string;
|
||||
avatar: JSX.Element;
|
||||
link: string;
|
||||
description?: string; // Optional description field
|
||||
}
|
||||
|
||||
const ProfileCard: React.FC<ProfileCardProps> = ({ name, avatar, link, description }) => {
|
||||
return (
|
||||
<div className="relative group flex">
|
||||
{avatar}
|
||||
<span>{name}</span>
|
||||
<div className="absolute left-0 bottom-full w-80 h-30 p-2 pb-4 bg-white border border-gray-300 rounded-lg shadow-lg opacity-0 group-hover:opacity-100 transition-opacity duration-300">
|
||||
<div className="flex items-center">
|
||||
{avatar}
|
||||
<span className="mr-2 mt-1 flex">
|
||||
{name}
|
||||
<a href={link} target="_blank" rel="noreferrer" className="mt-1 ml-2 block">
|
||||
<ArrowRight weight="bold"/>
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
{description && (
|
||||
<p className="mt-2 ml-6 text-sm text-gray-600 line-clamp-2">
|
||||
{description || 'A Khoj agent'}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ProfileCard;
|
||||
@@ -92,12 +92,19 @@ interface OnlineReferenceCardProps extends OnlineReferenceData {
|
||||
function GenericOnlineReferenceCard(props: OnlineReferenceCardProps) {
|
||||
const [isHovering, setIsHovering] = useState(false);
|
||||
|
||||
if (!props.link) {
|
||||
if (!props.link || props.link.split(' ').length > 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const domain = new URL(props.link).hostname;
|
||||
const favicon = `https://www.google.com/s2/favicons?domain=${domain}`;
|
||||
let favicon = `https://www.google.com/s2/favicons?domain=globe`;
|
||||
let domain = "unknown";
|
||||
try {
|
||||
domain = new URL(props.link).hostname;
|
||||
favicon = `https://www.google.com/s2/favicons?domain=${domain}`;
|
||||
} catch (error) {
|
||||
console.warn(`Error parsing domain from link: ${props.link}`);
|
||||
return null;
|
||||
}
|
||||
|
||||
const handleMouseEnter = () => {
|
||||
setIsHovering(true);
|
||||
@@ -269,14 +276,14 @@ export function TeaserReferencesSection(props: TeaserReferenceSectionProps) {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={`${props.isMobileWidth ? 'p-0' : 'p-4'}`}>
|
||||
<div className="pt-0 px-4 pb-4 md:px-6">
|
||||
<h3 className="inline-flex items-center">
|
||||
References
|
||||
<p className="text-gray-400 m-2">
|
||||
{numReferences} sources
|
||||
</p>
|
||||
</h3>
|
||||
<div className={`flex ${props.isMobileWidth ? 'w-[90vw]' : 'w-auto'} space-x-4 mt-2`}>
|
||||
<div className={`flex flex-wrap gap-2 w-auto mt-2`}>
|
||||
{
|
||||
notesDataToShow.map((note, index) => {
|
||||
return <NotesContextReferenceCard showFullContent={false} {...note} key={`${note.title}-${index}`} />
|
||||
@@ -313,15 +320,16 @@ export default function ReferencePanel(props: ReferencePanelDataProps) {
|
||||
return (
|
||||
<Sheet>
|
||||
<SheetTrigger
|
||||
className='text-balance w-[200px] overflow-hidden break-words p-0 bg-transparent border-none text-gray-400 align-middle justify-center items-center !m-0 inline-flex'>
|
||||
View references <ArrowRight className='m-1' />
|
||||
className='text-balance w-auto md:w-[200px] justify-start overflow-hidden break-words p-0 bg-transparent border-none text-gray-400 align-middle items-center !m-2 inline-flex'>
|
||||
View references
|
||||
<ArrowRight className='m-1' />
|
||||
</SheetTrigger>
|
||||
<SheetContent className="overflow-y-scroll">
|
||||
<SheetHeader>
|
||||
<SheetTitle>References</SheetTitle>
|
||||
<SheetDescription>View all references for this response</SheetDescription>
|
||||
</SheetHeader>
|
||||
<div className="flex flex-col w-auto gap-2 mt-2">
|
||||
<div className="flex flex-wrap gap-2 w-auto mt-2">
|
||||
{
|
||||
props.notesReferenceCardData.map((note, index) => {
|
||||
return <NotesContextReferenceCard showFullContent={true} {...note} key={`${note.title}-${index}`} />
|
||||
|
||||
@@ -2,13 +2,12 @@
|
||||
|
||||
import styles from "./sidePanel.module.css";
|
||||
|
||||
import { Suspense, useEffect, useState } from "react";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
import { UserProfile, useAuthenticatedData } from "@/app/common/auth";
|
||||
import { Avatar, AvatarImage, AvatarFallback } from "@/components/ui/avatar";
|
||||
import Link from "next/link";
|
||||
import useSWR from "swr";
|
||||
import Image from "next/image";
|
||||
|
||||
import {
|
||||
Command,
|
||||
@@ -54,6 +53,7 @@ interface ChatHistory {
|
||||
agent_avatar: string;
|
||||
compressed: boolean;
|
||||
created: string;
|
||||
showSidePanel: (isEnabled: boolean) => void;
|
||||
}
|
||||
|
||||
import {
|
||||
@@ -140,7 +140,6 @@ function deleteConversation(conversationId: string) {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
interface FilesMenuProps {
|
||||
conversationId: string | null;
|
||||
uploadedFiles: string[];
|
||||
@@ -333,33 +332,37 @@ interface SessionsAndFilesProps {
|
||||
function SessionsAndFiles(props: SessionsAndFilesProps) {
|
||||
return (
|
||||
<>
|
||||
<ScrollArea className="h-[40vh]">
|
||||
<ScrollAreaScrollbar orientation="vertical" className="h-full w-2.5 border-l border-l-transparent p-[1px]" />
|
||||
<div className={styles.sessionsList}>
|
||||
{props.subsetOrganizedData != null && Object.keys(props.subsetOrganizedData).map((timeGrouping) => (
|
||||
<div key={timeGrouping} className={`my-4`}>
|
||||
<div className={`text-muted-foreground text-sm font-bold p-[0.5rem] `}>
|
||||
{timeGrouping}
|
||||
<div>
|
||||
<ScrollArea>
|
||||
<ScrollAreaScrollbar orientation="vertical" className="h-full w-2.5 border-l border-l-transparent p-[1px]" />
|
||||
<div className={styles.sessionsList}>
|
||||
{props.subsetOrganizedData != null && Object.keys(props.subsetOrganizedData).map((timeGrouping) => (
|
||||
<div key={timeGrouping} className={`my-4`}>
|
||||
<div className={`text-muted-foreground text-sm font-bold p-[0.5rem]`}>
|
||||
{timeGrouping}
|
||||
</div>
|
||||
{props.subsetOrganizedData && props.subsetOrganizedData[timeGrouping].map((chatHistory) => (
|
||||
<ChatSession
|
||||
created={chatHistory.created}
|
||||
compressed={true}
|
||||
key={chatHistory.conversation_id}
|
||||
conversation_id={chatHistory.conversation_id}
|
||||
slug={chatHistory.slug}
|
||||
agent_avatar={chatHistory.agent_avatar}
|
||||
agent_name={chatHistory.agent_name}
|
||||
showSidePanel={props.setEnabled}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
{props.subsetOrganizedData && props.subsetOrganizedData[timeGrouping].map((chatHistory) => (
|
||||
<ChatSession
|
||||
created={chatHistory.created}
|
||||
compressed={true}
|
||||
key={chatHistory.conversation_id}
|
||||
conversation_id={chatHistory.conversation_id}
|
||||
slug={chatHistory.slug}
|
||||
agent_avatar={chatHistory.agent_avatar}
|
||||
agent_name={chatHistory.agent_name} />
|
||||
))}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</ScrollArea>
|
||||
{
|
||||
(props.data && props.data.length > 5) && (
|
||||
<ChatSessionsModal data={props.organizedData} />
|
||||
)
|
||||
}
|
||||
))}
|
||||
</div>
|
||||
</ScrollArea>
|
||||
{
|
||||
(props.data && props.data.length > 5) && (
|
||||
<ChatSessionsModal data={props.organizedData} showSidePanel={props.setEnabled} />
|
||||
)
|
||||
}
|
||||
</div>
|
||||
<FilesMenu conversationId={props.conversationId} uploadedFiles={props.uploadedFiles} isMobileWidth={props.isMobileWidth} />
|
||||
{props.userProfile &&
|
||||
<UserProfileComponent userProfile={props.userProfile} webSocketConnected={props.webSocketConnected} collapsed={false} />
|
||||
@@ -527,7 +530,7 @@ function ChatSession(props: ChatHistory) {
|
||||
onMouseLeave={() => setIsHovered(false)}
|
||||
key={props.conversation_id}
|
||||
className={`${styles.session} ${props.compressed ? styles.compressed : '!max-w-full'} ${isHovered ? `${styles.sessionHover}` : ''}`}>
|
||||
<Link href={`/chat?conversationId=${props.conversation_id}`}>
|
||||
<Link href={`/chat?conversationId=${props.conversation_id}`} onClick={() => props.showSidePanel(false)}>
|
||||
<p className={styles.session}>{props.slug || "New Conversation 🌱"}</p>
|
||||
</Link>
|
||||
<ChatSessionActionMenu conversationId={props.conversation_id} />
|
||||
@@ -537,21 +540,22 @@ function ChatSession(props: ChatHistory) {
|
||||
|
||||
interface ChatSessionsModalProps {
|
||||
data: GroupedChatHistory | null;
|
||||
showSidePanel: (isEnabled: boolean) => void;
|
||||
}
|
||||
|
||||
function ChatSessionsModal({ data }: ChatSessionsModalProps) {
|
||||
function ChatSessionsModal({ data, showSidePanel }: ChatSessionsModalProps) {
|
||||
return (
|
||||
<Dialog>
|
||||
<DialogTrigger
|
||||
className="flex text-left text-medium text-gray-500 hover:text-gray-300 cursor-pointer my-4 text-sm p-[0.5rem]">
|
||||
<span className="mr-2">See All <ArrowRight className="h-4 w-4" /></span>
|
||||
<span className="mr-2">See All <ArrowRight className="inline h-4 w-4" weight="bold"/></span>
|
||||
</DialogTrigger>
|
||||
<DialogContent>
|
||||
<DialogHeader>
|
||||
<DialogTitle>All Conversations</DialogTitle>
|
||||
<DialogDescription
|
||||
className="p-0">
|
||||
<ScrollArea className="h-[500px] p-4">
|
||||
<ScrollArea className="h-[500px] py-4">
|
||||
{data && Object.keys(data).map((timeGrouping) => (
|
||||
<div key={timeGrouping}>
|
||||
<div className={`text-muted-foreground text-sm font-bold p-[0.5rem] `}>
|
||||
@@ -565,7 +569,8 @@ function ChatSessionsModal({ data }: ChatSessionsModalProps) {
|
||||
conversation_id={chatHistory.conversation_id}
|
||||
slug={chatHistory.slug}
|
||||
agent_avatar={chatHistory.agent_avatar}
|
||||
agent_name={chatHistory.agent_name} />
|
||||
agent_name={chatHistory.agent_name}
|
||||
showSidePanel={showSidePanel}/>
|
||||
))}
|
||||
</div>
|
||||
))}
|
||||
@@ -646,11 +651,11 @@ interface SidePanelProps {
|
||||
webSocketConnected?: boolean;
|
||||
conversationId: string | null;
|
||||
uploadedFiles: string[];
|
||||
isMobileWidth: boolean;
|
||||
}
|
||||
|
||||
|
||||
export default function SidePanel(props: SidePanelProps) {
|
||||
|
||||
const [data, setData] = useState<ChatHistory[] | null>(null);
|
||||
const [organizedData, setOrganizedData] = useState<GroupedChatHistory | null>(null);
|
||||
const [subsetOrganizedData, setSubsetOrganizedData] = useState<GroupedChatHistory | null>(null);
|
||||
@@ -659,9 +664,6 @@ export default function SidePanel(props: SidePanelProps) {
|
||||
const authenticatedData = useAuthenticatedData();
|
||||
const { data: chatSessions } = useChatSessionsFetchRequest(authenticatedData ? `/api/chat/sessions` : '');
|
||||
|
||||
|
||||
const [isMobileWidth, setIsMobileWidth] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (chatSessions) {
|
||||
setData(chatSessions);
|
||||
@@ -693,35 +695,23 @@ export default function SidePanel(props: SidePanelProps) {
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
setSubsetOrganizedData(subsetOrganizedData);
|
||||
setOrganizedData(groupedData);
|
||||
}
|
||||
}, [chatSessions]);
|
||||
|
||||
useEffect(() => {
|
||||
if (window.innerWidth < 768) {
|
||||
setIsMobileWidth(true);
|
||||
}
|
||||
|
||||
window.addEventListener('resize', () => {
|
||||
setIsMobileWidth(window.innerWidth < 768);
|
||||
});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className={`${styles.panel} ${enabled ? styles.expanded : styles.collapsed}`}>
|
||||
<div className="flex items-start justify-between">
|
||||
<Image src="/khoj-logo.svg"
|
||||
alt="logo"
|
||||
width={40}
|
||||
height={40}
|
||||
/>
|
||||
<div className="flex items-center justify-between">
|
||||
<img src="/khoj-logo.svg" alt="logo" className="w-16"/>
|
||||
{
|
||||
authenticatedData &&
|
||||
isMobileWidth ?
|
||||
<Drawer>
|
||||
<DrawerTrigger><ArrowRight className="h-4 w-4 mx-2" /></DrawerTrigger>
|
||||
authenticatedData && props.isMobileWidth ?
|
||||
<Drawer open={enabled} onOpenChange={(open) => {
|
||||
if (!enabled) setEnabled(false);
|
||||
setEnabled(open);
|
||||
}
|
||||
}>
|
||||
<DrawerTrigger><ArrowRight className="h-4 w-4 mx-2" weight="bold"/></DrawerTrigger>
|
||||
<DrawerContent>
|
||||
<DrawerHeader>
|
||||
<DrawerTitle>Sessions and Files</DrawerTitle>
|
||||
@@ -737,7 +727,7 @@ export default function SidePanel(props: SidePanelProps) {
|
||||
uploadedFiles={props.uploadedFiles}
|
||||
userProfile={authenticatedData}
|
||||
conversationId={props.conversationId}
|
||||
isMobileWidth={isMobileWidth}
|
||||
isMobileWidth={props.isMobileWidth}
|
||||
/>
|
||||
</div>
|
||||
<DrawerFooter>
|
||||
@@ -749,12 +739,12 @@ export default function SidePanel(props: SidePanelProps) {
|
||||
</Drawer>
|
||||
:
|
||||
<button className={styles.button} onClick={() => setEnabled(!enabled)}>
|
||||
{enabled ? <ArrowLeft className="h-4 w-4" /> : <ArrowRight className="h-4 w-4 mx-2" />}
|
||||
{enabled ? <ArrowLeft className="h-4 w-4" weight="bold"/> : <ArrowRight className="h-4 w-4 mx-2" weight="bold"/>}
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
{
|
||||
authenticatedData && enabled &&
|
||||
authenticatedData && !props.isMobileWidth && enabled &&
|
||||
<div className={`${styles.panelWrapper}`}>
|
||||
<SessionsAndFiles
|
||||
webSocketConnected={props.webSocketConnected}
|
||||
@@ -765,7 +755,7 @@ export default function SidePanel(props: SidePanelProps) {
|
||||
uploadedFiles={props.uploadedFiles}
|
||||
userProfile={authenticatedData}
|
||||
conversationId={props.conversationId}
|
||||
isMobileWidth={isMobileWidth}
|
||||
isMobileWidth={props.isMobileWidth}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -6,11 +6,12 @@ div.session {
|
||||
max-width: 14rem;
|
||||
font-size: medium;
|
||||
display: grid;
|
||||
grid-template-columns: minmax(auto, 350px) 1fr;
|
||||
grid-template-columns: minmax(auto, 400px) 1fr;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
div.compressed {
|
||||
grid-template-columns: minmax(auto, 12rem) 1fr 1fr;
|
||||
grid-template-columns: minmax(12rem, 100%) 1fr 1fr;
|
||||
}
|
||||
|
||||
div.sessionHover {
|
||||
@@ -83,11 +84,10 @@ div.profile {
|
||||
|
||||
div.panelWrapper {
|
||||
display: grid;
|
||||
grid-template-rows: auto 1fr auto auto;
|
||||
grid-template-rows: 1fr auto auto;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
|
||||
div.modalSessionsList {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
@@ -133,15 +133,16 @@ div.modalSessionsList div.session {
|
||||
|
||||
div.panelWrapper {
|
||||
width: 100%;
|
||||
padding: 0 1rem;
|
||||
}
|
||||
|
||||
div.session.compressed {
|
||||
max-width: 100%;
|
||||
grid-template-columns: minmax(auto, 350px) 1fr;
|
||||
grid-template-columns: minmax(auto, 300px) 1fr;
|
||||
}
|
||||
|
||||
div.session {
|
||||
max-width: 100%;
|
||||
grid-template-columns: 200px 1fr;
|
||||
grid-template-columns: minmax(auto, 70vw) 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,8 @@
|
||||
"watch": "nodemon --watch . --ext js,jsx,ts,tsx,css --ignore 'out/**/*' --exec 'yarn export'",
|
||||
"windowswatch": "nodemon --watch . --ext js,jsx,ts,tsx,css --ignore 'out/**/*' --exec 'yarn windowsexport'",
|
||||
"windowscollectstatic": "cd ..\\..\\.. && .\\.venv\\Scripts\\Activate.bat && py .\\src\\khoj\\manage.py collectstatic --noinput && .\\.venv\\Scripts\\deactivate.bat && cd ..",
|
||||
"windowsexport": "yarn build && xcopy out ..\\..\\khoj\\interface\\built /E /Y && yarn windowscollectstatic"
|
||||
"windowsexport": "yarn build && xcopy out ..\\..\\khoj\\interface\\built /E /Y && yarn windowscollectstatic",
|
||||
"prepare": "husky"
|
||||
},
|
||||
"dependencies": {
|
||||
"@phosphor-icons/react": "^2.1.7",
|
||||
@@ -31,6 +32,7 @@
|
||||
"@radix-ui/react-scroll-area": "^1.1.0",
|
||||
"@radix-ui/react-slot": "^1.1.0",
|
||||
"@radix-ui/react-toggle": "^1.1.0",
|
||||
"@tailwindcss/line-clamp": "^0.4.4",
|
||||
"@types/dompurify": "^3.0.5",
|
||||
"@types/katex": "^0.16.7",
|
||||
"@types/markdown-it": "^14.1.1",
|
||||
@@ -60,7 +62,18 @@
|
||||
"@types/react-dom": "^18",
|
||||
"eslint": "^8",
|
||||
"eslint-config-next": "14.2.3",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-prettier": "^5.1.3",
|
||||
"husky": "^9.0.11",
|
||||
"lint-staged": "^15.2.7",
|
||||
"nodemon": "^3.1.3",
|
||||
"prettier": "3.3.3",
|
||||
"typescript": "^5"
|
||||
},
|
||||
"prettier": {
|
||||
"tabWidth": 4
|
||||
},
|
||||
"lint-staged": {
|
||||
"*": "yarn lint --fix"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,7 +74,10 @@ const config = {
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [require("tailwindcss-animate")],
|
||||
plugins: [
|
||||
require("tailwindcss-animate"),
|
||||
require('@tailwindcss/line-clamp'),
|
||||
],
|
||||
} satisfies Config
|
||||
|
||||
export default config
|
||||
|
||||
@@ -496,6 +496,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33"
|
||||
integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==
|
||||
|
||||
"@pkgr/core@^0.1.0":
|
||||
version "0.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.1.1.tgz#1ec17e2edbec25c8306d424ecfbf13c7de1aaa31"
|
||||
integrity sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==
|
||||
|
||||
"@radix-ui/number@1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/number/-/number-1.1.0.tgz#1e95610461a09cdf8bb05c152e76ca1278d5da46"
|
||||
@@ -1035,6 +1040,11 @@
|
||||
"@swc/counter" "^0.1.3"
|
||||
tslib "^2.4.0"
|
||||
|
||||
"@tailwindcss/line-clamp@^0.4.4":
|
||||
version "0.4.4"
|
||||
resolved "https://registry.yarnpkg.com/@tailwindcss/line-clamp/-/line-clamp-0.4.4.tgz#767cf8e5d528a5d90c9740ca66eb079f5e87d423"
|
||||
integrity sha512-5U6SY5z8N42VtrCrKlsTAA35gy2VSyYtHWCsg1H87NU1SXnEfekTVlrga9fzUDrrHcGi2Lb5KenUWb4lRQT5/g==
|
||||
|
||||
"@ts-morph/common@~0.19.0":
|
||||
version "0.19.0"
|
||||
resolved "https://registry.yarnpkg.com/@ts-morph/common/-/common-0.19.0.tgz#927fcd81d1bbc09c89c4a310a84577fb55f3694e"
|
||||
@@ -1190,6 +1200,11 @@ ajv@^6.12.4:
|
||||
json-schema-traverse "^0.4.1"
|
||||
uri-js "^4.2.2"
|
||||
|
||||
ansi-escapes@^6.2.0:
|
||||
version "6.2.1"
|
||||
resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-6.2.1.tgz#76c54ce9b081dad39acec4b5d53377913825fb0f"
|
||||
integrity sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig==
|
||||
|
||||
ansi-regex@^5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
|
||||
@@ -1214,7 +1229,7 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0:
|
||||
dependencies:
|
||||
color-convert "^2.0.1"
|
||||
|
||||
ansi-styles@^6.1.0:
|
||||
ansi-styles@^6.0.0, ansi-styles@^6.1.0, ansi-styles@^6.2.1:
|
||||
version "6.2.1"
|
||||
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5"
|
||||
integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==
|
||||
@@ -1527,7 +1542,7 @@ chalk@^4.0.0:
|
||||
ansi-styles "^4.1.0"
|
||||
supports-color "^7.1.0"
|
||||
|
||||
chalk@^5.0.0:
|
||||
chalk@^5.0.0, chalk@~5.3.0:
|
||||
version "5.3.0"
|
||||
resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.3.0.tgz#67c20a7ebef70e7f3970a01f90fa210cb6860385"
|
||||
integrity sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==
|
||||
@@ -1566,6 +1581,14 @@ cli-spinners@^2.6.1:
|
||||
resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.9.2.tgz#1773a8f4b9c4d6ac31563df53b3fc1d79462fe41"
|
||||
integrity sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==
|
||||
|
||||
cli-truncate@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-4.0.0.tgz#6cc28a2924fee9e25ce91e973db56c7066e6172a"
|
||||
integrity sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==
|
||||
dependencies:
|
||||
slice-ansi "^5.0.0"
|
||||
string-width "^7.0.0"
|
||||
|
||||
client-only@0.0.1, client-only@^0.0.1:
|
||||
version "0.0.1"
|
||||
resolved "https://registry.yarnpkg.com/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1"
|
||||
@@ -1623,6 +1646,11 @@ color-name@~1.1.4:
|
||||
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
|
||||
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
|
||||
|
||||
colorette@^2.0.20:
|
||||
version "2.0.20"
|
||||
resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a"
|
||||
integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==
|
||||
|
||||
commander@^10.0.0:
|
||||
version "10.0.1"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06"
|
||||
@@ -1638,6 +1666,11 @@ commander@^8.3.0:
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66"
|
||||
integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==
|
||||
|
||||
commander@~12.1.0:
|
||||
version "12.1.0"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-12.1.0.tgz#01423b36f501259fdaac4d0e4d60c96c991585d3"
|
||||
integrity sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==
|
||||
|
||||
concat-map@0.0.1:
|
||||
version "0.0.1"
|
||||
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
||||
@@ -1714,7 +1747,7 @@ data-view-byte-offset@^1.0.0:
|
||||
es-errors "^1.3.0"
|
||||
is-data-view "^1.0.1"
|
||||
|
||||
debug@4, debug@^4, debug@^4.1.0, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4:
|
||||
debug@4, debug@^4, debug@^4.1.0, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@~4.3.4:
|
||||
version "4.3.5"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.5.tgz#e83444eceb9fedd4a1da56d671ae2446a01a6e1e"
|
||||
integrity sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==
|
||||
@@ -1819,6 +1852,11 @@ electron-to-chromium@^1.4.796:
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.812.tgz#21b78709c5a13af5d5c688d135a22dcea7617acf"
|
||||
integrity sha512-7L8fC2Ey/b6SePDFKR2zHAy4mbdp1/38Yk5TsARO66W3hC5KEaeKMMHoxwtuH+jcu2AYLSn9QX04i95t6Fl1Hg==
|
||||
|
||||
emoji-regex@^10.3.0:
|
||||
version "10.3.0"
|
||||
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-10.3.0.tgz#76998b9268409eb3dae3de989254d456e70cfe23"
|
||||
integrity sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==
|
||||
|
||||
emoji-regex@^8.0.0:
|
||||
version "8.0.0"
|
||||
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
|
||||
@@ -1995,6 +2033,11 @@ eslint-config-next@14.2.3:
|
||||
eslint-plugin-react "^7.33.2"
|
||||
eslint-plugin-react-hooks "^4.5.0 || 5.0.0-canary-7118f5dd7-20230705"
|
||||
|
||||
eslint-config-prettier@^9.1.0:
|
||||
version "9.1.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz#31af3d94578645966c082fcb71a5846d3c94867f"
|
||||
integrity sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==
|
||||
|
||||
eslint-import-resolver-node@^0.3.6, eslint-import-resolver-node@^0.3.9:
|
||||
version "0.3.9"
|
||||
resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz#d4eaac52b8a2e7c3cd1903eb00f7e053356118ac"
|
||||
@@ -2069,6 +2112,14 @@ eslint-plugin-jsx-a11y@^6.7.1:
|
||||
object.entries "^1.1.7"
|
||||
object.fromentries "^2.0.7"
|
||||
|
||||
eslint-plugin-prettier@^5.1.3:
|
||||
version "5.1.3"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz#17cfade9e732cef32b5f5be53bd4e07afd8e67e1"
|
||||
integrity sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==
|
||||
dependencies:
|
||||
prettier-linter-helpers "^1.0.0"
|
||||
synckit "^0.8.6"
|
||||
|
||||
"eslint-plugin-react-hooks@^4.5.0 || 5.0.0-canary-7118f5dd7-20230705":
|
||||
version "4.6.2"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz#c829eb06c0e6f484b3fbb85a97e57784f328c596"
|
||||
@@ -2193,6 +2244,11 @@ esutils@^2.0.2:
|
||||
resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
|
||||
integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==
|
||||
|
||||
eventemitter3@^5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-5.0.1.tgz#53f5ffd0a492ac800721bb42c66b841de96423c4"
|
||||
integrity sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==
|
||||
|
||||
execa@^7.0.0:
|
||||
version "7.2.0"
|
||||
resolved "https://registry.yarnpkg.com/execa/-/execa-7.2.0.tgz#657e75ba984f42a70f38928cedc87d6f2d4fe4e9"
|
||||
@@ -2208,11 +2264,31 @@ execa@^7.0.0:
|
||||
signal-exit "^3.0.7"
|
||||
strip-final-newline "^3.0.0"
|
||||
|
||||
execa@~8.0.1:
|
||||
version "8.0.1"
|
||||
resolved "https://registry.yarnpkg.com/execa/-/execa-8.0.1.tgz#51f6a5943b580f963c3ca9c6321796db8cc39b8c"
|
||||
integrity sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==
|
||||
dependencies:
|
||||
cross-spawn "^7.0.3"
|
||||
get-stream "^8.0.1"
|
||||
human-signals "^5.0.0"
|
||||
is-stream "^3.0.0"
|
||||
merge-stream "^2.0.0"
|
||||
npm-run-path "^5.1.0"
|
||||
onetime "^6.0.0"
|
||||
signal-exit "^4.1.0"
|
||||
strip-final-newline "^3.0.0"
|
||||
|
||||
fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
|
||||
version "3.1.3"
|
||||
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
|
||||
integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
|
||||
|
||||
fast-diff@^1.1.2:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.3.0.tgz#ece407fa550a64d638536cd727e129c61616e0f0"
|
||||
integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==
|
||||
|
||||
fast-glob@^3.2.12, fast-glob@^3.2.9, fast-glob@^3.3.0, fast-glob@^3.3.1, fast-glob@^3.3.2:
|
||||
version "3.3.2"
|
||||
resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129"
|
||||
@@ -2356,6 +2432,11 @@ gensync@^1.0.0-beta.2:
|
||||
resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0"
|
||||
integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==
|
||||
|
||||
get-east-asian-width@^1.0.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz#5e6ebd9baee6fb8b7b6bd505221065f0cd91f64e"
|
||||
integrity sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==
|
||||
|
||||
get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.3, get-intrinsic@^1.2.4:
|
||||
version "1.2.4"
|
||||
resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd"
|
||||
@@ -2377,6 +2458,11 @@ get-stream@^6.0.1:
|
||||
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7"
|
||||
integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==
|
||||
|
||||
get-stream@^8.0.1:
|
||||
version "8.0.1"
|
||||
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-8.0.1.tgz#def9dfd71742cd7754a7761ed43749a27d02eca2"
|
||||
integrity sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==
|
||||
|
||||
get-symbol-description@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.2.tgz#533744d5aa20aca4e079c8e5daf7fd44202821f5"
|
||||
@@ -2555,6 +2641,16 @@ human-signals@^4.3.0:
|
||||
resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-4.3.1.tgz#ab7f811e851fca97ffbd2c1fe9a958964de321b2"
|
||||
integrity sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==
|
||||
|
||||
human-signals@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-5.0.0.tgz#42665a284f9ae0dade3ba41ebc37eb4b852f3a28"
|
||||
integrity sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==
|
||||
|
||||
husky@^9.0.11:
|
||||
version "9.0.11"
|
||||
resolved "https://registry.yarnpkg.com/husky/-/husky-9.0.11.tgz#fc91df4c756050de41b3e478b2158b87c1e79af9"
|
||||
integrity sha512-AB6lFlbwwyIqMdHYhwPe+kjOC3Oc5P3nThEoW/AaO2BX3vJDjWPFxYLxokUZOo6RNX20He3AaT8sESs9NJcmEw==
|
||||
|
||||
ieee754@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
|
||||
@@ -2697,6 +2793,18 @@ is-fullwidth-code-point@^3.0.0:
|
||||
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
|
||||
integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
|
||||
|
||||
is-fullwidth-code-point@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz#fae3167c729e7463f8461ce512b080a49268aa88"
|
||||
integrity sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==
|
||||
|
||||
is-fullwidth-code-point@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz#9609efced7c2f97da7b60145ef481c787c7ba704"
|
||||
integrity sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==
|
||||
dependencies:
|
||||
get-east-asian-width "^1.0.0"
|
||||
|
||||
is-generator-function@^1.0.10:
|
||||
version "1.0.10"
|
||||
resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72"
|
||||
@@ -2970,7 +3078,7 @@ lilconfig@^2.1.0:
|
||||
resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.1.0.tgz#78e23ac89ebb7e1bfbf25b18043de756548e7f52"
|
||||
integrity sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==
|
||||
|
||||
lilconfig@^3.0.0:
|
||||
lilconfig@^3.0.0, lilconfig@~3.1.1:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-3.1.2.tgz#e4a7c3cb549e3a606c8dcc32e5ae1005e62c05cb"
|
||||
integrity sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==
|
||||
@@ -2987,6 +3095,34 @@ linkify-it@^5.0.0:
|
||||
dependencies:
|
||||
uc.micro "^2.0.0"
|
||||
|
||||
lint-staged@^15.2.7:
|
||||
version "15.2.7"
|
||||
resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-15.2.7.tgz#97867e29ed632820c0fb90be06cd9ed384025649"
|
||||
integrity sha512-+FdVbbCZ+yoh7E/RosSdqKJyUM2OEjTciH0TFNkawKgvFp1zbGlEC39RADg+xKBG1R4mhoH2j85myBQZ5wR+lw==
|
||||
dependencies:
|
||||
chalk "~5.3.0"
|
||||
commander "~12.1.0"
|
||||
debug "~4.3.4"
|
||||
execa "~8.0.1"
|
||||
lilconfig "~3.1.1"
|
||||
listr2 "~8.2.1"
|
||||
micromatch "~4.0.7"
|
||||
pidtree "~0.6.0"
|
||||
string-argv "~0.3.2"
|
||||
yaml "~2.4.2"
|
||||
|
||||
listr2@~8.2.1:
|
||||
version "8.2.3"
|
||||
resolved "https://registry.yarnpkg.com/listr2/-/listr2-8.2.3.tgz#c494bb89b34329cf900e4e0ae8aeef9081d7d7a5"
|
||||
integrity sha512-Lllokma2mtoniUOS94CcOErHWAug5iu7HOmDrvWgpw8jyQH2fomgB+7lZS4HWZxytUuQwkGOwe49FvwVaA85Xw==
|
||||
dependencies:
|
||||
cli-truncate "^4.0.0"
|
||||
colorette "^2.0.20"
|
||||
eventemitter3 "^5.0.1"
|
||||
log-update "^6.0.0"
|
||||
rfdc "^1.4.1"
|
||||
wrap-ansi "^9.0.0"
|
||||
|
||||
locate-path@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286"
|
||||
@@ -3027,6 +3163,17 @@ log-symbols@^5.1.0:
|
||||
chalk "^5.0.0"
|
||||
is-unicode-supported "^1.1.0"
|
||||
|
||||
log-update@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/log-update/-/log-update-6.0.0.tgz#0ddeb7ac6ad658c944c1de902993fce7c33f5e59"
|
||||
integrity sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw==
|
||||
dependencies:
|
||||
ansi-escapes "^6.2.0"
|
||||
cli-cursor "^4.0.0"
|
||||
slice-ansi "^7.0.0"
|
||||
strip-ansi "^7.1.0"
|
||||
wrap-ansi "^9.0.0"
|
||||
|
||||
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
|
||||
@@ -3085,7 +3232,7 @@ merge2@^1.3.0, merge2@^1.4.1:
|
||||
resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
|
||||
integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
|
||||
|
||||
micromatch@^4.0.4, micromatch@^4.0.5:
|
||||
micromatch@^4.0.4, micromatch@^4.0.5, micromatch@~4.0.7:
|
||||
version "4.0.7"
|
||||
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.7.tgz#33e8190d9fe474a9895525f5618eee136d46c2e5"
|
||||
integrity sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==
|
||||
@@ -3470,6 +3617,11 @@ picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1:
|
||||
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
|
||||
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
|
||||
|
||||
pidtree@~0.6.0:
|
||||
version "0.6.0"
|
||||
resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.6.0.tgz#90ad7b6d42d5841e69e0a2419ef38f8883aa057c"
|
||||
integrity sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==
|
||||
|
||||
pify@^2.3.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
|
||||
@@ -3552,6 +3704,18 @@ prelude-ls@^1.2.1:
|
||||
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
|
||||
integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==
|
||||
|
||||
prettier-linter-helpers@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b"
|
||||
integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==
|
||||
dependencies:
|
||||
fast-diff "^1.1.2"
|
||||
|
||||
prettier@3.3.3:
|
||||
version "3.3.3"
|
||||
resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.3.3.tgz#30c54fe0be0d8d12e6ae61dbb10109ea00d53105"
|
||||
integrity sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==
|
||||
|
||||
prompts@^2.4.2:
|
||||
version "2.4.2"
|
||||
resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069"
|
||||
@@ -3751,6 +3915,11 @@ reusify@^1.0.4:
|
||||
resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
|
||||
integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
|
||||
|
||||
rfdc@^1.4.1:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.4.1.tgz#778f76c4fb731d93414e8f925fbecf64cce7f6ca"
|
||||
integrity sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==
|
||||
|
||||
rimraf@^3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
|
||||
@@ -3881,7 +4050,7 @@ signal-exit@^3.0.2, signal-exit@^3.0.7:
|
||||
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9"
|
||||
integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==
|
||||
|
||||
signal-exit@^4.0.1:
|
||||
signal-exit@^4.0.1, signal-exit@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04"
|
||||
integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==
|
||||
@@ -3903,6 +4072,22 @@ slash@^3.0.0:
|
||||
resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"
|
||||
integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==
|
||||
|
||||
slice-ansi@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-5.0.0.tgz#b73063c57aa96f9cd881654b15294d95d285c42a"
|
||||
integrity sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==
|
||||
dependencies:
|
||||
ansi-styles "^6.0.0"
|
||||
is-fullwidth-code-point "^4.0.0"
|
||||
|
||||
slice-ansi@^7.0.0:
|
||||
version "7.1.0"
|
||||
resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-7.1.0.tgz#cd6b4655e298a8d1bdeb04250a433094b347b9a9"
|
||||
integrity sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==
|
||||
dependencies:
|
||||
ansi-styles "^6.2.1"
|
||||
is-fullwidth-code-point "^5.0.0"
|
||||
|
||||
source-map-js@^1.0.2, source-map-js@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.0.tgz#16b809c162517b5b8c3e7dcd315a2a5c2612b2af"
|
||||
@@ -3925,6 +4110,11 @@ streamsearch@^1.1.0:
|
||||
resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764"
|
||||
integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==
|
||||
|
||||
string-argv@~0.3.2:
|
||||
version "0.3.2"
|
||||
resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.2.tgz#2b6d0ef24b656274d957d54e0a4bbf6153dc02b6"
|
||||
integrity sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==
|
||||
|
||||
"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0:
|
||||
name string-width-cjs
|
||||
version "4.2.3"
|
||||
@@ -3944,6 +4134,15 @@ string-width@^5.0.1, string-width@^5.1.2:
|
||||
emoji-regex "^9.2.2"
|
||||
strip-ansi "^7.0.1"
|
||||
|
||||
string-width@^7.0.0:
|
||||
version "7.2.0"
|
||||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-7.2.0.tgz#b5bb8e2165ce275d4d43476dd2700ad9091db6dc"
|
||||
integrity sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==
|
||||
dependencies:
|
||||
emoji-regex "^10.3.0"
|
||||
get-east-asian-width "^1.0.0"
|
||||
strip-ansi "^7.1.0"
|
||||
|
||||
string.prototype.matchall@^4.0.11:
|
||||
version "4.0.11"
|
||||
resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz#1092a72c59268d2abaad76582dccc687c0297e0a"
|
||||
@@ -4005,7 +4204,7 @@ string_decoder@^1.1.1:
|
||||
dependencies:
|
||||
ansi-regex "^5.0.1"
|
||||
|
||||
strip-ansi@^7.0.1:
|
||||
strip-ansi@^7.0.1, strip-ansi@^7.1.0:
|
||||
version "7.1.0"
|
||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45"
|
||||
integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==
|
||||
@@ -4074,6 +4273,14 @@ swr@^2.2.5:
|
||||
client-only "^0.0.1"
|
||||
use-sync-external-store "^1.2.0"
|
||||
|
||||
synckit@^0.8.6:
|
||||
version "0.8.8"
|
||||
resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.8.8.tgz#fe7fe446518e3d3d49f5e429f443cf08b6edfcd7"
|
||||
integrity sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==
|
||||
dependencies:
|
||||
"@pkgr/core" "^0.1.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
tailwind-merge@^2.3.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/tailwind-merge/-/tailwind-merge-2.3.0.tgz#27d2134fd00a1f77eca22bcaafdd67055917d286"
|
||||
@@ -4197,7 +4404,7 @@ tsconfig-paths@^4.2.0:
|
||||
minimist "^1.2.6"
|
||||
strip-bom "^3.0.0"
|
||||
|
||||
tslib@^2.0.0, tslib@^2.0.1, tslib@^2.1.0, tslib@^2.4.0:
|
||||
tslib@^2.0.0, tslib@^2.0.1, tslib@^2.1.0, tslib@^2.4.0, tslib@^2.6.2:
|
||||
version "2.6.3"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.3.tgz#0438f810ad7a9edcde7a241c3d80db693c8cbfe0"
|
||||
integrity sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==
|
||||
@@ -4432,6 +4639,15 @@ wrap-ansi@^8.1.0:
|
||||
string-width "^5.0.1"
|
||||
strip-ansi "^7.0.1"
|
||||
|
||||
wrap-ansi@^9.0.0:
|
||||
version "9.0.0"
|
||||
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-9.0.0.tgz#1a3dc8b70d85eeb8398ddfb1e4a02cd186e58b3e"
|
||||
integrity sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==
|
||||
dependencies:
|
||||
ansi-styles "^6.2.1"
|
||||
string-width "^7.0.0"
|
||||
strip-ansi "^7.1.0"
|
||||
|
||||
wrappy@1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
|
||||
@@ -4442,7 +4658,7 @@ yallist@^3.0.2:
|
||||
resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"
|
||||
integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==
|
||||
|
||||
yaml@^2.3.4:
|
||||
yaml@^2.3.4, yaml@~2.4.2:
|
||||
version "2.4.5"
|
||||
resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.4.5.tgz#60630b206dd6d84df97003d33fc1ddf6296cca5e"
|
||||
integrity sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg==
|
||||
|
||||
@@ -212,6 +212,7 @@ def chat_history(
|
||||
"name": conversation.agent.name,
|
||||
"avatar": conversation.agent.avatar,
|
||||
"isCreator": conversation.agent.creator == user,
|
||||
"persona": conversation.agent.personality,
|
||||
}
|
||||
|
||||
meta_log = conversation.conversation_log
|
||||
@@ -266,6 +267,7 @@ def get_shared_chat(
|
||||
"name": conversation.agent.name,
|
||||
"avatar": conversation.agent.avatar,
|
||||
"isCreator": conversation.agent.creator == user,
|
||||
"persona": conversation.agent.personality,
|
||||
}
|
||||
|
||||
meta_log = conversation.conversation_log
|
||||
|
||||
Reference in New Issue
Block a user