/** * Telegram Auto-Session-Save * * Diese Funktion wird vom Agenten (OWL) bei jedem Telegram-Turn aufgerufen. * Sie zählt die Nachrichten und speichert bei Bedarf eine Zusammenfassung * im Obsidian Vault. * * Zusätzlich wird eine Session-Zusammenfassung als Kontext für den nächsten * Turn geladen, um Token zu sparen. */ import fs from 'fs'; import path from 'path'; const VAULT_PATH = 'E:\\OpenCode_Projekte\\obsidianVault'; const SESSIONS_DAILY = path.join(VAULT_PATH, '04-Sessions', 'Daily'); const TRACKER_PATH = path.join(VAULT_PATH, '04-Sessions', 'telegram-session-tracker.json'); interface SessionTracker { session_id: string; message_count: number; last_save_at: string | null; auto_save_interval: number; model: string; provider: string; total_tokens_estimated: number; created_at: string; } function loadTracker(): SessionTracker { try { if (fs.existsSync(TRACKER_PATH)) { return JSON.parse(fs.readFileSync(TRACKER_PATH, 'utf-8')); } } catch { /* ignore */ } return { session_id: 'telegram-floki', message_count: 0, last_save_at: null, auto_save_interval: 10, model: 'openrouter/owl-alpha', provider: 'openrouter', total_tokens_estimated: 0, created_at: new Date().toISOString(), }; } function saveTracker(tracker: SessionTracker): void { fs.writeFileSync(TRACKER_PATH, JSON.stringify(tracker, null, 2), 'utf-8'); } /** * Prüft ob ein Auto-Save nötig ist und gibt ggf. die Zusammenfassung zurück * die als Kontext für den nächsten Turn verwendet werden kann. */ export function checkAndSaveSession(userMessage: string, assistantReply: string): { shouldSave: boolean; summary?: string; tokensSaved: number; } { const tracker = loadTracker(); tracker.message_count += 1; // 1 Turn = User + Assistant // Tokens grob schätzen (4 chars pro Token) const turnTokens = Math.ceil((userMessage.length + assistantReply.length) / 4); tracker.total_tokens_estimated += turnTokens; const shouldSave = tracker.message_count % tracker.auto_save_interval === 0; if (shouldSave) { // Zusammenfassung generieren const now = new Date(); const dateStr = now.toISOString().split('T')[0]; const timeStr = now.toTimeString().split(' ')[0].substring(0, 5).replace(':', '-'); const summary = `Telegram-Session (${tracker.session_id}): ${tracker.message_count} Nachrichten, ~${tracker.total_tokens_estimated} Tokens. Letzte Nachricht: "${userMessage.substring(0, 60)}..."`; const markdown = `--- session_id: ${tracker.session_id} date: ${dateStr} time: ${timeStr} message_count: ${tracker.message_count} model: ${tracker.model} provider: ${tracker.provider} tokens_estimated: ${tracker.total_tokens_estimated} tags: [session, telegram, owl] --- # 📱 Telegram Session: ${dateStr} ## 📊 Metriken | Metrik | Wert | |--------|------| | **Nachrichten** | ${tracker.message_count} | | **Geschätzte Tokens** | ~${tracker.total_tokens_estimated} | | **Modell** | \`${tracker.model}\` | | **Provider** | ${tracker.provider} | ## 📝 Zusammenfassung ${summary} ## 🏷️ Tags \`#session\` \`#telegram\` \`#owl\` --- *Auto-generiert vom OWL Agent – Obsidian Sync* `; // Vault-Ordner sicherstellen fs.mkdirSync(SESSIONS_DAILY, { recursive: true }); // Datei schreiben const filename = `${dateStr}_${timeStr}_telegram.md`; const filePath = path.join(SESSIONS_DAILY, filename); fs.writeFileSync(filePath, markdown, 'utf-8'); // Tracker aktualisieren tracker.last_save_at = now.toISOString(); saveTracker(tracker); return { shouldSave: true, summary, tokensSaved: turnTokens, // Diese Tokens werden "gespart" da Zusammenfassung kleiner ist }; } saveTracker(tracker); return { shouldSave: false, tokensSaved: 0 }; } /** * Lädt die letzte Session-Zusammenfassung als Kontext * um Token beim nächsten Request zu sparen */ export function loadLastSessionContext(): string | null { try { const files = fs.readdirSync(SESSIONS_DAILY) .filter(f => f.endsWith('.md') && f.includes('telegram')) .sort() .reverse(); if (files.length === 0) return null; const lastFile = path.join(SESSIONS_DAILY, files[0]); const content = fs.readFileSync(lastFile, 'utf-8'); // Nur den Zusammenfassungs-Teil zurückgeben const summaryMatch = content.match(/## 📝 Zusammenfassung\n\n([\s\S]*?)\n\n## /); if (summaryMatch) { return `Vorherige Session-Zusammenfassung:\n${summaryMatch[1]}\n\n~Tokens durch Kompression gespart.`; } return null; } catch { return null; } }