Skip to content

Commit

Permalink
fix: add sorting for messages on package and ui level
Browse files Browse the repository at this point in the history
  • Loading branch information
ivanleomk committed Jan 19, 2025
1 parent 0fd2c54 commit 6084a36
Show file tree
Hide file tree
Showing 5 changed files with 161 additions and 5 deletions.
14 changes: 12 additions & 2 deletions kura/types/conversation.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ def from_claude_conversation_dump(cls, file_path: str) -> list["Conversation"]:
created_at=conversation["created_at"],
messages=[
Message(
created_at=message["created_at"],
created_at=datetime.fromisoformat(
message["created_at"].replace("Z", "+00:00")
),
role="user"
if message["sender"] == "human"
else "assistant",
Expand All @@ -36,7 +38,15 @@ def from_claude_conversation_dump(cls, file_path: str) -> list["Conversation"]:
]
),
)
for message in conversation["chat_messages"]
for message in sorted(
conversation["chat_messages"],
key=lambda x: (
datetime.fromisoformat(
x["created_at"].replace("Z", "+00:00")
),
0 if x["sender"] == "human" else 1,
),
)
],
)
for conversation in json.load(f)
Expand Down
Binary file modified ui/bun.lockb
Binary file not shown.
7 changes: 4 additions & 3 deletions ui/src/components/ChatDialog.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Conversation } from "@/types/conversation";
import React from "react";

import {
Dialog,
DialogContent,
Expand All @@ -8,6 +8,7 @@ import {
DialogTitle,
DialogTrigger,
} from "./ui/dialog";
import { Markdown } from "./markdown";

type Props = {
chatId: string;
Expand Down Expand Up @@ -36,13 +37,13 @@ const ChatDialog = ({ chatId, conversation }: Props) => {
}`}
>
<div
className={`max-w-[80%] rounded-xl p-2 ${
className={`max-w-[80%] rounded-xl px-4 py-2 ${
m.role === "user"
? "bg-blue-500 text-white rounded-br-none"
: "bg-gray-200 text-gray-800 rounded-bl-none"
}`}
>
<p className="whitespace-pre-line">{m.content}</p>
<Markdown>{m.content}</Markdown>
</div>
<span className="text-xs text-gray-500 mt-1">
{m.role === "user" ? "You" : "Assistant"}
Expand Down
38 changes: 38 additions & 0 deletions ui/src/components/code-block.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
"use client";

interface CodeBlockProps {
node: any;
inline: boolean;
className: string;
children: any;
}

export function CodeBlock({
node,
inline,
className,
children,
...props
}: CodeBlockProps) {
if (!inline) {
return (
<div className="not-prose flex flex-col bg-white my-4">
<pre
{...props}
className={`text-sm w-full overflow-x-auto dark:bg-zinc-900 p-4 border border-zinc-200 dark:border-zinc-700 rounded-xl dark:text-zinc-50 text-zinc-900`}
>
<code className="whitespace-pre-wrap break-words">{children}</code>
</pre>
</div>
);
} else {
return (
<code
className={`${className} text-sm bg-zinc-100 dark:bg-zinc-800 py-0.5 px-1 rounded-md`}
{...props}
>
{children}
</code>
);
}
}
107 changes: 107 additions & 0 deletions ui/src/components/markdown.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import { memo } from "react";
import ReactMarkdown, { type Components } from "react-markdown";
import remarkGfm from "remark-gfm";
import { CodeBlock } from "./code-block";

const components: Partial<Components> = {
// @ts-expect-error
code: CodeBlock,
pre: ({ children }) => <>{children}</>,
ol: ({ node, children, ...props }) => {
return (
<ol className="list-decimal list-outside ml-4" {...props}>
{children}
</ol>
);
},
li: ({ node, children, ...props }) => {
return (
<li className="py-1" {...props}>
{children}
</li>
);
},
ul: ({ node, children, ...props }) => {
return (
<ul className="list-decimal list-outside ml-4" {...props}>
{children}
</ul>
);
},
strong: ({ node, children, ...props }) => {
return (
<span className="font-semibold" {...props}>
{children}
</span>
);
},
a: ({ node, children, ...props }) => {
return (
<a
className="text-blue-500 hover:underline"
target="_blank"
rel="noreferrer"
{...props}
>
{children}
</a>
);
},
h1: ({ node, children, ...props }) => {
return (
<h1 className="text-3xl font-semibold mt-6 mb-2" {...props}>
{children}
</h1>
);
},
h2: ({ node, children, ...props }) => {
return (
<h2 className="text-2xl font-semibold mt-6 mb-2" {...props}>
{children}
</h2>
);
},
h3: ({ node, children, ...props }) => {
return (
<h3 className="text-xl font-semibold mt-6 mb-2" {...props}>
{children}
</h3>
);
},
h4: ({ node, children, ...props }) => {
return (
<h4 className="text-lg font-semibold mt-6 mb-2" {...props}>
{children}
</h4>
);
},
h5: ({ node, children, ...props }) => {
return (
<h5 className="text-base font-semibold mt-6 mb-2" {...props}>
{children}
</h5>
);
},
h6: ({ node, children, ...props }) => {
return (
<h6 className="text-sm font-semibold mt-6 mb-2" {...props}>
{children}
</h6>
);
},
};

const remarkPlugins = [remarkGfm];

const NonMemoizedMarkdown = ({ children }: { children: string }) => {
return (
<ReactMarkdown remarkPlugins={remarkPlugins} components={components}>
{children}
</ReactMarkdown>
);
};

export const Markdown = memo(
NonMemoizedMarkdown,
(prevProps, nextProps) => prevProps.children === nextProps.children
);

0 comments on commit 6084a36

Please sign in to comment.