@dailyautomations/terminal-logger
Version:
Terminal command logger with Supabase sync for swarm prompts
164 lines (163 loc) • 6.88 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 __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.config = exports.TerminalLogger = void 0;
const capture_1 = require("./capture");
const storage_1 = require("./storage");
const supabase_sync_1 = require("./supabase-sync");
const config_1 = require("./config");
const logger_1 = require("./logger");
class TerminalLogger {
capture;
storage;
supabaseSync;
isRunning = false;
constructor() {
this.storage = new storage_1.LocalStorage(config_1.config.logFilePath);
this.supabaseSync = new supabase_sync_1.SupabaseSync(config_1.config.supabaseUrl, config_1.config.supabaseAnonKey);
// Don't initialize capture here - wait until we have the session ID
this.capture = null; // Will be initialized in start()
}
async start() {
try {
(0, config_1.validateConfig)();
logger_1.logger.info('Starting Terminal Logger...');
// Initialize components
await this.storage.initialize();
await this.supabaseSync.initialize();
// Get the session info
const sessionInfo = await this.storage.getSessionInfo();
// Sync the current session to Supabase first
if (config_1.config.supabaseUrl && config_1.config.supabaseAnonKey) {
await this.supabaseSync.syncSession(sessionInfo);
}
// Now create capture with the correct session ID
this.capture = new capture_1.CommandCapture(config_1.config.shellHistoryFile, sessionInfo.id);
// Start command capture
await this.capture.startWatching(async (command) => {
await this.handleNewCommand(command);
});
// Start periodic sync if configured
if (config_1.config.supabaseUrl && config_1.config.supabaseAnonKey) {
this.supabaseSync.startPeriodicSync(config_1.config.syncIntervalMinutes, async () => {
const lastSync = this.supabaseSync.getSyncStatus().lastSyncTime;
return this.storage.getUnsyncedCommands(lastSync);
});
}
this.isRunning = true;
logger_1.logger.info('Terminal Logger started successfully');
// Handle graceful shutdown
this.setupShutdownHandlers();
}
catch (error) {
logger_1.logger.error('Failed to start Terminal Logger', error);
throw error;
}
}
async stop() {
logger_1.logger.info('Stopping Terminal Logger...');
if (this.capture) {
this.capture.stopWatching();
}
this.supabaseSync.stopPeriodicSync();
// Final sync before shutdown
if (config_1.config.supabaseUrl && config_1.config.supabaseAnonKey) {
try {
const lastSync = this.supabaseSync.getSyncStatus().lastSyncTime;
const unsyncedCommands = await this.storage.getUnsyncedCommands(lastSync);
if (unsyncedCommands.length > 0) {
await this.supabaseSync.syncCommands(unsyncedCommands);
}
// Sync session end time
const sessionInfo = await this.storage.getSessionInfo();
sessionInfo.endTime = new Date();
await this.supabaseSync.syncSession(sessionInfo);
}
catch (error) {
logger_1.logger.error('Error during final sync', error);
}
}
this.isRunning = false;
logger_1.logger.info('Terminal Logger stopped');
}
async handleNewCommand(command) {
try {
// Store locally
await this.storage.addCommand(command);
// Log special commands
if (command.metadata?.isSwarmPrompt) {
logger_1.logger.info('Captured swarm command', {
command: command.command,
swarmId: command.metadata.swarmId,
agentType: command.metadata.agentType
});
}
// Real-time sync if enabled
if (config_1.config.enableRealTimeSync && config_1.config.supabaseUrl && config_1.config.supabaseAnonKey) {
await this.supabaseSync.syncCommands([command]);
}
}
catch (error) {
logger_1.logger.error('Error handling new command', error);
}
}
setupShutdownHandlers() {
const shutdown = async () => {
if (this.isRunning) {
await this.stop();
process.exit(0);
}
};
process.on('SIGINT', shutdown);
process.on('SIGTERM', shutdown);
}
// Public API methods
async getRecentCommands(limit = 100) {
return this.storage.getCommands(limit);
}
async searchCommands(searchTerm) {
if (config_1.config.supabaseUrl && config_1.config.supabaseAnonKey) {
return this.supabaseSync.queryCommands({ searchTerm });
}
// Local search fallback
const allCommands = await this.storage.getCommands();
return allCommands.filter(cmd => cmd.command.toLowerCase().includes(searchTerm.toLowerCase()));
}
async getSwarmCommands() {
if (config_1.config.supabaseUrl && config_1.config.supabaseAnonKey) {
return this.supabaseSync.queryCommands({ isSwarmPrompt: true });
}
// Local filter fallback
const allCommands = await this.storage.getCommands();
return allCommands.filter(cmd => cmd.metadata?.isSwarmPrompt);
}
getSyncStatus() {
return this.supabaseSync.getSyncStatus();
}
}
exports.TerminalLogger = TerminalLogger;
// Export for library usage
__exportStar(require("./types"), exports);
var config_2 = require("./config");
Object.defineProperty(exports, "config", { enumerable: true, get: function () { return config_2.config; } });
// CLI execution
if (require.main === module) {
const terminalLogger = new TerminalLogger();
terminalLogger.start().catch(error => {
logger_1.logger.error('Fatal error', error);
process.exit(1);
});
}
;