- Wissensdatenbank Struktur - Projekt-Übersichten - Session-Management Templates - Dashboard Integration - README.md mit Recovery Guide - System Snapshot Generator Generiert: 2026-06-19
161 lines
4.5 KiB
TypeScript
161 lines
4.5 KiB
TypeScript
/**
|
||
* 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;
|
||
}
|
||
}
|