@madh-io/alfred-ai 0.19.0-jarvis.1181 → 0.19.0-jarvis.1182

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/bundle/index.js +5 -5
  2. package/package.json +1 -1
package/bundle/index.js CHANGED
@@ -6503,7 +6503,7 @@ Wenn nichts Handlungsrelevantes \xFCbrig bleibt: antworte exakt KEINE_INSIGHTS.`
6503
6503
  `),e);d?i.push({zeile:c[0].trim(),treffer:d}):r.push(...c),a=o}return r.some(o=>mf.test(o))?{text:r.join(`
6504
6504
  `),entfernt:i}:{text:null,entfernt:i}}function EN(l){let e=l.split(/(?<=[.!?])\s+/)[0]??l;return(e.length>200?e.slice(0,200)+"\u2026":e).trim()}function Yw(l,e){let t=e.filter(n=>Zw(n.value));if(t.length===0)return[];let s=new Set;for(let n of l.sections){if(n.key==="memories")continue;let i=new Set;for(let o of n.content.matchAll(/↳ NORMAL laut User-Korrektur[^[]*\[([^\]]+)\]/g))i.add(o[1]);let r=[];for(let o of n.content.split(`
6505
6505
  `)){if(r.push(o),o.trim().length<8||o.includes(qw))continue;let c=t.filter(u=>!i.has(u.key));if(c.length===0)continue;let d=Jn(o,c);if(d){i.add(d.key),s.add(d.key);let u=t.find(h=>h.key===d.key)?.value??"";r.push(` ${qw} [${d.key}]: ${EN(u)} \u2014 KEIN Fehler, NICHT als Problem/Insight melden.`)}}let a=t.filter(o=>!i.has(o.key));if(a.length>0){let o=Jn(n.content,a);if(o){s.add(o.key);let c=t.find(d=>d.key===o.key)?.value??"";r.push(`${qw} f\xFCr diesen Abschnitt [${o.key}]: ${EN(c)} \u2014 entsprechende Beobachtungen sind NORMAL, NICHT melden.`)}}n.content=r.join(`
6506
- `)}return[...s]}function ON(l,e){let t=m(r=>new Set(r.toLowerCase().replace(/[^a-zäöüß0-9\s]/g," ").split(/\s+/).filter(a=>a.length>=4)),"tok"),s=m(r=>{let a=r.toLowerCase();return SN.filter(o=>a.includes(o))},"objekte"),n=t(l);if(n.size===0)return!1;let i=new Set(s(l));for(let r of e){let a=t(r);if(a.size===0)continue;let o=0;for(let d of n)a.has(d)&&o++;let c=o/(n.size+a.size-o);if(c>=.5||c>=.25&&s(r).some(d=>i.has(d)))return!0}return!1}function Jw(l){if(!l||l.length<10)return!0;let e=l.trim();return e==="KEINE_INSIGHTS"||e.toLowerCase()==="keine_insights"}function $z(l){if(!l||l.length<10)return{hasInsights:!1,items:[]};try{let t=l.match(/\{[\s\S]*\}/);if(t){let s=JSON.parse(t[0]);if(typeof s.hasInsights=="boolean")return{hasInsights:s.hasInsights,items:Array.isArray(s.items)?s.items:[]}}}catch{}let e=l.toUpperCase();return e.includes("KEINE_INSIGHTS")||e.includes("KEINE NEUEN INSIGHTS")||e.includes("KEINE INSIGHTS")?{hasInsights:!1,items:[]}:{hasInsights:!0,items:[{summary:l,urgency:"normal"}]}}var kz,SN,vN,bz,Sz,vz,Iz,RN,NN,mf,qw,kN,Ml,bN,Nz,gf,Lo,Pl=A(()=>{"use strict";ze();uf();Nl();Ol();hf();wn();yN();kz=[7,12,18],SN=["wallbox","bmw","i4","batterie","akku","speicher","victron","ess","pool","heizung","geschirrsp\xFCler","waschmaschine","trockner","pv","solar","wechselrichter","strompreis","awattar","proxmox","unifi","mikrotik","fritzbox","nas","backup","zertifikat","domain","mqtt","kalender","termin","email","todo","erinnerung","tanken","laden","ladevorgang","reichweite","soc"],vN=/\b(ist (doch |völlig |ganz |eh |ohnehin )?(normal|ok|in ordnung|so gewollt)|kein (fehler|problem|defekt|grund zur)|falschalarm|nicht[^.!?\n]{0,60}\b(melden|warnen|alarmieren|erinnern)|sendet nur|nur (wenn|bei|während)|expected behavior|not an? (issue|error))\b/i;m(Zw,"istUnterdrueckungsAussage");bz=new Set(["nicht","mehr","wenn","dann","aber","auch","wurde","wurden","bereits","mehrfach","gesagt","wird","sind","ist","eine","einem","einer","dass","das","der","die","weil","nur","sendet","alfred","immer","dauernd","st\xE4ndig","melden","meldung","meldungen","bitte","sich","sein","seit","oder","beim","diese","dieser"]),Sz=new Set(["kritisch","kritischen","batterie","fehler","warnung","status","daten","offline","online","problem","sensor","sensoren","aktuell","aktuelle","aktuellen","daher","verwenden","wert","werte","sollte","sollten","tats\xE4chlich","tats\xE4chlichen","ausschlie\xDFlich","konfiguriert","konfigurierte","minimum","maximum","wieder","weiterhin","gerade","handlungsbedarf","offen","offene","offenen","gemeldet","gemeldeten","vollst\xE4ndig","insight","insights","e-mail","e-mails","nachricht","nachrichten","benachrichtigung","benachrichtigungen"]);m(Qw,"wortstamm");vz=new Set([...Sz].map(Qw));m(Az,"istFachAnker");m(AN,"kernwoerterAusKorrektur");Iz=["mqtt","wallbox","victron","proxmox","unifi","mikrotik","fritzbox","awattar","strompreis","wechselrichter","geschirrsp\xFCler","waschmaschine","trockner","pool","heizung","zertifikat","commvault"];m(IN,"istVorgangsbezogeneKorrektur");RN=new Set(["activity","skillHealth","insightTracking","feedback","action_feedback","trends","weather","energy","crypto","infra"]),NN=120;m($N,"istRundgangOhneAenderung");m(CN,"gateAusgesetztDurchWeltmodell");m(Jn,"findeVerletzteUnterdrueckungsKorrektur");m(Rz,"verletztUnterdrueckungsKorrektur");mf=/^\s*(?:[-*•]|\d+[.)])\s+/;m(LN,"filtereSegmentMitKorrekturen");m(EN,"korrekturKurzfassung");qw="\u21B3 NORMAL laut User-Korrektur";m(Yw,"annotiereKontextMitKorrekturen");m(ON,"istInhaltlichesInsightDuplikat");kN=1536,Ml="---ACTIONS---",bN=300*1e3,Nz=360*60*1e3,gf="---TOPICS---";m(Jw,"isNoInsights");m($z,"parseScanResponse");Lo=class l{static{m(this,"ReasoningEngine")}calendarProvider;todoRepo;watchRepo;memoryRepo;activityRepo;skillHealthRepo;notifRepo;skillRegistry;skillSandbox;llm;adapters;userRepo;defaultChatId;defaultPlatform;logger;activityLogger;defaultLocation;feedbackRepo;confirmationQueue;nodeId;adapter;insightTracker;kgService;workflowRepo;noteRepo;reminderRepoRef;documentRepo;userTimezone;conversationRepo;runbookRepo;projectRepo;tickTimer;lastRunHour=-1;lastDeferredCleanupDay="";lastEventTriggerAt=0;enabled;schedule;tier;deduplicationHours;collector;deliveryScheduler;planningAgent;notificationRouter;setPlanningAgent(e){this.planningAgent=e}setNotificationRouter(e){this.notificationRouter=e}interestsRepo;setInterestsRepo(e){this.interestsRepo=e}vorgaengeRepo;setVorgaengeRepo(e){this.vorgaengeRepo=e}async protokolliereSchritt(e,t,s,n){if(this.vorgaengeRepo)try{let{klassifiziereAktion:i}=await Promise.resolve().then(()=>(xl(),Dl));await this.vorgaengeRepo.schritt({vorgangId:n,userId:this.resolvedOwnerUserId||this.defaultChatId,art:t,skill:e.skillName,aktion:typeof e.skillParams?.action=="string"?e.skillParams.action:void 0,params:e.skillParams,beschreibung:e.description,ergebnis:s,autonomie:i(e.skillName,e.skillParams),quelle:"reasoning"})}catch(i){this.logger.debug({err:i.message},"v1179 Schritt nicht protokolliert")}}async legeVorgaengeAn(e){let t=new Map;if(!this.vorgaengeRepo||e.length===0)return t;try{let{klassifiziereAktion:s}=await Promise.resolve().then(()=>(xl(),Dl)),n=this.resolvedOwnerUserId||this.defaultChatId;for(let i of e.slice(0,5)){let r=s(i.skillName,i.skillParams),a=`${i.skillName}:${i.description.toLowerCase().replace(/[^a-zäöüß0-9]+/g," ").trim().slice(0,80)}`,o=await this.vorgaengeRepo.anlegen({userId:n,titel:i.description.slice(0,200),besitzer:r==="auto"?"alfred":"user",status:"offen",naechsterSchritt:r==="auto"?"ausf\xFChren":r==="nie"?"nur manuell durch den Owner":"Best\xE4tigung des Owners",quelle:"reasoning",autonomie:r,dedupeKey:a});t.set(i,o.id),await this.vorgaengeRepo.schritt({vorgangId:o.id,userId:n,art:"vorgeschlagen",skill:i.skillName,aktion:typeof i.skillParams?.action=="string"?i.skillParams.action:void 0,params:i.skillParams,beschreibung:i.description,autonomie:r,quelle:"reasoning"})}}catch(s){this.logger.debug({err:s.message},"v1179 Vorgang nicht angelegt")}return t}resolvedOwnerUserId;activityProfile;constructor(e,t,s,n,i,r,a,o,c,d,u,h,p,f,g,y,w,_,E,T,k="single",b,v,N,I,$,L,V,U,D,C,R,B,j){this.calendarProvider=e,this.todoRepo=t,this.watchRepo=s,this.memoryRepo=n,this.activityRepo=i,this.skillHealthRepo=r,this.notifRepo=a,this.skillRegistry=o,this.skillSandbox=c,this.llm=d,this.adapters=u,this.userRepo=h,this.defaultChatId=p,this.defaultPlatform=f,this.logger=y,this.activityLogger=w,this.defaultLocation=_,this.feedbackRepo=E,this.confirmationQueue=T,this.nodeId=k,this.adapter=b,this.insightTracker=v,this.kgService=I,this.workflowRepo=$,this.noteRepo=V,this.reminderRepoRef=U,this.documentRepo=D,this.userTimezone=C,this.conversationRepo=R,this.runbookRepo=B,this.projectRepo=j,this.enabled=g?.enabled!==!1,this.schedule=g?.schedule??"hourly",this.tier=g?.tier??"default",this.deduplicationHours=g?.deduplicationHours??12;let F=C||Intl.DateTimeFormat().resolvedOptions().timeZone;this.collector=N??new Ll(this.skillRegistry,this.skillSandbox,this.userRepo,this.calendarProvider,this.todoRepo,this.watchRepo,this.memoryRepo,this.activityRepo,this.skillHealthRepo,this.feedbackRepo,this.defaultChatId,this.defaultPlatform,this.defaultLocation,this.logger,this.workflowRepo,L,V,U,D,F,this.conversationRepo,this.runbookRepo,this.projectRepo),this.adapter&&(this.deliveryScheduler=new pf(this.adapter,this.logger.child({component:"delivery-scheduler"}),F,g?.quietHours??[22,7]))}start(){if(!this.enabled){this.logger.info("Reasoning engine disabled");return}let e=!1;this.tickTimer=setInterval(()=>{e||(e=!0,this.tick().catch(t=>this.logger.error({err:t},"Reasoning tick unhandled error")).finally(()=>{e=!1}))},6e4),this.logger.info({schedule:this.schedule,tier:this.tier,nodeId:this.nodeId,budget:3500},"Reasoning engine started")}stop(){this.tickTimer&&(clearInterval(this.tickTimer),this.tickTimer=void 0)}async triggerOnEvent(e,t,s={}){if(!this.enabled)return;let n=Date.now();if(n-this.lastEventTriggerAt<bN){this.logger.debug({eventType:e},"Event-triggered reasoning debounced (local)");return}if(this.lastEventTriggerAt=n,this.adapter&&this.adapter.type==="postgres"){let r=`reasoning-event:${Math.floor(n/bN)}:${e}`;if((await this.adapter.execute("INSERT INTO reasoning_slots (slot_key, node_id, claimed_at) VALUES (?, ?, ?) ON CONFLICT DO NOTHING",[r,this.nodeId,new Date().toISOString()])).changes===0)return}try{let i=await this.collector.collect();await this.enrichWithKnowledgeGraph(i),await this.wendeKorrekturenAufKontextAn(i);let r=`Du bist Alfreds holistisches Denk-Modul. Ein Event ist eingetreten:
6506
+ `)}return[...s]}function ON(l,e){let t=m(r=>new Set(r.toLowerCase().replace(/[^a-zäöüß0-9\s]/g," ").split(/\s+/).filter(a=>a.length>=4)),"tok"),s=m(r=>{let a=r.toLowerCase();return SN.filter(o=>a.includes(o))},"objekte"),n=t(l);if(n.size===0)return!1;let i=new Set(s(l));for(let r of e){let a=t(r);if(a.size===0)continue;let o=0;for(let d of n)a.has(d)&&o++;let c=o/(n.size+a.size-o);if(c>=.5||c>=.25&&s(r).some(d=>i.has(d)))return!0}return!1}function Jw(l){if(!l||l.length<10)return!0;let e=l.trim();return e==="KEINE_INSIGHTS"||e.toLowerCase()==="keine_insights"}function $z(l){if(!l||l.length<10)return{hasInsights:!1,items:[]};try{let t=l.match(/\{[\s\S]*\}/);if(t){let s=JSON.parse(t[0]);if(typeof s.hasInsights=="boolean")return{hasInsights:s.hasInsights,items:Array.isArray(s.items)?s.items:[]}}}catch{}let e=l.toUpperCase();return e.includes("KEINE_INSIGHTS")||e.includes("KEINE NEUEN INSIGHTS")||e.includes("KEINE INSIGHTS")?{hasInsights:!1,items:[]}:{hasInsights:!0,items:[{summary:l,urgency:"normal"}]}}var kz,SN,vN,bz,Sz,vz,Iz,RN,NN,mf,qw,kN,Ml,bN,Nz,gf,Lo,Pl=A(()=>{"use strict";ze();uf();Nl();Ol();hf();wn();yN();kz=[7,12,18],SN=["wallbox","bmw","i4","batterie","akku","speicher","victron","ess","pool","heizung","geschirrsp\xFCler","waschmaschine","trockner","pv","solar","wechselrichter","strompreis","awattar","proxmox","unifi","mikrotik","fritzbox","nas","backup","zertifikat","domain","mqtt","kalender","termin","email","todo","erinnerung","tanken","laden","ladevorgang","reichweite","soc"],vN=/\b(ist (doch |völlig |ganz |eh |ohnehin )?(normal|ok|in ordnung|so gewollt)|kein (fehler|problem|defekt|grund zur)|falschalarm|nicht[^.!?\n]{0,60}\b(melden|warnen|alarmieren|erinnern)|sendet nur|nur (wenn|bei|während)|expected behavior|not an? (issue|error))\b/i;m(Zw,"istUnterdrueckungsAussage");bz=new Set(["nicht","mehr","wenn","dann","aber","auch","wurde","wurden","bereits","mehrfach","gesagt","wird","sind","ist","eine","einem","einer","dass","das","der","die","weil","nur","sendet","alfred","immer","dauernd","st\xE4ndig","melden","meldung","meldungen","bitte","sich","sein","seit","oder","beim","diese","dieser"]),Sz=new Set(["kritisch","kritischen","batterie","fehler","warnung","status","daten","offline","online","problem","sensor","sensoren","aktuell","aktuelle","aktuellen","daher","verwenden","wert","werte","sollte","sollten","tats\xE4chlich","tats\xE4chlichen","ausschlie\xDFlich","konfiguriert","konfigurierte","minimum","maximum","wieder","weiterhin","gerade","handlungsbedarf","offen","offene","offenen","gemeldet","gemeldeten","vollst\xE4ndig","insight","insights","e-mail","e-mails","nachricht","nachrichten","benachrichtigung","benachrichtigungen"]);m(Qw,"wortstamm");vz=new Set([...Sz].map(Qw));m(Az,"istFachAnker");m(AN,"kernwoerterAusKorrektur");Iz=["mqtt","wallbox","victron","proxmox","unifi","mikrotik","fritzbox","awattar","strompreis","wechselrichter","geschirrsp\xFCler","waschmaschine","trockner","pool","heizung","zertifikat","commvault"];m(IN,"istVorgangsbezogeneKorrektur");RN=new Set(["activity","skillHealth","insightTracking","feedback","action_feedback","trends","weather","energy","crypto","infra"]),NN=120;m($N,"istRundgangOhneAenderung");m(CN,"gateAusgesetztDurchWeltmodell");m(Jn,"findeVerletzteUnterdrueckungsKorrektur");m(Rz,"verletztUnterdrueckungsKorrektur");mf=/^\s*(?:[-*•]|\d+[.)])\s+/;m(LN,"filtereSegmentMitKorrekturen");m(EN,"korrekturKurzfassung");qw="\u21B3 NORMAL laut User-Korrektur";m(Yw,"annotiereKontextMitKorrekturen");m(ON,"istInhaltlichesInsightDuplikat");kN=1536,Ml="---ACTIONS---",bN=300*1e3,Nz=360*60*1e3,gf="---TOPICS---";m(Jw,"isNoInsights");m($z,"parseScanResponse");Lo=class l{static{m(this,"ReasoningEngine")}calendarProvider;todoRepo;watchRepo;memoryRepo;activityRepo;skillHealthRepo;notifRepo;skillRegistry;skillSandbox;llm;adapters;userRepo;defaultChatId;defaultPlatform;logger;activityLogger;defaultLocation;feedbackRepo;confirmationQueue;nodeId;adapter;insightTracker;kgService;workflowRepo;noteRepo;reminderRepoRef;documentRepo;userTimezone;conversationRepo;runbookRepo;projectRepo;tickTimer;lastRunHour=-1;lastDeferredCleanupDay="";lastEventTriggerAt=0;enabled;schedule;tier;deduplicationHours;collector;deliveryScheduler;planningAgent;notificationRouter;setPlanningAgent(e){this.planningAgent=e}setNotificationRouter(e){this.notificationRouter=e}interestsRepo;setInterestsRepo(e){this.interestsRepo=e}vorgaengeRepo;setVorgaengeRepo(e){this.vorgaengeRepo=e}async protokolliereSchritt(e,t,s,n){if(this.vorgaengeRepo)try{let{klassifiziereAktion:i}=await Promise.resolve().then(()=>(xl(),Dl));await this.vorgaengeRepo.schritt({vorgangId:n,userId:this.resolvedOwnerUserId||this.defaultChatId,art:t,skill:e.skillName,aktion:typeof e.skillParams?.action=="string"?e.skillParams.action:void 0,params:e.skillParams,beschreibung:e.description,ergebnis:s,autonomie:i(e.skillName,e.skillParams),quelle:"reasoning"})}catch(i){this.logger.debug({err:i.message},"v1179 Schritt nicht protokolliert")}}async legeInsightVorgaengeAn(e){if(!(!this.vorgaengeRepo||e.length===0))try{let{istHandlungsInsight:t,vorgangTitelAus:s}=await Promise.resolve().then(()=>(xl(),Dl)),n=this.resolvedOwnerUserId||this.defaultChatId,i=0;for(let r of e){if(!t(r))continue;let a=s(r);a.length<8||(await this.vorgaengeRepo.anlegen({userId:n,titel:a,ziel:r.slice(0,500),besitzer:"user",status:"offen",naechsterSchritt:"Owner entscheidet",frist:new Date(Date.now()+7*864e5).toISOString(),quelle:"reasoning-insight",autonomie:"bestaetigen",dedupeKey:`insight:${this.insightTopicHash(r)}`}),i++)}i&&this.logger.info({angelegt:i,insights:e.length},"v1180 Handlungs-Insights als Vorg\xE4nge angelegt")}catch(t){this.logger.debug({err:t.message},"v1180 Insight\u2192Vorgang fehlgeschlagen")}}async legeVorgaengeAn(e){let t=new Map;if(!this.vorgaengeRepo||e.length===0)return t;try{let{klassifiziereAktion:s}=await Promise.resolve().then(()=>(xl(),Dl)),n=this.resolvedOwnerUserId||this.defaultChatId;for(let i of e.slice(0,5)){let r=s(i.skillName,i.skillParams),a=`${i.skillName}:${i.description.toLowerCase().replace(/[^a-zäöüß0-9]+/g," ").trim().slice(0,80)}`,o=await this.vorgaengeRepo.anlegen({userId:n,titel:i.description.slice(0,200),besitzer:r==="auto"?"alfred":"user",status:"offen",naechsterSchritt:r==="auto"?"ausf\xFChren":r==="nie"?"nur manuell durch den Owner":"Best\xE4tigung des Owners",quelle:"reasoning",autonomie:r,dedupeKey:a});t.set(i,o.id),await this.vorgaengeRepo.schritt({vorgangId:o.id,userId:n,art:"vorgeschlagen",skill:i.skillName,aktion:typeof i.skillParams?.action=="string"?i.skillParams.action:void 0,params:i.skillParams,beschreibung:i.description,autonomie:r,quelle:"reasoning"})}}catch(s){this.logger.debug({err:s.message},"v1179 Vorgang nicht angelegt")}return t}resolvedOwnerUserId;activityProfile;constructor(e,t,s,n,i,r,a,o,c,d,u,h,p,f,g,y,w,_,E,T,k="single",b,v,N,I,$,L,V,U,D,C,R,B,j){this.calendarProvider=e,this.todoRepo=t,this.watchRepo=s,this.memoryRepo=n,this.activityRepo=i,this.skillHealthRepo=r,this.notifRepo=a,this.skillRegistry=o,this.skillSandbox=c,this.llm=d,this.adapters=u,this.userRepo=h,this.defaultChatId=p,this.defaultPlatform=f,this.logger=y,this.activityLogger=w,this.defaultLocation=_,this.feedbackRepo=E,this.confirmationQueue=T,this.nodeId=k,this.adapter=b,this.insightTracker=v,this.kgService=I,this.workflowRepo=$,this.noteRepo=V,this.reminderRepoRef=U,this.documentRepo=D,this.userTimezone=C,this.conversationRepo=R,this.runbookRepo=B,this.projectRepo=j,this.enabled=g?.enabled!==!1,this.schedule=g?.schedule??"hourly",this.tier=g?.tier??"default",this.deduplicationHours=g?.deduplicationHours??12;let F=C||Intl.DateTimeFormat().resolvedOptions().timeZone;this.collector=N??new Ll(this.skillRegistry,this.skillSandbox,this.userRepo,this.calendarProvider,this.todoRepo,this.watchRepo,this.memoryRepo,this.activityRepo,this.skillHealthRepo,this.feedbackRepo,this.defaultChatId,this.defaultPlatform,this.defaultLocation,this.logger,this.workflowRepo,L,V,U,D,F,this.conversationRepo,this.runbookRepo,this.projectRepo),this.adapter&&(this.deliveryScheduler=new pf(this.adapter,this.logger.child({component:"delivery-scheduler"}),F,g?.quietHours??[22,7]))}start(){if(!this.enabled){this.logger.info("Reasoning engine disabled");return}let e=!1;this.tickTimer=setInterval(()=>{e||(e=!0,this.tick().catch(t=>this.logger.error({err:t},"Reasoning tick unhandled error")).finally(()=>{e=!1}))},6e4),this.logger.info({schedule:this.schedule,tier:this.tier,nodeId:this.nodeId,budget:3500},"Reasoning engine started")}stop(){this.tickTimer&&(clearInterval(this.tickTimer),this.tickTimer=void 0)}async triggerOnEvent(e,t,s={}){if(!this.enabled)return;let n=Date.now();if(n-this.lastEventTriggerAt<bN){this.logger.debug({eventType:e},"Event-triggered reasoning debounced (local)");return}if(this.lastEventTriggerAt=n,this.adapter&&this.adapter.type==="postgres"){let r=`reasoning-event:${Math.floor(n/bN)}:${e}`;if((await this.adapter.execute("INSERT INTO reasoning_slots (slot_key, node_id, claimed_at) VALUES (?, ?, ?) ON CONFLICT DO NOTHING",[r,this.nodeId,new Date().toISOString()])).changes===0)return}try{let i=await this.collector.collect();await this.enrichWithKnowledgeGraph(i),await this.wendeKorrekturenAufKontextAn(i);let r=`Du bist Alfreds holistisches Denk-Modul. Ein Event ist eingetreten:
6507
6507
 
6508
6508
  EVENT: ${String(e).replace(/[=\n\r]/g," ").slice(0,100)}
6509
6509
  DETAILS: ${String(t).replace(/[=\n\r]/g," ").slice(0,300)}
@@ -6527,7 +6527,7 @@ ${this.buildTopicInstructions()}`,o=(await this.llm.complete({messages:[{role:"u
6527
6527
  `),datum:new Date().toLocaleString("de-AT",{weekday:"long",day:"2-digit",month:"2-digit",year:"numeric",hour:"2-digit",minute:"2-digit"}),korrekturen:a.map(g=>g.value.slice(0,200))}),h=(await this.llm.complete({messages:[{role:"user",content:d}],maxTokens:400,tier:this.tier})).content.trim();if(Jw(h)){this.logger.info({quelle:e.quelle,objekte:e.objekte,dauerMs:Date.now()-r},"v1175 Mini-Pass: keine Meldung");return}let p=this.parseReasoningResponse(h),f=[];for(let g of p.insights){let y=await this.filtereBulletsDurchKorrekturen(g);y&&(await this.wasRecentlySent(y)||f.push(y))}this.logger.info({quelle:e.quelle,objekte:e.objekte,insights:f.length,verworfen:p.insights.length-f.length,dauerMs:Date.now()-r},"v1175 Mini-Pass gelaufen"),(f.length>0||p.actions.length>0)&&await this.deliverOrDefer(f,p.actions,"high",Date.now()-r)}catch(a){this.logger.warn({err:a.message,quelle:e.quelle},"v1175 Mini-Pass fehlgeschlagen")}}shouldRun(){let e=new Date,t=e.getHours(),s=e.getMinutes();switch(this.schedule){case"morning_noon_evening":return!!(kz.includes(t)&&s===0&&this.lastRunHour!==t);case"hourly":return s===0&&this.lastRunHour!==t;case"half_hourly":{let n=s<=1||s>=30&&s<=31,i=t*100+(s<2?0:30),r=this.lastRunHour!==i;return n&&this.logger.debug({hour:t,minute:s,slotId:i,lastRunHour:this.lastRunHour,notRun:r},"half_hourly shouldRun check"),!!(n&&r)}default:return!1}}markRun(){let e=new Date;if(this.schedule==="half_hourly"){let t=e.getMinutes();this.lastRunHour=e.getHours()*100+(t<15?0:30)}else this.lastRunHour=e.getHours()}async tick(){if(!this.shouldRun())return;this.markRun();let e=new Date().toISOString().slice(0,10);if(this.deliveryScheduler&&this.lastDeferredCleanupDay!==e){this.lastDeferredCleanupDay=e;try{let t=await this.deliveryScheduler.cleanup();t>0&&this.logger.info({geloescht:t},"v1158 Deferred-Insights aufger\xE4umt")}catch{}}if(!this.resolvedOwnerUserId)try{let t=await this.userRepo.findOrCreate(this.defaultPlatform,this.defaultChatId);this.resolvedOwnerUserId=t.masterUserId??t.id??this.defaultChatId}catch{this.resolvedOwnerUserId=this.defaultChatId}if(this.deliveryScheduler)try{let t=await this.deliveryScheduler.getPendingDeferred(this.defaultChatId);if(t.length>0){let s=await this.adapter?.queryOne(`SELECT MAX(created_at) as latest FROM messages WHERE conversation_id IN (
6528
6528
  SELECT id FROM conversations WHERE user_id = ?
6529
6529
  ) AND role = 'user'`,[this.resolvedOwnerUserId]),n=s?.latest?new Date(s.latest).getTime():0;if(Date.now()-n<30*6e4){let r=this.adapters.get(this.defaultPlatform);if(r){for(let a of t){let o=a.message;if(a.created_at){let c=Math.round((Date.now()-new Date(a.created_at).getTime())/6e4);if(c>30){let d=c>=120?`${Math.round(c/60)}h`:`${c} Min`;o=o.replace(/^(💡 \*\*Alfred Insights\*\*)/,`$1 _(erstellt vor ${d})_`)}}if(await r.sendMessage(this.defaultChatId,o),this.insightTracker&&a.message){let c=a.message.split(`
6530
- `).filter(u=>u.trim().length>10),d=c.map(u=>qn.categorizeInsight(u));this.insightTracker.trackInsightBatch(d,c)}try{let c=JSON.parse(a.actions);c.length>0&&await this.processActions(c)}catch{}}await this.deliveryScheduler.markDelivered(t.map(a=>a.id));for(let a of t)if(a.message){let o=a.message.split(`
6530
+ `).filter(u=>u.trim().length>10),d=c.map(u=>qn.categorizeInsight(u));this.insightTracker.trackInsightBatch(d,c)}try{let c=JSON.parse(a.actions);c.length>0&&(this.aktuelleVorgangIds=await this.legeVorgaengeAn(c),await this.processActions(c),this.aktuelleVorgangIds=void 0)}catch{}}await this.deliveryScheduler.markDelivered(t.map(a=>a.id));for(let a of t)if(a.message){let o=a.message.split(`
6531
6531
  `).filter(c=>c.trim().length>20);for(let c of o.slice(0,10))try{await this.markSent(c)}catch{}}this.logger.info({count:t.length},"Deferred insights flushed (cross-node activity detected)")}}}}catch{}try{if(this.adapter&&this.adapter.type==="postgres"){let U=new Date,D=U.getMinutes()<15?"00":"30",C=`reasoning:${U.toISOString().slice(0,13)}:${D}`;if((await this.adapter.execute("INSERT INTO reasoning_slots (slot_key, node_id, claimed_at) VALUES (?, ?, ?) ON CONFLICT DO NOTHING",[C,this.nodeId,new Date().toISOString()])).changes===0){this.logger.debug("Reasoning slot already claimed by another node, skipping");return}}this.logger.info({nodeId:this.nodeId,schedule:this.schedule},"Reasoning pass starting");let t=Date.now(),s=await this.collector.collect();await this.enrichWithKnowledgeGraph(s),await this.wendeKorrekturenAufKontextAn(s);let n=$N(s.changedSections,this.letzterVollpassAt,Date.now());if(n.ueberspringen){this.rundgaengeOhneVollpass++,this.logger.info({geaendert:s.changedSections,seitVollpassMin:n.seitVollpassMin,uebersprungen:this.rundgaengeOhneVollpass},"v1178 Rundgang: keine fachliche \xC4nderung \u2014 Vollpass \xFCbersprungen");return}this.letzterVollpassAt=Date.now(),this.logger.info({fachlichGeaendert:n.fachlich,seitVollpassMin:n.seitVollpassMin,rundgaengeUebersprungen:this.rundgaengeOhneVollpass},"v1178 Vollpass l\xE4uft"),this.rundgaengeOhneVollpass=0;let i=this.buildScanPrompt(s),a=(await this.llm.complete({messages:[{role:"user",content:i}],maxTokens:512,tier:this.tier})).content.trim(),o=Date.now()-t;this.logger.debug({response:a.slice(0,500),durationMs:o},"Reasoning scan response");let c=$z(a);if(this.interestsRepo&&c.items.length>0)try{let U=await this.resolveUserId(),D=await this.interestsRepo.listTopics(U,"active");if(D.length>0){let{boostByTopicRelevance:C}=await Promise.resolve().then(()=>(TN(),_N));c.items=C(c.items,D)}}catch{}if(!c.hasInsights||c.items.length===0){this.logger.info({durationMs:o},"Reasoning pass: no insights (scan)"),this.activityLogger?.logScheduledExec({actionId:"reasoning-engine",actionName:"Reasoning Engine",platform:this.defaultPlatform,chatId:this.defaultChatId,userId:this.resolvedOwnerUserId??this.defaultChatId,outcome:"success",durationMs:o});return}let d=c.items.filter(U=>U.urgency==="urgent"||U.urgency==="high"),u=c.items.filter(U=>U.urgency==="normal"),h=c.items.filter(U=>U.urgency==="low");if(this.notificationRouter&&h.length>0)for(let U of h)await this.wasRecentlySent(U.summary)||(await this.notificationRouter.store({source:"reasoning",urgency:"low",title:U.summary.split(`
6532
6532
  `)[0].slice(0,120),body:U.summary,reasons:U.warum?[U.warum]:void 0,chatId:this.defaultChatId,platform:this.defaultPlatform}),await this.markSent(U.summary));if(d.length===0&&u.length===0){this.logger.info({durationMs:o,lowStored:h.length},"Reasoning pass: only low-urgency items (stored silently)");return}let p=d.length>0?d.map(U=>`- [${U.urgency.toUpperCase()}] ${U.summary}`).join(`
6533
6533
  `):u.map(U=>`- ${U.summary}`).join(`
@@ -6864,7 +6864,7 @@ ${this.formatSections(e)}
6864
6864
  ${r}
6865
6865
  ${this.confirmationQueue?`
6866
6866
  Wenn eine sinnvolle Aktion m\xF6glich ist (Skill, Watch, Workflow, Delegate), trenne mit "${Ml}" und h\xE4nge JSON-Array an. Max 5 Aktionen.`:""}`}parseInsights(e){let t=e.split(/\n{2,}|\n(?=\d+\.\s)/).map(s=>s.trim()).filter(s=>s.length>10);return t.length<=1?[e.trim()]:t}insightContentHash(e){let t=e.slice(0,100).toLowerCase().replace(/\s+/g," ");return Vw.createHash("sha256").update(t).digest("hex").slice(0,16)}insightTopicHash(e){let t=e.slice(0,200).toLowerCase().replace(/[^a-zäöüß0-9\s]/g," ").split(/\s+/).filter(s=>s.length>=4).sort().join(" ");return Vw.createHash("sha256").update(t).digest("hex").slice(0,16)}gelieferteInsightsCache=null;korrekturenCache=null;async filtereBulletsDurchKorrekturen(e){try{let t=await this.holeUnterdrueckungsKorrekturen();if(t.length===0)return e;let{text:s,entfernt:n}=LN(e,t);for(let i of n)this.logger.info({korrektur:i.treffer.key,grund:i.treffer.grund,bullet:i.zeile.slice(0,160)},"v1157 Bullet durch User-Korrektur entfernt");return s===null&&n.length===0&&this.logger.info({insight:e.slice(0,160)},"v1157 Sektion durch Kopfzeilen-Treffer entfernt"),s}catch{return e}}async wendeKorrekturenAufKontextAn(e){try{let t=await this.holeUnterdrueckungsKorrekturen(),s=Yw(e,t);s.length>0&&this.logger.info({korrekturen:s},"v1151 Kontext-Daten mit User-Korrekturen annotiert")}catch{}}async holeUnterdrueckungsKorrekturen(){if(this.korrekturenCache&&Date.now()-this.korrekturenCache.geladen<5*6e4)return this.korrekturenCache.paare;let e=[];try{this.memoryRepo&&this.resolvedOwnerUserId&&(e=(await this.memoryRepo.getByType(this.resolvedOwnerUserId,"correction",50)).map(s=>({key:s.key,value:s.value})))}catch{}return this.korrekturenCache={paare:e,geladen:Date.now()},e}async holeGelieferteInsights(){if(this.gelieferteInsightsCache&&Date.now()-this.gelieferteInsightsCache.geladen<5*6e4)return this.gelieferteInsightsCache.texte;let e=[];try{this.memoryRepo&&this.resolvedOwnerUserId&&(e=(await this.memoryRepo.search(this.resolvedOwnerUserId,"insight_delivered")).filter(s=>s.key.startsWith("insight_delivered:")).map(s=>s.value))}catch{}return this.gelieferteInsightsCache={texte:e,geladen:Date.now()},e}async wasRecentlySent(e){let t=`reasoning:${this.insightContentHash(e)}`,s=`reasoning-topic:${this.insightTopicHash(e)}`,[n,i]=await Promise.all([this.notifRepo.wasNotified(t,this.defaultChatId),this.notifRepo.wasNotified(s,this.defaultChatId)]);if(n||i)return!0;let r=await this.holeUnterdrueckungsKorrekturen();if(r.length>0){let o=Jn(e,r);if(o){let c=this.collector.letzteAuffaelligeObjekte??new Set;if(CN(o,c))this.logger.info({korrektur:o.key,grund:o.grund,insight:e.slice(0,250)},"v1174 Gate ausgesetzt \u2014 Weltmodell meldet Auff\xE4lligkeit zum Objekt");else return this.logger.info({korrektur:o.key,grund:o.grund,insight:e.slice(0,250)},"v1148 insight durch User-Korrektur unterdr\xFCckt"),!0}}let a=await this.holeGelieferteInsights();return a.length>0&&ON(e,a)?(this.logger.info({insight:e.slice(0,80)},"v1142 insight inhaltlich bereits geliefert \u2014 unterdr\xFCckt"),!0):!1}async markSent(e){let t=new Date(Date.now()+this.deduplicationHours*60*60*1e3).toISOString(),s=`reasoning:${this.insightContentHash(e)}`,n=`reasoning-topic:${this.insightTopicHash(e)}`;await Promise.all([this.notifRepo.markNotified(s,this.defaultChatId,this.defaultPlatform,t),this.notifRepo.markNotified(n,this.defaultChatId,this.defaultPlatform,t)])}static ACTIONS_HEADER_REGEX=/\n\s*(?:\*{1,2}ACTIONS?\*{1,2}|#{1,3}[^\w\n]*ACTIONS?)\s*\n/i;static ACTIONS_HEADER_TRAILING_REGEX=/\n\s*(?:\*{1,2}ACTIONS?\*{1,2}|#{1,3}[^\w\n]*ACTIONS?)\s*$/i;parseReasoningResponse(e){let t=e.indexOf(Ml),s=Ml.length;if(t===-1){let c=e.match(l.ACTIONS_HEADER_REGEX);c&&c.index!==void 0&&(t=c.index,s=c[0].length)}if(t===-1){let c=e.match(/```(?:json)?\s*\n\s*(\[\s*\{[\s\S]*?"type"\s*:\s*"[\s\S]*?\}\s*\])\s*\n\s*```/);if(c&&c.index!==void 0){let u=e.slice(0,c.index).trim(),h=this.tryParseActions(c[1]),p=u.replace(l.ACTIONS_HEADER_TRAILING_REGEX,"").trim();return{insights:this.parseInsights(p),actions:h}}let d=this.stripUnparsedActions(e);return{insights:this.parseInsights(d),actions:[]}}let n=e.slice(0,t).trim(),i=e.slice(t+s).trim(),r=n?this.parseInsights(n):[],a=i.replace(/^```(?:json)?\s*\n?/,"").replace(/\n?\s*```\s*$/,"").trim(),o=this.tryParseActions(a);return{insights:r,actions:o}}stripUnparsedActions(e){let t=e,s=t.match(l.ACTIONS_HEADER_REGEX);return s&&s.index!==void 0&&(t=t.slice(0,s.index).trim()),t=t.replace(/```(?:json)?\s*\n[\s\S]*?\n\s*```/g,"").trim(),t=t.replace(/\n\s*\*{1,2}Aktion\s*#?\d+[^\n]*\*{1,2}\s*\n?/gi,`
6867
- `).trim(),t}tryParseActions(e){let t=e.replace(/^```(?:json)?\s*\n?/,"").replace(/\n?\s*```\s*$/,"").trim(),s=this.parseSingleJsonExpression(t);if(s.length>0)return s;let n=[...e.matchAll(/```(?:json)?\s*\n?([\s\S]*?)\n?\s*```/g)];if(n.length>0){let r=[];for(let a of n)r.push(...this.parseSingleJsonExpression(a[1].trim()));if(r.length>0)return r}let i=[...e.matchAll(/\{[^{}]*(?:\{[^{}]*\}[^{}]*)*\}/g)];if(i.length>0){let r=[];for(let a of i)r.push(...this.parseSingleJsonExpression(a[0].trim()));if(r.length>0)return r}return this.logger.warn("Reasoning: failed to parse actions JSON, ignoring"),[]}parseSingleJsonExpression(e){try{let t=JSON.parse(e);return(Array.isArray(t)?t:[t]).filter(n=>n&&typeof n=="object"&&typeof n.type=="string"&&typeof n.description=="string"&&typeof n.skillName=="string"&&typeof n.skillParams=="object"&&n.skillParams!==null)}catch{return[]}}actionHash(e){let t=`${e.description} ${e.skillName}`.toLowerCase().replace(/[^a-zäöüß0-9\s]/g," ").split(/\s+/).filter(s=>s.length>=4).sort().join(" ");return Vw.createHash("sha256").update(t).digest("hex").slice(0,16)}async actionWasRecentlyProposed(e){let t=this.actionHash(e);return await this.notifRepo.wasNotified(`reasoning-action:${t}`,this.defaultChatId)}async hasExpiredOrRejectedConfirmation(e){try{if(!this.confirmationQueue)return!1;let t=new Date(Date.now()-7*864e5).toISOString(),s=await this.adapter?.query("SELECT description, skill_name, skill_params, status FROM pending_confirmations WHERE chat_id = ? AND created_at > ? ORDER BY created_at DESC LIMIT 100",[this.defaultChatId,t]);if(!s)return!1;for(let n of s){if(n.status!=="expired"&&n.status!=="rejected")continue;let i={};try{i=n.skill_params?JSON.parse(n.skill_params):{}}catch{}let r={description:n.description,skillName:n.skill_name,skillParams:i};if($w({description:e.description,skillName:e.skillName,skillParams:e.skillParams},r))return!0}return!1}catch{return!1}}async markActionProposed(e){let s=`reasoning-action:${this.actionHash(e)}`,n=new Date(Date.now()+this.deduplicationHours*60*60*1e3).toISOString();await this.notifRepo.markNotified(s,this.defaultChatId,this.defaultPlatform,n)}static AUTO_SKILLS=new Set(["memory","calculator","weather","energy_price","crypto_price","routing","transit","feed_reader","shopping"]);static PROACTIVE_SKILLS=new Set(["reminder","note","todo","recipe","calendar","homeassistant","sonos","spotify","watch"]);static healActionSynonym(e,t){return Ca(e,t)}async getAutonomyLevel(){try{let e=await this.memoryRepo.recall(this.resolvedOwnerUserId||this.defaultChatId,"autonomy_level");if(e){let t=e.value.toLowerCase().trim();if(t.includes("autonomous")||t.includes("autonom"))return"autonomous";if(t.includes("confirm")||t.includes("best\xE4tig"))return"confirm_all";if(t.includes("proactive")||t.includes("proaktiv"))return"proactive"}}catch{}return"proactive"}async auditResolvedCorrectionOverlap(e){if(!(!this.memoryRepo||!this.resolvedOwnerUserId))try{let s=(await this.memoryRepo.getByType(this.resolvedOwnerUserId,"correction",50)).filter(a=>a.key.endsWith("_resolved"));if(s.length===0)return;let{extractSourceEventRefs:n}=await Promise.resolve().then(()=>(ze(),Ze)),i=new Set(n(e)),r=new Set(e.toLowerCase().split(/\s+/).filter(a=>a.length>=5));for(let a of s){if(a.key.replace(/_resolved$/,"").split("_").filter(p=>p.length>=5).filter(p=>r.has(p.toLowerCase())).length<2)continue;let d=new Set(a.sourceEventRefs??[]),u=[...i].filter(p=>d.has(p)),h=[...i].filter(p=>!d.has(p));h.length>0&&u.length===0?this.logger.info({insight:e.slice(0,120),correction:a.key,newRefs:h,corrRefs:[...d]},"Resolved-correction bypass: new event refs detected, insight is for a different instance"):u.length>0&&h.length===0&&this.logger.warn({insight:e.slice(0,120),correction:a.key,sharedRefs:u},"Resolved-correction overlap: insight refs match resolved correction \u2014 LLM may have erroneously bypassed")}}catch{}}resolveUrgency(e){let t=e.map(s=>s.urgency??"normal");return t.includes("urgent")?"urgent":t.includes("high")?"high":t.includes("normal")?"normal":t.length>0?"low":"normal"}async deliverOrDefer(e,t,s,n){if(this.notificationRouter&&e.length>0&&!this.notificationRouter.shouldSend("reasoning",s==="urgent"?"urgent":s)){for(let a of e){let o=t[0],c=t.length>0?`
6867
+ `).trim(),t}tryParseActions(e){let t=e.replace(/^```(?:json)?\s*\n?/,"").replace(/\n?\s*```\s*$/,"").trim(),s=this.parseSingleJsonExpression(t);if(s.length>0)return s;let n=[...e.matchAll(/```(?:json)?\s*\n?([\s\S]*?)\n?\s*```/g)];if(n.length>0){let r=[];for(let a of n)r.push(...this.parseSingleJsonExpression(a[1].trim()));if(r.length>0)return r}let i=[...e.matchAll(/\{[^{}]*(?:\{[^{}]*\}[^{}]*)*\}/g)];if(i.length>0){let r=[];for(let a of i)r.push(...this.parseSingleJsonExpression(a[0].trim()));if(r.length>0)return r}return this.logger.warn("Reasoning: failed to parse actions JSON, ignoring"),[]}parseSingleJsonExpression(e){try{let t=JSON.parse(e);return(Array.isArray(t)?t:[t]).filter(n=>n&&typeof n=="object"&&typeof n.type=="string"&&typeof n.description=="string"&&typeof n.skillName=="string"&&typeof n.skillParams=="object"&&n.skillParams!==null)}catch{return[]}}actionHash(e){let t=`${e.description} ${e.skillName}`.toLowerCase().replace(/[^a-zäöüß0-9\s]/g," ").split(/\s+/).filter(s=>s.length>=4).sort().join(" ");return Vw.createHash("sha256").update(t).digest("hex").slice(0,16)}async actionWasRecentlyProposed(e){let t=this.actionHash(e);return await this.notifRepo.wasNotified(`reasoning-action:${t}`,this.defaultChatId)}async hasExpiredOrRejectedConfirmation(e){try{if(!this.confirmationQueue)return!1;let t=new Date(Date.now()-7*864e5).toISOString(),s=await this.adapter?.query("SELECT description, skill_name, skill_params, status FROM pending_confirmations WHERE chat_id = ? AND created_at > ? ORDER BY created_at DESC LIMIT 100",[this.defaultChatId,t]);if(!s)return!1;for(let n of s){if(n.status!=="expired"&&n.status!=="rejected")continue;let i={};try{i=n.skill_params?JSON.parse(n.skill_params):{}}catch{}let r={description:n.description,skillName:n.skill_name,skillParams:i};if($w({description:e.description,skillName:e.skillName,skillParams:e.skillParams},r))return!0}return!1}catch{return!1}}async markActionProposed(e){let s=`reasoning-action:${this.actionHash(e)}`,n=new Date(Date.now()+this.deduplicationHours*60*60*1e3).toISOString();await this.notifRepo.markNotified(s,this.defaultChatId,this.defaultPlatform,n)}static AUTO_SKILLS=new Set(["memory","calculator","weather","energy_price","crypto_price","routing","transit","feed_reader","shopping"]);static PROACTIVE_SKILLS=new Set(["reminder","note","todo","recipe","calendar","homeassistant","sonos","spotify","watch"]);static healActionSynonym(e,t){return Ca(e,t)}async getAutonomyLevel(){try{let e=await this.memoryRepo.recall(this.resolvedOwnerUserId||this.defaultChatId,"autonomy_level");if(e){let t=e.value.toLowerCase().trim();if(t.includes("autonomous")||t.includes("autonom"))return"autonomous";if(t.includes("confirm")||t.includes("best\xE4tig"))return"confirm_all";if(t.includes("proactive")||t.includes("proaktiv"))return"proactive"}}catch{}return"proactive"}async auditResolvedCorrectionOverlap(e){if(!(!this.memoryRepo||!this.resolvedOwnerUserId))try{let s=(await this.memoryRepo.getByType(this.resolvedOwnerUserId,"correction",50)).filter(a=>a.key.endsWith("_resolved"));if(s.length===0)return;let{extractSourceEventRefs:n}=await Promise.resolve().then(()=>(ze(),Ze)),i=new Set(n(e)),r=new Set(e.toLowerCase().split(/\s+/).filter(a=>a.length>=5));for(let a of s){if(a.key.replace(/_resolved$/,"").split("_").filter(p=>p.length>=5).filter(p=>r.has(p.toLowerCase())).length<2)continue;let d=new Set(a.sourceEventRefs??[]),u=[...i].filter(p=>d.has(p)),h=[...i].filter(p=>!d.has(p));h.length>0&&u.length===0?this.logger.info({insight:e.slice(0,120),correction:a.key,newRefs:h,corrRefs:[...d]},"Resolved-correction bypass: new event refs detected, insight is for a different instance"):u.length>0&&h.length===0&&this.logger.warn({insight:e.slice(0,120),correction:a.key,sharedRefs:u},"Resolved-correction overlap: insight refs match resolved correction \u2014 LLM may have erroneously bypassed")}}catch{}}resolveUrgency(e){let t=e.map(s=>s.urgency??"normal");return t.includes("urgent")?"urgent":t.includes("high")?"high":t.includes("normal")?"normal":t.length>0?"low":"normal"}async deliverOrDefer(e,t,s,n){if(await this.legeInsightVorgaengeAn(e),this.notificationRouter&&e.length>0&&!this.notificationRouter.shouldSend("reasoning",s==="urgent"?"urgent":s)){for(let a of e){let o=t[0],c=t.length>0?`
6868
6868
 
6869
6869
  **Vorgeschlagene Aktionen:**
6870
6870
  ${t.slice(0,5).map(d=>`\u26A1 ${d.description}`).join(`
@@ -6877,7 +6877,7 @@ ${e.join(`
6877
6877
 
6878
6878
  **Vorgeschlagene Aktionen:**
6879
6879
  ${a.join(`
6880
- `)}`}let r=!0;if(this.deliveryScheduler&&s!=="urgent")try{this.activityProfile||(this.activityProfile=await this.deliveryScheduler.loadOrComputeProfile(this.defaultChatId)),r=await this.deliveryScheduler.shouldDeliverNow(s,this.activityProfile,this.resolvedOwnerUserId)}catch{r=!0}if(!r&&this.deliveryScheduler&&i){await this.deliveryScheduler.defer(this.defaultChatId,this.defaultPlatform,s,i,JSON.stringify(t)),this.logger.info({urgency:s,insightCount:e.length},"Insights deferred (user likely inactive)");for(let a of e)await this.markSent(a);return}if(i){let a=this.adapters.get(this.defaultPlatform);if(a){await a.sendMessage(this.defaultChatId,i);for(let o of e)await this.markSent(o);this.logger.info({durationMs:n,insights:e.length,actions:t.length,urgency:s},"Reasoning pass: insights sent")}if(this.insightTracker){let o=e.map(c=>qn.categorizeInsight(c));this.insightTracker.trackInsightBatch(o,e)}if(this.memoryRepo&&this.resolvedOwnerUserId){let o=new Date(Date.now()+1728e5).toISOString();for(let c of e){let d=c.toLowerCase().replace(/[^a-zäöüß\s]/g,"").split(/\s+/).filter(u=>u.length>=4).slice(0,3).sort().join("_");if(d)try{await this.memoryRepo.saveWithMetadata(this.resolvedOwnerUserId,`insight_delivered:${d}`,c.slice(0,200),"general","feedback",.6,"auto"),await this.memoryRepo.setExpiry(this.resolvedOwnerUserId,`insight_delivered:${d}`,o)}catch{}}this.gelieferteInsightsCache=null}}if(this.vorgaengeRepo&&e.length>0)try{let{istHandlungsInsight:a,vorgangTitelAus:o}=await Promise.resolve().then(()=>(xl(),Dl)),c=this.resolvedOwnerUserId||this.defaultChatId,d=0;for(let u of e){if(!a(u))continue;let h=o(u);h.length<8||(await this.vorgaengeRepo.anlegen({userId:c,titel:h,ziel:u.slice(0,500),besitzer:"user",status:"offen",naechsterSchritt:"Owner entscheidet",frist:new Date(Date.now()+7*864e5).toISOString(),quelle:"reasoning-insight",autonomie:"bestaetigen",dedupeKey:`insight:${this.insightTopicHash(u)}`}),d++)}d&&this.logger.info({angelegt:d,insights:e.length},"v1180 Handlungs-Insights als Vorg\xE4nge angelegt")}catch(a){this.logger.debug({err:a.message},"v1180 Insight\u2192Vorgang fehlgeschlagen")}t.length>0&&(this.aktuelleVorgangIds=await this.legeVorgaengeAn(t),await this.processActions(t),this.aktuelleVorgangIds=void 0)}aktuelleVorgangIds;async processActions(e){if(e.length===0)return;let t=await this.getAutonomyLevel(),s=e.slice(0,5);for(let n of s)if(n.type==="execute_plan"&&n.goal&&n.steps&&this.planningAgent){try{let i=await this.planningAgent.createPlan(this.resolvedUserId??"",n.goal,n.steps,"reasoning"),r=this.planningAgent.formatPlan(i);this.confirmationQueue&&await this.confirmationQueue.enqueuePlan(i,r),this.logger.info({planId:i.id,goal:i.goal,steps:i.steps.length},"Plan proposed for approval")}catch(i){this.logger.warn({err:i,goal:n.goal},"Failed to create plan")}continue}for(let n of s){let i=n;if(i.type!=="execute_plan"){if(i.skillName==="reminder"&&i.skillParams){let r=i.skillParams;if(r.action==="create"&&(r.action="set"),r.action==="delete"&&(r.action="cancel"),r.title&&!r.message&&(r.message=r.title,delete r.title),r.due&&!r.triggerAt&&(r.triggerAt=r.due,delete r.due),r.id&&!r.reminderId&&(r.reminderId=r.id,delete r.id),(r.action==="cancel"||r.action==="delete")&&!r.reminderId&&this.adapter)try{let a=this.resolvedOwnerUserId||this.defaultChatId,o=await this.adapter.query("SELECT id, message, trigger_at FROM reminders WHERE fired = 0 AND (user_id = ? OR chat_id = ?)",[a,this.defaultChatId]),c=i.description.toLowerCase().split(/\s+/).filter(d=>d.length>=4);for(let d of o){let u=`${d.message} ${d.trigger_at}`.toLowerCase().split(/\s+/).filter(p=>p.length>=3);if(c.filter(p=>u.some(f=>f.includes(p))).length>=2){r.reminderId=d.id.slice(0,8),this.logger.info({reminderId:r.reminderId,description:i.description,message:d.message},"Reasoning: resolved reminder ID by keyword match");break}}}catch{}if(r.triggerAt&&typeof r.triggerAt=="string"){let a=new Date(r.triggerAt.replace("T"," ").replace(/:\d{2}$/,""));if(!isNaN(a.getTime())&&a.getTime()<Date.now()){let o=new Date(a.getTime()+864e5);r.triggerAt=`${o.getFullYear()}-${String(o.getMonth()+1).padStart(2,"0")}-${String(o.getDate()).padStart(2,"0")}T${String(o.getHours()).padStart(2,"0")}:${String(o.getMinutes()).padStart(2,"0")}`}r.triggerAt=String(r.triggerAt).replace(/^(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}):\d{2}$/,"$1")}}if(i.skillName==="reminder"&&i.skillParams?.message)try{if(!this.resolvedOwnerUserId)try{let c=await this.userRepo.findOrCreate(this.defaultPlatform,this.defaultChatId);this.resolvedOwnerUserId=c.masterUserId??c.id??this.defaultChatId}catch{this.resolvedOwnerUserId=this.defaultChatId}let r=this.resolvedOwnerUserId,a=new Date(Date.now()-1440*6e4).toISOString(),o=await this.adapter?.query("SELECT message FROM reminders WHERE (fired = 0 OR (fired = 1 AND trigger_at > ?)) AND (user_id = ? OR chat_id = ?)",[a,r,this.defaultChatId]);if(o){let c=new Set(String(i.skillParams.message).toLowerCase().split(/\s+/).filter(u=>u.length>=4));if(o.some(u=>u.message.toLowerCase().split(/\s+/).filter(f=>f.length>=4).filter(f=>c.has(f)).length>=3)){this.logger.info({action:i.description},"Reasoning: reminder already exists, skipping");continue}}}catch{}if(i.skillName==="itsm"&&i.skillParams?.action==="create_incident")try{let r=this.resolvedOwnerUserId||this.defaultChatId,a=(i.skillParams.title??"").toLowerCase().split(/\s+/).filter(d=>d.length>=4),c=(await this.memoryRepo.search(r,a.slice(0,3).join(" "))).filter(d=>d.type==="correction");for(let d of c)if(a.filter(h=>d.value.toLowerCase().includes(h)).length>=2&&/nicht.*kritisch|not.*critical|kein.*handlungsbedarf|ignorier/i.test(d.value)){this.logger.info({action:i.description,correction:d.key},"Reasoning: ITSM incident blocked by correction memory");continue}}catch{}if(await this.actionWasRecentlyProposed(i)){let r=this.actionHash(i);if(!(this.confirmationQueue?await this.hasExpiredOrRejectedConfirmation(i):!1)){this.logger.info({action:i.description},"Reasoning: action deduplicated, skipping");continue}}try{let r=await this.memoryRepo.recall(this.resolvedOwnerUserId||this.defaultChatId,`action_feedback_${i.skillName}`);if(r){let a=br.extractRate(r.value);if(a!==void 0&&a<.2){this.logger.info({skillName:i.skillName,rate:a},"Reasoning: action skipped (low acceptance rate)"),await this.protokolliereSchritt(i,"uebersprungen",`Akzeptanzrate ${Math.round(a*100)} %`,this.aktuelleVorgangIds?.get(i));continue}}}catch{}if(i.skillName==="memory"){let r=String(i.skillParams?.action??"");if(r==="save"||r==="add"||r==="create"){let a=String(i.skillParams?.value??i.skillParams?.text??"");if(pN(a)){this.logger.info({key:i.skillParams?.key,text:a.slice(0,80)},"v1143 memory-Echo blockiert \u2014 Insight-Texte sind Ausgaben, kein Wissen");continue}let o=Oi(a);if(o&&Date.now()-o.getTime()>24*36e5){this.logger.info({key:i.skillParams?.key,datum:o.toISOString().slice(0,10)},"v1143 memory-Save blockiert \u2014 Ereignis liegt in der Vergangenheit");continue}let c=String(i.skillParams?.category??"").toLowerCase();c&&!l.ERLAUBTE_MEMORY_KATEGORIEN.has(c)&&(i.skillParams.category="general")}}try{let r=this.skillRegistry.get(i.skillName);if(r&&i.skillParams?.action){let p=r.metadata.inputSchema?.properties?.action?.enum;if(p&&!p.includes(i.skillParams.action)){let f=l.healActionSynonym(i.skillParams.action,p);if(f)this.logger.info({skillName:i.skillName,from:i.skillParams.action,to:f},"Reasoning: hallucinated action self-healed via synonym mapping"),i.skillParams.action=f;else{this.logger.warn({skillName:i.skillName,action:i.skillParams.action,validActions:p.join(",")},"Reasoning: hallucinated action rejected before execution");continue}}}let a=l.AUTO_SKILLS.has(i.skillName),o=l.PROACTIVE_SKILLS.has(i.skillName),c=!1,d=!1;switch(t){case"autonomous":c=!0,d=!a;break;case"proactive":c=a||o,d=o;break;case"confirm_all":default:c=a,d=!1;break}if(!a){let{klassifiziereAktion:h,entscheideAusfuehrung:p}=await Promise.resolve().then(()=>(xl(),Dl)),f=h(i.skillName,i.skillParams),g=p(f,t);if(g==="blockieren"){this.logger.warn({action:i.description,skillName:i.skillName,klasse:f},"v1180 Aktion blockiert \u2014 Autonomie-Klasse nie"),await this.protokolliereSchritt(i,"blockiert","Autonomie-Klasse nie: nur manuell durch den Owner",this.aktuelleVorgangIds?.get(i));let w=this.aktuelleVorgangIds?.get(i);w&&this.vorgaengeRepo&&await this.vorgaengeRepo.setzeStatus(this.resolvedOwnerUserId||this.defaultChatId,w,"verworfen","blockiert (Autonomie: nie)").catch(()=>{});continue}let y=c;c=g==="ausfuehren",c&&(d=!0),y!==c&&this.logger.info({action:i.description,skillName:i.skillName,klasse:f,entscheid:g,autonomyLevel:t},"v1180 Autonomie-Klasse entscheidet anders als Skill-Liste")}if(c&&o){let h=await this.knowledgeGate(i);if(h==="reject"){this.logger.info({action:i.description,gate:"reject"},"Reasoning: knowledge gate rejected action"),await this.protokolliereSchritt(i,"uebersprungen","Knowledge-Gate: Ziel unbekannt",this.aktuelleVorgangIds?.get(i));continue}h==="confirm"&&(c=!1,this.logger.info({action:i.description,gate:"confirm"},"Reasoning: knowledge gate \u2192 confirmation (unknown target)"))}if(c){let h=await this.executeDirectly(i);if(!h.success&&h.error){this.logger.info({action:i.description,firstError:h.error},"Reasoning: trying LLM self-heal");let p=await this.tryLlmSelfHeal(i,h.error);p&&(this.logger.info({originalAction:i.description,healed:p.description},"Reasoning: LLM proposed alternative \u2014 retrying"),h=await this.executeDirectly(p),h.success&&(i=p))}if(await this.markActionProposed(i),h.success&&i.skillName==="memory"&&typeof i.skillParams?.key=="string")try{let p=String(i.skillParams?.value??i.skillParams?.text??""),f=Oi(p),g=f&&f.getTime()>Date.now()?new Date(f.getTime()+24*36e5):new Date(Date.now()+48*36e5);await this.memoryRepo.setRelevantUntil(this.resolvedOwnerUserId||this.defaultChatId,String(i.skillParams.key),g.toISOString())}catch{}if(d){let p=this.adapters.get(this.defaultPlatform);p&&(h.success?await p.sendMessage(this.defaultChatId,`\u26A1 **Proaktiv ausgef\xFChrt:** ${i.description}`):(this.logger.warn({action:i.description,error:h.error,skillName:i.skillName},"Reasoning: proactive action failed (after self-heal)"),await p.sendMessage(this.defaultChatId,`\u26A0\uFE0F **Aktion nicht m\xF6glich:** ${i.description}
6880
+ `)}`}let r=!0;if(this.deliveryScheduler&&s!=="urgent")try{this.activityProfile||(this.activityProfile=await this.deliveryScheduler.loadOrComputeProfile(this.defaultChatId)),r=await this.deliveryScheduler.shouldDeliverNow(s,this.activityProfile,this.resolvedOwnerUserId)}catch{r=!0}if(!r&&this.deliveryScheduler&&i){await this.deliveryScheduler.defer(this.defaultChatId,this.defaultPlatform,s,i,JSON.stringify(t)),this.logger.info({urgency:s,insightCount:e.length},"Insights deferred (user likely inactive)");for(let a of e)await this.markSent(a);return}if(i){let a=this.adapters.get(this.defaultPlatform);if(a){await a.sendMessage(this.defaultChatId,i);for(let o of e)await this.markSent(o);this.logger.info({durationMs:n,insights:e.length,actions:t.length,urgency:s},"Reasoning pass: insights sent")}if(this.insightTracker){let o=e.map(c=>qn.categorizeInsight(c));this.insightTracker.trackInsightBatch(o,e)}if(this.memoryRepo&&this.resolvedOwnerUserId){let o=new Date(Date.now()+1728e5).toISOString();for(let c of e){let d=c.toLowerCase().replace(/[^a-zäöüß\s]/g,"").split(/\s+/).filter(u=>u.length>=4).slice(0,3).sort().join("_");if(d)try{await this.memoryRepo.saveWithMetadata(this.resolvedOwnerUserId,`insight_delivered:${d}`,c.slice(0,200),"general","feedback",.6,"auto"),await this.memoryRepo.setExpiry(this.resolvedOwnerUserId,`insight_delivered:${d}`,o)}catch{}}this.gelieferteInsightsCache=null}}t.length>0&&(this.aktuelleVorgangIds=await this.legeVorgaengeAn(t),await this.processActions(t),this.aktuelleVorgangIds=void 0)}aktuelleVorgangIds;async processActions(e){if(e.length===0)return;let t=await this.getAutonomyLevel(),s=e.slice(0,5);for(let n of s)if(n.type==="execute_plan"&&n.goal&&n.steps&&this.planningAgent){try{let i=await this.planningAgent.createPlan(this.resolvedUserId??"",n.goal,n.steps,"reasoning"),r=this.planningAgent.formatPlan(i);this.confirmationQueue&&await this.confirmationQueue.enqueuePlan(i,r),this.logger.info({planId:i.id,goal:i.goal,steps:i.steps.length},"Plan proposed for approval")}catch(i){this.logger.warn({err:i,goal:n.goal},"Failed to create plan")}continue}for(let n of s){let i=n;if(i.type!=="execute_plan"){if(i.skillName==="reminder"&&i.skillParams){let r=i.skillParams;if(r.action==="create"&&(r.action="set"),r.action==="delete"&&(r.action="cancel"),r.title&&!r.message&&(r.message=r.title,delete r.title),r.due&&!r.triggerAt&&(r.triggerAt=r.due,delete r.due),r.id&&!r.reminderId&&(r.reminderId=r.id,delete r.id),(r.action==="cancel"||r.action==="delete")&&!r.reminderId&&this.adapter)try{let a=this.resolvedOwnerUserId||this.defaultChatId,o=await this.adapter.query("SELECT id, message, trigger_at FROM reminders WHERE fired = 0 AND (user_id = ? OR chat_id = ?)",[a,this.defaultChatId]),c=i.description.toLowerCase().split(/\s+/).filter(d=>d.length>=4);for(let d of o){let u=`${d.message} ${d.trigger_at}`.toLowerCase().split(/\s+/).filter(p=>p.length>=3);if(c.filter(p=>u.some(f=>f.includes(p))).length>=2){r.reminderId=d.id.slice(0,8),this.logger.info({reminderId:r.reminderId,description:i.description,message:d.message},"Reasoning: resolved reminder ID by keyword match");break}}}catch{}if(r.triggerAt&&typeof r.triggerAt=="string"){let a=new Date(r.triggerAt.replace("T"," ").replace(/:\d{2}$/,""));if(!isNaN(a.getTime())&&a.getTime()<Date.now()){let o=new Date(a.getTime()+864e5);r.triggerAt=`${o.getFullYear()}-${String(o.getMonth()+1).padStart(2,"0")}-${String(o.getDate()).padStart(2,"0")}T${String(o.getHours()).padStart(2,"0")}:${String(o.getMinutes()).padStart(2,"0")}`}r.triggerAt=String(r.triggerAt).replace(/^(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}):\d{2}$/,"$1")}}if(i.skillName==="reminder"&&i.skillParams?.message)try{if(!this.resolvedOwnerUserId)try{let c=await this.userRepo.findOrCreate(this.defaultPlatform,this.defaultChatId);this.resolvedOwnerUserId=c.masterUserId??c.id??this.defaultChatId}catch{this.resolvedOwnerUserId=this.defaultChatId}let r=this.resolvedOwnerUserId,a=new Date(Date.now()-1440*6e4).toISOString(),o=await this.adapter?.query("SELECT message FROM reminders WHERE (fired = 0 OR (fired = 1 AND trigger_at > ?)) AND (user_id = ? OR chat_id = ?)",[a,r,this.defaultChatId]);if(o){let c=new Set(String(i.skillParams.message).toLowerCase().split(/\s+/).filter(u=>u.length>=4));if(o.some(u=>u.message.toLowerCase().split(/\s+/).filter(f=>f.length>=4).filter(f=>c.has(f)).length>=3)){this.logger.info({action:i.description},"Reasoning: reminder already exists, skipping");continue}}}catch{}if(i.skillName==="itsm"&&i.skillParams?.action==="create_incident")try{let r=this.resolvedOwnerUserId||this.defaultChatId,a=(i.skillParams.title??"").toLowerCase().split(/\s+/).filter(d=>d.length>=4),c=(await this.memoryRepo.search(r,a.slice(0,3).join(" "))).filter(d=>d.type==="correction");for(let d of c)if(a.filter(h=>d.value.toLowerCase().includes(h)).length>=2&&/nicht.*kritisch|not.*critical|kein.*handlungsbedarf|ignorier/i.test(d.value)){this.logger.info({action:i.description,correction:d.key},"Reasoning: ITSM incident blocked by correction memory");continue}}catch{}if(await this.actionWasRecentlyProposed(i)){let r=this.actionHash(i);if(!(this.confirmationQueue?await this.hasExpiredOrRejectedConfirmation(i):!1)){this.logger.info({action:i.description},"Reasoning: action deduplicated, skipping");continue}}try{let r=await this.memoryRepo.recall(this.resolvedOwnerUserId||this.defaultChatId,`action_feedback_${i.skillName}`);if(r){let a=br.extractRate(r.value);if(a!==void 0&&a<.2){this.logger.info({skillName:i.skillName,rate:a},"Reasoning: action skipped (low acceptance rate)"),await this.protokolliereSchritt(i,"uebersprungen",`Akzeptanzrate ${Math.round(a*100)} %`,this.aktuelleVorgangIds?.get(i));continue}}}catch{}if(i.skillName==="memory"){let r=String(i.skillParams?.action??"");if(r==="save"||r==="add"||r==="create"){let a=String(i.skillParams?.value??i.skillParams?.text??"");if(pN(a)){this.logger.info({key:i.skillParams?.key,text:a.slice(0,80)},"v1143 memory-Echo blockiert \u2014 Insight-Texte sind Ausgaben, kein Wissen");continue}let o=Oi(a);if(o&&Date.now()-o.getTime()>24*36e5){this.logger.info({key:i.skillParams?.key,datum:o.toISOString().slice(0,10)},"v1143 memory-Save blockiert \u2014 Ereignis liegt in der Vergangenheit");continue}let c=String(i.skillParams?.category??"").toLowerCase();c&&!l.ERLAUBTE_MEMORY_KATEGORIEN.has(c)&&(i.skillParams.category="general")}}try{let r=this.skillRegistry.get(i.skillName);if(r&&i.skillParams?.action){let p=r.metadata.inputSchema?.properties?.action?.enum;if(p&&!p.includes(i.skillParams.action)){let f=l.healActionSynonym(i.skillParams.action,p);if(f)this.logger.info({skillName:i.skillName,from:i.skillParams.action,to:f},"Reasoning: hallucinated action self-healed via synonym mapping"),i.skillParams.action=f;else{this.logger.warn({skillName:i.skillName,action:i.skillParams.action,validActions:p.join(",")},"Reasoning: hallucinated action rejected before execution");continue}}}let a=l.AUTO_SKILLS.has(i.skillName),o=l.PROACTIVE_SKILLS.has(i.skillName),c=!1,d=!1;switch(t){case"autonomous":c=!0,d=!a;break;case"proactive":c=a||o,d=o;break;case"confirm_all":default:c=a,d=!1;break}if(!a){let{klassifiziereAktion:h,entscheideAusfuehrung:p}=await Promise.resolve().then(()=>(xl(),Dl)),f=h(i.skillName,i.skillParams),g=p(f,t);if(g==="blockieren"){this.logger.warn({action:i.description,skillName:i.skillName,klasse:f},"v1180 Aktion blockiert \u2014 Autonomie-Klasse nie"),await this.protokolliereSchritt(i,"blockiert","Autonomie-Klasse nie: nur manuell durch den Owner",this.aktuelleVorgangIds?.get(i));let w=this.aktuelleVorgangIds?.get(i);w&&this.vorgaengeRepo&&await this.vorgaengeRepo.setzeStatus(this.resolvedOwnerUserId||this.defaultChatId,w,"verworfen","blockiert (Autonomie: nie)").catch(()=>{});continue}let y=c;c=g==="ausfuehren",c&&(d=!0),y!==c&&this.logger.info({action:i.description,skillName:i.skillName,klasse:f,entscheid:g,autonomyLevel:t},"v1180 Autonomie-Klasse entscheidet anders als Skill-Liste")}if(c&&o){let h=await this.knowledgeGate(i);if(h==="reject"){this.logger.info({action:i.description,gate:"reject"},"Reasoning: knowledge gate rejected action"),await this.protokolliereSchritt(i,"uebersprungen","Knowledge-Gate: Ziel unbekannt",this.aktuelleVorgangIds?.get(i));continue}h==="confirm"&&(c=!1,this.logger.info({action:i.description,gate:"confirm"},"Reasoning: knowledge gate \u2192 confirmation (unknown target)"))}if(c){let h=await this.executeDirectly(i);if(!h.success&&h.error){this.logger.info({action:i.description,firstError:h.error},"Reasoning: trying LLM self-heal");let p=await this.tryLlmSelfHeal(i,h.error);p&&(this.logger.info({originalAction:i.description,healed:p.description},"Reasoning: LLM proposed alternative \u2014 retrying"),h=await this.executeDirectly(p),h.success&&(i=p))}if(await this.markActionProposed(i),h.success&&i.skillName==="memory"&&typeof i.skillParams?.key=="string")try{let p=String(i.skillParams?.value??i.skillParams?.text??""),f=Oi(p),g=f&&f.getTime()>Date.now()?new Date(f.getTime()+24*36e5):new Date(Date.now()+48*36e5);await this.memoryRepo.setRelevantUntil(this.resolvedOwnerUserId||this.defaultChatId,String(i.skillParams.key),g.toISOString())}catch{}if(d){let p=this.adapters.get(this.defaultPlatform);p&&(h.success?await p.sendMessage(this.defaultChatId,`\u26A1 **Proaktiv ausgef\xFChrt:** ${i.description}`):(this.logger.warn({action:i.description,error:h.error,skillName:i.skillName},"Reasoning: proactive action failed (after self-heal)"),await p.sendMessage(this.defaultChatId,`\u26A0\uFE0F **Aktion nicht m\xF6glich:** ${i.description}
6881
6881
  Ich habe es probiert und auch eine Alternative gesucht \u2014 keiner der Wege funktioniert mit den aktuellen Skills. Sag mir wie ich "${i.description}" umsetzen soll, dann merke ich es mir f\xFCr n\xE4chstes Mal.
6882
6882
 
6883
6883
  _Details: ${(h.error??"").slice(0,200)}_`)))}if(this.logger.info({action:i.description,autonomyLevel:t},"Reasoning: action executed"),await this.protokolliereSchritt(i,h.success?"ausgefuehrt":"fehlgeschlagen",h.success?void 0:String(h.error??"").slice(0,300),this.aktuelleVorgangIds?.get(n)??this.aktuelleVorgangIds?.get(i)),this.vorgaengeRepo&&h.success){let p=this.aktuelleVorgangIds?.get(n)??this.aktuelleVorgangIds?.get(i);p&&await this.vorgaengeRepo.setzeStatus(this.resolvedOwnerUserId||this.defaultChatId,p,"erledigt","automatisch ausgef\xFChrt").catch(()=>{})}continue}let u=this.skillRegistry.get(i.skillName);if(u&&i.skillParams?.action){let p=u.metadata.inputSchema?.properties?.action?.enum;if(p&&!p.includes(i.skillParams.action)){this.logger.warn({skillName:i.skillName,action:i.skillParams.action},"Reasoning: hallucinated action rejected before enqueue");continue}}if(u&&i.skillName==="itsm"&&i.skillParams){let h=[{field:"incident_id",lookupAction:"get_incident"},{field:"change_id",lookupAction:"get_change"},{field:"problem_id",lookupAction:"get_problem"}],p;for(let f of h){let g=i.skillParams[f.field];if(!(typeof g!="string"||g.length===0))try{let{context:y}=await Qt(this.userRepo,{userId:this.defaultChatId,platform:this.defaultPlatform,chatId:this.defaultChatId,chatType:"dm"});if(!(await this.skillSandbox.execute(u,{action:f.lookupAction,[f.field]:g},y)).success){p=`${f.field}=${g}`;break}}catch(y){this.logger.debug({err:y,field:f.field,idVal:g},"Reasoning: entity-validation lookup failed \u2014 skipping check (treated as valid)")}}if(p){this.logger.warn({skillName:i.skillName,action:i.skillParams.action,halluzinatedRef:p,description:i.description},"Reasoning: action references unknown entity \u2014 dropped before enqueue");continue}}if(!this.confirmationQueue)continue;if(await this.confirmationQueue.enqueue({chatId:this.defaultChatId,platform:this.defaultPlatform,source:"reasoning",sourceId:"reasoning-engine",description:i.description,skillName:i.skillName,skillParams:i.skillParams,timeoutMinutes:180}),await this.markActionProposed(i),this.logger.info({action:i.description,autonomyLevel:t},"Reasoning: action enqueued for confirmation"),await this.protokolliereSchritt(i,"zur_bestaetigung",void 0,this.aktuelleVorgangIds?.get(i)),this.vorgaengeRepo){let h=this.aktuelleVorgangIds?.get(i);h&&await this.vorgaengeRepo.setzeStatus(this.resolvedOwnerUserId||this.defaultChatId,h,"wartet").catch(()=>{})}}catch(r){this.logger.error({err:r,action:i.description},"Reasoning: failed to process action")}}}}static ERLAUBTE_MEMORY_KATEGORIEN=new Set(["personal","work","preferences","relationships","health","hobbies","education","location","shopping","travel","schedule","general","other"]);static GATED_WRITE_ACTIONS={homeassistant:new Set(["turn_on","turn_off","toggle","call_service","create_automation","update_automation","delete_automation","create_script","run_script","create_scene"]),goe_charger:new Set(["start_charging","stop_charging","set_current"])};async knowledgeGate(e){let t=l.GATED_WRITE_ACTIONS[e.skillName],s=e.skillParams?.action;if(!t||!s||!t.has(s))return"proceed";let n=e.skillParams?.entityId??e.skillParams?.entity_id??e.skillParams?.device??e.skillParams?.entity??"";if(!n)return"confirm";let i=this.resolvedOwnerUserId||this.defaultChatId;try{let r=n.includes(".")?n.split(".").pop():n,a=await this.memoryRepo.search(i,r),o=a.filter(h=>h.type==="correction"),c=/nicht.*steuern|nicht.*manuell|regelt.*sich|finger.*weg|nicht.*ändern|lass.*das|nicht.*einschalten|nicht.*ausschalten|automatisch.*geregelt|nicht.*kritisch/i;for(let h of o)if(h.value.toLowerCase().includes(r.toLowerCase())&&c.test(h.value))return this.logger.info({target:n,correction:h.key,value:h.value.slice(0,100)},"Knowledge gate: correction blocks this action"),"reject";let d=e.description.toLowerCase().split(/\s+/).filter(h=>h.length>=4);for(let h of o){let p=h.value.toLowerCase().split(/\s+/).filter(g=>g.length>=4),f=d.filter(g=>p.some(y=>y.includes(g)));if(f.length>=3&&c.test(h.value))return this.logger.info({target:n,correction:h.key,sharedWords:f},"Knowledge gate: topic-level correction blocks this action"),"reject"}return a.filter(h=>h.value.toLowerCase().includes(r.toLowerCase())||h.key.toLowerCase().includes(r.toLowerCase())).length===0?"confirm":"proceed"}catch{return"confirm"}}async tryLlmSelfHeal(e,t){try{let s=[];for(let d of this.skillRegistry.getAll().slice(0,30)){let h=d.metadata.inputSchema?.properties?.action?.enum;h&&h.length>0?s.push(`- ${d.metadata.name}: ${h.slice(0,12).join(", ")}`):s.push(`- ${d.metadata.name}`)}let n=`Eine proaktive Aktion ist fehlgeschlagen. Schlage EINE alternative Action vor die das gleiche Ziel mit den verf\xFCgbaren Skills erreicht.
@@ -7811,7 +7811,7 @@ Base commit: \`${e.baseCommitSha.slice(0,8)}\``;return{ok:!0,prUrl:(await a.crea
7811
7811
  `)+d.join(`
7812
7812
  `)+`
7813
7813
  `;r(o,u,"utf8")}}catch(i){this.deps.logger.debug({err:i},"v726 .gitignore update skipped")}if(t.kind!=="empty")try{let{copyFileSync:i,statSync:r}=await import("node:fs");if(t.kind==="repo_path"){if(t.path.includes(".."))throw new Error("repo_path darf kein .. enthalten");let a=Xt.resolve(s,t.path);if(!a.startsWith(Xt.resolve(s)))throw new Error("repo_path verl\xE4sst projectCwd");let o=Xt.join(n,Xt.basename(a));i(a,o),this.deps.logger.info({src:a,target:o,size:r(o).size},"v726 db-seed copied from repo_path")}else if(t.kind==="upload"){if(!this.deps.dbSeedRepo||!this.deps.uploadSeedsPath)throw new Error("Upload-Seed angefordert aber dbSeedRepo/uploadSeedsPath nicht konfiguriert");let a=await this.deps.dbSeedRepo.getById(t.seedId);if(!a)throw new Error(`Seed ${t.seedId} nicht gefunden`);if(a.kind!=="upload")throw new Error(`Seed ${t.seedId} ist kind=${a.kind}, nicht upload`);let o=Xt.resolve(this.deps.uploadSeedsPath,a.storageRef);if(!o.startsWith(Xt.resolve(this.deps.uploadSeedsPath)))throw new Error("Upload-Seed verl\xE4sst uploadSeedsPath");let c=Xt.join(n,a.name);i(o,c),this.deps.logger.info({src:o,target:c,size:r(c).size},"v726 db-seed copied from upload")}}catch(i){this.deps.logger.warn({err:i},"v726 db-seed copy failed (sandbox startet mit leerem .alfred-data)")}}};m(Os,"runGit");m(WX,"runGitBoth");KX=[{name:"AWS Access Key",re:/\bAKIA[0-9A-Z]{16}\b/g},{name:"GitHub Token",re:/\bghp_[A-Za-z0-9]{36}\b/g},{name:"GitHub PAT",re:/\bghs_[A-Za-z0-9]{36}\b/g},{name:"GitLab Token",re:/\bglpat-[A-Za-z0-9_-]{20}\b/g},{name:"OpenAI Key",re:/\bsk-[A-Za-z0-9]{48,}\b/g},{name:"Anthropic Key",re:/\bsk-ant-[A-Za-z0-9-_]{24,}\b/g},{name:"Stripe Secret",re:/\bsk_live_[A-Za-z0-9]{24,}\b/g},{name:"Slack Token",re:/\bxox[abp]-[A-Za-z0-9-]{10,}\b/g},{name:"Private Key",re:/-----BEGIN (?:RSA |EC |DSA )?PRIVATE KEY-----/g},{name:"JWT Token",re:/\beyJ[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{20,}\b/g}];m(GX,"stripAnsi");m(VX,"summarizeTestFailure");m(qX,"scanForSecrets");m(JX,"parseRepoFromUrl");m(YX,"resolveDockerfilesDir")});var RL={};Ce(RL,{IdentityResolver:()=>uE});var uE,NL=A(()=>{"use strict";Ji();uE=class{static{m(this,"IdentityResolver")}users;projects;logger;constructor(e,t,s){this.users=e,this.projects=t,this.logger=s}async resolveOwnerFromConfig(e,t){if(!e||typeof e!="string")throw new Error("IdentityResolver.resolveOwnerFromConfig: empty/invalid envValue");if(Jr(e)){try{await this.users.findById(e)||this.logger.warn({envValue:e.slice(0,8)},"v804 owner UUID not found in users-table \u2014 accepting anyway (may belong to alfred_users table)")}catch{}return cg(e)}let s=t??this.guessPlatformFromFormat(e);if(!s)throw new Error(`IdentityResolver.resolveOwnerFromConfig: "${e.slice(0,20)}" ist kein UUID-Format und keine platform-hint angegeben. Setze ALFRED_OWNER_PLATFORM=telegram (oder matrix/discord/etc.) oder ALFRED_OWNER_USER_ID direkt auf den DB-UUID.`);let n=await this.users.findOrCreate(s,e),i=hc(n.id);if(!i)throw new Error(`IdentityResolver: findOrCreate returned non-UUID id "${n.id}"`);return this.logger.info({platform:s,platformUserId:e.slice(0,12)+"\u2026",resolvedUUID:i.slice(0,8)+"\u2026"},"v804 owner platform-id resolved to UUID"),i}async resolveMasterId(e){try{let t=await this.users.getMasterUserId(e);return hc(t)??e}catch(t){return this.logger.debug({err:t,userId:e.slice(0,8)},"v804 getMasterUserId failed, returning original"),e}}async findProjectOwner(e){if(!this.projects)return null;try{let t=await this.projects.getByIdAnyOwner(e);return t?hc(t.userId)??null:null}catch(t){return this.logger.debug({err:t,projectId:e},"v804 findProjectOwner failed"),null}}guessPlatformFromFormat(e){if(/^\d{6,15}$/.test(e))return"telegram";if(/^@[^:]+:[\w.-]+$/.test(e))return"matrix"}}});var $L={};Ce($L,{UserIdAuditScanner:()=>hE});import{randomUUID as ZX}from"node:crypto";var QX,hE,CL=A(()=>{"use strict";Ji();QX=[{table:"memories",pk:"id",uidColumn:"user_id"},{table:"documents",pk:"id",uidColumn:"user_id"},{table:"document_chunks",pk:"id",uidColumn:"user_id"},{table:"todos",pk:"id",uidColumn:"user_id"},{table:"notes",pk:"id",uidColumn:"user_id"},{table:"reminders",pk:"id",uidColumn:"user_id"},{table:"conversations",pk:"id",uidColumn:"user_id"},{table:"projects",pk:"id",uidColumn:"user_id"},{table:"background_tasks",pk:"id",uidColumn:"user_id"},{table:"agent_sessions",pk:"id",uidColumn:"user_id"},{table:"sandboxes",pk:"id",uidColumn:"user_id"},{table:"project_automations",pk:"id",uidColumn:"user_id"},{table:"goals",pk:"id",uidColumn:"user_id"},{table:"runbooks",pk:"id",uidColumn:"user_id"},{table:"insights",pk:"id",uidColumn:"user_id"}],hE=class{static{m(this,"UserIdAuditScanner")}adapter;logger;targets;constructor(e,t,s=QX){this.adapter=e,this.logger=t,this.targets=s}async scan(){let e={scanned:0,flaggedNew:0,alreadyFlagged:0,skippedTables:[]},t=new Date().toISOString();for(let s of this.targets)try{let n=await this.adapter.query(`SELECT ${s.pk} AS row_id, ${s.uidColumn} AS uid FROM ${s.table} WHERE ${s.uidColumn} IS NOT NULL`);for(let i of n){e.scanned+=1;let r=lg(i.uid);if(r==="uuid")continue;if(await this.adapter.queryOne("SELECT id FROM user_id_format_audit WHERE table_name = ? AND column_name = ? AND row_id = ?",[s.table,s.uidColumn,String(i.row_id)])){e.alreadyFlagged+=1;continue}await this.adapter.execute(`INSERT INTO user_id_format_audit (id, table_name, column_name, row_id, user_id_value, format_class, detected_at)
7814
- VALUES (?, ?, ?, ?, ?, ?, ?)`,[ZX(),s.table,s.uidColumn,String(i.row_id),i.uid,r,t]),e.flaggedNew+=1}}catch(n){let i=n.message??"";if(/no such table|does not exist|relation .* does not exist/i.test(i)){e.skippedTables.push(s.table);continue}this.logger.warn({err:n,table:s.table},"v808 audit-scan failed for table (continuing)")}return e.flaggedNew>0?this.logger.warn({scanned:e.scanned,flaggedNew:e.flaggedNew,alreadyFlagged:e.alreadyFlagged,skipped:e.skippedTables.length},"v808 UserIdAudit: non-UUID user_id rows detected \u2014 see user_id_format_audit table"):this.logger.debug({scanned:e.scanned,alreadyFlagged:e.alreadyFlagged,skipped:e.skippedTables.length},"v808 UserIdAudit: scan complete, all user_id rows have UUID format"),e}}});var sm={};Ce(sm,{default:()=>tW});var tW,nm=A(()=>{tW={name:"@madh-io/alfred-ai",version:"0.19.0-jarvis.1181",description:"Alfred \u2014 Personal AI Assistant across Telegram, Discord, WhatsApp, Matrix & Signal",type:"module",bin:{alfred:"bundle/index.js"},files:["bundle"],scripts:{build:"tsc",bundle:"node ../../scripts/bundle.mjs",prepublishOnly:"npm run build && npm run bundle",clean:"rm -rf dist bundle *.tsbuildinfo"},keywords:["ai","assistant","chatbot","telegram","discord","whatsapp","matrix","signal","claude","openai","ollama"],license:"MIT",repository:{type:"git",url:"https://github.com/madh99/alfred-ai.git"},homepage:"https://github.com/madh99/alfred-ai#readme",bugs:{url:"https://github.com/madh99/alfred-ai/issues"},dependencies:{"@anthropic-ai/sdk":"^0.105.0","@google/genai":"^1.45.0","@modelcontextprotocol/sdk":"^1.12.1","better-sqlite3":"^11.8.0",botbuilder:"^4.23.0",ccxt:"^4.4.0","discord.js":"^14.18.0",docx:"^9.0.0",dotenv:"^16.4.0",exceljs:"^4.4.0",grammy:"^1.35.0",imapflow:"^1.2.10","js-yaml":"^4.1.0",mammoth:"^1.8.0",mqtt:"^5.0.0",nodemailer:"^8.0.1",openai:"^6.44.0","pdf-parse":"^1.1.1",pdfkit:"^0.16.0",pino:"^9.6.0","pino-pretty":"^13.0.0",puppeteer:"^24.0.0","puppeteer-core":"^24.0.0","rss-parser":"^3.13.0",sharp:"^0.34.0",sonos:"^1.14.0",undici:"^7.10.0","youtube-transcript":"^1.3.0",zod:"^3.24.0"},optionalDependencies:{"@aws-sdk/client-s3":"^3.700.0","@influxdata/influxdb-client":"^1.35.0","@whiskeysockets/baileys":"6.7.21",googleapis:"^144.0.0","hafas-client":"^6.3.0",ioredis:"^5.4.0","matrix-bot-sdk":"^0.8.0",mongodb:"^6.12.0",mssql:"^11.0.0",mysql2:"^3.12.0",pg:"^8.13.0",tsdav:"^2.1.0"},devDependencies:{"@alfred/config":"workspace:*","@alfred/core":"workspace:*","@alfred/logger":"workspace:*","@alfred/mcp-server":"workspace:*","@alfred/security":"workspace:*","@alfred/storage":"workspace:*","@alfred/types":"workspace:*","@types/js-yaml":"^4.0.9"},publishConfig:{access:"public"},engines:{node:">=20"}}});var LL={};Ce(LL,{collectNodeMetrics:()=>im});import Ko from"node:os";import{statfs as sW}from"node:fs/promises";async function im(l){let e=[],t=new Set;for(let s of l)if(s)try{let n=await sW(s),i=Number(n.blocks)*Number(n.bsize),r=Number(n.bavail)*Number(n.bsize);if(i<=0)continue;let a=`${i}:${Number(n.bfree)}:${Number(n.type)}`;if(t.has(a))continue;t.add(a),e.push({path:s,totalGb:pE(i/1024**3),freeGb:pE(r/1024**3),usedPct:Math.min(100,Math.max(0,Math.round((1-r/i)*100)))})}catch{}return{cpuLoad1m:pE(Ko.loadavg()[0]??0),cpuCores:Ko.cpus().length,memTotalMb:Math.round(Ko.totalmem()/1024**2),memFreeMb:Math.round(Ko.freemem()/1024**2),rssMb:Math.round(process.memoryUsage().rss/1024**2),nodeJs:process.version,platform:Ko.platform(),osRelease:Ko.release(),disks:e}}function pE(l){return Math.round(l*10)/10}var rm=A(()=>{"use strict";m(im,"collectNodeMetrics");m(pE,"round1")});var DL={};Ce(DL,{ClusterManager:()=>$d});import OL from"node:os";var $d,fE=A(()=>{"use strict";rm();$d=class{static{m(this,"ClusterManager")}config;logger;redis;heartbeatTimer;heartbeatMs;failoverMs;constructor(e,t){this.config=e,this.logger=t,this.heartbeatMs=e.heartbeatIntervalMs??1e4,this.failoverMs=e.failoverAfterMs??3e4}async connect(){try{let e;try{e=(await Function('return import("ioredis")')()).default}catch{throw new Error('Cluster mode requires the "ioredis" package. Install it: npm install ioredis')}this.redis=new e(this.config.redisUrl),this.logger.info({nodeId:this.config.nodeId,role:this.config.role},"Cluster manager connected to Redis")}catch(e){this.logger.error({err:e},"Failed to connect to Redis \u2014 cluster features disabled");return}this.heartbeatTimer=setInterval(()=>this.sendHeartbeat(),this.heartbeatMs),await this.sendHeartbeat()}async disconnect(){this.heartbeatTimer&&clearInterval(this.heartbeatTimer),await this.redis?.quit()}nodeInfo;setNodeInfo(e){this.nodeInfo=e}async collectMetricsSafe(){try{return JSON.stringify(await im(this.nodeInfo?.diskPaths??["/"]))}catch{return"{}"}}async sendHeartbeat(){try{let e=Math.floor(process.uptime()),t=JSON.stringify({id:this.config.nodeId,role:this.config.role,timestamp:new Date().toISOString(),uptime:e,host:OL.hostname(),version:this.nodeInfo?.version??"",adapters:this.nodeInfo?.adapters?.()??[]});await this.redis.set(`alfred:cluster:heartbeat:${this.config.nodeId}`,t,"EX",Math.ceil(this.failoverMs/1e3))}catch(e){this.logger.warn({err:e},"Heartbeat send failed")}}async getNodes(){if(!this.redis)return[];try{let e=await this.redis.keys("alfred:cluster:heartbeat:*"),t=[];for(let s of e){let n=await this.redis.get(s);if(n)try{let i=JSON.parse(n);t.push({...i,healthy:!0})}catch{}}return t}catch{return[]}}async acquireLock(e,t=3e5){if(!this.redis)return!0;try{return await this.redis.set(`alfred:lock:${e}`,this.config.nodeId,"NX","PX",t)==="OK"}catch{return!0}}async releaseLock(e){if(this.redis)try{await this.redis.get(`alfred:lock:${e}`)===this.config.nodeId&&await this.redis.del(`alfred:lock:${e}`)}catch{}}async publish(e,t){if(this.redis)try{await this.redis.publish(`alfred:${e}`,JSON.stringify({...t,nodeId:this.config.nodeId}))}catch(s){this.logger.warn({err:s,channel:e},"Cluster publish failed")}}async subscribe(e,t){if(this.redis)try{let s=this.redis.duplicate();await s.subscribe(`alfred:${e}`),s.on("message",(n,i)=>{try{let r=JSON.parse(i);r.nodeId!==this.config.nodeId&&t(r)}catch{}})}catch(s){this.logger.warn({err:s,channel:e},"Cluster subscribe failed")}}async routeMessage(e,t,s){await this.publish("messages",{type:"send_message",targetPlatform:e,chatId:t,text:s})}failoverCheckTimer;onFailoverCallback;startFailoverMonitoring(e){this.config.role==="secondary"&&(this.onFailoverCallback=e,this.failoverCheckTimer=setInterval(async()=>{try{let t=await this.getNodes(),s=new Set(t.map(n=>n.id));for(let n of this.config.nodes??[])n.id!==this.config.nodeId&&(s.has(n.id)||(this.logger.warn({deadNodeId:n.id},"Node heartbeat missing \u2014 failover triggered"),this.onFailoverCallback?.(n.id)))}catch(t){this.logger.debug({err:t},"Failover check error")}},this.failoverMs))}stopFailoverMonitoring(){this.failoverCheckTimer&&clearInterval(this.failoverCheckTimer)}async announceTakeover(e,t){await this.publish("events",{type:"failover",deadNodeId:e,takenOverBy:this.config.nodeId,adapters:t}),this.logger.info({deadNodeId:e,adapters:t},"Failover: adapters taken over")}async syncConfig(e,t){await this.publish("config-sync",{type:e,...t})}async onConfigSync(e){await this.subscribe("config-sync",t=>{let{type:s,...n}=t;e(s,n)})}get nodeId(){return this.config.nodeId}get role(){return this.config.role??"node"}get isConnected(){return!!this.redis}pgAdapter;pgHeartbeatTimer;startPgHeartbeat(e){this.pgAdapter=e,this.pgHeartbeatTimer=setInterval(()=>this.sendPgHeartbeat(),this.heartbeatMs),this.sendPgHeartbeat()}async sendPgHeartbeat(){if(this.pgAdapter)try{let e=new Date().toISOString(),t=Math.floor(process.uptime()),s=new Date(Date.now()-t*1e3).toISOString(),n=await this.collectMetricsSafe();await this.pgAdapter.execute(`INSERT INTO node_heartbeats (node_id, host, last_seen_at, started_at, uptime_s, adapters, version, metrics)
7814
+ VALUES (?, ?, ?, ?, ?, ?, ?)`,[ZX(),s.table,s.uidColumn,String(i.row_id),i.uid,r,t]),e.flaggedNew+=1}}catch(n){let i=n.message??"";if(/no such table|does not exist|relation .* does not exist/i.test(i)){e.skippedTables.push(s.table);continue}this.logger.warn({err:n,table:s.table},"v808 audit-scan failed for table (continuing)")}return e.flaggedNew>0?this.logger.warn({scanned:e.scanned,flaggedNew:e.flaggedNew,alreadyFlagged:e.alreadyFlagged,skipped:e.skippedTables.length},"v808 UserIdAudit: non-UUID user_id rows detected \u2014 see user_id_format_audit table"):this.logger.debug({scanned:e.scanned,alreadyFlagged:e.alreadyFlagged,skipped:e.skippedTables.length},"v808 UserIdAudit: scan complete, all user_id rows have UUID format"),e}}});var sm={};Ce(sm,{default:()=>tW});var tW,nm=A(()=>{tW={name:"@madh-io/alfred-ai",version:"0.19.0-jarvis.1182",description:"Alfred \u2014 Personal AI Assistant across Telegram, Discord, WhatsApp, Matrix & Signal",type:"module",bin:{alfred:"bundle/index.js"},files:["bundle"],scripts:{build:"tsc",bundle:"node ../../scripts/bundle.mjs",prepublishOnly:"npm run build && npm run bundle",clean:"rm -rf dist bundle *.tsbuildinfo"},keywords:["ai","assistant","chatbot","telegram","discord","whatsapp","matrix","signal","claude","openai","ollama"],license:"MIT",repository:{type:"git",url:"https://github.com/madh99/alfred-ai.git"},homepage:"https://github.com/madh99/alfred-ai#readme",bugs:{url:"https://github.com/madh99/alfred-ai/issues"},dependencies:{"@anthropic-ai/sdk":"^0.105.0","@google/genai":"^1.45.0","@modelcontextprotocol/sdk":"^1.12.1","better-sqlite3":"^11.8.0",botbuilder:"^4.23.0",ccxt:"^4.4.0","discord.js":"^14.18.0",docx:"^9.0.0",dotenv:"^16.4.0",exceljs:"^4.4.0",grammy:"^1.35.0",imapflow:"^1.2.10","js-yaml":"^4.1.0",mammoth:"^1.8.0",mqtt:"^5.0.0",nodemailer:"^8.0.1",openai:"^6.44.0","pdf-parse":"^1.1.1",pdfkit:"^0.16.0",pino:"^9.6.0","pino-pretty":"^13.0.0",puppeteer:"^24.0.0","puppeteer-core":"^24.0.0","rss-parser":"^3.13.0",sharp:"^0.34.0",sonos:"^1.14.0",undici:"^7.10.0","youtube-transcript":"^1.3.0",zod:"^3.24.0"},optionalDependencies:{"@aws-sdk/client-s3":"^3.700.0","@influxdata/influxdb-client":"^1.35.0","@whiskeysockets/baileys":"6.7.21",googleapis:"^144.0.0","hafas-client":"^6.3.0",ioredis:"^5.4.0","matrix-bot-sdk":"^0.8.0",mongodb:"^6.12.0",mssql:"^11.0.0",mysql2:"^3.12.0",pg:"^8.13.0",tsdav:"^2.1.0"},devDependencies:{"@alfred/config":"workspace:*","@alfred/core":"workspace:*","@alfred/logger":"workspace:*","@alfred/mcp-server":"workspace:*","@alfred/security":"workspace:*","@alfred/storage":"workspace:*","@alfred/types":"workspace:*","@types/js-yaml":"^4.0.9"},publishConfig:{access:"public"},engines:{node:">=20"}}});var LL={};Ce(LL,{collectNodeMetrics:()=>im});import Ko from"node:os";import{statfs as sW}from"node:fs/promises";async function im(l){let e=[],t=new Set;for(let s of l)if(s)try{let n=await sW(s),i=Number(n.blocks)*Number(n.bsize),r=Number(n.bavail)*Number(n.bsize);if(i<=0)continue;let a=`${i}:${Number(n.bfree)}:${Number(n.type)}`;if(t.has(a))continue;t.add(a),e.push({path:s,totalGb:pE(i/1024**3),freeGb:pE(r/1024**3),usedPct:Math.min(100,Math.max(0,Math.round((1-r/i)*100)))})}catch{}return{cpuLoad1m:pE(Ko.loadavg()[0]??0),cpuCores:Ko.cpus().length,memTotalMb:Math.round(Ko.totalmem()/1024**2),memFreeMb:Math.round(Ko.freemem()/1024**2),rssMb:Math.round(process.memoryUsage().rss/1024**2),nodeJs:process.version,platform:Ko.platform(),osRelease:Ko.release(),disks:e}}function pE(l){return Math.round(l*10)/10}var rm=A(()=>{"use strict";m(im,"collectNodeMetrics");m(pE,"round1")});var DL={};Ce(DL,{ClusterManager:()=>$d});import OL from"node:os";var $d,fE=A(()=>{"use strict";rm();$d=class{static{m(this,"ClusterManager")}config;logger;redis;heartbeatTimer;heartbeatMs;failoverMs;constructor(e,t){this.config=e,this.logger=t,this.heartbeatMs=e.heartbeatIntervalMs??1e4,this.failoverMs=e.failoverAfterMs??3e4}async connect(){try{let e;try{e=(await Function('return import("ioredis")')()).default}catch{throw new Error('Cluster mode requires the "ioredis" package. Install it: npm install ioredis')}this.redis=new e(this.config.redisUrl),this.logger.info({nodeId:this.config.nodeId,role:this.config.role},"Cluster manager connected to Redis")}catch(e){this.logger.error({err:e},"Failed to connect to Redis \u2014 cluster features disabled");return}this.heartbeatTimer=setInterval(()=>this.sendHeartbeat(),this.heartbeatMs),await this.sendHeartbeat()}async disconnect(){this.heartbeatTimer&&clearInterval(this.heartbeatTimer),await this.redis?.quit()}nodeInfo;setNodeInfo(e){this.nodeInfo=e}async collectMetricsSafe(){try{return JSON.stringify(await im(this.nodeInfo?.diskPaths??["/"]))}catch{return"{}"}}async sendHeartbeat(){try{let e=Math.floor(process.uptime()),t=JSON.stringify({id:this.config.nodeId,role:this.config.role,timestamp:new Date().toISOString(),uptime:e,host:OL.hostname(),version:this.nodeInfo?.version??"",adapters:this.nodeInfo?.adapters?.()??[]});await this.redis.set(`alfred:cluster:heartbeat:${this.config.nodeId}`,t,"EX",Math.ceil(this.failoverMs/1e3))}catch(e){this.logger.warn({err:e},"Heartbeat send failed")}}async getNodes(){if(!this.redis)return[];try{let e=await this.redis.keys("alfred:cluster:heartbeat:*"),t=[];for(let s of e){let n=await this.redis.get(s);if(n)try{let i=JSON.parse(n);t.push({...i,healthy:!0})}catch{}}return t}catch{return[]}}async acquireLock(e,t=3e5){if(!this.redis)return!0;try{return await this.redis.set(`alfred:lock:${e}`,this.config.nodeId,"NX","PX",t)==="OK"}catch{return!0}}async releaseLock(e){if(this.redis)try{await this.redis.get(`alfred:lock:${e}`)===this.config.nodeId&&await this.redis.del(`alfred:lock:${e}`)}catch{}}async publish(e,t){if(this.redis)try{await this.redis.publish(`alfred:${e}`,JSON.stringify({...t,nodeId:this.config.nodeId}))}catch(s){this.logger.warn({err:s,channel:e},"Cluster publish failed")}}async subscribe(e,t){if(this.redis)try{let s=this.redis.duplicate();await s.subscribe(`alfred:${e}`),s.on("message",(n,i)=>{try{let r=JSON.parse(i);r.nodeId!==this.config.nodeId&&t(r)}catch{}})}catch(s){this.logger.warn({err:s,channel:e},"Cluster subscribe failed")}}async routeMessage(e,t,s){await this.publish("messages",{type:"send_message",targetPlatform:e,chatId:t,text:s})}failoverCheckTimer;onFailoverCallback;startFailoverMonitoring(e){this.config.role==="secondary"&&(this.onFailoverCallback=e,this.failoverCheckTimer=setInterval(async()=>{try{let t=await this.getNodes(),s=new Set(t.map(n=>n.id));for(let n of this.config.nodes??[])n.id!==this.config.nodeId&&(s.has(n.id)||(this.logger.warn({deadNodeId:n.id},"Node heartbeat missing \u2014 failover triggered"),this.onFailoverCallback?.(n.id)))}catch(t){this.logger.debug({err:t},"Failover check error")}},this.failoverMs))}stopFailoverMonitoring(){this.failoverCheckTimer&&clearInterval(this.failoverCheckTimer)}async announceTakeover(e,t){await this.publish("events",{type:"failover",deadNodeId:e,takenOverBy:this.config.nodeId,adapters:t}),this.logger.info({deadNodeId:e,adapters:t},"Failover: adapters taken over")}async syncConfig(e,t){await this.publish("config-sync",{type:e,...t})}async onConfigSync(e){await this.subscribe("config-sync",t=>{let{type:s,...n}=t;e(s,n)})}get nodeId(){return this.config.nodeId}get role(){return this.config.role??"node"}get isConnected(){return!!this.redis}pgAdapter;pgHeartbeatTimer;startPgHeartbeat(e){this.pgAdapter=e,this.pgHeartbeatTimer=setInterval(()=>this.sendPgHeartbeat(),this.heartbeatMs),this.sendPgHeartbeat()}async sendPgHeartbeat(){if(this.pgAdapter)try{let e=new Date().toISOString(),t=Math.floor(process.uptime()),s=new Date(Date.now()-t*1e3).toISOString(),n=await this.collectMetricsSafe();await this.pgAdapter.execute(`INSERT INTO node_heartbeats (node_id, host, last_seen_at, started_at, uptime_s, adapters, version, metrics)
7815
7815
  VALUES (?, ?, ?, ?, ?, ?, ?, ?)
7816
7816
  ON CONFLICT (node_id) DO UPDATE SET
7817
7817
  host = excluded.host,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@madh-io/alfred-ai",
3
- "version": "0.19.0-jarvis.1181",
3
+ "version": "0.19.0-jarvis.1182",
4
4
  "description": "Alfred — Personal AI Assistant across Telegram, Discord, WhatsApp, Matrix & Signal",
5
5
  "type": "module",
6
6
  "bin": {