Compare commits
1 Commits
main
...
save_threa
| Author | SHA1 | Date | |
|---|---|---|---|
| 135ea06ac1 |
@@ -1,6 +1,6 @@
|
|||||||
# LangGraph Configuration
|
# LangGraph Configuration
|
||||||
NEXT_PUBLIC_API_URL=http://localhost:2024
|
NEXT_PUBLIC_API_URL=http://localhost:2024
|
||||||
NEXT_PUBLIC_ASSISTANT_ID=agent
|
NEXT_PUBLIC_ASSISTANT_ID=my_agent
|
||||||
# Do NOT prefix this with "NEXT_PUBLIC_" as we do not want this exposed in the client.
|
# Do NOT prefix this with "NEXT_PUBLIC_" as we do not want this exposed in the client.
|
||||||
LANGSMITH_API_KEY=
|
LANGSMITH_API_KEY=
|
||||||
|
|
||||||
|
|||||||
10805
package-lock.json
generated
Normal file
10805
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -23,6 +23,7 @@ import {
|
|||||||
XIcon,
|
XIcon,
|
||||||
Plus,
|
Plus,
|
||||||
CircleX,
|
CircleX,
|
||||||
|
Download
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import { useQueryState, parseAsBoolean } from "nuqs";
|
import { useQueryState, parseAsBoolean } from "nuqs";
|
||||||
import { StickToBottom, useStickToBottomContext } from "use-stick-to-bottom";
|
import { StickToBottom, useStickToBottomContext } from "use-stick-to-bottom";
|
||||||
@@ -143,6 +144,59 @@ export function Thread() {
|
|||||||
const messages = stream.messages;
|
const messages = stream.messages;
|
||||||
const isLoading = stream.isLoading;
|
const isLoading = stream.isLoading;
|
||||||
|
|
||||||
|
// 保存聊天记录功能
|
||||||
|
const saveChatHistory = () => {
|
||||||
|
if (!messages.length) {
|
||||||
|
toast.info("没有可保存的聊天记录");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 准备聊天记录数据
|
||||||
|
const chatData = {
|
||||||
|
threadId: threadId || "new_thread",
|
||||||
|
timestamp: new Date().toISOString(),
|
||||||
|
messages: messages.map(msg => {
|
||||||
|
// 安全处理消息内容
|
||||||
|
let content = "";
|
||||||
|
try {
|
||||||
|
if (typeof msg.content === 'string') {
|
||||||
|
content = msg.content;
|
||||||
|
} else if (msg.content) {
|
||||||
|
// 直接将非字符串内容转换为字符串
|
||||||
|
content = JSON.stringify(msg.content, null, 2);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
content = String(msg.content || "");
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
type: msg.type || "unknown",
|
||||||
|
content: content,
|
||||||
|
id: msg.id || uuidv4(),
|
||||||
|
createdAt: new Date().toISOString()
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
|
// 创建Blob并下载
|
||||||
|
const blob = new Blob([JSON.stringify(chatData, null, 2)], { type: 'application/json' });
|
||||||
|
const url = URL.createObjectURL(blob);
|
||||||
|
const a = document.createElement('a');
|
||||||
|
a.href = url;
|
||||||
|
a.download = `chat_history_${new Date().toISOString().slice(0, 10)}_${threadId || 'new'}.json`;
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
document.body.removeChild(a);
|
||||||
|
URL.revokeObjectURL(url);
|
||||||
|
|
||||||
|
toast.success("聊天记录已保存");
|
||||||
|
} catch (error) {
|
||||||
|
console.error("保存聊天记录失败:", error);
|
||||||
|
toast.error("保存聊天记录失败,请重试");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const lastError = useRef<string | undefined>(undefined);
|
const lastError = useRef<string | undefined>(undefined);
|
||||||
|
|
||||||
const setThreadId = (id: string | null) => {
|
const setThreadId = (id: string | null) => {
|
||||||
@@ -371,6 +425,16 @@ export function Thread() {
|
|||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<OpenGitHubRepo />
|
<OpenGitHubRepo />
|
||||||
</div>
|
</div>
|
||||||
|
<TooltipIconButton
|
||||||
|
size="lg"
|
||||||
|
className="p-4"
|
||||||
|
tooltip="Save chat history"
|
||||||
|
variant="ghost"
|
||||||
|
onClick={saveChatHistory}
|
||||||
|
disabled={messages.length === 0}
|
||||||
|
>
|
||||||
|
<Download className="size-5" />
|
||||||
|
</TooltipIconButton>
|
||||||
<TooltipIconButton
|
<TooltipIconButton
|
||||||
size="lg"
|
size="lg"
|
||||||
className="p-4"
|
className="p-4"
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ const StreamSession = ({
|
|||||||
|
|
||||||
// Default values for the form
|
// Default values for the form
|
||||||
const DEFAULT_API_URL = "http://localhost:2024";
|
const DEFAULT_API_URL = "http://localhost:2024";
|
||||||
const DEFAULT_ASSISTANT_ID = "agent";
|
const DEFAULT_ASSISTANT_ID = "my_agent";
|
||||||
|
|
||||||
export const StreamProvider: React.FC<{ children: ReactNode }> = ({
|
export const StreamProvider: React.FC<{ children: ReactNode }> = ({
|
||||||
children,
|
children,
|
||||||
|
|||||||
Reference in New Issue
Block a user