UNPKG

@commit451/salamander

Version:

Never be AFK

128 lines 4.83 kB
import { collection, doc, getDocs, onSnapshot, orderBy, query, where, } from 'firebase/firestore'; import { db } from '../config/firebase.js'; import { AuthService } from './auth.js'; import { ApiService } from './api.js'; import { RunnerType } from '../types/runner.js'; import { generateDeviceId, getDeviceDisplayName } from '../utils/device.js'; import { EncryptionService } from '../utils/encryption.js'; import { loadAuth, saveAuth } from '../utils/storage.js'; export class RunnerService { static RUNNERS_COLLECTION = 'runners'; static async getAllRunners() { const userId = AuthService.userId; const deviceId = generateDeviceId(); if (!userId) { throw new Error('User not authenticated'); } const q = query(collection(db, this.RUNNERS_COLLECTION), where('userId', '==', userId), where('machineId', "==", deviceId), orderBy('lastUsed', 'desc')); const querySnapshot = await getDocs(q); return querySnapshot.docs.map(doc => this.docToRunner(doc.data(), doc.id)); } static async createRunner(data) { const userId = AuthService.userId; if (!userId) { throw new Error('User not authenticated'); } const deviceId = generateDeviceId(); const deviceName = getDeviceDisplayName(); // Generate or load encryption code let encryptionCode; const storedAuth = await loadAuth(); if (storedAuth?.encryptionCode) { encryptionCode = storedAuth.encryptionCode; } else { // Generate new random encryption code encryptionCode = EncryptionService.generateRandomSecret(); // Save to storage const updatedAuth = { ...storedAuth, encryptionCode }; await saveAuth(updatedAuth); } // Create verification string const encryptionVerification = EncryptionService.createVerificationString(encryptionCode); // Create runner via API with encryption verification const response = await ApiService.createRunner({ name: data.name, directory: data.directory, machineId: deviceId, machineName: deviceName, encryptionVerification }); const runnerId = response.id; return { id: runnerId, name: data.name, directory: data.directory, userId, runnerType: data.runnerType, createdAt: new Date(), lastUsed: new Date(), machineId: deviceId, machineName: deviceName, }; } static async deleteRunner(runnerId) { // Call the API to delete the runner await ApiService.deleteRunner(runnerId); } static async clearPendingCommand(runnerId) { await ApiService.updateRunner(runnerId, { clearPendingCommand: true }); } static async updateRunnerAfterCommand(runnerId, result) { await ApiService.updateRunner(runnerId, { updateLastUsed: true, lastMessage: result ?? '' }); } static async createMessage(runnerId, data) { const userId = AuthService.userId; if (!userId) { throw new Error('User not authenticated'); } if (!runnerId) { throw new Error('Runner ID is required to create a message'); } await ApiService.createRunnerMessage(runnerId, data); } static listenToRunner(runnerId, callback) { const runnerDoc = doc(db, this.RUNNERS_COLLECTION, runnerId); return onSnapshot(runnerDoc, (doc) => { if (doc.exists()) { const runner = this.docToRunner(doc.data(), doc.id); callback(runner); } else { callback(null); } }); } static docToRunner(data, id) { return { id, name: data.name || '', directory: data.directory || '', userId: data.userId || '', runnerType: this.parseRunnerType(data.runnerType), createdAt: data.createdAt?.toDate() || null, lastUsed: data.lastUsed?.toDate() || null, lastMessage: data.lastMessage || undefined, machineName: data.machineName || undefined, machineId: data.machineId || undefined, pendingCommand: data.pendingCommand || undefined, }; } static parseRunnerType(type) { switch (type) { case 'codex': return RunnerType.CODEX; case 'gemini': return RunnerType.GEMINI; case 'claude': default: return RunnerType.CLAUDE; } } } //# sourceMappingURL=runner.js.map