import { Anthropic } from "@anthropic-ai/sdk" import os from "os" import * as path from "path" import * as vscode from "vscode" export async function downloadTask(dateTs: number, conversationHistory: Anthropic.MessageParam[]) { // File name const date = new Date(dateTs) const month = date.toLocaleString("en-US", { month: "short" }).toLowerCase() const day = date.getDate() const year = date.getFullYear() let hours = date.getHours() const minutes = date.getMinutes().toString().padStart(2, "0") const seconds = date.getSeconds().toString().padStart(2, "0") const ampm = hours >= 12 ? "pm" : "am" hours = hours % 12 hours = hours ? hours : 12 // the hour '0' should be '12' const fileName = `claude_dev_task_${month}-${day}-${year}_${hours}-${minutes}-${seconds}-${ampm}.md` // Generate markdown const markdownContent = conversationHistory .map((message) => { const role = message.role === "user" ? "**User:**" : "**Assistant:**" const content = Array.isArray(message.content) ? message.content.map((block) => formatContentBlockToMarkdown(block, conversationHistory)).join("\n") : message.content return `${role}\n\n${content}\n\n` }) .join("---\n\n") // Prompt user for save location const saveUri = await vscode.window.showSaveDialog({ filters: { Markdown: ["md"] }, defaultUri: vscode.Uri.file(path.join(os.homedir(), "Downloads", fileName)), }) if (saveUri) { // Write content to the selected location await vscode.workspace.fs.writeFile(saveUri, Buffer.from(markdownContent)) vscode.window.showTextDocument(saveUri, { preview: true }) } } export function formatContentBlockToMarkdown( block: | Anthropic.TextBlockParam | Anthropic.ImageBlockParam | Anthropic.ToolUseBlockParam | Anthropic.ToolResultBlockParam, messages: Anthropic.MessageParam[] ): string { switch (block.type) { case "text": return block.text case "image": return `[Image]` case "tool_use": let input: string if (typeof block.input === "object" && block.input !== null) { input = Object.entries(block.input) .map(([key, value]) => `${key.charAt(0).toUpperCase() + key.slice(1)}: ${value}`) .join("\n") } else { input = String(block.input) } return `[Tool Use: ${block.name}]\n${input}` case "tool_result": const toolName = findToolName(block.tool_use_id, messages) if (typeof block.content === "string") { return `[${toolName}${block.is_error ? " (Error)" : ""}]\n${block.content}` } else if (Array.isArray(block.content)) { return `[${toolName}${block.is_error ? " (Error)" : ""}]\n${block.content .map((contentBlock) => formatContentBlockToMarkdown(contentBlock, messages)) .join("\n")}` } else { return `[${toolName}${block.is_error ? " (Error)" : ""}]` } default: return "[Unexpected content type]" } } function findToolName(toolCallId: string, messages: Anthropic.MessageParam[]): string { for (const message of messages) { if (Array.isArray(message.content)) { for (const block of message.content) { if (block.type === "tool_use" && block.id === toolCallId) { return block.name } } } } return "Unknown Tool" }