@madh-io/alfred-ai 0.10.77 → 0.10.80

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 +12 -6
  2. package/package.json +1 -1
package/bundle/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- var Pa=Object.defineProperty;var m=(l,e)=>Pa(l,"name",{value:e,configurable:!0}),Ua=(l=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(l,{get:(e,t)=>(typeof require<"u"?require:e)[t]}):l)(function(l){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+l+'" is not supported')});var T=(l,e)=>()=>(l&&(e=l(l=0)),e);var ue=(l,e)=>{for(var t in e)Pa(l,t,{get:e[t],enumerable:!0})};import{z as w}from"zod";var ja,Ba,Ha,qa,za,Wa,Ga,Va,_t,Pu,Uu,Fu,Fa,ju,Bu,Hu,qu,zu,Wu,Gu,Vu,Ku,Xu,Yu,Ju,Zu,Qu,em,tm,sm,rm,nm,om,im,am,cm,lm,dm,um,mm,pm,hm,Oo,Po=T(()=>{"use strict";ja=w.object({token:w.string().optional(),enabled:w.boolean()}),Ba=w.object({token:w.string().optional(),enabled:w.boolean()}),Ha=w.object({enabled:w.boolean(),dataPath:w.string()}),qa=w.object({homeserverUrl:w.string(),accessToken:w.string().optional(),userId:w.string().optional(),enabled:w.boolean()}),za=w.object({apiUrl:w.string(),phoneNumber:w.string().optional(),enabled:w.boolean()}),Wa=w.object({path:w.string()}),Ga=w.object({level:w.enum(["trace","debug","info","warn","error","fatal"]),pretty:w.boolean(),auditLogPath:w.string().optional()}),Va=w.object({rulesPath:w.string(),defaultEffect:w.enum(["allow","deny"]),ownerUserId:w.string().optional()}),_t=w.object({provider:w.enum(["anthropic","openai","openrouter","ollama","openwebui","google","mistral"]),apiKey:w.string().optional(),baseUrl:w.string().optional(),model:w.string(),temperature:w.number().optional(),maxTokens:w.number().optional()}),Pu=w.object({default:_t,strong:_t.optional(),fast:_t.optional(),embeddings:_t.optional(),local:_t.optional()}).passthrough(),Uu=w.union([_t,Pu]),Fu=w.object({provider:w.enum(["brave","searxng","tavily","duckduckgo"]),apiKey:w.string().optional(),baseUrl:w.string().optional()}),Fa=w.object({name:w.string().optional(),provider:w.enum(["imap-smtp","microsoft"]).optional(),imap:w.object({host:w.string(),port:w.number(),secure:w.boolean()}).optional(),smtp:w.object({host:w.string(),port:w.number(),secure:w.boolean()}).optional(),auth:w.object({user:w.string(),pass:w.string()}).optional(),microsoft:w.object({clientId:w.string(),clientSecret:w.string(),tenantId:w.string(),refreshToken:w.string()}).optional()}),ju=w.union([w.object({accounts:w.array(Fa)}),Fa]),Bu=w.object({provider:w.enum(["openai","groq","google"]),apiKey:w.string(),baseUrl:w.string().optional(),ttsEnabled:w.boolean().optional(),ttsModel:w.string().optional(),ttsVoice:w.string().optional()}),Hu=w.object({serverUrl:w.string(),username:w.string(),password:w.string()}),qu=w.object({clientId:w.string(),clientSecret:w.string(),refreshToken:w.string()}),zu=w.object({clientId:w.string(),clientSecret:w.string(),tenantId:w.string(),refreshToken:w.string()}),Wu=w.object({provider:w.enum(["caldav","google","microsoft"]),caldav:Hu.optional(),google:qu.optional(),microsoft:zu.optional()}),Gu=w.object({name:w.string(),command:w.string().optional(),args:w.array(w.string()).optional(),env:w.record(w.string()).optional(),url:w.string().optional()}),Vu=w.object({servers:w.array(Gu)}),Ku=w.object({enabled:w.boolean(),allowedLanguages:w.array(w.enum(["javascript","python"])).optional(),maxTimeoutMs:w.number().optional(),allowNetwork:w.boolean().optional()}),Xu=w.object({enabled:w.boolean().optional(),minMessageLength:w.number().optional(),minConfidence:w.number().min(0).max(1).optional(),maxExtractionsPerMinute:w.number().optional()}),Yu=w.object({enabled:w.boolean(),port:w.coerce.number().int().min(1).max(65535),host:w.string(),token:w.string().optional(),corsOrigin:w.string().optional()}),Ju=w.object({name:w.string(),command:w.string(),argsTemplate:w.array(w.string()),promptVia:w.enum(["arg","stdin"]).default("arg"),env:w.record(w.string()).optional(),cwd:w.string().optional(),timeoutMs:w.number().max(9e5).optional()}),Zu=w.object({token:w.string(),baseUrl:w.string().optional()}),Qu=w.object({token:w.string(),baseUrl:w.string().optional()}),em=w.object({provider:w.enum(["github","gitlab"]),baseBranch:w.string().optional(),github:Zu.optional(),gitlab:Qu.optional()}),tm=w.object({enabled:w.boolean(),agents:w.array(Ju),forge:em.optional()}),sm=w.object({baseUrl:w.string(),tokenId:w.string(),tokenSecret:w.string(),verifyTls:w.boolean().optional(),defaultNode:w.string().optional()}),rm=w.object({baseUrl:w.string(),apiKey:w.string().optional(),username:w.string().optional(),password:w.string().optional(),site:w.string().optional(),verifyTls:w.boolean().optional()}),nm=w.object({baseUrl:w.string(),accessToken:w.string(),verifyTls:w.boolean().optional()}),om=w.object({serverUrl:w.string(),username:w.string(),password:w.string(),addressBookPath:w.string().optional()}),im=w.object({clientId:w.string(),clientSecret:w.string(),refreshToken:w.string()}),am=w.object({clientId:w.string(),clientSecret:w.string(),tenantId:w.string(),refreshToken:w.string()}),cm=w.object({provider:w.enum(["carddav","google","microsoft"]),carddav:om.optional(),google:im.optional(),microsoft:am.optional()}),lm=w.object({socketPath:w.string().optional(),host:w.string().optional(),verifyTls:w.boolean().optional()}),dm=w.object({clientId:w.string()}),um=w.object({apiKey:w.string(),homeAddress:w.string().optional(),workAddress:w.string().optional()}),mm=w.object({gridName:w.string().optional(),gridUsageCt:w.coerce.number().optional(),gridLossCt:w.coerce.number().optional(),gridCapacityFee:w.coerce.number().optional(),gridMeterFee:w.coerce.number().optional()}),pm=w.object({clientId:w.string(),clientSecret:w.string(),tenantId:w.string(),refreshToken:w.string()}),hm=w.object({maxHistoryMessages:w.number().min(10).max(500).optional()}).optional(),Oo=w.object({name:w.string(),telegram:ja,discord:Ba.optional(),whatsapp:Ha.optional(),matrix:qa.optional(),signal:za.optional(),llm:Uu,storage:Wa,logger:Ga,security:Va,search:Fu.optional(),email:ju.optional(),speech:Bu.optional(),calendar:Wu.optional(),mcp:Vu.optional(),codeSandbox:Ku.optional(),activeLearning:Xu.optional(),api:Yu.optional(),codeAgents:tm.optional(),proxmox:sm.optional(),unifi:rm.optional(),homeassistant:nm.optional(),contacts:cm.optional(),docker:lm.optional(),bmw:dm.optional(),routing:um.optional(),todo:pm.optional(),energy:mm.optional(),conversation:hm})});var Uo,Fo=T(()=>{"use strict";Uo={name:"Alfred",telegram:{token:"",enabled:!1},discord:{token:"",enabled:!1},whatsapp:{enabled:!1,dataPath:"./data/whatsapp"},matrix:{homeserverUrl:"https://matrix.org",accessToken:"",userId:"",enabled:!1},signal:{apiUrl:"http://localhost:8080",phoneNumber:"",enabled:!1},llm:{provider:"anthropic",model:"claude-sonnet-4-20250514",temperature:.7,maxTokens:4096},storage:{path:"./data/alfred.db"},logger:{level:"info",pretty:!0},security:{rulesPath:"./config/rules",defaultEffect:"deny"},api:{enabled:!0,port:3420,host:"127.0.0.1"},conversation:{maxHistoryMessages:100}}});import Ka from"node:fs";import fm from"node:path";import{config as Xa}from"dotenv";import gm from"js-yaml";function Ya(l,e){let t={...l};for(let s of Object.keys(e)){let r=e[s],n=t[s];r!=null&&typeof r=="object"&&!Array.isArray(r)&&n!==null&&n!==void 0&&typeof n=="object"&&!Array.isArray(n)?t[s]=Ya(n,r):t[s]=r}return t}function wm(l){let e={...l};for(let[t,s]of Object.entries(ym)){let r=process.env[t];if(r===void 0)continue;let n=e;for(let o=0;o<s.length-1;o++){let i=s[o];(n[i]===void 0||n[i]===null||typeof n[i]!="object")&&(n[i]={}),n[i]={...n[i]},n=n[i]}n[s[s.length-1]]=r}return e}function jo(){Xa({override:!0})}var ym,le,Ja=T(()=>{"use strict";Po();Fo();m(Ya,"deepMerge");ym={ALFRED_TELEGRAM_TOKEN:["telegram","token"],ALFRED_DISCORD_TOKEN:["discord","token"],ALFRED_MATRIX_HOMESERVER_URL:["matrix","homeserverUrl"],ALFRED_MATRIX_ACCESS_TOKEN:["matrix","accessToken"],ALFRED_MATRIX_USER_ID:["matrix","userId"],ALFRED_SIGNAL_API_URL:["signal","apiUrl"],ALFRED_SIGNAL_PHONE_NUMBER:["signal","phoneNumber"],ALFRED_ANTHROPIC_API_KEY:["llm","apiKey"],ALFRED_OPENAI_API_KEY:["llm","apiKey"],ALFRED_GOOGLE_API_KEY:["llm","apiKey"],ALFRED_OPENROUTER_API_KEY:["llm","apiKey"],ALFRED_OPENWEBUI_API_KEY:["llm","apiKey"],ALFRED_LLM_PROVIDER:["llm","provider"],ALFRED_LLM_MODEL:["llm","model"],ALFRED_LLM_BASE_URL:["llm","baseUrl"],ALFRED_LLM_STRONG_PROVIDER:["llm","strong","provider"],ALFRED_LLM_STRONG_MODEL:["llm","strong","model"],ALFRED_LLM_STRONG_API_KEY:["llm","strong","apiKey"],ALFRED_LLM_FAST_PROVIDER:["llm","fast","provider"],ALFRED_LLM_FAST_MODEL:["llm","fast","model"],ALFRED_LLM_FAST_API_KEY:["llm","fast","apiKey"],ALFRED_LLM_EMBEDDINGS_PROVIDER:["llm","embeddings","provider"],ALFRED_LLM_EMBEDDINGS_MODEL:["llm","embeddings","model"],ALFRED_LLM_EMBEDDINGS_API_KEY:["llm","embeddings","apiKey"],ALFRED_LLM_LOCAL_PROVIDER:["llm","local","provider"],ALFRED_LLM_LOCAL_MODEL:["llm","local","model"],ALFRED_LLM_LOCAL_BASE_URL:["llm","local","baseUrl"],ALFRED_STORAGE_PATH:["storage","path"],ALFRED_LOG_LEVEL:["logger","level"],ALFRED_OWNER_USER_ID:["security","ownerUserId"],ALFRED_SEARCH_PROVIDER:["search","provider"],ALFRED_SEARCH_API_KEY:["search","apiKey"],ALFRED_SEARCH_BASE_URL:["search","baseUrl"],ALFRED_EMAIL_PROVIDER:["email","provider"],ALFRED_EMAIL_USER:["email","auth","user"],ALFRED_EMAIL_PASS:["email","auth","pass"],ALFRED_MICROSOFT_EMAIL_CLIENT_ID:["email","microsoft","clientId"],ALFRED_MICROSOFT_EMAIL_CLIENT_SECRET:["email","microsoft","clientSecret"],ALFRED_MICROSOFT_EMAIL_TENANT_ID:["email","microsoft","tenantId"],ALFRED_MICROSOFT_EMAIL_REFRESH_TOKEN:["email","microsoft","refreshToken"],ALFRED_SPEECH_PROVIDER:["speech","provider"],ALFRED_SPEECH_API_KEY:["speech","apiKey"],ALFRED_SPEECH_BASE_URL:["speech","baseUrl"],ALFRED_CALENDAR_PROVIDER:["calendar","provider"],ALFRED_CALDAV_SERVER_URL:["calendar","caldav","serverUrl"],ALFRED_CALDAV_USERNAME:["calendar","caldav","username"],ALFRED_CALDAV_PASSWORD:["calendar","caldav","password"],ALFRED_GOOGLE_CALENDAR_CLIENT_ID:["calendar","google","clientId"],ALFRED_GOOGLE_CALENDAR_CLIENT_SECRET:["calendar","google","clientSecret"],ALFRED_GOOGLE_CALENDAR_REFRESH_TOKEN:["calendar","google","refreshToken"],ALFRED_MICROSOFT_CALENDAR_CLIENT_ID:["calendar","microsoft","clientId"],ALFRED_MICROSOFT_CALENDAR_CLIENT_SECRET:["calendar","microsoft","clientSecret"],ALFRED_MICROSOFT_CALENDAR_TENANT_ID:["calendar","microsoft","tenantId"],ALFRED_MICROSOFT_CALENDAR_REFRESH_TOKEN:["calendar","microsoft","refreshToken"],ALFRED_FORGE_PROVIDER:["codeAgents","forge","provider"],ALFRED_FORGE_BASE_BRANCH:["codeAgents","forge","baseBranch"],ALFRED_GITHUB_TOKEN:["codeAgents","forge","github","token"],ALFRED_GITHUB_BASE_URL:["codeAgents","forge","github","baseUrl"],ALFRED_GITLAB_TOKEN:["codeAgents","forge","gitlab","token"],ALFRED_GITLAB_BASE_URL:["codeAgents","forge","gitlab","baseUrl"],ALFRED_PROXMOX_BASE_URL:["proxmox","baseUrl"],ALFRED_PROXMOX_TOKEN_ID:["proxmox","tokenId"],ALFRED_PROXMOX_TOKEN_SECRET:["proxmox","tokenSecret"],ALFRED_UNIFI_BASE_URL:["unifi","baseUrl"],ALFRED_UNIFI_API_KEY:["unifi","apiKey"],ALFRED_UNIFI_USERNAME:["unifi","username"],ALFRED_UNIFI_PASSWORD:["unifi","password"],ALFRED_UNIFI_SITE:["unifi","site"],ALFRED_HOMEASSISTANT_URL:["homeassistant","baseUrl"],ALFRED_HOMEASSISTANT_TOKEN:["homeassistant","accessToken"],ALFRED_CONTACTS_PROVIDER:["contacts","provider"],ALFRED_CARDDAV_CONTACTS_SERVER_URL:["contacts","carddav","serverUrl"],ALFRED_CARDDAV_CONTACTS_USERNAME:["contacts","carddav","username"],ALFRED_CARDDAV_CONTACTS_PASSWORD:["contacts","carddav","password"],ALFRED_GOOGLE_CONTACTS_CLIENT_ID:["contacts","google","clientId"],ALFRED_GOOGLE_CONTACTS_CLIENT_SECRET:["contacts","google","clientSecret"],ALFRED_GOOGLE_CONTACTS_REFRESH_TOKEN:["contacts","google","refreshToken"],ALFRED_MICROSOFT_CONTACTS_CLIENT_ID:["contacts","microsoft","clientId"],ALFRED_MICROSOFT_CONTACTS_CLIENT_SECRET:["contacts","microsoft","clientSecret"],ALFRED_MICROSOFT_CONTACTS_TENANT_ID:["contacts","microsoft","tenantId"],ALFRED_MICROSOFT_CONTACTS_REFRESH_TOKEN:["contacts","microsoft","refreshToken"],ALFRED_DOCKER_SOCKET_PATH:["docker","socketPath"],ALFRED_DOCKER_HOST:["docker","host"],ALFRED_BMW_CLIENT_ID:["bmw","clientId"],ALFRED_ROUTING_API_KEY:["routing","apiKey"],ALFRED_MICROSOFT_TODO_CLIENT_ID:["todo","clientId"],ALFRED_MICROSOFT_TODO_CLIENT_SECRET:["todo","clientSecret"],ALFRED_MICROSOFT_TODO_TENANT_ID:["todo","tenantId"],ALFRED_MICROSOFT_TODO_REFRESH_TOKEN:["todo","refreshToken"],ALFRED_ENERGY_GRID_NAME:["energy","gridName"],ALFRED_ENERGY_GRID_USAGE_CT:["energy","gridUsageCt"],ALFRED_ENERGY_GRID_LOSS_CT:["energy","gridLossCt"],ALFRED_ENERGY_GRID_CAPACITY_FEE:["energy","gridCapacityFee"],ALFRED_ENERGY_GRID_METER_FEE:["energy","gridMeterFee"],ALFRED_EBAY_APP_ID:["marketplace","ebay","appId"],ALFRED_EBAY_CERT_ID:["marketplace","ebay","certId"],ALFRED_BRIEFING_LOCATION:["briefing","location"],ALFRED_BRIEFING_HOME_ADDRESS:["briefing","homeAddress"],ALFRED_BRIEFING_OFFICE_ADDRESS:["briefing","officeAddress"]};m(wm,"applyEnvOverrides");m(jo,"reloadDotenv");le=class{static{m(this,"ConfigLoader")}loadConfig(e){Xa();let t=e??process.env.ALFRED_CONFIG_PATH??"./config/default.yml",s={},r=fm.resolve(t);if(Ka.existsSync(r)){let f=Ka.readFileSync(r,"utf-8"),g=gm.load(f);g&&typeof g=="object"&&(s=g)}let n=Ya(Uo,s),o=wm(n),i=["strong","fast","embeddings","local"],a=o.llm;if(a&&"provider"in a&&i.some(g=>a[g]&&typeof a[g]=="object")){let g={};for(let[y,b]of Object.entries(a))!i.includes(y)&&y!=="default"&&(g[y]=b);let h={default:g};for(let y of i)a[y]&&(h[y]=a[y]);o.llm=h}let c=Oo.parse(o),d=c.llm;d&&"provider"in d&&(c.llm={default:d});let u=c.llm;if(u&&typeof u=="object"){let f=u.apiKey??u.default?.apiKey;if(f)for(let g of["default","strong","fast","embeddings","local"]){let h=u[g];h&&!h.apiKey&&(h.apiKey=f)}}let p=c.email;if(p&&!("accounts"in p))c.email={accounts:[{name:"default",...p}]};else if(p&&"accounts"in p&&"microsoft"in p){let f=p.microsoft;if(f){let h=p.accounts.find(y=>y.provider==="microsoft");if(h){let y=h.microsoft??{};h.microsoft={...y,...f}}delete p.microsoft}}return c}}});var Xe=T(()=>{"use strict";Po();Fo();Ja()});import Bo from"pino";function js(l,e){let t=e??process.env.LOG_LEVEL??"info";if(t==="debug"||t==="trace"||process.env.NODE_ENV!=="production"){let r=Bo.transport({target:"pino-pretty",options:{colorize:!0}});return Bo({name:l,level:t,redact:Za},r)}return Bo({name:l,level:t,redact:Za})}var Za,Qa=T(()=>{"use strict";Za={paths:["*.apiKey","*.token","*.password","*.secret","*.accessToken","*.refreshToken","*.clientSecret","*.Authorization","*.authorization"],censor:"[REDACTED]"};m(js,"createLogger")});import Cf from"pino";var ec=T(()=>{"use strict"});var Ho=T(()=>{"use strict";Qa();ec()});var Ut,un=T(()=>{"use strict";Ut=class{static{m(this,"Migrator")}db;constructor(e){this.db=e,this.ensureMigrationsTable()}ensureMigrationsTable(){this.db.exec(`
2
+ var Pa=Object.defineProperty;var m=(l,e)=>Pa(l,"name",{value:e,configurable:!0}),Ua=(l=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(l,{get:(e,t)=>(typeof require<"u"?require:e)[t]}):l)(function(l){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+l+'" is not supported')});var T=(l,e)=>()=>(l&&(e=l(l=0)),e);var ue=(l,e)=>{for(var t in e)Pa(l,t,{get:e[t],enumerable:!0})};import{z as w}from"zod";var ja,Ba,Ha,qa,za,Wa,Ga,Va,_t,Pu,Uu,Fu,Fa,ju,Bu,Hu,qu,zu,Wu,Gu,Vu,Ku,Xu,Yu,Ju,Zu,Qu,em,tm,sm,rm,nm,om,im,am,cm,lm,dm,um,mm,pm,hm,Oo,Po=T(()=>{"use strict";ja=w.object({token:w.string().optional(),enabled:w.boolean()}),Ba=w.object({token:w.string().optional(),enabled:w.boolean()}),Ha=w.object({enabled:w.boolean(),dataPath:w.string()}),qa=w.object({homeserverUrl:w.string(),accessToken:w.string().optional(),userId:w.string().optional(),enabled:w.boolean()}),za=w.object({apiUrl:w.string(),phoneNumber:w.string().optional(),enabled:w.boolean()}),Wa=w.object({path:w.string()}),Ga=w.object({level:w.enum(["trace","debug","info","warn","error","fatal"]),pretty:w.boolean(),auditLogPath:w.string().optional()}),Va=w.object({rulesPath:w.string(),defaultEffect:w.enum(["allow","deny"]),ownerUserId:w.string().optional()}),_t=w.object({provider:w.enum(["anthropic","openai","openrouter","ollama","openwebui","google","mistral"]),apiKey:w.string().optional(),baseUrl:w.string().optional(),model:w.string(),temperature:w.number().optional(),maxTokens:w.number().optional()}),Pu=w.object({default:_t,strong:_t.optional(),fast:_t.optional(),embeddings:_t.optional(),local:_t.optional()}).passthrough(),Uu=w.union([_t,Pu]),Fu=w.object({provider:w.enum(["brave","searxng","tavily","duckduckgo"]),apiKey:w.string().optional(),baseUrl:w.string().optional()}),Fa=w.object({name:w.string().optional(),provider:w.enum(["imap-smtp","microsoft"]).optional(),imap:w.object({host:w.string(),port:w.number(),secure:w.boolean()}).optional(),smtp:w.object({host:w.string(),port:w.number(),secure:w.boolean()}).optional(),auth:w.object({user:w.string(),pass:w.string()}).optional(),microsoft:w.object({clientId:w.string(),clientSecret:w.string(),tenantId:w.string(),refreshToken:w.string()}).optional()}),ju=w.union([w.object({accounts:w.array(Fa)}),Fa]),Bu=w.object({provider:w.enum(["openai","groq","google"]),apiKey:w.string(),baseUrl:w.string().optional(),ttsEnabled:w.boolean().optional(),ttsModel:w.string().optional(),ttsVoice:w.string().optional()}),Hu=w.object({serverUrl:w.string(),username:w.string(),password:w.string()}),qu=w.object({clientId:w.string(),clientSecret:w.string(),refreshToken:w.string()}),zu=w.object({clientId:w.string(),clientSecret:w.string(),tenantId:w.string(),refreshToken:w.string()}),Wu=w.object({provider:w.enum(["caldav","google","microsoft"]),caldav:Hu.optional(),google:qu.optional(),microsoft:zu.optional()}),Gu=w.object({name:w.string(),command:w.string().optional(),args:w.array(w.string()).optional(),env:w.record(w.string()).optional(),url:w.string().optional()}),Vu=w.object({servers:w.array(Gu)}),Ku=w.object({enabled:w.boolean(),allowedLanguages:w.array(w.enum(["javascript","python"])).optional(),maxTimeoutMs:w.number().optional(),allowNetwork:w.boolean().optional()}),Xu=w.object({enabled:w.boolean().optional(),minMessageLength:w.number().optional(),minConfidence:w.number().min(0).max(1).optional(),maxExtractionsPerMinute:w.number().optional()}),Yu=w.object({enabled:w.boolean(),port:w.coerce.number().int().min(1).max(65535),host:w.string(),token:w.string().optional(),corsOrigin:w.string().optional()}),Ju=w.object({name:w.string(),command:w.string(),argsTemplate:w.array(w.string()),promptVia:w.enum(["arg","stdin"]).default("arg"),env:w.record(w.string()).optional(),cwd:w.string().optional(),timeoutMs:w.number().max(9e5).optional()}),Zu=w.object({token:w.string(),baseUrl:w.string().optional()}),Qu=w.object({token:w.string(),baseUrl:w.string().optional()}),em=w.object({provider:w.enum(["github","gitlab"]),baseBranch:w.string().optional(),github:Zu.optional(),gitlab:Qu.optional()}),tm=w.object({enabled:w.boolean(),agents:w.array(Ju),forge:em.optional()}),sm=w.object({baseUrl:w.string(),tokenId:w.string(),tokenSecret:w.string(),verifyTls:w.boolean().optional(),defaultNode:w.string().optional()}),rm=w.object({baseUrl:w.string(),apiKey:w.string().optional(),username:w.string().optional(),password:w.string().optional(),site:w.string().optional(),verifyTls:w.boolean().optional()}),nm=w.object({baseUrl:w.string(),accessToken:w.string(),verifyTls:w.boolean().optional()}),om=w.object({serverUrl:w.string(),username:w.string(),password:w.string(),addressBookPath:w.string().optional()}),im=w.object({clientId:w.string(),clientSecret:w.string(),refreshToken:w.string()}),am=w.object({clientId:w.string(),clientSecret:w.string(),tenantId:w.string(),refreshToken:w.string()}),cm=w.object({provider:w.enum(["carddav","google","microsoft"]),carddav:om.optional(),google:im.optional(),microsoft:am.optional()}),lm=w.object({socketPath:w.string().optional(),host:w.string().optional(),verifyTls:w.boolean().optional()}),dm=w.object({clientId:w.string()}),um=w.object({apiKey:w.string()}),mm=w.object({gridName:w.string().optional(),gridUsageCt:w.coerce.number().optional(),gridLossCt:w.coerce.number().optional(),gridCapacityFee:w.coerce.number().optional(),gridMeterFee:w.coerce.number().optional()}),pm=w.object({clientId:w.string(),clientSecret:w.string(),tenantId:w.string(),refreshToken:w.string()}),hm=w.object({maxHistoryMessages:w.number().min(10).max(500).optional()}).optional(),Oo=w.object({name:w.string(),telegram:ja,discord:Ba.optional(),whatsapp:Ha.optional(),matrix:qa.optional(),signal:za.optional(),llm:Uu,storage:Wa,logger:Ga,security:Va,search:Fu.optional(),email:ju.optional(),speech:Bu.optional(),calendar:Wu.optional(),mcp:Vu.optional(),codeSandbox:Ku.optional(),activeLearning:Xu.optional(),api:Yu.optional(),codeAgents:tm.optional(),proxmox:sm.optional(),unifi:rm.optional(),homeassistant:nm.optional(),contacts:cm.optional(),docker:lm.optional(),bmw:dm.optional(),routing:um.optional(),todo:pm.optional(),energy:mm.optional(),conversation:hm})});var Uo,Fo=T(()=>{"use strict";Uo={name:"Alfred",telegram:{token:"",enabled:!1},discord:{token:"",enabled:!1},whatsapp:{enabled:!1,dataPath:"./data/whatsapp"},matrix:{homeserverUrl:"https://matrix.org",accessToken:"",userId:"",enabled:!1},signal:{apiUrl:"http://localhost:8080",phoneNumber:"",enabled:!1},llm:{provider:"anthropic",model:"claude-sonnet-4-20250514",temperature:.7,maxTokens:4096},storage:{path:"./data/alfred.db"},logger:{level:"info",pretty:!0},security:{rulesPath:"./config/rules",defaultEffect:"deny"},api:{enabled:!0,port:3420,host:"127.0.0.1"},conversation:{maxHistoryMessages:100}}});import Ka from"node:fs";import fm from"node:path";import{config as Xa}from"dotenv";import gm from"js-yaml";function Ya(l,e){let t={...l};for(let s of Object.keys(e)){let r=e[s],n=t[s];r!=null&&typeof r=="object"&&!Array.isArray(r)&&n!==null&&n!==void 0&&typeof n=="object"&&!Array.isArray(n)?t[s]=Ya(n,r):t[s]=r}return t}function wm(l){let e={...l};for(let[t,s]of Object.entries(ym)){let r=process.env[t];if(r===void 0)continue;let n=e;for(let o=0;o<s.length-1;o++){let i=s[o];(n[i]===void 0||n[i]===null||typeof n[i]!="object")&&(n[i]={}),n[i]={...n[i]},n=n[i]}n[s[s.length-1]]=r}return e}function jo(){Xa({override:!0})}var ym,le,Ja=T(()=>{"use strict";Po();Fo();m(Ya,"deepMerge");ym={ALFRED_TELEGRAM_TOKEN:["telegram","token"],ALFRED_DISCORD_TOKEN:["discord","token"],ALFRED_MATRIX_HOMESERVER_URL:["matrix","homeserverUrl"],ALFRED_MATRIX_ACCESS_TOKEN:["matrix","accessToken"],ALFRED_MATRIX_USER_ID:["matrix","userId"],ALFRED_SIGNAL_API_URL:["signal","apiUrl"],ALFRED_SIGNAL_PHONE_NUMBER:["signal","phoneNumber"],ALFRED_ANTHROPIC_API_KEY:["llm","apiKey"],ALFRED_OPENAI_API_KEY:["llm","apiKey"],ALFRED_GOOGLE_API_KEY:["llm","apiKey"],ALFRED_OPENROUTER_API_KEY:["llm","apiKey"],ALFRED_OPENWEBUI_API_KEY:["llm","apiKey"],ALFRED_LLM_PROVIDER:["llm","provider"],ALFRED_LLM_MODEL:["llm","model"],ALFRED_LLM_BASE_URL:["llm","baseUrl"],ALFRED_LLM_STRONG_PROVIDER:["llm","strong","provider"],ALFRED_LLM_STRONG_MODEL:["llm","strong","model"],ALFRED_LLM_STRONG_API_KEY:["llm","strong","apiKey"],ALFRED_LLM_FAST_PROVIDER:["llm","fast","provider"],ALFRED_LLM_FAST_MODEL:["llm","fast","model"],ALFRED_LLM_FAST_API_KEY:["llm","fast","apiKey"],ALFRED_LLM_EMBEDDINGS_PROVIDER:["llm","embeddings","provider"],ALFRED_LLM_EMBEDDINGS_MODEL:["llm","embeddings","model"],ALFRED_LLM_EMBEDDINGS_API_KEY:["llm","embeddings","apiKey"],ALFRED_LLM_LOCAL_PROVIDER:["llm","local","provider"],ALFRED_LLM_LOCAL_MODEL:["llm","local","model"],ALFRED_LLM_LOCAL_BASE_URL:["llm","local","baseUrl"],ALFRED_STORAGE_PATH:["storage","path"],ALFRED_LOG_LEVEL:["logger","level"],ALFRED_OWNER_USER_ID:["security","ownerUserId"],ALFRED_SEARCH_PROVIDER:["search","provider"],ALFRED_SEARCH_API_KEY:["search","apiKey"],ALFRED_SEARCH_BASE_URL:["search","baseUrl"],ALFRED_EMAIL_PROVIDER:["email","provider"],ALFRED_EMAIL_USER:["email","auth","user"],ALFRED_EMAIL_PASS:["email","auth","pass"],ALFRED_MICROSOFT_EMAIL_CLIENT_ID:["email","microsoft","clientId"],ALFRED_MICROSOFT_EMAIL_CLIENT_SECRET:["email","microsoft","clientSecret"],ALFRED_MICROSOFT_EMAIL_TENANT_ID:["email","microsoft","tenantId"],ALFRED_MICROSOFT_EMAIL_REFRESH_TOKEN:["email","microsoft","refreshToken"],ALFRED_SPEECH_PROVIDER:["speech","provider"],ALFRED_SPEECH_API_KEY:["speech","apiKey"],ALFRED_SPEECH_BASE_URL:["speech","baseUrl"],ALFRED_CALENDAR_PROVIDER:["calendar","provider"],ALFRED_CALDAV_SERVER_URL:["calendar","caldav","serverUrl"],ALFRED_CALDAV_USERNAME:["calendar","caldav","username"],ALFRED_CALDAV_PASSWORD:["calendar","caldav","password"],ALFRED_GOOGLE_CALENDAR_CLIENT_ID:["calendar","google","clientId"],ALFRED_GOOGLE_CALENDAR_CLIENT_SECRET:["calendar","google","clientSecret"],ALFRED_GOOGLE_CALENDAR_REFRESH_TOKEN:["calendar","google","refreshToken"],ALFRED_MICROSOFT_CALENDAR_CLIENT_ID:["calendar","microsoft","clientId"],ALFRED_MICROSOFT_CALENDAR_CLIENT_SECRET:["calendar","microsoft","clientSecret"],ALFRED_MICROSOFT_CALENDAR_TENANT_ID:["calendar","microsoft","tenantId"],ALFRED_MICROSOFT_CALENDAR_REFRESH_TOKEN:["calendar","microsoft","refreshToken"],ALFRED_FORGE_PROVIDER:["codeAgents","forge","provider"],ALFRED_FORGE_BASE_BRANCH:["codeAgents","forge","baseBranch"],ALFRED_GITHUB_TOKEN:["codeAgents","forge","github","token"],ALFRED_GITHUB_BASE_URL:["codeAgents","forge","github","baseUrl"],ALFRED_GITLAB_TOKEN:["codeAgents","forge","gitlab","token"],ALFRED_GITLAB_BASE_URL:["codeAgents","forge","gitlab","baseUrl"],ALFRED_PROXMOX_BASE_URL:["proxmox","baseUrl"],ALFRED_PROXMOX_TOKEN_ID:["proxmox","tokenId"],ALFRED_PROXMOX_TOKEN_SECRET:["proxmox","tokenSecret"],ALFRED_UNIFI_BASE_URL:["unifi","baseUrl"],ALFRED_UNIFI_API_KEY:["unifi","apiKey"],ALFRED_UNIFI_USERNAME:["unifi","username"],ALFRED_UNIFI_PASSWORD:["unifi","password"],ALFRED_UNIFI_SITE:["unifi","site"],ALFRED_HOMEASSISTANT_URL:["homeassistant","baseUrl"],ALFRED_HOMEASSISTANT_TOKEN:["homeassistant","accessToken"],ALFRED_CONTACTS_PROVIDER:["contacts","provider"],ALFRED_CARDDAV_CONTACTS_SERVER_URL:["contacts","carddav","serverUrl"],ALFRED_CARDDAV_CONTACTS_USERNAME:["contacts","carddav","username"],ALFRED_CARDDAV_CONTACTS_PASSWORD:["contacts","carddav","password"],ALFRED_GOOGLE_CONTACTS_CLIENT_ID:["contacts","google","clientId"],ALFRED_GOOGLE_CONTACTS_CLIENT_SECRET:["contacts","google","clientSecret"],ALFRED_GOOGLE_CONTACTS_REFRESH_TOKEN:["contacts","google","refreshToken"],ALFRED_MICROSOFT_CONTACTS_CLIENT_ID:["contacts","microsoft","clientId"],ALFRED_MICROSOFT_CONTACTS_CLIENT_SECRET:["contacts","microsoft","clientSecret"],ALFRED_MICROSOFT_CONTACTS_TENANT_ID:["contacts","microsoft","tenantId"],ALFRED_MICROSOFT_CONTACTS_REFRESH_TOKEN:["contacts","microsoft","refreshToken"],ALFRED_DOCKER_SOCKET_PATH:["docker","socketPath"],ALFRED_DOCKER_HOST:["docker","host"],ALFRED_BMW_CLIENT_ID:["bmw","clientId"],ALFRED_ROUTING_API_KEY:["routing","apiKey"],ALFRED_MICROSOFT_TODO_CLIENT_ID:["todo","clientId"],ALFRED_MICROSOFT_TODO_CLIENT_SECRET:["todo","clientSecret"],ALFRED_MICROSOFT_TODO_TENANT_ID:["todo","tenantId"],ALFRED_MICROSOFT_TODO_REFRESH_TOKEN:["todo","refreshToken"],ALFRED_ENERGY_GRID_NAME:["energy","gridName"],ALFRED_ENERGY_GRID_USAGE_CT:["energy","gridUsageCt"],ALFRED_ENERGY_GRID_LOSS_CT:["energy","gridLossCt"],ALFRED_ENERGY_GRID_CAPACITY_FEE:["energy","gridCapacityFee"],ALFRED_ENERGY_GRID_METER_FEE:["energy","gridMeterFee"],ALFRED_EBAY_APP_ID:["marketplace","ebay","appId"],ALFRED_EBAY_CERT_ID:["marketplace","ebay","certId"],ALFRED_BRIEFING_LOCATION:["briefing","location"],ALFRED_BRIEFING_HOME_ADDRESS:["briefing","homeAddress"],ALFRED_BRIEFING_OFFICE_ADDRESS:["briefing","officeAddress"]};m(wm,"applyEnvOverrides");m(jo,"reloadDotenv");le=class{static{m(this,"ConfigLoader")}loadConfig(e){Xa();let t=e??process.env.ALFRED_CONFIG_PATH??"./config/default.yml",s={},r=fm.resolve(t);if(Ka.existsSync(r)){let f=Ka.readFileSync(r,"utf-8"),g=gm.load(f);g&&typeof g=="object"&&(s=g)}let n=Ya(Uo,s),o=wm(n),i=["strong","fast","embeddings","local"],a=o.llm;if(a&&"provider"in a&&i.some(g=>a[g]&&typeof a[g]=="object")){let g={};for(let[y,b]of Object.entries(a))!i.includes(y)&&y!=="default"&&(g[y]=b);let h={default:g};for(let y of i)a[y]&&(h[y]=a[y]);o.llm=h}let c=Oo.parse(o),d=c.llm;d&&"provider"in d&&(c.llm={default:d});let u=c.llm;if(u&&typeof u=="object"){let f=u.apiKey??u.default?.apiKey;if(f)for(let g of["default","strong","fast","embeddings","local"]){let h=u[g];h&&!h.apiKey&&(h.apiKey=f)}}let p=c.email;if(p&&!("accounts"in p))c.email={accounts:[{name:"default",...p}]};else if(p&&"accounts"in p&&"microsoft"in p){let f=p.microsoft;if(f){let h=p.accounts.find(y=>y.provider==="microsoft");if(h){let y=h.microsoft??{};h.microsoft={...y,...f}}delete p.microsoft}}return c}}});var Xe=T(()=>{"use strict";Po();Fo();Ja()});import Bo from"pino";function js(l,e){let t=e??process.env.LOG_LEVEL??"info";if(t==="debug"||t==="trace"||process.env.NODE_ENV!=="production"){let r=Bo.transport({target:"pino-pretty",options:{colorize:!0}});return Bo({name:l,level:t,redact:Za},r)}return Bo({name:l,level:t,redact:Za})}var Za,Qa=T(()=>{"use strict";Za={paths:["*.apiKey","*.token","*.password","*.secret","*.accessToken","*.refreshToken","*.clientSecret","*.Authorization","*.authorization"],censor:"[REDACTED]"};m(js,"createLogger")});import Cf from"pino";var ec=T(()=>{"use strict"});var Ho=T(()=>{"use strict";Qa();ec()});var Ut,un=T(()=>{"use strict";Ut=class{static{m(this,"Migrator")}db;constructor(e){this.db=e,this.ensureMigrationsTable()}ensureMigrationsTable(){this.db.exec(`
3
3
  CREATE TABLE IF NOT EXISTS _migrations (
4
4
  version INTEGER PRIMARY KEY,
5
5
  description TEXT,
@@ -777,9 +777,9 @@ ${n}`}}clearCompleted(e,t){let s=e.list,r=this.todoRepo.clearCompleted(ae(t),s);
777
777
  `)}}async getChargingSessions(e,t,s){let r=await this.resolveVin(e),n=new Date,o=s??n.toISOString(),i=t??new Date(n.getTime()-30*24*60*6e4).toISOString(),a=await this.apiGet(`/customers/vehicles/${r}/chargingHistory?from=${encodeURIComponent(i)}&to=${encodeURIComponent(o)}`),c=a.data??a.chargingSessions??[],d=[`## BMW Lade-Sessions (${i.slice(0,10)} \u2013 ${o.slice(0,10)})`,"","| Start | Ende | Dauer | Energie | Start-SoC | End-SoC | km-Stand | Ort |","|-------|------|-------|---------|-----------|---------|----------|-----|"];for(let u of c.slice(0,20)){let p=u.startTime,f=u.endTime,g=m(P=>new Date(P*1e3).toLocaleString("de-AT",{day:"2-digit",month:"2-digit",year:"2-digit",hour:"2-digit",minute:"2-digit"}),"fmtDateTime"),h=p?g(p):"-",y=f?g(f):"-",b=u.totalChargingDurationSec,k=b!=null?Math.round(b/60):"-",S=u.energyConsumedFromPowerGridKwh??"-",M=u.displayedStartSoc??"-",L=u.displayedSoc??"-",B=u.mileage!=null?`${u.mileage}`:"-",ee=u.chargingLocation,D=ee?.formattedAddress??ee?.streetAddress??"-";d.push(`| ${h} | ${y} | ${k} min | ${S} kWh | ${M}% | ${L}% | ${B} | ${D} |`)}return c.length===0&&d.push("| - | - | Keine Sessions gefunden | - | - | - | - | - |"),{success:!0,data:a,display:d.join(`
778
778
  `)}}async getConsumption(e,t){let s=await this.resolveVin(e),r=await this.resolveContainerId(),n=new Date,i={last:7,week:7,month:30,year:365,all:730}[t??"month"]??30,a=new Date(n.getTime()-i*864e5).toISOString(),c=n.toISOString(),[d,u]=await Promise.all([this.apiGet(`/customers/vehicles/${s}/chargingHistory?from=${encodeURIComponent(a)}&to=${encodeURIComponent(c)}`),this.apiGet(`/customers/vehicles/${s}/telematicData?containerId=${r}`)]),p=d.data??d.chargingSessions??[],f=parseFloat(fe(u.telematicData??{},"vehicle.drivetrain.batteryManagement.maxEnergy"))||63;if(p.length<2)return{success:!0,data:{sessions:p.length},display:"Nicht gen\xFCgend Lade-Sessions f\xFCr Verbrauchsberechnung (min. 2 n\xF6tig)."};let g=p.filter(P=>typeof P.mileage=="number"&&typeof P.displayedStartSoc=="number"&&typeof P.displayedSoc=="number").sort((P,ie)=>P.mileage-ie.mileage);if(g.length<2)return{success:!0,data:{sessions:g.length},display:"Nicht gen\xFCgend Lade-Sessions mit vollst\xE4ndigen Daten."};let h=[];for(let P=1;P<g.length;P++){let ie=g[P-1],He=g[P],ke=ie.mileage,oe=He.mileage,J=oe-ke;if(J<=0)continue;let H=ie.displayedSoc,de=He.displayedStartSoc,Re=H-de;if(Re<=0)continue;let Ie=Re/100*f,x=Ie/J*100,z=He.startTime,re=z?new Date(z*1e3).toLocaleDateString("de-AT"):"-";h.push({fromKm:ke,toKm:oe,distance:J,socUsed:Re,kWhUsed:Ie,consumption:x,date:re})}if(h.length===0)return{success:!0,data:{},display:"Keine auswertbaren Fahrtabschnitte gefunden."};if(t==="last"){let P=h[h.length-1];return{success:!0,data:P,display:["## Letzte Fahrt (gesch\xE4tzt)","",`**Datum:** ${P.date}`,`**Strecke:** ${P.distance} km`,`**Verbrauch:** ${P.consumption.toFixed(1)} kWh/100km`,`**Energie:** ${P.kWhUsed.toFixed(1)} kWh (${P.socUsed}% SoC)`,`**km-Stand:** ${P.fromKm} \u2192 ${P.toKm}`].join(`
779
779
  `)}}let y=h.reduce((P,ie)=>P+ie.distance,0),b=h.reduce((P,ie)=>P+ie.kWhUsed,0),k=b/y*100,S=h.map(P=>P.consumption).sort((P,ie)=>P-ie),M=S[0],L=S[S.length-1],B=S[Math.floor(S.length/2)],D=[`## BMW Verbrauchsstatistik \u2014 ${{week:"Letzte Woche",month:"Letzter Monat",year:"Letztes Jahr",all:"Gesamt"}[t??"month"]??"Letzter Monat"}`,"",`**Batteriekapazit\xE4t:** ${f} kWh`,`**Ausgewertete Fahrten:** ${h.length}`,`**Gesamtstrecke:** ${y.toLocaleString("de-AT")} km`,`**Gesamtverbrauch:** ${b.toFixed(1)} kWh`,"",`**Durchschnitt:** ${k.toFixed(1)} kWh/100km`,`**Min:** ${M.toFixed(1)} kWh/100km`,`**Max:** ${L.toFixed(1)} kWh/100km`,`**Median:** ${B.toFixed(1)} kWh/100km`,"","### Einzelne Fahrten","","| Datum | Strecke | Verbrauch | Energie |","|-------|---------|-----------|---------|"];for(let P of h)D.push(`| ${P.date} | ${P.distance} km | ${P.consumption.toFixed(1)} kWh/100km | ${P.kWhUsed.toFixed(1)} kWh |`);return{success:!0,data:{avgConsumption:k,totalDistance:y,totalKwh:b,segments:h},display:D.join(`
780
- `)}}}});var up,Mn,Bl=T(()=>{"use strict";F();up="https://routes.googleapis.com/directions/v2:computeRoutes",Mn=class extends R{static{m(this,"RoutingSkill")}metadata={name:"routing",category:"information",description:'Routenberechnung mit Live-Traffic via Google Routes API. "route" berechnet Route mit Distanz, Dauer und Dauer im aktuellen Verkehr. "departure_time" empfiehlt wann man losfahren soll, um zu einer bestimmten Zeit anzukommen. Orte als Adresse, "lat,lng", oder Alias ("home"/"zuhause", "work"/"b\xFCro") angeben.',riskLevel:"read",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["route","departure_time"],description:"Routing action"},origin:{type:"string",description:'Start-Adresse, "lat,lng", oder Alias wie "home"/"zuhause"/"work"/"b\xFCro"'},destination:{type:"string",description:'Ziel-Adresse, "lat,lng", oder Alias wie "home"/"zuhause"/"work"/"b\xFCro"'},departure_time:{type:"string",description:"ISO-Zeitpunkt f\xFCr Abfahrt (optional, f\xFCr Traffic-Berechnung)"},arrival_time:{type:"string",description:"ISO-Zeitpunkt gew\xFCnschte Ankunft (f\xFCr departure_time-Action)"},travel_mode:{type:"string",enum:["DRIVE","BICYCLE","WALK","TRANSIT"],description:"Fortbewegungsart (Standard: DRIVE)"}},required:["action","origin","destination"]}};config;constructor(e){super(),this.config=e}async execute(e,t){let s=e.action;if(!s)return{success:!1,error:'Missing required field "action"'};let r=e.origin,n=e.destination;if(!r)return{success:!1,error:'Missing required field "origin"'};if(!n)return{success:!1,error:'Missing required field "destination"'};try{switch(s){case"route":return await this.computeRoute(r,n,e.departure_time,e.travel_mode);case"departure_time":return await this.computeDepartureTime(r,n,e.arrival_time,e.travel_mode);default:return{success:!1,error:`Unknown action "${s}"`}}}catch(o){return{success:!1,error:`Google Routes API error: ${o instanceof Error?o.message:String(o)}`}}}async computeRoute(e,t,s,r){let n=this.buildRequestBody(e,t,r,s),i=(await this.callRoutesApi(n)).routes?.[0];if(!i)return{success:!1,error:"Keine Route gefunden."};let a=(i.distanceMeters/1e3).toFixed(1),c=this.parseDuration(i.duration),d=this.parseDuration(i.staticDuration),u=c-d,p=["## Route","",`**${e}** \u2192 **${t}**`,"",`**Distanz:** ${a} km`,`**Fahrzeit (aktuell):** ${this.formatMinutes(c)}`,`**Fahrzeit (ohne Verkehr):** ${this.formatMinutes(d)}`];if(u>1&&p.push(`**Verkehrsverz\xF6gerung:** +${this.formatMinutes(u)}`),s){let f=new Date(new Date(s).getTime()+c*6e4);p.push(`**Gesch\xE4tzte Ankunft:** ${f.toLocaleString("de-AT")}`)}return{success:!0,data:{distanceKm:parseFloat(a),durationMinutes:c,staticDurationMinutes:d},display:p.join(`
780
+ `)}}}});var up,Mn,Bl=T(()=>{"use strict";F();up="https://routes.googleapis.com/directions/v2:computeRoutes",Mn=class extends R{static{m(this,"RoutingSkill")}metadata={name:"routing",category:"information",description:'Routenberechnung mit Live-Traffic via Google Routes API. "route" berechnet Route mit Distanz, Dauer und Dauer im aktuellen Verkehr. "departure_time" empfiehlt wann man losfahren soll, um zu einer bestimmten Zeit anzukommen. WICHTIG: Aliase wie "zuhause", "daheim", "home", "bei mir", "im B\xFCro", "work" VOR dem Tool-Call in konkrete Adressen aufl\xF6sen \u2014 daf\xFCr bekannte Adressen aus Memory/Kontext verwenden. Nie rohe Alias-Werte wie "home" oder "work" als origin/destination senden. Wenn keine Adresse im Kontext vorhanden ist, den User nach der Adresse fragen.',riskLevel:"read",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["route","departure_time"],description:"Routing action"},origin:{type:"string",description:'Start-Adresse oder "lat,lng" \u2014 IMMER eine konkrete Adresse senden, KEINE Aliase wie "home"'},destination:{type:"string",description:'Ziel-Adresse oder "lat,lng" \u2014 IMMER eine konkrete Adresse senden, KEINE Aliase wie "home"'},departure_time:{type:"string",description:"ISO-Zeitpunkt f\xFCr Abfahrt (optional, f\xFCr Traffic-Berechnung)"},arrival_time:{type:"string",description:"ISO-Zeitpunkt gew\xFCnschte Ankunft (f\xFCr departure_time-Action)"},travel_mode:{type:"string",enum:["DRIVE","BICYCLE","WALK","TRANSIT"],description:"Fortbewegungsart (Standard: DRIVE)"}},required:["action","origin","destination"]}};config;constructor(e){super(),this.config=e}async execute(e,t){let s=e.action;if(!s)return{success:!1,error:'Missing required field "action"'};let r=e.origin,n=e.destination;if(!r)return{success:!1,error:'Missing required field "origin"'};if(!n)return{success:!1,error:'Missing required field "destination"'};try{switch(s){case"route":return await this.computeRoute(r,n,e.departure_time,e.travel_mode);case"departure_time":return await this.computeDepartureTime(r,n,e.arrival_time,e.travel_mode);default:return{success:!1,error:`Unknown action "${s}"`}}}catch(o){return{success:!1,error:`Google Routes API error: ${o instanceof Error?o.message:String(o)}`}}}async computeRoute(e,t,s,r){let n=this.buildRequestBody(e,t,r,s),i=(await this.callRoutesApi(n)).routes?.[0];if(!i)return{success:!1,error:"Keine Route gefunden."};let a=(i.distanceMeters/1e3).toFixed(1),c=this.parseDuration(i.duration),d=this.parseDuration(i.staticDuration),u=c-d,p=["## Route","",`**${e}** \u2192 **${t}**`,"",`**Distanz:** ${a} km`,`**Fahrzeit (aktuell):** ${this.formatMinutes(c)}`,`**Fahrzeit (ohne Verkehr):** ${this.formatMinutes(d)}`];if(u>1&&p.push(`**Verkehrsverz\xF6gerung:** +${this.formatMinutes(u)}`),s){let f=new Date(new Date(s).getTime()+c*6e4);p.push(`**Gesch\xE4tzte Ankunft:** ${f.toLocaleString("de-AT")}`)}return{success:!0,data:{distanceKm:parseFloat(a),durationMinutes:c,staticDurationMinutes:d},display:p.join(`
781
781
  `)}}async computeDepartureTime(e,t,s,r){if(!s)return{success:!1,error:'Missing required field "arrival_time" for departure_time action'};let n=this.buildRequestBody(e,t,r),i=(await this.callRoutesApi(n)).routes?.[0];if(!i)return{success:!1,error:"Keine Route gefunden."};let a=this.parseDuration(i.duration),c=Math.max(5,Math.round(a*.15)),d=new Date(s),u=new Date(d.getTime()-(a+c)*6e4),p=["## Abfahrtszeit-Empfehlung","",`**Route:** ${e} \u2192 ${t}`,`**Gew\xFCnschte Ankunft:** ${d.toLocaleString("de-AT")}`,`**Gesch\xE4tzte Fahrzeit:** ${this.formatMinutes(a)} (inkl. Verkehr)`,`**Puffer:** ${c} min`,"",`**Empfohlene Abfahrt:** ${u.toLocaleString("de-AT")}`];return{success:!0,data:{departureTime:u.toISOString(),durationMinutes:a,bufferMinutes:c},display:p.join(`
782
- `)}}resolveAddressAlias(e){let t=e.toLowerCase().trim(),s=["home","zuhause","von zuhause","nach hause","daheim"],r=["work","arbeit","b\xFCro","office","firma"];return this.config.homeAddress&&s.some(n=>t===n||t.startsWith(n+" "))?this.config.homeAddress:this.config.workAddress&&r.some(n=>t===n||t.startsWith(n+" "))?this.config.workAddress:e}buildWaypoint(e){let t=this.resolveAddressAlias(e),s=t.match(/^(-?\d+\.?\d*)\s*,\s*(-?\d+\.?\d*)$/);return s?{location:{latLng:{latitude:parseFloat(s[1]),longitude:parseFloat(s[2])}}}:{address:t}}normalizeTimestamp(e){let t=new Date(e);if(isNaN(t.getTime()))return e;if(/[Zz]|[+-]\d{2}:\d{2}$/.test(e))return t.toISOString();let s=t.getTimezoneOffset(),r=s<=0?"+":"-",n=Math.abs(s),o=String(Math.floor(n/60)).padStart(2,"0"),i=String(n%60).padStart(2,"0"),a=m(c=>String(c).padStart(2,"0"),"pad");return`${t.getFullYear()}-${a(t.getMonth()+1)}-${a(t.getDate())}T${a(t.getHours())}:${a(t.getMinutes())}:${a(t.getSeconds())}${r}${o}:${i}`}buildRequestBody(e,t,s,r,n){let o={origin:this.buildWaypoint(e),destination:this.buildWaypoint(t),travelMode:s??"DRIVE",routingPreference:"TRAFFIC_AWARE"};if(r){let i=this.normalizeTimestamp(r);new Date(i).getTime()>Date.now()+6e4&&(o.departureTime=i)}if(n){let i=this.normalizeTimestamp(n);new Date(i).getTime()>Date.now()+6e4&&(o.arrivalTime=i)}return o}async callRoutesApi(e){let t=await fetch(up,{method:"POST",headers:{"Content-Type":"application/json","X-Goog-Api-Key":this.config.apiKey,"X-Goog-FieldMask":"routes.duration,routes.staticDuration,routes.distanceMeters,routes.legs"},body:JSON.stringify(e),signal:AbortSignal.timeout(15e3)});if(!t.ok){let s=await t.text().catch(()=>"");throw new Error(`HTTP ${t.status} \u2014 ${s.slice(0,300)}`)}return await t.json()}parseDuration(e){let t=e?.match(/(\d+)s/);return t?Math.round(parseInt(t[1],10)/60):0}formatMinutes(e){if(e<60)return`${e} min`;let t=Math.floor(e/60),s=e%60;return s>0?`${t} h ${s} min`:`${t} h`}}});var Hl,ql,mp,pp,hp,us,zl,Wl,Gl,vi,Ai,Vl,On,Kl=T(()=>{"use strict";F();Hl=1.5,ql=4.79,mp=5.75,pp=1.03,hp=new Date("2026-04-01T00:00:00+02:00"),us=1.2,zl=.1,Wl=.58,Gl=.04,vi=.32,Ai=1.62,Vl="https://api.awattar.at/v1/marketdata",On=class extends R{static{m(this,"EnergyPriceSkill")}metadata={name:"energy_price",category:"information",description:'Strompreise (aWATTar HOURLY Tarif, EPEX Spot AT). "current" zeigt den aktuellen Strompreis mit Aufschl\xFCsselung (Marktpreis, Netzentgelte, Abgaben, Brutto). "today" zeigt alle Stundenpreise f\xFCr heute. "tomorrow" zeigt Stundenpreise f\xFCr morgen (verf\xFCgbar ab ~14:00). "cheapest" findet die g\xFCnstigsten Stunden (Standard: 3 Stunden in den n\xE4chsten 24h). "average" zeigt den Durchschnittspreis f\xFCr heute oder ein bestimmtes Datum.',riskLevel:"read",version:"1.0.0",timeoutMs:15e3,inputSchema:{type:"object",properties:{action:{type:"string",enum:["current","today","tomorrow","cheapest","average","briefing"],description:"Aktion (briefing = kompakte Tages\xFCbersicht f\xFCr Morgenbriefing)"},hours:{type:"number",description:"F\xFCr cheapest: Anzahl g\xFCnstigster Stunden (Standard: 3)"},date:{type:"string",description:"ISO-Datum f\xFCr average (Standard: heute)"}},required:["action"]}};config;constructor(e){super(),this.config=e}async execute(e,t){let s=e.action;if(!s)return{success:!1,error:'Missing required field "action"'};try{switch(s){case"current":return await this.current();case"today":return await this.dayPrices("today");case"tomorrow":return await this.dayPrices("tomorrow");case"cheapest":return await this.cheapest(e.hours);case"average":return await this.average(e.date);case"briefing":return await this.briefingSummary();default:return{success:!1,error:`Unknown action "${s}"`}}}catch(r){return{success:!1,error:`aWATTar API error: ${r instanceof Error?r.message:String(r)}`}}}async current(){let e=Date.now(),s=(await this.fetchMarketData()).find(i=>i.start_timestamp<=e&&i.end_timestamp>e);if(!s)return{success:!1,error:"Kein Marktpreis f\xFCr die aktuelle Stunde verf\xFCgbar."};let r=this.calculatePrice(s.marketprice),o=[`## Aktueller Strompreis (${this.formatHourRange(s.start_timestamp,s.end_timestamp)})`,""];return o.push(this.formatBreakdown(r)),{success:!0,data:r,display:o.join(`
782
+ `)}}buildWaypoint(e){let t=e.match(/^(-?\d+\.?\d*)\s*,\s*(-?\d+\.?\d*)$/);return t?{location:{latLng:{latitude:parseFloat(t[1]),longitude:parseFloat(t[2])}}}:{address:e}}normalizeTimestamp(e){let t=new Date(e);if(isNaN(t.getTime()))return e;if(/[Zz]|[+-]\d{2}:\d{2}$/.test(e))return t.toISOString();let s=t.getTimezoneOffset(),r=s<=0?"+":"-",n=Math.abs(s),o=String(Math.floor(n/60)).padStart(2,"0"),i=String(n%60).padStart(2,"0"),a=m(c=>String(c).padStart(2,"0"),"pad");return`${t.getFullYear()}-${a(t.getMonth()+1)}-${a(t.getDate())}T${a(t.getHours())}:${a(t.getMinutes())}:${a(t.getSeconds())}${r}${o}:${i}`}buildRequestBody(e,t,s,r,n){let o={origin:this.buildWaypoint(e),destination:this.buildWaypoint(t),travelMode:s??"DRIVE",routingPreference:"TRAFFIC_AWARE"};if(r){let i=this.normalizeTimestamp(r);new Date(i).getTime()>Date.now()+6e4&&(o.departureTime=i)}if(n){let i=this.normalizeTimestamp(n);new Date(i).getTime()>Date.now()+6e4&&(o.arrivalTime=i)}return o}async callRoutesApi(e){let t=await fetch(up,{method:"POST",headers:{"Content-Type":"application/json","X-Goog-Api-Key":this.config.apiKey,"X-Goog-FieldMask":"routes.duration,routes.staticDuration,routes.distanceMeters,routes.legs"},body:JSON.stringify(e),signal:AbortSignal.timeout(15e3)});if(!t.ok){let s=await t.text().catch(()=>"");throw new Error(`HTTP ${t.status} \u2014 ${s.slice(0,300)}`)}return await t.json()}parseDuration(e){let t=e?.match(/(\d+)s/);return t?Math.round(parseInt(t[1],10)/60):0}formatMinutes(e){if(e<60)return`${e} min`;let t=Math.floor(e/60),s=e%60;return s>0?`${t} h ${s} min`:`${t} h`}}});var Hl,ql,mp,pp,hp,us,zl,Wl,Gl,vi,Ai,Vl,On,Kl=T(()=>{"use strict";F();Hl=1.5,ql=4.79,mp=5.75,pp=1.03,hp=new Date("2026-04-01T00:00:00+02:00"),us=1.2,zl=.1,Wl=.58,Gl=.04,vi=.32,Ai=1.62,Vl="https://api.awattar.at/v1/marketdata",On=class extends R{static{m(this,"EnergyPriceSkill")}metadata={name:"energy_price",category:"information",description:'Strompreise (aWATTar HOURLY Tarif, EPEX Spot AT). "current" zeigt den aktuellen Strompreis mit Aufschl\xFCsselung (Marktpreis, Netzentgelte, Abgaben, Brutto). "today" zeigt alle Stundenpreise f\xFCr heute. "tomorrow" zeigt Stundenpreise f\xFCr morgen (verf\xFCgbar ab ~14:00). "cheapest" findet die g\xFCnstigsten Stunden (Standard: 3 Stunden in den n\xE4chsten 24h). "average" zeigt den Durchschnittspreis f\xFCr heute oder ein bestimmtes Datum.',riskLevel:"read",version:"1.0.0",timeoutMs:15e3,inputSchema:{type:"object",properties:{action:{type:"string",enum:["current","today","tomorrow","cheapest","average","briefing"],description:"Aktion (briefing = kompakte Tages\xFCbersicht f\xFCr Morgenbriefing)"},hours:{type:"number",description:"F\xFCr cheapest: Anzahl g\xFCnstigster Stunden (Standard: 3)"},date:{type:"string",description:"ISO-Datum f\xFCr average (Standard: heute)"}},required:["action"]}};config;constructor(e){super(),this.config=e}async execute(e,t){let s=e.action;if(!s)return{success:!1,error:'Missing required field "action"'};try{switch(s){case"current":return await this.current();case"today":return await this.dayPrices("today");case"tomorrow":return await this.dayPrices("tomorrow");case"cheapest":return await this.cheapest(e.hours);case"average":return await this.average(e.date);case"briefing":return await this.briefingSummary();default:return{success:!1,error:`Unknown action "${s}"`}}}catch(r){return{success:!1,error:`aWATTar API error: ${r instanceof Error?r.message:String(r)}`}}}async current(){let e=Date.now(),s=(await this.fetchMarketData()).find(i=>i.start_timestamp<=e&&i.end_timestamp>e);if(!s)return{success:!1,error:"Kein Marktpreis f\xFCr die aktuelle Stunde verf\xFCgbar."};let r=this.calculatePrice(s.marketprice),o=[`## Aktueller Strompreis (${this.formatHourRange(s.start_timestamp,s.end_timestamp)})`,""];return o.push(this.formatBreakdown(r)),{success:!0,data:r,display:o.join(`
783
783
  `)}}async dayPrices(e){let t=new Date,s=new Date(t);e==="tomorrow"&&s.setDate(s.getDate()+1);let r=new Date(s);r.setHours(0,0,0,0);let n=new Date(r);n.setDate(n.getDate()+1);let o=await this.fetchMarketData(r.getTime(),n.getTime());if(o.length===0)return{success:!1,error:`Keine Preisdaten f\xFCr ${e==="today"?"heute":"morgen"} verf\xFCgbar.${e==="tomorrow"?" Preise f\xFCr morgen sind ab ca. 14:00 verf\xFCgbar.":""}`};let i=e==="today"?"Heute":"Morgen",a=r.toLocaleDateString("de-AT"),c=[`## Strompreise ${i} (${a})`,""];c.push("| Uhrzeit | Markt ct/kWh | Brutto ct/kWh |"),c.push("|---|---|---|");let d=1/0,u=-1/0,p=0;for(let g of o){let h=this.calculatePrice(g.marketprice),y=this.formatHourRange(g.start_timestamp,g.end_timestamp),b=this.spotCtKwh(g.marketprice);c.push(`| ${y} | ${b.toFixed(2)} | ${h.bruttoCt.toFixed(2)} |`),d=Math.min(d,h.bruttoCt),u=Math.max(u,h.bruttoCt),p+=h.bruttoCt}let f=p/o.length;return c.push(""),c.push(`**Min:** ${d.toFixed(2)} ct/kWh | **Max:** ${u.toFixed(2)} ct/kWh | **\xD8:** ${f.toFixed(2)} ct/kWh`),{success:!0,data:{entries:o.length,min:d,max:u,avg:f},display:c.join(`
784
784
  `)}}async cheapest(e){let t=e??3,s=Date.now(),r=s+24*60*60*1e3,n=await this.fetchMarketData(s,r);if(n.length===0)return{success:!1,error:"Keine Preisdaten f\xFCr die n\xE4chsten 24 Stunden verf\xFCgbar."};let o=n.map(c=>({entry:c,breakdown:this.calculatePrice(c.marketprice)}));o.sort((c,d)=>c.breakdown.bruttoCt-d.breakdown.bruttoCt);let i=o.slice(0,Math.min(t,o.length));i.sort((c,d)=>c.entry.start_timestamp-d.entry.start_timestamp);let a=[`## ${t} g\xFCnstigste Stunden (n\xE4chste 24h)`,""];for(let{entry:c,breakdown:d}of i){let u=this.formatHourRange(c.start_timestamp,c.end_timestamp),p=new Date(c.start_timestamp).toLocaleDateString("de-AT",{weekday:"short"});a.push(`- **${p} ${u}**: ${d.bruttoCt.toFixed(2)} ct/kWh brutto (Markt: ${this.spotCtKwh(c.marketprice).toFixed(2)} ct/kWh)`)}return{success:!0,data:i.map(c=>({time:this.formatHourRange(c.entry.start_timestamp,c.entry.end_timestamp),bruttoCt:c.breakdown.bruttoCt})),display:a.join(`
785
785
  `)}}async average(e){let t;e?(t=new Date(e),t.setHours(0,0,0,0)):(t=new Date,t.setHours(0,0,0,0));let s=new Date(t);s.setDate(s.getDate()+1);let r=await this.fetchMarketData(t.getTime(),s.getTime());if(r.length===0)return{success:!1,error:`Keine Preisdaten f\xFCr ${t.toLocaleDateString("de-AT")} verf\xFCgbar.`};let n=0,o=0;for(let u of r)n+=this.spotCtKwh(u.marketprice),o+=this.calculatePrice(u.marketprice).bruttoCt;let i=n/r.length,a=o/r.length,c=t.toLocaleDateString("de-AT"),d=[`## Durchschnittspreis ${c}`,"",`**\xD8 Marktpreis:** ${i.toFixed(2)} ct/kWh`,`**\xD8 Brutto-Gesamtpreis:** ${a.toFixed(2)} ct/kWh`,"",`Basierend auf ${r.length} Stundenwerten.`];return{success:!0,data:{date:c,avgSpotCt:i,avgBruttoCt:a,hours:r.length},display:d.join(`
@@ -940,9 +940,15 @@ Result: ${o.display??JSON.stringify(o.data)}`:`\u274C Background task failed: ${
940
940
  Error: ${o.error}`;await a.sendMessage(e.chatId,c)}}catch(t){let s=t instanceof Error?t.message:String(t);this.taskRepo.updateStatus(e.id,"failed",void 0,s),this.logger.error({taskId:e.id,err:t},"Background task failed");let r=this.adapters.get(e.platform);r&&await r.sendMessage(e.chatId,`\u274C Background task failed: ${e.description}
941
941
 
942
942
  Error: ${s}`)}}}});import Wp from"node:crypto";var Br,sa=T(()=>{"use strict";_s();Br=class{static{m(this,"ProactiveScheduler")}actionRepo;skillRegistry;skillSandbox;llm;adapters;users;logger;pipeline;formatter;conversationManager;tickTimer;tickIntervalMs=6e4;constructor(e,t,s,r,n,o,i,a,c,d){this.actionRepo=e,this.skillRegistry=t,this.skillSandbox=s,this.llm=r,this.adapters=n,this.users=o,this.logger=i,this.pipeline=a,this.formatter=c,this.conversationManager=d}start(){this.tickTimer=setInterval(()=>this.tick(),this.tickIntervalMs),this.logger.info("Proactive scheduler started")}stop(){this.tickTimer&&(clearInterval(this.tickTimer),this.tickTimer=void 0),this.logger.info("Proactive scheduler stopped")}async tick(){try{let e=this.actionRepo.getDue();for(let t of e)try{await this.executeAction(t)}catch(s){this.logger.error({err:s,actionId:t.id},"Failed to execute scheduled action")}}catch(e){this.logger.error({err:e},"Error during proactive scheduler tick")}}async executeAction(e){let t=new Date().toISOString();this.logger.info({actionId:e.id,name:e.name},"Executing scheduled action");let s,r="text";if(e.skillName&&this.skillRegistry.has(e.skillName)){let u=this.skillRegistry.get(e.skillName);try{let p;try{p=JSON.parse(e.skillInput)}catch{p={},this.logger.warn({actionId:e.id},"Invalid skillInput JSON, using empty input")}let{context:f}=Ze(this.users,{userId:e.userId,platform:e.platform,chatId:e.chatId,chatType:"dm"}),g=await this.skillSandbox.execute(u,p,f);if(g.success){let h=g.display??JSON.stringify(g.data);if(this.formatter){let y=this.formatter.format(h,e.platform);s=y.text,r=y.parseMode}else s=h}else s=`\u274C Scheduled action "${e.name}" failed: ${g.error}`}catch(p){let f=p instanceof Error?p.message:String(p);s=`\u274C Scheduled action "${e.name}" failed: ${f}`}}else if(e.promptTemplate&&this.pipeline)try{let u=`scheduled-${e.id}`,p=this.users.findById(e.userId),f=p?.platformUserId??e.userId,g={id:`scheduled-${Wp.randomUUID()}`,platform:e.platform,chatId:u,chatType:"dm",userId:f,userName:p?.username??f,text:e.promptTemplate+"\n\n[Format: Use only Markdown (**, *, ~~, `, ```). Do NOT use HTML tags like <b>, <i>, <code>. The system converts Markdown to platform-specific formatting automatically.]",timestamp:new Date,metadata:{scheduled:!0,skipHistory:!0,tier:"fast"}},h=await this.pipeline.process(g),y=this.formatter?this.formatter.format(h.text,e.platform):{text:h.text,parseMode:"text"};s=y.text,r=y.parseMode;let b=this.adapters.get(e.platform);if(b&&h.attachments)for(let k of h.attachments)try{let S=k.mimeType.startsWith("image/"),M=k.mimeType==="audio/ogg"||k.mimeType==="audio/opus";S?await b.sendPhoto(e.chatId,k.data,k.fileName):M?await b.sendVoice(e.chatId,k.data):await b.sendFile(e.chatId,k.data,k.fileName)}catch(S){this.logger.warn({err:S,fileName:k.fileName,actionId:e.id},"Failed to send scheduled action attachment")}}catch(u){let p=u instanceof Error?u.message:String(u);this.logger.error({actionId:e.id,err:u},"Pipeline execution failed for scheduled action"),s=`Scheduled action "${e.name}" failed: ${p}`}else if(e.promptTemplate)try{s=(await this.llm.complete({messages:[{role:"user",content:e.promptTemplate}],maxTokens:1024,tier:"fast"})).content}catch(u){let p=u instanceof Error?u.message:String(u);this.logger.error({actionId:e.id,err:u},"LLM call failed for scheduled action"),s=`Scheduled action "${e.name}" failed: ${p}`}else this.logger.warn({actionId:e.id,skillName:e.skillName},"Unknown skill for scheduled action"),s=`Scheduled action "${e.name}" failed: unknown skill "${e.skillName}"`;let n=s.trim(),o=(e.promptTemplate??"").toLowerCase(),i=/nichts|silent|no\s*output|don't\s*respond|do\s*not\s*respond/i.test(o),a=/offline|down|fehler|error|warn|critical|alert|fail|nicht\s+(erreichbar|verf[uü]gbar|gefunden|online)|ausgefallen|stopped|unreachable|unavailable|⚠|❌|🚨|🔴/i.test(n)&&!/keine\s+(probleme|fehler|auff[aä]lligkeiten)/i.test(n);if(!n||n.length<3||i&&!a)this.logger.info({actionId:e.id,name:e.name},"Scheduled action produced no actionable output \u2014 skipping notification");else{let u=this.adapters.get(e.platform);if(u)try{if(await u.sendMessage(e.chatId,s,{parseMode:r!=="text"?r:void 0}),e.promptTemplate&&this.conversationManager){let p=this.conversationManager.getOrCreateConversation(e.platform,e.chatId,e.userId),f=`[Automated Scheduled Alert: ${e.name}]
943
- ${s}`;this.conversationManager.addMessage(p.id,"assistant",f)}}catch(p){this.logger.error({err:p,actionId:e.id},"Failed to send scheduled action result")}}if(e.promptTemplate&&this.conversationManager)try{let u=`scheduled-${e.id}`,p=this.conversationManager.getOrCreateConversation(e.platform,u,e.userId);this.conversationManager.pruneMessages(p.id,20)}catch{}let d=this.calculateNextRun(e);d?this.actionRepo.updateLastRun(e.id,t,d):(this.actionRepo.updateLastRun(e.id,t,null),this.actionRepo.setEnabled(e.id,!1))}calculateNextRun(e){let t=new Date;switch(e.scheduleType){case"interval":{let s=parseInt(e.scheduleValue,10);return isNaN(s)||s<=0?null:new Date(t.getTime()+s*6e4).toISOString()}case"once":return null;case"cron":return this.getNextCronDate(e.scheduleValue,t)?.toISOString()??null;default:return null}}getNextCronDate(e,t){let s=e.trim().split(/\s+/);if(s.length!==5)return null;let r=new Date(t.getTime()+6e4);r.setSeconds(0,0);for(let n=0;n<1440;n++){if(this.matchesCron(s,r))return r;r.setTime(r.getTime()+6e4)}return null}matchesCron(e,t){let s=t.getMinutes(),r=t.getHours(),n=t.getDate(),o=t.getMonth()+1,i=t.getDay();return this.matchCronField(e[0],s)&&this.matchCronField(e[1],r)&&this.matchCronField(e[2],n)&&this.matchCronField(e[3],o)&&this.matchCronField(e[4],i)}matchCronField(e,t){if(e==="*")return!0;let s=/^\*\/(\d+)$/.exec(e);if(s){let n=parseInt(s[1],10);return t%n===0}let r=parseInt(e,10);return isNaN(r)?!1:t===r}}});function bd(l,e){let t=e.split("."),s=l;for(let r of t){if(s==null)return;if(typeof s=="object"){if(r==="length"&&Array.isArray(s)){s=s.length;continue}s=s[r]}else return}return s}function kd(l,e,t,s){let r=Gp(l);if(s===null)return{triggered:!1,displayValue:r};switch(e){case"lt":case"gt":case"lte":case"gte":{let n=Ts(l),o=Ts(t);return n===null||o===null?{triggered:!1,displayValue:r}:{triggered:e==="lt"?n<o:e==="gt"?n>o:e==="lte"?n<=o:n>=o,displayValue:r}}case"eq":return{triggered:String(l)===String(t),displayValue:r};case"neq":return{triggered:String(l)!==String(t),displayValue:r};case"contains":return{triggered:String(l).includes(String(t??"")),displayValue:r};case"not_contains":return{triggered:!String(l).includes(String(t??"")),displayValue:r};case"changed":return{triggered:JSON.stringify(l)!==JSON.stringify(s),displayValue:r};case"increased":{let n=Ts(l),o=Ts(s);return n===null||o===null?{triggered:!1,displayValue:r}:{triggered:n>o,displayValue:r}}case"decreased":{let n=Ts(l),o=Ts(s);return n===null||o===null?{triggered:!1,displayValue:r}:{triggered:n<o,displayValue:r}}default:return{triggered:!1,displayValue:r}}}function Ts(l){if(typeof l=="number")return l;let e=parseFloat(String(l));return isNaN(e)?null:e}function Gp(l){return l==null?"null":typeof l=="object"?JSON.stringify(l):String(l)}var $d=T(()=>{"use strict";m(bd,"extractField");m(kd,"evaluateCondition");m(Ts,"toNumber");m(Gp,"formatValue")});var Vp,Wn,Sd=T(()=>{"use strict";$d();_s();Vp={lt:"<",gt:">",lte:"<=",gte:">=",eq:"=",neq:"!=",contains:"contains",not_contains:"not contains",changed:"changed",increased:"increased",decreased:"decreased"},Wn=class{static{m(this,"WatchEngine")}watchRepo;skillRegistry;skillSandbox;adapters;users;logger;timer=null;tickIntervalMs=6e4;constructor(e,t,s,r,n,o){this.watchRepo=e,this.skillRegistry=t,this.skillSandbox=s,this.adapters=r,this.users=n,this.logger=o}start(){this.timer=setInterval(()=>this.tick(),this.tickIntervalMs),this.logger.info("Watch engine started")}stop(){this.timer&&(clearInterval(this.timer),this.timer=null),this.logger.info("Watch engine stopped")}async tick(){try{let e=this.watchRepo.getDue();for(let t of e)try{await this.checkWatch(t)}catch(s){this.logger.error({err:s,watchId:t.id},"Failed to check watch")}}catch(e){this.logger.error({err:e},"Error during watch engine tick")}}async checkWatch(e){let t=new Date().toISOString();this.logger.debug({watchId:e.id,name:e.name,skill:e.skillName},"Checking watch");let s=this.skillRegistry.get(e.skillName);if(!s){this.logger.warn({watchId:e.id,skillName:e.skillName},"Unknown skill for watch"),this.watchRepo.updateAfterCheck(e.id,{lastCheckedAt:t,lastValue:e.lastValue});return}let{context:r}=Ze(this.users,{platformUserId:e.chatId,platform:e.platform,chatId:e.chatId,chatType:"dm"}),n=await this.skillSandbox.execute(s,e.skillParams,r);if(!n.success){this.logger.warn({watchId:e.id,error:n.error},"Watch skill execution failed"),this.watchRepo.updateAfterCheck(e.id,{lastCheckedAt:t,lastValue:e.lastValue});return}let o=bd(n.data,e.condition.field),i=e.lastValue!==null?JSON.parse(e.lastValue):null,{triggered:a,displayValue:c}=kd(o,e.condition.operator,e.condition.value,i),d=JSON.stringify(o);if(a&&this.isCooldownExpired(e)){let u=e.messageTemplate??this.formatAlert(e,c),p=this.adapters.get(e.platform);if(p)try{await p.sendMessage(e.chatId,u),this.logger.info({watchId:e.id,name:e.name,value:c},"Watch alert sent")}catch(f){this.logger.error({err:f,watchId:e.id},"Failed to send watch alert")}this.watchRepo.updateAfterCheck(e.id,{lastCheckedAt:t,lastValue:d,lastTriggeredAt:t})}else this.watchRepo.updateAfterCheck(e.id,{lastCheckedAt:t,lastValue:d})}isCooldownExpired(e){if(!e.lastTriggeredAt)return!0;let t=e.cooldownMinutes*6e4;return Date.now()-new Date(e.lastTriggeredAt).getTime()>=t}formatAlert(e,t){let s=Vp[e.condition.operator]??e.condition.operator,r=e.condition.value!=null?` ${s} ${e.condition.value}`:` ${s}`;return`\u26A1 Watch Alert: ${e.name}
944
- Bedingung erf\xFCllt: ${e.condition.field}${r}
945
- Aktueller Wert: ${t}`}}});function ra(l){let e=l.trim();if(e.length<10)return{level:"low",matchedPatterns:[]};for(let s of Kp)if(s.test(e))return{level:"low",matchedPatterns:[]};let t=[];for(let s of Xp)for(let r of s.patterns)if(r.test(e)){t.push(s.name);break}return t.length>0?{level:"high",matchedPatterns:t}:{level:"low",matchedPatterns:[]}}var Kp,Xp,na=T(()=>{"use strict";Kp=[/^(what|where|when|who|why|how|which|can you|could you|do you|is there|are there|was |wer |wo |wann |warum |wie |welch|kannst du|könntest du|gibt es)/i,/^(hi|hey|hello|hallo|guten (morgen|tag|abend)|moin|servus|grüß|na\b|yo\b|sup\b|good (morning|evening|night))\b/i,/^(tell me|show me|find|search|help|explain|describe|translate|summarize|zeig|such|hilf|erklär|beschreib|übersetze|fass zusammen)/i,/^(ok|okay|yes|no|ja|nein|danke|thanks|thank you|sure|alright|klar|gut|cool|nice|great|perfect|genau|stimmt|richtig)\b/i],Xp=[{name:"fact:name",patterns:[/\b(my name is|i'm called|i am called|ich heiße|ich bin der|ich bin die|mein name ist)\b/i]},{name:"fact:location",patterns:[/\b(i live in|i'm from|i am from|ich wohne|ich lebe in|ich komme aus|ich bin aus)\b/i]},{name:"fact:work",patterns:[/\b(i work at|i work as|i work for|ich arbeite|mein job|mein beruf|ich bin .{0,20}(entwickler|ingenieur|lehrer|arzt|designer))\b/i]},{name:"fact:birthday",patterns:[/\b(my birthday|i was born|ich bin geboren|mein geburtstag|ich habe am .{1,15} geburtstag)\b/i]},{name:"fact:age",patterns:[/\b(i'm \d+ years|i am \d+ years|ich bin \d+ (jahre|jahr))\b/i]},{name:"preference:like",patterns:[/\b(i love|i really like|i enjoy|ich liebe|ich mag|mir gefällt|mir gefallen)\b/i]},{name:"preference:dislike",patterns:[/\b(i hate|i dislike|i can't stand|ich hasse|ich mag .{0,5} nicht|ich kann .{0,10} nicht leiden)\b/i]},{name:"preference:prefer",patterns:[/\b(i prefer|i'd rather|ich bevorzuge|ich nehme lieber|mir ist .{0,10} lieber)\b/i]},{name:"preference:favorite",patterns:[/\b(my fav|my favorite|my favourite|mein lieblings|meine lieblings|am liebsten)\b/i]},{name:"correction",patterns:[/\b(actually|actually,? (i|my|it)|eigentlich|das stimmt nicht|nein,? ich|that's not right|that's wrong|nicht ganz)\b/i]},{name:"relationship:family",patterns:[/\b(my wife|my husband|my partner|meine frau|mein mann|mein partner|meine partnerin|my daughter|my son|mein sohn|meine tochter|my kids|meine kinder|my mother|my father|meine mutter|mein vater)\b/i]},{name:"relationship:professional",patterns:[/\b(my boss|my manager|my colleague|mein chef|mein vorgesetzter|mein kollege|meine kollegin)\b/i]},{name:"relationship:social",patterns:[/\b(my friend|my best friend|mein freund|meine freundin|mein bester freund)\b/i]},{name:"fact:language",patterns:[/\b(i speak|ich spreche|my native|meine muttersprache)\b/i]},{name:"fact:education",patterns:[/\b(i studied|i went to|ich habe .{0,10} studiert|ich war auf der|mein studium)\b/i]},{name:"fact:hobby",patterns:[/\b(my hobby|i play .{0,10}(guitar|piano|football|tennis|chess)|mein hobby|ich spiele|in my free time|in meiner freizeit)\b/i]},{name:"decision",patterns:[/\b(i've decided|i decided|i will always|ich habe (mich )?entschieden|ich werde immer)\b/i]},{name:"commitment",patterns:[/\b(i always|i never|ich mache immer|ich mache nie|i'm trying to|ich versuche)\b/i]}];m(ra,"scanSignal")});var Yp,Jp,Hr,oa=T(()=>{"use strict";Yp=["fact","preference","correction","entity","decision","relationship","principle","commitment","moment","skill"],Jp=`You are a memory extraction system. Analyze the user message and extract personal facts about the USER (not about what they're asking).
943
+ ${s}`;this.conversationManager.addMessage(p.id,"assistant",f)}}catch(p){this.logger.error({err:p,actionId:e.id},"Failed to send scheduled action result")}}if(e.promptTemplate&&this.conversationManager)try{let u=`scheduled-${e.id}`,p=this.conversationManager.getOrCreateConversation(e.platform,u,e.userId);this.conversationManager.pruneMessages(p.id,20)}catch{}let d=this.calculateNextRun(e);d?this.actionRepo.updateLastRun(e.id,t,d):(this.actionRepo.updateLastRun(e.id,t,null),this.actionRepo.setEnabled(e.id,!1))}calculateNextRun(e){let t=new Date;switch(e.scheduleType){case"interval":{let s=parseInt(e.scheduleValue,10);return isNaN(s)||s<=0?null:new Date(t.getTime()+s*6e4).toISOString()}case"once":return null;case"cron":return this.getNextCronDate(e.scheduleValue,t)?.toISOString()??null;default:return null}}getNextCronDate(e,t){let s=e.trim().split(/\s+/);if(s.length!==5)return null;let r=new Date(t.getTime()+6e4);r.setSeconds(0,0);for(let n=0;n<1440;n++){if(this.matchesCron(s,r))return r;r.setTime(r.getTime()+6e4)}return null}matchesCron(e,t){let s=t.getMinutes(),r=t.getHours(),n=t.getDate(),o=t.getMonth()+1,i=t.getDay();return this.matchCronField(e[0],s)&&this.matchCronField(e[1],r)&&this.matchCronField(e[2],n)&&this.matchCronField(e[3],o)&&this.matchCronField(e[4],i)}matchCronField(e,t){if(e==="*")return!0;let s=/^\*\/(\d+)$/.exec(e);if(s){let n=parseInt(s[1],10);return t%n===0}let r=parseInt(e,10);return isNaN(r)?!1:t===r}}});function bd(l,e){let t=e.split("."),s=l;for(let r of t){if(s==null)return;if(typeof s=="object"){if(r==="length"&&Array.isArray(s)){s=s.length;continue}s=s[r]}else return}return s}function kd(l,e,t,s){let r=Gp(l);if(s===null)return{triggered:!1,displayValue:r};switch(e){case"lt":case"gt":case"lte":case"gte":{let n=Ts(l),o=Ts(t);return n===null||o===null?{triggered:!1,displayValue:r}:{triggered:e==="lt"?n<o:e==="gt"?n>o:e==="lte"?n<=o:n>=o,displayValue:r}}case"eq":return{triggered:String(l)===String(t),displayValue:r};case"neq":return{triggered:String(l)!==String(t),displayValue:r};case"contains":return{triggered:String(l).includes(String(t??"")),displayValue:r};case"not_contains":return{triggered:!String(l).includes(String(t??"")),displayValue:r};case"changed":return{triggered:JSON.stringify(l)!==JSON.stringify(s),displayValue:r};case"increased":{let n=Ts(l),o=Ts(s);return n===null||o===null?{triggered:!1,displayValue:r}:{triggered:n>o,displayValue:r}}case"decreased":{let n=Ts(l),o=Ts(s);return n===null||o===null?{triggered:!1,displayValue:r}:{triggered:n<o,displayValue:r}}default:return{triggered:!1,displayValue:r}}}function Ts(l){if(typeof l=="number")return l;let e=parseFloat(String(l));return isNaN(e)?null:e}function Gp(l){return l==null?"null":typeof l=="object"?JSON.stringify(l):String(l)}var $d=T(()=>{"use strict";m(bd,"extractField");m(kd,"evaluateCondition");m(Ts,"toNumber");m(Gp,"formatValue")});var Vp,Wn,Sd=T(()=>{"use strict";$d();_s();Vp={lt:"<",gt:">",lte:"<=",gte:">=",eq:"=",neq:"!=",contains:"contains",not_contains:"not contains",changed:"changed",increased:"increased",decreased:"decreased"},Wn=class{static{m(this,"WatchEngine")}watchRepo;skillRegistry;skillSandbox;adapters;users;logger;timer=null;tickIntervalMs=6e4;constructor(e,t,s,r,n,o){this.watchRepo=e,this.skillRegistry=t,this.skillSandbox=s,this.adapters=r,this.users=n,this.logger=o}start(){this.timer=setInterval(()=>this.tick(),this.tickIntervalMs),this.logger.info("Watch engine started")}stop(){this.timer&&(clearInterval(this.timer),this.timer=null),this.logger.info("Watch engine stopped")}async tick(){try{let e=this.watchRepo.getDue();for(let t of e)try{await this.checkWatch(t)}catch(s){this.logger.error({err:s,watchId:t.id},"Failed to check watch")}}catch(e){this.logger.error({err:e},"Error during watch engine tick")}}async checkWatch(e){let t=new Date().toISOString();this.logger.debug({watchId:e.id,name:e.name,skill:e.skillName},"Checking watch");let s=this.skillRegistry.get(e.skillName);if(!s){this.logger.warn({watchId:e.id,skillName:e.skillName},"Unknown skill for watch"),this.watchRepo.updateAfterCheck(e.id,{lastCheckedAt:t,lastValue:e.lastValue});return}let{context:r}=Ze(this.users,{platformUserId:e.chatId,platform:e.platform,chatId:e.chatId,chatType:"dm"}),n=await this.skillSandbox.execute(s,e.skillParams,r);if(!n.success){this.logger.warn({watchId:e.id,error:n.error},"Watch skill execution failed"),this.watchRepo.updateAfterCheck(e.id,{lastCheckedAt:t,lastValue:e.lastValue});return}let o=bd(n.data,e.condition.field),i=e.lastValue!==null?JSON.parse(e.lastValue):null,{triggered:a,displayValue:c}=kd(o,e.condition.operator,e.condition.value,i),d=JSON.stringify(o);if(a&&this.isCooldownExpired(e)){let u=e.messageTemplate??this.formatAlert(e,c,n.data);if(e.messageTemplate&&n.data&&typeof n.data=="object"){let f=this.formatResultContext(n.data,e.condition.field);f&&(u+=`
944
+
945
+ `+f)}let p=this.adapters.get(e.platform);if(p)try{await p.sendMessage(e.chatId,u),this.logger.info({watchId:e.id,name:e.name,value:c},"Watch alert sent")}catch(f){this.logger.error({err:f,watchId:e.id},"Failed to send watch alert")}this.watchRepo.updateAfterCheck(e.id,{lastCheckedAt:t,lastValue:d,lastTriggeredAt:t})}else this.watchRepo.updateAfterCheck(e.id,{lastCheckedAt:t,lastValue:d})}isCooldownExpired(e){if(!e.lastTriggeredAt)return!0;let t=e.cooldownMinutes*6e4;return Date.now()-new Date(e.lastTriggeredAt).getTime()>=t}formatAlert(e,t,s){let r=Vp[e.condition.operator]??e.condition.operator,n=e.condition.value!=null?` ${r} ${e.condition.value}`:` ${r}`,o=[`\u26A1 Watch Alert: ${e.name}`,`Bedingung erf\xFCllt: ${e.condition.field}${n}`,`Aktueller Wert: ${t}`];if(s&&typeof s=="object"){let i=s,a=this.formatResultContext(i,e.condition.field);a&&o.push("",a)}return o.join(`
946
+ `)}formatResultContext(e,t){if(Array.isArray(e.listings)&&e.listings.length>0){let n=e.listings.filter(i=>typeof i.price=="number").sort((i,a)=>i.price-a.price).slice(0,3);if(n.length===0)return null;let o=[`G\xFCnstigste ${n.length}:`];for(let i of n){let a=String(i.title??"").slice(0,60),c=typeof i.price=="number"?`${i.price}\xA0\u20AC`:"k.A.",d=i.location?` \u2014 ${i.location}`:"",u=i.url?`
947
+ ${i.url}`:"";o.push(`\u2022 ${a} \u2014 ${c}${d}${u}`)}return typeof e.count=="number"&&o.push(`
948
+ Insgesamt: ${e.count} Inserate`),o.join(`
949
+ `)}if(Array.isArray(e.cheapest)&&e.cheapest.length>0){let s=e.cheapest,r=[`G\xFCnstigste ${Math.min(s.length,3)}:`];for(let n of s.slice(0,3)){let o=String(n.title??"").slice(0,60),i=typeof n.price=="number"?`${n.price}\xA0\u20AC`:"k.A.",a=n.url?`
950
+ ${n.url}`:"";r.push(`\u2022 ${o} \u2014 ${i}${a}`)}return r.join(`
951
+ `)}return null}}});function ra(l){let e=l.trim();if(e.length<10)return{level:"low",matchedPatterns:[]};for(let s of Kp)if(s.test(e))return{level:"low",matchedPatterns:[]};let t=[];for(let s of Xp)for(let r of s.patterns)if(r.test(e)){t.push(s.name);break}return t.length>0?{level:"high",matchedPatterns:t}:{level:"low",matchedPatterns:[]}}var Kp,Xp,na=T(()=>{"use strict";Kp=[/^(what|where|when|who|why|how|which|can you|could you|do you|is there|are there|was |wer |wo |wann |warum |wie |welch|kannst du|könntest du|gibt es)/i,/^(hi|hey|hello|hallo|guten (morgen|tag|abend)|moin|servus|grüß|na\b|yo\b|sup\b|good (morning|evening|night))\b/i,/^(tell me|show me|find|search|help|explain|describe|translate|summarize|zeig|such|hilf|erklär|beschreib|übersetze|fass zusammen)/i,/^(ok|okay|yes|no|ja|nein|danke|thanks|thank you|sure|alright|klar|gut|cool|nice|great|perfect|genau|stimmt|richtig)\b/i],Xp=[{name:"fact:name",patterns:[/\b(my name is|i'm called|i am called|ich heiße|ich bin der|ich bin die|mein name ist)\b/i]},{name:"fact:location",patterns:[/\b(i live in|i'm from|i am from|ich wohne|ich lebe in|ich komme aus|ich bin aus)\b/i]},{name:"fact:work",patterns:[/\b(i work at|i work as|i work for|ich arbeite|mein job|mein beruf|ich bin .{0,20}(entwickler|ingenieur|lehrer|arzt|designer))\b/i]},{name:"fact:birthday",patterns:[/\b(my birthday|i was born|ich bin geboren|mein geburtstag|ich habe am .{1,15} geburtstag)\b/i]},{name:"fact:age",patterns:[/\b(i'm \d+ years|i am \d+ years|ich bin \d+ (jahre|jahr))\b/i]},{name:"preference:like",patterns:[/\b(i love|i really like|i enjoy|ich liebe|ich mag|mir gefällt|mir gefallen)\b/i]},{name:"preference:dislike",patterns:[/\b(i hate|i dislike|i can't stand|ich hasse|ich mag .{0,5} nicht|ich kann .{0,10} nicht leiden)\b/i]},{name:"preference:prefer",patterns:[/\b(i prefer|i'd rather|ich bevorzuge|ich nehme lieber|mir ist .{0,10} lieber)\b/i]},{name:"preference:favorite",patterns:[/\b(my fav|my favorite|my favourite|mein lieblings|meine lieblings|am liebsten)\b/i]},{name:"correction",patterns:[/\b(actually|actually,? (i|my|it)|eigentlich|das stimmt nicht|nein,? ich|that's not right|that's wrong|nicht ganz)\b/i]},{name:"relationship:family",patterns:[/\b(my wife|my husband|my partner|meine frau|mein mann|mein partner|meine partnerin|my daughter|my son|mein sohn|meine tochter|my kids|meine kinder|my mother|my father|meine mutter|mein vater)\b/i]},{name:"relationship:professional",patterns:[/\b(my boss|my manager|my colleague|mein chef|mein vorgesetzter|mein kollege|meine kollegin)\b/i]},{name:"relationship:social",patterns:[/\b(my friend|my best friend|mein freund|meine freundin|mein bester freund)\b/i]},{name:"fact:language",patterns:[/\b(i speak|ich spreche|my native|meine muttersprache)\b/i]},{name:"fact:education",patterns:[/\b(i studied|i went to|ich habe .{0,10} studiert|ich war auf der|mein studium)\b/i]},{name:"fact:hobby",patterns:[/\b(my hobby|i play .{0,10}(guitar|piano|football|tennis|chess)|mein hobby|ich spiele|in my free time|in meiner freizeit)\b/i]},{name:"decision",patterns:[/\b(i've decided|i decided|i will always|ich habe (mich )?entschieden|ich werde immer)\b/i]},{name:"commitment",patterns:[/\b(i always|i never|ich mache immer|ich mache nie|i'm trying to|ich versuche)\b/i]}];m(ra,"scanSignal")});var Yp,Jp,Hr,oa=T(()=>{"use strict";Yp=["fact","preference","correction","entity","decision","relationship","principle","commitment","moment","skill"],Jp=`You are a memory extraction system. Analyze the user message and extract personal facts about the USER (not about what they're asking).
946
952
 
947
953
  Rules:
948
954
  - Only extract information the user STATES about themselves
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@madh-io/alfred-ai",
3
- "version": "0.10.77",
3
+ "version": "0.10.80",
4
4
  "description": "Alfred — Personal AI Assistant across Telegram, Discord, WhatsApp, Matrix & Signal",
5
5
  "type": "module",
6
6
  "bin": {