Skip to main content
Glama
MUSE-CODE-SPACE

Vibe Coding Documentation MCP (MUSE)

createSessionLog.ts5.64 kB
import { SessionLog, CodeContext, DesignDecision, SessionLogOptions } from '../types/index.js'; import { generateId, formatDate, getCurrentTimestamp } from '../utils/markdown.js'; import { validatePathWithinDirectory, sanitizeFilename } from '../core/security.js'; import * as fs from 'fs/promises'; import * as path from 'path'; export interface CreateSessionLogInput { title: string; summary: string; codeContexts?: CodeContext[]; designDecisions?: DesignDecision[]; duration?: number; tags?: string[]; options?: SessionLogOptions; } export interface CreateSessionLogOutput { sessionLog: SessionLog; filePath?: string; content: string; } export async function createSessionLog(input: CreateSessionLogInput): Promise<CreateSessionLogOutput> { const sessionLog: SessionLog = { sessionId: generateId(), date: formatDate(), title: input.title, summary: input.summary, codeContexts: input.codeContexts || [], designDecisions: input.designDecisions || [], duration: input.duration, tags: input.tags }; const options = input.options || { logType: 'session', format: 'markdown' }; let content: string; let filePath: string | undefined; if (options.format === 'json') { content = JSON.stringify(sessionLog, null, 2); } else { content = generateMarkdownLog(sessionLog, options.logType); } // 파일로 저장 if (options.outputPath) { const extension = options.format === 'json' ? '.json' : '.md'; const rawFilename = options.logType === 'daily' ? `${formatDate()}-daily-log${extension}` : `${sessionLog.sessionId}${extension}`; // Sanitize filename and validate path const safeFilename = sanitizeFilename(rawFilename) + (rawFilename.endsWith(extension) ? '' : extension); const targetPath = path.join(options.outputPath, safeFilename); try { // Validate path stays within output directory (prevent path traversal) filePath = validatePathWithinDirectory(targetPath, options.outputPath); await fs.mkdir(path.dirname(filePath), { recursive: true }); await fs.writeFile(filePath, content, 'utf-8'); } catch (error) { // 파일 저장 실패시 filePath를 undefined로 filePath = undefined; } } return { sessionLog, filePath, content }; } function generateMarkdownLog(log: SessionLog, logType: 'daily' | 'session'): string { let md = ''; if (logType === 'daily') { md += `# Daily Vibe Coding Log - ${log.date}\n\n`; } else { md += `# Session: ${log.title}\n\n`; md += `**Session ID:** ${log.sessionId}\n`; md += `**Date:** ${log.date}\n`; } if (log.duration) { md += `**Duration:** ${Math.round(log.duration / 60)} minutes\n`; } if (log.tags && log.tags.length > 0) { md += `**Tags:** ${log.tags.map(t => `#${t}`).join(' ')}\n`; } md += '\n---\n\n'; md += `## Summary\n\n${log.summary}\n\n`; if (log.codeContexts.length > 0) { md += `## Code Contexts\n\n`; for (const context of log.codeContexts) { md += `### ${context.timestamp}\n\n`; md += context.conversationSummary + '\n\n'; if (context.codeBlocks.length > 0) { md += `<details>\n<summary>View Code (${context.codeBlocks.length} blocks)</summary>\n\n`; for (const block of context.codeBlocks) { md += `\`\`\`${block.language}\n${block.code}\n\`\`\`\n\n`; } md += `</details>\n\n`; } } } if (log.designDecisions.length > 0) { md += `## Design Decisions\n\n`; for (const decision of log.designDecisions) { md += `### ${decision.title}\n\n`; md += `**Category:** ${decision.category}\n\n`; md += decision.description + '\n\n'; if (decision.rationale) { md += `> **Rationale:** ${decision.rationale}\n\n`; } if (decision.alternatives && decision.alternatives.length > 0) { md += `**Alternatives considered:**\n`; for (const alt of decision.alternatives) { md += `- ${alt}\n`; } md += '\n'; } } } md += `---\n\n*Log generated at ${getCurrentTimestamp()}*\n`; return md; } export const createSessionLogSchema = { name: 'muse_create_session_log', description: 'Creates daily or session-based vibe coding session logs.', inputSchema: { type: 'object', properties: { title: { type: 'string', description: 'Title of the session' }, summary: { type: 'string', description: 'Summary of what was accomplished' }, codeContexts: { type: 'array', description: 'Array of code contexts from the session', items: { type: 'object' } }, designDecisions: { type: 'array', description: 'Array of design decisions made', items: { type: 'object' } }, duration: { type: 'number', description: 'Session duration in seconds' }, tags: { type: 'array', items: { type: 'string' }, description: 'Tags for the session' }, options: { type: 'object', properties: { logType: { type: 'string', enum: ['daily', 'session'], description: 'Type of log to create' }, outputPath: { type: 'string', description: 'Directory path to save the log file' }, format: { type: 'string', enum: ['markdown', 'json'], description: 'Output format of the log' } } } }, required: ['title', 'summary'] } };

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/MUSE-CODE-SPACE/vibe-coding-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server