// ── Global 401 Handler ── (function() { var _origFetch = window.fetch; window.fetch = function(url, opts) { return _origFetch.apply(this, arguments).then(function(resp) { if (resp.status === 401 && typeof url === 'string' && !url.includes('/api/auth/')) { if (typeof currentPage !== 'undefined' && currentPage !== 'login') { navigateTo('login'); } } return resp; }); }; })(); // ── Internal Fetch Helpers ── var _jsonHeaders = { 'Content-Type': 'application/json' }; /** GET → JSON (returns fallback on error, default: throws) */ async function _get(url, fallback) { var resp = await fetch(url); if (!resp.ok) { if (arguments.length >= 2) return fallback; throw new Error('Fehler beim Laden'); } return resp.json(); } /** POST/PUT/DELETE with JSON body → JSON (throws on error) */ async function _send(method, url, body, errMsg) { var opts = { method: method }; if (body !== undefined) { opts.headers = _jsonHeaders; opts.body = JSON.stringify(body); } var resp = await fetch(url, opts); if (!resp.ok) { var err = await resp.json().catch(function() { return {}; }); throw new Error(err.error || errMsg || 'Anfrage fehlgeschlagen'); } return resp.json(); } /** POST with JSON body → JSON */ function _post(url, body, errMsg) { return _send('POST', url, body, errMsg); } /** PUT with JSON body → JSON */ function _put(url, body, errMsg) { return _send('PUT', url, body, errMsg); } /** DELETE → JSON */ function _del(url, errMsg) { return _send('DELETE', url, undefined, errMsg); } // ── Auth API ── function apiLogin(u, p) { return _post('/api/auth/login', { username: u, password: p }, 'Login fehlgeschlagen'); } function apiLogout() { return fetch('/api/auth/logout', { method: 'POST' }); } function apiMe() { return _get('/api/auth/me', null); } // ── Chat API ── function apiChat(content, sessionId, signal, planMode) { var payload = { content: content, sessionId: sessionId }; if (planMode) payload.planMode = true; return fetch('/api/chat', { method: 'POST', headers: _jsonHeaders, body: JSON.stringify(payload), signal: signal }); } function apiChatChoice(sessionId, choiceToolCallId, choiceResult, signal, planMode) { var payload = { sessionId: sessionId, choiceToolCallId: choiceToolCallId, choiceResult: choiceResult }; if (planMode) payload.planMode = true; return fetch('/api/chat', { method: 'POST', headers: _jsonHeaders, body: JSON.stringify(payload), signal: signal }); } function apiStopChat(sessionId) { return _post('/api/chat/stop', { sessionId: sessionId }); } // ── Agent API ── function apiGetAgents() { return _get('/api/agents'); } function apiGetAvailableAgents() { return _get('/api/agents/available', []); } function apiGetAgent(id) { return _get('/api/agents/' + id, null); } function apiCreateAgent(data) { return _post('/api/agents', data); } function apiUpdateAgent(id, data) { return _put('/api/agents/' + id, data); } function apiDeleteAgent(id) { return fetch('/api/agents/' + id, { method: 'DELETE' }); } // ── Session API ── function apiGetSessions() { return _get('/api/sessions'); } function apiGetSession(id) { return _get('/api/sessions/' + id, null); } function apiCreateSession(data) { return _post('/api/sessions', data || {}); } function apiUpdateSession(id, data) { return _put('/api/sessions/' + id, data); } function apiDeleteSession(id) { return fetch('/api/sessions/' + id, { method: 'DELETE' }); } function apiExecCommand(sessionId, command, mode) { mode = mode || 'background'; var resp = fetch('/api/sessions/' + sessionId + '/exec', { method: 'POST', headers: _jsonHeaders, body: JSON.stringify({ command: command, mode: mode }) }); return mode === 'foreground' ? resp.then(function(r) { return r.json(); }) : resp; } function apiGetSystemPrompt(sessionId) { return fetch('/api/sessions/' + sessionId + '/system-prompt').then(function(r) { if (!r.ok) throw new Error('System-Prompt konnte nicht geladen werden'); return r.text(); }); } function apiGetSystemPromptBlocks(sessionId, planMode) { var url = '/api/sessions/' + sessionId + '/system-prompt-blocks' + (planMode ? '?planMode=true' : ''); return _get(url); } function apiIsStreaming(sessionId) { return _get('/api/sessions/' + sessionId + '/streaming'); } function apiGitStatus(sessionId) { return _get('/api/sessions/' + sessionId + '/git-status', null); } // ── History API ── function apiHistory(sessionId, beforeSortKey, includeDeleted) { var url = '/api/history?sessionId=' + sessionId; if (beforeSortKey) url += '&beforeSortKey=' + beforeSortKey; if (includeDeleted) url += '&includeDeleted=true'; return _get(url); } function apiHistoryPoll(sessionId, afterSortKey, includeDeleted) { var url = '/api/history/poll?sessionId=' + sessionId + '&afterSortKey=' + afterSortKey; if (includeDeleted) url += '&includeDeleted=true'; return _get(url); } // ── Archive API ── function apiArchive(sessionId) { return fetch('/api/archive?sessionId=' + sessionId, { method: 'POST' }).then(function(r) { return r.status === 204 ? null : r.json(); }); } function apiListArchives(sessionId) { return _get('/api/archives?sessionId=' + sessionId); } function apiGetArchive(id) { return _get('/api/archive/' + id); } // ── Chain / Message API ── function apiGetChain(id) { return _get('/api/chains/' + id, null); } function apiToggleMessageMark(id) { return _put('/api/messages/' + id + '/mark'); } function apiToggleMessageDelete(id) { return _put('/api/messages/' + id + '/delete'); } // ── Skills API ── function apiGetSkills() { return _get('/api/skills'); } function apiGetAgentSkills(agentId) { return _get('/api/agents/' + agentId + '/skills'); } function apiSetAgentSkills(agentId, skills) { return _put('/api/agents/' + agentId + '/skills', { skills: skills }); } function apiAddAgentSkill(agentId, slug) { return fetch('/api/agents/' + agentId + '/skills/' + slug, { method: 'POST' }); } function apiRemoveAgentSkill(agentId, slug) { return fetch('/api/agents/' + agentId + '/skills/' + slug, { method: 'DELETE' }); } // ── Profile API ── function apiGetProfile() { return _get('/api/profile', null); } function apiUpdateProfile(data) { return _put('/api/profile', data, 'Fehler beim Speichern'); } function apiChangePassword(cur, pw) { return _put('/api/profile/password', { currentPassword: cur, newPassword: pw }, 'Fehler beim Ändern'); } // ── Telegram Bot API ── function apiGetTelegramBots() { return _get('/api/telegram/bots'); } function apiGetTelegramBot(id) { return _get('/api/telegram/bots/' + id, null); } function apiGetAvailableTelegramBots() { return _get('/api/telegram/bots/available'); } function apiCreateTelegramBot(name, token) { return _post('/api/telegram/bots', { name: name, botToken: token }, 'Bot erstellen fehlgeschlagen'); } function apiUpdateTelegramBot(id, name, token, isPublic) { return _put('/api/telegram/bots/' + id, { name: name, botToken: token, isPublic: isPublic }, 'Bot speichern fehlgeschlagen'); } function apiDeleteTelegramBot(id) { return _del('/api/telegram/bots/' + id, 'Bot löschen fehlgeschlagen'); } function apiTelegramBotRegisterWebhook(id, baseUrl) { return _post('/api/telegram/bots/' + id + '/register-webhook', { baseUrl: baseUrl }, 'Webhook-Registrierung fehlgeschlagen'); } function apiTelegramBotWebhookInfo(id) { return _get('/api/telegram/bots/' + id + '/webhook-info'); } function apiTelegramBotDeleteWebhook(id) { return _del('/api/telegram/bots/' + id + '/webhook', 'Webhook-Löschung fehlgeschlagen'); } // ── Session Telegram Config ── function apiSessionTelegramGet(sessionId) { return _get('/api/sessions/' + sessionId + '/telegram', { configured: false }); } function apiSessionTelegramSave(sessionId, botId, chatId) { return _put('/api/sessions/' + sessionId + '/telegram', { telegramBotId: botId, chatId: chatId }, 'Telegram-Config speichern fehlgeschlagen'); } // ── Settings API ── function apiGetSettings() { return _get('/api/settings', {}); } function apiSaveSettings(settings) { return _put('/api/settings', settings); } // ── Cronjob API ── function apiGetCronjobs() { return _get('/api/cronjobs'); } function apiGetCronjob(id) { return _get('/api/cronjobs/' + id, null); } function apiCreateCronjob(data) { return _post('/api/cronjobs', data, 'Cronjob erstellen fehlgeschlagen'); } function apiUpdateCronjob(id, data) { return _put('/api/cronjobs/' + id, data, 'Cronjob speichern fehlgeschlagen'); } function apiDeleteCronjob(id) { return fetch('/api/cronjobs/' + id, { method: 'DELETE' }); } function apiToggleCronjob(id) { return _post('/api/cronjobs/' + id + '/toggle'); } function apiRunCronjob(id) { return _post('/api/cronjobs/' + id + '/run'); } // ── Shared Message API ── function apiListShares() { return _get('/api/shared'); } function apiShareMessage(id, includeContext) { return _post('/api/messages/' + id + '/share', { includeContext: includeContext || false }, 'Teilen fehlgeschlagen'); } function apiGetShared(token) { return _get('/api/shared/' + token); } function apiDeleteShare(token) { return fetch('/api/shared/' + token, { method: 'DELETE' }); } // ── Admin User API ── function apiAdminGetUsers() { return _get('/api/admin/users'); } function apiAdminCreateUser(data) { return _post('/api/admin/users', data, 'Fehler beim Erstellen'); } function apiAdminUpdateUser(id, data) { return _put('/api/admin/users/' + id, data, 'Fehler beim Aktualisieren'); } function apiAdminResetPassword(id, pw) { return _put('/api/admin/users/' + id + '/password', { password: pw }, 'Fehler beim Zurücksetzen'); } function apiAdminDeleteUser(id) { return _del('/api/admin/users/' + id, 'Fehler beim Löschen'); } function apiAdminImpersonate(id) { return _post('/api/admin/users/' + id + '/impersonate', undefined, 'Fehler beim Anmelden'); } function apiAdminGetLoginLink(id) { return _post('/api/admin/users/' + id + '/login-link', undefined, 'Fehler beim Erstellen des Login-Links'); } // ── Server Settings API (Admin) ── function apiGetServerSettings() { return _get('/api/admin/server-settings'); } function apiSaveServerSettings(data) { return _put('/api/admin/server-settings', data, 'Fehler beim Speichern'); } // ── API Keys (Admin) ── function apiGetApiKeys() { return _get('/api/admin/api-keys'); } function apiCreateApiKey(data) { return _post('/api/admin/api-keys', data, 'Fehler beim Erstellen'); } function apiUpdateApiKey(id, data) { return _put('/api/admin/api-keys/' + id, data, 'Fehler beim Aktualisieren'); } function apiToggleApiKeyPublic(id) { return _put('/api/admin/api-keys/' + id + '/public', undefined, 'Fehler beim Umschalten'); } // ── User Key Selection API ── function apiGetAvailableKeys() { return _get('/api/api-keys/available', []); } function apiSelectApiKey(keyId) { return _put('/api/api-keys/select/' + keyId, undefined, 'Fehler beim Auswählen'); } function apiGetSelectedKey() { return _get('/api/api-keys/selected', null); } function apiDeleteApiKey(id) { return _del('/api/admin/api-keys/' + id, 'Fehler beim Löschen'); } function apiCheckApiKey(id) { return _post('/api/admin/api-keys/' + id + '/check', undefined, 'Fehler beim Prüfen'); } function apiCheckAllApiKeys() { return _post('/api/admin/api-keys/check-all', undefined, 'Fehler beim Prüfen'); } // ── Key Scanner API (Admin) ── function apiTriggerScan(mode) { return _post('/api/admin/api-keys/scan?mode=' + (mode || 'full'), undefined, 'Fehler beim Starten des Scans'); } function apiScanStatus() { return _get('/api/admin/api-keys/scan/status', {}); } function apiGetScannedKeys(type) { return _get('/api/admin/api-keys/scanned' + (type ? '?type=' + encodeURIComponent(type) : ''), []); } function apiGetScannedKeysSummary() { return _get('/api/admin/api-keys/scanned/summary', []); } function apiRecheckAllScannedKeys() { return _post('/api/admin/api-keys/scanned/recheck-all', undefined, 'Fehler beim Prüfen'); } function apiRecheckScannedKey(id) { return _post('/api/admin/api-keys/scanned/' + id + '/recheck', undefined, 'Fehler beim Prüfen'); } function apiAdoptScannedKey(id) { return _post('/api/admin/api-keys/scanned/' + id + '/adopt', undefined, 'Fehler beim Übernehmen'); } function apiDeleteScannedKey(id) { return _del('/api/admin/api-keys/scanned/' + id, 'Fehler beim Löschen'); } function apiEventScannerStatus() { return _get('/api/admin/api-keys/event-scanner/status', {}); } function apiEventScannerLog() { return _get('/api/admin/api-keys/event-scanner/log', { entries: [] }); } // ── Krea Image API ── function apiKreaStatus() { return _get('/api/images/status', { configured: false }); } function apiKreaGenerate(prompt, model, width, height) { return _post('/api/images/generate', { prompt: prompt, model: model || 'flux', width: width || 512, height: height || 512, batchSize: 1 }, 'Bildgenerierung fehlgeschlagen'); } // ── OpenClaw Import API ── function apiGetOpenclawSessions() { return _get('/api/openclaw/sessions'); } function apiImportOpenclawSession(openclawSessionId, sessionId) { return _post('/api/openclaw/import', { openclawSessionId: openclawSessionId, sessionId: sessionId }, 'Import fehlgeschlagen'); } // ── Remote API ── function apiGetRemoteConnections() { return _get('/api/remote/connections', []); } function apiAssignRemote(connectionId, sessionId) { return _post('/api/remote/assign', { connectionId: connectionId, sessionId: sessionId }); } function apiUnassignRemote(connectionId) { return _post('/api/remote/unassign', { connectionId: connectionId }); } // ── Backup API ── async function apiBackupDb() { var resp = await fetch('/api/backup', { method: 'POST', credentials: 'include' }); if (!resp.ok) throw new Error('Backup fehlgeschlagen'); var blob = await resp.blob(); var cd = resp.headers.get('content-disposition') || ''; var filename = cd.match(/filename\*=UTF-8''(.+?)(?:;|$)/i)?.[1] || cd.match(/filename="?([^";]+)"?/)?.[1] || 'gott-backup.tar.gz'; var url = URL.createObjectURL(blob); var a = document.createElement('a'); a.href = url; a.download = filename; document.body.appendChild(a); a.click(); a.remove(); URL.revokeObjectURL(url); }