// ─── Supervisor View ───
import { api } from '../api.js';
export class SupervisorView {
constructor(container, setStatus) {
this.container = container;
this.setStatus = setStatus;
this.currentSubTab = 'analysis';
this.profiles = [];
this.signals = [];
this.selectedSignal = null;
}
async render() {
this.container.innerHTML = `
`;
const subtabs = this.container.querySelectorAll('[data-subtab]');
subtabs.forEach(tab => {
tab.addEventListener('click', () => {
subtabs.forEach(t => t.classList.remove('active'));
tab.classList.add('active');
this.currentSubTab = tab.getAttribute('data-subtab');
this.renderSubTab();
});
});
await this.loadProfiles();
await this.renderSubTab();
}
async loadProfiles() {
try {
const data = await api.get('/api/modules/supervisor/profiles');
if (Array.isArray(data)) {
this.profiles = data;
}
} catch (e) {
console.warn('Konnte Supervisor-Profile nicht laden:', e);
}
}
async renderSubTab() {
const sub = document.getElementById('sup-subcontent');
if (!sub) return;
if (this.currentSubTab === 'analysis') {
sub.innerHTML = `
Wählen Sie ein Profil, geben Sie eine Frage ein und klicken Sie auf 'Fragen'.
`;
document.getElementById('sup-ask-btn').addEventListener('click', () => this.ask());
document.getElementById('sup-question-input').addEventListener('keydown', (e) => {
if (e.key === 'Enter' && (e.ctrlKey || e.metaKey)) {
e.preventDefault();
this.ask();
}
});
} else if (this.currentSubTab === 'dossier') {
sub.innerHTML = `
| Zeit |
Symbol |
Modul |
Entscheidung |
| Signale laden … |
Signal in der linken Tabelle auswählen.
`;
document.getElementById('sup-load-signals-btn').addEventListener('click', () => this.loadSignals());
await this.loadSignals();
} else if (this.currentSubTab === 'reports') {
sub.innerHTML = `
| Erstellt |
Profil |
Modell |
Frage |
Tools |
Tokens |
| Lade Berichte … |
`;
document.getElementById('sup-load-reports-btn').addEventListener('click', () => this.loadReports());
await this.loadReports();
} else if (this.currentSubTab === 'info') {
sub.innerHTML = `
Supervisor Modul-Hinweise
Lade Modul-Informationen …
`;
await this.loadInfo();
}
}
async ask() {
const qEl = document.getElementById('sup-question-input');
const question = qEl?.value?.trim();
if (!question) {
alert('Bitte eine Frage eingeben.');
return;
}
const pEl = document.getElementById('sup-profile-select');
const profile = pEl?.value;
const btn = document.getElementById('sup-ask-btn');
const ansEl = document.getElementById('sup-answer-container');
const statusEl = document.getElementById('sup-ask-status');
btn.disabled = true;
btn.textContent = '⏳ Analysiere …';
if (statusEl) statusEl.textContent = 'Agent denkt nach …';
ansEl.textContent = 'Agent führt Tool-Aufrufe und Analysen durch … Bitte warten.';
try {
const res = await api.post('/api/modules/supervisor/ask', { question, profile });
if (res && res.success) {
let output = res.answer || '(Keine Antwort erhalten)';
if (res.toolCalls && res.toolCalls.length > 0) {
output += '\n\n── Ausgeführte Tool-Calls ──\n' +
res.toolCalls.map(tc => `• ${tc.tool}: ${JSON.stringify(tc.arguments)}`).join('\n');
}
ansEl.textContent = output;
if (statusEl) statusEl.textContent = `Fertig (${res.toolCallCount || 0} Tools genutzt).`;
} else {
ansEl.textContent = `Fehler: ${res?.message || 'Unbekannter Fehler'}`;
}
} catch (e) {
ansEl.textContent = `Fehler bei der Abfrage: ${e.message}`;
} finally {
btn.disabled = false;
btn.textContent = '⚡ Fragen';
}
}
async loadSignals() {
this.setStatus('Lade Signale …');
try {
const signals = await api.get('/api/modules/supervisor/signals?limit=100');
this.signals = Array.isArray(signals) ? signals : [];
const tbody = document.getElementById('sup-signals-tbody');
if (!tbody) return;
if (this.signals.length === 0) {
tbody.innerHTML = `| Keine Signale gefunden. |
`;
} else {
tbody.innerHTML = this.signals.map((s, idx) => `
| ${s.firstSeen ? s.firstSeen.substring(5, 16) : '–'} |
${s.symbol || '–'} |
${s.module || '–'} |
${s.lastDecision || '–'} |
`).join('');
tbody.querySelectorAll('tr').forEach(tr => {
tr.addEventListener('click', () => {
const idx = parseInt(tr.getAttribute('data-idx'), 10);
this.selectSignal(this.signals[idx]);
});
});
}
this.setStatus(`Signale geladen (${this.signals.length}).`);
} catch (e) {
this.setStatus(`Fehler: ${e.message}`);
}
}
async selectSignal(s) {
this.selectedSignal = s;
const headerEl = document.getElementById('sup-dossier-header');
const bodyEl = document.getElementById('sup-dossier-body');
if (!bodyEl) return;
if (headerEl) headerEl.textContent = `Dossier: ${s.symbol} (${s.signalId})`;
bodyEl.textContent = 'Lade Dossier …';
try {
const data = await api.get(`/api/modules/supervisor/dossier/${encodeURIComponent(s.signalId)}`);
if (data && data.markdown) {
bodyEl.textContent = data.markdown;
} else {
bodyEl.textContent = 'Kein Dossier für dieses Signal verfügbar.';
}
} catch (e) {
bodyEl.textContent = `Fehler beim Laden des Dossiers: ${e.message}`;
}
}
async loadReports() {
this.setStatus('Lade Berichte …');
try {
const reports = await api.get('/api/modules/supervisor/reports?limit=100');
const tbody = document.getElementById('sup-reports-tbody');
if (!tbody) return;
if (!Array.isArray(reports) || reports.length === 0) {
tbody.innerHTML = `| Keine Berichte vorhanden. |
`;
} else {
tbody.innerHTML = reports.map(r => `
| ${r.createdAt} |
${r.profile} |
${r.model} |
${r.question} |
${r.toolCallCount} |
${r.tokens} |
`).join('');
}
this.setStatus(`Berichte geladen (${reports ? reports.length : 0}).`);
} catch (e) {
this.setStatus(`Fehler: ${e.message}`);
}
}
async loadInfo() {
try {
const info = await api.get('/api/modules/supervisor/info');
const el = document.getElementById('sup-info-content');
if (!el || !info) return;
el.innerHTML = `
OpenRouter API-Key: ${info.openRouterKeyConfigured ? '✅ Konfiguriert' : '⚠️ Nicht gesetzt (in settings.json oder OPENROUTER_API_KEY hinterlegen)'}
Zeitzone: ${info.timeZone || '–'}
Beschreibung: ${info.description || '–'}
`;
} catch (e) {
console.error(e);
}
}
}