diff --git a/packages/ui/src/components/message-item.tsx b/packages/ui/src/components/message-item.tsx
index 29a32c63..e9d9dc8e 100644
--- a/packages/ui/src/components/message-item.tsx
+++ b/packages/ui/src/components/message-item.tsx
@@ -1,4 +1,4 @@
-import { For, Show } from "solid-js"
+import { For, Show, createSignal } from "solid-js"
import type { MessageInfo, ClientPart } from "../types/message"
import { partHasRenderableText } from "../types/message"
import type { MessageRecord } from "../stores/message-v2/types"
@@ -18,6 +18,7 @@ interface MessageItemProps {
}
export default function MessageItem(props: MessageItemProps) {
+ const [copied, setCopied] = createSignal(false)
const isUser = () => props.record.role === "user"
const createdTimestamp = () => props.messageInfo?.time?.created ?? props.record.createdAt
@@ -143,6 +144,22 @@ interface MessageItemProps {
}
}
+ const getRawContent = () => {
+ return props.parts
+ .filter(part => part.type === "text" || part.type === "reasoning")
+ .map(part => (part as { text?: string }).text || "")
+ .filter(text => text.trim().length > 0)
+ .join("\n\n")
+ }
+
+ const handleCopy = async () => {
+ const content = getRawContent()
+ if (!content) return
+ await navigator.clipboard.writeText(content)
+ setCopied(true)
+ setTimeout(() => setCopied(false), 2000)
+ }
+
if (!isUser() && !hasContent()) {
return null
}
@@ -218,8 +235,30 @@ interface MessageItemProps {
Fork
+
+
+
+