Files
writing-agent/web/export.js

109 lines
2.9 KiB
JavaScript

/** 将会话消息导出为可读 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);
}