Initial commit
This commit is contained in:
108
web/export.js
Normal file
108
web/export.js
Normal file
@@ -0,0 +1,108 @@
|
||||
/** 将会话消息导出为可读 Markdown 文本 */
|
||||
|
||||
function formatExportTime(iso) {
|
||||
if (!iso) return "";
|
||||
const d = new Date(iso);
|
||||
return d.toLocaleString("zh-CN", {
|
||||
month: "numeric",
|
||||
day: "numeric",
|
||||
hour: "2-digit",
|
||||
minute: "2-digit",
|
||||
});
|
||||
}
|
||||
|
||||
const KIND_LABELS = {
|
||||
user_input: "用户输入",
|
||||
orchestrator_decision: "总管决策",
|
||||
orchestrator_prompt: "总管询问",
|
||||
agent_tool: "Agent Tool",
|
||||
worker_running: "Worker 执行",
|
||||
worker_output: "Worker 产出",
|
||||
worker_stub: "Worker 占位",
|
||||
system_info: "系统",
|
||||
error: "错误",
|
||||
};
|
||||
|
||||
export function sessionToMarkdown(view) {
|
||||
if (!view) return "";
|
||||
|
||||
const lines = [];
|
||||
lines.push(`# ${view.bookTitle ?? "未命名作品"}`);
|
||||
lines.push("");
|
||||
lines.push(`- Skill: \`${view.activeSkill ?? "—"}\``);
|
||||
lines.push(`- 阶段: ${view.phase ?? "—"}`);
|
||||
if (view.waitingReason?.kind) {
|
||||
lines.push(`- 等待: ${view.waitingReason.kind}`);
|
||||
}
|
||||
lines.push(`- 导出时间: ${new Date().toLocaleString("zh-CN")}`);
|
||||
lines.push("");
|
||||
|
||||
if (view.skillCatalog?.length) {
|
||||
const stageLabel = view.lifecycleStage === "play" ? "游玩" : "创作";
|
||||
lines.push(`## ${stageLabel}能力清单`);
|
||||
lines.push("");
|
||||
for (const skill of view.skillCatalog) {
|
||||
const mark =
|
||||
skill.status === "done"
|
||||
? "x"
|
||||
: skill.status === "active"
|
||||
? ">"
|
||||
: " ";
|
||||
lines.push(`- [${mark}] **${skill.label}** (\`${skill.id}\`) — ${skill.purpose}`);
|
||||
}
|
||||
lines.push("");
|
||||
} else if (view.pipeline?.length) {
|
||||
lines.push("## 流程进度");
|
||||
lines.push("");
|
||||
for (const step of view.pipeline) {
|
||||
const mark =
|
||||
step.status === "done" ? "x" : step.status === "active" ? ">" : " ";
|
||||
lines.push(`- [${mark}] ${step.label}`);
|
||||
}
|
||||
lines.push("");
|
||||
}
|
||||
|
||||
lines.push("## 对话与调度记录");
|
||||
lines.push("");
|
||||
|
||||
for (const msg of view.messages ?? []) {
|
||||
const kind = msg.kind ?? (msg.role === "user" ? "user_input" : "system_info");
|
||||
const label = msg.title ?? KIND_LABELS[kind] ?? kind;
|
||||
lines.push(`### ${label}`);
|
||||
lines.push("");
|
||||
lines.push(`*${formatExportTime(msg.createdAt)}${msg.actor ? ` · ${msg.actor}` : ""}*`);
|
||||
|
||||
if (msg.tokenUsage?.totalTokens) {
|
||||
lines.push(`*Token: ${msg.tokenUsage.totalTokens}*`);
|
||||
}
|
||||
lines.push("");
|
||||
|
||||
if (msg.thinking?.trim()) {
|
||||
lines.push("**思维链**");
|
||||
lines.push("");
|
||||
lines.push(msg.thinking.trim());
|
||||
lines.push("");
|
||||
}
|
||||
|
||||
const body = (msg.body ?? msg.text ?? "").trim();
|
||||
if (body) {
|
||||
lines.push(body);
|
||||
lines.push("");
|
||||
}
|
||||
|
||||
lines.push("---");
|
||||
lines.push("");
|
||||
}
|
||||
|
||||
return lines.join("\n").trim() + "\n";
|
||||
}
|
||||
|
||||
export function downloadMarkdown(filename, content) {
|
||||
const blob = new Blob([content], { type: "text/markdown;charset=utf-8" });
|
||||
const url = URL.createObjectURL(blob);
|
||||
const a = document.createElement("a");
|
||||
a.href = url;
|
||||
a.download = filename;
|
||||
a.click();
|
||||
URL.revokeObjectURL(url);
|
||||
}
|
||||
Reference in New Issue
Block a user