Project Files
dist / tools / export_chat.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createExportChatTool = createExportChatTool;
const sdk_1 = require("@lmstudio/sdk");
const promises_1 = require("fs/promises");
const fs_1 = require("fs");
const path_1 = require("path");
const config_1 = require("../config");
const workingDirectoryInfo_1 = require("../workingDirectoryInfo");
const embedLocalImages_1 = require("../embedLocalImages");
const common_1 = require("./common");
function createExportChatTool(ctl) {
return (0, sdk_1.tool)({
name: "export_chat",
description: (0, sdk_1.text) `
Export the current chat to Markdown. Confirm success and file paths only.
`,
parameters: {},
implementation: async () => {
const cfg = ctl.getPluginConfig(config_1.configSchematics);
const shouldOverwrite = cfg.get("overwrite");
const includeThinking = cfg.get("includeThinking");
const includeToolCalls = cfg.get("includeToolCalls");
const emitMessagesJson = cfg.get("emitMessagesJson");
const embedImages = cfg.get("embedImages");
const workingDirectory = ctl.getWorkingDirectory();
const wdInfo = (0, workingDirectoryInfo_1.getWorkingDirectoryInfo)(workingDirectory);
const chatId = (0, path_1.basename)(workingDirectory);
(0, common_1.validateChatId)(chatId);
if (!wdInfo.looksLikeLMStudioWorkingDir) {
throw new Error(`Unexpected working directory layout.\n` +
`Working directory (raw): ${wdInfo.workingDirectoryRaw}\n` +
`Working directory (trimmed): ${wdInfo.workingDirectoryTrimmed}\n` +
`parentDirName: ${wdInfo.parentDirName}\n` +
`chatId: ${wdInfo.chatId} (valid13Digits=${wdInfo.chatIdValid13Digits})`);
}
const lmHome = wdInfo.lmHomeFromWorkingDir;
if (!lmHome) {
throw new Error(`Unable to derive LM Studio home from working directory.\n` +
`Working directory (raw): ${wdInfo.workingDirectoryRaw}\n` +
`Working directory (trimmed): ${wdInfo.workingDirectoryTrimmed}\n` +
`parentDirName: ${wdInfo.parentDirName}\n` +
`chatId: ${wdInfo.chatId} (valid13Digits=${wdInfo.chatIdValid13Digits})`);
}
const globalSource = (0, path_1.join)(lmHome, "conversations", `${chatId}.conversation.json`);
const destMd = (0, path_1.join)(workingDirectory, `${chatId}.conversation.md`);
const destMessagesJson = (0, path_1.join)(workingDirectory, `${chatId}.conversation.messages.json`);
if (!(0, fs_1.existsSync)(globalSource)) {
throw new Error(`Conversation file not found: ${globalSource}\n` +
`Working directory (raw): ${wdInfo.workingDirectoryRaw}\n` +
`Working directory (trimmed): ${wdInfo.workingDirectoryTrimmed}\n` +
`isAbsolute: ${wdInfo.isAbsolute}\n` +
`resolvedPath: ${wdInfo.resolvedPath}`);
}
await (0, common_1.ensureDir)(workingDirectory);
if (!shouldOverwrite && ((0, fs_1.existsSync)(destMd) || (emitMessagesJson && (0, fs_1.existsSync)(destMessagesJson)))) {
return {
ok: true,
skipped_conversion: true,
reason: "Destination exists and overwrite=false",
destination_markdown: destMd,
destination_messages_json: emitMessagesJson ? destMessagesJson : undefined,
};
}
const data = await (0, common_1.readJson)(globalSource);
const messages = Array.isArray(data?.messages) ? data.messages : [];
let messagesJsonBytes = 0;
if (emitMessagesJson) {
const payload = JSON.stringify({ messages }, null, 2);
await (0, promises_1.writeFile)(destMessagesJson, payload, "utf-8");
messagesJsonBytes = Buffer.byteLength(payload, "utf-8");
}
let markdown = (0, common_1.convertMessagesToMarkdown)(messages, {
includeThinking,
includeToolCalls,
embedImages,
});
if (embedImages) {
markdown = await (0, embedLocalImages_1.embedLocalImagesInMarkdown)(markdown, workingDirectory);
}
await (0, promises_1.writeFile)(destMd, markdown.endsWith("\n") ? markdown : markdown + "\n", "utf-8");
const mdBytes = await (0, common_1.safeFileSize)(destMd);
return {
ok: true,
destination_markdown: destMd,
destination_messages_json: emitMessagesJson ? destMessagesJson : undefined,
bytes_markdown: mdBytes,
bytes_messages_json: emitMessagesJson ? messagesJsonBytes : undefined,
};
},
});
}