promptcoder-cli
Version:
AI-powered code generation CLI tool with conversation persistence, file tools, and LLM integration
217 lines • 8.92 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.ConversationManager = void 0;
const fs = __importStar(require("fs-extra"));
const path = __importStar(require("path"));
const os = __importStar(require("os"));
const CONVERSATIONS_DIR = path.join(os.homedir(), '.promptcoder', 'conversations');
class ConversationManager {
constructor() {
this.ensureConversationsDir();
}
async ensureConversationsDir() {
await fs.ensureDir(CONVERSATIONS_DIR);
}
getConversationPath(id) {
return path.join(CONVERSATIONS_DIR, `${id}.json`);
}
generateId() {
return `conv_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
}
async saveConversation(messages, workingDirectory, name, description, id) {
const conversationId = id || this.generateId();
const now = new Date();
const conversation = {
id: conversationId,
name: name || `Conversation ${new Date().toLocaleDateString()}`,
messages,
workingDirectory,
createdAt: id ? (await this.loadConversation(id))?.createdAt || now : now,
updatedAt: now,
description
};
const filePath = this.getConversationPath(conversationId);
await fs.writeJson(filePath, conversation, { spaces: 2 });
return conversationId;
}
async loadConversation(id) {
try {
const filePath = this.getConversationPath(id);
if (!(await fs.pathExists(filePath))) {
return null;
}
const conversation = await fs.readJson(filePath);
// Convert date strings back to Date objects
conversation.createdAt = new Date(conversation.createdAt);
conversation.updatedAt = new Date(conversation.updatedAt);
return conversation;
}
catch (error) {
console.error(`Error loading conversation ${id}:`, error);
return null;
}
}
async listConversations() {
try {
const files = await fs.readdir(CONVERSATIONS_DIR);
const conversationFiles = files.filter(file => file.endsWith('.json'));
const conversations = [];
for (const file of conversationFiles) {
try {
const filePath = path.join(CONVERSATIONS_DIR, file);
const conversation = await fs.readJson(filePath);
conversations.push({
id: conversation.id,
name: conversation.name,
workingDirectory: conversation.workingDirectory,
createdAt: new Date(conversation.createdAt),
updatedAt: new Date(conversation.updatedAt),
messageCount: conversation.messages.length,
description: conversation.description
});
}
catch (error) {
// Skip corrupted files
continue;
}
}
// Sort by last updated, newest first
return conversations.sort((a, b) => b.updatedAt.getTime() - a.updatedAt.getTime());
}
catch (error) {
console.error('Error listing conversations:', error);
return [];
}
}
async deleteConversation(id) {
try {
const filePath = this.getConversationPath(id);
if (await fs.pathExists(filePath)) {
await fs.remove(filePath);
return true;
}
return false;
}
catch (error) {
console.error(`Error deleting conversation ${id}:`, error);
return false;
}
}
async renameConversation(id, newName) {
try {
const conversation = await this.loadConversation(id);
if (!conversation) {
return false;
}
conversation.name = newName;
conversation.updatedAt = new Date();
await this.saveConversation(conversation.messages, conversation.workingDirectory, conversation.name, conversation.description, conversation.id);
return true;
}
catch (error) {
console.error(`Error renaming conversation ${id}:`, error);
return false;
}
}
async searchConversations(query) {
const allConversations = await this.listConversations();
const lowerQuery = query.toLowerCase();
return allConversations.filter(conv => conv.name.toLowerCase().includes(lowerQuery) ||
(conv.description && conv.description.toLowerCase().includes(lowerQuery)) ||
conv.workingDirectory.toLowerCase().includes(lowerQuery));
}
async exportConversation(id, format = 'json') {
const conversation = await this.loadConversation(id);
if (!conversation) {
return null;
}
if (format === 'json') {
return JSON.stringify(conversation, null, 2);
}
// Markdown format
let markdown = `# ${conversation.name}\n\n`;
markdown += `**Created:** ${conversation.createdAt.toISOString()}\n`;
markdown += `**Updated:** ${conversation.updatedAt.toISOString()}\n`;
markdown += `**Working Directory:** ${conversation.workingDirectory}\n`;
if (conversation.description) {
markdown += `**Description:** ${conversation.description}\n`;
}
markdown += `\n---\n\n`;
for (const message of conversation.messages) {
if (message.role === 'user') {
markdown += `## User\n\n${message.content}\n\n`;
}
else if (message.role === 'assistant') {
markdown += `## Assistant\n\n${message.content}\n\n`;
if (message.toolCalls && message.toolCalls.length > 0) {
markdown += `**Tool Calls:**\n`;
for (const call of message.toolCalls) {
markdown += `- ${call.name}(${JSON.stringify(call.parameters)})\n`;
}
markdown += `\n`;
}
}
else if (message.role === 'tool') {
markdown += `**Tool Result:**\n\n\`\`\`\n${message.content}\n\`\`\`\n\n`;
}
}
return markdown;
}
async getConversationStats() {
const conversations = await this.listConversations();
if (conversations.length === 0) {
return {
total: 0,
totalMessages: 0,
oldestDate: null,
newestDate: null,
averageMessagesPerConversation: 0
};
}
const totalMessages = conversations.reduce((sum, conv) => sum + conv.messageCount, 0);
const oldestDate = conversations.reduce((oldest, conv) => !oldest || conv.createdAt < oldest ? conv.createdAt : oldest, null);
const newestDate = conversations.reduce((newest, conv) => !newest || conv.updatedAt > newest ? conv.updatedAt : newest, null);
return {
total: conversations.length,
totalMessages,
oldestDate,
newestDate,
averageMessagesPerConversation: Math.round(totalMessages / conversations.length)
};
}
}
exports.ConversationManager = ConversationManager;
//# sourceMappingURL=conversation-manager.js.map