返回 DeepSeek-Reasonix
sessionExportData.ts
根目录 / desktop / frontend / src / lib / sessionExportData.ts
1 import type { Item, LiveStream } from "./useController";
2 import { mcpListAttribution } from "./mcpListAttribution";
3 export { mcpListAttribution, type McpListAttribution } from "./mcpListAttribution";
4
5 export function materializeLiveItems(items: Item[], live?: LiveStream): Item[] {
6 if (!live) return items;
7 return items.map((item) => {
8 if (item.kind !== "assistant" || item.id !== live.id) return item;
9 return { ...item, text: live.text, reasoning: live.reasoning, streaming: true };
10 });
11 }
12
13 function fence(label: string, value: string): string {
14 if (!value.trim()) return "";
15 const fenceToken = value.includes("```") ? "````" : "```";
16 return `${label}\n${fenceToken}\n${value.trim()}\n${fenceToken}`;
17 }
18
19 export function sessionItemsToMarkdown(title: string, items: Item[], live?: LiveStream): string {
20 const lines: string[] = [`# ${title.trim() || "Reasonix session"}`, ""];
21 for (const item of materializeLiveItems(items, live)) {
22 switch (item.kind) {
23 case "user":
24 lines.push("## User", "", item.text.trim(), "");
25 break;
26 case "assistant":
27 lines.push("## Assistant");
28 if (item.reasoning.trim()) lines.push("", "### Reasoning", "", item.reasoning.trim());
29 if (item.text.trim()) lines.push("", item.text.trim());
30 lines.push("");
31 break;
32 case "tool":
33 lines.push(`### Tool: ${item.name}`);
34 if (item.args.trim()) lines.push("", fence("Args", item.args));
35 if (item.output?.trim()) lines.push("", fence("Output", item.output));
36 if (item.error?.trim()) lines.push("", fence("Error", item.error));
37 lines.push("");
38 break;
39 case "phase":
40 lines.push("### Phase", "", item.text.trim(), "");
41 break;
42 case "notice":
43 lines.push(`### ${item.level === "warn" ? "Warning" : "Notice"}`, "", item.text.trim(), "");
44 if (item.detail?.trim()) lines.push("Details:", "", item.detail.trim(), "");
45 break;
46 case "compaction":
47 lines.push("### Context Compaction", "");
48 if (item.pending) lines.push("Compaction pending.");
49 else {
50 lines.push(`Messages: ${item.messages}`);
51 if (item.trigger) lines.push(`Trigger: ${item.trigger}`);
52 if (item.summary.trim()) lines.push("", item.summary.trim());
53 }
54 lines.push("");
55 break;
56 }
57 }
58 return lines.join("\n").replace(/\n{3,}/g, "\n\n").trimEnd() + "\n";
59 }
60
61 export function sessionItemsToJson(title: string, items: Item[], live?: LiveStream): string {
62 const materialized = materializeLiveItems(items, live);
63 return JSON.stringify({
64 title,
65 exportedAt: new Date().toISOString(),
66 mcpList: mcpListAttribution(materialized),
67 items: materialized,
68 }, null, 2);
69 }
70
70 lines TYPESCRIPT