9.1.1
release-tag / release-image (push) Failing after 9m47s

This commit is contained in:
2026-08-29 19:51:30 +02:00
parent 35e1c4c3f5
commit f00e3cd3d4
5 changed files with 412 additions and 7 deletions
+7
View File
@@ -971,3 +971,10 @@ Anschließend erkennt `GET /api/docker/skill-services` auch die gestoppten, gela
v9.1 ergänzt das Skill Mesh um dedizierte Remote-Integrationen für Philips Hue, UniFi Network, UniFi Protect, Proxmox VE, Dockge/Compose, Netzwerkdiagnose/Wake-on-LAN und ntfy. Außerdem unterstützt das Skill-Protokoll jetzt `runtime.env_from`, sodass Secrets aus Worker-ENVs nur explizit an den jeweiligen Skill-Prozess weitergegeben werden.
Details, ENV-Beispiele und Workflow-Ideen stehen in [`HOME-CONTROL-SKILLS.md`](HOME-CONTROL-SKILLS.md).
## v9.1.1 – Clean UI State Render Fix
- Fixes a Clean-UI JavaScript scope regression where `renderCleanHome()` referenced the `renderState()`-local `sttLabel`. The resulting `ReferenceError` stopped the render chain before groceries, meals, recipes and later modules were refreshed.
- Voice status labels are now derived through shared helpers (`sttStatusLabel` / `ttsStatusLabel`).
- Dashboard module renderers are isolated with `safeRender`, so an optional card can no longer prevent unrelated modules such as the grocery list from updating.
- Adds a regression test for the exact failure.
+30
View File
@@ -0,0 +1,30 @@
package main
import (
"os"
"strings"
"testing"
)
func TestCleanHomeVoiceLabelDoesNotBreakModuleRendering(t *testing.T) {
b, err := os.ReadFile("../../internal/ui/static/app.js")
if err != nil {
t.Fatal(err)
}
s := string(b)
start := strings.Index(s, "function renderCleanHome()")
end := strings.Index(s[start:], "function renderBrief()")
if start < 0 || end < 0 {
t.Fatal("renderCleanHome/renderBrief not found")
}
body := s[start : start+end]
if strings.Contains(body, "sttLabel") {
t.Fatal("renderCleanHome references renderState-local sttLabel and can abort downstream rendering")
}
if !strings.Contains(body, "sttStatusLabel(voice)") {
t.Fatal("renderCleanHome must derive its own STT label")
}
if !strings.Contains(s, "safeRender('groceries',renderGroceries)") {
t.Fatal("grocery renderer must be isolated from failures in other dashboard modules")
}
}
File diff suppressed because one or more lines are too long
+46 -5
View File
@@ -48,7 +48,7 @@
"source": "mealplan:auto:nudeln|gramm",
"aiManaged": true,
"createdAt": "2026-08-28T11:11:06+02:00",
"updatedAt": "2026-08-29T17:02:11+02:00"
"updatedAt": "2026-08-29T19:40:32+02:00"
},
{
"id": "grocery_ai_dl0gl2ul9jmg",
@@ -60,7 +60,7 @@
"source": "mealplan:auto:thomatensauce|ml",
"aiManaged": true,
"createdAt": "2026-08-28T11:11:06+02:00",
"updatedAt": "2026-08-29T17:02:11+02:00"
"updatedAt": "2026-08-29T19:40:32+02:00"
}
],
"recipes": [
@@ -178,15 +178,14 @@
{
"id": "card_ai_dl0dbme6x2a0",
"title": "Hausflur putzen",
"notes": "Offene Aufgabe ohne Fälligkeit; zunächst in der Inbox sammeln und bei Bedarf in den nächsten Arbeitsschritt verschieben.",
"column": "inbox",
"priority": "normal",
"taskId": "task_tool_dl0dbme5o3ls",
"source": "task-sync",
"aiManaged": true,
"confidence": 0.72,
"confidence": 1,
"createdAt": "2026-08-28T08:37:42+02:00",
"updatedAt": "2026-08-29T16:12:32+02:00"
"updatedAt": "2026-08-29T18:57:22+02:00"
}
],
"documents": [],
@@ -394,9 +393,51 @@
"role": "assistant",
"content": "Essensplan: 7 Abendessen geplant.\n• Freitag, 28.08. · Nudeln mit Thomatensauce\n• Samstag, 29.08. · Nudeln mit Thomatensauce\n• Sonntag, 30.08. · Nudeln mit Thomatensauce\n• Montag, 31.08. · Nudeln mit Thomatensauce\n• Dienstag, 01.09. · Nudeln mit Thomatensauce\n• Mittwoch, 02.09. · Nudeln mit Thomatensauce\n• Donnerstag, 03.09. · Nudeln mit Thomatensauce",
"createdAt": "2026-08-28T11:11:25+02:00"
},
{
"id": "chat_dl1l0y2k7420",
"role": "user",
"content": "Setze Spaghetti auf die Einkaufsliste",
"createdAt": "2026-08-29T18:52:34+02:00"
},
{
"id": "chat_dl1l1vh069nc",
"role": "assistant",
"content": "Der lokale JARVIS-Agent ist momentan nicht vollständig verfügbar. Es wurde keine unbestätigte Home-Änderung ausgeführt.",
"createdAt": "2026-08-29T18:53:47+02:00"
},
{
"id": "chat_dl1l2e7je3q4",
"role": "user",
"content": "Setze Spaghetti auf die Einkaufsliste",
"createdAt": "2026-08-29T18:54:28+02:00"
},
{
"id": "chat_dl1l3xc70g08",
"role": "assistant",
"content": "Der lokale JARVIS-Agent ist momentan nicht vollständig verfügbar. Es wurde keine unbestätigte Home-Änderung ausgeführt.",
"createdAt": "2026-08-29T18:56:28+02:00"
}
],
"activity": [
{
"id": "act_dl1l4mfzxeis",
"kind": "kanban",
"message": "KI-Kanban (interval/deterministic-fallback): 1 Karten gepflegt",
"createdAt": "2026-08-29T18:57:22+02:00"
},
{
"id": "act_dl1l3xc6e5x8",
"kind": "warning",
"message": "Tool-Agent: ollama nicht erreichbar: Post \"http://localhost:11434/api/chat\": context deadline exceeded (Client.Timeout exceeded while awaiting headers)",
"createdAt": "2026-08-29T18:56:28+02:00"
},
{
"id": "act_dl1l1vgzu0ag",
"kind": "warning",
"message": "Tool-Agent: ollama nicht erreichbar: Post \"http://localhost:11434/api/chat\": context canceled",
"createdAt": "2026-08-29T18:53:47+02:00"
},
{
"id": "act_dl1hmf4ihncw",
"kind": "kanban",
+5 -2
View File
@@ -11,6 +11,9 @@ const mealName=m=>({breakfast:'FRÜH',lunch:'MITTAG',dinner:'ABEND',snack:'SNACK
const taskOrigin=t=>t.source==='jarvis-command'?'JARVIS':t.aiManaged?'AI SCOUT':'MANUAL';
const messageHTML=text=>esc(text).replace(/\*\*(.+?)\*\*/g,'<strong>$1</strong>').replace(/`([^`]+)`/g,'<code>$1</code>').replace(/\n/g,'<br>');
function voiceSetupMessage(voice={},kind='stt'){if(kind==='stt'){if(!voice.ffmpegReady)return 'FFmpeg fehlt im Container';if(voice.whisperBinReady===false)return `Whisper-Binary fehlt: ${voice.whisperBin||'nicht gefunden'}`;if(voice.whisperModelReady===false)return `Whisper-Modell fehlt: ${voice.whisperModel||'/models/ggml-small.bin'}`;return voice.whisperError||voice.whisperModelError||'Lokales Whisper ist noch nicht konfiguriert'}if(voice.piperBinReady===false)return `Piper-Binary fehlt: ${voice.piperBin||'/tools/piper'}`;if(voice.piperModelReady===false)return `Piper-Modell fehlt: ${voice.piperModel||'/models/de_DE-thorsten-medium.onnx'}`;return voice.piperError||voice.piperModelError||'Lokales Piper ist noch nicht konfiguriert'}
function sttStatusLabel(voice={}){return voice.sttReady?'LOCAL':(!voice.whisperBinReady?'BIN':(!voice.whisperModelReady?'MODEL':(!voice.ffmpegReady?'FFMPEG':'SETUP')))}
function ttsStatusLabel(voice={}){return voice.ttsReady?'LOCAL':(!voice.piperBinReady?'BIN':(!voice.piperModelReady?'MODEL':'SETUP'))}
function safeRender(name,fn){try{fn()}catch(e){console.error(`[JARVIS UI] ${name} render failed`,e)}}
const THEME_KEY='jarvis-ui-theme',VIEW_KEY='jarvis-clean-view';
const cleanViews={
home:{eyebrow:'Übersicht',title:'Home',subtitle:'Dein Zuhause, Termine und Aufgaben auf einen Blick.'},
@@ -28,7 +31,7 @@ function toast(msg){const el=$('#toast');el.textContent=msg;el.classList.add('sh
function tickClock(){const n=new Date();$('#clock').textContent=n.toLocaleTimeString('de-DE',{hour:'2-digit',minute:'2-digit',second:'2-digit'});$('#date').textContent=n.toLocaleDateString('de-DE',{weekday:'short',day:'2-digit',month:'short',year:'numeric'}).toUpperCase();if($('#cleanTopDate'))$('#cleanTopDate').textContent=n.toLocaleDateString('de-DE',{weekday:'long',day:'numeric',month:'long',year:'numeric'})}setInterval(tickClock,1000);tickClock();
function setChip(id,ok,label){const dot=$(id+'Dot');if(!dot)return;const chip=dot.closest('.status-chip');chip.classList.toggle('online',!!ok);chip.classList.toggle('offline',ok===false);$(id+'Status').textContent=label}
async function refresh(){try{state=await api('/api/state');renderState();setChip('#core',true,'ONLINE')}catch(e){setChip('#core',false,'OFFLINE')}}
function renderState(){const sys=state.system||{},voice=sys.voice||{},ollama=sys.ollama||{},chunks=Number(sys.ragChunks||0);const chatReady=ollama.chatReady!==false&&!!(ollama.model||sys.model),embedReady=ollama.embeddingReady!==false&&!!(ollama.embeddingModel||sys.embeddingModel);setChip('#core',ollama.reachable===false?false:chatReady,chatReady?'LOCAL':(ollama.reachable===false?'OLLAMA OFF':'NO MODEL'));$('#coreStatus').title=chatReady?`ACTIVE MODEL: ${ollama.model||sys.model}`:(ollama.lastError||'Kein Chat-Modell erkannt');setChip('#rag',embedReady?(chunks>0?true:null):false,embedReady?(chunks?`${chunks} CHUNKS`:'EMPTY'):'NO EMBED');const sttLabel=voice.sttReady?'LOCAL':(!voice.whisperBinReady?'BIN':(!voice.whisperModelReady?'MODEL':(!voice.ffmpegReady?'FFMPEG':'SETUP'))),ttsLabel=voice.ttsReady?'LOCAL':(!voice.piperBinReady?'BIN':(!voice.piperModelReady?'MODEL':'SETUP'));setChip('#stt',!!voice.sttReady,sttLabel);setChip('#tts',!!voice.ttsReady,ttsLabel);$('#stt').title=voice.sttReady?`Whisper: ${voice.whisperBin||'whisper-cli'} · Modell: ${voice.whisperModel||''}`:voiceSetupMessage(voice,'stt');$('#tts').title=voice.ttsReady?`Piper: ${voice.piperBin||'piper'} · Modell: ${voice.piperModel||''}`:voiceSetupMessage(voice,'tts');const mt=$('#modelTag'),ctxN=Number(sys.context?.numCtx||0),ctxLabel=ctxN>=1024?`${Math.round(ctxN/1024)}K`:(ctxN||'—');if(mt){mt.textContent=chatReady?`LOCAL · ${String(ollama.model||sys.model).toUpperCase()} · CTX ${ctxLabel}`:'LOCAL · DEGRADED';mt.title=`Skill Agent: ${sys.agent?.mode||'unknown'} · ${sys.skills?.action_count||sys.agent?.tools?.length||0} actions · ${sys.skills?.plugin_count||0} plugins · max ${sys.agent?.maxSteps||0} steps · Conversation ${sys.context?.historyTokens||0} tokens`;}const scout=$('#scoutBtn'),kai=$('#kanbanAI'),reindex=$('#reindexBtn');if(scout){scout.disabled=!chatReady;scout.title=chatReady?'Lokalen Task-Scout starten':'Benötigt ein lokales Ollama-Chatmodell'}if(kai){kai.disabled=!chatReady;kai.title=chatReady?'Kanban mit lokalem Modell organisieren':'Benötigt ein lokales Ollama-Chatmodell'}if(reindex){reindex.disabled=!embedReady;reindex.title=embedReady?'RAG neu indexieren':'Benötigt ein lokales Embedding-Modell'}$('#chunkCount').textContent=chunks;$('#memoryBar').style.width=`${Math.min(100,5+Math.log2(chunks+1)*12)}%`;$('#wakeWord').textContent=String(voice.wakeWord||'jarvis').toUpperCase();$('#whisperDiag').textContent=voice.sttReady?'ONLINE':sttLabel;$('#whisperDiag').title=voice.sttReady?'Whisper bereit':voiceSetupMessage(voice,'stt');$('#whisperDiag').className=voice.sttReady?'good':'bad';$('#piperDiag').textContent=voice.ttsReady?'ONLINE':ttsLabel;$('#piperDiag').title=voice.ttsReady?'Piper bereit':voiceSetupMessage(voice,'tts');$('#piperDiag').className=voice.ttsReady?'good':'bad';renderCleanHome();renderBrief();renderCalendar();renderTasks();renderKanban();renderGroceries();renderMeals();renderRecipes();renderReminders();renderDocuments();renderSkills();renderSkillMesh();renderActivity();const dbg=sys.debug||{};const dstat=$('#debugTraceStatus');if(dstat){dstat.classList.toggle('off',!dbg.enabled);dstat.innerHTML=`<i></i> ${dbg.enabled?'DEBUG TRACE':'TRACE OFF'}`};if($('#debugExportBtn'))$('#debugExportBtn').disabled=!dbg.enabled;if($('#debugClearBtn'))$('#debugClearBtn').disabled=!dbg.enabled;if(!bootstrappedChat){renderInitialChat();bootstrappedChat=true}}
function renderState(){const sys=state.system||{},voice=sys.voice||{},ollama=sys.ollama||{},chunks=Number(sys.ragChunks||0);const chatReady=ollama.chatReady!==false&&!!(ollama.model||sys.model),embedReady=ollama.embeddingReady!==false&&!!(ollama.embeddingModel||sys.embeddingModel);setChip('#core',ollama.reachable===false?false:chatReady,chatReady?'LOCAL':(ollama.reachable===false?'OLLAMA OFF':'NO MODEL'));$('#coreStatus').title=chatReady?`ACTIVE MODEL: ${ollama.model||sys.model}`:(ollama.lastError||'Kein Chat-Modell erkannt');setChip('#rag',embedReady?(chunks>0?true:null):false,embedReady?(chunks?`${chunks} CHUNKS`:'EMPTY'):'NO EMBED');const sttLabel=sttStatusLabel(voice),ttsLabel=ttsStatusLabel(voice);setChip('#stt',!!voice.sttReady,sttLabel);setChip('#tts',!!voice.ttsReady,ttsLabel);$('#stt').title=voice.sttReady?`Whisper: ${voice.whisperBin||'whisper-cli'} · Modell: ${voice.whisperModel||''}`:voiceSetupMessage(voice,'stt');$('#tts').title=voice.ttsReady?`Piper: ${voice.piperBin||'piper'} · Modell: ${voice.piperModel||''}`:voiceSetupMessage(voice,'tts');const mt=$('#modelTag'),ctxN=Number(sys.context?.numCtx||0),ctxLabel=ctxN>=1024?`${Math.round(ctxN/1024)}K`:(ctxN||'—');if(mt){mt.textContent=chatReady?`LOCAL · ${String(ollama.model||sys.model).toUpperCase()} · CTX ${ctxLabel}`:'LOCAL · DEGRADED';mt.title=`Skill Agent: ${sys.agent?.mode||'unknown'} · ${sys.skills?.action_count||sys.agent?.tools?.length||0} actions · ${sys.skills?.plugin_count||0} plugins · max ${sys.agent?.maxSteps||0} steps · Conversation ${sys.context?.historyTokens||0} tokens`;}const scout=$('#scoutBtn'),kai=$('#kanbanAI'),reindex=$('#reindexBtn');if(scout){scout.disabled=!chatReady;scout.title=chatReady?'Lokalen Task-Scout starten':'Benötigt ein lokales Ollama-Chatmodell'}if(kai){kai.disabled=!chatReady;kai.title=chatReady?'Kanban mit lokalem Modell organisieren':'Benötigt ein lokales Ollama-Chatmodell'}if(reindex){reindex.disabled=!embedReady;reindex.title=embedReady?'RAG neu indexieren':'Benötigt ein lokales Embedding-Modell'}$('#chunkCount').textContent=chunks;$('#memoryBar').style.width=`${Math.min(100,5+Math.log2(chunks+1)*12)}%`;$('#wakeWord').textContent=String(voice.wakeWord||'jarvis').toUpperCase();$('#whisperDiag').textContent=voice.sttReady?'ONLINE':sttLabel;$('#whisperDiag').title=voice.sttReady?'Whisper bereit':voiceSetupMessage(voice,'stt');$('#whisperDiag').className=voice.sttReady?'good':'bad';$('#piperDiag').textContent=voice.ttsReady?'ONLINE':ttsLabel;$('#piperDiag').title=voice.ttsReady?'Piper bereit':voiceSetupMessage(voice,'tts');$('#piperDiag').className=voice.ttsReady?'good':'bad';safeRender('clean-home',renderCleanHome);safeRender('brief',renderBrief);safeRender('calendar',renderCalendar);safeRender('tasks',renderTasks);safeRender('kanban',renderKanban);safeRender('groceries',renderGroceries);safeRender('meals',renderMeals);safeRender('recipes',renderRecipes);safeRender('reminders',renderReminders);safeRender('documents',renderDocuments);safeRender('skills',renderSkills);safeRender('skill-mesh',renderSkillMesh);safeRender('activity',renderActivity);const dbg=sys.debug||{};const dstat=$('#debugTraceStatus');if(dstat){dstat.classList.toggle('off',!dbg.enabled);dstat.innerHTML=`<i></i> ${dbg.enabled?'DEBUG TRACE':'TRACE OFF'}`};if($('#debugExportBtn'))$('#debugExportBtn').disabled=!dbg.enabled;if($('#debugClearBtn'))$('#debugClearBtn').disabled=!dbg.enabled;if(!bootstrappedChat){renderInitialChat();bootstrappedChat=true}}
function renderCleanHome(){
const now=new Date(),today=new Date();today.setHours(0,0,0,0);const tomorrow=new Date(today);tomorrow.setDate(tomorrow.getDate()+1);const weekEnd=new Date(today);weekEnd.setDate(weekEnd.getDate()+7);
const events=[...(state.events||[])].filter(e=>{const d=parseDate(e.start);return d&&d>=today}).sort((a,b)=>String(a.start).localeCompare(String(b.start)));
@@ -43,7 +46,7 @@ function renderCleanHome(){
const ev=events[0],evEl=$('#cleanNextEvent');if(evEl)evEl.innerHTML=ev?`<strong>${esc(ev.title)}</strong><p>${esc(fmtDay(parseDate(ev.start)))} · ${esc(ev.allDay?'Ganztägig':fmtClock(ev.start))}${ev.location?' · '+esc(ev.location):''}</p>`:'<strong>Keine Termine</strong><p>Dein Kalender ist frei.</p>';
const task=tasks[0],taskEl=$('#cleanNextTask');if(taskEl)taskEl.innerHTML=task?`<strong>${esc(task.title)}</strong><p>${task.priority==='high'?'Hohe Priorität':'Offen'}${task.due?' · '+esc(fmtTime(task.due)):''}</p>`:'<strong>Keine offenen Aufgaben</strong><p>Du bist auf dem aktuellen Stand.</p>';
const meal=nextMeal,mealEl=$('#cleanNextMeal');if(mealEl)mealEl.innerHTML=meal?`<strong>${esc(meal.title||meal.recipeTitle||'Geplante Mahlzeit')}</strong><p>${esc(fmtDay(parseDate(meal.date)))} · ${esc(mealName(meal.meal))}${meal.servings?` · ${meal.servings} Portionen`:''}</p>`:'<strong>Noch nichts geplant</strong><p>Plane eine Mahlzeit für heute oder morgen.</p>';
const sys=state.system||{},ollama=sys.ollama||{},voice=sys.voice||{};if($('#cleanCoreQuick'))$('#cleanCoreQuick').textContent=ollama.chatReady===false?'Nicht bereit':String(ollama.model||sys.model||'Lokal');if($('#cleanRagQuick'))$('#cleanRagQuick').textContent=Number(sys.ragChunks||0)?`${sys.ragChunks} Chunks`:'Leer';if($('#cleanVoiceQuick')){const cv=$('#cleanVoiceQuick');cv.textContent=voice.sttReady?'Bereit':sttLabel;cv.title=voice.sttReady?'Lokales Whisper bereit':voiceSetupMessage(voice,'stt')}if($('#cleanModelStatus'))$('#cleanModelStatus').textContent=ollama.chatReady===false?'Modell fehlt':String(ollama.model||sys.model||'Online');if($('#cleanSkillsQuick'))$('#cleanSkillsQuick').textContent=`${Number(sys.mesh?.online_count||0)} Worker · ${Number(sys.skills?.action_count||0)} Actions`;
const sys=state.system||{},ollama=sys.ollama||{},voice=sys.voice||{};if($('#cleanCoreQuick'))$('#cleanCoreQuick').textContent=ollama.chatReady===false?'Nicht bereit':String(ollama.model||sys.model||'Lokal');if($('#cleanRagQuick'))$('#cleanRagQuick').textContent=Number(sys.ragChunks||0)?`${sys.ragChunks} Chunks`:'Leer';if($('#cleanVoiceQuick')){const cv=$('#cleanVoiceQuick'),label=sttStatusLabel(voice);cv.textContent=voice.sttReady?'Bereit':label;cv.title=voice.sttReady?'Lokales Whisper bereit':voiceSetupMessage(voice,'stt')}if($('#cleanModelStatus'))$('#cleanModelStatus').textContent=ollama.chatReady===false?'Modell fehlt':String(ollama.model||sys.model||'Online');if($('#cleanSkillsQuick'))$('#cleanSkillsQuick').textContent=`${Number(sys.mesh?.online_count||0)} Worker · ${Number(sys.skills?.action_count||0)} Actions`;
}
function renderBrief(){const start=new Date();start.setHours(0,0,0,0);const until=new Date(start);until.setDate(until.getDate()+7);$('#briefEvents').textContent=(state.events||[]).filter(e=>{const d=parseDate(e.start);return d&&d>=start&&d<until}).length;$('#briefTasks').textContent=(state.tasks||[]).filter(t=>t.status!=='done').length;$('#briefGroceries').textContent=(state.groceries||[]).filter(g=>!g.checked).length;$('#briefReminders').textContent=(state.reminders||[]).filter(r=>!r.done).length}
function renderCalendar(){const today=new Date();today.setHours(0,0,0,0);const end=new Date(today);end.setDate(end.getDate()+7);const events=[...(state.events||[])].sort((a,b)=>String(a.start).localeCompare(String(b.start)));const days=[];for(let i=0;i<7;i++){const d=new Date(today);d.setDate(d.getDate()+i);const key=localDateKey(d),count=events.filter(e=>{const ed=parseDate(e.start);return ed&&localDateKey(ed)===key}).length;days.push(`<div class="day-cell ${i===0?'today':''}"><span>${d.toLocaleDateString('de-DE',{weekday:'short'}).toUpperCase()}</span><strong>${d.getDate()}</strong>${count?`<b>${count}</b>`:''}</div>`)}$('#weekRail').innerHTML=days.join('');const visible=events.filter(e=>{const d=parseDate(e.start);return d&&d>=today&&d<end}).slice(0,18);$('#agenda').innerHTML=visible.length?visible.map(e=>`<div class="agenda-item"><div class="agenda-time">${esc(e.allDay?'GANZTÄGIG':fmtClock(e.start))}</div><div><strong>${esc(e.title)}</strong><span>${esc(fmtDay(parseDate(e.start)))}${e.location?' · '+esc(e.location):''} · ${e.aiManaged?'JARVIS':'MANUAL'}</span></div><button class="icon-delete" data-delete-event="${esc(e.id)}">×</button></div>`).join(''):'<div class="empty">KEINE TERMINE IN DEN NÄCHSTEN 7 TAGEN</div>';$$('[data-delete-event]').forEach(b=>b.onclick=()=>deleteEntity('/api/events/',b.dataset.deleteEvent,'Termin entfernt'))}