src / toolsProvider.ts
import { text, tool, type Tool, type ToolsProviderController } from "@lmstudio/sdk";
import { writeFile } from "fs/promises";
import { join } from "path";
import { z } from "zod";
import { Document, Packer, Paragraph, TextRun, HeadingLevel } from "docx";
const chatMessageSchema = z.object({
role: z.enum(["user", "assistant", "system"]),
content: z.string(),
timestamp: z.number().optional(),
});
export async function toolsProvider(ctl: ToolsProviderController) {
const tools: Tool[] = [];
const exportWordTool = tool({
name: "export_chat_to_word",
description: text`
Exports the current chat conversation to a Word (.docx) file.
You must receive the full list of messages from the user to export.
Each message should include the role (user/assistant/system) and content.
The file will be saved in the current working directory with a timestamped name.
Returns the path where the file was saved.
`,
parameters: {
messages: z.array(chatMessageSchema).describe("Array of chat messages to export"),
filename: z.string().optional().describe("Optional custom filename (without extension)"),
},
implementation: async ({ messages, filename }) => {
const workingDirectory = ctl.getWorkingDirectory();
const now = new Date();
const timestamp = now.toISOString().replace(/[:.]/g, "-");
const outputFilename = (filename ?? `chat-export-${timestamp}`) + ".docx";
const outputPath = join(workingDirectory, outputFilename);
const children: Paragraph[] = [];
children.push(
new Paragraph({
text: "EXPORTACION DE CHAT - LM STUDIO",
heading: HeadingLevel.HEADING_1,
}),
new Paragraph({
children: [new TextRun(`Fecha: ${now.toLocaleString("es-ES")}`)],
}),
new Paragraph({
children: [new TextRun(`Mensajes: ${messages.length}`)],
}),
new Paragraph({ text: "" }),
);
for (let i = 0; i < messages.length; i++) {
const msg = messages[i];
const role =
msg.role === "user" ? "USUARIO" :
msg.role === "assistant" ? "ASISTENTE" : "SISTEMA";
const time = msg.timestamp
? new Date(msg.timestamp).toLocaleTimeString("es-ES")
: "--:--";
children.push(
new Paragraph({
children: [
new TextRun({
text: `[${i + 1}] ${role} (${time})`,
bold: true,
}),
],
}),
new Paragraph({
children: [new TextRun(msg.content.replace(/\r/g, "").trim())],
}),
new Paragraph({ text: "" }),
);
}
const doc = new Document({ sections: [{ children }] });
const buffer = await Packer.toBuffer(doc);
await writeFile(outputPath, buffer);
return { success: true, path: outputPath };
},
});
tools.push(exportWordTool);
return tools;
}