UNPKG

@gacua/backend

Version:

GACUA Backend

153 lines 6.31 kB
/** * @license * Copyright 2025 MuleRun * SPDX-License-Identifier: Apache-2.0 */ import * as fs from 'fs/promises'; import * as path from 'path'; import { existsSync, mkdirSync } from 'fs'; import { logger } from '../logger.js'; const repositoryLogger = logger.child({ module: 'repository' }); export class SessionRepository { baseDir = '.gemini/gacua_sessions'; constructor() { if (!existsSync(this.baseDir)) { mkdirSync(this.baseDir, { recursive: true }); repositoryLogger.info({ baseDir: this.baseDir }, 'Created sessions directory'); } else { repositoryLogger.debug({ baseDir: this.baseDir }, 'Sessions directory exists'); } } getMetadataFilePath(sessionId) { return path.join(this.baseDir, sessionId, 'metadata.json'); } getMessagesFilePath(sessionId) { return path.join(this.baseDir, sessionId, 'messages.jsonl'); } getImagesFilePath(sessionId, fileName) { return path.join(this.baseDir, sessionId, 'images', fileName); } async createSession(metadata) { const imagesDir = path.join(this.baseDir, metadata.id, 'images'); await fs.mkdir(imagesDir, { recursive: true }); const metadataPath = this.getMetadataFilePath(metadata.id); await fs.writeFile(metadataPath, JSON.stringify(metadata, null, 2), 'utf8'); repositoryLogger.info({ sessionId: metadata.id, sessionName: metadata.name }, 'Session created in repository'); } async updateSession(sessionId, updates) { const metadataPath = this.getMetadataFilePath(sessionId); const existingMetadata = await this.getSession(sessionId); const updatedMetadata = { ...existingMetadata, ...updates, id: existingMetadata.id, }; await fs.writeFile(metadataPath, JSON.stringify(updatedMetadata, null, 2), 'utf8'); repositoryLogger.debug({ sessionId, updates }, 'Session metadata updated'); } async getSession(sessionId) { try { const metadataPath = this.getMetadataFilePath(sessionId); const content = await fs.readFile(metadataPath, 'utf8'); const metadata = JSON.parse(content); repositoryLogger.debug({ sessionId }, 'Session metadata retrieved'); return metadata; } catch (error) { repositoryLogger.warn({ sessionId, err: error }, 'Failed to retrieve session metadata'); throw error; } } async getAllSessions() { try { const sessionDirs = await fs.readdir(this.baseDir); const sessions = []; let skippedCount = 0; for (const sessionId of sessionDirs) { // Skip system files like .DS_Store if (sessionId.startsWith('.')) { continue; } try { const metadata = await this.getSession(sessionId); sessions.push(metadata); } catch (error) { skippedCount++; repositoryLogger.debug({ sessionId, err: error }, 'Skipping session with invalid metadata'); continue; } } repositoryLogger.info({ totalSessions: sessions.length, skippedSessions: skippedCount, }, 'Retrieved all sessions'); return sessions; } catch (error) { repositoryLogger.error({ err: error }, 'Failed to retrieve sessions'); throw error; } } async appendMessages(sessionId, messages) { try { const filePath = this.getMessagesFilePath(sessionId); const messageLines = messages.map((message) => JSON.stringify(message) + '\n'); await fs.appendFile(filePath, messageLines.join(''), 'utf8'); repositoryLogger.debug({ sessionId, messageCount: messages.length }, 'Messages appended to session'); } catch (error) { repositoryLogger.error({ sessionId, messageCount: messages.length, err: error }, 'Failed to append messages'); throw error; } } async getMessages(sessionId, includeHidden) { try { const filePath = this.getMessagesFilePath(sessionId); const content = await fs.readFile(filePath, 'utf8'); const messages = content .split('\n') .filter((line) => line.trim() !== '') .map((line) => JSON.parse(line)); const filteredMessages = includeHidden ? messages : messages.filter((message) => message.forDisplay !== false); repositoryLogger.debug({ sessionId, totalMessages: messages.length, displayedMessages: filteredMessages.length, includeHidden, }, 'Messages retrieved from session'); return filteredMessages; } catch (error) { repositoryLogger.error({ sessionId, includeHidden, err: error }, 'Failed to retrieve messages'); throw error; } } async saveImage(imageBuffer, sessionId, fileName) { try { const filePath = this.getImagesFilePath(sessionId, fileName); await fs.writeFile(filePath, imageBuffer); repositoryLogger.debug({ sessionId, fileName, imageSize: imageBuffer.length }, 'Image saved to session'); } catch (error) { repositoryLogger.error({ sessionId, fileName, err: error }, 'Failed to save image'); throw error; } } async getImage(sessionId, fileName) { try { const filePath = this.getImagesFilePath(sessionId, fileName); const imageBuffer = await fs.readFile(filePath); repositoryLogger.debug({ sessionId, fileName, imageSize: imageBuffer.length }, 'Image retrieved from session'); return imageBuffer; } catch (error) { repositoryLogger.warn({ sessionId, fileName, err: error }, 'Failed to retrieve image'); throw error; } } } //# sourceMappingURL=session.js.map