File size: 2,138 Bytes
9332ccf | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | /**
* @license
* Copyright 2025 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import * as fsPromises from 'node:fs/promises';
import path from 'node:path';
import type { Content } from '@google/genai';
/**
* Serializes chat history to a Markdown string.
*/
export function serializeHistoryToMarkdown(
history: readonly Content[],
): string {
return history
.map((item) => {
const text =
item.parts
?.map((part) => {
if (part.text) {
return part.text;
}
if (part.functionCall) {
return (
`**Tool Command**:\n` +
'```json\n' +
JSON.stringify(part.functionCall, null, 2) +
'\n```'
);
}
if (part.functionResponse) {
return (
`**Tool Response**:\n` +
'```json\n' +
JSON.stringify(part.functionResponse, null, 2) +
'\n```'
);
}
return '';
})
.join('') || '';
const roleIcon = item.role === 'user' ? '🧑💻' : '✨';
return `## ${(item.role || 'model').toUpperCase()} ${roleIcon}\n\n${text}`;
})
.join('\n\n---\n\n');
}
/**
* Options for exporting chat history.
*/
export interface ExportHistoryOptions {
history: readonly Content[];
filePath: string;
}
/**
* Exports chat history to a file (JSON or Markdown).
*/
export async function exportHistoryToFile(
options: ExportHistoryOptions,
): Promise<void> {
const { history, filePath } = options;
const extension = path.extname(filePath).toLowerCase();
let content: string;
if (extension === '.json') {
content = JSON.stringify(history, null, 2);
} else if (extension === '.md') {
content = serializeHistoryToMarkdown(history);
} else {
throw new Error(
`Unsupported file extension: ${extension}. Use .json or .md.`,
);
}
const dir = path.dirname(filePath);
await fsPromises.mkdir(dir, { recursive: true });
await fsPromises.writeFile(filePath, content, 'utf-8');
}
|