feat: add session export with full and compressed modes (#507)
Add export functionality that allows users to download session data as JSON or plain text, with optional LLM-based context compression for long conversations. Includes UI controls in chat panel, session list, and history view, plus i18n strings for all 8 locales. Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { renameSession, setSessionWorkspace, batchDeleteSessions } from "@/api/hermes/sessions";
|
||||
import { renameSession, setSessionWorkspace, batchDeleteSessions, exportSession } from "@/api/hermes/sessions";
|
||||
import { useChatStore, type Session } from "@/stores/hermes/chat";
|
||||
import { useSessionBrowserPrefsStore } from "@/stores/hermes/session-browser-prefs";
|
||||
import {
|
||||
@@ -303,6 +303,28 @@ const contextMenuOptions = computed(() => [
|
||||
},
|
||||
{ label: t("chat.rename"), key: "rename" },
|
||||
{ label: t("chat.setWorkspace"), key: "workspace" },
|
||||
{
|
||||
label: t("chat.export"),
|
||||
key: "export",
|
||||
children: [
|
||||
{
|
||||
label: t("chat.exportFull"),
|
||||
key: "export-full",
|
||||
children: [
|
||||
{ label: "JSON", key: "export-full-json" },
|
||||
{ label: "TXT", key: "export-full-txt" },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: t("chat.exportCompressed"),
|
||||
key: "export-compressed",
|
||||
children: [
|
||||
{ label: "JSON", key: "export-compressed-json" },
|
||||
{ label: "TXT", key: "export-compressed-txt" },
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{ label: t("chat.copySessionId"), key: "copy-id" },
|
||||
]);
|
||||
|
||||
@@ -318,7 +340,15 @@ const showContextMenu = ref(false);
|
||||
const contextMenuX = ref(0);
|
||||
const contextMenuY = ref(0);
|
||||
|
||||
function handleContextMenuSelect(key: string) {
|
||||
function parseExportKey(key: string): { mode: 'full' | 'compressed'; ext: 'json' | 'txt' } | null {
|
||||
if (key === 'export-full-json') return { mode: 'full', ext: 'json' }
|
||||
if (key === 'export-full-txt') return { mode: 'full', ext: 'txt' }
|
||||
if (key === 'export-compressed-json') return { mode: 'compressed', ext: 'json' }
|
||||
if (key === 'export-compressed-txt') return { mode: 'compressed', ext: 'txt' }
|
||||
return null
|
||||
}
|
||||
|
||||
async function handleContextMenuSelect(key: string) {
|
||||
showContextMenu.value = false;
|
||||
if (!contextSessionId.value) return;
|
||||
if (key === "pin") {
|
||||
@@ -327,6 +357,17 @@ function handleContextMenuSelect(key: string) {
|
||||
}
|
||||
if (key === "copy-id") {
|
||||
copySessionId(contextSessionId.value);
|
||||
} else if (parseExportKey(key)) {
|
||||
const { mode, ext } = parseExportKey(key)!;
|
||||
const loadingMsg = mode === "compressed" ? message.loading(t("chat.exportCompressing"), { duration: 0 }) : null;
|
||||
try {
|
||||
await exportSession(contextSessionId.value, mode, ext);
|
||||
loadingMsg?.destroy();
|
||||
message.success(t("chat.exportSuccess"));
|
||||
} catch {
|
||||
loadingMsg?.destroy();
|
||||
message.error(t("chat.exportFailed"));
|
||||
}
|
||||
} else if (key === "workspace") {
|
||||
const session = chatStore.sessions.find(
|
||||
(s) => s.id === contextSessionId.value,
|
||||
|
||||
Reference in New Issue
Block a user